mirror of
https://github.com/androidx/media.git
synced 2025-05-04 06:00:37 +08:00
Expose first index in SampleQueue
This will be needed when retaining a back-buffer. Being able to query the first index allows us to work out when we've discarded all samples that were obtained from a particular chunk, which we'll use to determine when to remove chunks from ChunkSampleStream.mediaChunks. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=175172085
This commit is contained in:
parent
694bd997cb
commit
eb4e05199f
@ -51,8 +51,8 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
private Format[] formats;
|
private Format[] formats;
|
||||||
|
|
||||||
private int length;
|
private int length;
|
||||||
private int absoluteStartIndex;
|
private int absoluteFirstIndex;
|
||||||
private int relativeStartIndex;
|
private int relativeFirstIndex;
|
||||||
private int readPosition;
|
private int readPosition;
|
||||||
|
|
||||||
private long largestDiscardedTimestampUs;
|
private long largestDiscardedTimestampUs;
|
||||||
@ -87,8 +87,8 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
*/
|
*/
|
||||||
public void reset(boolean resetUpstreamFormat) {
|
public void reset(boolean resetUpstreamFormat) {
|
||||||
length = 0;
|
length = 0;
|
||||||
absoluteStartIndex = 0;
|
absoluteFirstIndex = 0;
|
||||||
relativeStartIndex = 0;
|
relativeFirstIndex = 0;
|
||||||
readPosition = 0;
|
readPosition = 0;
|
||||||
upstreamKeyframeRequired = true;
|
upstreamKeyframeRequired = true;
|
||||||
largestDiscardedTimestampUs = Long.MIN_VALUE;
|
largestDiscardedTimestampUs = Long.MIN_VALUE;
|
||||||
@ -103,7 +103,7 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
* Returns the current absolute write index.
|
* Returns the current absolute write index.
|
||||||
*/
|
*/
|
||||||
public int getWriteIndex() {
|
public int getWriteIndex() {
|
||||||
return absoluteStartIndex + length;
|
return absoluteFirstIndex + length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -132,11 +132,18 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
|
|
||||||
// Called by the consuming thread.
|
// Called by the consuming thread.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current absolute start index.
|
||||||
|
*/
|
||||||
|
public int getFirstIndex() {
|
||||||
|
return absoluteFirstIndex;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current absolute read index.
|
* Returns the current absolute read index.
|
||||||
*/
|
*/
|
||||||
public int getReadIndex() {
|
public int getReadIndex() {
|
||||||
return absoluteStartIndex + readPosition;
|
return absoluteFirstIndex + readPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -297,11 +304,11 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
* {@link C#POSITION_UNSET} if no discarding of data is necessary.
|
* {@link C#POSITION_UNSET} if no discarding of data is necessary.
|
||||||
*/
|
*/
|
||||||
public synchronized long discardTo(long timeUs, boolean toKeyframe, boolean stopAtReadPosition) {
|
public synchronized long discardTo(long timeUs, boolean toKeyframe, boolean stopAtReadPosition) {
|
||||||
if (length == 0 || timeUs < timesUs[relativeStartIndex]) {
|
if (length == 0 || timeUs < timesUs[relativeFirstIndex]) {
|
||||||
return C.POSITION_UNSET;
|
return C.POSITION_UNSET;
|
||||||
}
|
}
|
||||||
int searchLength = stopAtReadPosition && readPosition != length ? readPosition + 1 : length;
|
int searchLength = stopAtReadPosition && readPosition != length ? readPosition + 1 : length;
|
||||||
int discardCount = findSampleBefore(relativeStartIndex, searchLength, timeUs, toKeyframe);
|
int discardCount = findSampleBefore(relativeFirstIndex, searchLength, timeUs, toKeyframe);
|
||||||
if (discardCount == -1) {
|
if (discardCount == -1) {
|
||||||
return C.POSITION_UNSET;
|
return C.POSITION_UNSET;
|
||||||
}
|
}
|
||||||
@ -382,15 +389,15 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
int[] newSizes = new int[newCapacity];
|
int[] newSizes = new int[newCapacity];
|
||||||
CryptoData[] newCryptoDatas = new CryptoData[newCapacity];
|
CryptoData[] newCryptoDatas = new CryptoData[newCapacity];
|
||||||
Format[] newFormats = new Format[newCapacity];
|
Format[] newFormats = new Format[newCapacity];
|
||||||
int beforeWrap = capacity - relativeStartIndex;
|
int beforeWrap = capacity - relativeFirstIndex;
|
||||||
System.arraycopy(offsets, relativeStartIndex, newOffsets, 0, beforeWrap);
|
System.arraycopy(offsets, relativeFirstIndex, newOffsets, 0, beforeWrap);
|
||||||
System.arraycopy(timesUs, relativeStartIndex, newTimesUs, 0, beforeWrap);
|
System.arraycopy(timesUs, relativeFirstIndex, newTimesUs, 0, beforeWrap);
|
||||||
System.arraycopy(flags, relativeStartIndex, newFlags, 0, beforeWrap);
|
System.arraycopy(flags, relativeFirstIndex, newFlags, 0, beforeWrap);
|
||||||
System.arraycopy(sizes, relativeStartIndex, newSizes, 0, beforeWrap);
|
System.arraycopy(sizes, relativeFirstIndex, newSizes, 0, beforeWrap);
|
||||||
System.arraycopy(cryptoDatas, relativeStartIndex, newCryptoDatas, 0, beforeWrap);
|
System.arraycopy(cryptoDatas, relativeFirstIndex, newCryptoDatas, 0, beforeWrap);
|
||||||
System.arraycopy(formats, relativeStartIndex, newFormats, 0, beforeWrap);
|
System.arraycopy(formats, relativeFirstIndex, newFormats, 0, beforeWrap);
|
||||||
System.arraycopy(sourceIds, relativeStartIndex, newSourceIds, 0, beforeWrap);
|
System.arraycopy(sourceIds, relativeFirstIndex, newSourceIds, 0, beforeWrap);
|
||||||
int afterWrap = relativeStartIndex;
|
int afterWrap = relativeFirstIndex;
|
||||||
System.arraycopy(offsets, 0, newOffsets, beforeWrap, afterWrap);
|
System.arraycopy(offsets, 0, newOffsets, beforeWrap, afterWrap);
|
||||||
System.arraycopy(timesUs, 0, newTimesUs, beforeWrap, afterWrap);
|
System.arraycopy(timesUs, 0, newTimesUs, beforeWrap, afterWrap);
|
||||||
System.arraycopy(flags, 0, newFlags, beforeWrap, afterWrap);
|
System.arraycopy(flags, 0, newFlags, beforeWrap, afterWrap);
|
||||||
@ -405,7 +412,7 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
cryptoDatas = newCryptoDatas;
|
cryptoDatas = newCryptoDatas;
|
||||||
formats = newFormats;
|
formats = newFormats;
|
||||||
sourceIds = newSourceIds;
|
sourceIds = newSourceIds;
|
||||||
relativeStartIndex = 0;
|
relativeFirstIndex = 0;
|
||||||
length = capacity;
|
length = capacity;
|
||||||
capacity = newCapacity;
|
capacity = newCapacity;
|
||||||
}
|
}
|
||||||
@ -440,7 +447,7 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
relativeSampleIndex = capacity - 1;
|
relativeSampleIndex = capacity - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
discardUpstreamSamples(absoluteStartIndex + retainCount);
|
discardUpstreamSamples(absoluteFirstIndex + retainCount);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,7 +461,7 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
* @param length The length of the range being searched.
|
* @param length The length of the range being searched.
|
||||||
* @param timeUs The specified time.
|
* @param timeUs The specified time.
|
||||||
* @param keyframe Whether only keyframes should be considered.
|
* @param keyframe Whether only keyframes should be considered.
|
||||||
* @return The offset from {@code relativeStartIndex} to the found sample, or -1 if no matching
|
* @return The offset from {@code relativeFirstIndex} to the found sample, or -1 if no matching
|
||||||
* sample was found.
|
* sample was found.
|
||||||
*/
|
*/
|
||||||
private int findSampleBefore(int relativeStartIndex, int length, long timeUs, boolean keyframe) {
|
private int findSampleBefore(int relativeStartIndex, int length, long timeUs, boolean keyframe) {
|
||||||
@ -487,20 +494,20 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
largestDiscardedTimestampUs = Math.max(largestDiscardedTimestampUs,
|
largestDiscardedTimestampUs = Math.max(largestDiscardedTimestampUs,
|
||||||
getLargestTimestamp(discardCount));
|
getLargestTimestamp(discardCount));
|
||||||
length -= discardCount;
|
length -= discardCount;
|
||||||
absoluteStartIndex += discardCount;
|
absoluteFirstIndex += discardCount;
|
||||||
relativeStartIndex += discardCount;
|
relativeFirstIndex += discardCount;
|
||||||
if (relativeStartIndex >= capacity) {
|
if (relativeFirstIndex >= capacity) {
|
||||||
relativeStartIndex -= capacity;
|
relativeFirstIndex -= capacity;
|
||||||
}
|
}
|
||||||
readPosition -= discardCount;
|
readPosition -= discardCount;
|
||||||
if (readPosition < 0) {
|
if (readPosition < 0) {
|
||||||
readPosition = 0;
|
readPosition = 0;
|
||||||
}
|
}
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
int relativeLastDiscardIndex = (relativeStartIndex == 0 ? capacity : relativeStartIndex) - 1;
|
int relativeLastDiscardIndex = (relativeFirstIndex == 0 ? capacity : relativeFirstIndex) - 1;
|
||||||
return offsets[relativeLastDiscardIndex] + sizes[relativeLastDiscardIndex];
|
return offsets[relativeLastDiscardIndex] + sizes[relativeLastDiscardIndex];
|
||||||
} else {
|
} else {
|
||||||
return offsets[relativeStartIndex];
|
return offsets[relativeFirstIndex];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -537,7 +544,7 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
* @param offset The offset, which must be in the range [0, length].
|
* @param offset The offset, which must be in the range [0, length].
|
||||||
*/
|
*/
|
||||||
private int getRelativeIndex(int offset) {
|
private int getRelativeIndex(int offset) {
|
||||||
int relativeIndex = relativeStartIndex + offset;
|
int relativeIndex = relativeFirstIndex + offset;
|
||||||
return relativeIndex < capacity ? relativeIndex : relativeIndex - capacity;
|
return relativeIndex < capacity ? relativeIndex : relativeIndex - capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +181,13 @@ public final class SampleQueue implements TrackOutput {
|
|||||||
return metadataQueue.hasNextSample();
|
return metadataQueue.hasNextSample();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the absolute index of the first sample.
|
||||||
|
*/
|
||||||
|
public int getFirstIndex() {
|
||||||
|
return metadataQueue.getFirstIndex();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current absolute read index.
|
* Returns the current absolute read index.
|
||||||
*/
|
*/
|
||||||
|
@ -215,12 +215,14 @@ public final class SampleQueueTest {
|
|||||||
public void testReadMultiWithRewind() {
|
public void testReadMultiWithRewind() {
|
||||||
writeTestData();
|
writeTestData();
|
||||||
assertReadTestData();
|
assertReadTestData();
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(0);
|
||||||
assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
|
||||||
assertAllocationCount(10);
|
assertAllocationCount(10);
|
||||||
// Rewind.
|
// Rewind.
|
||||||
sampleQueue.rewind();
|
sampleQueue.rewind();
|
||||||
assertAllocationCount(10);
|
assertAllocationCount(10);
|
||||||
// Read again.
|
// Read again.
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(0);
|
||||||
assertThat(sampleQueue.getReadIndex()).isEqualTo(0);
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(0);
|
||||||
assertReadTestData();
|
assertReadTestData();
|
||||||
}
|
}
|
||||||
@ -230,11 +232,14 @@ public final class SampleQueueTest {
|
|||||||
writeTestData();
|
writeTestData();
|
||||||
assertReadTestData();
|
assertReadTestData();
|
||||||
sampleQueue.discardToRead();
|
sampleQueue.discardToRead();
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(8);
|
||||||
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
|
||||||
assertAllocationCount(0);
|
assertAllocationCount(0);
|
||||||
// Rewind.
|
// Rewind.
|
||||||
sampleQueue.rewind();
|
sampleQueue.rewind();
|
||||||
assertAllocationCount(0);
|
assertAllocationCount(0);
|
||||||
// Can't read again.
|
// Can't read again.
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(8);
|
||||||
assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
|
||||||
assertReadEndOfStream(false);
|
assertReadEndOfStream(false);
|
||||||
}
|
}
|
||||||
@ -332,6 +337,7 @@ public final class SampleQueueTest {
|
|||||||
writeTestData();
|
writeTestData();
|
||||||
// Should discard everything.
|
// Should discard everything.
|
||||||
sampleQueue.discardToEnd();
|
sampleQueue.discardToEnd();
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(8);
|
||||||
assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
|
||||||
assertAllocationCount(0);
|
assertAllocationCount(0);
|
||||||
// We should still be able to read the upstream format.
|
// We should still be able to read the upstream format.
|
||||||
@ -346,28 +352,39 @@ public final class SampleQueueTest {
|
|||||||
writeTestData();
|
writeTestData();
|
||||||
// Shouldn't discard anything.
|
// Shouldn't discard anything.
|
||||||
sampleQueue.discardTo(LAST_SAMPLE_TIMESTAMP, false, true);
|
sampleQueue.discardTo(LAST_SAMPLE_TIMESTAMP, false, true);
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(0);
|
||||||
assertThat(sampleQueue.getReadIndex()).isEqualTo(0);
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(0);
|
||||||
assertAllocationCount(10);
|
assertAllocationCount(10);
|
||||||
// Read the first sample.
|
// Read the first sample.
|
||||||
assertReadTestData(null, 0, 1);
|
assertReadTestData(null, 0, 1);
|
||||||
// Shouldn't discard anything.
|
// Shouldn't discard anything.
|
||||||
sampleQueue.discardTo(TEST_SAMPLE_TIMESTAMPS[1] - 1, false, true);
|
sampleQueue.discardTo(TEST_SAMPLE_TIMESTAMPS[1] - 1, false, true);
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(0);
|
||||||
assertThat(sampleQueue.getReadIndex()).isEqualTo(1);
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(1);
|
||||||
assertAllocationCount(10);
|
assertAllocationCount(10);
|
||||||
// Should discard the read sample.
|
// Should discard the read sample.
|
||||||
sampleQueue.discardTo(TEST_SAMPLE_TIMESTAMPS[1], false, true);
|
sampleQueue.discardTo(TEST_SAMPLE_TIMESTAMPS[1], false, true);
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(1);
|
||||||
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(1);
|
||||||
assertAllocationCount(9);
|
assertAllocationCount(9);
|
||||||
// Shouldn't discard anything.
|
// Shouldn't discard anything.
|
||||||
sampleQueue.discardTo(LAST_SAMPLE_TIMESTAMP, false, true);
|
sampleQueue.discardTo(LAST_SAMPLE_TIMESTAMP, false, true);
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(1);
|
||||||
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(1);
|
||||||
assertAllocationCount(9);
|
assertAllocationCount(9);
|
||||||
// Should be able to read the remaining samples.
|
// Should be able to read the remaining samples.
|
||||||
assertReadTestData(TEST_FORMAT_1, 1, 7);
|
assertReadTestData(TEST_FORMAT_1, 1, 7);
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(1);
|
||||||
assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
|
||||||
// Should discard up to the second last sample
|
// Should discard up to the second last sample
|
||||||
sampleQueue.discardTo(LAST_SAMPLE_TIMESTAMP - 1, false, true);
|
sampleQueue.discardTo(LAST_SAMPLE_TIMESTAMP - 1, false, true);
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(6);
|
||||||
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
|
||||||
assertAllocationCount(3);
|
assertAllocationCount(3);
|
||||||
// Should discard up the last sample
|
// Should discard up the last sample
|
||||||
sampleQueue.discardTo(LAST_SAMPLE_TIMESTAMP, false, true);
|
sampleQueue.discardTo(LAST_SAMPLE_TIMESTAMP, false, true);
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(7);
|
||||||
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
|
||||||
assertAllocationCount(1);
|
assertAllocationCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,10 +393,12 @@ public final class SampleQueueTest {
|
|||||||
writeTestData();
|
writeTestData();
|
||||||
// Shouldn't discard anything.
|
// Shouldn't discard anything.
|
||||||
sampleQueue.discardTo(TEST_SAMPLE_TIMESTAMPS[1] - 1, false, false);
|
sampleQueue.discardTo(TEST_SAMPLE_TIMESTAMPS[1] - 1, false, false);
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(0);
|
||||||
assertThat(sampleQueue.getReadIndex()).isEqualTo(0);
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(0);
|
||||||
assertAllocationCount(10);
|
assertAllocationCount(10);
|
||||||
// Should discard the first sample.
|
// Should discard the first sample.
|
||||||
sampleQueue.discardTo(TEST_SAMPLE_TIMESTAMPS[1], false, false);
|
sampleQueue.discardTo(TEST_SAMPLE_TIMESTAMPS[1], false, false);
|
||||||
|
assertThat(sampleQueue.getFirstIndex()).isEqualTo(1);
|
||||||
assertThat(sampleQueue.getReadIndex()).isEqualTo(1);
|
assertThat(sampleQueue.getReadIndex()).isEqualTo(1);
|
||||||
assertAllocationCount(9);
|
assertAllocationCount(9);
|
||||||
// Should be able to read the remaining samples.
|
// Should be able to read the remaining samples.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user