Forward queue of media chunks to getNextChunk.

This allows to use this queue in the track selection in the future.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=202954871
This commit is contained in:
tonihei 2018-07-02 08:31:21 -07:00 committed by Oliver Woodman
parent 04341394a3
commit c8af6d176f
7 changed files with 50 additions and 31 deletions

View File

@ -486,16 +486,16 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
} }
boolean pendingReset = isPendingReset(); boolean pendingReset = isPendingReset();
MediaChunk previousChunk; List<BaseMediaChunk> chunkQueue;
long loadPositionUs; long loadPositionUs;
if (pendingReset) { if (pendingReset) {
previousChunk = null; chunkQueue = Collections.emptyList();
loadPositionUs = pendingResetPositionUs; loadPositionUs = pendingResetPositionUs;
} else { } else {
previousChunk = getLastMediaChunk(); chunkQueue = readOnlyMediaChunks;
loadPositionUs = previousChunk.endTimeUs; loadPositionUs = getLastMediaChunk().endTimeUs;
} }
chunkSource.getNextChunk(previousChunk, positionUs, loadPositionUs, nextChunkHolder); chunkSource.getNextChunk(positionUs, loadPositionUs, chunkQueue, nextChunkHolder);
boolean endOfStream = nextChunkHolder.endOfStream; boolean endOfStream = nextChunkHolder.endOfStream;
Chunk loadable = nextChunkHolder.chunk; Chunk loadable = nextChunkHolder.chunk;
nextChunkHolder.clear(); nextChunkHolder.clear();

View File

@ -59,22 +59,25 @@ public interface ChunkSource {
/** /**
* Returns the next chunk to load. * Returns the next chunk to load.
* <p> *
* If a chunk is available then {@link ChunkHolder#chunk} is set. If the end of the stream has * <p>If a chunk is available then {@link ChunkHolder#chunk} is set. If the end of the stream has
* been reached then {@link ChunkHolder#endOfStream} is set. If a chunk is not available but the * been reached then {@link ChunkHolder#endOfStream} is set. If a chunk is not available but the
* end of the stream has not been reached, the {@link ChunkHolder} is not modified. * end of the stream has not been reached, the {@link ChunkHolder} is not modified.
* *
* @param previous The most recently loaded media chunk.
* @param playbackPositionUs The current playback position in microseconds. If playback of the * @param playbackPositionUs The current playback position in microseconds. If playback of the
* period to which this chunk source belongs has not yet started, the value will be the * period to which this chunk source belongs has not yet started, the value will be the
* starting position in the period minus the duration of any media in previous periods still * starting position in the period minus the duration of any media in previous periods still
* to be played. * to be played.
* @param loadPositionUs The current load position in microseconds. If {@code previous} is null, * @param loadPositionUs The current load position in microseconds. If {@code queue} is empty,
* this is the starting position from which chunks should be provided. Else it's equal to * this is the starting position from which chunks should be provided. Else it's equal to
* {@code previous.endTimeUs}. * {@link MediaChunk#endTimeUs} of the last chunk in the {@code queue}.
* @param queue The queue of buffered {@link MediaChunk}s.
* @param out A holder to populate. * @param out A holder to populate.
*/ */
void getNextChunk(MediaChunk previous, long playbackPositionUs, long loadPositionUs, void getNextChunk(
long playbackPositionUs,
long loadPositionUs,
List<? extends MediaChunk> queue,
ChunkHolder out); ChunkHolder out);
/** /**

View File

@ -238,7 +238,10 @@ public class DefaultDashChunkSource implements DashChunkSource {
} }
@Override @Override
public void getNextChunk(MediaChunk previous, long playbackPositionUs, long loadPositionUs, public void getNextChunk(
long playbackPositionUs,
long loadPositionUs,
List<? extends MediaChunk> queue,
ChunkHolder out) { ChunkHolder out) {
if (fatalError != null) { if (fatalError != null) {
return; return;
@ -311,11 +314,11 @@ public class DefaultDashChunkSource implements DashChunkSource {
updateLiveEdgeTimeUs(representationHolder, lastAvailableSegmentNum); updateLiveEdgeTimeUs(representationHolder, lastAvailableSegmentNum);
long segmentNum; long segmentNum;
if (previous == null) { if (queue.isEmpty()) {
segmentNum = Util.constrainValue(representationHolder.getSegmentNum(loadPositionUs), segmentNum = Util.constrainValue(representationHolder.getSegmentNum(loadPositionUs),
firstAvailableSegmentNum, lastAvailableSegmentNum); firstAvailableSegmentNum, lastAvailableSegmentNum);
} else { } else {
segmentNum = previous.getNextChunkIndex(); segmentNum = queue.get(queue.size() - 1).getNextChunkIndex();
if (segmentNum < firstAvailableSegmentNum) { if (segmentNum < firstAvailableSegmentNum) {
// This is before the first chunk in the current manifest. // This is before the first chunk in the current manifest.
fatalError = new BehindLiveWindowException(); fatalError = new BehindLiveWindowException();
@ -332,7 +335,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
int maxSegmentCount = int maxSegmentCount =
(int) Math.min(maxSegmentsPerLoad, lastAvailableSegmentNum - segmentNum + 1); (int) Math.min(maxSegmentsPerLoad, lastAvailableSegmentNum - segmentNum + 1);
long seekTimeUs = previous == null ? loadPositionUs : C.TIME_UNSET; long seekTimeUs = queue.isEmpty() ? loadPositionUs : C.TIME_UNSET;
out.chunk = out.chunk =
newMediaChunk( newMediaChunk(
representationHolder, representationHolder,

View File

@ -204,18 +204,20 @@ import java.util.List;
* but the end of the stream has not been reached, {@link HlsChunkHolder#playlist} is set to * but the end of the stream has not been reached, {@link HlsChunkHolder#playlist} is set to
* contain the {@link HlsUrl} that refers to the playlist that needs refreshing. * contain the {@link HlsUrl} that refers to the playlist that needs refreshing.
* *
* @param previous The most recently loaded media chunk.
* @param playbackPositionUs The current playback position relative to the period start in * @param playbackPositionUs The current playback position relative to the period start in
* microseconds. If playback of the period to which this chunk source belongs has not yet * microseconds. If playback of the period to which this chunk source belongs has not yet
* started, the value will be the starting position in the period minus the duration of any * started, the value will be the starting position in the period minus the duration of any
* media in previous periods still to be played. * media in previous periods still to be played.
* @param loadPositionUs The current load position relative to the period start in microseconds. * @param loadPositionUs The current load position relative to the period start in microseconds.
* If {@code previous} is null, this is the starting position from which chunks should be * If {@code queue} is empty, this is the starting position from which chunks should be
* provided. Else it's equal to {@code previous.endTimeUs}. * provided. Else it's equal to {@link HlsMediaChunk#endTimeUs} of the last chunk in the
* {@code queue}.
* @param queue The queue of buffered {@link HlsMediaChunk}s.
* @param out A holder to populate. * @param out A holder to populate.
*/ */
public void getNextChunk( public void getNextChunk(
HlsMediaChunk previous, long playbackPositionUs, long loadPositionUs, HlsChunkHolder out) { long playbackPositionUs, long loadPositionUs, List<HlsMediaChunk> queue, HlsChunkHolder out) {
HlsMediaChunk previous = queue.isEmpty() ? null : queue.get(queue.size() - 1);
int oldVariantIndex = previous == null ? C.INDEX_UNSET int oldVariantIndex = previous == null ? C.INDEX_UNSET
: trackGroup.indexOf(previous.trackFormat); : trackGroup.indexOf(previous.trackFormat);
long bufferedDurationUs = loadPositionUs - playbackPositionUs; long bufferedDurationUs = loadPositionUs - playbackPositionUs;

View File

@ -49,6 +49,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/** /**
* Loads {@link HlsMediaChunk}s obtained from a {@link HlsChunkSource}, and provides * Loads {@link HlsMediaChunk}s obtained from a {@link HlsChunkSource}, and provides
@ -100,6 +102,7 @@ import java.util.Arrays;
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
private final HlsChunkSource.HlsChunkHolder nextChunkHolder; private final HlsChunkSource.HlsChunkHolder nextChunkHolder;
private final ArrayList<HlsMediaChunk> mediaChunks; private final ArrayList<HlsMediaChunk> mediaChunks;
private final List<HlsMediaChunk> readOnlyMediaChunks;
private final Runnable maybeFinishPrepareRunnable; private final Runnable maybeFinishPrepareRunnable;
private final Runnable onTracksEndedRunnable; private final Runnable onTracksEndedRunnable;
private final Handler handler; private final Handler handler;
@ -168,6 +171,7 @@ import java.util.Arrays;
sampleQueueIsAudioVideoFlags = new boolean[0]; sampleQueueIsAudioVideoFlags = new boolean[0];
sampleQueuesEnabledStates = new boolean[0]; sampleQueuesEnabledStates = new boolean[0];
mediaChunks = new ArrayList<>(); mediaChunks = new ArrayList<>();
readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks);
hlsSampleStreams = new ArrayList<>(); hlsSampleStreams = new ArrayList<>();
maybeFinishPrepareRunnable = maybeFinishPrepareRunnable =
new Runnable() { new Runnable() {
@ -527,16 +531,16 @@ import java.util.Arrays;
return false; return false;
} }
HlsMediaChunk previousChunk; List<HlsMediaChunk> chunkQueue;
long loadPositionUs; long loadPositionUs;
if (isPendingReset()) { if (isPendingReset()) {
previousChunk = null; chunkQueue = Collections.emptyList();
loadPositionUs = pendingResetPositionUs; loadPositionUs = pendingResetPositionUs;
} else { } else {
previousChunk = getLastMediaChunk(); chunkQueue = readOnlyMediaChunks;
loadPositionUs = previousChunk.endTimeUs; loadPositionUs = getLastMediaChunk().endTimeUs;
} }
chunkSource.getNextChunk(previousChunk, positionUs, loadPositionUs, nextChunkHolder); chunkSource.getNextChunk(positionUs, loadPositionUs, chunkQueue, nextChunkHolder);
boolean endOfStream = nextChunkHolder.endOfStream; boolean endOfStream = nextChunkHolder.endOfStream;
Chunk loadable = nextChunkHolder.chunk; Chunk loadable = nextChunkHolder.chunk;
HlsMasterPlaylist.HlsUrl playlistToLoad = nextChunkHolder.playlist; HlsMasterPlaylist.HlsUrl playlistToLoad = nextChunkHolder.playlist;

View File

@ -166,7 +166,10 @@ public class DefaultSsChunkSource implements SsChunkSource {
} }
@Override @Override
public final void getNextChunk(MediaChunk previous, long playbackPositionUs, long loadPositionUs, public final void getNextChunk(
long playbackPositionUs,
long loadPositionUs,
List<? extends MediaChunk> queue,
ChunkHolder out) { ChunkHolder out) {
if (fatalError != null) { if (fatalError != null) {
return; return;
@ -180,10 +183,11 @@ public class DefaultSsChunkSource implements SsChunkSource {
} }
int chunkIndex; int chunkIndex;
if (previous == null) { if (queue.isEmpty()) {
chunkIndex = streamElement.getChunkIndex(loadPositionUs); chunkIndex = streamElement.getChunkIndex(loadPositionUs);
} else { } else {
chunkIndex = (int) (previous.getNextChunkIndex() - currentManifestChunkOffset); chunkIndex =
(int) (queue.get(queue.size() - 1).getNextChunkIndex() - currentManifestChunkOffset);
if (chunkIndex < 0) { if (chunkIndex < 0) {
// This is before the first chunk in the current manifest. // This is before the first chunk in the current manifest.
fatalError = new BehindLiveWindowException(); fatalError = new BehindLiveWindowException();
@ -203,7 +207,7 @@ public class DefaultSsChunkSource implements SsChunkSource {
long chunkStartTimeUs = streamElement.getStartTimeUs(chunkIndex); long chunkStartTimeUs = streamElement.getStartTimeUs(chunkIndex);
long chunkEndTimeUs = chunkStartTimeUs + streamElement.getChunkDurationUs(chunkIndex); long chunkEndTimeUs = chunkStartTimeUs + streamElement.getChunkDurationUs(chunkIndex);
long chunkSeekTimeUs = previous == null ? loadPositionUs : C.TIME_UNSET; long chunkSeekTimeUs = queue.isEmpty() ? loadPositionUs : C.TIME_UNSET;
int currentAbsoluteChunkIndex = chunkIndex + currentManifestChunkOffset; int currentAbsoluteChunkIndex = chunkIndex + currentManifestChunkOffset;
int trackSelectionIndex = trackSelection.getSelectedIndex(); int trackSelectionIndex = trackSelection.getSelectedIndex();

View File

@ -95,14 +95,17 @@ public final class FakeChunkSource implements ChunkSource {
} }
@Override @Override
public void getNextChunk(MediaChunk previous, long playbackPositionUs, long loadPositionUs, public void getNextChunk(
long playbackPositionUs,
long loadPositionUs,
List<? extends MediaChunk> queue,
ChunkHolder out) { ChunkHolder out) {
long bufferedDurationUs = loadPositionUs - playbackPositionUs; long bufferedDurationUs = loadPositionUs - playbackPositionUs;
trackSelection.updateSelectedTrack(playbackPositionUs, bufferedDurationUs, C.TIME_UNSET); trackSelection.updateSelectedTrack(playbackPositionUs, bufferedDurationUs, C.TIME_UNSET);
int chunkIndex = int chunkIndex =
previous == null queue.isEmpty()
? dataSet.getChunkIndexByPosition(playbackPositionUs) ? dataSet.getChunkIndexByPosition(playbackPositionUs)
: (int) previous.getNextChunkIndex(); : (int) queue.get(queue.size() - 1).getNextChunkIndex();
if (chunkIndex >= dataSet.getChunkCount()) { if (chunkIndex >= dataSet.getChunkCount()) {
out.endOfStream = true; out.endOfStream = true;
} else { } else {