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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (799) hide show
  1. package/README.md +524 -0
  2. package/dist/.build-stamp +0 -0
  3. package/dist/__tests__/test-utils.d.ts +71 -0
  4. package/dist/__tests__/test-utils.d.ts.map +1 -0
  5. package/dist/align.d.ts +152 -0
  6. package/dist/align.d.ts.map +1 -0
  7. package/dist/align.js +88 -0
  8. package/dist/align.js.map +7 -0
  9. package/dist/audio-init-parser.d.ts +66 -0
  10. package/dist/audio-init-parser.d.ts.map +1 -0
  11. package/dist/audio-init-parser.js +118 -0
  12. package/dist/audio-init-parser.js.map +7 -0
  13. package/dist/audio-ring-buffer.d.ts +50 -0
  14. package/dist/audio-ring-buffer.d.ts.map +1 -0
  15. package/dist/audio-ring-buffer.js +80 -0
  16. package/dist/audio-ring-buffer.js.map +7 -0
  17. package/dist/authored-timing.d.ts +32 -0
  18. package/dist/authored-timing.d.ts.map +1 -0
  19. package/dist/authored-timing.js +32 -0
  20. package/dist/authored-timing.js.map +7 -0
  21. package/dist/block-policy.d.ts +314 -0
  22. package/dist/block-policy.d.ts.map +1 -0
  23. package/dist/block-policy.js +466 -0
  24. package/dist/block-policy.js.map +7 -0
  25. package/dist/browser-runtime.js +26549 -0
  26. package/dist/browser-runtime.js.map +7 -0
  27. package/dist/carp-catalog.d.ts +429 -0
  28. package/dist/carp-catalog.d.ts.map +1 -0
  29. package/dist/carp-catalog.js +985 -0
  30. package/dist/carp-catalog.js.map +7 -0
  31. package/dist/catalog-fec-params.d.ts +275 -0
  32. package/dist/catalog-fec-params.d.ts.map +1 -0
  33. package/dist/catalog-fec-params.js +702 -0
  34. package/dist/catalog-fec-params.js.map +7 -0
  35. package/dist/catalog-network-source.d.ts +42 -0
  36. package/dist/catalog-network-source.d.ts.map +1 -0
  37. package/dist/catalog-network-source.js +47 -0
  38. package/dist/catalog-network-source.js.map +7 -0
  39. package/dist/catalog-validator.d.ts +18 -0
  40. package/dist/catalog-validator.d.ts.map +1 -0
  41. package/dist/catalog-validator.js +7747 -0
  42. package/dist/catalog-validator.js.map +7 -0
  43. package/dist/cmaf-block-assembler.d.ts +285 -0
  44. package/dist/cmaf-block-assembler.d.ts.map +1 -0
  45. package/dist/cmaf-block-assembler.js +1966 -0
  46. package/dist/cmaf-block-assembler.js.map +7 -0
  47. package/dist/cmaf-group-batcher.d.ts +38 -0
  48. package/dist/cmaf-group-batcher.d.ts.map +1 -0
  49. package/dist/cmaf-group-batcher.js +176 -0
  50. package/dist/cmaf-group-batcher.js.map +7 -0
  51. package/dist/cmcd-producer.d.ts +104 -0
  52. package/dist/cmcd-producer.d.ts.map +1 -0
  53. package/dist/cmcd-producer.js +183 -0
  54. package/dist/cmcd-producer.js.map +7 -0
  55. package/dist/codec-utils.d.ts +384 -0
  56. package/dist/codec-utils.d.ts.map +1 -0
  57. package/dist/codec-utils.js +1546 -0
  58. package/dist/codec-utils.js.map +7 -0
  59. package/dist/conceal-timeline.d.ts +146 -0
  60. package/dist/conceal-timeline.d.ts.map +1 -0
  61. package/dist/conceal-timeline.js +137 -0
  62. package/dist/conceal-timeline.js.map +7 -0
  63. package/dist/delivery-gap.d.ts +75 -0
  64. package/dist/delivery-gap.d.ts.map +1 -0
  65. package/dist/delivery-gap.js +88 -0
  66. package/dist/delivery-gap.js.map +7 -0
  67. package/dist/duplicate-ledger.d.ts +197 -0
  68. package/dist/duplicate-ledger.d.ts.map +1 -0
  69. package/dist/duplicate-ledger.js +226 -0
  70. package/dist/duplicate-ledger.js.map +7 -0
  71. package/dist/fec-codec.d.ts +32 -0
  72. package/dist/fec-codec.d.ts.map +1 -0
  73. package/dist/fec-codec.js +47 -0
  74. package/dist/fec-codec.js.map +7 -0
  75. package/dist/fec-manager.d.ts +583 -0
  76. package/dist/fec-manager.d.ts.map +1 -0
  77. package/dist/fec-manager.js +3899 -0
  78. package/dist/fec-manager.js.map +7 -0
  79. package/dist/fec-starvation-detector.d.ts +59 -0
  80. package/dist/fec-starvation-detector.d.ts.map +1 -0
  81. package/dist/fec-starvation-detector.js +60 -0
  82. package/dist/fec-starvation-detector.js.map +7 -0
  83. package/dist/fec-state.d.ts +131 -0
  84. package/dist/fec-state.d.ts.map +1 -0
  85. package/dist/fec-state.js +87 -0
  86. package/dist/fec-state.js.map +7 -0
  87. package/dist/fec-worker-setup.d.ts +94 -0
  88. package/dist/fec-worker-setup.d.ts.map +1 -0
  89. package/dist/fec-worker-setup.js +673 -0
  90. package/dist/fec-worker-setup.js.map +7 -0
  91. package/dist/fmp4-completion.d.ts +30 -0
  92. package/dist/fmp4-completion.d.ts.map +1 -0
  93. package/dist/fmp4-completion.js +21 -0
  94. package/dist/fmp4-completion.js.map +7 -0
  95. package/dist/fmp4-reader.d.ts +37 -0
  96. package/dist/fmp4-reader.d.ts.map +1 -0
  97. package/dist/fmp4-reader.js +100 -0
  98. package/dist/fmp4-reader.js.map +7 -0
  99. package/dist/index.d.ts +44 -3
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +460 -14
  102. package/dist/index.js.map +7 -1
  103. package/dist/iso-block-locator.d.ts +118 -0
  104. package/dist/iso-block-locator.d.ts.map +1 -0
  105. package/dist/iso-block-locator.js +289 -0
  106. package/dist/iso-block-locator.js.map +7 -0
  107. package/dist/iso-bmff-timing.d.ts +78 -0
  108. package/dist/iso-bmff-timing.d.ts.map +1 -0
  109. package/dist/iso-bmff-timing.js +593 -0
  110. package/dist/iso-bmff-timing.js.map +7 -0
  111. package/dist/loc.d.ts +70 -75
  112. package/dist/loc.d.ts.map +1 -1
  113. package/dist/loc.js +106 -192
  114. package/dist/loc.js.map +7 -1
  115. package/dist/manifest-auth-plan.d.ts +30 -0
  116. package/dist/manifest-auth-plan.d.ts.map +1 -0
  117. package/dist/manifest-auth-plan.js +1266 -0
  118. package/dist/manifest-auth-plan.js.map +7 -0
  119. package/dist/media-router.d.ts +262 -0
  120. package/dist/media-router.d.ts.map +1 -0
  121. package/dist/media-router.js +584 -0
  122. package/dist/media-router.js.map +7 -0
  123. package/dist/mfu-reassembler.d.ts +313 -9
  124. package/dist/mfu-reassembler.d.ts.map +1 -1
  125. package/dist/mfu-reassembler.js +3051 -285
  126. package/dist/mfu-reassembler.js.map +7 -1
  127. package/dist/mfu-reassembly-policy.d.ts +24 -0
  128. package/dist/mfu-reassembly-policy.d.ts.map +1 -0
  129. package/dist/mfu-reassembly-policy.js +99 -0
  130. package/dist/mfu-reassembly-policy.js.map +7 -0
  131. package/dist/mmtp-container-parser.d.ts +568 -0
  132. package/dist/mmtp-container-parser.d.ts.map +1 -0
  133. package/dist/mmtp-container-parser.js +6580 -0
  134. package/dist/mmtp-container-parser.js.map +7 -0
  135. package/dist/mmtp-container-parser.no-modules.js +9616 -0
  136. package/dist/mmtp-container-parser.no-modules.js.map +7 -0
  137. package/dist/mmtp-decode-pipeline.d.ts +138 -0
  138. package/dist/mmtp-decode-pipeline.d.ts.map +1 -0
  139. package/dist/mmtp-decode-pipeline.js +6814 -0
  140. package/dist/mmtp-decode-pipeline.js.map +7 -0
  141. package/dist/mmtp-router.d.ts +679 -0
  142. package/dist/mmtp-router.d.ts.map +1 -0
  143. package/dist/mmtp-router.js +11278 -0
  144. package/dist/mmtp-router.js.map +7 -0
  145. package/dist/mmtp-to-cmaf.d.ts +187 -0
  146. package/dist/mmtp-to-cmaf.d.ts.map +1 -0
  147. package/dist/mmtp-to-cmaf.js +716 -0
  148. package/dist/mmtp-to-cmaf.js.map +7 -0
  149. package/dist/multicast-auth-catalog.d.ts +115 -0
  150. package/dist/multicast-auth-catalog.d.ts.map +1 -0
  151. package/dist/multicast-auth-catalog.js +202 -0
  152. package/dist/multicast-auth-catalog.js.map +7 -0
  153. package/dist/multicast-input.d.ts +141 -0
  154. package/dist/multicast-input.d.ts.map +1 -0
  155. package/dist/multicast-input.js +390 -0
  156. package/dist/multicast-input.js.map +7 -0
  157. package/dist/multicast-manager.d.ts +669 -0
  158. package/dist/multicast-manager.d.ts.map +1 -0
  159. package/dist/multicast-manager.js +19101 -0
  160. package/dist/multicast-manager.js.map +7 -0
  161. package/dist/multicast-transport.d.ts +271 -0
  162. package/dist/multicast-transport.d.ts.map +1 -0
  163. package/dist/multicast-transport.js +2264 -0
  164. package/dist/multicast-transport.js.map +7 -0
  165. package/dist/multicast-unwrap.d.ts +57 -0
  166. package/dist/multicast-unwrap.d.ts.map +1 -0
  167. package/dist/multicast-unwrap.js +418 -0
  168. package/dist/multicast-unwrap.js.map +7 -0
  169. package/dist/no-modules.d.ts +10 -0
  170. package/dist/no-modules.d.ts.map +1 -0
  171. package/dist/no-modules.js +9491 -0
  172. package/dist/no-modules.js.map +7 -0
  173. package/dist/phase14-catalog-override.d.ts +126 -0
  174. package/dist/phase14-catalog-override.d.ts.map +1 -0
  175. package/dist/phase14-catalog-override.js +155 -0
  176. package/dist/phase14-catalog-override.js.map +7 -0
  177. package/dist/repair-fetch.d.ts +270 -0
  178. package/dist/repair-fetch.d.ts.map +1 -0
  179. package/dist/repair-fetch.js +381 -0
  180. package/dist/repair-fetch.js.map +7 -0
  181. package/dist/repair-layers.d.ts +158 -0
  182. package/dist/repair-layers.d.ts.map +1 -0
  183. package/dist/repair-layers.js +344 -0
  184. package/dist/repair-layers.js.map +7 -0
  185. package/dist/sample-combiner.d.ts +212 -0
  186. package/dist/sample-combiner.d.ts.map +1 -0
  187. package/dist/sample-combiner.js +595 -0
  188. package/dist/sample-combiner.js.map +7 -0
  189. package/dist/signaling.d.ts +29 -0
  190. package/dist/signaling.d.ts.map +1 -0
  191. package/dist/signaling.js +572 -0
  192. package/dist/signaling.js.map +7 -0
  193. package/dist/source-auth.d.ts +2 -0
  194. package/dist/source-auth.d.ts.map +1 -0
  195. package/dist/source-auth.js +1209 -0
  196. package/dist/source-auth.js.map +7 -0
  197. package/dist/switching-set-alignment.d.ts +61 -0
  198. package/dist/switching-set-alignment.d.ts.map +1 -0
  199. package/dist/switching-set-alignment.js +70 -0
  200. package/dist/switching-set-alignment.js.map +7 -0
  201. package/dist/timestamp-codec.d.ts +34 -0
  202. package/dist/timestamp-codec.d.ts.map +1 -0
  203. package/dist/timestamp-codec.js +473 -0
  204. package/dist/timestamp-codec.js.map +7 -0
  205. package/dist/track-pipeline-setup.d.ts +83 -0
  206. package/dist/track-pipeline-setup.d.ts.map +1 -0
  207. package/dist/track-pipeline-setup.js +291 -0
  208. package/dist/track-pipeline-setup.js.map +7 -0
  209. package/dist/track-pipeline.d.ts +121 -0
  210. package/dist/track-pipeline.d.ts.map +1 -0
  211. package/dist/track-pipeline.js +209 -0
  212. package/dist/track-pipeline.js.map +7 -0
  213. package/dist/track-session.d.ts +414 -0
  214. package/dist/track-session.d.ts.map +1 -0
  215. package/dist/track-session.js +754 -0
  216. package/dist/track-session.js.map +7 -0
  217. package/dist/transport-pool.d.ts +69 -0
  218. package/dist/transport-pool.d.ts.map +1 -0
  219. package/dist/transport-pool.js +74 -0
  220. package/dist/transport-pool.js.map +7 -0
  221. package/dist/wasm-mfu-reassembler.d.ts +97 -0
  222. package/dist/wasm-mfu-reassembler.d.ts.map +1 -0
  223. package/dist/wasm-mfu-reassembler.js +2133 -0
  224. package/dist/wasm-mfu-reassembler.js.map +7 -0
  225. package/dist/wasm-mmtp-container-parser.d.ts +10 -0
  226. package/dist/wasm-mmtp-container-parser.d.ts.map +1 -0
  227. package/dist/wasm-mmtp-container-parser.js +6834 -0
  228. package/dist/wasm-mmtp-container-parser.js.map +7 -0
  229. package/node_modules/@blockcast/fec-worker/README.md +223 -0
  230. package/node_modules/@blockcast/fec-worker/dist/.build-stamp +0 -0
  231. package/node_modules/@blockcast/fec-worker/dist/block-order.d.ts +38 -0
  232. package/node_modules/@blockcast/fec-worker/dist/block-order.d.ts.map +1 -0
  233. package/node_modules/@blockcast/fec-worker/dist/block-order.js +78 -0
  234. package/node_modules/@blockcast/fec-worker/dist/block-order.js.map +1 -0
  235. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts +93 -0
  236. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts.map +1 -0
  237. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js +346 -0
  238. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js.map +1 -0
  239. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts +380 -0
  240. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts.map +1 -0
  241. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js +11 -0
  242. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js.map +1 -0
  243. package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts +14 -0
  244. package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts.map +1 -0
  245. package/node_modules/@blockcast/fec-worker/dist/fec-worker.js +859 -0
  246. package/node_modules/@blockcast/fec-worker/dist/fec-worker.js.map +7 -0
  247. package/node_modules/@blockcast/fec-worker/dist/index.d.ts +10 -0
  248. package/node_modules/@blockcast/fec-worker/dist/index.d.ts.map +1 -0
  249. package/node_modules/@blockcast/fec-worker/dist/index.js +8 -0
  250. package/node_modules/@blockcast/fec-worker/dist/index.js.map +1 -0
  251. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts +20 -0
  252. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts.map +1 -0
  253. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js +370 -0
  254. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js.map +7 -0
  255. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts +104 -0
  256. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts.map +1 -0
  257. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js +181 -0
  258. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js.map +1 -0
  259. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts +194 -0
  260. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts.map +1 -0
  261. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js +62 -0
  262. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js.map +1 -0
  263. package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts +9 -0
  264. package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts.map +1 -0
  265. package/node_modules/@blockcast/fec-worker/dist/transfer.js +13 -0
  266. package/node_modules/@blockcast/fec-worker/dist/transfer.js.map +1 -0
  267. package/node_modules/@blockcast/fec-worker/package.json +59 -0
  268. package/node_modules/@blockcast/fec-worker/src/block-order.ts +93 -0
  269. package/node_modules/@blockcast/fec-worker/src/fec-worker-client.ts +392 -0
  270. package/node_modules/@blockcast/fec-worker/src/fec-worker-types.ts +399 -0
  271. package/node_modules/@blockcast/fec-worker/src/fec-worker.ts +1502 -0
  272. package/node_modules/@blockcast/fec-worker/src/index.ts +35 -0
  273. package/node_modules/@blockcast/fec-worker/src/shred-fec-worker.ts +589 -0
  274. package/node_modules/@blockcast/fec-worker/src/shred-worker-client.ts +222 -0
  275. package/node_modules/@blockcast/fec-worker/src/shred-worker-types.ts +209 -0
  276. package/node_modules/@blockcast/fec-worker/src/transfer.ts +12 -0
  277. package/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
  278. package/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
  279. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
  280. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
  281. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
  282. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
  283. package/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
  284. package/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
  285. package/node_modules/@blockcast/mmt-base/README.md +134 -0
  286. package/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
  287. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts +55 -0
  288. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts.map +1 -0
  289. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js +128 -0
  290. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js.map +1 -0
  291. package/node_modules/@blockcast/mmt-base/dist/index.d.ts +7 -0
  292. package/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
  293. package/node_modules/@blockcast/mmt-base/dist/index.js +7 -0
  294. package/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
  295. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +292 -0
  296. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
  297. package/node_modules/@blockcast/mmt-base/dist/mmtp.js +612 -0
  298. package/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
  299. package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts +18 -0
  300. package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts.map +1 -0
  301. package/node_modules/@blockcast/mmt-base/dist/net-constants.js +18 -0
  302. package/node_modules/@blockcast/mmt-base/dist/net-constants.js.map +1 -0
  303. package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts +47 -0
  304. package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts.map +1 -0
  305. package/node_modules/@blockcast/mmt-base/dist/ntp-short.js +54 -0
  306. package/node_modules/@blockcast/mmt-base/dist/ntp-short.js.map +1 -0
  307. package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts +57 -0
  308. package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts.map +1 -0
  309. package/node_modules/@blockcast/mmt-base/dist/serial-number.js +98 -0
  310. package/node_modules/@blockcast/mmt-base/dist/serial-number.js.map +1 -0
  311. package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts +312 -0
  312. package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts.map +1 -0
  313. package/node_modules/@blockcast/mmt-base/dist/signalling.js +637 -0
  314. package/node_modules/@blockcast/mmt-base/dist/signalling.js.map +1 -0
  315. package/node_modules/@blockcast/mmt-base/package.json +49 -0
  316. package/node_modules/@blockcast/mmt-base/src/fec-block-profile.ts +145 -0
  317. package/node_modules/@blockcast/mmt-base/src/index.ts +6 -0
  318. package/node_modules/@blockcast/mmt-base/src/mmtp.ts +892 -0
  319. package/node_modules/@blockcast/mmt-base/src/net-constants.ts +17 -0
  320. package/node_modules/@blockcast/mmt-base/src/ntp-short.ts +67 -0
  321. package/node_modules/@blockcast/mmt-base/src/serial-number.ts +107 -0
  322. package/node_modules/@blockcast/mmt-base/src/signalling.ts +862 -0
  323. package/node_modules/@blockcast/mmt-fec/README.md +271 -0
  324. package/node_modules/@blockcast/mmt-fec/dist/.build-stamp +0 -0
  325. package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts +82 -0
  326. package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts.map +1 -0
  327. package/node_modules/@blockcast/mmt-fec/dist/block-manager.js +296 -0
  328. package/node_modules/@blockcast/mmt-fec/dist/block-manager.js.map +1 -0
  329. package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts +106 -0
  330. package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts.map +1 -0
  331. package/node_modules/@blockcast/mmt-fec/dist/block-processor.js +288 -0
  332. package/node_modules/@blockcast/mmt-fec/dist/block-processor.js.map +1 -0
  333. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts +46 -0
  334. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts.map +1 -0
  335. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js +96 -0
  336. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js.map +1 -0
  337. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts +33 -0
  338. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts.map +1 -0
  339. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js +57 -0
  340. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js.map +1 -0
  341. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts +205 -0
  342. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts.map +1 -0
  343. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js +240 -0
  344. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js.map +1 -0
  345. package/node_modules/@blockcast/mmt-fec/dist/index.d.ts +28 -0
  346. package/node_modules/@blockcast/mmt-fec/dist/index.d.ts.map +1 -0
  347. package/node_modules/@blockcast/mmt-fec/dist/index.js +28 -0
  348. package/node_modules/@blockcast/mmt-fec/dist/index.js.map +1 -0
  349. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts +20 -0
  350. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts.map +1 -0
  351. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js +28 -0
  352. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js.map +1 -0
  353. package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts +258 -0
  354. package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts.map +1 -0
  355. package/node_modules/@blockcast/mmt-fec/dist/oti.js +382 -0
  356. package/node_modules/@blockcast/mmt-fec/dist/oti.js.map +1 -0
  357. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts +41 -0
  358. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts.map +1 -0
  359. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js +81 -0
  360. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js.map +1 -0
  361. package/node_modules/@blockcast/mmt-fec/dist/repair-group.d.ts +82 -0
  362. package/node_modules/@blockcast/mmt-fec/dist/repair-group.d.ts.map +1 -0
  363. package/node_modules/@blockcast/mmt-fec/dist/repair-group.js +170 -0
  364. package/node_modules/@blockcast/mmt-fec/dist/repair-group.js.map +1 -0
  365. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
  366. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
  367. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
  368. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
  369. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
  370. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
  371. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
  372. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
  373. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/README.md +134 -0
  374. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
  375. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts +55 -0
  376. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts.map +1 -0
  377. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js +128 -0
  378. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js.map +1 -0
  379. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts +7 -0
  380. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
  381. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js +7 -0
  382. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
  383. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +292 -0
  384. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
  385. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js +612 -0
  386. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
  387. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts +18 -0
  388. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts.map +1 -0
  389. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.js +18 -0
  390. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.js.map +1 -0
  391. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts +47 -0
  392. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts.map +1 -0
  393. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.js +54 -0
  394. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.js.map +1 -0
  395. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts +57 -0
  396. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts.map +1 -0
  397. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.js +98 -0
  398. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.js.map +1 -0
  399. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.d.ts +312 -0
  400. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.d.ts.map +1 -0
  401. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.js +637 -0
  402. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.js.map +1 -0
  403. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/package.json +49 -0
  404. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/fec-block-profile.ts +145 -0
  405. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/index.ts +6 -0
  406. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/mmtp.ts +892 -0
  407. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/net-constants.ts +17 -0
  408. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/ntp-short.ts +67 -0
  409. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/serial-number.ts +107 -0
  410. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/signalling.ts +862 -0
  411. package/node_modules/@blockcast/mmt-fec/package.json +79 -0
  412. package/node_modules/@blockcast/mmt-fec/src/block-manager.ts +371 -0
  413. package/node_modules/@blockcast/mmt-fec/src/block-processor.ts +439 -0
  414. package/node_modules/@blockcast/mmt-fec/src/cmaf-recovery.ts +127 -0
  415. package/node_modules/@blockcast/mmt-fec/src/cmaf-symbols.ts +68 -0
  416. package/node_modules/@blockcast/mmt-fec/src/fec-block-mapper.ts +310 -0
  417. package/node_modules/@blockcast/mmt-fec/src/index.ts +94 -0
  418. package/node_modules/@blockcast/mmt-fec/src/loc-symbols.ts +34 -0
  419. package/node_modules/@blockcast/mmt-fec/src/oti.ts +463 -0
  420. package/node_modules/@blockcast/mmt-fec/src/reorder-buffer.ts +101 -0
  421. package/node_modules/@blockcast/mmt-fec/src/repair-group.ts +195 -0
  422. package/node_modules/@blockcast/mmt-manifest-verify/dist/.build-stamp +0 -0
  423. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts +28 -0
  424. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts.map +1 -0
  425. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js +128 -0
  426. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js.map +1 -0
  427. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts +4 -0
  428. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts.map +1 -0
  429. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js +4 -0
  430. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js.map +1 -0
  431. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts +37 -0
  432. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts.map +1 -0
  433. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js +179 -0
  434. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js.map +1 -0
  435. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts +99 -0
  436. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts.map +1 -0
  437. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js +492 -0
  438. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js.map +1 -0
  439. package/node_modules/@blockcast/mmt-manifest-verify/package.json +45 -0
  440. package/node_modules/@blockcast/mmt-manifest-verify/src/admission.ts +171 -0
  441. package/node_modules/@blockcast/mmt-manifest-verify/src/index.ts +3 -0
  442. package/node_modules/@blockcast/mmt-manifest-verify/src/source-auth.ts +230 -0
  443. package/node_modules/@blockcast/mmt-manifest-verify/src/verifier.ts +669 -0
  444. package/node_modules/@noble/hashes/LICENSE +21 -0
  445. package/node_modules/@noble/hashes/README.md +521 -0
  446. package/node_modules/@noble/hashes/_assert.d.ts +17 -0
  447. package/node_modules/@noble/hashes/_assert.d.ts.map +1 -0
  448. package/node_modules/@noble/hashes/_assert.js +18 -0
  449. package/node_modules/@noble/hashes/_assert.js.map +1 -0
  450. package/node_modules/@noble/hashes/_blake.d.ts +14 -0
  451. package/node_modules/@noble/hashes/_blake.d.ts.map +1 -0
  452. package/node_modules/@noble/hashes/_blake.js +50 -0
  453. package/node_modules/@noble/hashes/_blake.js.map +1 -0
  454. package/node_modules/@noble/hashes/_md.d.ts +51 -0
  455. package/node_modules/@noble/hashes/_md.d.ts.map +1 -0
  456. package/node_modules/@noble/hashes/_md.js +162 -0
  457. package/node_modules/@noble/hashes/_md.js.map +1 -0
  458. package/node_modules/@noble/hashes/_u64.d.ts +55 -0
  459. package/node_modules/@noble/hashes/_u64.d.ts.map +1 -0
  460. package/node_modules/@noble/hashes/_u64.js +90 -0
  461. package/node_modules/@noble/hashes/_u64.js.map +1 -0
  462. package/node_modules/@noble/hashes/argon2.d.ts +32 -0
  463. package/node_modules/@noble/hashes/argon2.d.ts.map +1 -0
  464. package/node_modules/@noble/hashes/argon2.js +401 -0
  465. package/node_modules/@noble/hashes/argon2.js.map +1 -0
  466. package/node_modules/@noble/hashes/blake1.d.ts +106 -0
  467. package/node_modules/@noble/hashes/blake1.d.ts.map +1 -0
  468. package/node_modules/@noble/hashes/blake1.js +459 -0
  469. package/node_modules/@noble/hashes/blake1.js.map +1 -0
  470. package/node_modules/@noble/hashes/blake2.d.ts +116 -0
  471. package/node_modules/@noble/hashes/blake2.d.ts.map +1 -0
  472. package/node_modules/@noble/hashes/blake2.js +420 -0
  473. package/node_modules/@noble/hashes/blake2.js.map +1 -0
  474. package/node_modules/@noble/hashes/blake2b.d.ts +11 -0
  475. package/node_modules/@noble/hashes/blake2b.d.ts.map +1 -0
  476. package/node_modules/@noble/hashes/blake2b.js +14 -0
  477. package/node_modules/@noble/hashes/blake2b.js.map +1 -0
  478. package/node_modules/@noble/hashes/blake2s.d.ts +20 -0
  479. package/node_modules/@noble/hashes/blake2s.d.ts.map +1 -0
  480. package/node_modules/@noble/hashes/blake2s.js +24 -0
  481. package/node_modules/@noble/hashes/blake2s.js.map +1 -0
  482. package/node_modules/@noble/hashes/blake3.d.ts +54 -0
  483. package/node_modules/@noble/hashes/blake3.d.ts.map +1 -0
  484. package/node_modules/@noble/hashes/blake3.js +255 -0
  485. package/node_modules/@noble/hashes/blake3.js.map +1 -0
  486. package/node_modules/@noble/hashes/crypto.d.ts +2 -0
  487. package/node_modules/@noble/hashes/crypto.d.ts.map +1 -0
  488. package/node_modules/@noble/hashes/crypto.js +5 -0
  489. package/node_modules/@noble/hashes/crypto.js.map +1 -0
  490. package/node_modules/@noble/hashes/cryptoNode.d.ts +2 -0
  491. package/node_modules/@noble/hashes/cryptoNode.d.ts.map +1 -0
  492. package/node_modules/@noble/hashes/cryptoNode.js +18 -0
  493. package/node_modules/@noble/hashes/cryptoNode.js.map +1 -0
  494. package/node_modules/@noble/hashes/eskdf.d.ts +47 -0
  495. package/node_modules/@noble/hashes/eskdf.d.ts.map +1 -0
  496. package/node_modules/@noble/hashes/eskdf.js +166 -0
  497. package/node_modules/@noble/hashes/eskdf.js.map +1 -0
  498. package/node_modules/@noble/hashes/esm/_assert.d.ts +17 -0
  499. package/node_modules/@noble/hashes/esm/_assert.d.ts.map +1 -0
  500. package/node_modules/@noble/hashes/esm/_assert.js +15 -0
  501. package/node_modules/@noble/hashes/esm/_assert.js.map +1 -0
  502. package/node_modules/@noble/hashes/esm/_blake.d.ts +14 -0
  503. package/node_modules/@noble/hashes/esm/_blake.d.ts.map +1 -0
  504. package/node_modules/@noble/hashes/esm/_blake.js +45 -0
  505. package/node_modules/@noble/hashes/esm/_blake.js.map +1 -0
  506. package/node_modules/@noble/hashes/esm/_md.d.ts +51 -0
  507. package/node_modules/@noble/hashes/esm/_md.d.ts.map +1 -0
  508. package/node_modules/@noble/hashes/esm/_md.js +155 -0
  509. package/node_modules/@noble/hashes/esm/_md.js.map +1 -0
  510. package/node_modules/@noble/hashes/esm/_u64.d.ts +55 -0
  511. package/node_modules/@noble/hashes/esm/_u64.d.ts.map +1 -0
  512. package/node_modules/@noble/hashes/esm/_u64.js +67 -0
  513. package/node_modules/@noble/hashes/esm/_u64.js.map +1 -0
  514. package/node_modules/@noble/hashes/esm/argon2.d.ts +32 -0
  515. package/node_modules/@noble/hashes/esm/argon2.d.ts.map +1 -0
  516. package/node_modules/@noble/hashes/esm/argon2.js +392 -0
  517. package/node_modules/@noble/hashes/esm/argon2.js.map +1 -0
  518. package/node_modules/@noble/hashes/esm/blake1.d.ts +106 -0
  519. package/node_modules/@noble/hashes/esm/blake1.d.ts.map +1 -0
  520. package/node_modules/@noble/hashes/esm/blake1.js +452 -0
  521. package/node_modules/@noble/hashes/esm/blake1.js.map +1 -0
  522. package/node_modules/@noble/hashes/esm/blake2.d.ts +116 -0
  523. package/node_modules/@noble/hashes/esm/blake2.d.ts.map +1 -0
  524. package/node_modules/@noble/hashes/esm/blake2.js +413 -0
  525. package/node_modules/@noble/hashes/esm/blake2.js.map +1 -0
  526. package/node_modules/@noble/hashes/esm/blake2b.d.ts +11 -0
  527. package/node_modules/@noble/hashes/esm/blake2b.d.ts.map +1 -0
  528. package/node_modules/@noble/hashes/esm/blake2b.js +11 -0
  529. package/node_modules/@noble/hashes/esm/blake2b.js.map +1 -0
  530. package/node_modules/@noble/hashes/esm/blake2s.d.ts +20 -0
  531. package/node_modules/@noble/hashes/esm/blake2s.d.ts.map +1 -0
  532. package/node_modules/@noble/hashes/esm/blake2s.js +21 -0
  533. package/node_modules/@noble/hashes/esm/blake2s.js.map +1 -0
  534. package/node_modules/@noble/hashes/esm/blake3.d.ts +54 -0
  535. package/node_modules/@noble/hashes/esm/blake3.d.ts.map +1 -0
  536. package/node_modules/@noble/hashes/esm/blake3.js +251 -0
  537. package/node_modules/@noble/hashes/esm/blake3.js.map +1 -0
  538. package/node_modules/@noble/hashes/esm/crypto.d.ts +2 -0
  539. package/node_modules/@noble/hashes/esm/crypto.d.ts.map +1 -0
  540. package/node_modules/@noble/hashes/esm/crypto.js +2 -0
  541. package/node_modules/@noble/hashes/esm/crypto.js.map +1 -0
  542. package/node_modules/@noble/hashes/esm/cryptoNode.d.ts +2 -0
  543. package/node_modules/@noble/hashes/esm/cryptoNode.d.ts.map +1 -0
  544. package/node_modules/@noble/hashes/esm/cryptoNode.js +15 -0
  545. package/node_modules/@noble/hashes/esm/cryptoNode.js.map +1 -0
  546. package/node_modules/@noble/hashes/esm/eskdf.d.ts +47 -0
  547. package/node_modules/@noble/hashes/esm/eskdf.d.ts.map +1 -0
  548. package/node_modules/@noble/hashes/esm/eskdf.js +160 -0
  549. package/node_modules/@noble/hashes/esm/eskdf.js.map +1 -0
  550. package/node_modules/@noble/hashes/esm/hkdf.d.ts +36 -0
  551. package/node_modules/@noble/hashes/esm/hkdf.d.ts.map +1 -0
  552. package/node_modules/@noble/hashes/esm/hkdf.js +82 -0
  553. package/node_modules/@noble/hashes/esm/hkdf.js.map +1 -0
  554. package/node_modules/@noble/hashes/esm/hmac.d.ts +35 -0
  555. package/node_modules/@noble/hashes/esm/hmac.d.ts.map +1 -0
  556. package/node_modules/@noble/hashes/esm/hmac.js +86 -0
  557. package/node_modules/@noble/hashes/esm/hmac.js.map +1 -0
  558. package/node_modules/@noble/hashes/esm/index.d.ts +2 -0
  559. package/node_modules/@noble/hashes/esm/index.d.ts.map +1 -0
  560. package/node_modules/@noble/hashes/esm/index.js +33 -0
  561. package/node_modules/@noble/hashes/esm/index.js.map +1 -0
  562. package/node_modules/@noble/hashes/esm/legacy.d.ts +71 -0
  563. package/node_modules/@noble/hashes/esm/legacy.d.ts.map +1 -0
  564. package/node_modules/@noble/hashes/esm/legacy.js +281 -0
  565. package/node_modules/@noble/hashes/esm/legacy.js.map +1 -0
  566. package/node_modules/@noble/hashes/esm/package.json +10 -0
  567. package/node_modules/@noble/hashes/esm/pbkdf2.d.ts +23 -0
  568. package/node_modules/@noble/hashes/esm/pbkdf2.d.ts.map +1 -0
  569. package/node_modules/@noble/hashes/esm/pbkdf2.js +97 -0
  570. package/node_modules/@noble/hashes/esm/pbkdf2.js.map +1 -0
  571. package/node_modules/@noble/hashes/esm/ripemd160.d.ts +13 -0
  572. package/node_modules/@noble/hashes/esm/ripemd160.d.ts.map +1 -0
  573. package/node_modules/@noble/hashes/esm/ripemd160.js +13 -0
  574. package/node_modules/@noble/hashes/esm/ripemd160.js.map +1 -0
  575. package/node_modules/@noble/hashes/esm/scrypt.d.ts +34 -0
  576. package/node_modules/@noble/hashes/esm/scrypt.d.ts.map +1 -0
  577. package/node_modules/@noble/hashes/esm/scrypt.js +228 -0
  578. package/node_modules/@noble/hashes/esm/scrypt.js.map +1 -0
  579. package/node_modules/@noble/hashes/esm/sha1.d.ts +11 -0
  580. package/node_modules/@noble/hashes/esm/sha1.d.ts.map +1 -0
  581. package/node_modules/@noble/hashes/esm/sha1.js +11 -0
  582. package/node_modules/@noble/hashes/esm/sha1.js.map +1 -0
  583. package/node_modules/@noble/hashes/esm/sha2.d.ts +159 -0
  584. package/node_modules/@noble/hashes/esm/sha2.d.ts.map +1 -0
  585. package/node_modules/@noble/hashes/esm/sha2.js +375 -0
  586. package/node_modules/@noble/hashes/esm/sha2.js.map +1 -0
  587. package/node_modules/@noble/hashes/esm/sha256.d.ts +20 -0
  588. package/node_modules/@noble/hashes/esm/sha256.d.ts.map +1 -0
  589. package/node_modules/@noble/hashes/esm/sha256.js +20 -0
  590. package/node_modules/@noble/hashes/esm/sha256.js.map +1 -0
  591. package/node_modules/@noble/hashes/esm/sha3-addons.d.ts +142 -0
  592. package/node_modules/@noble/hashes/esm/sha3-addons.d.ts.map +1 -0
  593. package/node_modules/@noble/hashes/esm/sha3-addons.js +393 -0
  594. package/node_modules/@noble/hashes/esm/sha3-addons.js.map +1 -0
  595. package/node_modules/@noble/hashes/esm/sha3.d.ts +53 -0
  596. package/node_modules/@noble/hashes/esm/sha3.d.ts.map +1 -0
  597. package/node_modules/@noble/hashes/esm/sha3.js +234 -0
  598. package/node_modules/@noble/hashes/esm/sha3.js.map +1 -0
  599. package/node_modules/@noble/hashes/esm/sha512.d.ts +26 -0
  600. package/node_modules/@noble/hashes/esm/sha512.d.ts.map +1 -0
  601. package/node_modules/@noble/hashes/esm/sha512.js +26 -0
  602. package/node_modules/@noble/hashes/esm/sha512.js.map +1 -0
  603. package/node_modules/@noble/hashes/esm/utils.d.ts +161 -0
  604. package/node_modules/@noble/hashes/esm/utils.d.ts.map +1 -0
  605. package/node_modules/@noble/hashes/esm/utils.js +281 -0
  606. package/node_modules/@noble/hashes/esm/utils.js.map +1 -0
  607. package/node_modules/@noble/hashes/hkdf.d.ts +36 -0
  608. package/node_modules/@noble/hashes/hkdf.d.ts.map +1 -0
  609. package/node_modules/@noble/hashes/hkdf.js +88 -0
  610. package/node_modules/@noble/hashes/hkdf.js.map +1 -0
  611. package/node_modules/@noble/hashes/hmac.d.ts +35 -0
  612. package/node_modules/@noble/hashes/hmac.d.ts.map +1 -0
  613. package/node_modules/@noble/hashes/hmac.js +91 -0
  614. package/node_modules/@noble/hashes/hmac.js.map +1 -0
  615. package/node_modules/@noble/hashes/index.d.ts +1 -0
  616. package/node_modules/@noble/hashes/index.d.ts.map +1 -0
  617. package/node_modules/@noble/hashes/index.js +33 -0
  618. package/node_modules/@noble/hashes/index.js.map +1 -0
  619. package/node_modules/@noble/hashes/legacy.d.ts +71 -0
  620. package/node_modules/@noble/hashes/legacy.d.ts.map +1 -0
  621. package/node_modules/@noble/hashes/legacy.js +287 -0
  622. package/node_modules/@noble/hashes/legacy.js.map +1 -0
  623. package/node_modules/@noble/hashes/package.json +266 -0
  624. package/node_modules/@noble/hashes/pbkdf2.d.ts +23 -0
  625. package/node_modules/@noble/hashes/pbkdf2.d.ts.map +1 -0
  626. package/node_modules/@noble/hashes/pbkdf2.js +101 -0
  627. package/node_modules/@noble/hashes/pbkdf2.js.map +1 -0
  628. package/node_modules/@noble/hashes/ripemd160.d.ts +13 -0
  629. package/node_modules/@noble/hashes/ripemd160.d.ts.map +1 -0
  630. package/node_modules/@noble/hashes/ripemd160.js +16 -0
  631. package/node_modules/@noble/hashes/ripemd160.js.map +1 -0
  632. package/node_modules/@noble/hashes/scrypt.d.ts +34 -0
  633. package/node_modules/@noble/hashes/scrypt.d.ts.map +1 -0
  634. package/node_modules/@noble/hashes/scrypt.js +232 -0
  635. package/node_modules/@noble/hashes/scrypt.js.map +1 -0
  636. package/node_modules/@noble/hashes/sha1.d.ts +11 -0
  637. package/node_modules/@noble/hashes/sha1.d.ts.map +1 -0
  638. package/node_modules/@noble/hashes/sha1.js +14 -0
  639. package/node_modules/@noble/hashes/sha1.js.map +1 -0
  640. package/node_modules/@noble/hashes/sha2.d.ts +159 -0
  641. package/node_modules/@noble/hashes/sha2.d.ts.map +1 -0
  642. package/node_modules/@noble/hashes/sha2.js +384 -0
  643. package/node_modules/@noble/hashes/sha2.js.map +1 -0
  644. package/node_modules/@noble/hashes/sha256.d.ts +20 -0
  645. package/node_modules/@noble/hashes/sha256.d.ts.map +1 -0
  646. package/node_modules/@noble/hashes/sha256.js +23 -0
  647. package/node_modules/@noble/hashes/sha256.js.map +1 -0
  648. package/node_modules/@noble/hashes/sha3-addons.d.ts +142 -0
  649. package/node_modules/@noble/hashes/sha3-addons.d.ts.map +1 -0
  650. package/node_modules/@noble/hashes/sha3-addons.js +402 -0
  651. package/node_modules/@noble/hashes/sha3-addons.js.map +1 -0
  652. package/node_modules/@noble/hashes/sha3.d.ts +53 -0
  653. package/node_modules/@noble/hashes/sha3.d.ts.map +1 -0
  654. package/node_modules/@noble/hashes/sha3.js +239 -0
  655. package/node_modules/@noble/hashes/sha3.js.map +1 -0
  656. package/node_modules/@noble/hashes/sha512.d.ts +26 -0
  657. package/node_modules/@noble/hashes/sha512.d.ts.map +1 -0
  658. package/node_modules/@noble/hashes/sha512.js +29 -0
  659. package/node_modules/@noble/hashes/sha512.js.map +1 -0
  660. package/node_modules/@noble/hashes/src/_assert.ts +22 -0
  661. package/node_modules/@noble/hashes/src/_blake.ts +50 -0
  662. package/node_modules/@noble/hashes/src/_md.ts +176 -0
  663. package/node_modules/@noble/hashes/src/_u64.ts +91 -0
  664. package/node_modules/@noble/hashes/src/argon2.ts +497 -0
  665. package/node_modules/@noble/hashes/src/blake1.ts +534 -0
  666. package/node_modules/@noble/hashes/src/blake2.ts +486 -0
  667. package/node_modules/@noble/hashes/src/blake2b.ts +10 -0
  668. package/node_modules/@noble/hashes/src/blake2s.ts +20 -0
  669. package/node_modules/@noble/hashes/src/blake3.ts +272 -0
  670. package/node_modules/@noble/hashes/src/crypto.ts +9 -0
  671. package/node_modules/@noble/hashes/src/cryptoNode.ts +15 -0
  672. package/node_modules/@noble/hashes/src/eskdf.ts +187 -0
  673. package/node_modules/@noble/hashes/src/hkdf.ts +88 -0
  674. package/node_modules/@noble/hashes/src/hmac.ts +94 -0
  675. package/node_modules/@noble/hashes/src/index.ts +31 -0
  676. package/node_modules/@noble/hashes/src/legacy.ts +293 -0
  677. package/node_modules/@noble/hashes/src/pbkdf2.ts +122 -0
  678. package/node_modules/@noble/hashes/src/ripemd160.ts +12 -0
  679. package/node_modules/@noble/hashes/src/scrypt.ts +257 -0
  680. package/node_modules/@noble/hashes/src/sha1.ts +10 -0
  681. package/node_modules/@noble/hashes/src/sha2.ts +402 -0
  682. package/node_modules/@noble/hashes/src/sha256.ts +24 -0
  683. package/node_modules/@noble/hashes/src/sha3-addons.ts +499 -0
  684. package/node_modules/@noble/hashes/src/sha3.ts +258 -0
  685. package/node_modules/@noble/hashes/src/sha512.ts +34 -0
  686. package/node_modules/@noble/hashes/src/utils.ts +395 -0
  687. package/node_modules/@noble/hashes/utils.d.ts +161 -0
  688. package/node_modules/@noble/hashes/utils.d.ts.map +1 -0
  689. package/node_modules/@noble/hashes/utils.js +313 -0
  690. package/node_modules/@noble/hashes/utils.js.map +1 -0
  691. package/package.json +179 -8
  692. package/schemas/catalog.schema.json +357 -0
  693. package/src/align.ts +239 -0
  694. package/src/audio-init-parser.ts +189 -0
  695. package/src/audio-ring-buffer.ts +120 -0
  696. package/src/authored-timing.ts +63 -0
  697. package/src/block-policy.ts +903 -0
  698. package/src/carp-catalog.ts +1065 -0
  699. package/src/catalog-fec-params.ts +729 -0
  700. package/src/catalog-network-source.ts +74 -0
  701. package/src/catalog-validator.ts +34 -0
  702. package/src/cmaf-block-assembler.ts +1255 -0
  703. package/src/cmaf-group-batcher.ts +104 -0
  704. package/src/cmcd-producer.ts +329 -0
  705. package/src/codec-utils.ts +1984 -0
  706. package/src/conceal-timeline.ts +293 -0
  707. package/src/delivery-gap.ts +147 -0
  708. package/src/duplicate-ledger.ts +372 -0
  709. package/src/fec-codec.ts +61 -0
  710. package/src/fec-manager.ts +4298 -0
  711. package/src/fec-starvation-detector.ts +128 -0
  712. package/src/fec-state.ts +219 -0
  713. package/src/fec-worker-setup.ts +283 -0
  714. package/src/fmp4-completion.ts +47 -0
  715. package/src/fmp4-reader.ts +112 -0
  716. package/src/index.ts +590 -21
  717. package/src/iso-block-locator.ts +329 -0
  718. package/src/iso-bmff-timing.ts +813 -0
  719. package/src/loc.ts +128 -154
  720. package/src/manifest-auth-plan.ts +107 -0
  721. package/src/media-router.ts +841 -0
  722. package/src/mfu-reassembler.ts +3480 -155
  723. package/src/mfu-reassembly-policy.ts +134 -0
  724. package/src/mmtp-container-parser.ts +2380 -0
  725. package/src/mmtp-decode-pipeline.ts +406 -0
  726. package/src/mmtp-router.ts +4860 -0
  727. package/src/mmtp-to-cmaf.ts +977 -0
  728. package/src/multicast-auth-catalog.ts +340 -0
  729. package/src/multicast-input.ts +793 -0
  730. package/src/multicast-manager.ts +2783 -0
  731. package/src/multicast-transport.ts +1058 -0
  732. package/src/multicast-unwrap.ts +132 -0
  733. package/src/no-modules.ts +21 -0
  734. package/src/phase14-catalog-override.ts +336 -0
  735. package/src/repair-fetch.ts +772 -0
  736. package/src/repair-layers.ts +533 -0
  737. package/src/sample-combiner.ts +938 -0
  738. package/src/signaling.ts +78 -0
  739. package/src/source-auth.ts +1 -0
  740. package/src/switching-set-alignment.ts +109 -0
  741. package/src/timestamp-codec.ts +265 -0
  742. package/src/track-pipeline-setup.ts +205 -0
  743. package/src/track-pipeline.ts +332 -0
  744. package/src/track-session.ts +1010 -0
  745. package/src/transport-pool.ts +128 -0
  746. package/src/wasm-mfu-reassembler.ts +405 -0
  747. package/src/wasm-mmtp-container-parser.ts +23 -0
  748. package/test-vectors/align.json +199 -0
  749. package/test-vectors/catalog/README.md +106 -0
  750. package/test-vectors/catalog/negative/archive-origin-with-path.json +33 -0
  751. package/test-vectors/catalog/negative/archive-unknown-field.json +34 -0
  752. package/test-vectors/catalog/negative/fec-block-profile-missing.json +51 -0
  753. package/test-vectors/catalog/negative/fec-block-profile-unknown.json +52 -0
  754. package/test-vectors/catalog/negative/fec-enhancement-repair-removed.json +28 -0
  755. package/test-vectors/catalog/negative/fec-repair-layer-geometry.json +33 -0
  756. package/test-vectors/catalog/negative/fec-repair-layer-missing-symbols.json +31 -0
  757. package/test-vectors/catalog/negative/fec-repair-multiple-depends.json +32 -0
  758. package/test-vectors/catalog/negative/fec-repair-overlay-with-layer.json +34 -0
  759. package/test-vectors/catalog/negative/fec-repair-priority-out-of-band.json +24 -0
  760. package/test-vectors/catalog/negative/fec-repair-source-symbols-without-scope.json +33 -0
  761. package/test-vectors/catalog/negative/legacy-selection-params.json +15 -0
  762. package/test-vectors/catalog/negative/media-track-repair-layer.json +16 -0
  763. package/test-vectors/catalog/negative/missing-mmtp-fields.json +12 -0
  764. package/test-vectors/catalog/negative/multicast-auth-padded-key.json +37 -0
  765. package/test-vectors/catalog/negative/multicast-auth-reused-track-format.json +53 -0
  766. package/test-vectors/catalog/negative/multicast-auth-trailing-pad-bits.json +37 -0
  767. package/test-vectors/catalog/negative/multicast-endpoint-missing-protocol-and-source.json +24 -0
  768. package/test-vectors/catalog/negative/multicast-network-source-empty.json +44 -0
  769. package/test-vectors/catalog/negative/multicast-packet-id-signaling.json +26 -0
  770. package/test-vectors/catalog/negative/network-source-object.json +25 -0
  771. package/test-vectors/catalog/negative/raptorq-source-symbols-over-max.json +24 -0
  772. package/test-vectors/catalog/negative/raptorq-unaligned-symbol.json +27 -0
  773. package/test-vectors/catalog/negative/repair-track-legacy-shape.json +19 -0
  774. package/test-vectors/catalog/negative/track-role-empty.json +16 -0
  775. package/test-vectors/catalog/negative/track-role-non-string.json +16 -0
  776. package/test-vectors/catalog/positive/archive-origin.json +34 -0
  777. package/test-vectors/catalog/positive/fec-iso-ssbg1.json +52 -0
  778. package/test-vectors/catalog/positive/fec-layered-repair.json +106 -0
  779. package/test-vectors/catalog/positive/fec-multicast.json +52 -0
  780. package/test-vectors/catalog/positive/flat-av.json +30 -0
  781. package/test-vectors/catalog/positive/multicast-auth-rotation.json +55 -0
  782. package/test-vectors/catalog/positive/multicast-native-ssm-no-network-source.json +43 -0
  783. package/test-vectors/catalog/positive/ticks-and-mixed-timescales.json +39 -0
  784. package/test-vectors/catalog/positive/track-role.json +49 -0
  785. package/test-vectors/catalog/releases/moqcast-native-v16-v1/catalog.json +65 -0
  786. package/test-vectors/catalog/releases/moqcast-native-v16-v1.archive.sha256 +1 -0
  787. package/test-vectors/catalog-multicast-auth-v1.json +26 -0
  788. package/test-vectors/catalog-validation.json +732 -0
  789. package/test-vectors/catalog-validator-public-api.mjs +25 -0
  790. package/test-vectors/generate-source-auth-fixture.mjs +114 -0
  791. package/test-vectors/hevc-x265-repeat-headers-v1.json +40 -0
  792. package/test-vectors/source-auth-v1.json +61 -0
  793. package/test-vectors/source-contiguity-v1.json +131 -0
  794. package/test-vectors/subsample-placement-v1.json +230 -0
  795. package/dist/mmtp.d.ts +0 -73
  796. package/dist/mmtp.d.ts.map +0 -1
  797. package/dist/mmtp.js +0 -210
  798. package/dist/mmtp.js.map +0 -1
  799. package/src/mmtp.ts +0 -277
@@ -0,0 +1,977 @@
1
+ /**
2
+ * MMTP → CMAF converter per draft-ramadan-moq-mmt §5.3.
3
+ *
4
+ * Converts reassembled MFU frames (raw codec samples from MMTP) into
5
+ * fMP4 segments (moof+mdat) suitable for MSE SourceBuffer.appendBuffer().
6
+ *
7
+ * MPU metadata (fragment_type=0) packets from FFmpeg are complete
8
+ * ftyp+moov init segments and can be used directly as MSE init data.
9
+ *
10
+ * MFU data (fragment_type=2) contains raw AVCC samples that must be
11
+ * wrapped in moof+mdat boxes for MSE consumption.
12
+ *
13
+ * ISO 14496-12 (ISOBMFF) box construction is inline — no dependencies.
14
+ */
15
+
16
+ // ── ISOBMFF box helpers ──
17
+
18
+ function box(type: string, ...children: Uint8Array[]): Uint8Array {
19
+ let size = 8
20
+ for (const c of children) size += c.length
21
+ const buf = new Uint8Array(size)
22
+ new DataView(buf.buffer).setUint32(0, size)
23
+ buf[4] = type.charCodeAt(0)
24
+ buf[5] = type.charCodeAt(1)
25
+ buf[6] = type.charCodeAt(2)
26
+ buf[7] = type.charCodeAt(3)
27
+ let pos = 8
28
+ for (const c of children) {
29
+ buf.set(c, pos)
30
+ pos += c.length
31
+ }
32
+ return buf
33
+ }
34
+
35
+ function fullBox(type: string, version: number, flags: number, ...children: Uint8Array[]): Uint8Array {
36
+ let size = 12
37
+ for (const c of children) size += c.length
38
+ const buf = new Uint8Array(size)
39
+ const dv = new DataView(buf.buffer)
40
+ dv.setUint32(0, size)
41
+ buf[4] = type.charCodeAt(0)
42
+ buf[5] = type.charCodeAt(1)
43
+ buf[6] = type.charCodeAt(2)
44
+ buf[7] = type.charCodeAt(3)
45
+ dv.setUint32(8, (version << 24) | (flags & 0xffffff))
46
+ let pos = 12
47
+ for (const c of children) {
48
+ buf.set(c, pos)
49
+ pos += c.length
50
+ }
51
+ return buf
52
+ }
53
+
54
+ function u32(v: number): Uint8Array {
55
+ const b = new Uint8Array(4)
56
+ new DataView(b.buffer).setUint32(0, v)
57
+ return b
58
+ }
59
+
60
+ // ── Sample flags per ISO 14496-12 §8.8.3.1 ──
61
+ const KEYFRAME_FLAGS = 0x02000000
62
+ const DELTA_FLAGS = 0x01010000
63
+
64
+ // ── Track geometry field ranges per ISO 14496-12 ──
65
+ // tkhd/trex/tfhd track_ID and the mdhd/mvhd timescales are all unsigned 32-bit
66
+ // fields, written below with DataView.setUint32. That call takes the value
67
+ // modulo 2^32 without complaint, so an out-of-range configuration does not
68
+ // fail — it silently emits different geometry than the caller asked for
69
+ // (trackId 2^32 becomes track 0, which no fragment can ever reference).
70
+ const UINT32_MAX = 0xffffffff
71
+ // mvhd next_track_ID is emitted as track_ID + 1 by both buildVideoInitSegment
72
+ // and buildAudioInitSegment (ISO 14496-12 §8.2.2.3, "a non-zero integer"). At
73
+ // track_ID = UINT32_MAX that sum wraps to 0, which is both invalid and
74
+ // indistinguishable from an unset field, so the largest usable track_ID is one
75
+ // below the field maximum. (Cited by symbol, not line: this repo's docs gate
76
+ // exists because line anchors rot silently — see rustfmt.yml's citation check.)
77
+ const MAX_TRACK_ID = UINT32_MAX - 1
78
+ const INT32_MIN = -0x80000000
79
+ const INT32_MAX = 0x7fffffff
80
+
81
+ /**
82
+ * Fail closed on a track_ID the fMP4 writers below cannot serialize faithfully.
83
+ *
84
+ * Called from both low-level encoders (encodeDataSegment,
85
+ * encodeMultiSampleSegment) so every fragment path is covered by construction
86
+ * rather than by enumerating callers. The class wrappers and init builders call
87
+ * it earlier as well — partly for a clearer label, partly because the encoders
88
+ * receive an already-incremented sequence number, so their throw would gap the
89
+ * sequence on a call that emitted nothing.
90
+ */
91
+ function assertTrackId(trackId: number, label: string): void {
92
+ if (!Number.isInteger(trackId) || trackId <= 0 || trackId > MAX_TRACK_ID) {
93
+ throw new RangeError(`${label} must be an integer in 1..${MAX_TRACK_ID}, got ${trackId}`)
94
+ }
95
+ }
96
+
97
+ /** Fail closed on a timescale the mdhd/mvhd uint32 fields cannot hold. */
98
+ function assertTimescale(timescale: number, label: string): void {
99
+ if (!Number.isInteger(timescale) || timescale <= 0 || timescale > UINT32_MAX) {
100
+ throw new RangeError(`${label} must be an integer in 1..${UINT32_MAX}, got ${timescale}`)
101
+ }
102
+ }
103
+
104
+ /** Fail closed on a signed trun sample_composition_time_offset. */
105
+ function assertCompositionTimeOffsets(
106
+ samples: Array<{ compositionTimeOffset?: number }>,
107
+ ): void {
108
+ for (let i = 0; i < samples.length; i++) {
109
+ const offset = samples[i]!.compositionTimeOffset
110
+ if (offset !== undefined &&
111
+ (!Number.isInteger(offset) || offset < INT32_MIN || offset > INT32_MAX)) {
112
+ throw new RangeError(
113
+ `sample ${i} compositionTimeOffset must be an integer in ${INT32_MIN}..${INT32_MAX}, got ${offset}`,
114
+ )
115
+ }
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Wrap multiple samples in a single moof+mdat fMP4 segment.
121
+ *
122
+ * Builds a trun with N sample entries (duration + size + flags each).
123
+ * Used by CmafBlockAssembler to emit one segment per FEC source block.
124
+ *
125
+ * @param samples - Array of samples with data, duration (timescale units), keyframe flag,
126
+ * and an optional signed composition-time offset (same timescale units)
127
+ * @param baseDecodeTime - Decode time of the first sample in timescale units
128
+ * @param sequence - moof sequence number
129
+ * @param trackId - ISO track ID (default 1)
130
+ * @returns moof+mdat bytes ready for SourceBuffer.appendBuffer()
131
+ */
132
+ export function encodeMultiSampleSegment(
133
+ samples: Array<{
134
+ data: Uint8Array
135
+ duration: number
136
+ keyframe: boolean
137
+ compositionTimeOffset?: number
138
+ }>,
139
+ baseDecodeTime: number,
140
+ sequence: number,
141
+ trackId = 1,
142
+ ): Uint8Array {
143
+ if (samples.length === 0) return new Uint8Array(0)
144
+ assertTrackId(trackId, 'trackId')
145
+ assertCompositionTimeOffsets(samples)
146
+
147
+ const mfhd = fullBox('mfhd', 0, 0, u32(sequence))
148
+ const tfhd = fullBox('tfhd', 0, 0x020000, u32(trackId))
149
+
150
+ // tfdt version=1 for 64-bit baseMediaDecodeTime
151
+ const tfdtBody = new Uint8Array(8)
152
+ const tfdtView = new DataView(tfdtBody.buffer)
153
+ tfdtView.setUint32(0, Math.floor(baseDecodeTime / 0x100000000))
154
+ tfdtView.setUint32(4, baseDecodeTime >>> 0)
155
+ const tfdt = fullBox('tfdt', 1, 0, tfdtBody)
156
+
157
+ // A composition-time offset is signed only in trun version 1. When one is
158
+ // present, every sample gets the field; omitted offsets are encoded as zero.
159
+ const hasCompositionTimeOffset = samples.some(sample => sample.compositionTimeOffset !== undefined)
160
+ const trunVersion = hasCompositionTimeOffset ? 1 : 0
161
+ const trunFlags = 0x000701 | (hasCompositionTimeOffset ? 0x000800 : 0)
162
+ // 4 bytes sample_count + 4 bytes data_offset + N * (4+4+4 [+4]) per sample
163
+ const sampleCount = samples.length
164
+ const sampleEntrySize = hasCompositionTimeOffset ? 16 : 12
165
+ const trunBody = new Uint8Array(8 + sampleCount * sampleEntrySize)
166
+ const trunView = new DataView(trunBody.buffer)
167
+ trunView.setUint32(0, sampleCount)
168
+ trunView.setUint32(4, 0) // dataOffset placeholder
169
+ for (let i = 0; i < sampleCount; i++) {
170
+ const s = samples[i]!
171
+ const off = 8 + i * sampleEntrySize
172
+ trunView.setUint32(off, s.duration >>> 0)
173
+ trunView.setUint32(off + 4, s.data.length)
174
+ trunView.setUint32(off + 8, s.keyframe ? KEYFRAME_FLAGS : DELTA_FLAGS)
175
+ if (hasCompositionTimeOffset) {
176
+ trunView.setInt32(off + 12, s.compositionTimeOffset ?? 0)
177
+ }
178
+ }
179
+ const trun = fullBox('trun', trunVersion, trunFlags, trunBody)
180
+
181
+ const traf = box('traf', tfhd, tfdt, trun)
182
+ const moof = box('moof', mfhd, traf)
183
+
184
+ // Concatenate all sample data into mdat
185
+ let mdatSize = 0
186
+ for (const s of samples) mdatSize += s.data.length
187
+ const mdatPayload = new Uint8Array(mdatSize)
188
+ let pos = 0
189
+ for (const s of samples) {
190
+ mdatPayload.set(s.data, pos)
191
+ pos += s.data.length
192
+ }
193
+ const mdat = box('mdat', mdatPayload)
194
+
195
+ // Fix trun.dataOffset: moof size + 8 (mdat box header)
196
+ const dataOffsetPos = 8 + mfhd.length + 8 + tfhd.length + tfdt.length + 12 + 4
197
+ new DataView(moof.buffer).setUint32(dataOffsetPos, moof.length + 8)
198
+
199
+ const result = new Uint8Array(moof.length + mdat.length)
200
+ result.set(moof, 0)
201
+ result.set(mdat, moof.length)
202
+ return result
203
+ }
204
+
205
+ // ── Silence generator ──
206
+
207
+ /**
208
+ * Generate a minimal silent audio frame for FEC fill.
209
+ *
210
+ * Supports AAC (mp4a) and Opus codecs. Returns raw frame data (no ADTS/OBU
211
+ * header) suitable for fMP4/CMAF wrapping.
212
+ *
213
+ * @param codec - Audio codec string (e.g. 'mp4a.40.2', 'opus')
214
+ * @param sampleRate - Audio sample rate (e.g. 48000)
215
+ * @param channels - Channel count (e.g. 1 or 2)
216
+ */
217
+ export function generateSilenceFrame(codec: string, sampleRate: number, channels: number): Uint8Array {
218
+ if (codec.startsWith('opus') || codec.startsWith('Opus')) {
219
+ return generateSilenceOpus(channels)
220
+ }
221
+ return generateSilenceAAC(sampleRate, channels)
222
+ }
223
+
224
+ /** Minimal silent AAC-LC access unit (raw, no ADTS). */
225
+ function generateSilenceAAC(sampleRate: number, channels: number): Uint8Array {
226
+ if (channels >= 2) {
227
+ // CPE (channel pair element) + END
228
+ return new Uint8Array([
229
+ 0x21, 0x00, 0x49, 0x90, 0x02, 0x19, 0x00, 0x23, 0x80,
230
+ ])
231
+ }
232
+ // SCE (single channel element) + END
233
+ return new Uint8Array([
234
+ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
235
+ ])
236
+ }
237
+
238
+ /** Minimal silent Opus frame.
239
+ * RFC 6716 §3.1: a 1-byte frame with code 0 encodes silence for SILK/CELT. */
240
+ function generateSilenceOpus(channels: number): Uint8Array {
241
+ // Opus TOC byte: config=0 (SILK NB 10ms), s=0 (mono/stereo from channel mapping), c=0 (1 frame)
242
+ // Frame data: single zero byte → silence
243
+ // For stereo, channel mapping in fMP4 init handles routing; the Opus frame itself is the same.
244
+ return new Uint8Array([0xF8, 0xFF, 0xFE])
245
+ }
246
+
247
+ export function normalizeAacSampleForCmaf(data: Uint8Array): Uint8Array {
248
+ if (data.length < 7 || data[0] !== 0xff || (data[1]! & 0xf6) !== 0xf0) {
249
+ return data
250
+ }
251
+ const headerLength = (data[1]! & 0x01) ? 7 : 9
252
+ if (data.length <= headerLength) return data
253
+ const frameLength = ((data[3]! & 0x03) << 11) | (data[4]! << 3) | ((data[5]! & 0xe0) >>> 5)
254
+ if (frameLength !== data.length || frameLength <= headerLength) return data
255
+ return data.subarray(headerLength)
256
+ }
257
+
258
+ /**
259
+ * Wrap a single raw codec sample in a moof+mdat fMP4 segment.
260
+ *
261
+ * @param data - Raw sample bytes (AVCC H.264 or raw AAC)
262
+ * @param timestamp - Decode time in timescale units
263
+ * @param duration - Sample duration in timescale units
264
+ * @param keyframe - true for IDR/sync sample
265
+ * @param sequence - moof sequence number (monotonically incrementing)
266
+ * @param trackId - ISO track ID (default 1)
267
+ * @returns moof+mdat bytes ready for SourceBuffer.appendBuffer()
268
+ */
269
+ export function encodeDataSegment(
270
+ data: Uint8Array,
271
+ timestamp: number,
272
+ duration: number,
273
+ keyframe: boolean,
274
+ sequence: number,
275
+ trackId = 1,
276
+ compositionTimeOffset?: number,
277
+ ): Uint8Array {
278
+ assertTrackId(trackId, 'trackId')
279
+ assertCompositionTimeOffsets([{ compositionTimeOffset }])
280
+ if (compositionTimeOffset !== undefined) {
281
+ return encodeMultiSampleSegment(
282
+ [{ data, duration, keyframe, compositionTimeOffset }],
283
+ timestamp,
284
+ sequence,
285
+ trackId,
286
+ )
287
+ }
288
+ const sampleFlags = keyframe ? KEYFRAME_FLAGS : DELTA_FLAGS
289
+
290
+ const mfhd = fullBox('mfhd', 0, 0, u32(sequence))
291
+ const tfhd = fullBox('tfhd', 0, 0x020000, u32(trackId))
292
+
293
+ // tfdt version=1 for 64-bit baseMediaDecodeTime
294
+ const tfdtBody = new Uint8Array(8)
295
+ const tfdtView = new DataView(tfdtBody.buffer)
296
+ tfdtView.setUint32(0, Math.floor(timestamp / 0x100000000))
297
+ tfdtView.setUint32(4, timestamp >>> 0)
298
+ const tfdt = fullBox('tfdt', 1, 0, tfdtBody)
299
+
300
+ // trun: flags=0x000701 (data-offset + duration + size + flags)
301
+ const trunBody = new Uint8Array(20)
302
+ const trunView = new DataView(trunBody.buffer)
303
+ trunView.setUint32(0, 1) // sample_count
304
+ trunView.setUint32(4, 0) // dataOffset placeholder
305
+ trunView.setUint32(8, duration >>> 0)
306
+ trunView.setUint32(12, data.length)
307
+ trunView.setUint32(16, sampleFlags)
308
+ const trun = fullBox('trun', 0, 0x000701, trunBody)
309
+
310
+ const traf = box('traf', tfhd, tfdt, trun)
311
+ const moof = box('moof', mfhd, traf)
312
+ const mdat = box('mdat', data)
313
+
314
+ // Fix trun.dataOffset: moof size + 8 (mdat box header)
315
+ const dataOffsetPos = 8 + mfhd.length + 8 + tfhd.length + tfdt.length + 12 + 4
316
+ new DataView(moof.buffer).setUint32(dataOffsetPos, moof.length + 8)
317
+
318
+ const result = new Uint8Array(moof.length + mdat.length)
319
+ result.set(moof, 0)
320
+ result.set(mdat, moof.length)
321
+ return result
322
+ }
323
+
324
+ /**
325
+ * Build an ftyp+moov init segment for H.264 video MSE from an avcC box.
326
+ *
327
+ * @param avcC - Raw avcC box payload (SPS/PPS configuration)
328
+ * @param width - Video width in pixels
329
+ * @param height - Video height in pixels
330
+ * @param timescale - Timescale (default 1_000_000 = microseconds)
331
+ * @param trackId - Track ID (default 1)
332
+ */
333
+ export function buildVideoInitSegment(
334
+ avcC: Uint8Array,
335
+ width: number,
336
+ height: number,
337
+ timescale = 1_000_000,
338
+ trackId = 1,
339
+ ): Uint8Array {
340
+ return buildVisualInitSegment('avc1', 'avcC', avcC, width, height, timescale, trackId)
341
+ }
342
+
343
+ /**
344
+ * Build an ftyp+moov init segment for H.265/HEVC video MSE.
345
+ *
346
+ * The sample entry is `hev1` or `hvc1` (ISO/IEC 14496-15 §8.4.1.1) carrying an
347
+ * `hvcC` HEVCDecoderConfigurationRecord (§8.3.3.1). Choose the entry from the
348
+ * catalog codec string's first element, never by inspecting the bitstream:
349
+ * `hev1` permits VPS/SPS/PPS to stay in-band in the samples (cast's
350
+ * `repeat-headers=1` stream), `hvc1` requires every parameter set in the
351
+ * `hvcC` and none in the samples.
352
+ *
353
+ * @param sampleEntry - `hev1` or `hvc1`
354
+ * @param hvcC - Raw hvcC record payload (e.g. from `generateHvcCFromParameterSets`)
355
+ * @param width - Video width in pixels
356
+ * @param height - Video height in pixels
357
+ * @param timescale - Media timescale
358
+ * @param trackId - ISO track ID
359
+ */
360
+ export function buildHevcVideoInitSegment(
361
+ sampleEntry: 'hev1' | 'hvc1',
362
+ hvcC: Uint8Array,
363
+ width: number,
364
+ height: number,
365
+ timescale: number,
366
+ trackId: number,
367
+ ): Uint8Array {
368
+ if (sampleEntry !== 'hev1' && sampleEntry !== 'hvc1') {
369
+ throw new Error(`HEVC init segment requires an hev1 or hvc1 sample entry, got ${String(sampleEntry)}`)
370
+ }
371
+ return buildVisualInitSegment(sampleEntry, 'hvcC', hvcC, width, height, timescale, trackId)
372
+ }
373
+
374
+ /**
375
+ * ftyp+moov for one video track whose VisualSampleEntry (ISO/IEC 14496-12
376
+ * §12.1.3) carries a single codec configuration box. AVC (`avc1`/`avcC`) and
377
+ * HEVC (`hev1`|`hvc1`/`hvcC`) share this layout byte for byte.
378
+ */
379
+ function buildVisualInitSegment(
380
+ sampleEntryType: 'avc1' | 'hev1' | 'hvc1',
381
+ configBoxType: 'avcC' | 'hvcC',
382
+ configRecord: Uint8Array,
383
+ width: number,
384
+ height: number,
385
+ timescale: number,
386
+ trackId: number,
387
+ ): Uint8Array {
388
+ // Validated here as well as in setVideoTrackParams: the builders are exported
389
+ // from the package index, so a direct caller reaches the same uint32 tkhd /
390
+ // trex / mdhd / mvhd fields without passing through the class.
391
+ assertTrackId(trackId, 'video trackId')
392
+ assertTimescale(timescale, 'video timescale')
393
+ const ftyp = box('ftyp', new Uint8Array([
394
+ 0x69, 0x73, 0x6f, 0x6d, 0, 0, 2, 0,
395
+ 0x69, 0x73, 0x6f, 0x6d,
396
+ 0x69, 0x73, 0x6f, 0x36,
397
+ 0x6d, 0x70, 0x34, 0x31,
398
+ ]))
399
+
400
+ const configBox = box(configBoxType, configRecord)
401
+ const sampleEntryBody = new Uint8Array(78 + configBox.length)
402
+ const sampleEntryView = new DataView(sampleEntryBody.buffer)
403
+ sampleEntryView.setUint16(6, 1)
404
+ sampleEntryView.setUint16(24, width)
405
+ sampleEntryView.setUint16(26, height)
406
+ sampleEntryView.setUint32(28, 0x00480000)
407
+ sampleEntryView.setUint32(32, 0x00480000)
408
+ sampleEntryView.setUint16(40, 1)
409
+ sampleEntryView.setUint16(74, 0x0018)
410
+ sampleEntryView.setInt16(76, -1)
411
+ sampleEntryBody.set(configBox, 78)
412
+ const visualSampleEntry = box(sampleEntryType, sampleEntryBody)
413
+
414
+ const stsd = fullBox('stsd', 0, 0, u32(1), visualSampleEntry)
415
+ const stbl = box('stbl', stsd,
416
+ fullBox('stts', 0, 0, u32(0)),
417
+ fullBox('stsc', 0, 0, u32(0)),
418
+ fullBox('stsz', 0, 0, u32(0), u32(0)),
419
+ fullBox('stco', 0, 0, u32(0)),
420
+ )
421
+ const dinf = box('dinf', fullBox('dref', 0, 0, u32(1), fullBox('url ', 0, 1)))
422
+ // ISO/IEC 14496-12 §12.1.2: VideoMediaHeaderBox is a FullBox (flags = 1)
423
+ // followed by graphicsmode (uint16) and opcolor (uint16[3]), all zero for
424
+ // copy mode. WebKit's MSE parser rejects the whole init segment when those
425
+ // 8 bytes are missing (SourceBuffer error on iPhone Safari); Chromium
426
+ // tolerates it, which is how the short box went unnoticed.
427
+ const minf = box('minf', fullBox('vmhd', 0, 1, new Uint8Array(8)), dinf, stbl)
428
+ const hdlr = fullBox('hdlr', 0, 0, new Uint8Array([
429
+ 0, 0, 0, 0, 0x76, 0x69, 0x64, 0x65,
430
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
431
+ 0x56, 0x69, 0x64, 0x65, 0x6f, 0,
432
+ ]))
433
+ const mdhdBody = new Uint8Array(20)
434
+ new DataView(mdhdBody.buffer).setUint32(8, timescale)
435
+ const mdhd = fullBox('mdhd', 0, 0, mdhdBody)
436
+ const mdia = box('mdia', mdhd, hdlr, minf)
437
+
438
+ const tkhdBody = new Uint8Array(80)
439
+ const tkhdView = new DataView(tkhdBody.buffer)
440
+ tkhdView.setUint32(8, trackId)
441
+ tkhdView.setUint32(36, 0x00010000)
442
+ tkhdView.setUint32(52, 0x00010000)
443
+ tkhdView.setUint32(64, 0x40000000)
444
+ tkhdView.setUint32(72, width << 16)
445
+ tkhdView.setUint32(76, height << 16)
446
+ const tkhd = fullBox('tkhd', 0, 3, tkhdBody)
447
+ const trak = box('trak', tkhd, mdia)
448
+
449
+ const mvhdBody = new Uint8Array(96)
450
+ const mvhdView = new DataView(mvhdBody.buffer)
451
+ mvhdView.setUint32(8, timescale)
452
+ mvhdView.setUint32(16, 0x00010000)
453
+ mvhdView.setUint16(20, 0x0100)
454
+ mvhdView.setUint32(32, 0x00010000)
455
+ mvhdView.setUint32(48, 0x00010000)
456
+ mvhdView.setUint32(60, 0x40000000)
457
+ mvhdView.setUint32(92, trackId + 1)
458
+ const mvhd = fullBox('mvhd', 0, 0, mvhdBody)
459
+
460
+ const trexBody = new Uint8Array(20)
461
+ new DataView(trexBody.buffer).setUint32(0, trackId)
462
+ new DataView(trexBody.buffer).setUint32(4, 1)
463
+ const mvex = box('mvex', fullBox('trex', 0, 0, trexBody))
464
+
465
+ const moov = box('moov', mvhd, trak, mvex)
466
+ const result = new Uint8Array(ftyp.length + moov.length)
467
+ result.set(ftyp, 0)
468
+ result.set(moov, ftyp.length)
469
+ return result
470
+ }
471
+
472
+ /**
473
+ * Build ftyp+moov init segment for AAC audio MSE.
474
+ */
475
+ export function buildAudioInitSegment(
476
+ sampleRate: number,
477
+ channels: number,
478
+ asc?: Uint8Array,
479
+ timescale?: number,
480
+ trackId = 1,
481
+ ): Uint8Array {
482
+ // Validated here as well as in setAudioTimescale, for the same reason the
483
+ // video builder is: this function is exported from the package index, so a
484
+ // direct caller reaches the same uint32 tkhd / trex / mdhd / mvhd fields
485
+ // without passing through the class.
486
+ assertTrackId(trackId, 'audio trackId')
487
+ const ts = timescale ?? sampleRate
488
+ assertTimescale(ts, 'audio timescale')
489
+
490
+ if (!asc) {
491
+ const freqTable = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350]
492
+ const fi = freqTable.indexOf(sampleRate)
493
+ const freqIdx = fi >= 0 ? fi : 0x0f
494
+ if (freqIdx <= 0x0e) {
495
+ const v = (2 << 11) | (freqIdx << 7) | (channels << 3)
496
+ asc = new Uint8Array([(v >> 8) & 0xff, v & 0xff])
497
+ } else {
498
+ asc = new Uint8Array([
499
+ (2 << 3) | 0x07,
500
+ (0x08 | ((sampleRate >> 20) & 0x07)) & 0xff,
501
+ (sampleRate >> 12) & 0xff,
502
+ (sampleRate >> 4) & 0xff,
503
+ (((sampleRate & 0x0f) << 4) | (channels << 0)) & 0xff,
504
+ ])
505
+ }
506
+ }
507
+
508
+ // esds: ES_Descriptor → DecoderConfigDescriptor → AudioSpecificConfig
509
+ const dsi = new Uint8Array(2 + asc.length)
510
+ dsi[0] = 0x05; dsi[1] = asc.length; dsi.set(asc, 2)
511
+ const dcdBody = new Uint8Array(13 + dsi.length)
512
+ dcdBody[0] = 0x40; dcdBody[1] = 0x15; dcdBody.set(dsi, 13)
513
+ const dcd = new Uint8Array(2 + dcdBody.length)
514
+ dcd[0] = 0x04; dcd[1] = dcdBody.length; dcd.set(dcdBody, 2)
515
+ const esBody = new Uint8Array(3 + dcd.length)
516
+ esBody[0] = 0; esBody[1] = 0x01; esBody[2] = 0; esBody.set(dcd, 3)
517
+ const es = new Uint8Array(2 + esBody.length)
518
+ es[0] = 0x03; es[1] = esBody.length; es.set(esBody, 2)
519
+ const esdsBox = fullBox('esds', 0, 0, es)
520
+
521
+ const mp4aBody = new Uint8Array(28 + esdsBox.length)
522
+ const mp4aView = new DataView(mp4aBody.buffer)
523
+ mp4aView.setUint16(6, 1)
524
+ mp4aView.setUint16(16, channels)
525
+ mp4aView.setUint16(18, 16)
526
+ mp4aView.setUint32(24, sampleRate << 16)
527
+ mp4aBody.set(esdsBox, 28)
528
+ const mp4a = box('mp4a', mp4aBody)
529
+
530
+ const stsd = fullBox('stsd', 0, 0, u32(1), mp4a)
531
+ const stbl = box('stbl', stsd,
532
+ fullBox('stts', 0, 0, u32(0)),
533
+ fullBox('stsc', 0, 0, u32(0)),
534
+ fullBox('stsz', 0, 0, u32(0), u32(0)),
535
+ fullBox('stco', 0, 0, u32(0)),
536
+ )
537
+ const dinf = box('dinf', fullBox('dref', 0, 0, u32(1), fullBox('url ', 0, 1)))
538
+ const minf = box('minf', fullBox('smhd', 0, 0, new Uint8Array(4)), dinf, stbl)
539
+ const hdlr = fullBox('hdlr', 0, 0, new Uint8Array([
540
+ 0, 0, 0, 0, 0x73, 0x6f, 0x75, 0x6e,
541
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
542
+ 0x53, 0x6f, 0x75, 0x6e, 0x64, 0,
543
+ ]))
544
+ const mdhdBody = new Uint8Array(20)
545
+ new DataView(mdhdBody.buffer).setUint32(8, ts)
546
+ const mdhd = fullBox('mdhd', 0, 0, mdhdBody)
547
+ const mdia = box('mdia', mdhd, hdlr, minf)
548
+
549
+ const tkhdBody = new Uint8Array(80)
550
+ const tkhdView = new DataView(tkhdBody.buffer)
551
+ tkhdView.setUint32(8, trackId)
552
+ tkhdView.setUint32(36, 0x00010000)
553
+ tkhdView.setUint32(52, 0x00010000)
554
+ tkhdView.setUint32(64, 0x40000000)
555
+ const tkhd = fullBox('tkhd', 0, 3, tkhdBody)
556
+ const trak = box('trak', tkhd, mdia)
557
+
558
+ const mvhdBody = new Uint8Array(96)
559
+ const mvhdView = new DataView(mvhdBody.buffer)
560
+ mvhdView.setUint32(8, ts)
561
+ mvhdView.setUint32(16, 0x00010000)
562
+ mvhdView.setUint16(20, 0x0100)
563
+ mvhdView.setUint32(32, 0x00010000)
564
+ mvhdView.setUint32(48, 0x00010000)
565
+ mvhdView.setUint32(60, 0x40000000)
566
+ mvhdView.setUint32(92, trackId + 1)
567
+ const mvhd = fullBox('mvhd', 0, 0, mvhdBody)
568
+
569
+ const trexBody = new Uint8Array(20)
570
+ new DataView(trexBody.buffer).setUint32(0, trackId)
571
+ new DataView(trexBody.buffer).setUint32(4, 1)
572
+ const mvex = box('mvex', fullBox('trex', 0, 0, trexBody))
573
+
574
+ const moov = box('moov', mvhd, trak, mvex)
575
+ const ftyp = box('ftyp', new Uint8Array([
576
+ 0x69, 0x73, 0x6f, 0x6d, 0, 0, 2, 0,
577
+ 0x69, 0x73, 0x6f, 0x6d,
578
+ 0x69, 0x73, 0x6f, 0x36,
579
+ 0x6d, 0x70, 0x34, 0x31,
580
+ ]))
581
+ const result = new Uint8Array(ftyp.length + moov.length)
582
+ result.set(ftyp, 0)
583
+ result.set(moov, ftyp.length)
584
+ return result
585
+ }
586
+
587
+ /**
588
+ * MMTP → CMAF converter.
589
+ *
590
+ * Accepts reassembled MFU frames (raw codec samples) from MmtpDecoder
591
+ * and produces fMP4 segments for MSE SourceBuffer.
592
+ *
593
+ * Per draft-ramadan-moq-mmt §5.3:
594
+ * MPU metadata (ftyp+moov) → init segment
595
+ * MFU sample bytes → moof+mdat data segment
596
+ *
597
+ * Timescale is microseconds (1_000_000) matching MMTP NTP short timestamps
598
+ * converted via mmtpTimestampToMicros().
599
+ */
600
+ export class MmtpToCmaf {
601
+ #videoSeq = 1
602
+ #audioSeq = 1
603
+ #videoInitSegment: Uint8Array | null = null
604
+ // Known only for locally-built init segments. Wire-supplied MPU metadata is
605
+ // intentionally opaque here, so setVideoTrackParams remains the API that
606
+ // lets a caller declare its track geometry before wrapping samples.
607
+ #videoInitTrackId: number | null = null
608
+ #audioInitSegment: Uint8Array | null = null
609
+ #lastVideoTimestamp = 0
610
+ // Sticky sample duration in video timescale units, updated from caller-
611
+ // supplied durations or adjacent-timestamp deltas. null means "nothing
612
+ // observed yet", in which case #videoFrameDuration derives ~30fps from the
613
+ // configured timescale (33333 at the 1_000_000 default, i.e. unchanged).
614
+ #frameDuration: number | null = null
615
+ // Per-track rebase: each track anchors on its OWN first sample so
616
+ // baseMediaDecodeTime is never negative. A shared base was wrong — if the
617
+ // first sample of one track arrives later than the other's first sample,
618
+ // the earlier track computes `timestamp - sharedBase` as a negative number,
619
+ // which serializes into tfdt as a huge unsigned uint64 (~2^64 - 46) and
620
+ // Chromium rejects the segment with CHUNK_DEMUXER_ERROR_APPEND_FAILED,
621
+ // closing the MediaSource and detaching all SourceBuffers.
622
+ // For A/V alignment, choose a COMMON anchor: set when the first sample of
623
+ // EITHER track arrives, but only if that sample's timestamp is <= any
624
+ // subsequent track's first sample. Implementation: each track rebases to
625
+ // the minimum timestamp seen across tracks on their respective first sample.
626
+ #videoBaseTs = -1
627
+ #audioBaseTs = -1
628
+
629
+ // Video track geometry. These pair with the video init segment's tkhd
630
+ // track_ID and mdhd/mvhd timescale: every moof this converter emits must
631
+ // reference the same track at the same rate or the browser either drops the
632
+ // fragment (unknown track) or plays it at the wrong rate. They are
633
+ // configuration rather than stream state, so — unlike the sequence numbers
634
+ // and time bases above — reset() deliberately preserves them, matching the
635
+ // fact that reset() also preserves #videoInitSegment.
636
+ #videoTrackId = 1
637
+ #videoTimescale = 1_000_000
638
+
639
+ /**
640
+ * Point the single-sample video wrappers at a specific track and rate.
641
+ *
642
+ * Call this when the init segment came off the wire (setInitSegmentFromMpu)
643
+ * rather than from buildVideoInit, so the wrappers match the publisher's
644
+ * tkhd/mdhd instead of assuming trackId=1 at microsecond rate. Consumers
645
+ * that build their init through buildVideoInit can pass the same values
646
+ * there instead and skip this call.
647
+ *
648
+ * The rate is settable only until the first single-sample wrap — see the
649
+ * throw below for why.
650
+ */
651
+ setVideoTrackParams(trackId: number, timescale: number) {
652
+ assertTrackId(trackId, 'video trackId')
653
+ assertTimescale(timescale, 'video timescale')
654
+ // #frameDuration, #lastVideoTimestamp and #videoBaseTs are all denominated
655
+ // in #videoTimescale, so moving the rate out from under them reinterprets
656
+ // every one at the new rate. Both consequences are silent:
657
+ // - a duration latched as 33333 (1 MHz ~30fps) re-emits as 33333 ticks of
658
+ // 90 kHz, a 370 ms frame;
659
+ // - a base captured on the old scale rebases new-scale timestamps to a
660
+ // negative relTs, which tfdt serializes as a ~2^64 uint64 and Chromium
661
+ // rejects with CHUNK_DEMUXER_ERROR_APPEND_FAILED, closing the
662
+ // MediaSource (same failure the #videoBaseTs comment above describes).
663
+ // Rescaling instead of refusing would be a guess: the class cannot tell
664
+ // whether the caller's next timestamps continue this timeline in new units
665
+ // or open a fresh epoch. reset() is the exact mechanism for that
666
+ // discontinuity — it clears all three fields while preserving geometry —
667
+ // so require it rather than infer. Re-asserting the same rate is a no-op.
668
+ // A cached init also fixes the track ID in tkhd/trex; changing only the
669
+ // wrapper setting would make later tfhd IDs disagree with that init.
670
+ if (trackId !== this.#videoTrackId && this.#videoInitTrackId !== null) {
671
+ throw new Error(
672
+ `video track ID cannot change from ${this.#videoTrackId} to ${trackId} ` +
673
+ 'after a video init has been cached; replace the init atomically',
674
+ )
675
+ }
676
+ if (timescale !== this.#videoTimescale && this.#videoBaseTs >= 0) {
677
+ throw new Error(
678
+ `video timescale cannot change from ${this.#videoTimescale} to ${timescale} ` +
679
+ `after video samples have been wrapped; call reset() first`,
680
+ )
681
+ }
682
+ this.#videoTrackId = trackId
683
+ this.#videoTimescale = timescale
684
+ }
685
+
686
+ /** Set init segment from MPU metadata packet (fragment_type=0).
687
+ * These are complete ftyp+moov bytes from FFmpeg — use directly. */
688
+ setInitSegmentFromMpu(data: Uint8Array, isAudio: boolean) {
689
+ if (isAudio) {
690
+ this.#audioInitSegment = data
691
+ } else {
692
+ this.#videoInitSegment = data
693
+ this.#videoInitTrackId = null
694
+ }
695
+ }
696
+
697
+ /** Build init segment from codec config (catalog path — no MPU metadata available).
698
+ * Passing timescale/trackId also configures the wrappers via
699
+ * setVideoTrackParams, so init and media segments cannot disagree. */
700
+ buildVideoInit(avcC: Uint8Array, width: number, height: number, timescale?: number, trackId?: number) {
701
+ const nextTimescale = timescale ?? this.#videoTimescale
702
+ const nextTrackId = trackId ?? this.#videoTrackId
703
+ assertTrackId(nextTrackId, 'video trackId')
704
+ assertTimescale(nextTimescale, 'video timescale')
705
+ if (nextTimescale !== this.#videoTimescale && this.#videoBaseTs >= 0) {
706
+ throw new Error(
707
+ `video timescale cannot change from ${this.#videoTimescale} to ${nextTimescale} ` +
708
+ 'after video samples have been wrapped; call reset() first',
709
+ )
710
+ }
711
+ // Build first, then publish both geometry and init together. This is the
712
+ // sanctioned path for replacing a cached init with a new track ID.
713
+ const init = buildVideoInitSegment(
714
+ avcC,
715
+ width,
716
+ height,
717
+ nextTimescale,
718
+ nextTrackId,
719
+ )
720
+ this.#videoTimescale = nextTimescale
721
+ this.#videoTrackId = nextTrackId
722
+ this.#videoInitSegment = init
723
+ this.#videoInitTrackId = nextTrackId
724
+ }
725
+
726
+ buildAudioInit(sampleRate: number, channels: number, asc?: Uint8Array, timescale?: number) {
727
+ const ts = timescale ?? sampleRate
728
+ // Build first, then publish, as the video path does: buildAudioInitSegment
729
+ // validates, so assigning the field first would leave a rejected timescale
730
+ // latched on the instance with no init segment to match it.
731
+ const init = buildAudioInitSegment(sampleRate, channels, asc, ts)
732
+ this.#audioTimescale = ts
733
+ this.#audioInitSegment = init
734
+ }
735
+
736
+ get videoInitSegment(): Uint8Array | null { return this.#videoInitSegment }
737
+ get audioInitSegment(): Uint8Array | null { return this.#audioInitSegment }
738
+
739
+ /** Convert a raw video sample to an fMP4 moof+mdat segment. */
740
+ wrapVideoSample(
741
+ data: Uint8Array,
742
+ timestamp: number,
743
+ keyframe: boolean,
744
+ duration?: number,
745
+ compositionTimeOffset?: number,
746
+ ): Uint8Array {
747
+ return this.wrapVideoSampleWithTiming(data, timestamp, keyframe, duration, compositionTimeOffset).segment
748
+ }
749
+
750
+ /**
751
+ * Convert a raw video sample and return the exact browser media interval
752
+ * encoded into tfdt/trun. Consumers that correlate SourceBuffer appends with
753
+ * requestVideoFrameCallback must use this rebased timestamp, not the wire or
754
+ * caller-owned timestamp passed above.
755
+ *
756
+ * `compositionTimeOffset` is the signed authored PTS-DTS delta, in the same
757
+ * #videoTimescale units as `timestamp` and `duration` — unlike wrapAudioSample,
758
+ * which takes microseconds and rescales, because every other quantity on this
759
+ * path is already denominated in #videoTimescale (see setVideoTrackParams).
760
+ * Passing it therefore needs no conversion here; rescaling would double-convert.
761
+ * Absent leaves the trun at version 0 with no offset field; a declared 0 is an
762
+ * authored value and still promotes to version 1. Never reconstruct it from
763
+ * arrival time.
764
+ */
765
+ wrapVideoSampleWithTiming(
766
+ data: Uint8Array,
767
+ timestamp: number,
768
+ keyframe: boolean,
769
+ duration?: number,
770
+ compositionTimeOffset?: number,
771
+ ): Readonly<{ segment: Uint8Array; mediaTimestamp: number; duration: number }> {
772
+ // Checked before #videoSeq++ and before the duration/base-timestamp latches
773
+ // below, for the same reason as wrapAudioSample and wrapVideoSamples: the
774
+ // encoder validates too, but by then the sequence number is spent and a
775
+ // caller that corrects the offset and retries emits a gapped mfhd.
776
+ assertCompositionTimeOffsets([{ compositionTimeOffset }])
777
+ // Prefer a caller-provided media duration when the browser append timeline
778
+ // is intentionally decoupled from sparse MMTP wire timestamps. Fall back to
779
+ // estimating from adjacent timestamps for legacy/direct callers. A delta of
780
+ // a full second or more is not a frame interval, so it is rejected as a
781
+ // discontinuity rather than latched.
782
+ if (duration !== undefined && Number.isFinite(duration) && duration > 0) {
783
+ this.#frameDuration = Math.round(duration)
784
+ } else if (this.#lastVideoTimestamp > 0 && timestamp > this.#lastVideoTimestamp) {
785
+ const delta = timestamp - this.#lastVideoTimestamp
786
+ if (delta > 0 && delta < this.#videoTimescale) this.#frameDuration = delta
787
+ }
788
+ this.#lastVideoTimestamp = timestamp
789
+ if (this.#videoBaseTs < 0) this.#videoBaseTs = timestamp
790
+ const relTs = timestamp - this.#videoBaseTs
791
+ const frameDuration = this.#videoFrameDuration
792
+ return Object.freeze({
793
+ segment: encodeDataSegment(
794
+ data,
795
+ relTs,
796
+ frameDuration,
797
+ keyframe,
798
+ this.#videoSeq++,
799
+ this.#videoTrackId,
800
+ compositionTimeOffset,
801
+ ),
802
+ mediaTimestamp: relTs,
803
+ duration: frameDuration,
804
+ })
805
+ }
806
+
807
+ /** Sticky duration if one has been observed, else ~30fps at the current rate. */
808
+ get #videoFrameDuration(): number {
809
+ return this.#frameDuration ?? Math.max(1, Math.round(this.#videoTimescale / 30))
810
+ }
811
+
812
+ /** Convert an append-safe video batch using the caller-owned timeline.
813
+ * Durations, baseDecodeTime, and compositionTimeOffset are in the
814
+ * configured video timescale. compositionTimeOffset is the signed PTS-DTS
815
+ * delta; its presence selects a version-1 trun for the whole batch.
816
+ * An explicit trackId is range-checked before #videoSeq++ for the same
817
+ * reason as wrapAudioSamples: the encoder's own check fires too late to
818
+ * keep the sequence ungapped. */
819
+ wrapVideoSamples(
820
+ samples: Array<{
821
+ data: Uint8Array
822
+ duration: number
823
+ keyframe: boolean
824
+ compositionTimeOffset?: number
825
+ }>,
826
+ baseDecodeTime: number,
827
+ trackId = this.#videoTrackId,
828
+ ): Uint8Array {
829
+ assertTrackId(trackId, 'video trackId')
830
+ assertCompositionTimeOffsets(samples)
831
+ return encodeMultiSampleSegment(samples, baseDecodeTime, this.#videoSeq++, trackId)
832
+ }
833
+
834
+ // Audio timescale from init segment (default 1M µs; real FFmpeg init uses sampleRate).
835
+ // Set by buildAudioInit or setAudioTimescale.
836
+ #audioTimescale = 1_000_000
837
+
838
+ /** Set audio timescale to match the init segment's mdhd timescale.
839
+ * Call after appending the real encoder init (FT=0 ftyp+moov).
840
+ * Fails closed on a value the mdhd uint32 cannot hold, as the video paths
841
+ * already do. wrapAudioSample rescales the authored composition offset by
842
+ * this value, so the two failure modes are both silent: a 0 multiplies
843
+ * every authored offset to 0 — indistinguishable from a feed that authored
844
+ * none — while a value above uint32 scales the trun to a timescale the
845
+ * mdhd cannot declare, since it is emitted with setUint32 modulo 2^32. */
846
+ setAudioTimescale(timescale: number) {
847
+ assertTimescale(timescale, 'audio timescale')
848
+ this.#audioTimescale = timescale
849
+ }
850
+
851
+ // Audio sample counter for drift-free baseMediaDecodeTime.
852
+ // AAC frames are exactly 1024 samples at sampleRate. Using sequential
853
+ // counter × 1024 avoids floating-point rounding drift from timestamp conversion.
854
+ #audioSampleCount = 0
855
+
856
+ /** AAC access-unit length in samples. ISO/IEC 14496-3: an AAC-LC frame is
857
+ * exactly 1024 samples at every sample rate — it is not rate-dependent. */
858
+ readonly #aacFrameSamples = 1024
859
+
860
+ /** Convert a raw audio sample to an fMP4 moof+mdat segment. */
861
+ wrapAudioSample(
862
+ data: Uint8Array,
863
+ timestamp: number,
864
+ sampleDuration = 21333,
865
+ compositionTimeOffset?: number,
866
+ ): Uint8Array {
867
+ assertCompositionTimeOffsets([{ compositionTimeOffset }])
868
+ const sampleData = normalizeAacSampleForCmaf(data)
869
+ if (this.#audioBaseTs < 0) this.#audioBaseTs = timestamp
870
+
871
+ // When timescale matches sampleRate (e.g. 48000), use integer sample counting
872
+ // for exact baseMediaDecodeTime alignment. This eliminates cumulative rounding
873
+ // drift from Math.round(µs * sampleRate / 1_000_000) that causes frequency
874
+ // wandering in FFT analysis (42% consistency → 99%+ with exact counting).
875
+ //
876
+ // samplesPerFrame is the AAC access-unit length, NOT a rescaled duration.
877
+ // Deriving it as Math.round(sampleDuration * timescale / 1e6) only lands on
878
+ // 1024 when the rate happens to be 48 kHz (21333 * 48000 / 1e6 = 1023.98),
879
+ // which made the default silently correct at 48 kHz and wrong everywhere
880
+ // else: at 44.1 kHz it yields 941, so every moof declared ~8% short frames
881
+ // and Chrome rejected the first packet with PIPELINE_ERROR_DECODE
882
+ // ("Failed to send audio packet for decoding", duration=21337µs = 941/44100).
883
+ const samplesPerFrame = this.#audioTimescale !== 1_000_000
884
+ ? this.#aacFrameSamples
885
+ : sampleDuration
886
+ const scaledTs = this.#audioTimescale !== 1_000_000
887
+ ? this.#audioSampleCount * samplesPerFrame
888
+ : (timestamp - this.#audioBaseTs)
889
+ this.#audioSampleCount++
890
+
891
+ // compositionTimeOffset arrives in microsecond ticks, like timestamp and
892
+ // sampleDuration: the block assembler scales authored PTS-DTS into its own
893
+ // timescale, which defaults to 1e6 whenever the caller omits `timescale`
894
+ // (cmaf-block-assembler.ts). The trun it lands in is at #audioTimescale, so
895
+ // on the sample-counting branch it needs the same rescale its two siblings
896
+ // above already get. Without it a 10 ms authored offset is written as
897
+ // 10_000 ticks of a 48 kHz track — 1e6/48000 = 20.83x, ~208 ms of A/V
898
+ // desync — which is the samplesPerFrame hazard documented above, one field
899
+ // over. Undefined stays undefined so raw feeds keep a v0 trun with no
900
+ // composition-offset field rather than claiming an authored zero.
901
+ //
902
+ // This 1e6 is the assembler's default timescale, not a free constant, so
903
+ // the two move together. Configuring the audio assembler with
904
+ // `timescale: sampleRate` makes its offsets already trun ticks and turns
905
+ // this rescale into a 20.83x *under*-count: an authored 480 arrives as 23.
906
+ //
907
+ // The two bridges currently disagree on that config, so this rescale is
908
+ // correct for exactly one of them at a time. moqtail omits `timescale`
909
+ // (apps/client-js/src/lib/player.ts, audio enableMseAssembler) and needs
910
+ // the rescale. hang passes `timescale: sampleRate` (js/watch/src/element.ts,
911
+ // audio enableMseAssembler) and must not get it. hang is safe today only
912
+ // because it pins a libmmt revision older than this rescale. Bumping that
913
+ // pin past this commit without dropping hang's `timescale` in the same
914
+ // change is the 20.83x under-count, so the pin bump and the hang edit are
915
+ // one atomic change. mmtp-to-cmaf-audio-composition-offset.test.ts pins
916
+ // both configs against a real CmafBlockAssembler so the pairing is checked
917
+ // by CI rather than by this comment.
918
+ const scaledCompositionTimeOffset =
919
+ compositionTimeOffset === undefined || this.#audioTimescale === 1_000_000
920
+ ? compositionTimeOffset
921
+ : Math.round((compositionTimeOffset * this.#audioTimescale) / 1_000_000)
922
+
923
+ return encodeDataSegment(
924
+ sampleData,
925
+ scaledTs,
926
+ samplesPerFrame,
927
+ true,
928
+ this.#audioSeq++,
929
+ 1,
930
+ scaledCompositionTimeOffset,
931
+ )
932
+ }
933
+
934
+ /** Convert an ordered audio batch using the caller-owned timeline. */
935
+ wrapAudioSamples(
936
+ samples: Array<{
937
+ data: Uint8Array
938
+ duration: number
939
+ compositionTimeOffset?: number
940
+ }>,
941
+ baseDecodeTime: number,
942
+ trackId = 1,
943
+ ): Uint8Array {
944
+ // Checked before #audioSeq++ below: the encoder validates too, but its
945
+ // throw would land after the counter had already advanced, leaving the
946
+ // sequence gapped by a call that produced no segment.
947
+ assertTrackId(trackId, 'audio trackId')
948
+ assertCompositionTimeOffsets(samples)
949
+ return encodeMultiSampleSegment(
950
+ samples.map(sample => ({
951
+ data: normalizeAacSampleForCmaf(sample.data),
952
+ duration: sample.duration,
953
+ keyframe: true,
954
+ compositionTimeOffset: sample.compositionTimeOffset,
955
+ })),
956
+ baseDecodeTime,
957
+ this.#audioSeq++,
958
+ trackId,
959
+ )
960
+ }
961
+
962
+ /** Clear per-stream sequencing and time bases.
963
+ * Cached init segments and the video track geometry survive, so a converter
964
+ * reset mid-subscription keeps emitting moofs the existing init can resolve.
965
+ * Clearing the timescale-denominated timing state also re-opens the video
966
+ * rate for change — this is the sanctioned way to retarget mid-subscription. */
967
+ reset() {
968
+ this.#videoSeq = 1
969
+ this.#audioSeq = 1
970
+ this.#audioSampleCount = 0
971
+ this.#lastVideoTimestamp = 0
972
+ this.#frameDuration = null
973
+ this.#videoBaseTs = -1
974
+ this.#audioBaseTs = -1
975
+ this.#audioTimescale = 1_000_000
976
+ }
977
+ }