@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/mmtp-to-cmaf.ts"],
4
+ "sourcesContent": ["/**\n * MMTP \u2192 CMAF converter per draft-ramadan-moq-mmt \u00A75.3.\n *\n * Converts reassembled MFU frames (raw codec samples from MMTP) into\n * fMP4 segments (moof+mdat) suitable for MSE SourceBuffer.appendBuffer().\n *\n * MPU metadata (fragment_type=0) packets from FFmpeg are complete\n * ftyp+moov init segments and can be used directly as MSE init data.\n *\n * MFU data (fragment_type=2) contains raw AVCC samples that must be\n * wrapped in moof+mdat boxes for MSE consumption.\n *\n * ISO 14496-12 (ISOBMFF) box construction is inline \u2014 no dependencies.\n */\n\n// \u2500\u2500 ISOBMFF box helpers \u2500\u2500\n\nfunction box(type: string, ...children: Uint8Array[]): Uint8Array {\n let size = 8\n for (const c of children) size += c.length\n const buf = new Uint8Array(size)\n new DataView(buf.buffer).setUint32(0, size)\n buf[4] = type.charCodeAt(0)\n buf[5] = type.charCodeAt(1)\n buf[6] = type.charCodeAt(2)\n buf[7] = type.charCodeAt(3)\n let pos = 8\n for (const c of children) {\n buf.set(c, pos)\n pos += c.length\n }\n return buf\n}\n\nfunction fullBox(type: string, version: number, flags: number, ...children: Uint8Array[]): Uint8Array {\n let size = 12\n for (const c of children) size += c.length\n const buf = new Uint8Array(size)\n const dv = new DataView(buf.buffer)\n dv.setUint32(0, size)\n buf[4] = type.charCodeAt(0)\n buf[5] = type.charCodeAt(1)\n buf[6] = type.charCodeAt(2)\n buf[7] = type.charCodeAt(3)\n dv.setUint32(8, (version << 24) | (flags & 0xffffff))\n let pos = 12\n for (const c of children) {\n buf.set(c, pos)\n pos += c.length\n }\n return buf\n}\n\nfunction u32(v: number): Uint8Array {\n const b = new Uint8Array(4)\n new DataView(b.buffer).setUint32(0, v)\n return b\n}\n\n// \u2500\u2500 Sample flags per ISO 14496-12 \u00A78.8.3.1 \u2500\u2500\nconst KEYFRAME_FLAGS = 0x02000000\nconst DELTA_FLAGS = 0x01010000\n\n// \u2500\u2500 Track geometry field ranges per ISO 14496-12 \u2500\u2500\n// tkhd/trex/tfhd track_ID and the mdhd/mvhd timescales are all unsigned 32-bit\n// fields, written below with DataView.setUint32. That call takes the value\n// modulo 2^32 without complaint, so an out-of-range configuration does not\n// fail \u2014 it silently emits different geometry than the caller asked for\n// (trackId 2^32 becomes track 0, which no fragment can ever reference).\nconst UINT32_MAX = 0xffffffff\n// mvhd next_track_ID is emitted as track_ID + 1 by both buildVideoInitSegment\n// and buildAudioInitSegment (ISO 14496-12 \u00A78.2.2.3, \"a non-zero integer\"). At\n// track_ID = UINT32_MAX that sum wraps to 0, which is both invalid and\n// indistinguishable from an unset field, so the largest usable track_ID is one\n// below the field maximum. (Cited by symbol, not line: this repo's docs gate\n// exists because line anchors rot silently \u2014 see rustfmt.yml's citation check.)\nconst MAX_TRACK_ID = UINT32_MAX - 1\nconst INT32_MIN = -0x80000000\nconst INT32_MAX = 0x7fffffff\n\n/**\n * Fail closed on a track_ID the fMP4 writers below cannot serialize faithfully.\n *\n * Called from both low-level encoders (encodeDataSegment,\n * encodeMultiSampleSegment) so every fragment path is covered by construction\n * rather than by enumerating callers. The class wrappers and init builders call\n * it earlier as well \u2014 partly for a clearer label, partly because the encoders\n * receive an already-incremented sequence number, so their throw would gap the\n * sequence on a call that emitted nothing.\n */\nfunction assertTrackId(trackId: number, label: string): void {\n if (!Number.isInteger(trackId) || trackId <= 0 || trackId > MAX_TRACK_ID) {\n throw new RangeError(`${label} must be an integer in 1..${MAX_TRACK_ID}, got ${trackId}`)\n }\n}\n\n/** Fail closed on a timescale the mdhd/mvhd uint32 fields cannot hold. */\nfunction assertTimescale(timescale: number, label: string): void {\n if (!Number.isInteger(timescale) || timescale <= 0 || timescale > UINT32_MAX) {\n throw new RangeError(`${label} must be an integer in 1..${UINT32_MAX}, got ${timescale}`)\n }\n}\n\n/** Fail closed on a signed trun sample_composition_time_offset. */\nfunction assertCompositionTimeOffsets(\n samples: Array<{ compositionTimeOffset?: number }>,\n): void {\n for (let i = 0; i < samples.length; i++) {\n const offset = samples[i]!.compositionTimeOffset\n if (offset !== undefined &&\n (!Number.isInteger(offset) || offset < INT32_MIN || offset > INT32_MAX)) {\n throw new RangeError(\n `sample ${i} compositionTimeOffset must be an integer in ${INT32_MIN}..${INT32_MAX}, got ${offset}`,\n )\n }\n }\n}\n\n/**\n * Wrap multiple samples in a single moof+mdat fMP4 segment.\n *\n * Builds a trun with N sample entries (duration + size + flags each).\n * Used by CmafBlockAssembler to emit one segment per FEC source block.\n *\n * @param samples - Array of samples with data, duration (timescale units), keyframe flag,\n * and an optional signed composition-time offset (same timescale units)\n * @param baseDecodeTime - Decode time of the first sample in timescale units\n * @param sequence - moof sequence number\n * @param trackId - ISO track ID (default 1)\n * @returns moof+mdat bytes ready for SourceBuffer.appendBuffer()\n */\nexport function encodeMultiSampleSegment(\n samples: Array<{\n data: Uint8Array\n duration: number\n keyframe: boolean\n compositionTimeOffset?: number\n }>,\n baseDecodeTime: number,\n sequence: number,\n trackId = 1,\n): Uint8Array {\n if (samples.length === 0) return new Uint8Array(0)\n assertTrackId(trackId, 'trackId')\n assertCompositionTimeOffsets(samples)\n\n const mfhd = fullBox('mfhd', 0, 0, u32(sequence))\n const tfhd = fullBox('tfhd', 0, 0x020000, u32(trackId))\n\n // tfdt version=1 for 64-bit baseMediaDecodeTime\n const tfdtBody = new Uint8Array(8)\n const tfdtView = new DataView(tfdtBody.buffer)\n tfdtView.setUint32(0, Math.floor(baseDecodeTime / 0x100000000))\n tfdtView.setUint32(4, baseDecodeTime >>> 0)\n const tfdt = fullBox('tfdt', 1, 0, tfdtBody)\n\n // A composition-time offset is signed only in trun version 1. When one is\n // present, every sample gets the field; omitted offsets are encoded as zero.\n const hasCompositionTimeOffset = samples.some(sample => sample.compositionTimeOffset !== undefined)\n const trunVersion = hasCompositionTimeOffset ? 1 : 0\n const trunFlags = 0x000701 | (hasCompositionTimeOffset ? 0x000800 : 0)\n // 4 bytes sample_count + 4 bytes data_offset + N * (4+4+4 [+4]) per sample\n const sampleCount = samples.length\n const sampleEntrySize = hasCompositionTimeOffset ? 16 : 12\n const trunBody = new Uint8Array(8 + sampleCount * sampleEntrySize)\n const trunView = new DataView(trunBody.buffer)\n trunView.setUint32(0, sampleCount)\n trunView.setUint32(4, 0) // dataOffset placeholder\n for (let i = 0; i < sampleCount; i++) {\n const s = samples[i]!\n const off = 8 + i * sampleEntrySize\n trunView.setUint32(off, s.duration >>> 0)\n trunView.setUint32(off + 4, s.data.length)\n trunView.setUint32(off + 8, s.keyframe ? KEYFRAME_FLAGS : DELTA_FLAGS)\n if (hasCompositionTimeOffset) {\n trunView.setInt32(off + 12, s.compositionTimeOffset ?? 0)\n }\n }\n const trun = fullBox('trun', trunVersion, trunFlags, trunBody)\n\n const traf = box('traf', tfhd, tfdt, trun)\n const moof = box('moof', mfhd, traf)\n\n // Concatenate all sample data into mdat\n let mdatSize = 0\n for (const s of samples) mdatSize += s.data.length\n const mdatPayload = new Uint8Array(mdatSize)\n let pos = 0\n for (const s of samples) {\n mdatPayload.set(s.data, pos)\n pos += s.data.length\n }\n const mdat = box('mdat', mdatPayload)\n\n // Fix trun.dataOffset: moof size + 8 (mdat box header)\n const dataOffsetPos = 8 + mfhd.length + 8 + tfhd.length + tfdt.length + 12 + 4\n new DataView(moof.buffer).setUint32(dataOffsetPos, moof.length + 8)\n\n const result = new Uint8Array(moof.length + mdat.length)\n result.set(moof, 0)\n result.set(mdat, moof.length)\n return result\n}\n\n// \u2500\u2500 Green fill / silence generators \u2500\u2500\n\n/**\n * Generate a minimal H.264 IDR slice NAL for green fill (YUV 0,128,128).\n *\n * Reuses SPS/PPS from the stream's avcC so the fill frame is compatible\n * with the existing decoder configuration. Returns AVCC-framed data\n * (4-byte length prefix per NAL) ready for moof+mdat wrapping.\n *\n * @param avcC - Raw avcC payload from catalog description\n * @param width - Video width in pixels\n * @param height - Video height in pixels\n */\nexport function generateGreenFillNAL(avcC: Uint8Array, width: number, height: number): Uint8Array {\n // Parse SPS and PPS from avcC box payload\n // avcC layout: version(1) + profile(1) + compat(1) + level(1) + lengthSizeMinusOne(1)\n // + numSPS(1) + [spsLen(2) + spsData]... + numPPS(1) + [ppsLen(2) + ppsData]...\n if (avcC.length < 8) return new Uint8Array(0)\n\n const lengthSize = (avcC[4]! & 0x03) + 1 // NAL length field size (usually 4)\n let offset = 5\n const numSPS = avcC[offset++]! & 0x1f\n const nals: Uint8Array[] = []\n\n // Extract SPS NAL(s)\n for (let i = 0; i < numSPS; i++) {\n if (offset + 2 > avcC.length) break\n const spsLen = (avcC[offset]! << 8) | avcC[offset + 1]!\n offset += 2\n if (offset + spsLen > avcC.length) break\n const sps = avcC.subarray(offset, offset + spsLen)\n // AVCC frame: 4-byte length + NAL\n const framed = new Uint8Array(4 + sps.length)\n new DataView(framed.buffer).setUint32(0, sps.length)\n framed.set(sps, 4)\n nals.push(framed)\n offset += spsLen\n }\n\n // Extract PPS NAL(s)\n if (offset < avcC.length) {\n const numPPS = avcC[offset++]!\n for (let i = 0; i < numPPS; i++) {\n if (offset + 2 > avcC.length) break\n const ppsLen = (avcC[offset]! << 8) | avcC[offset + 1]!\n offset += 2\n if (offset + ppsLen > avcC.length) break\n const pps = avcC.subarray(offset, offset + ppsLen)\n const framed = new Uint8Array(4 + pps.length)\n new DataView(framed.buffer).setUint32(0, pps.length)\n framed.set(pps, 4)\n nals.push(framed)\n offset += ppsLen\n }\n }\n\n // Build minimal IDR slice NAL (NAL type 5)\n // Slice header: first_mb_in_slice=0, slice_type=7 (I), pic_parameter_set_id=0\n // Exp-Golomb coded: 0(1 bit) + 0001000(slice_type=7=I-all, ue(v)) + 1(pps_id=0, ue(v))\n // Then fill with green macroblocks.\n //\n // For a minimal valid IDR that decodes to green, we use:\n // nal_type=5 (IDR), slice_type=I, then CABAC/CAVLC all-intra-16x16\n // with luma DC=0, chroma DC=128. Exact encoding depends on SPS entropy mode.\n //\n // Simplified approach: generate a very small IDR slice that MSE will accept.\n // The slice header + minimal macroblock data. The decoder fills with the\n // predicted values which default to mid-gray/green.\n const mbWidth = Math.ceil(width / 16)\n const mbHeight = Math.ceil(height / 16)\n const totalMBs = mbWidth * mbHeight\n\n // Minimal IDR slice: nal_ref_idc=3, nal_type=5\n // Slice header bits: first_mb=0 (1 bit ue), slice_type=7 (I-all, 0001000 ue),\n // pps_id=0 (1 bit ue), frame_num=0 (depends on SPS log2_max)\n // We construct a minimal bitstream that encodes an all-skip I-slice.\n // For simplicity, build a fixed small IDR payload \u2014 the decoder will\n // pad/error-conceal remaining MBs producing a solid fill frame.\n const idrSlice = new Uint8Array([\n 0x65, // nal_ref_idc=3, nal_type=5 (IDR)\n 0x88, // slice header: first_mb_in_slice=0, slice_type=7 (I)\n 0x80, // pps_id=0, frame_num=0, idr_pic_id=0\n 0x40, // slice data: mb_skip_run covering remaining MBs\n // Truncated \u2014 decoder will error-conceal remaining MBs as green/gray\n ])\n const idrFramed = new Uint8Array(4 + idrSlice.length)\n new DataView(idrFramed.buffer).setUint32(0, idrSlice.length)\n idrFramed.set(idrSlice, 4)\n nals.push(idrFramed)\n\n // Concatenate all NALs: SPS + PPS + IDR\n let totalLen = 0\n for (const n of nals) totalLen += n.length\n const result = new Uint8Array(totalLen)\n let p = 0\n for (const n of nals) {\n result.set(n, p)\n p += n.length\n }\n return result\n}\n\n/**\n * Generate a minimal silent audio frame for FEC fill.\n *\n * Supports AAC (mp4a) and Opus codecs. Returns raw frame data (no ADTS/OBU\n * header) suitable for fMP4/CMAF wrapping.\n *\n * @param codec - Audio codec string (e.g. 'mp4a.40.2', 'opus')\n * @param sampleRate - Audio sample rate (e.g. 48000)\n * @param channels - Channel count (e.g. 1 or 2)\n */\nexport function generateSilenceFrame(codec: string, sampleRate: number, channels: number): Uint8Array {\n if (codec.startsWith('opus') || codec.startsWith('Opus')) {\n return generateSilenceOpus(channels)\n }\n return generateSilenceAAC(sampleRate, channels)\n}\n\n/** Minimal silent AAC-LC access unit (raw, no ADTS). */\nfunction generateSilenceAAC(sampleRate: number, channels: number): Uint8Array {\n if (channels >= 2) {\n // CPE (channel pair element) + END\n return new Uint8Array([\n 0x21, 0x00, 0x49, 0x90, 0x02, 0x19, 0x00, 0x23, 0x80,\n ])\n }\n // SCE (single channel element) + END\n return new Uint8Array([\n 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,\n ])\n}\n\n/** Minimal silent Opus frame.\n * RFC 6716 \u00A73.1: a 1-byte frame with code 0 encodes silence for SILK/CELT. */\nfunction generateSilenceOpus(channels: number): Uint8Array {\n // Opus TOC byte: config=0 (SILK NB 10ms), s=0 (mono/stereo from channel mapping), c=0 (1 frame)\n // Frame data: single zero byte \u2192 silence\n // For stereo, channel mapping in fMP4 init handles routing; the Opus frame itself is the same.\n return new Uint8Array([0xF8, 0xFF, 0xFE])\n}\n\nexport function normalizeAacSampleForCmaf(data: Uint8Array): Uint8Array {\n if (data.length < 7 || data[0] !== 0xff || (data[1]! & 0xf6) !== 0xf0) {\n return data\n }\n const headerLength = (data[1]! & 0x01) ? 7 : 9\n if (data.length <= headerLength) return data\n const frameLength = ((data[3]! & 0x03) << 11) | (data[4]! << 3) | ((data[5]! & 0xe0) >>> 5)\n if (frameLength !== data.length || frameLength <= headerLength) return data\n return data.subarray(headerLength)\n}\n\n/**\n * Wrap a single raw codec sample in a moof+mdat fMP4 segment.\n *\n * @param data - Raw sample bytes (AVCC H.264 or raw AAC)\n * @param timestamp - Decode time in timescale units\n * @param duration - Sample duration in timescale units\n * @param keyframe - true for IDR/sync sample\n * @param sequence - moof sequence number (monotonically incrementing)\n * @param trackId - ISO track ID (default 1)\n * @returns moof+mdat bytes ready for SourceBuffer.appendBuffer()\n */\nexport function encodeDataSegment(\n data: Uint8Array,\n timestamp: number,\n duration: number,\n keyframe: boolean,\n sequence: number,\n trackId = 1,\n compositionTimeOffset?: number,\n): Uint8Array {\n assertTrackId(trackId, 'trackId')\n assertCompositionTimeOffsets([{ compositionTimeOffset }])\n if (compositionTimeOffset !== undefined) {\n return encodeMultiSampleSegment(\n [{ data, duration, keyframe, compositionTimeOffset }],\n timestamp,\n sequence,\n trackId,\n )\n }\n const sampleFlags = keyframe ? KEYFRAME_FLAGS : DELTA_FLAGS\n\n const mfhd = fullBox('mfhd', 0, 0, u32(sequence))\n const tfhd = fullBox('tfhd', 0, 0x020000, u32(trackId))\n\n // tfdt version=1 for 64-bit baseMediaDecodeTime\n const tfdtBody = new Uint8Array(8)\n const tfdtView = new DataView(tfdtBody.buffer)\n tfdtView.setUint32(0, Math.floor(timestamp / 0x100000000))\n tfdtView.setUint32(4, timestamp >>> 0)\n const tfdt = fullBox('tfdt', 1, 0, tfdtBody)\n\n // trun: flags=0x000701 (data-offset + duration + size + flags)\n const trunBody = new Uint8Array(20)\n const trunView = new DataView(trunBody.buffer)\n trunView.setUint32(0, 1) // sample_count\n trunView.setUint32(4, 0) // dataOffset placeholder\n trunView.setUint32(8, duration >>> 0)\n trunView.setUint32(12, data.length)\n trunView.setUint32(16, sampleFlags)\n const trun = fullBox('trun', 0, 0x000701, trunBody)\n\n const traf = box('traf', tfhd, tfdt, trun)\n const moof = box('moof', mfhd, traf)\n const mdat = box('mdat', data)\n\n // Fix trun.dataOffset: moof size + 8 (mdat box header)\n const dataOffsetPos = 8 + mfhd.length + 8 + tfhd.length + tfdt.length + 12 + 4\n new DataView(moof.buffer).setUint32(dataOffsetPos, moof.length + 8)\n\n const result = new Uint8Array(moof.length + mdat.length)\n result.set(moof, 0)\n result.set(mdat, moof.length)\n return result\n}\n\n/**\n * Build an ftyp+moov init segment for H.264 video MSE from an avcC box.\n *\n * @param avcC - Raw avcC box payload (SPS/PPS configuration)\n * @param width - Video width in pixels\n * @param height - Video height in pixels\n * @param timescale - Timescale (default 1_000_000 = microseconds)\n * @param trackId - Track ID (default 1)\n */\nexport function buildVideoInitSegment(\n avcC: Uint8Array,\n width: number,\n height: number,\n timescale = 1_000_000,\n trackId = 1,\n): Uint8Array {\n // Validated here as well as in setVideoTrackParams: this builder is exported\n // from the package index, so a direct caller reaches the same uint32 tkhd /\n // trex / mdhd / mvhd fields without passing through the class.\n assertTrackId(trackId, 'video trackId')\n assertTimescale(timescale, 'video timescale')\n const ftyp = box('ftyp', new Uint8Array([\n 0x69, 0x73, 0x6f, 0x6d, 0, 0, 2, 0,\n 0x69, 0x73, 0x6f, 0x6d,\n 0x69, 0x73, 0x6f, 0x36,\n 0x6d, 0x70, 0x34, 0x31,\n ]))\n\n const avcCBox = box('avcC', avcC)\n const avc1Body = new Uint8Array(78 + avcCBox.length)\n const avc1View = new DataView(avc1Body.buffer)\n avc1View.setUint16(6, 1)\n avc1View.setUint16(24, width)\n avc1View.setUint16(26, height)\n avc1View.setUint32(28, 0x00480000)\n avc1View.setUint32(32, 0x00480000)\n avc1View.setUint16(40, 1)\n avc1View.setUint16(74, 0x0018)\n avc1View.setInt16(76, -1)\n avc1Body.set(avcCBox, 78)\n const avc1 = box('avc1', avc1Body)\n\n const stsd = fullBox('stsd', 0, 0, u32(1), avc1)\n const stbl = box('stbl', stsd,\n fullBox('stts', 0, 0, u32(0)),\n fullBox('stsc', 0, 0, u32(0)),\n fullBox('stsz', 0, 0, u32(0), u32(0)),\n fullBox('stco', 0, 0, u32(0)),\n )\n const dinf = box('dinf', fullBox('dref', 0, 0, u32(1), fullBox('url ', 0, 1)))\n const minf = box('minf', fullBox('vmhd', 0, 1), dinf, stbl)\n const hdlr = fullBox('hdlr', 0, 0, new Uint8Array([\n 0, 0, 0, 0, 0x76, 0x69, 0x64, 0x65,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n 0x56, 0x69, 0x64, 0x65, 0x6f, 0,\n ]))\n const mdhdBody = new Uint8Array(20)\n new DataView(mdhdBody.buffer).setUint32(8, timescale)\n const mdhd = fullBox('mdhd', 0, 0, mdhdBody)\n const mdia = box('mdia', mdhd, hdlr, minf)\n\n const tkhdBody = new Uint8Array(80)\n const tkhdView = new DataView(tkhdBody.buffer)\n tkhdView.setUint32(8, trackId)\n tkhdView.setUint32(36, 0x00010000)\n tkhdView.setUint32(52, 0x00010000)\n tkhdView.setUint32(64, 0x40000000)\n tkhdView.setUint32(72, width << 16)\n tkhdView.setUint32(76, height << 16)\n const tkhd = fullBox('tkhd', 0, 3, tkhdBody)\n const trak = box('trak', tkhd, mdia)\n\n const mvhdBody = new Uint8Array(96)\n const mvhdView = new DataView(mvhdBody.buffer)\n mvhdView.setUint32(8, timescale)\n mvhdView.setUint32(16, 0x00010000)\n mvhdView.setUint16(20, 0x0100)\n mvhdView.setUint32(32, 0x00010000)\n mvhdView.setUint32(48, 0x00010000)\n mvhdView.setUint32(60, 0x40000000)\n mvhdView.setUint32(92, trackId + 1)\n const mvhd = fullBox('mvhd', 0, 0, mvhdBody)\n\n const trexBody = new Uint8Array(20)\n new DataView(trexBody.buffer).setUint32(0, trackId)\n new DataView(trexBody.buffer).setUint32(4, 1)\n const mvex = box('mvex', fullBox('trex', 0, 0, trexBody))\n\n const moov = box('moov', mvhd, trak, mvex)\n const result = new Uint8Array(ftyp.length + moov.length)\n result.set(ftyp, 0)\n result.set(moov, ftyp.length)\n return result\n}\n\n/**\n * Build ftyp+moov init segment for AAC audio MSE.\n */\nexport function buildAudioInitSegment(\n sampleRate: number,\n channels: number,\n asc?: Uint8Array,\n timescale?: number,\n trackId = 1,\n): Uint8Array {\n // trackId only: this reaches the same uint32 tkhd/trex/mvhd fields as the\n // video builder. The audio *timescale* is deliberately left unchecked here \u2014\n // wrapAudioSample branches on its exact value, so constraining it belongs\n // with that path rather than in this range fix.\n assertTrackId(trackId, 'audio trackId')\n const ts = timescale ?? sampleRate\n\n if (!asc) {\n const freqTable = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350]\n const fi = freqTable.indexOf(sampleRate)\n const freqIdx = fi >= 0 ? fi : 0x0f\n if (freqIdx <= 0x0e) {\n const v = (2 << 11) | (freqIdx << 7) | (channels << 3)\n asc = new Uint8Array([(v >> 8) & 0xff, v & 0xff])\n } else {\n asc = new Uint8Array([\n (2 << 3) | 0x07,\n (0x08 | ((sampleRate >> 20) & 0x07)) & 0xff,\n (sampleRate >> 12) & 0xff,\n (sampleRate >> 4) & 0xff,\n (((sampleRate & 0x0f) << 4) | (channels << 0)) & 0xff,\n ])\n }\n }\n\n // esds: ES_Descriptor \u2192 DecoderConfigDescriptor \u2192 AudioSpecificConfig\n const dsi = new Uint8Array(2 + asc.length)\n dsi[0] = 0x05; dsi[1] = asc.length; dsi.set(asc, 2)\n const dcdBody = new Uint8Array(13 + dsi.length)\n dcdBody[0] = 0x40; dcdBody[1] = 0x15; dcdBody.set(dsi, 13)\n const dcd = new Uint8Array(2 + dcdBody.length)\n dcd[0] = 0x04; dcd[1] = dcdBody.length; dcd.set(dcdBody, 2)\n const esBody = new Uint8Array(3 + dcd.length)\n esBody[0] = 0; esBody[1] = 0x01; esBody[2] = 0; esBody.set(dcd, 3)\n const es = new Uint8Array(2 + esBody.length)\n es[0] = 0x03; es[1] = esBody.length; es.set(esBody, 2)\n const esdsBox = fullBox('esds', 0, 0, es)\n\n const mp4aBody = new Uint8Array(28 + esdsBox.length)\n const mp4aView = new DataView(mp4aBody.buffer)\n mp4aView.setUint16(6, 1)\n mp4aView.setUint16(16, channels)\n mp4aView.setUint16(18, 16)\n mp4aView.setUint32(24, sampleRate << 16)\n mp4aBody.set(esdsBox, 28)\n const mp4a = box('mp4a', mp4aBody)\n\n const stsd = fullBox('stsd', 0, 0, u32(1), mp4a)\n const stbl = box('stbl', stsd,\n fullBox('stts', 0, 0, u32(0)),\n fullBox('stsc', 0, 0, u32(0)),\n fullBox('stsz', 0, 0, u32(0), u32(0)),\n fullBox('stco', 0, 0, u32(0)),\n )\n const dinf = box('dinf', fullBox('dref', 0, 0, u32(1), fullBox('url ', 0, 1)))\n const minf = box('minf', fullBox('smhd', 0, 0, new Uint8Array(4)), dinf, stbl)\n const hdlr = fullBox('hdlr', 0, 0, new Uint8Array([\n 0, 0, 0, 0, 0x73, 0x6f, 0x75, 0x6e,\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n 0x53, 0x6f, 0x75, 0x6e, 0x64, 0,\n ]))\n const mdhdBody = new Uint8Array(20)\n new DataView(mdhdBody.buffer).setUint32(8, ts)\n const mdhd = fullBox('mdhd', 0, 0, mdhdBody)\n const mdia = box('mdia', mdhd, hdlr, minf)\n\n const tkhdBody = new Uint8Array(80)\n const tkhdView = new DataView(tkhdBody.buffer)\n tkhdView.setUint32(8, trackId)\n tkhdView.setUint32(36, 0x00010000)\n tkhdView.setUint32(52, 0x00010000)\n tkhdView.setUint32(64, 0x40000000)\n const tkhd = fullBox('tkhd', 0, 3, tkhdBody)\n const trak = box('trak', tkhd, mdia)\n\n const mvhdBody = new Uint8Array(96)\n const mvhdView = new DataView(mvhdBody.buffer)\n mvhdView.setUint32(8, ts)\n mvhdView.setUint32(16, 0x00010000)\n mvhdView.setUint16(20, 0x0100)\n mvhdView.setUint32(32, 0x00010000)\n mvhdView.setUint32(48, 0x00010000)\n mvhdView.setUint32(60, 0x40000000)\n mvhdView.setUint32(92, trackId + 1)\n const mvhd = fullBox('mvhd', 0, 0, mvhdBody)\n\n const trexBody = new Uint8Array(20)\n new DataView(trexBody.buffer).setUint32(0, trackId)\n new DataView(trexBody.buffer).setUint32(4, 1)\n const mvex = box('mvex', fullBox('trex', 0, 0, trexBody))\n\n const moov = box('moov', mvhd, trak, mvex)\n const ftyp = box('ftyp', new Uint8Array([\n 0x69, 0x73, 0x6f, 0x6d, 0, 0, 2, 0,\n 0x69, 0x73, 0x6f, 0x6d,\n 0x69, 0x73, 0x6f, 0x36,\n 0x6d, 0x70, 0x34, 0x31,\n ]))\n const result = new Uint8Array(ftyp.length + moov.length)\n result.set(ftyp, 0)\n result.set(moov, ftyp.length)\n return result\n}\n\n/**\n * MMTP \u2192 CMAF converter.\n *\n * Accepts reassembled MFU frames (raw codec samples) from MmtpDecoder\n * and produces fMP4 segments for MSE SourceBuffer.\n *\n * Per draft-ramadan-moq-mmt \u00A75.3:\n * MPU metadata (ftyp+moov) \u2192 init segment\n * MFU sample bytes \u2192 moof+mdat data segment\n *\n * Timescale is microseconds (1_000_000) matching MMTP NTP short timestamps\n * converted via mmtpTimestampToMicros().\n */\nexport class MmtpToCmaf {\n #videoSeq = 1\n #audioSeq = 1\n #videoInitSegment: Uint8Array | null = null\n // Known only for locally-built init segments. Wire-supplied MPU metadata is\n // intentionally opaque here, so setVideoTrackParams remains the API that\n // lets a caller declare its track geometry before wrapping samples.\n #videoInitTrackId: number | null = null\n #audioInitSegment: Uint8Array | null = null\n #lastVideoTimestamp = 0\n // Sticky sample duration in video timescale units, updated from caller-\n // supplied durations or adjacent-timestamp deltas. null means \"nothing\n // observed yet\", in which case #videoFrameDuration derives ~30fps from the\n // configured timescale (33333 at the 1_000_000 default, i.e. unchanged).\n #frameDuration: number | null = null\n // Per-track rebase: each track anchors on its OWN first sample so\n // baseMediaDecodeTime is never negative. A shared base was wrong \u2014 if the\n // first sample of one track arrives later than the other's first sample,\n // the earlier track computes `timestamp - sharedBase` as a negative number,\n // which serializes into tfdt as a huge unsigned uint64 (~2^64 - 46) and\n // Chromium rejects the segment with CHUNK_DEMUXER_ERROR_APPEND_FAILED,\n // closing the MediaSource and detaching all SourceBuffers.\n // For A/V alignment, choose a COMMON anchor: set when the first sample of\n // EITHER track arrives, but only if that sample's timestamp is <= any\n // subsequent track's first sample. Implementation: each track rebases to\n // the minimum timestamp seen across tracks on their respective first sample.\n #videoBaseTs = -1\n #audioBaseTs = -1\n\n // Video track geometry. These pair with the video init segment's tkhd\n // track_ID and mdhd/mvhd timescale: every moof this converter emits must\n // reference the same track at the same rate or the browser either drops the\n // fragment (unknown track) or plays it at the wrong rate. They are\n // configuration rather than stream state, so \u2014 unlike the sequence numbers\n // and time bases above \u2014 reset() deliberately preserves them, matching the\n // fact that reset() also preserves #videoInitSegment.\n #videoTrackId = 1\n #videoTimescale = 1_000_000\n\n /**\n * Point the single-sample video wrappers at a specific track and rate.\n *\n * Call this when the init segment came off the wire (setInitSegmentFromMpu)\n * rather than from buildVideoInit, so the wrappers match the publisher's\n * tkhd/mdhd instead of assuming trackId=1 at microsecond rate. Consumers\n * that build their init through buildVideoInit can pass the same values\n * there instead and skip this call.\n *\n * The rate is settable only until the first single-sample wrap \u2014 see the\n * throw below for why.\n */\n setVideoTrackParams(trackId: number, timescale: number) {\n assertTrackId(trackId, 'video trackId')\n assertTimescale(timescale, 'video timescale')\n // #frameDuration, #lastVideoTimestamp and #videoBaseTs are all denominated\n // in #videoTimescale, so moving the rate out from under them reinterprets\n // every one at the new rate. Both consequences are silent:\n // - a duration latched as 33333 (1 MHz ~30fps) re-emits as 33333 ticks of\n // 90 kHz, a 370 ms frame;\n // - a base captured on the old scale rebases new-scale timestamps to a\n // negative relTs, which tfdt serializes as a ~2^64 uint64 and Chromium\n // rejects with CHUNK_DEMUXER_ERROR_APPEND_FAILED, closing the\n // MediaSource (same failure the #videoBaseTs comment above describes).\n // Rescaling instead of refusing would be a guess: the class cannot tell\n // whether the caller's next timestamps continue this timeline in new units\n // or open a fresh epoch. reset() is the exact mechanism for that\n // discontinuity \u2014 it clears all three fields while preserving geometry \u2014\n // so require it rather than infer. Re-asserting the same rate is a no-op.\n // A cached init also fixes the track ID in tkhd/trex; changing only the\n // wrapper setting would make later tfhd IDs disagree with that init.\n if (trackId !== this.#videoTrackId && this.#videoInitTrackId !== null) {\n throw new Error(\n `video track ID cannot change from ${this.#videoTrackId} to ${trackId} ` +\n 'after a video init has been cached; replace the init atomically',\n )\n }\n if (timescale !== this.#videoTimescale && this.#videoBaseTs >= 0) {\n throw new Error(\n `video timescale cannot change from ${this.#videoTimescale} to ${timescale} ` +\n `after video samples have been wrapped; call reset() first`,\n )\n }\n this.#videoTrackId = trackId\n this.#videoTimescale = timescale\n }\n\n /** Set init segment from MPU metadata packet (fragment_type=0).\n * These are complete ftyp+moov bytes from FFmpeg \u2014 use directly. */\n setInitSegmentFromMpu(data: Uint8Array, isAudio: boolean) {\n if (isAudio) {\n this.#audioInitSegment = data\n } else {\n this.#videoInitSegment = data\n this.#videoInitTrackId = null\n }\n }\n\n /** Build init segment from codec config (catalog path \u2014 no MPU metadata available).\n * Passing timescale/trackId also configures the wrappers via\n * setVideoTrackParams, so init and media segments cannot disagree. */\n buildVideoInit(avcC: Uint8Array, width: number, height: number, timescale?: number, trackId?: number) {\n const nextTimescale = timescale ?? this.#videoTimescale\n const nextTrackId = trackId ?? this.#videoTrackId\n assertTrackId(nextTrackId, 'video trackId')\n assertTimescale(nextTimescale, 'video timescale')\n if (nextTimescale !== this.#videoTimescale && this.#videoBaseTs >= 0) {\n throw new Error(\n `video timescale cannot change from ${this.#videoTimescale} to ${nextTimescale} ` +\n 'after video samples have been wrapped; call reset() first',\n )\n }\n // Build first, then publish both geometry and init together. This is the\n // sanctioned path for replacing a cached init with a new track ID.\n const init = buildVideoInitSegment(\n avcC,\n width,\n height,\n nextTimescale,\n nextTrackId,\n )\n this.#videoTimescale = nextTimescale\n this.#videoTrackId = nextTrackId\n this.#videoInitSegment = init\n this.#videoInitTrackId = nextTrackId\n }\n\n buildAudioInit(sampleRate: number, channels: number, asc?: Uint8Array, timescale?: number) {\n const ts = timescale ?? sampleRate\n this.#audioTimescale = ts\n this.#audioInitSegment = buildAudioInitSegment(sampleRate, channels, asc, ts)\n }\n\n get videoInitSegment(): Uint8Array | null { return this.#videoInitSegment }\n get audioInitSegment(): Uint8Array | null { return this.#audioInitSegment }\n\n /** Convert a raw video sample to an fMP4 moof+mdat segment. */\n wrapVideoSample(data: Uint8Array, timestamp: number, keyframe: boolean, duration?: number): Uint8Array {\n return this.wrapVideoSampleWithTiming(data, timestamp, keyframe, duration).segment\n }\n\n /**\n * Convert a raw video sample and return the exact browser media interval\n * encoded into tfdt/trun. Consumers that correlate SourceBuffer appends with\n * requestVideoFrameCallback must use this rebased timestamp, not the wire or\n * caller-owned timestamp passed above.\n */\n wrapVideoSampleWithTiming(\n data: Uint8Array,\n timestamp: number,\n keyframe: boolean,\n duration?: number,\n ): Readonly<{ segment: Uint8Array; mediaTimestamp: number; duration: number }> {\n // Prefer a caller-provided media duration when the browser append timeline\n // is intentionally decoupled from sparse MMTP wire timestamps. Fall back to\n // estimating from adjacent timestamps for legacy/direct callers. A delta of\n // a full second or more is not a frame interval, so it is rejected as a\n // discontinuity rather than latched.\n if (duration !== undefined && Number.isFinite(duration) && duration > 0) {\n this.#frameDuration = Math.round(duration)\n } else if (this.#lastVideoTimestamp > 0 && timestamp > this.#lastVideoTimestamp) {\n const delta = timestamp - this.#lastVideoTimestamp\n if (delta > 0 && delta < this.#videoTimescale) this.#frameDuration = delta\n }\n this.#lastVideoTimestamp = timestamp\n if (this.#videoBaseTs < 0) this.#videoBaseTs = timestamp\n const relTs = timestamp - this.#videoBaseTs\n const frameDuration = this.#videoFrameDuration\n return Object.freeze({\n segment: encodeDataSegment(\n data,\n relTs,\n frameDuration,\n keyframe,\n this.#videoSeq++,\n this.#videoTrackId,\n ),\n mediaTimestamp: relTs,\n duration: frameDuration,\n })\n }\n\n /** Sticky duration if one has been observed, else ~30fps at the current rate. */\n get #videoFrameDuration(): number {\n return this.#frameDuration ?? Math.max(1, Math.round(this.#videoTimescale / 30))\n }\n\n /** Convert an append-safe video batch using the caller-owned timeline.\n * Durations, baseDecodeTime, and compositionTimeOffset are in the\n * configured video timescale. compositionTimeOffset is the signed PTS-DTS\n * delta; its presence selects a version-1 trun for the whole batch.\n * An explicit trackId is range-checked before #videoSeq++ for the same\n * reason as wrapAudioSamples: the encoder's own check fires too late to\n * keep the sequence ungapped. */\n wrapVideoSamples(\n samples: Array<{\n data: Uint8Array\n duration: number\n keyframe: boolean\n compositionTimeOffset?: number\n }>,\n baseDecodeTime: number,\n trackId = this.#videoTrackId,\n ): Uint8Array {\n assertTrackId(trackId, 'video trackId')\n assertCompositionTimeOffsets(samples)\n return encodeMultiSampleSegment(samples, baseDecodeTime, this.#videoSeq++, trackId)\n }\n\n // Audio timescale from init segment (default 1M \u00B5s; real FFmpeg init uses sampleRate).\n // Set by buildAudioInit or setAudioTimescale.\n #audioTimescale = 1_000_000\n\n /** Set audio timescale to match the init segment's mdhd timescale.\n * Call after appending the real encoder init (FT=0 ftyp+moov). */\n setAudioTimescale(timescale: number) { this.#audioTimescale = timescale }\n\n // Audio sample counter for drift-free baseMediaDecodeTime.\n // AAC frames are exactly 1024 samples at sampleRate. Using sequential\n // counter \u00D7 1024 avoids floating-point rounding drift from timestamp conversion.\n #audioSampleCount = 0\n\n /** AAC access-unit length in samples. ISO/IEC 14496-3: an AAC-LC frame is\n * exactly 1024 samples at every sample rate \u2014 it is not rate-dependent. */\n readonly #aacFrameSamples = 1024\n\n /** Convert a raw audio sample to an fMP4 moof+mdat segment. */\n wrapAudioSample(\n data: Uint8Array,\n timestamp: number,\n sampleDuration = 21333,\n compositionTimeOffset?: number,\n ): Uint8Array {\n assertCompositionTimeOffsets([{ compositionTimeOffset }])\n const sampleData = normalizeAacSampleForCmaf(data)\n if (this.#audioBaseTs < 0) this.#audioBaseTs = timestamp\n\n // When timescale matches sampleRate (e.g. 48000), use integer sample counting\n // for exact baseMediaDecodeTime alignment. This eliminates cumulative rounding\n // drift from Math.round(\u00B5s * sampleRate / 1_000_000) that causes frequency\n // wandering in FFT analysis (42% consistency \u2192 99%+ with exact counting).\n //\n // samplesPerFrame is the AAC access-unit length, NOT a rescaled duration.\n // Deriving it as Math.round(sampleDuration * timescale / 1e6) only lands on\n // 1024 when the rate happens to be 48 kHz (21333 * 48000 / 1e6 = 1023.98),\n // which made the default silently correct at 48 kHz and wrong everywhere\n // else: at 44.1 kHz it yields 941, so every moof declared ~8% short frames\n // and Chrome rejected the first packet with PIPELINE_ERROR_DECODE\n // (\"Failed to send audio packet for decoding\", duration=21337\u00B5s = 941/44100).\n const samplesPerFrame = this.#audioTimescale !== 1_000_000\n ? this.#aacFrameSamples\n : sampleDuration\n const scaledTs = this.#audioTimescale !== 1_000_000\n ? this.#audioSampleCount * samplesPerFrame\n : (timestamp - this.#audioBaseTs)\n this.#audioSampleCount++\n\n return encodeDataSegment(\n sampleData,\n scaledTs,\n samplesPerFrame,\n true,\n this.#audioSeq++,\n 1,\n compositionTimeOffset,\n )\n }\n\n /** Convert an ordered audio batch using the caller-owned timeline. */\n wrapAudioSamples(\n samples: Array<{\n data: Uint8Array\n duration: number\n compositionTimeOffset?: number\n }>,\n baseDecodeTime: number,\n trackId = 1,\n ): Uint8Array {\n // Checked before #audioSeq++ below: the encoder validates too, but its\n // throw would land after the counter had already advanced, leaving the\n // sequence gapped by a call that produced no segment.\n assertTrackId(trackId, 'audio trackId')\n assertCompositionTimeOffsets(samples)\n return encodeMultiSampleSegment(\n samples.map(sample => ({\n data: normalizeAacSampleForCmaf(sample.data),\n duration: sample.duration,\n keyframe: true,\n compositionTimeOffset: sample.compositionTimeOffset,\n })),\n baseDecodeTime,\n this.#audioSeq++,\n trackId,\n )\n }\n\n /** Clear per-stream sequencing and time bases.\n * Cached init segments and the video track geometry survive, so a converter\n * reset mid-subscription keeps emitting moofs the existing init can resolve.\n * Clearing the timescale-denominated timing state also re-opens the video\n * rate for change \u2014 this is the sanctioned way to retarget mid-subscription. */\n reset() {\n this.#videoSeq = 1\n this.#audioSeq = 1\n this.#audioSampleCount = 0\n this.#lastVideoTimestamp = 0\n this.#frameDuration = null\n this.#videoBaseTs = -1\n this.#audioBaseTs = -1\n this.#audioTimescale = 1_000_000\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * `multicast.auth` v2 — catalog representation for per-track source-auth
3
+ * scopes and manifest tracks (BLO-16700 decision).
4
+ *
5
+ * Reconciles two previously-accepted, mutually incompatible contracts:
6
+ * - BLO-16481 (S0): every publisher session/track/source-symbol-format
7
+ * needs its own fresh, unpredictable 32-byte `auth_scope`, bound into
8
+ * the signed per-group Merkle root (see `sourceAuthSignaturePreimage`
9
+ * in ./source-auth.ts).
10
+ * - BLO-16485 (S3 draft): a singular `multicast.auth` block with one
11
+ * `manifestTrack` string and no `authScope` field at all — unable to
12
+ * describe two protected tracks (e.g. audio + video) in one session.
13
+ *
14
+ * `multicast.auth` v2 keeps one shared signing identity (scheme, hash,
15
+ * sig, publicKey, keyId, previousKey, compaction, enforcement) but moves
16
+ * `manifestTrack` into a `tracks[]` array, one entry per protected media
17
+ * track, each carrying its own `manifestTrack` name, `authScope`, and
18
+ * `sourceSymbolFormat`. This is additive over the S3 draft shape (every
19
+ * top-level field the draft specified still exists at the top level) —
20
+ * only `manifestTrack` moves from top-level into each track entry.
21
+ *
22
+ * `manifestTrack` is carried as an opaque string field, deliberately NOT
23
+ * run through `parseTrackRole`/`VALID_ROLE_SUFFIXES` in ./carp-catalog.ts.
24
+ * `carp-catalog.ts` only recognises `base`/`delta`/`repair` role suffixes
25
+ * and throws on anything else (including a hypothetical `manifest` role);
26
+ * resolving BLO-16485's "manifest-track name collision" MANDATORY item by
27
+ * adding a role would force every catalog consumer to learn a fourth role
28
+ * and would break `validateSwitchingSet`'s base/delta/repair completeness
29
+ * check. Carrying it as a typed field here avoids both.
30
+ */
31
+ export type MulticastAuthScheme = "bc-provenance";
32
+ export type MulticastAuthHash = "blake3";
33
+ export type MulticastAuthSig = "ed25519";
34
+ export type MulticastAuthCompaction = "merkle" | "none";
35
+ export type MulticastAuthEnforcement = "shadow" | "enforce";
36
+ export type MulticastAuthMode = "off" | MulticastAuthEnforcement;
37
+ /** Encode raw bytes as unpadded base64url — the one accepted encoding for
38
+ * `authScope`/`publicKey`/`previousKey` (BLO-16483's operator quickstart). */
39
+ export declare function encodeBase64Url(bytes: Uint8Array): string;
40
+ /** Decode unpadded base64url text to raw bytes. Throws on any padding
41
+ * (`=`), standard-alphabet (`+`/`/`), or otherwise invalid character. */
42
+ export declare function decodeBase64Url(text: string): Uint8Array;
43
+ /** Decode + length-validate an `authScope` field. Throws unless it decodes
44
+ * to exactly `SOURCE_AUTH_SCOPE_LENGTH` (32) raw bytes. */
45
+ export declare function decodeAuthScope(authScope: string): Uint8Array;
46
+ /** Decode a catalog key in the only accepted representation: exactly 32 raw
47
+ * ed25519 bytes encoded as canonical, unpadded base64url. */
48
+ export declare function decodeEd25519PublicKey(publicKey: string): Uint8Array;
49
+ /**
50
+ * One protected media track's manifest + scope binding.
51
+ *
52
+ * - `mediaTrack`: the actual media track name (e.g. `"video/base"`).
53
+ * - `manifestTrack`: the sibling track carrying this track's signed
54
+ * manifest objects (see ./source-auth.ts `SourceAuthObjectEntry`/
55
+ * `SourceAuthGroupClose`). Opaque string — not role-parsed.
56
+ * - `authScope`: this track's unique 32-byte scope, raw bytes as unpadded
57
+ * base64url. BLO-16481 requires a scope fresh per (publisher session,
58
+ * track, source-symbol format) — a track publishing under two source-
59
+ * symbol formats in the same session MUST appear as two entries here,
60
+ * each with its own scope.
61
+ * - `sourceSymbolFormat`: names the deployed source-symbol profile this
62
+ * track's authenticated bytes are derived from (e.g.
63
+ * `"full-mmtp-packet"` or `"fec-padded-recovery"`, the two formats
64
+ * BLO-16481's S0 fixture covers).
65
+ */
66
+ export interface MulticastAuthTrackConfig {
67
+ mediaTrack: string;
68
+ manifestTrack: string;
69
+ authScope: string;
70
+ sourceSymbolFormat: string;
71
+ }
72
+ /**
73
+ * `multicast.auth` v2 — supersedes the BLO-16485 draft's singular
74
+ * `manifestTrack`/no-`authScope` shape (BLO-16700 decision).
75
+ */
76
+ export interface MulticastAuthConfig {
77
+ scheme: MulticastAuthScheme;
78
+ hash: MulticastAuthHash;
79
+ sig: MulticastAuthSig;
80
+ /** Raw 32-byte ed25519 public key, unpadded base64url. */
81
+ publicKey: string;
82
+ keyId: string;
83
+ /** Raw 32-byte ed25519 public key, unpadded base64url. Accepted
84
+ * alongside `publicKey` during a key-rotation overlap window. */
85
+ previousKey?: string;
86
+ compaction: MulticastAuthCompaction;
87
+ /** Player-config-wins default; catalog value only selects the default
88
+ * when the player hasn't pinned one (S3 enforcement precedence). */
89
+ enforcement?: MulticastAuthEnforcement;
90
+ tracks: MulticastAuthTrackConfig[];
91
+ }
92
+ export declare function isMulticastAuthTrackConfig(obj: unknown): obj is MulticastAuthTrackConfig;
93
+ /** Semantic uniqueness rule shared by runtime parsing and the published
94
+ * catalog schema's `uniqueMulticastAuthTrackBindings` keyword. */
95
+ export declare function hasUniqueMulticastAuthTrackBindings(tracks: readonly unknown[]): boolean;
96
+ export declare function isMulticastAuthConfig(obj: unknown): obj is MulticastAuthConfig;
97
+ export interface ResolvedMulticastAuthConfig {
98
+ keyId: string;
99
+ /** Current key first, followed by the overlap key when advertised. */
100
+ acceptedPublicKeys: Uint8Array[];
101
+ mode: MulticastAuthMode;
102
+ compaction: MulticastAuthCompaction;
103
+ tracks: Array<Omit<MulticastAuthTrackConfig, "authScope"> & {
104
+ authScope: Uint8Array;
105
+ }>;
106
+ }
107
+ /** Player configuration is authoritative, including an explicit `off`.
108
+ * Catalog enforcement is only a default; an auth block without it defaults
109
+ * to shadow, while a catalog without auth defaults to off. */
110
+ export declare function resolveMulticastAuthMode(playerMode: MulticastAuthMode | undefined, auth: MulticastAuthConfig | undefined): MulticastAuthMode;
111
+ /** Parse and resolve the catalog auth block into verifier-ready raw keys and
112
+ * scopes. Invalid blocks and dangling media/manifest track references fail
113
+ * closed instead of silently falling back to unauthenticated playback. */
114
+ export declare function resolveMulticastAuthCatalog(catalog: unknown, playerMode?: MulticastAuthMode): ResolvedMulticastAuthConfig | undefined;
115
+ //# sourceMappingURL=multicast-auth-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multicast-auth-catalog.d.ts","sourceRoot":"","sources":["../src/multicast-auth-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,MAAM,mBAAmB,GAAG,eAAe,CAAC;AAClD,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AACzC,MAAM,MAAM,gBAAgB,GAAG,SAAS,CAAC;AACzC,MAAM,MAAM,uBAAuB,GAAG,QAAQ,GAAG,MAAM,CAAC;AACxD,MAAM,MAAM,wBAAwB,GAAG,QAAQ,GAAG,SAAS,CAAC;AAC5D,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,wBAAwB,CAAC;AAQjE;8EAC8E;AAC9E,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAczD;AAUD;yEACyE;AACzE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAyBxD;AAED;2DAC2D;AAC3D,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAQ7D;AAED;6DAC6D;AAC7D,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAQpE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,wBAAwB;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IACnC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,IAAI,EAAE,iBAAiB,CAAC;IACxB,GAAG,EAAE,gBAAgB,CAAC;IACtB,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd;qEACiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,uBAAuB,CAAC;IACpC;wEACoE;IACpE,WAAW,CAAC,EAAE,wBAAwB,CAAC;IACvC,MAAM,EAAE,wBAAwB,EAAE,CAAC;CACnC;AA+BD,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,wBAAwB,CAWxF;AAKD;kEACkE;AAClE,wBAAgB,mCAAmC,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAUvF;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,mBAAmB,CAiC9E;AAED,MAAM,WAAW,2BAA2B;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,kBAAkB,EAAE,UAAU,EAAE,CAAC;IACjC,IAAI,EAAE,iBAAiB,CAAC;IACxB,UAAU,EAAE,uBAAuB,CAAC;IACpC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,wBAAwB,EAAE,WAAW,CAAC,GAAG;QAAE,SAAS,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;CACvF;AAED;;8DAE8D;AAC9D,wBAAgB,wBAAwB,CACvC,UAAU,EAAE,iBAAiB,GAAG,SAAS,EACzC,IAAI,EAAE,mBAAmB,GAAG,SAAS,GACnC,iBAAiB,CAInB;AAED;;0EAE0E;AAC1E,wBAAgB,2BAA2B,CAC1C,OAAO,EAAE,OAAO,EAChB,UAAU,CAAC,EAAE,iBAAiB,GAC5B,2BAA2B,GAAG,SAAS,CAkDzC"}
@@ -0,0 +1,202 @@
1
+ // src/multicast-auth-catalog.ts
2
+ var RAW_ED25519_KEY_LENGTH = 32;
3
+ var SOURCE_AUTH_SCOPE_LENGTH = 32;
4
+ var BASE64URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
5
+ function encodeBase64Url(bytes) {
6
+ let output = "";
7
+ for (let i = 0; i < bytes.length; i += 3) {
8
+ const b0 = bytes[i];
9
+ const b1 = bytes[i + 1];
10
+ const b2 = bytes[i + 2];
11
+ output += BASE64URL_ALPHABET[b0 >> 2];
12
+ output += BASE64URL_ALPHABET[(b0 & 3) << 4 | (b1 === void 0 ? 0 : b1 >> 4)];
13
+ if (b1 === void 0) break;
14
+ output += BASE64URL_ALPHABET[(b1 & 15) << 2 | (b2 === void 0 ? 0 : b2 >> 6)];
15
+ if (b2 === void 0) break;
16
+ output += BASE64URL_ALPHABET[b2 & 63];
17
+ }
18
+ return output;
19
+ }
20
+ var BASE64URL_DECODE_TABLE = (() => {
21
+ const table = new Int8Array(128).fill(-1);
22
+ for (let i = 0; i < BASE64URL_ALPHABET.length; i++) {
23
+ table[BASE64URL_ALPHABET.charCodeAt(i)] = i;
24
+ }
25
+ return table;
26
+ })();
27
+ function decodeBase64Url(text) {
28
+ if (text.length % 4 === 1) {
29
+ throw new Error(`[multicast-auth-catalog] invalid unpadded base64url length for "${text}"`);
30
+ }
31
+ const bytes = [];
32
+ let buffer = 0;
33
+ let bits = 0;
34
+ for (let i = 0; i < text.length; i++) {
35
+ const code = text.charCodeAt(i);
36
+ const value = code < 128 ? BASE64URL_DECODE_TABLE[code] : -1;
37
+ if (value === void 0 || value < 0) {
38
+ throw new Error(`[multicast-auth-catalog] invalid base64url character in "${text}"`);
39
+ }
40
+ buffer = buffer << 6 | value;
41
+ bits += 6;
42
+ if (bits >= 8) {
43
+ bits -= 8;
44
+ bytes.push(buffer >> bits & 255);
45
+ }
46
+ }
47
+ const decoded = Uint8Array.from(bytes);
48
+ if (encodeBase64Url(decoded) !== text) {
49
+ throw new Error(`[multicast-auth-catalog] non-canonical base64url encoding "${text}"`);
50
+ }
51
+ return decoded;
52
+ }
53
+ function decodeAuthScope(authScope) {
54
+ const bytes = decodeBase64Url(authScope);
55
+ if (bytes.byteLength !== SOURCE_AUTH_SCOPE_LENGTH) {
56
+ throw new Error(
57
+ `[multicast-auth-catalog] authScope must decode to ${SOURCE_AUTH_SCOPE_LENGTH} raw bytes, got ${bytes.byteLength}`
58
+ );
59
+ }
60
+ return bytes;
61
+ }
62
+ function decodeEd25519PublicKey(publicKey) {
63
+ const bytes = decodeBase64Url(publicKey);
64
+ if (bytes.byteLength !== RAW_ED25519_KEY_LENGTH) {
65
+ throw new Error(
66
+ `[multicast-auth-catalog] public key must decode to ${RAW_ED25519_KEY_LENGTH} raw bytes, got ${bytes.byteLength}`
67
+ );
68
+ }
69
+ return bytes;
70
+ }
71
+ function isNonEmptyString(value) {
72
+ return typeof value === "string" && value.length > 0;
73
+ }
74
+ function isValidAuthScopeField(value) {
75
+ if (!isNonEmptyString(value)) return false;
76
+ try {
77
+ decodeAuthScope(value);
78
+ return true;
79
+ } catch {
80
+ return false;
81
+ }
82
+ }
83
+ function isValidPublicKeyField(value) {
84
+ if (!isNonEmptyString(value)) return false;
85
+ try {
86
+ decodeEd25519PublicKey(value);
87
+ return true;
88
+ } catch {
89
+ return false;
90
+ }
91
+ }
92
+ function hasOnlyKeys(object, allowed) {
93
+ const allowedKeys = new Set(allowed);
94
+ return Object.keys(object).every((key) => allowedKeys.has(key));
95
+ }
96
+ function isMulticastAuthTrackConfig(obj) {
97
+ if (typeof obj !== "object" || obj === null) return false;
98
+ const o = obj;
99
+ return hasOnlyKeys(o, ["mediaTrack", "manifestTrack", "authScope", "sourceSymbolFormat"]) && isNonEmptyString(o["mediaTrack"]) && isNonEmptyString(o["manifestTrack"]) && o["mediaTrack"] !== o["manifestTrack"] && isValidAuthScopeField(o["authScope"]) && isNonEmptyString(o["sourceSymbolFormat"]);
100
+ }
101
+ var VALID_COMPACTION = /* @__PURE__ */ new Set(["merkle", "none"]);
102
+ var VALID_ENFORCEMENT = /* @__PURE__ */ new Set(["shadow", "enforce"]);
103
+ function hasUniqueMulticastAuthTrackBindings(tracks) {
104
+ const bindings = tracks.flatMap((track) => {
105
+ if (typeof track !== "object" || track === null) return [];
106
+ const value = track;
107
+ if (typeof value["mediaTrack"] !== "string" || typeof value["sourceSymbolFormat"] !== "string") {
108
+ return [];
109
+ }
110
+ return [JSON.stringify([value["mediaTrack"], value["sourceSymbolFormat"]])];
111
+ });
112
+ return new Set(bindings).size === bindings.length;
113
+ }
114
+ function isMulticastAuthConfig(obj) {
115
+ if (typeof obj !== "object" || obj === null) return false;
116
+ const o = obj;
117
+ if (o["scheme"] !== "bc-provenance") return false;
118
+ if (o["hash"] !== "blake3") return false;
119
+ if (o["sig"] !== "ed25519") return false;
120
+ if (!hasOnlyKeys(o, ["scheme", "hash", "sig", "publicKey", "keyId", "previousKey", "compaction", "enforcement", "tracks"])) return false;
121
+ if (!isValidPublicKeyField(o["publicKey"])) return false;
122
+ if (!isNonEmptyString(o["keyId"])) return false;
123
+ if (o["previousKey"] !== void 0 && !isValidPublicKeyField(o["previousKey"])) return false;
124
+ if (o["previousKey"] === o["publicKey"]) return false;
125
+ if (typeof o["compaction"] !== "string" || !VALID_COMPACTION.has(o["compaction"])) return false;
126
+ if (o["enforcement"] !== void 0) {
127
+ if (typeof o["enforcement"] !== "string" || !VALID_ENFORCEMENT.has(o["enforcement"])) return false;
128
+ }
129
+ if (!Array.isArray(o["tracks"]) || o["tracks"].length === 0) return false;
130
+ const tracks = o["tracks"];
131
+ if (!tracks.every((t) => isMulticastAuthTrackConfig(t))) return false;
132
+ const typedTracks = tracks;
133
+ const scopes = typedTracks.map((t) => t.authScope);
134
+ if (new Set(scopes).size !== scopes.length) return false;
135
+ if (!hasUniqueMulticastAuthTrackBindings(typedTracks)) return false;
136
+ const manifestTracks = typedTracks.map((t) => t.manifestTrack);
137
+ if (new Set(manifestTracks).size !== manifestTracks.length) return false;
138
+ return true;
139
+ }
140
+ function resolveMulticastAuthMode(playerMode, auth) {
141
+ if (playerMode !== void 0) return playerMode;
142
+ if (auth === void 0) return "off";
143
+ return auth.enforcement ?? "shadow";
144
+ }
145
+ function resolveMulticastAuthCatalog(catalog, playerMode) {
146
+ if (typeof catalog !== "object" || catalog === null || Array.isArray(catalog)) {
147
+ throw new Error("[multicast-auth-catalog] catalog must be an object");
148
+ }
149
+ const root = catalog;
150
+ const rawAuth = root["multicast.auth"];
151
+ if (rawAuth === void 0) {
152
+ if (playerMode === "enforce") {
153
+ throw new Error("[multicast-auth-catalog] player enforce mode requires multicast.auth");
154
+ }
155
+ return void 0;
156
+ }
157
+ if (!isMulticastAuthConfig(rawAuth)) {
158
+ throw new Error("[multicast-auth-catalog] invalid multicast.auth v2 block");
159
+ }
160
+ const rawTracks = root["tracks"];
161
+ if (!Array.isArray(rawTracks)) {
162
+ throw new Error("[multicast-auth-catalog] catalog tracks must be an array");
163
+ }
164
+ const catalogTrackNames = new Set(
165
+ rawTracks.flatMap(
166
+ (track) => typeof track === "object" && track !== null && typeof track["name"] === "string" ? [track["name"]] : []
167
+ )
168
+ );
169
+ for (const track of rawAuth.tracks) {
170
+ if (!catalogTrackNames.has(track.mediaTrack)) {
171
+ throw new Error(`[multicast-auth-catalog] unknown mediaTrack "${track.mediaTrack}"`);
172
+ }
173
+ if (!catalogTrackNames.has(track.manifestTrack)) {
174
+ throw new Error(`[multicast-auth-catalog] unknown manifestTrack "${track.manifestTrack}"`);
175
+ }
176
+ }
177
+ return {
178
+ keyId: rawAuth.keyId,
179
+ acceptedPublicKeys: [
180
+ decodeEd25519PublicKey(rawAuth.publicKey),
181
+ ...rawAuth.previousKey === void 0 ? [] : [decodeEd25519PublicKey(rawAuth.previousKey)]
182
+ ],
183
+ mode: resolveMulticastAuthMode(playerMode, rawAuth),
184
+ compaction: rawAuth.compaction,
185
+ tracks: rawAuth.tracks.map((track) => ({
186
+ ...track,
187
+ authScope: decodeAuthScope(track.authScope)
188
+ }))
189
+ };
190
+ }
191
+ export {
192
+ decodeAuthScope,
193
+ decodeBase64Url,
194
+ decodeEd25519PublicKey,
195
+ encodeBase64Url,
196
+ hasUniqueMulticastAuthTrackBindings,
197
+ isMulticastAuthConfig,
198
+ isMulticastAuthTrackConfig,
199
+ resolveMulticastAuthCatalog,
200
+ resolveMulticastAuthMode
201
+ };
202
+ //# sourceMappingURL=multicast-auth-catalog.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/multicast-auth-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"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Multicast catalog input contract — validator + builder.
3
+ *
4
+ * Per draft-ramadan-moq-multicast-00 §3 + §4.1, the publisher (FFmpeg,
5
+ * cast bridge, GStreamer, OBS-bridge) populates `multicast.endpoints[]`
6
+ * in the catalog when its output includes a UDP multicast destination.
7
+ *
8
+ * This module is the TypeScript-side validator over a versioned input
9
+ * shape. Sister-language validators (FFmpeg C, cast Rust) target the
10
+ * same invariants — eventually via a shared JSON Schema + fixtures
11
+ * (BLO-3341 follow-up); today parity is enforced by code review against
12
+ * 1:1 ports. Each publisher's integration MUST also assert that the
13
+ * declared `(sourceAddress, groupAddress, port)` matches what it
14
+ * actually emits — that's a separate runtime check the helper cannot
15
+ * perform.
16
+ *
17
+ * Validation invariants (per codex review of BLO-3323 v2):
18
+ * - protocol === 'ssm' → sourceAddress REQUIRED
19
+ * - protocol === 'amt' → relayAddress REQUIRED
20
+ * - groupAddress is a valid IPv4 multicast group (224.0.0.0/4)
21
+ * or IPv6 multicast group (ff00::/8)
22
+ * - SSM groupAddress MUST be in 232.0.0.0/8 (IPv4) or ff3x::/32 (IPv6),
23
+ * where the IPv6 form requires P=1 + T=1 (the `3` nibble) AND the
24
+ * 16-bit reserved-zero second hextet per RFC 3306 §4 / RFC 4607.
25
+ * - port in 1..65535
26
+ * - tracks non-empty; per-track packetId in 0..65535
27
+ * - packetIds unique within an endpoint
28
+ * - (sourceAddress, groupAddress, port) tuple unique across endpoints
29
+ * - bandwidth (if present) > 0
30
+ * - validUntil (if present) is a positive unix-ms timestamp
31
+ *
32
+ * @see draft-ramadan-moq-multicast-00 §4.1
33
+ * @see .planning/drafts/blo-3323-multicast-catalog-source-of-truth.md
34
+ */
35
+ import { type AmtDiscovery, type MulticastCatalogConfig, type MulticastProtocol, type MulticastTrackObject } from "./carp-catalog.js";
36
+ /**
37
+ * Strict typed input for one multicast endpoint. The publisher provides
38
+ * this shape (env vars / CLI / config record), the helper validates and
39
+ * lifts it into a `MulticastEndpoint` ready to embed in the catalog.
40
+ */
41
+ export interface MulticastEndpointInput {
42
+ readonly protocol: MulticastProtocol;
43
+ readonly sourceAddress?: string;
44
+ readonly groupAddress: string;
45
+ readonly port: number;
46
+ /** New emitters MUST use the object form (name + packetId). */
47
+ readonly tracks: ReadonlyArray<MulticastTrackObject>;
48
+ readonly relayAddress?: string;
49
+ /** Aggregate bandwidth in bits per second. RECOMMENDED per draft §4.1. */
50
+ readonly bandwidth?: number;
51
+ }
52
+ /**
53
+ * Strict typed input for the catalog-level multicast extension.
54
+ *
55
+ * `version` (monotonic) + `validUntil` (unix ms) support the catalog
56
+ * freshness model: subscribers refetch before expiry, and publishers
57
+ * MUST republish (with bumped `version`) on any endpoint mutation.
58
+ */
59
+ export interface MulticastInput {
60
+ readonly enabled?: boolean;
61
+ readonly endpoints: ReadonlyArray<MulticastEndpointInput>;
62
+ readonly amtFallback?: {
63
+ readonly discovery: AmtDiscovery;
64
+ readonly relayDns?: string;
65
+ };
66
+ readonly version?: number;
67
+ readonly validUntil?: number;
68
+ }
69
+ export type MulticastInputErrorKind = "empty_endpoints" | "ssm_requires_source" | "amt_requires_relay" | "invalid_group_address" | "ssm_group_out_of_range" | "invalid_port" | "empty_tracks" | "invalid_track_name" | "invalid_packet_id" | "duplicate_packet_id" | "duplicate_endpoint_tuple" | "invalid_bandwidth" | "invalid_valid_until" | "invalid_version" | "invalid_env_shape";
70
+ export declare class MulticastInputError extends Error {
71
+ readonly kind: MulticastInputErrorKind;
72
+ readonly endpointIndex: number | null;
73
+ constructor(kind: MulticastInputErrorKind, endpointIndex: number | null, message: string);
74
+ }
75
+ /**
76
+ * Validate a typed publisher input and lift it into a
77
+ * `MulticastCatalogConfig` ready for `catalog.multicast = …`.
78
+ *
79
+ * Throws `MulticastInputError` on any invariant violation. Fail-fast
80
+ * at config-load time, never at runtime — silent fallbacks hide bugs
81
+ * upstream (per the project's "no anti-patterns" directive).
82
+ */
83
+ export declare function multicastFromConfig(input: MulticastInput): MulticastCatalogConfig;
84
+ /**
85
+ * Read `MOQCAST_MULTICAST_*` env vars and return a
86
+ * `MulticastCatalogConfig`. Returns `undefined` when no per-endpoint
87
+ * key is set.
88
+ *
89
+ * Env contract — per-endpoint keys take an optional non-negative index:
90
+ *
91
+ * MOQCAST_MULTICAST[_<idx>]_PROTOCOL=ssm
92
+ * MOQCAST_MULTICAST[_<idx>]_GROUP=232.1.1.1
93
+ * MOQCAST_MULTICAST[_<idx>]_PORT=5004
94
+ * MOQCAST_MULTICAST[_<idx>]_SOURCE=10.0.0.20 (required for ssm)
95
+ * MOQCAST_MULTICAST[_<idx>]_RELAY=amt.example.com (required for amt)
96
+ * MOQCAST_MULTICAST[_<idx>]_TRACKS=video:1,audio:3
97
+ * MOQCAST_MULTICAST[_<idx>]_BANDWIDTH=8000000 (optional, bps)
98
+ *
99
+ * MOQCAST_MULTICAST_AMT_DISCOVERY=driad (catalog-level)
100
+ * MOQCAST_MULTICAST_AMT_RELAY_DNS=relay.example.com (catalog-level)
101
+ *
102
+ * The unindexed form (`MOQCAST_MULTICAST_GROUP`) is exactly index 0;
103
+ * mixing it with explicit `_0_` keys is rejected as ambiguous. Indices
104
+ * need not be contiguous; observed indices are sorted ascending.
105
+ */
106
+ export declare function multicastFromEnv(env?: Record<string, string | undefined>): MulticastCatalogConfig | undefined;
107
+ //# sourceMappingURL=multicast-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multicast-input.d.ts","sourceRoot":"","sources":["../src/multicast-input.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EACN,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAE3B,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,MAAM,mBAAmB,CAAC;AAE3B;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IACrD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC1D,QAAQ,CAAC,WAAW,CAAC,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;QAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,uBAAuB,GAChC,iBAAiB,GACjB,qBAAqB,GACrB,oBAAoB,GACpB,uBAAuB,GACvB,wBAAwB,GACxB,cAAc,GACd,cAAc,GACd,oBAAoB,GACpB,mBAAmB,GACnB,qBAAqB,GACrB,0BAA0B,GAC1B,mBAAmB,GACnB,qBAAqB,GACrB,iBAAiB,GACjB,mBAAmB,CAAC;AAEvB,qBAAa,mBAAoB,SAAQ,KAAK;aAE5B,IAAI,EAAE,uBAAuB;aAC7B,aAAa,EAAE,MAAM,GAAG,IAAI;gBAD5B,IAAI,EAAE,uBAAuB,EAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5C,OAAO,EAAE,MAAM;CAKhB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,GAAG,sBAAsB,CA8BjF;AAqID;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAC/B,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CACqB,GACzD,sBAAsB,GAAG,SAAS,CAwCpC"}