diff --git a/demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/PlayerManager.java b/demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/PlayerManager.java index 20ef72f9f2..aec53c8e8a 100644 --- a/demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/PlayerManager.java +++ b/demos/cast/src/main/java/com/google/android/exoplayer2/castdemo/PlayerManager.java @@ -396,9 +396,7 @@ import java.util.ArrayList; new DefaultDashChunkSource.Factory(DATA_SOURCE_FACTORY), DATA_SOURCE_FACTORY) .createMediaSource(uri); case DemoUtil.MIME_TYPE_HLS: - return HlsMediaSource.Builder - .forDataSource(uri, DATA_SOURCE_FACTORY) - .build(); + return new HlsMediaSource.Factory(DATA_SOURCE_FACTORY).createMediaSource(uri); case DemoUtil.MIME_TYPE_VIDEO_MP4: return new ExtractorMediaSource.Builder(uri, DATA_SOURCE_FACTORY).build(); default: { 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 38938bd367..215c4708e8 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 @@ -375,10 +375,8 @@ public class PlayerActivity extends Activity implements OnClickListener, buildDataSourceFactory(false)) .createMediaSource(uri, mainHandler, eventLogger); case C.TYPE_HLS: - return HlsMediaSource.Builder - .forDataSource(uri, mediaDataSourceFactory) - .setEventListener(mainHandler, eventLogger) - .build(); + return new HlsMediaSource.Factory(mediaDataSourceFactory) + .createMediaSource(uri, mainHandler, eventLogger); case C.TYPE_OTHER: return new ExtractorMediaSource.Builder(uri, mediaDataSourceFactory) .setEventListener(mainHandler, eventLogger) diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java index 1cddf6e94e..4c14d2029e 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java @@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source.hls; import android.net.Uri; import android.os.Handler; +import android.support.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; @@ -29,6 +30,7 @@ import com.google.android.exoplayer2.source.MediaSourceEventListener; import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.SequenceableLoader; import com.google.android.exoplayer2.source.SinglePeriodTimeline; +import com.google.android.exoplayer2.source.ads.AdsMediaSource; import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist; import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylist; import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser; @@ -50,68 +52,54 @@ public final class HlsMediaSource implements MediaSource, ExoPlayerLibraryInfo.registerModule("goog.exo.hls"); } - /** - * Builder for {@link HlsMediaSource}. Each builder instance can only be used once. - */ - public static final class Builder { + /** Factory for {@link HlsMediaSource}s. */ + public static final class Factory implements AdsMediaSource.MediaSourceFactory { - private final Uri manifestUri; private final HlsDataSourceFactory hlsDataSourceFactory; private HlsExtractorFactory extractorFactory; - private ParsingLoadable.Parser playlistParser; - private MediaSourceEventListener eventListener; - private Handler eventHandler; + private @Nullable ParsingLoadable.Parser playlistParser; private CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory; private int minLoadableRetryCount; private boolean allowChunklessPreparation; - - private boolean isBuildCalled; + private boolean isCreateCalled; /** - * Creates a {@link Builder} for a {@link HlsMediaSource} with a loadable manifest Uri and - * a {@link DataSource.Factory}. + * Creates a new factory for {@link HlsMediaSource}s. * - * @param manifestUri The {@link Uri} of the HLS manifest. - * @param dataSourceFactory A data source factory that will be wrapped by a - * {@link DefaultHlsDataSourceFactory} to build {@link DataSource}s for manifests, - * segments and keys. - * @return A new builder. + * @param dataSourceFactory A data source factory that will be wrapped by a {@link + * DefaultHlsDataSourceFactory} to create {@link DataSource}s for manifests, segments and + * keys. */ - public static Builder forDataSource(Uri manifestUri, DataSource.Factory dataSourceFactory) { - return new Builder(manifestUri, new DefaultHlsDataSourceFactory(dataSourceFactory)); + public Factory(DataSource.Factory dataSourceFactory) { + this(new DefaultHlsDataSourceFactory(dataSourceFactory)); } /** - * Creates a {@link Builder} for a {@link HlsMediaSource} with a loadable manifest Uri and - * a {@link HlsDataSourceFactory}. + * Creates a new factory for {@link HlsMediaSource}s. * - * @param manifestUri The {@link Uri} of the HLS manifest. - * @param dataSourceFactory An {@link HlsDataSourceFactory} for {@link DataSource}s for + * @param hlsDataSourceFactory An {@link HlsDataSourceFactory} for {@link DataSource}s for * manifests, segments and keys. - * @return A new builder. */ - public static Builder forHlsDataSource(Uri manifestUri, - HlsDataSourceFactory dataSourceFactory) { - return new Builder(manifestUri, dataSourceFactory); - } - - private Builder(Uri manifestUri, HlsDataSourceFactory hlsDataSourceFactory) { - this.manifestUri = manifestUri; - this.hlsDataSourceFactory = hlsDataSourceFactory; + public Factory(HlsDataSourceFactory hlsDataSourceFactory) { + this.hlsDataSourceFactory = Assertions.checkNotNull(hlsDataSourceFactory); + extractorFactory = HlsExtractorFactory.DEFAULT; minLoadableRetryCount = DEFAULT_MIN_LOADABLE_RETRY_COUNT; + compositeSequenceableLoaderFactory = new DefaultCompositeSequenceableLoaderFactory(); } /** - * Sets the factory for {@link Extractor}s for the segments. Default value is - * {@link HlsExtractorFactory#DEFAULT}. + * Sets the factory for {@link Extractor}s for the segments. The default value is {@link + * HlsExtractorFactory#DEFAULT}. * * @param extractorFactory An {@link HlsExtractorFactory} for {@link Extractor}s for the - * segments. - * @return This builder. + * segments. + * @return This factory, for convenience. + * @throws IllegalStateException If one of the {@code create} methods has already been called. */ - public Builder setExtractorFactory(HlsExtractorFactory extractorFactory) { - this.extractorFactory = extractorFactory; + public Factory setExtractorFactory(HlsExtractorFactory extractorFactory) { + Assertions.checkState(!isCreateCalled); + this.extractorFactory = Assertions.checkNotNull(extractorFactory); return this; } @@ -119,54 +107,46 @@ public final class HlsMediaSource implements MediaSource, * Sets the minimum number of times to retry if a loading error occurs. The default value is * {@link #DEFAULT_MIN_LOADABLE_RETRY_COUNT}. * - * @param minLoadableRetryCount The minimum number of times loads must be retried before - * errors are propagated. - * @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 setMinLoadableRetryCount(int minLoadableRetryCount) { + public Factory setMinLoadableRetryCount(int minLoadableRetryCount) { + Assertions.checkState(!isCreateCalled); this.minLoadableRetryCount = minLoadableRetryCount; return this; } /** - * Sets the listener to respond to adaptive {@link MediaSource} events and the handler to - * deliver these events. - * - * @param eventHandler A handler for events. - * @param eventListener A listener of events. - * @return This builder. - */ - public Builder setEventListener(Handler eventHandler, MediaSourceEventListener eventListener) { - this.eventHandler = eventHandler; - this.eventListener = eventListener; - return this; - } - - /** - * Sets the parser to parse HLS playlists. The default is an instance of - * {@link HlsPlaylistParser}. + * Sets the parser to parse HLS playlists. The default is an instance of {@link + * HlsPlaylistParser}. * * @param playlistParser A {@link ParsingLoadable.Parser} for HLS playlists. - * @return This builder. + * @return This factory, for convenience. + * @throws IllegalStateException If one of the {@code create} methods has already been called. */ - public Builder setPlaylistParser(ParsingLoadable.Parser playlistParser) { - this.playlistParser = playlistParser; + public Factory setPlaylistParser(ParsingLoadable.Parser playlistParser) { + Assertions.checkState(!isCreateCalled); + this.playlistParser = Assertions.checkNotNull(playlistParser); return this; } /** * Sets the factory to create composite {@link SequenceableLoader}s for when this media source - * loads data from multiple streams (video, audio etc...). The default is an instance of - * {@link DefaultCompositeSequenceableLoaderFactory}. + * loads data from multiple streams (video, audio etc...). The default is an instance of {@link + * DefaultCompositeSequenceableLoaderFactory}. * - * @param compositeSequenceableLoaderFactory A factory to create composite - * {@link SequenceableLoader}s for when this media source loads data from multiple streams - * (video, audio etc...). - * @return This builder. + * @param compositeSequenceableLoaderFactory A factory to create composite {@link + * SequenceableLoader}s for when this media source loads data from multiple streams (video, + * audio etc...). + * @return This factory, for convenience. + * @throws IllegalStateException If one of the {@code create} methods has already been called. */ - public Builder setCompositeSequenceableLoaderFactory( + public Factory setCompositeSequenceableLoaderFactory( CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory) { - this.compositeSequenceableLoaderFactory = compositeSequenceableLoaderFactory; + Assertions.checkState(!isCreateCalled); + this.compositeSequenceableLoaderFactory = + Assertions.checkNotNull(compositeSequenceableLoaderFactory); return this; } @@ -175,35 +155,44 @@ public final class HlsMediaSource implements MediaSource, * will be enabled for streams that provide sufficient information in their master playlist. * * @param allowChunklessPreparation Whether chunkless preparation is allowed. - * @return This builder. + * @return This factory, for convenience. + * @throws IllegalStateException If one of the {@code create} methods has already been called. */ - public Builder setAllowChunklessPreparation(boolean allowChunklessPreparation) { + public Factory setAllowChunklessPreparation(boolean allowChunklessPreparation) { + Assertions.checkState(!isCreateCalled); this.allowChunklessPreparation = allowChunklessPreparation; return this; } /** - * Builds a new {@link HlsMediaSource} using the current parameters. - *

- * After this call, the builder should not be re-used. + * Returns a new {@link HlsMediaSource} using the current parameters. Media source events will + * not be delivered. * - * @return The newly built {@link HlsMediaSource}. + * @return The new {@link HlsMediaSource}. */ - public HlsMediaSource build() { - Assertions.checkArgument((eventListener == null) == (eventHandler == null)); - Assertions.checkState(!isBuildCalled); - isBuildCalled = true; - if (extractorFactory == null) { - extractorFactory = HlsExtractorFactory.DEFAULT; - } + public MediaSource createMediaSource(Uri playlistUri) { + return createMediaSource(playlistUri, null, null); + } + + /** + * Returns a new {@link HlsMediaSource} using the current parameters. + * + * @param playlistUri The playlist {@link Uri}. + * @param eventHandler A handler for events. + * @param eventListener A listener of events. + * @return The new {@link HlsMediaSource}. + */ + @Override + public MediaSource createMediaSource( + Uri playlistUri, + @Nullable Handler eventHandler, + @Nullable MediaSourceEventListener eventListener) { + isCreateCalled = true; if (playlistParser == null) { playlistParser = new HlsPlaylistParser(); } - if (compositeSequenceableLoaderFactory == null) { - compositeSequenceableLoaderFactory = new DefaultCompositeSequenceableLoaderFactory(); - } return new HlsMediaSource( - manifestUri, + playlistUri, hlsDataSourceFactory, extractorFactory, compositeSequenceableLoaderFactory, @@ -214,6 +203,10 @@ public final class HlsMediaSource implements MediaSource, allowChunklessPreparation); } + @Override + public int[] getSupportedTypes() { + return new int[] {C.TYPE_HLS}; + } } /** @@ -240,7 +233,7 @@ public final class HlsMediaSource implements MediaSource, * @param eventHandler A handler for events. May be null if delivery of events is not required. * @param eventListener A {@link MediaSourceEventListener}. May be null if delivery of events is * not required. - * @deprecated Use {@link Builder} instead. + * @deprecated Use {@link Factory} instead. */ @Deprecated public HlsMediaSource( @@ -261,7 +254,7 @@ public final class HlsMediaSource implements MediaSource, * @param eventHandler A handler for events. May be null if delivery of events is not required. * @param eventListener A {@link MediaSourceEventListener}. May be null if delivery of events is * not required. - * @deprecated Use {@link Builder} instead. + * @deprecated Use {@link Factory} instead. */ @Deprecated public HlsMediaSource( @@ -286,7 +279,7 @@ public final class HlsMediaSource implements MediaSource, * @param eventListener A {@link MediaSourceEventListener}. May be null if delivery of events is * not required. * @param playlistParser A {@link ParsingLoadable.Parser} for HLS playlists. - * @deprecated Use {@link Builder} instead. + * @deprecated Use {@link Factory} instead. */ @Deprecated public HlsMediaSource(