From 0cf52ed45d6403764fd659da0ccc786443a47696 Mon Sep 17 00:00:00 2001 From: dancho Date: Wed, 8 Jan 2025 04:52:02 -0800 Subject: [PATCH] Read sample dependencies for H.265 in MP4 Add a new Mp4Extractor.FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES_H265 Read two bytes from H.265 videos to determine NAL unit type and temporal layer id. PiperOrigin-RevId: 713248154 --- .../media3/container/NalUnitUtil.java | 53 ++++++ .../media3/container/NalUnitUtilTest.java | 18 +++ .../media3/extractor/mp4/Mp4Extractor.java | 65 +++++--- .../mp4/Mp4ExtractorParameterizedTest.java | 6 + .../mp4/h265_bframes.mp4.0.dump | 151 ++++++++++++++++++ .../mp4/h265_bframes.mp4.1.dump | 151 ++++++++++++++++++ .../mp4/h265_bframes.mp4.2.dump | 151 ++++++++++++++++++ .../mp4/h265_bframes.mp4.3.dump | 151 ++++++++++++++++++ ...ding_within_gop_sample_dependencies.0.dump | 151 ++++++++++++++++++ ...ding_within_gop_sample_dependencies.1.dump | 151 ++++++++++++++++++ ...ding_within_gop_sample_dependencies.2.dump | 151 ++++++++++++++++++ ...ding_within_gop_sample_dependencies.3.dump | 151 ++++++++++++++++++ ...op_sample_dependencies.unknown_length.dump | 151 ++++++++++++++++++ .../mp4/h265_bframes.mp4.unknown_length.dump | 151 ++++++++++++++++++ .../test/assets/media/mp4/h265_bframes.mp4 | Bin 0 -> 20634 bytes 15 files changed, 1632 insertions(+), 20 deletions(-) create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.0.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.1.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.2.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.3.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.0.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.1.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.2.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.3.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.unknown_length.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.unknown_length.dump create mode 100644 libraries/test_data/src/test/assets/media/mp4/h265_bframes.mp4 diff --git a/libraries/container/src/main/java/androidx/media3/container/NalUnitUtil.java b/libraries/container/src/main/java/androidx/media3/container/NalUnitUtil.java index 748d5b81ef..4f3fa76e34 100644 --- a/libraries/container/src/main/java/androidx/media3/container/NalUnitUtil.java +++ b/libraries/container/src/main/java/androidx/media3/container/NalUnitUtil.java @@ -681,6 +681,59 @@ public final class NalUnitUtil { return true; } + /** + * Returns the number of bytes needed from the NAL unit to determine whether subsequent NAL units + * can depend on the current NAL unit. + * + * @param format The sample {@link Format}. + */ + public static int numberOfBytesToDetermineSampleDependencies(Format format) { + if (Objects.equals(format.sampleMimeType, MimeTypes.VIDEO_H264)) { + return 1; + } + if (Objects.equals(format.sampleMimeType, MimeTypes.VIDEO_H265)) { + return 2; + } + return 0; + } + + /** + * Returns whether the NAL unit starting with the given bytes can be depended on by subsequent NAL + * units in decoding order. + * + * @param data The array holding the first {@code length} bytes of the NAL unit. + * @param offset The offset in {@code data} at which the NAL unit starts. + * @param length The number of bytes available. + * @param format The sample {@link Format}. + */ + public static boolean isDependedOn(byte[] data, int offset, int length, Format format) { + if (Objects.equals(format.sampleMimeType, MimeTypes.VIDEO_H264)) { + return isH264NalUnitDependedOn(data[offset]); + } + if (Objects.equals(format.sampleMimeType, MimeTypes.VIDEO_H265)) { + return isH265NalUnitDependedOn(data, offset, length, format); + } + return true; + } + + private static boolean isH265NalUnitDependedOn( + byte[] data, int offset, int length, Format format) { + H265NalHeader header = + parseH265NalHeader(new ParsableNalUnitBitArray(data, offset, /* limit= */ offset + length)); + if (header.nalUnitType == H265_NAL_UNIT_TYPE_AUD) { + // NAL unit delimiters are not depended on. + return false; + } + boolean isSubLayerNonReferencePicture = header.nalUnitType <= 14 && header.nalUnitType % 2 == 0; + if (isSubLayerNonReferencePicture && header.temporalId == format.maxSubLayers - 1) { + // Sub-layer non-reference (SLNR) pictures cannot be used for inter prediction in the same + // temporal layer. That is, SLNR pictures are not depended on if they are part of the highest + // temporal layer. + return false; + } + return true; + } + /** * Returns the type of the H.265 NAL unit in {@code data} that starts at {@code offset}. * diff --git a/libraries/container/src/test/java/androidx/media3/container/NalUnitUtilTest.java b/libraries/container/src/test/java/androidx/media3/container/NalUnitUtilTest.java index 334000ac35..fa2cd5a6dc 100644 --- a/libraries/container/src/test/java/androidx/media3/container/NalUnitUtilTest.java +++ b/libraries/container/src/test/java/androidx/media3/container/NalUnitUtilTest.java @@ -15,9 +15,13 @@ */ package androidx.media3.container; +import static androidx.media3.container.NalUnitUtil.isDependedOn; +import static androidx.media3.container.NalUnitUtil.numberOfBytesToDetermineSampleDependencies; import static androidx.media3.test.utils.TestUtil.createByteArray; import static com.google.common.truth.Truth.assertThat; +import androidx.media3.common.Format; +import androidx.media3.common.MimeTypes; import androidx.media3.common.util.Util; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.common.collect.ImmutableList; @@ -494,6 +498,20 @@ public final class NalUnitUtilTest { assertThat(spsData.maxNumReorderPics).isEqualTo(0); } + @Test + public void numberOfBytesToDetermineSampleDependencies_vp8_returnsZero() { + Format vp8Video = new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_VP8).build(); + + assertThat(numberOfBytesToDetermineSampleDependencies(vp8Video)).isEqualTo(0); + } + + @Test + public void isDependedOn_vp8_returnsTrue() { + Format vp8Video = new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_VP8).build(); + + assertThat(isDependedOn(new byte[0], /* offset= */ 0, /* length= */ 0, vp8Video)).isTrue(); + } + private static byte[] buildTestData() { byte[] data = new byte[20]; Arrays.fill(data, (byte) 0xFF); diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Mp4Extractor.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Mp4Extractor.java index 5b51804b0e..3891f27879 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Mp4Extractor.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Mp4Extractor.java @@ -164,6 +164,14 @@ public final class Mp4Extractor implements Extractor, SeekMap { */ public static final int FLAG_READ_AUXILIARY_TRACKS = 1 << 6; + /** + * Flag to extract additional sample dependency information, and mark output buffers with {@link + * C#BUFFER_FLAG_NOT_DEPENDED_ON} for {@linkplain MimeTypes#VIDEO_H265 H.265} video. + * + *

See {@link #FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES}. + */ + public static final int FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES_H265 = 1 << 7; + /** * @deprecated Use {@link #newFactory(SubtitleParser.Factory)} instead. */ @@ -302,13 +310,11 @@ public final class Mp4Extractor implements Extractor, SeekMap { atomHeader = new ParsableByteArray(Mp4Box.LONG_HEADER_SIZE); containerAtoms = new ArrayDeque<>(); nalStartCode = new ParsableByteArray(NalUnitUtil.NAL_START_CODE); - nalPrefix = new ParsableByteArray(5); + nalPrefix = new ParsableByteArray(6); scratch = new ParsableByteArray(); sampleTrackIndex = C.INDEX_UNSET; extractorOutput = ExtractorOutput.PLACEHOLDER; tracks = new Mp4Track[0]; - // Treat all samples as depended on when FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES is unset. - isSampleDependedOn = (flags & FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES) == 0; } @Override @@ -342,8 +348,7 @@ public final class Mp4Extractor implements Extractor, SeekMap { sampleBytesRead = 0; sampleBytesWritten = 0; sampleCurrentNalBytesRemaining = 0; - // Treat all samples as depended on when FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES is unset. - isSampleDependedOn = (flags & FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES) == 0; + isSampleDependedOn = false; if (position == 0) { // Reading the SEF data occurs before normal MP4 parsing. Therefore we can not transition to // reading the atom header until that has completed. @@ -877,8 +882,7 @@ public final class Mp4Extractor implements Extractor, SeekMap { sampleSize -= Mp4Box.HEADER_SIZE; } input.skipFully((int) skipAmount); - // Treat all samples in non-H.264 codecs as depended on. - if (!Objects.equals(track.track.format.sampleMimeType, MimeTypes.VIDEO_H264)) { + if (!canReadWithinGopSampleDependencies(track.track.format)) { isSampleDependedOn = true; } if (track.track.nalUnitLengthFieldLength != 0) { @@ -895,16 +899,19 @@ public final class Mp4Extractor implements Extractor, SeekMap { while (sampleBytesWritten < sampleSize) { if (sampleCurrentNalBytesRemaining == 0) { int nalUnitPrefixLength = track.track.nalUnitLengthFieldLength; - boolean readNalType = false; + int numberOfBytesToDetermineSampleDependencies = 0; if (!isSampleDependedOn - && nalUnitPrefixLength + 1 + && nalUnitPrefixLength + + NalUnitUtil.numberOfBytesToDetermineSampleDependencies(track.track.format) <= track.sampleTable.sizes[sampleIndex] - sampleBytesRead) { - // Parsing sample dependencies needs the first NAL unit byte. Read it in the same + // Parsing sample dependencies needs the first few NAL unit bytes. Read them in the same // readFully call that reads the NAL length. This ensures sampleBytesRead, // sampleBytesWritten and isSampleDependedOn remain in a consistent state if we have // read failures. - nalUnitPrefixLength = track.track.nalUnitLengthFieldLength + 1; - readNalType = true; + numberOfBytesToDetermineSampleDependencies = + NalUnitUtil.numberOfBytesToDetermineSampleDependencies(track.track.format); + nalUnitPrefixLength = + track.track.nalUnitLengthFieldLength + numberOfBytesToDetermineSampleDependencies; } // Read the NAL length so that we know where we find the next one. input.readFully(nalPrefixData, nalUnitLengthFieldLengthDiff, nalUnitPrefixLength); @@ -915,19 +922,24 @@ public final class Mp4Extractor implements Extractor, SeekMap { throw ParserException.createForMalformedContainer( "Invalid NAL length", /* cause= */ null); } - sampleCurrentNalBytesRemaining = nalLengthInt - (readNalType ? 1 : 0); + sampleCurrentNalBytesRemaining = + nalLengthInt - numberOfBytesToDetermineSampleDependencies; // Write a start code for the current NAL unit. nalStartCode.setPosition(0); trackOutput.sampleData(nalStartCode, 4); sampleBytesWritten += 4; sampleSize += nalUnitLengthFieldLengthDiff; - if (readNalType) { - // Write the NAL unit type byte. - trackOutput.sampleData(nalPrefix, 1); - sampleBytesWritten += 1; + if (numberOfBytesToDetermineSampleDependencies > 0) { + // Write the first NAL unit bytes that were read. + trackOutput.sampleData(nalPrefix, numberOfBytesToDetermineSampleDependencies); + sampleBytesWritten += numberOfBytesToDetermineSampleDependencies; // If any NAL unit that's part of this sample can be depended on, treat the entire // sample as depended on. - if (NalUnitUtil.isH264NalUnitDependedOn(nalPrefixData[4])) { + if (NalUnitUtil.isDependedOn( + nalPrefixData, + /* offset= */ 4, + /* length= */ numberOfBytesToDetermineSampleDependencies, + track.track.format)) { isSampleDependedOn = true; } } @@ -980,8 +992,7 @@ public final class Mp4Extractor implements Extractor, SeekMap { sampleBytesRead = 0; sampleBytesWritten = 0; sampleCurrentNalBytesRemaining = 0; - // Treat all samples as depended on when FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES is unset. - isSampleDependedOn = (flags & FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES) == 0; + isSampleDependedOn = false; return RESULT_CONTINUE; } @@ -1083,6 +1094,20 @@ public final class Mp4Extractor implements Extractor, SeekMap { } } + /** + * Returns whether reading within GOP sample dependencies is enabled for the sample {@link + * Format}. + */ + private boolean canReadWithinGopSampleDependencies(Format format) { + if (Objects.equals(format.sampleMimeType, MimeTypes.VIDEO_H264)) { + return (flags & FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES) != 0; + } + if (Objects.equals(format.sampleMimeType, MimeTypes.VIDEO_H265)) { + return (flags & FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES_H265) != 0; + } + return false; + } + /** * For each sample of each track, calculates accumulated size of all samples which need to be read * before this sample can be used. diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/Mp4ExtractorParameterizedTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/Mp4ExtractorParameterizedTest.java index 427be2b6b0..57c1619933 100644 --- a/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/Mp4ExtractorParameterizedTest.java +++ b/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/Mp4ExtractorParameterizedTest.java @@ -244,6 +244,11 @@ public final class Mp4ExtractorParameterizedTest { assertExtractorBehavior("media/mp4/sample_with_invalid_nalu.mp4"); } + @Test + public void mp4SampleWithNonReferenceH265Frames() throws Exception { + assertExtractorBehavior("media/mp4/h265_bframes.mp4"); + } + private void assertExtractorBehavior(String file) throws IOException { ExtractorAsserts.AssertionConfig.Builder assertionConfigBuilder = new ExtractorAsserts.AssertionConfig.Builder(); @@ -272,6 +277,7 @@ public final class Mp4ExtractorParameterizedTest { } if (readWithinGopSampleDependencies) { flags |= Mp4Extractor.FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES; + flags |= Mp4Extractor.FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES_H265; } @Mp4Extractor.Flags int finalFlags = flags; diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.0.dump new file mode 100644 index 0000000000..c3747ca083 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.0.dump @@ -0,0 +1,151 @@ +seekMap: + isSeekable = true + duration = 1000000 + getPosition(0) = [[timeUs=0, position=44]] + getPosition(1) = [[timeUs=0, position=44]] + getPosition(500000) = [[timeUs=0, position=44]] + getPosition(1000000) = [[timeUs=0, position=44]] +numberOfTracks = 1 +track 0: + total output bytes = 19395 + sample count = 30 + track duration = 1000000 + format 0: + id = 1 + containerMimeType = video/mp4 + sampleMimeType = video/hevc + codecs = hvc1.1.6.L90.90 + maxInputSize = 7848 + maxNumReorderSamples = 2 + width = 854 + height = 480 + frameRate = 30.00 + maxSubLayers = 1 + colorInfo: + colorRange = 2 + lumaBitdepth = 8 + chromaBitdepth = 8 + metadata = entries=[TSSE: description=null: values=[Lavf60.16.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000] + initializationData: + data = length 84, hash 6FF5034A + sample 0: + time = 0 + flags = 1 + data = length 2520, hash 9DF10E5A + sample 1: + time = 33333 + flags = 0 + data = length 1227, hash C3B78778 + sample 2: + time = 200000 + flags = 0 + data = length 7818, hash 3118F8A5 + sample 3: + time = 133333 + flags = 0 + data = length 2314, hash F06B088 + sample 4: + time = 66666 + flags = 0 + data = length 1066, hash 2F1BE2DB + sample 5: + time = 100000 + flags = 0 + data = length 106, hash CF881CF + sample 6: + time = 166666 + flags = 0 + data = length 69, hash 43B2E357 + sample 7: + time = 366666 + flags = 0 + data = length 304, hash 19293C74 + sample 8: + time = 300000 + flags = 0 + data = length 145, hash C3F16A + sample 9: + time = 233333 + flags = 0 + data = length 226, hash FDA9A38B + sample 10: + time = 266666 + flags = 0 + data = length 185, hash 9C800E54 + sample 11: + time = 333333 + flags = 0 + data = length 90, hash D1EA90C4 + sample 12: + time = 466666 + flags = 0 + data = length 298, hash F203E87C + sample 13: + time = 433333 + flags = 0 + data = length 276, hash 66430FFD + sample 14: + time = 400000 + flags = 0 + data = length 186, hash B985342A + sample 15: + time = 500000 + flags = 0 + data = length 279, hash 1EFA3459 + sample 16: + time = 666666 + flags = 0 + data = length 265, hash 7FCB3588 + sample 17: + time = 600000 + flags = 0 + data = length 214, hash EFA105EC + sample 18: + time = 533333 + flags = 0 + data = length 138, hash 5F4FDE79 + sample 19: + time = 566666 + flags = 0 + data = length 122, hash 951D945A + sample 20: + time = 633333 + flags = 0 + data = length 103, hash 50A4D1ED + sample 21: + time = 833333 + flags = 0 + data = length 241, hash 290CE032 + sample 22: + time = 766666 + flags = 0 + data = length 211, hash D120B486 + sample 23: + time = 700000 + flags = 0 + data = length 103, hash D33CDF67 + sample 24: + time = 733333 + flags = 0 + data = length 111, hash E8A78D5 + sample 25: + time = 800000 + flags = 0 + data = length 119, hash 3FA7645D + sample 26: + time = 966666 + flags = 0 + data = length 261, hash 53B1BD3B + sample 27: + time = 900000 + flags = 0 + data = length 142, hash B45973DC + sample 28: + time = 866666 + flags = 0 + data = length 88, hash 757187AE + sample 29: + time = 933333 + flags = 536870912 + data = length 168, hash 8220F9BC +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.1.dump new file mode 100644 index 0000000000..c3747ca083 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.1.dump @@ -0,0 +1,151 @@ +seekMap: + isSeekable = true + duration = 1000000 + getPosition(0) = [[timeUs=0, position=44]] + getPosition(1) = [[timeUs=0, position=44]] + getPosition(500000) = [[timeUs=0, position=44]] + getPosition(1000000) = [[timeUs=0, position=44]] +numberOfTracks = 1 +track 0: + total output bytes = 19395 + sample count = 30 + track duration = 1000000 + format 0: + id = 1 + containerMimeType = video/mp4 + sampleMimeType = video/hevc + codecs = hvc1.1.6.L90.90 + maxInputSize = 7848 + maxNumReorderSamples = 2 + width = 854 + height = 480 + frameRate = 30.00 + maxSubLayers = 1 + colorInfo: + colorRange = 2 + lumaBitdepth = 8 + chromaBitdepth = 8 + metadata = entries=[TSSE: description=null: values=[Lavf60.16.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000] + initializationData: + data = length 84, hash 6FF5034A + sample 0: + time = 0 + flags = 1 + data = length 2520, hash 9DF10E5A + sample 1: + time = 33333 + flags = 0 + data = length 1227, hash C3B78778 + sample 2: + time = 200000 + flags = 0 + data = length 7818, hash 3118F8A5 + sample 3: + time = 133333 + flags = 0 + data = length 2314, hash F06B088 + sample 4: + time = 66666 + flags = 0 + data = length 1066, hash 2F1BE2DB + sample 5: + time = 100000 + flags = 0 + data = length 106, hash CF881CF + sample 6: + time = 166666 + flags = 0 + data = length 69, hash 43B2E357 + sample 7: + time = 366666 + flags = 0 + data = length 304, hash 19293C74 + sample 8: + time = 300000 + flags = 0 + data = length 145, hash C3F16A + sample 9: + time = 233333 + flags = 0 + data = length 226, hash FDA9A38B + sample 10: + time = 266666 + flags = 0 + data = length 185, hash 9C800E54 + sample 11: + time = 333333 + flags = 0 + data = length 90, hash D1EA90C4 + sample 12: + time = 466666 + flags = 0 + data = length 298, hash F203E87C + sample 13: + time = 433333 + flags = 0 + data = length 276, hash 66430FFD + sample 14: + time = 400000 + flags = 0 + data = length 186, hash B985342A + sample 15: + time = 500000 + flags = 0 + data = length 279, hash 1EFA3459 + sample 16: + time = 666666 + flags = 0 + data = length 265, hash 7FCB3588 + sample 17: + time = 600000 + flags = 0 + data = length 214, hash EFA105EC + sample 18: + time = 533333 + flags = 0 + data = length 138, hash 5F4FDE79 + sample 19: + time = 566666 + flags = 0 + data = length 122, hash 951D945A + sample 20: + time = 633333 + flags = 0 + data = length 103, hash 50A4D1ED + sample 21: + time = 833333 + flags = 0 + data = length 241, hash 290CE032 + sample 22: + time = 766666 + flags = 0 + data = length 211, hash D120B486 + sample 23: + time = 700000 + flags = 0 + data = length 103, hash D33CDF67 + sample 24: + time = 733333 + flags = 0 + data = length 111, hash E8A78D5 + sample 25: + time = 800000 + flags = 0 + data = length 119, hash 3FA7645D + sample 26: + time = 966666 + flags = 0 + data = length 261, hash 53B1BD3B + sample 27: + time = 900000 + flags = 0 + data = length 142, hash B45973DC + sample 28: + time = 866666 + flags = 0 + data = length 88, hash 757187AE + sample 29: + time = 933333 + flags = 536870912 + data = length 168, hash 8220F9BC +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.2.dump new file mode 100644 index 0000000000..c3747ca083 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.2.dump @@ -0,0 +1,151 @@ +seekMap: + isSeekable = true + duration = 1000000 + getPosition(0) = [[timeUs=0, position=44]] + getPosition(1) = [[timeUs=0, position=44]] + getPosition(500000) = [[timeUs=0, position=44]] + getPosition(1000000) = [[timeUs=0, position=44]] +numberOfTracks = 1 +track 0: + total output bytes = 19395 + sample count = 30 + track duration = 1000000 + format 0: + id = 1 + containerMimeType = video/mp4 + sampleMimeType = video/hevc + codecs = hvc1.1.6.L90.90 + maxInputSize = 7848 + maxNumReorderSamples = 2 + width = 854 + height = 480 + frameRate = 30.00 + maxSubLayers = 1 + colorInfo: + colorRange = 2 + lumaBitdepth = 8 + chromaBitdepth = 8 + metadata = entries=[TSSE: description=null: values=[Lavf60.16.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000] + initializationData: + data = length 84, hash 6FF5034A + sample 0: + time = 0 + flags = 1 + data = length 2520, hash 9DF10E5A + sample 1: + time = 33333 + flags = 0 + data = length 1227, hash C3B78778 + sample 2: + time = 200000 + flags = 0 + data = length 7818, hash 3118F8A5 + sample 3: + time = 133333 + flags = 0 + data = length 2314, hash F06B088 + sample 4: + time = 66666 + flags = 0 + data = length 1066, hash 2F1BE2DB + sample 5: + time = 100000 + flags = 0 + data = length 106, hash CF881CF + sample 6: + time = 166666 + flags = 0 + data = length 69, hash 43B2E357 + sample 7: + time = 366666 + flags = 0 + data = length 304, hash 19293C74 + sample 8: + time = 300000 + flags = 0 + data = length 145, hash C3F16A + sample 9: + time = 233333 + flags = 0 + data = length 226, hash FDA9A38B + sample 10: + time = 266666 + flags = 0 + data = length 185, hash 9C800E54 + sample 11: + time = 333333 + flags = 0 + data = length 90, hash D1EA90C4 + sample 12: + time = 466666 + flags = 0 + data = length 298, hash F203E87C + sample 13: + time = 433333 + flags = 0 + data = length 276, hash 66430FFD + sample 14: + time = 400000 + flags = 0 + data = length 186, hash B985342A + sample 15: + time = 500000 + flags = 0 + data = length 279, hash 1EFA3459 + sample 16: + time = 666666 + flags = 0 + data = length 265, hash 7FCB3588 + sample 17: + time = 600000 + flags = 0 + data = length 214, hash EFA105EC + sample 18: + time = 533333 + flags = 0 + data = length 138, hash 5F4FDE79 + sample 19: + time = 566666 + flags = 0 + data = length 122, hash 951D945A + sample 20: + time = 633333 + flags = 0 + data = length 103, hash 50A4D1ED + sample 21: + time = 833333 + flags = 0 + data = length 241, hash 290CE032 + sample 22: + time = 766666 + flags = 0 + data = length 211, hash D120B486 + sample 23: + time = 700000 + flags = 0 + data = length 103, hash D33CDF67 + sample 24: + time = 733333 + flags = 0 + data = length 111, hash E8A78D5 + sample 25: + time = 800000 + flags = 0 + data = length 119, hash 3FA7645D + sample 26: + time = 966666 + flags = 0 + data = length 261, hash 53B1BD3B + sample 27: + time = 900000 + flags = 0 + data = length 142, hash B45973DC + sample 28: + time = 866666 + flags = 0 + data = length 88, hash 757187AE + sample 29: + time = 933333 + flags = 536870912 + data = length 168, hash 8220F9BC +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.3.dump new file mode 100644 index 0000000000..c3747ca083 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.3.dump @@ -0,0 +1,151 @@ +seekMap: + isSeekable = true + duration = 1000000 + getPosition(0) = [[timeUs=0, position=44]] + getPosition(1) = [[timeUs=0, position=44]] + getPosition(500000) = [[timeUs=0, position=44]] + getPosition(1000000) = [[timeUs=0, position=44]] +numberOfTracks = 1 +track 0: + total output bytes = 19395 + sample count = 30 + track duration = 1000000 + format 0: + id = 1 + containerMimeType = video/mp4 + sampleMimeType = video/hevc + codecs = hvc1.1.6.L90.90 + maxInputSize = 7848 + maxNumReorderSamples = 2 + width = 854 + height = 480 + frameRate = 30.00 + maxSubLayers = 1 + colorInfo: + colorRange = 2 + lumaBitdepth = 8 + chromaBitdepth = 8 + metadata = entries=[TSSE: description=null: values=[Lavf60.16.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000] + initializationData: + data = length 84, hash 6FF5034A + sample 0: + time = 0 + flags = 1 + data = length 2520, hash 9DF10E5A + sample 1: + time = 33333 + flags = 0 + data = length 1227, hash C3B78778 + sample 2: + time = 200000 + flags = 0 + data = length 7818, hash 3118F8A5 + sample 3: + time = 133333 + flags = 0 + data = length 2314, hash F06B088 + sample 4: + time = 66666 + flags = 0 + data = length 1066, hash 2F1BE2DB + sample 5: + time = 100000 + flags = 0 + data = length 106, hash CF881CF + sample 6: + time = 166666 + flags = 0 + data = length 69, hash 43B2E357 + sample 7: + time = 366666 + flags = 0 + data = length 304, hash 19293C74 + sample 8: + time = 300000 + flags = 0 + data = length 145, hash C3F16A + sample 9: + time = 233333 + flags = 0 + data = length 226, hash FDA9A38B + sample 10: + time = 266666 + flags = 0 + data = length 185, hash 9C800E54 + sample 11: + time = 333333 + flags = 0 + data = length 90, hash D1EA90C4 + sample 12: + time = 466666 + flags = 0 + data = length 298, hash F203E87C + sample 13: + time = 433333 + flags = 0 + data = length 276, hash 66430FFD + sample 14: + time = 400000 + flags = 0 + data = length 186, hash B985342A + sample 15: + time = 500000 + flags = 0 + data = length 279, hash 1EFA3459 + sample 16: + time = 666666 + flags = 0 + data = length 265, hash 7FCB3588 + sample 17: + time = 600000 + flags = 0 + data = length 214, hash EFA105EC + sample 18: + time = 533333 + flags = 0 + data = length 138, hash 5F4FDE79 + sample 19: + time = 566666 + flags = 0 + data = length 122, hash 951D945A + sample 20: + time = 633333 + flags = 0 + data = length 103, hash 50A4D1ED + sample 21: + time = 833333 + flags = 0 + data = length 241, hash 290CE032 + sample 22: + time = 766666 + flags = 0 + data = length 211, hash D120B486 + sample 23: + time = 700000 + flags = 0 + data = length 103, hash D33CDF67 + sample 24: + time = 733333 + flags = 0 + data = length 111, hash E8A78D5 + sample 25: + time = 800000 + flags = 0 + data = length 119, hash 3FA7645D + sample 26: + time = 966666 + flags = 0 + data = length 261, hash 53B1BD3B + sample 27: + time = 900000 + flags = 0 + data = length 142, hash B45973DC + sample 28: + time = 866666 + flags = 0 + data = length 88, hash 757187AE + sample 29: + time = 933333 + flags = 536870912 + data = length 168, hash 8220F9BC +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.0.dump new file mode 100644 index 0000000000..7f2a42e0e9 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.0.dump @@ -0,0 +1,151 @@ +seekMap: + isSeekable = true + duration = 1000000 + getPosition(0) = [[timeUs=0, position=44]] + getPosition(1) = [[timeUs=0, position=44]] + getPosition(500000) = [[timeUs=0, position=44]] + getPosition(1000000) = [[timeUs=0, position=44]] +numberOfTracks = 1 +track 0: + total output bytes = 19395 + sample count = 30 + track duration = 1000000 + format 0: + id = 1 + containerMimeType = video/mp4 + sampleMimeType = video/hevc + codecs = hvc1.1.6.L90.90 + maxInputSize = 7848 + maxNumReorderSamples = 2 + width = 854 + height = 480 + frameRate = 30.00 + maxSubLayers = 1 + colorInfo: + colorRange = 2 + lumaBitdepth = 8 + chromaBitdepth = 8 + metadata = entries=[TSSE: description=null: values=[Lavf60.16.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000] + initializationData: + data = length 84, hash 6FF5034A + sample 0: + time = 0 + flags = 1 + data = length 2520, hash 9DF10E5A + sample 1: + time = 33333 + flags = 0 + data = length 1227, hash C3B78778 + sample 2: + time = 200000 + flags = 0 + data = length 7818, hash 3118F8A5 + sample 3: + time = 133333 + flags = 0 + data = length 2314, hash F06B088 + sample 4: + time = 66666 + flags = 67108864 + data = length 1066, hash 2F1BE2DB + sample 5: + time = 100000 + flags = 67108864 + data = length 106, hash CF881CF + sample 6: + time = 166666 + flags = 67108864 + data = length 69, hash 43B2E357 + sample 7: + time = 366666 + flags = 0 + data = length 304, hash 19293C74 + sample 8: + time = 300000 + flags = 0 + data = length 145, hash C3F16A + sample 9: + time = 233333 + flags = 67108864 + data = length 226, hash FDA9A38B + sample 10: + time = 266666 + flags = 67108864 + data = length 185, hash 9C800E54 + sample 11: + time = 333333 + flags = 67108864 + data = length 90, hash D1EA90C4 + sample 12: + time = 466666 + flags = 0 + data = length 298, hash F203E87C + sample 13: + time = 433333 + flags = 0 + data = length 276, hash 66430FFD + sample 14: + time = 400000 + flags = 67108864 + data = length 186, hash B985342A + sample 15: + time = 500000 + flags = 0 + data = length 279, hash 1EFA3459 + sample 16: + time = 666666 + flags = 0 + data = length 265, hash 7FCB3588 + sample 17: + time = 600000 + flags = 0 + data = length 214, hash EFA105EC + sample 18: + time = 533333 + flags = 67108864 + data = length 138, hash 5F4FDE79 + sample 19: + time = 566666 + flags = 67108864 + data = length 122, hash 951D945A + sample 20: + time = 633333 + flags = 67108864 + data = length 103, hash 50A4D1ED + sample 21: + time = 833333 + flags = 0 + data = length 241, hash 290CE032 + sample 22: + time = 766666 + flags = 0 + data = length 211, hash D120B486 + sample 23: + time = 700000 + flags = 67108864 + data = length 103, hash D33CDF67 + sample 24: + time = 733333 + flags = 67108864 + data = length 111, hash E8A78D5 + sample 25: + time = 800000 + flags = 67108864 + data = length 119, hash 3FA7645D + sample 26: + time = 966666 + flags = 0 + data = length 261, hash 53B1BD3B + sample 27: + time = 900000 + flags = 0 + data = length 142, hash B45973DC + sample 28: + time = 866666 + flags = 67108864 + data = length 88, hash 757187AE + sample 29: + time = 933333 + flags = 603979776 + data = length 168, hash 8220F9BC +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.1.dump new file mode 100644 index 0000000000..7f2a42e0e9 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.1.dump @@ -0,0 +1,151 @@ +seekMap: + isSeekable = true + duration = 1000000 + getPosition(0) = [[timeUs=0, position=44]] + getPosition(1) = [[timeUs=0, position=44]] + getPosition(500000) = [[timeUs=0, position=44]] + getPosition(1000000) = [[timeUs=0, position=44]] +numberOfTracks = 1 +track 0: + total output bytes = 19395 + sample count = 30 + track duration = 1000000 + format 0: + id = 1 + containerMimeType = video/mp4 + sampleMimeType = video/hevc + codecs = hvc1.1.6.L90.90 + maxInputSize = 7848 + maxNumReorderSamples = 2 + width = 854 + height = 480 + frameRate = 30.00 + maxSubLayers = 1 + colorInfo: + colorRange = 2 + lumaBitdepth = 8 + chromaBitdepth = 8 + metadata = entries=[TSSE: description=null: values=[Lavf60.16.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000] + initializationData: + data = length 84, hash 6FF5034A + sample 0: + time = 0 + flags = 1 + data = length 2520, hash 9DF10E5A + sample 1: + time = 33333 + flags = 0 + data = length 1227, hash C3B78778 + sample 2: + time = 200000 + flags = 0 + data = length 7818, hash 3118F8A5 + sample 3: + time = 133333 + flags = 0 + data = length 2314, hash F06B088 + sample 4: + time = 66666 + flags = 67108864 + data = length 1066, hash 2F1BE2DB + sample 5: + time = 100000 + flags = 67108864 + data = length 106, hash CF881CF + sample 6: + time = 166666 + flags = 67108864 + data = length 69, hash 43B2E357 + sample 7: + time = 366666 + flags = 0 + data = length 304, hash 19293C74 + sample 8: + time = 300000 + flags = 0 + data = length 145, hash C3F16A + sample 9: + time = 233333 + flags = 67108864 + data = length 226, hash FDA9A38B + sample 10: + time = 266666 + flags = 67108864 + data = length 185, hash 9C800E54 + sample 11: + time = 333333 + flags = 67108864 + data = length 90, hash D1EA90C4 + sample 12: + time = 466666 + flags = 0 + data = length 298, hash F203E87C + sample 13: + time = 433333 + flags = 0 + data = length 276, hash 66430FFD + sample 14: + time = 400000 + flags = 67108864 + data = length 186, hash B985342A + sample 15: + time = 500000 + flags = 0 + data = length 279, hash 1EFA3459 + sample 16: + time = 666666 + flags = 0 + data = length 265, hash 7FCB3588 + sample 17: + time = 600000 + flags = 0 + data = length 214, hash EFA105EC + sample 18: + time = 533333 + flags = 67108864 + data = length 138, hash 5F4FDE79 + sample 19: + time = 566666 + flags = 67108864 + data = length 122, hash 951D945A + sample 20: + time = 633333 + flags = 67108864 + data = length 103, hash 50A4D1ED + sample 21: + time = 833333 + flags = 0 + data = length 241, hash 290CE032 + sample 22: + time = 766666 + flags = 0 + data = length 211, hash D120B486 + sample 23: + time = 700000 + flags = 67108864 + data = length 103, hash D33CDF67 + sample 24: + time = 733333 + flags = 67108864 + data = length 111, hash E8A78D5 + sample 25: + time = 800000 + flags = 67108864 + data = length 119, hash 3FA7645D + sample 26: + time = 966666 + flags = 0 + data = length 261, hash 53B1BD3B + sample 27: + time = 900000 + flags = 0 + data = length 142, hash B45973DC + sample 28: + time = 866666 + flags = 67108864 + data = length 88, hash 757187AE + sample 29: + time = 933333 + flags = 603979776 + data = length 168, hash 8220F9BC +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.2.dump new file mode 100644 index 0000000000..7f2a42e0e9 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.2.dump @@ -0,0 +1,151 @@ +seekMap: + isSeekable = true + duration = 1000000 + getPosition(0) = [[timeUs=0, position=44]] + getPosition(1) = [[timeUs=0, position=44]] + getPosition(500000) = [[timeUs=0, position=44]] + getPosition(1000000) = [[timeUs=0, position=44]] +numberOfTracks = 1 +track 0: + total output bytes = 19395 + sample count = 30 + track duration = 1000000 + format 0: + id = 1 + containerMimeType = video/mp4 + sampleMimeType = video/hevc + codecs = hvc1.1.6.L90.90 + maxInputSize = 7848 + maxNumReorderSamples = 2 + width = 854 + height = 480 + frameRate = 30.00 + maxSubLayers = 1 + colorInfo: + colorRange = 2 + lumaBitdepth = 8 + chromaBitdepth = 8 + metadata = entries=[TSSE: description=null: values=[Lavf60.16.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000] + initializationData: + data = length 84, hash 6FF5034A + sample 0: + time = 0 + flags = 1 + data = length 2520, hash 9DF10E5A + sample 1: + time = 33333 + flags = 0 + data = length 1227, hash C3B78778 + sample 2: + time = 200000 + flags = 0 + data = length 7818, hash 3118F8A5 + sample 3: + time = 133333 + flags = 0 + data = length 2314, hash F06B088 + sample 4: + time = 66666 + flags = 67108864 + data = length 1066, hash 2F1BE2DB + sample 5: + time = 100000 + flags = 67108864 + data = length 106, hash CF881CF + sample 6: + time = 166666 + flags = 67108864 + data = length 69, hash 43B2E357 + sample 7: + time = 366666 + flags = 0 + data = length 304, hash 19293C74 + sample 8: + time = 300000 + flags = 0 + data = length 145, hash C3F16A + sample 9: + time = 233333 + flags = 67108864 + data = length 226, hash FDA9A38B + sample 10: + time = 266666 + flags = 67108864 + data = length 185, hash 9C800E54 + sample 11: + time = 333333 + flags = 67108864 + data = length 90, hash D1EA90C4 + sample 12: + time = 466666 + flags = 0 + data = length 298, hash F203E87C + sample 13: + time = 433333 + flags = 0 + data = length 276, hash 66430FFD + sample 14: + time = 400000 + flags = 67108864 + data = length 186, hash B985342A + sample 15: + time = 500000 + flags = 0 + data = length 279, hash 1EFA3459 + sample 16: + time = 666666 + flags = 0 + data = length 265, hash 7FCB3588 + sample 17: + time = 600000 + flags = 0 + data = length 214, hash EFA105EC + sample 18: + time = 533333 + flags = 67108864 + data = length 138, hash 5F4FDE79 + sample 19: + time = 566666 + flags = 67108864 + data = length 122, hash 951D945A + sample 20: + time = 633333 + flags = 67108864 + data = length 103, hash 50A4D1ED + sample 21: + time = 833333 + flags = 0 + data = length 241, hash 290CE032 + sample 22: + time = 766666 + flags = 0 + data = length 211, hash D120B486 + sample 23: + time = 700000 + flags = 67108864 + data = length 103, hash D33CDF67 + sample 24: + time = 733333 + flags = 67108864 + data = length 111, hash E8A78D5 + sample 25: + time = 800000 + flags = 67108864 + data = length 119, hash 3FA7645D + sample 26: + time = 966666 + flags = 0 + data = length 261, hash 53B1BD3B + sample 27: + time = 900000 + flags = 0 + data = length 142, hash B45973DC + sample 28: + time = 866666 + flags = 67108864 + data = length 88, hash 757187AE + sample 29: + time = 933333 + flags = 603979776 + data = length 168, hash 8220F9BC +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.3.dump new file mode 100644 index 0000000000..7f2a42e0e9 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.3.dump @@ -0,0 +1,151 @@ +seekMap: + isSeekable = true + duration = 1000000 + getPosition(0) = [[timeUs=0, position=44]] + getPosition(1) = [[timeUs=0, position=44]] + getPosition(500000) = [[timeUs=0, position=44]] + getPosition(1000000) = [[timeUs=0, position=44]] +numberOfTracks = 1 +track 0: + total output bytes = 19395 + sample count = 30 + track duration = 1000000 + format 0: + id = 1 + containerMimeType = video/mp4 + sampleMimeType = video/hevc + codecs = hvc1.1.6.L90.90 + maxInputSize = 7848 + maxNumReorderSamples = 2 + width = 854 + height = 480 + frameRate = 30.00 + maxSubLayers = 1 + colorInfo: + colorRange = 2 + lumaBitdepth = 8 + chromaBitdepth = 8 + metadata = entries=[TSSE: description=null: values=[Lavf60.16.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000] + initializationData: + data = length 84, hash 6FF5034A + sample 0: + time = 0 + flags = 1 + data = length 2520, hash 9DF10E5A + sample 1: + time = 33333 + flags = 0 + data = length 1227, hash C3B78778 + sample 2: + time = 200000 + flags = 0 + data = length 7818, hash 3118F8A5 + sample 3: + time = 133333 + flags = 0 + data = length 2314, hash F06B088 + sample 4: + time = 66666 + flags = 67108864 + data = length 1066, hash 2F1BE2DB + sample 5: + time = 100000 + flags = 67108864 + data = length 106, hash CF881CF + sample 6: + time = 166666 + flags = 67108864 + data = length 69, hash 43B2E357 + sample 7: + time = 366666 + flags = 0 + data = length 304, hash 19293C74 + sample 8: + time = 300000 + flags = 0 + data = length 145, hash C3F16A + sample 9: + time = 233333 + flags = 67108864 + data = length 226, hash FDA9A38B + sample 10: + time = 266666 + flags = 67108864 + data = length 185, hash 9C800E54 + sample 11: + time = 333333 + flags = 67108864 + data = length 90, hash D1EA90C4 + sample 12: + time = 466666 + flags = 0 + data = length 298, hash F203E87C + sample 13: + time = 433333 + flags = 0 + data = length 276, hash 66430FFD + sample 14: + time = 400000 + flags = 67108864 + data = length 186, hash B985342A + sample 15: + time = 500000 + flags = 0 + data = length 279, hash 1EFA3459 + sample 16: + time = 666666 + flags = 0 + data = length 265, hash 7FCB3588 + sample 17: + time = 600000 + flags = 0 + data = length 214, hash EFA105EC + sample 18: + time = 533333 + flags = 67108864 + data = length 138, hash 5F4FDE79 + sample 19: + time = 566666 + flags = 67108864 + data = length 122, hash 951D945A + sample 20: + time = 633333 + flags = 67108864 + data = length 103, hash 50A4D1ED + sample 21: + time = 833333 + flags = 0 + data = length 241, hash 290CE032 + sample 22: + time = 766666 + flags = 0 + data = length 211, hash D120B486 + sample 23: + time = 700000 + flags = 67108864 + data = length 103, hash D33CDF67 + sample 24: + time = 733333 + flags = 67108864 + data = length 111, hash E8A78D5 + sample 25: + time = 800000 + flags = 67108864 + data = length 119, hash 3FA7645D + sample 26: + time = 966666 + flags = 0 + data = length 261, hash 53B1BD3B + sample 27: + time = 900000 + flags = 0 + data = length 142, hash B45973DC + sample 28: + time = 866666 + flags = 67108864 + data = length 88, hash 757187AE + sample 29: + time = 933333 + flags = 603979776 + data = length 168, hash 8220F9BC +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.unknown_length.dump new file mode 100644 index 0000000000..7f2a42e0e9 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.reading_within_gop_sample_dependencies.unknown_length.dump @@ -0,0 +1,151 @@ +seekMap: + isSeekable = true + duration = 1000000 + getPosition(0) = [[timeUs=0, position=44]] + getPosition(1) = [[timeUs=0, position=44]] + getPosition(500000) = [[timeUs=0, position=44]] + getPosition(1000000) = [[timeUs=0, position=44]] +numberOfTracks = 1 +track 0: + total output bytes = 19395 + sample count = 30 + track duration = 1000000 + format 0: + id = 1 + containerMimeType = video/mp4 + sampleMimeType = video/hevc + codecs = hvc1.1.6.L90.90 + maxInputSize = 7848 + maxNumReorderSamples = 2 + width = 854 + height = 480 + frameRate = 30.00 + maxSubLayers = 1 + colorInfo: + colorRange = 2 + lumaBitdepth = 8 + chromaBitdepth = 8 + metadata = entries=[TSSE: description=null: values=[Lavf60.16.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000] + initializationData: + data = length 84, hash 6FF5034A + sample 0: + time = 0 + flags = 1 + data = length 2520, hash 9DF10E5A + sample 1: + time = 33333 + flags = 0 + data = length 1227, hash C3B78778 + sample 2: + time = 200000 + flags = 0 + data = length 7818, hash 3118F8A5 + sample 3: + time = 133333 + flags = 0 + data = length 2314, hash F06B088 + sample 4: + time = 66666 + flags = 67108864 + data = length 1066, hash 2F1BE2DB + sample 5: + time = 100000 + flags = 67108864 + data = length 106, hash CF881CF + sample 6: + time = 166666 + flags = 67108864 + data = length 69, hash 43B2E357 + sample 7: + time = 366666 + flags = 0 + data = length 304, hash 19293C74 + sample 8: + time = 300000 + flags = 0 + data = length 145, hash C3F16A + sample 9: + time = 233333 + flags = 67108864 + data = length 226, hash FDA9A38B + sample 10: + time = 266666 + flags = 67108864 + data = length 185, hash 9C800E54 + sample 11: + time = 333333 + flags = 67108864 + data = length 90, hash D1EA90C4 + sample 12: + time = 466666 + flags = 0 + data = length 298, hash F203E87C + sample 13: + time = 433333 + flags = 0 + data = length 276, hash 66430FFD + sample 14: + time = 400000 + flags = 67108864 + data = length 186, hash B985342A + sample 15: + time = 500000 + flags = 0 + data = length 279, hash 1EFA3459 + sample 16: + time = 666666 + flags = 0 + data = length 265, hash 7FCB3588 + sample 17: + time = 600000 + flags = 0 + data = length 214, hash EFA105EC + sample 18: + time = 533333 + flags = 67108864 + data = length 138, hash 5F4FDE79 + sample 19: + time = 566666 + flags = 67108864 + data = length 122, hash 951D945A + sample 20: + time = 633333 + flags = 67108864 + data = length 103, hash 50A4D1ED + sample 21: + time = 833333 + flags = 0 + data = length 241, hash 290CE032 + sample 22: + time = 766666 + flags = 0 + data = length 211, hash D120B486 + sample 23: + time = 700000 + flags = 67108864 + data = length 103, hash D33CDF67 + sample 24: + time = 733333 + flags = 67108864 + data = length 111, hash E8A78D5 + sample 25: + time = 800000 + flags = 67108864 + data = length 119, hash 3FA7645D + sample 26: + time = 966666 + flags = 0 + data = length 261, hash 53B1BD3B + sample 27: + time = 900000 + flags = 0 + data = length 142, hash B45973DC + sample 28: + time = 866666 + flags = 67108864 + data = length 88, hash 757187AE + sample 29: + time = 933333 + flags = 603979776 + data = length 168, hash 8220F9BC +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.unknown_length.dump new file mode 100644 index 0000000000..c3747ca083 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/h265_bframes.mp4.unknown_length.dump @@ -0,0 +1,151 @@ +seekMap: + isSeekable = true + duration = 1000000 + getPosition(0) = [[timeUs=0, position=44]] + getPosition(1) = [[timeUs=0, position=44]] + getPosition(500000) = [[timeUs=0, position=44]] + getPosition(1000000) = [[timeUs=0, position=44]] +numberOfTracks = 1 +track 0: + total output bytes = 19395 + sample count = 30 + track duration = 1000000 + format 0: + id = 1 + containerMimeType = video/mp4 + sampleMimeType = video/hevc + codecs = hvc1.1.6.L90.90 + maxInputSize = 7848 + maxNumReorderSamples = 2 + width = 854 + height = 480 + frameRate = 30.00 + maxSubLayers = 1 + colorInfo: + colorRange = 2 + lumaBitdepth = 8 + chromaBitdepth = 8 + metadata = entries=[TSSE: description=null: values=[Lavf60.16.100], Mp4Timestamp: creation time=0, modification time=0, timescale=1000] + initializationData: + data = length 84, hash 6FF5034A + sample 0: + time = 0 + flags = 1 + data = length 2520, hash 9DF10E5A + sample 1: + time = 33333 + flags = 0 + data = length 1227, hash C3B78778 + sample 2: + time = 200000 + flags = 0 + data = length 7818, hash 3118F8A5 + sample 3: + time = 133333 + flags = 0 + data = length 2314, hash F06B088 + sample 4: + time = 66666 + flags = 0 + data = length 1066, hash 2F1BE2DB + sample 5: + time = 100000 + flags = 0 + data = length 106, hash CF881CF + sample 6: + time = 166666 + flags = 0 + data = length 69, hash 43B2E357 + sample 7: + time = 366666 + flags = 0 + data = length 304, hash 19293C74 + sample 8: + time = 300000 + flags = 0 + data = length 145, hash C3F16A + sample 9: + time = 233333 + flags = 0 + data = length 226, hash FDA9A38B + sample 10: + time = 266666 + flags = 0 + data = length 185, hash 9C800E54 + sample 11: + time = 333333 + flags = 0 + data = length 90, hash D1EA90C4 + sample 12: + time = 466666 + flags = 0 + data = length 298, hash F203E87C + sample 13: + time = 433333 + flags = 0 + data = length 276, hash 66430FFD + sample 14: + time = 400000 + flags = 0 + data = length 186, hash B985342A + sample 15: + time = 500000 + flags = 0 + data = length 279, hash 1EFA3459 + sample 16: + time = 666666 + flags = 0 + data = length 265, hash 7FCB3588 + sample 17: + time = 600000 + flags = 0 + data = length 214, hash EFA105EC + sample 18: + time = 533333 + flags = 0 + data = length 138, hash 5F4FDE79 + sample 19: + time = 566666 + flags = 0 + data = length 122, hash 951D945A + sample 20: + time = 633333 + flags = 0 + data = length 103, hash 50A4D1ED + sample 21: + time = 833333 + flags = 0 + data = length 241, hash 290CE032 + sample 22: + time = 766666 + flags = 0 + data = length 211, hash D120B486 + sample 23: + time = 700000 + flags = 0 + data = length 103, hash D33CDF67 + sample 24: + time = 733333 + flags = 0 + data = length 111, hash E8A78D5 + sample 25: + time = 800000 + flags = 0 + data = length 119, hash 3FA7645D + sample 26: + time = 966666 + flags = 0 + data = length 261, hash 53B1BD3B + sample 27: + time = 900000 + flags = 0 + data = length 142, hash B45973DC + sample 28: + time = 866666 + flags = 0 + data = length 88, hash 757187AE + sample 29: + time = 933333 + flags = 536870912 + data = length 168, hash 8220F9BC +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/media/mp4/h265_bframes.mp4 b/libraries/test_data/src/test/assets/media/mp4/h265_bframes.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..d389df86f780a95fc1576ea08d7486ca2bbcb8ba GIT binary patch literal 20634 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