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 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