| 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 |