diff --git a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
index 787946d6a94..ba3a375a377 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
@@ -38,6 +38,8 @@
import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.device.DeviceInfo;
import com.google.android.exoplayer2.device.DeviceListener;
+import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
+import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataOutput;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
@@ -52,6 +54,7 @@
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
+import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.Log;
@@ -115,9 +118,11 @@ public static final class Builder {
/**
* Creates a builder.
*
- *
Use {@link #Builder(Context, RenderersFactory)} instead, if you intend to provide a custom
- * {@link RenderersFactory}. This is to ensure that ProGuard or R8 can remove ExoPlayer's {@link
- * DefaultRenderersFactory} from the APK.
+ *
Use {@link #Builder(Context, RenderersFactory)} or {@link #Builder(Context,
+ * RenderersFactory, ExtractorsFactory)} instead, if you intend to provide a custom {@link
+ * RenderersFactory} or a custom {@link ExtractorsFactory}. This is to ensure that ProGuard or
+ * R8 can remove ExoPlayer's {@link DefaultRenderersFactory} and {@link
+ * DefaultExtractorsFactory} from the APK.
*
*
The builder uses the following default values:
*
@@ -146,7 +151,7 @@ public static final class Builder {
* @param context A {@link Context}.
*/
public Builder(Context context) {
- this(context, new DefaultRenderersFactory(context));
+ this(context, new DefaultRenderersFactory(context), new DefaultExtractorsFactory());
}
/**
@@ -159,11 +164,30 @@ public Builder(Context context) {
* player.
*/
public Builder(Context context, RenderersFactory renderersFactory) {
+ this(context, renderersFactory, new DefaultExtractorsFactory());
+ }
+
+ /**
+ * Creates a builder with a custom {@link RenderersFactory} and {@link ExtractorsFactory}.
+ *
+ *
See {@link #Builder(Context)} for a list of default values.
+ *
+ * @param context A {@link Context}.
+ * @param renderersFactory A factory for creating {@link Renderer Renderers} to be used by the
+ * player.
+ * @param extractorsFactory An {@link ExtractorsFactory} used to extract progressive media from
+ * its container.
+ */
+ public Builder(
+ Context context, RenderersFactory renderersFactory, ExtractorsFactory extractorsFactory) {
this(
context,
renderersFactory,
new DefaultTrackSelector(context),
- new DefaultMediaSourceFactory(context),
+ new DefaultMediaSourceFactory(
+ new DefaultDataSourceFactory(
+ context, Util.getUserAgent(context, ExoPlayerLibraryInfo.VERSION_SLASHY)),
+ extractorsFactory),
new DefaultLoadControl(),
DefaultBandwidthMeter.getSingletonInstance(context),
new AnalyticsCollector(Clock.DEFAULT));
@@ -546,7 +570,7 @@ protected SimpleExoPlayer(
Clock clock,
Looper applicationLooper) {
this(
- new Builder(context, renderersFactory)
+ new Builder(context, renderersFactory, new DefaultExtractorsFactory())
.setTrackSelector(trackSelector)
.setMediaSourceFactory(mediaSourceFactory)
.setLoadControl(loadControl)
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 dd868f98225..ba8a799381a 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
@@ -34,6 +34,7 @@
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.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
@@ -889,7 +890,7 @@ private static MediaSource createMediaSourceInternal(
MediaItem mediaItem,
DataSource.Factory dataSourceFactory,
@Nullable DrmSessionManager drmSessionManager) {
- return new DefaultMediaSourceFactory(dataSourceFactory)
+ return new DefaultMediaSourceFactory(dataSourceFactory, ExtractorsFactory.EMPTY)
.setDrmSessionManager(drmSessionManager)
.createMediaSource(mediaItem);
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.java
index 89b4ffb6a59..df1f3e2cf04 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.java
@@ -23,13 +23,14 @@
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.drm.DrmSessionManager;
+import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
+import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.source.ads.AdsLoader.AdViewProvider;
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
-import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.util.Assertions;
@@ -64,9 +65,10 @@
*
{@link ProgressiveMediaSource.Factory} serves as a fallback if the item's {@link
* MediaItem.PlaybackProperties#uri uri} doesn't match one of the above. It tries to infer the
* required extractor by using the {@link
- * com.google.android.exoplayer2.extractor.DefaultExtractorsFactory}. An {@link
- * UnrecognizedInputFormatException} is thrown if none of the available extractors can read
- * the stream.
+ * com.google.android.exoplayer2.extractor.DefaultExtractorsFactory} or the {@link
+ * ExtractorsFactory} provided in {@link #DefaultMediaSourceFactory(DataSource.Factory,
+ * ExtractorsFactory)}. An {@link UnrecognizedInputFormatException} is thrown if none of the
+ * available extractors can read the stream.
*
*
* Ad support for media items with ad tag URIs
@@ -105,6 +107,7 @@ public interface AdsLoaderProvider {
@Nullable private AdViewProvider adViewProvider;
@Nullable private DrmSessionManager drmSessionManager;
@Nullable private List streamKeys;
+ @Nullable private LoadErrorHandlingPolicy loadErrorHandlingPolicy;
/**
* Creates a new instance.
@@ -124,9 +127,22 @@ public DefaultMediaSourceFactory(Context context) {
* for requesting media data.
*/
public DefaultMediaSourceFactory(DataSource.Factory dataSourceFactory) {
+ this(dataSourceFactory, new DefaultExtractorsFactory());
+ }
+
+ /**
+ * Creates a new instance.
+ *
+ * @param dataSourceFactory A {@link DataSource.Factory} to create {@link DataSource} instances
+ * for requesting media data.
+ * @param extractorsFactory An {@link ExtractorsFactory} used to extract progressive media from
+ * its container.
+ */
+ public DefaultMediaSourceFactory(
+ DataSource.Factory dataSourceFactory, ExtractorsFactory extractorsFactory) {
this.dataSourceFactory = dataSourceFactory;
mediaSourceDrmHelper = new MediaSourceDrmHelper();
- mediaSourceFactories = loadDelegates(dataSourceFactory);
+ mediaSourceFactories = loadDelegates(dataSourceFactory, extractorsFactory);
supportedTypes = new int[mediaSourceFactories.size()];
for (int i = 0; i < mediaSourceFactories.size(); i++) {
supportedTypes[i] = mediaSourceFactories.keyAt(i);
@@ -180,13 +196,7 @@ public DefaultMediaSourceFactory setDrmSessionManager(
@Override
public DefaultMediaSourceFactory setLoadErrorHandlingPolicy(
@Nullable LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
- LoadErrorHandlingPolicy newLoadErrorHandlingPolicy =
- loadErrorHandlingPolicy != null
- ? loadErrorHandlingPolicy
- : new DefaultLoadErrorHandlingPolicy();
- for (int i = 0; i < mediaSourceFactories.size(); i++) {
- mediaSourceFactories.valueAt(i).setLoadErrorHandlingPolicy(newLoadErrorHandlingPolicy);
- }
+ this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
return this;
}
@@ -224,6 +234,7 @@ public MediaSource createMediaSource(MediaItem mediaItem) {
!mediaItem.playbackProperties.streamKeys.isEmpty()
? mediaItem.playbackProperties.streamKeys
: streamKeys);
+ mediaSourceFactory.setLoadErrorHandlingPolicy(loadErrorHandlingPolicy);
MediaSource mediaSource = mediaSourceFactory.createMediaSource(mediaItem);
@@ -285,7 +296,7 @@ private MediaSource maybeWrapWithAdsMediaSource(MediaItem mediaItem, MediaSource
}
private static SparseArray loadDelegates(
- DataSource.Factory dataSourceFactory) {
+ DataSource.Factory dataSourceFactory, ExtractorsFactory extractorsFactory) {
SparseArray factories = new SparseArray<>();
// LINT.IfChange
try {
@@ -320,7 +331,8 @@ private static SparseArray loadDelegates(
// Expected if the app was built without the hls module.
}
// LINT.ThenChange(../../../../../../../../proguard-rules.txt)
- factories.put(C.TYPE_OTHER, new ProgressiveMediaSource.Factory(dataSourceFactory));
+ factories.put(
+ C.TYPE_OTHER, new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory));
return factories;
}
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceFactory.java
index 4175121d385..204220e334e 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceFactory.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceFactory.java
@@ -24,6 +24,7 @@
import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
+import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import java.util.List;
@@ -59,7 +60,8 @@ default MediaSourceFactory setStreamKeys(@Nullable List streamKeys) {
* Sets the {@link DrmSessionManager} to use for all media items regardless of their {@link
* MediaItem.DrmConfiguration}.
*
- * @param drmSessionManager The {@link DrmSessionManager}.
+ * @param drmSessionManager The {@link DrmSessionManager}, or {@code null} to use the {@link
+ * DefaultDrmSessionManager}.
* @return This factory, for convenience.
*/
MediaSourceFactory setDrmSessionManager(@Nullable DrmSessionManager drmSessionManager);
@@ -85,7 +87,8 @@ MediaSourceFactory setDrmHttpDataSourceFactory(
* #setDrmHttpDataSourceFactory(HttpDataSource.Factory)} or a {@link DrmSessionManager} has been
* set by {@link #setDrmSessionManager(DrmSessionManager)}, this user agent is ignored.
*
- * @param userAgent The user agent to be used for DRM requests.
+ * @param userAgent The user agent to be used for DRM requests, or {@code null} to use the
+ * default.
* @return This factory, for convenience.
*/
MediaSourceFactory setDrmUserAgent(@Nullable String userAgent);
@@ -93,7 +96,8 @@ MediaSourceFactory setDrmHttpDataSourceFactory(
/**
* Sets an optional {@link LoadErrorHandlingPolicy}.
*
- * @param loadErrorHandlingPolicy A {@link LoadErrorHandlingPolicy}.
+ * @param loadErrorHandlingPolicy A {@link LoadErrorHandlingPolicy}, or {@code null} to use the
+ * {@link DefaultLoadErrorHandlingPolicy}.
* @return This factory, for convenience.
*/
MediaSourceFactory setLoadErrorHandlingPolicy(
diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorsFactory.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorsFactory.java
index d077b1b11ef..97ae74b9d23 100644
--- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorsFactory.java
+++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ExtractorsFactory.java
@@ -22,6 +22,12 @@
/** Factory for arrays of {@link Extractor} instances. */
public interface ExtractorsFactory {
+ /**
+ * Extractor factory that returns an empty list of extractors. Can be used whenever {@link
+ * Extractor Extractors} are not required.
+ */
+ ExtractorsFactory EMPTY = () -> new Extractor[] {};
+
/** Returns an array of new {@link Extractor} instances. */
Extractor[] createExtractors();