@openmoq/playback 0.0.0-stage → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +202 -0
- package/README.md +18 -2
- package/dist/adaptive-tolerance.d.ts +128 -0
- package/dist/adaptive-tolerance.d.ts.map +1 -0
- package/dist/adaptive-tolerance.js +339 -0
- package/dist/adaptive-tolerance.js.map +1 -0
- package/dist/bandwidth-estimator.d.ts +49 -0
- package/dist/bandwidth-estimator.d.ts.map +1 -0
- package/dist/bandwidth-estimator.js +77 -0
- package/dist/bandwidth-estimator.js.map +1 -0
- package/dist/browser/index.global.js +2813 -0
- package/dist/browser/index.global.js.map +1 -0
- package/dist/browser/index.js +2788 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/buffer-based-controller.d.ts +87 -0
- package/dist/buffer-based-controller.d.ts.map +1 -0
- package/dist/buffer-based-controller.js +85 -0
- package/dist/buffer-based-controller.js.map +1 -0
- package/dist/decoder-state.d.ts +103 -0
- package/dist/decoder-state.d.ts.map +1 -0
- package/dist/decoder-state.js +145 -0
- package/dist/decoder-state.js.map +1 -0
- package/dist/gap-detector.d.ts +83 -0
- package/dist/gap-detector.d.ts.map +1 -0
- package/dist/gap-detector.js +129 -0
- package/dist/gap-detector.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/jitter-buffer.d.ts +73 -0
- package/dist/jitter-buffer.d.ts.map +1 -0
- package/dist/jitter-buffer.js +216 -0
- package/dist/jitter-buffer.js.map +1 -0
- package/dist/keyframe-validator.d.ts +26 -0
- package/dist/keyframe-validator.d.ts.map +1 -0
- package/dist/keyframe-validator.js +170 -0
- package/dist/keyframe-validator.js.map +1 -0
- package/dist/pipeline.d.ts +215 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +852 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/recovery.d.ts +166 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +176 -0
- package/dist/recovery.js.map +1 -0
- package/dist/render-scheduler.d.ts +50 -0
- package/dist/render-scheduler.d.ts.map +1 -0
- package/dist/render-scheduler.js +84 -0
- package/dist/render-scheduler.js.map +1 -0
- package/dist/startup-buffer.d.ts +68 -0
- package/dist/startup-buffer.d.ts.map +1 -0
- package/dist/startup-buffer.js +107 -0
- package/dist/startup-buffer.js.map +1 -0
- package/dist/sync.d.ts +234 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +343 -0
- package/dist/sync.js.map +1 -0
- package/dist/types.d.ts +229 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/package.json +56 -3
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playback pipeline orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Wires jitter-buffer + gap-detector + decoder-state + sync together.
|
|
5
|
+
* Accepts MoqtObject + LocHeaders, emits DecoderCommand + PlaybackEvent.
|
|
6
|
+
*
|
|
7
|
+
* Sans-I/O: no WebCodecs, no Canvas, no AudioContext — just pure logic.
|
|
8
|
+
* The browser adapter consumes the emitted DecoderCommands.
|
|
9
|
+
*
|
|
10
|
+
* @see draft-ietf-moq-loc-01 §4.2 (decode order)
|
|
11
|
+
* @see draft-ietf-moq-transport-16 §10.2.1.1 (Object Status)
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import type { MoqtObject } from '@openmoq/transport';
|
|
15
|
+
import type { LocHeaders } from '@openmoq/loc';
|
|
16
|
+
import { SyncController } from './sync.js';
|
|
17
|
+
import type { RecoveryController } from './recovery.js';
|
|
18
|
+
import type { ClockSource, DecoderCommand, PlaybackEvent, PlaybackConfig, DecoderFeedback } from './types.js';
|
|
19
|
+
/**
|
|
20
|
+
* Pipeline constructor options.
|
|
21
|
+
*/
|
|
22
|
+
export interface PipelineOptions {
|
|
23
|
+
readonly mediaType: 'video' | 'audio';
|
|
24
|
+
readonly config: PlaybackConfig;
|
|
25
|
+
readonly clock: ClockSource;
|
|
26
|
+
readonly sync: SyncController;
|
|
27
|
+
readonly onCommand: (cmd: DecoderCommand) => void;
|
|
28
|
+
readonly onEvent: (evt: PlaybackEvent) => void;
|
|
29
|
+
/** Optional recovery controller for escalation decisions. */
|
|
30
|
+
readonly recovery?: RecoveryController;
|
|
31
|
+
/** Video-only mode: set video reference from first CaptureTimestamp. */
|
|
32
|
+
readonly videoOnly?: boolean;
|
|
33
|
+
/** Live stream: enables bounded release + backlog shedding. Default: true. */
|
|
34
|
+
readonly isLive?: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Playback pipeline orchestrator.
|
|
38
|
+
*
|
|
39
|
+
* @see draft-ietf-moq-loc-01 §4.2
|
|
40
|
+
*/
|
|
41
|
+
export declare class PlaybackPipeline {
|
|
42
|
+
private readonly mediaType;
|
|
43
|
+
private readonly clock;
|
|
44
|
+
private readonly sync;
|
|
45
|
+
private readonly onCommand;
|
|
46
|
+
private readonly onEvent;
|
|
47
|
+
private readonly recovery;
|
|
48
|
+
private readonly buffer;
|
|
49
|
+
private readonly gapDetector;
|
|
50
|
+
private readonly decoderState;
|
|
51
|
+
/** Headers stored alongside objects, keyed by "groupId:objectId". */
|
|
52
|
+
private readonly headerMap;
|
|
53
|
+
/** Group reference counts in the jitter buffer. */
|
|
54
|
+
private readonly bufferedGroupCounts;
|
|
55
|
+
/** Next expected objectId within the current group for contiguity check. */
|
|
56
|
+
private nextExpectedObjectId;
|
|
57
|
+
/** Highest group from which at least one object was consumed. -1n = nothing consumed yet. */
|
|
58
|
+
private lastConsumedGroupId;
|
|
59
|
+
/** Groups for which END_OF_GROUP has been observed. */
|
|
60
|
+
private readonly endedGroups;
|
|
61
|
+
/** Timestamp when we first started waiting for active group completion. */
|
|
62
|
+
private activeGroupWaitStartUs;
|
|
63
|
+
/**
|
|
64
|
+
* Minimum group ID accepted by pushObject().
|
|
65
|
+
* Set after SKIP_FORWARD to reject stale objects from pre-skip groups
|
|
66
|
+
* that arrive late due to async QUIC stream delivery.
|
|
67
|
+
*/
|
|
68
|
+
private minAcceptGroupId;
|
|
69
|
+
/** Last group for which keyframe_waiting was emitted (dedup). */
|
|
70
|
+
private lastKeyframeWaitingGroupId;
|
|
71
|
+
/**
|
|
72
|
+
* When true, the first tick syncs to whatever group is available
|
|
73
|
+
* without gap detection — avoids cascading recovery on initial
|
|
74
|
+
* live join or after pause→resume on a live stream.
|
|
75
|
+
*
|
|
76
|
+
* Starts `true` so the first arriving group is accepted as the
|
|
77
|
+
* starting point (joining mid-broadcast is not a gap).
|
|
78
|
+
*/
|
|
79
|
+
private resetPending;
|
|
80
|
+
/** True once track_ended has been emitted — prevents re-emission on every tick. */
|
|
81
|
+
private _trackEnded;
|
|
82
|
+
/** Last emitted playback rate — dedup to avoid spamming commands. */
|
|
83
|
+
private _lastEmittedRate;
|
|
84
|
+
/**
|
|
85
|
+
* Throttle flag — set by decoder feedback when queue depth is high.
|
|
86
|
+
* While true, tick() evaluates gaps but does NOT drain the buffer.
|
|
87
|
+
* Objects still enter the jitter buffer (needed for gap detection).
|
|
88
|
+
*/
|
|
89
|
+
private _throttled;
|
|
90
|
+
/** Adaptive jitter tolerance controller (null if disabled). */
|
|
91
|
+
private readonly adaptiveTolerance;
|
|
92
|
+
/** Max objects to release per tick (video only). 0 = unlimited. */
|
|
93
|
+
private readonly maxReleasePerTick;
|
|
94
|
+
/** Max groups before shedding old ones. 0 = unlimited. */
|
|
95
|
+
private readonly maxBacklogGroups;
|
|
96
|
+
/** Video codec string from catalog (e.g., 'avc1.42c01f'). Used for keyframe validation. */
|
|
97
|
+
private _videoCodec;
|
|
98
|
+
private _videoOnly;
|
|
99
|
+
constructor(opts: PipelineOptions);
|
|
100
|
+
/**
|
|
101
|
+
* Set the video codec string for keyframe payload validation.
|
|
102
|
+
*
|
|
103
|
+
* @param codec Codec string from catalog (e.g., 'avc1.42c01f', 'hvc1', 'av01.0.08M.10')
|
|
104
|
+
* @see draft-ietf-moq-loc-01 §4.2 (decode order)
|
|
105
|
+
*/
|
|
106
|
+
setCodec(codec: string): void;
|
|
107
|
+
/**
|
|
108
|
+
* Current effective gap timeout in microseconds.
|
|
109
|
+
* When adaptive tolerance is enabled, this is auto-calibrated from jitter.
|
|
110
|
+
* Otherwise, returns the fixed configured value.
|
|
111
|
+
*/
|
|
112
|
+
get effectiveGapTimeoutUs(): number;
|
|
113
|
+
/** Last consumed group ID — for track switch subscription filters. */
|
|
114
|
+
get currentGroupId(): bigint;
|
|
115
|
+
/** Number of distinct groups currently in the jitter buffer. */
|
|
116
|
+
get bufferedGroupCount(): number;
|
|
117
|
+
/** Whether draining is throttled due to decoder backpressure. */
|
|
118
|
+
get throttled(): boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Handle feedback from browser adapters (decoder queue, errors, drift).
|
|
121
|
+
*
|
|
122
|
+
* @see draft-ietf-moq-loc-01 §2.3.1.1 (drift detection)
|
|
123
|
+
*/
|
|
124
|
+
handleFeedback(fb: DecoderFeedback): void;
|
|
125
|
+
/**
|
|
126
|
+
* Provide codec configuration (from catalog or initial headers).
|
|
127
|
+
*
|
|
128
|
+
* This is also triggered automatically when a LOC object carries the
|
|
129
|
+
* matching config property: Video Config for video, Audio Config for
|
|
130
|
+
* audio.
|
|
131
|
+
*
|
|
132
|
+
* @param config Codec-specific configuration bytes
|
|
133
|
+
*/
|
|
134
|
+
configure(config: Uint8Array): void;
|
|
135
|
+
/**
|
|
136
|
+
* Push an object into the pipeline.
|
|
137
|
+
*
|
|
138
|
+
* Data objects are buffered. Gap objects notify the gap detector.
|
|
139
|
+
*
|
|
140
|
+
* @param obj The MoqtObject (data or gap)
|
|
141
|
+
* @param headers Parsed LocHeaders (only meaningful for data objects)
|
|
142
|
+
*/
|
|
143
|
+
pushObject(obj: MoqtObject, headers?: LocHeaders): void;
|
|
144
|
+
/**
|
|
145
|
+
* Reset pipeline state for pause→resume or seek.
|
|
146
|
+
*
|
|
147
|
+
* Clears the jitter buffer, gap detector, and decoder FSM so the first
|
|
148
|
+
* arriving group after resume is accepted cleanly without cascading
|
|
149
|
+
* gap-recovery escalation from the stale pre-pause position.
|
|
150
|
+
*
|
|
151
|
+
* Emits a decoder 'reset' command so the WebCodecs decoder clears its
|
|
152
|
+
* queue and waits for the next keyframe (video) or resumes immediately
|
|
153
|
+
* (audio — Opus/AAC-LC frames are independently decodable).
|
|
154
|
+
*
|
|
155
|
+
* @param targetGroupId When seeking, set this to the target group ID.
|
|
156
|
+
* Objects from groups before this ID are rejected — prevents stale
|
|
157
|
+
* in-flight objects from corrupting the post-seek decoder state.
|
|
158
|
+
* @see draft-ietf-moq-transport-16 §9.11.1 — "it might still receive
|
|
159
|
+
* Objects outside the new range if the publisher sent them before the
|
|
160
|
+
* update was processed."
|
|
161
|
+
*/
|
|
162
|
+
/**
|
|
163
|
+
* Reset for a track switch — clears jitter buffer (old-track objects
|
|
164
|
+
* use the same groupIds as new-track per altGroup alignment), resets
|
|
165
|
+
* gap detector and group tracking. Does NOT reset decoder state or
|
|
166
|
+
* emit flush/reset commands — already-decoded frames in the renderer
|
|
167
|
+
* queue play out naturally for seamless visual transition.
|
|
168
|
+
*
|
|
169
|
+
* @param firstGroupId The first group ID from the new track — sets
|
|
170
|
+
* lastConsumedGroupId to firstGroupId-1 so the gap detector doesn't
|
|
171
|
+
* see a gap and trigger skip_forward (which would reset sync).
|
|
172
|
+
*/
|
|
173
|
+
resetForTrackSwitch(firstGroupId: bigint): void;
|
|
174
|
+
reset(targetGroupId?: bigint): void;
|
|
175
|
+
/**
|
|
176
|
+
* Process buffered objects: evaluate gaps, feed decoder FSM, emit commands.
|
|
177
|
+
*
|
|
178
|
+
* Call this on a regular interval (e.g., requestAnimationFrame or timer).
|
|
179
|
+
*/
|
|
180
|
+
tick(): void;
|
|
181
|
+
/**
|
|
182
|
+
* Drop oldest whole groups when backlog exceeds maxBacklogGroups.
|
|
183
|
+
* Keeps the newest maxBacklogGroups groups, discards the rest.
|
|
184
|
+
* After shedding, notifies decoder that a gap occurred (needs keyframe).
|
|
185
|
+
*/
|
|
186
|
+
private shedBacklog;
|
|
187
|
+
/**
|
|
188
|
+
* Whether late encoded VIDEO may be discarded before it reaches the decoder.
|
|
189
|
+
*
|
|
190
|
+
* Only explicitly discardable, non-independent frames may be. Everything
|
|
191
|
+
* else is NOT PROVEN SAFE TO DISCARD and is therefore preserved
|
|
192
|
+
* conservatively: RFC 9626 §3.1 defines D=1 as the sender asserting the
|
|
193
|
+
* frame can be removed while the stream stays decodable, so D=0 does not
|
|
194
|
+
* prove the frame is a reference — it means the receiver has no assurance
|
|
195
|
+
* that discarding it is safe. Absent marking is treated the same way, and
|
|
196
|
+
* an independent frame is preserved even if it also claims to be
|
|
197
|
+
* discardable.
|
|
198
|
+
*
|
|
199
|
+
* Lateness of decoded OUTPUT remains the output stage's decision.
|
|
200
|
+
*
|
|
201
|
+
* @see draft-ietf-moq-loc-01 §2.3.2.2 (Video Frame Marking)
|
|
202
|
+
*/
|
|
203
|
+
private isPreDecodeDroppable;
|
|
204
|
+
/**
|
|
205
|
+
* Attempt to evict a lower-importance object to make room.
|
|
206
|
+
* @returns true if the incoming object was inserted.
|
|
207
|
+
* @see draft-ietf-moq-transport-16 §7 (Priority-based dropping)
|
|
208
|
+
*/
|
|
209
|
+
private tryEvictAndInsert;
|
|
210
|
+
private processDataObject;
|
|
211
|
+
private emitFsmDecision;
|
|
212
|
+
private discardBefore;
|
|
213
|
+
private decrementGroupCount;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,oBAAoB,CAAC;AAErE,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,cAAc,CAAC;AAOlE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAI9G;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IACvC,wEAAwE;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;GAIG;AACH,qBAAa,gBAAgB;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAE1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IAEnD,qEAAqE;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAE3D,mDAAmD;IACnD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA6B;IAEjE,4EAA4E;IAC5E,OAAO,CAAC,oBAAoB,CAAM;IAElC,6FAA6F;IAC7F,OAAO,CAAC,mBAAmB,CAAO;IAElC,uDAAuD;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IAEjD,2EAA2E;IAC3E,OAAO,CAAC,sBAAsB,CAAuB;IAErD;;;;GAID;IACC,OAAO,CAAC,gBAAgB,CAAO;IAE/B,iEAAiE;IACjE,OAAO,CAAC,0BAA0B,CAAO;IAEzC;;;;;;;GAOD;IACC,OAAO,CAAC,YAAY,CAAQ;IAE5B,mFAAmF;IACnF,OAAO,CAAC,WAAW,CAAS;IAE5B,qEAAqE;IACrE,OAAO,CAAC,gBAAgB,CAAO;IAE/B;;;;GAID;IACC,OAAO,CAAC,UAAU,CAAS;IAE3B,+DAA+D;IAC/D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqC;IAEvE,mEAAmE;IACnE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAE1C,2FAA2F;IAC3F,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,UAAU,CAAU;gBAEhB,IAAI,EAAE,eAAe;IAmCjC;;;;;GAKD;IACC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B;;;;GAID;IACC,IAAI,qBAAqB,IAAI,MAAM,CAKlC;IAED,sEAAsE;IACtE,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,gEAAgE;IAChE,IAAI,kBAAkB,IAAI,MAAM,CAE/B;IAED,iEAAiE;IACjE,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;;;GAID;IACC,cAAc,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI;IAwDzC;;;;;;;;GAQD;IACC,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAWnC;;;;;;;GAOD;IACC,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IA0DvD;;;;;;;;;;;;;;;;;GAiBD;IACC;;;;;;;;;;GAUD;IACC,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAsB/C,KAAK,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;IAmBnC;;;;GAID;IACC,IAAI,IAAI,IAAI;IAiOZ;;;;GAID;IACC,OAAO,CAAC,WAAW;IAsCnB;;;;;;;;;;;;;;;GAeD;IACC,OAAO,CAAC,oBAAoB;IAM5B;;;;GAID;IACC,OAAO,CAAC,iBAAiB;IAuBzB,OAAO,CAAC,iBAAiB;IA+JzB,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,aAAa;IAqBrB,OAAO,CAAC,mBAAmB;CAU9B"}
|