Commit 99503e6e by olly Committed by Oliver Woodman

Fix playback of OGG with only a single payload page

Issue: #1976

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=137044583
parent 5c83c28a
...@@ -27,9 +27,9 @@ import junit.framework.TestCase; ...@@ -27,9 +27,9 @@ import junit.framework.TestCase;
*/ */
public final class DefaultOggSeekerTest extends TestCase { public final class DefaultOggSeekerTest extends TestCase {
public void testSetupUnboundAudioLength() { public void testSetupWithUnsetEndPositionFails() {
try { try {
new DefaultOggSeeker(0, C.LENGTH_UNSET, new TestStreamReader()); new DefaultOggSeeker(0, C.LENGTH_UNSET, new TestStreamReader(), 1, 1);
fail(); fail();
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// ignored // ignored
...@@ -43,11 +43,12 @@ public final class DefaultOggSeekerTest extends TestCase { ...@@ -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); OggTestFile testFile = OggTestFile.generate(random, 1000);
FakeExtractorInput input = new FakeExtractorInput.Builder().setData(testFile.data).build(); FakeExtractorInput input = new FakeExtractorInput.Builder().setData(testFile.data).build();
TestStreamReader streamReader = new TestStreamReader(); 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(); OggPageHeader pageHeader = new OggPageHeader();
while (true) { while (true) {
......
...@@ -75,7 +75,7 @@ public class DefaultOggSeekerUtilMethodsTest extends TestCase { ...@@ -75,7 +75,7 @@ public class DefaultOggSeekerUtilMethodsTest extends TestCase {
private static void skipToNextPage(ExtractorInput extractorInput) private static void skipToNextPage(ExtractorInput extractorInput)
throws IOException, InterruptedException { throws IOException, InterruptedException {
DefaultOggSeeker oggSeeker = new DefaultOggSeeker(0, extractorInput.getLength(), DefaultOggSeeker oggSeeker = new DefaultOggSeeker(0, extractorInput.getLength(),
new FlacReader()); new FlacReader(), 1, 2);
while (true) { while (true) {
try { try {
oggSeeker.skipToNextPage(extractorInput); oggSeeker.skipToNextPage(extractorInput);
...@@ -143,7 +143,7 @@ public class DefaultOggSeekerUtilMethodsTest extends TestCase { ...@@ -143,7 +143,7 @@ public class DefaultOggSeekerUtilMethodsTest extends TestCase {
private void skipToPageOfGranule(ExtractorInput input, long granule, private void skipToPageOfGranule(ExtractorInput input, long granule,
long elapsedSamplesExpected) throws IOException, InterruptedException { 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) { while (true) {
try { try {
assertEquals(elapsedSamplesExpected, oggSeeker.skipToPageOfGranule(input, granule, -1)); assertEquals(elapsedSamplesExpected, oggSeeker.skipToPageOfGranule(input, granule, -1));
...@@ -193,7 +193,7 @@ public class DefaultOggSeekerUtilMethodsTest extends TestCase { ...@@ -193,7 +193,7 @@ public class DefaultOggSeekerUtilMethodsTest extends TestCase {
private void assertReadGranuleOfLastPage(FakeExtractorInput input, int expected) private void assertReadGranuleOfLastPage(FakeExtractorInput input, int expected)
throws IOException, InterruptedException { 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) { while (true) {
try { try {
assertEquals(expected, oggSeeker.readGranuleOfLastPage(input)); assertEquals(expected, oggSeeker.readGranuleOfLastPage(input));
......
...@@ -33,12 +33,17 @@ import junit.framework.Assert; ...@@ -33,12 +33,17 @@ import junit.framework.Assert;
long lastGranule; long lastGranule;
int packetCount; int packetCount;
int pageCount; 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.data = data;
this.lastGranule = lastGranule; this.lastGranule = lastGranule;
this.packetCount = packetCount; this.packetCount = packetCount;
this.pageCount = pageCount; this.pageCount = pageCount;
this.firstPayloadPageSize = firstPayloadPageSize;
this.firstPayloadPageGranulePosition = firstPayloadPageGranulePosition;
} }
public static OggTestFile generate(Random random, int pageCount) { public static OggTestFile generate(Random random, int pageCount) {
...@@ -47,6 +52,8 @@ import junit.framework.Assert; ...@@ -47,6 +52,8 @@ import junit.framework.Assert;
long granule = 0; long granule = 0;
int packetLength = -1; int packetLength = -1;
int packetCount = 0; int packetCount = 0;
int firstPayloadPageSize = 0;
long firstPayloadPageGranulePosition = 0;
for (int i = 0; i < pageCount; i++) { for (int i = 0; i < pageCount; i++) {
int headerType = 0x00; int headerType = 0x00;
...@@ -89,6 +96,10 @@ import junit.framework.Assert; ...@@ -89,6 +96,10 @@ import junit.framework.Assert;
byte[] payload = TestUtil.buildTestData(bodySize, random); byte[] payload = TestUtil.buildTestData(bodySize, random);
fileData.add(payload); fileData.add(payload);
fileSize += payload.length; fileSize += payload.length;
if (i == 0) {
firstPayloadPageSize = header.length + bodySize;
firstPayloadPageGranulePosition = granule;
}
} }
byte[] file = new byte[fileSize]; byte[] file = new byte[fileSize];
...@@ -97,7 +108,8 @@ import junit.framework.Assert; ...@@ -97,7 +108,8 @@ import junit.framework.Assert;
System.arraycopy(data, 0, file, position, data.length); System.arraycopy(data, 0, file, position, data.length);
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) { public int findPreviousPageStart(long position) {
......
...@@ -59,13 +59,21 @@ import java.io.IOException; ...@@ -59,13 +59,21 @@ import java.io.IOException;
* @param startPosition Start position of the payload (inclusive). * @param startPosition Start position of the payload (inclusive).
* @param endPosition End position of the payload (exclusive). * @param endPosition End position of the payload (exclusive).
* @param streamReader StreamReader instance which owns this OggSeeker * @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); Assertions.checkArgument(startPosition >= 0 && endPosition > startPosition);
this.streamReader = streamReader; this.streamReader = streamReader;
this.startPosition = startPosition; this.startPosition = startPosition;
this.endPosition = endPosition; 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 @Override
...@@ -77,9 +85,9 @@ import java.io.IOException; ...@@ -77,9 +85,9 @@ import java.io.IOException;
positionBeforeSeekToEnd = input.getPosition(); positionBeforeSeekToEnd = input.getPosition();
state = STATE_READ_LAST_PAGE; state = STATE_READ_LAST_PAGE;
// Seek to the end just before the last page of stream to get the duration. // Seek to the end just before the last page of stream to get the duration.
long lastPagePosition = endPosition - OggPageHeader.MAX_PAGE_SIZE; long lastPageSearchPosition = endPosition - OggPageHeader.MAX_PAGE_SIZE;
if (lastPagePosition > positionBeforeSeekToEnd) { if (lastPageSearchPosition > positionBeforeSeekToEnd) {
return lastPagePosition; return lastPageSearchPosition;
} }
// Fall through. // Fall through.
case STATE_READ_LAST_PAGE: case STATE_READ_LAST_PAGE:
......
...@@ -144,7 +144,10 @@ import java.io.IOException; ...@@ -144,7 +144,10 @@ import java.io.IOException;
} else if (input.getLength() == C.LENGTH_UNSET) { } else if (input.getLength() == C.LENGTH_UNSET) {
oggSeeker = new UnseekableOggSeeker(); oggSeeker = new UnseekableOggSeeker();
} else { } 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; setupData = null;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment