@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.
@@ -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
- if (typeof navigator !== "undefined" && navigator.serviceWorker) {
8766
- navigator.serviceWorker.addEventListener("message", this.messageHandler);
8767
- console.log("[AMT] Registered service worker message handler");
8768
- } else {
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,