diff --git a/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerTest.java b/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerTest.java index cccc619a0e..71edba0612 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerTest.java +++ b/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerTest.java @@ -27,9 +27,9 @@ import junit.framework.TestCase; */ public final class DefaultOggSeekerTest extends TestCase { - public void testSetupUnboundAudioLength() { + public void testSetupWithUnsetEndPositionFails() { try { - new DefaultOggSeeker(0, C.LENGTH_UNSET, new TestStreamReader()); + new DefaultOggSeeker(0, C.LENGTH_UNSET, new TestStreamReader(), 1, 1); fail(); } catch (IllegalArgumentException e) { // ignored @@ -43,11 +43,12 @@ public final class DefaultOggSeekerTest extends TestCase { } } - public void testSeeking(Random random) throws IOException, InterruptedException { + private void testSeeking(Random random) throws IOException, InterruptedException { OggTestFile testFile = OggTestFile.generate(random, 1000); FakeExtractorInput input = new FakeExtractorInput.Builder().setData(testFile.data).build(); TestStreamReader streamReader = new TestStreamReader(); - DefaultOggSeeker oggSeeker = new DefaultOggSeeker(0, testFile.data.length, streamReader); + DefaultOggSeeker oggSeeker = new DefaultOggSeeker(0, testFile.data.length, streamReader, + testFile.firstPayloadPageSize, testFile.firstPayloadPageGranulePosition); OggPageHeader pageHeader = new OggPageHeader(); while (true) { diff --git a/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerUtilMethodsTest.java b/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerUtilMethodsTest.java index 052f45b8f4..5431d35bdf 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerUtilMethodsTest.java +++ b/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeekerUtilMethodsTest.java @@ -29,7 +29,7 @@ import junit.framework.TestCase; public class DefaultOggSeekerUtilMethodsTest extends TestCase { private Random random = new Random(0); - + public void testSkipToNextPage() throws Exception { FakeExtractorInput extractorInput = TestData.createInput( TestUtil.joinByteArrays( @@ -75,7 +75,7 @@ public class DefaultOggSeekerUtilMethodsTest extends TestCase { private static void skipToNextPage(ExtractorInput extractorInput) throws IOException, InterruptedException { DefaultOggSeeker oggSeeker = new DefaultOggSeeker(0, extractorInput.getLength(), - new FlacReader()); + new FlacReader(), 1, 2); while (true) { try { oggSeeker.skipToNextPage(extractorInput); @@ -143,7 +143,7 @@ public class DefaultOggSeekerUtilMethodsTest extends TestCase { private void skipToPageOfGranule(ExtractorInput input, long granule, long elapsedSamplesExpected) throws IOException, InterruptedException { - DefaultOggSeeker oggSeeker = new DefaultOggSeeker(0, input.getLength(), new FlacReader()); + DefaultOggSeeker oggSeeker = new DefaultOggSeeker(0, input.getLength(), new FlacReader(), 1, 2); while (true) { try { assertEquals(elapsedSamplesExpected, oggSeeker.skipToPageOfGranule(input, granule, -1)); @@ -193,7 +193,7 @@ public class DefaultOggSeekerUtilMethodsTest extends TestCase { private void assertReadGranuleOfLastPage(FakeExtractorInput input, int expected) throws IOException, InterruptedException { - DefaultOggSeeker oggSeeker = new DefaultOggSeeker(0, input.getLength(), new FlacReader()); + DefaultOggSeeker oggSeeker = new DefaultOggSeeker(0, input.getLength(), new FlacReader(), 1, 2); while (true) { try { assertEquals(expected, oggSeeker.readGranuleOfLastPage(input)); diff --git a/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/OggTestFile.java b/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/OggTestFile.java index 88f36d35c1..b1294c7a14 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/OggTestFile.java +++ b/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ogg/OggTestFile.java @@ -33,12 +33,17 @@ import junit.framework.Assert; long lastGranule; int packetCount; int pageCount; + int firstPayloadPageSize; + long firstPayloadPageGranulePosition; - private OggTestFile(byte[] data, long lastGranule, int packetCount, int pageCount) { + private OggTestFile(byte[] data, long lastGranule, int packetCount, int pageCount, + int firstPayloadPageSize, long firstPayloadPageGranulePosition) { this.data = data; this.lastGranule = lastGranule; this.packetCount = packetCount; this.pageCount = pageCount; + this.firstPayloadPageSize = firstPayloadPageSize; + this.firstPayloadPageGranulePosition = firstPayloadPageGranulePosition; } public static OggTestFile generate(Random random, int pageCount) { @@ -47,6 +52,8 @@ import junit.framework.Assert; long granule = 0; int packetLength = -1; int packetCount = 0; + int firstPayloadPageSize = 0; + long firstPayloadPageGranulePosition = 0; for (int i = 0; i < pageCount; i++) { int headerType = 0x00; @@ -89,6 +96,10 @@ import junit.framework.Assert; byte[] payload = TestUtil.buildTestData(bodySize, random); fileData.add(payload); fileSize += payload.length; + if (i == 0) { + firstPayloadPageSize = header.length + bodySize; + firstPayloadPageGranulePosition = granule; + } } byte[] file = new byte[fileSize]; @@ -97,7 +108,8 @@ import junit.framework.Assert; System.arraycopy(data, 0, file, position, data.length); position += data.length; } - return new OggTestFile(file, granule, packetCount, pageCount); + return new OggTestFile(file, granule, packetCount, pageCount, firstPayloadPageSize, + firstPayloadPageGranulePosition); } public int findPreviousPageStart(long position) { diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java index c6e5d46b8e..87e5811a9a 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java @@ -59,13 +59,21 @@ import java.io.IOException; * @param startPosition Start position of the payload (inclusive). * @param endPosition End position of the payload (exclusive). * @param streamReader StreamReader instance which owns this OggSeeker + * @param firstPayloadPageSize The total size of the first payload page, in bytes. + * @param firstPayloadPageGranulePosition The granule position of the first payload page. */ - public DefaultOggSeeker(long startPosition, long endPosition, StreamReader streamReader) { + public DefaultOggSeeker(long startPosition, long endPosition, StreamReader streamReader, + int firstPayloadPageSize, long firstPayloadPageGranulePosition) { Assertions.checkArgument(startPosition >= 0 && endPosition > startPosition); this.streamReader = streamReader; this.startPosition = startPosition; this.endPosition = endPosition; - this.state = STATE_SEEK_TO_END; + if (firstPayloadPageSize == endPosition - startPosition) { + totalGranules = firstPayloadPageGranulePosition; + state = STATE_IDLE; + } else { + state = STATE_SEEK_TO_END; + } } @Override @@ -77,9 +85,9 @@ import java.io.IOException; positionBeforeSeekToEnd = input.getPosition(); state = STATE_READ_LAST_PAGE; // Seek to the end just before the last page of stream to get the duration. - long lastPagePosition = endPosition - OggPageHeader.MAX_PAGE_SIZE; - if (lastPagePosition > positionBeforeSeekToEnd) { - return lastPagePosition; + long lastPageSearchPosition = endPosition - OggPageHeader.MAX_PAGE_SIZE; + if (lastPageSearchPosition > positionBeforeSeekToEnd) { + return lastPageSearchPosition; } // Fall through. case STATE_READ_LAST_PAGE: diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java index aa3f8e2353..a8b44f8fe9 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java @@ -144,7 +144,10 @@ import java.io.IOException; } else if (input.getLength() == C.LENGTH_UNSET) { oggSeeker = new UnseekableOggSeeker(); } else { - oggSeeker = new DefaultOggSeeker(payloadStartPosition, input.getLength(), this); + OggPageHeader firstPayloadPageHeader = oggPacket.getPageHeader(); + oggSeeker = new DefaultOggSeeker(payloadStartPosition, input.getLength(), this, + firstPayloadPageHeader.headerSize + firstPayloadPageHeader.bodySize, + firstPayloadPageHeader.granulePosition); } setupData = null;