Commit 6c7a2c3c by tonihei Committed by Oliver Woodman

Ensure seeks are not ignored in ended state.

We should only ignore seek to the current position if we are
currently READY or BUFFERING. Also, pending initial seek positions
should only be saved while we have an empty timeline, independent of
the player state.

Issue:#6886
PiperOrigin-RevId: 297813854
parent 68c401b5
...@@ -902,12 +902,14 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -902,12 +902,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
} }
try { try {
if (playbackInfo.timeline.isEmpty() || !playlist.isPrepared()) { if (playbackInfo.timeline.isEmpty()) {
// Save seek position for later, as we are still waiting for a prepared source. // Save seek position for later, as we are still waiting for a prepared source.
pendingInitialSeekPosition = seekPosition; pendingInitialSeekPosition = seekPosition;
} else if (resolvedSeekPosition == null) { } else if (resolvedSeekPosition == null) {
// End playback, as we didn't manage to find a valid seek position. // End playback, as we didn't manage to find a valid seek position.
setState(Player.STATE_ENDED); if (playbackInfo.playbackState != Player.STATE_IDLE) {
setState(Player.STATE_ENDED);
}
resetInternal( resetInternal(
/* resetRenderers= */ false, /* resetRenderers= */ false,
/* resetPosition= */ true, /* resetPosition= */ true,
...@@ -926,7 +928,9 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -926,7 +928,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
playingPeriodHolder.mediaPeriod.getAdjustedSeekPositionUs( playingPeriodHolder.mediaPeriod.getAdjustedSeekPositionUs(
newPeriodPositionUs, seekParameters); newPeriodPositionUs, seekParameters);
} }
if (C.usToMs(newPeriodPositionUs) == C.usToMs(playbackInfo.positionUs)) { if (C.usToMs(newPeriodPositionUs) == C.usToMs(playbackInfo.positionUs)
&& (playbackInfo.playbackState == Player.STATE_BUFFERING
|| playbackInfo.playbackState == Player.STATE_READY)) {
// Seek will be performed to the current position. Do nothing. // Seek will be performed to the current position. Do nothing.
periodPositionUs = playbackInfo.positionUs; periodPositionUs = playbackInfo.positionUs;
return; return;
......
...@@ -5728,6 +5728,43 @@ public final class ExoPlayerTest { ...@@ -5728,6 +5728,43 @@ public final class ExoPlayerTest {
assertThat(trackSelectionsAfterError.get().get(1)).isNotNull(); // Audio renderer. assertThat(trackSelectionsAfterError.get().get(1)).isNotNull(); // Audio renderer.
} }
@Test
public void seekToCurrentPosition_inEndedState_switchesToBufferingStateAndContinuesPlayback()
throws Exception {
MediaSource mediaSource = new FakeMediaSource(new FakeTimeline(/* windowCount = */ 1));
AtomicInteger windowIndexAfterFinalEndedState = new AtomicInteger();
ActionSchedule actionSchedule =
new ActionSchedule.Builder("seekToCurrentPosition_inEndedState")
.waitForPlaybackState(Player.STATE_ENDED)
.addMediaSources(mediaSource)
.executeRunnable(
new PlayerRunnable() {
@Override
public void run(SimpleExoPlayer player) {
player.seekTo(player.getCurrentPosition());
}
})
.waitForPlaybackState(Player.STATE_READY)
.waitForPlaybackState(Player.STATE_ENDED)
.executeRunnable(
new PlayerRunnable() {
@Override
public void run(SimpleExoPlayer player) {
windowIndexAfterFinalEndedState.set(player.getCurrentWindowIndex());
}
})
.build();
new Builder()
.setMediaSources(mediaSource)
.setActionSchedule(actionSchedule)
.build(context)
.start()
.blockUntilActionScheduleFinished(TIMEOUT_MS)
.blockUntilEnded(TIMEOUT_MS);
assertThat(windowIndexAfterFinalEndedState.get()).isEqualTo(1);
}
// Internal methods. // Internal methods.
private static ActionSchedule.Builder addSurfaceSwitch(ActionSchedule.Builder builder) { private static ActionSchedule.Builder addSurfaceSwitch(ActionSchedule.Builder builder) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment