From 8655429af725f4d2cea090665a34e81bc2c80a63 Mon Sep 17 00:00:00 2001 From: tonihei Date: Mon, 17 Jul 2023 18:38:24 +0100 Subject: [PATCH] Reset loading period after reading discontinuity that requires loading Reading a discontinuity from a media period indicates that a position reset is required. As part of this event, the media period may need further loading (e.g in a MergingMediaPeriod where one stream reported a discontinuity and the other need to reload from this position). This currently fails if the media periods was already fully loaded and we started loading further items in the playlist. As a result, playback is stuck forever. We can fix this by detecting that further loading is needed and resetting the loading period to the current one. The existing MergingPlaylistPlaybackTest already covers this case reliably, because it combines all the right preconditions (merging source, clipping to get a discontinuity and a playlist). PiperOrigin-RevId: 548735177 --- .../androidx/media3/exoplayer/ExoPlayerImplInternal.java | 7 +++++++ .../exoplayer/e2etest/MergingPlaylistPlaybackTest.java | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java index 4c0c840b4c..e02e208bcf 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java @@ -965,6 +965,13 @@ import java.util.concurrent.atomic.AtomicBoolean; ? playingPeriodHolder.mediaPeriod.readDiscontinuity() : C.TIME_UNSET; if (discontinuityPositionUs != C.TIME_UNSET) { + if (!playingPeriodHolder.isFullyBuffered()) { + // The discontinuity caused the period to not be fully buffered. Continue loading from this + // period again and discard all other periods we already started loading. + queue.removeAfter(playingPeriodHolder); + handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */ false); + maybeContinueLoading(); + } resetRendererPosition(discontinuityPositionUs); // A MediaPeriod may report a discontinuity at the current playback position to ensure the // renderers are flushed. Only report the discontinuity externally if the position changed. diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/MergingPlaylistPlaybackTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/MergingPlaylistPlaybackTest.java index e2180aa814..555a2f3419 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/MergingPlaylistPlaybackTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/MergingPlaylistPlaybackTest.java @@ -15,8 +15,6 @@ */ package androidx.media3.exoplayer.e2etest; -import static org.junit.Assume.assumeTrue; - import android.content.Context; import android.graphics.SurfaceTexture; import android.view.Surface; @@ -86,11 +84,6 @@ public final class MergingPlaylistPlaybackTest { @Test public void test() throws Exception { - // TODO: These cases are reliably failing due to a bug in ExoPlayerImplInternal that doesn't - // reset its loading period when reading a discontinuity and the current period requires more - // loading as a result. - assumeTrue(!firstItemVideoClipped); - Context applicationContext = ApplicationProvider.getApplicationContext(); CapturingRenderersFactory capturingRenderersFactory = new CapturingRenderersFactory(applicationContext);