Index: media/filters/gpu_video_decoder.cc |
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc |
index 723c6da03b6bb0becb79a26ce75f7d64c9be2aae..5366b831f1b911e54a91a59a418fa002a51891c5 100644 |
--- a/media/filters/gpu_video_decoder.cc |
+++ b/media/filters/gpu_video_decoder.cc |
@@ -330,29 +330,28 @@ void GpuVideoDecoder::Initialize(const VideoDecoderConfig& config, |
void GpuVideoDecoder::OnSurfaceAvailable(int surface_id) { |
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
- // It's possible for the vda to become null if NotifyError is called. |
- if (!vda_) { |
- if (!init_cb_.is_null()) |
- base::ResetAndReturn(&init_cb_).Run(false); |
+ if (!vda_) |
return; |
- } |
- // If initialization has already completed, there's nothing to do but try to |
- // set the surface. If we're still initializing, we must pass the surface via |
- // the config since the remote VDA has not yet been created. |
- if (init_cb_.is_null()) { |
- vda_->SetSurface(surface_id); |
+ // If the VDA has not been initialized, we were waiting for the first surface |
+ // so it can be passed to Initialize() via the config. We can't call |
+ // SetSurface() before initializing because there is no remote VDA to handle |
+ // the call yet. |
+ if (!vda_initialized_) { |
+ CompleteInitialization(surface_id); |
return; |
} |
- // Otherwise initialization was waiting for the surface, so complete it now. |
- CompleteInitialization(surface_id); |
+ // The VDA must be already initialized (or async initialization is in |
+ // progress) so we can call SetSurface(). |
+ vda_->SetSurface(surface_id); |
} |
void GpuVideoDecoder::CompleteInitialization(int surface_id) { |
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
DCHECK(vda_); |
DCHECK(!init_cb_.is_null()); |
+ DCHECK(!vda_initialized_); |
VideoDecodeAccelerator::Config vda_config; |
vda_config.profile = config_.profile(); |
@@ -369,8 +368,12 @@ void GpuVideoDecoder::CompleteInitialization(int surface_id) { |
ExtractSpsAndPps(config_.extra_data(), &vda_config.sps, &vda_config.pps); |
#endif |
+ vda_initialized_ = true; |
if (!vda_->Initialize(vda_config, this)) { |
DVLOG(1) << "VDA::Initialize failed."; |
+ // It's important to set |vda_| to null so that OnSurfaceAvailable() will |
+ // not call SetSurface() on a nonexistent remote VDA. |
+ DestroyVDA(); |
base::ResetAndReturn(&init_cb_).Run(false); |
return; |
} |
@@ -384,9 +387,9 @@ void GpuVideoDecoder::CompleteInitialization(int surface_id) { |
void GpuVideoDecoder::NotifyInitializationComplete(bool success) { |
DVLOG_IF(1, !success) << __func__ << " Deferred initialization failed."; |
- DCHECK(!init_cb_.is_null()); |
- base::ResetAndReturn(&init_cb_).Run(success); |
+ if (init_cb_) |
+ base::ResetAndReturn(&init_cb_).Run(success); |
} |
void GpuVideoDecoder::DestroyPictureBuffers(PictureBufferMap* buffers) { |
@@ -861,6 +864,9 @@ void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
if (!vda_) |
return; |
+ if (init_cb_) |
+ base::ResetAndReturn(&init_cb_).Run(false); |
+ |
// If we have any bitstream buffers, then notify one that an error has |
// occurred. This guarantees that somebody finds out about the error. If |
// we don't do this, and if the max decodes are already in flight, then there |