summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorfischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-04 00:31:56 +0000
committerfischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-04 00:31:56 +0000
commit86b3fd5d7acd2eca32b4319ce9aa7e6515ebd6f2 (patch)
tree7dfa01a16fba102935170d23ca3c91ad77131b3e /media
parent840a1d1a56005c26f82acb78c04bc27c7cc515c4 (diff)
downloadchromium_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.cc30
-rw-r--r--media/filters/gpu_video_decoder.h4
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);