diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java index 57da40fc68..e807f3f169 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java @@ -70,13 +70,12 @@ import java.util.concurrent.TimeoutException; private final List mediaSourceHolders; private final boolean useLazyPreparation; + private boolean playWhenReady; + @PlaybackSuppressionReason private int playbackSuppressionReason; @RepeatMode private int repeatMode; private boolean shuffleModeEnabled; private int pendingOperationAcks; private boolean hasPendingSeek; - private boolean hasPendingDiscontinuity; - @DiscontinuityReason private int pendingDiscontinuityReason; - @PlayWhenReadyChangeReason private int pendingPlayWhenReadyChangeReason; private boolean foregroundMode; private int pendingSetPlaybackParametersAcks; private PlaybackParameters playbackParameters; @@ -122,7 +121,9 @@ import java.util.concurrent.TimeoutException; this.renderers = Assertions.checkNotNull(renderers); this.trackSelector = Assertions.checkNotNull(trackSelector); this.useLazyPreparation = useLazyPreparation; + playWhenReady = false; repeatMode = Player.REPEAT_MODE_OFF; + shuffleModeEnabled = false; listeners = new CopyOnWriteArrayList<>(); mediaSourceHolders = new ArrayList<>(); shuffleOrder = new ShuffleOrder.DefaultShuffleOrder(/* length= */ 0); @@ -134,6 +135,7 @@ import java.util.concurrent.TimeoutException; period = new Timeline.Period(); playbackParameters = PlaybackParameters.DEFAULT; seekParameters = SeekParameters.DEFAULT; + playbackSuppressionReason = PLAYBACK_SUPPRESSION_REASON_NONE; maskingWindowIndex = C.INDEX_UNSET; eventHandler = new Handler(looper) { @@ -154,6 +156,7 @@ import java.util.concurrent.TimeoutException; emptyTrackSelectorResult, loadControl, bandwidthMeter, + playWhenReady, repeatMode, shuffleModeEnabled, analyticsCollector, @@ -234,7 +237,7 @@ import java.util.concurrent.TimeoutException; @Override @PlaybackSuppressionReason public int getPlaybackSuppressionReason() { - return playbackInfo.playbackSuppressionReason; + return playbackSuppressionReason; } @Deprecated @@ -280,7 +283,6 @@ import java.util.concurrent.TimeoutException; /* positionDiscontinuity= */ false, /* ignored */ DISCONTINUITY_REASON_INTERNAL, /* ignored */ TIMELINE_CHANGE_REASON_SOURCE_UPDATE, - /* ignored */ PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST, /* seekProcessed= */ false); } @@ -441,36 +443,40 @@ import java.util.concurrent.TimeoutException; @PlaybackSuppressionReason int playbackSuppressionReason, @PlayWhenReadyChangeReason int playWhenReadyChangeReason) { boolean oldIsPlaying = isPlaying(); - boolean playWhenReadyChanged = playbackInfo.playWhenReady != playWhenReady; - boolean suppressionReasonChanged = - playbackInfo.playbackSuppressionReason != playbackSuppressionReason; - if (!playWhenReadyChanged && !suppressionReasonChanged) { - return; + boolean oldInternalPlayWhenReady = + this.playWhenReady && this.playbackSuppressionReason == PLAYBACK_SUPPRESSION_REASON_NONE; + boolean internalPlayWhenReady = + playWhenReady && playbackSuppressionReason == PLAYBACK_SUPPRESSION_REASON_NONE; + if (oldInternalPlayWhenReady != internalPlayWhenReady) { + internalPlayer.setPlayWhenReady(internalPlayWhenReady); } - pendingOperationAcks++; - playbackInfo = playbackInfo.copyWithPlayWhenReady(playWhenReady, playbackSuppressionReason); - internalPlayer.setPlayWhenReady(playWhenReady, playbackSuppressionReason); + boolean playWhenReadyChanged = this.playWhenReady != playWhenReady; + boolean suppressionReasonChanged = this.playbackSuppressionReason != playbackSuppressionReason; + this.playWhenReady = playWhenReady; + this.playbackSuppressionReason = playbackSuppressionReason; boolean isPlaying = isPlaying(); boolean isPlayingChanged = oldIsPlaying != isPlaying; - int playbackState = playbackInfo.playbackState; - notifyListeners( - listener -> { - if (playWhenReadyChanged) { - listener.onPlayerStateChanged(playWhenReady, playbackState); - listener.onPlayWhenReadyChanged(playWhenReady, playWhenReadyChangeReason); - } - if (suppressionReasonChanged) { - listener.onPlaybackSuppressionReasonChanged(playbackSuppressionReason); - } - if (isPlayingChanged) { - listener.onIsPlayingChanged(isPlaying); - } - }); + if (playWhenReadyChanged || suppressionReasonChanged || isPlayingChanged) { + int playbackState = playbackInfo.playbackState; + notifyListeners( + listener -> { + if (playWhenReadyChanged) { + listener.onPlayerStateChanged(playWhenReady, playbackState); + listener.onPlayWhenReadyChanged(playWhenReady, playWhenReadyChangeReason); + } + if (suppressionReasonChanged) { + listener.onPlaybackSuppressionReasonChanged(playbackSuppressionReason); + } + if (isPlayingChanged) { + listener.onIsPlayingChanged(isPlaying); + } + }); + } } @Override public boolean getPlayWhenReady() { - return playbackInfo.playWhenReady; + return playWhenReady; } @Override @@ -595,7 +601,6 @@ import java.util.concurrent.TimeoutException; /* positionDiscontinuity= */ false, /* ignored */ DISCONTINUITY_REASON_INTERNAL, TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED, - /* ignored */ PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST, /* seekProcessed= */ false); } @@ -758,9 +763,14 @@ import java.util.concurrent.TimeoutException; // Not private so it can be called from an inner class without going through a thunk method. /* package */ void handleEvent(Message msg) { + switch (msg.what) { case ExoPlayerImplInternal.MSG_PLAYBACK_INFO_CHANGED: - handlePlaybackInfo((ExoPlayerImplInternal.PlaybackInfoUpdate) msg.obj); + handlePlaybackInfo( + /* playbackInfo= */ (PlaybackInfo) msg.obj, + /* operationAcks= */ msg.arg1, + /* positionDiscontinuity= */ msg.arg2 != C.INDEX_UNSET, + /* positionDiscontinuityReason= */ msg.arg2); break; case ExoPlayerImplInternal.MSG_PLAYBACK_PARAMETERS_CHANGED: handlePlaybackParameters((PlaybackParameters) msg.obj, /* operationAck= */ msg.arg1 != 0); @@ -792,31 +802,24 @@ import java.util.concurrent.TimeoutException; } } - private void handlePlaybackInfo(ExoPlayerImplInternal.PlaybackInfoUpdate playbackInfoUpdate) { - pendingOperationAcks -= playbackInfoUpdate.operationAcks; - if (playbackInfoUpdate.positionDiscontinuity) { - hasPendingDiscontinuity = true; - pendingDiscontinuityReason = playbackInfoUpdate.discontinuityReason; - } - if (playbackInfoUpdate.hasPlayWhenReadyChangeReason) { - pendingPlayWhenReadyChangeReason = playbackInfoUpdate.playWhenReadyChangeReason; - } + private void handlePlaybackInfo( + PlaybackInfo playbackInfo, + int operationAcks, + boolean positionDiscontinuity, + @DiscontinuityReason int positionDiscontinuityReason) { + pendingOperationAcks -= operationAcks; if (pendingOperationAcks == 0) { - if (!this.playbackInfo.timeline.isEmpty() - && playbackInfoUpdate.playbackInfo.timeline.isEmpty()) { + if (!this.playbackInfo.timeline.isEmpty() && playbackInfo.timeline.isEmpty()) { // Update the masking variables, which are used when the timeline becomes empty. resetMaskingPosition(); } boolean seekProcessed = hasPendingSeek; - boolean positionDiscontinuity = hasPendingDiscontinuity; hasPendingSeek = false; - hasPendingDiscontinuity = false; updatePlaybackInfo( - playbackInfoUpdate.playbackInfo, + playbackInfo, positionDiscontinuity, - pendingDiscontinuityReason, + positionDiscontinuityReason, TIMELINE_CHANGE_REASON_SOURCE_UPDATE, - pendingPlayWhenReadyChangeReason, seekProcessed); } } @@ -853,8 +856,6 @@ import java.util.concurrent.TimeoutException; clearPlaylist ? TrackGroupArray.EMPTY : playbackInfo.trackGroups, clearPlaylist ? emptyTrackSelectorResult : playbackInfo.trackSelectorResult, mediaPeriodId, - playbackInfo.playWhenReady, - playbackInfo.playbackSuppressionReason, positionUs, /* totalBufferedDurationUs= */ 0, positionUs); @@ -865,11 +866,12 @@ import java.util.concurrent.TimeoutException; boolean positionDiscontinuity, @DiscontinuityReason int positionDiscontinuityReason, @TimelineChangeReason int timelineChangeReason, - @PlayWhenReadyChangeReason int playWhenReadyChangeReason, boolean seekProcessed) { + boolean previousIsPlaying = isPlaying(); // Assign playback info immediately such that all getters return the right values. PlaybackInfo previousPlaybackInfo = this.playbackInfo; this.playbackInfo = playbackInfo; + boolean isPlaying = isPlaying(); notifyListeners( new PlaybackInfoUpdate( playbackInfo, @@ -879,8 +881,9 @@ import java.util.concurrent.TimeoutException; positionDiscontinuity, positionDiscontinuityReason, timelineChangeReason, - playWhenReadyChangeReason, - seekProcessed)); + seekProcessed, + playWhenReady, + /* isPlayingChanged= */ previousIsPlaying != isPlaying)); } @SuppressWarnings("deprecation") @@ -1133,18 +1136,16 @@ import java.util.concurrent.TimeoutException; private final CopyOnWriteArrayList listenerSnapshot; private final TrackSelector trackSelector; private final boolean positionDiscontinuity; - @DiscontinuityReason private final int positionDiscontinuityReason; - @TimelineChangeReason private final int timelineChangeReason; - @PlayWhenReadyChangeReason private final int playWhenReadyChangeReason; + private final @Player.DiscontinuityReason int positionDiscontinuityReason; + private final int timelineChangeReason; private final boolean seekProcessed; private final boolean playbackStateChanged; private final boolean playbackErrorChanged; private final boolean timelineChanged; private final boolean isLoadingChanged; private final boolean trackSelectorResultChanged; + private final boolean playWhenReady; private final boolean isPlayingChanged; - private final boolean playWhenReadyChanged; - private final boolean playbackSuppressionReasonChanged; public PlaybackInfoUpdate( PlaybackInfo playbackInfo, @@ -1154,16 +1155,18 @@ import java.util.concurrent.TimeoutException; boolean positionDiscontinuity, @DiscontinuityReason int positionDiscontinuityReason, @TimelineChangeReason int timelineChangeReason, - @PlayWhenReadyChangeReason int playWhenReadyChangeReason, - boolean seekProcessed) { + boolean seekProcessed, + boolean playWhenReady, + boolean isPlayingChanged) { this.playbackInfo = playbackInfo; this.listenerSnapshot = new CopyOnWriteArrayList<>(listeners); this.trackSelector = trackSelector; this.positionDiscontinuity = positionDiscontinuity; this.positionDiscontinuityReason = positionDiscontinuityReason; this.timelineChangeReason = timelineChangeReason; - this.playWhenReadyChangeReason = playWhenReadyChangeReason; this.seekProcessed = seekProcessed; + this.playWhenReady = playWhenReady; + this.isPlayingChanged = isPlayingChanged; playbackStateChanged = previousPlaybackInfo.playbackState != playbackInfo.playbackState; playbackErrorChanged = previousPlaybackInfo.playbackError != playbackInfo.playbackError @@ -1172,10 +1175,6 @@ import java.util.concurrent.TimeoutException; timelineChanged = !previousPlaybackInfo.timeline.equals(playbackInfo.timeline); trackSelectorResultChanged = previousPlaybackInfo.trackSelectorResult != playbackInfo.trackSelectorResult; - playWhenReadyChanged = previousPlaybackInfo.playWhenReady != playbackInfo.playWhenReady; - playbackSuppressionReasonChanged = - previousPlaybackInfo.playbackSuppressionReason != playbackInfo.playbackSuppressionReason; - isPlayingChanged = isPlaying(previousPlaybackInfo) != isPlaying(playbackInfo); } @SuppressWarnings("deprecation") @@ -1203,49 +1202,30 @@ import java.util.concurrent.TimeoutException; playbackInfo.trackGroups, playbackInfo.trackSelectorResult.selections)); } if (isLoadingChanged) { - invokeAll( - listenerSnapshot, listener -> listener.onIsLoadingChanged(playbackInfo.isLoading)); - } - if (playbackStateChanged || playWhenReadyChanged) { invokeAll( listenerSnapshot, - listener -> - listener.onPlayerStateChanged( - playbackInfo.playWhenReady, playbackInfo.playbackState)); + listener -> { + listener.onIsLoadingChanged(playbackInfo.isLoading); + }); } if (playbackStateChanged) { invokeAll( listenerSnapshot, - listener -> listener.onPlaybackStateChanged(playbackInfo.playbackState)); - } - if (playWhenReadyChanged) { - invokeAll( - listenerSnapshot, - listener -> - listener.onPlayWhenReadyChanged( - playbackInfo.playWhenReady, playWhenReadyChangeReason)); - } - if (playbackSuppressionReasonChanged) { - invokeAll( - listenerSnapshot, - listener -> - listener.onPlaybackSuppressionReasonChanged( - playbackInfo.playbackSuppressionReason)); + listener -> { + listener.onPlayerStateChanged(playWhenReady, playbackInfo.playbackState); + listener.onPlaybackStateChanged(playbackInfo.playbackState); + }); } if (isPlayingChanged) { invokeAll( - listenerSnapshot, listener -> listener.onIsPlayingChanged(isPlaying(playbackInfo))); + listenerSnapshot, + listener -> + listener.onIsPlayingChanged(playbackInfo.playbackState == Player.STATE_READY)); } if (seekProcessed) { invokeAll(listenerSnapshot, EventListener::onSeekProcessed); } } - - private static boolean isPlaying(PlaybackInfo playbackInfo) { - return playbackInfo.playbackState == Player.STATE_READY - && playbackInfo.playWhenReady - && playbackInfo.playbackSuppressionReason == PLAYBACK_SUPPRESSION_REASON_NONE; - } } private static void invokeAll( diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index a81deb1ba5..e93d336ab9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -26,8 +26,6 @@ import androidx.annotation.CheckResult; import androidx.annotation.Nullable; import com.google.android.exoplayer2.DefaultMediaClock.PlaybackParameterListener; import com.google.android.exoplayer2.Player.DiscontinuityReason; -import com.google.android.exoplayer2.Player.PlayWhenReadyChangeReason; -import com.google.android.exoplayer2.Player.PlaybackSuppressionReason; import com.google.android.exoplayer2.Player.RepeatMode; import com.google.android.exoplayer2.analytics.AnalyticsCollector; import com.google.android.exoplayer2.source.MediaPeriod; @@ -109,6 +107,7 @@ import java.util.concurrent.atomic.AtomicBoolean; private final long backBufferDurationUs; private final boolean retainBackBufferFromKeyframe; private final DefaultMediaClock mediaClock; + private final PlaybackInfoUpdate playbackInfoUpdate; private final ArrayList pendingMessages; private final Clock clock; private final MediaPeriodQueue queue; @@ -118,9 +117,9 @@ import java.util.concurrent.atomic.AtomicBoolean; private SeekParameters seekParameters; private PlaybackInfo playbackInfo; - private PlaybackInfoUpdate playbackInfoUpdate; private Renderer[] enabledRenderers; private boolean released; + private boolean playWhenReady; private boolean pauseAtEndOfWindow; private boolean pendingPauseAtEndOfPeriod; private boolean rebuffering; @@ -142,6 +141,7 @@ import java.util.concurrent.atomic.AtomicBoolean; TrackSelectorResult emptyTrackSelectorResult, LoadControl loadControl, BandwidthMeter bandwidthMeter, + boolean playWhenReady, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled, @Nullable AnalyticsCollector analyticsCollector, @@ -152,6 +152,7 @@ import java.util.concurrent.atomic.AtomicBoolean; this.emptyTrackSelectorResult = emptyTrackSelectorResult; this.loadControl = loadControl; this.bandwidthMeter = bandwidthMeter; + this.playWhenReady = playWhenReady; this.repeatMode = repeatMode; this.shuffleModeEnabled = shuffleModeEnabled; this.eventHandler = eventHandler; @@ -163,7 +164,7 @@ import java.util.concurrent.atomic.AtomicBoolean; seekParameters = SeekParameters.DEFAULT; playbackInfo = PlaybackInfo.createDummy(emptyTrackSelectorResult); - playbackInfoUpdate = new PlaybackInfoUpdate(playbackInfo); + playbackInfoUpdate = new PlaybackInfoUpdate(); rendererCapabilities = new RendererCapabilities[renderers.length]; for (int i = 0; i < renderers.length; i++) { renderers[i].setIndex(i); @@ -197,11 +198,8 @@ import java.util.concurrent.atomic.AtomicBoolean; handler.obtainMessage(MSG_PREPARE).sendToTarget(); } - public void setPlayWhenReady( - boolean playWhenReady, @PlaybackSuppressionReason int playbackSuppressionReason) { - handler - .obtainMessage(MSG_SET_PLAY_WHEN_READY, playWhenReady ? 1 : 0, playbackSuppressionReason) - .sendToTarget(); + public void setPlayWhenReady(boolean playWhenReady) { + handler.obtainMessage(MSG_SET_PLAY_WHEN_READY, playWhenReady ? 1 : 0, 0).sendToTarget(); } public void setPauseAtEndOfWindow(boolean pauseAtEndOfWindow) { @@ -383,11 +381,7 @@ import java.util.concurrent.atomic.AtomicBoolean; prepareInternal(); break; case MSG_SET_PLAY_WHEN_READY: - setPlayWhenReadyInternal( - /* playWhenReady= */ msg.arg1 != 0, - /* playbackSuppressionReason= */ msg.arg2, - /* operationAck= */ true, - Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST); + setPlayWhenReadyInternal(msg.arg1 != 0); break; case MSG_SET_REPEAT_MODE: setRepeatModeInternal(msg.arg1); @@ -577,10 +571,17 @@ import java.util.concurrent.atomic.AtomicBoolean; } private void maybeNotifyPlaybackInfoChanged() { - playbackInfoUpdate.setPlaybackInfo(playbackInfo); - if (playbackInfoUpdate.hasPendingChange) { - eventHandler.obtainMessage(MSG_PLAYBACK_INFO_CHANGED, playbackInfoUpdate).sendToTarget(); - playbackInfoUpdate = new PlaybackInfoUpdate(playbackInfo); + if (playbackInfoUpdate.hasPendingUpdate(playbackInfo)) { + eventHandler + .obtainMessage( + MSG_PLAYBACK_INFO_CHANGED, + playbackInfoUpdate.operationAcks, + playbackInfoUpdate.positionDiscontinuity + ? playbackInfoUpdate.discontinuityReason + : C.INDEX_UNSET, + playbackInfo) + .sendToTarget(); + playbackInfoUpdate.reset(playbackInfo); } } @@ -655,17 +656,10 @@ import java.util.concurrent.atomic.AtomicBoolean; handlePlaylistInfoRefreshed(timeline); } - private void setPlayWhenReadyInternal( - boolean playWhenReady, - @PlaybackSuppressionReason int playbackSuppressionReason, - boolean operationAck, - @Player.PlayWhenReadyChangeReason int reason) - throws ExoPlaybackException { - playbackInfoUpdate.incrementPendingOperationAcks(operationAck ? 1 : 0); - playbackInfoUpdate.setPlayWhenReadyChangeReason(reason); - playbackInfo = playbackInfo.copyWithPlayWhenReady(playWhenReady, playbackSuppressionReason); + private void setPlayWhenReadyInternal(boolean playWhenReady) throws ExoPlaybackException { rebuffering = false; - if (!shouldPlayWhenReady()) { + this.playWhenReady = playWhenReady; + if (!playWhenReady) { stopRenderers(); updatePlaybackPositions(); } else { @@ -846,12 +840,7 @@ import java.util.concurrent.atomic.AtomicBoolean; || playingPeriodDurationUs <= playbackInfo.positionUs); if (finishedRendering && pendingPauseAtEndOfPeriod) { pendingPauseAtEndOfPeriod = false; - // TODO: Add new change reason for timed pause requests. - setPlayWhenReadyInternal( - /* playWhenReady= */ false, - playbackInfo.playbackSuppressionReason, - /* operationAck= */ false, - Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST); + setPlayWhenReadyInternal(false); } if (finishedRendering && playingPeriodHolder.info.isFinal) { setState(Player.STATE_ENDED); @@ -859,12 +848,12 @@ import java.util.concurrent.atomic.AtomicBoolean; } else if (playbackInfo.playbackState == Player.STATE_BUFFERING && shouldTransitionToReadyState(renderersAllowPlayback)) { setState(Player.STATE_READY); - if (shouldPlayWhenReady()) { + if (playWhenReady) { startRenderers(); } } else if (playbackInfo.playbackState == Player.STATE_READY && !(enabledRenderers.length == 0 ? isTimelineReady() : renderersAllowPlayback)) { - rebuffering = shouldPlayWhenReady(); + rebuffering = playWhenReady; setState(Player.STATE_BUFFERING); stopRenderers(); } @@ -875,7 +864,7 @@ import java.util.concurrent.atomic.AtomicBoolean; } } - if ((shouldPlayWhenReady() && playbackInfo.playbackState == Player.STATE_READY) + if ((playWhenReady && playbackInfo.playbackState == Player.STATE_READY) || playbackInfo.playbackState == Player.STATE_BUFFERING) { scheduleNextWork(operationStartTimeMs, ACTIVE_INTERVAL_MS); } else if (enabledRenderers.length != 0 && playbackInfo.playbackState != Player.STATE_ENDED) { @@ -917,7 +906,7 @@ import java.util.concurrent.atomic.AtomicBoolean; periodId = firstPeriodAndPosition.first; periodPositionUs = firstPeriodAndPosition.second; requestedContentPosition = C.TIME_UNSET; - seekPositionAdjusted = !playbackInfo.timeline.isEmpty(); + seekPositionAdjusted = true; } else { // Update the resolved seek position to take ads into account. Object periodUid = resolvedSeekPosition.first; @@ -1220,8 +1209,6 @@ import java.util.concurrent.atomic.AtomicBoolean; resetTrackInfo ? TrackGroupArray.EMPTY : playbackInfo.trackGroups, resetTrackInfo ? emptyTrackSelectorResult : playbackInfo.trackSelectorResult, mediaPeriodId, - playbackInfo.playWhenReady, - playbackInfo.playbackSuppressionReason, startPositionUs, /* totalBufferedDurationUs= */ 0, startPositionUs); @@ -1819,7 +1806,7 @@ import java.util.concurrent.atomic.AtomicBoolean; } private boolean shouldAdvancePlayingPeriod() { - if (!shouldPlayWhenReady()) { + if (!playWhenReady) { return false; } if (pendingPauseAtEndOfPeriod) { @@ -2061,7 +2048,7 @@ import java.util.concurrent.atomic.AtomicBoolean; TrackSelection newSelection = trackSelectorResult.selections.get(rendererIndex); Format[] formats = getFormats(newSelection); // The renderer needs enabling with its new track selection. - boolean playing = shouldPlayWhenReady() && playbackInfo.playbackState == Player.STATE_READY; + boolean playing = playWhenReady && playbackInfo.playbackState == Player.STATE_READY; // Consider as joining only if the renderer was previously disabled. boolean joining = !wasRendererEnabled && playing; // Enable the renderer. @@ -2134,11 +2121,6 @@ import java.util.concurrent.atomic.AtomicBoolean; .sendToTarget(); } - private boolean shouldPlayWhenReady() { - return playbackInfo.playWhenReady - && playbackInfo.playbackSuppressionReason == Player.PLAYBACK_SUPPRESSION_REASON_NONE; - } - private static PositionUpdateForPlaylistChange resolvePositionForPlaylistChange( Timeline timeline, PlaybackInfo playbackInfo, @@ -2624,31 +2606,27 @@ import java.util.concurrent.atomic.AtomicBoolean; } } - /* package */ static final class PlaybackInfoUpdate { + private static final class PlaybackInfoUpdate { - private boolean hasPendingChange; + private PlaybackInfo lastPlaybackInfo; + private int operationAcks; + private boolean positionDiscontinuity; + @DiscontinuityReason private int discontinuityReason; - public PlaybackInfo playbackInfo; - public int operationAcks; - public boolean positionDiscontinuity; - @DiscontinuityReason public int discontinuityReason; - public boolean hasPlayWhenReadyChangeReason; - @PlayWhenReadyChangeReason public int playWhenReadyChangeReason; + public boolean hasPendingUpdate(PlaybackInfo playbackInfo) { + return playbackInfo != lastPlaybackInfo || operationAcks > 0 || positionDiscontinuity; + } - public PlaybackInfoUpdate(PlaybackInfo playbackInfo) { - this.playbackInfo = playbackInfo; + public void reset(PlaybackInfo playbackInfo) { + lastPlaybackInfo = playbackInfo; + operationAcks = 0; + positionDiscontinuity = false; } public void incrementPendingOperationAcks(int operationAcks) { - hasPendingChange |= operationAcks > 0; this.operationAcks += operationAcks; } - public void setPlaybackInfo(PlaybackInfo playbackInfo) { - hasPendingChange |= this.playbackInfo != playbackInfo; - this.playbackInfo = playbackInfo; - } - public void setPositionDiscontinuity(@DiscontinuityReason int discontinuityReason) { if (positionDiscontinuity && this.discontinuityReason != Player.DISCONTINUITY_REASON_INTERNAL) { @@ -2657,16 +2635,8 @@ import java.util.concurrent.atomic.AtomicBoolean; Assertions.checkArgument(discontinuityReason == Player.DISCONTINUITY_REASON_INTERNAL); return; } - hasPendingChange = true; positionDiscontinuity = true; this.discontinuityReason = discontinuityReason; } - - public void setPlayWhenReadyChangeReason( - @PlayWhenReadyChangeReason int playWhenReadyChangeReason) { - hasPendingChange = true; - this.hasPlayWhenReadyChangeReason = true; - this.playWhenReadyChangeReason = playWhenReadyChangeReason; - } } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java index f183af0d8c..d545ce4905 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java @@ -17,7 +17,6 @@ package com.google.android.exoplayer2; import androidx.annotation.CheckResult; import androidx.annotation.Nullable; -import com.google.android.exoplayer2.Player.PlaybackSuppressionReason; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.TrackSelectorResult; @@ -59,10 +58,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; public final TrackSelectorResult trackSelectorResult; /** The {@link MediaPeriodId} of the currently loading media period in the {@link #timeline}. */ public final MediaPeriodId loadingMediaPeriodId; - /** Whether playback should proceed when {@link #playbackState} == {@link Player#STATE_READY}. */ - public final boolean playWhenReady; - /** Reason why playback is suppressed even though {@link #playWhenReady} is {@code true}. */ - @PlaybackSuppressionReason public final int playbackSuppressionReason; /** * Position up to which media is buffered in {@link #loadingMediaPeriodId) relative to the start @@ -99,8 +94,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; TrackGroupArray.EMPTY, emptyTrackSelectorResult, DUMMY_MEDIA_PERIOD_ID, - /* playWhenReady= */ false, - Player.PLAYBACK_SUPPRESSION_REASON_NONE, /* bufferedPositionUs= */ 0, /* totalBufferedDurationUs= */ 0, /* positionUs= */ 0); @@ -131,8 +124,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; TrackGroupArray trackGroups, TrackSelectorResult trackSelectorResult, MediaPeriodId loadingMediaPeriodId, - boolean playWhenReady, - @PlaybackSuppressionReason int playbackSuppressionReason, long bufferedPositionUs, long totalBufferedDurationUs, long positionUs) { @@ -145,8 +136,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; this.trackGroups = trackGroups; this.trackSelectorResult = trackSelectorResult; this.loadingMediaPeriodId = loadingMediaPeriodId; - this.playWhenReady = playWhenReady; - this.playbackSuppressionReason = playbackSuppressionReason; this.bufferedPositionUs = bufferedPositionUs; this.totalBufferedDurationUs = totalBufferedDurationUs; this.positionUs = positionUs; @@ -188,8 +177,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; trackGroups, trackSelectorResult, loadingMediaPeriodId, - playWhenReady, - playbackSuppressionReason, bufferedPositionUs, totalBufferedDurationUs, positionUs); @@ -213,8 +200,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; trackGroups, trackSelectorResult, loadingMediaPeriodId, - playWhenReady, - playbackSuppressionReason, bufferedPositionUs, totalBufferedDurationUs, positionUs); @@ -238,8 +223,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; trackGroups, trackSelectorResult, loadingMediaPeriodId, - playWhenReady, - playbackSuppressionReason, bufferedPositionUs, totalBufferedDurationUs, positionUs); @@ -263,8 +246,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; trackGroups, trackSelectorResult, loadingMediaPeriodId, - playWhenReady, - playbackSuppressionReason, bufferedPositionUs, totalBufferedDurationUs, positionUs); @@ -288,8 +269,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; trackGroups, trackSelectorResult, loadingMediaPeriodId, - playWhenReady, - playbackSuppressionReason, bufferedPositionUs, totalBufferedDurationUs, positionUs); @@ -313,37 +292,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; trackGroups, trackSelectorResult, loadingMediaPeriodId, - playWhenReady, - playbackSuppressionReason, - bufferedPositionUs, - totalBufferedDurationUs, - positionUs); - } - - /** - * Copies playback info with new information about whether playback should proceed when ready. - * - * @param playWhenReady Whether playback should proceed when {@link #playbackState} == {@link - * Player#STATE_READY}. - * @param playbackSuppressionReason Reason why playback is suppressed even though {@link - * #playWhenReady} is {@code true}. - * @return Copied playback info with new information. - */ - @CheckResult - public PlaybackInfo copyWithPlayWhenReady( - boolean playWhenReady, @PlaybackSuppressionReason int playbackSuppressionReason) { - return new PlaybackInfo( - timeline, - periodId, - requestedContentPositionUs, - playbackState, - playbackError, - isLoading, - trackGroups, - trackSelectorResult, - loadingMediaPeriodId, - playWhenReady, - playbackSuppressionReason, bufferedPositionUs, totalBufferedDurationUs, positionUs); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java index ea0e18ca18..e951c67725 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java @@ -548,7 +548,6 @@ public final class ExoPlayerTest { // only on seek processed callback). .seek(5) .seek(60) - .waitForSeekProcessed() .play() .build(); final List playbackStatesWhenSeekProcessed = new ArrayList<>(); @@ -2791,7 +2790,6 @@ public final class ExoPlayerTest { .pause() .waitForPlaybackState(Player.STATE_READY) .seek(/* windowIndex= */ 1, /* positionMs= */ 0) - .waitForSeekProcessed() .play() .build(); List trackGroupsList = new ArrayList<>(); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java b/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java index fb424cc92c..5b3b321e09 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java @@ -421,8 +421,6 @@ public final class MediaPeriodQueueTest { /* trackGroups= */ null, /* trackSelectorResult= */ null, /* loadingMediaPeriodId= */ null, - /* playWhenReady= */ false, - Player.PLAYBACK_SUPPRESSION_REASON_NONE, /* bufferedPositionUs= */ 0, /* totalBufferedDurationUs= */ 0, /* positionUs= */ 0); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java index ac0c444769..f779b70637 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java @@ -315,7 +315,6 @@ public final class AnalyticsCollectorTest { .pause() .waitForPlaybackState(Player.STATE_READY) .seek(/* windowIndex= */ 1, /* positionMs= */ 0) - .waitForSeekProcessed() .play() .build(); TestAnalyticsListener listener = runAnalyticsTest(mediaSource, actionSchedule); @@ -328,8 +327,8 @@ public final class AnalyticsCollectorTest { WINDOW_0 /* setPlayWhenReady=false */, period0 /* READY */, period1 /* BUFFERING */, - period1 /* setPlayWhenReady=true */, period1 /* READY */, + period1 /* setPlayWhenReady=true */, period1 /* ENDED */); assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) .containsExactly(WINDOW_0 /* PLAYLIST_CHANGED */, period0 /* SOURCE_UPDATE */); @@ -467,9 +466,6 @@ public final class AnalyticsCollectorTest { .pause() .waitForPlaybackState(Player.STATE_READY) .setMediaSources(/* resetPosition= */ false, mediaSource2) - .waitForTimelineChanged() - // Wait until loading started to prevent flakiness caused by loading finishing too fast. - .waitForIsLoading(true) .play() .build(); TestAnalyticsListener listener = runAnalyticsTest(mediaSource1, actionSchedule); @@ -490,7 +486,7 @@ public final class AnalyticsCollectorTest { WINDOW_0 /* setPlayWhenReady=false */, period0Seq0 /* READY */, WINDOW_0 /* BUFFERING */, - period0Seq1 /* setPlayWhenReady=true */, + WINDOW_0 /* setPlayWhenReady=true */, period0Seq1 /* READY */, period0Seq1 /* ENDED */); assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) @@ -549,8 +545,6 @@ public final class AnalyticsCollectorTest { .waitForPlaybackState(Player.STATE_IDLE) .seek(/* positionMs= */ 0) .prepare() - // Wait until loading started to assert loading events without flakiness. - .waitForIsLoading(true) .play() .waitForPlaybackState(Player.STATE_ENDED) .build(); @@ -704,8 +698,6 @@ public final class AnalyticsCollectorTest { .waitForIsLoading(true) .waitForIsLoading(false) .removeMediaItem(/* index= */ 0) - .waitForPlaybackState(Player.STATE_BUFFERING) - .waitForPlaybackState(Player.STATE_READY) .play() .build(); TestAnalyticsListener listener = runAnalyticsTest(fakeMediaSource, actionSchedule); @@ -727,8 +719,8 @@ public final class AnalyticsCollectorTest { WINDOW_0 /* BUFFERING */, period0Seq0 /* READY */, period0Seq1 /* BUFFERING */, - period0Seq1 /* READY */, period0Seq1 /* setPlayWhenReady=true */, + period0Seq1 /* READY */, period0Seq1 /* ENDED */); assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) .containsExactly( @@ -823,19 +815,6 @@ public final class AnalyticsCollectorTest { } }) .pause() - // Ensure everything is preloaded. - .waitForIsLoading(true) - .waitForIsLoading(false) - .waitForIsLoading(true) - .waitForIsLoading(false) - .waitForIsLoading(true) - .waitForIsLoading(false) - .waitForIsLoading(true) - .waitForIsLoading(false) - .waitForIsLoading(true) - .waitForIsLoading(false) - .waitForIsLoading(true) - .waitForIsLoading(false) .waitForPlaybackState(Player.STATE_READY) // Wait in each content part to ensure previously triggered events get a chance to be // delivered. This prevents flakiness caused by playback progressing too fast. @@ -1039,8 +1018,6 @@ public final class AnalyticsCollectorTest { .waitForIsLoading(false) // Seek behind the midroll. .seek(6 * C.MICROS_PER_SECOND) - // Wait until loading started again to assert loading events without flakiness. - .waitForIsLoading(true) .play() .waitForPlaybackState(Player.STATE_ENDED) .build(); @@ -1070,8 +1047,8 @@ public final class AnalyticsCollectorTest { WINDOW_0 /* setPlayWhenReady=false */, WINDOW_0 /* BUFFERING */, contentBeforeMidroll /* READY */, + contentAfterMidroll /* setPlayWhenReady=true */, midrollAd /* BUFFERING */, - midrollAd /* setPlayWhenReady=true */, midrollAd /* READY */, contentAfterMidroll /* ENDED */); assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED))