Populate HevcConfig with number of temporal layers

The number of temporal sub-layers is required for
H.265 non-reference frame identification as
only frames from the highest temporal sub-layer can be
discarded.

PiperOrigin-RevId: 713242894
This commit is contained in:
dancho 2025-01-08 04:27:54 -08:00 committed by Copybara-Service
parent b3e18729d3
commit 281a0e7ac8
2 changed files with 12 additions and 0 deletions

View File

@ -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<byte[]> 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;

View File

@ -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);
}