Chromium Code Reviews| 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/public/common/content_switches.h" | 23 #include "content/public/common/content_switches.h" |
| 23 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 24 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| 24 #include "gpu/command_buffer/service/gpu_switches.h" | 25 #include "gpu/command_buffer/service/gpu_switches.h" |
| 25 #include "gpu/command_buffer/service/mailbox_manager.h" | 26 #include "gpu/command_buffer/service/mailbox_manager.h" |
| 26 #include "media/base/android/media_codec_bridge.h" | 27 #include "media/base/android/media_codec_bridge.h" |
| 27 #include "media/base/android/media_codec_util.h" | 28 #include "media/base/android/media_codec_util.h" |
| 28 #include "media/base/bind_to_current_loop.h" | 29 #include "media/base/bind_to_current_loop.h" |
| 29 #include "media/base/bitstream_buffer.h" | 30 #include "media/base/bitstream_buffer.h" |
| 30 #include "media/base/limits.h" | 31 #include "media/base/limits.h" |
| 31 #include "media/base/media.h" | 32 #include "media/base/media.h" |
| 32 #include "media/base/media_switches.h" | 33 #include "media/base/media_switches.h" |
| 33 #include "media/base/timestamp_constants.h" | 34 #include "media/base/timestamp_constants.h" |
| 34 #include "media/base/video_decoder_config.h" | 35 #include "media/base/video_decoder_config.h" |
| 35 #include "media/video/picture.h" | 36 #include "media/video/picture.h" |
| 36 #include "ui/gl/android/scoped_java_surface.h" | 37 #include "ui/gl/android/scoped_java_surface.h" |
| 37 #include "ui/gl/android/surface_texture.h" | 38 #include "ui/gl/android/surface_texture.h" |
| 38 #include "ui/gl/gl_bindings.h" | 39 #include "ui/gl/gl_bindings.h" |
| 39 | 40 |
| 40 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 41 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 41 #include "media/base/media_keys.h" | 42 #include "media/base/media_keys.h" |
| 42 #include "media/mojo/services/mojo_cdm_service.h" | 43 #include "media/mojo/services/mojo_cdm_service.h" |
| 43 #endif | 44 #endif |
| 44 | 45 |
| 45 #define POST_ERROR(error_code, error_message) \ | 46 #define POST_ERROR(error_code, error_message) \ |
| 46 do { \ | 47 do { \ |
| 47 DLOG(ERROR) << error_message; \ | 48 DLOG(ERROR) << error_message; \ |
| 48 PostError(FROM_HERE, media::VideoDecodeAccelerator::error_code); \ | 49 PostError(FROM_HERE, media::VideoDecodeAccelerator::error_code); \ |
| 49 } while (0) | 50 } while (0) |
| 50 | 51 |
| 52 // Override definition from avda_return_on_failure.h to s/state_provider_/this/. | |
| 53 #undef RETURN_NULL_IF_NULL | |
| 54 #define RETURN_NULL_IF_NULL(ptr, ...) \ | |
| 55 RETURN_ON_FAILURE(this, ptr, "Got null for " << #ptr, ILLEGAL_STATE, nullptr); | |
| 56 | |
| 51 namespace content { | 57 namespace content { |
| 52 | 58 |
| 53 enum { kNumPictureBuffers = media::limits::kMaxVideoFrames + 1 }; | 59 enum { kNumPictureBuffers = media::limits::kMaxVideoFrames + 1 }; |
| 54 | 60 |
| 55 // Max number of bitstreams notified to the client with | 61 // Max number of bitstreams notified to the client with |
| 56 // NotifyEndOfBitstreamBuffer() before getting output from the bitstream. | 62 // NotifyEndOfBitstreamBuffer() before getting output from the bitstream. |
| 57 enum { kMaxBitstreamsNotifiedInAdvance = 32 }; | 63 enum { kMaxBitstreamsNotifiedInAdvance = 32 }; |
| 58 | 64 |
| 59 // MediaCodec is only guaranteed to support baseline, but some devices may | 65 // MediaCodec is only guaranteed to support baseline, but some devices may |
| 60 // support others. Advertise support for all H264 profiles and let the | 66 // support others. Advertise support for all H264 profiles and let the |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 578 | 584 |
| 579 switch (status) { | 585 switch (status) { |
| 580 case media::MEDIA_CODEC_ERROR: | 586 case media::MEDIA_CODEC_ERROR: |
| 581 POST_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed."); | 587 POST_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed."); |
| 582 return false; | 588 return false; |
| 583 | 589 |
| 584 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: | 590 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
| 585 return false; | 591 return false; |
| 586 | 592 |
| 587 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { | 593 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { |
| 588 if (!output_picture_buffers_.empty()) { | |
| 589 // TODO(chcunningham): This will likely dismiss a handful of decoded | |
| 590 // frames that have not yet been drawn and returned to us for re-use. | |
| 591 // Consider a more complicated design that would wait for them to be | |
| 592 // drawn before dismissing. | |
| 593 DismissPictureBuffers(); | |
| 594 } | |
| 595 | |
| 596 if (media_codec_->GetOutputSize(&size_) != media::MEDIA_CODEC_OK) { | 594 if (media_codec_->GetOutputSize(&size_) != media::MEDIA_CODEC_OK) { |
| 597 POST_ERROR(PLATFORM_FAILURE, "GetOutputSize failed."); | 595 POST_ERROR(PLATFORM_FAILURE, "GetOutputSize failed."); |
| 598 return false; | 596 return false; |
| 599 } | 597 } |
| 598 DVLOG(3) << __FUNCTION__ | |
| 599 << " OUTPUT_FORMAT_CHANGED, new size: " << size_.ToString(); | |
| 600 | 600 |
| 601 picturebuffers_requested_ = true; | 601 // Don't request picture buffers if we already have some. This avoids |
| 602 base::MessageLoop::current()->PostTask( | 602 // having to dismiss the existing buffers which may actively reference |
| 603 FROM_HERE, | 603 // decoded images. Breaking their connection to the decoded image will |
| 604 base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers, | 604 // cause rendering of black frames. Instead, we let the existing |
| 605 weak_this_factory_.GetWeakPtr())); | 605 // PictureBuffers live on and we simply update their size the next time |
| 606 return false; | 606 // they're attachted to an image of the new resolution. See the |
| 607 // size update in |SendDecodedFrameToClient| and https://crbug/587994. | |
| 608 if (output_picture_buffers_.empty()) { | |
| 609 picturebuffers_requested_ = true; | |
| 610 base::MessageLoop::current()->PostTask( | |
| 611 FROM_HERE, | |
| 612 base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers, | |
| 613 weak_this_factory_.GetWeakPtr())); | |
| 614 return false; | |
| 615 } | |
| 616 | |
| 617 return true; | |
| 607 } | 618 } |
| 608 | 619 |
| 609 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: | 620 case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: |
| 610 break; | 621 break; |
| 611 | 622 |
| 612 case media::MEDIA_CODEC_OK: | 623 case media::MEDIA_CODEC_OK: |
| 613 DCHECK_GE(buf_index, 0); | 624 DCHECK_GE(buf_index, 0); |
| 614 DVLOG(3) << __FUNCTION__ << ": pts:" << presentation_timestamp | 625 DVLOG(3) << __FUNCTION__ << ": pts:" << presentation_timestamp |
| 615 << " buf_index:" << buf_index << " offset:" << offset | 626 << " buf_index:" << buf_index << " offset:" << offset |
| 616 << " size:" << size << " eos:" << eos; | 627 << " size:" << size << " eos:" << eos; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 702 | 713 |
| 703 if (!make_context_current_.Run()) { | 714 if (!make_context_current_.Run()) { |
| 704 POST_ERROR(PLATFORM_FAILURE, "Failed to make the GL context current."); | 715 POST_ERROR(PLATFORM_FAILURE, "Failed to make the GL context current."); |
| 705 return; | 716 return; |
| 706 } | 717 } |
| 707 | 718 |
| 708 int32_t picture_buffer_id = free_picture_ids_.front(); | 719 int32_t picture_buffer_id = free_picture_ids_.front(); |
| 709 free_picture_ids_.pop(); | 720 free_picture_ids_.pop(); |
| 710 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); | 721 TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size()); |
| 711 | 722 |
| 712 OutputBufferMap::const_iterator i = | 723 OutputBufferMap::iterator i = output_picture_buffers_.find(picture_buffer_id); |
| 713 output_picture_buffers_.find(picture_buffer_id); | |
| 714 if (i == output_picture_buffers_.end()) { | 724 if (i == output_picture_buffers_.end()) { |
| 715 POST_ERROR(PLATFORM_FAILURE, | 725 POST_ERROR(PLATFORM_FAILURE, |
| 716 "Can't find PictureBuffer id: " << picture_buffer_id); | 726 "Can't find PictureBuffer id: " << picture_buffer_id); |
| 717 return; | 727 return; |
| 718 } | 728 } |
| 719 | 729 |
| 730 bool size_changed = false; | |
| 731 if (i->second.size() != size_) { | |
| 732 // Size may have changed due to resolution change since the last time this | |
| 733 // PictureBuffer was used. | |
| 734 strategy_->UpdatePictureBufferSize(&i->second, size_); | |
|
liberato (no reviews please)
2016/03/07 16:39:17
an alternate idea is to add a "const gfx::Size*" t
chcunningham
2016/03/08 03:19:36
"then again, you'd have to also send in the Pictur
chcunningham
2016/03/08 22:22:13
We talked over chat - decided not to do this becau
liberato (no reviews please)
2016/03/09 15:32:06
discussed offline. you're right, i misread the si
| |
| 735 size_changed = true; | |
| 736 } | |
| 737 | |
| 720 // Connect the PictureBuffer to the decoded frame, via whatever | 738 // Connect the PictureBuffer to the decoded frame, via whatever |
| 721 // mechanism the strategy likes. | 739 // mechanism the strategy likes. |
| 722 strategy_->UseCodecBufferForPictureBuffer(codec_buffer_index, i->second); | 740 strategy_->UseCodecBufferForPictureBuffer(codec_buffer_index, i->second); |
| 723 | 741 |
| 724 const bool allow_overlay = strategy_->ArePicturesOverlayable(); | 742 const bool allow_overlay = strategy_->ArePicturesOverlayable(); |
| 725 base::MessageLoop::current()->PostTask( | 743 base::MessageLoop::current()->PostTask( |
| 726 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady, | 744 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady, |
| 727 weak_this_factory_.GetWeakPtr(), | 745 weak_this_factory_.GetWeakPtr(), |
| 728 media::Picture(picture_buffer_id, bitstream_id, | 746 media::Picture(picture_buffer_id, bitstream_id, |
| 729 gfx::Rect(size_), allow_overlay))); | 747 gfx::Rect(size_), allow_overlay, |
| 748 size_changed))); | |
| 730 } | 749 } |
| 731 | 750 |
| 732 void AndroidVideoDecodeAccelerator::Decode( | 751 void AndroidVideoDecodeAccelerator::Decode( |
| 733 const media::BitstreamBuffer& bitstream_buffer) { | 752 const media::BitstreamBuffer& bitstream_buffer) { |
| 734 DCHECK(thread_checker_.CalledOnValidThread()); | 753 DCHECK(thread_checker_.CalledOnValidThread()); |
| 735 | 754 |
| 736 if (bitstream_buffer.id() >= 0 && bitstream_buffer.size() > 0) { | 755 if (bitstream_buffer.id() >= 0 && bitstream_buffer.size() > 0) { |
| 737 DecodeBuffer(bitstream_buffer); | 756 DecodeBuffer(bitstream_buffer); |
| 738 return; | 757 return; |
| 739 } | 758 } |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 994 const base::ThreadChecker& AndroidVideoDecodeAccelerator::ThreadChecker() | 1013 const base::ThreadChecker& AndroidVideoDecodeAccelerator::ThreadChecker() |
| 995 const { | 1014 const { |
| 996 return thread_checker_; | 1015 return thread_checker_; |
| 997 } | 1016 } |
| 998 | 1017 |
| 999 base::WeakPtr<gpu::gles2::GLES2Decoder> | 1018 base::WeakPtr<gpu::gles2::GLES2Decoder> |
| 1000 AndroidVideoDecodeAccelerator::GetGlDecoder() const { | 1019 AndroidVideoDecodeAccelerator::GetGlDecoder() const { |
| 1001 return gl_decoder_; | 1020 return gl_decoder_; |
| 1002 } | 1021 } |
| 1003 | 1022 |
| 1023 gpu::gles2::TextureRef* AndroidVideoDecodeAccelerator::GetTextureForPicture( | |
| 1024 const media::PictureBuffer& picture_buffer) { | |
| 1025 RETURN_NULL_IF_NULL(GetGlDecoder()); | |
| 1026 RETURN_NULL_IF_NULL(GetGlDecoder()->GetContextGroup()); | |
| 1027 gpu::gles2::TextureManager* texture_manager = | |
| 1028 GetGlDecoder()->GetContextGroup()->texture_manager(); | |
| 1029 RETURN_NULL_IF_NULL(texture_manager); | |
| 1030 gpu::gles2::TextureRef* texture_ref = | |
| 1031 texture_manager->GetTexture(picture_buffer.internal_texture_id()); | |
| 1032 RETURN_NULL_IF_NULL(texture_ref); | |
| 1033 | |
| 1034 return texture_ref; | |
| 1035 } | |
| 1036 | |
| 1004 void AndroidVideoDecodeAccelerator::OnFrameAvailable() { | 1037 void AndroidVideoDecodeAccelerator::OnFrameAvailable() { |
| 1005 // Remember: this may be on any thread. | 1038 // Remember: this may be on any thread. |
| 1006 DCHECK(strategy_); | 1039 DCHECK(strategy_); |
| 1007 strategy_->OnFrameAvailable(); | 1040 strategy_->OnFrameAvailable(); |
| 1008 } | 1041 } |
| 1009 | 1042 |
| 1010 void AndroidVideoDecodeAccelerator::PostError( | 1043 void AndroidVideoDecodeAccelerator::PostError( |
| 1011 const ::tracked_objects::Location& from_here, | 1044 const ::tracked_objects::Location& from_here, |
| 1012 media::VideoDecodeAccelerator::Error error) { | 1045 media::VideoDecodeAccelerator::Error error) { |
| 1013 base::MessageLoop::current()->PostDelayedTask( | 1046 base::MessageLoop::current()->PostDelayedTask( |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1148 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: | 1181 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: |
| 1149 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | | 1182 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | |
| 1150 media::VideoDecodeAccelerator::Capabilities:: | 1183 media::VideoDecodeAccelerator::Capabilities:: |
| 1151 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1184 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
| 1152 } | 1185 } |
| 1153 | 1186 |
| 1154 return capabilities; | 1187 return capabilities; |
| 1155 } | 1188 } |
| 1156 | 1189 |
| 1157 } // namespace content | 1190 } // namespace content |
| OLD | NEW |