From f31696b79a608328454f1ae20ef8801aba91dfd0 Mon Sep 17 00:00:00 2001 From: andrewlewis Date: Mon, 11 Dec 2017 05:23:00 -0800 Subject: [PATCH] Make ExtractorMediaSource.Builder a factory for ExtractorMediaSources ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=178605481 --- .../exoplayer2/imademo/PlayerManager.java | 3 +- .../exoplayer2/demo/PlayerActivity.java | 5 +- .../exoplayer2/ext/flac/FlacPlaybackTest.java | 10 +- .../exoplayer2/ext/opus/OpusPlaybackTest.java | 10 +- .../exoplayer2/ext/vp9/VpxPlaybackTest.java | 10 +- .../source/ExtractorMediaSource.java | 159 +++++++++--------- .../exoplayer2/source/ads/AdsMediaSource.java | 26 +-- 7 files changed, 104 insertions(+), 119 deletions(-) diff --git a/demos/ima/src/main/java/com/google/android/exoplayer2/imademo/PlayerManager.java b/demos/ima/src/main/java/com/google/android/exoplayer2/imademo/PlayerManager.java index 6b840830c5e..ec21f6d2654 100644 --- a/demos/ima/src/main/java/com/google/android/exoplayer2/imademo/PlayerManager.java +++ b/demos/ima/src/main/java/com/google/android/exoplayer2/imademo/PlayerManager.java @@ -70,7 +70,8 @@ public void init(Context context, SimpleExoPlayerView simpleExoPlayerView) { // This is the MediaSource representing the content media (i.e. not the ad). String contentUrl = context.getString(R.string.content_url); 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. MediaSource mediaSourceWithAds = new AdsMediaSource(contentMediaSource, dataSourceFactory, diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java index 215c4708e85..a60ae0c8766 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java @@ -378,9 +378,8 @@ private MediaSource buildMediaSource(Uri uri, String overrideExtension) { return new HlsMediaSource.Factory(mediaDataSourceFactory) .createMediaSource(uri, mainHandler, eventLogger); case C.TYPE_OTHER: - return new ExtractorMediaSource.Builder(uri, mediaDataSourceFactory) - .setEventListener(mainHandler, eventLogger) - .build(); + return new ExtractorMediaSource.Factory(mediaDataSourceFactory) + .createMediaSource(uri, mainHandler, eventLogger); default: { throw new IllegalStateException("Unsupported type: " + type); } diff --git a/extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java b/extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java index bd6e698dc6e..fd18a3b1ae0 100644 --- a/extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java +++ b/extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java @@ -26,6 +26,7 @@ import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor; 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.upstream.DefaultDataSourceFactory; @@ -76,10 +77,11 @@ public void run() { DefaultTrackSelector trackSelector = new DefaultTrackSelector(); player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector); player.addListener(this); - ExtractorMediaSource mediaSource = new ExtractorMediaSource.Builder( - uri, new DefaultDataSourceFactory(context, "ExoPlayerExtFlacTest")) - .setExtractorsFactory(MatroskaExtractor.FACTORY) - .build(); + MediaSource mediaSource = + new ExtractorMediaSource.Factory( + new DefaultDataSourceFactory(context, "ExoPlayerExtFlacTest")) + .setExtractorsFactory(MatroskaExtractor.FACTORY) + .createMediaSource(uri); player.prepare(mediaSource); player.setPlayWhenReady(true); Looper.loop(); diff --git a/extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java b/extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java index aa61df74d9a..d3ab4216552 100644 --- a/extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java +++ b/extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java @@ -26,6 +26,7 @@ import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor; 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.upstream.DefaultDataSourceFactory; @@ -76,10 +77,11 @@ public void run() { DefaultTrackSelector trackSelector = new DefaultTrackSelector(); player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector); player.addListener(this); - ExtractorMediaSource mediaSource = new ExtractorMediaSource.Builder( - uri, new DefaultDataSourceFactory(context, "ExoPlayerExtOpusTest")) - .setExtractorsFactory(MatroskaExtractor.FACTORY) - .build(); + MediaSource mediaSource = + new ExtractorMediaSource.Factory( + new DefaultDataSourceFactory(context, "ExoPlayerExtOpusTest")) + .setExtractorsFactory(MatroskaExtractor.FACTORY) + .createMediaSource(uri); player.prepare(mediaSource); player.setPlayWhenReady(true); Looper.loop(); diff --git a/extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java b/extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java index 746f3d273f9..3cc1a1d340b 100644 --- a/extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java +++ b/extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java @@ -27,6 +27,7 @@ import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor; 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.upstream.DefaultDataSourceFactory; @@ -105,10 +106,11 @@ public void run() { DefaultTrackSelector trackSelector = new DefaultTrackSelector(); player = ExoPlayerFactory.newInstance(new Renderer[] {videoRenderer}, trackSelector); player.addListener(this); - ExtractorMediaSource mediaSource = new ExtractorMediaSource.Builder( - uri, new DefaultDataSourceFactory(context, "ExoPlayerExtVp9Test")) - .setExtractorsFactory(MatroskaExtractor.FACTORY) - .build(); + MediaSource mediaSource = + new ExtractorMediaSource.Factory( + new DefaultDataSourceFactory(context, "ExoPlayerExtVp9Test")) + .setExtractorsFactory(MatroskaExtractor.FACTORY) + .createMediaSource(uri); player.sendMessages(new ExoPlayer.ExoPlayerMessage(videoRenderer, LibvpxVideoRenderer.MSG_SET_OUTPUT_BUFFER_RENDERER, new VpxVideoSurfaceView(context))); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java index 247eacd519c..e787c34a9cd 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java @@ -26,6 +26,7 @@ import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorsFactory; 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.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; @@ -103,129 +104,113 @@ public interface EventListener { private long timelineDurationUs; private boolean timelineIsSeekable; - /** - * Builder for {@link ExtractorMediaSource}. Each builder instance can only be used once. - */ - public static final class Builder { + /** Factory for {@link ExtractorMediaSource}s. */ + public static final class Factory implements AdsMediaSource.MediaSourceFactory { - private final Uri uri; private final DataSource.Factory dataSourceFactory; - private ExtractorsFactory extractorsFactory; + private @Nullable ExtractorsFactory extractorsFactory; + private @Nullable String customCacheKey; private int minLoadableRetryCount; - @Nullable private Handler eventHandler; - @Nullable private MediaSourceEventListener eventListener; - @Nullable private String customCacheKey; 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. */ - public Builder(Uri uri, DataSource.Factory dataSourceFactory) { - this.uri = uri; + public Factory(DataSource.Factory dataSourceFactory) { this.dataSourceFactory = dataSourceFactory; - minLoadableRetryCount = MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA; continueLoadingCheckIntervalBytes = DEFAULT_LOADING_CHECK_INTERVAL_BYTES; } /** - * Sets the minimum number of times to retry if a loading error occurs. The default value is - * {@link #MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA}. - * - * @param minLoadableRetryCount The minimum number of times to retry if a loading error occurs. - * @return This builder. - */ - public Builder setMinLoadableRetryCount(int minLoadableRetryCount) { - this.minLoadableRetryCount = minLoadableRetryCount; - return this; - } - - /** - * Sets the factory for {@link Extractor}s to process the media stream. Default value is an + * 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 builder. + * @return This factory, for convenience. + * @throws IllegalStateException If one of the {@code create} methods has already been called. */ - public Builder setExtractorsFactory(ExtractorsFactory extractorsFactory) { + 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. - * Default value is null. + * The default value is {@code null}. * * @param customCacheKey A custom key that uniquely identifies the original stream. Used for * cache indexing. - * @return This builder. + * @return This factory, for convenience. + * @throws IllegalStateException If one of the {@code create} methods has already been called. */ - public Builder setCustomCacheKey(String customCacheKey) { + public Factory setCustomCacheKey(String customCacheKey) { + Assertions.checkState(!isCreateCalled); 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}. + * Sets the minimum number of times to retry if a loading error occurs. The default value is + * {@link #MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA}. * - * @param continueLoadingCheckIntervalBytes The number of bytes that should be loaded between - * each invocation of - * {@link MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}. - * @return This builder. + * @param minLoadableRetryCount The minimum number of times to retry if a loading error occurs. + * @return This factory, for convenience. + * @throws IllegalStateException If one of the {@code create} methods has already been called. */ - public Builder setContinueLoadingCheckIntervalBytes(int continueLoadingCheckIntervalBytes) { - this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes; + public Factory setMinLoadableRetryCount(int minLoadableRetryCount) { + Assertions.checkState(!isCreateCalled); + this.minLoadableRetryCount = minLoadableRetryCount; return this; } /** - * Sets the listener to respond to {@link ExtractorMediaSource} events and the handler to - * deliver these events. + * Sets the number of bytes that should be loaded between each invocation of {@link + * MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}. The default value is + * {@link #DEFAULT_LOADING_CHECK_INTERVAL_BYTES}. * - * @param eventHandler A handler for events. - * @param eventListener A listener of events. - * @return This builder. - * @deprecated Use {@link #setEventListener(Handler, MediaSourceEventListener)}. + * @param continueLoadingCheckIntervalBytes The number of bytes that should be loaded between + * each invocation of {@link + * MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}. + * @return This factory, for convenience. + * @throws IllegalStateException If one of the {@code create} methods has already been called. */ - @Deprecated - public Builder setEventListener(Handler eventHandler, EventListener eventListener) { - this.eventHandler = eventHandler; - this.eventListener = eventListener == null ? null : new EventListenerWrapper(eventListener); + public Factory setContinueLoadingCheckIntervalBytes(int continueLoadingCheckIntervalBytes) { + Assertions.checkState(!isCreateCalled); + this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes; return this; } /** - * Sets the listener to respond to {@link ExtractorMediaSource} events and the handler to - * deliver these events. + * Returns a new {@link ExtractorMediaSource} using the current parameters. Media source events + * will not be delivered. * - * @param eventHandler A handler for events. - * @param eventListener A listener of events. - * @return This builder. + * @param uri The {@link Uri}. + * @return The new {@link ExtractorMediaSource}. */ - public Builder setEventListener(Handler eventHandler, MediaSourceEventListener eventListener) { - this.eventHandler = eventHandler; - this.eventListener = eventListener; - return this; + public MediaSource createMediaSource(Uri uri) { + return createMediaSource(uri, null, null); } /** - * Builds a new {@link ExtractorMediaSource} using the current parameters. - *

- * After this call, the builder should not be re-used. + * Returns a new {@link ExtractorMediaSource} using the current parameters. * - * @return The newly built {@link ExtractorMediaSource}. + * @param uri The {@link Uri}. + * @param eventHandler A handler for events. + * @param eventListener A listener of events. + * @return The new {@link ExtractorMediaSource}. */ - public ExtractorMediaSource build() { - Assertions.checkArgument((eventListener == null) == (eventHandler == null)); - Assertions.checkState(!isBuildCalled); - isBuildCalled = true; + @Override + public MediaSource createMediaSource( + Uri uri, @Nullable Handler eventHandler, @Nullable MediaSourceEventListener eventListener) { + isCreateCalled = true; if (extractorsFactory == null) { extractorsFactory = new DefaultExtractorsFactory(); } @@ -234,6 +219,10 @@ public ExtractorMediaSource build() { continueLoadingCheckIntervalBytes); } + @Override + public int[] getSupportedTypes() { + return new int[] {C.TYPE_OTHER}; + } } /** @@ -244,11 +233,15 @@ public ExtractorMediaSource build() { * 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 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 - public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory, - ExtractorsFactory extractorsFactory, Handler eventHandler, EventListener eventListener) { + public ExtractorMediaSource( + Uri uri, + DataSource.Factory dataSourceFactory, + ExtractorsFactory extractorsFactory, + Handler eventHandler, + EventListener eventListener) { this(uri, dataSourceFactory, extractorsFactory, eventHandler, eventListener, null); } @@ -262,11 +255,15 @@ public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory, * @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 * indexing. May be null. - * @deprecated Use {@link Builder} instead. + * @deprecated Use {@link Factory} instead. */ @Deprecated - public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory, - ExtractorsFactory extractorsFactory, Handler eventHandler, EventListener eventListener, + public ExtractorMediaSource( + Uri uri, + DataSource.Factory dataSourceFactory, + ExtractorsFactory extractorsFactory, + Handler eventHandler, + EventListener eventListener, String customCacheKey) { this(uri, dataSourceFactory, extractorsFactory, MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA, eventHandler, eventListener, customCacheKey, DEFAULT_LOADING_CHECK_INTERVAL_BYTES); @@ -285,12 +282,18 @@ public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory, * indexing. May be null. * @param continueLoadingCheckIntervalBytes The number of bytes that should be loaded between each * invocation of {@link MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}. - * @deprecated Use {@link Builder} instead. + * @deprecated Use {@link Factory} instead. */ @Deprecated - public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory, - ExtractorsFactory extractorsFactory, int minLoadableRetryCount, Handler eventHandler, - EventListener eventListener, String customCacheKey, int continueLoadingCheckIntervalBytes) { + public ExtractorMediaSource( + Uri uri, + DataSource.Factory dataSourceFactory, + ExtractorsFactory extractorsFactory, + int minLoadableRetryCount, + Handler eventHandler, + EventListener eventListener, + String customCacheKey, + int continueLoadingCheckIntervalBytes) { this( uri, dataSourceFactory, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java index c701d6ca647..5611bedccac 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java @@ -163,7 +163,7 @@ public AdsMediaSource( this.eventListener = eventListener; mainHandler = new Handler(Looper.getMainLooper()); componentListener = new ComponentListener(); - adMediaSourceFactory = new ExtractorMediaSourceFactory(dataSourceFactory); + adMediaSourceFactory = new ExtractorMediaSource.Factory(dataSourceFactory); deferredMediaPeriodByAdMediaSource = new HashMap<>(); period = new Timeline.Period(); adGroupMediaSources = new MediaSource[0][]; @@ -396,28 +396,4 @@ public void run() { } - 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}; - } - - } - }