Commit d8876712 by rohks Committed by Rohit Singh

Add support to fetch `ColorInfo` from `avcC` box in `AtomParsers`

#minor-release

PiperOrigin-RevId: 526082823
parent 49802cd2
Showing with 177 additions and 27 deletions
......@@ -61,6 +61,9 @@ public final class NalUnitUtil {
public final int picOrderCountType;
public final int picOrderCntLsbLength;
public final boolean deltaPicOrderAlwaysZeroFlag;
public final @C.ColorSpace int colorSpace;
public final @C.ColorRange int colorRange;
public final @C.ColorTransfer int colorTransfer;
public SpsData(
int profileIdc,
......@@ -76,7 +79,10 @@ public final class NalUnitUtil {
int frameNumLength,
int picOrderCountType,
int picOrderCntLsbLength,
boolean deltaPicOrderAlwaysZeroFlag) {
boolean deltaPicOrderAlwaysZeroFlag,
@C.ColorSpace int colorSpace,
@C.ColorRange int colorRange,
@C.ColorTransfer int colorTransfer) {
this.profileIdc = profileIdc;
this.constraintsFlagsAndReservedZero2Bits = constraintsFlagsAndReservedZero2Bits;
this.levelIdc = levelIdc;
......@@ -91,6 +97,9 @@ public final class NalUnitUtil {
this.picOrderCountType = picOrderCountType;
this.picOrderCntLsbLength = picOrderCntLsbLength;
this.deltaPicOrderAlwaysZeroFlag = deltaPicOrderAlwaysZeroFlag;
this.colorSpace = colorSpace;
this.colorRange = colorRange;
this.colorTransfer = colorTransfer;
}
}
......@@ -441,6 +450,9 @@ public final class NalUnitUtil {
frameHeight -= (frameCropTopOffset + frameCropBottomOffset) * cropUnitY;
}
@C.ColorSpace int colorSpace = Format.NO_VALUE;
@C.ColorRange int colorRange = Format.NO_VALUE;
@C.ColorTransfer int colorTransfer = Format.NO_VALUE;
float pixelWidthHeightRatio = 1;
boolean vuiParametersPresentFlag = data.readBit();
if (vuiParametersPresentFlag) {
......@@ -459,6 +471,23 @@ public final class NalUnitUtil {
Log.w(TAG, "Unexpected aspect_ratio_idc value: " + aspectRatioIdc);
}
}
if (data.readBit()) { // overscan_info_present_flag
data.skipBit(); // overscan_appropriate_flag
}
if (data.readBit()) { // video_signal_type_present_flag
data.skipBits(3); // video_format
colorRange =
data.readBit() ? C.COLOR_RANGE_FULL : C.COLOR_RANGE_LIMITED; // video_full_range_flag
if (data.readBit()) { // colour_description_present_flag
int colorPrimaries = data.readBits(8); // colour_primaries
int transferCharacteristics = data.readBits(8); // transfer_characteristics
data.skipBits(8); // matrix_coeffs
colorSpace = ColorInfo.isoColorPrimariesToColorSpace(colorPrimaries);
colorTransfer =
ColorInfo.isoTransferCharacteristicsToColorTransfer(transferCharacteristics);
}
}
}
return new SpsData(
......@@ -475,7 +504,10 @@ public final class NalUnitUtil {
frameNumLength,
picOrderCntType,
picOrderCntLsbLength,
deltaPicOrderAlwaysZeroFlag);
deltaPicOrderAlwaysZeroFlag,
colorSpace,
colorRange,
colorTransfer);
}
/**
......@@ -503,10 +535,6 @@ public final class NalUnitUtil {
public static H265SpsData parseH265SpsNalUnitPayload(
byte[] nalData, int nalOffset, int nalLimit) {
ParsableNalUnitBitArray data = new ParsableNalUnitBitArray(nalData, nalOffset, nalLimit);
// HDR related metadata.
@C.ColorSpace int colorSpace = Format.NO_VALUE;
@C.ColorRange int colorRange = Format.NO_VALUE;
@C.ColorTransfer int colorTransfer = Format.NO_VALUE;
data.skipBits(4); // sps_video_parameter_set_id
int maxSubLayersMinus1 = data.readBits(3);
data.skipBit(); // sps_temporal_id_nesting_flag
......@@ -593,6 +621,9 @@ public final class NalUnitUtil {
}
}
data.skipBits(2); // sps_temporal_mvp_enabled_flag, strong_intra_smoothing_enabled_flag
@C.ColorSpace int colorSpace = Format.NO_VALUE;
@C.ColorRange int colorRange = Format.NO_VALUE;
@C.ColorTransfer int colorTransfer = Format.NO_VALUE;
float pixelWidthHeightRatio = 1;
if (data.readBit()) { // vui_parameters_present_flag
if (data.readBit()) { // aspect_ratio_info_present_flag
......@@ -614,14 +645,14 @@ public final class NalUnitUtil {
}
if (data.readBit()) { // video_signal_type_present_flag
data.skipBits(3); // video_format
boolean fullRangeFlag = data.readBit(); // video_full_range_flag
colorRange =
data.readBit() ? C.COLOR_RANGE_FULL : C.COLOR_RANGE_LIMITED; // video_full_range_flag
if (data.readBit()) { // colour_description_present_flag
int colorPrimaries = data.readBits(8); // colour_primaries
int transferCharacteristics = data.readBits(8); // transfer_characteristics
data.skipBits(8); // matrix_coeffs
colorSpace = ColorInfo.isoColorPrimariesToColorSpace(colorPrimaries);
colorRange = fullRangeFlag ? C.COLOR_RANGE_FULL : C.COLOR_RANGE_LIMITED;
colorTransfer =
ColorInfo.isoTransferCharacteristicsToColorTransfer(transferCharacteristics);
}
......
......@@ -31,8 +31,8 @@ public final class NalUnitUtilTest {
private static final int TEST_NAL_POSITION = 10;
private static final byte[] SPS_TEST_DATA =
createByteArray(
0x00, 0x00, 0x01, 0x67, 0x4D, 0x40, 0x16, 0xEC, 0xA0, 0x50, 0x17, 0xFC, 0xB8, 0x08, 0x80,
0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x0F, 0x47, 0x8B, 0x16, 0xCB);
0x00, 0x00, 0x01, 0x67, 0x4D, 0x40, 0x16, 0xEC, 0xA0, 0x50, 0x17, 0xFC, 0xB8, 0x0A, 0x90,
0x91, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x0F, 0x47, 0x8B, 0x16, 0xCB);
private static final int SPS_TEST_DATA_OFFSET = 3;
@Test
......@@ -135,6 +135,9 @@ public final class NalUnitUtilTest {
assertThat(data.pixelWidthHeightRatio).isEqualTo(1.0f);
assertThat(data.picOrderCountType).isEqualTo(0);
assertThat(data.separateColorPlaneFlag).isFalse();
assertThat(data.colorSpace).isEqualTo(6);
assertThat(data.colorRange).isEqualTo(2);
assertThat(data.colorTransfer).isEqualTo(6);
}
@Test
......
......@@ -1197,6 +1197,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
pixelWidthHeightRatio = avcConfig.pixelWidthHeightRatio;
}
codecs = avcConfig.codecs;
colorSpace = avcConfig.colorSpace;
colorRange = avcConfig.colorRange;
colorTransfer = avcConfig.colorTransfer;
} else if (childAtomType == Atom.TYPE_hvcC) {
ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null);
mimeType = MimeTypes.VIDEO_H265;
......@@ -1309,12 +1312,13 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
}
} else if (childAtomType == Atom.TYPE_colr) {
// Only modify these values if they have not been previously established by the bitstream.
// If 'Atom.TYPE_hvcC' atom or 'Atom.TYPE_vpcC' is available, they will take precedence and
// overwrite any existing values.
if (colorSpace == Format.NO_VALUE
&& colorRange == Format.NO_VALUE
&& colorTransfer == Format.NO_VALUE) {
// Only modify these values if 'colorSpace' and 'colorTransfer' have not been previously
// established by the bitstream. The absence of color descriptors ('colorSpace' and
// 'colorTransfer') does not necessarily mean that 'colorRange' has default values, hence it
// is not being verified here.
// If 'Atom.TYPE_avcC', 'Atom.TYPE_hvcC' or 'Atom.TYPE_vpcC' is available, they will take
// precedence and overwrite any existing values.
if (colorSpace == Format.NO_VALUE && colorTransfer == Format.NO_VALUE) {
int colorType = parent.readInt();
if (colorType == TYPE_nclx || colorType == TYPE_nclc) {
// For more info on syntax, see Section 8.5.2.2 in ISO/IEC 14496-12:2012(E) and
......
......@@ -16,6 +16,7 @@
package com.google.android.exoplayer2.video;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.util.CodecSpecificDataUtil;
......@@ -55,6 +56,9 @@ public final class AvcConfig {
int width = Format.NO_VALUE;
int height = Format.NO_VALUE;
@C.ColorSpace int colorSpace = Format.NO_VALUE;
@C.ColorRange int colorRange = Format.NO_VALUE;
@C.ColorTransfer int colorTransfer = Format.NO_VALUE;
float pixelWidthHeightRatio = 1;
@Nullable String codecs = null;
if (numSequenceParameterSets > 0) {
......@@ -64,6 +68,9 @@ public final class AvcConfig {
initializationData.get(0), nalUnitLengthFieldLength, sps.length);
width = spsData.width;
height = spsData.height;
colorSpace = spsData.colorSpace;
colorRange = spsData.colorRange;
colorTransfer = spsData.colorTransfer;
pixelWidthHeightRatio = spsData.pixelWidthHeightRatio;
codecs =
CodecSpecificDataUtil.buildAvcCodecString(
......@@ -75,6 +82,9 @@ public final class AvcConfig {
nalUnitLengthFieldLength,
width,
height,
colorSpace,
colorRange,
colorTransfer,
pixelWidthHeightRatio,
codecs);
} catch (ArrayIndexOutOfBoundsException e) {
......@@ -98,6 +108,22 @@ public final class AvcConfig {
/** The height of each decoded frame, or {@link Format#NO_VALUE} if unknown. */
public final int height;
/**
* The {@link C.ColorSpace} of the video, or {@link Format#NO_VALUE} if unknown or not applicable.
*/
public final @C.ColorSpace int colorSpace;
/**
* The {@link C.ColorRange} of the video, or {@link Format#NO_VALUE} if unknown or not applicable.
*/
public final @C.ColorRange int colorRange;
/**
* The {@link C.ColorTransfer} of the video, or {@link Format#NO_VALUE} if unknown or not
* applicable.
*/
public final @C.ColorTransfer int colorTransfer;
/** The pixel width to height ratio. */
public final float pixelWidthHeightRatio;
......@@ -113,12 +139,18 @@ public final class AvcConfig {
int nalUnitLengthFieldLength,
int width,
int height,
@C.ColorSpace int colorSpace,
@C.ColorRange int colorRange,
@C.ColorTransfer int colorTransfer,
float pixelWidthHeightRatio,
@Nullable String codecs) {
this.initializationData = initializationData;
this.nalUnitLengthFieldLength = nalUnitLengthFieldLength;
this.width = width;
this.height = height;
this.colorSpace = colorSpace;
this.colorRange = colorRange;
this.colorTransfer = colorTransfer;
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
this.codecs = codecs;
}
......
......@@ -112,11 +112,11 @@ public final class HevcConfig {
lengthSizeMinusOne + 1,
width,
height,
pixelWidthHeightRatio,
codecs,
colorSpace,
colorRange,
colorTransfer);
colorTransfer,
pixelWidthHeightRatio,
codecs);
} catch (ArrayIndexOutOfBoundsException e) {
throw ParserException.createForMalformedContainer("Error parsing HEVC config", e);
}
......@@ -140,9 +140,6 @@ public final class HevcConfig {
/** The height of each decoded frame, or {@link Format#NO_VALUE} if unknown. */
public final int height;
/** The pixel width to height ratio. */
public final float pixelWidthHeightRatio;
/**
* The {@link C.ColorSpace} of the video or {@link Format#NO_VALUE} if unknown or not applicable.
*/
......@@ -159,6 +156,9 @@ public final class HevcConfig {
*/
public final @C.ColorTransfer int colorTransfer;
/** The pixel width to height ratio. */
public final float pixelWidthHeightRatio;
/**
* An RFC 6381 codecs string representing the video format, or {@code null} if not known.
*
......@@ -171,19 +171,19 @@ public final class HevcConfig {
int nalUnitLengthFieldLength,
int width,
int height,
float pixelWidthHeightRatio,
@Nullable String codecs,
@C.ColorSpace int colorSpace,
@C.ColorRange int colorRange,
@C.ColorTransfer int colorTransfer) {
@C.ColorTransfer int colorTransfer,
float pixelWidthHeightRatio,
@Nullable String codecs) {
this.initializationData = initializationData;
this.nalUnitLengthFieldLength = nalUnitLengthFieldLength;
this.width = width;
this.height = height;
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
this.codecs = codecs;
this.colorSpace = colorSpace;
this.colorRange = colorRange;
this.colorTransfer = colorTransfer;
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
this.codecs = codecs;
}
}
......@@ -17,6 +17,11 @@ track 0:
width = 1280
height = 720
frameRate = 13.307984
colorInfo:
colorSpace = 2
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
metadata = entries=[mdta: key=com.android.capture.fps, value=43700000]
initializationData:
data = length 22, hash 4CF81805
......
......@@ -17,6 +17,11 @@ track 0:
width = 1280
height = 720
frameRate = 13.307984
colorInfo:
colorSpace = 2
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
metadata = entries=[mdta: key=com.android.capture.fps, value=43700000]
initializationData:
data = length 22, hash 4CF81805
......
......@@ -17,6 +17,11 @@ track 0:
width = 1280
height = 720
frameRate = 13.307984
colorInfo:
colorSpace = 2
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
metadata = entries=[mdta: key=com.android.capture.fps, value=43700000]
initializationData:
data = length 22, hash 4CF81805
......
......@@ -17,6 +17,11 @@ track 0:
width = 1280
height = 720
frameRate = 13.307984
colorInfo:
colorSpace = 2
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
metadata = entries=[mdta: key=com.android.capture.fps, value=43700000]
initializationData:
data = length 22, hash 4CF81805
......
......@@ -17,6 +17,11 @@ track 0:
width = 1280
height = 720
frameRate = 13.307984
colorInfo:
colorSpace = 2
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
metadata = entries=[mdta: key=com.android.capture.fps, value=43700000]
initializationData:
data = length 22, hash 4CF81805
......
......@@ -16,6 +16,11 @@ track 0:
maxInputSize = 85
width = 12
height = 10
colorInfo:
colorSpace = -1
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
......
......@@ -17,6 +17,11 @@ track 0:
width = 12
height = 10
rotationDegrees = 180
colorInfo:
colorSpace = -1
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
......
......@@ -17,6 +17,11 @@ track 0:
width = 12
height = 10
rotationDegrees = 270
colorInfo:
colorSpace = -1
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
......
......@@ -17,6 +17,11 @@ track 0:
width = 12
height = 10
rotationDegrees = 90
colorInfo:
colorSpace = -1
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
......
......@@ -17,6 +17,11 @@ track 0:
width = 12
height = 10
frameRate = 20000.0
colorInfo:
colorSpace = -1
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
......@@ -39,6 +44,11 @@ track 1:
width = 12
height = 10
frameRate = 10000.0
colorInfo:
colorSpace = -1
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
......
......@@ -16,6 +16,11 @@ track 0:
maxInputSize = 85
width = 12
height = 10
colorInfo:
colorSpace = -1
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
metadata = entries=[mdta: key=com.android.capture.fps, value=42f00000]
initializationData:
data = length 28, hash 410B510
......
......@@ -16,6 +16,11 @@ track 0:
maxInputSize = 85
width = 12
height = 10
colorInfo:
colorSpace = -1
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
metadata = entries=[xyz: latitude=33.0, longitude=-120.0]
initializationData:
data = length 28, hash 410B510
......
......@@ -16,6 +16,11 @@ track 0:
maxInputSize = 85
width = 12
height = 10
colorInfo:
colorSpace = -1
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
......
......@@ -17,6 +17,11 @@ track 0:
width = 12
height = 10
frameRate = 20000.0
colorInfo:
colorSpace = -1
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
......@@ -39,6 +44,11 @@ track 1:
width = 12
height = 10
frameRate = 10000.0
colorInfo:
colorSpace = -1
colorRange = 1
colorTransfer = -1
hdrStaticInfo = length 0, hash 0
initializationData:
data = length 28, hash 410B510
data = length 9, hash FBADD682
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment