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;
* May also be configured to expose additional embedded {@link SampleStream}s.
*/
public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, SequenceableLoader,
Loader.Callback<Chunk> {
Loader.Callback<Chunk>, Loader.ReleaseCallback {
private final int primaryTrackType;
private final int[] embeddedTrackTypes;
......@@ -106,17 +106,20 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
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
* specified position.
* Discards buffered media for embedded tracks, up to the specified position.
*
* @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++) {
if (!embeddedTracksSelected[i]) {
embeddedSampleQueues[i].skipToKeyframeBefore(positionUs, true);
}
embeddedSampleQueues[i].discardTo(positionUs, true, embeddedTracksSelected[i]);
}
}
......@@ -135,7 +138,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
if (embeddedTrackTypes[i] == trackType) {
Assertions.checkState(!embeddedTracksSelected[i]);
embeddedTracksSelected[i] = true;
embeddedSampleQueues[i].skipToKeyframeBefore(positionUs, true);
embeddedSampleQueues[i].rewind();
embeddedSampleQueues[i].advanceTo(positionUs, true, true);
return new EmbeddedSampleStream(this, embeddedSampleQueues[i], i);
}
}
......@@ -181,19 +185,15 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
public void seekToUs(long positionUs) {
lastSeekPositionUs = positionUs;
// If we're not pending a reset, see if we can seek within the primary sample queue.
boolean seekInsideBuffer = !isPendingReset() && primarySampleQueue.skipToKeyframeBefore(
positionUs, positionUs < getNextLoadPositionUs());
boolean seekInsideBuffer = !isPendingReset() && primarySampleQueue.advanceTo(positionUs, true,
positionUs < getNextLoadPositionUs());
if (seekInsideBuffer) {
// We succeeded. We need to discard any chunks that we've moved past and perform the seek for
// any embedded streams as well.
while (mediaChunks.size() > 1
&& 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.
// We succeeded. Discard samples and corresponding chunks prior to the seek position.
discardDownstreamMediaChunks(primarySampleQueue.getReadIndex());
primarySampleQueue.discardToRead();
for (SampleQueue embeddedSampleQueue : embeddedSampleQueues) {
embeddedSampleQueue.skipToKeyframeBefore(positionUs, true);
embeddedSampleQueue.rewind();
embeddedSampleQueue.discardTo(positionUs, true, false);
}
} else {
// We failed, and need to restart.
......@@ -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.
*/
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) {
embeddedSampleQueue.disable();
embeddedSampleQueue.reset(true);
}
loader.release();
}
// SampleStream implementation.
......@@ -246,17 +257,22 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
return C.RESULT_NOTHING_READ;
}
discardDownstreamMediaChunks(primarySampleQueue.getReadIndex());
return primarySampleQueue.readData(formatHolder, buffer, formatRequired, loadingFinished,
int result = primarySampleQueue.read(formatHolder, buffer, formatRequired, loadingFinished,
lastSeekPositionUs);
if (result == C.RESULT_BUFFER_READ) {
primarySampleQueue.discardToRead();
}
return result;
}
@Override
public void skipData(long positionUs) {
if (loadingFinished && positionUs > primarySampleQueue.getLargestQueuedTimestampUs()) {
primarySampleQueue.skipAll();
primarySampleQueue.advanceToEnd();
} else {
primarySampleQueue.skipToKeyframeBefore(positionUs, true);
primarySampleQueue.advanceTo(positionUs, true, true);
}
primarySampleQueue.discardToRead();
}
// Loader.Callback implementation.
......@@ -416,18 +432,18 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
if (mediaChunks.size() <= queueLength) {
return false;
}
long startTimeUs = 0;
BaseMediaChunk removed;
long startTimeUs;
long endTimeUs = mediaChunks.getLast().endTimeUs;
BaseMediaChunk removed = null;
while (mediaChunks.size() > queueLength) {
do {
removed = mediaChunks.removeLast();
startTimeUs = removed.startTimeUs;
loadingFinished = false;
}
} while (mediaChunks.size() > queueLength);
primarySampleQueue.discardUpstreamSamples(removed.getFirstSampleIndex(0));
for (int i = 0; i < embeddedSampleQueues.length; i++) {
embeddedSampleQueues[i].discardUpstreamSamples(removed.getFirstSampleIndex(i + 1));
}
loadingFinished = false;
eventDispatcher.upstreamDiscarded(primaryTrackType, startTimeUs, endTimeUs);
return true;
}
......@@ -442,8 +458,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
private final SampleQueue sampleQueue;
private final int index;
public EmbeddedSampleStream(ChunkSampleStream<T> parent, SampleQueue sampleQueue,
int index) {
public EmbeddedSampleStream(ChunkSampleStream<T> parent, SampleQueue sampleQueue, int index) {
this.parent = parent;
this.sampleQueue = sampleQueue;
this.index = index;
......@@ -457,9 +472,9 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
@Override
public void skipData(long positionUs) {
if (loadingFinished && positionUs > sampleQueue.getLargestQueuedTimestampUs()) {
sampleQueue.skipAll();
sampleQueue.advanceToEnd();
} else {
sampleQueue.skipToKeyframeBefore(positionUs, true);
sampleQueue.advanceTo(positionUs, true, true);
}
}
......@@ -474,7 +489,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
if (isPendingReset()) {
return C.RESULT_NOTHING_READ;
}
return sampleQueue.readData(formatHolder, buffer, formatRequired, loadingFinished,
return sampleQueue.read(formatHolder, buffer, formatRequired, loadingFinished,
lastSeekPositionUs);
}
......
......@@ -188,7 +188,7 @@ import java.util.List;
@Override
public void discardBuffer(long positionUs) {
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