Use TracksInfo and selection override in users

Update the UI module, the demos and most other users
to make use of the new player TracksInfo and track
selection override APIs.

PiperOrigin-RevId: 402817857
This commit is contained in:
krocard 2021-10-13 14:44:46 +01:00 committed by Oliver Woodman
parent fe0a5662de
commit 98ee159df1
10 changed files with 284 additions and 313 deletions

View File

@ -19,7 +19,6 @@ import android.content.Context;
import android.view.KeyEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.MediaItem;
@ -28,12 +27,9 @@ import com.google.android.exoplayer2.Player.DiscontinuityReason;
import com.google.android.exoplayer2.Player.TimelineChangeReason;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.ext.cast.CastPlayer;
import com.google.android.exoplayer2.ext.cast.SessionAvailabilityListener;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.PlayerControlView;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.gms.cast.framework.CastContext;
@ -58,13 +54,12 @@ import java.util.ArrayList;
private final PlayerView localPlayerView;
private final PlayerControlView castControlView;
private final DefaultTrackSelector trackSelector;
private final SimpleExoPlayer exoPlayer;
private final Player localPlayer;
private final CastPlayer castPlayer;
private final ArrayList<MediaItem> mediaQueue;
private final Listener listener;
private TrackGroupArray lastSeenTrackGroupArray;
private TracksInfo lastSeenTrackGroupInfo;
private int currentItemIndex;
private Player currentPlayer;
@ -89,17 +84,16 @@ import java.util.ArrayList;
mediaQueue = new ArrayList<>();
currentItemIndex = C.INDEX_UNSET;
trackSelector = new DefaultTrackSelector(context);
exoPlayer = new ExoPlayer.Builder(context).setTrackSelector(trackSelector).build();
exoPlayer.addListener(this);
localPlayerView.setPlayer(exoPlayer);
localPlayer = new ExoPlayer.Builder(context).build();
localPlayer.addListener(this);
localPlayerView.setPlayer(localPlayer);
castPlayer = new CastPlayer(castContext);
castPlayer.addListener(this);
castPlayer.setSessionAvailabilityListener(this);
castControlView.setPlayer(castPlayer);
setCurrentPlayer(castPlayer.isCastSessionAvailable() ? castPlayer : exoPlayer);
setCurrentPlayer(castPlayer.isCastSessionAvailable() ? castPlayer : localPlayer);
}
// Queue manipulation methods.
@ -200,7 +194,7 @@ import java.util.ArrayList;
* @return Whether the event was handled by the target view.
*/
public boolean dispatchKeyEvent(KeyEvent event) {
if (currentPlayer == exoPlayer) {
if (currentPlayer == localPlayer) {
return localPlayerView.dispatchKeyEvent(event);
} else /* currentPlayer == castPlayer */ {
return castControlView.dispatchKeyEvent(event);
@ -214,7 +208,7 @@ import java.util.ArrayList;
castPlayer.setSessionAvailabilityListener(null);
castPlayer.release();
localPlayerView.setPlayer(null);
exoPlayer.release();
localPlayer.release();
}
// Player.Listener implementation.
@ -238,24 +232,17 @@ import java.util.ArrayList;
}
@Override
public void onTracksChanged(
@NonNull TrackGroupArray trackGroups, @NonNull TrackSelectionArray trackSelections) {
if (currentPlayer == exoPlayer && trackGroups != lastSeenTrackGroupArray) {
@Nullable
MappingTrackSelector.MappedTrackInfo mappedTrackInfo =
trackSelector.getCurrentMappedTrackInfo();
if (mappedTrackInfo != null) {
if (mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_VIDEO)
== MappingTrackSelector.MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
listener.onUnsupportedTrack(C.TRACK_TYPE_VIDEO);
}
if (mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_AUDIO)
== MappingTrackSelector.MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
listener.onUnsupportedTrack(C.TRACK_TYPE_AUDIO);
}
}
lastSeenTrackGroupArray = trackGroups;
public void onTracksInfoChanged(TracksInfo tracksInfo) {
if (currentPlayer != localPlayer || tracksInfo == lastSeenTrackGroupInfo) {
return;
}
if (!tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_VIDEO)) {
listener.onUnsupportedTrack(C.TRACK_TYPE_VIDEO);
}
if (!tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_AUDIO)) {
listener.onUnsupportedTrack(C.TRACK_TYPE_AUDIO);
}
lastSeenTrackGroupInfo = tracksInfo;
}
// CastPlayer.SessionAvailabilityListener implementation.
@ -267,7 +254,7 @@ import java.util.ArrayList;
@Override
public void onCastSessionUnavailable() {
setCurrentPlayer(exoPlayer);
setCurrentPlayer(localPlayer);
}
// Internal methods.
@ -286,7 +273,7 @@ import java.util.ArrayList;
}
// View management.
if (currentPlayer == exoPlayer) {
if (currentPlayer == localPlayer) {
localPlayerView.setVisibility(View.VISIBLE);
castControlView.hide();
} else /* currentPlayer == castPlayer */ {

View File

@ -38,6 +38,7 @@ import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.drm.FrameworkMediaDrm;
import com.google.android.exoplayer2.ext.ima.ImaAdsLoader;
@ -46,11 +47,8 @@ import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryExcep
import com.google.android.exoplayer2.offline.DownloadRequest;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.StyledPlayerControlView;
import com.google.android.exoplayer2.ui.StyledPlayerView;
import com.google.android.exoplayer2.upstream.DataSource;
@ -69,7 +67,7 @@ public class PlayerActivity extends AppCompatActivity
// Saved instance state keys.
private static final String KEY_TRACK_SELECTOR_PARAMETERS = "track_selector_parameters";
private static final String KEY_TRACK_SELECTION_PARAMETERS = "track_selection_parameters";
private static final String KEY_WINDOW = "window";
private static final String KEY_POSITION = "position";
private static final String KEY_AUTO_PLAY = "auto_play";
@ -84,9 +82,9 @@ public class PlayerActivity extends AppCompatActivity
private DataSource.Factory dataSourceFactory;
private List<MediaItem> mediaItems;
private DefaultTrackSelector trackSelector;
private DefaultTrackSelector.Parameters trackSelectorParameters;
private DefaultTrackSelector.Parameters trackSelectionParameters;
private DebugTextViewHelper debugViewHelper;
private TrackGroupArray lastSeenTrackGroupArray;
private TracksInfo lastSeenTracksInfo;
private boolean startAutoPlay;
private int startWindow;
private long startPosition;
@ -114,16 +112,16 @@ public class PlayerActivity extends AppCompatActivity
playerView.requestFocus();
if (savedInstanceState != null) {
trackSelectorParameters =
// Restore as DefaultTrackSelector.Parameters in case ExoPlayer specific parameters were set.
trackSelectionParameters =
DefaultTrackSelector.Parameters.CREATOR.fromBundle(
savedInstanceState.getBundle(KEY_TRACK_SELECTOR_PARAMETERS));
savedInstanceState.getBundle(KEY_TRACK_SELECTION_PARAMETERS));
startAutoPlay = savedInstanceState.getBoolean(KEY_AUTO_PLAY);
startWindow = savedInstanceState.getInt(KEY_WINDOW);
startPosition = savedInstanceState.getLong(KEY_POSITION);
} else {
DefaultTrackSelector.ParametersBuilder builder =
new DefaultTrackSelector.ParametersBuilder(/* context= */ this);
trackSelectorParameters = builder.build();
trackSelectionParameters =
new DefaultTrackSelector.ParametersBuilder(/* context= */ this).build();
clearStartPosition();
}
}
@ -209,7 +207,7 @@ public class PlayerActivity extends AppCompatActivity
super.onSaveInstanceState(outState);
updateTrackSelectorParameters();
updateStartPosition();
outState.putBundle(KEY_TRACK_SELECTOR_PARAMETERS, trackSelectorParameters.toBundle());
outState.putBundle(KEY_TRACK_SELECTION_PARAMETERS, trackSelectionParameters.toBundle());
outState.putBoolean(KEY_AUTO_PLAY, startAutoPlay);
outState.putInt(KEY_WINDOW, startWindow);
outState.putLong(KEY_POSITION, startPosition);
@ -272,13 +270,13 @@ public class PlayerActivity extends AppCompatActivity
.setAdViewProvider(playerView);
trackSelector = new DefaultTrackSelector(/* context= */ this);
trackSelector.setParameters(trackSelectorParameters);
lastSeenTrackGroupArray = null;
lastSeenTracksInfo = TracksInfo.EMPTY;
player =
new ExoPlayer.Builder(/* context= */ this, renderersFactory)
.setMediaSourceFactory(mediaSourceFactory)
.setTrackSelector(trackSelector)
.build();
player.setTrackSelectionParameters(trackSelectionParameters);
player.addListener(new PlayerEventListener());
player.addAnalyticsListener(new EventLogger(trackSelector));
player.setAudioAttributes(AudioAttributes.DEFAULT, /* handleAudioFocus= */ true);
@ -361,7 +359,6 @@ public class PlayerActivity extends AppCompatActivity
player.release();
player = null;
mediaItems = Collections.emptyList();
trackSelector = null;
}
if (adsLoader != null) {
adsLoader.setPlayer(null);
@ -377,8 +374,11 @@ public class PlayerActivity extends AppCompatActivity
}
private void updateTrackSelectorParameters() {
if (trackSelector != null) {
trackSelectorParameters = trackSelector.getParameters();
if (player != null) {
// Until the demo app is fully migrated to TrackSelectionParameters, rely on ExoPlayer to use
// DefaultTrackSelector by default.
trackSelectionParameters =
(DefaultTrackSelector.Parameters) player.getTrackSelectionParameters();
}
}
@ -438,23 +438,18 @@ public class PlayerActivity extends AppCompatActivity
@Override
@SuppressWarnings("ReferenceEquality")
public void onTracksChanged(
@NonNull TrackGroupArray trackGroups, @NonNull TrackSelectionArray trackSelections) {
public void onTracksInfoChanged(TracksInfo tracksInfo) {
updateButtonVisibility();
if (trackGroups != lastSeenTrackGroupArray) {
MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
if (mappedTrackInfo != null) {
if (mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_VIDEO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
showToast(R.string.error_unsupported_video);
}
if (mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_AUDIO)
== MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) {
showToast(R.string.error_unsupported_audio);
}
}
lastSeenTrackGroupArray = trackGroups;
if (tracksInfo == lastSeenTracksInfo) {
return;
}
if (!tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_VIDEO)) {
showToast(R.string.error_unsupported_video);
}
if (!tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_AUDIO)) {
showToast(R.string.error_unsupported_audio);
}
lastSeenTracksInfo = tracksInfo;
}
}

View File

@ -58,8 +58,6 @@ import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
import com.google.android.exoplayer2.source.ads.AdsLoader.EventListener;
import com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionUtil;
import com.google.android.exoplayer2.ui.AdOverlayInfo;
import com.google.android.exoplayer2.ui.AdViewProvider;
import com.google.android.exoplayer2.upstream.DataSpec;
@ -706,8 +704,7 @@ import java.util.Map;
}
// Check for a selected track using an audio renderer.
TrackSelectionArray trackSelections = player.getCurrentTrackSelections();
return TrackSelectionUtil.hasTrackOfType(trackSelections, C.TRACK_TYPE_AUDIO) ? 100 : 0;
return player.getCurrentTracksInfo().isTypeSelected(C.TRACK_TYPE_AUDIO) ? 100 : 0;
}
private void handleAdEvent(AdEvent adEvent) {

View File

@ -112,10 +112,13 @@ public final class TracksInfo implements Bundleable {
/**
* Returns if a track in a {@link TrackGroup} is selected for playback.
*
* <p>Multiple tracks of a track group may be selected, in which case the the active one
* (currently playing) is undefined. This is common in adaptive streaming, where multiple tracks
* of different quality are selected and the active one changes depending on the network and the
* {@link TrackSelectionParameters}.
* <p>Multiple tracks of a track group may be selected. This is common in adaptive streaming,
* where multiple tracks of different quality are selected and the player switches between them
* depending on the network and the {@link TrackSelectionParameters}.
*
* <p>While this class doesn't provide which selected track is currently playing, some player
* implementations have ways of getting such information. For example ExoPlayer provides this
* information in {@code ExoTrackSelection.getSelectedFormat}.
*
* @param trackIndex The index of the track in the {@link TrackGroup}.
* @return true if the track is selected, false otherwise.

View File

@ -27,6 +27,7 @@ import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndException;
import com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndFormat;
import com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndPlaybackState;
@ -34,9 +35,7 @@ import com.google.android.exoplayer2.analytics.PlaybackStats.PlaybackState;
import com.google.android.exoplayer2.source.LoadEventInfo;
import com.google.android.exoplayer2.source.MediaLoadData;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoSize;
import java.io.IOException;
@ -523,23 +522,11 @@ public final class PlaybackStatsListener
hasFatalError = false;
}
if (isForeground && !isInterruptedByAd) {
boolean videoEnabled = false;
boolean audioEnabled = false;
for (TrackSelection trackSelection : player.getCurrentTrackSelections().getAll()) {
if (trackSelection != null && trackSelection.length() > 0) {
@C.TrackType
int trackType = MimeTypes.getTrackType(trackSelection.getFormat(0).sampleMimeType);
if (trackType == C.TRACK_TYPE_VIDEO) {
videoEnabled = true;
} else if (trackType == C.TRACK_TYPE_AUDIO) {
audioEnabled = true;
}
}
}
if (!videoEnabled) {
TracksInfo currentTracksInfo = player.getCurrentTracksInfo();
if (!currentTracksInfo.isTypeSelected(C.TRACK_TYPE_VIDEO)) {
maybeUpdateVideoFormat(eventTime, /* newFormat= */ null);
}
if (!audioEnabled) {
if (!currentTracksInfo.isTypeSelected(C.TRACK_TYPE_AUDIO)) {
maybeUpdateAudioFormat(eventTime, /* newFormat= */ null);
}
}

View File

@ -17,12 +17,21 @@ package com.google.android.exoplayer2.trackselection;
import android.os.SystemClock;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection.Definition;
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters.TrackSelectionOverride;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import org.checkerframework.checker.nullness.compatqual.NullableType;
import org.checkerframework.dataflow.qual.Pure;
/** Track selection related utility methods. */
public final class TrackSelectionUtil {
@ -101,22 +110,6 @@ public final class TrackSelectionUtil {
return builder.build();
}
/** Returns if a {@link TrackSelectionArray} has at least one track of the given type. */
public static boolean hasTrackOfType(TrackSelectionArray trackSelections, int trackType) {
for (int i = 0; i < trackSelections.length; i++) {
@Nullable TrackSelection trackSelection = trackSelections.get(i);
if (trackSelection == null) {
continue;
}
for (int j = 0; j < trackSelection.length(); j++) {
if (MimeTypes.getTrackType(trackSelection.getFormat(j).sampleMimeType) == trackType) {
return true;
}
}
}
return false;
}
/**
* Returns the {@link LoadErrorHandlingPolicy.FallbackOptions} with the tracks of the given {@link
* ExoTrackSelection} and with a single location option indicating that there are no alternative
@ -141,4 +134,67 @@ public final class TrackSelectionUtil {
numberOfTracks,
numberOfExcludedTracks);
}
/**
* Forces tracks in a {@link TrackGroup} to be the only ones selected for a {@link C.TrackType}.
* No other tracks of that type will be selectable. If the forced tracks are not supported, then
* no tracks of that type will be selected.
*
* @param trackSelectionOverrides The current {@link TrackSelectionOverride overrides}.
* @param tracksInfo The current {@link TracksInfo}.
* @param forcedTrackGroupIndex The index of the {@link TrackGroup} in {@code tracksInfo} that
* should have its track selected.
* @param forcedTrackSelectionOverride The tracks to force selection of.
* @return The updated {@link TrackSelectionOverride overrides}.
*/
@Pure
public static ImmutableMap<TrackGroup, TrackSelectionOverride> forceTrackSelection(
ImmutableMap<TrackGroup, TrackSelectionOverride> trackSelectionOverrides,
TracksInfo tracksInfo,
int forcedTrackGroupIndex,
TrackSelectionOverride forcedTrackSelectionOverride) {
@C.TrackType
int trackType = tracksInfo.getTrackGroupInfos().get(forcedTrackGroupIndex).getTrackType();
ImmutableMap.Builder<TrackGroup, TrackSelectionOverride> overridesBuilder =
new ImmutableMap.Builder<>();
// Maintain overrides for the other track types.
for (Map.Entry<TrackGroup, TrackSelectionOverride> entry : trackSelectionOverrides.entrySet()) {
if (MimeTypes.getTrackType(entry.getKey().getFormat(0).sampleMimeType) != trackType) {
overridesBuilder.put(entry);
}
}
ImmutableList<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
for (int i = 0; i < trackGroupInfos.size(); i++) {
TrackGroup trackGroup = trackGroupInfos.get(i).getTrackGroup();
if (i == forcedTrackGroupIndex) {
overridesBuilder.put(trackGroup, forcedTrackSelectionOverride);
} else {
overridesBuilder.put(trackGroup, TrackSelectionOverride.DISABLE);
}
}
return overridesBuilder.build();
}
/**
* Removes all {@link TrackSelectionOverride overrides} associated with {@link TrackGroup
* TrackGroups} of type {@code trackType}.
*
* @param trackType The {@link C.TrackType} of all overrides to remove.
* @param trackSelectionOverrides The current {@link TrackSelectionOverride overrides}.
* @return The updated {@link TrackSelectionOverride overrides}.
*/
@Pure
public static ImmutableMap<TrackGroup, TrackSelectionOverride>
clearTrackSelectionOverridesForType(
@C.TrackType int trackType,
ImmutableMap<TrackGroup, TrackSelectionOverride> trackSelectionOverrides) {
ImmutableMap.Builder<TrackGroup, TrackSelectionOverride> overridesBuilder =
ImmutableMap.builder();
for (Map.Entry<TrackGroup, TrackSelectionOverride> entry : trackSelectionOverrides.entrySet()) {
if (MimeTypes.getTrackType(entry.getKey().getFormat(0).sampleMimeType) != trackType) {
overridesBuilder.put(entry);
}
}
return overridesBuilder.build();
}
}

View File

@ -7349,7 +7349,7 @@ public final class ExoPlayerTest {
}
};
AtomicReference<Timeline> timelineAfterError = new AtomicReference<>();
AtomicReference<TrackGroupArray> trackGroupsAfterError = new AtomicReference<>();
AtomicReference<TracksInfo> trackInfosAfterError = new AtomicReference<>();
AtomicReference<TrackSelectionArray> trackSelectionsAfterError = new AtomicReference<>();
AtomicInteger windowIndexAfterError = new AtomicInteger();
ActionSchedule actionSchedule =
@ -7363,7 +7363,7 @@ public final class ExoPlayerTest {
@Override
public void onPlayerError(EventTime eventTime, PlaybackException error) {
timelineAfterError.set(player.getCurrentTimeline());
trackGroupsAfterError.set(player.getCurrentTrackGroups());
trackInfosAfterError.set(player.getCurrentTracksInfo());
trackSelectionsAfterError.set(player.getCurrentTrackSelections());
windowIndexAfterError.set(player.getCurrentWindowIndex());
}
@ -7393,8 +7393,8 @@ public final class ExoPlayerTest {
assertThat(timelineAfterError.get().getWindowCount()).isEqualTo(1);
assertThat(windowIndexAfterError.get()).isEqualTo(0);
assertThat(trackGroupsAfterError.get().length).isEqualTo(1);
assertThat(trackGroupsAfterError.get().get(0).getFormat(0))
assertThat(trackInfosAfterError.get().getTrackGroupInfos()).hasSize(1);
assertThat(trackInfosAfterError.get().getTrackGroupInfos().get(0).getTrackGroup().getFormat(0))
.isEqualTo(ExoPlayerTestRunner.AUDIO_FORMAT);
assertThat(trackSelectionsAfterError.get().get(0)).isNull(); // Video renderer.
assertThat(trackSelectionsAfterError.get().get(1)).isNotNull(); // Audio renderer.

View File

@ -47,7 +47,6 @@ import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ControlDispatcher;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ForwardingPlayer;
import com.google.android.exoplayer2.MediaMetadata;
import com.google.android.exoplayer2.PlaybackException;
@ -57,12 +56,9 @@ import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ErrorMessageProvider;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.RepeatModeUtil;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoSize;
@ -1256,7 +1252,9 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
private void updateForCurrentTrackSelections(boolean isNewPlayer) {
@Nullable Player player = this.player;
if (player == null || player.getCurrentTrackGroups().isEmpty()) {
if (player == null
|| !player.isCommandAvailable(Player.COMMAND_GET_TRACK_INFOS)
|| player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) {
if (!keepContentOnPlayerReset) {
hideArtwork();
closeShutter();
@ -1268,21 +1266,11 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
// Hide any video from the previous player.
closeShutter();
}
TrackSelectionArray trackSelections = player.getCurrentTrackSelections();
for (int i = 0; i < trackSelections.length; i++) {
@Nullable TrackSelection trackSelection = trackSelections.get(i);
if (trackSelection != null) {
for (int j = 0; j < trackSelection.length(); j++) {
Format format = trackSelection.getFormat(j);
if (MimeTypes.getTrackType(format.sampleMimeType) == C.TRACK_TYPE_VIDEO) {
// Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened
// in onRenderedFirstFrame().
hideArtwork();
return;
}
}
}
if (player.getCurrentTracksInfo().isTypeSelected(C.TRACK_TYPE_VIDEO)) {
// Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened
// in onRenderedFirstFrame().
hideArtwork();
return;
}
// Video disabled so the shutter must be closed.
@ -1518,7 +1506,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
Timeline timeline = player.getCurrentTimeline();
if (timeline.isEmpty()) {
lastPeriodUidWithTracks = null;
} else if (!player.getCurrentTrackGroups().isEmpty()) {
} else if (!player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) {
lastPeriodUidWithTracks =
timeline.getPeriod(player.getCurrentPeriodIndex(), period, /* setIds= */ true).uid;
} else if (lastPeriodUidWithTracks != null) {

View File

@ -32,6 +32,8 @@ import static com.google.android.exoplayer2.Player.EVENT_SEEK_FORWARD_INCREMENT_
import static com.google.android.exoplayer2.Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED;
import static com.google.android.exoplayer2.Player.EVENT_TIMELINE_CHANGED;
import static com.google.android.exoplayer2.Player.EVENT_TRACKS_CHANGED;
import static com.google.android.exoplayer2.trackselection.TrackSelectionUtil.clearTrackSelectionOverridesForType;
import static com.google.android.exoplayer2.trackselection.TrackSelectionUtil.forceTrackSelection;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import android.annotation.SuppressLint;
@ -59,7 +61,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ControlDispatcher;
import com.google.android.exoplayer2.DefaultControlDispatcher;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ForwardingPlayer;
@ -67,24 +68,23 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Player.Events;
import com.google.android.exoplayer2.Player.State;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters;
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters.TrackSelectionOverride;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.RepeatModeUtil;
import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Formatter;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@ -437,9 +437,8 @@ public class StyledPlayerControlView extends FrameLayout {
private boolean needToHideBars;
private int settingsWindowMargin;
@Nullable private DefaultTrackSelector trackSelector;
private TrackSelectionAdapter textTrackSelectionAdapter;
private TrackSelectionAdapter audioTrackSelectionAdapter;
private TextTrackSelectionAdapter textTrackSelectionAdapter;
private AudioTrackSelectionAdapter audioTrackSelectionAdapter;
// TODO(insun): Add setTrackNameProvider to use customized track name provider.
private TrackNameProvider trackNameProvider;
@ -764,14 +763,6 @@ public class StyledPlayerControlView extends FrameLayout {
if (player instanceof ForwardingPlayer) {
player = ((ForwardingPlayer) player).getWrappedPlayer();
}
if (player instanceof ExoPlayer) {
TrackSelector trackSelector = ((ExoPlayer) player).getTrackSelector();
if (trackSelector instanceof DefaultTrackSelector) {
this.trackSelector = (DefaultTrackSelector) trackSelector;
}
} else {
this.trackSelector = null;
}
updateAll();
}
@ -818,7 +809,7 @@ public class StyledPlayerControlView extends FrameLayout {
* @param listener The listener to be notified about visibility changes.
*/
public void addVisibilityListener(VisibilityListener listener) {
Assertions.checkNotNull(listener);
checkNotNull(listener);
visibilityListeners.add(listener);
}
@ -1254,58 +1245,46 @@ public class StyledPlayerControlView extends FrameLayout {
private void initTrackSelectionAdapter() {
textTrackSelectionAdapter.clear();
audioTrackSelectionAdapter.clear();
if (player == null || trackSelector == null) {
if (player == null
|| !player.isCommandAvailable(Player.COMMAND_GET_TRACK_INFOS)
|| !player.isCommandAvailable(Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
return;
}
DefaultTrackSelector trackSelector = this.trackSelector;
@Nullable MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
if (mappedTrackInfo == null) {
TracksInfo tracksInfo = player.getCurrentTracksInfo();
List<TrackGroupInfo> trackGroupInfos = tracksInfo.getTrackGroupInfos();
if (trackGroupInfos.isEmpty()) {
return;
}
List<TrackInfo> textTracks = new ArrayList<>();
List<TrackInfo> audioTracks = new ArrayList<>();
List<Integer> textRendererIndices = new ArrayList<>();
List<Integer> audioRendererIndices = new ArrayList<>();
for (int rendererIndex = 0;
rendererIndex < mappedTrackInfo.getRendererCount();
rendererIndex++) {
if (mappedTrackInfo.getRendererType(rendererIndex) == C.TRACK_TYPE_TEXT
List<TrackInformation> textTracks = new ArrayList<>();
List<TrackInformation> audioTracks = new ArrayList<>();
for (int trackGroupIndex = 0; trackGroupIndex < trackGroupInfos.size(); trackGroupIndex++) {
TrackGroupInfo trackGroupInfo = trackGroupInfos.get(trackGroupIndex);
if (!trackGroupInfo.isSupported()) {
continue;
}
if (trackGroupInfo.getTrackType() == C.TRACK_TYPE_TEXT
&& controlViewLayoutManager.getShowButton(subtitleButton)) {
// Get TrackSelection at the corresponding renderer index.
gatherTrackInfosForAdapter(mappedTrackInfo, rendererIndex, textTracks);
textRendererIndices.add(rendererIndex);
} else if (mappedTrackInfo.getRendererType(rendererIndex) == C.TRACK_TYPE_AUDIO) {
gatherTrackInfosForAdapter(mappedTrackInfo, rendererIndex, audioTracks);
audioRendererIndices.add(rendererIndex);
gatherTrackInfosForAdapter(tracksInfo, trackGroupIndex, textTracks);
} else if (trackGroupInfo.getTrackType() == C.TRACK_TYPE_AUDIO) {
gatherTrackInfosForAdapter(tracksInfo, trackGroupIndex, audioTracks);
}
}
textTrackSelectionAdapter.init(textRendererIndices, textTracks, mappedTrackInfo);
audioTrackSelectionAdapter.init(audioRendererIndices, audioTracks, mappedTrackInfo);
textTrackSelectionAdapter.init(textTracks);
audioTrackSelectionAdapter.init(audioTracks);
}
private void gatherTrackInfosForAdapter(
MappedTrackInfo mappedTrackInfo, int rendererIndex, List<TrackInfo> tracks) {
TrackGroupArray trackGroupArray = mappedTrackInfo.getTrackGroups(rendererIndex);
TracksInfo tracksInfo, int trackGroupIndex, List<TrackInformation> tracks) {
TrackSelectionArray trackSelections = checkNotNull(player).getCurrentTrackSelections();
@Nullable TrackSelection trackSelection = trackSelections.get(rendererIndex);
for (int groupIndex = 0; groupIndex < trackGroupArray.length; groupIndex++) {
TrackGroup trackGroup = trackGroupArray.get(groupIndex);
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
Format format = trackGroup.getFormat(trackIndex);
if (mappedTrackInfo.getTrackSupport(rendererIndex, groupIndex, trackIndex)
== C.FORMAT_HANDLED) {
boolean trackIsSelected =
trackSelection != null && trackSelection.indexOf(format) != C.INDEX_UNSET;
tracks.add(
new TrackInfo(
rendererIndex,
groupIndex,
trackIndex,
trackNameProvider.getTrackName(format),
trackIsSelected));
}
TrackGroupInfo trackGroupInfo = tracksInfo.getTrackGroupInfos().get(trackGroupIndex);
TrackGroup trackGroup = trackGroupInfo.getTrackGroup();
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
Format format = trackGroup.getFormat(trackIndex);
if (trackGroupInfo.isTrackSupported(trackIndex)) {
tracks.add(
new TrackInformation(
tracksInfo, trackGroupIndex, trackIndex, trackNameProvider.getTrackName(format)));
}
}
}
@ -1988,33 +1967,36 @@ public class StyledPlayerControlView extends FrameLayout {
}
}
private static final class TrackInfo {
private static final class TrackInformation {
public final int rendererIndex;
public final int groupIndex;
private TracksInfo tracksInfo;
private int trackGroupIndex;
public final TrackGroupInfo trackGroupInfo;
public final TrackGroup trackGroup;
public final int trackIndex;
public final String trackName;
public final boolean selected;
public TrackInfo(
int rendererIndex, int groupIndex, int trackIndex, String trackName, boolean selected) {
this.rendererIndex = rendererIndex;
this.groupIndex = groupIndex;
public TrackInformation(
TracksInfo tracksInfo, int trackGroupIndex, int trackIndex, String trackName) {
this.tracksInfo = tracksInfo;
this.trackGroupIndex = trackGroupIndex;
this.trackGroupInfo = tracksInfo.getTrackGroupInfos().get(trackGroupIndex);
this.trackGroup = trackGroupInfo.getTrackGroup();
this.trackIndex = trackIndex;
this.trackName = trackName;
this.selected = selected;
}
public boolean isSelected() {
return trackGroupInfo.isTrackSelected(trackIndex);
}
}
private final class TextTrackSelectionAdapter extends TrackSelectionAdapter {
@Override
public void init(
List<Integer> rendererIndices,
List<TrackInfo> trackInfos,
MappedTrackInfo mappedTrackInfo) {
public void init(List<TrackInformation> trackInformations) {
boolean subtitleIsOn = false;
for (int i = 0; i < trackInfos.size(); i++) {
if (trackInfos.get(i).selected) {
for (int i = 0; i < trackInformations.size(); i++) {
if (trackInformations.get(i).isSelected()) {
subtitleIsOn = true;
break;
}
@ -2026,9 +2008,7 @@ public class StyledPlayerControlView extends FrameLayout {
subtitleButton.setContentDescription(
subtitleIsOn ? subtitleOnContentDescription : subtitleOffContentDescription);
}
this.rendererIndices = rendererIndices;
this.tracks = trackInfos;
this.mappedTrackInfo = mappedTrackInfo;
this.tracks = trackInformations;
}
@Override
@ -2037,7 +2017,7 @@ public class StyledPlayerControlView extends FrameLayout {
holder.textView.setText(R.string.exo_track_selection_none);
boolean isTrackSelectionOff = true;
for (int i = 0; i < tracks.size(); i++) {
if (tracks.get(i).selected) {
if (tracks.get(i).isSelected()) {
isTrackSelectionOff = false;
break;
}
@ -2045,16 +2025,18 @@ public class StyledPlayerControlView extends FrameLayout {
holder.checkView.setVisibility(isTrackSelectionOff ? VISIBLE : INVISIBLE);
holder.itemView.setOnClickListener(
v -> {
if (trackSelector != null) {
ParametersBuilder parametersBuilder = trackSelector.getParameters().buildUpon();
for (int i = 0; i < rendererIndices.size(); i++) {
int rendererIndex = rendererIndices.get(i);
parametersBuilder =
parametersBuilder
.clearSelectionOverrides(rendererIndex)
.setRendererDisabled(rendererIndex, true);
}
checkNotNull(trackSelector).setParameters(parametersBuilder);
if (player != null) {
TrackSelectionParameters trackSelectionParameters =
player.getTrackSelectionParameters();
player.setTrackSelectionParameters(
trackSelectionParameters
.buildUpon()
.setDisabledTrackTypes(
new ImmutableSet.Builder<@C.TrackType Integer>()
.addAll(trackSelectionParameters.disabledTrackTypes)
.add(C.TRACK_TYPE_TEXT)
.build())
.build());
settingsWindow.dismiss();
}
});
@ -2064,8 +2046,8 @@ public class StyledPlayerControlView extends FrameLayout {
public void onBindViewHolder(SubSettingViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
if (position > 0) {
TrackInfo track = tracks.get(position - 1);
holder.checkView.setVisibility(track.selected ? VISIBLE : INVISIBLE);
TrackInformation track = tracks.get(position - 1);
holder.checkView.setVisibility(track.isSelected() ? VISIBLE : INVISIBLE);
}
}
@ -2083,11 +2065,9 @@ public class StyledPlayerControlView extends FrameLayout {
holder.textView.setText(R.string.exo_track_selection_auto);
// hasSelectionOverride is true means there is an explicit track selection, not "Auto".
boolean hasSelectionOverride = false;
DefaultTrackSelector.Parameters parameters = checkNotNull(trackSelector).getParameters();
for (int i = 0; i < rendererIndices.size(); i++) {
int rendererIndex = rendererIndices.get(i);
TrackGroupArray trackGroups = checkNotNull(mappedTrackInfo).getTrackGroups(rendererIndex);
if (parameters.hasSelectionOverride(rendererIndex, trackGroups)) {
TrackSelectionParameters parameters = checkNotNull(player).getTrackSelectionParameters();
for (int i = 0; i < tracks.size(); i++) {
if (parameters.trackSelectionOverrides.containsKey(tracks.get(i).trackGroup)) {
hasSelectionOverride = true;
break;
}
@ -2095,14 +2075,20 @@ public class StyledPlayerControlView extends FrameLayout {
holder.checkView.setVisibility(hasSelectionOverride ? INVISIBLE : VISIBLE);
holder.itemView.setOnClickListener(
v -> {
if (trackSelector != null) {
ParametersBuilder parametersBuilder = trackSelector.getParameters().buildUpon();
for (int i = 0; i < rendererIndices.size(); i++) {
int rendererIndex = rendererIndices.get(i);
parametersBuilder = parametersBuilder.clearSelectionOverrides(rendererIndex);
}
checkNotNull(trackSelector).setParameters(parametersBuilder);
if (player == null) {
return;
}
TrackSelectionParameters trackSelectionParameters =
player.getTrackSelectionParameters();
// Remove all audio overrides.
ImmutableMap<TrackGroup, TrackSelectionOverride> trackSelectionOverrides =
clearTrackSelectionOverridesForType(
C.TRACK_TYPE_AUDIO, trackSelectionParameters.trackSelectionOverrides);
player.setTrackSelectionParameters(
trackSelectionParameters
.buildUpon()
.setTrackSelectionOverrides(trackSelectionOverrides)
.build());
settingsAdapter.setSubTextAtPosition(
SETTINGS_AUDIO_TRACK_SELECTION_POSITION,
getResources().getString(R.string.exo_track_selection_auto));
@ -2116,22 +2102,19 @@ public class StyledPlayerControlView extends FrameLayout {
}
@Override
public void init(
List<Integer> rendererIndices,
List<TrackInfo> trackInfos,
MappedTrackInfo mappedTrackInfo) {
public void init(List<TrackInformation> trackInformations) {
// Update subtext in settings menu with current audio track selection.
boolean hasSelectionOverride = false;
for (int i = 0; i < rendererIndices.size(); i++) {
int rendererIndex = rendererIndices.get(i);
TrackGroupArray trackGroups = mappedTrackInfo.getTrackGroups(rendererIndex);
if (trackSelector != null
&& trackSelector.getParameters().hasSelectionOverride(rendererIndex, trackGroups)) {
for (int i = 0; i < trackInformations.size(); i++) {
if (checkNotNull(player)
.getTrackSelectionParameters()
.trackSelectionOverrides
.containsKey(trackInformations.get(i).trackGroup)) {
hasSelectionOverride = true;
break;
}
}
if (trackInfos.isEmpty()) {
if (trackInformations.isEmpty()) {
settingsAdapter.setSubTextAtPosition(
SETTINGS_AUDIO_TRACK_SELECTION_POSITION,
getResources().getString(R.string.exo_track_selection_none));
@ -2142,35 +2125,28 @@ public class StyledPlayerControlView extends FrameLayout {
SETTINGS_AUDIO_TRACK_SELECTION_POSITION,
getResources().getString(R.string.exo_track_selection_auto));
} else {
for (int i = 0; i < trackInfos.size(); i++) {
TrackInfo track = trackInfos.get(i);
if (track.selected) {
for (int i = 0; i < trackInformations.size(); i++) {
TrackInformation track = trackInformations.get(i);
if (track.isSelected()) {
settingsAdapter.setSubTextAtPosition(
SETTINGS_AUDIO_TRACK_SELECTION_POSITION, track.trackName);
break;
}
}
}
this.rendererIndices = rendererIndices;
this.tracks = trackInfos;
this.mappedTrackInfo = mappedTrackInfo;
this.tracks = trackInformations;
}
}
private abstract class TrackSelectionAdapter extends RecyclerView.Adapter<SubSettingViewHolder> {
protected List<Integer> rendererIndices;
protected List<TrackInfo> tracks;
protected @Nullable MappedTrackInfo mappedTrackInfo;
protected List<TrackInformation> tracks;
public TrackSelectionAdapter() {
this.rendererIndices = new ArrayList<>();
protected TrackSelectionAdapter() {
this.tracks = new ArrayList<>();
this.mappedTrackInfo = null;
}
public abstract void init(
List<Integer> rendererIndices, List<TrackInfo> trackInfos, MappedTrackInfo mappedTrackInfo);
public abstract void init(List<TrackInformation> trackInformations);
@Override
public SubSettingViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
@ -2181,52 +2157,48 @@ public class StyledPlayerControlView extends FrameLayout {
return new SubSettingViewHolder(v);
}
public abstract void onBindViewHolderAtZeroPosition(SubSettingViewHolder holder);
protected abstract void onBindViewHolderAtZeroPosition(SubSettingViewHolder holder);
public abstract void onTrackSelection(String subtext);
protected abstract void onTrackSelection(String subtext);
@Override
public void onBindViewHolder(SubSettingViewHolder holder, int position) {
if (trackSelector == null || mappedTrackInfo == null) {
if (player == null) {
return;
}
if (position == 0) {
onBindViewHolderAtZeroPosition(holder);
} else {
TrackInfo track = tracks.get(position - 1);
TrackGroupArray trackGroups = mappedTrackInfo.getTrackGroups(track.rendererIndex);
TrackInformation track = tracks.get(position - 1);
boolean explicitlySelected =
checkNotNull(trackSelector)
.getParameters()
.hasSelectionOverride(track.rendererIndex, trackGroups)
&& track.selected;
checkNotNull(player)
.getTrackSelectionParameters()
.trackSelectionOverrides
.containsKey(track.trackGroup)
&& track.isSelected();
holder.textView.setText(track.trackName);
holder.checkView.setVisibility(explicitlySelected ? VISIBLE : INVISIBLE);
holder.itemView.setOnClickListener(
v -> {
if (mappedTrackInfo != null && trackSelector != null) {
ParametersBuilder parametersBuilder = trackSelector.getParameters().buildUpon();
for (int i = 0; i < rendererIndices.size(); i++) {
int rendererIndex = rendererIndices.get(i);
if (rendererIndex == track.rendererIndex) {
parametersBuilder =
parametersBuilder
.setSelectionOverride(
rendererIndex,
checkNotNull(mappedTrackInfo).getTrackGroups(rendererIndex),
new SelectionOverride(track.groupIndex, track.trackIndex))
.setRendererDisabled(rendererIndex, false);
} else {
parametersBuilder =
parametersBuilder
.clearSelectionOverrides(rendererIndex)
.setRendererDisabled(rendererIndex, true);
}
}
checkNotNull(trackSelector).setParameters(parametersBuilder);
onTrackSelection(track.trackName);
settingsWindow.dismiss();
if (player == null) {
return;
}
TrackSelectionParameters trackSelectionParameters =
player.getTrackSelectionParameters();
Map<TrackGroup, TrackSelectionOverride> overrides =
forceTrackSelection(
trackSelectionParameters.trackSelectionOverrides,
track.tracksInfo,
track.trackGroupIndex,
new TrackSelectionOverride(ImmutableSet.of(track.trackIndex)));
checkNotNull(player)
.setTrackSelectionParameters(
trackSelectionParameters
.buildUpon()
.setTrackSelectionOverrides(overrides)
.build());
onTrackSelection(track.trackName);
settingsWindow.dismiss();
});
}
}
@ -2236,9 +2208,8 @@ public class StyledPlayerControlView extends FrameLayout {
return tracks.isEmpty() ? 0 : tracks.size() + 1;
}
public void clear() {
protected void clear() {
tracks = Collections.emptyList();
mappedTrackInfo = null;
}
}

View File

@ -48,7 +48,6 @@ import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ControlDispatcher;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ForwardingPlayer;
import com.google.android.exoplayer2.MediaMetadata;
import com.google.android.exoplayer2.PlaybackException;
@ -58,12 +57,9 @@ import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.TracksInfo;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ErrorMessageProvider;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.RepeatModeUtil;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoSize;
@ -1296,7 +1292,7 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider {
private void updateForCurrentTrackSelections(boolean isNewPlayer) {
@Nullable Player player = this.player;
if (player == null || player.getCurrentTrackGroups().isEmpty()) {
if (player == null || player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) {
if (!keepContentOnPlayerReset) {
hideArtwork();
closeShutter();
@ -1309,20 +1305,11 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider {
closeShutter();
}
TrackSelectionArray trackSelections = player.getCurrentTrackSelections();
for (int i = 0; i < trackSelections.length; i++) {
@Nullable TrackSelection trackSelection = trackSelections.get(i);
if (trackSelection != null) {
for (int j = 0; j < trackSelection.length(); j++) {
Format format = trackSelection.getFormat(j);
if (MimeTypes.getTrackType(format.sampleMimeType) == C.TRACK_TYPE_VIDEO) {
// Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened
// in onRenderedFirstFrame().
hideArtwork();
return;
}
}
}
if (player.getCurrentTracksInfo().isTypeSelected(C.TRACK_TYPE_VIDEO)) {
// Video enabled, so artwork must be hidden. If the shutter is closed, it will be opened
// in onRenderedFirstFrame().
hideArtwork();
return;
}
// Video disabled so the shutter must be closed.
@ -1558,7 +1545,7 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider {
Timeline timeline = player.getCurrentTimeline();
if (timeline.isEmpty()) {
lastPeriodUidWithTracks = null;
} else if (!player.getCurrentTrackGroups().isEmpty()) {
} else if (!player.getCurrentTracksInfo().getTrackGroupInfos().isEmpty()) {
lastPeriodUidWithTracks =
timeline.getPeriod(player.getCurrentPeriodIndex(), period, /* setIds= */ true).uid;
} else if (lastPeriodUidWithTracks != null) {