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 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/cpu.h" | 13 #include "base/cpu.h" |
| 14 #include "base/memory/ptr_util.h" |
14 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
15 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
16 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
17 #include "base/task_runner_util.h" | 18 #include "base/task_runner_util.h" |
18 #include "build/build_config.h" | 19 #include "build/build_config.h" |
19 #include "gpu/command_buffer/common/mailbox_holder.h" | 20 #include "gpu/command_buffer/common/mailbox_holder.h" |
20 #include "media/base/bind_to_current_loop.h" | 21 #include "media/base/bind_to_current_loop.h" |
21 #include "media/base/cdm_context.h" | 22 #include "media/base/cdm_context.h" |
22 #include "media/base/decoder_buffer.h" | 23 #include "media/base/decoder_buffer.h" |
23 #include "media/base/media_switches.h" | 24 #include "media/base/media_switches.h" |
24 #include "media/base/pipeline_status.h" | 25 #include "media/base/pipeline_status.h" |
25 #include "media/base/surface_manager.h" | 26 #include "media/base/surface_manager.h" |
26 #include "media/base/video_decoder_config.h" | 27 #include "media/base/video_decoder_config.h" |
27 #include "media/renderers/gpu_video_accelerator_factories.h" | 28 #include "media/renderers/gpu_video_accelerator_factories.h" |
28 #include "third_party/skia/include/core/SkBitmap.h" | 29 #include "third_party/skia/include/core/SkBitmap.h" |
29 | 30 |
30 namespace media { | 31 namespace media { |
31 | 32 |
32 const char GpuVideoDecoder::kDecoderName[] = "GpuVideoDecoder"; | 33 const char GpuVideoDecoder::kDecoderName[] = "GpuVideoDecoder"; |
33 | 34 |
34 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. | 35 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. |
35 // Higher values allow better pipelining in the GPU, but also require more | 36 // Higher values allow better pipelining in the GPU, but also require more |
36 // resources. | 37 // resources. |
37 enum { kMaxInFlightDecodes = 4 }; | 38 enum { kMaxInFlightDecodes = 4 }; |
38 | 39 |
39 // Size of shared-memory segments we allocate. Since we reuse them we let them | 40 // Size of shared-memory segments we allocate. Since we reuse them we let them |
40 // be on the beefy side. | 41 // be on the beefy side. |
41 static const size_t kSharedMemorySegmentBytes = 100 << 10; | 42 static const size_t kSharedMemorySegmentBytes = 100 << 10; |
42 | 43 |
43 GpuVideoDecoder::SHMBuffer::SHMBuffer(scoped_ptr<base::SharedMemory> m, | 44 GpuVideoDecoder::SHMBuffer::SHMBuffer(std::unique_ptr<base::SharedMemory> m, |
44 size_t s) | 45 size_t s) |
45 : shm(std::move(m)), size(s) {} | 46 : shm(std::move(m)), size(s) {} |
46 | 47 |
47 GpuVideoDecoder::SHMBuffer::~SHMBuffer() {} | 48 GpuVideoDecoder::SHMBuffer::~SHMBuffer() {} |
48 | 49 |
49 GpuVideoDecoder::PendingDecoderBuffer::PendingDecoderBuffer( | 50 GpuVideoDecoder::PendingDecoderBuffer::PendingDecoderBuffer( |
50 SHMBuffer* s, | 51 SHMBuffer* s, |
51 const scoped_refptr<DecoderBuffer>& b, | 52 const scoped_refptr<DecoderBuffer>& b, |
52 const DecodeCB& done_cb) | 53 const DecodeCB& done_cb) |
53 : shm_buffer(s), buffer(b), done_cb(done_cb) { | 54 : shm_buffer(s), buffer(b), done_cb(done_cb) { |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 | 340 |
340 if (buffer->end_of_stream()) { | 341 if (buffer->end_of_stream()) { |
341 DVLOG(3) << __FUNCTION__ << " Initiating Flush for EOS."; | 342 DVLOG(3) << __FUNCTION__ << " Initiating Flush for EOS."; |
342 state_ = kDrainingDecoder; | 343 state_ = kDrainingDecoder; |
343 eos_decode_cb_ = bound_decode_cb; | 344 eos_decode_cb_ = bound_decode_cb; |
344 vda_->Flush(); | 345 vda_->Flush(); |
345 return; | 346 return; |
346 } | 347 } |
347 | 348 |
348 size_t size = buffer->data_size(); | 349 size_t size = buffer->data_size(); |
349 scoped_ptr<SHMBuffer> shm_buffer = GetSHM(size); | 350 std::unique_ptr<SHMBuffer> shm_buffer = GetSHM(size); |
350 if (!shm_buffer) { | 351 if (!shm_buffer) { |
351 bound_decode_cb.Run(DecodeStatus::DECODE_ERROR); | 352 bound_decode_cb.Run(DecodeStatus::DECODE_ERROR); |
352 return; | 353 return; |
353 } | 354 } |
354 | 355 |
355 memcpy(shm_buffer->shm->memory(), buffer->data(), size); | 356 memcpy(shm_buffer->shm->memory(), buffer->data(), size); |
356 // AndroidVideoDecodeAccelerator needs the timestamp to output frames in | 357 // AndroidVideoDecodeAccelerator needs the timestamp to output frames in |
357 // presentation order. | 358 // presentation order. |
358 BitstreamBuffer bitstream_buffer(next_bitstream_buffer_id_, | 359 BitstreamBuffer bitstream_buffer(next_bitstream_buffer_id_, |
359 shm_buffer->shm->handle(), size, 0, | 360 shm_buffer->shm->handle(), size, 0, |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 return; | 627 return; |
627 } | 628 } |
628 | 629 |
629 ++available_pictures_; | 630 ++available_pictures_; |
630 | 631 |
631 // DestroyVDA() might already have been called. | 632 // DestroyVDA() might already have been called. |
632 if (vda_) | 633 if (vda_) |
633 vda_->ReusePictureBuffer(picture_buffer_id); | 634 vda_->ReusePictureBuffer(picture_buffer_id); |
634 } | 635 } |
635 | 636 |
636 scoped_ptr<GpuVideoDecoder::SHMBuffer> GpuVideoDecoder::GetSHM( | 637 std::unique_ptr<GpuVideoDecoder::SHMBuffer> GpuVideoDecoder::GetSHM( |
637 size_t min_size) { | 638 size_t min_size) { |
638 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 639 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
639 if (available_shm_segments_.empty() || | 640 if (available_shm_segments_.empty() || |
640 available_shm_segments_.back()->size < min_size) { | 641 available_shm_segments_.back()->size < min_size) { |
641 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); | 642 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); |
642 scoped_ptr<base::SharedMemory> shm = | 643 std::unique_ptr<base::SharedMemory> shm = |
643 factories_->CreateSharedMemory(size_to_allocate); | 644 factories_->CreateSharedMemory(size_to_allocate); |
644 // CreateSharedMemory() can return NULL during Shutdown. | 645 // CreateSharedMemory() can return NULL during Shutdown. |
645 if (!shm) | 646 if (!shm) |
646 return NULL; | 647 return NULL; |
647 return make_scoped_ptr(new SHMBuffer(std::move(shm), size_to_allocate)); | 648 return base::WrapUnique(new SHMBuffer(std::move(shm), size_to_allocate)); |
648 } | 649 } |
649 scoped_ptr<SHMBuffer> ret(available_shm_segments_.back()); | 650 std::unique_ptr<SHMBuffer> ret(available_shm_segments_.back()); |
650 available_shm_segments_.pop_back(); | 651 available_shm_segments_.pop_back(); |
651 return ret; | 652 return ret; |
652 } | 653 } |
653 | 654 |
654 void GpuVideoDecoder::PutSHM(scoped_ptr<SHMBuffer> shm_buffer) { | 655 void GpuVideoDecoder::PutSHM(std::unique_ptr<SHMBuffer> shm_buffer) { |
655 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 656 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
656 available_shm_segments_.push_back(shm_buffer.release()); | 657 available_shm_segments_.push_back(shm_buffer.release()); |
657 } | 658 } |
658 | 659 |
659 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32_t id) { | 660 void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32_t id) { |
660 DVLOG(3) << "NotifyEndOfBitstreamBuffer(" << id << ")"; | 661 DVLOG(3) << "NotifyEndOfBitstreamBuffer(" << id << ")"; |
661 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 662 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
662 | 663 |
663 std::map<int32_t, PendingDecoderBuffer>::iterator it = | 664 std::map<int32_t, PendingDecoderBuffer>::iterator it = |
664 bitstream_buffers_in_decoder_.find(id); | 665 bitstream_buffers_in_decoder_.find(id); |
665 if (it == bitstream_buffers_in_decoder_.end()) { | 666 if (it == bitstream_buffers_in_decoder_.end()) { |
666 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 667 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
667 NOTREACHED() << "Missing bitstream buffer: " << id; | 668 NOTREACHED() << "Missing bitstream buffer: " << id; |
668 return; | 669 return; |
669 } | 670 } |
670 | 671 |
671 PutSHM(make_scoped_ptr(it->second.shm_buffer)); | 672 PutSHM(base::WrapUnique(it->second.shm_buffer)); |
672 it->second.done_cb.Run(state_ == kError ? DecodeStatus::DECODE_ERROR | 673 it->second.done_cb.Run(state_ == kError ? DecodeStatus::DECODE_ERROR |
673 : DecodeStatus::OK); | 674 : DecodeStatus::OK); |
674 bitstream_buffers_in_decoder_.erase(it); | 675 bitstream_buffers_in_decoder_.erase(it); |
675 } | 676 } |
676 | 677 |
677 GpuVideoDecoder::~GpuVideoDecoder() { | 678 GpuVideoDecoder::~GpuVideoDecoder() { |
678 DVLOG(3) << __FUNCTION__; | 679 DVLOG(3) << __FUNCTION__; |
679 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 680 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
680 | 681 |
681 if (vda_) | 682 if (vda_) |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 } | 768 } |
768 return false; | 769 return false; |
769 } | 770 } |
770 | 771 |
771 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() | 772 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() |
772 const { | 773 const { |
773 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); | 774 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); |
774 } | 775 } |
775 | 776 |
776 } // namespace media | 777 } // namespace media |
OLD | NEW |