Merge pull request #8462 from zeninsta:advertise-vp9-profile

PiperOrigin-RevId: 352611965
This commit is contained in:
Oliver Woodman 2021-01-19 19:24:16 +00:00
commit c40d1c6620
2 changed files with 71 additions and 4 deletions

View file

@ -195,6 +195,11 @@
`DecoderReuseEvaluation` indicates whether it was possible to re-use an
existing decoder instance for the new format, and if not then the
reasons why.
* Video:
* Fix VP9 format capability checks on API level 23 and earlier. The
platform does not correctly report the VP9 level supported by the
decoder in this case, so we estimate it based on the decoder's maximum
supported bitrate.
* Audio:
* Fix handling of audio session IDs
([#8190](https://github.com/google/ExoPlayer/issues/8190)).

View file

@ -298,8 +298,16 @@ public final class MediaCodecInfo {
// which may not be widely supported. See https://github.com/google/ExoPlayer/issues/5145.
return true;
}
for (CodecProfileLevel capabilities : getProfileLevels()) {
if (capabilities.profile == profile && capabilities.level >= level) {
CodecProfileLevel[] profileLevels = getProfileLevels();
if (Util.SDK_INT <= 23 && MimeTypes.VIDEO_VP9.equals(mimeType) && profileLevels.length == 0) {
// Some older devices don't report profile levels for VP9. Estimate them using other data in
// the codec capabilities.
profileLevels = estimateLegacyVp9ProfileLevels(capabilities);
}
for (CodecProfileLevel profileLevel : profileLevels) {
if (profileLevel.profile == profile && profileLevel.level >= level) {
return true;
}
}
@ -334,8 +342,8 @@ public final class MediaCodecInfo {
if (isVideo) {
return adaptive;
} else {
Pair<Integer, Integer> codecProfileLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
return codecProfileLevel != null && codecProfileLevel.first == CodecProfileLevel.AACObjectXHE;
Pair<Integer, Integer> profileLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
return profileLevel != null && profileLevel.first == CodecProfileLevel.AACObjectXHE;
}
}
@ -678,6 +686,60 @@ public final class MediaCodecInfo {
return capabilities.getMaxSupportedInstances();
}
/**
* Called on devices with {@link Util#SDK_INT} 23 and below, for VP9 decoders whose {@link
* CodecCapabilities} do not correctly report profile levels. The returned {@link
* CodecProfileLevel CodecProfileLevels} are estimated based on other data in the {@link
* CodecCapabilities}.
*
* @param capabilities The {@link CodecCapabilities} for a VP9 decoder, or {@code null} if not
* known.
* @return The estimated {@link CodecProfileLevel CodecProfileLevels} for the decoder.
*/
private static CodecProfileLevel[] estimateLegacyVp9ProfileLevels(
@Nullable CodecCapabilities capabilities) {
int maxBitrate = 0;
if (capabilities != null) {
@Nullable VideoCapabilities videoCapabilities = capabilities.getVideoCapabilities();
if (videoCapabilities != null) {
maxBitrate = videoCapabilities.getBitrateRange().getUpper();
}
}
// Values taken from https://www.webmproject.org/vp9/levels.
int level;
if (maxBitrate >= 180_000_000) {
level = CodecProfileLevel.VP9Level52;
} else if (maxBitrate >= 120_000_000) {
level = CodecProfileLevel.VP9Level51;
} else if (maxBitrate >= 60_000_000) {
level = CodecProfileLevel.VP9Level5;
} else if (maxBitrate >= 30_000_000) {
level = CodecProfileLevel.VP9Level41;
} else if (maxBitrate >= 18_000_000) {
level = CodecProfileLevel.VP9Level4;
} else if (maxBitrate >= 12_000_000) {
level = CodecProfileLevel.VP9Level31;
} else if (maxBitrate >= 7_200_000) {
level = CodecProfileLevel.VP9Level3;
} else if (maxBitrate >= 3_600_000) {
level = CodecProfileLevel.VP9Level21;
} else if (maxBitrate >= 1_800_000) {
level = CodecProfileLevel.VP9Level2;
} else if (maxBitrate >= 800_000) {
level = CodecProfileLevel.VP9Level11;
} else { // Assume level 1 is always supported.
level = CodecProfileLevel.VP9Level1;
}
CodecProfileLevel profileLevel = new CodecProfileLevel();
// Since this method is for legacy devices only, assume that only profile 0 is supported.
profileLevel.profile = CodecProfileLevel.VP9Profile0;
profileLevel.level = level;
return new CodecProfileLevel[] {profileLevel};
}
/**
* Returns whether the decoder is known to fail when adapting, despite advertising itself as an
* adaptive decoder.