mirror of
https://github.com/samsonjs/media.git
synced 2026-04-09 11:55:46 +00:00
Allow injection of custom FormatEvaluators
This was possible previously, but now we support things like multi-period DASH we need to do the injection in the form of factories rather than concrete instances. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=127735816
This commit is contained in:
parent
e7d95aff34
commit
5360ddc519
17 changed files with 171 additions and 162 deletions
|
|
@ -37,6 +37,8 @@ import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
|
|||
import com.google.android.exoplayer2.source.ExtractorMediaSource;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
import com.google.android.exoplayer2.source.chunk.FormatEvaluator;
|
||||
import com.google.android.exoplayer2.source.chunk.FormatEvaluator.AdaptiveEvaluator;
|
||||
import com.google.android.exoplayer2.source.dash.DashMediaSource;
|
||||
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
|
||||
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingMediaSource;
|
||||
|
|
@ -47,12 +49,12 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
|||
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
||||
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.TrackInfo;
|
||||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
||||
import com.google.android.exoplayer2.ui.DebugTextViewHelper;
|
||||
import com.google.android.exoplayer2.ui.PlayerControl;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
import com.google.android.exoplayer2.ui.DebugTextViewHelper;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
import android.Manifest.permission;
|
||||
|
|
@ -129,12 +131,12 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||
private SubtitleLayout subtitleLayout;
|
||||
private Button retryButton;
|
||||
|
||||
private DataSourceFactory dataSourceFactory;
|
||||
private DataSource.Factory dataSourceFactory;
|
||||
private FormatEvaluator.Factory formatEvaluatorFactory;
|
||||
private SimpleExoPlayer player;
|
||||
private MappingTrackSelector trackSelector;
|
||||
private TrackSelectionHelper trackSelectionHelper;
|
||||
private DebugTextViewHelper debugViewHelper;
|
||||
private BandwidthMeter bandwidthMeter;
|
||||
private boolean playerNeedsSource;
|
||||
|
||||
private int playerPeriodIndex;
|
||||
|
|
@ -146,10 +148,11 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
String userAgent = Util.getUserAgent(this, "ExoPlayerDemo");
|
||||
dataSourceFactory = new DefaultDataSourceFactory(this, userAgent);
|
||||
bandwidthMeter = new DefaultBandwidthMeter();
|
||||
mainHandler = new Handler();
|
||||
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
|
||||
dataSourceFactory = new DefaultDataSourceFactory(this, userAgent, bandwidthMeter);
|
||||
formatEvaluatorFactory = new AdaptiveEvaluator.Factory(bandwidthMeter);
|
||||
|
||||
mainHandler = new Handler();
|
||||
setContentView(R.layout.player_activity);
|
||||
rootView = findViewById(R.id.root);
|
||||
rootView.setOnTouchListener(new OnTouchListener() {
|
||||
|
|
@ -340,16 +343,17 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||
int type = Util.inferContentType(lastPathSegment);
|
||||
switch (type) {
|
||||
case Util.TYPE_SS:
|
||||
return new SmoothStreamingMediaSource(uri, dataSourceFactory, bandwidthMeter, mainHandler,
|
||||
eventLogger);
|
||||
return new SmoothStreamingMediaSource(uri, dataSourceFactory, formatEvaluatorFactory,
|
||||
mainHandler, eventLogger);
|
||||
case Util.TYPE_DASH:
|
||||
return new DashMediaSource(uri, dataSourceFactory, bandwidthMeter, mainHandler,
|
||||
return new DashMediaSource(uri, dataSourceFactory, formatEvaluatorFactory, mainHandler,
|
||||
eventLogger);
|
||||
case Util.TYPE_HLS:
|
||||
return new HlsMediaSource(uri, dataSourceFactory, bandwidthMeter, mainHandler, eventLogger);
|
||||
return new HlsMediaSource(uri, dataSourceFactory, formatEvaluatorFactory, mainHandler,
|
||||
eventLogger);
|
||||
case Util.TYPE_OTHER:
|
||||
return new ExtractorMediaSource(uri, dataSourceFactory, bandwidthMeter,
|
||||
new DefaultExtractorsFactory(), mainHandler, eventLogger);
|
||||
return new ExtractorMediaSource(uri, dataSourceFactory, new DefaultExtractorsFactory(),
|
||||
mainHandler, eventLogger);
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported type: " + type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
|
|||
ExtractorMediaSource mediaSource = new ExtractorMediaSource(
|
||||
uri,
|
||||
new DefaultDataSourceFactory(context, "ExoPlayerExtFlacTest"),
|
||||
null,
|
||||
MatroskaExtractor.FACTORY,
|
||||
null,
|
||||
null);
|
||||
|
|
|
|||
|
|
@ -15,51 +15,46 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.ext.okhttp;
|
||||
|
||||
import com.google.android.exoplayer2.upstream.DataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSource.Factory;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSource;
|
||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
||||
import com.google.android.exoplayer2.util.Predicate;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import okhttp3.CacheControl;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
/**
|
||||
* A {@link DataSourceFactory} that produces {@link DefaultDataSource} instances that delegate to
|
||||
* A {@link Factory} that produces {@link DefaultDataSource} instances that delegate to
|
||||
* {@link OkHttpDataSource}s for non-file/asset/content URIs.
|
||||
*/
|
||||
public final class DefaultOkHttpDataSourceFactory implements DataSourceFactory {
|
||||
public final class DefaultOkHttpDataSourceFactory implements Factory {
|
||||
|
||||
private final Context context;
|
||||
private final OkHttpClient client;
|
||||
private final String userAgent;
|
||||
private final Predicate<String> contentTypePredicate;
|
||||
private final TransferListener transferListener;
|
||||
private final CacheControl cacheControl;
|
||||
|
||||
public DefaultOkHttpDataSourceFactory(Context context, OkHttpClient client, String userAgent,
|
||||
Predicate<String> contentTypePredicate) {
|
||||
this(context, client, userAgent, contentTypePredicate, null);
|
||||
TransferListener transferListener) {
|
||||
this(context, client, userAgent, transferListener, null);
|
||||
}
|
||||
|
||||
public DefaultOkHttpDataSourceFactory(Context context, OkHttpClient client, String userAgent,
|
||||
Predicate<String> contentTypePredicate, CacheControl cacheControl) {
|
||||
TransferListener transferListener, CacheControl cacheControl) {
|
||||
this.context = context.getApplicationContext();
|
||||
this.client = client;
|
||||
this.userAgent = userAgent;
|
||||
this.contentTypePredicate = contentTypePredicate;
|
||||
this.transferListener = transferListener;
|
||||
this.cacheControl = cacheControl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultDataSource createDataSource() {
|
||||
return createDataSource(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultDataSource createDataSource(TransferListener listener) {
|
||||
return new DefaultDataSource(context, listener,
|
||||
new OkHttpDataSource(client, userAgent, contentTypePredicate, listener, cacheControl));
|
||||
DataSource httpDataSource = new OkHttpDataSource(client, userAgent, null, transferListener,
|
||||
cacheControl);
|
||||
return new DefaultDataSource(context, transferListener, httpDataSource);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
|
|||
ExtractorMediaSource mediaSource = new ExtractorMediaSource(
|
||||
uri,
|
||||
new DefaultDataSourceFactory(context, "ExoPlayerExtOpusTest"),
|
||||
null,
|
||||
MatroskaExtractor.FACTORY,
|
||||
null,
|
||||
null);
|
||||
|
|
|
|||
|
|
@ -93,7 +93,6 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
|
|||
ExtractorMediaSource mediaSource = new ExtractorMediaSource(
|
||||
uri,
|
||||
new DefaultDataSourceFactory(context, "ExoPlayerExtVp9Test"),
|
||||
null,
|
||||
MatroskaExtractor.FACTORY,
|
||||
null,
|
||||
null);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,7 @@ import com.google.android.exoplayer2.extractor.SeekMap;
|
|||
import com.google.android.exoplayer2.extractor.TrackOutput;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import com.google.android.exoplayer2.upstream.Allocator;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||
import com.google.android.exoplayer2.upstream.Loader;
|
||||
import com.google.android.exoplayer2.upstream.Loader.Loadable;
|
||||
|
|
@ -112,8 +110,7 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
|
|||
private static final long DEFAULT_LAST_SAMPLE_DURATION_US = 10000;
|
||||
|
||||
private final Uri uri;
|
||||
private final DataSourceFactory dataSourceFactory;
|
||||
private final BandwidthMeter bandwidthMeter;
|
||||
private final DataSource.Factory dataSourceFactory;
|
||||
private final ExtractorsFactory extractorsFactory;
|
||||
private final int minLoadableRetryCount;
|
||||
private final Handler eventHandler;
|
||||
|
|
@ -148,23 +145,20 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
|
|||
/**
|
||||
* @param uri The {@link Uri} of the media stream.
|
||||
* @param dataSourceFactory A factory for {@link DataSource}s to read the media.
|
||||
* @param bandwidthMeter A {@link BandwidthMeter} to notify of loads performed by the source.
|
||||
* @param extractorsFactory 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.
|
||||
* Otherwise, pass a {@link DefaultExtractorsFactory} to use default extractors.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
*/
|
||||
public ExtractorMediaSource(Uri uri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, ExtractorsFactory extractorsFactory, Handler eventHandler,
|
||||
EventListener eventListener) {
|
||||
this(uri, dataSourceFactory, bandwidthMeter, extractorsFactory,
|
||||
MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA, eventHandler, eventListener);
|
||||
public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory,
|
||||
ExtractorsFactory extractorsFactory, Handler eventHandler, EventListener eventListener) {
|
||||
this(uri, dataSourceFactory, extractorsFactory, MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA, eventHandler,
|
||||
eventListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uri The {@link Uri} of the media stream.
|
||||
* @param dataSourceFactory A factory for {@link DataSource}s to read the media.
|
||||
* @param bandwidthMeter A {@link BandwidthMeter} to notify of loads performed by the source.
|
||||
* @param extractorsFactory 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.
|
||||
* Otherwise, pass a {@link DefaultExtractorsFactory} to use default extractors.
|
||||
|
|
@ -172,12 +166,11 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
|
|||
* if a loading error occurs.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
*/
|
||||
public ExtractorMediaSource(Uri uri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, ExtractorsFactory extractorsFactory, int minLoadableRetryCount,
|
||||
Handler eventHandler, EventListener eventListener) {
|
||||
public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory,
|
||||
ExtractorsFactory extractorsFactory, int minLoadableRetryCount, Handler eventHandler,
|
||||
EventListener eventListener) {
|
||||
this.uri = uri;
|
||||
this.dataSourceFactory = dataSourceFactory;
|
||||
this.bandwidthMeter = bandwidthMeter;
|
||||
this.extractorsFactory = extractorsFactory;
|
||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||
this.eventHandler = eventHandler;
|
||||
|
|
@ -214,7 +207,7 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
|
|||
this.callback = callback;
|
||||
this.allocator = allocator;
|
||||
|
||||
dataSource = dataSourceFactory.createDataSource(bandwidthMeter);
|
||||
dataSource = dataSourceFactory.createDataSource();
|
||||
loader = new Loader("Loader:ExtractorMediaSource");
|
||||
extractorHolder = new ExtractorHolder(extractorsFactory.createExtractors(), this);
|
||||
loadCondition = new ConditionVariable();
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
|||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import com.google.android.exoplayer2.upstream.Allocator;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||
import com.google.android.exoplayer2.upstream.Loader;
|
||||
import com.google.android.exoplayer2.upstream.Loader.Loadable;
|
||||
|
|
@ -71,7 +70,7 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
|
|||
private static final int STREAM_STATE_END_OF_STREAM = 2;
|
||||
|
||||
private final Uri uri;
|
||||
private final DataSourceFactory dataSourceFactory;
|
||||
private final DataSource.Factory dataSourceFactory;
|
||||
private final Format format;
|
||||
private final long durationUs;
|
||||
private final int minLoadableRetryCount;
|
||||
|
|
@ -87,17 +86,17 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
|
|||
private byte[] sampleData;
|
||||
private int sampleSize;
|
||||
|
||||
public SingleSampleMediaSource(Uri uri, DataSourceFactory dataSourceFactory, Format format,
|
||||
public SingleSampleMediaSource(Uri uri, DataSource.Factory dataSourceFactory, Format format,
|
||||
long durationUs) {
|
||||
this(uri, dataSourceFactory, format, durationUs, DEFAULT_MIN_LOADABLE_RETRY_COUNT);
|
||||
}
|
||||
|
||||
public SingleSampleMediaSource(Uri uri, DataSourceFactory dataSourceFactory, Format format,
|
||||
public SingleSampleMediaSource(Uri uri, DataSource.Factory dataSourceFactory, Format format,
|
||||
long durationUs, int minLoadableRetryCount) {
|
||||
this(uri, dataSourceFactory, format, durationUs, minLoadableRetryCount, null, null, 0);
|
||||
}
|
||||
|
||||
public SingleSampleMediaSource(Uri uri, DataSourceFactory dataSourceFactory, Format format,
|
||||
public SingleSampleMediaSource(Uri uri, DataSource.Factory dataSourceFactory, Format format,
|
||||
long durationUs, int minLoadableRetryCount, Handler eventHandler, EventListener eventListener,
|
||||
int eventSourceId) {
|
||||
this.uri = uri;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,18 @@ import java.util.Random;
|
|||
* Selects from a number of available formats during playback.
|
||||
*/
|
||||
public interface FormatEvaluator {
|
||||
|
||||
/**
|
||||
* A factory for {@link FormatEvaluator} instances.
|
||||
*/
|
||||
interface Factory {
|
||||
|
||||
/**
|
||||
* Creates a {@link FormatEvaluator} instance.
|
||||
*/
|
||||
FormatEvaluator createFormatEvaluator();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A trigger for a load whose reason is unknown or unspecified.
|
||||
|
|
@ -124,6 +136,28 @@ public interface FormatEvaluator {
|
|||
*/
|
||||
final class RandomEvaluator implements FormatEvaluator {
|
||||
|
||||
public static class Factory implements FormatEvaluator.Factory {
|
||||
|
||||
private final int seed;
|
||||
private final boolean seedIsSet;
|
||||
|
||||
public Factory() {
|
||||
seed = 0;
|
||||
seedIsSet = false;
|
||||
}
|
||||
|
||||
public Factory(int seed) {
|
||||
this.seed = seed;
|
||||
seedIsSet = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FormatEvaluator createFormatEvaluator() {
|
||||
return seedIsSet ? new RandomEvaluator(seed) : new RandomEvaluator();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final Random random;
|
||||
|
||||
private Format[] formats;
|
||||
|
|
@ -196,6 +230,21 @@ public interface FormatEvaluator {
|
|||
*/
|
||||
final class AdaptiveEvaluator implements FormatEvaluator {
|
||||
|
||||
public static class Factory implements FormatEvaluator.Factory {
|
||||
|
||||
private final BandwidthMeter bandwidthMeter;
|
||||
|
||||
public Factory(BandwidthMeter bandwidthMeter) {
|
||||
this.bandwidthMeter = bandwidthMeter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FormatEvaluator createFormatEvaluator() {
|
||||
return new AdaptiveEvaluator(bandwidthMeter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final int DEFAULT_MAX_INITIAL_BITRATE = 800000;
|
||||
|
||||
private static final int DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS = 10000;
|
||||
|
|
|
|||
|
|
@ -32,9 +32,7 @@ import com.google.android.exoplayer2.source.dash.mpd.Period;
|
|||
import com.google.android.exoplayer2.source.dash.mpd.Representation;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import com.google.android.exoplayer2.upstream.Allocator;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.Loader;
|
||||
|
||||
import android.util.Pair;
|
||||
|
|
@ -49,8 +47,8 @@ import java.util.List;
|
|||
/* package */ final class DashMediaPeriod implements MediaPeriod,
|
||||
SequenceableLoader.Callback<ChunkSampleStream<DashChunkSource>> {
|
||||
|
||||
private final DataSourceFactory dataSourceFactory;
|
||||
private final BandwidthMeter bandwidthMeter;
|
||||
private final DataSource.Factory dataSourceFactory;
|
||||
private final FormatEvaluator.Factory formatEvaluatorFactory;
|
||||
private final int minLoadableRetryCount;
|
||||
private final EventDispatcher eventDispatcher;
|
||||
private final long elapsedRealtimeOffset;
|
||||
|
|
@ -68,13 +66,13 @@ import java.util.List;
|
|||
private Period period;
|
||||
|
||||
public DashMediaPeriod(MediaPresentationDescription manifest, int index,
|
||||
DataSourceFactory dataSourceFactory, BandwidthMeter bandwidthMeter,
|
||||
DataSource.Factory dataSourceFactory, FormatEvaluator.Factory formatEvaluatorFactory,
|
||||
int minLoadableRetryCount, EventDispatcher eventDispatcher, long elapsedRealtimeOffset,
|
||||
Loader loader) {
|
||||
this.manifest = manifest;
|
||||
this.index = index;
|
||||
this.dataSourceFactory = dataSourceFactory;
|
||||
this.bandwidthMeter = bandwidthMeter;
|
||||
this.formatEvaluatorFactory = formatEvaluatorFactory;
|
||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||
this.eventDispatcher = eventDispatcher;
|
||||
this.elapsedRealtimeOffset = elapsedRealtimeOffset;
|
||||
|
|
@ -245,11 +243,11 @@ import java.util.List;
|
|||
long positionUs) {
|
||||
int[] selectedTracks = selection.getTracks();
|
||||
FormatEvaluator adaptiveEvaluator = selectedTracks.length > 1
|
||||
? new FormatEvaluator.AdaptiveEvaluator(bandwidthMeter) : null;
|
||||
? formatEvaluatorFactory.createFormatEvaluator() : null;
|
||||
int adaptationSetIndex = trackGroupAdaptationSetIndices[selection.group];
|
||||
AdaptationSet adaptationSet = period.adaptationSets.get(adaptationSetIndex);
|
||||
int adaptationSetType = adaptationSet.type;
|
||||
DataSource dataSource = dataSourceFactory.createDataSource(bandwidthMeter);
|
||||
DataSource dataSource = dataSourceFactory.createDataSource();
|
||||
DashChunkSource chunkSource = new DashChunkSource(loader, manifest, index, adaptationSetIndex,
|
||||
trackGroups.get(selection.group), selectedTracks, dataSource, adaptiveEvaluator,
|
||||
elapsedRealtimeOffset);
|
||||
|
|
|
|||
|
|
@ -21,12 +21,11 @@ import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
|
|||
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
|
||||
import com.google.android.exoplayer2.source.MediaPeriod;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
import com.google.android.exoplayer2.source.chunk.FormatEvaluator;
|
||||
import com.google.android.exoplayer2.source.dash.mpd.MediaPresentationDescription;
|
||||
import com.google.android.exoplayer2.source.dash.mpd.MediaPresentationDescriptionParser;
|
||||
import com.google.android.exoplayer2.source.dash.mpd.UtcTimingElement;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.Loader;
|
||||
import com.google.android.exoplayer2.upstream.ParsingLoadable;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
|
@ -57,8 +56,8 @@ public final class DashMediaSource implements MediaSource {
|
|||
|
||||
private static final String TAG = "DashMediaSource";
|
||||
|
||||
private final DataSourceFactory dataSourceFactory;
|
||||
private final BandwidthMeter bandwidthMeter;
|
||||
private final DataSource.Factory dataSourceFactory;
|
||||
private final FormatEvaluator.Factory formatEvaluatorFactory;
|
||||
private final int minLoadableRetryCount;
|
||||
private final EventDispatcher eventDispatcher;
|
||||
private final MediaPresentationDescriptionParser manifestParser;
|
||||
|
|
@ -75,19 +74,19 @@ public final class DashMediaSource implements MediaSource {
|
|||
private DashMediaPeriod[] periods;
|
||||
private long elapsedRealtimeOffset;
|
||||
|
||||
public DashMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, Handler eventHandler,
|
||||
public DashMediaSource(Uri manifestUri, DataSource.Factory dataSourceFactory,
|
||||
FormatEvaluator.Factory formatEvaluatorFactory, Handler eventHandler,
|
||||
AdaptiveMediaSourceEventListener eventListener) {
|
||||
this(manifestUri, dataSourceFactory, bandwidthMeter, DEFAULT_MIN_LOADABLE_RETRY_COUNT,
|
||||
this(manifestUri, dataSourceFactory, formatEvaluatorFactory, DEFAULT_MIN_LOADABLE_RETRY_COUNT,
|
||||
eventHandler, eventListener);
|
||||
}
|
||||
|
||||
public DashMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, int minLoadableRetryCount, Handler eventHandler,
|
||||
AdaptiveMediaSourceEventListener eventListener) {
|
||||
public DashMediaSource(Uri manifestUri, DataSource.Factory dataSourceFactory,
|
||||
FormatEvaluator.Factory formatEvaluatorFactory, int minLoadableRetryCount,
|
||||
Handler eventHandler, AdaptiveMediaSourceEventListener eventListener) {
|
||||
this.manifestUri = manifestUri;
|
||||
this.dataSourceFactory = dataSourceFactory;
|
||||
this.bandwidthMeter = bandwidthMeter;
|
||||
this.formatEvaluatorFactory = formatEvaluatorFactory;
|
||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
||||
manifestParser = new MediaPresentationDescriptionParser();
|
||||
|
|
@ -245,7 +244,7 @@ public final class DashMediaSource implements MediaSource {
|
|||
int periodCount = manifest.getPeriodCount();
|
||||
periods = new DashMediaPeriod[periodCount];
|
||||
for (int i = 0; i < periodCount; i++) {
|
||||
periods[i] = new DashMediaPeriod(manifest, i, dataSourceFactory, bandwidthMeter,
|
||||
periods[i] = new DashMediaPeriod(manifest, i, dataSourceFactory, formatEvaluatorFactory,
|
||||
minLoadableRetryCount, eventDispatcher, elapsedRealtimeOffset, loader);
|
||||
}
|
||||
scheduleManifestRefresh();
|
||||
|
|
|
|||
|
|
@ -34,9 +34,7 @@ import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser;
|
|||
import com.google.android.exoplayer2.source.hls.playlist.Variant;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import com.google.android.exoplayer2.upstream.Allocator;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.Loader;
|
||||
import com.google.android.exoplayer2.upstream.ParsingLoadable;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
|
|
@ -64,8 +62,8 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
|||
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3;
|
||||
|
||||
private final Uri manifestUri;
|
||||
private final DataSourceFactory dataSourceFactory;
|
||||
private final BandwidthMeter bandwidthMeter;
|
||||
private final DataSource.Factory dataSourceFactory;
|
||||
private final FormatEvaluator.Factory formatEvaluatorFactory;
|
||||
private final int minLoadableRetryCount;
|
||||
private final EventDispatcher eventDispatcher;
|
||||
private final IdentityHashMap<SampleStream, HlsSampleStreamWrapper> sampleStreamSources;
|
||||
|
|
@ -89,19 +87,19 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
|||
private HlsSampleStreamWrapper[] enabledSampleStreamWrappers;
|
||||
private CompositeSequenceableLoader sequenceableLoader;
|
||||
|
||||
public HlsMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, Handler eventHandler,
|
||||
public HlsMediaSource(Uri manifestUri, DataSource.Factory dataSourceFactory,
|
||||
FormatEvaluator.Factory formatEvaluatorFactory, Handler eventHandler,
|
||||
AdaptiveMediaSourceEventListener eventListener) {
|
||||
this(manifestUri, dataSourceFactory, bandwidthMeter, DEFAULT_MIN_LOADABLE_RETRY_COUNT,
|
||||
this(manifestUri, dataSourceFactory, formatEvaluatorFactory, DEFAULT_MIN_LOADABLE_RETRY_COUNT,
|
||||
eventHandler, eventListener);
|
||||
}
|
||||
|
||||
public HlsMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, int minLoadableRetryCount, Handler eventHandler,
|
||||
AdaptiveMediaSourceEventListener eventListener) {
|
||||
public HlsMediaSource(Uri manifestUri, DataSource.Factory dataSourceFactory,
|
||||
FormatEvaluator.Factory formatEvaluatorFactory, int minLoadableRetryCount,
|
||||
Handler eventHandler, AdaptiveMediaSourceEventListener eventListener) {
|
||||
this.manifestUri = manifestUri;
|
||||
this.dataSourceFactory = dataSourceFactory;
|
||||
this.bandwidthMeter = bandwidthMeter;
|
||||
this.formatEvaluatorFactory = formatEvaluatorFactory;
|
||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
||||
|
||||
|
|
@ -347,7 +345,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
|||
Format.NO_VALUE);
|
||||
Variant[] variants = new Variant[] {new Variant(playlist.baseUri, format, null)};
|
||||
sampleStreamWrappers.add(buildSampleStreamWrapper(C.TRACK_TYPE_DEFAULT, baseUri, variants,
|
||||
new FormatEvaluator.AdaptiveEvaluator(bandwidthMeter), null, null));
|
||||
formatEvaluatorFactory.createFormatEvaluator(), null, null));
|
||||
return sampleStreamWrappers;
|
||||
}
|
||||
|
||||
|
|
@ -381,7 +379,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
|||
Variant[] variants = new Variant[selectedVariants.size()];
|
||||
selectedVariants.toArray(variants);
|
||||
sampleStreamWrappers.add(buildSampleStreamWrapper(C.TRACK_TYPE_DEFAULT, baseUri, variants,
|
||||
new FormatEvaluator.AdaptiveEvaluator(bandwidthMeter), masterPlaylist.muxedAudioFormat,
|
||||
formatEvaluatorFactory.createFormatEvaluator(), masterPlaylist.muxedAudioFormat,
|
||||
masterPlaylist.muxedCaptionFormat));
|
||||
}
|
||||
|
||||
|
|
@ -409,7 +407,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
|||
private HlsSampleStreamWrapper buildSampleStreamWrapper(int trackType, String baseUri,
|
||||
Variant[] variants, FormatEvaluator formatEvaluator, Format muxedAudioFormat,
|
||||
Format muxedCaptionFormat) {
|
||||
DataSource dataSource = dataSourceFactory.createDataSource(bandwidthMeter);
|
||||
DataSource dataSource = dataSourceFactory.createDataSource();
|
||||
HlsChunkSource defaultChunkSource = new HlsChunkSource(baseUri, variants, dataSource,
|
||||
timestampAdjusterProvider, formatEvaluator);
|
||||
return new HlsSampleStreamWrapper(trackType, this, defaultChunkSource, allocator,
|
||||
|
|
|
|||
|
|
@ -30,14 +30,11 @@ import com.google.android.exoplayer2.source.TrackGroup;
|
|||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
import com.google.android.exoplayer2.source.chunk.ChunkSampleStream;
|
||||
import com.google.android.exoplayer2.source.chunk.FormatEvaluator;
|
||||
import com.google.android.exoplayer2.source.chunk.FormatEvaluator.AdaptiveEvaluator;
|
||||
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingManifest.ProtectionElement;
|
||||
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingManifest.StreamElement;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import com.google.android.exoplayer2.upstream.Allocator;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.Loader;
|
||||
import com.google.android.exoplayer2.upstream.ParsingLoadable;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
|
|
@ -68,8 +65,8 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||
private static final int INITIALIZATION_VECTOR_SIZE = 8;
|
||||
|
||||
private final Uri manifestUri;
|
||||
private final DataSourceFactory dataSourceFactory;
|
||||
private final BandwidthMeter bandwidthMeter;
|
||||
private final DataSource.Factory dataSourceFactory;
|
||||
private final FormatEvaluator.Factory formatEvaluatorFactory;
|
||||
private final int minLoadableRetryCount;
|
||||
private final EventDispatcher eventDispatcher;
|
||||
private final SmoothStreamingManifestParser manifestParser;
|
||||
|
|
@ -91,20 +88,20 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||
private TrackGroupArray trackGroups;
|
||||
private int[] trackGroupElementIndices;
|
||||
|
||||
public SmoothStreamingMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, Handler eventHandler,
|
||||
public SmoothStreamingMediaSource(Uri manifestUri, DataSource.Factory dataSourceFactory,
|
||||
FormatEvaluator.Factory formatEvaluatorFactory, Handler eventHandler,
|
||||
AdaptiveMediaSourceEventListener eventListener) {
|
||||
this(manifestUri, dataSourceFactory, bandwidthMeter, DEFAULT_MIN_LOADABLE_RETRY_COUNT,
|
||||
this(manifestUri, dataSourceFactory, formatEvaluatorFactory, DEFAULT_MIN_LOADABLE_RETRY_COUNT,
|
||||
eventHandler, eventListener);
|
||||
}
|
||||
|
||||
public SmoothStreamingMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, int minLoadableRetryCount, Handler eventHandler,
|
||||
AdaptiveMediaSourceEventListener eventListener) {
|
||||
public SmoothStreamingMediaSource(Uri manifestUri, DataSource.Factory dataSourceFactory,
|
||||
FormatEvaluator.Factory formatEvaluatorFactory, int minLoadableRetryCount,
|
||||
Handler eventHandler, AdaptiveMediaSourceEventListener eventListener) {
|
||||
this.manifestUri = Util.toLowerInvariant(manifestUri.getLastPathSegment()).equals("manifest")
|
||||
? manifestUri : Uri.withAppendedPath(manifestUri, "Manifest");
|
||||
this.dataSourceFactory = dataSourceFactory;
|
||||
this.bandwidthMeter = bandwidthMeter;
|
||||
this.formatEvaluatorFactory = formatEvaluatorFactory;
|
||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||
this.eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
||||
manifestParser = new SmoothStreamingManifestParser();
|
||||
|
|
@ -358,11 +355,11 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
|||
long positionUs) {
|
||||
int[] selectedTracks = selection.getTracks();
|
||||
FormatEvaluator adaptiveEvaluator = selectedTracks.length > 1
|
||||
? new AdaptiveEvaluator(bandwidthMeter) : null;
|
||||
? formatEvaluatorFactory.createFormatEvaluator() : null;
|
||||
int streamElementIndex = trackGroupElementIndices[selection.group];
|
||||
StreamElement streamElement = manifest.streamElements[streamElementIndex];
|
||||
int streamElementType = streamElement.type;
|
||||
DataSource dataSource = dataSourceFactory.createDataSource(bandwidthMeter);
|
||||
DataSource dataSource = dataSourceFactory.createDataSource();
|
||||
SmoothStreamingChunkSource chunkSource = new SmoothStreamingChunkSource(manifestLoader,
|
||||
manifest, streamElementIndex, trackGroups.get(selection.group), selectedTracks, dataSource,
|
||||
adaptiveEvaluator, trackEncryptionBoxes);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,18 @@ import java.io.IOException;
|
|||
*/
|
||||
public interface DataSource {
|
||||
|
||||
/**
|
||||
* A factory for {@link DataSource} instances.
|
||||
*/
|
||||
interface Factory {
|
||||
|
||||
/**
|
||||
* Creates a {@link DataSource} instance.
|
||||
*/
|
||||
DataSource createDataSource();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the {@link DataSource} to read the specified data.
|
||||
* <p>
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.upstream;
|
||||
|
||||
/**
|
||||
* A factory for {@link DataSource} instances.
|
||||
*/
|
||||
public interface DataSourceFactory {
|
||||
|
||||
/**
|
||||
* Creates a {@link DataSource} instance.
|
||||
*/
|
||||
DataSource createDataSource();
|
||||
|
||||
/**
|
||||
* Creates a {@link DataSource} instance.
|
||||
*
|
||||
* @param listener A {@link TransferListener} to receive events from the instance.
|
||||
*/
|
||||
DataSource createDataSource(TransferListener listener);
|
||||
|
||||
}
|
||||
|
|
@ -15,37 +15,41 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.upstream;
|
||||
|
||||
import com.google.android.exoplayer2.upstream.DataSource.Factory;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* A {@link DataSourceFactory} that produces {@link DefaultDataSource} instances that delegate to
|
||||
* A {@link Factory} that produces {@link DefaultDataSource} instances that delegate to
|
||||
* {@link DefaultHttpDataSource}s for non-file/asset/content URIs.
|
||||
*/
|
||||
public final class DefaultDataSourceFactory implements DataSourceFactory {
|
||||
public final class DefaultDataSourceFactory implements Factory {
|
||||
|
||||
private final Context context;
|
||||
private final String userAgent;
|
||||
private final TransferListener transferListener;
|
||||
private final boolean allowCrossProtocolRedirects;
|
||||
|
||||
public DefaultDataSourceFactory(Context context, String userAgent) {
|
||||
this(context, userAgent, false);
|
||||
this(context, userAgent, null);
|
||||
}
|
||||
|
||||
public DefaultDataSourceFactory(Context context, String userAgent,
|
||||
boolean allowCrossProtocolRedirects) {
|
||||
TransferListener transferListener) {
|
||||
this(context, userAgent, transferListener, false);
|
||||
}
|
||||
|
||||
public DefaultDataSourceFactory(Context context, String userAgent,
|
||||
TransferListener transferListener, boolean allowCrossProtocolRedirects) {
|
||||
this.context = context.getApplicationContext();
|
||||
this.userAgent = userAgent;
|
||||
this.transferListener = transferListener;
|
||||
this.allowCrossProtocolRedirects = allowCrossProtocolRedirects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultDataSource createDataSource() {
|
||||
return createDataSource(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultDataSource createDataSource(TransferListener listener) {
|
||||
return new DefaultDataSource(context, listener, userAgent, allowCrossProtocolRedirects);
|
||||
return new DefaultDataSource(context, transferListener, userAgent, allowCrossProtocolRedirects);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,11 +31,15 @@ import com.google.android.exoplayer2.playbacktests.util.MetricsLogger;
|
|||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
import com.google.android.exoplayer2.source.TrackGroup;
|
||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
import com.google.android.exoplayer2.source.chunk.FormatEvaluator;
|
||||
import com.google.android.exoplayer2.source.chunk.FormatEvaluator.AdaptiveEvaluator;
|
||||
import com.google.android.exoplayer2.source.dash.DashMediaSource;
|
||||
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
|
@ -418,9 +422,13 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
|
|||
}
|
||||
|
||||
@Override
|
||||
public MediaSource buildSource(HostActivity host, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter) {
|
||||
return new DashMediaSource(manifestUri, dataSourceFactory, bandwidthMeter,
|
||||
public MediaSource buildSource(HostActivity host, String userAgent) {
|
||||
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
|
||||
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(host, userAgent,
|
||||
bandwidthMeter);
|
||||
FormatEvaluator.Factory formatEvaluatorFactory = new AdaptiveEvaluator.Factory(
|
||||
bandwidthMeter);
|
||||
return new DashMediaSource(manifestUri, dataSourceFactory, formatEvaluatorFactory,
|
||||
MIN_LOADABLE_RETRY_COUNT, null, null);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,17 +26,12 @@ import com.google.android.exoplayer2.playbacktests.util.HostActivity.HostedTest;
|
|||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
||||
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
/**
|
||||
|
|
@ -126,10 +121,7 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
|
|||
// Build the player.
|
||||
trackSelector = buildTrackSelector(host);
|
||||
player = buildExoPlayer(host, surface, trackSelector);
|
||||
DataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(host, Util
|
||||
.getUserAgent(host, "ExoPlayerPlaybackTests"));
|
||||
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
|
||||
player.setMediaSource(buildSource(host, dataSourceFactory, bandwidthMeter));
|
||||
player.setMediaSource(buildSource(host, Util.getUserAgent(host, "ExoPlayerPlaybackTests")));
|
||||
player.addListener(this);
|
||||
player.setDebugListener(this);
|
||||
player.setPlayWhenReady(true);
|
||||
|
|
@ -293,8 +285,7 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
|
|||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected abstract MediaSource buildSource(HostActivity host, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter);
|
||||
protected abstract MediaSource buildSource(HostActivity host, String userAgent);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected void onPlayerErrorInternal(ExoPlaybackException error) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue