Commit 52c285e3 authored by Dale Curtis's avatar Dale Curtis Committed by Commit Bot

Don't call into MediaCodec from the renderer process for VP9.2.

We'll have to limit support to P+, since it's otherwise quite a
chore to get the correct MediaCodec status in the renderer.

This also does the following:
- Strips media:: prefix from media/base/supported_types.cc
- Adds warnings to MediaCodecUtil around methods which can't be
used from the renderer process.
- Moves opus support checks to MediaCodecUtil where they belong.
- Moves hevc support checks to MimeUtilInternal::PlatformInfo where
they belong. Expands unit test for this. Updates MediaCodecUtil.java
to accommodate this.
- Removes a unreachable statements from IsCodecSupportedOnAndroid.
- Switches MimeUtil to use base::NoDestructor for MimeUtilInternal,
required adding const to a few more methods in MimeUtilInternal.

BUG=980091, 980682
TEST=passes locally now.
R=chcunningham

Change-Id: Ib59dce569a5198754e8f5a0df7ee28241f76a5fc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1694241
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: default avatarChrome Cunningham <chcunningham@chromium.org>
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#677034}
parent 601c8433
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
#include "base/android/build_info.h" #include "base/android/build_info.h"
#include "media/base/android/media_codec_util.h"
#endif #endif
#if defined(OS_WIN) #if defined(OS_WIN)
...@@ -227,7 +228,7 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM) { ...@@ -227,7 +228,7 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM) {
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM_Opus) { IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM_Opus) {
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
if (!media::PlatformHasOpusSupport()) if (!media::MediaCodecUtil::IsOpusDecoderAvailable())
return; return;
#endif #endif
TestSimplePlayback("bear-320x240-opus-a_enc-a.webm"); TestSimplePlayback("bear-320x240-opus-a_enc-a.webm");
...@@ -235,7 +236,7 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM_Opus) { ...@@ -235,7 +236,7 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM_Opus) {
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoAudio_WebM_Opus) { IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoAudio_WebM_Opus) {
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
if (!media::PlatformHasOpusSupport()) if (!media::MediaCodecUtil::IsOpusDecoderAvailable())
return; return;
#endif #endif
TestSimplePlayback("bear-320x240-opus-av_enc-av.webm"); TestSimplePlayback("bear-320x240-opus-av_enc-av.webm");
...@@ -243,7 +244,7 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoAudio_WebM_Opus) { ...@@ -243,7 +244,7 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoAudio_WebM_Opus) {
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM_Opus) { IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM_Opus) {
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
if (!media::PlatformHasOpusSupport()) if (!media::MediaCodecUtil::IsOpusDecoderAvailable())
return; return;
#endif #endif
TestSimplePlayback("bear-320x240-opus-av_enc-v.webm"); TestSimplePlayback("bear-320x240-opus-av_enc-v.webm");
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
#include "content/public/test/content_browser_test_utils.h" #include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h" #include "content/shell/browser/shell.h"
#include "media/base/media_switches.h" #include "media/base/media_switches.h"
#include "media/base/supported_types.h"
#include "media/base/video_codecs.h"
#include "media/media_buildflags.h" #include "media/media_buildflags.h"
#include "ui/display/display_switches.h" #include "ui/display/display_switches.h"
...@@ -1539,15 +1537,20 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mpeg2TsAudio) { ...@@ -1539,15 +1537,20 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mpeg2TsAudio) {
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_NewVp9Variants) { IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_NewVp9Variants) {
const std::string kSupportedMimeTypes[] = {"video/webm", "video/mp4"}; const std::string kSupportedMimeTypes[] = {"video/webm", "video/mp4"};
for (const auto& mime_type : kSupportedMimeTypes) { for (const auto& mime_type : kSupportedMimeTypes) {
// Profile 2 and 3 support isn't always available. // Profile 2 and 3 support is currently disabled on ARM and MIPS.
const char* kVP9Profile2 = #if defined(ARCH_CPU_ARM_FAMILY) || defined(ARCH_CPU_MIPS_FAMILY)
media::IsVp9ProfileSupportedForTesting(media::VP9PROFILE_PROFILE2) #if defined(OS_ANDROID)
? kProbably const char* kVP9Profile2And3Probably =
: kNot; base::android::BuildInfo::GetInstance()->sdk_int() >=
const char* kVP9Profile3 = base::android::SDK_VERSION_P
media::IsVp9ProfileSupportedForTesting(media::VP9PROFILE_PROFILE3)
? kProbably ? kProbably
: kNot; : kNot;
#else
const char* kVP9Profile2And3Probably = kNot;
#endif
#else
const char* kVP9Profile2And3Probably = kProbably;
#endif
// E.g. "'video/webm; " // E.g. "'video/webm; "
std::string prefix = "'" + mime_type + "; "; std::string prefix = "'" + mime_type + "; ";
...@@ -1565,8 +1568,10 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_NewVp9Variants) { ...@@ -1565,8 +1568,10 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_NewVp9Variants) {
// Profiles 0 and 1 are always supported supported. Profiles 2 and 3 are // Profiles 0 and 1 are always supported supported. Profiles 2 and 3 are
// only supported on certain architectures. // only supported on certain architectures.
EXPECT_EQ(kProbably, CanPlay(prefix + "codecs=\"vp09.01.10.08\"'")); EXPECT_EQ(kProbably, CanPlay(prefix + "codecs=\"vp09.01.10.08\"'"));
EXPECT_EQ(kVP9Profile2, CanPlay(prefix + "codecs=\"vp09.02.10.08\"'")); EXPECT_EQ(kVP9Profile2And3Probably,
EXPECT_EQ(kVP9Profile3, CanPlay(prefix + "codecs=\"vp09.03.10.08\"'")); CanPlay(prefix + "codecs=\"vp09.02.10.08\"'"));
EXPECT_EQ(kVP9Profile2And3Probably,
CanPlay(prefix + "codecs=\"vp09.03.10.08\"'"));
} }
} }
......
...@@ -54,9 +54,11 @@ class MediaCodecUtil { ...@@ -54,9 +54,11 @@ class MediaCodecUtil {
public static final String VIDEO_MP4 = "video/mp4"; public static final String VIDEO_MP4 = "video/mp4";
public static final String VIDEO_WEBM = "video/webm"; public static final String VIDEO_WEBM = "video/webm";
public static final String VIDEO_H264 = "video/avc"; public static final String VIDEO_H264 = "video/avc";
public static final String VIDEO_H265 = "video/hevc"; public static final String VIDEO_HEVC = "video/hevc";
public static final String VIDEO_VP8 = "video/x-vnd.on2.vp8"; public static final String VIDEO_VP8 = "video/x-vnd.on2.vp8";
public static final String VIDEO_VP9 = "video/x-vnd.on2.vp9"; public static final String VIDEO_VP9 = "video/x-vnd.on2.vp9";
public static final String VIDEO_AV1 = "video/av01";
public static final String AUDIO_OPUS = "audio/opus";
} }
/** /**
...@@ -351,6 +353,10 @@ class MediaCodecUtil { ...@@ -351,6 +353,10 @@ class MediaCodecUtil {
/** /**
* This is a way to blacklist misbehaving devices. * This is a way to blacklist misbehaving devices.
* Some devices cannot decode certain codecs, while other codecs work fine. * Some devices cannot decode certain codecs, while other codecs work fine.
*
* Do not access MediaCodec or MediaCodecList in this function since it's
* used from the renderer process.
*
* @param mime MIME type as passed to mediaCodec.createDecoderByType(mime). * @param mime MIME type as passed to mediaCodec.createDecoderByType(mime).
* @return true if this codec is supported for decoder on this device. * @return true if this codec is supported for decoder on this device.
*/ */
...@@ -359,7 +365,7 @@ class MediaCodecUtil { ...@@ -359,7 +365,7 @@ class MediaCodecUtil {
// ************************************************************* // *************************************************************
// *** DO NOT ADD ANY NEW CODECS WITHOUT UPDATING MIME_UTIL. *** // *** DO NOT ADD ANY NEW CODECS WITHOUT UPDATING MIME_UTIL. ***
// ************************************************************* // *************************************************************
if (mime.equals("video/x-vnd.on2.vp8")) { if (mime.equals(MimeTypes.VIDEO_VP8)) {
if (Build.MANUFACTURER.toLowerCase(Locale.getDefault()).equals("samsung")) { if (Build.MANUFACTURER.toLowerCase(Locale.getDefault()).equals("samsung")) {
// Some Samsung devices cannot render VP8 video directly to the surface. // Some Samsung devices cannot render VP8 video directly to the surface.
...@@ -408,7 +414,7 @@ class MediaCodecUtil { ...@@ -408,7 +414,7 @@ class MediaCodecUtil {
&& Build.MODEL.startsWith("Lenovo A6000")) { && Build.MODEL.startsWith("Lenovo A6000")) {
return false; return false;
} }
} else if (mime.equals("video/x-vnd.on2.vp9")) { } else if (mime.equals(MimeTypes.VIDEO_VP9)) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return false; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return false;
// MediaTek decoders do not work properly on vp9 before Lollipop. See // MediaTek decoders do not work properly on vp9 before Lollipop. See
...@@ -422,9 +428,12 @@ class MediaCodecUtil { ...@@ -422,9 +428,12 @@ class MediaCodecUtil {
if (Build.MODEL.equals("Nexus Player")) { if (Build.MODEL.equals("Nexus Player")) {
return false; return false;
} }
} else if (mime.equals("video/av01")) { } else if (mime.equals(MimeTypes.VIDEO_AV1)) {
if (!BuildInfo.isAtLeastQ()) return false; if (!BuildInfo.isAtLeastQ()) return false;
} else if (mime.equals("audio/opus") } else if (mime.equals(MimeTypes.AUDIO_OPUS)
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return false;
} else if (mime.equals(MimeTypes.VIDEO_HEVC)
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return false; return false;
} }
......
...@@ -102,7 +102,7 @@ class MediaFormatBuilder { ...@@ -102,7 +102,7 @@ class MediaFormatBuilder {
maxPixels = maxWidth * maxHeight; maxPixels = maxWidth * maxHeight;
minCompressionRatio = 2; minCompressionRatio = 2;
break; break;
case MimeTypes.VIDEO_H265: case MimeTypes.VIDEO_HEVC:
case MimeTypes.VIDEO_VP9: case MimeTypes.VIDEO_VP9:
maxPixels = maxWidth * maxHeight; maxPixels = maxWidth * maxHeight;
minCompressionRatio = 4; minCompressionRatio = 4;
......
...@@ -98,6 +98,26 @@ static bool IsEncoderSupportedByDevice(const std::string& android_mime_type) { ...@@ -98,6 +98,26 @@ static bool IsEncoderSupportedByDevice(const std::string& android_mime_type) {
return Java_MediaCodecUtil_isEncoderSupportedByDevice(env, j_mime); return Java_MediaCodecUtil_isEncoderSupportedByDevice(env, j_mime);
} }
static bool CanDecodeInternal(const std::string& mime, bool is_secure) {
if (!MediaCodecUtil::IsMediaCodecAvailable())
return false;
if (mime.empty())
return false;
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
return Java_MediaCodecUtil_canDecode(env, j_mime, is_secure);
}
static bool HasVp9Profile23Decoder() {
// Support for VP9.2, VP9.3 was added in Nougat but it requires hardware
// support which we can't check from the renderer process. Since Android P+
// has a software decoder available for VP9.2, VP9.3 content and usage is nil
// on Android, just gate support on P+.
return base::android::BuildInfo::GetInstance()->sdk_int() >=
base::android::SDK_VERSION_P;
}
// static // static
std::string MediaCodecUtil::CodecToAndroidMimeType(AudioCodec codec) { std::string MediaCodecUtil::CodecToAndroidMimeType(AudioCodec codec) {
if (IsPassthroughAudioFormat(codec)) if (IsPassthroughAudioFormat(codec))
...@@ -218,83 +238,6 @@ std::set<int> MediaCodecUtil::GetEncoderColorFormats( ...@@ -218,83 +238,6 @@ std::set<int> MediaCodecUtil::GetEncoderColorFormats(
return color_formats; return color_formats;
} }
// static
bool MediaCodecUtil::CanDecode(VideoCodec codec, bool is_secure) {
return CanDecodeInternal(CodecToAndroidMimeType(codec), is_secure);
}
// static
bool MediaCodecUtil::CanDecode(AudioCodec codec) {
return CanDecodeInternal(CodecToAndroidMimeType(codec), false);
}
// static
bool MediaCodecUtil::CanDecodeInternal(const std::string& mime,
bool is_secure) {
if (!IsMediaCodecAvailable())
return false;
if (mime.empty())
return false;
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime);
return Java_MediaCodecUtil_canDecode(env, j_mime, is_secure);
}
// static
bool MediaCodecUtil::AddSupportedCodecProfileLevels(
std::vector<CodecProfileLevel>* result) {
DCHECK(result);
if (!IsMediaCodecAvailable())
return false;
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobjectArray> j_codec_profile_levels(
Java_MediaCodecUtil_getSupportedCodecProfileLevels(env));
for (auto java_codec_profile_level :
j_codec_profile_levels.ReadElements<jobject>()) {
result->push_back(MediaCodecProfileLevelToChromiumProfileLevel(
env, java_codec_profile_level));
}
return true;
}
// static
bool MediaCodecUtil::IsKnownUnaccelerated(VideoCodec codec,
MediaCodecDirection direction) {
if (!IsMediaCodecAvailable())
return true;
std::string codec_name =
GetDefaultCodecName(CodecToAndroidMimeType(codec), direction, false);
DVLOG(1) << __func__ << "Default codec for " << GetCodecName(codec) << " : "
<< codec_name << ", direction: " << static_cast<int>(direction);
if (codec_name.empty())
return true;
// MediaTek hardware vp8 is known slower than the software implementation.
// MediaTek hardware vp9 is known crashy, see http://crbug.com/446974 and
// http://crbug.com/597836.
if (base::StartsWith(codec_name, "OMX.MTK.", base::CompareCase::SENSITIVE)) {
if (codec == kCodecVP8)
return true;
if (codec == kCodecVP9)
return base::android::BuildInfo::GetInstance()->sdk_int() <
SDK_VERSION_LOLLIPOP;
return false;
}
// It would be nice if MediaCodecInfo externalized some notion of
// HW-acceleration but it doesn't. Android Media guidance is that the
// "OMX.google" prefix is always used for SW decoders, so that's what we
// use. "OMX.SEC.*" codec is Samsung software implementation - report it
// as unaccelerated as well.
return base::StartsWith(codec_name, "OMX.google.",
base::CompareCase::SENSITIVE) ||
base::StartsWith(codec_name, "OMX.SEC.", base::CompareCase::SENSITIVE);
}
// static // static
bool MediaCodecUtil::IsHLSPath(const GURL& url) { bool MediaCodecUtil::IsHLSPath(const GURL& url) {
return (url.SchemeIsHTTPOrHTTPS() || url.SchemeIsFile()) && return (url.SchemeIsHTTPOrHTTPS() || url.SchemeIsFile()) &&
...@@ -325,11 +268,33 @@ bool MediaCodecUtil::IsVp9DecoderAvailable() { ...@@ -325,11 +268,33 @@ bool MediaCodecUtil::IsVp9DecoderAvailable() {
return IsMediaCodecAvailable() && IsDecoderSupportedByDevice(kVp9MimeType); return IsMediaCodecAvailable() && IsDecoderSupportedByDevice(kVp9MimeType);
} }
// static
bool MediaCodecUtil::IsVp9Profile2DecoderAvailable() {
return IsVp9DecoderAvailable() && HasVp9Profile23Decoder();
}
// static
bool MediaCodecUtil::IsVp9Profile3DecoderAvailable() {
return IsVp9DecoderAvailable() && HasVp9Profile23Decoder();
}
// static
bool MediaCodecUtil::IsOpusDecoderAvailable() {
return IsMediaCodecAvailable() && IsDecoderSupportedByDevice(kOpusMimeType);
}
// static // static
bool MediaCodecUtil::IsAv1DecoderAvailable() { bool MediaCodecUtil::IsAv1DecoderAvailable() {
return IsMediaCodecAvailable() && IsDecoderSupportedByDevice(kAv1MimeType); return IsMediaCodecAvailable() && IsDecoderSupportedByDevice(kAv1MimeType);
} }
#if BUILDFLAG(ENABLE_HEVC_DEMUXING)
// static
bool MediaCodecUtil::IsHEVCDecoderAvailable() {
return IsMediaCodecAvailable() && IsEncoderSupportedByDevice(kHevcMimeType);
}
#endif
// static // static
bool MediaCodecUtil::IsH264EncoderAvailable() { bool MediaCodecUtil::IsH264EncoderAvailable() {
return IsMediaCodecAvailable() && IsEncoderSupportedByDevice(kAvcMimeType); return IsMediaCodecAvailable() && IsEncoderSupportedByDevice(kAvcMimeType);
...@@ -372,6 +337,70 @@ bool MediaCodecUtil::IsPassthroughAudioFormat(AudioCodec codec) { ...@@ -372,6 +337,70 @@ bool MediaCodecUtil::IsPassthroughAudioFormat(AudioCodec codec) {
return codec == kCodecAC3 || codec == kCodecEAC3; return codec == kCodecAC3 || codec == kCodecEAC3;
} }
// static
bool MediaCodecUtil::CanDecode(VideoCodec codec, bool is_secure) {
return CanDecodeInternal(CodecToAndroidMimeType(codec), is_secure);
}
// static
bool MediaCodecUtil::CanDecode(AudioCodec codec) {
return CanDecodeInternal(CodecToAndroidMimeType(codec), false);
}
// static
bool MediaCodecUtil::AddSupportedCodecProfileLevels(
std::vector<CodecProfileLevel>* result) {
DCHECK(result);
if (!IsMediaCodecAvailable())
return false;
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobjectArray> j_codec_profile_levels(
Java_MediaCodecUtil_getSupportedCodecProfileLevels(env));
for (auto java_codec_profile_level :
j_codec_profile_levels.ReadElements<jobject>()) {
result->push_back(MediaCodecProfileLevelToChromiumProfileLevel(
env, java_codec_profile_level));
}
return true;
}
// static
bool MediaCodecUtil::IsKnownUnaccelerated(VideoCodec codec,
MediaCodecDirection direction) {
if (!IsMediaCodecAvailable())
return true;
std::string codec_name =
GetDefaultCodecName(CodecToAndroidMimeType(codec), direction, false);
DVLOG(1) << __func__ << "Default codec for " << GetCodecName(codec) << " : "
<< codec_name << ", direction: " << static_cast<int>(direction);
if (codec_name.empty())
return true;
// MediaTek hardware vp8 is known slower than the software implementation.
// MediaTek hardware vp9 is known crashy, see http://crbug.com/446974 and
// http://crbug.com/597836.
if (base::StartsWith(codec_name, "OMX.MTK.", base::CompareCase::SENSITIVE)) {
if (codec == kCodecVP8)
return true;
if (codec == kCodecVP9)
return base::android::BuildInfo::GetInstance()->sdk_int() <
SDK_VERSION_LOLLIPOP;
return false;
}
// It would be nice if MediaCodecInfo externalized some notion of
// HW-acceleration but it doesn't. Android Media guidance is that the
// "OMX.google" prefix is always used for SW decoders, so that's what we
// use. "OMX.SEC.*" codec is Samsung software implementation - report it
// as unaccelerated as well.
return base::StartsWith(codec_name, "OMX.google.",
base::CompareCase::SENSITIVE) ||
base::StartsWith(codec_name, "OMX.SEC.", base::CompareCase::SENSITIVE);
}
// static // static
bool MediaCodecUtil::CodecNeedsFlushWorkaround(MediaCodecBridge* codec) { bool MediaCodecUtil::CodecNeedsFlushWorkaround(MediaCodecBridge* codec) {
const auto& codec_name = codec->GetName(); const auto& codec_name = codec->GetName();
......
...@@ -23,6 +23,11 @@ namespace media { ...@@ -23,6 +23,11 @@ namespace media {
class MediaCodecBridge; class MediaCodecBridge;
// WARNING: Not all methods on this class can be used in the renderer process,
// only those which do not attempt to use MediaCodec or MediaCodecList.
//
// TODO(dalecurtis): We should move out all methods which can't be used in the
// renderer into a media/gpu helper class.
class MEDIA_EXPORT MediaCodecUtil { class MEDIA_EXPORT MediaCodecUtil {
public: public:
static std::string CodecToAndroidMimeType(AudioCodec codec); static std::string CodecToAndroidMimeType(AudioCodec codec);
...@@ -46,25 +51,6 @@ class MEDIA_EXPORT MediaCodecUtil { ...@@ -46,25 +51,6 @@ class MEDIA_EXPORT MediaCodecUtil {
// Returns true if MediaCodec supports CBCS Encryption. // Returns true if MediaCodec supports CBCS Encryption.
static bool PlatformSupportsCbcsEncryption(int sdk); static bool PlatformSupportsCbcsEncryption(int sdk);
// Returns whether it's possible to create a MediaCodec for the given codec
// and secureness.
static bool CanDecode(VideoCodec codec, bool is_secure);
static bool CanDecode(AudioCodec codec);
// Returns a vector of supported codecs profiles and levels.
static bool AddSupportedCodecProfileLevels(
std::vector<CodecProfileLevel>* out);
// Get a list of encoder supported color formats for |mime_type|.
// The mapping of color format name and its value refers to
// MediaCodecInfo.CodecCapabilities.
static std::set<int> GetEncoderColorFormats(const std::string& mime_type);
// Returns true if |mime_type| is known to be unaccelerated (i.e. backed by a
// software codec instead of a hardware one).
static bool IsKnownUnaccelerated(VideoCodec codec,
MediaCodecDirection direction);
// Test whether a URL contains "m3u8". // Test whether a URL contains "m3u8".
static bool IsHLSURL(const GURL& url); static bool IsHLSURL(const GURL& url);
...@@ -77,10 +63,20 @@ class MEDIA_EXPORT MediaCodecUtil { ...@@ -77,10 +63,20 @@ class MEDIA_EXPORT MediaCodecUtil {
// Indicates if the vp9 decoder is available on this device. // Indicates if the vp9 decoder is available on this device.
static bool IsVp9DecoderAvailable(); static bool IsVp9DecoderAvailable();
static bool IsVp9Profile2DecoderAvailable();
static bool IsVp9Profile3DecoderAvailable();
// Indicates if the Opus decoder is available on this device.
static bool IsOpusDecoderAvailable();
// Indicates if the av1 decoder is available on this device. // Indicates if the av1 decoder is available on this device.
static bool IsAv1DecoderAvailable(); static bool IsAv1DecoderAvailable();
#if BUILDFLAG(ENABLE_HEVC_DEMUXING)
// Indicates if the h265 decoder is available on this device.
static bool IsHEVCDecoderAvailable();
#endif
// Indicates if the h264 encoder is available on this device. // Indicates if the h264 encoder is available on this device.
static bool IsH264EncoderAvailable(); static bool IsH264EncoderAvailable();
...@@ -94,14 +90,51 @@ class MEDIA_EXPORT MediaCodecUtil { ...@@ -94,14 +90,51 @@ class MEDIA_EXPORT MediaCodecUtil {
// pipelines without decompression. // pipelines without decompression.
static bool IsPassthroughAudioFormat(AudioCodec codec); static bool IsPassthroughAudioFormat(AudioCodec codec);
//
// ***************************************************************
// *** THE FOLLOWING METHODS CAN'T BE CALLED FROM THE RENDERER ***
// ***************************************************************
//
// Returns whether it's possible to create a MediaCodec for the given codec
// and secureness.
//
// WARNING: This can't be used from the renderer process since it attempts to
// create a MediaCodec (which requires permissions) to get the codec name.
static bool CanDecode(VideoCodec codec, bool is_secure);
static bool CanDecode(AudioCodec codec);
// Returns a vector of supported codecs profiles and levels.
//
// WARNING: This can't be used from the renderer process since it attempts to
// access MediaCodecList (which requires permissions).
static bool AddSupportedCodecProfileLevels(
std::vector<CodecProfileLevel>* out);
// Get a list of encoder supported color formats for |mime_type|.
// The mapping of color format name and its value refers to
// MediaCodecInfo.CodecCapabilities.
//
// WARNING: This can't be used from the renderer process since it attempts to
// access MediaCodecList (which requires permissions).
static std::set<int> GetEncoderColorFormats(const std::string& mime_type);
// Returns true if |mime_type| is known to be unaccelerated (i.e. backed by a
// software codec instead of a hardware one).
//
// WARNING: This can't be used from the renderer process since it attempts to
// create a MediaCodec (which requires permissions) to get the codec name.
static bool IsKnownUnaccelerated(VideoCodec codec,
MediaCodecDirection direction);
// Indicates if the decoder is known to fail when flushed. (b/8125974, // Indicates if the decoder is known to fail when flushed. (b/8125974,
// b/8347958) // b/8347958)
// When true, the client should work around the issue by releasing the // When true, the client should work around the issue by releasing the
// decoder and instantiating a new one rather than flushing the current one. // decoder and instantiating a new one rather than flushing the current one.
//
// WARNING: This can't be used from the renderer process since it attempts to
// create a MediaCodec (which requires permissions) to get the codec name.
static bool CodecNeedsFlushWorkaround(MediaCodecBridge* codec); static bool CodecNeedsFlushWorkaround(MediaCodecBridge* codec);
private:
static bool CanDecodeInternal(const std::string& mime, bool is_secure);
}; };
} // namespace media } // namespace media
......
...@@ -13,10 +13,6 @@ ...@@ -13,10 +13,6 @@
#include "media/media_buildflags.h" #include "media/media_buildflags.h"
#include "third_party/libyuv/include/libyuv.h" #include "third_party/libyuv/include/libyuv.h"
#if defined(OS_ANDROID)
#include "base/android/build_info.h"
#endif
#if BUILDFLAG(ENABLE_FFMPEG) #if BUILDFLAG(ENABLE_FFMPEG)
#include "third_party/ffmpeg/ffmpeg_features.h" // nogncheck #include "third_party/ffmpeg/ffmpeg_features.h" // nogncheck
extern "C" { extern "C" {
...@@ -99,11 +95,6 @@ void EnablePlatformDecoderSupport() { ...@@ -99,11 +95,6 @@ void EnablePlatformDecoderSupport() {
bool HasPlatformDecoderSupport() { bool HasPlatformDecoderSupport() {
return GetMediaInstance()->has_platform_decoder_support(); return GetMediaInstance()->has_platform_decoder_support();
} }
bool PlatformHasOpusSupport() {
return base::android::BuildInfo::GetInstance()->sdk_int() >=
base::android::SDK_VERSION_LOLLIPOP;
}
#endif // defined(OS_ANDROID) #endif // defined(OS_ANDROID)
} // namespace media } // namespace media
...@@ -34,10 +34,6 @@ MEDIA_EXPORT void InitializeMediaLibraryInSandbox(int64_t libyuv_cpu_flags, ...@@ -34,10 +34,6 @@ MEDIA_EXPORT void InitializeMediaLibraryInSandbox(int64_t libyuv_cpu_flags,
// (e.g. MediaPlayer). // (e.g. MediaPlayer).
MEDIA_EXPORT void EnablePlatformDecoderSupport(); MEDIA_EXPORT void EnablePlatformDecoderSupport();
MEDIA_EXPORT bool HasPlatformDecoderSupport(); MEDIA_EXPORT bool HasPlatformDecoderSupport();
// Indicates if the platform supports Opus. Determined *ONLY* by the platform
// version, so does not guarantee that either can actually be played.
MEDIA_EXPORT bool PlatformHasOpusSupport();
#endif #endif
} // namespace media } // namespace media
......
...@@ -4,14 +4,15 @@ ...@@ -4,14 +4,15 @@
#include "media/base/mime_util.h" #include "media/base/mime_util.h"
#include "base/no_destructor.h"
#include "media/base/mime_util_internal.h" #include "media/base/mime_util_internal.h"
namespace media { namespace media {
// This variable is Leaky because it is accessed from WorkerPool threads. // This variable is Leaky because it is accessed from WorkerPool threads.
static internal::MimeUtil* GetMimeUtil() { static const internal::MimeUtil* GetMimeUtil() {
static internal::MimeUtil* mime_util = new internal::MimeUtil(); static const base::NoDestructor<internal::MimeUtil> mime_util;
return mime_util; return &(*mime_util);
} }
bool IsSupportedMediaMimeType(const std::string& mime_type) { bool IsSupportedMediaMimeType(const std::string& mime_type) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "media/base/media.h" #include "media/base/media.h"
#include "media/base/media_client.h"
#include "media/base/media_switches.h" #include "media/base/media_switches.h"
#include "media/base/supported_types.h" #include "media/base/supported_types.h"
#include "media/base/video_codecs.h" #include "media/base/video_codecs.h"
...@@ -123,6 +124,17 @@ static bool IsValidH264Level(uint8_t level_idc) { ...@@ -123,6 +124,17 @@ static bool IsValidH264Level(uint8_t level_idc) {
(level_idc >= 50 && level_idc <= 52)); (level_idc >= 50 && level_idc <= 52));
} }
// Make a default ParsedCodecResult. Values should indicate "unspecified"
// where possible. Color space is an exception where we choose a default value
// because most codec strings will not describe a color space.
static MimeUtil::ParsedCodecResult MakeDefaultParsedCodecResult() {
return {
MimeUtil::INVALID_CODEC, false, VIDEO_CODEC_PROFILE_UNKNOWN, 0,
// We choose 709 as default color space elsewhere, so defaulting to 709
// here as well. See here for context: https://crrev.com/1221903003/
VideoColorSpace::REC709()};
}
MimeUtil::MimeUtil() { MimeUtil::MimeUtil() {
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
// When the unified media pipeline is enabled, we need support for both GPU // When the unified media pipeline is enabled, we need support for both GPU
...@@ -133,7 +145,16 @@ MimeUtil::MimeUtil() { ...@@ -133,7 +145,16 @@ MimeUtil::MimeUtil() {
MediaCodecUtil::IsVp8DecoderAvailable(); MediaCodecUtil::IsVp8DecoderAvailable();
platform_info_.has_platform_vp9_decoder = platform_info_.has_platform_vp9_decoder =
MediaCodecUtil::IsVp9DecoderAvailable(); MediaCodecUtil::IsVp9DecoderAvailable();
platform_info_.supports_opus = PlatformHasOpusSupport(); platform_info_.has_platform_vp9_2_decoder =
MediaCodecUtil::IsVp9Profile2DecoderAvailable();
platform_info_.has_platform_vp9_3_decoder =
MediaCodecUtil::IsVp9Profile3DecoderAvailable();
#if BUILDFLAG(ENABLE_HEVC_DEMUXING)
platform_info_.has_platform_hevc_decoder =
MediaCodecUtil::IsHEVCDecoderAvailable();
#endif
platform_info_.has_platform_opus_decoder =
MediaCodecUtil::IsOpusDecoderAvailable();
#endif #endif
InitializeMimeTypeMaps(); InitializeMimeTypeMaps();
...@@ -393,7 +414,7 @@ bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { ...@@ -393,7 +414,7 @@ bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const {
} }
void MimeUtil::SplitCodecs(const std::string& codecs, void MimeUtil::SplitCodecs(const std::string& codecs,
std::vector<std::string>* codecs_out) { std::vector<std::string>* codecs_out) const {
*codecs_out = *codecs_out =
base::SplitString(base::TrimString(codecs, "\"", base::TRIM_ALL), ",", base::SplitString(base::TrimString(codecs, "\"", base::TRIM_ALL), ",",
base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
...@@ -403,7 +424,7 @@ void MimeUtil::SplitCodecs(const std::string& codecs, ...@@ -403,7 +424,7 @@ void MimeUtil::SplitCodecs(const std::string& codecs,
codecs_out->clear(); codecs_out->clear();
} }
void MimeUtil::StripCodecs(std::vector<std::string>* codecs) { void MimeUtil::StripCodecs(std::vector<std::string>* codecs) const {
// Strip everything past the first '.' // Strip everything past the first '.'
for (auto it = codecs->begin(); it != codecs->end(); ++it) { for (auto it = codecs->begin(); it != codecs->end(); ++it) {
size_t found = it->find_first_of('.'); size_t found = it->find_first_of('.');
...@@ -418,7 +439,7 @@ bool MimeUtil::ParseVideoCodecString(const std::string& mime_type, ...@@ -418,7 +439,7 @@ bool MimeUtil::ParseVideoCodecString(const std::string& mime_type,
VideoCodec* out_codec, VideoCodec* out_codec,
VideoCodecProfile* out_profile, VideoCodecProfile* out_profile,
uint8_t* out_level, uint8_t* out_level,
VideoColorSpace* out_color_space) { VideoColorSpace* out_color_space) const {
DCHECK(out_is_ambiguous); DCHECK(out_is_ambiguous);
DCHECK(out_codec); DCHECK(out_codec);
DCHECK(out_profile); DCHECK(out_profile);
...@@ -457,7 +478,7 @@ bool MimeUtil::ParseVideoCodecString(const std::string& mime_type, ...@@ -457,7 +478,7 @@ bool MimeUtil::ParseVideoCodecString(const std::string& mime_type,
bool MimeUtil::ParseAudioCodecString(const std::string& mime_type, bool MimeUtil::ParseAudioCodecString(const std::string& mime_type,
const std::string& codec_id, const std::string& codec_id,
bool* out_is_ambiguous, bool* out_is_ambiguous,
AudioCodec* out_codec) { AudioCodec* out_codec) const {
DCHECK(out_is_ambiguous); DCHECK(out_is_ambiguous);
DCHECK(out_codec); DCHECK(out_codec);
...@@ -522,6 +543,7 @@ bool MimeUtil::IsCodecSupportedOnAndroid( ...@@ -522,6 +543,7 @@ bool MimeUtil::IsCodecSupportedOnAndroid(
Codec codec, Codec codec,
const std::string& mime_type_lower_case, const std::string& mime_type_lower_case,
bool is_encrypted, bool is_encrypted,
VideoCodecProfile video_profile,
const PlatformInfo& platform_info) { const PlatformInfo& platform_info) {
DVLOG(3) << __func__; DVLOG(3) << __func__;
DCHECK_NE(mime_type_lower_case, ""); DCHECK_NE(mime_type_lower_case, "");
...@@ -576,17 +598,11 @@ bool MimeUtil::IsCodecSupportedOnAndroid( ...@@ -576,17 +598,11 @@ bool MimeUtil::IsCodecSupportedOnAndroid(
return true; return true;
// Otherwise, platform support is required. // Otherwise, platform support is required.
if (!platform_info.supports_opus) { if (!platform_info.has_platform_opus_decoder) {
DVLOG(3) << "Platform does not support opus"; DVLOG(3) << "Platform does not support opus";
return false; return false;
} }
// MediaPlayer does not support Opus in ogg containers.
if (base::EndsWith(mime_type_lower_case, "ogg",
base::CompareCase::SENSITIVE)) {
return false;
}
DCHECK(!is_encrypted || platform_info.has_platform_decoders); DCHECK(!is_encrypted || platform_info.has_platform_decoders);
return true; return true;
...@@ -597,32 +613,15 @@ bool MimeUtil::IsCodecSupportedOnAndroid( ...@@ -597,32 +613,15 @@ bool MimeUtil::IsCodecSupportedOnAndroid(
case HEVC: case HEVC:
#if BUILDFLAG(ENABLE_HEVC_DEMUXING) #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
if (!platform_info.has_platform_decoders) return platform_info.has_platform_decoders &&
return false; platform_info.has_platform_hevc_decoder;
#if defined(OS_ANDROID)
// HEVC/H.265 is supported in Lollipop+ (API Level 21), according to
// http://developer.android.com/reference/android/media/MediaFormat.html
return base::android::BuildInfo::GetInstance()->sdk_int() >=
base::android::SDK_VERSION_LOLLIPOP;
#else
return true;
#endif // defined(OS_ANDROID)
#else #else
return false; return false;
#endif // BUILDFLAG(ENABLE_HEVC_DEMUXING) #endif // BUILDFLAG(ENABLE_HEVC_DEMUXING)
case VP8: case VP8:
// If clear, the unified pipeline can always decode VP8 in software. // If clear, the unified pipeline can always decode VP8 in software.
if (!is_encrypted) return is_encrypted ? platform_info.has_platform_vp8_decoder : true;
return true;
if (is_encrypted)
return platform_info.has_platform_vp8_decoder;
// MediaPlayer can always play VP8. Note: This is incorrect for MSE, but
// MSE does not use this code. http://crbug.com/587303.
return true;
case VP9: { case VP9: {
if (base::CommandLine::ForCurrentProcess()->HasSwitch( if (base::CommandLine::ForCurrentProcess()->HasSwitch(
...@@ -630,19 +629,29 @@ bool MimeUtil::IsCodecSupportedOnAndroid( ...@@ -630,19 +629,29 @@ bool MimeUtil::IsCodecSupportedOnAndroid(
return false; return false;
} }
// If clear, the unified pipeline can always decode VP9 in software. // If clear, the unified pipeline can always decode VP9.0,1 in software.
if (!is_encrypted) // If we don't know the profile, then support is ambiguous, but default to
// true for historical reasons.
if (!is_encrypted && (video_profile == VP9PROFILE_PROFILE0 ||
video_profile == VP9PROFILE_PROFILE1 ||
video_profile == VIDEO_CODEC_PROFILE_UNKNOWN)) {
return true; return true;
}
if (!platform_info.has_platform_vp9_decoder) if (!platform_info.has_platform_vp9_decoder)
return false; return false;
// Encrypted content is demuxed so the container is irrelevant. if (video_profile == VP9PROFILE_PROFILE2 &&
if (is_encrypted) !platform_info.has_platform_vp9_2_decoder) {
return true; return false;
}
if (video_profile == VP9PROFILE_PROFILE3 &&
!platform_info.has_platform_vp9_3_decoder) {
return false;
}
// MediaPlayer only supports VP9 in WebM. return true;
return mime_type_lower_case == "video/webm";
} }
case DOLBY_VISION: case DOLBY_VISION:
...@@ -662,17 +671,6 @@ bool MimeUtil::IsCodecSupportedOnAndroid( ...@@ -662,17 +671,6 @@ bool MimeUtil::IsCodecSupportedOnAndroid(
return false; return false;
} }
// Make a default ParsedCodecResult. Values should indicate "unspecified"
// where possible. Color space is an exception where we choose a default value
// because most codec strings will not describe a color space.
MimeUtil::ParsedCodecResult MakeDefaultParsedCodecResult() {
return {
MimeUtil::INVALID_CODEC, false, VIDEO_CODEC_PROFILE_UNKNOWN, 0,
// We choose 709 as default color space elsewhere, so defaulting to 709
// here as well. See here for context: https://crrev.com/1221903003/
VideoColorSpace::REC709()};
}
bool MimeUtil::ParseCodecStrings( bool MimeUtil::ParseCodecStrings(
const std::string& mime_type_lower_case, const std::string& mime_type_lower_case,
const std::vector<std::string>& codecs, const std::vector<std::string>& codecs,
...@@ -907,15 +905,16 @@ SupportsType MimeUtil::IsCodecSupported(const std::string& mime_type_lower_case, ...@@ -907,15 +905,16 @@ SupportsType MimeUtil::IsCodecSupported(const std::string& mime_type_lower_case,
if (video_codec != kUnknownVideoCodec) { if (video_codec != kUnknownVideoCodec) {
if (!IsSupportedVideoType( if (!IsSupportedVideoType(
{video_codec, video_profile, video_level, color_space})) {video_codec, video_profile, video_level, color_space})) {
return IsNotSupported; return IsNotSupported;
}
} }
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
// TODO(chcunningham): Delete this. Android platform support should be // TODO(chcunningham): Delete this. Android platform support should be
// handled by (android specific) media::IsSupportedVideoType() above. // handled by (android specific) media::IsSupportedVideoType() above.
if (!IsCodecSupportedOnAndroid(codec, mime_type_lower_case, is_encrypted, if (!IsCodecSupportedOnAndroid(codec, mime_type_lower_case, is_encrypted,
platform_info_)) { video_profile, platform_info_)) {
return IsNotSupported; return IsNotSupported;
} }
#endif #endif
......
...@@ -53,10 +53,14 @@ class MEDIA_EXPORT MimeUtil { ...@@ -53,10 +53,14 @@ class MEDIA_EXPORT MimeUtil {
// runtime. Also used by tests to simulate platform differences. // runtime. Also used by tests to simulate platform differences.
struct PlatformInfo { struct PlatformInfo {
bool has_platform_decoders = false; bool has_platform_decoders = false;
bool has_platform_vp8_decoder = false; bool has_platform_vp8_decoder = false;
bool has_platform_vp9_decoder = false; bool has_platform_vp9_decoder = false;
bool supports_opus = false; bool has_platform_vp9_2_decoder = false;
bool has_platform_vp9_3_decoder = false;
#if BUILDFLAG(ENABLE_HEVC_DEMUXING)
bool has_platform_hevc_decoder = false;
#endif
bool has_platform_opus_decoder = false;
}; };
struct ParsedCodecResult { struct ParsedCodecResult {
...@@ -70,19 +74,19 @@ class MEDIA_EXPORT MimeUtil { ...@@ -70,19 +74,19 @@ class MEDIA_EXPORT MimeUtil {
// See mime_util.h for more information on these methods. // See mime_util.h for more information on these methods.
bool IsSupportedMediaMimeType(const std::string& mime_type) const; bool IsSupportedMediaMimeType(const std::string& mime_type) const;
void SplitCodecs(const std::string& codecs, void SplitCodecs(const std::string& codecs,
std::vector<std::string>* codecs_out); std::vector<std::string>* codecs_out) const;
void StripCodecs(std::vector<std::string>* codecs); void StripCodecs(std::vector<std::string>* codecs) const;
bool ParseVideoCodecString(const std::string& mime_type, bool ParseVideoCodecString(const std::string& mime_type,
const std::string& codec_id, const std::string& codec_id,
bool* out_is_ambiguous, bool* out_is_ambiguous,
VideoCodec* out_codec, VideoCodec* out_codec,
VideoCodecProfile* out_profile, VideoCodecProfile* out_profile,
uint8_t* out_level, uint8_t* out_level,
VideoColorSpace* out_color_space); VideoColorSpace* out_color_space) const;
bool ParseAudioCodecString(const std::string& mime_type, bool ParseAudioCodecString(const std::string& mime_type,
const std::string& codec_id, const std::string& codec_id,
bool* out_is_ambiguous, bool* out_is_ambiguous,
AudioCodec* out_codec); AudioCodec* out_codec) const;
SupportsType IsSupportedMediaFormat(const std::string& mime_type, SupportsType IsSupportedMediaFormat(const std::string& mime_type,
const std::vector<std::string>& codecs, const std::vector<std::string>& codecs,
bool is_encrypted) const; bool is_encrypted) const;
...@@ -95,6 +99,7 @@ class MEDIA_EXPORT MimeUtil { ...@@ -95,6 +99,7 @@ class MEDIA_EXPORT MimeUtil {
static bool IsCodecSupportedOnAndroid(Codec codec, static bool IsCodecSupportedOnAndroid(Codec codec,
const std::string& mime_type_lower_case, const std::string& mime_type_lower_case,
bool is_encrypted, bool is_encrypted,
VideoCodecProfile video_profile,
const PlatformInfo& platform_info); const PlatformInfo& platform_info);
private: private:
......
...@@ -77,36 +77,35 @@ static void RunCodecSupportTest(const MimeUtil::PlatformInfo& states_to_vary, ...@@ -77,36 +77,35 @@ static void RunCodecSupportTest(const MimeUtil::PlatformInfo& states_to_vary,
MAKE_TEST_VECTOR(has_platform_decoders); MAKE_TEST_VECTOR(has_platform_decoders);
MAKE_TEST_VECTOR(has_platform_vp8_decoder); MAKE_TEST_VECTOR(has_platform_vp8_decoder);
MAKE_TEST_VECTOR(has_platform_vp9_decoder); MAKE_TEST_VECTOR(has_platform_vp9_decoder);
MAKE_TEST_VECTOR(supports_opus); MAKE_TEST_VECTOR(has_platform_opus_decoder);
#undef MAKE_TEST_VECTOR #undef MAKE_TEST_VECTOR
MimeUtil::PlatformInfo info; MimeUtil::PlatformInfo info;
#define RUN_TEST_VECTOR_BEGIN(name) \ #define RUN_TEST_VECTOR_BEGIN(name) \
for (size_t name##_index = 0; \ for (size_t name##_index = 0; name##_index < name##_states.size(); \
name##_index < name##_states.size(); \ ++name##_index) { \
++name##_index) { \
info.name = name##_states[name##_index]; info.name = name##_states[name##_index];
#define RUN_TEST_VECTOR_END() } #define RUN_TEST_VECTOR_END() }
RUN_TEST_VECTOR_BEGIN(has_platform_decoders) RUN_TEST_VECTOR_BEGIN(has_platform_decoders)
RUN_TEST_VECTOR_BEGIN(has_platform_vp8_decoder) RUN_TEST_VECTOR_BEGIN(has_platform_vp8_decoder)
RUN_TEST_VECTOR_BEGIN(has_platform_vp9_decoder) RUN_TEST_VECTOR_BEGIN(has_platform_vp9_decoder)
RUN_TEST_VECTOR_BEGIN(supports_opus) RUN_TEST_VECTOR_BEGIN(has_platform_opus_decoder)
for (int codec = MimeUtil::INVALID_CODEC; for (int codec = MimeUtil::INVALID_CODEC; codec <= MimeUtil::LAST_CODEC;
codec <= MimeUtil::LAST_CODEC; ++codec) { ++codec) {
SCOPED_TRACE(base::StringPrintf( SCOPED_TRACE(base::StringPrintf(
"has_platform_decoders=%d, has_platform_vp8_decoder=%d, " "has_platform_decoders=%d, has_platform_vp8_decoder=%d, "
"supports_opus=%d, " "has_platform_opus_decoder=%d, "
"has_platform_vp9_decoder=%d, " "has_platform_vp9_decoder=%d, "
"codec=%d", "codec=%d",
info.has_platform_decoders, info.has_platform_vp8_decoder, info.has_platform_decoders, info.has_platform_vp8_decoder,
info.supports_opus, info.has_platform_vp9_decoder, codec)); info.has_platform_opus_decoder, info.has_platform_vp9_decoder, codec));
test_func(info, static_cast<MimeUtil::Codec>(codec)); test_func(info, static_cast<MimeUtil::Codec>(codec));
} }
RUN_TEST_VECTOR_END() RUN_TEST_VECTOR_END()
RUN_TEST_VECTOR_END() RUN_TEST_VECTOR_END()
RUN_TEST_VECTOR_END() RUN_TEST_VECTOR_END()
RUN_TEST_VECTOR_END() RUN_TEST_VECTOR_END()
#undef RUN_TEST_VECTOR_BEGIN #undef RUN_TEST_VECTOR_BEGIN
...@@ -119,24 +118,11 @@ static MimeUtil::PlatformInfo VaryAllFields() { ...@@ -119,24 +118,11 @@ static MimeUtil::PlatformInfo VaryAllFields() {
MimeUtil::PlatformInfo states_to_vary; MimeUtil::PlatformInfo states_to_vary;
states_to_vary.has_platform_vp8_decoder = true; states_to_vary.has_platform_vp8_decoder = true;
states_to_vary.has_platform_vp9_decoder = true; states_to_vary.has_platform_vp9_decoder = true;
states_to_vary.supports_opus = true; states_to_vary.has_platform_opus_decoder = true;
states_to_vary.has_platform_decoders = true; states_to_vary.has_platform_decoders = true;
return states_to_vary; return states_to_vary;
} }
static bool HasHevcSupport() {
#if BUILDFLAG(ENABLE_HEVC_DEMUXING)
#if defined(OS_ANDROID)
return base::android::BuildInfo::GetInstance()->sdk_int() >=
base::android::SDK_VERSION_LOLLIPOP;
#else
return true;
#endif // defined(OS_ANDROID)
#else
return false;
#endif // BUILDFLAG(ENABLE_HEVC_DEMUXING)
}
// This is to validate MimeUtil::IsCodecSupportedOnPlatform(), which is used // This is to validate MimeUtil::IsCodecSupportedOnPlatform(), which is used
// only on Android platform. // only on Android platform.
static bool HasDolbyVisionSupport() { static bool HasDolbyVisionSupport() {
...@@ -421,8 +407,8 @@ TEST(IsCodecSupportedOnAndroidTest, EncryptedCodecsFailWithoutPlatformSupport) { ...@@ -421,8 +407,8 @@ TEST(IsCodecSupportedOnAndroidTest, EncryptedCodecsFailWithoutPlatformSupport) {
RunCodecSupportTest( RunCodecSupportTest(
states_to_vary, test_states, states_to_vary, test_states,
[](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) { [](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) {
EXPECT_FALSE(MimeUtil::IsCodecSupportedOnAndroid(codec, kTestMimeType, EXPECT_FALSE(MimeUtil::IsCodecSupportedOnAndroid(
true, info)); codec, kTestMimeType, true, VIDEO_CODEC_PROFILE_UNKNOWN, info));
}); });
} }
...@@ -439,7 +425,7 @@ TEST(IsCodecSupportedOnAndroidTest, EncryptedCodecBehavior) { ...@@ -439,7 +425,7 @@ TEST(IsCodecSupportedOnAndroidTest, EncryptedCodecBehavior) {
states_to_vary, test_states, states_to_vary, test_states,
[](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) { [](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) {
const bool result = MimeUtil::IsCodecSupportedOnAndroid( const bool result = MimeUtil::IsCodecSupportedOnAndroid(
codec, kTestMimeType, true, info); codec, kTestMimeType, true, VIDEO_CODEC_PROFILE_UNKNOWN, info);
switch (codec) { switch (codec) {
// These codecs are never supported by the Android platform. // These codecs are never supported by the Android platform.
case MimeUtil::INVALID_CODEC: case MimeUtil::INVALID_CODEC:
...@@ -463,7 +449,7 @@ TEST(IsCodecSupportedOnAndroidTest, EncryptedCodecBehavior) { ...@@ -463,7 +449,7 @@ TEST(IsCodecSupportedOnAndroidTest, EncryptedCodecBehavior) {
// The remaining codecs are not available on all platforms even when // The remaining codecs are not available on all platforms even when
// a platform decoder is available. // a platform decoder is available.
case MimeUtil::OPUS: case MimeUtil::OPUS:
EXPECT_EQ(info.supports_opus, result); EXPECT_EQ(info.has_platform_opus_decoder, result);
break; break;
case MimeUtil::VP8: case MimeUtil::VP8:
...@@ -475,7 +461,11 @@ TEST(IsCodecSupportedOnAndroidTest, EncryptedCodecBehavior) { ...@@ -475,7 +461,11 @@ TEST(IsCodecSupportedOnAndroidTest, EncryptedCodecBehavior) {
break; break;
case MimeUtil::HEVC: case MimeUtil::HEVC:
EXPECT_EQ(HasHevcSupport(), result); #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
EXPECT_EQ(info.has_platform_hevc_decoder, result);
#else
EXPECT_FALSE(result);
#endif
break; break;
case MimeUtil::DOLBY_VISION: case MimeUtil::DOLBY_VISION:
...@@ -499,7 +489,7 @@ TEST(IsCodecSupportedOnAndroidTest, ClearCodecBehavior) { ...@@ -499,7 +489,7 @@ TEST(IsCodecSupportedOnAndroidTest, ClearCodecBehavior) {
states_to_vary, test_states, states_to_vary, test_states,
[](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) { [](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) {
const bool result = MimeUtil::IsCodecSupportedOnAndroid( const bool result = MimeUtil::IsCodecSupportedOnAndroid(
codec, kTestMimeType, false, info); codec, kTestMimeType, false, VIDEO_CODEC_PROFILE_UNKNOWN, info);
switch (codec) { switch (codec) {
// These codecs are never supported by the Android platform. // These codecs are never supported by the Android platform.
case MimeUtil::INVALID_CODEC: case MimeUtil::INVALID_CODEC:
...@@ -525,7 +515,13 @@ TEST(IsCodecSupportedOnAndroidTest, ClearCodecBehavior) { ...@@ -525,7 +515,13 @@ TEST(IsCodecSupportedOnAndroidTest, ClearCodecBehavior) {
// These codecs are only supported if platform decoders are supported. // These codecs are only supported if platform decoders are supported.
case MimeUtil::HEVC: case MimeUtil::HEVC:
EXPECT_EQ(HasHevcSupport() && info.has_platform_decoders, result); #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
EXPECT_EQ(
info.has_platform_decoders && info.has_platform_hevc_decoder,
result);
#else
EXPECT_FALSE(result);
#endif
break; break;
case MimeUtil::DOLBY_VISION: case MimeUtil::DOLBY_VISION:
...@@ -549,10 +545,62 @@ TEST(IsCodecSupportedOnAndroidTest, OpusOggSupport) { ...@@ -549,10 +545,62 @@ TEST(IsCodecSupportedOnAndroidTest, OpusOggSupport) {
states_to_vary, test_states, states_to_vary, test_states,
[](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) { [](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) {
EXPECT_TRUE(MimeUtil::IsCodecSupportedOnAndroid( EXPECT_TRUE(MimeUtil::IsCodecSupportedOnAndroid(
MimeUtil::OPUS, "audio/ogg", false, info)); MimeUtil::OPUS, "audio/ogg", false, VIDEO_CODEC_PROFILE_UNKNOWN,
info));
}); });
} }
#if BUILDFLAG(ENABLE_HEVC_DEMUXING)
TEST(IsCodecSupportedOnAndroidTest, HEVCSupport) {
MimeUtil::PlatformInfo info;
info.has_platform_decoders = false;
info.has_platform_hevc_decoder = false;
EXPECT_FALSE(MimeUtil::IsCodecSupportedOnAndroid(
MimeUtil::HEVC, kTestMimeType, false, VIDEO_CODEC_PROFILE_UNKNOWN, info));
info.has_platform_decoders = true;
EXPECT_FALSE(MimeUtil::IsCodecSupportedOnAndroid(
MimeUtil::HEVC, kTestMimeType, false, VIDEO_CODEC_PROFILE_UNKNOWN, info));
info.has_platform_hevc_decoder = true;
EXPECT_TRUE(MimeUtil::IsCodecSupportedOnAndroid(
MimeUtil::HEVC, kTestMimeType, false, VIDEO_CODEC_PROFILE_UNKNOWN, info));
}
#endif
TEST(IsCodecSupportedOnAndroidTest, Vp9Profile23Support) {
MimeUtil::PlatformInfo info;
info.has_platform_decoders = false;
info.has_platform_vp9_decoder = false;
info.has_platform_vp9_2_decoder = false;
info.has_platform_vp9_3_decoder = false;
EXPECT_FALSE(MimeUtil::IsCodecSupportedOnAndroid(
MimeUtil::VP9, kTestMimeType, false, VP9PROFILE_PROFILE2, info));
EXPECT_FALSE(MimeUtil::IsCodecSupportedOnAndroid(
MimeUtil::VP9, kTestMimeType, false, VP9PROFILE_PROFILE3, info));
info.has_platform_decoders = true;
info.has_platform_vp9_decoder = true;
EXPECT_FALSE(MimeUtil::IsCodecSupportedOnAndroid(
MimeUtil::VP9, kTestMimeType, false, VP9PROFILE_PROFILE2, info));
EXPECT_FALSE(MimeUtil::IsCodecSupportedOnAndroid(
MimeUtil::VP9, kTestMimeType, false, VP9PROFILE_PROFILE3, info));
info.has_platform_vp9_2_decoder = true;
EXPECT_TRUE(MimeUtil::IsCodecSupportedOnAndroid(
MimeUtil::VP9, kTestMimeType, false, VP9PROFILE_PROFILE2, info));
EXPECT_FALSE(MimeUtil::IsCodecSupportedOnAndroid(
MimeUtil::VP9, kTestMimeType, false, VP9PROFILE_PROFILE3, info));
info.has_platform_vp9_3_decoder = true;
EXPECT_TRUE(MimeUtil::IsCodecSupportedOnAndroid(
MimeUtil::VP9, kTestMimeType, false, VP9PROFILE_PROFILE2, info));
EXPECT_TRUE(MimeUtil::IsCodecSupportedOnAndroid(
MimeUtil::VP9, kTestMimeType, false, VP9PROFILE_PROFILE3, info));
}
TEST(IsCodecSupportedOnAndroidTest, AndroidHLSAAC) { TEST(IsCodecSupportedOnAndroidTest, AndroidHLSAAC) {
const std::string hls_mime_types[] = {"application/x-mpegurl", const std::string hls_mime_types[] = {"application/x-mpegurl",
"application/vnd.apple.mpegurl", "application/vnd.apple.mpegurl",
......
This diff is collapsed.
...@@ -21,9 +21,6 @@ MEDIA_EXPORT bool IsSupportedVideoType(const VideoType& type); ...@@ -21,9 +21,6 @@ MEDIA_EXPORT bool IsSupportedVideoType(const VideoType& type);
MEDIA_EXPORT bool IsDefaultSupportedAudioType(const AudioType& type); MEDIA_EXPORT bool IsDefaultSupportedAudioType(const AudioType& type);
MEDIA_EXPORT bool IsDefaultSupportedVideoType(const VideoType& type); MEDIA_EXPORT bool IsDefaultSupportedVideoType(const VideoType& type);
// Test helper for navigating the complexities of VP9.2 and VP9.3 support.
MEDIA_EXPORT bool IsVp9ProfileSupportedForTesting(VideoCodecProfile profile);
} // namespace media } // namespace media
#endif // MEDIA_BASE_SUPPORTED_TYPES_H_ #endif // MEDIA_BASE_SUPPORTED_TYPES_H_
...@@ -57,8 +57,8 @@ const char kInvalidContainer[] = "video/invalid"; ...@@ -57,8 +57,8 @@ const char kInvalidContainer[] = "video/invalid";
// that the test can perform EmeMediaType check. // that the test can perform EmeMediaType check.
// TODO(sandersd): Extended codec variants (requires proprietary codec support). // TODO(sandersd): Extended codec variants (requires proprietary codec support).
// TODO(xhwang): Platform Opus is not available on all Android versions, where // TODO(xhwang): Platform Opus is not available on all Android versions, where
// some encrypted Opus related tests may fail. See PlatformHasOpusSupport() // some encrypted Opus related tests may fail. See
// for more details. // MediaCodecUtil::IsOpusDecoderAvailable() for more details.
const char kSupportedAudioCodec[] = "audio_codec"; const char kSupportedAudioCodec[] = "audio_codec";
const char kSupportedVideoCodec[] = "video_codec"; const char kSupportedVideoCodec[] = "video_codec";
const char kUnsupportedCodec[] = "unsupported_codec"; const char kUnsupportedCodec[] = "unsupported_codec";
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment