Simplify DownloadHelper

PiperOrigin-RevId: 312467496
This commit is contained in:
bachinger 2020-05-20 14:03:15 +01:00 committed by tonihei
parent b9157a9e23
commit d233c04582
7 changed files with 342 additions and 377 deletions

View File

@ -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

View File

@ -62,7 +62,7 @@
<init>(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 {
<init>(com.google.android.exoplayer2.upstream.DataSource$Factory);

View File

@ -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<? extends MediaSourceFactory> DASH_FACTORY_CONSTRUCTOR =
getConstructor("com.google.android.exoplayer2.source.dash.DashMediaSource$Factory");
@Nullable
private static final Constructor<? extends MediaSourceFactory> SS_FACTORY_CONSTRUCTOR =
getConstructor("com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory");
@Nullable
private static final Constructor<? extends MediaSourceFactory> 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<? extends MediaSourceFactory> 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<StreamKey> 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<? extends MediaSourceFactory> getConstructor(String className) {
try {
// LINT.IfChange
Class<? extends MediaSourceFactory> 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<? extends MediaSourceFactory> constructor,
Uri uri,
Factory dataSourceFactory,
@Nullable DrmSessionManager drmSessionManager,
@Nullable List<StreamKey> 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;

View File

@ -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(

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}