H.265 parse number of temporal layers from SPS

Expose NalUnitUtil.H265SpsData.maxSubLayersMinus1
Required for H.265 non-reference frame identification as
only frames from the highest temporal sub-layer can be
discarded.

PiperOrigin-RevId: 713232825
This commit is contained in:
dancho 2025-01-08 03:46:17 -08:00 committed by Copybara-Service
parent 1bea11637b
commit b3e18729d3
2 changed files with 11 additions and 0 deletions

View file

@ -384,6 +384,7 @@ public final class NalUnitUtil {
public static final class H265SpsData { public static final class H265SpsData {
public final H265NalHeader nalHeader; public final H265NalHeader nalHeader;
public final int maxSubLayersMinus1;
@Nullable public final H265ProfileTierLevel profileTierLevel; @Nullable public final H265ProfileTierLevel profileTierLevel;
public final int chromaFormatIdc; public final int chromaFormatIdc;
public final int bitDepthLumaMinus8; public final int bitDepthLumaMinus8;
@ -399,6 +400,7 @@ public final class NalUnitUtil {
public H265SpsData( public H265SpsData(
H265NalHeader nalHeader, H265NalHeader nalHeader,
int maxSubLayersMinus1,
@Nullable H265ProfileTierLevel profileTierLevel, @Nullable H265ProfileTierLevel profileTierLevel,
int chromaFormatIdc, int chromaFormatIdc,
int bitDepthLumaMinus8, int bitDepthLumaMinus8,
@ -412,6 +414,7 @@ public final class NalUnitUtil {
@C.ColorRange int colorRange, @C.ColorRange int colorRange,
@C.ColorTransfer int colorTransfer) { @C.ColorTransfer int colorTransfer) {
this.nalHeader = nalHeader; this.nalHeader = nalHeader;
this.maxSubLayersMinus1 = maxSubLayersMinus1;
this.profileTierLevel = profileTierLevel; this.profileTierLevel = profileTierLevel;
this.chromaFormatIdc = chromaFormatIdc; this.chromaFormatIdc = chromaFormatIdc;
this.bitDepthLumaMinus8 = bitDepthLumaMinus8; this.bitDepthLumaMinus8 = bitDepthLumaMinus8;
@ -1638,6 +1641,7 @@ public final class NalUnitUtil {
return new H265SpsData( return new H265SpsData(
nalHeader, nalHeader,
maxSubLayersMinus1,
profileTierLevel, profileTierLevel,
chromaFormatIdc, chromaFormatIdc,
bitDepthLumaMinus8, bitDepthLumaMinus8,

View file

@ -218,6 +218,7 @@ public final class NalUnitUtilTest {
NalUnitUtil.parseH265SpsNalUnit( NalUnitUtil.parseH265SpsNalUnit(
H265_SPS_TEST_DATA, /* nalOffset= */ 0, H265_SPS_TEST_DATA.length, vpsData); H265_SPS_TEST_DATA, /* nalOffset= */ 0, H265_SPS_TEST_DATA.length, vpsData);
assertThat(spsData.nalHeader.layerId).isEqualTo(0); assertThat(spsData.nalHeader.layerId).isEqualTo(0);
assertThat(spsData.maxSubLayersMinus1).isEqualTo(0);
assertThat(spsData.profileTierLevel.generalProfileIdc).isEqualTo(2); assertThat(spsData.profileTierLevel.generalProfileIdc).isEqualTo(2);
assertThat(spsData.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(4); assertThat(spsData.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(4);
assertThat(spsData.profileTierLevel.generalLevelIdc).isEqualTo(153); assertThat(spsData.profileTierLevel.generalLevelIdc).isEqualTo(153);
@ -270,6 +271,7 @@ public final class NalUnitUtilTest {
H265_SPS_TEST_DATA_2VIEWS_VIEW_0.length, H265_SPS_TEST_DATA_2VIEWS_VIEW_0.length,
vpsData); vpsData);
assertThat(spsDataView0.nalHeader.layerId).isEqualTo(0); assertThat(spsDataView0.nalHeader.layerId).isEqualTo(0);
assertThat(spsDataView0.maxSubLayersMinus1).isEqualTo(0);
assertThat(spsDataView0.profileTierLevel.generalProfileIdc).isEqualTo(1); assertThat(spsDataView0.profileTierLevel.generalProfileIdc).isEqualTo(1);
assertThat(spsDataView0.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(6); assertThat(spsDataView0.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(6);
assertThat(spsDataView0.profileTierLevel.generalLevelIdc).isEqualTo(120); assertThat(spsDataView0.profileTierLevel.generalLevelIdc).isEqualTo(120);
@ -289,6 +291,7 @@ public final class NalUnitUtilTest {
H265_SPS_TEST_DATA_2VIEWS_VIEW_1.length, H265_SPS_TEST_DATA_2VIEWS_VIEW_1.length,
vpsData); vpsData);
assertThat(spsDataView1.nalHeader.layerId).isEqualTo(1); assertThat(spsDataView1.nalHeader.layerId).isEqualTo(1);
assertThat(spsDataView1.maxSubLayersMinus1).isEqualTo(7);
assertThat(spsDataView1.profileTierLevel.generalProfileIdc).isEqualTo(6); assertThat(spsDataView1.profileTierLevel.generalProfileIdc).isEqualTo(6);
assertThat(spsDataView1.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(64); assertThat(spsDataView1.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(64);
assertThat(spsDataView1.profileTierLevel.generalLevelIdc).isEqualTo(120); assertThat(spsDataView1.profileTierLevel.generalLevelIdc).isEqualTo(120);
@ -351,6 +354,7 @@ public final class NalUnitUtilTest {
H265_SPS_TEST_DATA_2VIEWS_HDR_VIEW_0.length, H265_SPS_TEST_DATA_2VIEWS_HDR_VIEW_0.length,
vpsData); vpsData);
assertThat(spsDataView0.nalHeader.layerId).isEqualTo(0); assertThat(spsDataView0.nalHeader.layerId).isEqualTo(0);
assertThat(spsDataView0.maxSubLayersMinus1).isEqualTo(0);
assertThat(spsDataView0.profileTierLevel.generalProfileIdc).isEqualTo(2); assertThat(spsDataView0.profileTierLevel.generalProfileIdc).isEqualTo(2);
assertThat(spsDataView0.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(4); assertThat(spsDataView0.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(4);
assertThat(spsDataView0.profileTierLevel.generalLevelIdc).isEqualTo(153); assertThat(spsDataView0.profileTierLevel.generalLevelIdc).isEqualTo(153);
@ -367,6 +371,7 @@ public final class NalUnitUtilTest {
H265_SPS_TEST_DATA_2VIEWS_HDR_VIEW_1.length, H265_SPS_TEST_DATA_2VIEWS_HDR_VIEW_1.length,
vpsData); vpsData);
assertThat(spsDataView1.nalHeader.layerId).isEqualTo(1); assertThat(spsDataView1.nalHeader.layerId).isEqualTo(1);
assertThat(spsDataView1.maxSubLayersMinus1).isEqualTo(7);
assertThat(spsDataView1.profileTierLevel.generalProfileIdc).isEqualTo(6); assertThat(spsDataView1.profileTierLevel.generalProfileIdc).isEqualTo(6);
assertThat(spsDataView1.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(68); assertThat(spsDataView1.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(68);
assertThat(spsDataView1.profileTierLevel.generalLevelIdc).isEqualTo(153); assertThat(spsDataView1.profileTierLevel.generalLevelIdc).isEqualTo(153);
@ -436,6 +441,7 @@ public final class NalUnitUtilTest {
NalUnitUtil.parseH265SpsNalUnitPayload( NalUnitUtil.parseH265SpsNalUnitPayload(
spsNalUnitPayload, 0, spsNalUnitPayload.length, nalHeader, null); spsNalUnitPayload, 0, spsNalUnitPayload.length, nalHeader, null);
assertThat(spsData.maxSubLayersMinus1).isEqualTo(0);
assertThat(spsData.profileTierLevel.constraintBytes).isEqualTo(new int[] {144, 0, 0, 0, 0, 0}); assertThat(spsData.profileTierLevel.constraintBytes).isEqualTo(new int[] {144, 0, 0, 0, 0, 0});
assertThat(spsData.profileTierLevel.generalLevelIdc).isEqualTo(150); assertThat(spsData.profileTierLevel.generalLevelIdc).isEqualTo(150);
assertThat(spsData.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(4); assertThat(spsData.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(4);
@ -468,6 +474,7 @@ public final class NalUnitUtilTest {
NalUnitUtil.parseH265SpsNalUnitPayload( NalUnitUtil.parseH265SpsNalUnitPayload(
spsNalUnitPayload, 0, spsNalUnitPayload.length, nalHeader, null); spsNalUnitPayload, 0, spsNalUnitPayload.length, nalHeader, null);
assertThat(spsData.maxSubLayersMinus1).isEqualTo(0);
assertThat(spsData.profileTierLevel.constraintBytes).isEqualTo(new int[] {0, 0, 0, 0, 0, 0}); assertThat(spsData.profileTierLevel.constraintBytes).isEqualTo(new int[] {0, 0, 0, 0, 0, 0});
assertThat(spsData.profileTierLevel.generalLevelIdc).isEqualTo(150); assertThat(spsData.profileTierLevel.generalLevelIdc).isEqualTo(150);
assertThat(spsData.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(6); assertThat(spsData.profileTierLevel.generalProfileCompatibilityFlags).isEqualTo(6);