Skip to content

Commit 02298fa

Browse files
toniheimarcbaechinger
authored andcommitted
Fix issue where previous PositionInfo uses unset window index
When receiving a PlaybackInfo update from the internal player with a discontinuity, while ExoPlayerImpl has an empty timeline, we currently use C.INDEX_UNSET as the placeholder window index, which is not valid. In addition, receiving these stale discontinuities while both the current and new timelines are empty are misleading anyway, so added a new check to avoid sending out these specifcally. The fix to pass in the current masking window index is still needed to be absolutely sure it's set in case there is a discontinuity at the same time as a change from an empty Timeline to a non-empty one (wasn't able to craft a test for this case). PiperOrigin-RevId: 831406115 (cherry picked from commit 9be90e0)
1 parent 2a020c5 commit 02298fa

File tree

2 files changed

+54
-5
lines changed

2 files changed

+54
-5
lines changed

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,12 +2158,17 @@ private void handlePlaybackInfo(ExoPlayerImplInternal.PlaybackInfoUpdate playbac
21582158
}
21592159
boolean positionDiscontinuity = false;
21602160
long discontinuityWindowStartPositionUs = C.TIME_UNSET;
2161+
int oldMaskingMediaItemIndex = C.INDEX_UNSET;
21612162
if (pendingDiscontinuity) {
2162-
positionDiscontinuity =
2163-
!playbackInfoUpdate.playbackInfo.periodId.equals(playbackInfo.periodId)
2164-
|| playbackInfoUpdate.playbackInfo.discontinuityStartPositionUs
2165-
!= playbackInfo.positionUs;
2163+
boolean oldAndNewTimelineEmpty =
2164+
playbackInfoUpdate.playbackInfo.timeline.isEmpty() && playbackInfo.timeline.isEmpty();
2165+
boolean sameMediaPeriodId =
2166+
playbackInfoUpdate.playbackInfo.periodId.equals(playbackInfo.periodId);
2167+
boolean samePositon =
2168+
playbackInfoUpdate.playbackInfo.discontinuityStartPositionUs == playbackInfo.positionUs;
2169+
positionDiscontinuity = !oldAndNewTimelineEmpty && (!sameMediaPeriodId || !samePositon);
21662170
if (positionDiscontinuity) {
2171+
oldMaskingMediaItemIndex = getCurrentMediaItemIndex();
21672172
discontinuityWindowStartPositionUs =
21682173
newTimeline.isEmpty() || playbackInfoUpdate.playbackInfo.periodId.isAd()
21692174
? playbackInfoUpdate.playbackInfo.discontinuityStartPositionUs
@@ -2180,7 +2185,7 @@ private void handlePlaybackInfo(ExoPlayerImplInternal.PlaybackInfoUpdate playbac
21802185
positionDiscontinuity,
21812186
pendingDiscontinuityReason,
21822187
discontinuityWindowStartPositionUs,
2183-
/* ignored */ C.INDEX_UNSET,
2188+
oldMaskingMediaItemIndex,
21842189
/* repeatCurrentMediaItem= */ false);
21852190
}
21862191
}

libraries/exoplayer/src/test/java/androidx/media3/exoplayer/ExoPlayerTest.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16535,6 +16535,50 @@ public void setAudioOutputProvider_forwardsProviderToAudioSink() throws Exceptio
1653516535
player.release();
1653616536
}
1653716537

16538+
@Test
16539+
public void positionDiscontinuityFromInternalPlayer_whilePlaylistAlreadyCleared_isNotReported()
16540+
throws Exception {
16541+
FakeTimeline timeline = new FakeTimeline(/* windowCount= */ 1);
16542+
FakeMediaSource mediaSource =
16543+
new FakeMediaSource(timeline, ExoPlayerTestRunner.VIDEO_FORMAT) {
16544+
@Override
16545+
protected MediaPeriod createMediaPeriod(
16546+
MediaPeriodId id,
16547+
TrackGroupArray trackGroupArray,
16548+
Allocator allocator,
16549+
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
16550+
DrmSessionManager drmSessionManager,
16551+
DrmSessionEventListener.EventDispatcher drmEventDispatcher,
16552+
@Nullable TransferListener transferListener) {
16553+
FakeMediaPeriod mediaPeriod =
16554+
new FakeMediaPeriod(
16555+
trackGroupArray,
16556+
allocator,
16557+
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
16558+
mediaSourceEventDispatcher,
16559+
drmSessionManager,
16560+
drmEventDispatcher,
16561+
/* deferOnPrepared= */ false);
16562+
mediaPeriod.setSeekToUsOffset(10);
16563+
return mediaPeriod;
16564+
}
16565+
};
16566+
ExoPlayer player = parameterizeTestExoPlayerBuilder(new TestExoPlayerBuilder(context)).build();
16567+
Player.Listener listener = mock(Player.Listener.class);
16568+
player.addListener(listener);
16569+
player.setMediaSource(mediaSource);
16570+
player.prepare();
16571+
advance(player).untilState(Player.STATE_READY);
16572+
16573+
player.seekTo(10);
16574+
player.clearMediaItems();
16575+
advance(player).untilPendingCommandsAreFullyHandled();
16576+
player.release();
16577+
16578+
verify(listener, never())
16579+
.onPositionDiscontinuity(any(), any(), eq(DISCONTINUITY_REASON_SEEK_ADJUSTMENT));
16580+
}
16581+
1653816582
// Internal methods.
1653916583

1654016584
private void addWatchAsSystemFeature() {

0 commit comments

Comments
 (0)