Split mutations method out of TrackSelection

`TrackSelection` had mutation methods which were to be called only
internally by ExoPlayer components but were exposed in the
public `Player` interface.

The mutation methods have been moved out of `TrackSelection`
to a new class `ExoTrackSelection`.

Current track related read-only method have also been moved out,
because they are actually something quite unclear.
Even for a single item playlist, it's the track being buffered rather
than the track being played, which is unclear.
But when you have a playlist it starts to get really confusing,
because if the next item is being buffered, then it's actually
the last track to be buffered in the currently playing item.
As a final aside, the implementations don't do proper thread synchronization
to ensure visibility of updated state by the calling thread.

Exposing those mutable methods in the public `Player` interface
was problematic because they leaking internal concepts of `ExoPlayer`.
This is also required to minimize the `Player` interface for long term
stability.

`ExoTrackSelection` is a subclass of `TrackSelection`.
This is not ideal as an `TrackSelection` implementation could
break the current immutability.
This was done in order for this refactor to be simpler.
A future patch will fully split the two classes.

All `MediaPeriod` and `Sources` had to be updated to use the new
`TrackSelection` dynamic aspect class name.
An alternative would have been to break ExoPlayer's public API, keeping
`TrackSelection` as the dynamic aspect name, and calling the public static
aspect class `TrackSelectionState` or similar.
Nevertheless, while it would have impacted less files, it would have
many more small apps and casual users of ExoPlayer.

#player-to-common

PiperOrigin-RevId: 353637924
This commit is contained in:
krocard 2021-01-25 14:58:41 +00:00 committed by Ian Baker
parent b069a567ea
commit ec43735054
45 changed files with 632 additions and 633 deletions

View file

@ -167,6 +167,10 @@
([#8320](https://github.com/google/ExoPlayer/issues/8320)).
* Add option to specify preferred audio role flags.
* Forward `Timeline` and `MediaPeriodId` to `TrackSelection.Factory`.
* In order to make it immutable, `TrackSelection` in the `Player` API now
only contains methods related to static selection.
The rest of the methods have been moved to the child
class `ExoTrackSelection` which is used by all ExoPlayer components.
* DASH:
* Support low-latency DASH playback (`availabilityTimeOffset` and
`ServiceDescription` tags)

View file

@ -21,7 +21,7 @@ import static java.lang.Math.min;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.android.exoplayer2.util.Assertions;
@ -317,7 +317,7 @@ public class DefaultLoadControl implements LoadControl {
@Override
public void onTracksSelected(
Renderer[] renderers, TrackGroupArray trackGroups, TrackSelection[] trackSelections) {
Renderer[] renderers, TrackGroupArray trackGroups, ExoTrackSelection[] trackSelections) {
targetBufferBytes =
targetBufferBytesOverwrite == C.LENGTH_UNSET
? calculateTargetBufferBytes(renderers, trackSelections)
@ -400,7 +400,7 @@ public class DefaultLoadControl implements LoadControl {
* @return The target buffer size in bytes.
*/
protected int calculateTargetBufferBytes(
Renderer[] renderers, TrackSelection[] trackSelectionArray) {
Renderer[] renderers, ExoTrackSelection[] trackSelectionArray) {
int targetBufferSize = 0;
for (int i = 0; i < renderers.length; i++) {
if (trackSelectionArray[i] != null) {

View file

@ -34,7 +34,7 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.source.ShuffleOrder;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
@ -171,7 +171,7 @@ import java.util.List;
emptyTrackSelectorResult =
new TrackSelectorResult(
new RendererConfiguration[renderers.length],
new TrackSelection[renderers.length],
new ExoTrackSelection[renderers.length],
/* info= */ null);
period = new Timeline.Period();
maskingWindowIndex = C.INDEX_UNSET;

View file

@ -40,7 +40,7 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.ShuffleOrder;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
@ -725,7 +725,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
private void notifyTrackSelectionPlayWhenReadyChanged(boolean playWhenReady) {
MediaPeriodHolder periodHolder = queue.getPlayingPeriod();
while (periodHolder != null) {
for (TrackSelection trackSelection : periodHolder.getTrackSelectorResult().selections) {
for (ExoTrackSelection trackSelection : periodHolder.getTrackSelectorResult().selections) {
if (trackSelection != null) {
trackSelection.onPlayWhenReadyChanged(playWhenReady);
}
@ -899,7 +899,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
private void notifyTrackSelectionRebuffer() {
MediaPeriodHolder periodHolder = queue.getPlayingPeriod();
while (periodHolder != null) {
for (TrackSelection trackSelection : periodHolder.getTrackSelectorResult().selections) {
for (ExoTrackSelection trackSelection : periodHolder.getTrackSelectorResult().selections) {
if (trackSelection != null) {
trackSelection.onRebuffer();
}
@ -1689,7 +1689,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
private void updateTrackSelectionPlaybackSpeed(float playbackSpeed) {
MediaPeriodHolder periodHolder = queue.getPlayingPeriod();
while (periodHolder != null) {
for (TrackSelection trackSelection : periodHolder.getTrackSelectorResult().selections) {
for (ExoTrackSelection trackSelection : periodHolder.getTrackSelectorResult().selections) {
if (trackSelection != null) {
trackSelection.onPlaybackSpeed(playbackSpeed);
}
@ -1701,7 +1701,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
private void notifyTrackSelectionDiscontinuity() {
MediaPeriodHolder periodHolder = queue.getPlayingPeriod();
while (periodHolder != null) {
for (TrackSelection trackSelection : periodHolder.getTrackSelectorResult().selections) {
for (ExoTrackSelection trackSelection : periodHolder.getTrackSelectorResult().selections) {
if (trackSelection != null) {
trackSelection.onDiscontinuity();
}
@ -2268,10 +2268,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
}
private ImmutableList<Metadata> extractMetadataFromTrackSelectionArray(
TrackSelection[] trackSelections) {
ExoTrackSelection[] trackSelections) {
ImmutableList.Builder<Metadata> result = new ImmutableList.Builder<>();
boolean seenNonEmptyMetadata = false;
for (TrackSelection trackSelection : trackSelections) {
for (ExoTrackSelection trackSelection : trackSelections) {
if (trackSelection != null) {
Format format = trackSelection.getFormat(/* index= */ 0);
if (format.metadata == null) {
@ -2319,7 +2319,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
TrackSelectorResult trackSelectorResult = periodHolder.getTrackSelectorResult();
RendererConfiguration rendererConfiguration =
trackSelectorResult.rendererConfigurations[rendererIndex];
TrackSelection newSelection = trackSelectorResult.selections[rendererIndex];
ExoTrackSelection newSelection = trackSelectorResult.selections[rendererIndex];
Format[] formats = getFormats(newSelection);
// The renderer needs enabling with its new track selection.
boolean playing = shouldPlayWhenReady() && playbackInfo.playbackState == Player.STATE_READY;
@ -2793,7 +2793,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
return newPeriodIndex == C.INDEX_UNSET ? null : newTimeline.getUidOfPeriod(newPeriodIndex);
}
private static Format[] getFormats(TrackSelection newSelection) {
private static Format[] getFormats(ExoTrackSelection newSelection) {
// Build an array of formats contained by the selection.
int length = newSelection != null ? newSelection.length() : 0;
Format[] formats = new Format[length];

View file

@ -17,7 +17,7 @@ package com.google.android.exoplayer2;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
/** Controls buffering of media. */
@ -34,7 +34,7 @@ public interface LoadControl {
* @param trackSelections The track selections that were made.
*/
void onTracksSelected(
Renderer[] renderers, TrackGroupArray trackGroups, TrackSelection[] trackSelections);
Renderer[] renderers, TrackGroupArray trackGroups, ExoTrackSelection[] trackSelections);
/** Called by the player when stopped. */
void onStopped();

View file

@ -24,7 +24,7 @@ import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
import com.google.android.exoplayer2.upstream.Allocator;
@ -232,7 +232,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
throws ExoPlaybackException {
TrackSelectorResult selectorResult =
trackSelector.selectTracks(rendererCapabilities, getTrackGroups(), info.id, timeline);
for (TrackSelection trackSelection : selectorResult.selections) {
for (ExoTrackSelection trackSelection : selectorResult.selections) {
if (trackSelection != null) {
trackSelection.onPlaybackSpeed(playbackSpeed);
}
@ -359,7 +359,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
for (int i = 0; i < trackSelectorResult.length; i++) {
boolean rendererEnabled = trackSelectorResult.isRendererEnabled(i);
TrackSelection trackSelection = trackSelectorResult.selections[i];
ExoTrackSelection trackSelection = trackSelectorResult.selections[i];
if (rendererEnabled && trackSelection != null) {
trackSelection.enable();
}
@ -372,7 +372,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
for (int i = 0; i < trackSelectorResult.length; i++) {
boolean rendererEnabled = trackSelectorResult.isRendererEnabled(i);
TrackSelection trackSelection = trackSelectorResult.selections[i];
ExoTrackSelection trackSelection = trackSelectorResult.selections[i];
if (rendererEnabled && trackSelection != null) {
trackSelection.disable();
}

View file

@ -48,8 +48,8 @@ import com.google.android.exoplayer2.trackselection.BaseTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
@ -465,8 +465,9 @@ public final class DownloadHelper {
private @MonotonicNonNull MediaPreparer mediaPreparer;
private TrackGroupArray @MonotonicNonNull [] trackGroupArrays;
private MappedTrackInfo @MonotonicNonNull [] mappedTrackInfos;
private List<TrackSelection> @MonotonicNonNull [][] trackSelectionsByPeriodAndRenderer;
private List<TrackSelection> @MonotonicNonNull [][] immutableTrackSelectionsByPeriodAndRenderer;
private List<ExoTrackSelection> @MonotonicNonNull [][] trackSelectionsByPeriodAndRenderer;
private List<ExoTrackSelection> @MonotonicNonNull [][]
immutableTrackSelectionsByPeriodAndRenderer;
/**
* Creates download helper.
@ -573,14 +574,14 @@ public final class DownloadHelper {
}
/**
* Returns all {@link TrackSelection track selections} for a period and renderer. Must not be
* Returns all {@link ExoTrackSelection track selections} for a period and renderer. Must not be
* called until after preparation completes.
*
* @param periodIndex The period index.
* @param rendererIndex The renderer index.
* @return A list of selected {@link TrackSelection track selections}.
* @return A list of selected {@link ExoTrackSelection track selections}.
*/
public List<TrackSelection> getTrackSelections(int periodIndex, int rendererIndex) {
public List<ExoTrackSelection> getTrackSelections(int periodIndex, int rendererIndex) {
assertPreparedWithMedia();
return immutableTrackSelectionsByPeriodAndRenderer[periodIndex][rendererIndex];
}
@ -751,7 +752,7 @@ public final class DownloadHelper {
}
assertPreparedWithMedia();
List<StreamKey> streamKeys = new ArrayList<>();
List<TrackSelection> allSelections = new ArrayList<>();
List<ExoTrackSelection> allSelections = new ArrayList<>();
int periodCount = trackSelectionsByPeriodAndRenderer.length;
for (int periodIndex = 0; periodIndex < periodCount; periodIndex++) {
allSelections.clear();
@ -773,9 +774,9 @@ public final class DownloadHelper {
int periodCount = mediaPreparer.mediaPeriods.length;
int rendererCount = rendererCapabilities.length;
trackSelectionsByPeriodAndRenderer =
(List<TrackSelection>[][]) new List<?>[periodCount][rendererCount];
(List<ExoTrackSelection>[][]) new List<?>[periodCount][rendererCount];
immutableTrackSelectionsByPeriodAndRenderer =
(List<TrackSelection>[][]) new List<?>[periodCount][rendererCount];
(List<ExoTrackSelection>[][]) new List<?>[periodCount][rendererCount];
for (int i = 0; i < periodCount; i++) {
for (int j = 0; j < rendererCount; j++) {
trackSelectionsByPeriodAndRenderer[i][j] = new ArrayList<>();
@ -847,15 +848,15 @@ public final class DownloadHelper {
new MediaPeriodId(mediaPreparer.timeline.getUidOfPeriod(periodIndex)),
mediaPreparer.timeline);
for (int i = 0; i < trackSelectorResult.length; i++) {
@Nullable TrackSelection newSelection = trackSelectorResult.selections[i];
@Nullable ExoTrackSelection newSelection = trackSelectorResult.selections[i];
if (newSelection == null) {
continue;
}
List<TrackSelection> existingSelectionList =
List<ExoTrackSelection> existingSelectionList =
trackSelectionsByPeriodAndRenderer[periodIndex][i];
boolean mergedWithExistingSelection = false;
for (int j = 0; j < existingSelectionList.size(); j++) {
TrackSelection existingSelection = existingSelectionList.get(j);
ExoTrackSelection existingSelection = existingSelectionList.get(j);
if (existingSelection.getTrackGroup() == newSelection.getTrackGroup()) {
// Merge with existing selection.
scratchSet.clear();
@ -1066,15 +1067,15 @@ public final class DownloadHelper {
private static final class DownloadTrackSelection extends BaseTrackSelection {
private static final class Factory implements TrackSelection.Factory {
private static final class Factory implements ExoTrackSelection.Factory {
@Override
public @NullableType TrackSelection[] createTrackSelections(
public @NullableType ExoTrackSelection[] createTrackSelections(
@NullableType Definition[] definitions,
BandwidthMeter bandwidthMeter,
MediaPeriodId mediaPeriodId,
Timeline timeline) {
@NullableType TrackSelection[] selections = new TrackSelection[definitions.length];
@NullableType ExoTrackSelection[] selections = new ExoTrackSelection[definitions.length];
for (int i = 0; i < definitions.length; i++) {
selections[i] =
definitions[i] == null

View file

@ -21,7 +21,7 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
@ -34,9 +34,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
*/
public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callback {
/**
* The {@link MediaPeriod} wrapped by this clipping media period.
*/
/** The {@link MediaPeriod} wrapped by this clipping media period. */
public final MediaPeriod mediaPeriod;
@Nullable private MediaPeriod.Callback callback;
@ -98,7 +96,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
@Override
public long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
@ -250,7 +248,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
}
private static boolean shouldKeepInitialDiscontinuity(
long startUs, @NullableType TrackSelection[] selections) {
long startUs, @NullableType ExoTrackSelection[] selections) {
// If the clipping start position is non-zero, the clipping sample streams will adjust
// timestamps on buffers they read from the unclipped sample streams. These adjusted buffer
// timestamps can be negative, because sample streams provide buffers starting at a key-frame,
@ -261,7 +259,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
// However, for tracks where all samples are sync samples, we assume they have random access
// seek behaviour and do not need an initial discontinuity to reset the renderer.
if (startUs != 0) {
for (TrackSelection trackSelection : selections) {
for (ExoTrackSelection trackSelection : selections) {
if (trackSelection != null) {
Format selectedFormat = trackSelection.getSelectedFormat();
if (!MimeTypes.allSamplesAreSyncSamples(
@ -274,9 +272,7 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
return false;
}
/**
* Wraps a {@link SampleStream} and clips its samples.
*/
/** Wraps a {@link SampleStream} and clips its samples. */
private final class ClippingSampleStream implements SampleStream {
public final SampleStream childStream;
@ -302,8 +298,8 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb
}
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
boolean requireFormat) {
public int readData(
FormatHolder formatHolder, DecoderInputBuffer buffer, boolean requireFormat) {
if (isPendingInitialDiscontinuity()) {
return C.RESULT_NOTHING_READ;
}

View file

@ -23,7 +23,7 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import java.io.IOException;
import org.checkerframework.checker.nullness.compatqual.NullableType;
@ -173,7 +173,7 @@ public final class MaskingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
@Override
public long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,

View file

@ -21,7 +21,7 @@ import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
@ -45,7 +45,7 @@ public interface MediaPeriod extends SequenceableLoader {
* Called when preparation completes.
*
* <p>Called on the playback thread. After invoking this method, the {@link MediaPeriod} can
* expect for {@link #selectTracks(TrackSelection[], boolean[], SampleStream[], boolean[],
* expect for {@link #selectTracks(ExoTrackSelection[], boolean[], SampleStream[], boolean[],
* long)} to be called with the initial track selection.
*
* @param mediaPeriod The prepared {@link MediaPeriod}.
@ -90,17 +90,17 @@ public interface MediaPeriod extends SequenceableLoader {
/**
* Returns a list of {@link StreamKey StreamKeys} which allow to filter the media in this period
* to load only the parts needed to play the provided {@link TrackSelection TrackSelections}.
* to load only the parts needed to play the provided {@link ExoTrackSelection TrackSelections}.
*
* <p>This method is only called after the period has been prepared.
*
* @param trackSelections The {@link TrackSelection TrackSelections} describing the tracks for
* @param trackSelections The {@link ExoTrackSelection TrackSelections} describing the tracks for
* which stream keys are requested.
* @return The corresponding {@link StreamKey StreamKeys} for the selected tracks, or an empty
* list if filtering is not possible and the entire media needs to be loaded to play the
* selected tracks.
*/
default List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) {
default List<StreamKey> getStreamKeys(List<ExoTrackSelection> trackSelections) {
return Collections.emptyList();
}
@ -115,8 +115,8 @@ public interface MediaPeriod extends SequenceableLoader {
* 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 passed {@link TrackSelection TrackSelections} are no longer valid, and
* any references to them must be updated to point to the new selections.
* <p>Note that previously passed {@link ExoTrackSelection TrackSelections} are no longer valid,
* and any references to them must be updated to point to the new selections.
*
* <p>This method is only called after the period has been prepared.
*
@ -135,7 +135,7 @@ public interface MediaPeriod extends SequenceableLoader {
* @return The actual position at which the tracks were enabled, in microseconds.
*/
long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,

View file

@ -23,7 +23,7 @@ import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.util.Assertions;
import java.io.IOException;
import java.util.ArrayList;
@ -33,9 +33,7 @@ import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Merges multiple {@link MediaPeriod}s.
*/
/** Merges multiple {@link MediaPeriod}s. */
/* package */ final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callback {
private final MediaPeriod[] periods;
@ -100,7 +98,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@Override
public long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
@ -126,15 +124,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
// Select tracks for each child, copying the resulting streams back into a new streams array.
@NullableType SampleStream[] newStreams = new SampleStream[selections.length];
@NullableType SampleStream[] childStreams = new SampleStream[selections.length];
@NullableType TrackSelection[] childSelections = new TrackSelection[selections.length];
@NullableType ExoTrackSelection[] childSelections = new ExoTrackSelection[selections.length];
ArrayList<MediaPeriod> enabledPeriodsList = new ArrayList<>(periods.length);
for (int i = 0; i < periods.length; i++) {
for (int j = 0; j < selections.length; j++) {
childStreams[j] = streamChildIndices[j] == i ? streams[j] : null;
childSelections[j] = selectionChildIndices[j] == i ? selections[j] : null;
}
long selectPositionUs = periods[i].selectTracks(childSelections, mayRetainStreamFlags,
childStreams, streamResetFlags, positionUs);
long selectPositionUs =
periods[i].selectTracks(
childSelections, mayRetainStreamFlags, childStreams, streamResetFlags, positionUs);
if (i == 0) {
positionUs = selectPositionUs;
} else if (selectPositionUs != positionUs) {
@ -314,13 +313,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
@Override
public List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) {
public List<StreamKey> getStreamKeys(List<ExoTrackSelection> trackSelections) {
return mediaPeriod.getStreamKeys(trackSelections);
}
@Override
public long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,

View file

@ -40,7 +40,7 @@ import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.icy.IcyHeaders;
import com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
@ -252,7 +252,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@Override
public long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
@ -277,7 +277,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
// Select new tracks.
for (int i = 0; i < selections.length; i++) {
if (streams[i] == null && selections[i] != null) {
TrackSelection selection = selections[i];
ExoTrackSelection selection = selections[i];
Assertions.checkState(selection.length() == 1);
Assertions.checkState(selection.getIndexInTrackGroup(0) == 0);
int track = tracks.indexOf(selection.getTrackGroup());

View file

@ -25,7 +25,7 @@ import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions;
@ -194,7 +194,7 @@ public final class SilenceMediaSource extends BaseMediaSource {
@Override
public long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,

View file

@ -22,7 +22,7 @@ import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
@ -41,15 +41,11 @@ import java.util.Arrays;
import org.checkerframework.checker.nullness.compatqual.NullableType;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* A {@link MediaPeriod} with a single sample.
*/
/* package */ final class SingleSampleMediaPeriod implements MediaPeriod,
Loader.Callback<SingleSampleMediaPeriod.SourceLoadable> {
/** A {@link MediaPeriod} with a single sample. */
/* package */ final class SingleSampleMediaPeriod
implements MediaPeriod, Loader.Callback<SingleSampleMediaPeriod.SourceLoadable> {
/**
* The initial size of the allocation used to hold the sample data.
*/
/** The initial size of the allocation used to hold the sample data. */
private static final int INITIAL_SAMPLE_SIZE = 1024;
private final DataSpec dataSpec;
@ -113,7 +109,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@Override
public long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
@ -348,8 +344,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
boolean requireFormat) {
public int readData(
FormatHolder formatHolder, DecoderInputBuffer buffer, boolean requireFormat) {
maybeNotifyDownstreamFormat();
if (streamState == STREAM_STATE_END_OF_STREAM) {
buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);

View file

@ -38,13 +38,13 @@ import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/**
* A bandwidth based adaptive {@link TrackSelection}, whose selected track is updated to be the one
* of highest quality given the current network conditions and the state of the buffer.
* A bandwidth based adaptive {@link ExoTrackSelection}, whose selected track is updated to be the
* one of highest quality given the current network conditions and the state of the buffer.
*/
public class AdaptiveTrackSelection extends BaseTrackSelection {
/** Factory for {@link AdaptiveTrackSelection} instances. */
public static class Factory implements TrackSelection.Factory {
public static class Factory implements ExoTrackSelection.Factory {
private final int minDurationForQualityIncreaseMs;
private final int maxDurationForQualityDecreaseMs;
@ -132,14 +132,14 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
}
@Override
public final @NullableType TrackSelection[] createTrackSelections(
public final @NullableType ExoTrackSelection[] createTrackSelections(
@NullableType Definition[] definitions,
BandwidthMeter bandwidthMeter,
MediaPeriodId mediaPeriodId,
Timeline timeline) {
ImmutableList<ImmutableList<AdaptationCheckpoint>> adaptationCheckpoints =
getAdaptationCheckpoints(definitions);
TrackSelection[] selections = new TrackSelection[definitions.length];
ExoTrackSelection[] selections = new ExoTrackSelection[definitions.length];
for (int i = 0; i < definitions.length; i++) {
@Nullable Definition definition = definitions[i];
if (definition == null || definition.tracks.length == 0) {

View file

@ -28,27 +28,17 @@ import com.google.android.exoplayer2.util.Util;
import java.util.Arrays;
import java.util.List;
/**
* An abstract base class suitable for most {@link TrackSelection} implementations.
*/
public abstract class BaseTrackSelection implements TrackSelection {
/** An abstract base class suitable for most {@link ExoTrackSelection} implementations. */
public abstract class BaseTrackSelection implements ExoTrackSelection {
/**
* The selected {@link TrackGroup}.
*/
/** The selected {@link TrackGroup}. */
protected final TrackGroup group;
/**
* The number of selected tracks within the {@link TrackGroup}. Always greater than zero.
*/
/** The number of selected tracks within the {@link TrackGroup}. Always greater than zero. */
protected final int length;
/**
* The indices of the selected tracks in {@link #group}, in order of decreasing bandwidth.
*/
/** The indices of the selected tracks in {@link #group}, in order of decreasing bandwidth. */
protected final int[] tracks;
/**
* The {@link Format}s of the selected tracks, in order of decreasing bandwidth.
*/
/** The {@link Format}s of the selected tracks, in order of decreasing bandwidth. */
private final Format[] formats;
/** Selected track exclusion timestamps, in order of decreasing bandwidth. */
private final long[] excludeUntilTimes;

View file

@ -222,7 +222,6 @@ public class DefaultTrackSelector extends MappingTrackSelector {
*
* @param context Any context.
*/
public ParametersBuilder(Context context) {
super(context);
setInitialValuesWithoutContext();
@ -826,9 +825,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
return this;
}
/**
* Builds a {@link Parameters} instance with the selected values.
*/
/** Builds a {@link Parameters} instance with the selected values. */
public Parameters build() {
return new Parameters(
// Video
@ -1614,6 +1611,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* dimension).
*/
private static final float FRACTION_TO_CONSIDER_FULLSCREEN = 0.98f;
private static final int[] NO_TRACKS = new int[0];
/** Ordering of two format values. A known value is considered greater than Format#NO_VALUE. */
private static final Ordering<Integer> FORMAT_VALUE_ORDERING =
@ -1625,7 +1623,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
/** Ordering where all elements are equal. */
private static final Ordering<Integer> NO_ORDER = Ordering.from((first, second) -> 0);
private final TrackSelection.Factory trackSelectionFactory;
private final ExoTrackSelection.Factory trackSelectionFactory;
private final AtomicReference<Parameters> parametersReference;
/** @deprecated Use {@link #DefaultTrackSelector(Context)} instead. */
@ -1634,9 +1632,9 @@ public class DefaultTrackSelector extends MappingTrackSelector {
this(Parameters.DEFAULT_WITHOUT_CONTEXT, new AdaptiveTrackSelection.Factory());
}
/** @deprecated Use {@link #DefaultTrackSelector(Context, TrackSelection.Factory)}. */
/** @deprecated Use {@link #DefaultTrackSelector(Context, ExoTrackSelection.Factory)}. */
@Deprecated
public DefaultTrackSelector(TrackSelection.Factory trackSelectionFactory) {
public DefaultTrackSelector(ExoTrackSelection.Factory trackSelectionFactory) {
this(Parameters.DEFAULT_WITHOUT_CONTEXT, trackSelectionFactory);
}
@ -1647,17 +1645,18 @@ public class DefaultTrackSelector extends MappingTrackSelector {
/**
* @param context Any {@link Context}.
* @param trackSelectionFactory A factory for {@link TrackSelection}s.
* @param trackSelectionFactory A factory for {@link ExoTrackSelection}s.
*/
public DefaultTrackSelector(Context context, TrackSelection.Factory trackSelectionFactory) {
public DefaultTrackSelector(Context context, ExoTrackSelection.Factory trackSelectionFactory) {
this(Parameters.getDefaults(context), trackSelectionFactory);
}
/**
* @param parameters Initial {@link Parameters}.
* @param trackSelectionFactory A factory for {@link TrackSelection}s.
* @param trackSelectionFactory A factory for {@link ExoTrackSelection}s.
*/
public DefaultTrackSelector(Parameters parameters, TrackSelection.Factory trackSelectionFactory) {
public DefaultTrackSelector(
Parameters parameters, ExoTrackSelection.Factory trackSelectionFactory) {
this.trackSelectionFactory = trackSelectionFactory;
parametersReference = new AtomicReference<>(parameters);
}
@ -1700,7 +1699,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
// MappingTrackSelector implementation.
@Override
protected final Pair<@NullableType RendererConfiguration[], @NullableType TrackSelection[]>
protected final Pair<@NullableType RendererConfiguration[], @NullableType ExoTrackSelection[]>
selectTracks(
MappedTrackInfo mappedTrackInfo,
@Capabilities int[][][] rendererFormatSupports,
@ -1710,7 +1709,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
throws ExoPlaybackException {
Parameters params = parametersReference.get();
int rendererCount = mappedTrackInfo.getRendererCount();
TrackSelection.@NullableType Definition[] definitions =
ExoTrackSelection.@NullableType Definition[] definitions =
selectAllTracks(
mappedTrackInfo,
rendererFormatSupports,
@ -1729,7 +1728,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
definitions[i] =
override == null
? null
: new TrackSelection.Definition(
: new ExoTrackSelection.Definition(
rendererTrackGroups.get(override.groupIndex),
override.tracks,
override.reason,
@ -1738,14 +1737,14 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
@NullableType
TrackSelection[] rendererTrackSelections =
ExoTrackSelection[] rendererTrackSelections =
trackSelectionFactory.createTrackSelections(
definitions, getBandwidthMeter(), mediaPeriodId, timeline);
// Initialize the renderer configurations to the default configuration for all renderers with
// selections, and null otherwise.
@NullableType RendererConfiguration[] rendererConfigurations =
new RendererConfiguration[rendererCount];
@NullableType
RendererConfiguration[] rendererConfigurations = new RendererConfiguration[rendererCount];
for (int i = 0; i < rendererCount; i++) {
boolean forceRendererDisabled = params.getRendererDisabled(i);
boolean rendererEnabled =
@ -1779,19 +1778,19 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* renderer, track group and track (in that order).
* @param rendererMixedMimeTypeAdaptationSupports The {@link AdaptiveSupport} for mixed MIME type
* adaptation for the renderer.
* @return The {@link TrackSelection.Definition}s for the renderers. A null entry indicates no
* @return The {@link ExoTrackSelection.Definition}s for the renderers. A null entry indicates no
* selection was made.
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
*/
protected TrackSelection.@NullableType Definition[] selectAllTracks(
protected ExoTrackSelection.@NullableType Definition[] selectAllTracks(
MappedTrackInfo mappedTrackInfo,
@Capabilities int[][][] rendererFormatSupports,
@AdaptiveSupport int[] rendererMixedMimeTypeAdaptationSupports,
Parameters params)
throws ExoPlaybackException {
int rendererCount = mappedTrackInfo.getRendererCount();
TrackSelection.@NullableType Definition[] definitions =
new TrackSelection.Definition[rendererCount];
ExoTrackSelection.@NullableType Definition[] definitions =
new ExoTrackSelection.Definition[rendererCount];
boolean seenVideoRendererWithMappedTracks = false;
boolean selectedVideoTracks = false;
@ -1819,7 +1818,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
boolean enableAdaptiveTrackSelection =
params.allowMultipleAdaptiveSelections || !seenVideoRendererWithMappedTracks;
@Nullable
Pair<TrackSelection.Definition, AudioTrackScore> audioSelection =
Pair<ExoTrackSelection.Definition, AudioTrackScore> audioSelection =
selectAudioTrack(
mappedTrackInfo.getTrackGroups(i),
rendererFormatSupports[i],
@ -1834,7 +1833,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
// score. Clear the selection for that renderer.
definitions[selectedAudioRendererIndex] = null;
}
TrackSelection.Definition definition = audioSelection.first;
ExoTrackSelection.Definition definition = audioSelection.first;
definitions[i] = definition;
// We assume that audio tracks in the same group have matching language.
selectedAudioLanguage = definition.group.getFormat(definition.tracks[0]).language;
@ -1855,7 +1854,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
break;
case C.TRACK_TYPE_TEXT:
@Nullable
Pair<TrackSelection.Definition, TextTrackScore> textSelection =
Pair<ExoTrackSelection.Definition, TextTrackScore> textSelection =
selectTextTrack(
mappedTrackInfo.getTrackGroups(i),
rendererFormatSupports[i],
@ -1889,7 +1888,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
/**
* Called by {@link #selectAllTracks(MappedTrackInfo, int[][][], int[], Parameters)} to create a
* {@link TrackSelection} for a video renderer.
* {@link ExoTrackSelection} for a video renderer.
*
* @param groups The {@link TrackGroupArray} mapped to the renderer.
* @param formatSupport The {@link Capabilities} for each mapped track, indexed by track group and
@ -1898,19 +1897,19 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* adaptation for the renderer.
* @param params The selector's current constraint parameters.
* @param enableAdaptiveTrackSelection Whether adaptive track selection is allowed.
* @return The {@link TrackSelection.Definition} for the renderer, or null if no selection was
* @return The {@link ExoTrackSelection.Definition} for the renderer, or null if no selection was
* made.
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
*/
@Nullable
protected TrackSelection.Definition selectVideoTrack(
protected ExoTrackSelection.Definition selectVideoTrack(
TrackGroupArray groups,
@Capabilities int[][] formatSupport,
@AdaptiveSupport int mixedMimeTypeAdaptationSupports,
Parameters params,
boolean enableAdaptiveTrackSelection)
throws ExoPlaybackException {
TrackSelection.Definition definition = null;
ExoTrackSelection.Definition definition = null;
if (!params.forceHighestSupportedBitrate
&& !params.forceLowestBitrate
&& enableAdaptiveTrackSelection) {
@ -1924,7 +1923,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
@Nullable
private static TrackSelection.Definition selectAdaptiveVideoTrack(
private static ExoTrackSelection.Definition selectAdaptiveVideoTrack(
TrackGroupArray groups,
@Capabilities int[][] formatSupport,
@AdaptiveSupport int mixedMimeTypeAdaptationSupports,
@ -1956,7 +1955,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
params.viewportHeight,
params.viewportOrientationMayChange);
if (adaptiveTracks.length > 0) {
return new TrackSelection.Definition(group, adaptiveTracks);
return new ExoTrackSelection.Definition(group, adaptiveTracks);
}
}
return null;
@ -1982,8 +1981,9 @@ public class DefaultTrackSelector extends MappingTrackSelector {
return NO_TRACKS;
}
List<Integer> selectedTrackIndices = getViewportFilteredTrackIndices(group, viewportWidth,
viewportHeight, viewportOrientationMayChange);
List<Integer> selectedTrackIndices =
getViewportFilteredTrackIndices(
group, viewportWidth, viewportHeight, viewportOrientationMayChange);
if (selectedTrackIndices.size() < 2) {
return NO_TRACKS;
}
@ -2140,7 +2140,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
@Nullable
private static TrackSelection.Definition selectFixedVideoTrack(
private static ExoTrackSelection.Definition selectFixedVideoTrack(
TrackGroupArray groups, @Capabilities int[][] formatSupport, Parameters params) {
int selectedTrackIndex = C.INDEX_UNSET;
@Nullable TrackGroup selectedGroup = null;
@ -2160,8 +2160,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
// Ignore trick-play tracks for now.
continue;
}
if (isSupported(trackFormatSupport[trackIndex],
params.exceedRendererCapabilitiesIfNecessary)) {
if (isSupported(
trackFormatSupport[trackIndex], params.exceedRendererCapabilitiesIfNecessary)) {
VideoTrackScore trackScore =
new VideoTrackScore(
format,
@ -2183,14 +2183,14 @@ public class DefaultTrackSelector extends MappingTrackSelector {
return selectedGroup == null
? null
: new TrackSelection.Definition(selectedGroup, selectedTrackIndex);
: new ExoTrackSelection.Definition(selectedGroup, selectedTrackIndex);
}
// Audio track selection implementation.
/**
* Called by {@link #selectAllTracks(MappedTrackInfo, int[][][], int[], Parameters)} to create a
* {@link TrackSelection} for an audio renderer.
* {@link ExoTrackSelection} for an audio renderer.
*
* @param groups The {@link TrackGroupArray} mapped to the renderer.
* @param formatSupport The {@link Capabilities} for each mapped track, indexed by track group and
@ -2199,13 +2199,13 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* adaptation for the renderer.
* @param params The selector's current constraint parameters.
* @param enableAdaptiveTrackSelection Whether adaptive track selection is allowed.
* @return The {@link TrackSelection.Definition} and corresponding {@link AudioTrackScore}, or
* @return The {@link ExoTrackSelection.Definition} and corresponding {@link AudioTrackScore}, or
* null if no selection was made.
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
*/
@SuppressWarnings("unused")
@Nullable
protected Pair<TrackSelection.Definition, AudioTrackScore> selectAudioTrack(
protected Pair<ExoTrackSelection.Definition, AudioTrackScore> selectAudioTrack(
TrackGroupArray groups,
@Capabilities int[][] formatSupport,
@AdaptiveSupport int mixedMimeTypeAdaptationSupports,
@ -2219,8 +2219,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
TrackGroup trackGroup = groups.get(groupIndex);
@Capabilities int[] trackFormatSupport = formatSupport[groupIndex];
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
if (isSupported(trackFormatSupport[trackIndex],
params.exceedRendererCapabilitiesIfNecessary)) {
if (isSupported(
trackFormatSupport[trackIndex], params.exceedRendererCapabilitiesIfNecessary)) {
Format format = trackGroup.getFormat(trackIndex);
AudioTrackScore trackScore =
new AudioTrackScore(format, params, trackFormatSupport[trackIndex]);
@ -2243,7 +2243,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
TrackGroup selectedGroup = groups.get(selectedGroupIndex);
TrackSelection.Definition definition = null;
ExoTrackSelection.Definition definition = null;
if (!params.forceHighestSupportedBitrate
&& !params.forceLowestBitrate
&& enableAdaptiveTrackSelection) {
@ -2258,12 +2258,12 @@ public class DefaultTrackSelector extends MappingTrackSelector {
params.allowAudioMixedSampleRateAdaptiveness,
params.allowAudioMixedChannelCountAdaptiveness);
if (adaptiveTracks.length > 1) {
definition = new TrackSelection.Definition(selectedGroup, adaptiveTracks);
definition = new ExoTrackSelection.Definition(selectedGroup, adaptiveTracks);
}
}
if (definition == null) {
// We didn't make an adaptive selection, so make a fixed one instead.
definition = new TrackSelection.Definition(selectedGroup, selectedTrackIndex);
definition = new ExoTrackSelection.Definition(selectedGroup, selectedTrackIndex);
}
return Pair.create(definition, Assertions.checkNotNull(selectedTrackScore));
@ -2322,7 +2322,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
/**
* Called by {@link #selectAllTracks(MappedTrackInfo, int[][][], int[], Parameters)} to create a
* {@link TrackSelection} for a text renderer.
* {@link ExoTrackSelection} for a text renderer.
*
* @param groups The {@link TrackGroupArray} mapped to the renderer.
* @param formatSupport The {@link Capabilities} for each mapped track, indexed by track group and
@ -2330,12 +2330,12 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* @param params The selector's current constraint parameters.
* @param selectedAudioLanguage The language of the selected audio track. May be null if the
* selected text track declares no language or no text track was selected.
* @return The {@link TrackSelection.Definition} and corresponding {@link TextTrackScore}, or null
* if no selection was made.
* @return The {@link ExoTrackSelection.Definition} and corresponding {@link TextTrackScore}, or
* null if no selection was made.
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
*/
@Nullable
protected Pair<TrackSelection.Definition, TextTrackScore> selectTextTrack(
protected Pair<ExoTrackSelection.Definition, TextTrackScore> selectTextTrack(
TrackGroupArray groups,
@Capabilities int[][] formatSupport,
Parameters params,
@ -2348,8 +2348,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
TrackGroup trackGroup = groups.get(groupIndex);
@Capabilities int[] trackFormatSupport = formatSupport[groupIndex];
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
if (isSupported(trackFormatSupport[trackIndex],
params.exceedRendererCapabilitiesIfNecessary)) {
if (isSupported(
trackFormatSupport[trackIndex], params.exceedRendererCapabilitiesIfNecessary)) {
Format format = trackGroup.getFormat(trackIndex);
TextTrackScore trackScore =
new TextTrackScore(
@ -2366,7 +2366,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
return selectedGroup == null
? null
: Pair.create(
new TrackSelection.Definition(selectedGroup, selectedTrackIndex),
new ExoTrackSelection.Definition(selectedGroup, selectedTrackIndex),
Assertions.checkNotNull(selectedTrackScore));
}
@ -2374,18 +2374,18 @@ public class DefaultTrackSelector extends MappingTrackSelector {
/**
* Called by {@link #selectAllTracks(MappedTrackInfo, int[][][], int[], Parameters)} to create a
* {@link TrackSelection} for a renderer whose type is neither video, audio or text.
* {@link ExoTrackSelection} for a renderer whose type is neither video, audio or text.
*
* @param trackType The type of the renderer.
* @param groups The {@link TrackGroupArray} mapped to the renderer.
* @param formatSupport The {@link Capabilities} for each mapped track, indexed by track group and
* track (in that order).
* @param params The selector's current constraint parameters.
* @return The {@link TrackSelection} for the renderer, or null if no selection was made.
* @return The {@link ExoTrackSelection} for the renderer, or null if no selection was made.
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
*/
@Nullable
protected TrackSelection.Definition selectOtherTrack(
protected ExoTrackSelection.Definition selectOtherTrack(
int trackType, TrackGroupArray groups, @Capabilities int[][] formatSupport, Parameters params)
throws ExoPlaybackException {
@Nullable TrackGroup selectedGroup = null;
@ -2395,8 +2395,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
TrackGroup trackGroup = groups.get(groupIndex);
@Capabilities int[] trackFormatSupport = formatSupport[groupIndex];
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
if (isSupported(trackFormatSupport[trackIndex],
params.exceedRendererCapabilitiesIfNecessary)) {
if (isSupported(
trackFormatSupport[trackIndex], params.exceedRendererCapabilitiesIfNecessary)) {
Format format = trackGroup.getFormat(trackIndex);
OtherTrackScore trackScore = new OtherTrackScore(format, trackFormatSupport[trackIndex]);
if (selectedTrackScore == null || trackScore.compareTo(selectedTrackScore) > 0) {
@ -2409,7 +2409,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
return selectedGroup == null
? null
: new TrackSelection.Definition(selectedGroup, selectedTrackIndex);
: new ExoTrackSelection.Definition(selectedGroup, selectedTrackIndex);
}
// Utility methods.
@ -2430,7 +2430,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
MappedTrackInfo mappedTrackInfo,
@Capabilities int[][][] renderererFormatSupports,
@NullableType RendererConfiguration[] rendererConfigurations,
@NullableType TrackSelection[] trackSelections) {
@NullableType ExoTrackSelection[] trackSelections) {
// Check whether we can enable tunneling. To enable tunneling we require exactly one audio and
// one video renderer to support tunneling and have a selection.
int tunnelingAudioRendererIndex = -1;
@ -2438,7 +2438,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
boolean enableTunneling = true;
for (int i = 0; i < mappedTrackInfo.getRendererCount(); i++) {
int rendererType = mappedTrackInfo.getRendererType(i);
TrackSelection trackSelection = trackSelections[i];
ExoTrackSelection trackSelection = trackSelections[i];
if ((rendererType == C.TRACK_TYPE_AUDIO || rendererType == C.TRACK_TYPE_VIDEO)
&& trackSelection != null) {
if (rendererSupportsTunneling(
@ -2471,16 +2471,18 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
/**
* Returns whether a renderer supports tunneling for a {@link TrackSelection}.
* Returns whether a renderer supports tunneling for a {@link ExoTrackSelection}.
*
* @param formatSupport The {@link Capabilities} for each track, indexed by group index and track
* index (in that order).
* @param trackGroups The {@link TrackGroupArray}s for the renderer.
* @param selection The track selection.
* @return Whether the renderer supports tunneling for the {@link TrackSelection}.
* @return Whether the renderer supports tunneling for the {@link ExoTrackSelection}.
*/
private static boolean rendererSupportsTunneling(
@Capabilities int[][] formatSupport, TrackGroupArray trackGroups, TrackSelection selection) {
@Capabilities int[][] formatSupport,
TrackGroupArray trackGroups,
ExoTrackSelection selection) {
if (selection == null) {
return false;
}
@ -2565,8 +2567,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
return 0;
}
private static List<Integer> getViewportFilteredTrackIndices(TrackGroup group, int viewportWidth,
int viewportHeight, boolean orientationMayChange) {
private static List<Integer> getViewportFilteredTrackIndices(
TrackGroup group, int viewportWidth, int viewportHeight, boolean orientationMayChange) {
// Initially include all indices.
ArrayList<Integer> selectedTrackIndices = new ArrayList<>(group.length);
for (int i = 0; i < group.length; i++) {
@ -2585,8 +2587,9 @@ public class DefaultTrackSelector extends MappingTrackSelector {
// smallest to exceed the maximum size at which it can be displayed within the viewport.
// We'll discard formats of higher resolution.
if (format.width > 0 && format.height > 0) {
Point maxVideoSizeInViewport = getMaxVideoSizeInViewport(orientationMayChange,
viewportWidth, viewportHeight, format.width, format.height);
Point maxVideoSizeInViewport =
getMaxVideoSizeInViewport(
orientationMayChange, viewportWidth, viewportHeight, format.width, format.height);
int videoPixels = format.width * format.height;
if (format.width >= (int) (maxVideoSizeInViewport.x * FRACTION_TO_CONSIDER_FULLSCREEN)
&& format.height >= (int) (maxVideoSizeInViewport.y * FRACTION_TO_CONSIDER_FULLSCREEN)
@ -2616,8 +2619,12 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* Given viewport dimensions and video dimensions, computes the maximum size of the video as it
* will be rendered to fit inside of the viewport.
*/
private static Point getMaxVideoSizeInViewport(boolean orientationMayChange, int viewportWidth,
int viewportHeight, int videoWidth, int videoHeight) {
private static Point getMaxVideoSizeInViewport(
boolean orientationMayChange,
int viewportWidth,
int viewportHeight,
int videoWidth,
int videoHeight) {
if (orientationMayChange && (videoWidth > videoHeight) != (viewportWidth > viewportHeight)) {
// Rotation is allowed, and the video will be larger in the rotated viewport.
int tempViewportWidth = viewportWidth;

View file

@ -0,0 +1,277 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.trackselection;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.chunk.Chunk;
import com.google.android.exoplayer2.source.chunk.MediaChunk;
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/**
* A {@link TrackSelection} that can change the individually selected track as a result of calling
* {@link #updateSelectedTrack(long, long, long, List, MediaChunkIterator[])} or {@link
* #evaluateQueueSize(long, List)}. This only happens between calls to {@link #enable()} and {@link
* #disable()}.
*/
public interface ExoTrackSelection extends TrackSelection {
/** Contains of a subset of selected tracks belonging to a {@link TrackGroup}. */
final class Definition {
/** The {@link TrackGroup} which tracks belong to. */
public final TrackGroup group;
/** The indices of the selected tracks in {@link #group}. */
public final int[] tracks;
/** The track selection reason. One of the {@link C} SELECTION_REASON_ constants. */
public final int reason;
/** Optional data associated with this selection of tracks. */
@Nullable public final Object data;
/**
* @param group The {@link TrackGroup}. Must not be null.
* @param tracks The indices of the selected tracks within the {@link TrackGroup}. Must not be
* null or empty. May be in any order.
*/
public Definition(TrackGroup group, int... tracks) {
this(group, tracks, C.SELECTION_REASON_UNKNOWN, /* data= */ null);
}
/**
* @param group The {@link TrackGroup}. Must not be null.
* @param tracks The indices of the selected tracks within the {@link TrackGroup}. Must not be
* @param reason The track selection reason. One of the {@link C} SELECTION_REASON_ constants.
* @param data Optional data associated with this selection of tracks.
*/
public Definition(TrackGroup group, int[] tracks, int reason, @Nullable Object data) {
this.group = group;
this.tracks = tracks;
this.reason = reason;
this.data = data;
}
}
/** Factory for {@link ExoTrackSelection} instances. */
interface Factory {
/**
* Creates track selections for the provided {@link Definition Definitions}.
*
* <p>Implementations that create at most one adaptive track selection may use {@link
* TrackSelectionUtil#createTrackSelectionsForDefinitions}.
*
* @param definitions A {@link Definition} array. May include null values.
* @param bandwidthMeter A {@link BandwidthMeter} which can be used to select tracks.
* @param mediaPeriodId The {@link MediaPeriodId} of the period for which tracks are to be
* selected.
* @param timeline The {@link Timeline} holding the period for which tracks are to be selected.
* @return The created selections. Must have the same length as {@code definitions} and may
* include null values.
*/
@NullableType
ExoTrackSelection[] createTrackSelections(
@NullableType Definition[] definitions,
BandwidthMeter bandwidthMeter,
MediaPeriodId mediaPeriodId,
Timeline timeline);
}
/**
* Enables the track selection. Dynamic changes via {@link #updateSelectedTrack(long, long, long,
* List, MediaChunkIterator[])}, {@link #evaluateQueueSize(long, List)} or {@link
* #shouldCancelChunkLoad(long, Chunk, List)} will only happen after this call.
*
* <p>This method may not be called when the track selection is already enabled.
*/
void enable();
/**
* Disables this track selection. No further dynamic changes via {@link #updateSelectedTrack(long,
* long, long, List, MediaChunkIterator[])}, {@link #evaluateQueueSize(long, List)} or {@link
* #shouldCancelChunkLoad(long, Chunk, List)} will happen after this call.
*
* <p>This method may only be called when the track selection is already enabled.
*/
void disable();
// Individual selected track.
/** Returns the {@link Format} of the individual selected track. */
Format getSelectedFormat();
/** Returns the index in the track group of the individual selected track. */
int getSelectedIndexInTrackGroup();
/** Returns the index of the selected track. */
int getSelectedIndex();
/** Returns the reason for the current track selection. */
int getSelectionReason();
/** Returns optional data associated with the current track selection. */
@Nullable
Object getSelectionData();
// Adaptation.
/**
* Called to notify the selection of the current playback speed. The playback speed may affect
* adaptive track selection.
*
* @param speed The factor by which playback is sped up.
*/
void onPlaybackSpeed(float speed);
/**
* Called to notify the selection of a position discontinuity.
*
* <p>This happens when the playback position jumps, e.g., as a result of a seek being performed.
*/
default void onDiscontinuity() {}
/**
* Called to notify when a rebuffer occurred.
*
* <p>A rebuffer is defined to be caused by buffer depletion rather than a user action. Hence this
* method is not called during initial buffering or when buffering as a result of a seek
* operation.
*/
default void onRebuffer() {}
/**
* Called to notify when the playback is paused or resumed.
*
* @param playWhenReady Whether playback will proceed when ready.
*/
default void onPlayWhenReadyChanged(boolean playWhenReady) {}
/**
* Updates the selected track for sources that load media in discrete {@link MediaChunk}s.
*
* <p>This method will only be called when the selection is enabled.
*
* @param playbackPositionUs The current playback position in microseconds. If playback of the
* period to which this track selection belongs has not yet started, the value will be the
* starting position in the period minus the duration of any media in previous periods still
* to be played.
* @param bufferedDurationUs The duration of media currently buffered from the current playback
* position, in microseconds. Note that the next load position can be calculated as {@code
* (playbackPositionUs + bufferedDurationUs)}.
* @param availableDurationUs The duration of media available for buffering from the current
* playback position, in microseconds, or {@link C#TIME_UNSET} if media can be buffered to the
* end of the current period. Note that if not set to {@link C#TIME_UNSET}, the position up to
* which media is available for buffering can be calculated as {@code (playbackPositionUs +
* availableDurationUs)}.
* @param queue The queue of already buffered {@link MediaChunk}s. Must not be modified.
* @param mediaChunkIterators An array of {@link MediaChunkIterator}s providing information about
* the sequence of upcoming media chunks for each track in the selection. All iterators start
* from the media chunk which will be loaded next if the respective track is selected. Note
* that this information may not be available for all tracks, and so some iterators may be
* empty.
*/
void updateSelectedTrack(
long playbackPositionUs,
long bufferedDurationUs,
long availableDurationUs,
List<? extends MediaChunk> queue,
MediaChunkIterator[] mediaChunkIterators);
/**
* Returns the number of chunks that should be retained in the queue.
*
* <p>May be called by sources that load media in discrete {@link MediaChunk MediaChunks} and
* support discarding of buffered chunks.
*
* <p>To avoid excessive re-buffering, implementations should normally return the size of the
* queue. An example of a case where a smaller value may be returned is if network conditions have
* improved dramatically, allowing chunks to be discarded and re-buffered in a track of
* significantly higher quality. Discarding chunks may allow faster switching to a higher quality
* track in this case.
*
* <p>Note that even if the source supports discarding of buffered chunks, the actual number of
* discarded chunks is not guaranteed. The source will call {@link #updateSelectedTrack(long,
* long, long, List, MediaChunkIterator[])} with the updated queue of chunks before loading a new
* chunk to allow switching to another quality.
*
* <p>This method will only be called when the selection is enabled and none of the {@link
* MediaChunk MediaChunks} in the queue are currently loading.
*
* @param playbackPositionUs The current playback position in microseconds. If playback of the
* period to which this track selection belongs has not yet started, the value will be the
* starting position in the period minus the duration of any media in previous periods still
* to be played.
* @param queue The queue of buffered {@link MediaChunk MediaChunks}. Must not be modified.
* @return The number of chunks to retain in the queue.
*/
int evaluateQueueSize(long playbackPositionUs, List<? extends MediaChunk> queue);
/**
* Returns whether an ongoing load of a chunk should be canceled.
*
* <p>May be called by sources that load media in discrete {@link MediaChunk MediaChunks} and
* support canceling the ongoing chunk load. The ongoing chunk load is either the last {@link
* MediaChunk} in the queue or another type of {@link Chunk}, for example, if the source loads
* initialization or encryption data.
*
* <p>To avoid excessive re-buffering, implementations should normally return {@code false}. An
* example where {@code true} might be returned is if a load of a high quality chunk gets stuck
* and canceling this load in favor of a lower quality alternative may avoid a rebuffer.
*
* <p>The source will call {@link #evaluateQueueSize(long, List)} after the cancelation finishes
* to allow discarding of chunks, and {@link #updateSelectedTrack(long, long, long, List,
* MediaChunkIterator[])} before loading a new chunk to allow switching to another quality.
*
* <p>This method will only be called when the selection is enabled.
*
* @param playbackPositionUs The current playback position in microseconds. If playback of the
* period to which this track selection belongs has not yet started, the value will be the
* starting position in the period minus the duration of any media in previous periods still
* to be played.
* @param loadingChunk The currently loading {@link Chunk} that will be canceled if this method
* returns {@code true}.
* @param queue The queue of buffered {@link MediaChunk MediaChunks}, including the {@code
* loadingChunk} if it's a {@link MediaChunk}. Must not be modified.
* @return Whether the ongoing load of {@code loadingChunk} should be canceled.
*/
default boolean shouldCancelChunkLoad(
long playbackPositionUs, Chunk loadingChunk, List<? extends MediaChunk> queue) {
return false;
}
/**
* Attempts to exclude the track at the specified index in the selection, making it ineligible for
* selection by calls to {@link #updateSelectedTrack(long, long, long, List,
* MediaChunkIterator[])} for the specified period of time.
*
* <p>Exclusion will fail if all other tracks are currently excluded. If excluding the currently
* selected track, note that it will remain selected until the next call to {@link
* #updateSelectedTrack(long, long, long, List, MediaChunkIterator[])}.
*
* <p>This method will only be called when the selection is enabled.
*
* @param index The index of the track in the selection.
* @param exclusionDurationMs The duration of time for which the track should be excluded, in
* milliseconds.
* @return Whether exclusion was successful.
*/
boolean blacklist(int index, long exclusionDurationMs);
}

View file

@ -43,14 +43,12 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
/**
* Base class for {@link TrackSelector}s that first establish a mapping between {@link TrackGroup}s
* and {@link Renderer}s, and then from that mapping create a {@link TrackSelection} for each
* and {@link Renderer}s, and then from that mapping create a {@link ExoTrackSelection} for each
* renderer.
*/
public abstract class MappingTrackSelector extends TrackSelector {
/**
* Provides mapped track information for each renderer.
*/
/** Provides mapped track information for each renderer. */
public static final class MappedTrackInfo {
/**
@ -401,7 +399,7 @@ public abstract class MappingTrackSelector extends TrackSelector {
rendererFormatSupports,
unmappedTrackGroupArray);
Pair<@NullableType RendererConfiguration[], @NullableType TrackSelection[]> result =
Pair<@NullableType RendererConfiguration[], @NullableType ExoTrackSelection[]> result =
selectTracks(
mappedTrackInfo,
rendererFormatSupports,
@ -428,7 +426,7 @@ public abstract class MappingTrackSelector extends TrackSelector {
* RendererCapabilities#getTrackType()} is {@link C#TRACK_TYPE_NONE}.
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
*/
protected abstract Pair<@NullableType RendererConfiguration[], @NullableType TrackSelection[]>
protected abstract Pair<@NullableType RendererConfiguration[], @NullableType ExoTrackSelection[]>
selectTracks(
MappedTrackInfo mappedTrackInfo,
@Capabilities int[][][] rendererFormatSupports,
@ -538,5 +536,4 @@ public abstract class MappingTrackSelector extends TrackSelector {
}
return mixedMimeTypeAdaptationSupport;
}
}

View file

@ -28,15 +28,11 @@ import java.util.List;
import java.util.Random;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/**
* A {@link TrackSelection} whose selected track is updated randomly.
*/
/** An {@link ExoTrackSelection} whose selected track is updated randomly. */
public final class RandomTrackSelection extends BaseTrackSelection {
/**
* Factory for {@link RandomTrackSelection} instances.
*/
public static final class Factory implements TrackSelection.Factory {
/** Factory for {@link RandomTrackSelection} instances. */
public static final class Factory implements ExoTrackSelection.Factory {
private final Random random;
@ -44,15 +40,13 @@ public final class RandomTrackSelection extends BaseTrackSelection {
random = new Random();
}
/**
* @param seed A seed for the {@link Random} instance used by the factory.
*/
/** @param seed A seed for the {@link Random} instance used by the factory. */
public Factory(int seed) {
random = new Random(seed);
}
@Override
public @NullableType TrackSelection[] createTrackSelections(
public @NullableType ExoTrackSelection[] createTrackSelections(
@NullableType Definition[] definitions,
BandwidthMeter bandwidthMeter,
MediaPeriodId mediaPeriodId,
@ -144,5 +138,4 @@ public final class RandomTrackSelection extends BaseTrackSelection {
public Object getSelectionData() {
return null;
}
}

View file

@ -15,107 +15,18 @@
*/
package com.google.android.exoplayer2.trackselection;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.chunk.Chunk;
import com.google.android.exoplayer2.source.chunk.MediaChunk;
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/**
* A track selection consisting of a static subset of selected tracks belonging to a {@link
* TrackGroup}, and a possibly varying individual selected track from the subset.
* TrackGroup}.
*
* <p>Tracks belonging to the subset are exposed in decreasing bandwidth order. The individual
* selected track may change dynamically as a result of calling {@link #updateSelectedTrack(long,
* long, long, List, MediaChunkIterator[])} or {@link #evaluateQueueSize(long, List)}. This only
* happens between calls to {@link #enable()} and {@link #disable()}.
* <p>Tracks belonging to the subset are exposed in decreasing bandwidth order.
*/
public interface TrackSelection {
/** Contains of a subset of selected tracks belonging to a {@link TrackGroup}. */
final class Definition {
/** The {@link TrackGroup} which tracks belong to. */
public final TrackGroup group;
/** The indices of the selected tracks in {@link #group}. */
public final int[] tracks;
/** The track selection reason. One of the {@link C} SELECTION_REASON_ constants. */
public final int reason;
/** Optional data associated with this selection of tracks. */
@Nullable public final Object data;
/**
* @param group The {@link TrackGroup}. Must not be null.
* @param tracks The indices of the selected tracks within the {@link TrackGroup}. Must not be
* null or empty. May be in any order.
*/
public Definition(TrackGroup group, int... tracks) {
this(group, tracks, C.SELECTION_REASON_UNKNOWN, /* data= */ null);
}
/**
* @param group The {@link TrackGroup}. Must not be null.
* @param tracks The indices of the selected tracks within the {@link TrackGroup}. Must not be
* @param reason The track selection reason. One of the {@link C} SELECTION_REASON_ constants.
* @param data Optional data associated with this selection of tracks.
*/
public Definition(TrackGroup group, int[] tracks, int reason, @Nullable Object data) {
this.group = group;
this.tracks = tracks;
this.reason = reason;
this.data = data;
}
}
/** Factory for {@link TrackSelection} instances. */
interface Factory {
/**
* Creates track selections for the provided {@link Definition Definitions}.
*
* <p>Implementations that create at most one adaptive track selection may use {@link
* TrackSelectionUtil#createTrackSelectionsForDefinitions}.
*
* @param definitions A {@link Definition} array. May include null values.
* @param bandwidthMeter A {@link BandwidthMeter} which can be used to select tracks.
* @param mediaPeriodId The {@link MediaPeriodId} of the period for which tracks are to be
* selected.
* @param timeline The {@link Timeline} holding the period for which tracks are to be selected.
* @return The created selections. Must have the same length as {@code definitions} and may
* include null values.
*/
@NullableType
TrackSelection[] createTrackSelections(
@NullableType Definition[] definitions,
BandwidthMeter bandwidthMeter,
MediaPeriodId mediaPeriodId,
Timeline timeline);
}
/**
* Enables the track selection. Dynamic changes via {@link #updateSelectedTrack(long, long, long,
* List, MediaChunkIterator[])}, {@link #evaluateQueueSize(long, List)} or {@link
* #shouldCancelChunkLoad(long, Chunk, List)} will only happen after this call.
*
* <p>This method may not be called when the track selection is already enabled.
*/
void enable();
/**
* Disables this track selection. No further dynamic changes via {@link #updateSelectedTrack(long,
* long, long, List, MediaChunkIterator[])}, {@link #evaluateQueueSize(long, List)} or {@link
* #shouldCancelChunkLoad(long, Chunk, List)} will happen after this call.
*
* <p>This method may only be called when the track selection is already enabled.
*/
void disable();
/** Returns the {@link TrackGroup} to which the selected tracks belong. */
TrackGroup getTrackGroup();
@ -159,166 +70,4 @@ public interface TrackSelection {
* index is not part of the selection.
*/
int indexOf(int indexInTrackGroup);
// Individual selected track.
/** Returns the {@link Format} of the individual selected track. */
Format getSelectedFormat();
/** Returns the index in the track group of the individual selected track. */
int getSelectedIndexInTrackGroup();
/** Returns the index of the selected track. */
int getSelectedIndex();
/** Returns the reason for the current track selection. */
int getSelectionReason();
/** Returns optional data associated with the current track selection. */
@Nullable
Object getSelectionData();
// Adaptation.
/**
* Called to notify the selection of the current playback speed. The playback speed may affect
* adaptive track selection.
*
* @param speed The factor by which playback is sped up.
*/
void onPlaybackSpeed(float speed);
/**
* Called to notify the selection of a position discontinuity.
*
* <p>This happens when the playback position jumps, e.g., as a result of a seek being performed.
*/
default void onDiscontinuity() {}
/**
* Called to notify when a rebuffer occurred.
*
* <p>A rebuffer is defined to be caused by buffer depletion rather than a user action. Hence this
* method is not called during initial buffering or when buffering as a result of a seek
* operation.
*/
default void onRebuffer() {}
/**
* Called to notify when the playback is paused or resumed.
*
* @param playWhenReady Whether playback will proceed when ready.
*/
default void onPlayWhenReadyChanged(boolean playWhenReady) {}
/**
* Updates the selected track for sources that load media in discrete {@link MediaChunk}s.
*
* <p>This method will only be called when the selection is enabled.
*
* @param playbackPositionUs The current playback position in microseconds. If playback of the
* period to which this track selection belongs has not yet started, the value will be the
* starting position in the period minus the duration of any media in previous periods still
* to be played.
* @param bufferedDurationUs The duration of media currently buffered from the current playback
* position, in microseconds. Note that the next load position can be calculated as {@code
* (playbackPositionUs + bufferedDurationUs)}.
* @param availableDurationUs The duration of media available for buffering from the current
* playback position, in microseconds, or {@link C#TIME_UNSET} if media can be buffered to the
* end of the current period. Note that if not set to {@link C#TIME_UNSET}, the position up to
* which media is available for buffering can be calculated as {@code (playbackPositionUs +
* availableDurationUs)}.
* @param queue The queue of already buffered {@link MediaChunk}s. Must not be modified.
* @param mediaChunkIterators An array of {@link MediaChunkIterator}s providing information about
* the sequence of upcoming media chunks for each track in the selection. All iterators start
* from the media chunk which will be loaded next if the respective track is selected. Note
* that this information may not be available for all tracks, and so some iterators may be
* empty.
*/
void updateSelectedTrack(
long playbackPositionUs,
long bufferedDurationUs,
long availableDurationUs,
List<? extends MediaChunk> queue,
MediaChunkIterator[] mediaChunkIterators);
/**
* Returns the number of chunks that should be retained in the queue.
*
* <p>May be called by sources that load media in discrete {@link MediaChunk MediaChunks} and
* support discarding of buffered chunks.
*
* <p>To avoid excessive re-buffering, implementations should normally return the size of the
* queue. An example of a case where a smaller value may be returned is if network conditions have
* improved dramatically, allowing chunks to be discarded and re-buffered in a track of
* significantly higher quality. Discarding chunks may allow faster switching to a higher quality
* track in this case.
*
* <p>Note that even if the source supports discarding of buffered chunks, the actual number of
* discarded chunks is not guaranteed. The source will call {@link #updateSelectedTrack(long,
* long, long, List, MediaChunkIterator[])} with the updated queue of chunks before loading a new
* chunk to allow switching to another quality.
*
* <p>This method will only be called when the selection is enabled and none of the {@link
* MediaChunk MediaChunks} in the queue are currently loading.
*
* @param playbackPositionUs The current playback position in microseconds. If playback of the
* period to which this track selection belongs has not yet started, the value will be the
* starting position in the period minus the duration of any media in previous periods still
* to be played.
* @param queue The queue of buffered {@link MediaChunk MediaChunks}. Must not be modified.
* @return The number of chunks to retain in the queue.
*/
int evaluateQueueSize(long playbackPositionUs, List<? extends MediaChunk> queue);
/**
* Returns whether an ongoing load of a chunk should be canceled.
*
* <p>May be called by sources that load media in discrete {@link MediaChunk MediaChunks} and
* support canceling the ongoing chunk load. The ongoing chunk load is either the last {@link
* MediaChunk} in the queue or another type of {@link Chunk}, for example, if the source loads
* initialization or encryption data.
*
* <p>To avoid excessive re-buffering, implementations should normally return {@code false}. An
* example where {@code true} might be returned is if a load of a high quality chunk gets stuck
* and canceling this load in favor of a lower quality alternative may avoid a rebuffer.
*
* <p>The source will call {@link #evaluateQueueSize(long, List)} after the cancelation finishes
* to allow discarding of chunks, and {@link #updateSelectedTrack(long, long, long, List,
* MediaChunkIterator[])} before loading a new chunk to allow switching to another quality.
*
* <p>This method will only be called when the selection is enabled.
*
* @param playbackPositionUs The current playback position in microseconds. If playback of the
* period to which this track selection belongs has not yet started, the value will be the
* starting position in the period minus the duration of any media in previous periods still
* to be played.
* @param loadingChunk The currently loading {@link Chunk} that will be canceled if this method
* returns {@code true}.
* @param queue The queue of buffered {@link MediaChunk MediaChunks}, including the {@code
* loadingChunk} if it's a {@link MediaChunk}. Must not be modified.
* @return Whether the ongoing load of {@code loadingChunk} should be canceled.
*/
default boolean shouldCancelChunkLoad(
long playbackPositionUs, Chunk loadingChunk, List<? extends MediaChunk> queue) {
return false;
}
/**
* Attempts to exclude the track at the specified index in the selection, making it ineligible for
* selection by calls to {@link #updateSelectedTrack(long, long, long, List,
* MediaChunkIterator[])} for the specified period of time.
*
* <p>Exclusion will fail if all other tracks are currently excluded. If excluding the currently
* selected track, note that it will remain selected until the next call to {@link
* #updateSelectedTrack(long, long, long, List, MediaChunkIterator[])}.
*
* <p>This method will only be called when the selection is enabled.
*
* @param index The index of the track in the selection.
* @param exclusionDurationMs The duration of time for which the track should be excluded, in
* milliseconds.
* @return Whether exclusion was successful.
*/
boolean blacklist(int index, long exclusionDurationMs);
}

View file

@ -18,7 +18,7 @@ package com.google.android.exoplayer2.trackselection;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.TrackSelection.Definition;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/** Track selection related utility methods. */
@ -35,7 +35,7 @@ public final class TrackSelectionUtil {
* @param trackSelectionDefinition A {@link Definition} for the track selection.
* @return The created track selection.
*/
TrackSelection createAdaptiveTrackSelection(Definition trackSelectionDefinition);
ExoTrackSelection createAdaptiveTrackSelection(Definition trackSelectionDefinition);
}
/**
@ -48,10 +48,10 @@ public final class TrackSelectionUtil {
* @return The array of created track selection. For null entries in {@code definitions} returns
* null values.
*/
public static @NullableType TrackSelection[] createTrackSelectionsForDefinitions(
public static @NullableType ExoTrackSelection[] createTrackSelectionsForDefinitions(
@NullableType Definition[] definitions,
AdaptiveTrackSelectionFactory adaptiveTrackSelectionFactory) {
TrackSelection[] selections = new TrackSelection[definitions.length];
ExoTrackSelection[] selections = new ExoTrackSelection[definitions.length];
boolean createdAdaptiveTrackSelection = false;
for (int i = 0; i < definitions.length; i++) {
Definition definition = definitions[i];

View file

@ -30,8 +30,8 @@ public final class TrackSelectorResult {
* renderer should be disabled.
*/
public final @NullableType RendererConfiguration[] rendererConfigurations;
/** A {@link TrackSelection} array containing the track selection for each renderer. */
public final @NullableType TrackSelection[] selections;
/** A {@link ExoTrackSelection} array containing the track selection for each renderer. */
public final @NullableType ExoTrackSelection[] selections;
/**
* An opaque object that will be returned to {@link TrackSelector#onSelectionActivated(Object)}
* should the selections be activated.
@ -41,14 +41,14 @@ public final class TrackSelectorResult {
/**
* @param rendererConfigurations A {@link RendererConfiguration} for each renderer. A null entry
* indicates the corresponding renderer should be disabled.
* @param selections A {@link TrackSelection} array containing the selection for each renderer.
* @param selections A {@link ExoTrackSelection} array containing the selection for each renderer.
* @param info An opaque object that will be returned to {@link
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
* {@code null}.
*/
public TrackSelectorResult(
@NullableType RendererConfiguration[] rendererConfigurations,
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
@Nullable Object info) {
this.rendererConfigurations = rendererConfigurations;
this.selections = selections.clone();

View file

@ -20,7 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.DefaultLoadControl.Builder;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.DefaultAllocator;
import org.junit.Before;
import org.junit.Test;
@ -177,7 +177,7 @@ public class DefaultLoadControlTest {
@Test
public void shouldContinueLoading_withNoSelectedTracks_returnsTrue() {
loadControl = builder.build();
loadControl.onTracksSelected(new Renderer[0], TrackGroupArray.EMPTY, new TrackSelection[0]);
loadControl.onTracksSelected(new Renderer[0], TrackGroupArray.EMPTY, new ExoTrackSelection[0]);
assertThat(
loadControl.shouldContinueLoading(

View file

@ -31,7 +31,7 @@ import com.google.android.exoplayer2.testutil.FakeMediaSource;
import com.google.android.exoplayer2.testutil.FakeShuffleOrder;
import com.google.android.exoplayer2.testutil.FakeTimeline;
import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
import com.google.android.exoplayer2.upstream.Allocator;
@ -470,7 +470,7 @@ public final class MediaPeriodQueueTest {
mediaSourceList,
getNextMediaPeriodInfo(),
new TrackSelectorResult(
new RendererConfiguration[0], new TrackSelection[0], /* info= */ null));
new RendererConfiguration[0], new ExoTrackSelection[0], /* info= */ null));
}
private MediaPeriodInfo getNextMediaPeriodInfo() {

View file

@ -38,8 +38,8 @@ import com.google.android.exoplayer2.testutil.FakeRenderer;
import com.google.android.exoplayer2.testutil.FakeTimeline;
import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException;
@ -99,8 +99,7 @@ public class DownloadHelperTest {
trackGroupTextZh);
TrackGroupArray trackGroupArraySingle =
new TrackGroupArray(TRACK_GROUP_VIDEO_SINGLE, trackGroupAudioUs);
trackGroupArrays =
new TrackGroupArray[] {trackGroupArrayAll, trackGroupArraySingle};
trackGroupArrays = new TrackGroupArray[] {trackGroupArrayAll, trackGroupArraySingle};
testMediaItem =
new MediaItem.Builder().setUri("http://test.uri").setCustomCacheKey("cacheKey").build();
@ -194,17 +193,17 @@ public class DownloadHelperTest {
public void getTrackSelections_returnsInitialSelection() throws Exception {
prepareDownloadHelper(downloadHelper);
List<TrackSelection> selectedText0 =
List<ExoTrackSelection> selectedText0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 0);
List<TrackSelection> selectedAudio0 =
List<ExoTrackSelection> selectedAudio0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 1);
List<TrackSelection> selectedVideo0 =
List<ExoTrackSelection> selectedVideo0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 2);
List<TrackSelection> selectedText1 =
List<ExoTrackSelection> selectedText1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 0);
List<TrackSelection> selectedAudio1 =
List<ExoTrackSelection> selectedAudio1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 1);
List<TrackSelection> selectedVideo1 =
List<ExoTrackSelection> selectedVideo1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 2);
assertSingleTrackSelectionEquals(selectedText0, trackGroupTextUs, 0);
@ -222,17 +221,17 @@ public class DownloadHelperTest {
// Clear only one period selection to verify second period selection is untouched.
downloadHelper.clearTrackSelections(/* periodIndex= */ 0);
List<TrackSelection> selectedText0 =
List<ExoTrackSelection> selectedText0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 0);
List<TrackSelection> selectedAudio0 =
List<ExoTrackSelection> selectedAudio0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 1);
List<TrackSelection> selectedVideo0 =
List<ExoTrackSelection> selectedVideo0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 2);
List<TrackSelection> selectedText1 =
List<ExoTrackSelection> selectedText1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 0);
List<TrackSelection> selectedAudio1 =
List<ExoTrackSelection> selectedAudio1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 1);
List<TrackSelection> selectedVideo1 =
List<ExoTrackSelection> selectedVideo1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 2);
assertThat(selectedText0).isEmpty();
@ -258,17 +257,17 @@ public class DownloadHelperTest {
// Replace only one period selection to verify second period selection is untouched.
downloadHelper.replaceTrackSelections(/* periodIndex= */ 0, parameters);
List<TrackSelection> selectedText0 =
List<ExoTrackSelection> selectedText0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 0);
List<TrackSelection> selectedAudio0 =
List<ExoTrackSelection> selectedAudio0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 1);
List<TrackSelection> selectedVideo0 =
List<ExoTrackSelection> selectedVideo0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 2);
List<TrackSelection> selectedText1 =
List<ExoTrackSelection> selectedText1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 0);
List<TrackSelection> selectedAudio1 =
List<ExoTrackSelection> selectedAudio1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 1);
List<TrackSelection> selectedVideo1 =
List<ExoTrackSelection> selectedVideo1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 2);
assertSingleTrackSelectionEquals(selectedText0, trackGroupTextZh, 0);
@ -294,17 +293,17 @@ public class DownloadHelperTest {
// Add only to one period selection to verify second period selection is untouched.
downloadHelper.addTrackSelection(/* periodIndex= */ 0, parameters);
List<TrackSelection> selectedText0 =
List<ExoTrackSelection> selectedText0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 0);
List<TrackSelection> selectedAudio0 =
List<ExoTrackSelection> selectedAudio0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 1);
List<TrackSelection> selectedVideo0 =
List<ExoTrackSelection> selectedVideo0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 2);
List<TrackSelection> selectedText1 =
List<ExoTrackSelection> selectedText1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 0);
List<TrackSelection> selectedAudio1 =
List<ExoTrackSelection> selectedAudio1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 1);
List<TrackSelection> selectedVideo1 =
List<ExoTrackSelection> selectedVideo1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 2);
assertSingleTrackSelectionEquals(selectedText0, trackGroupTextUs, 0);
@ -327,17 +326,17 @@ public class DownloadHelperTest {
// Add a non-default language, and a non-existing language (which will select the default).
downloadHelper.addAudioLanguagesToSelection("ZH", "Klingonese");
List<TrackSelection> selectedText0 =
List<ExoTrackSelection> selectedText0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 0);
List<TrackSelection> selectedAudio0 =
List<ExoTrackSelection> selectedAudio0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 1);
List<TrackSelection> selectedVideo0 =
List<ExoTrackSelection> selectedVideo0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 2);
List<TrackSelection> selectedText1 =
List<ExoTrackSelection> selectedText1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 0);
List<TrackSelection> selectedAudio1 =
List<ExoTrackSelection> selectedAudio1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 1);
List<TrackSelection> selectedVideo1 =
List<ExoTrackSelection> selectedVideo1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 2);
assertThat(selectedVideo0).isEmpty();
@ -361,17 +360,17 @@ public class DownloadHelperTest {
// Add a non-default language, and a non-existing language (which will select the default).
downloadHelper.addTextLanguagesToSelection(
/* selectUndeterminedTextLanguage= */ true, "ZH", "Klingonese");
List<TrackSelection> selectedText0 =
List<ExoTrackSelection> selectedText0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 0);
List<TrackSelection> selectedAudio0 =
List<ExoTrackSelection> selectedAudio0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 1);
List<TrackSelection> selectedVideo0 =
List<ExoTrackSelection> selectedVideo0 =
downloadHelper.getTrackSelections(/* periodIndex= */ 0, /* rendererIndex= */ 2);
List<TrackSelection> selectedText1 =
List<ExoTrackSelection> selectedText1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 0);
List<TrackSelection> selectedAudio1 =
List<ExoTrackSelection> selectedAudio1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 1);
List<TrackSelection> selectedVideo1 =
List<ExoTrackSelection> selectedVideo1 =
downloadHelper.getTrackSelections(/* periodIndex= */ 1, /* rendererIndex= */ 2);
assertThat(selectedVideo0).isEmpty();
@ -464,13 +463,13 @@ public class DownloadHelperTest {
}
private static void assertSingleTrackSelectionEquals(
List<TrackSelection> trackSelectionList, TrackGroup trackGroup, int... tracks) {
List<ExoTrackSelection> trackSelectionList, TrackGroup trackGroup, int... tracks) {
assertThat(trackSelectionList).hasSize(1);
assertTrackSelectionEquals(trackSelectionList.get(0), trackGroup, tracks);
}
private static void assertTrackSelectionEquals(
TrackSelection trackSelection, TrackGroup trackGroup, int... tracks) {
ExoTrackSelection trackSelection, TrackGroup trackGroup, int... tracks) {
assertThat(trackSelection.getTrackGroup()).isEqualTo(trackGroup);
assertThat(trackSelection.length()).isEqualTo(tracks.length);
int[] selectedTracksInGroup = new int[trackSelection.length()];
@ -498,9 +497,9 @@ public class DownloadHelperTest {
new EventDispatcher()
.withParameters(/* windowIndex= */ 0, id, /* mediaTimeOffsetMs= */ 0)) {
@Override
public List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) {
public List<StreamKey> getStreamKeys(List<ExoTrackSelection> trackSelections) {
List<StreamKey> result = new ArrayList<>();
for (TrackSelection trackSelection : trackSelections) {
for (ExoTrackSelection trackSelection : trackSelections) {
int groupIndex = trackGroupArrays[periodIndex].indexOf(trackSelection.getTrackGroup());
for (int i = 0; i < trackSelection.length(); i++) {
result.add(

View file

@ -29,8 +29,8 @@ import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.testutil.FakeMediaPeriod;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.trackselection.FixedTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.common.collect.ImmutableList;
import java.util.concurrent.CountDownLatch;
@ -72,13 +72,15 @@ public final class MergingMediaPeriodTest {
new MergingPeriodDefinition(
/* timeOffsetUs= */ 0, /* singleSampleTimeUs= */ 0, childFormat21, childFormat22));
TrackSelection selectionForChild1 =
ExoTrackSelection selectionForChild1 =
new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(1), /* track= */ 0);
TrackSelection selectionForChild2 =
ExoTrackSelection selectionForChild2 =
new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(2), /* track= */ 0);
SampleStream[] streams = new SampleStream[4];
mergingMediaPeriod.selectTracks(
/* selections= */ new TrackSelection[] {null, selectionForChild1, selectionForChild2, null},
/* selections= */ new ExoTrackSelection[] {
null, selectionForChild1, selectionForChild2, null
},
/* mayRetainStreamFlags= */ new boolean[] {false, false, false, false},
streams,
/* streamResetFlags= */ new boolean[] {false, false, false, false},
@ -117,13 +119,13 @@ public final class MergingMediaPeriodTest {
childFormat21,
childFormat22));
TrackSelection selectionForChild1 =
ExoTrackSelection selectionForChild1 =
new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(0), /* track= */ 0);
TrackSelection selectionForChild2 =
ExoTrackSelection selectionForChild2 =
new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(2), /* track= */ 0);
SampleStream[] streams = new SampleStream[2];
mergingMediaPeriod.selectTracks(
/* selections= */ new TrackSelection[] {selectionForChild1, selectionForChild2},
/* selections= */ new ExoTrackSelection[] {selectionForChild1, selectionForChild2},
/* mayRetainStreamFlags= */ new boolean[] {false, false},
streams,
/* streamResetFlags= */ new boolean[] {false, false},
@ -218,7 +220,7 @@ public final class MergingMediaPeriodTest {
@Override
public long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,

View file

@ -30,7 +30,7 @@ import com.google.android.exoplayer2.testutil.FakeClock;
import com.google.android.exoplayer2.testutil.FakeMediaChunk;
import com.google.android.exoplayer2.testutil.FakeTimeline;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection.AdaptationCheckpoint;
import com.google.android.exoplayer2.trackselection.TrackSelection.Definition;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.common.collect.ImmutableList;

View file

@ -138,7 +138,7 @@ public final class MappingTrackSelectorTest {
private MappedTrackInfo lastMappedTrackInfo;
@Override
protected Pair<RendererConfiguration[], TrackSelection[]> selectTracks(
protected Pair<RendererConfiguration[], ExoTrackSelection[]> selectTracks(
MappedTrackInfo mappedTrackInfo,
@Capabilities int[][][] rendererFormatSupports,
@AdaptiveSupport int[] rendererMixedMimeTypeAdaptationSupports,
@ -147,7 +147,7 @@ public final class MappingTrackSelectorTest {
int rendererCount = mappedTrackInfo.getRendererCount();
lastMappedTrackInfo = mappedTrackInfo;
return Pair.create(
new RendererConfiguration[rendererCount], new TrackSelection[rendererCount]);
new RendererConfiguration[rendererCount], new ExoTrackSelection[rendererCount]);
}
public void assertMappedTrackGroups(int rendererIndex, TrackGroup... expected) {

View file

@ -21,14 +21,12 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.source.chunk.ChunkSource;
import com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.upstream.TransferListener;
import java.util.List;
/**
* An {@link ChunkSource} for DASH streams.
*/
/** A {@link ChunkSource} for DASH streams. */
public interface DashChunkSource extends ChunkSource {
/** Factory for {@link DashChunkSource}s. */
@ -55,7 +53,7 @@ public interface DashChunkSource extends ChunkSource {
DashManifest manifest,
int periodIndex,
int[] adaptationSetIndices,
TrackSelection trackSelection,
ExoTrackSelection trackSelection,
int type,
long elapsedRealtimeOffsetMs,
boolean enableEventMessageTrack,
@ -76,5 +74,5 @@ public interface DashChunkSource extends ChunkSource {
*
* @param trackSelection The new track selection instance. Must be equivalent to the previous one.
*/
void updateTrackSelection(TrackSelection trackSelection);
void updateTrackSelection(ExoTrackSelection trackSelection);
}

View file

@ -47,7 +47,7 @@ import com.google.android.exoplayer2.source.dash.manifest.Descriptor;
import com.google.android.exoplayer2.source.dash.manifest.EventStream;
import com.google.android.exoplayer2.source.dash.manifest.Period;
import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
@ -213,10 +213,10 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
@Override
public List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) {
public List<StreamKey> getStreamKeys(List<ExoTrackSelection> trackSelections) {
List<AdaptationSet> manifestAdaptationSets = manifest.getPeriod(periodIndex).adaptationSets;
List<StreamKey> streamKeys = new ArrayList<>();
for (TrackSelection trackSelection : trackSelections) {
for (ExoTrackSelection trackSelection : trackSelections) {
int trackGroupIndex = trackGroups.indexOf(trackSelection.getTrackGroup());
TrackGroupInfo trackGroupInfo = trackGroupInfos[trackGroupIndex];
if (trackGroupInfo.trackGroupCategory != TrackGroupInfo.CATEGORY_PRIMARY) {
@ -256,7 +256,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
@Override
public long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
@ -356,7 +356,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
// Internal methods.
private int[] getStreamIndexToTrackGroupIndex(TrackSelection[] selections) {
private int[] getStreamIndexToTrackGroupIndex(ExoTrackSelection[] selections) {
int[] streamIndexToTrackGroupIndex = new int[selections.length];
for (int i = 0; i < selections.length; i++) {
if (selections[i] != null) {
@ -369,7 +369,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
private void releaseDisabledStreams(
TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams) {
ExoTrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams) {
for (int i = 0; i < selections.length; i++) {
if (selections[i] == null || !mayRetainStreamFlags[i]) {
if (streams[i] instanceof ChunkSampleStream) {
@ -386,7 +386,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
private void releaseOrphanEmbeddedStreams(
TrackSelection[] selections, SampleStream[] streams, int[] streamIndexToTrackGroupIndex) {
ExoTrackSelection[] selections, SampleStream[] streams, int[] streamIndexToTrackGroupIndex) {
for (int i = 0; i < selections.length; i++) {
if (streams[i] instanceof EmptySampleStream || streams[i] instanceof EmbeddedSampleStream) {
// We need to release an embedded stream if the corresponding primary stream is released.
@ -414,14 +414,14 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
private void selectNewStreams(
TrackSelection[] selections,
ExoTrackSelection[] selections,
SampleStream[] streams,
boolean[] streamResetFlags,
long positionUs,
int[] streamIndexToTrackGroupIndex) {
// Create newly selected primary and event streams.
for (int i = 0; i < selections.length; i++) {
TrackSelection selection = selections[i];
ExoTrackSelection selection = selections[i];
if (selection == null) {
continue;
}
@ -703,8 +703,11 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
return trackGroupCount;
}
private static void buildManifestEventTrackGroupInfos(List<EventStream> eventStreams,
TrackGroup[] trackGroups, TrackGroupInfo[] trackGroupInfos, int existingTrackGroupCount) {
private static void buildManifestEventTrackGroupInfos(
List<EventStream> eventStreams,
TrackGroup[] trackGroups,
TrackGroupInfo[] trackGroupInfos,
int existingTrackGroupCount) {
for (int i = 0; i < eventStreams.size(); i++) {
EventStream eventStream = eventStreams.get(i);
Format format =
@ -717,8 +720,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
}
private ChunkSampleStream<DashChunkSource> buildSampleStream(TrackGroupInfo trackGroupInfo,
TrackSelection selection, long positionUs) {
private ChunkSampleStream<DashChunkSource> buildSampleStream(
TrackGroupInfo trackGroupInfo, ExoTrackSelection selection, long positionUs) {
int embeddedTrackCount = 0;
boolean enableEventMessageTrack =
trackGroupInfo.embeddedEventMessageTrackGroupIndex != C.INDEX_UNSET;
@ -813,8 +816,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
return null;
}
private static boolean hasEventMessageTrack(List<AdaptationSet> adaptationSets,
int[] adaptationSetIndices) {
private static boolean hasEventMessageTrack(
List<AdaptationSet> adaptationSets, int[] adaptationSetIndices) {
for (int i : adaptationSetIndices) {
List<Representation> representations = adaptationSets.get(i).representations;
for (int j = 0; j < representations.size(); j++) {
@ -897,8 +900,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
public @interface TrackGroupCategory {}
/**
* A normal track group that has its samples drawn from the stream.
* For example: a video Track Group or an audio Track Group.
* A normal track group that has its samples drawn from the stream. For example: a video Track
* Group or an audio Track Group.
*/
private static final int CATEGORY_PRIMARY = 0;
@ -909,9 +912,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
private static final int CATEGORY_EMBEDDED = 1;
/**
* A track group that has its samples listed explicitly in the DASH manifest file.
* For example: an EventStream track has its sample (Events) included directly in the DASH
* manifest file.
* A track group that has its samples listed explicitly in the DASH manifest file. For example:
* an EventStream track has its sample (Events) included directly in the DASH manifest file.
*/
private static final int CATEGORY_MANIFEST_EVENTS = 2;
@ -940,8 +942,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
/* eventStreamGroupIndex= */ -1);
}
public static TrackGroupInfo embeddedEmsgTrack(int[] adaptationSetIndices,
int primaryTrackGroupIndex) {
public static TrackGroupInfo embeddedEmsgTrack(
int[] adaptationSetIndices, int primaryTrackGroupIndex) {
return new TrackGroupInfo(
C.TRACK_TYPE_METADATA,
CATEGORY_EMBEDDED,
@ -992,5 +994,4 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
this.eventStreamGroupIndex = eventStreamGroupIndex;
}
}
}

View file

@ -47,7 +47,7 @@ import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.source.dash.manifest.RangedUri;
import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException;
@ -84,7 +84,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
DashManifest manifest,
int periodIndex,
int[] adaptationSetIndices,
TrackSelection trackSelection,
ExoTrackSelection trackSelection,
int trackType,
long elapsedRealtimeOffsetMs,
boolean enableEventMessageTrack,
@ -122,7 +122,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
protected final RepresentationHolder[] representationHolders;
private TrackSelection trackSelection;
private ExoTrackSelection trackSelection;
private DashManifest manifest;
private int periodIndex;
@Nullable private IOException fatalError;
@ -152,7 +152,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
DashManifest manifest,
int periodIndex,
int[] adaptationSetIndices,
TrackSelection trackSelection,
ExoTrackSelection trackSelection,
int trackType,
DataSource dataSource,
long elapsedRealtimeOffsetMs,
@ -228,7 +228,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
}
@Override
public void updateTrackSelection(TrackSelection trackSelection) {
public void updateTrackSelection(ExoTrackSelection trackSelection) {
this.trackSelection = trackSelection;
}

View file

@ -37,7 +37,7 @@ import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist;
import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment;
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker;
import com.google.android.exoplayer2.trackselection.BaseTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.TransferListener;
@ -137,8 +137,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
// Note: The track group in the selection is typically *not* equal to trackGroup. This is due to
// the way in which HlsSampleStreamWrapper generates track groups. Use only index based methods
// in TrackSelection to avoid unexpected behavior.
private TrackSelection trackSelection;
// in ExoTrackSelection to avoid unexpected behavior.
private ExoTrackSelection trackSelection;
private long liveEdgeInPeriodTimeUs;
private boolean seenExpectedPlaylistError;
@ -219,14 +219,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Sets the current track selection.
*
* @param trackSelection The {@link TrackSelection}.
* @param trackSelection The {@link ExoTrackSelection}.
*/
public void setTrackSelection(TrackSelection trackSelection) {
public void setTrackSelection(ExoTrackSelection trackSelection) {
this.trackSelection = trackSelection;
}
/** Returns the current {@link TrackSelection}. */
public TrackSelection getTrackSelection() {
/** Returns the current {@link ExoTrackSelection}. */
public ExoTrackSelection getTrackSelection() {
return trackSelection;
}
@ -810,9 +810,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
// Private classes.
/**
* A {@link TrackSelection} to use for initialization.
*/
/** A {@link ExoTrackSelection} to use for initialization. */
private static final class InitializationTrackSelection extends BaseTrackSelection {
private int selectedIndex;

View file

@ -39,7 +39,7 @@ import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist;
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Rendition;
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Variant;
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
@ -177,7 +177,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
// null URLs, this method must be updated to calculate stream keys that are compatible with those
// that may already be persisted for offline.
@Override
public List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) {
public List<StreamKey> getStreamKeys(List<ExoTrackSelection> trackSelections) {
// See HlsMasterPlaylist.copy for interpretation of StreamKeys.
HlsMasterPlaylist masterPlaylist = Assertions.checkNotNull(playlistTracker.getMasterPlaylist());
boolean hasVariants = !masterPlaylist.variants.isEmpty();
@ -202,7 +202,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
List<StreamKey> streamKeys = new ArrayList<>();
boolean needsPrimaryTrackGroupSelection = false;
boolean hasPrimaryTrackGroupSelection = false;
for (TrackSelection trackSelection : trackSelections) {
for (ExoTrackSelection trackSelection : trackSelections) {
TrackGroup trackSelectionGroup = trackSelection.getTrackGroup();
int mainWrapperTrackGroupIndex = mainWrapperTrackGroups.indexOf(trackSelectionGroup);
if (mainWrapperTrackGroupIndex != C.INDEX_UNSET) {
@ -258,7 +258,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
@Override
public long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
@ -286,7 +286,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
// Select tracks for each child, copying the resulting streams back into a new streams array.
SampleStream[] newStreams = new SampleStream[selections.length];
@NullableType SampleStream[] childStreams = new SampleStream[selections.length];
@NullableType TrackSelection[] childSelections = new TrackSelection[selections.length];
@NullableType ExoTrackSelection[] childSelections = new ExoTrackSelection[selections.length];
int newEnabledSampleStreamWrapperCount = 0;
HlsSampleStreamWrapper[] newEnabledSampleStreamWrappers =
new HlsSampleStreamWrapper[sampleStreamWrappers.length];

View file

@ -53,7 +53,7 @@ import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.chunk.Chunk;
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataReader;
import com.google.android.exoplayer2.upstream.HttpDataSource;
@ -331,7 +331,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* part of the track selection.
*/
public boolean selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
@ -358,11 +358,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
: positionUs != lastSeekPositionUs);
// Get the old (i.e. current before the loop below executes) primary track selection. The new
// primary selection will equal the old one unless it's changed in the loop.
TrackSelection oldPrimaryTrackSelection = chunkSource.getTrackSelection();
TrackSelection primaryTrackSelection = oldPrimaryTrackSelection;
ExoTrackSelection oldPrimaryTrackSelection = chunkSource.getTrackSelection();
ExoTrackSelection primaryTrackSelection = oldPrimaryTrackSelection;
// Select new tracks.
for (int i = 0; i < selections.length; i++) {
TrackSelection selection = selections[i];
ExoTrackSelection selection = selections[i];
if (selection == null) {
continue;
}

View file

@ -34,7 +34,7 @@ import com.google.android.exoplayer2.source.chunk.MediaChunk;
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
@ -61,7 +61,7 @@ public class DefaultSsChunkSource implements SsChunkSource {
LoaderErrorThrower manifestLoaderErrorThrower,
SsManifest manifest,
int elementIndex,
TrackSelection trackSelection,
ExoTrackSelection trackSelection,
@Nullable TransferListener transferListener) {
DataSource dataSource = dataSourceFactory.createDataSource();
if (transferListener != null) {
@ -78,7 +78,7 @@ public class DefaultSsChunkSource implements SsChunkSource {
private final ChunkExtractor[] chunkExtractors;
private final DataSource dataSource;
private TrackSelection trackSelection;
private ExoTrackSelection trackSelection;
private SsManifest manifest;
private int currentManifestChunkOffset;
@ -95,7 +95,7 @@ public class DefaultSsChunkSource implements SsChunkSource {
LoaderErrorThrower manifestLoaderErrorThrower,
SsManifest manifest,
int streamElementIndex,
TrackSelection trackSelection,
ExoTrackSelection trackSelection,
DataSource dataSource) {
this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
this.manifest = manifest;
@ -163,7 +163,7 @@ public class DefaultSsChunkSource implements SsChunkSource {
}
@Override
public void updateTrackSelection(TrackSelection trackSelection) {
public void updateTrackSelection(ExoTrackSelection trackSelection) {
this.trackSelection = trackSelection;
}

View file

@ -18,13 +18,11 @@ package com.google.android.exoplayer2.source.smoothstreaming;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.source.chunk.ChunkSource;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.upstream.TransferListener;
/**
* A {@link ChunkSource} for SmoothStreaming.
*/
/** A {@link ChunkSource} for SmoothStreaming. */
public interface SsChunkSource extends ChunkSource {
/** Factory for {@link SsChunkSource}s. */
@ -45,7 +43,7 @@ public interface SsChunkSource extends ChunkSource {
LoaderErrorThrower manifestLoaderErrorThrower,
SsManifest manifest,
int streamElementIndex,
TrackSelection trackSelection,
ExoTrackSelection trackSelection,
@Nullable TransferListener transferListener);
}
@ -61,5 +59,5 @@ public interface SsChunkSource extends ChunkSource {
*
* @param trackSelection The new track selection instance. Must be equivalent to the previous one.
*/
void updateTrackSelection(TrackSelection trackSelection);
void updateTrackSelection(ExoTrackSelection trackSelection);
}

View file

@ -31,7 +31,7 @@ import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.chunk.ChunkSampleStream;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
@ -123,7 +123,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
@Override
public long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
@ -156,10 +156,10 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
@Override
public List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) {
public List<StreamKey> getStreamKeys(List<ExoTrackSelection> trackSelections) {
List<StreamKey> streamKeys = new ArrayList<>();
for (int selectionIndex = 0; selectionIndex < trackSelections.size(); selectionIndex++) {
TrackSelection trackSelection = trackSelections.get(selectionIndex);
ExoTrackSelection trackSelection = trackSelections.get(selectionIndex);
int streamElementIndex = trackGroups.indexOf(trackSelection.getTrackGroup());
for (int i = 0; i < trackSelection.length(); i++) {
streamKeys.add(new StreamKey(streamElementIndex, trackSelection.getIndexInTrackGroup(i)));
@ -232,16 +232,12 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
// Private methods.
private ChunkSampleStream<SsChunkSource> buildSampleStream(TrackSelection selection,
long positionUs) {
private ChunkSampleStream<SsChunkSource> buildSampleStream(
ExoTrackSelection selection, long positionUs) {
int streamElementIndex = trackGroups.indexOf(selection.getTrackGroup());
SsChunkSource chunkSource =
chunkSourceFactory.createChunkSource(
manifestLoaderErrorThrower,
manifest,
streamElementIndex,
selection,
transferListener);
manifestLoaderErrorThrower, manifest, streamElementIndex, selection, transferListener);
return new ChunkSampleStream<>(
manifest.streamElements[streamElementIndex].type,
null,

View file

@ -46,9 +46,9 @@ import com.google.android.exoplayer2.testutil.ExoHostedTest;
import com.google.android.exoplayer2.testutil.HostActivity;
import com.google.android.exoplayer2.testutil.HostActivity.HostedTest;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.RandomTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
@ -386,7 +386,7 @@ import java.util.List;
}
@Override
protected TrackSelection.Definition[] selectAllTracks(
protected ExoTrackSelection.Definition[] selectAllTracks(
MappedTrackInfo mappedTrackInfo,
int[][][] rendererFormatSupports,
int[] rendererMixedMimeTypeAdaptationSupports,
@ -399,10 +399,10 @@ import java.util.List;
TrackGroupArray audioTrackGroups = mappedTrackInfo.getTrackGroups(AUDIO_RENDERER_INDEX);
Assertions.checkState(videoTrackGroups.length == 1);
Assertions.checkState(audioTrackGroups.length == 1);
TrackSelection.Definition[] definitions =
new TrackSelection.Definition[mappedTrackInfo.getRendererCount()];
ExoTrackSelection.Definition[] definitions =
new ExoTrackSelection.Definition[mappedTrackInfo.getRendererCount()];
definitions[VIDEO_RENDERER_INDEX] =
new TrackSelection.Definition(
new ExoTrackSelection.Definition(
videoTrackGroups.get(0),
getVideoTrackIndices(
videoTrackGroups.get(0),
@ -410,7 +410,7 @@ import java.util.List;
videoFormatIds,
canIncludeAdditionalVideoFormats));
definitions[AUDIO_RENDERER_INDEX] =
new TrackSelection.Definition(
new ExoTrackSelection.Definition(
audioTrackGroups.get(0), getTrackIndex(audioTrackGroups.get(0), audioFormatId));
includedAdditionalVideoFormats =
definitions[VIDEO_RENDERER_INDEX].tracks.length > videoFormatIds.length;

View file

@ -33,7 +33,7 @@ import com.google.android.exoplayer2.source.SequenceableLoader;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.chunk.ChunkSampleStream;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
@ -143,7 +143,7 @@ public class FakeAdaptiveMediaPeriod
@SuppressWarnings({"unchecked", "rawtypes"}) // Casting sample streams created by this class.
@Override
public long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
@ -157,7 +157,7 @@ public class FakeAdaptiveMediaPeriod
streams[i] = null;
}
if (streams[i] == null && selections[i] != null) {
TrackSelection selection = selections[i];
ExoTrackSelection selection = selections[i];
assertThat(selection.length()).isAtLeast(1);
TrackGroup trackGroup = selection.getTrackGroup();
assertThat(trackGroupArray.indexOf(trackGroup)).isNotEqualTo(C.INDEX_UNSET);

View file

@ -27,7 +27,7 @@ import com.google.android.exoplayer2.source.chunk.MediaChunk;
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
import com.google.android.exoplayer2.source.chunk.SingleSampleMediaChunk;
import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData.Segment;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.TransferListener;
@ -55,7 +55,7 @@ public final class FakeChunkSource implements ChunkSource {
}
public FakeChunkSource createChunkSource(
TrackSelection trackSelection,
ExoTrackSelection trackSelection,
long durationUs,
@Nullable TransferListener transferListener) {
FakeAdaptiveDataSet dataSet =
@ -70,12 +70,12 @@ public final class FakeChunkSource implements ChunkSource {
}
private final TrackSelection trackSelection;
private final ExoTrackSelection trackSelection;
private final DataSource dataSource;
private final FakeAdaptiveDataSet dataSet;
public FakeChunkSource(TrackSelection trackSelection, DataSource dataSource,
FakeAdaptiveDataSet dataSet) {
public FakeChunkSource(
ExoTrackSelection trackSelection, DataSource dataSource, FakeAdaptiveDataSet dataSet) {
this.trackSelection = trackSelection;
this.dataSource = dataSource;
this.dataSet = dataSet;

View file

@ -38,7 +38,7 @@ import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Util;
@ -187,8 +187,8 @@ public class FakeMediaPeriod implements MediaPeriod {
}
/**
* Sets a discontinuity position to be returned from the next call to
* {@link #readDiscontinuity()}.
* Sets a discontinuity position to be returned from the next call to {@link
* #readDiscontinuity()}.
*
* @param discontinuityPositionUs The position to be returned, in microseconds.
*/
@ -196,9 +196,7 @@ public class FakeMediaPeriod implements MediaPeriod {
this.discontinuityPositionUs = discontinuityPositionUs;
}
/**
* Allows the fake media period to complete preparation. May be called on any thread.
*/
/** Allows the fake media period to complete preparation. May be called on any thread. */
public synchronized void setPreparationComplete() {
deferOnPrepared = false;
if (playerHandler != null && prepareCallback != null) {
@ -256,7 +254,7 @@ public class FakeMediaPeriod implements MediaPeriod {
@Override
public long selectTracks(
@NullableType TrackSelection[] selections,
@NullableType ExoTrackSelection[] selections,
boolean[] mayRetainStreamFlags,
@NullableType SampleStream[] streams,
boolean[] streamResetFlags,
@ -270,7 +268,7 @@ public class FakeMediaPeriod implements MediaPeriod {
streams[i] = null;
}
if (streams[i] == null && selections[i] != null) {
TrackSelection selection = selections[i];
ExoTrackSelection selection = selections[i];
assertThat(selection.length()).isAtLeast(1);
TrackGroup trackGroup = selection.getTrackGroup();
assertThat(trackGroupArray.indexOf(trackGroup) != C.INDEX_UNSET).isTrue();

View file

@ -23,14 +23,14 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.chunk.MediaChunk;
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import java.util.List;
/**
* A fake {@link TrackSelection} that only returns 1 fixed track, and allows querying the number of
* calls to its methods.
* A fake {@link ExoTrackSelection} that only returns 1 fixed track, and allows querying the number
* of calls to its methods.
*/
public final class FakeTrackSelection implements TrackSelection {
public final class FakeTrackSelection implements ExoTrackSelection {
private final TrackGroup rendererTrackGroup;

View file

@ -23,8 +23,8 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import java.util.ArrayList;
import java.util.List;
@ -41,8 +41,8 @@ public class FakeTrackSelector extends DefaultTrackSelector {
/**
* @param mayReuseTrackSelection Whether this {@link FakeTrackSelector} will reuse {@link
* TrackSelection}s during track selection, when it finds previously-selected track selection
* using the same {@link TrackGroup}.
* ExoTrackSelection}s during track selection, when it finds previously-selected track
* selection using the same {@link TrackGroup}.
*/
public FakeTrackSelector(boolean mayReuseTrackSelection) {
this(new FakeTrackSelectionFactory(mayReuseTrackSelection));
@ -54,18 +54,18 @@ public class FakeTrackSelector extends DefaultTrackSelector {
}
@Override
protected TrackSelection.@NullableType Definition[] selectAllTracks(
protected ExoTrackSelection.@NullableType Definition[] selectAllTracks(
MappedTrackInfo mappedTrackInfo,
@Capabilities int[][][] rendererFormatSupports,
@AdaptiveSupport int[] rendererMixedMimeTypeAdaptationSupports,
Parameters params) {
int rendererCount = mappedTrackInfo.getRendererCount();
TrackSelection.@NullableType Definition[] definitions =
new TrackSelection.Definition[rendererCount];
ExoTrackSelection.@NullableType Definition[] definitions =
new ExoTrackSelection.Definition[rendererCount];
for (int i = 0; i < rendererCount; i++) {
TrackGroupArray trackGroupArray = mappedTrackInfo.getTrackGroups(i);
boolean hasTracks = trackGroupArray.length > 0;
definitions[i] = hasTracks ? new TrackSelection.Definition(trackGroupArray.get(0)) : null;
definitions[i] = hasTracks ? new ExoTrackSelection.Definition(trackGroupArray.get(0)) : null;
}
return definitions;
}
@ -75,7 +75,7 @@ public class FakeTrackSelector extends DefaultTrackSelector {
return fakeTrackSelectionFactory.trackSelections;
}
private static class FakeTrackSelectionFactory implements TrackSelection.Factory {
private static class FakeTrackSelectionFactory implements ExoTrackSelection.Factory {
private final List<FakeTrackSelection> trackSelections;
private final boolean mayReuseTrackSelection;
@ -86,14 +86,14 @@ public class FakeTrackSelector extends DefaultTrackSelector {
}
@Override
public TrackSelection[] createTrackSelections(
TrackSelection.@NullableType Definition[] definitions,
public ExoTrackSelection[] createTrackSelections(
ExoTrackSelection.@NullableType Definition[] definitions,
BandwidthMeter bandwidthMeter,
MediaPeriodId mediaPeriodId,
Timeline timeline) {
TrackSelection[] selections = new TrackSelection[definitions.length];
ExoTrackSelection[] selections = new ExoTrackSelection[definitions.length];
for (int i = 0; i < definitions.length; i++) {
TrackSelection.Definition definition = definitions[i];
ExoTrackSelection.Definition definition = definitions[i];
if (definition != null) {
selections[i] = createTrackSelection(definition.group);
}
@ -101,7 +101,7 @@ public class FakeTrackSelector extends DefaultTrackSelector {
return selections;
}
private TrackSelection createTrackSelection(TrackGroup trackGroup) {
private ExoTrackSelection createTrackSelection(TrackGroup trackGroup) {
if (mayReuseTrackSelection) {
for (FakeTrackSelection trackSelection : trackSelections) {
if (trackSelection.getTrackGroup().equals(trackGroup)) {

View file

@ -29,7 +29,7 @@ import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.chunk.MediaChunk;
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
import com.google.android.exoplayer2.trackselection.BaseTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.util.ConditionVariable;
import java.util.ArrayList;
import java.util.Arrays;
@ -102,7 +102,7 @@ public final class MediaPeriodAsserts {
// - One selection with one track per group, two tracks or all tracks.
// - Two selections with tracks from multiple groups, or tracks from a single group.
// - Multiple selections with tracks from all groups.
List<List<TrackSelection>> testSelections = new ArrayList<>();
List<List<ExoTrackSelection>> testSelections = new ArrayList<>();
for (int i = 0; i < trackGroupArray.length; i++) {
TrackGroup trackGroup = trackGroupArray.get(i);
for (int j = 0; j < trackGroup.length; j++) {
@ -112,7 +112,7 @@ public final class MediaPeriodAsserts {
testSelections.add(Collections.singletonList(new TestTrackSelection(trackGroup, 0, 1)));
testSelections.add(
Arrays.asList(
new TrackSelection[] {
new ExoTrackSelection[] {
new TestTrackSelection(trackGroup, 0), new TestTrackSelection(trackGroup, 1)
}));
}
@ -130,7 +130,7 @@ public final class MediaPeriodAsserts {
for (int j = i + 1; j < trackGroupArray.length; j++) {
testSelections.add(
Arrays.asList(
new TrackSelection[] {
new ExoTrackSelection[] {
new TestTrackSelection(trackGroupArray.get(i), 0),
new TestTrackSelection(trackGroupArray.get(j), 0)
}));
@ -138,7 +138,7 @@ public final class MediaPeriodAsserts {
}
}
if (trackGroupArray.length > 2) {
List<TrackSelection> selectionsFromAllGroups = new ArrayList<>();
List<ExoTrackSelection> selectionsFromAllGroups = new ArrayList<>();
for (int i = 0; i < trackGroupArray.length; i++) {
selectionsFromAllGroups.add(new TestTrackSelection(trackGroupArray.get(i), 0));
}
@ -147,7 +147,7 @@ public final class MediaPeriodAsserts {
// Verify for each case that stream keys can be used to create filtered tracks which still
// contain at least all requested formats.
for (List<TrackSelection> testSelection : testSelections) {
for (List<ExoTrackSelection> testSelection : testSelections) {
List<StreamKey> streamKeys = mediaPeriod.getStreamKeys(testSelection);
if (streamKeys.isEmpty()) {
// Manifests won't be filtered if stream key is empty.
@ -158,7 +158,7 @@ public final class MediaPeriodAsserts {
MediaPeriod filteredMediaPeriod =
mediaPeriodFactory.createMediaPeriod(filteredManifest, /* periodIndex= */ 0);
TrackGroupArray filteredTrackGroupArray = prepareAndGetTrackGroups(filteredMediaPeriod);
for (TrackSelection trackSelection : testSelection) {
for (ExoTrackSelection trackSelection : testSelection) {
if (ignoredMimeType != null
&& ignoredMimeType.equals(trackSelection.getFormat(0).sampleMimeType)) {
continue;