Commit 98200c26 by ibaker Committed by bachinger

Replace ExtractorsFactory with MediaSourceFactory in ExoPlayer.Builder

This has a few benefits:
  * Aligns the Builder constructors with the setters
    (setRenderersFactory is missing, but can be easily added in a
    follow-up change).
  * Allows DefaultMediaSourceFactory to be stripped by R8 and
    makes the shrinking dev guide for the cases of providing a custom
    MediaSourceFactory or directly instantiating MediaSource instances
    less weird too.

#minor-release

PiperOrigin-RevId: 405632981
parent 649fe702
......@@ -81,36 +81,49 @@ an app that only needs to play mp4 files can provide a factory like:
ExtractorsFactory mp4ExtractorFactory =
() -> new Extractor[] {new Mp4Extractor()};
ExoPlayer player =
new ExoPlayer.Builder(context, mp4ExtractorFactory).build();
new ExoPlayer.Builder(
context,
new DefaultMediaSourceFactory(context, mp4ExtractorFactory))
.build();
~~~
{: .language-java}
This will allow other `Extractor` implementations to be removed by code
shrinking, which can result in a significant reduction in size.
You should pass `ExtractorsFactory.EMPTY` to the `ExoPlayer.Builder`
constructor, if your app is doing one of the following:
* Not playing progressive media at all, for example because it only
plays DASH, HLS or SmoothStreaming content
* Providing a customized `DefaultMediaSourceFactory`
* Using `MediaSource`s directly instead of `MediaItem`s
If your app is not playing progressive content at all, you should pass
`ExtractorsFactory.EMPTY` to the `DefaultMediaSourceFactory` constructor, then
pass that `mediaSourceFactory` to the `ExoPlayer.Builder` constructor.
~~~
// Only playing DASH, HLS or SmoothStreaming.
ExoPlayer player =
new ExoPlayer.Builder(context, ExtractorsFactory.EMPTY).build();
new ExoPlayer.Builder(
context,
new DefaultMediaSourceFactory(context, ExtractorsFactory.EMPTY))
.build();
~~~
{: .language-java}
## Custom `MediaSource` instantiation ##
If your app is using a custom `MediaSourceFactory` and you want
`DefaultMediaSourceFactory` to be removed by code stripping, you should pass
your `MediaSourceFactory` directly to the `ExoPlayer.Builder` constructor.
// Providing a customized `DefaultMediaSourceFactory`
~~~
ExoPlayer player =
new ExoPlayer.Builder(context, ExtractorsFactory.EMPTY)
.setMediaSourceFactory(
new DefaultMediaSourceFactory(context, customExtractorsFactory))
.build();
new ExoPlayer.Builder(context, customMediaSourceFactory).build();
~~~
{: .language-java}
If your app is using `MediaSource`s directly instead of `MediaItem`s you should
pass `MediaSourceFactory.UNSUPPORTED` to the `ExoPlayer.Builder` constructor, to
ensure `DefaultMediaSourceFactory` and `DefaultExtractorsFactory` can be
stripped by code shrinking.
// Using a MediaSource directly.
~~~
ExoPlayer player =
new ExoPlayer.Builder(context, ExtractorsFactory.EMPTY).build();
new ExoPlayer.Builder(context, MediaSourceFactory.UNSUPPORTED).build();
ProgressiveMediaSource mediaSource =
new ProgressiveMediaSource.Factory(
dataSourceFactory, customExtractorsFactory)
......
......@@ -367,8 +367,8 @@ public interface ExoPlayer extends Player {
/* package */ Clock clock;
/* package */ long foregroundModeTimeoutMs;
/* package */ TrackSelector trackSelector;
/* package */ MediaSourceFactory mediaSourceFactory;
/* package */ TrackSelector trackSelector;
/* package */ LoadControl loadControl;
/* package */ BandwidthMeter bandwidthMeter;
/* package */ AnalyticsCollector analyticsCollector;
......@@ -395,10 +395,11 @@ public interface ExoPlayer extends Player {
* Creates a builder.
*
* <p>Use {@link #Builder(Context, RenderersFactory)}, {@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.
* MediaSourceFactory)} or {@link #Builder(Context, RenderersFactory, MediaSourceFactory)}
* instead, if you intend to provide a custom {@link RenderersFactory}, {@link
* ExtractorsFactory} or {@link DefaultMediaSourceFactory}. This is to ensure that ProGuard or
* R8 can remove ExoPlayer's {@link DefaultRenderersFactory}, {@link DefaultExtractorsFactory}
* and {@link DefaultMediaSourceFactory} from the APK.
*
* <p>The builder uses the following default values:
*
......@@ -434,7 +435,10 @@ public interface ExoPlayer extends Player {
* @param context A {@link Context}.
*/
public Builder(Context context) {
this(context, new DefaultRenderersFactory(context), new DefaultExtractorsFactory());
this(
context,
new DefaultRenderersFactory(context),
new DefaultMediaSourceFactory(context, new DefaultExtractorsFactory()));
}
/**
......@@ -447,40 +451,23 @@ public interface ExoPlayer extends Player {
* player.
*/
public Builder(Context context, RenderersFactory renderersFactory) {
this(context, renderersFactory, new DefaultExtractorsFactory());
this(
context,
renderersFactory,
new DefaultMediaSourceFactory(context, new DefaultExtractorsFactory()));
}
/**
* Creates a builder with a custom {@link ExtractorsFactory}.
*
* <p>See {@link #Builder(Context)} for a list of default values.
*
* @param context A {@link Context}.
* @param extractorsFactory An {@link ExtractorsFactory} used to extract progressive media from
* its container.
*/
public Builder(Context context, ExtractorsFactory extractorsFactory) {
this(context, new DefaultRenderersFactory(context), extractorsFactory);
public Builder(Context context, MediaSourceFactory mediaSourceFactory) {
this(context, new DefaultRenderersFactory(context), mediaSourceFactory);
}
/**
* 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) {
Context context, RenderersFactory renderersFactory, MediaSourceFactory mediaSourceFactory) {
this(
context,
renderersFactory,
mediaSourceFactory,
new DefaultTrackSelector(context),
new DefaultMediaSourceFactory(context, extractorsFactory),
new DefaultLoadControl(),
DefaultBandwidthMeter.getSingletonInstance(context),
new AnalyticsCollector(Clock.DEFAULT));
......@@ -495,8 +482,8 @@ public interface ExoPlayer extends Player {
* @param context A {@link Context}.
* @param renderersFactory A factory for creating {@link Renderer Renderers} to be used by the
* player.
* @param trackSelector A {@link TrackSelector}.
* @param mediaSourceFactory A {@link MediaSourceFactory}.
* @param trackSelector A {@link TrackSelector}.
* @param loadControl A {@link LoadControl}.
* @param bandwidthMeter A {@link BandwidthMeter}.
* @param analyticsCollector An {@link AnalyticsCollector}.
......@@ -504,15 +491,15 @@ public interface ExoPlayer extends Player {
public Builder(
Context context,
RenderersFactory renderersFactory,
TrackSelector trackSelector,
MediaSourceFactory mediaSourceFactory,
TrackSelector trackSelector,
LoadControl loadControl,
BandwidthMeter bandwidthMeter,
AnalyticsCollector analyticsCollector) {
this.context = context;
this.renderersFactory = renderersFactory;
this.trackSelector = trackSelector;
this.mediaSourceFactory = mediaSourceFactory;
this.trackSelector = trackSelector;
this.loadControl = loadControl;
this.bandwidthMeter = bandwidthMeter;
this.analyticsCollector = analyticsCollector;
......@@ -547,28 +534,28 @@ public interface ExoPlayer extends Player {
}
/**
* Sets the {@link TrackSelector} that will be used by the player.
* Sets the {@link MediaSourceFactory} that will be used by the player.
*
* @param trackSelector A {@link TrackSelector}.
* @param mediaSourceFactory A {@link MediaSourceFactory}.
* @return This builder.
* @throws IllegalStateException If {@link #build()} has already been called.
*/
public Builder setTrackSelector(TrackSelector trackSelector) {
public Builder setMediaSourceFactory(MediaSourceFactory mediaSourceFactory) {
checkState(!buildCalled);
this.trackSelector = trackSelector;
this.mediaSourceFactory = mediaSourceFactory;
return this;
}
/**
* Sets the {@link MediaSourceFactory} that will be used by the player.
* Sets the {@link TrackSelector} that will be used by the player.
*
* @param mediaSourceFactory A {@link MediaSourceFactory}.
* @param trackSelector A {@link TrackSelector}.
* @return This builder.
* @throws IllegalStateException If {@link #build()} has already been called.
*/
public Builder setMediaSourceFactory(MediaSourceFactory mediaSourceFactory) {
public Builder setTrackSelector(TrackSelector trackSelector) {
checkState(!buildCalled);
this.mediaSourceFactory = mediaSourceFactory;
this.trackSelector = trackSelector;
return this;
}
......
......@@ -55,6 +55,7 @@ import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation;
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;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.source.ShuffleOrder;
......@@ -111,25 +112,33 @@ public class SimpleExoPlayer extends BasePlayer
wrappedBuilder = new ExoPlayer.Builder(context, renderersFactory);
}
/** @deprecated Use {@link ExoPlayer.Builder#Builder(Context, ExtractorsFactory)} instead. */
/**
* @deprecated Use {@link ExoPlayer.Builder#Builder(Context, MediaSourceFactory)} and {@link
* DefaultMediaSourceFactory#DefaultMediaSourceFactory(Context, ExtractorsFactory)} instead.
*/
@Deprecated
public Builder(Context context, ExtractorsFactory extractorsFactory) {
wrappedBuilder = new ExoPlayer.Builder(context, extractorsFactory);
wrappedBuilder =
new ExoPlayer.Builder(context, new DefaultMediaSourceFactory(context, extractorsFactory));
}
/**
* @deprecated Use {@link ExoPlayer.Builder#Builder(Context, RenderersFactory,
* ExtractorsFactory)} instead.
* MediaSourceFactory)} and {@link
* DefaultMediaSourceFactory#DefaultMediaSourceFactory(Context, ExtractorsFactory)} instead.
*/
@Deprecated
public Builder(
Context context, RenderersFactory renderersFactory, ExtractorsFactory extractorsFactory) {
wrappedBuilder = new ExoPlayer.Builder(context, renderersFactory, extractorsFactory);
wrappedBuilder =
new ExoPlayer.Builder(
context, renderersFactory, new DefaultMediaSourceFactory(context, extractorsFactory));
}
/**
* @deprecated Use {@link ExoPlayer.Builder#Builder(Context, RenderersFactory, TrackSelector,
* MediaSourceFactory, LoadControl, BandwidthMeter, AnalyticsCollector)} instead.
* @deprecated Use {@link ExoPlayer.Builder#Builder(Context, RenderersFactory,
* MediaSourceFactory, TrackSelector, LoadControl, BandwidthMeter, AnalyticsCollector)}
* instead.
*/
@Deprecated
public Builder(
......@@ -144,8 +153,8 @@ public class SimpleExoPlayer extends BasePlayer
new ExoPlayer.Builder(
context,
renderersFactory,
trackSelector,
mediaSourceFactory,
trackSelector,
loadControl,
bandwidthMeter,
analyticsCollector);
......
......@@ -34,6 +34,56 @@ import java.util.List;
/** Factory for creating {@link MediaSource MediaSources} from {@link MediaItem MediaItems}. */
public interface MediaSourceFactory {
/**
* An instance that throws {@link UnsupportedOperationException} from {@link #createMediaSource}
* and {@link #getSupportedTypes()}.
*/
MediaSourceFactory UNSUPPORTED =
new MediaSourceFactory() {
@Override
public MediaSourceFactory setDrmSessionManagerProvider(
@Nullable DrmSessionManagerProvider drmSessionManagerProvider) {
return this;
}
@Deprecated
@Override
public MediaSourceFactory setDrmSessionManager(
@Nullable DrmSessionManager drmSessionManager) {
return this;
}
@Deprecated
@Override
public MediaSourceFactory setDrmHttpDataSourceFactory(
@Nullable HttpDataSource.Factory drmHttpDataSourceFactory) {
return this;
}
@Deprecated
@Override
public MediaSourceFactory setDrmUserAgent(@Nullable String userAgent) {
return this;
}
@Override
public MediaSourceFactory setLoadErrorHandlingPolicy(
@Nullable LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
return this;
}
@Override
@C.ContentType
public int[] getSupportedTypes() {
throw new UnsupportedOperationException();
}
@Override
public MediaSource createMediaSource(MediaItem mediaItem) {
throw new UnsupportedOperationException();
}
};
/** @deprecated Use {@link MediaItem.LocalConfiguration#streamKeys} instead. */
@Deprecated
default MediaSourceFactory setStreamKeys(@Nullable List<StreamKey> streamKeys) {
......
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