blob: f3fda162cece590fec1a5f8f2a9cb73178f1a809 [file] [log] [blame]
// 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