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 3d20a0382e..682b3630ee 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/HevcConfig.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/HevcConfig.java @@ -95,6 +95,7 @@ public final class HevcConfig { // Concatenate the codec-specific data into a single buffer. data.setPosition(csdStartPosition); byte[] buffer = new byte[csdLength]; + int maxSubLayers = Format.NO_VALUE; int bufferPosition = 0; int width = Format.NO_VALUE; int height = Format.NO_VALUE; @@ -131,6 +132,7 @@ public final class HevcConfig { NalUnitUtil.H265SpsData spsData = NalUnitUtil.parseH265SpsNalUnit( buffer, bufferPosition, bufferPosition + nalUnitLength, currentVpsData); + maxSubLayers = spsData.maxSubLayersMinus1 + 1; width = spsData.width; height = spsData.height; bitdepthLuma = spsData.bitDepthLumaMinus8 + 8; @@ -172,6 +174,7 @@ public final class HevcConfig { return new HevcConfig( initializationData, lengthSizeMinusOne + 1, + maxSubLayers, width, height, bitdepthLuma, @@ -200,6 +203,9 @@ public final class HevcConfig { /** The length of the NAL unit length field in the bitstream's container, in bytes. */ public final int nalUnitLengthFieldLength; + /** The {@code sps_max_sub_layers_minus1 + 1} value: the number of temporal sub-layers. */ + public final int maxSubLayers; + /** The width of each decoded frame, or {@link Format#NO_VALUE} if unknown. */ public final int width; @@ -258,6 +264,7 @@ public final class HevcConfig { private HevcConfig( List initializationData, int nalUnitLengthFieldLength, + int maxSubLayers, int width, int height, int bitdepthLuma, @@ -272,6 +279,7 @@ public final class HevcConfig { @Nullable NalUnitUtil.H265VpsData vpsData) { this.initializationData = initializationData; this.nalUnitLengthFieldLength = nalUnitLengthFieldLength; + this.maxSubLayers = maxSubLayers; this.width = width; this.height = height; this.bitdepthLuma = bitdepthLuma; diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/HevcConfigTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/HevcConfigTest.java index 9130cd54da..4d38e7b560 100644 --- a/libraries/extractor/src/test/java/androidx/media3/extractor/HevcConfigTest.java +++ b/libraries/extractor/src/test/java/androidx/media3/extractor/HevcConfigTest.java @@ -477,6 +477,7 @@ public final class HevcConfigTest { ParsableByteArray data = new ParsableByteArray(HVCC_BOX_PAYLOAD); HevcConfig hevcConfig = HevcConfig.parse(data); + assertThat(hevcConfig.maxSubLayers).isEqualTo(1); assertThat(hevcConfig.codecs).isEqualTo("hvc1.1.6.L153.B0"); assertThat(hevcConfig.nalUnitLengthFieldLength).isEqualTo(4); } @@ -487,6 +488,7 @@ public final class HevcConfigTest { ParsableByteArray data = new ParsableByteArray(HVCC_BOX_PAYLOAD_WITH_SET_RESERVED_BIT); HevcConfig hevcConfig = HevcConfig.parse(data); + assertThat(hevcConfig.maxSubLayers).isEqualTo(1); assertThat(hevcConfig.codecs).isEqualTo("hvc1.1.6.L153.B0"); assertThat(hevcConfig.nalUnitLengthFieldLength).isEqualTo(4); } @@ -496,12 +498,14 @@ public final class HevcConfigTest { ParsableByteArray hevcData = new ParsableByteArray(HVCC_BOX_PAYLOAD_MV_HEVC); HevcConfig hevcConfig = HevcConfig.parse(hevcData); + assertThat(hevcConfig.maxSubLayers).isEqualTo(1); assertThat(hevcConfig.codecs).isEqualTo("hvc1.1.6.L120.B0"); assertThat(hevcConfig.nalUnitLengthFieldLength).isEqualTo(4); ParsableByteArray lhevcData = new ParsableByteArray(LHVC_BOX_PAYLOAD_MV_HEVC); HevcConfig lhevcConfig = HevcConfig.parseLayered(lhevcData, hevcConfig.vpsData); + assertThat(lhevcConfig.maxSubLayers).isEqualTo(8); assertThat(lhevcConfig.codecs).isEqualTo("hvc1.6.40.L120.BF.80"); assertThat(lhevcConfig.nalUnitLengthFieldLength).isEqualTo(4); }