@blockcast/mmt-container 0.1.0 → 0.3.0-main.288475b64b3e

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