Add AV1 HDR profile recognition

Recognize AV1ProfileMain10HDR when getting codec profile and level.

PiperOrigin-RevId: 258799457
This commit is contained in:
olly 2019-07-18 18:37:55 +01:00 committed by Oliver Woodman
parent 08624113d4
commit 421f6e0303
2 changed files with 78 additions and 4 deletions

View file

@ -25,10 +25,12 @@ import androidx.annotation.Nullable;
import android.text.TextUtils;
import android.util.Pair;
import android.util.SparseIntArray;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.ColorInfo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -255,7 +257,7 @@ public final class MediaCodecUtil {
case CODEC_ID_DVH1:
return getDolbyVisionProfileAndLevel(format.codecs, parts);
case CODEC_ID_AV01:
return getAv1ProfileAndLevel(format.codecs, parts);
return getAv1ProfileAndLevel(format.codecs, parts, format.colorInfo);
case CODEC_ID_MP4A:
return getAacCodecProfileAndLevel(format.codecs, parts);
default:
@ -686,7 +688,8 @@ public final class MediaCodecUtil {
return new Pair<>(profile, level);
}
private static Pair<Integer, Integer> getAv1ProfileAndLevel(String codec, String[] parts) {
private static Pair<Integer, Integer> getAv1ProfileAndLevel(
String codec, String[] parts, @Nullable ColorInfo colorInfo) {
if (parts.length < 4) {
Log.w(TAG, "Ignoring malformed AV1 codec string: " + codec);
return null;
@ -703,8 +706,6 @@ public final class MediaCodecUtil {
return null;
}
// TODO: Recognize HDR profiles. Currently, the profile is assumed to be either Main8 or Main10.
// See [Internal: b/124435216].
if (profileInteger != 0) {
Log.w(TAG, "Unknown AV1 profile: " + profileInteger);
return null;
@ -716,6 +717,11 @@ public final class MediaCodecUtil {
int profile;
if (bitDepthInteger == 8) {
profile = CodecProfileLevel.AV1ProfileMain8;
} else if (colorInfo != null
&& (colorInfo.hdrStaticInfo != null
|| colorInfo.colorTransfer == C.COLOR_TRANSFER_HLG
|| colorInfo.colorTransfer == C.COLOR_TRANSFER_ST2084)) {
profile = CodecProfileLevel.AV1ProfileMain10HDR10;
} else {
profile = CodecProfileLevel.AV1ProfileMain10;
}

View file

@ -20,8 +20,10 @@ 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.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.video.ColorInfo;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -78,6 +80,68 @@ public final class MediaCodecUtilTest {
MediaCodecInfo.CodecProfileLevel.AV1Level7);
}
@Test
public void getCodecProfileAndLevel_handlesAv1ProfileMain10HDRWithHdrInfoSet() {
ColorInfo colorInfo =
new ColorInfo(
/* colorSpace= */ C.COLOR_SPACE_BT709,
/* colorRange= */ C.COLOR_RANGE_LIMITED,
/* colorTransfer= */ C.COLOR_TRANSFER_SDR,
/* hdrStaticInfo= */ new byte[] {1, 2, 3, 4, 5, 6, 7});
Format format =
Format.createVideoSampleFormat(
/* id= */ null,
/* sampleMimeType= */ MimeTypes.VIDEO_UNKNOWN,
/* codecs= */ "av01.0.21M.10",
/* bitrate= */ Format.NO_VALUE,
/* maxInputSize= */ Format.NO_VALUE,
/* width= */ 1024,
/* height= */ 768,
/* frameRate= */ Format.NO_VALUE,
/* initializationData= */ null,
/* rotationDegrees= */ Format.NO_VALUE,
/* pixelWidthHeightRatio= */ 0,
/* projectionData= */ null,
/* stereoMode= */ Format.NO_VALUE,
/* colorInfo= */ colorInfo,
/* drmInitData */ null);
assertCodecProfileAndLevelForFormat(
format,
MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10HDR10,
MediaCodecInfo.CodecProfileLevel.AV1Level71);
}
@Test
public void getCodecProfileAndLevel_handlesAv1ProfileMain10HDRWithoutHdrInfoSet() {
ColorInfo colorInfo =
new ColorInfo(
/* colorSpace= */ C.COLOR_SPACE_BT709,
/* colorRange= */ C.COLOR_RANGE_LIMITED,
/* colorTransfer= */ C.COLOR_TRANSFER_HLG,
/* hdrStaticInfo= */ null);
Format format =
Format.createVideoSampleFormat(
/* id= */ null,
/* sampleMimeType= */ MimeTypes.VIDEO_UNKNOWN,
/* codecs= */ "av01.0.21M.10",
/* bitrate= */ Format.NO_VALUE,
/* maxInputSize= */ Format.NO_VALUE,
/* width= */ 1024,
/* height= */ 768,
/* frameRate= */ Format.NO_VALUE,
/* initializationData= */ null,
/* rotationDegrees= */ Format.NO_VALUE,
/* pixelWidthHeightRatio= */ 0,
/* projectionData= */ null,
/* stereoMode= */ Format.NO_VALUE,
/* colorInfo= */ colorInfo,
/* drmInitData */ null);
assertCodecProfileAndLevelForFormat(
format,
MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10HDR10,
MediaCodecInfo.CodecProfileLevel.AV1Level71);
}
@Test
public void getCodecProfileAndLevel_handlesFullAv1CodecString() {
// Example from https://aomediacodec.github.io/av1-isobmff/#codecsparam.
@ -135,6 +199,10 @@ public final class MediaCodecUtilTest {
/* frameRate= */ Format.NO_VALUE,
/* initializationData= */ null,
/* drmInitData= */ null);
assertCodecProfileAndLevelForFormat(format, profile, level);
}
private static void assertCodecProfileAndLevelForFormat(Format format, int profile, int level) {
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
assertThat(codecProfileAndLevel).isNotNull();
assertThat(codecProfileAndLevel.first).isEqualTo(profile);