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
af8435816a
commit
83daa052cb
@ -15,6 +15,10 @@
|
|||||||
* Track selection:
|
* Track selection:
|
||||||
* Flatten `TrackSelectionOverrides` class into `TrackSelectionParameters`,
|
* Flatten `TrackSelectionOverrides` class into `TrackSelectionParameters`,
|
||||||
and promote `TrackSelectionOverride` to a top level class.
|
and promote `TrackSelectionOverride` to a top level class.
|
||||||
|
* Rename `TracksInfo` to `Tracks` and `TracksInfo.TrackGroupInfo` to
|
||||||
|
`Tracks.Group`. `Player.getCurrentTracksInfo` and
|
||||||
|
`Player.Listener.onTracksInfoChanged` have also been renamed to
|
||||||
|
`Player.getCurrentTracks` and `Player.Listener.onTracksChanged`.
|
||||||
* Video:
|
* Video:
|
||||||
* Rename `DummySurface` to `PlaceHolderSurface`.
|
* Rename `DummySurface` to `PlaceHolderSurface`.
|
||||||
* Audio:
|
* Audio:
|
||||||
|
@ -26,7 +26,7 @@ import androidx.media3.common.Player;
|
|||||||
import androidx.media3.common.Player.DiscontinuityReason;
|
import androidx.media3.common.Player.DiscontinuityReason;
|
||||||
import androidx.media3.common.Player.TimelineChangeReason;
|
import androidx.media3.common.Player.TimelineChangeReason;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.exoplayer.ExoPlayer;
|
import androidx.media3.exoplayer.ExoPlayer;
|
||||||
import androidx.media3.ui.PlayerControlView;
|
import androidx.media3.ui.PlayerControlView;
|
||||||
import androidx.media3.ui.PlayerView;
|
import androidx.media3.ui.PlayerView;
|
||||||
@ -57,7 +57,7 @@ import java.util.ArrayList;
|
|||||||
private final ArrayList<MediaItem> mediaQueue;
|
private final ArrayList<MediaItem> mediaQueue;
|
||||||
private final Listener listener;
|
private final Listener listener;
|
||||||
|
|
||||||
private TracksInfo lastSeenTrackGroupInfo;
|
private Tracks lastSeenTracks;
|
||||||
private int currentItemIndex;
|
private int currentItemIndex;
|
||||||
private Player currentPlayer;
|
private Player currentPlayer;
|
||||||
|
|
||||||
@ -219,19 +219,19 @@ import java.util.ArrayList;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
if (currentPlayer != localPlayer || tracksInfo == lastSeenTrackGroupInfo) {
|
if (currentPlayer != localPlayer || tracks == lastSeenTracks) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tracksInfo.containsType(C.TRACK_TYPE_VIDEO)
|
if (tracks.containsType(C.TRACK_TYPE_VIDEO)
|
||||||
&& !tracksInfo.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
|
&& !tracks.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
|
||||||
listener.onUnsupportedTrack(C.TRACK_TYPE_VIDEO);
|
listener.onUnsupportedTrack(C.TRACK_TYPE_VIDEO);
|
||||||
}
|
}
|
||||||
if (tracksInfo.containsType(C.TRACK_TYPE_AUDIO)
|
if (tracks.containsType(C.TRACK_TYPE_AUDIO)
|
||||||
&& !tracksInfo.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
|
&& !tracks.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
|
||||||
listener.onUnsupportedTrack(C.TRACK_TYPE_AUDIO);
|
listener.onUnsupportedTrack(C.TRACK_TYPE_AUDIO);
|
||||||
}
|
}
|
||||||
lastSeenTrackGroupInfo = tracksInfo;
|
lastSeenTracks = tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CastPlayer.SessionAvailabilityListener implementation.
|
// CastPlayer.SessionAvailabilityListener implementation.
|
||||||
|
@ -31,7 +31,7 @@ import androidx.media3.common.Format;
|
|||||||
import androidx.media3.common.MediaItem;
|
import androidx.media3.common.MediaItem;
|
||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.util.Log;
|
import androidx.media3.common.util.Log;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.datasource.DataSource;
|
import androidx.media3.datasource.DataSource;
|
||||||
@ -303,17 +303,17 @@ public class DownloadTracker {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TracksInfo tracksInfo = downloadHelper.getTracksInfo(/* periodIndex= */ 0);
|
Tracks tracks = downloadHelper.getTracks(/* periodIndex= */ 0);
|
||||||
if (!TrackSelectionDialog.willHaveContent(tracksInfo)) {
|
if (!TrackSelectionDialog.willHaveContent(tracks)) {
|
||||||
Log.d(TAG, "No dialog content. Downloading entire stream.");
|
Log.d(TAG, "No dialog content. Downloading entire stream.");
|
||||||
startDownload();
|
startDownload();
|
||||||
downloadHelper.release();
|
downloadHelper.release();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
trackSelectionDialog =
|
trackSelectionDialog =
|
||||||
TrackSelectionDialog.createForTracksInfoAndParameters(
|
TrackSelectionDialog.createForTracksAndParameters(
|
||||||
/* titleId= */ R.string.exo_download_description,
|
/* titleId= */ R.string.exo_download_description,
|
||||||
tracksInfo,
|
tracks,
|
||||||
DownloadHelper.getDefaultTrackSelectorParameters(context),
|
DownloadHelper.getDefaultTrackSelectorParameters(context),
|
||||||
/* allowAdaptiveSelections= */ false,
|
/* allowAdaptiveSelections= */ false,
|
||||||
/* allowMultipleOverrides= */ true,
|
/* allowMultipleOverrides= */ true,
|
||||||
|
@ -37,7 +37,7 @@ import androidx.media3.common.MediaItem;
|
|||||||
import androidx.media3.common.PlaybackException;
|
import androidx.media3.common.PlaybackException;
|
||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.datasource.DataSource;
|
import androidx.media3.datasource.DataSource;
|
||||||
import androidx.media3.exoplayer.ExoPlayer;
|
import androidx.media3.exoplayer.ExoPlayer;
|
||||||
@ -83,7 +83,7 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
private List<MediaItem> mediaItems;
|
private List<MediaItem> mediaItems;
|
||||||
private TrackSelectionParameters trackSelectionParameters;
|
private TrackSelectionParameters trackSelectionParameters;
|
||||||
private DebugTextViewHelper debugViewHelper;
|
private DebugTextViewHelper debugViewHelper;
|
||||||
private TracksInfo lastSeenTracksInfo;
|
private Tracks lastSeenTracks;
|
||||||
private boolean startAutoPlay;
|
private boolean startAutoPlay;
|
||||||
private int startItemIndex;
|
private int startItemIndex;
|
||||||
private long startPosition;
|
private long startPosition;
|
||||||
@ -276,7 +276,7 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
RenderersFactory renderersFactory =
|
RenderersFactory renderersFactory =
|
||||||
DemoUtil.buildRenderersFactory(/* context= */ this, preferExtensionDecoders);
|
DemoUtil.buildRenderersFactory(/* context= */ this, preferExtensionDecoders);
|
||||||
|
|
||||||
lastSeenTracksInfo = TracksInfo.EMPTY;
|
lastSeenTracks = Tracks.EMPTY;
|
||||||
player =
|
player =
|
||||||
new ExoPlayer.Builder(/* context= */ this)
|
new ExoPlayer.Builder(/* context= */ this)
|
||||||
.setRenderersFactory(renderersFactory)
|
.setRenderersFactory(renderersFactory)
|
||||||
@ -456,22 +456,20 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("ReferenceEquality")
|
@SuppressWarnings("ReferenceEquality")
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
updateButtonVisibility();
|
updateButtonVisibility();
|
||||||
if (tracksInfo == lastSeenTracksInfo) {
|
if (tracks == lastSeenTracks) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tracksInfo.containsType(C.TRACK_TYPE_VIDEO)
|
if (tracks.containsType(C.TRACK_TYPE_VIDEO)
|
||||||
&& !tracksInfo.isTypeSupported(
|
&& !tracks.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
|
||||||
C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
|
|
||||||
showToast(R.string.error_unsupported_video);
|
showToast(R.string.error_unsupported_video);
|
||||||
}
|
}
|
||||||
if (tracksInfo.containsType(C.TRACK_TYPE_AUDIO)
|
if (tracks.containsType(C.TRACK_TYPE_AUDIO)
|
||||||
&& !tracksInfo.isTypeSupported(
|
&& !tracks.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
|
||||||
C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
|
|
||||||
showToast(R.string.error_unsupported_audio);
|
showToast(R.string.error_unsupported_audio);
|
||||||
}
|
}
|
||||||
lastSeenTracksInfo = tracksInfo;
|
lastSeenTracks = tracks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,8 +35,7 @@ import androidx.media3.common.Player;
|
|||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TrackSelectionOverride;
|
import androidx.media3.common.TrackSelectionOverride;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.TracksInfo.TrackGroupInfo;
|
|
||||||
import androidx.media3.ui.TrackSelectionView;
|
import androidx.media3.ui.TrackSelectionView;
|
||||||
import androidx.viewpager.widget.ViewPager;
|
import androidx.viewpager.widget.ViewPager;
|
||||||
import com.google.android.material.tabs.TabLayout;
|
import com.google.android.material.tabs.TabLayout;
|
||||||
@ -79,16 +78,16 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
* specified {@link Player}.
|
* specified {@link Player}.
|
||||||
*/
|
*/
|
||||||
public static boolean willHaveContent(Player player) {
|
public static boolean willHaveContent(Player player) {
|
||||||
return willHaveContent(player.getCurrentTracksInfo());
|
return willHaveContent(player.getCurrentTracks());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether a track selection dialog will have content to display if initialized with the
|
* Returns whether a track selection dialog will have content to display if initialized with the
|
||||||
* specified {@link TracksInfo}.
|
* specified {@link Tracks}.
|
||||||
*/
|
*/
|
||||||
public static boolean willHaveContent(TracksInfo tracksInfo) {
|
public static boolean willHaveContent(Tracks tracks) {
|
||||||
for (TrackGroupInfo trackGroupInfo : tracksInfo.getTrackGroupInfos()) {
|
for (Tracks.Group trackGroup : tracks.getGroups()) {
|
||||||
if (SUPPORTED_TRACK_TYPES.contains(trackGroupInfo.getTrackType())) {
|
if (SUPPORTED_TRACK_TYPES.contains(trackGroup.getType())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,9 +104,9 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
*/
|
*/
|
||||||
public static TrackSelectionDialog createForPlayer(
|
public static TrackSelectionDialog createForPlayer(
|
||||||
Player player, DialogInterface.OnDismissListener onDismissListener) {
|
Player player, DialogInterface.OnDismissListener onDismissListener) {
|
||||||
return createForTracksInfoAndParameters(
|
return createForTracksAndParameters(
|
||||||
R.string.track_selection_title,
|
R.string.track_selection_title,
|
||||||
player.getCurrentTracksInfo(),
|
player.getCurrentTracks(),
|
||||||
player.getTrackSelectionParameters(),
|
player.getTrackSelectionParameters(),
|
||||||
/* allowAdaptiveSelections= */ true,
|
/* allowAdaptiveSelections= */ true,
|
||||||
/* allowMultipleOverrides= */ false,
|
/* allowMultipleOverrides= */ false,
|
||||||
@ -116,10 +115,10 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a dialog for given {@link TracksInfo} and {@link TrackSelectionParameters}.
|
* Creates a dialog for given {@link Tracks} and {@link TrackSelectionParameters}.
|
||||||
*
|
*
|
||||||
* @param titleId The resource id of the dialog title.
|
* @param titleId The resource id of the dialog title.
|
||||||
* @param tracksInfo The {@link TracksInfo} describing the tracks to display.
|
* @param tracks The {@link Tracks} describing the tracks to display.
|
||||||
* @param trackSelectionParameters The initial {@link TrackSelectionParameters}.
|
* @param trackSelectionParameters The initial {@link TrackSelectionParameters}.
|
||||||
* @param allowAdaptiveSelections Whether adaptive selections (consisting of more than one track)
|
* @param allowAdaptiveSelections Whether adaptive selections (consisting of more than one track)
|
||||||
* can be made.
|
* can be made.
|
||||||
@ -128,9 +127,9 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
* @param onDismissListener {@link DialogInterface.OnDismissListener} called when the dialog is
|
* @param onDismissListener {@link DialogInterface.OnDismissListener} called when the dialog is
|
||||||
* dismissed.
|
* dismissed.
|
||||||
*/
|
*/
|
||||||
public static TrackSelectionDialog createForTracksInfoAndParameters(
|
public static TrackSelectionDialog createForTracksAndParameters(
|
||||||
int titleId,
|
int titleId,
|
||||||
TracksInfo tracksInfo,
|
Tracks tracks,
|
||||||
TrackSelectionParameters trackSelectionParameters,
|
TrackSelectionParameters trackSelectionParameters,
|
||||||
boolean allowAdaptiveSelections,
|
boolean allowAdaptiveSelections,
|
||||||
boolean allowMultipleOverrides,
|
boolean allowMultipleOverrides,
|
||||||
@ -138,7 +137,7 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
DialogInterface.OnDismissListener onDismissListener) {
|
DialogInterface.OnDismissListener onDismissListener) {
|
||||||
TrackSelectionDialog trackSelectionDialog = new TrackSelectionDialog();
|
TrackSelectionDialog trackSelectionDialog = new TrackSelectionDialog();
|
||||||
trackSelectionDialog.init(
|
trackSelectionDialog.init(
|
||||||
tracksInfo,
|
tracks,
|
||||||
trackSelectionParameters,
|
trackSelectionParameters,
|
||||||
titleId,
|
titleId,
|
||||||
allowAdaptiveSelections,
|
allowAdaptiveSelections,
|
||||||
@ -169,7 +168,7 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void init(
|
private void init(
|
||||||
TracksInfo tracksInfo,
|
Tracks tracks,
|
||||||
TrackSelectionParameters trackSelectionParameters,
|
TrackSelectionParameters trackSelectionParameters,
|
||||||
int titleId,
|
int titleId,
|
||||||
boolean allowAdaptiveSelections,
|
boolean allowAdaptiveSelections,
|
||||||
@ -182,16 +181,16 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
|
|
||||||
for (int i = 0; i < SUPPORTED_TRACK_TYPES.size(); i++) {
|
for (int i = 0; i < SUPPORTED_TRACK_TYPES.size(); i++) {
|
||||||
@C.TrackType int trackType = SUPPORTED_TRACK_TYPES.get(i);
|
@C.TrackType int trackType = SUPPORTED_TRACK_TYPES.get(i);
|
||||||
ArrayList<TrackGroupInfo> trackGroupInfos = new ArrayList<>();
|
ArrayList<Tracks.Group> trackGroups = new ArrayList<>();
|
||||||
for (TrackGroupInfo trackGroupInfo : tracksInfo.getTrackGroupInfos()) {
|
for (Tracks.Group trackGroup : tracks.getGroups()) {
|
||||||
if (trackGroupInfo.getTrackType() == trackType) {
|
if (trackGroup.getType() == trackType) {
|
||||||
trackGroupInfos.add(trackGroupInfo);
|
trackGroups.add(trackGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!trackGroupInfos.isEmpty()) {
|
if (!trackGroups.isEmpty()) {
|
||||||
TrackSelectionViewFragment tabFragment = new TrackSelectionViewFragment();
|
TrackSelectionViewFragment tabFragment = new TrackSelectionViewFragment();
|
||||||
tabFragment.init(
|
tabFragment.init(
|
||||||
trackGroupInfos,
|
trackGroups,
|
||||||
trackSelectionParameters.disabledTrackTypes.contains(trackType),
|
trackSelectionParameters.disabledTrackTypes.contains(trackType),
|
||||||
trackSelectionParameters.overrides,
|
trackSelectionParameters.overrides,
|
||||||
allowAdaptiveSelections,
|
allowAdaptiveSelections,
|
||||||
@ -300,7 +299,7 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
public static final class TrackSelectionViewFragment extends Fragment
|
public static final class TrackSelectionViewFragment extends Fragment
|
||||||
implements TrackSelectionView.TrackSelectionListener {
|
implements TrackSelectionView.TrackSelectionListener {
|
||||||
|
|
||||||
private List<TrackGroupInfo> trackGroupInfos;
|
private List<Tracks.Group> trackGroups;
|
||||||
private boolean allowAdaptiveSelections;
|
private boolean allowAdaptiveSelections;
|
||||||
private boolean allowMultipleOverrides;
|
private boolean allowMultipleOverrides;
|
||||||
|
|
||||||
@ -313,12 +312,12 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void init(
|
public void init(
|
||||||
List<TrackGroupInfo> trackGroupInfos,
|
List<Tracks.Group> trackGroups,
|
||||||
boolean isDisabled,
|
boolean isDisabled,
|
||||||
Map<TrackGroup, TrackSelectionOverride> overrides,
|
Map<TrackGroup, TrackSelectionOverride> overrides,
|
||||||
boolean allowAdaptiveSelections,
|
boolean allowAdaptiveSelections,
|
||||||
boolean allowMultipleOverrides) {
|
boolean allowMultipleOverrides) {
|
||||||
this.trackGroupInfos = trackGroupInfos;
|
this.trackGroups = trackGroups;
|
||||||
this.isDisabled = isDisabled;
|
this.isDisabled = isDisabled;
|
||||||
this.allowAdaptiveSelections = allowAdaptiveSelections;
|
this.allowAdaptiveSelections = allowAdaptiveSelections;
|
||||||
this.allowMultipleOverrides = allowMultipleOverrides;
|
this.allowMultipleOverrides = allowMultipleOverrides;
|
||||||
@ -326,8 +325,7 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
// handle the case where the TrackSelectionView is never created.
|
// handle the case where the TrackSelectionView is never created.
|
||||||
this.overrides =
|
this.overrides =
|
||||||
new HashMap<>(
|
new HashMap<>(
|
||||||
TrackSelectionView.filterOverrides(
|
TrackSelectionView.filterOverrides(overrides, trackGroups, allowMultipleOverrides));
|
||||||
overrides, trackGroupInfos, allowMultipleOverrides));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -343,7 +341,7 @@ public final class TrackSelectionDialog extends DialogFragment {
|
|||||||
trackSelectionView.setAllowMultipleOverrides(allowMultipleOverrides);
|
trackSelectionView.setAllowMultipleOverrides(allowMultipleOverrides);
|
||||||
trackSelectionView.setAllowAdaptiveSelections(allowAdaptiveSelections);
|
trackSelectionView.setAllowAdaptiveSelections(allowAdaptiveSelections);
|
||||||
trackSelectionView.init(
|
trackSelectionView.init(
|
||||||
trackGroupInfos,
|
trackGroups,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
overrides,
|
overrides,
|
||||||
/* trackFormatComparator= */ null,
|
/* trackFormatComparator= */ null,
|
||||||
|
@ -40,8 +40,7 @@ import androidx.media3.common.Player;
|
|||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.TracksInfo.TrackGroupInfo;
|
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.text.Cue;
|
import androidx.media3.common.text.Cue;
|
||||||
import androidx.media3.common.util.Assertions;
|
import androidx.media3.common.util.Assertions;
|
||||||
@ -136,7 +135,7 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
private final StateHolder<PlaybackParameters> playbackParameters;
|
private final StateHolder<PlaybackParameters> playbackParameters;
|
||||||
@Nullable private RemoteMediaClient remoteMediaClient;
|
@Nullable private RemoteMediaClient remoteMediaClient;
|
||||||
private CastTimeline currentTimeline;
|
private CastTimeline currentTimeline;
|
||||||
private TracksInfo currentTracksInfo;
|
private Tracks currentTracks;
|
||||||
private Commands availableCommands;
|
private Commands availableCommands;
|
||||||
private @Player.State int playbackState;
|
private @Player.State int playbackState;
|
||||||
private int currentWindowIndex;
|
private int currentWindowIndex;
|
||||||
@ -212,7 +211,7 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
playbackParameters = new StateHolder<>(PlaybackParameters.DEFAULT);
|
playbackParameters = new StateHolder<>(PlaybackParameters.DEFAULT);
|
||||||
playbackState = STATE_IDLE;
|
playbackState = STATE_IDLE;
|
||||||
currentTimeline = CastTimeline.EMPTY_CAST_TIMELINE;
|
currentTimeline = CastTimeline.EMPTY_CAST_TIMELINE;
|
||||||
currentTracksInfo = TracksInfo.EMPTY;
|
currentTracks = Tracks.EMPTY;
|
||||||
availableCommands = new Commands.Builder().addAll(PERMANENT_AVAILABLE_COMMANDS).build();
|
availableCommands = new Commands.Builder().addAll(PERMANENT_AVAILABLE_COMMANDS).build();
|
||||||
pendingSeekWindowIndex = C.INDEX_UNSET;
|
pendingSeekWindowIndex = C.INDEX_UNSET;
|
||||||
pendingSeekPositionMs = C.TIME_UNSET;
|
pendingSeekPositionMs = C.TIME_UNSET;
|
||||||
@ -544,8 +543,8 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
return currentTracksInfo;
|
return currentTracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -818,7 +817,7 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
}
|
}
|
||||||
if (updateTracksAndSelectionsAndNotifyIfChanged()) {
|
if (updateTracksAndSelectionsAndNotifyIfChanged()) {
|
||||||
listeners.queueEvent(
|
listeners.queueEvent(
|
||||||
Player.EVENT_TRACKS_CHANGED, listener -> listener.onTracksInfoChanged(currentTracksInfo));
|
Player.EVENT_TRACKS_CHANGED, listener -> listener.onTracksChanged(currentTracks));
|
||||||
}
|
}
|
||||||
updateAvailableCommandsAndNotifyIfChanged();
|
updateAvailableCommandsAndNotifyIfChanged();
|
||||||
listeners.flushEvents();
|
listeners.flushEvents();
|
||||||
@ -978,8 +977,8 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
@Nullable
|
@Nullable
|
||||||
List<MediaTrack> castMediaTracks = mediaInfo != null ? mediaInfo.getMediaTracks() : null;
|
List<MediaTrack> castMediaTracks = mediaInfo != null ? mediaInfo.getMediaTracks() : null;
|
||||||
if (castMediaTracks == null || castMediaTracks.isEmpty()) {
|
if (castMediaTracks == null || castMediaTracks.isEmpty()) {
|
||||||
boolean hasChanged = !TracksInfo.EMPTY.equals(currentTracksInfo);
|
boolean hasChanged = !Tracks.EMPTY.equals(currentTracks);
|
||||||
currentTracksInfo = TracksInfo.EMPTY;
|
currentTracks = Tracks.EMPTY;
|
||||||
return hasChanged;
|
return hasChanged;
|
||||||
}
|
}
|
||||||
@Nullable long[] activeTrackIds = mediaStatus.getActiveTrackIds();
|
@Nullable long[] activeTrackIds = mediaStatus.getActiveTrackIds();
|
||||||
@ -987,20 +986,19 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
activeTrackIds = EMPTY_TRACK_ID_ARRAY;
|
activeTrackIds = EMPTY_TRACK_ID_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackGroupInfo[] trackGroupInfos = new TrackGroupInfo[castMediaTracks.size()];
|
Tracks.Group[] trackGroups = new Tracks.Group[castMediaTracks.size()];
|
||||||
for (int i = 0; i < castMediaTracks.size(); i++) {
|
for (int i = 0; i < castMediaTracks.size(); i++) {
|
||||||
MediaTrack mediaTrack = castMediaTracks.get(i);
|
MediaTrack mediaTrack = castMediaTracks.get(i);
|
||||||
TrackGroup trackGroup =
|
TrackGroup trackGroup =
|
||||||
new TrackGroup(/* id= */ Integer.toString(i), CastUtils.mediaTrackToFormat(mediaTrack));
|
new TrackGroup(/* id= */ Integer.toString(i), CastUtils.mediaTrackToFormat(mediaTrack));
|
||||||
@C.FormatSupport int[] trackSupport = new int[] {C.FORMAT_HANDLED};
|
@C.FormatSupport int[] trackSupport = new int[] {C.FORMAT_HANDLED};
|
||||||
boolean[] trackSelected = new boolean[] {isTrackActive(mediaTrack.getId(), activeTrackIds)};
|
boolean[] trackSelected = new boolean[] {isTrackActive(mediaTrack.getId(), activeTrackIds)};
|
||||||
trackGroupInfos[i] =
|
trackGroups[i] =
|
||||||
new TrackGroupInfo(
|
new Tracks.Group(trackGroup, /* adaptiveSupported= */ false, trackSupport, trackSelected);
|
||||||
trackGroup, /* adaptiveSupported= */ false, trackSupport, trackSelected);
|
|
||||||
}
|
}
|
||||||
TracksInfo newTracksInfo = new TracksInfo(ImmutableList.copyOf(trackGroupInfos));
|
Tracks newTracks = new Tracks(ImmutableList.copyOf(trackGroups));
|
||||||
if (!newTracksInfo.equals(currentTracksInfo)) {
|
if (!newTracks.equals(currentTracks)) {
|
||||||
currentTracksInfo = newTracksInfo;
|
currentTracks = newTracks;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -442,10 +442,10 @@ public class ForwardingPlayer implements Player {
|
|||||||
player.release();
|
player.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Calls {@link Player#getCurrentTracksInfo()} on the delegate and returns the result. */
|
/** Calls {@link Player#getCurrentTracks()} on the delegate and returns the result. */
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
return player.getCurrentTracksInfo();
|
return player.getCurrentTracks();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Calls {@link Player#getTrackSelectionParameters()} on the delegate and returns the result. */
|
/** Calls {@link Player#getTrackSelectionParameters()} on the delegate and returns the result. */
|
||||||
@ -831,8 +831,8 @@ public class ForwardingPlayer implements Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
listener.onTracksInfoChanged(tracksInfo);
|
listener.onTracksChanged(tracks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -57,8 +57,8 @@ import java.util.List;
|
|||||||
* <ul>
|
* <ul>
|
||||||
* <li>They can provide a {@link Timeline} representing the structure of the media being played,
|
* <li>They can provide a {@link Timeline} representing the structure of the media being played,
|
||||||
* which can be obtained by calling {@link #getCurrentTimeline()}.
|
* which can be obtained by calling {@link #getCurrentTimeline()}.
|
||||||
* <li>They can provide a {@link TracksInfo} defining the currently available tracks and which are
|
* <li>They can provide a {@link Tracks} defining the currently available tracks and which are
|
||||||
* selected to be rendered, which can be obtained by calling {@link #getCurrentTracksInfo()}.
|
* selected to be rendered, which can be obtained by calling {@link #getCurrentTracks()}.
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public interface Player {
|
public interface Player {
|
||||||
@ -676,14 +676,14 @@ public interface Player {
|
|||||||
@Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {}
|
@Nullable MediaItem mediaItem, @MediaItemTransitionReason int reason) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the available or selected tracks change.
|
* Called when the tracks change.
|
||||||
*
|
*
|
||||||
* <p>{@link #onEvents(Player, Events)} will also be called to report this event along with
|
* <p>{@link #onEvents(Player, Events)} will also be called to report this event along with
|
||||||
* other events that happen in the same {@link Looper} message queue iteration.
|
* other events that happen in the same {@link Looper} message queue iteration.
|
||||||
*
|
*
|
||||||
* @param tracksInfo The available tracks information. Never null, but may be of length zero.
|
* @param tracks The available tracks information. Never null, but may be of length zero.
|
||||||
*/
|
*/
|
||||||
default void onTracksInfoChanged(TracksInfo tracksInfo) {}
|
default void onTracksChanged(Tracks tracks) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the combined {@link MediaMetadata} changes.
|
* Called when the combined {@link MediaMetadata} changes.
|
||||||
@ -1308,7 +1308,7 @@ public interface Player {
|
|||||||
int EVENT_TIMELINE_CHANGED = 0;
|
int EVENT_TIMELINE_CHANGED = 0;
|
||||||
/** {@link #getCurrentMediaItem()} changed or the player started repeating the current item. */
|
/** {@link #getCurrentMediaItem()} changed or the player started repeating the current item. */
|
||||||
int EVENT_MEDIA_ITEM_TRANSITION = 1;
|
int EVENT_MEDIA_ITEM_TRANSITION = 1;
|
||||||
/** {@link #getCurrentTracksInfo()} changed. */
|
/** {@link #getCurrentTracks()} changed. */
|
||||||
int EVENT_TRACKS_CHANGED = 2;
|
int EVENT_TRACKS_CHANGED = 2;
|
||||||
/** {@link #isLoading()} ()} changed. */
|
/** {@link #isLoading()} ()} changed. */
|
||||||
int EVENT_IS_LOADING_CHANGED = 3;
|
int EVENT_IS_LOADING_CHANGED = 3;
|
||||||
@ -2093,11 +2093,11 @@ public interface Player {
|
|||||||
void release();
|
void release();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns information about the current tracks.
|
* Returns the current tracks.
|
||||||
*
|
*
|
||||||
* @see Listener#onTracksInfoChanged(TracksInfo)
|
* @see Listener#onTracksChanged(Tracks)
|
||||||
*/
|
*/
|
||||||
TracksInfo getCurrentTracksInfo();
|
Tracks getCurrentTracks();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the parameters constraining the track selection.
|
* Returns the parameters constraining the track selection.
|
||||||
|
@ -92,7 +92,7 @@ public final class TrackSelectionOverride implements Bundleable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the {@link C.TrackType} of the overridden track group. */
|
/** Returns the {@link C.TrackType} of the overridden track group. */
|
||||||
public @C.TrackType int getTrackType() {
|
public @C.TrackType int getType() {
|
||||||
return trackGroup.type;
|
return trackGroup.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,7 +684,7 @@ public class TrackSelectionParameters implements Bundleable {
|
|||||||
|
|
||||||
/** Sets an override, replacing all existing overrides with the same track type. */
|
/** Sets an override, replacing all existing overrides with the same track type. */
|
||||||
public Builder setOverrideForType(TrackSelectionOverride override) {
|
public Builder setOverrideForType(TrackSelectionOverride override) {
|
||||||
clearOverridesOfType(override.getTrackType());
|
clearOverridesOfType(override.getType());
|
||||||
overrides.put(override.trackGroup, override);
|
overrides.put(override.trackGroup, override);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -700,7 +700,7 @@ public class TrackSelectionParameters implements Bundleable {
|
|||||||
Iterator<TrackSelectionOverride> it = overrides.values().iterator();
|
Iterator<TrackSelectionOverride> it = overrides.values().iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
TrackSelectionOverride override = it.next();
|
TrackSelectionOverride override = it.next();
|
||||||
if (override.getTrackType() == trackType) {
|
if (override.getType() == trackType) {
|
||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,14 +37,14 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Information about groups of tracks. */
|
/** Information about groups of tracks. */
|
||||||
public final class TracksInfo implements Bundleable {
|
public final class Tracks implements Bundleable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about a single group of tracks, including the underlying {@link TrackGroup}, the
|
* Information about a single group of tracks, including the underlying {@link TrackGroup}, the
|
||||||
* level to which each track is supported by the player, and whether any of the tracks are
|
* level to which each track is supported by the player, and whether any of the tracks are
|
||||||
* selected.
|
* selected.
|
||||||
*/
|
*/
|
||||||
public static final class TrackGroupInfo implements Bundleable {
|
public static final class Group implements Bundleable {
|
||||||
|
|
||||||
/** The number of tracks in the group. */
|
/** The number of tracks in the group. */
|
||||||
public final int length;
|
public final int length;
|
||||||
@ -64,7 +64,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
* @param trackSelected Whether each track in the {@code trackGroup} is selected.
|
* @param trackSelected Whether each track in the {@code trackGroup} is selected.
|
||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public TrackGroupInfo(
|
public Group(
|
||||||
TrackGroup trackGroup,
|
TrackGroup trackGroup,
|
||||||
boolean adaptiveSupported,
|
boolean adaptiveSupported,
|
||||||
@C.FormatSupport int[] trackSupport,
|
@C.FormatSupport int[] trackSupport,
|
||||||
@ -85,7 +85,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
/**
|
/**
|
||||||
* Returns the {@link Format} for a specified track.
|
* Returns the {@link Format} for a specified track.
|
||||||
*
|
*
|
||||||
* @param trackIndex The index of the track in the {@link TrackGroup}.
|
* @param trackIndex The index of the track in the group.
|
||||||
* @return The {@link Format} of the track.
|
* @return The {@link Format} of the track.
|
||||||
*/
|
*/
|
||||||
public Format getTrackFormat(int trackIndex) {
|
public Format getTrackFormat(int trackIndex) {
|
||||||
@ -95,7 +95,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
/**
|
/**
|
||||||
* Returns the level of support for a specified track.
|
* Returns the level of support for a specified track.
|
||||||
*
|
*
|
||||||
* @param trackIndex The index of the track in the {@link TrackGroup}.
|
* @param trackIndex The index of the track in the group.
|
||||||
* @return The {@link C.FormatSupport} of the track.
|
* @return The {@link C.FormatSupport} of the track.
|
||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
@ -107,7 +107,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
* Returns whether a specified track is supported for playback, without exceeding the advertised
|
* Returns whether a specified track is supported for playback, without exceeding the advertised
|
||||||
* capabilities of the device. Equivalent to {@code isTrackSupported(trackIndex, false)}.
|
* capabilities of the device. Equivalent to {@code isTrackSupported(trackIndex, false)}.
|
||||||
*
|
*
|
||||||
* @param trackIndex The index of the track in the {@link TrackGroup}.
|
* @param trackIndex The index of the track in the group.
|
||||||
* @return True if the track's format can be played, false otherwise.
|
* @return True if the track's format can be played, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isTrackSupported(int trackIndex) {
|
public boolean isTrackSupported(int trackIndex) {
|
||||||
@ -117,7 +117,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
/**
|
/**
|
||||||
* Returns whether a specified track is supported for playback.
|
* Returns whether a specified track is supported for playback.
|
||||||
*
|
*
|
||||||
* @param trackIndex The index of the track in the {@link TrackGroup}.
|
* @param trackIndex The index of the track in the group.
|
||||||
* @param allowExceedsCapabilities Whether to consider the track as supported if it has a
|
* @param allowExceedsCapabilities Whether to consider the track as supported if it has a
|
||||||
* supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised
|
* supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised
|
||||||
* capabilities of the device. For example, a video track for which there's a corresponding
|
* capabilities of the device. For example, a video track for which there's a corresponding
|
||||||
@ -178,7 +178,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
* playing, however some player implementations have ways of getting such information. For
|
* playing, however some player implementations have ways of getting such information. For
|
||||||
* example, ExoPlayer provides this information via {@code ExoTrackSelection.getSelectedFormat}.
|
* example, ExoPlayer provides this information via {@code ExoTrackSelection.getSelectedFormat}.
|
||||||
*
|
*
|
||||||
* @param trackIndex The index of the track in the {@link TrackGroup}.
|
* @param trackIndex The index of the track in the group.
|
||||||
* @return True if the track is selected, false otherwise.
|
* @return True if the track is selected, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isTrackSelected(int trackIndex) {
|
public boolean isTrackSelected(int trackIndex) {
|
||||||
@ -186,7 +186,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the {@link C.TrackType} of the group. */
|
/** Returns the {@link C.TrackType} of the group. */
|
||||||
public @C.TrackType int getTrackType() {
|
public @C.TrackType int getType() {
|
||||||
return trackGroup.type;
|
return trackGroup.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
if (other == null || getClass() != other.getClass()) {
|
if (other == null || getClass() != other.getClass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
TrackGroupInfo that = (TrackGroupInfo) other;
|
Group that = (Group) other;
|
||||||
return adaptiveSupported == that.adaptiveSupported
|
return adaptiveSupported == that.adaptiveSupported
|
||||||
&& trackGroup.equals(that.trackGroup)
|
&& trackGroup.equals(that.trackGroup)
|
||||||
&& Arrays.equals(trackSupport, that.trackSupport)
|
&& Arrays.equals(trackSupport, that.trackSupport)
|
||||||
@ -241,9 +241,9 @@ public final class TracksInfo implements Bundleable {
|
|||||||
return bundle;
|
return bundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Object that can restores a {@code TracksInfo} from a {@link Bundle}. */
|
/** Object that can restore a group of tracks from a {@link Bundle}. */
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public static final Creator<TrackGroupInfo> CREATOR =
|
public static final Creator<Group> CREATOR =
|
||||||
bundle -> {
|
bundle -> {
|
||||||
TrackGroup trackGroup =
|
TrackGroup trackGroup =
|
||||||
fromNullableBundle(
|
fromNullableBundle(
|
||||||
@ -258,7 +258,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
new boolean[trackGroup.length]);
|
new boolean[trackGroup.length]);
|
||||||
boolean adaptiveSupported =
|
boolean adaptiveSupported =
|
||||||
bundle.getBoolean(keyForField(FIELD_ADAPTIVE_SUPPORTED), false);
|
bundle.getBoolean(keyForField(FIELD_ADAPTIVE_SUPPORTED), false);
|
||||||
return new TrackGroupInfo(trackGroup, adaptiveSupported, trackSupport, selected);
|
return new Group(trackGroup, adaptiveSupported, trackSupport, selected);
|
||||||
};
|
};
|
||||||
|
|
||||||
private static String keyForField(@FieldNumber int field) {
|
private static String keyForField(@FieldNumber int field) {
|
||||||
@ -266,31 +266,35 @@ public final class TracksInfo implements Bundleable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An {@code TrackInfo} that contains no tracks. */
|
/** Empty tracks. */
|
||||||
@UnstableApi public static final TracksInfo EMPTY = new TracksInfo(ImmutableList.of());
|
@UnstableApi public static final Tracks EMPTY = new Tracks(ImmutableList.of());
|
||||||
|
|
||||||
private final ImmutableList<TrackGroupInfo> trackGroupInfos;
|
private final ImmutableList<Group> groups;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance.
|
* Constructs an instance.
|
||||||
*
|
*
|
||||||
* @param trackGroupInfos The {@link TrackGroupInfo TrackGroupInfos} describing the groups of
|
* @param groups The {@link Group groups} of tracks.
|
||||||
* tracks.
|
|
||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public TracksInfo(List<TrackGroupInfo> trackGroupInfos) {
|
public Tracks(List<Group> groups) {
|
||||||
this.trackGroupInfos = ImmutableList.copyOf(trackGroupInfos);
|
this.groups = ImmutableList.copyOf(groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the {@link TrackGroupInfo TrackGroupInfos} describing the groups of tracks. */
|
/** Returns the {@link Group groups} of tracks. */
|
||||||
public ImmutableList<TrackGroupInfo> getTrackGroupInfos() {
|
public ImmutableList<Group> getGroups() {
|
||||||
return trackGroupInfos;
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns {@code true} if there are no tracks, and {@code false} otherwise. */
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return groups.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if there are tracks of type {@code trackType}, and false otherwise. */
|
/** Returns true if there are tracks of type {@code trackType}, and false otherwise. */
|
||||||
public boolean containsType(@C.TrackType int trackType) {
|
public boolean containsType(@C.TrackType int trackType) {
|
||||||
for (int i = 0; i < trackGroupInfos.size(); i++) {
|
for (int i = 0; i < groups.size(); i++) {
|
||||||
if (trackGroupInfos.get(i).getTrackType() == trackType) {
|
if (groups.get(i).getType() == trackType) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,7 +303,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if at least one track of type {@code trackType} is {@link
|
* Returns true if at least one track of type {@code trackType} is {@link
|
||||||
* TrackGroupInfo#isTrackSupported(int) supported}.
|
* Group#isTrackSupported(int) supported}.
|
||||||
*/
|
*/
|
||||||
public boolean isTypeSupported(@C.TrackType int trackType) {
|
public boolean isTypeSupported(@C.TrackType int trackType) {
|
||||||
return isTypeSupported(trackType, /* allowExceedsCapabilities= */ false);
|
return isTypeSupported(trackType, /* allowExceedsCapabilities= */ false);
|
||||||
@ -307,7 +311,7 @@ public final class TracksInfo implements Bundleable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if at least one track of type {@code trackType} is {@link
|
* Returns true if at least one track of type {@code trackType} is {@link
|
||||||
* TrackGroupInfo#isTrackSupported(int, boolean) supported}.
|
* Group#isTrackSupported(int, boolean) supported}.
|
||||||
*
|
*
|
||||||
* @param allowExceedsCapabilities Whether to consider the track as supported if it has a
|
* @param allowExceedsCapabilities Whether to consider the track as supported if it has a
|
||||||
* supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised
|
* supported {@link Format#sampleMimeType MIME type}, but otherwise exceeds the advertised
|
||||||
@ -316,9 +320,9 @@ public final class TracksInfo implements Bundleable {
|
|||||||
* Such tracks may be playable in some cases.
|
* Such tracks may be playable in some cases.
|
||||||
*/
|
*/
|
||||||
public boolean isTypeSupported(@C.TrackType int trackType, boolean allowExceedsCapabilities) {
|
public boolean isTypeSupported(@C.TrackType int trackType, boolean allowExceedsCapabilities) {
|
||||||
for (int i = 0; i < trackGroupInfos.size(); i++) {
|
for (int i = 0; i < groups.size(); i++) {
|
||||||
if (trackGroupInfos.get(i).getTrackType() == trackType) {
|
if (groups.get(i).getType() == trackType) {
|
||||||
if (trackGroupInfos.get(i).isSupported(allowExceedsCapabilities)) {
|
if (groups.get(i).isSupported(allowExceedsCapabilities)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -348,9 +352,9 @@ public final class TracksInfo implements Bundleable {
|
|||||||
|
|
||||||
/** Returns true if at least one track of the type {@code trackType} is selected for playback. */
|
/** Returns true if at least one track of the type {@code trackType} is selected for playback. */
|
||||||
public boolean isTypeSelected(@C.TrackType int trackType) {
|
public boolean isTypeSelected(@C.TrackType int trackType) {
|
||||||
for (int i = 0; i < trackGroupInfos.size(); i++) {
|
for (int i = 0; i < groups.size(); i++) {
|
||||||
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(i);
|
Group group = groups.get(i);
|
||||||
if (trackGroupInfo.isSelected() && trackGroupInfo.getTrackType() == trackType) {
|
if (group.isSelected() && group.getType() == trackType) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,13 +369,13 @@ public final class TracksInfo implements Bundleable {
|
|||||||
if (other == null || getClass() != other.getClass()) {
|
if (other == null || getClass() != other.getClass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
TracksInfo that = (TracksInfo) other;
|
Tracks that = (Tracks) other;
|
||||||
return trackGroupInfos.equals(that.trackGroupInfos);
|
return groups.equals(that.groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return trackGroupInfos.hashCode();
|
return groups.hashCode();
|
||||||
}
|
}
|
||||||
// Bundleable implementation.
|
// Bundleable implementation.
|
||||||
|
|
||||||
@ -379,31 +383,30 @@ public final class TracksInfo implements Bundleable {
|
|||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@Target(TYPE_USE)
|
@Target(TYPE_USE)
|
||||||
@IntDef({
|
@IntDef({
|
||||||
FIELD_TRACK_GROUP_INFOS,
|
FIELD_TRACK_GROUPS,
|
||||||
})
|
})
|
||||||
private @interface FieldNumber {}
|
private @interface FieldNumber {}
|
||||||
|
|
||||||
private static final int FIELD_TRACK_GROUP_INFOS = 0;
|
private static final int FIELD_TRACK_GROUPS = 0;
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
@Override
|
@Override
|
||||||
public Bundle toBundle() {
|
public Bundle toBundle() {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putParcelableArrayList(
|
bundle.putParcelableArrayList(keyForField(FIELD_TRACK_GROUPS), toBundleArrayList(groups));
|
||||||
keyForField(FIELD_TRACK_GROUP_INFOS), toBundleArrayList(trackGroupInfos));
|
|
||||||
return bundle;
|
return bundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Object that can restore a {@code TracksInfo} from a {@link Bundle}. */
|
/** Object that can restore tracks from a {@link Bundle}. */
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public static final Creator<TracksInfo> CREATOR =
|
public static final Creator<Tracks> CREATOR =
|
||||||
bundle -> {
|
bundle -> {
|
||||||
List<TrackGroupInfo> trackGroupInfos =
|
List<Group> groups =
|
||||||
fromBundleNullableList(
|
fromBundleNullableList(
|
||||||
TrackGroupInfo.CREATOR,
|
Group.CREATOR,
|
||||||
bundle.getParcelableArrayList(keyForField(FIELD_TRACK_GROUP_INFOS)),
|
bundle.getParcelableArrayList(keyForField(FIELD_TRACK_GROUPS)),
|
||||||
/* defaultValue= */ ImmutableList.of());
|
/* defaultValue= */ ImmutableList.of());
|
||||||
return new TracksInfo(trackGroupInfos);
|
return new Tracks(groups);
|
||||||
};
|
};
|
||||||
|
|
||||||
private static String keyForField(@FieldNumber int field) {
|
private static String keyForField(@FieldNumber int field) {
|
@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2021 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package androidx.media3.common;
|
|
||||||
|
|
||||||
import static androidx.media3.common.MimeTypes.AUDIO_AAC;
|
|
||||||
import static androidx.media3.common.MimeTypes.VIDEO_H264;
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
|
|
||||||
import androidx.media3.common.TracksInfo.TrackGroupInfo;
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
/** Unit test for {@link TracksInfo}. */
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
public class TracksInfoTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void roundTripViaBundle_ofEmptyTracksInfo_yieldsEqualInstance() {
|
|
||||||
TracksInfo before = TracksInfo.EMPTY;
|
|
||||||
TracksInfo after = TracksInfo.CREATOR.fromBundle(before.toBundle());
|
|
||||||
assertThat(after).isEqualTo(before);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void roundTripViaBundle_ofTracksInfo_yieldsEqualInstance() {
|
|
||||||
TracksInfo before =
|
|
||||||
new TracksInfo(
|
|
||||||
ImmutableList.of(
|
|
||||||
new TrackGroupInfo(
|
|
||||||
new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()),
|
|
||||||
/* adaptiveSupported= */ false,
|
|
||||||
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
|
|
||||||
/* tracksSelected= */ new boolean[] {true}),
|
|
||||||
new TrackGroupInfo(
|
|
||||||
new TrackGroup(
|
|
||||||
new Format.Builder().setSampleMimeType(VIDEO_H264).build(),
|
|
||||||
new Format.Builder().setSampleMimeType(VIDEO_H264).build()),
|
|
||||||
/* adaptiveSupported= */ true,
|
|
||||||
new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_UNSUPPORTED_TYPE},
|
|
||||||
/* tracksSelected= */ new boolean[] {false, true})));
|
|
||||||
TracksInfo after = TracksInfo.CREATOR.fromBundle(before.toBundle());
|
|
||||||
assertThat(after).isEqualTo(before);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void tracksInfoGetters_withoutTrack_returnExpectedValues() {
|
|
||||||
TracksInfo tracksInfo = new TracksInfo(ImmutableList.of());
|
|
||||||
|
|
||||||
assertThat(tracksInfo.containsType(C.TRACK_TYPE_AUDIO)).isFalse();
|
|
||||||
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_AUDIO)).isFalse();
|
|
||||||
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true))
|
|
||||||
.isFalse();
|
|
||||||
assertThat(tracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO)).isFalse();
|
|
||||||
ImmutableList<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
|
||||||
assertThat(trackGroupInfos).isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void tracksInfo_emptyStaticInstance_isEmpty() {
|
|
||||||
TracksInfo tracksInfo = TracksInfo.EMPTY;
|
|
||||||
|
|
||||||
assertThat(tracksInfo.getTrackGroupInfos()).isEmpty();
|
|
||||||
assertThat(tracksInfo).isEqualTo(new TracksInfo(ImmutableList.of()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void tracksInfoGetters_ofComplexTracksInfo_returnExpectedValues() {
|
|
||||||
TrackGroupInfo trackGroupInfo0 =
|
|
||||||
new TrackGroupInfo(
|
|
||||||
new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()),
|
|
||||||
/* adaptiveSupported= */ false,
|
|
||||||
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
|
|
||||||
/* tracksSelected= */ new boolean[] {false});
|
|
||||||
TrackGroupInfo trackGroupInfo1 =
|
|
||||||
new TrackGroupInfo(
|
|
||||||
new TrackGroup(
|
|
||||||
new Format.Builder().setSampleMimeType(VIDEO_H264).build(),
|
|
||||||
new Format.Builder().setSampleMimeType(VIDEO_H264).build()),
|
|
||||||
/* adaptiveSupported= */ true,
|
|
||||||
new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_HANDLED},
|
|
||||||
/* tracksSelected= */ new boolean[] {false, true});
|
|
||||||
TracksInfo tracksInfo = new TracksInfo(ImmutableList.of(trackGroupInfo0, trackGroupInfo1));
|
|
||||||
|
|
||||||
assertThat(tracksInfo.containsType(C.TRACK_TYPE_AUDIO)).isTrue();
|
|
||||||
assertThat(tracksInfo.containsType(C.TRACK_TYPE_VIDEO)).isTrue();
|
|
||||||
assertThat(tracksInfo.containsType(C.TRACK_TYPE_TEXT)).isFalse();
|
|
||||||
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_AUDIO)).isFalse();
|
|
||||||
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_VIDEO)).isTrue();
|
|
||||||
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_TEXT)).isFalse();
|
|
||||||
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true))
|
|
||||||
.isTrue();
|
|
||||||
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true))
|
|
||||||
.isTrue();
|
|
||||||
assertThat(tracksInfo.isTypeSupported(C.TRACK_TYPE_TEXT, /* allowExceedsCapabilities= */ true))
|
|
||||||
.isFalse();
|
|
||||||
assertThat(tracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO)).isFalse();
|
|
||||||
assertThat(tracksInfo.isTypeSelected(C.TRACK_TYPE_VIDEO)).isTrue();
|
|
||||||
ImmutableList<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
|
||||||
assertThat(trackGroupInfos).hasSize(2);
|
|
||||||
assertThat(trackGroupInfos.get(0)).isSameInstanceAs(trackGroupInfo0);
|
|
||||||
assertThat(trackGroupInfos.get(1)).isSameInstanceAs(trackGroupInfo1);
|
|
||||||
assertThat(trackGroupInfos.get(0).isTrackSupported(0)).isFalse();
|
|
||||||
assertThat(trackGroupInfos.get(1).isTrackSupported(0)).isFalse();
|
|
||||||
assertThat(trackGroupInfos.get(1).isTrackSupported(1)).isTrue();
|
|
||||||
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(C.FORMAT_EXCEEDS_CAPABILITIES);
|
|
||||||
assertThat(trackGroupInfos.get(1).getTrackSupport(0)).isEqualTo(C.FORMAT_UNSUPPORTED_DRM);
|
|
||||||
assertThat(trackGroupInfos.get(1).getTrackSupport(1)).isEqualTo(C.FORMAT_HANDLED);
|
|
||||||
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isFalse();
|
|
||||||
assertThat(trackGroupInfos.get(1).isTrackSelected(0)).isFalse();
|
|
||||||
assertThat(trackGroupInfos.get(1).isTrackSelected(1)).isTrue();
|
|
||||||
assertThat(trackGroupInfos.get(0).getTrackType()).isEqualTo(C.TRACK_TYPE_AUDIO);
|
|
||||||
assertThat(trackGroupInfos.get(1).getTrackType()).isEqualTo(C.TRACK_TYPE_VIDEO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that {@link TrackGroupInfo#isAdaptiveSupported} returns false if the group only contains
|
|
||||||
* a single track, even if true is passed to the constructor.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void trackGroupInfo_withSingleTrack_isNotAdaptive() {
|
|
||||||
TrackGroupInfo trackGroupInfo0 =
|
|
||||||
new TrackGroupInfo(
|
|
||||||
new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()),
|
|
||||||
/* adaptiveSupported= */ true,
|
|
||||||
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
|
|
||||||
/* tracksSelected= */ new boolean[] {false});
|
|
||||||
assertThat(trackGroupInfo0.isAdaptiveSupported()).isFalse();
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package androidx.media3.common;
|
||||||
|
|
||||||
|
import static androidx.media3.common.MimeTypes.AUDIO_AAC;
|
||||||
|
import static androidx.media3.common.MimeTypes.VIDEO_H264;
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
/** Unit test for {@link Tracks}. */
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class TracksTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void roundTripViaBundle_ofEmptyTracks_yieldsEqualInstance() {
|
||||||
|
Tracks before = Tracks.EMPTY;
|
||||||
|
Tracks after = Tracks.CREATOR.fromBundle(before.toBundle());
|
||||||
|
assertThat(after).isEqualTo(before);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void roundTripViaBundle_ofTracks_yieldsEqualInstance() {
|
||||||
|
Tracks before =
|
||||||
|
new Tracks(
|
||||||
|
ImmutableList.of(
|
||||||
|
new Tracks.Group(
|
||||||
|
new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()),
|
||||||
|
/* adaptiveSupported= */ false,
|
||||||
|
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
|
||||||
|
/* trackSelected= */ new boolean[] {true}),
|
||||||
|
new Tracks.Group(
|
||||||
|
new TrackGroup(
|
||||||
|
new Format.Builder().setSampleMimeType(VIDEO_H264).build(),
|
||||||
|
new Format.Builder().setSampleMimeType(VIDEO_H264).build()),
|
||||||
|
/* adaptiveSupported= */ true,
|
||||||
|
new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_UNSUPPORTED_TYPE},
|
||||||
|
/* trackSelected= */ new boolean[] {false, true})));
|
||||||
|
Tracks after = Tracks.CREATOR.fromBundle(before.toBundle());
|
||||||
|
assertThat(after).isEqualTo(before);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getters_withoutTrack_returnExpectedValues() {
|
||||||
|
Tracks tracks = new Tracks(ImmutableList.of());
|
||||||
|
|
||||||
|
assertThat(tracks.containsType(C.TRACK_TYPE_AUDIO)).isFalse();
|
||||||
|
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_AUDIO)).isFalse();
|
||||||
|
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true))
|
||||||
|
.isFalse();
|
||||||
|
assertThat(tracks.isTypeSelected(C.TRACK_TYPE_AUDIO)).isFalse();
|
||||||
|
ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
|
||||||
|
assertThat(trackGroups).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void emptyStaticInstance_isEmpty() {
|
||||||
|
Tracks tracks = Tracks.EMPTY;
|
||||||
|
|
||||||
|
assertThat(tracks.getGroups()).isEmpty();
|
||||||
|
assertThat(tracks).isEqualTo(new Tracks(ImmutableList.of()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getters_ofComplexTracks_returnExpectedValues() {
|
||||||
|
Tracks.Group trackGroup0 =
|
||||||
|
new Tracks.Group(
|
||||||
|
new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()),
|
||||||
|
/* adaptiveSupported= */ false,
|
||||||
|
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
|
||||||
|
/* trackSelected= */ new boolean[] {false});
|
||||||
|
Tracks.Group trackGroup1 =
|
||||||
|
new Tracks.Group(
|
||||||
|
new TrackGroup(
|
||||||
|
new Format.Builder().setSampleMimeType(VIDEO_H264).build(),
|
||||||
|
new Format.Builder().setSampleMimeType(VIDEO_H264).build()),
|
||||||
|
/* adaptiveSupported= */ true,
|
||||||
|
new int[] {C.FORMAT_UNSUPPORTED_DRM, C.FORMAT_HANDLED},
|
||||||
|
/* trackSelected= */ new boolean[] {false, true});
|
||||||
|
Tracks tracks = new Tracks(ImmutableList.of(trackGroup0, trackGroup1));
|
||||||
|
|
||||||
|
assertThat(tracks.containsType(C.TRACK_TYPE_AUDIO)).isTrue();
|
||||||
|
assertThat(tracks.containsType(C.TRACK_TYPE_VIDEO)).isTrue();
|
||||||
|
assertThat(tracks.containsType(C.TRACK_TYPE_TEXT)).isFalse();
|
||||||
|
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_AUDIO)).isFalse();
|
||||||
|
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_VIDEO)).isTrue();
|
||||||
|
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_TEXT)).isFalse();
|
||||||
|
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true))
|
||||||
|
.isTrue();
|
||||||
|
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true))
|
||||||
|
.isTrue();
|
||||||
|
assertThat(tracks.isTypeSupported(C.TRACK_TYPE_TEXT, /* allowExceedsCapabilities= */ true))
|
||||||
|
.isFalse();
|
||||||
|
assertThat(tracks.isTypeSelected(C.TRACK_TYPE_AUDIO)).isFalse();
|
||||||
|
assertThat(tracks.isTypeSelected(C.TRACK_TYPE_VIDEO)).isTrue();
|
||||||
|
ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
|
||||||
|
assertThat(trackGroups).hasSize(2);
|
||||||
|
assertThat(trackGroups.get(0)).isSameInstanceAs(trackGroup0);
|
||||||
|
assertThat(trackGroups.get(1)).isSameInstanceAs(trackGroup1);
|
||||||
|
assertThat(trackGroups.get(0).isTrackSupported(0)).isFalse();
|
||||||
|
assertThat(trackGroups.get(1).isTrackSupported(0)).isFalse();
|
||||||
|
assertThat(trackGroups.get(1).isTrackSupported(1)).isTrue();
|
||||||
|
assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(C.FORMAT_EXCEEDS_CAPABILITIES);
|
||||||
|
assertThat(trackGroups.get(1).getTrackSupport(0)).isEqualTo(C.FORMAT_UNSUPPORTED_DRM);
|
||||||
|
assertThat(trackGroups.get(1).getTrackSupport(1)).isEqualTo(C.FORMAT_HANDLED);
|
||||||
|
assertThat(trackGroups.get(0).isTrackSelected(0)).isFalse();
|
||||||
|
assertThat(trackGroups.get(1).isTrackSelected(0)).isFalse();
|
||||||
|
assertThat(trackGroups.get(1).isTrackSelected(1)).isTrue();
|
||||||
|
assertThat(trackGroups.get(0).getType()).isEqualTo(C.TRACK_TYPE_AUDIO);
|
||||||
|
assertThat(trackGroups.get(1).getType()).isEqualTo(C.TRACK_TYPE_VIDEO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that {@link Tracks.Group#isAdaptiveSupported} returns false if the group only contains a
|
||||||
|
* single track, even if true is passed to the constructor.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void groupWithSingleTrack_isNotAdaptive() {
|
||||||
|
Tracks.Group trackGroup =
|
||||||
|
new Tracks.Group(
|
||||||
|
new TrackGroup(new Format.Builder().setSampleMimeType(AUDIO_AAC).build()),
|
||||||
|
/* adaptiveSupported= */ true,
|
||||||
|
new int[] {C.FORMAT_EXCEEDS_CAPABILITIES},
|
||||||
|
/* trackSelected= */ new boolean[] {false});
|
||||||
|
assertThat(trackGroup.isAdaptiveSupported()).isFalse();
|
||||||
|
}
|
||||||
|
}
|
@ -38,7 +38,7 @@ import androidx.media3.common.MediaItem;
|
|||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.PriorityTaskManager;
|
import androidx.media3.common.PriorityTaskManager;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.text.Cue;
|
import androidx.media3.common.text.Cue;
|
||||||
import androidx.media3.common.util.Clock;
|
import androidx.media3.common.util.Clock;
|
||||||
@ -1222,8 +1222,8 @@ public interface ExoPlayer extends Player {
|
|||||||
/**
|
/**
|
||||||
* Returns the available track groups.
|
* Returns the available track groups.
|
||||||
*
|
*
|
||||||
* @see Listener#onTracksInfoChanged(TracksInfo)
|
* @see Listener#onTracksChanged(Tracks)
|
||||||
* @deprecated Use {@link #getCurrentTracksInfo()}.
|
* @deprecated Use {@link #getCurrentTracks()}.
|
||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -1233,8 +1233,8 @@ public interface ExoPlayer extends Player {
|
|||||||
* Returns the current track selections for each renderer, which may include {@code null} elements
|
* Returns the current track selections for each renderer, which may include {@code null} elements
|
||||||
* if some renderers do not have any selected tracks.
|
* if some renderers do not have any selected tracks.
|
||||||
*
|
*
|
||||||
* @see Listener#onTracksInfoChanged(TracksInfo)
|
* @see Listener#onTracksChanged(Tracks)
|
||||||
* @deprecated Use {@link #getCurrentTracksInfo()}.
|
* @deprecated Use {@link #getCurrentTracks()}.
|
||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -70,7 +70,7 @@ import androidx.media3.common.PriorityTaskManager;
|
|||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.text.Cue;
|
import androidx.media3.common.text.Cue;
|
||||||
import androidx.media3.common.util.Assertions;
|
import androidx.media3.common.util.Assertions;
|
||||||
@ -277,7 +277,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
new TrackSelectorResult(
|
new TrackSelectorResult(
|
||||||
new RendererConfiguration[renderers.length],
|
new RendererConfiguration[renderers.length],
|
||||||
new ExoTrackSelection[renderers.length],
|
new ExoTrackSelection[renderers.length],
|
||||||
TracksInfo.EMPTY,
|
Tracks.EMPTY,
|
||||||
/* info= */ null);
|
/* info= */ null);
|
||||||
period = new Timeline.Period();
|
period = new Timeline.Period();
|
||||||
permanentAvailableCommands =
|
permanentAvailableCommands =
|
||||||
@ -1147,9 +1147,9 @@ import java.util.concurrent.TimeoutException;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
return playbackInfo.trackSelectorResult.tracksInfo;
|
return playbackInfo.trackSelectorResult.tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1898,7 +1898,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
trackSelector.onSelectionActivated(newPlaybackInfo.trackSelectorResult.info);
|
trackSelector.onSelectionActivated(newPlaybackInfo.trackSelectorResult.info);
|
||||||
listeners.queueEvent(
|
listeners.queueEvent(
|
||||||
Player.EVENT_TRACKS_CHANGED,
|
Player.EVENT_TRACKS_CHANGED,
|
||||||
listener -> listener.onTracksInfoChanged(newPlaybackInfo.trackSelectorResult.tracksInfo));
|
listener -> listener.onTracksChanged(newPlaybackInfo.trackSelectorResult.tracks));
|
||||||
}
|
}
|
||||||
if (metadataChanged) {
|
if (metadataChanged) {
|
||||||
final MediaMetadata finalMediaMetadata = mediaMetadata;
|
final MediaMetadata finalMediaMetadata = mediaMetadata;
|
||||||
|
@ -36,7 +36,7 @@ import androidx.media3.common.PlaybackParameters;
|
|||||||
import androidx.media3.common.PriorityTaskManager;
|
import androidx.media3.common.PriorityTaskManager;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.text.Cue;
|
import androidx.media3.common.text.Cue;
|
||||||
import androidx.media3.common.util.Clock;
|
import androidx.media3.common.util.Clock;
|
||||||
@ -1059,9 +1059,9 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
blockUntilConstructorFinished();
|
blockUntilConstructorFinished();
|
||||||
return player.getCurrentTracksInfo();
|
return player.getCurrentTracks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -46,7 +46,7 @@ import androidx.media3.common.Player.PlaybackSuppressionReason;
|
|||||||
import androidx.media3.common.Player.TimelineChangeReason;
|
import androidx.media3.common.Player.TimelineChangeReason;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.text.Cue;
|
import androidx.media3.common.text.Cue;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
@ -238,7 +238,7 @@ public interface AnalyticsListener {
|
|||||||
* {@link Player#getCurrentMediaItem()} changed or the player started repeating the current item.
|
* {@link Player#getCurrentMediaItem()} changed or the player started repeating the current item.
|
||||||
*/
|
*/
|
||||||
int EVENT_MEDIA_ITEM_TRANSITION = Player.EVENT_MEDIA_ITEM_TRANSITION;
|
int EVENT_MEDIA_ITEM_TRANSITION = Player.EVENT_MEDIA_ITEM_TRANSITION;
|
||||||
/** {@link Player#getCurrentTracksInfo()} changed. */
|
/** {@link Player#getCurrentTracks()} changed. */
|
||||||
int EVENT_TRACKS_CHANGED = Player.EVENT_TRACKS_CHANGED;
|
int EVENT_TRACKS_CHANGED = Player.EVENT_TRACKS_CHANGED;
|
||||||
/** {@link Player#isLoading()} ()} changed. */
|
/** {@link Player#isLoading()} ()} changed. */
|
||||||
int EVENT_IS_LOADING_CHANGED = Player.EVENT_IS_LOADING_CHANGED;
|
int EVENT_IS_LOADING_CHANGED = Player.EVENT_IS_LOADING_CHANGED;
|
||||||
@ -706,12 +706,12 @@ public interface AnalyticsListener {
|
|||||||
default void onPlayerErrorChanged(EventTime eventTime, @Nullable PlaybackException error) {}
|
default void onPlayerErrorChanged(EventTime eventTime, @Nullable PlaybackException error) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the available or selected tracks change.
|
* Called when the tracks change.
|
||||||
*
|
*
|
||||||
* @param eventTime The event time.
|
* @param eventTime The event time.
|
||||||
* @param tracksInfo The available tracks information. Never null, but may be of length zero.
|
* @param tracks The tracks. Never null, but may be of length zero.
|
||||||
*/
|
*/
|
||||||
default void onTracksInfoChanged(EventTime eventTime, TracksInfo tracksInfo) {}
|
default void onTracksChanged(EventTime eventTime, Tracks tracks) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when track selection parameters change.
|
* Called when track selection parameters change.
|
||||||
|
@ -39,7 +39,7 @@ import androidx.media3.common.Timeline;
|
|||||||
import androidx.media3.common.Timeline.Period;
|
import androidx.media3.common.Timeline.Period;
|
||||||
import androidx.media3.common.Timeline.Window;
|
import androidx.media3.common.Timeline.Window;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.text.Cue;
|
import androidx.media3.common.text.Cue;
|
||||||
import androidx.media3.common.util.Clock;
|
import androidx.media3.common.util.Clock;
|
||||||
@ -483,12 +483,12 @@ public class DefaultAnalyticsCollector implements AnalyticsCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
sendEvent(
|
sendEvent(
|
||||||
eventTime,
|
eventTime,
|
||||||
AnalyticsListener.EVENT_TRACKS_CHANGED,
|
AnalyticsListener.EVENT_TRACKS_CHANGED,
|
||||||
listener -> listener.onTracksInfoChanged(eventTime, tracksInfo));
|
listener -> listener.onTracksChanged(eventTime, tracks));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation") // Implementing deprecated method.
|
@SuppressWarnings("deprecation") // Implementing deprecated method.
|
||||||
|
@ -49,8 +49,7 @@ import androidx.media3.common.ParserException;
|
|||||||
import androidx.media3.common.PlaybackException;
|
import androidx.media3.common.PlaybackException;
|
||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.TracksInfo.TrackGroupInfo;
|
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.util.NetworkTypeObserver;
|
import androidx.media3.common.util.NetworkTypeObserver;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
@ -340,8 +339,7 @@ public final class MediaMetricsListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (events.contains(EVENT_TRACKS_CHANGED) && metricsBuilder != null) {
|
if (events.contains(EVENT_TRACKS_CHANGED) && metricsBuilder != null) {
|
||||||
@Nullable
|
@Nullable DrmInitData drmInitData = getDrmInitData(player.getCurrentTracks().getGroups());
|
||||||
DrmInitData drmInitData = getDrmInitData(player.getCurrentTracksInfo().getTrackGroupInfos());
|
|
||||||
if (drmInitData != null) {
|
if (drmInitData != null) {
|
||||||
castNonNull(metricsBuilder).setDrmType(getDrmType(drmInitData));
|
castNonNull(metricsBuilder).setDrmType(getDrmType(drmInitData));
|
||||||
}
|
}
|
||||||
@ -372,10 +370,10 @@ public final class MediaMetricsListener
|
|||||||
|
|
||||||
private void maybeReportTrackChanges(Player player, Events events, long realtimeMs) {
|
private void maybeReportTrackChanges(Player player, Events events, long realtimeMs) {
|
||||||
if (events.contains(EVENT_TRACKS_CHANGED)) {
|
if (events.contains(EVENT_TRACKS_CHANGED)) {
|
||||||
TracksInfo tracksInfo = player.getCurrentTracksInfo();
|
Tracks tracks = player.getCurrentTracks();
|
||||||
boolean isVideoSelected = tracksInfo.isTypeSelected(C.TRACK_TYPE_VIDEO);
|
boolean isVideoSelected = tracks.isTypeSelected(C.TRACK_TYPE_VIDEO);
|
||||||
boolean isAudioSelected = tracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO);
|
boolean isAudioSelected = tracks.isTypeSelected(C.TRACK_TYPE_AUDIO);
|
||||||
boolean isTextSelected = tracksInfo.isTypeSelected(C.TRACK_TYPE_TEXT);
|
boolean isTextSelected = tracks.isTypeSelected(C.TRACK_TYPE_TEXT);
|
||||||
if (isVideoSelected || isAudioSelected || isTextSelected) {
|
if (isVideoSelected || isAudioSelected || isTextSelected) {
|
||||||
// Ignore updates with insufficient information where no tracks are selected.
|
// Ignore updates with insufficient information where no tracks are selected.
|
||||||
if (!isVideoSelected) {
|
if (!isVideoSelected) {
|
||||||
@ -822,11 +820,11 @@ public final class MediaMetricsListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static DrmInitData getDrmInitData(ImmutableList<TrackGroupInfo> trackGroupInfos) {
|
private static DrmInitData getDrmInitData(ImmutableList<Tracks.Group> trackGroups) {
|
||||||
for (TrackGroupInfo trackGroupInfo : trackGroupInfos) {
|
for (Tracks.Group trackGroup : trackGroups) {
|
||||||
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) {
|
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
||||||
if (trackGroupInfo.isTrackSelected(trackIndex)) {
|
if (trackGroup.isTrackSelected(trackIndex)) {
|
||||||
@Nullable DrmInitData drmInitData = trackGroupInfo.getTrackFormat(trackIndex).drmInitData;
|
@Nullable DrmInitData drmInitData = trackGroup.getTrackFormat(trackIndex).drmInitData;
|
||||||
if (drmInitData != null) {
|
if (drmInitData != null) {
|
||||||
return drmInitData;
|
return drmInitData;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import androidx.media3.common.PlaybackException;
|
|||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.Timeline.Period;
|
import androidx.media3.common.Timeline.Period;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.util.Assertions;
|
import androidx.media3.common.util.Assertions;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
@ -524,11 +524,11 @@ public final class PlaybackStatsListener
|
|||||||
hasFatalError = false;
|
hasFatalError = false;
|
||||||
}
|
}
|
||||||
if (isForeground && !isInterruptedByAd) {
|
if (isForeground && !isInterruptedByAd) {
|
||||||
TracksInfo currentTracksInfo = player.getCurrentTracksInfo();
|
Tracks currentTracks = player.getCurrentTracks();
|
||||||
if (!currentTracksInfo.isTypeSelected(C.TRACK_TYPE_VIDEO)) {
|
if (!currentTracks.isTypeSelected(C.TRACK_TYPE_VIDEO)) {
|
||||||
maybeUpdateVideoFormat(eventTime, /* newFormat= */ null);
|
maybeUpdateVideoFormat(eventTime, /* newFormat= */ null);
|
||||||
}
|
}
|
||||||
if (!currentTracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO)) {
|
if (!currentTracks.isTypeSelected(C.TRACK_TYPE_AUDIO)) {
|
||||||
maybeUpdateAudioFormat(eventTime, /* newFormat= */ null);
|
maybeUpdateAudioFormat(eventTime, /* newFormat= */ null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ import androidx.media3.common.Timeline;
|
|||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TrackSelectionOverride;
|
import androidx.media3.common.TrackSelectionOverride;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.util.Assertions;
|
import androidx.media3.common.util.Assertions;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
@ -546,16 +546,16 @@ public final class DownloadHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link TracksInfo} for the given period. Must not be called until after preparation
|
* Returns {@link Tracks} for the given period. Must not be called until after preparation
|
||||||
* completes.
|
* completes.
|
||||||
*
|
*
|
||||||
* @param periodIndex The period index.
|
* @param periodIndex The period index.
|
||||||
* @return The {@link TracksInfo} for the period. May be {@link TracksInfo#EMPTY} for single
|
* @return The {@link Tracks} for the period. May be {@link Tracks#EMPTY} for single stream
|
||||||
* stream content.
|
* content.
|
||||||
*/
|
*/
|
||||||
public TracksInfo getTracksInfo(int periodIndex) {
|
public Tracks getTracks(int periodIndex) {
|
||||||
assertPreparedWithMedia();
|
assertPreparedWithMedia();
|
||||||
return TrackSelectionUtil.buildTracksInfo(
|
return TrackSelectionUtil.buildTracks(
|
||||||
mappedTrackInfos[periodIndex], immutableTrackSelectionsByPeriodAndRenderer[periodIndex]);
|
mappedTrackInfos[periodIndex], immutableTrackSelectionsByPeriodAndRenderer[periodIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1962,12 +1962,11 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
if (override == null) {
|
if (override == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@Nullable
|
@Nullable TrackSelectionOverride existingOverride = overridesByType.get(override.getType());
|
||||||
TrackSelectionOverride existingOverride = overridesByType.get(override.getTrackType());
|
|
||||||
// Only replace an existing override if it's empty and the one being considered is not.
|
// Only replace an existing override if it's empty and the one being considered is not.
|
||||||
if (existingOverride == null
|
if (existingOverride == null
|
||||||
|| (existingOverride.trackIndices.isEmpty() && !override.trackIndices.isEmpty())) {
|
|| (existingOverride.trackIndices.isEmpty() && !override.trackIndices.isEmpty())) {
|
||||||
overridesByType.put(override.getTrackType(), override);
|
overridesByType.put(override.getType(), override);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ import androidx.media3.common.C;
|
|||||||
import androidx.media3.common.C.FormatSupport;
|
import androidx.media3.common.C.FormatSupport;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.exoplayer.ExoPlaybackException;
|
import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
@ -427,9 +427,9 @@ public abstract class MappingTrackSelector extends TrackSelector {
|
|||||||
periodId,
|
periodId,
|
||||||
timeline);
|
timeline);
|
||||||
|
|
||||||
TracksInfo tracksInfo = TrackSelectionUtil.buildTracksInfo(mappedTrackInfo, result.second);
|
Tracks tracks = TrackSelectionUtil.buildTracks(mappedTrackInfo, result.second);
|
||||||
|
|
||||||
return new TrackSelectorResult(result.first, result.second, tracksInfo, mappedTrackInfo);
|
return new TrackSelectorResult(result.first, result.second, tracks, mappedTrackInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,8 +19,7 @@ import android.os.SystemClock;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.TracksInfo.TrackGroupInfo;
|
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.exoplayer.RendererCapabilities;
|
import androidx.media3.exoplayer.RendererCapabilities;
|
||||||
import androidx.media3.exoplayer.source.TrackGroupArray;
|
import androidx.media3.exoplayer.source.TrackGroupArray;
|
||||||
@ -136,16 +135,16 @@ public final class TrackSelectionUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link TracksInfo} built from {@link MappingTrackSelector.MappedTrackInfo} and {@link
|
* Returns {@link Tracks} built from {@link MappingTrackSelector.MappedTrackInfo} and {@link
|
||||||
* TrackSelection TrackSelections} for each renderer.
|
* TrackSelection TrackSelections} for each renderer.
|
||||||
*
|
*
|
||||||
* @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
|
* @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
|
||||||
* @param selections The track selections, indexed by renderer. A null entry indicates that a
|
* @param selections The track selections, indexed by renderer. A null entry indicates that a
|
||||||
* renderer does not have any selected tracks.
|
* renderer does not have any selected tracks.
|
||||||
* @return The corresponding {@link TracksInfo}.
|
* @return The corresponding {@link Tracks}.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"}) // Initialization of array of Lists.
|
@SuppressWarnings({"unchecked", "rawtypes"}) // Initialization of array of Lists.
|
||||||
public static TracksInfo buildTracksInfo(
|
public static Tracks buildTracks(
|
||||||
MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
|
MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
|
||||||
@NullableType TrackSelection[] selections) {
|
@NullableType TrackSelection[] selections) {
|
||||||
List<? extends TrackSelection>[] listSelections = new List[selections.length];
|
List<? extends TrackSelection>[] listSelections = new List[selections.length];
|
||||||
@ -153,22 +152,22 @@ public final class TrackSelectionUtil {
|
|||||||
@Nullable TrackSelection selection = selections[i];
|
@Nullable TrackSelection selection = selections[i];
|
||||||
listSelections[i] = selection != null ? ImmutableList.of(selection) : ImmutableList.of();
|
listSelections[i] = selection != null ? ImmutableList.of(selection) : ImmutableList.of();
|
||||||
}
|
}
|
||||||
return buildTracksInfo(mappedTrackInfo, listSelections);
|
return buildTracks(mappedTrackInfo, listSelections);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link TracksInfo} built from {@link MappingTrackSelector.MappedTrackInfo} and {@link
|
* Returns {@link Tracks} built from {@link MappingTrackSelector.MappedTrackInfo} and {@link
|
||||||
* TrackSelection TrackSelections} for each renderer.
|
* TrackSelection TrackSelections} for each renderer.
|
||||||
*
|
*
|
||||||
* @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
|
* @param mappedTrackInfo The {@link MappingTrackSelector.MappedTrackInfo}
|
||||||
* @param selections The track selections, indexed by renderer. Null entries are not permitted. An
|
* @param selections The track selections, indexed by renderer. Null entries are not permitted. An
|
||||||
* empty list indicates that a renderer does not have any selected tracks.
|
* empty list indicates that a renderer does not have any selected tracks.
|
||||||
* @return The corresponding {@link TracksInfo}.
|
* @return The corresponding {@link Tracks}.
|
||||||
*/
|
*/
|
||||||
public static TracksInfo buildTracksInfo(
|
public static Tracks buildTracks(
|
||||||
MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
|
MappingTrackSelector.MappedTrackInfo mappedTrackInfo,
|
||||||
List<? extends TrackSelection>[] selections) {
|
List<? extends TrackSelection>[] selections) {
|
||||||
ImmutableList.Builder<TrackGroupInfo> trackGroupInfos = new ImmutableList.Builder<>();
|
ImmutableList.Builder<Tracks.Group> trackGroups = new ImmutableList.Builder<>();
|
||||||
for (int rendererIndex = 0;
|
for (int rendererIndex = 0;
|
||||||
rendererIndex < mappedTrackInfo.getRendererCount();
|
rendererIndex < mappedTrackInfo.getRendererCount();
|
||||||
rendererIndex++) {
|
rendererIndex++) {
|
||||||
@ -196,8 +195,7 @@ public final class TrackSelectionUtil {
|
|||||||
}
|
}
|
||||||
selected[trackIndex] = isTrackSelected;
|
selected[trackIndex] = isTrackSelected;
|
||||||
}
|
}
|
||||||
trackGroupInfos.add(
|
trackGroups.add(new Tracks.Group(trackGroup, adaptiveSupported, trackSupport, selected));
|
||||||
new TrackGroupInfo(trackGroup, adaptiveSupported, trackSupport, selected));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TrackGroupArray unmappedTrackGroups = mappedTrackInfo.getUnmappedTrackGroups();
|
TrackGroupArray unmappedTrackGroups = mappedTrackInfo.getUnmappedTrackGroups();
|
||||||
@ -206,9 +204,9 @@ public final class TrackSelectionUtil {
|
|||||||
@C.FormatSupport int[] trackSupport = new int[trackGroup.length];
|
@C.FormatSupport int[] trackSupport = new int[trackGroup.length];
|
||||||
Arrays.fill(trackSupport, C.FORMAT_UNSUPPORTED_TYPE);
|
Arrays.fill(trackSupport, C.FORMAT_UNSUPPORTED_TYPE);
|
||||||
boolean[] selected = new boolean[trackGroup.length];
|
boolean[] selected = new boolean[trackGroup.length];
|
||||||
trackGroupInfos.add(
|
trackGroups.add(
|
||||||
new TrackGroupInfo(trackGroup, /* adaptiveSupported= */ false, trackSupport, selected));
|
new Tracks.Group(trackGroup, /* adaptiveSupported= */ false, trackSupport, selected));
|
||||||
}
|
}
|
||||||
return new TracksInfo(trackGroupInfos.build());
|
return new Tracks(trackGroups.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
package androidx.media3.exoplayer.trackselection;
|
package androidx.media3.exoplayer.trackselection;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.exoplayer.RendererConfiguration;
|
import androidx.media3.exoplayer.RendererConfiguration;
|
||||||
@ -36,7 +36,7 @@ public final class TrackSelectorResult {
|
|||||||
/** A {@link ExoTrackSelection} array containing the track selection for each renderer. */
|
/** A {@link ExoTrackSelection} array containing the track selection for each renderer. */
|
||||||
public final @NullableType ExoTrackSelection[] selections;
|
public final @NullableType ExoTrackSelection[] selections;
|
||||||
/** Describe the tracks and which one were selected. */
|
/** Describe the tracks and which one were selected. */
|
||||||
public final TracksInfo tracksInfo;
|
public final Tracks tracks;
|
||||||
/**
|
/**
|
||||||
* An opaque object that will be returned to {@link TrackSelector#onSelectionActivated(Object)}
|
* An opaque object that will be returned to {@link TrackSelector#onSelectionActivated(Object)}
|
||||||
* should the selections be activated.
|
* should the selections be activated.
|
||||||
@ -51,21 +51,21 @@ public final class TrackSelectorResult {
|
|||||||
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
|
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
|
||||||
* {@code null}.
|
* {@code null}.
|
||||||
* @deprecated Use {@link #TrackSelectorResult(RendererConfiguration[], ExoTrackSelection[],
|
* @deprecated Use {@link #TrackSelectorResult(RendererConfiguration[], ExoTrackSelection[],
|
||||||
* TracksInfo, Object)}.
|
* Tracks, Object)}.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public TrackSelectorResult(
|
public TrackSelectorResult(
|
||||||
@NullableType RendererConfiguration[] rendererConfigurations,
|
@NullableType RendererConfiguration[] rendererConfigurations,
|
||||||
@NullableType ExoTrackSelection[] selections,
|
@NullableType ExoTrackSelection[] selections,
|
||||||
@Nullable Object info) {
|
@Nullable Object info) {
|
||||||
this(rendererConfigurations, selections, TracksInfo.EMPTY, info);
|
this(rendererConfigurations, selections, Tracks.EMPTY, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param rendererConfigurations A {@link RendererConfiguration} for each renderer. A null entry
|
* @param rendererConfigurations A {@link RendererConfiguration} for each renderer. A null entry
|
||||||
* indicates the corresponding renderer should be disabled.
|
* indicates the corresponding renderer should be disabled.
|
||||||
* @param selections A {@link ExoTrackSelection} array containing the selection for each renderer.
|
* @param selections A {@link ExoTrackSelection} array containing the selection for each renderer.
|
||||||
* @param tracksInfo Description of the available tracks and which one were selected.
|
* @param tracks Description of the available tracks and which one were selected.
|
||||||
* @param info An opaque object that will be returned to {@link
|
* @param info An opaque object that will be returned to {@link
|
||||||
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
|
* TrackSelector#onSelectionActivated(Object)} should the selection be activated. May be
|
||||||
* {@code null}.
|
* {@code null}.
|
||||||
@ -73,11 +73,11 @@ public final class TrackSelectorResult {
|
|||||||
public TrackSelectorResult(
|
public TrackSelectorResult(
|
||||||
@NullableType RendererConfiguration[] rendererConfigurations,
|
@NullableType RendererConfiguration[] rendererConfigurations,
|
||||||
@NullableType ExoTrackSelection[] selections,
|
@NullableType ExoTrackSelection[] selections,
|
||||||
TracksInfo tracksInfo,
|
Tracks tracks,
|
||||||
@Nullable Object info) {
|
@Nullable Object info) {
|
||||||
this.rendererConfigurations = rendererConfigurations;
|
this.rendererConfigurations = rendererConfigurations;
|
||||||
this.selections = selections.clone();
|
this.selections = selections.clone();
|
||||||
this.tracksInfo = tracksInfo;
|
this.tracks = tracks;
|
||||||
this.info = info;
|
this.info = info;
|
||||||
length = rendererConfigurations.length;
|
length = rendererConfigurations.length;
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ import androidx.media3.common.PlaybackParameters;
|
|||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.Player.PlaybackSuppressionReason;
|
import androidx.media3.common.Player.PlaybackSuppressionReason;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.util.Log;
|
import androidx.media3.common.util.Log;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
@ -261,23 +261,23 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(EventTime eventTime, TracksInfo tracksInfo) {
|
public void onTracksChanged(EventTime eventTime, Tracks tracks) {
|
||||||
logd("tracks [" + getEventTimeString(eventTime));
|
logd("tracks [" + getEventTimeString(eventTime));
|
||||||
// Log tracks associated to renderers.
|
// Log tracks associated to renderers.
|
||||||
ImmutableList<TracksInfo.TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
|
||||||
for (int groupIndex = 0; groupIndex < trackGroupInfos.size(); groupIndex++) {
|
for (int groupIndex = 0; groupIndex < trackGroups.size(); groupIndex++) {
|
||||||
TracksInfo.TrackGroupInfo trackGroupInfo = trackGroupInfos.get(groupIndex);
|
Tracks.Group trackGroup = trackGroups.get(groupIndex);
|
||||||
logd(" group [");
|
logd(" group [");
|
||||||
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) {
|
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
||||||
String status = getTrackStatusString(trackGroupInfo.isTrackSelected(trackIndex));
|
String status = getTrackStatusString(trackGroup.isTrackSelected(trackIndex));
|
||||||
String formatSupport = getFormatSupportString(trackGroupInfo.getTrackSupport(trackIndex));
|
String formatSupport = getFormatSupportString(trackGroup.getTrackSupport(trackIndex));
|
||||||
logd(
|
logd(
|
||||||
" "
|
" "
|
||||||
+ status
|
+ status
|
||||||
+ " Track:"
|
+ " Track:"
|
||||||
+ trackIndex
|
+ trackIndex
|
||||||
+ ", "
|
+ ", "
|
||||||
+ Format.toLogString(trackGroupInfo.getTrackFormat(trackIndex))
|
+ Format.toLogString(trackGroup.getTrackFormat(trackIndex))
|
||||||
+ ", supported="
|
+ ", supported="
|
||||||
+ formatSupport);
|
+ formatSupport);
|
||||||
}
|
}
|
||||||
@ -286,8 +286,8 @@ public class EventLogger implements AnalyticsListener {
|
|||||||
// TODO: Replace this with an override of onMediaMetadataChanged.
|
// TODO: Replace this with an override of onMediaMetadataChanged.
|
||||||
// Log metadata for at most one of the selected tracks.
|
// Log metadata for at most one of the selected tracks.
|
||||||
boolean loggedMetadata = false;
|
boolean loggedMetadata = false;
|
||||||
for (int groupIndex = 0; !loggedMetadata && groupIndex < trackGroupInfos.size(); groupIndex++) {
|
for (int groupIndex = 0; !loggedMetadata && groupIndex < trackGroups.size(); groupIndex++) {
|
||||||
TracksInfo.TrackGroupInfo trackGroup = trackGroupInfos.get(groupIndex);
|
Tracks.Group trackGroup = trackGroups.get(groupIndex);
|
||||||
for (int trackIndex = 0; !loggedMetadata && trackIndex < trackGroup.length; trackIndex++) {
|
for (int trackIndex = 0; !loggedMetadata && trackIndex < trackGroup.length; trackIndex++) {
|
||||||
if (trackGroup.isTrackSelected(trackIndex)) {
|
if (trackGroup.isTrackSelected(trackIndex)) {
|
||||||
@Nullable Metadata metadata = trackGroup.getTrackFormat(trackIndex).metadata;
|
@Nullable Metadata metadata = trackGroup.getTrackFormat(trackIndex).metadata;
|
||||||
|
@ -108,8 +108,7 @@ import androidx.media3.common.Player.PositionInfo;
|
|||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.Timeline.Window;
|
import androidx.media3.common.Timeline.Window;
|
||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.TracksInfo.TrackGroupInfo;
|
|
||||||
import androidx.media3.common.util.Assertions;
|
import androidx.media3.common.util.Assertions;
|
||||||
import androidx.media3.common.util.Clock;
|
import androidx.media3.common.util.Clock;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
@ -277,15 +276,15 @@ public final class ExoPlayerTest {
|
|||||||
argThat(noUid(timeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
|
argThat(noUid(timeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockListener)
|
.verify(mockListener)
|
||||||
.onTracksInfoChanged(
|
.onTracksChanged(
|
||||||
eq(
|
eq(
|
||||||
new TracksInfo(
|
new Tracks(
|
||||||
ImmutableList.of(
|
ImmutableList.of(
|
||||||
new TrackGroupInfo(
|
new Tracks.Group(
|
||||||
new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT),
|
new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT),
|
||||||
/* adaptiveSupported= */ false,
|
/* adaptiveSupported= */ false,
|
||||||
new int[] {C.FORMAT_HANDLED},
|
new int[] {C.FORMAT_HANDLED},
|
||||||
/* tracksSelected= */ new boolean[] {true})))));
|
/* trackSelected= */ new boolean[] {true})))));
|
||||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
|
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
|
||||||
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
|
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
|
||||||
assertThat(renderer.getFormatsRead()).containsExactly(ExoPlayerTestRunner.VIDEO_FORMAT);
|
assertThat(renderer.getFormatsRead()).containsExactly(ExoPlayerTestRunner.VIDEO_FORMAT);
|
||||||
@ -656,15 +655,15 @@ public final class ExoPlayerTest {
|
|||||||
argThat(noUid(thirdTimeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
|
argThat(noUid(thirdTimeline)), eq(Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE));
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockPlayerListener)
|
.verify(mockPlayerListener)
|
||||||
.onTracksInfoChanged(
|
.onTracksChanged(
|
||||||
eq(
|
eq(
|
||||||
new TracksInfo(
|
new Tracks(
|
||||||
ImmutableList.of(
|
ImmutableList.of(
|
||||||
new TrackGroupInfo(
|
new Tracks.Group(
|
||||||
new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT),
|
new TrackGroup(ExoPlayerTestRunner.VIDEO_FORMAT),
|
||||||
/* adaptiveSupported= */ false,
|
/* adaptiveSupported= */ false,
|
||||||
new int[] {C.FORMAT_HANDLED},
|
new int[] {C.FORMAT_HANDLED},
|
||||||
/* tracksSelected= */ new boolean[] {true})))));
|
/* trackSelected= */ new boolean[] {true})))));
|
||||||
assertThat(renderer.isEnded).isTrue();
|
assertThat(renderer.isEnded).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3426,7 +3425,7 @@ public final class ExoPlayerTest {
|
|||||||
.waitForPendingPlayerCommands()
|
.waitForPendingPlayerCommands()
|
||||||
.play()
|
.play()
|
||||||
.build();
|
.build();
|
||||||
List<TracksInfo> tracksInfoList = new ArrayList<>();
|
List<Tracks> tracksList = new ArrayList<>();
|
||||||
new ExoPlayerTestRunner.Builder(context)
|
new ExoPlayerTestRunner.Builder(context)
|
||||||
.setMediaSources(mediaSource)
|
.setMediaSources(mediaSource)
|
||||||
.setSupportedFormats(ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT)
|
.setSupportedFormats(ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT)
|
||||||
@ -3434,21 +3433,21 @@ public final class ExoPlayerTest {
|
|||||||
.setPlayerListener(
|
.setPlayerListener(
|
||||||
new Player.Listener() {
|
new Player.Listener() {
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
tracksInfoList.add(tracksInfo);
|
tracksList.add(tracks);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
.start()
|
.start()
|
||||||
.blockUntilEnded(TIMEOUT_MS);
|
.blockUntilEnded(TIMEOUT_MS);
|
||||||
assertThat(tracksInfoList).hasSize(3);
|
assertThat(tracksList).hasSize(3);
|
||||||
// First track groups of the 1st period are reported.
|
// First track groups of the 1st period are reported.
|
||||||
// Then the seek to an unprepared period will result in empty track groups being returned.
|
// Then the seek to an unprepared period will result in empty track groups being returned.
|
||||||
// Then the track groups of the 2nd period are reported.
|
// Then the track groups of the 2nd period are reported.
|
||||||
assertThat(tracksInfoList.get(0).getTrackGroupInfos().get(0).getTrackFormat(0))
|
assertThat(tracksList.get(0).getGroups().get(0).getTrackFormat(0))
|
||||||
.isEqualTo(ExoPlayerTestRunner.VIDEO_FORMAT);
|
.isEqualTo(ExoPlayerTestRunner.VIDEO_FORMAT);
|
||||||
assertThat(tracksInfoList.get(1)).isEqualTo(TracksInfo.EMPTY);
|
assertThat(tracksList.get(1)).isEqualTo(Tracks.EMPTY);
|
||||||
assertThat(tracksInfoList.get(2).getTrackGroupInfos().get(0).getTrackFormat(0))
|
assertThat(tracksList.get(2).getGroups().get(0).getTrackFormat(0))
|
||||||
.isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
|
.isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7993,7 +7992,7 @@ public final class ExoPlayerTest {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
AtomicReference<Timeline> timelineAfterError = new AtomicReference<>();
|
AtomicReference<Timeline> timelineAfterError = new AtomicReference<>();
|
||||||
AtomicReference<TracksInfo> trackInfosAfterError = new AtomicReference<>();
|
AtomicReference<Tracks> trackInfosAfterError = new AtomicReference<>();
|
||||||
AtomicInteger mediaItemIndexAfterError = new AtomicInteger();
|
AtomicInteger mediaItemIndexAfterError = new AtomicInteger();
|
||||||
ActionSchedule actionSchedule =
|
ActionSchedule actionSchedule =
|
||||||
new ActionSchedule.Builder(TAG)
|
new ActionSchedule.Builder(TAG)
|
||||||
@ -8006,7 +8005,7 @@ public final class ExoPlayerTest {
|
|||||||
@Override
|
@Override
|
||||||
public void onPlayerError(EventTime eventTime, PlaybackException error) {
|
public void onPlayerError(EventTime eventTime, PlaybackException error) {
|
||||||
timelineAfterError.set(player.getCurrentTimeline());
|
timelineAfterError.set(player.getCurrentTimeline());
|
||||||
trackInfosAfterError.set(player.getCurrentTracksInfo());
|
trackInfosAfterError.set(player.getCurrentTracks());
|
||||||
mediaItemIndexAfterError.set(player.getCurrentMediaItemIndex());
|
mediaItemIndexAfterError.set(player.getCurrentMediaItemIndex());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -8035,8 +8034,8 @@ public final class ExoPlayerTest {
|
|||||||
|
|
||||||
assertThat(timelineAfterError.get().getWindowCount()).isEqualTo(1);
|
assertThat(timelineAfterError.get().getWindowCount()).isEqualTo(1);
|
||||||
assertThat(mediaItemIndexAfterError.get()).isEqualTo(0);
|
assertThat(mediaItemIndexAfterError.get()).isEqualTo(0);
|
||||||
assertThat(trackInfosAfterError.get().getTrackGroupInfos()).hasSize(1);
|
assertThat(trackInfosAfterError.get().getGroups()).hasSize(1);
|
||||||
assertThat(trackInfosAfterError.get().getTrackGroupInfos().get(0).getTrackFormat(0))
|
assertThat(trackInfosAfterError.get().getGroups().get(0).getTrackFormat(0))
|
||||||
.isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
|
.isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
|
||||||
assertThat(trackInfosAfterError.get().isTypeSelected(C.TRACK_TYPE_VIDEO)).isFalse();
|
assertThat(trackInfosAfterError.get().isTypeSelected(C.TRACK_TYPE_VIDEO)).isFalse();
|
||||||
assertThat(trackInfosAfterError.get().isTypeSelected(C.TRACK_TYPE_AUDIO)).isTrue();
|
assertThat(trackInfosAfterError.get().isTypeSelected(C.TRACK_TYPE_AUDIO)).isTrue();
|
||||||
@ -10423,7 +10422,7 @@ public final class ExoPlayerTest {
|
|||||||
verify(listener, atLeastOnce()).onShuffleModeEnabledChanged(anyBoolean());
|
verify(listener, atLeastOnce()).onShuffleModeEnabledChanged(anyBoolean());
|
||||||
verify(listener, atLeastOnce()).onPlaybackStateChanged(anyInt());
|
verify(listener, atLeastOnce()).onPlaybackStateChanged(anyInt());
|
||||||
verify(listener, atLeastOnce()).onIsLoadingChanged(anyBoolean());
|
verify(listener, atLeastOnce()).onIsLoadingChanged(anyBoolean());
|
||||||
verify(listener, atLeastOnce()).onTracksInfoChanged(any());
|
verify(listener, atLeastOnce()).onTracksChanged(any());
|
||||||
verify(listener, atLeastOnce()).onMediaMetadataChanged(any());
|
verify(listener, atLeastOnce()).onMediaMetadataChanged(any());
|
||||||
verify(listener, atLeastOnce()).onPlayWhenReadyChanged(anyBoolean(), anyInt());
|
verify(listener, atLeastOnce()).onPlayWhenReadyChanged(anyBoolean(), anyInt());
|
||||||
verify(listener, atLeastOnce()).onIsPlayingChanged(anyBoolean());
|
verify(listener, atLeastOnce()).onIsPlayingChanged(anyBoolean());
|
||||||
|
@ -34,7 +34,7 @@ import androidx.media3.common.MediaItem;
|
|||||||
import androidx.media3.common.PlaybackParameters;
|
import androidx.media3.common.PlaybackParameters;
|
||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.util.Clock;
|
import androidx.media3.common.util.Clock;
|
||||||
import androidx.media3.exoplayer.analytics.AnalyticsCollector;
|
import androidx.media3.exoplayer.analytics.AnalyticsCollector;
|
||||||
import androidx.media3.exoplayer.analytics.DefaultAnalyticsCollector;
|
import androidx.media3.exoplayer.analytics.DefaultAnalyticsCollector;
|
||||||
@ -1141,7 +1141,7 @@ public final class MediaPeriodQueueTest {
|
|||||||
new TrackSelectorResult(
|
new TrackSelectorResult(
|
||||||
new RendererConfiguration[0],
|
new RendererConfiguration[0],
|
||||||
new ExoTrackSelection[0],
|
new ExoTrackSelection[0],
|
||||||
TracksInfo.EMPTY,
|
Tracks.EMPTY,
|
||||||
/* info= */ null));
|
/* info= */ null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ import androidx.media3.common.PlaybackParameters;
|
|||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.Timeline.Window;
|
import androidx.media3.common.Timeline.Window;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.util.Clock;
|
import androidx.media3.common.util.Clock;
|
||||||
import androidx.media3.common.util.ConditionVariable;
|
import androidx.media3.common.util.ConditionVariable;
|
||||||
@ -1729,7 +1729,7 @@ public final class DefaultAnalyticsCollectorTest {
|
|||||||
ArgumentCaptor<AnalyticsListener.EventTime> individualTracksChangedEventTimes =
|
ArgumentCaptor<AnalyticsListener.EventTime> individualTracksChangedEventTimes =
|
||||||
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
verify(listener, atLeastOnce())
|
verify(listener, atLeastOnce())
|
||||||
.onTracksInfoChanged(individualTracksChangedEventTimes.capture(), any());
|
.onTracksChanged(individualTracksChangedEventTimes.capture(), any());
|
||||||
ArgumentCaptor<AnalyticsListener.EventTime> individualPlayWhenReadyChangedEventTimes =
|
ArgumentCaptor<AnalyticsListener.EventTime> individualPlayWhenReadyChangedEventTimes =
|
||||||
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
verify(listener, atLeastOnce())
|
verify(listener, atLeastOnce())
|
||||||
@ -2243,7 +2243,7 @@ public final class DefaultAnalyticsCollectorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(EventTime eventTime, TracksInfo tracksInfo) {
|
public void onTracksChanged(EventTime eventTime, Tracks tracks) {
|
||||||
reportedEvents.add(new ReportedEvent(EVENT_TRACKS_CHANGED, eventTime));
|
reportedEvents.add(new ReportedEvent(EVENT_TRACKS_CHANGED, eventTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ import androidx.media3.common.MimeTypes;
|
|||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TrackSelectionOverride;
|
import androidx.media3.common.TrackSelectionOverride;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.exoplayer.ExoPlaybackException;
|
import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
import androidx.media3.exoplayer.RendererCapabilities;
|
import androidx.media3.exoplayer.RendererCapabilities;
|
||||||
@ -2224,10 +2224,10 @@ public final class DefaultTrackSelectorTest {
|
|||||||
public void selectTracks_multipleRenderer_allSelected() throws Exception {
|
public void selectTracks_multipleRenderer_allSelected() throws Exception {
|
||||||
RendererCapabilities[] rendererCapabilities =
|
RendererCapabilities[] rendererCapabilities =
|
||||||
new RendererCapabilities[] {VIDEO_CAPABILITIES, AUDIO_CAPABILITIES, AUDIO_CAPABILITIES};
|
new RendererCapabilities[] {VIDEO_CAPABILITIES, AUDIO_CAPABILITIES, AUDIO_CAPABILITIES};
|
||||||
TrackGroupArray trackGroups = new TrackGroupArray(AUDIO_TRACK_GROUP);
|
TrackGroupArray trackGroupArray = new TrackGroupArray(AUDIO_TRACK_GROUP);
|
||||||
|
|
||||||
TrackSelectorResult result =
|
TrackSelectorResult result =
|
||||||
trackSelector.selectTracks(rendererCapabilities, trackGroups, periodId, TIMELINE);
|
trackSelector.selectTracks(rendererCapabilities, trackGroupArray, periodId, TIMELINE);
|
||||||
|
|
||||||
assertThat(result.length).isEqualTo(3);
|
assertThat(result.length).isEqualTo(3);
|
||||||
assertThat(result.rendererConfigurations)
|
assertThat(result.rendererConfigurations)
|
||||||
@ -2235,14 +2235,14 @@ public final class DefaultTrackSelectorTest {
|
|||||||
.containsExactly(null, DEFAULT, null)
|
.containsExactly(null, DEFAULT, null)
|
||||||
.inOrder();
|
.inOrder();
|
||||||
assertThat(result.selections[0]).isNull();
|
assertThat(result.selections[0]).isNull();
|
||||||
assertFixedSelection(result.selections[1], trackGroups, trackGroups.get(0).getFormat(0));
|
assertFixedSelection(
|
||||||
|
result.selections[1], trackGroupArray, trackGroupArray.get(0).getFormat(0));
|
||||||
assertThat(result.selections[2]).isNull();
|
assertThat(result.selections[2]).isNull();
|
||||||
ImmutableList<TracksInfo.TrackGroupInfo> trackGroupInfos =
|
ImmutableList<Tracks.Group> trackGroups = result.tracks.getGroups();
|
||||||
result.tracksInfo.getTrackGroupInfos();
|
assertThat(trackGroups).hasSize(1);
|
||||||
assertThat(trackGroupInfos).hasSize(1);
|
assertThat(trackGroups.get(0).getTrackGroup()).isEqualTo(AUDIO_TRACK_GROUP);
|
||||||
assertThat(trackGroupInfos.get(0).getTrackGroup()).isEqualTo(AUDIO_TRACK_GROUP);
|
assertThat(trackGroups.get(0).isTrackSelected(0)).isTrue();
|
||||||
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isTrue();
|
assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
||||||
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Tests {@link SelectionOverride}'s {@link Bundleable} implementation. */
|
/** Tests {@link SelectionOverride}'s {@link Bundleable} implementation. */
|
||||||
|
@ -32,8 +32,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.TracksInfo.TrackGroupInfo;
|
|
||||||
import androidx.media3.exoplayer.source.TrackGroupArray;
|
import androidx.media3.exoplayer.source.TrackGroupArray;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
@ -73,32 +72,32 @@ public class TrackSelectionUtilTest {
|
|||||||
new FixedTrackSelection(mappedTrackInfo.getTrackGroups(1).get(0), 1)
|
new FixedTrackSelection(mappedTrackInfo.getTrackGroups(1).get(0), 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
TracksInfo tracksInfo = TrackSelectionUtil.buildTracksInfo(mappedTrackInfo, selections);
|
Tracks tracks = TrackSelectionUtil.buildTracks(mappedTrackInfo, selections);
|
||||||
|
|
||||||
ImmutableList<TracksInfo.TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
|
||||||
assertThat(trackGroupInfos).hasSize(4);
|
assertThat(trackGroups).hasSize(4);
|
||||||
assertThat(trackGroupInfos.get(0).getTrackGroup())
|
assertThat(trackGroups.get(0).getTrackGroup())
|
||||||
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0));
|
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0));
|
||||||
assertThat(trackGroupInfos.get(1).getTrackGroup())
|
assertThat(trackGroups.get(1).getTrackGroup())
|
||||||
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1));
|
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1));
|
||||||
assertThat(trackGroupInfos.get(2).getTrackGroup())
|
assertThat(trackGroups.get(2).getTrackGroup())
|
||||||
.isEqualTo(mappedTrackInfo.getTrackGroups(1).get(0));
|
.isEqualTo(mappedTrackInfo.getTrackGroups(1).get(0));
|
||||||
assertThat(trackGroupInfos.get(3).getTrackGroup())
|
assertThat(trackGroups.get(3).getTrackGroup())
|
||||||
.isEqualTo(mappedTrackInfo.getUnmappedTrackGroups().get(0));
|
.isEqualTo(mappedTrackInfo.getUnmappedTrackGroups().get(0));
|
||||||
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
||||||
assertThat(trackGroupInfos.get(1).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_SUBTYPE);
|
assertThat(trackGroups.get(1).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_SUBTYPE);
|
||||||
assertThat(trackGroupInfos.get(2).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_DRM);
|
assertThat(trackGroups.get(2).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_DRM);
|
||||||
assertThat(trackGroupInfos.get(2).getTrackSupport(1)).isEqualTo(FORMAT_EXCEEDS_CAPABILITIES);
|
assertThat(trackGroups.get(2).getTrackSupport(1)).isEqualTo(FORMAT_EXCEEDS_CAPABILITIES);
|
||||||
assertThat(trackGroupInfos.get(3).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_TYPE);
|
assertThat(trackGroups.get(3).getTrackSupport(0)).isEqualTo(FORMAT_UNSUPPORTED_TYPE);
|
||||||
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isFalse();
|
assertThat(trackGroups.get(0).isTrackSelected(0)).isFalse();
|
||||||
assertThat(trackGroupInfos.get(1).isTrackSelected(0)).isTrue();
|
assertThat(trackGroups.get(1).isTrackSelected(0)).isTrue();
|
||||||
assertThat(trackGroupInfos.get(2).isTrackSelected(0)).isFalse();
|
assertThat(trackGroups.get(2).isTrackSelected(0)).isFalse();
|
||||||
assertThat(trackGroupInfos.get(2).isTrackSelected(1)).isTrue();
|
assertThat(trackGroups.get(2).isTrackSelected(1)).isTrue();
|
||||||
assertThat(trackGroupInfos.get(3).isTrackSelected(0)).isFalse();
|
assertThat(trackGroups.get(3).isTrackSelected(0)).isFalse();
|
||||||
assertThat(trackGroupInfos.get(0).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO);
|
assertThat(trackGroups.get(0).getType()).isEqualTo(TRACK_TYPE_AUDIO);
|
||||||
assertThat(trackGroupInfos.get(1).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO);
|
assertThat(trackGroups.get(1).getType()).isEqualTo(TRACK_TYPE_AUDIO);
|
||||||
assertThat(trackGroupInfos.get(2).getTrackType()).isEqualTo(TRACK_TYPE_VIDEO);
|
assertThat(trackGroups.get(2).getType()).isEqualTo(TRACK_TYPE_VIDEO);
|
||||||
assertThat(trackGroupInfos.get(3).getTrackType()).isEqualTo(TRACK_TYPE_UNKNOWN);
|
assertThat(trackGroups.get(3).getType()).isEqualTo(TRACK_TYPE_UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -132,21 +131,21 @@ public class TrackSelectionUtilTest {
|
|||||||
ImmutableList.of()
|
ImmutableList.of()
|
||||||
};
|
};
|
||||||
|
|
||||||
TracksInfo tracksInfo = TrackSelectionUtil.buildTracksInfo(mappedTrackInfo, selections);
|
Tracks tracks = TrackSelectionUtil.buildTracks(mappedTrackInfo, selections);
|
||||||
|
|
||||||
ImmutableList<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
ImmutableList<Tracks.Group> trackGroups = tracks.getGroups();
|
||||||
assertThat(trackGroupInfos).hasSize(2);
|
assertThat(trackGroups).hasSize(2);
|
||||||
assertThat(trackGroupInfos.get(0).getTrackGroup())
|
assertThat(trackGroups.get(0).getTrackGroup())
|
||||||
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0));
|
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(0));
|
||||||
assertThat(trackGroupInfos.get(1).getTrackGroup())
|
assertThat(trackGroups.get(1).getTrackGroup())
|
||||||
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1));
|
.isEqualTo(mappedTrackInfo.getTrackGroups(0).get(1));
|
||||||
assertThat(trackGroupInfos.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
assertThat(trackGroups.get(0).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
||||||
assertThat(trackGroupInfos.get(1).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
assertThat(trackGroups.get(1).getTrackSupport(0)).isEqualTo(FORMAT_HANDLED);
|
||||||
assertThat(trackGroupInfos.get(1).getTrackSupport(1)).isEqualTo(FORMAT_HANDLED);
|
assertThat(trackGroups.get(1).getTrackSupport(1)).isEqualTo(FORMAT_HANDLED);
|
||||||
assertThat(trackGroupInfos.get(0).isTrackSelected(0)).isTrue();
|
assertThat(trackGroups.get(0).isTrackSelected(0)).isTrue();
|
||||||
assertThat(trackGroupInfos.get(1).isTrackSelected(0)).isFalse();
|
assertThat(trackGroups.get(1).isTrackSelected(0)).isFalse();
|
||||||
assertThat(trackGroupInfos.get(1).isTrackSelected(1)).isTrue();
|
assertThat(trackGroups.get(1).isTrackSelected(1)).isTrue();
|
||||||
assertThat(trackGroupInfos.get(0).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO);
|
assertThat(trackGroups.get(0).getType()).isEqualTo(TRACK_TYPE_AUDIO);
|
||||||
assertThat(trackGroupInfos.get(1).getTrackType()).isEqualTo(TRACK_TYPE_AUDIO);
|
assertThat(trackGroups.get(1).getType()).isEqualTo(TRACK_TYPE_AUDIO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 androidx.media3.common.PlaybackException;
|
|||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.util.Clock;
|
import androidx.media3.common.util.Clock;
|
||||||
import androidx.media3.common.util.ListenerSet;
|
import androidx.media3.common.util.ListenerSet;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
@ -266,8 +266,8 @@ import androidx.media3.test.utils.StubExoPlayer;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
return TracksInfo.EMPTY;
|
return Tracks.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,7 +50,7 @@ import androidx.media3.common.Player;
|
|||||||
import androidx.media3.common.Rating;
|
import androidx.media3.common.Rating;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.text.Cue;
|
import androidx.media3.common.text.Cue;
|
||||||
import androidx.media3.common.util.Consumer;
|
import androidx.media3.common.util.Consumer;
|
||||||
@ -1680,8 +1680,8 @@ public class MediaController implements Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
return TracksInfo.EMPTY; // TODO(b/178486745)
|
return Tracks.EMPTY; // TODO(b/178486745)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -36,7 +36,7 @@ import androidx.media3.common.PlaybackParameters;
|
|||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.text.Cue;
|
import androidx.media3.common.text.Cue;
|
||||||
import androidx.media3.common.util.ConditionVariable;
|
import androidx.media3.common.util.ConditionVariable;
|
||||||
@ -1171,7 +1171,7 @@ public class MockPlayer implements Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ import androidx.media3.common.PlaybackParameters;
|
|||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.text.Cue;
|
import androidx.media3.common.text.Cue;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
@ -191,7 +191,7 @@ public class StubPlayer extends BasePlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TracksInfo getCurrentTracksInfo() {
|
public Tracks getCurrentTracks() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ import androidx.media3.common.MimeTypes;
|
|||||||
import androidx.media3.common.PlaybackException;
|
import androidx.media3.common.PlaybackException;
|
||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.util.Clock;
|
import androidx.media3.common.util.Clock;
|
||||||
import androidx.media3.common.util.ListenerSet;
|
import androidx.media3.common.util.ListenerSet;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
@ -949,7 +949,7 @@ public final class Transformer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
if (muxerWrapper.getTrackCount() == 0) {
|
if (muxerWrapper.getTrackCount() == 0) {
|
||||||
handleTransformationEnded(
|
handleTransformationEnded(
|
||||||
TransformationException.createForUnexpected(
|
TransformationException.createForUnexpected(
|
||||||
|
@ -66,8 +66,7 @@ import androidx.media3.common.Timeline;
|
|||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TrackSelectionOverride;
|
import androidx.media3.common.TrackSelectionOverride;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.TracksInfo.TrackGroupInfo;
|
|
||||||
import androidx.media3.common.util.Assertions;
|
import androidx.media3.common.util.Assertions;
|
||||||
import androidx.media3.common.util.RepeatModeUtil;
|
import androidx.media3.common.util.RepeatModeUtil;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
@ -1101,39 +1100,37 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
|| !player.isCommandAvailable(Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
|
|| !player.isCommandAvailable(Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TracksInfo tracksInfo = player.getCurrentTracksInfo();
|
Tracks tracks = player.getCurrentTracks();
|
||||||
audioTrackSelectionAdapter.init(
|
audioTrackSelectionAdapter.init(gatherSupportedTrackInfosOfType(tracks, C.TRACK_TYPE_AUDIO));
|
||||||
gatherSupportedTrackInfosOfType(tracksInfo, C.TRACK_TYPE_AUDIO));
|
|
||||||
if (controlViewLayoutManager.getShowButton(subtitleButton)) {
|
if (controlViewLayoutManager.getShowButton(subtitleButton)) {
|
||||||
textTrackSelectionAdapter.init(
|
textTrackSelectionAdapter.init(gatherSupportedTrackInfosOfType(tracks, C.TRACK_TYPE_TEXT));
|
||||||
gatherSupportedTrackInfosOfType(tracksInfo, C.TRACK_TYPE_TEXT));
|
|
||||||
} else {
|
} else {
|
||||||
textTrackSelectionAdapter.init(ImmutableList.of());
|
textTrackSelectionAdapter.init(ImmutableList.of());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImmutableList<TrackInformation> gatherSupportedTrackInfosOfType(
|
private ImmutableList<TrackInformation> gatherSupportedTrackInfosOfType(
|
||||||
TracksInfo tracksInfo, @C.TrackType int trackType) {
|
Tracks tracks, @C.TrackType int trackType) {
|
||||||
ImmutableList.Builder<TrackInformation> tracks = new ImmutableList.Builder<>();
|
ImmutableList.Builder<TrackInformation> trackInfos = new ImmutableList.Builder<>();
|
||||||
List<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
|
List<Tracks.Group> trackGroups = tracks.getGroups();
|
||||||
for (int trackGroupIndex = 0; trackGroupIndex < trackGroupInfos.size(); trackGroupIndex++) {
|
for (int trackGroupIndex = 0; trackGroupIndex < trackGroups.size(); trackGroupIndex++) {
|
||||||
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(trackGroupIndex);
|
Tracks.Group trackGroup = trackGroups.get(trackGroupIndex);
|
||||||
if (trackGroupInfo.getTrackType() != trackType) {
|
if (trackGroup.getType() != trackType) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) {
|
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
||||||
if (!trackGroupInfo.isTrackSupported(trackIndex)) {
|
if (!trackGroup.isTrackSupported(trackIndex)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Format trackFormat = trackGroupInfo.getTrackFormat(trackIndex);
|
Format trackFormat = trackGroup.getTrackFormat(trackIndex);
|
||||||
if ((trackFormat.selectionFlags & C.SELECTION_FLAG_FORCED) != 0) {
|
if ((trackFormat.selectionFlags & C.SELECTION_FLAG_FORCED) != 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String trackName = trackNameProvider.getTrackName(trackFormat);
|
String trackName = trackNameProvider.getTrackName(trackFormat);
|
||||||
tracks.add(new TrackInformation(tracksInfo, trackGroupIndex, trackIndex, trackName));
|
trackInfos.add(new TrackInformation(tracks, trackGroupIndex, trackIndex, trackName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tracks.build();
|
return trackInfos.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTimeline() {
|
private void updateTimeline() {
|
||||||
@ -1812,19 +1809,18 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
|
|
||||||
private static final class TrackInformation {
|
private static final class TrackInformation {
|
||||||
|
|
||||||
public final TrackGroupInfo trackGroupInfo;
|
public final Tracks.Group trackGroup;
|
||||||
public final int trackIndex;
|
public final int trackIndex;
|
||||||
public final String trackName;
|
public final String trackName;
|
||||||
|
|
||||||
public TrackInformation(
|
public TrackInformation(Tracks tracks, int trackGroupIndex, int trackIndex, String trackName) {
|
||||||
TracksInfo tracksInfo, int trackGroupIndex, int trackIndex, String trackName) {
|
this.trackGroup = tracks.getGroups().get(trackGroupIndex);
|
||||||
this.trackGroupInfo = tracksInfo.getTrackGroupInfos().get(trackGroupIndex);
|
|
||||||
this.trackIndex = trackIndex;
|
this.trackIndex = trackIndex;
|
||||||
this.trackName = trackName;
|
this.trackName = trackName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSelected() {
|
public boolean isSelected() {
|
||||||
return trackGroupInfo.isTrackSelected(trackIndex);
|
return trackGroup.isTrackSelected(trackIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1924,7 +1920,7 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
|
|
||||||
private boolean hasSelectionOverride(TrackSelectionParameters trackSelectionParameters) {
|
private boolean hasSelectionOverride(TrackSelectionParameters trackSelectionParameters) {
|
||||||
for (int i = 0; i < tracks.size(); i++) {
|
for (int i = 0; i < tracks.size(); i++) {
|
||||||
TrackGroup trackGroup = tracks.get(i).trackGroupInfo.getTrackGroup();
|
TrackGroup trackGroup = tracks.get(i).trackGroup.getTrackGroup();
|
||||||
if (trackSelectionParameters.overrides.containsKey(trackGroup)) {
|
if (trackSelectionParameters.overrides.containsKey(trackGroup)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1998,7 +1994,7 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
onBindViewHolderAtZeroPosition(holder);
|
onBindViewHolderAtZeroPosition(holder);
|
||||||
} else {
|
} else {
|
||||||
TrackInformation track = tracks.get(position - 1);
|
TrackInformation track = tracks.get(position - 1);
|
||||||
TrackGroup trackGroup = track.trackGroupInfo.getTrackGroup();
|
TrackGroup trackGroup = track.trackGroup.getTrackGroup();
|
||||||
TrackSelectionParameters params = player.getTrackSelectionParameters();
|
TrackSelectionParameters params = player.getTrackSelectionParameters();
|
||||||
boolean explicitlySelected = params.overrides.get(trackGroup) != null && track.isSelected();
|
boolean explicitlySelected = params.overrides.get(trackGroup) != null && track.isSelected();
|
||||||
holder.textView.setText(track.trackName);
|
holder.textView.setText(track.trackName);
|
||||||
@ -2013,8 +2009,7 @@ public class PlayerControlView extends FrameLayout {
|
|||||||
.setOverrideForType(
|
.setOverrideForType(
|
||||||
new TrackSelectionOverride(
|
new TrackSelectionOverride(
|
||||||
trackGroup, ImmutableList.of(track.trackIndex)))
|
trackGroup, ImmutableList.of(track.trackIndex)))
|
||||||
.setTrackTypeDisabled(
|
.setTrackTypeDisabled(track.trackGroup.getType(), /* disabled= */ false)
|
||||||
track.trackGroupInfo.getTrackType(), /* disabled= */ false)
|
|
||||||
.build());
|
.build());
|
||||||
onTrackSelection(track.trackName);
|
onTrackSelection(track.trackName);
|
||||||
settingsWindow.dismiss();
|
settingsWindow.dismiss();
|
||||||
|
@ -58,7 +58,7 @@ import androidx.media3.common.Player;
|
|||||||
import androidx.media3.common.Player.DiscontinuityReason;
|
import androidx.media3.common.Player.DiscontinuityReason;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.Timeline.Period;
|
import androidx.media3.common.Timeline.Period;
|
||||||
import androidx.media3.common.TracksInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.common.text.Cue;
|
import androidx.media3.common.text.Cue;
|
||||||
import androidx.media3.common.util.Assertions;
|
import androidx.media3.common.util.Assertions;
|
||||||
@ -1216,7 +1216,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
|
|
||||||
private void updateForCurrentTrackSelections(boolean isNewPlayer) {
|
private void updateForCurrentTrackSelections(boolean isNewPlayer) {
|
||||||
@Nullable Player player = this.player;
|
@Nullable Player player = this.player;
|
||||||
if (player == null || player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) {
|
if (player == null || player.getCurrentTracks().isEmpty()) {
|
||||||
if (!keepContentOnPlayerReset) {
|
if (!keepContentOnPlayerReset) {
|
||||||
hideArtwork();
|
hideArtwork();
|
||||||
closeShutter();
|
closeShutter();
|
||||||
@ -1229,7 +1229,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
closeShutter();
|
closeShutter();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.getCurrentTracksInfo().isTypeSelected(C.TRACK_TYPE_VIDEO)) {
|
if (player.getCurrentTracks().isTypeSelected(C.TRACK_TYPE_VIDEO)) {
|
||||||
// Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened
|
// Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened
|
||||||
// in onRenderedFirstFrame().
|
// in onRenderedFirstFrame().
|
||||||
hideArtwork();
|
hideArtwork();
|
||||||
@ -1461,7 +1461,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksInfoChanged(TracksInfo tracksInfo) {
|
public void onTracksChanged(Tracks tracks) {
|
||||||
// Suppress the update if transitioning to an unprepared period within the same window. This
|
// Suppress the update if transitioning to an unprepared period within the same window. This
|
||||||
// is necessary to avoid closing the shutter when such a transition occurs. See:
|
// is necessary to avoid closing the shutter when such a transition occurs. See:
|
||||||
// https://github.com/google/ExoPlayer/issues/5507.
|
// https://github.com/google/ExoPlayer/issues/5507.
|
||||||
@ -1469,7 +1469,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
|
|||||||
Timeline timeline = player.getCurrentTimeline();
|
Timeline timeline = player.getCurrentTimeline();
|
||||||
if (timeline.isEmpty()) {
|
if (timeline.isEmpty()) {
|
||||||
lastPeriodUidWithTracks = null;
|
lastPeriodUidWithTracks = null;
|
||||||
} else if (!player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) {
|
} else if (!player.getCurrentTracks().isEmpty()) {
|
||||||
lastPeriodUidWithTracks =
|
lastPeriodUidWithTracks =
|
||||||
timeline.getPeriod(player.getCurrentPeriodIndex(), period, /* setIds= */ true).uid;
|
timeline.getPeriod(player.getCurrentPeriodIndex(), period, /* setIds= */ true).uid;
|
||||||
} else if (lastPeriodUidWithTracks != null) {
|
} else if (lastPeriodUidWithTracks != null) {
|
||||||
|
@ -29,7 +29,7 @@ import androidx.media3.common.Player;
|
|||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TrackSelectionOverride;
|
import androidx.media3.common.TrackSelectionOverride;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
import androidx.media3.common.TracksInfo.TrackGroupInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
@ -58,7 +58,7 @@ public final class TrackSelectionDialogBuilder {
|
|||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final CharSequence title;
|
private final CharSequence title;
|
||||||
private final List<TrackGroupInfo> trackGroupInfos;
|
private final List<Tracks.Group> trackGroups;
|
||||||
private final DialogCallback callback;
|
private final DialogCallback callback;
|
||||||
|
|
||||||
@StyleRes private int themeResId;
|
@StyleRes private int themeResId;
|
||||||
@ -75,17 +75,17 @@ public final class TrackSelectionDialogBuilder {
|
|||||||
*
|
*
|
||||||
* @param context The context of the dialog.
|
* @param context The context of the dialog.
|
||||||
* @param title The title of the dialog.
|
* @param title The title of the dialog.
|
||||||
* @param trackGroupInfos The {@link TrackGroupInfo TrackGroupInfos} for the track groups.
|
* @param trackGroups The {@link Tracks.Group track groups}.
|
||||||
* @param callback The {@link DialogCallback} invoked when a track selection has been made.
|
* @param callback The {@link DialogCallback} invoked when a track selection has been made.
|
||||||
*/
|
*/
|
||||||
public TrackSelectionDialogBuilder(
|
public TrackSelectionDialogBuilder(
|
||||||
Context context,
|
Context context,
|
||||||
CharSequence title,
|
CharSequence title,
|
||||||
List<TrackGroupInfo> trackGroupInfos,
|
List<Tracks.Group> trackGroups,
|
||||||
DialogCallback callback) {
|
DialogCallback callback) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.trackGroupInfos = ImmutableList.copyOf(trackGroupInfos);
|
this.trackGroups = ImmutableList.copyOf(trackGroups);
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
overrides = Collections.emptyMap();
|
overrides = Collections.emptyMap();
|
||||||
}
|
}
|
||||||
@ -102,12 +102,12 @@ public final class TrackSelectionDialogBuilder {
|
|||||||
Context context, CharSequence title, Player player, @C.TrackType int trackType) {
|
Context context, CharSequence title, Player player, @C.TrackType int trackType) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
List<TrackGroupInfo> allTrackGroupInfos = player.getCurrentTracksInfo().getTrackGroupInfos();
|
List<Tracks.Group> allTrackGroups = player.getCurrentTracks().getGroups();
|
||||||
trackGroupInfos = new ArrayList<>();
|
trackGroups = new ArrayList<>();
|
||||||
for (int i = 0; i < allTrackGroupInfos.size(); i++) {
|
for (int i = 0; i < allTrackGroups.size(); i++) {
|
||||||
TrackGroupInfo trackGroupInfo = allTrackGroupInfos.get(i);
|
Tracks.Group trackGroup = allTrackGroups.get(i);
|
||||||
if (trackGroupInfo.getTrackType() == trackType) {
|
if (trackGroup.getType() == trackType) {
|
||||||
trackGroupInfos.add(trackGroupInfo);
|
trackGroups.add(trackGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
overrides = Collections.emptyMap();
|
overrides = Collections.emptyMap();
|
||||||
@ -158,11 +158,11 @@ public final class TrackSelectionDialogBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the initial track overrides. Any overrides that do not correspond to track groups
|
* Sets the initial track overrides. Any overrides that do not correspond to track groups that
|
||||||
* described by {@code trackGroupInfos} that have been given to this instance will be ignored. If
|
* were passed to the constructor will be ignored. If {@link #setAllowMultipleOverrides(boolean)}
|
||||||
* {@link #setAllowMultipleOverrides(boolean)} hasn't been set to {@code true} then all but one
|
* hasn't been set to {@code true} then all but one override will be ignored. The retained
|
||||||
* override will be ignored. The retained override will be the one whose track group is described
|
* override will be the one whose track group was first in the list of track groups passed to the
|
||||||
* first in {@code trackGroupInfos}.
|
* constructor.
|
||||||
*
|
*
|
||||||
* @param overrides The initially selected track overrides.
|
* @param overrides The initially selected track overrides.
|
||||||
* @return This builder, for convenience.
|
* @return This builder, for convenience.
|
||||||
@ -298,7 +298,7 @@ public final class TrackSelectionDialogBuilder {
|
|||||||
selectionView.setTrackNameProvider(trackNameProvider);
|
selectionView.setTrackNameProvider(trackNameProvider);
|
||||||
}
|
}
|
||||||
selectionView.init(
|
selectionView.init(
|
||||||
trackGroupInfos, isDisabled, overrides, trackFormatComparator, /* listener= */ null);
|
trackGroups, isDisabled, overrides, trackFormatComparator, /* listener= */ null);
|
||||||
return (dialog, which) ->
|
return (dialog, which) ->
|
||||||
callback.onTracksSelected(selectionView.getIsDisabled(), selectionView.getOverrides());
|
callback.onTracksSelected(selectionView.getIsDisabled(), selectionView.getOverrides());
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TrackSelectionOverride;
|
import androidx.media3.common.TrackSelectionOverride;
|
||||||
import androidx.media3.common.TracksInfo.TrackGroupInfo;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.util.Assertions;
|
import androidx.media3.common.util.Assertions;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
@ -56,23 +56,23 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the subset of {@code overrides} that apply to track groups in {@code trackGroupInfos}.
|
* Returns the subset of {@code overrides} that apply to the specified {@code trackGroups}. If
|
||||||
* If {@code allowMultipleOverrides} is {@code} then at most one override is retained, which will
|
* {@code allowMultipleOverrides} is {@code} then at most one override is retained, which will be
|
||||||
* be the one whose track group is first in {@code trackGroupInfos}.
|
* the one whose track group is first in {@code trackGroups}.
|
||||||
*
|
*
|
||||||
* @param overrides The overrides to filter.
|
* @param overrides The overrides to filter.
|
||||||
* @param trackGroupInfos The track groups whose overrides should be retained.
|
* @param trackGroups The track groups whose overrides should be retained.
|
||||||
* @param allowMultipleOverrides Whether more than one override can be retained.
|
* @param allowMultipleOverrides Whether more than one override can be retained.
|
||||||
* @return The filtered overrides.
|
* @return The filtered overrides.
|
||||||
*/
|
*/
|
||||||
public static Map<TrackGroup, TrackSelectionOverride> filterOverrides(
|
public static Map<TrackGroup, TrackSelectionOverride> filterOverrides(
|
||||||
Map<TrackGroup, TrackSelectionOverride> overrides,
|
Map<TrackGroup, TrackSelectionOverride> overrides,
|
||||||
List<TrackGroupInfo> trackGroupInfos,
|
List<Tracks.Group> trackGroups,
|
||||||
boolean allowMultipleOverrides) {
|
boolean allowMultipleOverrides) {
|
||||||
HashMap<TrackGroup, TrackSelectionOverride> filteredOverrides = new HashMap<>();
|
HashMap<TrackGroup, TrackSelectionOverride> filteredOverrides = new HashMap<>();
|
||||||
for (int i = 0; i < trackGroupInfos.size(); i++) {
|
for (int i = 0; i < trackGroups.size(); i++) {
|
||||||
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(i);
|
Tracks.Group trackGroup = trackGroups.get(i);
|
||||||
@Nullable TrackSelectionOverride override = overrides.get(trackGroupInfo.getTrackGroup());
|
@Nullable TrackSelectionOverride override = overrides.get(trackGroup.getTrackGroup());
|
||||||
if (override != null && (allowMultipleOverrides || filteredOverrides.isEmpty())) {
|
if (override != null && (allowMultipleOverrides || filteredOverrides.isEmpty())) {
|
||||||
filteredOverrides.put(override.trackGroup, override);
|
filteredOverrides.put(override.trackGroup, override);
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
private final CheckedTextView disableView;
|
private final CheckedTextView disableView;
|
||||||
private final CheckedTextView defaultView;
|
private final CheckedTextView defaultView;
|
||||||
private final ComponentListener componentListener;
|
private final ComponentListener componentListener;
|
||||||
private final List<TrackGroupInfo> trackGroupInfos;
|
private final List<Tracks.Group> trackGroups;
|
||||||
private final Map<TrackGroup, TrackSelectionOverride> overrides;
|
private final Map<TrackGroup, TrackSelectionOverride> overrides;
|
||||||
|
|
||||||
private boolean allowAdaptiveSelections;
|
private boolean allowAdaptiveSelections;
|
||||||
@ -127,7 +127,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
inflater = LayoutInflater.from(context);
|
inflater = LayoutInflater.from(context);
|
||||||
componentListener = new ComponentListener();
|
componentListener = new ComponentListener();
|
||||||
trackNameProvider = new DefaultTrackNameProvider(getResources());
|
trackNameProvider = new DefaultTrackNameProvider(getResources());
|
||||||
trackGroupInfos = new ArrayList<>();
|
trackGroups = new ArrayList<>();
|
||||||
overrides = new HashMap<>();
|
overrides = new HashMap<>();
|
||||||
|
|
||||||
// View for disabling the renderer.
|
// View for disabling the renderer.
|
||||||
@ -183,7 +183,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
if (!allowMultipleOverrides && overrides.size() > 1) {
|
if (!allowMultipleOverrides && overrides.size() > 1) {
|
||||||
// Re-filter the overrides to retain only one of them.
|
// Re-filter the overrides to retain only one of them.
|
||||||
Map<TrackGroup, TrackSelectionOverride> filteredOverrides =
|
Map<TrackGroup, TrackSelectionOverride> filteredOverrides =
|
||||||
filterOverrides(overrides, trackGroupInfos, /* allowMultipleOverrides= */ false);
|
filterOverrides(overrides, trackGroups, /* allowMultipleOverrides= */ false);
|
||||||
overrides.clear();
|
overrides.clear();
|
||||||
overrides.putAll(filteredOverrides);
|
overrides.putAll(filteredOverrides);
|
||||||
}
|
}
|
||||||
@ -214,19 +214,19 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
/**
|
/**
|
||||||
* Initialize the view to select tracks from a specified list of track groups.
|
* Initialize the view to select tracks from a specified list of track groups.
|
||||||
*
|
*
|
||||||
* @param trackGroupInfos {@link TrackGroupInfo TrackGroupInfos} for the track groups.
|
* @param trackGroups The {@link Tracks.Group track groups}.
|
||||||
* @param isDisabled Whether the disabled option should be initially selected.
|
* @param isDisabled Whether the disabled option should be initially selected.
|
||||||
* @param overrides The initially selected track overrides. Any overrides that do not correspond
|
* @param overrides The initially selected track overrides. Any overrides that do not correspond
|
||||||
* to track groups described in {@code trackGroupInfos} will be ignored. If {@link
|
* to track groups in {@code trackGroups} will be ignored. If {@link
|
||||||
* #setAllowMultipleOverrides(boolean)} hasn't been set to {@code true} then all but one
|
* #setAllowMultipleOverrides(boolean)} hasn't been set to {@code true} then all but one
|
||||||
* override will be ignored. The retained override will be the one whose track group is
|
* override will be ignored. The retained override will be the one whose track group is first
|
||||||
* described first in {@code trackGroupInfos}.
|
* in {@code trackGroups}.
|
||||||
* @param trackFormatComparator An optional comparator used to determine the display order of the
|
* @param trackFormatComparator An optional comparator used to determine the display order of the
|
||||||
* tracks within each track group.
|
* tracks within each track group.
|
||||||
* @param listener An optional listener to receive selection updates.
|
* @param listener An optional listener to receive selection updates.
|
||||||
*/
|
*/
|
||||||
public void init(
|
public void init(
|
||||||
List<TrackGroupInfo> trackGroupInfos,
|
List<Tracks.Group> trackGroups,
|
||||||
boolean isDisabled,
|
boolean isDisabled,
|
||||||
Map<TrackGroup, TrackSelectionOverride> overrides,
|
Map<TrackGroup, TrackSelectionOverride> overrides,
|
||||||
@Nullable Comparator<Format> trackFormatComparator,
|
@Nullable Comparator<Format> trackFormatComparator,
|
||||||
@ -238,10 +238,10 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
: (o1, o2) -> trackFormatComparator.compare(o1.getFormat(), o2.getFormat());
|
: (o1, o2) -> trackFormatComparator.compare(o1.getFormat(), o2.getFormat());
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
|
|
||||||
this.trackGroupInfos.clear();
|
this.trackGroups.clear();
|
||||||
this.trackGroupInfos.addAll(trackGroupInfos);
|
this.trackGroups.addAll(trackGroups);
|
||||||
this.overrides.clear();
|
this.overrides.clear();
|
||||||
this.overrides.putAll(filterOverrides(overrides, trackGroupInfos, allowMultipleOverrides));
|
this.overrides.putAll(filterOverrides(overrides, trackGroups, allowMultipleOverrides));
|
||||||
updateViews();
|
updateViews();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,7 +263,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
removeViewAt(i);
|
removeViewAt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trackGroupInfos.isEmpty()) {
|
if (trackGroups.isEmpty()) {
|
||||||
// The view is not initialized.
|
// The view is not initialized.
|
||||||
disableView.setEnabled(false);
|
disableView.setEnabled(false);
|
||||||
defaultView.setEnabled(false);
|
defaultView.setEnabled(false);
|
||||||
@ -273,17 +273,16 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
defaultView.setEnabled(true);
|
defaultView.setEnabled(true);
|
||||||
|
|
||||||
// Add per-track views.
|
// Add per-track views.
|
||||||
trackViews = new CheckedTextView[trackGroupInfos.size()][];
|
trackViews = new CheckedTextView[trackGroups.size()][];
|
||||||
boolean enableMultipleChoiceForMultipleOverrides = shouldEnableMultiGroupSelection();
|
boolean enableMultipleChoiceForMultipleOverrides = shouldEnableMultiGroupSelection();
|
||||||
for (int trackGroupIndex = 0; trackGroupIndex < trackGroupInfos.size(); trackGroupIndex++) {
|
for (int trackGroupIndex = 0; trackGroupIndex < trackGroups.size(); trackGroupIndex++) {
|
||||||
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(trackGroupIndex);
|
Tracks.Group trackGroup = trackGroups.get(trackGroupIndex);
|
||||||
boolean enableMultipleChoiceForAdaptiveSelections =
|
boolean enableMultipleChoiceForAdaptiveSelections = shouldEnableAdaptiveSelection(trackGroup);
|
||||||
shouldEnableAdaptiveSelection(trackGroupInfo);
|
trackViews[trackGroupIndex] = new CheckedTextView[trackGroup.length];
|
||||||
trackViews[trackGroupIndex] = new CheckedTextView[trackGroupInfo.length];
|
|
||||||
|
|
||||||
TrackInfo[] trackInfos = new TrackInfo[trackGroupInfo.length];
|
TrackInfo[] trackInfos = new TrackInfo[trackGroup.length];
|
||||||
for (int trackIndex = 0; trackIndex < trackGroupInfo.length; trackIndex++) {
|
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
|
||||||
trackInfos[trackIndex] = new TrackInfo(trackGroupInfo, trackIndex);
|
trackInfos[trackIndex] = new TrackInfo(trackGroup, trackIndex);
|
||||||
}
|
}
|
||||||
if (trackInfoComparator != null) {
|
if (trackInfoComparator != null) {
|
||||||
Arrays.sort(trackInfos, trackInfoComparator);
|
Arrays.sort(trackInfos, trackInfoComparator);
|
||||||
@ -302,7 +301,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
trackView.setBackgroundResource(selectableItemBackgroundResourceId);
|
trackView.setBackgroundResource(selectableItemBackgroundResourceId);
|
||||||
trackView.setText(trackNameProvider.getTrackName(trackInfos[trackIndex].getFormat()));
|
trackView.setText(trackNameProvider.getTrackName(trackInfos[trackIndex].getFormat()));
|
||||||
trackView.setTag(trackInfos[trackIndex]);
|
trackView.setTag(trackInfos[trackIndex]);
|
||||||
if (trackGroupInfo.isTrackSupported(trackIndex)) {
|
if (trackGroup.isTrackSupported(trackIndex)) {
|
||||||
trackView.setFocusable(true);
|
trackView.setFocusable(true);
|
||||||
trackView.setOnClickListener(componentListener);
|
trackView.setOnClickListener(componentListener);
|
||||||
} else {
|
} else {
|
||||||
@ -321,8 +320,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
disableView.setChecked(isDisabled);
|
disableView.setChecked(isDisabled);
|
||||||
defaultView.setChecked(!isDisabled && overrides.size() == 0);
|
defaultView.setChecked(!isDisabled && overrides.size() == 0);
|
||||||
for (int i = 0; i < trackViews.length; i++) {
|
for (int i = 0; i < trackViews.length; i++) {
|
||||||
@Nullable
|
@Nullable TrackSelectionOverride override = overrides.get(trackGroups.get(i).getTrackGroup());
|
||||||
TrackSelectionOverride override = overrides.get(trackGroupInfos.get(i).getTrackGroup());
|
|
||||||
for (int j = 0; j < trackViews[i].length; j++) {
|
for (int j = 0; j < trackViews[i].length; j++) {
|
||||||
if (override != null) {
|
if (override != null) {
|
||||||
TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(trackViews[i][j].getTag());
|
TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(trackViews[i][j].getTag());
|
||||||
@ -361,7 +359,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
private void onTrackViewClicked(View view) {
|
private void onTrackViewClicked(View view) {
|
||||||
isDisabled = false;
|
isDisabled = false;
|
||||||
TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(view.getTag());
|
TrackInfo trackInfo = (TrackInfo) Assertions.checkNotNull(view.getTag());
|
||||||
TrackGroup trackGroup = trackInfo.trackGroupInfo.getTrackGroup();
|
TrackGroup trackGroup = trackInfo.trackGroup.getTrackGroup();
|
||||||
int trackIndex = trackInfo.trackIndex;
|
int trackIndex = trackInfo.trackIndex;
|
||||||
@Nullable TrackSelectionOverride override = overrides.get(trackGroup);
|
@Nullable TrackSelectionOverride override = overrides.get(trackGroup);
|
||||||
if (override == null) {
|
if (override == null) {
|
||||||
@ -376,7 +374,7 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
// An existing override is being modified.
|
// An existing override is being modified.
|
||||||
ArrayList<Integer> trackIndices = new ArrayList<>(override.trackIndices);
|
ArrayList<Integer> trackIndices = new ArrayList<>(override.trackIndices);
|
||||||
boolean isCurrentlySelected = ((CheckedTextView) view).isChecked();
|
boolean isCurrentlySelected = ((CheckedTextView) view).isChecked();
|
||||||
boolean isAdaptiveAllowed = shouldEnableAdaptiveSelection(trackInfo.trackGroupInfo);
|
boolean isAdaptiveAllowed = shouldEnableAdaptiveSelection(trackInfo.trackGroup);
|
||||||
boolean isUsingCheckBox = isAdaptiveAllowed || shouldEnableMultiGroupSelection();
|
boolean isUsingCheckBox = isAdaptiveAllowed || shouldEnableMultiGroupSelection();
|
||||||
if (isCurrentlySelected && isUsingCheckBox) {
|
if (isCurrentlySelected && isUsingCheckBox) {
|
||||||
// Remove the track from the override.
|
// Remove the track from the override.
|
||||||
@ -401,12 +399,12 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldEnableAdaptiveSelection(TrackGroupInfo trackGroupInfo) {
|
private boolean shouldEnableAdaptiveSelection(Tracks.Group trackGroup) {
|
||||||
return allowAdaptiveSelections && trackGroupInfo.isAdaptiveSupported();
|
return allowAdaptiveSelections && trackGroup.isAdaptiveSupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldEnableMultiGroupSelection() {
|
private boolean shouldEnableMultiGroupSelection() {
|
||||||
return allowMultipleOverrides && trackGroupInfos.size() > 1;
|
return allowMultipleOverrides && trackGroups.size() > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal classes.
|
// Internal classes.
|
||||||
@ -420,16 +418,16 @@ public class TrackSelectionView extends LinearLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final class TrackInfo {
|
private static final class TrackInfo {
|
||||||
public final TrackGroupInfo trackGroupInfo;
|
public final Tracks.Group trackGroup;
|
||||||
public final int trackIndex;
|
public final int trackIndex;
|
||||||
|
|
||||||
public TrackInfo(TrackGroupInfo trackGroupInfo, int trackIndex) {
|
public TrackInfo(Tracks.Group trackGroup, int trackIndex) {
|
||||||
this.trackGroupInfo = trackGroupInfo;
|
this.trackGroup = trackGroup;
|
||||||
this.trackIndex = trackIndex;
|
this.trackIndex = trackIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format getFormat() {
|
public Format getFormat() {
|
||||||
return trackGroupInfo.getTrackFormat(trackIndex);
|
return trackGroup.getTrackFormat(trackIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user