@blockcast/mmt-fec 0.1.0 → 0.3.0

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 (105) hide show
  1. package/README.md +271 -0
  2. package/dist/.build-stamp +0 -0
  3. package/dist/block-manager.d.ts +82 -0
  4. package/dist/block-manager.d.ts.map +1 -0
  5. package/dist/block-manager.js +296 -0
  6. package/dist/block-manager.js.map +1 -0
  7. package/dist/block-processor.d.ts +106 -0
  8. package/dist/block-processor.d.ts.map +1 -0
  9. package/dist/block-processor.js +288 -0
  10. package/dist/block-processor.js.map +1 -0
  11. package/dist/cmaf-recovery.d.ts +46 -0
  12. package/dist/cmaf-recovery.d.ts.map +1 -0
  13. package/dist/cmaf-recovery.js +96 -0
  14. package/dist/cmaf-recovery.js.map +1 -0
  15. package/dist/cmaf-symbols.d.ts +33 -0
  16. package/dist/cmaf-symbols.d.ts.map +1 -0
  17. package/dist/cmaf-symbols.js +57 -0
  18. package/dist/cmaf-symbols.js.map +1 -0
  19. package/dist/fec-block-mapper.d.ts +205 -0
  20. package/dist/fec-block-mapper.d.ts.map +1 -0
  21. package/dist/fec-block-mapper.js +240 -0
  22. package/dist/fec-block-mapper.js.map +1 -0
  23. package/dist/index.d.ts +17 -12
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +17 -12
  26. package/dist/index.js.map +1 -1
  27. package/dist/loc-symbols.d.ts +20 -0
  28. package/dist/loc-symbols.d.ts.map +1 -0
  29. package/dist/loc-symbols.js +28 -0
  30. package/dist/loc-symbols.js.map +1 -0
  31. package/dist/oti.d.ts +258 -0
  32. package/dist/oti.d.ts.map +1 -0
  33. package/dist/oti.js +382 -0
  34. package/dist/oti.js.map +1 -0
  35. package/dist/reorder-buffer.d.ts +41 -0
  36. package/dist/reorder-buffer.d.ts.map +1 -0
  37. package/dist/reorder-buffer.js +81 -0
  38. package/dist/reorder-buffer.js.map +1 -0
  39. package/dist/repair-group.d.ts +82 -0
  40. package/dist/repair-group.d.ts.map +1 -0
  41. package/dist/repair-group.js +170 -0
  42. package/dist/repair-group.js.map +1 -0
  43. package/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
  44. package/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
  45. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
  46. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
  47. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
  48. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
  49. package/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
  50. package/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
  51. package/node_modules/@blockcast/mmt-base/README.md +134 -0
  52. package/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
  53. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts +55 -0
  54. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts.map +1 -0
  55. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js +128 -0
  56. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js.map +1 -0
  57. package/node_modules/@blockcast/mmt-base/dist/index.d.ts +7 -0
  58. package/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
  59. package/node_modules/@blockcast/mmt-base/dist/index.js +7 -0
  60. package/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
  61. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +292 -0
  62. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
  63. package/node_modules/@blockcast/mmt-base/dist/mmtp.js +612 -0
  64. package/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
  65. package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts +18 -0
  66. package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts.map +1 -0
  67. package/node_modules/@blockcast/mmt-base/dist/net-constants.js +18 -0
  68. package/node_modules/@blockcast/mmt-base/dist/net-constants.js.map +1 -0
  69. package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts +47 -0
  70. package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts.map +1 -0
  71. package/node_modules/@blockcast/mmt-base/dist/ntp-short.js +54 -0
  72. package/node_modules/@blockcast/mmt-base/dist/ntp-short.js.map +1 -0
  73. package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts +57 -0
  74. package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts.map +1 -0
  75. package/node_modules/@blockcast/mmt-base/dist/serial-number.js +98 -0
  76. package/node_modules/@blockcast/mmt-base/dist/serial-number.js.map +1 -0
  77. package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts +312 -0
  78. package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts.map +1 -0
  79. package/node_modules/@blockcast/mmt-base/dist/signalling.js +637 -0
  80. package/node_modules/@blockcast/mmt-base/dist/signalling.js.map +1 -0
  81. package/node_modules/@blockcast/mmt-base/package.json +49 -0
  82. package/node_modules/@blockcast/mmt-base/src/fec-block-profile.ts +145 -0
  83. package/node_modules/@blockcast/mmt-base/src/index.ts +6 -0
  84. package/node_modules/@blockcast/mmt-base/src/mmtp.ts +892 -0
  85. package/node_modules/@blockcast/mmt-base/src/net-constants.ts +17 -0
  86. package/node_modules/@blockcast/mmt-base/src/ntp-short.ts +67 -0
  87. package/node_modules/@blockcast/mmt-base/src/serial-number.ts +107 -0
  88. package/node_modules/@blockcast/mmt-base/src/signalling.ts +862 -0
  89. package/package.json +35 -3
  90. package/src/block-manager.ts +371 -0
  91. package/src/block-processor.ts +439 -0
  92. package/src/cmaf-recovery.ts +127 -0
  93. package/src/cmaf-symbols.ts +68 -0
  94. package/src/fec-block-mapper.ts +310 -0
  95. package/src/index.ts +82 -19
  96. package/src/loc-symbols.ts +34 -0
  97. package/src/oti.ts +463 -0
  98. package/src/reorder-buffer.ts +101 -0
  99. package/src/repair-group.ts +195 -0
  100. package/dist/fec-client.d.ts +0 -191
  101. package/dist/fec-client.d.ts.map +0 -1
  102. package/dist/fec-client.js +0 -233
  103. package/dist/fec-client.js.map +0 -1
  104. package/src/fec-client.test.ts +0 -158
  105. package/src/fec-client.ts +0 -354
@@ -1,158 +0,0 @@
1
- /**
2
- * Tests for shared FecClient
3
- *
4
- * Note: Full WASM integration is tested in mmt-wasm.
5
- * These tests cover the TypeScript wrapper behavior.
6
- */
7
-
8
- import { describe, expect, it, beforeEach } from "vitest";
9
- import { FecClient, type FecConfig, type FecProcessingStats } from "./fec-client.js";
10
-
11
- describe("FecConfig interface", () => {
12
- it("should have correct shape for RFC 6330 OTI parameters", () => {
13
- const config: FecConfig = {
14
- symbolSize: 1280,
15
- sourceBlocks: 1,
16
- subBlocks: 1,
17
- alignment: 8,
18
- interleaveDepth: 30,
19
- };
20
-
21
- expect(config.symbolSize).toBe(1280);
22
- expect(config.sourceBlocks).toBe(1);
23
- expect(config.subBlocks).toBe(1);
24
- expect(config.alignment).toBe(8);
25
- expect(config.interleaveDepth).toBe(30);
26
- });
27
- });
28
-
29
- describe("FecProcessingStats interface", () => {
30
- it("should have correct shape", () => {
31
- const stats: FecProcessingStats = {
32
- sourcePackets: 100,
33
- repairPackets: 30,
34
- blocksComplete: 10,
35
- blocksRecovered: 2,
36
- blocksFailed: 0,
37
- recoveryRate: 100,
38
- greenFillFrames: 0,
39
- };
40
-
41
- expect(stats.sourcePackets).toBe(100);
42
- expect(stats.repairPackets).toBe(30);
43
- expect(stats.blocksComplete).toBe(10);
44
- expect(stats.blocksRecovered).toBe(2);
45
- expect(stats.blocksFailed).toBe(0);
46
- expect(stats.recoveryRate).toBe(100);
47
- expect(stats.greenFillFrames).toBe(0);
48
- });
49
- });
50
-
51
- describe("FecClient", () => {
52
- let client: FecClient;
53
-
54
- beforeEach(() => {
55
- client = new FecClient({
56
- interleaveDepth: 30,
57
- blockTimeoutMs: 2000,
58
- greenFillEnabled: true,
59
- });
60
- });
61
-
62
- it("should create with default options", () => {
63
- const defaultClient = new FecClient();
64
- expect(defaultClient.isInitialized()).toBe(false);
65
- });
66
-
67
- it("should not be initialized without calling init()", () => {
68
- expect(client.isInitialized()).toBe(false);
69
- });
70
-
71
- it("should throw when configuring without initialization", () => {
72
- expect(() => client.configure(new Uint8Array(12))).toThrow(
73
- "FecClient not initialized"
74
- );
75
- });
76
-
77
- it("should return default stats when not initialized", () => {
78
- const stats = client.getStats();
79
-
80
- expect(stats.sourcePackets).toBe(0);
81
- expect(stats.repairPackets).toBe(0);
82
- expect(stats.blocksComplete).toBe(0);
83
- expect(stats.blocksRecovered).toBe(0);
84
- expect(stats.blocksFailed).toBe(0);
85
- expect(stats.recoveryRate).toBe(100);
86
- expect(stats.greenFillFrames).toBe(0);
87
- });
88
-
89
- it("should return default config when not initialized", () => {
90
- const config = client.getConfig();
91
-
92
- expect(config.symbolSize).toBe(1280);
93
- expect(config.sourceBlocks).toBe(1);
94
- expect(config.subBlocks).toBe(1);
95
- expect(config.alignment).toBe(8);
96
- expect(config.interleaveDepth).toBe(30);
97
- });
98
-
99
- it("should no-op setInterleaveDepth when not initialized", () => {
100
- client.setInterleaveDepth(10);
101
- const config = client.getConfig();
102
- expect(config.interleaveDepth).toBe(30); // Unchanged since not init'd
103
- });
104
-
105
- it("should return empty array from cleanupByInterleave when not initialized", () => {
106
- const expired = client.cleanupByInterleave(100);
107
- expect(expired).toEqual([]);
108
- });
109
-
110
- it("should return null from addRepair when not initialized", () => {
111
- const result = client.addRepair(0, 0, new Uint8Array(100), 0);
112
- expect(result).toBeNull();
113
- });
114
-
115
- it("should return null from addSource when not initialized", () => {
116
- const result = client.addSource(0, 0, new Uint8Array(100), 0);
117
- expect(result).toBeNull();
118
- });
119
-
120
- it("should return null from processRepairPacket when not initialized", () => {
121
- const result = client.processRepairPacket(new Uint8Array(10), 0);
122
- expect(result).toBeNull();
123
- });
124
-
125
- it("should return null from processRepairPacket with short payload", () => {
126
- const result = client.processRepairPacket(new Uint8Array(3), 0);
127
- expect(result).toBeNull();
128
- });
129
-
130
- it("should dispose cleanly without initialization", () => {
131
- client.dispose();
132
- expect(client.isInitialized()).toBe(false);
133
- });
134
-
135
- it("should reset stats when not initialized", () => {
136
- client.resetStats();
137
- const stats = client.getStats();
138
- expect(stats.greenFillFrames).toBe(0);
139
- });
140
-
141
- it("should throw when init without WASM module", async () => {
142
- await expect(client.init()).rejects.toThrow(
143
- "WASM module not set"
144
- );
145
- });
146
- });
147
-
148
- describe("FecClient callbacks", () => {
149
- it("should store callbacks from options", () => {
150
- const client = new FecClient({
151
- onRecovered: () => {},
152
- onGreenFill: () => {},
153
- onStatsUpdate: () => {},
154
- });
155
-
156
- expect(client.isInitialized()).toBe(false);
157
- });
158
- });
package/src/fec-client.ts DELETED
@@ -1,354 +0,0 @@
1
- /**
2
- * Container-Agnostic FEC Client
3
- *
4
- * Provides RaptorQ-based Forward Error Correction (RFC 6330) that works with:
5
- * - MMTP (MMT Protocol) containers
6
- * - LOC (Low Overhead Container)
7
- * - Raw NAL units with FEC_CONFIG
8
- * - MoQ (Media over QUIC)
9
- *
10
- * Transport independent - works over both:
11
- * - Unicast (MOQ/QUIC/WebTransport)
12
- * - Multicast (SSM/AMT via window.Multicast API)
13
- *
14
- * Based on draft-ramadan-moq-fec-00
15
- */
16
-
17
- // WASM module types - matches mmt-wasm MmtFecDecoder
18
- interface WasmFecDecoder {
19
- configure(oti: Uint8Array): void;
20
- add_repair(sbn: number, esi: number, data: Uint8Array, timestamp: number): Uint8Array | undefined;
21
- add_source(sbn: number, esi: number, data: Uint8Array, timestamp: number): Uint8Array | undefined;
22
- cleanup(current_time: number): Uint8Array;
23
- get_stats(): WasmFecStats;
24
- reset_stats(): void;
25
- flush(): void;
26
- set_timeout(timeout_ms: number): void;
27
- set_green_fill(enabled: boolean): void;
28
- pending_blocks(): number;
29
- }
30
-
31
- interface WasmFecStats {
32
- source_packets: bigint;
33
- repair_packets: bigint;
34
- blocks_complete: bigint;
35
- blocks_recovered: bigint;
36
- blocks_failed: bigint;
37
- recovery_rate(): number;
38
- }
39
-
40
- interface WasmFecPayloadId {
41
- sbn: number;
42
- esi: number;
43
- }
44
-
45
- /**
46
- * FEC processing statistics (transport & container independent)
47
- */
48
- export interface FecProcessingStats {
49
- /** Source packets received */
50
- sourcePackets: number;
51
- /** Repair packets received */
52
- repairPackets: number;
53
- /** Blocks completed (received all source symbols) */
54
- blocksComplete: number;
55
- /** Blocks recovered via FEC */
56
- blocksRecovered: number;
57
- /** Blocks that failed to recover */
58
- blocksFailed: number;
59
- /** Recovery rate (0-100%) */
60
- recoveryRate: number;
61
- /** Green-fill frames (unrecoverable data replaced with placeholder) */
62
- greenFillFrames: number;
63
- }
64
-
65
- /**
66
- * FEC configuration parameters (RFC 6330 OTI)
67
- */
68
- export interface FecConfig {
69
- /** Symbol size in bytes (T) */
70
- symbolSize: number;
71
- /** Number of source blocks (Z) */
72
- sourceBlocks: number;
73
- /** Number of sub-blocks (N) - used for large blocks */
74
- subBlocks: number;
75
- /** Symbol alignment (Al) - typically 8 for byte-aligned */
76
- alignment: number;
77
- /** Interleave depth - number of blocks that can be "in flight" */
78
- interleaveDepth: number;
79
- }
80
-
81
- /**
82
- * Options for FecClient
83
- */
84
- export interface FecClientOptions {
85
- /** Interleave depth for FEC (default: 30 for ~1s at 30fps) */
86
- interleaveDepth?: number;
87
- /** Block timeout in milliseconds (default: 2000) */
88
- blockTimeoutMs?: number;
89
- /** Enable green-fill for failed frames (default: true) */
90
- greenFillEnabled?: boolean;
91
- /** Callback when data is recovered via FEC */
92
- onRecovered?: (data: Uint8Array, timestamp: bigint) => void;
93
- /** Callback for green-fill event */
94
- onGreenFill?: (timestamp: bigint) => void;
95
- /** Callback for stats update */
96
- onStatsUpdate?: (stats: FecProcessingStats) => void;
97
- }
98
-
99
- /**
100
- * WASM module interface for FecClient
101
- * Matches mmt-wasm module exports
102
- */
103
- export interface FecWasmModule {
104
- init: () => Promise<unknown>;
105
- MmtFecDecoder: new (interleaveDepth?: number | null) => WasmFecDecoder;
106
- parse_fec_payload_id: (data: Uint8Array) => WasmFecPayloadId;
107
- is_simd_enabled: () => boolean;
108
- }
109
-
110
- /**
111
- * Container-Agnostic FEC Client
112
- *
113
- * Provides RaptorQ FEC decoding for any container format.
114
- * The actual container parsing (MMTP, LOC, etc.) is handled separately.
115
- */
116
- export class FecClient {
117
- private fecDecoder: WasmFecDecoder | null = null;
118
- private options: Required<FecClientOptions>;
119
- private initialized = false;
120
- private greenFillCount = 0;
121
- private cleanupInterval: ReturnType<typeof setInterval> | null = null;
122
-
123
- // WASM module references (set via setWasmModule or init)
124
- private wasmModule: FecWasmModule | null = null;
125
-
126
- constructor(options: FecClientOptions = {}) {
127
- this.options = {
128
- interleaveDepth: options.interleaveDepth ?? 30,
129
- blockTimeoutMs: options.blockTimeoutMs ?? 2000,
130
- greenFillEnabled: options.greenFillEnabled ?? true,
131
- onRecovered: options.onRecovered ?? (() => {}),
132
- onGreenFill: options.onGreenFill ?? (() => {}),
133
- onStatsUpdate: options.onStatsUpdate ?? (() => {}),
134
- };
135
- }
136
-
137
- /**
138
- * Set WASM module (call before init)
139
- */
140
- setWasmModule(module: FecWasmModule): void {
141
- this.wasmModule = module;
142
- }
143
-
144
- /**
145
- * Initialize the WASM FEC decoder
146
- */
147
- async init(wasmModule?: FecWasmModule): Promise<void> {
148
- if (this.initialized) return;
149
-
150
- if (wasmModule) {
151
- this.wasmModule = wasmModule;
152
- }
153
-
154
- if (!this.wasmModule) {
155
- throw new Error("WASM module not set. Call setWasmModule() or pass module to init()");
156
- }
157
-
158
- await this.wasmModule.init();
159
-
160
- this.fecDecoder = new this.wasmModule.MmtFecDecoder(this.options.interleaveDepth);
161
- this.fecDecoder.set_timeout(this.options.blockTimeoutMs);
162
- this.fecDecoder.set_green_fill(this.options.greenFillEnabled);
163
-
164
- // Start periodic cleanup
165
- this.cleanupInterval = setInterval(() => {
166
- this.cleanup();
167
- }, 500);
168
-
169
- this.initialized = true;
170
- console.log(`[FecClient] Initialized (SIMD: ${this.wasmModule.is_simd_enabled()})`);
171
- }
172
-
173
- /**
174
- * Check if initialized
175
- */
176
- isInitialized(): boolean {
177
- return this.initialized;
178
- }
179
-
180
- /**
181
- * Configure FEC parameters from OTI (Object Transmission Information)
182
- * Per RFC 6330 (RaptorQ)
183
- */
184
- configure(oti: Uint8Array): void {
185
- if (!this.fecDecoder) {
186
- throw new Error("FecClient not initialized");
187
- }
188
- this.fecDecoder.configure(oti);
189
- }
190
-
191
- /**
192
- * Add a source symbol to the FEC decoder
193
- *
194
- * @param sbn - Source Block Number
195
- * @param esi - Encoding Symbol ID (< K for source symbols)
196
- * @param data - Symbol data
197
- * @param timestamp - Packet timestamp for ordering
198
- * @returns Decoded data if block is complete, null otherwise
199
- */
200
- addSource(sbn: number, esi: number, data: Uint8Array, timestamp: number): Uint8Array | null {
201
- if (!this.fecDecoder) return null;
202
- return this.fecDecoder.add_source(sbn, esi, data, timestamp) ?? null;
203
- }
204
-
205
- /**
206
- * Add a repair symbol to the FEC decoder
207
- *
208
- * @param sbn - Source Block Number
209
- * @param esi - Encoding Symbol ID (>= K for repair symbols)
210
- * @param data - Repair symbol data
211
- * @param timestamp - Packet timestamp for ordering
212
- * @returns Recovered data if FEC decoding succeeded, null otherwise
213
- */
214
- addRepair(sbn: number, esi: number, data: Uint8Array, timestamp: number): Uint8Array | null {
215
- if (!this.fecDecoder) return null;
216
-
217
- try {
218
- const decoded = this.fecDecoder.add_repair(sbn, esi, data, timestamp);
219
-
220
- if (decoded && decoded.length > 0) {
221
- const recovered = new Uint8Array(decoded);
222
- this.options.onRecovered(recovered, BigInt(timestamp));
223
- return recovered;
224
- }
225
- } catch (e) {
226
- console.warn("[FecClient] Repair processing error:", e);
227
- }
228
-
229
- return null;
230
- }
231
-
232
- /**
233
- * Process a repair packet with FEC payload ID header
234
- * Per draft-ramadan-moq-fec-00 Section 6.1
235
- *
236
- * @param payload - Repair packet payload (4-byte header + repair symbols)
237
- * @param timestamp - Packet timestamp
238
- * @returns Recovered data if FEC decoding succeeded, null otherwise
239
- */
240
- processRepairPacket(payload: Uint8Array, timestamp: number): Uint8Array | null {
241
- if (!this.fecDecoder || !this.wasmModule || payload.length < 4) return null;
242
-
243
- try {
244
- const { sbn, esi } = this.wasmModule.parse_fec_payload_id(payload.subarray(0, 4));
245
- const data = payload.subarray(4);
246
-
247
- return this.addRepair(sbn, esi, data, timestamp);
248
- } catch (e) {
249
- console.warn("[FecClient] FEC payload parse error:", e);
250
- return null;
251
- }
252
- }
253
-
254
- /**
255
- * Cleanup expired blocks
256
- * Returns green-fill frame data for expired blocks if green-fill is enabled
257
- */
258
- cleanup(): void {
259
- if (!this.fecDecoder) return;
260
-
261
- const greenFillData = this.fecDecoder.cleanup(performance.now());
262
-
263
- // greenFillData is a Uint8Array returned by WASM for expired blocks
264
- if (greenFillData && greenFillData.length > 0 && this.options.greenFillEnabled) {
265
- // Count green-fills based on data returned
266
- const greenFillsTriggered = Math.ceil(greenFillData.length / 8);
267
- if (greenFillsTriggered > 0) {
268
- this.greenFillCount += greenFillsTriggered;
269
- this.options.onGreenFill(BigInt(performance.now()));
270
- }
271
- }
272
- }
273
-
274
- /**
275
- * Get number of pending blocks
276
- */
277
- getPendingBlocks(): number {
278
- return this.fecDecoder?.pending_blocks() ?? 0;
279
- }
280
-
281
- /**
282
- * Get current FEC statistics
283
- */
284
- getStats(): FecProcessingStats {
285
- const fecStats = this.fecDecoder?.get_stats();
286
-
287
- return {
288
- sourcePackets: Number(fecStats?.source_packets ?? 0n),
289
- repairPackets: Number(fecStats?.repair_packets ?? 0n),
290
- blocksComplete: Number(fecStats?.blocks_complete ?? 0n),
291
- blocksRecovered: Number(fecStats?.blocks_recovered ?? 0n),
292
- blocksFailed: Number(fecStats?.blocks_failed ?? 0n),
293
- recoveryRate: fecStats?.recovery_rate() ?? 100,
294
- greenFillFrames: this.greenFillCount,
295
- };
296
- }
297
-
298
- /**
299
- * Get current FEC configuration
300
- * Returns the configured interleave depth (OTI params set via configure())
301
- */
302
- getConfig(): FecConfig {
303
- return {
304
- symbolSize: 1280, // Default, configured via OTI
305
- sourceBlocks: 1, // Default, configured via OTI
306
- subBlocks: 1, // Default, configured via OTI
307
- alignment: 8, // Default, configured via OTI
308
- interleaveDepth: this.options.interleaveDepth,
309
- };
310
- }
311
-
312
- /**
313
- * Reset statistics
314
- */
315
- resetStats(): void {
316
- this.fecDecoder?.reset_stats();
317
- this.greenFillCount = 0;
318
- }
319
-
320
- /**
321
- * Dispose of resources
322
- */
323
- dispose(): void {
324
- if (this.cleanupInterval) {
325
- clearInterval(this.cleanupInterval);
326
- this.cleanupInterval = null;
327
- }
328
- this.fecDecoder?.flush();
329
- this.initialized = false;
330
- }
331
- }
332
-
333
- /**
334
- * Create a shared FEC client instance (singleton pattern)
335
- */
336
- let sharedFecClient: FecClient | null = null;
337
-
338
- export async function getSharedFecClient(
339
- wasmModule: FecWasmModule,
340
- options?: FecClientOptions
341
- ): Promise<FecClient> {
342
- if (!sharedFecClient) {
343
- sharedFecClient = new FecClient(options);
344
- await sharedFecClient.init(wasmModule);
345
- }
346
- return sharedFecClient;
347
- }
348
-
349
- export function resetSharedFecClient(): void {
350
- if (sharedFecClient) {
351
- sharedFecClient.dispose();
352
- sharedFecClient = null;
353
- }
354
- }