@blockcast/mmt-container 2.2.0-main.75b39a2cdddf → 2.2.0-main.7e8a9d13c01c
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 +634 -129
- package/dist/browser-runtime.js.map +3 -3
- package/dist/delta-fallback-config.js.map +1 -1
- package/dist/fec-manager.d.ts +37 -11
- package/dist/fec-manager.d.ts.map +1 -1
- package/dist/fec-manager.js +181 -52
- package/dist/fec-manager.js.map +2 -2
- package/dist/fec-worker-setup.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +2 -2
- package/dist/iso-block-locator.d.ts +39 -13
- package/dist/iso-block-locator.d.ts.map +1 -1
- package/dist/iso-block-locator.js +80 -25
- package/dist/iso-block-locator.js.map +2 -2
- package/dist/media-router.js.map +1 -1
- package/dist/mmtp-container-parser.d.ts +21 -0
- package/dist/mmtp-container-parser.d.ts.map +1 -1
- package/dist/mmtp-container-parser.js +114 -11
- package/dist/mmtp-container-parser.js.map +2 -2
- package/dist/mmtp-container-parser.no-modules.js +113 -12
- package/dist/mmtp-container-parser.no-modules.js.map +2 -2
- package/dist/mmtp-decode-pipeline.js +114 -11
- package/dist/mmtp-decode-pipeline.js.map +2 -2
- package/dist/mmtp-router.d.ts +18 -9
- package/dist/mmtp-router.d.ts.map +1 -1
- package/dist/mmtp-router.js +254 -44
- package/dist/mmtp-router.js.map +2 -2
- package/dist/multicast-manager.d.ts +13 -3
- package/dist/multicast-manager.d.ts.map +1 -1
- package/dist/multicast-manager.js +455 -103
- package/dist/multicast-manager.js.map +2 -2
- package/dist/no-modules.js +114 -11
- package/dist/no-modules.js.map +2 -2
- package/dist/repair-fetch.d.ts +36 -8
- package/dist/repair-fetch.d.ts.map +1 -1
- package/dist/repair-fetch.js +285 -26
- package/dist/repair-fetch.js.map +3 -3
- package/dist/track-session.d.ts.map +1 -1
- package/dist/track-session.js +1 -0
- package/dist/track-session.js.map +2 -2
- package/dist/wasm-mmtp-container-parser.js +114 -11
- package/dist/wasm-mmtp-container-parser.js.map +2 -2
- package/package.json +5 -5
- package/src/fec-manager.ts +156 -26
- package/src/index.ts +2 -0
- package/src/iso-block-locator.ts +114 -31
- package/src/mmtp-container-parser.ts +181 -10
- package/src/mmtp-router.ts +231 -58
- package/src/multicast-manager.ts +44 -6
- package/src/repair-fetch.ts +363 -49
- package/src/track-session.ts +3 -0
package/dist/no-modules.js
CHANGED
|
@@ -5914,6 +5914,9 @@ function authoredGap(before, after) {
|
|
|
5914
5914
|
function ssIdAfter(a, b) {
|
|
5915
5915
|
return (a - b | 0) > 0;
|
|
5916
5916
|
}
|
|
5917
|
+
function holdsRebuilt(stream) {
|
|
5918
|
+
return stream.buf.some(({ meta }) => meta.fecSbnFirst !== void 0);
|
|
5919
|
+
}
|
|
5917
5920
|
var FecReleaseSequencer = class {
|
|
5918
5921
|
#streams = /* @__PURE__ */ new Map();
|
|
5919
5922
|
#gate;
|
|
@@ -5976,6 +5979,7 @@ var FecReleaseSequencer = class {
|
|
|
5976
5979
|
stream.lastSbn = void 0;
|
|
5977
5980
|
stream.discontinuity = false;
|
|
5978
5981
|
stream.rapSsId = void 0;
|
|
5982
|
+
stream.sourced = false;
|
|
5979
5983
|
}
|
|
5980
5984
|
if (stream.last !== null && compareFrameOrder(frame, stream.last) <= 0) {
|
|
5981
5985
|
this.#recordStat("droppedStale");
|
|
@@ -6002,6 +6006,7 @@ var FecReleaseSequencer = class {
|
|
|
6002
6006
|
if (compareFrameOrder(stream.buf[mid], frame) < 0) lo = mid + 1;
|
|
6003
6007
|
else hi = mid;
|
|
6004
6008
|
}
|
|
6009
|
+
if (stream.buf[lo]?.passed === true) frame.passed = true;
|
|
6005
6010
|
stream.buf.splice(lo, 0, frame);
|
|
6006
6011
|
this.#drainUnlessDeferred(stream);
|
|
6007
6012
|
}
|
|
@@ -6037,6 +6042,41 @@ var FecReleaseSequencer = class {
|
|
|
6037
6042
|
}
|
|
6038
6043
|
return false;
|
|
6039
6044
|
}
|
|
6045
|
+
/**
|
|
6046
|
+
* These streams' sink is being replaced by one that has seen no source
|
|
6047
|
+
* frame yet. First, from a stream that holds a frame the overlay rebuilt,
|
|
6048
|
+
* release to the sink being replaced the frames the unanchored path had
|
|
6049
|
+
* already released to it (#cursorPassed): there they waited in its queue,
|
|
6050
|
+
* which its replacement flushes. A stream that holds none is not drained:
|
|
6051
|
+
* it holds nothing the anchor kept back, and a drain would still force out
|
|
6052
|
+
* a frame held past the hold limit, which before the anchor waited for the
|
|
6053
|
+
* next push. Then treat the streams as unsourced until a source frame is
|
|
6054
|
+
* released.
|
|
6055
|
+
*/
|
|
6056
|
+
unsource(packetId, catalogTrackName) {
|
|
6057
|
+
for (const stream of this.#streams.values()) {
|
|
6058
|
+
if (stream.packetId === packetId && (catalogTrackName === void 0 || stream.catalogTrackName === catalogTrackName)) {
|
|
6059
|
+
if (stream.draining === 0 && holdsRebuilt(stream)) {
|
|
6060
|
+
if (this.#deferDepth > 0) this.#deferredStreams.add(stream);
|
|
6061
|
+
else this.#drain(stream, true);
|
|
6062
|
+
}
|
|
6063
|
+
stream.sourced = false;
|
|
6064
|
+
}
|
|
6065
|
+
}
|
|
6066
|
+
}
|
|
6067
|
+
/**
|
|
6068
|
+
* Whether a stream of `packetId` holds a frame the keyframe overlay rebuilt
|
|
6069
|
+
* (FrameMeta.fecSbnFirst). Without `catalogTrackName`, every stream of the
|
|
6070
|
+
* packetId.
|
|
6071
|
+
*/
|
|
6072
|
+
holdsRebuilt(packetId, catalogTrackName) {
|
|
6073
|
+
for (const stream of this.#streams.values()) {
|
|
6074
|
+
if (stream.packetId !== packetId) continue;
|
|
6075
|
+
if (catalogTrackName !== void 0 && stream.catalogTrackName !== catalogTrackName) continue;
|
|
6076
|
+
if (holdsRebuilt(stream)) return true;
|
|
6077
|
+
}
|
|
6078
|
+
return false;
|
|
6079
|
+
}
|
|
6040
6080
|
/** Re-evaluate held gaps after FEC state changed. */
|
|
6041
6081
|
poke(streamKey) {
|
|
6042
6082
|
if (streamKey !== void 0) {
|
|
@@ -6128,16 +6168,32 @@ var FecReleaseSequencer = class {
|
|
|
6128
6168
|
last: null,
|
|
6129
6169
|
lastSbn: void 0,
|
|
6130
6170
|
discontinuity: false,
|
|
6131
|
-
rapSsId: void 0
|
|
6171
|
+
rapSsId: void 0,
|
|
6172
|
+
sourced: false,
|
|
6173
|
+
draining: 0
|
|
6132
6174
|
};
|
|
6133
6175
|
this.#streams.set(streamKey, stream);
|
|
6134
6176
|
}
|
|
6135
6177
|
return stream;
|
|
6136
6178
|
}
|
|
6137
|
-
#
|
|
6179
|
+
/** `asUnanchored`: release overlay-rebuilt frames when unanchored did (#cursorPassed). */
|
|
6180
|
+
#drain(stream, asUnanchored = false) {
|
|
6181
|
+
stream.draining++;
|
|
6182
|
+
try {
|
|
6183
|
+
this.#drainLoop(stream, asUnanchored);
|
|
6184
|
+
} finally {
|
|
6185
|
+
stream.draining--;
|
|
6186
|
+
}
|
|
6187
|
+
}
|
|
6188
|
+
#drainLoop(stream, asUnanchored) {
|
|
6138
6189
|
while (stream.buf.length > 0 && stream.last !== null) {
|
|
6139
6190
|
const head = stream.buf[0];
|
|
6140
6191
|
const last = stream.last;
|
|
6192
|
+
if (compareFrameOrder(head, last) <= 0) {
|
|
6193
|
+
stream.buf.shift();
|
|
6194
|
+
this.#release(stream, head, void 0);
|
|
6195
|
+
continue;
|
|
6196
|
+
}
|
|
6141
6197
|
if (stream.discontinuity) {
|
|
6142
6198
|
stream.discontinuity = false;
|
|
6143
6199
|
stream.buf.shift();
|
|
@@ -6151,9 +6207,10 @@ var FecReleaseSequencer = class {
|
|
|
6151
6207
|
}
|
|
6152
6208
|
const headSbn = head.meta.fecSbn;
|
|
6153
6209
|
const from = stream.lastSbn ?? headSbn;
|
|
6154
|
-
const to = headSbn ?? stream.lastSbn;
|
|
6210
|
+
const to = head.meta.fecSbnFirst ?? headSbn ?? stream.lastSbn;
|
|
6155
6211
|
let lost = [];
|
|
6156
6212
|
const unanchored = from === void 0 && to === void 0;
|
|
6213
|
+
let unresolved = false;
|
|
6157
6214
|
if (from !== void 0 && to !== void 0) {
|
|
6158
6215
|
const resolved = this.#gate.resolvedLoss(
|
|
6159
6216
|
stream.packetId,
|
|
@@ -6162,7 +6219,8 @@ var FecReleaseSequencer = class {
|
|
|
6162
6219
|
Math.max(from, to),
|
|
6163
6220
|
from
|
|
6164
6221
|
);
|
|
6165
|
-
|
|
6222
|
+
unresolved = resolved === null;
|
|
6223
|
+
if (unresolved && !this.#cursorPassed(stream, asUnanchored)) {
|
|
6166
6224
|
const heldMs = performance.now() - head.arrivedAtMs;
|
|
6167
6225
|
if (heldMs <= this.#gate.holdLimitMs(stream.packetId, stream.catalogTrackName)) return;
|
|
6168
6226
|
this.#recordStat("forcedWindowFlushes");
|
|
@@ -6170,22 +6228,56 @@ var FecReleaseSequencer = class {
|
|
|
6170
6228
|
this.#release(stream, head, this.#gate.decide(last, head, [], true));
|
|
6171
6229
|
continue;
|
|
6172
6230
|
}
|
|
6173
|
-
lost = resolved;
|
|
6231
|
+
lost = resolved ?? [];
|
|
6174
6232
|
}
|
|
6175
6233
|
stream.buf.shift();
|
|
6176
6234
|
this.#release(
|
|
6177
6235
|
stream,
|
|
6178
6236
|
head,
|
|
6179
|
-
lost.length > 0 || unanchored || authoredGap(last.meta, head.meta) ? this.#gate.decide(last, head, lost, false) : void 0
|
|
6237
|
+
lost.length > 0 || unanchored || unresolved || authoredGap(last.meta, head.meta) ? this.#gate.decide(last, head, lost, false) : void 0
|
|
6180
6238
|
);
|
|
6181
6239
|
}
|
|
6182
6240
|
}
|
|
6241
|
+
/**
|
|
6242
|
+
* An overlay-rebuilt frame (fecSbnFirst) waits no longer than the BLO-53342
|
|
6243
|
+
* source cursor holds it unanchored, and neither does a later frame behind
|
|
6244
|
+
* it. Unanchored, a frame that waits on no block (fecSbnFirst set, or no
|
|
6245
|
+
* fecSbn) left the gate once every frame ahead of it had: mark it `passed`,
|
|
6246
|
+
* like each frame that arrived in front of it since (stale there). The head
|
|
6247
|
+
* then goes, decided as it would be unanchored, once a frame the base path
|
|
6248
|
+
* delivered (a source frame, or one base FEC recovered) is buffered after a
|
|
6249
|
+
* marked one: the base path has passed that one, so a frame still missing
|
|
6250
|
+
* before it can only come from a repair. It also goes while no source frame
|
|
6251
|
+
* has been released, when the direct path shows a recovered frame at once.
|
|
6252
|
+
* And it goes at once while a staged switch decides on when frames arrive
|
|
6253
|
+
* (FecReleaseGate.releaseUnanchored), and when unsource releases into a
|
|
6254
|
+
* sink being replaced: unanchored, it had already reached the sink.
|
|
6255
|
+
* The scan also writes: the `passed` marks it sets stay on the frames,
|
|
6256
|
+
* and push marks a frame it inserts in front of a marked one from them.
|
|
6257
|
+
*/
|
|
6258
|
+
#cursorPassed(stream, asUnanchored) {
|
|
6259
|
+
let at = -1;
|
|
6260
|
+
for (let i = 0; i < stream.buf.length; i++) {
|
|
6261
|
+
const frame = stream.buf[i];
|
|
6262
|
+
if (frame.meta.fecSbnFirst !== void 0 || frame.meta.fecSbn === void 0) {
|
|
6263
|
+
frame.passed = true;
|
|
6264
|
+
if (at < 0) at = i;
|
|
6265
|
+
} else if (frame.passed !== true) break;
|
|
6266
|
+
}
|
|
6267
|
+
if (at < 0) return false;
|
|
6268
|
+
return asUnanchored || !stream.sourced || this.#gate.releaseUnanchored?.(stream.packetId, stream.catalogTrackName) === true || stream.buf.some(({ meta }, i) => i > at && meta.fecSbnFirst === void 0 && (meta.recovered !== true || meta.fecSbn !== void 0));
|
|
6269
|
+
}
|
|
6183
6270
|
#release(stream, frame, decision) {
|
|
6271
|
+
const stale = stream.last !== null && compareFrameOrder(frame, stream.last) <= 0;
|
|
6272
|
+
if (stale) this.#recordStat("droppedStale");
|
|
6184
6273
|
if (decision) frame.meta.gapBefore = decision;
|
|
6185
6274
|
stream.last = frame;
|
|
6186
|
-
if (frame.meta.fecSbn !== void 0
|
|
6275
|
+
if (frame.meta.fecSbn !== void 0 && (frame.meta.fecSbnFirst === void 0 || stream.lastSbn !== void 0)) {
|
|
6276
|
+
stream.lastSbn = frame.meta.fecSbn;
|
|
6277
|
+
}
|
|
6278
|
+
if (frame.meta.recovered !== true) stream.sourced = true;
|
|
6187
6279
|
this.#gate.onReleased?.(frame.data, frame.meta);
|
|
6188
|
-
this.#emit(frame.data, frame.meta);
|
|
6280
|
+
if (!stale) this.#emit(frame.data, frame.meta);
|
|
6189
6281
|
}
|
|
6190
6282
|
};
|
|
6191
6283
|
var FMPU_BOX_TYPES = /* @__PURE__ */ new Set(["ftyp", "moov", "moof"]);
|
|
@@ -6511,6 +6603,14 @@ var MmtpContainerParser = class _MmtpContainerParser {
|
|
|
6511
6603
|
fecReleaseRapAbove(packetId, catalogTrackName, ssId) {
|
|
6512
6604
|
return this.#fecSequencer?.rapAbove(packetId, catalogTrackName, ssId) ?? false;
|
|
6513
6605
|
}
|
|
6606
|
+
/** See FecReleaseSequencer.unsource. */
|
|
6607
|
+
unsourceFecRelease(packetId, catalogTrackName) {
|
|
6608
|
+
this.#fecSequencer?.unsource(packetId, catalogTrackName);
|
|
6609
|
+
}
|
|
6610
|
+
/** See FecReleaseSequencer.holdsRebuilt. */
|
|
6611
|
+
fecReleaseHoldsRebuilt(packetId, catalogTrackName) {
|
|
6612
|
+
return this.#fecSequencer?.holdsRebuilt(packetId, catalogTrackName) ?? false;
|
|
6613
|
+
}
|
|
6514
6614
|
/** Re-evaluate held gaps after FEC block state changed. */
|
|
6515
6615
|
pokeFecRelease(packetId, catalogTrackName) {
|
|
6516
6616
|
if (!this.#fecSequencer) return;
|
|
@@ -6837,7 +6937,8 @@ var MmtpContainerParser = class _MmtpContainerParser {
|
|
|
6837
6937
|
info,
|
|
6838
6938
|
resolver,
|
|
6839
6939
|
options?.recovered === true,
|
|
6840
|
-
options?.fecSbn
|
|
6940
|
+
options?.fecSbn,
|
|
6941
|
+
options?.fecSbnFirst
|
|
6841
6942
|
);
|
|
6842
6943
|
if (deferred.record === void 0) this.#countDeferredOutcome(deferred.reason);
|
|
6843
6944
|
}
|
|
@@ -6930,7 +7031,8 @@ var MmtpContainerParser = class _MmtpContainerParser {
|
|
|
6930
7031
|
info,
|
|
6931
7032
|
resolver,
|
|
6932
7033
|
options?.recovered === true,
|
|
6933
|
-
options?.fecSbn
|
|
7034
|
+
options?.fecSbn,
|
|
7035
|
+
options?.fecSbnFirst
|
|
6934
7036
|
);
|
|
6935
7037
|
if (outcome.record !== void 0) return outcome.record;
|
|
6936
7038
|
return this.#drop(outcome.reason);
|
|
@@ -6950,7 +7052,7 @@ var MmtpContainerParser = class _MmtpContainerParser {
|
|
|
6950
7052
|
* attribution exists to keep readable. Leaving the choice at the call site
|
|
6951
7053
|
* is what keeps both true.
|
|
6952
7054
|
*/
|
|
6953
|
-
#emitCombinedSample(combined, info, resolver, recovered, fecSbn) {
|
|
7055
|
+
#emitCombinedSample(combined, info, resolver, recovered, fecSbn, fecSbnFirst) {
|
|
6954
7056
|
const timing = resolver.sampleTiming(
|
|
6955
7057
|
combined.mpuSequenceNumber,
|
|
6956
7058
|
combined.movieFragmentSequenceNumber,
|
|
@@ -6967,6 +7069,7 @@ var MmtpContainerParser = class _MmtpContainerParser {
|
|
|
6967
7069
|
);
|
|
6968
7070
|
if (!meta) return { reason: "combined-meta-build-failed" };
|
|
6969
7071
|
if (fecSbn !== void 0) meta.fecSbn = fecSbn;
|
|
7072
|
+
if (fecSbnFirst !== void 0) meta.fecSbnFirst = fecSbnFirst;
|
|
6970
7073
|
if (!resolver.consumeSample(
|
|
6971
7074
|
combined.mpuSequenceNumber,
|
|
6972
7075
|
combined.movieFragmentSequenceNumber,
|