Update stale TrackSelections in chunk sources when keeping the streams.

If we keep streams in chunk sources after selecting new tracks, we also keep
a reference to a stale disabled TrackSelection object. Fix this by updating
the TrackSelection object when keeping the stream. The static part of the
selection (i.e. the subset of selected tracks) stays the same in all cases.

Issue:#6256
PiperOrigin-RevId: 261696082
This commit is contained in:
tonihei 2019-08-05 16:57:44 +01:00 committed by Oliver Woodman
parent b6441a02f5
commit 17a9030e1d
10 changed files with 61 additions and 19 deletions

View File

@ -55,6 +55,9 @@
* Fix issue when calling `performClick` on `PlayerView` without
`PlayerControlView`
([#6260](https://github.com/google/ExoPlayer/issues/6260)).
* Fix issue where playback speeds are not used in adaptive track selections
after manual selection changes for other renderers
([#6256](https://github.com/google/ExoPlayer/issues/6256)).
### 2.10.3 ###

View File

@ -106,13 +106,16 @@ public interface MediaPeriod extends SequenceableLoader {
* Performs a track selection.
*
* <p>The call receives track {@code selections} for each renderer, {@code mayRetainStreamFlags}
* indicating whether the existing {@code SampleStream} can be retained for each selection, and
* indicating whether the existing {@link SampleStream} can be retained for each selection, and
* the existing {@code stream}s themselves. The call will update {@code streams} to reflect the
* provided selections, clearing, setting and replacing entries as required. If an existing sample
* stream is retained but with the requirement that the consuming renderer be reset, then the
* corresponding flag in {@code streamResetFlags} will be set to true. This flag will also be set
* if a new sample stream is created.
*
* <p>Note that previously received {@link TrackSelection TrackSelections} are no longer valid and
* references need to be replaced even if the corresponding {@link SampleStream} is kept.
*
* <p>This method is only called after the period has been prepared.
*
* @param selections The renderer track selections.

View File

@ -69,4 +69,11 @@ public interface DashChunkSource extends ChunkSource {
* @param newManifest The new manifest.
*/
void updateManifest(DashManifest newManifest, int periodIndex);
/**
* Updates the track selection.
*
* @param trackSelection The new track selection instance. Must be equivalent to the previous one.
*/
void updateTrackSelection(TrackSelection trackSelection);
}

View File

@ -406,17 +406,27 @@ import java.util.regex.Pattern;
int[] streamIndexToTrackGroupIndex) {
// Create newly selected primary and event streams.
for (int i = 0; i < selections.length; i++) {
if (streams[i] == null && selections[i] != null) {
TrackSelection selection = selections[i];
if (selection == null) {
continue;
}
if (streams[i] == null) {
// Create new stream for selection.
streamResetFlags[i] = true;
int trackGroupIndex = streamIndexToTrackGroupIndex[i];
TrackGroupInfo trackGroupInfo = trackGroupInfos[trackGroupIndex];
if (trackGroupInfo.trackGroupCategory == TrackGroupInfo.CATEGORY_PRIMARY) {
streams[i] = buildSampleStream(trackGroupInfo, selections[i], positionUs);
streams[i] = buildSampleStream(trackGroupInfo, selection, positionUs);
} else if (trackGroupInfo.trackGroupCategory == TrackGroupInfo.CATEGORY_MANIFEST_EVENTS) {
EventStream eventStream = eventStreams.get(trackGroupInfo.eventStreamGroupIndex);
Format format = selections[i].getTrackGroup().getFormat(0);
Format format = selection.getTrackGroup().getFormat(0);
streams[i] = new EventSampleStream(eventStream, format, manifest.dynamic);
}
} else if (streams[i] instanceof ChunkSampleStream) {
// Update selection in existing stream.
@SuppressWarnings("unchecked")
ChunkSampleStream<DashChunkSource> stream = (ChunkSampleStream<DashChunkSource>) streams[i];
stream.getChunkSource().updateTrackSelection(selection);
}
}
// Create newly selected embedded streams from the corresponding primary stream. Note that this

View File

@ -111,7 +111,6 @@ public class DefaultDashChunkSource implements DashChunkSource {
private final LoaderErrorThrower manifestLoaderErrorThrower;
private final int[] adaptationSetIndices;
private final TrackSelection trackSelection;
private final int trackType;
private final DataSource dataSource;
private final long elapsedRealtimeOffsetMs;
@ -120,6 +119,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
protected final RepresentationHolder[] representationHolders;
private TrackSelection trackSelection;
private DashManifest manifest;
private int periodIndex;
private IOException fatalError;
@ -222,6 +222,11 @@ public class DefaultDashChunkSource implements DashChunkSource {
}
}
@Override
public void updateTrackSelection(TrackSelection trackSelection) {
this.trackSelection = trackSelection;
}
@Override
public void maybeThrowError() throws IOException {
if (fatalError != null) {

View File

@ -183,17 +183,15 @@ import java.util.Map;
}
/**
* Selects tracks for use.
* Sets the current track selection.
*
* @param trackSelection The track selection.
* @param trackSelection The {@link TrackSelection}.
*/
public void selectTracks(TrackSelection trackSelection) {
public void setTrackSelection(TrackSelection trackSelection) {
this.trackSelection = trackSelection;
}
/**
* Returns the current track selection.
*/
/** Returns the current {@link TrackSelection}. */
public TrackSelection getTrackSelection() {
return trackSelection;
}

View File

@ -306,14 +306,17 @@ import java.util.Set;
TrackSelection primaryTrackSelection = oldPrimaryTrackSelection;
// Select new tracks.
for (int i = 0; i < selections.length; i++) {
if (streams[i] == null && selections[i] != null) {
enabledTrackGroupCount++;
TrackSelection selection = selections[i];
if (selection == null) {
continue;
}
int trackGroupIndex = trackGroups.indexOf(selection.getTrackGroup());
if (trackGroupIndex == primaryTrackGroupIndex) {
primaryTrackSelection = selection;
chunkSource.selectTracks(selection);
chunkSource.setTrackSelection(selection);
}
if (streams[i] == null) {
enabledTrackGroupCount++;
streams[i] = new HlsSampleStream(this, trackGroupIndex);
streamResetFlags[i] = true;
if (trackGroupToSampleQueueIndex != null) {

View File

@ -74,10 +74,10 @@ public class DefaultSsChunkSource implements SsChunkSource {
private final LoaderErrorThrower manifestLoaderErrorThrower;
private final int streamElementIndex;
private final TrackSelection trackSelection;
private final ChunkExtractorWrapper[] extractorWrappers;
private final DataSource dataSource;
private TrackSelection trackSelection;
private SsManifest manifest;
private int currentManifestChunkOffset;
@ -155,6 +155,11 @@ public class DefaultSsChunkSource implements SsChunkSource {
manifest = newManifest;
}
@Override
public void updateTrackSelection(TrackSelection trackSelection) {
this.trackSelection = trackSelection;
}
// ChunkSource implementation.
@Override

View File

@ -55,4 +55,11 @@ public interface SsChunkSource extends ChunkSource {
* @param newManifest The new manifest.
*/
void updateManifest(SsManifest newManifest);
/**
* Updates the track selection.
*
* @param trackSelection The new track selection instance. Must be equivalent to the previous one.
*/
void updateTrackSelection(TrackSelection trackSelection);
}

View File

@ -131,6 +131,7 @@ import java.util.List;
stream.release();
streams[i] = null;
} else {
stream.getChunkSource().updateTrackSelection(selections[i]);
sampleStreamsList.add(stream);
}
}