@blockcast/mmt-container 0.5.0 → 1.0.0-main.3cb7359ea316
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/README.md +21 -16
- package/dist/browser-runtime.js +1024 -1078
- package/dist/browser-runtime.js.map +4 -4
- package/dist/carp-catalog.d.ts +33 -87
- package/dist/carp-catalog.d.ts.map +1 -1
- package/dist/carp-catalog.js +12 -434
- package/dist/carp-catalog.js.map +4 -4
- package/dist/catalog-fec-params.d.ts +48 -161
- package/dist/catalog-fec-params.d.ts.map +1 -1
- package/dist/catalog-fec-params.js +567 -592
- package/dist/catalog-fec-params.js.map +4 -4
- package/dist/catalog-network-source.js +6 -2
- package/dist/catalog-network-source.js.map +3 -3
- package/dist/delivery-catalog.js +12 -4
- package/dist/delivery-catalog.js.map +4 -4
- package/dist/delta-fallback-config.d.ts +21 -26
- package/dist/delta-fallback-config.d.ts.map +1 -1
- package/dist/delta-fallback-config.js +582 -24
- package/dist/delta-fallback-config.js.map +4 -4
- package/dist/fec-manager.js +6 -2
- package/dist/fec-manager.js.map +3 -3
- package/dist/fec-state.d.ts +5 -43
- package/dist/fec-state.d.ts.map +1 -1
- package/dist/fec-state.js +529 -34
- package/dist/fec-state.js.map +4 -4
- package/dist/fec-worker-setup.js +6 -2
- package/dist/fec-worker-setup.js.map +3 -3
- package/dist/held-layer-admission.js +6 -2
- package/dist/held-layer-admission.js.map +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -39
- package/dist/index.js.map +2 -2
- package/dist/iso-block-locator.js +6 -2
- package/dist/iso-block-locator.js.map +3 -3
- package/dist/mfu-reassembler.js +6 -2
- package/dist/mfu-reassembler.js.map +3 -3
- package/dist/mmtp-container-parser.js +6 -2
- package/dist/mmtp-container-parser.js.map +3 -3
- package/dist/mmtp-container-parser.no-modules.js +551 -452
- package/dist/mmtp-container-parser.no-modules.js.map +4 -4
- package/dist/mmtp-decode-pipeline.js +6 -2
- package/dist/mmtp-decode-pipeline.js.map +3 -3
- package/dist/mmtp-fec-session.d.ts +7 -6
- package/dist/mmtp-fec-session.d.ts.map +1 -1
- package/dist/mmtp-fec-session.js +13 -9
- package/dist/mmtp-fec-session.js.map +3 -3
- package/dist/mmtp-router.d.ts +7 -16
- package/dist/mmtp-router.d.ts.map +1 -1
- package/dist/mmtp-router.js +19 -29
- package/dist/mmtp-router.js.map +3 -3
- package/dist/multicast-auth-catalog.js +7 -3
- package/dist/multicast-auth-catalog.js.map +3 -3
- package/dist/multicast-input.js +7 -3
- package/dist/multicast-input.js.map +3 -3
- package/dist/multicast-manager.d.ts +29 -32
- package/dist/multicast-manager.d.ts.map +1 -1
- package/dist/multicast-manager.js +682 -253
- package/dist/multicast-manager.js.map +4 -4
- package/dist/multicast-transport.d.ts +23 -2
- package/dist/multicast-transport.d.ts.map +1 -1
- package/dist/multicast-transport.js +57 -16
- package/dist/multicast-transport.js.map +4 -4
- package/dist/multicast-unwrap.js +6 -2
- package/dist/multicast-unwrap.js.map +3 -3
- package/dist/no-modules.js +551 -452
- package/dist/no-modules.js.map +4 -4
- package/dist/phase14-catalog-override.d.ts +10 -5
- package/dist/phase14-catalog-override.d.ts.map +1 -1
- package/dist/phase14-catalog-override.js +35 -11
- package/dist/phase14-catalog-override.js.map +2 -2
- package/dist/repair-fetch.d.ts +3 -1
- package/dist/repair-fetch.d.ts.map +1 -1
- package/dist/repair-fetch.js +16 -3
- package/dist/repair-fetch.js.map +3 -3
- package/dist/repair-layers.d.ts +0 -123
- package/dist/repair-layers.d.ts.map +1 -1
- package/dist/repair-layers.js +1 -349
- package/dist/repair-layers.js.map +3 -3
- package/dist/signaling.js +6 -2
- package/dist/signaling.js.map +3 -3
- package/dist/timestamp-codec.js +6 -2
- package/dist/timestamp-codec.js.map +3 -3
- package/dist/wasm-mfu-reassembler.js +6 -2
- package/dist/wasm-mfu-reassembler.js.map +3 -3
- package/dist/wasm-mmtp-container-parser.js +6 -2
- package/dist/wasm-mmtp-container-parser.js.map +3 -3
- package/package.json +9 -5
- package/schemas/catalog.schema.json +53 -58
- package/src/carp-catalog.ts +39 -229
- package/src/catalog-fec-params.ts +130 -493
- package/src/delta-fallback-config.ts +63 -50
- package/src/fec-state.ts +7 -62
- package/src/index.ts +10 -30
- package/src/mmtp-fec-session.ts +11 -10
- package/src/mmtp-router.ts +14 -29
- package/src/multicast-manager.ts +89 -121
- package/src/multicast-transport.ts +65 -12
- package/src/phase14-catalog-override.ts +67 -16
- package/src/repair-fetch.ts +27 -3
- package/src/repair-layers.ts +7 -520
- package/test-vectors/catalog/README.md +39 -67
- package/test-vectors/catalog/fec-01-runtime/README.md +15 -0
- package/test-vectors/catalog/{negative/fec-block-profile-retired.json → fec-01-runtime/fec-iso-ssbg1.json} +1 -1
- package/test-vectors/catalog/fec-01-runtime/fec-layered-repair.json +106 -0
- package/test-vectors/catalog/{negative/fec-block-profile-unknown.json → fec-01-runtime/fec-multicast.json} +2 -1
- package/test-vectors/catalog/fec-01-runtime/multicast-native-ssm-no-network-source.json +44 -0
- package/test-vectors/catalog/negative/fec-block-profile-missing.json +24 -11
- package/test-vectors/catalog/negative/fec-iso-symbol-size-below-floor.json +13 -8
- package/test-vectors/catalog/negative/fec-reed-solomon-iso-symbol-size-13.json +13 -8
- package/test-vectors/catalog/negative/fec-repair-layer-geometry.json +20 -10
- package/test-vectors/catalog/negative/fec-repair-layer-missing-symbols.json +20 -10
- package/test-vectors/catalog/negative/fec-repair-overlay-source-symbols-zero.json +25 -17
- package/test-vectors/catalog/negative/fec-repair-symbols-zero.json +13 -8
- package/test-vectors/catalog/negative/fec-source-symbols-zero.json +13 -8
- package/test-vectors/catalog/negative/fec-symbol-size-zero.json +13 -8
- package/test-vectors/catalog/negative/raptorq-source-symbols-over-max.json +18 -9
- package/test-vectors/catalog/negative/raptorq-unaligned-symbol.json +13 -8
- package/test-vectors/catalog/positive/fec-algorithm-unimplemented.json +14 -9
- package/test-vectors/catalog/positive/fec-iso-ssbg1.json +25 -12
- package/test-vectors/catalog/positive/fec-layered-repair.json +79 -35
- package/test-vectors/catalog/positive/fec-multicast.json +26 -13
- package/test-vectors/catalog/positive/fec-reed-solomon-layered.json +29 -18
- package/test-vectors/catalog/positive/multicast-draft01-4-1-example.json +28 -20
- package/test-vectors/catalog/positive/multicast-draft01-7-2-6-example.json +14 -10
- package/test-vectors/catalog/positive/multicast-native-ssm-no-network-source.json +22 -12
- package/test-vectors/catalog/section-codes.json +13 -22
- package/test-vectors/catalog-timing.json +2 -2
- package/test-vectors/catalog-validation.json +30 -243
- package/test-vectors/catalog/negative/fec-enhancement-repair-removed.json +0 -28
- package/test-vectors/catalog/negative/fec-reed-solomon-k-plus-p-over-255.json +0 -39
- package/test-vectors/catalog/negative/fec-reed-solomon-overlay-over-255.json +0 -40
- package/test-vectors/catalog/negative/fec-repair-multiple-depends.json +0 -32
- package/test-vectors/catalog/negative/fec-repair-overlay-with-layer.json +0 -34
- package/test-vectors/catalog/negative/fec-repair-priority-out-of-band.json +0 -24
- package/test-vectors/catalog/negative/fec-repair-source-symbols-without-scope.json +0 -33
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
* switching set without asking the publisher to change its catalog.
|
|
15
15
|
* - Tracks present only in the override are appended as-is.
|
|
16
16
|
* - Tracks present only in the MoQ catalog are preserved unchanged.
|
|
17
|
+
* - `fec` is the draft-ramadan-moq-fec-catalog-00 instance array; a repair
|
|
18
|
+
* track is `packaging: "fec-repair"` with `source` + `instanceId`, and each
|
|
19
|
+
* of base and delta names its own (one Track Name in two `repairTrack`
|
|
20
|
+
* members is no FEC on either, catalog-00 5 rule 2).
|
|
17
21
|
*
|
|
18
22
|
* This module is deliberately player-agnostic. It exposes:
|
|
19
23
|
*
|
|
@@ -30,7 +34,7 @@
|
|
|
30
34
|
* runtime unless the test harness opts in.
|
|
31
35
|
*/
|
|
32
36
|
|
|
33
|
-
import type {
|
|
37
|
+
import type { FecCatalogConfig } from "./carp-catalog.js";
|
|
34
38
|
|
|
35
39
|
// ---------------------------------------------------------------------------
|
|
36
40
|
// Override fixture shape (IETF draft-ietf-moq-catalogformat-01)
|
|
@@ -48,7 +52,10 @@ export interface Phase14OverrideTrack {
|
|
|
48
52
|
name: string;
|
|
49
53
|
/** CMSF packaging kind. Optional per track — when absent, the merge
|
|
50
54
|
* derives it from the override's top-level `streamingFormat`. */
|
|
51
|
-
packaging?: "mmtp" | "cmaf" | "loc" | "timeline";
|
|
55
|
+
packaging?: "mmtp" | "cmaf" | "loc" | "timeline" | "fec-repair";
|
|
56
|
+
/** A `fec-repair` track's source track and instance (catalog-00 3.2). */
|
|
57
|
+
source?: string;
|
|
58
|
+
instanceId?: number;
|
|
52
59
|
/** Required when packaging is `mmtp`; the current publisher emits MFU mode. */
|
|
53
60
|
mmtpMode?: "mfu";
|
|
54
61
|
/** Required when packaging is `mmtp`; copied into synthesized CMSF tracks. */
|
|
@@ -63,7 +70,7 @@ export interface Phase14OverrideTrack {
|
|
|
63
70
|
role?: "video" | "audio" | "timeline";
|
|
64
71
|
altGroup?: number;
|
|
65
72
|
framerate?: number;
|
|
66
|
-
fec?:
|
|
73
|
+
fec?: FecCatalogConfig;
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
/**
|
|
@@ -150,6 +157,8 @@ export function mergeOverrideIntoHangRenditions<T extends Record<string, any>>(
|
|
|
150
157
|
if (!override) return catalog;
|
|
151
158
|
|
|
152
159
|
for (const track of override.tracks) {
|
|
160
|
+
// Repair tracks are placed after the media merge, below.
|
|
161
|
+
if (track.packaging === "fec-repair") continue;
|
|
153
162
|
// Default role inference: names without an explicit role field are
|
|
154
163
|
// treated as video unless the name suffix says audio.
|
|
155
164
|
const role: "video" | "audio" =
|
|
@@ -188,9 +197,41 @@ export function mergeOverrideIntoHangRenditions<T extends Record<string, any>>(
|
|
|
188
197
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
189
198
|
(catalog as any)[bagKey] = bag;
|
|
190
199
|
}
|
|
200
|
+
|
|
201
|
+
// A repair track is a hang `repair.renditions` entry, bound by `source` +
|
|
202
|
+
// `instanceId`, never a media rendition. It is added only when the
|
|
203
|
+
// source's effective `fec` names it: a publisher `fec` that won the merge
|
|
204
|
+
// may bind a different repair track, and attaching this one would cost
|
|
205
|
+
// that instance its FEC (rule 3).
|
|
206
|
+
for (const track of override.tracks) {
|
|
207
|
+
if (track.packaging !== "fec-repair") continue;
|
|
208
|
+
const source =
|
|
209
|
+
catalog["video"]?.renditions?.[track.source as string] ??
|
|
210
|
+
catalog["audio"]?.renditions?.[track.source as string];
|
|
211
|
+
if (!namesRepairTrack(source?.fec, track.name, track.instanceId)) continue;
|
|
212
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
213
|
+
const repair: { renditions?: Record<string, any> } = catalog["repair"] ?? {};
|
|
214
|
+
repair.renditions ??= {};
|
|
215
|
+
const { name, packaging: _p, mmtpMode: _m, timescale: _t, groupDurationMs: _g, altGroup: _a, ...entry } = track;
|
|
216
|
+
repair.renditions[name] ??= entry;
|
|
217
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
218
|
+
(catalog as any)["repair"] = repair;
|
|
219
|
+
}
|
|
191
220
|
return catalog;
|
|
192
221
|
}
|
|
193
222
|
|
|
223
|
+
/** Whether `fec` holds the instance `instanceId` (default 0) whose `repairTrack` is `name`. */
|
|
224
|
+
function namesRepairTrack(fec: unknown, name: string, instanceId: unknown): boolean {
|
|
225
|
+
const id = instanceId ?? 0;
|
|
226
|
+
return (
|
|
227
|
+
Array.isArray(fec) &&
|
|
228
|
+
fec.some(
|
|
229
|
+
(i) =>
|
|
230
|
+
typeof i === "object" && i !== null && (i.instanceId ?? 0) === id && i.repairTrack === name,
|
|
231
|
+
)
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
194
235
|
// ---------------------------------------------------------------------------
|
|
195
236
|
// CMSF tracks merge (moqtail-private)
|
|
196
237
|
// ---------------------------------------------------------------------------
|
|
@@ -248,7 +289,12 @@ export function mergeOverrideIntoCmsfTracks(
|
|
|
248
289
|
(t) => t.role === "audio" && typeof t.codec === "string" && (t.codec as string).length > 0,
|
|
249
290
|
);
|
|
250
291
|
|
|
251
|
-
|
|
292
|
+
// Media first, so a repair track can check its source's effective `fec`.
|
|
293
|
+
const ordered = [
|
|
294
|
+
...override.tracks.filter((t) => t.packaging !== "fec-repair"),
|
|
295
|
+
...override.tracks.filter((t) => t.packaging === "fec-repair"),
|
|
296
|
+
];
|
|
297
|
+
for (const ot of ordered) {
|
|
252
298
|
const existing = byName.get(ot.name);
|
|
253
299
|
if (existing !== undefined) {
|
|
254
300
|
// Preserve publisher-emitted fec + framerate — those describe what
|
|
@@ -290,13 +336,18 @@ export function mergeOverrideIntoCmsfTracks(
|
|
|
290
336
|
`[phase14-catalog-override] track "${ot.name}" has no packaging — supply per-track or set top-level streamingFormat`,
|
|
291
337
|
);
|
|
292
338
|
}
|
|
293
|
-
// Role inference: repair tracks
|
|
294
|
-
//
|
|
295
|
-
const
|
|
339
|
+
// Role inference: repair tracks stay role-less per CMSF convention;
|
|
340
|
+
// others default to video. Decided by packaging, never by name.
|
|
341
|
+
const isRepair = packaging === "fec-repair";
|
|
342
|
+
// Same rule as the hang path: only a repair track its source names.
|
|
343
|
+
if (isRepair && !namesRepairTrack(byName.get(ot.source as string)?.fec, ot.name, ot.instanceId)) {
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
const role = ot.role ?? (isRepair ? undefined : "video");
|
|
296
347
|
const inheritedCodec =
|
|
297
348
|
role === "audio" ? existingAudioTrack?.codec : existingVideoTrack?.codec;
|
|
298
349
|
const codec = ot.codec ?? inheritedCodec;
|
|
299
|
-
if (packaging !== "timeline" && (typeof codec !== "string" || codec.length === 0)) {
|
|
350
|
+
if (packaging !== "timeline" && !isRepair && (typeof codec !== "string" || codec.length === 0)) {
|
|
300
351
|
throw new Error(
|
|
301
352
|
`[phase14-catalog-override] track "${ot.name}" has no codec (packaging='${packaging}') — supply per-track or ensure the publisher catalog has a ${role ?? "video"} track to inherit from`,
|
|
302
353
|
);
|
|
@@ -317,14 +368,14 @@ export function mergeOverrideIntoCmsfTracks(
|
|
|
317
368
|
`[phase14-catalog-override] track "${ot.name}" has packaging='mmtp' but no valid groupDurationMs`,
|
|
318
369
|
);
|
|
319
370
|
}
|
|
320
|
-
const entry: CmsfTrackJson = {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
if (mmtpMode !== undefined) entry.mmtpMode = mmtpMode;
|
|
326
|
-
if (ot.timescale !== undefined) entry.timescale = ot.timescale;
|
|
327
|
-
if (ot.groupDurationMs !== undefined) entry.groupDurationMs = ot.groupDurationMs;
|
|
371
|
+
const entry: CmsfTrackJson = { name: ot.name, packaging };
|
|
372
|
+
if (codec !== undefined && !isRepair) entry.codec = codec as string;
|
|
373
|
+
if (ot.source !== undefined) entry["source"] = ot.source;
|
|
374
|
+
if (ot.instanceId !== undefined) entry["instanceId"] = ot.instanceId;
|
|
375
|
+
// Block geometry on a repair track costs its instance FEC (rule 1).
|
|
376
|
+
if (mmtpMode !== undefined && !isRepair) entry.mmtpMode = mmtpMode;
|
|
377
|
+
if (ot.timescale !== undefined && !isRepair) entry.timescale = ot.timescale;
|
|
378
|
+
if (ot.groupDurationMs !== undefined && !isRepair) entry.groupDurationMs = ot.groupDurationMs;
|
|
328
379
|
if (role !== undefined) entry.role = role;
|
|
329
380
|
if (ot.framerate !== undefined) entry.framerate = ot.framerate;
|
|
330
381
|
if (ot.fec !== undefined) entry.fec = ot.fec;
|
package/src/repair-fetch.ts
CHANGED
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
* below a RAP the receiver already holds complete is not requested at
|
|
30
30
|
* all (`moot-rap`), and a P0 FETCH still running when such a RAP
|
|
31
31
|
* arrives is cancelled (`repair-stopped`, `moot`): the receiver resumes
|
|
32
|
-
* from that RAP (draft-ramadan-moq-fec §11.4.2).
|
|
32
|
+
* from that RAP (draft-ramadan-moq-fec §11.4.2). Only a repair that
|
|
33
|
+
* could not land by the block's playout deadline (it relies on the
|
|
34
|
+
* keyframe budget's extension) is moot: one that can stalls nothing.
|
|
33
35
|
* - P1 (audio) dispatches, uncapped, while no P0 is queued or in flight;
|
|
34
36
|
* P2 (delta) only while no P0/P1 is, earliest absolute fail deadline
|
|
35
37
|
* first (§11.4.5 item 3).
|
|
@@ -575,6 +577,8 @@ type StopReason = RepairStopReason
|
|
|
575
577
|
|
|
576
578
|
interface FetchRun {
|
|
577
579
|
readonly controller: AbortController
|
|
580
|
+
/** When this FETCH went out: it lands around `sentAt + rtt`. */
|
|
581
|
+
readonly sentAt: number
|
|
578
582
|
stopped: StopReason | null
|
|
579
583
|
}
|
|
580
584
|
|
|
@@ -596,6 +600,11 @@ interface RepairEntry {
|
|
|
596
600
|
* later: a block reclassified from delta can gain the keyframe budget.
|
|
597
601
|
*/
|
|
598
602
|
deadlineAt: number
|
|
603
|
+
/**
|
|
604
|
+
* `deadlineAt` without the keyframe budget's extension: the block's playout
|
|
605
|
+
* deadline. A FETCH landing by it costs no stall, so it is never moot.
|
|
606
|
+
*/
|
|
607
|
+
playoutDeadlineAt: number
|
|
599
608
|
/** Inputs `deadlineAt` was computed from; they move with it. */
|
|
600
609
|
anchorAt: number | null
|
|
601
610
|
delayMs: number | null
|
|
@@ -697,9 +706,18 @@ export function wireRepairFetch(mc: RepairFetchHost, opts: WireRepairFetchOption
|
|
|
697
706
|
return length === undefined ? undefined : entry.sbn + length - 1
|
|
698
707
|
}
|
|
699
708
|
|
|
700
|
-
/**
|
|
709
|
+
/**
|
|
710
|
+
* A keyframe request whose whole block lies below a RAP already held
|
|
711
|
+
* complete, and whose repair can only land on the keyframe budget's
|
|
712
|
+
* extension. One that lands by the playout deadline stalls nothing, and
|
|
713
|
+
* skipping it only throws away the block's frames (BLO-51635).
|
|
714
|
+
*/
|
|
701
715
|
const moot = (entry: RepairEntry): boolean => {
|
|
702
716
|
if (entry.priority !== 0) return false
|
|
717
|
+
const rttMs = readRtt()
|
|
718
|
+
// A running FETCH lands relative to when it was sent, not to now.
|
|
719
|
+
const sentAt = entry.running?.sentAt ?? performance.now()
|
|
720
|
+
if (rttMs !== null && sentAt + rttMs < entry.playoutDeadlineAt) return false
|
|
703
721
|
const last = lastSsId(entry)
|
|
704
722
|
if (last === undefined) return false
|
|
705
723
|
try {
|
|
@@ -832,7 +850,7 @@ export function wireRepairFetch(mc: RepairFetchHost, opts: WireRepairFetchOption
|
|
|
832
850
|
bound: entry.bound,
|
|
833
851
|
...(entry.range ? { range: true as const } : {}),
|
|
834
852
|
})
|
|
835
|
-
const run: FetchRun = { controller: new AbortController(), stopped: null }
|
|
853
|
+
const run: FetchRun = { controller: new AbortController(), sentAt: now, stopped: null }
|
|
836
854
|
entry.running = run
|
|
837
855
|
// Hold the block open to the presentation deadline while this FETCH can
|
|
838
856
|
// still land: the multicast span elapsing must not abort it.
|
|
@@ -1053,6 +1071,10 @@ export function wireRepairFetch(mc: RepairFetchHost, opts: WireRepairFetchOption
|
|
|
1053
1071
|
)
|
|
1054
1072
|
if (promotedDeadline !== null && promotedDeadline.deadlineAt > entry.deadlineAt) {
|
|
1055
1073
|
entry.deadlineAt = promotedDeadline.deadlineAt
|
|
1074
|
+
entry.playoutDeadlineAt = Math.max(
|
|
1075
|
+
entry.playoutDeadlineAt,
|
|
1076
|
+
promotedDeadline.deadlineAt - promotedDeadline.extensionMs,
|
|
1077
|
+
)
|
|
1056
1078
|
entry.anchorAt = promotedDeadline.anchorAt
|
|
1057
1079
|
entry.delayMs = promotedDeadline.delayMs
|
|
1058
1080
|
entry.bound = promotedDeadline.bound
|
|
@@ -1231,6 +1253,7 @@ export function wireRepairFetch(mc: RepairFetchHost, opts: WireRepairFetchOption
|
|
|
1231
1253
|
priority,
|
|
1232
1254
|
subscriberPriority: wire.subscriberPriority,
|
|
1233
1255
|
deadlineAt: deadline.deadlineAt,
|
|
1256
|
+
playoutDeadlineAt: deadline.deadlineAt - deadline.extensionMs,
|
|
1234
1257
|
anchorAt: deadline.anchorAt,
|
|
1235
1258
|
delayMs: deadline.delayMs,
|
|
1236
1259
|
bound: deadline.bound,
|
|
@@ -1313,6 +1336,7 @@ export function wireRepairFetch(mc: RepairFetchHost, opts: WireRepairFetchOption
|
|
|
1313
1336
|
priority,
|
|
1314
1337
|
subscriberPriority: wire.subscriberPriority,
|
|
1315
1338
|
deadlineAt: deadline.deadlineAt,
|
|
1339
|
+
playoutDeadlineAt: deadline.deadlineAt - deadline.extensionMs,
|
|
1316
1340
|
anchorAt: deadline.anchorAt,
|
|
1317
1341
|
delayMs: deadline.delayMs,
|
|
1318
1342
|
bound: deadline.bound,
|