Make ExtractorMediaSource.Builder a factory for ExtractorMediaSources

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=178605481
This commit is contained in:
andrewlewis 2017-12-11 05:23:00 -08:00 committed by Oliver Woodman
parent f8834dacc6
commit 8c7fe8a258
8 changed files with 118 additions and 133 deletions

View File

@ -398,7 +398,7 @@ import java.util.ArrayList;
case DemoUtil.MIME_TYPE_HLS: case DemoUtil.MIME_TYPE_HLS:
return new HlsMediaSource.Factory(DATA_SOURCE_FACTORY).createMediaSource(uri); return new HlsMediaSource.Factory(DATA_SOURCE_FACTORY).createMediaSource(uri);
case DemoUtil.MIME_TYPE_VIDEO_MP4: case DemoUtil.MIME_TYPE_VIDEO_MP4:
return new ExtractorMediaSource.Builder(uri, DATA_SOURCE_FACTORY).build(); return new ExtractorMediaSource.Factory(DATA_SOURCE_FACTORY).createMediaSource(uri);
default: { default: {
throw new IllegalStateException("Unsupported type: " + sample.mimeType); throw new IllegalStateException("Unsupported type: " + sample.mimeType);
} }

View File

@ -70,7 +70,8 @@ import com.google.android.exoplayer2.util.Util;
// This is the MediaSource representing the content media (i.e. not the ad). // This is the MediaSource representing the content media (i.e. not the ad).
String contentUrl = context.getString(R.string.content_url); String contentUrl = context.getString(R.string.content_url);
MediaSource contentMediaSource = MediaSource contentMediaSource =
new ExtractorMediaSource.Builder(Uri.parse(contentUrl), dataSourceFactory).build(); new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(contentUrl));
// Compose the content media source into a new AdsMediaSource with both ads and content. // Compose the content media source into a new AdsMediaSource with both ads and content.
MediaSource mediaSourceWithAds = new AdsMediaSource(contentMediaSource, dataSourceFactory, MediaSource mediaSourceWithAds = new AdsMediaSource(contentMediaSource, dataSourceFactory,

View File

@ -378,9 +378,8 @@ public class PlayerActivity extends Activity implements OnClickListener,
return new HlsMediaSource.Factory(mediaDataSourceFactory) return new HlsMediaSource.Factory(mediaDataSourceFactory)
.createMediaSource(uri, mainHandler, eventLogger); .createMediaSource(uri, mainHandler, eventLogger);
case C.TYPE_OTHER: case C.TYPE_OTHER:
return new ExtractorMediaSource.Builder(uri, mediaDataSourceFactory) return new ExtractorMediaSource.Factory(mediaDataSourceFactory)
.setEventListener(mainHandler, eventLogger) .createMediaSource(uri, mainHandler, eventLogger);
.build();
default: { default: {
throw new IllegalStateException("Unsupported type: " + type); throw new IllegalStateException("Unsupported type: " + type);
} }

View File

@ -26,6 +26,7 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor; import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
import com.google.android.exoplayer2.source.ExtractorMediaSource; import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
@ -76,10 +77,11 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
DefaultTrackSelector trackSelector = new DefaultTrackSelector(); DefaultTrackSelector trackSelector = new DefaultTrackSelector();
player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector); player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector);
player.addListener(this); player.addListener(this);
ExtractorMediaSource mediaSource = new ExtractorMediaSource.Builder( MediaSource mediaSource =
uri, new DefaultDataSourceFactory(context, "ExoPlayerExtFlacTest")) new ExtractorMediaSource.Factory(
.setExtractorsFactory(MatroskaExtractor.FACTORY) new DefaultDataSourceFactory(context, "ExoPlayerExtFlacTest"))
.build(); .setExtractorsFactory(MatroskaExtractor.FACTORY)
.createMediaSource(uri);
player.prepare(mediaSource); player.prepare(mediaSource);
player.setPlayWhenReady(true); player.setPlayWhenReady(true);
Looper.loop(); Looper.loop();

View File

@ -26,6 +26,7 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor; import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
import com.google.android.exoplayer2.source.ExtractorMediaSource; import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
@ -76,10 +77,11 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
DefaultTrackSelector trackSelector = new DefaultTrackSelector(); DefaultTrackSelector trackSelector = new DefaultTrackSelector();
player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector); player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector);
player.addListener(this); player.addListener(this);
ExtractorMediaSource mediaSource = new ExtractorMediaSource.Builder( MediaSource mediaSource =
uri, new DefaultDataSourceFactory(context, "ExoPlayerExtOpusTest")) new ExtractorMediaSource.Factory(
.setExtractorsFactory(MatroskaExtractor.FACTORY) new DefaultDataSourceFactory(context, "ExoPlayerExtOpusTest"))
.build(); .setExtractorsFactory(MatroskaExtractor.FACTORY)
.createMediaSource(uri);
player.prepare(mediaSource); player.prepare(mediaSource);
player.setPlayWhenReady(true); player.setPlayWhenReady(true);
Looper.loop(); Looper.loop();

View File

@ -27,6 +27,7 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor; import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
import com.google.android.exoplayer2.source.ExtractorMediaSource; import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
@ -105,10 +106,11 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
DefaultTrackSelector trackSelector = new DefaultTrackSelector(); DefaultTrackSelector trackSelector = new DefaultTrackSelector();
player = ExoPlayerFactory.newInstance(new Renderer[] {videoRenderer}, trackSelector); player = ExoPlayerFactory.newInstance(new Renderer[] {videoRenderer}, trackSelector);
player.addListener(this); player.addListener(this);
ExtractorMediaSource mediaSource = new ExtractorMediaSource.Builder( MediaSource mediaSource =
uri, new DefaultDataSourceFactory(context, "ExoPlayerExtVp9Test")) new ExtractorMediaSource.Factory(
.setExtractorsFactory(MatroskaExtractor.FACTORY) new DefaultDataSourceFactory(context, "ExoPlayerExtVp9Test"))
.build(); .setExtractorsFactory(MatroskaExtractor.FACTORY)
.createMediaSource(uri);
player.sendMessages(new ExoPlayer.ExoPlayerMessage(videoRenderer, player.sendMessages(new ExoPlayer.ExoPlayerMessage(videoRenderer,
LibvpxVideoRenderer.MSG_SET_OUTPUT_BUFFER_RENDERER, LibvpxVideoRenderer.MSG_SET_OUTPUT_BUFFER_RENDERER,
new VpxVideoSurfaceView(context))); new VpxVideoSurfaceView(context)));

View File

@ -26,6 +26,7 @@ import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorsFactory; import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
@ -103,129 +104,113 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
private long timelineDurationUs; private long timelineDurationUs;
private boolean timelineIsSeekable; private boolean timelineIsSeekable;
/** /** Factory for {@link ExtractorMediaSource}s. */
* Builder for {@link ExtractorMediaSource}. Each builder instance can only be used once. public static final class Factory implements AdsMediaSource.MediaSourceFactory {
*/
public static final class Builder {
private final Uri uri;
private final DataSource.Factory dataSourceFactory; private final DataSource.Factory dataSourceFactory;
private ExtractorsFactory extractorsFactory; private @Nullable ExtractorsFactory extractorsFactory;
private @Nullable String customCacheKey;
private int minLoadableRetryCount; private int minLoadableRetryCount;
@Nullable private Handler eventHandler;
@Nullable private MediaSourceEventListener eventListener;
@Nullable private String customCacheKey;
private int continueLoadingCheckIntervalBytes; private int continueLoadingCheckIntervalBytes;
private boolean isBuildCalled; private boolean isCreateCalled;
/** /**
* @param uri The {@link Uri} of the media stream. * Creates a new factory for {@link ExtractorMediaSource}s.
*
* @param dataSourceFactory A factory for {@link DataSource}s to read the media. * @param dataSourceFactory A factory for {@link DataSource}s to read the media.
*/ */
public Builder(Uri uri, DataSource.Factory dataSourceFactory) { public Factory(DataSource.Factory dataSourceFactory) {
this.uri = uri;
this.dataSourceFactory = dataSourceFactory; this.dataSourceFactory = dataSourceFactory;
minLoadableRetryCount = MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA; minLoadableRetryCount = MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA;
continueLoadingCheckIntervalBytes = DEFAULT_LOADING_CHECK_INTERVAL_BYTES; continueLoadingCheckIntervalBytes = DEFAULT_LOADING_CHECK_INTERVAL_BYTES;
} }
/**
* Sets the factory for {@link Extractor}s to process the media stream. The default value is an
* instance of {@link DefaultExtractorsFactory}.
*
* @param extractorsFactory A factory for {@link Extractor}s to process the media stream. If the
* possible formats are known, pass a factory that instantiates extractors for those
* formats.
* @return This factory, for convenience.
* @throws IllegalStateException If one of the {@code create} methods has already been called.
*/
public Factory setExtractorsFactory(ExtractorsFactory extractorsFactory) {
Assertions.checkState(!isCreateCalled);
this.extractorsFactory = extractorsFactory;
return this;
}
/**
* Sets the custom key that uniquely identifies the original stream. Used for cache indexing.
* The default value is {@code null}.
*
* @param customCacheKey A custom key that uniquely identifies the original stream. Used for
* cache indexing.
* @return This factory, for convenience.
* @throws IllegalStateException If one of the {@code create} methods has already been called.
*/
public Factory setCustomCacheKey(String customCacheKey) {
Assertions.checkState(!isCreateCalled);
this.customCacheKey = customCacheKey;
return this;
}
/** /**
* Sets the minimum number of times to retry if a loading error occurs. The default value is * Sets the minimum number of times to retry if a loading error occurs. The default value is
* {@link #MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA}. * {@link #MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA}.
* *
* @param minLoadableRetryCount The minimum number of times to retry if a loading error occurs. * @param minLoadableRetryCount The minimum number of times to retry if a loading error occurs.
* @return This builder. * @return This factory, for convenience.
* @throws IllegalStateException If one of the {@code create} methods has already been called.
*/ */
public Builder setMinLoadableRetryCount(int minLoadableRetryCount) { public Factory setMinLoadableRetryCount(int minLoadableRetryCount) {
Assertions.checkState(!isCreateCalled);
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
return this; return this;
} }
/** /**
* Sets the factory for {@link Extractor}s to process the media stream. Default value is an * Sets the number of bytes that should be loaded between each invocation of {@link
* instance of {@link DefaultExtractorsFactory}. * MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}. The default value is
* * {@link #DEFAULT_LOADING_CHECK_INTERVAL_BYTES}.
* @param extractorsFactory A factory for {@link Extractor}s to process the media stream. If the
* possible formats are known, pass a factory that instantiates extractors for those
* formats.
* @return This builder.
*/
public Builder setExtractorsFactory(ExtractorsFactory extractorsFactory) {
this.extractorsFactory = extractorsFactory;
return this;
}
/**
* Sets the custom key that uniquely identifies the original stream. Used for cache indexing.
* Default value is null.
*
* @param customCacheKey A custom key that uniquely identifies the original stream. Used for
* cache indexing.
* @return This builder.
*/
public Builder setCustomCacheKey(String customCacheKey) {
this.customCacheKey = customCacheKey;
return this;
}
/**
* Sets the number of bytes that should be loaded between each invocation of
* {@link MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}. Default value
* is {@link #DEFAULT_LOADING_CHECK_INTERVAL_BYTES}.
* *
* @param continueLoadingCheckIntervalBytes The number of bytes that should be loaded between * @param continueLoadingCheckIntervalBytes The number of bytes that should be loaded between
* each invocation of * each invocation of {@link
* {@link MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}. * MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}.
* @return This builder. * @return This factory, for convenience.
* @throws IllegalStateException If one of the {@code create} methods has already been called.
*/ */
public Builder setContinueLoadingCheckIntervalBytes(int continueLoadingCheckIntervalBytes) { public Factory setContinueLoadingCheckIntervalBytes(int continueLoadingCheckIntervalBytes) {
Assertions.checkState(!isCreateCalled);
this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes; this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes;
return this; return this;
} }
/** /**
* Sets the listener to respond to {@link ExtractorMediaSource} events and the handler to * Returns a new {@link ExtractorMediaSource} using the current parameters. Media source events
* deliver these events. * will not be delivered.
* *
* @param eventHandler A handler for events. * @param uri The {@link Uri}.
* @param eventListener A listener of events. * @return The new {@link ExtractorMediaSource}.
* @return This builder.
* @deprecated Use {@link #setEventListener(Handler, MediaSourceEventListener)}.
*/ */
@Deprecated public MediaSource createMediaSource(Uri uri) {
public Builder setEventListener(Handler eventHandler, EventListener eventListener) { return createMediaSource(uri, null, null);
this.eventHandler = eventHandler;
this.eventListener = eventListener == null ? null : new EventListenerWrapper(eventListener);
return this;
} }
/** /**
* Sets the listener to respond to {@link ExtractorMediaSource} events and the handler to * Returns a new {@link ExtractorMediaSource} using the current parameters.
* deliver these events.
* *
* @param uri The {@link Uri}.
* @param eventHandler A handler for events. * @param eventHandler A handler for events.
* @param eventListener A listener of events. * @param eventListener A listener of events.
* @return This builder. * @return The new {@link ExtractorMediaSource}.
*/ */
public Builder setEventListener(Handler eventHandler, MediaSourceEventListener eventListener) { @Override
this.eventHandler = eventHandler; public MediaSource createMediaSource(
this.eventListener = eventListener; Uri uri, @Nullable Handler eventHandler, @Nullable MediaSourceEventListener eventListener) {
return this; isCreateCalled = true;
}
/**
* Builds a new {@link ExtractorMediaSource} using the current parameters.
* <p>
* After this call, the builder should not be re-used.
*
* @return The newly built {@link ExtractorMediaSource}.
*/
public ExtractorMediaSource build() {
Assertions.checkArgument((eventListener == null) == (eventHandler == null));
Assertions.checkState(!isBuildCalled);
isBuildCalled = true;
if (extractorsFactory == null) { if (extractorsFactory == null) {
extractorsFactory = new DefaultExtractorsFactory(); extractorsFactory = new DefaultExtractorsFactory();
} }
@ -234,6 +219,10 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
continueLoadingCheckIntervalBytes); continueLoadingCheckIntervalBytes);
} }
@Override
public int[] getSupportedTypes() {
return new int[] {C.TYPE_OTHER};
}
} }
/** /**
@ -244,11 +233,15 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
* Otherwise, pass a {@link DefaultExtractorsFactory} to use default extractors. * Otherwise, pass a {@link DefaultExtractorsFactory} to use default extractors.
* @param eventHandler A handler for events. May be null if delivery of events is not required. * @param eventHandler A handler for events. May be null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
* @deprecated Use {@link Builder} instead. * @deprecated Use {@link Factory} instead.
*/ */
@Deprecated @Deprecated
public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory, public ExtractorMediaSource(
ExtractorsFactory extractorsFactory, Handler eventHandler, EventListener eventListener) { Uri uri,
DataSource.Factory dataSourceFactory,
ExtractorsFactory extractorsFactory,
Handler eventHandler,
EventListener eventListener) {
this(uri, dataSourceFactory, extractorsFactory, eventHandler, eventListener, null); this(uri, dataSourceFactory, extractorsFactory, eventHandler, eventListener, null);
} }
@ -262,11 +255,15 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
* @param customCacheKey A custom key that uniquely identifies the original stream. Used for cache * @param customCacheKey A custom key that uniquely identifies the original stream. Used for cache
* indexing. May be null. * indexing. May be null.
* @deprecated Use {@link Builder} instead. * @deprecated Use {@link Factory} instead.
*/ */
@Deprecated @Deprecated
public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory, public ExtractorMediaSource(
ExtractorsFactory extractorsFactory, Handler eventHandler, EventListener eventListener, Uri uri,
DataSource.Factory dataSourceFactory,
ExtractorsFactory extractorsFactory,
Handler eventHandler,
EventListener eventListener,
String customCacheKey) { String customCacheKey) {
this(uri, dataSourceFactory, extractorsFactory, MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA, eventHandler, this(uri, dataSourceFactory, extractorsFactory, MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA, eventHandler,
eventListener, customCacheKey, DEFAULT_LOADING_CHECK_INTERVAL_BYTES); eventListener, customCacheKey, DEFAULT_LOADING_CHECK_INTERVAL_BYTES);
@ -285,12 +282,18 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
* indexing. May be null. * indexing. May be null.
* @param continueLoadingCheckIntervalBytes The number of bytes that should be loaded between each * @param continueLoadingCheckIntervalBytes The number of bytes that should be loaded between each
* invocation of {@link MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}. * invocation of {@link MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}.
* @deprecated Use {@link Builder} instead. * @deprecated Use {@link Factory} instead.
*/ */
@Deprecated @Deprecated
public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory, public ExtractorMediaSource(
ExtractorsFactory extractorsFactory, int minLoadableRetryCount, Handler eventHandler, Uri uri,
EventListener eventListener, String customCacheKey, int continueLoadingCheckIntervalBytes) { DataSource.Factory dataSourceFactory,
ExtractorsFactory extractorsFactory,
int minLoadableRetryCount,
Handler eventHandler,
EventListener eventListener,
String customCacheKey,
int continueLoadingCheckIntervalBytes) {
this( this(
uri, uri,
dataSourceFactory, dataSourceFactory,

View File

@ -163,7 +163,7 @@ public final class AdsMediaSource implements MediaSource {
this.eventListener = eventListener; this.eventListener = eventListener;
mainHandler = new Handler(Looper.getMainLooper()); mainHandler = new Handler(Looper.getMainLooper());
componentListener = new ComponentListener(); componentListener = new ComponentListener();
adMediaSourceFactory = new ExtractorMediaSourceFactory(dataSourceFactory); adMediaSourceFactory = new ExtractorMediaSource.Factory(dataSourceFactory);
deferredMediaPeriodByAdMediaSource = new HashMap<>(); deferredMediaPeriodByAdMediaSource = new HashMap<>();
period = new Timeline.Period(); period = new Timeline.Period();
adGroupMediaSources = new MediaSource[0][]; adGroupMediaSources = new MediaSource[0][];
@ -396,28 +396,4 @@ public final class AdsMediaSource implements MediaSource {
} }
private static final class ExtractorMediaSourceFactory implements MediaSourceFactory {
private final DataSource.Factory dataSourceFactory;
public ExtractorMediaSourceFactory(DataSource.Factory dataSourceFactory) {
this.dataSourceFactory = dataSourceFactory;
}
@Override
public MediaSource createMediaSource(
Uri uri, @Nullable Handler handler, @Nullable MediaSourceEventListener listener) {
return new ExtractorMediaSource.Builder(uri, dataSourceFactory)
.setEventListener(handler, listener)
.build();
}
@Override
public int[] getSupportedTypes() {
// Only ExtractorMediaSource is supported.
return new int[] {C.TYPE_OTHER};
}
}
} }