Commit 0887ab05 by tonihei Committed by Oliver Woodman

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
parent 5eab5199
......@@ -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,15 +1197,12 @@ 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();
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);
......
......@@ -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)) {
......
......@@ -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);
......
......@@ -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.
......
......@@ -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() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment