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 76ea0e34cf..77e61e39a9 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 @@ -258,45 +258,45 @@ public class SampleQueueTest extends TestCase { public void testAdvanceToBeforeBuffer() { writeTestData(); - boolean result = sampleQueue.advanceTo(TEST_SAMPLE_TIMESTAMPS[0] - 1, true, false); + int skipCount = sampleQueue.advanceTo(TEST_SAMPLE_TIMESTAMPS[0] - 1, true, false); // Should fail and have no effect. - assertFalse(result); + assertEquals(SampleQueue.ADVANCE_FAILED, skipCount); assertReadTestData(); assertNoSamplesToRead(TEST_FORMAT_2); } public void testAdvanceToStartOfBuffer() { writeTestData(); - boolean result = sampleQueue.advanceTo(TEST_SAMPLE_TIMESTAMPS[0], true, false); + int skipCount = sampleQueue.advanceTo(TEST_SAMPLE_TIMESTAMPS[0], true, false); // Should succeed but have no effect (we're already at the first frame). - assertTrue(result); + assertEquals(0, skipCount); assertReadTestData(); assertNoSamplesToRead(TEST_FORMAT_2); } public void testAdvanceToEndOfBuffer() { writeTestData(); - boolean result = sampleQueue.advanceTo(LAST_SAMPLE_TIMESTAMP, true, false); - // Should succeed and skip to 2nd keyframe. - assertTrue(result); + int skipCount = sampleQueue.advanceTo(LAST_SAMPLE_TIMESTAMP, true, false); + // Should succeed and skip to 2nd keyframe (the 4th frame). + assertEquals(4, skipCount); assertReadTestData(null, TEST_DATA_SECOND_KEYFRAME_INDEX); assertNoSamplesToRead(TEST_FORMAT_2); } public void testAdvanceToAfterBuffer() { writeTestData(); - boolean result = sampleQueue.advanceTo(LAST_SAMPLE_TIMESTAMP + 1, true, false); + int skipCount = sampleQueue.advanceTo(LAST_SAMPLE_TIMESTAMP + 1, true, false); // Should fail and have no effect. - assertFalse(result); + assertEquals(SampleQueue.ADVANCE_FAILED, skipCount); assertReadTestData(); assertNoSamplesToRead(TEST_FORMAT_2); } public void testAdvanceToAfterBufferAllowed() { writeTestData(); - boolean result = sampleQueue.advanceTo(LAST_SAMPLE_TIMESTAMP + 1, true, true); - // Should succeed and skip to 2nd keyframe. - assertTrue(result); + int skipCount = sampleQueue.advanceTo(LAST_SAMPLE_TIMESTAMP + 1, true, true); + // Should succeed and skip to 2nd keyframe (the 4th frame). + assertEquals(4, skipCount); assertReadTestData(null, TEST_DATA_SECOND_KEYFRAME_INDEX); assertNoSamplesToRead(TEST_FORMAT_2); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java index a88a1dd615..7f14837965 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java @@ -296,9 +296,10 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { * {@code positionUs} is beyond it. * * @param positionUs The position in microseconds. + * @return The number of samples that were skipped. */ - protected void skipSource(long positionUs) { - stream.skipData(positionUs - streamOffsetUs); + protected int skipSource(long positionUs) { + return stream.skipData(positionUs - streamOffsetUs); } /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/decoder/DecoderCounters.java b/library/core/src/main/java/com/google/android/exoplayer2/decoder/DecoderCounters.java index 3c2d6d96e9..7a532110d3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/decoder/DecoderCounters.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/decoder/DecoderCounters.java @@ -36,6 +36,12 @@ public final class DecoderCounters { * The number of queued input buffers. */ public int inputBufferCount; + /** + * The number of skipped input buffers. + *
+ * A skipped input buffer is an input buffer that was deliberately not sent to the decoder.
+ */
+ public int skippedInputBufferCount;
/**
* The number of rendered output buffers.
*/
@@ -79,6 +85,7 @@ public final class DecoderCounters {
decoderInitCount += other.decoderInitCount;
decoderReleaseCount += other.decoderReleaseCount;
inputBufferCount += other.inputBufferCount;
+ skippedInputBufferCount += other.skippedInputBufferCount;
renderedOutputBufferCount += other.renderedOutputBufferCount;
skippedOutputBufferCount += other.skippedOutputBufferCount;
droppedOutputBufferCount += other.droppedOutputBufferCount;
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java
index 01229c1104..7c0549de25 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java
@@ -530,7 +530,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
while (feedInputBuffer()) {}
TraceUtil.endSection();
} else {
- skipSource(positionUs);
+ decoderCounters.skippedInputBufferCount += skipSource(positionUs);
// We need to read any format changes despite not having a codec so that drmSession can be
// updated, and so that we have the most recent format should the codec be initialized. We may
// also reach the end of the stream. Note that readSource will not read a sample into a
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java
index 12f58d9a21..a8c33b4625 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java
@@ -286,8 +286,8 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
}
@Override
- public void skipData(long positionUs) {
- stream.skipData(startUs + positionUs);
+ public int skipData(long positionUs) {
+ return stream.skipData(startUs + positionUs);
}
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/EmptySampleStream.java b/library/core/src/main/java/com/google/android/exoplayer2/source/EmptySampleStream.java
index 7aab22d8a0..299b816cc8 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/EmptySampleStream.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/EmptySampleStream.java
@@ -43,8 +43,8 @@ public final class EmptySampleStream implements SampleStream {
}
@Override
- public void skipData(long positionUs) {
- // Do nothing.
+ public int skipData(long positionUs) {
+ return 0;
}
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java
index e7273f834b..511f7f4a8a 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java
@@ -238,7 +238,7 @@ import java.util.Arrays;
// sample queue, or if we haven't read anything from the queue since the previous seek
// (this case is common for sparse tracks such as metadata tracks). In all other cases a
// seek is required.
- seekRequired = !sampleQueue.advanceTo(positionUs, true, true)
+ seekRequired = sampleQueue.advanceTo(positionUs, true, true) == SampleQueue.ADVANCE_FAILED
&& sampleQueue.getReadIndex() != 0;
}
}
@@ -371,12 +371,13 @@ import java.util.Arrays;
lastSeekPositionUs);
}
- /* package */ void skipData(int track, long positionUs) {
+ /* package */ int skipData(int track, long positionUs) {
SampleQueue sampleQueue = sampleQueues[track];
if (loadingFinished && positionUs > sampleQueue.getLargestQueuedTimestampUs()) {
- sampleQueue.advanceToEnd();
+ return sampleQueue.advanceToEnd();
} else {
- sampleQueue.advanceTo(positionUs, true, true);
+ int skipCount = sampleQueue.advanceTo(positionUs, true, true);
+ return skipCount == SampleQueue.ADVANCE_FAILED ? 0 : skipCount;
}
}
@@ -558,7 +559,8 @@ import java.util.Arrays;
for (int i = 0; i < trackCount; i++) {
SampleQueue sampleQueue = sampleQueues[i];
sampleQueue.rewind();
- boolean seekInsideQueue = sampleQueue.advanceTo(positionUs, true, false);
+ boolean seekInsideQueue = sampleQueue.advanceTo(positionUs, true, false)
+ != SampleQueue.ADVANCE_FAILED;
// If we have AV tracks then an in-buffer seek is successful if the seek into every AV queue
// is successful. We ignore whether seeks within non-AV queues are successful in this case, as
// they may be sparse or poorly interleaved. If we only have non-AV tracks then a seek is
@@ -632,8 +634,8 @@ import java.util.Arrays;
}
@Override
- public void skipData(long positionUs) {
- ExtractorMediaPeriod.this.skipData(track, positionUs);
+ public int skipData(long positionUs) {
+ return ExtractorMediaPeriod.this.skipData(track, positionUs);
}
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleMetadataQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleMetadataQueue.java
index 03b2e3b715..d70c59b195 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleMetadataQueue.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleMetadataQueue.java
@@ -253,32 +253,35 @@ import com.google.android.exoplayer2.util.Util;
* @param allowTimeBeyondBuffer Whether the operation can succeed if {@code timeUs} is beyond the
* end of the queue, by advancing the read position to the last sample (or keyframe) in the
* queue.
- * @return Whether the operation was a success. A successful advance is one in which the read
- * position was unchanged or advanced, and is now at a sample meeting the specified criteria.
+ * @return The number of samples that were skipped if the operation was successful, which may be
+ * equal to 0, or {@link SampleQueue#ADVANCE_FAILED} if the operation was not successful. A
+ * successful advance is one in which the read position was unchanged or advanced, and is now
+ * at a sample meeting the specified criteria.
*/
- public synchronized boolean advanceTo(long timeUs, boolean toKeyframe,
+ public synchronized int advanceTo(long timeUs, boolean toKeyframe,
boolean allowTimeBeyondBuffer) {
int relativeReadIndex = getRelativeIndex(readPosition);
if (!hasNextSample() || timeUs < timesUs[relativeReadIndex]
|| (timeUs > largestQueuedTimestampUs && !allowTimeBeyondBuffer)) {
- return false;
+ return SampleQueue.ADVANCE_FAILED;
}
int offset = findSampleBefore(relativeReadIndex, length - readPosition, timeUs, toKeyframe);
if (offset == -1) {
- return false;
+ return SampleQueue.ADVANCE_FAILED;
}
readPosition += offset;
- return true;
+ return offset;
}
/**
* Advances the read position to the end of the queue.
+ *
+ * @return The number of samples that were skipped.
*/
- public synchronized void advanceToEnd() {
- if (!hasNextSample()) {
- return;
- }
+ public synchronized int advanceToEnd() {
+ int skipCount = length - readPosition;
readPosition = length;
+ return skipCount;
}
/**
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 c7bae8f8b4..b83cf7df5b 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
@@ -49,6 +49,8 @@ public final class SampleQueue implements TrackOutput {
}
+ public static final int ADVANCE_FAILED = -1;
+
private static final int INITIAL_SCRATCH_SIZE = 32;
private final Allocator allocator;
@@ -255,9 +257,11 @@ public final class SampleQueue implements TrackOutput {
/**
* Advances the read position to the end of the queue.
+ *
+ * @return The number of samples that were skipped.
*/
- public void advanceToEnd() {
- metadataQueue.advanceToEnd();
+ public int advanceToEnd() {
+ return metadataQueue.advanceToEnd();
}
/**
@@ -268,10 +272,12 @@ public final class SampleQueue implements TrackOutput {
* time, rather than to any sample before or at that time.
* @param allowTimeBeyondBuffer Whether the operation can succeed if {@code timeUs} is beyond the
* end of the queue, by advancing the read position to the last sample (or keyframe).
- * @return Whether the operation was a success. A successful advance is one in which the read
- * position was unchanged or advanced, and is now at a sample meeting the specified criteria.
+ * @return The number of samples that were skipped if the operation was successful, which may be
+ * equal to 0, or {@link #ADVANCE_FAILED} if the operation was not successful. A successful
+ * advance is one in which the read position was unchanged or advanced, and is now at a sample
+ * meeting the specified criteria.
*/
- public boolean advanceTo(long timeUs, boolean toKeyframe, boolean allowTimeBeyondBuffer) {
+ public int advanceTo(long timeUs, boolean toKeyframe, boolean allowTimeBeyondBuffer) {
return metadataQueue.advanceTo(timeUs, toKeyframe, allowTimeBeyondBuffer);
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleStream.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleStream.java
index dc58c29c22..06efc980e2 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleStream.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleStream.java
@@ -70,7 +70,8 @@ public interface SampleStream {
* {@code positionUs} is beyond it.
*
* @param positionUs The specified time.
+ * @return The number of samples that were skipped.
*/
- void skipData(long positionUs);
+ int skipData(long positionUs);
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java
index 3435c01eeb..b19f398d86 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java
@@ -235,10 +235,12 @@ import java.util.Arrays;
}
@Override
- public void skipData(long positionUs) {
- if (positionUs > 0) {
+ public int skipData(long positionUs) {
+ if (positionUs > 0 && streamState != STREAM_STATE_END_OF_STREAM) {
streamState = STREAM_STATE_END_OF_STREAM;
+ return 1;
}
+ return 0;
}
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java
index 0fc3d5881e..f2609a0ffd 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java
@@ -160,6 +160,7 @@ public class ChunkSampleStream