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:
* Flatten `TrackSelectionOverrides` class into `TrackSelectionParameters`,
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:
* Rename `DummySurface` to `PlaceHolderSurface`.
* Audio:

View File

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

View File

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

View File

@ -37,7 +37,7 @@ import androidx.media3.common.MediaItem;
import androidx.media3.common.PlaybackException;
import androidx.media3.common.Player;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.Tracks;
import androidx.media3.common.util.Util;
import androidx.media3.datasource.DataSource;
import androidx.media3.exoplayer.ExoPlayer;
@ -83,7 +83,7 @@ public class PlayerActivity extends AppCompatActivity
private List<MediaItem> mediaItems;
private TrackSelectionParameters trackSelectionParameters;
private DebugTextViewHelper debugViewHelper;
private TracksInfo lastSeenTracksInfo;
private Tracks lastSeenTracks;
private boolean startAutoPlay;
private int startItemIndex;
private long startPosition;
@ -276,7 +276,7 @@ public class PlayerActivity extends AppCompatActivity
RenderersFactory renderersFactory =
DemoUtil.buildRenderersFactory(/* context= */ this, preferExtensionDecoders);
lastSeenTracksInfo = TracksInfo.EMPTY;
lastSeenTracks = Tracks.EMPTY;
player =
new ExoPlayer.Builder(/* context= */ this)
.setRenderersFactory(renderersFactory)
@ -456,22 +456,20 @@ public class PlayerActivity extends AppCompatActivity
@Override
@SuppressWarnings("ReferenceEquality")
public void onTracksInfoChanged(TracksInfo tracksInfo) {
public void onTracksChanged(Tracks tracks) {
updateButtonVisibility();
if (tracksInfo == lastSeenTracksInfo) {
if (tracks == lastSeenTracks) {
return;
}
if (tracksInfo.containsType(C.TRACK_TYPE_VIDEO)
&& !tracksInfo.isTypeSupported(
C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
if (tracks.containsType(C.TRACK_TYPE_VIDEO)
&& !tracks.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
showToast(R.string.error_unsupported_video);
}
if (tracksInfo.containsType(C.TRACK_TYPE_AUDIO)
&& !tracksInfo.isTypeSupported(
C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
if (tracks.containsType(C.TRACK_TYPE_AUDIO)
&& !tracks.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
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.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.media3.common.Tracks;
import androidx.media3.ui.TrackSelectionView;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
@ -79,16 +78,16 @@ public final class TrackSelectionDialog extends DialogFragment {
* specified {@link 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
* specified {@link TracksInfo}.
* specified {@link Tracks}.
*/
public static boolean willHaveContent(TracksInfo tracksInfo) {
for (TrackGroupInfo trackGroupInfo : tracksInfo.getTrackGroupInfos()) {
if (SUPPORTED_TRACK_TYPES.contains(trackGroupInfo.getTrackType())) {
public static boolean willHaveContent(Tracks tracks) {
for (Tracks.Group trackGroup : tracks.getGroups()) {
if (SUPPORTED_TRACK_TYPES.contains(trackGroup.getType())) {
return true;
}
}
@ -105,9 +104,9 @@ public final class TrackSelectionDialog extends DialogFragment {
*/
public static TrackSelectionDialog createForPlayer(
Player player, DialogInterface.OnDismissListener onDismissListener) {
return createForTracksInfoAndParameters(
return createForTracksAndParameters(
R.string.track_selection_title,
player.getCurrentTracksInfo(),
player.getCurrentTracks(),
player.getTrackSelectionParameters(),
/* allowAdaptiveSelections= */ true,
/* 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 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 allowAdaptiveSelections Whether adaptive selections (consisting of more than one track)
* can be made.
@ -128,9 +127,9 @@ public final class TrackSelectionDialog extends DialogFragment {
* @param onDismissListener {@link DialogInterface.OnDismissListener} called when the dialog is
* dismissed.
*/
public static TrackSelectionDialog createForTracksInfoAndParameters(
public static TrackSelectionDialog createForTracksAndParameters(
int titleId,
TracksInfo tracksInfo,
Tracks tracks,
TrackSelectionParameters trackSelectionParameters,
boolean allowAdaptiveSelections,
boolean allowMultipleOverrides,
@ -138,7 +137,7 @@ public final class TrackSelectionDialog extends DialogFragment {
DialogInterface.OnDismissListener onDismissListener) {
TrackSelectionDialog trackSelectionDialog = new TrackSelectionDialog();
trackSelectionDialog.init(
tracksInfo,
tracks,
trackSelectionParameters,
titleId,
allowAdaptiveSelections,
@ -169,7 +168,7 @@ public final class TrackSelectionDialog extends DialogFragment {
}
private void init(
TracksInfo tracksInfo,
Tracks tracks,
TrackSelectionParameters trackSelectionParameters,
int titleId,
boolean allowAdaptiveSelections,
@ -182,16 +181,16 @@ public final class TrackSelectionDialog extends DialogFragment {
for (int i = 0; i < SUPPORTED_TRACK_TYPES.size(); i++) {
@C.TrackType int trackType = SUPPORTED_TRACK_TYPES.get(i);
ArrayList<TrackGroupInfo> trackGroupInfos = new ArrayList<>();
for (TrackGroupInfo trackGroupInfo : tracksInfo.getTrackGroupInfos()) {
if (trackGroupInfo.getTrackType() == trackType) {
trackGroupInfos.add(trackGroupInfo);
ArrayList<Tracks.Group> trackGroups = new ArrayList<>();
for (Tracks.Group trackGroup : tracks.getGroups()) {
if (trackGroup.getType() == trackType) {
trackGroups.add(trackGroup);
}
}
if (!trackGroupInfos.isEmpty()) {
if (!trackGroups.isEmpty()) {
TrackSelectionViewFragment tabFragment = new TrackSelectionViewFragment();
tabFragment.init(
trackGroupInfos,
trackGroups,
trackSelectionParameters.disabledTrackTypes.contains(trackType),
trackSelectionParameters.overrides,
allowAdaptiveSelections,
@ -300,7 +299,7 @@ public final class TrackSelectionDialog extends DialogFragment {
public static final class TrackSelectionViewFragment extends Fragment
implements TrackSelectionView.TrackSelectionListener {
private List<TrackGroupInfo> trackGroupInfos;
private List<Tracks.Group> trackGroups;
private boolean allowAdaptiveSelections;
private boolean allowMultipleOverrides;
@ -313,12 +312,12 @@ public final class TrackSelectionDialog extends DialogFragment {
}
public void init(
List<TrackGroupInfo> trackGroupInfos,
List<Tracks.Group> trackGroups,
boolean isDisabled,
Map<TrackGroup, TrackSelectionOverride> overrides,
boolean allowAdaptiveSelections,
boolean allowMultipleOverrides) {
this.trackGroupInfos = trackGroupInfos;
this.trackGroups = trackGroups;
this.isDisabled = isDisabled;
this.allowAdaptiveSelections = allowAdaptiveSelections;
this.allowMultipleOverrides = allowMultipleOverrides;
@ -326,8 +325,7 @@ public final class TrackSelectionDialog extends DialogFragment {
// handle the case where the TrackSelectionView is never created.
this.overrides =
new HashMap<>(
TrackSelectionView.filterOverrides(
overrides, trackGroupInfos, allowMultipleOverrides));
TrackSelectionView.filterOverrides(overrides, trackGroups, allowMultipleOverrides));
}
@Override
@ -343,7 +341,7 @@ public final class TrackSelectionDialog extends DialogFragment {
trackSelectionView.setAllowMultipleOverrides(allowMultipleOverrides);
trackSelectionView.setAllowAdaptiveSelections(allowAdaptiveSelections);
trackSelectionView.init(
trackGroupInfos,
trackGroups,
isDisabled,
overrides,
/* trackFormatComparator= */ null,

View File

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

View File

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

View File

@ -57,8 +57,8 @@ import java.util.List;
* <ul>
* <li>They can provide a {@link Timeline} representing the structure of the media being played,
* which can be obtained by calling {@link #getCurrentTimeline()}.
* <li>They can provide a {@link TracksInfo} defining the currently available tracks and which are
* selected to be rendered, which can be obtained by calling {@link #getCurrentTracksInfo()}.
* <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 #getCurrentTracks()}.
* </ul>
*/
public interface Player {
@ -676,14 +676,14 @@ public interface Player {
@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
* 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.
@ -1308,7 +1308,7 @@ public interface Player {
int EVENT_TIMELINE_CHANGED = 0;
/** {@link #getCurrentMediaItem()} changed or the player started repeating the current item. */
int EVENT_MEDIA_ITEM_TRANSITION = 1;
/** {@link #getCurrentTracksInfo()} changed. */
/** {@link #getCurrentTracks()} changed. */
int EVENT_TRACKS_CHANGED = 2;
/** {@link #isLoading()} ()} changed. */
int EVENT_IS_LOADING_CHANGED = 3;
@ -2093,11 +2093,11 @@ public interface Player {
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.

View File

@ -92,7 +92,7 @@ public final class TrackSelectionOverride implements Bundleable {
}
/** Returns the {@link C.TrackType} of the overridden track group. */
public @C.TrackType int getTrackType() {
public @C.TrackType int getType() {
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. */
public Builder setOverrideForType(TrackSelectionOverride override) {
clearOverridesOfType(override.getTrackType());
clearOverridesOfType(override.getType());
overrides.put(override.trackGroup, override);
return this;
}
@ -700,7 +700,7 @@ public class TrackSelectionParameters implements Bundleable {
Iterator<TrackSelectionOverride> it = overrides.values().iterator();
while (it.hasNext()) {
TrackSelectionOverride override = it.next();
if (override.getTrackType() == trackType) {
if (override.getType() == trackType) {
it.remove();
}
}

View File

@ -37,14 +37,14 @@ import java.util.Arrays;
import java.util.List;
/** 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
* level to which each track is supported by the player, and whether any of the tracks are
* selected.
*/
public static final class TrackGroupInfo implements Bundleable {
public static final class Group implements Bundleable {
/** The number of tracks in the group. */
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.
*/
@UnstableApi
public TrackGroupInfo(
public Group(
TrackGroup trackGroup,
boolean adaptiveSupported,
@C.FormatSupport int[] trackSupport,
@ -85,7 +85,7 @@ public final class TracksInfo implements Bundleable {
/**
* 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.
*/
public Format getTrackFormat(int trackIndex) {
@ -95,7 +95,7 @@ public final class TracksInfo implements Bundleable {
/**
* 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.
*/
@UnstableApi
@ -107,7 +107,7 @@ public final class TracksInfo implements Bundleable {
* Returns whether a specified track is supported for playback, without exceeding the advertised
* 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.
*/
public boolean isTrackSupported(int trackIndex) {
@ -117,7 +117,7 @@ public final class TracksInfo implements Bundleable {
/**
* 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
* 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
@ -178,7 +178,7 @@ public final class TracksInfo implements Bundleable {
* playing, however some player implementations have ways of getting such information. For
* 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.
*/
public boolean isTrackSelected(int trackIndex) {
@ -186,7 +186,7 @@ public final class TracksInfo implements Bundleable {
}
/** Returns the {@link C.TrackType} of the group. */
public @C.TrackType int getTrackType() {
public @C.TrackType int getType() {
return trackGroup.type;
}
@ -198,7 +198,7 @@ public final class TracksInfo implements Bundleable {
if (other == null || getClass() != other.getClass()) {
return false;
}
TrackGroupInfo that = (TrackGroupInfo) other;
Group that = (Group) other;
return adaptiveSupported == that.adaptiveSupported
&& trackGroup.equals(that.trackGroup)
&& Arrays.equals(trackSupport, that.trackSupport)
@ -241,9 +241,9 @@ public final class TracksInfo implements Bundleable {
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
public static final Creator<TrackGroupInfo> CREATOR =
public static final Creator<Group> CREATOR =
bundle -> {
TrackGroup trackGroup =
fromNullableBundle(
@ -258,7 +258,7 @@ public final class TracksInfo implements Bundleable {
new boolean[trackGroup.length]);
boolean adaptiveSupported =
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) {
@ -266,31 +266,35 @@ public final class TracksInfo implements Bundleable {
}
}
/** An {@code TrackInfo} that contains no tracks. */
@UnstableApi public static final TracksInfo EMPTY = new TracksInfo(ImmutableList.of());
/** Empty tracks. */
@UnstableApi public static final Tracks EMPTY = new Tracks(ImmutableList.of());
private final ImmutableList<TrackGroupInfo> trackGroupInfos;
private final ImmutableList<Group> groups;
/**
* Constructs an instance.
*
* @param trackGroupInfos The {@link TrackGroupInfo TrackGroupInfos} describing the groups of
* tracks.
* @param groups The {@link Group groups} of tracks.
*/
@UnstableApi
public TracksInfo(List<TrackGroupInfo> trackGroupInfos) {
this.trackGroupInfos = ImmutableList.copyOf(trackGroupInfos);
public Tracks(List<Group> groups) {
this.groups = ImmutableList.copyOf(groups);
}
/** Returns the {@link TrackGroupInfo TrackGroupInfos} describing the groups of tracks. */
public ImmutableList<TrackGroupInfo> getTrackGroupInfos() {
return trackGroupInfos;
/** Returns the {@link Group groups} of tracks. */
public ImmutableList<Group> getGroups() {
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. */
public boolean containsType(@C.TrackType int trackType) {
for (int i = 0; i < trackGroupInfos.size(); i++) {
if (trackGroupInfos.get(i).getTrackType() == trackType) {
for (int i = 0; i < groups.size(); i++) {
if (groups.get(i).getType() == trackType) {
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
* TrackGroupInfo#isTrackSupported(int) supported}.
* Group#isTrackSupported(int) supported}.
*/
public boolean isTypeSupported(@C.TrackType int trackType) {
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
* TrackGroupInfo#isTrackSupported(int, boolean) supported}.
* Group#isTrackSupported(int, boolean) supported}.
*
* @param allowExceedsCapabilities Whether to consider the track as supported if it has a
* 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.
*/
public boolean isTypeSupported(@C.TrackType int trackType, boolean allowExceedsCapabilities) {
for (int i = 0; i < trackGroupInfos.size(); i++) {
if (trackGroupInfos.get(i).getTrackType() == trackType) {
if (trackGroupInfos.get(i).isSupported(allowExceedsCapabilities)) {
for (int i = 0; i < groups.size(); i++) {
if (groups.get(i).getType() == trackType) {
if (groups.get(i).isSupported(allowExceedsCapabilities)) {
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. */
public boolean isTypeSelected(@C.TrackType int trackType) {
for (int i = 0; i < trackGroupInfos.size(); i++) {
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(i);
if (trackGroupInfo.isSelected() && trackGroupInfo.getTrackType() == trackType) {
for (int i = 0; i < groups.size(); i++) {
Group group = groups.get(i);
if (group.isSelected() && group.getType() == trackType) {
return true;
}
}
@ -365,13 +369,13 @@ public final class TracksInfo implements Bundleable {
if (other == null || getClass() != other.getClass()) {
return false;
}
TracksInfo that = (TracksInfo) other;
return trackGroupInfos.equals(that.trackGroupInfos);
Tracks that = (Tracks) other;
return groups.equals(that.groups);
}
@Override
public int hashCode() {
return trackGroupInfos.hashCode();
return groups.hashCode();
}
// Bundleable implementation.
@ -379,31 +383,30 @@ public final class TracksInfo implements Bundleable {
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({
FIELD_TRACK_GROUP_INFOS,
FIELD_TRACK_GROUPS,
})
private @interface FieldNumber {}
private static final int FIELD_TRACK_GROUP_INFOS = 0;
private static final int FIELD_TRACK_GROUPS = 0;
@UnstableApi
@Override
public Bundle toBundle() {
Bundle bundle = new Bundle();
bundle.putParcelableArrayList(
keyForField(FIELD_TRACK_GROUP_INFOS), toBundleArrayList(trackGroupInfos));
bundle.putParcelableArrayList(keyForField(FIELD_TRACK_GROUPS), toBundleArrayList(groups));
return bundle;
}
/** Object that can restore a {@code TracksInfo} from a {@link Bundle}. */
/** Object that can restore tracks from a {@link Bundle}. */
@UnstableApi
public static final Creator<TracksInfo> CREATOR =
public static final Creator<Tracks> CREATOR =
bundle -> {
List<TrackGroupInfo> trackGroupInfos =
List<Group> groups =
fromBundleNullableList(
TrackGroupInfo.CREATOR,
bundle.getParcelableArrayList(keyForField(FIELD_TRACK_GROUP_INFOS)),
Group.CREATOR,
bundle.getParcelableArrayList(keyForField(FIELD_TRACK_GROUPS)),
/* defaultValue= */ ImmutableList.of());
return new TracksInfo(trackGroupInfos);
return new Tracks(groups);
};
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.PriorityTaskManager;
import androidx.media3.common.Timeline;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue;
import androidx.media3.common.util.Clock;
@ -1222,8 +1222,8 @@ public interface ExoPlayer extends Player {
/**
* Returns the available track groups.
*
* @see Listener#onTracksInfoChanged(TracksInfo)
* @deprecated Use {@link #getCurrentTracksInfo()}.
* @see Listener#onTracksChanged(Tracks)
* @deprecated Use {@link #getCurrentTracks()}.
*/
@UnstableApi
@Deprecated
@ -1233,8 +1233,8 @@ public interface ExoPlayer extends Player {
* Returns the current track selections for each renderer, which may include {@code null} elements
* if some renderers do not have any selected tracks.
*
* @see Listener#onTracksInfoChanged(TracksInfo)
* @deprecated Use {@link #getCurrentTracksInfo()}.
* @see Listener#onTracksChanged(Tracks)
* @deprecated Use {@link #getCurrentTracks()}.
*/
@UnstableApi
@Deprecated

View File

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

View File

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

View File

@ -46,7 +46,7 @@ import androidx.media3.common.Player.PlaybackSuppressionReason;
import androidx.media3.common.Player.TimelineChangeReason;
import androidx.media3.common.Timeline;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue;
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.
*/
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;
/** {@link Player#isLoading()} ()} 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) {}
/**
* Called when the available or selected tracks change.
* Called when the tracks change.
*
* @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.

View File

@ -39,7 +39,7 @@ import androidx.media3.common.Timeline;
import androidx.media3.common.Timeline.Period;
import androidx.media3.common.Timeline.Window;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue;
import androidx.media3.common.util.Clock;
@ -483,12 +483,12 @@ public class DefaultAnalyticsCollector implements AnalyticsCollector {
}
@Override
public void onTracksInfoChanged(TracksInfo tracksInfo) {
public void onTracksChanged(Tracks tracks) {
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
sendEvent(
eventTime,
AnalyticsListener.EVENT_TRACKS_CHANGED,
listener -> listener.onTracksInfoChanged(eventTime, tracksInfo));
listener -> listener.onTracksChanged(eventTime, tracks));
}
@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.Player;
import androidx.media3.common.Timeline;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize;
import androidx.media3.common.util.NetworkTypeObserver;
import androidx.media3.common.util.UnstableApi;
@ -340,8 +339,7 @@ public final class MediaMetricsListener
}
}
if (events.contains(EVENT_TRACKS_CHANGED) && metricsBuilder != null) {
@Nullable
DrmInitData drmInitData = getDrmInitData(player.getCurrentTracksInfo().getTrackGroupInfos());
@Nullable DrmInitData drmInitData = getDrmInitData(player.getCurrentTracks().getGroups());
if (drmInitData != null) {
castNonNull(metricsBuilder).setDrmType(getDrmType(drmInitData));
}
@ -372,10 +370,10 @@ public final class MediaMetricsListener
private void maybeReportTrackChanges(Player player, Events events, long realtimeMs) {
if (events.contains(EVENT_TRACKS_CHANGED)) {
TracksInfo tracksInfo = player.getCurrentTracksInfo();
boolean isVideoSelected = tracksInfo.isTypeSelected(C.TRACK_TYPE_VIDEO);
boolean isAudioSelected = tracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO);
boolean isTextSelected = tracksInfo.isTypeSelected(C.TRACK_TYPE_TEXT);
Tracks tracks = player.getCurrentTracks();
boolean isVideoSelected = tracks.isTypeSelected(C.TRACK_TYPE_VIDEO);
boolean isAudioSelected = tracks.isTypeSelected(C.TRACK_TYPE_AUDIO);
boolean isTextSelected = tracks.isTypeSelected(C.TRACK_TYPE_TEXT);
if (isVideoSelected || isAudioSelected || isTextSelected) {
// Ignore updates with insufficient information where no tracks are selected.
if (!isVideoSelected) {
@ -822,11 +820,11 @@ public final class MediaMetricsListener
}
@Nullable
private static DrmInitData getDrmInitData(ImmutableList<TrackGroupInfo> trackGroupInfos) {
for (TrackGroupInfo trackGroupInfo : trackGroupInfos) {
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) {
if (trackGroupInfo.isTrackSelected(trackIndex)) {
@Nullable DrmInitData drmInitData = trackGroupInfo.getTrackFormat(trackIndex).drmInitData;
private static DrmInitData getDrmInitData(ImmutableList<Tracks.Group> trackGroups) {
for (Tracks.Group trackGroup : trackGroups) {
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
if (trackGroup.isTrackSelected(trackIndex)) {
@Nullable DrmInitData drmInitData = trackGroup.getTrackFormat(trackIndex).drmInitData;
if (drmInitData != null) {
return drmInitData;
}

View File

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

View File

@ -33,7 +33,7 @@ import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionOverride;
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.UnstableApi;
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.
*
* @param periodIndex The period index.
* @return The {@link TracksInfo} for the period. May be {@link TracksInfo#EMPTY} for single
* stream content.
* @return The {@link Tracks} for the period. May be {@link Tracks#EMPTY} for single stream
* content.
*/
public TracksInfo getTracksInfo(int periodIndex) {
public Tracks getTracks(int periodIndex) {
assertPreparedWithMedia();
return TrackSelectionUtil.buildTracksInfo(
return TrackSelectionUtil.buildTracks(
mappedTrackInfos[periodIndex], immutableTrackSelectionsByPeriodAndRenderer[periodIndex]);
}

View File

@ -1962,12 +1962,11 @@ public class DefaultTrackSelector extends MappingTrackSelector {
if (override == null) {
continue;
}
@Nullable
TrackSelectionOverride existingOverride = overridesByType.get(override.getTrackType());
@Nullable TrackSelectionOverride existingOverride = overridesByType.get(override.getType());
// Only replace an existing override if it's empty and the one being considered is not.
if (existingOverride == null
|| (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.Timeline;
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.Util;
import androidx.media3.exoplayer.ExoPlaybackException;
@ -427,9 +427,9 @@ public abstract class MappingTrackSelector extends TrackSelector {
periodId,
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.media3.common.C;
import androidx.media3.common.TrackGroup;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.media3.common.Tracks;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.exoplayer.RendererCapabilities;
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.
*
* @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
* @param selections The track selections, indexed by renderer. A null entry indicates that a
* 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.
public static TracksInfo buildTracksInfo(
public static Tracks buildTracks(
MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
@NullableType TrackSelection[] selections) {
List<? extends TrackSelection>[] listSelections = new List[selections.length];
@ -153,22 +152,22 @@ public final class TrackSelectionUtil {
@Nullable TrackSelection selection = selections[i];
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.
*
* @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
* @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.
* @return The corresponding {@link TracksInfo}.
* @return The corresponding {@link Tracks}.
*/
public static TracksInfo buildTracksInfo(
public static Tracks buildTracks(
MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
List<? extends TrackSelection>[] selections) {
ImmutableList.Builder<TrackGroupInfo> trackGroupInfos = new ImmutableList.Builder<>();
ImmutableList.Builder<Tracks.Group> trackGroups = new ImmutableList.Builder<>();
for (int rendererIndex = 0;
rendererIndex < mappedTrackInfo.getRendererCount();
rendererIndex++) {
@ -196,8 +195,7 @@ public final class TrackSelectionUtil {
}
selected[trackIndex] = isTrackSelected;
}
trackGroupInfos.add(
new TrackGroupInfo(trackGroup, adaptiveSupported, trackSupport, selected));
trackGroups.add(new Tracks.Group(trackGroup, adaptiveSupported, trackSupport, selected));
}
}
TrackGroupArray unmappedTrackGroups = mappedTrackInfo.getUnmappedTrackGroups();
@ -206,9 +204,9 @@ public final class TrackSelectionUtil {
@C.FormatSupport int[] trackSupport = new int[trackGroup.length];
Arrays.fill(trackSupport, C.FORMAT_UNSUPPORTED_TYPE);
boolean[] selected = new boolean[trackGroup.length];
trackGroupInfos.add(
new TrackGroupInfo(trackGroup, /* adaptiveSupported= */ false, trackSupport, selected));
trackGroups.add(
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;
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.Util;
import androidx.media3.exoplayer.RendererConfiguration;
@ -36,7 +36,7 @@ public final class TrackSelectorResult {
/** A {@link ExoTrackSelection} array containing the track selection for each renderer. */
public final @NullableType ExoTrackSelection[] selections;
/** 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)}
* should the selections be activated.
@ -51,21 +51,21 @@ public final class TrackSelectorResult {
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
* {@code null}.
* @deprecated Use {@link #TrackSelectorResult(RendererConfiguration[], ExoTrackSelection[],
* TracksInfo, Object)}.
* Tracks, Object)}.
*/
@Deprecated
public TrackSelectorResult(
@NullableType RendererConfiguration[] rendererConfigurations,
@NullableType ExoTrackSelection[] selections,
@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
* indicates the corresponding renderer should be disabled.
* @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
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
* {@code null}.
@ -73,11 +73,11 @@ public final class TrackSelectorResult {
public TrackSelectorResult(
@NullableType RendererConfiguration[] rendererConfigurations,
@NullableType ExoTrackSelection[] selections,
TracksInfo tracksInfo,
Tracks tracks,
@Nullable Object info) {
this.rendererConfigurations = rendererConfigurations;
this.selections = selections.clone();
this.tracksInfo = tracksInfo;
this.tracks = tracks;
this.info = info;
length = rendererConfigurations.length;
}

View File

@ -31,7 +31,7 @@ import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player;
import androidx.media3.common.Player.PlaybackSuppressionReason;
import androidx.media3.common.Timeline;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.Tracks;
import androidx.media3.common.VideoSize;
import androidx.media3.common.util.Log;
import androidx.media3.common.util.UnstableApi;
@ -261,23 +261,23 @@ public class EventLogger implements AnalyticsListener {
}
@Override
public void onTracksInfoChanged(EventTime eventTime, TracksInfo tracksInfo) {
public void onTracksChanged(EventTime eventTime, Tracks tracks) {
logd("tracks [" + getEventTimeString(eventTime));
// Log tracks associated to renderers.
ImmutableList<TracksInfo.TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
for (int groupIndex = 0; groupIndex < trackGroupInfos.size(); groupIndex++) {
TracksInfo.TrackGroupInfo trackGroupInfo = trackGroupInfos.get(groupIndex);
ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
for (int groupIndex = 0; groupIndex < trackGroups.size(); groupIndex++) {
Tracks.Group trackGroup = trackGroups.get(groupIndex);
logd(" group [");
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) {
String status = getTrackStatusString(trackGroupInfo.isTrackSelected(trackIndex));
String formatSupport = getFormatSupportString(trackGroupInfo.getTrackSupport(trackIndex));
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
String status = getTrackStatusString(trackGroup.isTrackSelected(trackIndex));
String formatSupport = getFormatSupportString(trackGroup.getTrackSupport(trackIndex));
logd(
" "
+ status
+ " Track:"
+ trackIndex
+ ", "
+ Format.toLogString(trackGroupInfo.getTrackFormat(trackIndex))
+ Format.toLogString(trackGroup.getTrackFormat(trackIndex))
+ ", supported="
+ formatSupport);
}
@ -286,8 +286,8 @@ public class EventLogger implements AnalyticsListener {
// TODO: Replace this with an override of onMediaMetadataChanged.
// Log metadata for at most one of the selected tracks.
boolean loggedMetadata = false;
for (int groupIndex = 0; !loggedMetadata && groupIndex < trackGroupInfos.size(); groupIndex++) {
TracksInfo.TrackGroupInfo trackGroup = trackGroupInfos.get(groupIndex);
for (int groupIndex = 0; !loggedMetadata && groupIndex < trackGroups.size(); groupIndex++) {
Tracks.Group trackGroup = trackGroups.get(groupIndex);
for (int trackIndex = 0; !loggedMetadata && trackIndex < trackGroup.length; trackIndex++) {
if (trackGroup.isTrackSelected(trackIndex)) {
@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.Window;
import androidx.media3.common.TrackGroup;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.media3.common.Tracks;
import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.Clock;
import androidx.media3.common.util.Util;
@ -277,15 +276,15 @@ public final class ExoPlayerTest {
argThat(noUid(timeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
inOrder
.verify(mockListener)
.onTracksInfoChanged(
.onTracksChanged(
eq(
new TracksInfo(
new Tracks(
ImmutableList.of(
new TrackGroupInfo(
new Tracks.Group(
new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT),
/* adaptiveSupported= */ false,
new int[] {C.FORMAT_HANDLED},
/* tracksSelected= */ new boolean[] {true})))));
/* trackSelected= */ new boolean[] {true})))));
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
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));
inOrder
.verify(mockPlayerListener)
.onTracksInfoChanged(
.onTracksChanged(
eq(
new TracksInfo(
new Tracks(
ImmutableList.of(
new TrackGroupInfo(
new Tracks.Group(
new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT),
/* adaptiveSupported= */ false,
new int[] {C.FORMAT_HANDLED},
/* tracksSelected= */ new boolean[] {true})))));
/* trackSelected= */ new boolean[] {true})))));
assertThat(renderer.isEnded).isTrue();
}
@ -3426,7 +3425,7 @@ public final class ExoPlayerTest {
.waitForPendingPlayerCommands()
.play()
.build();
List<TracksInfo> tracksInfoList = new ArrayList<>();
List<Tracks> tracksList = new ArrayList<>();
new ExoPlayerTestRunner.Builder(context)
.setMediaSources(mediaSource)
.setSupportedFormats(ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT)
@ -3434,21 +3433,21 @@ public final class ExoPlayerTest {
.setPlayerListener(
new Player.Listener() {
@Override
public void onTracksInfoChanged(TracksInfo tracksInfo) {
tracksInfoList.add(tracksInfo);
public void onTracksChanged(Tracks tracks) {
tracksList.add(tracks);
}
})
.build()
.start()
.blockUntilEnded(TIMEOUT_MS);
assertThat(tracksInfoList).hasSize(3);
assertThat(tracksList).hasSize(3);
// 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 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);
assertThat(tracksInfoList.get(1)).isEqualTo(TracksInfo.EMPTY);
assertThat(tracksInfoList.get(2).getTrackGroupInfos().get(0).getTrackFormat(0))
assertThat(tracksList.get(1)).isEqualTo(Tracks.EMPTY);
assertThat(tracksList.get(2).getGroups().get(0).getTrackFormat(0))
.isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
}
@ -7993,7 +7992,7 @@ public final class ExoPlayerTest {
}
};
AtomicReference<Timeline> timelineAfterError = new AtomicReference<>();
AtomicReference<TracksInfo> trackInfosAfterError = new AtomicReference<>();
AtomicReference<Tracks> trackInfosAfterError = new AtomicReference<>();
AtomicInteger mediaItemIndexAfterError = new AtomicInteger();
ActionSchedule actionSchedule =
new ActionSchedule.Builder(TAG)
@ -8006,7 +8005,7 @@ public final class ExoPlayerTest {
@Override
public void onPlayerError(EventTime eventTime, PlaybackException error) {
timelineAfterError.set(player.getCurrentTimeline());
trackInfosAfterError.set(player.getCurrentTracksInfo());
trackInfosAfterError.set(player.getCurrentTracks());
mediaItemIndexAfterError.set(player.getCurrentMediaItemIndex());
}
});
@ -8035,8 +8034,8 @@ public final class ExoPlayerTest {
assertThat(timelineAfterError.get().getWindowCount()).isEqualTo(1);
assertThat(mediaItemIndexAfterError.get()).isEqualTo(0);
assertThat(trackInfosAfterError.get().getTrackGroupInfos()).hasSize(1);
assertThat(trackInfosAfterError.get().getTrackGroupInfos().get(0).getTrackFormat(0))
assertThat(trackInfosAfterError.get().getGroups()).hasSize(1);
assertThat(trackInfosAfterError.get().getGroups().get(0).getTrackFormat(0))
.isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
assertThat(trackInfosAfterError.get().isTypeSelected(C.TRACK_TYPE_VIDEO)).isFalse();
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()).onPlaybackStateChanged(anyInt());
verify(listener, atLeastOnce()).onIsLoadingChanged(anyBoolean());
verify(listener, atLeastOnce()).onTracksInfoChanged(any());
verify(listener, atLeastOnce()).onTracksChanged(any());
verify(listener, atLeastOnce()).onMediaMetadataChanged(any());
verify(listener, atLeastOnce()).onPlayWhenReadyChanged(anyBoolean(), anyInt());
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.Player;
import androidx.media3.common.Timeline;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.Tracks;
import androidx.media3.common.util.Clock;
import androidx.media3.exoplayer.analytics.AnalyticsCollector;
import androidx.media3.exoplayer.analytics.DefaultAnalyticsCollector;
@ -1141,7 +1141,7 @@ public final class MediaPeriodQueueTest {
new TrackSelectorResult(
new RendererConfiguration[0],
new ExoTrackSelection[0],
TracksInfo.EMPTY,
Tracks.EMPTY,
/* info= */ null));
}

View File

@ -81,7 +81,7 @@ import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player;
import androidx.media3.common.Timeline;
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.util.Clock;
import androidx.media3.common.util.ConditionVariable;
@ -1729,7 +1729,7 @@ public final class DefaultAnalyticsCollectorTest {
ArgumentCaptor<AnalyticsListener.EventTime> individualTracksChangedEventTimes =
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
verify(listener, atLeastOnce())
.onTracksInfoChanged(individualTracksChangedEventTimes.capture(), any());
.onTracksChanged(individualTracksChangedEventTimes.capture(), any());
ArgumentCaptor<AnalyticsListener.EventTime> individualPlayWhenReadyChangedEventTimes =
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
verify(listener, atLeastOnce())
@ -2243,7 +2243,7 @@ public final class DefaultAnalyticsCollectorTest {
}
@Override
public void onTracksInfoChanged(EventTime eventTime, TracksInfo tracksInfo) {
public void onTracksChanged(EventTime eventTime, Tracks tracks) {
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.TrackGroup;
import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.Tracks;
import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.ExoPlaybackException;
import androidx.media3.exoplayer.RendererCapabilities;
@ -2224,10 +2224,10 @@ public final class DefaultTrackSelectorTest {
public void selectTracks_multipleRenderer_allSelected() throws Exception {
RendererCapabilities[] rendererCapabilities =
new RendererCapabilities[] {VIDEO_CAPABILITIES, AUDIO_CAPABILITIES, AUDIO_CAPABILITIES};
TrackGroupArray trackGroups = new TrackGroupArray(AUDIO_TRACK_GROUP);
TrackGroupArray trackGroupArray = new TrackGroupArray(AUDIO_TRACK_GROUP);
TrackSelectorResult result =
trackSelector.selectTracks(rendererCapabilities, trackGroups, periodId, TIMELINE);
trackSelector.selectTracks(rendererCapabilities, trackGroupArray, periodId, TIMELINE);
assertThat(result.length).isEqualTo(3);
assertThat(result.rendererConfigurations)
@ -2235,14 +2235,14 @@ public final class DefaultTrackSelectorTest {
.containsExactly(null, DEFAULT, null)
.inOrder();
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();
ImmutableList<TracksInfo.TrackGroupInfo> trackGroupInfos =
result.tracksInfo.getTrackGroupInfos();
assertThat(trackGroupInfos).hasSize(1);
assertThat(trackGroupInfos.get(0).getTrackGroup()).isEqualTo(AUDIO_TRACK_GROUP);
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isTrue();
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
ImmutableList<Tracks.Group> trackGroups = result.tracks.getGroups();
assertThat(trackGroups).hasSize(1);
assertThat(trackGroups.get(0).getTrackGroup()).isEqualTo(AUDIO_TRACK_GROUP);
assertThat(trackGroups.get(0).isTrackSelected(0)).isTrue();
assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
}
/** 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.TrackGroup;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.media3.common.Tracks;
import androidx.media3.exoplayer.source.TrackGroupArray;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
@ -73,32 +72,32 @@ public class TrackSelectionUtilTest {
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();
assertThat(trackGroupInfos).hasSize(4);
assertThat(trackGroupInfos.get(0).getTrackGroup())
ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
assertThat(trackGroups).hasSize(4);
assertThat(trackGroups.get(0).getTrackGroup())
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0));
assertThat(trackGroupInfos.get(1).getTrackGroup())
assertThat(trackGroups.get(1).getTrackGroup())
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1));
assertThat(trackGroupInfos.get(2).getTrackGroup())
assertThat(trackGroups.get(2).getTrackGroup())
.isEqualTo(mappedTrackInfo.getTrackGroups(1).get(0));
assertThat(trackGroupInfos.get(3).getTrackGroup())
assertThat(trackGroups.get(3).getTrackGroup())
.isEqualTo(mappedTrackInfo.getUnmappedTrackGroups().get(0));
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
assertThat(trackGroupInfos.get(1).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_SUBTYPE);
assertThat(trackGroupInfos.get(2).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_DRM);
assertThat(trackGroupInfos.get(2).getTrackSupport(1)).isEqualTo(FORMAT_EXCEEDS_CAPABILITIES);
assertThat(trackGroupInfos.get(3).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_TYPE);
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isFalse();
assertThat(trackGroupInfos.get(1).isTrackSelected(0)).isTrue();
assertThat(trackGroupInfos.get(2).isTrackSelected(0)).isFalse();
assertThat(trackGroupInfos.get(2).isTrackSelected(1)).isTrue();
assertThat(trackGroupInfos.get(3).isTrackSelected(0)).isFalse();
assertThat(trackGroupInfos.get(0).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO);
assertThat(trackGroupInfos.get(1).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO);
assertThat(trackGroupInfos.get(2).getTrackType()).isEqualTo(TRACK_TYPE_VIDEO);
assertThat(trackGroupInfos.get(3).getTrackType()).isEqualTo(TRACK_TYPE_UNKNOWN);
assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
assertThat(trackGroups.get(1).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_SUBTYPE);
assertThat(trackGroups.get(2).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_DRM);
assertThat(trackGroups.get(2).getTrackSupport(1)).isEqualTo(FORMAT_EXCEEDS_CAPABILITIES);
assertThat(trackGroups.get(3).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_TYPE);
assertThat(trackGroups.get(0).isTrackSelected(0)).isFalse();
assertThat(trackGroups.get(1).isTrackSelected(0)).isTrue();
assertThat(trackGroups.get(2).isTrackSelected(0)).isFalse();
assertThat(trackGroups.get(2).isTrackSelected(1)).isTrue();
assertThat(trackGroups.get(3).isTrackSelected(0)).isFalse();
assertThat(trackGroups.get(0).getType()).isEqualTo(TRACK_TYPE_AUDIO);
assertThat(trackGroups.get(1).getType()).isEqualTo(TRACK_TYPE_AUDIO);
assertThat(trackGroups.get(2).getType()).isEqualTo(TRACK_TYPE_VIDEO);
assertThat(trackGroups.get(3).getType()).isEqualTo(TRACK_TYPE_UNKNOWN);
}
@Test
@ -132,21 +131,21 @@ public class TrackSelectionUtilTest {
ImmutableList.of()
};
TracksInfo tracksInfo = TrackSelectionUtil.buildTracksInfo(mappedTrackInfo, selections);
Tracks tracks = TrackSelectionUtil.buildTracks(mappedTrackInfo, selections);
ImmutableList<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
assertThat(trackGroupInfos).hasSize(2);
assertThat(trackGroupInfos.get(0).getTrackGroup())
ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
assertThat(trackGroups).hasSize(2);
assertThat(trackGroups.get(0).getTrackGroup())
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0));
assertThat(trackGroupInfos.get(1).getTrackGroup())
assertThat(trackGroups.get(1).getTrackGroup())
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1));
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
assertThat(trackGroupInfos.get(1).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
assertThat(trackGroupInfos.get(1).getTrackSupport(1)).isEqualTo(FORMAT_HANDLED);
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isTrue();
assertThat(trackGroupInfos.get(1).isTrackSelected(0)).isFalse();
assertThat(trackGroupInfos.get(1).isTrackSelected(1)).isTrue();
assertThat(trackGroupInfos.get(0).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO);
assertThat(trackGroupInfos.get(1).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO);
assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
assertThat(trackGroups.get(1).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
assertThat(trackGroups.get(1).getTrackSupport(1)).isEqualTo(FORMAT_HANDLED);
assertThat(trackGroups.get(0).isTrackSelected(0)).isTrue();
assertThat(trackGroups.get(1).isTrackSelected(0)).isFalse();
assertThat(trackGroups.get(1).isTrackSelected(1)).isTrue();
assertThat(trackGroups.get(0).getType()).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.
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) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -58,7 +58,7 @@ import androidx.media3.common.Player;
import androidx.media3.common.Player.DiscontinuityReason;
import androidx.media3.common.Timeline;
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.text.Cue;
import androidx.media3.common.util.Assertions;
@ -1216,7 +1216,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
private void updateForCurrentTrackSelections(boolean isNewPlayer) {
@Nullable Player player = this.player;
if (player == null || player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) {
if (player == null || player.getCurrentTracks().isEmpty()) {
if (!keepContentOnPlayerReset) {
hideArtwork();
closeShutter();
@ -1229,7 +1229,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
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
// in onRenderedFirstFrame().
hideArtwork();
@ -1461,7 +1461,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
}
@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
// is necessary to avoid closing the shutter when such a transition occurs. See:
// https://github.com/google/ExoPlayer/issues/5507.
@ -1469,7 +1469,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
Timeline timeline = player.getCurrentTimeline();
if (timeline.isEmpty()) {
lastPeriodUidWithTracks = null;
} else if (!player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) {
} else if (!player.getCurrentTracks().isEmpty()) {
lastPeriodUidWithTracks =
timeline.getPeriod(player.getCurrentPeriodIndex(), period, /* setIds= */ true).uid;
} else if (lastPeriodUidWithTracks != null) {

View File

@ -29,7 +29,7 @@ import androidx.media3.common.Player;
import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
import androidx.media3.common.Tracks;
import androidx.media3.common.util.UnstableApi;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@ -58,7 +58,7 @@ public final class TrackSelectionDialogBuilder {
private final Context context;
private final CharSequence title;
private final List<TrackGroupInfo> trackGroupInfos;
private final List<Tracks.Group> trackGroups;
private final DialogCallback callback;
@StyleRes private int themeResId;
@ -75,17 +75,17 @@ public final class TrackSelectionDialogBuilder {
*
* @param context The context 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.
*/
public TrackSelectionDialogBuilder(
Context context,
CharSequence title,
List<TrackGroupInfo> trackGroupInfos,
List<Tracks.Group> trackGroups,
DialogCallback callback) {
this.context = context;
this.title = title;
this.trackGroupInfos = ImmutableList.copyOf(trackGroupInfos);
this.trackGroups = ImmutableList.copyOf(trackGroups);
this.callback = callback;
overrides = Collections.emptyMap();
}
@ -102,12 +102,12 @@ public final class TrackSelectionDialogBuilder {
Context context, CharSequence title, Player player, @C.TrackType int trackType) {
this.context = context;
this.title = title;
List<TrackGroupInfo> allTrackGroupInfos = player.getCurrentTracksInfo().getTrackGroupInfos();
trackGroupInfos = new ArrayList<>();
for (int i = 0; i < allTrackGroupInfos.size(); i++) {
TrackGroupInfo trackGroupInfo = allTrackGroupInfos.get(i);
if (trackGroupInfo.getTrackType() == trackType) {
trackGroupInfos.add(trackGroupInfo);
List<Tracks.Group> allTrackGroups = player.getCurrentTracks().getGroups();
trackGroups = new ArrayList<>();
for (int i = 0; i < allTrackGroups.size(); i++) {
Tracks.Group trackGroup = allTrackGroups.get(i);
if (trackGroup.getType() == trackType) {
trackGroups.add(trackGroup);
}
}
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
* described by {@code trackGroupInfos} that have been given to this instance will be ignored. If
* {@link #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 described
* first in {@code trackGroupInfos}.
* Sets the initial track overrides. Any overrides that do not correspond to track groups that
* were passed to the constructor will be ignored. If {@link #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 was first in the list of track groups passed to the
* constructor.
*
* @param overrides The initially selected track overrides.
* @return This builder, for convenience.
@ -298,7 +298,7 @@ public final class TrackSelectionDialogBuilder {
selectionView.setTrackNameProvider(trackNameProvider);
}
selectionView.init(
trackGroupInfos, isDisabled, overrides, trackFormatComparator, /* listener= */ null);
trackGroups, isDisabled, overrides, trackFormatComparator, /* listener= */ null);
return (dialog, which) ->
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.TrackGroup;
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.UnstableApi;
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}.
* If {@code allowMultipleOverrides} is {@code} then at most one override is retained, which will
* be the one whose track group is first in {@code trackGroupInfos}.
* Returns the subset of {@code overrides} that apply to the specified {@code trackGroups}. If
* {@code allowMultipleOverrides} is {@code} then at most one override is retained, which will be
* the one whose track group is first in {@code trackGroups}.
*
* @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.
* @return The filtered overrides.
*/
public static Map<TrackGroup, TrackSelectionOverride> filterOverrides(
Map<TrackGroup, TrackSelectionOverride> overrides,
List<TrackGroupInfo> trackGroupInfos,
List<Tracks.Group> trackGroups,
boolean allowMultipleOverrides) {
HashMap<TrackGroup, TrackSelectionOverride> filteredOverrides = new HashMap<>();
for (int i = 0; i < trackGroupInfos.size(); i++) {
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(i);
@Nullable TrackSelectionOverride override = overrides.get(trackGroupInfo.getTrackGroup());
for (int i = 0; i < trackGroups.size(); i++) {
Tracks.Group trackGroup = trackGroups.get(i);
@Nullable TrackSelectionOverride override = overrides.get(trackGroup.getTrackGroup());
if (override != null && (allowMultipleOverrides || filteredOverrides.isEmpty())) {
filteredOverrides.put(override.trackGroup, override);
}
@ -85,7 +85,7 @@ public class TrackSelectionView extends LinearLayout {
private final CheckedTextView disableView;
private final CheckedTextView defaultView;
private final ComponentListener componentListener;
private final List<TrackGroupInfo> trackGroupInfos;
private final List<Tracks.Group> trackGroups;
private final Map<TrackGroup, TrackSelectionOverride> overrides;
private boolean allowAdaptiveSelections;
@ -127,7 +127,7 @@ public class TrackSelectionView extends LinearLayout {
inflater = LayoutInflater.from(context);
componentListener = new ComponentListener();
trackNameProvider = new DefaultTrackNameProvider(getResources());
trackGroupInfos = new ArrayList<>();
trackGroups = new ArrayList<>();
overrides = new HashMap<>();
// View for disabling the renderer.
@ -183,7 +183,7 @@ public class TrackSelectionView extends LinearLayout {
if (!allowMultipleOverrides && overrides.size() > 1) {
// Re-filter the overrides to retain only one of them.
Map<TrackGroup, TrackSelectionOverride> filteredOverrides =
filterOverrides(overrides, trackGroupInfos, /* allowMultipleOverrides= */ false);
filterOverrides(overrides, trackGroups, /* allowMultipleOverrides= */ false);
overrides.clear();
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.
*
* @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 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
* override will be ignored. The retained override will be the one whose track group is
* described first in {@code trackGroupInfos}.
* override will be ignored. The retained override will be the one whose track group is first
* in {@code trackGroups}.
* @param trackFormatComparator An optional comparator used to determine the display order of the
* tracks within each track group.
* @param listener An optional listener to receive selection updates.
*/
public void init(
List<TrackGroupInfo> trackGroupInfos,
List<Tracks.Group> trackGroups,
boolean isDisabled,
Map<TrackGroup, TrackSelectionOverride> overrides,
@Nullable Comparator<Format> trackFormatComparator,
@ -238,10 +238,10 @@ public class TrackSelectionView extends LinearLayout {
: (o1, o2) -> trackFormatComparator.compare(o1.getFormat(), o2.getFormat());
this.listener = listener;
this.trackGroupInfos.clear();
this.trackGroupInfos.addAll(trackGroupInfos);
this.trackGroups.clear();
this.trackGroups.addAll(trackGroups);
this.overrides.clear();
this.overrides.putAll(filterOverrides(overrides, trackGroupInfos, allowMultipleOverrides));
this.overrides.putAll(filterOverrides(overrides, trackGroups, allowMultipleOverrides));
updateViews();
}
@ -263,7 +263,7 @@ public class TrackSelectionView extends LinearLayout {
removeViewAt(i);
}
if (trackGroupInfos.isEmpty()) {
if (trackGroups.isEmpty()) {
// The view is not initialized.
disableView.setEnabled(false);
defaultView.setEnabled(false);
@ -273,17 +273,16 @@ public class TrackSelectionView extends LinearLayout {
defaultView.setEnabled(true);
// Add per-track views.
trackViews = new CheckedTextView[trackGroupInfos.size()][];
trackViews = new CheckedTextView[trackGroups.size()][];
boolean enableMultipleChoiceForMultipleOverrides = shouldEnableMultiGroupSelection();
for (int trackGroupIndex = 0; trackGroupIndex < trackGroupInfos.size(); trackGroupIndex++) {
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(trackGroupIndex);
boolean enableMultipleChoiceForAdaptiveSelections =
shouldEnableAdaptiveSelection(trackGroupInfo);
trackViews[trackGroupIndex] = new CheckedTextView[trackGroupInfo.length];
for (int trackGroupIndex = 0; trackGroupIndex < trackGroups.size(); trackGroupIndex++) {
Tracks.Group trackGroup = trackGroups.get(trackGroupIndex);
boolean enableMultipleChoiceForAdaptiveSelections = shouldEnableAdaptiveSelection(trackGroup);
trackViews[trackGroupIndex] = new CheckedTextView[trackGroup.length];
TrackInfo[] trackInfos = new TrackInfo[trackGroupInfo.length];
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) {
trackInfos[trackIndex] = new TrackInfo(trackGroupInfo, trackIndex);
TrackInfo[] trackInfos = new TrackInfo[trackGroup.length];
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
trackInfos[trackIndex] = new TrackInfo(trackGroup, trackIndex);
}
if (trackInfoComparator != null) {
Arrays.sort(trackInfos, trackInfoComparator);
@ -302,7 +301,7 @@ public class TrackSelectionView extends LinearLayout {
trackView.setBackgroundResource(selectableItemBackgroundResourceId);
trackView.setText(trackNameProvider.getTrackName(trackInfos[trackIndex].getFormat()));
trackView.setTag(trackInfos[trackIndex]);
if (trackGroupInfo.isTrackSupported(trackIndex)) {
if (trackGroup.isTrackSupported(trackIndex)) {
trackView.setFocusable(true);
trackView.setOnClickListener(componentListener);
} else {
@ -321,8 +320,7 @@ public class TrackSelectionView extends LinearLayout {
disableView.setChecked(isDisabled);
defaultView.setChecked(!isDisabled && overrides.size() == 0);
for (int i = 0; i < trackViews.length; i++) {
@Nullable
TrackSelectionOverride override = overrides.get(trackGroupInfos.get(i).getTrackGroup());
@Nullable TrackSelectionOverride override = overrides.get(trackGroups.get(i).getTrackGroup());
for (int j = 0; j < trackViews[i].length; j++) {
if (override != null) {
TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(trackViews[i][j].getTag());
@ -361,7 +359,7 @@ public class TrackSelectionView extends LinearLayout {
private void onTrackViewClicked(View view) {
isDisabled = false;
TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(view.getTag());
TrackGroup trackGroup = trackInfo.trackGroupInfo.getTrackGroup();
TrackGroup trackGroup = trackInfo.trackGroup.getTrackGroup();
int trackIndex = trackInfo.trackIndex;
@Nullable TrackSelectionOverride override = overrides.get(trackGroup);
if (override == null) {
@ -376,7 +374,7 @@ public class TrackSelectionView extends LinearLayout {
// An existing override is being modified.
ArrayList<Integer> trackIndices = new ArrayList<>(override.trackIndices);
boolean isCurrentlySelected = ((CheckedTextView) view).isChecked();
boolean isAdaptiveAllowed = shouldEnableAdaptiveSelection(trackInfo.trackGroupInfo);
boolean isAdaptiveAllowed = shouldEnableAdaptiveSelection(trackInfo.trackGroup);
boolean isUsingCheckBox = isAdaptiveAllowed || shouldEnableMultiGroupSelection();
if (isCurrentlySelected && isUsingCheckBox) {
// Remove the track from the override.
@ -401,12 +399,12 @@ public class TrackSelectionView extends LinearLayout {
}
}
private boolean shouldEnableAdaptiveSelection(TrackGroupInfo trackGroupInfo) {
return allowAdaptiveSelections && trackGroupInfo.isAdaptiveSupported();
private boolean shouldEnableAdaptiveSelection(Tracks.Group trackGroup) {
return allowAdaptiveSelections && trackGroup.isAdaptiveSupported();
}
private boolean shouldEnableMultiGroupSelection() {
return allowMultipleOverrides && trackGroupInfos.size() > 1;
return allowMultipleOverrides && trackGroups.size() > 1;
}
// Internal classes.
@ -420,16 +418,16 @@ public class TrackSelectionView extends LinearLayout {
}
private static final class TrackInfo {
public final TrackGroupInfo trackGroupInfo;
public final Tracks.Group trackGroup;
public final int trackIndex;
public TrackInfo(TrackGroupInfo trackGroupInfo, int trackIndex) {
this.trackGroupInfo = trackGroupInfo;
public TrackInfo(Tracks.Group trackGroup, int trackIndex) {
this.trackGroup = trackGroup;
this.trackIndex = trackIndex;
}
public Format getFormat() {
return trackGroupInfo.getTrackFormat(trackIndex);
return trackGroup.getTrackFormat(trackIndex);
}
}
}