From d233c04582feba5ec3de1b6f0ab1377f4244a7bf Mon Sep 17 00:00:00 2001 From: bachinger Date: Wed, 20 May 2020 14:03:15 +0100 Subject: [PATCH] Simplify DownloadHelper PiperOrigin-RevId: 312467496 --- .../exoplayer2/demo/DownloadTracker.java | 27 +- library/core/proguard-rules.txt | 2 +- .../exoplayer2/offline/DownloadHelper.java | 601 +++++++++--------- .../offline/DownloadHelperTest.java | 20 +- .../dash/offline/DownloadHelperTest.java | 21 +- .../hls/offline/DownloadHelperTest.java | 27 +- .../offline/DownloadHelperTest.java | 21 +- 7 files changed, 342 insertions(+), 377 deletions(-) diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/DownloadTracker.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/DownloadTracker.java index 3127ed95e9..a36635acb0 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/DownloadTracker.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/DownloadTracker.java @@ -24,7 +24,6 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.FragmentManager; -import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.offline.Download; @@ -106,7 +105,9 @@ public class DownloadTracker { } startDownloadDialogHelper = new StartDownloadDialogHelper( - fragmentManager, getDownloadHelper(mediaItem, renderersFactory), mediaItem); + fragmentManager, + DownloadHelper.forMediaItem(context, mediaItem, renderersFactory, dataSourceFactory), + mediaItem); } } @@ -121,28 +122,6 @@ public class DownloadTracker { } } - private DownloadHelper getDownloadHelper(MediaItem mediaItem, RenderersFactory renderersFactory) { - MediaItem.PlaybackProperties playbackProperties = checkNotNull(mediaItem.playbackProperties); - @C.ContentType - int type = - Util.inferContentTypeWithMimeType(playbackProperties.uri, playbackProperties.mimeType); - switch (type) { - case C.TYPE_DASH: - return DownloadHelper.forDash( - context, playbackProperties.uri, dataSourceFactory, renderersFactory); - case C.TYPE_SS: - return DownloadHelper.forSmoothStreaming( - context, playbackProperties.uri, dataSourceFactory, renderersFactory); - case C.TYPE_HLS: - return DownloadHelper.forHls( - context, playbackProperties.uri, dataSourceFactory, renderersFactory); - case C.TYPE_OTHER: - return DownloadHelper.forProgressive(context, playbackProperties.uri); - default: - throw new IllegalStateException("Unsupported type: " + type); - } - } - private class DownloadManagerListener implements DownloadManager.Listener { @Override diff --git a/library/core/proguard-rules.txt b/library/core/proguard-rules.txt index cbeb74cf6c..9578bd869b 100644 --- a/library/core/proguard-rules.txt +++ b/library/core/proguard-rules.txt @@ -62,7 +62,7 @@ (android.net.Uri, java.util.List, com.google.android.exoplayer2.upstream.cache.CacheDataSource.Factory, java.util.concurrent.Executor); } -# Constructors accessed via reflection in DefaultMediaSourceFactory and DownloadHelper +# Constructors accessed via reflection in DefaultMediaSourceFactory -dontnote com.google.android.exoplayer2.source.dash.DashMediaSource$Factory -keepclasseswithmembers class com.google.android.exoplayer2.source.dash.DashMediaSource$Factory { (com.google.android.exoplayer2.upstream.DataSource$Factory); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java index 8e50d70020..11933e7834 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java @@ -15,6 +15,9 @@ */ package com.google.android.exoplayer2.offline; +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; +import static com.google.android.exoplayer2.util.Util.castNonNull; + import android.content.Context; import android.net.Uri; import android.os.Handler; @@ -24,18 +27,18 @@ import android.util.SparseIntArray; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; +import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.audio.AudioRendererEventListener; import com.google.android.exoplayer2.drm.DrmSessionManager; +import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller; -import com.google.android.exoplayer2.source.MediaSourceFactory; -import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.chunk.MediaChunk; @@ -50,14 +53,13 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DataSource.Factory; import com.google.android.exoplayer2.upstream.DefaultAllocator; import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.video.VideoRendererEventListener; import java.io.IOException; -import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -144,18 +146,6 @@ public final class DownloadHelper { /** Thrown at an attempt to download live content. */ public static class LiveContentUnsupportedException extends IOException {} - @Nullable - private static final Constructor DASH_FACTORY_CONSTRUCTOR = - getConstructor("com.google.android.exoplayer2.source.dash.DashMediaSource$Factory"); - - @Nullable - private static final Constructor SS_FACTORY_CONSTRUCTOR = - getConstructor("com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory"); - - @Nullable - private static final Constructor HLS_FACTORY_CONSTRUCTOR = - getConstructor("com.google.android.exoplayer2.source.hls.HlsMediaSource$Factory"); - /** * Extracts renderer capabilities for the renderers created by the provided renderers factory. * @@ -178,262 +168,264 @@ public final class DownloadHelper { return capabilities; } - /** @deprecated Use {@link #forProgressive(Context, Uri)} */ + /** @deprecated Use {@link #forMediaItem(Context, MediaItem)} */ @Deprecated - @SuppressWarnings("deprecation") - public static DownloadHelper forProgressive(Uri uri) { - return forProgressive(uri, /* cacheKey= */ null); - } - - /** - * Creates a {@link DownloadHelper} for progressive streams. - * - * @param context Any {@link Context}. - * @param uri A stream {@link Uri}. - * @return A {@link DownloadHelper} for progressive streams. - */ public static DownloadHelper forProgressive(Context context, Uri uri) { - return forProgressive(context, uri, /* cacheKey= */ null); + return forMediaItem(context, new MediaItem.Builder().setUri(uri).build()); } - /** @deprecated Use {@link #forProgressive(Context, Uri, String)} */ + /** @deprecated Use {@link #forMediaItem(Context, MediaItem)} */ @Deprecated - public static DownloadHelper forProgressive(Uri uri, @Nullable String cacheKey) { - return new DownloadHelper( - DownloadRequest.TYPE_PROGRESSIVE, - uri, - cacheKey, - /* mediaSource= */ null, - DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT, - /* rendererCapabilities= */ new RendererCapabilities[0]); - } - - /** - * Creates a {@link DownloadHelper} for progressive streams. - * - * @param context Any {@link Context}. - * @param uri A stream {@link Uri}. - * @param cacheKey An optional cache key. - * @return A {@link DownloadHelper} for progressive streams. - */ public static DownloadHelper forProgressive(Context context, Uri uri, @Nullable String cacheKey) { - return new DownloadHelper( - DownloadRequest.TYPE_PROGRESSIVE, + return forMediaItem( + context, new MediaItem.Builder().setUri(uri).setCustomCacheKey(cacheKey).build()); + } + + /** + * @deprecated Use {@link #forMediaItem(MediaItem, Parameters, RenderersFactory, + * DataSource.Factory)} instead. + */ + @SuppressWarnings("deprecation") + @Deprecated + public static DownloadHelper forDash( + Context context, + Uri uri, + DataSource.Factory dataSourceFactory, + RenderersFactory renderersFactory) { + return forDash( uri, - cacheKey, - /* mediaSource= */ null, + dataSourceFactory, + renderersFactory, + /* drmSessionManager= */ null, + getDefaultTrackSelectorParameters(context)); + } + + /** + * @deprecated Use {@link #forMediaItem(MediaItem, Parameters, RenderersFactory, + * DataSource.Factory, DrmSessionManager)} instead. + */ + @Deprecated + public static DownloadHelper forDash( + Uri uri, + DataSource.Factory dataSourceFactory, + RenderersFactory renderersFactory, + @Nullable DrmSessionManager drmSessionManager, + DefaultTrackSelector.Parameters trackSelectorParameters) { + return forMediaItem( + new MediaItem.Builder().setUri(uri).setMimeType(MimeTypes.APPLICATION_MPD).build(), + trackSelectorParameters, + renderersFactory, + dataSourceFactory, + drmSessionManager); + } + + /** + * @deprecated Use {@link #forMediaItem(MediaItem, Parameters, RenderersFactory, + * DataSource.Factory)} instead. + */ + @SuppressWarnings("deprecation") + @Deprecated + public static DownloadHelper forHls( + Context context, + Uri uri, + DataSource.Factory dataSourceFactory, + RenderersFactory renderersFactory) { + return forHls( + uri, + dataSourceFactory, + renderersFactory, + /* drmSessionManager= */ null, + getDefaultTrackSelectorParameters(context)); + } + + /** + * @deprecated Use {@link #forMediaItem(MediaItem, Parameters, RenderersFactory, + * DataSource.Factory, DrmSessionManager)} instead. + */ + @Deprecated + public static DownloadHelper forHls( + Uri uri, + DataSource.Factory dataSourceFactory, + RenderersFactory renderersFactory, + @Nullable DrmSessionManager drmSessionManager, + DefaultTrackSelector.Parameters trackSelectorParameters) { + return forMediaItem( + new MediaItem.Builder().setUri(uri).setMimeType(MimeTypes.APPLICATION_M3U8).build(), + trackSelectorParameters, + renderersFactory, + dataSourceFactory, + drmSessionManager); + } + + /** + * @deprecated Use {@link #forMediaItem(MediaItem, Parameters, RenderersFactory, + * DataSource.Factory)} instead. + */ + @SuppressWarnings("deprecation") + @Deprecated + public static DownloadHelper forSmoothStreaming( + Uri uri, DataSource.Factory dataSourceFactory, RenderersFactory renderersFactory) { + return forSmoothStreaming( + uri, + dataSourceFactory, + renderersFactory, + /* drmSessionManager= */ null, + DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT); + } + + /** + * @deprecated Use {@link #forMediaItem(MediaItem, Parameters, RenderersFactory, + * DataSource.Factory)} instead. + */ + @SuppressWarnings("deprecation") + @Deprecated + public static DownloadHelper forSmoothStreaming( + Context context, + Uri uri, + DataSource.Factory dataSourceFactory, + RenderersFactory renderersFactory) { + return forSmoothStreaming( + uri, + dataSourceFactory, + renderersFactory, + /* drmSessionManager= */ null, + getDefaultTrackSelectorParameters(context)); + } + + /** + * @deprecated Use {@link #forMediaItem(MediaItem, Parameters, RenderersFactory, + * DataSource.Factory, DrmSessionManager)} instead. + */ + @Deprecated + public static DownloadHelper forSmoothStreaming( + Uri uri, + DataSource.Factory dataSourceFactory, + RenderersFactory renderersFactory, + @Nullable DrmSessionManager drmSessionManager, + DefaultTrackSelector.Parameters trackSelectorParameters) { + return forMediaItem( + new MediaItem.Builder().setUri(uri).setMimeType(MimeTypes.APPLICATION_SS).build(), + trackSelectorParameters, + renderersFactory, + dataSourceFactory, + drmSessionManager); + } + + /** + * Creates a {@link DownloadHelper} for the given progressive media item. + * + * @param context The context. + * @param mediaItem A {@link MediaItem}. + * @return A {@link DownloadHelper} for progressive streams. + * @throws IllegalStateException If the media item is of type DASH, HLS or SmoothStreaming. + */ + public static DownloadHelper forMediaItem(Context context, MediaItem mediaItem) { + Assertions.checkArgument( + DownloadRequest.TYPE_PROGRESSIVE.equals( + getDownloadType(checkNotNull(mediaItem.playbackProperties)))); + return forMediaItem( + mediaItem, getDefaultTrackSelectorParameters(context), - /* rendererCapabilities= */ new RendererCapabilities[0]); - } - - /** @deprecated Use {@link #forDash(Context, Uri, Factory, RenderersFactory)} */ - @Deprecated - public static DownloadHelper forDash( - Uri uri, DataSource.Factory dataSourceFactory, RenderersFactory renderersFactory) { - return forDash( - uri, - dataSourceFactory, - renderersFactory, - /* drmSessionManager= */ null, - DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT); + /* renderersFactory= */ null, + /* dataSourceFactory= */ null, + /* drmSessionManager= */ null); } /** - * Creates a {@link DownloadHelper} for DASH streams. + * Creates a {@link DownloadHelper} for the given media item. * - * @param context Any {@link Context}. - * @param uri A manifest {@link Uri}. - * @param dataSourceFactory A {@link DataSource.Factory} used to load the manifest. + * @param context The context. + * @param mediaItem A {@link MediaItem}. * @param renderersFactory A {@link RenderersFactory} creating the renderers for which tracks are * selected. - * @return A {@link DownloadHelper} for DASH streams. - * @throws IllegalStateException If the DASH module is missing. + * @param dataSourceFactory A {@link DataSource.Factory} used to load the manifest for adaptive + * streams. This argument is required for adaptive streams and ignored for progressive + * streams. + * @return A {@link DownloadHelper}. + * @throws IllegalStateException If the the corresponding module is missing for DASH, HLS or + * SmoothStreaming media items. + * @throws IllegalArgumentException If the {@code dataSourceFactory} is null for adaptive streams. */ - public static DownloadHelper forDash( + public static DownloadHelper forMediaItem( Context context, - Uri uri, - DataSource.Factory dataSourceFactory, - RenderersFactory renderersFactory) { - return forDash( - uri, - dataSourceFactory, + MediaItem mediaItem, + @Nullable RenderersFactory renderersFactory, + @Nullable DataSource.Factory dataSourceFactory) { + return forMediaItem( + mediaItem, + getDefaultTrackSelectorParameters(context), renderersFactory, - /* drmSessionManager= */ null, - getDefaultTrackSelectorParameters(context)); + dataSourceFactory, + /* drmSessionManager= */ null); } /** - * Creates a {@link DownloadHelper} for DASH streams. + * Creates a {@link DownloadHelper} for the given media item. * - * @param uri A manifest {@link Uri}. - * @param dataSourceFactory A {@link DataSource.Factory} used to load the manifest. + * @param mediaItem A {@link MediaItem}. * @param renderersFactory A {@link RenderersFactory} creating the renderers for which tracks are * selected. - * @param drmSessionManager An optional {@link DrmSessionManager}. Used to help determine which - * tracks can be selected. * @param trackSelectorParameters {@link DefaultTrackSelector.Parameters} for selecting tracks for * downloading. - * @return A {@link DownloadHelper} for DASH streams. - * @throws IllegalStateException If the DASH module is missing. + * @param dataSourceFactory A {@link DataSource.Factory} used to load the manifest for adaptive + * streams. This argument is required for adaptive streams and ignored for progressive + * streams. + * @return A {@link DownloadHelper}. + * @throws IllegalStateException If the the corresponding module is missing for DASH, HLS or + * SmoothStreaming media items. + * @throws IllegalArgumentException If the {@code dataSourceFactory} is null for adaptive streams. */ - public static DownloadHelper forDash( - Uri uri, - DataSource.Factory dataSourceFactory, - RenderersFactory renderersFactory, - @Nullable DrmSessionManager drmSessionManager, - DefaultTrackSelector.Parameters trackSelectorParameters) { - return new DownloadHelper( - DownloadRequest.TYPE_DASH, - uri, - /* cacheKey= */ null, - createMediaSourceInternal( - DASH_FACTORY_CONSTRUCTOR, - uri, - dataSourceFactory, - drmSessionManager, - /* streamKeys= */ null), + public static DownloadHelper forMediaItem( + MediaItem mediaItem, + DefaultTrackSelector.Parameters trackSelectorParameters, + @Nullable RenderersFactory renderersFactory, + @Nullable DataSource.Factory dataSourceFactory) { + return forMediaItem( + mediaItem, trackSelectorParameters, - getRendererCapabilities(renderersFactory)); - } - - /** @deprecated Use {@link #forHls(Context, Uri, Factory, RenderersFactory)} */ - @Deprecated - public static DownloadHelper forHls( - Uri uri, DataSource.Factory dataSourceFactory, RenderersFactory renderersFactory) { - return forHls( - uri, - dataSourceFactory, renderersFactory, - /* drmSessionManager= */ null, - DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT); + dataSourceFactory, + /* drmSessionManager= */ null); } /** - * Creates a {@link DownloadHelper} for HLS streams. + * Creates a {@link DownloadHelper} for the given media item. * - * @param context Any {@link Context}. - * @param uri A playlist {@link Uri}. - * @param dataSourceFactory A {@link DataSource.Factory} used to load the playlist. + * @param mediaItem A {@link MediaItem}. * @param renderersFactory A {@link RenderersFactory} creating the renderers for which tracks are * selected. - * @return A {@link DownloadHelper} for HLS streams. - * @throws IllegalStateException If the HLS module is missing. - */ - public static DownloadHelper forHls( - Context context, - Uri uri, - DataSource.Factory dataSourceFactory, - RenderersFactory renderersFactory) { - return forHls( - uri, - dataSourceFactory, - renderersFactory, - /* drmSessionManager= */ null, - getDefaultTrackSelectorParameters(context)); - } - - /** - * Creates a {@link DownloadHelper} for HLS streams. - * - * @param uri A playlist {@link Uri}. - * @param dataSourceFactory A {@link DataSource.Factory} used to load the playlist. - * @param renderersFactory A {@link RenderersFactory} creating the renderers for which tracks are - * selected. - * @param drmSessionManager An optional {@link DrmSessionManager}. Used to help determine which - * tracks can be selected. * @param trackSelectorParameters {@link DefaultTrackSelector.Parameters} for selecting tracks for * downloading. - * @return A {@link DownloadHelper} for HLS streams. - * @throws IllegalStateException If the HLS module is missing. - */ - public static DownloadHelper forHls( - Uri uri, - DataSource.Factory dataSourceFactory, - RenderersFactory renderersFactory, - @Nullable DrmSessionManager drmSessionManager, - DefaultTrackSelector.Parameters trackSelectorParameters) { - return new DownloadHelper( - DownloadRequest.TYPE_HLS, - uri, - /* cacheKey= */ null, - createMediaSourceInternal( - HLS_FACTORY_CONSTRUCTOR, - uri, - dataSourceFactory, - drmSessionManager, - /* streamKeys= */ null), - trackSelectorParameters, - getRendererCapabilities(renderersFactory)); - } - - /** @deprecated Use {@link #forSmoothStreaming(Context, Uri, Factory, RenderersFactory)} */ - @Deprecated - public static DownloadHelper forSmoothStreaming( - Uri uri, DataSource.Factory dataSourceFactory, RenderersFactory renderersFactory) { - return forSmoothStreaming( - uri, - dataSourceFactory, - renderersFactory, - /* drmSessionManager= */ null, - DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT); - } - - /** - * Creates a {@link DownloadHelper} for SmoothStreaming streams. - * - * @param context Any {@link Context}. - * @param uri A manifest {@link Uri}. - * @param dataSourceFactory A {@link DataSource.Factory} used to load the manifest. - * @param renderersFactory A {@link RenderersFactory} creating the renderers for which tracks are - * selected. - * @return A {@link DownloadHelper} for SmoothStreaming streams. - * @throws IllegalStateException If the SmoothStreaming module is missing. - */ - public static DownloadHelper forSmoothStreaming( - Context context, - Uri uri, - DataSource.Factory dataSourceFactory, - RenderersFactory renderersFactory) { - return forSmoothStreaming( - uri, - dataSourceFactory, - renderersFactory, - /* drmSessionManager= */ null, - getDefaultTrackSelectorParameters(context)); - } - - /** - * Creates a {@link DownloadHelper} for SmoothStreaming streams. - * - * @param uri A manifest {@link Uri}. - * @param dataSourceFactory A {@link DataSource.Factory} used to load the manifest. - * @param renderersFactory A {@link RenderersFactory} creating the renderers for which tracks are - * selected. + * @param dataSourceFactory A {@link DataSource.Factory} used to load the manifest for adaptive + * streams. This argument is required for adaptive streams and ignored for progressive + * streams. * @param drmSessionManager An optional {@link DrmSessionManager}. Used to help determine which * tracks can be selected. - * @param trackSelectorParameters {@link DefaultTrackSelector.Parameters} for selecting tracks for - * downloading. - * @return A {@link DownloadHelper} for SmoothStreaming streams. - * @throws IllegalStateException If the SmoothStreaming module is missing. + * @return A {@link DownloadHelper}. + * @throws IllegalStateException If the the corresponding module is missing for DASH, HLS or + * SmoothStreaming media items. + * @throws IllegalArgumentException If the {@code dataSourceFactory} is null for adaptive streams. */ - public static DownloadHelper forSmoothStreaming( - Uri uri, - DataSource.Factory dataSourceFactory, - RenderersFactory renderersFactory, - @Nullable DrmSessionManager drmSessionManager, - DefaultTrackSelector.Parameters trackSelectorParameters) { + public static DownloadHelper forMediaItem( + MediaItem mediaItem, + DefaultTrackSelector.Parameters trackSelectorParameters, + @Nullable RenderersFactory renderersFactory, + @Nullable DataSource.Factory dataSourceFactory, + @Nullable DrmSessionManager drmSessionManager) { + boolean isProgressive = + DownloadRequest.TYPE_PROGRESSIVE.equals( + getDownloadType(checkNotNull(mediaItem.playbackProperties))); + Assertions.checkArgument(isProgressive || dataSourceFactory != null); return new DownloadHelper( - DownloadRequest.TYPE_SS, - uri, - /* cacheKey= */ null, - createMediaSourceInternal( - SS_FACTORY_CONSTRUCTOR, - uri, - dataSourceFactory, - drmSessionManager, - /* streamKeys= */ null), + mediaItem, + isProgressive + ? null + : createMediaSourceInternal( + mediaItem, castNonNull(dataSourceFactory), drmSessionManager), trackSelectorParameters, - getRendererCapabilities(renderersFactory)); + renderersFactory != null + ? getRendererCapabilities(renderersFactory) + : new RendererCapabilities[0]); } /** @@ -459,35 +451,18 @@ public final class DownloadHelper { DownloadRequest downloadRequest, DataSource.Factory dataSourceFactory, @Nullable DrmSessionManager drmSessionManager) { - @Nullable Constructor constructor; - switch (downloadRequest.type) { - case DownloadRequest.TYPE_DASH: - constructor = DASH_FACTORY_CONSTRUCTOR; - break; - case DownloadRequest.TYPE_SS: - constructor = SS_FACTORY_CONSTRUCTOR; - break; - case DownloadRequest.TYPE_HLS: - constructor = HLS_FACTORY_CONSTRUCTOR; - break; - case DownloadRequest.TYPE_PROGRESSIVE: - return new ProgressiveMediaSource.Factory(dataSourceFactory) - .setCustomCacheKey(downloadRequest.customCacheKey) - .createMediaSource(downloadRequest.uri); - default: - throw new IllegalStateException("Unsupported type: " + downloadRequest.type); - } return createMediaSourceInternal( - constructor, - downloadRequest.uri, + new MediaItem.Builder() + .setUri(downloadRequest.uri) + .setCustomCacheKey(downloadRequest.customCacheKey) + .setMimeType(getMimeType(downloadRequest.type)) + .setStreamKeys(downloadRequest.streamKeys) + .build(), dataSourceFactory, - drmSessionManager, - downloadRequest.streamKeys); + drmSessionManager); } - private final String downloadType; - private final Uri uri; - @Nullable private final String cacheKey; + private final MediaItem.PlaybackProperties playbackProperties; @Nullable private final MediaSource mediaSource; private final DefaultTrackSelector trackSelector; private final RendererCapabilities[] rendererCapabilities; @@ -506,9 +481,7 @@ public final class DownloadHelper { /** * Creates download helper. * - * @param downloadType A download type. This value will be used as {@link DownloadRequest#type}. - * @param uri A {@link Uri}. - * @param cacheKey An optional cache key. + * @param mediaItem The media item. * @param mediaSource A {@link MediaSource} for which tracks are selected, or null if no track * selection needs to be made. * @param trackSelectorParameters {@link DefaultTrackSelector.Parameters} for selecting tracks for @@ -517,15 +490,11 @@ public final class DownloadHelper { * are selected. */ public DownloadHelper( - String downloadType, - Uri uri, - @Nullable String cacheKey, + MediaItem mediaItem, @Nullable MediaSource mediaSource, DefaultTrackSelector.Parameters trackSelectorParameters, RendererCapabilities[] rendererCapabilities) { - this.downloadType = downloadType; - this.uri = uri; - this.cacheKey = cacheKey; + this.playbackProperties = checkNotNull(mediaItem.playbackProperties); this.mediaSource = mediaSource; this.trackSelector = new DefaultTrackSelector(trackSelectorParameters, new DownloadTrackSelection.Factory()); @@ -766,7 +735,7 @@ public final class DownloadHelper { * @return The built {@link DownloadRequest}. */ public DownloadRequest getDownloadRequest(@Nullable byte[] data) { - return getDownloadRequest(uri.toString(), data); + return getDownloadRequest(playbackProperties.uri.toString(), data); } /** @@ -778,9 +747,15 @@ public final class DownloadHelper { * @return The built {@link DownloadRequest}. */ public DownloadRequest getDownloadRequest(String id, @Nullable byte[] data) { + String downloadType = getDownloadType(playbackProperties); if (mediaSource == null) { return new DownloadRequest( - id, downloadType, uri, /* streamKeys= */ Collections.emptyList(), cacheKey, data); + id, + downloadType, + playbackProperties.uri, + /* streamKeys= */ Collections.emptyList(), + playbackProperties.customCacheKey, + data); } assertPreparedWithMedia(); List streamKeys = new ArrayList<>(); @@ -794,15 +769,21 @@ public final class DownloadHelper { } streamKeys.addAll(mediaPreparer.mediaPeriods[periodIndex].getStreamKeys(allSelections)); } - return new DownloadRequest(id, downloadType, uri, streamKeys, cacheKey, data); + return new DownloadRequest( + id, + downloadType, + playbackProperties.uri, + streamKeys, + playbackProperties.customCacheKey, + data); } // Initialization of array of Lists. @SuppressWarnings("unchecked") private void onMediaPrepared() { - Assertions.checkNotNull(mediaPreparer); - Assertions.checkNotNull(mediaPreparer.mediaPeriods); - Assertions.checkNotNull(mediaPreparer.timeline); + checkNotNull(mediaPreparer); + checkNotNull(mediaPreparer.mediaPeriods); + checkNotNull(mediaPreparer.timeline); int periodCount = mediaPreparer.mediaPeriods.length; int rendererCount = rendererCapabilities.length; trackSelectionsByPeriodAndRenderer = @@ -822,16 +803,14 @@ public final class DownloadHelper { trackGroupArrays[i] = mediaPreparer.mediaPeriods[i].getTrackGroups(); TrackSelectorResult trackSelectorResult = runTrackSelection(/* periodIndex= */ i); trackSelector.onSelectionActivated(trackSelectorResult.info); - mappedTrackInfos[i] = Assertions.checkNotNull(trackSelector.getCurrentMappedTrackInfo()); + mappedTrackInfos[i] = checkNotNull(trackSelector.getCurrentMappedTrackInfo()); } setPreparedWithMedia(); - Assertions.checkNotNull(callbackHandler) - .post(() -> Assertions.checkNotNull(callback).onPrepared(this)); + checkNotNull(callbackHandler).post(() -> checkNotNull(callback).onPrepared(this)); } private void onMediaPreparationFailed(IOException error) { - Assertions.checkNotNull(callbackHandler) - .post(() -> Assertions.checkNotNull(callback).onPrepareError(this, error)); + checkNotNull(callbackHandler).post(() -> checkNotNull(callback).onPrepareError(this, error)); } @RequiresNonNull({ @@ -921,43 +900,43 @@ public final class DownloadHelper { } } - @Nullable - private static Constructor getConstructor(String className) { - try { - // LINT.IfChange - Class factoryClazz = - Class.forName(className).asSubclass(MediaSourceFactory.class); - return factoryClazz.getConstructor(Factory.class); - // LINT.ThenChange(../../../../../../../../proguard-rules.txt) - } catch (ClassNotFoundException e) { - // Expected if the app was built without the respective module. - return null; - } catch (NoSuchMethodException e) { - // Something is wrong with the library or the proguard configuration. - throw new IllegalStateException(e); + private static MediaSource createMediaSourceInternal( + MediaItem mediaItem, + DataSource.Factory dataSourceFactory, + @Nullable DrmSessionManager drmSessionManager) { + return new DefaultMediaSourceFactory(dataSourceFactory, /* adSupportProvider= */ null) + .setDrmSessionManager(drmSessionManager) + .createMediaSource(mediaItem); + } + + private static String getDownloadType(MediaItem.PlaybackProperties playbackProperties) { + int contentType = + Util.inferContentTypeWithMimeType(playbackProperties.uri, playbackProperties.mimeType); + switch (contentType) { + case C.TYPE_DASH: + return DownloadRequest.TYPE_DASH; + case C.TYPE_HLS: + return DownloadRequest.TYPE_HLS; + case C.TYPE_SS: + return DownloadRequest.TYPE_SS; + default: + return DownloadRequest.TYPE_PROGRESSIVE; } } - private static MediaSource createMediaSourceInternal( - @Nullable Constructor constructor, - Uri uri, - Factory dataSourceFactory, - @Nullable DrmSessionManager drmSessionManager, - @Nullable List streamKeys) { - if (constructor == null) { - throw new IllegalStateException("Module missing to create media source."); - } - try { - MediaSourceFactory factory = constructor.newInstance(dataSourceFactory); - if (drmSessionManager != null) { - factory.setDrmSessionManager(drmSessionManager); - } - if (streamKeys != null) { - factory.setStreamKeys(streamKeys); - } - return Assertions.checkNotNull(factory.createMediaSource(uri)); - } catch (Exception e) { - throw new IllegalStateException("Failed to instantiate media source.", e); + @Nullable + private static String getMimeType(String downloadType) { + switch (downloadType) { + case DownloadRequest.TYPE_DASH: + return MimeTypes.APPLICATION_MPD; + case DownloadRequest.TYPE_HLS: + return MimeTypes.APPLICATION_M3U8; + case DownloadRequest.TYPE_SS: + return MimeTypes.APPLICATION_SS; + case DownloadRequest.TYPE_PROGRESSIVE: + return null; + default: + throw new IllegalArgumentException(); } } @@ -1115,7 +1094,7 @@ public final class DownloadHelper { return true; case DOWNLOAD_HELPER_CALLBACK_MESSAGE_FAILED: release(); - downloadHelper.onMediaPreparationFailed((IOException) Util.castNonNull(msg.obj)); + downloadHelper.onMediaPreparationFailed((IOException) castNonNull(msg.obj)); return true; default: return false; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadHelperTest.java b/library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadHelperTest.java index 5fa9ae082f..b8edff6f60 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadHelperTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadHelperTest.java @@ -18,11 +18,11 @@ package com.google.android.exoplayer2.offline; import static com.google.common.truth.Truth.assertThat; import static org.robolectric.shadows.ShadowBaseLooper.shadowMainLooper; -import android.net.Uri; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.Timeline; @@ -59,8 +59,6 @@ import org.robolectric.annotation.LooperMode; @LooperMode(LooperMode.Mode.PAUSED) public class DownloadHelperTest { - private static final String TEST_DOWNLOAD_TYPE = "downloadType"; - private static final String TEST_CACHE_KEY = "cacheKey"; private static final Object TEST_MANIFEST = new Object(); private static final Timeline TEST_TIMELINE = new FakeTimeline( @@ -86,7 +84,7 @@ public class DownloadHelperTest { private static TrackGroupArray trackGroupArraySingle; private static TrackGroupArray[] trackGroupArrays; - private static Uri testUri; + private static MediaItem testMediaItem; private DownloadHelper downloadHelper; @@ -114,7 +112,8 @@ public class DownloadHelperTest { trackGroupArrays = new TrackGroupArray[] {trackGroupArrayAll, trackGroupArraySingle}; - testUri = Uri.parse("http://test.uri"); + testMediaItem = + new MediaItem.Builder().setUri("http://test.uri").setCustomCacheKey("cacheKey").build(); } @Before @@ -128,9 +127,7 @@ public class DownloadHelperTest { downloadHelper = new DownloadHelper( - TEST_DOWNLOAD_TYPE, - testUri, - TEST_CACHE_KEY, + testMediaItem, new TestMediaSource(), DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT, DownloadHelper.getRendererCapabilities(renderersFactory)); @@ -414,9 +411,10 @@ public class DownloadHelperTest { DownloadRequest downloadRequest = downloadHelper.getDownloadRequest(data); - assertThat(downloadRequest.type).isEqualTo(TEST_DOWNLOAD_TYPE); - assertThat(downloadRequest.uri).isEqualTo(testUri); - assertThat(downloadRequest.customCacheKey).isEqualTo(TEST_CACHE_KEY); + assertThat(downloadRequest.type).isEqualTo(DownloadRequest.TYPE_PROGRESSIVE); + assertThat(downloadRequest.uri).isEqualTo(testMediaItem.playbackProperties.uri); + assertThat(downloadRequest.customCacheKey) + .isEqualTo(testMediaItem.playbackProperties.customCacheKey); assertThat(downloadRequest.data).isEqualTo(data); assertThat(downloadRequest.streamKeys) .containsExactly( diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadHelperTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadHelperTest.java index 5ecdba11eb..9efe20c635 100644 --- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadHelperTest.java +++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadHelperTest.java @@ -15,13 +15,14 @@ */ package com.google.android.exoplayer2.source.dash.offline; -import android.net.Uri; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.offline.DownloadHelper; import com.google.android.exoplayer2.testutil.FakeDataSource; +import com.google.android.exoplayer2.util.MimeTypes; import org.junit.Test; import org.junit.runner.RunWith; @@ -31,16 +32,16 @@ public final class DownloadHelperTest { @Test public void staticDownloadHelperForDash_doesNotThrow() { - DownloadHelper.forDash( + DownloadHelper.forMediaItem( ApplicationProvider.getApplicationContext(), - Uri.parse("http://uri"), - new FakeDataSource.Factory(), - (handler, videoListener, audioListener, text, metadata) -> new Renderer[0]); - DownloadHelper.forDash( - Uri.parse("http://uri"), - new FakeDataSource.Factory(), + new MediaItem.Builder().setUri("http://uri").setMimeType(MimeTypes.APPLICATION_MPD).build(), (handler, videoListener, audioListener, text, metadata) -> new Renderer[0], - /* drmSessionManager= */ DrmSessionManager.getDummyDrmSessionManager(), - DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT); + new FakeDataSource.Factory()); + DownloadHelper.forMediaItem( + new MediaItem.Builder().setUri("http://uri").setMimeType(MimeTypes.APPLICATION_MPD).build(), + DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT, + (handler, videoListener, audioListener, text, metadata) -> new Renderer[0], + new FakeDataSource.Factory(), + /* drmSessionManager= */ DrmSessionManager.getDummyDrmSessionManager()); } } diff --git a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/offline/DownloadHelperTest.java b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/offline/DownloadHelperTest.java index f1d0b8ab8a..834f0457b9 100644 --- a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/offline/DownloadHelperTest.java +++ b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/offline/DownloadHelperTest.java @@ -15,12 +15,13 @@ */ package com.google.android.exoplayer2.source.hls.offline; -import android.net.Uri; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.offline.DownloadHelper; import com.google.android.exoplayer2.testutil.FakeDataSource; +import com.google.android.exoplayer2.util.MimeTypes; import org.junit.Test; import org.junit.runner.RunWith; @@ -30,16 +31,22 @@ public final class DownloadHelperTest { @Test public void staticDownloadHelperForHls_doesNotThrow() { - DownloadHelper.forHls( + DownloadHelper.forMediaItem( ApplicationProvider.getApplicationContext(), - Uri.parse("http://uri"), - new FakeDataSource.Factory(), - (handler, videoListener, audioListener, text, metadata) -> new Renderer[0]); - DownloadHelper.forHls( - Uri.parse("http://uri"), - new FakeDataSource.Factory(), + new MediaItem.Builder() + .setUri("http://uri") + .setMimeType(MimeTypes.APPLICATION_M3U8) + .build(), (handler, videoListener, audioListener, text, metadata) -> new Renderer[0], - /* drmSessionManager= */ null, - DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT); + new FakeDataSource.Factory()); + DownloadHelper.forMediaItem( + new MediaItem.Builder() + .setUri("http://uri") + .setMimeType(MimeTypes.APPLICATION_M3U8) + .build(), + DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT, + (handler, videoListener, audioListener, text, metadata) -> new Renderer[0], + new FakeDataSource.Factory(), + /* drmSessionManager= */ null); } } diff --git a/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/offline/DownloadHelperTest.java b/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/offline/DownloadHelperTest.java index b6d29d8b72..180deb3068 100644 --- a/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/offline/DownloadHelperTest.java +++ b/library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/offline/DownloadHelperTest.java @@ -15,12 +15,13 @@ */ package com.google.android.exoplayer2.source.smoothstreaming.offline; -import android.net.Uri; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.offline.DownloadHelper; import com.google.android.exoplayer2.testutil.FakeDataSource; +import com.google.android.exoplayer2.util.MimeTypes; import org.junit.Test; import org.junit.runner.RunWith; @@ -30,16 +31,16 @@ public final class DownloadHelperTest { @Test public void staticDownloadHelperForSmoothStreaming_doesNotThrow() { - DownloadHelper.forSmoothStreaming( + DownloadHelper.forMediaItem( ApplicationProvider.getApplicationContext(), - Uri.parse("http://uri"), - new FakeDataSource.Factory(), - (handler, videoListener, audioListener, text, metadata) -> new Renderer[0]); - DownloadHelper.forSmoothStreaming( - Uri.parse("http://uri"), - new FakeDataSource.Factory(), + new MediaItem.Builder().setUri("http://uri").setMimeType(MimeTypes.APPLICATION_SS).build(), (handler, videoListener, audioListener, text, metadata) -> new Renderer[0], - /* drmSessionManager= */ null, - DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT); + new FakeDataSource.Factory()); + DownloadHelper.forMediaItem( + new MediaItem.Builder().setUri("http://uri").setMimeType(MimeTypes.APPLICATION_SS).build(), + DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_VIEWPORT, + (handler, videoListener, audioListener, text, metadata) -> new Renderer[0], + new FakeDataSource.Factory(), + /* drmSessionManager= */ null); } }