From 3474c39c10f3b02bc3d66f15628b9d7ee177cd9a Mon Sep 17 00:00:00 2001 From: ibaker Date: Thu, 4 Jun 2020 14:09:57 +0100 Subject: [PATCH] Add support for non-contiguous Ogg pages bear_vorbis_gap.ogg is a copy of bear_vorbis.ogg with 10 garbage bytes (DE AD BE EF DE AD BE EF DE AD) inserted before the second capture pattern and 3 garbage bytes inserted at the end (DE AD BE). Issue: #7230 PiperOrigin-RevId: 314715729 --- RELEASENOTES.md | 2 + .../extractor/ogg/DefaultOggSeeker.java | 75 +- .../exoplayer2/extractor/ogg/OggPacket.java | 2 +- .../extractor/ogg/OggPageHeader.java | 96 ++- .../extractor/ogg/DefaultOggSeekerTest.java | 68 -- .../ogg/OggExtractorParameterizedTest.java | 7 + .../extractor/ogg/OggPageHeaderTest.java | 99 ++- .../src/test/assets/ogg/bear_vorbis_gap.ogg | Bin 0 -> 30530 bytes .../assets/ogg/bear_vorbis_gap.ogg.0.dump | 740 ++++++++++++++++++ .../assets/ogg/bear_vorbis_gap.ogg.1.dump | 456 +++++++++++ .../assets/ogg/bear_vorbis_gap.ogg.2.dump | 216 +++++ .../assets/ogg/bear_vorbis_gap.ogg.3.dump | 20 + .../bear_vorbis_gap.ogg.unknown_length.dump | 737 +++++++++++++++++ 13 files changed, 2359 insertions(+), 159 deletions(-) create mode 100644 testdata/src/test/assets/ogg/bear_vorbis_gap.ogg create mode 100644 testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.0.dump create mode 100644 testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.1.dump create mode 100644 testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.2.dump create mode 100644 testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.3.dump create mode 100644 testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.unknown_length.dump diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8153b58f60..5017ab3ec1 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -156,6 +156,8 @@ * HLS: * Add support for upstream discard including cancelation of ongoing load ([#6322](https://github.com/google/ExoPlayer/issues/6322)). +* Ogg: Allow non-contiguous pages + ([#7230](https://github.com/google/ExoPlayer/issues/7230)). * Extractors: * Add `IndexSeeker` for accurate seeks in VBR MP3 streams ([#6787](https://github.com/google/ExoPlayer/issues/6787)). This seeker diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java index b7d86632fb..b7a8039489 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java @@ -155,7 +155,7 @@ import java.io.IOException; } long currentPosition = input.getPosition(); - if (!skipToNextPage(input, end)) { + if (!pageHeader.skipToNextPage(input, end)) { if (start == currentPosition) { throw new IOException("No ogg page can be found."); } @@ -200,68 +200,21 @@ import java.io.IOException; * @throws IOException If reading from the input fails. */ private void skipToPageOfTargetGranule(ExtractorInput input) throws IOException { - pageHeader.populate(input, /* quiet= */ false); - while (pageHeader.granulePosition <= targetGranule) { + while (true) { + // If pageHeader.skipToNextPage fails to find a page it will advance input.position to the + // end of the file, so pageHeader.populate will throw EOFException (because quiet=false). + pageHeader.skipToNextPage(input); + pageHeader.populate(input, /* quiet= */ false); + if (pageHeader.granulePosition > targetGranule) { + break; + } input.skipFully(pageHeader.headerSize + pageHeader.bodySize); start = input.getPosition(); startGranule = pageHeader.granulePosition; - pageHeader.populate(input, /* quiet= */ false); } input.resetPeekPosition(); } - /** - * Skips to the next page. - * - * @param input The {@code ExtractorInput} to skip to the next page. - * @throws IOException If peeking/reading from the input fails. - * @throws EOFException If the next page can't be found before the end of the input. - */ - @VisibleForTesting - void skipToNextPage(ExtractorInput input) throws IOException { - if (!skipToNextPage(input, payloadEndPosition)) { - // Not found until eof. - throw new EOFException(); - } - } - - /** - * Skips to the next page. Searches for the next page header. - * - * @param input The {@code ExtractorInput} to skip to the next page. - * @param limit The limit up to which the search should take place. - * @return Whether the next page was found. - * @throws IOException If peeking/reading from the input fails. - */ - private boolean skipToNextPage(ExtractorInput input, long limit) throws IOException { - limit = Math.min(limit + 3, payloadEndPosition); - byte[] buffer = new byte[2048]; - int peekLength = buffer.length; - while (true) { - if (input.getPosition() + peekLength > limit) { - // Make sure to not peek beyond the end of the input. - peekLength = (int) (limit - input.getPosition()); - if (peekLength < 4) { - // Not found until end. - return false; - } - } - input.peekFully(buffer, 0, peekLength, false); - for (int i = 0; i < peekLength - 3; i++) { - if (buffer[i] == 'O' - && buffer[i + 1] == 'g' - && buffer[i + 2] == 'g' - && buffer[i + 3] == 'S') { - // Match! Skip to the start of the pattern. - input.skipFully(i); - return true; - } - } - // Overlap by not skipping the entire peekLength. - input.skipFully(peekLength - 3); - } - } - /** * Skips to the last Ogg page in the stream and reads the header's granule field which is the * total number of samples per channel. @@ -272,12 +225,16 @@ import java.io.IOException; */ @VisibleForTesting long readGranuleOfLastPage(ExtractorInput input) throws IOException { - skipToNextPage(input); pageHeader.reset(); - while ((pageHeader.type & 0x04) != 0x04 && input.getPosition() < payloadEndPosition) { + if (!pageHeader.skipToNextPage(input)) { + throw new EOFException(); + } + do { pageHeader.populate(input, /* quiet= */ false); input.skipFully(pageHeader.headerSize + pageHeader.bodySize); - } + } while ((pageHeader.type & 0x04) != 0x04 + && pageHeader.skipToNextPage(input) + && input.getPosition() < payloadEndPosition); return pageHeader.granulePosition; } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java index 2ee65f0112..07724cc33c 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java @@ -67,7 +67,7 @@ import java.util.Arrays; while (!populated) { if (currentSegmentIndex < 0) { // We're at the start of a page. - if (!pageHeader.populate(input, true)) { + if (!pageHeader.skipToNextPage(input) || !pageHeader.populate(input, /* quiet= */ true)) { return false; } int segmentIndex = 0; diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeader.java index d96aaa4568..853347ee18 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeader.java @@ -18,6 +18,7 @@ package com.google.android.exoplayer2.extractor.ogg; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.extractor.ExtractorInput; +import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.ParsableByteArray; import java.io.EOFException; import java.io.IOException; @@ -33,7 +34,8 @@ import java.io.IOException; public static final int MAX_PAGE_SIZE = EMPTY_PAGE_HEADER_SIZE + MAX_SEGMENT_COUNT + MAX_PAGE_PAYLOAD; - private static final int TYPE_OGGS = 0x4f676753; + private static final int CAPTURE_PATTERN = 0x4f676753; // OggS + private static final int CAPTURE_PATTERN_SIZE = 4; public int revision; public int type; @@ -73,6 +75,51 @@ import java.io.IOException; bodySize = 0; } + /** + * Advances through {@code input} looking for the start of the next Ogg page. + * + *

Equivalent to {@link #skipToNextPage(ExtractorInput, long) skipToNextPage(input, /* limit= + * *\/ C.POSITION_UNSET)}. + */ + public boolean skipToNextPage(ExtractorInput input) throws IOException { + return skipToNextPage(input, /* limit= */ C.POSITION_UNSET); + } + + /** + * Advances through {@code input} looking for the start of the next Ogg page. + * + *

The start of a page is identified by the 4-byte capture_pattern 'OggS'. + * + *

Returns {@code true} if a capture pattern was found, with the read and peek positions of + * {@code input} at the start of the page, just before the capture_pattern. Otherwise returns + * {@code false}, with the read and peek positions of {@code input} at either {@code limit} (if + * set) or end-of-input. + * + * @param input The {@link ExtractorInput} to read from (must have {@code readPosition == + * peekPosition}). + * @param limit The max position in {@code input} to peek to, or {@link C#POSITION_UNSET} to allow + * peeking to the end. + * @return True if a capture_pattern was found. + * @throws IOException If reading data fails. + */ + public boolean skipToNextPage(ExtractorInput input, long limit) throws IOException { + Assertions.checkArgument(input.getPosition() == input.getPeekPosition()); + while ((limit == C.POSITION_UNSET || input.getPosition() + CAPTURE_PATTERN_SIZE < limit) + && peekSafely(input, scratch.data, 0, CAPTURE_PATTERN_SIZE, /* quiet= */ true)) { + scratch.reset(); + if (scratch.readUnsignedInt() == CAPTURE_PATTERN) { + input.resetPeekPosition(); + return true; + } + // Advance one byte before looking for the capture pattern again. + input.skipFully(1); + } + // Move the read & peek positions to limit or end-of-input, whichever is closer. + while ((limit == C.POSITION_UNSET || input.getPosition() < limit) + && input.skip(1) != C.RESULT_END_OF_INPUT) {} + return false; + } + /** * Peeks an Ogg page header and updates this {@link OggPageHeader}. * @@ -84,23 +131,11 @@ import java.io.IOException; * @throws IOException If reading data fails or the stream is invalid. */ public boolean populate(ExtractorInput input, boolean quiet) throws IOException { - scratch.reset(); reset(); - boolean hasEnoughBytes = input.getLength() == C.LENGTH_UNSET - || input.getLength() - input.getPeekPosition() >= EMPTY_PAGE_HEADER_SIZE; - if (!hasEnoughBytes || !input.peekFully(scratch.data, 0, EMPTY_PAGE_HEADER_SIZE, true)) { - if (quiet) { - return false; - } else { - throw new EOFException(); - } - } - if (scratch.readUnsignedInt() != TYPE_OGGS) { - if (quiet) { - return false; - } else { - throw new ParserException("expected OggS capture pattern at begin of page"); - } + scratch.reset(); + if (!peekSafely(input, scratch.data, 0, EMPTY_PAGE_HEADER_SIZE, quiet) + || scratch.readUnsignedInt() != CAPTURE_PATTERN) { + return false; } revision = scratch.readUnsignedByte(); @@ -130,4 +165,31 @@ import java.io.IOException; return true; } + + /** + * Peek data from {@code input}, respecting {@code quiet}. Return true if the peek is successful. + * + *

If {@code quiet=false} then encountering the end of the input (whether before or after + * reading some data) will throw {@link EOFException}. + * + *

If {@code quiet=true} then encountering the end of the input (even after reading some data) + * will return {@code false}. + * + *

This is slightly different to the behaviour of {@link ExtractorInput#peekFully(byte[], int, + * int, boolean)}, where {@code allowEndOfInput=true} only returns false (and suppresses the + * exception) if the end of the input is reached before reading any data. + */ + private static boolean peekSafely( + ExtractorInput input, byte[] output, int offset, int length, boolean quiet) + throws IOException { + try { + return input.peekFully(output, offset, length, /* allowEndOfInput= */ quiet); + } catch (EOFException e) { + if (quiet) { + return false; + } else { + throw e; + } + } + } } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerTest.java index be471ac40c..57b9525d10 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerTest.java @@ -22,11 +22,9 @@ import static org.junit.Assert.fail; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.testutil.FakeExtractorInput; import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.util.ParsableByteArray; -import com.google.common.primitives.Bytes; import java.io.EOFException; import java.io.IOException; import java.util.Random; @@ -122,53 +120,6 @@ public final class DefaultOggSeekerTest { } } - @Test - public void skipToNextPage_success() throws Exception { - FakeExtractorInput extractorInput = - createInput( - Bytes.concat( - TestUtil.buildTestData(4000, random), - new byte[] {'O', 'g', 'g', 'S'}, - TestUtil.buildTestData(4000, random)), - /* simulateUnknownLength= */ false); - skipToNextPage(extractorInput); - assertThat(extractorInput.getPosition()).isEqualTo(4000); - } - - @Test - public void skipToNextPage_withOverlappingInput_success() throws Exception { - FakeExtractorInput extractorInput = - createInput( - Bytes.concat( - TestUtil.buildTestData(2046, random), - new byte[] {'O', 'g', 'g', 'S'}, - TestUtil.buildTestData(4000, random)), - /* simulateUnknownLength= */ false); - skipToNextPage(extractorInput); - assertThat(extractorInput.getPosition()).isEqualTo(2046); - } - - @Test - public void skipToNextPage_withInputShorterThanPeekLength_success() throws Exception { - FakeExtractorInput extractorInput = - createInput( - Bytes.concat(new byte[] {'x', 'O', 'g', 'g', 'S'}), /* simulateUnknownLength= */ false); - skipToNextPage(extractorInput); - assertThat(extractorInput.getPosition()).isEqualTo(1); - } - - @Test - public void skipToNextPage_withoutMatch_throwsException() throws Exception { - FakeExtractorInput extractorInput = - createInput(new byte[] {'g', 'g', 'S', 'O', 'g', 'g'}, /* simulateUnknownLength= */ false); - try { - skipToNextPage(extractorInput); - fail(); - } catch (EOFException e) { - // expected - } - } - @Test public void readGranuleOfLastPage() throws IOException { // This test stream has three headers with granule numbers 20000, 40000 and 60000. @@ -200,25 +151,6 @@ public final class DefaultOggSeekerTest { } } - private static void skipToNextPage(ExtractorInput extractorInput) throws IOException { - DefaultOggSeeker oggSeeker = - new DefaultOggSeeker( - /* streamReader= */ new FlacReader(), - /* payloadStartPosition= */ 0, - /* payloadEndPosition= */ extractorInput.getLength(), - /* firstPayloadPageSize= */ 1, - /* firstPayloadPageGranulePosition= */ 2, - /* firstPayloadPageIsLastPage= */ false); - while (true) { - try { - oggSeeker.skipToNextPage(extractorInput); - break; - } catch (FakeExtractorInput.SimulatedIOException e) { - /* ignored */ - } - } - } - private static void assertReadGranuleOfLastPage(FakeExtractorInput input, int expected) throws IOException { DefaultOggSeeker oggSeeker = diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggExtractorParameterizedTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggExtractorParameterizedTest.java index 9b2c6caf89..fa9879f77a 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggExtractorParameterizedTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggExtractorParameterizedTest.java @@ -59,4 +59,11 @@ public final class OggExtractorParameterizedTest { public void vorbis() throws Exception { ExtractorAsserts.assertBehavior(OggExtractor::new, "ogg/bear_vorbis.ogg", simulationConfig); } + + // Ensure the extractor can handle non-contiguous pages by using a file with 10 bytes of garbage + // data before the start of the second page. + @Test + public void vorbisWithGapBeforeSecondPage() throws Exception { + ExtractorAsserts.assertBehavior(OggExtractor::new, "ogg/bear_vorbis_gap.ogg", simulationConfig); + } } diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeaderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeaderTest.java index 6b5ffe8f91..6dde47bed3 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeaderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/extractor/ogg/OggPageHeaderTest.java @@ -23,6 +23,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.testutil.FakeExtractorInput; import com.google.android.exoplayer2.testutil.FakeExtractorInput.SimulatedIOException; import com.google.android.exoplayer2.testutil.TestUtil; +import com.google.common.primitives.Bytes; +import java.io.IOException; +import java.util.Random; import org.junit.Test; import org.junit.runner.RunWith; @@ -30,14 +33,69 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public final class OggPageHeaderTest { + private final Random random; + + public OggPageHeaderTest() { + this.random = new Random(/* seed= */ 0); + } + + @Test + public void skipToNextPage_success() throws Exception { + FakeExtractorInput input = + createInput( + Bytes.concat( + TestUtil.buildTestData(20, random), + new byte[] {'O', 'g', 'g', 'S'}, + TestUtil.buildTestData(20, random)), + /* simulateUnknownLength= */ false); + OggPageHeader oggHeader = new OggPageHeader(); + + boolean result = retrySimulatedIOException(() -> oggHeader.skipToNextPage(input)); + + assertThat(result).isTrue(); + assertThat(input.getPosition()).isEqualTo(20); + } + + @Test + public void skipToNextPage_noPage_returnsFalse() throws Exception { + FakeExtractorInput input = + createInput( + Bytes.concat(TestUtil.buildTestData(20, random)), /* simulateUnknownLength= */ false); + OggPageHeader oggHeader = new OggPageHeader(); + + boolean result = retrySimulatedIOException(() -> oggHeader.skipToNextPage(input)); + + assertThat(result).isFalse(); + assertThat(input.getPosition()).isEqualTo(20); + } + + @Test + public void skipToNextPage_respectsLimit() throws Exception { + FakeExtractorInput input = + createInput( + Bytes.concat( + TestUtil.buildTestData(20, random), + new byte[] {'O', 'g', 'g', 'S'}, + TestUtil.buildTestData(20, random)), + /* simulateUnknownLength= */ false); + OggPageHeader oggHeader = new OggPageHeader(); + + boolean result = retrySimulatedIOException(() -> oggHeader.skipToNextPage(input, 10)); + + assertThat(result).isFalse(); + assertThat(input.getPosition()).isEqualTo(10); + } + @Test public void populatePageHeader_success() throws Exception { byte[] data = getByteArray(ApplicationProvider.getApplicationContext(), "ogg/page_header"); FakeExtractorInput input = createInput(data, /* simulateUnknownLength= */ true); OggPageHeader header = new OggPageHeader(); - populatePageHeader(input, header, /* quiet= */ false); + boolean result = retrySimulatedIOException(() -> header.populate(input, /* quiet= */ false)); + + assertThat(result).isTrue(); assertThat(header.type).isEqualTo(0x01); assertThat(header.headerSize).isEqualTo(27 + 2); assertThat(header.bodySize).isEqualTo(4); @@ -55,7 +113,10 @@ public final class OggPageHeaderTest { FakeExtractorInput input = createInput(TestUtil.createByteArray(2, 2), /* simulateUnknownLength= */ false); OggPageHeader header = new OggPageHeader(); - assertThat(populatePageHeader(input, header, /* quiet= */ true)).isFalse(); + + boolean result = retrySimulatedIOException(() -> header.populate(input, /* quiet= */ true)); + + assertThat(result).isFalse(); } @Test @@ -65,7 +126,10 @@ public final class OggPageHeaderTest { data[0] = 'o'; FakeExtractorInput input = createInput(data, /* simulateUnknownLength= */ false); OggPageHeader header = new OggPageHeader(); - assertThat(populatePageHeader(input, header, /* quiet= */ true)).isFalse(); + + boolean result = retrySimulatedIOException(() -> header.populate(input, /* quiet= */ true)); + + assertThat(result).isFalse(); } @Test @@ -75,18 +139,10 @@ public final class OggPageHeaderTest { data[4] = 0x01; FakeExtractorInput input = createInput(data, /* simulateUnknownLength= */ false); OggPageHeader header = new OggPageHeader(); - assertThat(populatePageHeader(input, header, /* quiet= */ true)).isFalse(); - } - private static boolean populatePageHeader( - FakeExtractorInput input, OggPageHeader header, boolean quiet) throws Exception { - while (true) { - try { - return header.populate(input, quiet); - } catch (SimulatedIOException e) { - // ignored - } - } + boolean result = retrySimulatedIOException(() -> header.populate(input, /* quiet= */ true)); + + assertThat(result).isFalse(); } private static FakeExtractorInput createInput(byte[] data, boolean simulateUnknownLength) { @@ -97,5 +153,20 @@ public final class OggPageHeaderTest { .setSimulatePartialReads(true) .build(); } + + private static T retrySimulatedIOException(ThrowingSupplier supplier) + throws IOException { + while (true) { + try { + return supplier.get(); + } catch (SimulatedIOException e) { + // ignored + } + } + } + + private interface ThrowingSupplier { + S get() throws E; + } } diff --git a/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg b/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg new file mode 100644 index 0000000000000000000000000000000000000000..99d3efac4484ccd10652dfd0ffcc8511a0249f90 GIT binary patch literal 30530 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%0Dl}yf07Y3r9gJ8E2HvS?i#T$_@!Z}X6T2IL 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 R`yM(upUt&<90WAL{XcI9qy7K@ literal 0 HcmV?d00001 diff --git a/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.0.dump b/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.0.dump new file mode 100644 index 0000000000..bf05a1a039 --- /dev/null +++ b/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.0.dump @@ -0,0 +1,740 @@ +seekMap: + isSeekable = true + duration = 2741000 + getPosition(0) = [[timeUs=0, position=4005]] + getPosition(1) = [[timeUs=1, position=4005]] + getPosition(1370500) = [[timeUs=1370500, position=4005]] + getPosition(2741000) = [[timeUs=2741000, position=4005]] +numberOfTracks = 1 +track 0: + total output bytes = 26873 + sample count = 180 + format 0: + averageBitrate = 112000 + sampleMimeType = audio/vorbis + channelCount = 2 + sampleRate = 48000 + initializationData: + data = length 30, hash 9A8FF207 + data = length 3832, hash 8A406249 + sample 0: + time = 0 + flags = 1 + data = length 49, hash 2FFF94F0 + sample 1: + time = 0 + flags = 1 + data = length 44, hash 3946418A + sample 2: + time = 2666 + flags = 1 + data = length 55, hash 2A0B878E + sample 3: + time = 5333 + flags = 1 + data = length 53, hash CC3B6879 + sample 4: + time = 8000 + flags = 1 + data = length 215, hash 106AE950 + sample 5: + time = 20000 + flags = 1 + data = length 192, hash 2B219F53 + sample 6: + time = 41333 + flags = 1 + data = length 197, hash FBC39422 + sample 7: + time = 62666 + flags = 1 + data = length 209, hash 386E8979 + sample 8: + time = 84000 + flags = 1 + data = length 42, hash E81162C1 + sample 9: + time = 96000 + flags = 1 + data = length 41, hash F15BEE36 + sample 10: + time = 98666 + flags = 1 + data = length 42, hash D67EB19 + sample 11: + time = 101333 + flags = 1 + data = length 42, hash F4DE4792 + sample 12: + time = 104000 + flags = 1 + data = length 53, hash 80F66AC3 + sample 13: + time = 106666 + flags = 1 + data = length 56, hash DCB9DFC4 + sample 14: + time = 109333 + flags = 1 + data = length 55, hash 4E0C4E9D + sample 15: + time = 112000 + flags = 1 + data = length 203, hash 176B6862 + sample 16: + time = 124000 + flags = 1 + data = length 193, hash AB13CB10 + sample 17: + time = 145333 + flags = 1 + data = length 203, hash DE63DE9F + sample 18: + time = 166666 + flags = 1 + data = length 194, hash 4A9508A2 + sample 19: + time = 188000 + flags = 1 + data = length 210, hash 196899B3 + sample 20: + time = 209333 + flags = 1 + data = length 195, hash B68407F1 + sample 21: + time = 230666 + flags = 1 + data = length 193, hash A1FA86E3 + sample 22: + time = 252000 + flags = 1 + data = length 194, hash 5C0B9343 + sample 23: + time = 273333 + flags = 1 + data = length 198, hash 789914B2 + sample 24: + time = 294666 + flags = 1 + data = length 183, hash 1B82D11F + sample 25: + time = 316000 + flags = 1 + data = length 199, hash D5B848F4 + sample 26: + time = 337333 + flags = 1 + data = length 192, hash B34427EA + sample 27: + time = 358666 + flags = 1 + data = length 199, hash C2599BB5 + sample 28: + time = 380000 + flags = 1 + data = length 195, hash BFD83194 + sample 29: + time = 401333 + flags = 1 + data = length 199, hash C9A7F7CA + sample 30: + time = 422666 + flags = 1 + data = length 44, hash 5D76EAD6 + sample 31: + time = 434666 + flags = 1 + data = length 43, hash 8619C423 + sample 32: + time = 437333 + flags = 1 + data = length 43, hash E490BBE + sample 33: + time = 440000 + flags = 1 + data = length 53, hash 8A557CAE + sample 34: + time = 442666 + flags = 1 + data = length 56, hash 81007BBA + sample 35: + time = 445333 + flags = 1 + data = length 56, hash 4E4DD67F + sample 36: + time = 448000 + flags = 1 + data = length 222, hash 414188AB + sample 37: + time = 460000 + flags = 1 + data = length 202, hash 67A07D30 + sample 38: + time = 481333 + flags = 1 + data = length 200, hash E357D853 + sample 39: + time = 502666 + flags = 1 + data = length 203, hash 4653DC90 + sample 40: + time = 524000 + flags = 1 + data = length 192, hash A65E6C09 + sample 41: + time = 545333 + flags = 1 + data = length 202, hash FBEAC508 + sample 42: + time = 566666 + flags = 1 + data = length 202, hash E9B7B59F + sample 43: + time = 588000 + flags = 1 + data = length 204, hash E24AA78E + sample 44: + time = 609333 + flags = 1 + data = length 41, hash 3FBC5216 + sample 45: + time = 621333 + flags = 1 + data = length 47, hash 153FBC55 + sample 46: + time = 624000 + flags = 1 + data = length 42, hash 2B493D6C + sample 47: + time = 626666 + flags = 1 + data = length 42, hash 8303BEE3 + sample 48: + time = 629333 + flags = 1 + data = length 62, hash 71AEE50B + sample 49: + time = 632000 + flags = 1 + data = length 54, hash 52F61908 + sample 50: + time = 634666 + flags = 1 + data = length 45, hash 7BD3E3A1 + sample 51: + time = 637333 + flags = 1 + data = length 41, hash E0F65472 + sample 52: + time = 640000 + flags = 1 + data = length 45, hash 41838675 + sample 53: + time = 642666 + flags = 1 + data = length 44, hash FCBC2147 + sample 54: + time = 645333 + flags = 1 + data = length 45, hash 1A5987E3 + sample 55: + time = 648000 + flags = 1 + data = length 43, hash 99074864 + sample 56: + time = 650666 + flags = 1 + data = length 57, hash D4A9B60A + sample 57: + time = 653333 + flags = 1 + data = length 52, hash 302129DA + sample 58: + time = 656000 + flags = 1 + data = length 57, hash D8DD99C0 + sample 59: + time = 658666 + flags = 1 + data = length 206, hash F4B9EF26 + sample 60: + time = 670666 + flags = 1 + data = length 197, hash 7B8ACC8A + sample 61: + time = 692000 + flags = 1 + data = length 186, hash 161027CB + sample 62: + time = 713333 + flags = 1 + data = length 186, hash 1D6871B6 + sample 63: + time = 734666 + flags = 1 + data = length 201, hash 536E9FDB + sample 64: + time = 756000 + flags = 1 + data = length 192, hash D38EFAC5 + sample 65: + time = 777333 + flags = 1 + data = length 194, hash 4B394EF3 + sample 66: + time = 798666 + flags = 1 + data = length 206, hash 1B31BA99 + sample 67: + time = 820000 + flags = 1 + data = length 212, hash AD061F43 + sample 68: + time = 841333 + flags = 1 + data = length 180, hash 6D1F7481 + sample 69: + time = 862666 + flags = 1 + data = length 195, hash D80B21F + sample 70: + time = 884000 + flags = 1 + data = length 186, hash D367882 + sample 71: + time = 905333 + flags = 1 + data = length 195, hash 2722159A + sample 72: + time = 926666 + flags = 1 + data = length 199, hash 10CEE97A + sample 73: + time = 948000 + flags = 1 + data = length 191, hash 2CF9FB3F + sample 74: + time = 969333 + flags = 1 + data = length 197, hash A725DA0 + sample 75: + time = 990666 + flags = 1 + data = length 211, hash D4E5DB9E + sample 76: + time = 1012000 + flags = 1 + data = length 189, hash 1A90F496 + sample 77: + time = 1033333 + flags = 1 + data = length 187, hash 44DB2689 + sample 78: + time = 1054666 + flags = 1 + data = length 197, hash 6D3E5117 + sample 79: + time = 1076000 + flags = 1 + data = length 208, hash 5B57B288 + sample 80: + time = 1097333 + flags = 1 + data = length 198, hash D5FC05 + sample 81: + time = 1118666 + flags = 1 + data = length 192, hash 350BBA45 + sample 82: + time = 1140000 + flags = 1 + data = length 195, hash 5F96F2A8 + sample 83: + time = 1161333 + flags = 1 + data = length 202, hash 61D7CC33 + sample 84: + time = 1182666 + flags = 1 + data = length 202, hash 49D335F2 + sample 85: + time = 1204000 + flags = 1 + data = length 192, hash 2FE9CB1A + sample 86: + time = 1225333 + flags = 1 + data = length 201, hash BF0763B2 + sample 87: + time = 1246666 + flags = 1 + data = length 184, hash AD047421 + sample 88: + time = 1268000 + flags = 1 + data = length 196, hash F9088F14 + sample 89: + time = 1289333 + flags = 1 + data = length 190, hash AC6D38FD + sample 90: + time = 1310666 + flags = 1 + data = length 195, hash 8D1A66D2 + sample 91: + time = 1332000 + flags = 1 + data = length 197, hash B46BFB6B + sample 92: + time = 1353333 + flags = 1 + data = length 195, hash D9761F23 + sample 93: + time = 1374666 + flags = 1 + data = length 204, hash 3391B617 + sample 94: + time = 1396000 + flags = 1 + data = length 42, hash 33A1FB52 + sample 95: + time = 1408000 + flags = 1 + data = length 44, hash 408B146E + sample 96: + time = 1410666 + flags = 1 + data = length 44, hash 171C7E0D + sample 97: + time = 1413333 + flags = 1 + data = length 54, hash 6307E16C + sample 98: + time = 1416000 + flags = 1 + data = length 53, hash 4A319572 + sample 99: + time = 1418666 + flags = 1 + data = length 215, hash BA9C445C + sample 100: + time = 1430666 + flags = 1 + data = length 201, hash 3120D234 + sample 101: + time = 1452000 + flags = 1 + data = length 187, hash DB44993C + sample 102: + time = 1473333 + flags = 1 + data = length 196, hash CF2002D7 + sample 103: + time = 1494666 + flags = 1 + data = length 185, hash E03B5D7 + sample 104: + time = 1516000 + flags = 1 + data = length 187, hash DA399A2C + sample 105: + time = 1537333 + flags = 1 + data = length 191, hash 292AA0DB + sample 106: + time = 1558666 + flags = 1 + data = length 201, hash 221910E0 + sample 107: + time = 1580000 + flags = 1 + data = length 194, hash F4ED7821 + sample 108: + time = 1601333 + flags = 1 + data = length 43, hash FDDA515E + sample 109: + time = 1613333 + flags = 1 + data = length 42, hash F3571C0A + sample 110: + time = 1616000 + flags = 1 + data = length 38, hash 39F910B3 + sample 111: + time = 1618666 + flags = 1 + data = length 41, hash 2D189531 + sample 112: + time = 1621333 + flags = 1 + data = length 43, hash 1F7574DB + sample 113: + time = 1624000 + flags = 1 + data = length 43, hash 644D15E5 + sample 114: + time = 1626666 + flags = 1 + data = length 49, hash E8A0878 + sample 115: + time = 1629333 + flags = 1 + data = length 55, hash DFF2046D + sample 116: + time = 1632000 + flags = 1 + data = length 49, hash 9FB8A23 + sample 117: + time = 1634666 + flags = 1 + data = length 41, hash E3E15E3B + sample 118: + time = 1637333 + flags = 1 + data = length 42, hash E5D17A32 + sample 119: + time = 1640000 + flags = 1 + data = length 42, hash F308B653 + sample 120: + time = 1642666 + flags = 1 + data = length 55, hash BB750D76 + sample 121: + time = 1645333 + flags = 1 + data = length 51, hash 96772ABF + sample 122: + time = 1648000 + flags = 1 + data = length 197, hash E4524346 + sample 123: + time = 1660000 + flags = 1 + data = length 188, hash AC3E1BB5 + sample 124: + time = 1681333 + flags = 1 + data = length 195, hash F56DB8A5 + sample 125: + time = 1702666 + flags = 1 + data = length 198, hash C8970FF7 + sample 126: + time = 1724000 + flags = 1 + data = length 202, hash AF425C68 + sample 127: + time = 1745333 + flags = 1 + data = length 196, hash 4215D839 + sample 128: + time = 1766666 + flags = 1 + data = length 204, hash DB9BE8E3 + sample 129: + time = 1788000 + flags = 1 + data = length 206, hash E5B20AB8 + sample 130: + time = 1809333 + flags = 1 + data = length 209, hash D7F47B95 + sample 131: + time = 1830666 + flags = 1 + data = length 193, hash FB54FB05 + sample 132: + time = 1852000 + flags = 1 + data = length 199, hash D99C3106 + sample 133: + time = 1873333 + flags = 1 + data = length 206, hash 253885B9 + sample 134: + time = 1894666 + flags = 1 + data = length 191, hash FBDD8162 + sample 135: + time = 1916000 + flags = 1 + data = length 183, hash 7290332F + sample 136: + time = 1937333 + flags = 1 + data = length 189, hash 1A9DC3DE + sample 137: + time = 1958666 + flags = 1 + data = length 201, hash 5D936764 + sample 138: + time = 1980000 + flags = 1 + data = length 193, hash 6B03E75E + sample 139: + time = 2001333 + flags = 1 + data = length 199, hash 8A21BA83 + sample 140: + time = 2022666 + flags = 1 + data = length 41, hash E6362210 + sample 141: + time = 2034666 + flags = 1 + data = length 43, hash 36A57B44 + sample 142: + time = 2037333 + flags = 1 + data = length 43, hash E51797D5 + sample 143: + time = 2040000 + flags = 1 + data = length 43, hash 1F336C72 + sample 144: + time = 2042666 + flags = 1 + data = length 42, hash 201AD367 + sample 145: + time = 2045333 + flags = 1 + data = length 50, hash 606CCD6 + sample 146: + time = 2048000 + flags = 1 + data = length 56, hash B15EBD7A + sample 147: + time = 2050666 + flags = 1 + data = length 212, hash 273B8D22 + sample 148: + time = 2062666 + flags = 1 + data = length 194, hash 44F9CE1 + sample 149: + time = 2084000 + flags = 1 + data = length 195, hash EDF9EBA1 + sample 150: + time = 2105333 + flags = 1 + data = length 194, hash CE9F2D26 + sample 151: + time = 2126666 + flags = 1 + data = length 192, hash 204F8A23 + sample 152: + time = 2148000 + flags = 1 + data = length 206, hash DFA57E67 + sample 153: + time = 2169333 + flags = 1 + data = length 196, hash 3CF084AB + sample 154: + time = 2190666 + flags = 1 + data = length 202, hash 2AF75C08 + sample 155: + time = 2212000 + flags = 1 + data = length 203, hash 748EAF7 + sample 156: + time = 2233333 + flags = 1 + data = length 205, hash ED82379D + sample 157: + time = 2254666 + flags = 1 + data = length 193, hash 61F26F22 + sample 158: + time = 2276000 + flags = 1 + data = length 189, hash 85EF1D20 + sample 159: + time = 2297333 + flags = 1 + data = length 187, hash 25E41FBF + sample 160: + time = 2318666 + flags = 1 + data = length 199, hash F365808 + sample 161: + time = 2340000 + flags = 1 + data = length 197, hash 94205329 + sample 162: + time = 2361333 + flags = 1 + data = length 201, hash FA2B2055 + sample 163: + time = 2382666 + flags = 1 + data = length 194, hash AF95381F + sample 164: + time = 2404000 + flags = 1 + data = length 201, hash 923D3534 + sample 165: + time = 2425333 + flags = 1 + data = length 198, hash 35F84C2E + sample 166: + time = 2446666 + flags = 1 + data = length 204, hash 6642CA40 + sample 167: + time = 2468000 + flags = 1 + data = length 183, hash 3E2DC6BE + sample 168: + time = 2489333 + flags = 1 + data = length 197, hash B1E458CE + sample 169: + time = 2510666 + flags = 1 + data = length 193, hash E9218C84 + sample 170: + time = 2532000 + flags = 1 + data = length 192, hash FEF08D4B + sample 171: + time = 2553333 + flags = 1 + data = length 201, hash FC411147 + sample 172: + time = 2574666 + flags = 1 + data = length 218, hash 86893464 + sample 173: + time = 2596000 + flags = 1 + data = length 226, hash 31C5320 + sample 174: + time = 2617333 + flags = 1 + data = length 233, hash 9432BEE5 + sample 175: + time = 2638666 + flags = 1 + data = length 213, hash B3FCC53E + sample 176: + time = 2660000 + flags = 1 + data = length 204, hash D70DD5A2 + sample 177: + time = 2681333 + flags = 1 + data = length 212, hash A4EF1B69 + sample 178: + time = 2702666 + flags = 1 + data = length 203, hash 8B0748B5 + sample 179: + time = 2724000 + flags = 1 + data = length 149, hash E455335B +tracksEnded = true diff --git a/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.1.dump b/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.1.dump new file mode 100644 index 0000000000..1946984309 --- /dev/null +++ b/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.1.dump @@ -0,0 +1,456 @@ +seekMap: + isSeekable = true + duration = 2741000 + getPosition(0) = [[timeUs=0, position=4005]] + getPosition(1) = [[timeUs=1, position=4005]] + getPosition(1370500) = [[timeUs=1370500, position=4005]] + getPosition(2741000) = [[timeUs=2741000, position=4005]] +numberOfTracks = 1 +track 0: + total output bytes = 17598 + sample count = 109 + format 0: + averageBitrate = 112000 + sampleMimeType = audio/vorbis + channelCount = 2 + sampleRate = 48000 + initializationData: + data = length 30, hash 9A8FF207 + data = length 3832, hash 8A406249 + sample 0: + time = 896000 + flags = 1 + data = length 195, hash 2722159A + sample 1: + time = 917333 + flags = 1 + data = length 199, hash 10CEE97A + sample 2: + time = 938666 + flags = 1 + data = length 191, hash 2CF9FB3F + sample 3: + time = 960000 + flags = 1 + data = length 197, hash A725DA0 + sample 4: + time = 981333 + flags = 1 + data = length 211, hash D4E5DB9E + sample 5: + time = 1002666 + flags = 1 + data = length 189, hash 1A90F496 + sample 6: + time = 1024000 + flags = 1 + data = length 187, hash 44DB2689 + sample 7: + time = 1045333 + flags = 1 + data = length 197, hash 6D3E5117 + sample 8: + time = 1066666 + flags = 1 + data = length 208, hash 5B57B288 + sample 9: + time = 1088000 + flags = 1 + data = length 198, hash D5FC05 + sample 10: + time = 1109333 + flags = 1 + data = length 192, hash 350BBA45 + sample 11: + time = 1130666 + flags = 1 + data = length 195, hash 5F96F2A8 + sample 12: + time = 1152000 + flags = 1 + data = length 202, hash 61D7CC33 + sample 13: + time = 1173333 + flags = 1 + data = length 202, hash 49D335F2 + sample 14: + time = 1194666 + flags = 1 + data = length 192, hash 2FE9CB1A + sample 15: + time = 1216000 + flags = 1 + data = length 201, hash BF0763B2 + sample 16: + time = 1237333 + flags = 1 + data = length 184, hash AD047421 + sample 17: + time = 1258666 + flags = 1 + data = length 196, hash F9088F14 + sample 18: + time = 1280000 + flags = 1 + data = length 190, hash AC6D38FD + sample 19: + time = 1301333 + flags = 1 + data = length 195, hash 8D1A66D2 + sample 20: + time = 1322666 + flags = 1 + data = length 197, hash B46BFB6B + sample 21: + time = 1344000 + flags = 1 + data = length 195, hash D9761F23 + sample 22: + time = 1365333 + flags = 1 + data = length 204, hash 3391B617 + sample 23: + time = 1386666 + flags = 1 + data = length 42, hash 33A1FB52 + sample 24: + time = 1398666 + flags = 1 + data = length 44, hash 408B146E + sample 25: + time = 1401333 + flags = 1 + data = length 44, hash 171C7E0D + sample 26: + time = 1404000 + flags = 1 + data = length 54, hash 6307E16C + sample 27: + time = 1406666 + flags = 1 + data = length 53, hash 4A319572 + sample 28: + time = 1409333 + flags = 1 + data = length 215, hash BA9C445C + sample 29: + time = 1421333 + flags = 1 + data = length 201, hash 3120D234 + sample 30: + time = 1442666 + flags = 1 + data = length 187, hash DB44993C + sample 31: + time = 1464000 + flags = 1 + data = length 196, hash CF2002D7 + sample 32: + time = 1485333 + flags = 1 + data = length 185, hash E03B5D7 + sample 33: + time = 1506666 + flags = 1 + data = length 187, hash DA399A2C + sample 34: + time = 1528000 + flags = 1 + data = length 191, hash 292AA0DB + sample 35: + time = 1549333 + flags = 1 + data = length 201, hash 221910E0 + sample 36: + time = 1570666 + flags = 1 + data = length 194, hash F4ED7821 + sample 37: + time = 1592000 + flags = 1 + data = length 43, hash FDDA515E + sample 38: + time = 1604000 + flags = 1 + data = length 42, hash F3571C0A + sample 39: + time = 1606666 + flags = 1 + data = length 38, hash 39F910B3 + sample 40: + time = 1609333 + flags = 1 + data = length 41, hash 2D189531 + sample 41: + time = 1612000 + flags = 1 + data = length 43, hash 1F7574DB + sample 42: + time = 1614666 + flags = 1 + data = length 43, hash 644D15E5 + sample 43: + time = 1617333 + flags = 1 + data = length 49, hash E8A0878 + sample 44: + time = 1620000 + flags = 1 + data = length 55, hash DFF2046D + sample 45: + time = 1622666 + flags = 1 + data = length 49, hash 9FB8A23 + sample 46: + time = 1625333 + flags = 1 + data = length 41, hash E3E15E3B + sample 47: + time = 1628000 + flags = 1 + data = length 42, hash E5D17A32 + sample 48: + time = 1630666 + flags = 1 + data = length 42, hash F308B653 + sample 49: + time = 1633333 + flags = 1 + data = length 55, hash BB750D76 + sample 50: + time = 1636000 + flags = 1 + data = length 51, hash 96772ABF + sample 51: + time = 1638666 + flags = 1 + data = length 197, hash E4524346 + sample 52: + time = 1650666 + flags = 1 + data = length 188, hash AC3E1BB5 + sample 53: + time = 1672000 + flags = 1 + data = length 195, hash F56DB8A5 + sample 54: + time = 1693333 + flags = 1 + data = length 198, hash C8970FF7 + sample 55: + time = 1714666 + flags = 1 + data = length 202, hash AF425C68 + sample 56: + time = 1736000 + flags = 1 + data = length 196, hash 4215D839 + sample 57: + time = 1757333 + flags = 1 + data = length 204, hash DB9BE8E3 + sample 58: + time = 1778666 + flags = 1 + data = length 206, hash E5B20AB8 + sample 59: + time = 1800000 + flags = 1 + data = length 209, hash D7F47B95 + sample 60: + time = 1821333 + flags = 1 + data = length 193, hash FB54FB05 + sample 61: + time = 1842666 + flags = 1 + data = length 199, hash D99C3106 + sample 62: + time = 1864000 + flags = 1 + data = length 206, hash 253885B9 + sample 63: + time = 1885333 + flags = 1 + data = length 191, hash FBDD8162 + sample 64: + time = 1906666 + flags = 1 + data = length 183, hash 7290332F + sample 65: + time = 1928000 + flags = 1 + data = length 189, hash 1A9DC3DE + sample 66: + time = 1949333 + flags = 1 + data = length 201, hash 5D936764 + sample 67: + time = 1970666 + flags = 1 + data = length 193, hash 6B03E75E + sample 68: + time = 1992000 + flags = 1 + data = length 199, hash 8A21BA83 + sample 69: + time = 2013333 + flags = 1 + data = length 41, hash E6362210 + sample 70: + time = 2025333 + flags = 1 + data = length 43, hash 36A57B44 + sample 71: + time = 2028000 + flags = 1 + data = length 43, hash E51797D5 + sample 72: + time = 2030666 + flags = 1 + data = length 43, hash 1F336C72 + sample 73: + time = 2033333 + flags = 1 + data = length 42, hash 201AD367 + sample 74: + time = 2036000 + flags = 1 + data = length 50, hash 606CCD6 + sample 75: + time = 2038666 + flags = 1 + data = length 56, hash B15EBD7A + sample 76: + time = 2041333 + flags = 1 + data = length 212, hash 273B8D22 + sample 77: + time = 2053333 + flags = 1 + data = length 194, hash 44F9CE1 + sample 78: + time = 2074666 + flags = 1 + data = length 195, hash EDF9EBA1 + sample 79: + time = 2096000 + flags = 1 + data = length 194, hash CE9F2D26 + sample 80: + time = 2117333 + flags = 1 + data = length 192, hash 204F8A23 + sample 81: + time = 2138666 + flags = 1 + data = length 206, hash DFA57E67 + sample 82: + time = 2160000 + flags = 1 + data = length 196, hash 3CF084AB + sample 83: + time = 2181333 + flags = 1 + data = length 202, hash 2AF75C08 + sample 84: + time = 2202666 + flags = 1 + data = length 203, hash 748EAF7 + sample 85: + time = 2224000 + flags = 1 + data = length 205, hash ED82379D + sample 86: + time = 2245333 + flags = 1 + data = length 193, hash 61F26F22 + sample 87: + time = 2266666 + flags = 1 + data = length 189, hash 85EF1D20 + sample 88: + time = 2288000 + flags = 1 + data = length 187, hash 25E41FBF + sample 89: + time = 2309333 + flags = 1 + data = length 199, hash F365808 + sample 90: + time = 2330666 + flags = 1 + data = length 197, hash 94205329 + sample 91: + time = 2352000 + flags = 1 + data = length 201, hash FA2B2055 + sample 92: + time = 2373333 + flags = 1 + data = length 194, hash AF95381F + sample 93: + time = 2394666 + flags = 1 + data = length 201, hash 923D3534 + sample 94: + time = 2416000 + flags = 1 + data = length 198, hash 35F84C2E + sample 95: + time = 2437333 + flags = 1 + data = length 204, hash 6642CA40 + sample 96: + time = 2458666 + flags = 1 + data = length 183, hash 3E2DC6BE + sample 97: + time = 2480000 + flags = 1 + data = length 197, hash B1E458CE + sample 98: + time = 2501333 + flags = 1 + data = length 193, hash E9218C84 + sample 99: + time = 2522666 + flags = 1 + data = length 192, hash FEF08D4B + sample 100: + time = 2544000 + flags = 1 + data = length 201, hash FC411147 + sample 101: + time = 2565333 + flags = 1 + data = length 218, hash 86893464 + sample 102: + time = 2586666 + flags = 1 + data = length 226, hash 31C5320 + sample 103: + time = 2608000 + flags = 1 + data = length 233, hash 9432BEE5 + sample 104: + time = 2629333 + flags = 1 + data = length 213, hash B3FCC53E + sample 105: + time = 2650666 + flags = 1 + data = length 204, hash D70DD5A2 + sample 106: + time = 2672000 + flags = 1 + data = length 212, hash A4EF1B69 + sample 107: + time = 2693333 + flags = 1 + data = length 203, hash 8B0748B5 + sample 108: + time = 2714666 + flags = 1 + data = length 149, hash E455335B +tracksEnded = true diff --git a/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.2.dump b/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.2.dump new file mode 100644 index 0000000000..b936c3621a --- /dev/null +++ b/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.2.dump @@ -0,0 +1,216 @@ +seekMap: + isSeekable = true + duration = 2741000 + getPosition(0) = [[timeUs=0, position=4005]] + getPosition(1) = [[timeUs=1, position=4005]] + getPosition(1370500) = [[timeUs=1370500, position=4005]] + getPosition(2741000) = [[timeUs=2741000, position=4005]] +numberOfTracks = 1 +track 0: + total output bytes = 8658 + sample count = 49 + format 0: + averageBitrate = 112000 + sampleMimeType = audio/vorbis + channelCount = 2 + sampleRate = 48000 + initializationData: + data = length 30, hash 9A8FF207 + data = length 3832, hash 8A406249 + sample 0: + time = 1821333 + flags = 1 + data = length 193, hash FB54FB05 + sample 1: + time = 1842666 + flags = 1 + data = length 199, hash D99C3106 + sample 2: + time = 1864000 + flags = 1 + data = length 206, hash 253885B9 + sample 3: + time = 1885333 + flags = 1 + data = length 191, hash FBDD8162 + sample 4: + time = 1906666 + flags = 1 + data = length 183, hash 7290332F + sample 5: + time = 1928000 + flags = 1 + data = length 189, hash 1A9DC3DE + sample 6: + time = 1949333 + flags = 1 + data = length 201, hash 5D936764 + sample 7: + time = 1970666 + flags = 1 + data = length 193, hash 6B03E75E + sample 8: + time = 1992000 + flags = 1 + data = length 199, hash 8A21BA83 + sample 9: + time = 2013333 + flags = 1 + data = length 41, hash E6362210 + sample 10: + time = 2025333 + flags = 1 + data = length 43, hash 36A57B44 + sample 11: + time = 2028000 + flags = 1 + data = length 43, hash E51797D5 + sample 12: + time = 2030666 + flags = 1 + data = length 43, hash 1F336C72 + sample 13: + time = 2033333 + flags = 1 + data = length 42, hash 201AD367 + sample 14: + time = 2036000 + flags = 1 + data = length 50, hash 606CCD6 + sample 15: + time = 2038666 + flags = 1 + data = length 56, hash B15EBD7A + sample 16: + time = 2041333 + flags = 1 + data = length 212, hash 273B8D22 + sample 17: + time = 2053333 + flags = 1 + data = length 194, hash 44F9CE1 + sample 18: + time = 2074666 + flags = 1 + data = length 195, hash EDF9EBA1 + sample 19: + time = 2096000 + flags = 1 + data = length 194, hash CE9F2D26 + sample 20: + time = 2117333 + flags = 1 + data = length 192, hash 204F8A23 + sample 21: + time = 2138666 + flags = 1 + data = length 206, hash DFA57E67 + sample 22: + time = 2160000 + flags = 1 + data = length 196, hash 3CF084AB + sample 23: + time = 2181333 + flags = 1 + data = length 202, hash 2AF75C08 + sample 24: + time = 2202666 + flags = 1 + data = length 203, hash 748EAF7 + sample 25: + time = 2224000 + flags = 1 + data = length 205, hash ED82379D + sample 26: + time = 2245333 + flags = 1 + data = length 193, hash 61F26F22 + sample 27: + time = 2266666 + flags = 1 + data = length 189, hash 85EF1D20 + sample 28: + time = 2288000 + flags = 1 + data = length 187, hash 25E41FBF + sample 29: + time = 2309333 + flags = 1 + data = length 199, hash F365808 + sample 30: + time = 2330666 + flags = 1 + data = length 197, hash 94205329 + sample 31: + time = 2352000 + flags = 1 + data = length 201, hash FA2B2055 + sample 32: + time = 2373333 + flags = 1 + data = length 194, hash AF95381F + sample 33: + time = 2394666 + flags = 1 + data = length 201, hash 923D3534 + sample 34: + time = 2416000 + flags = 1 + data = length 198, hash 35F84C2E + sample 35: + time = 2437333 + flags = 1 + data = length 204, hash 6642CA40 + sample 36: + time = 2458666 + flags = 1 + data = length 183, hash 3E2DC6BE + sample 37: + time = 2480000 + flags = 1 + data = length 197, hash B1E458CE + sample 38: + time = 2501333 + flags = 1 + data = length 193, hash E9218C84 + sample 39: + time = 2522666 + flags = 1 + data = length 192, hash FEF08D4B + sample 40: + time = 2544000 + flags = 1 + data = length 201, hash FC411147 + sample 41: + time = 2565333 + flags = 1 + data = length 218, hash 86893464 + sample 42: + time = 2586666 + flags = 1 + data = length 226, hash 31C5320 + sample 43: + time = 2608000 + flags = 1 + data = length 233, hash 9432BEE5 + sample 44: + time = 2629333 + flags = 1 + data = length 213, hash B3FCC53E + sample 45: + time = 2650666 + flags = 1 + data = length 204, hash D70DD5A2 + sample 46: + time = 2672000 + flags = 1 + data = length 212, hash A4EF1B69 + sample 47: + time = 2693333 + flags = 1 + data = length 203, hash 8B0748B5 + sample 48: + time = 2714666 + flags = 1 + data = length 149, hash E455335B +tracksEnded = true diff --git a/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.3.dump b/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.3.dump new file mode 100644 index 0000000000..91fc8a7b09 --- /dev/null +++ b/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.3.dump @@ -0,0 +1,20 @@ +seekMap: + isSeekable = true + duration = 2741000 + getPosition(0) = [[timeUs=0, position=4005]] + getPosition(1) = [[timeUs=1, position=4005]] + getPosition(1370500) = [[timeUs=1370500, position=4005]] + getPosition(2741000) = [[timeUs=2741000, position=4005]] +numberOfTracks = 1 +track 0: + total output bytes = 0 + sample count = 0 + format 0: + averageBitrate = 112000 + sampleMimeType = audio/vorbis + channelCount = 2 + sampleRate = 48000 + initializationData: + data = length 30, hash 9A8FF207 + data = length 3832, hash 8A406249 +tracksEnded = true diff --git a/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.unknown_length.dump b/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.unknown_length.dump new file mode 100644 index 0000000000..9830a08357 --- /dev/null +++ b/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg.unknown_length.dump @@ -0,0 +1,737 @@ +seekMap: + isSeekable = false + duration = UNSET TIME + getPosition(0) = [[timeUs=0, position=0]] +numberOfTracks = 1 +track 0: + total output bytes = 26873 + sample count = 180 + format 0: + averageBitrate = 112000 + sampleMimeType = audio/vorbis + channelCount = 2 + sampleRate = 48000 + initializationData: + data = length 30, hash 9A8FF207 + data = length 3832, hash 8A406249 + sample 0: + time = 0 + flags = 1 + data = length 49, hash 2FFF94F0 + sample 1: + time = 0 + flags = 1 + data = length 44, hash 3946418A + sample 2: + time = 2666 + flags = 1 + data = length 55, hash 2A0B878E + sample 3: + time = 5333 + flags = 1 + data = length 53, hash CC3B6879 + sample 4: + time = 8000 + flags = 1 + data = length 215, hash 106AE950 + sample 5: + time = 20000 + flags = 1 + data = length 192, hash 2B219F53 + sample 6: + time = 41333 + flags = 1 + data = length 197, hash FBC39422 + sample 7: + time = 62666 + flags = 1 + data = length 209, hash 386E8979 + sample 8: + time = 84000 + flags = 1 + data = length 42, hash E81162C1 + sample 9: + time = 96000 + flags = 1 + data = length 41, hash F15BEE36 + sample 10: + time = 98666 + flags = 1 + data = length 42, hash D67EB19 + sample 11: + time = 101333 + flags = 1 + data = length 42, hash F4DE4792 + sample 12: + time = 104000 + flags = 1 + data = length 53, hash 80F66AC3 + sample 13: + time = 106666 + flags = 1 + data = length 56, hash DCB9DFC4 + sample 14: + time = 109333 + flags = 1 + data = length 55, hash 4E0C4E9D + sample 15: + time = 112000 + flags = 1 + data = length 203, hash 176B6862 + sample 16: + time = 124000 + flags = 1 + data = length 193, hash AB13CB10 + sample 17: + time = 145333 + flags = 1 + data = length 203, hash DE63DE9F + sample 18: + time = 166666 + flags = 1 + data = length 194, hash 4A9508A2 + sample 19: + time = 188000 + flags = 1 + data = length 210, hash 196899B3 + sample 20: + time = 209333 + flags = 1 + data = length 195, hash B68407F1 + sample 21: + time = 230666 + flags = 1 + data = length 193, hash A1FA86E3 + sample 22: + time = 252000 + flags = 1 + data = length 194, hash 5C0B9343 + sample 23: + time = 273333 + flags = 1 + data = length 198, hash 789914B2 + sample 24: + time = 294666 + flags = 1 + data = length 183, hash 1B82D11F + sample 25: + time = 316000 + flags = 1 + data = length 199, hash D5B848F4 + sample 26: + time = 337333 + flags = 1 + data = length 192, hash B34427EA + sample 27: + time = 358666 + flags = 1 + data = length 199, hash C2599BB5 + sample 28: + time = 380000 + flags = 1 + data = length 195, hash BFD83194 + sample 29: + time = 401333 + flags = 1 + data = length 199, hash C9A7F7CA + sample 30: + time = 422666 + flags = 1 + data = length 44, hash 5D76EAD6 + sample 31: + time = 434666 + flags = 1 + data = length 43, hash 8619C423 + sample 32: + time = 437333 + flags = 1 + data = length 43, hash E490BBE + sample 33: + time = 440000 + flags = 1 + data = length 53, hash 8A557CAE + sample 34: + time = 442666 + flags = 1 + data = length 56, hash 81007BBA + sample 35: + time = 445333 + flags = 1 + data = length 56, hash 4E4DD67F + sample 36: + time = 448000 + flags = 1 + data = length 222, hash 414188AB + sample 37: + time = 460000 + flags = 1 + data = length 202, hash 67A07D30 + sample 38: + time = 481333 + flags = 1 + data = length 200, hash E357D853 + sample 39: + time = 502666 + flags = 1 + data = length 203, hash 4653DC90 + sample 40: + time = 524000 + flags = 1 + data = length 192, hash A65E6C09 + sample 41: + time = 545333 + flags = 1 + data = length 202, hash FBEAC508 + sample 42: + time = 566666 + flags = 1 + data = length 202, hash E9B7B59F + sample 43: + time = 588000 + flags = 1 + data = length 204, hash E24AA78E + sample 44: + time = 609333 + flags = 1 + data = length 41, hash 3FBC5216 + sample 45: + time = 621333 + flags = 1 + data = length 47, hash 153FBC55 + sample 46: + time = 624000 + flags = 1 + data = length 42, hash 2B493D6C + sample 47: + time = 626666 + flags = 1 + data = length 42, hash 8303BEE3 + sample 48: + time = 629333 + flags = 1 + data = length 62, hash 71AEE50B + sample 49: + time = 632000 + flags = 1 + data = length 54, hash 52F61908 + sample 50: + time = 634666 + flags = 1 + data = length 45, hash 7BD3E3A1 + sample 51: + time = 637333 + flags = 1 + data = length 41, hash E0F65472 + sample 52: + time = 640000 + flags = 1 + data = length 45, hash 41838675 + sample 53: + time = 642666 + flags = 1 + data = length 44, hash FCBC2147 + sample 54: + time = 645333 + flags = 1 + data = length 45, hash 1A5987E3 + sample 55: + time = 648000 + flags = 1 + data = length 43, hash 99074864 + sample 56: + time = 650666 + flags = 1 + data = length 57, hash D4A9B60A + sample 57: + time = 653333 + flags = 1 + data = length 52, hash 302129DA + sample 58: + time = 656000 + flags = 1 + data = length 57, hash D8DD99C0 + sample 59: + time = 658666 + flags = 1 + data = length 206, hash F4B9EF26 + sample 60: + time = 670666 + flags = 1 + data = length 197, hash 7B8ACC8A + sample 61: + time = 692000 + flags = 1 + data = length 186, hash 161027CB + sample 62: + time = 713333 + flags = 1 + data = length 186, hash 1D6871B6 + sample 63: + time = 734666 + flags = 1 + data = length 201, hash 536E9FDB + sample 64: + time = 756000 + flags = 1 + data = length 192, hash D38EFAC5 + sample 65: + time = 777333 + flags = 1 + data = length 194, hash 4B394EF3 + sample 66: + time = 798666 + flags = 1 + data = length 206, hash 1B31BA99 + sample 67: + time = 820000 + flags = 1 + data = length 212, hash AD061F43 + sample 68: + time = 841333 + flags = 1 + data = length 180, hash 6D1F7481 + sample 69: + time = 862666 + flags = 1 + data = length 195, hash D80B21F + sample 70: + time = 884000 + flags = 1 + data = length 186, hash D367882 + sample 71: + time = 905333 + flags = 1 + data = length 195, hash 2722159A + sample 72: + time = 926666 + flags = 1 + data = length 199, hash 10CEE97A + sample 73: + time = 948000 + flags = 1 + data = length 191, hash 2CF9FB3F + sample 74: + time = 969333 + flags = 1 + data = length 197, hash A725DA0 + sample 75: + time = 990666 + flags = 1 + data = length 211, hash D4E5DB9E + sample 76: + time = 1012000 + flags = 1 + data = length 189, hash 1A90F496 + sample 77: + time = 1033333 + flags = 1 + data = length 187, hash 44DB2689 + sample 78: + time = 1054666 + flags = 1 + data = length 197, hash 6D3E5117 + sample 79: + time = 1076000 + flags = 1 + data = length 208, hash 5B57B288 + sample 80: + time = 1097333 + flags = 1 + data = length 198, hash D5FC05 + sample 81: + time = 1118666 + flags = 1 + data = length 192, hash 350BBA45 + sample 82: + time = 1140000 + flags = 1 + data = length 195, hash 5F96F2A8 + sample 83: + time = 1161333 + flags = 1 + data = length 202, hash 61D7CC33 + sample 84: + time = 1182666 + flags = 1 + data = length 202, hash 49D335F2 + sample 85: + time = 1204000 + flags = 1 + data = length 192, hash 2FE9CB1A + sample 86: + time = 1225333 + flags = 1 + data = length 201, hash BF0763B2 + sample 87: + time = 1246666 + flags = 1 + data = length 184, hash AD047421 + sample 88: + time = 1268000 + flags = 1 + data = length 196, hash F9088F14 + sample 89: + time = 1289333 + flags = 1 + data = length 190, hash AC6D38FD + sample 90: + time = 1310666 + flags = 1 + data = length 195, hash 8D1A66D2 + sample 91: + time = 1332000 + flags = 1 + data = length 197, hash B46BFB6B + sample 92: + time = 1353333 + flags = 1 + data = length 195, hash D9761F23 + sample 93: + time = 1374666 + flags = 1 + data = length 204, hash 3391B617 + sample 94: + time = 1396000 + flags = 1 + data = length 42, hash 33A1FB52 + sample 95: + time = 1408000 + flags = 1 + data = length 44, hash 408B146E + sample 96: + time = 1410666 + flags = 1 + data = length 44, hash 171C7E0D + sample 97: + time = 1413333 + flags = 1 + data = length 54, hash 6307E16C + sample 98: + time = 1416000 + flags = 1 + data = length 53, hash 4A319572 + sample 99: + time = 1418666 + flags = 1 + data = length 215, hash BA9C445C + sample 100: + time = 1430666 + flags = 1 + data = length 201, hash 3120D234 + sample 101: + time = 1452000 + flags = 1 + data = length 187, hash DB44993C + sample 102: + time = 1473333 + flags = 1 + data = length 196, hash CF2002D7 + sample 103: + time = 1494666 + flags = 1 + data = length 185, hash E03B5D7 + sample 104: + time = 1516000 + flags = 1 + data = length 187, hash DA399A2C + sample 105: + time = 1537333 + flags = 1 + data = length 191, hash 292AA0DB + sample 106: + time = 1558666 + flags = 1 + data = length 201, hash 221910E0 + sample 107: + time = 1580000 + flags = 1 + data = length 194, hash F4ED7821 + sample 108: + time = 1601333 + flags = 1 + data = length 43, hash FDDA515E + sample 109: + time = 1613333 + flags = 1 + data = length 42, hash F3571C0A + sample 110: + time = 1616000 + flags = 1 + data = length 38, hash 39F910B3 + sample 111: + time = 1618666 + flags = 1 + data = length 41, hash 2D189531 + sample 112: + time = 1621333 + flags = 1 + data = length 43, hash 1F7574DB + sample 113: + time = 1624000 + flags = 1 + data = length 43, hash 644D15E5 + sample 114: + time = 1626666 + flags = 1 + data = length 49, hash E8A0878 + sample 115: + time = 1629333 + flags = 1 + data = length 55, hash DFF2046D + sample 116: + time = 1632000 + flags = 1 + data = length 49, hash 9FB8A23 + sample 117: + time = 1634666 + flags = 1 + data = length 41, hash E3E15E3B + sample 118: + time = 1637333 + flags = 1 + data = length 42, hash E5D17A32 + sample 119: + time = 1640000 + flags = 1 + data = length 42, hash F308B653 + sample 120: + time = 1642666 + flags = 1 + data = length 55, hash BB750D76 + sample 121: + time = 1645333 + flags = 1 + data = length 51, hash 96772ABF + sample 122: + time = 1648000 + flags = 1 + data = length 197, hash E4524346 + sample 123: + time = 1660000 + flags = 1 + data = length 188, hash AC3E1BB5 + sample 124: + time = 1681333 + flags = 1 + data = length 195, hash F56DB8A5 + sample 125: + time = 1702666 + flags = 1 + data = length 198, hash C8970FF7 + sample 126: + time = 1724000 + flags = 1 + data = length 202, hash AF425C68 + sample 127: + time = 1745333 + flags = 1 + data = length 196, hash 4215D839 + sample 128: + time = 1766666 + flags = 1 + data = length 204, hash DB9BE8E3 + sample 129: + time = 1788000 + flags = 1 + data = length 206, hash E5B20AB8 + sample 130: + time = 1809333 + flags = 1 + data = length 209, hash D7F47B95 + sample 131: + time = 1830666 + flags = 1 + data = length 193, hash FB54FB05 + sample 132: + time = 1852000 + flags = 1 + data = length 199, hash D99C3106 + sample 133: + time = 1873333 + flags = 1 + data = length 206, hash 253885B9 + sample 134: + time = 1894666 + flags = 1 + data = length 191, hash FBDD8162 + sample 135: + time = 1916000 + flags = 1 + data = length 183, hash 7290332F + sample 136: + time = 1937333 + flags = 1 + data = length 189, hash 1A9DC3DE + sample 137: + time = 1958666 + flags = 1 + data = length 201, hash 5D936764 + sample 138: + time = 1980000 + flags = 1 + data = length 193, hash 6B03E75E + sample 139: + time = 2001333 + flags = 1 + data = length 199, hash 8A21BA83 + sample 140: + time = 2022666 + flags = 1 + data = length 41, hash E6362210 + sample 141: + time = 2034666 + flags = 1 + data = length 43, hash 36A57B44 + sample 142: + time = 2037333 + flags = 1 + data = length 43, hash E51797D5 + sample 143: + time = 2040000 + flags = 1 + data = length 43, hash 1F336C72 + sample 144: + time = 2042666 + flags = 1 + data = length 42, hash 201AD367 + sample 145: + time = 2045333 + flags = 1 + data = length 50, hash 606CCD6 + sample 146: + time = 2048000 + flags = 1 + data = length 56, hash B15EBD7A + sample 147: + time = 2050666 + flags = 1 + data = length 212, hash 273B8D22 + sample 148: + time = 2062666 + flags = 1 + data = length 194, hash 44F9CE1 + sample 149: + time = 2084000 + flags = 1 + data = length 195, hash EDF9EBA1 + sample 150: + time = 2105333 + flags = 1 + data = length 194, hash CE9F2D26 + sample 151: + time = 2126666 + flags = 1 + data = length 192, hash 204F8A23 + sample 152: + time = 2148000 + flags = 1 + data = length 206, hash DFA57E67 + sample 153: + time = 2169333 + flags = 1 + data = length 196, hash 3CF084AB + sample 154: + time = 2190666 + flags = 1 + data = length 202, hash 2AF75C08 + sample 155: + time = 2212000 + flags = 1 + data = length 203, hash 748EAF7 + sample 156: + time = 2233333 + flags = 1 + data = length 205, hash ED82379D + sample 157: + time = 2254666 + flags = 1 + data = length 193, hash 61F26F22 + sample 158: + time = 2276000 + flags = 1 + data = length 189, hash 85EF1D20 + sample 159: + time = 2297333 + flags = 1 + data = length 187, hash 25E41FBF + sample 160: + time = 2318666 + flags = 1 + data = length 199, hash F365808 + sample 161: + time = 2340000 + flags = 1 + data = length 197, hash 94205329 + sample 162: + time = 2361333 + flags = 1 + data = length 201, hash FA2B2055 + sample 163: + time = 2382666 + flags = 1 + data = length 194, hash AF95381F + sample 164: + time = 2404000 + flags = 1 + data = length 201, hash 923D3534 + sample 165: + time = 2425333 + flags = 1 + data = length 198, hash 35F84C2E + sample 166: + time = 2446666 + flags = 1 + data = length 204, hash 6642CA40 + sample 167: + time = 2468000 + flags = 1 + data = length 183, hash 3E2DC6BE + sample 168: + time = 2489333 + flags = 1 + data = length 197, hash B1E458CE + sample 169: + time = 2510666 + flags = 1 + data = length 193, hash E9218C84 + sample 170: + time = 2532000 + flags = 1 + data = length 192, hash FEF08D4B + sample 171: + time = 2553333 + flags = 1 + data = length 201, hash FC411147 + sample 172: + time = 2574666 + flags = 1 + data = length 218, hash 86893464 + sample 173: + time = 2596000 + flags = 1 + data = length 226, hash 31C5320 + sample 174: + time = 2617333 + flags = 1 + data = length 233, hash 9432BEE5 + sample 175: + time = 2638666 + flags = 1 + data = length 213, hash B3FCC53E + sample 176: + time = 2660000 + flags = 1 + data = length 204, hash D70DD5A2 + sample 177: + time = 2681333 + flags = 1 + data = length 212, hash A4EF1B69 + sample 178: + time = 2702666 + flags = 1 + data = length 203, hash 8B0748B5 + sample 179: + time = 2724000 + flags = 1 + data = length 149, hash E455335B +tracksEnded = true