Make DashMediaSource.Builder a factory for DashMediaSources

This is in preparation for supporting non-extractor MediaSources for ads in
AdsMediaSource.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=178377627
This commit is contained in:
andrewlewis 2017-12-08 07:57:06 -08:00 committed by Oliver Woodman
parent aa01fb85dc
commit e419154b86
5 changed files with 159 additions and 146 deletions

View File

@ -393,10 +393,9 @@ import java.util.ArrayList;
new DefaultSsChunkSource.Factory(DATA_SOURCE_FACTORY)) new DefaultSsChunkSource.Factory(DATA_SOURCE_FACTORY))
.build(); .build();
case DemoUtil.MIME_TYPE_DASH: case DemoUtil.MIME_TYPE_DASH:
return DashMediaSource.Builder return new DashMediaSource.Factory(
.forManifestUri(uri, DATA_SOURCE_FACTORY, new DefaultDashChunkSource.Factory(DATA_SOURCE_FACTORY), DATA_SOURCE_FACTORY)
new DefaultDashChunkSource.Factory(DATA_SOURCE_FACTORY)) .createMediaSource(uri);
.build();
case DemoUtil.MIME_TYPE_HLS: case DemoUtil.MIME_TYPE_HLS:
return HlsMediaSource.Builder return HlsMediaSource.Builder
.forDataSource(uri, DATA_SOURCE_FACTORY) .forDataSource(uri, DATA_SOURCE_FACTORY)

View File

@ -371,11 +371,10 @@ public class PlayerActivity extends Activity implements OnClickListener,
.setEventListener(mainHandler, eventLogger) .setEventListener(mainHandler, eventLogger)
.build(); .build();
case C.TYPE_DASH: case C.TYPE_DASH:
return DashMediaSource.Builder return new DashMediaSource.Factory(
.forManifestUri(uri, buildDataSourceFactory(false), new DefaultDashChunkSource.Factory(mediaDataSourceFactory),
new DefaultDashChunkSource.Factory(mediaDataSourceFactory)) buildDataSourceFactory(false))
.setEventListener(mainHandler, eventLogger) .createMediaSource(uri, mainHandler, eventLogger);
.build();
case C.TYPE_HLS: case C.TYPE_HLS:
return HlsMediaSource.Builder return HlsMediaSource.Builder
.forDataSource(uri, mediaDataSourceFactory) .forDataSource(uri, mediaDataSourceFactory)

View File

@ -44,6 +44,31 @@ import java.util.Map;
*/ */
public final class AdsMediaSource implements MediaSource { public final class AdsMediaSource implements MediaSource {
/** Factory for creating {@link MediaSource}s to play ad media. */
public interface MediaSourceFactory {
/**
* Creates a new {@link MediaSource} for loading the ad media with the specified {@code uri}.
*
* @param uri The URI of the media or manifest to play.
* @param handler A handler for listener events. May be null if delivery of events is not
* required.
* @param listener A listener for events. May be null if delivery of events is not required.
* @return The new media source.
*/
MediaSource createMediaSource(
Uri uri, @Nullable Handler handler, @Nullable MediaSourceEventListener listener);
/**
* Returns the content types supported by media sources created by this factory. Each element
* should be one of {@link C#TYPE_DASH}, {@link C#TYPE_SS}, {@link C#TYPE_HLS} or {@link
* C#TYPE_OTHER}.
*
* @return The content types supported by media sources created by this factory.
*/
int[] getSupportedTypes();
}
/** Listener for ads media source events. */ /** Listener for ads media source events. */
public interface EventListener extends MediaSourceEventListener { public interface EventListener extends MediaSourceEventListener {
@ -77,7 +102,7 @@ public final class AdsMediaSource implements MediaSource {
@Nullable private final EventListener eventListener; @Nullable private final EventListener eventListener;
private final Handler mainHandler; private final Handler mainHandler;
private final ComponentListener componentListener; private final ComponentListener componentListener;
private final AdMediaSourceFactory adMediaSourceFactory; private final MediaSourceFactory adMediaSourceFactory;
private final Map<MediaSource, List<DeferredMediaPeriod>> deferredMediaPeriodByAdMediaSource; private final Map<MediaSource, List<DeferredMediaPeriod>> deferredMediaPeriodByAdMediaSource;
private final Timeline.Period period; private final Timeline.Period period;
@ -138,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 ExtractorAdMediaSourceFactory(dataSourceFactory); adMediaSourceFactory = new ExtractorMediaSourceFactory(dataSourceFactory);
deferredMediaPeriodByAdMediaSource = new HashMap<>(); deferredMediaPeriodByAdMediaSource = new HashMap<>();
period = new Timeline.Period(); period = new Timeline.Period();
adGroupMediaSources = new MediaSource[0][]; adGroupMediaSources = new MediaSource[0][];
@ -186,7 +211,7 @@ public final class AdsMediaSource implements MediaSource {
if (adGroupMediaSources[adGroupIndex].length <= adIndexInAdGroup) { if (adGroupMediaSources[adGroupIndex].length <= adIndexInAdGroup) {
Uri adUri = adPlaybackState.adUris[id.adGroupIndex][id.adIndexInAdGroup]; Uri adUri = adPlaybackState.adUris[id.adGroupIndex][id.adIndexInAdGroup];
final MediaSource adMediaSource = final MediaSource adMediaSource =
adMediaSourceFactory.createAdMediaSource(adUri, eventHandler, eventListener); adMediaSourceFactory.createMediaSource(adUri, eventHandler, eventListener);
int oldAdCount = adGroupMediaSources[id.adGroupIndex].length; int oldAdCount = adGroupMediaSources[id.adGroupIndex].length;
if (adIndexInAdGroup >= oldAdCount) { if (adIndexInAdGroup >= oldAdCount) {
int adCount = adIndexInAdGroup + 1; int adCount = adIndexInAdGroup + 1;
@ -371,44 +396,16 @@ public final class AdsMediaSource implements MediaSource {
} }
/** private static final class ExtractorMediaSourceFactory implements MediaSourceFactory {
* Factory for {@link MediaSource}s for loading ad media.
*/
private interface AdMediaSourceFactory {
/**
* Creates a new {@link MediaSource} for loading the ad media with the specified {@code uri}.
*
* @param uri The URI of the ad.
* @param handler A handler for listener events. May be null if delivery of events is not
* required.
* @param listener A listener for events. May be null if delivery of events is not required.
* @return The new media source.
*/
MediaSource createAdMediaSource(
Uri uri, @Nullable Handler handler, @Nullable MediaSourceEventListener listener);
/**
* Returns the content types supported by media sources created by this factory. Each element
* should be one of {@link C#TYPE_DASH}, {@link C#TYPE_SS}, {@link C#TYPE_HLS} or
* {@link C#TYPE_OTHER}.
*
* @return The content types supported by the factory.
*/
int[] getSupportedTypes();
}
private static final class ExtractorAdMediaSourceFactory implements AdMediaSourceFactory {
private final DataSource.Factory dataSourceFactory; private final DataSource.Factory dataSourceFactory;
public ExtractorAdMediaSourceFactory(DataSource.Factory dataSourceFactory) { public ExtractorMediaSourceFactory(DataSource.Factory dataSourceFactory) {
this.dataSourceFactory = dataSourceFactory; this.dataSourceFactory = dataSourceFactory;
} }
@Override @Override
public MediaSource createAdMediaSource( public MediaSource createMediaSource(
Uri uri, @Nullable Handler handler, @Nullable MediaSourceEventListener listener) { Uri uri, @Nullable Handler handler, @Nullable MediaSourceEventListener listener) {
return new ExtractorMediaSource.Builder(uri, dataSourceFactory) return new ExtractorMediaSource.Builder(uri, dataSourceFactory)
.setEventListener(handler, listener) .setEventListener(handler, listener)

View File

@ -34,6 +34,7 @@ import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceEventListener; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.SequenceableLoader; import com.google.android.exoplayer2.source.SequenceableLoader;
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest; import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.source.dash.manifest.DashManifestParser; import com.google.android.exoplayer2.source.dash.manifest.DashManifestParser;
import com.google.android.exoplayer2.source.dash.manifest.UtcTimingElement; import com.google.android.exoplayer2.source.dash.manifest.UtcTimingElement;
@ -64,62 +65,35 @@ public final class DashMediaSource implements MediaSource {
ExoPlayerLibraryInfo.registerModule("goog.exo.dash"); ExoPlayerLibraryInfo.registerModule("goog.exo.dash");
} }
/** /** Factory for {@link DashMediaSource}s. */
* Builder for {@link DashMediaSource}. Each builder instance can only be used once. public static final class Factory implements AdsMediaSource.MediaSourceFactory {
*/
public static final class Builder {
private final DashManifest manifest;
private final Uri manifestUri;
private final DataSource.Factory manifestDataSourceFactory;
private final DashChunkSource.Factory chunkSourceFactory; private final DashChunkSource.Factory chunkSourceFactory;
private final @Nullable DataSource.Factory manifestDataSourceFactory;
private ParsingLoadable.Parser<? extends DashManifest> manifestParser; private @Nullable ParsingLoadable.Parser<? extends DashManifest> manifestParser;
private MediaSourceEventListener eventListener;
private Handler eventHandler;
private CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory; private CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
private int minLoadableRetryCount; private int minLoadableRetryCount;
private long livePresentationDelayMs; private long livePresentationDelayMs;
private boolean isBuildCalled; private boolean isCreateCalled;
/** /**
* Creates a {@link Builder} for a {@link DashMediaSource} with a side-loaded manifest. * Creates a new factory for {@link DashMediaSource}s.
* *
* @param manifest The manifest. {@link DashManifest#dynamic} must be false.
* @param chunkSourceFactory A factory for {@link DashChunkSource} instances. * @param chunkSourceFactory A factory for {@link DashChunkSource} instances.
* @return A new builder.
*/
public static Builder forSideloadedManifest(DashManifest manifest,
DashChunkSource.Factory chunkSourceFactory) {
Assertions.checkArgument(!manifest.dynamic);
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 * @param manifestDataSourceFactory A factory for {@link DataSource} instances that will be used
* to load (and refresh) the manifest. * to load (and refresh) the manifest. May be {@code null} if the factory will only ever be
* @param chunkSourceFactory A factory for {@link DashChunkSource} instances. * used to create create media sources with sideloaded manifests via {@link
* @return A new builder. * #createMediaSource(DashManifest, Handler, MediaSourceEventListener)}.
*/ */
public static Builder forManifestUri(Uri manifestUri, public Factory(
DataSource.Factory manifestDataSourceFactory, DashChunkSource.Factory chunkSourceFactory) { DashChunkSource.Factory chunkSourceFactory,
return new Builder(null, manifestUri, manifestDataSourceFactory, chunkSourceFactory); @Nullable DataSource.Factory manifestDataSourceFactory) {
} this.chunkSourceFactory = Assertions.checkNotNull(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.manifestDataSourceFactory = manifestDataSourceFactory;
this.chunkSourceFactory = chunkSourceFactory;
minLoadableRetryCount = DEFAULT_MIN_LOADABLE_RETRY_COUNT; minLoadableRetryCount = DEFAULT_MIN_LOADABLE_RETRY_COUNT;
livePresentationDelayMs = DEFAULT_LIVE_PRESENTATION_DELAY_PREFER_MANIFEST_MS; livePresentationDelayMs = DEFAULT_LIVE_PRESENTATION_DELAY_PREFER_MANIFEST_MS;
compositeSequenceableLoaderFactory = new DefaultCompositeSequenceableLoaderFactory();
} }
/** /**
@ -127,95 +101,140 @@ public final class DashMediaSource implements MediaSource {
* {@link #DEFAULT_MIN_LOADABLE_RETRY_COUNT}. * {@link #DEFAULT_MIN_LOADABLE_RETRY_COUNT}.
* *
* @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 duration in milliseconds by which the default start position should precede the end * 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 * of the live window for live playbacks. The default value is {@link
* {@link #DEFAULT_LIVE_PRESENTATION_DELAY_PREFER_MANIFEST_MS}. * #DEFAULT_LIVE_PRESENTATION_DELAY_PREFER_MANIFEST_MS}.
* *
* @param livePresentationDelayMs For live playbacks, the duration in milliseconds by which the * @param livePresentationDelayMs For live playbacks, the duration in milliseconds by which the
* default start position should precede the end of the live window. Use * default start position should precede the end of the live window. Use {@link
* {@link #DEFAULT_LIVE_PRESENTATION_DELAY_PREFER_MANIFEST_MS} to use the value specified by * #DEFAULT_LIVE_PRESENTATION_DELAY_PREFER_MANIFEST_MS} to use the value specified by the
* the manifest, if present. * manifest, if present.
* @return This builder. * @return This factory, for convenience.
* @throws IllegalStateException If one of the {@code create} methods has already been called.
*/ */
public Builder setLivePresentationDelayMs(long livePresentationDelayMs) { public Factory setLivePresentationDelayMs(long livePresentationDelayMs) {
Assertions.checkState(!isCreateCalled);
this.livePresentationDelayMs = livePresentationDelayMs; this.livePresentationDelayMs = livePresentationDelayMs;
return this; return this;
} }
/** /**
* Sets the listener to respond to adaptive {@link MediaSource} events and the handler to * Sets the manifest parser to parse loaded manifest data when loading a manifest URI.
* 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 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. * @param manifestParser A parser for loaded manifest data.
* @return This builder. * @return This factory, for convenience.
* @throws IllegalStateException If one of the {@code create} methods has already been called.
*/ */
public Builder setManifestParser( public Factory setManifestParser(
ParsingLoadable.Parser<? extends DashManifest> manifestParser) { ParsingLoadable.Parser<? extends DashManifest> manifestParser) {
this.manifestParser = manifestParser; Assertions.checkState(!isCreateCalled);
this.manifestParser = Assertions.checkNotNull(manifestParser);
return this; return this;
} }
/** /**
* Sets the factory to create composite {@link SequenceableLoader}s for when this media source * 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 * loads data from multiple streams (video, audio etc...). The default is an instance of {@link
* {@link DefaultCompositeSequenceableLoaderFactory}. * DefaultCompositeSequenceableLoaderFactory}.
* *
* @param compositeSequenceableLoaderFactory A factory to create composite * @param compositeSequenceableLoaderFactory A factory to create composite {@link
* {@link SequenceableLoader}s for when this media source loads data from multiple streams * SequenceableLoader}s for when this media source loads data from multiple streams (video,
* (video, audio etc...). * audio etc...).
* @return This builder. * @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) { CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory) {
this.compositeSequenceableLoaderFactory = compositeSequenceableLoaderFactory; Assertions.checkState(!isCreateCalled);
this.compositeSequenceableLoaderFactory =
Assertions.checkNotNull(compositeSequenceableLoaderFactory);
return this; return this;
} }
/** /**
* Builds a new {@link DashMediaSource} using the current parameters. * Returns a new {@link DashMediaSource} using the current parameters and the specified
* <p> * sideloaded manifest.
* After this call, the builder should not be re-used.
* *
* @return The newly built {@link DashMediaSource}. * @param manifest The manifest. {@link DashManifest#dynamic} must be false.
* @param eventHandler A handler for events.
* @param eventListener A listener of events.
* @return The new {@link DashMediaSource}.
* @throws IllegalArgumentException If {@link DashManifest#dynamic} is true.
*/ */
public DashMediaSource build() { public DashMediaSource createMediaSource(
Assertions.checkArgument((eventListener == null) == (eventHandler == null)); DashManifest manifest,
Assertions.checkState(!isBuildCalled); @Nullable Handler eventHandler,
isBuildCalled = true; @Nullable MediaSourceEventListener eventListener) {
boolean loadableManifestUri = manifestUri != null; Assertions.checkArgument(!manifest.dynamic);
if (loadableManifestUri && manifestParser == null) { isCreateCalled = true;
manifestParser = new DashManifestParser(); return new DashMediaSource(
} manifest,
if (compositeSequenceableLoaderFactory == null) { null,
compositeSequenceableLoaderFactory = new DefaultCompositeSequenceableLoaderFactory(); null,
} null,
return new DashMediaSource(manifest, manifestUri, manifestDataSourceFactory, manifestParser, chunkSourceFactory,
chunkSourceFactory, compositeSequenceableLoaderFactory, minLoadableRetryCount, compositeSequenceableLoaderFactory,
livePresentationDelayMs, eventHandler, eventListener); minLoadableRetryCount,
livePresentationDelayMs,
eventHandler,
eventListener);
} }
/**
* Returns a new {@link DashMediaSource} using the current parameters. Media source events will
* not be delivered.
*
* @param manifestUri The manifest {@link Uri}.
* @return The new {@link DashMediaSource}.
*/
public DashMediaSource createMediaSource(Uri manifestUri) {
return createMediaSource(manifestUri, null, null);
}
/**
* Returns a new {@link DashMediaSource} using the current parameters.
*
* @param manifestUri The manifest {@link Uri}.
* @param eventHandler A handler for events.
* @param eventListener A listener of events.
* @return The new {@link DashMediaSource}.
*/
@Override
public DashMediaSource createMediaSource(
Uri manifestUri,
@Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener) {
isCreateCalled = true;
if (manifestParser == null) {
manifestParser = new DashManifestParser();
}
return new DashMediaSource(
null,
Assertions.checkNotNull(manifestUri),
manifestDataSourceFactory,
manifestParser,
chunkSourceFactory,
compositeSequenceableLoaderFactory,
minLoadableRetryCount,
livePresentationDelayMs,
eventHandler,
eventListener);
}
@Override
public int[] getSupportedTypes() {
return new int[] {C.TYPE_DASH};
}
} }
/** /**
@ -283,7 +302,7 @@ public final class DashMediaSource implements MediaSource {
* @param chunkSourceFactory A factory for {@link DashChunkSource} instances. * @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 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 DashMediaSource( public DashMediaSource(
@ -303,7 +322,7 @@ public final class DashMediaSource implements MediaSource {
* @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.
* @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 DashMediaSource( public DashMediaSource(
@ -327,7 +346,7 @@ public final class DashMediaSource implements MediaSource {
* @param chunkSourceFactory A factory for {@link DashChunkSource} instances. * @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 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 DashMediaSource( public DashMediaSource(
@ -356,7 +375,7 @@ public final class DashMediaSource implements MediaSource {
* manifest, if present. * manifest, if present.
* @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 DashMediaSource( public DashMediaSource(
@ -387,7 +406,7 @@ public final class DashMediaSource implements MediaSource {
* manifest, if present. * manifest, if present.
* @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 DashMediaSource( public DashMediaSource(

View File

@ -316,11 +316,10 @@ public final class DashTestRunner {
Uri manifestUri = Uri.parse(manifestUrl); Uri manifestUri = Uri.parse(manifestUrl);
DefaultDashChunkSource.Factory chunkSourceFactory = new DefaultDashChunkSource.Factory( DefaultDashChunkSource.Factory chunkSourceFactory = new DefaultDashChunkSource.Factory(
mediaDataSourceFactory); mediaDataSourceFactory);
return DashMediaSource.Builder return new DashMediaSource.Factory(chunkSourceFactory, manifestDataSourceFactory)
.forManifestUri(manifestUri, manifestDataSourceFactory, chunkSourceFactory)
.setMinLoadableRetryCount(MIN_LOADABLE_RETRY_COUNT) .setMinLoadableRetryCount(MIN_LOADABLE_RETRY_COUNT)
.setLivePresentationDelayMs(0) .setLivePresentationDelayMs(0)
.build(); .createMediaSource(manifestUri);
} }
@Override @Override