mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Fix playback of OGG with only a single payload page
Issue: #1976 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=137044583
This commit is contained in:
parent
5c83c28a1f
commit
99503e6e3a
5 changed files with 40 additions and 16 deletions
|
|
@ -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 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import junit.framework.TestCase;
|
||||||
public class DefaultOggSeekerUtilMethodsTest extends TestCase {
|
public class DefaultOggSeekerUtilMethodsTest extends TestCase {
|
||||||
|
|
||||||
private Random random = new Random(0);
|
private Random random = new Random(0);
|
||||||
|
|
||||||
public void testSkipToNextPage() throws Exception {
|
public void testSkipToNextPage() throws Exception {
|
||||||
FakeExtractorInput extractorInput = TestData.createInput(
|
FakeExtractorInput extractorInput = TestData.createInput(
|
||||||
TestUtil.joinByteArrays(
|
TestUtil.joinByteArrays(
|
||||||
|
|
@ -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 {
|
||||||
|
|
||||||
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 {
|
||||||
|
|
||||||
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;
|
||||||
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;
|
||||||
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;
|
||||||
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;
|
||||||
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;
|
||||||
* @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;
|
||||||
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;
|
||||||
} 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;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue