Add Builder to ExtractorMediaSource.

Add Builder pattern to ExtractorMediaSource and mark existing constructors as
deprecated.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=176088810
This commit is contained in:
hoangtc 2017-11-17 03:08:55 -08:00 committed by Oliver Woodman
parent f5a3a27726
commit 1f70d3cdd7
8 changed files with 146 additions and 32 deletions

View file

@ -2,6 +2,8 @@
### dev-v2 (not yet released) ###
* Add Builder to ExtractorMediaSource, HlsMediaSource, SsMediaSource,
DashMediaSource.
* Support 32-bit PCM float output from `DefaultAudioSink`, and add an option to
use this with `FfmpegAudioRenderer`.

View file

@ -21,8 +21,6 @@ import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.ext.ima.ImaAdsLoader;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
@ -69,13 +67,10 @@ import com.google.android.exoplayer2.util.Util;
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
Util.getUserAgent(context, context.getString(R.string.application_name)));
// Produces Extractor instances for parsing the content media (i.e. not the ad).
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// 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(
Uri.parse(contentUrl), dataSourceFactory, extractorsFactory, null, null);
MediaSource contentMediaSource =
new ExtractorMediaSource.Builder(Uri.parse(contentUrl), dataSourceFactory).build();
// Compose the content media source into a new AdsMediaSource with both ads and content.
MediaSource mediaSourceWithAds = new AdsMediaSource(contentMediaSource, dataSourceFactory,

View file

@ -46,7 +46,6 @@ import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.drm.FrameworkMediaDrm;
import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
import com.google.android.exoplayer2.drm.UnsupportedDrmException;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
import com.google.android.exoplayer2.source.BehindLiveWindowException;
@ -379,8 +378,9 @@ public class PlayerActivity extends Activity implements OnClickListener,
.setEventListener(mainHandler, eventLogger)
.build();
case C.TYPE_OTHER:
return new ExtractorMediaSource(uri, mediaDataSourceFactory, new DefaultExtractorsFactory(),
mainHandler, eventLogger);
return new ExtractorMediaSource.Builder(uri, mediaDataSourceFactory)
.setEventListener(mainHandler, eventLogger)
.build();
default: {
throw new IllegalStateException("Unsupported type: " + type);
}

View file

@ -76,12 +76,10 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
DefaultTrackSelector trackSelector = new DefaultTrackSelector();
player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector);
player.addListener(this);
ExtractorMediaSource mediaSource = new ExtractorMediaSource(
uri,
new DefaultDataSourceFactory(context, "ExoPlayerExtFlacTest"),
MatroskaExtractor.FACTORY,
null,
null);
ExtractorMediaSource mediaSource = new ExtractorMediaSource.Builder(
uri, new DefaultDataSourceFactory(context, "ExoPlayerExtFlacTest"))
.setExtractorsFactory(MatroskaExtractor.FACTORY)
.build();
player.prepare(mediaSource);
player.setPlayWhenReady(true);
Looper.loop();

View file

@ -76,12 +76,10 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
DefaultTrackSelector trackSelector = new DefaultTrackSelector();
player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector);
player.addListener(this);
ExtractorMediaSource mediaSource = new ExtractorMediaSource(
uri,
new DefaultDataSourceFactory(context, "ExoPlayerExtOpusTest"),
MatroskaExtractor.FACTORY,
null,
null);
ExtractorMediaSource mediaSource = new ExtractorMediaSource.Builder(
uri, new DefaultDataSourceFactory(context, "ExoPlayerExtOpusTest"))
.setExtractorsFactory(MatroskaExtractor.FACTORY)
.build();
player.prepare(mediaSource);
player.setPlayWhenReady(true);
Looper.loop();

View file

@ -105,12 +105,10 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
DefaultTrackSelector trackSelector = new DefaultTrackSelector();
player = ExoPlayerFactory.newInstance(new Renderer[] {videoRenderer}, trackSelector);
player.addListener(this);
ExtractorMediaSource mediaSource = new ExtractorMediaSource(
uri,
new DefaultDataSourceFactory(context, "ExoPlayerExtVp9Test"),
MatroskaExtractor.FACTORY,
null,
null);
ExtractorMediaSource mediaSource = new ExtractorMediaSource.Builder(
uri, new DefaultDataSourceFactory(context, "ExoPlayerExtVp9Test"))
.setExtractorsFactory(MatroskaExtractor.FACTORY)
.build();
player.sendMessages(new ExoPlayer.ExoPlayerMessage(videoRenderer,
LibvpxVideoRenderer.MSG_SET_OUTPUT_BUFFER_RENDERER,
new VpxVideoSurfaceView(context)));

View file

@ -98,6 +98,123 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
private long timelineDurationUs;
private boolean timelineIsSeekable;
/**
* Builder for {@link ExtractorMediaSource}. Each builder instance can only be used once.
*/
public static final class Builder {
private final Uri uri;
private final DataSource.Factory dataSourceFactory;
private ExtractorsFactory extractorsFactory;
private int minLoadableRetryCount;
private Handler eventHandler;
private EventListener eventListener;
private String customCacheKey;
private int continueLoadingCheckIntervalBytes;
private boolean isBuildCalled;
/**
* @param uri The {@link Uri} of the media stream.
* @param dataSourceFactory A factory for {@link DataSource}s to read the media.
*/
public Builder(Uri uri, DataSource.Factory dataSourceFactory) {
this.uri = uri;
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
* 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.
*/
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
* each invocation of
* {@link MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}.
* @return This builder.
*/
public Builder setContinueLoadingCheckIntervalBytes(int continueLoadingCheckIntervalBytes) {
this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes;
return this;
}
/**
* Sets the listener to respond to {@link ExtractorMediaSource} 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, EventListener eventListener) {
this.eventHandler = eventHandler;
this.eventListener = eventListener;
return this;
}
/**
* 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) {
extractorsFactory = new DefaultExtractorsFactory();
}
return new ExtractorMediaSource(uri, dataSourceFactory, extractorsFactory,
minLoadableRetryCount, eventHandler, eventListener, customCacheKey,
continueLoadingCheckIntervalBytes);
}
}
/**
* @param uri The {@link Uri} of the media stream.
* @param dataSourceFactory A factory for {@link DataSource}s to read the media.
@ -106,7 +223,9 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
* 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
public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory,
ExtractorsFactory extractorsFactory, Handler eventHandler, EventListener eventListener) {
this(uri, dataSourceFactory, extractorsFactory, eventHandler, eventListener, null);
@ -122,7 +241,9 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
* @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
public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory,
ExtractorsFactory extractorsFactory, Handler eventHandler, EventListener eventListener,
String customCacheKey) {
@ -143,7 +264,9 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
* 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
public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory,
ExtractorsFactory extractorsFactory, int minLoadableRetryCount, Handler eventHandler,
EventListener eventListener, String customCacheKey, int continueLoadingCheckIntervalBytes) {

View file

@ -23,7 +23,6 @@ import android.view.ViewGroup;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
@ -173,9 +172,10 @@ public final class AdsMediaSource implements MediaSource {
final int adGroupIndex = id.adGroupIndex;
final int adIndexInAdGroup = id.adIndexInAdGroup;
if (adGroupMediaSources[adGroupIndex].length <= adIndexInAdGroup) {
MediaSource adMediaSource = new ExtractorMediaSource(
adPlaybackState.adUris[id.adGroupIndex][id.adIndexInAdGroup], dataSourceFactory,
new DefaultExtractorsFactory(), mainHandler, componentListener);
MediaSource adMediaSource = new ExtractorMediaSource.Builder(
adPlaybackState.adUris[id.adGroupIndex][id.adIndexInAdGroup], dataSourceFactory)
.setEventListener(mainHandler, componentListener)
.build();
int oldAdCount = adGroupMediaSources[id.adGroupIndex].length;
if (adIndexInAdGroup >= oldAdCount) {
int adCount = adIndexInAdGroup + 1;