diff --git a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java index 7d8d05bbaa6..80d9817a463 100644 --- a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java +++ b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java @@ -458,32 +458,16 @@ public void seekTo(int windowIndex, long positionMs) { flushNotifications(); } - /** @deprecated Use {@link #setPlaybackSpeed(float)} instead. */ - @SuppressWarnings("deprecation") - @Deprecated @Override public void setPlaybackParameters(@Nullable PlaybackParameters playbackParameters) { // Unsupported by the RemoteMediaClient API. Do nothing. } - /** @deprecated Use {@link #getPlaybackSpeed()} instead. */ - @SuppressWarnings("deprecation") - @Deprecated @Override public PlaybackParameters getPlaybackParameters() { return PlaybackParameters.DEFAULT; } - @Override - public void setPlaybackSpeed(float playbackSpeed) { - // Unsupported by the RemoteMediaClient API. Do nothing. - } - - @Override - public float getPlaybackSpeed() { - return Player.DEFAULT_PLAYBACK_SPEED; - } - @Override public void stop(boolean reset) { playbackState = STATE_IDLE; diff --git a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/PlayerWrapper.java b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/PlayerWrapper.java index 888eccbe940..453a7b6d55f 100644 --- a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/PlayerWrapper.java +++ b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/PlayerWrapper.java @@ -26,6 +26,7 @@ import com.google.android.exoplayer2.ControlDispatcher; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.audio.AudioAttributes; @@ -383,11 +384,11 @@ public AudioAttributesCompat getAudioAttributes() { } public void setPlaybackSpeed(float playbackSpeed) { - player.setPlaybackSpeed(playbackSpeed); + player.setPlaybackParameters(new PlaybackParameters(playbackSpeed)); } public float getPlaybackSpeed() { - return player.getPlaybackSpeed(); + return player.getPlaybackParameters().speed; } public void reset() { @@ -483,8 +484,8 @@ private void handleShuffleMode(boolean shuffleModeEnabled) { listener.onShuffleModeChanged(Utils.getShuffleMode(shuffleModeEnabled)); } - private void handlePlaybackSpeedChanged(float playbackSpeed) { - listener.onPlaybackSpeedChanged(playbackSpeed); + private void handlePlaybackParametersChanged(PlaybackParameters playbackParameters) { + listener.onPlaybackSpeedChanged(playbackParameters.speed); } private void handleTimelineChanged(Timeline timeline) { @@ -627,8 +628,8 @@ public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) { } @Override - public void onPlaybackSpeedChanged(float playbackSpeed) { - handlePlaybackSpeedChanged(playbackSpeed); + public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { + handlePlaybackParametersChanged(playbackParameters); } @Override diff --git a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java index f3edfa3545a..85d0155bd77 100644 --- a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java +++ b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java @@ -38,6 +38,7 @@ import com.google.android.exoplayer2.DefaultControlDispatcher; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.util.Assertions; @@ -127,8 +128,8 @@ public final class MediaSessionConnector { @PlaybackActions public static final long DEFAULT_PLAYBACK_ACTIONS = ALL_PLAYBACK_ACTIONS; /** - * The name of the {@link PlaybackStateCompat} float extra with the value of {@link - * Player#getPlaybackSpeed()}. + * The name of the {@link PlaybackStateCompat} float extra with the value of {@code + * Player.getPlaybackParameters().speed}. */ public static final String EXTRAS_SPEED = "EXO_SPEED"; @@ -765,7 +766,7 @@ public final void invalidateMediaSessionPlaybackState() { queueNavigator != null ? queueNavigator.getActiveQueueItemId(player) : MediaSessionCompat.QueueItem.UNKNOWN_ID; - float playbackSpeed = player.getPlaybackSpeed(); + float playbackSpeed = player.getPlaybackParameters().speed; extras.putFloat(EXTRAS_SPEED, playbackSpeed); float sessionPlaybackSpeed = player.isPlaying() ? playbackSpeed : 0f; builder @@ -1134,7 +1135,7 @@ public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) { } @Override - public void onPlaybackSpeedChanged(float playbackSpeed) { + public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { invalidateMediaSessionPlaybackState(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/DefaultMediaClock.java b/library/core/src/main/java/com/google/android/exoplayer2/DefaultMediaClock.java index 6276f3bca88..9ee1846fc12 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/DefaultMediaClock.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/DefaultMediaClock.java @@ -27,20 +27,20 @@ */ /* package */ final class DefaultMediaClock implements MediaClock { - /** Listener interface to be notified of changes to the active playback speed. */ - public interface PlaybackSpeedListener { + /** Listener interface to be notified of changes to the active playback parameters. */ + public interface PlaybackParametersListener { /** - * Called when the active playback speed changed. Will not be called for {@link - * #setPlaybackSpeed(float)}. + * Called when the active playback parameters changed. Will not be called for {@link + * #setPlaybackParameters(PlaybackParameters)}. * - * @param newPlaybackSpeed The newly active playback speed. + * @param newPlaybackParameters The newly active playback parameters. */ - void onPlaybackSpeedChanged(float newPlaybackSpeed); + void onPlaybackParametersChanged(PlaybackParameters newPlaybackParameters); } private final StandaloneMediaClock standaloneClock; - private final PlaybackSpeedListener listener; + private final PlaybackParametersListener listener; @Nullable private Renderer rendererClockSource; @Nullable private MediaClock rendererClock; @@ -48,13 +48,13 @@ public interface PlaybackSpeedListener { private boolean standaloneClockIsStarted; /** - * Creates a new instance with listener for playback speed changes and a {@link Clock} to use for - * the standalone clock implementation. + * Creates a new instance with a listener for playback parameters changes and a {@link Clock} to + * use for the standalone clock implementation. * - * @param listener A {@link PlaybackSpeedListener} to listen for playback speed changes. + * @param listener A {@link PlaybackParametersListener} to listen for playback parameters changes. * @param clock A {@link Clock}. */ - public DefaultMediaClock(PlaybackSpeedListener listener, Clock clock) { + public DefaultMediaClock(PlaybackParametersListener listener, Clock clock) { this.listener = listener; this.standaloneClock = new StandaloneMediaClock(clock); isUsingStandaloneClock = true; @@ -102,7 +102,7 @@ public void onRendererEnabled(Renderer renderer) throws ExoPlaybackException { } this.rendererClock = rendererMediaClock; this.rendererClockSource = renderer; - rendererClock.setPlaybackSpeed(standaloneClock.getPlaybackSpeed()); + rendererClock.setPlaybackParameters(standaloneClock.getPlaybackParameters()); } } @@ -140,19 +140,19 @@ public long getPositionUs() { } @Override - public void setPlaybackSpeed(float playbackSpeed) { + public void setPlaybackParameters(PlaybackParameters playbackParameters) { if (rendererClock != null) { - rendererClock.setPlaybackSpeed(playbackSpeed); - playbackSpeed = rendererClock.getPlaybackSpeed(); + rendererClock.setPlaybackParameters(playbackParameters); + playbackParameters = rendererClock.getPlaybackParameters(); } - standaloneClock.setPlaybackSpeed(playbackSpeed); + standaloneClock.setPlaybackParameters(playbackParameters); } @Override - public float getPlaybackSpeed() { + public PlaybackParameters getPlaybackParameters() { return rendererClock != null - ? rendererClock.getPlaybackSpeed() - : standaloneClock.getPlaybackSpeed(); + ? rendererClock.getPlaybackParameters() + : standaloneClock.getPlaybackParameters(); } private void syncClocks(boolean isReadingAhead) { @@ -180,10 +180,10 @@ private void syncClocks(boolean isReadingAhead) { } // Continuously sync stand-alone clock to renderer clock so that it can take over if needed. standaloneClock.resetPosition(rendererClockPositionUs); - float playbackSpeed = rendererClock.getPlaybackSpeed(); - if (playbackSpeed != standaloneClock.getPlaybackSpeed()) { - standaloneClock.setPlaybackSpeed(playbackSpeed); - listener.onPlaybackSpeedChanged(playbackSpeed); + PlaybackParameters playbackParameters = rendererClock.getPlaybackParameters(); + if (!playbackParameters.equals(standaloneClock.getPlaybackParameters())) { + standaloneClock.setPlaybackParameters(playbackParameters); + listener.onPlaybackParametersChanged(playbackParameters); } } 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 76be46eb40a..b1f57364658 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 @@ -619,32 +619,17 @@ public void seekTo(int windowIndex, long positionMs) { /* seekProcessed= */ true); } - /** @deprecated Use {@link #setPlaybackSpeed(float)} instead. */ - @SuppressWarnings("deprecation") - @Deprecated @Override public void setPlaybackParameters(@Nullable PlaybackParameters playbackParameters) { - setPlaybackSpeed( - playbackParameters != null ? playbackParameters.speed : Player.DEFAULT_PLAYBACK_SPEED); - } - - /** @deprecated Use {@link #getPlaybackSpeed()} instead. */ - @SuppressWarnings("deprecation") - @Deprecated - @Override - public PlaybackParameters getPlaybackParameters() { - return new PlaybackParameters(playbackInfo.playbackSpeed); - } - - @Override - public void setPlaybackSpeed(float playbackSpeed) { - checkState(playbackSpeed > 0); - if (playbackInfo.playbackSpeed == playbackSpeed) { + if (playbackParameters == null) { + playbackParameters = PlaybackParameters.DEFAULT; + } + if (playbackInfo.playbackParameters.equals(playbackParameters)) { return; } - PlaybackInfo newPlaybackInfo = playbackInfo.copyWithPlaybackSpeed(playbackSpeed); + PlaybackInfo newPlaybackInfo = playbackInfo.copyWithPlaybackParameters(playbackParameters); pendingOperationAcks++; - internalPlayer.setPlaybackSpeed(playbackSpeed); + internalPlayer.setPlaybackParameters(playbackParameters); updatePlaybackInfo( newPlaybackInfo, /* positionDiscontinuity= */ false, @@ -655,8 +640,8 @@ public void setPlaybackSpeed(float playbackSpeed) { } @Override - public float getPlaybackSpeed() { - return playbackInfo.playbackSpeed; + public PlaybackParameters getPlaybackParameters() { + return playbackInfo.playbackParameters; } @Override @@ -1366,7 +1351,7 @@ private static final class PlaybackInfoUpdate implements Runnable { private final boolean playWhenReadyChanged; private final boolean playbackSuppressionReasonChanged; private final boolean isPlayingChanged; - private final boolean playbackSpeedChanged; + private final boolean playbackParametersChanged; private final boolean offloadSchedulingEnabledChanged; public PlaybackInfoUpdate( @@ -1405,7 +1390,8 @@ public PlaybackInfoUpdate( playbackSuppressionReasonChanged = previousPlaybackInfo.playbackSuppressionReason != playbackInfo.playbackSuppressionReason; isPlayingChanged = isPlaying(previousPlaybackInfo) != isPlaying(playbackInfo); - playbackSpeedChanged = previousPlaybackInfo.playbackSpeed != playbackInfo.playbackSpeed; + playbackParametersChanged = + !previousPlaybackInfo.playbackParameters.equals(playbackInfo.playbackParameters); offloadSchedulingEnabledChanged = previousPlaybackInfo.offloadSchedulingEnabled != playbackInfo.offloadSchedulingEnabled; } @@ -1473,13 +1459,11 @@ public void run() { invokeAll( listenerSnapshot, listener -> listener.onIsPlayingChanged(isPlaying(playbackInfo))); } - if (playbackSpeedChanged) { - PlaybackParameters playbackParameters = new PlaybackParameters(playbackInfo.playbackSpeed); + if (playbackParametersChanged) { invokeAll( listenerSnapshot, listener -> { - listener.onPlaybackSpeedChanged(playbackInfo.playbackSpeed); - listener.onPlaybackParametersChanged(playbackParameters); + listener.onPlaybackParametersChanged(playbackInfo.playbackParameters); }); } if (seekProcessed) { 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 c1c6a629202..220b2633178 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 @@ -27,7 +27,7 @@ import android.util.Pair; import androidx.annotation.CheckResult; import androidx.annotation.Nullable; -import com.google.android.exoplayer2.DefaultMediaClock.PlaybackSpeedListener; +import com.google.android.exoplayer2.DefaultMediaClock.PlaybackParametersListener; import com.google.android.exoplayer2.Player.DiscontinuityReason; import com.google.android.exoplayer2.Player.PlayWhenReadyChangeReason; import com.google.android.exoplayer2.Player.PlaybackSuppressionReason; @@ -61,7 +61,7 @@ MediaPeriod.Callback, TrackSelector.InvalidationListener, MediaSourceList.MediaSourceListInfoRefreshListener, - PlaybackSpeedListener, + PlaybackParametersListener, PlayerMessage.Sender { private static final String TAG = "ExoPlayerImplInternal"; @@ -121,7 +121,7 @@ public interface PlaybackInfoUpdateListener { private static final int MSG_SET_PLAY_WHEN_READY = 1; private static final int MSG_DO_SOME_WORK = 2; private static final int MSG_SEEK_TO = 3; - private static final int MSG_SET_PLAYBACK_SPEED = 4; + private static final int MSG_SET_PLAYBACK_PARAMETERS = 4; private static final int MSG_SET_SEEK_PARAMETERS = 5; private static final int MSG_STOP = 6; private static final int MSG_RELEASE = 7; @@ -133,7 +133,7 @@ public interface PlaybackInfoUpdateListener { private static final int MSG_SET_FOREGROUND_MODE = 13; private static final int MSG_SEND_MESSAGE = 14; private static final int MSG_SEND_MESSAGE_TO_TARGET_THREAD = 15; - private static final int MSG_PLAYBACK_SPEED_CHANGED_INTERNAL = 16; + private static final int MSG_PLAYBACK_PARAMETERS_CHANGED_INTERNAL = 16; private static final int MSG_SET_MEDIA_SOURCES = 17; private static final int MSG_ADD_MEDIA_SOURCES = 18; private static final int MSG_MOVE_MEDIA_SOURCES = 19; @@ -301,8 +301,8 @@ public void seekTo(Timeline timeline, int windowIndex, long positionUs) { .sendToTarget(); } - public void setPlaybackSpeed(float playbackSpeed) { - handler.obtainMessage(MSG_SET_PLAYBACK_SPEED, playbackSpeed).sendToTarget(); + public void setPlaybackParameters(PlaybackParameters playbackParameters) { + handler.obtainMessage(MSG_SET_PLAYBACK_PARAMETERS, playbackParameters).sendToTarget(); } public void setSeekParameters(SeekParameters seekParameters) { @@ -432,11 +432,11 @@ public void onTrackSelectionsInvalidated() { handler.sendEmptyMessage(MSG_TRACK_SELECTION_INVALIDATED); } - // DefaultMediaClock.PlaybackSpeedListener implementation. + // DefaultMediaClock.PlaybackParametersListener implementation. @Override - public void onPlaybackSpeedChanged(float playbackSpeed) { - sendPlaybackSpeedChangedInternal(playbackSpeed, /* acknowledgeCommand= */ false); + public void onPlaybackParametersChanged(PlaybackParameters newPlaybackParameters) { + sendPlaybackParametersChangedInternal(newPlaybackParameters, /* acknowledgeCommand= */ false); } // Handler.Callback implementation. @@ -467,8 +467,8 @@ public boolean handleMessage(Message msg) { case MSG_SEEK_TO: seekToInternal((SeekPosition) msg.obj); break; - case MSG_SET_PLAYBACK_SPEED: - setPlaybackSpeedInternal((Float) msg.obj); + case MSG_SET_PLAYBACK_PARAMETERS: + setPlaybackParametersInternal((PlaybackParameters) msg.obj); break; case MSG_SET_SEEK_PARAMETERS: setSeekParametersInternal((SeekParameters) msg.obj); @@ -489,8 +489,9 @@ public boolean handleMessage(Message msg) { case MSG_TRACK_SELECTION_INVALIDATED: reselectTracksInternal(); break; - case MSG_PLAYBACK_SPEED_CHANGED_INTERNAL: - handlePlaybackSpeed((Float) msg.obj, /* acknowledgeCommand= */ msg.arg1 != 0); + case MSG_PLAYBACK_PARAMETERS_CHANGED_INTERNAL: + handlePlaybackParameters( + (PlaybackParameters) msg.obj, /* acknowledgeCommand= */ msg.arg1 != 0); break; case MSG_SEND_MESSAGE: sendMessageInternal((PlayerMessage) msg.obj); @@ -1184,9 +1185,10 @@ private void resetRendererPosition(long periodPositionUs) throws ExoPlaybackExce notifyTrackSelectionDiscontinuity(); } - private void setPlaybackSpeedInternal(float playbackSpeed) { - mediaClock.setPlaybackSpeed(playbackSpeed); - sendPlaybackSpeedChangedInternal(mediaClock.getPlaybackSpeed(), /* acknowledgeCommand= */ true); + private void setPlaybackParametersInternal(PlaybackParameters playbackParameters) { + mediaClock.setPlaybackParameters(playbackParameters); + sendPlaybackParametersChangedInternal( + mediaClock.getPlaybackParameters(), /* acknowledgeCommand= */ true); } private void setSeekParametersInternal(SeekParameters seekParameters) { @@ -1303,7 +1305,7 @@ private void resetInternal( mediaPeriodId, playbackInfo.playWhenReady, playbackInfo.playbackSuppressionReason, - playbackInfo.playbackSpeed, + playbackInfo.playbackParameters, startPositionUs, /* totalBufferedDurationUs= */ 0, startPositionUs, @@ -1508,7 +1510,7 @@ private void disableRenderer(Renderer renderer) throws ExoPlaybackException { } private void reselectTracksInternal() throws ExoPlaybackException { - float playbackSpeed = mediaClock.getPlaybackSpeed(); + float playbackSpeed = mediaClock.getPlaybackParameters().speed; // Reselect tracks on each period in turn, until the selection changes. MediaPeriodHolder periodHolder = queue.getPlayingPeriod(); MediaPeriodHolder readingPeriodHolder = queue.getReadingPeriod(); @@ -1626,7 +1628,7 @@ private boolean shouldTransitionToReadyState(boolean renderersReadyOrEnded) { boolean bufferedToEnd = loadingHolder.isFullyBuffered() && loadingHolder.info.isFinal; return bufferedToEnd || loadControl.shouldStartPlayback( - getTotalBufferedDurationUs(), mediaClock.getPlaybackSpeed(), rebuffering); + getTotalBufferedDurationUs(), mediaClock.getPlaybackParameters().speed, rebuffering); } private boolean isTimelineReady() { @@ -1962,7 +1964,8 @@ private void handlePeriodPrepared(MediaPeriod mediaPeriod) throws ExoPlaybackExc return; } MediaPeriodHolder loadingPeriodHolder = queue.getLoadingPeriod(); - loadingPeriodHolder.handlePrepared(mediaClock.getPlaybackSpeed(), playbackInfo.timeline); + loadingPeriodHolder.handlePrepared( + mediaClock.getPlaybackParameters().speed, playbackInfo.timeline); updateLoadControlTrackSelection( loadingPeriodHolder.getTrackGroups(), loadingPeriodHolder.getTrackSelectorResult()); if (loadingPeriodHolder == queue.getPlayingPeriod()) { @@ -1987,14 +1990,15 @@ private void handleContinueLoadingRequested(MediaPeriod mediaPeriod) { maybeContinueLoading(); } - private void handlePlaybackSpeed(float playbackSpeed, boolean acknowledgeCommand) + private void handlePlaybackParameters( + PlaybackParameters playbackParameters, boolean acknowledgeCommand) throws ExoPlaybackException { playbackInfoUpdate.incrementPendingOperationAcks(acknowledgeCommand ? 1 : 0); - playbackInfo = playbackInfo.copyWithPlaybackSpeed(playbackSpeed); - updateTrackSelectionPlaybackSpeed(playbackSpeed); + playbackInfo = playbackInfo.copyWithPlaybackParameters(playbackParameters); + updateTrackSelectionPlaybackSpeed(playbackParameters.speed); for (Renderer renderer : renderers) { if (renderer != null) { - renderer.setOperatingRate(playbackSpeed); + renderer.setOperatingRate(playbackParameters.speed); } } } @@ -2020,7 +2024,7 @@ private boolean shouldContinueLoading() { : loadingPeriodHolder.toPeriodTime(rendererPositionUs) - loadingPeriodHolder.info.startPositionUs; return loadControl.shouldContinueLoading( - playbackPositionUs, bufferedDurationUs, mediaClock.getPlaybackSpeed()); + playbackPositionUs, bufferedDurationUs, mediaClock.getPlaybackParameters().speed); } private boolean isLoadingPossible() { @@ -2196,10 +2200,14 @@ private void updateLoadControlTrackSelection( loadControl.onTracksSelected(renderers, trackGroups, trackSelectorResult.selections); } - private void sendPlaybackSpeedChangedInternal(float playbackSpeed, boolean acknowledgeCommand) { + private void sendPlaybackParametersChangedInternal( + PlaybackParameters playbackParameters, boolean acknowledgeCommand) { handler .obtainMessage( - MSG_PLAYBACK_SPEED_CHANGED_INTERNAL, acknowledgeCommand ? 1 : 0, 0, playbackSpeed) + MSG_PLAYBACK_PARAMETERS_CHANGED_INTERNAL, + acknowledgeCommand ? 1 : 0, + 0, + playbackParameters) .sendToTarget(); } 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 57295c54fc6..9fb65630058 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 @@ -63,8 +63,8 @@ public final boolean playWhenReady; /** Reason why playback is suppressed even though {@link #playWhenReady} is {@code true}. */ @PlaybackSuppressionReason public final int playbackSuppressionReason; - /** The playback speed. */ - public final float playbackSpeed; + /** The playback parameters. */ + public final PlaybackParameters playbackParameters; /** Whether offload scheduling is enabled for the main player loop. */ public final boolean offloadSchedulingEnabled; @@ -105,7 +105,7 @@ public static PlaybackInfo createDummy(TrackSelectorResult emptyTrackSelectorRes PLACEHOLDER_MEDIA_PERIOD_ID, /* playWhenReady= */ false, Player.PLAYBACK_SUPPRESSION_REASON_NONE, - Player.DEFAULT_PLAYBACK_SPEED, + PlaybackParameters.DEFAULT, /* bufferedPositionUs= */ 0, /* totalBufferedDurationUs= */ 0, /* positionUs= */ 0, @@ -119,10 +119,14 @@ public static PlaybackInfo createDummy(TrackSelectorResult emptyTrackSelectorRes * @param periodId See {@link #periodId}. * @param requestedContentPositionUs See {@link #requestedContentPositionUs}. * @param playbackState See {@link #playbackState}. + * @param playbackError See {@link #playbackError}. * @param isLoading See {@link #isLoading}. * @param trackGroups See {@link #trackGroups}. * @param trackSelectorResult See {@link #trackSelectorResult}. * @param loadingMediaPeriodId See {@link #loadingMediaPeriodId}. + * @param playWhenReady See {@link #playWhenReady}. + * @param playbackSuppressionReason See {@link #playbackSuppressionReason}. + * @param playbackParameters See {@link #playbackParameters}. * @param bufferedPositionUs See {@link #bufferedPositionUs}. * @param totalBufferedDurationUs See {@link #totalBufferedDurationUs}. * @param positionUs See {@link #positionUs}. @@ -140,7 +144,7 @@ public PlaybackInfo( MediaPeriodId loadingMediaPeriodId, boolean playWhenReady, @PlaybackSuppressionReason int playbackSuppressionReason, - float playbackSpeed, + PlaybackParameters playbackParameters, long bufferedPositionUs, long totalBufferedDurationUs, long positionUs, @@ -156,7 +160,7 @@ public PlaybackInfo( this.loadingMediaPeriodId = loadingMediaPeriodId; this.playWhenReady = playWhenReady; this.playbackSuppressionReason = playbackSuppressionReason; - this.playbackSpeed = playbackSpeed; + this.playbackParameters = playbackParameters; this.bufferedPositionUs = bufferedPositionUs; this.totalBufferedDurationUs = totalBufferedDurationUs; this.positionUs = positionUs; @@ -201,7 +205,7 @@ public PlaybackInfo copyWithNewPosition( loadingMediaPeriodId, playWhenReady, playbackSuppressionReason, - playbackSpeed, + playbackParameters, bufferedPositionUs, totalBufferedDurationUs, positionUs, @@ -228,7 +232,7 @@ public PlaybackInfo copyWithTimeline(Timeline timeline) { loadingMediaPeriodId, playWhenReady, playbackSuppressionReason, - playbackSpeed, + playbackParameters, bufferedPositionUs, totalBufferedDurationUs, positionUs, @@ -255,7 +259,7 @@ public PlaybackInfo copyWithPlaybackState(int playbackState) { loadingMediaPeriodId, playWhenReady, playbackSuppressionReason, - playbackSpeed, + playbackParameters, bufferedPositionUs, totalBufferedDurationUs, positionUs, @@ -282,7 +286,7 @@ public PlaybackInfo copyWithPlaybackError(@Nullable ExoPlaybackException playbac loadingMediaPeriodId, playWhenReady, playbackSuppressionReason, - playbackSpeed, + playbackParameters, bufferedPositionUs, totalBufferedDurationUs, positionUs, @@ -309,7 +313,7 @@ public PlaybackInfo copyWithIsLoading(boolean isLoading) { loadingMediaPeriodId, playWhenReady, playbackSuppressionReason, - playbackSpeed, + playbackParameters, bufferedPositionUs, totalBufferedDurationUs, positionUs, @@ -336,7 +340,7 @@ public PlaybackInfo copyWithLoadingMediaPeriodId(MediaPeriodId loadingMediaPerio loadingMediaPeriodId, playWhenReady, playbackSuppressionReason, - playbackSpeed, + playbackParameters, bufferedPositionUs, totalBufferedDurationUs, positionUs, @@ -367,7 +371,7 @@ public PlaybackInfo copyWithPlayWhenReady( loadingMediaPeriodId, playWhenReady, playbackSuppressionReason, - playbackSpeed, + playbackParameters, bufferedPositionUs, totalBufferedDurationUs, positionUs, @@ -375,13 +379,13 @@ public PlaybackInfo copyWithPlayWhenReady( } /** - * Copies playback info with new playback speed. + * Copies playback info with new playback parameters. * - * @param playbackSpeed New playback speed. See {@link #playbackSpeed}. - * @return Copied playback info with new playback speed. + * @param playbackParameters New playback parameters. See {@link #playbackParameters}. + * @return Copied playback info with new playback parameters. */ @CheckResult - public PlaybackInfo copyWithPlaybackSpeed(float playbackSpeed) { + public PlaybackInfo copyWithPlaybackParameters(PlaybackParameters playbackParameters) { return new PlaybackInfo( timeline, periodId, @@ -394,7 +398,7 @@ public PlaybackInfo copyWithPlaybackSpeed(float playbackSpeed) { loadingMediaPeriodId, playWhenReady, playbackSuppressionReason, - playbackSpeed, + playbackParameters, bufferedPositionUs, totalBufferedDurationUs, positionUs, @@ -422,7 +426,7 @@ public PlaybackInfo copyWithOffloadSchedulingEnabled(boolean offloadSchedulingEn loadingMediaPeriodId, playWhenReady, playbackSuppressionReason, - playbackSpeed, + playbackParameters, bufferedPositionUs, totalBufferedDurationUs, positionUs, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/PlaybackParameters.java b/library/core/src/main/java/com/google/android/exoplayer2/PlaybackParameters.java index afa0a7ebc40..7dcd6f80aa0 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/PlaybackParameters.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/PlaybackParameters.java @@ -17,13 +17,9 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.Util; -/** - * @deprecated Use {@link Player#setPlaybackSpeed(float)} and {@link - * Player.AudioComponent#setSkipSilenceEnabled(boolean)} instead. - */ -@SuppressWarnings("deprecation") -@Deprecated +/** Parameters that apply to playback, including speed setting. */ public final class PlaybackParameters { /** The default playback parameters: real-time playback with no silence skipping. */ @@ -32,16 +28,34 @@ public final class PlaybackParameters { /** The factor by which playback will be sped up. */ public final float speed; + /** The factor by which pitch will be shifted. */ + public final float pitch; + private final int scaledUsPerMs; /** - * Creates new playback parameters that set the playback speed. + * Creates new playback parameters that set the playback speed. The pitch of audio will not be + * adjusted, so the effect is to time-stretch the audio. * * @param speed The factor by which playback will be sped up. Must be greater than zero. */ public PlaybackParameters(float speed) { + this(speed, /* pitch= */ 1f); + } + + /** + * Creates new playback parameters that set the playback speed/pitch. + * + * @param speed The factor by which playback will be sped up. Must be greater than zero. + * @param pitch The factor by which the pitch of audio will be adjusted. Must be greater than + * zero. Useful values are {@code 1} (to time-stretch audio) and the same value as passed in + * as the {@code speed} (to resample audio, which is useful for slow-motion videos). + */ + public PlaybackParameters(float speed, float pitch) { Assertions.checkArgument(speed > 0); + Assertions.checkArgument(pitch > 0); this.speed = speed; + this.pitch = pitch; scaledUsPerMs = Math.round(speed * 1000f); } @@ -65,11 +79,19 @@ public boolean equals(@Nullable Object obj) { return false; } PlaybackParameters other = (PlaybackParameters) obj; - return this.speed == other.speed; + return this.speed == other.speed && this.pitch == other.pitch; } @Override public int hashCode() { - return Float.floatToRawIntBits(speed); + int result = 17; + result = 31 * result + Float.floatToRawIntBits(speed); + result = 31 * result + Float.floatToRawIntBits(pitch); + return result; + } + + @Override + public String toString() { + return Util.formatInvariant("PlaybackParameters(speed=%.2f, pitch=%.2f)", speed, pitch); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/Player.java b/library/core/src/main/java/com/google/android/exoplayer2/Player.java index 93443453753..490022de93c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/Player.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/Player.java @@ -583,21 +583,15 @@ default void onPlayerError(ExoPlaybackException error) {} default void onPositionDiscontinuity(@DiscontinuityReason int reason) {} /** - * @deprecated Use {@link #onPlaybackSpeedChanged(float)} and {@link - * AudioListener#onSkipSilenceEnabledChanged(boolean)} instead. + * Called when the current playback parameters change. The playback parameters may change due to + * a call to {@link #setPlaybackParameters(PlaybackParameters)}, or the player itself may change + * them (for example, if audio playback switches to passthrough or offload mode, where speed + * adjustment is no longer possible). + * + * @param playbackParameters The playback parameters. */ - @SuppressWarnings("deprecation") - @Deprecated default void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {} - /** - * Called when the current playback speed changes. The normal playback speed is 1. The speed may - * change due to a call to {@link #setPlaybackSpeed(float)}, or the player itself may change it - * (for example, if audio playback switches to passthrough mode, where speed adjustment is no - * longer possible). - */ - default void onPlaybackSpeedChanged(float playbackSpeed) {} - /** * @deprecated Seeks are processed without delay. Listen to {@link * #onPositionDiscontinuity(int)} with reason {@link #DISCONTINUITY_REASON_SEEK} instead. @@ -810,9 +804,6 @@ public void onTimelineChanged(Timeline timeline, @Nullable Object manifest) { */ int MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED = 3; - /** The default playback speed. */ - float DEFAULT_PLAYBACK_SPEED = 1.0f; - /** Returns the component of this player for audio output, or null if audio is not supported. */ @Nullable AudioComponent getAudioComponent(); @@ -1161,38 +1152,23 @@ public void onTimelineChanged(Timeline timeline, @Nullable Object manifest) { void next(); /** - * @deprecated Use {@link #setPlaybackSpeed(float)} or {@link - * AudioComponent#setSkipSilenceEnabled(boolean)} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - void setPlaybackParameters(@Nullable PlaybackParameters playbackParameters); - - /** - * @deprecated Use {@link #getPlaybackSpeed()} or {@link AudioComponent#getSkipSilenceEnabled()} - * instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - PlaybackParameters getPlaybackParameters(); - - /** - * Attempts to set the playback speed. + * Attempts to set the playback parameters. Passing {@code null} sets the parameters to the + * default, {@link PlaybackParameters#DEFAULT}, which means there is no speed or pitch adjustment. * - *

Playback speed changes may cause the player to buffer. {@link - * EventListener#onPlaybackSpeedChanged(float)} will be called whenever the currently active - * playback speed change. + *

Playback parameters changes may cause the player to buffer. {@link + * EventListener#onPlaybackParametersChanged(PlaybackParameters)} will be called whenever the + * currently active playback parameters change. * - * @param playbackSpeed The playback speed. + * @param playbackParameters The playback parameters, or {@code null} to use the defaults. */ - void setPlaybackSpeed(float playbackSpeed); + void setPlaybackParameters(@Nullable PlaybackParameters playbackParameters); /** - * Returns the currently active playback speed. + * Returns the currently active playback parameters. * - * @see EventListener#onPlaybackSpeedChanged(float) + * @see EventListener#onPlaybackParametersChanged(PlaybackParameters) */ - float getPlaybackSpeed(); + PlaybackParameters getPlaybackParameters(); /** * Stops playback without resetting the player. Use {@link #pause()} rather than this method if diff --git a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java index d927161d168..a43973b31c9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java @@ -1030,18 +1030,23 @@ public void setPriorityTaskManager(@Nullable PriorityTaskManager priorityTaskMan this.priorityTaskManager = priorityTaskManager; } - /** @deprecated Use {@link #setPlaybackSpeed(float)} instead. */ + /** + * Sets the {@link PlaybackParams} governing audio playback. + * + * @param params The {@link PlaybackParams}, or null to clear any previously set parameters. + * @deprecated Use {@link #setPlaybackParameters(PlaybackParameters)}. + */ @Deprecated @RequiresApi(23) public void setPlaybackParams(@Nullable PlaybackParams params) { - float playbackSpeed; + PlaybackParameters playbackParameters; if (params != null) { params.allowDefaults(); - playbackSpeed = params.getSpeed(); + playbackParameters = new PlaybackParameters(params.getSpeed(), params.getPitch()); } else { - playbackSpeed = 1.0f; + playbackParameters = null; } - setPlaybackSpeed(playbackSpeed); + setPlaybackParameters(playbackParameters); } /** Returns the video format currently being played, or null if no video is being played. */ @@ -1623,39 +1628,18 @@ public void seekTo(int windowIndex, long positionMs) { player.seekTo(windowIndex, positionMs); } - /** - * @deprecated Use {@link #setPlaybackSpeed(float)} and {@link #setSkipSilenceEnabled(boolean)} - * instead. - */ - @SuppressWarnings("deprecation") - @Deprecated @Override public void setPlaybackParameters(@Nullable PlaybackParameters playbackParameters) { verifyApplicationThread(); player.setPlaybackParameters(playbackParameters); } - /** @deprecated Use {@link #getPlaybackSpeed()} and {@link #getSkipSilenceEnabled()} instead. */ - @SuppressWarnings("deprecation") - @Deprecated @Override public PlaybackParameters getPlaybackParameters() { verifyApplicationThread(); return player.getPlaybackParameters(); } - @Override - public void setPlaybackSpeed(float playbackSpeed) { - verifyApplicationThread(); - player.setPlaybackSpeed(playbackSpeed); - } - - @Override - public float getPlaybackSpeed() { - verifyApplicationThread(); - return player.getPlaybackSpeed(); - } - @Override public void setSeekParameters(@Nullable SeekParameters seekParameters) { verifyApplicationThread(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java index 0193c94deb6..35f3099dc94 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java @@ -552,12 +552,6 @@ public final void onPositionDiscontinuity(@Player.DiscontinuityReason int reason } } - /** - * @deprecated Use {@link #onPlaybackSpeedChanged(float)} and {@link - * #onSkipSilenceEnabledChanged(boolean)} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated @Override public final void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); @@ -566,14 +560,6 @@ public final void onPlaybackParametersChanged(PlaybackParameters playbackParamet } } - @Override - public void onPlaybackSpeedChanged(float playbackSpeed) { - EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime(); - for (AnalyticsListener listener : listeners) { - listener.onPlaybackSpeedChanged(eventTime, playbackSpeed); - } - } - @SuppressWarnings("deprecation") @Override public final void onSeekProcessed() { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java index d80ef5f70ab..2e26019541e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java @@ -279,21 +279,13 @@ default void onSeekStarted(EventTime eventTime) {} default void onSeekProcessed(EventTime eventTime) {} /** - * @deprecated Use {@link #onPlaybackSpeedChanged(EventTime, float)} and {@link - * #onSkipSilenceEnabledChanged(EventTime, boolean)} instead. - */ - @SuppressWarnings("deprecation") - @Deprecated - default void onPlaybackParametersChanged( - EventTime eventTime, PlaybackParameters playbackParameters) {} - - /** - * Called when the playback speed changes. + * Called when the playback parameters changed. * * @param eventTime The event time. - * @param playbackSpeed The playback speed. + * @param playbackParameters The new playback parameters. */ - default void onPlaybackSpeedChanged(EventTime eventTime, float playbackSpeed) {} + default void onPlaybackParametersChanged( + EventTime eventTime, PlaybackParameters playbackParameters) {} /** * Called when the repeat mode changed. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java b/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java index 1efb072ef0a..ab137f98e19 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java @@ -22,6 +22,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline.Period; @@ -334,8 +335,9 @@ public void onPlayerError(EventTime eventTime, ExoPlaybackException error) { } @Override - public void onPlaybackSpeedChanged(EventTime eventTime, float playbackSpeed) { - this.playbackSpeed = playbackSpeed; + public void onPlaybackParametersChanged( + EventTime eventTime, PlaybackParameters playbackParameters) { + playbackSpeed = playbackParameters.speed; maybeAddSession(eventTime); for (PlaybackStatsTracker tracker : playbackStatsTrackers.values()) { tracker.onPlaybackSpeedChanged(eventTime, playbackSpeed); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java index 21683bda480..b7d375fd9dc 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java @@ -20,6 +20,7 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackParameters; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -306,16 +307,21 @@ boolean handleBuffer(ByteBuffer buffer, long presentationTimeUs, int encodedAcce */ boolean hasPendingData(); - /** Sets the playback speed. */ - void setPlaybackSpeed(float playbackSpeed); + /** + * Attempts to set the playback parameters. The audio sink may override these parameters if they + * are not supported. + * + * @param playbackParameters The new playback parameters to attempt to set. + */ + void setPlaybackParameters(PlaybackParameters playbackParameters); - /** Gets the playback speed. */ - float getPlaybackSpeed(); + /** Returns the active {@link PlaybackParameters}. */ + PlaybackParameters getPlaybackParameters(); /** Sets whether silences should be skipped in the audio stream. */ void setSkipSilenceEnabled(boolean skipSilenceEnabled); - /** Gets whether silences are skipped in the audio stream. */ + /** Returns whether silences are skipped in the audio stream. */ boolean getSkipSilenceEnabled(); /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java index 84a4e36d074..1c1e593e223 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java @@ -29,6 +29,7 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher; @@ -498,13 +499,13 @@ public long getPositionUs() { } @Override - public void setPlaybackSpeed(float playbackSpeed) { - audioSink.setPlaybackSpeed(playbackSpeed); + public void setPlaybackParameters(PlaybackParameters playbackParameters) { + audioSink.setPlaybackParameters(playbackParameters); } @Override - public float getPlaybackSpeed() { - return audioSink.getPlaybackSpeed(); + public PlaybackParameters getPlaybackParameters() { + return audioSink.getPlaybackParameters(); } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java index 7075fce5d08..1e04b1e8d7b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java @@ -32,6 +32,7 @@ import androidx.annotation.RequiresApi; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.audio.AudioProcessor.UnhandledAudioFormatException; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Log; @@ -92,14 +93,14 @@ public interface AudioProcessorChain { AudioProcessor[] getAudioProcessors(); /** - * Configures audio processors to apply the specified playback speed immediately, returning the - * new playback speed, which may differ from the speed passed in. Only called when processors - * have no input pending. + * Configures audio processors to apply the specified playback parameters immediately, returning + * the new playback parameters, which may differ from those passed in. Only called when + * processors have no input pending. * - * @param playbackSpeed The playback speed to try to apply. - * @return The playback speed that was actually applied. + * @param playbackParameters The playback parameters to try to apply. + * @return The playback parameters that were actually applied. */ - float applyPlaybackSpeed(float playbackSpeed); + PlaybackParameters applyPlaybackParameters(PlaybackParameters playbackParameters); /** * Configures audio processors to apply whether to skip silences immediately, returning the new @@ -170,8 +171,10 @@ public AudioProcessor[] getAudioProcessors() { } @Override - public float applyPlaybackSpeed(float playbackSpeed) { - return sonicAudioProcessor.setSpeed(playbackSpeed); + public PlaybackParameters applyPlaybackParameters(PlaybackParameters playbackParameters) { + float speed = sonicAudioProcessor.setSpeed(playbackParameters.speed); + float pitch = sonicAudioProcessor.setPitch(playbackParameters.pitch); + return new PlaybackParameters(speed, pitch); } @Override @@ -197,6 +200,10 @@ public long getSkippedOutputFrameCount() { public static final float MIN_PLAYBACK_SPEED = 0.1f; /** The maximum allowed playback speed. Higher values will be constrained to fall in range. */ public static final float MAX_PLAYBACK_SPEED = 8f; + /** The minimum allowed pitch factor. Lower values will be constrained to fall in range. */ + public static final float MIN_PITCH = 0.1f; + /** The maximum allowed pitch factor. Higher values will be constrained to fall in range. */ + public static final float MAX_PITCH = 8f; /** The default skip silence flag. */ private static final boolean DEFAULT_SKIP_SILENCE = false; @@ -296,7 +303,7 @@ public long getSkippedOutputFrameCount() { private AudioAttributes audioAttributes; @Nullable private MediaPositionParameters afterDrainParameters; private MediaPositionParameters mediaPositionParameters; - private float audioTrackPlaybackSpeed; + private PlaybackParameters audioTrackPlaybackParameters; @Nullable private ByteBuffer avSyncHeader; private int bytesUntilNextAvSync; @@ -418,11 +425,11 @@ public DefaultAudioSink( auxEffectInfo = new AuxEffectInfo(AuxEffectInfo.NO_AUX_EFFECT_ID, 0f); mediaPositionParameters = new MediaPositionParameters( - DEFAULT_PLAYBACK_SPEED, + PlaybackParameters.DEFAULT, DEFAULT_SKIP_SILENCE, /* mediaTimeUs= */ 0, /* audioTrackPositionUs= */ 0); - audioTrackPlaybackSpeed = 1f; + audioTrackPlaybackParameters = PlaybackParameters.DEFAULT; drainingAudioProcessorIndex = C.INDEX_UNSET; activeAudioProcessors = new AudioProcessor[0]; outputBuffers = new ByteBuffer[0]; @@ -707,7 +714,7 @@ public boolean handleBuffer( } } // Re-apply playback parameters. - applyAudioProcessorPlaybackSpeedAndSkipSilence(presentationTimeUs); + applyAudioProcessorPlaybackParametersAndSkipSilence(presentationTimeUs); } if (!isAudioTrackInitialized()) { @@ -720,9 +727,9 @@ public boolean handleBuffer( startMediaTimeUsNeedsInit = false; if (enableAudioTrackPlaybackParams && Util.SDK_INT >= 23) { - setAudioTrackPlaybackSpeedV23(audioTrackPlaybackSpeed); + setAudioTrackPlaybackParametersV23(audioTrackPlaybackParameters); } - applyAudioProcessorPlaybackSpeedAndSkipSilence(presentationTimeUs); + applyAudioProcessorPlaybackParametersAndSkipSilence(presentationTimeUs); if (playing) { play(); @@ -758,7 +765,7 @@ public boolean handleBuffer( // Don't process any more input until draining completes. return false; } - applyAudioProcessorPlaybackSpeedAndSkipSilence(presentationTimeUs); + applyAudioProcessorPlaybackParametersAndSkipSilence(presentationTimeUs); afterDrainParameters = null; } @@ -789,7 +796,7 @@ public boolean handleBuffer( startMediaTimeUs += adjustmentUs; startMediaTimeUsNeedsSync = false; // Re-apply playback parameters because the startMediaTimeUs changed. - applyAudioProcessorPlaybackSpeedAndSkipSilence(presentationTimeUs); + applyAudioProcessorPlaybackParametersAndSkipSilence(presentationTimeUs); if (listener != null && adjustmentUs != 0) { listener.onPositionDiscontinuity(); } @@ -1011,26 +1018,30 @@ public boolean hasPendingData() { } @Override - public void setPlaybackSpeed(float playbackSpeed) { - playbackSpeed = Util.constrainValue(playbackSpeed, MIN_PLAYBACK_SPEED, MAX_PLAYBACK_SPEED); + public void setPlaybackParameters(PlaybackParameters playbackParameters) { + playbackParameters = + new PlaybackParameters( + Util.constrainValue(playbackParameters.speed, MIN_PLAYBACK_SPEED, MAX_PLAYBACK_SPEED), + Util.constrainValue(playbackParameters.pitch, MIN_PITCH, MAX_PITCH)); if (enableAudioTrackPlaybackParams && Util.SDK_INT >= 23) { - setAudioTrackPlaybackSpeedV23(playbackSpeed); + setAudioTrackPlaybackParametersV23(playbackParameters); } else { - setAudioProcessorPlaybackSpeedAndSkipSilence(playbackSpeed, getSkipSilenceEnabled()); + setAudioProcessorPlaybackParametersAndSkipSilence( + playbackParameters, getSkipSilenceEnabled()); } } @Override - public float getPlaybackSpeed() { - // We use either audio processor speed adjustment or AudioTrack playback parameters, so one of - // the operands is always 1f. - return getAudioProcessorPlaybackSpeed() * audioTrackPlaybackSpeed; + public PlaybackParameters getPlaybackParameters() { + return enableAudioTrackPlaybackParams + ? audioTrackPlaybackParameters + : getAudioProcessorPlaybackParameters(); } @Override public void setSkipSilenceEnabled(boolean skipSilenceEnabled) { - setAudioProcessorPlaybackSpeedAndSkipSilence( - getAudioProcessorPlaybackSpeed(), skipSilenceEnabled); + setAudioProcessorPlaybackParametersAndSkipSilence( + getAudioProcessorPlaybackParameters(), skipSilenceEnabled); } @Override @@ -1212,7 +1223,7 @@ private void resetSinkStateForFlush() { framesPerEncodedSample = 0; mediaPositionParameters = new MediaPositionParameters( - getAudioProcessorPlaybackSpeed(), + getAudioProcessorPlaybackParameters(), getSkipSilenceEnabled(), /* mediaTimeUs= */ 0, /* audioTrackPositionUs= */ 0); @@ -1249,12 +1260,13 @@ public void run() { } @RequiresApi(23) - private void setAudioTrackPlaybackSpeedV23(float audioTrackPlaybackSpeed) { + private void setAudioTrackPlaybackParametersV23(PlaybackParameters audioTrackPlaybackParameters) { if (isAudioTrackInitialized()) { PlaybackParams playbackParams = new PlaybackParams() .allowDefaults() - .setSpeed(audioTrackPlaybackSpeed) + .setSpeed(audioTrackPlaybackParameters.speed) + .setPitch(audioTrackPlaybackParameters.pitch) .setAudioFallbackMode(PlaybackParams.AUDIO_FALLBACK_MODE_FAIL); try { audioTrack.setPlaybackParams(playbackParams); @@ -1262,20 +1274,22 @@ private void setAudioTrackPlaybackSpeedV23(float audioTrackPlaybackSpeed) { Log.w(TAG, "Failed to set playback params", e); } // Update the speed using the actual effective speed from the audio track. - audioTrackPlaybackSpeed = audioTrack.getPlaybackParams().getSpeed(); - audioTrackPositionTracker.setAudioTrackPlaybackSpeed(audioTrackPlaybackSpeed); + audioTrackPlaybackParameters = + new PlaybackParameters( + audioTrack.getPlaybackParams().getSpeed(), audioTrack.getPlaybackParams().getPitch()); + audioTrackPositionTracker.setAudioTrackPlaybackSpeed(audioTrackPlaybackParameters.speed); } - this.audioTrackPlaybackSpeed = audioTrackPlaybackSpeed; + this.audioTrackPlaybackParameters = audioTrackPlaybackParameters; } - private void setAudioProcessorPlaybackSpeedAndSkipSilence( - float playbackSpeed, boolean skipSilence) { + private void setAudioProcessorPlaybackParametersAndSkipSilence( + PlaybackParameters playbackParameters, boolean skipSilence) { MediaPositionParameters currentMediaPositionParameters = getMediaPositionParameters(); - if (playbackSpeed != currentMediaPositionParameters.playbackSpeed + if (!playbackParameters.equals(currentMediaPositionParameters.playbackParameters) || skipSilence != currentMediaPositionParameters.skipSilence) { MediaPositionParameters mediaPositionParameters = new MediaPositionParameters( - playbackSpeed, + playbackParameters, skipSilence, /* mediaTimeUs= */ C.TIME_UNSET, /* audioTrackPositionUs= */ C.TIME_UNSET); @@ -1291,8 +1305,8 @@ private void setAudioProcessorPlaybackSpeedAndSkipSilence( } } - private float getAudioProcessorPlaybackSpeed() { - return getMediaPositionParameters().playbackSpeed; + private PlaybackParameters getAudioProcessorPlaybackParameters() { + return getMediaPositionParameters().playbackParameters; } private MediaPositionParameters getMediaPositionParameters() { @@ -1304,18 +1318,18 @@ private MediaPositionParameters getMediaPositionParameters() { : mediaPositionParameters; } - private void applyAudioProcessorPlaybackSpeedAndSkipSilence(long presentationTimeUs) { - float playbackSpeed = + private void applyAudioProcessorPlaybackParametersAndSkipSilence(long presentationTimeUs) { + PlaybackParameters playbackParameters = configuration.canApplyPlaybackParameters - ? audioProcessorChain.applyPlaybackSpeed(getAudioProcessorPlaybackSpeed()) - : DEFAULT_PLAYBACK_SPEED; + ? audioProcessorChain.applyPlaybackParameters(getAudioProcessorPlaybackParameters()) + : PlaybackParameters.DEFAULT; boolean skipSilenceEnabled = configuration.canApplyPlaybackParameters ? audioProcessorChain.applySkipSilenceEnabled(getSkipSilenceEnabled()) : DEFAULT_SKIP_SILENCE; mediaPositionParametersCheckpoints.add( new MediaPositionParameters( - playbackSpeed, + playbackParameters, skipSilenceEnabled, /* mediaTimeUs= */ max(0, presentationTimeUs), /* audioTrackPositionUs= */ configuration.framesToDurationUs(getWrittenFrames()))); @@ -1340,7 +1354,7 @@ private long applyMediaPositionParameters(long positionUs) { long playoutDurationSinceLastCheckpoint = positionUs - mediaPositionParameters.audioTrackPositionUs; - if (mediaPositionParameters.playbackSpeed != 1f) { + if (!mediaPositionParameters.playbackParameters.equals(PlaybackParameters.DEFAULT)) { if (mediaPositionParametersCheckpoints.isEmpty()) { playoutDurationSinceLastCheckpoint = audioProcessorChain.getMediaDuration(playoutDurationSinceLastCheckpoint); @@ -1348,7 +1362,8 @@ private long applyMediaPositionParameters(long positionUs) { // Playing data at a previous playback speed, so fall back to multiplying by the speed. playoutDurationSinceLastCheckpoint = Util.getMediaDurationForPlayoutDuration( - playoutDurationSinceLastCheckpoint, mediaPositionParameters.playbackSpeed); + playoutDurationSinceLastCheckpoint, + mediaPositionParameters.playbackParameters.speed); } } return mediaPositionParameters.mediaTimeUs + playoutDurationSinceLastCheckpoint; @@ -1692,8 +1707,8 @@ public void unregister(AudioTrack audioTrack) { /** Stores parameters used to calculate the current media position. */ private static final class MediaPositionParameters { - /** The playback speed. */ - public final float playbackSpeed; + /** The playback parameters. */ + public final PlaybackParameters playbackParameters; /** Whether to skip silences. */ public final boolean skipSilence; /** The media time from which the playback parameters apply, in microseconds. */ @@ -1702,8 +1717,11 @@ private static final class MediaPositionParameters { public final long audioTrackPositionUs; private MediaPositionParameters( - float playbackSpeed, boolean skipSilence, long mediaTimeUs, long audioTrackPositionUs) { - this.playbackSpeed = playbackSpeed; + PlaybackParameters playbackParameters, + boolean skipSilence, + long mediaTimeUs, + long audioTrackPositionUs) { + this.playbackParameters = playbackParameters; this.skipSilence = skipSilence; this.mediaTimeUs = mediaTimeUs; this.audioTrackPositionUs = audioTrackPositionUs; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/ForwardingAudioSink.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/ForwardingAudioSink.java index 3f755a71300..7460d124576 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/ForwardingAudioSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/ForwardingAudioSink.java @@ -17,6 +17,7 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackParameters; import java.nio.ByteBuffer; /** An overridable {@link AudioSink} implementation forwarding all methods to another sink. */ @@ -88,13 +89,13 @@ public boolean hasPendingData() { } @Override - public void setPlaybackSpeed(float playbackSpeed) { - sink.setPlaybackSpeed(playbackSpeed); + public void setPlaybackParameters(PlaybackParameters playbackParameters) { + sink.setPlaybackParameters(playbackParameters); } @Override - public float getPlaybackSpeed() { - return sink.getPlaybackSpeed(); + public PlaybackParameters getPlaybackParameters() { + return sink.getPlaybackParameters(); } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java index dfcc41d670c..2d034335c8d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java @@ -33,6 +33,7 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher; @@ -545,13 +546,13 @@ public long getPositionUs() { } @Override - public void setPlaybackSpeed(float playbackSpeed) { - audioSink.setPlaybackSpeed(playbackSpeed); + public void setPlaybackParameters(PlaybackParameters playbackParameters) { + audioSink.setPlaybackParameters(playbackParameters); } @Override - public float getPlaybackSpeed() { - return audioSink.getPlaybackSpeed(); + public PlaybackParameters getPlaybackParameters() { + return audioSink.getPlaybackParameters(); } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java index a2cdaa8b742..ae65eacd130 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java @@ -37,6 +37,7 @@ private final int inputSampleRateHz; private final int channelCount; private final float speed; + private final float pitch; private final float rate; private final int minPeriod; private final int maxPeriod; @@ -63,12 +64,15 @@ * @param inputSampleRateHz The sample rate of input audio, in hertz. * @param channelCount The number of channels in the input audio. * @param speed The speedup factor for output audio. + * @param pitch The pitch factor for output audio. * @param outputSampleRateHz The sample rate for output audio, in hertz. */ - public Sonic(int inputSampleRateHz, int channelCount, float speed, int outputSampleRateHz) { + public Sonic( + int inputSampleRateHz, int channelCount, float speed, float pitch, int outputSampleRateHz) { this.inputSampleRateHz = inputSampleRateHz; this.channelCount = channelCount; this.speed = speed; + this.pitch = pitch; rate = (float) inputSampleRateHz / outputSampleRateHz; minPeriod = inputSampleRateHz / MAXIMUM_PITCH; maxPeriod = inputSampleRateHz / MINIMUM_PITCH; @@ -118,8 +122,10 @@ public void getOutput(ShortBuffer buffer) { */ public void queueEndOfStream() { int remainingFrameCount = inputFrameCount; + float s = speed / pitch; + float r = rate * pitch; int expectedOutputFrames = - outputFrameCount + (int) ((remainingFrameCount / speed + pitchFrameCount) / rate + 0.5f); + outputFrameCount + (int) ((remainingFrameCount / s + pitchFrameCount) / r + 0.5f); // Add enough silence to flush both input and pitch buffers. inputBuffer = @@ -464,14 +470,16 @@ private void changeSpeed(float speed) { private void processStreamInput() { // Resample as many pitch periods as we have buffered on the input. int originalOutputFrameCount = outputFrameCount; - if (speed > 1.00001 || speed < 0.99999) { - changeSpeed(speed); + float s = speed / pitch; + float r = rate * pitch; + if (s > 1.00001 || s < 0.99999) { + changeSpeed(s); } else { copyToOutput(inputBuffer, 0, inputFrameCount); inputFrameCount = 0; } - if (rate != 1.0f) { - adjustRate(rate, originalOutputFrameCount); + if (r != 1.0f) { + adjustRate(r, originalOutputFrameCount); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java index d582461c810..5c3c1db0c74 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java @@ -43,6 +43,7 @@ public final class SonicAudioProcessor implements AudioProcessor { private int pendingOutputSampleRate; private float speed; + private float pitch; private AudioFormat pendingInputAudioFormat; private AudioFormat pendingOutputAudioFormat; @@ -61,6 +62,7 @@ public final class SonicAudioProcessor implements AudioProcessor { /** Creates a new Sonic audio processor. */ public SonicAudioProcessor() { speed = 1f; + pitch = 1f; pendingInputAudioFormat = AudioFormat.NOT_SET; pendingOutputAudioFormat = AudioFormat.NOT_SET; inputAudioFormat = AudioFormat.NOT_SET; @@ -87,6 +89,22 @@ public float setSpeed(float speed) { return speed; } + /** + * Sets the playback pitch. This method may only be called after draining data through the + * processor. The value returned by {@link #isActive()} may change, and the processor must be + * {@link #flush() flushed} before queueing more data. + * + * @param pitch The requested new pitch. + * @return The actual new pitch. + */ + public float setPitch(float pitch) { + if (this.pitch != pitch) { + this.pitch = pitch; + pendingSonicRecreation = true; + } + return pitch; + } + /** * Sets the sample rate for output audio, in Hertz. Pass {@link #SAMPLE_RATE_NO_CHANGE} to output * audio at the same sample rate as the input. After calling this method, call {@link @@ -140,6 +158,7 @@ public AudioFormat configure(AudioFormat inputAudioFormat) throws UnhandledAudio public boolean isActive() { return pendingOutputAudioFormat.sampleRate != Format.NO_VALUE && (Math.abs(speed - 1f) >= CLOSE_THRESHOLD + || Math.abs(pitch - 1f) >= CLOSE_THRESHOLD || pendingOutputAudioFormat.sampleRate != pendingInputAudioFormat.sampleRate); } @@ -200,6 +219,7 @@ public void flush() { inputAudioFormat.sampleRate, inputAudioFormat.channelCount, speed, + pitch, outputAudioFormat.sampleRate); } else if (sonic != null) { sonic.flush(); @@ -214,6 +234,7 @@ public void flush() { @Override public void reset() { speed = 1f; + pitch = 1f; pendingInputAudioFormat = AudioFormat.NOT_SET; pendingOutputAudioFormat = AudioFormat.NOT_SET; inputAudioFormat = AudioFormat.NOT_SET; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java b/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java index 4d1ebe0111c..aa82d41414f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java @@ -25,6 +25,7 @@ import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.MediaItem; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player.PlaybackSuppressionReason; import com.google.android.exoplayer2.RendererCapabilities; @@ -147,8 +148,9 @@ public void onSeekStarted(EventTime eventTime) { } @Override - public void onPlaybackSpeedChanged(EventTime eventTime, float playbackSpeed) { - logd(eventTime, "playbackSpeed", Float.toString(playbackSpeed)); + public void onPlaybackParametersChanged( + EventTime eventTime, PlaybackParameters playbackParameters) { + logd(eventTime, "playbackParameters", playbackParameters.toString()); } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/MediaClock.java b/library/core/src/main/java/com/google/android/exoplayer2/util/MediaClock.java index 44c3c5e7fae..df335908c09 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/MediaClock.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/MediaClock.java @@ -15,6 +15,8 @@ */ package com.google.android.exoplayer2.util; +import com.google.android.exoplayer2.PlaybackParameters; + /** * Tracks the progression of media time. */ @@ -26,13 +28,13 @@ public interface MediaClock { long getPositionUs(); /** - * Attempts to set the playback speed. The media clock may override the speed if changing the - * speed is not supported. + * Attempts to set the playback parameters. The media clock may override the speed if changing the + * playback parameters is not supported. * - * @param playbackSpeed The playback speed to attempt to set. + * @param playbackParameters The playback parameters to attempt to set. */ - void setPlaybackSpeed(float playbackSpeed); + void setPlaybackParameters(PlaybackParameters playbackParameters); - /** Returns the active playback speed. */ - float getPlaybackSpeed(); + /** Returns the active playback parameters. */ + PlaybackParameters getPlaybackParameters(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/StandaloneMediaClock.java b/library/core/src/main/java/com/google/android/exoplayer2/util/StandaloneMediaClock.java index e1df77a2002..87970d3c003 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/StandaloneMediaClock.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/StandaloneMediaClock.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.util; import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.PlaybackParameters; /** * A {@link MediaClock} whose position advances with real time based on the playback parameters when @@ -29,8 +29,7 @@ public final class StandaloneMediaClock implements MediaClock { private boolean started; private long baseUs; private long baseElapsedMs; - private float playbackSpeed; - private int scaledUsPerMs; + private PlaybackParameters playbackParameters; /** * Creates a new standalone media clock using the given {@link Clock} implementation. @@ -39,8 +38,7 @@ public final class StandaloneMediaClock implements MediaClock { */ public StandaloneMediaClock(Clock clock) { this.clock = clock; - playbackSpeed = Player.DEFAULT_PLAYBACK_SPEED; - scaledUsPerMs = getScaledUsPerMs(playbackSpeed); + playbackParameters = PlaybackParameters.DEFAULT; } /** @@ -80,33 +78,29 @@ public long getPositionUs() { long positionUs = baseUs; if (started) { long elapsedSinceBaseMs = clock.elapsedRealtime() - baseElapsedMs; - if (playbackSpeed == 1f) { + if (playbackParameters.speed == 1f) { positionUs += C.msToUs(elapsedSinceBaseMs); } else { // Add the media time in microseconds that will elapse in elapsedSinceBaseMs milliseconds of // wallclock time - positionUs += elapsedSinceBaseMs * scaledUsPerMs; + positionUs += playbackParameters.getMediaTimeUsForPlayoutTimeMs(elapsedSinceBaseMs); } } return positionUs; } @Override - public void setPlaybackSpeed(float playbackSpeed) { + public void setPlaybackParameters(PlaybackParameters playbackParameters) { // Store the current position as the new base, in case the playback speed has changed. if (started) { resetPosition(getPositionUs()); } - this.playbackSpeed = playbackSpeed; - scaledUsPerMs = getScaledUsPerMs(playbackSpeed); + this.playbackParameters = playbackParameters; } @Override - public float getPlaybackSpeed() { - return playbackSpeed; + public PlaybackParameters getPlaybackParameters() { + return playbackParameters; } - private static int getScaledUsPerMs(float playbackSpeed) { - return Math.round(playbackSpeed * 1000f); - } } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/DefaultMediaClockTest.java b/library/core/src/test/java/com/google/android/exoplayer2/DefaultMediaClockTest.java index 217df762f64..867857cbe5d 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/DefaultMediaClockTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/DefaultMediaClockTest.java @@ -22,7 +22,7 @@ import static org.mockito.MockitoAnnotations.initMocks; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.google.android.exoplayer2.DefaultMediaClock.PlaybackSpeedListener; +import com.google.android.exoplayer2.DefaultMediaClock.PlaybackParametersListener; import com.google.android.exoplayer2.testutil.FakeClock; import com.google.android.exoplayer2.testutil.FakeMediaClockRenderer; import org.junit.Before; @@ -36,9 +36,10 @@ public class DefaultMediaClockTest { private static final long TEST_POSITION_US = 123456789012345678L; private static final long SLEEP_TIME_MS = 1_000; - private static final float TEST_PLAYBACK_SPEED = 2f; + private static final PlaybackParameters TEST_PLAYBACK_PARAMETERS = + new PlaybackParameters(/* speed= */ 2f); - @Mock private PlaybackSpeedListener listener; + @Mock private PlaybackParametersListener listener; private FakeClock fakeClock; private DefaultMediaClock mediaClock; @@ -109,44 +110,44 @@ public void standaloneStartAndStop_shouldNotTriggerCallback() throws Exception { } @Test - public void standaloneGetPlaybackSpeed_initializedWithDefaultPlaybackSpeed() { - assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(Player.DEFAULT_PLAYBACK_SPEED); + public void standaloneGetPlaybackParameters_initializedWithDefaultPlaybackParameters() { + assertThat(mediaClock.getPlaybackParameters()).isEqualTo(PlaybackParameters.DEFAULT); } @Test - public void standaloneSetPlaybackSpeed_getPlaybackSpeedShouldReturnSameValue() { - mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED); - assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(TEST_PLAYBACK_SPEED); + public void standaloneSetPlaybackParameters_getPlaybackParametersShouldReturnSameValue() { + mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); + assertThat(mediaClock.getPlaybackParameters()).isEqualTo(TEST_PLAYBACK_PARAMETERS); } @Test - public void standaloneSetPlaybackSpeed_shouldNotTriggerCallback() { - mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED); + public void standaloneSetPlaybackParameters_shouldNotTriggerCallback() { + mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); verifyNoMoreInteractions(listener); } @Test - public void standaloneSetPlaybackSpeed_shouldApplyNewPlaybackSpeed() { - mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED); + public void standaloneSetPlaybackParameters_shouldApplyNewPlaybackParameters() { + mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); mediaClock.start(); - // Asserts that clock is running with speed declared in getPlaybackSpeed(). + // Asserts that clock is running with speed declared in getPlaybackParameters(). assertClockIsRunning(/* isReadingAhead= */ false); } @Test - public void standaloneSetOtherPlaybackSpeed_getPlaybackSpeedShouldReturnSameValue() { - mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED); - mediaClock.setPlaybackSpeed(Player.DEFAULT_PLAYBACK_SPEED); - assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(Player.DEFAULT_PLAYBACK_SPEED); + public void standaloneSetOtherPlaybackParameters_getPlaybackParametersShouldReturnSameValue() { + mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); + mediaClock.setPlaybackParameters(PlaybackParameters.DEFAULT); + assertThat(mediaClock.getPlaybackParameters()).isEqualTo(PlaybackParameters.DEFAULT); } @Test - public void enableRendererMediaClock_shouldOverwriteRendererPlaybackSpeedIfPossible() + public void enableRendererMediaClock_shouldOverwriteRendererPlaybackParametersIfPossible() throws ExoPlaybackException { FakeMediaClockRenderer mediaClockRenderer = - new MediaClockRenderer(TEST_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ true); + new MediaClockRenderer(TEST_PLAYBACK_PARAMETERS, /* playbackParametersAreMutable= */ true); mediaClock.onRendererEnabled(mediaClockRenderer); - assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(Player.DEFAULT_PLAYBACK_SPEED); + assertThat(mediaClock.getPlaybackParameters()).isEqualTo(PlaybackParameters.DEFAULT); verifyNoMoreInteractions(listener); } @@ -154,26 +155,27 @@ public void enableRendererMediaClock_shouldOverwriteRendererPlaybackSpeedIfPossi public void enableRendererMediaClockWithFixedPlaybackSpeed_usesRendererPlaybackSpeed() throws ExoPlaybackException { FakeMediaClockRenderer mediaClockRenderer = - new MediaClockRenderer(TEST_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ false); + new MediaClockRenderer(TEST_PLAYBACK_PARAMETERS, /* playbackParametersAreMutable= */ false); mediaClock.onRendererEnabled(mediaClockRenderer); - assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(TEST_PLAYBACK_SPEED); + assertThat(mediaClock.getPlaybackParameters()).isEqualTo(TEST_PLAYBACK_PARAMETERS); } @Test public void enableRendererMediaClockWithFixedPlaybackSpeed_shouldTriggerCallback() throws ExoPlaybackException { FakeMediaClockRenderer mediaClockRenderer = - new MediaClockRenderer(TEST_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ false); + new MediaClockRenderer(TEST_PLAYBACK_PARAMETERS, /* playbackParametersAreMutable= */ false); mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); - verify(listener).onPlaybackSpeedChanged(TEST_PLAYBACK_SPEED); + verify(listener).onPlaybackParametersChanged(TEST_PLAYBACK_PARAMETERS); } @Test public void enableRendererMediaClockWithFixedButSamePlaybackSpeed_shouldNotTriggerCallback() throws ExoPlaybackException { FakeMediaClockRenderer mediaClockRenderer = - new MediaClockRenderer(Player.DEFAULT_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ false); + new MediaClockRenderer( + PlaybackParameters.DEFAULT, /* playbackParametersAreMutable= */ false); mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); verifyNoMoreInteractions(listener); @@ -182,44 +184,47 @@ public void enableRendererMediaClockWithFixedButSamePlaybackSpeed_shouldNotTrigg @Test public void disableRendererMediaClock_shouldKeepPlaybackSpeed() throws ExoPlaybackException { FakeMediaClockRenderer mediaClockRenderer = - new MediaClockRenderer(TEST_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ false); + new MediaClockRenderer(TEST_PLAYBACK_PARAMETERS, /* playbackParametersAreMutable= */ false); mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); mediaClock.onRendererDisabled(mediaClockRenderer); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); - assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(TEST_PLAYBACK_SPEED); + assertThat(mediaClock.getPlaybackParameters()).isEqualTo(TEST_PLAYBACK_PARAMETERS); } @Test - public void rendererClockSetPlaybackSpeed_getPlaybackSpeedShouldReturnSameValue() + public void rendererClockSetPlaybackSpeed_getPlaybackParametersShouldReturnSameValue() throws ExoPlaybackException { FakeMediaClockRenderer mediaClockRenderer = - new MediaClockRenderer(Player.DEFAULT_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ true); + new MediaClockRenderer( + PlaybackParameters.DEFAULT, /* playbackParametersAreMutable= */ true); mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); - mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED); - assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(TEST_PLAYBACK_SPEED); + mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); + assertThat(mediaClock.getPlaybackParameters()).isEqualTo(TEST_PLAYBACK_PARAMETERS); } @Test public void rendererClockSetPlaybackSpeed_shouldNotTriggerCallback() throws ExoPlaybackException { FakeMediaClockRenderer mediaClockRenderer = - new MediaClockRenderer(Player.DEFAULT_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ true); + new MediaClockRenderer( + PlaybackParameters.DEFAULT, /* playbackParametersAreMutable= */ true); mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); - mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED); + mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); verifyNoMoreInteractions(listener); } @Test - public void rendererClockSetPlaybackSpeedOverwrite_getPlaybackSpeedShouldReturnSameValue() + public void rendererClockSetPlaybackSpeedOverwrite_getPlaybackParametersShouldReturnSameValue() throws ExoPlaybackException { FakeMediaClockRenderer mediaClockRenderer = - new MediaClockRenderer(Player.DEFAULT_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ false); + new MediaClockRenderer( + PlaybackParameters.DEFAULT, /* playbackParametersAreMutable= */ false); mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); - mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED); - assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(Player.DEFAULT_PLAYBACK_SPEED); + mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); + assertThat(mediaClock.getPlaybackParameters()).isEqualTo(PlaybackParameters.DEFAULT); } @Test @@ -266,12 +271,13 @@ public void disableRendererMediaClock_standaloneShouldBeSynced() throws ExoPlayb public void getPositionWithPlaybackSpeedChange_shouldTriggerCallback() throws ExoPlaybackException { MediaClockRenderer mediaClockRenderer = - new MediaClockRenderer(Player.DEFAULT_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ true); + new MediaClockRenderer( + PlaybackParameters.DEFAULT, /* playbackParametersAreMutable= */ true); mediaClock.onRendererEnabled(mediaClockRenderer); // Silently change playback speed of renderer clock. - mediaClockRenderer.playbackSpeed = TEST_PLAYBACK_SPEED; + mediaClockRenderer.playbackParameters = TEST_PLAYBACK_PARAMETERS; mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); - verify(listener).onPlaybackSpeedChanged(TEST_PLAYBACK_SPEED); + verify(listener).onPlaybackParametersChanged(TEST_PLAYBACK_PARAMETERS); } @Test @@ -356,7 +362,7 @@ public void enableOtherRendererClock_shouldThrow() private void assertClockIsRunning(boolean isReadingAhead) { long clockStartUs = mediaClock.syncAndGetPositionUs(isReadingAhead); fakeClock.advanceTime(SLEEP_TIME_MS); - int scaledUsPerMs = Math.round(mediaClock.getPlaybackSpeed() * 1000f); + int scaledUsPerMs = Math.round(mediaClock.getPlaybackParameters().speed * 1000f); assertThat(mediaClock.syncAndGetPositionUs(isReadingAhead)) .isEqualTo(clockStartUs + (SLEEP_TIME_MS * scaledUsPerMs)); } @@ -371,37 +377,53 @@ private void assertClockIsStopped() { @SuppressWarnings("HidingField") private static class MediaClockRenderer extends FakeMediaClockRenderer { - private final boolean playbackSpeedIsMutable; + private final boolean playbackParametersAreMutable; private final boolean isReady; private final boolean isEnded; - public float playbackSpeed; + public PlaybackParameters playbackParameters; public long positionUs; public MediaClockRenderer() throws ExoPlaybackException { - this(Player.DEFAULT_PLAYBACK_SPEED, false, true, false, false); + this( + PlaybackParameters.DEFAULT, + /* playbackParametersAreMutable= */ false, + /* isReady= */ true, + /* isEnded= */ false, + /* hasReadStreamToEnd= */ false); } - public MediaClockRenderer(float playbackSpeed, boolean playbackSpeedIsMutable) + public MediaClockRenderer( + PlaybackParameters playbackParameters, boolean playbackParametersAreMutable) throws ExoPlaybackException { - this(playbackSpeed, playbackSpeedIsMutable, true, false, false); + this( + playbackParameters, + playbackParametersAreMutable, + /* isReady= */ true, + /* isEnded= */ false, + /* hasReadStreamToEnd= */ false); } public MediaClockRenderer(boolean isReady, boolean isEnded, boolean hasReadStreamToEnd) throws ExoPlaybackException { - this(Player.DEFAULT_PLAYBACK_SPEED, false, isReady, isEnded, hasReadStreamToEnd); + this( + PlaybackParameters.DEFAULT, + /* playbackParametersAreMutable= */ false, + isReady, + isEnded, + hasReadStreamToEnd); } private MediaClockRenderer( - float playbackSpeed, - boolean playbackSpeedIsMutable, + PlaybackParameters playbackParameters, + boolean playbackParametersAreMutable, boolean isReady, boolean isEnded, boolean hasReadStreamToEnd) throws ExoPlaybackException { super(C.TRACK_TYPE_UNKNOWN); - this.playbackSpeed = playbackSpeed; - this.playbackSpeedIsMutable = playbackSpeedIsMutable; + this.playbackParameters = playbackParameters; + this.playbackParametersAreMutable = playbackParametersAreMutable; this.isReady = isReady; this.isEnded = isEnded; this.positionUs = TEST_POSITION_US; @@ -416,15 +438,15 @@ public long getPositionUs() { } @Override - public void setPlaybackSpeed(float playbackSpeed) { - if (playbackSpeedIsMutable) { - this.playbackSpeed = playbackSpeed; + public void setPlaybackParameters(PlaybackParameters playbackParameters) { + if (playbackParametersAreMutable) { + this.playbackParameters = playbackParameters; } } @Override - public float getPlaybackSpeed() { - return playbackSpeed; + public PlaybackParameters getPlaybackParameters() { + return playbackParameters; } @Override 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 3c43d3c22f5..0043cb9e748 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 @@ -328,11 +328,11 @@ public long getPositionUs() { } @Override - public void setPlaybackSpeed(float playbackSpeed) {} + public void setPlaybackParameters(PlaybackParameters playbackParameters) {} @Override - public float getPlaybackSpeed() { - return Player.DEFAULT_PLAYBACK_SPEED; + public PlaybackParameters getPlaybackParameters() { + return PlaybackParameters.DEFAULT; } @Override @@ -1010,7 +1010,7 @@ protected FakeMediaPeriod createFakeMediaPeriod( } }) // Set playback speed (while the fake media period is not yet prepared). - .setPlaybackSpeed(2f) + .setPlaybackParameters(new PlaybackParameters(/* speed= */ 2f)) // Complete preparation of the fake media period. .executeRunnable(() -> fakeMediaPeriodHolder[0].setPreparationComplete()) .build(); @@ -3378,18 +3378,18 @@ protected void doActionImpl( SimpleExoPlayer player, DefaultTrackSelector trackSelector, @Nullable Surface surface) { - maskedPlaybackSpeeds.add(player.getPlaybackSpeed()); + maskedPlaybackSpeeds.add(player.getPlaybackParameters().speed); } }; ActionSchedule actionSchedule = new ActionSchedule.Builder(TAG) .pause() .waitForPlaybackState(Player.STATE_READY) - .setPlaybackSpeed(1.1f) + .setPlaybackParameters(new PlaybackParameters(/* speed= */ 1.1f)) .apply(getPlaybackSpeedAction) - .setPlaybackSpeed(1.2f) + .setPlaybackParameters(new PlaybackParameters(/* speed= */ 1.2f)) .apply(getPlaybackSpeedAction) - .setPlaybackSpeed(1.3f) + .setPlaybackParameters(new PlaybackParameters(/* speed= */ 1.3f)) .apply(getPlaybackSpeedAction) .play() .build(); @@ -3397,8 +3397,8 @@ protected void doActionImpl( EventListener listener = new EventListener() { @Override - public void onPlaybackSpeedChanged(float playbackSpeed) { - reportedPlaybackSpeeds.add(playbackSpeed); + public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { + reportedPlaybackSpeeds.add(playbackParameters.speed); } }; new ExoPlayerTestRunner.Builder(context) @@ -3424,28 +3424,28 @@ public long getPositionUs() { } @Override - public void setPlaybackSpeed(float playbackSpeed) {} + public void setPlaybackParameters(PlaybackParameters playbackParameters) {} @Override - public float getPlaybackSpeed() { - return Player.DEFAULT_PLAYBACK_SPEED; + public PlaybackParameters getPlaybackParameters() { + return PlaybackParameters.DEFAULT; } }; ActionSchedule actionSchedule = new ActionSchedule.Builder(TAG) .pause() .waitForPlaybackState(Player.STATE_READY) - .setPlaybackSpeed(1.1f) - .setPlaybackSpeed(1.2f) - .setPlaybackSpeed(1.3f) + .setPlaybackParameters(new PlaybackParameters(/* speed= */ 1.1f)) + .setPlaybackParameters(new PlaybackParameters(/* speed= */ 1.2f)) + .setPlaybackParameters(new PlaybackParameters(/* speed= */ 1.3f)) .play() .build(); - List reportedPlaybackParameters = new ArrayList<>(); + List reportedPlaybackParameters = new ArrayList<>(); EventListener listener = new EventListener() { @Override - public void onPlaybackSpeedChanged(float playbackSpeed) { - reportedPlaybackParameters.add(playbackSpeed); + public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { + reportedPlaybackParameters.add(playbackParameters); } }; new ExoPlayerTestRunner.Builder(context) @@ -3458,7 +3458,11 @@ public void onPlaybackSpeedChanged(float playbackSpeed) { .blockUntilEnded(TIMEOUT_MS); assertThat(reportedPlaybackParameters) - .containsExactly(1.1f, 1.2f, 1.3f, Player.DEFAULT_PLAYBACK_SPEED) + .containsExactly( + new PlaybackParameters(/* speed= */ 1.1f), + new PlaybackParameters(/* speed= */ 1.2f), + new PlaybackParameters(/* speed= */ 1.3f), + PlaybackParameters.DEFAULT) .inOrder(); } 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 7fa586c3232..20be8fe12b9 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 @@ -435,7 +435,7 @@ private void setupTimeline(Timeline timeline) { /* loadingMediaPeriodId= */ null, /* playWhenReady= */ false, Player.PLAYBACK_SUPPRESSION_REASON_NONE, - /* playbackSpeed= */ Player.DEFAULT_PLAYBACK_SPEED, + /* playbackParameters= */ PlaybackParameters.DEFAULT, /* 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 1b686b8d040..1238831cbca 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 @@ -26,6 +26,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.RenderersFactory; @@ -82,7 +83,7 @@ public final class AnalyticsCollectorTest { private static final int EVENT_POSITION_DISCONTINUITY = 2; private static final int EVENT_SEEK_STARTED = 3; private static final int EVENT_SEEK_PROCESSED = 4; - private static final int EVENT_PLAYBACK_SPEED_CHANGED = 5; + private static final int EVENT_PLAYBACK_PARAMETERS_CHANGED = 5; private static final int EVENT_REPEAT_MODE_CHANGED = 6; private static final int EVENT_SHUFFLE_MODE_CHANGED = 7; private static final int EVENT_LOADING_CHANGED = 8; @@ -1795,8 +1796,9 @@ public void onSeekProcessed(EventTime eventTime) { } @Override - public void onPlaybackSpeedChanged(EventTime eventTime, float playbackSpeed) { - reportedEvents.add(new ReportedEvent(EVENT_PLAYBACK_SPEED_CHANGED, eventTime)); + public void onPlaybackParametersChanged( + EventTime eventTime, PlaybackParameters playbackParameters) { + reportedEvents.add(new ReportedEvent(EVENT_PLAYBACK_PARAMETERS_CHANGED, eventTime)); } @Override diff --git a/library/core/src/test/java/com/google/android/exoplayer2/analytics/PlaybackStatsListenerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/analytics/PlaybackStatsListenerTest.java index 8a1f8807eaa..1f19c2af588 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/analytics/PlaybackStatsListenerTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/analytics/PlaybackStatsListenerTest.java @@ -26,6 +26,7 @@ import android.os.SystemClock; import androidx.annotation.Nullable; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.MediaSource; @@ -75,8 +76,8 @@ public void events_duringInitialIdleState_dontCreateNewPlaybackStats() { playbackStatsListener.onPositionDiscontinuity( EMPTY_TIMELINE_EVENT_TIME, Player.DISCONTINUITY_REASON_SEEK); - playbackStatsListener.onPlaybackSpeedChanged( - EMPTY_TIMELINE_EVENT_TIME, /* playbackSpeed= */ 2.0f); + playbackStatsListener.onPlaybackParametersChanged( + EMPTY_TIMELINE_EVENT_TIME, new PlaybackParameters(/* speed= */ 2.0f)); playbackStatsListener.onPlayWhenReadyChanged( EMPTY_TIMELINE_EVENT_TIME, /* playWhenReady= */ true, diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java index 54628f91bee..2f86988d424 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java @@ -25,6 +25,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.util.MimeTypes; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -89,7 +90,7 @@ public void handlesBufferAfterReset() throws Exception { @Test public void handlesBufferAfterReset_withPlaybackSpeed() throws Exception { - defaultAudioSink.setPlaybackSpeed(/* playbackSpeed= */ 1.5f); + defaultAudioSink.setPlaybackParameters(new PlaybackParameters(/* speed= */ 1.5f)); configureDefaultAudioSink(CHANNEL_COUNT_STEREO); defaultAudioSink.handleBuffer( createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1); @@ -99,7 +100,8 @@ public void handlesBufferAfterReset_withPlaybackSpeed() throws Exception { configureDefaultAudioSink(CHANNEL_COUNT_STEREO); defaultAudioSink.handleBuffer( createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1); - assertThat(defaultAudioSink.getPlaybackSpeed()).isEqualTo(1.5f); + assertThat(defaultAudioSink.getPlaybackParameters()) + .isEqualTo(new PlaybackParameters(/* speed= */ 1.5f)); } @Test @@ -117,7 +119,7 @@ public void handlesBufferAfterReset_withFormatChange() throws Exception { @Test public void handlesBufferAfterReset_withFormatChangeAndPlaybackSpeed() throws Exception { - defaultAudioSink.setPlaybackSpeed(/* playbackSpeed= */ 1.5f); + defaultAudioSink.setPlaybackParameters(new PlaybackParameters(/* speed= */ 1.5f)); configureDefaultAudioSink(CHANNEL_COUNT_STEREO); defaultAudioSink.handleBuffer( createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1); @@ -127,7 +129,8 @@ public void handlesBufferAfterReset_withFormatChangeAndPlaybackSpeed() throws Ex configureDefaultAudioSink(CHANNEL_COUNT_MONO); defaultAudioSink.handleBuffer( createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1); - assertThat(defaultAudioSink.getPlaybackSpeed()).isEqualTo(1.5f); + assertThat(defaultAudioSink.getPlaybackParameters()) + .isEqualTo(new PlaybackParameters(/* speed= */ 1.5f)); } @Test diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java index 62e9094cf0f..fe802f9c0e2 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java @@ -1085,8 +1085,8 @@ private void updateProgress() { long mediaTimeUntilNextFullSecondMs = 1000 - position % 1000; mediaTimeDelayMs = Math.min(mediaTimeDelayMs, mediaTimeUntilNextFullSecondMs); - // Calculate the delay until the next update in real time, taking playbackSpeed into account. - float playbackSpeed = player.getPlaybackSpeed(); + // Calculate the delay until the next update in real time, taking playback speed into account. + float playbackSpeed = player.getPlaybackParameters().speed; long delayMs = playbackSpeed > 0 ? (long) (mediaTimeDelayMs / playbackSpeed) : MAX_UPDATE_INTERVAL_MS; diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java index d0e7b0da9ec..06a53414998 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java @@ -37,6 +37,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ControlDispatcher; import com.google.android.exoplayer2.DefaultControlDispatcher; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.PlaybackPreparer; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; @@ -923,7 +924,7 @@ public final void setSmallIcon(@DrawableRes int smallIconResourceId) { *

  • The media is not {@link Player#isCurrentWindowDynamic() dynamically changing its * duration} (like for example a live stream). *
  • The media is not {@link Player#isPlayingAd() interrupted by an ad}. - *
  • The media is played at {@link Player#getPlaybackSpeed() regular speed}. + *
  • The media is played at {@link Player#getPlaybackParameters() regular speed}. *
  • The device is running at least API 21 (Lollipop). * * @@ -1086,7 +1087,7 @@ protected NotificationCompat.Builder createNotification( && player.isPlaying() && !player.isPlayingAd() && !player.isCurrentWindowDynamic() - && player.getPlaybackSpeed() == 1f) { + && player.getPlaybackParameters().speed == 1f) { builder .setWhen(System.currentTimeMillis() - player.getContentPosition()) .setShowWhen(true) @@ -1336,7 +1337,7 @@ public void onTimelineChanged(Timeline timeline, int reason) { } @Override - public void onPlaybackSpeedChanged(float playbackSpeed) { + public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { postStartOrUpdateNotification(); } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java index ae523b4387c..07106686ad2 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java @@ -42,6 +42,7 @@ import com.google.android.exoplayer2.DefaultControlDispatcher; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.PlaybackPreparer; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.RendererCapabilities; @@ -1408,8 +1409,8 @@ private void updateProgress() { long mediaTimeUntilNextFullSecondMs = 1000 - position % 1000; mediaTimeDelayMs = Math.min(mediaTimeDelayMs, mediaTimeUntilNextFullSecondMs); - // Calculate the delay until the next update in real time, taking playbackSpeed into account. - float playbackSpeed = player.getPlaybackSpeed(); + // Calculate the delay until the next update in real time, taking playback speed into account. + float playbackSpeed = player.getPlaybackParameters().speed; long delayMs = playbackSpeed > 0 ? (long) (mediaTimeDelayMs / playbackSpeed) : MAX_UPDATE_INTERVAL_MS; @@ -1425,7 +1426,7 @@ private void updateSettingsPlaybackSpeedLists() { if (player == null) { return; } - float speed = player.getPlaybackSpeed(); + float speed = player.getPlaybackParameters().speed; int currentSpeedMultBy100 = Math.round(speed * 100); int indexForCurrentSpeed = playbackSpeedMultBy100List.indexOf(currentSpeedMultBy100); if (indexForCurrentSpeed == UNDEFINED_POSITION) { @@ -1481,7 +1482,7 @@ private void setPlaybackSpeed(float speed) { if (player == null) { return; } - player.setPlaybackSpeed(speed); + player.setPlaybackParameters(new PlaybackParameters(speed)); } /* package */ void requestPlayPauseFocus() { @@ -1771,7 +1772,7 @@ public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) { } @Override - public void onPlaybackSpeedChanged(float playbackSpeed) { + public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { updateSettingsPlaybackSpeedLists(); } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/Action.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/Action.java index 5b8d501d001..ca514432f23 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/Action.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/Action.java @@ -22,6 +22,7 @@ import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.IllegalSeekPositionException; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.PlayerMessage; import com.google.android.exoplayer2.PlayerMessage.Target; @@ -608,26 +609,26 @@ protected void doActionImpl( } } - /** Calls {@link Player#setPlaybackSpeed(float)}. */ - public static final class SetPlaybackSpeed extends Action { + /** Calls {@link Player#setPlaybackParameters(PlaybackParameters)}. */ + public static final class SetPlaybackParameters extends Action { - private final float playbackSpeed; + private final PlaybackParameters playbackParameters; /** - * Creates a set playback speed action instance. + * Creates a set playback parameters action instance. * * @param tag A tag to use for logging. - * @param playbackSpeed The playback speed. + * @param playbackParameters The playback parameters. */ - public SetPlaybackSpeed(String tag, float playbackSpeed) { - super(tag, "SetPlaybackSpeed:" + playbackSpeed); - this.playbackSpeed = playbackSpeed; + public SetPlaybackParameters(String tag, PlaybackParameters playbackParameters) { + super(tag, "SetPlaybackParameters:" + playbackParameters); + this.playbackParameters = playbackParameters; } @Override protected void doActionImpl( SimpleExoPlayer player, DefaultTrackSelector trackSelector, @Nullable Surface surface) { - player.setPlaybackSpeed(playbackSpeed); + player.setPlaybackParameters(playbackParameters); } } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/ActionSchedule.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/ActionSchedule.java index 8051e997b3d..fa672b844ac 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/ActionSchedule.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/ActionSchedule.java @@ -20,6 +20,7 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; +import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.PlayerMessage; import com.google.android.exoplayer2.PlayerMessage.Target; @@ -35,7 +36,7 @@ import com.google.android.exoplayer2.testutil.Action.SendMessages; import com.google.android.exoplayer2.testutil.Action.SetAudioAttributes; import com.google.android.exoplayer2.testutil.Action.SetPlayWhenReady; -import com.google.android.exoplayer2.testutil.Action.SetPlaybackSpeed; +import com.google.android.exoplayer2.testutil.Action.SetPlaybackParameters; import com.google.android.exoplayer2.testutil.Action.SetRendererDisabled; import com.google.android.exoplayer2.testutil.Action.SetRepeatMode; import com.google.android.exoplayer2.testutil.Action.SetShuffleModeEnabled; @@ -214,14 +215,14 @@ public Builder waitForPendingPlayerCommands() { } /** - * Schedules a playback speed setting action. + * Schedules a playback parameters setting action. * - * @param playbackSpeed The playback speed to set. + * @param playbackParameters The playback parameters to set. * @return The builder, for convenience. - * @see Player#setPlaybackSpeed(float) + * @see Player#setPlaybackParameters(PlaybackParameters) */ - public Builder setPlaybackSpeed(float playbackSpeed) { - return apply(new SetPlaybackSpeed(tag, playbackSpeed)); + public Builder setPlaybackParameters(PlaybackParameters playbackParameters) { + return apply(new SetPlaybackParameters(tag, playbackParameters)); } /** diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java index 250dd01c0f2..7a96e1c797f 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java @@ -314,32 +314,16 @@ public void seekTo(int windowIndex, long positionMs) { throw new UnsupportedOperationException(); } - /** @deprecated Use {@link #setPlaybackSpeed(float)} instead. */ - @SuppressWarnings("deprecation") - @Deprecated @Override public void setPlaybackParameters(@Nullable PlaybackParameters playbackParameters) { throw new UnsupportedOperationException(); } - /** @deprecated Use {@link #getPlaybackSpeed()} instead. */ - @SuppressWarnings("deprecation") - @Deprecated @Override public PlaybackParameters getPlaybackParameters() { throw new UnsupportedOperationException(); } - @Override - public void setPlaybackSpeed(float playbackSpeed) { - throw new UnsupportedOperationException(); - } - - @Override - public float getPlaybackSpeed() { - throw new UnsupportedOperationException(); - } - @Override public void setSeekParameters(@Nullable SeekParameters seekParameters) { throw new UnsupportedOperationException();