diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 187c6114e6..05f0ff7d52 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -56,6 +56,10 @@ ([#9370](https://github.com/google/ExoPlayer/issues/9370)). * Fix base URL selection and load error handling when base URLs are shared across adaptation sets. +* HLS + * Fix bug where the player would get stuck if all download attempts fail + and would not raise an error to the application. + ([#9390](https://github.com/google/ExoPlayer/issues/9390)). * Remove deprecated symbols: * Remove `Renderer.VIDEO_SCALING_MODE_*` constants. Use identically named constants in `C` instead. diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java index 1f0f92d158..8f639518bc 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java @@ -555,6 +555,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; chunkSource.setIsTimestampMaster(isTimestampMaster); } + /** + * Called if an error is encountered while loading a playlist. + * + * @param playlistUrl The {@link Uri} of the playlist whose load encountered an error. + * @param loadErrorInfo The load error info. + * @param forceRetry Whether retry should be forced without considering exclusion. + * @return True if excluding did not encounter errors. False otherwise. + */ public boolean onPlaylistError(Uri playlistUrl, LoadErrorInfo loadErrorInfo, boolean forceRetry) { if (!chunkSource.obtainsChunksForPlaylist(playlistUrl)) { // Return early if the chunk source doesn't deliver chunks for the failing playlist. @@ -571,7 +579,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; exclusionDurationMs = fallbackSelection.exclusionDurationMs; } } - return chunkSource.onPlaylistError(playlistUrl, exclusionDurationMs); + // We must call ChunkSource.onPlaylistError in any case to give the chunk source the chance to + // mark the playlist as failing. + return chunkSource.onPlaylistError(playlistUrl, exclusionDurationMs) + && exclusionDurationMs != C.TIME_UNSET; } // SampleStream implementation.