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..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 @@ -298,7 +298,16 @@ 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()) { + + CodecProfileLevel[] codecProfileLevels = getProfileLevels(); + if (MimeTypes.VIDEO_VP9.equals(mimeType) + && Util.SDK_INT <= 23 + && codecProfileLevels.length == 0 + && capabilities != null) { + codecProfileLevels = getVp9CodecProfileLevelsV23(capabilities); + } + + for (CodecProfileLevel capabilities : codecProfileLevels) { if (capabilities.profile == profile && capabilities.level >= level) { return true; } @@ -572,6 +581,49 @@ public boolean isAudioChannelCountSupportedV21(int channelCount) { return true; } + /** + * On versions M and below, VP9 codecCapabilities do not advertise profile level + * support. In this case, estimate the level from MediaCodecInfo.VideoCapabilities + * 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 = { + {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(); + + if (videoCapabilities == null) { + return new CodecProfileLevel[0]; + } + + 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; + return new CodecProfileLevel[] { profileLevel }; + } + } + + return new CodecProfileLevel[0]; + } + private void logNoSupport(String message) { Log.d(TAG, "NoSupport [" + message + "] [" + name + ", " + mimeType + "] [" + Util.DEVICE_DEBUG_INFO + "]");