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" |
11 #include "base/cpu.h" | 11 #include "base/cpu.h" |
12 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 15 #include "base/synchronization/waitable_event.h" |
15 #include "base/task_runner_util.h" | 16 #include "base/task_runner_util.h" |
16 #include "media/base/bind_to_current_loop.h" | 17 #include "media/base/bind_to_current_loop.h" |
17 #include "media/base/decoder_buffer.h" | 18 #include "media/base/decoder_buffer.h" |
18 #include "media/base/media_log.h" | 19 #include "media/base/media_log.h" |
19 #include "media/base/pipeline.h" | 20 #include "media/base/pipeline.h" |
20 #include "media/base/pipeline_status.h" | 21 #include "media/base/pipeline_status.h" |
21 #include "media/base/video_decoder_config.h" | 22 #include "media/base/video_decoder_config.h" |
22 #include "media/filters/gpu_video_accelerator_factories.h" | 23 #include "media/filters/gpu_video_accelerator_factories.h" |
| 24 #include "third_party/skia/include/core/SkBitmap.h" |
23 | 25 |
24 namespace media { | 26 namespace media { |
25 | 27 |
26 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. | 28 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. |
27 // Higher values allow better pipelining in the GPU, but also require more | 29 // Higher values allow better pipelining in the GPU, but also require more |
28 // resources. | 30 // resources. |
29 enum { kMaxInFlightDecodes = 4 }; | 31 enum { kMaxInFlightDecodes = 4 }; |
30 | 32 |
31 // Size of shared-memory segments we allocate. Since we reuse them we let them | 33 // Size of shared-memory segments we allocate. Since we reuse them we let them |
32 // be on the beefy side. | 34 // be on the beefy side. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 next_picture_buffer_id_(0), | 67 next_picture_buffer_id_(0), |
66 next_bitstream_buffer_id_(0), | 68 next_bitstream_buffer_id_(0), |
67 available_pictures_(0) { | 69 available_pictures_(0) { |
68 DCHECK(factories_.get()); | 70 DCHECK(factories_.get()); |
69 } | 71 } |
70 | 72 |
71 void GpuVideoDecoder::Reset(const base::Closure& closure) { | 73 void GpuVideoDecoder::Reset(const base::Closure& closure) { |
72 DVLOG(3) << "Reset()"; | 74 DVLOG(3) << "Reset()"; |
73 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 75 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
74 | 76 |
75 if (state_ == kDrainingDecoder && !factories_->IsAborted()) { | 77 if (state_ == kDrainingDecoder) { |
76 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 78 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( |
77 &GpuVideoDecoder::Reset, weak_this_, closure)); | 79 &GpuVideoDecoder::Reset, weak_this_, closure)); |
78 // NOTE: if we're deferring Reset() until a Flush() completes, return | 80 // 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(). | 81 // queued pictures to the VDA so they can be used to finish that Flush(). |
80 if (pending_decode_cb_.is_null()) | 82 if (pending_decode_cb_.is_null()) |
81 ready_video_frames_.clear(); | 83 ready_video_frames_.clear(); |
82 return; | 84 return; |
83 } | 85 } |
84 | 86 |
85 // Throw away any already-decoded, not-yet-delivered frames. | 87 // Throw away any already-decoded, not-yet-delivered frames. |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 CHECK_GT(available_pictures_, 0); | 415 CHECK_GT(available_pictures_, 0); |
414 --available_pictures_; | 416 --available_pictures_; |
415 } else { | 417 } else { |
416 // Texture in display. Postpone deletion until after it's returned to us. | 418 // Texture in display. Postpone deletion until after it's returned to us. |
417 bool inserted = dismissed_picture_buffers_.insert(std::make_pair( | 419 bool inserted = dismissed_picture_buffers_.insert(std::make_pair( |
418 id, buffer_to_dismiss)).second; | 420 id, buffer_to_dismiss)).second; |
419 DCHECK(inserted); | 421 DCHECK(inserted); |
420 } | 422 } |
421 } | 423 } |
422 | 424 |
| 425 static void ReadPixelsSyncInner( |
| 426 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, |
| 427 uint32 texture_id, |
| 428 const gfx::Rect& visible_rect, |
| 429 const SkBitmap& pixels, |
| 430 base::WaitableEvent* event) { |
| 431 factories->ReadPixels(texture_id, visible_rect, pixels); |
| 432 event->Signal(); |
| 433 } |
| 434 |
| 435 static void ReadPixelsSync( |
| 436 const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories, |
| 437 uint32 texture_id, |
| 438 const gfx::Rect& visible_rect, |
| 439 const SkBitmap& pixels) { |
| 440 base::WaitableEvent event(true, false); |
| 441 if (!factories->GetTaskRunner()->PostTask(FROM_HERE, |
| 442 base::Bind(&ReadPixelsSyncInner, |
| 443 factories, |
| 444 texture_id, |
| 445 visible_rect, |
| 446 pixels, |
| 447 &event))) |
| 448 return; |
| 449 event.Wait(); |
| 450 } |
| 451 |
423 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { | 452 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { |
424 DVLOG(3) << "PictureReady()"; | 453 DVLOG(3) << "PictureReady()"; |
425 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 454 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
426 | 455 |
427 PictureBufferMap::iterator it = | 456 PictureBufferMap::iterator it = |
428 assigned_picture_buffers_.find(picture.picture_buffer_id()); | 457 assigned_picture_buffers_.find(picture.picture_buffer_id()); |
429 if (it == assigned_picture_buffers_.end()) { | 458 if (it == assigned_picture_buffers_.end()) { |
430 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); | 459 NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); |
431 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 460 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
432 return; | 461 return; |
(...skipping 13 matching lines...) Expand all Loading... |
446 pb.texture_mailbox(), | 475 pb.texture_mailbox(), |
447 0, // sync_point | 476 0, // sync_point |
448 BindToCurrentLoop(base::Bind(&GpuVideoDecoder::ReusePictureBuffer, | 477 BindToCurrentLoop(base::Bind(&GpuVideoDecoder::ReusePictureBuffer, |
449 weak_this_, | 478 weak_this_, |
450 picture.picture_buffer_id())))), | 479 picture.picture_buffer_id())))), |
451 decoder_texture_target_, | 480 decoder_texture_target_, |
452 pb.size(), | 481 pb.size(), |
453 visible_rect, | 482 visible_rect, |
454 natural_size, | 483 natural_size, |
455 timestamp, | 484 timestamp, |
456 base::Bind(&GpuVideoAcceleratorFactories::ReadPixels, | 485 base::Bind(&ReadPixelsSync, factories_, pb.texture_id(), visible_rect), |
457 factories_, | |
458 pb.texture_id(), | |
459 gfx::Size(visible_rect.width(), visible_rect.height())), | |
460 base::Closure())); | 486 base::Closure())); |
461 CHECK_GT(available_pictures_, 0); | 487 CHECK_GT(available_pictures_, 0); |
462 --available_pictures_; | 488 --available_pictures_; |
463 bool inserted = | 489 bool inserted = |
464 picture_buffers_at_display_.insert(picture.picture_buffer_id()).second; | 490 picture_buffers_at_display_.insert(picture.picture_buffer_id()).second; |
465 DCHECK(inserted); | 491 DCHECK(inserted); |
466 | 492 |
467 EnqueueFrameAndTriggerFrameDelivery(frame); | 493 EnqueueFrameAndTriggerFrameDelivery(frame); |
468 } | 494 } |
469 | 495 |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
621 return; | 647 return; |
622 } | 648 } |
623 } | 649 } |
624 | 650 |
625 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() | 651 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() |
626 const { | 652 const { |
627 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); | 653 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); |
628 } | 654 } |
629 | 655 |
630 } // namespace media | 656 } // namespace media |
OLD | NEW |