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 {
+ 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 0000000000..99d3efac44
Binary files /dev/null and b/testdata/src/test/assets/ogg/bear_vorbis_gap.ogg differ
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