From 0f665fbeb8fca52853ab5dd0a8030484e50402dd Mon Sep 17 00:00:00 2001 From: rohks Date: Tue, 12 Jul 2022 16:53:03 +0000 Subject: [PATCH] Ignore reserved bit in parsing NAL unit type `HevcConfig.parse` misreads reserved bit to determine NAL unit type. This is currently meant to be always set to 0, but could be given some kind of meaning in a future revision. Issue: google/ExoPlayer#10366 PiperOrigin-RevId: 460487613 --- .../android/exoplayer2/video/HevcConfig.java | 5 +- .../exoplayer2/video/HevcConfigTest.java | 90 +++++++++++++++++++ 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java b/library/extractor/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java index 7e688b2e42..6b8e633555 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java @@ -45,7 +45,7 @@ public final class HevcConfig { int csdLength = 0; int csdStartPosition = data.getPosition(); for (int i = 0; i < numberOfArrays; i++) { - data.skipBytes(1); // completeness (1), nal_unit_type (7) + data.skipBytes(1); // completeness (1), reserved (1), nal_unit_type (6) int numberOfNalUnits = data.readUnsignedShort(); for (int j = 0; j < numberOfNalUnits; j++) { int nalUnitLength = data.readUnsignedShort(); @@ -63,7 +63,8 @@ public final class HevcConfig { float pixelWidthHeightRatio = 1; @Nullable String codecs = null; for (int i = 0; i < numberOfArrays; i++) { - int nalUnitType = data.readUnsignedByte() & 0x7F; // completeness (1), nal_unit_type (7) + int nalUnitType = + data.readUnsignedByte() & 0x3F; // completeness (1), reserved (1), nal_unit_type (6) int numberOfNalUnits = data.readUnsignedShort(); for (int j = 0; j < numberOfNalUnits; j++) { int nalUnitLength = data.readUnsignedShort(); diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/video/HevcConfigTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/video/HevcConfigTest.java index a4c312e8f7..d87948bb69 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/video/HevcConfigTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/video/HevcConfigTest.java @@ -162,6 +162,86 @@ public final class HevcConfigTest { 64 }; + private static final byte[] HVCC_BOX_PAYLOAD_WITH_SET_RESERVED_BIT = + new byte[] { + // Header + 1, + 1, + 96, + 0, + 0, + 0, + -80, + 0, + 0, + 0, + 0, + 0, + -103, + -16, + 0, + -4, + -4, + -8, + -8, + 0, + 0, + 15, + + // Number of arrays + 1, + + // NAL unit type = SPS (Ignoring reserved bit) + // completeness (1), reserved (1), nal_unit_type (6) + 97, + // Number of NAL units + 0, + 1, + // NAL unit length + 0, + 39, + // NAL unit + 66, + 1, + 1, + 1, + 96, + 0, + 0, + 3, + 0, + -80, + 0, + 0, + 3, + 0, + 0, + 3, + 0, + -103, + -96, + 1, + -32, + 32, + 2, + 32, + 124, + 78, + 90, + -18, + 76, + -110, + -22, + 86, + 10, + 12, + 12, + 5, + -38, + 20, + 37 + }; + @Test public void parseHevcDecoderConfigurationRecord() throws Exception { ParsableByteArray data = new ParsableByteArray(HVCC_BOX_PAYLOAD); @@ -170,4 +250,14 @@ public final class HevcConfigTest { assertThat(hevcConfig.codecs).isEqualTo("hvc1.1.6.L153.B0"); assertThat(hevcConfig.nalUnitLengthFieldLength).isEqualTo(4); } + + /** https://github.com/google/ExoPlayer/issues/10366 */ + @Test + public void parseHevcDecoderConfigurationRecord_ignoresReservedBit() throws Exception { + ParsableByteArray data = new ParsableByteArray(HVCC_BOX_PAYLOAD_WITH_SET_RESERVED_BIT); + HevcConfig hevcConfig = HevcConfig.parse(data); + + assertThat(hevcConfig.codecs).isEqualTo("hvc1.1.6.L153.B0"); + assertThat(hevcConfig.nalUnitLengthFieldLength).isEqualTo(4); + } }