@blockcast/mmt-container 2.1.0 → 2.2.0-main.51d1358fdf4c
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/dist/browser-runtime.js +446 -58
- package/dist/browser-runtime.js.map +4 -4
- package/dist/cmcd-producer.d.ts +5 -0
- package/dist/cmcd-producer.d.ts.map +1 -1
- package/dist/cmcd-producer.js.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +2 -2
- package/dist/mmtp-container-parser.no-modules.js +121 -15
- package/dist/mmtp-container-parser.no-modules.js.map +3 -3
- package/dist/mmtp-fec-session.d.ts +41 -3
- package/dist/mmtp-fec-session.d.ts.map +1 -1
- package/dist/mmtp-fec-session.js +118 -13
- package/dist/mmtp-fec-session.js.map +3 -3
- package/dist/mmtp-router.d.ts +9 -1
- package/dist/mmtp-router.d.ts.map +1 -1
- package/dist/mmtp-router.js +1456 -14
- package/dist/mmtp-router.js.map +4 -4
- package/dist/multicast-manager.d.ts +15 -2
- package/dist/multicast-manager.d.ts.map +1 -1
- package/dist/multicast-manager.js +15235 -14951
- package/dist/multicast-manager.js.map +4 -4
- package/dist/multicast-transport.d.ts +11 -3
- package/dist/multicast-transport.d.ts.map +1 -1
- package/dist/multicast-transport.js +255 -19
- package/dist/multicast-transport.js.map +4 -4
- package/dist/no-modules.js +118 -14
- package/dist/no-modules.js.map +3 -3
- package/dist/signaling.js.map +2 -2
- package/package.json +5 -5
- package/src/cmcd-producer.ts +5 -0
- package/src/index.ts +2 -0
- package/src/mmtp-fec-session.ts +115 -15
- package/src/mmtp-router.ts +81 -16
- package/src/multicast-manager.ts +26 -5
- package/src/multicast-transport.ts +44 -20
package/dist/no-modules.js
CHANGED
|
@@ -10,6 +10,8 @@ var PACKET_TYPE_MPU = 0;
|
|
|
10
10
|
var PACKET_TYPE_REPAIR = 3;
|
|
11
11
|
var MMTP_SIGNALING_PACKET_ID = 0;
|
|
12
12
|
var MMTP_PACKET_ID_MAX = 65535;
|
|
13
|
+
var FEC_CODE_REED_SOLOMON = 1;
|
|
14
|
+
var FEC_CODE_RAPTORQ = 3;
|
|
13
15
|
function parseMMTPHeader(buffer) {
|
|
14
16
|
if (buffer.length < MMTP_HEADER_SIZE) {
|
|
15
17
|
throw new Error(`MMTP packet too small: ${buffer.length} bytes`);
|
|
@@ -360,6 +362,50 @@ var NTP_SHORT_BITS = 32;
|
|
|
360
362
|
var NTP_SHORT_MODULUS = 2 ** NTP_SHORT_BITS;
|
|
361
363
|
var NTP_SHORT_HALF_RANGE = 2 ** (NTP_SHORT_BITS - 1);
|
|
362
364
|
|
|
365
|
+
// ../mmt-base/dist/signalling.js
|
|
366
|
+
var FEC_CODING_STRUCTURE_ONE_STAGE = 1;
|
|
367
|
+
var SSBG_MODE_1 = 1;
|
|
368
|
+
var RAPTORQ_MAX_SOURCE_SYMBOLS = 56403;
|
|
369
|
+
var REPAIR_SYMBOL_ID_MAX = 16777215;
|
|
370
|
+
var MIN_REPAIR_SYMBOL_SIZE = 14;
|
|
371
|
+
var REED_SOLOMON_MAX_BLOCK = 255;
|
|
372
|
+
function alFecRaptorQFlowConfig(flow) {
|
|
373
|
+
if (flow.fecCodingStructure !== FEC_CODING_STRUCTURE_ONE_STAGE || flow.repairFlows.length !== 1)
|
|
374
|
+
return null;
|
|
375
|
+
if (flow.ssbgMode !== SSBG_MODE_1 || flow.ffsrptsFlag !== 0 || flow.fecPayloadIdMode !== 0)
|
|
376
|
+
return null;
|
|
377
|
+
if (flow.packetIds.length !== 1)
|
|
378
|
+
return null;
|
|
379
|
+
const repair = flow.repairFlows[0];
|
|
380
|
+
const { fecCodeId, maximumK: k, maximumP: p } = repair;
|
|
381
|
+
const t = flow.repairSymbolSize;
|
|
382
|
+
if (t < MIN_REPAIR_SYMBOL_SIZE || k < 1 || p < 1 || k + p - 1 > REPAIR_SYMBOL_ID_MAX)
|
|
383
|
+
return null;
|
|
384
|
+
if (fecCodeId === FEC_CODE_RAPTORQ) {
|
|
385
|
+
if (t % 8 !== 0 || k > RAPTORQ_MAX_SOURCE_SYMBOLS)
|
|
386
|
+
return null;
|
|
387
|
+
} else if (fecCodeId === FEC_CODE_REED_SOLOMON) {
|
|
388
|
+
if (k + p > REED_SOLOMON_MAX_BLOCK)
|
|
389
|
+
return null;
|
|
390
|
+
} else {
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
if (repair.repairFlowId === MMTP_SIGNALING_PACKET_ID || repair.repairFlowId === flow.packetIds[0])
|
|
394
|
+
return null;
|
|
395
|
+
return {
|
|
396
|
+
sourcePacketIds: [...flow.packetIds],
|
|
397
|
+
repairFlowId: repair.repairFlowId,
|
|
398
|
+
fecCodeId,
|
|
399
|
+
ssbgMode: flow.ssbgMode,
|
|
400
|
+
fecPayloadIdMode: flow.fecPayloadIdMode,
|
|
401
|
+
repairSymbolSize: t,
|
|
402
|
+
maximumK: k,
|
|
403
|
+
maximumP: p,
|
|
404
|
+
protectionWindowTime: repair.protectionWindowTime,
|
|
405
|
+
protectionWindowSize: repair.protectionWindowSize
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
363
409
|
// ../mmt-base/dist/serial-number.js
|
|
364
410
|
var SERIAL32_SPAN = 4294967296;
|
|
365
411
|
var SERIAL32_HALF = 2147483648;
|
|
@@ -8071,7 +8117,14 @@ var HeldLayerAdmission = class {
|
|
|
8071
8117
|
var PATH_BITS = { moq: 1, multicast: 2 };
|
|
8072
8118
|
var MIXED_PATHS = PATH_BITS.moq | PATH_BITS.multicast;
|
|
8073
8119
|
var MmtpFecSession = class {
|
|
8120
|
+
/** P_0 = B_0, the held total every repair packet is checked against. */
|
|
8121
|
+
get repairSymbols() {
|
|
8122
|
+
return this.#repairSymbols;
|
|
8123
|
+
}
|
|
8074
8124
|
#decoder;
|
|
8125
|
+
#repairSymbols;
|
|
8126
|
+
/** The message entry a catalog-less session was built from; undefined under a catalog. */
|
|
8127
|
+
#message;
|
|
8075
8128
|
/** Blocks a repair has defined and that are not settled yet, by SS_Start. */
|
|
8076
8129
|
#blocks = /* @__PURE__ */ new Map();
|
|
8077
8130
|
/** SS_Starts of settled blocks, so a later repair for one is refused. */
|
|
@@ -8109,6 +8162,24 @@ var MmtpFecSession = class {
|
|
|
8109
8162
|
* `interleaveDepthMs` or `reorderToleranceMs`. None is defaulted.
|
|
8110
8163
|
*/
|
|
8111
8164
|
constructor(config) {
|
|
8165
|
+
if (config && "alFecFlow" in config) {
|
|
8166
|
+
const message = alFecRaptorQFlowConfig(config.alFecFlow);
|
|
8167
|
+
if (!message) {
|
|
8168
|
+
throw new Error("MmtpFecSession: the AL-FEC entry is outside draft-ramadan-moq-mmt-02 8.3 (iso-ssbg1-v1)");
|
|
8169
|
+
}
|
|
8170
|
+
this.#message = message;
|
|
8171
|
+
this.blockProfile = parseFecBlockProfile("iso-ssbg1-v1", "alFecFlow");
|
|
8172
|
+
this.algorithm = message.fecCodeId === FEC_CODE_RAPTORQ ? "raptorq" : "reed-solomon";
|
|
8173
|
+
this.sourceSymbols = message.maximumK;
|
|
8174
|
+
this.#repairSymbols = message.maximumP;
|
|
8175
|
+
this.symbolSize = message.repairSymbolSize;
|
|
8176
|
+
this.retentionBlocks = requirePositiveInteger(config.retentionBlocks, "retentionBlocks");
|
|
8177
|
+
this.#repairPacketId = message.repairFlowId;
|
|
8178
|
+
this.#heldLayers = layerZero(message.maximumP);
|
|
8179
|
+
this.#anchorHorizon = heldLayerAnchorHorizon(this.retentionBlocks, this.sourceSymbols);
|
|
8180
|
+
this.#decoder = buildDecoder(config.Decoder, this);
|
|
8181
|
+
return;
|
|
8182
|
+
}
|
|
8112
8183
|
const fec = config?.fec;
|
|
8113
8184
|
if (!fec || typeof fec !== "object") {
|
|
8114
8185
|
throw new Error("MmtpFecSession: the catalog fec instance is required");
|
|
@@ -8119,7 +8190,7 @@ var MmtpFecSession = class {
|
|
|
8119
8190
|
}
|
|
8120
8191
|
this.algorithm = fec.scheme;
|
|
8121
8192
|
this.sourceSymbols = requirePositiveInteger(fec.sourceSymbols, "fec.sourceSymbols");
|
|
8122
|
-
this
|
|
8193
|
+
this.#repairSymbols = requirePositiveInteger(fec.repairSymbols, "fec.repairSymbols");
|
|
8123
8194
|
this.symbolSize = requirePositiveInteger(fec.symbolSize, "fec.symbolSize");
|
|
8124
8195
|
const interleaveDepthMs = requireNumber(fec.interleaveDepthMs, "fec.interleaveDepthMs");
|
|
8125
8196
|
const reorderToleranceMs = requireNumber(fec.reorderToleranceMs, "fec.reorderToleranceMs");
|
|
@@ -8139,17 +8210,30 @@ var MmtpFecSession = class {
|
|
|
8139
8210
|
config.heldLayers
|
|
8140
8211
|
);
|
|
8141
8212
|
this.#anchorHorizon = heldLayerAnchorHorizon(this.retentionBlocks, this.sourceSymbols);
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
-
|
|
8149
|
-
|
|
8150
|
-
|
|
8151
|
-
|
|
8152
|
-
|
|
8213
|
+
this.#decoder = buildDecoder(config.Decoder, this);
|
|
8214
|
+
}
|
|
8215
|
+
/**
|
|
8216
|
+
* A later version of the AL-FEC message, catalog-less sessions only. A
|
|
8217
|
+
* maximum_p_for_repair_flow above the held total raises it (`raised`): the
|
|
8218
|
+
* anchored check restarts at the new total, so a block generated under the
|
|
8219
|
+
* previous one stays valid before the first block carrying the new total
|
|
8220
|
+
* (fec-core-00 7.3.2, mmt-02 8.3). A field at or below it changes nothing
|
|
8221
|
+
* (`unchanged`): no publisher lowers it, and the check catches a wire that
|
|
8222
|
+
* does. An entry with another asset, repair flow, code point, K or T, or
|
|
8223
|
+
* one outside 8.3, is `refused`: that is a new source encoding, which needs
|
|
8224
|
+
* a new session. A latched fail-closed stays latched either way.
|
|
8225
|
+
*/
|
|
8226
|
+
updateAlFecFlow(flow) {
|
|
8227
|
+
const held = this.#message;
|
|
8228
|
+
if (!held) throw new Error("MmtpFecSession: updateAlFecFlow() needs a session built from an AL-FEC entry");
|
|
8229
|
+
const next = alFecRaptorQFlowConfig(flow);
|
|
8230
|
+
if (!next || next.sourcePacketIds[0] !== held.sourcePacketIds[0] || next.repairFlowId !== held.repairFlowId || next.fecCodeId !== held.fecCodeId || next.maximumK !== held.maximumK || next.repairSymbolSize !== held.repairSymbolSize) {
|
|
8231
|
+
return "refused";
|
|
8232
|
+
}
|
|
8233
|
+
if (next.maximumP <= this.#repairSymbols) return "unchanged";
|
|
8234
|
+
this.#repairSymbols = next.maximumP;
|
|
8235
|
+
this.#heldLayers = layerZero(next.maximumP);
|
|
8236
|
+
return "raised";
|
|
8153
8237
|
}
|
|
8154
8238
|
/** True once release() ran. */
|
|
8155
8239
|
get released() {
|
|
@@ -8244,7 +8328,7 @@ var MmtpFecSession = class {
|
|
|
8244
8328
|
}
|
|
8245
8329
|
if (admission.reject) {
|
|
8246
8330
|
const verdict2 = this.#heldLayers.failsClosed(
|
|
8247
|
-
repairTrackName,
|
|
8331
|
+
this.#trackFor(repairTrackName),
|
|
8248
8332
|
frame.ssStart,
|
|
8249
8333
|
frame.rsbLength,
|
|
8250
8334
|
this.#anchorHorizon,
|
|
@@ -8259,7 +8343,7 @@ var MmtpFecSession = class {
|
|
|
8259
8343
|
this.#repairPacketId ??= frame.packetId;
|
|
8260
8344
|
if (frame.ssbLength > this.sourceSymbols) return this.#drop("repair:ssb-length");
|
|
8261
8345
|
const verdict = this.#heldLayers.admit(
|
|
8262
|
-
repairTrackName,
|
|
8346
|
+
this.#trackFor(repairTrackName),
|
|
8263
8347
|
frame.ssStart,
|
|
8264
8348
|
frame.rsbLength,
|
|
8265
8349
|
this.#anchorHorizon,
|
|
@@ -8318,6 +8402,10 @@ var MmtpFecSession = class {
|
|
|
8318
8402
|
decoder.free();
|
|
8319
8403
|
return true;
|
|
8320
8404
|
}
|
|
8405
|
+
/** Catalog-less: layer 0 has no own-track clause (mmt-02 8.3), so no track name is judged. */
|
|
8406
|
+
#trackFor(repairTrackName) {
|
|
8407
|
+
return this.#message ? void 0 : repairTrackName;
|
|
8408
|
+
}
|
|
8321
8409
|
#drop(reason) {
|
|
8322
8410
|
this.#stats.dropped[reason] = (this.#stats.dropped[reason] ?? 0) + 1;
|
|
8323
8411
|
return [];
|
|
@@ -8439,6 +8527,22 @@ var MmtpFecSession = class {
|
|
|
8439
8527
|
}
|
|
8440
8528
|
}
|
|
8441
8529
|
};
|
|
8530
|
+
function layerZero(total) {
|
|
8531
|
+
return new HeldLayerAdmission([{ layer: 0, repairTrackName: "", rsIdOffset: 0, repairSymbols: total }]);
|
|
8532
|
+
}
|
|
8533
|
+
function buildDecoder(Decoder, session) {
|
|
8534
|
+
if (typeof Decoder !== "function") {
|
|
8535
|
+
throw new Error("MmtpFecSession: a decoder constructor (wasm_bindgen.MmtFecDecoder) is required");
|
|
8536
|
+
}
|
|
8537
|
+
const decoder = new Decoder(session.retentionBlocks, session.blockProfile, session.algorithm);
|
|
8538
|
+
try {
|
|
8539
|
+
decoder.configure_params(session.sourceSymbols, session.symbolSize);
|
|
8540
|
+
} catch (error) {
|
|
8541
|
+
decoder.free();
|
|
8542
|
+
throw error;
|
|
8543
|
+
}
|
|
8544
|
+
return decoder;
|
|
8545
|
+
}
|
|
8442
8546
|
function requirePositiveInteger(value, path) {
|
|
8443
8547
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0) {
|
|
8444
8548
|
throw new Error(`MmtpFecSession: ${path} must be a positive integer (got ${String(value)})`);
|