mirror of
https://github.com/androidx/media.git
synced 2025-05-07 23:50:44 +08:00
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:
parent
3f47c1ead3
commit
0ad508b14f
@ -25,7 +25,7 @@ import com.google.android.exoplayer2.Player;
|
|||||||
import com.google.android.exoplayer2.Player.DiscontinuityReason;
|
import com.google.android.exoplayer2.Player.DiscontinuityReason;
|
||||||
import com.google.android.exoplayer2.Player.TimelineChangeReason;
|
import com.google.android.exoplayer2.Player.TimelineChangeReason;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
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.CastPlayer;
|
||||||
import com.google.android.exoplayer2.ext.cast.SessionAvailabilityListener;
|
import com.google.android.exoplayer2.ext.cast.SessionAvailabilityListener;
|
||||||
import com.google.android.exoplayer2.ui.StyledPlayerControlView;
|
import com.google.android.exoplayer2.ui.StyledPlayerControlView;
|
||||||
@ -57,7 +57,7 @@ import java.util.ArrayList;
|
|||||||
private final ArrayList<MediaItem> mediaQueue;
|
private final ArrayList<MediaItem> mediaQueue;
|
||||||
private final Listener listener;
|
private final Listener listener;
|
||||||
|
|
||||||
private TracksInfo lastSeenTrackGroupInfo;
|
private Tracks lastSeenTracks;
|
||||||
private int currentItemIndex;
|
private int currentItemIndex;
|
||||||
private Player currentPlayer;
|
private Player currentPlayer;
|
||||||
|
|
||||||
@ -219,19 +219,19 @@ import java.util.ArrayList;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
if (currentPlayer != localPlayer || tracksInfo == lastSeenTrackGroupInfo) {
|
if (currentPlayer != localPlayer || tracks == lastSeenTracks) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tracksInfo.containsType(C.TRACK_TYPE_VIDEO)
|
if (tracks.containsType(C.TRACK_TYPE_VIDEO)
|
||||||
&& !tracksInfo.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
|
&& !tracks.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
|
||||||
listener.onUnsupportedTrack(C.TRACK_TYPE_VIDEO);
|
listener.onUnsupportedTrack(C.TRACK_TYPE_VIDEO);
|
||||||
}
|
}
|
||||||
if (tracksInfo.containsType(C.TRACK_TYPE_AUDIO)
|
if (tracks.containsType(C.TRACK_TYPE_AUDIO)
|
||||||
&& !tracksInfo.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
|
&& !tracks.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
|
||||||
listener.onUnsupportedTrack(C.TRACK_TYPE_AUDIO);
|
listener.onUnsupportedTrack(C.TRACK_TYPE_AUDIO);
|
||||||
}
|
}
|
||||||
lastSeenTrackGroupInfo = tracksInfo;
|
lastSeenTracks = tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CastPlayer.SessionAvailabilityListener implementation.
|
// CastPlayer.SessionAvailabilityListener implementation.
|
||||||
|
@ -28,7 +28,7 @@ import androidx.fragment.app.FragmentManager;
|
|||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.MediaItem;
|
import com.google.android.exoplayer2.MediaItem;
|
||||||
import com.google.android.exoplayer2.RenderersFactory;
|
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.DrmInitData;
|
||||||
import com.google.android.exoplayer2.drm.DrmSession;
|
import com.google.android.exoplayer2.drm.DrmSession;
|
||||||
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
|
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
|
||||||
@ -301,17 +301,17 @@ public class DownloadTracker {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TracksInfo tracksInfo = downloadHelper.getTracksInfo(/* periodIndex= */ 0);
|
Tracks tracks = downloadHelper.getTracks(/* periodIndex= */ 0);
|
||||||
if (!TrackSelectionDialog.willHaveContent(tracksInfo)) {
|
if (!TrackSelectionDialog.willHaveContent(tracks)) {
|
||||||
Log.d(TAG, "No dialog content. Downloading entire stream.");
|
Log.d(TAG, "No dialog content. Downloading entire stream.");
|
||||||
startDownload();
|
startDownload();
|
||||||
downloadHelper.release();
|
downloadHelper.release();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
trackSelectionDialog =
|
trackSelectionDialog =
|
||||||
TrackSelectionDialog.createForTracksInfoAndParameters(
|
TrackSelectionDialog.createForTracksAndParameters(
|
||||||
/* titleId= */ R.string.exo_download_description,
|
/* titleId= */ R.string.exo_download_description,
|
||||||
tracksInfo,
|
tracks,
|
||||||
DownloadHelper.getDefaultTrackSelectorParameters(context),
|
DownloadHelper.getDefaultTrackSelectorParameters(context),
|
||||||
/* allowAdaptiveSelections= */ false,
|
/* allowAdaptiveSelections= */ false,
|
||||||
/* allowMultipleOverrides= */ true,
|
/* allowMultipleOverrides= */ true,
|
||||||
|
@ -35,7 +35,7 @@ import com.google.android.exoplayer2.MediaItem;
|
|||||||
import com.google.android.exoplayer2.PlaybackException;
|
import com.google.android.exoplayer2.PlaybackException;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.RenderersFactory;
|
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.audio.AudioAttributes;
|
||||||
import com.google.android.exoplayer2.drm.FrameworkMediaDrm;
|
import com.google.android.exoplayer2.drm.FrameworkMediaDrm;
|
||||||
import com.google.android.exoplayer2.ext.ima.ImaAdsLoader;
|
import com.google.android.exoplayer2.ext.ima.ImaAdsLoader;
|
||||||
@ -82,7 +82,7 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
private List<MediaItem> mediaItems;
|
private List<MediaItem> mediaItems;
|
||||||
private TrackSelectionParameters trackSelectionParameters;
|
private TrackSelectionParameters trackSelectionParameters;
|
||||||
private DebugTextViewHelper debugViewHelper;
|
private DebugTextViewHelper debugViewHelper;
|
||||||
private TracksInfo lastSeenTracksInfo;
|
private Tracks lastSeenTracks;
|
||||||
private boolean startAutoPlay;
|
private boolean startAutoPlay;
|
||||||
private int startItemIndex;
|
private int startItemIndex;
|
||||||
private long startPosition;
|
private long startPosition;
|
||||||
@ -275,7 +275,7 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
RenderersFactory renderersFactory =
|
RenderersFactory renderersFactory =
|
||||||
DemoUtil.buildRenderersFactory(/* context= */ this, preferExtensionDecoders);
|
DemoUtil.buildRenderersFactory(/* context= */ this, preferExtensionDecoders);
|
||||||
|
|
||||||
lastSeenTracksInfo = TracksInfo.EMPTY;
|
lastSeenTracks = Tracks.EMPTY;
|
||||||
player =
|
player =
|
||||||
new ExoPlayer.Builder(/* context= */ this)
|
new ExoPlayer.Builder(/* context= */ this)
|
||||||
.setRenderersFactory(renderersFactory)
|
.setRenderersFactory(renderersFactory)
|
||||||
@ -455,22 +455,20 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("ReferenceEquality")
|
@SuppressWarnings("ReferenceEquality")
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
updateButtonVisibility();
|
updateButtonVisibility();
|
||||||
if (tracksInfo == lastSeenTracksInfo) {
|
if (tracks == lastSeenTracks) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tracksInfo.containsType(C.TRACK_TYPE_VIDEO)
|
if (tracks.containsType(C.TRACK_TYPE_VIDEO)
|
||||||
&& !tracksInfo.isTypeSupported(
|
&& !tracks.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
|
||||||
C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
|
|
||||||
showToast(R.string.error_unsupported_video);
|
showToast(R.string.error_unsupported_video);
|
||||||
}
|
}
|
||||||
if (tracksInfo.containsType(C.TRACK_TYPE_AUDIO)
|
if (tracks.containsType(C.TRACK_TYPE_AUDIO)
|
||||||
&& !tracksInfo.isTypeSupported(
|
&& !tracks.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
|
||||||
C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
|
|
||||||
showToast(R.string.error_unsupported_audio);
|
showToast(R.string.error_unsupported_audio);
|
||||||
}
|
}
|
||||||
lastSeenTracksInfo = tracksInfo;
|
lastSeenTracks = tracks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,8 +33,7 @@ import androidx.fragment.app.FragmentPagerAdapter;
|
|||||||
import androidx.viewpager.widget.ViewPager;
|
import androidx.viewpager.widget.ViewPager;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.TracksInfo;
|
import com.google.android.exoplayer2.Tracks;
|
||||||
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
|
|
||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
|
||||||
@ -79,16 +78,16 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
* specified {@link Player}.
|
* specified {@link Player}.
|
||||||
*/
|
*/
|
||||||
public static boolean willHaveContent(Player player) {
|
public static boolean willHaveContent(Player player) {
|
||||||
return willHaveContent(player.getCurrentTracksInfo());
|
return willHaveContent(player.getCurrentTracks());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether a track selection dialog will have content to display if initialized with the
|
* Returns whether a track selection dialog will have content to display if initialized with the
|
||||||
* specified {@link TracksInfo}.
|
* specified {@link Tracks}.
|
||||||
*/
|
*/
|
||||||
public static boolean willHaveContent(TracksInfo tracksInfo) {
|
public static boolean willHaveContent(Tracks tracks) {
|
||||||
for (TrackGroupInfo trackGroupInfo : tracksInfo.getTrackGroupInfos()) {
|
for (Tracks.Group trackGroup : tracks.getGroups()) {
|
||||||
if (SUPPORTED_TRACK_TYPES.contains(trackGroupInfo.getTrackType())) {
|
if (SUPPORTED_TRACK_TYPES.contains(trackGroup.getType())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,9 +104,9 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
*/
|
*/
|
||||||
public static TrackSelectionDialog createForPlayer(
|
public static TrackSelectionDialog createForPlayer(
|
||||||
Player player, DialogInterface.OnDismissListener onDismissListener) {
|
Player player, DialogInterface.OnDismissListener onDismissListener) {
|
||||||
return createForTracksInfoAndParameters(
|
return createForTracksAndParameters(
|
||||||
R.string.track_selection_title,
|
R.string.track_selection_title,
|
||||||
player.getCurrentTracksInfo(),
|
player.getCurrentTracks(),
|
||||||
player.getTrackSelectionParameters(),
|
player.getTrackSelectionParameters(),
|
||||||
/* allowAdaptiveSelections= */ true,
|
/* allowAdaptiveSelections= */ true,
|
||||||
/* allowMultipleOverrides= */ false,
|
/* allowMultipleOverrides= */ false,
|
||||||
@ -116,10 +115,10 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a dialog for given {@link TracksInfo} and {@link TrackSelectionParameters}.
|
* Creates a dialog for given {@link Tracks} and {@link TrackSelectionParameters}.
|
||||||
*
|
*
|
||||||
* @param titleId The resource id of the dialog title.
|
* @param titleId The resource id of the dialog title.
|
||||||
* @param tracksInfo The {@link TracksInfo} describing the tracks to display.
|
* @param tracks The {@link Tracks} describing the tracks to display.
|
||||||
* @param trackSelectionParameters The initial {@link TrackSelectionParameters}.
|
* @param trackSelectionParameters The initial {@link TrackSelectionParameters}.
|
||||||
* @param allowAdaptiveSelections Whether adaptive selections (consisting of more than one track)
|
* @param allowAdaptiveSelections Whether adaptive selections (consisting of more than one track)
|
||||||
* can be made.
|
* can be made.
|
||||||
@ -128,9 +127,9 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
* @param onDismissListener {@link DialogInterface.OnDismissListener} called when the dialog is
|
* @param onDismissListener {@link DialogInterface.OnDismissListener} called when the dialog is
|
||||||
* dismissed.
|
* dismissed.
|
||||||
*/
|
*/
|
||||||
public static TrackSelectionDialog createForTracksInfoAndParameters(
|
public static TrackSelectionDialog createForTracksAndParameters(
|
||||||
int titleId,
|
int titleId,
|
||||||
TracksInfo tracksInfo,
|
Tracks tracks,
|
||||||
TrackSelectionParameters trackSelectionParameters,
|
TrackSelectionParameters trackSelectionParameters,
|
||||||
boolean allowAdaptiveSelections,
|
boolean allowAdaptiveSelections,
|
||||||
boolean allowMultipleOverrides,
|
boolean allowMultipleOverrides,
|
||||||
@ -138,7 +137,7 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
DialogInterface.OnDismissListener onDismissListener) {
|
DialogInterface.OnDismissListener onDismissListener) {
|
||||||
TrackSelectionDialog trackSelectionDialog = new TrackSelectionDialog();
|
TrackSelectionDialog trackSelectionDialog = new TrackSelectionDialog();
|
||||||
trackSelectionDialog.init(
|
trackSelectionDialog.init(
|
||||||
tracksInfo,
|
tracks,
|
||||||
trackSelectionParameters,
|
trackSelectionParameters,
|
||||||
titleId,
|
titleId,
|
||||||
allowAdaptiveSelections,
|
allowAdaptiveSelections,
|
||||||
@ -169,7 +168,7 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void init(
|
private void init(
|
||||||
TracksInfo tracksInfo,
|
Tracks tracks,
|
||||||
TrackSelectionParameters trackSelectionParameters,
|
TrackSelectionParameters trackSelectionParameters,
|
||||||
int titleId,
|
int titleId,
|
||||||
boolean allowAdaptiveSelections,
|
boolean allowAdaptiveSelections,
|
||||||
@ -182,16 +181,16 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
|
|
||||||
for (int i = 0; i < SUPPORTED_TRACK_TYPES.size(); i++) {
|
for (int i = 0; i < SUPPORTED_TRACK_TYPES.size(); i++) {
|
||||||
@C.TrackType int trackType = SUPPORTED_TRACK_TYPES.get(i);
|
@C.TrackType int trackType = SUPPORTED_TRACK_TYPES.get(i);
|
||||||
ArrayList<TrackGroupInfo> trackGroupInfos = new ArrayList<>();
|
ArrayList<Tracks.Group> trackGroups = new ArrayList<>();
|
||||||
for (TrackGroupInfo trackGroupInfo : tracksInfo.getTrackGroupInfos()) {
|
for (Tracks.Group trackGroup : tracks.getGroups()) {
|
||||||
if (trackGroupInfo.getTrackType() == trackType) {
|
if (trackGroup.getType() == trackType) {
|
||||||
trackGroupInfos.add(trackGroupInfo);
|
trackGroups.add(trackGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!trackGroupInfos.isEmpty()) {
|
if (!trackGroups.isEmpty()) {
|
||||||
TrackSelectionViewFragment tabFragment = new TrackSelectionViewFragment();
|
TrackSelectionViewFragment tabFragment = new TrackSelectionViewFragment();
|
||||||
tabFragment.init(
|
tabFragment.init(
|
||||||
trackGroupInfos,
|
trackGroups,
|
||||||
trackSelectionParameters.disabledTrackTypes.contains(trackType),
|
trackSelectionParameters.disabledTrackTypes.contains(trackType),
|
||||||
trackSelectionParameters.overrides,
|
trackSelectionParameters.overrides,
|
||||||
allowAdaptiveSelections,
|
allowAdaptiveSelections,
|
||||||
@ -300,7 +299,7 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
public static final class TrackSelectionViewFragment extends Fragment
|
public static final class TrackSelectionViewFragment extends Fragment
|
||||||
implements TrackSelectionView.TrackSelectionListener {
|
implements TrackSelectionView.TrackSelectionListener {
|
||||||
|
|
||||||
private List<TrackGroupInfo> trackGroupInfos;
|
private List<Tracks.Group> trackGroups;
|
||||||
private boolean allowAdaptiveSelections;
|
private boolean allowAdaptiveSelections;
|
||||||
private boolean allowMultipleOverrides;
|
private boolean allowMultipleOverrides;
|
||||||
|
|
||||||
@ -313,12 +312,12 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void init(
|
public void init(
|
||||||
List<TrackGroupInfo> trackGroupInfos,
|
List<Tracks.Group> trackGroups,
|
||||||
boolean isDisabled,
|
boolean isDisabled,
|
||||||
Map<TrackGroup, TrackSelectionOverride> overrides,
|
Map<TrackGroup, TrackSelectionOverride> overrides,
|
||||||
boolean allowAdaptiveSelections,
|
boolean allowAdaptiveSelections,
|
||||||
boolean allowMultipleOverrides) {
|
boolean allowMultipleOverrides) {
|
||||||
this.trackGroupInfos = trackGroupInfos;
|
this.trackGroups = trackGroups;
|
||||||
this.isDisabled = isDisabled;
|
this.isDisabled = isDisabled;
|
||||||
this.allowAdaptiveSelections = allowAdaptiveSelections;
|
this.allowAdaptiveSelections = allowAdaptiveSelections;
|
||||||
this.allowMultipleOverrides = allowMultipleOverrides;
|
this.allowMultipleOverrides = allowMultipleOverrides;
|
||||||
@ -326,8 +325,7 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
// handle the case where the TrackSelectionView is never created.
|
// handle the case where the TrackSelectionView is never created.
|
||||||
this.overrides =
|
this.overrides =
|
||||||
new HashMap<>(
|
new HashMap<>(
|
||||||
TrackSelectionView.filterOverrides(
|
TrackSelectionView.filterOverrides(overrides, trackGroups, allowMultipleOverrides));
|
||||||
overrides, trackGroupInfos, allowMultipleOverrides));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -343,7 +341,7 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
trackSelectionView.setAllowMultipleOverrides(allowMultipleOverrides);
|
trackSelectionView.setAllowMultipleOverrides(allowMultipleOverrides);
|
||||||
trackSelectionView.setAllowAdaptiveSelections(allowAdaptiveSelections);
|
trackSelectionView.setAllowAdaptiveSelections(allowAdaptiveSelections);
|
||||||
trackSelectionView.init(
|
trackSelectionView.init(
|
||||||
trackGroupInfos,
|
trackGroups,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
overrides,
|
overrides,
|
||||||
/* trackFormatComparator= */ null,
|
/* trackFormatComparator= */ null,
|
||||||
|
@ -2,49 +2,63 @@
|
|||||||
title: Track selection
|
title: Track selection
|
||||||
---
|
---
|
||||||
|
|
||||||
Track selection determines which of the available media tracks are played by the
|
When a media item contains multiple tracks, track selection is the process that
|
||||||
player. This process is configured by [`TrackSelectionParameters`][], which
|
determines which of them are chosen for playback. The track selection process is
|
||||||
support many different options to specify constraints and overrides.
|
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
|
You can listen to `Player.Listener.onTracksChanged` to be notified about changes
|
||||||
selection. You can listen to `Player.Listener.onTracksInfoChanged` to get
|
to tracks, including:
|
||||||
notified about changes, which may happen
|
|
||||||
* When preparation completes
|
* The available tracks becoming known when preparation of the media item being
|
||||||
* When the available or selected tracks change
|
played completes. Note that the player needs to prepare a media item to know
|
||||||
* When the playlist item changes
|
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() {
|
player.addListener(new Player.Listener() {
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
// Update UI using current TracksInfo.
|
// Update UI using current tracks.
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
~~~
|
~~~
|
||||||
{: .language-java}
|
{: .language-java}
|
||||||
|
|
||||||
You can also retrieve the current `TracksInfo` by calling
|
You can also query the current tracks by calling `player.getCurrentTracks()`.
|
||||||
`player.getCurrentTracksInfo()`.
|
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
|
As an example of how tracks can be grouped, consider an adaptive playback where
|
||||||
track type, format details, player support and selection status of each
|
a main video feed is provided in five bitrates, and an alternative video feed
|
||||||
available track. Tracks are grouped together into one `TrackGroup` if they
|
(e.g., a different camera angle in a sports match) is provided in two bitrates.
|
||||||
represent the same content that can be used interchangeably by the player (for
|
In this case there will be two video track groups, one corresponding to the main
|
||||||
example, all audio tracks of a single language, but with different bitrates).
|
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.
|
// Group level information.
|
||||||
@C.TrackType int trackType = groupInfo.getTrackType();
|
@C.TrackType int trackType = trackGroup.getTrackType();
|
||||||
boolean trackInGroupIsSelected = groupInfo.isSelected();
|
boolean trackInGroupIsSelected = trackGroup.isSelected();
|
||||||
boolean trackInGroupIsSupported = groupInfo.isSupported();
|
boolean trackInGroupIsSupported = trackGroup.isSupported();
|
||||||
for (int i = 0; i < groupInfo.length; i++) {
|
for (int i = 0; i < trackGroup.length; i++) {
|
||||||
// Individual track information.
|
// Individual track information.
|
||||||
boolean isSupported = groupInfo.isTrackSupported(i);
|
boolean isSupported = trackGroup.isTrackSupported(i);
|
||||||
boolean isSelected = groupInfo.isTrackSelected(i);
|
boolean isSelected = trackGroup.isTrackSelected(i);
|
||||||
Format trackFormat = groupInfo.getTrackFormat(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
|
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
|
supported individually and the player is not necessarily able to play them at
|
||||||
the same time.
|
the same time.
|
||||||
* A track is 'selected' if the track selector chose this track for playback
|
* A track is 'selected' if it has been chosen for playback given the current
|
||||||
using the current `TrackSelectionParameters`. If multiple tracks within one
|
`TrackSelectionParameters`. If multiple tracks within one track group are
|
||||||
track group are selected, the player uses these tracks for adaptive playback
|
selected, the player uses these tracks for adaptive playback (for example,
|
||||||
(for example, multiple video tracks with different bitrates). Note that only
|
multiple video tracks with different bitrates). Note that only one of these
|
||||||
one of these tracks will be played at any one time. If you want to be notified
|
tracks will be played at any one time.
|
||||||
of in-playback changes to the adaptive video track you can listen to
|
|
||||||
`Player.Listener.onVideoSizeChanged`.
|
|
||||||
|
|
||||||
## Modifying track selection parameters
|
## Modifying track selection parameters
|
||||||
|
|
||||||
The selection process can be configured by setting `TrackSelectionParameters` on
|
The track selection process can be configured using
|
||||||
the `Player` with `Player.setTrackSelectionParameters`. These updates can be
|
`Player.setTrackSelectionParameters`. This can be done both before and during
|
||||||
done before and during playback. In most cases, it's advisable to obtain the
|
playback. The example below demonstrates how to obtain the current
|
||||||
current parameters and only modify the required aspects with the
|
`TrackSelectionParameters` from the player, modify them, and update the `Player`
|
||||||
`TrackSelectionParameters.Builder`. The builder class also allows chaining to
|
with the modified result:
|
||||||
specify multiple options with one command:
|
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
player.setTrackSelectionParameters(
|
player.setTrackSelectionParameters(
|
||||||
@ -85,58 +96,60 @@ player.setTrackSelectionParameters(
|
|||||||
### Constraint based track selection
|
### Constraint based track selection
|
||||||
|
|
||||||
Most options in `TrackSelectionParameters` allow you to specify constraints,
|
Most options in `TrackSelectionParameters` allow you to specify constraints,
|
||||||
which are independent of the tracks that are actually available. Typical
|
which are independent of the tracks that are actually available. Available
|
||||||
constraints are:
|
constraints include:
|
||||||
|
|
||||||
* Maximum or minimum video width, height, frame rate, or bitrate.
|
* Maximum and minimum video width, height, frame rate, and bitrate.
|
||||||
* Maximum audio channel count or bitrate.
|
* Maximum audio channel count and bitrate.
|
||||||
* Preferred MIME types for video or audio.
|
* Preferred MIME types for video and audio.
|
||||||
* Preferred audio languages or role flags.
|
* Preferred audio languages and role flags.
|
||||||
* Preferred text languages or role flags.
|
* Preferred text languages and role flags.
|
||||||
|
|
||||||
Note that ExoPlayer already applies sensible defaults for most of these values,
|
ExoPlayer uses sensible defaults for these constraints, for example restricting
|
||||||
for example restricting video resolution to the display size or preferring the
|
video resolution to the display size and preferring the audio language that
|
||||||
audio language that matches the user's system Locale setting.
|
matches the user's system Locale setting.
|
||||||
|
|
||||||
There are several benefits to using constraint based track selection instead of
|
There are several benefits to using constraint based track selection rather than
|
||||||
specifying specific tracks directly:
|
selecting specific tracks from those that are available:
|
||||||
|
|
||||||
* You can specify constraints before knowing what tracks the media provides.
|
* You can specify constraints before knowing what tracks a media item provides.
|
||||||
This allows to immediately select the appropriate tracks for faster startup
|
This means that constraints can be specified before the player has prepared a
|
||||||
time and also simplifies track selection code as you don't have to listen for
|
media item, whereas selecting specific tracks requires application code to
|
||||||
changes in the available tracks.
|
wait until the available tracks become known.
|
||||||
* Constraints can be applied consistently across all items in a playlist. For
|
* Constraints are applied for all media items in a playlist, even when those
|
||||||
example, selecting an audio language based on user preference will
|
items have different available tracks. For example, a preferred audio language
|
||||||
automatically apply to the next playlist item too, whereas overriding a
|
constraint will be automatically applied for all media items, even if the
|
||||||
specific track will only apply to the current playlist item for which the
|
`Format` of the track in that language varies from one media item to the next.
|
||||||
track exists.
|
This is not the case when selecting specific tracks, as described below.
|
||||||
|
|
||||||
### Selecting specific tracks
|
### Selecting specific tracks
|
||||||
|
|
||||||
It's possible to specify in `TrackSelectionParameters` which of the currently
|
It's possible to select specific tracks using `TrackSelectionParameters`. First,
|
||||||
available tracks should be selected. First, the player's currently available
|
the player's currently available tracks should be queried using
|
||||||
tracks should be queried using `Player.getTracksInfo`. Second, having identified
|
`Player.getCurrentTracks`. Second, having identified which tracks to select,
|
||||||
which tracks to select, they can be set on `TrackSelectionParameters` using
|
they can be set on `TrackSelectionParameters` using a `TrackSelectionOverride`.
|
||||||
`TrackSelectionOverrides`. For example, to select the first track from a
|
For example, to select the first track from a specific `audioTrackGroup`:
|
||||||
specific `audioTrackGroup`:
|
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
player.setTrackSelectionParameters(
|
player.setTrackSelectionParameters(
|
||||||
player.getTrackSelectionParameters()
|
player.getTrackSelectionParameters()
|
||||||
.buildUpon()
|
.buildUpon()
|
||||||
.setOverrideForType(
|
.setOverrideForType(
|
||||||
new TrackSelectionOverride(audioTrackGroup, /* trackIndex= */ 0))
|
new TrackSelectionOverride(
|
||||||
|
audioTrackGroup.getTrackGroup(),
|
||||||
|
/* trackIndex= */ 0))
|
||||||
.build());
|
.build());
|
||||||
~~~
|
~~~
|
||||||
{: .language-java}
|
{: .language-java}
|
||||||
|
|
||||||
Note that a `TrackSelectionOverride` will only apply to media items that contain
|
A `TrackSelectionOverride` will only apply to media items that contain a
|
||||||
the `TrackGroup` specified in the override. Hence an override may not apply to
|
`TrackGroup` exactly matching the one specified in the override. Hence an
|
||||||
a subsequent media item if that item contains different tracks.
|
override may not apply to a subsequent media item if that item contains
|
||||||
|
different tracks.
|
||||||
|
|
||||||
### Disabling track types or groups
|
### 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
|
`TrackSelectionParameters.Builder.setTrackTypeDisabled`. A disabled track type
|
||||||
will be disabled for all media items:
|
will be disabled for all media items:
|
||||||
|
|
||||||
@ -158,7 +171,7 @@ player.setTrackSelectionParameters(
|
|||||||
.buildUpon()
|
.buildUpon()
|
||||||
.addOverride(
|
.addOverride(
|
||||||
new TrackSelectionOverride(
|
new TrackSelectionOverride(
|
||||||
disabledTrackGroup, ImmutableList.of()))
|
disabledTrackGroup.getTrackGroup(), ImmutableList.of()))
|
||||||
.build());
|
.build());
|
||||||
~~~
|
~~~
|
||||||
{: .language-java}
|
{: .language-java}
|
||||||
|
@ -37,8 +37,7 @@ import com.google.android.exoplayer2.PlaybackException;
|
|||||||
import com.google.android.exoplayer2.PlaybackParameters;
|
import com.google.android.exoplayer2.PlaybackParameters;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.TracksInfo;
|
import com.google.android.exoplayer2.Tracks;
|
||||||
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
|
|
||||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.text.Cue;
|
import com.google.android.exoplayer2.text.Cue;
|
||||||
@ -134,7 +133,7 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
private final StateHolder<PlaybackParameters> playbackParameters;
|
private final StateHolder<PlaybackParameters> playbackParameters;
|
||||||
@Nullable private RemoteMediaClient remoteMediaClient;
|
@Nullable private RemoteMediaClient remoteMediaClient;
|
||||||
private CastTimeline currentTimeline;
|
private CastTimeline currentTimeline;
|
||||||
private TracksInfo currentTracksInfo;
|
private Tracks currentTracks;
|
||||||
private Commands availableCommands;
|
private Commands availableCommands;
|
||||||
private @Player.State int playbackState;
|
private @Player.State int playbackState;
|
||||||
private int currentWindowIndex;
|
private int currentWindowIndex;
|
||||||
@ -210,7 +209,7 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
playbackParameters = new StateHolder<>(PlaybackParameters.DEFAULT);
|
playbackParameters = new StateHolder<>(PlaybackParameters.DEFAULT);
|
||||||
playbackState = STATE_IDLE;
|
playbackState = STATE_IDLE;
|
||||||
currentTimeline = CastTimeline.EMPTY_CAST_TIMELINE;
|
currentTimeline = CastTimeline.EMPTY_CAST_TIMELINE;
|
||||||
currentTracksInfo = TracksInfo.EMPTY;
|
currentTracks = Tracks.EMPTY;
|
||||||
availableCommands = new Commands.Builder().addAll(PERMANENT_AVAILABLE_COMMANDS).build();
|
availableCommands = new Commands.Builder().addAll(PERMANENT_AVAILABLE_COMMANDS).build();
|
||||||
pendingSeekWindowIndex = C.INDEX_UNSET;
|
pendingSeekWindowIndex = C.INDEX_UNSET;
|
||||||
pendingSeekPositionMs = C.TIME_UNSET;
|
pendingSeekPositionMs = C.TIME_UNSET;
|
||||||
@ -542,8 +541,8 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
return currentTracksInfo;
|
return currentTracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -816,7 +815,7 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
}
|
}
|
||||||
if (updateTracksAndSelectionsAndNotifyIfChanged()) {
|
if (updateTracksAndSelectionsAndNotifyIfChanged()) {
|
||||||
listeners.queueEvent(
|
listeners.queueEvent(
|
||||||
Player.EVENT_TRACKS_CHANGED, listener -> listener.onTracksInfoChanged(currentTracksInfo));
|
Player.EVENT_TRACKS_CHANGED, listener -> listener.onTracksChanged(currentTracks));
|
||||||
}
|
}
|
||||||
updateAvailableCommandsAndNotifyIfChanged();
|
updateAvailableCommandsAndNotifyIfChanged();
|
||||||
listeners.flushEvents();
|
listeners.flushEvents();
|
||||||
@ -976,8 +975,8 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
@Nullable
|
@Nullable
|
||||||
List<MediaTrack> castMediaTracks = mediaInfo != null ? mediaInfo.getMediaTracks() : null;
|
List<MediaTrack> castMediaTracks = mediaInfo != null ? mediaInfo.getMediaTracks() : null;
|
||||||
if (castMediaTracks == null || castMediaTracks.isEmpty()) {
|
if (castMediaTracks == null || castMediaTracks.isEmpty()) {
|
||||||
boolean hasChanged = !TracksInfo.EMPTY.equals(currentTracksInfo);
|
boolean hasChanged = !Tracks.EMPTY.equals(currentTracks);
|
||||||
currentTracksInfo = TracksInfo.EMPTY;
|
currentTracks = Tracks.EMPTY;
|
||||||
return hasChanged;
|
return hasChanged;
|
||||||
}
|
}
|
||||||
@Nullable long[] activeTrackIds = mediaStatus.getActiveTrackIds();
|
@Nullable long[] activeTrackIds = mediaStatus.getActiveTrackIds();
|
||||||
@ -985,20 +984,19 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
activeTrackIds = EMPTY_TRACK_ID_ARRAY;
|
activeTrackIds = EMPTY_TRACK_ID_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackGroupInfo[] trackGroupInfos = new TrackGroupInfo[castMediaTracks.size()];
|
Tracks.Group[] trackGroups = new Tracks.Group[castMediaTracks.size()];
|
||||||
for (int i = 0; i < castMediaTracks.size(); i++) {
|
for (int i = 0; i < castMediaTracks.size(); i++) {
|
||||||
MediaTrack mediaTrack = castMediaTracks.get(i);
|
MediaTrack mediaTrack = castMediaTracks.get(i);
|
||||||
TrackGroup trackGroup =
|
TrackGroup trackGroup =
|
||||||
new TrackGroup(/* id= */ Integer.toString(i), CastUtils.mediaTrackToFormat(mediaTrack));
|
new TrackGroup(/* id= */ Integer.toString(i), CastUtils.mediaTrackToFormat(mediaTrack));
|
||||||
@C.FormatSupport int[] trackSupport = new int[] {C.FORMAT_HANDLED};
|
@C.FormatSupport int[] trackSupport = new int[] {C.FORMAT_HANDLED};
|
||||||
boolean[] trackSelected = new boolean[] {isTrackActive(mediaTrack.getId(), activeTrackIds)};
|
boolean[] trackSelected = new boolean[] {isTrackActive(mediaTrack.getId(), activeTrackIds)};
|
||||||
trackGroupInfos[i] =
|
trackGroups[i] =
|
||||||
new TrackGroupInfo(
|
new Tracks.Group(trackGroup, /* adaptiveSupported= */ false, trackSupport, trackSelected);
|
||||||
trackGroup, /* adaptiveSupported= */ false, trackSupport, trackSelected);
|
|
||||||
}
|
}
|
||||||
TracksInfo newTracksInfo = new TracksInfo(ImmutableList.copyOf(trackGroupInfos));
|
Tracks newTracks = new Tracks(ImmutableList.copyOf(trackGroups));
|
||||||
if (!newTracksInfo.equals(currentTracksInfo)) {
|
if (!newTracks.equals(currentTracks)) {
|
||||||
currentTracksInfo = newTracksInfo;
|
currentTracks = newTracks;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -710,7 +710,7 @@ import java.util.Map;
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for a selected track using an audio renderer.
|
// Check for a selected track using an audio renderer.
|
||||||
return player.getCurrentTracksInfo().isTypeSelected(C.TRACK_TYPE_AUDIO) ? 100 : 0;
|
return player.getCurrentTracks().isTypeSelected(C.TRACK_TYPE_AUDIO) ? 100 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleAdEvent(AdEvent adEvent) {
|
private void handleAdEvent(AdEvent adEvent) {
|
||||||
|
@ -24,7 +24,7 @@ import com.google.android.exoplayer2.MediaItem;
|
|||||||
import com.google.android.exoplayer2.PlaybackException;
|
import com.google.android.exoplayer2.PlaybackException;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
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.testutil.StubExoPlayer;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
|
||||||
@ -266,8 +266,8 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
return TracksInfo.EMPTY;
|
return Tracks.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -444,10 +444,10 @@ public class ForwardingPlayer implements Player {
|
|||||||
player.release();
|
player.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Calls {@link Player#getCurrentTracksInfo()} on the delegate and returns the result. */
|
/** Calls {@link Player#getCurrentTracks()} on the delegate and returns the result. */
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
return player.getCurrentTracksInfo();
|
return player.getCurrentTracks();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Calls {@link Player#getTrackSelectionParameters()} on the delegate and returns the result. */
|
/** Calls {@link Player#getTrackSelectionParameters()} on the delegate and returns the result. */
|
||||||
@ -833,8 +833,8 @@ public class ForwardingPlayer implements Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
listener.onTracksInfoChanged(tracksInfo);
|
listener.onTracksChanged(tracks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,8 +61,8 @@ import java.util.List;
|
|||||||
* <ul>
|
* <ul>
|
||||||
* <li>They can provide a {@link Timeline} representing the structure of the media being played,
|
* <li>They can provide a {@link Timeline} representing the structure of the media being played,
|
||||||
* which can be obtained by calling {@link #getCurrentTimeline()}.
|
* which can be obtained by calling {@link #getCurrentTimeline()}.
|
||||||
* <li>They can provide a {@link TracksInfo} defining the currently available tracks and which are
|
* <li>They can provide a {@link Tracks} defining the currently available tracks and which are
|
||||||
* selected to be rendered, which can be obtained by calling {@link #getCurrentTracksInfo()}.
|
* selected to be rendered, which can be obtained by calling {@link #getCurrentTracks()}.
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public interface Player {
|
public interface Player {
|
||||||
@ -673,14 +673,14 @@ public interface Player {
|
|||||||
@Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {}
|
@Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the available or selected tracks change.
|
* Called when the tracks change.
|
||||||
*
|
*
|
||||||
* <p>{@link #onEvents(Player, Events)} will also be called to report this event along with
|
* <p>{@link #onEvents(Player, Events)} will also be called to report this event along with
|
||||||
* other events that happen in the same {@link Looper} message queue iteration.
|
* other events that happen in the same {@link Looper} message queue iteration.
|
||||||
*
|
*
|
||||||
* @param tracksInfo The available tracks information. Never null, but may be of length zero.
|
* @param tracks The available tracks information. Never null, but may be of length zero.
|
||||||
*/
|
*/
|
||||||
default void onTracksInfoChanged(TracksInfo tracksInfo) {}
|
default void onTracksChanged(Tracks tracks) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the combined {@link MediaMetadata} changes.
|
* Called when the combined {@link MediaMetadata} changes.
|
||||||
@ -1299,7 +1299,7 @@ public interface Player {
|
|||||||
int EVENT_TIMELINE_CHANGED = 0;
|
int EVENT_TIMELINE_CHANGED = 0;
|
||||||
/** {@link #getCurrentMediaItem()} changed or the player started repeating the current item. */
|
/** {@link #getCurrentMediaItem()} changed or the player started repeating the current item. */
|
||||||
int EVENT_MEDIA_ITEM_TRANSITION = 1;
|
int EVENT_MEDIA_ITEM_TRANSITION = 1;
|
||||||
/** {@link #getCurrentTracksInfo()} changed. */
|
/** {@link #getCurrentTracks()} changed. */
|
||||||
int EVENT_TRACKS_CHANGED = 2;
|
int EVENT_TRACKS_CHANGED = 2;
|
||||||
/** {@link #isLoading()} ()} changed. */
|
/** {@link #isLoading()} ()} changed. */
|
||||||
int EVENT_IS_LOADING_CHANGED = 3;
|
int EVENT_IS_LOADING_CHANGED = 3;
|
||||||
@ -2074,11 +2074,11 @@ public interface Player {
|
|||||||
void release();
|
void release();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns information about the current tracks.
|
* Returns the current tracks.
|
||||||
*
|
*
|
||||||
* @see Listener#onTracksInfoChanged(TracksInfo)
|
* @see Listener#onTracksChanged(Tracks)
|
||||||
*/
|
*/
|
||||||
TracksInfo getCurrentTracksInfo();
|
Tracks getCurrentTracks();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the parameters constraining the track selection.
|
* Returns the parameters constraining the track selection.
|
||||||
|
@ -37,14 +37,14 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Information about groups of tracks. */
|
/** Information about groups of tracks. */
|
||||||
public final class TracksInfo implements Bundleable {
|
public final class Tracks implements Bundleable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about a single group of tracks, including the underlying {@link TrackGroup}, the
|
* Information about a single group of tracks, including the underlying {@link TrackGroup}, the
|
||||||
* level to which each track is supported by the player, and whether any of the tracks are
|
* level to which each track is supported by the player, and whether any of the tracks are
|
||||||
* selected.
|
* selected.
|
||||||
*/
|
*/
|
||||||
public static final class TrackGroupInfo implements Bundleable {
|
public static final class Group implements Bundleable {
|
||||||
|
|
||||||
/** The number of tracks in the group. */
|
/** The number of tracks in the group. */
|
||||||
public final int length;
|
public final int length;
|
||||||
@ -63,7 +63,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
* @param trackSupport The {@link C.FormatSupport} of each track in the group.
|
* @param trackSupport The {@link C.FormatSupport} of each track in the group.
|
||||||
* @param trackSelected Whether each track in the {@code trackGroup} is selected.
|
* @param trackSelected Whether each track in the {@code trackGroup} is selected.
|
||||||
*/
|
*/
|
||||||
public TrackGroupInfo(
|
public Group(
|
||||||
TrackGroup trackGroup,
|
TrackGroup trackGroup,
|
||||||
boolean adaptiveSupported,
|
boolean adaptiveSupported,
|
||||||
@C.FormatSupport int[] trackSupport,
|
@C.FormatSupport int[] trackSupport,
|
||||||
@ -84,7 +84,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
/**
|
/**
|
||||||
* Returns the {@link Format} for a specified track.
|
* Returns the {@link Format} for a specified track.
|
||||||
*
|
*
|
||||||
* @param trackIndex The index of the track in the {@link TrackGroup}.
|
* @param trackIndex The index of the track in the group.
|
||||||
* @return The {@link Format} of the track.
|
* @return The {@link Format} of the track.
|
||||||
*/
|
*/
|
||||||
public Format getTrackFormat(int trackIndex) {
|
public Format getTrackFormat(int trackIndex) {
|
||||||
@ -94,7 +94,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
/**
|
/**
|
||||||
* Returns the level of support for a specified track.
|
* Returns the level of support for a specified track.
|
||||||
*
|
*
|
||||||
* @param trackIndex The index of the track in the {@link TrackGroup}.
|
* @param trackIndex The index of the track in the group.
|
||||||
* @return The {@link C.FormatSupport} of the track.
|
* @return The {@link C.FormatSupport} of the track.
|
||||||
*/
|
*/
|
||||||
public @C.FormatSupport int getTrackSupport(int trackIndex) {
|
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
|
* Returns whether a specified track is supported for playback, without exceeding the advertised
|
||||||
* capabilities of the device. Equivalent to {@code isTrackSupported(trackIndex, false)}.
|
* capabilities of the device. Equivalent to {@code isTrackSupported(trackIndex, false)}.
|
||||||
*
|
*
|
||||||
* @param trackIndex The index of the track in the {@link TrackGroup}.
|
* @param trackIndex The index of the track in the group.
|
||||||
* @return True if the track's format can be played, false otherwise.
|
* @return True if the track's format can be played, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isTrackSupported(int trackIndex) {
|
public boolean isTrackSupported(int trackIndex) {
|
||||||
@ -115,7 +115,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether a specified track is supported for playback.
|
* Returns whether a specified track is supported for playback.
|
||||||
*
|
*
|
||||||
* @param trackIndex The index of the track in the {@link TrackGroup}.
|
* @param trackIndex The index of the track in the group.
|
||||||
* @param allowExceedsCapabilities Whether to consider the track as supported if it has a
|
* @param allowExceedsCapabilities Whether to consider the track as supported if it has a
|
||||||
* supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised
|
* supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised
|
||||||
* capabilities of the device. For example, a video track for which there's a corresponding
|
* capabilities of the device. For example, a video track for which there's a corresponding
|
||||||
@ -176,7 +176,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
* playing, however some player implementations have ways of getting such information. For
|
* playing, however some player implementations have ways of getting such information. For
|
||||||
* example, ExoPlayer provides this information via {@code ExoTrackSelection.getSelectedFormat}.
|
* example, ExoPlayer provides this information via {@code ExoTrackSelection.getSelectedFormat}.
|
||||||
*
|
*
|
||||||
* @param trackIndex The index of the track in the {@link TrackGroup}.
|
* @param trackIndex The index of the track in the group.
|
||||||
* @return True if the track is selected, false otherwise.
|
* @return True if the track is selected, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isTrackSelected(int trackIndex) {
|
public boolean isTrackSelected(int trackIndex) {
|
||||||
@ -184,7 +184,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the {@link C.TrackType} of the group. */
|
/** Returns the {@link C.TrackType} of the group. */
|
||||||
public @C.TrackType int getTrackType() {
|
public @C.TrackType int getType() {
|
||||||
return trackGroup.type;
|
return trackGroup.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
if (other == null || getClass() != other.getClass()) {
|
if (other == null || getClass() != other.getClass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
TrackGroupInfo that = (TrackGroupInfo) other;
|
Group that = (Group) other;
|
||||||
return adaptiveSupported == that.adaptiveSupported
|
return adaptiveSupported == that.adaptiveSupported
|
||||||
&& trackGroup.equals(that.trackGroup)
|
&& trackGroup.equals(that.trackGroup)
|
||||||
&& Arrays.equals(trackSupport, that.trackSupport)
|
&& Arrays.equals(trackSupport, that.trackSupport)
|
||||||
@ -239,8 +239,8 @@ public final class TracksInfo implements Bundleable {
|
|||||||
return bundle;
|
return bundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Object that can restores a {@code TracksInfo} from a {@link Bundle}. */
|
/** Object that can restore a group of tracks from a {@link Bundle}. */
|
||||||
public static final Creator<TrackGroupInfo> CREATOR =
|
public static final Creator<Group> CREATOR =
|
||||||
bundle -> {
|
bundle -> {
|
||||||
TrackGroup trackGroup =
|
TrackGroup trackGroup =
|
||||||
fromNullableBundle(
|
fromNullableBundle(
|
||||||
@ -255,7 +255,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
new boolean[trackGroup.length]);
|
new boolean[trackGroup.length]);
|
||||||
boolean adaptiveSupported =
|
boolean adaptiveSupported =
|
||||||
bundle.getBoolean(keyForField(FIELD_ADAPTIVE_SUPPORTED), false);
|
bundle.getBoolean(keyForField(FIELD_ADAPTIVE_SUPPORTED), false);
|
||||||
return new TrackGroupInfo(trackGroup, adaptiveSupported, trackSupport, selected);
|
return new Group(trackGroup, adaptiveSupported, trackSupport, selected);
|
||||||
};
|
};
|
||||||
|
|
||||||
private static String keyForField(@FieldNumber int field) {
|
private static String keyForField(@FieldNumber int field) {
|
||||||
@ -263,30 +263,34 @@ public final class TracksInfo implements Bundleable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An {@code TrackInfo} that contains no tracks. */
|
/** Empty tracks. */
|
||||||
public static final TracksInfo EMPTY = new TracksInfo(ImmutableList.of());
|
public static final Tracks EMPTY = new Tracks(ImmutableList.of());
|
||||||
|
|
||||||
private final ImmutableList<TrackGroupInfo> trackGroupInfos;
|
private final ImmutableList<Group> groups;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance.
|
* Constructs an instance.
|
||||||
*
|
*
|
||||||
* @param trackGroupInfos The {@link TrackGroupInfo TrackGroupInfos} describing the groups of
|
* @param groups The {@link Group groups} of tracks.
|
||||||
* tracks.
|
|
||||||
*/
|
*/
|
||||||
public TracksInfo(List<TrackGroupInfo> trackGroupInfos) {
|
public Tracks(List<Group> groups) {
|
||||||
this.trackGroupInfos = ImmutableList.copyOf(trackGroupInfos);
|
this.groups = ImmutableList.copyOf(groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the {@link TrackGroupInfo TrackGroupInfos} describing the groups of tracks. */
|
/** Returns the {@link Group groups} of tracks. */
|
||||||
public ImmutableList<TrackGroupInfo> getTrackGroupInfos() {
|
public ImmutableList<Group> getGroups() {
|
||||||
return trackGroupInfos;
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns {@code true} if there are no tracks, and {@code false} otherwise. */
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return groups.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if there are tracks of type {@code trackType}, and false otherwise. */
|
/** Returns true if there are tracks of type {@code trackType}, and false otherwise. */
|
||||||
public boolean containsType(@C.TrackType int trackType) {
|
public boolean containsType(@C.TrackType int trackType) {
|
||||||
for (int i = 0; i < trackGroupInfos.size(); i++) {
|
for (int i = 0; i < groups.size(); i++) {
|
||||||
if (trackGroupInfos.get(i).getTrackType() == trackType) {
|
if (groups.get(i).getType() == trackType) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,7 +299,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if at least one track of type {@code trackType} is {@link
|
* Returns true if at least one track of type {@code trackType} is {@link
|
||||||
* TrackGroupInfo#isTrackSupported(int) supported}.
|
* Group#isTrackSupported(int) supported}.
|
||||||
*/
|
*/
|
||||||
public boolean isTypeSupported(@C.TrackType int trackType) {
|
public boolean isTypeSupported(@C.TrackType int trackType) {
|
||||||
return isTypeSupported(trackType, /* allowExceedsCapabilities= */ false);
|
return isTypeSupported(trackType, /* allowExceedsCapabilities= */ false);
|
||||||
@ -303,7 +307,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if at least one track of type {@code trackType} is {@link
|
* Returns true if at least one track of type {@code trackType} is {@link
|
||||||
* TrackGroupInfo#isTrackSupported(int, boolean) supported}.
|
* Group#isTrackSupported(int, boolean) supported}.
|
||||||
*
|
*
|
||||||
* @param allowExceedsCapabilities Whether to consider the track as supported if it has a
|
* @param allowExceedsCapabilities Whether to consider the track as supported if it has a
|
||||||
* supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised
|
* supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised
|
||||||
@ -312,9 +316,9 @@ public final class TracksInfo implements Bundleable {
|
|||||||
* Such tracks may be playable in some cases.
|
* Such tracks may be playable in some cases.
|
||||||
*/
|
*/
|
||||||
public boolean isTypeSupported(@C.TrackType int trackType, boolean allowExceedsCapabilities) {
|
public boolean isTypeSupported(@C.TrackType int trackType, boolean allowExceedsCapabilities) {
|
||||||
for (int i = 0; i < trackGroupInfos.size(); i++) {
|
for (int i = 0; i < groups.size(); i++) {
|
||||||
if (trackGroupInfos.get(i).getTrackType() == trackType) {
|
if (groups.get(i).getType() == trackType) {
|
||||||
if (trackGroupInfos.get(i).isSupported(allowExceedsCapabilities)) {
|
if (groups.get(i).isSupported(allowExceedsCapabilities)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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. */
|
/** Returns true if at least one track of the type {@code trackType} is selected for playback. */
|
||||||
public boolean isTypeSelected(@C.TrackType int trackType) {
|
public boolean isTypeSelected(@C.TrackType int trackType) {
|
||||||
for (int i = 0; i < trackGroupInfos.size(); i++) {
|
for (int i = 0; i < groups.size(); i++) {
|
||||||
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(i);
|
Group group = groups.get(i);
|
||||||
if (trackGroupInfo.isSelected() && trackGroupInfo.getTrackType() == trackType) {
|
if (group.isSelected() && group.getType() == trackType) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -359,13 +363,13 @@ public final class TracksInfo implements Bundleable {
|
|||||||
if (other == null || getClass() != other.getClass()) {
|
if (other == null || getClass() != other.getClass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
TracksInfo that = (TracksInfo) other;
|
Tracks that = (Tracks) other;
|
||||||
return trackGroupInfos.equals(that.trackGroupInfos);
|
return groups.equals(that.groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return trackGroupInfos.hashCode();
|
return groups.hashCode();
|
||||||
}
|
}
|
||||||
// Bundleable implementation.
|
// Bundleable implementation.
|
||||||
|
|
||||||
@ -373,29 +377,28 @@ public final class TracksInfo implements Bundleable {
|
|||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@Target(TYPE_USE)
|
@Target(TYPE_USE)
|
||||||
@IntDef({
|
@IntDef({
|
||||||
FIELD_TRACK_GROUP_INFOS,
|
FIELD_TRACK_GROUPS,
|
||||||
})
|
})
|
||||||
private @interface FieldNumber {}
|
private @interface FieldNumber {}
|
||||||
|
|
||||||
private static final int FIELD_TRACK_GROUP_INFOS = 0;
|
private static final int FIELD_TRACK_GROUPS = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bundle toBundle() {
|
public Bundle toBundle() {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putParcelableArrayList(
|
bundle.putParcelableArrayList(keyForField(FIELD_TRACK_GROUPS), toBundleArrayList(groups));
|
||||||
keyForField(FIELD_TRACK_GROUP_INFOS), toBundleArrayList(trackGroupInfos));
|
|
||||||
return bundle;
|
return bundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Object that can restore a {@code TracksInfo} from a {@link Bundle}. */
|
/** Object that can restore tracks from a {@link Bundle}. */
|
||||||
public static final Creator<TracksInfo> CREATOR =
|
public static final Creator<Tracks> CREATOR =
|
||||||
bundle -> {
|
bundle -> {
|
||||||
List<TrackGroupInfo> trackGroupInfos =
|
List<Group> groups =
|
||||||
fromBundleNullableList(
|
fromBundleNullableList(
|
||||||
TrackGroupInfo.CREATOR,
|
Group.CREATOR,
|
||||||
bundle.getParcelableArrayList(keyForField(FIELD_TRACK_GROUP_INFOS)),
|
bundle.getParcelableArrayList(keyForField(FIELD_TRACK_GROUPS)),
|
||||||
/* defaultValue= */ ImmutableList.of());
|
/* defaultValue= */ ImmutableList.of());
|
||||||
return new TracksInfo(trackGroupInfos);
|
return new Tracks(groups);
|
||||||
};
|
};
|
||||||
|
|
||||||
private static String keyForField(@FieldNumber int field) {
|
private static String keyForField(@FieldNumber int field) {
|
@ -94,7 +94,7 @@ public final class TrackSelectionOverride implements Bundleable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the {@link C.TrackType} of the overridden track group. */
|
/** Returns the {@link C.TrackType} of the overridden track group. */
|
||||||
public @C.TrackType int getTrackType() {
|
public @C.TrackType int getType() {
|
||||||
return trackGroup.type;
|
return trackGroup.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,7 +682,7 @@ public class TrackSelectionParameters implements Bundleable {
|
|||||||
|
|
||||||
/** Sets an override, replacing all existing overrides with the same track type. */
|
/** Sets an override, replacing all existing overrides with the same track type. */
|
||||||
public Builder setOverrideForType(TrackSelectionOverride override) {
|
public Builder setOverrideForType(TrackSelectionOverride override) {
|
||||||
clearOverridesOfType(override.getTrackType());
|
clearOverridesOfType(override.getType());
|
||||||
overrides.put(override.trackGroup, override);
|
overrides.put(override.trackGroup, override);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -698,7 +698,7 @@ public class TrackSelectionParameters implements Bundleable {
|
|||||||
Iterator<TrackSelectionOverride> it = overrides.values().iterator();
|
Iterator<TrackSelectionOverride> it = overrides.values().iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
TrackSelectionOverride override = it.next();
|
TrackSelectionOverride override = it.next();
|
||||||
if (override.getTrackType() == trackType) {
|
if (override.getType() == trackType) {
|
||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -1172,8 +1172,8 @@ public interface ExoPlayer extends Player {
|
|||||||
/**
|
/**
|
||||||
* Returns the available track groups.
|
* Returns the available track groups.
|
||||||
*
|
*
|
||||||
* @see Listener#onTracksInfoChanged(TracksInfo)
|
* @see Listener#onTracksChanged(Tracks)
|
||||||
* @deprecated Use {@link #getCurrentTracksInfo()}.
|
* @deprecated Use {@link #getCurrentTracks()}.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
TrackGroupArray getCurrentTrackGroups();
|
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
|
* Returns the current track selections for each renderer, which may include {@code null} elements
|
||||||
* if some renderers do not have any selected tracks.
|
* if some renderers do not have any selected tracks.
|
||||||
*
|
*
|
||||||
* @see Listener#onTracksInfoChanged(TracksInfo)
|
* @see Listener#onTracksChanged(Tracks)
|
||||||
* @deprecated Use {@link #getCurrentTracksInfo()}.
|
* @deprecated Use {@link #getCurrentTracks()}.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
TrackSelectionArray getCurrentTrackSelections();
|
TrackSelectionArray getCurrentTrackSelections();
|
||||||
|
@ -266,7 +266,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
new TrackSelectorResult(
|
new TrackSelectorResult(
|
||||||
new RendererConfiguration[renderers.length],
|
new RendererConfiguration[renderers.length],
|
||||||
new ExoTrackSelection[renderers.length],
|
new ExoTrackSelection[renderers.length],
|
||||||
TracksInfo.EMPTY,
|
Tracks.EMPTY,
|
||||||
/* info= */ null);
|
/* info= */ null);
|
||||||
period = new Timeline.Period();
|
period = new Timeline.Period();
|
||||||
permanentAvailableCommands =
|
permanentAvailableCommands =
|
||||||
@ -1136,9 +1136,9 @@ import java.util.concurrent.TimeoutException;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
return playbackInfo.trackSelectorResult.tracksInfo;
|
return playbackInfo.trackSelectorResult.tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1887,7 +1887,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
trackSelector.onSelectionActivated(newPlaybackInfo.trackSelectorResult.info);
|
trackSelector.onSelectionActivated(newPlaybackInfo.trackSelectorResult.info);
|
||||||
listeners.queueEvent(
|
listeners.queueEvent(
|
||||||
Player.EVENT_TRACKS_CHANGED,
|
Player.EVENT_TRACKS_CHANGED,
|
||||||
listener -> listener.onTracksInfoChanged(newPlaybackInfo.trackSelectorResult.tracksInfo));
|
listener -> listener.onTracksChanged(newPlaybackInfo.trackSelectorResult.tracks));
|
||||||
}
|
}
|
||||||
if (metadataChanged) {
|
if (metadataChanged) {
|
||||||
final MediaMetadata finalMediaMetadata = mediaMetadata;
|
final MediaMetadata finalMediaMetadata = mediaMetadata;
|
||||||
|
@ -1049,9 +1049,9 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
blockUntilConstructorFinished();
|
blockUntilConstructorFinished();
|
||||||
return player.getCurrentTracksInfo();
|
return player.getCurrentTracks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -42,7 +42,7 @@ import com.google.android.exoplayer2.Player.DiscontinuityReason;
|
|||||||
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
|
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
|
||||||
import com.google.android.exoplayer2.Player.TimelineChangeReason;
|
import com.google.android.exoplayer2.Player.TimelineChangeReason;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
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.AudioAttributes;
|
||||||
import com.google.android.exoplayer2.audio.AudioSink;
|
import com.google.android.exoplayer2.audio.AudioSink;
|
||||||
import com.google.android.exoplayer2.decoder.DecoderCounters;
|
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.
|
* {@link Player#getCurrentMediaItem()} changed or the player started repeating the current item.
|
||||||
*/
|
*/
|
||||||
int EVENT_MEDIA_ITEM_TRANSITION = Player.EVENT_MEDIA_ITEM_TRANSITION;
|
int EVENT_MEDIA_ITEM_TRANSITION = Player.EVENT_MEDIA_ITEM_TRANSITION;
|
||||||
/** {@link Player#getCurrentTracksInfo()} changed. */
|
/** {@link Player#getCurrentTracks()} changed. */
|
||||||
int EVENT_TRACKS_CHANGED = Player.EVENT_TRACKS_CHANGED;
|
int EVENT_TRACKS_CHANGED = Player.EVENT_TRACKS_CHANGED;
|
||||||
/** {@link Player#isLoading()} ()} changed. */
|
/** {@link Player#isLoading()} ()} changed. */
|
||||||
int EVENT_IS_LOADING_CHANGED = Player.EVENT_IS_LOADING_CHANGED;
|
int EVENT_IS_LOADING_CHANGED = Player.EVENT_IS_LOADING_CHANGED;
|
||||||
@ -704,12 +704,12 @@ public interface AnalyticsListener {
|
|||||||
default void onPlayerErrorChanged(EventTime eventTime, @Nullable PlaybackException error) {}
|
default void onPlayerErrorChanged(EventTime eventTime, @Nullable PlaybackException error) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the available or selected tracks change.
|
* Called when the tracks change.
|
||||||
*
|
*
|
||||||
* @param eventTime The event time.
|
* @param eventTime The event time.
|
||||||
* @param tracksInfo The available tracks information. Never null, but may be of length zero.
|
* @param tracks The tracks. Never null, but may be of length zero.
|
||||||
*/
|
*/
|
||||||
default void onTracksInfoChanged(EventTime eventTime, TracksInfo tracksInfo) {}
|
default void onTracksChanged(EventTime eventTime, Tracks tracks) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when track selection parameters change.
|
* Called when track selection parameters change.
|
||||||
|
@ -37,7 +37,7 @@ import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
|
|||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.Timeline.Period;
|
import com.google.android.exoplayer2.Timeline.Period;
|
||||||
import com.google.android.exoplayer2.Timeline.Window;
|
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.analytics.AnalyticsListener.EventTime;
|
||||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||||
import com.google.android.exoplayer2.decoder.DecoderCounters;
|
import com.google.android.exoplayer2.decoder.DecoderCounters;
|
||||||
@ -481,12 +481,12 @@ public class DefaultAnalyticsCollector implements AnalyticsCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
sendEvent(
|
sendEvent(
|
||||||
eventTime,
|
eventTime,
|
||||||
AnalyticsListener.EVENT_TRACKS_CHANGED,
|
AnalyticsListener.EVENT_TRACKS_CHANGED,
|
||||||
listener -> listener.onTracksInfoChanged(eventTime, tracksInfo));
|
listener -> listener.onTracksChanged(eventTime, tracks));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation") // Implementing deprecated method.
|
@SuppressWarnings("deprecation") // Implementing deprecated method.
|
||||||
|
@ -49,8 +49,7 @@ import com.google.android.exoplayer2.ParserException;
|
|||||||
import com.google.android.exoplayer2.PlaybackException;
|
import com.google.android.exoplayer2.PlaybackException;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.TracksInfo;
|
import com.google.android.exoplayer2.Tracks;
|
||||||
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
|
|
||||||
import com.google.android.exoplayer2.audio.AudioSink;
|
import com.google.android.exoplayer2.audio.AudioSink;
|
||||||
import com.google.android.exoplayer2.decoder.DecoderCounters;
|
import com.google.android.exoplayer2.decoder.DecoderCounters;
|
||||||
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
|
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
|
||||||
@ -338,8 +337,7 @@ public final class MediaMetricsListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (events.contains(EVENT_TRACKS_CHANGED) && metricsBuilder != null) {
|
if (events.contains(EVENT_TRACKS_CHANGED) && metricsBuilder != null) {
|
||||||
@Nullable
|
@Nullable DrmInitData drmInitData = getDrmInitData(player.getCurrentTracks().getGroups());
|
||||||
DrmInitData drmInitData = getDrmInitData(player.getCurrentTracksInfo().getTrackGroupInfos());
|
|
||||||
if (drmInitData != null) {
|
if (drmInitData != null) {
|
||||||
castNonNull(metricsBuilder).setDrmType(getDrmType(drmInitData));
|
castNonNull(metricsBuilder).setDrmType(getDrmType(drmInitData));
|
||||||
}
|
}
|
||||||
@ -370,10 +368,10 @@ public final class MediaMetricsListener
|
|||||||
|
|
||||||
private void maybeReportTrackChanges(Player player, Events events, long realtimeMs) {
|
private void maybeReportTrackChanges(Player player, Events events, long realtimeMs) {
|
||||||
if (events.contains(EVENT_TRACKS_CHANGED)) {
|
if (events.contains(EVENT_TRACKS_CHANGED)) {
|
||||||
TracksInfo tracksInfo = player.getCurrentTracksInfo();
|
Tracks tracks = player.getCurrentTracks();
|
||||||
boolean isVideoSelected = tracksInfo.isTypeSelected(C.TRACK_TYPE_VIDEO);
|
boolean isVideoSelected = tracks.isTypeSelected(C.TRACK_TYPE_VIDEO);
|
||||||
boolean isAudioSelected = tracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO);
|
boolean isAudioSelected = tracks.isTypeSelected(C.TRACK_TYPE_AUDIO);
|
||||||
boolean isTextSelected = tracksInfo.isTypeSelected(C.TRACK_TYPE_TEXT);
|
boolean isTextSelected = tracks.isTypeSelected(C.TRACK_TYPE_TEXT);
|
||||||
if (isVideoSelected || isAudioSelected || isTextSelected) {
|
if (isVideoSelected || isAudioSelected || isTextSelected) {
|
||||||
// Ignore updates with insufficient information where no tracks are selected.
|
// Ignore updates with insufficient information where no tracks are selected.
|
||||||
if (!isVideoSelected) {
|
if (!isVideoSelected) {
|
||||||
@ -820,11 +818,11 @@ public final class MediaMetricsListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static DrmInitData getDrmInitData(ImmutableList<TrackGroupInfo> trackGroupInfos) {
|
private static DrmInitData getDrmInitData(ImmutableList<Tracks.Group> trackGroups) {
|
||||||
for (TrackGroupInfo trackGroupInfo : trackGroupInfos) {
|
for (Tracks.Group trackGroup : trackGroups) {
|
||||||
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) {
|
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
||||||
if (trackGroupInfo.isTrackSelected(trackIndex)) {
|
if (trackGroup.isTrackSelected(trackIndex)) {
|
||||||
@Nullable DrmInitData drmInitData = trackGroupInfo.getTrackFormat(trackIndex).drmInitData;
|
@Nullable DrmInitData drmInitData = trackGroup.getTrackFormat(trackIndex).drmInitData;
|
||||||
if (drmInitData != null) {
|
if (drmInitData != null) {
|
||||||
return drmInitData;
|
return drmInitData;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import com.google.android.exoplayer2.PlaybackException;
|
|||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.Timeline.Period;
|
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.EventTimeAndException;
|
||||||
import com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndFormat;
|
import com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndFormat;
|
||||||
import com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndPlaybackState;
|
import com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndPlaybackState;
|
||||||
@ -522,11 +522,11 @@ public final class PlaybackStatsListener
|
|||||||
hasFatalError = false;
|
hasFatalError = false;
|
||||||
}
|
}
|
||||||
if (isForeground && !isInterruptedByAd) {
|
if (isForeground && !isInterruptedByAd) {
|
||||||
TracksInfo currentTracksInfo = player.getCurrentTracksInfo();
|
Tracks currentTracks = player.getCurrentTracks();
|
||||||
if (!currentTracksInfo.isTypeSelected(C.TRACK_TYPE_VIDEO)) {
|
if (!currentTracks.isTypeSelected(C.TRACK_TYPE_VIDEO)) {
|
||||||
maybeUpdateVideoFormat(eventTime, /* newFormat= */ null);
|
maybeUpdateVideoFormat(eventTime, /* newFormat= */ null);
|
||||||
}
|
}
|
||||||
if (!currentTracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO)) {
|
if (!currentTracks.isTypeSelected(C.TRACK_TYPE_AUDIO)) {
|
||||||
maybeUpdateAudioFormat(eventTime, /* newFormat= */ null);
|
maybeUpdateAudioFormat(eventTime, /* newFormat= */ null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ import com.google.android.exoplayer2.Renderer;
|
|||||||
import com.google.android.exoplayer2.RendererCapabilities;
|
import com.google.android.exoplayer2.RendererCapabilities;
|
||||||
import com.google.android.exoplayer2.RenderersFactory;
|
import com.google.android.exoplayer2.RenderersFactory;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
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.analytics.PlayerId;
|
||||||
import com.google.android.exoplayer2.audio.AudioRendererEventListener;
|
import com.google.android.exoplayer2.audio.AudioRendererEventListener;
|
||||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
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.
|
* completes.
|
||||||
*
|
*
|
||||||
* @param periodIndex The period index.
|
* @param periodIndex The period index.
|
||||||
* @return The {@link TracksInfo} for the period. May be {@link TracksInfo#EMPTY} for single
|
* @return The {@link Tracks} for the period. May be {@link Tracks#EMPTY} for single stream
|
||||||
* stream content.
|
* content.
|
||||||
*/
|
*/
|
||||||
public TracksInfo getTracksInfo(int periodIndex) {
|
public Tracks getTracks(int periodIndex) {
|
||||||
assertPreparedWithMedia();
|
assertPreparedWithMedia();
|
||||||
return TrackSelectionUtil.buildTracksInfo(
|
return TrackSelectionUtil.buildTracks(
|
||||||
mappedTrackInfos[periodIndex], immutableTrackSelectionsByPeriodAndRenderer[periodIndex]);
|
mappedTrackInfos[periodIndex], immutableTrackSelectionsByPeriodAndRenderer[periodIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1955,12 +1955,11 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
if (override == null) {
|
if (override == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@Nullable
|
@Nullable TrackSelectionOverride existingOverride = overridesByType.get(override.getType());
|
||||||
TrackSelectionOverride existingOverride = overridesByType.get(override.getTrackType());
|
|
||||||
// Only replace an existing override if it's empty and the one being considered is not.
|
// Only replace an existing override if it's empty and the one being considered is not.
|
||||||
if (existingOverride == null
|
if (existingOverride == null
|
||||||
|| (existingOverride.trackIndices.isEmpty() && !override.trackIndices.isEmpty())) {
|
|| (existingOverride.trackIndices.isEmpty() && !override.trackIndices.isEmpty())) {
|
||||||
overridesByType.put(override.getTrackType(), override);
|
overridesByType.put(override.getType(), override);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ import com.google.android.exoplayer2.RendererCapabilities.AdaptiveSupport;
|
|||||||
import com.google.android.exoplayer2.RendererCapabilities.Capabilities;
|
import com.google.android.exoplayer2.RendererCapabilities.Capabilities;
|
||||||
import com.google.android.exoplayer2.RendererConfiguration;
|
import com.google.android.exoplayer2.RendererConfiguration;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
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.MediaSource.MediaPeriodId;
|
||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
@ -425,9 +425,9 @@ public abstract class MappingTrackSelector extends TrackSelector {
|
|||||||
periodId,
|
periodId,
|
||||||
timeline);
|
timeline);
|
||||||
|
|
||||||
TracksInfo tracksInfo = TrackSelectionUtil.buildTracksInfo(mappedTrackInfo, result.second);
|
Tracks tracks = TrackSelectionUtil.buildTracks(mappedTrackInfo, result.second);
|
||||||
|
|
||||||
return new TrackSelectorResult(result.first, result.second, tracksInfo, mappedTrackInfo);
|
return new TrackSelectorResult(result.first, result.second, tracks, mappedTrackInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,8 +19,7 @@ import android.os.SystemClock;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.RendererCapabilities;
|
import com.google.android.exoplayer2.RendererCapabilities;
|
||||||
import com.google.android.exoplayer2.TracksInfo;
|
import com.google.android.exoplayer2.Tracks;
|
||||||
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
|
|
||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
|
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.
|
* TrackSelection TrackSelections} for each renderer.
|
||||||
*
|
*
|
||||||
* @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
|
* @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
|
||||||
* @param selections The track selections, indexed by renderer. A null entry indicates that a
|
* @param selections The track selections, indexed by renderer. A null entry indicates that a
|
||||||
* renderer does not have any selected tracks.
|
* renderer does not have any selected tracks.
|
||||||
* @return The corresponding {@link TracksInfo}.
|
* @return The corresponding {@link Tracks}.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"}) // Initialization of array of Lists.
|
@SuppressWarnings({"unchecked", "rawtypes"}) // Initialization of array of Lists.
|
||||||
public static TracksInfo buildTracksInfo(
|
public static Tracks buildTracks(
|
||||||
MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
|
MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
|
||||||
@NullableType TrackSelection[] selections) {
|
@NullableType TrackSelection[] selections) {
|
||||||
List<? extends TrackSelection>[] listSelections = new List[selections.length];
|
List<? extends TrackSelection>[] listSelections = new List[selections.length];
|
||||||
@ -151,22 +150,22 @@ public final class TrackSelectionUtil {
|
|||||||
@Nullable TrackSelection selection = selections[i];
|
@Nullable TrackSelection selection = selections[i];
|
||||||
listSelections[i] = selection != null ? ImmutableList.of(selection) : ImmutableList.of();
|
listSelections[i] = selection != null ? ImmutableList.of(selection) : ImmutableList.of();
|
||||||
}
|
}
|
||||||
return buildTracksInfo(mappedTrackInfo, listSelections);
|
return buildTracks(mappedTrackInfo, listSelections);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link TracksInfo} built from {@link MappingTrackSelector.MappedTrackInfo} and {@link
|
* Returns {@link Tracks} built from {@link MappingTrackSelector.MappedTrackInfo} and {@link
|
||||||
* TrackSelection TrackSelections} for each renderer.
|
* TrackSelection TrackSelections} for each renderer.
|
||||||
*
|
*
|
||||||
* @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
|
* @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
|
||||||
* @param selections The track selections, indexed by renderer. Null entries are not permitted. An
|
* @param selections The track selections, indexed by renderer. Null entries are not permitted. An
|
||||||
* empty list indicates that a renderer does not have any selected tracks.
|
* empty list indicates that a renderer does not have any selected tracks.
|
||||||
* @return The corresponding {@link TracksInfo}.
|
* @return The corresponding {@link Tracks}.
|
||||||
*/
|
*/
|
||||||
public static TracksInfo buildTracksInfo(
|
public static Tracks buildTracks(
|
||||||
MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
|
MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
|
||||||
List<? extends TrackSelection>[] selections) {
|
List<? extends TrackSelection>[] selections) {
|
||||||
ImmutableList.Builder<TrackGroupInfo> trackGroupInfos = new ImmutableList.Builder<>();
|
ImmutableList.Builder<Tracks.Group> trackGroups = new ImmutableList.Builder<>();
|
||||||
for (int rendererIndex = 0;
|
for (int rendererIndex = 0;
|
||||||
rendererIndex < mappedTrackInfo.getRendererCount();
|
rendererIndex < mappedTrackInfo.getRendererCount();
|
||||||
rendererIndex++) {
|
rendererIndex++) {
|
||||||
@ -194,8 +193,7 @@ public final class TrackSelectionUtil {
|
|||||||
}
|
}
|
||||||
selected[trackIndex] = isTrackSelected;
|
selected[trackIndex] = isTrackSelected;
|
||||||
}
|
}
|
||||||
trackGroupInfos.add(
|
trackGroups.add(new Tracks.Group(trackGroup, adaptiveSupported, trackSupport, selected));
|
||||||
new TrackGroupInfo(trackGroup, adaptiveSupported, trackSupport, selected));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TrackGroupArray unmappedTrackGroups = mappedTrackInfo.getUnmappedTrackGroups();
|
TrackGroupArray unmappedTrackGroups = mappedTrackInfo.getUnmappedTrackGroups();
|
||||||
@ -204,9 +202,9 @@ public final class TrackSelectionUtil {
|
|||||||
@C.FormatSupport int[] trackSupport = new int[trackGroup.length];
|
@C.FormatSupport int[] trackSupport = new int[trackGroup.length];
|
||||||
Arrays.fill(trackSupport, C.FORMAT_UNSUPPORTED_TYPE);
|
Arrays.fill(trackSupport, C.FORMAT_UNSUPPORTED_TYPE);
|
||||||
boolean[] selected = new boolean[trackGroup.length];
|
boolean[] selected = new boolean[trackGroup.length];
|
||||||
trackGroupInfos.add(
|
trackGroups.add(
|
||||||
new TrackGroupInfo(trackGroup, /* adaptiveSupported= */ false, trackSupport, selected));
|
new Tracks.Group(trackGroup, /* adaptiveSupported= */ false, trackSupport, selected));
|
||||||
}
|
}
|
||||||
return new TracksInfo(trackGroupInfos.build());
|
return new Tracks(trackGroups.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ package com.google.android.exoplayer2.trackselection;
|
|||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.RendererConfiguration;
|
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 com.google.android.exoplayer2.util.Util;
|
||||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
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. */
|
/** A {@link ExoTrackSelection} array containing the track selection for each renderer. */
|
||||||
public final @NullableType ExoTrackSelection[] selections;
|
public final @NullableType ExoTrackSelection[] selections;
|
||||||
/** Describe the tracks and which one were selected. */
|
/** Describe the tracks and which one were selected. */
|
||||||
public final TracksInfo tracksInfo;
|
public final Tracks tracks;
|
||||||
/**
|
/**
|
||||||
* An opaque object that will be returned to {@link TrackSelector#onSelectionActivated(Object)}
|
* An opaque object that will be returned to {@link TrackSelector#onSelectionActivated(Object)}
|
||||||
* should the selections be activated.
|
* should the selections be activated.
|
||||||
@ -49,21 +49,21 @@ public final class TrackSelectorResult {
|
|||||||
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
|
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
|
||||||
* {@code null}.
|
* {@code null}.
|
||||||
* @deprecated Use {@link #TrackSelectorResult(RendererConfiguration[], ExoTrackSelection[],
|
* @deprecated Use {@link #TrackSelectorResult(RendererConfiguration[], ExoTrackSelection[],
|
||||||
* TracksInfo, Object)}.
|
* Tracks, Object)}.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public TrackSelectorResult(
|
public TrackSelectorResult(
|
||||||
@NullableType RendererConfiguration[] rendererConfigurations,
|
@NullableType RendererConfiguration[] rendererConfigurations,
|
||||||
@NullableType ExoTrackSelection[] selections,
|
@NullableType ExoTrackSelection[] selections,
|
||||||
@Nullable Object info) {
|
@Nullable Object info) {
|
||||||
this(rendererConfigurations, selections, TracksInfo.EMPTY, info);
|
this(rendererConfigurations, selections, Tracks.EMPTY, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param rendererConfigurations A {@link RendererConfiguration} for each renderer. A null entry
|
* @param rendererConfigurations A {@link RendererConfiguration} for each renderer. A null entry
|
||||||
* indicates the corresponding renderer should be disabled.
|
* indicates the corresponding renderer should be disabled.
|
||||||
* @param selections A {@link ExoTrackSelection} array containing the selection for each renderer.
|
* @param selections A {@link ExoTrackSelection} array containing the selection for each renderer.
|
||||||
* @param tracksInfo Description of the available tracks and which one were selected.
|
* @param tracks Description of the available tracks and which one were selected.
|
||||||
* @param info An opaque object that will be returned to {@link
|
* @param info An opaque object that will be returned to {@link
|
||||||
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
|
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
|
||||||
* {@code null}.
|
* {@code null}.
|
||||||
@ -71,11 +71,11 @@ public final class TrackSelectorResult {
|
|||||||
public TrackSelectorResult(
|
public TrackSelectorResult(
|
||||||
@NullableType RendererConfiguration[] rendererConfigurations,
|
@NullableType RendererConfiguration[] rendererConfigurations,
|
||||||
@NullableType ExoTrackSelection[] selections,
|
@NullableType ExoTrackSelection[] selections,
|
||||||
TracksInfo tracksInfo,
|
Tracks tracks,
|
||||||
@Nullable Object info) {
|
@Nullable Object info) {
|
||||||
this.rendererConfigurations = rendererConfigurations;
|
this.rendererConfigurations = rendererConfigurations;
|
||||||
this.selections = selections.clone();
|
this.selections = selections.clone();
|
||||||
this.tracksInfo = tracksInfo;
|
this.tracks = tracks;
|
||||||
this.info = info;
|
this.info = info;
|
||||||
length = rendererConfigurations.length;
|
length = rendererConfigurations.length;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ import com.google.android.exoplayer2.PlaybackParameters;
|
|||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
|
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
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.analytics.AnalyticsListener;
|
||||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||||
import com.google.android.exoplayer2.decoder.DecoderCounters;
|
import com.google.android.exoplayer2.decoder.DecoderCounters;
|
||||||
@ -258,23 +258,23 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(EventTime eventTime, TracksInfo tracksInfo) {
|
public void onTracksChanged(EventTime eventTime, Tracks tracks) {
|
||||||
logd("tracks [" + getEventTimeString(eventTime));
|
logd("tracks [" + getEventTimeString(eventTime));
|
||||||
// Log tracks associated to renderers.
|
// Log tracks associated to renderers.
|
||||||
ImmutableList<TracksInfo.TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
|
||||||
for (int groupIndex = 0; groupIndex < trackGroupInfos.size(); groupIndex++) {
|
for (int groupIndex = 0; groupIndex < trackGroups.size(); groupIndex++) {
|
||||||
TracksInfo.TrackGroupInfo trackGroupInfo = trackGroupInfos.get(groupIndex);
|
Tracks.Group trackGroup = trackGroups.get(groupIndex);
|
||||||
logd(" group [");
|
logd(" group [");
|
||||||
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) {
|
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
||||||
String status = getTrackStatusString(trackGroupInfo.isTrackSelected(trackIndex));
|
String status = getTrackStatusString(trackGroup.isTrackSelected(trackIndex));
|
||||||
String formatSupport = getFormatSupportString(trackGroupInfo.getTrackSupport(trackIndex));
|
String formatSupport = getFormatSupportString(trackGroup.getTrackSupport(trackIndex));
|
||||||
logd(
|
logd(
|
||||||
" "
|
" "
|
||||||
+ status
|
+ status
|
||||||
+ " Track:"
|
+ " Track:"
|
||||||
+ trackIndex
|
+ trackIndex
|
||||||
+ ", "
|
+ ", "
|
||||||
+ Format.toLogString(trackGroupInfo.getTrackFormat(trackIndex))
|
+ Format.toLogString(trackGroup.getTrackFormat(trackIndex))
|
||||||
+ ", supported="
|
+ ", supported="
|
||||||
+ formatSupport);
|
+ formatSupport);
|
||||||
}
|
}
|
||||||
@ -283,8 +283,8 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
// TODO: Replace this with an override of onMediaMetadataChanged.
|
// TODO: Replace this with an override of onMediaMetadataChanged.
|
||||||
// Log metadata for at most one of the selected tracks.
|
// Log metadata for at most one of the selected tracks.
|
||||||
boolean loggedMetadata = false;
|
boolean loggedMetadata = false;
|
||||||
for (int groupIndex = 0; !loggedMetadata && groupIndex < trackGroupInfos.size(); groupIndex++) {
|
for (int groupIndex = 0; !loggedMetadata && groupIndex < trackGroups.size(); groupIndex++) {
|
||||||
TracksInfo.TrackGroupInfo trackGroup = trackGroupInfos.get(groupIndex);
|
Tracks.Group trackGroup = trackGroups.get(groupIndex);
|
||||||
for (int trackIndex = 0; !loggedMetadata && trackIndex < trackGroup.length; trackIndex++) {
|
for (int trackIndex = 0; !loggedMetadata && trackIndex < trackGroup.length; trackIndex++) {
|
||||||
if (trackGroup.isTrackSelected(trackIndex)) {
|
if (trackGroup.isTrackSelected(trackIndex)) {
|
||||||
@Nullable Metadata metadata = trackGroup.getTrackFormat(trackIndex).metadata;
|
@Nullable Metadata metadata = trackGroup.getTrackFormat(trackIndex).metadata;
|
||||||
|
@ -96,7 +96,6 @@ import com.google.android.exoplayer2.Player.DiscontinuityReason;
|
|||||||
import com.google.android.exoplayer2.Player.Listener;
|
import com.google.android.exoplayer2.Player.Listener;
|
||||||
import com.google.android.exoplayer2.Player.PositionInfo;
|
import com.google.android.exoplayer2.Player.PositionInfo;
|
||||||
import com.google.android.exoplayer2.Timeline.Window;
|
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.analytics.AnalyticsListener;
|
||||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||||
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
|
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));
|
argThat(noUid(timeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockListener)
|
.verify(mockListener)
|
||||||
.onTracksInfoChanged(
|
.onTracksChanged(
|
||||||
eq(
|
eq(
|
||||||
new TracksInfo(
|
new Tracks(
|
||||||
ImmutableList.of(
|
ImmutableList.of(
|
||||||
new TrackGroupInfo(
|
new Tracks.Group(
|
||||||
new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT),
|
new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT),
|
||||||
/* adaptiveSupported= */ false,
|
/* adaptiveSupported= */ false,
|
||||||
new int[] {C.FORMAT_HANDLED},
|
new int[] {C.FORMAT_HANDLED},
|
||||||
/* tracksSelected= */ new boolean[] {true})))));
|
/* trackSelected= */ new boolean[] {true})))));
|
||||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
|
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
|
||||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
|
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
|
||||||
assertThat(renderer.getFormatsRead()).containsExactly(ExoPlayerTestRunner.VIDEO_FORMAT);
|
assertThat(renderer.getFormatsRead()).containsExactly(ExoPlayerTestRunner.VIDEO_FORMAT);
|
||||||
@ -646,15 +645,15 @@ public final class ExoPlayerTest {
|
|||||||
argThat(noUid(thirdTimeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
|
argThat(noUid(thirdTimeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockPlayerListener)
|
.verify(mockPlayerListener)
|
||||||
.onTracksInfoChanged(
|
.onTracksChanged(
|
||||||
eq(
|
eq(
|
||||||
new TracksInfo(
|
new Tracks(
|
||||||
ImmutableList.of(
|
ImmutableList.of(
|
||||||
new TrackGroupInfo(
|
new Tracks.Group(
|
||||||
new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT),
|
new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT),
|
||||||
/* adaptiveSupported= */ false,
|
/* adaptiveSupported= */ false,
|
||||||
new int[] {C.FORMAT_HANDLED},
|
new int[] {C.FORMAT_HANDLED},
|
||||||
/* tracksSelected= */ new boolean[] {true})))));
|
/* trackSelected= */ new boolean[] {true})))));
|
||||||
assertThat(renderer.isEnded).isTrue();
|
assertThat(renderer.isEnded).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3416,7 +3415,7 @@ public final class ExoPlayerTest {
|
|||||||
.waitForPendingPlayerCommands()
|
.waitForPendingPlayerCommands()
|
||||||
.play()
|
.play()
|
||||||
.build();
|
.build();
|
||||||
List<TracksInfo> tracksInfoList = new ArrayList<>();
|
List<Tracks> tracksList = new ArrayList<>();
|
||||||
new ExoPlayerTestRunner.Builder(context)
|
new ExoPlayerTestRunner.Builder(context)
|
||||||
.setMediaSources(mediaSource)
|
.setMediaSources(mediaSource)
|
||||||
.setSupportedFormats(ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT)
|
.setSupportedFormats(ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT)
|
||||||
@ -3424,21 +3423,21 @@ public final class ExoPlayerTest {
|
|||||||
.setPlayerListener(
|
.setPlayerListener(
|
||||||
new Player.Listener() {
|
new Player.Listener() {
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
tracksInfoList.add(tracksInfo);
|
tracksList.add(tracks);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
.start()
|
.start()
|
||||||
.blockUntilEnded(TIMEOUT_MS);
|
.blockUntilEnded(TIMEOUT_MS);
|
||||||
assertThat(tracksInfoList).hasSize(3);
|
assertThat(tracksList).hasSize(3);
|
||||||
// First track groups of the 1st period are reported.
|
// First track groups of the 1st period are reported.
|
||||||
// Then the seek to an unprepared period will result in empty track groups being returned.
|
// Then the seek to an unprepared period will result in empty track groups being returned.
|
||||||
// Then the track groups of the 2nd period are reported.
|
// Then the track groups of the 2nd period are reported.
|
||||||
assertThat(tracksInfoList.get(0).getTrackGroupInfos().get(0).getTrackFormat(0))
|
assertThat(tracksList.get(0).getGroups().get(0).getTrackFormat(0))
|
||||||
.isEqualTo(ExoPlayerTestRunner.VIDEO_FORMAT);
|
.isEqualTo(ExoPlayerTestRunner.VIDEO_FORMAT);
|
||||||
assertThat(tracksInfoList.get(1)).isEqualTo(TracksInfo.EMPTY);
|
assertThat(tracksList.get(1)).isEqualTo(Tracks.EMPTY);
|
||||||
assertThat(tracksInfoList.get(2).getTrackGroupInfos().get(0).getTrackFormat(0))
|
assertThat(tracksList.get(2).getGroups().get(0).getTrackFormat(0))
|
||||||
.isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
|
.isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7983,7 +7982,7 @@ public final class ExoPlayerTest {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
AtomicReference<Timeline> timelineAfterError = new AtomicReference<>();
|
AtomicReference<Timeline> timelineAfterError = new AtomicReference<>();
|
||||||
AtomicReference<TracksInfo> trackInfosAfterError = new AtomicReference<>();
|
AtomicReference<Tracks> trackInfosAfterError = new AtomicReference<>();
|
||||||
AtomicInteger mediaItemIndexAfterError = new AtomicInteger();
|
AtomicInteger mediaItemIndexAfterError = new AtomicInteger();
|
||||||
ActionSchedule actionSchedule =
|
ActionSchedule actionSchedule =
|
||||||
new ActionSchedule.Builder(TAG)
|
new ActionSchedule.Builder(TAG)
|
||||||
@ -7996,7 +7995,7 @@ public final class ExoPlayerTest {
|
|||||||
@Override
|
@Override
|
||||||
public void onPlayerError(EventTime eventTime, PlaybackException error) {
|
public void onPlayerError(EventTime eventTime, PlaybackException error) {
|
||||||
timelineAfterError.set(player.getCurrentTimeline());
|
timelineAfterError.set(player.getCurrentTimeline());
|
||||||
trackInfosAfterError.set(player.getCurrentTracksInfo());
|
trackInfosAfterError.set(player.getCurrentTracks());
|
||||||
mediaItemIndexAfterError.set(player.getCurrentMediaItemIndex());
|
mediaItemIndexAfterError.set(player.getCurrentMediaItemIndex());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -8025,8 +8024,8 @@ public final class ExoPlayerTest {
|
|||||||
|
|
||||||
assertThat(timelineAfterError.get().getWindowCount()).isEqualTo(1);
|
assertThat(timelineAfterError.get().getWindowCount()).isEqualTo(1);
|
||||||
assertThat(mediaItemIndexAfterError.get()).isEqualTo(0);
|
assertThat(mediaItemIndexAfterError.get()).isEqualTo(0);
|
||||||
assertThat(trackInfosAfterError.get().getTrackGroupInfos()).hasSize(1);
|
assertThat(trackInfosAfterError.get().getGroups()).hasSize(1);
|
||||||
assertThat(trackInfosAfterError.get().getTrackGroupInfos().get(0).getTrackFormat(0))
|
assertThat(trackInfosAfterError.get().getGroups().get(0).getTrackFormat(0))
|
||||||
.isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
|
.isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
|
||||||
assertThat(trackInfosAfterError.get().isTypeSelected(C.TRACK_TYPE_VIDEO)).isFalse();
|
assertThat(trackInfosAfterError.get().isTypeSelected(C.TRACK_TYPE_VIDEO)).isFalse();
|
||||||
assertThat(trackInfosAfterError.get().isTypeSelected(C.TRACK_TYPE_AUDIO)).isTrue();
|
assertThat(trackInfosAfterError.get().isTypeSelected(C.TRACK_TYPE_AUDIO)).isTrue();
|
||||||
@ -10413,7 +10412,7 @@ public final class ExoPlayerTest {
|
|||||||
verify(listener, atLeastOnce()).onShuffleModeEnabledChanged(anyBoolean());
|
verify(listener, atLeastOnce()).onShuffleModeEnabledChanged(anyBoolean());
|
||||||
verify(listener, atLeastOnce()).onPlaybackStateChanged(anyInt());
|
verify(listener, atLeastOnce()).onPlaybackStateChanged(anyInt());
|
||||||
verify(listener, atLeastOnce()).onIsLoadingChanged(anyBoolean());
|
verify(listener, atLeastOnce()).onIsLoadingChanged(anyBoolean());
|
||||||
verify(listener, atLeastOnce()).onTracksInfoChanged(any());
|
verify(listener, atLeastOnce()).onTracksChanged(any());
|
||||||
verify(listener, atLeastOnce()).onMediaMetadataChanged(any());
|
verify(listener, atLeastOnce()).onMediaMetadataChanged(any());
|
||||||
verify(listener, atLeastOnce()).onPlayWhenReadyChanged(anyBoolean(), anyInt());
|
verify(listener, atLeastOnce()).onPlayWhenReadyChanged(anyBoolean(), anyInt());
|
||||||
verify(listener, atLeastOnce()).onIsPlayingChanged(anyBoolean());
|
verify(listener, atLeastOnce()).onIsPlayingChanged(anyBoolean());
|
||||||
|
@ -1135,7 +1135,7 @@ public final class MediaPeriodQueueTest {
|
|||||||
new TrackSelectorResult(
|
new TrackSelectorResult(
|
||||||
new RendererConfiguration[0],
|
new RendererConfiguration[0],
|
||||||
new ExoTrackSelection[0],
|
new ExoTrackSelection[0],
|
||||||
TracksInfo.EMPTY,
|
Tracks.EMPTY,
|
||||||
/* info= */ null));
|
/* info= */ null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ import com.google.android.exoplayer2.Renderer;
|
|||||||
import com.google.android.exoplayer2.RenderersFactory;
|
import com.google.android.exoplayer2.RenderersFactory;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.Timeline.Window;
|
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.decoder.DecoderCounters;
|
||||||
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
|
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
|
||||||
import com.google.android.exoplayer2.drm.DrmInitData;
|
import com.google.android.exoplayer2.drm.DrmInitData;
|
||||||
@ -1729,7 +1729,7 @@ public final class DefaultAnalyticsCollectorTest {
|
|||||||
ArgumentCaptor<AnalyticsListener.EventTime> individualTracksChangedEventTimes =
|
ArgumentCaptor<AnalyticsListener.EventTime> individualTracksChangedEventTimes =
|
||||||
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
verify(listener, atLeastOnce())
|
verify(listener, atLeastOnce())
|
||||||
.onTracksInfoChanged(individualTracksChangedEventTimes.capture(), any());
|
.onTracksChanged(individualTracksChangedEventTimes.capture(), any());
|
||||||
ArgumentCaptor<AnalyticsListener.EventTime> individualPlayWhenReadyChangedEventTimes =
|
ArgumentCaptor<AnalyticsListener.EventTime> individualPlayWhenReadyChangedEventTimes =
|
||||||
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
verify(listener, atLeastOnce())
|
verify(listener, atLeastOnce())
|
||||||
@ -2243,7 +2243,7 @@ public final class DefaultAnalyticsCollectorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(EventTime eventTime, TracksInfo tracksInfo) {
|
public void onTracksChanged(EventTime eventTime, Tracks tracks) {
|
||||||
reportedEvents.add(new ReportedEvent(EVENT_TRACKS_CHANGED, eventTime));
|
reportedEvents.add(new ReportedEvent(EVENT_TRACKS_CHANGED, eventTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ import com.google.android.exoplayer2.RendererCapabilities;
|
|||||||
import com.google.android.exoplayer2.RendererCapabilities.Capabilities;
|
import com.google.android.exoplayer2.RendererCapabilities.Capabilities;
|
||||||
import com.google.android.exoplayer2.RendererConfiguration;
|
import com.google.android.exoplayer2.RendererConfiguration;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
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.MediaSource.MediaPeriodId;
|
||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
@ -2223,10 +2223,10 @@ public final class DefaultTrackSelectorTest {
|
|||||||
public void selectTracks_multipleRenderer_allSelected() throws Exception {
|
public void selectTracks_multipleRenderer_allSelected() throws Exception {
|
||||||
RendererCapabilities[] rendererCapabilities =
|
RendererCapabilities[] rendererCapabilities =
|
||||||
new RendererCapabilities[] {VIDEO_CAPABILITIES, AUDIO_CAPABILITIES, AUDIO_CAPABILITIES};
|
new RendererCapabilities[] {VIDEO_CAPABILITIES, AUDIO_CAPABILITIES, AUDIO_CAPABILITIES};
|
||||||
TrackGroupArray trackGroups = new TrackGroupArray(AUDIO_TRACK_GROUP);
|
TrackGroupArray trackGroupArray = new TrackGroupArray(AUDIO_TRACK_GROUP);
|
||||||
|
|
||||||
TrackSelectorResult result =
|
TrackSelectorResult result =
|
||||||
trackSelector.selectTracks(rendererCapabilities, trackGroups, periodId, TIMELINE);
|
trackSelector.selectTracks(rendererCapabilities, trackGroupArray, periodId, TIMELINE);
|
||||||
|
|
||||||
assertThat(result.length).isEqualTo(3);
|
assertThat(result.length).isEqualTo(3);
|
||||||
assertThat(result.rendererConfigurations)
|
assertThat(result.rendererConfigurations)
|
||||||
@ -2234,14 +2234,14 @@ public final class DefaultTrackSelectorTest {
|
|||||||
.containsExactly(null, DEFAULT, null)
|
.containsExactly(null, DEFAULT, null)
|
||||||
.inOrder();
|
.inOrder();
|
||||||
assertThat(result.selections[0]).isNull();
|
assertThat(result.selections[0]).isNull();
|
||||||
assertFixedSelection(result.selections[1], trackGroups, trackGroups.get(0).getFormat(0));
|
assertFixedSelection(
|
||||||
|
result.selections[1], trackGroupArray, trackGroupArray.get(0).getFormat(0));
|
||||||
assertThat(result.selections[2]).isNull();
|
assertThat(result.selections[2]).isNull();
|
||||||
ImmutableList<TracksInfo.TrackGroupInfo> trackGroupInfos =
|
ImmutableList<Tracks.Group> trackGroups = result.tracks.getGroups();
|
||||||
result.tracksInfo.getTrackGroupInfos();
|
assertThat(trackGroups).hasSize(1);
|
||||||
assertThat(trackGroupInfos).hasSize(1);
|
assertThat(trackGroups.get(0).getTrackGroup()).isEqualTo(AUDIO_TRACK_GROUP);
|
||||||
assertThat(trackGroupInfos.get(0).getTrackGroup()).isEqualTo(AUDIO_TRACK_GROUP);
|
assertThat(trackGroups.get(0).isTrackSelected(0)).isTrue();
|
||||||
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isTrue();
|
assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
||||||
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Tests {@link SelectionOverride}'s {@link Bundleable} implementation. */
|
/** Tests {@link SelectionOverride}'s {@link Bundleable} implementation. */
|
||||||
|
@ -32,8 +32,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.TracksInfo;
|
import com.google.android.exoplayer2.Tracks;
|
||||||
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
|
|
||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
@ -73,32 +72,32 @@ public class TrackSelectionUtilTest {
|
|||||||
new FixedTrackSelection(mappedTrackInfo.getTrackGroups(1).get(0), 1)
|
new FixedTrackSelection(mappedTrackInfo.getTrackGroups(1).get(0), 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
TracksInfo tracksInfo = TrackSelectionUtil.buildTracksInfo(mappedTrackInfo, selections);
|
Tracks tracks = TrackSelectionUtil.buildTracks(mappedTrackInfo, selections);
|
||||||
|
|
||||||
ImmutableList<TracksInfo.TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
|
||||||
assertThat(trackGroupInfos).hasSize(4);
|
assertThat(trackGroups).hasSize(4);
|
||||||
assertThat(trackGroupInfos.get(0).getTrackGroup())
|
assertThat(trackGroups.get(0).getTrackGroup())
|
||||||
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0));
|
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0));
|
||||||
assertThat(trackGroupInfos.get(1).getTrackGroup())
|
assertThat(trackGroups.get(1).getTrackGroup())
|
||||||
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1));
|
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1));
|
||||||
assertThat(trackGroupInfos.get(2).getTrackGroup())
|
assertThat(trackGroups.get(2).getTrackGroup())
|
||||||
.isEqualTo(mappedTrackInfo.getTrackGroups(1).get(0));
|
.isEqualTo(mappedTrackInfo.getTrackGroups(1).get(0));
|
||||||
assertThat(trackGroupInfos.get(3).getTrackGroup())
|
assertThat(trackGroups.get(3).getTrackGroup())
|
||||||
.isEqualTo(mappedTrackInfo.getUnmappedTrackGroups().get(0));
|
.isEqualTo(mappedTrackInfo.getUnmappedTrackGroups().get(0));
|
||||||
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
||||||
assertThat(trackGroupInfos.get(1).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_SUBTYPE);
|
assertThat(trackGroups.get(1).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_SUBTYPE);
|
||||||
assertThat(trackGroupInfos.get(2).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_DRM);
|
assertThat(trackGroups.get(2).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_DRM);
|
||||||
assertThat(trackGroupInfos.get(2).getTrackSupport(1)).isEqualTo(FORMAT_EXCEEDS_CAPABILITIES);
|
assertThat(trackGroups.get(2).getTrackSupport(1)).isEqualTo(FORMAT_EXCEEDS_CAPABILITIES);
|
||||||
assertThat(trackGroupInfos.get(3).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_TYPE);
|
assertThat(trackGroups.get(3).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_TYPE);
|
||||||
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isFalse();
|
assertThat(trackGroups.get(0).isTrackSelected(0)).isFalse();
|
||||||
assertThat(trackGroupInfos.get(1).isTrackSelected(0)).isTrue();
|
assertThat(trackGroups.get(1).isTrackSelected(0)).isTrue();
|
||||||
assertThat(trackGroupInfos.get(2).isTrackSelected(0)).isFalse();
|
assertThat(trackGroups.get(2).isTrackSelected(0)).isFalse();
|
||||||
assertThat(trackGroupInfos.get(2).isTrackSelected(1)).isTrue();
|
assertThat(trackGroups.get(2).isTrackSelected(1)).isTrue();
|
||||||
assertThat(trackGroupInfos.get(3).isTrackSelected(0)).isFalse();
|
assertThat(trackGroups.get(3).isTrackSelected(0)).isFalse();
|
||||||
assertThat(trackGroupInfos.get(0).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO);
|
assertThat(trackGroups.get(0).getType()).isEqualTo(TRACK_TYPE_AUDIO);
|
||||||
assertThat(trackGroupInfos.get(1).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO);
|
assertThat(trackGroups.get(1).getType()).isEqualTo(TRACK_TYPE_AUDIO);
|
||||||
assertThat(trackGroupInfos.get(2).getTrackType()).isEqualTo(TRACK_TYPE_VIDEO);
|
assertThat(trackGroups.get(2).getType()).isEqualTo(TRACK_TYPE_VIDEO);
|
||||||
assertThat(trackGroupInfos.get(3).getTrackType()).isEqualTo(TRACK_TYPE_UNKNOWN);
|
assertThat(trackGroups.get(3).getType()).isEqualTo(TRACK_TYPE_UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -132,21 +131,21 @@ public class TrackSelectionUtilTest {
|
|||||||
ImmutableList.of()
|
ImmutableList.of()
|
||||||
};
|
};
|
||||||
|
|
||||||
TracksInfo tracksInfo = TrackSelectionUtil.buildTracksInfo(mappedTrackInfo, selections);
|
Tracks tracks = TrackSelectionUtil.buildTracks(mappedTrackInfo, selections);
|
||||||
|
|
||||||
ImmutableList<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
|
||||||
assertThat(trackGroupInfos).hasSize(2);
|
assertThat(trackGroups).hasSize(2);
|
||||||
assertThat(trackGroupInfos.get(0).getTrackGroup())
|
assertThat(trackGroups.get(0).getTrackGroup())
|
||||||
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0));
|
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0));
|
||||||
assertThat(trackGroupInfos.get(1).getTrackGroup())
|
assertThat(trackGroups.get(1).getTrackGroup())
|
||||||
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1));
|
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1));
|
||||||
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
||||||
assertThat(trackGroupInfos.get(1).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
assertThat(trackGroups.get(1).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
||||||
assertThat(trackGroupInfos.get(1).getTrackSupport(1)).isEqualTo(FORMAT_HANDLED);
|
assertThat(trackGroups.get(1).getTrackSupport(1)).isEqualTo(FORMAT_HANDLED);
|
||||||
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isTrue();
|
assertThat(trackGroups.get(0).isTrackSelected(0)).isTrue();
|
||||||
assertThat(trackGroupInfos.get(1).isTrackSelected(0)).isFalse();
|
assertThat(trackGroups.get(1).isTrackSelected(0)).isFalse();
|
||||||
assertThat(trackGroupInfos.get(1).isTrackSelected(1)).isTrue();
|
assertThat(trackGroups.get(1).isTrackSelected(1)).isTrue();
|
||||||
assertThat(trackGroupInfos.get(0).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO);
|
assertThat(trackGroups.get(0).getType()).isEqualTo(TRACK_TYPE_AUDIO);
|
||||||
assertThat(trackGroupInfos.get(1).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO);
|
assertThat(trackGroups.get(1).getType()).isEqualTo(TRACK_TYPE_AUDIO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ import com.google.android.exoplayer2.Player;
|
|||||||
import com.google.android.exoplayer2.Renderer;
|
import com.google.android.exoplayer2.Renderer;
|
||||||
import com.google.android.exoplayer2.RenderersFactory;
|
import com.google.android.exoplayer2.RenderersFactory;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
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.audio.AudioRendererEventListener;
|
||||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
||||||
import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor;
|
import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor;
|
||||||
@ -947,7 +947,7 @@ public final class Transformer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
if (muxerWrapper.getTrackCount() == 0) {
|
if (muxerWrapper.getTrackCount() == 0) {
|
||||||
handleTransformationEnded(
|
handleTransformationEnded(
|
||||||
TransformationException.createForUnexpected(
|
TransformationException.createForUnexpected(
|
||||||
|
@ -53,7 +53,7 @@ import com.google.android.exoplayer2.Player;
|
|||||||
import com.google.android.exoplayer2.Player.DiscontinuityReason;
|
import com.google.android.exoplayer2.Player.DiscontinuityReason;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.Timeline.Period;
|
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.text.Cue;
|
||||||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
|
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
@ -1230,7 +1230,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
@Nullable Player player = this.player;
|
@Nullable Player player = this.player;
|
||||||
if (player == null
|
if (player == null
|
||||||
|| !player.isCommandAvailable(Player.COMMAND_GET_TRACK_INFOS)
|
|| !player.isCommandAvailable(Player.COMMAND_GET_TRACK_INFOS)
|
||||||
|| player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) {
|
|| player.getCurrentTracks().isEmpty()) {
|
||||||
if (!keepContentOnPlayerReset) {
|
if (!keepContentOnPlayerReset) {
|
||||||
hideArtwork();
|
hideArtwork();
|
||||||
closeShutter();
|
closeShutter();
|
||||||
@ -1242,7 +1242,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
// Hide any video from the previous player.
|
// Hide any video from the previous player.
|
||||||
closeShutter();
|
closeShutter();
|
||||||
}
|
}
|
||||||
if (player.getCurrentTracksInfo().isTypeSelected(C.TRACK_TYPE_VIDEO)) {
|
if (player.getCurrentTracks().isTypeSelected(C.TRACK_TYPE_VIDEO)) {
|
||||||
// Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened
|
// Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened
|
||||||
// in onRenderedFirstFrame().
|
// in onRenderedFirstFrame().
|
||||||
hideArtwork();
|
hideArtwork();
|
||||||
@ -1474,7 +1474,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
// Suppress the update if transitioning to an unprepared period within the same window. This
|
// Suppress the update if transitioning to an unprepared period within the same window. This
|
||||||
// is necessary to avoid closing the shutter when such a transition occurs. See:
|
// is necessary to avoid closing the shutter when such a transition occurs. See:
|
||||||
// https://github.com/google/ExoPlayer/issues/5507.
|
// https://github.com/google/ExoPlayer/issues/5507.
|
||||||
@ -1482,7 +1482,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
Timeline timeline = player.getCurrentTimeline();
|
Timeline timeline = player.getCurrentTimeline();
|
||||||
if (timeline.isEmpty()) {
|
if (timeline.isEmpty()) {
|
||||||
lastPeriodUidWithTracks = null;
|
lastPeriodUidWithTracks = null;
|
||||||
} else if (!player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) {
|
} else if (!player.getCurrentTracks().isEmpty()) {
|
||||||
lastPeriodUidWithTracks =
|
lastPeriodUidWithTracks =
|
||||||
timeline.getPeriod(player.getCurrentPeriodIndex(), period, /* setIds= */ true).uid;
|
timeline.getPeriod(player.getCurrentPeriodIndex(), period, /* setIds= */ true).uid;
|
||||||
} else if (lastPeriodUidWithTracks != null) {
|
} else if (lastPeriodUidWithTracks != null) {
|
||||||
|
@ -65,8 +65,7 @@ import com.google.android.exoplayer2.Player;
|
|||||||
import com.google.android.exoplayer2.Player.Events;
|
import com.google.android.exoplayer2.Player.Events;
|
||||||
import com.google.android.exoplayer2.Player.State;
|
import com.google.android.exoplayer2.Player.State;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.TracksInfo;
|
import com.google.android.exoplayer2.Tracks;
|
||||||
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
|
|
||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
|
||||||
@ -1107,39 +1106,37 @@ public class StyledPlayerControlView extends FrameLayout {
|
|||||||
|| !player.isCommandAvailable(Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
|
|| !player.isCommandAvailable(Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TracksInfo tracksInfo = player.getCurrentTracksInfo();
|
Tracks tracks = player.getCurrentTracks();
|
||||||
audioTrackSelectionAdapter.init(
|
audioTrackSelectionAdapter.init(gatherSupportedTrackInfosOfType(tracks, C.TRACK_TYPE_AUDIO));
|
||||||
gatherSupportedTrackInfosOfType(tracksInfo, C.TRACK_TYPE_AUDIO));
|
|
||||||
if (controlViewLayoutManager.getShowButton(subtitleButton)) {
|
if (controlViewLayoutManager.getShowButton(subtitleButton)) {
|
||||||
textTrackSelectionAdapter.init(
|
textTrackSelectionAdapter.init(gatherSupportedTrackInfosOfType(tracks, C.TRACK_TYPE_TEXT));
|
||||||
gatherSupportedTrackInfosOfType(tracksInfo, C.TRACK_TYPE_TEXT));
|
|
||||||
} else {
|
} else {
|
||||||
textTrackSelectionAdapter.init(ImmutableList.of());
|
textTrackSelectionAdapter.init(ImmutableList.of());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImmutableList<TrackInformation> gatherSupportedTrackInfosOfType(
|
private ImmutableList<TrackInformation> gatherSupportedTrackInfosOfType(
|
||||||
TracksInfo tracksInfo, @C.TrackType int trackType) {
|
Tracks tracks, @C.TrackType int trackType) {
|
||||||
ImmutableList.Builder<TrackInformation> tracks = new ImmutableList.Builder<>();
|
ImmutableList.Builder<TrackInformation> trackInfos = new ImmutableList.Builder<>();
|
||||||
List<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
List<Tracks.Group> trackGroups = tracks.getGroups();
|
||||||
for (int trackGroupIndex = 0; trackGroupIndex < trackGroupInfos.size(); trackGroupIndex++) {
|
for (int trackGroupIndex = 0; trackGroupIndex < trackGroups.size(); trackGroupIndex++) {
|
||||||
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(trackGroupIndex);
|
Tracks.Group trackGroup = trackGroups.get(trackGroupIndex);
|
||||||
if (trackGroupInfo.getTrackType() != trackType) {
|
if (trackGroup.getType() != trackType) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) {
|
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
||||||
if (!trackGroupInfo.isTrackSupported(trackIndex)) {
|
if (!trackGroup.isTrackSupported(trackIndex)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Format trackFormat = trackGroupInfo.getTrackFormat(trackIndex);
|
Format trackFormat = trackGroup.getTrackFormat(trackIndex);
|
||||||
if ((trackFormat.selectionFlags & C.SELECTION_FLAG_FORCED) != 0) {
|
if ((trackFormat.selectionFlags & C.SELECTION_FLAG_FORCED) != 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String trackName = trackNameProvider.getTrackName(trackFormat);
|
String trackName = trackNameProvider.getTrackName(trackFormat);
|
||||||
tracks.add(new TrackInformation(tracksInfo, trackGroupIndex, trackIndex, trackName));
|
trackInfos.add(new TrackInformation(tracks, trackGroupIndex, trackIndex, trackName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tracks.build();
|
return trackInfos.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTimeline() {
|
private void updateTimeline() {
|
||||||
@ -1818,19 +1815,18 @@ public class StyledPlayerControlView extends FrameLayout {
|
|||||||
|
|
||||||
private static final class TrackInformation {
|
private static final class TrackInformation {
|
||||||
|
|
||||||
public final TrackGroupInfo trackGroupInfo;
|
public final Tracks.Group trackGroup;
|
||||||
public final int trackIndex;
|
public final int trackIndex;
|
||||||
public final String trackName;
|
public final String trackName;
|
||||||
|
|
||||||
public TrackInformation(
|
public TrackInformation(Tracks tracks, int trackGroupIndex, int trackIndex, String trackName) {
|
||||||
TracksInfo tracksInfo, int trackGroupIndex, int trackIndex, String trackName) {
|
this.trackGroup = tracks.getGroups().get(trackGroupIndex);
|
||||||
this.trackGroupInfo = tracksInfo.getTrackGroupInfos().get(trackGroupIndex);
|
|
||||||
this.trackIndex = trackIndex;
|
this.trackIndex = trackIndex;
|
||||||
this.trackName = trackName;
|
this.trackName = trackName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSelected() {
|
public boolean isSelected() {
|
||||||
return trackGroupInfo.isTrackSelected(trackIndex);
|
return trackGroup.isTrackSelected(trackIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1930,7 +1926,7 @@ public class StyledPlayerControlView extends FrameLayout {
|
|||||||
|
|
||||||
private boolean hasSelectionOverride(TrackSelectionParameters trackSelectionParameters) {
|
private boolean hasSelectionOverride(TrackSelectionParameters trackSelectionParameters) {
|
||||||
for (int i = 0; i < tracks.size(); i++) {
|
for (int i = 0; i < tracks.size(); i++) {
|
||||||
TrackGroup trackGroup = tracks.get(i).trackGroupInfo.getTrackGroup();
|
TrackGroup trackGroup = tracks.get(i).trackGroup.getTrackGroup();
|
||||||
if (trackSelectionParameters.overrides.containsKey(trackGroup)) {
|
if (trackSelectionParameters.overrides.containsKey(trackGroup)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2004,7 +2000,7 @@ public class StyledPlayerControlView extends FrameLayout {
|
|||||||
onBindViewHolderAtZeroPosition(holder);
|
onBindViewHolderAtZeroPosition(holder);
|
||||||
} else {
|
} else {
|
||||||
TrackInformation track = tracks.get(position - 1);
|
TrackInformation track = tracks.get(position - 1);
|
||||||
TrackGroup trackGroup = track.trackGroupInfo.getTrackGroup();
|
TrackGroup trackGroup = track.trackGroup.getTrackGroup();
|
||||||
TrackSelectionParameters params = player.getTrackSelectionParameters();
|
TrackSelectionParameters params = player.getTrackSelectionParameters();
|
||||||
boolean explicitlySelected = params.overrides.get(trackGroup) != null && track.isSelected();
|
boolean explicitlySelected = params.overrides.get(trackGroup) != null && track.isSelected();
|
||||||
holder.textView.setText(track.trackName);
|
holder.textView.setText(track.trackName);
|
||||||
@ -2019,8 +2015,7 @@ public class StyledPlayerControlView extends FrameLayout {
|
|||||||
.setOverrideForType(
|
.setOverrideForType(
|
||||||
new TrackSelectionOverride(
|
new TrackSelectionOverride(
|
||||||
trackGroup, ImmutableList.of(track.trackIndex)))
|
trackGroup, ImmutableList.of(track.trackIndex)))
|
||||||
.setTrackTypeDisabled(
|
.setTrackTypeDisabled(track.trackGroup.getType(), /* disabled= */ false)
|
||||||
track.trackGroupInfo.getTrackType(), /* disabled= */ false)
|
|
||||||
.build());
|
.build());
|
||||||
onTrackSelection(track.trackName);
|
onTrackSelection(track.trackName);
|
||||||
settingsWindow.dismiss();
|
settingsWindow.dismiss();
|
||||||
|
@ -55,7 +55,7 @@ import com.google.android.exoplayer2.Player;
|
|||||||
import com.google.android.exoplayer2.Player.DiscontinuityReason;
|
import com.google.android.exoplayer2.Player.DiscontinuityReason;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.Timeline.Period;
|
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.text.Cue;
|
||||||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
|
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
@ -1177,7 +1177,7 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
|
|
||||||
private void updateForCurrentTrackSelections(boolean isNewPlayer) {
|
private void updateForCurrentTrackSelections(boolean isNewPlayer) {
|
||||||
@Nullable Player player = this.player;
|
@Nullable Player player = this.player;
|
||||||
if (player == null || player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) {
|
if (player == null || player.getCurrentTracks().isEmpty()) {
|
||||||
if (!keepContentOnPlayerReset) {
|
if (!keepContentOnPlayerReset) {
|
||||||
hideArtwork();
|
hideArtwork();
|
||||||
closeShutter();
|
closeShutter();
|
||||||
@ -1190,7 +1190,7 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
closeShutter();
|
closeShutter();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.getCurrentTracksInfo().isTypeSelected(C.TRACK_TYPE_VIDEO)) {
|
if (player.getCurrentTracks().isTypeSelected(C.TRACK_TYPE_VIDEO)) {
|
||||||
// Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened
|
// Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened
|
||||||
// in onRenderedFirstFrame().
|
// in onRenderedFirstFrame().
|
||||||
hideArtwork();
|
hideArtwork();
|
||||||
@ -1422,7 +1422,7 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
// Suppress the update if transitioning to an unprepared period within the same window. This
|
// Suppress the update if transitioning to an unprepared period within the same window. This
|
||||||
// is necessary to avoid closing the shutter when such a transition occurs. See:
|
// is necessary to avoid closing the shutter when such a transition occurs. See:
|
||||||
// https://github.com/google/ExoPlayer/issues/5507.
|
// https://github.com/google/ExoPlayer/issues/5507.
|
||||||
@ -1430,7 +1430,7 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
Timeline timeline = player.getCurrentTimeline();
|
Timeline timeline = player.getCurrentTimeline();
|
||||||
if (timeline.isEmpty()) {
|
if (timeline.isEmpty()) {
|
||||||
lastPeriodUidWithTracks = null;
|
lastPeriodUidWithTracks = null;
|
||||||
} else if (!player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) {
|
} else if (!player.getCurrentTracks().isEmpty()) {
|
||||||
lastPeriodUidWithTracks =
|
lastPeriodUidWithTracks =
|
||||||
timeline.getPeriod(player.getCurrentPeriodIndex(), period, /* setIds= */ true).uid;
|
timeline.getPeriod(player.getCurrentPeriodIndex(), period, /* setIds= */ true).uid;
|
||||||
} else if (lastPeriodUidWithTracks != null) {
|
} else if (lastPeriodUidWithTracks != null) {
|
||||||
|
@ -26,7 +26,7 @@ import androidx.annotation.StyleRes;
|
|||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.Player;
|
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.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
|
||||||
@ -56,7 +56,7 @@ public final class TrackSelectionDialogBuilder {
|
|||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final CharSequence title;
|
private final CharSequence title;
|
||||||
private final List<TrackGroupInfo> trackGroupInfos;
|
private final List<Tracks.Group> trackGroups;
|
||||||
private final DialogCallback callback;
|
private final DialogCallback callback;
|
||||||
|
|
||||||
@StyleRes private int themeResId;
|
@StyleRes private int themeResId;
|
||||||
@ -73,17 +73,17 @@ public final class TrackSelectionDialogBuilder {
|
|||||||
*
|
*
|
||||||
* @param context The context of the dialog.
|
* @param context The context of the dialog.
|
||||||
* @param title The title of the dialog.
|
* @param title The title of the dialog.
|
||||||
* @param trackGroupInfos The {@link TrackGroupInfo TrackGroupInfos} for the track groups.
|
* @param trackGroups The {@link Tracks.Group track groups}.
|
||||||
* @param callback The {@link DialogCallback} invoked when a track selection has been made.
|
* @param callback The {@link DialogCallback} invoked when a track selection has been made.
|
||||||
*/
|
*/
|
||||||
public TrackSelectionDialogBuilder(
|
public TrackSelectionDialogBuilder(
|
||||||
Context context,
|
Context context,
|
||||||
CharSequence title,
|
CharSequence title,
|
||||||
List<TrackGroupInfo> trackGroupInfos,
|
List<Tracks.Group> trackGroups,
|
||||||
DialogCallback callback) {
|
DialogCallback callback) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.trackGroupInfos = ImmutableList.copyOf(trackGroupInfos);
|
this.trackGroups = ImmutableList.copyOf(trackGroups);
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
overrides = Collections.emptyMap();
|
overrides = Collections.emptyMap();
|
||||||
}
|
}
|
||||||
@ -100,12 +100,12 @@ public final class TrackSelectionDialogBuilder {
|
|||||||
Context context, CharSequence title, Player player, @C.TrackType int trackType) {
|
Context context, CharSequence title, Player player, @C.TrackType int trackType) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
List<TrackGroupInfo> allTrackGroupInfos = player.getCurrentTracksInfo().getTrackGroupInfos();
|
List<Tracks.Group> allTrackGroups = player.getCurrentTracks().getGroups();
|
||||||
trackGroupInfos = new ArrayList<>();
|
trackGroups = new ArrayList<>();
|
||||||
for (int i = 0; i < allTrackGroupInfos.size(); i++) {
|
for (int i = 0; i < allTrackGroups.size(); i++) {
|
||||||
TrackGroupInfo trackGroupInfo = allTrackGroupInfos.get(i);
|
Tracks.Group trackGroup = allTrackGroups.get(i);
|
||||||
if (trackGroupInfo.getTrackType() == trackType) {
|
if (trackGroup.getType() == trackType) {
|
||||||
trackGroupInfos.add(trackGroupInfo);
|
trackGroups.add(trackGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
overrides = Collections.emptyMap();
|
overrides = Collections.emptyMap();
|
||||||
@ -156,11 +156,11 @@ public final class TrackSelectionDialogBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the initial track overrides. Any overrides that do not correspond to track groups
|
* Sets the initial track overrides. Any overrides that do not correspond to track groups that
|
||||||
* described by {@code trackGroupInfos} that have been given to this instance will be ignored. If
|
* were passed to the constructor will be ignored. If {@link #setAllowMultipleOverrides(boolean)}
|
||||||
* {@link #setAllowMultipleOverrides(boolean)} hasn't been set to {@code true} then all but one
|
* hasn't been set to {@code true} then all but one override will be ignored. The retained
|
||||||
* override will be ignored. The retained override will be the one whose track group is described
|
* override will be the one whose track group was first in the list of track groups passed to the
|
||||||
* first in {@code trackGroupInfos}.
|
* constructor.
|
||||||
*
|
*
|
||||||
* @param overrides The initially selected track overrides.
|
* @param overrides The initially selected track overrides.
|
||||||
* @return This builder, for convenience.
|
* @return This builder, for convenience.
|
||||||
@ -296,7 +296,7 @@ public final class TrackSelectionDialogBuilder {
|
|||||||
selectionView.setTrackNameProvider(trackNameProvider);
|
selectionView.setTrackNameProvider(trackNameProvider);
|
||||||
}
|
}
|
||||||
selectionView.init(
|
selectionView.init(
|
||||||
trackGroupInfos, isDisabled, overrides, trackFormatComparator, /* listener= */ null);
|
trackGroups, isDisabled, overrides, trackFormatComparator, /* listener= */ null);
|
||||||
return (dialog, which) ->
|
return (dialog, which) ->
|
||||||
callback.onTracksSelected(selectionView.getIsDisabled(), selectionView.getOverrides());
|
callback.onTracksSelected(selectionView.getIsDisabled(), selectionView.getOverrides());
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import android.widget.LinearLayout;
|
|||||||
import androidx.annotation.AttrRes;
|
import androidx.annotation.AttrRes;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.Format;
|
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.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
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}.
|
* Returns the subset of {@code overrides} that apply to the specified {@code trackGroups}. If
|
||||||
* If {@code allowMultipleOverrides} is {@code} then at most one override is retained, which will
|
* {@code allowMultipleOverrides} is {@code} then at most one override is retained, which will be
|
||||||
* be the one whose track group is first in {@code trackGroupInfos}.
|
* the one whose track group is first in {@code trackGroups}.
|
||||||
*
|
*
|
||||||
* @param overrides The overrides to filter.
|
* @param overrides The overrides to filter.
|
||||||
* @param trackGroupInfos The track groups whose overrides should be retained.
|
* @param trackGroups The track groups whose overrides should be retained.
|
||||||
* @param allowMultipleOverrides Whether more than one override can be retained.
|
* @param allowMultipleOverrides Whether more than one override can be retained.
|
||||||
* @return The filtered overrides.
|
* @return The filtered overrides.
|
||||||
*/
|
*/
|
||||||
public static Map<TrackGroup, TrackSelectionOverride> filterOverrides(
|
public static Map<TrackGroup, TrackSelectionOverride> filterOverrides(
|
||||||
Map<TrackGroup, TrackSelectionOverride> overrides,
|
Map<TrackGroup, TrackSelectionOverride> overrides,
|
||||||
List<TrackGroupInfo> trackGroupInfos,
|
List<Tracks.Group> trackGroups,
|
||||||
boolean allowMultipleOverrides) {
|
boolean allowMultipleOverrides) {
|
||||||
HashMap<TrackGroup, TrackSelectionOverride> filteredOverrides = new HashMap<>();
|
HashMap<TrackGroup, TrackSelectionOverride> filteredOverrides = new HashMap<>();
|
||||||
for (int i = 0; i < trackGroupInfos.size(); i++) {
|
for (int i = 0; i < trackGroups.size(); i++) {
|
||||||
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(i);
|
Tracks.Group trackGroup = trackGroups.get(i);
|
||||||
@Nullable TrackSelectionOverride override = overrides.get(trackGroupInfo.getTrackGroup());
|
@Nullable TrackSelectionOverride override = overrides.get(trackGroup.getTrackGroup());
|
||||||
if (override != null && (allowMultipleOverrides || filteredOverrides.isEmpty())) {
|
if (override != null && (allowMultipleOverrides || filteredOverrides.isEmpty())) {
|
||||||
filteredOverrides.put(override.trackGroup, override);
|
filteredOverrides.put(override.trackGroup, override);
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
private final CheckedTextView disableView;
|
private final CheckedTextView disableView;
|
||||||
private final CheckedTextView defaultView;
|
private final CheckedTextView defaultView;
|
||||||
private final ComponentListener componentListener;
|
private final ComponentListener componentListener;
|
||||||
private final List<TrackGroupInfo> trackGroupInfos;
|
private final List<Tracks.Group> trackGroups;
|
||||||
private final Map<TrackGroup, TrackSelectionOverride> overrides;
|
private final Map<TrackGroup, TrackSelectionOverride> overrides;
|
||||||
|
|
||||||
private boolean allowAdaptiveSelections;
|
private boolean allowAdaptiveSelections;
|
||||||
@ -125,7 +125,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
inflater = LayoutInflater.from(context);
|
inflater = LayoutInflater.from(context);
|
||||||
componentListener = new ComponentListener();
|
componentListener = new ComponentListener();
|
||||||
trackNameProvider = new DefaultTrackNameProvider(getResources());
|
trackNameProvider = new DefaultTrackNameProvider(getResources());
|
||||||
trackGroupInfos = new ArrayList<>();
|
trackGroups = new ArrayList<>();
|
||||||
overrides = new HashMap<>();
|
overrides = new HashMap<>();
|
||||||
|
|
||||||
// View for disabling the renderer.
|
// View for disabling the renderer.
|
||||||
@ -181,7 +181,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
if (!allowMultipleOverrides && overrides.size() > 1) {
|
if (!allowMultipleOverrides && overrides.size() > 1) {
|
||||||
// Re-filter the overrides to retain only one of them.
|
// Re-filter the overrides to retain only one of them.
|
||||||
Map<TrackGroup, TrackSelectionOverride> filteredOverrides =
|
Map<TrackGroup, TrackSelectionOverride> filteredOverrides =
|
||||||
filterOverrides(overrides, trackGroupInfos, /* allowMultipleOverrides= */ false);
|
filterOverrides(overrides, trackGroups, /* allowMultipleOverrides= */ false);
|
||||||
overrides.clear();
|
overrides.clear();
|
||||||
overrides.putAll(filteredOverrides);
|
overrides.putAll(filteredOverrides);
|
||||||
}
|
}
|
||||||
@ -212,19 +212,19 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
/**
|
/**
|
||||||
* Initialize the view to select tracks from a specified list of track groups.
|
* Initialize the view to select tracks from a specified list of track groups.
|
||||||
*
|
*
|
||||||
* @param trackGroupInfos {@link TrackGroupInfo TrackGroupInfos} for the track groups.
|
* @param trackGroups The {@link Tracks.Group track groups}.
|
||||||
* @param isDisabled Whether the disabled option should be initially selected.
|
* @param isDisabled Whether the disabled option should be initially selected.
|
||||||
* @param overrides The initially selected track overrides. Any overrides that do not correspond
|
* @param overrides The initially selected track overrides. Any overrides that do not correspond
|
||||||
* to track groups described in {@code trackGroupInfos} will be ignored. If {@link
|
* to track groups in {@code trackGroups} will be ignored. If {@link
|
||||||
* #setAllowMultipleOverrides(boolean)} hasn't been set to {@code true} then all but one
|
* #setAllowMultipleOverrides(boolean)} hasn't been set to {@code true} then all but one
|
||||||
* override will be ignored. The retained override will be the one whose track group is
|
* override will be ignored. The retained override will be the one whose track group is first
|
||||||
* described first in {@code trackGroupInfos}.
|
* in {@code trackGroups}.
|
||||||
* @param trackFormatComparator An optional comparator used to determine the display order of the
|
* @param trackFormatComparator An optional comparator used to determine the display order of the
|
||||||
* tracks within each track group.
|
* tracks within each track group.
|
||||||
* @param listener An optional listener to receive selection updates.
|
* @param listener An optional listener to receive selection updates.
|
||||||
*/
|
*/
|
||||||
public void init(
|
public void init(
|
||||||
List<TrackGroupInfo> trackGroupInfos,
|
List<Tracks.Group> trackGroups,
|
||||||
boolean isDisabled,
|
boolean isDisabled,
|
||||||
Map<TrackGroup, TrackSelectionOverride> overrides,
|
Map<TrackGroup, TrackSelectionOverride> overrides,
|
||||||
@Nullable Comparator<Format> trackFormatComparator,
|
@Nullable Comparator<Format> trackFormatComparator,
|
||||||
@ -236,10 +236,10 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
: (o1, o2) -> trackFormatComparator.compare(o1.getFormat(), o2.getFormat());
|
: (o1, o2) -> trackFormatComparator.compare(o1.getFormat(), o2.getFormat());
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
|
|
||||||
this.trackGroupInfos.clear();
|
this.trackGroups.clear();
|
||||||
this.trackGroupInfos.addAll(trackGroupInfos);
|
this.trackGroups.addAll(trackGroups);
|
||||||
this.overrides.clear();
|
this.overrides.clear();
|
||||||
this.overrides.putAll(filterOverrides(overrides, trackGroupInfos, allowMultipleOverrides));
|
this.overrides.putAll(filterOverrides(overrides, trackGroups, allowMultipleOverrides));
|
||||||
updateViews();
|
updateViews();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,7 +261,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
removeViewAt(i);
|
removeViewAt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trackGroupInfos.isEmpty()) {
|
if (trackGroups.isEmpty()) {
|
||||||
// The view is not initialized.
|
// The view is not initialized.
|
||||||
disableView.setEnabled(false);
|
disableView.setEnabled(false);
|
||||||
defaultView.setEnabled(false);
|
defaultView.setEnabled(false);
|
||||||
@ -271,17 +271,16 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
defaultView.setEnabled(true);
|
defaultView.setEnabled(true);
|
||||||
|
|
||||||
// Add per-track views.
|
// Add per-track views.
|
||||||
trackViews = new CheckedTextView[trackGroupInfos.size()][];
|
trackViews = new CheckedTextView[trackGroups.size()][];
|
||||||
boolean enableMultipleChoiceForMultipleOverrides = shouldEnableMultiGroupSelection();
|
boolean enableMultipleChoiceForMultipleOverrides = shouldEnableMultiGroupSelection();
|
||||||
for (int trackGroupIndex = 0; trackGroupIndex < trackGroupInfos.size(); trackGroupIndex++) {
|
for (int trackGroupIndex = 0; trackGroupIndex < trackGroups.size(); trackGroupIndex++) {
|
||||||
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(trackGroupIndex);
|
Tracks.Group trackGroup = trackGroups.get(trackGroupIndex);
|
||||||
boolean enableMultipleChoiceForAdaptiveSelections =
|
boolean enableMultipleChoiceForAdaptiveSelections = shouldEnableAdaptiveSelection(trackGroup);
|
||||||
shouldEnableAdaptiveSelection(trackGroupInfo);
|
trackViews[trackGroupIndex] = new CheckedTextView[trackGroup.length];
|
||||||
trackViews[trackGroupIndex] = new CheckedTextView[trackGroupInfo.length];
|
|
||||||
|
|
||||||
TrackInfo[] trackInfos = new TrackInfo[trackGroupInfo.length];
|
TrackInfo[] trackInfos = new TrackInfo[trackGroup.length];
|
||||||
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) {
|
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
||||||
trackInfos[trackIndex] = new TrackInfo(trackGroupInfo, trackIndex);
|
trackInfos[trackIndex] = new TrackInfo(trackGroup, trackIndex);
|
||||||
}
|
}
|
||||||
if (trackInfoComparator != null) {
|
if (trackInfoComparator != null) {
|
||||||
Arrays.sort(trackInfos, trackInfoComparator);
|
Arrays.sort(trackInfos, trackInfoComparator);
|
||||||
@ -300,7 +299,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
trackView.setBackgroundResource(selectableItemBackgroundResourceId);
|
trackView.setBackgroundResource(selectableItemBackgroundResourceId);
|
||||||
trackView.setText(trackNameProvider.getTrackName(trackInfos[trackIndex].getFormat()));
|
trackView.setText(trackNameProvider.getTrackName(trackInfos[trackIndex].getFormat()));
|
||||||
trackView.setTag(trackInfos[trackIndex]);
|
trackView.setTag(trackInfos[trackIndex]);
|
||||||
if (trackGroupInfo.isTrackSupported(trackIndex)) {
|
if (trackGroup.isTrackSupported(trackIndex)) {
|
||||||
trackView.setFocusable(true);
|
trackView.setFocusable(true);
|
||||||
trackView.setOnClickListener(componentListener);
|
trackView.setOnClickListener(componentListener);
|
||||||
} else {
|
} else {
|
||||||
@ -319,8 +318,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
disableView.setChecked(isDisabled);
|
disableView.setChecked(isDisabled);
|
||||||
defaultView.setChecked(!isDisabled && overrides.size() == 0);
|
defaultView.setChecked(!isDisabled && overrides.size() == 0);
|
||||||
for (int i = 0; i < trackViews.length; i++) {
|
for (int i = 0; i < trackViews.length; i++) {
|
||||||
@Nullable
|
@Nullable TrackSelectionOverride override = overrides.get(trackGroups.get(i).getTrackGroup());
|
||||||
TrackSelectionOverride override = overrides.get(trackGroupInfos.get(i).getTrackGroup());
|
|
||||||
for (int j = 0; j < trackViews[i].length; j++) {
|
for (int j = 0; j < trackViews[i].length; j++) {
|
||||||
if (override != null) {
|
if (override != null) {
|
||||||
TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(trackViews[i][j].getTag());
|
TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(trackViews[i][j].getTag());
|
||||||
@ -359,7 +357,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
private void onTrackViewClicked(View view) {
|
private void onTrackViewClicked(View view) {
|
||||||
isDisabled = false;
|
isDisabled = false;
|
||||||
TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(view.getTag());
|
TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(view.getTag());
|
||||||
TrackGroup trackGroup = trackInfo.trackGroupInfo.getTrackGroup();
|
TrackGroup trackGroup = trackInfo.trackGroup.getTrackGroup();
|
||||||
int trackIndex = trackInfo.trackIndex;
|
int trackIndex = trackInfo.trackIndex;
|
||||||
@Nullable TrackSelectionOverride override = overrides.get(trackGroup);
|
@Nullable TrackSelectionOverride override = overrides.get(trackGroup);
|
||||||
if (override == null) {
|
if (override == null) {
|
||||||
@ -374,7 +372,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
// An existing override is being modified.
|
// An existing override is being modified.
|
||||||
ArrayList<Integer> trackIndices = new ArrayList<>(override.trackIndices);
|
ArrayList<Integer> trackIndices = new ArrayList<>(override.trackIndices);
|
||||||
boolean isCurrentlySelected = ((CheckedTextView) view).isChecked();
|
boolean isCurrentlySelected = ((CheckedTextView) view).isChecked();
|
||||||
boolean isAdaptiveAllowed = shouldEnableAdaptiveSelection(trackInfo.trackGroupInfo);
|
boolean isAdaptiveAllowed = shouldEnableAdaptiveSelection(trackInfo.trackGroup);
|
||||||
boolean isUsingCheckBox = isAdaptiveAllowed || shouldEnableMultiGroupSelection();
|
boolean isUsingCheckBox = isAdaptiveAllowed || shouldEnableMultiGroupSelection();
|
||||||
if (isCurrentlySelected && isUsingCheckBox) {
|
if (isCurrentlySelected && isUsingCheckBox) {
|
||||||
// Remove the track from the override.
|
// Remove the track from the override.
|
||||||
@ -399,12 +397,12 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldEnableAdaptiveSelection(TrackGroupInfo trackGroupInfo) {
|
private boolean shouldEnableAdaptiveSelection(Tracks.Group trackGroup) {
|
||||||
return allowAdaptiveSelections && trackGroupInfo.isAdaptiveSupported();
|
return allowAdaptiveSelections && trackGroup.isAdaptiveSupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldEnableMultiGroupSelection() {
|
private boolean shouldEnableMultiGroupSelection() {
|
||||||
return allowMultipleOverrides && trackGroupInfos.size() > 1;
|
return allowMultipleOverrides && trackGroups.size() > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal classes.
|
// Internal classes.
|
||||||
@ -418,16 +416,16 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final class TrackInfo {
|
private static final class TrackInfo {
|
||||||
public final TrackGroupInfo trackGroupInfo;
|
public final Tracks.Group trackGroup;
|
||||||
public final int trackIndex;
|
public final int trackIndex;
|
||||||
|
|
||||||
public TrackInfo(TrackGroupInfo trackGroupInfo, int trackIndex) {
|
public TrackInfo(Tracks.Group trackGroup, int trackIndex) {
|
||||||
this.trackGroupInfo = trackGroupInfo;
|
this.trackGroup = trackGroup;
|
||||||
this.trackIndex = trackIndex;
|
this.trackIndex = trackIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format getFormat() {
|
public Format getFormat() {
|
||||||
return trackGroupInfo.getTrackFormat(trackIndex);
|
return trackGroup.getTrackFormat(trackIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ import com.google.android.exoplayer2.PlaybackException;
|
|||||||
import com.google.android.exoplayer2.PlaybackParameters;
|
import com.google.android.exoplayer2.PlaybackParameters;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
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.AudioAttributes;
|
||||||
import com.google.android.exoplayer2.text.Cue;
|
import com.google.android.exoplayer2.text.Cue;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
|
||||||
@ -189,7 +189,7 @@ public class StubPlayer extends BasePlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user