remove PlaybackParameter dependency from MediaClock

After this change MediaClocks and ExoPlayerImplInternal don't depend on the deprecated PlaybackParameter anymore but only know about playbackSpeed.

PiperOrigin-RevId: 300428791
This commit is contained in:
bachinger 2020-03-11 23:12:01 +00:00 committed by Oliver Woodman
parent 683cb0260e
commit 072720270d
9 changed files with 159 additions and 174 deletions

View File

@ -26,22 +26,20 @@ import com.google.android.exoplayer2.util.StandaloneMediaClock;
*/ */
/* package */ final class DefaultMediaClock implements MediaClock { /* package */ final class DefaultMediaClock implements MediaClock {
/** /** Listener interface to be notified of changes to the active playback speed. */
* Listener interface to be notified of changes to the active playback parameters. public interface PlaybackSpeedListener {
*/
public interface PlaybackParameterListener {
/** /**
* Called when the active playback parameters changed. Will not be called for {@link * Called when the active playback speed changed. Will not be called for {@link
* #setPlaybackParameters(PlaybackParameters)}. * #setPlaybackSpeed(float)}.
* *
* @param newPlaybackParameters The newly active {@link PlaybackParameters}. * @param newPlaybackSpeed The newly active playback speed.
*/ */
void onPlaybackParametersChanged(PlaybackParameters newPlaybackParameters); void onPlaybackSpeedChanged(float newPlaybackSpeed);
} }
private final StandaloneMediaClock standaloneClock; private final StandaloneMediaClock standaloneClock;
private final PlaybackParameterListener listener; private final PlaybackSpeedListener listener;
@Nullable private Renderer rendererClockSource; @Nullable private Renderer rendererClockSource;
@Nullable private MediaClock rendererClock; @Nullable private MediaClock rendererClock;
@ -49,14 +47,13 @@ import com.google.android.exoplayer2.util.StandaloneMediaClock;
private boolean standaloneClockIsStarted; private boolean standaloneClockIsStarted;
/** /**
* Creates a new instance with listener for playback parameter changes and a {@link Clock} to use * Creates a new instance with listener for playback speed changes and a {@link Clock} to use for
* for the standalone clock implementation. * the standalone clock implementation.
* *
* @param listener A {@link PlaybackParameterListener} to listen for playback parameter * @param listener A {@link PlaybackSpeedListener} to listen for playback speed changes.
* changes.
* @param clock A {@link Clock}. * @param clock A {@link Clock}.
*/ */
public DefaultMediaClock(PlaybackParameterListener listener, Clock clock) { public DefaultMediaClock(PlaybackSpeedListener listener, Clock clock) {
this.listener = listener; this.listener = listener;
this.standaloneClock = new StandaloneMediaClock(clock); this.standaloneClock = new StandaloneMediaClock(clock);
isUsingStandaloneClock = true; isUsingStandaloneClock = true;
@ -96,7 +93,7 @@ import com.google.android.exoplayer2.util.StandaloneMediaClock;
* clock is already provided. * clock is already provided.
*/ */
public void onRendererEnabled(Renderer renderer) throws ExoPlaybackException { public void onRendererEnabled(Renderer renderer) throws ExoPlaybackException {
MediaClock rendererMediaClock = renderer.getMediaClock(); @Nullable MediaClock rendererMediaClock = renderer.getMediaClock();
if (rendererMediaClock != null && rendererMediaClock != rendererClock) { if (rendererMediaClock != null && rendererMediaClock != rendererClock) {
if (rendererClock != null) { if (rendererClock != null) {
throw ExoPlaybackException.createForUnexpected( throw ExoPlaybackException.createForUnexpected(
@ -104,7 +101,7 @@ import com.google.android.exoplayer2.util.StandaloneMediaClock;
} }
this.rendererClock = rendererMediaClock; this.rendererClock = rendererMediaClock;
this.rendererClockSource = renderer; this.rendererClockSource = renderer;
rendererClock.setPlaybackParameters(standaloneClock.getPlaybackParameters()); rendererClock.setPlaybackSpeed(standaloneClock.getPlaybackSpeed());
} }
} }
@ -140,19 +137,19 @@ import com.google.android.exoplayer2.util.StandaloneMediaClock;
} }
@Override @Override
public void setPlaybackParameters(PlaybackParameters playbackParameters) { public void setPlaybackSpeed(float playbackSpeed) {
if (rendererClock != null) { if (rendererClock != null) {
rendererClock.setPlaybackParameters(playbackParameters); rendererClock.setPlaybackSpeed(playbackSpeed);
playbackParameters = rendererClock.getPlaybackParameters(); playbackSpeed = rendererClock.getPlaybackSpeed();
} }
standaloneClock.setPlaybackParameters(playbackParameters); standaloneClock.setPlaybackSpeed(playbackSpeed);
} }
@Override @Override
public PlaybackParameters getPlaybackParameters() { public float getPlaybackSpeed() {
return rendererClock != null return rendererClock != null
? rendererClock.getPlaybackParameters() ? rendererClock.getPlaybackSpeed()
: standaloneClock.getPlaybackParameters(); : standaloneClock.getPlaybackSpeed();
} }
private void syncClocks(boolean isReadingAhead) { private void syncClocks(boolean isReadingAhead) {
@ -177,10 +174,10 @@ import com.google.android.exoplayer2.util.StandaloneMediaClock;
} }
// Continuously sync stand-alone clock to renderer clock so that it can take over if needed. // Continuously sync stand-alone clock to renderer clock so that it can take over if needed.
standaloneClock.resetPosition(rendererClockPositionUs); standaloneClock.resetPosition(rendererClockPositionUs);
PlaybackParameters playbackParameters = rendererClock.getPlaybackParameters(); float playbackSpeed = rendererClock.getPlaybackSpeed();
if (!playbackParameters.equals(standaloneClock.getPlaybackParameters())) { if (playbackSpeed != standaloneClock.getPlaybackSpeed()) {
standaloneClock.setPlaybackParameters(playbackParameters); standaloneClock.setPlaybackSpeed(playbackSpeed);
listener.onPlaybackParametersChanged(playbackParameters); listener.onPlaybackSpeedChanged(playbackSpeed);
} }
} }

View File

@ -562,7 +562,7 @@ import java.util.concurrent.TimeoutException;
pendingSetPlaybackSpeedAcks++; pendingSetPlaybackSpeedAcks++;
this.playbackSpeed = playbackSpeed; this.playbackSpeed = playbackSpeed;
PlaybackParameters playbackParameters = new PlaybackParameters(playbackSpeed); PlaybackParameters playbackParameters = new PlaybackParameters(playbackSpeed);
internalPlayer.setPlaybackParameters(playbackParameters); internalPlayer.setPlaybackSpeed(playbackSpeed);
notifyListeners( notifyListeners(
listener -> { listener -> {
listener.onPlaybackParametersChanged(playbackParameters); listener.onPlaybackParametersChanged(playbackParameters);

View File

@ -24,7 +24,7 @@ import android.os.SystemClock;
import android.util.Pair; import android.util.Pair;
import androidx.annotation.CheckResult; import androidx.annotation.CheckResult;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.DefaultMediaClock.PlaybackParameterListener; import com.google.android.exoplayer2.DefaultMediaClock.PlaybackSpeedListener;
import com.google.android.exoplayer2.Player.DiscontinuityReason; import com.google.android.exoplayer2.Player.DiscontinuityReason;
import com.google.android.exoplayer2.Player.PlayWhenReadyChangeReason; import com.google.android.exoplayer2.Player.PlayWhenReadyChangeReason;
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason; import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
@ -57,7 +57,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
MediaPeriod.Callback, MediaPeriod.Callback,
TrackSelector.InvalidationListener, TrackSelector.InvalidationListener,
Playlist.PlaylistInfoRefreshListener, Playlist.PlaylistInfoRefreshListener,
PlaybackParameterListener, PlaybackSpeedListener,
PlayerMessage.Sender { PlayerMessage.Sender {
private static final String TAG = "ExoPlayerImplInternal"; private static final String TAG = "ExoPlayerImplInternal";
@ -71,7 +71,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
private static final int MSG_SET_PLAY_WHEN_READY = 1; private static final int MSG_SET_PLAY_WHEN_READY = 1;
private static final int MSG_DO_SOME_WORK = 2; private static final int MSG_DO_SOME_WORK = 2;
private static final int MSG_SEEK_TO = 3; private static final int MSG_SEEK_TO = 3;
private static final int MSG_SET_PLAYBACK_PARAMETERS = 4; private static final int MSG_SET_PLAYBACK_SPEED = 4;
private static final int MSG_SET_SEEK_PARAMETERS = 5; private static final int MSG_SET_SEEK_PARAMETERS = 5;
private static final int MSG_STOP = 6; private static final int MSG_STOP = 6;
private static final int MSG_RELEASE = 7; private static final int MSG_RELEASE = 7;
@ -83,7 +83,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
private static final int MSG_SET_FOREGROUND_MODE = 13; private static final int MSG_SET_FOREGROUND_MODE = 13;
private static final int MSG_SEND_MESSAGE = 14; private static final int MSG_SEND_MESSAGE = 14;
private static final int MSG_SEND_MESSAGE_TO_TARGET_THREAD = 15; private static final int MSG_SEND_MESSAGE_TO_TARGET_THREAD = 15;
private static final int MSG_PLAYBACK_PARAMETERS_CHANGED_INTERNAL = 16; private static final int MSG_PLAYBACK_SPEED_CHANGED_INTERNAL = 16;
private static final int MSG_SET_MEDIA_SOURCES = 17; private static final int MSG_SET_MEDIA_SOURCES = 17;
private static final int MSG_ADD_MEDIA_SOURCES = 18; private static final int MSG_ADD_MEDIA_SOURCES = 18;
private static final int MSG_MOVE_MEDIA_SOURCES = 19; private static final int MSG_MOVE_MEDIA_SOURCES = 19;
@ -224,8 +224,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
.sendToTarget(); .sendToTarget();
} }
public void setPlaybackParameters(PlaybackParameters playbackParameters) { public void setPlaybackSpeed(float playbackSpeed) {
handler.obtainMessage(MSG_SET_PLAYBACK_PARAMETERS, playbackParameters).sendToTarget(); handler.obtainMessage(MSG_SET_PLAYBACK_SPEED, playbackSpeed).sendToTarget();
} }
public void setSeekParameters(SeekParameters seekParameters) { public void setSeekParameters(SeekParameters seekParameters) {
@ -365,11 +365,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
handler.sendEmptyMessage(MSG_TRACK_SELECTION_INVALIDATED); handler.sendEmptyMessage(MSG_TRACK_SELECTION_INVALIDATED);
} }
// DefaultMediaClock.PlaybackParameterListener implementation. // DefaultMediaClock.PlaybackSpeedListener implementation.
@Override @Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { public void onPlaybackSpeedChanged(float playbackSpeed) {
sendPlaybackParametersChangedInternal(playbackParameters, /* acknowledgeCommand= */ false); sendPlaybackSpeedChangedInternal(playbackSpeed, /* acknowledgeCommand= */ false);
} }
// Handler.Callback implementation. // Handler.Callback implementation.
@ -401,8 +401,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
case MSG_SEEK_TO: case MSG_SEEK_TO:
seekToInternal((SeekPosition) msg.obj); seekToInternal((SeekPosition) msg.obj);
break; break;
case MSG_SET_PLAYBACK_PARAMETERS: case MSG_SET_PLAYBACK_SPEED:
setPlaybackParametersInternal((PlaybackParameters) msg.obj); setPlaybackSpeedInternal((Float) msg.obj);
break; break;
case MSG_SET_SEEK_PARAMETERS: case MSG_SET_SEEK_PARAMETERS:
setSeekParametersInternal((SeekParameters) msg.obj); setSeekParametersInternal((SeekParameters) msg.obj);
@ -426,9 +426,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
case MSG_TRACK_SELECTION_INVALIDATED: case MSG_TRACK_SELECTION_INVALIDATED:
reselectTracksInternal(); reselectTracksInternal();
break; break;
case MSG_PLAYBACK_PARAMETERS_CHANGED_INTERNAL: case MSG_PLAYBACK_SPEED_CHANGED_INTERNAL:
handlePlaybackParameters( handlePlaybackSpeed((Float) msg.obj, /* acknowledgeCommand= */ msg.arg1 != 0);
(PlaybackParameters) msg.obj, /* acknowledgeCommand= */ msg.arg1 != 0);
break; break;
case MSG_SEND_MESSAGE: case MSG_SEND_MESSAGE:
sendMessageInternal((PlayerMessage) msg.obj); sendMessageInternal((PlayerMessage) msg.obj);
@ -1089,10 +1088,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
notifyTrackSelectionDiscontinuity(); notifyTrackSelectionDiscontinuity();
} }
private void setPlaybackParametersInternal(PlaybackParameters playbackParameters) { private void setPlaybackSpeedInternal(float playbackSpeed) {
mediaClock.setPlaybackParameters(playbackParameters); mediaClock.setPlaybackSpeed(playbackSpeed);
sendPlaybackParametersChangedInternal( sendPlaybackSpeedChangedInternal(mediaClock.getPlaybackSpeed(), /* acknowledgeCommand= */ true);
mediaClock.getPlaybackParameters(), /* acknowledgeCommand= */ true);
} }
private void setSeekParametersInternal(SeekParameters seekParameters) { private void setSeekParametersInternal(SeekParameters seekParameters) {
@ -1419,7 +1417,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
} }
private void reselectTracksInternal() throws ExoPlaybackException { private void reselectTracksInternal() throws ExoPlaybackException {
float playbackSpeed = mediaClock.getPlaybackParameters().speed; float playbackSpeed = mediaClock.getPlaybackSpeed();
// Reselect tracks on each period in turn, until the selection changes. // Reselect tracks on each period in turn, until the selection changes.
MediaPeriodHolder periodHolder = queue.getPlayingPeriod(); MediaPeriodHolder periodHolder = queue.getPlayingPeriod();
MediaPeriodHolder readingPeriodHolder = queue.getReadingPeriod(); MediaPeriodHolder readingPeriodHolder = queue.getReadingPeriod();
@ -1542,7 +1540,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
boolean bufferedToEnd = loadingHolder.isFullyBuffered() && loadingHolder.info.isFinal; boolean bufferedToEnd = loadingHolder.isFullyBuffered() && loadingHolder.info.isFinal;
return bufferedToEnd return bufferedToEnd
|| loadControl.shouldStartPlayback( || loadControl.shouldStartPlayback(
getTotalBufferedDurationUs(), mediaClock.getPlaybackParameters().speed, rebuffering); getTotalBufferedDurationUs(), mediaClock.getPlaybackSpeed(), rebuffering);
} }
private boolean isTimelineReady() { private boolean isTimelineReady() {
@ -1871,8 +1869,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
return; return;
} }
MediaPeriodHolder loadingPeriodHolder = queue.getLoadingPeriod(); MediaPeriodHolder loadingPeriodHolder = queue.getLoadingPeriod();
loadingPeriodHolder.handlePrepared( loadingPeriodHolder.handlePrepared(mediaClock.getPlaybackSpeed(), playbackInfo.timeline);
mediaClock.getPlaybackParameters().speed, playbackInfo.timeline);
updateLoadControlTrackSelection( updateLoadControlTrackSelection(
loadingPeriodHolder.getTrackGroups(), loadingPeriodHolder.getTrackSelectorResult()); loadingPeriodHolder.getTrackGroups(), loadingPeriodHolder.getTrackSelectorResult());
if (loadingPeriodHolder == queue.getPlayingPeriod()) { if (loadingPeriodHolder == queue.getPlayingPeriod()) {
@ -1897,17 +1894,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
maybeContinueLoading(); maybeContinueLoading();
} }
private void handlePlaybackParameters( private void handlePlaybackSpeed(float playbackSpeed, boolean acknowledgeCommand)
PlaybackParameters playbackParameters, boolean acknowledgeCommand)
throws ExoPlaybackException { throws ExoPlaybackException {
eventHandler eventHandler
.obtainMessage( .obtainMessage(MSG_PLAYBACK_SPEED_CHANGED, acknowledgeCommand ? 1 : 0, 0, playbackSpeed)
MSG_PLAYBACK_SPEED_CHANGED, acknowledgeCommand ? 1 : 0, 0, playbackParameters.speed)
.sendToTarget(); .sendToTarget();
updateTrackSelectionPlaybackSpeed(playbackParameters.speed); updateTrackSelectionPlaybackSpeed(playbackSpeed);
for (Renderer renderer : renderers) { for (Renderer renderer : renderers) {
if (renderer != null) { if (renderer != null) {
renderer.setOperatingRate(playbackParameters.speed); renderer.setOperatingRate(playbackSpeed);
} }
} }
} }
@ -1933,8 +1928,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
// where playback gets stuck. // where playback gets stuck.
return true; return true;
} }
float playbackSpeed = mediaClock.getPlaybackParameters().speed; return loadControl.shouldContinueLoading(bufferedDurationUs, mediaClock.getPlaybackSpeed());
return loadControl.shouldContinueLoading(bufferedDurationUs, playbackSpeed);
} }
private boolean isLoadingPossible() { private boolean isLoadingPossible() {
@ -2123,14 +2117,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
loadControl.onTracksSelected(renderers, trackGroups, trackSelectorResult.selections); loadControl.onTracksSelected(renderers, trackGroups, trackSelectorResult.selections);
} }
private void sendPlaybackParametersChangedInternal( private void sendPlaybackSpeedChangedInternal(float playbackSpeed, boolean acknowledgeCommand) {
PlaybackParameters playbackParameters, boolean acknowledgeCommand) {
handler handler
.obtainMessage( .obtainMessage(
MSG_PLAYBACK_PARAMETERS_CHANGED_INTERNAL, MSG_PLAYBACK_SPEED_CHANGED_INTERNAL, acknowledgeCommand ? 1 : 0, 0, playbackSpeed)
acknowledgeCommand ? 1 : 0,
0,
playbackParameters)
.sendToTarget(); .sendToTarget();
} }

View File

@ -28,7 +28,6 @@ import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.PlayerMessage.Target;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher; import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher;
@ -567,13 +566,13 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
} }
@Override @Override
public void setPlaybackParameters(PlaybackParameters playbackParameters) { public void setPlaybackSpeed(float playbackSpeed) {
audioSink.setPlaybackParameters(playbackParameters); audioSink.setPlaybackSpeed(playbackSpeed);
} }
@Override @Override
public PlaybackParameters getPlaybackParameters() { public float getPlaybackSpeed() {
return audioSink.getPlaybackParameters(); return audioSink.getPlaybackSpeed();
} }
@Override @Override

View File

@ -26,7 +26,6 @@ import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.PlayerMessage.Target;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher; import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher;
@ -487,13 +486,13 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
} }
@Override @Override
public void setPlaybackParameters(PlaybackParameters playbackParameters) { public void setPlaybackSpeed(float playbackSpeed) {
audioSink.setPlaybackParameters(playbackParameters); audioSink.setPlaybackSpeed(playbackSpeed);
} }
@Override @Override
public PlaybackParameters getPlaybackParameters() { public float getPlaybackSpeed() {
return audioSink.getPlaybackParameters(); return audioSink.getPlaybackSpeed();
} }
@Override @Override

View File

@ -15,8 +15,6 @@
*/ */
package com.google.android.exoplayer2.util; package com.google.android.exoplayer2.util;
import com.google.android.exoplayer2.PlaybackParameters;
/** /**
* Tracks the progression of media time. * Tracks the progression of media time.
*/ */
@ -28,16 +26,13 @@ public interface MediaClock {
long getPositionUs(); long getPositionUs();
/** /**
* Attempts to set the playback parameters. The media clock may override these parameters if they * Attempts to set the playback speed. The media clock may override the speed if changing the
* are not supported. * speed is not supported.
* *
* @param playbackParameters The playback parameters to attempt to set. * @param playbackSpeed The playback speed to attempt to set.
*/ */
void setPlaybackParameters(PlaybackParameters playbackParameters); void setPlaybackSpeed(float playbackSpeed);
/**
* Returns the active playback parameters.
*/
PlaybackParameters getPlaybackParameters();
/** Returns the active playback speed. */
float getPlaybackSpeed();
} }

View File

@ -16,7 +16,7 @@
package com.google.android.exoplayer2.util; package com.google.android.exoplayer2.util;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player;
/** /**
* A {@link MediaClock} whose position advances with real time based on the playback parameters when * A {@link MediaClock} whose position advances with real time based on the playback parameters when
@ -29,7 +29,8 @@ public final class StandaloneMediaClock implements MediaClock {
private boolean started; private boolean started;
private long baseUs; private long baseUs;
private long baseElapsedMs; private long baseElapsedMs;
private PlaybackParameters playbackParameters; private float playbackSpeed;
private int scaledUsPerMs;
/** /**
* Creates a new standalone media clock using the given {@link Clock} implementation. * Creates a new standalone media clock using the given {@link Clock} implementation.
@ -38,7 +39,8 @@ public final class StandaloneMediaClock implements MediaClock {
*/ */
public StandaloneMediaClock(Clock clock) { public StandaloneMediaClock(Clock clock) {
this.clock = clock; this.clock = clock;
this.playbackParameters = PlaybackParameters.DEFAULT; playbackSpeed = Player.DEFAULT_PLAYBACK_SPEED;
scaledUsPerMs = getScaledUsPerMs(playbackSpeed);
} }
/** /**
@ -78,27 +80,33 @@ public final class StandaloneMediaClock implements MediaClock {
long positionUs = baseUs; long positionUs = baseUs;
if (started) { if (started) {
long elapsedSinceBaseMs = clock.elapsedRealtime() - baseElapsedMs; long elapsedSinceBaseMs = clock.elapsedRealtime() - baseElapsedMs;
if (playbackParameters.speed == 1f) { if (playbackSpeed == 1f) {
positionUs += C.msToUs(elapsedSinceBaseMs); positionUs += C.msToUs(elapsedSinceBaseMs);
} else { } else {
positionUs += playbackParameters.getMediaTimeUsForPlayoutTimeMs(elapsedSinceBaseMs); // Add the media time in microseconds that will elapse in elapsedSinceBaseMs milliseconds of
// wallclock time
positionUs += elapsedSinceBaseMs * scaledUsPerMs;
} }
} }
return positionUs; return positionUs;
} }
@Override @Override
public void setPlaybackParameters(PlaybackParameters playbackParameters) { public void setPlaybackSpeed(float playbackSpeed) {
// Store the current position as the new base, in case the playback speed has changed. // Store the current position as the new base, in case the playback speed has changed.
if (started) { if (started) {
resetPosition(getPositionUs()); resetPosition(getPositionUs());
} }
this.playbackParameters = playbackParameters; this.playbackSpeed = playbackSpeed;
scaledUsPerMs = getScaledUsPerMs(playbackSpeed);
} }
@Override @Override
public PlaybackParameters getPlaybackParameters() { public float getPlaybackSpeed() {
return playbackParameters; return playbackSpeed;
} }
private static int getScaledUsPerMs(float playbackSpeed) {
return Math.round(playbackSpeed * 1000f);
}
} }

View File

@ -22,7 +22,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.MockitoAnnotations.initMocks; import static org.mockito.MockitoAnnotations.initMocks;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.DefaultMediaClock.PlaybackParameterListener; import com.google.android.exoplayer2.DefaultMediaClock.PlaybackSpeedListener;
import com.google.android.exoplayer2.testutil.FakeClock; import com.google.android.exoplayer2.testutil.FakeClock;
import com.google.android.exoplayer2.testutil.FakeMediaClockRenderer; import com.google.android.exoplayer2.testutil.FakeMediaClockRenderer;
import org.junit.Before; import org.junit.Before;
@ -36,10 +36,9 @@ public class DefaultMediaClockTest {
private static final long TEST_POSITION_US = 123456789012345678L; private static final long TEST_POSITION_US = 123456789012345678L;
private static final long SLEEP_TIME_MS = 1_000; private static final long SLEEP_TIME_MS = 1_000;
private static final PlaybackParameters TEST_PLAYBACK_PARAMETERS = private static final float TEST_PLAYBACK_SPEED = 2f;
new PlaybackParameters(/* speed= */ 2f);
@Mock private PlaybackParameterListener listener; @Mock private PlaybackSpeedListener listener;
private FakeClock fakeClock; private FakeClock fakeClock;
private DefaultMediaClock mediaClock; private DefaultMediaClock mediaClock;
@ -110,119 +109,117 @@ public class DefaultMediaClockTest {
} }
@Test @Test
public void standaloneGetPlaybackParameters_initializedWithDefaultPlaybackParameters() { public void standaloneGetPlaybackSpeed_initializedWithDefaultPlaybackSpeed() {
assertThat(mediaClock.getPlaybackParameters()).isEqualTo(PlaybackParameters.DEFAULT); assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(Player.DEFAULT_PLAYBACK_SPEED);
} }
@Test @Test
public void standaloneSetPlaybackParameters_getPlaybackParametersShouldReturnSameValue() { public void standaloneSetPlaybackSpeed_getPlaybackSpeedShouldReturnSameValue() {
mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED);
assertThat(mediaClock.getPlaybackParameters()).isEqualTo(TEST_PLAYBACK_PARAMETERS); assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(TEST_PLAYBACK_SPEED);
} }
@Test @Test
public void standaloneSetPlaybackParameters_shouldNotTriggerCallback() { public void standaloneSetPlaybackSpeed_shouldNotTriggerCallback() {
mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED);
verifyNoMoreInteractions(listener); verifyNoMoreInteractions(listener);
} }
@Test @Test
public void standaloneSetPlaybackParameters_shouldApplyNewPlaybackSpeed() { public void standaloneSetPlaybackSpeed_shouldApplyNewPlaybackSpeed() {
mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED);
mediaClock.start(); mediaClock.start();
// Asserts that clock is running with speed declared in getPlaybackParameters(). // Asserts that clock is running with speed declared in getPlaybackSpeed().
assertClockIsRunning(/* isReadingAhead= */ false); assertClockIsRunning(/* isReadingAhead= */ false);
} }
@Test @Test
public void standaloneSetOtherPlaybackParameters_getPlaybackParametersShouldReturnSameValue() { public void standaloneSetOtherPlaybackSpeed_getPlaybackSpeedShouldReturnSameValue() {
mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED);
mediaClock.setPlaybackParameters(PlaybackParameters.DEFAULT); mediaClock.setPlaybackSpeed(Player.DEFAULT_PLAYBACK_SPEED);
assertThat(mediaClock.getPlaybackParameters()).isEqualTo(PlaybackParameters.DEFAULT); assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(Player.DEFAULT_PLAYBACK_SPEED);
} }
@Test @Test
public void enableRendererMediaClock_shouldOverwriteRendererPlaybackParametersIfPossible() public void enableRendererMediaClock_shouldOverwriteRendererPlaybackSpeedIfPossible()
throws ExoPlaybackException { throws ExoPlaybackException {
FakeMediaClockRenderer mediaClockRenderer = FakeMediaClockRenderer mediaClockRenderer =
new MediaClockRenderer(TEST_PLAYBACK_PARAMETERS, /* playbackParametersAreMutable= */ true); new MediaClockRenderer(TEST_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ true);
mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.onRendererEnabled(mediaClockRenderer);
assertThat(mediaClock.getPlaybackParameters()).isEqualTo(PlaybackParameters.DEFAULT); assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(Player.DEFAULT_PLAYBACK_SPEED);
verifyNoMoreInteractions(listener); verifyNoMoreInteractions(listener);
} }
@Test @Test
public void enableRendererMediaClockWithFixedParameters_usesRendererPlaybackParameters() public void enableRendererMediaClockWithFixedPlaybackSpeed_usesRendererPlaybackSpeed()
throws ExoPlaybackException { throws ExoPlaybackException {
FakeMediaClockRenderer mediaClockRenderer = FakeMediaClockRenderer mediaClockRenderer =
new MediaClockRenderer(TEST_PLAYBACK_PARAMETERS, /* playbackParametersAreMutable= */ false); new MediaClockRenderer(TEST_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ false);
mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.onRendererEnabled(mediaClockRenderer);
assertThat(mediaClock.getPlaybackParameters()).isEqualTo(TEST_PLAYBACK_PARAMETERS); assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(TEST_PLAYBACK_SPEED);
} }
@Test @Test
public void enableRendererMediaClockWithFixedParameters_shouldTriggerCallback() public void enableRendererMediaClockWithFixedPlaybackSpeed_shouldTriggerCallback()
throws ExoPlaybackException { throws ExoPlaybackException {
FakeMediaClockRenderer mediaClockRenderer = FakeMediaClockRenderer mediaClockRenderer =
new MediaClockRenderer(TEST_PLAYBACK_PARAMETERS, /* playbackParametersAreMutable= */ false); new MediaClockRenderer(TEST_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ false);
mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.onRendererEnabled(mediaClockRenderer);
mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false);
verify(listener).onPlaybackParametersChanged(TEST_PLAYBACK_PARAMETERS); verify(listener).onPlaybackSpeedChanged(TEST_PLAYBACK_SPEED);
} }
@Test @Test
public void enableRendererMediaClockWithFixedButSamePlaybackParameters_shouldNotTriggerCallback() public void enableRendererMediaClockWithFixedButSamePlaybackSpeed_shouldNotTriggerCallback()
throws ExoPlaybackException { throws ExoPlaybackException {
FakeMediaClockRenderer mediaClockRenderer = new MediaClockRenderer(PlaybackParameters.DEFAULT, FakeMediaClockRenderer mediaClockRenderer =
/* playbackParametersAreMutable= */ false); new MediaClockRenderer(Player.DEFAULT_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ false);
mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.onRendererEnabled(mediaClockRenderer);
mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false);
verifyNoMoreInteractions(listener); verifyNoMoreInteractions(listener);
} }
@Test @Test
public void disableRendererMediaClock_shouldKeepPlaybackParameters() public void disableRendererMediaClock_shouldKeepPlaybackSpeed() throws ExoPlaybackException {
throws ExoPlaybackException {
FakeMediaClockRenderer mediaClockRenderer = FakeMediaClockRenderer mediaClockRenderer =
new MediaClockRenderer(TEST_PLAYBACK_PARAMETERS, /* playbackParametersAreMutable= */ false); new MediaClockRenderer(TEST_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ false);
mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.onRendererEnabled(mediaClockRenderer);
mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false);
mediaClock.onRendererDisabled(mediaClockRenderer); mediaClock.onRendererDisabled(mediaClockRenderer);
mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false);
assertThat(mediaClock.getPlaybackParameters()).isEqualTo(TEST_PLAYBACK_PARAMETERS); assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(TEST_PLAYBACK_SPEED);
} }
@Test @Test
public void rendererClockSetPlaybackParameters_getPlaybackParametersShouldReturnSameValue() public void rendererClockSetPlaybackSpeed_getPlaybackSpeedShouldReturnSameValue()
throws ExoPlaybackException { throws ExoPlaybackException {
FakeMediaClockRenderer mediaClockRenderer = new MediaClockRenderer(PlaybackParameters.DEFAULT, FakeMediaClockRenderer mediaClockRenderer =
/* playbackParametersAreMutable= */ true); new MediaClockRenderer(Player.DEFAULT_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ true);
mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.onRendererEnabled(mediaClockRenderer);
mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false);
mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED);
assertThat(mediaClock.getPlaybackParameters()).isEqualTo(TEST_PLAYBACK_PARAMETERS); assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(TEST_PLAYBACK_SPEED);
} }
@Test @Test
public void rendererClockSetPlaybackParameters_shouldNotTriggerCallback() public void rendererClockSetPlaybackSpeed_shouldNotTriggerCallback() throws ExoPlaybackException {
throws ExoPlaybackException { FakeMediaClockRenderer mediaClockRenderer =
FakeMediaClockRenderer mediaClockRenderer = new MediaClockRenderer(PlaybackParameters.DEFAULT, new MediaClockRenderer(Player.DEFAULT_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ true);
/* playbackParametersAreMutable= */ true);
mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.onRendererEnabled(mediaClockRenderer);
mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false);
mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED);
verifyNoMoreInteractions(listener); verifyNoMoreInteractions(listener);
} }
@Test @Test
public void rendererClockSetPlaybackParametersOverwrite_getParametersShouldReturnSameValue() public void rendererClockSetPlaybackSpeedOverwrite_getPlaybackSpeedShouldReturnSameValue()
throws ExoPlaybackException { throws ExoPlaybackException {
FakeMediaClockRenderer mediaClockRenderer = new MediaClockRenderer(PlaybackParameters.DEFAULT, FakeMediaClockRenderer mediaClockRenderer =
/* playbackParametersAreMutable= */ false); new MediaClockRenderer(Player.DEFAULT_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ false);
mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.onRendererEnabled(mediaClockRenderer);
mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false);
mediaClock.setPlaybackParameters(TEST_PLAYBACK_PARAMETERS); mediaClock.setPlaybackSpeed(TEST_PLAYBACK_SPEED);
assertThat(mediaClock.getPlaybackParameters()).isEqualTo(PlaybackParameters.DEFAULT); assertThat(mediaClock.getPlaybackSpeed()).isEqualTo(Player.DEFAULT_PLAYBACK_SPEED);
} }
@Test @Test
@ -266,16 +263,15 @@ public class DefaultMediaClockTest {
} }
@Test @Test
public void getPositionWithPlaybackParameterChange_shouldTriggerCallback() public void getPositionWithPlaybackSpeedChange_shouldTriggerCallback()
throws ExoPlaybackException { throws ExoPlaybackException {
MediaClockRenderer mediaClockRenderer = MediaClockRenderer mediaClockRenderer =
new MediaClockRenderer( new MediaClockRenderer(Player.DEFAULT_PLAYBACK_SPEED, /* playbackSpeedIsMutable= */ true);
PlaybackParameters.DEFAULT, /* playbackParametersAreMutable= */ true);
mediaClock.onRendererEnabled(mediaClockRenderer); mediaClock.onRendererEnabled(mediaClockRenderer);
// Silently change playback parameters of renderer clock. // Silently change playback speed of renderer clock.
mediaClockRenderer.playbackParameters = TEST_PLAYBACK_PARAMETERS; mediaClockRenderer.playbackSpeed = TEST_PLAYBACK_SPEED;
mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false); mediaClock.syncAndGetPositionUs(/* isReadingAhead= */ false);
verify(listener).onPlaybackParametersChanged(TEST_PLAYBACK_PARAMETERS); verify(listener).onPlaybackSpeedChanged(TEST_PLAYBACK_SPEED);
} }
@Test @Test
@ -360,10 +356,9 @@ public class DefaultMediaClockTest {
private void assertClockIsRunning(boolean isReadingAhead) { private void assertClockIsRunning(boolean isReadingAhead) {
long clockStartUs = mediaClock.syncAndGetPositionUs(isReadingAhead); long clockStartUs = mediaClock.syncAndGetPositionUs(isReadingAhead);
fakeClock.advanceTime(SLEEP_TIME_MS); fakeClock.advanceTime(SLEEP_TIME_MS);
int scaledUsPerMs = Math.round(mediaClock.getPlaybackSpeed() * 1000f);
assertThat(mediaClock.syncAndGetPositionUs(isReadingAhead)) assertThat(mediaClock.syncAndGetPositionUs(isReadingAhead))
.isEqualTo( .isEqualTo(clockStartUs + (SLEEP_TIME_MS * scaledUsPerMs));
clockStartUs
+ mediaClock.getPlaybackParameters().getMediaTimeUsForPlayoutTimeMs(SLEEP_TIME_MS));
} }
private void assertClockIsStopped() { private void assertClockIsStopped() {
@ -376,34 +371,36 @@ public class DefaultMediaClockTest {
@SuppressWarnings("HidingField") @SuppressWarnings("HidingField")
private static class MediaClockRenderer extends FakeMediaClockRenderer { private static class MediaClockRenderer extends FakeMediaClockRenderer {
private final boolean playbackParametersAreMutable; private final boolean playbackSpeedIsMutable;
private final boolean isReady; private final boolean isReady;
private final boolean isEnded; private final boolean isEnded;
public PlaybackParameters playbackParameters; public float playbackSpeed;
public long positionUs; public long positionUs;
public MediaClockRenderer() throws ExoPlaybackException { public MediaClockRenderer() throws ExoPlaybackException {
this(PlaybackParameters.DEFAULT, false, true, false, false); this(Player.DEFAULT_PLAYBACK_SPEED, false, true, false, false);
} }
public MediaClockRenderer(PlaybackParameters playbackParameters, public MediaClockRenderer(float playbackSpeed, boolean playbackSpeedIsMutable)
boolean playbackParametersAreMutable)
throws ExoPlaybackException { throws ExoPlaybackException {
this(playbackParameters, playbackParametersAreMutable, true, false, false); this(playbackSpeed, playbackSpeedIsMutable, true, false, false);
} }
public MediaClockRenderer(boolean isReady, boolean isEnded, boolean hasReadStreamToEnd) public MediaClockRenderer(boolean isReady, boolean isEnded, boolean hasReadStreamToEnd)
throws ExoPlaybackException { throws ExoPlaybackException {
this(PlaybackParameters.DEFAULT, false, isReady, isEnded, hasReadStreamToEnd); this(Player.DEFAULT_PLAYBACK_SPEED, false, isReady, isEnded, hasReadStreamToEnd);
} }
private MediaClockRenderer(PlaybackParameters playbackParameters, private MediaClockRenderer(
boolean playbackParametersAreMutable, boolean isReady, boolean isEnded, float playbackSpeed,
boolean playbackSpeedIsMutable,
boolean isReady,
boolean isEnded,
boolean hasReadStreamToEnd) boolean hasReadStreamToEnd)
throws ExoPlaybackException { throws ExoPlaybackException {
this.playbackParameters = playbackParameters; this.playbackSpeed = playbackSpeed;
this.playbackParametersAreMutable = playbackParametersAreMutable; this.playbackSpeedIsMutable = playbackSpeedIsMutable;
this.isReady = isReady; this.isReady = isReady;
this.isEnded = isEnded; this.isEnded = isEnded;
this.positionUs = TEST_POSITION_US; this.positionUs = TEST_POSITION_US;
@ -418,15 +415,15 @@ public class DefaultMediaClockTest {
} }
@Override @Override
public void setPlaybackParameters(PlaybackParameters playbackParameters) { public void setPlaybackSpeed(float playbackSpeed) {
if (playbackParametersAreMutable) { if (playbackSpeedIsMutable) {
this.playbackParameters = playbackParameters; this.playbackSpeed = playbackSpeed;
} }
} }
@Override @Override
public PlaybackParameters getPlaybackParameters() { public float getPlaybackSpeed() {
return playbackParameters; return playbackSpeed;
} }
@Override @Override

View File

@ -256,11 +256,11 @@ public final class ExoPlayerTest {
} }
@Override @Override
public void setPlaybackParameters(PlaybackParameters playbackParameters) {} public void setPlaybackSpeed(float playbackSpeed) {}
@Override @Override
public PlaybackParameters getPlaybackParameters() { public float getPlaybackSpeed() {
return PlaybackParameters.DEFAULT; return Player.DEFAULT_PLAYBACK_SPEED;
} }
@Override @Override
@ -3217,11 +3217,11 @@ public final class ExoPlayerTest {
} }
@Override @Override
public void setPlaybackParameters(PlaybackParameters playbackParameters) {} public void setPlaybackSpeed(float playbackSpeed) {}
@Override @Override
public PlaybackParameters getPlaybackParameters() { public float getPlaybackSpeed() {
return PlaybackParameters.DEFAULT; return Player.DEFAULT_PLAYBACK_SPEED;
} }
}; };
ActionSchedule actionSchedule = ActionSchedule actionSchedule =