Commit 950c2159 by olly Committed by Oliver Woodman

Discard upstream allocations more aggressively + doc cleanup

- If we have <s1>garbage<s2> and discard <s2>, throw away
  the garbage too.
- Cleanup some documentation to consistently refer to the
  queue as "queue" rather than "buffer".

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=159816309
parent aca80b83
...@@ -364,7 +364,7 @@ public class SampleQueueTest extends TestCase { ...@@ -364,7 +364,7 @@ public class SampleQueueTest extends TestCase {
sampleQueue.discardUpstreamSamples(7); sampleQueue.discardUpstreamSamples(7);
assertAllocationCount(9); assertAllocationCount(9);
sampleQueue.discardUpstreamSamples(6); sampleQueue.discardUpstreamSamples(6);
assertAllocationCount(8); // Byte not belonging to sample prevents 7. assertAllocationCount(7);
sampleQueue.discardUpstreamSamples(5); sampleQueue.discardUpstreamSamples(5);
assertAllocationCount(5); assertAllocationCount(5);
sampleQueue.discardUpstreamSamples(4); sampleQueue.discardUpstreamSamples(4);
...@@ -372,11 +372,11 @@ public class SampleQueueTest extends TestCase { ...@@ -372,11 +372,11 @@ public class SampleQueueTest extends TestCase {
sampleQueue.discardUpstreamSamples(3); sampleQueue.discardUpstreamSamples(3);
assertAllocationCount(3); assertAllocationCount(3);
sampleQueue.discardUpstreamSamples(2); sampleQueue.discardUpstreamSamples(2);
assertAllocationCount(3); // Byte not belonging to sample prevents 2. assertAllocationCount(2);
sampleQueue.discardUpstreamSamples(1); sampleQueue.discardUpstreamSamples(1);
assertAllocationCount(2); // Byte not belonging to sample prevents 1. assertAllocationCount(1);
sampleQueue.discardUpstreamSamples(0); sampleQueue.discardUpstreamSamples(0);
assertAllocationCount(1); // Byte not belonging to sample prevents 0. assertAllocationCount(0);
assertReadFormat(false, TEST_FORMAT_2); assertReadFormat(false, TEST_FORMAT_2);
assertNoSamplesToRead(TEST_FORMAT_2); assertNoSamplesToRead(TEST_FORMAT_2);
} }
...@@ -386,7 +386,7 @@ public class SampleQueueTest extends TestCase { ...@@ -386,7 +386,7 @@ public class SampleQueueTest extends TestCase {
sampleQueue.discardUpstreamSamples(4); sampleQueue.discardUpstreamSamples(4);
assertAllocationCount(4); assertAllocationCount(4);
sampleQueue.discardUpstreamSamples(0); sampleQueue.discardUpstreamSamples(0);
assertAllocationCount(1); // Byte not belonging to sample prevents 0. assertAllocationCount(0);
assertReadFormat(false, TEST_FORMAT_2); assertReadFormat(false, TEST_FORMAT_2);
assertNoSamplesToRead(TEST_FORMAT_2); assertNoSamplesToRead(TEST_FORMAT_2);
} }
...@@ -410,7 +410,7 @@ public class SampleQueueTest extends TestCase { ...@@ -410,7 +410,7 @@ public class SampleQueueTest extends TestCase {
sampleQueue.discardUpstreamSamples(7); sampleQueue.discardUpstreamSamples(7);
assertAllocationCount(6); assertAllocationCount(6);
sampleQueue.discardUpstreamSamples(6); sampleQueue.discardUpstreamSamples(6);
assertAllocationCount(5); // Byte not belonging to sample prevents 4. assertAllocationCount(4);
sampleQueue.discardUpstreamSamples(5); sampleQueue.discardUpstreamSamples(5);
assertAllocationCount(2); assertAllocationCount(2);
sampleQueue.discardUpstreamSamples(4); sampleQueue.discardUpstreamSamples(4);
......
...@@ -100,30 +100,23 @@ import com.google.android.exoplayer2.util.Util; ...@@ -100,30 +100,23 @@ import com.google.android.exoplayer2.util.Util;
} }
/** /**
* Discards samples from the write side of the buffer. * Discards samples from the write side of the queue.
* *
* @param discardFromIndex The absolute index of the first sample to be discarded. * @param discardFromIndex The absolute index of the first sample to be discarded.
* @return The reduced total number of bytes written, after the samples have been discarded. * @return The reduced total number of bytes written after the samples have been discarded, or 0
* if the queue is now empty.
*/ */
public long discardUpstreamSamples(int discardFromIndex) { public long discardUpstreamSamples(int discardFromIndex) {
int discardCount = getWriteIndex() - discardFromIndex; int discardCount = getWriteIndex() - discardFromIndex;
Assertions.checkArgument(0 <= discardCount && discardCount <= (length - readPosition)); Assertions.checkArgument(0 <= discardCount && discardCount <= (length - readPosition));
int relativeEndIndex = (relativeStartIndex + length) % capacity;
if (discardCount == 0) {
if (absoluteStartIndex == 0 && length == 0) {
// Nothing has been written to the queue.
return 0;
}
int lastWriteIndex = (relativeEndIndex == 0 ? capacity : relativeEndIndex) - 1;
return offsets[lastWriteIndex] + sizes[lastWriteIndex];
}
length -= discardCount; length -= discardCount;
relativeEndIndex = (relativeEndIndex + capacity - discardCount) % capacity; largestQueuedTimestampUs = Math.max(largestDiscardedTimestampUs, getLargestTimestamp(length));
largestQueuedTimestampUs = Math.max(largestDiscardedTimestampUs, if (length == 0) {
getLargestTimestamp(relativeStartIndex, length)); return 0;
return offsets[relativeEndIndex]; } else {
int relativeLastWriteIndex = (relativeStartIndex + length - 1) % capacity;
return offsets[relativeLastWriteIndex] + sizes[relativeLastWriteIndex];
}
} }
public void sourceId(int sourceId) { public void sourceId(int sourceId) {
...@@ -140,8 +133,10 @@ import com.google.android.exoplayer2.util.Util; ...@@ -140,8 +133,10 @@ import com.google.android.exoplayer2.util.Util;
} }
/** /**
* Peeks the source id of the next sample, or the current upstream source id if * Peeks the source id of the next sample to be read, or the current upstream source id if the
* {@link #hasNextSample()} is {@code false}. * queue is empty or if the read position is at the end of the queue.
*
* @return The source id.
*/ */
public int peekSourceId() { public int peekSourceId() {
int relativeReadIndex = (relativeStartIndex + readPosition) % capacity; int relativeReadIndex = (relativeStartIndex + readPosition) % capacity;
...@@ -249,8 +244,8 @@ import com.google.android.exoplayer2.util.Util; ...@@ -249,8 +244,8 @@ import com.google.android.exoplayer2.util.Util;
* @param toKeyframe If true then attempts to advance to the keyframe before or at the specified * @param toKeyframe If true then attempts to advance to the keyframe before or at the specified
* time, rather than to any sample before or at that time. * time, rather than to any sample before or at that time.
* @param allowTimeBeyondBuffer Whether the operation can succeed if {@code timeUs} is beyond the * @param allowTimeBeyondBuffer Whether the operation can succeed if {@code timeUs} is beyond the
* end of the buffer, by advancing the read position to the last sample (or keyframe) in the * end of the queue, by advancing the read position to the last sample (or keyframe) in the
* buffer. * queue.
* @return Whether the operation was a success. A successful advance is one in which the read * @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. * position was unchanged or advanced, and is now at a sample meeting the specified criteria.
*/ */
...@@ -418,8 +413,11 @@ import com.google.android.exoplayer2.util.Util; ...@@ -418,8 +413,11 @@ import com.google.android.exoplayer2.util.Util;
* @return Whether the splice was successful. * @return Whether the splice was successful.
*/ */
public synchronized boolean attemptSplice(long timeUs) { public synchronized boolean attemptSplice(long timeUs) {
if (length == 0) {
return timeUs > largestDiscardedTimestampUs;
}
long largestReadTimestampUs = Math.max(largestDiscardedTimestampUs, long largestReadTimestampUs = Math.max(largestDiscardedTimestampUs,
getLargestTimestamp(relativeStartIndex, readPosition)); getLargestTimestamp(readPosition));
if (largestReadTimestampUs >= timeUs) { if (largestReadTimestampUs >= timeUs) {
return false; return false;
} }
...@@ -470,7 +468,7 @@ import com.google.android.exoplayer2.util.Util; ...@@ -470,7 +468,7 @@ import com.google.android.exoplayer2.util.Util;
*/ */
private long discardSamples(int discardCount) { private long discardSamples(int discardCount) {
largestDiscardedTimestampUs = Math.max(largestDiscardedTimestampUs, largestDiscardedTimestampUs = Math.max(largestDiscardedTimestampUs,
getLargestTimestamp(relativeStartIndex, discardCount)); getLargestTimestamp(discardCount));
length -= discardCount; length -= discardCount;
absoluteStartIndex += discardCount; absoluteStartIndex += discardCount;
relativeStartIndex += discardCount; relativeStartIndex += discardCount;
...@@ -482,22 +480,22 @@ import com.google.android.exoplayer2.util.Util; ...@@ -482,22 +480,22 @@ import com.google.android.exoplayer2.util.Util;
readPosition = 0; readPosition = 0;
} }
if (length == 0) { if (length == 0) {
int relativeLastDiscardedIndex = (relativeStartIndex - 1 + capacity) % capacity; int relativeLastDiscardIndex = (relativeStartIndex == 0 ? capacity : relativeStartIndex) - 1;
return offsets[relativeLastDiscardedIndex] + sizes[relativeLastDiscardedIndex]; return offsets[relativeLastDiscardIndex] + sizes[relativeLastDiscardIndex];
} else { } else {
return offsets[relativeStartIndex]; return offsets[relativeStartIndex];
} }
} }
/** /**
* Finds the largest timestamp in the specified range, assuming that the timestamps prior to a * Finds the largest timestamp of any sample from the start of the queue up to the specified
* keyframe are always less than the timestamp of the keyframe itself, and of subsequent frames. * length, assuming that the timestamps prior to a keyframe are always less than the timestamp of
* the keyframe itself, and of subsequent frames.
* *
* @param relativeStartIndex The relative index from which to start searching.
* @param length The length of the range being searched. * @param length The length of the range being searched.
* @return The largest timestamp, or {@link Long#MIN_VALUE} if {@code length <= 0}. * @return The largest timestamp, or {@link Long#MIN_VALUE} if {@code length <= 0}.
*/ */
private long getLargestTimestamp(int relativeStartIndex, int length) { private long getLargestTimestamp(int length) {
long largestTimestampUs = Long.MIN_VALUE; long largestTimestampUs = Long.MIN_VALUE;
for (int i = length - 1; i >= 0; i--) { for (int i = length - 1; i >= 0; i--) {
int sampleIndex = (relativeStartIndex + i) % capacity; int sampleIndex = (relativeStartIndex + i) % capacity;
......
...@@ -120,8 +120,7 @@ public final class SampleQueue implements TrackOutput { ...@@ -120,8 +120,7 @@ public final class SampleQueue implements TrackOutput {
} }
/** /**
* Indicates that samples subsequently queued to the buffer should be spliced into those already * Indicates samples that are subsequently queued should be spliced into those already queued.
* queued.
*/ */
public void splice() { public void splice() {
pendingSplice = true; pendingSplice = true;
...@@ -135,14 +134,14 @@ public final class SampleQueue implements TrackOutput { ...@@ -135,14 +134,14 @@ public final class SampleQueue implements TrackOutput {
} }
/** /**
* Discards samples from the write side of the buffer. * Discards samples from the write side of the queue.
* *
* @param discardFromIndex The absolute index of the first sample to be discarded. Must be in the * @param discardFromIndex The absolute index of the first sample to be discarded. Must be in the
* range [{@link #getReadIndex()}, {@link #getWriteIndex()}]. * range [{@link #getReadIndex()}, {@link #getWriteIndex()}].
*/ */
public void discardUpstreamSamples(int discardFromIndex) { public void discardUpstreamSamples(int discardFromIndex) {
totalBytesWritten = metadataQueue.discardUpstreamSamples(discardFromIndex); totalBytesWritten = metadataQueue.discardUpstreamSamples(discardFromIndex);
if (totalBytesWritten == firstAllocationNode.startPosition) { if (totalBytesWritten == 0 || totalBytesWritten == firstAllocationNode.startPosition) {
clearAllocationNodes(firstAllocationNode); clearAllocationNodes(firstAllocationNode);
firstAllocationNode = new AllocationNode(totalBytesWritten, allocationLength); firstAllocationNode = new AllocationNode(totalBytesWritten, allocationLength);
readAllocationNode = firstAllocationNode; readAllocationNode = firstAllocationNode;
...@@ -193,8 +192,8 @@ public final class SampleQueue implements TrackOutput { ...@@ -193,8 +192,8 @@ public final class SampleQueue implements TrackOutput {
} }
/** /**
* Peeks the source id of the next sample, or the current upstream source id if the buffer is * Peeks the source id of the next sample to be read, or the current upstream source id if the
* empty. * queue is empty or if the read position is at the end of the queue.
* *
* @return The source id. * @return The source id.
*/ */
...@@ -293,8 +292,7 @@ public final class SampleQueue implements TrackOutput { ...@@ -293,8 +292,7 @@ public final class SampleQueue implements TrackOutput {
* @param toKeyframe If true then attempts to advance to the keyframe before or at the specified * @param toKeyframe If true then attempts to advance to the keyframe before or at the specified
* time, rather than to any sample before or at that time. * time, rather than to any sample before or at that time.
* @param allowTimeBeyondBuffer Whether the operation can succeed if {@code timeUs} is beyond the * @param allowTimeBeyondBuffer Whether the operation can succeed if {@code timeUs} is beyond the
* end of the buffer, by advancing the read position to the last sample (or keyframe) in the * end of the queue, by advancing the read position to the last sample (or keyframe).
* buffer.
* @return Whether the operation was a success. A successful advance is one in which the read * @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. * position was unchanged or advanced, and is now at a sample meeting the specified criteria.
*/ */
...@@ -528,7 +526,7 @@ public final class SampleQueue implements TrackOutput { ...@@ -528,7 +526,7 @@ public final class SampleQueue implements TrackOutput {
/** /**
* Sets an offset that will be added to the timestamps (and sub-sample timestamps) of samples * Sets an offset that will be added to the timestamps (and sub-sample timestamps) of samples
* subsequently queued to the buffer. * that are subsequently queued.
* *
* @param sampleOffsetUs The timestamp offset in microseconds. * @param sampleOffsetUs The timestamp offset in microseconds.
*/ */
......
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