Commit c448463a by olly Committed by Oliver Woodman

Move DashMediaSource and SsMediaSource to new SampleQueue methods

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=160130540
parent 1b71e3b4
...@@ -36,7 +36,7 @@ import java.util.List; ...@@ -36,7 +36,7 @@ import java.util.List;
* May also be configured to expose additional embedded {@link SampleStream}s. * May also be configured to expose additional embedded {@link SampleStream}s.
*/ */
public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, SequenceableLoader, public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, SequenceableLoader,
Loader.Callback<Chunk> { Loader.Callback<Chunk>, Loader.ReleaseCallback {
private final int primaryTrackType; private final int primaryTrackType;
private final int[] embeddedTrackTypes; private final int[] embeddedTrackTypes;
...@@ -106,17 +106,20 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -106,17 +106,20 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
lastSeekPositionUs = positionUs; lastSeekPositionUs = positionUs;
} }
// TODO: Generalize this method to also discard from the primary sample queue and stop discarding
// from this queue in readData and skipData. This will cause samples to be kept in the queue until
// they've been rendered, rather than being discarded as soon as they're read by the renderer.
// This will make in-buffer seeks more likely when seeking slightly forward from the current
// position. This change will need handling with care, in particular when considering removal of
// chunks from the front of the mediaChunks list.
/** /**
* Discards buffered media for embedded tracks that are not currently selected, up to the * Discards buffered media for embedded tracks, up to the specified position.
* specified position.
* *
* @param positionUs The position to discard up to, in microseconds. * @param positionUs The position to discard up to, in microseconds.
*/ */
public void discardUnselectedEmbeddedTracksTo(long positionUs) { public void discardEmbeddedTracksTo(long positionUs) {
for (int i = 0; i < embeddedSampleQueues.length; i++) { for (int i = 0; i < embeddedSampleQueues.length; i++) {
if (!embeddedTracksSelected[i]) { embeddedSampleQueues[i].discardTo(positionUs, true, embeddedTracksSelected[i]);
embeddedSampleQueues[i].skipToKeyframeBefore(positionUs, true);
}
} }
} }
...@@ -135,7 +138,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -135,7 +138,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
if (embeddedTrackTypes[i] == trackType) { if (embeddedTrackTypes[i] == trackType) {
Assertions.checkState(!embeddedTracksSelected[i]); Assertions.checkState(!embeddedTracksSelected[i]);
embeddedTracksSelected[i] = true; embeddedTracksSelected[i] = true;
embeddedSampleQueues[i].skipToKeyframeBefore(positionUs, true); embeddedSampleQueues[i].rewind();
embeddedSampleQueues[i].advanceTo(positionUs, true, true);
return new EmbeddedSampleStream(this, embeddedSampleQueues[i], i); return new EmbeddedSampleStream(this, embeddedSampleQueues[i], i);
} }
} }
...@@ -181,19 +185,15 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -181,19 +185,15 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
public void seekToUs(long positionUs) { public void seekToUs(long positionUs) {
lastSeekPositionUs = positionUs; lastSeekPositionUs = positionUs;
// If we're not pending a reset, see if we can seek within the primary sample queue. // If we're not pending a reset, see if we can seek within the primary sample queue.
boolean seekInsideBuffer = !isPendingReset() && primarySampleQueue.skipToKeyframeBefore( boolean seekInsideBuffer = !isPendingReset() && primarySampleQueue.advanceTo(positionUs, true,
positionUs, positionUs < getNextLoadPositionUs()); positionUs < getNextLoadPositionUs());
if (seekInsideBuffer) { if (seekInsideBuffer) {
// We succeeded. We need to discard any chunks that we've moved past and perform the seek for // We succeeded. Discard samples and corresponding chunks prior to the seek position.
// any embedded streams as well. discardDownstreamMediaChunks(primarySampleQueue.getReadIndex());
while (mediaChunks.size() > 1 primarySampleQueue.discardToRead();
&& mediaChunks.get(1).getFirstSampleIndex(0) <= primarySampleQueue.getReadIndex()) {
mediaChunks.removeFirst();
}
// TODO: For this to work correctly, the embedded streams must not discard anything from their
// sample queues beyond the current read position of the primary stream.
for (SampleQueue embeddedSampleQueue : embeddedSampleQueues) { for (SampleQueue embeddedSampleQueue : embeddedSampleQueues) {
embeddedSampleQueue.skipToKeyframeBefore(positionUs, true); embeddedSampleQueue.rewind();
embeddedSampleQueue.discardTo(positionUs, true, false);
} }
} else { } else {
// We failed, and need to restart. // We failed, and need to restart.
...@@ -217,11 +217,22 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -217,11 +217,22 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
* This method should be called when the stream is no longer required. * This method should be called when the stream is no longer required.
*/ */
public void release() { public void release() {
primarySampleQueue.disable(); boolean releasedSynchronously = loader.release(this);
if (!releasedSynchronously) {
// Discard as much as we can synchronously.
primarySampleQueue.discardToEnd();
for (SampleQueue embeddedSampleQueue : embeddedSampleQueues) {
embeddedSampleQueue.discardToEnd();
}
}
}
@Override
public void onLoaderReleased() {
primarySampleQueue.reset(true);
for (SampleQueue embeddedSampleQueue : embeddedSampleQueues) { for (SampleQueue embeddedSampleQueue : embeddedSampleQueues) {
embeddedSampleQueue.disable(); embeddedSampleQueue.reset(true);
} }
loader.release();
} }
// SampleStream implementation. // SampleStream implementation.
...@@ -246,17 +257,22 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -246,17 +257,22 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
return C.RESULT_NOTHING_READ; return C.RESULT_NOTHING_READ;
} }
discardDownstreamMediaChunks(primarySampleQueue.getReadIndex()); discardDownstreamMediaChunks(primarySampleQueue.getReadIndex());
return primarySampleQueue.readData(formatHolder, buffer, formatRequired, loadingFinished, int result = primarySampleQueue.read(formatHolder, buffer, formatRequired, loadingFinished,
lastSeekPositionUs); lastSeekPositionUs);
if (result == C.RESULT_BUFFER_READ) {
primarySampleQueue.discardToRead();
}
return result;
} }
@Override @Override
public void skipData(long positionUs) { public void skipData(long positionUs) {
if (loadingFinished && positionUs > primarySampleQueue.getLargestQueuedTimestampUs()) { if (loadingFinished && positionUs > primarySampleQueue.getLargestQueuedTimestampUs()) {
primarySampleQueue.skipAll(); primarySampleQueue.advanceToEnd();
} else { } else {
primarySampleQueue.skipToKeyframeBefore(positionUs, true); primarySampleQueue.advanceTo(positionUs, true, true);
} }
primarySampleQueue.discardToRead();
} }
// Loader.Callback implementation. // Loader.Callback implementation.
...@@ -416,18 +432,18 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -416,18 +432,18 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
if (mediaChunks.size() <= queueLength) { if (mediaChunks.size() <= queueLength) {
return false; return false;
} }
long startTimeUs = 0; BaseMediaChunk removed;
long startTimeUs;
long endTimeUs = mediaChunks.getLast().endTimeUs; long endTimeUs = mediaChunks.getLast().endTimeUs;
BaseMediaChunk removed = null; do {
while (mediaChunks.size() > queueLength) {
removed = mediaChunks.removeLast(); removed = mediaChunks.removeLast();
startTimeUs = removed.startTimeUs; startTimeUs = removed.startTimeUs;
loadingFinished = false; } while (mediaChunks.size() > queueLength);
}
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++) {
embeddedSampleQueues[i].discardUpstreamSamples(removed.getFirstSampleIndex(i + 1)); embeddedSampleQueues[i].discardUpstreamSamples(removed.getFirstSampleIndex(i + 1));
} }
loadingFinished = false;
eventDispatcher.upstreamDiscarded(primaryTrackType, startTimeUs, endTimeUs); eventDispatcher.upstreamDiscarded(primaryTrackType, startTimeUs, endTimeUs);
return true; return true;
} }
...@@ -442,8 +458,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -442,8 +458,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
private final SampleQueue sampleQueue; private final SampleQueue sampleQueue;
private final int index; private final int index;
public EmbeddedSampleStream(ChunkSampleStream<T> parent, SampleQueue sampleQueue, public EmbeddedSampleStream(ChunkSampleStream<T> parent, SampleQueue sampleQueue, int index) {
int index) {
this.parent = parent; this.parent = parent;
this.sampleQueue = sampleQueue; this.sampleQueue = sampleQueue;
this.index = index; this.index = index;
...@@ -457,9 +472,9 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -457,9 +472,9 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
@Override @Override
public void skipData(long positionUs) { public void skipData(long positionUs) {
if (loadingFinished && positionUs > sampleQueue.getLargestQueuedTimestampUs()) { if (loadingFinished && positionUs > sampleQueue.getLargestQueuedTimestampUs()) {
sampleQueue.skipAll(); sampleQueue.advanceToEnd();
} else { } else {
sampleQueue.skipToKeyframeBefore(positionUs, true); sampleQueue.advanceTo(positionUs, true, true);
} }
} }
...@@ -474,7 +489,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -474,7 +489,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
if (isPendingReset()) { if (isPendingReset()) {
return C.RESULT_NOTHING_READ; return C.RESULT_NOTHING_READ;
} }
return sampleQueue.readData(formatHolder, buffer, formatRequired, loadingFinished, return sampleQueue.read(formatHolder, buffer, formatRequired, loadingFinished,
lastSeekPositionUs); lastSeekPositionUs);
} }
......
...@@ -188,7 +188,7 @@ import java.util.List; ...@@ -188,7 +188,7 @@ import java.util.List;
@Override @Override
public void discardBuffer(long positionUs) { public void discardBuffer(long positionUs) {
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) { for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
sampleStream.discardUnselectedEmbeddedTracksTo(positionUs); sampleStream.discardEmbeddedTracksTo(positionUs);
} }
} }
......
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