From 5b8be42fa1c476c36b66adb6be20165188b2ae99 Mon Sep 17 00:00:00 2001 From: olly Date: Mon, 21 Jun 2021 23:42:35 +0100 Subject: [PATCH] HLS: Fix issue where a live event doesn't transition to STATE_ENDED The problem occurs when the primary media playlist URL switches from one whose latest snapshot has not yet got the ended tag, to one whose latest snapshot already has the ended tag. In this case: - We trigger a redundant load of the ended playlist. - When the redundant load completes, MediaPlaylistBundle.processLoadedPlaylist detects that the playlist is unchanged from the one it already has, and so doesn't call onPlaylistUpdated. - PrimaryPlaylistListener.onPrimaryPlaylistRefreshed is never called with the new primary. Hence the externally visible primary is still the one that hasn't ended. HlsMediaSource therefore thinks the event hasn't ended, which in turn prevents the player from transitioning to the ended state. This commit detects when the new primary already has the ended tag. In this case, we call onPrimaryPlaylistRefreshed directly and remove the unnecessary playlist load. Issue: #9067 #minor-release PiperOrigin-RevId: 380680532 --- RELEASENOTES.md | 3 +++ .../hls/playlist/DefaultHlsPlaylistTracker.java | 13 ++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9c7a68cec6e..2c1cfde1ead 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -20,6 +20,9 @@ ([#4083](https://github.com/google/ExoPlayer/issues/4083)). Such content is malformed and should be re-encoded. * HLS: + * Fix issue where playback of a live event could become stuck rather than + transitioning to `STATE_ENDED` when the event ends + ([#9067](https://github.com/google/ExoPlayer/issues/9067)). * Fix issue where a new initialization segment, as specified by an `EXT-X-MAP` tag in a media playlist, would not be loaded when encountered during playback diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java index 2a69f5c6af3..9ad1cb59349 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java @@ -339,9 +339,16 @@ private void maybeSetPrimaryUrl(Uri url) { return; } primaryMediaPlaylistUrl = url; - playlistBundles - .get(primaryMediaPlaylistUrl) - .loadPlaylistInternal(getRequestUriForPrimaryChange(url)); + MediaPlaylistBundle newPrimaryBundle = playlistBundles.get(primaryMediaPlaylistUrl); + @Nullable HlsMediaPlaylist newPrimarySnapshot = newPrimaryBundle.playlistSnapshot; + if (newPrimarySnapshot != null && newPrimarySnapshot.hasEndTag) { + primaryMediaPlaylistSnapshot = newPrimarySnapshot; + primaryPlaylistListener.onPrimaryPlaylistRefreshed(newPrimarySnapshot); + } else { + // The snapshot for the new primary media playlist URL may be stale. Defer updating the + // primary snapshot until after we've refreshed it. + newPrimaryBundle.loadPlaylistInternal(getRequestUriForPrimaryChange(url)); + } } private Uri getRequestUriForPrimaryChange(Uri newPrimaryPlaylistUri) {