diff --git a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index 11e2b1f86a..127f9886e1 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -727,8 +727,13 @@ import java.io.IOException; // Update streams for the new selection, recreating all streams if reading ahead. boolean recreateStreams = readingPeriod != playingPeriod; - boolean[] streamResetFlags = playingPeriod.updatePeriodTrackSelection(playbackInfo.positionUs, - loadControl, recreateStreams); + boolean[] streamResetFlags = new boolean[renderers.length]; + long positionUs = playingPeriod.updatePeriodTrackSelection(playbackInfo.positionUs, + loadControl, recreateStreams, streamResetFlags); + if (positionUs != playbackInfo.positionUs) { + playbackInfo.positionUs = positionUs; + resetInternalPosition(positionUs); + } int enabledRendererCount = 0; boolean[] rendererWasEnabledFlags = new boolean[renderers.length]; @@ -1156,12 +1161,12 @@ import java.io.IOException; public final MediaPeriod mediaPeriod; public final Object id; - public final long startPositionUs; public final SampleStream[] sampleStreams; public final boolean[] mayRetainStreamFlags; public int index; + public long startPositionUs; public boolean isLast; public boolean prepared; public boolean hasEnabledTracks; @@ -1205,7 +1210,7 @@ import java.io.IOException; throws ExoPlaybackException { prepared = true; selectTracks(); - updatePeriodTrackSelection(positionUs, loadControl, false); + startPositionUs = updatePeriodTrackSelection(positionUs, loadControl, false); } public boolean selectTracks() throws ExoPlaybackException { @@ -1220,19 +1225,23 @@ import java.io.IOException; return true; } - public boolean[] updatePeriodTrackSelection(long positionUs, LoadControl loadControl, + public long updatePeriodTrackSelection(long positionUs, LoadControl loadControl, boolean forceRecreateStreams) throws ExoPlaybackException { + return updatePeriodTrackSelection(positionUs, loadControl, forceRecreateStreams, + new boolean[renderers.length]); + } + + public long updatePeriodTrackSelection(long positionUs, LoadControl loadControl, + boolean forceRecreateStreams, boolean[] streamResetFlags) throws ExoPlaybackException { for (int i = 0; i < trackSelections.length; i++) { mayRetainStreamFlags[i] = !forceRecreateStreams && Util.areEqual(periodTrackSelections == null ? null : periodTrackSelections.get(i), trackSelections.get(i)); } - boolean[] streamResetFlags = new boolean[renderers.length]; - // Disable streams on the period and get new streams for updated/newly-enabled tracks. - mediaPeriod.selectTracks(trackSelections.getAll(), mayRetainStreamFlags, sampleStreams, - streamResetFlags, positionUs); + positionUs = mediaPeriod.selectTracks(trackSelections.getAll(), mayRetainStreamFlags, + sampleStreams, streamResetFlags, positionUs); periodTrackSelections = trackSelections; hasEnabledTracks = false; @@ -1245,8 +1254,7 @@ import java.io.IOException; // The track selection has changed. loadControl.onTrackSelections(renderers, mediaPeriod.getTrackGroups(), trackSelections); - - return streamResetFlags; + return positionUs; } public void release() { diff --git a/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java index 5cf72e64dc..df9a6c9ce8 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java @@ -239,7 +239,7 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource, } @Override - public void selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, + public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { Assertions.checkState(prepared); // Disable old tracks. @@ -284,7 +284,7 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource, loader.cancelLoading(); } } else if (seenFirstTrackSelection ? selectedNewTracks : positionUs != 0) { - seekToUs(positionUs); + positionUs = seekToUs(positionUs); // We'll need to reset renderers consuming from all streams due to the seek. for (int i = 0; i < streams.length; i++) { if (streams[i] != null) { @@ -293,6 +293,7 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource, } } seenFirstTrackSelection = true; + return positionUs; } @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java index 87b78ec0d8..422725bc8f 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java @@ -110,8 +110,9 @@ public interface MediaPeriod extends SequenceableLoader { * @param streamResetFlags Will be updated to indicate new sample streams, and sample streams that * have been retained but with the requirement that the consuming renderer be reset. * @param positionUs The current playback position in microseconds. + * @return The actual position at which the tracks were enabled, in microseconds. */ - void selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, + long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs); /** diff --git a/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java index 6e499e9c77..5ba321dd54 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java @@ -70,7 +70,7 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba } @Override - public void selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, + public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { // Map each selection and stream onto a child period index. int[] streamChildIndices = new int[selections.length]; @@ -98,8 +98,13 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba childStreams[j] = streamChildIndices[j] == i ? streams[j] : null; childSelections[j] = selectionChildIndices[j] == i ? selections[j] : null; } - periods[i].selectTracks(childSelections, mayRetainStreamFlags, childStreams, streamResetFlags, - positionUs); + long selectPositionUs = periods[i].selectTracks(childSelections, mayRetainStreamFlags, + childStreams, streamResetFlags, positionUs); + if (i == 0) { + positionUs = selectPositionUs; + } else if (selectPositionUs != positionUs) { + throw new IllegalStateException("Children enabled at different positions"); + } boolean periodEnabled = false; for (int j = 0; j < selections.length; j++) { if (selectionChildIndices[j] == i) { @@ -118,6 +123,7 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba enabledPeriods = new MediaPeriod[enabledPeriodsList.size()]; enabledPeriodsList.toArray(enabledPeriods); sequenceableLoader = new CompositeSequenceableLoader(enabledPeriods); + return positionUs; } @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java index 2d919abb70..1f1d0c51db 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java @@ -158,7 +158,7 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource, } @Override - public void selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, + public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { for (int i = 0; i < selections.length; i++) { if (streams[i] != null && (selections[i] == null || !mayRetainStreamFlags[i])) { @@ -172,6 +172,7 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource, streamResetFlags[i] = true; } } + return positionUs; } @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java index 4f006be26c..8eee46afbf 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java @@ -118,7 +118,7 @@ import java.util.List; } @Override - public void selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, + public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { ArrayList> sampleStreamsList = new ArrayList<>(); for (int i = 0; i < selections.length; i++) { @@ -142,6 +142,7 @@ import java.util.List; sampleStreams = newSampleStreamArray(sampleStreamsList.size()); sampleStreamsList.toArray(sampleStreams); sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); + return positionUs; } @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java index 0043d8d62f..1a84a42642 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java @@ -171,7 +171,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource, } @Override - public void selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, + public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { // Map each selection and stream onto a child period index. int[] streamChildIndices = new int[selections.length]; @@ -231,6 +231,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource, } } seenFirstTrackSelection = true; + return positionUs; } @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java index 98e2ca9f37..018eb46dec 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java @@ -109,7 +109,7 @@ import java.util.ArrayList; } @Override - public void selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, + public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { ArrayList> sampleStreamsList = new ArrayList<>(); for (int i = 0; i < selections.length; i++) { @@ -133,6 +133,7 @@ import java.util.ArrayList; sampleStreams = newSampleStreamArray(sampleStreamsList.size()); sampleStreamsList.toArray(sampleStreams); sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); + return positionUs; } @Override