@blockcast/mmt-container 0.1.0 → 0.3.0

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