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 1fc8d27614..f30cb8848c 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 @@ -553,7 +553,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; listener.onSourceInfoRefreshed(durationUs, isSeekable, isLive); } StatsDataSource dataSource = loadable.dataSource; - eventDispatcher.loadCompleted( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -561,7 +561,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; dataSource.getLastResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - dataSource.getBytesRead()), + dataSource.getBytesRead()); + loadErrorHandlingPolicy.onLoadCompleted(loadEventInfo); + eventDispatcher.loadCompleted( + loadEventInfo, C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, /* trackFormat= */ null, @@ -578,7 +581,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; public void onLoadCanceled( ExtractingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs, boolean released) { StatsDataSource dataSource = loadable.dataSource; - eventDispatcher.loadCanceled( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -586,7 +589,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; dataSource.getLastResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - dataSource.getBytesRead()), + dataSource.getBytesRead()); + loadErrorHandlingPolicy.onLoadCanceled(loadEventInfo); + eventDispatcher.loadCanceled( + loadEventInfo, C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, /* trackFormat= */ null, 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 3fcb91afbc..79d8fc73c8 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 @@ -218,7 +218,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; sampleData = Assertions.checkNotNull(loadable.sampleData); loadingFinished = true; StatsDataSource dataSource = loadable.dataSource; - eventDispatcher.loadCompleted( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -226,7 +226,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; dataSource.getLastResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - sampleSize), + sampleSize); + loadErrorHandlingPolicy.onLoadCompleted(loadEventInfo); + eventDispatcher.loadCompleted( + loadEventInfo, C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, format, @@ -240,7 +243,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; public void onLoadCanceled( SourceLoadable loadable, long elapsedRealtimeMs, long loadDurationMs, boolean released) { StatsDataSource dataSource = loadable.dataSource; - eventDispatcher.loadCanceled( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -248,7 +251,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; dataSource.getLastResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - dataSource.getBytesRead()), + dataSource.getBytesRead()); + loadErrorHandlingPolicy.onLoadCanceled(loadEventInfo); + eventDispatcher.loadCanceled( + loadEventInfo, C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, /* trackFormat= */ null, 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 2e275cd200..5d5138dbc0 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 @@ -405,7 +405,7 @@ public class ChunkSampleStream implements SampleStream, S @Override public void onLoadCompleted(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs) { chunkSource.onChunkLoadCompleted(loadable); - eventDispatcher.loadCompleted( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -413,7 +413,10 @@ public class ChunkSampleStream implements SampleStream, S loadable.getResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded()), + loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadCompleted(loadEventInfo); + eventDispatcher.loadCompleted( + loadEventInfo, loadable.type, primaryTrackType, loadable.trackFormat, @@ -427,7 +430,7 @@ public class ChunkSampleStream implements SampleStream, S @Override public void onLoadCanceled( Chunk loadable, long elapsedRealtimeMs, long loadDurationMs, boolean released) { - eventDispatcher.loadCanceled( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -435,7 +438,10 @@ public class ChunkSampleStream implements SampleStream, S loadable.getResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded()), + loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadCanceled(loadEventInfo); + eventDispatcher.loadCanceled( + loadEventInfo, loadable.type, primaryTrackType, loadable.trackFormat, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.java index 37922db0da..88c0c23f6c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/LoadErrorHandlingPolicy.java @@ -136,6 +136,22 @@ public interface LoadErrorHandlingPolicy { loadErrorInfo.errorCount); } + /** + * Called when the load associated with the given {@link LoadEventInfo} completes. + * + *

Implementations of this interface should avoid resource leaks by releasing resources + * associated to the given {@link LoadEventInfo#loadTaskId}. + */ + default void onLoadCompleted(LoadEventInfo loadEventInfo) {} + + /** + * Called when the load associated with the given {@link LoadEventInfo} is canceled. + * + *

Implementations of this interface should avoid resource leaks by releasing resources + * associated to the given {@link LoadEventInfo#loadTaskId}. + */ + default void onLoadCanceled(LoadEventInfo loadEventInfo) {} + /** * Returns the minimum number of times to retry a load in the case of a load error, before * propagating the error. 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 de2ce70de6..72e38729c9 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 @@ -754,7 +754,7 @@ public final class DashMediaSource extends BaseMediaSource { /* package */ void onManifestLoadCompleted(ParsingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs) { - manifestEventDispatcher.loadCompleted( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -762,8 +762,9 @@ public final class DashMediaSource extends BaseMediaSource { loadable.getResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded()), - loadable.type); + loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadCompleted(loadEventInfo); + manifestEventDispatcher.loadCompleted(loadEventInfo, loadable.type); DashManifest newManifest = loadable.getResult(); int oldPeriodCount = manifest == null ? 0 : manifest.getPeriodCount(); @@ -875,7 +876,7 @@ public final class DashMediaSource extends BaseMediaSource { /* package */ void onUtcTimestampLoadCompleted(ParsingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs) { - manifestEventDispatcher.loadCompleted( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -883,8 +884,9 @@ public final class DashMediaSource extends BaseMediaSource { loadable.getResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded()), - loadable.type); + loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadCompleted(loadEventInfo); + manifestEventDispatcher.loadCompleted(loadEventInfo, loadable.type); onUtcTimestampResolved(loadable.getResult() - elapsedRealtimeMs); } @@ -911,7 +913,7 @@ public final class DashMediaSource extends BaseMediaSource { /* package */ void onLoadCanceled(ParsingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs) { - manifestEventDispatcher.loadCanceled( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -919,8 +921,9 @@ public final class DashMediaSource extends BaseMediaSource { loadable.getResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded()), - loadable.type); + loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadCanceled(loadEventInfo); + manifestEventDispatcher.loadCanceled(loadEventInfo, loadable.type); } // Internal methods. 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 20ce9af3f0..334a80bd74 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 @@ -702,7 +702,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; @Override public void onLoadCompleted(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs) { chunkSource.onChunkLoadCompleted(loadable); - eventDispatcher.loadCompleted( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -710,7 +710,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; loadable.getResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded()), + loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadCompleted(loadEventInfo); + eventDispatcher.loadCompleted( + loadEventInfo, loadable.type, trackType, loadable.trackFormat, @@ -728,7 +731,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; @Override public void onLoadCanceled( Chunk loadable, long elapsedRealtimeMs, long loadDurationMs, boolean released) { - eventDispatcher.loadCanceled( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -736,7 +739,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; loadable.getResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded()), + loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadCanceled(loadEventInfo); + eventDispatcher.loadCanceled( + loadEventInfo, loadable.type, trackType, loadable.trackFormat, 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 d8f48e6f34..2071da3ebb 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 @@ -242,7 +242,7 @@ public final class DefaultHlsPlaylistTracker } else { primaryBundle.loadPlaylist(); } - eventDispatcher.loadCompleted( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -250,8 +250,9 @@ public final class DefaultHlsPlaylistTracker loadable.getResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded()), - C.DATA_TYPE_MANIFEST); + loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadCompleted(loadEventInfo); + eventDispatcher.loadCompleted(loadEventInfo, C.DATA_TYPE_MANIFEST); } @Override @@ -260,7 +261,7 @@ public final class DefaultHlsPlaylistTracker long elapsedRealtimeMs, long loadDurationMs, boolean released) { - eventDispatcher.loadCanceled( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -268,8 +269,9 @@ public final class DefaultHlsPlaylistTracker loadable.getResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded()), - C.DATA_TYPE_MANIFEST); + loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadCanceled(loadEventInfo); + eventDispatcher.loadCanceled(loadEventInfo, C.DATA_TYPE_MANIFEST); } @Override @@ -525,18 +527,19 @@ public final class DefaultHlsPlaylistTracker public void onLoadCompleted( ParsingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs) { HlsPlaylist result = loadable.getResult(); + LoadEventInfo loadEventInfo = + new LoadEventInfo( + loadable.loadTaskId, + loadable.dataSpec, + loadable.getUri(), + loadable.getResponseHeaders(), + elapsedRealtimeMs, + loadDurationMs, + loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadCompleted(loadEventInfo); if (result instanceof HlsMediaPlaylist) { processLoadedPlaylist((HlsMediaPlaylist) result, loadDurationMs); - eventDispatcher.loadCompleted( - new LoadEventInfo( - loadable.loadTaskId, - loadable.dataSpec, - loadable.getUri(), - loadable.getResponseHeaders(), - elapsedRealtimeMs, - loadDurationMs, - loadable.bytesLoaded()), - C.DATA_TYPE_MANIFEST); + eventDispatcher.loadCompleted(loadEventInfo, C.DATA_TYPE_MANIFEST); } else { playlistError = new ParserException("Loaded playlist has unexpected type."); } @@ -548,7 +551,7 @@ public final class DefaultHlsPlaylistTracker long elapsedRealtimeMs, long loadDurationMs, boolean released) { - eventDispatcher.loadCanceled( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -556,8 +559,9 @@ public final class DefaultHlsPlaylistTracker loadable.getResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded()), - C.DATA_TYPE_MANIFEST); + loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadCanceled(loadEventInfo); + eventDispatcher.loadCanceled(loadEventInfo, C.DATA_TYPE_MANIFEST); } @Override 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 2f3379af95..98104266da 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 @@ -621,7 +621,7 @@ public final class SsMediaSource extends BaseMediaSource @Override public void onLoadCompleted( ParsingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs) { - manifestEventDispatcher.loadCompleted( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -629,8 +629,9 @@ public final class SsMediaSource extends BaseMediaSource loadable.getResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded()), - loadable.type); + loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadCompleted(loadEventInfo); + manifestEventDispatcher.loadCompleted(loadEventInfo, loadable.type); manifest = loadable.getResult(); manifestLoadStartTimestamp = elapsedRealtimeMs - loadDurationMs; processManifest(); @@ -643,7 +644,7 @@ public final class SsMediaSource extends BaseMediaSource long elapsedRealtimeMs, long loadDurationMs, boolean released) { - manifestEventDispatcher.loadCanceled( + LoadEventInfo loadEventInfo = new LoadEventInfo( loadable.loadTaskId, loadable.dataSpec, @@ -651,8 +652,9 @@ public final class SsMediaSource extends BaseMediaSource loadable.getResponseHeaders(), elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded()), - loadable.type); + loadable.bytesLoaded()); + loadErrorHandlingPolicy.onLoadCanceled(loadEventInfo); + manifestEventDispatcher.loadCanceled(loadEventInfo, loadable.type); } @Override