mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
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:
parent
5eab519925
commit
0887ab059c
5 changed files with 49 additions and 42 deletions
|
|
@ -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;
|
||||||
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;
|
||||||
} 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;
|
||||||
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;
|
||||||
* @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;
|
||||||
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;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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;
|
||||||
/** 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;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
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;
|
||||||
* @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;
|
||||||
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 {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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;
|
||||||
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 {
|
||||||
|
|
||||||
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() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue