Commit bfe17aee by tonihei Committed by Oliver Woodman

Support ExtractorFactory in DefaultMediaSourceFactory.

This allows to customize extractor flags more easily when setting up the player.

In addition, we need to provide a way to pass in the ExtractorFactory through
the constructor chain starting in SimpleExoPlayer so that removing the
DefaultExtractorsFactory is possible for R8.

PiperOrigin-RevId: 330472935
parent 3110587f
...@@ -38,6 +38,8 @@ import com.google.android.exoplayer2.audio.AuxEffectInfo; ...@@ -38,6 +38,8 @@ import com.google.android.exoplayer2.audio.AuxEffectInfo;
import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.device.DeviceInfo; import com.google.android.exoplayer2.device.DeviceInfo;
import com.google.android.exoplayer2.device.DeviceListener; 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.Metadata;
import com.google.android.exoplayer2.metadata.MetadataOutput; import com.google.android.exoplayer2.metadata.MetadataOutput;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
...@@ -52,6 +54,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectionArray; ...@@ -52,6 +54,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector; import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; 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.Assertions;
import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
...@@ -115,9 +118,11 @@ public class SimpleExoPlayer extends BasePlayer ...@@ -115,9 +118,11 @@ public class SimpleExoPlayer extends BasePlayer
/** /**
* Creates a builder. * Creates a builder.
* *
* <p>Use {@link #Builder(Context, RenderersFactory)} instead, if you intend to provide a custom * <p>Use {@link #Builder(Context, RenderersFactory)} or {@link #Builder(Context,
* {@link RenderersFactory}. This is to ensure that ProGuard or R8 can remove ExoPlayer's {@link * RenderersFactory, ExtractorsFactory)} instead, if you intend to provide a custom {@link
* DefaultRenderersFactory} from the APK. * 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.
* *
* <p>The builder uses the following default values: * <p>The builder uses the following default values:
* *
...@@ -146,7 +151,7 @@ public class SimpleExoPlayer extends BasePlayer ...@@ -146,7 +151,7 @@ public class SimpleExoPlayer extends BasePlayer
* @param context A {@link Context}. * @param context A {@link Context}.
*/ */
public Builder(Context context) { public Builder(Context context) {
this(context, new DefaultRenderersFactory(context)); this(context, new DefaultRenderersFactory(context), new DefaultExtractorsFactory());
} }
/** /**
...@@ -159,11 +164,30 @@ public class SimpleExoPlayer extends BasePlayer ...@@ -159,11 +164,30 @@ public class SimpleExoPlayer extends BasePlayer
* player. * player.
*/ */
public Builder(Context context, RenderersFactory renderersFactory) { public Builder(Context context, RenderersFactory renderersFactory) {
this(context, renderersFactory, new DefaultExtractorsFactory());
}
/**
* Creates a builder with a custom {@link RenderersFactory} and {@link ExtractorsFactory}.
*
* <p>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( this(
context, context,
renderersFactory, renderersFactory,
new DefaultTrackSelector(context), new DefaultTrackSelector(context),
new DefaultMediaSourceFactory(context), new DefaultMediaSourceFactory(
new DefaultDataSourceFactory(
context, Util.getUserAgent(context, ExoPlayerLibraryInfo.VERSION_SLASHY)),
extractorsFactory),
new DefaultLoadControl(), new DefaultLoadControl(),
DefaultBandwidthMeter.getSingletonInstance(context), DefaultBandwidthMeter.getSingletonInstance(context),
new AnalyticsCollector(Clock.DEFAULT)); new AnalyticsCollector(Clock.DEFAULT));
...@@ -546,7 +570,7 @@ public class SimpleExoPlayer extends BasePlayer ...@@ -546,7 +570,7 @@ public class SimpleExoPlayer extends BasePlayer
Clock clock, Clock clock,
Looper applicationLooper) { Looper applicationLooper) {
this( this(
new Builder(context, renderersFactory) new Builder(context, renderersFactory, new DefaultExtractorsFactory())
.setTrackSelector(trackSelector) .setTrackSelector(trackSelector)
.setMediaSourceFactory(mediaSourceFactory) .setMediaSourceFactory(mediaSourceFactory)
.setLoadControl(loadControl) .setLoadControl(loadControl)
......
...@@ -34,6 +34,7 @@ import com.google.android.exoplayer2.RenderersFactory; ...@@ -34,6 +34,7 @@ import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.audio.AudioRendererEventListener; import com.google.android.exoplayer2.audio.AudioRendererEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; 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.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
...@@ -889,7 +890,7 @@ public final class DownloadHelper { ...@@ -889,7 +890,7 @@ public final class DownloadHelper {
MediaItem mediaItem, MediaItem mediaItem,
DataSource.Factory dataSourceFactory, DataSource.Factory dataSourceFactory,
@Nullable DrmSessionManager drmSessionManager) { @Nullable DrmSessionManager drmSessionManager) {
return new DefaultMediaSourceFactory(dataSourceFactory) return new DefaultMediaSourceFactory(dataSourceFactory, ExtractorsFactory.EMPTY)
.setDrmSessionManager(drmSessionManager) .setDrmSessionManager(drmSessionManager)
.createMediaSource(mediaItem); .createMediaSource(mediaItem);
} }
......
...@@ -23,13 +23,14 @@ import com.google.android.exoplayer2.C; ...@@ -23,13 +23,14 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.drm.DrmSessionManager; 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.offline.StreamKey;
import com.google.android.exoplayer2.source.ads.AdsLoader; import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.source.ads.AdsLoader.AdViewProvider; import com.google.android.exoplayer2.source.ads.AdsLoader.AdViewProvider;
import com.google.android.exoplayer2.source.ads.AdsMediaSource; import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; 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.HttpDataSource;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
...@@ -64,9 +65,10 @@ import java.util.List; ...@@ -64,9 +65,10 @@ import java.util.List;
* <li>{@link ProgressiveMediaSource.Factory} serves as a fallback if the item's {@link * <li>{@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 * MediaItem.PlaybackProperties#uri uri} doesn't match one of the above. It tries to infer the
* required extractor by using the {@link * required extractor by using the {@link
* com.google.android.exoplayer2.extractor.DefaultExtractorsFactory}. An {@link * com.google.android.exoplayer2.extractor.DefaultExtractorsFactory} or the {@link
* UnrecognizedInputFormatException} is thrown if none of the available extractors can read * ExtractorsFactory} provided in {@link #DefaultMediaSourceFactory(DataSource.Factory,
* the stream. * ExtractorsFactory)}. An {@link UnrecognizedInputFormatException} is thrown if none of the
* available extractors can read the stream.
* </ul> * </ul>
* *
* <h3>Ad support for media items with ad tag URIs</h3> * <h3>Ad support for media items with ad tag URIs</h3>
...@@ -105,6 +107,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { ...@@ -105,6 +107,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
@Nullable private AdViewProvider adViewProvider; @Nullable private AdViewProvider adViewProvider;
@Nullable private DrmSessionManager drmSessionManager; @Nullable private DrmSessionManager drmSessionManager;
@Nullable private List<StreamKey> streamKeys; @Nullable private List<StreamKey> streamKeys;
@Nullable private LoadErrorHandlingPolicy loadErrorHandlingPolicy;
/** /**
* Creates a new instance. * Creates a new instance.
...@@ -124,9 +127,22 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { ...@@ -124,9 +127,22 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
* for requesting media data. * for requesting media data.
*/ */
public DefaultMediaSourceFactory(DataSource.Factory dataSourceFactory) { 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; this.dataSourceFactory = dataSourceFactory;
mediaSourceDrmHelper = new MediaSourceDrmHelper(); mediaSourceDrmHelper = new MediaSourceDrmHelper();
mediaSourceFactories = loadDelegates(dataSourceFactory); mediaSourceFactories = loadDelegates(dataSourceFactory, extractorsFactory);
supportedTypes = new int[mediaSourceFactories.size()]; supportedTypes = new int[mediaSourceFactories.size()];
for (int i = 0; i < mediaSourceFactories.size(); i++) { for (int i = 0; i < mediaSourceFactories.size(); i++) {
supportedTypes[i] = mediaSourceFactories.keyAt(i); supportedTypes[i] = mediaSourceFactories.keyAt(i);
...@@ -180,13 +196,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { ...@@ -180,13 +196,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
@Override @Override
public DefaultMediaSourceFactory setLoadErrorHandlingPolicy( public DefaultMediaSourceFactory setLoadErrorHandlingPolicy(
@Nullable LoadErrorHandlingPolicy loadErrorHandlingPolicy) { @Nullable LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
LoadErrorHandlingPolicy newLoadErrorHandlingPolicy = this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
loadErrorHandlingPolicy != null
? loadErrorHandlingPolicy
: new DefaultLoadErrorHandlingPolicy();
for (int i = 0; i < mediaSourceFactories.size(); i++) {
mediaSourceFactories.valueAt(i).setLoadErrorHandlingPolicy(newLoadErrorHandlingPolicy);
}
return this; return this;
} }
...@@ -224,6 +234,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { ...@@ -224,6 +234,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
!mediaItem.playbackProperties.streamKeys.isEmpty() !mediaItem.playbackProperties.streamKeys.isEmpty()
? mediaItem.playbackProperties.streamKeys ? mediaItem.playbackProperties.streamKeys
: streamKeys); : streamKeys);
mediaSourceFactory.setLoadErrorHandlingPolicy(loadErrorHandlingPolicy);
MediaSource mediaSource = mediaSourceFactory.createMediaSource(mediaItem); MediaSource mediaSource = mediaSourceFactory.createMediaSource(mediaItem);
...@@ -285,7 +296,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { ...@@ -285,7 +296,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
} }
private static SparseArray<MediaSourceFactory> loadDelegates( private static SparseArray<MediaSourceFactory> loadDelegates(
DataSource.Factory dataSourceFactory) { DataSource.Factory dataSourceFactory, ExtractorsFactory extractorsFactory) {
SparseArray<MediaSourceFactory> factories = new SparseArray<>(); SparseArray<MediaSourceFactory> factories = new SparseArray<>();
// LINT.IfChange // LINT.IfChange
try { try {
...@@ -320,7 +331,8 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory { ...@@ -320,7 +331,8 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
// Expected if the app was built without the hls module. // Expected if the app was built without the hls module.
} }
// LINT.ThenChange(../../../../../../../../proguard-rules.txt) // 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; return factories;
} }
} }
...@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.drm.DrmSessionManager; ...@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.HttpMediaDrmCallback; import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; 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.HttpDataSource;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import java.util.List; import java.util.List;
...@@ -59,7 +60,8 @@ public interface MediaSourceFactory { ...@@ -59,7 +60,8 @@ public interface MediaSourceFactory {
* Sets the {@link DrmSessionManager} to use for all media items regardless of their {@link * Sets the {@link DrmSessionManager} to use for all media items regardless of their {@link
* MediaItem.DrmConfiguration}. * 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. * @return This factory, for convenience.
*/ */
MediaSourceFactory setDrmSessionManager(@Nullable DrmSessionManager drmSessionManager); MediaSourceFactory setDrmSessionManager(@Nullable DrmSessionManager drmSessionManager);
...@@ -85,7 +87,8 @@ public interface MediaSourceFactory { ...@@ -85,7 +87,8 @@ public interface MediaSourceFactory {
* #setDrmHttpDataSourceFactory(HttpDataSource.Factory)} or a {@link DrmSessionManager} has been * #setDrmHttpDataSourceFactory(HttpDataSource.Factory)} or a {@link DrmSessionManager} has been
* set by {@link #setDrmSessionManager(DrmSessionManager)}, this user agent is ignored. * 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. * @return This factory, for convenience.
*/ */
MediaSourceFactory setDrmUserAgent(@Nullable String userAgent); MediaSourceFactory setDrmUserAgent(@Nullable String userAgent);
...@@ -93,7 +96,8 @@ public interface MediaSourceFactory { ...@@ -93,7 +96,8 @@ public interface MediaSourceFactory {
/** /**
* Sets an optional {@link LoadErrorHandlingPolicy}. * 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. * @return This factory, for convenience.
*/ */
MediaSourceFactory setLoadErrorHandlingPolicy( MediaSourceFactory setLoadErrorHandlingPolicy(
......
...@@ -22,6 +22,12 @@ import java.util.Map; ...@@ -22,6 +22,12 @@ import java.util.Map;
/** Factory for arrays of {@link Extractor} instances. */ /** Factory for arrays of {@link Extractor} instances. */
public interface ExtractorsFactory { 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. */ /** Returns an array of new {@link Extractor} instances. */
Extractor[] createExtractors(); Extractor[] createExtractors();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment