@blockcast/mmt-container 0.1.0-main.0399efef1f07

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 (694) hide show
  1. package/README.md +432 -0
  2. package/dist/.build-stamp +0 -0
  3. package/dist/__tests__/test-utils.d.ts +71 -0
  4. package/dist/__tests__/test-utils.d.ts.map +1 -0
  5. package/dist/align.d.ts +152 -0
  6. package/dist/align.d.ts.map +1 -0
  7. package/dist/align.js +88 -0
  8. package/dist/align.js.map +7 -0
  9. package/dist/audio-init-parser.d.ts +66 -0
  10. package/dist/audio-init-parser.d.ts.map +1 -0
  11. package/dist/audio-init-parser.js +118 -0
  12. package/dist/audio-init-parser.js.map +7 -0
  13. package/dist/audio-ring-buffer.d.ts +50 -0
  14. package/dist/audio-ring-buffer.d.ts.map +1 -0
  15. package/dist/audio-ring-buffer.js +93 -0
  16. package/dist/audio-ring-buffer.js.map +7 -0
  17. package/dist/authored-timing.d.ts +32 -0
  18. package/dist/authored-timing.d.ts.map +1 -0
  19. package/dist/authored-timing.js +32 -0
  20. package/dist/authored-timing.js.map +7 -0
  21. package/dist/browser-runtime.js +20087 -0
  22. package/dist/browser-runtime.js.map +7 -0
  23. package/dist/carp-catalog.d.ts +318 -0
  24. package/dist/carp-catalog.d.ts.map +1 -0
  25. package/dist/carp-catalog.js +873 -0
  26. package/dist/carp-catalog.js.map +7 -0
  27. package/dist/catalog-fec-params.d.ts +202 -0
  28. package/dist/catalog-fec-params.d.ts.map +1 -0
  29. package/dist/catalog-fec-params.js +568 -0
  30. package/dist/catalog-fec-params.js.map +7 -0
  31. package/dist/catalog-network-source.d.ts +19 -0
  32. package/dist/catalog-network-source.d.ts.map +1 -0
  33. package/dist/catalog-network-source.js +22 -0
  34. package/dist/catalog-network-source.js.map +7 -0
  35. package/dist/catalog-validator.d.ts +18 -0
  36. package/dist/catalog-validator.d.ts.map +1 -0
  37. package/dist/catalog-validator.js +7747 -0
  38. package/dist/catalog-validator.js.map +7 -0
  39. package/dist/cmaf-block-assembler.d.ts +217 -0
  40. package/dist/cmaf-block-assembler.d.ts.map +1 -0
  41. package/dist/cmaf-block-assembler.js +1769 -0
  42. package/dist/cmaf-block-assembler.js.map +7 -0
  43. package/dist/cmaf-group-batcher.d.ts +38 -0
  44. package/dist/cmaf-group-batcher.d.ts.map +1 -0
  45. package/dist/cmaf-group-batcher.js +195 -0
  46. package/dist/cmaf-group-batcher.js.map +7 -0
  47. package/dist/cmcd-producer.d.ts +104 -0
  48. package/dist/cmcd-producer.d.ts.map +1 -0
  49. package/dist/cmcd-producer.js +207 -0
  50. package/dist/cmcd-producer.js.map +7 -0
  51. package/dist/codec-utils.d.ts +248 -0
  52. package/dist/codec-utils.d.ts.map +1 -0
  53. package/dist/codec-utils.js +1268 -0
  54. package/dist/codec-utils.js.map +7 -0
  55. package/dist/fec-codec.d.ts +32 -0
  56. package/dist/fec-codec.d.ts.map +1 -0
  57. package/dist/fec-codec.js +47 -0
  58. package/dist/fec-codec.js.map +7 -0
  59. package/dist/fec-manager.d.ts +307 -0
  60. package/dist/fec-manager.d.ts.map +1 -0
  61. package/dist/fec-manager.js +1530 -0
  62. package/dist/fec-manager.js.map +7 -0
  63. package/dist/fec-starvation-detector.d.ts +59 -0
  64. package/dist/fec-starvation-detector.d.ts.map +1 -0
  65. package/dist/fec-starvation-detector.js +75 -0
  66. package/dist/fec-starvation-detector.js.map +7 -0
  67. package/dist/fec-worker-setup.d.ts +88 -0
  68. package/dist/fec-worker-setup.d.ts.map +1 -0
  69. package/dist/fec-worker-setup.js +614 -0
  70. package/dist/fec-worker-setup.js.map +7 -0
  71. package/dist/fmp4-completion.d.ts +30 -0
  72. package/dist/fmp4-completion.d.ts.map +1 -0
  73. package/dist/fmp4-completion.js +21 -0
  74. package/dist/fmp4-completion.js.map +7 -0
  75. package/dist/fmp4-reader.d.ts +37 -0
  76. package/dist/fmp4-reader.d.ts.map +1 -0
  77. package/dist/fmp4-reader.js +100 -0
  78. package/dist/fmp4-reader.js.map +7 -0
  79. package/dist/index.d.ts +47 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +380 -0
  82. package/dist/index.js.map +7 -0
  83. package/dist/iso-bmff-timing.d.ts +78 -0
  84. package/dist/iso-bmff-timing.d.ts.map +1 -0
  85. package/dist/iso-bmff-timing.js +618 -0
  86. package/dist/iso-bmff-timing.js.map +7 -0
  87. package/dist/loc.d.ts +68 -0
  88. package/dist/loc.d.ts.map +1 -0
  89. package/dist/loc.js +143 -0
  90. package/dist/loc.js.map +7 -0
  91. package/dist/manifest-auth-plan.d.ts +30 -0
  92. package/dist/manifest-auth-plan.d.ts.map +1 -0
  93. package/dist/manifest-auth-plan.js +1285 -0
  94. package/dist/manifest-auth-plan.js.map +7 -0
  95. package/dist/media-router.d.ts +251 -0
  96. package/dist/media-router.d.ts.map +1 -0
  97. package/dist/media-router.js +624 -0
  98. package/dist/media-router.js.map +7 -0
  99. package/dist/mfu-reassembler.d.ts +396 -0
  100. package/dist/mfu-reassembler.d.ts.map +1 -0
  101. package/dist/mfu-reassembler.js +3085 -0
  102. package/dist/mfu-reassembler.js.map +7 -0
  103. package/dist/mfu-reassembly-policy.d.ts +24 -0
  104. package/dist/mfu-reassembly-policy.d.ts.map +1 -0
  105. package/dist/mfu-reassembly-policy.js +99 -0
  106. package/dist/mfu-reassembly-policy.js.map +7 -0
  107. package/dist/mmtp-container-parser.d.ts +434 -0
  108. package/dist/mmtp-container-parser.d.ts.map +1 -0
  109. package/dist/mmtp-container-parser.js +6164 -0
  110. package/dist/mmtp-container-parser.js.map +7 -0
  111. package/dist/mmtp-container-parser.no-modules.js +8999 -0
  112. package/dist/mmtp-container-parser.no-modules.js.map +7 -0
  113. package/dist/mmtp-decode-pipeline.d.ts +132 -0
  114. package/dist/mmtp-decode-pipeline.d.ts.map +1 -0
  115. package/dist/mmtp-decode-pipeline.js +6413 -0
  116. package/dist/mmtp-decode-pipeline.js.map +7 -0
  117. package/dist/mmtp-router.d.ts +390 -0
  118. package/dist/mmtp-router.d.ts.map +1 -0
  119. package/dist/mmtp-router.js +9242 -0
  120. package/dist/mmtp-router.js.map +7 -0
  121. package/dist/mmtp-to-cmaf.d.ts +181 -0
  122. package/dist/mmtp-to-cmaf.d.ts.map +1 -0
  123. package/dist/mmtp-to-cmaf.js +802 -0
  124. package/dist/mmtp-to-cmaf.js.map +7 -0
  125. package/dist/multicast-auth-catalog.d.ts +115 -0
  126. package/dist/multicast-auth-catalog.d.ts.map +1 -0
  127. package/dist/multicast-auth-catalog.js +202 -0
  128. package/dist/multicast-auth-catalog.js.map +7 -0
  129. package/dist/multicast-input.d.ts +107 -0
  130. package/dist/multicast-input.d.ts.map +1 -0
  131. package/dist/multicast-input.js +256 -0
  132. package/dist/multicast-input.js.map +7 -0
  133. package/dist/multicast-manager.d.ts +369 -0
  134. package/dist/multicast-manager.d.ts.map +1 -0
  135. package/dist/multicast-manager.js +13400 -0
  136. package/dist/multicast-manager.js.map +7 -0
  137. package/dist/multicast-transport.d.ts +61 -0
  138. package/dist/multicast-transport.d.ts.map +1 -0
  139. package/dist/multicast-transport.js +1665 -0
  140. package/dist/multicast-transport.js.map +7 -0
  141. package/dist/multicast-unwrap.d.ts +57 -0
  142. package/dist/multicast-unwrap.d.ts.map +1 -0
  143. package/dist/multicast-unwrap.js +384 -0
  144. package/dist/multicast-unwrap.js.map +7 -0
  145. package/dist/no-modules.d.ts +9 -0
  146. package/dist/no-modules.d.ts.map +1 -0
  147. package/dist/no-modules.js +8965 -0
  148. package/dist/no-modules.js.map +7 -0
  149. package/dist/phase14-catalog-override.d.ts +126 -0
  150. package/dist/phase14-catalog-override.d.ts.map +1 -0
  151. package/dist/phase14-catalog-override.js +155 -0
  152. package/dist/phase14-catalog-override.js.map +7 -0
  153. package/dist/repair-fetch.d.ts +58 -0
  154. package/dist/repair-fetch.d.ts.map +1 -0
  155. package/dist/repair-fetch.js +127 -0
  156. package/dist/repair-fetch.js.map +7 -0
  157. package/dist/repair-layers.d.ts +141 -0
  158. package/dist/repair-layers.d.ts.map +1 -0
  159. package/dist/repair-layers.js +303 -0
  160. package/dist/repair-layers.js.map +7 -0
  161. package/dist/sample-combiner.d.ts +212 -0
  162. package/dist/sample-combiner.d.ts.map +1 -0
  163. package/dist/sample-combiner.js +616 -0
  164. package/dist/sample-combiner.js.map +7 -0
  165. package/dist/signaling.d.ts +29 -0
  166. package/dist/signaling.d.ts.map +1 -0
  167. package/dist/signaling.js +232 -0
  168. package/dist/signaling.js.map +7 -0
  169. package/dist/source-auth.d.ts +2 -0
  170. package/dist/source-auth.d.ts.map +1 -0
  171. package/dist/source-auth.js +1238 -0
  172. package/dist/source-auth.js.map +7 -0
  173. package/dist/switching-set-alignment.d.ts +61 -0
  174. package/dist/switching-set-alignment.d.ts.map +1 -0
  175. package/dist/switching-set-alignment.js +85 -0
  176. package/dist/switching-set-alignment.js.map +7 -0
  177. package/dist/timestamp-codec.d.ts +34 -0
  178. package/dist/timestamp-codec.d.ts.map +1 -0
  179. package/dist/timestamp-codec.js +456 -0
  180. package/dist/timestamp-codec.js.map +7 -0
  181. package/dist/track-pipeline-setup.d.ts +72 -0
  182. package/dist/track-pipeline-setup.d.ts.map +1 -0
  183. package/dist/track-pipeline-setup.js +306 -0
  184. package/dist/track-pipeline-setup.js.map +7 -0
  185. package/dist/track-pipeline.d.ts +121 -0
  186. package/dist/track-pipeline.d.ts.map +1 -0
  187. package/dist/track-pipeline.js +229 -0
  188. package/dist/track-pipeline.js.map +7 -0
  189. package/dist/track-session.d.ts +398 -0
  190. package/dist/track-session.d.ts.map +1 -0
  191. package/dist/track-session.js +767 -0
  192. package/dist/track-session.js.map +7 -0
  193. package/dist/transport-pool.d.ts +69 -0
  194. package/dist/transport-pool.d.ts.map +1 -0
  195. package/dist/transport-pool.js +88 -0
  196. package/dist/transport-pool.js.map +7 -0
  197. package/dist/wasm-mfu-reassembler.d.ts +92 -0
  198. package/dist/wasm-mfu-reassembler.d.ts.map +1 -0
  199. package/dist/wasm-mfu-reassembler.js +2139 -0
  200. package/dist/wasm-mfu-reassembler.js.map +7 -0
  201. package/dist/wasm-mmtp-container-parser.d.ts +10 -0
  202. package/dist/wasm-mmtp-container-parser.d.ts.map +1 -0
  203. package/dist/wasm-mmtp-container-parser.js +6418 -0
  204. package/dist/wasm-mmtp-container-parser.js.map +7 -0
  205. package/node_modules/@blockcast/fec-worker/README.md +213 -0
  206. package/node_modules/@blockcast/fec-worker/dist/.build-stamp +0 -0
  207. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts +87 -0
  208. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts.map +1 -0
  209. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js +279 -0
  210. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js.map +1 -0
  211. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts +252 -0
  212. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts.map +1 -0
  213. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js +11 -0
  214. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js.map +1 -0
  215. package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts +14 -0
  216. package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts.map +1 -0
  217. package/node_modules/@blockcast/fec-worker/dist/fec-worker.js +565 -0
  218. package/node_modules/@blockcast/fec-worker/dist/fec-worker.js.map +7 -0
  219. package/node_modules/@blockcast/fec-worker/dist/index.d.ts +10 -0
  220. package/node_modules/@blockcast/fec-worker/dist/index.d.ts.map +1 -0
  221. package/node_modules/@blockcast/fec-worker/dist/index.js +8 -0
  222. package/node_modules/@blockcast/fec-worker/dist/index.js.map +1 -0
  223. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts +20 -0
  224. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts.map +1 -0
  225. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js +349 -0
  226. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js.map +7 -0
  227. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts +104 -0
  228. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts.map +1 -0
  229. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js +181 -0
  230. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js.map +1 -0
  231. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts +179 -0
  232. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts.map +1 -0
  233. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js +47 -0
  234. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js.map +1 -0
  235. package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts +9 -0
  236. package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts.map +1 -0
  237. package/node_modules/@blockcast/fec-worker/dist/transfer.js +13 -0
  238. package/node_modules/@blockcast/fec-worker/dist/transfer.js.map +1 -0
  239. package/node_modules/@blockcast/fec-worker/package.json +59 -0
  240. package/node_modules/@blockcast/fec-worker/src/fec-worker-client.ts +319 -0
  241. package/node_modules/@blockcast/fec-worker/src/fec-worker-types.ts +268 -0
  242. package/node_modules/@blockcast/fec-worker/src/fec-worker.ts +1048 -0
  243. package/node_modules/@blockcast/fec-worker/src/index.ts +32 -0
  244. package/node_modules/@blockcast/fec-worker/src/shred-fec-worker.ts +558 -0
  245. package/node_modules/@blockcast/fec-worker/src/shred-worker-client.ts +222 -0
  246. package/node_modules/@blockcast/fec-worker/src/shred-worker-types.ts +194 -0
  247. package/node_modules/@blockcast/fec-worker/src/transfer.ts +12 -0
  248. package/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
  249. package/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
  250. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
  251. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
  252. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
  253. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
  254. package/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
  255. package/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
  256. package/node_modules/@blockcast/mmt-base/README.md +120 -0
  257. package/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
  258. package/node_modules/@blockcast/mmt-base/dist/index.d.ts +2 -0
  259. package/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
  260. package/node_modules/@blockcast/mmt-base/dist/index.js +2 -0
  261. package/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
  262. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +276 -0
  263. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
  264. package/node_modules/@blockcast/mmt-base/dist/mmtp.js +645 -0
  265. package/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
  266. package/node_modules/@blockcast/mmt-base/package.json +49 -0
  267. package/node_modules/@blockcast/mmt-base/src/index.ts +1 -0
  268. package/node_modules/@blockcast/mmt-base/src/mmtp.ts +899 -0
  269. package/node_modules/@blockcast/mmt-fec/README.md +270 -0
  270. package/node_modules/@blockcast/mmt-fec/dist/.build-stamp +0 -0
  271. package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts +82 -0
  272. package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts.map +1 -0
  273. package/node_modules/@blockcast/mmt-fec/dist/block-manager.js +296 -0
  274. package/node_modules/@blockcast/mmt-fec/dist/block-manager.js.map +1 -0
  275. package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts +72 -0
  276. package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts.map +1 -0
  277. package/node_modules/@blockcast/mmt-fec/dist/block-processor.js +192 -0
  278. package/node_modules/@blockcast/mmt-fec/dist/block-processor.js.map +1 -0
  279. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts +46 -0
  280. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts.map +1 -0
  281. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js +96 -0
  282. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js.map +1 -0
  283. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts +33 -0
  284. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts.map +1 -0
  285. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js +57 -0
  286. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js.map +1 -0
  287. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts +185 -0
  288. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts.map +1 -0
  289. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js +273 -0
  290. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js.map +1 -0
  291. package/node_modules/@blockcast/mmt-fec/dist/index.d.ts +22 -0
  292. package/node_modules/@blockcast/mmt-fec/dist/index.d.ts.map +1 -0
  293. package/node_modules/@blockcast/mmt-fec/dist/index.js +22 -0
  294. package/node_modules/@blockcast/mmt-fec/dist/index.js.map +1 -0
  295. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts +20 -0
  296. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts.map +1 -0
  297. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js +28 -0
  298. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js.map +1 -0
  299. package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts +172 -0
  300. package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts.map +1 -0
  301. package/node_modules/@blockcast/mmt-fec/dist/oti.js +254 -0
  302. package/node_modules/@blockcast/mmt-fec/dist/oti.js.map +1 -0
  303. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts +41 -0
  304. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts.map +1 -0
  305. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js +81 -0
  306. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js.map +1 -0
  307. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
  308. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
  309. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
  310. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
  311. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
  312. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
  313. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
  314. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
  315. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/README.md +120 -0
  316. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
  317. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts +2 -0
  318. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
  319. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js +2 -0
  320. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
  321. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +276 -0
  322. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
  323. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js +645 -0
  324. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
  325. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/package.json +49 -0
  326. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/index.ts +1 -0
  327. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/mmtp.ts +899 -0
  328. package/node_modules/@blockcast/mmt-fec/package.json +79 -0
  329. package/node_modules/@blockcast/mmt-fec/src/block-manager.ts +371 -0
  330. package/node_modules/@blockcast/mmt-fec/src/block-processor.ts +277 -0
  331. package/node_modules/@blockcast/mmt-fec/src/cmaf-recovery.ts +127 -0
  332. package/node_modules/@blockcast/mmt-fec/src/cmaf-symbols.ts +68 -0
  333. package/node_modules/@blockcast/mmt-fec/src/fec-block-mapper.ts +332 -0
  334. package/node_modules/@blockcast/mmt-fec/src/index.ts +77 -0
  335. package/node_modules/@blockcast/mmt-fec/src/loc-symbols.ts +34 -0
  336. package/node_modules/@blockcast/mmt-fec/src/oti.ts +317 -0
  337. package/node_modules/@blockcast/mmt-fec/src/reorder-buffer.ts +101 -0
  338. package/node_modules/@blockcast/mmt-manifest-verify/dist/.build-stamp +0 -0
  339. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts +28 -0
  340. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts.map +1 -0
  341. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js +128 -0
  342. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js.map +1 -0
  343. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts +4 -0
  344. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts.map +1 -0
  345. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js +4 -0
  346. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js.map +1 -0
  347. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts +37 -0
  348. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts.map +1 -0
  349. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js +179 -0
  350. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js.map +1 -0
  351. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts +99 -0
  352. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts.map +1 -0
  353. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js +492 -0
  354. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js.map +1 -0
  355. package/node_modules/@blockcast/mmt-manifest-verify/package.json +45 -0
  356. package/node_modules/@blockcast/mmt-manifest-verify/src/admission.ts +171 -0
  357. package/node_modules/@blockcast/mmt-manifest-verify/src/index.ts +3 -0
  358. package/node_modules/@blockcast/mmt-manifest-verify/src/source-auth.ts +230 -0
  359. package/node_modules/@blockcast/mmt-manifest-verify/src/verifier.ts +669 -0
  360. package/node_modules/@noble/hashes/LICENSE +21 -0
  361. package/node_modules/@noble/hashes/README.md +521 -0
  362. package/node_modules/@noble/hashes/_assert.d.ts +17 -0
  363. package/node_modules/@noble/hashes/_assert.d.ts.map +1 -0
  364. package/node_modules/@noble/hashes/_assert.js +18 -0
  365. package/node_modules/@noble/hashes/_assert.js.map +1 -0
  366. package/node_modules/@noble/hashes/_blake.d.ts +14 -0
  367. package/node_modules/@noble/hashes/_blake.d.ts.map +1 -0
  368. package/node_modules/@noble/hashes/_blake.js +50 -0
  369. package/node_modules/@noble/hashes/_blake.js.map +1 -0
  370. package/node_modules/@noble/hashes/_md.d.ts +51 -0
  371. package/node_modules/@noble/hashes/_md.d.ts.map +1 -0
  372. package/node_modules/@noble/hashes/_md.js +162 -0
  373. package/node_modules/@noble/hashes/_md.js.map +1 -0
  374. package/node_modules/@noble/hashes/_u64.d.ts +55 -0
  375. package/node_modules/@noble/hashes/_u64.d.ts.map +1 -0
  376. package/node_modules/@noble/hashes/_u64.js +90 -0
  377. package/node_modules/@noble/hashes/_u64.js.map +1 -0
  378. package/node_modules/@noble/hashes/argon2.d.ts +32 -0
  379. package/node_modules/@noble/hashes/argon2.d.ts.map +1 -0
  380. package/node_modules/@noble/hashes/argon2.js +401 -0
  381. package/node_modules/@noble/hashes/argon2.js.map +1 -0
  382. package/node_modules/@noble/hashes/blake1.d.ts +106 -0
  383. package/node_modules/@noble/hashes/blake1.d.ts.map +1 -0
  384. package/node_modules/@noble/hashes/blake1.js +459 -0
  385. package/node_modules/@noble/hashes/blake1.js.map +1 -0
  386. package/node_modules/@noble/hashes/blake2.d.ts +116 -0
  387. package/node_modules/@noble/hashes/blake2.d.ts.map +1 -0
  388. package/node_modules/@noble/hashes/blake2.js +420 -0
  389. package/node_modules/@noble/hashes/blake2.js.map +1 -0
  390. package/node_modules/@noble/hashes/blake2b.d.ts +11 -0
  391. package/node_modules/@noble/hashes/blake2b.d.ts.map +1 -0
  392. package/node_modules/@noble/hashes/blake2b.js +14 -0
  393. package/node_modules/@noble/hashes/blake2b.js.map +1 -0
  394. package/node_modules/@noble/hashes/blake2s.d.ts +20 -0
  395. package/node_modules/@noble/hashes/blake2s.d.ts.map +1 -0
  396. package/node_modules/@noble/hashes/blake2s.js +24 -0
  397. package/node_modules/@noble/hashes/blake2s.js.map +1 -0
  398. package/node_modules/@noble/hashes/blake3.d.ts +54 -0
  399. package/node_modules/@noble/hashes/blake3.d.ts.map +1 -0
  400. package/node_modules/@noble/hashes/blake3.js +255 -0
  401. package/node_modules/@noble/hashes/blake3.js.map +1 -0
  402. package/node_modules/@noble/hashes/crypto.d.ts +2 -0
  403. package/node_modules/@noble/hashes/crypto.d.ts.map +1 -0
  404. package/node_modules/@noble/hashes/crypto.js +5 -0
  405. package/node_modules/@noble/hashes/crypto.js.map +1 -0
  406. package/node_modules/@noble/hashes/cryptoNode.d.ts +2 -0
  407. package/node_modules/@noble/hashes/cryptoNode.d.ts.map +1 -0
  408. package/node_modules/@noble/hashes/cryptoNode.js +18 -0
  409. package/node_modules/@noble/hashes/cryptoNode.js.map +1 -0
  410. package/node_modules/@noble/hashes/eskdf.d.ts +47 -0
  411. package/node_modules/@noble/hashes/eskdf.d.ts.map +1 -0
  412. package/node_modules/@noble/hashes/eskdf.js +166 -0
  413. package/node_modules/@noble/hashes/eskdf.js.map +1 -0
  414. package/node_modules/@noble/hashes/esm/_assert.d.ts +17 -0
  415. package/node_modules/@noble/hashes/esm/_assert.d.ts.map +1 -0
  416. package/node_modules/@noble/hashes/esm/_assert.js +15 -0
  417. package/node_modules/@noble/hashes/esm/_assert.js.map +1 -0
  418. package/node_modules/@noble/hashes/esm/_blake.d.ts +14 -0
  419. package/node_modules/@noble/hashes/esm/_blake.d.ts.map +1 -0
  420. package/node_modules/@noble/hashes/esm/_blake.js +45 -0
  421. package/node_modules/@noble/hashes/esm/_blake.js.map +1 -0
  422. package/node_modules/@noble/hashes/esm/_md.d.ts +51 -0
  423. package/node_modules/@noble/hashes/esm/_md.d.ts.map +1 -0
  424. package/node_modules/@noble/hashes/esm/_md.js +155 -0
  425. package/node_modules/@noble/hashes/esm/_md.js.map +1 -0
  426. package/node_modules/@noble/hashes/esm/_u64.d.ts +55 -0
  427. package/node_modules/@noble/hashes/esm/_u64.d.ts.map +1 -0
  428. package/node_modules/@noble/hashes/esm/_u64.js +67 -0
  429. package/node_modules/@noble/hashes/esm/_u64.js.map +1 -0
  430. package/node_modules/@noble/hashes/esm/argon2.d.ts +32 -0
  431. package/node_modules/@noble/hashes/esm/argon2.d.ts.map +1 -0
  432. package/node_modules/@noble/hashes/esm/argon2.js +392 -0
  433. package/node_modules/@noble/hashes/esm/argon2.js.map +1 -0
  434. package/node_modules/@noble/hashes/esm/blake1.d.ts +106 -0
  435. package/node_modules/@noble/hashes/esm/blake1.d.ts.map +1 -0
  436. package/node_modules/@noble/hashes/esm/blake1.js +452 -0
  437. package/node_modules/@noble/hashes/esm/blake1.js.map +1 -0
  438. package/node_modules/@noble/hashes/esm/blake2.d.ts +116 -0
  439. package/node_modules/@noble/hashes/esm/blake2.d.ts.map +1 -0
  440. package/node_modules/@noble/hashes/esm/blake2.js +413 -0
  441. package/node_modules/@noble/hashes/esm/blake2.js.map +1 -0
  442. package/node_modules/@noble/hashes/esm/blake2b.d.ts +11 -0
  443. package/node_modules/@noble/hashes/esm/blake2b.d.ts.map +1 -0
  444. package/node_modules/@noble/hashes/esm/blake2b.js +11 -0
  445. package/node_modules/@noble/hashes/esm/blake2b.js.map +1 -0
  446. package/node_modules/@noble/hashes/esm/blake2s.d.ts +20 -0
  447. package/node_modules/@noble/hashes/esm/blake2s.d.ts.map +1 -0
  448. package/node_modules/@noble/hashes/esm/blake2s.js +21 -0
  449. package/node_modules/@noble/hashes/esm/blake2s.js.map +1 -0
  450. package/node_modules/@noble/hashes/esm/blake3.d.ts +54 -0
  451. package/node_modules/@noble/hashes/esm/blake3.d.ts.map +1 -0
  452. package/node_modules/@noble/hashes/esm/blake3.js +251 -0
  453. package/node_modules/@noble/hashes/esm/blake3.js.map +1 -0
  454. package/node_modules/@noble/hashes/esm/crypto.d.ts +2 -0
  455. package/node_modules/@noble/hashes/esm/crypto.d.ts.map +1 -0
  456. package/node_modules/@noble/hashes/esm/crypto.js +2 -0
  457. package/node_modules/@noble/hashes/esm/crypto.js.map +1 -0
  458. package/node_modules/@noble/hashes/esm/cryptoNode.d.ts +2 -0
  459. package/node_modules/@noble/hashes/esm/cryptoNode.d.ts.map +1 -0
  460. package/node_modules/@noble/hashes/esm/cryptoNode.js +15 -0
  461. package/node_modules/@noble/hashes/esm/cryptoNode.js.map +1 -0
  462. package/node_modules/@noble/hashes/esm/eskdf.d.ts +47 -0
  463. package/node_modules/@noble/hashes/esm/eskdf.d.ts.map +1 -0
  464. package/node_modules/@noble/hashes/esm/eskdf.js +160 -0
  465. package/node_modules/@noble/hashes/esm/eskdf.js.map +1 -0
  466. package/node_modules/@noble/hashes/esm/hkdf.d.ts +36 -0
  467. package/node_modules/@noble/hashes/esm/hkdf.d.ts.map +1 -0
  468. package/node_modules/@noble/hashes/esm/hkdf.js +82 -0
  469. package/node_modules/@noble/hashes/esm/hkdf.js.map +1 -0
  470. package/node_modules/@noble/hashes/esm/hmac.d.ts +35 -0
  471. package/node_modules/@noble/hashes/esm/hmac.d.ts.map +1 -0
  472. package/node_modules/@noble/hashes/esm/hmac.js +86 -0
  473. package/node_modules/@noble/hashes/esm/hmac.js.map +1 -0
  474. package/node_modules/@noble/hashes/esm/index.d.ts +2 -0
  475. package/node_modules/@noble/hashes/esm/index.d.ts.map +1 -0
  476. package/node_modules/@noble/hashes/esm/index.js +33 -0
  477. package/node_modules/@noble/hashes/esm/index.js.map +1 -0
  478. package/node_modules/@noble/hashes/esm/legacy.d.ts +71 -0
  479. package/node_modules/@noble/hashes/esm/legacy.d.ts.map +1 -0
  480. package/node_modules/@noble/hashes/esm/legacy.js +281 -0
  481. package/node_modules/@noble/hashes/esm/legacy.js.map +1 -0
  482. package/node_modules/@noble/hashes/esm/package.json +10 -0
  483. package/node_modules/@noble/hashes/esm/pbkdf2.d.ts +23 -0
  484. package/node_modules/@noble/hashes/esm/pbkdf2.d.ts.map +1 -0
  485. package/node_modules/@noble/hashes/esm/pbkdf2.js +97 -0
  486. package/node_modules/@noble/hashes/esm/pbkdf2.js.map +1 -0
  487. package/node_modules/@noble/hashes/esm/ripemd160.d.ts +13 -0
  488. package/node_modules/@noble/hashes/esm/ripemd160.d.ts.map +1 -0
  489. package/node_modules/@noble/hashes/esm/ripemd160.js +13 -0
  490. package/node_modules/@noble/hashes/esm/ripemd160.js.map +1 -0
  491. package/node_modules/@noble/hashes/esm/scrypt.d.ts +34 -0
  492. package/node_modules/@noble/hashes/esm/scrypt.d.ts.map +1 -0
  493. package/node_modules/@noble/hashes/esm/scrypt.js +228 -0
  494. package/node_modules/@noble/hashes/esm/scrypt.js.map +1 -0
  495. package/node_modules/@noble/hashes/esm/sha1.d.ts +11 -0
  496. package/node_modules/@noble/hashes/esm/sha1.d.ts.map +1 -0
  497. package/node_modules/@noble/hashes/esm/sha1.js +11 -0
  498. package/node_modules/@noble/hashes/esm/sha1.js.map +1 -0
  499. package/node_modules/@noble/hashes/esm/sha2.d.ts +159 -0
  500. package/node_modules/@noble/hashes/esm/sha2.d.ts.map +1 -0
  501. package/node_modules/@noble/hashes/esm/sha2.js +375 -0
  502. package/node_modules/@noble/hashes/esm/sha2.js.map +1 -0
  503. package/node_modules/@noble/hashes/esm/sha256.d.ts +20 -0
  504. package/node_modules/@noble/hashes/esm/sha256.d.ts.map +1 -0
  505. package/node_modules/@noble/hashes/esm/sha256.js +20 -0
  506. package/node_modules/@noble/hashes/esm/sha256.js.map +1 -0
  507. package/node_modules/@noble/hashes/esm/sha3-addons.d.ts +142 -0
  508. package/node_modules/@noble/hashes/esm/sha3-addons.d.ts.map +1 -0
  509. package/node_modules/@noble/hashes/esm/sha3-addons.js +393 -0
  510. package/node_modules/@noble/hashes/esm/sha3-addons.js.map +1 -0
  511. package/node_modules/@noble/hashes/esm/sha3.d.ts +53 -0
  512. package/node_modules/@noble/hashes/esm/sha3.d.ts.map +1 -0
  513. package/node_modules/@noble/hashes/esm/sha3.js +234 -0
  514. package/node_modules/@noble/hashes/esm/sha3.js.map +1 -0
  515. package/node_modules/@noble/hashes/esm/sha512.d.ts +26 -0
  516. package/node_modules/@noble/hashes/esm/sha512.d.ts.map +1 -0
  517. package/node_modules/@noble/hashes/esm/sha512.js +26 -0
  518. package/node_modules/@noble/hashes/esm/sha512.js.map +1 -0
  519. package/node_modules/@noble/hashes/esm/utils.d.ts +161 -0
  520. package/node_modules/@noble/hashes/esm/utils.d.ts.map +1 -0
  521. package/node_modules/@noble/hashes/esm/utils.js +281 -0
  522. package/node_modules/@noble/hashes/esm/utils.js.map +1 -0
  523. package/node_modules/@noble/hashes/hkdf.d.ts +36 -0
  524. package/node_modules/@noble/hashes/hkdf.d.ts.map +1 -0
  525. package/node_modules/@noble/hashes/hkdf.js +88 -0
  526. package/node_modules/@noble/hashes/hkdf.js.map +1 -0
  527. package/node_modules/@noble/hashes/hmac.d.ts +35 -0
  528. package/node_modules/@noble/hashes/hmac.d.ts.map +1 -0
  529. package/node_modules/@noble/hashes/hmac.js +91 -0
  530. package/node_modules/@noble/hashes/hmac.js.map +1 -0
  531. package/node_modules/@noble/hashes/index.d.ts +1 -0
  532. package/node_modules/@noble/hashes/index.d.ts.map +1 -0
  533. package/node_modules/@noble/hashes/index.js +33 -0
  534. package/node_modules/@noble/hashes/index.js.map +1 -0
  535. package/node_modules/@noble/hashes/legacy.d.ts +71 -0
  536. package/node_modules/@noble/hashes/legacy.d.ts.map +1 -0
  537. package/node_modules/@noble/hashes/legacy.js +287 -0
  538. package/node_modules/@noble/hashes/legacy.js.map +1 -0
  539. package/node_modules/@noble/hashes/package.json +266 -0
  540. package/node_modules/@noble/hashes/pbkdf2.d.ts +23 -0
  541. package/node_modules/@noble/hashes/pbkdf2.d.ts.map +1 -0
  542. package/node_modules/@noble/hashes/pbkdf2.js +101 -0
  543. package/node_modules/@noble/hashes/pbkdf2.js.map +1 -0
  544. package/node_modules/@noble/hashes/ripemd160.d.ts +13 -0
  545. package/node_modules/@noble/hashes/ripemd160.d.ts.map +1 -0
  546. package/node_modules/@noble/hashes/ripemd160.js +16 -0
  547. package/node_modules/@noble/hashes/ripemd160.js.map +1 -0
  548. package/node_modules/@noble/hashes/scrypt.d.ts +34 -0
  549. package/node_modules/@noble/hashes/scrypt.d.ts.map +1 -0
  550. package/node_modules/@noble/hashes/scrypt.js +232 -0
  551. package/node_modules/@noble/hashes/scrypt.js.map +1 -0
  552. package/node_modules/@noble/hashes/sha1.d.ts +11 -0
  553. package/node_modules/@noble/hashes/sha1.d.ts.map +1 -0
  554. package/node_modules/@noble/hashes/sha1.js +14 -0
  555. package/node_modules/@noble/hashes/sha1.js.map +1 -0
  556. package/node_modules/@noble/hashes/sha2.d.ts +159 -0
  557. package/node_modules/@noble/hashes/sha2.d.ts.map +1 -0
  558. package/node_modules/@noble/hashes/sha2.js +384 -0
  559. package/node_modules/@noble/hashes/sha2.js.map +1 -0
  560. package/node_modules/@noble/hashes/sha256.d.ts +20 -0
  561. package/node_modules/@noble/hashes/sha256.d.ts.map +1 -0
  562. package/node_modules/@noble/hashes/sha256.js +23 -0
  563. package/node_modules/@noble/hashes/sha256.js.map +1 -0
  564. package/node_modules/@noble/hashes/sha3-addons.d.ts +142 -0
  565. package/node_modules/@noble/hashes/sha3-addons.d.ts.map +1 -0
  566. package/node_modules/@noble/hashes/sha3-addons.js +402 -0
  567. package/node_modules/@noble/hashes/sha3-addons.js.map +1 -0
  568. package/node_modules/@noble/hashes/sha3.d.ts +53 -0
  569. package/node_modules/@noble/hashes/sha3.d.ts.map +1 -0
  570. package/node_modules/@noble/hashes/sha3.js +239 -0
  571. package/node_modules/@noble/hashes/sha3.js.map +1 -0
  572. package/node_modules/@noble/hashes/sha512.d.ts +26 -0
  573. package/node_modules/@noble/hashes/sha512.d.ts.map +1 -0
  574. package/node_modules/@noble/hashes/sha512.js +29 -0
  575. package/node_modules/@noble/hashes/sha512.js.map +1 -0
  576. package/node_modules/@noble/hashes/src/_assert.ts +22 -0
  577. package/node_modules/@noble/hashes/src/_blake.ts +50 -0
  578. package/node_modules/@noble/hashes/src/_md.ts +176 -0
  579. package/node_modules/@noble/hashes/src/_u64.ts +91 -0
  580. package/node_modules/@noble/hashes/src/argon2.ts +497 -0
  581. package/node_modules/@noble/hashes/src/blake1.ts +534 -0
  582. package/node_modules/@noble/hashes/src/blake2.ts +486 -0
  583. package/node_modules/@noble/hashes/src/blake2b.ts +10 -0
  584. package/node_modules/@noble/hashes/src/blake2s.ts +20 -0
  585. package/node_modules/@noble/hashes/src/blake3.ts +272 -0
  586. package/node_modules/@noble/hashes/src/crypto.ts +9 -0
  587. package/node_modules/@noble/hashes/src/cryptoNode.ts +15 -0
  588. package/node_modules/@noble/hashes/src/eskdf.ts +187 -0
  589. package/node_modules/@noble/hashes/src/hkdf.ts +88 -0
  590. package/node_modules/@noble/hashes/src/hmac.ts +94 -0
  591. package/node_modules/@noble/hashes/src/index.ts +31 -0
  592. package/node_modules/@noble/hashes/src/legacy.ts +293 -0
  593. package/node_modules/@noble/hashes/src/pbkdf2.ts +122 -0
  594. package/node_modules/@noble/hashes/src/ripemd160.ts +12 -0
  595. package/node_modules/@noble/hashes/src/scrypt.ts +257 -0
  596. package/node_modules/@noble/hashes/src/sha1.ts +10 -0
  597. package/node_modules/@noble/hashes/src/sha2.ts +402 -0
  598. package/node_modules/@noble/hashes/src/sha256.ts +24 -0
  599. package/node_modules/@noble/hashes/src/sha3-addons.ts +499 -0
  600. package/node_modules/@noble/hashes/src/sha3.ts +258 -0
  601. package/node_modules/@noble/hashes/src/sha512.ts +34 -0
  602. package/node_modules/@noble/hashes/src/utils.ts +395 -0
  603. package/node_modules/@noble/hashes/utils.d.ts +161 -0
  604. package/node_modules/@noble/hashes/utils.d.ts.map +1 -0
  605. package/node_modules/@noble/hashes/utils.js +313 -0
  606. package/node_modules/@noble/hashes/utils.js.map +1 -0
  607. package/package.json +203 -0
  608. package/schemas/catalog.schema.json +360 -0
  609. package/src/align.ts +239 -0
  610. package/src/audio-init-parser.ts +189 -0
  611. package/src/audio-ring-buffer.ts +120 -0
  612. package/src/authored-timing.ts +63 -0
  613. package/src/carp-catalog.ts +845 -0
  614. package/src/catalog-fec-params.ts +535 -0
  615. package/src/catalog-network-source.ts +49 -0
  616. package/src/catalog-validator.ts +34 -0
  617. package/src/cmaf-block-assembler.ts +1167 -0
  618. package/src/cmaf-group-batcher.ts +104 -0
  619. package/src/cmcd-producer.ts +334 -0
  620. package/src/codec-utils.ts +1611 -0
  621. package/src/fec-codec.ts +61 -0
  622. package/src/fec-manager.ts +2081 -0
  623. package/src/fec-starvation-detector.ts +128 -0
  624. package/src/fec-worker-setup.ts +213 -0
  625. package/src/fmp4-completion.ts +47 -0
  626. package/src/fmp4-reader.ts +112 -0
  627. package/src/index.ts +486 -0
  628. package/src/iso-bmff-timing.ts +813 -0
  629. package/src/loc.ts +181 -0
  630. package/src/manifest-auth-plan.ts +107 -0
  631. package/src/media-router.ts +795 -0
  632. package/src/mfu-reassembler.ts +3741 -0
  633. package/src/mfu-reassembly-policy.ts +134 -0
  634. package/src/mmtp-container-parser.ts +1836 -0
  635. package/src/mmtp-decode-pipeline.ts +389 -0
  636. package/src/mmtp-router.ts +3136 -0
  637. package/src/mmtp-to-cmaf.ts +1024 -0
  638. package/src/multicast-auth-catalog.ts +340 -0
  639. package/src/multicast-input.ts +439 -0
  640. package/src/multicast-manager.ts +1720 -0
  641. package/src/multicast-transport.ts +321 -0
  642. package/src/multicast-unwrap.ts +132 -0
  643. package/src/no-modules.ts +20 -0
  644. package/src/phase14-catalog-override.ts +336 -0
  645. package/src/repair-fetch.ts +238 -0
  646. package/src/repair-layers.ts +490 -0
  647. package/src/sample-combiner.ts +938 -0
  648. package/src/signaling.ts +78 -0
  649. package/src/source-auth.ts +1 -0
  650. package/src/switching-set-alignment.ts +109 -0
  651. package/src/timestamp-codec.ts +265 -0
  652. package/src/track-pipeline-setup.ts +189 -0
  653. package/src/track-pipeline.ts +332 -0
  654. package/src/track-session.ts +994 -0
  655. package/src/transport-pool.ts +128 -0
  656. package/src/wasm-mfu-reassembler.ts +389 -0
  657. package/src/wasm-mmtp-container-parser.ts +23 -0
  658. package/test-vectors/align.json +199 -0
  659. package/test-vectors/catalog/README.md +40 -0
  660. package/test-vectors/catalog/negative/fec-enhancement-repair-removed.json +27 -0
  661. package/test-vectors/catalog/negative/fec-repair-layer-geometry.json +32 -0
  662. package/test-vectors/catalog/negative/fec-repair-layer-missing-symbols.json +30 -0
  663. package/test-vectors/catalog/negative/fec-repair-multiple-depends.json +31 -0
  664. package/test-vectors/catalog/negative/fec-repair-overlay-with-layer.json +33 -0
  665. package/test-vectors/catalog/negative/fec-repair-priority-out-of-band.json +23 -0
  666. package/test-vectors/catalog/negative/fec-repair-source-symbols-without-scope.json +32 -0
  667. package/test-vectors/catalog/negative/legacy-selection-params.json +15 -0
  668. package/test-vectors/catalog/negative/media-track-repair-layer.json +16 -0
  669. package/test-vectors/catalog/negative/missing-mmtp-fields.json +12 -0
  670. package/test-vectors/catalog/negative/multicast-auth-padded-key.json +37 -0
  671. package/test-vectors/catalog/negative/multicast-auth-reused-track-format.json +53 -0
  672. package/test-vectors/catalog/negative/multicast-auth-trailing-pad-bits.json +37 -0
  673. package/test-vectors/catalog/negative/multicast-endpoint-missing-protocol-and-source.json +24 -0
  674. package/test-vectors/catalog/negative/network-source-object.json +25 -0
  675. package/test-vectors/catalog/negative/raptorq-source-symbols-over-max.json +23 -0
  676. package/test-vectors/catalog/negative/raptorq-unaligned-symbol.json +26 -0
  677. package/test-vectors/catalog/negative/repair-track-legacy-shape.json +19 -0
  678. package/test-vectors/catalog/negative/track-role-empty.json +16 -0
  679. package/test-vectors/catalog/negative/track-role-non-string.json +16 -0
  680. package/test-vectors/catalog/positive/fec-layered-repair.json +104 -0
  681. package/test-vectors/catalog/positive/fec-multicast.json +51 -0
  682. package/test-vectors/catalog/positive/flat-av.json +30 -0
  683. package/test-vectors/catalog/positive/multicast-auth-rotation.json +55 -0
  684. package/test-vectors/catalog/positive/ticks-and-mixed-timescales.json +39 -0
  685. package/test-vectors/catalog/positive/track-role.json +49 -0
  686. package/test-vectors/catalog/releases/moqcast-native-v16-v1/catalog.json +65 -0
  687. package/test-vectors/catalog/releases/moqcast-native-v16-v1.archive.sha256 +1 -0
  688. package/test-vectors/catalog-multicast-auth-v1.json +26 -0
  689. package/test-vectors/catalog-validation.json +148 -0
  690. package/test-vectors/catalog-validator-public-api.mjs +25 -0
  691. package/test-vectors/generate-source-auth-fixture.mjs +114 -0
  692. package/test-vectors/source-auth-v1.json +61 -0
  693. package/test-vectors/source-contiguity-v1.json +131 -0
  694. package/test-vectors/subsample-placement-v1.json +230 -0
@@ -0,0 +1,2139 @@
1
+ var __typeError = (msg) => {
2
+ throw TypeError(msg);
3
+ };
4
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
5
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
6
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
7
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
8
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
9
+ var __privateWrapper = (obj, member, setter, getter) => ({
10
+ set _(value) {
11
+ __privateSet(obj, member, value, setter);
12
+ },
13
+ get _() {
14
+ return __privateGet(obj, member, getter);
15
+ }
16
+ });
17
+
18
+ // ../mmt-alta-parse/dist/index.js
19
+ var MPU_HEADER_SIZE = 8;
20
+ var MPU_LENGTH_FIELD_SIZE = 2;
21
+ var MPU_HEADER_REMAINDER_SIZE = MPU_HEADER_SIZE - MPU_LENGTH_FIELD_SIZE;
22
+
23
+ // ../mmt-base/dist/mmtp.js
24
+ var MPU_HEADER_SIZE2 = 8;
25
+ var MPU_LENGTH_FIELD_SIZE2 = 2;
26
+ var MPU_HEADER_REMAINDER_SIZE2 = MPU_HEADER_SIZE2 - MPU_LENGTH_FIELD_SIZE2;
27
+
28
+ // src/mfu-reassembler.ts
29
+ var MFU_REASSEMBLY_ERROR_CODES = [
30
+ "invalid-fragment-state",
31
+ "missing-data-unit-identity",
32
+ "missing-packet-sequence",
33
+ "conflicting-data-unit-identity",
34
+ "overlapping-data-unit",
35
+ "fragment-counter-mismatch",
36
+ "data-unit-identity-mismatch",
37
+ "offset-overflow",
38
+ "active-data-unit-limit",
39
+ "incomplete-terminal-fragment",
40
+ "ambiguous-continuation"
41
+ ];
42
+ var mfuReassemblyErrorCodes = new Set(MFU_REASSEMBLY_ERROR_CODES);
43
+ function isMfuReassemblyErrorCode(value) {
44
+ return typeof value === "string" && mfuReassemblyErrorCodes.has(value);
45
+ }
46
+ var MfuReassemblyError = class extends Error {
47
+ constructor(code, message) {
48
+ super(message);
49
+ this.code = code;
50
+ this.name = "MfuReassemblyError";
51
+ }
52
+ };
53
+ if (void 0) {
54
+ const { describe, test, expect, vi } = void 0;
55
+ const expectRejection = (call, code) => {
56
+ let rejection;
57
+ try {
58
+ call();
59
+ } catch (error) {
60
+ rejection = error;
61
+ }
62
+ expect(rejection).toBeInstanceOf(MfuReassemblyError);
63
+ expect(rejection.code).toBe(code);
64
+ };
65
+ const testPacketSequence = (mpu, counter, run = 0) => (mpu * 1e3 + run - counter + 4294967296) % 4294967296;
66
+ describe("MFUReassembler", () => {
67
+ test("should return complete MFU for FI=0", () => {
68
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
69
+ const result = reassembler.addFragment({
70
+ fragmentationIndicator: 0,
71
+ mpuSequenceNumber: 1,
72
+ fragmentCounter: 0,
73
+ itemId: 1,
74
+ data: new Uint8Array([1, 2, 3, 4]),
75
+ timestamp: 1000n,
76
+ rapFlag: true
77
+ });
78
+ expect(result).not.toBeNull();
79
+ expect(result?.data).toEqual(new Uint8Array([1, 2, 3, 4]));
80
+ expect(result?.fragmentCount).toBe(1);
81
+ expect(result?.rapFlag).toBe(true);
82
+ });
83
+ test("rejects a complete MFU without a valid sample identity", () => {
84
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
85
+ const complete = (identity) => ({
86
+ fragmentationIndicator: 0,
87
+ mpuSequenceNumber: 1,
88
+ fragmentCounter: 0,
89
+ data: new Uint8Array([1]),
90
+ timestamp: 1000n,
91
+ rapFlag: true,
92
+ ...identity
93
+ });
94
+ expectRejection(() => reassembler.addFragment(complete({})), "missing-data-unit-identity");
95
+ expectRejection(
96
+ () => reassembler.addFragment(
97
+ complete({
98
+ movieFragmentSequenceNumber: 2,
99
+ sampleNumber: 1
100
+ })
101
+ ),
102
+ "missing-data-unit-identity"
103
+ );
104
+ });
105
+ test("accepts a complete subsample MFU with a nonzero authored offset", () => {
106
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
107
+ const result = reassembler.addFragment({
108
+ fragmentationIndicator: 0,
109
+ mpuSequenceNumber: 1,
110
+ fragmentCounter: 0,
111
+ movieFragmentSequenceNumber: 2,
112
+ sampleNumber: 1,
113
+ sampleOffset: 4,
114
+ data: new Uint8Array([1]),
115
+ timestamp: 1000n,
116
+ rapFlag: true
117
+ });
118
+ expect(result).not.toBeNull();
119
+ expect(result?.sampleOffset).toBe(4);
120
+ });
121
+ test("accepts a fragmented subsample DU whose first fragment has a nonzero authored offset", () => {
122
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
123
+ expect(
124
+ reassembler.addFragment({
125
+ fragmentationIndicator: 1,
126
+ mpuSequenceNumber: 2,
127
+ fragmentCounter: 1,
128
+ movieFragmentSequenceNumber: 2,
129
+ sampleNumber: 1,
130
+ sampleOffset: 4,
131
+ packetSequenceNumber: testPacketSequence(2, 1),
132
+ data: new Uint8Array([161]),
133
+ timestamp: 1000n,
134
+ rapFlag: true
135
+ })
136
+ ).toBeNull();
137
+ expect(reassembler.pendingCount).toBe(1);
138
+ expect(reassembler.getStatus().pendingFragments).toBe(1);
139
+ const out = reassembler.addFragment({
140
+ fragmentationIndicator: 3,
141
+ mpuSequenceNumber: 2,
142
+ fragmentCounter: 0,
143
+ data: new Uint8Array([162]),
144
+ timestamp: 1001n,
145
+ rapFlag: false,
146
+ packetSequenceNumber: testPacketSequence(2, 0)
147
+ });
148
+ expect(out?.data).toEqual(new Uint8Array([161, 162]));
149
+ expect(out?.sampleOffset).toBe(4);
150
+ });
151
+ test("a mid-data-unit packet sequence gap strands the data unit", () => {
152
+ const reassembler = new MFUReassembler({ timeoutMs: null, maxBuffered: 10 });
153
+ expect(
154
+ reassembler.addFragment({
155
+ fragmentationIndicator: 1,
156
+ mpuSequenceNumber: 7,
157
+ fragmentCounter: 2,
158
+ movieFragmentSequenceNumber: 9,
159
+ sampleNumber: 17,
160
+ sampleOffset: 0,
161
+ packetSequenceNumber: 100,
162
+ data: new Uint8Array([161]),
163
+ timestamp: 1100n,
164
+ rapFlag: true
165
+ })
166
+ ).toBeNull();
167
+ const interleaved = reassembler.addFragment({
168
+ fragmentationIndicator: 0,
169
+ mpuSequenceNumber: 7,
170
+ fragmentCounter: 0,
171
+ movieFragmentSequenceNumber: 9,
172
+ sampleNumber: 18,
173
+ sampleOffset: 0,
174
+ packetSequenceNumber: 101,
175
+ data: new Uint8Array([255]),
176
+ timestamp: 1101n,
177
+ rapFlag: true
178
+ });
179
+ expect(interleaved?.data).toEqual(new Uint8Array([255]));
180
+ expect(
181
+ reassembler.addFragment({
182
+ fragmentationIndicator: 2,
183
+ mpuSequenceNumber: 7,
184
+ fragmentCounter: 1,
185
+ packetSequenceNumber: 102,
186
+ data: new Uint8Array([162]),
187
+ timestamp: 1102n,
188
+ rapFlag: false
189
+ })
190
+ ).toBeNull();
191
+ const output = reassembler.addFragment({
192
+ fragmentationIndicator: 3,
193
+ mpuSequenceNumber: 7,
194
+ fragmentCounter: 0,
195
+ packetSequenceNumber: 103,
196
+ data: new Uint8Array([163]),
197
+ timestamp: 1103n,
198
+ rapFlag: false
199
+ });
200
+ expect(output).toBeNull();
201
+ expect(reassembler.stats.reassembledMFUs).toBe(1);
202
+ expect(reassembler.stats.rejectedFragments).toBe(0);
203
+ expect(reassembler.stats.evictedMemoryLimit).toBe(0);
204
+ expect(reassembler.getStatus().bufferedMFUs).toBe(2);
205
+ expect(reassembler.getStatus().pendingFragments).toBe(3);
206
+ });
207
+ test("sibling subsample DUs of one sample reassemble independently by offset", () => {
208
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
209
+ expect(
210
+ reassembler.addFragment({
211
+ mpuSequenceNumber: 3,
212
+ movieFragmentSequenceNumber: 5,
213
+ sampleNumber: 9,
214
+ fragmentationIndicator: 1,
215
+ fragmentCounter: 1,
216
+ sampleOffset: 0,
217
+ data: new Uint8Array([161]),
218
+ timestamp: 2000n,
219
+ rapFlag: true,
220
+ packetSequenceNumber: testPacketSequence(3, 1, 0)
221
+ })
222
+ ).toBeNull();
223
+ expect(
224
+ reassembler.addFragment({
225
+ mpuSequenceNumber: 3,
226
+ movieFragmentSequenceNumber: 5,
227
+ sampleNumber: 9,
228
+ fragmentationIndicator: 1,
229
+ fragmentCounter: 2,
230
+ sampleOffset: 3,
231
+ data: new Uint8Array([177]),
232
+ timestamp: 2001n,
233
+ rapFlag: false,
234
+ packetSequenceNumber: testPacketSequence(3, 1, 1)
235
+ })
236
+ ).toBeNull();
237
+ expect(reassembler.pendingCount).toBe(2);
238
+ const first = reassembler.addFragment({
239
+ mpuSequenceNumber: 3,
240
+ fragmentationIndicator: 3,
241
+ fragmentCounter: 0,
242
+ data: new Uint8Array([162]),
243
+ timestamp: 2000n,
244
+ rapFlag: false,
245
+ packetSequenceNumber: testPacketSequence(3, 0, 0)
246
+ });
247
+ expect(first?.data).toEqual(new Uint8Array([161, 162]));
248
+ expect(first?.sampleOffset).toBe(0);
249
+ expect(
250
+ reassembler.addFragment({
251
+ mpuSequenceNumber: 3,
252
+ fragmentationIndicator: 2,
253
+ fragmentCounter: 1,
254
+ data: new Uint8Array([178]),
255
+ timestamp: 2001n,
256
+ rapFlag: false,
257
+ packetSequenceNumber: testPacketSequence(3, 0, 1)
258
+ })
259
+ ).toBeNull();
260
+ const second = reassembler.addFragment({
261
+ mpuSequenceNumber: 3,
262
+ fragmentationIndicator: 3,
263
+ fragmentCounter: 0,
264
+ data: new Uint8Array([179]),
265
+ timestamp: 2001n,
266
+ rapFlag: false,
267
+ packetSequenceNumber: testPacketSequence(3, 0, 2)
268
+ });
269
+ expect(second?.data).toEqual(new Uint8Array([177, 178, 179]));
270
+ expect(second?.sampleOffset).toBe(3);
271
+ expect(reassembler.pendingCount).toBe(0);
272
+ });
273
+ test("isolates colliding fragment coordinates by catalog track identity", () => {
274
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
275
+ const fragment = (catalogTrackName, fragmentationIndicator, fragmentCounter, byte) => ({
276
+ itemId: 1,
277
+ fragmentationIndicator,
278
+ fragmentCounter,
279
+ mpuSequenceNumber: 1,
280
+ data: new Uint8Array([byte]),
281
+ timestamp: 1000n,
282
+ rapFlag: fragmentationIndicator === 1,
283
+ catalogTrackName,
284
+ packetSequenceNumber: testPacketSequence(1, fragmentCounter)
285
+ });
286
+ expect(reassembler.addFragment(fragment("video/720p", 1, 1, 113))).toBeNull();
287
+ expect(reassembler.addFragment(fragment("video/540p", 1, 1, 81))).toBeNull();
288
+ const high = reassembler.addFragment(fragment("video/720p", 3, 0, 114));
289
+ const low = reassembler.addFragment(fragment("video/540p", 3, 0, 82));
290
+ expect(high?.data).toEqual(new Uint8Array([113, 114]));
291
+ expect(high?.catalogTrackName).toBe("video/720p");
292
+ expect(low?.data).toEqual(new Uint8Array([81, 82]));
293
+ expect(low?.catalogTrackName).toBe("video/540p");
294
+ });
295
+ test("rejects an overlapping non-timed item without replacing the active run", () => {
296
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
297
+ const fragment = (itemId, fragmentationIndicator, fragmentCounter, byte) => ({
298
+ itemId,
299
+ fragmentationIndicator,
300
+ fragmentCounter,
301
+ mpuSequenceNumber: 1,
302
+ data: new Uint8Array([byte]),
303
+ timestamp: 1000n,
304
+ rapFlag: false,
305
+ packetSequenceNumber: testPacketSequence(1, fragmentCounter)
306
+ });
307
+ expect(reassembler.addFragment(fragment(10, 1, 1, 16))).toBeNull();
308
+ expectRejection(() => reassembler.addFragment(fragment(20, 1, 1, 32)), "overlapping-data-unit");
309
+ expect(reassembler.pendingCount).toBe(1);
310
+ expect(reassembler.addFragment(fragment(10, 3, 0, 17))?.data).toEqual(new Uint8Array([16, 17]));
311
+ expect(reassembler.pendingCount).toBe(0);
312
+ });
313
+ test("associates continuations by authored state when packet timestamps change", () => {
314
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
315
+ const fragment = (itemId, fragmentationIndicator, fragmentCounter, byte, timestamp) => ({
316
+ ...itemId === void 0 ? {} : { itemId },
317
+ fragmentationIndicator,
318
+ fragmentCounter,
319
+ mpuSequenceNumber: 1,
320
+ data: new Uint8Array([byte]),
321
+ timestamp,
322
+ rapFlag: false,
323
+ packetSequenceNumber: testPacketSequence(1, fragmentCounter)
324
+ });
325
+ expect(reassembler.addFragment(fragment(10, 1, 2, 16, 1000n))).toBeNull();
326
+ expect(reassembler.addFragment(fragment(void 0, 2, 1, 17, 1001n))).toBeNull();
327
+ const out = reassembler.addFragment(fragment(void 0, 3, 0, 18, 1002n));
328
+ expect(out?.data).toEqual(new Uint8Array([16, 17, 18]));
329
+ expect(out?.timestamp).toBe(1000n);
330
+ });
331
+ test("should buffer and reassemble 2 fragments", () => {
332
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
333
+ const result1 = reassembler.addFragment({
334
+ fragmentationIndicator: 1,
335
+ mpuSequenceNumber: 1,
336
+ fragmentCounter: 1,
337
+ itemId: 1,
338
+ data: new Uint8Array([1, 2]),
339
+ timestamp: 1000n,
340
+ rapFlag: true,
341
+ packetSequenceNumber: testPacketSequence(1, 1)
342
+ });
343
+ expect(result1).toBeNull();
344
+ const result2 = reassembler.addFragment({
345
+ fragmentationIndicator: 3,
346
+ mpuSequenceNumber: 1,
347
+ fragmentCounter: 0,
348
+ data: new Uint8Array([3, 4]),
349
+ timestamp: 1000n,
350
+ rapFlag: false,
351
+ packetSequenceNumber: testPacketSequence(1, 0)
352
+ });
353
+ expect(result2).not.toBeNull();
354
+ expect(result2?.data).toEqual(new Uint8Array([1, 2, 3, 4]));
355
+ expect(result2?.fragmentCount).toBe(2);
356
+ expect(result2?.rapFlag).toBe(true);
357
+ });
358
+ test("buffers a terminal continuation until its authored first fragment arrives", () => {
359
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
360
+ expect(
361
+ reassembler.addFragment({
362
+ fragmentationIndicator: 3,
363
+ mpuSequenceNumber: 1,
364
+ fragmentCounter: 0,
365
+ data: new Uint8Array([3, 4]),
366
+ timestamp: 1000n,
367
+ rapFlag: false,
368
+ packetSequenceNumber: testPacketSequence(1, 0)
369
+ })
370
+ ).toBeNull();
371
+ expect(reassembler.pendingCount).toBe(1);
372
+ const completed = reassembler.addFragment({
373
+ fragmentationIndicator: 1,
374
+ mpuSequenceNumber: 1,
375
+ fragmentCounter: 1,
376
+ itemId: 1,
377
+ data: new Uint8Array([1, 2]),
378
+ timestamp: 1000n,
379
+ rapFlag: true,
380
+ packetSequenceNumber: testPacketSequence(1, 1)
381
+ });
382
+ expect(completed?.data).toEqual(new Uint8Array([1, 2, 3, 4]));
383
+ expect(completed?.rapFlag).toBe(true);
384
+ expect(reassembler.pendingCount).toBe(0);
385
+ });
386
+ test("clock-free mode keeps an admitted MFU until completion", async () => {
387
+ const reassembler = new MFUReassembler({ timeoutMs: null });
388
+ reassembler.addFragment({
389
+ fragmentationIndicator: 1,
390
+ mpuSequenceNumber: 1,
391
+ fragmentCounter: 1,
392
+ itemId: 1,
393
+ data: new Uint8Array([1, 2]),
394
+ timestamp: 1000n,
395
+ rapFlag: true,
396
+ packetSequenceNumber: testPacketSequence(1, 1)
397
+ });
398
+ await new Promise((resolve) => setTimeout(resolve, 5));
399
+ const result = reassembler.addFragment({
400
+ fragmentationIndicator: 3,
401
+ mpuSequenceNumber: 1,
402
+ fragmentCounter: 0,
403
+ data: new Uint8Array([3, 4]),
404
+ timestamp: 1000n,
405
+ rapFlag: false,
406
+ packetSequenceNumber: testPacketSequence(1, 0)
407
+ });
408
+ expect(result).not.toBeNull();
409
+ expect(result?.data).toEqual(new Uint8Array([1, 2, 3, 4]));
410
+ expect(reassembler.stats.timedOutMFUs).toBe(0);
411
+ });
412
+ test("should track pending count", () => {
413
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
414
+ expect(reassembler.pendingCount).toBe(0);
415
+ reassembler.addFragment({
416
+ fragmentationIndicator: 1,
417
+ mpuSequenceNumber: 1,
418
+ fragmentCounter: 1,
419
+ itemId: 1,
420
+ data: new Uint8Array([1]),
421
+ timestamp: 1000n,
422
+ rapFlag: false,
423
+ packetSequenceNumber: testPacketSequence(1, 1)
424
+ });
425
+ expect(reassembler.pendingCount).toBe(1);
426
+ reassembler.flush();
427
+ expect(reassembler.pendingCount).toBe(0);
428
+ });
429
+ test("should reassemble 3 fragments (FI=1, FI=2, FI=3)", () => {
430
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
431
+ expect(
432
+ reassembler.addFragment({
433
+ fragmentationIndicator: 1,
434
+ mpuSequenceNumber: 10,
435
+ fragmentCounter: 2,
436
+ itemId: 1,
437
+ data: new Uint8Array([170, 187]),
438
+ timestamp: 5000n,
439
+ rapFlag: true,
440
+ packetSequenceNumber: testPacketSequence(10, 2)
441
+ })
442
+ ).toBeNull();
443
+ expect(
444
+ reassembler.addFragment({
445
+ fragmentationIndicator: 2,
446
+ mpuSequenceNumber: 10,
447
+ fragmentCounter: 1,
448
+ data: new Uint8Array([204, 221]),
449
+ timestamp: 5000n,
450
+ rapFlag: false,
451
+ packetSequenceNumber: testPacketSequence(10, 1)
452
+ })
453
+ ).toBeNull();
454
+ const result = reassembler.addFragment({
455
+ fragmentationIndicator: 3,
456
+ mpuSequenceNumber: 10,
457
+ fragmentCounter: 0,
458
+ data: new Uint8Array([238, 255]),
459
+ timestamp: 5000n,
460
+ rapFlag: false,
461
+ packetSequenceNumber: testPacketSequence(10, 0)
462
+ });
463
+ expect(result).not.toBeNull();
464
+ expect(result.data).toEqual(new Uint8Array([170, 187, 204, 221, 238, 255]));
465
+ expect(result.fragmentCount).toBe(3);
466
+ expect(result.rapFlag).toBe(true);
467
+ expect(result.mpuSequenceNumber).toBe(10);
468
+ });
469
+ test("should handle interleaved MPU sequences", () => {
470
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
471
+ reassembler.addFragment({
472
+ fragmentationIndicator: 1,
473
+ mpuSequenceNumber: 1,
474
+ fragmentCounter: 1,
475
+ itemId: 1,
476
+ data: new Uint8Array([1]),
477
+ timestamp: 100n,
478
+ rapFlag: false,
479
+ packetSequenceNumber: testPacketSequence(1, 1)
480
+ });
481
+ const r2 = reassembler.addFragment({
482
+ fragmentationIndicator: 0,
483
+ mpuSequenceNumber: 2,
484
+ fragmentCounter: 0,
485
+ itemId: 2,
486
+ data: new Uint8Array([2]),
487
+ timestamp: 200n,
488
+ rapFlag: false
489
+ });
490
+ expect(r2).not.toBeNull();
491
+ expect(r2.mpuSequenceNumber).toBe(2);
492
+ const r1 = reassembler.addFragment({
493
+ fragmentationIndicator: 3,
494
+ mpuSequenceNumber: 1,
495
+ fragmentCounter: 0,
496
+ data: new Uint8Array([3]),
497
+ timestamp: 100n,
498
+ rapFlag: false,
499
+ packetSequenceNumber: testPacketSequence(1, 0)
500
+ });
501
+ expect(r1).not.toBeNull();
502
+ expect(r1.data).toEqual(new Uint8Array([1, 3]));
503
+ });
504
+ test("rejects overlapping fragmented MFUs sharing one stream and MPU", () => {
505
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
506
+ const mpuSeq = 5;
507
+ expect(
508
+ reassembler.addFragment({
509
+ fragmentationIndicator: 1,
510
+ mpuSequenceNumber: mpuSeq,
511
+ fragmentCounter: 1,
512
+ itemId: 10,
513
+ data: new Uint8Array([161]),
514
+ timestamp: 100n,
515
+ rapFlag: true,
516
+ packetSequenceNumber: testPacketSequence(mpuSeq, 1)
517
+ })
518
+ ).toBeNull();
519
+ expectRejection(
520
+ () => reassembler.addFragment({
521
+ fragmentationIndicator: 1,
522
+ mpuSequenceNumber: mpuSeq,
523
+ fragmentCounter: 1,
524
+ itemId: 20,
525
+ data: new Uint8Array([177]),
526
+ timestamp: 200n,
527
+ rapFlag: false,
528
+ packetSequenceNumber: testPacketSequence(mpuSeq, 1)
529
+ }),
530
+ "overlapping-data-unit"
531
+ );
532
+ expect(reassembler.pendingCount).toBe(1);
533
+ const a = reassembler.addFragment({
534
+ fragmentationIndicator: 3,
535
+ mpuSequenceNumber: mpuSeq,
536
+ fragmentCounter: 0,
537
+ data: new Uint8Array([162]),
538
+ timestamp: 101n,
539
+ rapFlag: false,
540
+ packetSequenceNumber: testPacketSequence(mpuSeq, 0)
541
+ });
542
+ expect(a).not.toBeNull();
543
+ expect(a.data).toEqual(new Uint8Array([161, 162]));
544
+ expect(a.rapFlag).toBe(true);
545
+ expect(
546
+ reassembler.addFragment({
547
+ fragmentationIndicator: 1,
548
+ mpuSequenceNumber: mpuSeq,
549
+ fragmentCounter: 1,
550
+ itemId: 20,
551
+ data: new Uint8Array([177]),
552
+ timestamp: 200n,
553
+ rapFlag: false,
554
+ packetSequenceNumber: testPacketSequence(mpuSeq, 1, 10)
555
+ })
556
+ ).toBeNull();
557
+ const b = reassembler.addFragment({
558
+ fragmentationIndicator: 3,
559
+ mpuSequenceNumber: mpuSeq,
560
+ fragmentCounter: 0,
561
+ data: new Uint8Array([178]),
562
+ timestamp: 201n,
563
+ rapFlag: false,
564
+ packetSequenceNumber: testPacketSequence(mpuSeq, 0, 10)
565
+ });
566
+ expect(b).not.toBeNull();
567
+ expect(b.data).toEqual(new Uint8Array([177, 178]));
568
+ });
569
+ test("reassembles FFmpeg timed MFU fragments by sample number and byte offset", () => {
570
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
571
+ const common = {
572
+ mpuSequenceNumber: 0,
573
+ movieFragmentSequenceNumber: 9,
574
+ sampleNumber: 17
575
+ };
576
+ expect(
577
+ reassembler.addFragment({
578
+ ...common,
579
+ fragmentationIndicator: 1,
580
+ fragmentCounter: 2,
581
+ sampleOffset: 0,
582
+ data: new Uint8Array([161]),
583
+ timestamp: 1000n,
584
+ rapFlag: true,
585
+ packetSequenceNumber: testPacketSequence(0, 2)
586
+ })
587
+ ).toBeNull();
588
+ expect(
589
+ reassembler.addFragment({
590
+ ...common,
591
+ fragmentationIndicator: 2,
592
+ fragmentCounter: 1,
593
+ sampleOffset: 1,
594
+ data: new Uint8Array([178]),
595
+ timestamp: 1001n,
596
+ rapFlag: false,
597
+ packetSequenceNumber: testPacketSequence(0, 1)
598
+ })
599
+ ).toBeNull();
600
+ const out = reassembler.addFragment({
601
+ ...common,
602
+ fragmentationIndicator: 3,
603
+ fragmentCounter: 0,
604
+ sampleOffset: 2,
605
+ data: new Uint8Array([195]),
606
+ timestamp: 1002n,
607
+ rapFlag: false,
608
+ packetSequenceNumber: testPacketSequence(0, 0)
609
+ });
610
+ expect(out).not.toBeNull();
611
+ expect(out.data).toEqual(new Uint8Array([161, 178, 195]));
612
+ expect(out.timestamp).toBe(1000n);
613
+ expect(out.sampleNumber).toBe(17);
614
+ expect(out.movieFragmentSequenceNumber).toBe(9);
615
+ });
616
+ test("buffers a counter gap without advancing the active data unit", () => {
617
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
618
+ const common = {
619
+ mpuSequenceNumber: 0,
620
+ movieFragmentSequenceNumber: 9,
621
+ sampleNumber: 17,
622
+ timestamp: 1000n,
623
+ rapFlag: true
624
+ };
625
+ expect(
626
+ reassembler.addFragment({
627
+ ...common,
628
+ fragmentationIndicator: 1,
629
+ fragmentCounter: 2,
630
+ sampleOffset: 0,
631
+ data: new Uint8Array([161, 162]),
632
+ packetSequenceNumber: testPacketSequence(0, 2)
633
+ })
634
+ ).toBeNull();
635
+ expect(
636
+ reassembler.addFragment({
637
+ ...common,
638
+ fragmentationIndicator: 3,
639
+ fragmentCounter: 0,
640
+ sampleOffset: 4,
641
+ data: new Uint8Array([193, 194]),
642
+ packetSequenceNumber: testPacketSequence(0, 0)
643
+ })
644
+ ).toBeNull();
645
+ expect(reassembler.pendingCount).toBe(1);
646
+ const out = reassembler.addFragment({
647
+ ...common,
648
+ fragmentationIndicator: 2,
649
+ fragmentCounter: 1,
650
+ sampleOffset: 2,
651
+ data: new Uint8Array([177, 178]),
652
+ packetSequenceNumber: testPacketSequence(0, 1)
653
+ });
654
+ expect(out?.data).toEqual(new Uint8Array([161, 162, 177, 178, 193, 194]));
655
+ });
656
+ test("reassembles first-only DU-header fragments across changing packet timestamps", () => {
657
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
658
+ expect(
659
+ reassembler.addFragment({
660
+ fragmentationIndicator: 1,
661
+ mpuSequenceNumber: 44,
662
+ fragmentCounter: 2,
663
+ movieFragmentSequenceNumber: 9,
664
+ sampleNumber: 17,
665
+ sampleOffset: 0,
666
+ data: new Uint8Array([161]),
667
+ timestamp: 12345n,
668
+ rapFlag: true,
669
+ packetSequenceNumber: testPacketSequence(44, 2)
670
+ })
671
+ ).toBeNull();
672
+ expect(
673
+ reassembler.addFragment({
674
+ fragmentationIndicator: 2,
675
+ mpuSequenceNumber: 44,
676
+ fragmentCounter: 1,
677
+ data: new Uint8Array([178]),
678
+ timestamp: 12346n,
679
+ rapFlag: false,
680
+ packetSequenceNumber: testPacketSequence(44, 1)
681
+ })
682
+ ).toBeNull();
683
+ const out = reassembler.addFragment({
684
+ fragmentationIndicator: 3,
685
+ mpuSequenceNumber: 44,
686
+ fragmentCounter: 0,
687
+ data: new Uint8Array([195]),
688
+ timestamp: 12347n,
689
+ rapFlag: false,
690
+ packetSequenceNumber: testPacketSequence(44, 0)
691
+ });
692
+ expect(out).not.toBeNull();
693
+ expect(out.data).toEqual(new Uint8Array([161, 178, 195]));
694
+ expect(out.timestamp).toBe(12345n);
695
+ expect(out.sampleNumber).toBe(17);
696
+ expect(out.movieFragmentSequenceNumber).toBe(9);
697
+ });
698
+ test("reassembles first-only DU-header fragments with an ISO countdown", () => {
699
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
700
+ const timestamp = 12345n;
701
+ expect(
702
+ reassembler.addFragment({
703
+ fragmentationIndicator: 1,
704
+ mpuSequenceNumber: 44,
705
+ fragmentCounter: 3,
706
+ movieFragmentSequenceNumber: 9,
707
+ sampleNumber: 17,
708
+ sampleOffset: 0,
709
+ data: new Uint8Array([161]),
710
+ timestamp,
711
+ rapFlag: true,
712
+ packetSequenceNumber: testPacketSequence(44, 3)
713
+ })
714
+ ).toBeNull();
715
+ expect(
716
+ reassembler.addFragment({
717
+ fragmentationIndicator: 2,
718
+ mpuSequenceNumber: 44,
719
+ fragmentCounter: 2,
720
+ data: new Uint8Array([178]),
721
+ timestamp,
722
+ rapFlag: false,
723
+ packetSequenceNumber: testPacketSequence(44, 2)
724
+ })
725
+ ).toBeNull();
726
+ expect(
727
+ reassembler.addFragment({
728
+ fragmentationIndicator: 2,
729
+ mpuSequenceNumber: 44,
730
+ fragmentCounter: 1,
731
+ data: new Uint8Array([195]),
732
+ timestamp,
733
+ rapFlag: false,
734
+ packetSequenceNumber: testPacketSequence(44, 1)
735
+ })
736
+ ).toBeNull();
737
+ const out = reassembler.addFragment({
738
+ fragmentationIndicator: 3,
739
+ mpuSequenceNumber: 44,
740
+ fragmentCounter: 0,
741
+ data: new Uint8Array([212]),
742
+ timestamp,
743
+ rapFlag: false,
744
+ packetSequenceNumber: testPacketSequence(44, 0)
745
+ });
746
+ expect(out).not.toBeNull();
747
+ expect(out.data).toEqual(new Uint8Array([161, 178, 195, 212]));
748
+ expect(out.sampleNumber).toBe(17);
749
+ expect(out.movieFragmentSequenceNumber).toBe(9);
750
+ });
751
+ test("rejects fragmented MFUs without an authored DU identity", () => {
752
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
753
+ const timestamp = 22222n;
754
+ expectRejection(
755
+ () => reassembler.addFragment({
756
+ fragmentationIndicator: 1,
757
+ mpuSequenceNumber: 55,
758
+ fragmentCounter: 2,
759
+ data: new Uint8Array([161]),
760
+ timestamp,
761
+ rapFlag: true,
762
+ packetSequenceNumber: testPacketSequence(55, 2)
763
+ }),
764
+ "missing-data-unit-identity"
765
+ );
766
+ expect(reassembler.pendingCount).toBe(0);
767
+ });
768
+ test("rejects fragmented MFUs without an authored packet sequence", () => {
769
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
770
+ expectRejection(
771
+ () => reassembler.addFragment({
772
+ fragmentationIndicator: 1,
773
+ mpuSequenceNumber: 55,
774
+ fragmentCounter: 1,
775
+ itemId: 1,
776
+ data: new Uint8Array([161]),
777
+ timestamp: 22222n,
778
+ rapFlag: true
779
+ }),
780
+ "missing-packet-sequence"
781
+ );
782
+ expect(reassembler.pendingCount).toBe(0);
783
+ });
784
+ test("rejects fragmented MFUs whose authored packet sequence is not u32", () => {
785
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
786
+ for (const packetSequenceNumber of [-1, 4294967296, 1.5, Number.NaN]) {
787
+ expectRejection(
788
+ () => reassembler.addFragment({
789
+ fragmentationIndicator: 1,
790
+ mpuSequenceNumber: 55,
791
+ fragmentCounter: 1,
792
+ itemId: 1,
793
+ data: new Uint8Array([161]),
794
+ timestamp: 22222n,
795
+ rapFlag: true,
796
+ packetSequenceNumber
797
+ }),
798
+ "missing-packet-sequence"
799
+ );
800
+ }
801
+ expect(reassembler.pendingCount).toBe(0);
802
+ });
803
+ test("a packet sequence gap inside a fragmented DU splits it and never completes", () => {
804
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
805
+ const timestamp = 66666n;
806
+ expect(
807
+ reassembler.addFragment({
808
+ fragmentationIndicator: 1,
809
+ mpuSequenceNumber: 80,
810
+ fragmentCounter: 3,
811
+ movieFragmentSequenceNumber: 241,
812
+ sampleNumber: 1,
813
+ sampleOffset: 0,
814
+ packetSequenceNumber: 1e3,
815
+ data: new Uint8Array([160]),
816
+ timestamp,
817
+ rapFlag: true
818
+ })
819
+ ).toBeNull();
820
+ for (const [counter, psn] of [
821
+ [2, 1002],
822
+ [1, 1003]
823
+ ]) {
824
+ expect(
825
+ reassembler.addFragment({
826
+ fragmentationIndicator: 2,
827
+ mpuSequenceNumber: 80,
828
+ fragmentCounter: counter,
829
+ packetSequenceNumber: psn,
830
+ data: new Uint8Array([160 + counter]),
831
+ timestamp,
832
+ rapFlag: false
833
+ })
834
+ ).toBeNull();
835
+ }
836
+ expect(
837
+ reassembler.addFragment({
838
+ fragmentationIndicator: 3,
839
+ mpuSequenceNumber: 80,
840
+ fragmentCounter: 0,
841
+ packetSequenceNumber: 1004,
842
+ data: new Uint8Array([177]),
843
+ timestamp,
844
+ rapFlag: false
845
+ })
846
+ ).toBeNull();
847
+ expect(reassembler.pendingCount).toBe(2);
848
+ expect(reassembler.getStatus().pendingFragments).toBe(4);
849
+ expect(reassembler.stats.reassembledMFUs).toBe(0);
850
+ expect(reassembler.stats.rejectedFragments).toBe(0);
851
+ });
852
+ test("keeps adjacent MFUs with equal countdowns in one MPU separate", () => {
853
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
854
+ const common = { mpuSequenceNumber: 80, packetId: 7, timestamp: 66666n };
855
+ expect(
856
+ reassembler.addFragment({
857
+ ...common,
858
+ fragmentationIndicator: 1,
859
+ fragmentCounter: 1,
860
+ packetSequenceNumber: 100,
861
+ movieFragmentSequenceNumber: 241,
862
+ sampleNumber: 1,
863
+ sampleOffset: 0,
864
+ data: new Uint8Array([161]),
865
+ rapFlag: true
866
+ })
867
+ ).toBeNull();
868
+ expect(
869
+ reassembler.addFragment({
870
+ ...common,
871
+ fragmentationIndicator: 1,
872
+ fragmentCounter: 1,
873
+ packetSequenceNumber: 102,
874
+ movieFragmentSequenceNumber: 241,
875
+ sampleNumber: 2,
876
+ sampleOffset: 0,
877
+ data: new Uint8Array([177]),
878
+ rapFlag: false
879
+ })
880
+ ).toBeNull();
881
+ expect(reassembler.pendingCount).toBe(2);
882
+ const earlier = reassembler.addFragment({
883
+ ...common,
884
+ fragmentationIndicator: 3,
885
+ fragmentCounter: 0,
886
+ packetSequenceNumber: 101,
887
+ data: new Uint8Array([162]),
888
+ rapFlag: false
889
+ });
890
+ expect(earlier?.data).toEqual(new Uint8Array([161, 162]));
891
+ expect(earlier?.packetSequenceNumbers).toEqual([100, 101]);
892
+ const later = reassembler.addFragment({
893
+ ...common,
894
+ fragmentationIndicator: 3,
895
+ fragmentCounter: 0,
896
+ packetSequenceNumber: 103,
897
+ data: new Uint8Array([178]),
898
+ rapFlag: false
899
+ });
900
+ expect(later?.data).toEqual(new Uint8Array([177, 178]));
901
+ expect(later?.packetSequenceNumbers).toEqual([102, 103]);
902
+ expect(reassembler.pendingCount).toBe(0);
903
+ });
904
+ test("wraps the fragmented run coordinate at u32 packet sequence", () => {
905
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
906
+ expect(
907
+ reassembler.addFragment({
908
+ fragmentationIndicator: 1,
909
+ mpuSequenceNumber: 81,
910
+ fragmentCounter: 1,
911
+ packetSequenceNumber: 4294967295,
912
+ itemId: 1,
913
+ data: new Uint8Array([161]),
914
+ timestamp: 66666n,
915
+ rapFlag: true
916
+ })
917
+ ).toBeNull();
918
+ expect(
919
+ reassembler.addFragment({
920
+ fragmentationIndicator: 3,
921
+ mpuSequenceNumber: 81,
922
+ fragmentCounter: 0,
923
+ packetSequenceNumber: 0,
924
+ data: new Uint8Array([162]),
925
+ timestamp: 66667n,
926
+ rapFlag: false
927
+ })?.data
928
+ ).toEqual(new Uint8Array([161, 162]));
929
+ });
930
+ test("dedupes recovered copies by ISO fragment-counter position", () => {
931
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
932
+ const timestamp = 44444n;
933
+ expect(
934
+ reassembler.addFragment({
935
+ fragmentationIndicator: 1,
936
+ mpuSequenceNumber: 77,
937
+ fragmentCounter: 2,
938
+ movieFragmentSequenceNumber: 12,
939
+ sampleNumber: 1,
940
+ sampleOffset: 0,
941
+ packetSequenceNumber: 2e3,
942
+ data: new Uint8Array([161]),
943
+ timestamp,
944
+ rapFlag: true
945
+ })
946
+ ).toBeNull();
947
+ expect(
948
+ reassembler.addFragment({
949
+ fragmentationIndicator: 2,
950
+ mpuSequenceNumber: 77,
951
+ fragmentCounter: 1,
952
+ packetSequenceNumber: 2001,
953
+ data: new Uint8Array([178]),
954
+ timestamp,
955
+ rapFlag: false
956
+ })
957
+ ).toBeNull();
958
+ expect(
959
+ reassembler.addFragment({
960
+ fragmentationIndicator: 3,
961
+ mpuSequenceNumber: 77,
962
+ fragmentCounter: 0,
963
+ packetSequenceNumber: 2002,
964
+ data: new Uint8Array([195]),
965
+ timestamp,
966
+ rapFlag: false
967
+ })
968
+ ).not.toBeNull();
969
+ reassembler.flush();
970
+ expect(
971
+ reassembler.addFragment({
972
+ fragmentationIndicator: 1,
973
+ mpuSequenceNumber: 78,
974
+ fragmentCounter: 2,
975
+ movieFragmentSequenceNumber: 13,
976
+ sampleNumber: 1,
977
+ sampleOffset: 0,
978
+ packetSequenceNumber: 3e3,
979
+ data: new Uint8Array([212]),
980
+ timestamp,
981
+ rapFlag: true
982
+ })
983
+ ).toBeNull();
984
+ expect(
985
+ reassembler.addFragment({
986
+ fragmentationIndicator: 2,
987
+ mpuSequenceNumber: 78,
988
+ fragmentCounter: 1,
989
+ packetSequenceNumber: 3001,
990
+ data: new Uint8Array([229]),
991
+ timestamp,
992
+ rapFlag: false
993
+ })
994
+ ).toBeNull();
995
+ expectRejection(
996
+ () => reassembler.addFragment({
997
+ fragmentationIndicator: 2,
998
+ mpuSequenceNumber: 78,
999
+ fragmentCounter: 1,
1000
+ packetSequenceNumber: 3001,
1001
+ data: new Uint8Array([229]),
1002
+ timestamp,
1003
+ rapFlag: false
1004
+ }),
1005
+ "fragment-counter-mismatch"
1006
+ );
1007
+ const out = reassembler.addFragment({
1008
+ fragmentationIndicator: 3,
1009
+ mpuSequenceNumber: 78,
1010
+ fragmentCounter: 0,
1011
+ packetSequenceNumber: 3002,
1012
+ data: new Uint8Array([246]),
1013
+ timestamp,
1014
+ rapFlag: false
1015
+ });
1016
+ expect(out).not.toBeNull();
1017
+ expect(out.data).toEqual(new Uint8Array([212, 229, 246]));
1018
+ });
1019
+ test("reassembles middle and terminal continuations that arrive before first", () => {
1020
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1021
+ const timestamp = 54321n;
1022
+ expect(
1023
+ reassembler.addFragment({
1024
+ fragmentationIndicator: 2,
1025
+ mpuSequenceNumber: 45,
1026
+ fragmentCounter: 1,
1027
+ data: new Uint8Array([178]),
1028
+ timestamp,
1029
+ rapFlag: false,
1030
+ packetSequenceNumber: testPacketSequence(45, 1)
1031
+ })
1032
+ ).toBeNull();
1033
+ expect(
1034
+ reassembler.addFragment({
1035
+ fragmentationIndicator: 3,
1036
+ mpuSequenceNumber: 45,
1037
+ fragmentCounter: 0,
1038
+ data: new Uint8Array([195]),
1039
+ timestamp: timestamp + 1n,
1040
+ rapFlag: false,
1041
+ packetSequenceNumber: testPacketSequence(45, 0)
1042
+ })
1043
+ ).toBeNull();
1044
+ expect(reassembler.pendingCount).toBe(1);
1045
+ const out = reassembler.addFragment({
1046
+ fragmentationIndicator: 1,
1047
+ mpuSequenceNumber: 45,
1048
+ fragmentCounter: 2,
1049
+ movieFragmentSequenceNumber: 10,
1050
+ sampleNumber: 18,
1051
+ sampleOffset: 0,
1052
+ data: new Uint8Array([161]),
1053
+ timestamp,
1054
+ rapFlag: true,
1055
+ packetSequenceNumber: testPacketSequence(45, 2)
1056
+ });
1057
+ expect(out).not.toBeNull();
1058
+ expect(out.data).toEqual(new Uint8Array([161, 178, 195]));
1059
+ expect(out.sampleNumber).toBe(18);
1060
+ expect(out.movieFragmentSequenceNumber).toBe(10);
1061
+ expect(reassembler.pendingCount).toBe(0);
1062
+ });
1063
+ test("rejects a duplicate continuation before first without replacing retained media", () => {
1064
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1065
+ const timestamp = 54322n;
1066
+ expect(
1067
+ reassembler.addFragment({
1068
+ fragmentationIndicator: 3,
1069
+ mpuSequenceNumber: 46,
1070
+ fragmentCounter: 0,
1071
+ data: new Uint8Array([195]),
1072
+ timestamp,
1073
+ rapFlag: false,
1074
+ packetSequenceNumber: testPacketSequence(46, 0)
1075
+ })
1076
+ ).toBeNull();
1077
+ expectRejection(
1078
+ () => reassembler.addFragment({
1079
+ fragmentationIndicator: 3,
1080
+ mpuSequenceNumber: 46,
1081
+ fragmentCounter: 0,
1082
+ data: new Uint8Array([255]),
1083
+ timestamp: timestamp + 1n,
1084
+ rapFlag: false,
1085
+ packetSequenceNumber: testPacketSequence(46, 0)
1086
+ }),
1087
+ "fragment-counter-mismatch"
1088
+ );
1089
+ expect(
1090
+ reassembler.addFragment({
1091
+ fragmentationIndicator: 2,
1092
+ mpuSequenceNumber: 46,
1093
+ fragmentCounter: 1,
1094
+ data: new Uint8Array([178]),
1095
+ timestamp: timestamp + 2n,
1096
+ rapFlag: false,
1097
+ packetSequenceNumber: testPacketSequence(46, 1)
1098
+ })
1099
+ ).toBeNull();
1100
+ const out = reassembler.addFragment({
1101
+ fragmentationIndicator: 1,
1102
+ mpuSequenceNumber: 46,
1103
+ fragmentCounter: 2,
1104
+ movieFragmentSequenceNumber: 10,
1105
+ sampleNumber: 19,
1106
+ sampleOffset: 0,
1107
+ data: new Uint8Array([161]),
1108
+ timestamp: timestamp + 3n,
1109
+ rapFlag: true,
1110
+ packetSequenceNumber: testPacketSequence(46, 2)
1111
+ });
1112
+ expect(out).not.toBeNull();
1113
+ expect(out.data).toEqual(new Uint8Array([161, 178, 195]));
1114
+ expect(reassembler.pendingCount).toBe(0);
1115
+ });
1116
+ test("rejects invalid ISO fragmentation-indicator and counter combinations", () => {
1117
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1118
+ const invalidHeaders = [
1119
+ { fragmentationIndicator: 0, fragmentCounter: 1 },
1120
+ { fragmentationIndicator: 3, fragmentCounter: 1 },
1121
+ { fragmentationIndicator: 1, fragmentCounter: 0 },
1122
+ { fragmentationIndicator: 2, fragmentCounter: 0 },
1123
+ { fragmentationIndicator: -1, fragmentCounter: 1 },
1124
+ { fragmentationIndicator: 4, fragmentCounter: 1 },
1125
+ { fragmentationIndicator: 1.5, fragmentCounter: 1 },
1126
+ { fragmentationIndicator: 1, fragmentCounter: -1 },
1127
+ { fragmentationIndicator: 1, fragmentCounter: 256 },
1128
+ { fragmentationIndicator: 1, fragmentCounter: 1.5 },
1129
+ { fragmentationIndicator: 1, fragmentCounter: Number.NaN }
1130
+ ];
1131
+ for (const header of invalidHeaders) {
1132
+ expectRejection(
1133
+ () => reassembler.addFragment({
1134
+ ...header,
1135
+ mpuSequenceNumber: 48,
1136
+ data: new Uint8Array([161]),
1137
+ timestamp: 54324n,
1138
+ rapFlag: false
1139
+ }),
1140
+ "invalid-fragment-state"
1141
+ );
1142
+ }
1143
+ expect(reassembler.pendingCount).toBe(0);
1144
+ expect(reassembler.stats.reassembledMFUs).toBe(0);
1145
+ });
1146
+ test("reassembles the maximum ISO chain of 256 payloads", () => {
1147
+ const reassembler = new MFUReassembler({ timeoutMs: null });
1148
+ const common = {
1149
+ mpuSequenceNumber: 47,
1150
+ timestamp: 54323n,
1151
+ rapFlag: false
1152
+ };
1153
+ expect(
1154
+ reassembler.addFragment({
1155
+ ...common,
1156
+ fragmentationIndicator: 1,
1157
+ fragmentCounter: 255,
1158
+ itemId: 1,
1159
+ data: new Uint8Array([0]),
1160
+ rapFlag: true,
1161
+ packetSequenceNumber: testPacketSequence(47, 255)
1162
+ })
1163
+ ).toBeNull();
1164
+ for (let counter = 254; counter > 0; counter--) {
1165
+ expect(
1166
+ reassembler.addFragment({
1167
+ ...common,
1168
+ fragmentationIndicator: 2,
1169
+ fragmentCounter: counter,
1170
+ data: new Uint8Array([255 - counter]),
1171
+ packetSequenceNumber: testPacketSequence(47, counter)
1172
+ })
1173
+ ).toBeNull();
1174
+ }
1175
+ const out = reassembler.addFragment({
1176
+ ...common,
1177
+ fragmentationIndicator: 3,
1178
+ fragmentCounter: 0,
1179
+ data: new Uint8Array([255]),
1180
+ packetSequenceNumber: testPacketSequence(47, 0)
1181
+ });
1182
+ expect(out?.fragmentCount).toBe(256);
1183
+ expect(out?.data).toEqual(Uint8Array.from({ length: 256 }, (_, index) => index));
1184
+ });
1185
+ test("should not reassemble without last fragment (FI=3)", () => {
1186
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1187
+ reassembler.addFragment({
1188
+ fragmentationIndicator: 1,
1189
+ mpuSequenceNumber: 1,
1190
+ fragmentCounter: 2,
1191
+ itemId: 1,
1192
+ data: new Uint8Array([1]),
1193
+ timestamp: 1000n,
1194
+ rapFlag: false,
1195
+ packetSequenceNumber: testPacketSequence(1, 2)
1196
+ });
1197
+ const result = reassembler.addFragment({
1198
+ fragmentationIndicator: 2,
1199
+ mpuSequenceNumber: 1,
1200
+ fragmentCounter: 1,
1201
+ data: new Uint8Array([2]),
1202
+ timestamp: 1000n,
1203
+ rapFlag: false,
1204
+ packetSequenceNumber: testPacketSequence(1, 1)
1205
+ });
1206
+ expect(result).toBeNull();
1207
+ expect(reassembler.pendingCount).toBe(1);
1208
+ });
1209
+ test("bounds continuations that arrive before their first fragments", () => {
1210
+ const reassembler = new MFUReassembler({
1211
+ timeoutMs: null,
1212
+ maxBuffered: 1
1213
+ });
1214
+ expect(
1215
+ reassembler.addFragment({
1216
+ fragmentationIndicator: 3,
1217
+ mpuSequenceNumber: 1,
1218
+ fragmentCounter: 0,
1219
+ data: new Uint8Array([1]),
1220
+ timestamp: 1000n,
1221
+ rapFlag: false,
1222
+ packetSequenceNumber: testPacketSequence(1, 0)
1223
+ })
1224
+ ).toBeNull();
1225
+ expect(reassembler.pendingCount).toBe(1);
1226
+ expect(
1227
+ reassembler.addFragment({
1228
+ fragmentationIndicator: 3,
1229
+ mpuSequenceNumber: 2,
1230
+ fragmentCounter: 0,
1231
+ data: new Uint8Array([2]),
1232
+ timestamp: 1000n,
1233
+ rapFlag: false,
1234
+ packetSequenceNumber: testPacketSequence(2, 0)
1235
+ })
1236
+ ).toBeNull();
1237
+ expect(reassembler.pendingCount).toBe(1);
1238
+ expect(reassembler.getStatus().pendingFragments).toBe(1);
1239
+ expect(reassembler.stats.evictedMemoryLimit).toBe(1);
1240
+ const completed = reassembler.addFragment({
1241
+ fragmentationIndicator: 1,
1242
+ mpuSequenceNumber: 2,
1243
+ fragmentCounter: 1,
1244
+ itemId: 2,
1245
+ data: new Uint8Array([4]),
1246
+ timestamp: 1000n,
1247
+ rapFlag: true,
1248
+ packetSequenceNumber: testPacketSequence(2, 1)
1249
+ });
1250
+ expect(completed?.data).toEqual(new Uint8Array([4, 2]));
1251
+ expect(reassembler.stats.evictedMemoryLimit).toBe(1);
1252
+ expect(reassembler.pendingCount).toBe(0);
1253
+ const result = reassembler.addFragment({
1254
+ fragmentationIndicator: 1,
1255
+ mpuSequenceNumber: 1,
1256
+ fragmentCounter: 1,
1257
+ itemId: 1,
1258
+ data: new Uint8Array([3]),
1259
+ timestamp: 1000n,
1260
+ rapFlag: true,
1261
+ packetSequenceNumber: testPacketSequence(1, 1)
1262
+ });
1263
+ expect(result).toBeNull();
1264
+ expect(reassembler.pendingCount).toBe(1);
1265
+ });
1266
+ test("expires a continuation that never receives its first fragment", () => {
1267
+ vi.useFakeTimers();
1268
+ try {
1269
+ const reassembler = new MFUReassembler({
1270
+ timeoutMs: 50,
1271
+ maxBuffered: 1
1272
+ });
1273
+ expect(
1274
+ reassembler.addFragment({
1275
+ fragmentationIndicator: 3,
1276
+ mpuSequenceNumber: 1,
1277
+ fragmentCounter: 0,
1278
+ data: new Uint8Array([1]),
1279
+ timestamp: 1000n,
1280
+ rapFlag: false,
1281
+ packetSequenceNumber: testPacketSequence(1, 0)
1282
+ })
1283
+ ).toBeNull();
1284
+ vi.advanceTimersByTime(50);
1285
+ expect(reassembler.pendingCount).toBe(0);
1286
+ expect(reassembler.stats.timedOutMFUs).toBe(1);
1287
+ } finally {
1288
+ vi.useRealTimers();
1289
+ }
1290
+ });
1291
+ test("retimes retained continuations when the timeout policy changes", () => {
1292
+ vi.useFakeTimers();
1293
+ try {
1294
+ const enabled = new MFUReassembler({ timeoutMs: null, maxBuffered: 1 });
1295
+ expect(
1296
+ enabled.addFragment({
1297
+ fragmentationIndicator: 3,
1298
+ mpuSequenceNumber: 1,
1299
+ fragmentCounter: 0,
1300
+ data: new Uint8Array([1]),
1301
+ timestamp: 1000n,
1302
+ rapFlag: false,
1303
+ packetSequenceNumber: testPacketSequence(1, 0)
1304
+ })
1305
+ ).toBeNull();
1306
+ enabled.timeoutMs = 10;
1307
+ vi.advanceTimersByTime(10);
1308
+ expect(enabled.pendingCount).toBe(0);
1309
+ const disabled = new MFUReassembler({ timeoutMs: 10, maxBuffered: 1 });
1310
+ expect(
1311
+ disabled.addFragment({
1312
+ fragmentationIndicator: 3,
1313
+ mpuSequenceNumber: 2,
1314
+ fragmentCounter: 0,
1315
+ data: new Uint8Array([2]),
1316
+ timestamp: 1000n,
1317
+ rapFlag: false,
1318
+ packetSequenceNumber: testPacketSequence(2, 0)
1319
+ })
1320
+ ).toBeNull();
1321
+ disabled.timeoutMs = null;
1322
+ vi.advanceTimersByTime(10);
1323
+ expect(disabled.pendingCount).toBe(1);
1324
+ disabled.flush();
1325
+ } finally {
1326
+ vi.useRealTimers();
1327
+ }
1328
+ });
1329
+ test("bounds active data units by evicting the oldest at maxBuffered", () => {
1330
+ const reassembler = new MFUReassembler({
1331
+ timeoutMs: 1e3,
1332
+ maxBuffered: 2
1333
+ });
1334
+ for (let i = 0; i < 2; i++) {
1335
+ reassembler.addFragment({
1336
+ fragmentationIndicator: 1,
1337
+ mpuSequenceNumber: i,
1338
+ fragmentCounter: 1,
1339
+ itemId: i,
1340
+ data: new Uint8Array([i]),
1341
+ timestamp: BigInt(i * 100),
1342
+ rapFlag: false,
1343
+ packetSequenceNumber: testPacketSequence(i, 1)
1344
+ });
1345
+ }
1346
+ expect(
1347
+ reassembler.addFragment({
1348
+ fragmentationIndicator: 1,
1349
+ mpuSequenceNumber: 2,
1350
+ fragmentCounter: 1,
1351
+ itemId: 2,
1352
+ data: new Uint8Array([2]),
1353
+ timestamp: 200n,
1354
+ rapFlag: false,
1355
+ packetSequenceNumber: testPacketSequence(2, 1)
1356
+ })
1357
+ ).toBeNull();
1358
+ expect(reassembler.pendingCount).toBe(2);
1359
+ expect(reassembler.stats.timedOutMFUs).toBe(0);
1360
+ expect(reassembler.stats.evictedMemoryLimit).toBe(1);
1361
+ expect(
1362
+ reassembler.addFragment({
1363
+ fragmentationIndicator: 3,
1364
+ mpuSequenceNumber: 0,
1365
+ fragmentCounter: 0,
1366
+ data: new Uint8Array([9]),
1367
+ timestamp: 300n,
1368
+ rapFlag: false,
1369
+ packetSequenceNumber: testPacketSequence(0, 0)
1370
+ })
1371
+ ).toBeNull();
1372
+ expect(reassembler.pendingCount).toBe(2);
1373
+ expect(reassembler.stats.evictedMemoryLimit).toBe(2);
1374
+ expect(reassembler.stats.timedOutMFUs).toBe(0);
1375
+ });
1376
+ test("should report stats correctly", () => {
1377
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1378
+ reassembler.addFragment({
1379
+ fragmentationIndicator: 0,
1380
+ mpuSequenceNumber: 1,
1381
+ fragmentCounter: 0,
1382
+ itemId: 1,
1383
+ data: new Uint8Array([1]),
1384
+ timestamp: 1000n,
1385
+ rapFlag: false
1386
+ });
1387
+ const status = reassembler.getStatus();
1388
+ expect(status.bufferedMFUs).toBe(0);
1389
+ expect(status.stats.totalFragments).toBe(1);
1390
+ expect(status.stats.reassembledMFUs).toBe(1);
1391
+ });
1392
+ test("rejects an overlapping first without replacing the original fragment", () => {
1393
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1394
+ reassembler.addFragment({
1395
+ fragmentationIndicator: 1,
1396
+ mpuSequenceNumber: 1,
1397
+ fragmentCounter: 1,
1398
+ itemId: 1,
1399
+ data: new Uint8Array([170]),
1400
+ timestamp: 1000n,
1401
+ rapFlag: true,
1402
+ source: "multicast",
1403
+ packetSequenceNumber: testPacketSequence(1, 1)
1404
+ });
1405
+ expectRejection(
1406
+ () => reassembler.addFragment({
1407
+ fragmentationIndicator: 1,
1408
+ mpuSequenceNumber: 1,
1409
+ fragmentCounter: 1,
1410
+ itemId: 2,
1411
+ data: new Uint8Array([187]),
1412
+ timestamp: 1000n,
1413
+ rapFlag: true,
1414
+ source: "moq",
1415
+ packetSequenceNumber: testPacketSequence(1, 1)
1416
+ }),
1417
+ "overlapping-data-unit"
1418
+ );
1419
+ const result = reassembler.addFragment({
1420
+ fragmentationIndicator: 3,
1421
+ mpuSequenceNumber: 1,
1422
+ fragmentCounter: 0,
1423
+ data: new Uint8Array([204]),
1424
+ timestamp: 1000n,
1425
+ rapFlag: false,
1426
+ packetSequenceNumber: testPacketSequence(1, 0)
1427
+ });
1428
+ expect(result).not.toBeNull();
1429
+ expect(result.data).toEqual(new Uint8Array([170, 204]));
1430
+ expect(result.fragmentCount).toBe(2);
1431
+ expect(result.source).toBe("multicast");
1432
+ });
1433
+ });
1434
+ test("should retain an assembly with a gap in fragment counters", () => {
1435
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1436
+ reassembler.addFragment({
1437
+ fragmentationIndicator: 1,
1438
+ mpuSequenceNumber: 1,
1439
+ fragmentCounter: 3,
1440
+ itemId: 1,
1441
+ data: new Uint8Array([170]),
1442
+ timestamp: 1000n,
1443
+ rapFlag: true,
1444
+ packetSequenceNumber: testPacketSequence(1, 3)
1445
+ });
1446
+ expect(
1447
+ reassembler.addFragment({
1448
+ fragmentationIndicator: 2,
1449
+ mpuSequenceNumber: 1,
1450
+ fragmentCounter: 1,
1451
+ data: new Uint8Array([204]),
1452
+ timestamp: 1000n,
1453
+ rapFlag: false,
1454
+ packetSequenceNumber: testPacketSequence(1, 1)
1455
+ })
1456
+ ).toBeNull();
1457
+ expect(
1458
+ reassembler.addFragment({
1459
+ fragmentationIndicator: 3,
1460
+ mpuSequenceNumber: 1,
1461
+ fragmentCounter: 0,
1462
+ data: new Uint8Array([221]),
1463
+ timestamp: 1000n,
1464
+ rapFlag: false,
1465
+ packetSequenceNumber: testPacketSequence(1, 0)
1466
+ })
1467
+ ).toBeNull();
1468
+ expect(reassembler.pendingCount).toBe(1);
1469
+ expect(reassembler.getStatus().pendingFragments).toBe(3);
1470
+ });
1471
+ test("accepts a reordered countdown and rejects a stale duplicate", () => {
1472
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1473
+ reassembler.addFragment({
1474
+ fragmentationIndicator: 1,
1475
+ mpuSequenceNumber: 1,
1476
+ fragmentCounter: 3,
1477
+ itemId: 1,
1478
+ data: new Uint8Array([170]),
1479
+ timestamp: 1000n,
1480
+ rapFlag: true,
1481
+ packetSequenceNumber: testPacketSequence(1, 3)
1482
+ });
1483
+ expect(
1484
+ reassembler.addFragment({
1485
+ fragmentationIndicator: 2,
1486
+ mpuSequenceNumber: 1,
1487
+ fragmentCounter: 1,
1488
+ data: new Uint8Array([204]),
1489
+ timestamp: 1000n,
1490
+ rapFlag: false,
1491
+ packetSequenceNumber: testPacketSequence(1, 1)
1492
+ })
1493
+ ).toBeNull();
1494
+ expect(
1495
+ reassembler.addFragment({
1496
+ fragmentationIndicator: 2,
1497
+ mpuSequenceNumber: 1,
1498
+ fragmentCounter: 2,
1499
+ data: new Uint8Array([187]),
1500
+ timestamp: 1000n,
1501
+ rapFlag: false,
1502
+ packetSequenceNumber: testPacketSequence(1, 2)
1503
+ })
1504
+ ).toBeNull();
1505
+ expectRejection(
1506
+ () => reassembler.addFragment({
1507
+ fragmentationIndicator: 2,
1508
+ mpuSequenceNumber: 1,
1509
+ fragmentCounter: 1,
1510
+ data: new Uint8Array([204]),
1511
+ timestamp: 1001n,
1512
+ rapFlag: false,
1513
+ packetSequenceNumber: testPacketSequence(1, 1)
1514
+ }),
1515
+ "fragment-counter-mismatch"
1516
+ );
1517
+ const result = reassembler.addFragment({
1518
+ fragmentationIndicator: 3,
1519
+ mpuSequenceNumber: 1,
1520
+ fragmentCounter: 0,
1521
+ data: new Uint8Array([221]),
1522
+ timestamp: 1002n,
1523
+ rapFlag: false,
1524
+ packetSequenceNumber: testPacketSequence(1, 0)
1525
+ });
1526
+ expect(result).not.toBeNull();
1527
+ expect(result.data).toEqual(new Uint8Array([170, 187, 204, 221]));
1528
+ expect(result.fragmentCount).toBe(4);
1529
+ });
1530
+ test("rejects an overlapping first without discarding queued continuations", () => {
1531
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1532
+ const fragment = (fragmentationIndicator, fragmentCounter, byte) => ({
1533
+ fragmentationIndicator,
1534
+ mpuSequenceNumber: 2,
1535
+ fragmentCounter,
1536
+ data: new Uint8Array([byte]),
1537
+ timestamp: 1000n,
1538
+ rapFlag: fragmentationIndicator === 1,
1539
+ packetSequenceNumber: testPacketSequence(2, fragmentCounter),
1540
+ ...fragmentationIndicator === 1 ? { itemId: 9 } : {}
1541
+ });
1542
+ expect(reassembler.addFragment(fragment(1, 3, 170))).toBeNull();
1543
+ expect(reassembler.addFragment(fragment(2, 1, 204))).toBeNull();
1544
+ expectRejection(() => reassembler.addFragment(fragment(1, 1, 238)), "overlapping-data-unit");
1545
+ expect(reassembler.addFragment(fragment(2, 2, 187))).toBeNull();
1546
+ expect(reassembler.addFragment(fragment(3, 0, 221))?.data).toEqual(new Uint8Array([170, 187, 204, 221]));
1547
+ });
1548
+ test("rejects a duplicate emitted intrinsic identity", () => {
1549
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1550
+ expect(
1551
+ reassembler.addFragment({
1552
+ fragmentationIndicator: 1,
1553
+ mpuSequenceNumber: 42,
1554
+ fragmentCounter: 1,
1555
+ itemId: 1,
1556
+ data: new Uint8Array([170]),
1557
+ timestamp: 1000n,
1558
+ rapFlag: true,
1559
+ packetSequenceNumber: testPacketSequence(42, 1)
1560
+ })
1561
+ ).toBeNull();
1562
+ expect(
1563
+ reassembler.addFragment({
1564
+ fragmentationIndicator: 3,
1565
+ mpuSequenceNumber: 42,
1566
+ fragmentCounter: 0,
1567
+ data: new Uint8Array([171]),
1568
+ timestamp: 1001n,
1569
+ rapFlag: false,
1570
+ packetSequenceNumber: testPacketSequence(42, 0)
1571
+ })
1572
+ ).not.toBeNull();
1573
+ expect(
1574
+ reassembler.addFragment({
1575
+ fragmentationIndicator: 3,
1576
+ mpuSequenceNumber: 42,
1577
+ fragmentCounter: 0,
1578
+ data: new Uint8Array([188]),
1579
+ timestamp: 1002n,
1580
+ rapFlag: false,
1581
+ packetSequenceNumber: testPacketSequence(42, 0, 10)
1582
+ })
1583
+ ).toBeNull();
1584
+ expect(reassembler.pendingCount).toBe(1);
1585
+ expect(
1586
+ reassembler.addFragment({
1587
+ fragmentationIndicator: 1,
1588
+ mpuSequenceNumber: 42,
1589
+ fragmentCounter: 1,
1590
+ itemId: 1,
1591
+ data: new Uint8Array([187]),
1592
+ timestamp: 2000n,
1593
+ rapFlag: true,
1594
+ packetSequenceNumber: testPacketSequence(42, 1, 10)
1595
+ })
1596
+ ).toBeNull();
1597
+ expect(reassembler.pendingCount).toBe(1);
1598
+ const result = reassembler.addFragment({
1599
+ fragmentationIndicator: 1,
1600
+ mpuSequenceNumber: 43,
1601
+ fragmentCounter: 1,
1602
+ itemId: 1,
1603
+ data: new Uint8Array([204]),
1604
+ timestamp: 2000n,
1605
+ rapFlag: false,
1606
+ packetSequenceNumber: testPacketSequence(43, 1)
1607
+ });
1608
+ expect(result).toBeNull();
1609
+ expect(
1610
+ reassembler.addFragment({
1611
+ fragmentationIndicator: 3,
1612
+ mpuSequenceNumber: 43,
1613
+ fragmentCounter: 0,
1614
+ data: new Uint8Array([221]),
1615
+ timestamp: 2001n,
1616
+ rapFlag: false,
1617
+ packetSequenceNumber: testPacketSequence(43, 0)
1618
+ })?.data
1619
+ ).toEqual(new Uint8Array([204, 221]));
1620
+ });
1621
+ test("does not create active state for an emitted identity duplicate", () => {
1622
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1623
+ expect(
1624
+ reassembler.addFragment({
1625
+ fragmentationIndicator: 1,
1626
+ mpuSequenceNumber: 50,
1627
+ fragmentCounter: 1,
1628
+ movieFragmentSequenceNumber: 10,
1629
+ sampleNumber: 18,
1630
+ sampleOffset: 0,
1631
+ data: new Uint8Array([161]),
1632
+ timestamp: 1000n,
1633
+ rapFlag: true,
1634
+ packetSequenceNumber: testPacketSequence(50, 1)
1635
+ })
1636
+ ).toBeNull();
1637
+ expect(
1638
+ reassembler.addFragment({
1639
+ fragmentationIndicator: 3,
1640
+ mpuSequenceNumber: 50,
1641
+ fragmentCounter: 0,
1642
+ data: new Uint8Array([178]),
1643
+ timestamp: 1000n,
1644
+ rapFlag: false,
1645
+ packetSequenceNumber: testPacketSequence(50, 0)
1646
+ })?.data
1647
+ ).toEqual(new Uint8Array([161, 178]));
1648
+ expect(reassembler.pendingCount).toBe(0);
1649
+ expect(
1650
+ reassembler.addFragment({
1651
+ fragmentationIndicator: 1,
1652
+ mpuSequenceNumber: 50,
1653
+ fragmentCounter: 1,
1654
+ movieFragmentSequenceNumber: 10,
1655
+ sampleNumber: 18,
1656
+ sampleOffset: 0,
1657
+ data: new Uint8Array([161]),
1658
+ timestamp: 2000n,
1659
+ rapFlag: true,
1660
+ packetSequenceNumber: testPacketSequence(50, 1, 10)
1661
+ })
1662
+ ).toBeNull();
1663
+ expect(reassembler.pendingCount).toBe(0);
1664
+ });
1665
+ test("flush should clear emitted set and allow re-assembly", () => {
1666
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1667
+ const first = reassembler.addFragment({
1668
+ fragmentationIndicator: 1,
1669
+ mpuSequenceNumber: 42,
1670
+ fragmentCounter: 1,
1671
+ itemId: 1,
1672
+ data: new Uint8Array([170]),
1673
+ timestamp: 1000n,
1674
+ rapFlag: true,
1675
+ packetSequenceNumber: testPacketSequence(42, 1)
1676
+ });
1677
+ expect(first).toBeNull();
1678
+ const assembled = reassembler.addFragment({
1679
+ fragmentationIndicator: 3,
1680
+ mpuSequenceNumber: 42,
1681
+ fragmentCounter: 0,
1682
+ data: new Uint8Array([187]),
1683
+ timestamp: 1000n,
1684
+ rapFlag: true,
1685
+ packetSequenceNumber: testPacketSequence(42, 0)
1686
+ });
1687
+ expect(assembled).not.toBeNull();
1688
+ expect(
1689
+ reassembler.addFragment({
1690
+ fragmentationIndicator: 1,
1691
+ mpuSequenceNumber: 42,
1692
+ fragmentCounter: 1,
1693
+ itemId: 1,
1694
+ data: new Uint8Array([204]),
1695
+ timestamp: 1000n,
1696
+ rapFlag: true,
1697
+ packetSequenceNumber: testPacketSequence(42, 1, 10)
1698
+ })
1699
+ ).toBeNull();
1700
+ reassembler.flush();
1701
+ const r2 = reassembler.addFragment({
1702
+ fragmentationIndicator: 1,
1703
+ mpuSequenceNumber: 42,
1704
+ fragmentCounter: 1,
1705
+ itemId: 1,
1706
+ data: new Uint8Array([221]),
1707
+ timestamp: 1000n,
1708
+ rapFlag: true,
1709
+ packetSequenceNumber: testPacketSequence(42, 1)
1710
+ });
1711
+ expect(r2).toBeNull();
1712
+ const r3 = reassembler.addFragment({
1713
+ fragmentationIndicator: 3,
1714
+ mpuSequenceNumber: 42,
1715
+ fragmentCounter: 0,
1716
+ data: new Uint8Array([238]),
1717
+ timestamp: 1000n,
1718
+ rapFlag: true,
1719
+ packetSequenceNumber: testPacketSequence(42, 0)
1720
+ });
1721
+ expect(r3).not.toBeNull();
1722
+ expect(r3.data).toEqual(new Uint8Array([221, 238]));
1723
+ });
1724
+ describe("createFragment", () => {
1725
+ test("should create fragment from complete timed MMTP packet", () => {
1726
+ const packet = new Uint8Array(12 + 8 + 14 + 5);
1727
+ packet[0] = 1;
1728
+ packet[1] = 0;
1729
+ const view = new DataView(packet.buffer);
1730
+ view.setUint16(2, 1, false);
1731
+ view.setUint32(4, 42, false);
1732
+ view.setUint32(8, 100, false);
1733
+ view.setUint16(12, 25, false);
1734
+ packet[14] = 40;
1735
+ packet[15] = 0;
1736
+ view.setUint32(16, 999, false);
1737
+ view.setUint32(20, 7, false);
1738
+ view.setUint32(24, 1, false);
1739
+ packet[34] = 222;
1740
+ packet[35] = 173;
1741
+ packet[36] = 190;
1742
+ packet[37] = 239;
1743
+ packet[38] = 1;
1744
+ const frag = createFragment(packet);
1745
+ expect(frag.mpuSequenceNumber).toBe(999);
1746
+ expect(frag.fragmentationIndicator).toBe(0);
1747
+ expect(frag.rapFlag).toBe(true);
1748
+ expect(frag.movieFragmentSequenceNumber).toBe(7);
1749
+ expect(frag.sampleNumber).toBe(1);
1750
+ expect(frag.sampleOffset).toBe(0);
1751
+ expect(frag.data.length).toBe(5);
1752
+ });
1753
+ test("reads Item_ID from a non-timed MFU DU header", () => {
1754
+ const packet = new Uint8Array(12 + 8 + 4 + 2);
1755
+ const view = new DataView(packet.buffer);
1756
+ view.setUint16(2, 1, false);
1757
+ view.setUint32(4, 42, false);
1758
+ view.setUint32(8, 100, false);
1759
+ view.setUint16(12, 12, false);
1760
+ packet[14] = 32;
1761
+ view.setUint32(16, 999, false);
1762
+ view.setUint32(20, 16909060, false);
1763
+ packet.set([222, 173], 24);
1764
+ const fragment = createFragment(packet);
1765
+ expect(fragment.itemId).toBe(16909060);
1766
+ expect(fragment.data).toEqual(new Uint8Array([222, 173]));
1767
+ });
1768
+ });
1769
+ describe("processMMTPWithReassembly", () => {
1770
+ test("should skip FEC repair packets", () => {
1771
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1772
+ const packet = new Uint8Array(12 + 8 + 14 + 4);
1773
+ packet[0] = 16;
1774
+ const result = processMMTPWithReassembly(packet, reassembler);
1775
+ expect(result).toBeNull();
1776
+ });
1777
+ test("should return reassembled MFU for complete packet", () => {
1778
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1779
+ const packet = new Uint8Array(12 + 8 + 14 + 4);
1780
+ packet[0] = 1;
1781
+ packet[1] = 0;
1782
+ const view = new DataView(packet.buffer);
1783
+ view.setUint16(2, 1, false);
1784
+ view.setUint32(4, 100, false);
1785
+ view.setUint32(8, 1, false);
1786
+ view.setUint16(12, 24, false);
1787
+ packet[14] = 40;
1788
+ view.setUint32(16, 42, false);
1789
+ view.setUint32(20, 7, false);
1790
+ view.setUint32(24, 1, false);
1791
+ packet[34] = 0;
1792
+ packet[35] = 0;
1793
+ packet[36] = 0;
1794
+ packet[37] = 1;
1795
+ const result = processMMTPWithReassembly(packet, reassembler);
1796
+ expect(result).not.toBeNull();
1797
+ expect(result.mpuSequenceNumber).toBe(42);
1798
+ expect(result.rapFlag).toBe(true);
1799
+ });
1800
+ });
1801
+ describe("strict delivery provenance", () => {
1802
+ test("folds to multicast only when every fragment is explicitly multicast", () => {
1803
+ expect(deliveryProvenanceOf([{ source: "multicast" }, { source: "multicast" }])).toBe("multicast");
1804
+ });
1805
+ test("a single moq fragment makes the whole frame mixed", () => {
1806
+ expect(deliveryProvenanceOf([{ source: "multicast" }, { source: "moq" }])).toBe("mixed");
1807
+ expect(deliveryProvenanceOf([{ source: "moq" }, { source: "multicast" }])).toBe("mixed");
1808
+ });
1809
+ test("an unattributed fragment degrades multicast to unknown, never to proven", () => {
1810
+ expect(deliveryProvenanceOf([{ source: "multicast" }, {}])).toBe("unknown");
1811
+ expect(deliveryProvenanceOf([{}])).toBe("unknown");
1812
+ });
1813
+ test("mixed absorbs unknown \u2014 a moq byte is worse news than a missing label", () => {
1814
+ expect(deliveryProvenanceOf([{ source: "moq" }, {}])).toBe("mixed");
1815
+ expect(deliveryProvenanceOf([{}, { source: "moq" }])).toBe("mixed");
1816
+ });
1817
+ test("an empty fragment set proves nothing", () => {
1818
+ expect(deliveryProvenanceOf([])).toBe("unknown");
1819
+ });
1820
+ test("the fold never upgrades a verdict", () => {
1821
+ expect(foldDeliveryProvenance("mixed", "multicast")).toBe("mixed");
1822
+ expect(foldDeliveryProvenance("unknown", "multicast")).toBe("unknown");
1823
+ expect(foldDeliveryProvenance("unknown", "moq")).toBe("mixed");
1824
+ });
1825
+ test("a multicast head with a non-multicast tail is NOT multicast-exclusive", () => {
1826
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1827
+ reassembler.addFragment({
1828
+ fragmentationIndicator: 1,
1829
+ mpuSequenceNumber: 1,
1830
+ fragmentCounter: 1,
1831
+ itemId: 1,
1832
+ data: new Uint8Array([170]),
1833
+ timestamp: 1000n,
1834
+ rapFlag: true,
1835
+ source: "multicast",
1836
+ packetSequenceNumber: testPacketSequence(1, 1)
1837
+ });
1838
+ const result = reassembler.addFragment({
1839
+ fragmentationIndicator: 3,
1840
+ mpuSequenceNumber: 1,
1841
+ fragmentCounter: 0,
1842
+ data: new Uint8Array([204]),
1843
+ timestamp: 1000n,
1844
+ rapFlag: false,
1845
+ source: "moq",
1846
+ packetSequenceNumber: testPacketSequence(1, 0)
1847
+ });
1848
+ expect(result).not.toBeNull();
1849
+ expect(result.fragmentCount).toBe(2);
1850
+ expect(result.source).toBe("multicast");
1851
+ expect(result.deliveryProvenance).toBe("mixed");
1852
+ });
1853
+ test("an all-multicast fragmented frame is multicast-exclusive", () => {
1854
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1855
+ reassembler.addFragment({
1856
+ fragmentationIndicator: 1,
1857
+ mpuSequenceNumber: 2,
1858
+ fragmentCounter: 1,
1859
+ itemId: 1,
1860
+ data: new Uint8Array([170]),
1861
+ timestamp: 2000n,
1862
+ rapFlag: true,
1863
+ source: "multicast",
1864
+ packetSequenceNumber: testPacketSequence(2, 1)
1865
+ });
1866
+ const result = reassembler.addFragment({
1867
+ fragmentationIndicator: 3,
1868
+ mpuSequenceNumber: 2,
1869
+ fragmentCounter: 0,
1870
+ data: new Uint8Array([204]),
1871
+ timestamp: 2000n,
1872
+ rapFlag: false,
1873
+ source: "multicast",
1874
+ packetSequenceNumber: testPacketSequence(2, 0)
1875
+ });
1876
+ expect(result).not.toBeNull();
1877
+ expect(result.deliveryProvenance).toBe("multicast");
1878
+ });
1879
+ test("an unlabelled complete frame proves nothing", () => {
1880
+ const reassembler = new MFUReassembler({ timeoutMs: 1e3 });
1881
+ const result = reassembler.addFragment({
1882
+ fragmentationIndicator: 0,
1883
+ mpuSequenceNumber: 3,
1884
+ fragmentCounter: 0,
1885
+ itemId: 1,
1886
+ data: new Uint8Array([1]),
1887
+ timestamp: 3000n,
1888
+ rapFlag: true
1889
+ });
1890
+ expect(result).not.toBeNull();
1891
+ expect(result.deliveryProvenance).toBe("unknown");
1892
+ });
1893
+ });
1894
+ }
1895
+
1896
+ // src/wasm-mfu-reassembler.ts
1897
+ function asNumber(value) {
1898
+ return typeof value === "bigint" ? Number(value) : value;
1899
+ }
1900
+ function timestampU32(timestamp) {
1901
+ return Number(BigInt.asUintN(32, timestamp));
1902
+ }
1903
+ var _bindings, _core, _now, _timeoutMs, _cleanupTimer, _nextStreamIdentity, _streamIdentityByKey, _streamNameByIdentity, _coreTotalFragments, _rejectedBeforeCore, _rejectedFragments, _WasmMfuReassembler_instances, refreshStats_fn, streamIdentityFor_fn, asReassemblyError_fn, scheduleCleanup_fn, clearCleanupTimer_fn;
1904
+ var WasmMfuReassembler = class {
1905
+ constructor(options) {
1906
+ __privateAdd(this, _WasmMfuReassembler_instances);
1907
+ __privateAdd(this, _bindings);
1908
+ __privateAdd(this, _core);
1909
+ __privateAdd(this, _now);
1910
+ __privateAdd(this, _timeoutMs);
1911
+ __privateAdd(this, _cleanupTimer, null);
1912
+ __privateAdd(this, _nextStreamIdentity, 1);
1913
+ __privateAdd(this, _streamIdentityByKey, /* @__PURE__ */ new Map());
1914
+ __privateAdd(this, _streamNameByIdentity, /* @__PURE__ */ new Map());
1915
+ __privateAdd(this, _coreTotalFragments, 0);
1916
+ __privateAdd(this, _rejectedBeforeCore, 0);
1917
+ __privateAdd(this, _rejectedFragments, 0);
1918
+ this.stats = {
1919
+ totalFragments: 0,
1920
+ reassembledMFUs: 0,
1921
+ rejectedFragments: 0,
1922
+ timedOutMFUs: 0,
1923
+ evictedMemoryLimit: 0,
1924
+ outOfOrderFragments: 0
1925
+ };
1926
+ const maxBuffered = options.maxBuffered ?? 100;
1927
+ if (!Number.isInteger(maxBuffered) || maxBuffered <= 0) {
1928
+ throw new Error("[WasmMfuReassembler] maxBuffered must be a positive integer");
1929
+ }
1930
+ __privateSet(this, _bindings, options.bindings);
1931
+ __privateSet(this, _timeoutMs, options.timeoutMs);
1932
+ __privateSet(this, _now, options.now ?? (() => globalThis.performance?.now() ?? Date.now()));
1933
+ __privateSet(this, _core, options.timeoutMs === null ? options.bindings.MmtReassembler.clock_free(maxBuffered) : new options.bindings.MmtReassembler(options.timeoutMs, maxBuffered));
1934
+ }
1935
+ get timeoutMs() {
1936
+ return __privateGet(this, _timeoutMs);
1937
+ }
1938
+ set timeoutMs(timeoutMs) {
1939
+ if (timeoutMs !== null && (!Number.isFinite(timeoutMs) || timeoutMs <= 0)) {
1940
+ throw new Error("[WasmMfuReassembler] timeoutMs must be a finite number > 0");
1941
+ }
1942
+ __privateSet(this, _timeoutMs, timeoutMs);
1943
+ if (timeoutMs === null) __privateGet(this, _core).set_clock_free();
1944
+ else __privateGet(this, _core).set_timeout(Math.ceil(timeoutMs));
1945
+ __privateMethod(this, _WasmMfuReassembler_instances, scheduleCleanup_fn).call(this);
1946
+ }
1947
+ addFragment(fragment) {
1948
+ const wasmFragment = new (__privateGet(this, _bindings)).MfuFragmentJs(
1949
+ fragment.mpuSequenceNumber,
1950
+ fragment.fragmentationIndicator,
1951
+ fragment.fragmentCounter,
1952
+ fragment.data,
1953
+ timestampU32(fragment.timestamp),
1954
+ fragment.rapFlag
1955
+ );
1956
+ if (fragment.movieFragmentSequenceNumber !== void 0 && fragment.sampleNumber !== void 0 && fragment.sampleNumber > 0 && fragment.sampleOffset !== void 0) {
1957
+ wasmFragment.with_sample_identity(
1958
+ fragment.movieFragmentSequenceNumber,
1959
+ fragment.sampleNumber,
1960
+ fragment.sampleOffset
1961
+ );
1962
+ }
1963
+ if (fragment.itemId !== void 0) wasmFragment.set_item_id(fragment.itemId);
1964
+ if (fragment.packetSequenceNumber !== void 0) {
1965
+ wasmFragment.set_packet_delivery?.(
1966
+ fragment.packetSequenceNumber,
1967
+ fragment.recovered === true
1968
+ );
1969
+ }
1970
+ if (fragment.priority !== void 0) wasmFragment.set_priority(fragment.priority);
1971
+ if (fragment.source !== void 0) {
1972
+ wasmFragment.set_attribution(fragment.source === "multicast" ? 1 : 2);
1973
+ }
1974
+ const streamIdentity = __privateMethod(this, _WasmMfuReassembler_instances, streamIdentityFor_fn).call(this, fragment);
1975
+ if (streamIdentity !== void 0) {
1976
+ wasmFragment.set_stream_identity(streamIdentity);
1977
+ }
1978
+ let output;
1979
+ const coreTotalBefore = __privateGet(this, _coreTotalFragments);
1980
+ try {
1981
+ output = __privateGet(this, _core).add_fragment(__privateGet(this, _now).call(this), wasmFragment);
1982
+ } catch (error) {
1983
+ const rejection = __privateMethod(this, _WasmMfuReassembler_instances, asReassemblyError_fn).call(this, error);
1984
+ if (rejection === null) throw error;
1985
+ __privateMethod(this, _WasmMfuReassembler_instances, refreshStats_fn).call(this);
1986
+ if (__privateGet(this, _coreTotalFragments) === coreTotalBefore) __privateWrapper(this, _rejectedBeforeCore)._++;
1987
+ __privateWrapper(this, _rejectedFragments)._++;
1988
+ this.stats.totalFragments = __privateGet(this, _coreTotalFragments) + __privateGet(this, _rejectedBeforeCore);
1989
+ this.stats.rejectedFragments = __privateGet(this, _rejectedFragments);
1990
+ __privateMethod(this, _WasmMfuReassembler_instances, scheduleCleanup_fn).call(this);
1991
+ throw rejection;
1992
+ }
1993
+ __privateMethod(this, _WasmMfuReassembler_instances, refreshStats_fn).call(this);
1994
+ __privateMethod(this, _WasmMfuReassembler_instances, scheduleCleanup_fn).call(this);
1995
+ if (!output) return null;
1996
+ try {
1997
+ const catalogTrackName = output.stream_identity === void 0 ? void 0 : __privateGet(this, _streamNameByIdentity).get(output.stream_identity);
1998
+ const packetSequenceNumbers = output.packet_sequence_numbers === void 0 ? void 0 : Array.from(output.packet_sequence_numbers);
1999
+ const repairedPacketSequenceNumbers = output.repaired_packet_sequence_numbers === void 0 ? void 0 : Array.from(output.repaired_packet_sequence_numbers);
2000
+ return {
2001
+ mpuSequenceNumber: output.mpu_sequence_number,
2002
+ ...packetSequenceNumbers?.[0] === void 0 ? {} : { packetSequenceNumber: packetSequenceNumbers[0] },
2003
+ ...packetSequenceNumbers === void 0 ? {} : { packetSequenceNumbers },
2004
+ ...repairedPacketSequenceNumbers === void 0 ? {} : { repairedPacketSequenceNumbers },
2005
+ data: output.data,
2006
+ timestamp: BigInt(output.timestamp),
2007
+ fragmentCount: output.fragment_count,
2008
+ rapFlag: output.rap_flag,
2009
+ ...output.priority === void 0 ? {} : { priority: output.priority },
2010
+ ...output.sample_number === void 0 ? {} : { sampleNumber: output.sample_number },
2011
+ ...output.movie_fragment_sequence_number === void 0 ? {} : {
2012
+ movieFragmentSequenceNumber: output.movie_fragment_sequence_number
2013
+ },
2014
+ ...output.attribution === 1 ? { source: "multicast" } : output.attribution === 2 ? { source: "moq" } : {},
2015
+ // The Rust core folds `attribution` over every contributing fragment
2016
+ // and reports None unless they were unanimous, so a tag here is
2017
+ // already whole-frame evidence. A missing tag means "not unanimous or
2018
+ // never recorded" — both unproven, never multicast.
2019
+ deliveryProvenance: output.attribution === 1 ? "multicast" : output.attribution === 2 ? "mixed" : "unknown",
2020
+ ...catalogTrackName === void 0 ? {} : { catalogTrackName }
2021
+ };
2022
+ } finally {
2023
+ output.free();
2024
+ }
2025
+ }
2026
+ flush() {
2027
+ __privateMethod(this, _WasmMfuReassembler_instances, clearCleanupTimer_fn).call(this);
2028
+ __privateGet(this, _core).flush();
2029
+ }
2030
+ resetStream(catalogTrackName) {
2031
+ const streamIdentity = __privateGet(this, _streamIdentityByKey).get(`catalog:${catalogTrackName}`);
2032
+ if (streamIdentity === void 0) return;
2033
+ __privateMethod(this, _WasmMfuReassembler_instances, clearCleanupTimer_fn).call(this);
2034
+ __privateGet(this, _core).reset_stream(streamIdentity);
2035
+ __privateMethod(this, _WasmMfuReassembler_instances, refreshStats_fn).call(this);
2036
+ __privateMethod(this, _WasmMfuReassembler_instances, scheduleCleanup_fn).call(this);
2037
+ }
2038
+ reset() {
2039
+ __privateMethod(this, _WasmMfuReassembler_instances, clearCleanupTimer_fn).call(this);
2040
+ __privateGet(this, _core).reset();
2041
+ __privateSet(this, _nextStreamIdentity, 1);
2042
+ __privateGet(this, _streamIdentityByKey).clear();
2043
+ __privateGet(this, _streamNameByIdentity).clear();
2044
+ __privateSet(this, _coreTotalFragments, 0);
2045
+ __privateSet(this, _rejectedBeforeCore, 0);
2046
+ __privateSet(this, _rejectedFragments, 0);
2047
+ __privateMethod(this, _WasmMfuReassembler_instances, refreshStats_fn).call(this);
2048
+ }
2049
+ get pendingCount() {
2050
+ return __privateGet(this, _core).buffered_count;
2051
+ }
2052
+ getStatus() {
2053
+ __privateMethod(this, _WasmMfuReassembler_instances, refreshStats_fn).call(this);
2054
+ return {
2055
+ bufferedMFUs: __privateGet(this, _core).buffered_count,
2056
+ pendingFragments: __privateGet(this, _core).pending_fragment_count,
2057
+ // Detailed fragment coordinates remain internal to the Rust core. Counts
2058
+ // and health statistics stay available to MmtpRouter diagnostics.
2059
+ pendingSamples: [],
2060
+ stats: { ...this.stats }
2061
+ };
2062
+ }
2063
+ };
2064
+ _bindings = new WeakMap();
2065
+ _core = new WeakMap();
2066
+ _now = new WeakMap();
2067
+ _timeoutMs = new WeakMap();
2068
+ _cleanupTimer = new WeakMap();
2069
+ _nextStreamIdentity = new WeakMap();
2070
+ _streamIdentityByKey = new WeakMap();
2071
+ _streamNameByIdentity = new WeakMap();
2072
+ _coreTotalFragments = new WeakMap();
2073
+ _rejectedBeforeCore = new WeakMap();
2074
+ _rejectedFragments = new WeakMap();
2075
+ _WasmMfuReassembler_instances = new WeakSet();
2076
+ refreshStats_fn = function() {
2077
+ const stats = __privateGet(this, _core).stats();
2078
+ __privateSet(this, _coreTotalFragments, asNumber(stats.total_fragments));
2079
+ this.stats.totalFragments = __privateGet(this, _coreTotalFragments) + __privateGet(this, _rejectedBeforeCore);
2080
+ this.stats.reassembledMFUs = asNumber(stats.reassembled_mfus);
2081
+ this.stats.rejectedFragments = __privateGet(this, _rejectedFragments);
2082
+ this.stats.timedOutMFUs = asNumber(stats.timed_out_mfus);
2083
+ this.stats.evictedMemoryLimit = asNumber(stats.evicted_memory_limit) + asNumber(stats.evicted_data_units ?? 0);
2084
+ this.stats.outOfOrderFragments = asNumber(stats.out_of_order_fragments);
2085
+ stats.free?.();
2086
+ };
2087
+ streamIdentityFor_fn = function(fragment) {
2088
+ const key = fragment.catalogTrackName !== void 0 ? `catalog:${fragment.catalogTrackName}` : fragment.packetId !== void 0 ? `packet:${fragment.packetId}` : void 0;
2089
+ if (key === void 0) return void 0;
2090
+ const existing = __privateGet(this, _streamIdentityByKey).get(key);
2091
+ if (existing !== void 0) return existing;
2092
+ const identity = __privateWrapper(this, _nextStreamIdentity)._++;
2093
+ __privateGet(this, _streamIdentityByKey).set(key, identity);
2094
+ if (fragment.catalogTrackName !== void 0) {
2095
+ __privateGet(this, _streamNameByIdentity).set(identity, fragment.catalogTrackName);
2096
+ }
2097
+ return identity;
2098
+ };
2099
+ asReassemblyError_fn = function(error) {
2100
+ if (typeof error !== "object" && typeof error !== "function" || error === null) return null;
2101
+ const code = Reflect.get(error, "code");
2102
+ if (!isMfuReassemblyErrorCode(code)) return null;
2103
+ const message = Reflect.get(error, "message");
2104
+ return new MfuReassemblyError(
2105
+ code,
2106
+ typeof message === "string" ? message : `MFU reassembly rejected: ${code}`
2107
+ );
2108
+ };
2109
+ scheduleCleanup_fn = function() {
2110
+ __privateMethod(this, _WasmMfuReassembler_instances, clearCleanupTimer_fn).call(this);
2111
+ if (__privateGet(this, _timeoutMs) === null) return;
2112
+ const next = __privateGet(this, _core).next_timeout_at();
2113
+ if (next === void 0) return;
2114
+ const delay = Math.max(0, Math.ceil(next - __privateGet(this, _now).call(this)));
2115
+ __privateSet(this, _cleanupTimer, setTimeout(() => {
2116
+ __privateSet(this, _cleanupTimer, null);
2117
+ __privateGet(this, _core).cleanup_timeouts(__privateGet(this, _now).call(this));
2118
+ __privateMethod(this, _WasmMfuReassembler_instances, refreshStats_fn).call(this);
2119
+ __privateMethod(this, _WasmMfuReassembler_instances, scheduleCleanup_fn).call(this);
2120
+ }, delay));
2121
+ };
2122
+ clearCleanupTimer_fn = function() {
2123
+ if (__privateGet(this, _cleanupTimer) === null) return;
2124
+ clearTimeout(__privateGet(this, _cleanupTimer));
2125
+ __privateSet(this, _cleanupTimer, null);
2126
+ };
2127
+ function resolveGlobalMmtWasmBindings() {
2128
+ const globals = globalThis;
2129
+ const bindings = globals.__MmtWasmBindings ?? globals.__blockcastMmtReassemblerWasmBindgen;
2130
+ if (!bindings?.MmtReassembler || !bindings.MfuFragmentJs) {
2131
+ throw new Error("[WasmMfuReassembler] initialized mmt-wasm bindings are unavailable");
2132
+ }
2133
+ return bindings;
2134
+ }
2135
+ export {
2136
+ WasmMfuReassembler,
2137
+ resolveGlobalMmtWasmBindings
2138
+ };
2139
+ //# sourceMappingURL=wasm-mfu-reassembler.js.map