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; ...@@ -1108,7 +1108,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
return; return;
} }
newTrackSelectorResult = periodHolder.selectTracks(playbackSpeed, playbackInfo.timeline); newTrackSelectorResult = periodHolder.selectTracks(playbackSpeed, playbackInfo.timeline);
if (newTrackSelectorResult != null) { if (!newTrackSelectorResult.isEquivalent(periodHolder.getTrackSelectorResult())) {
// Selected tracks have changed for this period. // Selected tracks have changed for this period.
break; break;
} }
...@@ -1197,13 +1197,10 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1197,13 +1197,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
private void notifyTrackSelectionDiscontinuity() { private void notifyTrackSelectionDiscontinuity() {
MediaPeriodHolder periodHolder = queue.getFrontPeriod(); MediaPeriodHolder periodHolder = queue.getFrontPeriod();
while (periodHolder != null) { while (periodHolder != null) {
TrackSelectorResult trackSelectorResult = periodHolder.getTrackSelectorResult(); TrackSelection[] trackSelections = periodHolder.getTrackSelectorResult().selections.getAll();
if (trackSelectorResult != null) { for (TrackSelection trackSelection : trackSelections) {
TrackSelection[] trackSelections = trackSelectorResult.selections.getAll(); if (trackSelection != null) {
for (TrackSelection trackSelection : trackSelections) { trackSelection.onDiscontinuity();
if (trackSelection != null) {
trackSelection.onDiscontinuity();
}
} }
} }
periodHolder = periodHolder.getNext(); periodHolder = periodHolder.getNext();
...@@ -1506,7 +1503,12 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1506,7 +1503,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
} else { } else {
MediaPeriod mediaPeriod = MediaPeriod mediaPeriod =
queue.enqueueNextMediaPeriod( queue.enqueueNextMediaPeriod(
rendererCapabilities, trackSelector, loadControl.getAllocator(), mediaSource, info); rendererCapabilities,
trackSelector,
loadControl.getAllocator(),
mediaSource,
info,
emptyTrackSelectorResult);
mediaPeriod.prepare(this, info.startPositionUs); mediaPeriod.prepare(this, info.startPositionUs);
setIsLoading(true); setIsLoading(true);
handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */ false); handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */ false);
......
...@@ -59,8 +59,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -59,8 +59,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
private final MediaSource mediaSource; private final MediaSource mediaSource;
@Nullable private MediaPeriodHolder next; @Nullable private MediaPeriodHolder next;
@Nullable private TrackGroupArray trackGroups; private TrackGroupArray trackGroups;
@Nullable private TrackSelectorResult trackSelectorResult; private TrackSelectorResult trackSelectorResult;
private long rendererPositionOffsetUs; private long rendererPositionOffsetUs;
/** /**
...@@ -72,6 +72,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -72,6 +72,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
* @param allocator The allocator. * @param allocator The allocator.
* @param mediaSource The media source that produced the media period. * @param mediaSource The media source that produced the media period.
* @param info Information used to identify this media period in its timeline 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( public MediaPeriodHolder(
RendererCapabilities[] rendererCapabilities, RendererCapabilities[] rendererCapabilities,
...@@ -79,13 +81,16 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -79,13 +81,16 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
TrackSelector trackSelector, TrackSelector trackSelector,
Allocator allocator, Allocator allocator,
MediaSource mediaSource, MediaSource mediaSource,
MediaPeriodInfo info) { MediaPeriodInfo info,
TrackSelectorResult emptyTrackSelectorResult) {
this.rendererCapabilities = rendererCapabilities; this.rendererCapabilities = rendererCapabilities;
this.rendererPositionOffsetUs = rendererPositionOffsetUs; this.rendererPositionOffsetUs = rendererPositionOffsetUs;
this.trackSelector = trackSelector; this.trackSelector = trackSelector;
this.mediaSource = mediaSource; this.mediaSource = mediaSource;
this.uid = info.id.periodUid; this.uid = info.id.periodUid;
this.info = info; this.info = info;
this.trackGroups = TrackGroupArray.EMPTY;
this.trackSelectorResult = emptyTrackSelectorResult;
sampleStreams = new SampleStream[rendererCapabilities.length]; sampleStreams = new SampleStream[rendererCapabilities.length];
mayRetainStreamFlags = new boolean[rendererCapabilities.length]; mayRetainStreamFlags = new boolean[rendererCapabilities.length];
mediaPeriod = mediaPeriod =
...@@ -167,8 +172,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -167,8 +172,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
public void handlePrepared(float playbackSpeed, Timeline timeline) throws ExoPlaybackException { public void handlePrepared(float playbackSpeed, Timeline timeline) throws ExoPlaybackException {
prepared = true; prepared = true;
trackGroups = mediaPeriod.getTrackGroups(); trackGroups = mediaPeriod.getTrackGroups();
TrackSelectorResult selectorResult = TrackSelectorResult selectorResult = selectTracks(playbackSpeed, timeline);
Assertions.checkNotNull(selectTracks(playbackSpeed, timeline));
long newStartPositionUs = long newStartPositionUs =
applyTrackSelection( applyTrackSelection(
selectorResult, info.startPositionUs, /* forceRecreateStreams= */ false); selectorResult, info.startPositionUs, /* forceRecreateStreams= */ false);
...@@ -202,22 +206,20 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -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 * Selects tracks for the period. Must only be called if {@link #prepared} is {@code true}.
* 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 playbackSpeed The current playback speed.
* @param timeline The current {@link Timeline}. * @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. * @throws ExoPlaybackException If an error occurs during track selection.
*/ */
@Nullable
public TrackSelectorResult selectTracks(float playbackSpeed, Timeline timeline) public TrackSelectorResult selectTracks(float playbackSpeed, Timeline timeline)
throws ExoPlaybackException { throws ExoPlaybackException {
TrackSelectorResult selectorResult = TrackSelectorResult selectorResult =
trackSelector.selectTracks(rendererCapabilities, getTrackGroups(), info.id, timeline); trackSelector.selectTracks(rendererCapabilities, getTrackGroups(), info.id, timeline);
if (selectorResult.isEquivalent(trackSelectorResult)) {
return null;
}
for (TrackSelection trackSelection : selectorResult.selections.getAll()) { for (TrackSelection trackSelection : selectorResult.selections.getAll()) {
if (trackSelection != null) { if (trackSelection != null) {
trackSelection.onPlaybackSpeed(playbackSpeed); trackSelection.onPlaybackSpeed(playbackSpeed);
...@@ -303,7 +305,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -303,7 +305,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
/** Releases the media period. No other method should be called after the release. */ /** Releases the media period. No other method should be called after the release. */
public void release() { public void release() {
disableTrackSelectionsInResult(); disableTrackSelectionsInResult();
trackSelectorResult = null;
releaseMediaPeriod(info.endPositionUs, mediaSource, mediaPeriod); releaseMediaPeriod(info.endPositionUs, mediaSource, mediaPeriod);
} }
...@@ -331,25 +332,18 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -331,25 +332,18 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
return next; return next;
} }
/** /** Returns the {@link TrackGroupArray} exposed by this media period. */
* Returns the {@link TrackGroupArray} exposed by this media period. Must only be called if {@link
* #prepared} is {@code true}.
*/
public TrackGroupArray getTrackGroups() { public TrackGroupArray getTrackGroups() {
return Assertions.checkNotNull(trackGroups); return trackGroups;
} }
/** /** Returns the {@link TrackSelectorResult} which is currently applied. */
* Returns the {@link TrackSelectorResult} which is currently applied. Must only be called if
* {@link #prepared} is {@code true}.
*/
public TrackSelectorResult getTrackSelectorResult() { public TrackSelectorResult getTrackSelectorResult() {
return Assertions.checkNotNull(trackSelectorResult); return trackSelectorResult;
} }
private void enableTrackSelectionsInResult() { private void enableTrackSelectionsInResult() {
TrackSelectorResult trackSelectorResult = this.trackSelectorResult; if (!isLoadingMediaPeriod()) {
if (!isLoadingMediaPeriod() || trackSelectorResult == null) {
return; return;
} }
for (int i = 0; i < trackSelectorResult.length; i++) { for (int i = 0; i < trackSelectorResult.length; i++) {
...@@ -362,8 +356,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -362,8 +356,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
} }
private void disableTrackSelectionsInResult() { private void disableTrackSelectionsInResult() {
TrackSelectorResult trackSelectorResult = this.trackSelectorResult; if (!isLoadingMediaPeriod()) {
if (!isLoadingMediaPeriod() || trackSelectorResult == null) {
return; return;
} }
for (int i = 0; i < trackSelectorResult.length; i++) { for (int i = 0; i < trackSelectorResult.length; i++) {
...@@ -394,7 +387,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -394,7 +387,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
*/ */
private void associateNoSampleRenderersWithEmptySampleStream( private void associateNoSampleRenderersWithEmptySampleStream(
@NullableType SampleStream[] sampleStreams) { @NullableType SampleStream[] sampleStreams) {
TrackSelectorResult trackSelectorResult = Assertions.checkNotNull(this.trackSelectorResult);
for (int i = 0; i < rendererCapabilities.length; i++) { for (int i = 0; i < rendererCapabilities.length; i++) {
if (rendererCapabilities[i].getTrackType() == C.TRACK_TYPE_NONE if (rendererCapabilities[i].getTrackType() == C.TRACK_TYPE_NONE
&& trackSelectorResult.isRendererEnabled(i)) { && trackSelectorResult.isRendererEnabled(i)) {
......
...@@ -22,6 +22,7 @@ import com.google.android.exoplayer2.source.MediaPeriod; ...@@ -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;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.trackselection.TrackSelector; 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.upstream.Allocator;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
...@@ -135,13 +136,16 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -135,13 +136,16 @@ import com.google.android.exoplayer2.util.Assertions;
* @param allocator The allocator. * @param allocator The allocator.
* @param mediaSource The media source that produced the media period. * @param mediaSource The media source that produced the media period.
* @param info Information used to identify this media period in its timeline 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( public MediaPeriod enqueueNextMediaPeriod(
RendererCapabilities[] rendererCapabilities, RendererCapabilities[] rendererCapabilities,
TrackSelector trackSelector, TrackSelector trackSelector,
Allocator allocator, Allocator allocator,
MediaSource mediaSource, MediaSource mediaSource,
MediaPeriodInfo info) { MediaPeriodInfo info,
TrackSelectorResult emptyTrackSelectorResult) {
long rendererPositionOffsetUs = long rendererPositionOffsetUs =
loading == null loading == null
? (info.id.isAd() && info.contentPositionUs != C.TIME_UNSET ? (info.id.isAd() && info.contentPositionUs != C.TIME_UNSET
...@@ -155,7 +159,8 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -155,7 +159,8 @@ import com.google.android.exoplayer2.util.Assertions;
trackSelector, trackSelector,
allocator, allocator,
mediaSource, mediaSource,
info); info,
emptyTrackSelectorResult);
if (loading != null) { if (loading != null) {
Assertions.checkState(hasPlayingPeriod()); Assertions.checkState(hasPlayingPeriod());
loading.setNext(newPeriodHolder); loading.setNext(newPeriodHolder);
......
...@@ -85,8 +85,8 @@ public final class TrackSelectorResult { ...@@ -85,8 +85,8 @@ public final class TrackSelectorResult {
/** /**
* Returns whether this result is equivalent to {@code other} for the renderer at the given index. * 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 * The results are equivalent if they have equal track selections and configurations for the
* configurations for the renderer. * renderer.
* *
* @param other The other {@link TrackSelectorResult}. May be null, in which case {@code false} * @param other The other {@link TrackSelectorResult}. May be null, in which case {@code false}
* will be returned. * will be returned.
......
...@@ -26,7 +26,9 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; ...@@ -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.SinglePeriodTimeline;
import com.google.android.exoplayer2.source.ads.AdPlaybackState; import com.google.android.exoplayer2.source.ads.AdPlaybackState;
import com.google.android.exoplayer2.source.ads.SinglePeriodAdTimeline; 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.TrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
...@@ -381,7 +383,13 @@ public final class MediaPeriodQueueTest { ...@@ -381,7 +383,13 @@ public final class MediaPeriodQueueTest {
private void enqueueNext() { private void enqueueNext() {
mediaPeriodQueue.enqueueNextMediaPeriod( 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() { 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