Commit 29b12e2f by tonihei Committed by Ian Baker

Split SampleQueue.advanceTo into two operations.

The method currently advances the read position and returns the number
of skipped samples. This prevents checking how many samples are skipped
before the operation is executed.

Instead, we have a new method that returns the number of to be skipped
samples and a skip method that executes the skipping.

PiperOrigin-RevId: 320953439
parent 92437f3a
......@@ -499,12 +499,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
maybeNotifyDownstreamFormat(track);
SampleQueue sampleQueue = sampleQueues[track];
int skipCount;
if (loadingFinished && positionUs > sampleQueue.getLargestQueuedTimestampUs()) {
skipCount = sampleQueue.advanceToEnd();
} else {
skipCount = sampleQueue.advanceTo(positionUs);
}
int skipCount = sampleQueue.getSkipCount(positionUs, loadingFinished);
sampleQueue.skip(skipCount);
if (skipCount == 0) {
maybeStartDeferredRetry(track);
}
......
......@@ -15,6 +15,8 @@
*/
package com.google.android.exoplayer2.source;
import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import android.os.Looper;
import android.util.Log;
import androidx.annotation.CallSuper;
......@@ -402,34 +404,39 @@ public class SampleQueue implements TrackOutput {
}
/**
* Advances the read position to the keyframe before or at the specified time.
* Returns the number of samples that need to be {@link #skip(int) skipped} to advance the read
* position to the keyframe before or at the specified time.
*
* @param timeUs The time to advance to.
* @return The number of samples that were skipped, which may be equal to 0.
* @param allowEndOfQueue Whether the end of the queue is considered a keyframe when {@code
* timeUs} is larger than the largest queued timestamp.
* @return The number of samples that need to be skipped, which may be equal to 0.
*/
public final synchronized int advanceTo(long timeUs) {
public final synchronized int getSkipCount(long timeUs, boolean allowEndOfQueue) {
int relativeReadIndex = getRelativeIndex(readPosition);
if (!hasNextSample() || timeUs < timesUs[relativeReadIndex]) {
return 0;
}
if (timeUs > largestQueuedTimestampUs && allowEndOfQueue) {
return length - readPosition;
}
int offset =
findSampleBefore(relativeReadIndex, length - readPosition, timeUs, /* keyframe= */ true);
if (offset == -1) {
return 0;
}
readPosition += offset;
return offset;
}
/**
* Advances the read position to the end of the queue.
* Advances the read position by the specified number of samples.
*
* @return The number of samples that were skipped.
* @param count The number of samples to advance the read position by. Must be at least 0 and at
* most {@link #getWriteIndex()} - {@link #getReadIndex()}.
*/
public final synchronized int advanceToEnd() {
int skipCount = length - readPosition;
readPosition = length;
return skipCount;
public final synchronized void skip(int count) {
checkArgument(count >= 0 && readPosition + count <= length);
readPosition += count;
}
/**
......@@ -788,7 +795,7 @@ public class SampleQueue implements TrackOutput {
private long discardUpstreamSampleMetadata(int discardFromIndex) {
int discardCount = getWriteIndex() - discardFromIndex;
Assertions.checkArgument(0 <= discardCount && discardCount <= (length - readPosition));
checkArgument(0 <= discardCount && discardCount <= (length - readPosition));
length -= discardCount;
largestQueuedTimestampUs = Math.max(largestDiscardedTimestampUs, getLargestTimestamp(length));
isLastSampleQueued = discardCount == 0 && isLastSampleQueued;
......
......@@ -392,12 +392,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
if (isPendingReset()) {
return 0;
}
int skipCount;
if (loadingFinished && positionUs > primarySampleQueue.getLargestQueuedTimestampUs()) {
skipCount = primarySampleQueue.advanceToEnd();
} else {
skipCount = primarySampleQueue.advanceTo(positionUs);
}
int skipCount = primarySampleQueue.getSkipCount(positionUs, loadingFinished);
primarySampleQueue.skip(skipCount);
maybeNotifyPrimaryTrackFormatChanged();
return skipCount;
}
......@@ -789,12 +785,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
return 0;
}
maybeNotifyDownstreamFormat();
int skipCount;
if (loadingFinished && positionUs > sampleQueue.getLargestQueuedTimestampUs()) {
skipCount = sampleQueue.advanceToEnd();
} else {
skipCount = sampleQueue.advanceTo(positionUs);
}
int skipCount = sampleQueue.getSkipCount(positionUs, loadingFinished);
sampleQueue.skip(skipCount);
return skipCount;
}
......
......@@ -21,6 +21,7 @@ import static com.google.android.exoplayer2.C.RESULT_BUFFER_READ;
import static com.google.android.exoplayer2.C.RESULT_FORMAT_READ;
import static com.google.android.exoplayer2.C.RESULT_NOTHING_READ;
import static com.google.common.truth.Truth.assertThat;
import static java.lang.Long.MAX_VALUE;
import static java.lang.Long.MIN_VALUE;
import static java.util.Arrays.copyOfRange;
import static org.junit.Assert.assertArrayEquals;
......@@ -590,9 +591,10 @@ public final class SampleQueueTest {
}
@Test
public void advanceToEnd() {
public void skipToEnd() {
writeTestData();
sampleQueue.advanceToEnd();
sampleQueue.skip(
sampleQueue.getSkipCount(/* timeUs= */ MAX_VALUE, /* allowEndOfQueue= */ true));
assertAllocationCount(10);
sampleQueue.discardToRead();
assertAllocationCount(0);
......@@ -604,10 +606,11 @@ public final class SampleQueueTest {
}
@Test
public void advanceToEndRetainsUnassignedData() {
public void skipToEndRetainsUnassignedData() {
sampleQueue.format(FORMAT_1);
sampleQueue.sampleData(new ParsableByteArray(DATA), ALLOCATION_SIZE);
sampleQueue.advanceToEnd();
sampleQueue.skip(
sampleQueue.getSkipCount(/* timeUs= */ MAX_VALUE, /* allowEndOfQueue= */ true));
assertAllocationCount(1);
sampleQueue.discardToRead();
// Skipping shouldn't discard data that may belong to a sample whose metadata has yet to be
......@@ -635,41 +638,47 @@ public final class SampleQueueTest {
}
@Test
public void advanceToBeforeBuffer() {
public void skipToBeforeBuffer() {
writeTestData();
int skipCount = sampleQueue.advanceTo(SAMPLE_TIMESTAMPS[0] - 1);
int skipCount =
sampleQueue.getSkipCount(SAMPLE_TIMESTAMPS[0] - 1, /* allowEndOfQueue= */ false);
// Should have no effect (we're already at the first frame).
assertThat(skipCount).isEqualTo(0);
sampleQueue.skip(skipCount);
assertReadTestData();
assertNoSamplesToRead(FORMAT_2);
}
@Test
public void advanceToStartOfBuffer() {
public void skipToStartOfBuffer() {
writeTestData();
int skipCount = sampleQueue.advanceTo(SAMPLE_TIMESTAMPS[0]);
int skipCount = sampleQueue.getSkipCount(SAMPLE_TIMESTAMPS[0], /* allowEndOfQueue= */ false);
// Should have no effect (we're already at the first frame).
assertThat(skipCount).isEqualTo(0);
sampleQueue.skip(skipCount);
assertReadTestData();
assertNoSamplesToRead(FORMAT_2);
}
@Test
public void advanceToEndOfBuffer() {
public void skipToEndOfBuffer() {
writeTestData();
int skipCount = sampleQueue.advanceTo(LAST_SAMPLE_TIMESTAMP);
int skipCount = sampleQueue.getSkipCount(LAST_SAMPLE_TIMESTAMP, /* allowEndOfQueue= */ false);
// Should advance to 2nd keyframe (the 4th frame).
assertThat(skipCount).isEqualTo(4);
sampleQueue.skip(skipCount);
assertReadTestData(/* startFormat= */ null, DATA_SECOND_KEYFRAME_INDEX);
assertNoSamplesToRead(FORMAT_2);
}
@Test
public void advanceToAfterBuffer() {
public void skipToAfterBuffer() {
writeTestData();
int skipCount = sampleQueue.advanceTo(LAST_SAMPLE_TIMESTAMP + 1);
int skipCount =
sampleQueue.getSkipCount(LAST_SAMPLE_TIMESTAMP + 1, /* allowEndOfQueue= */ false);
// Should advance to 2nd keyframe (the 4th frame).
assertThat(skipCount).isEqualTo(4);
sampleQueue.skip(skipCount);
assertReadTestData(/* startFormat= */ null, DATA_SECOND_KEYFRAME_INDEX);
assertNoSamplesToRead(FORMAT_2);
}
......
......@@ -595,11 +595,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
}
SampleQueue sampleQueue = sampleQueues[sampleQueueIndex];
if (loadingFinished && positionUs > sampleQueue.getLargestQueuedTimestampUs()) {
return sampleQueue.advanceToEnd();
} else {
return sampleQueue.advanceTo(positionUs);
}
int skipCount = sampleQueue.getSkipCount(positionUs, loadingFinished);
sampleQueue.skip(skipCount);
return skipCount;
}
// SequenceableLoader implementation
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment