@blockcast/mmt-container 0.1.0-main.0399efef1f07

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 (694) 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 +152 -0
  6. package/dist/align.d.ts.map +1 -0
  7. package/dist/align.js +88 -0
  8. package/dist/align.js.map +7 -0
  9. package/dist/audio-init-parser.d.ts +66 -0
  10. package/dist/audio-init-parser.d.ts.map +1 -0
  11. package/dist/audio-init-parser.js +118 -0
  12. package/dist/audio-init-parser.js.map +7 -0
  13. package/dist/audio-ring-buffer.d.ts +50 -0
  14. package/dist/audio-ring-buffer.d.ts.map +1 -0
  15. package/dist/audio-ring-buffer.js +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 +20087 -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 +873 -0
  26. package/dist/carp-catalog.js.map +7 -0
  27. package/dist/catalog-fec-params.d.ts +202 -0
  28. package/dist/catalog-fec-params.d.ts.map +1 -0
  29. package/dist/catalog-fec-params.js +568 -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 +217 -0
  40. package/dist/cmaf-block-assembler.d.ts.map +1 -0
  41. package/dist/cmaf-block-assembler.js +1769 -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 +248 -0
  52. package/dist/codec-utils.d.ts.map +1 -0
  53. package/dist/codec-utils.js +1268 -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 +307 -0
  60. package/dist/fec-manager.d.ts.map +1 -0
  61. package/dist/fec-manager.js +1530 -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 +88 -0
  68. package/dist/fec-worker-setup.d.ts.map +1 -0
  69. package/dist/fec-worker-setup.js +614 -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 +380 -0
  82. package/dist/index.js.map +7 -0
  83. package/dist/iso-bmff-timing.d.ts +78 -0
  84. package/dist/iso-bmff-timing.d.ts.map +1 -0
  85. package/dist/iso-bmff-timing.js +618 -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 +1285 -0
  94. package/dist/manifest-auth-plan.js.map +7 -0
  95. package/dist/media-router.d.ts +251 -0
  96. package/dist/media-router.d.ts.map +1 -0
  97. package/dist/media-router.js +624 -0
  98. package/dist/media-router.js.map +7 -0
  99. package/dist/mfu-reassembler.d.ts +396 -0
  100. package/dist/mfu-reassembler.d.ts.map +1 -0
  101. package/dist/mfu-reassembler.js +3085 -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 +434 -0
  108. package/dist/mmtp-container-parser.d.ts.map +1 -0
  109. package/dist/mmtp-container-parser.js +6164 -0
  110. package/dist/mmtp-container-parser.js.map +7 -0
  111. package/dist/mmtp-container-parser.no-modules.js +8999 -0
  112. package/dist/mmtp-container-parser.no-modules.js.map +7 -0
  113. package/dist/mmtp-decode-pipeline.d.ts +132 -0
  114. package/dist/mmtp-decode-pipeline.d.ts.map +1 -0
  115. package/dist/mmtp-decode-pipeline.js +6413 -0
  116. package/dist/mmtp-decode-pipeline.js.map +7 -0
  117. package/dist/mmtp-router.d.ts +390 -0
  118. package/dist/mmtp-router.d.ts.map +1 -0
  119. package/dist/mmtp-router.js +9242 -0
  120. package/dist/mmtp-router.js.map +7 -0
  121. package/dist/mmtp-to-cmaf.d.ts +181 -0
  122. package/dist/mmtp-to-cmaf.d.ts.map +1 -0
  123. package/dist/mmtp-to-cmaf.js +802 -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 +369 -0
  134. package/dist/multicast-manager.d.ts.map +1 -0
  135. package/dist/multicast-manager.js +13400 -0
  136. package/dist/multicast-manager.js.map +7 -0
  137. package/dist/multicast-transport.d.ts +61 -0
  138. package/dist/multicast-transport.d.ts.map +1 -0
  139. package/dist/multicast-transport.js +1665 -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 +8965 -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 +127 -0
  156. package/dist/repair-fetch.js.map +7 -0
  157. package/dist/repair-layers.d.ts +141 -0
  158. package/dist/repair-layers.d.ts.map +1 -0
  159. package/dist/repair-layers.js +303 -0
  160. package/dist/repair-layers.js.map +7 -0
  161. package/dist/sample-combiner.d.ts +212 -0
  162. package/dist/sample-combiner.d.ts.map +1 -0
  163. package/dist/sample-combiner.js +616 -0
  164. package/dist/sample-combiner.js.map +7 -0
  165. package/dist/signaling.d.ts +29 -0
  166. package/dist/signaling.d.ts.map +1 -0
  167. package/dist/signaling.js +232 -0
  168. package/dist/signaling.js.map +7 -0
  169. package/dist/source-auth.d.ts +2 -0
  170. package/dist/source-auth.d.ts.map +1 -0
  171. package/dist/source-auth.js +1238 -0
  172. package/dist/source-auth.js.map +7 -0
  173. package/dist/switching-set-alignment.d.ts +61 -0
  174. package/dist/switching-set-alignment.d.ts.map +1 -0
  175. package/dist/switching-set-alignment.js +85 -0
  176. package/dist/switching-set-alignment.js.map +7 -0
  177. package/dist/timestamp-codec.d.ts +34 -0
  178. package/dist/timestamp-codec.d.ts.map +1 -0
  179. package/dist/timestamp-codec.js +456 -0
  180. package/dist/timestamp-codec.js.map +7 -0
  181. package/dist/track-pipeline-setup.d.ts +72 -0
  182. package/dist/track-pipeline-setup.d.ts.map +1 -0
  183. package/dist/track-pipeline-setup.js +306 -0
  184. package/dist/track-pipeline-setup.js.map +7 -0
  185. package/dist/track-pipeline.d.ts +121 -0
  186. package/dist/track-pipeline.d.ts.map +1 -0
  187. package/dist/track-pipeline.js +229 -0
  188. package/dist/track-pipeline.js.map +7 -0
  189. package/dist/track-session.d.ts +398 -0
  190. package/dist/track-session.d.ts.map +1 -0
  191. package/dist/track-session.js +767 -0
  192. package/dist/track-session.js.map +7 -0
  193. package/dist/transport-pool.d.ts +69 -0
  194. package/dist/transport-pool.d.ts.map +1 -0
  195. package/dist/transport-pool.js +88 -0
  196. package/dist/transport-pool.js.map +7 -0
  197. package/dist/wasm-mfu-reassembler.d.ts +92 -0
  198. package/dist/wasm-mfu-reassembler.d.ts.map +1 -0
  199. package/dist/wasm-mfu-reassembler.js +2139 -0
  200. package/dist/wasm-mfu-reassembler.js.map +7 -0
  201. package/dist/wasm-mmtp-container-parser.d.ts +10 -0
  202. package/dist/wasm-mmtp-container-parser.d.ts.map +1 -0
  203. package/dist/wasm-mmtp-container-parser.js +6418 -0
  204. package/dist/wasm-mmtp-container-parser.js.map +7 -0
  205. package/node_modules/@blockcast/fec-worker/README.md +213 -0
  206. package/node_modules/@blockcast/fec-worker/dist/.build-stamp +0 -0
  207. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts +87 -0
  208. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts.map +1 -0
  209. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js +279 -0
  210. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js.map +1 -0
  211. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts +252 -0
  212. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts.map +1 -0
  213. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js +11 -0
  214. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js.map +1 -0
  215. package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts +14 -0
  216. package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts.map +1 -0
  217. package/node_modules/@blockcast/fec-worker/dist/fec-worker.js +565 -0
  218. package/node_modules/@blockcast/fec-worker/dist/fec-worker.js.map +7 -0
  219. package/node_modules/@blockcast/fec-worker/dist/index.d.ts +10 -0
  220. package/node_modules/@blockcast/fec-worker/dist/index.d.ts.map +1 -0
  221. package/node_modules/@blockcast/fec-worker/dist/index.js +8 -0
  222. package/node_modules/@blockcast/fec-worker/dist/index.js.map +1 -0
  223. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts +20 -0
  224. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts.map +1 -0
  225. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js +349 -0
  226. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js.map +7 -0
  227. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts +104 -0
  228. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts.map +1 -0
  229. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js +181 -0
  230. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js.map +1 -0
  231. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts +179 -0
  232. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts.map +1 -0
  233. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js +47 -0
  234. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js.map +1 -0
  235. package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts +9 -0
  236. package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts.map +1 -0
  237. package/node_modules/@blockcast/fec-worker/dist/transfer.js +13 -0
  238. package/node_modules/@blockcast/fec-worker/dist/transfer.js.map +1 -0
  239. package/node_modules/@blockcast/fec-worker/package.json +59 -0
  240. package/node_modules/@blockcast/fec-worker/src/fec-worker-client.ts +319 -0
  241. package/node_modules/@blockcast/fec-worker/src/fec-worker-types.ts +268 -0
  242. package/node_modules/@blockcast/fec-worker/src/fec-worker.ts +1048 -0
  243. package/node_modules/@blockcast/fec-worker/src/index.ts +32 -0
  244. package/node_modules/@blockcast/fec-worker/src/shred-fec-worker.ts +558 -0
  245. package/node_modules/@blockcast/fec-worker/src/shred-worker-client.ts +222 -0
  246. package/node_modules/@blockcast/fec-worker/src/shred-worker-types.ts +194 -0
  247. package/node_modules/@blockcast/fec-worker/src/transfer.ts +12 -0
  248. package/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
  249. package/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
  250. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
  251. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
  252. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
  253. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
  254. package/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
  255. package/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
  256. package/node_modules/@blockcast/mmt-base/README.md +120 -0
  257. package/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
  258. package/node_modules/@blockcast/mmt-base/dist/index.d.ts +2 -0
  259. package/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
  260. package/node_modules/@blockcast/mmt-base/dist/index.js +2 -0
  261. package/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
  262. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +276 -0
  263. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
  264. package/node_modules/@blockcast/mmt-base/dist/mmtp.js +645 -0
  265. package/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
  266. package/node_modules/@blockcast/mmt-base/package.json +49 -0
  267. package/node_modules/@blockcast/mmt-base/src/index.ts +1 -0
  268. package/node_modules/@blockcast/mmt-base/src/mmtp.ts +899 -0
  269. package/node_modules/@blockcast/mmt-fec/README.md +270 -0
  270. package/node_modules/@blockcast/mmt-fec/dist/.build-stamp +0 -0
  271. package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts +82 -0
  272. package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts.map +1 -0
  273. package/node_modules/@blockcast/mmt-fec/dist/block-manager.js +296 -0
  274. package/node_modules/@blockcast/mmt-fec/dist/block-manager.js.map +1 -0
  275. package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts +72 -0
  276. package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts.map +1 -0
  277. package/node_modules/@blockcast/mmt-fec/dist/block-processor.js +192 -0
  278. package/node_modules/@blockcast/mmt-fec/dist/block-processor.js.map +1 -0
  279. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts +46 -0
  280. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts.map +1 -0
  281. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js +96 -0
  282. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js.map +1 -0
  283. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts +33 -0
  284. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts.map +1 -0
  285. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js +57 -0
  286. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js.map +1 -0
  287. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts +185 -0
  288. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts.map +1 -0
  289. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js +273 -0
  290. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js.map +1 -0
  291. package/node_modules/@blockcast/mmt-fec/dist/index.d.ts +22 -0
  292. package/node_modules/@blockcast/mmt-fec/dist/index.d.ts.map +1 -0
  293. package/node_modules/@blockcast/mmt-fec/dist/index.js +22 -0
  294. package/node_modules/@blockcast/mmt-fec/dist/index.js.map +1 -0
  295. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts +20 -0
  296. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts.map +1 -0
  297. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js +28 -0
  298. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js.map +1 -0
  299. package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts +172 -0
  300. package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts.map +1 -0
  301. package/node_modules/@blockcast/mmt-fec/dist/oti.js +254 -0
  302. package/node_modules/@blockcast/mmt-fec/dist/oti.js.map +1 -0
  303. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts +41 -0
  304. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts.map +1 -0
  305. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js +81 -0
  306. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js.map +1 -0
  307. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
  308. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
  309. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
  310. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
  311. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
  312. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
  313. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
  314. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
  315. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/README.md +120 -0
  316. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
  317. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts +2 -0
  318. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
  319. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js +2 -0
  320. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
  321. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +276 -0
  322. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
  323. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js +645 -0
  324. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
  325. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/package.json +49 -0
  326. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/index.ts +1 -0
  327. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/mmtp.ts +899 -0
  328. package/node_modules/@blockcast/mmt-fec/package.json +79 -0
  329. package/node_modules/@blockcast/mmt-fec/src/block-manager.ts +371 -0
  330. package/node_modules/@blockcast/mmt-fec/src/block-processor.ts +277 -0
  331. package/node_modules/@blockcast/mmt-fec/src/cmaf-recovery.ts +127 -0
  332. package/node_modules/@blockcast/mmt-fec/src/cmaf-symbols.ts +68 -0
  333. package/node_modules/@blockcast/mmt-fec/src/fec-block-mapper.ts +332 -0
  334. package/node_modules/@blockcast/mmt-fec/src/index.ts +77 -0
  335. package/node_modules/@blockcast/mmt-fec/src/loc-symbols.ts +34 -0
  336. package/node_modules/@blockcast/mmt-fec/src/oti.ts +317 -0
  337. package/node_modules/@blockcast/mmt-fec/src/reorder-buffer.ts +101 -0
  338. package/node_modules/@blockcast/mmt-manifest-verify/dist/.build-stamp +0 -0
  339. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts +28 -0
  340. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts.map +1 -0
  341. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js +128 -0
  342. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js.map +1 -0
  343. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts +4 -0
  344. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts.map +1 -0
  345. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js +4 -0
  346. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js.map +1 -0
  347. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts +37 -0
  348. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts.map +1 -0
  349. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js +179 -0
  350. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js.map +1 -0
  351. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts +99 -0
  352. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts.map +1 -0
  353. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js +492 -0
  354. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js.map +1 -0
  355. package/node_modules/@blockcast/mmt-manifest-verify/package.json +45 -0
  356. package/node_modules/@blockcast/mmt-manifest-verify/src/admission.ts +171 -0
  357. package/node_modules/@blockcast/mmt-manifest-verify/src/index.ts +3 -0
  358. package/node_modules/@blockcast/mmt-manifest-verify/src/source-auth.ts +230 -0
  359. package/node_modules/@blockcast/mmt-manifest-verify/src/verifier.ts +669 -0
  360. package/node_modules/@noble/hashes/LICENSE +21 -0
  361. package/node_modules/@noble/hashes/README.md +521 -0
  362. package/node_modules/@noble/hashes/_assert.d.ts +17 -0
  363. package/node_modules/@noble/hashes/_assert.d.ts.map +1 -0
  364. package/node_modules/@noble/hashes/_assert.js +18 -0
  365. package/node_modules/@noble/hashes/_assert.js.map +1 -0
  366. package/node_modules/@noble/hashes/_blake.d.ts +14 -0
  367. package/node_modules/@noble/hashes/_blake.d.ts.map +1 -0
  368. package/node_modules/@noble/hashes/_blake.js +50 -0
  369. package/node_modules/@noble/hashes/_blake.js.map +1 -0
  370. package/node_modules/@noble/hashes/_md.d.ts +51 -0
  371. package/node_modules/@noble/hashes/_md.d.ts.map +1 -0
  372. package/node_modules/@noble/hashes/_md.js +162 -0
  373. package/node_modules/@noble/hashes/_md.js.map +1 -0
  374. package/node_modules/@noble/hashes/_u64.d.ts +55 -0
  375. package/node_modules/@noble/hashes/_u64.d.ts.map +1 -0
  376. package/node_modules/@noble/hashes/_u64.js +90 -0
  377. package/node_modules/@noble/hashes/_u64.js.map +1 -0
  378. package/node_modules/@noble/hashes/argon2.d.ts +32 -0
  379. package/node_modules/@noble/hashes/argon2.d.ts.map +1 -0
  380. package/node_modules/@noble/hashes/argon2.js +401 -0
  381. package/node_modules/@noble/hashes/argon2.js.map +1 -0
  382. package/node_modules/@noble/hashes/blake1.d.ts +106 -0
  383. package/node_modules/@noble/hashes/blake1.d.ts.map +1 -0
  384. package/node_modules/@noble/hashes/blake1.js +459 -0
  385. package/node_modules/@noble/hashes/blake1.js.map +1 -0
  386. package/node_modules/@noble/hashes/blake2.d.ts +116 -0
  387. package/node_modules/@noble/hashes/blake2.d.ts.map +1 -0
  388. package/node_modules/@noble/hashes/blake2.js +420 -0
  389. package/node_modules/@noble/hashes/blake2.js.map +1 -0
  390. package/node_modules/@noble/hashes/blake2b.d.ts +11 -0
  391. package/node_modules/@noble/hashes/blake2b.d.ts.map +1 -0
  392. package/node_modules/@noble/hashes/blake2b.js +14 -0
  393. package/node_modules/@noble/hashes/blake2b.js.map +1 -0
  394. package/node_modules/@noble/hashes/blake2s.d.ts +20 -0
  395. package/node_modules/@noble/hashes/blake2s.d.ts.map +1 -0
  396. package/node_modules/@noble/hashes/blake2s.js +24 -0
  397. package/node_modules/@noble/hashes/blake2s.js.map +1 -0
  398. package/node_modules/@noble/hashes/blake3.d.ts +54 -0
  399. package/node_modules/@noble/hashes/blake3.d.ts.map +1 -0
  400. package/node_modules/@noble/hashes/blake3.js +255 -0
  401. package/node_modules/@noble/hashes/blake3.js.map +1 -0
  402. package/node_modules/@noble/hashes/crypto.d.ts +2 -0
  403. package/node_modules/@noble/hashes/crypto.d.ts.map +1 -0
  404. package/node_modules/@noble/hashes/crypto.js +5 -0
  405. package/node_modules/@noble/hashes/crypto.js.map +1 -0
  406. package/node_modules/@noble/hashes/cryptoNode.d.ts +2 -0
  407. package/node_modules/@noble/hashes/cryptoNode.d.ts.map +1 -0
  408. package/node_modules/@noble/hashes/cryptoNode.js +18 -0
  409. package/node_modules/@noble/hashes/cryptoNode.js.map +1 -0
  410. package/node_modules/@noble/hashes/eskdf.d.ts +47 -0
  411. package/node_modules/@noble/hashes/eskdf.d.ts.map +1 -0
  412. package/node_modules/@noble/hashes/eskdf.js +166 -0
  413. package/node_modules/@noble/hashes/eskdf.js.map +1 -0
  414. package/node_modules/@noble/hashes/esm/_assert.d.ts +17 -0
  415. package/node_modules/@noble/hashes/esm/_assert.d.ts.map +1 -0
  416. package/node_modules/@noble/hashes/esm/_assert.js +15 -0
  417. package/node_modules/@noble/hashes/esm/_assert.js.map +1 -0
  418. package/node_modules/@noble/hashes/esm/_blake.d.ts +14 -0
  419. package/node_modules/@noble/hashes/esm/_blake.d.ts.map +1 -0
  420. package/node_modules/@noble/hashes/esm/_blake.js +45 -0
  421. package/node_modules/@noble/hashes/esm/_blake.js.map +1 -0
  422. package/node_modules/@noble/hashes/esm/_md.d.ts +51 -0
  423. package/node_modules/@noble/hashes/esm/_md.d.ts.map +1 -0
  424. package/node_modules/@noble/hashes/esm/_md.js +155 -0
  425. package/node_modules/@noble/hashes/esm/_md.js.map +1 -0
  426. package/node_modules/@noble/hashes/esm/_u64.d.ts +55 -0
  427. package/node_modules/@noble/hashes/esm/_u64.d.ts.map +1 -0
  428. package/node_modules/@noble/hashes/esm/_u64.js +67 -0
  429. package/node_modules/@noble/hashes/esm/_u64.js.map +1 -0
  430. package/node_modules/@noble/hashes/esm/argon2.d.ts +32 -0
  431. package/node_modules/@noble/hashes/esm/argon2.d.ts.map +1 -0
  432. package/node_modules/@noble/hashes/esm/argon2.js +392 -0
  433. package/node_modules/@noble/hashes/esm/argon2.js.map +1 -0
  434. package/node_modules/@noble/hashes/esm/blake1.d.ts +106 -0
  435. package/node_modules/@noble/hashes/esm/blake1.d.ts.map +1 -0
  436. package/node_modules/@noble/hashes/esm/blake1.js +452 -0
  437. package/node_modules/@noble/hashes/esm/blake1.js.map +1 -0
  438. package/node_modules/@noble/hashes/esm/blake2.d.ts +116 -0
  439. package/node_modules/@noble/hashes/esm/blake2.d.ts.map +1 -0
  440. package/node_modules/@noble/hashes/esm/blake2.js +413 -0
  441. package/node_modules/@noble/hashes/esm/blake2.js.map +1 -0
  442. package/node_modules/@noble/hashes/esm/blake2b.d.ts +11 -0
  443. package/node_modules/@noble/hashes/esm/blake2b.d.ts.map +1 -0
  444. package/node_modules/@noble/hashes/esm/blake2b.js +11 -0
  445. package/node_modules/@noble/hashes/esm/blake2b.js.map +1 -0
  446. package/node_modules/@noble/hashes/esm/blake2s.d.ts +20 -0
  447. package/node_modules/@noble/hashes/esm/blake2s.d.ts.map +1 -0
  448. package/node_modules/@noble/hashes/esm/blake2s.js +21 -0
  449. package/node_modules/@noble/hashes/esm/blake2s.js.map +1 -0
  450. package/node_modules/@noble/hashes/esm/blake3.d.ts +54 -0
  451. package/node_modules/@noble/hashes/esm/blake3.d.ts.map +1 -0
  452. package/node_modules/@noble/hashes/esm/blake3.js +251 -0
  453. package/node_modules/@noble/hashes/esm/blake3.js.map +1 -0
  454. package/node_modules/@noble/hashes/esm/crypto.d.ts +2 -0
  455. package/node_modules/@noble/hashes/esm/crypto.d.ts.map +1 -0
  456. package/node_modules/@noble/hashes/esm/crypto.js +2 -0
  457. package/node_modules/@noble/hashes/esm/crypto.js.map +1 -0
  458. package/node_modules/@noble/hashes/esm/cryptoNode.d.ts +2 -0
  459. package/node_modules/@noble/hashes/esm/cryptoNode.d.ts.map +1 -0
  460. package/node_modules/@noble/hashes/esm/cryptoNode.js +15 -0
  461. package/node_modules/@noble/hashes/esm/cryptoNode.js.map +1 -0
  462. package/node_modules/@noble/hashes/esm/eskdf.d.ts +47 -0
  463. package/node_modules/@noble/hashes/esm/eskdf.d.ts.map +1 -0
  464. package/node_modules/@noble/hashes/esm/eskdf.js +160 -0
  465. package/node_modules/@noble/hashes/esm/eskdf.js.map +1 -0
  466. package/node_modules/@noble/hashes/esm/hkdf.d.ts +36 -0
  467. package/node_modules/@noble/hashes/esm/hkdf.d.ts.map +1 -0
  468. package/node_modules/@noble/hashes/esm/hkdf.js +82 -0
  469. package/node_modules/@noble/hashes/esm/hkdf.js.map +1 -0
  470. package/node_modules/@noble/hashes/esm/hmac.d.ts +35 -0
  471. package/node_modules/@noble/hashes/esm/hmac.d.ts.map +1 -0
  472. package/node_modules/@noble/hashes/esm/hmac.js +86 -0
  473. package/node_modules/@noble/hashes/esm/hmac.js.map +1 -0
  474. package/node_modules/@noble/hashes/esm/index.d.ts +2 -0
  475. package/node_modules/@noble/hashes/esm/index.d.ts.map +1 -0
  476. package/node_modules/@noble/hashes/esm/index.js +33 -0
  477. package/node_modules/@noble/hashes/esm/index.js.map +1 -0
  478. package/node_modules/@noble/hashes/esm/legacy.d.ts +71 -0
  479. package/node_modules/@noble/hashes/esm/legacy.d.ts.map +1 -0
  480. package/node_modules/@noble/hashes/esm/legacy.js +281 -0
  481. package/node_modules/@noble/hashes/esm/legacy.js.map +1 -0
  482. package/node_modules/@noble/hashes/esm/package.json +10 -0
  483. package/node_modules/@noble/hashes/esm/pbkdf2.d.ts +23 -0
  484. package/node_modules/@noble/hashes/esm/pbkdf2.d.ts.map +1 -0
  485. package/node_modules/@noble/hashes/esm/pbkdf2.js +97 -0
  486. package/node_modules/@noble/hashes/esm/pbkdf2.js.map +1 -0
  487. package/node_modules/@noble/hashes/esm/ripemd160.d.ts +13 -0
  488. package/node_modules/@noble/hashes/esm/ripemd160.d.ts.map +1 -0
  489. package/node_modules/@noble/hashes/esm/ripemd160.js +13 -0
  490. package/node_modules/@noble/hashes/esm/ripemd160.js.map +1 -0
  491. package/node_modules/@noble/hashes/esm/scrypt.d.ts +34 -0
  492. package/node_modules/@noble/hashes/esm/scrypt.d.ts.map +1 -0
  493. package/node_modules/@noble/hashes/esm/scrypt.js +228 -0
  494. package/node_modules/@noble/hashes/esm/scrypt.js.map +1 -0
  495. package/node_modules/@noble/hashes/esm/sha1.d.ts +11 -0
  496. package/node_modules/@noble/hashes/esm/sha1.d.ts.map +1 -0
  497. package/node_modules/@noble/hashes/esm/sha1.js +11 -0
  498. package/node_modules/@noble/hashes/esm/sha1.js.map +1 -0
  499. package/node_modules/@noble/hashes/esm/sha2.d.ts +159 -0
  500. package/node_modules/@noble/hashes/esm/sha2.d.ts.map +1 -0
  501. package/node_modules/@noble/hashes/esm/sha2.js +375 -0
  502. package/node_modules/@noble/hashes/esm/sha2.js.map +1 -0
  503. package/node_modules/@noble/hashes/esm/sha256.d.ts +20 -0
  504. package/node_modules/@noble/hashes/esm/sha256.d.ts.map +1 -0
  505. package/node_modules/@noble/hashes/esm/sha256.js +20 -0
  506. package/node_modules/@noble/hashes/esm/sha256.js.map +1 -0
  507. package/node_modules/@noble/hashes/esm/sha3-addons.d.ts +142 -0
  508. package/node_modules/@noble/hashes/esm/sha3-addons.d.ts.map +1 -0
  509. package/node_modules/@noble/hashes/esm/sha3-addons.js +393 -0
  510. package/node_modules/@noble/hashes/esm/sha3-addons.js.map +1 -0
  511. package/node_modules/@noble/hashes/esm/sha3.d.ts +53 -0
  512. package/node_modules/@noble/hashes/esm/sha3.d.ts.map +1 -0
  513. package/node_modules/@noble/hashes/esm/sha3.js +234 -0
  514. package/node_modules/@noble/hashes/esm/sha3.js.map +1 -0
  515. package/node_modules/@noble/hashes/esm/sha512.d.ts +26 -0
  516. package/node_modules/@noble/hashes/esm/sha512.d.ts.map +1 -0
  517. package/node_modules/@noble/hashes/esm/sha512.js +26 -0
  518. package/node_modules/@noble/hashes/esm/sha512.js.map +1 -0
  519. package/node_modules/@noble/hashes/esm/utils.d.ts +161 -0
  520. package/node_modules/@noble/hashes/esm/utils.d.ts.map +1 -0
  521. package/node_modules/@noble/hashes/esm/utils.js +281 -0
  522. package/node_modules/@noble/hashes/esm/utils.js.map +1 -0
  523. package/node_modules/@noble/hashes/hkdf.d.ts +36 -0
  524. package/node_modules/@noble/hashes/hkdf.d.ts.map +1 -0
  525. package/node_modules/@noble/hashes/hkdf.js +88 -0
  526. package/node_modules/@noble/hashes/hkdf.js.map +1 -0
  527. package/node_modules/@noble/hashes/hmac.d.ts +35 -0
  528. package/node_modules/@noble/hashes/hmac.d.ts.map +1 -0
  529. package/node_modules/@noble/hashes/hmac.js +91 -0
  530. package/node_modules/@noble/hashes/hmac.js.map +1 -0
  531. package/node_modules/@noble/hashes/index.d.ts +1 -0
  532. package/node_modules/@noble/hashes/index.d.ts.map +1 -0
  533. package/node_modules/@noble/hashes/index.js +33 -0
  534. package/node_modules/@noble/hashes/index.js.map +1 -0
  535. package/node_modules/@noble/hashes/legacy.d.ts +71 -0
  536. package/node_modules/@noble/hashes/legacy.d.ts.map +1 -0
  537. package/node_modules/@noble/hashes/legacy.js +287 -0
  538. package/node_modules/@noble/hashes/legacy.js.map +1 -0
  539. package/node_modules/@noble/hashes/package.json +266 -0
  540. package/node_modules/@noble/hashes/pbkdf2.d.ts +23 -0
  541. package/node_modules/@noble/hashes/pbkdf2.d.ts.map +1 -0
  542. package/node_modules/@noble/hashes/pbkdf2.js +101 -0
  543. package/node_modules/@noble/hashes/pbkdf2.js.map +1 -0
  544. package/node_modules/@noble/hashes/ripemd160.d.ts +13 -0
  545. package/node_modules/@noble/hashes/ripemd160.d.ts.map +1 -0
  546. package/node_modules/@noble/hashes/ripemd160.js +16 -0
  547. package/node_modules/@noble/hashes/ripemd160.js.map +1 -0
  548. package/node_modules/@noble/hashes/scrypt.d.ts +34 -0
  549. package/node_modules/@noble/hashes/scrypt.d.ts.map +1 -0
  550. package/node_modules/@noble/hashes/scrypt.js +232 -0
  551. package/node_modules/@noble/hashes/scrypt.js.map +1 -0
  552. package/node_modules/@noble/hashes/sha1.d.ts +11 -0
  553. package/node_modules/@noble/hashes/sha1.d.ts.map +1 -0
  554. package/node_modules/@noble/hashes/sha1.js +14 -0
  555. package/node_modules/@noble/hashes/sha1.js.map +1 -0
  556. package/node_modules/@noble/hashes/sha2.d.ts +159 -0
  557. package/node_modules/@noble/hashes/sha2.d.ts.map +1 -0
  558. package/node_modules/@noble/hashes/sha2.js +384 -0
  559. package/node_modules/@noble/hashes/sha2.js.map +1 -0
  560. package/node_modules/@noble/hashes/sha256.d.ts +20 -0
  561. package/node_modules/@noble/hashes/sha256.d.ts.map +1 -0
  562. package/node_modules/@noble/hashes/sha256.js +23 -0
  563. package/node_modules/@noble/hashes/sha256.js.map +1 -0
  564. package/node_modules/@noble/hashes/sha3-addons.d.ts +142 -0
  565. package/node_modules/@noble/hashes/sha3-addons.d.ts.map +1 -0
  566. package/node_modules/@noble/hashes/sha3-addons.js +402 -0
  567. package/node_modules/@noble/hashes/sha3-addons.js.map +1 -0
  568. package/node_modules/@noble/hashes/sha3.d.ts +53 -0
  569. package/node_modules/@noble/hashes/sha3.d.ts.map +1 -0
  570. package/node_modules/@noble/hashes/sha3.js +239 -0
  571. package/node_modules/@noble/hashes/sha3.js.map +1 -0
  572. package/node_modules/@noble/hashes/sha512.d.ts +26 -0
  573. package/node_modules/@noble/hashes/sha512.d.ts.map +1 -0
  574. package/node_modules/@noble/hashes/sha512.js +29 -0
  575. package/node_modules/@noble/hashes/sha512.js.map +1 -0
  576. package/node_modules/@noble/hashes/src/_assert.ts +22 -0
  577. package/node_modules/@noble/hashes/src/_blake.ts +50 -0
  578. package/node_modules/@noble/hashes/src/_md.ts +176 -0
  579. package/node_modules/@noble/hashes/src/_u64.ts +91 -0
  580. package/node_modules/@noble/hashes/src/argon2.ts +497 -0
  581. package/node_modules/@noble/hashes/src/blake1.ts +534 -0
  582. package/node_modules/@noble/hashes/src/blake2.ts +486 -0
  583. package/node_modules/@noble/hashes/src/blake2b.ts +10 -0
  584. package/node_modules/@noble/hashes/src/blake2s.ts +20 -0
  585. package/node_modules/@noble/hashes/src/blake3.ts +272 -0
  586. package/node_modules/@noble/hashes/src/crypto.ts +9 -0
  587. package/node_modules/@noble/hashes/src/cryptoNode.ts +15 -0
  588. package/node_modules/@noble/hashes/src/eskdf.ts +187 -0
  589. package/node_modules/@noble/hashes/src/hkdf.ts +88 -0
  590. package/node_modules/@noble/hashes/src/hmac.ts +94 -0
  591. package/node_modules/@noble/hashes/src/index.ts +31 -0
  592. package/node_modules/@noble/hashes/src/legacy.ts +293 -0
  593. package/node_modules/@noble/hashes/src/pbkdf2.ts +122 -0
  594. package/node_modules/@noble/hashes/src/ripemd160.ts +12 -0
  595. package/node_modules/@noble/hashes/src/scrypt.ts +257 -0
  596. package/node_modules/@noble/hashes/src/sha1.ts +10 -0
  597. package/node_modules/@noble/hashes/src/sha2.ts +402 -0
  598. package/node_modules/@noble/hashes/src/sha256.ts +24 -0
  599. package/node_modules/@noble/hashes/src/sha3-addons.ts +499 -0
  600. package/node_modules/@noble/hashes/src/sha3.ts +258 -0
  601. package/node_modules/@noble/hashes/src/sha512.ts +34 -0
  602. package/node_modules/@noble/hashes/src/utils.ts +395 -0
  603. package/node_modules/@noble/hashes/utils.d.ts +161 -0
  604. package/node_modules/@noble/hashes/utils.d.ts.map +1 -0
  605. package/node_modules/@noble/hashes/utils.js +313 -0
  606. package/node_modules/@noble/hashes/utils.js.map +1 -0
  607. package/package.json +203 -0
  608. package/schemas/catalog.schema.json +360 -0
  609. package/src/align.ts +239 -0
  610. package/src/audio-init-parser.ts +189 -0
  611. package/src/audio-ring-buffer.ts +120 -0
  612. package/src/authored-timing.ts +63 -0
  613. package/src/carp-catalog.ts +845 -0
  614. package/src/catalog-fec-params.ts +535 -0
  615. package/src/catalog-network-source.ts +49 -0
  616. package/src/catalog-validator.ts +34 -0
  617. package/src/cmaf-block-assembler.ts +1167 -0
  618. package/src/cmaf-group-batcher.ts +104 -0
  619. package/src/cmcd-producer.ts +334 -0
  620. package/src/codec-utils.ts +1611 -0
  621. package/src/fec-codec.ts +61 -0
  622. package/src/fec-manager.ts +2081 -0
  623. package/src/fec-starvation-detector.ts +128 -0
  624. package/src/fec-worker-setup.ts +213 -0
  625. package/src/fmp4-completion.ts +47 -0
  626. package/src/fmp4-reader.ts +112 -0
  627. package/src/index.ts +486 -0
  628. package/src/iso-bmff-timing.ts +813 -0
  629. package/src/loc.ts +181 -0
  630. package/src/manifest-auth-plan.ts +107 -0
  631. package/src/media-router.ts +795 -0
  632. package/src/mfu-reassembler.ts +3741 -0
  633. package/src/mfu-reassembly-policy.ts +134 -0
  634. package/src/mmtp-container-parser.ts +1836 -0
  635. package/src/mmtp-decode-pipeline.ts +389 -0
  636. package/src/mmtp-router.ts +3136 -0
  637. package/src/mmtp-to-cmaf.ts +1024 -0
  638. package/src/multicast-auth-catalog.ts +340 -0
  639. package/src/multicast-input.ts +439 -0
  640. package/src/multicast-manager.ts +1720 -0
  641. package/src/multicast-transport.ts +321 -0
  642. package/src/multicast-unwrap.ts +132 -0
  643. package/src/no-modules.ts +20 -0
  644. package/src/phase14-catalog-override.ts +336 -0
  645. package/src/repair-fetch.ts +238 -0
  646. package/src/repair-layers.ts +490 -0
  647. package/src/sample-combiner.ts +938 -0
  648. package/src/signaling.ts +78 -0
  649. package/src/source-auth.ts +1 -0
  650. package/src/switching-set-alignment.ts +109 -0
  651. package/src/timestamp-codec.ts +265 -0
  652. package/src/track-pipeline-setup.ts +189 -0
  653. package/src/track-pipeline.ts +332 -0
  654. package/src/track-session.ts +994 -0
  655. package/src/transport-pool.ts +128 -0
  656. package/src/wasm-mfu-reassembler.ts +389 -0
  657. package/src/wasm-mmtp-container-parser.ts +23 -0
  658. package/test-vectors/align.json +199 -0
  659. package/test-vectors/catalog/README.md +40 -0
  660. package/test-vectors/catalog/negative/fec-enhancement-repair-removed.json +27 -0
  661. package/test-vectors/catalog/negative/fec-repair-layer-geometry.json +32 -0
  662. package/test-vectors/catalog/negative/fec-repair-layer-missing-symbols.json +30 -0
  663. package/test-vectors/catalog/negative/fec-repair-multiple-depends.json +31 -0
  664. package/test-vectors/catalog/negative/fec-repair-overlay-with-layer.json +33 -0
  665. package/test-vectors/catalog/negative/fec-repair-priority-out-of-band.json +23 -0
  666. package/test-vectors/catalog/negative/fec-repair-source-symbols-without-scope.json +32 -0
  667. package/test-vectors/catalog/negative/legacy-selection-params.json +15 -0
  668. package/test-vectors/catalog/negative/media-track-repair-layer.json +16 -0
  669. package/test-vectors/catalog/negative/missing-mmtp-fields.json +12 -0
  670. package/test-vectors/catalog/negative/multicast-auth-padded-key.json +37 -0
  671. package/test-vectors/catalog/negative/multicast-auth-reused-track-format.json +53 -0
  672. package/test-vectors/catalog/negative/multicast-auth-trailing-pad-bits.json +37 -0
  673. package/test-vectors/catalog/negative/multicast-endpoint-missing-protocol-and-source.json +24 -0
  674. package/test-vectors/catalog/negative/network-source-object.json +25 -0
  675. package/test-vectors/catalog/negative/raptorq-source-symbols-over-max.json +23 -0
  676. package/test-vectors/catalog/negative/raptorq-unaligned-symbol.json +26 -0
  677. package/test-vectors/catalog/negative/repair-track-legacy-shape.json +19 -0
  678. package/test-vectors/catalog/negative/track-role-empty.json +16 -0
  679. package/test-vectors/catalog/negative/track-role-non-string.json +16 -0
  680. package/test-vectors/catalog/positive/fec-layered-repair.json +104 -0
  681. package/test-vectors/catalog/positive/fec-multicast.json +51 -0
  682. package/test-vectors/catalog/positive/flat-av.json +30 -0
  683. package/test-vectors/catalog/positive/multicast-auth-rotation.json +55 -0
  684. package/test-vectors/catalog/positive/ticks-and-mixed-timescales.json +39 -0
  685. package/test-vectors/catalog/positive/track-role.json +49 -0
  686. package/test-vectors/catalog/releases/moqcast-native-v16-v1/catalog.json +65 -0
  687. package/test-vectors/catalog/releases/moqcast-native-v16-v1.archive.sha256 +1 -0
  688. package/test-vectors/catalog-multicast-auth-v1.json +26 -0
  689. package/test-vectors/catalog-validation.json +148 -0
  690. package/test-vectors/catalog-validator-public-api.mjs +25 -0
  691. package/test-vectors/generate-source-auth-fixture.mjs +114 -0
  692. package/test-vectors/source-auth-v1.json +61 -0
  693. package/test-vectors/source-contiguity-v1.json +131 -0
  694. package/test-vectors/subsample-placement-v1.json +230 -0
@@ -0,0 +1,795 @@
1
+ /**
2
+ * MediaRouter — source arbitration for MoQ ↔ multicast switching.
3
+ *
4
+ * Both moq-lib and moqtail wire their MoQ and multicast frame outputs
5
+ * through this router. The router decides which source reaches the decoder:
6
+ *
7
+ * - MoQ frames pass through while multicast is inactive.
8
+ * - Multicast video frames are suppressed until the first keyframe.
9
+ * - Once multicast has both a video keyframe and audio, takeover is requested.
10
+ * - MoQ is suppressed only after the source-switch callback completes.
11
+ * - failbackToMoq() reverses the switch immediately.
12
+ *
13
+ * Per-track setTrackSource() allows individual tracks to be wired to a
14
+ * specific transport source (video=multicast, audio=moq, overlay=amt) without
15
+ * changing the binary MoQ↔multicast switching for other tracks.
16
+ */
17
+
18
+ import { computeFecDeliveryWindowMs } from './track-session.js'
19
+
20
+ export type FrameMeta = {
21
+ timestamp: number
22
+ keyframe: boolean
23
+ packetId?: number
24
+ packetSequenceNumber?: number
25
+ source?: 'moq' | 'multicast' | 'repair'
26
+ recovered?: boolean
27
+ sourceDiscontinuity?: boolean
28
+ /**
29
+ * Raw MMTP header timestamp (RFC 5905 short NTP, 32 bits): the publisher's
30
+ * send-wall clock for the packet that carried this frame. On timed media it
31
+ * is distinct from `timestamp`, the authored media presentation time. On a
32
+ * non-timed MFU there is no authored presentation time, so `MmtpRouter`
33
+ * derives `timestamp` from this same clock and the two carry no latency
34
+ * between them. Populated from `RoutedFrameMeta.mmtpTimestamp` and
35
+ * preserved by every re-emit on this router (multicast, MoQ, and repair) so
36
+ * players can measure network ingress on the multicast legs; absent when
37
+ * the packet header could not be read.
38
+ */
39
+ mmtpTimestamp?: bigint
40
+ }
41
+ export type FrameKind = 'video' | 'audio'
42
+ export type SourceKind = 'moq' | 'multicast'
43
+
44
+ type FrameCb = (data: Uint8Array, meta: FrameMeta) => void
45
+ type SwitchCb = (source: SourceKind) => void | Promise<void>
46
+
47
+ export interface MediaRouterOptions {
48
+ /** Set false for video-only streams. Default: true. */
49
+ requireAudio?: boolean
50
+ /**
51
+ * Audio fallback timeout (ms): force multicast activation if video keyframe
52
+ * arrived but audio hasn't within this window. Catalog-derived via
53
+ * computeFecDeliveryWindowMs (the single FEC recovery-window source of truth).
54
+ * Omit to disable the independent audio-fallback timer (no magic default).
55
+ */
56
+ audioFallbackMs?: number
57
+ /**
58
+ * Number of binary-path frames to allow through during a crossfade transition.
59
+ * Derive from FEC block size (e.g., ceil(K / groupsPerBlock)). Default: 10.
60
+ */
61
+ crossfadeFrames?: number
62
+ /**
63
+ * Max pre-boundary overlay frames to buffer before dropping.
64
+ * Derive from FEC config (e.g., ceil(K * 1.5)). Default: 128.
65
+ */
66
+ maxOverlayBuffer?: number
67
+ /**
68
+ * Max concurrent in-flight repairs. Prevents relay SUBSCRIBE flood (T-13-01 mitigation).
69
+ * Default: 2.
70
+ */
71
+ maxRepairInFlight?: number
72
+ /**
73
+ * Allow multicast takeover from a delta frame after the player has confirmed
74
+ * that MoQ already seeded the same decoder timeline with a video keyframe.
75
+ * Default false: decoder-reset paths still need multicast to provide a RAP.
76
+ */
77
+ allowDeltaMulticastTakeoverAfterMoqKeyframe?: boolean
78
+ }
79
+
80
+ /**
81
+ * A per-track source that emits frames independently of the binary MoQ/multicast path.
82
+ * Used by setTrackSource() to wire specific tracks to specific transport sources.
83
+ */
84
+ export interface TrackSource {
85
+ name: string
86
+ /**
87
+ * Register a frame callback. Returns an unsubscribe function.
88
+ * MediaRouter calls unsubscribe() when clearTrackSource() is called.
89
+ */
90
+ onFrame(cb: (data: Uint8Array, meta: FrameMeta) => void): () => void
91
+ /**
92
+ * Optional error callback for when the source fails.
93
+ * MediaRouter uses this to trigger failback to binary switching for this track.
94
+ */
95
+ onError?(cb: () => void): () => void
96
+ /** Optional dispose hook called when clearTrackSource() is called. */
97
+ dispose?(): void
98
+ }
99
+
100
+ /**
101
+ * Thrown when setTrackSource() is called for a track that already has a source
102
+ * without an intervening clearTrackSource(). Prevents silent concurrent-assignment
103
+ * races (T-02-16 mitigation).
104
+ */
105
+ export class TrackSourceConflictError extends Error {
106
+ constructor(public readonly trackName: string) {
107
+ super(`Track source already assigned for '${trackName}'; call clearTrackSource first`)
108
+ this.name = 'TrackSourceConflictError'
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Migration policy for setTrackSource() transport switching.
114
+ *
115
+ * - 'crossfade': Overlap old (binary) and new source briefly (CROSSFADE_WINDOW_FRAMES),
116
+ * then suppress the binary path. Default for audio.
117
+ * - 'drop': Cut to new source immediately. Binary path suppressed at once.
118
+ * Suitable for latency-critical tracks.
119
+ * - 'wait': Defer migration until first FEC block boundary (same as overlay=true).
120
+ * Default for video — avoids decoder reset mid-block.
121
+ */
122
+ export type MigrationPolicy = 'crossfade' | 'drop' | 'wait'
123
+
124
+ /** Default crossfade window — override via MediaRouterOptions.crossfadeFrames. */
125
+ const DEFAULT_CROSSFADE_FRAMES = 10
126
+
127
+ /** Options passed to setTrackSource(). */
128
+ export interface SetTrackSourceOptions {
129
+ /**
130
+ * If true, this source is an overlay track that must wait for the first FEC
131
+ * block boundary signal (via notifyFecBlockBoundary()) before emitting frames.
132
+ * Frames arriving before the first boundary are buffered up to MAX_OVERLAY_BUFFER.
133
+ *
134
+ * Backwards compat: equivalent to policy: 'wait'.
135
+ */
136
+ overlay?: boolean
137
+ /**
138
+ * Migration policy for the transport switch. Overrides `overlay` when provided.
139
+ * See MigrationPolicy for semantics.
140
+ */
141
+ policy?: MigrationPolicy
142
+ }
143
+
144
+ /** Default overlay buffer cap — override via MediaRouterOptions.maxOverlayBuffer. */
145
+ const DEFAULT_MAX_OVERLAY_BUFFER = 128
146
+
147
+ /** Internal per-track source record. */
148
+ interface TrackSourceRecord {
149
+ source: TrackSource
150
+ unsubscribeFrame: () => void
151
+ unsubscribeError?: () => void
152
+ emitCount: number
153
+ }
154
+
155
+ export class MediaRouter {
156
+ #active: SourceKind = 'moq'
157
+ #multicastVideoKeyed = false
158
+ #multicastAudioReceived = false
159
+ #moqVideoKeyframeEmitted = false
160
+ #requireAudio: boolean
161
+ #suppressed = false // true after multicast confirmed — suppresses MoQ
162
+ #audioFallbackTimer: ReturnType<typeof setTimeout> | null = null
163
+
164
+ // Configurable constants (from catalog/FEC config, not magic numbers)
165
+ readonly #audioFallbackMs: number
166
+ readonly #crossfadeFrames: number
167
+ readonly #maxOverlayBuffer: number
168
+ readonly #allowDeltaMulticastTakeoverAfterMoqKeyframe: boolean
169
+
170
+ // ── Keyframe repair state ────────────────────────────────────────
171
+ /** Groups currently being repaired — idempotent guard per Pitfall 2 (T-13-01 mitigation) */
172
+ #repairInFlight = new Set<number>()
173
+ /** Max concurrent repairs — prevents relay SUBSCRIBE flood (T-13-01 mitigation) */
174
+ readonly #maxRepairInFlight: number
175
+ /** Callback to request MoQ subscribe for a specific group (wired by player) */
176
+ #onRepairRequest: ((expectedGroupId: number, trackName: string) => void) | null = null
177
+
178
+ #onVideoFrame: FrameCb | null = null
179
+ #onAudioFrame: FrameCb | null = null
180
+ #onOverlayFrame: FrameCb | null = null
181
+ #onSourceSwitch: SwitchCb | null = null
182
+ #sourceSwitchReady: Promise<void> | null = null
183
+ #sourceSwitchToken = 0
184
+ #pendingMulticastToken: number | null = null
185
+ #pendingMulticastVideo: { data: Uint8Array; meta: FrameMeta } | null = null
186
+ #pendingMulticastAudio: { data: Uint8Array; meta: FrameMeta } | null = null
187
+
188
+ // Per-track source state
189
+ #trackSources = new Map<string, TrackSourceRecord>()
190
+
191
+ // Track type registry: trackName → { type, source }.
192
+ // Init data / inline signaling is authoritative until catalog updates.
193
+ // Priority: 'init' > 'catalog' > 'name' (backward compat fallback).
194
+ #trackTypes = new Map<string, { type: FrameKind; source: 'catalog' | 'init' }>()
195
+
196
+ // Crossfade state: maps trackName → remaining binary-path frames allowed during window
197
+ #crossfadeCounters = new Map<string, number>()
198
+
199
+ // Overlay alignment state
200
+ #overlayBoundaryReached = false
201
+ #overlayBuffer: Array<{ data: Uint8Array; meta: FrameMeta }> = []
202
+
203
+ // ── Phase 14: deltaActive state machine (D-11..D-14) ─────────────
204
+ // No timers — state transitions driven entirely by notifyDeltaBlock() callbacks.
205
+ // All thresholds derived from catalog fields or throw at configureDelta() time.
206
+ #deltaConfigured = false
207
+ #deltaActive: boolean = true
208
+ #deltaWindow: boolean[] = [] // ring buffer: true = block failed
209
+ #deltaWindowSize: number = 0
210
+ #deltaFailThresholdRatio: number = 0 // P/K
211
+ #deltaRecoverThresholdRatio: number = 0 // (P/K)/2 — hysteresis (D-13)
212
+ #deltaProbeIntervalMs: number = 0
213
+ #lastProbeAt: number = 0
214
+ #onDeltaFallbackCb: (() => void) | null = null
215
+ #onDeltaRecoverCb: (() => void) | null = null
216
+
217
+ constructor(options?: MediaRouterOptions) {
218
+ this.#requireAudio = options?.requireAudio ?? true
219
+ // Catalog-derived — the caller passes an audioFallbackMs computed from the
220
+ // FEC recovery window (computeFecDeliveryWindowMs). No magic default: when
221
+ // absent, the independent audio-fallback timer is disabled (0) and
222
+ // activation waits for real audio arrival.
223
+ this.#audioFallbackMs = options?.audioFallbackMs ?? 0
224
+ this.#crossfadeFrames = options?.crossfadeFrames ?? DEFAULT_CROSSFADE_FRAMES
225
+ this.#maxOverlayBuffer = options?.maxOverlayBuffer ?? DEFAULT_MAX_OVERLAY_BUFFER
226
+ this.#maxRepairInFlight = options?.maxRepairInFlight ?? 2
227
+ this.#allowDeltaMulticastTakeoverAfterMoqKeyframe =
228
+ options?.allowDeltaMulticastTakeoverAfterMoqKeyframe ?? false
229
+ }
230
+
231
+ onVideoFrame(cb: FrameCb) { this.#onVideoFrame = cb }
232
+ onAudioFrame(cb: FrameCb) { this.#onAudioFrame = cb }
233
+ onOverlayFrame(cb: FrameCb) { this.#onOverlayFrame = cb }
234
+ onSourceSwitch(cb: SwitchCb) { this.#onSourceSwitch = cb }
235
+
236
+ get activeSource(): SourceKind { return this.#active }
237
+
238
+ // ── Keyframe repair API ──────────────────────────────────────────
239
+
240
+ /** Register callback for keyframe repair requests. Player wires this to issue MoQ SUBSCRIBE. */
241
+ onRepairRequest(cb: (expectedGroupId: number, trackName: string) => void): void {
242
+ this.#onRepairRequest = cb
243
+ }
244
+
245
+ /**
246
+ * Request repair for a lost keyframe group. Only fires when activeSource is 'multicast'.
247
+ * Idempotent per groupId — duplicate calls for the same group are suppressed.
248
+ * @param expectedGroupId - The group ID expected but not received
249
+ * @param trackName - Track name for the SUBSCRIBE (e.g. 'video'). Default: 'video'.
250
+ */
251
+ repairLostGroup(expectedGroupId: number, trackName = 'video'): void {
252
+ if (this.#active !== 'multicast') return // only repair on multicast path
253
+ if (this.#repairInFlight.has(expectedGroupId)) return // idempotent
254
+ if (this.#repairInFlight.size >= this.#maxRepairInFlight) {
255
+ console.warn(
256
+ `[MediaRouter] max repair in flight (${this.#maxRepairInFlight}), dropping repair for group ${expectedGroupId}`,
257
+ )
258
+ return
259
+ }
260
+ this.#repairInFlight.add(expectedGroupId)
261
+ this.#onRepairRequest?.(expectedGroupId, trackName)
262
+ }
263
+
264
+ /**
265
+ * Feed a recovered keyframe frame from the repair path.
266
+ * Bypasses source arbitration entirely — goes directly to decoder callbacks.
267
+ * Does NOT change activeSource. Does NOT trigger failbackToMoq.
268
+ */
269
+ feedRepair(data: Uint8Array, meta: FrameMeta, kind: FrameKind): void {
270
+ // Repair only makes sense when multicast is active.
271
+ // Silently drop if MoQ became active (race with failbackToMoq) to avoid
272
+ // injecting stale-timestamp frames into the MoQ decoder path (WR-02).
273
+ if (this.#active !== 'multicast') return
274
+ const routedMeta = { ...meta, source: 'repair' as const, recovered: true }
275
+ if (kind === 'video') this.#onVideoFrame?.(data, routedMeta)
276
+ else this.#onAudioFrame?.(data, routedMeta)
277
+ }
278
+
279
+ /**
280
+ * Clear repair-in-flight state for a group (called after repair completes or times out).
281
+ */
282
+ clearRepairInFlight(groupId: number): void {
283
+ this.#repairInFlight.delete(groupId)
284
+ }
285
+
286
+ // ── Phase 14: deltaActive state machine API ──────────────────────
287
+
288
+ /**
289
+ * Configure the delta-track fallback state machine from catalog parameters.
290
+ *
291
+ * D-11: Thresholds derive from fec.sourceSymbols, fec.repairSymbols, framerate.
292
+ * D-13: Probe interval derives from deltaProbeIntervalMs or interleaveDepthMs*2.
293
+ * CLAUDE.md: error on bad init — throws if required inputs are absent.
294
+ *
295
+ * Calling again resets deltaActive=true and clears the window buffer (stream restart).
296
+ */
297
+ configureDelta(cfg: {
298
+ framerate: number
299
+ sourceSymbols: number
300
+ repairSymbols: number
301
+ deltaFailWindowBlocks?: number
302
+ deltaProbeIntervalMs?: number
303
+ interleaveDepthMs?: number
304
+ }): void {
305
+ if (typeof cfg.framerate !== 'number' || !Number.isFinite(cfg.framerate) || cfg.framerate <= 0) {
306
+ throw new Error('[MediaRouter] configureDelta: framerate required and must be > 0')
307
+ }
308
+ if (typeof cfg.sourceSymbols !== 'number' || cfg.sourceSymbols <= 0) {
309
+ throw new Error('[MediaRouter] configureDelta: sourceSymbols (K_delta) required and must be > 0')
310
+ }
311
+ if (typeof cfg.repairSymbols !== 'number' || cfg.repairSymbols <= 0) {
312
+ throw new Error('[MediaRouter] configureDelta: repairSymbols (P_delta) required and must be > 0')
313
+ }
314
+ if (cfg.deltaProbeIntervalMs === undefined && cfg.interleaveDepthMs === undefined) {
315
+ throw new Error(
316
+ '[MediaRouter] configureDelta: either deltaProbeIntervalMs or interleaveDepthMs required for probe interval derivation'
317
+ )
318
+ }
319
+
320
+ // Derivations — no magic floors, no hardcoded defaults (CLAUDE.md).
321
+ this.#deltaWindowSize = cfg.deltaFailWindowBlocks ?? Math.ceil(cfg.framerate)
322
+ this.#deltaFailThresholdRatio = cfg.repairSymbols / cfg.sourceSymbols
323
+ this.#deltaRecoverThresholdRatio = this.#deltaFailThresholdRatio / 2
324
+ // Without an explicit probe interval, use one complete signaled block span.
325
+ this.#deltaProbeIntervalMs = cfg.deltaProbeIntervalMs ?? computeFecDeliveryWindowMs({
326
+ interleaveDepthMs: cfg.interleaveDepthMs!,
327
+ sourceSymbols: cfg.sourceSymbols,
328
+ })
329
+
330
+ // Reset state — useful for stream restart.
331
+ this.#deltaActive = true
332
+ this.#deltaWindow = []
333
+ this.#lastProbeAt = 0
334
+ this.#deltaConfigured = true
335
+ }
336
+
337
+ /**
338
+ * Notify the state machine of a completed FEC block for the delta track.
339
+ *
340
+ * @param failed - true if the block was unrecoverable (FEC failure)
341
+ * @param nowMs - caller-injected monotonic ms (no internal timer — D-13, CLAUDE.md)
342
+ *
343
+ * If configureDelta() has not been called, this is a silent no-op (pre-catalog state).
344
+ */
345
+ notifyDeltaBlock(failed: boolean, nowMs: number): void {
346
+ if (!this.#deltaConfigured) return
347
+
348
+ // Maintain sliding window — ring buffer semantics.
349
+ this.#deltaWindow.push(failed)
350
+ if (this.#deltaWindow.length > this.#deltaWindowSize) {
351
+ this.#deltaWindow.shift()
352
+ }
353
+
354
+ // Window not yet full — insufficient data for decision.
355
+ if (this.#deltaWindow.length < this.#deltaWindowSize) return
356
+
357
+ const failedCount = this.#deltaWindow.filter(x => x).length
358
+ const ratio = failedCount / this.#deltaWindowSize
359
+
360
+ if (this.#deltaActive) {
361
+ // Fallback transition: active → inactive (T-14-03: fires exactly once)
362
+ if (ratio > this.#deltaFailThresholdRatio) {
363
+ this.#deltaActive = false
364
+ this.#lastProbeAt = nowMs
365
+ this.#onDeltaFallbackCb?.()
366
+ }
367
+ } else {
368
+ // Recovery transition: inactive → active (after probe interval + low ratio)
369
+ if (
370
+ (nowMs - this.#lastProbeAt) >= this.#deltaProbeIntervalMs &&
371
+ ratio < this.#deltaRecoverThresholdRatio
372
+ ) {
373
+ this.#deltaActive = true
374
+ this.#lastProbeAt = nowMs
375
+ this.#onDeltaRecoverCb?.()
376
+ }
377
+ }
378
+ }
379
+
380
+ /** Register callback fired when delta track degrades past threshold (D-12). */
381
+ onDeltaFallback(cb: () => void): void {
382
+ this.#onDeltaFallbackCb = cb
383
+ }
384
+
385
+ /** Register callback fired when delta track recovers below recovery threshold (D-13). */
386
+ onDeltaRecover(cb: () => void): void {
387
+ this.#onDeltaRecoverCb = cb
388
+ }
389
+
390
+ /** Whether the delta track is currently considered healthy (true = active). */
391
+ get deltaActive(): boolean {
392
+ return this.#deltaActive
393
+ }
394
+
395
+ // ── Test-visible accessors for threshold verification ────────────
396
+ // These expose internal derived values for test assertions (Tests 3,4,5,6,7).
397
+ // Prefixed with 'delta' to namespace clearly within the public API surface.
398
+
399
+ /** Derived window size — exposed for test assertions (Test 3, 4). */
400
+ get deltaWindowSize(): number { return this.#deltaWindowSize }
401
+ /** Derived fail threshold ratio (P/K) — exposed for test assertions (Test 6). */
402
+ get deltaFailThresholdRatio(): number { return this.#deltaFailThresholdRatio }
403
+ /** Derived recovery threshold ratio ((P/K)/2) — exposed for test assertions (Test 7). */
404
+ get deltaRecoverThresholdRatio(): number { return this.#deltaRecoverThresholdRatio }
405
+ /** Derived probe interval ms — exposed for test assertions (Test 5a). */
406
+ get deltaProbeIntervalMs(): number { return this.#deltaProbeIntervalMs }
407
+
408
+ /**
409
+ * Register a track name → type mapping from catalog.
410
+ * Catalog is the default authority. Init data / inline signaling
411
+ * takes precedence until the next catalog update.
412
+ */
413
+ registerTrackType(trackName: string, type: FrameKind): void {
414
+ // Catalog overwrites any previous registration (including init).
415
+ this.#trackTypes.set(trackName, { type, source: 'catalog' })
416
+ }
417
+
418
+ /**
419
+ * Register a track name → type from init data / inline signaling (MMTP FT=0).
420
+ * Authoritative until the next catalog update per §5.3.
421
+ * Does NOT overwrite an existing catalog registration.
422
+ */
423
+ registerTrackTypeFromInit(trackName: string, type: FrameKind): void {
424
+ const existing = this.#trackTypes.get(trackName)
425
+ if (existing?.source === 'catalog') return // catalog already set — don't downgrade
426
+ this.#trackTypes.set(trackName, { type, source: 'init' })
427
+ }
428
+
429
+ /**
430
+ * Assign a per-track source. Frames from this source bypass the binary
431
+ * MoQ↔multicast switching for this track only.
432
+ *
433
+ * Throws TrackSourceConflictError if a source is already assigned for this
434
+ * track without a clearTrackSource() in between.
435
+ */
436
+ setTrackSource(trackName: string, source: TrackSource, opts?: SetTrackSourceOptions): void {
437
+ if (this.#trackSources.has(trackName)) {
438
+ throw new TrackSourceConflictError(trackName)
439
+ }
440
+
441
+ // Resolve effective policy. opts.policy takes precedence; overlay=true is legacy 'wait'.
442
+ const effectivePolicy: MigrationPolicy | undefined =
443
+ opts?.policy ?? (opts?.overlay ? 'wait' : undefined)
444
+
445
+ // For crossfade: open the binary-path window immediately so the first per-track frame
446
+ // triggers the window (counter starts before the frame callback is wired).
447
+ if (effectivePolicy === 'crossfade') {
448
+ this.#crossfadeCounters.set(trackName, this.#crossfadeFrames)
449
+ }
450
+
451
+ const record: TrackSourceRecord = {
452
+ source,
453
+ unsubscribeFrame: () => {},
454
+ emitCount: 0,
455
+ }
456
+
457
+ // Wire the frame callback
458
+ record.unsubscribeFrame = source.onFrame((data, meta) => {
459
+ record.emitCount++
460
+ if (effectivePolicy === 'wait') {
461
+ this.#handleOverlayFrame(data, meta)
462
+ } else {
463
+ // 'drop', 'crossfade', or undefined: emit immediately
464
+ this.#emitForTrack(trackName, data, meta)
465
+ }
466
+ })
467
+
468
+ // Wire the optional error callback — failback to binary switching
469
+ if (source.onError) {
470
+ record.unsubscribeError = source.onError(() => {
471
+ this.clearTrackSource(trackName)
472
+ })
473
+ }
474
+
475
+ this.#trackSources.set(trackName, record)
476
+ }
477
+
478
+ /**
479
+ * Remove the per-track source for the given track.
480
+ * Binary switching resumes for this track after this call.
481
+ */
482
+ clearTrackSource(trackName: string): void {
483
+ const record = this.#trackSources.get(trackName)
484
+ if (!record) return
485
+
486
+ record.unsubscribeFrame()
487
+ record.unsubscribeError?.()
488
+ record.source.dispose?.()
489
+ this.#trackSources.delete(trackName)
490
+
491
+ // Clean up crossfade window if one was active for this track
492
+ this.#crossfadeCounters.delete(trackName)
493
+
494
+ // Reset overlay buffer if removing a non-media track (overlay/unknown)
495
+ const reg = this.#trackTypes.get(trackName)
496
+ const isMedia = reg?.type === 'video' || reg?.type === 'audio' ||
497
+ (reg === undefined && (trackName === 'video' || trackName === 'audio'))
498
+ if (!isMedia) {
499
+ this.#overlayBoundaryReached = false
500
+ this.#overlayBuffer = []
501
+ }
502
+ }
503
+
504
+ /**
505
+ * Signal that a FEC block boundary has been reached on the base track.
506
+ * Overlay tracks waiting for alignment flush their buffered frames now.
507
+ */
508
+ notifyFecBlockBoundary(): void {
509
+ if (this.#overlayBoundaryReached) return
510
+ this.#overlayBoundaryReached = true
511
+
512
+ // Flush buffered overlay frames
513
+ const buffered = this.#overlayBuffer.splice(0)
514
+ for (const { data, meta } of buffered) {
515
+ this.#onOverlayFrame?.(data, meta)
516
+ }
517
+ }
518
+
519
+ /**
520
+ * Return the number of frames emitted from the per-track source for a given
521
+ * track. Used in test-mode to verify per-track routing histogram.
522
+ * Returns 0 if no per-track source is active for the track.
523
+ */
524
+ trackSourceEmitCount(trackName: string): number {
525
+ return this.#trackSources.get(trackName)?.emitCount ?? 0
526
+ }
527
+
528
+ /** Feed a frame from the MoQ path. Suppressed when multicast is active OR a per-track source owns this track. */
529
+ feedMoq(data: Uint8Array, meta: FrameMeta, kind: FrameKind) {
530
+ // Per-track source takes precedence; allow through during crossfade window
531
+ if (this.#trackSources.has(kind)) {
532
+ const remaining = this.#crossfadeCounters.get(kind)
533
+ if (remaining && remaining > 0) {
534
+ // Decrement crossfade counter and allow this frame through
535
+ const next = remaining - 1
536
+ if (next === 0) {
537
+ this.#crossfadeCounters.delete(kind)
538
+ } else {
539
+ this.#crossfadeCounters.set(kind, next)
540
+ }
541
+ // Fall through to emit below (no return)
542
+ } else {
543
+ return // suppressed — no crossfade window active
544
+ }
545
+ }
546
+ if (this.#suppressed) return
547
+ // Audio suppression is handled by SessionManager onSuppress callback —
548
+ // do NOT independently suppress based on multicastAudioReceived.
549
+ // The state machine decides when to switch; the router just routes.
550
+ const routedMeta = { ...meta, source: 'moq' as const }
551
+ if (kind === 'video') this.#onVideoFrame?.(data, routedMeta)
552
+ else this.#onAudioFrame?.(data, routedMeta)
553
+ }
554
+
555
+ /** Feed a frame from the multicast path. Video waits for keyframe before activating. */
556
+ feedMulticast(data: Uint8Array, meta: FrameMeta, kind: FrameKind) {
557
+ // Per-track source takes precedence; allow through during crossfade window
558
+ if (this.#trackSources.has(kind)) {
559
+ const remaining = this.#crossfadeCounters.get(kind)
560
+ if (remaining && remaining > 0) {
561
+ const next = remaining - 1
562
+ if (next === 0) {
563
+ this.#crossfadeCounters.delete(kind)
564
+ } else {
565
+ this.#crossfadeCounters.set(kind, next)
566
+ }
567
+ // Fall through to emit below (no return)
568
+ } else {
569
+ return // suppressed
570
+ }
571
+ }
572
+
573
+ if (kind === 'video') {
574
+ if (!this.#multicastVideoKeyed) {
575
+ const moqSeededDelta =
576
+ !meta.keyframe &&
577
+ this.#allowDeltaMulticastTakeoverAfterMoqKeyframe &&
578
+ this.#moqVideoKeyframeEmitted
579
+ if (!meta.keyframe && !moqSeededDelta) return // drop until first safe decode point
580
+ this.#multicastVideoKeyed = true
581
+ const pendingMeta: FrameMeta = { ...meta, source: 'multicast' }
582
+ if (!moqSeededDelta) pendingMeta.sourceDiscontinuity = true
583
+ this.#pendingMulticastVideo = {
584
+ data: data.slice(),
585
+ meta: pendingMeta,
586
+ }
587
+ // If audio is required but hasn't arrived yet, start a fallback timer.
588
+ // Audio FEC blocks may recover after video — don't block activation forever.
589
+ // Only arms when a catalog-derived audioFallbackMs was supplied (>0).
590
+ if (this.#requireAudio && this.#audioFallbackMs > 0 && !this.#multicastAudioReceived && !this.#audioFallbackTimer) {
591
+ this.#audioFallbackTimer = setTimeout(() => {
592
+ if (!this.#multicastAudioReceived && this.#active !== 'multicast') {
593
+ this.#multicastAudioReceived = true // force
594
+ // Also release the MoQ-audio-warmup gate so the fallback actually
595
+ // activates — otherwise #tryActivateMulticast would still bail.
596
+ this.#moqAudioWarmed = true
597
+ this.#tryActivateMulticast()
598
+ }
599
+ }, this.#audioFallbackMs)
600
+ }
601
+ } else if (this.#active !== 'multicast') {
602
+ // Do not feed video into the multicast decoder while the source switch
603
+ // is still pending. Keep the newest keyframe as the post-activation
604
+ // decoder opener and drop deltas until takeover commits.
605
+ if (meta.keyframe) {
606
+ this.#pendingMulticastVideo = {
607
+ data: data.slice(),
608
+ meta: { ...meta, source: 'multicast', sourceDiscontinuity: true },
609
+ }
610
+ }
611
+ this.#tryActivateMulticast()
612
+ return
613
+ }
614
+ if (this.#active === 'multicast') this.#onVideoFrame?.(data, { ...meta, source: 'multicast' })
615
+ this.#tryActivateMulticast()
616
+ } else {
617
+ this.#multicastAudioReceived = true
618
+ if (this.#audioFallbackTimer) {
619
+ clearTimeout(this.#audioFallbackTimer)
620
+ this.#audioFallbackTimer = null
621
+ }
622
+ // BLO-3035 layer 5: in a multicast-first scenario (no MoQ unicast audio
623
+ // source) `notifyMoqAudioEmit()` is never called and the audio-fallback
624
+ // timer's force-set is bypassed (the timer's inner `!multicastAudioReceived`
625
+ // check returns early because audio already arrived). Without this gate
626
+ // `#moqAudioWarmed` stays false forever and `#tryActivateMulticast` never
627
+ // fires `onSourceSwitch('multicast')` — the player can't know to emit
628
+ // `__MULTICAST_TAKEOVER_TIME`. Treat the arrival of multicast audio as
629
+ // sufficient evidence to release the warmup gate. For the MoQ→multicast
630
+ // handoff case `notifyMoqAudioEmit()` will already have set this flag, so
631
+ // the assignment is idempotent.
632
+ if (!this.#moqAudioWarmed) this.#moqAudioWarmed = true
633
+ // Activate BEFORE delivering the frame — the source switch callback
634
+ // (e.g. ring buffer reset) must fire before the first multicast audio
635
+ // frame reaches the backend. Otherwise the NTP timestamp hits the
636
+ // MoQ-era ring buffer base → overflow → silence gap.
637
+ this.#tryActivateMulticast()
638
+ // Only emit multicast audio AFTER takeover succeeds. Before takeover,
639
+ // MoQ audio is still flowing through feedMoq → #onAudioFrame; emitting
640
+ // multicast audio too would double-feed the backend (2x audio frames,
641
+ // pitch wobble and distortion). Post-takeover, feedMoq is suppressed
642
+ // (#suppressed=true) so only multicast audio reaches the backend.
643
+ if (this.#active === 'multicast') {
644
+ this.#onAudioFrame?.(data, { ...meta, source: 'multicast' })
645
+ } else if (this.#pendingMulticastToken !== null) {
646
+ this.#pendingMulticastAudio = { data: data.slice(), meta: { ...meta, source: 'multicast' } }
647
+ }
648
+ }
649
+ }
650
+
651
+ /**
652
+ * MoQ unicast audio warmup gate. When audio is required, multicast takeover
653
+ * waits until the MoQ unicast audio decoder has emitted at least one frame
654
+ * (so downstream samples-before-takeover counters observe nonzero) or until
655
+ * the existing audio-fallback timer forces the flag true.
656
+ */
657
+ #moqAudioWarmed = false
658
+
659
+ /** Called by the player when the MoQ unicast audio decoder emits first frame. */
660
+ public notifyMoqAudioEmit(): void {
661
+ if (this.#moqAudioWarmed) return
662
+ this.#moqAudioWarmed = true
663
+ this.#tryActivateMulticast()
664
+ }
665
+
666
+ /**
667
+ * Called by the player after a MoQ video keyframe has reached the active
668
+ * decoder path. Used only by MSE/MMTP continuity switching; decoder-reset
669
+ * paths leave allowDeltaMulticastTakeoverAfterMoqKeyframe disabled.
670
+ */
671
+ public notifyMoqVideoKeyframeEmit(): void {
672
+ this.#moqVideoKeyframeEmitted = true
673
+ this.#tryActivateMulticast()
674
+ }
675
+
676
+ #tryActivateMulticast() {
677
+ if (this.#active === 'multicast') return
678
+ if (this.#pendingMulticastToken !== null) return
679
+ if (!this.#multicastVideoKeyed) return
680
+ if (this.#requireAudio && !this.#multicastAudioReceived) return
681
+ if (this.#requireAudio && !this.#moqAudioWarmed) return
682
+ const token = ++this.#sourceSwitchToken
683
+ const maybeReady = this.#onSourceSwitch?.('multicast')
684
+ if (!maybeReady || typeof (maybeReady as Promise<void>).then !== 'function') {
685
+ this.#commitMulticastActivation(token)
686
+ return
687
+ }
688
+ const ready = Promise.resolve(maybeReady)
689
+ this.#pendingMulticastToken = token
690
+ this.#sourceSwitchReady = ready
691
+ void ready.then(
692
+ () => this.#commitMulticastActivation(token),
693
+ err => this.#rejectMulticastActivation(token, err),
694
+ ).finally(() => {
695
+ if (this.#sourceSwitchReady === ready) this.#sourceSwitchReady = null
696
+ })
697
+ }
698
+
699
+ #commitMulticastActivation(token: number) {
700
+ if (token !== this.#sourceSwitchToken) return
701
+ this.#active = 'multicast'
702
+ this.#suppressed = true
703
+ this.#pendingMulticastToken = null
704
+ const video = this.#pendingMulticastVideo
705
+ this.#pendingMulticastVideo = null
706
+ const audio = this.#pendingMulticastAudio
707
+ this.#pendingMulticastAudio = null
708
+ if (video) this.#onVideoFrame?.(video.data, video.meta)
709
+ if (audio) this.#onAudioFrame?.(audio.data, audio.meta)
710
+ }
711
+
712
+ #rejectMulticastActivation(token: number, err: unknown) {
713
+ if (token !== this.#sourceSwitchToken) return
714
+ if (this.#pendingMulticastToken === token) this.#pendingMulticastToken = null
715
+ this.#pendingMulticastVideo = null
716
+ this.#pendingMulticastAudio = null
717
+ console.warn('[MediaRouter] onSourceSwitch(multicast) failed', err)
718
+ }
719
+
720
+ /** Switch back to MoQ immediately (called on multicast failback). */
721
+ failbackToMoq() {
722
+ const hadPendingMulticast = this.#pendingMulticastToken !== null
723
+ if (this.#active === 'moq' && !hadPendingMulticast) return // already on MoQ, no-op
724
+ ++this.#sourceSwitchToken
725
+ this.#active = 'moq'
726
+ this.#suppressed = false
727
+ this.#pendingMulticastToken = null
728
+ this.#pendingMulticastVideo = null
729
+ this.#pendingMulticastAudio = null
730
+ this.#sourceSwitchReady = null
731
+ this.#multicastVideoKeyed = false
732
+ this.#multicastAudioReceived = false
733
+ this.#moqVideoKeyframeEmitted = false
734
+ // A pending audio-fallback timer belongs to the abandoned takeover attempt.
735
+ // Left running it would force-set the audio flags against the next attempt's
736
+ // fresh state (BLO-9413 failback coherence — every takeover-era flag/timer
737
+ // unwinds on this edge).
738
+ if (this.#audioFallbackTimer) {
739
+ clearTimeout(this.#audioFallbackTimer)
740
+ this.#audioFallbackTimer = null
741
+ }
742
+ this.#onSourceSwitch?.('moq')
743
+ }
744
+
745
+ /** Dispose timers and per-track sources. Call on teardown to prevent
746
+ * stale timer callbacks firing into garbage-collected closures (WR-03). */
747
+ dispose(): void {
748
+ if (this.#audioFallbackTimer) {
749
+ clearTimeout(this.#audioFallbackTimer)
750
+ this.#audioFallbackTimer = null
751
+ }
752
+ for (const [name] of this.#trackSources) {
753
+ this.clearTrackSource(name)
754
+ }
755
+ }
756
+
757
+ // ── Private helpers ──────────────────────────────────────────────────────
758
+
759
+ /** Emit a frame on the correct per-track callback using the type registry.
760
+ * Falls back to name match if no type registered (backward compat). */
761
+ #emitForTrack(trackName: string, data: Uint8Array, meta: FrameMeta): void {
762
+ // Prefer explicit type registry (catalog or init data)
763
+ const reg = this.#trackTypes.get(trackName)
764
+ if (reg?.type === 'video') {
765
+ this.#onVideoFrame?.(data, meta)
766
+ } else if (reg?.type === 'audio') {
767
+ this.#onAudioFrame?.(data, meta)
768
+ } else if (reg !== undefined) {
769
+ // Registered but unknown type — overlay
770
+ this.#onOverlayFrame?.(data, meta)
771
+ } else {
772
+ // Not registered — fall back to name match (backward compat for tests/legacy)
773
+ if (trackName === 'video') this.#onVideoFrame?.(data, meta)
774
+ else if (trackName === 'audio') this.#onAudioFrame?.(data, meta)
775
+ else this.#onOverlayFrame?.(data, meta)
776
+ }
777
+ }
778
+
779
+ /** Handle an overlay frame: buffer until first FEC block boundary, then pass through. */
780
+ #handleOverlayFrame(data: Uint8Array, meta: FrameMeta): void {
781
+ if (this.#overlayBoundaryReached) {
782
+ this.#onOverlayFrame?.(data, meta)
783
+ return
784
+ }
785
+
786
+ // Buffer until boundary — enforcing cap for T-02-17 DoS mitigation
787
+ if (this.#overlayBuffer.length >= this.#maxOverlayBuffer) {
788
+ console.warn(
789
+ `[MediaRouter] overlay buffer full (${this.#maxOverlayBuffer} frames); dropping frame ts=${meta.timestamp}`
790
+ )
791
+ return
792
+ }
793
+ this.#overlayBuffer.push({ data, meta })
794
+ }
795
+ }