@blockcast/mmt-container 0.1.0-main.149f78a4adae

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