@blockcast/mmt-transport 0.2.0 → 0.2.2

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.
Files changed (98) hide show
  1. package/README.md +264 -0
  2. package/dist/.build-stamp +0 -0
  3. package/dist/abr-controller.d.ts +3 -0
  4. package/dist/abr-controller.d.ts.map +1 -1
  5. package/dist/abr-controller.js +5 -0
  6. package/dist/abr-controller.js.map +1 -1
  7. package/dist/amt-gateway.d.ts.map +1 -1
  8. package/dist/amt-gateway.js +2 -1
  9. package/dist/amt-gateway.js.map +1 -1
  10. package/dist/endpoint-config.d.ts +20 -0
  11. package/dist/endpoint-config.d.ts.map +1 -0
  12. package/dist/endpoint-config.js +103 -0
  13. package/dist/endpoint-config.js.map +1 -0
  14. package/dist/endpoint-config.test.d.ts +2 -0
  15. package/dist/endpoint-config.test.d.ts.map +1 -0
  16. package/dist/endpoint-config.test.js +39 -0
  17. package/dist/endpoint-config.test.js.map +1 -0
  18. package/dist/fec-client.d.ts +2 -2
  19. package/dist/fec-client.d.ts.map +1 -1
  20. package/dist/fec-client.js +10 -5
  21. package/dist/fec-client.js.map +1 -1
  22. package/dist/index.d.ts +8 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +7 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/mmt-transport.no-modules.js +1154 -0
  27. package/dist/mmt-transport.no-modules.js.map +7 -0
  28. package/dist/multicast-orchestrator.d.ts +56 -0
  29. package/dist/multicast-orchestrator.d.ts.map +1 -0
  30. package/dist/multicast-orchestrator.js +123 -0
  31. package/dist/multicast-orchestrator.js.map +1 -0
  32. package/dist/multicast-subscription-pool.d.ts +18 -0
  33. package/dist/multicast-subscription-pool.d.ts.map +1 -0
  34. package/dist/multicast-subscription-pool.js +130 -0
  35. package/dist/multicast-subscription-pool.js.map +1 -0
  36. package/dist/multicast-subscription-pool.test.d.ts +2 -0
  37. package/dist/multicast-subscription-pool.test.d.ts.map +1 -0
  38. package/dist/multicast-subscription-pool.test.js +108 -0
  39. package/dist/multicast-subscription-pool.test.js.map +1 -0
  40. package/dist/multicast-tier.d.ts +14 -0
  41. package/dist/multicast-tier.d.ts.map +1 -0
  42. package/dist/multicast-tier.js +22 -0
  43. package/dist/multicast-tier.js.map +1 -0
  44. package/dist/multicast-tier.test.d.ts +2 -0
  45. package/dist/multicast-tier.test.d.ts.map +1 -0
  46. package/dist/multicast-tier.test.js +75 -0
  47. package/dist/multicast-tier.test.js.map +1 -0
  48. package/dist/no-modules.d.ts +29 -0
  49. package/dist/no-modules.d.ts.map +1 -0
  50. package/dist/no-modules.js +35 -0
  51. package/dist/no-modules.js.map +1 -0
  52. package/dist/stall-detector.d.ts +22 -0
  53. package/dist/stall-detector.d.ts.map +1 -0
  54. package/dist/stall-detector.js +46 -0
  55. package/dist/stall-detector.js.map +1 -0
  56. package/dist/stall-detector.test.d.ts +2 -0
  57. package/dist/stall-detector.test.d.ts.map +1 -0
  58. package/dist/stall-detector.test.js +33 -0
  59. package/dist/stall-detector.test.js.map +1 -0
  60. package/dist/takeover.d.ts +49 -0
  61. package/dist/takeover.d.ts.map +1 -0
  62. package/dist/takeover.js +43 -0
  63. package/dist/takeover.js.map +1 -0
  64. package/dist/transport-manager.d.ts +28 -18
  65. package/dist/transport-manager.d.ts.map +1 -1
  66. package/dist/transport-manager.js +192 -138
  67. package/dist/transport-manager.js.map +1 -1
  68. package/dist/transport-manager.test.d.ts +2 -0
  69. package/dist/transport-manager.test.d.ts.map +1 -0
  70. package/dist/transport-manager.test.js +155 -0
  71. package/dist/transport-manager.test.js.map +1 -0
  72. package/dist/types.d.ts +36 -36
  73. package/dist/types.d.ts.map +1 -1
  74. package/dist/types.js.map +1 -1
  75. package/dist/unicast-fallback.d.ts +36 -0
  76. package/dist/unicast-fallback.d.ts.map +1 -0
  77. package/dist/unicast-fallback.js +53 -0
  78. package/dist/unicast-fallback.js.map +1 -0
  79. package/package.json +6 -6
  80. package/src/abr-controller.ts +9 -0
  81. package/src/amt-gateway.ts +2 -1
  82. package/src/endpoint-config.test.ts +54 -0
  83. package/src/endpoint-config.ts +121 -0
  84. package/src/fec-client.ts +11 -5
  85. package/src/index.ts +72 -2
  86. package/src/multicast-orchestrator.ts +150 -0
  87. package/src/multicast-subscription-pool.test.ts +115 -0
  88. package/src/multicast-subscription-pool.ts +164 -0
  89. package/src/multicast-tier.test.ts +80 -0
  90. package/src/multicast-tier.ts +32 -0
  91. package/src/no-modules.ts +44 -0
  92. package/src/stall-detector.test.ts +34 -0
  93. package/src/stall-detector.ts +63 -0
  94. package/src/takeover.ts +71 -0
  95. package/src/transport-manager.test.ts +192 -0
  96. package/src/transport-manager.ts +203 -153
  97. package/src/types.ts +50 -31
  98. package/src/unicast-fallback.ts +57 -0
@@ -0,0 +1,108 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { MulticastSubscriptionPool } from "./multicast-subscription-pool.js";
3
+ const config = {
4
+ group: "232.1.1.1",
5
+ source: "192.0.2.1",
6
+ port: 5000,
7
+ streamType: "video",
8
+ };
9
+ describe("MulticastSubscriptionPool", () => {
10
+ it("shares an endpoint and unsubscribes only after the last owner releases", async () => {
11
+ const listeners = new Map();
12
+ const unsubscribe = vi.fn();
13
+ const subscription = {
14
+ addEventListener: vi.fn((type, listener) => listeners.set(type, listener)),
15
+ removeEventListener: vi.fn(),
16
+ unsubscribe,
17
+ };
18
+ const subscribe = vi.fn().mockResolvedValue(subscription);
19
+ const gateway = { subscribe };
20
+ const pool = new MulticastSubscriptionPool();
21
+ const firstPacket = vi.fn();
22
+ const secondPacket = vi.fn();
23
+ const first = await pool.acquire(gateway, config, { onBytes: firstPacket });
24
+ const second = await pool.acquire(gateway, { ...config, group: " 232.1.1.1 " }, { onBytes: secondPacket });
25
+ expect(subscribe).toHaveBeenCalledOnce();
26
+ const payload = new Uint8Array([1, 2]).buffer;
27
+ listeners.get("bytes")?.({ detail: payload });
28
+ expect(firstPacket).toHaveBeenCalledWith(payload);
29
+ expect(secondPacket).toHaveBeenCalledWith(payload);
30
+ await first.release();
31
+ expect(unsubscribe).not.toHaveBeenCalled();
32
+ await second.release();
33
+ expect(unsubscribe).toHaveBeenCalledOnce();
34
+ expect(pool.size).toBe(0);
35
+ });
36
+ it("counts an awaiting acquire before the previous owner releases", async () => {
37
+ const unsubscribe = vi.fn();
38
+ const subscription = {
39
+ addEventListener: vi.fn(), removeEventListener: vi.fn(), unsubscribe,
40
+ };
41
+ const subscribe = vi.fn().mockResolvedValue(subscription);
42
+ const gateway = { subscribe };
43
+ const pool = new MulticastSubscriptionPool();
44
+ const first = await pool.acquire(gateway, config, { onBytes: vi.fn() });
45
+ const secondPending = pool.acquire(gateway, config, { onBytes: vi.fn() });
46
+ await first.release();
47
+ const second = await secondPending;
48
+ expect(unsubscribe).not.toHaveBeenCalled();
49
+ expect(pool.size).toBe(1);
50
+ await second.release();
51
+ expect(unsubscribe).toHaveBeenCalledOnce();
52
+ });
53
+ it("does not conflate transport preferences or gateway instances", async () => {
54
+ const makeSubscription = () => ({
55
+ addEventListener: vi.fn(), removeEventListener: vi.fn(), unsubscribe: vi.fn(),
56
+ });
57
+ const firstGateway = { subscribe: vi.fn().mockResolvedValue(makeSubscription()) };
58
+ const secondGateway = { subscribe: vi.fn().mockResolvedValue(makeSubscription()) };
59
+ const pool = new MulticastSubscriptionPool();
60
+ const native = await pool.acquire(firstGateway, { ...config, mode: "native" }, { onBytes: vi.fn() });
61
+ const tunnel = await pool.acquire(firstGateway, { ...config, mode: "tunnel", amtRelay: "relay.example" }, { onBytes: vi.fn() });
62
+ const replacement = await pool.acquire(secondGateway, { ...config, mode: "native" }, { onBytes: vi.fn() });
63
+ expect(firstGateway.subscribe).toHaveBeenCalledTimes(2);
64
+ expect(secondGateway.subscribe).toHaveBeenCalledOnce();
65
+ await Promise.all([native.release(), tunnel.release(), replacement.release()]);
66
+ });
67
+ it("evicts a closed entry so the next owner reconnects", async () => {
68
+ const stateListeners = [];
69
+ const subscribe = vi.fn().mockImplementation(async () => ({
70
+ addEventListener: vi.fn((type, listener) => {
71
+ if (type === "state")
72
+ stateListeners.push(listener);
73
+ }),
74
+ removeEventListener: vi.fn(),
75
+ unsubscribe: vi.fn(),
76
+ }));
77
+ const gateway = { subscribe };
78
+ const pool = new MulticastSubscriptionPool();
79
+ const first = await pool.acquire(gateway, config, { onBytes: vi.fn() });
80
+ stateListeners[0]({ detail: "closed" });
81
+ expect(pool.size).toBe(0);
82
+ const second = await pool.acquire(gateway, config, { onBytes: vi.fn() });
83
+ expect(subscribe).toHaveBeenCalledTimes(2);
84
+ await first.release();
85
+ await second.release();
86
+ });
87
+ it("isolates consumer callback failures", async () => {
88
+ let bytesListener;
89
+ const subscribe = vi.fn().mockResolvedValue({
90
+ addEventListener: vi.fn((type, listener) => {
91
+ if (type === "bytes")
92
+ bytesListener = listener;
93
+ }),
94
+ removeEventListener: vi.fn(), unsubscribe: vi.fn(),
95
+ });
96
+ const gateway = { subscribe };
97
+ const pool = new MulticastSubscriptionPool();
98
+ const secondConsumer = vi.fn();
99
+ const first = await pool.acquire(gateway, config, { onBytes: () => { throw new Error("boom"); } });
100
+ const second = await pool.acquire(gateway, config, { onBytes: secondConsumer });
101
+ const consoleError = vi.spyOn(console, "error").mockImplementation(() => { });
102
+ bytesListener?.({ detail: new ArrayBuffer(1) });
103
+ expect(secondConsumer).toHaveBeenCalledOnce();
104
+ consoleError.mockRestore();
105
+ await Promise.all([first.release(), second.release()]);
106
+ });
107
+ });
108
+ //# sourceMappingURL=multicast-subscription-pool.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multicast-subscription-pool.test.js","sourceRoot":"","sources":["../src/multicast-subscription-pool.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface MulticastTierEndpoint {
2
+ sourceAddress?: string;
3
+ groupAddress: string;
4
+ port: number;
5
+ tracks: {
6
+ name: string;
7
+ packetId?: number;
8
+ }[];
9
+ bandwidth?: number;
10
+ protocol?: string;
11
+ }
12
+ export declare function endpointKey(endpoint: MulticastTierEndpoint): string;
13
+ export declare function selectMulticastTier(endpoints: readonly MulticastTierEndpoint[], estimate: number | undefined): MulticastTierEndpoint | undefined;
14
+ //# sourceMappingURL=multicast-tier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multicast-tier.d.ts","sourceRoot":"","sources":["../src/multicast-tier.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,qBAAqB,GAAG,MAAM,CAEnE;AAED,wBAAgB,mBAAmB,CAClC,SAAS,EAAE,SAAS,qBAAqB,EAAE,EAC3C,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC1B,qBAAqB,GAAG,SAAS,CAenC"}
@@ -0,0 +1,22 @@
1
+ export function endpointKey(endpoint) {
2
+ return `${endpoint.sourceAddress ?? ""}|${endpoint.groupAddress}|${endpoint.port}`;
3
+ }
4
+ export function selectMulticastTier(endpoints, estimate) {
5
+ if (endpoints.length <= 1)
6
+ return endpoints[0];
7
+ const ranked = endpoints
8
+ .filter((endpoint) => typeof endpoint.bandwidth === "number" && endpoint.bandwidth > 0)
9
+ .sort((a, b) => a.bandwidth - b.bandwidth);
10
+ if (ranked.length < 2)
11
+ return endpoints[0];
12
+ if (estimate === undefined)
13
+ return ranked[0];
14
+ const budget = estimate * 0.8;
15
+ let selected;
16
+ for (const endpoint of ranked) {
17
+ if (endpoint.bandwidth <= budget)
18
+ selected = endpoint;
19
+ }
20
+ return selected ?? ranked[0];
21
+ }
22
+ //# sourceMappingURL=multicast-tier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multicast-tier.js","sourceRoot":"","sources":["../src/multicast-tier.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,WAAW,CAAC,QAA+B;IAC1D,OAAO,GAAG,QAAQ,CAAC,aAAa,IAAI,EAAE,IAAI,QAAQ,CAAC,YAAY,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,mBAAmB,CAClC,SAA2C,EAC3C,QAA4B;IAE5B,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;IAE/C,MAAM,MAAM,GAAG,SAAS;SACtB,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,QAAQ,CAAC,SAAS,KAAK,QAAQ,IAAI,QAAQ,CAAC,SAAS,GAAG,CAAC,CAAC;SACtF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAU,GAAG,CAAC,CAAC,SAAU,CAAC,CAAC;IAC9C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;IAC3C,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAG,QAAQ,GAAG,GAAG,CAAC;IAC9B,IAAI,QAA2C,CAAC;IAChD,KAAK,MAAM,QAAQ,IAAI,MAAM,EAAE,CAAC;QAC/B,IAAI,QAAQ,CAAC,SAAU,IAAI,MAAM;YAAE,QAAQ,GAAG,QAAQ,CAAC;IACxD,CAAC;IACD,OAAO,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=multicast-tier.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multicast-tier.test.d.ts","sourceRoot":"","sources":["../src/multicast-tier.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { MulticastOrchestrator } from "./multicast-orchestrator.js";
3
+ import { endpointKey, selectMulticastTier } from "./multicast-tier.js";
4
+ const low = {
5
+ groupAddress: "232.1.1.1", port: 5000, tracks: [{ name: "video/720p" }], bandwidth: 2_000_000,
6
+ };
7
+ const high = {
8
+ groupAddress: "232.1.1.2", port: 5000, tracks: [{ name: "video/4k" }], bandwidth: 15_000_000,
9
+ };
10
+ describe("multicast tier selection", () => {
11
+ it("starts conservatively and applies headroom", () => {
12
+ expect(selectMulticastTier([high, low], undefined)).toBe(low);
13
+ expect(selectMulticastTier([low, high], 16_000_000)).toBe(low);
14
+ expect(selectMulticastTier([low, high], 20_000_000)).toBe(high);
15
+ });
16
+ it("switches make-before-break only on a valid target RAP", () => {
17
+ let now = 0;
18
+ const orchestrator = new MulticastOrchestrator({
19
+ endpoints: [low, high], now: () => now, dwellMs: 1000, joinDeadlineMs: 5000,
20
+ });
21
+ expect(orchestrator.start()).toBe(low);
22
+ expect(orchestrator.onGoodput({ bitrate: 20_000_000 })).toBeUndefined();
23
+ now = 1000;
24
+ expect(orchestrator.onGoodput({ bitrate: 20_000_000 })?.kind).toBe("join-target");
25
+ expect(orchestrator.onTierPacket({
26
+ endpointKey: endpointKey(high), keyframe: false, timestamp: 10, hasValidCodecConfig: true,
27
+ })).toBeUndefined();
28
+ expect(orchestrator.onTierPacket({
29
+ endpointKey: endpointKey(high), keyframe: true, timestamp: 11, hasValidCodecConfig: true,
30
+ })?.kind).toBe("commit-swap");
31
+ });
32
+ it("preserves a pinned initial tier", () => {
33
+ let now = 0;
34
+ const orchestrator = new MulticastOrchestrator({
35
+ endpoints: [low, high], initialEndpoint: high, adaptive: false,
36
+ now: () => now, dwellMs: 1000, joinDeadlineMs: 5000,
37
+ });
38
+ expect(orchestrator.start()).toBe(high);
39
+ expect(orchestrator.onGoodput({ bitrate: 1_000_000 })).toBeUndefined();
40
+ now = 10_000;
41
+ expect(orchestrator.onGoodput({ bitrate: 1_000_000 })).toBeUndefined();
42
+ expect(orchestrator.current).toBe(high);
43
+ });
44
+ it("abandons a silent target when polled after the join deadline", () => {
45
+ let now = 0;
46
+ const orchestrator = new MulticastOrchestrator({
47
+ endpoints: [low, high], now: () => now, dwellMs: 1000, joinDeadlineMs: 5000,
48
+ });
49
+ orchestrator.start();
50
+ orchestrator.onGoodput({ bitrate: 20_000_000 });
51
+ now = 1000;
52
+ orchestrator.onGoodput({ bitrate: 20_000_000 });
53
+ now = 6000;
54
+ expect(orchestrator.poll()?.kind).toBe("abandon-join");
55
+ expect(orchestrator.state).toBe("stable");
56
+ });
57
+ it("rejects a target RAP older than the active tier high-water mark", () => {
58
+ let now = 0;
59
+ const orchestrator = new MulticastOrchestrator({
60
+ endpoints: [low, high], now: () => now, dwellMs: 1000, joinDeadlineMs: 5000,
61
+ });
62
+ orchestrator.start();
63
+ orchestrator.onTierPacket({
64
+ endpointKey: endpointKey(low), keyframe: false, timestamp: 10_000, hasValidCodecConfig: true,
65
+ });
66
+ orchestrator.onGoodput({ bitrate: 20_000_000 });
67
+ now = 1000;
68
+ orchestrator.onGoodput({ bitrate: 20_000_000 });
69
+ expect(orchestrator.onTierPacket({
70
+ endpointKey: endpointKey(high), keyframe: true, timestamp: 9_000, hasValidCodecConfig: true,
71
+ })).toBeUndefined();
72
+ expect(orchestrator.state).toBe("joining");
73
+ });
74
+ });
75
+ //# sourceMappingURL=multicast-tier.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multicast-tier.test.js","sourceRoot":"","sources":["../src/multicast-tier.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { AdaptiveBitrateController } from "./abr-controller.js";
2
+ import { isMulticastExplicitlyDisabled, isUsableMulticastEndpoint, isValidMulticastGroupAddress, multicastEndpointKey, normalizeMulticastEndpoint, readUrlMulticastConfig } from "./endpoint-config.js";
3
+ import { MulticastOrchestrator } from "./multicast-orchestrator.js";
4
+ import { MulticastSubscriptionPool } from "./multicast-subscription-pool.js";
5
+ import { endpointKey, selectMulticastTier } from "./multicast-tier.js";
6
+ import { TransportStallDetector } from "./stall-detector.js";
7
+ import { makeSourceSwitchHandler, wireStarvationDetector } from "./takeover.js";
8
+ import { TransportManager } from "./transport-manager.js";
9
+ import { runUnicastFallback } from "./unicast-fallback.js";
10
+ declare const api: {
11
+ AdaptiveBitrateController: typeof AdaptiveBitrateController;
12
+ MulticastOrchestrator: typeof MulticastOrchestrator;
13
+ MulticastSubscriptionPool: typeof MulticastSubscriptionPool;
14
+ TransportManager: typeof TransportManager;
15
+ TransportStallDetector: typeof TransportStallDetector;
16
+ endpointKey: typeof endpointKey;
17
+ isMulticastExplicitlyDisabled: typeof isMulticastExplicitlyDisabled;
18
+ isUsableMulticastEndpoint: typeof isUsableMulticastEndpoint;
19
+ isValidMulticastGroupAddress: typeof isValidMulticastGroupAddress;
20
+ makeSourceSwitchHandler: typeof makeSourceSwitchHandler;
21
+ multicastEndpointKey: typeof multicastEndpointKey;
22
+ normalizeMulticastEndpoint: typeof normalizeMulticastEndpoint;
23
+ readUrlMulticastConfig: typeof readUrlMulticastConfig;
24
+ runUnicastFallback: typeof runUnicastFallback;
25
+ selectMulticastTier: typeof selectMulticastTier;
26
+ wireStarvationDetector: typeof wireStarvationDetector;
27
+ };
28
+ export default api;
29
+ //# sourceMappingURL=no-modules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-modules.d.ts","sourceRoot":"","sources":["../src/no-modules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EACN,6BAA6B,EAC7B,yBAAyB,EACzB,4BAA4B,EAC5B,oBAAoB,EACpB,0BAA0B,EAC1B,sBAAsB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,QAAA,MAAM,GAAG;;;;;;;;;;;;;;;;;CAiBR,CAAC;AASF,eAAe,GAAG,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { AdaptiveBitrateController } from "./abr-controller.js";
2
+ import { isMulticastExplicitlyDisabled, isUsableMulticastEndpoint, isValidMulticastGroupAddress, multicastEndpointKey, normalizeMulticastEndpoint, readUrlMulticastConfig, } from "./endpoint-config.js";
3
+ import { MulticastOrchestrator } from "./multicast-orchestrator.js";
4
+ import { MulticastSubscriptionPool } from "./multicast-subscription-pool.js";
5
+ import { endpointKey, selectMulticastTier } from "./multicast-tier.js";
6
+ import { TransportStallDetector } from "./stall-detector.js";
7
+ import { makeSourceSwitchHandler, wireStarvationDetector } from "./takeover.js";
8
+ import { TransportManager } from "./transport-manager.js";
9
+ import { runUnicastFallback } from "./unicast-fallback.js";
10
+ const api = {
11
+ AdaptiveBitrateController,
12
+ MulticastOrchestrator,
13
+ MulticastSubscriptionPool,
14
+ TransportManager,
15
+ TransportStallDetector,
16
+ endpointKey,
17
+ isMulticastExplicitlyDisabled,
18
+ isUsableMulticastEndpoint,
19
+ isValidMulticastGroupAddress,
20
+ makeSourceSwitchHandler,
21
+ multicastEndpointKey,
22
+ normalizeMulticastEndpoint,
23
+ readUrlMulticastConfig,
24
+ runUnicastFallback,
25
+ selectMulticastTier,
26
+ wireStarvationDetector,
27
+ };
28
+ Object.defineProperty(globalThis, "__MmtTransport", {
29
+ configurable: true,
30
+ enumerable: false,
31
+ writable: false,
32
+ value: Object.freeze(api),
33
+ });
34
+ export default api;
35
+ //# sourceMappingURL=no-modules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-modules.js","sourceRoot":"","sources":["../src/no-modules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EACN,6BAA6B,EAC7B,yBAAyB,EACzB,4BAA4B,EAC5B,oBAAoB,EACpB,0BAA0B,EAC1B,sBAAsB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,GAAG,GAAG;IACX,yBAAyB;IACzB,qBAAqB;IACrB,yBAAyB;IACzB,gBAAgB;IAChB,sBAAsB;IACtB,WAAW;IACX,6BAA6B;IAC7B,yBAAyB;IACzB,4BAA4B;IAC5B,uBAAuB;IACvB,oBAAoB;IACpB,0BAA0B;IAC1B,sBAAsB;IACtB,kBAAkB;IAClB,mBAAmB;IACnB,sBAAsB;CACtB,CAAC;AAEF,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,gBAAgB,EAAE;IACnD,YAAY,EAAE,IAAI;IAClB,UAAU,EAAE,KAAK;IACjB,QAAQ,EAAE,KAAK;IACf,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;CACzB,CAAC,CAAC;AAEH,eAAe,GAAG,CAAC"}
@@ -0,0 +1,22 @@
1
+ export interface FecProgressSnapshot {
2
+ sourceSymbols: number;
3
+ repairSymbols: number;
4
+ blocksComplete: number;
5
+ blocksRecovered: number;
6
+ mediaFrames?: number;
7
+ }
8
+ export interface StallDetectorConfig {
9
+ windowMs: number;
10
+ onStarvation(): void;
11
+ onRecovery(): void;
12
+ now?: () => number;
13
+ }
14
+ export declare class TransportStallDetector {
15
+ #private;
16
+ private readonly config;
17
+ constructor(config: StallDetectorConfig);
18
+ get isStarved(): boolean;
19
+ update(snapshot: FecProgressSnapshot): void;
20
+ reset(): void;
21
+ }
22
+ //# sourceMappingURL=stall-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stall-detector.d.ts","sourceRoot":"","sources":["../src/stall-detector.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,IAAI,IAAI,CAAC;IACrB,UAAU,IAAI,IAAI,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACnB;AAED,qBAAa,sBAAsB;;IAOtB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,mBAAmB;IAKxD,IAAI,SAAS,IAAI,OAAO,CAA0B;IAElD,MAAM,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI;IA4B3C,KAAK,IAAI,IAAI;CAKb"}
@@ -0,0 +1,46 @@
1
+ export class TransportStallDetector {
2
+ config;
3
+ #last = null;
4
+ #lastSampleAt = 0;
5
+ #starvedSince = null;
6
+ #latched = false;
7
+ #now;
8
+ constructor(config) {
9
+ this.config = config;
10
+ if (config.windowMs <= 0)
11
+ throw new Error("Stall window must be positive and catalog-derived");
12
+ this.#now = config.now ?? Date.now;
13
+ }
14
+ get isStarved() { return this.#latched; }
15
+ update(snapshot) {
16
+ const previous = this.#last;
17
+ const previousAt = this.#lastSampleAt;
18
+ const now = this.#now();
19
+ this.#last = { ...snapshot };
20
+ this.#lastSampleAt = now;
21
+ if (!previous)
22
+ return;
23
+ const blockDelta = snapshot.blocksComplete - previous.blocksComplete +
24
+ snapshot.blocksRecovered - previous.blocksRecovered;
25
+ const mediaDelta = (snapshot.mediaFrames ?? 0) - (previous.mediaFrames ?? 0);
26
+ if (blockDelta <= 0 && mediaDelta <= 0) {
27
+ this.#starvedSince ??= previousAt;
28
+ if (!this.#latched && now - this.#starvedSince >= this.config.windowMs) {
29
+ this.#latched = true;
30
+ this.config.onStarvation();
31
+ }
32
+ return;
33
+ }
34
+ this.#starvedSince = null;
35
+ if (this.#latched) {
36
+ this.#latched = false;
37
+ this.config.onRecovery();
38
+ }
39
+ }
40
+ reset() {
41
+ this.#last = null;
42
+ this.#starvedSince = null;
43
+ this.#latched = false;
44
+ }
45
+ }
46
+ //# sourceMappingURL=stall-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stall-detector.js","sourceRoot":"","sources":["../src/stall-detector.ts"],"names":[],"mappings":"AAeA,MAAM,OAAO,sBAAsB;IAOL;IAN7B,KAAK,GAA+B,IAAI,CAAC;IACzC,aAAa,GAAG,CAAC,CAAC;IAClB,aAAa,GAAkB,IAAI,CAAC;IACpC,QAAQ,GAAG,KAAK,CAAC;IACR,IAAI,CAAe;IAE5B,YAA6B,MAA2B;QAA3B,WAAM,GAAN,MAAM,CAAqB;QACvD,IAAI,MAAM,CAAC,QAAQ,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QAC/F,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACpC,CAAC;IAED,IAAI,SAAS,KAAc,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAElD,MAAM,CAAC,QAA6B;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC;QACzB,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,MAAM,UAAU,GAAG,QAAQ,CAAC,cAAc,GAAG,QAAQ,CAAC,cAAc;YACnE,QAAQ,CAAC,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC;QACrD,MAAM,UAAU,GAAG,CAAC,QAAQ,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;QAE7E,IAAI,UAAU,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,aAAa,KAAK,UAAU,CAAC;YAClC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,GAAG,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACxE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACrB,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YAC5B,CAAC;YACD,OAAO;QACR,CAAC;QAED,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YACtB,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QAC1B,CAAC;IACF,CAAC;IAED,KAAK;QACJ,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACvB,CAAC;CACD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stall-detector.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stall-detector.test.d.ts","sourceRoot":"","sources":["../src/stall-detector.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,33 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { TransportStallDetector } from "./stall-detector.js";
3
+ describe("TransportStallDetector", () => {
4
+ it("detects repair-only starvation and recovery", () => {
5
+ let now = 0;
6
+ const onStarvation = vi.fn();
7
+ const onRecovery = vi.fn();
8
+ const detector = new TransportStallDetector({ windowMs: 1000, now: () => now, onStarvation, onRecovery });
9
+ detector.update({ sourceSymbols: 0, repairSymbols: 0, blocksComplete: 0, blocksRecovered: 0 });
10
+ now = 1000;
11
+ detector.update({ sourceSymbols: 0, repairSymbols: 10, blocksComplete: 0, blocksRecovered: 0 });
12
+ expect(onStarvation).toHaveBeenCalledOnce();
13
+ now = 1100;
14
+ detector.update({ sourceSymbols: 1, repairSymbols: 10, blocksComplete: 1, blocksRecovered: 0 });
15
+ expect(onRecovery).toHaveBeenCalledOnce();
16
+ });
17
+ it("detects starvation when all packet counters stop", () => {
18
+ let now = 0;
19
+ const onStarvation = vi.fn();
20
+ const detector = new TransportStallDetector({
21
+ windowMs: 1000,
22
+ now: () => now,
23
+ onStarvation,
24
+ onRecovery: vi.fn(),
25
+ });
26
+ const snapshot = { sourceSymbols: 10, repairSymbols: 2, blocksComplete: 1, blocksRecovered: 0 };
27
+ detector.update(snapshot);
28
+ now = 1000;
29
+ detector.update(snapshot);
30
+ expect(onStarvation).toHaveBeenCalledOnce();
31
+ });
32
+ });
33
+ //# sourceMappingURL=stall-detector.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stall-detector.test.js","sourceRoot":"","sources":["../src/stall-detector.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACtD,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,MAAM,YAAY,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,IAAI,sBAAsB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC;QAC1G,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/F,GAAG,GAAG,IAAI,CAAC;QACX,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC,CAAC;QAChG,MAAM,CAAC,YAAY,CAAC,CAAC,oBAAoB,EAAE,CAAC;QAC5C,GAAG,GAAG,IAAI,CAAC;QACX,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC,CAAC;QAChG,MAAM,CAAC,UAAU,CAAC,CAAC,oBAAoB,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC3D,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,MAAM,YAAY,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,IAAI,sBAAsB,CAAC;YAC3C,QAAQ,EAAE,IAAI;YACd,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG;YACd,YAAY;YACZ,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;SACnB,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,EAAE,aAAa,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC;QAChG,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1B,GAAG,GAAG,IAAI,CAAC;QACX,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1B,MAAM,CAAC,YAAY,CAAC,CAAC,oBAAoB,EAAE,CAAC;IAC7C,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,49 @@
1
+ export interface ActivatableSessions {
2
+ activateMulticast(): void;
3
+ }
4
+ export declare function makeSourceSwitchHandler(options: {
5
+ multicastBridgeAvailable: boolean;
6
+ sessionsReady: Promise<ActivatableSessions | null>;
7
+ onMulticastConfirmed?(): void;
8
+ onAbortTakeover?(): void;
9
+ log?(message: string): void;
10
+ warn?(message: string): void;
11
+ }): (source: string) => Promise<void>;
12
+ export interface LossArcSession {
13
+ lossDetected(): void;
14
+ lossRecovered(): void;
15
+ }
16
+ export interface FecStarvationSnapshot {
17
+ sourceSymbols: number;
18
+ repairSymbols: number;
19
+ blocksComplete: number;
20
+ blocksRecovered: number;
21
+ mediaFrames?: number;
22
+ }
23
+ export interface StarvationDetectorLike {
24
+ update(snapshot: FecStarvationSnapshot): void;
25
+ reset(): void;
26
+ }
27
+ export type StallDetectorLike = StarvationDetectorLike;
28
+ export declare function wireStallDetector(args: {
29
+ session: LossArcSession | undefined;
30
+ windowMs: number;
31
+ makeDetector(config: {
32
+ windowMs: number;
33
+ onStarvation(): void;
34
+ onRecovery(): void;
35
+ }): StallDetectorLike;
36
+ }): StallDetectorLike | null;
37
+ export declare function wireStarvationDetector(args: {
38
+ session: LossArcSession | undefined;
39
+ trackName: string;
40
+ fecInterleaveMs: number;
41
+ fecK: number;
42
+ makeDetector(config: {
43
+ windowMs: number;
44
+ onStarvation(): void;
45
+ onRecovery(): void;
46
+ }): StarvationDetectorLike;
47
+ warn?(message: string): void;
48
+ }): Promise<StarvationDetectorLike | null>;
49
+ //# sourceMappingURL=takeover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"takeover.d.ts","sourceRoot":"","sources":["../src/takeover.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAAG,iBAAiB,IAAI,IAAI,CAAC;CAAE;AAEnE,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAChD,wBAAwB,EAAE,OAAO,CAAC;IAClC,aAAa,EAAE,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IACnD,oBAAoB,CAAC,IAAI,IAAI,CAAC;IAC9B,eAAe,CAAC,IAAI,IAAI,CAAC;IACzB,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAmBpC;AAED,MAAM,WAAW,cAAc;IAAG,YAAY,IAAI,IAAI,CAAC;IAAC,aAAa,IAAI,IAAI,CAAC;CAAE;AAChF,MAAM,WAAW,qBAAqB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,WAAW,sBAAsB;IAAG,MAAM,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAAC,KAAK,IAAI,IAAI,CAAC;CAAE;AACzG,MAAM,MAAM,iBAAiB,GAAG,sBAAsB,CAAC;AAEvD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACvC,OAAO,EAAE,cAAc,GAAG,SAAS,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,IAAI,IAAI,CAAC;QAAC,UAAU,IAAI,IAAI,CAAA;KAAE,GAAG,iBAAiB,CAAC;CACxG,GAAG,iBAAiB,GAAG,IAAI,CAO3B;AAED,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IAClD,OAAO,EAAE,cAAc,GAAG,SAAS,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,IAAI,IAAI,CAAC;QAAC,UAAU,IAAI,IAAI,CAAA;KAAE,GAAG,sBAAsB,CAAC;IAC7G,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CASzC"}
@@ -0,0 +1,43 @@
1
+ export function makeSourceSwitchHandler(options) {
2
+ const log = options.log ?? console.log;
3
+ const warn = options.warn ?? console.warn;
4
+ return async (source) => {
5
+ if (source !== "multicast")
6
+ return;
7
+ if (!options.multicastBridgeAvailable) {
8
+ warn("[MoqWatch] MediaRouter requested multicast without bridge; keeping MoQ active");
9
+ return;
10
+ }
11
+ const sessions = await options.sessionsReady;
12
+ if (!sessions) {
13
+ warn("[MoqWatch] SessionManager unavailable; aborting multicast takeover, staying on MoQ");
14
+ options.onAbortTakeover?.();
15
+ return;
16
+ }
17
+ log("[MoqWatch] MediaRouter -> multicast; activating via SessionManager");
18
+ sessions.activateMulticast();
19
+ options.onMulticastConfirmed?.();
20
+ };
21
+ }
22
+ export function wireStallDetector(args) {
23
+ if (!args.session || args.windowMs <= 0)
24
+ return null;
25
+ return args.makeDetector({
26
+ windowMs: args.windowMs,
27
+ onStarvation: () => args.session.lossDetected(),
28
+ onRecovery: () => args.session.lossRecovered(),
29
+ });
30
+ }
31
+ export async function wireStarvationDetector(args) {
32
+ if (!args.session || args.fecInterleaveMs <= 0 || args.fecK <= 0)
33
+ return null;
34
+ const detector = wireStallDetector({
35
+ session: args.session,
36
+ windowMs: Math.ceil(args.fecInterleaveMs * 3),
37
+ makeDetector: args.makeDetector,
38
+ });
39
+ if (!detector)
40
+ args.warn?.(`Unable to create starvation detector for ${args.trackName}`);
41
+ return detector;
42
+ }
43
+ //# sourceMappingURL=takeover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"takeover.js","sourceRoot":"","sources":["../src/takeover.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,uBAAuB,CAAC,OAOvC;IACA,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACvC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,EAAE;QACvB,IAAI,MAAM,KAAK,WAAW;YAAE,OAAO;QACnC,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,CAAC;YACvC,IAAI,CAAC,+EAA+E,CAAC,CAAC;YACtF,OAAO;QACR,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC;QAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,IAAI,CAAC,oFAAoF,CAAC,CAAC;YAC3F,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;YAC5B,OAAO;QACR,CAAC;QACD,GAAG,CAAC,oEAAoE,CAAC,CAAC;QAC1E,QAAQ,CAAC,iBAAiB,EAAE,CAAC;QAC7B,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC;IAClC,CAAC,CAAC;AACH,CAAC;AAaD,MAAM,UAAU,iBAAiB,CAAC,IAIjC;IACA,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACrD,OAAO,IAAI,CAAC,YAAY,CAAC;QACxB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAQ,CAAC,YAAY,EAAE;QAChD,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAQ,CAAC,aAAa,EAAE;KAC/C,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,IAO5C;IACA,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9E,MAAM,QAAQ,GAAG,iBAAiB,CAAC;QAClC,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;QAC7C,YAAY,EAAE,IAAI,CAAC,YAAY;KAC/B,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ;QAAE,IAAI,CAAC,IAAI,EAAE,CAAC,4CAA4C,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IACzF,OAAO,QAAQ,CAAC;AACjB,CAAC"}