Commit d458b90c by aquilescanta Committed by Oliver Woodman

Parameterize load error handling in ExtractorMediaSource

Issue:#2844
Issue:#3370
Issue:#2981

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=206927295
parent d744c979
...@@ -496,9 +496,9 @@ public final class C { ...@@ -496,9 +496,9 @@ public final class C {
/** A data type constant for ads loader data. */ /** A data type constant for ads loader data. */
public static final int DATA_TYPE_AD = 6; public static final int DATA_TYPE_AD = 6;
/** /**
* A data type constant for progressive media live streams, typically containing media samples. * A data type constant for live progressive media streams, typically containing media samples.
*/ */
public static final int DATA_TYPE_MEDIA_LIVE_STREAM = 7; public static final int DATA_TYPE_MEDIA_PROGRESSIVE_LIVE = 7;
/** /**
* Applications or extensions may define custom {@code DATA_TYPE_*} constants greater than or * Applications or extensions may define custom {@code DATA_TYPE_*} constants greater than or
* equal to this value. * equal to this value.
......
...@@ -37,6 +37,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelection; ...@@ -37,6 +37,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.Loader; import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction; import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction;
import com.google.android.exoplayer2.upstream.Loader.Loadable; import com.google.android.exoplayer2.upstream.Loader.Loadable;
...@@ -79,7 +80,7 @@ import java.util.Arrays; ...@@ -79,7 +80,7 @@ import java.util.Arrays;
private final Uri uri; private final Uri uri;
private final DataSource dataSource; private final DataSource dataSource;
private final int minLoadableRetryCount; private final LoadErrorHandlingPolicy loadErrorHandlingPolicy;
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
private final Listener listener; private final Listener listener;
private final Allocator allocator; private final Allocator allocator;
...@@ -98,7 +99,7 @@ import java.util.Arrays; ...@@ -98,7 +99,7 @@ import java.util.Arrays;
private int[] sampleQueueTrackIds; private int[] sampleQueueTrackIds;
private boolean sampleQueuesBuilt; private boolean sampleQueuesBuilt;
private boolean prepared; private boolean prepared;
private int actualMinLoadableRetryCount; private int dataType;
private boolean seenFirstTrackSelection; private boolean seenFirstTrackSelection;
private boolean notifyDiscontinuity; private boolean notifyDiscontinuity;
...@@ -124,7 +125,7 @@ import java.util.Arrays; ...@@ -124,7 +125,7 @@ import java.util.Arrays;
* @param uri The {@link Uri} of the media stream. * @param uri The {@link Uri} of the media stream.
* @param dataSource The data source to read the media. * @param dataSource The data source to read the media.
* @param extractors The extractors to use to read the data source. * @param extractors The extractors to use to read the data source.
* @param minLoadableRetryCount The minimum number of times to retry if a loading error occurs. * @param loadErrorHandlingPolicy The {@link LoadErrorHandlingPolicy}.
* @param eventDispatcher A dispatcher to notify of events. * @param eventDispatcher A dispatcher to notify of events.
* @param listener A listener to notify when information about the period changes. * @param listener A listener to notify when information about the period changes.
* @param allocator An {@link Allocator} from which to obtain media buffer allocations. * @param allocator An {@link Allocator} from which to obtain media buffer allocations.
...@@ -137,7 +138,7 @@ import java.util.Arrays; ...@@ -137,7 +138,7 @@ import java.util.Arrays;
Uri uri, Uri uri,
DataSource dataSource, DataSource dataSource,
Extractor[] extractors, Extractor[] extractors,
int minLoadableRetryCount, LoadErrorHandlingPolicy loadErrorHandlingPolicy,
EventDispatcher eventDispatcher, EventDispatcher eventDispatcher,
Listener listener, Listener listener,
Allocator allocator, Allocator allocator,
...@@ -145,7 +146,7 @@ import java.util.Arrays; ...@@ -145,7 +146,7 @@ import java.util.Arrays;
int continueLoadingCheckIntervalBytes) { int continueLoadingCheckIntervalBytes) {
this.uri = uri; this.uri = uri;
this.dataSource = dataSource; this.dataSource = dataSource;
this.minLoadableRetryCount = minLoadableRetryCount; this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
this.eventDispatcher = eventDispatcher; this.eventDispatcher = eventDispatcher;
this.listener = listener; this.listener = listener;
this.allocator = allocator; this.allocator = allocator;
...@@ -154,31 +155,16 @@ import java.util.Arrays; ...@@ -154,31 +155,16 @@ import java.util.Arrays;
loader = new Loader("Loader:ExtractorMediaPeriod"); loader = new Loader("Loader:ExtractorMediaPeriod");
extractorHolder = new ExtractorHolder(extractors, this); extractorHolder = new ExtractorHolder(extractors, this);
loadCondition = new ConditionVariable(); loadCondition = new ConditionVariable();
maybeFinishPrepareRunnable = new Runnable() { maybeFinishPrepareRunnable = this::maybeFinishPrepare;
@Override onContinueLoadingRequestedRunnable =
public void run() { () -> callback.onContinueLoadingRequested(ExtractorMediaPeriod.this);
maybeFinishPrepare();
}
};
onContinueLoadingRequestedRunnable = new Runnable() {
@Override
public void run() {
if (!released) {
callback.onContinueLoadingRequested(ExtractorMediaPeriod.this);
}
}
};
handler = new Handler(); handler = new Handler();
sampleQueueTrackIds = new int[0]; sampleQueueTrackIds = new int[0];
sampleQueues = new SampleQueue[0]; sampleQueues = new SampleQueue[0];
pendingResetPositionUs = C.TIME_UNSET; pendingResetPositionUs = C.TIME_UNSET;
length = C.LENGTH_UNSET; length = C.LENGTH_UNSET;
durationUs = C.TIME_UNSET; durationUs = C.TIME_UNSET;
// Assume on-demand for MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA, until prepared. dataType = C.DATA_TYPE_MEDIA;
actualMinLoadableRetryCount =
minLoadableRetryCount == ExtractorMediaSource.MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA
? ExtractorMediaSource.DEFAULT_MIN_LOADABLE_RETRY_COUNT_ON_DEMAND
: minLoadableRetryCount;
eventDispatcher.mediaPeriodCreated(); eventDispatcher.mediaPeriodCreated();
} }
...@@ -404,7 +390,7 @@ import java.util.Arrays; ...@@ -404,7 +390,7 @@ import java.util.Arrays;
} }
/* package */ void maybeThrowError() throws IOException { /* package */ void maybeThrowError() throws IOException {
loader.maybeThrowError(actualMinLoadableRetryCount); loader.maybeThrowError(loadErrorHandlingPolicy.getMinimumLoadableRetryCount(dataType));
} }
/* package */ int readData(int track, FormatHolder formatHolder, DecoderInputBuffer buffer, /* package */ int readData(int track, FormatHolder formatHolder, DecoderInputBuffer buffer,
...@@ -543,19 +529,20 @@ import java.util.Arrays; ...@@ -543,19 +529,20 @@ import java.util.Arrays;
IOException error, IOException error,
int errorCount) { int errorCount) {
copyLengthFromLoader(loadable); copyLengthFromLoader(loadable);
LoadErrorAction retryAction; LoadErrorAction loadErrorAction;
if (isLoadableExceptionFatal(error)) { long retryDelayMs =
retryAction = Loader.DONT_RETRY_FATAL; loadErrorHandlingPolicy.getRetryDelayMsFor(dataType, durationUs, error, errorCount);
} else { if (retryDelayMs == C.TIME_UNSET) {
loadErrorAction = Loader.DONT_RETRY_FATAL;
} else /* the load should be retried */ {
int extractedSamplesCount = getExtractedSamplesCount(); int extractedSamplesCount = getExtractedSamplesCount();
boolean madeProgress = extractedSamplesCount > extractedSamplesCountAtStartOfLoad; boolean madeProgress = extractedSamplesCount > extractedSamplesCountAtStartOfLoad;
retryAction = loadErrorAction =
configureRetry(loadable, extractedSamplesCount) configureRetry(loadable, extractedSamplesCount)
? (madeProgress ? Loader.RETRY_RESET_ERROR_COUNT : Loader.RETRY) ? Loader.createRetryAction(/* resetErrorCount= */ madeProgress, retryDelayMs)
: Loader.DONT_RETRY; : Loader.DONT_RETRY;
} }
boolean wasCanceled =
retryAction == Loader.DONT_RETRY || retryAction == Loader.DONT_RETRY_FATAL;
eventDispatcher.loadError( eventDispatcher.loadError(
loadable.dataSpec, loadable.dataSpec,
loadable.dataSource.getLastOpenedUri(), loadable.dataSource.getLastOpenedUri(),
...@@ -570,8 +557,8 @@ import java.util.Arrays; ...@@ -570,8 +557,8 @@ import java.util.Arrays;
loadDurationMs, loadDurationMs,
loadable.dataSource.getBytesRead(), loadable.dataSource.getBytesRead(),
error, error,
wasCanceled); !loadErrorAction.isRetry());
return retryAction; return loadErrorAction;
} }
// ExtractorOutput implementation. Called by the loading thread. // ExtractorOutput implementation. Called by the loading thread.
...@@ -639,10 +626,10 @@ import java.util.Arrays; ...@@ -639,10 +626,10 @@ import java.util.Arrays;
haveAudioVideoTracks |= isAudioVideo; haveAudioVideoTracks |= isAudioVideo;
} }
tracks = new TrackGroupArray(trackArray); tracks = new TrackGroupArray(trackArray);
if (minLoadableRetryCount == ExtractorMediaSource.MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA dataType =
&& length == C.LENGTH_UNSET && seekMap.getDurationUs() == C.TIME_UNSET) { length == C.LENGTH_UNSET && seekMap.getDurationUs() == C.TIME_UNSET
actualMinLoadableRetryCount = ExtractorMediaSource.DEFAULT_MIN_LOADABLE_RETRY_COUNT_LIVE; ? C.DATA_TYPE_MEDIA_PROGRESSIVE_LIVE
} : C.DATA_TYPE_MEDIA;
prepared = true; prepared = true;
listener.onSourceInfoRefreshed(durationUs, seekMap.isSeekable()); listener.onSourceInfoRefreshed(durationUs, seekMap.isSeekable());
callback.onPrepared(this); callback.onPrepared(this);
...@@ -655,8 +642,8 @@ import java.util.Arrays; ...@@ -655,8 +642,8 @@ import java.util.Arrays;
} }
private void startLoading() { private void startLoading() {
ExtractingLoadable loadable = new ExtractingLoadable(uri, dataSource, extractorHolder, ExtractingLoadable loadable =
loadCondition); new ExtractingLoadable(uri, dataSource, extractorHolder, loadCondition);
if (prepared) { if (prepared) {
Assertions.checkState(isPendingReset()); Assertions.checkState(isPendingReset());
if (durationUs != C.TIME_UNSET && pendingResetPositionUs >= durationUs) { if (durationUs != C.TIME_UNSET && pendingResetPositionUs >= durationUs) {
...@@ -669,7 +656,9 @@ import java.util.Arrays; ...@@ -669,7 +656,9 @@ import java.util.Arrays;
pendingResetPositionUs = C.TIME_UNSET; pendingResetPositionUs = C.TIME_UNSET;
} }
extractedSamplesCountAtStartOfLoad = getExtractedSamplesCount(); extractedSamplesCountAtStartOfLoad = getExtractedSamplesCount();
long elapsedRealtimeMs = loader.startLoading(loadable, this, actualMinLoadableRetryCount); long elapsedRealtimeMs =
loader.startLoading(
loadable, this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(dataType));
eventDispatcher.loadStarted( eventDispatcher.loadStarted(
loadable.dataSpec, loadable.dataSpec,
loadable.dataSpec.uri, loadable.dataSpec.uri,
...@@ -772,10 +761,6 @@ import java.util.Arrays; ...@@ -772,10 +761,6 @@ import java.util.Arrays;
return pendingResetPositionUs != C.TIME_UNSET; return pendingResetPositionUs != C.TIME_UNSET;
} }
private static boolean isLoadableExceptionFatal(IOException e) {
return e instanceof UnrecognizedInputFormatException;
}
private final class SampleStreamImpl implements SampleStream { private final class SampleStreamImpl implements SampleStream {
private final int track; private final int track;
...@@ -807,9 +792,7 @@ import java.util.Arrays; ...@@ -807,9 +792,7 @@ import java.util.Arrays;
} }
/** /** Loads the media stream and extracts sample data from it. */
* Loads the media stream and extracts sample data from it.
*/
/* package */ final class ExtractingLoadable implements Loadable { /* package */ final class ExtractingLoadable implements Loadable {
private final Uri uri; private final Uri uri;
...@@ -825,7 +808,10 @@ import java.util.Arrays; ...@@ -825,7 +808,10 @@ import java.util.Arrays;
private DataSpec dataSpec; private DataSpec dataSpec;
private long length; private long length;
public ExtractingLoadable(Uri uri, DataSource dataSource, ExtractorHolder extractorHolder, public ExtractingLoadable(
Uri uri,
DataSource dataSource,
ExtractorHolder extractorHolder,
ConditionVariable loadCondition) { ConditionVariable loadCondition) {
this.uri = Assertions.checkNotNull(uri); this.uri = Assertions.checkNotNull(uri);
this.dataSource = new StatsDataSource(dataSource); this.dataSource = new StatsDataSource(dataSource);
...@@ -837,11 +823,7 @@ import java.util.Arrays; ...@@ -837,11 +823,7 @@ import java.util.Arrays;
dataSpec = new DataSpec(uri, positionHolder.position, C.LENGTH_UNSET, customCacheKey); dataSpec = new DataSpec(uri, positionHolder.position, C.LENGTH_UNSET, customCacheKey);
} }
public void setLoadPosition(long position, long timeUs) { // Loadable implementation.
positionHolder.position = position;
seekTimeUs = timeUs;
pendingExtractorSeek = true;
}
@Override @Override
public void cancelLoad() { public void cancelLoad() {
...@@ -886,6 +868,13 @@ import java.util.Arrays; ...@@ -886,6 +868,13 @@ import java.util.Arrays;
} }
} }
// Internal methods.
private void setLoadPosition(long position, long timeUs) {
positionHolder.position = position;
seekTimeUs = timeUs;
pendingExtractorSeek = true;
}
} }
/** /**
...@@ -950,7 +939,5 @@ import java.util.Arrays; ...@@ -950,7 +939,5 @@ import java.util.Arrays;
extractor = null; extractor = null;
} }
} }
} }
} }
...@@ -27,6 +27,8 @@ import com.google.android.exoplayer2.extractor.ExtractorsFactory; ...@@ -27,6 +27,8 @@ import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.ads.AdsMediaSource; import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.io.IOException; import java.io.IOException;
...@@ -44,6 +46,7 @@ import java.io.IOException; ...@@ -44,6 +46,7 @@ import java.io.IOException;
*/ */
public final class ExtractorMediaSource extends BaseMediaSource public final class ExtractorMediaSource extends BaseMediaSource
implements ExtractorMediaPeriod.Listener { implements ExtractorMediaPeriod.Listener {
/** /**
* Listener of {@link ExtractorMediaSource} events. * Listener of {@link ExtractorMediaSource} events.
* *
...@@ -76,7 +79,7 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -76,7 +79,7 @@ public final class ExtractorMediaSource extends BaseMediaSource
private @Nullable ExtractorsFactory extractorsFactory; private @Nullable ExtractorsFactory extractorsFactory;
private @Nullable String customCacheKey; private @Nullable String customCacheKey;
private @Nullable Object tag; private @Nullable Object tag;
private int minLoadableRetryCount; private LoadErrorHandlingPolicy loadErrorHandlingPolicy;
private int continueLoadingCheckIntervalBytes; private int continueLoadingCheckIntervalBytes;
private boolean isCreateCalled; private boolean isCreateCalled;
...@@ -87,7 +90,7 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -87,7 +90,7 @@ public final class ExtractorMediaSource extends BaseMediaSource
*/ */
public Factory(DataSource.Factory dataSourceFactory) { public Factory(DataSource.Factory dataSourceFactory) {
this.dataSourceFactory = dataSourceFactory; this.dataSourceFactory = dataSourceFactory;
minLoadableRetryCount = MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA; loadErrorHandlingPolicy = new DefaultLoadErrorHandlingPolicy();
continueLoadingCheckIntervalBytes = DEFAULT_LOADING_CHECK_INTERVAL_BYTES; continueLoadingCheckIntervalBytes = DEFAULT_LOADING_CHECK_INTERVAL_BYTES;
} }
...@@ -138,16 +141,36 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -138,16 +141,36 @@ public final class ExtractorMediaSource extends BaseMediaSource
} }
/** /**
* Sets the minimum number of times to retry if a loading error occurs. The default value is * Sets the minimum number of times to retry if a loading error occurs. See {@link
* {@link #MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA}. * #setLoadErrorHandlingPolicy} for the default value.
*
* <p>Calling this method is equivalent to calling {@link #setLoadErrorHandlingPolicy} with
* {@link DefaultLoadErrorHandlingPolicy(int)
* DefaultLoadErrorHandlingPolicy(minLoadableRetryCount)}
* *
* @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 factory, for convenience. * @return This factory, for convenience.
* @throws IllegalStateException If one of the {@code create} methods has already been called. * @throws IllegalStateException If one of the {@code create} methods has already been called.
* @deprecated Use {@link #setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)} instead.
*/ */
@Deprecated
public Factory setMinLoadableRetryCount(int minLoadableRetryCount) { public Factory setMinLoadableRetryCount(int minLoadableRetryCount) {
return setLoadErrorHandlingPolicy(new DefaultLoadErrorHandlingPolicy(minLoadableRetryCount));
}
/**
* Sets the {@link LoadErrorHandlingPolicy}. The default value is created by calling {@link
* DefaultLoadErrorHandlingPolicy()}.
*
* <p>Calling this method overrides any calls to {@link #setMinLoadableRetryCount(int)}.
*
* @param loadErrorHandlingPolicy A {@link LoadErrorHandlingPolicy}.
* @return This factory, for convenience.
* @throws IllegalStateException If one of the {@code create} methods has already been called.
*/
public Factory setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
Assertions.checkState(!isCreateCalled); Assertions.checkState(!isCreateCalled);
this.minLoadableRetryCount = minLoadableRetryCount; this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
return this; return this;
} }
...@@ -184,7 +207,7 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -184,7 +207,7 @@ public final class ExtractorMediaSource extends BaseMediaSource
uri, uri,
dataSourceFactory, dataSourceFactory,
extractorsFactory, extractorsFactory,
minLoadableRetryCount, loadErrorHandlingPolicy,
customCacheKey, customCacheKey,
continueLoadingCheckIntervalBytes, continueLoadingCheckIntervalBytes,
tag); tag);
...@@ -211,21 +234,6 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -211,21 +234,6 @@ public final class ExtractorMediaSource extends BaseMediaSource
} }
/** /**
* The default minimum number of times to retry loading prior to failing for on-demand streams.
*/
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT_ON_DEMAND = 3;
/** The default minimum number of times to retry loading prior to failing for live streams. */
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT_LIVE = 6;
/**
* Value for {@code minLoadableRetryCount} that causes the loader to retry {@link
* #DEFAULT_MIN_LOADABLE_RETRY_COUNT_LIVE} times for live streams and {@link
* #DEFAULT_MIN_LOADABLE_RETRY_COUNT_ON_DEMAND} for on-demand streams.
*/
public static final int MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA = -1;
/**
* The default number of bytes that should be loaded between each each invocation of {@link * The default number of bytes that should be loaded between each each invocation of {@link
* MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}. * MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}.
*/ */
...@@ -234,7 +242,7 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -234,7 +242,7 @@ public final class ExtractorMediaSource extends BaseMediaSource
private final Uri uri; private final Uri uri;
private final DataSource.Factory dataSourceFactory; private final DataSource.Factory dataSourceFactory;
private final ExtractorsFactory extractorsFactory; private final ExtractorsFactory extractorsFactory;
private final int minLoadableRetryCount; private final LoadErrorHandlingPolicy loadableLoadErrorHandlingPolicy;
private final String customCacheKey; private final String customCacheKey;
private final int continueLoadingCheckIntervalBytes; private final int continueLoadingCheckIntervalBytes;
private final @Nullable Object tag; private final @Nullable Object tag;
...@@ -283,8 +291,14 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -283,8 +291,14 @@ public final class ExtractorMediaSource extends BaseMediaSource
Handler eventHandler, Handler eventHandler,
EventListener eventListener, EventListener eventListener,
String customCacheKey) { String customCacheKey) {
this(uri, dataSourceFactory, extractorsFactory, MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA, eventHandler, this(
eventListener, customCacheKey, DEFAULT_LOADING_CHECK_INTERVAL_BYTES); uri,
dataSourceFactory,
extractorsFactory,
eventHandler,
eventListener,
customCacheKey,
DEFAULT_LOADING_CHECK_INTERVAL_BYTES);
} }
/** /**
...@@ -293,7 +307,6 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -293,7 +307,6 @@ public final class ExtractorMediaSource extends BaseMediaSource
* @param extractorsFactory A factory for {@link Extractor}s to process the media stream. If the * @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. * possible formats are known, pass a factory that instantiates extractors for those formats.
* Otherwise, pass a {@link DefaultExtractorsFactory} to use default extractors. * Otherwise, pass a {@link DefaultExtractorsFactory} to use default extractors.
* @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.
* @param customCacheKey A custom key that uniquely identifies the original stream. Used for cache * @param customCacheKey A custom key that uniquely identifies the original stream. Used for cache
...@@ -307,7 +320,6 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -307,7 +320,6 @@ public final class ExtractorMediaSource extends BaseMediaSource
Uri uri, Uri uri,
DataSource.Factory dataSourceFactory, DataSource.Factory dataSourceFactory,
ExtractorsFactory extractorsFactory, ExtractorsFactory extractorsFactory,
int minLoadableRetryCount,
Handler eventHandler, Handler eventHandler,
EventListener eventListener, EventListener eventListener,
String customCacheKey, String customCacheKey,
...@@ -316,7 +328,7 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -316,7 +328,7 @@ public final class ExtractorMediaSource extends BaseMediaSource
uri, uri,
dataSourceFactory, dataSourceFactory,
extractorsFactory, extractorsFactory,
minLoadableRetryCount, new DefaultLoadErrorHandlingPolicy(),
customCacheKey, customCacheKey,
continueLoadingCheckIntervalBytes, continueLoadingCheckIntervalBytes,
/* tag= */ null); /* tag= */ null);
...@@ -329,14 +341,14 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -329,14 +341,14 @@ public final class ExtractorMediaSource extends BaseMediaSource
Uri uri, Uri uri,
DataSource.Factory dataSourceFactory, DataSource.Factory dataSourceFactory,
ExtractorsFactory extractorsFactory, ExtractorsFactory extractorsFactory,
int minLoadableRetryCount, LoadErrorHandlingPolicy loadableLoadErrorHandlingPolicy,
@Nullable String customCacheKey, @Nullable String customCacheKey,
int continueLoadingCheckIntervalBytes, int continueLoadingCheckIntervalBytes,
@Nullable Object tag) { @Nullable Object tag) {
this.uri = uri; this.uri = uri;
this.dataSourceFactory = dataSourceFactory; this.dataSourceFactory = dataSourceFactory;
this.extractorsFactory = extractorsFactory; this.extractorsFactory = extractorsFactory;
this.minLoadableRetryCount = minLoadableRetryCount; this.loadableLoadErrorHandlingPolicy = loadableLoadErrorHandlingPolicy;
this.customCacheKey = customCacheKey; this.customCacheKey = customCacheKey;
this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes; this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes;
this.timelineDurationUs = C.TIME_UNSET; this.timelineDurationUs = C.TIME_UNSET;
...@@ -368,7 +380,7 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -368,7 +380,7 @@ public final class ExtractorMediaSource extends BaseMediaSource
uri, uri,
dataSource, dataSource,
extractorsFactory.createExtractors(), extractorsFactory.createExtractors(),
minLoadableRetryCount, loadableLoadErrorHandlingPolicy,
createEventDispatcher(id), createEventDispatcher(id),
this, this,
allocator, allocator,
......
...@@ -26,12 +26,26 @@ public final class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPo ...@@ -26,12 +26,26 @@ public final class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPo
/** The default minimum number of times to retry loading data prior to propagating the error. */ /** The default minimum number of times to retry loading data prior to propagating the error. */
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3; public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3;
/**
* The default minimum number of times to retry loading prior to failing for progressive live
* streams.
*/
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT_PROGRESSIVE_LIVE = 6;
private static final int DEFAULT_BEHAVIOR_MIN_LOADABLE_RETRY_COUNT = -1;
private final int minimumLoadableRetryCount; private final int minimumLoadableRetryCount;
/** Creates an instance that returns the default values. */ /**
* Creates an instance with default behavior.
*
* <p>{@link #getMinimumLoadableRetryCount} will return {@link
* #DEFAULT_MIN_LOADABLE_RETRY_COUNT_PROGRESSIVE_LIVE} for {@code dataType} {@link
* C#DATA_TYPE_MEDIA_PROGRESSIVE_LIVE}. For other {@code dataType} values, it will return {@link
* #DEFAULT_MIN_LOADABLE_RETRY_COUNT}.
*/
public DefaultLoadErrorHandlingPolicy() { public DefaultLoadErrorHandlingPolicy() {
this(DEFAULT_MIN_LOADABLE_RETRY_COUNT); this(DEFAULT_BEHAVIOR_MIN_LOADABLE_RETRY_COUNT);
} }
/** /**
...@@ -73,9 +87,18 @@ public final class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPo ...@@ -73,9 +87,18 @@ public final class DefaultLoadErrorHandlingPolicy implements LoadErrorHandlingPo
: Math.min((errorCount - 1) * 1000, 5000); : Math.min((errorCount - 1) * 1000, 5000);
} }
/** Returns {@link #DEFAULT_MIN_LOADABLE_RETRY_COUNT}. */ /**
* See {@link #DefaultLoadErrorHandlingPolicy()} and {@link #DefaultLoadErrorHandlingPolicy(int)}
* for documentation about the behavior of this method.
*/
@Override @Override
public int getMinimumLoadableRetryCount(int dataType) { public int getMinimumLoadableRetryCount(int dataType) {
return minimumLoadableRetryCount; if (minimumLoadableRetryCount == DEFAULT_BEHAVIOR_MIN_LOADABLE_RETRY_COUNT) {
return dataType == C.DATA_TYPE_MEDIA_PROGRESSIVE_LIVE
? DEFAULT_MIN_LOADABLE_RETRY_COUNT_PROGRESSIVE_LIVE
: DEFAULT_MIN_LOADABLE_RETRY_COUNT;
} else {
return minimumLoadableRetryCount;
}
} }
} }
...@@ -33,6 +33,8 @@ import java.io.IOException; ...@@ -33,6 +33,8 @@ import java.io.IOException;
* int)} defines whether the load is retried. Errors whose load is not retried are propagated. Load * int)} defines whether the load is retried. Errors whose load is not retried are propagated. Load
* errors whose load is retried are propagated according to {@link * errors whose load is retried are propagated according to {@link
* #getMinimumLoadableRetryCount(int)}. * #getMinimumLoadableRetryCount(int)}.
*
* <p>Methods are invoked on the playback thread.
*/ */
public interface LoadErrorHandlingPolicy { public interface LoadErrorHandlingPolicy {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment