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
This commit is contained in:
parent
68c401b53e
commit
6c7a2c3cfd
@ -902,12 +902,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
}
|
||||
|
||||
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.
|
||||
pendingInitialSeekPosition = seekPosition;
|
||||
} else if (resolvedSeekPosition == null) {
|
||||
// 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(
|
||||
/* resetRenderers= */ false,
|
||||
/* resetPosition= */ true,
|
||||
@ -926,7 +928,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
playingPeriodHolder.mediaPeriod.getAdjustedSeekPositionUs(
|
||||
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.
|
||||
periodPositionUs = playbackInfo.positionUs;
|
||||
return;
|
||||
|
@ -5728,6 +5728,43 @@ public final class ExoPlayerTest {
|
||||
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.
|
||||
|
||||
private static ActionSchedule.Builder addSurfaceSwitch(ActionSchedule.Builder builder) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user