diff --git a/libraries/common/src/main/java/androidx/media3/common/Format.java b/libraries/common/src/main/java/androidx/media3/common/Format.java
index ad2b579743..8761834d25 100644
--- a/libraries/common/src/main/java/androidx/media3/common/Format.java
+++ b/libraries/common/src/main/java/androidx/media3/common/Format.java
@@ -96,6 +96,8 @@ import java.util.UUID;
*
{@link #projectionData}
* {@link #stereoMode}
* {@link #colorInfo}
+ * {@link #lumaBitdepth}
+ * {@link #chromaBitdepth}
*
*
*
@@ -167,6 +169,8 @@ public final class Format implements Bundleable {
@Nullable private byte[] projectionData;
private @C.StereoMode int stereoMode;
@Nullable private ColorInfo colorInfo;
+ private int lumaBitdepth;
+ private int chromaBitdepth;
// Audio specific.
@@ -203,6 +207,8 @@ public final class Format implements Bundleable {
frameRate = NO_VALUE;
pixelWidthHeightRatio = 1.0f;
stereoMode = NO_VALUE;
+ lumaBitdepth = 8;
+ chromaBitdepth = 8;
// Audio specific.
channelCount = NO_VALUE;
sampleRate = NO_VALUE;
@@ -249,6 +255,8 @@ public final class Format implements Bundleable {
this.projectionData = format.projectionData;
this.stereoMode = format.stereoMode;
this.colorInfo = format.colorInfo;
+ this.lumaBitdepth = format.lumaBitdepth;
+ this.chromaBitdepth = format.chromaBitdepth;
// Audio specific.
this.channelCount = format.channelCount;
this.sampleRate = format.sampleRate;
@@ -560,6 +568,30 @@ public final class Format implements Bundleable {
return this;
}
+ /**
+ * Sets {@link Format#lumaBitdepth}. The default value is 8.
+ *
+ * @param lumaBitdepth The {@link Format#lumaBitdepth}.
+ * @return The builder.
+ */
+ @CanIgnoreReturnValue
+ public Builder setLumaBitdepth(int lumaBitdepth) {
+ this.lumaBitdepth = lumaBitdepth;
+ return this;
+ }
+
+ /**
+ * Sets {@link Format#chromaBitdepth}. The default value is 8.
+ *
+ * @param chromaBitdepth The {@link Format#chromaBitdepth}.
+ * @return The builder.
+ */
+ @CanIgnoreReturnValue
+ public Builder setChromaBitdepth(int chromaBitdepth) {
+ this.chromaBitdepth = chromaBitdepth;
+ return this;
+ }
+
// Audio specific.
/**
@@ -872,6 +904,10 @@ public final class Format implements Bundleable {
/** The color metadata associated with the video, or null if not applicable. */
@UnstableApi @Nullable public final ColorInfo colorInfo;
+ /** The bit depth of the luma samples of the video. */
+ public final int lumaBitdepth;
+ /** The bit depth of the chroma samples of the video. It might differ from the luma bit depth. */
+ public final int chromaBitdepth;
// Audio specific.
@@ -959,6 +995,8 @@ public final class Format implements Bundleable {
projectionData = builder.projectionData;
stereoMode = builder.stereoMode;
colorInfo = builder.colorInfo;
+ lumaBitdepth = builder.lumaBitdepth;
+ chromaBitdepth = builder.chromaBitdepth;
// Audio specific.
channelCount = builder.channelCount;
sampleRate = builder.sampleRate;
@@ -1092,6 +1130,10 @@ public final class Format implements Bundleable {
+ ", "
+ frameRate
+ ", "
+ + lumaBitdepth
+ + ", "
+ + chromaBitdepth
+ + ", "
+ colorInfo
+ "]"
+ ", ["
@@ -1132,6 +1174,8 @@ public final class Format implements Bundleable {
// [Omitted] projectionData.
result = 31 * result + stereoMode;
// [Omitted] colorInfo.
+ result = 31 * result + lumaBitdepth;
+ result = 31 * result + chromaBitdepth;
// Audio specific.
result = 31 * result + channelCount;
result = 31 * result + sampleRate;
@@ -1173,6 +1217,8 @@ public final class Format implements Bundleable {
&& height == other.height
&& rotationDegrees == other.rotationDegrees
&& stereoMode == other.stereoMode
+ && lumaBitdepth == other.lumaBitdepth
+ && chromaBitdepth == other.chromaBitdepth
&& channelCount == other.channelCount
&& sampleRate == other.sampleRate
&& pcmEncoding == other.pcmEncoding
@@ -1259,6 +1305,9 @@ public final class Format implements Bundleable {
if (format.width != NO_VALUE && format.height != NO_VALUE) {
builder.append(", res=").append(format.width).append("x").append(format.height);
}
+ if (format.lumaBitdepth != NO_VALUE && format.chromaBitdepth != NO_VALUE) {
+ builder.append(", bitdepth=[").append(format.lumaBitdepth).append(",").append(format.chromaBitdepth).append(']');
+ }
if (format.colorInfo != null && format.colorInfo.isValid()) {
builder.append(", color=").append(format.colorInfo.toLogString());
}
@@ -1373,15 +1422,17 @@ public final class Format implements Bundleable {
private static final String FIELD_PROJECTION_DATA = Util.intToStringMaxRadix(20);
private static final String FIELD_STEREO_MODE = Util.intToStringMaxRadix(21);
private static final String FIELD_COLOR_INFO = Util.intToStringMaxRadix(22);
- private static final String FIELD_CHANNEL_COUNT = Util.intToStringMaxRadix(23);
- private static final String FIELD_SAMPLE_RATE = Util.intToStringMaxRadix(24);
- private static final String FIELD_PCM_ENCODING = Util.intToStringMaxRadix(25);
- private static final String FIELD_ENCODER_DELAY = Util.intToStringMaxRadix(26);
- private static final String FIELD_ENCODER_PADDING = Util.intToStringMaxRadix(27);
- private static final String FIELD_ACCESSIBILITY_CHANNEL = Util.intToStringMaxRadix(28);
- private static final String FIELD_CRYPTO_TYPE = Util.intToStringMaxRadix(29);
- private static final String FIELD_TILE_COUNT_HORIZONTAL = Util.intToStringMaxRadix(30);
- private static final String FIELD_TILE_COUNT_VERTICAL = Util.intToStringMaxRadix(31);
+ private static final String FIELD_LUMA_BITDEPTH = Util.intToStringMaxRadix(23);
+ private static final String FIELD_CHROMA_BITDEPTH = Util.intToStringMaxRadix(24);
+ private static final String FIELD_CHANNEL_COUNT = Util.intToStringMaxRadix(25);
+ private static final String FIELD_SAMPLE_RATE = Util.intToStringMaxRadix(26);
+ private static final String FIELD_PCM_ENCODING = Util.intToStringMaxRadix(27);
+ private static final String FIELD_ENCODER_DELAY = Util.intToStringMaxRadix(28);
+ private static final String FIELD_ENCODER_PADDING = Util.intToStringMaxRadix(29);
+ private static final String FIELD_ACCESSIBILITY_CHANNEL = Util.intToStringMaxRadix(30);
+ private static final String FIELD_CRYPTO_TYPE = Util.intToStringMaxRadix(31);
+ private static final String FIELD_TILE_COUNT_HORIZONTAL = Util.intToStringMaxRadix(32);
+ private static final String FIELD_TILE_COUNT_VERTICAL = Util.intToStringMaxRadix(33);
@UnstableApi
@Override
@@ -1431,6 +1482,8 @@ public final class Format implements Bundleable {
if (colorInfo != null) {
bundle.putBundle(FIELD_COLOR_INFO, colorInfo.toBundle());
}
+ bundle.putInt(FIELD_LUMA_BITDEPTH, lumaBitdepth);
+ bundle.putInt(FIELD_CHROMA_BITDEPTH, chromaBitdepth);
// Audio specific.
bundle.putInt(FIELD_CHANNEL_COUNT, channelCount);
bundle.putInt(FIELD_SAMPLE_RATE, sampleRate);
@@ -1496,6 +1549,8 @@ public final class Format implements Bundleable {
if (colorInfoBundle != null) {
builder.setColorInfo(ColorInfo.CREATOR.fromBundle(colorInfoBundle));
}
+ builder.setLumaBitdepth(bundle.getInt(FIELD_LUMA_BITDEPTH, DEFAULT.lumaBitdepth));
+ builder.setChromaBitdepth(bundle.getInt(FIELD_CHROMA_BITDEPTH, DEFAULT.chromaBitdepth));
// Audio specific.
builder
.setChannelCount(bundle.getInt(FIELD_CHANNEL_COUNT, DEFAULT.channelCount))
diff --git a/libraries/container/src/main/java/androidx/media3/container/NalUnitUtil.java b/libraries/container/src/main/java/androidx/media3/container/NalUnitUtil.java
index 635b189c51..5da2bc43bf 100644
--- a/libraries/container/src/main/java/androidx/media3/container/NalUnitUtil.java
+++ b/libraries/container/src/main/java/androidx/media3/container/NalUnitUtil.java
@@ -66,6 +66,8 @@ public final class NalUnitUtil {
public final int width;
public final int height;
public final float pixelWidthHeightRatio;
+ public final int bitDepthLumaMinus8;
+ public final int bitDepthChromaMinus8;
public final boolean separateColorPlaneFlag;
public final boolean frameMbsOnlyFlag;
public final int frameNumLength;
@@ -85,6 +87,8 @@ public final class NalUnitUtil {
int width,
int height,
float pixelWidthHeightRatio,
+ int bitDepthLumaMinus8,
+ int bitDepthChromaMinus8,
boolean separateColorPlaneFlag,
boolean frameMbsOnlyFlag,
int frameNumLength,
@@ -102,6 +106,8 @@ public final class NalUnitUtil {
this.width = width;
this.height = height;
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
+ this.bitDepthLumaMinus8 = bitDepthLumaMinus8;
+ this.bitDepthChromaMinus8 = bitDepthChromaMinus8;
this.separateColorPlaneFlag = separateColorPlaneFlag;
this.frameMbsOnlyFlag = frameMbsOnlyFlag;
this.frameNumLength = frameNumLength;
@@ -382,6 +388,8 @@ public final class NalUnitUtil {
int chromaFormatIdc = 1; // Default is 4:2:0
boolean separateColorPlaneFlag = false;
+ int bitDepthLumaMinus8 = 0;
+ int bitDepthChromaMinus8 = 0;
if (profileIdc == 100
|| profileIdc == 110
|| profileIdc == 122
@@ -396,8 +404,8 @@ public final class NalUnitUtil {
if (chromaFormatIdc == 3) {
separateColorPlaneFlag = data.readBit();
}
- data.readUnsignedExpGolombCodedInt(); // bit_depth_luma_minus8
- data.readUnsignedExpGolombCodedInt(); // bit_depth_chroma_minus8
+ bitDepthLumaMinus8 = data.readUnsignedExpGolombCodedInt();
+ bitDepthChromaMinus8 = data.readUnsignedExpGolombCodedInt();
data.skipBit(); // qpprime_y_zero_transform_bypass_flag
boolean seqScalingMatrixPresentFlag = data.readBit();
if (seqScalingMatrixPresentFlag) {
@@ -511,6 +519,8 @@ public final class NalUnitUtil {
frameWidth,
frameHeight,
pixelWidthHeightRatio,
+ bitDepthLumaMinus8,
+ bitDepthChromaMinus8,
separateColorPlaneFlag,
frameMbsOnlyFlag,
frameNumLength,
diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/util/DebugTextViewHelper.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/util/DebugTextViewHelper.java
index 08a42bfc5c..0b06841a2e 100644
--- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/util/DebugTextViewHelper.java
+++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/util/DebugTextViewHelper.java
@@ -139,6 +139,7 @@ public class DebugTextViewHelper {
+ format.width
+ "x"
+ format.height
+ + getBitdepthInfoString(format.lumaBitdepth)
+ getColorInfoString(format.colorInfo)
+ getPixelAspectRatioString(format.pixelWidthHeightRatio)
+ getDecoderCountersBufferCountString(decoderCounters)
@@ -188,6 +189,10 @@ public class DebugTextViewHelper {
+ counters.droppedToKeyframeCount;
}
+ private static String getBitdepthInfoString(int lumaBitdepth) {
+ return lumaBitdepth != -1 ? " b:" + lumaBitdepth : "";
+ }
+
private static String getColorInfoString(@Nullable ColorInfo colorInfo) {
return colorInfo != null && colorInfo.isValid() ? " colr:" + colorInfo.toLogString() : "";
}
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/AvcConfig.java b/libraries/extractor/src/main/java/androidx/media3/extractor/AvcConfig.java
index 0de91bb649..3a813705dd 100644
--- a/libraries/extractor/src/main/java/androidx/media3/extractor/AvcConfig.java
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/AvcConfig.java
@@ -58,6 +58,8 @@ public final class AvcConfig {
int width = Format.NO_VALUE;
int height = Format.NO_VALUE;
+ int bitdepthLuma = Format.NO_VALUE;
+ int bitdepthChroma = Format.NO_VALUE;
@C.ColorSpace int colorSpace = Format.NO_VALUE;
@C.ColorRange int colorRange = Format.NO_VALUE;
@C.ColorTransfer int colorTransfer = Format.NO_VALUE;
@@ -70,6 +72,8 @@ public final class AvcConfig {
initializationData.get(0), nalUnitLengthFieldLength, sps.length);
width = spsData.width;
height = spsData.height;
+ bitdepthLuma = spsData.bitDepthLumaMinus8 + 8;
+ bitdepthChroma = spsData.bitDepthChromaMinus8 + 8;
colorSpace = spsData.colorSpace;
colorRange = spsData.colorRange;
colorTransfer = spsData.colorTransfer;
@@ -84,6 +88,8 @@ public final class AvcConfig {
nalUnitLengthFieldLength,
width,
height,
+ bitdepthLuma,
+ bitdepthChroma,
colorSpace,
colorRange,
colorTransfer,
@@ -110,6 +116,12 @@ public final class AvcConfig {
/** The height of each decoded frame, or {@link Format#NO_VALUE} if unknown. */
public final int height;
+ /** The bit depth of the luma samples, or {@link Format#NO_VALUE} if unknown. */
+ public final int bitdepthLuma;
+
+ /** The bit depth of the chroma samples, or {@link Format#NO_VALUE} if unknown. */
+ public final int bitdepthChroma;
+
/**
* The {@link C.ColorSpace} of the video, or {@link Format#NO_VALUE} if unknown or not applicable.
*/
@@ -141,6 +153,8 @@ public final class AvcConfig {
int nalUnitLengthFieldLength,
int width,
int height,
+ int bitdepthLuma,
+ int bitdepthChroma,
@C.ColorSpace int colorSpace,
@C.ColorRange int colorRange,
@C.ColorTransfer int colorTransfer,
@@ -150,6 +164,8 @@ public final class AvcConfig {
this.nalUnitLengthFieldLength = nalUnitLengthFieldLength;
this.width = width;
this.height = height;
+ this.bitdepthLuma = bitdepthLuma;
+ this.bitdepthChroma = bitdepthChroma;
this.colorSpace = colorSpace;
this.colorRange = colorRange;
this.colorTransfer = colorTransfer;
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/HevcConfig.java b/libraries/extractor/src/main/java/androidx/media3/extractor/HevcConfig.java
index fa9674ac74..81ae354fd0 100644
--- a/libraries/extractor/src/main/java/androidx/media3/extractor/HevcConfig.java
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/HevcConfig.java
@@ -63,6 +63,8 @@ public final class HevcConfig {
int bufferPosition = 0;
int width = Format.NO_VALUE;
int height = Format.NO_VALUE;
+ int bitdepthLuma = Format.NO_VALUE;
+ int bitdepthChroma = Format.NO_VALUE;
@C.ColorSpace int colorSpace = Format.NO_VALUE;
@C.ColorRange int colorRange = Format.NO_VALUE;
@C.ColorTransfer int colorTransfer = Format.NO_VALUE;
@@ -89,6 +91,8 @@ public final class HevcConfig {
buffer, bufferPosition, bufferPosition + nalUnitLength);
width = spsData.width;
height = spsData.height;
+ bitdepthLuma = spsData.bitDepthLumaMinus8 + 8;
+ bitdepthChroma = spsData.bitDepthChromaMinus8 + 8;
colorSpace = spsData.colorSpace;
colorRange = spsData.colorRange;
colorTransfer = spsData.colorTransfer;
@@ -114,6 +118,8 @@ public final class HevcConfig {
lengthSizeMinusOne + 1,
width,
height,
+ bitdepthLuma,
+ bitdepthChroma,
colorSpace,
colorRange,
colorTransfer,
@@ -142,6 +148,12 @@ public final class HevcConfig {
/** The height of each decoded frame, or {@link Format#NO_VALUE} if unknown. */
public final int height;
+ /** The bit depth of the luma samples, or {@link Format#NO_VALUE} if unknown. */
+ public final int bitdepthLuma;
+
+ /** The bit depth of the chroma samples, or {@link Format#NO_VALUE} if unknown. */
+ public final int bitdepthChroma;
+
/**
* The {@link C.ColorSpace} of the video or {@link Format#NO_VALUE} if unknown or not applicable.
*/
@@ -173,6 +185,8 @@ public final class HevcConfig {
int nalUnitLengthFieldLength,
int width,
int height,
+ int bitdepthLuma,
+ int bitdepthChroma,
@C.ColorSpace int colorSpace,
@C.ColorRange int colorRange,
@C.ColorTransfer int colorTransfer,
@@ -182,6 +196,8 @@ public final class HevcConfig {
this.nalUnitLengthFieldLength = nalUnitLengthFieldLength;
this.width = width;
this.height = height;
+ this.bitdepthLuma = bitdepthLuma;
+ this.bitdepthChroma = bitdepthChroma;
this.colorSpace = colorSpace;
this.colorRange = colorRange;
this.colorTransfer = colorTransfer;
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mkv/MatroskaExtractor.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mkv/MatroskaExtractor.java
index 03f897629b..fe207d2243 100644
--- a/libraries/extractor/src/main/java/androidx/media3/extractor/mkv/MatroskaExtractor.java
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mkv/MatroskaExtractor.java
@@ -232,6 +232,7 @@ public class MatroskaExtractor implements Extractor {
private static final int ID_STEREO_MODE = 0x53B8;
private static final int ID_COLOUR = 0x55B0;
private static final int ID_COLOUR_RANGE = 0x55B9;
+ private static final int ID_COLOUR_BITS_PER_CHANNEL = 0x55B2;
private static final int ID_COLOUR_TRANSFER = 0x55BA;
private static final int ID_COLOUR_PRIMARIES = 0x55BB;
private static final int ID_MAX_CLL = 0x55BC;
@@ -608,6 +609,7 @@ public class MatroskaExtractor implements Extractor {
case ID_CUE_CLUSTER_POSITION:
case ID_REFERENCE_BLOCK:
case ID_STEREO_MODE:
+ case ID_COLOUR_BITS_PER_CHANNEL:
case ID_COLOUR_RANGE:
case ID_COLOUR_TRANSFER:
case ID_COLOUR_PRIMARIES:
@@ -1017,6 +1019,10 @@ public class MatroskaExtractor implements Extractor {
currentTrack.colorTransfer = colorTransfer;
}
break;
+ case ID_COLOUR_BITS_PER_CHANNEL:
+ assertInTrackEntry(id);
+ currentTrack.bitsPerChannel = (int)value;
+ break;
case ID_COLOUR_RANGE:
assertInTrackEntry(id);
switch ((int) value) {
@@ -2013,6 +2019,7 @@ public class MatroskaExtractor implements Extractor {
// Video elements.
public int width = Format.NO_VALUE;
public int height = Format.NO_VALUE;
+ public int bitsPerChannel = Format.NO_VALUE;
public int displayWidth = Format.NO_VALUE;
public int displayHeight = Format.NO_VALUE;
public int displayUnit = DISPLAY_UNIT_PIXELS;
@@ -2325,6 +2332,8 @@ public class MatroskaExtractor implements Extractor {
formatBuilder
.setWidth(width)
.setHeight(height)
+ .setLumaBitdepth(bitsPerChannel)
+ .setChromaBitdepth(bitsPerChannel)
.setPixelWidthHeightRatio(pixelWidthHeightRatio)
.setRotationDegrees(rotationDegrees)
.setProjectionData(projectionData)
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java
index a40f9a78b9..f87db2d364 100644
--- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/AtomParsers.java
@@ -1111,6 +1111,9 @@ import java.util.List;
int height = parent.readUnsignedShort();
boolean pixelWidthHeightRatioFromPasp = false;
float pixelWidthHeightRatio = 1;
+ // Set default luma and chroma bit depths to 8 as old codecs might not even signal them
+ int bitdepthLuma = 8;
+ int bitdepthChroma = 8;
parent.skipBytes(50);
int childPosition = parent.getPosition();
@@ -1177,6 +1180,8 @@ import java.util.List;
colorSpace = avcConfig.colorSpace;
colorRange = avcConfig.colorRange;
colorTransfer = avcConfig.colorTransfer;
+ bitdepthLuma = avcConfig.bitdepthLuma;
+ bitdepthChroma = avcConfig.bitdepthChroma;
} else if (childAtomType == Atom.TYPE_hvcC) {
ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null);
mimeType = MimeTypes.VIDEO_H265;
@@ -1191,6 +1196,8 @@ import java.util.List;
colorSpace = hevcConfig.colorSpace;
colorRange = hevcConfig.colorRange;
colorTransfer = hevcConfig.colorTransfer;
+ bitdepthLuma = hevcConfig.bitdepthLuma;
+ bitdepthChroma = hevcConfig.bitdepthChroma;
} else if (childAtomType == Atom.TYPE_dvcC || childAtomType == Atom.TYPE_dvvC) {
@Nullable DolbyVisionConfig dolbyVisionConfig = DolbyVisionConfig.parse(parent);
if (dolbyVisionConfig != null) {
@@ -1203,7 +1210,10 @@ import java.util.List;
parent.setPosition(childStartPosition + Atom.FULL_HEADER_SIZE);
// See vpcC atom syntax: https://www.webmproject.org/vp9/mp4/#syntax_1
parent.skipBytes(2); // profile(8), level(8)
- boolean fullRangeFlag = (parent.readUnsignedByte() & 1) != 0;
+ int byte3 = parent.readUnsignedByte();
+ bitdepthLuma = byte3 >> 4;
+ bitdepthChroma = bitdepthLuma;
+ boolean fullRangeFlag = (byte3 & 0b1) != 0;
int colorPrimaries = parent.readUnsignedByte();
int transferCharacteristics = parent.readUnsignedByte();
colorSpace = ColorInfo.isoColorPrimariesToColorSpace(colorPrimaries);
@@ -1213,6 +1223,22 @@ import java.util.List;
} else if (childAtomType == Atom.TYPE_av1C) {
ExtractorUtil.checkContainerInput(mimeType == null, /* message= */ null);
mimeType = MimeTypes.VIDEO_AV1;
+ parent.setPosition(childStartPosition + Atom.HEADER_SIZE);
+ if (childAtomSize > Atom.HEADER_SIZE) {
+ parent.skipBytes(1); ; // marker(1), version(7)
+ int byte2 = parent.readUnsignedByte();
+ int seqProfile = byte2 >> 5;
+ int byte3 = parent.readUnsignedByte();
+ boolean highBitdepth = ((byte3 >> 6) & 0b1) != 0;
+ boolean twelveBit = ((byte3 >> 5) & 0b1) != 0;
+ // From https://aomediacodec.github.io/av1-spec/av1-spec.pdf#page=44
+ if (seqProfile == 2 && highBitdepth) {
+ bitdepthLuma = twelveBit ? 12 : 10;
+ } else if (seqProfile <= 2) {
+ bitdepthLuma = highBitdepth ? 10 : 8;
+ }
+ bitdepthChroma = bitdepthLuma;
+ }
} else if (childAtomType == Atom.TYPE_clli) {
if (hdrStaticInfo == null) {
hdrStaticInfo = allocateHdrStaticInfo();
@@ -1334,6 +1360,8 @@ import java.util.List;
.setCodecs(codecs)
.setWidth(width)
.setHeight(height)
+ .setLumaBitdepth(bitdepthLuma)
+ .setChromaBitdepth(bitdepthChroma)
.setPixelWidthHeightRatio(pixelWidthHeightRatio)
.setRotationDegrees(rotationDegrees)
.setProjectionData(projectionData)
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/ts/H264Reader.java b/libraries/extractor/src/main/java/androidx/media3/extractor/ts/H264Reader.java
index 147af676be..9c90117b1d 100644
--- a/libraries/extractor/src/main/java/androidx/media3/extractor/ts/H264Reader.java
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/ts/H264Reader.java
@@ -219,6 +219,8 @@ public final class H264Reader implements ElementaryStreamReader {
.setCodecs(codecs)
.setWidth(spsData.width)
.setHeight(spsData.height)
+ .setLumaBitdepth(spsData.bitDepthLumaMinus8 + 8)
+ .setChromaBitdepth(spsData.bitDepthChromaMinus8 + 8)
.setPixelWidthHeightRatio(spsData.pixelWidthHeightRatio)
.setInitializationData(initializationData)
.build());
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/ts/H265Reader.java b/libraries/extractor/src/main/java/androidx/media3/extractor/ts/H265Reader.java
index c1e3d4ccb1..930151a5a9 100644
--- a/libraries/extractor/src/main/java/androidx/media3/extractor/ts/H265Reader.java
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/ts/H265Reader.java
@@ -264,6 +264,8 @@ public final class H265Reader implements ElementaryStreamReader {
.setCodecs(codecs)
.setWidth(spsData.width)
.setHeight(spsData.height)
+ .setLumaBitdepth(spsData.bitDepthLumaMinus8 + 8)
+ .setChromaBitdepth(spsData.bitDepthChromaMinus8 + 8)
.setPixelWidthHeightRatio(spsData.pixelWidthHeightRatio)
.setInitializationData(Collections.singletonList(csdData))
.build();