Add support to fetch ColorInfo from hvcc box in AtomParsers

#minor-release

PiperOrigin-RevId: 517086016
This commit is contained in:
rohks 2023-03-16 11:37:04 +00:00 committed by Rohit Singh
parent eb6fc93b15
commit e4446c37fb
4 changed files with 81 additions and 7 deletions

View File

@ -1208,6 +1208,15 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
pixelWidthHeightRatio = hevcConfig.pixelWidthHeightRatio;
}
codecs = hevcConfig.codecs;
// Modify these values only if they have not already been set. If 'Atom.TYPE_colr' atom is
// present, these values may be overridden.
if (colorSpace == Format.NO_VALUE
&& colorRange == Format.NO_VALUE
&& colorTransfer == Format.NO_VALUE) {
colorSpace = hevcConfig.colorSpace;
colorRange = hevcConfig.colorRange;
colorTransfer = hevcConfig.colorTransfer;
}
} else if (childAtomType == Atom.TYPE_dvcC || childAtomType == Atom.TYPE_dvvC) {
@Nullable DolbyVisionConfig dolbyVisionConfig = DolbyVisionConfig.parse(parent);
if (dolbyVisionConfig != null) {

View File

@ -19,6 +19,8 @@ import static java.lang.Math.min;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.video.ColorInfo;
import java.nio.ByteBuffer;
import java.util.Arrays;
@ -105,6 +107,9 @@ public final class NalUnitUtil {
public final int width;
public final int height;
public final float pixelWidthHeightRatio;
public final @C.ColorSpace int colorSpace;
public final @C.ColorRange int colorRange;
public final @C.ColorTransfer int colorTransfer;
public H265SpsData(
int generalProfileSpace,
@ -116,7 +121,10 @@ public final class NalUnitUtil {
int seqParameterSetId,
int width,
int height,
float pixelWidthHeightRatio) {
float pixelWidthHeightRatio,
@C.ColorSpace int colorSpace,
@C.ColorRange int colorRange,
@C.ColorTransfer int colorTransfer) {
this.generalProfileSpace = generalProfileSpace;
this.generalTierFlag = generalTierFlag;
this.generalProfileIdc = generalProfileIdc;
@ -127,6 +135,9 @@ public final class NalUnitUtil {
this.width = width;
this.height = height;
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
this.colorSpace = colorSpace;
this.colorRange = colorRange;
this.colorTransfer = colorTransfer;
}
}
@ -483,6 +494,10 @@ 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
@ -589,10 +604,17 @@ public final class NalUnitUtil {
data.skipBit(); // overscan_appropriate_flag
}
if (data.readBit()) { // video_signal_type_present_flag
data.skipBits(4); // video_format, video_full_range_flag
data.skipBits(3); // video_format
boolean fullRangeFlag = data.readBit(); // video_full_range_flag
if (data.readBit()) { // colour_description_present_flag
// colour_primaries, transfer_characteristics, matrix_coeffs
data.skipBits(24);
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);
}
}
if (data.readBit()) { // chroma_loc_info_present_flag
@ -617,7 +639,10 @@ public final class NalUnitUtil {
seqParameterSetId,
frameWidth,
frameHeight,
pixelWidthHeightRatio);
pixelWidthHeightRatio,
colorSpace,
colorRange,
colorTransfer);
}
/**

View File

@ -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;
@ -60,6 +61,9 @@ public final class HevcConfig {
int bufferPosition = 0;
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;
for (int i = 0; i < numberOfArrays; i++) {
@ -83,6 +87,9 @@ public final class HevcConfig {
buffer, bufferPosition, bufferPosition + nalUnitLength);
width = spsData.width;
height = spsData.height;
colorSpace = spsData.colorSpace;
colorRange = spsData.colorRange;
colorTransfer = spsData.colorTransfer;
pixelWidthHeightRatio = spsData.pixelWidthHeightRatio;
codecs =
CodecSpecificDataUtil.buildHevcCodecString(
@ -101,7 +108,15 @@ public final class HevcConfig {
List<byte[]> initializationData =
csdLength == 0 ? Collections.emptyList() : Collections.singletonList(buffer);
return new HevcConfig(
initializationData, lengthSizeMinusOne + 1, width, height, pixelWidthHeightRatio, codecs);
initializationData,
lengthSizeMinusOne + 1,
width,
height,
pixelWidthHeightRatio,
codecs,
colorSpace,
colorRange,
colorTransfer);
} catch (ArrayIndexOutOfBoundsException e) {
throw ParserException.createForMalformedContainer("Error parsing HEVC config", e);
}
@ -128,6 +143,22 @@ public final class HevcConfig {
/** 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.
*/
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;
/**
* An RFC 6381 codecs string representing the video format, or {@code null} if not known.
*
@ -141,12 +172,18 @@ public final class HevcConfig {
int width,
int height,
float pixelWidthHeightRatio,
@Nullable String codecs) {
@Nullable String codecs,
@C.ColorSpace int colorSpace,
@C.ColorRange int colorRange,
@C.ColorTransfer int colorTransfer) {
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;
}
}

View File

@ -192,6 +192,9 @@ public final class NalUnitUtilTest {
assertThat(spsData.pixelWidthHeightRatio).isEqualTo(1);
assertThat(spsData.seqParameterSetId).isEqualTo(0);
assertThat(spsData.width).isEqualTo(3840);
assertThat(spsData.colorSpace).isEqualTo(6);
assertThat(spsData.colorRange).isEqualTo(2);
assertThat(spsData.colorTransfer).isEqualTo(6);
}
private static byte[] buildTestData() {