mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
feat(spf): relocate non-zero-PTS sources to a 0-based timeline
Assets whose A/V encode starts at a non-zero native PTS (Mux instant clips, Apple bipbop @10s) are relocated onto a 0-based presentation timeline via `SourceBuffer.timestampOffset`, so buffer / model / `currentTime` / `seekable` stay 0-based and the adapter is untouched. - `establishStartMediaTime` reactor establishes each track's media-timeline origin once per source (the DOM-free half), running an injected `deriveStartMediaTime` seam over discovered container data. - Default `deriveSharedMinStartMediaTime`: relocate every track by the `min` across selected A/V origins — preserves real A/V skew and keeps every DTS >= 0. Origins below NEAR_ZERO_ORIGIN_THRESHOLD (1s) are left native (ordinary ~0-PTS VOD isn't perturbed). - `relocation-steps` message pipelines discover the origin (mdhd/tfdt head-peek) and stamp `timestampOffset`; text cues rebase by X-TIMESTAMP-MAP − origin. - Wired into both the default and audio-only HLS engines. See internal/design/spf/presentation-timeline-model.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c0cad09fd5
commit
2733cba052
@@ -17,6 +17,13 @@ export type AppendSegmentMeta = Pick<Segment, 'id' | 'startTime' | 'duration'> &
|
||||
trackId: Track['id'];
|
||||
/** Declared track bandwidth in bps (from playlist BANDWIDTH attribute). */
|
||||
trackBandwidth?: number;
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
export type { AppendData };
|
||||
@@ -151,6 +158,12 @@ function appendSegmentTask(
|
||||
});
|
||||
}
|
||||
|
||||
// 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);
|
||||
// No abort check here: the physical SourceBuffer has been modified, so
|
||||
// the model must be updated to match regardless of signal state.
|
||||
|
||||
Reference in New Issue
Block a user