Allow playback to continue even after SingleSampleMediaPeriod load errors
This prevents users from having to check sideloaded subtitles URLs before preparing a SingleSampleMediaSource with it. Issue:#3140 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=174475274
This commit is contained in:
parent
ecaaed9674
commit
54a2a69b05
@ -27,7 +27,6 @@ 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.Loadable;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -52,16 +51,20 @@ import java.util.Arrays;
|
||||
private final int eventSourceId;
|
||||
private final TrackGroupArray tracks;
|
||||
private final ArrayList<SampleStreamImpl> sampleStreams;
|
||||
// Package private to avoid thunk methods.
|
||||
/* package */ final Loader loader;
|
||||
/* package */ final Format format;
|
||||
/* package */ final boolean treatLoadErrorsAsEndOfStream;
|
||||
|
||||
/* package */ boolean loadingFinished;
|
||||
/* package */ boolean loadingSucceeded;
|
||||
/* package */ byte[] sampleData;
|
||||
/* package */ int sampleSize;
|
||||
private int errorCount;
|
||||
|
||||
public SingleSampleMediaPeriod(Uri uri, DataSource.Factory dataSourceFactory, Format format,
|
||||
int minLoadableRetryCount, Handler eventHandler, EventListener eventListener,
|
||||
int eventSourceId) {
|
||||
int eventSourceId, boolean treatLoadErrorsAsEndOfStream) {
|
||||
this.uri = uri;
|
||||
this.dataSourceFactory = dataSourceFactory;
|
||||
this.format = format;
|
||||
@ -69,6 +72,7 @@ import java.util.Arrays;
|
||||
this.eventHandler = eventHandler;
|
||||
this.eventListener = eventListener;
|
||||
this.eventSourceId = eventSourceId;
|
||||
this.treatLoadErrorsAsEndOfStream = treatLoadErrorsAsEndOfStream;
|
||||
tracks = new TrackGroupArray(new TrackGroup(format));
|
||||
sampleStreams = new ArrayList<>();
|
||||
loader = new Loader("Loader:SingleSampleMediaPeriod");
|
||||
@ -85,7 +89,7 @@ import java.util.Arrays;
|
||||
|
||||
@Override
|
||||
public void maybeThrowPrepareError() throws IOException {
|
||||
loader.maybeThrowError();
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -157,6 +161,7 @@ import java.util.Arrays;
|
||||
sampleSize = loadable.sampleSize;
|
||||
sampleData = loadable.sampleData;
|
||||
loadingFinished = true;
|
||||
loadingSucceeded = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -169,6 +174,11 @@ import java.util.Arrays;
|
||||
public int onLoadError(SourceLoadable loadable, long elapsedRealtimeMs, long loadDurationMs,
|
||||
IOException error) {
|
||||
notifyLoadError(error);
|
||||
errorCount++;
|
||||
if (treatLoadErrorsAsEndOfStream && errorCount >= minLoadableRetryCount) {
|
||||
loadingFinished = true;
|
||||
return Loader.DONT_RETRY;
|
||||
}
|
||||
return Loader.RETRY;
|
||||
}
|
||||
|
||||
@ -206,7 +216,9 @@ import java.util.Arrays;
|
||||
|
||||
@Override
|
||||
public void maybeThrowError() throws IOException {
|
||||
loader.maybeThrowError();
|
||||
if (!treatLoadErrorsAsEndOfStream) {
|
||||
loader.maybeThrowError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -219,19 +231,19 @@ import java.util.Arrays;
|
||||
formatHolder.format = format;
|
||||
streamState = STREAM_STATE_SEND_SAMPLE;
|
||||
return C.RESULT_FORMAT_READ;
|
||||
}
|
||||
|
||||
Assertions.checkState(streamState == STREAM_STATE_SEND_SAMPLE);
|
||||
if (!loadingFinished) {
|
||||
return C.RESULT_NOTHING_READ;
|
||||
} else {
|
||||
buffer.timeUs = 0;
|
||||
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
|
||||
buffer.ensureSpaceForWrite(sampleSize);
|
||||
buffer.data.put(sampleData, 0, sampleSize);
|
||||
} else if (loadingFinished) {
|
||||
if (loadingSucceeded) {
|
||||
buffer.timeUs = 0;
|
||||
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
|
||||
buffer.ensureSpaceForWrite(sampleSize);
|
||||
buffer.data.put(sampleData, 0, sampleSize);
|
||||
} else {
|
||||
buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
|
||||
}
|
||||
streamState = STREAM_STATE_END_OF_STREAM;
|
||||
return C.RESULT_BUFFER_READ;
|
||||
}
|
||||
return C.RESULT_NOTHING_READ;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,21 +57,51 @@ public final class SingleSampleMediaSource implements MediaSource {
|
||||
private final Handler eventHandler;
|
||||
private final EventListener eventListener;
|
||||
private final int eventSourceId;
|
||||
private final boolean treatLoadErrorsAsEndOfStream;
|
||||
private final Timeline timeline;
|
||||
|
||||
/**
|
||||
* @param uri The {@link Uri} of the media stream.
|
||||
* @param dataSourceFactory The factory from which the {@link DataSource} to read the media will
|
||||
* be obtained.
|
||||
* @param format The {@link Format} associated with the output track.
|
||||
* @param durationUs The duration of the media stream in microseconds.
|
||||
*/
|
||||
public SingleSampleMediaSource(Uri uri, DataSource.Factory dataSourceFactory, Format format,
|
||||
long durationUs) {
|
||||
this(uri, dataSourceFactory, format, durationUs, DEFAULT_MIN_LOADABLE_RETRY_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uri The {@link Uri} of the media stream.
|
||||
* @param dataSourceFactory The factory from which the {@link DataSource} to read the media will
|
||||
* be obtained.
|
||||
* @param format The {@link Format} associated with the output track.
|
||||
* @param durationUs The duration of the media stream in microseconds.
|
||||
* @param minLoadableRetryCount The minimum number of times to retry if a loading error occurs.
|
||||
*/
|
||||
public SingleSampleMediaSource(Uri uri, DataSource.Factory dataSourceFactory, Format format,
|
||||
long durationUs, int minLoadableRetryCount) {
|
||||
this(uri, dataSourceFactory, format, durationUs, minLoadableRetryCount, null, null, 0);
|
||||
this(uri, dataSourceFactory, format, durationUs, minLoadableRetryCount, null, null, 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uri The {@link Uri} of the media stream.
|
||||
* @param dataSourceFactory The factory from which the {@link DataSource} to read the media will
|
||||
* be obtained.
|
||||
* @param format The {@link Format} associated with the output track.
|
||||
* @param durationUs The duration of the media stream in microseconds.
|
||||
* @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 eventListener A listener of events. May be null if delivery of events is not required.
|
||||
* @param eventSourceId An identifier that gets passed to {@code eventListener} methods.
|
||||
* @param treatLoadErrorsAsEndOfStream If true, load errors will not be propagated by sample
|
||||
* streams, treating them as ended instead. If false, load errors will be propagated normally
|
||||
* by {@link SampleStream#maybeThrowError()}.
|
||||
*/
|
||||
public SingleSampleMediaSource(Uri uri, DataSource.Factory dataSourceFactory, Format format,
|
||||
long durationUs, int minLoadableRetryCount, Handler eventHandler, EventListener eventListener,
|
||||
int eventSourceId) {
|
||||
int eventSourceId, boolean treatLoadErrorsAsEndOfStream) {
|
||||
this.uri = uri;
|
||||
this.dataSourceFactory = dataSourceFactory;
|
||||
this.format = format;
|
||||
@ -79,6 +109,7 @@ public final class SingleSampleMediaSource implements MediaSource {
|
||||
this.eventHandler = eventHandler;
|
||||
this.eventListener = eventListener;
|
||||
this.eventSourceId = eventSourceId;
|
||||
this.treatLoadErrorsAsEndOfStream = treatLoadErrorsAsEndOfStream;
|
||||
timeline = new SinglePeriodTimeline(durationUs, true);
|
||||
}
|
||||
|
||||
@ -98,7 +129,7 @@ public final class SingleSampleMediaSource implements MediaSource {
|
||||
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
|
||||
Assertions.checkArgument(id.periodIndex == 0);
|
||||
return new SingleSampleMediaPeriod(uri, dataSourceFactory, format, minLoadableRetryCount,
|
||||
eventHandler, eventListener, eventSourceId);
|
||||
eventHandler, eventListener, eventSourceId, treatLoadErrorsAsEndOfStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user