Skip to content

Commit

Permalink
Fix wrong start position in resetInternal.
Browse files Browse the repository at this point in the history
The start position was set to the old start position instead of the current
playback position. We need to set the start position to the current playback
position to ensure a repreperation with the same media starts from the last
playback position.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=188025439
  • Loading branch information
tonihei authored and ojw28 committed Mar 7, 2018
1 parent b10f033 commit b7d2ae1
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ private void resetInternal(
resetState ? null : playbackInfo.manifest,
resetPosition ? new MediaPeriodId(getFirstPeriodIndex()) : playbackInfo.periodId,
// Set the start position to TIME_UNSET so that a subsequent seek to 0 isn't ignored.
resetPosition ? C.TIME_UNSET : playbackInfo.startPositionUs,
resetPosition ? C.TIME_UNSET : playbackInfo.positionUs,
resetPosition ? C.TIME_UNSET : playbackInfo.contentPositionUs,
playbackInfo.playbackState,
/* isLoading= */ false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import com.google.android.exoplayer2.testutil.FakeTrackSelection;
import com.google.android.exoplayer2.testutil.FakeTrackSelector;
import com.google.android.exoplayer2.upstream.Allocator;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -1169,10 +1170,8 @@ public void testReprepareAfterPlaybackError() throws Exception {
Timeline timeline = new FakeTimeline(/* windowCount= */ 1);
ActionSchedule actionSchedule =
new ActionSchedule.Builder("testReprepareAfterPlaybackError")
.waitForPlaybackState(Player.STATE_BUFFERING)
// Cause an internal exception by seeking to an invalid position while the media source
// is still being prepared and the player doesn't immediately know it will fail.
.seek(/* windowIndex= */ 100, /* positionMs= */ 0)
.waitForPlaybackState(Player.STATE_READY)
.throwPlaybackException(ExoPlaybackException.createForSource(new IOException()))
.waitForPlaybackState(Player.STATE_IDLE)
.prepareSource(
new FakeMediaSource(timeline, /* manifest= */ null),
Expand Down Expand Up @@ -1203,11 +1202,8 @@ public void testSeekAndReprepareAfterPlaybackError() throws Exception {
ActionSchedule actionSchedule =
new ActionSchedule.Builder("testReprepareAfterPlaybackError")
.pause()
.waitForPlaybackState(Player.STATE_BUFFERING)
// Cause an internal exception by seeking to an invalid position while the media source
// is still being prepared and the player doesn't immediately know it will fail.
.seek(/* windowIndex= */ 100, /* positionMs= */ 0)
.waitForSeekProcessed()
.waitForPlaybackState(Player.STATE_READY)
.throwPlaybackException(ExoPlaybackException.createForSource(new IOException()))
.waitForPlaybackState(Player.STATE_IDLE)
.seek(/* positionMs= */ 50)
.waitForSeekProcessed()
Expand Down Expand Up @@ -1246,8 +1242,7 @@ public void run(SimpleExoPlayer player) {
testRunner.assertTimelinesEqual(timeline, timeline);
testRunner.assertTimelineChangeReasonsEqual(
Player.TIMELINE_CHANGE_REASON_PREPARED, Player.TIMELINE_CHANGE_REASON_PREPARED);
testRunner.assertPositionDiscontinuityReasonsEqual(
Player.DISCONTINUITY_REASON_SEEK, Player.DISCONTINUITY_REASON_SEEK);
testRunner.assertPositionDiscontinuityReasonsEqual(Player.DISCONTINUITY_REASON_SEEK);
assertThat(positionHolder[0]).isEqualTo(50);
assertThat(positionHolder[1]).isEqualTo(50);
}
Expand Down Expand Up @@ -1288,6 +1283,72 @@ public void run() {
testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED);
}

@Test
public void testPlaybackErrorAndReprepareDoesNotResetPosition() throws Exception {
final Timeline timeline = new FakeTimeline(/* windowCount= */ 2);
final long[] positionHolder = new long[3];
final int[] windowIndexHolder = new int[3];
final FakeMediaSource secondMediaSource =
new FakeMediaSource(/* timeline= */ null, /* manifest= */ null);
ActionSchedule actionSchedule =
new ActionSchedule.Builder("testPlaybackErrorDoesNotResetPosition")
.pause()
.waitForPlaybackState(Player.STATE_READY)
.playUntilPosition(/* windowIndex= */ 1, /* positionMs= */ 500)
.throwPlaybackException(ExoPlaybackException.createForSource(new IOException()))
.waitForPlaybackState(Player.STATE_IDLE)
.executeRunnable(
new PlayerRunnable() {
@Override
public void run(SimpleExoPlayer player) {
// Position while in error state
positionHolder[0] = player.getCurrentPosition();
windowIndexHolder[0] = player.getCurrentWindowIndex();
}
})
.prepareSource(secondMediaSource, /* resetPosition= */ false, /* resetState= */ false)
.waitForPlaybackState(Player.STATE_BUFFERING)
.executeRunnable(
new PlayerRunnable() {
@Override
public void run(SimpleExoPlayer player) {
// Position while repreparing.
positionHolder[1] = player.getCurrentPosition();
windowIndexHolder[1] = player.getCurrentWindowIndex();
secondMediaSource.setNewSourceInfo(timeline, /* newManifest= */ null);
}
})
.waitForPlaybackState(Player.STATE_READY)
.executeRunnable(
new PlayerRunnable() {
@Override
public void run(SimpleExoPlayer player) {
// Position after repreparation finished.
positionHolder[2] = player.getCurrentPosition();
windowIndexHolder[2] = player.getCurrentWindowIndex();
}
})
.play()
.build();
ExoPlayerTestRunner testRunner =
new ExoPlayerTestRunner.Builder()
.setTimeline(timeline)
.setActionSchedule(actionSchedule)
.build();
try {
testRunner.start().blockUntilActionScheduleFinished(TIMEOUT_MS).blockUntilEnded(TIMEOUT_MS);
fail();
} catch (ExoPlaybackException e) {
// Expected exception.
}
assertThat(positionHolder[0]).isAtLeast(500L);
assertThat(positionHolder[1]).isEqualTo(positionHolder[0]);
assertThat(positionHolder[2]).isEqualTo(positionHolder[0]);
assertThat(windowIndexHolder[0]).isEqualTo(1);
assertThat(windowIndexHolder[1]).isEqualTo(1);
assertThat(windowIndexHolder[2]).isEqualTo(1);
}

@Test
public void testSendMessagesDuringPreparation() throws Exception {
Timeline timeline = new FakeTimeline(/* windowCount= */ 1);
Expand Down Expand Up @@ -1421,7 +1482,8 @@ public void testSendMessagesAtStartAndEndOfPeriod() throws Exception {
new FakeMediaSource(timeline, null),
/* resetPosition= */ false,
/* resetState= */ true)
.waitForPlaybackState(Player.STATE_READY)
.waitForPlaybackState(Player.STATE_BUFFERING)
.waitForPlaybackState(Player.STATE_ENDED)
.build();
new Builder()
.setTimeline(timeline)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,36 @@ protected void doActionImpl(SimpleExoPlayer player, MappingTrackSelector trackSe

}

/** Throws a playback exception on the playback thread. */
public static final class ThrowPlaybackException extends Action {

private final ExoPlaybackException exception;

/**
* @param tag A tag to use for logging.
* @param exception The exception to throw.
*/
public ThrowPlaybackException(String tag, ExoPlaybackException exception) {
super(tag, "ThrowPlaybackException:" + exception);
this.exception = exception;
}

@Override
protected void doActionImpl(
SimpleExoPlayer player, MappingTrackSelector trackSelector, Surface surface) {
player
.createMessage(
new Target() {
@Override
public void handleMessage(int messageType, Object payload)
throws ExoPlaybackException {
throw exception;
}
})
.send();
}
}

/**
* Schedules a play action to be executed, waits until the player reaches the specified position,
* and pauses the player again.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.google.android.exoplayer2.testutil.Action.SetShuffleModeEnabled;
import com.google.android.exoplayer2.testutil.Action.SetVideoSurface;
import com.google.android.exoplayer2.testutil.Action.Stop;
import com.google.android.exoplayer2.testutil.Action.ThrowPlaybackException;
import com.google.android.exoplayer2.testutil.Action.WaitForPlaybackState;
import com.google.android.exoplayer2.testutil.Action.WaitForPositionDiscontinuity;
import com.google.android.exoplayer2.testutil.Action.WaitForSeekProcessed;
Expand Down Expand Up @@ -412,6 +413,16 @@ public Builder executeRunnable(Runnable runnable) {
return apply(new ExecuteRunnable(tag, runnable));
}

/**
* Schedules to throw a playback exception on the playback thread.
*
* @param exception The exception to throw.
* @return The builder, for convenience.
*/
public Builder throwPlaybackException(ExoPlaybackException exception) {
return apply(new ThrowPlaybackException(tag, exception));
}

public ActionSchedule build() {
CallbackAction callbackAction = new CallbackAction(tag);
apply(callbackAction);
Expand Down

0 comments on commit b7d2ae1

Please sign in to comment.