wip(spf): relocation via messagePipelines step model

Rework the segment loader's per-message execution into composable step
pipelines (fetch → dispatch by default); relocation injects discover/stamp
steps between them, so loader + SourceBuffer actor stay relocation-oblivious
and Tier 0 imports no relocation code.

- segment-loader: Frame/LoadStep/StepDeps/MessagePipelines, fetchStep/
  dispatchStep (deps as 3rd arg), step-runner makeLoadTask + inFlight wrapper.
- source-buffer: drop CreateAppendMeta; keep idempotent timestampOffset guard.
- relocation.ts / origin-discoverer.ts: TRANSITIONAL — slated for rebuild as
  the establishStartMediaTime reactor.

WIP checkpoint; outstanding work tracked in
.claude/plans/spf-non-zero-pts-timestamp-offset-spike.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Christian Pillsbury
2026-07-09 12:04:23 -07:00
co-authored by Claude Opus 4.8
parent 6a20bade9b
commit 041cecca6a
9 changed files with 360 additions and 234 deletions
@@ -18,10 +18,10 @@ export type AppendSegmentMeta = Pick<Segment, 'id' | 'startTime' | 'duration'> &
/** Declared track bandwidth in bps (from playlist BANDWIDTH attribute). */
trackBandwidth?: number;
/**
* Non-zero-PTS relocation (spike): when present, set as
* `SourceBuffer.timestampOffset` before this append so native PTS is relocated
* onto a 0-based presentation timeline. Constant per source; the loader
* includes it once (on the first media segment). Absent = no relocation.
* Non-zero-PTS relocation: when present, applied as `SourceBuffer.timestampOffset`
* before this append so native PTS is relocated onto a 0-based presentation
* timeline. A relocating composition stamps it (constant per source) onto each
* media segment's meta; the apply is idempotent-guarded. Absent = no relocation.
*/
timestampOffset?: number;
};
@@ -158,10 +158,10 @@ function appendSegmentTask(
});
}
// Relocation (non-zero-PTS spike): set the offset before the coded frames
// are appended. The SerialRunner guarantees the buffer is idle here, so the
// assignment is safe; it's constant per source (loader sends it once).
if (meta.timestampOffset != null) {
// Relocation: set the offset before the coded frames are appended. The
// SerialRunner guarantees the buffer is idle here, so the assignment is safe.
// Guarded so re-stamping the (constant) offset on later appends is a no-op.
if (meta.timestampOffset != null && sourceBuffer.timestampOffset !== meta.timestampOffset) {
sourceBuffer.timestampOffset = meta.timestampOffset;
}
await appendSegment(sourceBuffer, message.data, taskSignal);