@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": ["../src/multicast-auth-catalog.ts", "../src/carp-catalog.ts"],
4
+ "sourcesContent": ["/**\n * `multicast.auth` v2 \u2014 catalog representation for per-track source-auth\n * scopes and manifest tracks (BLO-16700 decision).\n *\n * Reconciles two previously-accepted, mutually incompatible contracts:\n * - BLO-16481 (S0): every publisher session/track/source-symbol-format\n * needs its own fresh, unpredictable 32-byte `auth_scope`, bound into\n * the signed per-group Merkle root (see `sourceAuthSignaturePreimage`\n * in ./source-auth.ts).\n * - BLO-16485 (S3 draft): a singular `multicast.auth` block with one\n * `manifestTrack` string and no `authScope` field at all \u2014 unable to\n * describe two protected tracks (e.g. audio + video) in one session.\n *\n * `multicast.auth` v2 keeps one shared signing identity (scheme, hash,\n * sig, publicKey, keyId, previousKey, compaction, enforcement) but moves\n * `manifestTrack` into a `tracks[]` array, one entry per protected media\n * track, each carrying its own `manifestTrack` name, `authScope`, and\n * `sourceSymbolFormat`. This is additive over the S3 draft shape (every\n * top-level field the draft specified still exists at the top level) \u2014\n * only `manifestTrack` moves from top-level into each track entry.\n *\n * `manifestTrack` is carried as an opaque string field, deliberately NOT\n * run through `parseTrackRole`/`VALID_ROLE_SUFFIXES` in ./carp-catalog.ts.\n * `carp-catalog.ts` only recognises `base`/`delta`/`repair` role suffixes\n * and throws on anything else (including a hypothetical `manifest` role);\n * resolving BLO-16485's \"manifest-track name collision\" MANDATORY item by\n * adding a role would force every catalog consumer to learn a fourth role\n * and would break `validateSwitchingSet`'s base/delta/repair completeness\n * check. Carrying it as a typed field here avoids both.\n */\n\nexport type MulticastAuthScheme = \"bc-provenance\";\nexport type MulticastAuthHash = \"blake3\";\nexport type MulticastAuthSig = \"ed25519\";\nexport type MulticastAuthCompaction = \"merkle\" | \"none\";\nexport type MulticastAuthEnforcement = \"shadow\" | \"enforce\";\nexport type MulticastAuthMode = \"off\" | MulticastAuthEnforcement;\n\nconst RAW_ED25519_KEY_LENGTH = 32;\nconst SOURCE_AUTH_SCOPE_LENGTH = 32;\n\nconst BASE64URL_ALPHABET =\n\t\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n\n/** Encode raw bytes as unpadded base64url \u2014 the one accepted encoding for\n * `authScope`/`publicKey`/`previousKey` (BLO-16483's operator quickstart). */\nexport function encodeBase64Url(bytes: Uint8Array): string {\n\tlet output = \"\";\n\tfor (let i = 0; i < bytes.length; i += 3) {\n\t\tconst b0 = bytes[i]!;\n\t\tconst b1 = bytes[i + 1];\n\t\tconst b2 = bytes[i + 2];\n\t\toutput += BASE64URL_ALPHABET[b0 >> 2];\n\t\toutput += BASE64URL_ALPHABET[((b0 & 0x03) << 4) | (b1 === undefined ? 0 : b1 >> 4)];\n\t\tif (b1 === undefined) break;\n\t\toutput += BASE64URL_ALPHABET[((b1 & 0x0f) << 2) | (b2 === undefined ? 0 : b2 >> 6)];\n\t\tif (b2 === undefined) break;\n\t\toutput += BASE64URL_ALPHABET[b2 & 0x3f];\n\t}\n\treturn output;\n}\n\nconst BASE64URL_DECODE_TABLE = (() => {\n\tconst table = new Int8Array(128).fill(-1);\n\tfor (let i = 0; i < BASE64URL_ALPHABET.length; i++) {\n\t\ttable[BASE64URL_ALPHABET.charCodeAt(i)] = i;\n\t}\n\treturn table;\n})();\n\n/** Decode unpadded base64url text to raw bytes. Throws on any padding\n * (`=`), standard-alphabet (`+`/`/`), or otherwise invalid character. */\nexport function decodeBase64Url(text: string): Uint8Array {\n\tif (text.length % 4 === 1) {\n\t\tthrow new Error(`[multicast-auth-catalog] invalid unpadded base64url length for \"${text}\"`);\n\t}\n\tconst bytes: number[] = [];\n\tlet buffer = 0;\n\tlet bits = 0;\n\tfor (let i = 0; i < text.length; i++) {\n\t\tconst code = text.charCodeAt(i);\n\t\tconst value = code < 128 ? BASE64URL_DECODE_TABLE[code] : -1;\n\t\tif (value === undefined || value < 0) {\n\t\t\tthrow new Error(`[multicast-auth-catalog] invalid base64url character in \"${text}\"`);\n\t\t}\n\t\tbuffer = (buffer << 6) | value;\n\t\tbits += 6;\n\t\tif (bits >= 8) {\n\t\t\tbits -= 8;\n\t\t\tbytes.push((buffer >> bits) & 0xff);\n\t\t}\n\t}\n\tconst decoded = Uint8Array.from(bytes);\n\tif (encodeBase64Url(decoded) !== text) {\n\t\tthrow new Error(`[multicast-auth-catalog] non-canonical base64url encoding \"${text}\"`);\n\t}\n\treturn decoded;\n}\n\n/** Decode + length-validate an `authScope` field. Throws unless it decodes\n * to exactly `SOURCE_AUTH_SCOPE_LENGTH` (32) raw bytes. */\nexport function decodeAuthScope(authScope: string): Uint8Array {\n\tconst bytes = decodeBase64Url(authScope);\n\tif (bytes.byteLength !== SOURCE_AUTH_SCOPE_LENGTH) {\n\t\tthrow new Error(\n\t\t\t`[multicast-auth-catalog] authScope must decode to ${SOURCE_AUTH_SCOPE_LENGTH} raw bytes, got ${bytes.byteLength}`,\n\t\t);\n\t}\n\treturn bytes;\n}\n\n/** Decode a catalog key in the only accepted representation: exactly 32 raw\n * ed25519 bytes encoded as canonical, unpadded base64url. */\nexport function decodeEd25519PublicKey(publicKey: string): Uint8Array {\n\tconst bytes = decodeBase64Url(publicKey);\n\tif (bytes.byteLength !== RAW_ED25519_KEY_LENGTH) {\n\t\tthrow new Error(\n\t\t\t`[multicast-auth-catalog] public key must decode to ${RAW_ED25519_KEY_LENGTH} raw bytes, got ${bytes.byteLength}`,\n\t\t);\n\t}\n\treturn bytes;\n}\n\n/**\n * One protected media track's manifest + scope binding.\n *\n * - `mediaTrack`: the actual media track name (e.g. `\"video/base\"`).\n * - `manifestTrack`: the sibling track carrying this track's signed\n * manifest objects (see ./source-auth.ts `SourceAuthObjectEntry`/\n * `SourceAuthGroupClose`). Opaque string \u2014 not role-parsed.\n * - `authScope`: this track's unique 32-byte scope, raw bytes as unpadded\n * base64url. BLO-16481 requires a scope fresh per (publisher session,\n * track, source-symbol format) \u2014 a track publishing under two source-\n * symbol formats in the same session MUST appear as two entries here,\n * each with its own scope.\n * - `sourceSymbolFormat`: names the deployed source-symbol profile this\n * track's authenticated bytes are derived from (e.g.\n * `\"full-mmtp-packet\"` or `\"fec-padded-recovery\"`, the two formats\n * BLO-16481's S0 fixture covers).\n */\nexport interface MulticastAuthTrackConfig {\n\tmediaTrack: string;\n\tmanifestTrack: string;\n\tauthScope: string;\n\tsourceSymbolFormat: string;\n}\n\n/**\n * `multicast.auth` v2 \u2014 supersedes the BLO-16485 draft's singular\n * `manifestTrack`/no-`authScope` shape (BLO-16700 decision).\n */\nexport interface MulticastAuthConfig {\n\tscheme: MulticastAuthScheme;\n\thash: MulticastAuthHash;\n\tsig: MulticastAuthSig;\n\t/** Raw 32-byte ed25519 public key, unpadded base64url. */\n\tpublicKey: string;\n\tkeyId: string;\n\t/** Raw 32-byte ed25519 public key, unpadded base64url. Accepted\n\t * alongside `publicKey` during a key-rotation overlap window. */\n\tpreviousKey?: string;\n\tcompaction: MulticastAuthCompaction;\n\t/** Player-config-wins default; catalog value only selects the default\n\t * when the player hasn't pinned one (S3 enforcement precedence). */\n\tenforcement?: MulticastAuthEnforcement;\n\ttracks: MulticastAuthTrackConfig[];\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n\treturn typeof value === \"string\" && value.length > 0;\n}\n\nfunction isValidAuthScopeField(value: unknown): value is string {\n\tif (!isNonEmptyString(value)) return false;\n\ttry {\n\t\tdecodeAuthScope(value);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction isValidPublicKeyField(value: unknown): value is string {\n\tif (!isNonEmptyString(value)) return false;\n\ttry {\n\t\tdecodeEd25519PublicKey(value);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction hasOnlyKeys(object: Record<string, unknown>, allowed: readonly string[]): boolean {\n\tconst allowedKeys = new Set(allowed);\n\treturn Object.keys(object).every((key) => allowedKeys.has(key));\n}\n\nexport function isMulticastAuthTrackConfig(obj: unknown): obj is MulticastAuthTrackConfig {\n\tif (typeof obj !== \"object\" || obj === null) return false;\n\tconst o = obj as Record<string, unknown>;\n\treturn (\n\t\thasOnlyKeys(o, [\"mediaTrack\", \"manifestTrack\", \"authScope\", \"sourceSymbolFormat\"]) &&\n\t\tisNonEmptyString(o[\"mediaTrack\"]) &&\n\t\tisNonEmptyString(o[\"manifestTrack\"]) &&\n\t\to[\"mediaTrack\"] !== o[\"manifestTrack\"] &&\n\t\tisValidAuthScopeField(o[\"authScope\"]) &&\n\t\tisNonEmptyString(o[\"sourceSymbolFormat\"])\n\t);\n}\n\nconst VALID_COMPACTION = new Set<string>([\"merkle\", \"none\"]);\nconst VALID_ENFORCEMENT = new Set<string>([\"shadow\", \"enforce\"]);\n\n/** Semantic uniqueness rule shared by runtime parsing and the published\n * catalog schema's `uniqueMulticastAuthTrackBindings` keyword. */\nexport function hasUniqueMulticastAuthTrackBindings(tracks: readonly unknown[]): boolean {\n\tconst bindings = tracks.flatMap((track) => {\n\t\tif (typeof track !== \"object\" || track === null) return [];\n\t\tconst value = track as Record<string, unknown>;\n\t\tif (typeof value[\"mediaTrack\"] !== \"string\" || typeof value[\"sourceSymbolFormat\"] !== \"string\") {\n\t\t\treturn [];\n\t\t}\n\t\treturn [JSON.stringify([value[\"mediaTrack\"], value[\"sourceSymbolFormat\"]])];\n\t});\n\treturn new Set(bindings).size === bindings.length;\n}\n\nexport function isMulticastAuthConfig(obj: unknown): obj is MulticastAuthConfig {\n\tif (typeof obj !== \"object\" || obj === null) return false;\n\tconst o = obj as Record<string, unknown>;\n\n\tif (o[\"scheme\"] !== \"bc-provenance\") return false;\n\tif (o[\"hash\"] !== \"blake3\") return false;\n\tif (o[\"sig\"] !== \"ed25519\") return false;\n\tif (!hasOnlyKeys(o, [\"scheme\", \"hash\", \"sig\", \"publicKey\", \"keyId\", \"previousKey\", \"compaction\", \"enforcement\", \"tracks\"])) return false;\n\tif (!isValidPublicKeyField(o[\"publicKey\"])) return false;\n\tif (!isNonEmptyString(o[\"keyId\"])) return false;\n\tif (o[\"previousKey\"] !== undefined && !isValidPublicKeyField(o[\"previousKey\"])) return false;\n\tif (o[\"previousKey\"] === o[\"publicKey\"]) return false;\n\tif (typeof o[\"compaction\"] !== \"string\" || !VALID_COMPACTION.has(o[\"compaction\"])) return false;\n\tif (o[\"enforcement\"] !== undefined) {\n\t\tif (typeof o[\"enforcement\"] !== \"string\" || !VALID_ENFORCEMENT.has(o[\"enforcement\"])) return false;\n\t}\n\n\tif (!Array.isArray(o[\"tracks\"]) || o[\"tracks\"].length === 0) return false;\n\tconst tracks = o[\"tracks\"] as unknown[];\n\tif (!tracks.every((t) => isMulticastAuthTrackConfig(t))) return false;\n\tconst typedTracks = tracks as MulticastAuthTrackConfig[];\n\n\t// BLO-16481: a fresh scope per track \u2014 catalog-declared scopes must be\n\t// pairwise distinct within one auth block.\n\tconst scopes = typedTracks.map((t) => t.authScope);\n\tif (new Set(scopes).size !== scopes.length) return false;\n\tif (!hasUniqueMulticastAuthTrackBindings(typedTracks)) return false;\n\n\t// Each entry must point at its own manifest track.\n\tconst manifestTracks = typedTracks.map((t) => t.manifestTrack);\n\tif (new Set(manifestTracks).size !== manifestTracks.length) return false;\n\n\treturn true;\n}\n\nexport interface ResolvedMulticastAuthConfig {\n\tkeyId: string;\n\t/** Current key first, followed by the overlap key when advertised. */\n\tacceptedPublicKeys: Uint8Array[];\n\tmode: MulticastAuthMode;\n\tcompaction: MulticastAuthCompaction;\n\ttracks: Array<Omit<MulticastAuthTrackConfig, \"authScope\"> & { authScope: Uint8Array }>;\n}\n\n/** Player configuration is authoritative, including an explicit `off`.\n * Catalog enforcement is only a default; an auth block without it defaults\n * to shadow, while a catalog without auth defaults to off. */\nexport function resolveMulticastAuthMode(\n\tplayerMode: MulticastAuthMode | undefined,\n\tauth: MulticastAuthConfig | undefined,\n): MulticastAuthMode {\n\tif (playerMode !== undefined) return playerMode;\n\tif (auth === undefined) return \"off\";\n\treturn auth.enforcement ?? \"shadow\";\n}\n\n/** Parse and resolve the catalog auth block into verifier-ready raw keys and\n * scopes. Invalid blocks and dangling media/manifest track references fail\n * closed instead of silently falling back to unauthenticated playback. */\nexport function resolveMulticastAuthCatalog(\n\tcatalog: unknown,\n\tplayerMode?: MulticastAuthMode,\n): ResolvedMulticastAuthConfig | undefined {\n\tif (typeof catalog !== \"object\" || catalog === null || Array.isArray(catalog)) {\n\t\tthrow new Error(\"[multicast-auth-catalog] catalog must be an object\");\n\t}\n\tconst root = catalog as Record<string, unknown>;\n\tconst rawAuth = root[\"multicast.auth\"];\n\tif (rawAuth === undefined) {\n\t\tif (playerMode === \"enforce\") {\n\t\t\tthrow new Error(\"[multicast-auth-catalog] player enforce mode requires multicast.auth\");\n\t\t}\n\t\treturn undefined;\n\t}\n\tif (!isMulticastAuthConfig(rawAuth)) {\n\t\tthrow new Error(\"[multicast-auth-catalog] invalid multicast.auth v2 block\");\n\t}\n\n\tconst rawTracks = root[\"tracks\"];\n\tif (!Array.isArray(rawTracks)) {\n\t\tthrow new Error(\"[multicast-auth-catalog] catalog tracks must be an array\");\n\t}\n\tconst catalogTrackNames = new Set(\n\t\trawTracks.flatMap((track) =>\n\t\t\ttypeof track === \"object\" && track !== null &&\n\t\t\ttypeof (track as Record<string, unknown>)[\"name\"] === \"string\"\n\t\t\t\t? [(track as Record<string, unknown>)[\"name\"] as string]\n\t\t\t\t: []\n\t\t),\n\t);\n\tfor (const track of rawAuth.tracks) {\n\t\tif (!catalogTrackNames.has(track.mediaTrack)) {\n\t\t\tthrow new Error(`[multicast-auth-catalog] unknown mediaTrack \"${track.mediaTrack}\"`);\n\t\t}\n\t\tif (!catalogTrackNames.has(track.manifestTrack)) {\n\t\t\tthrow new Error(`[multicast-auth-catalog] unknown manifestTrack \"${track.manifestTrack}\"`);\n\t\t}\n\t}\n\n\treturn {\n\t\tkeyId: rawAuth.keyId,\n\t\tacceptedPublicKeys: [\n\t\t\tdecodeEd25519PublicKey(rawAuth.publicKey),\n\t\t\t...(rawAuth.previousKey === undefined ? [] : [decodeEd25519PublicKey(rawAuth.previousKey)]),\n\t\t],\n\t\tmode: resolveMulticastAuthMode(playerMode, rawAuth),\n\t\tcompaction: rawAuth.compaction,\n\t\ttracks: rawAuth.tracks.map((track) => ({\n\t\t\t...track,\n\t\t\tauthScope: decodeAuthScope(track.authScope),\n\t\t})),\n\t};\n}\n", "/**\n * CARP Catalog Types \u2014 FEC and Multicast catalog extensions.\n *\n * Per draft-law-ramadan-moq-carp-reliability \u00A73 (FEC) and \u00A74 (Multicast).\n * Plain TypeScript interfaces + type guards \u2014 no Zod dependency.\n *\n * These are the canonical type definitions. Upstream Zod schemas\n * should derive from these via z.infer<> to avoid duplication.\n */\n\nimport { resolveMulticastAuthCatalog, type MulticastAuthConfig } from \"./multicast-auth-catalog.js\";\n\n// \u2500\u2500 Track Role (Phase 14, D-02..D-05) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Track role derived from the last slash-segment of the track name.\n *\n * Convention: `{content}/base`, `{content}/delta`, `{content}/repair`.\n * Single-track (no slash) legacy streams use `\"single\"`.\n *\n * D-01: No `trackRole` / `role` / `kind` field in the catalog.\n * D-02: Role is expressed via track name suffix only.\n * D-03: Unknown suffixes throw at parse time (error on bad init).\n * D-04: Legacy single-track streams (no slash suffix) return `\"single\"`.\n * D-05: Single role per track \u2014 no multi-role arrays.\n */\nexport type TrackRole = \"base\" | \"delta\" | \"repair\" | \"single\";\n\nconst VALID_ROLE_SUFFIXES = new Set<string>([\"base\", \"delta\", \"repair\"]);\n\n/**\n * Derive the role of a track from its name.\n *\n * - Names with no `/` \u2192 `\"single\"` (legacy single-track streams, D-04).\n * - Names ending with `/base`, `/delta`, or `/repair` \u2192 that role (D-02).\n * - Empty name \u2192 throws (error on bad init).\n * - Trailing slash (empty last segment) \u2192 throws.\n * - Non-ASCII or control characters anywhere in the name \u2192 throws (T-14-01 fuzz hardening).\n * - Unknown last segment \u2192 throws.\n *\n * @throws {Error} On empty name, non-ASCII/control chars, empty suffix, or unknown suffix.\n */\nexport function parseTrackRole(trackName: string): TrackRole {\n\tif (trackName === \"\") {\n\t\tthrow new Error(\"[carp-catalog] empty track name\");\n\t}\n\n\t// T-14-01 fuzz hardening: reject non-ASCII and control characters.\n\t// This prevents catalog injection attacks where a publisher sends a crafted\n\t// track name that bypasses role checks by embedding unusual code points.\n\tfor (let i = 0; i < trackName.length; i++) {\n\t\tconst cp = trackName.charCodeAt(i);\n\t\t// Reject control characters (0x00-0x1F, 0x7F) and non-ASCII (>0x7E)\n\t\tif (cp <= 0x1f || cp === 0x7f || cp > 0x7e) {\n\t\t\tthrow new Error(\n\t\t\t\t`[carp-catalog] track name contains non-ASCII or control character (code point 0x${cp.toString(16)}) in \"${trackName}\"`,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst lastSlash = trackName.lastIndexOf(\"/\");\n\tif (lastSlash === -1) {\n\t\t// No slash \u2014 legacy single-track stream (D-04)\n\t\treturn \"single\";\n\t}\n\n\tconst suffix = trackName.slice(lastSlash + 1);\n\tif (suffix === \"\") {\n\t\tthrow new Error(\n\t\t\t`[carp-catalog] empty role suffix in track name \"${trackName}\"; track names must not end with \"/\"`,\n\t\t);\n\t}\n\n\tif (!VALID_ROLE_SUFFIXES.has(suffix)) {\n\t\tthrow new Error(\n\t\t\t`[carp-catalog] unknown role suffix \"${suffix}\" in track name \"${trackName}\"; expected one of: base, delta, repair`,\n\t\t);\n\t}\n\n\treturn suffix as TrackRole;\n}\n\n/**\n * Non-throwing switching-set detector (BLO-8158).\n *\n * Returns `true` iff at least one track name carries a media role suffix\n * (`base` or `delta`) \u2014 i.e. the set looks like a base/delta/repair switching\n * set. A `/repair` track alone is ordinary FEC topology and is not sufficient\n * evidence of a switching set. Unlike `parseTrackRole`, this NEVER throws:\n * names without a `/`, and names with an unrecognised suffix (e.g. an ABR\n * resolution ladder like `video/1080p`, `video/720p`, `video/8k`), simply do\n * not count as a role.\n *\n * Use this for DETECTION (\"is this a switching set?\"). Once a switching set is\n * confirmed, `parseTrackRole` / `validateSwitchingSet` still strictly gate the\n * actual wiring. ABR ladders yield `false` here and fall through to the\n * ABR/single path instead of throwing.\n */\nexport function hasSwitchingSetRole(names: string[]): boolean {\n\treturn names.some((name) => {\n\t\tconst lastSlash = name.lastIndexOf(\"/\");\n\t\tif (lastSlash === -1) return false;\n\t\tconst suffix = name.slice(lastSlash + 1);\n\t\treturn suffix === \"base\" || suffix === \"delta\";\n\t});\n}\n\n/**\n * Validate that a set of track names forms a complete switching set.\n *\n * - Empty or single-track sets (all parsing to `\"single\"`) \u2192 `{ ok: true }`.\n * - Multi-track sets (any name has a role suffix) MUST include all three\n * roles (`base`, `delta`, `repair`). Missing roles are listed.\n *\n * Propagates throws from `parseTrackRole` (non-ASCII, unknown suffix, etc.).\n *\n * D-04: Legacy single-track streams pass without enforcement.\n * D-04: Once any suffix appears, the set is multi-track and must be complete.\n */\nexport function validateSwitchingSet(\n\ttrackNames: string[],\n): { ok: true } | { ok: false; missing: TrackRole[] } {\n\tif (trackNames.length === 0) return { ok: true };\n\n\tconst roles = trackNames.map(parseTrackRole);\n\n\t// If every role is \"single\", this is a legacy single-track stream \u2014 pass.\n\tif (roles.every((r) => r === \"single\")) {\n\t\treturn { ok: true };\n\t}\n\n\t// Multi-track: at least one name has a role suffix.\n\t// The set MUST contain all three required roles.\n\t// Explicit Set<TrackRole> so the TrackRole-typed `required.filter`\n\t// callback can call .has(r) without a narrow-mismatch complaint.\n\tconst presentRoles: Set<TrackRole> = new Set(roles.filter((r) => r !== \"single\"));\n\tconst required: TrackRole[] = [\"base\", \"delta\", \"repair\"];\n\tconst missing = required.filter((r) => !presentRoles.has(r));\n\n\tif (missing.length > 0) {\n\t\treturn { ok: false, missing };\n\t}\n\treturn { ok: true };\n}\n\n// \u2500\u2500 FEC Catalog Extension (CARP \u00A73.2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type FecAlgorithm = \"none\" | \"raptorq\" | \"reed-solomon\";\n\nexport interface FecCatalogConfig {\n\t/** FEC algorithm identifier (REQUIRED per \u00A74.1, values per \u00A73.1). */\n\talgorithm: FecAlgorithm;\n\t/** K \u2014 source symbols per block (REQUIRED). */\n\tsourceSymbols: number;\n\t/** P \u2014 repair symbols per block (REQUIRED). */\n\trepairSymbols: number;\n\t/** T \u2014 bytes per symbol, 8-byte aligned (REQUIRED). */\n\tsymbolSize: number;\n\t/** FEC block span in MILLISECONDS (OPTIONAL, default 0 = single-group blocks).\n\t * D is the positive round-half-up value of interleaveDepthMs / GOP_duration_ms.\n\t * BLO-14526: renamed from the legacy `interleaveDepth` count-era key \u2014 no fallback read. */\n\tinterleaveDepthMs?: number;\n\t/** Declared jitter/reorder allowance in MILLISECONDS.\n\t * Added to interleaveDepthMs to form a block's deadline; never multiplied\n\t * by it. Jitter is a property of the network path and the block span is a\n\t * property of the encoder, so a multiplicative \"safety factor\" couples two\n\t * independent quantities and grants different slack per track for the same\n\t * network. Consumed identically by FECManager, FEC workers and player\n\t * policies so one signaled value governs end to end. */\n\treorderToleranceMs?: number;\n\t/** Track name for repair symbols (REQUIRED per \u00A76.1). */\n\trepairTrack: string;\n\t/** FEC block mode: \"interleaved\" (default) or \"object\" (per-frame). */\n\t// extensions feature \u2014 see moqcast-draft docs/fec-extensions-material.md, not in public -00\n\tmode?: \"interleaved\" | \"object\";\n\t/** UEP (Unequal Error Protection) \u2014 extensions feature, see moqcast-draft docs/fec-extensions-material.md, not in public -00. When present, repair count\n\t * varies per frame type. repairSymbols becomes the base (P-frame) count.\n\t * MUST be omitted on multi-track base/delta streams (D-08). */\n\tuep?: {\n\t\t/** Keyframe repair ratio: P = ceil(K * keyRatio). Default 0.5. */\n\t\tkeyRatio: number;\n\t\t/** Delta frame repair ratio: P = ceil(K * deltaRatio). Default 0.25. */\n\t\tdeltaRatio: number;\n\t};\n\t/**\n\t * Base-only fallback window in FEC blocks (D-11, Phase 14).\n\t *\n\t * When the delta track's FEC block failure rate exceeds the derived threshold\n\t * over this many consecutive blocks, MediaRouter falls back to base-only mode.\n\t * Derivation: framerate * fallback_window_seconds. If absent, construction\n\t * of the multi-track subscriber MUST throw (error on bad init).\n\t *\n\t * Present only on the base track's fec config (not the delta or repair track).\n\t */\n\tdeltaFailWindowBlocks?: number;\n\t/**\n\t * Delta re-subscribe probe interval in milliseconds (D-13, Phase 14).\n\t *\n\t * After a base-only fallback, wait this long before re-subscribing to the\n\t * delta track to check if conditions have improved.\n\t * Derivation: computeFecDeliveryWindowMs(...) \u2014 the single FEC recovery-window\n\t * source of truth (draft-ramadan-moq-fec \u00A79). Never a fixed interleave multiple.\n\t *\n\t * Present only on the base track's fec config (not the delta or repair track).\n\t */\n\tdeltaProbeIntervalMs?: number;\n\t/**\n\t * Jitter + one-way-delay + reorder budget in MILLISECONDS (draft \u00A79).\n\t *\n\t * The single catalog source for the ADDITIVE margin that the FEC\n\t * recovery/loss window adds on top of max(interleave span, source+repair horizon,\n\t * block serialization) \u2014 see computeFecDeliveryWindowMs. It is a margin, not\n\t * a multiplier. OPTIONAL: when absent, the derivation falls back to the\n\t * un-rounded interleave window as the reorder-budget bound (margin-policy).\n\t */\n\tjitterBufferMs?: number;\n}\n\nexport function isFecCatalogConfig(obj: unknown): obj is FecCatalogConfig {\n\tif (typeof obj !== \"object\" || obj === null) return false;\n\tconst o = obj as Record<string, unknown>;\n\tconst algorithm = o[\"algorithm\"];\n\tconst symbolSize = o[\"symbolSize\"];\n\treturn (\n\t\ttypeof algorithm === \"string\" &&\n\t\t(algorithm === \"none\" || algorithm === \"raptorq\" || algorithm === \"reed-solomon\") &&\n\t\ttypeof o[\"sourceSymbols\"] === \"number\" && o[\"sourceSymbols\"] >= 1 &&\n\t\ttypeof o[\"repairSymbols\"] === \"number\" && o[\"repairSymbols\"] >= 1 &&\n\t\ttypeof symbolSize === \"number\" && symbolSize >= 1 &&\n\t\t(algorithm !== \"raptorq\" || symbolSize % 8 === 0) &&\n\t\ttypeof o[\"repairTrack\"] === \"string\" && (o[\"repairTrack\"] as string).length > 0\n\t);\n}\n\n// \u2500\u2500 Multicast Catalog Extension (CARP \u00A74.1-4.4) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type MulticastProtocol = \"ssm\" | \"asm\" | \"amt\" | \"atsc3\";\n\n/**\n * Per-track endpoint membership, per draft-ramadan-moq-multicast-00 \u00A74.1.\n *\n * `packetId` is the MMTP packet_id used for packet-level demux on the\n * multicast wire. New emitters MUST use this object form; the legacy\n * `string` form is accepted by parsers for one release for backward\n * compatibility (BLO-3323 migration).\n */\nexport interface MulticastTrackObject {\n\tname: string;\n\tpacketId: number;\n}\n\n/** Track entry in a multicast endpoint \u2014 accepts both legacy and v2 shape. */\nexport type MulticastTrack = string | MulticastTrackObject;\n\nexport interface MulticastEndpoint {\n\t/** Transport protocol. Defaults to SSM when sourceAddress is present. */\n\tprotocol?: MulticastProtocol;\n\t/** SSM source IP address (REQUIRED for SSM). */\n\tsourceAddress?: string;\n\t/** Multicast group address (REQUIRED). */\n\tgroupAddress: string;\n\t/** UDP port number (REQUIRED). */\n\tport: number;\n\t/**\n\t * Tracks available on this endpoint (REQUIRED).\n\t *\n\t * Accepts both legacy `string` (track name only) and v2 object form\n\t * (`{ name, packetId }`) for backward compatibility. New emitters\n\t * MUST use the object form (BLO-3323 / draft \u00A74.1). Consumers can\n\t * type-narrow with `typeof t === \"string\"` to handle both.\n\t */\n\ttracks: MulticastTrack[];\n\t/** AMT relay hostname (REQUIRED for AMT). */\n\trelayAddress?: string;\n\t/**\n\t * Aggregate bandwidth of this endpoint in bits per second.\n\t * RECOMMENDED per draft \u00A74.1 \u2014 enables capacity-aware joins.\n\t */\n\tbandwidth?: number;\n}\n\nexport type AmtDiscovery = \"driad\" | \"manual\";\n\nexport interface MulticastCatalogConfig {\n\t/** Enable/disable multicast (OPTIONAL, default true). */\n\tenabled?: boolean;\n\t/** Multicast endpoints (REQUIRED). */\n\tendpoints: MulticastEndpoint[];\n\t/** AMT fallback configuration (OPTIONAL). */\n\tamtFallback?: {\n\t\tdiscovery: AmtDiscovery;\n\t\trelayDns?: string;\n\t};\n\t/**\n\t * Monotonic catalog version. Publishers MUST bump on any\n\t * `endpoints[]` mutation (BLO-3323 catalog freshness model).\n\t */\n\tversion?: number;\n\t/**\n\t * Unix-ms timestamp after which subscribers SHOULD refetch the\n\t * catalog. Refetch-on-multicast-receive-timeout short-circuits this.\n\t */\n\tvalidUntil?: number;\n}\n\nexport function isMulticastTrackObject(obj: unknown): obj is MulticastTrackObject {\n\tif (typeof obj !== \"object\" || obj === null) return false;\n\tconst o = obj as Record<string, unknown>;\n\treturn typeof o[\"name\"] === \"string\" && typeof o[\"packetId\"] === \"number\";\n}\n\n/**\n * Wire-shape predicate: returns `true` when `obj` matches the\n * MulticastEndpoint JSON shape strictly enough to be safely cast.\n *\n * Intentionally less strict than `multicastFromConfig`'s\n * `validateEndpoint` (in `multicast-input.ts`):\n *\n * - `tracks: []` is accepted here (Array.isArray check only) but\n * rejected by `validateEndpoint` as `empty_tracks`.\n * - SSM-specific group-range and source-required checks are not\n * enforced here.\n * - Bandwidth/AmtFallback/version are not type-checked.\n *\n * That asymmetry is deliberate: this predicate guards JSON parsed off\n * the wire (already-published catalogs that downstream may have\n * trimmed), while `validateEndpoint` guards publisher input *before*\n * a catalog is composed. Subscribers are tolerant; publishers are\n * strict \u2014 the catalog format never re-validates upstream invariants.\n */\nexport function isMulticastEndpoint(obj: unknown): obj is MulticastEndpoint {\n\tif (typeof obj !== \"object\" || obj === null) return false;\n\tconst o = obj as Record<string, unknown>;\n\tconst protocol = o[\"protocol\"] ??\n\t\t(typeof o[\"sourceAddress\"] === \"string\" && o[\"sourceAddress\"].length > 0 ? \"ssm\" : undefined);\n\treturn (\n\t\ttypeof protocol === \"string\" &&\n\t\t(protocol === \"ssm\" || protocol === \"asm\" || protocol === \"amt\" || protocol === \"atsc3\") &&\n\t\ttypeof o[\"groupAddress\"] === \"string\" && (o[\"groupAddress\"] as string).length > 0 &&\n\t\ttypeof o[\"port\"] === \"number\" && (o[\"port\"] as number) > 0 && (o[\"port\"] as number) <= 65535 &&\n\t\tArray.isArray(o[\"tracks\"]) &&\n\t\t(o[\"tracks\"] as unknown[]).every((t: unknown) => typeof t === \"string\" || isMulticastTrackObject(t))\n\t);\n}\n\nexport function isMulticastCatalogConfig(obj: unknown): obj is MulticastCatalogConfig {\n\tif (typeof obj !== \"object\" || obj === null) return false;\n\tconst o = obj as Record<string, unknown>;\n\treturn (\n\t\tArray.isArray(o[\"endpoints\"]) &&\n\t\t(o[\"endpoints\"] as unknown[]).every((ep: unknown) => isMulticastEndpoint(ep))\n\t);\n}\n\n// \u2500\u2500 Track Timing (mmt-00 \u00A74.4.4) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Per-track group-duration signaling.\n *\n * The catalog publishes either `groupDurationMs` (integer ms) or the exact\n * `groupDurationTicks` value used by `groupIdForTicks` in align.ts. The tick\n * form is required for cases where milliseconds cannot represent the cadence\n * exactly:\n *\n * - Per-frame group durations at non-integer-ms cadences\n * (1/30 s = 33.333\u2026 ms; 1/60 s = 16.666\u2026 ms).\n * - Audio sample-rate timescales not divisible by 1000 Hz\n * (e.g. 44 100 Hz \u00D7 333 ms = 14 685.3 ticks).\n *\n * If both fields are present, `groupDurationTicks` wins (matches the\n * spec, mmt-00 \u00A74.4.4).\n *\n * @see draft-ramadan-moq-mmt-00 \u00A74.4.4\n * @see ./align.ts groupIdForTicks\n */\nexport interface TrackTimingConfig {\n\t/** Group duration in milliseconds (positive integer). Required unless an\n\t * exact groupDurationTicks value is supplied. */\n\tgroupDurationMs?: number;\n\t/** Integer-tick override (OPTIONAL, positive integer). Wins over the\n\t * ms field when both are present. Required when\n\t * `(groupDurationMs * timescale) % 1000 != 0`. */\n\tgroupDurationTicks?: number;\n}\n\nexport function isTrackTimingConfig(obj: unknown): obj is TrackTimingConfig {\n\tif (typeof obj !== \"object\" || obj === null) return false;\n\tconst o = obj as Record<string, unknown>;\n\tconst ms = o[\"groupDurationMs\"];\n\tconst ticks = o[\"groupDurationTicks\"];\n\tif (ms === undefined && ticks === undefined) return false;\n\tif (ms !== undefined && (typeof ms !== \"number\" || !Number.isInteger(ms) || ms <= 0)) return false;\n\tif (\"groupDurationTicks\" in o) {\n\t\tif (ticks === undefined) return ms !== undefined;\n\t\tif (typeof ticks !== \"number\" || !Number.isInteger(ticks) || ticks <= 0) return false;\n\t}\n\treturn true;\n}\n\n/** Resolve catalog group timing to an operational wall-clock duration.\n *\n * `groupDurationTicks` wins when both wire fields are present, matching\n * mmt-00 \u00A74.4.4. The result may be fractional because exact frame cadences\n * such as 33_333 ticks at 1 MHz cannot be represented by the wire catalog's\n * integer `groupDurationMs` field.\n */\nexport function resolveGroupDurationMs(\n\ttiming: TrackTimingConfig,\n\ttimescale: number,\n): number {\n\tif (!Number.isSafeInteger(timescale) || timescale <= 0) {\n\t\tthrow new Error(\n\t\t\t`[carp-catalog] resolveGroupDurationMs: timescale must be a positive safe integer Hz, got ${timescale}`,\n\t\t);\n\t}\n\tif (!isTrackTimingConfig(timing)) {\n\t\tthrow new Error(\n\t\t\t`[carp-catalog] resolveGroupDurationMs: invalid TrackTimingConfig: ${JSON.stringify(timing)}`,\n\t\t);\n\t}\n\tif (timing.groupDurationTicks === undefined) {\n\t\treturn timing.groupDurationMs!;\n\t}\n\n\tconst durationMs = (timing.groupDurationTicks / timescale) * 1000;\n\tif (!Number.isFinite(durationMs) || durationMs <= 0 || durationMs > Number.MAX_SAFE_INTEGER) {\n\t\tthrow new Error(\n\t\t\t`[carp-catalog] resolveGroupDurationMs: groupDurationTicks=${timing.groupDurationTicks} ` +\n\t\t\t\t`at timescale=${timescale} cannot be represented as a positive safe millisecond duration`,\n\t\t);\n\t}\n\treturn durationMs;\n}\n\nexport type CmsfCatalog = {\n\tversion: number;\n\ttracks: Record<string, unknown>[];\n\tcommonTrackFields?: Record<string, unknown>;\n\tmulticast?: Record<string, unknown>;\n\t\"multicast.auth\"?: MulticastAuthConfig;\n\t[key: string]: unknown;\n};\n\nexport type CmsfCatalogErrorCode =\n\t| \"catalog_object\"\n\t| \"catalog_version\"\n\t| \"catalog_tracks\"\n\t| \"track_object\"\n\t| \"track_name\"\n\t| \"track_packaging\"\n\t| \"track_is_live\"\n\t| \"track_codec\"\n\t| \"track_mmtp_mode\"\n\t| \"track_timescale\"\n\t| \"track_group_duration_ms\"\n\t| \"track_group_duration_ticks\"\n\t| \"track_group_duration_exact\"\n\t| \"track_keyframe_interval\"\n\t| \"track_fec\"\n\t| \"track_repair_track\"\n\t| \"track_switching_set\"\n\t| \"multicast_auth\"\n\t| \"multicast_track\"\n\t| \"multicast_packet_id\";\n\nexport class CmsfCatalogValidationError extends Error {\n\tconstructor(\n\t\tpublic readonly code: CmsfCatalogErrorCode,\n\t\tpublic readonly path: string,\n\t\tmessage: string,\n\t) {\n\t\tsuper(`[cmsf:${code}] ${path}: ${message}`);\n\t\tthis.name = \"CmsfCatalogValidationError\";\n\t}\n}\n\nfunction catalogError(code: CmsfCatalogErrorCode, path: string, message: string): never {\n\tthrow new CmsfCatalogValidationError(code, path, message);\n}\n\n/** Validate the common CMSF shape and the MMTP required-field profile. */\nexport function validateCmsfMmtpCatalog(value: unknown): CmsfCatalog {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tcatalogError(\"catalog_object\", \"$\", \"catalog must be an object\");\n\t}\n\tconst catalog = value as Record<string, unknown>;\n\t// IETF-draft catalogs (cast `ladder_catalog.rs`, moq-server\n\t// `catalog-synthesizer.ts`, consumed by the hang player) carry a string\n\t// version tag such as \"draft-ietf-moq-catalogformat-01\" instead of the CMSF\n\t// `version: 1` integer. Nothing keys behavior off the catalog version, so\n\t// normalize the tag to a number rather than rejecting the whole catalog \u2014\n\t// mirrors the relay (dual-stack-relay `bridge/catalog.rs`\n\t// `deserialize_optional_u32_lenient`, #825) and moqtail-ts\n\t// `normalizeCatalogVersion`.\n\tconst rawVersion = catalog[\"version\"];\n\tconst normalizedVersion =\n\t\ttypeof rawVersion === \"string\"\n\t\t\t? Number.isFinite(Number(rawVersion))\n\t\t\t\t? Number(rawVersion)\n\t\t\t\t: rawVersion.startsWith(\"draft-ietf-moq-catalogformat\")\n\t\t\t\t\t? 1\n\t\t\t\t\t: NaN\n\t\t\t: rawVersion;\n\tif (!Number.isInteger(normalizedVersion) || (normalizedVersion as number) <= 0) {\n\t\tcatalogError(\"catalog_version\", \"$.version\", \"version must be a positive integer or a recognized format tag\");\n\t}\n\tcatalog[\"version\"] = normalizedVersion;\n\tif (!Array.isArray(catalog[\"tracks\"])) {\n\t\tcatalogError(\"catalog_tracks\", \"$.tracks\", \"tracks must be an array\");\n\t}\n\n\tconst common = typeof catalog[\"commonTrackFields\"] === \"object\" &&\n\t\tcatalog[\"commonTrackFields\"] !== null && !Array.isArray(catalog[\"commonTrackFields\"])\n\t\t? catalog[\"commonTrackFields\"] as Record<string, unknown>\n\t\t: {};\n\tconst tracks = catalog[\"tracks\"] as unknown[];\n\tconst trackRecords: Record<string, unknown>[] = [];\n\tconst effective = (track: Record<string, unknown>, field: string): unknown => track[field] ?? common[field];\n\tconst positiveInteger = (input: unknown): input is number => Number.isSafeInteger(input) && (input as number) > 0;\n\tconst positiveNumber = (input: unknown): input is number =>\n\t\ttypeof input === \"number\" && Number.isFinite(input) && input > 0;\n\n\tfor (let index = 0; index < tracks.length; index++) {\n\t\tconst raw = tracks[index];\n\t\tconst path = `$.tracks[${index}]`;\n\t\tif (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n\t\t\tcatalogError(\"track_object\", path, \"track must be an object\");\n\t\t}\n\t\tconst track = raw as Record<string, unknown>;\n\t\tconst name = track[\"name\"];\n\t\tif (typeof name !== \"string\" || name.length === 0) {\n\t\t\tcatalogError(\"track_name\", `${path}.name`, \"name must be a non-empty string\");\n\t\t}\n\t\ttrackRecords.push(track);\n\n\t\tconst packaging = effective(track, \"packaging\");\n\t\tif (typeof packaging !== \"string\" || packaging.length === 0) {\n\t\t\tcatalogError(\"track_packaging\", `${path}.packaging`, \"packaging must be a non-empty string\");\n\t\t}\n\t\tconst trackHasIsLive = Object.prototype.hasOwnProperty.call(track, \"isLive\");\n\t\tconst hasIsLive = trackHasIsLive || Object.prototype.hasOwnProperty.call(common, \"isLive\");\n\t\tconst isLive = trackHasIsLive ? track[\"isLive\"] : common[\"isLive\"];\n\t\tif (hasIsLive && typeof isLive !== \"boolean\") {\n\t\t\tcatalogError(\"track_is_live\", `${path}.isLive`, \"isLive must be a boolean\");\n\t\t}\n\t\ttrack[\"isLive\"] = isLive ?? true;\n\t\tconst selectionValue = effective(track, \"selectionParams\");\n\t\tconst selection = typeof selectionValue === \"object\" && selectionValue !== null && !Array.isArray(selectionValue)\n\t\t\t? selectionValue as Record<string, unknown>\n\t\t\t: undefined;\n\t\tconst codec = selection?.[\"codec\"] ?? effective(track, \"codec\");\n\t\tif (packaging !== \"timeline\" && packaging !== \"mediatimeline\" && packaging !== \"eventtimeline\" && packaging !== \"fec-repair\" &&\n\t\t\t(typeof codec !== \"string\" || codec.length === 0)) {\n\t\t\tcatalogError(\"track_codec\", `${path}.codec`, `codec is required for packaging=${packaging}`);\n\t\t}\n\n\t\tconst timescale = effective(track, \"timescale\");\n\t\tconst groupDurationMs = effective(track, \"groupDurationMs\");\n\t\tconst groupDurationTicks = effective(track, \"groupDurationTicks\");\n\t\tconst keyframeIntervalMs = effective(track, \"keyframeIntervalMs\");\n\t\tconst keyframeIntervalTicks = effective(track, \"keyframeIntervalTicks\");\n\t\tif (groupDurationMs !== undefined && !positiveInteger(groupDurationMs)) {\n\t\t\tcatalogError(\"track_group_duration_ms\", `${path}.groupDurationMs`, \"must be a positive integer\");\n\t\t}\n\t\tif (groupDurationTicks !== undefined && !positiveInteger(groupDurationTicks)) {\n\t\t\tcatalogError(\"track_group_duration_ticks\", `${path}.groupDurationTicks`, \"must be a positive integer\");\n\t\t}\n\t\tif ((keyframeIntervalMs !== undefined && !positiveNumber(keyframeIntervalMs)) ||\n\t\t\t(keyframeIntervalTicks !== undefined && !positiveInteger(keyframeIntervalTicks))) {\n\t\t\tcatalogError(\"track_keyframe_interval\", path, \"keyframe interval fields must be positive numbers\");\n\t\t}\n\t\tif (packaging === \"mmtp\") {\n\t\t\tconst mmtpMode = effective(track, \"mmtpMode\");\n\t\t\tif (mmtpMode !== \"mpu\" && mmtpMode !== \"mfu\") {\n\t\t\t\tcatalogError(\"track_mmtp_mode\", `${path}.mmtpMode`, \"must be mpu or mfu\");\n\t\t\t}\n\t\t\tif (!positiveInteger(timescale)) {\n\t\t\t\tcatalogError(\"track_timescale\", `${path}.timescale`, \"must be a positive integer\");\n\t\t\t}\n\t\t\tif (groupDurationMs === undefined && groupDurationTicks === undefined) {\n\t\t\t\tcatalogError(\n\t\t\t\t\t\"track_group_duration_ms\",\n\t\t\t\t\tpath,\n\t\t\t\t\t\"groupDurationMs or groupDurationTicks must be a positive integer\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (groupDurationTicks === undefined &&\n\t\t\t\t(BigInt(groupDurationMs as number) * BigInt(timescale)) % 1000n !== 0n) {\n\t\t\t\tcatalogError(\"track_group_duration_exact\", `${path}.groupDurationMs`, \"does not resolve to an exact integer tick count\");\n\t\t\t}\n\t\t}\n\n\t\tif (track[\"fec\"] !== undefined) {\n\t\t\tconst fec = track[\"fec\"];\n\t\t\tif (typeof fec !== \"object\" || fec === null || Array.isArray(fec)) {\n\t\t\t\tcatalogError(\"track_fec\", `${path}.fec`, \"FEC must be an object\");\n\t\t\t}\n\t\t\tconst config = fec as Record<string, unknown>;\n\t\t\tconst algorithm = config[\"algorithm\"];\n\t\t\tif (algorithm !== \"none\" && algorithm !== \"raptorq\" && algorithm !== \"reed-solomon\") {\n\t\t\t\tcatalogError(\"track_fec\", `${path}.fec.algorithm`, \"algorithm is not supported\");\n\t\t\t}\n\t\t\tif (\"interleaveDepth\" in config || \"interleaveMs\" in config) {\n\t\t\t\tcatalogError(\"track_fec\", `${path}.fec`, \"interleaveDepthMs is the only supported interleave field\");\n\t\t\t}\n\t\t\tif (config[\"interleaveDepthMs\"] !== undefined && !positiveInteger(config[\"interleaveDepthMs\"])) {\n\t\t\t\tcatalogError(\"track_fec\", `${path}.fec.interleaveDepthMs`, \"must be a positive integer\");\n\t\t\t}\n\t\t\tif (algorithm !== \"none\") {\n\t\t\t\tfor (const field of [\"sourceSymbols\", \"repairSymbols\", \"symbolSize\"] as const) {\n\t\t\t\t\tif (!positiveInteger(config[field])) {\n\t\t\t\t\t\tcatalogError(\"track_fec\", `${path}.fec.${field}`, \"must be a positive integer\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (typeof config[\"repairTrack\"] !== \"string\" || config[\"repairTrack\"].length === 0) {\n\t\t\t\t\tcatalogError(\"track_fec\", `${path}.fec.repairTrack`, \"must be a non-empty string\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (let index = 0; index < trackRecords.length; index++) {\n\t\tconst track = trackRecords[index]!;\n\t\tconst fec = track[\"fec\"] as Record<string, unknown> | undefined;\n\t\tif (!fec || fec[\"algorithm\"] === \"none\") continue;\n\t\tconst repairTrack = fec[\"repairTrack\"] as string;\n\t\tconst target = trackRecords.find((candidate) => candidate[\"name\"] === repairTrack);\n\t\tif (!target || effective(target, \"packaging\") !== \"fec-repair\") {\n\t\t\tcatalogError(\"track_repair_track\", `$.tracks[${index}].fec.repairTrack`, `unknown FEC repair track ${JSON.stringify(repairTrack)}`);\n\t\t}\n\t}\n\n\tconst switchingSets = new Map<number, { name: string; ticks: bigint; timescale: bigint }>();\n\tfor (let index = 0; index < trackRecords.length; index++) {\n\t\tconst track = trackRecords[index]!;\n\t\tif (effective(track, \"packaging\") !== \"mmtp\") continue;\n\t\tconst altGroup = effective(track, \"altGroup\");\n\t\tif (!Number.isSafeInteger(altGroup)) continue;\n\t\tconst timescale = BigInt(effective(track, \"timescale\") as number);\n\t\tconst durationTicks = effective(track, \"groupDurationTicks\");\n\t\tconst ticks = durationTicks !== undefined\n\t\t\t? BigInt(durationTicks as number)\n\t\t\t: BigInt(effective(track, \"groupDurationMs\") as number) * timescale / 1000n;\n\t\tconst anchor = switchingSets.get(altGroup as number);\n\t\tif (anchor && ticks * anchor.timescale !== anchor.ticks * timescale) {\n\t\t\tcatalogError(\"track_switching_set\", `$.tracks[${index}]`, `group duration does not match ${JSON.stringify(anchor.name)} in altGroup ${altGroup}`);\n\t\t}\n\t\tif (!anchor) switchingSets.set(altGroup as number, { name: track[\"name\"] as string, ticks, timescale });\n\t}\n\n\tconst multicast = catalog[\"multicast\"];\n\tif (typeof multicast === \"object\" && multicast !== null && !Array.isArray(multicast)) {\n\t\tconst endpoints = (multicast as Record<string, unknown>)[\"endpoints\"];\n\t\tif (Array.isArray(endpoints)) {\n\t\t\tfor (let endpointIndex = 0; endpointIndex < endpoints.length; endpointIndex++) {\n\t\t\t\tconst endpoint = endpoints[endpointIndex];\n\t\t\t\tif (typeof endpoint !== \"object\" || endpoint === null || Array.isArray(endpoint)) continue;\n\t\t\t\tconst refs = (endpoint as Record<string, unknown>)[\"tracks\"];\n\t\t\t\tif (!Array.isArray(refs)) continue;\n\t\t\t\tconst packetIds = new Map<number, string>();\n\t\t\t\tfor (let refIndex = 0; refIndex < refs.length; refIndex++) {\n\t\t\t\t\tconst ref = refs[refIndex];\n\t\t\t\t\tif (typeof ref !== \"object\" || ref === null || Array.isArray(ref)) continue;\n\t\t\t\t\tconst trackRef = ref as Record<string, unknown>;\n\t\t\t\t\tconst refPath = `$.multicast.endpoints[${endpointIndex}].tracks[${refIndex}]`;\n\t\t\t\t\tconst name = trackRef[\"name\"];\n\t\t\t\t\tif (typeof name !== \"string\" || !trackRecords.some((track) => track[\"name\"] === name)) {\n\t\t\t\t\t\tcatalogError(\"multicast_track\", `${refPath}.name`, `unknown catalog track ${JSON.stringify(name)}`);\n\t\t\t\t\t}\n\t\t\t\t\tconst packetId = trackRef[\"packetId\"];\n\t\t\t\t\tif (!Number.isSafeInteger(packetId) || (packetId as number) < 0 || (packetId as number) > 65535) {\n\t\t\t\t\t\tcatalogError(\"multicast_packet_id\", `${refPath}.packetId`, \"packetId must be an integer from 0 to 65535\");\n\t\t\t\t\t}\n\t\t\t\t\tconst previous = packetIds.get(packetId as number);\n\t\t\t\t\tif (previous !== undefined) {\n\t\t\t\t\t\tcatalogError(\"multicast_packet_id\", `${refPath}.packetId`, `packetId is already assigned to ${JSON.stringify(previous)}`);\n\t\t\t\t\t}\n\t\t\t\t\tpacketIds.set(packetId as number, name as string);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\ttry {\n\t\tresolveMulticastAuthCatalog(catalog);\n\t} catch (error) {\n\t\tcatalogError(\n\t\t\t\"multicast_auth\",\n\t\t\t\"$.multicast.auth\",\n\t\t\terror instanceof Error ? error.message : \"invalid multicast.auth v2 block\",\n\t\t);\n\t}\n\n\treturn catalog as CmsfCatalog;\n}\n\n/**\n * Resolve a track's group duration to integer ticks using the supplied\n * timescale (Hz). Implements mmt-00 \u00A74.4.4:\n *\n * - If `groupDurationTicks` is present, return it (override wins).\n * - Else compute `groupDurationMs * timescale / 1000`. The result MUST\n * be an exact integer; throws if `(ms * timescale) % 1000 != 0`.\n *\n * Throws on invalid timing config or non-positive timescale (CLAUDE.md:\n * error on bad init).\n */\nexport function resolveGroupDurationTicks(\n\ttiming: TrackTimingConfig,\n\ttimescale: number,\n): number {\n\tif (!Number.isFinite(timescale) || !Number.isInteger(timescale) || timescale <= 0) {\n\t\tthrow new Error(\n\t\t\t`[carp-catalog] resolveGroupDurationTicks: timescale must be a positive integer Hz, got ${timescale}`,\n\t\t);\n\t}\n\tif (!isTrackTimingConfig(timing)) {\n\t\tthrow new Error(\n\t\t\t`[carp-catalog] resolveGroupDurationTicks: invalid TrackTimingConfig: ${JSON.stringify(timing)}`,\n\t\t);\n\t}\n\tif (timing.groupDurationTicks !== undefined) {\n\t\treturn timing.groupDurationTicks;\n\t}\n\tif (timing.groupDurationMs === undefined) {\n\t\tthrow new Error(\n\t\t\t\"[carp-catalog] resolveGroupDurationTicks: groupDurationMs is required when groupDurationTicks is absent\",\n\t\t);\n\t}\n\tconst product = timing.groupDurationMs * timescale;\n\tif (product % 1000 !== 0) {\n\t\tthrow new Error(\n\t\t\t`[carp-catalog] resolveGroupDurationTicks: groupDurationMs=${timing.groupDurationMs} at timescale=${timescale} ` +\n\t\t\t\t`produces non-integer ticks (${product / 1000}); publisher must use groupDurationTicks override (mmt-00 \u00A74.4.4)`,\n\t\t);\n\t}\n\treturn product / 1000;\n}\n\n/**\n * Validate that every track in a switching set agrees on the same\n * wall-clock group duration (mmt-00 \u00A74.4.4). Per-track timescales may\n * differ, so raw tick counts cannot be compared directly.\n *\n * Returns `{ ok: true }` when all tracks agree (or the set is empty);\n * `{ ok: false, mismatches }` listing each track whose effective ticks\n * differ from the first track's value. Subscribers per spec SHOULD\n * reject the catalog on mismatch.\n *\n * Throws if any track's timing config is invalid (per\n * `resolveGroupDurationTicks`).\n */\nexport function validateSwitchingSetTiming(\n\ttracks: Array<{ name: string; timing: TrackTimingConfig; timescale: number }>,\n):\n\t| { ok: true }\n\t| { ok: false; expectedTicks: number; mismatches: Array<{ name: string; ticks: number }> } {\n\tif (tracks.length === 0) return { ok: true };\n\tconst ticksByTrack = tracks.map((t) => ({\n\t\tname: t.name,\n\t\tticks: resolveGroupDurationTicks(t.timing, t.timescale),\n\t\ttimescale: t.timescale,\n\t}));\n\tconst expectedTicks = ticksByTrack[0].ticks;\n\tconst expectedTimescale = ticksByTrack[0].timescale;\n\tconst mismatches = ticksByTrack\n\t\t.slice(1)\n\t\t.filter(\n\t\t\t(t) =>\n\t\t\t\tBigInt(t.ticks) * BigInt(expectedTimescale) !==\n\t\t\t\tBigInt(expectedTicks) * BigInt(t.timescale),\n\t\t)\n\t\t.map(({ name, ticks }) => ({ name, ticks }));\n\tif (mismatches.length === 0) return { ok: true };\n\treturn { ok: false, expectedTicks, mismatches };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,82 @@
1
+ import { catalogFecInterleaveMs, type FecInterleaveCatalog } from "@blockcast/mmt-fec";
2
+ export { catalogFecInterleaveMs, type FecInterleaveCatalog };
3
+ /**
4
+ * Minimal structural shape of a resolved endpoint track. Callers may carry
5
+ * extra fields (e.g. hang's ResolvedEndpointTrack adds `pid`) — the resolver
6
+ * only reads `name` and `type`.
7
+ */
8
+ export type CatalogTrackRef = {
9
+ name: string;
10
+ type: "video" | "audio" | (string & {});
11
+ };
12
+ type FecCatalog = FecInterleaveCatalog & {
13
+ sourceSymbols?: number;
14
+ repairSymbols?: number;
15
+ symbolSize?: number;
16
+ /** Signaled jitter/reorder allowance in ms (added to the block span). */
17
+ reorderToleranceMs?: number;
18
+ repairTrack?: string;
19
+ };
20
+ type RenditionCatalog = KeyframeCadenceCatalog & {
21
+ fec?: FecCatalog;
22
+ framerate?: unknown;
23
+ sampleRate?: unknown;
24
+ samplerate?: unknown;
25
+ };
26
+ type CatalogWithRenditions = {
27
+ video?: {
28
+ renditions?: Record<string, RenditionCatalog>;
29
+ };
30
+ audio?: {
31
+ renditions?: Record<string, RenditionCatalog>;
32
+ };
33
+ };
34
+ export type GroupDurationCatalog = {
35
+ groupDurationTicks?: number;
36
+ groupDurationMs?: number;
37
+ timescale?: number;
38
+ };
39
+ export type KeyframeCadenceCatalog = GroupDurationCatalog & {
40
+ keyframeDurationTicks?: number;
41
+ keyframeDurationMs?: number;
42
+ keyframeIntervalTicks?: number;
43
+ keyframeIntervalMs?: number;
44
+ gopDurationTicks?: number;
45
+ gopDurationMs?: number;
46
+ };
47
+ export type TrackFecParams = {
48
+ fecK: number;
49
+ fecRepairCount: number;
50
+ fecSymbolSize: number;
51
+ fecInterleaveMs: number;
52
+ /** Catalog fec.reorderToleranceMs — signaled jitter/reorder allowance, ADDED
53
+ * to the block span to form a deadline. Deliberately `number | undefined`
54
+ * and NOT floored to 0: a declared 0 ("this path needs no slack") and an
55
+ * absent value ("the encoder never said") must stay distinguishable, or a
56
+ * consumer that wants to fail loud on absence silently reads a default
57
+ * instead — which is exactly how the magic 3.0 survived. */
58
+ fecReorderToleranceMs?: number;
59
+ repairTrackName?: string;
60
+ fps?: number;
61
+ sampleRate?: number;
62
+ };
63
+ /**
64
+ * Resolves per-track FEC geometry from the catalog for the active endpoint tracks.
65
+ *
66
+ * Invariant: expects at most one video track and one audio track. `forTrack`
67
+ * dispatches purely on `track.type`, so a second video track (e.g. a simulcast
68
+ * variant) would silently receive the first video rendition's geometry. Revisit
69
+ * the `track.type` dispatch before relaxing that one-per-type assumption.
70
+ */
71
+ export declare function resolveCatalogTrackFec(catalog: CatalogWithRenditions | undefined, tracks: readonly CatalogTrackRef[]): {
72
+ videoTrackName?: string;
73
+ audioTrackName?: string;
74
+ missingVideoRendition?: string;
75
+ missingAudioRendition?: string;
76
+ videoForKeyframeRepair?: KeyframeCadenceCatalog;
77
+ catalogFps?: number;
78
+ video: TrackFecParams;
79
+ audio: TrackFecParams;
80
+ forTrack(track: CatalogTrackRef): TrackFecParams;
81
+ };
82
+ //# sourceMappingURL=catalog-fec-params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-fec-params.d.ts","sourceRoot":"","sources":["../src/catalog-fec-params.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,sBAAsB,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAEvF,OAAO,EAAE,sBAAsB,EAAE,KAAK,oBAAoB,EAAE,CAAC;AAE7D;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;CACxC,CAAC;AAEF,KAAK,UAAU,GAAG,oBAAoB,GAAG;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,KAAK,gBAAgB,GAAG,sBAAsB,GAAG;IAChD,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,KAAK,qBAAqB,GAAG;IAC5B,KAAK,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;KAAE,CAAC;IAC1D,KAAK,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;KAAE,CAAC;CAC1D,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,oBAAoB,GAAG;IAC3D,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB;;;;;iEAK6D;IAC7D,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAgDF;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,qBAAqB,GAAG,SAAS,EAC1C,MAAM,EAAE,SAAS,eAAe,EAAE,GAChC;IACF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,cAAc,CAAC;CACjD,CAwBA"}
@@ -0,0 +1,66 @@
1
+ // src/catalog-fec-params.ts
2
+ import { catalogFecInterleaveMs } from "@blockcast/mmt-fec";
3
+ var NO_FEC = {
4
+ fecK: 0,
5
+ fecRepairCount: 0,
6
+ fecSymbolSize: 0,
7
+ fecInterleaveMs: 0
8
+ };
9
+ function numericField(value) {
10
+ const n = typeof value === "number" ? value : typeof value === "string" ? Number(value) : Number.NaN;
11
+ return Number.isFinite(n) && n > 0 ? n : void 0;
12
+ }
13
+ function nonNegativeField(value) {
14
+ const n = typeof value === "number" ? value : typeof value === "string" ? Number(value) : Number.NaN;
15
+ return Number.isFinite(n) && n >= 0 ? n : void 0;
16
+ }
17
+ function fecParams(rendition, fps, sampleRate) {
18
+ const mediaRate = sampleRate === void 0 ? { fps } : { fps, sampleRate };
19
+ const fec = rendition?.fec;
20
+ if (!fec) return { ...NO_FEC, ...mediaRate };
21
+ return {
22
+ fecK: fec.sourceSymbols ?? 0,
23
+ fecRepairCount: fec.repairSymbols ?? 0,
24
+ fecSymbolSize: fec.symbolSize ?? 0,
25
+ // interleaveDepthMs is the FEC block span in MILLISECONDS (§5.1) — the
26
+ // only interleave key the catalog carries post-BLO-14526. Receivers
27
+ // derive D by positive round-half-up of span / GOP duration where needed.
28
+ fecInterleaveMs: catalogFecInterleaveMs(fec) ?? 0,
29
+ // Additive, never a multiplier on the span: jitter belongs to the network
30
+ // path and the span belongs to the encoder, so scaling one by the other
31
+ // hands one network different slack per track. `numericField` rejects 0,
32
+ // so it cannot be reused here — a declared 0 is a legitimate value.
33
+ fecReorderToleranceMs: nonNegativeField(fec.reorderToleranceMs),
34
+ repairTrackName: fec.repairTrack,
35
+ ...mediaRate
36
+ };
37
+ }
38
+ function resolveCatalogTrackFec(catalog, tracks) {
39
+ const videoTrackName = tracks.find((t) => t.type === "video")?.name;
40
+ const audioTrackName = tracks.find((t) => t.type === "audio")?.name;
41
+ const videoRenditions = catalog?.video?.renditions;
42
+ const audioRenditions = catalog?.audio?.renditions;
43
+ const video = videoTrackName ? videoRenditions?.[videoTrackName] : void 0;
44
+ const audio = audioTrackName ? audioRenditions?.[audioTrackName] : void 0;
45
+ const catalogFps = numericField(video?.framerate);
46
+ const sampleRate = numericField(audio?.sampleRate ?? audio?.samplerate);
47
+ const audioFps = sampleRate ? sampleRate / 1024 : void 0;
48
+ const videoParams = fecParams(video, catalogFps);
49
+ const audioParams = fecParams(audio, audioFps, sampleRate);
50
+ return {
51
+ videoTrackName,
52
+ audioTrackName,
53
+ missingVideoRendition: videoTrackName && videoRenditions && !video ? videoTrackName : void 0,
54
+ missingAudioRendition: audioTrackName && audioRenditions && !audio ? audioTrackName : void 0,
55
+ videoForKeyframeRepair: video,
56
+ catalogFps,
57
+ video: videoParams,
58
+ audio: audioParams,
59
+ forTrack: (track) => track.type === "audio" ? audioParams : videoParams
60
+ };
61
+ }
62
+ export {
63
+ catalogFecInterleaveMs,
64
+ resolveCatalogTrackFec
65
+ };
66
+ //# sourceMappingURL=catalog-fec-params.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/catalog-fec-params.ts"],
4
+ "sourcesContent": ["// Catalog \u2192 per-track FEC geometry resolution.\n//\n// Moved from hang-mmt-fec's js/watch/src/track-fec-params.ts so every player\n// (moq-lib/hang, moqtail, shaka MSF) resolves catalog FEC semantics through\n// one shared implementation \u2014 players keep only wiring, not MMT/catalog\n// interpretation. Structural track shape ({ name, type }) keeps this module\n// player-agnostic.\n\nimport { catalogFecInterleaveMs, type FecInterleaveCatalog } from \"@blockcast/mmt-fec\";\n\nexport { catalogFecInterleaveMs, type FecInterleaveCatalog };\n\n/**\n * Minimal structural shape of a resolved endpoint track. Callers may carry\n * extra fields (e.g. hang's ResolvedEndpointTrack adds `pid`) \u2014 the resolver\n * only reads `name` and `type`.\n */\nexport type CatalogTrackRef = {\n\tname: string;\n\ttype: \"video\" | \"audio\" | (string & {});\n};\n\ntype FecCatalog = FecInterleaveCatalog & {\n\tsourceSymbols?: number;\n\trepairSymbols?: number;\n\tsymbolSize?: number;\n\t/** Signaled jitter/reorder allowance in ms (added to the block span). */\n\treorderToleranceMs?: number;\n\trepairTrack?: string;\n};\n\ntype RenditionCatalog = KeyframeCadenceCatalog & {\n\tfec?: FecCatalog;\n\tframerate?: unknown;\n\tsampleRate?: unknown;\n\tsamplerate?: unknown;\n};\n\ntype CatalogWithRenditions = {\n\tvideo?: { renditions?: Record<string, RenditionCatalog> };\n\taudio?: { renditions?: Record<string, RenditionCatalog> };\n};\n\nexport type GroupDurationCatalog = {\n\tgroupDurationTicks?: number;\n\tgroupDurationMs?: number;\n\ttimescale?: number;\n};\n\nexport type KeyframeCadenceCatalog = GroupDurationCatalog & {\n\tkeyframeDurationTicks?: number;\n\tkeyframeDurationMs?: number;\n\tkeyframeIntervalTicks?: number;\n\tkeyframeIntervalMs?: number;\n\tgopDurationTicks?: number;\n\tgopDurationMs?: number;\n};\n\nexport type TrackFecParams = {\n\tfecK: number;\n\tfecRepairCount: number;\n\tfecSymbolSize: number;\n\tfecInterleaveMs: number;\n\t/** Catalog fec.reorderToleranceMs \u2014 signaled jitter/reorder allowance, ADDED\n\t * to the block span to form a deadline. Deliberately `number | undefined`\n\t * and NOT floored to 0: a declared 0 (\"this path needs no slack\") and an\n\t * absent value (\"the encoder never said\") must stay distinguishable, or a\n\t * consumer that wants to fail loud on absence silently reads a default\n\t * instead \u2014 which is exactly how the magic 3.0 survived. */\n\tfecReorderToleranceMs?: number;\n\trepairTrackName?: string;\n\tfps?: number;\n\tsampleRate?: number;\n};\n\nconst NO_FEC: TrackFecParams = {\n\tfecK: 0,\n\tfecRepairCount: 0,\n\tfecSymbolSize: 0,\n\tfecInterleaveMs: 0,\n};\n\nfunction numericField(value: unknown): number | undefined {\n\tconst n = typeof value === \"number\" ? value : typeof value === \"string\" ? Number(value) : Number.NaN;\n\treturn Number.isFinite(n) && n > 0 ? n : undefined;\n}\n\n/** Like `numericField` but admits an explicit 0, and still rejects absent,\n * negative and non-finite input. Absence returns undefined so callers can\n * tell \"declared none\" from \"never declared\". */\nfunction nonNegativeField(value: unknown): number | undefined {\n\tconst n = typeof value === \"number\" ? value : typeof value === \"string\" ? Number(value) : Number.NaN;\n\treturn Number.isFinite(n) && n >= 0 ? n : undefined;\n}\n\nfunction fecParams(\n\trendition: RenditionCatalog | undefined,\n\tfps?: number,\n\tsampleRate?: number,\n): TrackFecParams {\n\tconst mediaRate = sampleRate === undefined ? { fps } : { fps, sampleRate };\n\tconst fec = rendition?.fec;\n\tif (!fec) return { ...NO_FEC, ...mediaRate };\n\treturn {\n\t\tfecK: fec.sourceSymbols ?? 0,\n\t\tfecRepairCount: fec.repairSymbols ?? 0,\n\t\tfecSymbolSize: fec.symbolSize ?? 0,\n\t\t// interleaveDepthMs is the FEC block span in MILLISECONDS (\u00A75.1) \u2014 the\n\t\t// only interleave key the catalog carries post-BLO-14526. Receivers\n\t\t// derive D by positive round-half-up of span / GOP duration where needed.\n\t\tfecInterleaveMs: catalogFecInterleaveMs(fec) ?? 0,\n\t\t// Additive, never a multiplier on the span: jitter belongs to the network\n\t\t// path and the span belongs to the encoder, so scaling one by the other\n\t\t// hands one network different slack per track. `numericField` rejects 0,\n\t\t// so it cannot be reused here \u2014 a declared 0 is a legitimate value.\n\t\tfecReorderToleranceMs: nonNegativeField(fec.reorderToleranceMs),\n\t\trepairTrackName: fec.repairTrack,\n\t\t...mediaRate,\n\t};\n}\n\n/**\n * Resolves per-track FEC geometry from the catalog for the active endpoint tracks.\n *\n * Invariant: expects at most one video track and one audio track. `forTrack`\n * dispatches purely on `track.type`, so a second video track (e.g. a simulcast\n * variant) would silently receive the first video rendition's geometry. Revisit\n * the `track.type` dispatch before relaxing that one-per-type assumption.\n */\nexport function resolveCatalogTrackFec(\n\tcatalog: CatalogWithRenditions | undefined,\n\ttracks: readonly CatalogTrackRef[],\n): {\n\tvideoTrackName?: string;\n\taudioTrackName?: string;\n\tmissingVideoRendition?: string;\n\tmissingAudioRendition?: string;\n\tvideoForKeyframeRepair?: KeyframeCadenceCatalog;\n\tcatalogFps?: number;\n\tvideo: TrackFecParams;\n\taudio: TrackFecParams;\n\tforTrack(track: CatalogTrackRef): TrackFecParams;\n} {\n\tconst videoTrackName = tracks.find((t) => t.type === \"video\")?.name;\n\tconst audioTrackName = tracks.find((t) => t.type === \"audio\")?.name;\n\tconst videoRenditions = catalog?.video?.renditions;\n\tconst audioRenditions = catalog?.audio?.renditions;\n\tconst video = videoTrackName ? videoRenditions?.[videoTrackName] : undefined;\n\tconst audio = audioTrackName ? audioRenditions?.[audioTrackName] : undefined;\n\tconst catalogFps = numericField(video?.framerate);\n\tconst sampleRate = numericField(audio?.sampleRate ?? audio?.samplerate);\n\tconst audioFps = sampleRate ? sampleRate / 1024 : undefined;\n\tconst videoParams = fecParams(video, catalogFps);\n\tconst audioParams = fecParams(audio, audioFps, sampleRate);\n\n\treturn {\n\t\tvideoTrackName,\n\t\taudioTrackName,\n\t\tmissingVideoRendition: videoTrackName && videoRenditions && !video ? videoTrackName : undefined,\n\t\tmissingAudioRendition: audioTrackName && audioRenditions && !audio ? audioTrackName : undefined,\n\t\tvideoForKeyframeRepair: video,\n\t\tcatalogFps,\n\t\tvideo: videoParams,\n\t\taudio: audioParams,\n\t\tforTrack: (track) => (track.type === \"audio\" ? audioParams : videoParams),\n\t};\n}\n"],
5
+ "mappings": ";AAQA,SAAS,8BAAyD;AAmElE,IAAM,SAAyB;AAAA,EAC9B,MAAM;AAAA,EACN,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,iBAAiB;AAClB;AAEA,SAAS,aAAa,OAAoC;AACzD,QAAM,IAAI,OAAO,UAAU,WAAW,QAAQ,OAAO,UAAU,WAAW,OAAO,KAAK,IAAI,OAAO;AACjG,SAAO,OAAO,SAAS,CAAC,KAAK,IAAI,IAAI,IAAI;AAC1C;AAKA,SAAS,iBAAiB,OAAoC;AAC7D,QAAM,IAAI,OAAO,UAAU,WAAW,QAAQ,OAAO,UAAU,WAAW,OAAO,KAAK,IAAI,OAAO;AACjG,SAAO,OAAO,SAAS,CAAC,KAAK,KAAK,IAAI,IAAI;AAC3C;AAEA,SAAS,UACR,WACA,KACA,YACiB;AACjB,QAAM,YAAY,eAAe,SAAY,EAAE,IAAI,IAAI,EAAE,KAAK,WAAW;AACzE,QAAM,MAAM,WAAW;AACvB,MAAI,CAAC,IAAK,QAAO,EAAE,GAAG,QAAQ,GAAG,UAAU;AAC3C,SAAO;AAAA,IACN,MAAM,IAAI,iBAAiB;AAAA,IAC3B,gBAAgB,IAAI,iBAAiB;AAAA,IACrC,eAAe,IAAI,cAAc;AAAA;AAAA;AAAA;AAAA,IAIjC,iBAAiB,uBAAuB,GAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,IAKhD,uBAAuB,iBAAiB,IAAI,kBAAkB;AAAA,IAC9D,iBAAiB,IAAI;AAAA,IACrB,GAAG;AAAA,EACJ;AACD;AAUO,SAAS,uBACf,SACA,QAWC;AACD,QAAM,iBAAiB,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,GAAG;AAC/D,QAAM,iBAAiB,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,GAAG;AAC/D,QAAM,kBAAkB,SAAS,OAAO;AACxC,QAAM,kBAAkB,SAAS,OAAO;AACxC,QAAM,QAAQ,iBAAiB,kBAAkB,cAAc,IAAI;AACnE,QAAM,QAAQ,iBAAiB,kBAAkB,cAAc,IAAI;AACnE,QAAM,aAAa,aAAa,OAAO,SAAS;AAChD,QAAM,aAAa,aAAa,OAAO,cAAc,OAAO,UAAU;AACtE,QAAM,WAAW,aAAa,aAAa,OAAO;AAClD,QAAM,cAAc,UAAU,OAAO,UAAU;AAC/C,QAAM,cAAc,UAAU,OAAO,UAAU,UAAU;AAEzD,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA,uBAAuB,kBAAkB,mBAAmB,CAAC,QAAQ,iBAAiB;AAAA,IACtF,uBAAuB,kBAAkB,mBAAmB,CAAC,QAAQ,iBAAiB;AAAA,IACtF,wBAAwB;AAAA,IACxB;AAAA,IACA,OAAO;AAAA,IACP,OAAO;AAAA,IACP,UAAU,CAAC,UAAW,MAAM,SAAS,UAAU,cAAc;AAAA,EAC9D;AACD;",
6
+ "names": []
7
+ }
@@ -0,0 +1,19 @@
1
+ /** One `networkSource[]` entry as published (`{type, relay, port?}`). */
2
+ export type CatalogNetworkSource = {
3
+ type?: string;
4
+ relay?: string;
5
+ port?: number;
6
+ };
7
+ /** Resolved AMT relay a player can hand to its multicast join/subscribe. */
8
+ export type AmtNetworkSource = {
9
+ relay: string;
10
+ port?: number;
11
+ };
12
+ /**
13
+ * Resolve the AMT relay from a catalog `multicast` block's `networkSource`
14
+ * (array or bare-object form). Returns the first entry with `type: "amt"`
15
+ * and a non-blank relay, or `undefined` when the catalog advertises none —
16
+ * callers fall back to native multicast (or their own explicit relay config).
17
+ */
18
+ export declare function catalogAmtNetworkSource(networkSource: unknown): AmtNetworkSource | undefined;
19
+ //# sourceMappingURL=catalog-network-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-network-source.d.ts","sourceRoot":"","sources":["../src/catalog-network-source.ts"],"names":[],"mappings":"AAYA,yEAAyE;AACzE,MAAM,MAAM,oBAAoB,GAAG;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,4EAA4E;AAC5E,MAAM,MAAM,gBAAgB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAOF;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,aAAa,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAY5F"}
@@ -0,0 +1,22 @@
1
+ // src/catalog-network-source.ts
2
+ function normalizePort(value) {
3
+ const n = typeof value === "number" ? value : typeof value === "string" ? Number(value) : Number.NaN;
4
+ return Number.isInteger(n) && n > 0 && n <= 65535 ? n : void 0;
5
+ }
6
+ function catalogAmtNetworkSource(networkSource) {
7
+ const entries = Array.isArray(networkSource) ? networkSource : networkSource ? [networkSource] : [];
8
+ for (const raw of entries) {
9
+ if (!raw || typeof raw !== "object") continue;
10
+ const ns = raw;
11
+ if (ns.type !== "amt") continue;
12
+ const relay = typeof ns.relay === "string" ? ns.relay.trim() : "";
13
+ if (!relay) continue;
14
+ const port = normalizePort(ns.port);
15
+ return port !== void 0 ? { relay, port } : { relay };
16
+ }
17
+ return void 0;
18
+ }
19
+ export {
20
+ catalogAmtNetworkSource
21
+ };
22
+ //# sourceMappingURL=catalog-network-source.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/catalog-network-source.ts"],
4
+ "sourcesContent": ["// Catalog \u2192 AMT relay discovery (multicast.networkSource).\n//\n// Shared by every player (moq-lib/hang, moqtail, shaka MSF) so networkSource\n// interpretation lives in one place \u2014 players keep only wiring, not\n// MMT/catalog semantics.\n//\n// draft-ramadan-moq-multicast \u00A74.1 carries relay discovery as\n// `multicast.networkSource`. Publishers emit the canonical ARRAY form\n// (hang-rs `Option<Vec<NetworkSource>>`; cast's bridge + ladder catalogs), but\n// hang's zod RootSchema also accepts a bare object and older hand-authored\n// catalogs used it \u2014 consume both.\n\n/** One `networkSource[]` entry as published (`{type, relay, port?}`). */\nexport type CatalogNetworkSource = {\n\ttype?: string;\n\trelay?: string;\n\tport?: number;\n};\n\n/** Resolved AMT relay a player can hand to its multicast join/subscribe. */\nexport type AmtNetworkSource = {\n\trelay: string;\n\tport?: number;\n};\n\nfunction normalizePort(value: unknown): number | undefined {\n\tconst n = typeof value === \"number\" ? value : typeof value === \"string\" ? Number(value) : Number.NaN;\n\treturn Number.isInteger(n) && n > 0 && n <= 65535 ? n : undefined;\n}\n\n/**\n * Resolve the AMT relay from a catalog `multicast` block's `networkSource`\n * (array or bare-object form). Returns the first entry with `type: \"amt\"`\n * and a non-blank relay, or `undefined` when the catalog advertises none \u2014\n * callers fall back to native multicast (or their own explicit relay config).\n */\nexport function catalogAmtNetworkSource(networkSource: unknown): AmtNetworkSource | undefined {\n\tconst entries = Array.isArray(networkSource) ? networkSource : networkSource ? [networkSource] : [];\n\tfor (const raw of entries) {\n\t\tif (!raw || typeof raw !== \"object\") continue;\n\t\tconst ns = raw as CatalogNetworkSource;\n\t\tif (ns.type !== \"amt\") continue;\n\t\tconst relay = typeof ns.relay === \"string\" ? ns.relay.trim() : \"\";\n\t\tif (!relay) continue;\n\t\tconst port = normalizePort(ns.port);\n\t\treturn port !== undefined ? { relay, port } : { relay };\n\t}\n\treturn undefined;\n}\n"],
5
+ "mappings": ";AAyBA,SAAS,cAAc,OAAoC;AAC1D,QAAM,IAAI,OAAO,UAAU,WAAW,QAAQ,OAAO,UAAU,WAAW,OAAO,KAAK,IAAI,OAAO;AACjG,SAAO,OAAO,UAAU,CAAC,KAAK,IAAI,KAAK,KAAK,QAAQ,IAAI;AACzD;AAQO,SAAS,wBAAwB,eAAsD;AAC7F,QAAM,UAAU,MAAM,QAAQ,aAAa,IAAI,gBAAgB,gBAAgB,CAAC,aAAa,IAAI,CAAC;AAClG,aAAW,OAAO,SAAS;AAC1B,QAAI,CAAC,OAAO,OAAO,QAAQ,SAAU;AACrC,UAAM,KAAK;AACX,QAAI,GAAG,SAAS,MAAO;AACvB,UAAM,QAAQ,OAAO,GAAG,UAAU,WAAW,GAAG,MAAM,KAAK,IAAI;AAC/D,QAAI,CAAC,MAAO;AACZ,UAAM,OAAO,cAAc,GAAG,IAAI;AAClC,WAAO,SAAS,SAAY,EAAE,OAAO,KAAK,IAAI,EAAE,MAAM;AAAA,EACvD;AACA,SAAO;AACR;",
6
+ "names": []
7
+ }
@@ -0,0 +1,18 @@
1
+ export interface CatalogSchemaValidationError {
2
+ instancePath: string;
3
+ schemaPath: string;
4
+ keyword: string;
5
+ params: Record<string, unknown>;
6
+ message?: string;
7
+ }
8
+ export interface CatalogSchemaValidator {
9
+ (catalog: unknown): boolean;
10
+ errors: CatalogSchemaValidationError[] | null;
11
+ }
12
+ /**
13
+ * Compile the published catalog schema with every package-defined semantic
14
+ * keyword installed. Consumers must use this entry point instead of compiling
15
+ * `catalog.schema.json` with a bare JSON Schema validator.
16
+ */
17
+ export declare function createCatalogSchemaValidator(schema: object): CatalogSchemaValidator;
18
+ //# sourceMappingURL=catalog-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-validator.d.ts","sourceRoot":"","sources":["../src/catalog-validator.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,4BAA4B;IAC3C,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAA;IAC3B,MAAM,EAAE,4BAA4B,EAAE,GAAG,IAAI,CAAA;CAC9C;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,sBAAsB,CAWnF"}