diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 77a153f337..0eafc816c8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -2,6 +2,7 @@ ### dev-v2 (not yet released) ### +* Fix bug causing the retry of loading tasks that resulted in fatal errors. * DASH: Support negative @r values in segment timelines ([#1787](https://github.com/google/ExoPlayer/issues/1787)). * Add `allowedCapturePolicy` field to `AudioAttributes` wrapper to allow to diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java index 41fefafab7..7cb767854f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java @@ -337,7 +337,10 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; @Override public boolean continueLoading(long playbackPositionUs) { - if (loadingFinished || pendingDeferredRetry || (prepared && enabledTrackCount == 0)) { + if (loadingFinished + || loader.hasFatalError() + || pendingDeferredRetry + || (prepared && enabledTrackCount == 0)) { return false; } boolean continuedLoading = loadCondition.open(); @@ -422,6 +425,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; if (loader.isLoading()) { loader.cancelLoading(); } else { + loader.clearFatalError(); for (SampleQueue sampleQueue : sampleQueues) { sampleQueue.reset(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java index 62d873868e..8d41fbc73f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java @@ -147,7 +147,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Override public boolean continueLoading(long positionUs) { - if (loadingFinished || loader.isLoading()) { + if (loadingFinished || loader.isLoading() || loader.hasFatalError()) { return false; } DataSource dataSource = dataSourceFactory.createDataSource(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java index 6eaeefec6b..6817f294b2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java @@ -306,6 +306,7 @@ public class ChunkSampleStream implements SampleStream, S if (loader.isLoading()) { loader.cancelLoading(); } else { + loader.clearFatalError(); primarySampleQueue.reset(); for (SampleQueue embeddedSampleQueue : embeddedSampleQueues) { embeddedSampleQueue.reset(); @@ -520,7 +521,7 @@ public class ChunkSampleStream implements SampleStream, S @Override public boolean continueLoading(long positionUs) { - if (loadingFinished || loader.isLoading()) { + if (loadingFinished || loader.isLoading() || loader.hasFatalError()) { return false; } @@ -587,7 +588,7 @@ public class ChunkSampleStream implements SampleStream, S @Override public void reevaluateBuffer(long positionUs) { - if (loader.isLoading() || isPendingReset()) { + if (loader.isLoading() || loader.hasFatalError() || isPendingReset()) { return; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/Loader.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/Loader.java index b9032cb8e0..616859f047 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/Loader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/Loader.java @@ -213,6 +213,19 @@ public final class Loader implements LoaderErrorThrower { retryDelayMillis); } + /** + * Whether the last call to {@link #startLoading} resulted in a fatal error. Calling {@link + * #maybeThrowError()} will throw the fatal error. + */ + public boolean hasFatalError() { + return fatalError != null; + } + + /** Clears any stored fatal error. */ + public void clearFatalError() { + fatalError = null; + } + /** * Starts loading a {@link Loadable}. * diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java index f8bdfd5ec6..ac7dcc3737 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java @@ -1057,6 +1057,9 @@ public final class DashMediaSource extends BaseMediaSource { private void startLoadingManifest() { handler.removeCallbacks(refreshManifestRunnable); + if (loader.hasFatalError()) { + return; + } if (loader.isLoading()) { manifestLoadPending = true; return; 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 e4c756c6b6..e618d7f134 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 @@ -443,6 +443,7 @@ import java.util.Set; if (loader.isLoading()) { loader.cancelLoading(); } else { + loader.clearFatalError(); resetSampleQueues(); } return true; @@ -595,7 +596,7 @@ import java.util.Set; @Override public boolean continueLoading(long positionUs) { - if (loadingFinished || loader.isLoading()) { + if (loadingFinished || loader.isLoading() || loader.hasFatalError()) { return false; } 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 e7a072839e..f4fa2ad030 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 @@ -491,8 +491,8 @@ public final class DefaultHlsPlaylistTracker public void loadPlaylist() { blacklistUntilMs = 0; - if (loadPending || mediaPlaylistLoader.isLoading()) { - // Load already pending or in progress. Do nothing. + if (loadPending || mediaPlaylistLoader.isLoading() || mediaPlaylistLoader.hasFatalError()) { + // Load already pending, in progress, or a fatal error has been encountered. Do nothing. return; } long currentTimeMs = SystemClock.elapsedRealtime(); diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java index 9ddc7aa0f0..410f41caee 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java @@ -746,6 +746,9 @@ public final class SsMediaSource extends BaseMediaSource } private void startLoadingManifest() { + if (manifestLoader.hasFatalError()) { + return; + } ParsingLoadable loadable = new ParsingLoadable<>(manifestDataSource, manifestUri, C.DATA_TYPE_MANIFEST, manifestParser); long elapsedRealtimeMs =