OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |