Allow configuration of the Loader retry delay

Issue:#3370

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=201996109
This commit is contained in:
aquilescanta 2018-06-25 12:09:27 -07:00 committed by Oliver Woodman
parent eb8c686243
commit a1f89bec0d
9 changed files with 92 additions and 30 deletions

View File

@ -13,6 +13,9 @@
([#3972](https://github.com/google/ExoPlayer/issues/3972)).
* Pass `BandwidthMeter` to `TrackSelection.Factory` which can be used to obtain
bandwidth estimates in the future. Always null at the moment.
* Error handling:
* Allow configuration of the Loader retry delay
([#3370](https://github.com/google/ExoPlayer/issues/3370)).
* HLS:
* Allow injection of custom playlist trackers.
* Pass HTTP response headers to `HlsExtractorFactory.createExtractor`.

View File

@ -38,6 +38,7 @@ import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction;
import com.google.android.exoplayer2.upstream.Loader.Loadable;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ConditionVariable;
@ -532,7 +533,7 @@ import java.util.Arrays;
}
@Override
public @Loader.RetryAction int onLoadError(
public LoadErrorAction onLoadError(
ExtractingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) {
boolean isErrorFatal = isLoadableExceptionFatal(error);
eventDispatcher.loadError(

View File

@ -25,6 +25,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction;
import com.google.android.exoplayer2.upstream.Loader.Loadable;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
@ -228,7 +229,7 @@ import java.util.Arrays;
}
@Override
public @Loader.RetryAction int onLoadError(
public LoadErrorAction onLoadError(
SourceLoadable loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) {
errorCount++;
boolean cancel = treatLoadErrorsAsEndOfStream && errorCount >= minLoadableRetryCount;

View File

@ -28,6 +28,7 @@ import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.SequenceableLoader;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
@ -409,7 +410,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
}
@Override
public @Loader.RetryAction int onLoadError(
public LoadErrorAction onLoadError(
Chunk loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) {
long bytesLoaded = loadable.bytesLoaded();
boolean isMediaChunk = isMediaChunk(loadable);

View File

@ -23,6 +23,7 @@ import android.os.SystemClock;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.util.Util;
@ -110,12 +111,12 @@ public final class Loader implements LoaderErrorThrower {
* @param elapsedRealtimeMs {@link SystemClock#elapsedRealtime} when the error occurred.
* @param loadDurationMs The duration of the load up to the point at which the error occurred.
* @param error The load error.
* @return The desired retry action. One of {@link Loader#RETRY}, {@link
* Loader#RETRY_RESET_ERROR_COUNT}, {@link Loader#DONT_RETRY} and {@link
* Loader#DONT_RETRY_FATAL}.
* @return The desired error handling action. One of {@link Loader#RETRY}, {@link
* Loader#RETRY_RESET_ERROR_COUNT}, {@link Loader#DONT_RETRY}, {@link
* Loader#DONT_RETRY_FATAL} or a retry action created by {@link #createRetryAction}.
*/
@RetryAction
int onLoadError(T loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error);
LoadErrorAction onLoadError(
T loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error);
}
/**
@ -130,15 +131,51 @@ public final class Loader implements LoaderErrorThrower {
}
/** Actions that can be taken in response to a load error. */
/** Types of action that can be taken in response to a load error. */
@Retention(RetentionPolicy.SOURCE)
@IntDef({RETRY, RETRY_RESET_ERROR_COUNT, DONT_RETRY, DONT_RETRY_FATAL})
public @interface RetryAction {}
@IntDef({
ACTION_TYPE_RETRY,
ACTION_TYPE_RETRY_AND_RESET_ERROR_COUNT,
ACTION_TYPE_DONT_RETRY,
ACTION_TYPE_DONT_RETRY_FATAL
})
private @interface RetryActionType {}
public static final int RETRY = 0;
public static final int RETRY_RESET_ERROR_COUNT = 1;
public static final int DONT_RETRY = 2;
public static final int DONT_RETRY_FATAL = 3;
private static final int ACTION_TYPE_RETRY = 0;
private static final int ACTION_TYPE_RETRY_AND_RESET_ERROR_COUNT = 1;
private static final int ACTION_TYPE_DONT_RETRY = 2;
private static final int ACTION_TYPE_DONT_RETRY_FATAL = 3;
/** Retries the load using the default delay. */
public static final LoadErrorAction RETRY =
createRetryAction(/* resetErrorCount= */ false, C.TIME_UNSET);
/** Retries the load using the default delay and resets the error count. */
public static final LoadErrorAction RETRY_RESET_ERROR_COUNT =
createRetryAction(/* resetErrorCount= */ true, C.TIME_UNSET);
/** Discards the failed loading task and ignores any errors that have occurred. */
public static final LoadErrorAction DONT_RETRY =
new LoadErrorAction(ACTION_TYPE_DONT_RETRY, C.TIME_UNSET);
/**
* Discards the failed load. The next call to {@link #maybeThrowError()} will throw the last load
* error.
*/
public static final LoadErrorAction DONT_RETRY_FATAL =
new LoadErrorAction(ACTION_TYPE_DONT_RETRY_FATAL, C.TIME_UNSET);
/**
* Action that can be taken in response to {@link Callback#onLoadError(Loadable, long, long,
* IOException)}.
*/
public static final class LoadErrorAction {
private final @RetryActionType int type;
private final long retryDelayMillis;
private LoadErrorAction(@RetryActionType int type, long retryDelayMillis) {
this.type = type;
this.retryDelayMillis = retryDelayMillis;
}
}
private final ExecutorService downloadExecutorService;
@ -152,6 +189,19 @@ public final class Loader implements LoaderErrorThrower {
this.downloadExecutorService = Util.newSingleThreadExecutor(threadName);
}
/**
* Creates a {@link LoadErrorAction} for retrying with the given parameters.
*
* @param resetErrorCount Whether the previous error count should be set to zero.
* @param retryDelayMillis The number of milliseconds to wait before retrying.
* @return A {@link LoadErrorAction} for retrying with the given parameters.
*/
public static LoadErrorAction createRetryAction(boolean resetErrorCount, long retryDelayMillis) {
return new LoadErrorAction(
resetErrorCount ? ACTION_TYPE_RETRY_AND_RESET_ERROR_COUNT : ACTION_TYPE_RETRY,
retryDelayMillis);
}
/**
* Starts loading a {@link Loadable}.
*
@ -395,12 +445,16 @@ public final class Loader implements LoaderErrorThrower {
break;
case MSG_IO_EXCEPTION:
currentError = (IOException) msg.obj;
int retryAction = callback.onLoadError(loadable, nowMs, durationMs, currentError);
if (retryAction == DONT_RETRY_FATAL) {
LoadErrorAction action = callback.onLoadError(loadable, nowMs, durationMs, currentError);
if (action.type == ACTION_TYPE_DONT_RETRY_FATAL) {
fatalError = currentError;
} else if (retryAction != DONT_RETRY) {
errorCount = retryAction == RETRY_RESET_ERROR_COUNT ? 1 : errorCount + 1;
start(getRetryDelayMillis());
} else if (action.type != ACTION_TYPE_DONT_RETRY) {
errorCount =
action.type == ACTION_TYPE_RETRY_AND_RESET_ERROR_COUNT ? 1 : errorCount + 1;
start(
action.retryDelayMillis != C.TIME_UNSET
? action.retryDelayMillis
: getRetryDelayMillis());
}
break;
default:

View File

@ -43,6 +43,7 @@ import com.google.android.exoplayer2.source.dash.manifest.UtcTimingElement;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.upstream.ParsingLoadable;
import com.google.android.exoplayer2.util.Assertions;
@ -716,8 +717,7 @@ public final class DashMediaSource extends BaseMediaSource {
}
}
/* package */ @Loader.RetryAction
int onManifestLoadError(
/* package */ LoadErrorAction onManifestLoadError(
ParsingLoadable<DashManifest> loadable,
long elapsedRealtimeMs,
long loadDurationMs,
@ -745,8 +745,7 @@ public final class DashMediaSource extends BaseMediaSource {
onUtcTimestampResolved(loadable.getResult() - elapsedRealtimeMs);
}
/* package */ @Loader.RetryAction
int onUtcTimestampLoadError(
/* package */ LoadErrorAction onUtcTimestampLoadError(
ParsingLoadable<Long> loadable,
long elapsedRealtimeMs,
long loadDurationMs,
@ -1172,7 +1171,7 @@ public final class DashMediaSource extends BaseMediaSource {
}
@Override
public @Loader.RetryAction int onLoadError(
public LoadErrorAction onLoadError(
ParsingLoadable<DashManifest> loadable,
long elapsedRealtimeMs,
long loadDurationMs,
@ -1197,7 +1196,7 @@ public final class DashMediaSource extends BaseMediaSource {
}
@Override
public @Loader.RetryAction int onLoadError(
public LoadErrorAction onLoadError(
ParsingLoadable<Long> loadable,
long elapsedRealtimeMs,
long loadDurationMs,

View File

@ -40,6 +40,7 @@ import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.HlsUr
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
@ -602,7 +603,7 @@ import java.util.Arrays;
}
@Override
public @Loader.RetryAction int onLoadError(
public LoadErrorAction onLoadError(
Chunk loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) {
long bytesLoaded = loadable.bytesLoaded();
boolean isMediaChunk = isMediaChunk(loadable);

View File

@ -27,6 +27,7 @@ import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.HlsUr
import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction;
import com.google.android.exoplayer2.upstream.ParsingLoadable;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.UriUtil;
@ -229,7 +230,7 @@ public final class DefaultHlsPlaylistTracker
}
@Override
public @Loader.RetryAction int onLoadError(
public LoadErrorAction onLoadError(
ParsingLoadable<HlsPlaylist> loadable,
long elapsedRealtimeMs,
long loadDurationMs,
@ -485,7 +486,7 @@ public final class DefaultHlsPlaylistTracker
}
@Override
public @Loader.RetryAction int onLoadError(
public LoadErrorAction onLoadError(
ParsingLoadable<HlsPlaylist> loadable,
long elapsedRealtimeMs,
long loadDurationMs,

View File

@ -41,6 +41,7 @@ import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsUtil;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.upstream.ParsingLoadable;
import com.google.android.exoplayer2.util.Assertions;
@ -540,7 +541,7 @@ public final class SsMediaSource extends BaseMediaSource
}
@Override
public @Loader.RetryAction int onLoadError(
public LoadErrorAction onLoadError(
ParsingLoadable<SsManifest> loadable,
long elapsedRealtimeMs,
long loadDurationMs,