deliver player messages only once when at start position
ISSUE: #6550 PiperOrigin-RevId: 275842161
This commit is contained in:
parent
7ccbc4c436
commit
3bb97f4bbf
@ -122,6 +122,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
private SeekPosition pendingInitialSeekPosition;
|
private SeekPosition pendingInitialSeekPosition;
|
||||||
private long rendererPositionUs;
|
private long rendererPositionUs;
|
||||||
private int nextPendingMessageIndex;
|
private int nextPendingMessageIndex;
|
||||||
|
private boolean deliverPendingMessageAtStartPositionRequired;
|
||||||
|
|
||||||
public ExoPlayerImplInternal(
|
public ExoPlayerImplInternal(
|
||||||
Renderer[] renderers,
|
Renderer[] renderers,
|
||||||
@ -171,6 +172,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
new HandlerThread("ExoPlayerImplInternal:Handler", Process.THREAD_PRIORITY_AUDIO);
|
new HandlerThread("ExoPlayerImplInternal:Handler", Process.THREAD_PRIORITY_AUDIO);
|
||||||
internalPlaybackThread.start();
|
internalPlaybackThread.start();
|
||||||
handler = clock.createHandler(internalPlaybackThread.getLooper(), this);
|
handler = clock.createHandler(internalPlaybackThread.getLooper(), this);
|
||||||
|
deliverPendingMessageAtStartPositionRequired = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prepare(MediaSource mediaSource, boolean resetPosition, boolean resetState) {
|
public void prepare(MediaSource mediaSource, boolean resetPosition, boolean resetState) {
|
||||||
@ -487,12 +489,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
long newPositionUs =
|
long newPositionUs =
|
||||||
seekToPeriodPosition(periodId, playbackInfo.positionUs, /* forceDisableRenderers= */ true);
|
seekToPeriodPosition(periodId, playbackInfo.positionUs, /* forceDisableRenderers= */ true);
|
||||||
if (newPositionUs != playbackInfo.positionUs) {
|
if (newPositionUs != playbackInfo.positionUs) {
|
||||||
playbackInfo =
|
playbackInfo = copyWithNewPosition(periodId, newPositionUs, playbackInfo.contentPositionUs);
|
||||||
playbackInfo.copyWithNewPosition(
|
|
||||||
periodId,
|
|
||||||
newPositionUs,
|
|
||||||
playbackInfo.contentPositionUs,
|
|
||||||
getTotalBufferedDurationUs());
|
|
||||||
if (sendDiscontinuity) {
|
if (sendDiscontinuity) {
|
||||||
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
|
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
|
||||||
}
|
}
|
||||||
@ -531,11 +528,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
// renderers are flushed. Only report the discontinuity externally if the position changed.
|
// renderers are flushed. Only report the discontinuity externally if the position changed.
|
||||||
if (discontinuityPositionUs != playbackInfo.positionUs) {
|
if (discontinuityPositionUs != playbackInfo.positionUs) {
|
||||||
playbackInfo =
|
playbackInfo =
|
||||||
playbackInfo.copyWithNewPosition(
|
copyWithNewPosition(
|
||||||
playbackInfo.periodId,
|
playbackInfo.periodId, discontinuityPositionUs, playbackInfo.contentPositionUs);
|
||||||
discontinuityPositionUs,
|
|
||||||
playbackInfo.contentPositionUs,
|
|
||||||
getTotalBufferedDurationUs());
|
|
||||||
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
|
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -722,9 +716,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
periodPositionUs = newPeriodPositionUs;
|
periodPositionUs = newPeriodPositionUs;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
playbackInfo =
|
playbackInfo = copyWithNewPosition(periodId, periodPositionUs, contentPositionUs);
|
||||||
playbackInfo.copyWithNewPosition(
|
|
||||||
periodId, periodPositionUs, contentPositionUs, getTotalBufferedDurationUs());
|
|
||||||
if (seekPositionAdjusted) {
|
if (seekPositionAdjusted) {
|
||||||
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT);
|
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT);
|
||||||
}
|
}
|
||||||
@ -1062,10 +1054,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// If this is the first call from the start position, include oldPeriodPositionUs in potential
|
// If this is the first call from the start position, include oldPeriodPositionUs in potential
|
||||||
// trigger positions.
|
// trigger positions, but make sure we deliver it only once.
|
||||||
if (playbackInfo.startPositionUs == oldPeriodPositionUs) {
|
if (playbackInfo.startPositionUs == oldPeriodPositionUs
|
||||||
|
&& deliverPendingMessageAtStartPositionRequired) {
|
||||||
oldPeriodPositionUs--;
|
oldPeriodPositionUs--;
|
||||||
}
|
}
|
||||||
|
deliverPendingMessageAtStartPositionRequired = false;
|
||||||
|
|
||||||
// Correct next index if necessary (e.g. after seeking, timeline changes, or new messages)
|
// Correct next index if necessary (e.g. after seeking, timeline changes, or new messages)
|
||||||
int currentPeriodIndex =
|
int currentPeriodIndex =
|
||||||
playbackInfo.timeline.getIndexOfPeriod(playbackInfo.periodId.periodUid);
|
playbackInfo.timeline.getIndexOfPeriod(playbackInfo.periodId.periodUid);
|
||||||
@ -1164,11 +1159,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
if (playbackInfo.playbackState != Player.STATE_ENDED
|
if (playbackInfo.playbackState != Player.STATE_ENDED
|
||||||
&& periodPositionUs != playbackInfo.positionUs) {
|
&& periodPositionUs != playbackInfo.positionUs) {
|
||||||
playbackInfo =
|
playbackInfo =
|
||||||
playbackInfo.copyWithNewPosition(
|
copyWithNewPosition(
|
||||||
playbackInfo.periodId,
|
playbackInfo.periodId, periodPositionUs, playbackInfo.contentPositionUs);
|
||||||
periodPositionUs,
|
|
||||||
playbackInfo.contentPositionUs,
|
|
||||||
getTotalBufferedDurationUs());
|
|
||||||
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
|
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
|
||||||
resetRendererPosition(periodPositionUs);
|
resetRendererPosition(periodPositionUs);
|
||||||
}
|
}
|
||||||
@ -1371,9 +1363,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
// Actually do the seek.
|
// Actually do the seek.
|
||||||
long newPositionUs = newPeriodId.isAd() ? 0 : newContentPositionUs;
|
long newPositionUs = newPeriodId.isAd() ? 0 : newContentPositionUs;
|
||||||
long seekedToPositionUs = seekToPeriodPosition(newPeriodId, newPositionUs);
|
long seekedToPositionUs = seekToPeriodPosition(newPeriodId, newPositionUs);
|
||||||
playbackInfo =
|
playbackInfo = copyWithNewPosition(newPeriodId, seekedToPositionUs, newContentPositionUs);
|
||||||
playbackInfo.copyWithNewPosition(
|
|
||||||
newPeriodId, seekedToPositionUs, newContentPositionUs, getTotalBufferedDurationUs());
|
|
||||||
}
|
}
|
||||||
handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */ false);
|
handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */ false);
|
||||||
}
|
}
|
||||||
@ -1649,11 +1639,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
MediaPeriodHolder newPlayingPeriodHolder = queue.advancePlayingPeriod();
|
MediaPeriodHolder newPlayingPeriodHolder = queue.advancePlayingPeriod();
|
||||||
updatePlayingPeriodRenderers(oldPlayingPeriodHolder);
|
updatePlayingPeriodRenderers(oldPlayingPeriodHolder);
|
||||||
playbackInfo =
|
playbackInfo =
|
||||||
playbackInfo.copyWithNewPosition(
|
copyWithNewPosition(
|
||||||
newPlayingPeriodHolder.info.id,
|
newPlayingPeriodHolder.info.id,
|
||||||
newPlayingPeriodHolder.info.startPositionUs,
|
newPlayingPeriodHolder.info.startPositionUs,
|
||||||
newPlayingPeriodHolder.info.contentPositionUs,
|
newPlayingPeriodHolder.info.contentPositionUs);
|
||||||
getTotalBufferedDurationUs());
|
|
||||||
int discontinuityReason =
|
int discontinuityReason =
|
||||||
oldPlayingPeriodHolder.info.isLastInTimelinePeriod
|
oldPlayingPeriodHolder.info.isLastInTimelinePeriod
|
||||||
? Player.DISCONTINUITY_REASON_PERIOD_TRANSITION
|
? Player.DISCONTINUITY_REASON_PERIOD_TRANSITION
|
||||||
@ -1789,6 +1778,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PlaybackInfo copyWithNewPosition(
|
||||||
|
MediaPeriodId mediaPeriodId, long positionUs, long contentPositionUs) {
|
||||||
|
deliverPendingMessageAtStartPositionRequired = true;
|
||||||
|
return playbackInfo.copyWithNewPosition(
|
||||||
|
mediaPeriodId, positionUs, contentPositionUs, getTotalBufferedDurationUs());
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ParameterNotNullable")
|
@SuppressWarnings("ParameterNotNullable")
|
||||||
private void updatePlayingPeriodRenderers(@Nullable MediaPeriodHolder oldPlayingPeriodHolder)
|
private void updatePlayingPeriodRenderers(@Nullable MediaPeriodHolder oldPlayingPeriodHolder)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
|
@ -1576,6 +1576,34 @@ public final class ExoPlayerTest {
|
|||||||
assertThat(target80.positionMs).isAtLeast(target50.positionMs);
|
assertThat(target80.positionMs).isAtLeast(target50.positionMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSendMessagesFromStartPositionOnlyOnce() throws Exception {
|
||||||
|
Timeline timeline = new FakeTimeline(/* windowCount= */ 1);
|
||||||
|
AtomicInteger counter = new AtomicInteger();
|
||||||
|
ActionSchedule actionSchedule =
|
||||||
|
new ActionSchedule.Builder("testSendMessagesFromStartPositionOnlyOnce")
|
||||||
|
.pause()
|
||||||
|
.sendMessage(
|
||||||
|
(messageType, payload) -> {
|
||||||
|
counter.getAndIncrement();
|
||||||
|
},
|
||||||
|
/* windowIndex= */ 0,
|
||||||
|
/* positionMs= */ 2000,
|
||||||
|
/* deleteAfterDelivery= */ false)
|
||||||
|
.seek(/* positionMs= */ 2000)
|
||||||
|
.delay(/* delayMs= */ 2000)
|
||||||
|
.play()
|
||||||
|
.build();
|
||||||
|
new Builder()
|
||||||
|
.setTimeline(timeline)
|
||||||
|
.setActionSchedule(actionSchedule)
|
||||||
|
.build(context)
|
||||||
|
.start()
|
||||||
|
.blockUntilActionScheduleFinished(TIMEOUT_MS)
|
||||||
|
.blockUntilEnded(TIMEOUT_MS);
|
||||||
|
assertThat(counter.get()).isEqualTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleSendMessagesAtSameTime() throws Exception {
|
public void testMultipleSendMessagesAtSameTime() throws Exception {
|
||||||
Timeline timeline = new FakeTimeline(/* windowCount= */ 1);
|
Timeline timeline = new FakeTimeline(/* windowCount= */ 1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user