Chromium Code Reviews| Index: media/gpu/android/media_codec_video_decoder.cc |
| diff --git a/media/gpu/android/media_codec_video_decoder.cc b/media/gpu/android/media_codec_video_decoder.cc |
| index b3ca23e3211cd72a8c74a9d5d9d7986f7fe4b7fe..0c9294f61641dd4eae9f735db7ec3ad21594f91c 100644 |
| --- a/media/gpu/android/media_codec_video_decoder.cc |
| +++ b/media/gpu/android/media_codec_video_decoder.cc |
| @@ -60,28 +60,6 @@ namespace { |
| // NotifyEndOfBitstreamBuffer() before getting output from the bitstream. |
| enum { kMaxBitstreamsNotifiedInAdvance = 32 }; |
| -// MediaCodec is only guaranteed to support baseline, but some devices may |
| -// support others. Advertise support for all H264 profiles and let the |
| -// MediaCodec fail when decoding if it's not actually supported. It's assumed |
| -// that consumers won't have software fallback for H264 on Android anyway. |
| -constexpr VideoCodecProfile kSupportedH264Profiles[] = { |
| - H264PROFILE_BASELINE, |
| - H264PROFILE_MAIN, |
| - H264PROFILE_EXTENDED, |
| - H264PROFILE_HIGH, |
| - H264PROFILE_HIGH10PROFILE, |
| - H264PROFILE_HIGH422PROFILE, |
| - H264PROFILE_HIGH444PREDICTIVEPROFILE, |
| - H264PROFILE_SCALABLEBASELINE, |
| - H264PROFILE_SCALABLEHIGH, |
| - H264PROFILE_STEREOHIGH, |
| - H264PROFILE_MULTIVIEWHIGH}; |
| - |
| -#if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| -constexpr VideoCodecProfile kSupportedHevcProfiles[] = {HEVCPROFILE_MAIN, |
| - HEVCPROFILE_MAIN10}; |
| -#endif |
| - |
| // Because MediaCodec is thread-hostile (must be poked on a single thread) and |
| // has no callback mechanism (b/11990118), we must drive it by polling for |
| // complete frames (and available input buffers, when the codec is fully |
| @@ -114,6 +92,57 @@ bool ShouldDeferSurfaceCreation(int surface_id, VideoCodec codec) { |
| base::SysInfo::IsLowEndDevice()); |
| } |
| +// Don't use MediaCodecs 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) { |
| + const auto codec = config.codec(); |
| + |
| + // Only use MediaCodec for VP8 or VP9 if it's likely backed by hardware or if |
| + // the stream is encrypted. |
| + 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. |
| + auto size = config.coded_size(); |
| + 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 |
| // MCVDManager manages shared resources for a number of MCVD instances. |
| @@ -1191,109 +1220,6 @@ void MediaCodecVideoDecoder::ManageTimer(bool did_work) { |
| g_mcvd_manager.Get().StopTimer(this); |
| } |
| -// static |
| -VideoDecodeAccelerator::Capabilities MediaCodecVideoDecoder::GetCapabilities( |
| - const gpu::GpuPreferences& gpu_preferences) { |
| - Capabilities capabilities; |
| - SupportedProfiles& profiles = capabilities.supported_profiles; |
| - |
| - if (MediaCodecUtil::IsVp8DecoderAvailable()) { |
| - SupportedProfile profile; |
| - profile.profile = VP8PROFILE_ANY; |
| - // Since there is little to no power benefit below 360p, don't advertise |
| - // support for it. Let libvpx decode it, and save a MediaCodec instance. |
| - // Note that we allow it anyway for encrypted content, since we push a |
| - // separate profile for that. |
| - profile.min_resolution.SetSize(480, 360); |
| - profile.max_resolution.SetSize(3840, 2160); |
| - // If we know MediaCodec will just create a software codec, prefer our |
| - // internal software decoder instead. It's more up to date and secured |
| - // within the renderer sandbox. However if the content is encrypted, we |
| - // must use MediaCodec anyways since MediaDrm offers no way to decrypt |
| - // the buffers and let us use our internal software decoders. |
| - profile.encrypted_only = |
| - VideoCodecBridge::IsKnownUnaccelerated(kCodecVP8, MEDIA_CODEC_DECODER); |
| - profiles.push_back(profile); |
| - |
| - // Always allow encrypted content, even at low resolutions. |
| - profile.min_resolution.SetSize(0, 0); |
| - profile.encrypted_only = true; |
| - profiles.push_back(profile); |
| - } |
| - |
| - if (MediaCodecUtil::IsVp9DecoderAvailable()) { |
| - const VideoCodecProfile profile_types[] = { |
| - VP9PROFILE_PROFILE0, VP9PROFILE_PROFILE1, VP9PROFILE_PROFILE2, |
| - VP9PROFILE_PROFILE3, VIDEO_CODEC_PROFILE_UNKNOWN}; |
| - const bool is_known_unaccelerated = |
| - VideoCodecBridge::IsKnownUnaccelerated(kCodecVP9, MEDIA_CODEC_DECODER); |
| - for (int i = 0; profile_types[i] != VIDEO_CODEC_PROFILE_UNKNOWN; i++) { |
| - SupportedProfile profile; |
| - // Limit to 360p, like we do for vp8. See above. |
| - profile.min_resolution.SetSize(480, 360); |
| - profile.max_resolution.SetSize(3840, 2160); |
| - // If we know MediaCodec will just create a software codec, prefer our |
| - // internal software decoder instead. It's more up to date and secured |
| - // within the renderer sandbox. However if the content is encrypted, we |
| - // must use MediaCodec anyways since MediaDrm offers no way to decrypt |
| - // the buffers and let us use our internal software decoders. |
| - profile.encrypted_only = is_known_unaccelerated; |
| - profile.profile = profile_types[i]; |
| - profiles.push_back(profile); |
| - |
| - // Always allow encrypted content. |
| - profile.min_resolution.SetSize(0, 0); |
| - profile.encrypted_only = true; |
| - profiles.push_back(profile); |
| - } |
| - } |
| - |
| - for (const auto& supported_profile : kSupportedH264Profiles) { |
| - SupportedProfile profile; |
| - profile.profile = supported_profile; |
| - profile.min_resolution.SetSize(0, 0); |
| - // Advertise support for 4k and let the MediaCodec fail when decoding if it |
| - // doesn't support the resolution. It's assumed that consumers won't have |
| - // software fallback for H264 on Android anyway. |
| - profile.max_resolution.SetSize(3840, 2160); |
| - profiles.push_back(profile); |
| - } |
| - |
| - capabilities.flags = |
| - VideoDecodeAccelerator::Capabilities::SUPPORTS_DEFERRED_INITIALIZATION; |
|
watk
2016/12/02 22:21:15
This is not needed.
|
| - capabilities.flags |= |
| - VideoDecodeAccelerator::Capabilities::NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE; |
|
watk
2016/12/02 22:21:15
This is done via CanReadWithoutStalling.
|
| - |
| - // If we're using threaded texture mailboxes the COPY_REQUIRED flag must be |
| - // set on the video frames (http://crbug.com/582170), and SurfaceView output |
| - // is disabled (http://crbug.com/582170). |
| - if (gpu_preferences.enable_threaded_texture_mailboxes) { |
| - capabilities.flags |= |
| - VideoDecodeAccelerator::Capabilities::REQUIRES_TEXTURE_COPY; |
|
watk
2016/12/02 22:21:15
This can be set on the VideoFrames directly. Bug t
|
| - } else if (MediaCodecUtil::IsSurfaceViewOutputSupported()) { |
| - capabilities.flags |= |
| - VideoDecodeAccelerator::Capabilities::SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
|
watk
2016/12/02 22:21:15
Bug to add this back http://crbug.com/670871
|
| - } |
| - |
| -#if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| - for (const auto& supported_profile : kSupportedHevcProfiles) { |
| - SupportedProfile profile; |
| - profile.profile = supported_profile; |
| - profile.min_resolution.SetSize(0, 0); |
| - profile.max_resolution.SetSize(3840, 2160); |
| - profiles.push_back(profile); |
| - } |
| -#endif |
| - |
| - return capabilities; |
| -} |
| - |
| -bool MediaCodecVideoDecoder::IsMediaCodecSoftwareDecodingForbidden() const { |
| - // Prevent MediaCodec from using its internal software decoders when we have |
| - // more secure and up to date versions in the renderer process. |
| - return !config_.is_encrypted && (codec_config_->codec_ == kCodecVP8 || |
| - codec_config_->codec_ == kCodecVP9); |
| -} |
| bool MediaCodecVideoDecoder::UpdateSurface() { |
| DCHECK(pending_surface_id_); |