mirror of
https://github.com/androidx/media.git
synced 2025-05-03 21:57:46 +08:00
Add support to fetch ColorInfo
from hvcc
box in AtomParsers
#minor-release PiperOrigin-RevId: 517086016
This commit is contained in:
parent
eb6fc93b15
commit
e4446c37fb
@ -1208,6 +1208,15 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
pixelWidthHeightRatio = hevcConfig.pixelWidthHeightRatio;
|
pixelWidthHeightRatio = hevcConfig.pixelWidthHeightRatio;
|
||||||
}
|
}
|
||||||
codecs = hevcConfig.codecs;
|
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) {
|
} else if (childAtomType == Atom.TYPE_dvcC || childAtomType == Atom.TYPE_dvvC) {
|
||||||
@Nullable DolbyVisionConfig dolbyVisionConfig = DolbyVisionConfig.parse(parent);
|
@Nullable DolbyVisionConfig dolbyVisionConfig = DolbyVisionConfig.parse(parent);
|
||||||
if (dolbyVisionConfig != null) {
|
if (dolbyVisionConfig != null) {
|
||||||
|
@ -19,6 +19,8 @@ import static java.lang.Math.min;
|
|||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
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.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@ -105,6 +107,9 @@ public final class NalUnitUtil {
|
|||||||
public final int width;
|
public final int width;
|
||||||
public final int height;
|
public final int height;
|
||||||
public final float pixelWidthHeightRatio;
|
public final float pixelWidthHeightRatio;
|
||||||
|
public final @C.ColorSpace int colorSpace;
|
||||||
|
public final @C.ColorRange int colorRange;
|
||||||
|
public final @C.ColorTransfer int colorTransfer;
|
||||||
|
|
||||||
public H265SpsData(
|
public H265SpsData(
|
||||||
int generalProfileSpace,
|
int generalProfileSpace,
|
||||||
@ -116,7 +121,10 @@ public final class NalUnitUtil {
|
|||||||
int seqParameterSetId,
|
int seqParameterSetId,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
float pixelWidthHeightRatio) {
|
float pixelWidthHeightRatio,
|
||||||
|
@C.ColorSpace int colorSpace,
|
||||||
|
@C.ColorRange int colorRange,
|
||||||
|
@C.ColorTransfer int colorTransfer) {
|
||||||
this.generalProfileSpace = generalProfileSpace;
|
this.generalProfileSpace = generalProfileSpace;
|
||||||
this.generalTierFlag = generalTierFlag;
|
this.generalTierFlag = generalTierFlag;
|
||||||
this.generalProfileIdc = generalProfileIdc;
|
this.generalProfileIdc = generalProfileIdc;
|
||||||
@ -127,6 +135,9 @@ public final class NalUnitUtil {
|
|||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
|
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
|
||||||
|
this.colorSpace = colorSpace;
|
||||||
|
this.colorRange = colorRange;
|
||||||
|
this.colorTransfer = colorTransfer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,6 +494,10 @@ public final class NalUnitUtil {
|
|||||||
public static H265SpsData parseH265SpsNalUnitPayload(
|
public static H265SpsData parseH265SpsNalUnitPayload(
|
||||||
byte[] nalData, int nalOffset, int nalLimit) {
|
byte[] nalData, int nalOffset, int nalLimit) {
|
||||||
ParsableNalUnitBitArray data = new ParsableNalUnitBitArray(nalData, nalOffset, 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
|
data.skipBits(4); // sps_video_parameter_set_id
|
||||||
int maxSubLayersMinus1 = data.readBits(3);
|
int maxSubLayersMinus1 = data.readBits(3);
|
||||||
data.skipBit(); // sps_temporal_id_nesting_flag
|
data.skipBit(); // sps_temporal_id_nesting_flag
|
||||||
@ -589,10 +604,17 @@ public final class NalUnitUtil {
|
|||||||
data.skipBit(); // overscan_appropriate_flag
|
data.skipBit(); // overscan_appropriate_flag
|
||||||
}
|
}
|
||||||
if (data.readBit()) { // video_signal_type_present_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
|
if (data.readBit()) { // colour_description_present_flag
|
||||||
// colour_primaries, transfer_characteristics, matrix_coeffs
|
int colorPrimaries = data.readBits(8); // colour_primaries
|
||||||
data.skipBits(24);
|
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
|
if (data.readBit()) { // chroma_loc_info_present_flag
|
||||||
@ -617,7 +639,10 @@ public final class NalUnitUtil {
|
|||||||
seqParameterSetId,
|
seqParameterSetId,
|
||||||
frameWidth,
|
frameWidth,
|
||||||
frameHeight,
|
frameHeight,
|
||||||
pixelWidthHeightRatio);
|
pixelWidthHeightRatio,
|
||||||
|
colorSpace,
|
||||||
|
colorRange,
|
||||||
|
colorTransfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.google.android.exoplayer2.video;
|
package com.google.android.exoplayer2.video;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
import com.google.android.exoplayer2.util.CodecSpecificDataUtil;
|
import com.google.android.exoplayer2.util.CodecSpecificDataUtil;
|
||||||
@ -60,6 +61,9 @@ public final class HevcConfig {
|
|||||||
int bufferPosition = 0;
|
int bufferPosition = 0;
|
||||||
int width = Format.NO_VALUE;
|
int width = Format.NO_VALUE;
|
||||||
int height = 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;
|
float pixelWidthHeightRatio = 1;
|
||||||
@Nullable String codecs = null;
|
@Nullable String codecs = null;
|
||||||
for (int i = 0; i < numberOfArrays; i++) {
|
for (int i = 0; i < numberOfArrays; i++) {
|
||||||
@ -83,6 +87,9 @@ public final class HevcConfig {
|
|||||||
buffer, bufferPosition, bufferPosition + nalUnitLength);
|
buffer, bufferPosition, bufferPosition + nalUnitLength);
|
||||||
width = spsData.width;
|
width = spsData.width;
|
||||||
height = spsData.height;
|
height = spsData.height;
|
||||||
|
colorSpace = spsData.colorSpace;
|
||||||
|
colorRange = spsData.colorRange;
|
||||||
|
colorTransfer = spsData.colorTransfer;
|
||||||
pixelWidthHeightRatio = spsData.pixelWidthHeightRatio;
|
pixelWidthHeightRatio = spsData.pixelWidthHeightRatio;
|
||||||
codecs =
|
codecs =
|
||||||
CodecSpecificDataUtil.buildHevcCodecString(
|
CodecSpecificDataUtil.buildHevcCodecString(
|
||||||
@ -101,7 +108,15 @@ public final class HevcConfig {
|
|||||||
List<byte[]> initializationData =
|
List<byte[]> initializationData =
|
||||||
csdLength == 0 ? Collections.emptyList() : Collections.singletonList(buffer);
|
csdLength == 0 ? Collections.emptyList() : Collections.singletonList(buffer);
|
||||||
return new HevcConfig(
|
return new HevcConfig(
|
||||||
initializationData, lengthSizeMinusOne + 1, width, height, pixelWidthHeightRatio, codecs);
|
initializationData,
|
||||||
|
lengthSizeMinusOne + 1,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
pixelWidthHeightRatio,
|
||||||
|
codecs,
|
||||||
|
colorSpace,
|
||||||
|
colorRange,
|
||||||
|
colorTransfer);
|
||||||
} catch (ArrayIndexOutOfBoundsException e) {
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
throw ParserException.createForMalformedContainer("Error parsing HEVC config", e);
|
throw ParserException.createForMalformedContainer("Error parsing HEVC config", e);
|
||||||
}
|
}
|
||||||
@ -128,6 +143,22 @@ public final class HevcConfig {
|
|||||||
/** The pixel width to height ratio. */
|
/** The pixel width to height ratio. */
|
||||||
public final float pixelWidthHeightRatio;
|
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.
|
* 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 width,
|
||||||
int height,
|
int height,
|
||||||
float pixelWidthHeightRatio,
|
float pixelWidthHeightRatio,
|
||||||
@Nullable String codecs) {
|
@Nullable String codecs,
|
||||||
|
@C.ColorSpace int colorSpace,
|
||||||
|
@C.ColorRange int colorRange,
|
||||||
|
@C.ColorTransfer int colorTransfer) {
|
||||||
this.initializationData = initializationData;
|
this.initializationData = initializationData;
|
||||||
this.nalUnitLengthFieldLength = nalUnitLengthFieldLength;
|
this.nalUnitLengthFieldLength = nalUnitLengthFieldLength;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
|
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
|
||||||
this.codecs = codecs;
|
this.codecs = codecs;
|
||||||
|
this.colorSpace = colorSpace;
|
||||||
|
this.colorRange = colorRange;
|
||||||
|
this.colorTransfer = colorTransfer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,6 +192,9 @@ public final class NalUnitUtilTest {
|
|||||||
assertThat(spsData.pixelWidthHeightRatio).isEqualTo(1);
|
assertThat(spsData.pixelWidthHeightRatio).isEqualTo(1);
|
||||||
assertThat(spsData.seqParameterSetId).isEqualTo(0);
|
assertThat(spsData.seqParameterSetId).isEqualTo(0);
|
||||||
assertThat(spsData.width).isEqualTo(3840);
|
assertThat(spsData.width).isEqualTo(3840);
|
||||||
|
assertThat(spsData.colorSpace).isEqualTo(6);
|
||||||
|
assertThat(spsData.colorRange).isEqualTo(2);
|
||||||
|
assertThat(spsData.colorTransfer).isEqualTo(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] buildTestData() {
|
private static byte[] buildTestData() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user