@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,776 @@
1
+ /**
2
+ * CARP Catalog Types — FEC and Multicast catalog extensions.
3
+ *
4
+ * Per draft-law-ramadan-moq-carp-reliability §3 (FEC) and §4 (Multicast).
5
+ * Plain TypeScript interfaces + type guards — no Zod dependency.
6
+ *
7
+ * These are the canonical type definitions. Upstream Zod schemas
8
+ * should derive from these via z.infer<> to avoid duplication.
9
+ */
10
+
11
+ import { resolveMulticastAuthCatalog, type MulticastAuthConfig } from "./multicast-auth-catalog.js";
12
+
13
+ // ── Track Role (Phase 14, D-02..D-05) ─────────────────────────
14
+
15
+ /**
16
+ * Track role derived from the last slash-segment of the track name.
17
+ *
18
+ * Convention: `{content}/base`, `{content}/delta`, `{content}/repair`.
19
+ * Single-track (no slash) legacy streams use `"single"`.
20
+ *
21
+ * D-01: No `trackRole` / `role` / `kind` field in the catalog.
22
+ * D-02: Role is expressed via track name suffix only.
23
+ * D-03: Unknown suffixes throw at parse time (error on bad init).
24
+ * D-04: Legacy single-track streams (no slash suffix) return `"single"`.
25
+ * D-05: Single role per track — no multi-role arrays.
26
+ */
27
+ export type TrackRole = "base" | "delta" | "repair" | "single";
28
+
29
+ const VALID_ROLE_SUFFIXES = new Set<string>(["base", "delta", "repair"]);
30
+
31
+ /**
32
+ * Derive the role of a track from its name.
33
+ *
34
+ * - Names with no `/` → `"single"` (legacy single-track streams, D-04).
35
+ * - Names ending with `/base`, `/delta`, or `/repair` → that role (D-02).
36
+ * - Empty name → throws (error on bad init).
37
+ * - Trailing slash (empty last segment) → throws.
38
+ * - Non-ASCII or control characters anywhere in the name → throws (T-14-01 fuzz hardening).
39
+ * - Unknown last segment → throws.
40
+ *
41
+ * @throws {Error} On empty name, non-ASCII/control chars, empty suffix, or unknown suffix.
42
+ */
43
+ export function parseTrackRole(trackName: string): TrackRole {
44
+ if (trackName === "") {
45
+ throw new Error("[carp-catalog] empty track name");
46
+ }
47
+
48
+ // T-14-01 fuzz hardening: reject non-ASCII and control characters.
49
+ // This prevents catalog injection attacks where a publisher sends a crafted
50
+ // track name that bypasses role checks by embedding unusual code points.
51
+ for (let i = 0; i < trackName.length; i++) {
52
+ const cp = trackName.charCodeAt(i);
53
+ // Reject control characters (0x00-0x1F, 0x7F) and non-ASCII (>0x7E)
54
+ if (cp <= 0x1f || cp === 0x7f || cp > 0x7e) {
55
+ throw new Error(
56
+ `[carp-catalog] track name contains non-ASCII or control character (code point 0x${cp.toString(16)}) in "${trackName}"`,
57
+ );
58
+ }
59
+ }
60
+
61
+ const lastSlash = trackName.lastIndexOf("/");
62
+ if (lastSlash === -1) {
63
+ // No slash — legacy single-track stream (D-04)
64
+ return "single";
65
+ }
66
+
67
+ const suffix = trackName.slice(lastSlash + 1);
68
+ if (suffix === "") {
69
+ throw new Error(
70
+ `[carp-catalog] empty role suffix in track name "${trackName}"; track names must not end with "/"`,
71
+ );
72
+ }
73
+
74
+ if (!VALID_ROLE_SUFFIXES.has(suffix)) {
75
+ throw new Error(
76
+ `[carp-catalog] unknown role suffix "${suffix}" in track name "${trackName}"; expected one of: base, delta, repair`,
77
+ );
78
+ }
79
+
80
+ return suffix as TrackRole;
81
+ }
82
+
83
+ /**
84
+ * Non-throwing switching-set detector (BLO-8158).
85
+ *
86
+ * Returns `true` iff at least one track name carries a media role suffix
87
+ * (`base` or `delta`) — i.e. the set looks like a base/delta/repair switching
88
+ * set. A `/repair` track alone is ordinary FEC topology and is not sufficient
89
+ * evidence of a switching set. Unlike `parseTrackRole`, this NEVER throws:
90
+ * names without a `/`, and names with an unrecognised suffix (e.g. an ABR
91
+ * resolution ladder like `video/1080p`, `video/720p`, `video/8k`), simply do
92
+ * not count as a role.
93
+ *
94
+ * Use this for DETECTION ("is this a switching set?"). Once a switching set is
95
+ * confirmed, `parseTrackRole` / `validateSwitchingSet` still strictly gate the
96
+ * actual wiring. ABR ladders yield `false` here and fall through to the
97
+ * ABR/single path instead of throwing.
98
+ */
99
+ export function hasSwitchingSetRole(names: string[]): boolean {
100
+ return names.some((name) => {
101
+ const lastSlash = name.lastIndexOf("/");
102
+ if (lastSlash === -1) return false;
103
+ const suffix = name.slice(lastSlash + 1);
104
+ return suffix === "base" || suffix === "delta";
105
+ });
106
+ }
107
+
108
+ /**
109
+ * Validate that a set of track names forms a complete switching set.
110
+ *
111
+ * - Empty or single-track sets (all parsing to `"single"`) → `{ ok: true }`.
112
+ * - Multi-track sets (any name has a role suffix) MUST include all three
113
+ * roles (`base`, `delta`, `repair`). Missing roles are listed.
114
+ *
115
+ * Propagates throws from `parseTrackRole` (non-ASCII, unknown suffix, etc.).
116
+ *
117
+ * D-04: Legacy single-track streams pass without enforcement.
118
+ * D-04: Once any suffix appears, the set is multi-track and must be complete.
119
+ */
120
+ export function validateSwitchingSet(
121
+ trackNames: string[],
122
+ ): { ok: true } | { ok: false; missing: TrackRole[] } {
123
+ if (trackNames.length === 0) return { ok: true };
124
+
125
+ const roles = trackNames.map(parseTrackRole);
126
+
127
+ // If every role is "single", this is a legacy single-track stream — pass.
128
+ if (roles.every((r) => r === "single")) {
129
+ return { ok: true };
130
+ }
131
+
132
+ // Multi-track: at least one name has a role suffix.
133
+ // The set MUST contain all three required roles.
134
+ // Explicit Set<TrackRole> so the TrackRole-typed `required.filter`
135
+ // callback can call .has(r) without a narrow-mismatch complaint.
136
+ const presentRoles: Set<TrackRole> = new Set(roles.filter((r) => r !== "single"));
137
+ const required: TrackRole[] = ["base", "delta", "repair"];
138
+ const missing = required.filter((r) => !presentRoles.has(r));
139
+
140
+ if (missing.length > 0) {
141
+ return { ok: false, missing };
142
+ }
143
+ return { ok: true };
144
+ }
145
+
146
+ // ── FEC Catalog Extension (CARP §3.2) ─────────────────────────
147
+
148
+ export type FecAlgorithm = "none" | "raptorq" | "reed-solomon";
149
+
150
+ export interface FecCatalogConfig {
151
+ /** FEC algorithm identifier (REQUIRED per §4.1, values per §3.1). */
152
+ algorithm: FecAlgorithm;
153
+ /** K — source symbols per block (REQUIRED). */
154
+ sourceSymbols: number;
155
+ /** P — repair symbols per block (REQUIRED). */
156
+ repairSymbols: number;
157
+ /** T — bytes per symbol, 8-byte aligned (REQUIRED). */
158
+ symbolSize: number;
159
+ /** FEC block span in MILLISECONDS (OPTIONAL, default 0 = single-group blocks).
160
+ * D is the positive round-half-up value of interleaveDepthMs / GOP_duration_ms.
161
+ * BLO-14526: renamed from the legacy `interleaveDepth` count-era key — no fallback read. */
162
+ interleaveDepthMs?: number;
163
+ /** Declared jitter/reorder allowance in MILLISECONDS.
164
+ * Added to interleaveDepthMs to form a block's deadline; never multiplied
165
+ * by it. Jitter is a property of the network path and the block span is a
166
+ * property of the encoder, so a multiplicative "safety factor" couples two
167
+ * independent quantities and grants different slack per track for the same
168
+ * network. Consumed identically by FECManager, FEC workers and player
169
+ * policies so one signaled value governs end to end. */
170
+ reorderToleranceMs?: number;
171
+ /** Track name for repair symbols (REQUIRED per §6.1). */
172
+ repairTrack: string;
173
+ /** FEC block mode: "interleaved" (default) or "object" (per-frame). */
174
+ // extensions feature — see moqcast-draft docs/fec-extensions-material.md, not in public -00
175
+ mode?: "interleaved" | "object";
176
+ /** UEP (Unequal Error Protection) — extensions feature, see moqcast-draft docs/fec-extensions-material.md, not in public -00. When present, repair count
177
+ * varies per frame type. repairSymbols becomes the base (P-frame) count.
178
+ * MUST be omitted on multi-track base/delta streams (D-08). */
179
+ uep?: {
180
+ /** Keyframe repair ratio: P = ceil(K * keyRatio). Default 0.5. */
181
+ keyRatio: number;
182
+ /** Delta frame repair ratio: P = ceil(K * deltaRatio). Default 0.25. */
183
+ deltaRatio: number;
184
+ };
185
+ /**
186
+ * Base-only fallback window in FEC blocks (D-11, Phase 14).
187
+ *
188
+ * When the delta track's FEC block failure rate exceeds the derived threshold
189
+ * over this many consecutive blocks, MediaRouter falls back to base-only mode.
190
+ * Derivation: framerate * fallback_window_seconds. If absent, construction
191
+ * of the multi-track subscriber MUST throw (error on bad init).
192
+ *
193
+ * Present only on the base track's fec config (not the delta or repair track).
194
+ */
195
+ deltaFailWindowBlocks?: number;
196
+ /**
197
+ * Delta re-subscribe probe interval in milliseconds (D-13, Phase 14).
198
+ *
199
+ * After a base-only fallback, wait this long before re-subscribing to the
200
+ * delta track to check if conditions have improved.
201
+ * Derivation: computeFecDeliveryWindowMs(...) — the single FEC recovery-window
202
+ * source of truth (draft-ramadan-moq-fec §9). Never a fixed interleave multiple.
203
+ *
204
+ * Present only on the base track's fec config (not the delta or repair track).
205
+ */
206
+ deltaProbeIntervalMs?: number;
207
+ /**
208
+ * Jitter + one-way-delay + reorder budget in MILLISECONDS (draft §9).
209
+ *
210
+ * The single catalog source for the ADDITIVE margin that the FEC
211
+ * recovery/loss window adds on top of max(interleave span, source+repair horizon,
212
+ * block serialization) — see computeFecDeliveryWindowMs. It is a margin, not
213
+ * a multiplier. OPTIONAL: when absent, the derivation falls back to the
214
+ * un-rounded interleave window as the reorder-budget bound (margin-policy).
215
+ */
216
+ jitterBufferMs?: number;
217
+ }
218
+
219
+ export function isFecCatalogConfig(obj: unknown): obj is FecCatalogConfig {
220
+ if (typeof obj !== "object" || obj === null) return false;
221
+ const o = obj as Record<string, unknown>;
222
+ const algorithm = o["algorithm"];
223
+ const symbolSize = o["symbolSize"];
224
+ return (
225
+ typeof algorithm === "string" &&
226
+ (algorithm === "none" || algorithm === "raptorq" || algorithm === "reed-solomon") &&
227
+ typeof o["sourceSymbols"] === "number" && o["sourceSymbols"] >= 1 &&
228
+ typeof o["repairSymbols"] === "number" && o["repairSymbols"] >= 1 &&
229
+ typeof symbolSize === "number" && symbolSize >= 1 &&
230
+ (algorithm !== "raptorq" || symbolSize % 8 === 0) &&
231
+ typeof o["repairTrack"] === "string" && (o["repairTrack"] as string).length > 0
232
+ );
233
+ }
234
+
235
+ // ── Multicast Catalog Extension (CARP §4.1-4.4) ───────────────
236
+
237
+ export type MulticastProtocol = "ssm" | "asm" | "amt" | "atsc3";
238
+
239
+ /**
240
+ * Per-track endpoint membership, per draft-ramadan-moq-multicast-00 §4.1.
241
+ *
242
+ * `packetId` is the MMTP packet_id used for packet-level demux on the
243
+ * multicast wire. New emitters MUST use this object form; the legacy
244
+ * `string` form is accepted by parsers for one release for backward
245
+ * compatibility (BLO-3323 migration).
246
+ */
247
+ export interface MulticastTrackObject {
248
+ name: string;
249
+ packetId: number;
250
+ }
251
+
252
+ /** Track entry in a multicast endpoint — accepts both legacy and v2 shape. */
253
+ export type MulticastTrack = string | MulticastTrackObject;
254
+
255
+ export interface MulticastEndpoint {
256
+ /** Transport protocol. Defaults to SSM when sourceAddress is present. */
257
+ protocol?: MulticastProtocol;
258
+ /** SSM source IP address (REQUIRED for SSM). */
259
+ sourceAddress?: string;
260
+ /** Multicast group address (REQUIRED). */
261
+ groupAddress: string;
262
+ /** UDP port number (REQUIRED). */
263
+ port: number;
264
+ /**
265
+ * Tracks available on this endpoint (REQUIRED).
266
+ *
267
+ * Accepts both legacy `string` (track name only) and v2 object form
268
+ * (`{ name, packetId }`) for backward compatibility. New emitters
269
+ * MUST use the object form (BLO-3323 / draft §4.1). Consumers can
270
+ * type-narrow with `typeof t === "string"` to handle both.
271
+ */
272
+ tracks: MulticastTrack[];
273
+ /** AMT relay hostname (REQUIRED for AMT). */
274
+ relayAddress?: string;
275
+ /**
276
+ * Aggregate bandwidth of this endpoint in bits per second.
277
+ * RECOMMENDED per draft §4.1 — enables capacity-aware joins.
278
+ */
279
+ bandwidth?: number;
280
+ }
281
+
282
+ export type AmtDiscovery = "driad" | "manual";
283
+
284
+ export interface MulticastCatalogConfig {
285
+ /** Enable/disable multicast (OPTIONAL, default true). */
286
+ enabled?: boolean;
287
+ /** Multicast endpoints (REQUIRED). */
288
+ endpoints: MulticastEndpoint[];
289
+ /** AMT fallback configuration (OPTIONAL). */
290
+ amtFallback?: {
291
+ discovery: AmtDiscovery;
292
+ relayDns?: string;
293
+ };
294
+ /**
295
+ * Monotonic catalog version. Publishers MUST bump on any
296
+ * `endpoints[]` mutation (BLO-3323 catalog freshness model).
297
+ */
298
+ version?: number;
299
+ /**
300
+ * Unix-ms timestamp after which subscribers SHOULD refetch the
301
+ * catalog. Refetch-on-multicast-receive-timeout short-circuits this.
302
+ */
303
+ validUntil?: number;
304
+ }
305
+
306
+ export function isMulticastTrackObject(obj: unknown): obj is MulticastTrackObject {
307
+ if (typeof obj !== "object" || obj === null) return false;
308
+ const o = obj as Record<string, unknown>;
309
+ return typeof o["name"] === "string" && typeof o["packetId"] === "number";
310
+ }
311
+
312
+ /**
313
+ * Wire-shape predicate: returns `true` when `obj` matches the
314
+ * MulticastEndpoint JSON shape strictly enough to be safely cast.
315
+ *
316
+ * Intentionally less strict than `multicastFromConfig`'s
317
+ * `validateEndpoint` (in `multicast-input.ts`):
318
+ *
319
+ * - `tracks: []` is accepted here (Array.isArray check only) but
320
+ * rejected by `validateEndpoint` as `empty_tracks`.
321
+ * - SSM-specific group-range and source-required checks are not
322
+ * enforced here.
323
+ * - Bandwidth/AmtFallback/version are not type-checked.
324
+ *
325
+ * That asymmetry is deliberate: this predicate guards JSON parsed off
326
+ * the wire (already-published catalogs that downstream may have
327
+ * trimmed), while `validateEndpoint` guards publisher input *before*
328
+ * a catalog is composed. Subscribers are tolerant; publishers are
329
+ * strict — the catalog format never re-validates upstream invariants.
330
+ */
331
+ export function isMulticastEndpoint(obj: unknown): obj is MulticastEndpoint {
332
+ if (typeof obj !== "object" || obj === null) return false;
333
+ const o = obj as Record<string, unknown>;
334
+ const protocol = o["protocol"] ??
335
+ (typeof o["sourceAddress"] === "string" && o["sourceAddress"].length > 0 ? "ssm" : undefined);
336
+ return (
337
+ typeof protocol === "string" &&
338
+ (protocol === "ssm" || protocol === "asm" || protocol === "amt" || protocol === "atsc3") &&
339
+ typeof o["groupAddress"] === "string" && (o["groupAddress"] as string).length > 0 &&
340
+ typeof o["port"] === "number" && (o["port"] as number) > 0 && (o["port"] as number) <= 65535 &&
341
+ Array.isArray(o["tracks"]) &&
342
+ (o["tracks"] as unknown[]).every((t: unknown) => typeof t === "string" || isMulticastTrackObject(t))
343
+ );
344
+ }
345
+
346
+ export function isMulticastCatalogConfig(obj: unknown): obj is MulticastCatalogConfig {
347
+ if (typeof obj !== "object" || obj === null) return false;
348
+ const o = obj as Record<string, unknown>;
349
+ return (
350
+ Array.isArray(o["endpoints"]) &&
351
+ (o["endpoints"] as unknown[]).every((ep: unknown) => isMulticastEndpoint(ep))
352
+ );
353
+ }
354
+
355
+ // ── Track Timing (mmt-00 §4.4.4) ──────────────────────────────
356
+
357
+ /**
358
+ * Per-track group-duration signaling.
359
+ *
360
+ * The catalog publishes either `groupDurationMs` (integer ms) or the exact
361
+ * `groupDurationTicks` value used by `groupIdForTicks` in align.ts. The tick
362
+ * form is required for cases where milliseconds cannot represent the cadence
363
+ * exactly:
364
+ *
365
+ * - Per-frame group durations at non-integer-ms cadences
366
+ * (1/30 s = 33.333… ms; 1/60 s = 16.666… ms).
367
+ * - Audio sample-rate timescales not divisible by 1000 Hz
368
+ * (e.g. 44 100 Hz × 333 ms = 14 685.3 ticks).
369
+ *
370
+ * If both fields are present, `groupDurationTicks` wins (matches the
371
+ * spec, mmt-00 §4.4.4).
372
+ *
373
+ * @see draft-ramadan-moq-mmt-00 §4.4.4
374
+ * @see ./align.ts groupIdForTicks
375
+ */
376
+ export interface TrackTimingConfig {
377
+ /** Group duration in milliseconds (positive integer). Required unless an
378
+ * exact groupDurationTicks value is supplied. */
379
+ groupDurationMs?: number;
380
+ /** Integer-tick override (OPTIONAL, positive integer). Wins over the
381
+ * ms field when both are present. Required when
382
+ * `(groupDurationMs * timescale) % 1000 != 0`. */
383
+ groupDurationTicks?: number;
384
+ }
385
+
386
+ export function isTrackTimingConfig(obj: unknown): obj is TrackTimingConfig {
387
+ if (typeof obj !== "object" || obj === null) return false;
388
+ const o = obj as Record<string, unknown>;
389
+ const ms = o["groupDurationMs"];
390
+ const ticks = o["groupDurationTicks"];
391
+ if (ms === undefined && ticks === undefined) return false;
392
+ if (ms !== undefined && (typeof ms !== "number" || !Number.isInteger(ms) || ms <= 0)) return false;
393
+ if ("groupDurationTicks" in o) {
394
+ if (ticks === undefined) return ms !== undefined;
395
+ if (typeof ticks !== "number" || !Number.isInteger(ticks) || ticks <= 0) return false;
396
+ }
397
+ return true;
398
+ }
399
+
400
+ /** Resolve catalog group timing to an operational wall-clock duration.
401
+ *
402
+ * `groupDurationTicks` wins when both wire fields are present, matching
403
+ * mmt-00 §4.4.4. The result may be fractional because exact frame cadences
404
+ * such as 33_333 ticks at 1 MHz cannot be represented by the wire catalog's
405
+ * integer `groupDurationMs` field.
406
+ */
407
+ export function resolveGroupDurationMs(
408
+ timing: TrackTimingConfig,
409
+ timescale: number,
410
+ ): number {
411
+ if (!Number.isSafeInteger(timescale) || timescale <= 0) {
412
+ throw new Error(
413
+ `[carp-catalog] resolveGroupDurationMs: timescale must be a positive safe integer Hz, got ${timescale}`,
414
+ );
415
+ }
416
+ if (!isTrackTimingConfig(timing)) {
417
+ throw new Error(
418
+ `[carp-catalog] resolveGroupDurationMs: invalid TrackTimingConfig: ${JSON.stringify(timing)}`,
419
+ );
420
+ }
421
+ if (timing.groupDurationTicks === undefined) {
422
+ return timing.groupDurationMs!;
423
+ }
424
+
425
+ const durationMs = (timing.groupDurationTicks / timescale) * 1000;
426
+ if (!Number.isFinite(durationMs) || durationMs <= 0 || durationMs > Number.MAX_SAFE_INTEGER) {
427
+ throw new Error(
428
+ `[carp-catalog] resolveGroupDurationMs: groupDurationTicks=${timing.groupDurationTicks} ` +
429
+ `at timescale=${timescale} cannot be represented as a positive safe millisecond duration`,
430
+ );
431
+ }
432
+ return durationMs;
433
+ }
434
+
435
+ export type CmsfCatalog = {
436
+ version: number;
437
+ tracks: Record<string, unknown>[];
438
+ commonTrackFields?: Record<string, unknown>;
439
+ multicast?: Record<string, unknown>;
440
+ "multicast.auth"?: MulticastAuthConfig;
441
+ [key: string]: unknown;
442
+ };
443
+
444
+ export type CmsfCatalogErrorCode =
445
+ | "catalog_object"
446
+ | "catalog_version"
447
+ | "catalog_tracks"
448
+ | "track_object"
449
+ | "track_name"
450
+ | "track_packaging"
451
+ | "track_is_live"
452
+ | "track_codec"
453
+ | "track_mmtp_mode"
454
+ | "track_timescale"
455
+ | "track_group_duration_ms"
456
+ | "track_group_duration_ticks"
457
+ | "track_group_duration_exact"
458
+ | "track_keyframe_interval"
459
+ | "track_fec"
460
+ | "track_repair_track"
461
+ | "track_switching_set"
462
+ | "multicast_auth"
463
+ | "multicast_track"
464
+ | "multicast_packet_id";
465
+
466
+ export class CmsfCatalogValidationError extends Error {
467
+ constructor(
468
+ public readonly code: CmsfCatalogErrorCode,
469
+ public readonly path: string,
470
+ message: string,
471
+ ) {
472
+ super(`[cmsf:${code}] ${path}: ${message}`);
473
+ this.name = "CmsfCatalogValidationError";
474
+ }
475
+ }
476
+
477
+ function catalogError(code: CmsfCatalogErrorCode, path: string, message: string): never {
478
+ throw new CmsfCatalogValidationError(code, path, message);
479
+ }
480
+
481
+ /** Validate the common CMSF shape and the MMTP required-field profile. */
482
+ export function validateCmsfMmtpCatalog(value: unknown): CmsfCatalog {
483
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
484
+ catalogError("catalog_object", "$", "catalog must be an object");
485
+ }
486
+ const catalog = value as Record<string, unknown>;
487
+ // IETF-draft catalogs (cast `ladder_catalog.rs`, moq-server
488
+ // `catalog-synthesizer.ts`, consumed by the hang player) carry a string
489
+ // version tag such as "draft-ietf-moq-catalogformat-01" instead of the CMSF
490
+ // `version: 1` integer. Nothing keys behavior off the catalog version, so
491
+ // normalize the tag to a number rather than rejecting the whole catalog —
492
+ // mirrors the relay (dual-stack-relay `bridge/catalog.rs`
493
+ // `deserialize_optional_u32_lenient`, #825) and moqtail-ts
494
+ // `normalizeCatalogVersion`.
495
+ const rawVersion = catalog["version"];
496
+ const normalizedVersion =
497
+ typeof rawVersion === "string"
498
+ ? Number.isFinite(Number(rawVersion))
499
+ ? Number(rawVersion)
500
+ : rawVersion.startsWith("draft-ietf-moq-catalogformat")
501
+ ? 1
502
+ : NaN
503
+ : rawVersion;
504
+ if (!Number.isInteger(normalizedVersion) || (normalizedVersion as number) <= 0) {
505
+ catalogError("catalog_version", "$.version", "version must be a positive integer or a recognized format tag");
506
+ }
507
+ catalog["version"] = normalizedVersion;
508
+ if (!Array.isArray(catalog["tracks"])) {
509
+ catalogError("catalog_tracks", "$.tracks", "tracks must be an array");
510
+ }
511
+
512
+ const common = typeof catalog["commonTrackFields"] === "object" &&
513
+ catalog["commonTrackFields"] !== null && !Array.isArray(catalog["commonTrackFields"])
514
+ ? catalog["commonTrackFields"] as Record<string, unknown>
515
+ : {};
516
+ const tracks = catalog["tracks"] as unknown[];
517
+ const trackRecords: Record<string, unknown>[] = [];
518
+ const effective = (track: Record<string, unknown>, field: string): unknown => track[field] ?? common[field];
519
+ const positiveInteger = (input: unknown): input is number => Number.isSafeInteger(input) && (input as number) > 0;
520
+ const positiveNumber = (input: unknown): input is number =>
521
+ typeof input === "number" && Number.isFinite(input) && input > 0;
522
+
523
+ for (let index = 0; index < tracks.length; index++) {
524
+ const raw = tracks[index];
525
+ const path = `$.tracks[${index}]`;
526
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
527
+ catalogError("track_object", path, "track must be an object");
528
+ }
529
+ const track = raw as Record<string, unknown>;
530
+ const name = track["name"];
531
+ if (typeof name !== "string" || name.length === 0) {
532
+ catalogError("track_name", `${path}.name`, "name must be a non-empty string");
533
+ }
534
+ trackRecords.push(track);
535
+
536
+ const packaging = effective(track, "packaging");
537
+ if (typeof packaging !== "string" || packaging.length === 0) {
538
+ catalogError("track_packaging", `${path}.packaging`, "packaging must be a non-empty string");
539
+ }
540
+ const trackHasIsLive = Object.prototype.hasOwnProperty.call(track, "isLive");
541
+ const hasIsLive = trackHasIsLive || Object.prototype.hasOwnProperty.call(common, "isLive");
542
+ const isLive = trackHasIsLive ? track["isLive"] : common["isLive"];
543
+ if (hasIsLive && typeof isLive !== "boolean") {
544
+ catalogError("track_is_live", `${path}.isLive`, "isLive must be a boolean");
545
+ }
546
+ track["isLive"] = isLive ?? true;
547
+ const selectionValue = effective(track, "selectionParams");
548
+ const selection = typeof selectionValue === "object" && selectionValue !== null && !Array.isArray(selectionValue)
549
+ ? selectionValue as Record<string, unknown>
550
+ : undefined;
551
+ const codec = selection?.["codec"] ?? effective(track, "codec");
552
+ if (packaging !== "timeline" && packaging !== "mediatimeline" && packaging !== "eventtimeline" && packaging !== "fec-repair" &&
553
+ (typeof codec !== "string" || codec.length === 0)) {
554
+ catalogError("track_codec", `${path}.codec`, `codec is required for packaging=${packaging}`);
555
+ }
556
+
557
+ const timescale = effective(track, "timescale");
558
+ const groupDurationMs = effective(track, "groupDurationMs");
559
+ const groupDurationTicks = effective(track, "groupDurationTicks");
560
+ const keyframeIntervalMs = effective(track, "keyframeIntervalMs");
561
+ const keyframeIntervalTicks = effective(track, "keyframeIntervalTicks");
562
+ if (groupDurationMs !== undefined && !positiveInteger(groupDurationMs)) {
563
+ catalogError("track_group_duration_ms", `${path}.groupDurationMs`, "must be a positive integer");
564
+ }
565
+ if (groupDurationTicks !== undefined && !positiveInteger(groupDurationTicks)) {
566
+ catalogError("track_group_duration_ticks", `${path}.groupDurationTicks`, "must be a positive integer");
567
+ }
568
+ if ((keyframeIntervalMs !== undefined && !positiveNumber(keyframeIntervalMs)) ||
569
+ (keyframeIntervalTicks !== undefined && !positiveInteger(keyframeIntervalTicks))) {
570
+ catalogError("track_keyframe_interval", path, "keyframe interval fields must be positive numbers");
571
+ }
572
+ if (packaging === "mmtp") {
573
+ const mmtpMode = effective(track, "mmtpMode");
574
+ if (mmtpMode !== "mpu" && mmtpMode !== "mfu") {
575
+ catalogError("track_mmtp_mode", `${path}.mmtpMode`, "must be mpu or mfu");
576
+ }
577
+ if (!positiveInteger(timescale)) {
578
+ catalogError("track_timescale", `${path}.timescale`, "must be a positive integer");
579
+ }
580
+ if (groupDurationMs === undefined && groupDurationTicks === undefined) {
581
+ catalogError(
582
+ "track_group_duration_ms",
583
+ path,
584
+ "groupDurationMs or groupDurationTicks must be a positive integer",
585
+ );
586
+ }
587
+ if (groupDurationTicks === undefined &&
588
+ (BigInt(groupDurationMs as number) * BigInt(timescale)) % 1000n !== 0n) {
589
+ catalogError("track_group_duration_exact", `${path}.groupDurationMs`, "does not resolve to an exact integer tick count");
590
+ }
591
+ }
592
+
593
+ if (track["fec"] !== undefined) {
594
+ const fec = track["fec"];
595
+ if (typeof fec !== "object" || fec === null || Array.isArray(fec)) {
596
+ catalogError("track_fec", `${path}.fec`, "FEC must be an object");
597
+ }
598
+ const config = fec as Record<string, unknown>;
599
+ const algorithm = config["algorithm"];
600
+ if (algorithm !== "none" && algorithm !== "raptorq" && algorithm !== "reed-solomon") {
601
+ catalogError("track_fec", `${path}.fec.algorithm`, "algorithm is not supported");
602
+ }
603
+ if ("interleaveDepth" in config || "interleaveMs" in config) {
604
+ catalogError("track_fec", `${path}.fec`, "interleaveDepthMs is the only supported interleave field");
605
+ }
606
+ if (config["interleaveDepthMs"] !== undefined && !positiveInteger(config["interleaveDepthMs"])) {
607
+ catalogError("track_fec", `${path}.fec.interleaveDepthMs`, "must be a positive integer");
608
+ }
609
+ if (algorithm !== "none") {
610
+ for (const field of ["sourceSymbols", "repairSymbols", "symbolSize"] as const) {
611
+ if (!positiveInteger(config[field])) {
612
+ catalogError("track_fec", `${path}.fec.${field}`, "must be a positive integer");
613
+ }
614
+ }
615
+ if (typeof config["repairTrack"] !== "string" || config["repairTrack"].length === 0) {
616
+ catalogError("track_fec", `${path}.fec.repairTrack`, "must be a non-empty string");
617
+ }
618
+ }
619
+ }
620
+ }
621
+
622
+ for (let index = 0; index < trackRecords.length; index++) {
623
+ const track = trackRecords[index]!;
624
+ const fec = track["fec"] as Record<string, unknown> | undefined;
625
+ if (!fec || fec["algorithm"] === "none") continue;
626
+ const repairTrack = fec["repairTrack"] as string;
627
+ const target = trackRecords.find((candidate) => candidate["name"] === repairTrack);
628
+ if (!target || effective(target, "packaging") !== "fec-repair") {
629
+ catalogError("track_repair_track", `$.tracks[${index}].fec.repairTrack`, `unknown FEC repair track ${JSON.stringify(repairTrack)}`);
630
+ }
631
+ }
632
+
633
+ const switchingSets = new Map<number, { name: string; ticks: bigint; timescale: bigint }>();
634
+ for (let index = 0; index < trackRecords.length; index++) {
635
+ const track = trackRecords[index]!;
636
+ if (effective(track, "packaging") !== "mmtp") continue;
637
+ const altGroup = effective(track, "altGroup");
638
+ if (!Number.isSafeInteger(altGroup)) continue;
639
+ const timescale = BigInt(effective(track, "timescale") as number);
640
+ const durationTicks = effective(track, "groupDurationTicks");
641
+ const ticks = durationTicks !== undefined
642
+ ? BigInt(durationTicks as number)
643
+ : BigInt(effective(track, "groupDurationMs") as number) * timescale / 1000n;
644
+ const anchor = switchingSets.get(altGroup as number);
645
+ if (anchor && ticks * anchor.timescale !== anchor.ticks * timescale) {
646
+ catalogError("track_switching_set", `$.tracks[${index}]`, `group duration does not match ${JSON.stringify(anchor.name)} in altGroup ${altGroup}`);
647
+ }
648
+ if (!anchor) switchingSets.set(altGroup as number, { name: track["name"] as string, ticks, timescale });
649
+ }
650
+
651
+ const multicast = catalog["multicast"];
652
+ if (typeof multicast === "object" && multicast !== null && !Array.isArray(multicast)) {
653
+ const endpoints = (multicast as Record<string, unknown>)["endpoints"];
654
+ if (Array.isArray(endpoints)) {
655
+ for (let endpointIndex = 0; endpointIndex < endpoints.length; endpointIndex++) {
656
+ const endpoint = endpoints[endpointIndex];
657
+ if (typeof endpoint !== "object" || endpoint === null || Array.isArray(endpoint)) continue;
658
+ const refs = (endpoint as Record<string, unknown>)["tracks"];
659
+ if (!Array.isArray(refs)) continue;
660
+ const packetIds = new Map<number, string>();
661
+ for (let refIndex = 0; refIndex < refs.length; refIndex++) {
662
+ const ref = refs[refIndex];
663
+ if (typeof ref !== "object" || ref === null || Array.isArray(ref)) continue;
664
+ const trackRef = ref as Record<string, unknown>;
665
+ const refPath = `$.multicast.endpoints[${endpointIndex}].tracks[${refIndex}]`;
666
+ const name = trackRef["name"];
667
+ if (typeof name !== "string" || !trackRecords.some((track) => track["name"] === name)) {
668
+ catalogError("multicast_track", `${refPath}.name`, `unknown catalog track ${JSON.stringify(name)}`);
669
+ }
670
+ const packetId = trackRef["packetId"];
671
+ if (!Number.isSafeInteger(packetId) || (packetId as number) < 0 || (packetId as number) > 65535) {
672
+ catalogError("multicast_packet_id", `${refPath}.packetId`, "packetId must be an integer from 0 to 65535");
673
+ }
674
+ const previous = packetIds.get(packetId as number);
675
+ if (previous !== undefined) {
676
+ catalogError("multicast_packet_id", `${refPath}.packetId`, `packetId is already assigned to ${JSON.stringify(previous)}`);
677
+ }
678
+ packetIds.set(packetId as number, name as string);
679
+ }
680
+ }
681
+ }
682
+ }
683
+
684
+ try {
685
+ resolveMulticastAuthCatalog(catalog);
686
+ } catch (error) {
687
+ catalogError(
688
+ "multicast_auth",
689
+ "$.multicast.auth",
690
+ error instanceof Error ? error.message : "invalid multicast.auth v2 block",
691
+ );
692
+ }
693
+
694
+ return catalog as CmsfCatalog;
695
+ }
696
+
697
+ /**
698
+ * Resolve a track's group duration to integer ticks using the supplied
699
+ * timescale (Hz). Implements mmt-00 §4.4.4:
700
+ *
701
+ * - If `groupDurationTicks` is present, return it (override wins).
702
+ * - Else compute `groupDurationMs * timescale / 1000`. The result MUST
703
+ * be an exact integer; throws if `(ms * timescale) % 1000 != 0`.
704
+ *
705
+ * Throws on invalid timing config or non-positive timescale (CLAUDE.md:
706
+ * error on bad init).
707
+ */
708
+ export function resolveGroupDurationTicks(
709
+ timing: TrackTimingConfig,
710
+ timescale: number,
711
+ ): number {
712
+ if (!Number.isFinite(timescale) || !Number.isInteger(timescale) || timescale <= 0) {
713
+ throw new Error(
714
+ `[carp-catalog] resolveGroupDurationTicks: timescale must be a positive integer Hz, got ${timescale}`,
715
+ );
716
+ }
717
+ if (!isTrackTimingConfig(timing)) {
718
+ throw new Error(
719
+ `[carp-catalog] resolveGroupDurationTicks: invalid TrackTimingConfig: ${JSON.stringify(timing)}`,
720
+ );
721
+ }
722
+ if (timing.groupDurationTicks !== undefined) {
723
+ return timing.groupDurationTicks;
724
+ }
725
+ if (timing.groupDurationMs === undefined) {
726
+ throw new Error(
727
+ "[carp-catalog] resolveGroupDurationTicks: groupDurationMs is required when groupDurationTicks is absent",
728
+ );
729
+ }
730
+ const product = timing.groupDurationMs * timescale;
731
+ if (product % 1000 !== 0) {
732
+ throw new Error(
733
+ `[carp-catalog] resolveGroupDurationTicks: groupDurationMs=${timing.groupDurationMs} at timescale=${timescale} ` +
734
+ `produces non-integer ticks (${product / 1000}); publisher must use groupDurationTicks override (mmt-00 §4.4.4)`,
735
+ );
736
+ }
737
+ return product / 1000;
738
+ }
739
+
740
+ /**
741
+ * Validate that every track in a switching set agrees on the same
742
+ * wall-clock group duration (mmt-00 §4.4.4). Per-track timescales may
743
+ * differ, so raw tick counts cannot be compared directly.
744
+ *
745
+ * Returns `{ ok: true }` when all tracks agree (or the set is empty);
746
+ * `{ ok: false, mismatches }` listing each track whose effective ticks
747
+ * differ from the first track's value. Subscribers per spec SHOULD
748
+ * reject the catalog on mismatch.
749
+ *
750
+ * Throws if any track's timing config is invalid (per
751
+ * `resolveGroupDurationTicks`).
752
+ */
753
+ export function validateSwitchingSetTiming(
754
+ tracks: Array<{ name: string; timing: TrackTimingConfig; timescale: number }>,
755
+ ):
756
+ | { ok: true }
757
+ | { ok: false; expectedTicks: number; mismatches: Array<{ name: string; ticks: number }> } {
758
+ if (tracks.length === 0) return { ok: true };
759
+ const ticksByTrack = tracks.map((t) => ({
760
+ name: t.name,
761
+ ticks: resolveGroupDurationTicks(t.timing, t.timescale),
762
+ timescale: t.timescale,
763
+ }));
764
+ const expectedTicks = ticksByTrack[0].ticks;
765
+ const expectedTimescale = ticksByTrack[0].timescale;
766
+ const mismatches = ticksByTrack
767
+ .slice(1)
768
+ .filter(
769
+ (t) =>
770
+ BigInt(t.ticks) * BigInt(expectedTimescale) !==
771
+ BigInt(expectedTicks) * BigInt(t.timescale),
772
+ )
773
+ .map(({ name, ticks }) => ({ name, ticks }));
774
+ if (mismatches.length === 0) return { ok: true };
775
+ return { ok: false, expectedTicks, mismatches };
776
+ }