From 467fd2535c030171a0520e4884de76ecd9308731 Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 20 Jun 2017 07:01:35 -0700 Subject: [PATCH] Expose new non-discarding SampleQueue read/skip methods ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=159555748 --- .../exoplayer2/source/SampleQueueTest.java | 70 ++++++++++++++--- .../exoplayer2/source/SampleQueue.java | 75 +++++++++++++------ 2 files changed, 112 insertions(+), 33 deletions(-) diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/source/SampleQueueTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/source/SampleQueueTest.java index 129f299779..8723e39020 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/source/SampleQueueTest.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/source/SampleQueueTest.java @@ -133,6 +133,9 @@ public class SampleQueueTest extends TestCase { assertReadFormat(true, TEST_FORMAT_1); // Otherwise should read the sample. assertSampleRead(1000, true, TEST_DATA, 0, ALLOCATION_SIZE); + // Allocation should still be held. + assertAllocationCount(1); + sampleQueue.discardToRead(); // The allocation should have been released. assertAllocationCount(0); @@ -147,6 +150,9 @@ public class SampleQueueTest extends TestCase { assertReadFormat(true, TEST_FORMAT_1); // Read the sample. 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 // written, so an allocation should still be held. assertAllocationCount(1); @@ -158,6 +164,9 @@ public class SampleQueueTest extends TestCase { assertReadFormat(true, TEST_FORMAT_1); // Read the sample. assertSampleRead(3000, false, TEST_DATA, ALLOCATION_SIZE - 1, 1); + // Allocation should still be held. + assertAllocationCount(1); + sampleQueue.discardToRead(); // The allocation should have been released. assertAllocationCount(0); } @@ -168,6 +177,8 @@ public class SampleQueueTest extends TestCase { sampleQueue.getLargestQueuedTimestampUs()); assertAllocationCount(10); assertReadTestData(); + assertAllocationCount(10); + sampleQueue.discardToRead(); assertAllocationCount(0); } @@ -177,12 +188,42 @@ public class SampleQueueTest extends TestCase { assertAllocationCount(20); assertReadTestData(TEST_FORMAT_2); assertReadTestData(TEST_FORMAT_2); + assertAllocationCount(20); + sampleQueue.discardToRead(); 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() { writeTestData(); - sampleQueue.skipAll(); + sampleQueue.skipAll2(); + assertAllocationCount(10); + sampleQueue.discardToRead(); assertAllocationCount(0); // Despite skipping all samples, we should still read the last format, since this is the // expected format for a subsequent sample. @@ -194,7 +235,9 @@ public class SampleQueueTest extends TestCase { public void testSkipAllRetainsUnassignedData() { sampleQueue.format(TEST_FORMAT_1); 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 // written. 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. assertSampleRead(0, true, TEST_DATA, 0, ALLOCATION_SIZE); assertNoSamplesToRead(TEST_FORMAT_1); + assertAllocationCount(1); + sampleQueue.discardToRead(); assertAllocationCount(0); } public void testSkipToKeyframeBeforeBuffer() { 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. assertFalse(result); assertReadTestData(); @@ -221,7 +266,7 @@ public class SampleQueueTest extends TestCase { public void testSkipToKeyframeStartOfBuffer() { 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). assertTrue(result); assertReadTestData(); @@ -230,7 +275,7 @@ public class SampleQueueTest extends TestCase { public void testSkipToKeyframeEndOfBuffer() { writeTestData(); - boolean result = sampleQueue.skipToKeyframeBefore( + boolean result = sampleQueue.skipToKeyframeBefore2( TEST_SAMPLE_TIMESTAMPS[TEST_SAMPLE_TIMESTAMPS.length - 1], false); // Should succeed and skip to 2nd keyframe. assertTrue(result); @@ -240,7 +285,7 @@ public class SampleQueueTest extends TestCase { public void testSkipToKeyframeAfterBuffer() { writeTestData(); - boolean result = sampleQueue.skipToKeyframeBefore( + boolean result = sampleQueue.skipToKeyframeBefore2( TEST_SAMPLE_TIMESTAMPS[TEST_SAMPLE_TIMESTAMPS.length - 1] + 1, false); // Should fail and have no effect. assertFalse(result); @@ -250,7 +295,7 @@ public class SampleQueueTest extends TestCase { public void testSkipToKeyframeAfterBufferAllowed() { writeTestData(); - boolean result = sampleQueue.skipToKeyframeBefore( + boolean result = sampleQueue.skipToKeyframeBefore2( TEST_SAMPLE_TIMESTAMPS[TEST_SAMPLE_TIMESTAMPS.length - 1] + 1, true); // Should succeed and skip to 2nd keyframe. assertTrue(result); @@ -305,6 +350,8 @@ public class SampleQueueTest extends TestCase { writeTestData(); assertReadTestData(null, 0, 3); sampleQueue.discardUpstreamSamples(8); + assertAllocationCount(10); + sampleQueue.discardToRead(); assertAllocationCount(7); sampleQueue.discardUpstreamSamples(7); assertAllocationCount(6); @@ -359,6 +406,7 @@ public class SampleQueueTest extends TestCase { * Asserts correct reading of standard test data 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) { assertReadTestData(startFormat, firstSampleIndex, @@ -428,7 +476,7 @@ public class SampleQueueTest extends TestCase { */ private void assertReadNothing(boolean formatRequired) { 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); // formatHolder should not be populated. assertNull(formatHolder.format); @@ -445,7 +493,7 @@ public class SampleQueueTest extends TestCase { */ private void assertReadEndOfStream(boolean formatRequired) { 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); // formatHolder should not be populated. assertNull(formatHolder.format); @@ -465,7 +513,7 @@ public class SampleQueueTest extends TestCase { */ private void assertReadFormat(boolean formatRequired, Format format) { 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); // formatHolder should be populated. assertEquals(format, formatHolder.format); @@ -487,7 +535,7 @@ public class SampleQueueTest extends TestCase { private void assertSampleRead(long timeUs, boolean isKeyframe, byte[] sampleData, int offset, int length) { 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); // formatHolder should not be populated. assertNull(formatHolder.format); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java index ca266eb11d..35a53c5cdf 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java @@ -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() { - metadataQueue.skipAll(); - // TODO - Remove the following block and expose explicit discard operations. + public void rewind() { + metadataQueue.rewind(); + readAllocationNode = firstAllocationNode; + } + + /** + * Discards samples up to the current read position. + */ + public void discardToRead() { long nextOffset = metadataQueue.discardToRead(); if (nextOffset != C.POSITION_UNSET) { 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 * 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. * @return Whether the skip was successful. */ - public boolean skipToKeyframeBefore(long timeUs, boolean allowTimeBeyondBuffer) { - boolean success = 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) { - dropDownstreamTo(nextOffset); - } - return true; - } else { - return false; - } + public boolean skipToKeyframeBefore2(long timeUs, boolean allowTimeBeyondBuffer) { + return metadataQueue.skipToKeyframeBefore(timeUs, allowTimeBeyondBuffer); + } + + /** + * @deprecated Use {@link #readData2(FormatHolder, DecoderInputBuffer, boolean, boolean, long)} + * followed by {@link #discardToRead()}. + */ + @Deprecated + public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired, + 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 * {@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) { int result = metadataQueue.readData(formatHolder, buffer, formatRequired, loadingFinished, downstreamFormat, extrasHolder); @@ -296,11 +332,6 @@ public final class SampleQueue implements TrackOutput { // Write the sample data into the holder. buffer.ensureSpaceForWrite(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; case C.RESULT_NOTHING_READ: