Make seeking when there's a pending reset more obviously correct

If there's already a pending reset, we need only update the pending
reset position. We can currently end up calling cancelLoading more
than once on the loader for the same task, which is hard to reason
about (although I don't think anything actually broke in practice).

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=212432266
This commit is contained in:
olly 2018-09-11 04:50:13 -07:00 committed by Oliver Woodman
parent 72efc80037
commit ba8c22aba5
3 changed files with 59 additions and 43 deletions

View File

@ -368,15 +368,22 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
boolean[] trackIsAudioVideoFlags = preparedState.trackIsAudioVideoFlags;
// Treat all seeks into non-seekable media as being to t=0.
positionUs = seekMap.isSeekable() ? positionUs : 0;
lastSeekPositionUs = positionUs;
notifyDiscontinuity = false;
// If we're not playing a live stream or pending a reset, see if we can seek within the buffer.
lastSeekPositionUs = positionUs;
if (isPendingReset()) {
// A reset is already pending. We only need to update its position.
pendingResetPositionUs = positionUs;
return positionUs;
}
// If we're not playing a live stream, try and seek within the buffer.
if (dataType != C.DATA_TYPE_MEDIA_PROGRESSIVE_LIVE
&& !isPendingReset()
&& seekInsideBufferUs(trackIsAudioVideoFlags, positionUs)) {
return positionUs;
}
// We were unable to seek within the buffer, so need to reset.
// We can't seek inside the buffer, and so need to reset.
pendingDeferredRetry = false;
pendingResetPositionUs = positionUs;
loadingFinished = false;

View File

@ -274,13 +274,12 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
*/
public void seekToUs(long positionUs) {
lastSeekPositionUs = positionUs;
primarySampleQueue.rewind();
// See if we can seek within the primary sample queue.
boolean seekInsideBuffer;
if (isPendingReset()) {
seekInsideBuffer = false;
} else {
// A reset is already pending. We only need to update its position.
pendingResetPositionUs = positionUs;
return;
}
// Detect whether the seek is to the start of a chunk that's at least partially buffered.
BaseMediaChunk seekToMediaChunk = null;
for (int i = 0; i < mediaChunks.size(); i++) {
@ -294,6 +293,10 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
break;
}
}
// See if we can seek inside the primary sample queue.
boolean seekInsideBuffer;
primarySampleQueue.rewind();
if (seekToMediaChunk != null) {
// When seeking to the start of a chunk we use the index of the first sample in the chunk
// rather than the seek position. This ensures we seek to the keyframe at the start of the
@ -310,16 +313,15 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
!= SampleQueue.ADVANCE_FAILED;
decodeOnlyUntilPositionUs = lastSeekPositionUs;
}
}
if (seekInsideBuffer) {
// We succeeded. Advance the embedded sample queues to the seek position.
// We can seek inside the buffer. Advance the embedded sample queues to the seek position.
for (SampleQueue embeddedSampleQueue : embeddedSampleQueues) {
embeddedSampleQueue.rewind();
embeddedSampleQueue.advanceTo(positionUs, true, false);
}
} else {
// We failed, and need to restart.
// We can't seek inside the buffer, and so need to reset.
pendingResetPositionUs = positionUs;
loadingFinished = false;
mediaChunks.clear();

View File

@ -386,11 +386,18 @@ import java.util.List;
*/
public boolean seekToUs(long positionUs, boolean forceReset) {
lastSeekPositionUs = positionUs;
// If we're not forced to reset nor have a pending reset, see if we can seek within the buffer.
if (sampleQueuesBuilt && !forceReset && !isPendingReset() && seekInsideBufferUs(positionUs)) {
if (isPendingReset()) {
// A reset is already pending. We only need to update its position.
pendingResetPositionUs = positionUs;
return true;
}
// If we're not forced to reset, try and seek within the buffer.
if (sampleQueuesBuilt && !forceReset && seekInsideBufferUs(positionUs)) {
return false;
}
// We were unable to seek within the buffer, so need to reset.
// We can't seek inside the buffer, and so need to reset.
pendingResetPositionUs = positionUs;
loadingFinished = false;
mediaChunks.clear();