Index: media/filters/gpu_video_decoder.cc |
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc |
index c7a086974b7c4ac4df5a315a4b72f97f3afb76f1..e7481207b95eee4e632b1fec2ffcf650f69114a0 100644 |
--- a/media/filters/gpu_video_decoder.cc |
+++ b/media/filters/gpu_video_decoder.cc |
@@ -36,6 +36,10 @@ |
#include "media/formats/mp4/box_definitions.h" |
#endif |
+#if defined(OS_ANDROID) |
+#include "base/android/build_info.h" |
+#endif |
+ |
namespace media { |
namespace { |
@@ -126,6 +130,7 @@ GpuVideoDecoder::GpuVideoDecoder(GpuVideoAcceleratorFactories* factories, |
needs_all_picture_buffers_to_decode_(false), |
supports_deferred_initialization_(false), |
requires_texture_copy_(false), |
+ cdm_id_(CdmContext::kInvalidCdmId), |
weak_factory_(this) { |
DCHECK(factories_); |
} |
@@ -212,12 +217,16 @@ void GpuVideoDecoder::Initialize(const VideoDecoderConfig& config, |
base::Bind(&ReportGpuVideoDecoderInitializeStatusToUMAAndRunCB, |
BindToCurrentLoop(init_cb), media_log_); |
+ bool requires_restart_for_external_output_surface = false; |
#if !defined(OS_ANDROID) |
if (config.is_encrypted()) { |
DVLOG(1) << "Encrypted stream not supported."; |
bound_init_cb.Run(false); |
return; |
} |
+#else |
+ requires_restart_for_external_output_surface = |
+ base::android::BuildInfo::GetInstance()->sdk_int() < 23; |
#endif |
bool previously_initialized = config_.IsValidConfig(); |
@@ -288,12 +297,11 @@ void GpuVideoDecoder::Initialize(const VideoDecoderConfig& config, |
return; |
} |
- int cdm_id = CdmContext::kInvalidCdmId; |
if (config.is_encrypted()) { |
DCHECK(cdm_context); |
- cdm_id = cdm_context->GetCdmId(); |
+ cdm_id_ = cdm_context->GetCdmId(); |
// No need to store |cdm_context| since it's not needed in reinitialization. |
- if (cdm_id == CdmContext::kInvalidCdmId) { |
+ if (cdm_id_ == CdmContext::kInvalidCdmId) { |
DVLOG(1) << "CDM ID not available."; |
bound_init_cb.Run(false); |
return; |
@@ -309,31 +317,45 @@ void GpuVideoDecoder::Initialize(const VideoDecoderConfig& config, |
// If we have a surface request callback we should call it and complete |
// initialization with the returned surface. |
request_surface_cb_.Run( |
- BindToCurrentLoop(base::Bind(&GpuVideoDecoder::CompleteInitialization, |
- weak_factory_.GetWeakPtr(), cdm_id))); |
+ requires_restart_for_external_output_surface, |
+ BindToCurrentLoop(base::Bind(&GpuVideoDecoder::OnSurfaceAvailable, |
+ weak_factory_.GetWeakPtr()))); |
return; |
} |
- // If we don't have to wait for a surface complete initialization with a null |
- // surface. |
- CompleteInitialization(cdm_id, SurfaceManager::kNoSurfaceID); |
+ // If external surfaces are not supported we can complete initialization now. |
+ CompleteInitialization(); |
} |
-void GpuVideoDecoder::CompleteInitialization(int cdm_id, int surface_id) { |
+void GpuVideoDecoder::OnSurfaceAvailable(int surface_id) { |
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
- DCHECK(!init_cb_.is_null()); |
// It's possible for the vda to become null if NotifyError is called. |
if (!vda_) { |
- base::ResetAndReturn(&init_cb_).Run(false); |
+ if (!init_cb_.is_null()) |
+ base::ResetAndReturn(&init_cb_).Run(false); |
return; |
} |
+ vda_->SetSurface(surface_id); |
+ |
+ // If initialization has already completed, there's nothing left to do. |
+ if (init_cb_.is_null()) |
+ return; |
+ |
+ // Otherwise initialization was waiting for the surface, so complete it now. |
+ CompleteInitialization(); |
+} |
+ |
+void GpuVideoDecoder::CompleteInitialization() { |
+ DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
+ DCHECK(vda_); |
+ DCHECK(!init_cb_.is_null()); |
+ |
VideoDecodeAccelerator::Config vda_config; |
vda_config.profile = config_.profile(); |
- vda_config.cdm_id = cdm_id; |
+ vda_config.cdm_id = cdm_id_; |
vda_config.is_encrypted = config_.is_encrypted(); |
- vda_config.surface_id = surface_id; |
vda_config.is_deferred_initialization_allowed = true; |
vda_config.initial_expected_coded_size = config_.coded_size(); |
@@ -785,7 +807,7 @@ GpuVideoDecoder::~GpuVideoDecoder() { |
if (!init_cb_.is_null()) |
base::ResetAndReturn(&init_cb_).Run(false); |
if (!request_surface_cb_.is_null()) |
- base::ResetAndReturn(&request_surface_cb_).Run(SurfaceCreatedCB()); |
+ base::ResetAndReturn(&request_surface_cb_).Run(false, SurfaceCreatedCB()); |
for (size_t i = 0; i < available_shm_segments_.size(); ++i) { |
delete available_shm_segments_[i]; |