Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1290)

Side by Side Diff: media/filters/gpu_video_decoder.cc

Issue 10852009: Clarify ownership of GpuVideoDecodeAcceleratorHost and avoid crash on context loss. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/filters/gpu_video_decoder.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "media/filters/gpu_video_decoder.h" 5 #include "media/filters/gpu_video_decoder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback_helpers.h" 8 #include "base/callback_helpers.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 void GpuVideoDecoder::Stop(const base::Closure& closure) { 92 void GpuVideoDecoder::Stop(const base::Closure& closure) {
93 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 93 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
94 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 94 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
95 &GpuVideoDecoder::Stop, this, closure)); 95 &GpuVideoDecoder::Stop, this, closure));
96 return; 96 return;
97 } 97 }
98 if (!vda_.get()) { 98 if (!vda_.get()) {
99 closure.Run(); 99 closure.Run();
100 return; 100 return;
101 } 101 }
102 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release(); 102 DestroyVDA();
103 // Tricky: |this| needs to stay alive until after VDA::Destroy is actually
104 // called, not just posted. We can't simply PostTaskAndReply using |closure|
105 // as the |reply| because we might be called while the renderer thread
106 // (a.k.a. vda_loop_proxy_) is paused (during WebMediaPlayerImpl::Destroy()),
107 // which would result in an apparent hang. Instead, we take an artificial ref
108 // to |this| and release it as |reply| after VDA::Destroy returns.
109 AddRef();
110 vda_loop_proxy_->PostTaskAndReply(
111 FROM_HERE,
112 base::Bind(&VideoDecodeAccelerator::Destroy, weak_vda_),
113 base::Bind(&GpuVideoDecoder::Release, this));
114 closure.Run(); 103 closure.Run();
115 } 104 }
116 105
117 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, 106 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
118 const PipelineStatusCB& orig_status_cb, 107 const PipelineStatusCB& orig_status_cb,
119 const StatisticsCB& statistics_cb) { 108 const StatisticsCB& statistics_cb) {
120 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 109 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
121 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 110 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
122 &GpuVideoDecoder::Initialize, 111 &GpuVideoDecoder::Initialize,
123 this, stream, orig_status_cb, statistics_cb)); 112 this, stream, orig_status_cb, statistics_cb));
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 148
160 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded."; 149 DVLOG(1) << "GpuVideoDecoder::Initialize() succeeded.";
161 vda_loop_proxy_->PostTaskAndReply( 150 vda_loop_proxy_->PostTaskAndReply(
162 FROM_HERE, 151 FROM_HERE,
163 base::Bind(&GpuVideoDecoder::SetVDA, this, vda), 152 base::Bind(&GpuVideoDecoder::SetVDA, this, vda),
164 base::Bind(status_cb, PIPELINE_OK)); 153 base::Bind(status_cb, PIPELINE_OK));
165 } 154 }
166 155
167 void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) { 156 void GpuVideoDecoder::SetVDA(VideoDecodeAccelerator* vda) {
168 DCHECK(vda_loop_proxy_->BelongsToCurrentThread()); 157 DCHECK(vda_loop_proxy_->BelongsToCurrentThread());
158 DCHECK(!vda_.get());
169 vda_.reset(vda); 159 vda_.reset(vda);
170 weak_vda_ = vda->AsWeakPtr(); 160 weak_vda_ = vda->AsWeakPtr();
171 } 161 }
172 162
163 void GpuVideoDecoder::DestroyVDA() {
164 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
165 VideoDecodeAccelerator* vda ALLOW_UNUSED = vda_.release();
166 // Tricky: |this| needs to stay alive until after VDA::Destroy is actually
167 // called, not just posted. We can't simply PostTaskAndReply using |closure|
piman 2012/08/03 21:09:02 nit: the comment about |closure| isn't meaningful
Ami GONE FROM CHROMIUM 2012/08/03 21:53:16 Done.
168 // as the |reply| because we might be called while the renderer thread
169 // (a.k.a. vda_loop_proxy_) is paused (during WebMediaPlayerImpl::Destroy()),
170 // which would result in an apparent hang. Instead, we take an artificial ref
171 // to |this| and release it as |reply| after VDA::Destroy returns.
172 AddRef();
173 vda_loop_proxy_->PostTaskAndReply(
174 FROM_HERE,
175 base::Bind(&VideoDecodeAccelerator::Destroy, weak_vda_),
176 base::Bind(&GpuVideoDecoder::Release, this));
177 }
178
173 void GpuVideoDecoder::Read(const ReadCB& read_cb) { 179 void GpuVideoDecoder::Read(const ReadCB& read_cb) {
174 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 180 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
175 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 181 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
176 &GpuVideoDecoder::Read, this, read_cb)); 182 &GpuVideoDecoder::Read, this, read_cb));
177 return; 183 return;
178 } 184 }
179 185
180 if (error_occured_) { 186 if (error_occured_) {
181 read_cb.Run(kDecodeError, NULL); 187 read_cb.Run(kDecodeError, NULL);
182 return; 188 return;
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 } 541 }
536 542
537 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { 543 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) {
538 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 544 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
539 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 545 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
540 &GpuVideoDecoder::NotifyError, this, error)); 546 &GpuVideoDecoder::NotifyError, this, error));
541 return; 547 return;
542 } 548 }
543 if (!vda_.get()) 549 if (!vda_.get())
544 return; 550 return;
545 vda_loop_proxy_->DeleteSoon(FROM_HERE, vda_.release()); 551
546 DLOG(ERROR) << "VDA Error: " << error; 552 DLOG(ERROR) << "VDA Error: " << error;
553 DestroyVDA();
547 554
548 error_occured_ = true; 555 error_occured_ = true;
549 556
550 if (!pending_read_cb_.is_null()) { 557 if (!pending_read_cb_.is_null()) {
551 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); 558 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL);
552 return; 559 return;
553 } 560 }
554 } 561 }
555 562
556 } // namespace media 563 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/gpu_video_decoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698