@blockcast/mmt-container 2.2.0-main.0f6aad7bb803 → 2.2.0-main.10bec7edb00b
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 +189 -6
- package/dist/browser-runtime.js.map +4 -4
- package/dist/catalog-fec-params.d.ts +16 -0
- package/dist/catalog-fec-params.d.ts.map +1 -1
- package/dist/catalog-fec-params.js +15 -0
- package/dist/catalog-fec-params.js.map +2 -2
- package/dist/delivery-catalog.js +11 -6
- package/dist/delivery-catalog.js.map +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +2 -2
- package/dist/mmtp-router.js +11 -6
- package/dist/mmtp-router.js.map +2 -2
- package/dist/multicast-manager.js +11 -6
- package/dist/multicast-manager.js.map +2 -2
- package/dist/multicast-transport.js +11 -6
- package/dist/multicast-transport.js.map +2 -2
- package/dist/repair-layer-subscriptions.d.ts +82 -0
- package/dist/repair-layer-subscriptions.d.ts.map +1 -0
- package/dist/repair-layer-subscriptions.js +192 -0
- package/dist/repair-layer-subscriptions.js.map +7 -0
- package/package.json +5 -5
- package/schemas/catalog.schema.json +4 -0
- package/src/catalog-fec-params.ts +35 -0
- package/src/index.ts +10 -0
- package/src/repair-layer-subscriptions.ts +261 -0
package/dist/browser-runtime.js
CHANGED
|
@@ -8749,6 +8749,7 @@ var MOQT_PUBLISHER_PRIORITY = Object.freeze({
|
|
|
8749
8749
|
var AMTGatewayManager = class {
|
|
8750
8750
|
subscriptions = /* @__PURE__ */ new Map();
|
|
8751
8751
|
messageHandler;
|
|
8752
|
+
messageListenerRegistered = false;
|
|
8752
8753
|
pendingPackets = /* @__PURE__ */ new Map();
|
|
8753
8754
|
constructor() {
|
|
8754
8755
|
this.messageHandler = (event) => {
|
|
@@ -8762,12 +8763,14 @@ var AMTGatewayManager = class {
|
|
|
8762
8763
|
console.log(`[AMT SW Debug] ${data.message}`);
|
|
8763
8764
|
}
|
|
8764
8765
|
};
|
|
8765
|
-
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
|
|
8769
|
-
console.warn("[AMT] Service worker not available");
|
|
8766
|
+
}
|
|
8767
|
+
ensureMessageListener() {
|
|
8768
|
+
if (this.messageListenerRegistered || typeof navigator === "undefined" || !navigator.serviceWorker || !this.messageHandler) {
|
|
8769
|
+
return;
|
|
8770
8770
|
}
|
|
8771
|
+
navigator.serviceWorker.addEventListener("message", this.messageHandler);
|
|
8772
|
+
this.messageListenerRegistered = true;
|
|
8773
|
+
console.log("[AMT] Registered service worker message handler");
|
|
8771
8774
|
}
|
|
8772
8775
|
/**
|
|
8773
8776
|
* Subscribe via AMT tunnel
|
|
@@ -8777,6 +8780,7 @@ var AMTGatewayManager = class {
|
|
|
8777
8780
|
if (config.protected) {
|
|
8778
8781
|
throw new Error("AMTGatewayManager refuses a protected join: it reports no per-datagram sender (multicast-02 7.2.7)");
|
|
8779
8782
|
}
|
|
8783
|
+
this.ensureMessageListener();
|
|
8780
8784
|
const keyStr = this.getKeyString(key);
|
|
8781
8785
|
if (this.subscriptions.has(keyStr)) {
|
|
8782
8786
|
console.log(`[AMT] Reusing existing subscription to ${keyStr}`);
|
|
@@ -8892,8 +8896,9 @@ var AMTGatewayManager = class {
|
|
|
8892
8896
|
* Cleanup on destroy
|
|
8893
8897
|
*/
|
|
8894
8898
|
destroy() {
|
|
8895
|
-
if (this.messageHandler && typeof navigator !== "undefined" && navigator.serviceWorker) {
|
|
8899
|
+
if (this.messageListenerRegistered && this.messageHandler && typeof navigator !== "undefined" && navigator.serviceWorker) {
|
|
8896
8900
|
navigator.serviceWorker.removeEventListener("message", this.messageHandler);
|
|
8901
|
+
this.messageListenerRegistered = false;
|
|
8897
8902
|
}
|
|
8898
8903
|
const handles = Array.from(this.subscriptions.keys());
|
|
8899
8904
|
for (const handle of handles) {
|
|
@@ -31487,6 +31492,19 @@ function resolveRepairLayers(catalog, source) {
|
|
|
31487
31492
|
totalBaseRepairSymbols: binding.totalBaseRepairSymbols
|
|
31488
31493
|
};
|
|
31489
31494
|
}
|
|
31495
|
+
function valueAt(catalog, pointer) {
|
|
31496
|
+
let node = catalog;
|
|
31497
|
+
for (const segment of pointer.split("/").slice(1)) {
|
|
31498
|
+
if (typeof node !== "object" || node === null) return void 0;
|
|
31499
|
+
node = node[segment.replace(/~1/g, "/").replace(/~0/g, "~")];
|
|
31500
|
+
}
|
|
31501
|
+
return node;
|
|
31502
|
+
}
|
|
31503
|
+
function catalogTrackDeliveryMode(catalog, source) {
|
|
31504
|
+
const binding = bindingOf(catalog, source);
|
|
31505
|
+
const entry = binding ? valueAt(catalog, binding.pointer) : void 0;
|
|
31506
|
+
return entry?.deliveryMode === "stream" ? "stream" : "datagram";
|
|
31507
|
+
}
|
|
31490
31508
|
function moqtPriority2(value) {
|
|
31491
31509
|
return Number.isSafeInteger(value) && value >= 0 && value <= 255 ? value : null;
|
|
31492
31510
|
}
|
|
@@ -31530,6 +31548,7 @@ function fecParams(catalog, track, fps, sampleRate) {
|
|
|
31530
31548
|
repairTrackName: base.repairTrack,
|
|
31531
31549
|
repairLayers: repair.baseLayers,
|
|
31532
31550
|
repairOverlays: repair.overlays,
|
|
31551
|
+
deliveryMode: catalogTrackDeliveryMode(catalog, track),
|
|
31533
31552
|
...mediaRate
|
|
31534
31553
|
};
|
|
31535
31554
|
}
|
|
@@ -32019,6 +32038,168 @@ function requireNumber(value, path) {
|
|
|
32019
32038
|
return value;
|
|
32020
32039
|
}
|
|
32021
32040
|
|
|
32041
|
+
// src/repair-layer-subscriptions.ts
|
|
32042
|
+
var SERIAL32_HALF2 = 2147483648;
|
|
32043
|
+
var RepairLayerSubscriptions = class {
|
|
32044
|
+
#opts;
|
|
32045
|
+
#windowPackets;
|
|
32046
|
+
#margin;
|
|
32047
|
+
#dropAfterWindows;
|
|
32048
|
+
#source;
|
|
32049
|
+
#layerCount = 0;
|
|
32050
|
+
#subs = /* @__PURE__ */ new Map();
|
|
32051
|
+
#disposed = false;
|
|
32052
|
+
#lastSeq;
|
|
32053
|
+
#expected = 0;
|
|
32054
|
+
#lost = 0;
|
|
32055
|
+
#wantFewer = 0;
|
|
32056
|
+
#lossRate = null;
|
|
32057
|
+
#repairPackets = 0;
|
|
32058
|
+
#repairBytes = 0;
|
|
32059
|
+
#staleDropped = 0;
|
|
32060
|
+
constructor(opts) {
|
|
32061
|
+
this.#opts = opts;
|
|
32062
|
+
this.#source = opts.source;
|
|
32063
|
+
this.#windowPackets = opts.windowPackets ?? 500;
|
|
32064
|
+
this.#margin = opts.margin ?? 2;
|
|
32065
|
+
this.#dropAfterWindows = opts.dropAfterWindows ?? 3;
|
|
32066
|
+
}
|
|
32067
|
+
get layerCount() {
|
|
32068
|
+
return this.#layerCount;
|
|
32069
|
+
}
|
|
32070
|
+
/**
|
|
32071
|
+
* One source packet's MMTP `packet_sequence_number`, in arrival order.
|
|
32072
|
+
* The sequence is per `packet_id`: pass the packets of ONE packet_id only,
|
|
32073
|
+
* or interleaved sequences read as loss.
|
|
32074
|
+
*/
|
|
32075
|
+
noteSourceSequence(seq) {
|
|
32076
|
+
if (this.#disposed || this.#delivery() === "stream") return;
|
|
32077
|
+
seq >>>= 0;
|
|
32078
|
+
if (this.#lastSeq === void 0) {
|
|
32079
|
+
this.#lastSeq = seq;
|
|
32080
|
+
return;
|
|
32081
|
+
}
|
|
32082
|
+
const d = serial32Distance(this.#lastSeq, seq);
|
|
32083
|
+
if (d === 0) return;
|
|
32084
|
+
const back = d >= SERIAL32_HALF2 ? 2 ** 32 - d : 0;
|
|
32085
|
+
if (d > this.#windowPackets && (back === 0 || back > this.#windowPackets)) {
|
|
32086
|
+
this.#lastSeq = seq;
|
|
32087
|
+
this.#expected = 0;
|
|
32088
|
+
this.#lost = 0;
|
|
32089
|
+
return;
|
|
32090
|
+
}
|
|
32091
|
+
if (back === 0) {
|
|
32092
|
+
this.#expected += d;
|
|
32093
|
+
this.#lost += d - 1;
|
|
32094
|
+
this.#lastSeq = seq;
|
|
32095
|
+
} else if (this.#lost > 0) {
|
|
32096
|
+
this.#lost -= 1;
|
|
32097
|
+
}
|
|
32098
|
+
if (this.#expected >= this.#windowPackets) this.#closeWindow();
|
|
32099
|
+
}
|
|
32100
|
+
/** ABR switch R -> R': close R's tracks, carry the layer count to R'. */
|
|
32101
|
+
switchSource(next) {
|
|
32102
|
+
if (this.#disposed) return;
|
|
32103
|
+
this.#closeAll();
|
|
32104
|
+
this.#source = next;
|
|
32105
|
+
this.#lastSeq = void 0;
|
|
32106
|
+
this.#expected = 0;
|
|
32107
|
+
this.#lost = 0;
|
|
32108
|
+
this.#wantFewer = 0;
|
|
32109
|
+
this.#layerCount = this.#delivery() === "stream" ? 0 : Math.min(this.#layerCount, this.#layers().length);
|
|
32110
|
+
this.#reconcile();
|
|
32111
|
+
}
|
|
32112
|
+
snapshot() {
|
|
32113
|
+
return {
|
|
32114
|
+
delivery: this.#delivery(),
|
|
32115
|
+
layerCount: this.#layerCount,
|
|
32116
|
+
subscribedTracks: [...this.#subs.keys()],
|
|
32117
|
+
repairPackets: this.#repairPackets,
|
|
32118
|
+
repairBytes: this.#repairBytes,
|
|
32119
|
+
staleDropped: this.#staleDropped,
|
|
32120
|
+
lossRate: this.#lossRate
|
|
32121
|
+
};
|
|
32122
|
+
}
|
|
32123
|
+
dispose() {
|
|
32124
|
+
if (this.#disposed) return;
|
|
32125
|
+
this.#closeAll();
|
|
32126
|
+
this.#disposed = true;
|
|
32127
|
+
}
|
|
32128
|
+
#delivery() {
|
|
32129
|
+
return this.#source.deliveryMode === "stream" ? "stream" : "datagram";
|
|
32130
|
+
}
|
|
32131
|
+
#layers() {
|
|
32132
|
+
return this.#source.repairLayers ?? [];
|
|
32133
|
+
}
|
|
32134
|
+
#closeWindow() {
|
|
32135
|
+
const rate = this.#lost / this.#expected;
|
|
32136
|
+
this.#lossRate = rate;
|
|
32137
|
+
this.#expected = 0;
|
|
32138
|
+
this.#lost = 0;
|
|
32139
|
+
const target = this.#targetLayers(rate);
|
|
32140
|
+
if (target > this.#layerCount) {
|
|
32141
|
+
this.#wantFewer = 0;
|
|
32142
|
+
this.#layerCount = target;
|
|
32143
|
+
} else if (target < this.#layerCount) {
|
|
32144
|
+
this.#wantFewer += 1;
|
|
32145
|
+
if (this.#wantFewer >= this.#dropAfterWindows) {
|
|
32146
|
+
this.#wantFewer = 0;
|
|
32147
|
+
this.#layerCount -= 1;
|
|
32148
|
+
}
|
|
32149
|
+
} else {
|
|
32150
|
+
this.#wantFewer = 0;
|
|
32151
|
+
}
|
|
32152
|
+
this.#reconcile();
|
|
32153
|
+
}
|
|
32154
|
+
/** Fewest base layers whose summed P covers margin x the measured loss of K. */
|
|
32155
|
+
#targetLayers(rate) {
|
|
32156
|
+
if (rate <= 0) return 0;
|
|
32157
|
+
const needed = Math.ceil(rate * this.#source.fecK * this.#margin);
|
|
32158
|
+
const layers = this.#layers();
|
|
32159
|
+
let held = 0;
|
|
32160
|
+
for (let n = 0; n < layers.length; n++) {
|
|
32161
|
+
held += layers[n].repairSymbols;
|
|
32162
|
+
if (held >= needed) return n + 1;
|
|
32163
|
+
}
|
|
32164
|
+
return layers.length;
|
|
32165
|
+
}
|
|
32166
|
+
/** Stream delivery never leaves layer count 0, so it never subscribes. */
|
|
32167
|
+
#reconcile() {
|
|
32168
|
+
const want = /* @__PURE__ */ new Map();
|
|
32169
|
+
for (const layer of this.#layers().slice(0, this.#layerCount)) {
|
|
32170
|
+
want.set(layer.repairTrackName, layer.priority);
|
|
32171
|
+
}
|
|
32172
|
+
const overlay = this.#source.repairOverlays?.[0];
|
|
32173
|
+
if (this.#layerCount > 0 && overlay) want.set(overlay.repairTrackName, overlay.priority);
|
|
32174
|
+
for (const [name, entry] of this.#subs) {
|
|
32175
|
+
if (!want.has(name)) {
|
|
32176
|
+
entry.sub.close();
|
|
32177
|
+
this.#subs.delete(name);
|
|
32178
|
+
}
|
|
32179
|
+
}
|
|
32180
|
+
for (const [name, priority] of want) {
|
|
32181
|
+
if (this.#subs.has(name)) continue;
|
|
32182
|
+
const entry = {};
|
|
32183
|
+
entry.sub = this.#opts.subscribe(name, priority, (packet) => this.#onPacket(name, entry, packet));
|
|
32184
|
+
this.#subs.set(name, entry);
|
|
32185
|
+
}
|
|
32186
|
+
}
|
|
32187
|
+
/** Fenced on the entry itself, so a closed subscription is stale even if its track is re-added. */
|
|
32188
|
+
#onPacket(name, entry, packet) {
|
|
32189
|
+
if (this.#disposed || this.#subs.get(name) !== entry) {
|
|
32190
|
+
this.#staleDropped += 1;
|
|
32191
|
+
return;
|
|
32192
|
+
}
|
|
32193
|
+
this.#repairPackets += 1;
|
|
32194
|
+
this.#repairBytes += packet.byteLength;
|
|
32195
|
+
this.#opts.feed(packet, name);
|
|
32196
|
+
}
|
|
32197
|
+
#closeAll() {
|
|
32198
|
+
for (const entry of this.#subs.values()) entry.sub.close();
|
|
32199
|
+
this.#subs.clear();
|
|
32200
|
+
}
|
|
32201
|
+
};
|
|
32202
|
+
|
|
32022
32203
|
// src/repair-fetch.ts
|
|
32023
32204
|
var MOQT_PRIORITY_MAX = 255;
|
|
32024
32205
|
var SOURCE_MEDIA_PRIORITY_MAX = REPAIR_PRIORITY_MIN - 1;
|
|
@@ -32664,6 +32845,7 @@ export {
|
|
|
32664
32845
|
REPAIR_LIFECYCLE_LOG_PREFIX,
|
|
32665
32846
|
REPAIR_PRIORITY_MAX,
|
|
32666
32847
|
REPAIR_PRIORITY_MIN,
|
|
32848
|
+
RepairLayerSubscriptions,
|
|
32667
32849
|
SOURCE_MEDIA_PRIORITY_MAX,
|
|
32668
32850
|
SampleCombineError,
|
|
32669
32851
|
SampleCombiner,
|
|
@@ -32688,6 +32870,7 @@ export {
|
|
|
32688
32870
|
catalogGroupDurationMs,
|
|
32689
32871
|
catalogKeyframeCadenceMs,
|
|
32690
32872
|
catalogRepairTarget,
|
|
32873
|
+
catalogTrackDeliveryMode,
|
|
32691
32874
|
catalogTrackFecUnavailable,
|
|
32692
32875
|
classifyH264Keyframe,
|
|
32693
32876
|
classifyHevcKeyframe,
|