Ensure SampleQueue seek only happens if needed
When selecting progressive and HLS tracks, we currently check if we can either seek in the existing samples or are starting from the beginning of the stream. In both cases, we don't need to reload the stream and can continue reading. Seeking to the beginning isn't side-effect free though because it also sets the startTimeUs to zero. Whether a seek to the beginning is successful also depends on whether we already loaded a sample or not. This mean that the startTimeUs value is set (or not set) based on the speed of the Loader thread even for the same input starting from the beginning. This race condition means the actual samples we write to the stream may differ if the stream has initial samples with negative timestamps. We can avoid this race condition by checking if the queue is empty first, so that we only call seekTo if really needed. PiperOrigin-RevId: 546010951
This commit is contained in:
parent
1ef7579f5c
commit
a9be9caf40
@ -288,13 +288,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
// If there's still a chance of avoiding a seek, try and seek within the sample queue.
|
// If there's still a chance of avoiding a seek, try and seek within the sample queue.
|
||||||
if (!seekRequired) {
|
if (!seekRequired) {
|
||||||
SampleQueue sampleQueue = sampleQueues[track];
|
SampleQueue sampleQueue = sampleQueues[track];
|
||||||
// A seek can be avoided if we're able to seek to the current playback position in the
|
// A seek can be avoided if we haven't read any samples yet (e.g. for the first track
|
||||||
// sample queue, or if we haven't read anything from the queue since the previous seek
|
// selection) or we are able to seek to the current playback position in the sample queue.
|
||||||
// (this case is common for sparse tracks such as metadata tracks). In all other cases a
|
// In all other cases a seek is required.
|
||||||
// seek is required.
|
|
||||||
seekRequired =
|
seekRequired =
|
||||||
!sampleQueue.seekTo(positionUs, /* allowTimeBeyondBuffer= */ true)
|
sampleQueue.getReadIndex() != 0
|
||||||
&& sampleQueue.getReadIndex() != 0;
|
&& !sampleQueue.seekTo(positionUs, /* allowTimeBeyondBuffer= */ true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -393,13 +393,12 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
// If there's still a chance of avoiding a seek, try and seek within the sample queue.
|
// If there's still a chance of avoiding a seek, try and seek within the sample queue.
|
||||||
if (!seekRequired) {
|
if (!seekRequired) {
|
||||||
SampleQueue sampleQueue = sampleQueues[trackGroupToSampleQueueIndex[trackGroupIndex]];
|
SampleQueue sampleQueue = sampleQueues[trackGroupToSampleQueueIndex[trackGroupIndex]];
|
||||||
// A seek can be avoided if we're able to seek to the current playback position in
|
// A seek can be avoided if we haven't read any samples yet (e.g. for the first track
|
||||||
// the sample queue, or if we haven't read anything from the queue since the previous
|
// selection) or we are able to seek to the current playback position in the sample
|
||||||
// seek (this case is common for sparse tracks such as metadata tracks). In all other
|
// queue. In all other cases a seek is required.
|
||||||
// cases a seek is required.
|
|
||||||
seekRequired =
|
seekRequired =
|
||||||
!sampleQueue.seekTo(positionUs, /* allowTimeBeyondBuffer= */ true)
|
sampleQueue.getReadIndex() != 0
|
||||||
&& sampleQueue.getReadIndex() != 0;
|
&& !sampleQueue.seekTo(positionUs, /* allowTimeBeyondBuffer= */ true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user