Commit 7eb0af7c by tonihei Committed by Oliver Woodman

Replace LinkedList with ArrayList in ChunkSampleStream.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=176759080
parent 2086c129
...@@ -28,9 +28,10 @@ import com.google.android.exoplayer2.source.SequenceableLoader; ...@@ -28,9 +28,10 @@ import com.google.android.exoplayer2.source.SequenceableLoader;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.Loader; import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList;
import java.util.List; import java.util.List;
/** /**
...@@ -51,7 +52,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -51,7 +52,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final Loader loader; private final Loader loader;
private final ChunkHolder nextChunkHolder; private final ChunkHolder nextChunkHolder;
private final LinkedList<BaseMediaChunk> mediaChunks; private final ArrayList<BaseMediaChunk> mediaChunks;
private final List<BaseMediaChunk> readOnlyMediaChunks; private final List<BaseMediaChunk> readOnlyMediaChunks;
private final SampleQueue primarySampleQueue; private final SampleQueue primarySampleQueue;
private final SampleQueue[] embeddedSampleQueues; private final SampleQueue[] embeddedSampleQueues;
...@@ -85,7 +86,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -85,7 +86,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
loader = new Loader("Loader:ChunkSampleStream"); loader = new Loader("Loader:ChunkSampleStream");
nextChunkHolder = new ChunkHolder(); nextChunkHolder = new ChunkHolder();
mediaChunks = new LinkedList<>(); mediaChunks = new ArrayList<>();
readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks); readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks);
int embeddedTrackCount = embeddedTrackTypes == null ? 0 : embeddedTrackTypes.length; int embeddedTrackCount = embeddedTrackTypes == null ? 0 : embeddedTrackTypes.length;
...@@ -170,7 +171,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -170,7 +171,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
return pendingResetPositionUs; return pendingResetPositionUs;
} else { } else {
long bufferedPositionUs = lastSeekPositionUs; long bufferedPositionUs = lastSeekPositionUs;
BaseMediaChunk lastMediaChunk = mediaChunks.getLast(); BaseMediaChunk lastMediaChunk = getLastMediaChunk();
BaseMediaChunk lastCompletedMediaChunk = lastMediaChunk.isLoadCompleted() ? lastMediaChunk BaseMediaChunk lastCompletedMediaChunk = lastMediaChunk.isLoadCompleted() ? lastMediaChunk
: mediaChunks.size() > 1 ? mediaChunks.get(mediaChunks.size() - 2) : null; : mediaChunks.size() > 1 ? mediaChunks.get(mediaChunks.size() - 2) : null;
if (lastCompletedMediaChunk != null) { if (lastCompletedMediaChunk != null) {
...@@ -268,9 +269,11 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -268,9 +269,11 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
@Override @Override
public int skipData(long positionUs) { public int skipData(long positionUs) {
if (isPendingReset()) {
return 0;
}
int skipCount; int skipCount;
if (loadingFinished && positionUs > primarySampleQueue.getLargestQueuedTimestampUs()) { if (loadingFinished && positionUs > primarySampleQueue.getLargestQueuedTimestampUs()) {
primarySampleQueue.advanceToEnd();
skipCount = primarySampleQueue.advanceToEnd(); skipCount = primarySampleQueue.advanceToEnd();
} else { } else {
skipCount = primarySampleQueue.advanceTo(positionUs, true, true); skipCount = primarySampleQueue.advanceTo(positionUs, true, true);
...@@ -325,7 +328,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -325,7 +328,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
} else { } else {
canceled = true; canceled = true;
if (isMediaChunk) { if (isMediaChunk) {
BaseMediaChunk removed = mediaChunks.removeLast(); BaseMediaChunk removed = mediaChunks.remove(mediaChunks.size() - 1);
Assertions.checkState(removed == loadable); Assertions.checkState(removed == loadable);
primarySampleQueue.discardUpstreamSamples(removed.getFirstSampleIndex(0)); primarySampleQueue.discardUpstreamSamples(removed.getFirstSampleIndex(0));
for (int i = 0; i < embeddedSampleQueues.length; i++) { for (int i = 0; i < embeddedSampleQueues.length; i++) {
...@@ -363,7 +366,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -363,7 +366,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
previousChunk = null; previousChunk = null;
loadPositionUs = pendingResetPositionUs; loadPositionUs = pendingResetPositionUs;
} else { } else {
previousChunk = mediaChunks.getLast(); previousChunk = getLastMediaChunk();
loadPositionUs = previousChunk.endTimeUs; loadPositionUs = previousChunk.endTimeUs;
} }
chunkSource.getNextChunk(previousChunk, positionUs, loadPositionUs, nextChunkHolder); chunkSource.getNextChunk(previousChunk, positionUs, loadPositionUs, nextChunkHolder);
...@@ -399,7 +402,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -399,7 +402,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
if (isPendingReset()) { if (isPendingReset()) {
return pendingResetPositionUs; return pendingResetPositionUs;
} else { } else {
return loadingFinished ? C.TIME_END_OF_SOURCE : mediaChunks.getLast().endTimeUs; return loadingFinished ? C.TIME_END_OF_SOURCE : getLastMediaChunk().endTimeUs;
} }
} }
...@@ -412,6 +415,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -412,6 +415,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
* *
* @param positionUs The current playback position in microseconds. * @param positionUs The current playback position in microseconds.
*/ */
@SuppressWarnings("unused")
private void maybeDiscardUpstream(long positionUs) { private void maybeDiscardUpstream(long positionUs) {
int queueSize = chunkSource.getPreferredQueueSize(positionUs, readOnlyMediaChunks); int queueSize = chunkSource.getPreferredQueueSize(positionUs, readOnlyMediaChunks);
discardUpstreamMediaChunks(Math.max(1, queueSize)); discardUpstreamMediaChunks(Math.max(1, queueSize));
...@@ -425,7 +429,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -425,7 +429,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
* Returns whether samples have been read from {@code mediaChunks.getLast()}. * Returns whether samples have been read from {@code mediaChunks.getLast()}.
*/ */
private boolean haveReadFromLastMediaChunk() { private boolean haveReadFromLastMediaChunk() {
BaseMediaChunk lastChunk = mediaChunks.getLast(); BaseMediaChunk lastChunk = getLastMediaChunk();
if (primarySampleQueue.getReadIndex() > lastChunk.getFirstSampleIndex(0)) { if (primarySampleQueue.getReadIndex() > lastChunk.getFirstSampleIndex(0)) {
return true; return true;
} }
...@@ -442,33 +446,21 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -442,33 +446,21 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
} }
private void discardDownstreamMediaChunks(int discardToPrimaryStreamIndex) { private void discardDownstreamMediaChunks(int discardToPrimaryStreamIndex) {
if (!mediaChunks.isEmpty()) { int discardToMediaChunkIndex =
while (mediaChunks.size() > 1 primaryStreamIndexToMediaChunkIndex(discardToPrimaryStreamIndex, /* minChunkIndex= */ 0);
&& mediaChunks.get(1).getFirstSampleIndex(0) <= discardToPrimaryStreamIndex) { if (discardToMediaChunkIndex > 0) {
mediaChunks.removeFirst(); Util.removeRange(mediaChunks, /* fromIndex= */ 0, /* toIndex= */ discardToMediaChunkIndex);
}
} }
} }
private void maybeNotifyPrimaryTrackFormatChanged(int toPrimaryStreamReadIndex, int readCount) { private void maybeNotifyPrimaryTrackFormatChanged(int toPrimaryStreamReadIndex, int readCount) {
if (!mediaChunks.isEmpty()) { int fromMediaChunkIndex = primaryStreamIndexToMediaChunkIndex(
int fromPrimaryStreamReadIndex = toPrimaryStreamReadIndex - readCount; toPrimaryStreamReadIndex - readCount, /* minChunkIndex= */ 0);
int fromChunkIndex = 0; int toMediaChunkIndexInclusive = readCount == 1 ? fromMediaChunkIndex
while (fromChunkIndex < mediaChunks.size() - 1 : primaryStreamIndexToMediaChunkIndex(toPrimaryStreamReadIndex - 1,
&& mediaChunks.get(fromChunkIndex + 1).getFirstSampleIndex(0) /* minChunkIndex= */ fromMediaChunkIndex);
<= fromPrimaryStreamReadIndex) { for (int i = fromMediaChunkIndex; i <= toMediaChunkIndexInclusive; i++) {
fromChunkIndex++; maybeNotifyPrimaryTrackFormatChanged(i);
}
int toChunkIndex = fromChunkIndex + 1;
if (readCount > 1) {
while (toChunkIndex < mediaChunks.size()
&& mediaChunks.get(toChunkIndex).getFirstSampleIndex(0) < toPrimaryStreamReadIndex) {
toChunkIndex++;
}
}
for (int i = fromChunkIndex; i < toChunkIndex; i++) {
maybeNotifyPrimaryTrackFormatChanged(i);
}
} }
} }
...@@ -484,6 +476,23 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -484,6 +476,23 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
} }
/** /**
* Returns media chunk index for primary stream sample index. May be -1 if the list of media
* chunks is empty or the requested index is less than the first index in the first media chunk.
*/
private int primaryStreamIndexToMediaChunkIndex(int primaryStreamIndex, int minChunkIndex) {
for (int i = minChunkIndex + 1; i < mediaChunks.size(); i++) {
if (mediaChunks.get(i).getFirstSampleIndex(0) > primaryStreamIndex) {
return i - 1;
}
}
return mediaChunks.size() - 1;
}
private BaseMediaChunk getLastMediaChunk() {
return mediaChunks.get(mediaChunks.size() - 1);
}
/**
* Discard upstream media chunks until the queue length is equal to the length specified. * Discard upstream media chunks until the queue length is equal to the length specified.
* *
* @param queueLength The desired length of the queue. * @param queueLength The desired length of the queue.
...@@ -493,16 +502,14 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -493,16 +502,14 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
if (mediaChunks.size() <= queueLength) { if (mediaChunks.size() <= queueLength) {
return false; return false;
} }
BaseMediaChunk removed;
long startTimeUs; long endTimeUs = getLastMediaChunk().endTimeUs;
long endTimeUs = mediaChunks.getLast().endTimeUs; BaseMediaChunk firstRemovedChunk = mediaChunks.get(queueLength);
do { long startTimeUs = firstRemovedChunk.startTimeUs;
removed = mediaChunks.removeLast(); Util.removeRange(mediaChunks, /* fromIndex= */ queueLength, /* toIndex= */ mediaChunks.size());
startTimeUs = removed.startTimeUs; primarySampleQueue.discardUpstreamSamples(firstRemovedChunk.getFirstSampleIndex(0));
} while (mediaChunks.size() > queueLength);
primarySampleQueue.discardUpstreamSamples(removed.getFirstSampleIndex(0));
for (int i = 0; i < embeddedSampleQueues.length; i++) { for (int i = 0; i < embeddedSampleQueues.length; i++) {
embeddedSampleQueues[i].discardUpstreamSamples(removed.getFirstSampleIndex(i + 1)); embeddedSampleQueues[i].discardUpstreamSamples(firstRemovedChunk.getFirstSampleIndex(i + 1));
} }
loadingFinished = false; loadingFinished = false;
eventDispatcher.upstreamDiscarded(primaryTrackType, startTimeUs, endTimeUs); eventDispatcher.upstreamDiscarded(primaryTrackType, startTimeUs, endTimeUs);
......
...@@ -192,6 +192,17 @@ public final class Util { ...@@ -192,6 +192,17 @@ public final class Util {
} }
/** /**
* Removes an indexed range from a List.
*
* @param list The List to remove the range from.
* @param fromIndex The first index to be removed (inclusive).
* @param toIndex The last index to be removed (exclusive).
*/
public static <T> void removeRange(List<T> list, int fromIndex, int toIndex) {
list.subList(fromIndex, toIndex).clear();
}
/**
* Instantiates a new single threaded executor whose thread has the specified name. * Instantiates a new single threaded executor whose thread has the specified name.
* *
* @param threadName The name of the thread. * @param threadName The name of the thread.
......
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