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 <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 | 67 |
68 void GpuVideoDecoder::Reset(const base::Closure& closure) { | 68 void GpuVideoDecoder::Reset(const base::Closure& closure) { |
69 DVLOG(3) << "Reset()"; | 69 DVLOG(3) << "Reset()"; |
70 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 70 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
71 | 71 |
72 if (state_ == kDrainingDecoder && !factories_->IsAborted()) { | 72 if (state_ == kDrainingDecoder && !factories_->IsAborted()) { |
73 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 73 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
74 &GpuVideoDecoder::Reset, weak_this_, closure)); | 74 &GpuVideoDecoder::Reset, weak_this_, closure)); |
75 // NOTE: if we're deferring Reset() until a Flush() completes, return | 75 // NOTE: if we're deferring Reset() until a Flush() completes, return |
76 // 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(). |
77 if (pending_read_cb_.is_null()) | 77 if (pending_decode_cb_.is_null()) |
78 ready_video_frames_.clear(); | 78 ready_video_frames_.clear(); |
79 return; | 79 return; |
80 } | 80 } |
81 | 81 |
82 // Throw away any already-decoded, not-yet-delivered frames. | 82 // Throw away any already-decoded, not-yet-delivered frames. |
83 ready_video_frames_.clear(); | 83 ready_video_frames_.clear(); |
84 | 84 |
85 if (!vda_) { | 85 if (!vda_) { |
86 gvd_loop_proxy_->PostTask(FROM_HERE, closure); | 86 gvd_loop_proxy_->PostTask(FROM_HERE, closure); |
87 return; | 87 return; |
88 } | 88 } |
89 | 89 |
90 if (!pending_read_cb_.is_null()) | 90 if (!pending_decode_cb_.is_null()) |
91 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 91 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
92 | 92 |
93 DCHECK(pending_reset_cb_.is_null()); | 93 DCHECK(pending_reset_cb_.is_null()); |
94 pending_reset_cb_ = BindToCurrentLoop(closure); | 94 pending_reset_cb_ = BindToCurrentLoop(closure); |
95 | 95 |
96 vda_->Reset(); | 96 vda_->Reset(); |
97 } | 97 } |
98 | 98 |
99 void GpuVideoDecoder::Stop(const base::Closure& closure) { | 99 void GpuVideoDecoder::Stop(const base::Closure& closure) { |
100 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 100 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
101 if (vda_) | 101 if (vda_) |
102 DestroyVDA(); | 102 DestroyVDA(); |
103 if (!pending_read_cb_.is_null()) | 103 if (!pending_decode_cb_.is_null()) |
104 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 104 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
105 if (!pending_reset_cb_.is_null()) | 105 if (!pending_reset_cb_.is_null()) |
106 base::ResetAndReturn(&pending_reset_cb_).Run(); | 106 base::ResetAndReturn(&pending_reset_cb_).Run(); |
107 BindToCurrentLoop(closure).Run(); | 107 BindToCurrentLoop(closure).Run(); |
108 } | 108 } |
109 | 109 |
110 static bool IsCodedSizeSupported(const gfx::Size& coded_size) { | 110 static bool IsCodedSizeSupported(const gfx::Size& coded_size) { |
111 // Only non-Windows, Ivy Bridge+ platforms can support more than 1920x1080. | 111 // Only non-Windows, Ivy Bridge+ platforms can support more than 1920x1080. |
112 // We test against 1088 to account for 16x16 macroblocks. | 112 // We test against 1088 to account for 16x16 macroblocks. |
113 if (coded_size.width() <= 1920 && coded_size.height() <= 1088) | 113 if (coded_size.width() <= 1920 && coded_size.height() <= 1088) |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 void GpuVideoDecoder::DestroyVDA() { | 181 void GpuVideoDecoder::DestroyVDA() { |
182 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 182 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
183 | 183 |
184 if (vda_) | 184 if (vda_) |
185 vda_.release()->Destroy(); | 185 vda_.release()->Destroy(); |
186 | 186 |
187 DestroyTextures(); | 187 DestroyTextures(); |
188 } | 188 } |
189 | 189 |
190 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 190 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
191 const ReadCB& read_cb) { | 191 const DecodeCB& decode_cb) { |
192 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 192 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
193 DCHECK(pending_reset_cb_.is_null()); | 193 DCHECK(pending_reset_cb_.is_null()); |
194 DCHECK(pending_read_cb_.is_null()); | 194 DCHECK(pending_decode_cb_.is_null()); |
195 | 195 |
196 pending_read_cb_ = BindToCurrentLoop(read_cb); | 196 pending_decode_cb_ = BindToCurrentLoop(decode_cb); |
197 | 197 |
198 if (state_ == kError || !vda_) { | 198 if (state_ == kError || !vda_) { |
199 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); | 199 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); |
200 return; | 200 return; |
201 } | 201 } |
202 | 202 |
203 switch (state_) { | 203 switch (state_) { |
204 case kDecoderDrained: | 204 case kDecoderDrained: |
205 if (!ready_video_frames_.empty()) { | 205 if (!ready_video_frames_.empty()) { |
206 EnqueueFrameAndTriggerFrameDelivery(NULL); | 206 EnqueueFrameAndTriggerFrameDelivery(NULL); |
207 return; | 207 return; |
208 } | 208 } |
209 state_ = kNormal; | 209 state_ = kNormal; |
(...skipping 14 matching lines...) Expand all Loading... |
224 if (state_ == kNormal) { | 224 if (state_ == kNormal) { |
225 state_ = kDrainingDecoder; | 225 state_ = kDrainingDecoder; |
226 vda_->Flush(); | 226 vda_->Flush(); |
227 } | 227 } |
228 return; | 228 return; |
229 } | 229 } |
230 | 230 |
231 size_t size = buffer->data_size(); | 231 size_t size = buffer->data_size(); |
232 SHMBuffer* shm_buffer = GetSHM(size); | 232 SHMBuffer* shm_buffer = GetSHM(size); |
233 if (!shm_buffer) { | 233 if (!shm_buffer) { |
234 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); | 234 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); |
235 return; | 235 return; |
236 } | 236 } |
237 | 237 |
238 memcpy(shm_buffer->shm->memory(), buffer->data(), size); | 238 memcpy(shm_buffer->shm->memory(), buffer->data(), size); |
239 BitstreamBuffer bitstream_buffer( | 239 BitstreamBuffer bitstream_buffer( |
240 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size); | 240 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size); |
241 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. | 241 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. |
242 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; | 242 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; |
243 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( | 243 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( |
244 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; | 244 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; |
245 DCHECK(inserted); | 245 DCHECK(inserted); |
246 RecordBufferData(bitstream_buffer, *buffer.get()); | 246 RecordBufferData(bitstream_buffer, *buffer.get()); |
247 | 247 |
248 vda_->Decode(bitstream_buffer); | 248 vda_->Decode(bitstream_buffer); |
249 | 249 |
250 if (!ready_video_frames_.empty()) { | 250 if (!ready_video_frames_.empty()) { |
251 EnqueueFrameAndTriggerFrameDelivery(NULL); | 251 EnqueueFrameAndTriggerFrameDelivery(NULL); |
252 return; | 252 return; |
253 } | 253 } |
254 | 254 |
255 if (CanMoreDecodeWorkBeDone()) | 255 if (CanMoreDecodeWorkBeDone()) |
256 base::ResetAndReturn(&pending_read_cb_).Run(kNotEnoughData, NULL); | 256 base::ResetAndReturn(&pending_decode_cb_).Run(kNotEnoughData, NULL); |
257 } | 257 } |
258 | 258 |
259 bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() { | 259 bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() { |
260 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes; | 260 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes; |
261 } | 261 } |
262 | 262 |
263 void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer, | 263 void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer, |
264 const DecoderBuffer& buffer) { | 264 const DecoderBuffer& buffer) { |
265 input_buffer_data_.push_front(BufferData(bitstream_buffer.id(), | 265 input_buffer_data_.push_front(BufferData(bitstream_buffer.id(), |
266 buffer.timestamp(), | 266 buffer.timestamp(), |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the | 436 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the |
437 // floor and return. | 437 // floor and return. |
438 if (!pending_reset_cb_.is_null()) | 438 if (!pending_reset_cb_.is_null()) |
439 return; | 439 return; |
440 | 440 |
441 if (frame.get()) | 441 if (frame.get()) |
442 ready_video_frames_.push_back(frame); | 442 ready_video_frames_.push_back(frame); |
443 else | 443 else |
444 DCHECK(!ready_video_frames_.empty()); | 444 DCHECK(!ready_video_frames_.empty()); |
445 | 445 |
446 if (pending_read_cb_.is_null()) | 446 if (pending_decode_cb_.is_null()) |
447 return; | 447 return; |
448 | 448 |
449 base::ResetAndReturn(&pending_read_cb_).Run(kOk, ready_video_frames_.front()); | 449 base::ResetAndReturn(&pending_decode_cb_) |
| 450 .Run(kOk, ready_video_frames_.front()); |
450 ready_video_frames_.pop_front(); | 451 ready_video_frames_.pop_front(); |
451 } | 452 } |
452 | 453 |
453 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id, | 454 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id, |
454 uint32 sync_point) { | 455 uint32 sync_point) { |
455 DVLOG(3) << "ReusePictureBuffer(" << picture_buffer_id << ")"; | 456 DVLOG(3) << "ReusePictureBuffer(" << picture_buffer_id << ")"; |
456 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 457 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
457 | 458 |
458 if (!vda_) | 459 if (!vda_) |
459 return; | 460 return; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 if (it == bitstream_buffers_in_decoder_.end()) { | 512 if (it == bitstream_buffers_in_decoder_.end()) { |
512 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 513 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
513 NOTREACHED() << "Missing bitstream buffer: " << id; | 514 NOTREACHED() << "Missing bitstream buffer: " << id; |
514 return; | 515 return; |
515 } | 516 } |
516 | 517 |
517 PutSHM(it->second.shm_buffer); | 518 PutSHM(it->second.shm_buffer); |
518 bitstream_buffers_in_decoder_.erase(it); | 519 bitstream_buffers_in_decoder_.erase(it); |
519 | 520 |
520 if (pending_reset_cb_.is_null() && state_ != kDrainingDecoder && | 521 if (pending_reset_cb_.is_null() && state_ != kDrainingDecoder && |
521 CanMoreDecodeWorkBeDone() && !pending_read_cb_.is_null()) { | 522 CanMoreDecodeWorkBeDone() && !pending_decode_cb_.is_null()) { |
522 base::ResetAndReturn(&pending_read_cb_).Run(kNotEnoughData, NULL); | 523 base::ResetAndReturn(&pending_decode_cb_).Run(kNotEnoughData, NULL); |
523 } | 524 } |
524 } | 525 } |
525 | 526 |
526 GpuVideoDecoder::~GpuVideoDecoder() { | 527 GpuVideoDecoder::~GpuVideoDecoder() { |
527 DCHECK(!vda_.get()); // Stop should have been already called. | 528 DCHECK(!vda_.get()); // Stop should have been already called. |
528 DCHECK(pending_read_cb_.is_null()); | 529 DCHECK(pending_decode_cb_.is_null()); |
529 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { | 530 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { |
530 available_shm_segments_[i]->shm->Close(); | 531 available_shm_segments_[i]->shm->Close(); |
531 delete available_shm_segments_[i]; | 532 delete available_shm_segments_[i]; |
532 } | 533 } |
533 available_shm_segments_.clear(); | 534 available_shm_segments_.clear(); |
534 for (std::map<int32, BufferPair>::iterator it = | 535 for (std::map<int32, BufferPair>::iterator it = |
535 bitstream_buffers_in_decoder_.begin(); | 536 bitstream_buffers_in_decoder_.begin(); |
536 it != bitstream_buffers_in_decoder_.end(); ++it) { | 537 it != bitstream_buffers_in_decoder_.end(); ++it) { |
537 it->second.shm_buffer->shm->Close(); | 538 it->second.shm_buffer->shm->Close(); |
538 } | 539 } |
(...skipping 15 matching lines...) Expand all Loading... |
554 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 555 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
555 DCHECK(ready_video_frames_.empty()); | 556 DCHECK(ready_video_frames_.empty()); |
556 | 557 |
557 // This needs to happen after the Reset() on vda_ is done to ensure pictures | 558 // This needs to happen after the Reset() on vda_ is done to ensure pictures |
558 // delivered during the reset can find their time data. | 559 // delivered during the reset can find their time data. |
559 input_buffer_data_.clear(); | 560 input_buffer_data_.clear(); |
560 | 561 |
561 if (!pending_reset_cb_.is_null()) | 562 if (!pending_reset_cb_.is_null()) |
562 base::ResetAndReturn(&pending_reset_cb_).Run(); | 563 base::ResetAndReturn(&pending_reset_cb_).Run(); |
563 | 564 |
564 if (!pending_read_cb_.is_null()) | 565 if (!pending_decode_cb_.is_null()) |
565 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); | 566 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEmptyFrame()); |
566 } | 567 } |
567 | 568 |
568 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { | 569 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
569 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 570 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
570 if (!vda_) | 571 if (!vda_) |
571 return; | 572 return; |
572 | 573 |
573 DLOG(ERROR) << "VDA Error: " << error; | 574 DLOG(ERROR) << "VDA Error: " << error; |
574 DestroyVDA(); | 575 DestroyVDA(); |
575 | 576 |
576 state_ = kError; | 577 state_ = kError; |
577 | 578 |
578 if (!pending_read_cb_.is_null()) { | 579 if (!pending_decode_cb_.is_null()) { |
579 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); | 580 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); |
580 return; | 581 return; |
581 } | 582 } |
582 } | 583 } |
583 | 584 |
584 } // namespace media | 585 } // namespace media |
OLD | NEW |