From 83a8e1e01dc1659ab48164bfbf790290b5b6b29a Mon Sep 17 00:00:00 2001 From: Zen Xu Date: Thu, 14 Jan 2021 23:56:52 -0800 Subject: [PATCH 1/4] Fix VP9 on Android L and M by advertising profile level --- .../exoplayer2/mediacodec/MediaCodecInfo.java | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java index 1b35fc98879..fad9b46dd6e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java @@ -47,6 +47,7 @@ import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; +import java.util.ArrayList; /** Information about a {@link MediaCodec} for a given mime type. */ @SuppressWarnings("InlinedApi") @@ -298,7 +299,15 @@ public boolean isCodecSupported(Format format) { // which may not be widely supported. See https://github.com/google/ExoPlayer/issues/5145. return true; } - for (CodecProfileLevel capabilities : getProfileLevels()) { + + final CodecProfileLevel[] codecProfileLevels; + if (MimeTypes.VIDEO_VP9.equals(mimeType) && Util.SDK_INT <= 23 && capabilities != null) { + codecProfileLevels = getVp9CodecProfileLevelsV23(capabilities); + } else { + codecProfileLevels = getProfileLevels(); + } + + for (CodecProfileLevel capabilities : codecProfileLevels) { if (capabilities.profile == profile && capabilities.level >= level) { return true; } @@ -572,6 +581,41 @@ public boolean isAudioChannelCountSupportedV21(int channelCount) { return true; } + /** + * On versions L and M, VP9 codecCapabilities do not advertise profile level + * support. In this case, estimate the level from MediaCodecInfo.VideoCapabilities + * instead. Assume VP9 is not supported before L. For more information, consult + * https://developer.android.com/reference/android/media/MediaCodecInfo.CodecProfileLevel.html + */ + private static CodecProfileLevel[] getVp9CodecProfileLevelsV23(CodecCapabilities capabilities) { + // https://www.webmproject.org/vp9/levels + final int[][] bitrateMapping = { + {200, 10}, {800, 11}, {1800, 20}, {3600, 21}, {7200, 30}, {12000, 31}, {18000, 40}, + {30000, 41}, {60000, 50}, {120000, 51}, {180000, 52}, + }; + + VideoCapabilities videoCapabilities = capabilities.getVideoCapabilities(); + + if (videoCapabilities == null) { + return new CodecProfileLevel[0]; + } + + ArrayList profileLevelList = new ArrayList<>(); + for (int[] entry : bitrateMapping) { + int bitrate = entry[0]; + int level = entry[1]; + if (videoCapabilities.getBitrateRange().contains(bitrate)) { + CodecProfileLevel profileLevel = new CodecProfileLevel(); + // Assume all platforms before N only support VP9 profile 0. + profileLevel.profile = CodecProfileLevel.VP9Profile0; + profileLevel.level = level; + profileLevelList.add(profileLevel); + } + } + + return profileLevelList.toArray(new CodecProfileLevel[profileLevelList.size()]); + } + private void logNoSupport(String message) { Log.d(TAG, "NoSupport [" + message + "] [" + name + ", " + mimeType + "] [" + Util.DEVICE_DEBUG_INFO + "]"); From 3854a97062e8bd1c3d5778a21f254d654c6a836e Mon Sep 17 00:00:00 2001 From: Zen Xu Date: Thu, 14 Jan 2021 23:56:52 -0800 Subject: [PATCH 2/4] Fix VP9 on Android L and M by advertising profile level --- .../exoplayer2/mediacodec/MediaCodecInfo.java | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java index 1b35fc98879..fad9b46dd6e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java @@ -47,6 +47,7 @@ import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; +import java.util.ArrayList; /** Information about a {@link MediaCodec} for a given mime type. */ @SuppressWarnings("InlinedApi") @@ -298,7 +299,15 @@ public boolean isCodecSupported(Format format) { // which may not be widely supported. See https://github.com/google/ExoPlayer/issues/5145. return true; } - for (CodecProfileLevel capabilities : getProfileLevels()) { + + final CodecProfileLevel[] codecProfileLevels; + if (MimeTypes.VIDEO_VP9.equals(mimeType) && Util.SDK_INT <= 23 && capabilities != null) { + codecProfileLevels = getVp9CodecProfileLevelsV23(capabilities); + } else { + codecProfileLevels = getProfileLevels(); + } + + for (CodecProfileLevel capabilities : codecProfileLevels) { if (capabilities.profile == profile && capabilities.level >= level) { return true; } @@ -572,6 +581,41 @@ public boolean isAudioChannelCountSupportedV21(int channelCount) { return true; } + /** + * On versions L and M, VP9 codecCapabilities do not advertise profile level + * support. In this case, estimate the level from MediaCodecInfo.VideoCapabilities + * instead. Assume VP9 is not supported before L. For more information, consult + * https://developer.android.com/reference/android/media/MediaCodecInfo.CodecProfileLevel.html + */ + private static CodecProfileLevel[] getVp9CodecProfileLevelsV23(CodecCapabilities capabilities) { + // https://www.webmproject.org/vp9/levels + final int[][] bitrateMapping = { + {200, 10}, {800, 11}, {1800, 20}, {3600, 21}, {7200, 30}, {12000, 31}, {18000, 40}, + {30000, 41}, {60000, 50}, {120000, 51}, {180000, 52}, + }; + + VideoCapabilities videoCapabilities = capabilities.getVideoCapabilities(); + + if (videoCapabilities == null) { + return new CodecProfileLevel[0]; + } + + ArrayList profileLevelList = new ArrayList<>(); + for (int[] entry : bitrateMapping) { + int bitrate = entry[0]; + int level = entry[1]; + if (videoCapabilities.getBitrateRange().contains(bitrate)) { + CodecProfileLevel profileLevel = new CodecProfileLevel(); + // Assume all platforms before N only support VP9 profile 0. + profileLevel.profile = CodecProfileLevel.VP9Profile0; + profileLevel.level = level; + profileLevelList.add(profileLevel); + } + } + + return profileLevelList.toArray(new CodecProfileLevel[profileLevelList.size()]); + } + private void logNoSupport(String message) { Log.d(TAG, "NoSupport [" + message + "] [" + name + ", " + mimeType + "] [" + Util.DEVICE_DEBUG_INFO + "]"); From 24db0859c3ff553f26440d21c0e66d2694e639b5 Mon Sep 17 00:00:00 2001 From: Zen Xu Date: Mon, 18 Jan 2021 01:24:24 -0800 Subject: [PATCH 3/4] fix level const etc --- .../exoplayer2/mediacodec/MediaCodecInfo.java | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java index fad9b46dd6e..e0ad25a4adc 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java @@ -300,11 +300,12 @@ public boolean isCodecSupported(Format format) { return true; } - final CodecProfileLevel[] codecProfileLevels; - if (MimeTypes.VIDEO_VP9.equals(mimeType) && Util.SDK_INT <= 23 && capabilities != null) { + CodecProfileLevel[] codecProfileLevels = getProfileLevels(); + if (MimeTypes.VIDEO_VP9.equals(mimeType) && + Util.SDK_INT <= 23 && + codecProfileLevels.length == 0 && + capabilities != null) { codecProfileLevels = getVp9CodecProfileLevelsV23(capabilities); - } else { - codecProfileLevels = getProfileLevels(); } for (CodecProfileLevel capabilities : codecProfileLevels) { @@ -582,16 +583,25 @@ public boolean isAudioChannelCountSupportedV21(int channelCount) { } /** - * On versions L and M, VP9 codecCapabilities do not advertise profile level + * On versions M and below, VP9 codecCapabilities do not advertise profile level * support. In this case, estimate the level from MediaCodecInfo.VideoCapabilities - * instead. Assume VP9 is not supported before L. For more information, consult + * instead. For more information, consult * https://developer.android.com/reference/android/media/MediaCodecInfo.CodecProfileLevel.html */ private static CodecProfileLevel[] getVp9CodecProfileLevelsV23(CodecCapabilities capabilities) { // https://www.webmproject.org/vp9/levels final int[][] bitrateMapping = { - {200, 10}, {800, 11}, {1800, 20}, {3600, 21}, {7200, 30}, {12000, 31}, {18000, 40}, - {30000, 41}, {60000, 50}, {120000, 51}, {180000, 52}, + {180000, CodecProfileLevel.VP9Level52}, + {120000, CodecProfileLevel.VP9Level51}, + {60000, CodecProfileLevel.VP9Level5}, + {30000, CodecProfileLevel.VP9Level41}, + {18000, CodecProfileLevel.VP9Level4}, + {12000, CodecProfileLevel.VP9Level31}, + {7200, CodecProfileLevel.VP9Level3}, + {3600, CodecProfileLevel.VP9Level21}, + {1800, CodecProfileLevel.VP9Level2}, + {800, CodecProfileLevel.VP9Level11}, + {200, CodecProfileLevel.VP9Level1}, }; VideoCapabilities videoCapabilities = capabilities.getVideoCapabilities(); @@ -600,7 +610,6 @@ private static CodecProfileLevel[] getVp9CodecProfileLevelsV23(CodecCapabilities return new CodecProfileLevel[0]; } - ArrayList profileLevelList = new ArrayList<>(); for (int[] entry : bitrateMapping) { int bitrate = entry[0]; int level = entry[1]; @@ -609,11 +618,11 @@ private static CodecProfileLevel[] getVp9CodecProfileLevelsV23(CodecCapabilities // Assume all platforms before N only support VP9 profile 0. profileLevel.profile = CodecProfileLevel.VP9Profile0; profileLevel.level = level; - profileLevelList.add(profileLevel); + return new CodecProfileLevel[] { profileLevel }; } } - return profileLevelList.toArray(new CodecProfileLevel[profileLevelList.size()]); + return new CodecProfileLevel[0]; } private void logNoSupport(String message) { From 2bb93be17bce54468186492bff6556945c0f8b8e Mon Sep 17 00:00:00 2001 From: Zen Xu Date: Mon, 18 Jan 2021 03:19:38 -0800 Subject: [PATCH 4/4] format --- .../android/exoplayer2/mediacodec/MediaCodecInfo.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java index e0ad25a4adc..0db36dacfd1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java @@ -47,7 +47,6 @@ import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; -import java.util.ArrayList; /** Information about a {@link MediaCodec} for a given mime type. */ @SuppressWarnings("InlinedApi") @@ -301,10 +300,10 @@ public boolean isCodecSupported(Format format) { } CodecProfileLevel[] codecProfileLevels = getProfileLevels(); - if (MimeTypes.VIDEO_VP9.equals(mimeType) && - Util.SDK_INT <= 23 && - codecProfileLevels.length == 0 && - capabilities != null) { + if (MimeTypes.VIDEO_VP9.equals(mimeType) + && Util.SDK_INT <= 23 + && codecProfileLevels.length == 0 + && capabilities != null) { codecProfileLevels = getVp9CodecProfileLevelsV23(capabilities); }