Skip to content

Commit

Permalink
Merge pull request #8462 from zeninsta:advertise-vp9-profile
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 352611965
  • Loading branch information
ojw28 committed Jan 19, 2021
2 parents b2a42ea + 2bb93be commit c40d1c6
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 4 deletions.
5 changes: 5 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +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()) {
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;
}
}
Expand Down Expand Up @@ -334,8 +342,8 @@ public boolean isSeamlessAdaptationSupported(Format format) {
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;
}
}

Expand Down Expand Up @@ -678,6 +686,60 @@ private static int getMaxSupportedInstancesV23(CodecCapabilities capabilities) {
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.
Expand Down

0 comments on commit c40d1c6

Please sign in to comment.