21.3 review fixes: guard superseded-seek failures; restore post-recovery retry
C6/AC8: IsStillActiveSeek() predicate guards all three SeekBeyondBuffer failure exits, so a superseded seek never recovers over a newer seek's state. AC6: empty scheduler routes to seekBeyondBuffer so a same-target retry (seek or play) refetches instead of no-oping.
This commit is contained in:
@@ -440,21 +440,28 @@ export class AudioPlayer {
|
||||
const bufferEnd = this.scheduler.getTotalDuration() + bufferStart;
|
||||
|
||||
// The window-miss test for BOTH directions, and the 21.3 refill trigger for backward seeks.
|
||||
// Position must be within [bufferStart, bufferEnd] to resolve from the retained buffers:
|
||||
// - position >= bufferStart : UC3 — seek back within the retained back-window. Served from
|
||||
// buffer with NO network refetch. (The lower bound is load-bearing: after eviction or a
|
||||
// prior seek-beyond-buffer, bufferStart > 0, and a target below it would otherwise produce
|
||||
// a negative bufferRelativePosition in seekWithinBuffer, silently clamping to position 0.)
|
||||
// Position must be within [bufferStart, bufferEnd] AND the scheduler must hold buffers to
|
||||
// resolve from the retained window:
|
||||
// - position >= bufferStart AND hasBuffers : UC3 — seek back within the retained back-window.
|
||||
// Served from buffer with NO network refetch. (The lower bound is load-bearing: after
|
||||
// eviction or a prior seek-beyond-buffer, bufferStart > 0, and a target below it would
|
||||
// otherwise produce a negative bufferRelativePosition in seekWithinBuffer, silently clamping
|
||||
// to position 0.)
|
||||
// - position < bufferStart : UC4 — seek back PAST the retained tail (the window was evicted).
|
||||
// Falls through to seekBeyondBuffer, which is the existing Range path run toward an EARLIER
|
||||
// offset. This is the 21.3 window-miss refill: "a seek the listener didn't initiate" reuses
|
||||
// the same per-path resolver + reinit a forward seek-beyond-buffer uses, no new mechanism.
|
||||
// - position > bufferEnd : UC2/UC5 — forward seek beyond buffer, unchanged.
|
||||
if (position >= bufferStart && position <= bufferEnd) {
|
||||
// - !hasBuffers (degenerate [P,P] window post-recovery): the window check above would
|
||||
// spuriously route ANY target to seekWithinBuffer (bufferStart==bufferEnd==seekPosition
|
||||
// after recoverFromFailedRefill). Force seekBeyondBuffer so a same-target retry actually
|
||||
// refetches (AC6 retry contract). The !hasBuffers guard only fires in the degenerate case —
|
||||
// a populated retained window has buffers and is unaffected (AC4 not regressed).
|
||||
if (position >= bufferStart && position <= bufferEnd && this.scheduler.hasBuffers()) {
|
||||
return this.seekWithinBuffer(position);
|
||||
} else {
|
||||
// Seeking outside the retained window - signal C# to fetch a new stream from the resolved
|
||||
// offset (earlier for a back-past-window refill, later for a forward seek).
|
||||
// Seeking outside the retained window, or to any position in an empty scheduler —
|
||||
// signal C# to fetch a new stream from the resolved offset.
|
||||
return this.seekBeyondBuffer(position);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user