@blockcast/mmt-container 0.1.0 → 0.3.0-main.d9354616fdf2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (799) hide show
  1. package/README.md +524 -0
  2. package/dist/.build-stamp +0 -0
  3. package/dist/__tests__/test-utils.d.ts +71 -0
  4. package/dist/__tests__/test-utils.d.ts.map +1 -0
  5. package/dist/align.d.ts +152 -0
  6. package/dist/align.d.ts.map +1 -0
  7. package/dist/align.js +88 -0
  8. package/dist/align.js.map +7 -0
  9. package/dist/audio-init-parser.d.ts +66 -0
  10. package/dist/audio-init-parser.d.ts.map +1 -0
  11. package/dist/audio-init-parser.js +118 -0
  12. package/dist/audio-init-parser.js.map +7 -0
  13. package/dist/audio-ring-buffer.d.ts +50 -0
  14. package/dist/audio-ring-buffer.d.ts.map +1 -0
  15. package/dist/audio-ring-buffer.js +80 -0
  16. package/dist/audio-ring-buffer.js.map +7 -0
  17. package/dist/authored-timing.d.ts +32 -0
  18. package/dist/authored-timing.d.ts.map +1 -0
  19. package/dist/authored-timing.js +32 -0
  20. package/dist/authored-timing.js.map +7 -0
  21. package/dist/block-policy.d.ts +314 -0
  22. package/dist/block-policy.d.ts.map +1 -0
  23. package/dist/block-policy.js +466 -0
  24. package/dist/block-policy.js.map +7 -0
  25. package/dist/browser-runtime.js +26549 -0
  26. package/dist/browser-runtime.js.map +7 -0
  27. package/dist/carp-catalog.d.ts +429 -0
  28. package/dist/carp-catalog.d.ts.map +1 -0
  29. package/dist/carp-catalog.js +985 -0
  30. package/dist/carp-catalog.js.map +7 -0
  31. package/dist/catalog-fec-params.d.ts +275 -0
  32. package/dist/catalog-fec-params.d.ts.map +1 -0
  33. package/dist/catalog-fec-params.js +702 -0
  34. package/dist/catalog-fec-params.js.map +7 -0
  35. package/dist/catalog-network-source.d.ts +42 -0
  36. package/dist/catalog-network-source.d.ts.map +1 -0
  37. package/dist/catalog-network-source.js +47 -0
  38. package/dist/catalog-network-source.js.map +7 -0
  39. package/dist/catalog-validator.d.ts +18 -0
  40. package/dist/catalog-validator.d.ts.map +1 -0
  41. package/dist/catalog-validator.js +7747 -0
  42. package/dist/catalog-validator.js.map +7 -0
  43. package/dist/cmaf-block-assembler.d.ts +285 -0
  44. package/dist/cmaf-block-assembler.d.ts.map +1 -0
  45. package/dist/cmaf-block-assembler.js +1966 -0
  46. package/dist/cmaf-block-assembler.js.map +7 -0
  47. package/dist/cmaf-group-batcher.d.ts +38 -0
  48. package/dist/cmaf-group-batcher.d.ts.map +1 -0
  49. package/dist/cmaf-group-batcher.js +176 -0
  50. package/dist/cmaf-group-batcher.js.map +7 -0
  51. package/dist/cmcd-producer.d.ts +104 -0
  52. package/dist/cmcd-producer.d.ts.map +1 -0
  53. package/dist/cmcd-producer.js +183 -0
  54. package/dist/cmcd-producer.js.map +7 -0
  55. package/dist/codec-utils.d.ts +384 -0
  56. package/dist/codec-utils.d.ts.map +1 -0
  57. package/dist/codec-utils.js +1546 -0
  58. package/dist/codec-utils.js.map +7 -0
  59. package/dist/conceal-timeline.d.ts +146 -0
  60. package/dist/conceal-timeline.d.ts.map +1 -0
  61. package/dist/conceal-timeline.js +137 -0
  62. package/dist/conceal-timeline.js.map +7 -0
  63. package/dist/delivery-gap.d.ts +75 -0
  64. package/dist/delivery-gap.d.ts.map +1 -0
  65. package/dist/delivery-gap.js +88 -0
  66. package/dist/delivery-gap.js.map +7 -0
  67. package/dist/duplicate-ledger.d.ts +197 -0
  68. package/dist/duplicate-ledger.d.ts.map +1 -0
  69. package/dist/duplicate-ledger.js +226 -0
  70. package/dist/duplicate-ledger.js.map +7 -0
  71. package/dist/fec-codec.d.ts +32 -0
  72. package/dist/fec-codec.d.ts.map +1 -0
  73. package/dist/fec-codec.js +47 -0
  74. package/dist/fec-codec.js.map +7 -0
  75. package/dist/fec-manager.d.ts +583 -0
  76. package/dist/fec-manager.d.ts.map +1 -0
  77. package/dist/fec-manager.js +3899 -0
  78. package/dist/fec-manager.js.map +7 -0
  79. package/dist/fec-starvation-detector.d.ts +59 -0
  80. package/dist/fec-starvation-detector.d.ts.map +1 -0
  81. package/dist/fec-starvation-detector.js +60 -0
  82. package/dist/fec-starvation-detector.js.map +7 -0
  83. package/dist/fec-state.d.ts +131 -0
  84. package/dist/fec-state.d.ts.map +1 -0
  85. package/dist/fec-state.js +87 -0
  86. package/dist/fec-state.js.map +7 -0
  87. package/dist/fec-worker-setup.d.ts +94 -0
  88. package/dist/fec-worker-setup.d.ts.map +1 -0
  89. package/dist/fec-worker-setup.js +673 -0
  90. package/dist/fec-worker-setup.js.map +7 -0
  91. package/dist/fmp4-completion.d.ts +30 -0
  92. package/dist/fmp4-completion.d.ts.map +1 -0
  93. package/dist/fmp4-completion.js +21 -0
  94. package/dist/fmp4-completion.js.map +7 -0
  95. package/dist/fmp4-reader.d.ts +37 -0
  96. package/dist/fmp4-reader.d.ts.map +1 -0
  97. package/dist/fmp4-reader.js +100 -0
  98. package/dist/fmp4-reader.js.map +7 -0
  99. package/dist/index.d.ts +44 -3
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +460 -14
  102. package/dist/index.js.map +7 -1
  103. package/dist/iso-block-locator.d.ts +118 -0
  104. package/dist/iso-block-locator.d.ts.map +1 -0
  105. package/dist/iso-block-locator.js +289 -0
  106. package/dist/iso-block-locator.js.map +7 -0
  107. package/dist/iso-bmff-timing.d.ts +78 -0
  108. package/dist/iso-bmff-timing.d.ts.map +1 -0
  109. package/dist/iso-bmff-timing.js +593 -0
  110. package/dist/iso-bmff-timing.js.map +7 -0
  111. package/dist/loc.d.ts +70 -75
  112. package/dist/loc.d.ts.map +1 -1
  113. package/dist/loc.js +106 -192
  114. package/dist/loc.js.map +7 -1
  115. package/dist/manifest-auth-plan.d.ts +30 -0
  116. package/dist/manifest-auth-plan.d.ts.map +1 -0
  117. package/dist/manifest-auth-plan.js +1266 -0
  118. package/dist/manifest-auth-plan.js.map +7 -0
  119. package/dist/media-router.d.ts +262 -0
  120. package/dist/media-router.d.ts.map +1 -0
  121. package/dist/media-router.js +584 -0
  122. package/dist/media-router.js.map +7 -0
  123. package/dist/mfu-reassembler.d.ts +313 -9
  124. package/dist/mfu-reassembler.d.ts.map +1 -1
  125. package/dist/mfu-reassembler.js +3051 -285
  126. package/dist/mfu-reassembler.js.map +7 -1
  127. package/dist/mfu-reassembly-policy.d.ts +24 -0
  128. package/dist/mfu-reassembly-policy.d.ts.map +1 -0
  129. package/dist/mfu-reassembly-policy.js +99 -0
  130. package/dist/mfu-reassembly-policy.js.map +7 -0
  131. package/dist/mmtp-container-parser.d.ts +568 -0
  132. package/dist/mmtp-container-parser.d.ts.map +1 -0
  133. package/dist/mmtp-container-parser.js +6580 -0
  134. package/dist/mmtp-container-parser.js.map +7 -0
  135. package/dist/mmtp-container-parser.no-modules.js +9616 -0
  136. package/dist/mmtp-container-parser.no-modules.js.map +7 -0
  137. package/dist/mmtp-decode-pipeline.d.ts +138 -0
  138. package/dist/mmtp-decode-pipeline.d.ts.map +1 -0
  139. package/dist/mmtp-decode-pipeline.js +6814 -0
  140. package/dist/mmtp-decode-pipeline.js.map +7 -0
  141. package/dist/mmtp-router.d.ts +679 -0
  142. package/dist/mmtp-router.d.ts.map +1 -0
  143. package/dist/mmtp-router.js +11278 -0
  144. package/dist/mmtp-router.js.map +7 -0
  145. package/dist/mmtp-to-cmaf.d.ts +187 -0
  146. package/dist/mmtp-to-cmaf.d.ts.map +1 -0
  147. package/dist/mmtp-to-cmaf.js +716 -0
  148. package/dist/mmtp-to-cmaf.js.map +7 -0
  149. package/dist/multicast-auth-catalog.d.ts +115 -0
  150. package/dist/multicast-auth-catalog.d.ts.map +1 -0
  151. package/dist/multicast-auth-catalog.js +202 -0
  152. package/dist/multicast-auth-catalog.js.map +7 -0
  153. package/dist/multicast-input.d.ts +141 -0
  154. package/dist/multicast-input.d.ts.map +1 -0
  155. package/dist/multicast-input.js +390 -0
  156. package/dist/multicast-input.js.map +7 -0
  157. package/dist/multicast-manager.d.ts +669 -0
  158. package/dist/multicast-manager.d.ts.map +1 -0
  159. package/dist/multicast-manager.js +19101 -0
  160. package/dist/multicast-manager.js.map +7 -0
  161. package/dist/multicast-transport.d.ts +271 -0
  162. package/dist/multicast-transport.d.ts.map +1 -0
  163. package/dist/multicast-transport.js +2264 -0
  164. package/dist/multicast-transport.js.map +7 -0
  165. package/dist/multicast-unwrap.d.ts +57 -0
  166. package/dist/multicast-unwrap.d.ts.map +1 -0
  167. package/dist/multicast-unwrap.js +418 -0
  168. package/dist/multicast-unwrap.js.map +7 -0
  169. package/dist/no-modules.d.ts +10 -0
  170. package/dist/no-modules.d.ts.map +1 -0
  171. package/dist/no-modules.js +9491 -0
  172. package/dist/no-modules.js.map +7 -0
  173. package/dist/phase14-catalog-override.d.ts +126 -0
  174. package/dist/phase14-catalog-override.d.ts.map +1 -0
  175. package/dist/phase14-catalog-override.js +155 -0
  176. package/dist/phase14-catalog-override.js.map +7 -0
  177. package/dist/repair-fetch.d.ts +270 -0
  178. package/dist/repair-fetch.d.ts.map +1 -0
  179. package/dist/repair-fetch.js +381 -0
  180. package/dist/repair-fetch.js.map +7 -0
  181. package/dist/repair-layers.d.ts +158 -0
  182. package/dist/repair-layers.d.ts.map +1 -0
  183. package/dist/repair-layers.js +344 -0
  184. package/dist/repair-layers.js.map +7 -0
  185. package/dist/sample-combiner.d.ts +212 -0
  186. package/dist/sample-combiner.d.ts.map +1 -0
  187. package/dist/sample-combiner.js +595 -0
  188. package/dist/sample-combiner.js.map +7 -0
  189. package/dist/signaling.d.ts +29 -0
  190. package/dist/signaling.d.ts.map +1 -0
  191. package/dist/signaling.js +572 -0
  192. package/dist/signaling.js.map +7 -0
  193. package/dist/source-auth.d.ts +2 -0
  194. package/dist/source-auth.d.ts.map +1 -0
  195. package/dist/source-auth.js +1209 -0
  196. package/dist/source-auth.js.map +7 -0
  197. package/dist/switching-set-alignment.d.ts +61 -0
  198. package/dist/switching-set-alignment.d.ts.map +1 -0
  199. package/dist/switching-set-alignment.js +70 -0
  200. package/dist/switching-set-alignment.js.map +7 -0
  201. package/dist/timestamp-codec.d.ts +34 -0
  202. package/dist/timestamp-codec.d.ts.map +1 -0
  203. package/dist/timestamp-codec.js +473 -0
  204. package/dist/timestamp-codec.js.map +7 -0
  205. package/dist/track-pipeline-setup.d.ts +83 -0
  206. package/dist/track-pipeline-setup.d.ts.map +1 -0
  207. package/dist/track-pipeline-setup.js +291 -0
  208. package/dist/track-pipeline-setup.js.map +7 -0
  209. package/dist/track-pipeline.d.ts +121 -0
  210. package/dist/track-pipeline.d.ts.map +1 -0
  211. package/dist/track-pipeline.js +209 -0
  212. package/dist/track-pipeline.js.map +7 -0
  213. package/dist/track-session.d.ts +414 -0
  214. package/dist/track-session.d.ts.map +1 -0
  215. package/dist/track-session.js +754 -0
  216. package/dist/track-session.js.map +7 -0
  217. package/dist/transport-pool.d.ts +69 -0
  218. package/dist/transport-pool.d.ts.map +1 -0
  219. package/dist/transport-pool.js +74 -0
  220. package/dist/transport-pool.js.map +7 -0
  221. package/dist/wasm-mfu-reassembler.d.ts +97 -0
  222. package/dist/wasm-mfu-reassembler.d.ts.map +1 -0
  223. package/dist/wasm-mfu-reassembler.js +2133 -0
  224. package/dist/wasm-mfu-reassembler.js.map +7 -0
  225. package/dist/wasm-mmtp-container-parser.d.ts +10 -0
  226. package/dist/wasm-mmtp-container-parser.d.ts.map +1 -0
  227. package/dist/wasm-mmtp-container-parser.js +6834 -0
  228. package/dist/wasm-mmtp-container-parser.js.map +7 -0
  229. package/node_modules/@blockcast/fec-worker/README.md +223 -0
  230. package/node_modules/@blockcast/fec-worker/dist/.build-stamp +0 -0
  231. package/node_modules/@blockcast/fec-worker/dist/block-order.d.ts +38 -0
  232. package/node_modules/@blockcast/fec-worker/dist/block-order.d.ts.map +1 -0
  233. package/node_modules/@blockcast/fec-worker/dist/block-order.js +78 -0
  234. package/node_modules/@blockcast/fec-worker/dist/block-order.js.map +1 -0
  235. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts +93 -0
  236. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts.map +1 -0
  237. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js +346 -0
  238. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js.map +1 -0
  239. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts +380 -0
  240. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts.map +1 -0
  241. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js +11 -0
  242. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js.map +1 -0
  243. package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts +14 -0
  244. package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts.map +1 -0
  245. package/node_modules/@blockcast/fec-worker/dist/fec-worker.js +859 -0
  246. package/node_modules/@blockcast/fec-worker/dist/fec-worker.js.map +7 -0
  247. package/node_modules/@blockcast/fec-worker/dist/index.d.ts +10 -0
  248. package/node_modules/@blockcast/fec-worker/dist/index.d.ts.map +1 -0
  249. package/node_modules/@blockcast/fec-worker/dist/index.js +8 -0
  250. package/node_modules/@blockcast/fec-worker/dist/index.js.map +1 -0
  251. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts +20 -0
  252. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts.map +1 -0
  253. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js +370 -0
  254. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js.map +7 -0
  255. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts +104 -0
  256. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts.map +1 -0
  257. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js +181 -0
  258. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js.map +1 -0
  259. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts +194 -0
  260. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts.map +1 -0
  261. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js +62 -0
  262. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js.map +1 -0
  263. package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts +9 -0
  264. package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts.map +1 -0
  265. package/node_modules/@blockcast/fec-worker/dist/transfer.js +13 -0
  266. package/node_modules/@blockcast/fec-worker/dist/transfer.js.map +1 -0
  267. package/node_modules/@blockcast/fec-worker/package.json +59 -0
  268. package/node_modules/@blockcast/fec-worker/src/block-order.ts +93 -0
  269. package/node_modules/@blockcast/fec-worker/src/fec-worker-client.ts +392 -0
  270. package/node_modules/@blockcast/fec-worker/src/fec-worker-types.ts +399 -0
  271. package/node_modules/@blockcast/fec-worker/src/fec-worker.ts +1502 -0
  272. package/node_modules/@blockcast/fec-worker/src/index.ts +35 -0
  273. package/node_modules/@blockcast/fec-worker/src/shred-fec-worker.ts +589 -0
  274. package/node_modules/@blockcast/fec-worker/src/shred-worker-client.ts +222 -0
  275. package/node_modules/@blockcast/fec-worker/src/shred-worker-types.ts +209 -0
  276. package/node_modules/@blockcast/fec-worker/src/transfer.ts +12 -0
  277. package/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
  278. package/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
  279. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
  280. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
  281. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
  282. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
  283. package/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
  284. package/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
  285. package/node_modules/@blockcast/mmt-base/README.md +134 -0
  286. package/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
  287. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts +55 -0
  288. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts.map +1 -0
  289. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js +128 -0
  290. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js.map +1 -0
  291. package/node_modules/@blockcast/mmt-base/dist/index.d.ts +7 -0
  292. package/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
  293. package/node_modules/@blockcast/mmt-base/dist/index.js +7 -0
  294. package/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
  295. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +292 -0
  296. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
  297. package/node_modules/@blockcast/mmt-base/dist/mmtp.js +612 -0
  298. package/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
  299. package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts +18 -0
  300. package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts.map +1 -0
  301. package/node_modules/@blockcast/mmt-base/dist/net-constants.js +18 -0
  302. package/node_modules/@blockcast/mmt-base/dist/net-constants.js.map +1 -0
  303. package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts +47 -0
  304. package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts.map +1 -0
  305. package/node_modules/@blockcast/mmt-base/dist/ntp-short.js +54 -0
  306. package/node_modules/@blockcast/mmt-base/dist/ntp-short.js.map +1 -0
  307. package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts +57 -0
  308. package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts.map +1 -0
  309. package/node_modules/@blockcast/mmt-base/dist/serial-number.js +98 -0
  310. package/node_modules/@blockcast/mmt-base/dist/serial-number.js.map +1 -0
  311. package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts +312 -0
  312. package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts.map +1 -0
  313. package/node_modules/@blockcast/mmt-base/dist/signalling.js +637 -0
  314. package/node_modules/@blockcast/mmt-base/dist/signalling.js.map +1 -0
  315. package/node_modules/@blockcast/mmt-base/package.json +49 -0
  316. package/node_modules/@blockcast/mmt-base/src/fec-block-profile.ts +145 -0
  317. package/node_modules/@blockcast/mmt-base/src/index.ts +6 -0
  318. package/node_modules/@blockcast/mmt-base/src/mmtp.ts +892 -0
  319. package/node_modules/@blockcast/mmt-base/src/net-constants.ts +17 -0
  320. package/node_modules/@blockcast/mmt-base/src/ntp-short.ts +67 -0
  321. package/node_modules/@blockcast/mmt-base/src/serial-number.ts +107 -0
  322. package/node_modules/@blockcast/mmt-base/src/signalling.ts +862 -0
  323. package/node_modules/@blockcast/mmt-fec/README.md +271 -0
  324. package/node_modules/@blockcast/mmt-fec/dist/.build-stamp +0 -0
  325. package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts +82 -0
  326. package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts.map +1 -0
  327. package/node_modules/@blockcast/mmt-fec/dist/block-manager.js +296 -0
  328. package/node_modules/@blockcast/mmt-fec/dist/block-manager.js.map +1 -0
  329. package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts +106 -0
  330. package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts.map +1 -0
  331. package/node_modules/@blockcast/mmt-fec/dist/block-processor.js +288 -0
  332. package/node_modules/@blockcast/mmt-fec/dist/block-processor.js.map +1 -0
  333. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts +46 -0
  334. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts.map +1 -0
  335. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js +96 -0
  336. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js.map +1 -0
  337. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts +33 -0
  338. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts.map +1 -0
  339. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js +57 -0
  340. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js.map +1 -0
  341. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts +205 -0
  342. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts.map +1 -0
  343. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js +240 -0
  344. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js.map +1 -0
  345. package/node_modules/@blockcast/mmt-fec/dist/index.d.ts +28 -0
  346. package/node_modules/@blockcast/mmt-fec/dist/index.d.ts.map +1 -0
  347. package/node_modules/@blockcast/mmt-fec/dist/index.js +28 -0
  348. package/node_modules/@blockcast/mmt-fec/dist/index.js.map +1 -0
  349. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts +20 -0
  350. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts.map +1 -0
  351. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js +28 -0
  352. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js.map +1 -0
  353. package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts +258 -0
  354. package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts.map +1 -0
  355. package/node_modules/@blockcast/mmt-fec/dist/oti.js +382 -0
  356. package/node_modules/@blockcast/mmt-fec/dist/oti.js.map +1 -0
  357. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts +41 -0
  358. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts.map +1 -0
  359. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js +81 -0
  360. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js.map +1 -0
  361. package/node_modules/@blockcast/mmt-fec/dist/repair-group.d.ts +82 -0
  362. package/node_modules/@blockcast/mmt-fec/dist/repair-group.d.ts.map +1 -0
  363. package/node_modules/@blockcast/mmt-fec/dist/repair-group.js +170 -0
  364. package/node_modules/@blockcast/mmt-fec/dist/repair-group.js.map +1 -0
  365. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
  366. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
  367. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
  368. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
  369. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
  370. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
  371. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
  372. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
  373. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/README.md +134 -0
  374. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
  375. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts +55 -0
  376. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts.map +1 -0
  377. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js +128 -0
  378. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js.map +1 -0
  379. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts +7 -0
  380. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
  381. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js +7 -0
  382. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
  383. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +292 -0
  384. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
  385. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js +612 -0
  386. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
  387. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts +18 -0
  388. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts.map +1 -0
  389. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.js +18 -0
  390. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.js.map +1 -0
  391. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts +47 -0
  392. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts.map +1 -0
  393. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.js +54 -0
  394. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.js.map +1 -0
  395. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts +57 -0
  396. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts.map +1 -0
  397. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.js +98 -0
  398. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.js.map +1 -0
  399. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.d.ts +312 -0
  400. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.d.ts.map +1 -0
  401. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.js +637 -0
  402. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.js.map +1 -0
  403. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/package.json +49 -0
  404. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/fec-block-profile.ts +145 -0
  405. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/index.ts +6 -0
  406. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/mmtp.ts +892 -0
  407. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/net-constants.ts +17 -0
  408. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/ntp-short.ts +67 -0
  409. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/serial-number.ts +107 -0
  410. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/signalling.ts +862 -0
  411. package/node_modules/@blockcast/mmt-fec/package.json +79 -0
  412. package/node_modules/@blockcast/mmt-fec/src/block-manager.ts +371 -0
  413. package/node_modules/@blockcast/mmt-fec/src/block-processor.ts +439 -0
  414. package/node_modules/@blockcast/mmt-fec/src/cmaf-recovery.ts +127 -0
  415. package/node_modules/@blockcast/mmt-fec/src/cmaf-symbols.ts +68 -0
  416. package/node_modules/@blockcast/mmt-fec/src/fec-block-mapper.ts +310 -0
  417. package/node_modules/@blockcast/mmt-fec/src/index.ts +94 -0
  418. package/node_modules/@blockcast/mmt-fec/src/loc-symbols.ts +34 -0
  419. package/node_modules/@blockcast/mmt-fec/src/oti.ts +463 -0
  420. package/node_modules/@blockcast/mmt-fec/src/reorder-buffer.ts +101 -0
  421. package/node_modules/@blockcast/mmt-fec/src/repair-group.ts +195 -0
  422. package/node_modules/@blockcast/mmt-manifest-verify/dist/.build-stamp +0 -0
  423. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts +28 -0
  424. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts.map +1 -0
  425. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js +128 -0
  426. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js.map +1 -0
  427. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts +4 -0
  428. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts.map +1 -0
  429. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js +4 -0
  430. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js.map +1 -0
  431. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts +37 -0
  432. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts.map +1 -0
  433. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js +179 -0
  434. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js.map +1 -0
  435. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts +99 -0
  436. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts.map +1 -0
  437. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js +492 -0
  438. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js.map +1 -0
  439. package/node_modules/@blockcast/mmt-manifest-verify/package.json +45 -0
  440. package/node_modules/@blockcast/mmt-manifest-verify/src/admission.ts +171 -0
  441. package/node_modules/@blockcast/mmt-manifest-verify/src/index.ts +3 -0
  442. package/node_modules/@blockcast/mmt-manifest-verify/src/source-auth.ts +230 -0
  443. package/node_modules/@blockcast/mmt-manifest-verify/src/verifier.ts +669 -0
  444. package/node_modules/@noble/hashes/LICENSE +21 -0
  445. package/node_modules/@noble/hashes/README.md +521 -0
  446. package/node_modules/@noble/hashes/_assert.d.ts +17 -0
  447. package/node_modules/@noble/hashes/_assert.d.ts.map +1 -0
  448. package/node_modules/@noble/hashes/_assert.js +18 -0
  449. package/node_modules/@noble/hashes/_assert.js.map +1 -0
  450. package/node_modules/@noble/hashes/_blake.d.ts +14 -0
  451. package/node_modules/@noble/hashes/_blake.d.ts.map +1 -0
  452. package/node_modules/@noble/hashes/_blake.js +50 -0
  453. package/node_modules/@noble/hashes/_blake.js.map +1 -0
  454. package/node_modules/@noble/hashes/_md.d.ts +51 -0
  455. package/node_modules/@noble/hashes/_md.d.ts.map +1 -0
  456. package/node_modules/@noble/hashes/_md.js +162 -0
  457. package/node_modules/@noble/hashes/_md.js.map +1 -0
  458. package/node_modules/@noble/hashes/_u64.d.ts +55 -0
  459. package/node_modules/@noble/hashes/_u64.d.ts.map +1 -0
  460. package/node_modules/@noble/hashes/_u64.js +90 -0
  461. package/node_modules/@noble/hashes/_u64.js.map +1 -0
  462. package/node_modules/@noble/hashes/argon2.d.ts +32 -0
  463. package/node_modules/@noble/hashes/argon2.d.ts.map +1 -0
  464. package/node_modules/@noble/hashes/argon2.js +401 -0
  465. package/node_modules/@noble/hashes/argon2.js.map +1 -0
  466. package/node_modules/@noble/hashes/blake1.d.ts +106 -0
  467. package/node_modules/@noble/hashes/blake1.d.ts.map +1 -0
  468. package/node_modules/@noble/hashes/blake1.js +459 -0
  469. package/node_modules/@noble/hashes/blake1.js.map +1 -0
  470. package/node_modules/@noble/hashes/blake2.d.ts +116 -0
  471. package/node_modules/@noble/hashes/blake2.d.ts.map +1 -0
  472. package/node_modules/@noble/hashes/blake2.js +420 -0
  473. package/node_modules/@noble/hashes/blake2.js.map +1 -0
  474. package/node_modules/@noble/hashes/blake2b.d.ts +11 -0
  475. package/node_modules/@noble/hashes/blake2b.d.ts.map +1 -0
  476. package/node_modules/@noble/hashes/blake2b.js +14 -0
  477. package/node_modules/@noble/hashes/blake2b.js.map +1 -0
  478. package/node_modules/@noble/hashes/blake2s.d.ts +20 -0
  479. package/node_modules/@noble/hashes/blake2s.d.ts.map +1 -0
  480. package/node_modules/@noble/hashes/blake2s.js +24 -0
  481. package/node_modules/@noble/hashes/blake2s.js.map +1 -0
  482. package/node_modules/@noble/hashes/blake3.d.ts +54 -0
  483. package/node_modules/@noble/hashes/blake3.d.ts.map +1 -0
  484. package/node_modules/@noble/hashes/blake3.js +255 -0
  485. package/node_modules/@noble/hashes/blake3.js.map +1 -0
  486. package/node_modules/@noble/hashes/crypto.d.ts +2 -0
  487. package/node_modules/@noble/hashes/crypto.d.ts.map +1 -0
  488. package/node_modules/@noble/hashes/crypto.js +5 -0
  489. package/node_modules/@noble/hashes/crypto.js.map +1 -0
  490. package/node_modules/@noble/hashes/cryptoNode.d.ts +2 -0
  491. package/node_modules/@noble/hashes/cryptoNode.d.ts.map +1 -0
  492. package/node_modules/@noble/hashes/cryptoNode.js +18 -0
  493. package/node_modules/@noble/hashes/cryptoNode.js.map +1 -0
  494. package/node_modules/@noble/hashes/eskdf.d.ts +47 -0
  495. package/node_modules/@noble/hashes/eskdf.d.ts.map +1 -0
  496. package/node_modules/@noble/hashes/eskdf.js +166 -0
  497. package/node_modules/@noble/hashes/eskdf.js.map +1 -0
  498. package/node_modules/@noble/hashes/esm/_assert.d.ts +17 -0
  499. package/node_modules/@noble/hashes/esm/_assert.d.ts.map +1 -0
  500. package/node_modules/@noble/hashes/esm/_assert.js +15 -0
  501. package/node_modules/@noble/hashes/esm/_assert.js.map +1 -0
  502. package/node_modules/@noble/hashes/esm/_blake.d.ts +14 -0
  503. package/node_modules/@noble/hashes/esm/_blake.d.ts.map +1 -0
  504. package/node_modules/@noble/hashes/esm/_blake.js +45 -0
  505. package/node_modules/@noble/hashes/esm/_blake.js.map +1 -0
  506. package/node_modules/@noble/hashes/esm/_md.d.ts +51 -0
  507. package/node_modules/@noble/hashes/esm/_md.d.ts.map +1 -0
  508. package/node_modules/@noble/hashes/esm/_md.js +155 -0
  509. package/node_modules/@noble/hashes/esm/_md.js.map +1 -0
  510. package/node_modules/@noble/hashes/esm/_u64.d.ts +55 -0
  511. package/node_modules/@noble/hashes/esm/_u64.d.ts.map +1 -0
  512. package/node_modules/@noble/hashes/esm/_u64.js +67 -0
  513. package/node_modules/@noble/hashes/esm/_u64.js.map +1 -0
  514. package/node_modules/@noble/hashes/esm/argon2.d.ts +32 -0
  515. package/node_modules/@noble/hashes/esm/argon2.d.ts.map +1 -0
  516. package/node_modules/@noble/hashes/esm/argon2.js +392 -0
  517. package/node_modules/@noble/hashes/esm/argon2.js.map +1 -0
  518. package/node_modules/@noble/hashes/esm/blake1.d.ts +106 -0
  519. package/node_modules/@noble/hashes/esm/blake1.d.ts.map +1 -0
  520. package/node_modules/@noble/hashes/esm/blake1.js +452 -0
  521. package/node_modules/@noble/hashes/esm/blake1.js.map +1 -0
  522. package/node_modules/@noble/hashes/esm/blake2.d.ts +116 -0
  523. package/node_modules/@noble/hashes/esm/blake2.d.ts.map +1 -0
  524. package/node_modules/@noble/hashes/esm/blake2.js +413 -0
  525. package/node_modules/@noble/hashes/esm/blake2.js.map +1 -0
  526. package/node_modules/@noble/hashes/esm/blake2b.d.ts +11 -0
  527. package/node_modules/@noble/hashes/esm/blake2b.d.ts.map +1 -0
  528. package/node_modules/@noble/hashes/esm/blake2b.js +11 -0
  529. package/node_modules/@noble/hashes/esm/blake2b.js.map +1 -0
  530. package/node_modules/@noble/hashes/esm/blake2s.d.ts +20 -0
  531. package/node_modules/@noble/hashes/esm/blake2s.d.ts.map +1 -0
  532. package/node_modules/@noble/hashes/esm/blake2s.js +21 -0
  533. package/node_modules/@noble/hashes/esm/blake2s.js.map +1 -0
  534. package/node_modules/@noble/hashes/esm/blake3.d.ts +54 -0
  535. package/node_modules/@noble/hashes/esm/blake3.d.ts.map +1 -0
  536. package/node_modules/@noble/hashes/esm/blake3.js +251 -0
  537. package/node_modules/@noble/hashes/esm/blake3.js.map +1 -0
  538. package/node_modules/@noble/hashes/esm/crypto.d.ts +2 -0
  539. package/node_modules/@noble/hashes/esm/crypto.d.ts.map +1 -0
  540. package/node_modules/@noble/hashes/esm/crypto.js +2 -0
  541. package/node_modules/@noble/hashes/esm/crypto.js.map +1 -0
  542. package/node_modules/@noble/hashes/esm/cryptoNode.d.ts +2 -0
  543. package/node_modules/@noble/hashes/esm/cryptoNode.d.ts.map +1 -0
  544. package/node_modules/@noble/hashes/esm/cryptoNode.js +15 -0
  545. package/node_modules/@noble/hashes/esm/cryptoNode.js.map +1 -0
  546. package/node_modules/@noble/hashes/esm/eskdf.d.ts +47 -0
  547. package/node_modules/@noble/hashes/esm/eskdf.d.ts.map +1 -0
  548. package/node_modules/@noble/hashes/esm/eskdf.js +160 -0
  549. package/node_modules/@noble/hashes/esm/eskdf.js.map +1 -0
  550. package/node_modules/@noble/hashes/esm/hkdf.d.ts +36 -0
  551. package/node_modules/@noble/hashes/esm/hkdf.d.ts.map +1 -0
  552. package/node_modules/@noble/hashes/esm/hkdf.js +82 -0
  553. package/node_modules/@noble/hashes/esm/hkdf.js.map +1 -0
  554. package/node_modules/@noble/hashes/esm/hmac.d.ts +35 -0
  555. package/node_modules/@noble/hashes/esm/hmac.d.ts.map +1 -0
  556. package/node_modules/@noble/hashes/esm/hmac.js +86 -0
  557. package/node_modules/@noble/hashes/esm/hmac.js.map +1 -0
  558. package/node_modules/@noble/hashes/esm/index.d.ts +2 -0
  559. package/node_modules/@noble/hashes/esm/index.d.ts.map +1 -0
  560. package/node_modules/@noble/hashes/esm/index.js +33 -0
  561. package/node_modules/@noble/hashes/esm/index.js.map +1 -0
  562. package/node_modules/@noble/hashes/esm/legacy.d.ts +71 -0
  563. package/node_modules/@noble/hashes/esm/legacy.d.ts.map +1 -0
  564. package/node_modules/@noble/hashes/esm/legacy.js +281 -0
  565. package/node_modules/@noble/hashes/esm/legacy.js.map +1 -0
  566. package/node_modules/@noble/hashes/esm/package.json +10 -0
  567. package/node_modules/@noble/hashes/esm/pbkdf2.d.ts +23 -0
  568. package/node_modules/@noble/hashes/esm/pbkdf2.d.ts.map +1 -0
  569. package/node_modules/@noble/hashes/esm/pbkdf2.js +97 -0
  570. package/node_modules/@noble/hashes/esm/pbkdf2.js.map +1 -0
  571. package/node_modules/@noble/hashes/esm/ripemd160.d.ts +13 -0
  572. package/node_modules/@noble/hashes/esm/ripemd160.d.ts.map +1 -0
  573. package/node_modules/@noble/hashes/esm/ripemd160.js +13 -0
  574. package/node_modules/@noble/hashes/esm/ripemd160.js.map +1 -0
  575. package/node_modules/@noble/hashes/esm/scrypt.d.ts +34 -0
  576. package/node_modules/@noble/hashes/esm/scrypt.d.ts.map +1 -0
  577. package/node_modules/@noble/hashes/esm/scrypt.js +228 -0
  578. package/node_modules/@noble/hashes/esm/scrypt.js.map +1 -0
  579. package/node_modules/@noble/hashes/esm/sha1.d.ts +11 -0
  580. package/node_modules/@noble/hashes/esm/sha1.d.ts.map +1 -0
  581. package/node_modules/@noble/hashes/esm/sha1.js +11 -0
  582. package/node_modules/@noble/hashes/esm/sha1.js.map +1 -0
  583. package/node_modules/@noble/hashes/esm/sha2.d.ts +159 -0
  584. package/node_modules/@noble/hashes/esm/sha2.d.ts.map +1 -0
  585. package/node_modules/@noble/hashes/esm/sha2.js +375 -0
  586. package/node_modules/@noble/hashes/esm/sha2.js.map +1 -0
  587. package/node_modules/@noble/hashes/esm/sha256.d.ts +20 -0
  588. package/node_modules/@noble/hashes/esm/sha256.d.ts.map +1 -0
  589. package/node_modules/@noble/hashes/esm/sha256.js +20 -0
  590. package/node_modules/@noble/hashes/esm/sha256.js.map +1 -0
  591. package/node_modules/@noble/hashes/esm/sha3-addons.d.ts +142 -0
  592. package/node_modules/@noble/hashes/esm/sha3-addons.d.ts.map +1 -0
  593. package/node_modules/@noble/hashes/esm/sha3-addons.js +393 -0
  594. package/node_modules/@noble/hashes/esm/sha3-addons.js.map +1 -0
  595. package/node_modules/@noble/hashes/esm/sha3.d.ts +53 -0
  596. package/node_modules/@noble/hashes/esm/sha3.d.ts.map +1 -0
  597. package/node_modules/@noble/hashes/esm/sha3.js +234 -0
  598. package/node_modules/@noble/hashes/esm/sha3.js.map +1 -0
  599. package/node_modules/@noble/hashes/esm/sha512.d.ts +26 -0
  600. package/node_modules/@noble/hashes/esm/sha512.d.ts.map +1 -0
  601. package/node_modules/@noble/hashes/esm/sha512.js +26 -0
  602. package/node_modules/@noble/hashes/esm/sha512.js.map +1 -0
  603. package/node_modules/@noble/hashes/esm/utils.d.ts +161 -0
  604. package/node_modules/@noble/hashes/esm/utils.d.ts.map +1 -0
  605. package/node_modules/@noble/hashes/esm/utils.js +281 -0
  606. package/node_modules/@noble/hashes/esm/utils.js.map +1 -0
  607. package/node_modules/@noble/hashes/hkdf.d.ts +36 -0
  608. package/node_modules/@noble/hashes/hkdf.d.ts.map +1 -0
  609. package/node_modules/@noble/hashes/hkdf.js +88 -0
  610. package/node_modules/@noble/hashes/hkdf.js.map +1 -0
  611. package/node_modules/@noble/hashes/hmac.d.ts +35 -0
  612. package/node_modules/@noble/hashes/hmac.d.ts.map +1 -0
  613. package/node_modules/@noble/hashes/hmac.js +91 -0
  614. package/node_modules/@noble/hashes/hmac.js.map +1 -0
  615. package/node_modules/@noble/hashes/index.d.ts +1 -0
  616. package/node_modules/@noble/hashes/index.d.ts.map +1 -0
  617. package/node_modules/@noble/hashes/index.js +33 -0
  618. package/node_modules/@noble/hashes/index.js.map +1 -0
  619. package/node_modules/@noble/hashes/legacy.d.ts +71 -0
  620. package/node_modules/@noble/hashes/legacy.d.ts.map +1 -0
  621. package/node_modules/@noble/hashes/legacy.js +287 -0
  622. package/node_modules/@noble/hashes/legacy.js.map +1 -0
  623. package/node_modules/@noble/hashes/package.json +266 -0
  624. package/node_modules/@noble/hashes/pbkdf2.d.ts +23 -0
  625. package/node_modules/@noble/hashes/pbkdf2.d.ts.map +1 -0
  626. package/node_modules/@noble/hashes/pbkdf2.js +101 -0
  627. package/node_modules/@noble/hashes/pbkdf2.js.map +1 -0
  628. package/node_modules/@noble/hashes/ripemd160.d.ts +13 -0
  629. package/node_modules/@noble/hashes/ripemd160.d.ts.map +1 -0
  630. package/node_modules/@noble/hashes/ripemd160.js +16 -0
  631. package/node_modules/@noble/hashes/ripemd160.js.map +1 -0
  632. package/node_modules/@noble/hashes/scrypt.d.ts +34 -0
  633. package/node_modules/@noble/hashes/scrypt.d.ts.map +1 -0
  634. package/node_modules/@noble/hashes/scrypt.js +232 -0
  635. package/node_modules/@noble/hashes/scrypt.js.map +1 -0
  636. package/node_modules/@noble/hashes/sha1.d.ts +11 -0
  637. package/node_modules/@noble/hashes/sha1.d.ts.map +1 -0
  638. package/node_modules/@noble/hashes/sha1.js +14 -0
  639. package/node_modules/@noble/hashes/sha1.js.map +1 -0
  640. package/node_modules/@noble/hashes/sha2.d.ts +159 -0
  641. package/node_modules/@noble/hashes/sha2.d.ts.map +1 -0
  642. package/node_modules/@noble/hashes/sha2.js +384 -0
  643. package/node_modules/@noble/hashes/sha2.js.map +1 -0
  644. package/node_modules/@noble/hashes/sha256.d.ts +20 -0
  645. package/node_modules/@noble/hashes/sha256.d.ts.map +1 -0
  646. package/node_modules/@noble/hashes/sha256.js +23 -0
  647. package/node_modules/@noble/hashes/sha256.js.map +1 -0
  648. package/node_modules/@noble/hashes/sha3-addons.d.ts +142 -0
  649. package/node_modules/@noble/hashes/sha3-addons.d.ts.map +1 -0
  650. package/node_modules/@noble/hashes/sha3-addons.js +402 -0
  651. package/node_modules/@noble/hashes/sha3-addons.js.map +1 -0
  652. package/node_modules/@noble/hashes/sha3.d.ts +53 -0
  653. package/node_modules/@noble/hashes/sha3.d.ts.map +1 -0
  654. package/node_modules/@noble/hashes/sha3.js +239 -0
  655. package/node_modules/@noble/hashes/sha3.js.map +1 -0
  656. package/node_modules/@noble/hashes/sha512.d.ts +26 -0
  657. package/node_modules/@noble/hashes/sha512.d.ts.map +1 -0
  658. package/node_modules/@noble/hashes/sha512.js +29 -0
  659. package/node_modules/@noble/hashes/sha512.js.map +1 -0
  660. package/node_modules/@noble/hashes/src/_assert.ts +22 -0
  661. package/node_modules/@noble/hashes/src/_blake.ts +50 -0
  662. package/node_modules/@noble/hashes/src/_md.ts +176 -0
  663. package/node_modules/@noble/hashes/src/_u64.ts +91 -0
  664. package/node_modules/@noble/hashes/src/argon2.ts +497 -0
  665. package/node_modules/@noble/hashes/src/blake1.ts +534 -0
  666. package/node_modules/@noble/hashes/src/blake2.ts +486 -0
  667. package/node_modules/@noble/hashes/src/blake2b.ts +10 -0
  668. package/node_modules/@noble/hashes/src/blake2s.ts +20 -0
  669. package/node_modules/@noble/hashes/src/blake3.ts +272 -0
  670. package/node_modules/@noble/hashes/src/crypto.ts +9 -0
  671. package/node_modules/@noble/hashes/src/cryptoNode.ts +15 -0
  672. package/node_modules/@noble/hashes/src/eskdf.ts +187 -0
  673. package/node_modules/@noble/hashes/src/hkdf.ts +88 -0
  674. package/node_modules/@noble/hashes/src/hmac.ts +94 -0
  675. package/node_modules/@noble/hashes/src/index.ts +31 -0
  676. package/node_modules/@noble/hashes/src/legacy.ts +293 -0
  677. package/node_modules/@noble/hashes/src/pbkdf2.ts +122 -0
  678. package/node_modules/@noble/hashes/src/ripemd160.ts +12 -0
  679. package/node_modules/@noble/hashes/src/scrypt.ts +257 -0
  680. package/node_modules/@noble/hashes/src/sha1.ts +10 -0
  681. package/node_modules/@noble/hashes/src/sha2.ts +402 -0
  682. package/node_modules/@noble/hashes/src/sha256.ts +24 -0
  683. package/node_modules/@noble/hashes/src/sha3-addons.ts +499 -0
  684. package/node_modules/@noble/hashes/src/sha3.ts +258 -0
  685. package/node_modules/@noble/hashes/src/sha512.ts +34 -0
  686. package/node_modules/@noble/hashes/src/utils.ts +395 -0
  687. package/node_modules/@noble/hashes/utils.d.ts +161 -0
  688. package/node_modules/@noble/hashes/utils.d.ts.map +1 -0
  689. package/node_modules/@noble/hashes/utils.js +313 -0
  690. package/node_modules/@noble/hashes/utils.js.map +1 -0
  691. package/package.json +179 -8
  692. package/schemas/catalog.schema.json +357 -0
  693. package/src/align.ts +239 -0
  694. package/src/audio-init-parser.ts +189 -0
  695. package/src/audio-ring-buffer.ts +120 -0
  696. package/src/authored-timing.ts +63 -0
  697. package/src/block-policy.ts +903 -0
  698. package/src/carp-catalog.ts +1065 -0
  699. package/src/catalog-fec-params.ts +729 -0
  700. package/src/catalog-network-source.ts +74 -0
  701. package/src/catalog-validator.ts +34 -0
  702. package/src/cmaf-block-assembler.ts +1255 -0
  703. package/src/cmaf-group-batcher.ts +104 -0
  704. package/src/cmcd-producer.ts +329 -0
  705. package/src/codec-utils.ts +1984 -0
  706. package/src/conceal-timeline.ts +293 -0
  707. package/src/delivery-gap.ts +147 -0
  708. package/src/duplicate-ledger.ts +372 -0
  709. package/src/fec-codec.ts +61 -0
  710. package/src/fec-manager.ts +4298 -0
  711. package/src/fec-starvation-detector.ts +128 -0
  712. package/src/fec-state.ts +219 -0
  713. package/src/fec-worker-setup.ts +283 -0
  714. package/src/fmp4-completion.ts +47 -0
  715. package/src/fmp4-reader.ts +112 -0
  716. package/src/index.ts +590 -21
  717. package/src/iso-block-locator.ts +329 -0
  718. package/src/iso-bmff-timing.ts +813 -0
  719. package/src/loc.ts +128 -154
  720. package/src/manifest-auth-plan.ts +107 -0
  721. package/src/media-router.ts +841 -0
  722. package/src/mfu-reassembler.ts +3480 -155
  723. package/src/mfu-reassembly-policy.ts +134 -0
  724. package/src/mmtp-container-parser.ts +2380 -0
  725. package/src/mmtp-decode-pipeline.ts +406 -0
  726. package/src/mmtp-router.ts +4860 -0
  727. package/src/mmtp-to-cmaf.ts +977 -0
  728. package/src/multicast-auth-catalog.ts +340 -0
  729. package/src/multicast-input.ts +793 -0
  730. package/src/multicast-manager.ts +2783 -0
  731. package/src/multicast-transport.ts +1058 -0
  732. package/src/multicast-unwrap.ts +132 -0
  733. package/src/no-modules.ts +21 -0
  734. package/src/phase14-catalog-override.ts +336 -0
  735. package/src/repair-fetch.ts +772 -0
  736. package/src/repair-layers.ts +533 -0
  737. package/src/sample-combiner.ts +938 -0
  738. package/src/signaling.ts +78 -0
  739. package/src/source-auth.ts +1 -0
  740. package/src/switching-set-alignment.ts +109 -0
  741. package/src/timestamp-codec.ts +265 -0
  742. package/src/track-pipeline-setup.ts +205 -0
  743. package/src/track-pipeline.ts +332 -0
  744. package/src/track-session.ts +1010 -0
  745. package/src/transport-pool.ts +128 -0
  746. package/src/wasm-mfu-reassembler.ts +405 -0
  747. package/src/wasm-mmtp-container-parser.ts +23 -0
  748. package/test-vectors/align.json +199 -0
  749. package/test-vectors/catalog/README.md +106 -0
  750. package/test-vectors/catalog/negative/archive-origin-with-path.json +33 -0
  751. package/test-vectors/catalog/negative/archive-unknown-field.json +34 -0
  752. package/test-vectors/catalog/negative/fec-block-profile-missing.json +51 -0
  753. package/test-vectors/catalog/negative/fec-block-profile-unknown.json +52 -0
  754. package/test-vectors/catalog/negative/fec-enhancement-repair-removed.json +28 -0
  755. package/test-vectors/catalog/negative/fec-repair-layer-geometry.json +33 -0
  756. package/test-vectors/catalog/negative/fec-repair-layer-missing-symbols.json +31 -0
  757. package/test-vectors/catalog/negative/fec-repair-multiple-depends.json +32 -0
  758. package/test-vectors/catalog/negative/fec-repair-overlay-with-layer.json +34 -0
  759. package/test-vectors/catalog/negative/fec-repair-priority-out-of-band.json +24 -0
  760. package/test-vectors/catalog/negative/fec-repair-source-symbols-without-scope.json +33 -0
  761. package/test-vectors/catalog/negative/legacy-selection-params.json +15 -0
  762. package/test-vectors/catalog/negative/media-track-repair-layer.json +16 -0
  763. package/test-vectors/catalog/negative/missing-mmtp-fields.json +12 -0
  764. package/test-vectors/catalog/negative/multicast-auth-padded-key.json +37 -0
  765. package/test-vectors/catalog/negative/multicast-auth-reused-track-format.json +53 -0
  766. package/test-vectors/catalog/negative/multicast-auth-trailing-pad-bits.json +37 -0
  767. package/test-vectors/catalog/negative/multicast-endpoint-missing-protocol-and-source.json +24 -0
  768. package/test-vectors/catalog/negative/multicast-network-source-empty.json +44 -0
  769. package/test-vectors/catalog/negative/multicast-packet-id-signaling.json +26 -0
  770. package/test-vectors/catalog/negative/network-source-object.json +25 -0
  771. package/test-vectors/catalog/negative/raptorq-source-symbols-over-max.json +24 -0
  772. package/test-vectors/catalog/negative/raptorq-unaligned-symbol.json +27 -0
  773. package/test-vectors/catalog/negative/repair-track-legacy-shape.json +19 -0
  774. package/test-vectors/catalog/negative/track-role-empty.json +16 -0
  775. package/test-vectors/catalog/negative/track-role-non-string.json +16 -0
  776. package/test-vectors/catalog/positive/archive-origin.json +34 -0
  777. package/test-vectors/catalog/positive/fec-iso-ssbg1.json +52 -0
  778. package/test-vectors/catalog/positive/fec-layered-repair.json +106 -0
  779. package/test-vectors/catalog/positive/fec-multicast.json +52 -0
  780. package/test-vectors/catalog/positive/flat-av.json +30 -0
  781. package/test-vectors/catalog/positive/multicast-auth-rotation.json +55 -0
  782. package/test-vectors/catalog/positive/multicast-native-ssm-no-network-source.json +43 -0
  783. package/test-vectors/catalog/positive/ticks-and-mixed-timescales.json +39 -0
  784. package/test-vectors/catalog/positive/track-role.json +49 -0
  785. package/test-vectors/catalog/releases/moqcast-native-v16-v1/catalog.json +65 -0
  786. package/test-vectors/catalog/releases/moqcast-native-v16-v1.archive.sha256 +1 -0
  787. package/test-vectors/catalog-multicast-auth-v1.json +26 -0
  788. package/test-vectors/catalog-validation.json +732 -0
  789. package/test-vectors/catalog-validator-public-api.mjs +25 -0
  790. package/test-vectors/generate-source-auth-fixture.mjs +114 -0
  791. package/test-vectors/hevc-x265-repeat-headers-v1.json +40 -0
  792. package/test-vectors/source-auth-v1.json +61 -0
  793. package/test-vectors/source-contiguity-v1.json +131 -0
  794. package/test-vectors/subsample-placement-v1.json +230 -0
  795. package/dist/mmtp.d.ts +0 -73
  796. package/dist/mmtp.d.ts.map +0 -1
  797. package/dist/mmtp.js +0 -210
  798. package/dist/mmtp.js.map +0 -1
  799. package/src/mmtp.ts +0 -277
@@ -0,0 +1,793 @@
1
+ // Module-local ambient: `multicastFromEnv` reads `process.env` when present
2
+ // (Node, FFI host) and falls back to `{}` in browser contexts. The package
3
+ // targets both, so we don't pull in `@types/node` org-wide — declaring the
4
+ // minimal surface we touch keeps the dependency graph tight and the
5
+ // published .d.ts free of node-isms.
6
+ declare const process: { env: Record<string, string | undefined> } | undefined;
7
+
8
+ /**
9
+ * Multicast catalog input contract — validator + builder.
10
+ *
11
+ * Per draft-ramadan-moq-multicast-00 §3 + §4.1, the publisher (FFmpeg,
12
+ * cast bridge, GStreamer, OBS-bridge) populates `multicast.endpoints[]`
13
+ * in the catalog when its output includes a UDP multicast destination.
14
+ *
15
+ * This module is the TypeScript-side validator over a versioned input
16
+ * shape. Sister-language validators (FFmpeg C, cast Rust) target the
17
+ * same invariants — eventually via a shared JSON Schema + fixtures
18
+ * (BLO-3341 follow-up); today parity is enforced by code review against
19
+ * 1:1 ports. Each publisher's integration MUST also assert that the
20
+ * declared `(sourceAddress, groupAddress, port)` matches what it
21
+ * actually emits — that's a separate runtime check the helper cannot
22
+ * perform.
23
+ *
24
+ * Validation invariants (per codex review of BLO-3323 v2):
25
+ * - protocol === 'ssm' → sourceAddress REQUIRED
26
+ * - protocol === 'amt' → a catalog-level `multicast.networkSource` entry of
27
+ * type "amt" REQUIRED; its `relay` is required only for
28
+ * `discovery: "manual"` ("driad" resolves the relay at runtime).
29
+ * A per-endpoint `relayAddress` input is LIFTED into that entry and is
30
+ * never emitted onto the endpoint.
31
+ * - protocol === 'atsc3' → a catalog-level `multicast.networkSource` entry of
32
+ * type "atsc3" REQUIRED; it carries the frequency, PLP, service id and SLS
33
+ * URI, which is the only tuning information an ATSC3 receiver has.
34
+ * - protocol === 'ssm' | 'asm' → no `networkSource` entry required: a native
35
+ * join describes no alternate bearer (BLO-37926).
36
+ * - groupAddress is a valid IPv4 multicast group (224.0.0.0/4)
37
+ * or IPv6 multicast group (ff00::/8)
38
+ * - SSM groupAddress MUST be in 232.0.0.0/8 (IPv4) or ff3x::/32 (IPv6),
39
+ * where the IPv6 form requires P=1 + T=1 (the `3` nibble) AND the
40
+ * 16-bit reserved-zero second hextet per RFC 3306 §4 / RFC 4607.
41
+ * - port in 1..65535
42
+ * - tracks non-empty; per-track packetId in 1..65535
43
+ * - packetId 0 (`MMTP_SIGNALING_PACKET_ID`) is the MMTP signaling flow
44
+ * (FFmpeg `moq_mmt` sends the AL-FEC message 0x0203 on it into the same
45
+ * multicast group) and is refused for a track with its own kind,
46
+ * `signaling_packet_id`. The kind string matches cast's
47
+ * `multicast_input.rs` so the two ports report the same reason.
48
+ * - packetIds unique within an endpoint
49
+ * - (sourceAddress, groupAddress, port) tuple unique across endpoints
50
+ * - bandwidth (if present) > 0
51
+ * - validUntil (if present) is a positive unix-ms timestamp
52
+ *
53
+ * @see draft-ramadan-moq-multicast-00 §4.1
54
+ * @see .planning/drafts/blo-3323-multicast-catalog-source-of-truth.md
55
+ */
56
+
57
+ import { MMTP_PACKET_ID_MAX, MMTP_SIGNALING_PACKET_ID } from "@blockcast/mmt-base";
58
+ import {
59
+ type AmtDiscovery,
60
+ type MulticastCatalogConfig,
61
+ type MulticastEndpoint,
62
+ type MulticastProtocol,
63
+ type MulticastTrackObject,
64
+ type NetworkSource,
65
+ } from "./carp-catalog.js";
66
+
67
+ /**
68
+ * Strict typed input for one multicast endpoint. The publisher provides
69
+ * this shape (env vars / CLI / config record), the helper validates and
70
+ * lifts it into a `MulticastEndpoint` ready to embed in the catalog.
71
+ */
72
+ export interface MulticastEndpointInput {
73
+ readonly protocol: MulticastProtocol;
74
+ readonly sourceAddress?: string;
75
+ readonly groupAddress: string;
76
+ readonly port: number;
77
+ /** New emitters MUST use the object form (name + packetId). */
78
+ readonly tracks: ReadonlyArray<MulticastTrackObject>;
79
+ /**
80
+ * AMT relay for this endpoint.
81
+ *
82
+ * Publisher-side input only — it is LIFTED into the catalog-level
83
+ * `multicast.networkSource` and is never written onto the emitted endpoint
84
+ * (the normative endpoint model carries no relay field). Because
85
+ * `networkSource` is catalog-level, a relay that differs from the catalog's
86
+ * AMT relay cannot be expressed and is rejected with `conflicting_amt_relay`.
87
+ *
88
+ * Prefer declaring `MulticastInput.networkSource` directly.
89
+ */
90
+ readonly relayAddress?: string;
91
+ /** Aggregate bandwidth in bits per second. RECOMMENDED per draft §4.1. */
92
+ readonly bandwidth?: number;
93
+ }
94
+
95
+ /**
96
+ * Strict typed input for the catalog-level multicast extension.
97
+ *
98
+ * `version` (monotonic) + `validUntil` (unix ms) support the catalog
99
+ * freshness model: subscribers refetch before expiry, and publishers
100
+ * MUST republish (with bumped `version`) on any endpoint mutation.
101
+ */
102
+ export interface MulticastInput {
103
+ readonly enabled?: boolean;
104
+ readonly endpoints: ReadonlyArray<MulticastEndpointInput>;
105
+ /**
106
+ * Canonical relay/tuning declaration (draft-ramadan-moq-multicast §4.1).
107
+ * When omitted, one is derived from `amtFallback` and any endpoint
108
+ * `relayAddress`; when present no derivation happens. Either way every entry
109
+ * is validated, and an endpoint `relayAddress` it does not carry is
110
+ * rejected (`conflicting_amt_relay`). Omit it entirely for native
111
+ * multicast: it describes alternate bearers only (BLO-37926).
112
+ */
113
+ readonly networkSource?: ReadonlyArray<NetworkSource>;
114
+ /** @deprecated Lifted into `networkSource`; no longer emitted. */
115
+ readonly amtFallback?: { readonly discovery: AmtDiscovery; readonly relayDns?: string };
116
+ readonly version?: number;
117
+ readonly validUntil?: number;
118
+ }
119
+
120
+ export type MulticastInputErrorKind =
121
+ | "empty_endpoints"
122
+ /**
123
+ * `endpoints` was not an array at all. Distinct from `empty_endpoints`,
124
+ * which reports a well-formed array that declares nothing: a caller
125
+ * handling these programmatically needs "you passed the wrong shape"
126
+ * apart from "you passed nothing".
127
+ */
128
+ | "invalid_endpoints"
129
+ | "ssm_requires_source"
130
+ /**
131
+ * Deliberately overloaded, unlike its one-site mirror
132
+ * `atsc3_requires_tuning`: an AMT relay can be missing at two layers, and
133
+ * both mean "this endpoint names a relay nobody can reach". Raised for an
134
+ * `amt` endpoint with no `networkSource` entry of type `"amt"`, and for an
135
+ * entry whose `discovery: "manual"` names no `relay`. Splitting them would
136
+ * make callers handle two kinds for one operator-visible fault.
137
+ */
138
+ | "amt_requires_relay"
139
+ /**
140
+ * An `atsc3` endpoint with no `networkSource` entry of type `"atsc3"`. The
141
+ * ATSC3 entry carries the frequency, PLP, service id and SLS URI — the only
142
+ * tuning information there is — so without it the endpoint names a broadcast
143
+ * nobody can tune to. The AMT mirror of this is `amt_requires_relay`; native
144
+ * joins ("ssm", "asm") describe no bearer and are exempt (BLO-37926).
145
+ */
146
+ | "atsc3_requires_tuning"
147
+ /**
148
+ * An endpoint `relayAddress` is not the relay of any AMT `networkSource`
149
+ * entry (another endpoint's relay, `amtFallback.relayDns`, or an explicit
150
+ * entry won). `networkSource` is catalog-level, so per-endpoint relays
151
+ * cannot be represented; fail closed rather than silently drop one.
152
+ */
153
+ | "conflicting_amt_relay"
154
+ /**
155
+ * A `networkSource` AMT entry's `discovery` was not `"driad"` or `"manual"`,
156
+ * the schema enum. Checked on explicit and derived entries alike.
157
+ */
158
+ | "invalid_amt_discovery"
159
+ /**
160
+ * A `networkSource` entry the schema rejects: unknown `type`, a key outside
161
+ * its `type`'s shape, a blank `relay`, or an out-of-range ATSC3 field.
162
+ */
163
+ | "invalid_network_source"
164
+ | "invalid_group_address"
165
+ | "ssm_group_out_of_range"
166
+ | "invalid_port"
167
+ | "empty_tracks"
168
+ | "invalid_track_name"
169
+ | "invalid_packet_id"
170
+ /**
171
+ * A track advertised on `MMTP_SIGNALING_PACKET_ID` (0), the MMTP signaling
172
+ * flow. Distinct from `invalid_packet_id` so the reason is legible: 0 is a
173
+ * well-formed 16-bit value, it is just not a track's to claim.
174
+ */
175
+ | "signaling_packet_id"
176
+ | "duplicate_packet_id"
177
+ | "duplicate_endpoint_tuple"
178
+ | "invalid_bandwidth"
179
+ | "invalid_valid_until"
180
+ | "invalid_version"
181
+ | "invalid_env_shape";
182
+
183
+ export class MulticastInputError extends Error {
184
+ constructor(
185
+ public readonly kind: MulticastInputErrorKind,
186
+ public readonly endpointIndex: number | null,
187
+ message: string,
188
+ ) {
189
+ super(message);
190
+ this.name = "MulticastInputError";
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Validate a typed publisher input and lift it into a
196
+ * `MulticastCatalogConfig` ready for `catalog.multicast = …`.
197
+ *
198
+ * Throws `MulticastInputError` on any invariant violation. Fail-fast
199
+ * at config-load time, never at runtime — silent fallbacks hide bugs
200
+ * upstream (per the project's "no anti-patterns" directive).
201
+ */
202
+ export function multicastFromConfig(input: MulticastInput): MulticastCatalogConfig {
203
+ // Both array-valued inputs are checked here, before anything indexes them.
204
+ // These helpers are consumed out-of-tree from plain JS (see
205
+ // `validateNetworkSourceEntry`), so the declared types are no guarantee —
206
+ // and object-instead-of-array is the likely mistake on both: `amtFallback`,
207
+ // which `networkSource` replaces, was a bare object. Without these a wrong
208
+ // shape escapes as a raw `TypeError` from `.map`, which a caller catching
209
+ // `MulticastInputError` does not catch.
210
+ if (!Array.isArray(input.endpoints)) {
211
+ throw new MulticastInputError(
212
+ "invalid_endpoints",
213
+ null,
214
+ `endpoints must be an array of endpoint objects; got ${typeof input.endpoints}`,
215
+ );
216
+ }
217
+ if (input.networkSource !== undefined && !Array.isArray(input.networkSource)) {
218
+ throw new MulticastInputError(
219
+ "invalid_network_source",
220
+ null,
221
+ "networkSource must be an array of entries; got " +
222
+ `${typeof input.networkSource} — a single entry still goes in a one-element array`,
223
+ );
224
+ }
225
+ if (input.endpoints.length === 0) {
226
+ throw new MulticastInputError(
227
+ "empty_endpoints",
228
+ null,
229
+ "endpoints[] must be non-empty — a multicast field with zero endpoints declares nothing",
230
+ );
231
+ }
232
+ if (input.version !== undefined && (!Number.isInteger(input.version) || input.version < 0)) {
233
+ throw new MulticastInputError("invalid_version", null, `version must be a non-negative integer; got ${input.version}`);
234
+ }
235
+ if (input.validUntil !== undefined) {
236
+ if (!Number.isFinite(input.validUntil) || input.validUntil <= 0) {
237
+ throw new MulticastInputError(
238
+ "invalid_valid_until",
239
+ null,
240
+ `validUntil must be a positive unix-ms timestamp; got ${input.validUntil}`,
241
+ );
242
+ }
243
+ }
244
+
245
+ const seenTuples = new Set<string>();
246
+ const endpoints: MulticastEndpoint[] = input.endpoints.map((ep, idx) => validateEndpoint(ep, idx, seenTuples));
247
+
248
+ const out: MulticastCatalogConfig = { endpoints };
249
+ const { entries: networkSource, relayFrom } = resolveNetworkSource(input);
250
+ // Checked on the resolved array, so an explicit `input.networkSource` gets
251
+ // exactly the same checks as one derived from the deprecated inputs.
252
+ networkSource.forEach(validateNetworkSourceEntry);
253
+ if (networkSource.length > 0) out.networkSource = networkSource;
254
+
255
+ // A relay the emitted catalog would not carry fails closed, on both paths:
256
+ // `networkSource` is catalog-level, so a per-endpoint relay that differs from
257
+ // it (another endpoint's, `amtFallback.relayDns`, or an explicit entry) would
258
+ // otherwise be dropped silently and that endpoint joins the wrong relay.
259
+ //
260
+ // A DRIAD entry does not count: both readers skip it, so its `relay` is a
261
+ // discovery hint, not a relay the catalog carries. Without this the derived
262
+ // path merges `amtFallback: {discovery: "driad"}` with an endpoint's
263
+ // `relayAddress` into a driad entry holding that relay, the check passes, and
264
+ // the join silently falls through to DRIAD -- where the explicit form of the
265
+ // same input already fails closed here.
266
+ const amtRelays = new Set(
267
+ networkSource
268
+ .flatMap((s) => (s.type === "amt" && s.discovery !== "driad" && s.relay?.trim() ? [s.relay.trim()] : []))
269
+ // Only the first, because it is the only one either reader can
270
+ // deliver: `catalogAmtNetworkSource` returns on it and `findAmtRelay`
271
+ // uses `.find`. Collecting every entry accepts an endpoint naming a
272
+ // second manual entry, which then joins the first -- the same silent
273
+ // wrong-relay join this guard exists to prevent, through the one
274
+ // shape the DRIAD filter does not cover. It also keeps the `(...)`
275
+ // listing below honest. Sliced rather than `.find`ed so the `amt`
276
+ // narrowing stays inside the callback.
277
+ .slice(0, 1),
278
+ );
279
+ input.endpoints.forEach((ep, idx) => {
280
+ const relay = ep.relayAddress?.trim();
281
+ if (!relay || amtRelays.has(relay)) return;
282
+ // Two different causes reach this throw and they need different fixes.
283
+ // If a DRIAD entry carries this exact relay, the catalog is not missing
284
+ // it -- the entry is present and demoted, so reporting the set as
285
+ // "(none)" sends the operator looking for an entry they already wrote.
286
+ // Name the demotion and the two-entry shape that escapes it; both
287
+ // readers take the first non-DRIAD AMT entry
288
+ // (`catalog-network-source.ts` `catalogAmtNetworkSource`,
289
+ // `multicast-catalog-policy.ts` `findAmtRelay`) and
290
+ // `validateNetworkSourceEntry` has no duplicate-type rule, so a manual
291
+ // entry beside the DRIAD one is joined while the DRIAD one is kept.
292
+ const demoted = networkSource.some(
293
+ (s) => s.type === "amt" && s.discovery === "driad" && s.relay?.trim() === relay,
294
+ );
295
+ // Same "written down but undeliverable" family as `demoted`, different
296
+ // reason and so a different fix: there the entry is skipped for its
297
+ // discovery, here for its position. Reachable only on the explicit
298
+ // path -- `resolveNetworkSource` emits at most one entry -- so there is
299
+ // no provenance clause to add, and saying "is not the relay of any AMT
300
+ // entry" here would be plainly false: the operator can see the entry.
301
+ // `amtRelays` holds only the first joinable relay, so reaching this
302
+ // throw at all already means this one is not it.
303
+ const shadowed = networkSource.some(
304
+ (s) => s.type === "amt" && s.discovery !== "driad" && s.relay?.trim() === relay,
305
+ );
306
+ // The derived and env paths never wrote `networkSource` at all -- it was
307
+ // synthesised below in `resolveNetworkSource` -- so naming only that key
308
+ // would name the one field the operator did not set. This applies to
309
+ // EVERY cause that reaches this throw, not just the demoted one: the
310
+ // clause belongs in the shared prefix, or the arm that omits it
311
+ // reproduces the misdiagnosis the other arm was written to fix.
312
+ //
313
+ // The two arms are about different values, so they name different
314
+ // fields. The demoted arm is about `discovery`: a derived entry is only
315
+ // `"driad"` when `amtFallback.discovery` said so (the default is
316
+ // `"manual"`), so `amtFallback` is always the actionable field there.
317
+ // The set clause is about the *relay*, which `resolveNetworkSource`
318
+ // takes from `amtFallback.relayDns` or from the endpoint
319
+ // `relayAddress` values -- and saying "amtFallback" to an operator who
320
+ // never wrote one is the same defect one level down. Read that source
321
+ // from `relayFrom` rather than re-inferring it: three review rounds
322
+ // found a local re-inference here drifting from the rule above it.
323
+ const derived = input.networkSource === undefined;
324
+ const fromAmtFallback = ", derived from amtFallback/MOQCAST_MULTICAST_AMT_*";
325
+ const fromRelay =
326
+ relayFrom === "amtFallback.relayDns"
327
+ ? fromAmtFallback
328
+ : relayFrom === "endpoint.relayAddress"
329
+ ? ", derived from the endpoint relayAddress values"
330
+ : "";
331
+ // `resolveNetworkSource` lets `relayDns` outrank an endpoint relay, so on
332
+ // the derived path the set can be non-empty and still not hold this
333
+ // relay. Blaming per-endpoint representation there is wrong twice over:
334
+ // there may be only one endpoint, and the field that actually won is
335
+ // `relayDns`, which is the one the operator can act on. Asking
336
+ // `amtRelays` instead would miss the case where the winning entry is
337
+ // `discovery: "driad"` and so filtered out of that set entirely.
338
+ const relayDns = input.amtFallback?.relayDns?.trim();
339
+ const outranked = relayFrom === "amtFallback.relayDns" && relayDns !== relay;
340
+ throw new MulticastInputError(
341
+ "conflicting_amt_relay",
342
+ idx,
343
+ `endpoint[${idx}] relayAddress ${JSON.stringify(relay)} ` +
344
+ (demoted
345
+ ? `is carried only by a multicast.networkSource AMT entry with discovery="driad"` +
346
+ `${derived ? fromAmtFallback : ""}, ` +
347
+ "whose relay is a DRIAD discovery hint that both readers skip, so the catalog names " +
348
+ "no relay to join; to join it, add a manual entry beside the driad one: " +
349
+ `[{type:"amt",discovery:"manual",relay:${JSON.stringify(relay)}},{type:"amt",discovery:"driad"}]`
350
+ : shadowed
351
+ ? `is carried by a multicast.networkSource AMT entry that is not the first one: ` +
352
+ `both readers join the first AMT entry (${[...amtRelays].join(", ")}) and ignore ` +
353
+ "the rest, so this relay is never joined; keep a single AMT entry, or put this one first"
354
+ : `is not the relay of any multicast.networkSource AMT entry ` +
355
+ `(${[...amtRelays].join(", ") || "none"})${fromRelay}; ` +
356
+ (outranked
357
+ ? `amtFallback.relayDns/MOQCAST_MULTICAST_AMT_RELAY_DNS (${relayDns}) outranks an ` +
358
+ "endpoint relay when networkSource is derived -- drop one, or make them agree"
359
+ : "networkSource is catalog-level and cannot represent per-endpoint relays")),
360
+ );
361
+ });
362
+
363
+ // A bearer endpoint must name its bearer. The two bearer protocols are
364
+ // exactly the two `networkSource` types, so an endpoint's own protocol names
365
+ // the entry it requires. Native joins ("ssm", "asm") describe no bearer and
366
+ // are exempt (BLO-37926) — the endpoint tuple is the whole join.
367
+ // Whether an AMT entry needs a relay string ("manual" does, "driad" does
368
+ // not) is per-entry, checked above.
369
+ input.endpoints.forEach((ep, idx) => {
370
+ if (ep.protocol !== "amt" && ep.protocol !== "atsc3") return;
371
+ if (networkSource.some((s) => s.type === ep.protocol)) return;
372
+ throw new MulticastInputError(
373
+ ep.protocol === "amt" ? "amt_requires_relay" : "atsc3_requires_tuning",
374
+ idx,
375
+ `endpoint[${idx}] protocol=${ep.protocol} requires a multicast.networkSource entry of ` +
376
+ `type "${ep.protocol}"` +
377
+ (ep.protocol === "atsc3"
378
+ ? " carrying frequency, plpId, serviceId and slsUri — an ATSC3 endpoint is not tunable without them"
379
+ : ""),
380
+ );
381
+ });
382
+
383
+ if (input.enabled !== undefined) out.enabled = input.enabled;
384
+ if (input.version !== undefined) out.version = input.version;
385
+ if (input.validUntil !== undefined) out.validUntil = input.validUntil;
386
+ return out;
387
+ }
388
+
389
+ /**
390
+ * Build the catalog-level `multicast.networkSource` for this input.
391
+ *
392
+ * An explicit `input.networkSource` is authoritative and used as given.
393
+ * Otherwise one AMT entry is derived from the deprecated inputs it replaces:
394
+ * `amtFallback.discovery`/`relayDns` and any endpoint `relayAddress`;
395
+ * `discovery` defaults to `"manual"` because a relay named in the catalog is,
396
+ * by definition, not discovered. Endpoint relays that disagree with the result
397
+ * are rejected by `multicastFromConfig`, not resolved here.
398
+ *
399
+ * `relayFrom` reports which deprecated input supplied the derived relay, so
400
+ * that rejection can name a field the operator actually set instead of
401
+ * re-deciding the precedence below at the throw site. It is `null` on the
402
+ * explicit path and when no relay was derived at all.
403
+ */
404
+ function resolveNetworkSource(input: MulticastInput): {
405
+ entries: NetworkSource[];
406
+ relayFrom: "amtFallback.relayDns" | "endpoint.relayAddress" | null;
407
+ } {
408
+ if (input.networkSource !== undefined) {
409
+ return { entries: input.networkSource.map((s) => ({ ...s })), relayFrom: null };
410
+ }
411
+
412
+ const relayDns = input.amtFallback?.relayDns?.trim();
413
+ const relay = relayDns || input.endpoints.map((ep) => ep.relayAddress?.trim()).find((r) => !!r);
414
+ const discovery = input.amtFallback?.discovery ?? (relay ? "manual" : undefined);
415
+ if (discovery === undefined) return { entries: [], relayFrom: null };
416
+ return {
417
+ entries: [{ type: "amt", discovery, ...(relay ? { relay } : {}) }],
418
+ relayFrom: !relay ? null : relayDns ? "amtFallback.relayDns" : "endpoint.relayAddress",
419
+ };
420
+ }
421
+
422
+ const AMT_SOURCE_KEYS = new Set(["type", "discovery", "relay", "port"]);
423
+ const ATSC3_SOURCE_KEYS = new Set(["type", "frequency", "plpId", "serviceId", "slsUri"]);
424
+
425
+ /**
426
+ * One `networkSource[]` entry against `catalog.schema.json` `$defs/networkSource`
427
+ * (and moq-rs `NetworkSource`), plus the one semantic rule the schema leaves
428
+ * out: `discovery: "manual"` names its relay. These helpers are consumed
429
+ * out-of-tree from plain JS, so the `NetworkSource` type is no guarantee.
430
+ */
431
+ function validateNetworkSourceEntry(s: NetworkSource, i: number): void {
432
+ const err = (kind: MulticastInputErrorKind, why: string) =>
433
+ new MulticastInputError(kind, null, `networkSource[${i}] ${why}`);
434
+ const keys = s?.type === "amt" ? AMT_SOURCE_KEYS : s?.type === "atsc3" ? ATSC3_SOURCE_KEYS : undefined;
435
+ if (!keys) throw err("invalid_network_source", `type must be "amt" or "atsc3"; got ${JSON.stringify(s?.type)}`);
436
+ // Definedness, not presence: `isMulticastCatalogConfig` in `carp-catalog.ts`
437
+ // already chose `=== undefined` over `in` for exactly this reason, and the
438
+ // two must agree on what "set" means. A key spread in as `undefined`
439
+ // (`{...entry, relayDns: undefined}`) is dropped by `JSON.stringify`, so the
440
+ // emitted catalog is clean and rejecting it would fail a shape that ships
441
+ // correctly.
442
+ const extra = Object.keys(s).filter((k) => !keys.has(k) && (s as Record<string, unknown>)[k] !== undefined);
443
+ if (extra.length > 0) throw err("invalid_network_source", `has keys the schema rejects: ${extra.join(", ")}`);
444
+
445
+ if (s.type === "amt") {
446
+ if (s.discovery !== "driad" && s.discovery !== "manual") {
447
+ throw err("invalid_amt_discovery", `discovery must be "driad" or "manual"; got ${JSON.stringify(s.discovery)}`);
448
+ }
449
+ if (s.relay !== undefined) {
450
+ // Canonicalize, don't just check: the conflict guard in
451
+ // `multicastFromConfig` compares `.trim()`ed values, so a padded
452
+ // explicit relay would pass the guard and then ship padded. The
453
+ // derived path (`resolveNetworkSource`) already trims, so trimming
454
+ // here is what makes both paths emit the same canonical string.
455
+ // Entries are copies by then, so this cannot mutate caller input.
456
+ const relay = typeof s.relay === "string" ? s.relay.trim() : "";
457
+ if (!relay) {
458
+ throw err("invalid_network_source", `relay must be non-blank when present; got ${JSON.stringify(s.relay)}`);
459
+ }
460
+ s.relay = relay;
461
+ }
462
+ if (s.discovery === "manual" && s.relay === undefined) {
463
+ throw err("amt_requires_relay", `discovery="manual" requires a relay ("driad" resolves it at runtime)`);
464
+ }
465
+ if (s.port !== undefined && (!Number.isInteger(s.port) || s.port < 1 || s.port > 65535)) {
466
+ throw err("invalid_port", `port must be 1..65535; got ${s.port}`);
467
+ }
468
+ return;
469
+ }
470
+ const inRange = (v: number, min: number, max: number) => Number.isInteger(v) && v >= min && v <= max;
471
+ if (!inRange(s.frequency, 1, Number.MAX_SAFE_INTEGER)) {
472
+ throw err("invalid_network_source", `frequency must be a positive integer; got ${s.frequency}`);
473
+ }
474
+ if (!inRange(s.plpId, 0, 63)) throw err("invalid_network_source", `plpId must be 0..63; got ${s.plpId}`);
475
+ if (!inRange(s.serviceId, 0, 65535)) {
476
+ throw err("invalid_network_source", `serviceId must be 0..65535; got ${s.serviceId}`);
477
+ }
478
+ if (typeof s.slsUri !== "string" || !isAbsoluteUri(s.slsUri)) {
479
+ throw err("invalid_network_source", `slsUri must be an absolute URI; got ${JSON.stringify(s.slsUri)}`);
480
+ }
481
+ }
482
+
483
+ function isAbsoluteUri(value: string): boolean {
484
+ try {
485
+ new URL(value);
486
+ return true;
487
+ } catch {
488
+ return false;
489
+ }
490
+ }
491
+
492
+ function validateEndpoint(
493
+ ep: MulticastEndpointInput,
494
+ idx: number,
495
+ seenTuples: Set<string>,
496
+ ): MulticastEndpoint {
497
+ if (ep.protocol === "ssm" && (!ep.sourceAddress || ep.sourceAddress.length === 0)) {
498
+ throw new MulticastInputError(
499
+ "ssm_requires_source",
500
+ idx,
501
+ `endpoint[${idx}] protocol=ssm requires sourceAddress`,
502
+ );
503
+ }
504
+ // NOTE: `protocol: "amt"` no longer requires a per-endpoint relay here. The
505
+ // relay is catalog-level (`multicast.networkSource`), which this function
506
+ // cannot see; `multicastFromConfig` enforces it once both halves are in hand.
507
+
508
+ if (!isMulticastGroupAddress(ep.groupAddress)) {
509
+ throw new MulticastInputError(
510
+ "invalid_group_address",
511
+ idx,
512
+ `endpoint[${idx}] groupAddress "${ep.groupAddress}" is not a valid multicast address`,
513
+ );
514
+ }
515
+ if (ep.protocol === "ssm" && !isSsmGroupAddress(ep.groupAddress)) {
516
+ throw new MulticastInputError(
517
+ "ssm_group_out_of_range",
518
+ idx,
519
+ `endpoint[${idx}] protocol=ssm requires groupAddress in 232.0.0.0/8 (IPv4) or ff3x::/32 (IPv6); got "${ep.groupAddress}"`,
520
+ );
521
+ }
522
+
523
+ if (!Number.isInteger(ep.port) || ep.port < 1 || ep.port > 65535) {
524
+ throw new MulticastInputError("invalid_port", idx, `endpoint[${idx}] port must be 1..65535; got ${ep.port}`);
525
+ }
526
+
527
+ if (ep.tracks.length === 0) {
528
+ throw new MulticastInputError("empty_tracks", idx, `endpoint[${idx}] tracks must be non-empty`);
529
+ }
530
+
531
+ const seenPids = new Set<number>();
532
+ for (const t of ep.tracks) {
533
+ if (typeof t.name !== "string" || t.name.length === 0) {
534
+ throw new MulticastInputError(
535
+ "invalid_track_name",
536
+ idx,
537
+ `endpoint[${idx}] track name must be a non-empty string`,
538
+ );
539
+ }
540
+ if (t.packetId === MMTP_SIGNALING_PACKET_ID) {
541
+ throw new MulticastInputError(
542
+ "signaling_packet_id",
543
+ idx,
544
+ `endpoint[${idx}] track "${t.name}" packetId ${t.packetId} is the MMTP signaling flow ` +
545
+ `and must not be advertised for a track; packetId must be 1..${MMTP_PACKET_ID_MAX}`,
546
+ );
547
+ }
548
+ if (!Number.isInteger(t.packetId) || t.packetId < 1 || t.packetId > MMTP_PACKET_ID_MAX) {
549
+ throw new MulticastInputError(
550
+ "invalid_packet_id",
551
+ idx,
552
+ `endpoint[${idx}] track "${t.name}" packetId must be 1..${MMTP_PACKET_ID_MAX}; got ${t.packetId}`,
553
+ );
554
+ }
555
+ if (seenPids.has(t.packetId)) {
556
+ throw new MulticastInputError(
557
+ "duplicate_packet_id",
558
+ idx,
559
+ `endpoint[${idx}] duplicate packetId ${t.packetId}`,
560
+ );
561
+ }
562
+ seenPids.add(t.packetId);
563
+ }
564
+
565
+ if (ep.bandwidth !== undefined && (!Number.isFinite(ep.bandwidth) || ep.bandwidth <= 0)) {
566
+ throw new MulticastInputError(
567
+ "invalid_bandwidth",
568
+ idx,
569
+ `endpoint[${idx}] bandwidth must be positive; got ${ep.bandwidth}`,
570
+ );
571
+ }
572
+
573
+ const tupleKey = `${ep.sourceAddress ?? ""}|${ep.groupAddress}|${ep.port}`;
574
+ if (seenTuples.has(tupleKey)) {
575
+ throw new MulticastInputError(
576
+ "duplicate_endpoint_tuple",
577
+ idx,
578
+ `endpoint[${idx}] duplicates (sourceAddress, groupAddress, port) tuple "${tupleKey}"`,
579
+ );
580
+ }
581
+ seenTuples.add(tupleKey);
582
+
583
+ const out: MulticastEndpoint = {
584
+ protocol: ep.protocol,
585
+ groupAddress: ep.groupAddress,
586
+ port: ep.port,
587
+ tracks: ep.tracks.map((t) => ({ name: t.name, packetId: t.packetId })),
588
+ };
589
+ if (ep.sourceAddress !== undefined) out.sourceAddress = ep.sourceAddress;
590
+ // `relayAddress` is deliberately NOT copied: the relay is lifted to
591
+ // catalog-level `multicast.networkSource` by `multicastFromConfig`.
592
+ if (ep.bandwidth !== undefined) out.bandwidth = ep.bandwidth;
593
+ return out;
594
+ }
595
+
596
+ function isMulticastGroupAddress(addr: string): boolean {
597
+ if (addr.includes(":")) {
598
+ // IPv6: ff00::/8. Prefix-only check; full IPv6 syntax validation
599
+ // is delegated to the OS bind() call downstream.
600
+ return /^ff[0-9a-f]{2}:/i.test(addr);
601
+ }
602
+ const m = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(addr);
603
+ if (!m) return false;
604
+ for (let i = 1; i <= 4; i++) {
605
+ const v = Number(m[i]);
606
+ if (!Number.isInteger(v) || v < 0 || v > 255) return false;
607
+ }
608
+ const first = Number(m[1]);
609
+ return first >= 224 && first <= 239;
610
+ }
611
+
612
+ function isSsmGroupAddress(addr: string): boolean {
613
+ if (addr.includes(":")) {
614
+ // SSM IPv6: ff3x::/32 per RFC 3306 §4. Requires P=1 + T=1 (the `3`
615
+ // nibble) AND the second 16-bit hextet to be all-zero (RFC 3306's
616
+ // "prefix length = 0" → next 32 bits are 0). The regex matches
617
+ // `ff3?:0000:` collapsed forms (`ff3e::`, `ff3e:0::`, `ff3e:0:`,
618
+ // `ff3e:0000:`) and rejects `ff3e:beef::1` etc.
619
+ return /^ff3[0-9a-f]:0{0,4}:/i.test(addr);
620
+ }
621
+ const m = /^(\d{1,3})\./.exec(addr);
622
+ return m !== null && Number(m[1]) === 232;
623
+ }
624
+
625
+ // Env-var helper (BLO-3337): read MOQCAST_MULTICAST_* keys and route
626
+ // through multicastFromConfig so all per-endpoint invariants apply.
627
+
628
+ /**
629
+ * Read `MOQCAST_MULTICAST_*` env vars and return a
630
+ * `MulticastCatalogConfig`. Returns `undefined` when no per-endpoint
631
+ * key is set.
632
+ *
633
+ * Env contract — per-endpoint keys take an optional non-negative index:
634
+ *
635
+ * MOQCAST_MULTICAST[_<idx>]_PROTOCOL=ssm
636
+ * MOQCAST_MULTICAST[_<idx>]_GROUP=232.1.1.1
637
+ * MOQCAST_MULTICAST[_<idx>]_PORT=5004
638
+ * MOQCAST_MULTICAST[_<idx>]_SOURCE=10.0.0.20 (required for ssm)
639
+ * MOQCAST_MULTICAST[_<idx>]_RELAY=amt.example.com (required for amt)
640
+ * MOQCAST_MULTICAST[_<idx>]_TRACKS=video:1,audio:3
641
+ * MOQCAST_MULTICAST[_<idx>]_BANDWIDTH=8000000 (optional, bps)
642
+ *
643
+ * MOQCAST_MULTICAST_AMT_DISCOVERY=driad (catalog-level)
644
+ * MOQCAST_MULTICAST_AMT_RELAY_DNS=relay.example.com (catalog-level)
645
+ *
646
+ * The unindexed form (`MOQCAST_MULTICAST_GROUP`) is exactly index 0;
647
+ * mixing it with explicit `_0_` keys is rejected as ambiguous. Indices
648
+ * need not be contiguous; observed indices are sorted ascending.
649
+ */
650
+ export function multicastFromEnv(
651
+ env: Record<string, string | undefined> = ((globalThis as { process?: { env?: Record<string, string | undefined> } })
652
+ .process?.env ?? {}) as Record<string, string | undefined>,
653
+ ): MulticastCatalogConfig | undefined {
654
+ const indices = collectMulticastIndices(env);
655
+ // An empty value is unset: `FOO=${BAR}` with BAR unset, or an empty
656
+ // configMap value, is a templating outcome, not a setting. Normalising
657
+ // here gives every test below one notion of "set". Stricter than SOURCE
658
+ // and RELAY, which gate on truthiness alone and so keep a whitespace-only
659
+ // value — deliberately, as these two decide whether AMT is declared at all.
660
+ const amtDiscovery = env["MOQCAST_MULTICAST_AMT_DISCOVERY"]?.trim() || undefined;
661
+ const amtRelayDns = env["MOQCAST_MULTICAST_AMT_RELAY_DNS"]?.trim() || undefined;
662
+ // One predicate, both guards: a key significant enough to reject at zero
663
+ // endpoints is not silently discarded once endpoints are present.
664
+ const hasCatalogAmt = amtDiscovery !== undefined || amtRelayDns !== undefined;
665
+ if (indices.length === 0) {
666
+ // Catalog-level AMT keys without per-endpoint keys is a
667
+ // misconfiguration, not a no-op: `MOQCAST_MULTICAST_AMT_DISCOVERY`
668
+ // only makes sense alongside endpoints to fall back FOR. Throw
669
+ // loudly instead of silently dropping the request — a publisher
670
+ // that meant to declare AMT fallback shouldn't have its config
671
+ // disappear without any signal.
672
+ if (hasCatalogAmt) {
673
+ throw new MulticastInputError(
674
+ "invalid_env_shape",
675
+ null,
676
+ "MOQCAST_MULTICAST_AMT_* env keys are set but no per-endpoint keys " +
677
+ "(MOQCAST_MULTICAST_GROUP / _PROTOCOL / _PORT / _TRACKS) were found. " +
678
+ "AMT discovery is a catalog-level fallback for endpoints; declaring it " +
679
+ "with zero endpoints is a misconfiguration.",
680
+ );
681
+ }
682
+ return undefined;
683
+ }
684
+
685
+ const endpoints: MulticastEndpointInput[] = indices.map((idx) => readEndpointAt(env, idx));
686
+
687
+ const input: MulticastInput = {
688
+ endpoints,
689
+ ...(hasCatalogAmt
690
+ ? {
691
+ amtFallback: {
692
+ // `"manual"` mirrors `resolveNetworkSource`: a relay named in
693
+ // the catalog is, by definition, not discovered.
694
+ discovery: (amtDiscovery ?? "manual") as AmtDiscovery,
695
+ ...(amtRelayDns ? { relayDns: amtRelayDns } : {}),
696
+ },
697
+ }
698
+ : {}),
699
+ };
700
+ return multicastFromConfig(input);
701
+ }
702
+
703
+ const ENV_PER_FIELD = ["PROTOCOL", "GROUP", "PORT", "SOURCE", "RELAY", "TRACKS", "BANDWIDTH"];
704
+ const ENV_CATALOG_LEVEL = new Set(["AMT_DISCOVERY", "AMT_RELAY_DNS"]);
705
+
706
+ function collectMulticastIndices(env: Record<string, string | undefined>): number[] {
707
+ const indices = new Set<number>();
708
+ let hasUnindexed = false;
709
+ let hasZeroIndexed = false;
710
+
711
+ for (const [key, val] of Object.entries(env)) {
712
+ if (val === undefined) continue;
713
+ if (!key.startsWith("MOQCAST_MULTICAST_")) continue;
714
+ const suffix = key.slice("MOQCAST_MULTICAST_".length);
715
+ if (ENV_CATALOG_LEVEL.has(suffix)) continue;
716
+
717
+ const m = /^(\d+)_(.+)$/.exec(suffix);
718
+ if (m) {
719
+ const idx = Number(m[1]);
720
+ const field = m[2];
721
+ if (!ENV_PER_FIELD.includes(field)) continue;
722
+ if (idx === 0) hasZeroIndexed = true;
723
+ indices.add(idx);
724
+ } else if (ENV_PER_FIELD.includes(suffix)) {
725
+ hasUnindexed = true;
726
+ indices.add(0);
727
+ }
728
+ }
729
+
730
+ if (hasUnindexed && hasZeroIndexed) {
731
+ throw new MulticastInputError(
732
+ "invalid_env_shape",
733
+ null,
734
+ "MOQCAST_MULTICAST_* env contract: cannot mix unindexed keys (MOQCAST_MULTICAST_GROUP) " +
735
+ "with explicitly-indexed keys at index 0 (MOQCAST_MULTICAST_0_GROUP) — they refer to " +
736
+ "the same endpoint. Use one form consistently.",
737
+ );
738
+ }
739
+
740
+ return [...indices].sort((a, b) => a - b);
741
+ }
742
+
743
+ function readEndpointAt(env: Record<string, string | undefined>, idx: number): MulticastEndpointInput {
744
+ const lookup = (field: string): string | undefined => {
745
+ if (idx === 0) {
746
+ return env[`MOQCAST_MULTICAST_${field}`] ?? env[`MOQCAST_MULTICAST_0_${field}`];
747
+ }
748
+ return env[`MOQCAST_MULTICAST_${idx}_${field}`];
749
+ };
750
+
751
+ const portStr = lookup("PORT");
752
+ const port = portStr !== undefined ? Number(portStr) : NaN;
753
+ const tracks = parseTracksEnv(lookup("TRACKS"), idx);
754
+ const bandwidthStr = lookup("BANDWIDTH");
755
+ const bandwidth = bandwidthStr !== undefined ? Number(bandwidthStr) : undefined;
756
+ const source = lookup("SOURCE");
757
+ const relay = lookup("RELAY");
758
+
759
+ return {
760
+ protocol: lookup("PROTOCOL") as MulticastProtocol,
761
+ groupAddress: lookup("GROUP") ?? "",
762
+ port,
763
+ tracks,
764
+ ...(source ? { sourceAddress: source } : {}),
765
+ ...(relay ? { relayAddress: relay } : {}),
766
+ ...(bandwidth !== undefined ? { bandwidth } : {}),
767
+ };
768
+ }
769
+
770
+ function parseTracksEnv(raw: string | undefined, endpointIdx: number): MulticastTrackObject[] {
771
+ if (!raw || raw.length === 0) return [];
772
+ return raw.split(",").map((entry, i) => {
773
+ const colon = entry.lastIndexOf(":");
774
+ if (colon < 0) {
775
+ throw new MulticastInputError(
776
+ "invalid_track_name",
777
+ endpointIdx,
778
+ `endpoint[${endpointIdx}] TRACKS[${i}] missing ":" — expected "name:packetId", got ${JSON.stringify(entry)}`,
779
+ );
780
+ }
781
+ const name = entry.slice(0, colon).trim();
782
+ const idStr = entry.slice(colon + 1).trim();
783
+ const packetId = Number(idStr);
784
+ if (!name || idStr.length === 0 || !Number.isFinite(packetId) || !Number.isInteger(packetId)) {
785
+ throw new MulticastInputError(
786
+ "invalid_packet_id",
787
+ endpointIdx,
788
+ `endpoint[${endpointIdx}] TRACKS[${i}] entry malformed (need "name:integer"): ${JSON.stringify(entry)}`,
789
+ );
790
+ }
791
+ return { name, packetId };
792
+ });
793
+ }