Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/common/gpu/media/android_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/android_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/android/build_info.h" | 9 #include "base/android/build_info.h" |
| 10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 #include "media/base/limits.h" | 31 #include "media/base/limits.h" |
| 32 #include "media/base/media.h" | 32 #include "media/base/media.h" |
| 33 #include "media/base/timestamp_constants.h" | 33 #include "media/base/timestamp_constants.h" |
| 34 #include "media/base/video_decoder_config.h" | 34 #include "media/base/video_decoder_config.h" |
| 35 #include "media/video/picture.h" | 35 #include "media/video/picture.h" |
| 36 #include "ui/gl/android/scoped_java_surface.h" | 36 #include "ui/gl/android/scoped_java_surface.h" |
| 37 #include "ui/gl/android/surface_texture.h" | 37 #include "ui/gl/android/surface_texture.h" |
| 38 #include "ui/gl/gl_bindings.h" | 38 #include "ui/gl/gl_bindings.h" |
| 39 | 39 |
| 40 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 40 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 41 #include "media/base/media_keys.h" | |
| 42 #include "media/mojo/services/mojo_cdm_service.h" | 41 #include "media/mojo/services/mojo_cdm_service.h" |
| 43 #endif | 42 #endif |
| 44 | 43 |
| 45 #define POST_ERROR(error_code, error_message) \ | 44 #define POST_ERROR(error_code, error_message) \ |
| 46 do { \ | 45 do { \ |
| 47 DLOG(ERROR) << error_message; \ | 46 DLOG(ERROR) << error_message; \ |
| 48 PostError(FROM_HERE, media::VideoDecodeAccelerator::error_code); \ | 47 PostError(FROM_HERE, media::VideoDecodeAccelerator::error_code); \ |
| 49 } while (0) | 48 } while (0) |
| 50 | 49 |
| 51 namespace content { | 50 namespace content { |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder, | 255 const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder, |
| 257 const base::Callback<bool(void)>& make_context_current) | 256 const base::Callback<bool(void)>& make_context_current) |
| 258 : client_(NULL), | 257 : client_(NULL), |
| 259 make_context_current_(make_context_current), | 258 make_context_current_(make_context_current), |
| 260 codec_(media::kCodecH264), | 259 codec_(media::kCodecH264), |
| 261 is_encrypted_(false), | 260 is_encrypted_(false), |
| 262 needs_protected_surface_(false), | 261 needs_protected_surface_(false), |
| 263 state_(NO_ERROR), | 262 state_(NO_ERROR), |
| 264 picturebuffers_requested_(false), | 263 picturebuffers_requested_(false), |
| 265 gl_decoder_(decoder), | 264 gl_decoder_(decoder), |
| 265 media_drm_bridge_cdm_context_(nullptr), | |
| 266 cdm_registration_id_(0), | 266 cdm_registration_id_(0), |
| 267 pending_input_buf_index_(-1), | 267 pending_input_buf_index_(-1), |
| 268 error_sequence_token_(0), | 268 error_sequence_token_(0), |
| 269 defer_errors_(false), | 269 defer_errors_(false), |
| 270 weak_this_factory_(this) { | 270 weak_this_factory_(this) { |
| 271 if (UseDeferredRenderingStrategy()) { | 271 if (UseDeferredRenderingStrategy()) { |
| 272 // TODO(liberato, watk): Figure out what we want to do about zero copy for | 272 // TODO(liberato, watk): Figure out what we want to do about zero copy for |
| 273 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. | 273 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. |
| 274 DCHECK(!gl_decoder_->GetContextGroup()->mailbox_manager()->UsesSync()); | 274 DCHECK(!gl_decoder_->GetContextGroup()->mailbox_manager()->UsesSync()); |
| 275 DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy."; | 275 DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy."; |
| 276 strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this)); | 276 strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this)); |
| 277 } else { | 277 } else { |
| 278 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; | 278 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; |
| 279 strategy_.reset(new AndroidCopyingBackingStrategy(this)); | 279 strategy_.reset(new AndroidCopyingBackingStrategy(this)); |
| 280 } | 280 } |
| 281 } | 281 } |
| 282 | 282 |
| 283 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 283 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
| 284 DCHECK(thread_checker_.CalledOnValidThread()); | 284 DCHECK(thread_checker_.CalledOnValidThread()); |
| 285 g_avda_timer.Pointer()->StopTimer(this); | 285 g_avda_timer.Pointer()->StopTimer(this); |
| 286 | 286 |
| 287 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 287 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 288 if (cdm_) { | 288 if (!media_drm_bridge_cdm_context_) |
| 289 DCHECK(cdm_registration_id_); | 289 return; |
| 290 static_cast<media::MediaDrmBridge*>(cdm_.get()) | 290 |
| 291 ->UnregisterPlayer(cdm_registration_id_); | 291 DCHECK(cdm_registration_id_); |
| 292 } | 292 media_drm_bridge_cdm_context_->UnregisterPlayer(cdm_registration_id_); |
| 293 #endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 293 #endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 294 } | 294 } |
| 295 | 295 |
| 296 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, | 296 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, |
| 297 Client* client) { | 297 Client* client) { |
| 298 DCHECK(!media_codec_); | 298 DCHECK(!media_codec_); |
| 299 DCHECK(thread_checker_.CalledOnValidThread()); | 299 DCHECK(thread_checker_.CalledOnValidThread()); |
| 300 TRACE_EVENT0("media", "AVDA::Initialize"); | 300 TRACE_EVENT0("media", "AVDA::Initialize"); |
| 301 | 301 |
| 302 DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString(); | 302 DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString(); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 358 if (is_encrypted_) | 358 if (is_encrypted_) |
| 359 return true; | 359 return true; |
| 360 | 360 |
| 361 return ConfigureMediaCodec(); | 361 return ConfigureMediaCodec(); |
| 362 } | 362 } |
| 363 | 363 |
| 364 void AndroidVideoDecodeAccelerator::SetCdm(int cdm_id) { | 364 void AndroidVideoDecodeAccelerator::SetCdm(int cdm_id) { |
| 365 DVLOG(2) << __FUNCTION__ << ": " << cdm_id; | 365 DVLOG(2) << __FUNCTION__ << ": " << cdm_id; |
| 366 | 366 |
| 367 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 367 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 368 using media::MediaDrmBridge; | |
| 369 | |
| 370 DCHECK(client_) << "SetCdm() must be called after Initialize()."; | 368 DCHECK(client_) << "SetCdm() must be called after Initialize()."; |
| 371 | 369 |
| 372 if (cdm_) { | 370 if (media_drm_bridge_cdm_context_) { |
| 373 NOTREACHED() << "We do not support resetting CDM."; | 371 NOTREACHED() << "We do not support resetting CDM."; |
| 374 NotifyCdmAttached(false); | 372 NotifyCdmAttached(false); |
| 375 return; | 373 return; |
| 376 } | 374 } |
| 377 | 375 |
| 378 cdm_ = media::MojoCdmService::LegacyGetCdm(cdm_id); | 376 // Store the CDM to hold a reference to it. |
| 379 DCHECK(cdm_); | 377 cdm_for_reference_holding_only_ = media::MojoCdmService::LegacyGetCdm(cdm_id); |
| 378 DCHECK(cdm_for_reference_holding_only_); | |
| 380 | 379 |
| 381 // On Android platform the MediaKeys will be its subclass MediaDrmBridge. | 380 // On Android platform the CdmContext must be a MediaDrmBridgeCdmContext. |
|
ddorwin
2016/03/22 17:20:12
nit: This sounds like this is true for all instanc
| |
| 382 MediaDrmBridge* drm_bridge = static_cast<MediaDrmBridge*>(cdm_.get()); | 381 media_drm_bridge_cdm_context_ = static_cast<media::MediaDrmBridgeCdmContext*>( |
| 382 cdm_for_reference_holding_only_->GetCdmContext()); | |
| 383 DCHECK(media_drm_bridge_cdm_context_); | |
| 383 | 384 |
| 384 // Register CDM callbacks. The callbacks registered will be posted back to | 385 // Register CDM callbacks. The callbacks registered will be posted back to |
| 385 // this thread via BindToCurrentLoop. | 386 // this thread via BindToCurrentLoop. |
| 386 | 387 |
| 387 // Since |this| holds a reference to the |cdm_|, by the time the CDM is | 388 // Since |this| holds a reference to the |cdm_|, by the time the CDM is |
| 388 // destructed, UnregisterPlayer() must have been called and |this| has been | 389 // destructed, UnregisterPlayer() must have been called and |this| has been |
| 389 // destructed as well. So the |cdm_unset_cb| will never have a chance to be | 390 // destructed as well. So the |cdm_unset_cb| will never have a chance to be |
| 390 // called. | 391 // called. |
| 391 // TODO(xhwang): Remove |cdm_unset_cb| after it's not used on all platforms. | 392 // TODO(xhwang): Remove |cdm_unset_cb| after it's not used on all platforms. |
| 392 cdm_registration_id_ = | 393 cdm_registration_id_ = media_drm_bridge_cdm_context_->RegisterPlayer( |
| 393 drm_bridge->RegisterPlayer(media::BindToCurrentLoop(base::Bind( | 394 media::BindToCurrentLoop( |
| 394 &AndroidVideoDecodeAccelerator::OnKeyAdded, | 395 base::Bind(&AndroidVideoDecodeAccelerator::OnKeyAdded, |
| 395 weak_this_factory_.GetWeakPtr())), | 396 weak_this_factory_.GetWeakPtr())), |
| 396 base::Bind(&base::DoNothing)); | 397 base::Bind(&base::DoNothing)); |
| 397 | 398 |
| 398 drm_bridge->SetMediaCryptoReadyCB(media::BindToCurrentLoop( | 399 media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB(media::BindToCurrentLoop( |
| 399 base::Bind(&AndroidVideoDecodeAccelerator::OnMediaCryptoReady, | 400 base::Bind(&AndroidVideoDecodeAccelerator::OnMediaCryptoReady, |
| 400 weak_this_factory_.GetWeakPtr()))); | 401 weak_this_factory_.GetWeakPtr()))); |
| 401 | 402 |
| 402 // Postpone NotifyCdmAttached() call till we create the MediaCodec after | 403 // Postpone NotifyCdmAttached() call till we create the MediaCodec after |
| 403 // OnMediaCryptoReady(). | 404 // OnMediaCryptoReady(). |
| 404 | |
| 405 #else | 405 #else |
| 406 | 406 |
| 407 NOTIMPLEMENTED(); | 407 NOTIMPLEMENTED(); |
| 408 NotifyCdmAttached(false); | 408 NotifyCdmAttached(false); |
| 409 | 409 |
| 410 #endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 410 #endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 411 } | 411 } |
| 412 | 412 |
| 413 void AndroidVideoDecodeAccelerator::DoIOTask() { | 413 void AndroidVideoDecodeAccelerator::DoIOTask() { |
| 414 DCHECK(thread_checker_.CalledOnValidThread()); | 414 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1064 media::VideoDecodeAccelerator::Error error) { | 1064 media::VideoDecodeAccelerator::Error error) { |
| 1065 base::MessageLoop::current()->PostDelayedTask( | 1065 base::MessageLoop::current()->PostDelayedTask( |
| 1066 from_here, | 1066 from_here, |
| 1067 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, | 1067 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, |
| 1068 weak_this_factory_.GetWeakPtr(), error, error_sequence_token_), | 1068 weak_this_factory_.GetWeakPtr(), error, error_sequence_token_), |
| 1069 (defer_errors_ ? ErrorPostingDelay() : base::TimeDelta())); | 1069 (defer_errors_ ? ErrorPostingDelay() : base::TimeDelta())); |
| 1070 state_ = ERROR; | 1070 state_ = ERROR; |
| 1071 } | 1071 } |
| 1072 | 1072 |
| 1073 void AndroidVideoDecodeAccelerator::OnMediaCryptoReady( | 1073 void AndroidVideoDecodeAccelerator::OnMediaCryptoReady( |
| 1074 media::MediaDrmBridge::JavaObjectPtr media_crypto, | 1074 media::MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto, |
| 1075 bool needs_protected_surface) { | 1075 bool needs_protected_surface) { |
| 1076 DVLOG(1) << __FUNCTION__; | 1076 DVLOG(1) << __FUNCTION__; |
| 1077 | 1077 |
| 1078 if (!media_crypto) { | 1078 if (!media_crypto) { |
| 1079 LOG(ERROR) << "MediaCrypto is not available, can't play encrypted stream."; | 1079 LOG(ERROR) << "MediaCrypto is not available, can't play encrypted stream."; |
| 1080 cdm_for_reference_holding_only_ = nullptr; | |
| 1081 media_drm_bridge_cdm_context_ = nullptr; | |
| 1080 NotifyCdmAttached(false); | 1082 NotifyCdmAttached(false); |
| 1081 return; | 1083 return; |
| 1082 } | 1084 } |
| 1083 | 1085 |
| 1084 DCHECK(!media_crypto->is_null()); | 1086 DCHECK(!media_crypto->is_null()); |
| 1085 | 1087 |
| 1086 // We assume this is a part of the initialization process, thus MediaCodec | 1088 // We assume this is a part of the initialization process, thus MediaCodec |
| 1087 // is not created yet. | 1089 // is not created yet. |
| 1088 DCHECK(!media_codec_); | 1090 DCHECK(!media_codec_); |
| 1089 | 1091 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1200 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: | 1202 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: |
| 1201 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | | 1203 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | |
| 1202 media::VideoDecodeAccelerator::Capabilities:: | 1204 media::VideoDecodeAccelerator::Capabilities:: |
| 1203 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1205 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
| 1204 } | 1206 } |
| 1205 | 1207 |
| 1206 return capabilities; | 1208 return capabilities; |
| 1207 } | 1209 } |
| 1208 | 1210 |
| 1209 } // namespace content | 1211 } // namespace content |
| OLD | NEW |