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

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

Issue 239893002: Allow multiple concurrent Decode() requests in VideoDecoder interface. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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
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 <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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 73
74 void GpuVideoDecoder::Reset(const base::Closure& closure) { 74 void GpuVideoDecoder::Reset(const base::Closure& closure) {
75 DVLOG(3) << "Reset()"; 75 DVLOG(3) << "Reset()";
76 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 76 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
77 77
78 if (state_ == kDrainingDecoder) { 78 if (state_ == kDrainingDecoder) {
79 base::MessageLoop::current()->PostTask( 79 base::MessageLoop::current()->PostTask(
80 FROM_HERE, 80 FROM_HERE,
81 base::Bind( 81 base::Bind(
82 &GpuVideoDecoder::Reset, weak_factory_.GetWeakPtr(), closure)); 82 &GpuVideoDecoder::Reset, weak_factory_.GetWeakPtr(), closure));
83 // NOTE: if we're deferring Reset() until a Flush() completes, return
84 // queued pictures to the VDA so they can be used to finish that Flush().
85 if (pending_decode_cb_.is_null())
86 ready_video_frames_.clear();
87 return; 83 return;
88 } 84 }
89 85
90 // Throw away any already-decoded, not-yet-delivered frames.
91 ready_video_frames_.clear();
92
93 if (!vda_) { 86 if (!vda_) {
94 base::MessageLoop::current()->PostTask(FROM_HERE, closure); 87 base::MessageLoop::current()->PostTask(FROM_HERE, closure);
95 return; 88 return;
96 } 89 }
97 90
98 if (!pending_decode_cb_.is_null()) 91 while (!pending_decode_callbacks_.empty()) {
99 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); 92 DeliverFrame(VideoFrame::CreateEOSFrame());
93 }
100 94
101 DCHECK(pending_reset_cb_.is_null()); 95 DCHECK(pending_reset_cb_.is_null());
102 pending_reset_cb_ = BindToCurrentLoop(closure); 96 pending_reset_cb_ = BindToCurrentLoop(closure);
103 97
104 vda_->Reset(); 98 vda_->Reset();
105 } 99 }
106 100
107 void GpuVideoDecoder::Stop() { 101 void GpuVideoDecoder::Stop() {
108 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 102 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
109 if (vda_) 103 if (vda_)
110 DestroyVDA(); 104 DestroyVDA();
111 if (!pending_decode_cb_.is_null()) 105 while (!pending_decode_callbacks_.empty()) {
112 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); 106 DeliverFrame(VideoFrame::CreateEOSFrame());
107 }
113 if (!pending_reset_cb_.is_null()) 108 if (!pending_reset_cb_.is_null())
114 base::ResetAndReturn(&pending_reset_cb_).Run(); 109 base::ResetAndReturn(&pending_reset_cb_).Run();
115 } 110 }
116 111
117 static bool IsCodedSizeSupported(const gfx::Size& coded_size) { 112 static bool IsCodedSizeSupported(const gfx::Size& coded_size) {
118 // Only non-Windows, Ivy Bridge+ platforms can support more than 1920x1080. 113 // Only non-Windows, Ivy Bridge+ platforms can support more than 1920x1080.
119 // We test against 1088 to account for 16x16 macroblocks. 114 // We test against 1088 to account for 16x16 macroblocks.
120 if (coded_size.width() <= 1920 && coded_size.height() <= 1088) 115 if (coded_size.width() <= 1920 && coded_size.height() <= 1088)
121 return true; 116 return true;
122 117
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 ++it) { 210 ++it) {
216 assigned_picture_buffers_.erase(it->first); 211 assigned_picture_buffers_.erase(it->first);
217 } 212 }
218 DestroyPictureBuffers(&assigned_picture_buffers_); 213 DestroyPictureBuffers(&assigned_picture_buffers_);
219 } 214 }
220 215
221 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, 216 void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
222 const DecodeCB& decode_cb) { 217 const DecodeCB& decode_cb) {
223 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 218 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
224 DCHECK(pending_reset_cb_.is_null()); 219 DCHECK(pending_reset_cb_.is_null());
225 DCHECK(pending_decode_cb_.is_null());
226
227 pending_decode_cb_ = BindToCurrentLoop(decode_cb);
228 220
229 if (state_ == kError || !vda_) { 221 if (state_ == kError || !vda_) {
230 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); 222 decode_cb.Run(kDecodeError, NULL);
231 return; 223 return;
232 } 224 }
233 225
234 switch (state_) { 226 switch (state_) {
235 case kDecoderDrained: 227 case kDecoderDrained:
236 if (!ready_video_frames_.empty()) {
237 EnqueueFrameAndTriggerFrameDelivery(NULL);
238 return;
239 }
240 state_ = kNormal; 228 state_ = kNormal;
241 // Fall-through. 229 // Fall-through.
242 case kNormal: 230 case kNormal:
243 break; 231 break;
244 case kDrainingDecoder: 232 case kDrainingDecoder:
245 DCHECK(buffer->end_of_stream()); 233 DCHECK(buffer->end_of_stream());
246 // Do nothing. Will be satisfied either by a PictureReady or 234 // Do nothing. Will be satisfied either by a PictureReady or
247 // NotifyFlushDone below. 235 // NotifyFlushDone below.
248 return; 236 return;
249 case kError: 237 case kError:
250 NOTREACHED(); 238 NOTREACHED();
251 return; 239 return;
252 } 240 }
253 241
254 if (buffer->end_of_stream()) { 242 if (buffer->end_of_stream()) {
255 if (state_ == kNormal) { 243 if (state_ == kNormal) {
256 state_ = kDrainingDecoder; 244 state_ = kDrainingDecoder;
245 pending_decode_callbacks_.push_back(BindToCurrentLoop(decode_cb));
246 DCHECK_LE(static_cast<int>(pending_decode_callbacks_.size()),
247 kMaxInFlightDecodes);
257 vda_->Flush(); 248 vda_->Flush();
258 // If we have ready frames, go ahead and process them to ensure that the
259 // Flush operation does not block in the VDA due to lack of picture
260 // buffers.
261 if (!ready_video_frames_.empty())
262 EnqueueFrameAndTriggerFrameDelivery(NULL);
263 } 249 }
264 return; 250 return;
265 } 251 }
266 252
267 size_t size = buffer->data_size(); 253 size_t size = buffer->data_size();
268 SHMBuffer* shm_buffer = GetSHM(size); 254 SHMBuffer* shm_buffer = GetSHM(size);
269 if (!shm_buffer) { 255 if (!shm_buffer) {
270 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); 256 decode_cb.Run(kDecodeError, NULL);
271 return; 257 return;
272 } 258 }
273 259
260 pending_decode_callbacks_.push_back(BindToCurrentLoop(decode_cb));
261 DCHECK_LE(static_cast<int>(pending_decode_callbacks_.size()),
262 kMaxInFlightDecodes);
263
274 memcpy(shm_buffer->shm->memory(), buffer->data(), size); 264 memcpy(shm_buffer->shm->memory(), buffer->data(), size);
275 BitstreamBuffer bitstream_buffer( 265 BitstreamBuffer bitstream_buffer(
276 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size); 266 next_bitstream_buffer_id_, shm_buffer->shm->handle(), size);
277 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. 267 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
278 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; 268 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
279 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair( 269 bool inserted = bitstream_buffers_in_decoder_.insert(std::make_pair(
280 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second; 270 bitstream_buffer.id(), BufferPair(shm_buffer, buffer))).second;
281 DCHECK(inserted); 271 DCHECK(inserted);
282 RecordBufferData(bitstream_buffer, *buffer.get()); 272 RecordBufferData(bitstream_buffer, *buffer.get());
283 273
284 vda_->Decode(bitstream_buffer); 274 vda_->Decode(bitstream_buffer);
285
286 if (!ready_video_frames_.empty()) {
287 EnqueueFrameAndTriggerFrameDelivery(NULL);
288 return;
289 }
290
291 if (CanMoreDecodeWorkBeDone())
292 base::ResetAndReturn(&pending_decode_cb_).Run(kNotEnoughData, NULL);
293 }
294
295 bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() {
296 return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes;
297 } 275 }
298 276
299 void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer, 277 void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer,
300 const DecoderBuffer& buffer) { 278 const DecoderBuffer& buffer) {
301 input_buffer_data_.push_front(BufferData(bitstream_buffer.id(), 279 input_buffer_data_.push_front(BufferData(bitstream_buffer.id(),
302 buffer.timestamp(), 280 buffer.timestamp(),
303 config_.visible_rect(), 281 config_.visible_rect(),
304 config_.natural_size())); 282 config_.natural_size()));
305 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but 283 // Why this value? Because why not. avformat.h:MAX_REORDER_DELAY is 16, but
306 // that's too small for some pathological B-frame test videos. The cost of 284 // that's too small for some pathological B-frame test videos. The cost of
(...skipping 23 matching lines...) Expand all
330 308
331 bool GpuVideoDecoder::NeedsBitstreamConversion() const { 309 bool GpuVideoDecoder::NeedsBitstreamConversion() const {
332 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 310 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
333 return needs_bitstream_conversion_; 311 return needs_bitstream_conversion_;
334 } 312 }
335 313
336 bool GpuVideoDecoder::CanReadWithoutStalling() const { 314 bool GpuVideoDecoder::CanReadWithoutStalling() const {
337 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 315 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
338 return 316 return
339 next_picture_buffer_id_ == 0 || // Decode() will ProvidePictureBuffers(). 317 next_picture_buffer_id_ == 0 || // Decode() will ProvidePictureBuffers().
340 available_pictures_ > 0 || !ready_video_frames_.empty(); 318 available_pictures_ > 0;
319 }
320
321 int GpuVideoDecoder::GetMaxDecodeRequests() const {
322 return kMaxInFlightDecodes;
341 } 323 }
342 324
343 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, 325 void GpuVideoDecoder::ProvidePictureBuffers(uint32 count,
344 const gfx::Size& size, 326 const gfx::Size& size,
345 uint32 texture_target) { 327 uint32 texture_target) {
346 DVLOG(3) << "ProvidePictureBuffers(" << count << ", " 328 DVLOG(3) << "ProvidePictureBuffers(" << count << ", "
347 << size.width() << "x" << size.height() << ")"; 329 << size.width() << "x" << size.height() << ")";
348 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 330 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
349 331
350 std::vector<uint32> texture_ids; 332 std::vector<uint32> texture_ids;
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 timestamp, 445 timestamp,
464 base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect))); 446 base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect)));
465 CHECK_GT(available_pictures_, 0); 447 CHECK_GT(available_pictures_, 0);
466 --available_pictures_; 448 --available_pictures_;
467 bool inserted = 449 bool inserted =
468 picture_buffers_at_display_.insert(std::make_pair( 450 picture_buffers_at_display_.insert(std::make_pair(
469 picture.picture_buffer_id(), 451 picture.picture_buffer_id(),
470 pb.texture_id())).second; 452 pb.texture_id())).second;
471 DCHECK(inserted); 453 DCHECK(inserted);
472 454
473 EnqueueFrameAndTriggerFrameDelivery(frame); 455 DeliverFrame(frame);
474 } 456 }
475 457
476 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( 458 void GpuVideoDecoder::DeliverFrame(
477 const scoped_refptr<VideoFrame>& frame) { 459 const scoped_refptr<VideoFrame>& frame) {
478 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 460 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
479 461
480 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the 462 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the
481 // floor and return. 463 // floor and return.
482 if (!pending_reset_cb_.is_null()) 464 if (!pending_reset_cb_.is_null())
483 return; 465 return;
484 466
485 if (frame.get()) 467 DCHECK(!pending_decode_callbacks_.empty());
486 ready_video_frames_.push_back(frame);
487 else
488 DCHECK(!ready_video_frames_.empty());
489 468
490 if (pending_decode_cb_.is_null()) 469 DecodeCB decode_cb = pending_decode_callbacks_.front();
491 return; 470 pending_decode_callbacks_.pop_front();
492 471
493 base::ResetAndReturn(&pending_decode_cb_) 472 decode_cb.Run(kOk, frame);
494 .Run(kOk, ready_video_frames_.front());
495 ready_video_frames_.pop_front();
496 } 473 }
497 474
498 // static 475 // static
499 void GpuVideoDecoder::ReleaseMailbox( 476 void GpuVideoDecoder::ReleaseMailbox(
500 base::WeakPtr<GpuVideoDecoder> decoder, 477 base::WeakPtr<GpuVideoDecoder> decoder,
501 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, 478 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories,
502 int64 picture_buffer_id, 479 int64 picture_buffer_id,
503 uint32 texture_id, 480 uint32 texture_id,
504 scoped_ptr<gpu::MailboxHolder> mailbox_holder) { 481 scoped_ptr<gpu::MailboxHolder> mailbox_holder) {
505 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); 482 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread());
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 std::map<int32, BufferPair>::iterator it = 543 std::map<int32, BufferPair>::iterator it =
567 bitstream_buffers_in_decoder_.find(id); 544 bitstream_buffers_in_decoder_.find(id);
568 if (it == bitstream_buffers_in_decoder_.end()) { 545 if (it == bitstream_buffers_in_decoder_.end()) {
569 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); 546 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
570 NOTREACHED() << "Missing bitstream buffer: " << id; 547 NOTREACHED() << "Missing bitstream buffer: " << id;
571 return; 548 return;
572 } 549 }
573 550
574 PutSHM(it->second.shm_buffer); 551 PutSHM(it->second.shm_buffer);
575 bitstream_buffers_in_decoder_.erase(it); 552 bitstream_buffers_in_decoder_.erase(it);
576
577 if (pending_reset_cb_.is_null() && state_ != kDrainingDecoder &&
578 CanMoreDecodeWorkBeDone() && !pending_decode_cb_.is_null()) {
579 base::ResetAndReturn(&pending_decode_cb_).Run(kNotEnoughData, NULL);
580 }
581 } 553 }
582 554
583 GpuVideoDecoder::~GpuVideoDecoder() { 555 GpuVideoDecoder::~GpuVideoDecoder() {
584 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 556 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
585 // Stop should have been already called. 557 // Stop should have been already called.
586 DCHECK(!vda_.get() && assigned_picture_buffers_.empty()); 558 DCHECK(!vda_.get() && assigned_picture_buffers_.empty());
587 DCHECK(pending_decode_cb_.is_null()); 559 DCHECK(pending_decode_callbacks_.empty());
588 for (size_t i = 0; i < available_shm_segments_.size(); ++i) { 560 for (size_t i = 0; i < available_shm_segments_.size(); ++i) {
589 available_shm_segments_[i]->shm->Close(); 561 available_shm_segments_[i]->shm->Close();
590 delete available_shm_segments_[i]; 562 delete available_shm_segments_[i];
591 } 563 }
592 available_shm_segments_.clear(); 564 available_shm_segments_.clear();
593 for (std::map<int32, BufferPair>::iterator it = 565 for (std::map<int32, BufferPair>::iterator it =
594 bitstream_buffers_in_decoder_.begin(); 566 bitstream_buffers_in_decoder_.begin();
595 it != bitstream_buffers_in_decoder_.end(); ++it) { 567 it != bitstream_buffers_in_decoder_.end(); ++it) {
596 it->second.shm_buffer->shm->Close(); 568 it->second.shm_buffer->shm->Close();
597 } 569 }
598 bitstream_buffers_in_decoder_.clear(); 570 bitstream_buffers_in_decoder_.clear();
599 } 571 }
600 572
601 void GpuVideoDecoder::NotifyFlushDone() { 573 void GpuVideoDecoder::NotifyFlushDone() {
602 DVLOG(3) << "NotifyFlushDone()"; 574 DVLOG(3) << "NotifyFlushDone()";
603 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 575 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
604 DCHECK_EQ(state_, kDrainingDecoder); 576 DCHECK_EQ(state_, kDrainingDecoder);
577 DCHECK_EQ(pending_decode_callbacks_.size(), 1U);
605 state_ = kDecoderDrained; 578 state_ = kDecoderDrained;
606 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); 579 DeliverFrame(VideoFrame::CreateEOSFrame());
607 } 580 }
608 581
609 void GpuVideoDecoder::NotifyResetDone() { 582 void GpuVideoDecoder::NotifyResetDone() {
610 DVLOG(3) << "NotifyResetDone()"; 583 DVLOG(3) << "NotifyResetDone()";
611 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 584 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
612 DCHECK(ready_video_frames_.empty()); 585 DCHECK(pending_decode_callbacks_.empty());
613 586
614 // This needs to happen after the Reset() on vda_ is done to ensure pictures 587 // This needs to happen after the Reset() on vda_ is done to ensure pictures
615 // delivered during the reset can find their time data. 588 // delivered during the reset can find their time data.
616 input_buffer_data_.clear(); 589 input_buffer_data_.clear();
617 590
618 if (!pending_reset_cb_.is_null()) 591 if (!pending_reset_cb_.is_null())
619 base::ResetAndReturn(&pending_reset_cb_).Run(); 592 base::ResetAndReturn(&pending_reset_cb_).Run();
620
621 if (!pending_decode_cb_.is_null())
622 EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame());
623 } 593 }
624 594
625 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { 595 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) {
626 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 596 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
627 if (!vda_) 597 if (!vda_)
628 return; 598 return;
629 599
630 DLOG(ERROR) << "VDA Error: " << error; 600 DLOG(ERROR) << "VDA Error: " << error;
631 DestroyVDA(); 601 DestroyVDA();
632 602
633 state_ = kError; 603 state_ = kError;
634 604
635 if (!pending_decode_cb_.is_null()) { 605 while (!pending_decode_callbacks_.empty()) {
636 base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); 606 pending_decode_callbacks_.front().Run(kDecodeError, NULL);
637 return; 607 pending_decode_callbacks_.pop_front();
638 } 608 }
639 } 609 }
640 610
641 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() 611 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent()
642 const { 612 const {
643 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); 613 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread());
644 } 614 }
645 615
646 } // namespace media 616 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698