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

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

Issue 11428095: Pass in media message loop to VideoRendererBase and enforce calling on the right thread. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: GVD Created 8 years 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
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/cpu.h" 9 #include "base/cpu.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "media/base/bind_to_loop.h"
12 #include "media/base/decoder_buffer.h" 13 #include "media/base/decoder_buffer.h"
13 #include "media/base/demuxer_stream.h" 14 #include "media/base/demuxer_stream.h"
14 #include "media/base/pipeline.h" 15 #include "media/base/pipeline.h"
15 #include "media/base/pipeline_status.h" 16 #include "media/base/pipeline_status.h"
16 #include "media/base/video_decoder_config.h" 17 #include "media/base/video_decoder_config.h"
17 18
18 namespace media { 19 namespace media {
19 20
20 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. 21 // Maximum number of concurrent VDA::Decode() operations GVD will maintain.
21 // Higher values allow better pipelining in the GPU, but also require more 22 // Higher values allow better pipelining in the GPU, but also require more
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 state_(kNormal), 60 state_(kNormal),
60 demuxer_read_in_progress_(false), 61 demuxer_read_in_progress_(false),
61 decoder_texture_target_(0), 62 decoder_texture_target_(0),
62 next_picture_buffer_id_(0), 63 next_picture_buffer_id_(0),
63 next_bitstream_buffer_id_(0), 64 next_bitstream_buffer_id_(0),
64 error_occured_(false) { 65 error_occured_(false) {
65 DCHECK(factories_); 66 DCHECK(factories_);
66 } 67 }
67 68
68 void GpuVideoDecoder::Reset(const base::Closure& closure) { 69 void GpuVideoDecoder::Reset(const base::Closure& closure) {
69 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 70 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
70 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
71 &GpuVideoDecoder::Reset, this, closure));
72 return;
73 }
74 71
75 if (state_ == kDrainingDecoder) { 72 if (state_ == kDrainingDecoder) {
76 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 73 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
77 &GpuVideoDecoder::Reset, this, closure)); 74 &GpuVideoDecoder::Reset, this, closure));
78 // NOTE: if we're deferring Reset() until a Flush() completes, return 75 // NOTE: if we're deferring Reset() until a Flush() completes, return
79 // queued pictures to the VDA so they can be used to finish that Flush(). 76 // queued pictures to the VDA so they can be used to finish that Flush().
80 if (pending_read_cb_.is_null()) 77 if (pending_read_cb_.is_null())
81 ready_video_frames_.clear(); 78 ready_video_frames_.clear();
82 return; 79 return;
83 } 80 }
84 81
85 // Throw away any already-decoded, not-yet-delivered frames. 82 // Throw away any already-decoded, not-yet-delivered frames.
86 ready_video_frames_.clear(); 83 ready_video_frames_.clear();
87 84
85 DCHECK(pending_reset_cb_.is_null());
86 pending_reset_cb_ = BindToCurrentLoop(closure);
87
88 if (!vda_.get()) { 88 if (!vda_.get()) {
89 closure.Run(); 89 base::ResetAndReturn(&pending_reset_cb_).Run();
90 return; 90 return;
91 } 91 }
92 92
93 DCHECK(pending_reset_cb_.is_null());
94 DCHECK(!closure.is_null());
95
96 // VideoRendererBase::Flush() can't complete while it has a pending read to 93 // VideoRendererBase::Flush() can't complete while it has a pending read to
97 // us, so we fulfill such a read here. 94 // us, so we fulfill such a read here.
98 if (!pending_read_cb_.is_null()) 95 if (!pending_read_cb_.is_null())
99 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); 96 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame());
100 97
101 pending_reset_cb_ = closure;
102 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( 98 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind(
103 &VideoDecodeAccelerator::Reset, weak_vda_)); 99 &VideoDecodeAccelerator::Reset, weak_vda_));
104 } 100 }
105 101
106 void GpuVideoDecoder::Stop(const base::Closure& closure) { 102 void GpuVideoDecoder::Stop(const base::Closure& closure) {
107 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 103 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
108 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 104 if (vda_.get())
109 &GpuVideoDecoder::Stop, this, closure)); 105 DestroyVDA();
110 return; 106 BindToCurrentLoop(closure).Run();
111 }
112 if (!vda_.get()) {
113 closure.Run();
114 return;
115 }
116 DestroyVDA();
117 closure.Run();
118 } 107 }
119 108
120 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, 109 void GpuVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream,
121 const PipelineStatusCB& orig_status_cb, 110 const PipelineStatusCB& orig_status_cb,
122 const StatisticsCB& statistics_cb) { 111 const StatisticsCB& statistics_cb) {
123 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
124 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
125 &GpuVideoDecoder::Initialize,
126 this, stream, orig_status_cb, statistics_cb));
127 return;
128 }
129
130 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); 112 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
131 PipelineStatusCB status_cb = CreateUMAReportingPipelineCB( 113 PipelineStatusCB status_cb = CreateUMAReportingPipelineCB(
132 "Media.GpuVideoDecoderInitializeStatus", orig_status_cb); 114 "Media.GpuVideoDecoderInitializeStatus",
115 BindToCurrentLoop(orig_status_cb));
116 DCHECK(!demuxer_stream_);
133 117
134 DCHECK(!demuxer_stream_);
135 if (!stream) { 118 if (!stream) {
136 status_cb.Run(PIPELINE_ERROR_DECODE); 119 status_cb.Run(PIPELINE_ERROR_DECODE);
137 return; 120 return;
138 } 121 }
139 122
140 // TODO(scherkus): this check should go in Pipeline prior to creating 123 // TODO(scherkus): this check should go in Pipeline prior to creating
141 // decoder objects. 124 // decoder objects.
142 const VideoDecoderConfig& config = stream->video_decoder_config(); 125 const VideoDecoderConfig& config = stream->video_decoder_config();
143 if (!config.IsValidConfig() || config.is_encrypted()) { 126 if (!config.IsValidConfig() || config.is_encrypted()) {
144 DLOG(ERROR) << "Unsupported video stream - " 127 DLOG(ERROR) << "Unsupported video stream - "
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 AddRef(); 192 AddRef();
210 vda_loop_proxy_->PostTaskAndReply( 193 vda_loop_proxy_->PostTaskAndReply(
211 FROM_HERE, 194 FROM_HERE,
212 base::Bind(&VideoDecodeAccelerator::Destroy, weak_vda_), 195 base::Bind(&VideoDecodeAccelerator::Destroy, weak_vda_),
213 base::Bind(&GpuVideoDecoder::Release, this)); 196 base::Bind(&GpuVideoDecoder::Release, this));
214 197
215 DestroyTextures(); 198 DestroyTextures();
216 } 199 }
217 200
218 void GpuVideoDecoder::Read(const ReadCB& read_cb) { 201 void GpuVideoDecoder::Read(const ReadCB& read_cb) {
219 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 202 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
220 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 203 DCHECK(pending_reset_cb_.is_null());
221 &GpuVideoDecoder::Read, this, read_cb)); 204 DCHECK(pending_read_cb_.is_null());
222 return; 205 pending_read_cb_ = BindToCurrentLoop(read_cb);
223 }
224 206
225 if (error_occured_) { 207 if (error_occured_) {
226 read_cb.Run(kDecodeError, NULL); 208 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL);
227 return; 209 return;
228 } 210 }
229 211
230 if (!vda_.get()) { 212 if (!vda_.get()) {
231 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); 213 base::ResetAndReturn(&pending_read_cb_).Run(
214 kOk, VideoFrame::CreateEmptyFrame());
232 return; 215 return;
233 } 216 }
234 217
235 DCHECK(pending_reset_cb_.is_null());
236 DCHECK(pending_read_cb_.is_null());
237 pending_read_cb_ = read_cb;
238
239 if (!ready_video_frames_.empty()) { 218 if (!ready_video_frames_.empty()) {
240 EnqueueFrameAndTriggerFrameDelivery(NULL); 219 EnqueueFrameAndTriggerFrameDelivery(NULL);
241 return; 220 return;
242 } 221 }
243 222
244 switch (state_) { 223 switch (state_) {
245 case kDecoderDrained: 224 case kDecoderDrained:
246 state_ = kNormal; 225 state_ = kNormal;
247 // Fall-through. 226 // Fall-through.
248 case kNormal: 227 case kNormal:
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 continue; 324 continue;
346 *timestamp = it->timestamp; 325 *timestamp = it->timestamp;
347 *visible_rect = it->visible_rect; 326 *visible_rect = it->visible_rect;
348 *natural_size = it->natural_size; 327 *natural_size = it->natural_size;
349 return; 328 return;
350 } 329 }
351 NOTREACHED() << "Missing bitstreambuffer id: " << id; 330 NOTREACHED() << "Missing bitstreambuffer id: " << id;
352 } 331 }
353 332
354 bool GpuVideoDecoder::HasAlpha() const { 333 bool GpuVideoDecoder::HasAlpha() const {
334 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread());
355 return true; 335 return true;
356 } 336 }
357 337
358 void GpuVideoDecoder::NotifyInitializeDone() { 338 void GpuVideoDecoder::NotifyInitializeDone() {
359 NOTREACHED() << "GpuVideoDecodeAcceleratorHost::Initialize is synchronous!"; 339 NOTREACHED() << "GpuVideoDecodeAcceleratorHost::Initialize is synchronous!";
360 } 340 }
361 341
362 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, 342 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count,
363 const gfx::Size& size, 343 const gfx::Size& size,
364 uint32 texture_target) { 344 uint32 texture_target) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 return; 433 return;
454 434
455 if (frame) 435 if (frame)
456 ready_video_frames_.push_back(frame); 436 ready_video_frames_.push_back(frame);
457 else 437 else
458 DCHECK(!ready_video_frames_.empty()); 438 DCHECK(!ready_video_frames_.empty());
459 439
460 if (pending_read_cb_.is_null()) 440 if (pending_read_cb_.is_null())
461 return; 441 return;
462 442
463 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 443 base::ResetAndReturn(&pending_read_cb_).Run(kOk, ready_video_frames_.front());
464 pending_read_cb_, kOk, ready_video_frames_.front()));
465 pending_read_cb_.Reset();
466 ready_video_frames_.pop_front(); 444 ready_video_frames_.pop_front();
467 } 445 }
468 446
469 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { 447 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) {
470 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { 448 if (!gvd_loop_proxy_->BelongsToCurrentThread()) {
471 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( 449 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind(
472 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id)); 450 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id));
473 return; 451 return;
474 } 452 }
475 if (!vda_.get()) 453 if (!vda_.get())
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 582
605 error_occured_ = true; 583 error_occured_ = true;
606 584
607 if (!pending_read_cb_.is_null()) { 585 if (!pending_read_cb_.is_null()) {
608 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); 586 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL);
609 return; 587 return;
610 } 588 }
611 } 589 }
612 590
613 } // namespace media 591 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_video_decoder_unittest.cc ('k') | media/filters/pipeline_integration_test_base.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698