From 736ea9a148b86547feaba95ed8ada41d67ba2393 Mon Sep 17 00:00:00 2001 From: tonihei Date: Tue, 23 Nov 2021 10:25:22 +0000 Subject: [PATCH] Remove ExoPlayerImpl inheritance from BasePlayer. This inheritance is really confusing because ExoPlayerImpl is not a full Player interface implementation. It also claims to be an ExoPlayer implementation in the Javadoc which isn't true in its current state. Removing the inheritance also allows to clean up some unused methods. PiperOrigin-RevId: 411756963 --- .../java/androidx/media3/cast/CastPlayer.java | 2 +- .../androidx/media3/common/BasePlayer.java | 31 -- .../androidx/media3/common/util/Util.java | 48 +++ .../media3/exoplayer/ExoPlayerImpl.java | 282 +++++------------- .../media3/exoplayer/SimpleExoPlayer.java | 1 - 5 files changed, 128 insertions(+), 236 deletions(-) diff --git a/libraries/cast/src/main/java/androidx/media3/cast/CastPlayer.java b/libraries/cast/src/main/java/androidx/media3/cast/CastPlayer.java index ead783827e..b3f981986e 100644 --- a/libraries/cast/src/main/java/androidx/media3/cast/CastPlayer.java +++ b/libraries/cast/src/main/java/androidx/media3/cast/CastPlayer.java @@ -1094,7 +1094,7 @@ public final class CastPlayer extends BasePlayer { private void updateAvailableCommandsAndNotifyIfChanged() { Commands previousAvailableCommands = availableCommands; - availableCommands = getAvailableCommands(PERMANENT_AVAILABLE_COMMANDS); + availableCommands = Util.getAvailableCommands(/* player= */ this, PERMANENT_AVAILABLE_COMMANDS); if (!availableCommands.equals(previousAvailableCommands)) { listeners.queueEvent( Player.EVENT_AVAILABLE_COMMANDS_CHANGED, diff --git a/libraries/common/src/main/java/androidx/media3/common/BasePlayer.java b/libraries/common/src/main/java/androidx/media3/common/BasePlayer.java index 44926b25fc..f79df0ff90 100644 --- a/libraries/common/src/main/java/androidx/media3/common/BasePlayer.java +++ b/libraries/common/src/main/java/androidx/media3/common/BasePlayer.java @@ -384,37 +384,6 @@ public abstract class BasePlayer implements Player { : timeline.getWindow(getCurrentMediaItemIndex(), window).getDurationMs(); } - /** - * Returns the {@link Commands} available in the player. - * - * @param permanentAvailableCommands The commands permanently available in the player. - * @return The available {@link Commands}. - */ - protected Commands getAvailableCommands(Commands permanentAvailableCommands) { - return new Commands.Builder() - .addAll(permanentAvailableCommands) - .addIf(COMMAND_SEEK_TO_DEFAULT_POSITION, !isPlayingAd()) - .addIf(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, isCurrentMediaItemSeekable() && !isPlayingAd()) - .addIf(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, hasPreviousMediaItem() && !isPlayingAd()) - .addIf( - COMMAND_SEEK_TO_PREVIOUS, - !getCurrentTimeline().isEmpty() - && (hasPreviousMediaItem() - || !isCurrentMediaItemLive() - || isCurrentMediaItemSeekable()) - && !isPlayingAd()) - .addIf(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, hasNextMediaItem() && !isPlayingAd()) - .addIf( - COMMAND_SEEK_TO_NEXT, - !getCurrentTimeline().isEmpty() - && (hasNextMediaItem() || (isCurrentMediaItemLive() && isCurrentMediaItemDynamic())) - && !isPlayingAd()) - .addIf(COMMAND_SEEK_TO_MEDIA_ITEM, !isPlayingAd()) - .addIf(COMMAND_SEEK_BACK, isCurrentMediaItemSeekable() && !isPlayingAd()) - .addIf(COMMAND_SEEK_FORWARD, isCurrentMediaItemSeekable() && !isPlayingAd()) - .build(); - } - @RepeatMode private int getRepeatModeForNavigation() { @RepeatMode int repeatMode = getRepeatMode(); diff --git a/libraries/common/src/main/java/androidx/media3/common/util/Util.java b/libraries/common/src/main/java/androidx/media3/common/util/Util.java index 548e759424..9246d37c6d 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/Util.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/Util.java @@ -16,6 +16,15 @@ package androidx.media3.common.util; import static android.content.Context.UI_MODE_SERVICE; +import static androidx.media3.common.Player.COMMAND_SEEK_BACK; +import static androidx.media3.common.Player.COMMAND_SEEK_FORWARD; +import static androidx.media3.common.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM; +import static androidx.media3.common.Player.COMMAND_SEEK_TO_DEFAULT_POSITION; +import static androidx.media3.common.Player.COMMAND_SEEK_TO_MEDIA_ITEM; +import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT; +import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM; +import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS; +import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM; import static androidx.media3.common.util.Assertions.checkNotNull; import static java.lang.Math.abs; import static java.lang.Math.max; @@ -64,6 +73,8 @@ import androidx.media3.common.MediaLibraryInfo; import androidx.media3.common.MimeTypes; import androidx.media3.common.ParserException; import androidx.media3.common.PlaybackException; +import androidx.media3.common.Player; +import androidx.media3.common.Player.Commands; import com.google.common.base.Ascii; import com.google.common.base.Charsets; import java.io.ByteArrayOutputStream; @@ -2479,6 +2490,43 @@ public final class Util { } } + /** + * Returns the {@link Commands} available in the {@link Player}. + * + * @param player The {@link Player}. + * @param permanentAvailableCommands The commands permanently available in the player. + * @return The available {@link Commands}. + */ + public static Commands getAvailableCommands(Player player, Commands permanentAvailableCommands) { + boolean isPlayingAd = player.isPlayingAd(); + boolean isCurrentMediaItemSeekable = player.isCurrentMediaItemSeekable(); + boolean hasPreviousMediaItem = player.hasPreviousMediaItem(); + boolean hasNextMediaItem = player.hasNextMediaItem(); + boolean isCurrentMediaItemLive = player.isCurrentMediaItemLive(); + boolean isCurrentMediaItemDynamic = player.isCurrentMediaItemDynamic(); + boolean isTimelineEmpty = player.getCurrentTimeline().isEmpty(); + return new Commands.Builder() + .addAll(permanentAvailableCommands) + .addIf(COMMAND_SEEK_TO_DEFAULT_POSITION, !isPlayingAd) + .addIf(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, isCurrentMediaItemSeekable && !isPlayingAd) + .addIf(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, hasPreviousMediaItem && !isPlayingAd) + .addIf( + COMMAND_SEEK_TO_PREVIOUS, + !isTimelineEmpty + && (hasPreviousMediaItem || !isCurrentMediaItemLive || isCurrentMediaItemSeekable) + && !isPlayingAd) + .addIf(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, hasNextMediaItem && !isPlayingAd) + .addIf( + COMMAND_SEEK_TO_NEXT, + !isTimelineEmpty + && (hasNextMediaItem || (isCurrentMediaItemLive && isCurrentMediaItemDynamic)) + && !isPlayingAd) + .addIf(COMMAND_SEEK_TO_MEDIA_ITEM, !isPlayingAd) + .addIf(COMMAND_SEEK_BACK, isCurrentMediaItemSeekable && !isPlayingAd) + .addIf(COMMAND_SEEK_FORWARD, isCurrentMediaItemSeekable && !isPlayingAd) + .build(); + } + @Nullable private static String getSystemProperty(String name) { try { diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java index fd693e8274..c2c61cf953 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java @@ -15,6 +15,39 @@ */ package androidx.media3.exoplayer; +import static androidx.media3.common.Player.COMMAND_CHANGE_MEDIA_ITEMS; +import static androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM; +import static androidx.media3.common.Player.COMMAND_GET_MEDIA_ITEMS_METADATA; +import static androidx.media3.common.Player.COMMAND_GET_TIMELINE; +import static androidx.media3.common.Player.COMMAND_GET_TRACK_INFOS; +import static androidx.media3.common.Player.COMMAND_PLAY_PAUSE; +import static androidx.media3.common.Player.COMMAND_PREPARE; +import static androidx.media3.common.Player.COMMAND_SEEK_TO_DEFAULT_POSITION; +import static androidx.media3.common.Player.COMMAND_SEEK_TO_MEDIA_ITEM; +import static androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEMS_METADATA; +import static androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE; +import static androidx.media3.common.Player.COMMAND_SET_SHUFFLE_MODE; +import static androidx.media3.common.Player.COMMAND_SET_SPEED_AND_PITCH; +import static androidx.media3.common.Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS; +import static androidx.media3.common.Player.COMMAND_STOP; +import static androidx.media3.common.Player.DISCONTINUITY_REASON_AUTO_TRANSITION; +import static androidx.media3.common.Player.DISCONTINUITY_REASON_INTERNAL; +import static androidx.media3.common.Player.DISCONTINUITY_REASON_REMOVE; +import static androidx.media3.common.Player.DISCONTINUITY_REASON_SEEK; +import static androidx.media3.common.Player.EVENT_MEDIA_METADATA_CHANGED; +import static androidx.media3.common.Player.EVENT_PLAYLIST_METADATA_CHANGED; +import static androidx.media3.common.Player.EVENT_TRACK_SELECTION_PARAMETERS_CHANGED; +import static androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_AUTO; +import static androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED; +import static androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT; +import static androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_SEEK; +import static androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_NONE; +import static androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST; +import static androidx.media3.common.Player.STATE_BUFFERING; +import static androidx.media3.common.Player.STATE_ENDED; +import static androidx.media3.common.Player.STATE_IDLE; +import static androidx.media3.common.Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED; +import static androidx.media3.common.Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE; import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Util.castNonNull; @@ -26,17 +59,10 @@ import android.media.metrics.LogSessionId; import android.os.Handler; import android.os.Looper; import android.util.Pair; -import android.view.Surface; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.TextureView; import androidx.annotation.DoNotInline; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; -import androidx.media3.common.AudioAttributes; -import androidx.media3.common.BasePlayer; import androidx.media3.common.C; -import androidx.media3.common.DeviceInfo; import androidx.media3.common.Format; import androidx.media3.common.IllegalSeekPositionException; import androidx.media3.common.MediaItem; @@ -46,14 +72,23 @@ import androidx.media3.common.Metadata; import androidx.media3.common.PlaybackException; import androidx.media3.common.PlaybackParameters; import androidx.media3.common.Player; +import androidx.media3.common.Player.Commands; +import androidx.media3.common.Player.DiscontinuityReason; +import androidx.media3.common.Player.EventListener; +import androidx.media3.common.Player.Events; +import androidx.media3.common.Player.Listener; +import androidx.media3.common.Player.PlayWhenReadyChangeReason; +import androidx.media3.common.Player.PlaybackSuppressionReason; +import androidx.media3.common.Player.PositionInfo; +import androidx.media3.common.Player.RepeatMode; +import androidx.media3.common.Player.State; +import androidx.media3.common.Player.TimelineChangeReason; import androidx.media3.common.Timeline; import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroupArray; import androidx.media3.common.TrackSelectionArray; import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TracksInfo; -import androidx.media3.common.VideoSize; -import androidx.media3.common.text.Cue; import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Clock; import androidx.media3.common.util.HandlerWrapper; @@ -78,8 +113,8 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArraySet; -/** An {@link ExoPlayer} implementation. */ -/* package */ final class ExoPlayerImpl extends BasePlayer { +/** A helper class for the {@link SimpleExoPlayer} implementation of {@link ExoPlayer}. */ +/* package */ final class ExoPlayerImpl { static { MediaLibraryInfo.registerModule("media3.exoplayer"); @@ -97,6 +132,7 @@ import java.util.concurrent.CopyOnWriteArraySet; /* package */ final TrackSelectorResult emptyTrackSelectorResult; /* package */ final Commands permanentAvailableCommands; + private final Player wrappingPlayer; private final Renderer[] renderers; private final TrackSelector trackSelector; private final HandlerWrapper playbackInfoUpdateHandler; @@ -105,10 +141,11 @@ import java.util.concurrent.CopyOnWriteArraySet; private final ListenerSet listeners; private final CopyOnWriteArraySet audioOffloadListeners; private final Timeline.Period period; + private final Timeline.Window window; private final List mediaSourceHolderSnapshots; private final boolean useLazyPreparation; private final MediaSourceFactory mediaSourceFactory; - @Nullable private final AnalyticsCollector analyticsCollector; + private final AnalyticsCollector analyticsCollector; private final Looper applicationLooper; private final BandwidthMeter bandwidthMeter; private final long seekBackIncrementMs; @@ -154,16 +191,15 @@ import java.util.concurrent.CopyOnWriteArraySet; * loads and other initial preparation steps happen immediately. If true, these initial * preparations are triggered only when the player starts buffering the media. * @param seekParameters The {@link SeekParameters}. - * @param seekBackIncrementMs The {@link #seekBack()} increment in milliseconds. - * @param seekForwardIncrementMs The {@link #seekForward()} increment in milliseconds. + * @param seekBackIncrementMs The seek back increment in milliseconds. + * @param seekForwardIncrementMs The seek forward increment in milliseconds. * @param livePlaybackSpeedControl The {@link LivePlaybackSpeedControl}. * @param releaseTimeoutMs The timeout for calls to {@link #release()} in milliseconds. * @param pauseAtEndOfMediaItems Whether to pause playback at the end of each media item. * @param clock The {@link Clock}. * @param applicationLooper The {@link Looper} that must be used for all calls to the player and * which is used to call listeners on. - * @param wrappingPlayer The {@link Player} wrapping this one if applicable. This player instance - * should be used for all externally visible callbacks. + * @param wrappingPlayer The {@link Player} using this class. * @param additionalPermanentAvailableCommands The {@link Commands} that are permanently available * in the wrapping player but that are not in this player. */ @@ -174,7 +210,7 @@ import java.util.concurrent.CopyOnWriteArraySet; MediaSourceFactory mediaSourceFactory, LoadControl loadControl, BandwidthMeter bandwidthMeter, - @Nullable AnalyticsCollector analyticsCollector, + AnalyticsCollector analyticsCollector, boolean useLazyPreparation, SeekParameters seekParameters, long seekBackIncrementMs, @@ -184,7 +220,7 @@ import java.util.concurrent.CopyOnWriteArraySet; boolean pauseAtEndOfMediaItems, Clock clock, Looper applicationLooper, - @Nullable Player wrappingPlayer, + Player wrappingPlayer, Commands additionalPermanentAvailableCommands) { Log.i( TAG, @@ -208,13 +244,13 @@ import java.util.concurrent.CopyOnWriteArraySet; this.pauseAtEndOfMediaItems = pauseAtEndOfMediaItems; this.applicationLooper = applicationLooper; this.clock = clock; + this.wrappingPlayer = wrappingPlayer; repeatMode = Player.REPEAT_MODE_OFF; - Player playerForListeners = wrappingPlayer != null ? wrappingPlayer : this; listeners = new ListenerSet<>( applicationLooper, clock, - (listener, flags) -> listener.onEvents(playerForListeners, new Events(flags))); + (listener, flags) -> listener.onEvents(wrappingPlayer, new Events(flags))); audioOffloadListeners = new CopyOnWriteArraySet<>(); mediaSourceHolderSnapshots = new ArrayList<>(); shuffleOrder = new ShuffleOrder.DefaultShuffleOrder(/* length= */ 0); @@ -225,6 +261,7 @@ import java.util.concurrent.CopyOnWriteArraySet; TracksInfo.EMPTY, /* info= */ null); period = new Timeline.Period(); + window = new Timeline.Window(); permanentAvailableCommands = new Commands.Builder() .addAll( @@ -258,11 +295,9 @@ import java.util.concurrent.CopyOnWriteArraySet; playbackInfoUpdate -> playbackInfoUpdateHandler.post(() -> handlePlaybackInfo(playbackInfoUpdate)); playbackInfo = PlaybackInfo.createDummy(emptyTrackSelectorResult); - if (analyticsCollector != null) { - analyticsCollector.setPlayer(playerForListeners, applicationLooper); - addListener(analyticsCollector); - bandwidthMeter.addEventListener(new Handler(applicationLooper), analyticsCollector); - } + analyticsCollector.setPlayer(wrappingPlayer, applicationLooper); + addListener(analyticsCollector); + bandwidthMeter.addEventListener(new Handler(applicationLooper), analyticsCollector); PlayerId playerId = Util.SDK_INT < 31 ? new PlayerId() : Api31.createPlayerId(); internalPlayer = new ExoPlayerImplInternal( @@ -310,7 +345,6 @@ import java.util.concurrent.CopyOnWriteArraySet; return internalPlayer.getPlaybackLooper(); } - @Override public Looper getApplicationLooper() { return applicationLooper; } @@ -319,16 +353,10 @@ import java.util.concurrent.CopyOnWriteArraySet; return clock; } - @Override public void addListener(Listener listener) { addEventListener(listener); } - @Override - public void removeListener(Listener listener) { - removeEventListener(listener); - } - @SuppressWarnings("deprecation") // Register deprecated EventListener. public void addEventListener(Player.EventListener eventListener) { listeners.add(eventListener); @@ -347,24 +375,20 @@ import java.util.concurrent.CopyOnWriteArraySet; audioOffloadListeners.remove(listener); } - @Override public Commands getAvailableCommands() { return availableCommands; } - @Override @State public int getPlaybackState() { return playbackInfo.playbackState; } - @Override @PlaybackSuppressionReason public int getPlaybackSuppressionReason() { return playbackInfo.playbackSuppressionReason; } - @Override @Nullable public ExoPlaybackException getPlayerError() { return playbackInfo.playbackError; @@ -376,7 +400,6 @@ import java.util.concurrent.CopyOnWriteArraySet; prepare(); } - @Override public void prepare() { if (playbackInfo.playbackState != Player.STATE_IDLE) { return; @@ -384,7 +407,7 @@ import java.util.concurrent.CopyOnWriteArraySet; PlaybackInfo playbackInfo = this.playbackInfo.copyWithPlaybackError(null); playbackInfo = playbackInfo.copyWithPlaybackState( - playbackInfo.timeline.isEmpty() ? Player.STATE_ENDED : Player.STATE_BUFFERING); + playbackInfo.timeline.isEmpty() ? STATE_ENDED : STATE_BUFFERING); // Trigger internal prepare first before updating the playback info and notifying external // listeners to ensure that new operations issued in the listener notifications reach the // player after this prepare. The internal player can't change the playback info immediately @@ -421,12 +444,10 @@ import java.util.concurrent.CopyOnWriteArraySet; prepare(); } - @Override public void setMediaItems(List mediaItems, boolean resetPosition) { setMediaSources(createMediaSources(mediaItems), resetPosition); } - @Override public void setMediaItems(List mediaItems, int startIndex, long startPositionMs) { setMediaSources(createMediaSources(mediaItems), startIndex, startPositionMs); } @@ -462,7 +483,6 @@ import java.util.concurrent.CopyOnWriteArraySet; mediaSources, startWindowIndex, startPositionMs, /* resetToDefaultPosition= */ false); } - @Override public void addMediaItems(int index, List mediaItems) { index = min(index, mediaSourceHolderSnapshots.size()); addMediaSources(index, createMediaSources(mediaItems)); @@ -503,7 +523,6 @@ import java.util.concurrent.CopyOnWriteArraySet; /* ignored */ C.INDEX_UNSET); } - @Override public void removeMediaItems(int fromIndex, int toIndex) { toIndex = min(toIndex, mediaSourceHolderSnapshots.size()); PlaybackInfo newPlaybackInfo = removeMediaItemsInternal(fromIndex, toIndex); @@ -515,12 +534,11 @@ import java.util.concurrent.CopyOnWriteArraySet; /* ignored */ PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST, /* seekProcessed= */ false, positionDiscontinuity, - Player.DISCONTINUITY_REASON_REMOVE, + DISCONTINUITY_REASON_REMOVE, /* discontinuityWindowStartPositionUs= */ getCurrentPositionUsInternal(newPlaybackInfo), /* ignored */ C.INDEX_UNSET); } - @Override public void moveMediaItems(int fromIndex, int toIndex, int newFromIndex) { Assertions.checkArgument( fromIndex >= 0 @@ -571,14 +589,6 @@ import java.util.concurrent.CopyOnWriteArraySet; /* ignored */ C.INDEX_UNSET); } - @Override - public void setPlayWhenReady(boolean playWhenReady) { - setPlayWhenReady( - playWhenReady, - PLAYBACK_SUPPRESSION_REASON_NONE, - PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST); - } - public void setPauseAtEndOfMediaItems(boolean pauseAtEndOfMediaItems) { if (this.pauseAtEndOfMediaItems == pauseAtEndOfMediaItems) { return; @@ -614,12 +624,10 @@ import java.util.concurrent.CopyOnWriteArraySet; /* ignored */ C.INDEX_UNSET); } - @Override public boolean getPlayWhenReady() { return playbackInfo.playWhenReady; } - @Override public void setRepeatMode(@RepeatMode int repeatMode) { if (this.repeatMode != repeatMode) { this.repeatMode = repeatMode; @@ -631,12 +639,11 @@ import java.util.concurrent.CopyOnWriteArraySet; } } - @Override - public @RepeatMode int getRepeatMode() { + @RepeatMode + public int getRepeatMode() { return repeatMode; } - @Override public void setShuffleModeEnabled(boolean shuffleModeEnabled) { if (this.shuffleModeEnabled != shuffleModeEnabled) { this.shuffleModeEnabled = shuffleModeEnabled; @@ -649,17 +656,14 @@ import java.util.concurrent.CopyOnWriteArraySet; } } - @Override public boolean getShuffleModeEnabled() { return shuffleModeEnabled; } - @Override public boolean isLoading() { return playbackInfo.isLoading; } - @Override public void seekTo(int mediaItemIndex, long positionMs) { Timeline timeline = playbackInfo.timeline; if (mediaItemIndex < 0 @@ -680,7 +684,7 @@ import java.util.concurrent.CopyOnWriteArraySet; } @Player.State int newPlaybackState = - getPlaybackState() == Player.STATE_IDLE ? Player.STATE_IDLE : Player.STATE_BUFFERING; + getPlaybackState() == Player.STATE_IDLE ? Player.STATE_IDLE : STATE_BUFFERING; int oldMaskingMediaItemIndex = getCurrentMediaItemIndex(); PlaybackInfo newPlaybackInfo = playbackInfo.copyWithPlaybackState(newPlaybackState); newPlaybackInfo = @@ -700,22 +704,18 @@ import java.util.concurrent.CopyOnWriteArraySet; oldMaskingMediaItemIndex); } - @Override public long getSeekBackIncrement() { return seekBackIncrementMs; } - @Override public long getSeekForwardIncrement() { return seekForwardIncrementMs; } - @Override public long getMaxSeekToPreviousPosition() { return C.DEFAULT_MAX_SEEK_TO_PREVIOUS_POSITION_MS; } - @Override public void setPlaybackParameters(PlaybackParameters playbackParameters) { if (playbackParameters == null) { playbackParameters = PlaybackParameters.DEFAULT; @@ -737,7 +737,6 @@ import java.util.concurrent.CopyOnWriteArraySet; /* ignored */ C.INDEX_UNSET); } - @Override public PlaybackParameters getPlaybackParameters() { return playbackInfo.playbackParameters; } @@ -770,13 +769,6 @@ import java.util.concurrent.CopyOnWriteArraySet; } } - @Override - public void stop() { - stop(/* reset= */ false); - } - - @Deprecated - @Override public void stop(boolean reset) { stop(reset, /* error= */ null); } @@ -819,7 +811,6 @@ import java.util.concurrent.CopyOnWriteArraySet; /* ignored */ C.INDEX_UNSET); } - @Override public void release() { Log.i( TAG, @@ -844,9 +835,7 @@ import java.util.concurrent.CopyOnWriteArraySet; } listeners.release(); playbackInfoUpdateHandler.removeCallbacksAndMessages(null); - if (analyticsCollector != null) { - bandwidthMeter.removeEventListener(analyticsCollector); - } + bandwidthMeter.removeEventListener(analyticsCollector); playbackInfo = playbackInfo.copyWithPlaybackState(Player.STATE_IDLE); playbackInfo = playbackInfo.copyWithLoadingMediaPeriodId(playbackInfo.periodId); playbackInfo.bufferedPositionUs = playbackInfo.positionUs; @@ -863,7 +852,6 @@ import java.util.concurrent.CopyOnWriteArraySet; internalPlayer.getPlaybackLooper()); } - @Override public int getCurrentPeriodIndex() { if (playbackInfo.timeline.isEmpty()) { return maskingPeriodIndex; @@ -872,13 +860,11 @@ import java.util.concurrent.CopyOnWriteArraySet; } } - @Override public int getCurrentMediaItemIndex() { int currentWindowIndex = getCurrentWindowIndexInternal(); return currentWindowIndex == C.INDEX_UNSET ? 0 : currentWindowIndex; } - @Override public long getDuration() { if (isPlayingAd()) { MediaPeriodId periodId = playbackInfo.periodId; @@ -889,12 +875,17 @@ import java.util.concurrent.CopyOnWriteArraySet; return getContentDuration(); } - @Override + private long getContentDuration() { + Timeline timeline = getCurrentTimeline(); + return timeline.isEmpty() + ? C.TIME_UNSET + : timeline.getWindow(getCurrentMediaItemIndex(), window).getDurationMs(); + } + public long getCurrentPosition() { return Util.usToMs(getCurrentPositionUsInternal(playbackInfo)); } - @Override public long getBufferedPosition() { if (isPlayingAd()) { return playbackInfo.loadingMediaPeriodId.equals(playbackInfo.periodId) @@ -904,27 +895,22 @@ import java.util.concurrent.CopyOnWriteArraySet; return getContentBufferedPosition(); } - @Override public long getTotalBufferedDuration() { return Util.usToMs(playbackInfo.totalBufferedDurationUs); } - @Override public boolean isPlayingAd() { return playbackInfo.periodId.isAd(); } - @Override public int getCurrentAdGroupIndex() { return isPlayingAd() ? playbackInfo.periodId.adGroupIndex : C.INDEX_UNSET; } - @Override public int getCurrentAdIndexInAdGroup() { return isPlayingAd() ? playbackInfo.periodId.adIndexInAdGroup : C.INDEX_UNSET; } - @Override public long getContentPosition() { if (isPlayingAd()) { playbackInfo.timeline.getPeriodByUid(playbackInfo.periodId.periodUid, period); @@ -939,7 +925,6 @@ import java.util.concurrent.CopyOnWriteArraySet; } } - @Override public long getContentBufferedPosition() { if (playbackInfo.timeline.isEmpty()) { return maskingWindowPositionMs; @@ -971,32 +956,26 @@ import java.util.concurrent.CopyOnWriteArraySet; return renderers[index].getTrackType(); } - @Nullable public TrackSelector getTrackSelector() { return trackSelector; } - @Override public TrackGroupArray getCurrentTrackGroups() { return playbackInfo.trackGroups; } - @Override public TrackSelectionArray getCurrentTrackSelections() { return new TrackSelectionArray(playbackInfo.trackSelectorResult.selections); } - @Override public TracksInfo getCurrentTracksInfo() { return playbackInfo.trackSelectorResult.tracksInfo; } - @Override public TrackSelectionParameters getTrackSelectionParameters() { return trackSelector.getParameters(); } - @Override public void setTrackSelectionParameters(TrackSelectionParameters parameters) { if (!trackSelector.isSetParametersSupported() || parameters.equals(trackSelector.getParameters())) { @@ -1008,7 +987,6 @@ import java.util.concurrent.CopyOnWriteArraySet; listener -> listener.onTrackSelectionParametersChanged(parameters)); } - @Override public MediaMetadata getMediaMetadata() { return mediaMetadata; } @@ -1027,12 +1005,10 @@ import java.util.concurrent.CopyOnWriteArraySet; EVENT_MEDIA_METADATA_CHANGED, listener -> listener.onMediaMetadataChanged(mediaMetadata)); } - @Override public MediaMetadata getPlaylistMetadata() { return playlistMetadata; } - @Override public void setPlaylistMetadata(MediaMetadata playlistMetadata) { checkNotNull(playlistMetadata); if (playlistMetadata.equals(this.playlistMetadata)) { @@ -1044,109 +1020,10 @@ import java.util.concurrent.CopyOnWriteArraySet; listener -> listener.onPlaylistMetadataChanged(this.playlistMetadata)); } - @Override public Timeline getCurrentTimeline() { return playbackInfo.timeline; } - /** This method is not supported and returns {@link AudioAttributes#DEFAULT}. */ - @Override - public AudioAttributes getAudioAttributes() { - return AudioAttributes.DEFAULT; - } - - /** This method is not supported and does nothing. */ - @Override - public void setVolume(float volume) {} - - /** This method is not supported and returns 1. */ - @Override - public float getVolume() { - return 1; - } - - /** This method is not supported and does nothing. */ - @Override - public void clearVideoSurface() {} - - /** This method is not supported and does nothing. */ - @Override - public void clearVideoSurface(@Nullable Surface surface) {} - - /** This method is not supported and does nothing. */ - @Override - public void setVideoSurface(@Nullable Surface surface) {} - - /** This method is not supported and does nothing. */ - @Override - public void setVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) {} - - /** This method is not supported and does nothing. */ - @Override - public void clearVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) {} - - /** This method is not supported and does nothing. */ - @Override - public void setVideoSurfaceView(@Nullable SurfaceView surfaceView) {} - - /** This method is not supported and does nothing. */ - @Override - public void clearVideoSurfaceView(@Nullable SurfaceView surfaceView) {} - - /** This method is not supported and does nothing. */ - @Override - public void setVideoTextureView(@Nullable TextureView textureView) {} - - /** This method is not supported and does nothing. */ - @Override - public void clearVideoTextureView(@Nullable TextureView textureView) {} - - /** This method is not supported and returns {@link VideoSize#UNKNOWN}. */ - @Override - public VideoSize getVideoSize() { - return VideoSize.UNKNOWN; - } - - /** This method is not supported and returns an empty list. */ - @Override - public ImmutableList getCurrentCues() { - return ImmutableList.of(); - } - - /** This method is not supported and always returns {@link DeviceInfo#UNKNOWN}. */ - @Override - public DeviceInfo getDeviceInfo() { - return DeviceInfo.UNKNOWN; - } - - /** This method is not supported and always returns {@code 0}. */ - @Override - public int getDeviceVolume() { - return 0; - } - - /** This method is not supported and always returns {@link false}. */ - @Override - public boolean isDeviceMuted() { - return false; - } - - /** This method is not supported and does nothing. */ - @Override - public void setDeviceVolume(int volume) {} - - /** This method is not supported and does nothing. */ - @Override - public void increaseDeviceVolume() {} - - /** This method is not supported and does nothing. */ - @Override - public void decreaseDeviceVolume() {} - - /** This method is not supported and does nothing. */ - @Override - public void setDeviceMuted(boolean muted) {} - private int getCurrentWindowIndexInternal() { if (playbackInfo.timeline.isEmpty()) { return maskingWindowIndex; @@ -1329,7 +1206,7 @@ import java.util.concurrent.CopyOnWriteArraySet; if (metadataChanged) { final MediaMetadata finalMediaMetadata = mediaMetadata; listeners.queueEvent( - Player.EVENT_MEDIA_METADATA_CHANGED, + EVENT_MEDIA_METADATA_CHANGED, listener -> listener.onMediaMetadataChanged(finalMediaMetadata)); } if (previousPlaybackInfo.isLoading != newPlaybackInfo.isLoading) { @@ -1537,7 +1414,7 @@ import java.util.concurrent.CopyOnWriteArraySet; private void updateAvailableCommands() { Commands previousAvailableCommands = availableCommands; - availableCommands = getAvailableCommands(permanentAvailableCommands); + availableCommands = Util.getAvailableCommands(wrappingPlayer, permanentAvailableCommands); if (!availableCommands.equals(previousAvailableCommands)) { listeners.queueEvent( Player.EVENT_AVAILABLE_COMMANDS_CHANGED, @@ -1599,7 +1476,7 @@ import java.util.concurrent.CopyOnWriteArraySet; /* ignored */ PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST, /* seekProcessed= */ false, /* positionDiscontinuity= */ positionDiscontinuity, - Player.DISCONTINUITY_REASON_REMOVE, + DISCONTINUITY_REASON_REMOVE, /* discontinuityWindowStartPositionUs= */ getCurrentPositionUsInternal(newPlaybackInfo), /* ignored */ C.INDEX_UNSET); } @@ -1838,12 +1715,11 @@ import java.util.concurrent.CopyOnWriteArraySet; * #onMetadata(Metadata)}) sources. */ private MediaMetadata buildUpdatedMediaMetadata() { - @Nullable MediaItem mediaItem = getCurrentMediaItem(); - - if (mediaItem == null) { + Timeline timeline = getCurrentTimeline(); + if (timeline.isEmpty()) { return staticAndDynamicMediaMetadata; } - + MediaItem mediaItem = timeline.getWindow(getCurrentMediaItemIndex(), window).mediaItem; // MediaItem metadata is prioritized over metadata within the media. return staticAndDynamicMediaMetadata.buildUpon().populate(mediaItem.mediaMetadata).build(); } diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/SimpleExoPlayer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/SimpleExoPlayer.java index ed8ee0d4a1..ff97399d12 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/SimpleExoPlayer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/SimpleExoPlayer.java @@ -1362,7 +1362,6 @@ public class SimpleExoPlayer extends BasePlayer } @Override - @Nullable public TrackSelector getTrackSelector() { verifyApplicationThread(); return player.getTrackSelector();