diff options
author | fischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-04 00:31:56 +0000 |
---|---|---|
committer | fischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-04 00:31:56 +0000 |
commit | 86b3fd5d7acd2eca32b4319ce9aa7e6515ebd6f2 (patch) | |
tree | 7dfa01a16fba102935170d23ca3c91ad77131b3e /media | |
parent | 840a1d1a56005c26f82acb78c04bc27c7cc515c4 (diff) | |
download | chromium_src-86b3fd5d7acd2eca32b4319ce9aa7e6515ebd6f2.zip chromium_src-86b3fd5d7acd2eca32b4319ce9aa7e6515ebd6f2.tar.gz chromium_src-86b3fd5d7acd2eca32b4319ce9aa7e6515ebd6f2.tar.bz2 |
Clarify ownership of GpuVideoDecodeAcceleratorHost and avoid crash on context loss.
GpuVideoDecoder owns GpuVideoDecodeAcceleratorHost; it was a bug that
~CommandBufferProxyImpl() called GpuVideoDecodeAcceleratorHost::Destroy() (since
the latter deletes |this|).
This bug was uncovered due to an unrelated GPU-process crashing bug, which
triggered context loss and the subsequent stack in the linked bug. With this
change, killing the GPU process mid-playback fires a JS error on the <video> tag
(correctly), but the renderer keeps on just fine.
BUG=140138
Review URL: https://chromiumcodereview.appspot.com/10852009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149985 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/filters/gpu_video_decoder.cc | 30 | ||||
-rw-r--r-- | media/filters/gpu_video_decoder.h | 4 |
2 files changed, 21 insertions, 13 deletions
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc index fc1afeb..684a300 100644 --- a/media/filters/gpu_video_decoder.cc +++ b/media/filters/gpu_video_decoder.cc @@ -106,18 +106,7 @@ void GpuVideoDecoder::Stop(const base::Closure& closure) { closure.Run(); return; } - VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release(); - // Tricky: |this| needs to stay alive until after VDA::Destroy is actually - // called, not just posted. We can't simply PostTaskAndReply using |closure| - // as the |reply| because we might be called while the renderer thread - // (a.k.a. vda_loop_proxy_) is paused (during WebMediaPlayerImpl::Destroy()), - // which would result in an apparent hang. Instead, we take an artificial ref - // to |this| and release it as |reply| after VDA::Destroy returns. - AddRef(); - vda_loop_proxy_->PostTaskAndReply( - FROM_HERE, - base::Bind(&VideoDecodeAccelerator::Destroy, weak_vda_), - base::Bind(&GpuVideoDecoder::Release, this)); + DestroyVDA(); closure.Run(); } @@ -171,10 +160,24 @@ void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) { DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); + DCHECK(!vda_.get()); vda_.reset(vda); weak_vda_ = vda->AsWeakPtr(); } +void GpuVideoDecoder::DestroyVDA() { + DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); + VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release(); + // Tricky: |this| needs to stay alive until after VDA::Destroy is actually + // called, not just posted, so we take an artificial ref to |this| and release + // it as |reply| after VDA::Destroy() returns. + AddRef(); + vda_loop_proxy_->PostTaskAndReply( + FROM_HERE, + base::Bind(&VideoDecodeAccelerator::Destroy, weak_vda_), + base::Bind(&GpuVideoDecoder::Release, this)); +} + void GpuVideoDecoder::Read(const ReadCB& read_cb) { if (!gvd_loop_proxy_->BelongsToCurrentThread()) { gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( @@ -549,8 +552,9 @@ void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { } if (!vda_.get()) return; - vda_loop_proxy_->DeleteSoon(FROM_HERE, vda_.release()); + DLOG(ERROR) << "VDA Error: " << error; + DestroyVDA(); error_occured_ = true; diff --git a/media/filters/gpu_video_decoder.h b/media/filters/gpu_video_decoder.h index 898537b..df765e6 100644 --- a/media/filters/gpu_video_decoder.h +++ b/media/filters/gpu_video_decoder.h @@ -125,6 +125,10 @@ class MEDIA_EXPORT GpuVideoDecoder // thread). void SetVDA(VideoDecodeAccelerator* vda); + // Call VDA::Destroy() on |vda_loop_proxy_| ensuring that |this| outlives the + // Destroy() call. + void DestroyVDA(); + // A shared memory segment and its allocated size. struct SHMBuffer { SHMBuffer(base::SharedMemory* m, size_t s); |