| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "media/gpu/android/media_codec_video_decoder.h" |
| |
| #include "base/logging.h" |
| #include "media/base/android/media_codec_util.h" |
| #include "media/base/android/sdk_media_codec_bridge.h" |
| #include "media/base/video_codecs.h" |
| #include "media/base/video_decoder_config.h" |
| |
| namespace media { |
| namespace { |
| |
| // Don't use MediaCodec's internal software decoders when we have more secure |
| // and up to date versions in the renderer process. |
| bool IsMediaCodecSoftwareDecodingForbidden(const VideoDecoderConfig& config) { |
| return !config.is_encrypted() && |
| (config.codec() == kCodecVP8 || config.codec() == kCodecVP9); |
| } |
| |
| bool ConfigSupported(const VideoDecoderConfig& config) { |
| // Don't support larger than 4k because it won't perform well on many devices. |
| const auto size = config.coded_size(); |
| if (size.width() > 3840 || size.height() > 2160) |
| return false; |
| |
| // Only use MediaCodec for VP8 or VP9 if it's likely backed by hardware or if |
| // the stream is encrypted. |
| const auto codec = config.codec(); |
| if (IsMediaCodecSoftwareDecodingForbidden(config) && |
| VideoCodecBridge::IsKnownUnaccelerated(codec, MEDIA_CODEC_DECODER)) { |
| DVLOG(1) << "Config not supported: " << GetCodecName(codec) |
| << " is not hardware accelerated"; |
| return false; |
| } |
| |
| switch (codec) { |
| case kCodecVP8: |
| case kCodecVP9: { |
| if ((codec == kCodecVP8 && !MediaCodecUtil::IsVp8DecoderAvailable()) || |
| (codec == kCodecVP9 && !MediaCodecUtil::IsVp9DecoderAvailable())) { |
| return false; |
| } |
| |
| // There's no fallback for encrypted content so we support all sizes. |
| if (config.is_encrypted()) |
| return true; |
| |
| // Below 360p there's little to no power benefit to using MediaCodec over |
| // libvpx so we prefer to use our newer version of libvpx, sandboxed in |
| // the renderer. |
| if (size.width() < 480 || size.height() < 360) |
| return false; |
| |
| return true; |
| } |
| case kCodecH264: |
| return true; |
| #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| case kCodecHEVC: |
| return true; |
| #endif |
| default: |
| return false; |
| } |
| } |
| |
| } // namespace |
| |
| MediaCodecVideoDecoder::MediaCodecVideoDecoder() {} |
| |
| MediaCodecVideoDecoder::~MediaCodecVideoDecoder() {} |
| |
| void MediaCodecVideoDecoder::Initialize(const VideoDecoderConfig& config, |
| bool low_delay, |
| CdmContext* cdm_context, |
| const InitCB& init_cb, |
| const OutputCB& output_cb) { |
| init_cb.Run(ConfigSupported(config)); |
| } |
| |
| void MediaCodecVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
| const DecodeCB& decode_cb) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void MediaCodecVideoDecoder::Reset(const base::Closure& closure) { |
| NOTIMPLEMENTED(); |
| } |
| |
| std::string MediaCodecVideoDecoder::GetDisplayName() const { |
| return "MediaCodecVideoDecoder"; |
| } |
| |
| bool MediaCodecVideoDecoder::NeedsBitstreamConversion() const { |
| return true; |
| } |
| |
| bool MediaCodecVideoDecoder::CanReadWithoutStalling() const { |
| NOTIMPLEMENTED(); |
| return false; |
| } |
| |
| int MediaCodecVideoDecoder::GetMaxDecodeRequests() const { |
| return 4; |
| } |
| |
| } // namespace media |