Update media controller position before pausing.

We stop estimating new position when pausing until we
receive a new position from the player. However, this
means that we will continue to return a possible stale
previous position. Updating the current position before
pausing solves this issue.

PiperOrigin-RevId: 503153982
This commit is contained in:
tonihei 2023-01-19 15:00:49 +00:00 committed by christosts
parent 2cb4e3d71e
commit e961c1b5e9
2 changed files with 65 additions and 29 deletions

View File

@ -129,7 +129,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
@Nullable private TextureView videoTextureView; @Nullable private TextureView videoTextureView;
private Size surfaceSize; private Size surfaceSize;
@Nullable private IMediaSession iSession; @Nullable private IMediaSession iSession;
private long lastReturnedCurrentPositionMs; private long currentPositionMs;
private long lastSetPlayWhenReadyCalledTimeMs; private long lastSetPlayWhenReadyCalledTimeMs;
@Nullable private PlayerInfo pendingPlayerInfo; @Nullable private PlayerInfo pendingPlayerInfo;
@Nullable private BundlingExclusions pendingBundlingExclusions; @Nullable private BundlingExclusions pendingBundlingExclusions;
@ -175,7 +175,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
? null ? null
: new SessionServiceConnection(connectionHints); : new SessionServiceConnection(connectionHints);
flushCommandQueueHandler = new FlushCommandQueueHandler(applicationLooper); flushCommandQueueHandler = new FlushCommandQueueHandler(applicationLooper);
lastReturnedCurrentPositionMs = C.TIME_UNSET; currentPositionMs = C.TIME_UNSET;
lastSetPlayWhenReadyCalledTimeMs = C.TIME_UNSET; lastSetPlayWhenReadyCalledTimeMs = C.TIME_UNSET;
} }
@ -582,32 +582,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
@Override @Override
public long getCurrentPosition() { public long getCurrentPosition() {
boolean receivedUpdatedPositionInfo = maybeUpdateCurrentPositionMs();
lastSetPlayWhenReadyCalledTimeMs < playerInfo.sessionPositionInfo.eventTimeMs; return currentPositionMs;
if (!playerInfo.isPlaying) {
if (receivedUpdatedPositionInfo || lastReturnedCurrentPositionMs == C.TIME_UNSET) {
lastReturnedCurrentPositionMs = playerInfo.sessionPositionInfo.positionInfo.positionMs;
}
return lastReturnedCurrentPositionMs;
}
if (!receivedUpdatedPositionInfo && lastReturnedCurrentPositionMs != C.TIME_UNSET) {
// Need an updated current position in order to make a new position estimation
return lastReturnedCurrentPositionMs;
}
long elapsedTimeMs =
(getInstance().getTimeDiffMs() != C.TIME_UNSET)
? getInstance().getTimeDiffMs()
: SystemClock.elapsedRealtime() - playerInfo.sessionPositionInfo.eventTimeMs;
long estimatedPositionMs =
playerInfo.sessionPositionInfo.positionInfo.positionMs
+ (long) (elapsedTimeMs * playerInfo.playbackParameters.speed);
if (playerInfo.sessionPositionInfo.durationMs != C.TIME_UNSET) {
estimatedPositionMs = min(estimatedPositionMs, playerInfo.sessionPositionInfo.durationMs);
}
lastReturnedCurrentPositionMs = estimatedPositionMs;
return lastReturnedCurrentPositionMs;
} }
@Override @Override
@ -1966,7 +1942,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
return; return;
} }
// Stop estimating content position until a new positionInfo arrives from the player // Update position and then stop estimating until a new positionInfo arrives from the player.
maybeUpdateCurrentPositionMs();
lastSetPlayWhenReadyCalledTimeMs = SystemClock.elapsedRealtime(); lastSetPlayWhenReadyCalledTimeMs = SystemClock.elapsedRealtime();
PlayerInfo playerInfo = PlayerInfo playerInfo =
this.playerInfo.copyWithPlayWhenReady( this.playerInfo.copyWithPlayWhenReady(
@ -2726,6 +2703,34 @@ import org.checkerframework.checker.nullness.qual.NonNull;
return playerInfo; return playerInfo;
} }
private void maybeUpdateCurrentPositionMs() {
boolean receivedUpdatedPositionInfo =
lastSetPlayWhenReadyCalledTimeMs < playerInfo.sessionPositionInfo.eventTimeMs;
if (!playerInfo.isPlaying) {
if (receivedUpdatedPositionInfo || currentPositionMs == C.TIME_UNSET) {
currentPositionMs = playerInfo.sessionPositionInfo.positionInfo.positionMs;
}
return;
}
if (!receivedUpdatedPositionInfo && currentPositionMs != C.TIME_UNSET) {
// Need an updated current position in order to make a new position estimation
return;
}
long elapsedTimeMs =
(getInstance().getTimeDiffMs() != C.TIME_UNSET)
? getInstance().getTimeDiffMs()
: SystemClock.elapsedRealtime() - playerInfo.sessionPositionInfo.eventTimeMs;
long estimatedPositionMs =
playerInfo.sessionPositionInfo.positionInfo.positionMs
+ (long) (elapsedTimeMs * playerInfo.playbackParameters.speed);
if (playerInfo.sessionPositionInfo.durationMs != C.TIME_UNSET) {
estimatedPositionMs = min(estimatedPositionMs, playerInfo.sessionPositionInfo.durationMs);
}
currentPositionMs = estimatedPositionMs;
}
private Period getPeriodWithNewWindowIndex(Timeline timeline, int periodIndex, int windowIndex) { private Period getPeriodWithNewWindowIndex(Timeline timeline, int periodIndex, int windowIndex) {
Period period = new Period(); Period period = new Period();
timeline.getPeriod(periodIndex, period); timeline.getPeriod(periodIndex, period);

View File

@ -887,6 +887,37 @@ public class MediaControllerTest {
assertThat(currentPositionMs).isEqualTo(expectedCurrentPositionMs); assertThat(currentPositionMs).isEqualTo(expectedCurrentPositionMs);
} }
@Test
public void getCurrentPosition_afterPause_returnsCorrectPosition() throws Exception {
long testCurrentPosition = 100L;
PlaybackParameters testPlaybackParameters = new PlaybackParameters(/* speed= */ 2.0f);
long testTimeDiff = 50L;
Bundle playerConfig =
new RemoteMediaSession.MockPlayerConfigBuilder()
.setPlaybackState(Player.STATE_READY)
.setPlayWhenReady(true)
.setCurrentPosition(testCurrentPosition)
.setDuration(10_000L)
.setPlaybackParameters(testPlaybackParameters)
.build();
remoteSession.setPlayer(playerConfig);
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
long currentPositionMs =
threadTestRule
.getHandler()
.postAndSync(
() -> {
controller.setTimeDiffMs(testTimeDiff);
controller.pause();
return controller.getCurrentPosition();
});
long expectedCurrentPositionMs =
testCurrentPosition + (long) (testTimeDiff * testPlaybackParameters.speed);
assertThat(currentPositionMs).isEqualTo(expectedCurrentPositionMs);
}
@Test @Test
public void getContentPosition_whenPlayingAd_doesNotAdvance() throws Exception { public void getContentPosition_whenPlayingAd_doesNotAdvance() throws Exception {
long testContentPosition = 100L; long testContentPosition = 100L;