@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,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../fec-worker/src/fec-worker-client.ts", "../../fec-worker/src/shred-worker-client.ts", "../../fec-worker/src/index.ts", "../src/fec-worker-setup.ts", "../src/track-session.ts"],
4
+ "sourcesContent": ["/**\n * @blockcast/fec-worker \u2014 Main-Thread Client\n *\n * Wraps one Worker per track instance. Provides typed API for the\n * FecWorkerCommand/FecWorkerEvent protocol with zero-copy ArrayBuffer transfers.\n *\n * Constructor accepts either a URL (creates Worker internally) or a pre-created\n * Worker instance (for testing via constructor injection).\n */\n\nimport type {\n\tFecWorkerCommand,\n\tFecWorkerEvent,\n\tFecTrackConfig,\n\tFecTrackStats,\n\tFecBlockSnapshot,\n\tFrameMeta,\n\tFecWorkerErrorCode,\n} from \"./fec-worker-types.js\";\n\nexport class FecWorkerClient {\n\treadonly #worker: Worker;\n\t#onFrame: ((data: ArrayBuffer, meta: FrameMeta) => void) | null = null;\n\t#onSnapshot: ((stats: FecTrackStats) => void) | null = null;\n\t#onBlockUpdate: ((block: FecBlockSnapshot) => void) | null = null;\n\t#onGreenFill: ((sbn: number, data: ArrayBuffer) => void) | null = null;\n\t#onCleanupComplete: ((sbn: number) => void) | null = null;\n\t#onError: ((message: string, code?: FecWorkerErrorCode) => void) | null = null;\n\t#cleanupInFlight: Set<number> | null = null;\n\t#queuedCleanupSbns = new Set<number>();\n\t#pendingResets = 0;\n\t#resetFailed = false;\n\t#disposed = false;\n\n\t/**\n\t * Create a FecWorkerClient.\n\t * @param workerOrUrl - Either a Worker instance (for testing) or a URL to create one\n\t */\n\tconstructor(workerOrUrl: Worker | URL) {\n\t\tif (workerOrUrl instanceof URL) {\n\t\t\tthis.#worker = new Worker(workerOrUrl, { type: \"module\" });\n\t\t} else {\n\t\t\tthis.#worker = workerOrUrl;\n\t\t}\n\t\tthis.#worker.onmessage = (e: MessageEvent<FecWorkerEvent>) =>\n\t\t\tthis.#handleEvent(e.data);\n\t\tthis.#worker.onerror = (e) => {\n\t\t\tthis.#onError?.(formatWorkerError(e), \"worker-runtime\");\n\t\t};\n\t\tthis.#worker.onmessageerror = (e) => {\n\t\t\tthis.#onError?.(formatWorkerMessageError(e), \"worker-message\");\n\t\t};\n\t}\n\n\t/**\n\t * Configure the Worker with FEC parameters and WASM module.\n\t * wasmModule is transferred (not neutered \u2014 WebAssembly.Module is shareable).\n\t * altaPublicKey is PKCS#8 SPKI DER bytes (self-describing \u2014 algorithm detected from OID).\n\t * Transferred (detached from sender).\n\t * altaWasmModule is structured-cloneable (NOT transferable \u2014 do not add to transfer list).\n\t */\n\tconfigure(\n\t\tconfig: FecTrackConfig,\n\t\twasmModule: WebAssembly.Module,\n\t\taltaPublicKey?: ArrayBuffer,\n\t\taltaWasmModule?: WebAssembly.Module,\n\t): void {\n\t\tif (this.#disposed) throw new Error(\"[FecWorkerClient] disposed\");\n\t\tconst cmd: FecWorkerCommand = {\n\t\t\ttype: \"configure\",\n\t\t\tconfig,\n\t\t\twasmModule,\n\t\t\taltaPublicKey,\n\t\t\taltaWasmModule,\n\t\t};\n\t\t// WebAssembly.Module is structured-cloneable, NOT transferable.\n\t\t// Pass it in the message body (Chrome clones it automatically).\n\t\t// Only ArrayBuffers (like altaPublicKey) go in the transfer list.\n\t\tconst transferList: Transferable[] = [];\n\t\tif (altaPublicKey) transferList.push(altaPublicKey);\n\t\t// altaWasmModule is structured-cloneable \u2014 NOT added to transferList\n\t\tthis.#worker.postMessage(cmd, transferList);\n\t}\n\n\t/**\n\t * Feed a source symbol to the Worker. data ArrayBuffer is transferred (zero-copy).\n\t * Caller must not access data after this call \u2014 it is detached.\n\t *\n\t * Optional `alta` carries the detached ALTA authenticator bytes and the\n\t * byte offset in `data` where the signed payload ends. The auth buffer is\n\t * transferred zero-copy alongside `data`. Use {@link getMmtpAltaTrailer}\n\t * upstream (mmtp-router) to extract it from the wire packet.\n\t */\n\tfeedSource(\n\t\tssId: number,\n\t\tdata: ArrayBuffer,\n\t\tts: number,\n\t\talta?: { auth: ArrayBuffer; payloadEnd: number },\n\t): void {\n\t\tif (this.#disposed) return;\n\t\tconst cmd: FecWorkerCommand = alta\n\t\t\t? {\n\t\t\t\t\ttype: \"feedSource\",\n\t\t\t\t\tssId,\n\t\t\t\t\tdata,\n\t\t\t\t\tts,\n\t\t\t\t\taltaAuth: alta.auth,\n\t\t\t\t\taltaPayloadEnd: alta.payloadEnd,\n\t\t\t\t}\n\t\t\t: { type: \"feedSource\", ssId, data, ts };\n\t\tconst transfer: Transferable[] = alta ? [data, alta.auth] : [data];\n\t\tthis.#worker.postMessage(cmd, transfer);\n\t}\n\n\t/**\n\t * Feed a repair symbol to the Worker. data ArrayBuffer is transferred (zero-copy).\n\t * Caller must not access data after this call \u2014 it is detached.\n\t *\n\t * Carries the wire-level Repair FEC Payload ID fields (ISO 23008-1 \u00A7C.5.3):\n\t * - ssStart: SS_ID of first source symbol in the block (= SBN * SSB_length)\n\t * - ssbLength: K for this block\n\t * - rsId: repair symbol index within the block\n\t */\n\tfeedRepair(\n\t\tssStart: number,\n\t\tssbLength: number,\n\t\trsId: number,\n\t\tdata: ArrayBuffer,\n\t\tts: number,\n\t): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#worker.postMessage(\n\t\t\t{\n\t\t\t\ttype: \"feedRepair\",\n\t\t\t\tssStart,\n\t\t\t\tssbLength,\n\t\t\t\trsId,\n\t\t\t\tdata,\n\t\t\t\tts,\n\t\t\t} satisfies FecWorkerCommand,\n\t\t\t[data],\n\t\t);\n\t}\n\n\t/**\n\t * Submit relay block signature for verification. sig and hash are transferred.\n\t */\n\trelayBlockSig(sbn: number, sig: ArrayBuffer, hash: ArrayBuffer): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#worker.postMessage(\n\t\t\t{ type: \"relayBlockSig\", sbn, sig, hash } satisfies FecWorkerCommand,\n\t\t\t[sig, hash],\n\t\t);\n\t}\n\n\t/**\n\t * Trigger cleanup after a block's inactivity deadline.\n\t *\n\t * While one queue-drain barrier is in flight, later SBNs are coalesced into\n\t * the next command without losing their individual acknowledgement identity.\n\t */\n\tcleanup(currentSbn: number): void {\n\t\tif (this.#disposed) return;\n\t\tif (\n\t\t\t!Number.isInteger(currentSbn) ||\n\t\t\tcurrentSbn < 0 ||\n\t\t\tcurrentSbn > 0xffff_ffff\n\t\t) {\n\t\t\tthrow new Error(\"[FecWorkerClient] cleanup: SBN must be a uint32\");\n\t\t}\n\t\tif (this.#cleanupInFlight) {\n\t\t\tthis.#queuedCleanupSbns.add(currentSbn);\n\t\t\treturn;\n\t\t}\n\t\tthis.#postCleanup(new Set([currentSbn]));\n\t}\n\n\t/** Reset this track's decoder epoch while preserving Worker configuration. */\n\treset(): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#pendingResets++;\n\t\tthis.#cleanupInFlight = null;\n\t\tthis.#queuedCleanupSbns.clear();\n\t\tthis.#worker.postMessage({ type: \"reset\" } satisfies FecWorkerCommand);\n\t}\n\n\t#postCleanup(sbns: Set<number>): void {\n\t\tthis.#cleanupInFlight = sbns;\n\t\tconst orderedSbns = [...sbns].sort((a, b) => a - b);\n\t\tthis.#worker.postMessage(\n\t\t\t{ type: \"cleanup\", sbns: orderedSbns } satisfies FecWorkerCommand,\n\t\t);\n\t}\n\n\t/** Register callback for decoded/recovered frames (FEC-03). */\n\tonFrame(cb: (data: ArrayBuffer, meta: FrameMeta) => void): void {\n\t\tthis.#onFrame = cb;\n\t}\n\n\t/** Register callback for periodic stats snapshots (FEC-04). */\n\tonSnapshot(cb: (stats: FecTrackStats) => void): void {\n\t\tthis.#onSnapshot = cb;\n\t}\n\n\t/** Register callback for individual block state changes. */\n\tonBlockUpdate(cb: (block: FecBlockSnapshot) => void): void {\n\t\tthis.#onBlockUpdate = cb;\n\t}\n\n\t/** Register callback for green-fill frames. */\n\tonGreenFill(cb: (sbn: number, data: ArrayBuffer) => void): void {\n\t\tthis.#onGreenFill = cb;\n\t}\n\n\t/** Register callback fired after the Worker drains all commands queued before cleanup. */\n\tonCleanupComplete(cb: (sbn: number) => void): void {\n\t\tthis.#onCleanupComplete = cb;\n\t}\n\n\t/** Register callback for Worker errors. */\n\tonError(cb: (message: string, code?: FecWorkerErrorCode) => void): void {\n\t\tthis.#onError = cb;\n\t}\n\n\t/**\n\t * Dispose the Worker. Sends dispose command then terminates.\n\t * Idempotent \u2014 safe to call multiple times.\n\t */\n\tdispose(): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#disposed = true;\n\t\tthis.#cleanupInFlight = null;\n\t\tthis.#queuedCleanupSbns.clear();\n\t\tthis.#worker.postMessage({ type: \"dispose\" } satisfies FecWorkerCommand);\n\t\tthis.#worker.terminate();\n\t}\n\n\t#handleEvent(event: FecWorkerEvent): void {\n\t\tif (event.type === \"resetComplete\") {\n\t\t\tthis.#pendingResets = Math.max(0, this.#pendingResets - 1);\n\t\t\tthis.#resetFailed = false;\n\t\t\treturn;\n\t\t}\n\t\tif (event.type === \"error\") {\n\t\t\tif (event.code === \"reset-failed\") {\n\t\t\t\tthis.#pendingResets = Math.max(0, this.#pendingResets - 1);\n\t\t\t\tthis.#resetFailed = true;\n\t\t\t}\n\t\t\tif (event.code) this.#onError?.(event.message, event.code);\n\t\t\telse this.#onError?.(event.message);\n\t\t\treturn;\n\t\t}\n\t\tif (this.#pendingResets > 0 || this.#resetFailed) return;\n\t\tswitch (event.type) {\n\t\t\tcase \"frame\":\n\t\t\t\tthis.#onFrame?.(event.data, event.meta);\n\t\t\t\tbreak;\n\t\t\tcase \"snapshot\":\n\t\t\t\tthis.#onSnapshot?.(event.stats);\n\t\t\t\tbreak;\n\t\t\tcase \"blockUpdate\":\n\t\t\t\tthis.#onBlockUpdate?.(event.block);\n\t\t\t\tbreak;\n\t\t\tcase \"greenFill\":\n\t\t\t\tthis.#onGreenFill?.(event.sbn, event.data);\n\t\t\t\tbreak;\n\t\t\tcase \"cleanupComplete\":\n\t\t\t\tfor (const sbn of event.sbns) {\n\t\t\t\t\tthis.#onCleanupComplete?.(sbn);\n\t\t\t\t}\n\t\t\t\tthis.#cleanupInFlight = null;\n\t\t\t\tif (this.#queuedCleanupSbns.size > 0) {\n\t\t\t\t\tconst next = this.#queuedCleanupSbns;\n\t\t\t\t\tthis.#queuedCleanupSbns = new Set();\n\t\t\t\t\tthis.#postCleanup(next);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\nfunction formatWorkerError(event: ErrorEvent): string {\n\tconst parts = [\"Worker error\"];\n\tif (event.message) parts.push(event.message);\n\tif (event.filename) {\n\t\tconst location = [event.filename];\n\t\tif (event.lineno) location.push(String(event.lineno));\n\t\tif (event.colno) location.push(String(event.colno));\n\t\tparts.push(`at ${location.join(\":\")}`);\n\t}\n\tif (event.error instanceof Error) {\n\t\tif (event.error.message && event.error.message !== event.message) {\n\t\t\tparts.push(event.error.message);\n\t\t}\n\t\tif (event.error.stack) parts.push(event.error.stack);\n\t} else if (event.error != null) {\n\t\tparts.push(String(event.error));\n\t}\n\treturn parts.join(\": \");\n}\n\nfunction formatWorkerMessageError(event: MessageEvent): string {\n\tconst data = event.data;\n\tconst detail =\n\t\tdata == null ? \"\" :\n\t\t\tdata instanceof Error ? `: ${data.message}` :\n\t\t\t\t`: ${Object.prototype.toString.call(data)}`;\n\treturn `Worker messageerror: failed to deserialize worker message${detail}`;\n}\n", "/**\n * @blockcast/fec-worker \u2014 Shred Worker Main-Thread Client\n *\n * Thin wrapper over the shred (Reed-Solomon) worker, mirroring\n * {@link FecWorkerClient}'s shape. Spawns one Worker, speaks the\n * {@link ShredWorkerCommand}/{@link ShredWorkerEvent} protocol, and keeps the\n * datagram read loop + wire parse + WASM FEC off the main thread.\n *\n * Typical wiring for a WebTransport datagram source (fully off-thread):\n *\n * const client = new ShredWorkerClient(new URL(\"./shred-fec-worker.js\", import.meta.url));\n * client.onRecovered((data, meta) => renderRecoveredSet(data, meta));\n * client.configure({ maxSlots: 5000, symbolSize: 512, wasmUrl: \"/vendor/fec/mmt_wasm.js\" });\n * client.attachStream(wt.datagrams.readable); // transferred; main does no read() per packet\n *\n * For sources that demux on the main thread (moqtail OBJECT_DATAGRAM callback,\n * IWA multicast bridge), push each raw frame with {@link feedShred} instead.\n *\n * {@link feedShred} is a fire-and-forget `postMessage` with no native\n * backpressure, so a consumer that decodes slower than the ingest rate (a\n * backgrounded/throttled tab, WASM RS falling behind a ~4k shred/s feed) would\n * grow the worker's inbound message queue without limit \u2014 the queue lives in the\n * renderer process and has been observed to reach multiple GB, GC-thrashing the\n * page into a wedge. The client bounds it with an in-flight window keyed off the\n * worker's own periodic stats heartbeat (no per-frame ack round-trip); see\n * {@link ShredWorkerClientOptions.maxInflight}.\n */\n\nimport type {\n\tShredWorkerCommand,\n\tShredWorkerConfig,\n\tShredWorkerEvent,\n\tShredWorkerStats,\n\tShredWorkerErrorCode,\n\tRecoveredMeta,\n} from \"./shred-worker-types.js\";\n\n/** Construction-time options for {@link ShredWorkerClient}. */\nexport interface ShredWorkerClientOptions {\n\t/**\n\t * Cap on frames posted via {@link ShredWorkerClient.feedShred} but not yet\n\t * drained by the worker, before further frames are dropped (\"skip-to-live\" at\n\t * the worker boundary). Bounds the worker's inbound message queue \u2014 the sole\n\t * unbounded structure on the main-thread-demux (`feedShred`) path.\n\t *\n\t * The drain signal is the worker's periodic `stats` heartbeat: the monotonic\n\t * total of frames it has taken off the queue (`shredsRx + malformed +\n\t * versionMismatch`). No per-frame acknowledgement crosses the boundary, so the\n\t * bound is heartbeat-granular \u2014 size it above one heartbeat's worth of ingest\n\t * (default 250ms heartbeat \u00D7 ~4k frames/s \u2248 ~1k frames).\n\t *\n\t * Default {@link DEFAULT_MAX_INFLIGHT} (8192 frames \u2248 ~10 MB at ~1.3 KB/frame).\n\t * Set to `0` (or any value `<= 0`) to disable the bound entirely \u2014 only do so\n\t * for a source with its own backpressure (e.g. a bounded {@link\n\t * ShredWorkerClient.attachStream} producer). Note the bound assumes `feedShred`\n\t * is the sole ingest path; mixing it with `attachStream` (whose frames also\n\t * advance the heartbeat total) makes the window under-count and benignly\n\t * disables the drop.\n\t */\n\tmaxInflight?: number;\n}\n\n/** Default {@link ShredWorkerClientOptions.maxInflight} (~10 MB of queued frames). */\nexport const DEFAULT_MAX_INFLIGHT = 8192;\n\nexport class ShredWorkerClient {\n\treadonly #worker: Worker;\n\t#onRecovered: ((data: ArrayBuffer, meta: RecoveredMeta) => void) | null = null;\n\t#onStats: ((stats: ShredWorkerStats) => void) | null = null;\n\t#onError: ((message: string, code?: ShredWorkerErrorCode) => void) | null = null;\n\t#disposed = false;\n\n\t/** feedShred in-flight backpressure accounting (see ShredWorkerClientOptions.maxInflight). */\n\treadonly #maxInflight: number;\n\t#sent = 0; // frames posted via feedShred (monotonic)\n\t#processed = 0; // worker-consumed total from the last stats heartbeat (monotonic)\n\t#droppedBackpressure = 0; // frames dropped by the in-flight guard (monotonic)\n\n\t/**\n\t * @param workerOrUrl - A URL (a Worker is created internally, `type: module`)\n\t * or a pre-created Worker (for testing via constructor injection).\n\t * @param opts - Optional {@link ShredWorkerClientOptions}.\n\t */\n\tconstructor(workerOrUrl: Worker | URL, opts: ShredWorkerClientOptions = {}) {\n\t\tthis.#maxInflight = opts.maxInflight ?? DEFAULT_MAX_INFLIGHT;\n\t\tthis.#worker =\n\t\t\tworkerOrUrl instanceof URL\n\t\t\t\t? new Worker(workerOrUrl, { type: \"module\" })\n\t\t\t\t: workerOrUrl;\n\t\tthis.#worker.onmessage = (e: MessageEvent<ShredWorkerEvent>) =>\n\t\t\tthis.#handleEvent(e.data);\n\t\tthis.#worker.onerror = (e) =>\n\t\t\tthis.#onError?.(formatWorkerError(e), \"worker-runtime\");\n\t\tthis.#worker.onmessageerror = () =>\n\t\t\tthis.#onError?.(\"failed to deserialize worker message\", \"worker-message\");\n\t}\n\n\t/** Configure the decoder (WASM load + ShredFecBuffer construction happen in the worker). */\n\tconfigure(config: ShredWorkerConfig): void {\n\t\tif (this.#disposed) throw new Error(\"[ShredWorkerClient] disposed\");\n\t\tthis.#post({ type: \"configure\", config });\n\t}\n\n\t/**\n\t * Hand the worker a stream of raw shred frames to batch-drain. The stream is\n\t * transferred \u2014 the caller must not use it afterward. One active stream at a\n\t * time; attaching a new one cancels the previous.\n\t */\n\tattachStream(readable: ReadableStream<Uint8Array>): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#post({ type: \"attachStream\", readable }, [readable]);\n\t}\n\n\t/**\n\t * Feed one already-demuxed raw shred frame. `frame` is transferred zero-copy;\n\t * the caller must not access it afterward.\n\t *\n\t * Dropped (frame NOT transferred, so the caller's buffer stays intact) when the\n\t * in-flight window is full \u2014 i.e. the worker is more than `maxInflight` frames\n\t * behind. This is the memory bound: a slow/wedged consumer costs bounded\n\t * skip-to-live drops (see {@link droppedBackpressure}), never an unbounded\n\t * renderer-heap blow-up.\n\t */\n\tfeedShred(frame: ArrayBuffer): void {\n\t\tif (this.#disposed) return;\n\t\tif (this.#maxInflight > 0 && this.#sent - this.#processed >= this.#maxInflight) {\n\t\t\tthis.#droppedBackpressure++;\n\t\t\treturn;\n\t\t}\n\t\tthis.#sent++;\n\t\tthis.#post({ type: \"feedShred\", frame }, [frame]);\n\t}\n\n\t/** Explicitly drive loss recovery (in addition to the worker's internal timer). */\n\trecoverAll(nowMs: number = Date.now()): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#post({ type: \"recoverAll\", nowMs });\n\t}\n\n\t/** Register callback for recovered/completed FEC sets. `data` is a transferred buffer. */\n\tonRecovered(cb: (data: ArrayBuffer, meta: RecoveredMeta) => void): void {\n\t\tthis.#onRecovered = cb;\n\t}\n\n\t/** Register callback for the coalesced stats heartbeat. */\n\tonStats(cb: (stats: ShredWorkerStats) => void): void {\n\t\tthis.#onStats = cb;\n\t}\n\n\t/** Register callback for worker errors. */\n\tonError(cb: (message: string, code?: ShredWorkerErrorCode) => void): void {\n\t\tthis.#onError = cb;\n\t}\n\n\t/**\n\t * Frames dropped by the in-flight backpressure guard since construction\n\t * (monotonic). Surface this in the UI so sustained loss is visible rather than\n\t * silent \u2014 a rising counter means the consumer can't keep pace with ingest.\n\t */\n\tget droppedBackpressure(): number {\n\t\treturn this.#droppedBackpressure;\n\t}\n\n\t/**\n\t * Frames posted via {@link feedShred} but not yet reported drained by the\n\t * worker's last stats heartbeat (best-effort, heartbeat-granular; never < 0).\n\t */\n\tget inflight(): number {\n\t\treturn Math.max(0, this.#sent - this.#processed);\n\t}\n\n\t/** Dispose the worker. Idempotent. */\n\tdispose(): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#disposed = true;\n\t\ttry {\n\t\t\tthis.#worker.postMessage({ type: \"dispose\" } satisfies ShredWorkerCommand);\n\t\t} catch {\n\t\t\t/* worker may already be gone */\n\t\t}\n\t\tthis.#worker.terminate();\n\t}\n\n\t#post(cmd: ShredWorkerCommand, transfer: Transferable[] = []): void {\n\t\tthis.#worker.postMessage(cmd, transfer);\n\t}\n\n\t#handleEvent(event: ShredWorkerEvent): void {\n\t\tswitch (event.type) {\n\t\t\tcase \"recovered\":\n\t\t\t\tthis.#onRecovered?.(event.data, event.meta);\n\t\t\t\tbreak;\n\t\t\tcase \"stats\":\n\t\t\t\t// The worker's monotonic consumed-frame total is the drain signal for\n\t\t\t\t// the feedShred in-flight guard. shredsRx counts only valid frames;\n\t\t\t\t// malformed + versionMismatch are consumed off the queue too, so the\n\t\t\t\t// sum is the true \"frames taken off the queue\" and keeps the window\n\t\t\t\t// from inflating (and false-dropping) on a malformed/skewed source.\n\t\t\t\tthis.#processed =\n\t\t\t\t\tevent.stats.shredsRx + event.stats.malformed + event.stats.versionMismatch;\n\t\t\t\tthis.#onStats?.(event.stats);\n\t\t\t\tbreak;\n\t\t\tcase \"error\":\n\t\t\t\tif (event.code) this.#onError?.(event.message, event.code);\n\t\t\t\telse this.#onError?.(event.message);\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\nfunction formatWorkerError(event: ErrorEvent): string {\n\tconst parts = [\"Worker error\"];\n\tif (event.message) parts.push(event.message);\n\tif (event.filename) {\n\t\tconst loc = [event.filename];\n\t\tif (event.lineno) loc.push(String(event.lineno));\n\t\tif (event.colno) loc.push(String(event.colno));\n\t\tparts.push(`at ${loc.join(\":\")}`);\n\t}\n\tif (event.error instanceof Error && event.error.stack) parts.push(event.error.stack);\n\treturn parts.join(\": \");\n}\n", "/**\n * @blockcast/fec-worker \u2014 Worker-per-track FEC decode with zero-copy transfers\n *\n * Re-exports shared types and main-thread client.\n */\n\nexport type {\n\tFecWorkerCommand,\n\tFecWorkerEvent,\n\tFecWorkerErrorCode,\n\tFecTrackConfig,\n\tFecTrackStats,\n\tFecBlockSnapshot,\n\tFrameMeta,\n} from \"./fec-worker-types.js\";\n\nexport { FecWorkerClient } from \"./fec-worker-client.js\";\n\n// --- Shred (Reed-Solomon) codec \u2014 sibling to the RaptorQ/MMTP worker above.\n// Different FEC payload identity (slot/fecSet/localIndex vs flat ssId) \u2192 its\n// own command shape and worker; shares the transfer + client/worker pattern.\nexport type {\n\tShredWorkerCommand,\n\tShredWorkerEvent,\n\tShredWorkerConfig,\n\tShredWorkerStats,\n\tShredWorkerErrorCode,\n\tRecoveredMeta,\n\tSlotSample,\n} from \"./shred-worker-types.js\";\n\nexport { ShredWorkerClient } from \"./shred-worker-client.js\";\n", "/**\n * Shared fec-setup helper.\n *\n * Wires a FecWorkerClient into a MulticastManager for a specific track.\n * Both moq-lib (`hang-mmt-fec/js/watch/src/element.ts`) and moqtail\n * (`moqtail-private/apps/client-js/src/lib/player.ts`) call this from their\n * SessionManager `fec-setup` handler so the Worker+ALTA setup lives in one\n * place instead of being duplicated across ~80 lines per player.\n *\n * Callers are responsible for holding the returned `dispose()` and calling it\n * from their `fec-teardown` path (and/or effect cleanup).\n */\n\nimport type { FecWorkerClient, FecTrackConfig } from '@blockcast/fec-worker'\nimport { deriveFecInterleaveDepth } from '@blockcast/mmt-fec'\nimport type { MulticastManager } from './multicast-manager.js'\nimport { computeFecDeliveryWindowMs } from './track-session.js'\n\n/** Asset URLs the helper needs. Callers pass the already-resolved set. */\nexport interface FecWorkerAssetUrls {\n /** URL to the fec-worker entry bundle (new Worker() target). */\n fecWorker: string\n /** URL to the RaptorQ WASM module (compiled via compileStreaming). */\n rqWasm: string\n /** URL to the ALTA WASM module. Fetched only when an ALTA key is provided. */\n altaWasm: string\n}\n\nexport interface FecWorkerSetupOptions {\n /** MulticastManager that should receive the configured Worker. */\n multicastManager: MulticastManager\n /** MMTP packetId this track occupies (from catalog). */\n packetId: number\n /** Human-readable track name (catalog key). */\n trackName: string\n /** Track type from catalog. Never inferred from name. */\n trackType: 'video' | 'audio'\n /** FEC K from catalog (source symbols per block). */\n fecK: number\n /** Symbol size in bytes (T) \u2014 the ALTA-adjusted value if ALTA is signed. */\n fecSymbolSize: number\n /** Repair symbols per block (P). */\n fecRepairCount: number\n /** Interleave depth in ms. */\n fecInterleaveMs: number\n /** Duration of one FEC media unit in ms (video frame or audio access unit). */\n mediaUnitDurationMs: number\n /** Optional repair track name (MoQ). Forwarded to FecTrackConfig. */\n repairTrackName?: string\n /** Audio sample rate (optional \u2014 audio tracks only). */\n sampleRate?: number\n /** Codec string (optional; \"unknown\" is acceptable for first setup). */\n codec?: string\n /** Video framerate (optional metadata forwarded to the worker). */\n framerate?: number\n /** Base64 SPKI public key (optional). Accepts padded/unpadded, std or url-safe alphabet. */\n altaPublicKeySpki?: string\n /** Absolute or origin-relative asset URLs. */\n assetUrls: FecWorkerAssetUrls\n /** Optional FecWorkerClient factory \u2014 main use is test injection. */\n clientFactory?: (workerUrl: URL) => FecWorkerClient\n}\n\nexport interface FecWorkerSetupResult {\n /** The configured client (already registered with MulticastManager). */\n client: FecWorkerClient\n /** True when the ALTA public key decoded and the ALTA WASM compiled. */\n altaEnabled: boolean\n /** Releases the Worker and removes it from MulticastManager routing. */\n dispose: () => void\n}\n\n/**\n * Configure a FecWorkerClient and attach it to `multicastManager` via\n * `setFecWorker(packetId, client, trackType, config, trackName)`. Worker-path takes precedence\n * over any sync WASM decoder already registered for the same packetId \u2014\n * sync decoders remain as a fallback.\n *\n * Any loader failure is re-thrown so the caller can log and leave the sync\n * WASM decoder active as fallback (same pattern both players used before).\n */\nexport async function setupFecWorkerForTrack(\n opts: FecWorkerSetupOptions,\n): Promise<FecWorkerSetupResult> {\n const interleaveDepthBlocks = deriveFecInterleaveDepth(\n opts.fecInterleaveMs,\n opts.mediaUnitDurationMs,\n )\n const deliveryWindowMs = computeFecDeliveryWindowMs({\n interleaveDepthMs: opts.fecInterleaveMs,\n sourceSymbols: opts.fecK,\n repairSymbols: opts.fecRepairCount,\n symbolSize: opts.fecSymbolSize,\n mediaUnitsPerSecond: 1000 / opts.mediaUnitDurationMs,\n })\n // Resolve URL against location.origin when available (browser runtime).\n // Absolute URLs pass through unchanged per the URL() spec.\n const origin =\n typeof location !== 'undefined' && location.origin ? location.origin : 'http://localhost'\n const workerUrl = new URL(opts.assetUrls.fecWorker, origin)\n\n const FecWorkerCtor = await import('@blockcast/fec-worker')\n const client = opts.clientFactory\n ? opts.clientFactory(workerUrl)\n : new FecWorkerCtor.FecWorkerClient(workerUrl)\n\n // Compile RaptorQ WASM once; ALTA WASM only when we have a key to decode.\n const rqWasm = await WebAssembly.compileStreaming(fetch(opts.assetUrls.rqWasm))\n\n let altaKeyBuffer: ArrayBuffer | undefined\n let altaWasmModule: WebAssembly.Module | undefined\n if (opts.altaPublicKeySpki) {\n const b64 = opts.altaPublicKeySpki.replace(/-/g, '+').replace(/_/g, '/')\n const padded = b64.padEnd(Math.ceil(b64.length / 4) * 4, '=')\n try {\n const keyBytes = Uint8Array.from(atob(padded), c => c.charCodeAt(0))\n // SPKI size range: Ed25519=44, P-256=91; tolerate 32..=256 for forward-compat.\n if (keyBytes.length >= 32 && keyBytes.length <= 256) {\n altaKeyBuffer = keyBytes.buffer\n altaWasmModule = await WebAssembly.compileStreaming(fetch(opts.assetUrls.altaWasm))\n } else {\n console.warn(\n `[fec-worker-setup] ALTA SPKI wrong length for \"${opts.trackName}\": ` +\n `${keyBytes.length} (expected 32..256) \u2014 ALTA disabled`,\n )\n }\n } catch (e) {\n console.warn(`[fec-worker-setup] ALTA key decode / WASM compile failed for \"${opts.trackName}\":`, e)\n }\n }\n\n const altaEnabled = !!(altaKeyBuffer && altaWasmModule)\n const fecTrackConfig = {\n codec: opts.codec ?? 'unknown',\n trackName: opts.trackName,\n trackType: opts.trackType,\n framerate: opts.framerate,\n sampleRate: opts.sampleRate,\n algorithm: 'raptor',\n k: opts.fecK,\n repairCount: opts.fecRepairCount,\n symbolSize: opts.fecSymbolSize,\n interleaveDepth: interleaveDepthBlocks,\n interleaveMs: opts.fecInterleaveMs,\n deliveryWindowMs,\n fecMode: 'subframe' as const,\n repairTrack: opts.repairTrackName,\n altaEnabled,\n relayBlockSigEnabled: false,\n } as unknown as FecTrackConfig\n\n client.configure(fecTrackConfig, rqWasm, altaKeyBuffer, altaWasmModule)\n opts.multicastManager.setFecWorker(opts.packetId, client, opts.trackType, {\n k: opts.fecK,\n symbolSize: opts.fecSymbolSize,\n interleaveDepthMs: opts.fecInterleaveMs,\n // FEC timing is expressed in media units. For audio this is the access-unit\n // cadence (for example 1024/48kHz), not a video-only framerate field.\n fps: 1000 / opts.mediaUnitDurationMs,\n timeoutMs: deliveryWindowMs,\n }, opts.trackName)\n\n let disposed = false\n return {\n client,\n altaEnabled,\n dispose: () => {\n if (disposed) return\n disposed = true\n try {\n client.dispose()\n } catch {\n /* dispose errors are non-fatal */\n }\n },\n }\n}\n", "/**\n * TrackSession \u2014 per-track transport state machine.\n * SessionManager \u2014 orchestrates all sessions + TransportPool.\n *\n * Implements Patent Claim 9 (draft-ramadan-moq-fec APPLICATION-1):\n * (a) subscribe unicast\n * (b) simultaneously join multicast\n * (c) render from unicast during join\n * (d) activate multicast on RAP, suppress unicast\n * (e) cross-transport FEC repair during transition\n * (f) hysteresis before switching away from multicast\n * (g) re-subscribe unicast on sustained failure\n *\n * PIM: manages transport state without inspecting packet contents.\n */\n\nimport {\n TransportPool,\n type Subscription,\n type SubscriptionMode,\n type AcquireOptions,\n type DirectSocketHealth,\n type TransportPoolOptions,\n} from './transport-pool.js'\nimport { deriveFecInterleaveDepth } from '@blockcast/mmt-fec'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type TrackState =\n | 'idle'\n | 'unicast'\n | 'unicast-fallback'\n | 'joining'\n | 'multicast'\n | 'amt'\n | 'failing'\n\nexport interface TrackSessionConfig {\n trackName: string\n trackType: 'video' | 'audio'\n packetId: number\n /** FEC interleave depth from catalog (ms). Used for hysteresis timer. */\n fecInterleaveMs: number\n /** FEC K from catalog. Used for audio worklet latency calculation. */\n fecK: number\n /** FEC repair symbols per block (P). NOT symbol size. */\n fecRepairCount: number\n /** FEC symbol size in bytes (T). Required for WASM decoder OTI. */\n fecSymbolSize: number\n /** MoQ repair track name from catalog FEC config. */\n repairTrackName?: string\n /** Frame samples from initData parsing (audio-init-parser.ts). */\n frameSamples?: number\n /** Audio sample rate from catalog. */\n sampleRate?: number\n /** Ordered transport preference: best first. */\n preferredTransports: SubscriptionMode[]\n /** Subscription key for multicast/AMT: \"(S,G,port)\". */\n multicastKey?: string\n /** MoQ track name for unicast subscription. */\n moqTrackName?: string\n /** AMT relay address (if AMT is in preference chain). */\n amtRelay?: string\n /** MoQ relay URL (for WebTransport subscription). */\n moqRelayUrl?: string\n}\n\n// ---------------------------------------------------------------------------\n// PIM callbacks (protocol-independent \u2014 transport state only)\n// ---------------------------------------------------------------------------\n\nexport interface SessionManagerCallbacks {\n /** Fired on every transport state transition. */\n onStateChange?(trackName: string, from: TrackState, to: TrackState): void\n /** Fired to suppress/unsuppress unicast for this track (transport arbitration). */\n onSuppress?(trackName: string, suppressed: boolean): void\n /**\n * Fired when a track sat in `joining` for SessionManager.takeoverDeadlineMs\n * without a RAP (BLO-9413/D9). The session has already returned to `unicast`\n * (nothing was suppressed, so nothing to restore) \u2014 the host should abandon\n * the multicast attempt (e.g. MediaRouter.failbackToMoq()) so the router\n * stops waiting for a keyframe that is never coming.\n */\n onTakeoverTimeout?(trackName: string): void\n}\n\n// ---------------------------------------------------------------------------\n// MMTP application-layer extension (FEC lifecycle, media resets)\n// ---------------------------------------------------------------------------\n\n/**\n * MMTP track events (discriminated union).\n * Each protocol layer defines its own event union \u2014 MMTP events cover\n * media resets, latency, and FEC lifecycle.\n */\nexport type MmtpTrackEvent =\n | { type: 'reset' }\n | { type: 'latency'; latencyMs: number }\n | { type: 'fec-setup' }\n | { type: 'fec-teardown' }\n\n/**\n * MMTP application-layer extension of SessionManagerCallbacks.\n * Single onTrackEvent dispatches all MMTP-specific events.\n * PIM consumers use the base SessionManagerCallbacks (no onTrackEvent).\n *\n * IWA can define its own subinterface with its own TrackEvent union\n * (e.g., IwaTrackEvent for socket health, AMT state) using the same pattern.\n */\nexport interface MmtpSessionCallbacks extends SessionManagerCallbacks {\n onTrackEvent?(trackName: string, event: MmtpTrackEvent, config: TrackSessionConfig): void\n}\n\n/**\n * Loss-hysteresis window covering the signaled interleave window plus jitter.\n *\n * This path lacks media cadence, so it intentionally does not estimate a full\n * source-plus-repair production horizon. FECManager uses\n * computeFecDeliveryWindowMs with media cadence when configuring block\n * inactivity deadlines.\n *\n * `fecK` no longer feeds the math; it is still validated as a catalog\n * well-formedness guard and kept in the signature for positional API compat\n * (removal is a follow-up with the next cross-repo pin bump).\n */\nexport function computeFecLossWindowMs(fecInterleaveMs: number, fecK: number, jitterBufferMs?: number): number {\n return computeFecDeliveryWindowMs({\n interleaveDepthMs: fecInterleaveMs,\n sourceSymbols: fecK,\n jitterBufferMs,\n })\n}\n\nexport interface FecDeliveryWindowConfig {\n interleaveDepthMs: number\n sourceSymbols: number\n repairSymbols?: number\n symbolSize?: number\n mediaUnitsPerSecond?: number\n bandwidthBps?: number\n /**\n * Jitter + one-way-delay + reorder budget in ms (draft-ramadan-moq-fec \u00A79),\n * sourced from the catalog `jitterBufferMs`. Added on top of the max-of-spans\n * core; it is NOT a multiplier. See the margin-policy note in the function.\n */\n jitterBufferMs?: number\n}\n\n/**\n * Catalog-derived silence window that covers interleave geometry plus the time\n * required to produce or serialize a complete source+repair block. The catalog\n * field remains D media units; this function does not feed mapper geometry.\n */\nexport function computeFecDeliveryWindowMs(\n config: FecDeliveryWindowConfig,\n): number {\n const fecInterleaveMs = config.interleaveDepthMs\n const fecK = config.sourceSymbols\n if (fecInterleaveMs <= 0) {\n throw new Error(\n `[TrackSession] fecInterleaveMs=${fecInterleaveMs}. ` +\n `Derive a positive FEC interleave window from the stream catalog.`\n )\n }\n if (fecK <= 0) {\n throw new Error(\n `[TrackSession] fecK=${fecK}. ` +\n `Derive a positive FEC source-symbol count from the stream catalog.`\n )\n }\n\n const spansMs = [fecInterleaveMs]\n if (config.mediaUnitsPerSecond && config.mediaUnitsPerSecond > 0) {\n const mediaUnitMs = 1000 / config.mediaUnitsPerSecond\n // interleaveDepthMs is integer catalog signaling while media-unit duration\n // is often fractional (for example 4/30s = 133.33ms). Recover D using the\n // producer's nearest-ms quantization, then cover every source and repair\n // round-robin cycle. A decoder cannot recover a partial MFU until the\n // repair tail arrives, so a K-only deadline expires the source fragments\n // before the final repair symbols that complete them.\n const interleaveUnits = deriveFecInterleaveDepth(fecInterleaveMs, mediaUnitMs)\n const deliverySymbols = fecK + Math.max(0, config.repairSymbols ?? 0)\n spansMs.push(deliverySymbols * interleaveUnits * mediaUnitMs)\n }\n if (\n config.symbolSize &&\n config.symbolSize > 0 &&\n config.bandwidthBps &&\n config.bandwidthBps > 0\n ) {\n const repairSymbols = Math.max(0, config.repairSymbols ?? 0)\n spansMs.push(\n ((fecK + repairSymbols) * config.symbolSize * 8 * 1000) /\n config.bandwidthBps,\n )\n }\n\n // draft-ramadan-moq-fec \u00A79: the recovery timeout is a DERIVED budget \u2014\n // max(interleave span, source+repair production horizon, block serialization) PLUS\n // an ADDITIVE margin for jitter + one-way delay + reorder. It MUST NOT be a\n // fixed multiple of the interleave span (this replaces the retired `* 3` /\n // `* 2` safety factors). The margin is the catalog `jitterBufferMs`.\n //\n // MARGIN-POLICY (operator sign-off \u2014 see PR): no catalog currently emits\n // `jitterBufferMs`. Rather than throw (which would break every existing\n // catalog) or invent a magic constant, the default margin is the un-rounded\n // interleave window \u2014 the spec's natural reorder-budget bound and already a\n // catalog value. Emit `jitterBufferMs` in the catalog to set it explicitly.\n const coreMs = Math.max(...spansMs)\n const marginMs =\n config.jitterBufferMs !== undefined && config.jitterBufferMs >= 0\n ? config.jitterBufferMs\n : fecInterleaveMs\n return Math.ceil(coreMs) + Math.ceil(marginMs)\n}\n\n/** Convert the shared FEC delivery deadline into an integer media timescale. */\nexport function computeFecDeliveryWindowMediaUnits(\n config: FecDeliveryWindowConfig,\n timestampTimescale: number,\n): number {\n if (!Number.isFinite(timestampTimescale) || timestampTimescale <= 0) {\n throw new Error(\n `[TrackSession] timestampTimescale=${timestampTimescale}. ` +\n 'Derive a positive media timescale from the container.',\n )\n }\n const deliveryWindow = Math.ceil(\n computeFecDeliveryWindowMs(config) * timestampTimescale / 1000,\n )\n if (!Number.isSafeInteger(deliveryWindow)) {\n throw new Error('[TrackSession] FEC delivery window exceeds the media timestamp range.')\n }\n return deliveryWindow\n}\n\n// ---------------------------------------------------------------------------\n// TrackSession\n// ---------------------------------------------------------------------------\n\nexport class TrackSession {\n readonly config: TrackSessionConfig\n #state: TrackState = 'idle'\n #subscription: Subscription | null = null\n #hysteresisTimer: ReturnType<typeof setTimeout> | null = null\n #joinDeadlineTimer: ReturnType<typeof setTimeout> | null = null\n #previousPrimary: SubscriptionMode | null = null\n #manager: SessionManager\n // Single suppression authority flag (BLO-9413 failback coherence): every\n // suppress this session fires is recorded here, and every path that leaves\n // a suppressed state unwinds through #unsuppress(). Before this flag,\n // unsubscribe() only un-suppressed from multicast/amt \u2014 a session torn down\n // from `failing` (exactly where a starving track sits) was re-subscribed to\n // unicast with the host's media still muted: MoQ playing into a dead sink.\n #suppressFired = false\n\n constructor(config: TrackSessionConfig, manager: SessionManager) {\n this.config = config\n this.#manager = manager\n }\n\n // -----------------------------------------------------------------------\n // State\n // -----------------------------------------------------------------------\n\n get state(): TrackState { return this.#state }\n get subscription(): Subscription | null { return this.#subscription }\n\n /** True while this session's onSuppress(true) is outstanding (no matching\n * onSuppress(false) yet). Test/assertion surface for failback coherence. */\n get isSuppressed(): boolean { return this.#suppressFired }\n\n /** Current active transport mode, or null if idle. */\n get transport(): SubscriptionMode | null {\n switch (this.#state) {\n case 'multicast': return 'multicast'\n case 'amt': return 'amt'\n case 'unicast': return 'moq'\n case 'unicast-fallback': return 'moq' // SSM bridge absent \u2014 MoQ unicast is the only source\n case 'joining': return 'moq' // MoQ still primary during join\n case 'failing': return this.#previousPrimary\n default: return null\n }\n }\n\n // -----------------------------------------------------------------------\n // Computed (no magic numbers)\n // -----------------------------------------------------------------------\n\n /** Audio worklet latency: max(fecInterleaveMs, frameDurationMs * fecK).\n * Returns undefined if frame duration unknown (no initData). */\n get audioLatencyMs(): number | undefined {\n const fd = this.frameDurationMs\n if (fd === undefined) {\n return this.config.fecInterleaveMs > 0 ? this.config.fecInterleaveMs : undefined\n }\n return Math.max(this.config.fecInterleaveMs, fd * this.config.fecK)\n }\n\n /** Frame duration in ms, derived from frameSamples + sampleRate. */\n get frameDurationMs(): number | undefined {\n const { frameSamples, sampleRate } = this.config\n if (!frameSamples || !sampleRate || sampleRate <= 0) return undefined\n return (frameSamples / sampleRate) * 1000\n }\n\n // -----------------------------------------------------------------------\n // Transitions (Patent Claim 9)\n // -----------------------------------------------------------------------\n\n /** idle \u2192 unicast: player subscribes to this track. */\n subscribe(): void {\n if (this.#state !== 'idle') return\n this.#transition('unicast')\n\n // Emit audio latency on first subscribe\n if (this.config.trackType === 'audio') {\n const latency = this.audioLatencyMs\n if (latency !== undefined) {\n this.#manager.mmtp?.onTrackEvent?.(this.config.trackName, { type: 'latency', latencyMs: latency }, this.config)\n }\n }\n }\n\n /** unicast \u2192 joining: multicast/AMT capability detected, join in progress. */\n joinStarted(): void {\n if (this.#state !== 'unicast') return\n this.#transition('joining')\n // FEC decoders must be ready before multicast data arrives (Claim 9e: cross-transport repair)\n this.#manager.mmtp?.onTrackEvent?.(this.config.trackName, { type: 'fec-setup' }, this.config)\n }\n\n /**\n * any non-fallback state \u2192 unicast-fallback. Used when the SSM bridge is\n * absent (vanilla Chromium / no extension) and the host falls back to a\n * MoQ unicast subscription per track. Terminal-ish: activateMulticast,\n * failbackAll, and transportFailed are no-ops while in this state.\n *\n * Fires fec-setup so the per-track repair worker spins up \u2014 repair packets\n * still flow over the MoQ repair-track subscription, so FEC source+repair\n * can converge as in the multicast path.\n *\n * Audio latency is NOT re-emitted here: subscribe() already fires latency\n * once on the idle \u2192 unicast edge, and enterUnicastFallback is only ever\n * reached from a non-idle state (SessionManager skips idle sessions).\n */\n enterUnicastFallback(): void {\n if (this.#state === 'unicast-fallback') return\n this.#clearHysteresis()\n this.#transition('unicast-fallback')\n // Suppress the redundant unicast media decoder. On the no-bridge path the\n // host feeds MoQ-unicast source packets into MulticastManager (the render\n // consumer); a second base-media subscribe (the @moq/watch decoder) would\n // split the single connection's QUIC flow-control budget and stall delivery\n // (BLO-8969). Fire suppress here, on the fallback edge, so the decoder is\n // gated off before it subscribes rather than after the relay forward task\n // has already wedged.\n this.#suppress()\n this.#manager.mmtp?.onTrackEvent?.(this.config.trackName, { type: 'fec-setup' }, this.config)\n }\n\n /**\n * unicast-fallback \u2192 unicast. Called when the SSM bridge appears mid-session\n * (extension installed after fallback engaged). Host first aborts the fallback\n * drainers, then transitions sessions back to unicast so the regular\n * multicast/AMT preference chain can take over via joinStarted().\n */\n exitUnicastFallback(): void {\n if (this.#state !== 'unicast-fallback') return\n this.#transition('unicast')\n // Un-suppress the unicast decoder: the bridge appeared mid-session, so the\n // host tears down the fallback drainers and the regular preference chain\n // (joinStarted -> joining -> rapReceived) will re-suppress on multicast RAP.\n this.#unsuppress()\n }\n\n /**\n * joining \u2192 multicast or amt: RAP received on the joined transport (Claim 9d).\n * Resets audio worklet, then suppresses MoQ.\n */\n rapReceived(mode: 'multicast' | 'amt'): void {\n if (this.#state !== 'joining') return\n this.#previousPrimary = mode\n this.#transition(mode)\n if (this.config.trackType === 'audio') {\n this.#manager.mmtp?.onTrackEvent?.(this.config.trackName, { type: 'reset' }, this.config)\n }\n this.#suppress()\n }\n\n /** multicast/amt \u2192 failing: loss detected, start hysteresis timer (Claim 9f). */\n lossDetected(): void {\n if (this.#state !== 'multicast' && this.#state !== 'amt') return\n this.#previousPrimary = this.#state as SubscriptionMode\n this.#transition('failing')\n\n // Hysteresis timer: sustained loss before failback (Claim 9f). The window\n // covers a complete FEC block plus safety margin: the catalog interleave\n // value IS the block span (interleaveDepthMs, \u00A75.1), scaled by the same\n // safety factor FECManager uses for its block timeout.\n const hysteresisMs = computeFecLossWindowMs(this.config.fecInterleaveMs, this.config.fecK)\n this.#hysteresisTimer = setTimeout(() => {\n this.hysteresisExpired()\n }, hysteresisMs)\n }\n\n /** failing \u2192 previous primary: loss recovered within hysteresis window. */\n lossRecovered(): void {\n if (this.#state !== 'failing') return\n this.#clearHysteresis()\n if (this.#previousPrimary) {\n this.#transition(this.#previousPrimary as TrackState)\n }\n }\n\n /**\n * Transport failed (AMT relay down, multicast interface gone).\n * Try next transport in preference chain.\n */\n transportFailed(): void {\n this.#clearHysteresis()\n // Unicast-fallback is terminal \u2014 the host owns the subscription and\n // SessionManager transport machinery does not arbitrate it.\n if (this.#state === 'unicast-fallback') return\n const current = this.#previousPrimary ?? this.transport\n const prefs = this.config.preferredTransports\n const currentIdx = current ? prefs.indexOf(current) : -1\n const nextMode = prefs[currentIdx + 1]\n\n if (nextMode) {\n // Failover to next in chain\n if (nextMode === 'moq') {\n this.#transition('unicast')\n this.#unsuppress()\n if (this.config.trackType === 'audio') {\n this.#manager.mmtp?.onTrackEvent?.(this.config.trackName, { type: 'reset' }, this.config)\n }\n } else {\n // Next is multicast or AMT \u2014 start joining. `joining` means MoQ is\n // primary again (see transport getter) \u2014 if the failed transport had\n // suppressed unicast, restore it for the join window or the viewer\n // watches black video until the next RAP (which may never come).\n this.#transition('joining')\n this.#unsuppress()\n }\n } else {\n // End of chain \u2014 fall back to unicast (Claim 9g)\n this.#transition('unicast')\n this.#unsuppress()\n if (this.config.trackType === 'audio') {\n this.#manager.mmtp?.onTrackEvent?.(this.config.trackName, { type: 'reset' }, this.config)\n }\n }\n }\n\n /** Hysteresis expired \u2192 failback to next transport (Claim 9g). */\n hysteresisExpired(): void {\n if (this.#state !== 'failing') return\n this.#clearHysteresis()\n this.transportFailed()\n }\n\n /** \u2192 idle: player unsubscribes / tab close / cleanup. */\n unsubscribe(): void {\n this.#clearHysteresis()\n if (this.#state !== 'idle') {\n this.#transition('idle')\n // Unwind any outstanding suppression regardless of which state we left.\n // The old `wasActive` check (multicast/amt only) leaked suppression when\n // tearing down from `failing` or `unicast-fallback` \u2014 failbackAll()'s\n // unsubscribe\u2192subscribe cycle then re-entered unicast with the host's\n // media still muted (BLO-9413 freeze: \"failing back\" logged, video dead).\n this.#unsuppress()\n }\n }\n\n /** True when SessionManager.enterUnicastFallback put this track into the\n * host-driven unicast subscription mode. Host can iterate sessions to\n * decide whether to keep its fallback drainer alive across MediaRouter\n * arbitration events. */\n get isUnicastFallback(): boolean {\n return this.#state === 'unicast-fallback'\n }\n\n dispose(): void {\n this.#clearHysteresis()\n this.#clearJoinDeadline()\n this.#state = 'idle'\n this.#subscription = null\n }\n\n // -----------------------------------------------------------------------\n // Internal\n // -----------------------------------------------------------------------\n\n #transition(to: TrackState): void {\n const from = this.#state\n if (from === to) return\n this.#state = to\n // Takeover deadline (BLO-9413/D9): every entry into `joining` arms it\n // (joinStarted AND transportFailed-failover both route through here);\n // every exit cancels it. Without this, a transport that accepts the\n // subscribe but never delivers a RAP parks the session in `joining`\n // forever (observed live in the Phase-0 headless repro).\n if (from === 'joining') this.#clearJoinDeadline()\n if (to === 'joining') this.#armJoinDeadline()\n // FEC teardown: leaving FEC-active states \u2192 non-FEC state\n const fecActive = (s: TrackState) =>\n s === 'joining' ||\n s === 'multicast' ||\n s === 'amt' ||\n s === 'failing' ||\n s === 'unicast-fallback'\n if (fecActive(from) && !fecActive(to)) {\n this.#manager.mmtp?.onTrackEvent?.(this.config.trackName, { type: 'fec-teardown' }, this.config)\n }\n this.#manager.callbacks?.onStateChange?.(this.config.trackName, from, to)\n }\n\n #clearHysteresis(): void {\n if (this.#hysteresisTimer !== null) {\n clearTimeout(this.#hysteresisTimer)\n this.#hysteresisTimer = null\n }\n }\n\n #armJoinDeadline(): void {\n this.#clearJoinDeadline()\n const deadlineMs = this.#manager.takeoverDeadlineMs\n if (deadlineMs <= 0) return // disabled\n this.#joinDeadlineTimer = setTimeout(() => {\n this.#joinDeadlineTimer = null\n if (this.#state !== 'joining') return\n // No RAP within the deadline: return to unicast. MoQ was never\n // suppressed in `joining`, so there is nothing to restore \u2014 this edge\n // must stay silent on onSuppress (asserted in tests).\n this.#transition('unicast')\n this.#manager.callbacks?.onTakeoverTimeout?.(this.config.trackName)\n }, deadlineMs)\n }\n\n #clearJoinDeadline(): void {\n if (this.#joinDeadlineTimer !== null) {\n clearTimeout(this.#joinDeadlineTimer)\n this.#joinDeadlineTimer = null\n }\n }\n\n /** Fire onSuppress(true) exactly once per suppression epoch. */\n #suppress(): void {\n if (this.#suppressFired) return\n this.#suppressFired = true\n this.#manager.callbacks?.onSuppress?.(this.config.trackName, true)\n }\n\n /** Unwind an outstanding suppression; no-op when none is outstanding. */\n #unsuppress(): void {\n if (!this.#suppressFired) return\n this.#suppressFired = false\n this.#manager.callbacks?.onSuppress?.(this.config.trackName, false)\n }\n}\n\n// ---------------------------------------------------------------------------\n// SessionManager\n// ---------------------------------------------------------------------------\n\nexport class SessionManager {\n readonly pool: TransportPool\n readonly sessions = new Map<string, TrackSession>()\n callbacks: SessionManagerCallbacks | null = null\n /**\n * Takeover deadline (BLO-9413/D9): max time a session may sit in `joining`\n * without a RAP before returning to `unicast` and firing onTakeoverTimeout.\n * MoQ is never suppressed during `joining`, so expiry is a silent abandon \u2014\n * playback never glitches. Hosts tune per stream (e.g. GOP length); 0\n * disables.\n */\n takeoverDeadlineMs = 5000\n\n /** Narrow to MMTP callbacks (onTrackEvent). Safe \u2014 optional chaining handles PIM-only consumers. */\n get mmtp(): MmtpSessionCallbacks | null {\n return this.callbacks as MmtpSessionCallbacks | null\n }\n\n constructor(poolOptions?: TransportPoolOptions) {\n this.pool = new TransportPool(poolOptions)\n\n // Wire pool failure \u2192 per-track failover\n this.pool.onSubscriptionFailed(sub => {\n for (const trackName of sub.consumers) {\n const session = this.sessions.get(trackName)\n if (session) session.transportFailed()\n }\n })\n }\n\n // -----------------------------------------------------------------------\n // Track management\n // -----------------------------------------------------------------------\n\n /** Add a track session from catalog config. */\n addTrack(config: TrackSessionConfig): TrackSession {\n if (this.sessions.has(config.trackName)) {\n throw new Error(`[SessionManager] Track \"${config.trackName}\" already exists`)\n }\n const session = new TrackSession(config, this)\n this.sessions.set(config.trackName, session)\n return session\n }\n\n /** Remove a track session. Releases subscription with grace period. */\n removeTrack(trackName: string): void {\n const session = this.sessions.get(trackName)\n if (!session) return\n session.unsubscribe()\n\n // Release pool subscription\n const subKey = session.config.multicastKey ?? session.config.moqTrackName\n if (subKey) this.pool.releaseSubscription(subKey, trackName)\n\n session.dispose()\n this.sessions.delete(trackName)\n }\n\n // -----------------------------------------------------------------------\n // Atomic multi-track operations\n // -----------------------------------------------------------------------\n\n /**\n * All tracks with multicast RAP \u2192 multicast state (atomic).\n * Called when MediaRouter fires onSourceSwitch('multicast').\n * Prevents split-brain between video and audio.\n *\n * A takeover deadline can return a track from `joining` to `unicast` while\n * the multicast socket keeps delivering packets. If a valid RAP arrives\n * later, allow that late-RAP edge to suppress unicast and promote multicast.\n */\n activateMulticast(): void {\n for (const [, session] of this.sessions) {\n if (session.state === 'unicast') {\n session.joinStarted()\n }\n if (session.state === 'joining') {\n session.rapReceived('multicast')\n }\n }\n }\n\n /**\n * All tracks with AMT RAP \u2192 amt state (atomic).\n */\n activateAmt(): void {\n for (const [, session] of this.sessions) {\n if (session.state === 'unicast') {\n session.joinStarted()\n }\n if (session.state === 'joining') {\n session.rapReceived('amt')\n }\n }\n }\n\n /**\n * All tracks \u2192 unicast (failback, atomic).\n * Called when MulticastManager fires onFailback().\n * unicast-fallback sessions are skipped \u2014 the host owns those subscriptions\n * and they must drain uninterrupted across transport-state events.\n *\n * Coherence invariant (BLO-9413): after this returns, every non-fallback\n * session is `unicast` (or `idle`) AND unsuppressed \u2014 unsubscribe() unwinds\n * any outstanding suppression regardless of the state it tears down from\n * (`failing` included; see TrackSession.#suppressFired).\n */\n failbackAll(): void {\n for (const [, session] of this.sessions) {\n if (\n session.state !== 'idle' &&\n session.state !== 'unicast' &&\n session.state !== 'unicast-fallback'\n ) {\n session.unsubscribe()\n session.subscribe() // re-enter unicast\n }\n }\n }\n\n /**\n * All tracks \u2192 unicast-fallback (atomic).\n * Called by the host when the multicast gateway is absent and\n * the player will subscribe to source tracks over MoQ unicast and feed\n * packets via MulticastManager.feedUnicastSource() (or manager.router\n * directly). Sessions in this state stay terminal until the host calls\n * unsubscribe() / disposes the SessionManager.\n */\n enterUnicastFallback(): void {\n for (const [, session] of this.sessions) {\n if (session.state === 'idle') continue\n session.enterUnicastFallback()\n }\n }\n\n /**\n * True if any session is currently in unicast-fallback. Hosts use this to\n * gate `multicastTrack.close()` on failback events \u2014 closing the shared\n * broadcast would kill the host's fallback drainers.\n */\n hasActiveFallback(): boolean {\n for (const [, session] of this.sessions) {\n if (session.isUnicastFallback) return true\n }\n return false\n }\n\n /**\n * All fallback tracks \u2192 unicast (atomic).\n * Called when the SSM bridge appears mid-session and the host has aborted\n * the fallback drainers. The session re-enters the regular preference chain\n * via joinStarted() (issued by the host immediately after).\n */\n exitUnicastFallback(): void {\n for (const [, session] of this.sessions) {\n if (session.isUnicastFallback) session.exitUnicastFallback()\n }\n }\n\n // -----------------------------------------------------------------------\n // Cleanup lifecycle\n // -----------------------------------------------------------------------\n\n /** Tab closed \u2014 release all subscriptions for this tab (grace period). */\n tabClosed(tabId: string): void {\n // All tracks owned by this tab \u2192 idle\n for (const [trackName, session] of this.sessions) {\n session.unsubscribe()\n this.pool.releaseAllForConsumer(trackName)\n }\n }\n\n /** Bridge WebTransport connection dropped \u2014 same as tab close. */\n bridgeDisconnected(): void {\n this.tabClosed('bridge')\n }\n\n /**\n * Track selection changed (user or ABR).\n * Old track released (grace period), new track subscribed.\n */\n trackSelectionChanged(oldTrackName: string, newConfig: TrackSessionConfig): void {\n this.removeTrack(oldTrackName)\n const session = this.addTrack(newConfig)\n session.subscribe()\n }\n\n // -----------------------------------------------------------------------\n // Query\n // -----------------------------------------------------------------------\n\n /** Get a track session by name. */\n getTrack(trackName: string): TrackSession | undefined {\n return this.sessions.get(trackName)\n }\n\n // -----------------------------------------------------------------------\n // Cleanup\n // -----------------------------------------------------------------------\n\n dispose(): void {\n for (const [, session] of this.sessions) {\n session.dispose()\n }\n this.sessions.clear()\n this.pool.dispose()\n this.callbacks = null\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["location", "formatWorkerError", "_worker", "_onError", "_disposed", "handleEvent_fn", "deriveFecInterleaveDepth", "deriveFecInterleaveDepth"]
7
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * fMP4 data-unit completion policy (BLO-13291).
3
+ *
4
+ * FFmpeg's `mmt` muxer in fMP4-fragments mode (mfu_mode=0, mmtenc_fmp4.c
5
+ * send_media_fragment) delivers one complete moof+mdat (optionally
6
+ * sidx-prefixed) per MPU data unit, split across FI=1/2/3 MMTP fragments.
7
+ * Neither wire counter can prove the chain is byte-complete:
8
+ *
9
+ * - MPU payload header byte 3 is the eight-bit fragment counter. It proves
10
+ * ordering, but cannot declare the total byte length of a fragmented DU.
11
+ * - Each fragment's payload_length bounds that packet only; it does not declare
12
+ * the total size of the multi-packet fMP4 data unit.
13
+ * - packet_sequence_number has legitimate gaps: repair and signaling packets
14
+ * consume sequence slots in the same flow at every FEC block boundary.
15
+ *
16
+ * The data unit is self-describing instead: ISOBMFF top-level box headers
17
+ * declare their 32-bit sizes. A candidate assembly is complete exactly when
18
+ * it parses as a whole number of known top-level boxes covering its full
19
+ * length. Any interior hole shifts subsequent box headers (type/size garbage)
20
+ * or leaves a declared size overrunning the buffer; missing tail bytes leave
21
+ * the final box short.
22
+ */
23
+ /**
24
+ * True when `candidate` parses as one or more complete top-level ISOBMFF
25
+ * boxes covering exactly its byte length. size==0 ("to end of file") and
26
+ * size==1 (64-bit largesize) are treated as unverifiable and return false —
27
+ * the MMT muxers never emit them for streamed data units.
28
+ */
29
+ export declare function isCompleteFmp4DataUnit(candidate: Uint8Array): boolean;
30
+ //# sourceMappingURL=fmp4-completion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fmp4-completion.d.ts","sourceRoot":"","sources":["../src/fmp4-completion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAcrE"}
@@ -0,0 +1,21 @@
1
+ // src/fmp4-completion.ts
2
+ var TOP_LEVEL_BOX_TYPES = /* @__PURE__ */ new Set(["ftyp", "styp", "moov", "moof", "mdat", "sidx", "free", "skip", "prft", "emsg"]);
3
+ function isCompleteFmp4DataUnit(candidate) {
4
+ if (candidate.length < 8) return false;
5
+ const dv = new DataView(candidate.buffer, candidate.byteOffset, candidate.byteLength);
6
+ let pos = 0;
7
+ while (pos < candidate.length) {
8
+ if (pos + 8 > candidate.length) return false;
9
+ const size = dv.getUint32(pos);
10
+ if (size < 8) return false;
11
+ const type = String.fromCharCode(candidate[pos + 4], candidate[pos + 5], candidate[pos + 6], candidate[pos + 7]);
12
+ if (!TOP_LEVEL_BOX_TYPES.has(type)) return false;
13
+ if (pos + size > candidate.length) return false;
14
+ pos += size;
15
+ }
16
+ return pos === candidate.length;
17
+ }
18
+ export {
19
+ isCompleteFmp4DataUnit
20
+ };
21
+ //# sourceMappingURL=fmp4-completion.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/fmp4-completion.ts"],
4
+ "sourcesContent": ["/**\n * fMP4 data-unit completion policy (BLO-13291).\n *\n * FFmpeg's `mmt` muxer in fMP4-fragments mode (mfu_mode=0, mmtenc_fmp4.c\n * send_media_fragment) delivers one complete moof+mdat (optionally\n * sidx-prefixed) per MPU data unit, split across FI=1/2/3 MMTP fragments.\n * Neither wire counter can prove the chain is byte-complete:\n *\n * - MPU payload header byte 3 is the eight-bit fragment counter. It proves\n * ordering, but cannot declare the total byte length of a fragmented DU.\n * - Each fragment's payload_length bounds that packet only; it does not declare\n * the total size of the multi-packet fMP4 data unit.\n * - packet_sequence_number has legitimate gaps: repair and signaling packets\n * consume sequence slots in the same flow at every FEC block boundary.\n *\n * The data unit is self-describing instead: ISOBMFF top-level box headers\n * declare their 32-bit sizes. A candidate assembly is complete exactly when\n * it parses as a whole number of known top-level boxes covering its full\n * length. Any interior hole shifts subsequent box headers (type/size garbage)\n * or leaves a declared size overrunning the buffer; missing tail bytes leave\n * the final box short.\n */\n\n/** Top-level box types the MMT fMP4 writers emit around a data unit. */\nconst TOP_LEVEL_BOX_TYPES = new Set(['ftyp', 'styp', 'moov', 'moof', 'mdat', 'sidx', 'free', 'skip', 'prft', 'emsg'])\n\n/**\n * True when `candidate` parses as one or more complete top-level ISOBMFF\n * boxes covering exactly its byte length. size==0 (\"to end of file\") and\n * size==1 (64-bit largesize) are treated as unverifiable and return false \u2014\n * the MMT muxers never emit them for streamed data units.\n */\nexport function isCompleteFmp4DataUnit(candidate: Uint8Array): boolean {\n if (candidate.length < 8) return false\n const dv = new DataView(candidate.buffer, candidate.byteOffset, candidate.byteLength)\n let pos = 0\n while (pos < candidate.length) {\n if (pos + 8 > candidate.length) return false\n const size = dv.getUint32(pos)\n if (size < 8) return false\n const type = String.fromCharCode(candidate[pos + 4]!, candidate[pos + 5]!, candidate[pos + 6]!, candidate[pos + 7]!)\n if (!TOP_LEVEL_BOX_TYPES.has(type)) return false\n if (pos + size > candidate.length) return false\n pos += size\n }\n return pos === candidate.length\n}\n"],
5
+ "mappings": ";AAwBA,IAAM,sBAAsB,oBAAI,IAAI,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,MAAM,CAAC;AAQ7G,SAAS,uBAAuB,WAAgC;AACrE,MAAI,UAAU,SAAS,EAAG,QAAO;AACjC,QAAM,KAAK,IAAI,SAAS,UAAU,QAAQ,UAAU,YAAY,UAAU,UAAU;AACpF,MAAI,MAAM;AACV,SAAO,MAAM,UAAU,QAAQ;AAC7B,QAAI,MAAM,IAAI,UAAU,OAAQ,QAAO;AACvC,UAAM,OAAO,GAAG,UAAU,GAAG;AAC7B,QAAI,OAAO,EAAG,QAAO;AACrB,UAAM,OAAO,OAAO,aAAa,UAAU,MAAM,CAAC,GAAI,UAAU,MAAM,CAAC,GAAI,UAAU,MAAM,CAAC,GAAI,UAAU,MAAM,CAAC,CAAE;AACnH,QAAI,CAAC,oBAAoB,IAAI,IAAI,EAAG,QAAO;AAC3C,QAAI,MAAM,OAAO,UAAU,OAAQ,QAAO;AAC1C,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,UAAU;AAC3B;",
6
+ "names": []
7
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Minimal ISOBMFF box reader. NOT a full MP4 parser — just enough to walk
3
+ * the box tree and pull out fields that libmmt's fMP4 writers emit.
4
+ * Used by unit tests; not part of the runtime pipeline.
5
+ */
6
+ export type Box = {
7
+ type: string;
8
+ start: number;
9
+ end: number;
10
+ payloadStart: number;
11
+ };
12
+ export declare function walkBoxes(data: Uint8Array, start?: number, end?: number): Box[];
13
+ export declare function findBox(boxes: Box[], type: string): Box | undefined;
14
+ export declare function childrenOf(data: Uint8Array, box: Box): Box[];
15
+ export declare function readFullBox(data: Uint8Array, box: Box): {
16
+ version: number;
17
+ flags: number;
18
+ bodyStart: number;
19
+ };
20
+ export declare function readTfdtBaseMediaDecodeTime(segment: Uint8Array): number;
21
+ export type TrunSample = {
22
+ duration: number;
23
+ size: number;
24
+ flags: number;
25
+ compositionTimeOffset: number;
26
+ };
27
+ export type TrunInfo = {
28
+ version: number;
29
+ flags: number;
30
+ sampleCount: number;
31
+ dataOffset: number;
32
+ samples: TrunSample[];
33
+ };
34
+ export declare function readTrun(segment: Uint8Array): TrunInfo;
35
+ export declare function readMfhdSequence(segment: Uint8Array): number;
36
+ export declare function readMdatSize(segment: Uint8Array): number;
37
+ //# sourceMappingURL=fmp4-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fmp4-reader.d.ts","sourceRoot":"","sources":["../src/fmp4-reader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,GAAG,GAAG;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,SAAI,EAAE,GAAG,SAAc,GAAG,GAAG,EAAE,CAY/E;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAEnE;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,CAE5D;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAI7G;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAYvE;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,qBAAqB,EAAE,MAAM,CAAA;CAC9B,CAAA;AACD,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,UAAU,EAAE,CAAA;CACtB,CAAA;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,QAAQ,CA6BtD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAM5D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAGxD"}
@@ -0,0 +1,100 @@
1
+ // src/fmp4-reader.ts
2
+ function walkBoxes(data, start = 0, end = data.length) {
3
+ const out = [];
4
+ const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);
5
+ let pos = start;
6
+ while (pos + 8 <= end) {
7
+ const size = dv.getUint32(pos);
8
+ const type = String.fromCharCode(data[pos + 4], data[pos + 5], data[pos + 6], data[pos + 7]);
9
+ if (size < 8 || pos + size > end) break;
10
+ out.push({ type, start: pos, end: pos + size, payloadStart: pos + 8 });
11
+ pos += size;
12
+ }
13
+ return out;
14
+ }
15
+ function findBox(boxes, type) {
16
+ return boxes.find((b) => b.type === type);
17
+ }
18
+ function childrenOf(data, box) {
19
+ return walkBoxes(data, box.payloadStart, box.end);
20
+ }
21
+ function readFullBox(data, box) {
22
+ const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);
23
+ const verFlags = dv.getUint32(box.payloadStart);
24
+ return { version: verFlags >>> 24, flags: verFlags & 16777215, bodyStart: box.payloadStart + 4 };
25
+ }
26
+ function readTfdtBaseMediaDecodeTime(segment) {
27
+ const moof = findBox(walkBoxes(segment), "moof");
28
+ const traf = findBox(childrenOf(segment, moof), "traf");
29
+ const tfdt = findBox(childrenOf(segment, traf), "tfdt");
30
+ const { version, bodyStart } = readFullBox(segment, tfdt);
31
+ const dv = new DataView(segment.buffer, segment.byteOffset, segment.byteLength);
32
+ if (version === 1) {
33
+ const hi = dv.getUint32(bodyStart);
34
+ const lo = dv.getUint32(bodyStart + 4);
35
+ return hi * 4294967296 + lo;
36
+ }
37
+ return dv.getUint32(bodyStart);
38
+ }
39
+ function readTrun(segment) {
40
+ const moof = findBox(walkBoxes(segment), "moof");
41
+ const traf = findBox(childrenOf(segment, moof), "traf");
42
+ const trun = findBox(childrenOf(segment, traf), "trun");
43
+ const { version, flags, bodyStart } = readFullBox(segment, trun);
44
+ const dv = new DataView(segment.buffer, segment.byteOffset, segment.byteLength);
45
+ const sampleCount = dv.getUint32(bodyStart);
46
+ let cursor = bodyStart + 4;
47
+ let dataOffset = 0;
48
+ if (flags & 1) {
49
+ dataOffset = dv.getInt32(cursor);
50
+ cursor += 4;
51
+ }
52
+ const hasDuration = !!(flags & 256);
53
+ const hasSize = !!(flags & 512);
54
+ const hasFlags = !!(flags & 1024);
55
+ const hasCompositionTimeOffset = !!(flags & 2048);
56
+ const samples = [];
57
+ for (let i = 0; i < sampleCount; i++) {
58
+ const s = { duration: 0, size: 0, flags: 0, compositionTimeOffset: 0 };
59
+ if (hasDuration) {
60
+ s.duration = dv.getUint32(cursor);
61
+ cursor += 4;
62
+ }
63
+ if (hasSize) {
64
+ s.size = dv.getUint32(cursor);
65
+ cursor += 4;
66
+ }
67
+ if (hasFlags) {
68
+ s.flags = dv.getUint32(cursor);
69
+ cursor += 4;
70
+ }
71
+ if (hasCompositionTimeOffset) {
72
+ s.compositionTimeOffset = version === 1 ? dv.getInt32(cursor) : dv.getUint32(cursor);
73
+ cursor += 4;
74
+ }
75
+ samples.push(s);
76
+ }
77
+ return { version, flags, sampleCount, dataOffset, samples };
78
+ }
79
+ function readMfhdSequence(segment) {
80
+ const moof = findBox(walkBoxes(segment), "moof");
81
+ const mfhd = findBox(childrenOf(segment, moof), "mfhd");
82
+ const { bodyStart } = readFullBox(segment, mfhd);
83
+ const dv = new DataView(segment.buffer, segment.byteOffset, segment.byteLength);
84
+ return dv.getUint32(bodyStart);
85
+ }
86
+ function readMdatSize(segment) {
87
+ const mdat = findBox(walkBoxes(segment), "mdat");
88
+ return mdat.end - mdat.payloadStart;
89
+ }
90
+ export {
91
+ childrenOf,
92
+ findBox,
93
+ readFullBox,
94
+ readMdatSize,
95
+ readMfhdSequence,
96
+ readTfdtBaseMediaDecodeTime,
97
+ readTrun,
98
+ walkBoxes
99
+ };
100
+ //# sourceMappingURL=fmp4-reader.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/fmp4-reader.ts"],
4
+ "sourcesContent": ["/**\n * Minimal ISOBMFF box reader. NOT a full MP4 parser \u2014 just enough to walk\n * the box tree and pull out fields that libmmt's fMP4 writers emit.\n * Used by unit tests; not part of the runtime pipeline.\n */\n\nexport type Box = {\n type: string\n start: number\n end: number\n payloadStart: number\n}\n\nexport function walkBoxes(data: Uint8Array, start = 0, end = data.length): Box[] {\n const out: Box[] = []\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength)\n let pos = start\n while (pos + 8 <= end) {\n const size = dv.getUint32(pos)\n const type = String.fromCharCode(data[pos + 4], data[pos + 5], data[pos + 6], data[pos + 7])\n if (size < 8 || pos + size > end) break\n out.push({ type, start: pos, end: pos + size, payloadStart: pos + 8 })\n pos += size\n }\n return out\n}\n\nexport function findBox(boxes: Box[], type: string): Box | undefined {\n return boxes.find(b => b.type === type)\n}\n\nexport function childrenOf(data: Uint8Array, box: Box): Box[] {\n return walkBoxes(data, box.payloadStart, box.end)\n}\n\nexport function readFullBox(data: Uint8Array, box: Box): { version: number; flags: number; bodyStart: number } {\n const dv = new DataView(data.buffer, data.byteOffset, data.byteLength)\n const verFlags = dv.getUint32(box.payloadStart)\n return { version: verFlags >>> 24, flags: verFlags & 0xffffff, bodyStart: box.payloadStart + 4 }\n}\n\nexport function readTfdtBaseMediaDecodeTime(segment: Uint8Array): number {\n const moof = findBox(walkBoxes(segment), 'moof')!\n const traf = findBox(childrenOf(segment, moof), 'traf')!\n const tfdt = findBox(childrenOf(segment, traf), 'tfdt')!\n const { version, bodyStart } = readFullBox(segment, tfdt)\n const dv = new DataView(segment.buffer, segment.byteOffset, segment.byteLength)\n if (version === 1) {\n const hi = dv.getUint32(bodyStart)\n const lo = dv.getUint32(bodyStart + 4)\n return hi * 0x100000000 + lo\n }\n return dv.getUint32(bodyStart)\n}\n\nexport type TrunSample = {\n duration: number\n size: number\n flags: number\n compositionTimeOffset: number\n}\nexport type TrunInfo = {\n version: number\n flags: number\n sampleCount: number\n dataOffset: number\n samples: TrunSample[]\n}\n\nexport function readTrun(segment: Uint8Array): TrunInfo {\n const moof = findBox(walkBoxes(segment), 'moof')!\n const traf = findBox(childrenOf(segment, moof), 'traf')!\n const trun = findBox(childrenOf(segment, traf), 'trun')!\n const { version, flags, bodyStart } = readFullBox(segment, trun)\n const dv = new DataView(segment.buffer, segment.byteOffset, segment.byteLength)\n const sampleCount = dv.getUint32(bodyStart)\n let cursor = bodyStart + 4\n let dataOffset = 0\n if (flags & 0x000001) { dataOffset = dv.getInt32(cursor); cursor += 4 }\n const hasDuration = !!(flags & 0x000100)\n const hasSize = !!(flags & 0x000200)\n const hasFlags = !!(flags & 0x000400)\n const hasCompositionTimeOffset = !!(flags & 0x000800)\n const samples: TrunSample[] = []\n for (let i = 0; i < sampleCount; i++) {\n const s: TrunSample = { duration: 0, size: 0, flags: 0, compositionTimeOffset: 0 }\n if (hasDuration) { s.duration = dv.getUint32(cursor); cursor += 4 }\n if (hasSize) { s.size = dv.getUint32(cursor); cursor += 4 }\n if (hasFlags) { s.flags = dv.getUint32(cursor); cursor += 4 }\n if (hasCompositionTimeOffset) {\n s.compositionTimeOffset = version === 1\n ? dv.getInt32(cursor)\n : dv.getUint32(cursor)\n cursor += 4\n }\n samples.push(s)\n }\n return { version, flags, sampleCount, dataOffset, samples }\n}\n\nexport function readMfhdSequence(segment: Uint8Array): number {\n const moof = findBox(walkBoxes(segment), 'moof')!\n const mfhd = findBox(childrenOf(segment, moof), 'mfhd')!\n const { bodyStart } = readFullBox(segment, mfhd)\n const dv = new DataView(segment.buffer, segment.byteOffset, segment.byteLength)\n return dv.getUint32(bodyStart)\n}\n\nexport function readMdatSize(segment: Uint8Array): number {\n const mdat = findBox(walkBoxes(segment), 'mdat')!\n return mdat.end - mdat.payloadStart\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @mmt/container - MMTP/LOC Container Parsing
3
+ *
4
+ * Shared container parsing library for MMT over MoQ and SSM.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ export type { AuthoredTiming } from './authored-timing.js';
9
+ export { type MFUFragment, type ReassembledMFU, type ReassemblerStats, type MFUReassemblerOptions, type MfuReassemblerBackend, type MmtpSourcePath, MFUReassembler, MfuReassemblyError, type MfuReassemblyErrorCode, createFragment, processMMTPWithReassembly, } from './mfu-reassembler.js';
10
+ export { type CombinedSample, type SampleCombinerStats, SampleCombiner, SampleCombineError, type SampleCombineErrorCode, } from './sample-combiner.js';
11
+ export { isCompleteFmp4DataUnit } from './fmp4-completion.js';
12
+ export { type AvcCInfo, type AacAscInfo, type SpsPps, type FallbackAvcCOptions, type HevcParameterSets, type H264KeyframeDetectionOptions, type H264AvccSample, type H264SampleFormat, type H264NalUnitFormat, type H264NalUnitSample, extractAvcCFromInitSegment, extractAacAscFromInitSegment, generateFallbackAvcC, extractSpsPpsFromAvcC, avccToAnnexB, extractCodecDescriptionFromAnnexB, codecStringFromAvcC, isAnnexB, isCompleteAvccSample, findAnnexBStartCode, splitAnnexBNalUnits, annexBToAvcc, normalizeH264SampleToAvcc, splitH264SampleNalUnits, classifyH264Keyframe, detectH264Keyframe, mmtpTimestampToMicros, isFmp4InitSegment, wrapAdtsFrame, isHevcCodec, removeEmulationPrevention, splitAvccNalUnits, extractHevcParameterSets, generateHvcCFromParameterSets, extractHevcCodecDescription, hevcVclOnly, } from './codec-utils.js';
13
+ export { LOCHeaderExtensionId, FEC_SBN_MAX, FEC_ESI_MAX, encodeFecSourceInfo, decodeFecSourceInfo, FecSourceInfo, AuthTag, } from './loc.js';
14
+ export { type FecAlgorithm, type FecCatalogConfig, isFecCatalogConfig, type MulticastProtocol, type MulticastTrack, type MulticastTrackObject, type MulticastEndpoint, type AmtDiscovery, type MulticastCatalogConfig, isMulticastTrackObject, isMulticastEndpoint, isMulticastCatalogConfig, type TrackTimingConfig, isTrackTimingConfig, resolveGroupDurationTicks, resolveGroupDurationMs, validateSwitchingSetTiming, type CmsfCatalog, type CmsfCatalogErrorCode, CmsfCatalogValidationError, validateCmsfMmtpCatalog, } from './carp-catalog.js';
15
+ export { type MulticastInput, type MulticastEndpointInput, type MulticastInputErrorKind, MulticastInputError, multicastFromConfig, multicastFromEnv, } from './multicast-input.js';
16
+ export { type Phase14OverrideTrack, type Phase14CatalogOverride, getPhase14CatalogOverride, mergeOverrideIntoHangRenditions, mergeOverrideIntoCmsfTracks, } from './phase14-catalog-override.js';
17
+ export { type MulticastContainerContract, type MulticastContainerErrorCode, type FecPayloadId as MulticastFecPayloadId, type MulticastFrame, MulticastContainerContractError, validateMulticastContainerContract, unwrapMulticastPacket, } from './multicast-unwrap.js';
18
+ export { type ContainerFormat, type LocHeader, encodeTimestamp, decodeTimestamp, getTimestampSize, decodeLocHeader, decodeLocTimestamp, encodeLocTimestamp, } from './timestamp-codec.js';
19
+ export { MmtpToCmaf, encodeDataSegment, encodeMultiSampleSegment, buildVideoInitSegment, buildAudioInitSegment, generateGreenFillNAL, generateSilenceFrame, } from './mmtp-to-cmaf.js';
20
+ export { type PacketClass, getPacketType, isSignalingPacket, isSourcePacket, classifyPacket, } from './signaling.js';
21
+ export { CmafBlockAssembler, type CmafBlockSample, type CmafSampleOrderPolicy, type CmafSampleOrderStats, type BlockAssemblerConfig, } from './cmaf-block-assembler.js';
22
+ export { CmafGroupBatcher, type CmafGroupBatcherConfig, } from './cmaf-group-batcher.js';
23
+ export { FECManager, type FECManagerConfig, type WasmFecDecoder, type FecStats, } from './fec-manager.js';
24
+ export { MmtpRouter, KEYFRAME_LOST_TIMEOUT_SLACK, type FrameCallback, type FECManagerLike, type MmtpIngressContext, type RoutedPacketMeta, type TrackPacketCallback, } from './mmtp-router.js';
25
+ export { MmtpContainerParser, type MmtpParserConfig, type MmtpParserRecord, type TrackInfo, type MmtpReorderStats, type MmtpReorderFrameDiagnostics, type MmtpReorderStreamDiagnostics, type FrameMeta as ParserFrameMeta, type PacketInfo, } from './mmtp-container-parser.js';
26
+ export { datagramMfuReassembly, reliableMoqMfuReassembly, mmtpFrameReorderWindowFrames, mfuReassemblyTimeoutMs, type MfuReassemblyPolicy, type MmtpTrackType, type ReliableMoqReassemblyOptions, } from './mfu-reassembly-policy.js';
27
+ export { WasmMfuReassembler, resolveGlobalMmtWasmBindings, type MmtWasmBindings, type WasmMfuReassemblerOptions, } from './wasm-mfu-reassembler.js';
28
+ export { createWasmMmtpContainerParser, type WasmMmtpParserConfig, } from './wasm-mmtp-container-parser.js';
29
+ export { type FecCodec, NoneCodec, ReedSolomonCodec, createFecCodec, } from './fec-codec.js';
30
+ export { MulticastTransport, type MulticastTransportConfig, type ResolvedMulticastTransport, } from './multicast-transport.js';
31
+ export { MulticastManager, forwardRepairLifecycleEvents, isRepairLifecycleEvent, REPAIR_LIFECYCLE_EVENT_TYPE, REPAIR_LIFECYCLE_LOG_PREFIX, type MulticastEndpointConfig, type MultiTrackCatalog, type MultiTrackCatalogTrack, type WasmFecDecoderFactory, type RepairBlockIdentity, type RepairLifecycleApplicationEvent, type RepairLifecycleEventOptions, type RepairLifecycleEventFactory, type RepairLifecycleEventTarget, type RepairLifecycleSource, type RepairLifecycleEvent, type RepairLifecycleObserver, } from './multicast-manager.js';
32
+ export { setupFecWorkerForTrack, type FecWorkerAssetUrls, type FecWorkerSetupOptions, type FecWorkerSetupResult, } from './fec-worker-setup.js';
33
+ export { MediaRouter, TrackSourceConflictError, type MediaRouterOptions, type TrackSource, type SetTrackSourceOptions, type MigrationPolicy, type FrameMeta as RouterFrameMeta, type FrameKind, type SourceKind, type GroupDriftEvent, type GroupBoundaryTicks, } from './media-router.js';
34
+ export { groupIdForTicks, groupIdFor, secondsFromTicks, asSeconds, driftCheck, type Seconds, type DriftCheckResult, } from './align.js';
35
+ export { AudioRingBuffer, type AudioRingBufferConfig, } from './audio-ring-buffer.js';
36
+ export { MmtpDecodePipeline, type PipelineFecClient, type PipelineConfig, } from './mmtp-decode-pipeline.js';
37
+ export { TrackPipeline, type TrackTransport, type TrackTransportPreference, type TransportCapabilityReport, type TrackTransportResolution, type TrackSourceFactory, } from './track-pipeline.js';
38
+ export { setupTrackPipeline, type TrackDescriptor, type SetupTrackPipelineOptions, type SetupTrackPipelineResult, } from './track-pipeline-setup.js';
39
+ export { parseAacFrameSamples, parseAacSampleRate, parseOpusFrameSamples, frameSamplesFromInit, } from './audio-init-parser.js';
40
+ export { TransportPool, type SubscriptionMode, type DirectSocketHealth, type Subscription, type SubscriptionStats, type AcquireOptions, type TransportPoolOptions, } from './transport-pool.js';
41
+ export { TrackSession, SessionManager, computeFecDeliveryWindowMs, computeFecDeliveryWindowMediaUnits, computeFecLossWindowMs, type FecDeliveryWindowConfig, type TrackState, type TrackSessionConfig, type SessionManagerCallbacks, type MmtpTrackEvent, type MmtpSessionCallbacks, } from './track-session.js';
42
+ export { FecStarvationDetector, type FecStarvationSnapshot, type FecStarvationDetectorConfig, } from './fec-starvation-detector.js';
43
+ export { CmcdProducer, type CmcdParams, type CmcdProducerOptions, type SnapshotData, type TransportSnapshot, type TransportTransitionEvent, } from './cmcd-producer.js';
44
+ export { catalogFecInterleaveMs, resolveCatalogTrackFec, type CatalogTrackRef, type FecInterleaveCatalog, type GroupDurationCatalog, type KeyframeCadenceCatalog, type TrackFecParams, } from "./catalog-fec-params.js";
45
+ export { catalogAmtNetworkSource, type AmtNetworkSource, type CatalogNetworkSource, } from "./catalog-network-source.js";
46
+ export { wireRepairFetch, type ResolveRepairTarget, type RepairFetchTransport, type WireRepairFetchOptions, } from './repair-fetch.js';
47
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}