mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
feat(spf): relocate non-zero-PTS origin to a 0-based timeline (spike)
Opt-in relocateTimestampOrigin on the HLS engine. The video loader reads each track's decode-time origin (tfdt baseMediaDecodeTime / mdhd timescale) from the init + first media segment, then relocates the buffer to 0-based via SourceBuffer.timestampOffset = -origin, so currentTime/seekable/duration stay 0-based with no adapter translation. Off by default (zero-PTS VOD pays nothing). The established offset is published on the segment-loader snapshot so the text path can rebase cues onto the same timeline: cueFinal = cueNative + timestampOffset, where cueNative applies the X-TIMESTAMP-MAP correction (Apple) or the absolute cue time (map-less Mux, which can't self-derive the origin and reads the A/V-established one). Checkpoint before the composition-driven refactor.
This commit is contained in:
@@ -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 (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.
|
||||
*/
|
||||
timestampOffset?: number;
|
||||
};
|
||||
|
||||
export type { AppendData };
|
||||
@@ -151,6 +158,12 @@ 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) {
|
||||
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