Rename TracksInfo and TrackGroupInfo

1. TracksInfo is renamed to Tracks
2. TracksInfo.TrackGroupInfo is renamed to Tracks.Group

PiperOrigin-RevId: 441232373
This commit is contained in:
olly 2022-04-12 18:47:49 +01:00 committed by Ian Baker
parent af8435816a
commit 83daa052cb
41 changed files with 522 additions and 536 deletions

View File

@ -15,6 +15,10 @@
* Track selection: * Track selection:
* Flatten `TrackSelectionOverrides` class into `TrackSelectionParameters`, * Flatten `TrackSelectionOverrides` class into `TrackSelectionParameters`,
and promote `TrackSelectionOverride` to a top level class. and promote `TrackSelectionOverride` to a top level class.
* Rename `TracksInfo` to `Tracks` and `TracksInfo.TrackGroupInfo` to
`Tracks.Group`. `Player.getCurrentTracksInfo` and
`Player.Listener.onTracksInfoChanged` have also been renamed to
`Player.getCurrentTracks` and `Player.Listener.onTracksChanged`.
* Video: * Video:
* Rename `DummySurface` to `PlaceHolderSurface`. * Rename `DummySurface` to `PlaceHolderSurface`.
* Audio: * Audio:

View File

@ -26,7 +26,7 @@ import androidx.media3.common.Player;
import androidx.media3.common.Player.DiscontinuityReason; import androidx.media3.common.Player.DiscontinuityReason;
import androidx.media3.common.Player.TimelineChangeReason; import androidx.media3.common.Player.TimelineChangeReason;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.ui.PlayerControlView; import androidx.media3.ui.PlayerControlView;
import androidx.media3.ui.PlayerView; import androidx.media3.ui.PlayerView;
@ -57,7 +57,7 @@ import java.util.ArrayList;
private final ArrayList<MediaItem> mediaQueue; private final ArrayList<MediaItem> mediaQueue;
private final Listener listener; private final Listener listener;
private TracksInfo lastSeenTrackGroupInfo; private Tracks lastSeenTracks;
private int currentItemIndex; private int currentItemIndex;
private Player currentPlayer; private Player currentPlayer;
@ -219,19 +219,19 @@ import java.util.ArrayList;
} }
@Override @Override
public void onTracksInfoChanged(TracksInfo tracksInfo) { public void onTracksChanged(Tracks tracks) {
if (currentPlayer != localPlayer || tracksInfo == lastSeenTrackGroupInfo) { if (currentPlayer != localPlayer || tracks == lastSeenTracks) {
return; return;
} }
if (tracksInfo.containsType(C.TRACK_TYPE_VIDEO) if (tracks.containsType(C.TRACK_TYPE_VIDEO)
&& !tracksInfo.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) { && !tracks.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
listener.onUnsupportedTrack(C.TRACK_TYPE_VIDEO); listener.onUnsupportedTrack(C.TRACK_TYPE_VIDEO);
} }
if (tracksInfo.containsType(C.TRACK_TYPE_AUDIO) if (tracks.containsType(C.TRACK_TYPE_AUDIO)
&& !tracksInfo.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) { && !tracks.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
listener.onUnsupportedTrack(C.TRACK_TYPE_AUDIO); listener.onUnsupportedTrack(C.TRACK_TYPE_AUDIO);
} }
lastSeenTrackGroupInfo = tracksInfo; lastSeenTracks = tracks;
} }
// CastPlayer.SessionAvailabilityListener implementation. // CastPlayer.SessionAvailabilityListener implementation.

View File

@ -31,7 +31,7 @@ import androidx.media3.common.Format;
import androidx.media3.common.MediaItem; import androidx.media3.common.MediaItem;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.util.Log; import androidx.media3.common.util.Log;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DataSource;
@ -303,17 +303,17 @@ public class DownloadTracker {
return; return;
} }
TracksInfo tracksInfo = downloadHelper.getTracksInfo(/* periodIndex= */ 0); Tracks tracks = downloadHelper.getTracks(/* periodIndex= */ 0);
if (!TrackSelectionDialog.willHaveContent(tracksInfo)) { if (!TrackSelectionDialog.willHaveContent(tracks)) {
Log.d(TAG, "No dialog content. Downloading entire stream."); Log.d(TAG, "No dialog content. Downloading entire stream.");
startDownload(); startDownload();
downloadHelper.release(); downloadHelper.release();
return; return;
} }
trackSelectionDialog = trackSelectionDialog =
TrackSelectionDialog.createForTracksInfoAndParameters( TrackSelectionDialog.createForTracksAndParameters(
/* titleId= */ R.string.exo_download_description, /* titleId= */ R.string.exo_download_description,
tracksInfo, tracks,
DownloadHelper.getDefaultTrackSelectorParameters(context), DownloadHelper.getDefaultTrackSelectorParameters(context),
/* allowAdaptiveSelections= */ false, /* allowAdaptiveSelections= */ false,
/* allowMultipleOverrides= */ true, /* allowMultipleOverrides= */ true,

View File

@ -37,7 +37,7 @@ import androidx.media3.common.MediaItem;
import androidx.media3.common.PlaybackException; import androidx.media3.common.PlaybackException;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DataSource;
import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.ExoPlayer;
@ -83,7 +83,7 @@ public class PlayerActivity extends AppCompatActivity
private List<MediaItem> mediaItems; private List<MediaItem> mediaItems;
private TrackSelectionParameters trackSelectionParameters; private TrackSelectionParameters trackSelectionParameters;
private DebugTextViewHelper debugViewHelper; private DebugTextViewHelper debugViewHelper;
private TracksInfo lastSeenTracksInfo; private Tracks lastSeenTracks;
private boolean startAutoPlay; private boolean startAutoPlay;
private int startItemIndex; private int startItemIndex;
private long startPosition; private long startPosition;
@ -276,7 +276,7 @@ public class PlayerActivity extends AppCompatActivity
RenderersFactory renderersFactory = RenderersFactory renderersFactory =
DemoUtil.buildRenderersFactory(/* context= */ this, preferExtensionDecoders); DemoUtil.buildRenderersFactory(/* context= */ this, preferExtensionDecoders);
lastSeenTracksInfo = TracksInfo.EMPTY; lastSeenTracks = Tracks.EMPTY;
player = player =
new ExoPlayer.Builder(/* context= */ this) new ExoPlayer.Builder(/* context= */ this)
.setRenderersFactory(renderersFactory) .setRenderersFactory(renderersFactory)
@ -456,22 +456,20 @@ public class PlayerActivity extends AppCompatActivity
@Override @Override
@SuppressWarnings("ReferenceEquality") @SuppressWarnings("ReferenceEquality")
public void onTracksInfoChanged(TracksInfo tracksInfo) { public void onTracksChanged(Tracks tracks) {
updateButtonVisibility(); updateButtonVisibility();
if (tracksInfo == lastSeenTracksInfo) { if (tracks == lastSeenTracks) {
return; return;
} }
if (tracksInfo.containsType(C.TRACK_TYPE_VIDEO) if (tracks.containsType(C.TRACK_TYPE_VIDEO)
&& !tracksInfo.isTypeSupported( && !tracks.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
showToast(R.string.error_unsupported_video); showToast(R.string.error_unsupported_video);
} }
if (tracksInfo.containsType(C.TRACK_TYPE_AUDIO) if (tracks.containsType(C.TRACK_TYPE_AUDIO)
&& !tracksInfo.isTypeSupported( && !tracks.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
showToast(R.string.error_unsupported_audio); showToast(R.string.error_unsupported_audio);
} }
lastSeenTracksInfo = tracksInfo; lastSeenTracks = tracks;
} }
} }

View File

@ -35,8 +35,7 @@ import androidx.media3.common.Player;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionOverride; import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.media3.ui.TrackSelectionView; import androidx.media3.ui.TrackSelectionView;
import androidx.viewpager.widget.ViewPager; import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayout;
@ -79,16 +78,16 @@ public final class TrackSelectionDialog extends DialogFragment {
* specified {@link Player}. * specified {@link Player}.
*/ */
public static boolean willHaveContent(Player player) { public static boolean willHaveContent(Player player) {
return willHaveContent(player.getCurrentTracksInfo()); return willHaveContent(player.getCurrentTracks());
} }
/** /**
* Returns whether a track selection dialog will have content to display if initialized with the * Returns whether a track selection dialog will have content to display if initialized with the
* specified {@link TracksInfo}. * specified {@link Tracks}.
*/ */
public static boolean willHaveContent(TracksInfo tracksInfo) { public static boolean willHaveContent(Tracks tracks) {
for (TrackGroupInfo trackGroupInfo : tracksInfo.getTrackGroupInfos()) { for (Tracks.Group trackGroup : tracks.getGroups()) {
if (SUPPORTED_TRACK_TYPES.contains(trackGroupInfo.getTrackType())) { if (SUPPORTED_TRACK_TYPES.contains(trackGroup.getType())) {
return true; return true;
} }
} }
@ -105,9 +104,9 @@ public final class TrackSelectionDialog extends DialogFragment {
*/ */
public static TrackSelectionDialog createForPlayer( public static TrackSelectionDialog createForPlayer(
Player player, DialogInterface.OnDismissListener onDismissListener) { Player player, DialogInterface.OnDismissListener onDismissListener) {
return createForTracksInfoAndParameters( return createForTracksAndParameters(
R.string.track_selection_title, R.string.track_selection_title,
player.getCurrentTracksInfo(), player.getCurrentTracks(),
player.getTrackSelectionParameters(), player.getTrackSelectionParameters(),
/* allowAdaptiveSelections= */ true, /* allowAdaptiveSelections= */ true,
/* allowMultipleOverrides= */ false, /* allowMultipleOverrides= */ false,
@ -116,10 +115,10 @@ public final class TrackSelectionDialog extends DialogFragment {
} }
/** /**
* Creates a dialog for given {@link TracksInfo} and {@link TrackSelectionParameters}. * Creates a dialog for given {@link Tracks} and {@link TrackSelectionParameters}.
* *
* @param titleId The resource id of the dialog title. * @param titleId The resource id of the dialog title.
* @param tracksInfo The {@link TracksInfo} describing the tracks to display. * @param tracks The {@link Tracks} describing the tracks to display.
* @param trackSelectionParameters The initial {@link TrackSelectionParameters}. * @param trackSelectionParameters The initial {@link TrackSelectionParameters}.
* @param allowAdaptiveSelections Whether adaptive selections (consisting of more than one track) * @param allowAdaptiveSelections Whether adaptive selections (consisting of more than one track)
* can be made. * can be made.
@ -128,9 +127,9 @@ public final class TrackSelectionDialog extends DialogFragment {
* @param onDismissListener {@link DialogInterface.OnDismissListener} called when the dialog is * @param onDismissListener {@link DialogInterface.OnDismissListener} called when the dialog is
* dismissed. * dismissed.
*/ */
public static TrackSelectionDialog createForTracksInfoAndParameters( public static TrackSelectionDialog createForTracksAndParameters(
int titleId, int titleId,
TracksInfo tracksInfo, Tracks tracks,
TrackSelectionParameters trackSelectionParameters, TrackSelectionParameters trackSelectionParameters,
boolean allowAdaptiveSelections, boolean allowAdaptiveSelections,
boolean allowMultipleOverrides, boolean allowMultipleOverrides,
@ -138,7 +137,7 @@ public final class TrackSelectionDialog extends DialogFragment {
DialogInterface.OnDismissListener onDismissListener) { DialogInterface.OnDismissListener onDismissListener) {
TrackSelectionDialog trackSelectionDialog = new TrackSelectionDialog(); TrackSelectionDialog trackSelectionDialog = new TrackSelectionDialog();
trackSelectionDialog.init( trackSelectionDialog.init(
tracksInfo, tracks,
trackSelectionParameters, trackSelectionParameters,
titleId, titleId,
allowAdaptiveSelections, allowAdaptiveSelections,
@ -169,7 +168,7 @@ public final class TrackSelectionDialog extends DialogFragment {
} }
private void init( private void init(
TracksInfo tracksInfo, Tracks tracks,
TrackSelectionParameters trackSelectionParameters, TrackSelectionParameters trackSelectionParameters,
int titleId, int titleId,
boolean allowAdaptiveSelections, boolean allowAdaptiveSelections,
@ -182,16 +181,16 @@ public final class TrackSelectionDialog extends DialogFragment {
for (int i = 0; i < SUPPORTED_TRACK_TYPES.size(); i++) { for (int i = 0; i < SUPPORTED_TRACK_TYPES.size(); i++) {
@C.TrackType int trackType = SUPPORTED_TRACK_TYPES.get(i); @C.TrackType int trackType = SUPPORTED_TRACK_TYPES.get(i);
ArrayList<TrackGroupInfo> trackGroupInfos = new ArrayList<>(); ArrayList<Tracks.Group> trackGroups = new ArrayList<>();
for (TrackGroupInfo trackGroupInfo : tracksInfo.getTrackGroupInfos()) { for (Tracks.Group trackGroup : tracks.getGroups()) {
if (trackGroupInfo.getTrackType() == trackType) { if (trackGroup.getType() == trackType) {
trackGroupInfos.add(trackGroupInfo); trackGroups.add(trackGroup);
} }
} }
if (!trackGroupInfos.isEmpty()) { if (!trackGroups.isEmpty()) {
TrackSelectionViewFragment tabFragment = new TrackSelectionViewFragment(); TrackSelectionViewFragment tabFragment = new TrackSelectionViewFragment();
tabFragment.init( tabFragment.init(
trackGroupInfos, trackGroups,
trackSelectionParameters.disabledTrackTypes.contains(trackType), trackSelectionParameters.disabledTrackTypes.contains(trackType),
trackSelectionParameters.overrides, trackSelectionParameters.overrides,
allowAdaptiveSelections, allowAdaptiveSelections,
@ -300,7 +299,7 @@ public final class TrackSelectionDialog extends DialogFragment {
public static final class TrackSelectionViewFragment extends Fragment public static final class TrackSelectionViewFragment extends Fragment
implements TrackSelectionView.TrackSelectionListener { implements TrackSelectionView.TrackSelectionListener {
private List<TrackGroupInfo> trackGroupInfos; private List<Tracks.Group> trackGroups;
private boolean allowAdaptiveSelections; private boolean allowAdaptiveSelections;
private boolean allowMultipleOverrides; private boolean allowMultipleOverrides;
@ -313,12 +312,12 @@ public final class TrackSelectionDialog extends DialogFragment {
} }
public void init( public void init(
List<TrackGroupInfo> trackGroupInfos, List<Tracks.Group> trackGroups,
boolean isDisabled, boolean isDisabled,
Map<TrackGroup, TrackSelectionOverride> overrides, Map<TrackGroup, TrackSelectionOverride> overrides,
boolean allowAdaptiveSelections, boolean allowAdaptiveSelections,
boolean allowMultipleOverrides) { boolean allowMultipleOverrides) {
this.trackGroupInfos = trackGroupInfos; this.trackGroups = trackGroups;
this.isDisabled = isDisabled; this.isDisabled = isDisabled;
this.allowAdaptiveSelections = allowAdaptiveSelections; this.allowAdaptiveSelections = allowAdaptiveSelections;
this.allowMultipleOverrides = allowMultipleOverrides; this.allowMultipleOverrides = allowMultipleOverrides;
@ -326,8 +325,7 @@ public final class TrackSelectionDialog extends DialogFragment {
// handle the case where the TrackSelectionView is never created. // handle the case where the TrackSelectionView is never created.
this.overrides = this.overrides =
new HashMap<>( new HashMap<>(
TrackSelectionView.filterOverrides( TrackSelectionView.filterOverrides(overrides, trackGroups, allowMultipleOverrides));
overrides, trackGroupInfos, allowMultipleOverrides));
} }
@Override @Override
@ -343,7 +341,7 @@ public final class TrackSelectionDialog extends DialogFragment {
trackSelectionView.setAllowMultipleOverrides(allowMultipleOverrides); trackSelectionView.setAllowMultipleOverrides(allowMultipleOverrides);
trackSelectionView.setAllowAdaptiveSelections(allowAdaptiveSelections); trackSelectionView.setAllowAdaptiveSelections(allowAdaptiveSelections);
trackSelectionView.init( trackSelectionView.init(
trackGroupInfos, trackGroups,
isDisabled, isDisabled,
overrides, overrides,
/* trackFormatComparator= */ null, /* trackFormatComparator= */ null,

View File

@ -40,8 +40,7 @@ import androidx.media3.common.Player;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue; import androidx.media3.common.text.Cue;
import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Assertions;
@ -136,7 +135,7 @@ public final class CastPlayer extends BasePlayer {
private final StateHolder<PlaybackParameters> playbackParameters; private final StateHolder<PlaybackParameters> playbackParameters;
@Nullable private RemoteMediaClient remoteMediaClient; @Nullable private RemoteMediaClient remoteMediaClient;
private CastTimeline currentTimeline; private CastTimeline currentTimeline;
private TracksInfo currentTracksInfo; private Tracks currentTracks;
private Commands availableCommands; private Commands availableCommands;
private @Player.State int playbackState; private @Player.State int playbackState;
private int currentWindowIndex; private int currentWindowIndex;
@ -212,7 +211,7 @@ public final class CastPlayer extends BasePlayer {
playbackParameters = new StateHolder<>(PlaybackParameters.DEFAULT); playbackParameters = new StateHolder<>(PlaybackParameters.DEFAULT);
playbackState = STATE_IDLE; playbackState = STATE_IDLE;
currentTimeline = CastTimeline.EMPTY_CAST_TIMELINE; currentTimeline = CastTimeline.EMPTY_CAST_TIMELINE;
currentTracksInfo = TracksInfo.EMPTY; currentTracks = Tracks.EMPTY;
availableCommands = new Commands.Builder().addAll(PERMANENT_AVAILABLE_COMMANDS).build(); availableCommands = new Commands.Builder().addAll(PERMANENT_AVAILABLE_COMMANDS).build();
pendingSeekWindowIndex = C.INDEX_UNSET; pendingSeekWindowIndex = C.INDEX_UNSET;
pendingSeekPositionMs = C.TIME_UNSET; pendingSeekPositionMs = C.TIME_UNSET;
@ -544,8 +543,8 @@ public final class CastPlayer extends BasePlayer {
} }
@Override @Override
public TracksInfo getCurrentTracksInfo() { public Tracks getCurrentTracks() {
return currentTracksInfo; return currentTracks;
} }
@Override @Override
@ -818,7 +817,7 @@ public final class CastPlayer extends BasePlayer {
} }
if (updateTracksAndSelectionsAndNotifyIfChanged()) { if (updateTracksAndSelectionsAndNotifyIfChanged()) {
listeners.queueEvent( listeners.queueEvent(
Player.EVENT_TRACKS_CHANGED, listener -> listener.onTracksInfoChanged(currentTracksInfo)); Player.EVENT_TRACKS_CHANGED, listener -> listener.onTracksChanged(currentTracks));
} }
updateAvailableCommandsAndNotifyIfChanged(); updateAvailableCommandsAndNotifyIfChanged();
listeners.flushEvents(); listeners.flushEvents();
@ -978,8 +977,8 @@ public final class CastPlayer extends BasePlayer {
@Nullable @Nullable
List<MediaTrack> castMediaTracks = mediaInfo != null ? mediaInfo.getMediaTracks() : null; List<MediaTrack> castMediaTracks = mediaInfo != null ? mediaInfo.getMediaTracks() : null;
if (castMediaTracks == null || castMediaTracks.isEmpty()) { if (castMediaTracks == null || castMediaTracks.isEmpty()) {
boolean hasChanged = !TracksInfo.EMPTY.equals(currentTracksInfo); boolean hasChanged = !Tracks.EMPTY.equals(currentTracks);
currentTracksInfo = TracksInfo.EMPTY; currentTracks = Tracks.EMPTY;
return hasChanged; return hasChanged;
} }
@Nullable long[] activeTrackIds = mediaStatus.getActiveTrackIds(); @Nullable long[] activeTrackIds = mediaStatus.getActiveTrackIds();
@ -987,20 +986,19 @@ public final class CastPlayer extends BasePlayer {
activeTrackIds = EMPTY_TRACK_ID_ARRAY; activeTrackIds = EMPTY_TRACK_ID_ARRAY;
} }
TrackGroupInfo[] trackGroupInfos = new TrackGroupInfo[castMediaTracks.size()]; Tracks.Group[] trackGroups = new Tracks.Group[castMediaTracks.size()];
for (int i = 0; i < castMediaTracks.size(); i++) { for (int i = 0; i < castMediaTracks.size(); i++) {
MediaTrack mediaTrack = castMediaTracks.get(i); MediaTrack mediaTrack = castMediaTracks.get(i);
TrackGroup trackGroup = TrackGroup trackGroup =
new TrackGroup(/* id= */ Integer.toString(i), CastUtils.mediaTrackToFormat(mediaTrack)); new TrackGroup(/* id= */ Integer.toString(i), CastUtils.mediaTrackToFormat(mediaTrack));
@C.FormatSupport int[] trackSupport = new int[] {C.FORMAT_HANDLED}; @C.FormatSupport int[] trackSupport = new int[] {C.FORMAT_HANDLED};
boolean[] trackSelected = new boolean[] {isTrackActive(mediaTrack.getId(), activeTrackIds)}; boolean[] trackSelected = new boolean[] {isTrackActive(mediaTrack.getId(), activeTrackIds)};
trackGroupInfos[i] = trackGroups[i] =
new TrackGroupInfo( new Tracks.Group(trackGroup, /* adaptiveSupported= */ false, trackSupport, trackSelected);
trackGroup, /* adaptiveSupported= */ false, trackSupport, trackSelected);
} }
TracksInfo newTracksInfo = new TracksInfo(ImmutableList.copyOf(trackGroupInfos)); Tracks newTracks = new Tracks(ImmutableList.copyOf(trackGroups));
if (!newTracksInfo.equals(currentTracksInfo)) { if (!newTracks.equals(currentTracks)) {
currentTracksInfo = newTracksInfo; currentTracks = newTracks;
return true; return true;
} }
return false; return false;

View File

@ -442,10 +442,10 @@ public class ForwardingPlayer implements Player {
player.release(); player.release();
} }
/** Calls {@link Player#getCurrentTracksInfo()} on the delegate and returns the result. */ /** Calls {@link Player#getCurrentTracks()} on the delegate and returns the result. */
@Override @Override
public TracksInfo getCurrentTracksInfo() { public Tracks getCurrentTracks() {
return player.getCurrentTracksInfo(); return player.getCurrentTracks();
} }
/** Calls {@link Player#getTrackSelectionParameters()} on the delegate and returns the result. */ /** Calls {@link Player#getTrackSelectionParameters()} on the delegate and returns the result. */
@ -831,8 +831,8 @@ public class ForwardingPlayer implements Player {
} }
@Override @Override
public void onTracksInfoChanged(TracksInfo tracksInfo) { public void onTracksChanged(Tracks tracks) {
listener.onTracksInfoChanged(tracksInfo); listener.onTracksChanged(tracks);
} }
@Override @Override

View File

@ -57,8 +57,8 @@ import java.util.List;
* <ul> * <ul>
* <li>They can provide a {@link Timeline} representing the structure of the media being played, * <li>They can provide a {@link Timeline} representing the structure of the media being played,
* which can be obtained by calling {@link #getCurrentTimeline()}. * which can be obtained by calling {@link #getCurrentTimeline()}.
* <li>They can provide a {@link TracksInfo} defining the currently available tracks and which are * <li>They can provide a {@link Tracks} defining the currently available tracks and which are
* selected to be rendered, which can be obtained by calling {@link #getCurrentTracksInfo()}. * selected to be rendered, which can be obtained by calling {@link #getCurrentTracks()}.
* </ul> * </ul>
*/ */
public interface Player { public interface Player {
@ -676,14 +676,14 @@ public interface Player {
@Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {} @Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {}
/** /**
* Called when the available or selected tracks change. * Called when the tracks change.
* *
* <p>{@link #onEvents(Player, Events)} will also be called to report this event along with * <p>{@link #onEvents(Player, Events)} will also be called to report this event along with
* other events that happen in the same {@link Looper} message queue iteration. * other events that happen in the same {@link Looper} message queue iteration.
* *
* @param tracksInfo The available tracks information. Never null, but may be of length zero. * @param tracks The available tracks information. Never null, but may be of length zero.
*/ */
default void onTracksInfoChanged(TracksInfo tracksInfo) {} default void onTracksChanged(Tracks tracks) {}
/** /**
* Called when the combined {@link MediaMetadata} changes. * Called when the combined {@link MediaMetadata} changes.
@ -1308,7 +1308,7 @@ public interface Player {
int EVENT_TIMELINE_CHANGED = 0; int EVENT_TIMELINE_CHANGED = 0;
/** {@link #getCurrentMediaItem()} changed or the player started repeating the current item. */ /** {@link #getCurrentMediaItem()} changed or the player started repeating the current item. */
int EVENT_MEDIA_ITEM_TRANSITION = 1; int EVENT_MEDIA_ITEM_TRANSITION = 1;
/** {@link #getCurrentTracksInfo()} changed. */ /** {@link #getCurrentTracks()} changed. */
int EVENT_TRACKS_CHANGED = 2; int EVENT_TRACKS_CHANGED = 2;
/** {@link #isLoading()} ()} changed. */ /** {@link #isLoading()} ()} changed. */
int EVENT_IS_LOADING_CHANGED = 3; int EVENT_IS_LOADING_CHANGED = 3;
@ -2093,11 +2093,11 @@ public interface Player {
void release(); void release();
/** /**
* Returns information about the current tracks. * Returns the current tracks.
* *
* @see Listener#onTracksInfoChanged(TracksInfo) * @see Listener#onTracksChanged(Tracks)
*/ */
TracksInfo getCurrentTracksInfo(); Tracks getCurrentTracks();
/** /**
* Returns the parameters constraining the track selection. * Returns the parameters constraining the track selection.

View File

@ -92,7 +92,7 @@ public final class TrackSelectionOverride implements Bundleable {
} }
/** Returns the {@link C.TrackType} of the overridden track group. */ /** Returns the {@link C.TrackType} of the overridden track group. */
public @C.TrackType int getTrackType() { public @C.TrackType int getType() {
return trackGroup.type; return trackGroup.type;
} }

View File

@ -684,7 +684,7 @@ public class TrackSelectionParameters implements Bundleable {
/** Sets an override, replacing all existing overrides with the same track type. */ /** Sets an override, replacing all existing overrides with the same track type. */
public Builder setOverrideForType(TrackSelectionOverride override) { public Builder setOverrideForType(TrackSelectionOverride override) {
clearOverridesOfType(override.getTrackType()); clearOverridesOfType(override.getType());
overrides.put(override.trackGroup, override); overrides.put(override.trackGroup, override);
return this; return this;
} }
@ -700,7 +700,7 @@ public class TrackSelectionParameters implements Bundleable {
Iterator<TrackSelectionOverride> it = overrides.values().iterator(); Iterator<TrackSelectionOverride> it = overrides.values().iterator();
while (it.hasNext()) { while (it.hasNext()) {
TrackSelectionOverride override = it.next(); TrackSelectionOverride override = it.next();
if (override.getTrackType() == trackType) { if (override.getType() == trackType) {
it.remove(); it.remove();
} }
} }

View File

@ -37,14 +37,14 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
/** Information about groups of tracks. */ /** Information about groups of tracks. */
public final class TracksInfo implements Bundleable { public final class Tracks implements Bundleable {
/** /**
* Information about a single group of tracks, including the underlying {@link TrackGroup}, the * Information about a single group of tracks, including the underlying {@link TrackGroup}, the
* level to which each track is supported by the player, and whether any of the tracks are * level to which each track is supported by the player, and whether any of the tracks are
* selected. * selected.
*/ */
public static final class TrackGroupInfo implements Bundleable { public static final class Group implements Bundleable {
/** The number of tracks in the group. */ /** The number of tracks in the group. */
public final int length; public final int length;
@ -64,7 +64,7 @@ public final class TracksInfo implements Bundleable {
* @param trackSelected Whether each track in the {@code trackGroup} is selected. * @param trackSelected Whether each track in the {@code trackGroup} is selected.
*/ */
@UnstableApi @UnstableApi
public TrackGroupInfo( public Group(
TrackGroup trackGroup, TrackGroup trackGroup,
boolean adaptiveSupported, boolean adaptiveSupported,
@C.FormatSupport int[] trackSupport, @C.FormatSupport int[] trackSupport,
@ -85,7 +85,7 @@ public final class TracksInfo implements Bundleable {
/** /**
* Returns the {@link Format} for a specified track. * Returns the {@link Format} for a specified track.
* *
* @param trackIndex The index of the track in the {@link TrackGroup}. * @param trackIndex The index of the track in the group.
* @return The {@link Format} of the track. * @return The {@link Format} of the track.
*/ */
public Format getTrackFormat(int trackIndex) { public Format getTrackFormat(int trackIndex) {
@ -95,7 +95,7 @@ public final class TracksInfo implements Bundleable {
/** /**
* Returns the level of support for a specified track. * Returns the level of support for a specified track.
* *
* @param trackIndex The index of the track in the {@link TrackGroup}. * @param trackIndex The index of the track in the group.
* @return The {@link C.FormatSupport} of the track. * @return The {@link C.FormatSupport} of the track.
*/ */
@UnstableApi @UnstableApi
@ -107,7 +107,7 @@ public final class TracksInfo implements Bundleable {
* Returns whether a specified track is supported for playback, without exceeding the advertised * Returns whether a specified track is supported for playback, without exceeding the advertised
* capabilities of the device. Equivalent to {@code isTrackSupported(trackIndex, false)}. * capabilities of the device. Equivalent to {@code isTrackSupported(trackIndex, false)}.
* *
* @param trackIndex The index of the track in the {@link TrackGroup}. * @param trackIndex The index of the track in the group.
* @return True if the track's format can be played, false otherwise. * @return True if the track's format can be played, false otherwise.
*/ */
public boolean isTrackSupported(int trackIndex) { public boolean isTrackSupported(int trackIndex) {
@ -117,7 +117,7 @@ public final class TracksInfo implements Bundleable {
/** /**
* Returns whether a specified track is supported for playback. * Returns whether a specified track is supported for playback.
* *
* @param trackIndex The index of the track in the {@link TrackGroup}. * @param trackIndex The index of the track in the group.
* @param allowExceedsCapabilities Whether to consider the track as supported if it has a * @param allowExceedsCapabilities Whether to consider the track as supported if it has a
* supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised * supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised
* capabilities of the device. For example, a video track for which there's a corresponding * capabilities of the device. For example, a video track for which there's a corresponding
@ -178,7 +178,7 @@ public final class TracksInfo implements Bundleable {
* playing, however some player implementations have ways of getting such information. For * playing, however some player implementations have ways of getting such information. For
* example, ExoPlayer provides this information via {@code ExoTrackSelection.getSelectedFormat}. * example, ExoPlayer provides this information via {@code ExoTrackSelection.getSelectedFormat}.
* *
* @param trackIndex The index of the track in the {@link TrackGroup}. * @param trackIndex The index of the track in the group.
* @return True if the track is selected, false otherwise. * @return True if the track is selected, false otherwise.
*/ */
public boolean isTrackSelected(int trackIndex) { public boolean isTrackSelected(int trackIndex) {
@ -186,7 +186,7 @@ public final class TracksInfo implements Bundleable {
} }
/** Returns the {@link C.TrackType} of the group. */ /** Returns the {@link C.TrackType} of the group. */
public @C.TrackType int getTrackType() { public @C.TrackType int getType() {
return trackGroup.type; return trackGroup.type;
} }
@ -198,7 +198,7 @@ public final class TracksInfo implements Bundleable {
if (other == null || getClass() != other.getClass()) { if (other == null || getClass() != other.getClass()) {
return false; return false;
} }
TrackGroupInfo that = (TrackGroupInfo) other; Group that = (Group) other;
return adaptiveSupported == that.adaptiveSupported return adaptiveSupported == that.adaptiveSupported
&& trackGroup.equals(that.trackGroup) && trackGroup.equals(that.trackGroup)
&& Arrays.equals(trackSupport, that.trackSupport) && Arrays.equals(trackSupport, that.trackSupport)
@ -241,9 +241,9 @@ public final class TracksInfo implements Bundleable {
return bundle; return bundle;
} }
/** Object that can restores a {@code TracksInfo} from a {@link Bundle}. */ /** Object that can restore a group of tracks from a {@link Bundle}. */
@UnstableApi @UnstableApi
public static final Creator<TrackGroupInfo> CREATOR = public static final Creator<Group> CREATOR =
bundle -> { bundle -> {
TrackGroup trackGroup = TrackGroup trackGroup =
fromNullableBundle( fromNullableBundle(
@ -258,7 +258,7 @@ public final class TracksInfo implements Bundleable {
new boolean[trackGroup.length]); new boolean[trackGroup.length]);
boolean adaptiveSupported = boolean adaptiveSupported =
bundle.getBoolean(keyForField(FIELD_ADAPTIVE_SUPPORTED), false); bundle.getBoolean(keyForField(FIELD_ADAPTIVE_SUPPORTED), false);
return new TrackGroupInfo(trackGroup, adaptiveSupported, trackSupport, selected); return new Group(trackGroup, adaptiveSupported, trackSupport, selected);
}; };
private static String keyForField(@FieldNumber int field) { private static String keyForField(@FieldNumber int field) {
@ -266,31 +266,35 @@ public final class TracksInfo implements Bundleable {
} }
} }
/** An {@code TrackInfo} that contains no tracks. */ /** Empty tracks. */
@UnstableApi public static final TracksInfo EMPTY = new TracksInfo(ImmutableList.of()); @UnstableApi public static final Tracks EMPTY = new Tracks(ImmutableList.of());
private final ImmutableList<TrackGroupInfo> trackGroupInfos; private final ImmutableList<Group> groups;
/** /**
* Constructs an instance. * Constructs an instance.
* *
* @param trackGroupInfos The {@link TrackGroupInfo TrackGroupInfos} describing the groups of * @param groups The {@link Group groups} of tracks.
* tracks.
*/ */
@UnstableApi @UnstableApi
public TracksInfo(List<TrackGroupInfo> trackGroupInfos) { public Tracks(List<Group> groups) {
this.trackGroupInfos = ImmutableList.copyOf(trackGroupInfos); this.groups = ImmutableList.copyOf(groups);
} }
/** Returns the {@link TrackGroupInfo TrackGroupInfos} describing the groups of tracks. */ /** Returns the {@link Group groups} of tracks. */
public ImmutableList<TrackGroupInfo> getTrackGroupInfos() { public ImmutableList<Group> getGroups() {
return trackGroupInfos; return groups;
}
/** Returns {@code true} if there are no tracks, and {@code false} otherwise. */
public boolean isEmpty() {
return groups.isEmpty();
} }
/** Returns true if there are tracks of type {@code trackType}, and false otherwise. */ /** Returns true if there are tracks of type {@code trackType}, and false otherwise. */
public boolean containsType(@C.TrackType int trackType) { public boolean containsType(@C.TrackType int trackType) {
for (int i = 0; i < trackGroupInfos.size(); i++) { for (int i = 0; i < groups.size(); i++) {
if (trackGroupInfos.get(i).getTrackType() == trackType) { if (groups.get(i).getType() == trackType) {
return true; return true;
} }
} }
@ -299,7 +303,7 @@ public final class TracksInfo implements Bundleable {
/** /**
* Returns true if at least one track of type {@code trackType} is {@link * Returns true if at least one track of type {@code trackType} is {@link
* TrackGroupInfo#isTrackSupported(int) supported}. * Group#isTrackSupported(int) supported}.
*/ */
public boolean isTypeSupported(@C.TrackType int trackType) { public boolean isTypeSupported(@C.TrackType int trackType) {
return isTypeSupported(trackType, /* allowExceedsCapabilities= */ false); return isTypeSupported(trackType, /* allowExceedsCapabilities= */ false);
@ -307,7 +311,7 @@ public final class TracksInfo implements Bundleable {
/** /**
* Returns true if at least one track of type {@code trackType} is {@link * Returns true if at least one track of type {@code trackType} is {@link
* TrackGroupInfo#isTrackSupported(int, boolean) supported}. * Group#isTrackSupported(int, boolean) supported}.
* *
* @param allowExceedsCapabilities Whether to consider the track as supported if it has a * @param allowExceedsCapabilities Whether to consider the track as supported if it has a
* supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised * supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised
@ -316,9 +320,9 @@ public final class TracksInfo implements Bundleable {
* Such tracks may be playable in some cases. * Such tracks may be playable in some cases.
*/ */
public boolean isTypeSupported(@C.TrackType int trackType, boolean allowExceedsCapabilities) { public boolean isTypeSupported(@C.TrackType int trackType, boolean allowExceedsCapabilities) {
for (int i = 0; i < trackGroupInfos.size(); i++) { for (int i = 0; i < groups.size(); i++) {
if (trackGroupInfos.get(i).getTrackType() == trackType) { if (groups.get(i).getType() == trackType) {
if (trackGroupInfos.get(i).isSupported(allowExceedsCapabilities)) { if (groups.get(i).isSupported(allowExceedsCapabilities)) {
return true; return true;
} }
} }
@ -348,9 +352,9 @@ public final class TracksInfo implements Bundleable {
/** Returns true if at least one track of the type {@code trackType} is selected for playback. */ /** Returns true if at least one track of the type {@code trackType} is selected for playback. */
public boolean isTypeSelected(@C.TrackType int trackType) { public boolean isTypeSelected(@C.TrackType int trackType) {
for (int i = 0; i < trackGroupInfos.size(); i++) { for (int i = 0; i < groups.size(); i++) {
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(i); Group group = groups.get(i);
if (trackGroupInfo.isSelected() && trackGroupInfo.getTrackType() == trackType) { if (group.isSelected() && group.getType() == trackType) {
return true; return true;
} }
} }
@ -365,13 +369,13 @@ public final class TracksInfo implements Bundleable {
if (other == null || getClass() != other.getClass()) { if (other == null || getClass() != other.getClass()) {
return false; return false;
} }
TracksInfo that = (TracksInfo) other; Tracks that = (Tracks) other;
return trackGroupInfos.equals(that.trackGroupInfos); return groups.equals(that.groups);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return trackGroupInfos.hashCode(); return groups.hashCode();
} }
// Bundleable implementation. // Bundleable implementation.
@ -379,31 +383,30 @@ public final class TracksInfo implements Bundleable {
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE) @Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_TRACK_GROUP_INFOS, FIELD_TRACK_GROUPS,
}) })
private @interface FieldNumber {} private @interface FieldNumber {}
private static final int FIELD_TRACK_GROUP_INFOS = 0; private static final int FIELD_TRACK_GROUPS = 0;
@UnstableApi @UnstableApi
@Override @Override
public Bundle toBundle() { public Bundle toBundle() {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putParcelableArrayList( bundle.putParcelableArrayList(keyForField(FIELD_TRACK_GROUPS), toBundleArrayList(groups));
keyForField(FIELD_TRACK_GROUP_INFOS), toBundleArrayList(trackGroupInfos));
return bundle; return bundle;
} }
/** Object that can restore a {@code TracksInfo} from a {@link Bundle}. */ /** Object that can restore tracks from a {@link Bundle}. */
@UnstableApi @UnstableApi
public static final Creator<TracksInfo> CREATOR = public static final Creator<Tracks> CREATOR =
bundle -> { bundle -> {
List<TrackGroupInfo> trackGroupInfos = List<Group> groups =
fromBundleNullableList( fromBundleNullableList(
TrackGroupInfo.CREATOR, Group.CREATOR,
bundle.getParcelableArrayList(keyForField(FIELD_TRACK_GROUP_INFOS)), bundle.getParcelableArrayList(keyForField(FIELD_TRACK_GROUPS)),
/* defaultValue= */ ImmutableList.of()); /* defaultValue= */ ImmutableList.of());
return new TracksInfo(trackGroupInfos); return new Tracks(groups);
}; };
private static String keyForField(@FieldNumber int field) { private static String keyForField(@FieldNumber int field) {

View File

@ -1,144 +0,0 @@
/*
* Copyright (C) 2021 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 androidx.media3.common;
import static androidx.media3.common.MimeTypes.AUDIO_AAC;
import static androidx.media3.common.MimeTypes.VIDEO_H264;
import static com.google.common.truth.Truth.assertThat;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
import org.junit.runner.RunWith;
/** Unit test for {@link TracksInfo}. */
@RunWith(AndroidJUnit4.class)
public class TracksInfoTest {
@Test
public void roundTripViaBundle_ofEmptyTracksInfo_yieldsEqualInstance() {
TracksInfo before = TracksInfo.EMPTY;
TracksInfo after = TracksInfo.CREATOR.fromBundle(before.toBundle());
assertThat(after).isEqualTo(before);
}
@Test
public void roundTripViaBundle_ofTracksInfo_yieldsEqualInstance() {
TracksInfo before =
new TracksInfo(
ImmutableList.of(
new TrackGroupInfo(
new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()),
/* adaptiveSupported= */ false,
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
/* tracksSelected= */ new boolean[] {true}),
new TrackGroupInfo(
new TrackGroup(
new Format.Builder().setSampleMimeType(VIDEO_H264).build(),
new Format.Builder().setSampleMimeType(VIDEO_H264).build()),
/* adaptiveSupported= */ true,
new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_UNSUPPORTED_TYPE},
/* tracksSelected= */ new boolean[] {false, true})));
TracksInfo after = TracksInfo.CREATOR.fromBundle(before.toBundle());
assertThat(after).isEqualTo(before);
}
@Test
public void tracksInfoGetters_withoutTrack_returnExpectedValues() {
TracksInfo tracksInfo = new TracksInfo(ImmutableList.of());
assertThat(tracksInfo.containsType(C.TRACK_TYPE_AUDIO)).isFalse();
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_AUDIO)).isFalse();
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true))
.isFalse();
assertThat(tracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO)).isFalse();
ImmutableList<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
assertThat(trackGroupInfos).isEmpty();
}
@Test
public void tracksInfo_emptyStaticInstance_isEmpty() {
TracksInfo tracksInfo = TracksInfo.EMPTY;
assertThat(tracksInfo.getTrackGroupInfos()).isEmpty();
assertThat(tracksInfo).isEqualTo(new TracksInfo(ImmutableList.of()));
}
@Test
public void tracksInfoGetters_ofComplexTracksInfo_returnExpectedValues() {
TrackGroupInfo trackGroupInfo0 =
new TrackGroupInfo(
new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()),
/* adaptiveSupported= */ false,
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
/* tracksSelected= */ new boolean[] {false});
TrackGroupInfo trackGroupInfo1 =
new TrackGroupInfo(
new TrackGroup(
new Format.Builder().setSampleMimeType(VIDEO_H264).build(),
new Format.Builder().setSampleMimeType(VIDEO_H264).build()),
/* adaptiveSupported= */ true,
new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_HANDLED},
/* tracksSelected= */ new boolean[] {false, true});
TracksInfo tracksInfo = new TracksInfo(ImmutableList.of(trackGroupInfo0, trackGroupInfo1));
assertThat(tracksInfo.containsType(C.TRACK_TYPE_AUDIO)).isTrue();
assertThat(tracksInfo.containsType(C.TRACK_TYPE_VIDEO)).isTrue();
assertThat(tracksInfo.containsType(C.TRACK_TYPE_TEXT)).isFalse();
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_AUDIO)).isFalse();
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_VIDEO)).isTrue();
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_TEXT)).isFalse();
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true))
.isTrue();
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true))
.isTrue();
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_TEXT, /* allowExceedsCapabilities= */ true))
.isFalse();
assertThat(tracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO)).isFalse();
assertThat(tracksInfo.isTypeSelected(C.TRACK_TYPE_VIDEO)).isTrue();
ImmutableList<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
assertThat(trackGroupInfos).hasSize(2);
assertThat(trackGroupInfos.get(0)).isSameInstanceAs(trackGroupInfo0);
assertThat(trackGroupInfos.get(1)).isSameInstanceAs(trackGroupInfo1);
assertThat(trackGroupInfos.get(0).isTrackSupported(0)).isFalse();
assertThat(trackGroupInfos.get(1).isTrackSupported(0)).isFalse();
assertThat(trackGroupInfos.get(1).isTrackSupported(1)).isTrue();
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(C.FORMAT_EXCEEDS_CAPABILITIES);
assertThat(trackGroupInfos.get(1).getTrackSupport(0)).isEqualTo(C.FORMAT_UNSUPPORTED_DRM);
assertThat(trackGroupInfos.get(1).getTrackSupport(1)).isEqualTo(C.FORMAT_HANDLED);
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isFalse();
assertThat(trackGroupInfos.get(1).isTrackSelected(0)).isFalse();
assertThat(trackGroupInfos.get(1).isTrackSelected(1)).isTrue();
assertThat(trackGroupInfos.get(0).getTrackType()).isEqualTo(C.TRACK_TYPE_AUDIO);
assertThat(trackGroupInfos.get(1).getTrackType()).isEqualTo(C.TRACK_TYPE_VIDEO);
}
/**
* Tests that {@link TrackGroupInfo#isAdaptiveSupported} returns false if the group only contains
* a single track, even if true is passed to the constructor.
*/
@Test
public void trackGroupInfo_withSingleTrack_isNotAdaptive() {
TrackGroupInfo trackGroupInfo0 =
new TrackGroupInfo(
new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()),
/* adaptiveSupported= */ true,
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
/* tracksSelected= */ new boolean[] {false});
assertThat(trackGroupInfo0.isAdaptiveSupported()).isFalse();
}
}

View File

@ -0,0 +1,143 @@
/*
* Copyright (C) 2021 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 androidx.media3.common;
import static androidx.media3.common.MimeTypes.AUDIO_AAC;
import static androidx.media3.common.MimeTypes.VIDEO_H264;
import static com.google.common.truth.Truth.assertThat;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
import org.junit.runner.RunWith;
/** Unit test for {@link Tracks}. */
@RunWith(AndroidJUnit4.class)
public class TracksTest {
@Test
public void roundTripViaBundle_ofEmptyTracks_yieldsEqualInstance() {
Tracks before = Tracks.EMPTY;
Tracks after = Tracks.CREATOR.fromBundle(before.toBundle());
assertThat(after).isEqualTo(before);
}
@Test
public void roundTripViaBundle_ofTracks_yieldsEqualInstance() {
Tracks before =
new Tracks(
ImmutableList.of(
new Tracks.Group(
new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()),
/* adaptiveSupported= */ false,
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
/* trackSelected= */ new boolean[] {true}),
new Tracks.Group(
new TrackGroup(
new Format.Builder().setSampleMimeType(VIDEO_H264).build(),
new Format.Builder().setSampleMimeType(VIDEO_H264).build()),
/* adaptiveSupported= */ true,
new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_UNSUPPORTED_TYPE},
/* trackSelected= */ new boolean[] {false, true})));
Tracks after = Tracks.CREATOR.fromBundle(before.toBundle());
assertThat(after).isEqualTo(before);
}
@Test
public void getters_withoutTrack_returnExpectedValues() {
Tracks tracks = new Tracks(ImmutableList.of());
assertThat(tracks.containsType(C.TRACK_TYPE_AUDIO)).isFalse();
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_AUDIO)).isFalse();
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true))
.isFalse();
assertThat(tracks.isTypeSelected(C.TRACK_TYPE_AUDIO)).isFalse();
ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
assertThat(trackGroups).isEmpty();
}
@Test
public void emptyStaticInstance_isEmpty() {
Tracks tracks = Tracks.EMPTY;
assertThat(tracks.getGroups()).isEmpty();
assertThat(tracks).isEqualTo(new Tracks(ImmutableList.of()));
}
@Test
public void getters_ofComplexTracks_returnExpectedValues() {
Tracks.Group trackGroup0 =
new Tracks.Group(
new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()),
/* adaptiveSupported= */ false,
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
/* trackSelected= */ new boolean[] {false});
Tracks.Group trackGroup1 =
new Tracks.Group(
new TrackGroup(
new Format.Builder().setSampleMimeType(VIDEO_H264).build(),
new Format.Builder().setSampleMimeType(VIDEO_H264).build()),
/* adaptiveSupported= */ true,
new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_HANDLED},
/* trackSelected= */ new boolean[] {false, true});
Tracks tracks = new Tracks(ImmutableList.of(trackGroup0, trackGroup1));
assertThat(tracks.containsType(C.TRACK_TYPE_AUDIO)).isTrue();
assertThat(tracks.containsType(C.TRACK_TYPE_VIDEO)).isTrue();
assertThat(tracks.containsType(C.TRACK_TYPE_TEXT)).isFalse();
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_AUDIO)).isFalse();
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_VIDEO)).isTrue();
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_TEXT)).isFalse();
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true))
.isTrue();
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true))
.isTrue();
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_TEXT, /* allowExceedsCapabilities= */ true))
.isFalse();
assertThat(tracks.isTypeSelected(C.TRACK_TYPE_AUDIO)).isFalse();
assertThat(tracks.isTypeSelected(C.TRACK_TYPE_VIDEO)).isTrue();
ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
assertThat(trackGroups).hasSize(2);
assertThat(trackGroups.get(0)).isSameInstanceAs(trackGroup0);
assertThat(trackGroups.get(1)).isSameInstanceAs(trackGroup1);
assertThat(trackGroups.get(0).isTrackSupported(0)).isFalse();
assertThat(trackGroups.get(1).isTrackSupported(0)).isFalse();
assertThat(trackGroups.get(1).isTrackSupported(1)).isTrue();
assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(C.FORMAT_EXCEEDS_CAPABILITIES);
assertThat(trackGroups.get(1).getTrackSupport(0)).isEqualTo(C.FORMAT_UNSUPPORTED_DRM);
assertThat(trackGroups.get(1).getTrackSupport(1)).isEqualTo(C.FORMAT_HANDLED);
assertThat(trackGroups.get(0).isTrackSelected(0)).isFalse();
assertThat(trackGroups.get(1).isTrackSelected(0)).isFalse();
assertThat(trackGroups.get(1).isTrackSelected(1)).isTrue();
assertThat(trackGroups.get(0).getType()).isEqualTo(C.TRACK_TYPE_AUDIO);
assertThat(trackGroups.get(1).getType()).isEqualTo(C.TRACK_TYPE_VIDEO);
}
/**
* Tests that {@link Tracks.Group#isAdaptiveSupported} returns false if the group only contains a
* single track, even if true is passed to the constructor.
*/
@Test
public void groupWithSingleTrack_isNotAdaptive() {
Tracks.Group trackGroup =
new Tracks.Group(
new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()),
/* adaptiveSupported= */ true,
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
/* trackSelected= */ new boolean[] {false});
assertThat(trackGroup.isAdaptiveSupported()).isFalse();
}
}

View File

@ -38,7 +38,7 @@ import androidx.media3.common.MediaItem;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.PriorityTaskManager; import androidx.media3.common.PriorityTaskManager;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue; import androidx.media3.common.text.Cue;
import androidx.media3.common.util.Clock; import androidx.media3.common.util.Clock;
@ -1222,8 +1222,8 @@ public interface ExoPlayer extends Player {
/** /**
* Returns the available track groups. * Returns the available track groups.
* *
* @see Listener#onTracksInfoChanged(TracksInfo) * @see Listener#onTracksChanged(Tracks)
* @deprecated Use {@link #getCurrentTracksInfo()}. * @deprecated Use {@link #getCurrentTracks()}.
*/ */
@UnstableApi @UnstableApi
@Deprecated @Deprecated
@ -1233,8 +1233,8 @@ public interface ExoPlayer extends Player {
* Returns the current track selections for each renderer, which may include {@code null} elements * Returns the current track selections for each renderer, which may include {@code null} elements
* if some renderers do not have any selected tracks. * if some renderers do not have any selected tracks.
* *
* @see Listener#onTracksInfoChanged(TracksInfo) * @see Listener#onTracksChanged(Tracks)
* @deprecated Use {@link #getCurrentTracksInfo()}. * @deprecated Use {@link #getCurrentTracks()}.
*/ */
@UnstableApi @UnstableApi
@Deprecated @Deprecated

View File

@ -70,7 +70,7 @@ import androidx.media3.common.PriorityTaskManager;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue; import androidx.media3.common.text.Cue;
import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Assertions;
@ -277,7 +277,7 @@ import java.util.concurrent.TimeoutException;
new TrackSelectorResult( new TrackSelectorResult(
new RendererConfiguration[renderers.length], new RendererConfiguration[renderers.length],
new ExoTrackSelection[renderers.length], new ExoTrackSelection[renderers.length],
TracksInfo.EMPTY, Tracks.EMPTY,
/* info= */ null); /* info= */ null);
period = new Timeline.Period(); period = new Timeline.Period();
permanentAvailableCommands = permanentAvailableCommands =
@ -1147,9 +1147,9 @@ import java.util.concurrent.TimeoutException;
} }
@Override @Override
public TracksInfo getCurrentTracksInfo() { public Tracks getCurrentTracks() {
verifyApplicationThread(); verifyApplicationThread();
return playbackInfo.trackSelectorResult.tracksInfo; return playbackInfo.trackSelectorResult.tracks;
} }
@Override @Override
@ -1898,7 +1898,7 @@ import java.util.concurrent.TimeoutException;
trackSelector.onSelectionActivated(newPlaybackInfo.trackSelectorResult.info); trackSelector.onSelectionActivated(newPlaybackInfo.trackSelectorResult.info);
listeners.queueEvent( listeners.queueEvent(
Player.EVENT_TRACKS_CHANGED, Player.EVENT_TRACKS_CHANGED,
listener -> listener.onTracksInfoChanged(newPlaybackInfo.trackSelectorResult.tracksInfo)); listener -> listener.onTracksChanged(newPlaybackInfo.trackSelectorResult.tracks));
} }
if (metadataChanged) { if (metadataChanged) {
final MediaMetadata finalMediaMetadata = mediaMetadata; final MediaMetadata finalMediaMetadata = mediaMetadata;

View File

@ -36,7 +36,7 @@ import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.PriorityTaskManager; import androidx.media3.common.PriorityTaskManager;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue; import androidx.media3.common.text.Cue;
import androidx.media3.common.util.Clock; import androidx.media3.common.util.Clock;
@ -1059,9 +1059,9 @@ public class SimpleExoPlayer extends BasePlayer
} }
@Override @Override
public TracksInfo getCurrentTracksInfo() { public Tracks getCurrentTracks() {
blockUntilConstructorFinished(); blockUntilConstructorFinished();
return player.getCurrentTracksInfo(); return player.getCurrentTracks();
} }
@Override @Override

View File

@ -46,7 +46,7 @@ import androidx.media3.common.Player.PlaybackSuppressionReason;
import androidx.media3.common.Player.TimelineChangeReason; import androidx.media3.common.Player.TimelineChangeReason;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue; import androidx.media3.common.text.Cue;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
@ -238,7 +238,7 @@ public interface AnalyticsListener {
* {@link Player#getCurrentMediaItem()} changed or the player started repeating the current item. * {@link Player#getCurrentMediaItem()} changed or the player started repeating the current item.
*/ */
int EVENT_MEDIA_ITEM_TRANSITION = Player.EVENT_MEDIA_ITEM_TRANSITION; int EVENT_MEDIA_ITEM_TRANSITION = Player.EVENT_MEDIA_ITEM_TRANSITION;
/** {@link Player#getCurrentTracksInfo()} changed. */ /** {@link Player#getCurrentTracks()} changed. */
int EVENT_TRACKS_CHANGED = Player.EVENT_TRACKS_CHANGED; int EVENT_TRACKS_CHANGED = Player.EVENT_TRACKS_CHANGED;
/** {@link Player#isLoading()} ()} changed. */ /** {@link Player#isLoading()} ()} changed. */
int EVENT_IS_LOADING_CHANGED = Player.EVENT_IS_LOADING_CHANGED; int EVENT_IS_LOADING_CHANGED = Player.EVENT_IS_LOADING_CHANGED;
@ -706,12 +706,12 @@ public interface AnalyticsListener {
default void onPlayerErrorChanged(EventTime eventTime, @Nullable PlaybackException error) {} default void onPlayerErrorChanged(EventTime eventTime, @Nullable PlaybackException error) {}
/** /**
* Called when the available or selected tracks change. * Called when the tracks change.
* *
* @param eventTime The event time. * @param eventTime The event time.
* @param tracksInfo The available tracks information. Never null, but may be of length zero. * @param tracks The tracks. Never null, but may be of length zero.
*/ */
default void onTracksInfoChanged(EventTime eventTime, TracksInfo tracksInfo) {} default void onTracksChanged(EventTime eventTime, Tracks tracks) {}
/** /**
* Called when track selection parameters change. * Called when track selection parameters change.

View File

@ -39,7 +39,7 @@ import androidx.media3.common.Timeline;
import androidx.media3.common.Timeline.Period; import androidx.media3.common.Timeline.Period;
import androidx.media3.common.Timeline.Window; import androidx.media3.common.Timeline.Window;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue; import androidx.media3.common.text.Cue;
import androidx.media3.common.util.Clock; import androidx.media3.common.util.Clock;
@ -483,12 +483,12 @@ public class DefaultAnalyticsCollector implements AnalyticsCollector {
} }
@Override @Override
public void onTracksInfoChanged(TracksInfo tracksInfo) { public void onTracksChanged(Tracks tracks) {
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
sendEvent( sendEvent(
eventTime, eventTime,
AnalyticsListener.EVENT_TRACKS_CHANGED, AnalyticsListener.EVENT_TRACKS_CHANGED,
listener -> listener.onTracksInfoChanged(eventTime, tracksInfo)); listener -> listener.onTracksChanged(eventTime, tracks));
} }
@SuppressWarnings("deprecation") // Implementing deprecated method. @SuppressWarnings("deprecation") // Implementing deprecated method.

View File

@ -49,8 +49,7 @@ import androidx.media3.common.ParserException;
import androidx.media3.common.PlaybackException; import androidx.media3.common.PlaybackException;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.util.NetworkTypeObserver; import androidx.media3.common.util.NetworkTypeObserver;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
@ -340,8 +339,7 @@ public final class MediaMetricsListener
} }
} }
if (events.contains(EVENT_TRACKS_CHANGED) && metricsBuilder != null) { if (events.contains(EVENT_TRACKS_CHANGED) && metricsBuilder != null) {
@Nullable @Nullable DrmInitData drmInitData = getDrmInitData(player.getCurrentTracks().getGroups());
DrmInitData drmInitData = getDrmInitData(player.getCurrentTracksInfo().getTrackGroupInfos());
if (drmInitData != null) { if (drmInitData != null) {
castNonNull(metricsBuilder).setDrmType(getDrmType(drmInitData)); castNonNull(metricsBuilder).setDrmType(getDrmType(drmInitData));
} }
@ -372,10 +370,10 @@ public final class MediaMetricsListener
private void maybeReportTrackChanges(Player player, Events events, long realtimeMs) { private void maybeReportTrackChanges(Player player, Events events, long realtimeMs) {
if (events.contains(EVENT_TRACKS_CHANGED)) { if (events.contains(EVENT_TRACKS_CHANGED)) {
TracksInfo tracksInfo = player.getCurrentTracksInfo(); Tracks tracks = player.getCurrentTracks();
boolean isVideoSelected = tracksInfo.isTypeSelected(C.TRACK_TYPE_VIDEO); boolean isVideoSelected = tracks.isTypeSelected(C.TRACK_TYPE_VIDEO);
boolean isAudioSelected = tracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO); boolean isAudioSelected = tracks.isTypeSelected(C.TRACK_TYPE_AUDIO);
boolean isTextSelected = tracksInfo.isTypeSelected(C.TRACK_TYPE_TEXT); boolean isTextSelected = tracks.isTypeSelected(C.TRACK_TYPE_TEXT);
if (isVideoSelected || isAudioSelected || isTextSelected) { if (isVideoSelected || isAudioSelected || isTextSelected) {
// Ignore updates with insufficient information where no tracks are selected. // Ignore updates with insufficient information where no tracks are selected.
if (!isVideoSelected) { if (!isVideoSelected) {
@ -822,11 +820,11 @@ public final class MediaMetricsListener
} }
@Nullable @Nullable
private static DrmInitData getDrmInitData(ImmutableList<TrackGroupInfo> trackGroupInfos) { private static DrmInitData getDrmInitData(ImmutableList<Tracks.Group> trackGroups) {
for (TrackGroupInfo trackGroupInfo : trackGroupInfos) { for (Tracks.Group trackGroup : trackGroups) {
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) { for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
if (trackGroupInfo.isTrackSelected(trackIndex)) { if (trackGroup.isTrackSelected(trackIndex)) {
@Nullable DrmInitData drmInitData = trackGroupInfo.getTrackFormat(trackIndex).drmInitData; @Nullable DrmInitData drmInitData = trackGroup.getTrackFormat(trackIndex).drmInitData;
if (drmInitData != null) { if (drmInitData != null) {
return drmInitData; return drmInitData;
} }

View File

@ -27,7 +27,7 @@ import androidx.media3.common.PlaybackException;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.Timeline.Period; import androidx.media3.common.Timeline.Period;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
@ -524,11 +524,11 @@ public final class PlaybackStatsListener
hasFatalError = false; hasFatalError = false;
} }
if (isForeground && !isInterruptedByAd) { if (isForeground && !isInterruptedByAd) {
TracksInfo currentTracksInfo = player.getCurrentTracksInfo(); Tracks currentTracks = player.getCurrentTracks();
if (!currentTracksInfo.isTypeSelected(C.TRACK_TYPE_VIDEO)) { if (!currentTracks.isTypeSelected(C.TRACK_TYPE_VIDEO)) {
maybeUpdateVideoFormat(eventTime, /* newFormat= */ null); maybeUpdateVideoFormat(eventTime, /* newFormat= */ null);
} }
if (!currentTracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO)) { if (!currentTracks.isTypeSelected(C.TRACK_TYPE_AUDIO)) {
maybeUpdateAudioFormat(eventTime, /* newFormat= */ null); maybeUpdateAudioFormat(eventTime, /* newFormat= */ null);
} }
} }

View File

@ -33,7 +33,7 @@ import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionOverride; import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
@ -546,16 +546,16 @@ public final class DownloadHelper {
} }
/** /**
* Returns {@link TracksInfo} for the given period. Must not be called until after preparation * Returns {@link Tracks} for the given period. Must not be called until after preparation
* completes. * completes.
* *
* @param periodIndex The period index. * @param periodIndex The period index.
* @return The {@link TracksInfo} for the period. May be {@link TracksInfo#EMPTY} for single * @return The {@link Tracks} for the period. May be {@link Tracks#EMPTY} for single stream
* stream content. * content.
*/ */
public TracksInfo getTracksInfo(int periodIndex) { public Tracks getTracks(int periodIndex) {
assertPreparedWithMedia(); assertPreparedWithMedia();
return TrackSelectionUtil.buildTracksInfo( return TrackSelectionUtil.buildTracks(
mappedTrackInfos[periodIndex], immutableTrackSelectionsByPeriodAndRenderer[periodIndex]); mappedTrackInfos[periodIndex], immutableTrackSelectionsByPeriodAndRenderer[periodIndex]);
} }

View File

@ -1962,12 +1962,11 @@ public class DefaultTrackSelector extends MappingTrackSelector {
if (override == null) { if (override == null) {
continue; continue;
} }
@Nullable @Nullable TrackSelectionOverride existingOverride = overridesByType.get(override.getType());
TrackSelectionOverride existingOverride = overridesByType.get(override.getTrackType());
// Only replace an existing override if it's empty and the one being considered is not. // Only replace an existing override if it's empty and the one being considered is not.
if (existingOverride == null if (existingOverride == null
|| (existingOverride.trackIndices.isEmpty() && !override.trackIndices.isEmpty())) { || (existingOverride.trackIndices.isEmpty() && !override.trackIndices.isEmpty())) {
overridesByType.put(override.getTrackType(), override); overridesByType.put(override.getType(), override);
} }
} }
} }

View File

@ -31,7 +31,7 @@ import androidx.media3.common.C;
import androidx.media3.common.C.FormatSupport; import androidx.media3.common.C.FormatSupport;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.ExoPlaybackException; import androidx.media3.exoplayer.ExoPlaybackException;
@ -427,9 +427,9 @@ public abstract class MappingTrackSelector extends TrackSelector {
periodId, periodId,
timeline); timeline);
TracksInfo tracksInfo = TrackSelectionUtil.buildTracksInfo(mappedTrackInfo, result.second); Tracks tracks = TrackSelectionUtil.buildTracks(mappedTrackInfo, result.second);
return new TrackSelectorResult(result.first, result.second, tracksInfo, mappedTrackInfo); return new TrackSelectorResult(result.first, result.second, tracks, mappedTrackInfo);
} }
/** /**

View File

@ -19,8 +19,7 @@ import android.os.SystemClock;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media3.common.C; import androidx.media3.common.C;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.exoplayer.RendererCapabilities; import androidx.media3.exoplayer.RendererCapabilities;
import androidx.media3.exoplayer.source.TrackGroupArray; import androidx.media3.exoplayer.source.TrackGroupArray;
@ -136,16 +135,16 @@ public final class TrackSelectionUtil {
} }
/** /**
* Returns {@link TracksInfo} built from {@link MappingTrackSelector.MappedTrackInfo} and {@link * Returns {@link Tracks} built from {@link MappingTrackSelector.MappedTrackInfo} and {@link
* TrackSelection TrackSelections} for each renderer. * TrackSelection TrackSelections} for each renderer.
* *
* @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo} * @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
* @param selections The track selections, indexed by renderer. A null entry indicates that a * @param selections The track selections, indexed by renderer. A null entry indicates that a
* renderer does not have any selected tracks. * renderer does not have any selected tracks.
* @return The corresponding {@link TracksInfo}. * @return The corresponding {@link Tracks}.
*/ */
@SuppressWarnings({"unchecked", "rawtypes"}) // Initialization of array of Lists. @SuppressWarnings({"unchecked", "rawtypes"}) // Initialization of array of Lists.
public static TracksInfo buildTracksInfo( public static Tracks buildTracks(
MappingTrackSelector.MappedTrackInfo mappedTrackInfo, MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
@NullableType TrackSelection[] selections) { @NullableType TrackSelection[] selections) {
List<? extends TrackSelection>[] listSelections = new List[selections.length]; List<? extends TrackSelection>[] listSelections = new List[selections.length];
@ -153,22 +152,22 @@ public final class TrackSelectionUtil {
@Nullable TrackSelection selection = selections[i]; @Nullable TrackSelection selection = selections[i];
listSelections[i] = selection != null ? ImmutableList.of(selection) : ImmutableList.of(); listSelections[i] = selection != null ? ImmutableList.of(selection) : ImmutableList.of();
} }
return buildTracksInfo(mappedTrackInfo, listSelections); return buildTracks(mappedTrackInfo, listSelections);
} }
/** /**
* Returns {@link TracksInfo} built from {@link MappingTrackSelector.MappedTrackInfo} and {@link * Returns {@link Tracks} built from {@link MappingTrackSelector.MappedTrackInfo} and {@link
* TrackSelection TrackSelections} for each renderer. * TrackSelection TrackSelections} for each renderer.
* *
* @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo} * @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
* @param selections The track selections, indexed by renderer. Null entries are not permitted. An * @param selections The track selections, indexed by renderer. Null entries are not permitted. An
* empty list indicates that a renderer does not have any selected tracks. * empty list indicates that a renderer does not have any selected tracks.
* @return The corresponding {@link TracksInfo}. * @return The corresponding {@link Tracks}.
*/ */
public static TracksInfo buildTracksInfo( public static Tracks buildTracks(
MappingTrackSelector.MappedTrackInfo mappedTrackInfo, MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
List<? extends TrackSelection>[] selections) { List<? extends TrackSelection>[] selections) {
ImmutableList.Builder<TrackGroupInfo> trackGroupInfos = new ImmutableList.Builder<>(); ImmutableList.Builder<Tracks.Group> trackGroups = new ImmutableList.Builder<>();
for (int rendererIndex = 0; for (int rendererIndex = 0;
rendererIndex < mappedTrackInfo.getRendererCount(); rendererIndex < mappedTrackInfo.getRendererCount();
rendererIndex++) { rendererIndex++) {
@ -196,8 +195,7 @@ public final class TrackSelectionUtil {
} }
selected[trackIndex] = isTrackSelected; selected[trackIndex] = isTrackSelected;
} }
trackGroupInfos.add( trackGroups.add(new Tracks.Group(trackGroup, adaptiveSupported, trackSupport, selected));
new TrackGroupInfo(trackGroup, adaptiveSupported, trackSupport, selected));
} }
} }
TrackGroupArray unmappedTrackGroups = mappedTrackInfo.getUnmappedTrackGroups(); TrackGroupArray unmappedTrackGroups = mappedTrackInfo.getUnmappedTrackGroups();
@ -206,9 +204,9 @@ public final class TrackSelectionUtil {
@C.FormatSupport int[] trackSupport = new int[trackGroup.length]; @C.FormatSupport int[] trackSupport = new int[trackGroup.length];
Arrays.fill(trackSupport, C.FORMAT_UNSUPPORTED_TYPE); Arrays.fill(trackSupport, C.FORMAT_UNSUPPORTED_TYPE);
boolean[] selected = new boolean[trackGroup.length]; boolean[] selected = new boolean[trackGroup.length];
trackGroupInfos.add( trackGroups.add(
new TrackGroupInfo(trackGroup, /* adaptiveSupported= */ false, trackSupport, selected)); new Tracks.Group(trackGroup, /* adaptiveSupported= */ false, trackSupport, selected));
} }
return new TracksInfo(trackGroupInfos.build()); return new Tracks(trackGroups.build());
} }
} }

View File

@ -16,7 +16,7 @@
package androidx.media3.exoplayer.trackselection; package androidx.media3.exoplayer.trackselection;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.RendererConfiguration; import androidx.media3.exoplayer.RendererConfiguration;
@ -36,7 +36,7 @@ public final class TrackSelectorResult {
/** A {@link ExoTrackSelection} array containing the track selection for each renderer. */ /** A {@link ExoTrackSelection} array containing the track selection for each renderer. */
public final @NullableType ExoTrackSelection[] selections; public final @NullableType ExoTrackSelection[] selections;
/** Describe the tracks and which one were selected. */ /** Describe the tracks and which one were selected. */
public final TracksInfo tracksInfo; public final Tracks tracks;
/** /**
* An opaque object that will be returned to {@link TrackSelector#onSelectionActivated(Object)} * An opaque object that will be returned to {@link TrackSelector#onSelectionActivated(Object)}
* should the selections be activated. * should the selections be activated.
@ -51,21 +51,21 @@ public final class TrackSelectorResult {
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be * TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
* {@code null}. * {@code null}.
* @deprecated Use {@link #TrackSelectorResult(RendererConfiguration[], ExoTrackSelection[], * @deprecated Use {@link #TrackSelectorResult(RendererConfiguration[], ExoTrackSelection[],
* TracksInfo, Object)}. * Tracks, Object)}.
*/ */
@Deprecated @Deprecated
public TrackSelectorResult( public TrackSelectorResult(
@NullableType RendererConfiguration[] rendererConfigurations, @NullableType RendererConfiguration[] rendererConfigurations,
@NullableType ExoTrackSelection[] selections, @NullableType ExoTrackSelection[] selections,
@Nullable Object info) { @Nullable Object info) {
this(rendererConfigurations, selections, TracksInfo.EMPTY, info); this(rendererConfigurations, selections, Tracks.EMPTY, info);
} }
/** /**
* @param rendererConfigurations A {@link RendererConfiguration} for each renderer. A null entry * @param rendererConfigurations A {@link RendererConfiguration} for each renderer. A null entry
* indicates the corresponding renderer should be disabled. * indicates the corresponding renderer should be disabled.
* @param selections A {@link ExoTrackSelection} array containing the selection for each renderer. * @param selections A {@link ExoTrackSelection} array containing the selection for each renderer.
* @param tracksInfo Description of the available tracks and which one were selected. * @param tracks Description of the available tracks and which one were selected.
* @param info An opaque object that will be returned to {@link * @param info An opaque object that will be returned to {@link
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be * TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
* {@code null}. * {@code null}.
@ -73,11 +73,11 @@ public final class TrackSelectorResult {
public TrackSelectorResult( public TrackSelectorResult(
@NullableType RendererConfiguration[] rendererConfigurations, @NullableType RendererConfiguration[] rendererConfigurations,
@NullableType ExoTrackSelection[] selections, @NullableType ExoTrackSelection[] selections,
TracksInfo tracksInfo, Tracks tracks,
@Nullable Object info) { @Nullable Object info) {
this.rendererConfigurations = rendererConfigurations; this.rendererConfigurations = rendererConfigurations;
this.selections = selections.clone(); this.selections = selections.clone();
this.tracksInfo = tracksInfo; this.tracks = tracks;
this.info = info; this.info = info;
length = rendererConfigurations.length; length = rendererConfigurations.length;
} }

View File

@ -31,7 +31,7 @@ import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.Player.PlaybackSuppressionReason; import androidx.media3.common.Player.PlaybackSuppressionReason;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.util.Log; import androidx.media3.common.util.Log;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
@ -261,23 +261,23 @@ public class EventLogger implements AnalyticsListener {
} }
@Override @Override
public void onTracksInfoChanged(EventTime eventTime, TracksInfo tracksInfo) { public void onTracksChanged(EventTime eventTime, Tracks tracks) {
logd("tracks [" + getEventTimeString(eventTime)); logd("tracks [" + getEventTimeString(eventTime));
// Log tracks associated to renderers. // Log tracks associated to renderers.
ImmutableList<TracksInfo.TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos(); ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
for (int groupIndex = 0; groupIndex < trackGroupInfos.size(); groupIndex++) { for (int groupIndex = 0; groupIndex < trackGroups.size(); groupIndex++) {
TracksInfo.TrackGroupInfo trackGroupInfo = trackGroupInfos.get(groupIndex); Tracks.Group trackGroup = trackGroups.get(groupIndex);
logd(" group ["); logd(" group [");
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) { for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
String status = getTrackStatusString(trackGroupInfo.isTrackSelected(trackIndex)); String status = getTrackStatusString(trackGroup.isTrackSelected(trackIndex));
String formatSupport = getFormatSupportString(trackGroupInfo.getTrackSupport(trackIndex)); String formatSupport = getFormatSupportString(trackGroup.getTrackSupport(trackIndex));
logd( logd(
" " " "
+ status + status
+ " Track:" + " Track:"
+ trackIndex + trackIndex
+ ", " + ", "
+ Format.toLogString(trackGroupInfo.getTrackFormat(trackIndex)) + Format.toLogString(trackGroup.getTrackFormat(trackIndex))
+ ", supported=" + ", supported="
+ formatSupport); + formatSupport);
} }
@ -286,8 +286,8 @@ public class EventLogger implements AnalyticsListener {
// TODO: Replace this with an override of onMediaMetadataChanged. // TODO: Replace this with an override of onMediaMetadataChanged.
// Log metadata for at most one of the selected tracks. // Log metadata for at most one of the selected tracks.
boolean loggedMetadata = false; boolean loggedMetadata = false;
for (int groupIndex = 0; !loggedMetadata && groupIndex < trackGroupInfos.size(); groupIndex++) { for (int groupIndex = 0; !loggedMetadata && groupIndex < trackGroups.size(); groupIndex++) {
TracksInfo.TrackGroupInfo trackGroup = trackGroupInfos.get(groupIndex); Tracks.Group trackGroup = trackGroups.get(groupIndex);
for (int trackIndex = 0; !loggedMetadata && trackIndex < trackGroup.length; trackIndex++) { for (int trackIndex = 0; !loggedMetadata && trackIndex < trackGroup.length; trackIndex++) {
if (trackGroup.isTrackSelected(trackIndex)) { if (trackGroup.isTrackSelected(trackIndex)) {
@Nullable Metadata metadata = trackGroup.getTrackFormat(trackIndex).metadata; @Nullable Metadata metadata = trackGroup.getTrackFormat(trackIndex).metadata;

View File

@ -108,8 +108,7 @@ import androidx.media3.common.Player.PositionInfo;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.Timeline.Window; import androidx.media3.common.Timeline.Window;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.Clock; import androidx.media3.common.util.Clock;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
@ -277,15 +276,15 @@ public final class ExoPlayerTest {
argThat(noUid(timeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE)); argThat(noUid(timeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
inOrder inOrder
.verify(mockListener) .verify(mockListener)
.onTracksInfoChanged( .onTracksChanged(
eq( eq(
new TracksInfo( new Tracks(
ImmutableList.of( ImmutableList.of(
new TrackGroupInfo( new Tracks.Group(
new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT), new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT),
/* adaptiveSupported= */ false, /* adaptiveSupported= */ false,
new int[] {C.FORMAT_HANDLED}, new int[] {C.FORMAT_HANDLED},
/* tracksSelected= */ new boolean[] {true}))))); /* trackSelected= */ new boolean[] {true})))));
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt()); inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt()); inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
assertThat(renderer.getFormatsRead()).containsExactly(ExoPlayerTestRunner.VIDEO_FORMAT); assertThat(renderer.getFormatsRead()).containsExactly(ExoPlayerTestRunner.VIDEO_FORMAT);
@ -656,15 +655,15 @@ public final class ExoPlayerTest {
argThat(noUid(thirdTimeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE)); argThat(noUid(thirdTimeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
inOrder inOrder
.verify(mockPlayerListener) .verify(mockPlayerListener)
.onTracksInfoChanged( .onTracksChanged(
eq( eq(
new TracksInfo( new Tracks(
ImmutableList.of( ImmutableList.of(
new TrackGroupInfo( new Tracks.Group(
new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT), new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT),
/* adaptiveSupported= */ false, /* adaptiveSupported= */ false,
new int[] {C.FORMAT_HANDLED}, new int[] {C.FORMAT_HANDLED},
/* tracksSelected= */ new boolean[] {true}))))); /* trackSelected= */ new boolean[] {true})))));
assertThat(renderer.isEnded).isTrue(); assertThat(renderer.isEnded).isTrue();
} }
@ -3426,7 +3425,7 @@ public final class ExoPlayerTest {
.waitForPendingPlayerCommands() .waitForPendingPlayerCommands()
.play() .play()
.build(); .build();
List<TracksInfo> tracksInfoList = new ArrayList<>(); List<Tracks> tracksList = new ArrayList<>();
new ExoPlayerTestRunner.Builder(context) new ExoPlayerTestRunner.Builder(context)
.setMediaSources(mediaSource) .setMediaSources(mediaSource)
.setSupportedFormats(ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT) .setSupportedFormats(ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT)
@ -3434,21 +3433,21 @@ public final class ExoPlayerTest {
.setPlayerListener( .setPlayerListener(
new Player.Listener() { new Player.Listener() {
@Override @Override
public void onTracksInfoChanged(TracksInfo tracksInfo) { public void onTracksChanged(Tracks tracks) {
tracksInfoList.add(tracksInfo); tracksList.add(tracks);
} }
}) })
.build() .build()
.start() .start()
.blockUntilEnded(TIMEOUT_MS); .blockUntilEnded(TIMEOUT_MS);
assertThat(tracksInfoList).hasSize(3); assertThat(tracksList).hasSize(3);
// First track groups of the 1st period are reported. // First track groups of the 1st period are reported.
// Then the seek to an unprepared period will result in empty track groups being returned. // Then the seek to an unprepared period will result in empty track groups being returned.
// Then the track groups of the 2nd period are reported. // Then the track groups of the 2nd period are reported.
assertThat(tracksInfoList.get(0).getTrackGroupInfos().get(0).getTrackFormat(0)) assertThat(tracksList.get(0).getGroups().get(0).getTrackFormat(0))
.isEqualTo(ExoPlayerTestRunner.VIDEO_FORMAT); .isEqualTo(ExoPlayerTestRunner.VIDEO_FORMAT);
assertThat(tracksInfoList.get(1)).isEqualTo(TracksInfo.EMPTY); assertThat(tracksList.get(1)).isEqualTo(Tracks.EMPTY);
assertThat(tracksInfoList.get(2).getTrackGroupInfos().get(0).getTrackFormat(0)) assertThat(tracksList.get(2).getGroups().get(0).getTrackFormat(0))
.isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT); .isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
} }
@ -7993,7 +7992,7 @@ public final class ExoPlayerTest {
} }
}; };
AtomicReference<Timeline> timelineAfterError = new AtomicReference<>(); AtomicReference<Timeline> timelineAfterError = new AtomicReference<>();
AtomicReference<TracksInfo> trackInfosAfterError = new AtomicReference<>(); AtomicReference<Tracks> trackInfosAfterError = new AtomicReference<>();
AtomicInteger mediaItemIndexAfterError = new AtomicInteger(); AtomicInteger mediaItemIndexAfterError = new AtomicInteger();
ActionSchedule actionSchedule = ActionSchedule actionSchedule =
new ActionSchedule.Builder(TAG) new ActionSchedule.Builder(TAG)
@ -8006,7 +8005,7 @@ public final class ExoPlayerTest {
@Override @Override
public void onPlayerError(EventTime eventTime, PlaybackException error) { public void onPlayerError(EventTime eventTime, PlaybackException error) {
timelineAfterError.set(player.getCurrentTimeline()); timelineAfterError.set(player.getCurrentTimeline());
trackInfosAfterError.set(player.getCurrentTracksInfo()); trackInfosAfterError.set(player.getCurrentTracks());
mediaItemIndexAfterError.set(player.getCurrentMediaItemIndex()); mediaItemIndexAfterError.set(player.getCurrentMediaItemIndex());
} }
}); });
@ -8035,8 +8034,8 @@ public final class ExoPlayerTest {
assertThat(timelineAfterError.get().getWindowCount()).isEqualTo(1); assertThat(timelineAfterError.get().getWindowCount()).isEqualTo(1);
assertThat(mediaItemIndexAfterError.get()).isEqualTo(0); assertThat(mediaItemIndexAfterError.get()).isEqualTo(0);
assertThat(trackInfosAfterError.get().getTrackGroupInfos()).hasSize(1); assertThat(trackInfosAfterError.get().getGroups()).hasSize(1);
assertThat(trackInfosAfterError.get().getTrackGroupInfos().get(0).getTrackFormat(0)) assertThat(trackInfosAfterError.get().getGroups().get(0).getTrackFormat(0))
.isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT); .isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
assertThat(trackInfosAfterError.get().isTypeSelected(C.TRACK_TYPE_VIDEO)).isFalse(); assertThat(trackInfosAfterError.get().isTypeSelected(C.TRACK_TYPE_VIDEO)).isFalse();
assertThat(trackInfosAfterError.get().isTypeSelected(C.TRACK_TYPE_AUDIO)).isTrue(); assertThat(trackInfosAfterError.get().isTypeSelected(C.TRACK_TYPE_AUDIO)).isTrue();
@ -10423,7 +10422,7 @@ public final class ExoPlayerTest {
verify(listener, atLeastOnce()).onShuffleModeEnabledChanged(anyBoolean()); verify(listener, atLeastOnce()).onShuffleModeEnabledChanged(anyBoolean());
verify(listener, atLeastOnce()).onPlaybackStateChanged(anyInt()); verify(listener, atLeastOnce()).onPlaybackStateChanged(anyInt());
verify(listener, atLeastOnce()).onIsLoadingChanged(anyBoolean()); verify(listener, atLeastOnce()).onIsLoadingChanged(anyBoolean());
verify(listener, atLeastOnce()).onTracksInfoChanged(any()); verify(listener, atLeastOnce()).onTracksChanged(any());
verify(listener, atLeastOnce()).onMediaMetadataChanged(any()); verify(listener, atLeastOnce()).onMediaMetadataChanged(any());
verify(listener, atLeastOnce()).onPlayWhenReadyChanged(anyBoolean(), anyInt()); verify(listener, atLeastOnce()).onPlayWhenReadyChanged(anyBoolean(), anyInt());
verify(listener, atLeastOnce()).onIsPlayingChanged(anyBoolean()); verify(listener, atLeastOnce()).onIsPlayingChanged(anyBoolean());

View File

@ -34,7 +34,7 @@ import androidx.media3.common.MediaItem;
import androidx.media3.common.PlaybackParameters; import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.util.Clock; import androidx.media3.common.util.Clock;
import androidx.media3.exoplayer.analytics.AnalyticsCollector; import androidx.media3.exoplayer.analytics.AnalyticsCollector;
import androidx.media3.exoplayer.analytics.DefaultAnalyticsCollector; import androidx.media3.exoplayer.analytics.DefaultAnalyticsCollector;
@ -1141,7 +1141,7 @@ public final class MediaPeriodQueueTest {
new TrackSelectorResult( new TrackSelectorResult(
new RendererConfiguration[0], new RendererConfiguration[0],
new ExoTrackSelection[0], new ExoTrackSelection[0],
TracksInfo.EMPTY, Tracks.EMPTY,
/* info= */ null)); /* info= */ null));
} }

View File

@ -81,7 +81,7 @@ import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.Timeline.Window; import androidx.media3.common.Timeline.Window;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.util.Clock; import androidx.media3.common.util.Clock;
import androidx.media3.common.util.ConditionVariable; import androidx.media3.common.util.ConditionVariable;
@ -1729,7 +1729,7 @@ public final class DefaultAnalyticsCollectorTest {
ArgumentCaptor<AnalyticsListener.EventTime> individualTracksChangedEventTimes = ArgumentCaptor<AnalyticsListener.EventTime> individualTracksChangedEventTimes =
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class); ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
verify(listener, atLeastOnce()) verify(listener, atLeastOnce())
.onTracksInfoChanged(individualTracksChangedEventTimes.capture(), any()); .onTracksChanged(individualTracksChangedEventTimes.capture(), any());
ArgumentCaptor<AnalyticsListener.EventTime> individualPlayWhenReadyChangedEventTimes = ArgumentCaptor<AnalyticsListener.EventTime> individualPlayWhenReadyChangedEventTimes =
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class); ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
verify(listener, atLeastOnce()) verify(listener, atLeastOnce())
@ -2243,7 +2243,7 @@ public final class DefaultAnalyticsCollectorTest {
} }
@Override @Override
public void onTracksInfoChanged(EventTime eventTime, TracksInfo tracksInfo) { public void onTracksChanged(EventTime eventTime, Tracks tracks) {
reportedEvents.add(new ReportedEvent(EVENT_TRACKS_CHANGED, eventTime)); reportedEvents.add(new ReportedEvent(EVENT_TRACKS_CHANGED, eventTime));
} }

View File

@ -41,7 +41,7 @@ import androidx.media3.common.MimeTypes;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionOverride; import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.ExoPlaybackException; import androidx.media3.exoplayer.ExoPlaybackException;
import androidx.media3.exoplayer.RendererCapabilities; import androidx.media3.exoplayer.RendererCapabilities;
@ -2224,10 +2224,10 @@ public final class DefaultTrackSelectorTest {
public void selectTracks_multipleRenderer_allSelected() throws Exception { public void selectTracks_multipleRenderer_allSelected() throws Exception {
RendererCapabilities[] rendererCapabilities = RendererCapabilities[] rendererCapabilities =
new RendererCapabilities[] {VIDEO_CAPABILITIES, AUDIO_CAPABILITIES, AUDIO_CAPABILITIES}; new RendererCapabilities[] {VIDEO_CAPABILITIES, AUDIO_CAPABILITIES, AUDIO_CAPABILITIES};
TrackGroupArray trackGroups = new TrackGroupArray(AUDIO_TRACK_GROUP); TrackGroupArray trackGroupArray = new TrackGroupArray(AUDIO_TRACK_GROUP);
TrackSelectorResult result = TrackSelectorResult result =
trackSelector.selectTracks(rendererCapabilities, trackGroups, periodId, TIMELINE); trackSelector.selectTracks(rendererCapabilities, trackGroupArray, periodId, TIMELINE);
assertThat(result.length).isEqualTo(3); assertThat(result.length).isEqualTo(3);
assertThat(result.rendererConfigurations) assertThat(result.rendererConfigurations)
@ -2235,14 +2235,14 @@ public final class DefaultTrackSelectorTest {
.containsExactly(null, DEFAULT, null) .containsExactly(null, DEFAULT, null)
.inOrder(); .inOrder();
assertThat(result.selections[0]).isNull(); assertThat(result.selections[0]).isNull();
assertFixedSelection(result.selections[1], trackGroups, trackGroups.get(0).getFormat(0)); assertFixedSelection(
result.selections[1], trackGroupArray, trackGroupArray.get(0).getFormat(0));
assertThat(result.selections[2]).isNull(); assertThat(result.selections[2]).isNull();
ImmutableList<TracksInfo.TrackGroupInfo> trackGroupInfos = ImmutableList<Tracks.Group> trackGroups = result.tracks.getGroups();
result.tracksInfo.getTrackGroupInfos(); assertThat(trackGroups).hasSize(1);
assertThat(trackGroupInfos).hasSize(1); assertThat(trackGroups.get(0).getTrackGroup()).isEqualTo(AUDIO_TRACK_GROUP);
assertThat(trackGroupInfos.get(0).getTrackGroup()).isEqualTo(AUDIO_TRACK_GROUP); assertThat(trackGroups.get(0).isTrackSelected(0)).isTrue();
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isTrue(); assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
} }
/** Tests {@link SelectionOverride}'s {@link Bundleable} implementation. */ /** Tests {@link SelectionOverride}'s {@link Bundleable} implementation. */

View File

@ -32,8 +32,7 @@ import static com.google.common.truth.Truth.assertThat;
import androidx.media3.common.Format; import androidx.media3.common.Format;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.media3.exoplayer.source.TrackGroupArray; import androidx.media3.exoplayer.source.TrackGroupArray;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -73,32 +72,32 @@ public class TrackSelectionUtilTest {
new FixedTrackSelection(mappedTrackInfo.getTrackGroups(1).get(0), 1) new FixedTrackSelection(mappedTrackInfo.getTrackGroups(1).get(0), 1)
}; };
TracksInfo tracksInfo = TrackSelectionUtil.buildTracksInfo(mappedTrackInfo, selections); Tracks tracks = TrackSelectionUtil.buildTracks(mappedTrackInfo, selections);
ImmutableList<TracksInfo.TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos(); ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
assertThat(trackGroupInfos).hasSize(4); assertThat(trackGroups).hasSize(4);
assertThat(trackGroupInfos.get(0).getTrackGroup()) assertThat(trackGroups.get(0).getTrackGroup())
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0)); .isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0));
assertThat(trackGroupInfos.get(1).getTrackGroup()) assertThat(trackGroups.get(1).getTrackGroup())
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1)); .isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1));
assertThat(trackGroupInfos.get(2).getTrackGroup()) assertThat(trackGroups.get(2).getTrackGroup())
.isEqualTo(mappedTrackInfo.getTrackGroups(1).get(0)); .isEqualTo(mappedTrackInfo.getTrackGroups(1).get(0));
assertThat(trackGroupInfos.get(3).getTrackGroup()) assertThat(trackGroups.get(3).getTrackGroup())
.isEqualTo(mappedTrackInfo.getUnmappedTrackGroups().get(0)); .isEqualTo(mappedTrackInfo.getUnmappedTrackGroups().get(0));
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED); assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
assertThat(trackGroupInfos.get(1).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_SUBTYPE); assertThat(trackGroups.get(1).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_SUBTYPE);
assertThat(trackGroupInfos.get(2).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_DRM); assertThat(trackGroups.get(2).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_DRM);
assertThat(trackGroupInfos.get(2).getTrackSupport(1)).isEqualTo(FORMAT_EXCEEDS_CAPABILITIES); assertThat(trackGroups.get(2).getTrackSupport(1)).isEqualTo(FORMAT_EXCEEDS_CAPABILITIES);
assertThat(trackGroupInfos.get(3).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_TYPE); assertThat(trackGroups.get(3).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_TYPE);
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isFalse(); assertThat(trackGroups.get(0).isTrackSelected(0)).isFalse();
assertThat(trackGroupInfos.get(1).isTrackSelected(0)).isTrue(); assertThat(trackGroups.get(1).isTrackSelected(0)).isTrue();
assertThat(trackGroupInfos.get(2).isTrackSelected(0)).isFalse(); assertThat(trackGroups.get(2).isTrackSelected(0)).isFalse();
assertThat(trackGroupInfos.get(2).isTrackSelected(1)).isTrue(); assertThat(trackGroups.get(2).isTrackSelected(1)).isTrue();
assertThat(trackGroupInfos.get(3).isTrackSelected(0)).isFalse(); assertThat(trackGroups.get(3).isTrackSelected(0)).isFalse();
assertThat(trackGroupInfos.get(0).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO); assertThat(trackGroups.get(0).getType()).isEqualTo(TRACK_TYPE_AUDIO);
assertThat(trackGroupInfos.get(1).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO); assertThat(trackGroups.get(1).getType()).isEqualTo(TRACK_TYPE_AUDIO);
assertThat(trackGroupInfos.get(2).getTrackType()).isEqualTo(TRACK_TYPE_VIDEO); assertThat(trackGroups.get(2).getType()).isEqualTo(TRACK_TYPE_VIDEO);
assertThat(trackGroupInfos.get(3).getTrackType()).isEqualTo(TRACK_TYPE_UNKNOWN); assertThat(trackGroups.get(3).getType()).isEqualTo(TRACK_TYPE_UNKNOWN);
} }
@Test @Test
@ -132,21 +131,21 @@ public class TrackSelectionUtilTest {
ImmutableList.of() ImmutableList.of()
}; };
TracksInfo tracksInfo = TrackSelectionUtil.buildTracksInfo(mappedTrackInfo, selections); Tracks tracks = TrackSelectionUtil.buildTracks(mappedTrackInfo, selections);
ImmutableList<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos(); ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
assertThat(trackGroupInfos).hasSize(2); assertThat(trackGroups).hasSize(2);
assertThat(trackGroupInfos.get(0).getTrackGroup()) assertThat(trackGroups.get(0).getTrackGroup())
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0)); .isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0));
assertThat(trackGroupInfos.get(1).getTrackGroup()) assertThat(trackGroups.get(1).getTrackGroup())
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1)); .isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1));
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED); assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
assertThat(trackGroupInfos.get(1).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED); assertThat(trackGroups.get(1).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
assertThat(trackGroupInfos.get(1).getTrackSupport(1)).isEqualTo(FORMAT_HANDLED); assertThat(trackGroups.get(1).getTrackSupport(1)).isEqualTo(FORMAT_HANDLED);
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isTrue(); assertThat(trackGroups.get(0).isTrackSelected(0)).isTrue();
assertThat(trackGroupInfos.get(1).isTrackSelected(0)).isFalse(); assertThat(trackGroups.get(1).isTrackSelected(0)).isFalse();
assertThat(trackGroupInfos.get(1).isTrackSelected(1)).isTrue(); assertThat(trackGroups.get(1).isTrackSelected(1)).isTrue();
assertThat(trackGroupInfos.get(0).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO); assertThat(trackGroups.get(0).getType()).isEqualTo(TRACK_TYPE_AUDIO);
assertThat(trackGroupInfos.get(1).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO); assertThat(trackGroups.get(1).getType()).isEqualTo(TRACK_TYPE_AUDIO);
} }
} }

View File

@ -710,7 +710,7 @@ import java.util.Map;
} }
// Check for a selected track using an audio renderer. // Check for a selected track using an audio renderer.
return player.getCurrentTracksInfo().isTypeSelected(C.TRACK_TYPE_AUDIO) ? 100 : 0; return player.getCurrentTracks().isTypeSelected(C.TRACK_TYPE_AUDIO) ? 100 : 0;
} }
private void handleAdEvent(AdEvent adEvent) { private void handleAdEvent(AdEvent adEvent) {

View File

@ -24,7 +24,7 @@ import androidx.media3.common.PlaybackException;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.util.Clock; import androidx.media3.common.util.Clock;
import androidx.media3.common.util.ListenerSet; import androidx.media3.common.util.ListenerSet;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
@ -266,8 +266,8 @@ import androidx.media3.test.utils.StubExoPlayer;
} }
@Override @Override
public TracksInfo getCurrentTracksInfo() { public Tracks getCurrentTracks() {
return TracksInfo.EMPTY; return Tracks.EMPTY;
} }
@Override @Override

View File

@ -50,7 +50,7 @@ import androidx.media3.common.Player;
import androidx.media3.common.Rating; import androidx.media3.common.Rating;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue; import androidx.media3.common.text.Cue;
import androidx.media3.common.util.Consumer; import androidx.media3.common.util.Consumer;
@ -1680,8 +1680,8 @@ public class MediaController implements Player {
} }
@Override @Override
public TracksInfo getCurrentTracksInfo() { public Tracks getCurrentTracks() {
return TracksInfo.EMPTY; // TODO(b/178486745) return Tracks.EMPTY; // TODO(b/178486745)
} }
@Override @Override

View File

@ -36,7 +36,7 @@ import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue; import androidx.media3.common.text.Cue;
import androidx.media3.common.util.ConditionVariable; import androidx.media3.common.util.ConditionVariable;
@ -1171,7 +1171,7 @@ public class MockPlayer implements Player {
} }
@Override @Override
public TracksInfo getCurrentTracksInfo() { public Tracks getCurrentTracks() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -31,7 +31,7 @@ import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue; import androidx.media3.common.text.Cue;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
@ -191,7 +191,7 @@ public class StubPlayer extends BasePlayer {
} }
@Override @Override
public TracksInfo getCurrentTracksInfo() { public Tracks getCurrentTracks() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -41,7 +41,7 @@ import androidx.media3.common.MimeTypes;
import androidx.media3.common.PlaybackException; import androidx.media3.common.PlaybackException;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.util.Clock; import androidx.media3.common.util.Clock;
import androidx.media3.common.util.ListenerSet; import androidx.media3.common.util.ListenerSet;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
@ -949,7 +949,7 @@ public final class Transformer {
} }
@Override @Override
public void onTracksInfoChanged(TracksInfo tracksInfo) { public void onTracksChanged(Tracks tracks) {
if (muxerWrapper.getTrackCount() == 0) { if (muxerWrapper.getTrackCount() == 0) {
handleTransformationEnded( handleTransformationEnded(
TransformationException.createForUnexpected( TransformationException.createForUnexpected(

View File

@ -66,8 +66,7 @@ import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionOverride; import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.RepeatModeUtil; import androidx.media3.common.util.RepeatModeUtil;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
@ -1101,39 +1100,37 @@ public class PlayerControlView extends FrameLayout {
|| !player.isCommandAvailable(Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS)) { || !player.isCommandAvailable(Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
return; return;
} }
TracksInfo tracksInfo = player.getCurrentTracksInfo(); Tracks tracks = player.getCurrentTracks();
audioTrackSelectionAdapter.init( audioTrackSelectionAdapter.init(gatherSupportedTrackInfosOfType(tracks, C.TRACK_TYPE_AUDIO));
gatherSupportedTrackInfosOfType(tracksInfo, C.TRACK_TYPE_AUDIO));
if (controlViewLayoutManager.getShowButton(subtitleButton)) { if (controlViewLayoutManager.getShowButton(subtitleButton)) {
textTrackSelectionAdapter.init( textTrackSelectionAdapter.init(gatherSupportedTrackInfosOfType(tracks, C.TRACK_TYPE_TEXT));
gatherSupportedTrackInfosOfType(tracksInfo, C.TRACK_TYPE_TEXT));
} else { } else {
textTrackSelectionAdapter.init(ImmutableList.of()); textTrackSelectionAdapter.init(ImmutableList.of());
} }
} }
private ImmutableList<TrackInformation> gatherSupportedTrackInfosOfType( private ImmutableList<TrackInformation> gatherSupportedTrackInfosOfType(
TracksInfo tracksInfo, @C.TrackType int trackType) { Tracks tracks, @C.TrackType int trackType) {
ImmutableList.Builder<TrackInformation> tracks = new ImmutableList.Builder<>(); ImmutableList.Builder<TrackInformation> trackInfos = new ImmutableList.Builder<>();
List<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos(); List<Tracks.Group> trackGroups = tracks.getGroups();
for (int trackGroupIndex = 0; trackGroupIndex < trackGroupInfos.size(); trackGroupIndex++) { for (int trackGroupIndex = 0; trackGroupIndex < trackGroups.size(); trackGroupIndex++) {
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(trackGroupIndex); Tracks.Group trackGroup = trackGroups.get(trackGroupIndex);
if (trackGroupInfo.getTrackType() != trackType) { if (trackGroup.getType() != trackType) {
continue; continue;
} }
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) { for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
if (!trackGroupInfo.isTrackSupported(trackIndex)) { if (!trackGroup.isTrackSupported(trackIndex)) {
continue; continue;
} }
Format trackFormat = trackGroupInfo.getTrackFormat(trackIndex); Format trackFormat = trackGroup.getTrackFormat(trackIndex);
if ((trackFormat.selectionFlags & C.SELECTION_FLAG_FORCED) != 0) { if ((trackFormat.selectionFlags & C.SELECTION_FLAG_FORCED) != 0) {
continue; continue;
} }
String trackName = trackNameProvider.getTrackName(trackFormat); String trackName = trackNameProvider.getTrackName(trackFormat);
tracks.add(new TrackInformation(tracksInfo, trackGroupIndex, trackIndex, trackName)); trackInfos.add(new TrackInformation(tracks, trackGroupIndex, trackIndex, trackName));
} }
} }
return tracks.build(); return trackInfos.build();
} }
private void updateTimeline() { private void updateTimeline() {
@ -1812,19 +1809,18 @@ public class PlayerControlView extends FrameLayout {
private static final class TrackInformation { private static final class TrackInformation {
public final TrackGroupInfo trackGroupInfo; public final Tracks.Group trackGroup;
public final int trackIndex; public final int trackIndex;
public final String trackName; public final String trackName;
public TrackInformation( public TrackInformation(Tracks tracks, int trackGroupIndex, int trackIndex, String trackName) {
TracksInfo tracksInfo, int trackGroupIndex, int trackIndex, String trackName) { this.trackGroup = tracks.getGroups().get(trackGroupIndex);
this.trackGroupInfo = tracksInfo.getTrackGroupInfos().get(trackGroupIndex);
this.trackIndex = trackIndex; this.trackIndex = trackIndex;
this.trackName = trackName; this.trackName = trackName;
} }
public boolean isSelected() { public boolean isSelected() {
return trackGroupInfo.isTrackSelected(trackIndex); return trackGroup.isTrackSelected(trackIndex);
} }
} }
@ -1924,7 +1920,7 @@ public class PlayerControlView extends FrameLayout {
private boolean hasSelectionOverride(TrackSelectionParameters trackSelectionParameters) { private boolean hasSelectionOverride(TrackSelectionParameters trackSelectionParameters) {
for (int i = 0; i < tracks.size(); i++) { for (int i = 0; i < tracks.size(); i++) {
TrackGroup trackGroup = tracks.get(i).trackGroupInfo.getTrackGroup(); TrackGroup trackGroup = tracks.get(i).trackGroup.getTrackGroup();
if (trackSelectionParameters.overrides.containsKey(trackGroup)) { if (trackSelectionParameters.overrides.containsKey(trackGroup)) {
return true; return true;
} }
@ -1998,7 +1994,7 @@ public class PlayerControlView extends FrameLayout {
onBindViewHolderAtZeroPosition(holder); onBindViewHolderAtZeroPosition(holder);
} else { } else {
TrackInformation track = tracks.get(position - 1); TrackInformation track = tracks.get(position - 1);
TrackGroup trackGroup = track.trackGroupInfo.getTrackGroup(); TrackGroup trackGroup = track.trackGroup.getTrackGroup();
TrackSelectionParameters params = player.getTrackSelectionParameters(); TrackSelectionParameters params = player.getTrackSelectionParameters();
boolean explicitlySelected = params.overrides.get(trackGroup) != null && track.isSelected(); boolean explicitlySelected = params.overrides.get(trackGroup) != null && track.isSelected();
holder.textView.setText(track.trackName); holder.textView.setText(track.trackName);
@ -2013,8 +2009,7 @@ public class PlayerControlView extends FrameLayout {
.setOverrideForType( .setOverrideForType(
new TrackSelectionOverride( new TrackSelectionOverride(
trackGroup, ImmutableList.of(track.trackIndex))) trackGroup, ImmutableList.of(track.trackIndex)))
.setTrackTypeDisabled( .setTrackTypeDisabled(track.trackGroup.getType(), /* disabled= */ false)
track.trackGroupInfo.getTrackType(), /* disabled= */ false)
.build()); .build());
onTrackSelection(track.trackName); onTrackSelection(track.trackName);
settingsWindow.dismiss(); settingsWindow.dismiss();

View File

@ -58,7 +58,7 @@ import androidx.media3.common.Player;
import androidx.media3.common.Player.DiscontinuityReason; import androidx.media3.common.Player.DiscontinuityReason;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.Timeline.Period; import androidx.media3.common.Timeline.Period;
import androidx.media3.common.TracksInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize; import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue; import androidx.media3.common.text.Cue;
import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Assertions;
@ -1216,7 +1216,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
private void updateForCurrentTrackSelections(boolean isNewPlayer) { private void updateForCurrentTrackSelections(boolean isNewPlayer) {
@Nullable Player player = this.player; @Nullable Player player = this.player;
if (player == null || player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) { if (player == null || player.getCurrentTracks().isEmpty()) {
if (!keepContentOnPlayerReset) { if (!keepContentOnPlayerReset) {
hideArtwork(); hideArtwork();
closeShutter(); closeShutter();
@ -1229,7 +1229,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
closeShutter(); closeShutter();
} }
if (player.getCurrentTracksInfo().isTypeSelected(C.TRACK_TYPE_VIDEO)) { if (player.getCurrentTracks().isTypeSelected(C.TRACK_TYPE_VIDEO)) {
// Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened // Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened
// in onRenderedFirstFrame(). // in onRenderedFirstFrame().
hideArtwork(); hideArtwork();
@ -1461,7 +1461,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
} }
@Override @Override
public void onTracksInfoChanged(TracksInfo tracksInfo) { public void onTracksChanged(Tracks tracks) {
// Suppress the update if transitioning to an unprepared period within the same window. This // Suppress the update if transitioning to an unprepared period within the same window. This
// is necessary to avoid closing the shutter when such a transition occurs. See: // is necessary to avoid closing the shutter when such a transition occurs. See:
// https://github.com/google/ExoPlayer/issues/5507. // https://github.com/google/ExoPlayer/issues/5507.
@ -1469,7 +1469,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
Timeline timeline = player.getCurrentTimeline(); Timeline timeline = player.getCurrentTimeline();
if (timeline.isEmpty()) { if (timeline.isEmpty()) {
lastPeriodUidWithTracks = null; lastPeriodUidWithTracks = null;
} else if (!player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) { } else if (!player.getCurrentTracks().isEmpty()) {
lastPeriodUidWithTracks = lastPeriodUidWithTracks =
timeline.getPeriod(player.getCurrentPeriodIndex(), period, /* setIds= */ true).uid; timeline.getPeriod(player.getCurrentPeriodIndex(), period, /* setIds= */ true).uid;
} else if (lastPeriodUidWithTracks != null) { } else if (lastPeriodUidWithTracks != null) {

View File

@ -29,7 +29,7 @@ import androidx.media3.common.Player;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionOverride; import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo.TrackGroupInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
@ -58,7 +58,7 @@ public final class TrackSelectionDialogBuilder {
private final Context context; private final Context context;
private final CharSequence title; private final CharSequence title;
private final List<TrackGroupInfo> trackGroupInfos; private final List<Tracks.Group> trackGroups;
private final DialogCallback callback; private final DialogCallback callback;
@StyleRes private int themeResId; @StyleRes private int themeResId;
@ -75,17 +75,17 @@ public final class TrackSelectionDialogBuilder {
* *
* @param context The context of the dialog. * @param context The context of the dialog.
* @param title The title of the dialog. * @param title The title of the dialog.
* @param trackGroupInfos The {@link TrackGroupInfo TrackGroupInfos} for the track groups. * @param trackGroups The {@link Tracks.Group track groups}.
* @param callback The {@link DialogCallback} invoked when a track selection has been made. * @param callback The {@link DialogCallback} invoked when a track selection has been made.
*/ */
public TrackSelectionDialogBuilder( public TrackSelectionDialogBuilder(
Context context, Context context,
CharSequence title, CharSequence title,
List<TrackGroupInfo> trackGroupInfos, List<Tracks.Group> trackGroups,
DialogCallback callback) { DialogCallback callback) {
this.context = context; this.context = context;
this.title = title; this.title = title;
this.trackGroupInfos = ImmutableList.copyOf(trackGroupInfos); this.trackGroups = ImmutableList.copyOf(trackGroups);
this.callback = callback; this.callback = callback;
overrides = Collections.emptyMap(); overrides = Collections.emptyMap();
} }
@ -102,12 +102,12 @@ public final class TrackSelectionDialogBuilder {
Context context, CharSequence title, Player player, @C.TrackType int trackType) { Context context, CharSequence title, Player player, @C.TrackType int trackType) {
this.context = context; this.context = context;
this.title = title; this.title = title;
List<TrackGroupInfo> allTrackGroupInfos = player.getCurrentTracksInfo().getTrackGroupInfos(); List<Tracks.Group> allTrackGroups = player.getCurrentTracks().getGroups();
trackGroupInfos = new ArrayList<>(); trackGroups = new ArrayList<>();
for (int i = 0; i < allTrackGroupInfos.size(); i++) { for (int i = 0; i < allTrackGroups.size(); i++) {
TrackGroupInfo trackGroupInfo = allTrackGroupInfos.get(i); Tracks.Group trackGroup = allTrackGroups.get(i);
if (trackGroupInfo.getTrackType() == trackType) { if (trackGroup.getType() == trackType) {
trackGroupInfos.add(trackGroupInfo); trackGroups.add(trackGroup);
} }
} }
overrides = Collections.emptyMap(); overrides = Collections.emptyMap();
@ -158,11 +158,11 @@ public final class TrackSelectionDialogBuilder {
} }
/** /**
* Sets the initial track overrides. Any overrides that do not correspond to track groups * Sets the initial track overrides. Any overrides that do not correspond to track groups that
* described by {@code trackGroupInfos} that have been given to this instance will be ignored. If * were passed to the constructor will be ignored. If {@link #setAllowMultipleOverrides(boolean)}
* {@link #setAllowMultipleOverrides(boolean)} hasn't been set to {@code true} then all but one * hasn't been set to {@code true} then all but one override will be ignored. The retained
* override will be ignored. The retained override will be the one whose track group is described * override will be the one whose track group was first in the list of track groups passed to the
* first in {@code trackGroupInfos}. * constructor.
* *
* @param overrides The initially selected track overrides. * @param overrides The initially selected track overrides.
* @return This builder, for convenience. * @return This builder, for convenience.
@ -298,7 +298,7 @@ public final class TrackSelectionDialogBuilder {
selectionView.setTrackNameProvider(trackNameProvider); selectionView.setTrackNameProvider(trackNameProvider);
} }
selectionView.init( selectionView.init(
trackGroupInfos, isDisabled, overrides, trackFormatComparator, /* listener= */ null); trackGroups, isDisabled, overrides, trackFormatComparator, /* listener= */ null);
return (dialog, which) -> return (dialog, which) ->
callback.onTracksSelected(selectionView.getIsDisabled(), selectionView.getOverrides()); callback.onTracksSelected(selectionView.getIsDisabled(), selectionView.getOverrides());
} }

View File

@ -27,7 +27,7 @@ import androidx.annotation.Nullable;
import androidx.media3.common.Format; import androidx.media3.common.Format;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionOverride; import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TracksInfo.TrackGroupInfo; import androidx.media3.common.Tracks;
import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -56,23 +56,23 @@ public class TrackSelectionView extends LinearLayout {
} }
/** /**
* Returns the subset of {@code overrides} that apply to track groups in {@code trackGroupInfos}. * Returns the subset of {@code overrides} that apply to the specified {@code trackGroups}. If
* If {@code allowMultipleOverrides} is {@code} then at most one override is retained, which will * {@code allowMultipleOverrides} is {@code} then at most one override is retained, which will be
* be the one whose track group is first in {@code trackGroupInfos}. * the one whose track group is first in {@code trackGroups}.
* *
* @param overrides The overrides to filter. * @param overrides The overrides to filter.
* @param trackGroupInfos The track groups whose overrides should be retained. * @param trackGroups The track groups whose overrides should be retained.
* @param allowMultipleOverrides Whether more than one override can be retained. * @param allowMultipleOverrides Whether more than one override can be retained.
* @return The filtered overrides. * @return The filtered overrides.
*/ */
public static Map<TrackGroup, TrackSelectionOverride> filterOverrides( public static Map<TrackGroup, TrackSelectionOverride> filterOverrides(
Map<TrackGroup, TrackSelectionOverride> overrides, Map<TrackGroup, TrackSelectionOverride> overrides,
List<TrackGroupInfo> trackGroupInfos, List<Tracks.Group> trackGroups,
boolean allowMultipleOverrides) { boolean allowMultipleOverrides) {
HashMap<TrackGroup, TrackSelectionOverride> filteredOverrides = new HashMap<>(); HashMap<TrackGroup, TrackSelectionOverride> filteredOverrides = new HashMap<>();
for (int i = 0; i < trackGroupInfos.size(); i++) { for (int i = 0; i < trackGroups.size(); i++) {
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(i); Tracks.Group trackGroup = trackGroups.get(i);
@Nullable TrackSelectionOverride override = overrides.get(trackGroupInfo.getTrackGroup()); @Nullable TrackSelectionOverride override = overrides.get(trackGroup.getTrackGroup());
if (override != null && (allowMultipleOverrides || filteredOverrides.isEmpty())) { if (override != null && (allowMultipleOverrides || filteredOverrides.isEmpty())) {
filteredOverrides.put(override.trackGroup, override); filteredOverrides.put(override.trackGroup, override);
} }
@ -85,7 +85,7 @@ public class TrackSelectionView extends LinearLayout {
private final CheckedTextView disableView; private final CheckedTextView disableView;
private final CheckedTextView defaultView; private final CheckedTextView defaultView;
private final ComponentListener componentListener; private final ComponentListener componentListener;
private final List<TrackGroupInfo> trackGroupInfos; private final List<Tracks.Group> trackGroups;
private final Map<TrackGroup, TrackSelectionOverride> overrides; private final Map<TrackGroup, TrackSelectionOverride> overrides;
private boolean allowAdaptiveSelections; private boolean allowAdaptiveSelections;
@ -127,7 +127,7 @@ public class TrackSelectionView extends LinearLayout {
inflater = LayoutInflater.from(context); inflater = LayoutInflater.from(context);
componentListener = new ComponentListener(); componentListener = new ComponentListener();
trackNameProvider = new DefaultTrackNameProvider(getResources()); trackNameProvider = new DefaultTrackNameProvider(getResources());
trackGroupInfos = new ArrayList<>(); trackGroups = new ArrayList<>();
overrides = new HashMap<>(); overrides = new HashMap<>();
// View for disabling the renderer. // View for disabling the renderer.
@ -183,7 +183,7 @@ public class TrackSelectionView extends LinearLayout {
if (!allowMultipleOverrides && overrides.size() > 1) { if (!allowMultipleOverrides && overrides.size() > 1) {
// Re-filter the overrides to retain only one of them. // Re-filter the overrides to retain only one of them.
Map<TrackGroup, TrackSelectionOverride> filteredOverrides = Map<TrackGroup, TrackSelectionOverride> filteredOverrides =
filterOverrides(overrides, trackGroupInfos, /* allowMultipleOverrides= */ false); filterOverrides(overrides, trackGroups, /* allowMultipleOverrides= */ false);
overrides.clear(); overrides.clear();
overrides.putAll(filteredOverrides); overrides.putAll(filteredOverrides);
} }
@ -214,19 +214,19 @@ public class TrackSelectionView extends LinearLayout {
/** /**
* Initialize the view to select tracks from a specified list of track groups. * Initialize the view to select tracks from a specified list of track groups.
* *
* @param trackGroupInfos {@link TrackGroupInfo TrackGroupInfos} for the track groups. * @param trackGroups The {@link Tracks.Group track groups}.
* @param isDisabled Whether the disabled option should be initially selected. * @param isDisabled Whether the disabled option should be initially selected.
* @param overrides The initially selected track overrides. Any overrides that do not correspond * @param overrides The initially selected track overrides. Any overrides that do not correspond
* to track groups described in {@code trackGroupInfos} will be ignored. If {@link * to track groups in {@code trackGroups} will be ignored. If {@link
* #setAllowMultipleOverrides(boolean)} hasn't been set to {@code true} then all but one * #setAllowMultipleOverrides(boolean)} hasn't been set to {@code true} then all but one
* override will be ignored. The retained override will be the one whose track group is * override will be ignored. The retained override will be the one whose track group is first
* described first in {@code trackGroupInfos}. * in {@code trackGroups}.
* @param trackFormatComparator An optional comparator used to determine the display order of the * @param trackFormatComparator An optional comparator used to determine the display order of the
* tracks within each track group. * tracks within each track group.
* @param listener An optional listener to receive selection updates. * @param listener An optional listener to receive selection updates.
*/ */
public void init( public void init(
List<TrackGroupInfo> trackGroupInfos, List<Tracks.Group> trackGroups,
boolean isDisabled, boolean isDisabled,
Map<TrackGroup, TrackSelectionOverride> overrides, Map<TrackGroup, TrackSelectionOverride> overrides,
@Nullable Comparator<Format> trackFormatComparator, @Nullable Comparator<Format> trackFormatComparator,
@ -238,10 +238,10 @@ public class TrackSelectionView extends LinearLayout {
: (o1, o2) -> trackFormatComparator.compare(o1.getFormat(), o2.getFormat()); : (o1, o2) -> trackFormatComparator.compare(o1.getFormat(), o2.getFormat());
this.listener = listener; this.listener = listener;
this.trackGroupInfos.clear(); this.trackGroups.clear();
this.trackGroupInfos.addAll(trackGroupInfos); this.trackGroups.addAll(trackGroups);
this.overrides.clear(); this.overrides.clear();
this.overrides.putAll(filterOverrides(overrides, trackGroupInfos, allowMultipleOverrides)); this.overrides.putAll(filterOverrides(overrides, trackGroups, allowMultipleOverrides));
updateViews(); updateViews();
} }
@ -263,7 +263,7 @@ public class TrackSelectionView extends LinearLayout {
removeViewAt(i); removeViewAt(i);
} }
if (trackGroupInfos.isEmpty()) { if (trackGroups.isEmpty()) {
// The view is not initialized. // The view is not initialized.
disableView.setEnabled(false); disableView.setEnabled(false);
defaultView.setEnabled(false); defaultView.setEnabled(false);
@ -273,17 +273,16 @@ public class TrackSelectionView extends LinearLayout {
defaultView.setEnabled(true); defaultView.setEnabled(true);
// Add per-track views. // Add per-track views.
trackViews = new CheckedTextView[trackGroupInfos.size()][]; trackViews = new CheckedTextView[trackGroups.size()][];
boolean enableMultipleChoiceForMultipleOverrides = shouldEnableMultiGroupSelection(); boolean enableMultipleChoiceForMultipleOverrides = shouldEnableMultiGroupSelection();
for (int trackGroupIndex = 0; trackGroupIndex < trackGroupInfos.size(); trackGroupIndex++) { for (int trackGroupIndex = 0; trackGroupIndex < trackGroups.size(); trackGroupIndex++) {
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(trackGroupIndex); Tracks.Group trackGroup = trackGroups.get(trackGroupIndex);
boolean enableMultipleChoiceForAdaptiveSelections = boolean enableMultipleChoiceForAdaptiveSelections = shouldEnableAdaptiveSelection(trackGroup);
shouldEnableAdaptiveSelection(trackGroupInfo); trackViews[trackGroupIndex] = new CheckedTextView[trackGroup.length];
trackViews[trackGroupIndex] = new CheckedTextView[trackGroupInfo.length];
TrackInfo[] trackInfos = new TrackInfo[trackGroupInfo.length]; TrackInfo[] trackInfos = new TrackInfo[trackGroup.length];
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) { for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
trackInfos[trackIndex] = new TrackInfo(trackGroupInfo, trackIndex); trackInfos[trackIndex] = new TrackInfo(trackGroup, trackIndex);
} }
if (trackInfoComparator != null) { if (trackInfoComparator != null) {
Arrays.sort(trackInfos, trackInfoComparator); Arrays.sort(trackInfos, trackInfoComparator);
@ -302,7 +301,7 @@ public class TrackSelectionView extends LinearLayout {
trackView.setBackgroundResource(selectableItemBackgroundResourceId); trackView.setBackgroundResource(selectableItemBackgroundResourceId);
trackView.setText(trackNameProvider.getTrackName(trackInfos[trackIndex].getFormat())); trackView.setText(trackNameProvider.getTrackName(trackInfos[trackIndex].getFormat()));
trackView.setTag(trackInfos[trackIndex]); trackView.setTag(trackInfos[trackIndex]);
if (trackGroupInfo.isTrackSupported(trackIndex)) { if (trackGroup.isTrackSupported(trackIndex)) {
trackView.setFocusable(true); trackView.setFocusable(true);
trackView.setOnClickListener(componentListener); trackView.setOnClickListener(componentListener);
} else { } else {
@ -321,8 +320,7 @@ public class TrackSelectionView extends LinearLayout {
disableView.setChecked(isDisabled); disableView.setChecked(isDisabled);
defaultView.setChecked(!isDisabled && overrides.size() == 0); defaultView.setChecked(!isDisabled && overrides.size() == 0);
for (int i = 0; i < trackViews.length; i++) { for (int i = 0; i < trackViews.length; i++) {
@Nullable @Nullable TrackSelectionOverride override = overrides.get(trackGroups.get(i).getTrackGroup());
TrackSelectionOverride override = overrides.get(trackGroupInfos.get(i).getTrackGroup());
for (int j = 0; j < trackViews[i].length; j++) { for (int j = 0; j < trackViews[i].length; j++) {
if (override != null) { if (override != null) {
TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(trackViews[i][j].getTag()); TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(trackViews[i][j].getTag());
@ -361,7 +359,7 @@ public class TrackSelectionView extends LinearLayout {
private void onTrackViewClicked(View view) { private void onTrackViewClicked(View view) {
isDisabled = false; isDisabled = false;
TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(view.getTag()); TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(view.getTag());
TrackGroup trackGroup = trackInfo.trackGroupInfo.getTrackGroup(); TrackGroup trackGroup = trackInfo.trackGroup.getTrackGroup();
int trackIndex = trackInfo.trackIndex; int trackIndex = trackInfo.trackIndex;
@Nullable TrackSelectionOverride override = overrides.get(trackGroup); @Nullable TrackSelectionOverride override = overrides.get(trackGroup);
if (override == null) { if (override == null) {
@ -376,7 +374,7 @@ public class TrackSelectionView extends LinearLayout {
// An existing override is being modified. // An existing override is being modified.
ArrayList<Integer> trackIndices = new ArrayList<>(override.trackIndices); ArrayList<Integer> trackIndices = new ArrayList<>(override.trackIndices);
boolean isCurrentlySelected = ((CheckedTextView) view).isChecked(); boolean isCurrentlySelected = ((CheckedTextView) view).isChecked();
boolean isAdaptiveAllowed = shouldEnableAdaptiveSelection(trackInfo.trackGroupInfo); boolean isAdaptiveAllowed = shouldEnableAdaptiveSelection(trackInfo.trackGroup);
boolean isUsingCheckBox = isAdaptiveAllowed || shouldEnableMultiGroupSelection(); boolean isUsingCheckBox = isAdaptiveAllowed || shouldEnableMultiGroupSelection();
if (isCurrentlySelected && isUsingCheckBox) { if (isCurrentlySelected && isUsingCheckBox) {
// Remove the track from the override. // Remove the track from the override.
@ -401,12 +399,12 @@ public class TrackSelectionView extends LinearLayout {
} }
} }
private boolean shouldEnableAdaptiveSelection(TrackGroupInfo trackGroupInfo) { private boolean shouldEnableAdaptiveSelection(Tracks.Group trackGroup) {
return allowAdaptiveSelections && trackGroupInfo.isAdaptiveSupported(); return allowAdaptiveSelections && trackGroup.isAdaptiveSupported();
} }
private boolean shouldEnableMultiGroupSelection() { private boolean shouldEnableMultiGroupSelection() {
return allowMultipleOverrides && trackGroupInfos.size() > 1; return allowMultipleOverrides && trackGroups.size() > 1;
} }
// Internal classes. // Internal classes.
@ -420,16 +418,16 @@ public class TrackSelectionView extends LinearLayout {
} }
private static final class TrackInfo { private static final class TrackInfo {
public final TrackGroupInfo trackGroupInfo; public final Tracks.Group trackGroup;
public final int trackIndex; public final int trackIndex;
public TrackInfo(TrackGroupInfo trackGroupInfo, int trackIndex) { public TrackInfo(Tracks.Group trackGroup, int trackIndex) {
this.trackGroupInfo = trackGroupInfo; this.trackGroup = trackGroup;
this.trackIndex = trackIndex; this.trackIndex = trackIndex;
} }
public Format getFormat() { public Format getFormat() {
return trackGroupInfo.getTrackFormat(trackIndex); return trackGroup.getTrackFormat(trackIndex);
} }
} }
} }