@blockcast/mmt-container 1.0.1 → 2.0.0-main.609e08d7e29f
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 +9 -7
- package/dist/browser-runtime.js +6972 -6693
- package/dist/browser-runtime.js.map +4 -4
- package/dist/carp-catalog.d.ts +7 -7
- package/dist/carp-catalog.d.ts.map +1 -1
- package/dist/carp-catalog.js +65 -230
- package/dist/carp-catalog.js.map +3 -3
- package/dist/catalog-fec-params.js.map +1 -1
- package/dist/catalog-network-source.js.map +1 -1
- package/dist/delivery-catalog.js +3 -0
- package/dist/delivery-catalog.js.map +2 -2
- package/dist/delta-fallback-config.js.map +1 -1
- package/dist/fec-manager.d.ts +25 -1
- package/dist/fec-manager.d.ts.map +1 -1
- package/dist/fec-manager.js +208 -15
- package/dist/fec-manager.js.map +2 -2
- package/dist/fec-state.js.map +1 -1
- package/dist/fec-worker-setup.js.map +1 -1
- package/dist/held-layer-admission.d.ts +8 -0
- package/dist/held-layer-admission.d.ts.map +1 -1
- package/dist/held-layer-admission.js +22 -1
- package/dist/held-layer-admission.js.map +2 -2
- package/dist/iso-block-locator.js.map +1 -1
- package/dist/mfu-reassembler.js.map +1 -1
- package/dist/mmtp-container-parser.js.map +1 -1
- package/dist/mmtp-container-parser.no-modules.js +146 -332
- package/dist/mmtp-container-parser.no-modules.js.map +4 -4
- package/dist/mmtp-decode-pipeline.js.map +1 -1
- package/dist/mmtp-fec-session.d.ts.map +1 -1
- package/dist/mmtp-fec-session.js +61 -15
- package/dist/mmtp-fec-session.js.map +3 -3
- package/dist/mmtp-router.d.ts +11 -6
- package/dist/mmtp-router.d.ts.map +1 -1
- package/dist/mmtp-router.js +47 -10
- package/dist/mmtp-router.js.map +3 -3
- package/dist/multicast-auth-catalog.d.ts +8 -8
- package/dist/multicast-auth-catalog.d.ts.map +1 -1
- package/dist/multicast-auth-catalog.js +171 -75
- package/dist/multicast-auth-catalog.js.map +4 -4
- package/dist/multicast-input.d.ts +5 -5
- package/dist/multicast-input.d.ts.map +1 -1
- package/dist/multicast-input.js +126 -49
- package/dist/multicast-input.js.map +3 -3
- package/dist/multicast-manager.d.ts +11 -4
- package/dist/multicast-manager.d.ts.map +1 -1
- package/dist/multicast-manager.js +7914 -7659
- package/dist/multicast-manager.js.map +4 -4
- package/dist/multicast-transport.d.ts +16 -1
- package/dist/multicast-transport.d.ts.map +1 -1
- package/dist/multicast-transport.js +120 -5
- package/dist/multicast-transport.js.map +4 -4
- package/dist/multicast-unwrap.js +2 -2
- package/dist/multicast-unwrap.js.map +2 -2
- package/dist/no-modules.js +100 -288
- package/dist/no-modules.js.map +4 -4
- package/dist/repair-fetch.js.map +1 -1
- package/dist/signaling.js.map +1 -1
- package/dist/timestamp-codec.js.map +1 -1
- package/dist/wasm-mfu-reassembler.js.map +1 -1
- package/dist/wasm-mmtp-container-parser.js.map +1 -1
- package/package.json +5 -5
- package/schemas/catalog.schema.json +15 -7
- package/src/carp-catalog.ts +14 -13
- package/src/fec-manager.ts +89 -14
- package/src/held-layer-admission.ts +38 -1
- package/src/mmtp-fec-session.ts +20 -12
- package/src/mmtp-router.ts +65 -16
- package/src/multicast-auth-catalog.ts +43 -36
- package/src/multicast-input.ts +28 -8
- package/src/multicast-manager.ts +38 -34
- package/src/multicast-transport.ts +74 -7
- package/test-vectors/bc-provenance-v2.json +614 -175
- package/test-vectors/catalog/README.md +24 -8
- package/test-vectors/catalog/negative/multicast-auth-asm-missing-sender-address.json +0 -2
- package/test-vectors/catalog/negative/{multicast-auth-manifest-port-equals-port.json → multicast-auth-draft01-manifest-port.json} +1 -1
- package/test-vectors/catalog/negative/multicast-auth-duplicate-first-epoch.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-duplicate-kid.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-endpoint-auth-without-object-auth.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-endpoint-missing-bandwidth.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-manifest-timer-out-of-range.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-sender-address-on-ssm.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-shared-sg-port.json +73 -0
- package/test-vectors/catalog/negative/multicast-auth-version-1.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-version-3.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-version-missing.json +0 -1
- package/test-vectors/catalog/negative/multicast-endpoint-address-family-mismatch.json +55 -0
- package/test-vectors/catalog/negative/multicast-endpoint-address-host-name.json +55 -0
- package/test-vectors/catalog/negative/multicast-endpoint-address-leading-zero.json +55 -0
- package/test-vectors/catalog/negative/multicast-endpoint-address-ls32-leading-zero.json +55 -0
- package/test-vectors/catalog/negative/multicast-endpoint-address-mapped-family-mismatch.json +55 -0
- package/test-vectors/catalog/negative/multicast-endpoint-address-zone-id.json +55 -0
- package/test-vectors/catalog/positive/multicast-auth-asm-sender.json +0 -2
- package/test-vectors/catalog/{negative/multicast-auth-max-auth-delay-above-max.json → positive/multicast-auth-max-auth-delay-above-max-clamped.json} +0 -1
- package/test-vectors/catalog/{negative/multicast-auth-max-auth-delay-below-min.json → positive/multicast-auth-max-auth-delay-below-min-clamped.json} +0 -1
- package/test-vectors/catalog/positive/multicast-auth-max-auth-delay-string.json +55 -0
- package/test-vectors/catalog/positive/multicast-auth-rotation.json +0 -1
- package/test-vectors/catalog/positive/multicast-draft01-7-2-6-example.json +0 -1
- package/test-vectors/catalog/section-codes.json +8 -3
- package/test-vectors/catalog-multicast-auth-v1.json +0 -1
- package/test-vectors/catalog-validation.json +3 -3
- package/test-vectors/generate-bc-provenance-v2.mjs +94 -14
|
@@ -25,10 +25,9 @@
|
|
|
25
25
|
"multicast-auth-endpoint-auth-without-object-auth.json": { "outOfSection": "multicast.auth" },
|
|
26
26
|
"multicast-auth-endpoint-missing-auth.json": { "outOfSection": "multicast.auth" },
|
|
27
27
|
"multicast-auth-endpoint-missing-bandwidth.json": { "outOfSection": "multicast.auth" },
|
|
28
|
-
"multicast-auth-manifest-port-equals-port.json": { "outOfSection": "multicast.auth" },
|
|
29
28
|
"multicast-auth-manifest-timer-out-of-range.json": { "outOfSection": "multicast.auth" },
|
|
30
|
-
"multicast-auth-
|
|
31
|
-
"multicast-auth-
|
|
29
|
+
"multicast-auth-draft01-manifest-port.json": { "outOfSection": "multicast.auth" },
|
|
30
|
+
"multicast-auth-shared-sg-port.json": { "outOfSection": "multicast.auth" },
|
|
32
31
|
"multicast-auth-padded-key.json": { "outOfSection": "multicast.auth" },
|
|
33
32
|
"multicast-auth-reused-track-format.json": { "outOfSection": "multicast.auth" },
|
|
34
33
|
"multicast-auth-root-dotted-key.json": { "outOfSection": "multicast.auth" },
|
|
@@ -37,6 +36,12 @@
|
|
|
37
36
|
"multicast-auth-version-1.json": { "outOfSection": "multicast.auth" },
|
|
38
37
|
"multicast-auth-version-3.json": { "outOfSection": "multicast.auth" },
|
|
39
38
|
"multicast-auth-version-missing.json": { "outOfSection": "multicast.auth" },
|
|
39
|
+
"multicast-endpoint-address-family-mismatch.json": { "outOfSection": "multicast" },
|
|
40
|
+
"multicast-endpoint-address-host-name.json": { "outOfSection": "multicast" },
|
|
41
|
+
"multicast-endpoint-address-leading-zero.json": { "outOfSection": "multicast" },
|
|
42
|
+
"multicast-endpoint-address-ls32-leading-zero.json": { "outOfSection": "multicast" },
|
|
43
|
+
"multicast-endpoint-address-mapped-family-mismatch.json": { "outOfSection": "multicast" },
|
|
44
|
+
"multicast-endpoint-address-zone-id.json": { "outOfSection": "multicast" },
|
|
40
45
|
"multicast-endpoint-foreign-namespace-track.json": { "outOfSection": "multicast" },
|
|
41
46
|
"multicast-endpoint-protocol-amt.json": { "outOfSection": "multicast" },
|
|
42
47
|
"multicast-endpoint-protocol-atsc3.json": { "outOfSection": "multicast" },
|
|
@@ -510,9 +510,9 @@
|
|
|
510
510
|
}
|
|
511
511
|
},
|
|
512
512
|
{
|
|
513
|
-
"name": "multicast.auth other than bc-provenance version 2
|
|
514
|
-
"valid":
|
|
515
|
-
"
|
|
513
|
+
"name": "multicast.auth other than bc-provenance version 2 admits no multicast endpoint, and the catalog parses (multicast-02 7.2.6)",
|
|
514
|
+
"valid": true,
|
|
515
|
+
"admitted_multicast_endpoints": 0,
|
|
516
516
|
"catalog": {
|
|
517
517
|
"version": 1,
|
|
518
518
|
"tracks": [
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// bc-provenance version 2 vectors, draft-ramadan-moq-multicast-
|
|
2
|
+
// bc-provenance version 2 vectors, draft-ramadan-moq-multicast-02 (7.2.3,
|
|
3
3
|
// 7.2.4, 7.2.7 step 1, 7.2.10, Appendix A). Case "appendix-a" reproduces the
|
|
4
4
|
// draft's Appendix A byte for byte; every other case is labelled beyond-draft.
|
|
5
|
+
// No published vector covers m >= 2 FEC instances or an empty fec array, so
|
|
6
|
+
// for those the TS, Rust and Go cells are each other's cross-check.
|
|
5
7
|
// Only node:crypto is used (sha-256, Ed25519), so the output is deterministic.
|
|
6
8
|
// Step 1 is read at join (no record of the flow verified yet), so the
|
|
7
9
|
// previous-epoch deadline of 7.2.7 (the bound of 7.2.5 plus maxAuthDelayMs +
|
|
@@ -14,7 +16,16 @@ import { dirname, join } from 'node:path';
|
|
|
14
16
|
import { fileURLToPath } from 'node:url';
|
|
15
17
|
|
|
16
18
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
17
|
-
const DRAFT_COMMIT = '
|
|
19
|
+
const DRAFT_COMMIT = '5f4917291e2f0e58bdee9e4a813ff248537695e2';
|
|
20
|
+
// The 196-octet record of draft-ramadan-moq-multicast-01 Appendix A @ abf183bf.
|
|
21
|
+
const APPENDIX_A_01_RECORD = Buffer.from(
|
|
22
|
+
'4d484d320000000100000011000000000000000100000000000003e800020100' +
|
|
23
|
+
'6ade9800fe68177dd329ee6fdd668cb43ebdeb6d2e4c2ae351fd25050ab68dd9' +
|
|
24
|
+
'8af192147ead4d8be7d24e08d7075bbac8fbe7779ab3b8f1c47d3f8be4d2a514' +
|
|
25
|
+
'f2ec20696f7d9007e81b73c9f54aff8c2f66bd6e8956bfa7e001789b986c328f' +
|
|
26
|
+
'9ed787519d5154a8e6beb7c472a09fa1e1d3d426b6042519343728835ed5c941' +
|
|
27
|
+
'6e615aad7ad335c0f0403aa8985e6b6979e5918d3d28e787ca29d55447930777' +
|
|
28
|
+
'c380d808', 'hex');
|
|
18
29
|
|
|
19
30
|
const H = (...parts) => createHash('sha256').update(Buffer.concat(parts)).digest();
|
|
20
31
|
const u8 = (n) => Buffer.from([n]);
|
|
@@ -45,12 +56,17 @@ const pseudoheader = (ep, len) =>
|
|
|
45
56
|
Buffer.concat([ip(ep.S), ip(ep.G), u8(0), u8(0x11), u16(len), u16(ep.port), u16(ep.port), u32(ep.streamId)]);
|
|
46
57
|
const digest = (ep, payload) => H(pseudoheader(ep, payload.length), payload);
|
|
47
58
|
const signedPrefix = (ep) =>
|
|
48
|
-
Buffer.concat([Buffer.from('mcast-manifest-v2\0'), u32(ep.streamId), ip(ep.S), ip(ep.G), u16(ep.
|
|
59
|
+
Buffer.concat([Buffer.from('mcast-manifest-v2\0'), u32(ep.streamId), ip(ep.S), ip(ep.G), u16(ep.port)]);
|
|
49
60
|
|
|
61
|
+
// 7.2.4: one tuple per instance of the entry's fec array in ascending
|
|
62
|
+
// instanceId, no count and no instanceId; none (absent or empty) is
|
|
63
|
+
// lp16("none") then four u32(0), and "none" is no scheme.
|
|
50
64
|
function paramsHash(p) {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
65
|
+
const instances = [...(p.fec ?? [])].sort((a, b) => (a.instanceId ?? 0) - (b.instanceId ?? 0));
|
|
66
|
+
if (instances.some((f) => f.scheme === 'none')) throw new Error('scheme "none" is reserved');
|
|
67
|
+
const fec = instances.length
|
|
68
|
+
? Buffer.concat(instances.map((f) => Buffer.concat([lp16(f.scheme), u32(f.sourceSymbols), u32(f.repairSymbols),
|
|
69
|
+
u32(f.symbolSize), u32(f.interleaveDepthMs ?? 0)])))
|
|
54
70
|
: Buffer.concat([lp16('none'), u32(0), u32(0), u32(0), u32(0)]);
|
|
55
71
|
return H(Buffer.from('BCPV2-params'), lp16(p.codec), u32(p.timescale ?? 0), u32(p.groupDurationTicks ?? 0), fec);
|
|
56
72
|
}
|
|
@@ -71,15 +87,18 @@ function record(ep, h, digests) {
|
|
|
71
87
|
return Buffer.concat([body, sign(null, Buffer.concat([signedPrefix(ep), body]), privateKey)]);
|
|
72
88
|
}
|
|
73
89
|
|
|
74
|
-
const anchorEp = { S: '198.51.100.7', G: '232.10.20.30', port: 5004,
|
|
90
|
+
const anchorEp = { S: '198.51.100.7', G: '232.10.20.30', port: 5004, streamId: 0xaabbccdd };
|
|
75
91
|
const anchorCtx = {
|
|
76
92
|
namespace: ['example.arena'],
|
|
77
93
|
packetIds: [1, 2],
|
|
78
94
|
params: {
|
|
79
95
|
codec: 'avc1.640028', timescale: 90000, groupDurationTicks: 3000,
|
|
80
|
-
fec: {
|
|
96
|
+
fec: [{ scheme: 'raptorq', sourceSymbols: 32, repairSymbols: 16, symbolSize: 1312, interleaveDepthMs: 133 }],
|
|
81
97
|
},
|
|
82
98
|
};
|
|
99
|
+
// Base plus keyframe overlay instance (draft-ramadan-moq-mmt-02 7.4.1).
|
|
100
|
+
const baseInstance = { instanceId: 0, ...anchorCtx.params.fec[0] };
|
|
101
|
+
const overlayInstance = { instanceId: 1, scheme: 'raptorq', sourceSymbols: 256, repairSymbols: 32, symbolSize: 1312, interleaveDepthMs: 1000 };
|
|
83
102
|
const anchorHdr = { kid: 1, epoch: 17, mseq: 1, firstSeq: 1000, flags: 0, sent: 1792972800 };
|
|
84
103
|
|
|
85
104
|
// A synthetic FEC Type 1 source block (ISO/IEC 23008-1 C.5.2), replacing the
|
|
@@ -114,7 +133,7 @@ function positive(id, source, note, { ep = anchorEp, ctx = anchorCtx, hdr = {},
|
|
|
114
133
|
|
|
115
134
|
const anchorDatagrams = [Buffer.alloc(1400, 0x11), Buffer.alloc(1400, 0x22)];
|
|
116
135
|
const cases = [
|
|
117
|
-
positive('appendix-a', 'appendix-a', 'draft-ramadan-moq-multicast-
|
|
136
|
+
positive('appendix-a', 'appendix-a', 'draft-ramadan-moq-multicast-02 Appendix A, byte for byte',
|
|
118
137
|
{ datagrams: anchorDatagrams }),
|
|
119
138
|
positive('twin', 'appendix-a', 'the twin of a record is byte-identical to it (7.2.5); equals appendix-a',
|
|
120
139
|
{ datagrams: anchorDatagrams }),
|
|
@@ -128,11 +147,21 @@ const cases = [
|
|
|
128
147
|
{ datagrams: anchorDatagrams, hdr: { mseq: 2, flags: 1 } }),
|
|
129
148
|
positive('ipv6', 'beyond-draft', 'IPv6 S and G, 44-octet pseudoheader and 50-octet signed_message prefix',
|
|
130
149
|
{ ep: { ...anchorEp, S: '2001:db8::7', G: 'ff3e::8000:1e' }, datagrams: anchorDatagrams }),
|
|
131
|
-
positive('params-no-fec', 'beyond-draft', 'catalog entry with no fec
|
|
132
|
-
{ ctx: { ...anchorCtx, params: { codec: 'avc1.640028', timescale: 90000, groupDurationTicks: 3000
|
|
150
|
+
positive('params-no-fec', 'beyond-draft', 'catalog entry with no fec member: lp16("none") then four u32(0)',
|
|
151
|
+
{ ctx: { ...anchorCtx, params: { codec: 'avc1.640028', timescale: 90000, groupDurationTicks: 3000 } },
|
|
133
152
|
datagrams: anchorDatagrams }),
|
|
134
|
-
positive('params-
|
|
135
|
-
{ ctx: { ...anchorCtx, params: {
|
|
153
|
+
positive('params-empty-fec-array', 'beyond-draft', 'empty fec array: hashes as the no-FEC encoding, params_hash equals params-no-fec',
|
|
154
|
+
{ ctx: { ...anchorCtx, params: { codec: 'avc1.640028', timescale: 90000, groupDurationTicks: 3000, fec: [] } },
|
|
155
|
+
datagrams: anchorDatagrams }),
|
|
156
|
+
positive('params-no-interleave', 'beyond-draft', 'fec instance without interleaveDepthMs: u32(0)',
|
|
157
|
+
{ ctx: { ...anchorCtx, params: { ...anchorCtx.params, fec: [{ ...anchorCtx.params.fec[0], interleaveDepthMs: undefined }] } },
|
|
158
|
+
datagrams: anchorDatagrams }),
|
|
159
|
+
positive('params-two-instances', 'beyond-draft', 'base and keyframe overlay instance (mmt-02 7.4.1): two tuples in ascending instanceId',
|
|
160
|
+
{ ctx: { ...anchorCtx, params: { ...anchorCtx.params, fec: [baseInstance, overlayInstance] } },
|
|
161
|
+
datagrams: anchorDatagrams }),
|
|
162
|
+
positive('params-two-instances-listed-reversed', 'beyond-draft',
|
|
163
|
+
'the same instances listed instanceId 1 first: hashed in ascending instanceId, so params_hash equals params-two-instances; array order would not',
|
|
164
|
+
{ ctx: { ...anchorCtx, params: { ...anchorCtx.params, fec: [overlayInstance, baseInstance] } },
|
|
136
165
|
datagrams: anchorDatagrams }),
|
|
137
166
|
positive('catalog-less', 'beyond-draft', 'flow carried without a MoQ catalog: ctx is 32 zero octets',
|
|
138
167
|
{ ctx: null, datagrams: anchorDatagrams }),
|
|
@@ -208,6 +237,9 @@ const negatives = [
|
|
|
208
237
|
negative('ctx-mismatch', 'ctx', { receiver: { catalogCtxHex: hex(Buffer.alloc(32, 0xff)) } }),
|
|
209
238
|
negative('budget-empty', 'budget', { receiver: { budgetTokens: 0 } }),
|
|
210
239
|
negative('signature', 'signature', { mutate: (r) => { const b = Buffer.from(r); b[b.length - 1] ^= 1; return b; } }),
|
|
240
|
+
// multicast-01 Appendix A @ abf183b: signed under the -01 prefix, which bound
|
|
241
|
+
// u16(manifestPort) = 5005; under the -02 prefix (u16(port)) it must fail.
|
|
242
|
+
negative('appendix-a-01-record', 'signature', { mutate: () => APPENDIX_A_01_RECORD }),
|
|
211
243
|
];
|
|
212
244
|
|
|
213
245
|
function boundary(id, receiver) {
|
|
@@ -236,11 +268,57 @@ boundaries.push(boundary('epoch-kid-range-top', {
|
|
|
236
268
|
keys: [...baseReceiver.keys, { kid: 2, publicKeyHex: hex(publicKey), firstEpoch: 17 }], minEpoch: 16,
|
|
237
269
|
}));
|
|
238
270
|
boundaries[3].recordHex = hex(record(anchorEp, { ...anchorHdr, ctx: c0, epoch: 16 }, anchorDigests));
|
|
271
|
+
// Highest mseq below the window: 0 + 64 > 10, so mseq 0 is above the floor.
|
|
272
|
+
// An unsigned highest - 64 wraps and would drop it (7.2.1, 7.2.7 step 1).
|
|
273
|
+
boundaries.push(boundary('mseq-floor-below-window', { highestMseq: { kid: 1, epoch: 17, mseq: 10 } }));
|
|
274
|
+
boundaries[4].recordHex = hex(record(anchorEp, { ...anchorHdr, ctx: c0, mseq: 0 }, anchorDigests));
|
|
275
|
+
|
|
276
|
+
// "none" is reserved (fec-core-00 15.2): an instance naming it is rejected,
|
|
277
|
+
// never hashed as the no-FEC encoding.
|
|
278
|
+
const paramsRejections = [
|
|
279
|
+
{ id: 'scheme-none', note: 'a fec instance whose scheme is "none" is rejected',
|
|
280
|
+
params: { ...anchorCtx.params, fec: [{ ...anchorCtx.params.fec[0], scheme: 'none' }] } },
|
|
281
|
+
];
|
|
282
|
+
for (const r of paramsRejections) {
|
|
283
|
+
let threw = false;
|
|
284
|
+
try { paramsHash(r.params); } catch { threw = true; }
|
|
285
|
+
if (!threw) throw new Error(`${r.id} hashed`);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// 7.2.4 repair-only endpoint: params_hash comes from the source track of the
|
|
289
|
+
// endpoint's lowest-packetId repair track, named by its `source` or, absent
|
|
290
|
+
// that, by any instance (not only layer 0's) naming it as `repairTrack`.
|
|
291
|
+
const catalogBase = (repair) => ({
|
|
292
|
+
version: 1,
|
|
293
|
+
streamingFormat: 'mmtp',
|
|
294
|
+
tracks: [
|
|
295
|
+
{ name: 'video', packaging: 'mmtp', codec: 'avc1.640028', mmtpMode: 'mfu', timescale: 90000, groupDurationTicks: 3000,
|
|
296
|
+
fec: [
|
|
297
|
+
{ instanceId: 1, scope: 'keyframe', scheme: 'raptorq', blockProfile: 'iso-ssbg1-v1', sourceSymbols: 256, repairSymbols: 32,
|
|
298
|
+
symbolSize: 1312, interleaveDepthMs: 1000, repairTrack: 'video/keyframe-repair' },
|
|
299
|
+
{ instanceId: 0, scheme: 'raptorq', blockProfile: 'iso-ssbg1-v1', sourceSymbols: 32, repairSymbols: 16,
|
|
300
|
+
symbolSize: 1312, interleaveDepthMs: 133, reorderToleranceMs: 40, repairTrack: 'video/repair' },
|
|
301
|
+
] },
|
|
302
|
+
{ name: 'video/repair', packaging: 'fec-repair', source: 'video', instanceId: 0, priority: 240 },
|
|
303
|
+
repair,
|
|
304
|
+
],
|
|
305
|
+
});
|
|
306
|
+
const resolvedVideo = { ...anchorCtx.params, fec: [baseInstance, overlayInstance] };
|
|
307
|
+
const catalogResolutions = [
|
|
308
|
+
{ id: 'repair-only-via-source', note: 'the repair track names its source track',
|
|
309
|
+
catalog: catalogBase({ name: 'video/keyframe-repair', packaging: 'fec-repair', source: 'video', instanceId: 1, priority: 242 }),
|
|
310
|
+
endpointTracks: [{ name: 'video/keyframe-repair', packetId: 9 }, { name: 'video/repair', packetId: 12 }],
|
|
311
|
+
resolvedParams: resolvedVideo },
|
|
312
|
+
{ id: 'repair-only-via-instance-repair-track', note: 'the repair track carries no source; the instance 1 (keyframe overlay) repairTrack names it',
|
|
313
|
+
catalog: catalogBase({ name: 'video/keyframe-repair', packaging: 'fec-repair', instanceId: 1, priority: 242 }),
|
|
314
|
+
endpointTracks: [{ name: 'video/keyframe-repair', packetId: 9 }],
|
|
315
|
+
resolvedParams: resolvedVideo },
|
|
316
|
+
].map((r) => ({ ...r, paramsHashHex: hex(paramsHash(r.resolvedParams)) }));
|
|
239
317
|
|
|
240
318
|
const out = {
|
|
241
319
|
version: 2,
|
|
242
320
|
profile: 'bc-provenance',
|
|
243
|
-
draft: 'draft-ramadan-moq-multicast-
|
|
321
|
+
draft: 'draft-ramadan-moq-multicast-02',
|
|
244
322
|
draftCommit: DRAFT_COMMIT,
|
|
245
323
|
hashAlg: 1,
|
|
246
324
|
key: { seedHex: hex(seed), publicKeyHex: hex(publicKey) },
|
|
@@ -248,5 +326,7 @@ const out = {
|
|
|
248
326
|
recovered: recoveredCase,
|
|
249
327
|
negatives,
|
|
250
328
|
boundaries,
|
|
329
|
+
paramsRejections,
|
|
330
|
+
catalogResolutions,
|
|
251
331
|
};
|
|
252
332
|
writeFileSync(join(here, 'bc-provenance-v2.json'), `${JSON.stringify(out, null, 2)}\n`);
|