Bugfix: Allow discontinuity on selectTracks

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=129987709
This commit is contained in:
olly 2016-08-11 08:14:02 -07:00 committed by Oliver Woodman
parent 153c0aef2b
commit f9005c7a78
8 changed files with 41 additions and 21 deletions

View File

@ -727,8 +727,13 @@ import java.io.IOException;
// Update streams for the new selection, recreating all streams if reading ahead. // Update streams for the new selection, recreating all streams if reading ahead.
boolean recreateStreams = readingPeriod != playingPeriod; boolean recreateStreams = readingPeriod != playingPeriod;
boolean[] streamResetFlags = playingPeriod.updatePeriodTrackSelection(playbackInfo.positionUs, boolean[] streamResetFlags = new boolean[renderers.length];
loadControl, recreateStreams); long positionUs = playingPeriod.updatePeriodTrackSelection(playbackInfo.positionUs,
loadControl, recreateStreams, streamResetFlags);
if (positionUs != playbackInfo.positionUs) {
playbackInfo.positionUs = positionUs;
resetInternalPosition(positionUs);
}
int enabledRendererCount = 0; int enabledRendererCount = 0;
boolean[] rendererWasEnabledFlags = new boolean[renderers.length]; boolean[] rendererWasEnabledFlags = new boolean[renderers.length];
@ -1156,12 +1161,12 @@ import java.io.IOException;
public final MediaPeriod mediaPeriod; public final MediaPeriod mediaPeriod;
public final Object id; public final Object id;
public final long startPositionUs;
public final SampleStream[] sampleStreams; public final SampleStream[] sampleStreams;
public final boolean[] mayRetainStreamFlags; public final boolean[] mayRetainStreamFlags;
public int index; public int index;
public long startPositionUs;
public boolean isLast; public boolean isLast;
public boolean prepared; public boolean prepared;
public boolean hasEnabledTracks; public boolean hasEnabledTracks;
@ -1205,7 +1210,7 @@ import java.io.IOException;
throws ExoPlaybackException { throws ExoPlaybackException {
prepared = true; prepared = true;
selectTracks(); selectTracks();
updatePeriodTrackSelection(positionUs, loadControl, false); startPositionUs = updatePeriodTrackSelection(positionUs, loadControl, false);
} }
public boolean selectTracks() throws ExoPlaybackException { public boolean selectTracks() throws ExoPlaybackException {
@ -1220,19 +1225,23 @@ import java.io.IOException;
return true; return true;
} }
public boolean[] updatePeriodTrackSelection(long positionUs, LoadControl loadControl, public long updatePeriodTrackSelection(long positionUs, LoadControl loadControl,
boolean forceRecreateStreams) throws ExoPlaybackException { 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++) { for (int i = 0; i < trackSelections.length; i++) {
mayRetainStreamFlags[i] = !forceRecreateStreams mayRetainStreamFlags[i] = !forceRecreateStreams
&& Util.areEqual(periodTrackSelections == null ? null : periodTrackSelections.get(i), && Util.areEqual(periodTrackSelections == null ? null : periodTrackSelections.get(i),
trackSelections.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. // Disable streams on the period and get new streams for updated/newly-enabled tracks.
mediaPeriod.selectTracks(trackSelections.getAll(), mayRetainStreamFlags, sampleStreams, positionUs = mediaPeriod.selectTracks(trackSelections.getAll(), mayRetainStreamFlags,
streamResetFlags, positionUs); sampleStreams, streamResetFlags, positionUs);
periodTrackSelections = trackSelections; periodTrackSelections = trackSelections;
hasEnabledTracks = false; hasEnabledTracks = false;
@ -1245,8 +1254,7 @@ import java.io.IOException;
// The track selection has changed. // The track selection has changed.
loadControl.onTrackSelections(renderers, mediaPeriod.getTrackGroups(), trackSelections); loadControl.onTrackSelections(renderers, mediaPeriod.getTrackGroups(), trackSelections);
return positionUs;
return streamResetFlags;
} }
public void release() { public void release() {

View File

@ -239,7 +239,7 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
} }
@Override @Override
public void selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
Assertions.checkState(prepared); Assertions.checkState(prepared);
// Disable old tracks. // Disable old tracks.
@ -284,7 +284,7 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
loader.cancelLoading(); loader.cancelLoading();
} }
} else if (seenFirstTrackSelection ? selectedNewTracks : positionUs != 0) { } 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. // We'll need to reset renderers consuming from all streams due to the seek.
for (int i = 0; i < streams.length; i++) { for (int i = 0; i < streams.length; i++) {
if (streams[i] != null) { if (streams[i] != null) {
@ -293,6 +293,7 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
} }
} }
seenFirstTrackSelection = true; seenFirstTrackSelection = true;
return positionUs;
} }
@Override @Override

View File

@ -110,8 +110,9 @@ public interface MediaPeriod extends SequenceableLoader {
* @param streamResetFlags Will be updated to indicate new sample streams, and sample streams that * @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. * have been retained but with the requirement that the consuming renderer be reset.
* @param positionUs The current playback position in microseconds. * @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); SampleStream[] streams, boolean[] streamResetFlags, long positionUs);
/** /**

View File

@ -70,7 +70,7 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
} }
@Override @Override
public void selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
// Map each selection and stream onto a child period index. // Map each selection and stream onto a child period index.
int[] streamChildIndices = new int[selections.length]; 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; childStreams[j] = streamChildIndices[j] == i ? streams[j] : null;
childSelections[j] = selectionChildIndices[j] == i ? selections[j] : null; childSelections[j] = selectionChildIndices[j] == i ? selections[j] : null;
} }
periods[i].selectTracks(childSelections, mayRetainStreamFlags, childStreams, streamResetFlags, long selectPositionUs = periods[i].selectTracks(childSelections, mayRetainStreamFlags,
positionUs); childStreams, streamResetFlags, positionUs);
if (i == 0) {
positionUs = selectPositionUs;
} else if (selectPositionUs != positionUs) {
throw new IllegalStateException("Children enabled at different positions");
}
boolean periodEnabled = false; boolean periodEnabled = false;
for (int j = 0; j < selections.length; j++) { for (int j = 0; j < selections.length; j++) {
if (selectionChildIndices[j] == i) { if (selectionChildIndices[j] == i) {
@ -118,6 +123,7 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
enabledPeriods = new MediaPeriod[enabledPeriodsList.size()]; enabledPeriods = new MediaPeriod[enabledPeriodsList.size()];
enabledPeriodsList.toArray(enabledPeriods); enabledPeriodsList.toArray(enabledPeriods);
sequenceableLoader = new CompositeSequenceableLoader(enabledPeriods); sequenceableLoader = new CompositeSequenceableLoader(enabledPeriods);
return positionUs;
} }
@Override @Override

View File

@ -158,7 +158,7 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
} }
@Override @Override
public void selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
for (int i = 0; i < selections.length; i++) { for (int i = 0; i < selections.length; i++) {
if (streams[i] != null && (selections[i] == null || !mayRetainStreamFlags[i])) { if (streams[i] != null && (selections[i] == null || !mayRetainStreamFlags[i])) {
@ -172,6 +172,7 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
streamResetFlags[i] = true; streamResetFlags[i] = true;
} }
} }
return positionUs;
} }
@Override @Override

View File

@ -118,7 +118,7 @@ import java.util.List;
} }
@Override @Override
public void selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
ArrayList<ChunkSampleStream<DashChunkSource>> sampleStreamsList = new ArrayList<>(); ArrayList<ChunkSampleStream<DashChunkSource>> sampleStreamsList = new ArrayList<>();
for (int i = 0; i < selections.length; i++) { for (int i = 0; i < selections.length; i++) {
@ -142,6 +142,7 @@ import java.util.List;
sampleStreams = newSampleStreamArray(sampleStreamsList.size()); sampleStreams = newSampleStreamArray(sampleStreamsList.size());
sampleStreamsList.toArray(sampleStreams); sampleStreamsList.toArray(sampleStreams);
sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
return positionUs;
} }
@Override @Override

View File

@ -171,7 +171,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
} }
@Override @Override
public void selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
// Map each selection and stream onto a child period index. // Map each selection and stream onto a child period index.
int[] streamChildIndices = new int[selections.length]; int[] streamChildIndices = new int[selections.length];
@ -231,6 +231,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
} }
} }
seenFirstTrackSelection = true; seenFirstTrackSelection = true;
return positionUs;
} }
@Override @Override

View File

@ -109,7 +109,7 @@ import java.util.ArrayList;
} }
@Override @Override
public void selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
ArrayList<ChunkSampleStream<SsChunkSource>> sampleStreamsList = new ArrayList<>(); ArrayList<ChunkSampleStream<SsChunkSource>> sampleStreamsList = new ArrayList<>();
for (int i = 0; i < selections.length; i++) { for (int i = 0; i < selections.length; i++) {
@ -133,6 +133,7 @@ import java.util.ArrayList;
sampleStreams = newSampleStreamArray(sampleStreamsList.size()); sampleStreams = newSampleStreamArray(sampleStreamsList.size());
sampleStreamsList.toArray(sampleStreams); sampleStreamsList.toArray(sampleStreams);
sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
return positionUs;
} }
@Override @Override