diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 87dae7f0b9..63f8b2594d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -145,7 +145,10 @@ ([#7078](https://github.com/google/ExoPlayer/issues/7078)). * Remove generics from DRM components. * Downloads and caching: - * Merge downloads in `SegmentDownloader` to improve overall download speed + * Support passing an `Executor` to `DefaultDownloaderFactory` on which + data downloads are performed. + * Parallelize and merge downloads in `SegmentDownloader` to improve + overall download speed ([#5978](https://github.com/google/ExoPlayer/issues/5978)). * Support multiple non-overlapping write locks for the same key in `SimpleCache`. diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/DemoApplication.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/DemoApplication.java index 86978a1613..39e64f8025 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/DemoApplication.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/DemoApplication.java @@ -36,6 +36,7 @@ import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Util; import java.io.File; import java.io.IOException; +import java.util.concurrent.Executors; /** * Placeholder application to facilitate overriding Application methods for debugging and testing. @@ -129,7 +130,11 @@ public class DemoApplication extends MultiDexApplication { DOWNLOAD_TRACKER_ACTION_FILE, downloadIndex, /* addNewDownloadsAsCompleted= */ true); downloadManager = new DownloadManager( - this, getDatabaseProvider(), getDownloadCache(), buildHttpDataSourceFactory()); + this, + getDatabaseProvider(), + getDownloadCache(), + buildHttpDataSourceFactory(), + Executors.newFixedThreadPool(/* nThreads= */ 6)); downloadTracker = new DownloadTracker(/* context= */ this, buildDataSourceFactory(), downloadManager); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.java index 67e2bd8c77..f7b12a349e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.java @@ -79,7 +79,9 @@ public class DefaultDownloaderFactory implements DownloaderFactory { * * @param cacheDataSourceFactory A {@link CacheDataSource.Factory} for the cache into which * downloads will be written. + * @deprecated Use {@link #DefaultDownloaderFactory(CacheDataSource.Factory, Executor)}. */ + @Deprecated public DefaultDownloaderFactory(CacheDataSource.Factory cacheDataSourceFactory) { this(cacheDataSourceFactory, Runnable::run); } @@ -89,9 +91,10 @@ public class DefaultDownloaderFactory implements DownloaderFactory { * * @param cacheDataSourceFactory A {@link CacheDataSource.Factory} for the cache into which * downloads will be written. - * @param executor An {@link Executor} used to make requests for media being downloaded. Providing - * an {@link Executor} that uses multiple threads will speed up download tasks that can be - * split into smaller parts for parallel execution. + * @param executor An {@link Executor} used to download data. Passing {@code Runnable::run} will + * cause each download task to download data on its own thread. Passing an {@link Executor} + * that uses multiple threads will speed up download tasks that can be split into smaller + * parts for parallel execution. */ public DefaultDownloaderFactory( CacheDataSource.Factory cacheDataSourceFactory, Executor executor) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java index 5b80b64ad8..6b12ab3759 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java @@ -52,6 +52,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.Executor; /** * Manages downloads. @@ -197,16 +198,42 @@ public final class DownloadManager { * an {@link CacheEvictor} that will not evict downloaded content, for example {@link * NoOpCacheEvictor}. * @param upstreamFactory A {@link Factory} for creating {@link DataSource}s for downloading data. + * @deprecated Use {@link #DownloadManager(Context, DatabaseProvider, Cache, Factory, Executor)}. */ + @Deprecated public DownloadManager( Context context, DatabaseProvider databaseProvider, Cache cache, Factory upstreamFactory) { + this(context, databaseProvider, cache, upstreamFactory, Runnable::run); + } + + /** + * Constructs a {@link DownloadManager}. + * + * @param context Any context. + * @param databaseProvider Provides the SQLite database in which downloads are persisted. + * @param cache A cache to be used to store downloaded data. The cache should be configured with + * an {@link CacheEvictor} that will not evict downloaded content, for example {@link + * NoOpCacheEvictor}. + * @param upstreamFactory A {@link Factory} for creating {@link DataSource}s for downloading data. + * @param executor An {@link Executor} used to download data. Passing {@code Runnable::run} will + * cause each download task to download data on its own thread. Passing an {@link Executor} + * that uses multiple threads will speed up download tasks that can be split into smaller + * parts for parallel execution. + */ + public DownloadManager( + Context context, + DatabaseProvider databaseProvider, + Cache cache, + Factory upstreamFactory, + Executor executor) { this( context, new DefaultDownloadIndex(databaseProvider), new DefaultDownloaderFactory( new CacheDataSource.Factory() .setCache(cache) - .setUpstreamDataSourceFactory(upstreamFactory))); + .setUpstreamDataSourceFactory(upstreamFactory), + executor)); } /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/RunnableFutureTask.java b/library/core/src/main/java/com/google/android/exoplayer2/util/RunnableFutureTask.java index 9f06f40a67..9da5f09629 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/RunnableFutureTask.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/RunnableFutureTask.java @@ -159,6 +159,8 @@ public abstract class RunnableFutureTask implements Runn // Do nothing. } + // The return value is guaranteed to be non-null if and only if R is a non-null type, but there's + // no way to assert this. Suppress the warning instead. @SuppressWarnings("return.type.incompatible") @UnknownNull private R getResult() throws ExecutionException {