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