Pass format instead of codec string when getting profile and level

AV1 profile recognition requires additional info contained in format.

PiperOrigin-RevId: 258746315
This commit is contained in:
olly 2019-07-18 12:40:40 +01:00 committed by Oliver Woodman
parent c779e84cbb
commit e25340be3d
4 changed files with 71 additions and 37 deletions

View file

@ -198,7 +198,7 @@ public final class MediaCodecInfo {
* @throws MediaCodecUtil.DecoderQueryException Thrown if an error occurs while querying decoders.
*/
public boolean isFormatSupported(Format format) throws MediaCodecUtil.DecoderQueryException {
if (!isCodecSupported(format.codecs)) {
if (!isCodecSupported(format)) {
return false;
}
@ -226,25 +226,25 @@ public final class MediaCodecInfo {
}
/**
* Whether the decoder supports the given {@code codec}. If there is insufficient information to
* decide, returns true.
* Whether the decoder supports the codec of the given {@code format}. If there is insufficient
* information to decide, returns true.
*
* @param codec Codec string as defined in RFC 6381.
* @return True if the given codec is supported by the decoder.
* @param format The input media format.
* @return True if the codec of the given {@code format} is supported by the decoder.
*/
public boolean isCodecSupported(String codec) {
if (codec == null || mimeType == null) {
public boolean isCodecSupported(Format format) {
if (format.codecs == null || mimeType == null) {
return true;
}
String codecMimeType = MimeTypes.getMediaMimeType(codec);
String codecMimeType = MimeTypes.getMediaMimeType(format.codecs);
if (codecMimeType == null) {
return true;
}
if (!mimeType.equals(codecMimeType)) {
logNoSupport("codec.mime " + codec + ", " + codecMimeType);
logNoSupport("codec.mime " + format.codecs + ", " + codecMimeType);
return false;
}
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(codec);
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
if (codecProfileAndLevel == null) {
// If we don't know any better, we assume that the profile and level are supported.
return true;
@ -261,7 +261,7 @@ public final class MediaCodecInfo {
return true;
}
}
logNoSupport("codec.profileLevel, " + codec + ", " + codecMimeType);
logNoSupport("codec.profileLevel, " + format.codecs + ", " + codecMimeType);
return false;
}
@ -279,8 +279,7 @@ public final class MediaCodecInfo {
if (isVideo) {
return adaptive;
} else {
Pair<Integer, Integer> codecProfileLevel =
MediaCodecUtil.getCodecProfileAndLevel(format.codecs);
Pair<Integer, Integer> codecProfileLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
return codecProfileLevel != null && codecProfileLevel.first == CodecProfileLevel.AACObjectXHE;
}
}
@ -314,9 +313,9 @@ public final class MediaCodecInfo {
}
// Check the codec profile levels support adaptation.
Pair<Integer, Integer> oldCodecProfileLevel =
MediaCodecUtil.getCodecProfileAndLevel(oldFormat.codecs);
MediaCodecUtil.getCodecProfileAndLevel(oldFormat);
Pair<Integer, Integer> newCodecProfileLevel =
MediaCodecUtil.getCodecProfileAndLevel(newFormat.codecs);
MediaCodecUtil.getCodecProfileAndLevel(newFormat);
if (oldCodecProfileLevel == null || newCodecProfileLevel == null) {
return false;
}

View file

@ -230,35 +230,34 @@ public final class MediaCodecUtil {
}
/**
* Returns profile and level (as defined by {@link CodecProfileLevel}) corresponding to the given
* codec description string (as defined by RFC 6381).
* Returns profile and level (as defined by {@link CodecProfileLevel}) corresponding to the codec
* description string (as defined by RFC 6381) of the given format.
*
* @param codec A codec description string, as defined by RFC 6381, or {@code null} if not known.
* @return A pair (profile constant, level constant) if {@code codec} is well-formed and
* recognized, or null otherwise
* @param format Media format with a codec description string, as defined by RFC 6381.
* @return A pair (profile constant, level constant) if the codec of the {@code format} is
* well-formed and recognized, or null otherwise.
*/
@Nullable
public static Pair<Integer, Integer> getCodecProfileAndLevel(@Nullable String codec) {
if (codec == null) {
public static Pair<Integer, Integer> getCodecProfileAndLevel(Format format) {
if (format.codecs == null) {
return null;
}
String[] parts = codec.split("\\.");
String[] parts = format.codecs.split("\\.");
switch (parts[0]) {
case CODEC_ID_AVC1:
case CODEC_ID_AVC2:
return getAvcProfileAndLevel(codec, parts);
return getAvcProfileAndLevel(format.codecs, parts);
case CODEC_ID_VP09:
return getVp9ProfileAndLevel(codec, parts);
return getVp9ProfileAndLevel(format.codecs, parts);
case CODEC_ID_HEV1:
case CODEC_ID_HVC1:
return getHevcProfileAndLevel(codec, parts);
return getHevcProfileAndLevel(format.codecs, parts);
case CODEC_ID_DVHE:
case CODEC_ID_DVH1:
return getDolbyVisionProfileAndLevel(codec, parts);
return getDolbyVisionProfileAndLevel(format.codecs, parts);
case CODEC_ID_AV01:
return getAv1ProfileAndLevel(codec, parts);
return getAv1ProfileAndLevel(format.codecs, parts);
case CODEC_ID_MP4A:
return getAacCodecProfileAndLevel(codec, parts);
return getAacCodecProfileAndLevel(format.codecs, parts);
default:
return null;
}

View file

@ -390,8 +390,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
decoderInfos = MediaCodecUtil.getDecoderInfosSortedByFormatSupport(decoderInfos, format);
if (MimeTypes.VIDEO_DOLBY_VISION.equals(format.sampleMimeType)) {
// Fallback to primary decoders for H.265/HEVC or H.264/AVC for the relevant DV profiles.
Pair<Integer, Integer> codecProfileAndLevel =
MediaCodecUtil.getCodecProfileAndLevel(format.codecs);
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
if (codecProfileAndLevel != null) {
int profile = codecProfileAndLevel.first;
if (profile == 4 || profile == 8) {
@ -1194,8 +1193,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
if (MimeTypes.VIDEO_DOLBY_VISION.equals(format.sampleMimeType)) {
// Some phones require the profile to be set on the codec.
// See https://github.com/google/ExoPlayer/pull/5438.
Pair<Integer, Integer> codecProfileAndLevel =
MediaCodecUtil.getCodecProfileAndLevel(format.codecs);
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
if (codecProfileAndLevel != null) {
MediaFormatUtil.maybeSetInteger(
mediaFormat, MediaFormat.KEY_PROFILE, codecProfileAndLevel.first);

View file

@ -20,6 +20,8 @@ import static com.google.common.truth.Truth.assertThat;
import android.media.MediaCodecInfo;
import android.util.Pair;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.util.MimeTypes;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -87,17 +89,53 @@ public final class MediaCodecUtilTest {
@Test
public void getCodecProfileAndLevel_rejectsNullCodecString() {
assertThat(MediaCodecUtil.getCodecProfileAndLevel(/* codec= */ null)).isNull();
Format format =
Format.createVideoSampleFormat(
/* id= */ null,
/* sampleMimeType= */ MimeTypes.VIDEO_UNKNOWN,
/* codecs= */ null,
/* bitrate= */ Format.NO_VALUE,
/* maxInputSize= */ Format.NO_VALUE,
/* width= */ 1024,
/* height= */ 768,
/* frameRate= */ Format.NO_VALUE,
/* initializationData= */ null,
/* drmInitData= */ null);
assertThat(MediaCodecUtil.getCodecProfileAndLevel(format)).isNull();
}
@Test
public void getCodecProfileAndLevel_rejectsEmptyCodecString() {
assertThat(MediaCodecUtil.getCodecProfileAndLevel("")).isNull();
Format format =
Format.createVideoSampleFormat(
/* id= */ null,
/* sampleMimeType= */ MimeTypes.VIDEO_UNKNOWN,
/* codecs= */ "",
/* bitrate= */ Format.NO_VALUE,
/* maxInputSize= */ Format.NO_VALUE,
/* width= */ 1024,
/* height= */ 768,
/* frameRate= */ Format.NO_VALUE,
/* initializationData= */ null,
/* drmInitData= */ null);
assertThat(MediaCodecUtil.getCodecProfileAndLevel(format)).isNull();
}
private static void assertCodecProfileAndLevelForCodecsString(
String codecs, int profile, int level) {
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(codecs);
Format format =
Format.createVideoSampleFormat(
/* id= */ null,
/* sampleMimeType= */ MimeTypes.VIDEO_UNKNOWN,
/* codecs= */ codecs,
/* bitrate= */ Format.NO_VALUE,
/* maxInputSize= */ Format.NO_VALUE,
/* width= */ 1024,
/* height= */ 768,
/* frameRate= */ Format.NO_VALUE,
/* initializationData= */ null,
/* drmInitData= */ null);
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
assertThat(codecProfileAndLevel).isNotNull();
assertThat(codecProfileAndLevel.first).isEqualTo(profile);
assertThat(codecProfileAndLevel.second).isEqualTo(level);