mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Expose new non-discarding SampleQueue read/skip methods
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=159555748
This commit is contained in:
parent
0ffc3ffd29
commit
467fd2535c
2 changed files with 112 additions and 33 deletions
|
|
@ -133,6 +133,9 @@ public class SampleQueueTest extends TestCase {
|
||||||
assertReadFormat(true, TEST_FORMAT_1);
|
assertReadFormat(true, TEST_FORMAT_1);
|
||||||
// Otherwise should read the sample.
|
// Otherwise should read the sample.
|
||||||
assertSampleRead(1000, true, TEST_DATA, 0, ALLOCATION_SIZE);
|
assertSampleRead(1000, true, TEST_DATA, 0, ALLOCATION_SIZE);
|
||||||
|
// Allocation should still be held.
|
||||||
|
assertAllocationCount(1);
|
||||||
|
sampleQueue.discardToRead();
|
||||||
// The allocation should have been released.
|
// The allocation should have been released.
|
||||||
assertAllocationCount(0);
|
assertAllocationCount(0);
|
||||||
|
|
||||||
|
|
@ -147,6 +150,9 @@ public class SampleQueueTest extends TestCase {
|
||||||
assertReadFormat(true, TEST_FORMAT_1);
|
assertReadFormat(true, TEST_FORMAT_1);
|
||||||
// Read the sample.
|
// Read the sample.
|
||||||
assertSampleRead(2000, false, TEST_DATA, 0, ALLOCATION_SIZE - 1);
|
assertSampleRead(2000, false, TEST_DATA, 0, ALLOCATION_SIZE - 1);
|
||||||
|
// Allocation should still be held.
|
||||||
|
assertAllocationCount(1);
|
||||||
|
sampleQueue.discardToRead();
|
||||||
// The last byte written to the sample queue may belong to a sample whose metadata has yet to be
|
// The last byte written to the sample queue may belong to a sample whose metadata has yet to be
|
||||||
// written, so an allocation should still be held.
|
// written, so an allocation should still be held.
|
||||||
assertAllocationCount(1);
|
assertAllocationCount(1);
|
||||||
|
|
@ -158,6 +164,9 @@ public class SampleQueueTest extends TestCase {
|
||||||
assertReadFormat(true, TEST_FORMAT_1);
|
assertReadFormat(true, TEST_FORMAT_1);
|
||||||
// Read the sample.
|
// Read the sample.
|
||||||
assertSampleRead(3000, false, TEST_DATA, ALLOCATION_SIZE - 1, 1);
|
assertSampleRead(3000, false, TEST_DATA, ALLOCATION_SIZE - 1, 1);
|
||||||
|
// Allocation should still be held.
|
||||||
|
assertAllocationCount(1);
|
||||||
|
sampleQueue.discardToRead();
|
||||||
// The allocation should have been released.
|
// The allocation should have been released.
|
||||||
assertAllocationCount(0);
|
assertAllocationCount(0);
|
||||||
}
|
}
|
||||||
|
|
@ -168,6 +177,8 @@ public class SampleQueueTest extends TestCase {
|
||||||
sampleQueue.getLargestQueuedTimestampUs());
|
sampleQueue.getLargestQueuedTimestampUs());
|
||||||
assertAllocationCount(10);
|
assertAllocationCount(10);
|
||||||
assertReadTestData();
|
assertReadTestData();
|
||||||
|
assertAllocationCount(10);
|
||||||
|
sampleQueue.discardToRead();
|
||||||
assertAllocationCount(0);
|
assertAllocationCount(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,12 +188,42 @@ public class SampleQueueTest extends TestCase {
|
||||||
assertAllocationCount(20);
|
assertAllocationCount(20);
|
||||||
assertReadTestData(TEST_FORMAT_2);
|
assertReadTestData(TEST_FORMAT_2);
|
||||||
assertReadTestData(TEST_FORMAT_2);
|
assertReadTestData(TEST_FORMAT_2);
|
||||||
|
assertAllocationCount(20);
|
||||||
|
sampleQueue.discardToRead();
|
||||||
assertAllocationCount(0);
|
assertAllocationCount(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testReadMultiWithRewind() {
|
||||||
|
writeTestData();
|
||||||
|
assertReadTestData();
|
||||||
|
assertEquals(8, sampleQueue.getReadIndex());
|
||||||
|
assertAllocationCount(10);
|
||||||
|
// Rewind.
|
||||||
|
sampleQueue.rewind();
|
||||||
|
assertAllocationCount(10);
|
||||||
|
// Read again.
|
||||||
|
assertEquals(0, sampleQueue.getReadIndex());
|
||||||
|
assertReadTestData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRewindAfterDiscard() {
|
||||||
|
writeTestData();
|
||||||
|
assertReadTestData();
|
||||||
|
sampleQueue.discardToRead();
|
||||||
|
assertAllocationCount(0);
|
||||||
|
// Rewind.
|
||||||
|
sampleQueue.rewind();
|
||||||
|
assertAllocationCount(0);
|
||||||
|
// Can't read again.
|
||||||
|
assertEquals(8, sampleQueue.getReadIndex());
|
||||||
|
assertReadEndOfStream(false);
|
||||||
|
}
|
||||||
|
|
||||||
public void testSkipAll() {
|
public void testSkipAll() {
|
||||||
writeTestData();
|
writeTestData();
|
||||||
sampleQueue.skipAll();
|
sampleQueue.skipAll2();
|
||||||
|
assertAllocationCount(10);
|
||||||
|
sampleQueue.discardToRead();
|
||||||
assertAllocationCount(0);
|
assertAllocationCount(0);
|
||||||
// Despite skipping all samples, we should still read the last format, since this is the
|
// Despite skipping all samples, we should still read the last format, since this is the
|
||||||
// expected format for a subsequent sample.
|
// expected format for a subsequent sample.
|
||||||
|
|
@ -194,7 +235,9 @@ public class SampleQueueTest extends TestCase {
|
||||||
public void testSkipAllRetainsUnassignedData() {
|
public void testSkipAllRetainsUnassignedData() {
|
||||||
sampleQueue.format(TEST_FORMAT_1);
|
sampleQueue.format(TEST_FORMAT_1);
|
||||||
sampleQueue.sampleData(new ParsableByteArray(TEST_DATA), ALLOCATION_SIZE);
|
sampleQueue.sampleData(new ParsableByteArray(TEST_DATA), ALLOCATION_SIZE);
|
||||||
sampleQueue.skipAll();
|
sampleQueue.skipAll2();
|
||||||
|
assertAllocationCount(1);
|
||||||
|
sampleQueue.discardToRead();
|
||||||
// Skipping shouldn't discard data that may belong to a sample whose metadata has yet to be
|
// Skipping shouldn't discard data that may belong to a sample whose metadata has yet to be
|
||||||
// written.
|
// written.
|
||||||
assertAllocationCount(1);
|
assertAllocationCount(1);
|
||||||
|
|
@ -207,12 +250,14 @@ public class SampleQueueTest extends TestCase {
|
||||||
// Once the metadata has been written, check the sample can be read as expected.
|
// Once the metadata has been written, check the sample can be read as expected.
|
||||||
assertSampleRead(0, true, TEST_DATA, 0, ALLOCATION_SIZE);
|
assertSampleRead(0, true, TEST_DATA, 0, ALLOCATION_SIZE);
|
||||||
assertNoSamplesToRead(TEST_FORMAT_1);
|
assertNoSamplesToRead(TEST_FORMAT_1);
|
||||||
|
assertAllocationCount(1);
|
||||||
|
sampleQueue.discardToRead();
|
||||||
assertAllocationCount(0);
|
assertAllocationCount(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSkipToKeyframeBeforeBuffer() {
|
public void testSkipToKeyframeBeforeBuffer() {
|
||||||
writeTestData();
|
writeTestData();
|
||||||
boolean result = sampleQueue.skipToKeyframeBefore(TEST_SAMPLE_TIMESTAMPS[0] - 1, false);
|
boolean result = sampleQueue.skipToKeyframeBefore2(TEST_SAMPLE_TIMESTAMPS[0] - 1, false);
|
||||||
// Should fail and have no effect.
|
// Should fail and have no effect.
|
||||||
assertFalse(result);
|
assertFalse(result);
|
||||||
assertReadTestData();
|
assertReadTestData();
|
||||||
|
|
@ -221,7 +266,7 @@ public class SampleQueueTest extends TestCase {
|
||||||
|
|
||||||
public void testSkipToKeyframeStartOfBuffer() {
|
public void testSkipToKeyframeStartOfBuffer() {
|
||||||
writeTestData();
|
writeTestData();
|
||||||
boolean result = sampleQueue.skipToKeyframeBefore(TEST_SAMPLE_TIMESTAMPS[0], false);
|
boolean result = sampleQueue.skipToKeyframeBefore2(TEST_SAMPLE_TIMESTAMPS[0], false);
|
||||||
// Should succeed but have no effect (we're already at the first frame).
|
// Should succeed but have no effect (we're already at the first frame).
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
assertReadTestData();
|
assertReadTestData();
|
||||||
|
|
@ -230,7 +275,7 @@ public class SampleQueueTest extends TestCase {
|
||||||
|
|
||||||
public void testSkipToKeyframeEndOfBuffer() {
|
public void testSkipToKeyframeEndOfBuffer() {
|
||||||
writeTestData();
|
writeTestData();
|
||||||
boolean result = sampleQueue.skipToKeyframeBefore(
|
boolean result = sampleQueue.skipToKeyframeBefore2(
|
||||||
TEST_SAMPLE_TIMESTAMPS[TEST_SAMPLE_TIMESTAMPS.length - 1], false);
|
TEST_SAMPLE_TIMESTAMPS[TEST_SAMPLE_TIMESTAMPS.length - 1], false);
|
||||||
// Should succeed and skip to 2nd keyframe.
|
// Should succeed and skip to 2nd keyframe.
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
@ -240,7 +285,7 @@ public class SampleQueueTest extends TestCase {
|
||||||
|
|
||||||
public void testSkipToKeyframeAfterBuffer() {
|
public void testSkipToKeyframeAfterBuffer() {
|
||||||
writeTestData();
|
writeTestData();
|
||||||
boolean result = sampleQueue.skipToKeyframeBefore(
|
boolean result = sampleQueue.skipToKeyframeBefore2(
|
||||||
TEST_SAMPLE_TIMESTAMPS[TEST_SAMPLE_TIMESTAMPS.length - 1] + 1, false);
|
TEST_SAMPLE_TIMESTAMPS[TEST_SAMPLE_TIMESTAMPS.length - 1] + 1, false);
|
||||||
// Should fail and have no effect.
|
// Should fail and have no effect.
|
||||||
assertFalse(result);
|
assertFalse(result);
|
||||||
|
|
@ -250,7 +295,7 @@ public class SampleQueueTest extends TestCase {
|
||||||
|
|
||||||
public void testSkipToKeyframeAfterBufferAllowed() {
|
public void testSkipToKeyframeAfterBufferAllowed() {
|
||||||
writeTestData();
|
writeTestData();
|
||||||
boolean result = sampleQueue.skipToKeyframeBefore(
|
boolean result = sampleQueue.skipToKeyframeBefore2(
|
||||||
TEST_SAMPLE_TIMESTAMPS[TEST_SAMPLE_TIMESTAMPS.length - 1] + 1, true);
|
TEST_SAMPLE_TIMESTAMPS[TEST_SAMPLE_TIMESTAMPS.length - 1] + 1, true);
|
||||||
// Should succeed and skip to 2nd keyframe.
|
// Should succeed and skip to 2nd keyframe.
|
||||||
assertTrue(result);
|
assertTrue(result);
|
||||||
|
|
@ -305,6 +350,8 @@ public class SampleQueueTest extends TestCase {
|
||||||
writeTestData();
|
writeTestData();
|
||||||
assertReadTestData(null, 0, 3);
|
assertReadTestData(null, 0, 3);
|
||||||
sampleQueue.discardUpstreamSamples(8);
|
sampleQueue.discardUpstreamSamples(8);
|
||||||
|
assertAllocationCount(10);
|
||||||
|
sampleQueue.discardToRead();
|
||||||
assertAllocationCount(7);
|
assertAllocationCount(7);
|
||||||
sampleQueue.discardUpstreamSamples(7);
|
sampleQueue.discardUpstreamSamples(7);
|
||||||
assertAllocationCount(6);
|
assertAllocationCount(6);
|
||||||
|
|
@ -359,6 +406,7 @@ public class SampleQueueTest extends TestCase {
|
||||||
* Asserts correct reading of standard test data from {@code sampleQueue}.
|
* Asserts correct reading of standard test data from {@code sampleQueue}.
|
||||||
*
|
*
|
||||||
* @param startFormat The format of the last sample previously read from {@code sampleQueue}.
|
* @param startFormat The format of the last sample previously read from {@code sampleQueue}.
|
||||||
|
* @param firstSampleIndex The index of the first sample that's expected to be read.
|
||||||
*/
|
*/
|
||||||
private void assertReadTestData(Format startFormat, int firstSampleIndex) {
|
private void assertReadTestData(Format startFormat, int firstSampleIndex) {
|
||||||
assertReadTestData(startFormat, firstSampleIndex,
|
assertReadTestData(startFormat, firstSampleIndex,
|
||||||
|
|
@ -428,7 +476,7 @@ public class SampleQueueTest extends TestCase {
|
||||||
*/
|
*/
|
||||||
private void assertReadNothing(boolean formatRequired) {
|
private void assertReadNothing(boolean formatRequired) {
|
||||||
clearFormatHolderAndInputBuffer();
|
clearFormatHolderAndInputBuffer();
|
||||||
int result = sampleQueue.readData(formatHolder, inputBuffer, formatRequired, false, 0);
|
int result = sampleQueue.readData2(formatHolder, inputBuffer, formatRequired, false, 0);
|
||||||
assertEquals(C.RESULT_NOTHING_READ, result);
|
assertEquals(C.RESULT_NOTHING_READ, result);
|
||||||
// formatHolder should not be populated.
|
// formatHolder should not be populated.
|
||||||
assertNull(formatHolder.format);
|
assertNull(formatHolder.format);
|
||||||
|
|
@ -445,7 +493,7 @@ public class SampleQueueTest extends TestCase {
|
||||||
*/
|
*/
|
||||||
private void assertReadEndOfStream(boolean formatRequired) {
|
private void assertReadEndOfStream(boolean formatRequired) {
|
||||||
clearFormatHolderAndInputBuffer();
|
clearFormatHolderAndInputBuffer();
|
||||||
int result = sampleQueue.readData(formatHolder, inputBuffer, formatRequired, true, 0);
|
int result = sampleQueue.readData2(formatHolder, inputBuffer, formatRequired, true, 0);
|
||||||
assertEquals(C.RESULT_BUFFER_READ, result);
|
assertEquals(C.RESULT_BUFFER_READ, result);
|
||||||
// formatHolder should not be populated.
|
// formatHolder should not be populated.
|
||||||
assertNull(formatHolder.format);
|
assertNull(formatHolder.format);
|
||||||
|
|
@ -465,7 +513,7 @@ public class SampleQueueTest extends TestCase {
|
||||||
*/
|
*/
|
||||||
private void assertReadFormat(boolean formatRequired, Format format) {
|
private void assertReadFormat(boolean formatRequired, Format format) {
|
||||||
clearFormatHolderAndInputBuffer();
|
clearFormatHolderAndInputBuffer();
|
||||||
int result = sampleQueue.readData(formatHolder, inputBuffer, formatRequired, false, 0);
|
int result = sampleQueue.readData2(formatHolder, inputBuffer, formatRequired, false, 0);
|
||||||
assertEquals(C.RESULT_FORMAT_READ, result);
|
assertEquals(C.RESULT_FORMAT_READ, result);
|
||||||
// formatHolder should be populated.
|
// formatHolder should be populated.
|
||||||
assertEquals(format, formatHolder.format);
|
assertEquals(format, formatHolder.format);
|
||||||
|
|
@ -487,7 +535,7 @@ public class SampleQueueTest extends TestCase {
|
||||||
private void assertSampleRead(long timeUs, boolean isKeyframe, byte[] sampleData, int offset,
|
private void assertSampleRead(long timeUs, boolean isKeyframe, byte[] sampleData, int offset,
|
||||||
int length) {
|
int length) {
|
||||||
clearFormatHolderAndInputBuffer();
|
clearFormatHolderAndInputBuffer();
|
||||||
int result = sampleQueue.readData(formatHolder, inputBuffer, false, false, 0);
|
int result = sampleQueue.readData2(formatHolder, inputBuffer, false, false, 0);
|
||||||
assertEquals(C.RESULT_BUFFER_READ, result);
|
assertEquals(C.RESULT_BUFFER_READ, result);
|
||||||
// formatHolder should not be populated.
|
// formatHolder should not be populated.
|
||||||
assertNull(formatHolder.format);
|
assertNull(formatHolder.format);
|
||||||
|
|
|
||||||
|
|
@ -224,17 +224,50 @@ public final class SampleQueue implements TrackOutput {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Skips all samples currently in the buffer.
|
* Rewinds the read position to the first sample in the queue.
|
||||||
*/
|
*/
|
||||||
public void skipAll() {
|
public void rewind() {
|
||||||
metadataQueue.skipAll();
|
metadataQueue.rewind();
|
||||||
// TODO - Remove the following block and expose explicit discard operations.
|
readAllocationNode = firstAllocationNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discards samples up to the current read position.
|
||||||
|
*/
|
||||||
|
public void discardToRead() {
|
||||||
long nextOffset = metadataQueue.discardToRead();
|
long nextOffset = metadataQueue.discardToRead();
|
||||||
if (nextOffset != C.POSITION_UNSET) {
|
if (nextOffset != C.POSITION_UNSET) {
|
||||||
dropDownstreamTo(nextOffset);
|
dropDownstreamTo(nextOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #skipAll2()} followed by {@link #discardToRead()}.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void skipAll() {
|
||||||
|
skipAll2();
|
||||||
|
discardToRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skips all samples currently in the buffer.
|
||||||
|
*/
|
||||||
|
public void skipAll2() {
|
||||||
|
metadataQueue.skipAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #skipToKeyframeBefore2(long, boolean)} followed by
|
||||||
|
* {@link #discardToRead()}.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public boolean skipToKeyframeBefore(long timeUs, boolean allowTimeBeyondBuffer) {
|
||||||
|
boolean success = skipToKeyframeBefore2(timeUs, allowTimeBeyondBuffer);
|
||||||
|
discardToRead();
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to skip to the keyframe before or at the specified time. Succeeds only if the buffer
|
* Attempts to skip to the keyframe before or at the specified time. Succeeds only if the buffer
|
||||||
* contains a keyframe with a timestamp of {@code timeUs} or earlier. If
|
* contains a keyframe with a timestamp of {@code timeUs} or earlier. If
|
||||||
|
|
@ -246,18 +279,21 @@ public final class SampleQueue implements TrackOutput {
|
||||||
* of the buffer.
|
* of the buffer.
|
||||||
* @return Whether the skip was successful.
|
* @return Whether the skip was successful.
|
||||||
*/
|
*/
|
||||||
public boolean skipToKeyframeBefore(long timeUs, boolean allowTimeBeyondBuffer) {
|
public boolean skipToKeyframeBefore2(long timeUs, boolean allowTimeBeyondBuffer) {
|
||||||
boolean success = metadataQueue.skipToKeyframeBefore(timeUs, allowTimeBeyondBuffer);
|
return metadataQueue.skipToKeyframeBefore(timeUs, allowTimeBeyondBuffer);
|
||||||
if (success) {
|
}
|
||||||
// TODO - Remove the following block and expose explicit discard operations.
|
|
||||||
long nextOffset = metadataQueue.discardToRead();
|
/**
|
||||||
if (nextOffset != C.POSITION_UNSET) {
|
* @deprecated Use {@link #readData2(FormatHolder, DecoderInputBuffer, boolean, boolean, long)}
|
||||||
dropDownstreamTo(nextOffset);
|
* followed by {@link #discardToRead()}.
|
||||||
}
|
*/
|
||||||
return true;
|
@Deprecated
|
||||||
} else {
|
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired,
|
||||||
return false;
|
boolean loadingFinished, long decodeOnlyUntilUs) {
|
||||||
}
|
int result = readData2(formatHolder, buffer, formatRequired, loadingFinished,
|
||||||
|
decodeOnlyUntilUs);
|
||||||
|
discardToRead();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -276,7 +312,7 @@ public final class SampleQueue implements TrackOutput {
|
||||||
* @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
|
* @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
|
||||||
* {@link C#RESULT_BUFFER_READ}.
|
* {@link C#RESULT_BUFFER_READ}.
|
||||||
*/
|
*/
|
||||||
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired,
|
public int readData2(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired,
|
||||||
boolean loadingFinished, long decodeOnlyUntilUs) {
|
boolean loadingFinished, long decodeOnlyUntilUs) {
|
||||||
int result = metadataQueue.readData(formatHolder, buffer, formatRequired, loadingFinished,
|
int result = metadataQueue.readData(formatHolder, buffer, formatRequired, loadingFinished,
|
||||||
downstreamFormat, extrasHolder);
|
downstreamFormat, extrasHolder);
|
||||||
|
|
@ -296,11 +332,6 @@ public final class SampleQueue implements TrackOutput {
|
||||||
// Write the sample data into the holder.
|
// Write the sample data into the holder.
|
||||||
buffer.ensureSpaceForWrite(extrasHolder.size);
|
buffer.ensureSpaceForWrite(extrasHolder.size);
|
||||||
readData(extrasHolder.offset, buffer.data, extrasHolder.size);
|
readData(extrasHolder.offset, buffer.data, extrasHolder.size);
|
||||||
// TODO - Remove the following block and expose explicit discard operations.
|
|
||||||
long nextOffset = metadataQueue.discardToRead();
|
|
||||||
if (nextOffset != C.POSITION_UNSET) {
|
|
||||||
dropDownstreamTo(nextOffset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return C.RESULT_BUFFER_READ;
|
return C.RESULT_BUFFER_READ;
|
||||||
case C.RESULT_NOTHING_READ:
|
case C.RESULT_NOTHING_READ:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue