NalUnitUtil { public static int findNalUnit(byte[] data, int startOffset, int endOffset, boolean[] prefixFlags) { int length = endOffset - startOffset; Assertions.checkState(length >= 0); if (length == 0) { return endOffset; } if (prefixFlags != null) { if (prefixFlags[0]) { clearPrefixFlags(prefixFlags); return startOffset - 3; } else if (length > 1 && prefixFlags[1] && data[startOffset] == 1) { clearPrefixFlags(prefixFlags); return startOffset - 2; } else if (length > 2 && prefixFlags[2] && data[startOffset] == 0 && data[startOffset + 1] == 1) { clearPrefixFlags(prefixFlags); return startOffset - 1; } } int limit = endOffset - 1; for (int i = startOffset + 2; i < limit; i += 3) { if ((data[i] & 0xFE) != 0) { } else if (data[i - 2] == 0 && data[i - 1] == 0 && data[i] == 1) { if (prefixFlags != null) { clearPrefixFlags(prefixFlags); } return i - 2; } else { i -= 2; } } if (prefixFlags != null) { prefixFlags[0] = length > 2 ? (data[endOffset - 3] == 0 && data[endOffset - 2] == 0 && data[endOffset - 1] == 1) : length == 2 ? (prefixFlags[2] && data[endOffset - 2] == 0 && data[endOffset - 1] == 1) : (prefixFlags[1] && data[endOffset - 1] == 1); prefixFlags[1] = length > 1 ? data[endOffset - 2] == 0 && data[endOffset - 1] == 0 : prefixFlags[2] && data[endOffset - 1] == 0; prefixFlags[2] = data[endOffset - 1] == 0; } return endOffset; } private  NalUnitUtil(); static int unescapeStream(byte[] data, int limit); static void discardToSps(ByteBuffer data); static boolean isNalUnitSei(String mimeType, byte nalUnitHeaderFirstByte); static int getNalUnitType(byte[] data, int offset); static int getH265NalUnitType(byte[] data, int offset); static SpsData parseSpsNalUnit(byte[] nalData, int nalOffset, int nalLimit); static PpsData parsePpsNalUnit(byte[] nalData, int nalOffset, int nalLimit); static int findNalUnit(byte[] data, int startOffset, int endOffset,
      boolean[] prefixFlags); static void clearPrefixFlags(boolean[] prefixFlags); static final byte[] NAL_START_CODE; static final int EXTENDED_SAR; static final float[] ASPECT_RATIO_IDC_VALUES; }
@Test public void testFindNalUnit() { byte[] data = buildTestData(); int result = NalUnitUtil.findNalUnit(data, 0, data.length, null); assertThat(result).isEqualTo(TEST_NAL_POSITION); result = NalUnitUtil.findNalUnit(data, 0, TEST_NAL_POSITION + 4, null); assertThat(result).isEqualTo(TEST_NAL_POSITION); result = NalUnitUtil.findNalUnit(data, 0, TEST_NAL_POSITION + 3, null); assertThat(result).isEqualTo(TEST_NAL_POSITION + 3); result = NalUnitUtil.findNalUnit(data, TEST_NAL_POSITION, data.length, null); assertThat(result).isEqualTo(TEST_NAL_POSITION); result = NalUnitUtil.findNalUnit(data, TEST_NAL_POSITION + 1, data.length, null); assertThat(result).isEqualTo(data.length); }
@Test public void testFindNalUnitWithPrefix() { byte[] data = buildTestData(); boolean[] prefixFlags = new boolean[3]; byte[] data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 1); byte[] data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 1, data.length); int result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags); assertThat(result).isEqualTo(data1.length); result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags); assertThat(result).isEqualTo(-1); assertPrefixFlagsCleared(prefixFlags); prefixFlags = new boolean[3]; data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 3); data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 3, data.length); result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags); assertThat(result).isEqualTo(data1.length); result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags); assertThat(result).isEqualTo(-3); assertPrefixFlagsCleared(prefixFlags); prefixFlags = new boolean[3]; data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 1); data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 1, TEST_NAL_POSITION + 2); byte[] data3 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 2, data.length); result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags); assertThat(result).isEqualTo(data1.length); result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags); assertThat(result).isEqualTo(data2.length); result = NalUnitUtil.findNalUnit(data3, 0, data3.length, prefixFlags); assertThat(result).isEqualTo(-2); assertPrefixFlagsCleared(prefixFlags); prefixFlags = new boolean[3]; data1 = Arrays.copyOfRange(data, 0, TEST_NAL_POSITION + 1); data2 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 1, TEST_NAL_POSITION + 2); data3 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 2, TEST_NAL_POSITION + 3); byte[] data4 = Arrays.copyOfRange(data, TEST_NAL_POSITION + 2, data.length); result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags); assertThat(result).isEqualTo(data1.length); result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags); assertThat(result).isEqualTo(data2.length); result = NalUnitUtil.findNalUnit(data3, 0, data3.length, prefixFlags); assertThat(result).isEqualTo(data3.length); result = NalUnitUtil.findNalUnit(data4, 0, data4.length, prefixFlags); assertThat(result).isEqualTo(-3); assertPrefixFlagsCleared(prefixFlags); prefixFlags = new boolean[3]; data1 = Arrays.copyOfRange(data, 0, TEST_PARTIAL_NAL_POSITION + 2); data2 = Arrays.copyOfRange(data, TEST_PARTIAL_NAL_POSITION + 2, data.length); result = NalUnitUtil.findNalUnit(data1, 0, data1.length, prefixFlags); assertThat(result).isEqualTo(data1.length); result = NalUnitUtil.findNalUnit(data2, 0, data2.length, prefixFlags); assertThat(result).isEqualTo(4); assertPrefixFlagsCleared(prefixFlags); }