@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.
- package/README.md +271 -0
- package/dist/.build-stamp +0 -0
- package/dist/block-manager.d.ts +82 -0
- package/dist/block-manager.d.ts.map +1 -0
- package/dist/block-manager.js +296 -0
- package/dist/block-manager.js.map +1 -0
- package/dist/block-processor.d.ts +106 -0
- package/dist/block-processor.d.ts.map +1 -0
- package/dist/block-processor.js +288 -0
- package/dist/block-processor.js.map +1 -0
- package/dist/cmaf-recovery.d.ts +46 -0
- package/dist/cmaf-recovery.d.ts.map +1 -0
- package/dist/cmaf-recovery.js +96 -0
- package/dist/cmaf-recovery.js.map +1 -0
- package/dist/cmaf-symbols.d.ts +33 -0
- package/dist/cmaf-symbols.d.ts.map +1 -0
- package/dist/cmaf-symbols.js +57 -0
- package/dist/cmaf-symbols.js.map +1 -0
- package/dist/fec-block-mapper.d.ts +205 -0
- package/dist/fec-block-mapper.d.ts.map +1 -0
- package/dist/fec-block-mapper.js +240 -0
- package/dist/fec-block-mapper.js.map +1 -0
- package/dist/index.d.ts +17 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -12
- package/dist/index.js.map +1 -1
- package/dist/loc-symbols.d.ts +20 -0
- package/dist/loc-symbols.d.ts.map +1 -0
- package/dist/loc-symbols.js +28 -0
- package/dist/loc-symbols.js.map +1 -0
- package/dist/oti.d.ts +258 -0
- package/dist/oti.d.ts.map +1 -0
- package/dist/oti.js +382 -0
- package/dist/oti.js.map +1 -0
- package/dist/reorder-buffer.d.ts +41 -0
- package/dist/reorder-buffer.d.ts.map +1 -0
- package/dist/reorder-buffer.js +81 -0
- package/dist/reorder-buffer.js.map +1 -0
- package/dist/repair-group.d.ts +82 -0
- package/dist/repair-group.d.ts.map +1 -0
- package/dist/repair-group.js +170 -0
- package/dist/repair-group.js.map +1 -0
- package/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
- package/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
- package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
- package/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
- package/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
- package/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
- package/node_modules/@blockcast/mmt-base/README.md +134 -0
- package/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
- package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts +55 -0
- package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js +128 -0
- package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/index.d.ts +7 -0
- package/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/index.js +7 -0
- package/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +292 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.js +612 -0
- package/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts +18 -0
- package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/net-constants.js +18 -0
- package/node_modules/@blockcast/mmt-base/dist/net-constants.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts +47 -0
- package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/ntp-short.js +54 -0
- package/node_modules/@blockcast/mmt-base/dist/ntp-short.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts +57 -0
- package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/serial-number.js +98 -0
- package/node_modules/@blockcast/mmt-base/dist/serial-number.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts +312 -0
- package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts.map +1 -0
- package/node_modules/@blockcast/mmt-base/dist/signalling.js +637 -0
- package/node_modules/@blockcast/mmt-base/dist/signalling.js.map +1 -0
- package/node_modules/@blockcast/mmt-base/package.json +49 -0
- package/node_modules/@blockcast/mmt-base/src/fec-block-profile.ts +145 -0
- package/node_modules/@blockcast/mmt-base/src/index.ts +6 -0
- package/node_modules/@blockcast/mmt-base/src/mmtp.ts +892 -0
- package/node_modules/@blockcast/mmt-base/src/net-constants.ts +17 -0
- package/node_modules/@blockcast/mmt-base/src/ntp-short.ts +67 -0
- package/node_modules/@blockcast/mmt-base/src/serial-number.ts +107 -0
- package/node_modules/@blockcast/mmt-base/src/signalling.ts +862 -0
- package/package.json +35 -3
- package/src/block-manager.ts +371 -0
- package/src/block-processor.ts +439 -0
- package/src/cmaf-recovery.ts +127 -0
- package/src/cmaf-symbols.ts +68 -0
- package/src/fec-block-mapper.ts +310 -0
- package/src/index.ts +82 -19
- package/src/loc-symbols.ts +34 -0
- package/src/oti.ts +463 -0
- package/src/reorder-buffer.ts +101 -0
- package/src/repair-group.ts +195 -0
- package/dist/fec-client.d.ts +0 -191
- package/dist/fec-client.d.ts.map +0 -1
- package/dist/fec-client.js +0 -233
- package/dist/fec-client.js.map +0 -1
- package/src/fec-client.test.ts +0 -158
- package/src/fec-client.ts +0 -354
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MoQ repair group ids for `iso-ssbg1-v1` FEC blocks (BLO-35597, decision D2(a)).
|
|
3
|
+
*
|
|
4
|
+
* SS_ID and SS_Start are 32-bit wire fields that wrap at 2^32 (ISO/IEC
|
|
5
|
+
* 23008-1 C.5.2, C.5.3; RFC 1982 serial arithmetic). A MoQ group id is a
|
|
6
|
+
* 62-bit unsigned integer that must never go backwards, so the repair group
|
|
7
|
+
* of an `iso-ssbg1-v1` block is the wrap-epoch-extended SS_Start:
|
|
8
|
+
*
|
|
9
|
+
* ext(SS_Start) = (wrap_epoch << 32) | SS_Start
|
|
10
|
+
*
|
|
11
|
+
* Repair group ids are therefore sparse (one per block, at the block's first
|
|
12
|
+
* SS_ID) and strictly increasing. A receiver that lost SS_ID x in a block it
|
|
13
|
+
* has not delimited FETCHes the absolute group range of draft-ramadan-moq-fec
|
|
14
|
+
* §7.5 (`repairFetchRange`); the last group that range returns is the block
|
|
15
|
+
* containing x.
|
|
16
|
+
*
|
|
17
|
+
* A receiver establishes its wrap-epoch reference from the Group ID of a
|
|
18
|
+
* repair object it received over MoQ, from the Largest Location a
|
|
19
|
+
* TRACK_STATUS for a repair track reports, or as epoch 0 when it observed the
|
|
20
|
+
* instance from its first block (draft-ramadan-moq-fec §7.5). The first two
|
|
21
|
+
* take the epoch from a Group ID itself (`groupId >> 32`): the publisher
|
|
22
|
+
* assigns repair Group IDs and MoQ delivers them unaltered, so a delivered
|
|
23
|
+
* Group ID is the epoch reference, on the same footing as the Largest
|
|
24
|
+
* Location, not a candidate for this module to verify. Nothing a receiver
|
|
25
|
+
* holds before its first reference can check an epoch: without one,
|
|
26
|
+
* `repairGroupIdMatches` checks only the low 32 bits, and its `true` means
|
|
27
|
+
* "this object can be this block's", never "this epoch is verified". It
|
|
28
|
+
* screens out an object to discard; it does not confirm an epoch. No other
|
|
29
|
+
* value is an epoch reference: not a group id computed from a 32-bit SS_ID,
|
|
30
|
+
* and not one carried in a payload rather than as an object's MoQ Group ID.
|
|
31
|
+
*
|
|
32
|
+
* All values are bigint: 62-bit group ids exceed Number's 2^53 exact range.
|
|
33
|
+
*/
|
|
34
|
+
import { SERIAL32_HALF, SERIAL32_SPAN, serial32Distance } from "@blockcast/mmt-base";
|
|
35
|
+
|
|
36
|
+
/** Bits of a MoQ group id above the 32-bit SS_Start: 62 - 32. */
|
|
37
|
+
const WRAP_EPOCH_BITS = 30n;
|
|
38
|
+
/** 2^32 as a bigint: the SS_ID wrap and the shift of the wrap epoch. */
|
|
39
|
+
const SS_ID_SPAN = BigInt(SERIAL32_SPAN);
|
|
40
|
+
/** Exclusive bound of the wrap epoch: 2^30. */
|
|
41
|
+
const WRAP_EPOCH_SPAN = 1n << WRAP_EPOCH_BITS;
|
|
42
|
+
/** Exclusive bound of a MoQ group id: 2^62. */
|
|
43
|
+
const MOQ_GROUP_ID_SPAN = WRAP_EPOCH_SPAN * SS_ID_SPAN;
|
|
44
|
+
|
|
45
|
+
function assertSsId(value: number, name: string): void {
|
|
46
|
+
if (!Number.isInteger(value) || value < 0 || value >= SERIAL32_SPAN) {
|
|
47
|
+
throw new RangeError(`${name} must be a uint32 SS_ID (got ${value})`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function assertGroupId(value: bigint, name: string): void {
|
|
52
|
+
if (typeof value !== "bigint" || value < 0n || value >= MOQ_GROUP_ID_SPAN) {
|
|
53
|
+
throw new RangeError(`${name} must be a 62-bit MoQ group id in [0, 2^62) (got ${String(value)})`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The MoQ repair group id of an `iso-ssbg1-v1` block: `(wrapEpoch << 32) | ssStart`.
|
|
59
|
+
*
|
|
60
|
+
* @param wrapEpoch - How many times SS_ID has wrapped before this block, in `[0, 2^30)`
|
|
61
|
+
* @param ssStart - The block's SS_Start (uint32) from its Repair FEC Payload ID
|
|
62
|
+
* @returns The 62-bit repair group id
|
|
63
|
+
* @throws RangeError unless `ssStart` is a uint32 and `wrapEpoch` a bigint in `[0, 2^30)`
|
|
64
|
+
*/
|
|
65
|
+
export function extSsStart(wrapEpoch: bigint, ssStart: number): bigint {
|
|
66
|
+
if (typeof wrapEpoch !== "bigint" || wrapEpoch < 0n || wrapEpoch >= WRAP_EPOCH_SPAN) {
|
|
67
|
+
throw new RangeError(`wrap epoch must be a bigint in [0, 2^30) (got ${String(wrapEpoch)})`);
|
|
68
|
+
}
|
|
69
|
+
assertSsId(ssStart, "ssStart");
|
|
70
|
+
return (wrapEpoch << 32n) | BigInt(ssStart);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Extend a 32-bit SS_ID to the 62-bit value congruent to it mod 2^32 that is
|
|
75
|
+
* nearest `reference` in RFC 1982 serial order: forward when `ssId` follows
|
|
76
|
+
* the reference's low 32 bits serially, backward when it precedes them, and
|
|
77
|
+
* `reference` itself when they are equal.
|
|
78
|
+
*
|
|
79
|
+
* @param reference - A 62-bit extended SS_ID or repair group id the receiver already holds
|
|
80
|
+
* @param ssId - The 32-bit SS_ID (or SS_Start) to extend
|
|
81
|
+
* @returns The extended 62-bit value
|
|
82
|
+
* @throws RangeError when `ssId` lies exactly 2^31 from the reference's low
|
|
83
|
+
* 32 bits (RFC 1982 leaves that pair unordered, so no direction exists), or
|
|
84
|
+
* when the extension falls outside `[0, 2^62)`
|
|
85
|
+
*/
|
|
86
|
+
export function extendSsId(reference: bigint, ssId: number): bigint {
|
|
87
|
+
assertGroupId(reference, "reference");
|
|
88
|
+
assertSsId(ssId, "ssId");
|
|
89
|
+
const low = Number(reference & (SS_ID_SPAN - 1n));
|
|
90
|
+
const forward = serial32Distance(low, ssId);
|
|
91
|
+
if (forward === SERIAL32_HALF) {
|
|
92
|
+
throw new RangeError(
|
|
93
|
+
`SS_ID ${ssId} is exactly 2^31 from ${low}; RFC 1982 leaves the pair unordered`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const extended = forward < SERIAL32_HALF
|
|
97
|
+
? reference + BigInt(forward)
|
|
98
|
+
: reference - BigInt(SERIAL32_SPAN - forward);
|
|
99
|
+
if (extended < 0n || extended >= MOQ_GROUP_ID_SPAN) {
|
|
100
|
+
throw new RangeError(
|
|
101
|
+
`SS_ID ${ssId} extends from ${String(reference)} to ${String(extended)}, outside [0, 2^62)`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
return extended;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** An absolute, inclusive MoQ group range for a repair FETCH. */
|
|
108
|
+
export interface RepairFetchRange {
|
|
109
|
+
/** First group of the FETCH. */
|
|
110
|
+
readonly startGroup: bigint;
|
|
111
|
+
/** Last group of the FETCH: the extended lost SS_ID. */
|
|
112
|
+
readonly endGroup: bigint;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** What a lost SS_ID is extended from (draft-ramadan-moq-fec §7.5). */
|
|
116
|
+
export type RepairFetchAnchor =
|
|
117
|
+
/** ext(S_prev): the extended SS_Start of the last block the receiver
|
|
118
|
+
* delimited that ends before the lost SS_ID. The caller vouches for that
|
|
119
|
+
* ordering; only a lost SS_ID at or before the block's start is
|
|
120
|
+
* detectable here, since the block's length is not an input. */
|
|
121
|
+
| { readonly previousBlockStart: bigint }
|
|
122
|
+
/** The reference value r of the receiver's wrap epoch, when it has
|
|
123
|
+
* delimited no block that ends before the lost SS_ID. */
|
|
124
|
+
| { readonly reference: bigint };
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The repair FETCH for a lost SS_ID x whose block the receiver has not
|
|
128
|
+
* delimited (draft-ramadan-moq-fec §7.5): the absolute, inclusive group range
|
|
129
|
+
*
|
|
130
|
+
* [max(ext(S_prev) + 1, ext(x) - (K - 1)), ext(x)]
|
|
131
|
+
*
|
|
132
|
+
* or, with no S_prev, `[max(ext(x) - (K - 1), 0), ext(x)]`, where ext(x) is x
|
|
133
|
+
* extended relative to ext(S_prev), or else to the epoch reference r. Repair
|
|
134
|
+
* group ids sit at block starts and no block holds more than K source symbols,
|
|
135
|
+
* so the block containing x starts at most K - 1 SS_IDs before x and is the
|
|
136
|
+
* last group the range returns. The range is never empty.
|
|
137
|
+
*
|
|
138
|
+
* @param lostSsId - The lost 32-bit SS_ID x
|
|
139
|
+
* @param kMax - K: the instance's catalog `sourceSymbols`, the largest
|
|
140
|
+
* SSB_length a block can have
|
|
141
|
+
* @param anchor - ext(S_prev), or the epoch reference r without one
|
|
142
|
+
* @throws RangeError when `kMax` is not a positive safe integer, when x does
|
|
143
|
+
* not extend past `previousBlockStart`, or whenever {@link extendSsId} throws
|
|
144
|
+
*/
|
|
145
|
+
export function repairFetchRange(lostSsId: number, kMax: number, anchor: RepairFetchAnchor): RepairFetchRange {
|
|
146
|
+
if (!Number.isSafeInteger(kMax) || kMax <= 0) {
|
|
147
|
+
throw new RangeError(`kMax must be a positive integer (got ${kMax})`);
|
|
148
|
+
}
|
|
149
|
+
let floor: bigint;
|
|
150
|
+
let endGroup: bigint;
|
|
151
|
+
if ("previousBlockStart" in anchor) {
|
|
152
|
+
assertGroupId(anchor.previousBlockStart, "previousBlockStart");
|
|
153
|
+
floor = anchor.previousBlockStart + 1n;
|
|
154
|
+
endGroup = extendSsId(anchor.previousBlockStart, lostSsId);
|
|
155
|
+
if (endGroup < floor) {
|
|
156
|
+
throw new RangeError(
|
|
157
|
+
`lost SS_ID ${lostSsId} extends to ${String(endGroup)}, not after the previous block at ${String(anchor.previousBlockStart)}`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
floor = 0n;
|
|
162
|
+
endGroup = extendSsId(anchor.reference, lostSsId);
|
|
163
|
+
}
|
|
164
|
+
const reach = endGroup - BigInt(kMax - 1);
|
|
165
|
+
return { startGroup: reach > floor ? reach : floor, endGroup };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Whether a repair object received over MoQ may be used: its Group ID must
|
|
170
|
+
* agree with the SS_Start of its Repair FEC Payload ID, which is authoritative
|
|
171
|
+
* (draft-ramadan-moq-fec §7.5). The Group ID must equal SS_Start modulo 2^32
|
|
172
|
+
* and, once the receiver holds an epoch reference, equal ext(SS_Start)
|
|
173
|
+
* extended relative to it. A receiver discards a repair object for which this
|
|
174
|
+
* is false, leaving every block's state unchanged, and never takes its Group
|
|
175
|
+
* ID as an epoch reference. An SS_Start that cannot be extended (exactly 2^31
|
|
176
|
+
* from the reference) cannot be checked, so it does not match either.
|
|
177
|
+
*
|
|
178
|
+
* @param groupId - The repair object's MoQ Group ID
|
|
179
|
+
* @param ssStart - The SS_Start of its Repair FEC Payload ID
|
|
180
|
+
* @param reference - The receiver's epoch reference r, once it holds one
|
|
181
|
+
* @throws RangeError unless `ssStart` is a uint32 or `reference` (when given)
|
|
182
|
+
* a 62-bit group id
|
|
183
|
+
*/
|
|
184
|
+
export function repairGroupIdMatches(groupId: bigint, ssStart: number, reference?: bigint): boolean {
|
|
185
|
+
assertSsId(ssStart, "ssStart");
|
|
186
|
+
if (reference !== undefined) assertGroupId(reference, "reference");
|
|
187
|
+
if (typeof groupId !== "bigint" || groupId < 0n || groupId >= MOQ_GROUP_ID_SPAN) return false;
|
|
188
|
+
if ((groupId & (SS_ID_SPAN - 1n)) !== BigInt(ssStart)) return false;
|
|
189
|
+
if (reference === undefined) return true;
|
|
190
|
+
try {
|
|
191
|
+
return extendSsId(reference, ssStart) === groupId;
|
|
192
|
+
} catch {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
}
|
package/dist/fec-client.d.ts
DELETED
|
@@ -1,191 +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
|
-
interface WasmFecDecoder {
|
|
17
|
-
configure(oti: Uint8Array): void;
|
|
18
|
-
add_repair(sbn: number, esi: number, data: Uint8Array, timestamp: number): Uint8Array | undefined;
|
|
19
|
-
add_source(sbn: number, esi: number, data: Uint8Array, timestamp: number): Uint8Array | undefined;
|
|
20
|
-
cleanup(current_time: number): Uint8Array;
|
|
21
|
-
get_stats(): WasmFecStats;
|
|
22
|
-
reset_stats(): void;
|
|
23
|
-
flush(): void;
|
|
24
|
-
set_timeout(timeout_ms: number): void;
|
|
25
|
-
set_green_fill(enabled: boolean): void;
|
|
26
|
-
pending_blocks(): number;
|
|
27
|
-
}
|
|
28
|
-
interface WasmFecStats {
|
|
29
|
-
source_packets: bigint;
|
|
30
|
-
repair_packets: bigint;
|
|
31
|
-
blocks_complete: bigint;
|
|
32
|
-
blocks_recovered: bigint;
|
|
33
|
-
blocks_failed: bigint;
|
|
34
|
-
recovery_rate(): number;
|
|
35
|
-
}
|
|
36
|
-
interface WasmFecPayloadId {
|
|
37
|
-
sbn: number;
|
|
38
|
-
esi: number;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* FEC processing statistics (transport & container independent)
|
|
42
|
-
*/
|
|
43
|
-
export interface FecProcessingStats {
|
|
44
|
-
/** Source packets received */
|
|
45
|
-
sourcePackets: number;
|
|
46
|
-
/** Repair packets received */
|
|
47
|
-
repairPackets: number;
|
|
48
|
-
/** Blocks completed (received all source symbols) */
|
|
49
|
-
blocksComplete: number;
|
|
50
|
-
/** Blocks recovered via FEC */
|
|
51
|
-
blocksRecovered: number;
|
|
52
|
-
/** Blocks that failed to recover */
|
|
53
|
-
blocksFailed: number;
|
|
54
|
-
/** Recovery rate (0-100%) */
|
|
55
|
-
recoveryRate: number;
|
|
56
|
-
/** Green-fill frames (unrecoverable data replaced with placeholder) */
|
|
57
|
-
greenFillFrames: number;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* FEC configuration parameters (RFC 6330 OTI)
|
|
61
|
-
*/
|
|
62
|
-
export interface FecConfig {
|
|
63
|
-
/** Symbol size in bytes (T) */
|
|
64
|
-
symbolSize: number;
|
|
65
|
-
/** Number of source blocks (Z) */
|
|
66
|
-
sourceBlocks: number;
|
|
67
|
-
/** Number of sub-blocks (N) - used for large blocks */
|
|
68
|
-
subBlocks: number;
|
|
69
|
-
/** Symbol alignment (Al) - typically 8 for byte-aligned */
|
|
70
|
-
alignment: number;
|
|
71
|
-
/** Interleave depth - number of blocks that can be "in flight" */
|
|
72
|
-
interleaveDepth: number;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Options for FecClient
|
|
76
|
-
*/
|
|
77
|
-
export interface FecClientOptions {
|
|
78
|
-
/** Interleave depth for FEC (default: 30 for ~1s at 30fps) */
|
|
79
|
-
interleaveDepth?: number;
|
|
80
|
-
/** Block timeout in milliseconds (default: 2000) */
|
|
81
|
-
blockTimeoutMs?: number;
|
|
82
|
-
/** Enable green-fill for failed frames (default: true) */
|
|
83
|
-
greenFillEnabled?: boolean;
|
|
84
|
-
/** Callback when data is recovered via FEC */
|
|
85
|
-
onRecovered?: (data: Uint8Array, timestamp: bigint) => void;
|
|
86
|
-
/** Callback for green-fill event */
|
|
87
|
-
onGreenFill?: (timestamp: bigint) => void;
|
|
88
|
-
/** Callback for stats update */
|
|
89
|
-
onStatsUpdate?: (stats: FecProcessingStats) => void;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* WASM module interface for FecClient
|
|
93
|
-
* Matches mmt-wasm module exports
|
|
94
|
-
*/
|
|
95
|
-
export interface FecWasmModule {
|
|
96
|
-
init: () => Promise<unknown>;
|
|
97
|
-
MmtFecDecoder: new (interleaveDepth?: number | null) => WasmFecDecoder;
|
|
98
|
-
parse_fec_payload_id: (data: Uint8Array) => WasmFecPayloadId;
|
|
99
|
-
is_simd_enabled: () => boolean;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Container-Agnostic FEC Client
|
|
103
|
-
*
|
|
104
|
-
* Provides RaptorQ FEC decoding for any container format.
|
|
105
|
-
* The actual container parsing (MMTP, LOC, etc.) is handled separately.
|
|
106
|
-
*/
|
|
107
|
-
export declare class FecClient {
|
|
108
|
-
private fecDecoder;
|
|
109
|
-
private options;
|
|
110
|
-
private initialized;
|
|
111
|
-
private greenFillCount;
|
|
112
|
-
private cleanupInterval;
|
|
113
|
-
private wasmModule;
|
|
114
|
-
constructor(options?: FecClientOptions);
|
|
115
|
-
/**
|
|
116
|
-
* Set WASM module (call before init)
|
|
117
|
-
*/
|
|
118
|
-
setWasmModule(module: FecWasmModule): void;
|
|
119
|
-
/**
|
|
120
|
-
* Initialize the WASM FEC decoder
|
|
121
|
-
*/
|
|
122
|
-
init(wasmModule?: FecWasmModule): Promise<void>;
|
|
123
|
-
/**
|
|
124
|
-
* Check if initialized
|
|
125
|
-
*/
|
|
126
|
-
isInitialized(): boolean;
|
|
127
|
-
/**
|
|
128
|
-
* Configure FEC parameters from OTI (Object Transmission Information)
|
|
129
|
-
* Per RFC 6330 (RaptorQ)
|
|
130
|
-
*/
|
|
131
|
-
configure(oti: Uint8Array): void;
|
|
132
|
-
/**
|
|
133
|
-
* Add a source symbol to the FEC decoder
|
|
134
|
-
*
|
|
135
|
-
* @param sbn - Source Block Number
|
|
136
|
-
* @param esi - Encoding Symbol ID (< K for source symbols)
|
|
137
|
-
* @param data - Symbol data
|
|
138
|
-
* @param timestamp - Packet timestamp for ordering
|
|
139
|
-
* @returns Decoded data if block is complete, null otherwise
|
|
140
|
-
*/
|
|
141
|
-
addSource(sbn: number, esi: number, data: Uint8Array, timestamp: number): Uint8Array | null;
|
|
142
|
-
/**
|
|
143
|
-
* Add a repair symbol to the FEC decoder
|
|
144
|
-
*
|
|
145
|
-
* @param sbn - Source Block Number
|
|
146
|
-
* @param esi - Encoding Symbol ID (>= K for repair symbols)
|
|
147
|
-
* @param data - Repair symbol data
|
|
148
|
-
* @param timestamp - Packet timestamp for ordering
|
|
149
|
-
* @returns Recovered data if FEC decoding succeeded, null otherwise
|
|
150
|
-
*/
|
|
151
|
-
addRepair(sbn: number, esi: number, data: Uint8Array, timestamp: number): Uint8Array | null;
|
|
152
|
-
/**
|
|
153
|
-
* Process a repair packet with FEC payload ID header
|
|
154
|
-
* Per draft-ramadan-moq-fec-00 Section 6.1
|
|
155
|
-
*
|
|
156
|
-
* @param payload - Repair packet payload (4-byte header + repair symbols)
|
|
157
|
-
* @param timestamp - Packet timestamp
|
|
158
|
-
* @returns Recovered data if FEC decoding succeeded, null otherwise
|
|
159
|
-
*/
|
|
160
|
-
processRepairPacket(payload: Uint8Array, timestamp: number): Uint8Array | null;
|
|
161
|
-
/**
|
|
162
|
-
* Cleanup expired blocks
|
|
163
|
-
* Returns green-fill frame data for expired blocks if green-fill is enabled
|
|
164
|
-
*/
|
|
165
|
-
cleanup(): void;
|
|
166
|
-
/**
|
|
167
|
-
* Get number of pending blocks
|
|
168
|
-
*/
|
|
169
|
-
getPendingBlocks(): number;
|
|
170
|
-
/**
|
|
171
|
-
* Get current FEC statistics
|
|
172
|
-
*/
|
|
173
|
-
getStats(): FecProcessingStats;
|
|
174
|
-
/**
|
|
175
|
-
* Get current FEC configuration
|
|
176
|
-
* Returns the configured interleave depth (OTI params set via configure())
|
|
177
|
-
*/
|
|
178
|
-
getConfig(): FecConfig;
|
|
179
|
-
/**
|
|
180
|
-
* Reset statistics
|
|
181
|
-
*/
|
|
182
|
-
resetStats(): void;
|
|
183
|
-
/**
|
|
184
|
-
* Dispose of resources
|
|
185
|
-
*/
|
|
186
|
-
dispose(): void;
|
|
187
|
-
}
|
|
188
|
-
export declare function getSharedFecClient(wasmModule: FecWasmModule, options?: FecClientOptions): Promise<FecClient>;
|
|
189
|
-
export declare function resetSharedFecClient(): void;
|
|
190
|
-
export {};
|
|
191
|
-
//# sourceMappingURL=fec-client.d.ts.map
|
package/dist/fec-client.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fec-client.d.ts","sourceRoot":"","sources":["../src/fec-client.ts"],"names":[],"mappings":"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"}
|
package/dist/fec-client.js
DELETED
|
@@ -1,233 +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
|
-
* Container-Agnostic FEC Client
|
|
18
|
-
*
|
|
19
|
-
* Provides RaptorQ FEC decoding for any container format.
|
|
20
|
-
* The actual container parsing (MMTP, LOC, etc.) is handled separately.
|
|
21
|
-
*/
|
|
22
|
-
export class FecClient {
|
|
23
|
-
fecDecoder = null;
|
|
24
|
-
options;
|
|
25
|
-
initialized = false;
|
|
26
|
-
greenFillCount = 0;
|
|
27
|
-
cleanupInterval = null;
|
|
28
|
-
// WASM module references (set via setWasmModule or init)
|
|
29
|
-
wasmModule = null;
|
|
30
|
-
constructor(options = {}) {
|
|
31
|
-
this.options = {
|
|
32
|
-
interleaveDepth: options.interleaveDepth ?? 30,
|
|
33
|
-
blockTimeoutMs: options.blockTimeoutMs ?? 2000,
|
|
34
|
-
greenFillEnabled: options.greenFillEnabled ?? true,
|
|
35
|
-
onRecovered: options.onRecovered ?? (() => { }),
|
|
36
|
-
onGreenFill: options.onGreenFill ?? (() => { }),
|
|
37
|
-
onStatsUpdate: options.onStatsUpdate ?? (() => { }),
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Set WASM module (call before init)
|
|
42
|
-
*/
|
|
43
|
-
setWasmModule(module) {
|
|
44
|
-
this.wasmModule = module;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Initialize the WASM FEC decoder
|
|
48
|
-
*/
|
|
49
|
-
async init(wasmModule) {
|
|
50
|
-
if (this.initialized)
|
|
51
|
-
return;
|
|
52
|
-
if (wasmModule) {
|
|
53
|
-
this.wasmModule = wasmModule;
|
|
54
|
-
}
|
|
55
|
-
if (!this.wasmModule) {
|
|
56
|
-
throw new Error("WASM module not set. Call setWasmModule() or pass module to init()");
|
|
57
|
-
}
|
|
58
|
-
await this.wasmModule.init();
|
|
59
|
-
this.fecDecoder = new this.wasmModule.MmtFecDecoder(this.options.interleaveDepth);
|
|
60
|
-
this.fecDecoder.set_timeout(this.options.blockTimeoutMs);
|
|
61
|
-
this.fecDecoder.set_green_fill(this.options.greenFillEnabled);
|
|
62
|
-
// Start periodic cleanup
|
|
63
|
-
this.cleanupInterval = setInterval(() => {
|
|
64
|
-
this.cleanup();
|
|
65
|
-
}, 500);
|
|
66
|
-
this.initialized = true;
|
|
67
|
-
console.log(`[FecClient] Initialized (SIMD: ${this.wasmModule.is_simd_enabled()})`);
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Check if initialized
|
|
71
|
-
*/
|
|
72
|
-
isInitialized() {
|
|
73
|
-
return this.initialized;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Configure FEC parameters from OTI (Object Transmission Information)
|
|
77
|
-
* Per RFC 6330 (RaptorQ)
|
|
78
|
-
*/
|
|
79
|
-
configure(oti) {
|
|
80
|
-
if (!this.fecDecoder) {
|
|
81
|
-
throw new Error("FecClient not initialized");
|
|
82
|
-
}
|
|
83
|
-
this.fecDecoder.configure(oti);
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Add a source symbol to the FEC decoder
|
|
87
|
-
*
|
|
88
|
-
* @param sbn - Source Block Number
|
|
89
|
-
* @param esi - Encoding Symbol ID (< K for source symbols)
|
|
90
|
-
* @param data - Symbol data
|
|
91
|
-
* @param timestamp - Packet timestamp for ordering
|
|
92
|
-
* @returns Decoded data if block is complete, null otherwise
|
|
93
|
-
*/
|
|
94
|
-
addSource(sbn, esi, data, timestamp) {
|
|
95
|
-
if (!this.fecDecoder)
|
|
96
|
-
return null;
|
|
97
|
-
return this.fecDecoder.add_source(sbn, esi, data, timestamp) ?? null;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Add a repair symbol to the FEC decoder
|
|
101
|
-
*
|
|
102
|
-
* @param sbn - Source Block Number
|
|
103
|
-
* @param esi - Encoding Symbol ID (>= K for repair symbols)
|
|
104
|
-
* @param data - Repair symbol data
|
|
105
|
-
* @param timestamp - Packet timestamp for ordering
|
|
106
|
-
* @returns Recovered data if FEC decoding succeeded, null otherwise
|
|
107
|
-
*/
|
|
108
|
-
addRepair(sbn, esi, data, timestamp) {
|
|
109
|
-
if (!this.fecDecoder)
|
|
110
|
-
return null;
|
|
111
|
-
try {
|
|
112
|
-
const decoded = this.fecDecoder.add_repair(sbn, esi, data, timestamp);
|
|
113
|
-
if (decoded && decoded.length > 0) {
|
|
114
|
-
const recovered = new Uint8Array(decoded);
|
|
115
|
-
this.options.onRecovered(recovered, BigInt(timestamp));
|
|
116
|
-
return recovered;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
catch (e) {
|
|
120
|
-
console.warn("[FecClient] Repair processing error:", e);
|
|
121
|
-
}
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Process a repair packet with FEC payload ID header
|
|
126
|
-
* Per draft-ramadan-moq-fec-00 Section 6.1
|
|
127
|
-
*
|
|
128
|
-
* @param payload - Repair packet payload (4-byte header + repair symbols)
|
|
129
|
-
* @param timestamp - Packet timestamp
|
|
130
|
-
* @returns Recovered data if FEC decoding succeeded, null otherwise
|
|
131
|
-
*/
|
|
132
|
-
processRepairPacket(payload, timestamp) {
|
|
133
|
-
if (!this.fecDecoder || !this.wasmModule || payload.length < 4)
|
|
134
|
-
return null;
|
|
135
|
-
try {
|
|
136
|
-
const { sbn, esi } = this.wasmModule.parse_fec_payload_id(payload.subarray(0, 4));
|
|
137
|
-
const data = payload.subarray(4);
|
|
138
|
-
return this.addRepair(sbn, esi, data, timestamp);
|
|
139
|
-
}
|
|
140
|
-
catch (e) {
|
|
141
|
-
console.warn("[FecClient] FEC payload parse error:", e);
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Cleanup expired blocks
|
|
147
|
-
* Returns green-fill frame data for expired blocks if green-fill is enabled
|
|
148
|
-
*/
|
|
149
|
-
cleanup() {
|
|
150
|
-
if (!this.fecDecoder)
|
|
151
|
-
return;
|
|
152
|
-
const greenFillData = this.fecDecoder.cleanup(performance.now());
|
|
153
|
-
// greenFillData is a Uint8Array returned by WASM for expired blocks
|
|
154
|
-
if (greenFillData && greenFillData.length > 0 && this.options.greenFillEnabled) {
|
|
155
|
-
// Count green-fills based on data returned
|
|
156
|
-
const greenFillsTriggered = Math.ceil(greenFillData.length / 8);
|
|
157
|
-
if (greenFillsTriggered > 0) {
|
|
158
|
-
this.greenFillCount += greenFillsTriggered;
|
|
159
|
-
this.options.onGreenFill(BigInt(performance.now()));
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Get number of pending blocks
|
|
165
|
-
*/
|
|
166
|
-
getPendingBlocks() {
|
|
167
|
-
return this.fecDecoder?.pending_blocks() ?? 0;
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Get current FEC statistics
|
|
171
|
-
*/
|
|
172
|
-
getStats() {
|
|
173
|
-
const fecStats = this.fecDecoder?.get_stats();
|
|
174
|
-
return {
|
|
175
|
-
sourcePackets: Number(fecStats?.source_packets ?? 0n),
|
|
176
|
-
repairPackets: Number(fecStats?.repair_packets ?? 0n),
|
|
177
|
-
blocksComplete: Number(fecStats?.blocks_complete ?? 0n),
|
|
178
|
-
blocksRecovered: Number(fecStats?.blocks_recovered ?? 0n),
|
|
179
|
-
blocksFailed: Number(fecStats?.blocks_failed ?? 0n),
|
|
180
|
-
recoveryRate: fecStats?.recovery_rate() ?? 100,
|
|
181
|
-
greenFillFrames: this.greenFillCount,
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Get current FEC configuration
|
|
186
|
-
* Returns the configured interleave depth (OTI params set via configure())
|
|
187
|
-
*/
|
|
188
|
-
getConfig() {
|
|
189
|
-
return {
|
|
190
|
-
symbolSize: 1280, // Default, configured via OTI
|
|
191
|
-
sourceBlocks: 1, // Default, configured via OTI
|
|
192
|
-
subBlocks: 1, // Default, configured via OTI
|
|
193
|
-
alignment: 8, // Default, configured via OTI
|
|
194
|
-
interleaveDepth: this.options.interleaveDepth,
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Reset statistics
|
|
199
|
-
*/
|
|
200
|
-
resetStats() {
|
|
201
|
-
this.fecDecoder?.reset_stats();
|
|
202
|
-
this.greenFillCount = 0;
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Dispose of resources
|
|
206
|
-
*/
|
|
207
|
-
dispose() {
|
|
208
|
-
if (this.cleanupInterval) {
|
|
209
|
-
clearInterval(this.cleanupInterval);
|
|
210
|
-
this.cleanupInterval = null;
|
|
211
|
-
}
|
|
212
|
-
this.fecDecoder?.flush();
|
|
213
|
-
this.initialized = false;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Create a shared FEC client instance (singleton pattern)
|
|
218
|
-
*/
|
|
219
|
-
let sharedFecClient = null;
|
|
220
|
-
export async function getSharedFecClient(wasmModule, options) {
|
|
221
|
-
if (!sharedFecClient) {
|
|
222
|
-
sharedFecClient = new FecClient(options);
|
|
223
|
-
await sharedFecClient.init(wasmModule);
|
|
224
|
-
}
|
|
225
|
-
return sharedFecClient;
|
|
226
|
-
}
|
|
227
|
-
export function resetSharedFecClient() {
|
|
228
|
-
if (sharedFecClient) {
|
|
229
|
-
sharedFecClient.dispose();
|
|
230
|
-
sharedFecClient = null;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
//# sourceMappingURL=fec-client.js.map
|
package/dist/fec-client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fec-client.js","sourceRoot":"","sources":["../src/fec-client.ts"],"names":[],"mappings":"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"}
|