提交 a1274591 编写于 作者: O olly 提交者: Oliver Woodman

Defer retries for progressive live audio streams

Issue: #1606

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=183058160
上级 5dff21e5
......@@ -38,6 +38,8 @@
sub-streams, by allowing injection of custom `CompositeSequenceableLoader`
factories through `DashMediaSource.Factory`, `HlsMediaSource.Factory`,
`SsMediaSource.Factory`, and `MergingMediaSource`.
* Play out existing buffer before retrying for progressive live streams
([#1606](https://github.com/google/ExoPlayer/issues/1606)).
* Add `ExoPlayer.setSeekParameters` for controlling how seek operations are
performed. The `SeekParameters` class contains defaults for exact seeking and
seeking to the closest sync points before, either side or after specified seek
......
......@@ -111,6 +111,7 @@ import java.util.Arrays;
private long lastSeekPositionUs;
private long pendingResetPositionUs;
private boolean pendingDeferredRetry;
private int extractedSamplesCountAtStartOfLoad;
private boolean loadingFinished;
......@@ -259,6 +260,7 @@ import java.util.Arrays;
}
}
if (enabledTrackCount == 0) {
pendingDeferredRetry = false;
notifyDiscontinuity = false;
if (loader.isLoading()) {
// Discard as much as we can synchronously.
......@@ -299,7 +301,7 @@ import java.util.Arrays;
@Override
public boolean continueLoading(long playbackPositionUs) {
if (loadingFinished || (prepared && enabledTrackCount == 0)) {
if (loadingFinished || pendingDeferredRetry || (prepared && enabledTrackCount == 0)) {
return false;
}
boolean continuedLoading = loadCondition.open();
......@@ -361,6 +363,7 @@ import java.util.Arrays;
return positionUs;
}
// We were unable to seek within the buffer, so need to reset.
pendingDeferredRetry = false;
pendingResetPositionUs = positionUs;
loadingFinished = false;
if (loader.isLoading()) {
......@@ -404,6 +407,8 @@ import java.util.Arrays;
formatHolder, buffer, formatRequired, loadingFinished, lastSeekPositionUs);
if (result == C.RESULT_BUFFER_READ) {
maybeNotifyTrackFormat(track);
} else if (result == C.RESULT_NOTHING_READ) {
maybeStartDeferredRetry(track);
}
return result;
}
......@@ -424,6 +429,8 @@ import java.util.Arrays;
}
if (skipCount > 0) {
maybeNotifyTrackFormat(track);
} else {
maybeStartDeferredRetry(track);
}
return skipCount;
}
......@@ -441,6 +448,23 @@ import java.util.Arrays;
}
}
private void maybeStartDeferredRetry(int track) {
if (!pendingDeferredRetry
|| !trackIsAudioVideoFlags[track]
|| sampleQueues[track].hasNextSample()) {
return;
}
pendingResetPositionUs = 0;
pendingDeferredRetry = false;
notifyDiscontinuity = true;
lastSeekPositionUs = 0;
extractedSamplesCountAtStartOfLoad = 0;
for (SampleQueue sampleQueue : sampleQueues) {
sampleQueue.reset();
}
callback.onContinueLoadingRequested(this);
}
private boolean suppressRead() {
return notifyDiscontinuity || isPendingReset();
}
......@@ -523,9 +547,9 @@ import java.util.Arrays;
}
int extractedSamplesCount = getExtractedSamplesCount();
boolean madeProgress = extractedSamplesCount > extractedSamplesCountAtStartOfLoad;
configureRetry(loadable); // May reset the sample queues.
extractedSamplesCountAtStartOfLoad = getExtractedSamplesCount();
return madeProgress ? Loader.RETRY_RESET_ERROR_COUNT : Loader.RETRY;
return configureRetry(loadable, extractedSamplesCount)
? (madeProgress ? Loader.RETRY_RESET_ERROR_COUNT : Loader.RETRY)
: Loader.DONT_RETRY;
}
// ExtractorOutput implementation. Called by the loading thread.
......@@ -636,23 +660,47 @@ import java.util.Arrays;
elapsedRealtimeMs);
}
private void configureRetry(ExtractingLoadable loadable) {
/**
* Called to configure a retry when a load error occurs.
*
* @param loadable The current loadable for which the error was encountered.
* @param currentExtractedSampleCount The current number of samples that have been extracted into
* the sample queues.
* @return Whether the loader should retry with the current loadable. False indicates a deferred
* retry.
*/
private boolean configureRetry(ExtractingLoadable loadable, int currentExtractedSampleCount) {
if (length != C.LENGTH_UNSET
|| (seekMap != null && seekMap.getDurationUs() != C.TIME_UNSET)) {
// We're playing an on-demand stream. Resume the current loadable, which will
// request data starting from the point it left off.
extractedSamplesCountAtStartOfLoad = currentExtractedSampleCount;
return true;
} else if (prepared && !suppressRead()) {
// We're playing a stream of unknown length and duration. Assume it's live, and therefore that
// the data at the uri is a continuously shifting window of the latest available media. For
// this case there's no way to continue loading from where a previous load finished, so it's
// necessary to load from the start whenever commencing a new load. Deferring the retry until
// we run out of buffered data makes for a much better user experience. See:
// https://github.com/google/ExoPlayer/issues/1606.
// Note that the suppressRead() check means only a single deferred retry can occur without
// progress being made. Any subsequent failures without progress will go through the else
// block below.
pendingDeferredRetry = true;
return false;
} else {
// We're playing a stream of unknown length and duration. Assume it's live, and
// therefore that the data at the uri is a continuously shifting window of the latest
// available media. For this case there's no way to continue loading from where a
// previous load finished, so it's necessary to load from the start whenever commencing
// a new load.
lastSeekPositionUs = 0;
// This is the same case as above, except in this case there's no value in deferring the retry
// because there's no buffered data to be read. This case also covers an on-demand stream with
// unknown length that has yet to be prepared. This case cannot be disambiguated from the live
// stream case, so we have no option but to load from the start.
notifyDiscontinuity = prepared;
lastSeekPositionUs = 0;
extractedSamplesCountAtStartOfLoad = 0;
for (SampleQueue sampleQueue : sampleQueues) {
sampleQueue.reset();
}
loadable.setLoadPosition(0, 0);
return true;
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册