| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "content/common/gpu/media/android_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/android_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/android/build_info.h" | 9 #include "base/android/build_info.h" |
| 10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| 17 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
| 18 #include "base/trace_event/trace_event.h" | 18 #include "base/trace_event/trace_event.h" |
| 19 #include "content/common/gpu/gpu_channel.h" | 19 #include "content/common/gpu/gpu_channel.h" |
| 20 #include "content/common/gpu/media/android_copying_backing_strategy.h" | 20 #include "content/common/gpu/media/android_copying_backing_strategy.h" |
| 21 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h
" | 21 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h
" |
| 22 #include "content/common/gpu/media/avda_return_on_failure.h" |
| 22 #include "content/common/gpu/media/shared_memory_region.h" | 23 #include "content/common/gpu/media/shared_memory_region.h" |
| 23 #include "content/public/common/content_switches.h" | 24 #include "content/public/common/content_switches.h" |
| 24 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 25 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| 25 #include "gpu/command_buffer/service/gpu_switches.h" | 26 #include "gpu/command_buffer/service/gpu_switches.h" |
| 26 #include "gpu/command_buffer/service/mailbox_manager.h" | 27 #include "gpu/command_buffer/service/mailbox_manager.h" |
| 27 #include "media/base/android/media_codec_bridge.h" | 28 #include "media/base/android/media_codec_bridge.h" |
| 28 #include "media/base/android/media_codec_util.h" | 29 #include "media/base/android/media_codec_util.h" |
| 29 #include "media/base/bind_to_current_loop.h" | 30 #include "media/base/bind_to_current_loop.h" |
| 30 #include "media/base/bitstream_buffer.h" | 31 #include "media/base/bitstream_buffer.h" |
| 31 #include "media/base/limits.h" | 32 #include "media/base/limits.h" |
| (...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 | 593 |
| 593 switch (status) { | 594 switch (status) { |
| 594 case media::MEDIA_CODEC_ERROR: | 595 case media::MEDIA_CODEC_ERROR: |
| 595 POST_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed."); | 596 POST_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed."); |
| 596 return false; | 597 return false; |
| 597 | 598 |
| 598 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: | 599 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
| 599 return false; | 600 return false; |
| 600 | 601 |
| 601 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { | 602 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { |
| 602 if (!output_picture_buffers_.empty()) { | |
| 603 // TODO(chcunningham): This will likely dismiss a handful of decoded | |
| 604 // frames that have not yet been drawn and returned to us for re-use. | |
| 605 // Consider a more complicated design that would wait for them to be | |
| 606 // drawn before dismissing. | |
| 607 DismissPictureBuffers(); | |
| 608 } | |
| 609 | |
| 610 if (media_codec_->GetOutputSize(&size_) != media::MEDIA_CODEC_OK) { | 603 if (media_codec_->GetOutputSize(&size_) != media::MEDIA_CODEC_OK) { |
| 611 POST_ERROR(PLATFORM_FAILURE, "GetOutputSize failed."); | 604 POST_ERROR(PLATFORM_FAILURE, "GetOutputSize failed."); |
| 612 return false; | 605 return false; |
| 613 } | 606 } |
| 607 DVLOG(3) << __FUNCTION__ |
| 608 << " OUTPUT_FORMAT_CHANGED, new size: " << size_.ToString(); |
| 614 | 609 |
| 615 picturebuffers_requested_ = true; | 610 // Don't request picture buffers if we already have some. This avoids |
| 616 base::MessageLoop::current()->PostTask( | 611 // having to dismiss the existing buffers which may actively reference |
| 617 FROM_HERE, | 612 // decoded images. Breaking their connection to the decoded image will |
| 618 base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers, | 613 // cause rendering of black frames. Instead, we let the existing |
| 619 weak_this_factory_.GetWeakPtr())); | 614 // PictureBuffers live on and we simply update their size the next time |
| 620 return false; | 615 // they're attachted to an image of the new resolution. See the |
| 616 // size update in |SendDecodedFrameToClient| and https://crbug/587994. |
| 617 if (output_picture_buffers_.empty() && !picturebuffers_requested_) { |
| 618 picturebuffers_requested_ = true; |
| 619 base::MessageLoop::current()->PostTask( |
| 620 FROM_HERE, |
| 621 base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers, |
| 622 weak_this_factory_.GetWeakPtr())); |
| 623 return false; |
| 624 } |
| 625 |
| 626 return true; |
| 621 } | 627 } |
| 622 | 628 |
| 623 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: | 629 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: |
| 624 break; | 630 break; |
| 625 | 631 |
| 626 case media::MEDIA_CODEC_OK: | 632 case media::MEDIA_CODEC_OK: |
| 627 DCHECK_GE(buf_index, 0); | 633 DCHECK_GE(buf_index, 0); |
| 628 DVLOG(3) << __FUNCTION__ << ": pts:" << presentation_timestamp | 634 DVLOG(3) << __FUNCTION__ << ": pts:" << presentation_timestamp |
| 629 << " buf_index:" << buf_index << " offset:" << offset | 635 << " buf_index:" << buf_index << " offset:" << offset |
| 630 << " size:" << size << " eos:" << eos; | 636 << " size:" << size << " eos:" << eos; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 | 722 |
| 717 if (!make_context_current_.Run()) { | 723 if (!make_context_current_.Run()) { |
| 718 POST_ERROR(PLATFORM_FAILURE, "Failed to make the GL context current."); | 724 POST_ERROR(PLATFORM_FAILURE, "Failed to make the GL context current."); |
| 719 return; | 725 return; |
| 720 } | 726 } |
| 721 | 727 |
| 722 int32_t picture_buffer_id = free_picture_ids_.front(); | 728 int32_t picture_buffer_id = free_picture_ids_.front(); |
| 723 free_picture_ids_.pop(); | 729 free_picture_ids_.pop(); |
| 724 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); | 730 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); |
| 725 | 731 |
| 726 OutputBufferMap::const_iterator i = | 732 const auto& i = output_picture_buffers_.find(picture_buffer_id); |
| 727 output_picture_buffers_.find(picture_buffer_id); | |
| 728 if (i == output_picture_buffers_.end()) { | 733 if (i == output_picture_buffers_.end()) { |
| 729 POST_ERROR(PLATFORM_FAILURE, | 734 POST_ERROR(PLATFORM_FAILURE, |
| 730 "Can't find PictureBuffer id: " << picture_buffer_id); | 735 "Can't find PictureBuffer id: " << picture_buffer_id); |
| 731 return; | 736 return; |
| 732 } | 737 } |
| 733 | 738 |
| 739 bool size_changed = false; |
| 740 if (i->second.size() != size_) { |
| 741 // Size may have changed due to resolution change since the last time this |
| 742 // PictureBuffer was used. |
| 743 strategy_->UpdatePictureBufferSize(&i->second, size_); |
| 744 size_changed = true; |
| 745 } |
| 746 |
| 734 // Connect the PictureBuffer to the decoded frame, via whatever | 747 // Connect the PictureBuffer to the decoded frame, via whatever |
| 735 // mechanism the strategy likes. | 748 // mechanism the strategy likes. |
| 736 strategy_->UseCodecBufferForPictureBuffer(codec_buffer_index, i->second); | 749 strategy_->UseCodecBufferForPictureBuffer(codec_buffer_index, i->second); |
| 737 | 750 |
| 738 const bool allow_overlay = strategy_->ArePicturesOverlayable(); | 751 const bool allow_overlay = strategy_->ArePicturesOverlayable(); |
| 752 |
| 753 media::Picture picture(picture_buffer_id, bitstream_id, gfx::Rect(size_), |
| 754 allow_overlay); |
| 755 picture.set_size_changed(size_changed); |
| 756 |
| 739 base::MessageLoop::current()->PostTask( | 757 base::MessageLoop::current()->PostTask( |
| 740 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady, | 758 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady, |
| 741 weak_this_factory_.GetWeakPtr(), | 759 weak_this_factory_.GetWeakPtr(), picture)); |
| 742 media::Picture(picture_buffer_id, bitstream_id, | |
| 743 gfx::Rect(size_), allow_overlay))); | |
| 744 } | 760 } |
| 745 | 761 |
| 746 void AndroidVideoDecodeAccelerator::Decode( | 762 void AndroidVideoDecodeAccelerator::Decode( |
| 747 const media::BitstreamBuffer& bitstream_buffer) { | 763 const media::BitstreamBuffer& bitstream_buffer) { |
| 748 DCHECK(thread_checker_.CalledOnValidThread()); | 764 DCHECK(thread_checker_.CalledOnValidThread()); |
| 749 | 765 |
| 750 if (bitstream_buffer.id() >= 0 && bitstream_buffer.size() > 0) { | 766 if (bitstream_buffer.id() >= 0 && bitstream_buffer.size() > 0) { |
| 751 DecodeBuffer(bitstream_buffer); | 767 DecodeBuffer(bitstream_buffer); |
| 752 return; | 768 return; |
| 753 } | 769 } |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1013 const base::ThreadChecker& AndroidVideoDecodeAccelerator::ThreadChecker() | 1029 const base::ThreadChecker& AndroidVideoDecodeAccelerator::ThreadChecker() |
| 1014 const { | 1030 const { |
| 1015 return thread_checker_; | 1031 return thread_checker_; |
| 1016 } | 1032 } |
| 1017 | 1033 |
| 1018 base::WeakPtr<gpu::gles2::GLES2Decoder> | 1034 base::WeakPtr<gpu::gles2::GLES2Decoder> |
| 1019 AndroidVideoDecodeAccelerator::GetGlDecoder() const { | 1035 AndroidVideoDecodeAccelerator::GetGlDecoder() const { |
| 1020 return gl_decoder_; | 1036 return gl_decoder_; |
| 1021 } | 1037 } |
| 1022 | 1038 |
| 1039 gpu::gles2::TextureRef* AndroidVideoDecodeAccelerator::GetTextureForPicture( |
| 1040 const media::PictureBuffer& picture_buffer) { |
| 1041 RETURN_ON_FAILURE(this, gl_decoder_, "Null gl_decoder_", ILLEGAL_STATE, |
| 1042 nullptr); |
| 1043 RETURN_ON_FAILURE(this, gl_decoder_->GetContextGroup(), |
| 1044 "Null gl_decoder_->GetContextGroup()", ILLEGAL_STATE, |
| 1045 nullptr); |
| 1046 gpu::gles2::TextureManager* texture_manager = |
| 1047 gl_decoder_->GetContextGroup()->texture_manager(); |
| 1048 RETURN_ON_FAILURE(this, texture_manager, "Null texture_manager", |
| 1049 ILLEGAL_STATE, nullptr); |
| 1050 gpu::gles2::TextureRef* texture_ref = |
| 1051 texture_manager->GetTexture(picture_buffer.internal_texture_id()); |
| 1052 RETURN_ON_FAILURE(this, texture_manager, "Null texture_ref", ILLEGAL_STATE, |
| 1053 nullptr); |
| 1054 |
| 1055 return texture_ref; |
| 1056 } |
| 1057 |
| 1023 void AndroidVideoDecodeAccelerator::OnFrameAvailable() { | 1058 void AndroidVideoDecodeAccelerator::OnFrameAvailable() { |
| 1024 // Remember: this may be on any thread. | 1059 // Remember: this may be on any thread. |
| 1025 DCHECK(strategy_); | 1060 DCHECK(strategy_); |
| 1026 strategy_->OnFrameAvailable(); | 1061 strategy_->OnFrameAvailable(); |
| 1027 } | 1062 } |
| 1028 | 1063 |
| 1029 void AndroidVideoDecodeAccelerator::PostError( | 1064 void AndroidVideoDecodeAccelerator::PostError( |
| 1030 const ::tracked_objects::Location& from_here, | 1065 const ::tracked_objects::Location& from_here, |
| 1031 media::VideoDecodeAccelerator::Error error) { | 1066 media::VideoDecodeAccelerator::Error error) { |
| 1032 base::MessageLoop::current()->PostDelayedTask( | 1067 base::MessageLoop::current()->PostDelayedTask( |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1167 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: | 1202 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: |
| 1168 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | | 1203 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | |
| 1169 media::VideoDecodeAccelerator::Capabilities:: | 1204 media::VideoDecodeAccelerator::Capabilities:: |
| 1170 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1205 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
| 1171 } | 1206 } |
| 1172 | 1207 |
| 1173 return capabilities; | 1208 return capabilities; |
| 1174 } | 1209 } |
| 1175 | 1210 |
| 1176 } // namespace content | 1211 } // namespace content |
| OLD | NEW |