Skip to content

Commit

Permalink
Support ExtractorFactory in DefaultMediaSourceFactory.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
tonihei authored and ojw28 committed Sep 9, 2020
1 parent 7dd4c73 commit 6290d09
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -115,9 +118,11 @@ public static final class Builder {
/**
* Creates a builder.
*
* <p>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.
* <p>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.
*
* <p>The builder uses the following default values:
*
Expand Down Expand Up @@ -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());
}

/**
Expand All @@ -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}.
*
* <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(
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));
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -64,9 +65,10 @@
* <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
* 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.
* </ul>
*
* <h3>Ad support for media items with ad tag URIs</h3>
Expand Down Expand Up @@ -105,6 +107,7 @@ public interface AdsLoaderProvider {
@Nullable private AdViewProvider adViewProvider;
@Nullable private DrmSessionManager drmSessionManager;
@Nullable private List<StreamKey> streamKeys;
@Nullable private LoadErrorHandlingPolicy loadErrorHandlingPolicy;

/**
* Creates a new instance.
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -285,7 +296,7 @@ private MediaSource maybeWrapWithAdsMediaSource(MediaItem mediaItem, MediaSource
}

private static SparseArray<MediaSourceFactory> loadDelegates(
DataSource.Factory dataSourceFactory) {
DataSource.Factory dataSourceFactory, ExtractorsFactory extractorsFactory) {
SparseArray<MediaSourceFactory> factories = new SparseArray<>();
// LINT.IfChange
try {
Expand Down Expand Up @@ -320,7 +331,8 @@ private static SparseArray<MediaSourceFactory> 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -59,7 +60,8 @@ default MediaSourceFactory setStreamKeys(@Nullable List<StreamKey> 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);
Expand All @@ -85,15 +87,17 @@ 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);

/**
* 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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down

0 comments on commit 6290d09

Please sign in to comment.