From c8af6d176f93368372852f2dd425cd6f11b15150 Mon Sep 17 00:00:00 2001 From: tonihei Date: Mon, 2 Jul 2018 08:31:21 -0700 Subject: [PATCH] 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 --- .../source/chunk/ChunkSampleStream.java | 10 +++++----- .../exoplayer2/source/chunk/ChunkSource.java | 15 +++++++++------ .../source/dash/DefaultDashChunkSource.java | 11 +++++++---- .../exoplayer2/source/hls/HlsChunkSource.java | 10 ++++++---- .../source/hls/HlsSampleStreamWrapper.java | 14 +++++++++----- .../smoothstreaming/DefaultSsChunkSource.java | 12 ++++++++---- .../exoplayer2/testutil/FakeChunkSource.java | 9 ++++++--- 7 files changed, 50 insertions(+), 31 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java index 325a75ea28..b71b236c4f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java @@ -486,16 +486,16 @@ public class ChunkSampleStream implements SampleStream, S } boolean pendingReset = isPendingReset(); - MediaChunk previousChunk; + List chunkQueue; long loadPositionUs; if (pendingReset) { - previousChunk = null; + chunkQueue = Collections.emptyList(); loadPositionUs = pendingResetPositionUs; } else { - previousChunk = getLastMediaChunk(); - loadPositionUs = previousChunk.endTimeUs; + chunkQueue = readOnlyMediaChunks; + loadPositionUs = getLastMediaChunk().endTimeUs; } - chunkSource.getNextChunk(previousChunk, positionUs, loadPositionUs, nextChunkHolder); + chunkSource.getNextChunk(positionUs, loadPositionUs, chunkQueue, nextChunkHolder); boolean endOfStream = nextChunkHolder.endOfStream; Chunk loadable = nextChunkHolder.chunk; nextChunkHolder.clear(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSource.java index 568461c206..be45138bd9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSource.java @@ -59,22 +59,25 @@ public interface ChunkSource { /** * Returns the next chunk to load. - *

- * If a chunk is available then {@link ChunkHolder#chunk} is set. If the end of the stream has + * + *

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 * 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 * 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 * 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 - * {@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. */ - void getNextChunk(MediaChunk previous, long playbackPositionUs, long loadPositionUs, + void getNextChunk( + long playbackPositionUs, + long loadPositionUs, + List queue, ChunkHolder out); /** diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java index 54c40722b3..41be4eb2f1 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java @@ -238,7 +238,10 @@ public class DefaultDashChunkSource implements DashChunkSource { } @Override - public void getNextChunk(MediaChunk previous, long playbackPositionUs, long loadPositionUs, + public void getNextChunk( + long playbackPositionUs, + long loadPositionUs, + List queue, ChunkHolder out) { if (fatalError != null) { return; @@ -311,11 +314,11 @@ public class DefaultDashChunkSource implements DashChunkSource { updateLiveEdgeTimeUs(representationHolder, lastAvailableSegmentNum); long segmentNum; - if (previous == null) { + if (queue.isEmpty()) { segmentNum = Util.constrainValue(representationHolder.getSegmentNum(loadPositionUs), firstAvailableSegmentNum, lastAvailableSegmentNum); } else { - segmentNum = previous.getNextChunkIndex(); + segmentNum = queue.get(queue.size() - 1).getNextChunkIndex(); if (segmentNum < firstAvailableSegmentNum) { // This is before the first chunk in the current manifest. fatalError = new BehindLiveWindowException(); @@ -332,7 +335,7 @@ public class DefaultDashChunkSource implements DashChunkSource { int maxSegmentCount = (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 = newMediaChunk( representationHolder, diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java index 4a8509d8ac..fd74657e2e 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java @@ -204,18 +204,20 @@ import java.util.List; * 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. * - * @param previous The most recently loaded media chunk. * @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 * started, the value will be the starting position in the period minus the duration of any * media in previous periods still to be played. * @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 - * provided. Else it's equal to {@code previous.endTimeUs}. + * If {@code queue} is empty, this is the starting position from which chunks should be + * 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. */ public void getNextChunk( - HlsMediaChunk previous, long playbackPositionUs, long loadPositionUs, HlsChunkHolder out) { + long playbackPositionUs, long loadPositionUs, List queue, HlsChunkHolder out) { + HlsMediaChunk previous = queue.isEmpty() ? null : queue.get(queue.size() - 1); int oldVariantIndex = previous == null ? C.INDEX_UNSET : trackGroup.indexOf(previous.trackFormat); long bufferedDurationUs = loadPositionUs - playbackPositionUs; diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java index 13f44aa3dd..01def14006 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java @@ -49,6 +49,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.List; /** * 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 HlsChunkSource.HlsChunkHolder nextChunkHolder; private final ArrayList mediaChunks; + private final List readOnlyMediaChunks; private final Runnable maybeFinishPrepareRunnable; private final Runnable onTracksEndedRunnable; private final Handler handler; @@ -168,6 +171,7 @@ import java.util.Arrays; sampleQueueIsAudioVideoFlags = new boolean[0]; sampleQueuesEnabledStates = new boolean[0]; mediaChunks = new ArrayList<>(); + readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks); hlsSampleStreams = new ArrayList<>(); maybeFinishPrepareRunnable = new Runnable() { @@ -527,16 +531,16 @@ import java.util.Arrays; return false; } - HlsMediaChunk previousChunk; + List chunkQueue; long loadPositionUs; if (isPendingReset()) { - previousChunk = null; + chunkQueue = Collections.emptyList(); loadPositionUs = pendingResetPositionUs; } else { - previousChunk = getLastMediaChunk(); - loadPositionUs = previousChunk.endTimeUs; + chunkQueue = readOnlyMediaChunks; + loadPositionUs = getLastMediaChunk().endTimeUs; } - chunkSource.getNextChunk(previousChunk, positionUs, loadPositionUs, nextChunkHolder); + chunkSource.getNextChunk(positionUs, loadPositionUs, chunkQueue, nextChunkHolder); boolean endOfStream = nextChunkHolder.endOfStream; Chunk loadable = nextChunkHolder.chunk; HlsMasterPlaylist.HlsUrl playlistToLoad = nextChunkHolder.playlist; diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java index de236c3514..20704346a1 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java @@ -166,7 +166,10 @@ public class DefaultSsChunkSource implements SsChunkSource { } @Override - public final void getNextChunk(MediaChunk previous, long playbackPositionUs, long loadPositionUs, + public final void getNextChunk( + long playbackPositionUs, + long loadPositionUs, + List queue, ChunkHolder out) { if (fatalError != null) { return; @@ -180,10 +183,11 @@ public class DefaultSsChunkSource implements SsChunkSource { } int chunkIndex; - if (previous == null) { + if (queue.isEmpty()) { chunkIndex = streamElement.getChunkIndex(loadPositionUs); } else { - chunkIndex = (int) (previous.getNextChunkIndex() - currentManifestChunkOffset); + chunkIndex = + (int) (queue.get(queue.size() - 1).getNextChunkIndex() - currentManifestChunkOffset); if (chunkIndex < 0) { // This is before the first chunk in the current manifest. fatalError = new BehindLiveWindowException(); @@ -203,7 +207,7 @@ public class DefaultSsChunkSource implements SsChunkSource { long chunkStartTimeUs = streamElement.getStartTimeUs(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 trackSelectionIndex = trackSelection.getSelectedIndex(); diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeChunkSource.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeChunkSource.java index 9234287e92..d0ee501fbd 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeChunkSource.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeChunkSource.java @@ -95,14 +95,17 @@ public final class FakeChunkSource implements ChunkSource { } @Override - public void getNextChunk(MediaChunk previous, long playbackPositionUs, long loadPositionUs, + public void getNextChunk( + long playbackPositionUs, + long loadPositionUs, + List queue, ChunkHolder out) { long bufferedDurationUs = loadPositionUs - playbackPositionUs; trackSelection.updateSelectedTrack(playbackPositionUs, bufferedDurationUs, C.TIME_UNSET); int chunkIndex = - previous == null + queue.isEmpty() ? dataSet.getChunkIndexByPosition(playbackPositionUs) - : (int) previous.getNextChunkIndex(); + : (int) queue.get(queue.size() - 1).getNextChunkIndex(); if (chunkIndex >= dataSet.getChunkCount()) { out.endOfStream = true; } else {