From 0be4b46bb486443a3bddd8a9c7e772cc0053ff0f Mon Sep 17 00:00:00 2001 From: hoangtc Date: Mon, 13 Nov 2017 07:28:57 -0800 Subject: [PATCH] Introduce Builder pattern to create MediaSource. Start with DASH MediaSource. The number of injected arguments is getting out-of-control. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=175529031 --- .../exoplayer2/castdemo/PlayerManager.java | 6 +- .../exoplayer2/demo/PlayerActivity.java | 7 +- .../source/dash/DashMediaSource.java | 147 ++++++++++++++++++ .../playbacktests/gts/DashTestRunner.java | 7 +- 4 files changed, 161 insertions(+), 6 deletions(-) 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 77dc018a73..ae0fdadfc9 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 @@ -160,8 +160,10 @@ import com.google.android.gms.cast.framework.CastContext; return new SsMediaSource(uri, DATA_SOURCE_FACTORY, new DefaultSsChunkSource.Factory(DATA_SOURCE_FACTORY), null, null); case DemoUtil.MIME_TYPE_DASH: - return new DashMediaSource(uri, DATA_SOURCE_FACTORY, - new DefaultDashChunkSource.Factory(DATA_SOURCE_FACTORY), null, null); + return DashMediaSource.Builder + .forManifestUri(uri, DATA_SOURCE_FACTORY, + new DefaultDashChunkSource.Factory(DATA_SOURCE_FACTORY)) + .build(); case DemoUtil.MIME_TYPE_HLS: return new HlsMediaSource(uri, DATA_SOURCE_FACTORY, null, null); case DemoUtil.MIME_TYPE_VIDEO_MP4: 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 08c5bddb09..614626077a 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 @@ -365,8 +365,11 @@ public class PlayerActivity extends Activity implements OnClickListener, return new SsMediaSource(uri, buildDataSourceFactory(false), new DefaultSsChunkSource.Factory(mediaDataSourceFactory), mainHandler, eventLogger); case C.TYPE_DASH: - return new DashMediaSource(uri, buildDataSourceFactory(false), - new DefaultDashChunkSource.Factory(mediaDataSourceFactory), mainHandler, eventLogger); + return DashMediaSource.Builder + .forManifestUri(uri, buildDataSourceFactory(false), + new DefaultDashChunkSource.Factory(mediaDataSourceFactory)) + .setEventListener(mainHandler, eventLogger) + .build(); case C.TYPE_HLS: return new HlsMediaSource(uri, mediaDataSourceFactory, mainHandler, eventLogger); case C.TYPE_OTHER: diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java index c529fcab4b..3d5a9c393d 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java @@ -18,6 +18,7 @@ package com.google.android.exoplayer2.source.dash; import android.net.Uri; import android.os.Handler; import android.os.SystemClock; +import android.support.annotation.Nullable; import android.util.Log; import android.util.SparseArray; import com.google.android.exoplayer2.C; @@ -114,6 +115,142 @@ public final class DashMediaSource implements MediaSource { private int firstPeriodId; + /** + * Builder for {@link DashMediaSource}. Each builder instance can only be used once. + */ + public static final class Builder { + + private final DashManifest manifest; + private final Uri manifestUri; + private final DataSource.Factory manifestDataSourceFactory; + private final DashChunkSource.Factory chunkSourceFactory; + + private ParsingLoadable.Parser manifestParser; + private AdaptiveMediaSourceEventListener eventListener; + private Handler eventHandler; + + private int minLoadableRetryCount; + private long livePresentationDelayMs; + private boolean isBuildCalled; + + /** + * Creates a {@link Builder} for a {@link DashMediaSource} with a side-loaded manifest. + * + * @param manifest The manifest. {@link DashManifest#dynamic} must be false. + * @param chunkSourceFactory A factory for {@link DashChunkSource} instances. + * @return A new builder. + */ + public static Builder forSideLoadedManifest(DashManifest manifest, + DashChunkSource.Factory chunkSourceFactory) { + return new Builder(manifest, null, null, chunkSourceFactory); + } + + /** + * Creates a {@link Builder} for a {@link DashMediaSource} with a loadable manifest Uri. + * + * @param manifestUri The manifest {@link Uri}. + * @param manifestDataSourceFactory A factory for {@link DataSource} instances that will be used + * to load (and refresh) the manifest. + * @param chunkSourceFactory A factory for {@link DashChunkSource} instances. + * @return A new builder. + */ + public static Builder forManifestUri(Uri manifestUri, + DataSource.Factory manifestDataSourceFactory, DashChunkSource.Factory chunkSourceFactory) { + return new Builder(null, manifestUri, manifestDataSourceFactory, chunkSourceFactory); + } + + private Builder(@Nullable DashManifest manifest, @Nullable Uri manifestUri, + @Nullable DataSource.Factory manifestDataSourceFactory, + DashChunkSource.Factory chunkSourceFactory) { + this.manifest = manifest; + this.manifestUri = manifestUri; + this.manifestDataSourceFactory = manifestDataSourceFactory; + this.chunkSourceFactory = chunkSourceFactory; + + minLoadableRetryCount = DEFAULT_MIN_LOADABLE_RETRY_COUNT; + livePresentationDelayMs = DEFAULT_LIVE_PRESENTATION_DELAY_PREFER_MANIFEST_MS; + } + + /** + * 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 to retry if a loading error occurs. + * @return This builder. + */ + public Builder setMinLoadableRetryCount(int minLoadableRetryCount) { + this.minLoadableRetryCount = minLoadableRetryCount; + return this; + } + + /** + * Sets the duration in milliseconds by which the default start position should precede the end + * of the live window for live playbacks. The default value is + * {@link #DEFAULT_LIVE_PRESENTATION_DELAY_PREFER_MANIFEST_MS}. + * + * @param livePresentationDelayMs For live playbacks, the duration in milliseconds by which the + * default start position should precede the end of the live window. Use + * {@link #DEFAULT_LIVE_PRESENTATION_DELAY_PREFER_MANIFEST_MS} to use the value specified by + * the manifest, if present. + * @return This builder. + */ + public Builder setLivePresentationDelayMs(long livePresentationDelayMs) { + this.livePresentationDelayMs = livePresentationDelayMs; + 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, + AdaptiveMediaSourceEventListener eventListener) { + this.eventHandler = eventHandler; + this.eventListener = eventListener; + return this; + } + + /** + * Sets the manifest parser to parse loaded manifest data. The default is + * {@link DashManifestParser}, or {@code null} if the manifest is sideloaded. + * + * @param manifestParser A parser for loaded manifest data. + * @return This builder. + */ + public Builder setManifestParser( + ParsingLoadable.Parser manifestParser) { + this.manifestParser = manifestParser; + return this; + } + + + /** + * Builds a new {@link DashMediaSource} using the current parameters. + *

+ * After this call, the builder should not be re-used. + * + * @return The newly built {@link DashMediaSource}. + */ + public DashMediaSource build() { + Assertions.checkArgument(manifest == null || !manifest.dynamic); + Assertions.checkArgument((eventListener == null) == (eventHandler == null)); + Assertions.checkState(!isBuildCalled); + isBuildCalled = true; + boolean loadableManifestUri = manifestUri != null; + if (loadableManifestUri && manifestParser == null) { + manifestParser = new DashManifestParser(); + } + return new DashMediaSource(manifest, manifestUri, manifestDataSourceFactory, manifestParser, + chunkSourceFactory, minLoadableRetryCount, livePresentationDelayMs, eventHandler, + eventListener); + } + + } + /** * Constructs an instance to play a given {@link DashManifest}, which must be static. * @@ -121,7 +258,9 @@ public final class DashMediaSource implements MediaSource { * @param chunkSourceFactory A factory for {@link DashChunkSource} instances. * @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 public DashMediaSource(DashManifest manifest, DashChunkSource.Factory chunkSourceFactory, Handler eventHandler, AdaptiveMediaSourceEventListener eventListener) { this(manifest, chunkSourceFactory, DEFAULT_MIN_LOADABLE_RETRY_COUNT, eventHandler, @@ -136,7 +275,9 @@ public final class DashMediaSource implements MediaSource { * @param minLoadableRetryCount The minimum number of times to retry if a loading error occurs. * @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 public DashMediaSource(DashManifest manifest, DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, Handler eventHandler, AdaptiveMediaSourceEventListener eventListener) { @@ -154,7 +295,9 @@ public final class DashMediaSource implements MediaSource { * @param chunkSourceFactory A factory for {@link DashChunkSource} instances. * @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 public DashMediaSource(Uri manifestUri, DataSource.Factory manifestDataSourceFactory, DashChunkSource.Factory chunkSourceFactory, Handler eventHandler, AdaptiveMediaSourceEventListener eventListener) { @@ -178,7 +321,9 @@ public final class DashMediaSource implements MediaSource { * the manifest, if present. * @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 public DashMediaSource(Uri manifestUri, DataSource.Factory manifestDataSourceFactory, DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, long livePresentationDelayMs, Handler eventHandler, @@ -203,7 +348,9 @@ public final class DashMediaSource implements MediaSource { * the manifest, if present. * @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 public DashMediaSource(Uri manifestUri, DataSource.Factory manifestDataSourceFactory, ParsingLoadable.Parser manifestParser, DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTestRunner.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTestRunner.java index 85cefbc2f6..215d8a0518 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTestRunner.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTestRunner.java @@ -316,8 +316,11 @@ public final class DashTestRunner { Uri manifestUri = Uri.parse(manifestUrl); DefaultDashChunkSource.Factory chunkSourceFactory = new DefaultDashChunkSource.Factory( mediaDataSourceFactory); - return new DashMediaSource(manifestUri, manifestDataSourceFactory, chunkSourceFactory, - MIN_LOADABLE_RETRY_COUNT, 0 /* livePresentationDelayMs */, null, null); + return DashMediaSource.Builder + .forManifestUri(manifestUri, manifestDataSourceFactory, chunkSourceFactory) + .setMinLoadableRetryCount(MIN_LOADABLE_RETRY_COUNT) + .setLivePresentationDelayMs(0) + .build(); } @Override