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 3f47c1ead3
commit 0ad508b14f
40 changed files with 600 additions and 605 deletions

View File

@ -25,7 +25,7 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Player.DiscontinuityReason;
import com.google.android.exoplayer2.Player.TimelineChangeReason;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.ext.cast.CastPlayer;
import com.google.android.exoplayer2.ext.cast.SessionAvailabilityListener;
import com.google.android.exoplayer2.ui.StyledPlayerControlView;
@ -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

@ -28,7 +28,7 @@ import androidx.fragment.app.FragmentManager;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
@ -301,17 +301,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

@ -35,7 +35,7 @@ import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.drm.FrameworkMediaDrm;
import com.google.android.exoplayer2.ext.ima.ImaAdsLoader;
@ -82,7 +82,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;
@ -275,7 +275,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)
@ -455,22 +455,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

@ -33,8 +33,7 @@ import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
@ -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

@ -2,49 +2,63 @@
title: Track selection
---
Track selection determines which of the available media tracks are played by the
player. This process is configured by [`TrackSelectionParameters`][], which
support many different options to specify constraints and overrides.
When a media item contains multiple tracks, track selection is the process that
determines which of them are chosen for playback. The track selection process is
configured by [`TrackSelectionParameters`][], which allows many different
constraints and overrides influencing track selection to be specified.
## Information about existing tracks
## Querying the available tracks
The player needs to prepare the media to know which tracks are available for
selection. You can listen to `Player.Listener.onTracksInfoChanged` to get
notified about changes, which may happen
* When preparation completes
* When the available or selected tracks change
* When the playlist item changes
You can listen to `Player.Listener.onTracksChanged` to be notified about changes
to tracks, including:
* The available tracks becoming known when preparation of the media item being
played completes. Note that the player needs to prepare a media item to know
what tracks it contains.
* The available tracks changing due to playback transitioning from one media
item to another.
* Changes to the selected tracks.
~~~
player.addListener(new Player.Listener() {
@Override
public void onTracksInfoChanged(TracksInfo tracksInfo) {
// Update UI using current TracksInfo.
public void onTracksChanged(Tracks tracks) {
// Update UI using current tracks.
}
});
~~~
{: .language-java}
You can also retrieve the current `TracksInfo` by calling
`player.getCurrentTracksInfo()`.
You can also query the current tracks by calling `player.getCurrentTracks()`.
The returned `Tracks` contains a list of `Track.Group`s, where tracks within a
single `Group` present the same content but in different formats.
`TracksInfo` contains a list of `TrackGroupInfo`s with information about the
track type, format details, player support and selection status of each
available track. Tracks are grouped together into one `TrackGroup` if they
represent the same content that can be used interchangeably by the player (for
example, all audio tracks of a single language, but with different bitrates).
As an example of how tracks can be grouped, consider an adaptive playback where
a main video feed is provided in five bitrates, and an alternative video feed
(e.g., a different camera angle in a sports match) is provided in two bitrates.
In this case there will be two video track groups, one corresponding to the main
video feed containing five tracks, and a second for the alternative video feed
containing two tracks.
Audio tracks whose languages differ are not grouped, because content in
different languages is not considered to be the same. Conversely, audio tracks
in the same language that only differ in properties such as bitrate, sampling
rate, channel count and so on can be grouped. This also applies to text tracks.
Each `Group` can be queried to determine which tracks are supported for
playback, which are currently selected, and what `Format` each track uses:
~~~
for (TrackGroupInfo groupInfo : tracksInfo.getTrackGroupInfos()) {
for (Tracks.Group trackGroup : tracks.getGroups()) {
// Group level information.
@C.TrackType int trackType = groupInfo.getTrackType();
boolean trackInGroupIsSelected = groupInfo.isSelected();
boolean trackInGroupIsSupported = groupInfo.isSupported();
for (int i = 0; i < groupInfo.length; i++) {
@C.TrackType int trackType = trackGroup.getTrackType();
boolean trackInGroupIsSelected = trackGroup.isSelected();
boolean trackInGroupIsSupported = trackGroup.isSupported();
for (int i = 0; i < trackGroup.length; i++) {
// Individual track information.
boolean isSupported = groupInfo.isTrackSupported(i);
boolean isSelected = groupInfo.isTrackSelected(i);
Format trackFormat = groupInfo.getTrackFormat(i);
boolean isSupported = trackGroup.isTrackSupported(i);
boolean isSelected = trackGroup.isTrackSelected(i);
Format trackFormat = trackGroup.getTrackFormat(i);
}
}
~~~
@ -55,22 +69,19 @@ for (TrackGroupInfo groupInfo : tracksInfo.getTrackGroupInfos()) {
multiple audio track groups) are supported, it only means that they are
supported individually and the player is not necessarily able to play them at
the same time.
* A track is 'selected' if the track selector chose this track for playback
using the current `TrackSelectionParameters`. If multiple tracks within one
track group are selected, the player uses these tracks for adaptive playback
(for example, multiple video tracks with different bitrates). Note that only
one of these tracks will be played at any one time. If you want to be notified
of in-playback changes to the adaptive video track you can listen to
`Player.Listener.onVideoSizeChanged`.
* A track is 'selected' if it has been chosen for playback given the current
`TrackSelectionParameters`. If multiple tracks within one track group are
selected, the player uses these tracks for adaptive playback (for example,
multiple video tracks with different bitrates). Note that only one of these
tracks will be played at any one time.
## Modifying track selection parameters
The selection process can be configured by setting `TrackSelectionParameters` on
the `Player` with `Player.setTrackSelectionParameters`. These updates can be
done before and during playback. In most cases, it's advisable to obtain the
current parameters and only modify the required aspects with the
`TrackSelectionParameters.Builder`. The builder class also allows chaining to
specify multiple options with one command:
The track selection process can be configured using
`Player.setTrackSelectionParameters`. This can be done both before and during
playback. The example below demonstrates how to obtain the current
`TrackSelectionParameters` from the player, modify them, and update the `Player`
with the modified result:
~~~
player.setTrackSelectionParameters(
@ -85,58 +96,60 @@ player.setTrackSelectionParameters(
### Constraint based track selection
Most options in `TrackSelectionParameters` allow you to specify constraints,
which are independent of the tracks that are actually available. Typical
constraints are:
which are independent of the tracks that are actually available. Available
constraints include:
* Maximum or minimum video width, height, frame rate, or bitrate.
* Maximum audio channel count or bitrate.
* Preferred MIME types for video or audio.
* Preferred audio languages or role flags.
* Preferred text languages or role flags.
* Maximum and minimum video width, height, frame rate, and bitrate.
* Maximum audio channel count and bitrate.
* Preferred MIME types for video and audio.
* Preferred audio languages and role flags.
* Preferred text languages and role flags.
Note that ExoPlayer already applies sensible defaults for most of these values,
for example restricting video resolution to the display size or preferring the
audio language that matches the user's system Locale setting.
ExoPlayer uses sensible defaults for these constraints, for example restricting
video resolution to the display size and preferring the audio language that
matches the user's system Locale setting.
There are several benefits to using constraint based track selection instead of
specifying specific tracks directly:
There are several benefits to using constraint based track selection rather than
selecting specific tracks from those that are available:
* You can specify constraints before knowing what tracks the media provides.
This allows to immediately select the appropriate tracks for faster startup
time and also simplifies track selection code as you don't have to listen for
changes in the available tracks.
* Constraints can be applied consistently across all items in a playlist. For
example, selecting an audio language based on user preference will
automatically apply to the next playlist item too, whereas overriding a
specific track will only apply to the current playlist item for which the
track exists.
* You can specify constraints before knowing what tracks a media item provides.
This means that constraints can be specified before the player has prepared a
media item, whereas selecting specific tracks requires application code to
wait until the available tracks become known.
* Constraints are applied for all media items in a playlist, even when those
items have different available tracks. For example, a preferred audio language
constraint will be automatically applied for all media items, even if the
`Format` of the track in that language varies from one media item to the next.
This is not the case when selecting specific tracks, as described below.
### Selecting specific tracks
It's possible to specify in `TrackSelectionParameters` which of the currently
available tracks should be selected. First, the player's currently available
tracks should be queried using `Player.getTracksInfo`. Second, having identified
which tracks to select, they can be set on `TrackSelectionParameters` using
`TrackSelectionOverrides`. For example, to select the first track from a
specific `audioTrackGroup`:
It's possible to select specific tracks using `TrackSelectionParameters`. First,
the player's currently available tracks should be queried using
`Player.getCurrentTracks`. Second, having identified which tracks to select,
they can be set on `TrackSelectionParameters` using a `TrackSelectionOverride`.
For example, to select the first track from a specific `audioTrackGroup`:
~~~
player.setTrackSelectionParameters(
player.getTrackSelectionParameters()
.buildUpon()
.setOverrideForType(
new TrackSelectionOverride(audioTrackGroup, /* trackIndex= */ 0))
new TrackSelectionOverride(
audioTrackGroup.getTrackGroup(),
/* trackIndex= */ 0))
.build());
~~~
{: .language-java}
Note that a `TrackSelectionOverride` will only apply to media items that contain
the `TrackGroup` specified in the override. Hence an override may not apply to
a subsequent media item if that item contains different tracks.
A `TrackSelectionOverride` will only apply to media items that contain a
`TrackGroup` exactly matching the one specified in the override. Hence an
override may not apply to a subsequent media item if that item contains
different tracks.
### Disabling track types or groups
Track types, like video, audio or text, can be disabled completely using
Track types like video, audio or text, can be disabled completely using
`TrackSelectionParameters.Builder.setTrackTypeDisabled`. A disabled track type
will be disabled for all media items:
@ -158,7 +171,7 @@ player.setTrackSelectionParameters(
.buildUpon()
.addOverride(
new TrackSelectionOverride(
disabledTrackGroup, ImmutableList.of()))
disabledTrackGroup.getTrackGroup(), ImmutableList.of()))
.build());
~~~
{: .language-java}

View File

@ -37,8 +37,7 @@ import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.text.Cue;
@ -134,7 +133,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;
@ -210,7 +209,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;
@ -542,8 +541,8 @@ public final class CastPlayer extends BasePlayer {
}
@Override
public TracksInfo getCurrentTracksInfo() {
return currentTracksInfo;
public Tracks getCurrentTracks() {
return currentTracks;
}
@Override
@ -816,7 +815,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();
@ -976,8 +975,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();
@ -985,20 +984,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

@ -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 com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.testutil.StubExoPlayer;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
@ -266,8 +266,8 @@ import com.google.android.exoplayer2.util.Util;
}
@Override
public TracksInfo getCurrentTracksInfo() {
return TracksInfo.EMPTY;
public Tracks getCurrentTracks() {
return Tracks.EMPTY;
}
@Override

View File

@ -444,10 +444,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. */
@ -833,8 +833,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

@ -61,8 +61,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 {
@ -673,14 +673,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.
@ -1299,7 +1299,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;
@ -2074,11 +2074,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

@ -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;
@ -63,7 +63,7 @@ public final class TracksInfo implements Bundleable {
* @param trackSupport The {@link C.FormatSupport} of each track in the group.
* @param trackSelected Whether each track in the {@code trackGroup} is selected.
*/
public TrackGroupInfo(
public Group(
TrackGroup trackGroup,
boolean adaptiveSupported,
@C.FormatSupport int[] trackSupport,
@ -84,7 +84,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) {
@ -94,7 +94,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.
*/
public @C.FormatSupport int getTrackSupport(int trackIndex) {
@ -105,7 +105,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) {
@ -115,7 +115,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
@ -176,7 +176,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) {
@ -184,7 +184,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;
}
@ -196,7 +196,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)
@ -239,8 +239,8 @@ public final class TracksInfo implements Bundleable {
return bundle;
}
/** Object that can restores a {@code TracksInfo} from a {@link Bundle}. */
public static final Creator<TrackGroupInfo> CREATOR =
/** Object that can restore a group of tracks from a {@link Bundle}. */
public static final Creator<Group> CREATOR =
bundle -> {
TrackGroup trackGroup =
fromNullableBundle(
@ -255,7 +255,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) {
@ -263,30 +263,34 @@ public final class TracksInfo implements Bundleable {
}
}
/** An {@code TrackInfo} that contains no tracks. */
public static final TracksInfo EMPTY = new TracksInfo(ImmutableList.of());
/** Empty tracks. */
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.
*/
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;
}
}
@ -295,7 +299,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);
@ -303,7 +307,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
@ -312,9 +316,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;
}
}
@ -342,9 +346,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;
}
}
@ -359,13 +363,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.
@ -373,29 +377,28 @@ 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;
@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}. */
public static final Creator<TracksInfo> CREATOR =
/** Object that can restore tracks from a {@link Bundle}. */
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

@ -94,7 +94,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

@ -682,7 +682,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;
}
@ -698,7 +698,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

@ -1,145 +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 com.google.android.exoplayer2;
import static com.google.android.exoplayer2.util.MimeTypes.AUDIO_AAC;
import static com.google.android.exoplayer2.util.MimeTypes.VIDEO_H264;
import static com.google.common.truth.Truth.assertThat;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
import com.google.android.exoplayer2.source.TrackGroup;
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,144 @@
/*
* 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 com.google.android.exoplayer2;
import static com.google.android.exoplayer2.util.MimeTypes.AUDIO_AAC;
import static com.google.android.exoplayer2.util.MimeTypes.VIDEO_H264;
import static com.google.common.truth.Truth.assertThat;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.source.TrackGroup;
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

@ -1172,8 +1172,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()}.
*/
@Deprecated
TrackGroupArray getCurrentTrackGroups();
@ -1182,8 +1182,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()}.
*/
@Deprecated
TrackSelectionArray getCurrentTrackSelections();

View File

@ -266,7 +266,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 =
@ -1136,9 +1136,9 @@ import java.util.concurrent.TimeoutException;
}
@Override
public TracksInfo getCurrentTracksInfo() {
public Tracks getCurrentTracks() {
verifyApplicationThread();
return playbackInfo.trackSelectorResult.tracksInfo;
return playbackInfo.trackSelectorResult.tracks;
}
@Override
@ -1887,7 +1887,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

@ -1049,9 +1049,9 @@ public class SimpleExoPlayer extends BasePlayer
}
@Override
public TracksInfo getCurrentTracksInfo() {
public Tracks getCurrentTracks() {
blockUntilConstructorFinished();
return player.getCurrentTracksInfo();
return player.getCurrentTracks();
}
@Override

View File

@ -42,7 +42,7 @@ import com.google.android.exoplayer2.Player.DiscontinuityReason;
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
import com.google.android.exoplayer2.Player.TimelineChangeReason;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.audio.AudioSink;
import com.google.android.exoplayer2.decoder.DecoderCounters;
@ -236,7 +236,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;
@ -704,12 +704,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

@ -37,7 +37,7 @@ import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.Timeline.Window;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.decoder.DecoderCounters;
@ -481,12 +481,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 com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.audio.AudioSink;
import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
@ -338,8 +337,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));
}
@ -370,10 +368,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) {
@ -820,11 +818,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 com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndException;
import com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndFormat;
import com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndPlaybackState;
@ -522,11 +522,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

@ -32,7 +32,7 @@ import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.analytics.PlayerId;
import com.google.android.exoplayer2.audio.AudioRendererEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager;
@ -543,16 +543,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

@ -1955,12 +1955,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

@ -36,7 +36,7 @@ import com.google.android.exoplayer2.RendererCapabilities.AdaptiveSupport;
import com.google.android.exoplayer2.RendererCapabilities.Capabilities;
import com.google.android.exoplayer2.RendererConfiguration;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
@ -425,9 +425,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 com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
@ -134,16 +133,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];
@ -151,22 +150,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++) {
@ -194,8 +193,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();
@ -204,9 +202,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

@ -17,7 +17,7 @@ package com.google.android.exoplayer2.trackselection;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.RendererConfiguration;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.util.Util;
import org.checkerframework.checker.nullness.compatqual.NullableType;
@ -34,7 +34,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.
@ -49,21 +49,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}.
@ -71,11 +71,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

@ -29,7 +29,7 @@ import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.analytics.AnalyticsListener;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.decoder.DecoderCounters;
@ -258,23 +258,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);
}
@ -283,8 +283,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

@ -96,7 +96,6 @@ import com.google.android.exoplayer2.Player.DiscontinuityReason;
import com.google.android.exoplayer2.Player.Listener;
import com.google.android.exoplayer2.Player.PositionInfo;
import com.google.android.exoplayer2.Timeline.Window;
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
import com.google.android.exoplayer2.analytics.AnalyticsListener;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
@ -267,15 +266,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);
@ -646,15 +645,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();
}
@ -3416,7 +3415,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)
@ -3424,21 +3423,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);
}
@ -7983,7 +7982,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)
@ -7996,7 +7995,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());
}
});
@ -8025,8 +8024,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();
@ -10413,7 +10412,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

@ -1135,7 +1135,7 @@ public final class MediaPeriodQueueTest {
new TrackSelectorResult(
new RendererConfiguration[0],
new ExoTrackSelection[0],
TracksInfo.EMPTY,
Tracks.EMPTY,
/* info= */ null));
}

View File

@ -83,7 +83,7 @@ import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Window;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
import com.google.android.exoplayer2.drm.DrmInitData;
@ -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

@ -44,7 +44,7 @@ import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.RendererCapabilities.Capabilities;
import com.google.android.exoplayer2.RendererConfiguration;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
@ -2223,10 +2223,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)
@ -2234,14 +2234,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.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
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

@ -44,7 +44,7 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.audio.AudioRendererEventListener;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor;
@ -947,7 +947,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

@ -53,7 +53,7 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Player.DiscontinuityReason;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
import com.google.android.exoplayer2.util.Assertions;
@ -1230,7 +1230,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
@Nullable Player player = this.player;
if (player == null
|| !player.isCommandAvailable(Player.COMMAND_GET_TRACK_INFOS)
|| player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) {
|| player.getCurrentTracks().isEmpty()) {
if (!keepContentOnPlayerReset) {
hideArtwork();
closeShutter();
@ -1242,7 +1242,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
// Hide any video from the previous player.
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();
@ -1474,7 +1474,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.
@ -1482,7 +1482,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

@ -65,8 +65,7 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Player.Events;
import com.google.android.exoplayer2.Player.State;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
@ -1107,39 +1106,37 @@ public class StyledPlayerControlView 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() {
@ -1818,19 +1815,18 @@ public class StyledPlayerControlView 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);
}
}
@ -1930,7 +1926,7 @@ public class StyledPlayerControlView 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;
}
@ -2004,7 +2000,7 @@ public class StyledPlayerControlView 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);
@ -2019,8 +2015,7 @@ public class StyledPlayerControlView 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

@ -55,7 +55,7 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Player.DiscontinuityReason;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
import com.google.android.exoplayer2.util.Assertions;
@ -1177,7 +1177,7 @@ public class StyledPlayerView 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();
@ -1190,7 +1190,7 @@ public class StyledPlayerView 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();
@ -1422,7 +1422,7 @@ public class StyledPlayerView 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.
@ -1430,7 +1430,7 @@ public class StyledPlayerView 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

@ -26,7 +26,7 @@ import androidx.annotation.StyleRes;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
@ -56,7 +56,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;
@ -73,17 +73,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();
}
@ -100,12 +100,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();
@ -156,11 +156,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.
@ -296,7 +296,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

@ -25,7 +25,7 @@ import android.widget.LinearLayout;
import androidx.annotation.AttrRes;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
import com.google.android.exoplayer2.util.Assertions;
@ -54,23 +54,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);
}
@ -83,7 +83,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;
@ -125,7 +125,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.
@ -181,7 +181,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);
}
@ -212,19 +212,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,
@ -236,10 +236,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();
}
@ -261,7 +261,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);
@ -271,17 +271,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);
@ -300,7 +299,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 {
@ -319,8 +318,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());
@ -359,7 +357,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) {
@ -374,7 +372,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.
@ -399,12 +397,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.
@ -418,16 +416,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);
}
}
}

View File

@ -29,7 +29,7 @@ import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.Tracks;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
@ -189,7 +189,7 @@ public class StubPlayer extends BasePlayer {
}
@Override
public TracksInfo getCurrentTracksInfo() {
public Tracks getCurrentTracks() {
throw new UnsupportedOperationException();
}