Remove nullablity of track groups and selections in MediaPeriodHolder.

These values can easily default to the empty track group and the empty
selection. As a result we can remove restrictions about not calling
holder.getTrackGroups before the period finished preparation.

PiperOrigin-RevId: 261280927
This commit is contained in:
tonihei 2019-08-02 09:28:17 +01:00 committed by Oliver Woodman
parent 5eab519925
commit 0887ab059c
5 changed files with 49 additions and 42 deletions

View file

@ -1108,7 +1108,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
return;
}
newTrackSelectorResult = periodHolder.selectTracks(playbackSpeed, playbackInfo.timeline);
if (newTrackSelectorResult != null) {
if (!newTrackSelectorResult.isEquivalent(periodHolder.getTrackSelectorResult())) {
// Selected tracks have changed for this period.
break;
}
@ -1197,13 +1197,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
private void notifyTrackSelectionDiscontinuity() {
MediaPeriodHolder periodHolder = queue.getFrontPeriod();
while (periodHolder != null) {
TrackSelectorResult trackSelectorResult = periodHolder.getTrackSelectorResult();
if (trackSelectorResult != null) {
TrackSelection[] trackSelections = trackSelectorResult.selections.getAll();
for (TrackSelection trackSelection : trackSelections) {
if (trackSelection != null) {
trackSelection.onDiscontinuity();
}
TrackSelection[] trackSelections = periodHolder.getTrackSelectorResult().selections.getAll();
for (TrackSelection trackSelection : trackSelections) {
if (trackSelection != null) {
trackSelection.onDiscontinuity();
}
}
periodHolder = periodHolder.getNext();
@ -1506,7 +1503,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
} else {
MediaPeriod mediaPeriod =
queue.enqueueNextMediaPeriod(
rendererCapabilities, trackSelector, loadControl.getAllocator(), mediaSource, info);
rendererCapabilities,
trackSelector,
loadControl.getAllocator(),
mediaSource,
info,
emptyTrackSelectorResult);
mediaPeriod.prepare(this, info.startPositionUs);
setIsLoading(true);
handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */ false);

View file

@ -59,8 +59,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
private final MediaSource mediaSource;
@Nullable private MediaPeriodHolder next;
@Nullable private TrackGroupArray trackGroups;
@Nullable private TrackSelectorResult trackSelectorResult;
private TrackGroupArray trackGroups;
private TrackSelectorResult trackSelectorResult;
private long rendererPositionOffsetUs;
/**
@ -72,6 +72,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
* @param allocator The allocator.
* @param mediaSource The media source that produced the media period.
* @param info Information used to identify this media period in its timeline period.
* @param emptyTrackSelectorResult A {@link TrackSelectorResult} with empty selections for each
* renderer.
*/
public MediaPeriodHolder(
RendererCapabilities[] rendererCapabilities,
@ -79,13 +81,16 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
TrackSelector trackSelector,
Allocator allocator,
MediaSource mediaSource,
MediaPeriodInfo info) {
MediaPeriodInfo info,
TrackSelectorResult emptyTrackSelectorResult) {
this.rendererCapabilities = rendererCapabilities;
this.rendererPositionOffsetUs = rendererPositionOffsetUs;
this.trackSelector = trackSelector;
this.mediaSource = mediaSource;
this.uid = info.id.periodUid;
this.info = info;
this.trackGroups = TrackGroupArray.EMPTY;
this.trackSelectorResult = emptyTrackSelectorResult;
sampleStreams = new SampleStream[rendererCapabilities.length];
mayRetainStreamFlags = new boolean[rendererCapabilities.length];
mediaPeriod =
@ -167,8 +172,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
public void handlePrepared(float playbackSpeed, Timeline timeline) throws ExoPlaybackException {
prepared = true;
trackGroups = mediaPeriod.getTrackGroups();
TrackSelectorResult selectorResult =
Assertions.checkNotNull(selectTracks(playbackSpeed, timeline));
TrackSelectorResult selectorResult = selectTracks(playbackSpeed, timeline);
long newStartPositionUs =
applyTrackSelection(
selectorResult, info.startPositionUs, /* forceRecreateStreams= */ false);
@ -202,22 +206,20 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
/**
* Selects tracks for the period and returns the new result if the selection changed. Must only be
* called if {@link #prepared} is {@code true}.
* Selects tracks for the period. Must only be called if {@link #prepared} is {@code true}.
*
* <p>The new track selection needs to be applied with {@link
* #applyTrackSelection(TrackSelectorResult, long, boolean)} before taking effect.
*
* @param playbackSpeed The current playback speed.
* @param timeline The current {@link Timeline}.
* @return The {@link TrackSelectorResult} if the result changed. Or null if nothing changed.
* @return The {@link TrackSelectorResult}.
* @throws ExoPlaybackException If an error occurs during track selection.
*/
@Nullable
public TrackSelectorResult selectTracks(float playbackSpeed, Timeline timeline)
throws ExoPlaybackException {
TrackSelectorResult selectorResult =
trackSelector.selectTracks(rendererCapabilities, getTrackGroups(), info.id, timeline);
if (selectorResult.isEquivalent(trackSelectorResult)) {
return null;
}
for (TrackSelection trackSelection : selectorResult.selections.getAll()) {
if (trackSelection != null) {
trackSelection.onPlaybackSpeed(playbackSpeed);
@ -303,7 +305,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
/** Releases the media period. No other method should be called after the release. */
public void release() {
disableTrackSelectionsInResult();
trackSelectorResult = null;
releaseMediaPeriod(info.endPositionUs, mediaSource, mediaPeriod);
}
@ -331,25 +332,18 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
return next;
}
/**
* Returns the {@link TrackGroupArray} exposed by this media period. Must only be called if {@link
* #prepared} is {@code true}.
*/
/** Returns the {@link TrackGroupArray} exposed by this media period. */
public TrackGroupArray getTrackGroups() {
return Assertions.checkNotNull(trackGroups);
return trackGroups;
}
/**
* Returns the {@link TrackSelectorResult} which is currently applied. Must only be called if
* {@link #prepared} is {@code true}.
*/
/** Returns the {@link TrackSelectorResult} which is currently applied. */
public TrackSelectorResult getTrackSelectorResult() {
return Assertions.checkNotNull(trackSelectorResult);
return trackSelectorResult;
}
private void enableTrackSelectionsInResult() {
TrackSelectorResult trackSelectorResult = this.trackSelectorResult;
if (!isLoadingMediaPeriod() || trackSelectorResult == null) {
if (!isLoadingMediaPeriod()) {
return;
}
for (int i = 0; i < trackSelectorResult.length; i++) {
@ -362,8 +356,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
private void disableTrackSelectionsInResult() {
TrackSelectorResult trackSelectorResult = this.trackSelectorResult;
if (!isLoadingMediaPeriod() || trackSelectorResult == null) {
if (!isLoadingMediaPeriod()) {
return;
}
for (int i = 0; i < trackSelectorResult.length; i++) {
@ -394,7 +387,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
*/
private void associateNoSampleRenderersWithEmptySampleStream(
@NullableType SampleStream[] sampleStreams) {
TrackSelectorResult trackSelectorResult = Assertions.checkNotNull(this.trackSelectorResult);
for (int i = 0; i < rendererCapabilities.length; i++) {
if (rendererCapabilities[i].getTrackType() == C.TRACK_TYPE_NONE
&& trackSelectorResult.isRendererEnabled(i)) {

View file

@ -22,6 +22,7 @@ import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.util.Assertions;
@ -135,13 +136,16 @@ import com.google.android.exoplayer2.util.Assertions;
* @param allocator The allocator.
* @param mediaSource The media source that produced the media period.
* @param info Information used to identify this media period in its timeline period.
* @param emptyTrackSelectorResult A {@link TrackSelectorResult} with empty selections for each
* renderer.
*/
public MediaPeriod enqueueNextMediaPeriod(
RendererCapabilities[] rendererCapabilities,
TrackSelector trackSelector,
Allocator allocator,
MediaSource mediaSource,
MediaPeriodInfo info) {
MediaPeriodInfo info,
TrackSelectorResult emptyTrackSelectorResult) {
long rendererPositionOffsetUs =
loading == null
? (info.id.isAd() && info.contentPositionUs != C.TIME_UNSET
@ -155,7 +159,8 @@ import com.google.android.exoplayer2.util.Assertions;
trackSelector,
allocator,
mediaSource,
info);
info,
emptyTrackSelectorResult);
if (loading != null) {
Assertions.checkState(hasPlayingPeriod());
loading.setNext(newPeriodHolder);

View file

@ -85,8 +85,8 @@ public final class TrackSelectorResult {
/**
* Returns whether this result is equivalent to {@code other} for the renderer at the given index.
* The results are equivalent if they have equal renderersEnabled array, track selections, and
* configurations for the renderer.
* The results are equivalent if they have equal track selections and configurations for the
* renderer.
*
* @param other The other {@link TrackSelectorResult}. May be null, in which case {@code false}
* will be returned.

View file

@ -26,7 +26,9 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.SinglePeriodTimeline;
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
import com.google.android.exoplayer2.source.ads.SinglePeriodAdTimeline;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
import com.google.android.exoplayer2.upstream.Allocator;
import org.junit.Before;
import org.junit.Test;
@ -381,7 +383,13 @@ public final class MediaPeriodQueueTest {
private void enqueueNext() {
mediaPeriodQueue.enqueueNextMediaPeriod(
rendererCapabilities, trackSelector, allocator, mediaSource, getNextMediaPeriodInfo());
rendererCapabilities,
trackSelector,
allocator,
mediaSource,
getNextMediaPeriodInfo(),
new TrackSelectorResult(
new RendererConfiguration[0], new TrackSelection[0], /* info= */ null));
}
private MediaPeriodInfo getNextMediaPeriodInfo() {