Propagate skipped input buffers through to CodecCounters
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=163683081
This commit is contained in:
parent
cdeea27973
commit
c2d7e05429
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,6 +36,12 @@ public final class DecoderCounters {
|
||||
* The number of queued input buffers.
|
||||
*/
|
||||
public int inputBufferCount;
|
||||
/**
|
||||
* The number of skipped input buffers.
|
||||
* <p>
|
||||
* 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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -160,6 +160,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
|
||||
* @return An estimate of the absolute position in microseconds up to which data is buffered, or
|
||||
* {@link C#TIME_END_OF_SOURCE} if the track is fully buffered.
|
||||
*/
|
||||
@Override
|
||||
public long getBufferedPositionUs() {
|
||||
if (loadingFinished) {
|
||||
return C.TIME_END_OF_SOURCE;
|
||||
@ -185,8 +186,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
|
||||
public void seekToUs(long positionUs) {
|
||||
lastSeekPositionUs = positionUs;
|
||||
// If we're not pending a reset, see if we can seek within the primary sample queue.
|
||||
boolean seekInsideBuffer = !isPendingReset() && primarySampleQueue.advanceTo(positionUs, true,
|
||||
positionUs < getNextLoadPositionUs());
|
||||
boolean seekInsideBuffer = !isPendingReset() && (primarySampleQueue.advanceTo(positionUs, true,
|
||||
positionUs < getNextLoadPositionUs()) != SampleQueue.ADVANCE_FAILED);
|
||||
if (seekInsideBuffer) {
|
||||
// We succeeded. Discard samples and corresponding chunks prior to the seek position.
|
||||
discardDownstreamMediaChunks(primarySampleQueue.getReadIndex());
|
||||
@ -266,13 +267,19 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skipData(long positionUs) {
|
||||
public int skipData(long positionUs) {
|
||||
int skipCount;
|
||||
if (loadingFinished && positionUs > primarySampleQueue.getLargestQueuedTimestampUs()) {
|
||||
primarySampleQueue.advanceToEnd();
|
||||
skipCount = primarySampleQueue.advanceToEnd();
|
||||
} else {
|
||||
primarySampleQueue.advanceTo(positionUs, true, true);
|
||||
skipCount = primarySampleQueue.advanceTo(positionUs, true, true);
|
||||
if (skipCount == SampleQueue.ADVANCE_FAILED) {
|
||||
skipCount = 0;
|
||||
}
|
||||
}
|
||||
primarySampleQueue.discardToRead();
|
||||
return skipCount;
|
||||
}
|
||||
|
||||
// Loader.Callback implementation.
|
||||
@ -470,11 +477,12 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skipData(long positionUs) {
|
||||
public int skipData(long positionUs) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,8 +50,8 @@ import java.io.IOException;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skipData(long positionUs) {
|
||||
sampleStreamWrapper.skipData(group, positionUs);
|
||||
public int skipData(long positionUs) {
|
||||
return sampleStreamWrapper.skipData(group, positionUs);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ import java.util.LinkedList;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@ -320,6 +320,7 @@ import java.util.LinkedList;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBufferedPositionUs() {
|
||||
if (loadingFinished) {
|
||||
return C.TIME_END_OF_SOURCE;
|
||||
@ -402,12 +403,13 @@ import java.util.LinkedList;
|
||||
lastSeekPositionUs);
|
||||
}
|
||||
|
||||
/* package */ void skipData(int trackGroupIndex, long positionUs) {
|
||||
/* package */ int skipData(int trackGroupIndex, long positionUs) {
|
||||
SampleQueue sampleQueue = sampleQueues[trackGroupIndex];
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -760,7 +762,8 @@ import java.util.LinkedList;
|
||||
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-queue 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
|
||||
|
@ -183,8 +183,9 @@ public final class DebugTextViewHelper implements Runnable, Player.EventListener
|
||||
return "";
|
||||
}
|
||||
counters.ensureUpdated();
|
||||
return " rb:" + counters.renderedOutputBufferCount
|
||||
return " sib:" + counters.skippedInputBufferCount
|
||||
+ " sb:" + counters.skippedOutputBufferCount
|
||||
+ " rb:" + counters.renderedOutputBufferCount
|
||||
+ " db:" + counters.droppedOutputBufferCount
|
||||
+ " mcdb:" + counters.maxConsecutiveDroppedOutputBufferCount;
|
||||
}
|
||||
|
@ -60,8 +60,8 @@ public final class FakeSampleStream implements SampleStream {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skipData(long positionUs) {
|
||||
// Do nothing.
|
||||
public int skipData(long positionUs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user