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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (799) hide show
  1. package/README.md +524 -0
  2. package/dist/.build-stamp +0 -0
  3. package/dist/__tests__/test-utils.d.ts +71 -0
  4. package/dist/__tests__/test-utils.d.ts.map +1 -0
  5. package/dist/align.d.ts +152 -0
  6. package/dist/align.d.ts.map +1 -0
  7. package/dist/align.js +88 -0
  8. package/dist/align.js.map +7 -0
  9. package/dist/audio-init-parser.d.ts +66 -0
  10. package/dist/audio-init-parser.d.ts.map +1 -0
  11. package/dist/audio-init-parser.js +118 -0
  12. package/dist/audio-init-parser.js.map +7 -0
  13. package/dist/audio-ring-buffer.d.ts +50 -0
  14. package/dist/audio-ring-buffer.d.ts.map +1 -0
  15. package/dist/audio-ring-buffer.js +80 -0
  16. package/dist/audio-ring-buffer.js.map +7 -0
  17. package/dist/authored-timing.d.ts +32 -0
  18. package/dist/authored-timing.d.ts.map +1 -0
  19. package/dist/authored-timing.js +32 -0
  20. package/dist/authored-timing.js.map +7 -0
  21. package/dist/block-policy.d.ts +314 -0
  22. package/dist/block-policy.d.ts.map +1 -0
  23. package/dist/block-policy.js +466 -0
  24. package/dist/block-policy.js.map +7 -0
  25. package/dist/browser-runtime.js +26549 -0
  26. package/dist/browser-runtime.js.map +7 -0
  27. package/dist/carp-catalog.d.ts +429 -0
  28. package/dist/carp-catalog.d.ts.map +1 -0
  29. package/dist/carp-catalog.js +985 -0
  30. package/dist/carp-catalog.js.map +7 -0
  31. package/dist/catalog-fec-params.d.ts +275 -0
  32. package/dist/catalog-fec-params.d.ts.map +1 -0
  33. package/dist/catalog-fec-params.js +702 -0
  34. package/dist/catalog-fec-params.js.map +7 -0
  35. package/dist/catalog-network-source.d.ts +42 -0
  36. package/dist/catalog-network-source.d.ts.map +1 -0
  37. package/dist/catalog-network-source.js +47 -0
  38. package/dist/catalog-network-source.js.map +7 -0
  39. package/dist/catalog-validator.d.ts +18 -0
  40. package/dist/catalog-validator.d.ts.map +1 -0
  41. package/dist/catalog-validator.js +7747 -0
  42. package/dist/catalog-validator.js.map +7 -0
  43. package/dist/cmaf-block-assembler.d.ts +285 -0
  44. package/dist/cmaf-block-assembler.d.ts.map +1 -0
  45. package/dist/cmaf-block-assembler.js +1966 -0
  46. package/dist/cmaf-block-assembler.js.map +7 -0
  47. package/dist/cmaf-group-batcher.d.ts +38 -0
  48. package/dist/cmaf-group-batcher.d.ts.map +1 -0
  49. package/dist/cmaf-group-batcher.js +176 -0
  50. package/dist/cmaf-group-batcher.js.map +7 -0
  51. package/dist/cmcd-producer.d.ts +104 -0
  52. package/dist/cmcd-producer.d.ts.map +1 -0
  53. package/dist/cmcd-producer.js +183 -0
  54. package/dist/cmcd-producer.js.map +7 -0
  55. package/dist/codec-utils.d.ts +384 -0
  56. package/dist/codec-utils.d.ts.map +1 -0
  57. package/dist/codec-utils.js +1546 -0
  58. package/dist/codec-utils.js.map +7 -0
  59. package/dist/conceal-timeline.d.ts +146 -0
  60. package/dist/conceal-timeline.d.ts.map +1 -0
  61. package/dist/conceal-timeline.js +137 -0
  62. package/dist/conceal-timeline.js.map +7 -0
  63. package/dist/delivery-gap.d.ts +75 -0
  64. package/dist/delivery-gap.d.ts.map +1 -0
  65. package/dist/delivery-gap.js +88 -0
  66. package/dist/delivery-gap.js.map +7 -0
  67. package/dist/duplicate-ledger.d.ts +197 -0
  68. package/dist/duplicate-ledger.d.ts.map +1 -0
  69. package/dist/duplicate-ledger.js +226 -0
  70. package/dist/duplicate-ledger.js.map +7 -0
  71. package/dist/fec-codec.d.ts +32 -0
  72. package/dist/fec-codec.d.ts.map +1 -0
  73. package/dist/fec-codec.js +47 -0
  74. package/dist/fec-codec.js.map +7 -0
  75. package/dist/fec-manager.d.ts +583 -0
  76. package/dist/fec-manager.d.ts.map +1 -0
  77. package/dist/fec-manager.js +3899 -0
  78. package/dist/fec-manager.js.map +7 -0
  79. package/dist/fec-starvation-detector.d.ts +59 -0
  80. package/dist/fec-starvation-detector.d.ts.map +1 -0
  81. package/dist/fec-starvation-detector.js +60 -0
  82. package/dist/fec-starvation-detector.js.map +7 -0
  83. package/dist/fec-state.d.ts +131 -0
  84. package/dist/fec-state.d.ts.map +1 -0
  85. package/dist/fec-state.js +87 -0
  86. package/dist/fec-state.js.map +7 -0
  87. package/dist/fec-worker-setup.d.ts +94 -0
  88. package/dist/fec-worker-setup.d.ts.map +1 -0
  89. package/dist/fec-worker-setup.js +673 -0
  90. package/dist/fec-worker-setup.js.map +7 -0
  91. package/dist/fmp4-completion.d.ts +30 -0
  92. package/dist/fmp4-completion.d.ts.map +1 -0
  93. package/dist/fmp4-completion.js +21 -0
  94. package/dist/fmp4-completion.js.map +7 -0
  95. package/dist/fmp4-reader.d.ts +37 -0
  96. package/dist/fmp4-reader.d.ts.map +1 -0
  97. package/dist/fmp4-reader.js +100 -0
  98. package/dist/fmp4-reader.js.map +7 -0
  99. package/dist/index.d.ts +44 -3
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +460 -14
  102. package/dist/index.js.map +7 -1
  103. package/dist/iso-block-locator.d.ts +118 -0
  104. package/dist/iso-block-locator.d.ts.map +1 -0
  105. package/dist/iso-block-locator.js +289 -0
  106. package/dist/iso-block-locator.js.map +7 -0
  107. package/dist/iso-bmff-timing.d.ts +78 -0
  108. package/dist/iso-bmff-timing.d.ts.map +1 -0
  109. package/dist/iso-bmff-timing.js +593 -0
  110. package/dist/iso-bmff-timing.js.map +7 -0
  111. package/dist/loc.d.ts +70 -75
  112. package/dist/loc.d.ts.map +1 -1
  113. package/dist/loc.js +106 -192
  114. package/dist/loc.js.map +7 -1
  115. package/dist/manifest-auth-plan.d.ts +30 -0
  116. package/dist/manifest-auth-plan.d.ts.map +1 -0
  117. package/dist/manifest-auth-plan.js +1266 -0
  118. package/dist/manifest-auth-plan.js.map +7 -0
  119. package/dist/media-router.d.ts +262 -0
  120. package/dist/media-router.d.ts.map +1 -0
  121. package/dist/media-router.js +584 -0
  122. package/dist/media-router.js.map +7 -0
  123. package/dist/mfu-reassembler.d.ts +313 -9
  124. package/dist/mfu-reassembler.d.ts.map +1 -1
  125. package/dist/mfu-reassembler.js +3051 -285
  126. package/dist/mfu-reassembler.js.map +7 -1
  127. package/dist/mfu-reassembly-policy.d.ts +24 -0
  128. package/dist/mfu-reassembly-policy.d.ts.map +1 -0
  129. package/dist/mfu-reassembly-policy.js +99 -0
  130. package/dist/mfu-reassembly-policy.js.map +7 -0
  131. package/dist/mmtp-container-parser.d.ts +568 -0
  132. package/dist/mmtp-container-parser.d.ts.map +1 -0
  133. package/dist/mmtp-container-parser.js +6580 -0
  134. package/dist/mmtp-container-parser.js.map +7 -0
  135. package/dist/mmtp-container-parser.no-modules.js +9616 -0
  136. package/dist/mmtp-container-parser.no-modules.js.map +7 -0
  137. package/dist/mmtp-decode-pipeline.d.ts +138 -0
  138. package/dist/mmtp-decode-pipeline.d.ts.map +1 -0
  139. package/dist/mmtp-decode-pipeline.js +6814 -0
  140. package/dist/mmtp-decode-pipeline.js.map +7 -0
  141. package/dist/mmtp-router.d.ts +679 -0
  142. package/dist/mmtp-router.d.ts.map +1 -0
  143. package/dist/mmtp-router.js +11278 -0
  144. package/dist/mmtp-router.js.map +7 -0
  145. package/dist/mmtp-to-cmaf.d.ts +187 -0
  146. package/dist/mmtp-to-cmaf.d.ts.map +1 -0
  147. package/dist/mmtp-to-cmaf.js +716 -0
  148. package/dist/mmtp-to-cmaf.js.map +7 -0
  149. package/dist/multicast-auth-catalog.d.ts +115 -0
  150. package/dist/multicast-auth-catalog.d.ts.map +1 -0
  151. package/dist/multicast-auth-catalog.js +202 -0
  152. package/dist/multicast-auth-catalog.js.map +7 -0
  153. package/dist/multicast-input.d.ts +141 -0
  154. package/dist/multicast-input.d.ts.map +1 -0
  155. package/dist/multicast-input.js +390 -0
  156. package/dist/multicast-input.js.map +7 -0
  157. package/dist/multicast-manager.d.ts +669 -0
  158. package/dist/multicast-manager.d.ts.map +1 -0
  159. package/dist/multicast-manager.js +19101 -0
  160. package/dist/multicast-manager.js.map +7 -0
  161. package/dist/multicast-transport.d.ts +271 -0
  162. package/dist/multicast-transport.d.ts.map +1 -0
  163. package/dist/multicast-transport.js +2264 -0
  164. package/dist/multicast-transport.js.map +7 -0
  165. package/dist/multicast-unwrap.d.ts +57 -0
  166. package/dist/multicast-unwrap.d.ts.map +1 -0
  167. package/dist/multicast-unwrap.js +418 -0
  168. package/dist/multicast-unwrap.js.map +7 -0
  169. package/dist/no-modules.d.ts +10 -0
  170. package/dist/no-modules.d.ts.map +1 -0
  171. package/dist/no-modules.js +9491 -0
  172. package/dist/no-modules.js.map +7 -0
  173. package/dist/phase14-catalog-override.d.ts +126 -0
  174. package/dist/phase14-catalog-override.d.ts.map +1 -0
  175. package/dist/phase14-catalog-override.js +155 -0
  176. package/dist/phase14-catalog-override.js.map +7 -0
  177. package/dist/repair-fetch.d.ts +270 -0
  178. package/dist/repair-fetch.d.ts.map +1 -0
  179. package/dist/repair-fetch.js +381 -0
  180. package/dist/repair-fetch.js.map +7 -0
  181. package/dist/repair-layers.d.ts +158 -0
  182. package/dist/repair-layers.d.ts.map +1 -0
  183. package/dist/repair-layers.js +344 -0
  184. package/dist/repair-layers.js.map +7 -0
  185. package/dist/sample-combiner.d.ts +212 -0
  186. package/dist/sample-combiner.d.ts.map +1 -0
  187. package/dist/sample-combiner.js +595 -0
  188. package/dist/sample-combiner.js.map +7 -0
  189. package/dist/signaling.d.ts +29 -0
  190. package/dist/signaling.d.ts.map +1 -0
  191. package/dist/signaling.js +572 -0
  192. package/dist/signaling.js.map +7 -0
  193. package/dist/source-auth.d.ts +2 -0
  194. package/dist/source-auth.d.ts.map +1 -0
  195. package/dist/source-auth.js +1209 -0
  196. package/dist/source-auth.js.map +7 -0
  197. package/dist/switching-set-alignment.d.ts +61 -0
  198. package/dist/switching-set-alignment.d.ts.map +1 -0
  199. package/dist/switching-set-alignment.js +70 -0
  200. package/dist/switching-set-alignment.js.map +7 -0
  201. package/dist/timestamp-codec.d.ts +34 -0
  202. package/dist/timestamp-codec.d.ts.map +1 -0
  203. package/dist/timestamp-codec.js +473 -0
  204. package/dist/timestamp-codec.js.map +7 -0
  205. package/dist/track-pipeline-setup.d.ts +83 -0
  206. package/dist/track-pipeline-setup.d.ts.map +1 -0
  207. package/dist/track-pipeline-setup.js +291 -0
  208. package/dist/track-pipeline-setup.js.map +7 -0
  209. package/dist/track-pipeline.d.ts +121 -0
  210. package/dist/track-pipeline.d.ts.map +1 -0
  211. package/dist/track-pipeline.js +209 -0
  212. package/dist/track-pipeline.js.map +7 -0
  213. package/dist/track-session.d.ts +414 -0
  214. package/dist/track-session.d.ts.map +1 -0
  215. package/dist/track-session.js +754 -0
  216. package/dist/track-session.js.map +7 -0
  217. package/dist/transport-pool.d.ts +69 -0
  218. package/dist/transport-pool.d.ts.map +1 -0
  219. package/dist/transport-pool.js +74 -0
  220. package/dist/transport-pool.js.map +7 -0
  221. package/dist/wasm-mfu-reassembler.d.ts +97 -0
  222. package/dist/wasm-mfu-reassembler.d.ts.map +1 -0
  223. package/dist/wasm-mfu-reassembler.js +2133 -0
  224. package/dist/wasm-mfu-reassembler.js.map +7 -0
  225. package/dist/wasm-mmtp-container-parser.d.ts +10 -0
  226. package/dist/wasm-mmtp-container-parser.d.ts.map +1 -0
  227. package/dist/wasm-mmtp-container-parser.js +6834 -0
  228. package/dist/wasm-mmtp-container-parser.js.map +7 -0
  229. package/node_modules/@blockcast/fec-worker/README.md +223 -0
  230. package/node_modules/@blockcast/fec-worker/dist/.build-stamp +0 -0
  231. package/node_modules/@blockcast/fec-worker/dist/block-order.d.ts +38 -0
  232. package/node_modules/@blockcast/fec-worker/dist/block-order.d.ts.map +1 -0
  233. package/node_modules/@blockcast/fec-worker/dist/block-order.js +78 -0
  234. package/node_modules/@blockcast/fec-worker/dist/block-order.js.map +1 -0
  235. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts +93 -0
  236. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts.map +1 -0
  237. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js +346 -0
  238. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js.map +1 -0
  239. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts +380 -0
  240. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts.map +1 -0
  241. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js +11 -0
  242. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js.map +1 -0
  243. package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts +14 -0
  244. package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts.map +1 -0
  245. package/node_modules/@blockcast/fec-worker/dist/fec-worker.js +859 -0
  246. package/node_modules/@blockcast/fec-worker/dist/fec-worker.js.map +7 -0
  247. package/node_modules/@blockcast/fec-worker/dist/index.d.ts +10 -0
  248. package/node_modules/@blockcast/fec-worker/dist/index.d.ts.map +1 -0
  249. package/node_modules/@blockcast/fec-worker/dist/index.js +8 -0
  250. package/node_modules/@blockcast/fec-worker/dist/index.js.map +1 -0
  251. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts +20 -0
  252. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts.map +1 -0
  253. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js +370 -0
  254. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js.map +7 -0
  255. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts +104 -0
  256. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts.map +1 -0
  257. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js +181 -0
  258. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js.map +1 -0
  259. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts +194 -0
  260. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts.map +1 -0
  261. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js +62 -0
  262. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js.map +1 -0
  263. package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts +9 -0
  264. package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts.map +1 -0
  265. package/node_modules/@blockcast/fec-worker/dist/transfer.js +13 -0
  266. package/node_modules/@blockcast/fec-worker/dist/transfer.js.map +1 -0
  267. package/node_modules/@blockcast/fec-worker/package.json +59 -0
  268. package/node_modules/@blockcast/fec-worker/src/block-order.ts +93 -0
  269. package/node_modules/@blockcast/fec-worker/src/fec-worker-client.ts +392 -0
  270. package/node_modules/@blockcast/fec-worker/src/fec-worker-types.ts +399 -0
  271. package/node_modules/@blockcast/fec-worker/src/fec-worker.ts +1502 -0
  272. package/node_modules/@blockcast/fec-worker/src/index.ts +35 -0
  273. package/node_modules/@blockcast/fec-worker/src/shred-fec-worker.ts +589 -0
  274. package/node_modules/@blockcast/fec-worker/src/shred-worker-client.ts +222 -0
  275. package/node_modules/@blockcast/fec-worker/src/shred-worker-types.ts +209 -0
  276. package/node_modules/@blockcast/fec-worker/src/transfer.ts +12 -0
  277. package/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
  278. package/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
  279. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
  280. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
  281. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
  282. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
  283. package/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
  284. package/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
  285. package/node_modules/@blockcast/mmt-base/README.md +134 -0
  286. package/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
  287. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts +55 -0
  288. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts.map +1 -0
  289. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js +128 -0
  290. package/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js.map +1 -0
  291. package/node_modules/@blockcast/mmt-base/dist/index.d.ts +7 -0
  292. package/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
  293. package/node_modules/@blockcast/mmt-base/dist/index.js +7 -0
  294. package/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
  295. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +292 -0
  296. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
  297. package/node_modules/@blockcast/mmt-base/dist/mmtp.js +612 -0
  298. package/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
  299. package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts +18 -0
  300. package/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts.map +1 -0
  301. package/node_modules/@blockcast/mmt-base/dist/net-constants.js +18 -0
  302. package/node_modules/@blockcast/mmt-base/dist/net-constants.js.map +1 -0
  303. package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts +47 -0
  304. package/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts.map +1 -0
  305. package/node_modules/@blockcast/mmt-base/dist/ntp-short.js +54 -0
  306. package/node_modules/@blockcast/mmt-base/dist/ntp-short.js.map +1 -0
  307. package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts +57 -0
  308. package/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts.map +1 -0
  309. package/node_modules/@blockcast/mmt-base/dist/serial-number.js +98 -0
  310. package/node_modules/@blockcast/mmt-base/dist/serial-number.js.map +1 -0
  311. package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts +312 -0
  312. package/node_modules/@blockcast/mmt-base/dist/signalling.d.ts.map +1 -0
  313. package/node_modules/@blockcast/mmt-base/dist/signalling.js +637 -0
  314. package/node_modules/@blockcast/mmt-base/dist/signalling.js.map +1 -0
  315. package/node_modules/@blockcast/mmt-base/package.json +49 -0
  316. package/node_modules/@blockcast/mmt-base/src/fec-block-profile.ts +145 -0
  317. package/node_modules/@blockcast/mmt-base/src/index.ts +6 -0
  318. package/node_modules/@blockcast/mmt-base/src/mmtp.ts +892 -0
  319. package/node_modules/@blockcast/mmt-base/src/net-constants.ts +17 -0
  320. package/node_modules/@blockcast/mmt-base/src/ntp-short.ts +67 -0
  321. package/node_modules/@blockcast/mmt-base/src/serial-number.ts +107 -0
  322. package/node_modules/@blockcast/mmt-base/src/signalling.ts +862 -0
  323. package/node_modules/@blockcast/mmt-fec/README.md +271 -0
  324. package/node_modules/@blockcast/mmt-fec/dist/.build-stamp +0 -0
  325. package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts +82 -0
  326. package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts.map +1 -0
  327. package/node_modules/@blockcast/mmt-fec/dist/block-manager.js +296 -0
  328. package/node_modules/@blockcast/mmt-fec/dist/block-manager.js.map +1 -0
  329. package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts +106 -0
  330. package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts.map +1 -0
  331. package/node_modules/@blockcast/mmt-fec/dist/block-processor.js +288 -0
  332. package/node_modules/@blockcast/mmt-fec/dist/block-processor.js.map +1 -0
  333. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts +46 -0
  334. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts.map +1 -0
  335. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js +96 -0
  336. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js.map +1 -0
  337. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts +33 -0
  338. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts.map +1 -0
  339. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js +57 -0
  340. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js.map +1 -0
  341. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts +205 -0
  342. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts.map +1 -0
  343. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js +240 -0
  344. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js.map +1 -0
  345. package/node_modules/@blockcast/mmt-fec/dist/index.d.ts +28 -0
  346. package/node_modules/@blockcast/mmt-fec/dist/index.d.ts.map +1 -0
  347. package/node_modules/@blockcast/mmt-fec/dist/index.js +28 -0
  348. package/node_modules/@blockcast/mmt-fec/dist/index.js.map +1 -0
  349. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts +20 -0
  350. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts.map +1 -0
  351. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js +28 -0
  352. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js.map +1 -0
  353. package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts +258 -0
  354. package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts.map +1 -0
  355. package/node_modules/@blockcast/mmt-fec/dist/oti.js +382 -0
  356. package/node_modules/@blockcast/mmt-fec/dist/oti.js.map +1 -0
  357. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts +41 -0
  358. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts.map +1 -0
  359. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js +81 -0
  360. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js.map +1 -0
  361. package/node_modules/@blockcast/mmt-fec/dist/repair-group.d.ts +82 -0
  362. package/node_modules/@blockcast/mmt-fec/dist/repair-group.d.ts.map +1 -0
  363. package/node_modules/@blockcast/mmt-fec/dist/repair-group.js +170 -0
  364. package/node_modules/@blockcast/mmt-fec/dist/repair-group.js.map +1 -0
  365. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
  366. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
  367. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
  368. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
  369. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
  370. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
  371. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
  372. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
  373. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/README.md +134 -0
  374. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
  375. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts +55 -0
  376. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.d.ts.map +1 -0
  377. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js +128 -0
  378. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/fec-block-profile.js.map +1 -0
  379. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts +7 -0
  380. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
  381. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js +7 -0
  382. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
  383. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +292 -0
  384. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
  385. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js +612 -0
  386. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
  387. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts +18 -0
  388. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.d.ts.map +1 -0
  389. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.js +18 -0
  390. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/net-constants.js.map +1 -0
  391. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts +47 -0
  392. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.d.ts.map +1 -0
  393. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.js +54 -0
  394. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/ntp-short.js.map +1 -0
  395. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts +57 -0
  396. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.d.ts.map +1 -0
  397. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.js +98 -0
  398. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/serial-number.js.map +1 -0
  399. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.d.ts +312 -0
  400. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.d.ts.map +1 -0
  401. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.js +637 -0
  402. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/signalling.js.map +1 -0
  403. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/package.json +49 -0
  404. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/fec-block-profile.ts +145 -0
  405. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/index.ts +6 -0
  406. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/mmtp.ts +892 -0
  407. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/net-constants.ts +17 -0
  408. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/ntp-short.ts +67 -0
  409. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/serial-number.ts +107 -0
  410. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/signalling.ts +862 -0
  411. package/node_modules/@blockcast/mmt-fec/package.json +79 -0
  412. package/node_modules/@blockcast/mmt-fec/src/block-manager.ts +371 -0
  413. package/node_modules/@blockcast/mmt-fec/src/block-processor.ts +439 -0
  414. package/node_modules/@blockcast/mmt-fec/src/cmaf-recovery.ts +127 -0
  415. package/node_modules/@blockcast/mmt-fec/src/cmaf-symbols.ts +68 -0
  416. package/node_modules/@blockcast/mmt-fec/src/fec-block-mapper.ts +310 -0
  417. package/node_modules/@blockcast/mmt-fec/src/index.ts +94 -0
  418. package/node_modules/@blockcast/mmt-fec/src/loc-symbols.ts +34 -0
  419. package/node_modules/@blockcast/mmt-fec/src/oti.ts +463 -0
  420. package/node_modules/@blockcast/mmt-fec/src/reorder-buffer.ts +101 -0
  421. package/node_modules/@blockcast/mmt-fec/src/repair-group.ts +195 -0
  422. package/node_modules/@blockcast/mmt-manifest-verify/dist/.build-stamp +0 -0
  423. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts +28 -0
  424. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts.map +1 -0
  425. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js +128 -0
  426. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js.map +1 -0
  427. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts +4 -0
  428. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts.map +1 -0
  429. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js +4 -0
  430. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js.map +1 -0
  431. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts +37 -0
  432. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts.map +1 -0
  433. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js +179 -0
  434. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js.map +1 -0
  435. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts +99 -0
  436. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts.map +1 -0
  437. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js +492 -0
  438. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js.map +1 -0
  439. package/node_modules/@blockcast/mmt-manifest-verify/package.json +45 -0
  440. package/node_modules/@blockcast/mmt-manifest-verify/src/admission.ts +171 -0
  441. package/node_modules/@blockcast/mmt-manifest-verify/src/index.ts +3 -0
  442. package/node_modules/@blockcast/mmt-manifest-verify/src/source-auth.ts +230 -0
  443. package/node_modules/@blockcast/mmt-manifest-verify/src/verifier.ts +669 -0
  444. package/node_modules/@noble/hashes/LICENSE +21 -0
  445. package/node_modules/@noble/hashes/README.md +521 -0
  446. package/node_modules/@noble/hashes/_assert.d.ts +17 -0
  447. package/node_modules/@noble/hashes/_assert.d.ts.map +1 -0
  448. package/node_modules/@noble/hashes/_assert.js +18 -0
  449. package/node_modules/@noble/hashes/_assert.js.map +1 -0
  450. package/node_modules/@noble/hashes/_blake.d.ts +14 -0
  451. package/node_modules/@noble/hashes/_blake.d.ts.map +1 -0
  452. package/node_modules/@noble/hashes/_blake.js +50 -0
  453. package/node_modules/@noble/hashes/_blake.js.map +1 -0
  454. package/node_modules/@noble/hashes/_md.d.ts +51 -0
  455. package/node_modules/@noble/hashes/_md.d.ts.map +1 -0
  456. package/node_modules/@noble/hashes/_md.js +162 -0
  457. package/node_modules/@noble/hashes/_md.js.map +1 -0
  458. package/node_modules/@noble/hashes/_u64.d.ts +55 -0
  459. package/node_modules/@noble/hashes/_u64.d.ts.map +1 -0
  460. package/node_modules/@noble/hashes/_u64.js +90 -0
  461. package/node_modules/@noble/hashes/_u64.js.map +1 -0
  462. package/node_modules/@noble/hashes/argon2.d.ts +32 -0
  463. package/node_modules/@noble/hashes/argon2.d.ts.map +1 -0
  464. package/node_modules/@noble/hashes/argon2.js +401 -0
  465. package/node_modules/@noble/hashes/argon2.js.map +1 -0
  466. package/node_modules/@noble/hashes/blake1.d.ts +106 -0
  467. package/node_modules/@noble/hashes/blake1.d.ts.map +1 -0
  468. package/node_modules/@noble/hashes/blake1.js +459 -0
  469. package/node_modules/@noble/hashes/blake1.js.map +1 -0
  470. package/node_modules/@noble/hashes/blake2.d.ts +116 -0
  471. package/node_modules/@noble/hashes/blake2.d.ts.map +1 -0
  472. package/node_modules/@noble/hashes/blake2.js +420 -0
  473. package/node_modules/@noble/hashes/blake2.js.map +1 -0
  474. package/node_modules/@noble/hashes/blake2b.d.ts +11 -0
  475. package/node_modules/@noble/hashes/blake2b.d.ts.map +1 -0
  476. package/node_modules/@noble/hashes/blake2b.js +14 -0
  477. package/node_modules/@noble/hashes/blake2b.js.map +1 -0
  478. package/node_modules/@noble/hashes/blake2s.d.ts +20 -0
  479. package/node_modules/@noble/hashes/blake2s.d.ts.map +1 -0
  480. package/node_modules/@noble/hashes/blake2s.js +24 -0
  481. package/node_modules/@noble/hashes/blake2s.js.map +1 -0
  482. package/node_modules/@noble/hashes/blake3.d.ts +54 -0
  483. package/node_modules/@noble/hashes/blake3.d.ts.map +1 -0
  484. package/node_modules/@noble/hashes/blake3.js +255 -0
  485. package/node_modules/@noble/hashes/blake3.js.map +1 -0
  486. package/node_modules/@noble/hashes/crypto.d.ts +2 -0
  487. package/node_modules/@noble/hashes/crypto.d.ts.map +1 -0
  488. package/node_modules/@noble/hashes/crypto.js +5 -0
  489. package/node_modules/@noble/hashes/crypto.js.map +1 -0
  490. package/node_modules/@noble/hashes/cryptoNode.d.ts +2 -0
  491. package/node_modules/@noble/hashes/cryptoNode.d.ts.map +1 -0
  492. package/node_modules/@noble/hashes/cryptoNode.js +18 -0
  493. package/node_modules/@noble/hashes/cryptoNode.js.map +1 -0
  494. package/node_modules/@noble/hashes/eskdf.d.ts +47 -0
  495. package/node_modules/@noble/hashes/eskdf.d.ts.map +1 -0
  496. package/node_modules/@noble/hashes/eskdf.js +166 -0
  497. package/node_modules/@noble/hashes/eskdf.js.map +1 -0
  498. package/node_modules/@noble/hashes/esm/_assert.d.ts +17 -0
  499. package/node_modules/@noble/hashes/esm/_assert.d.ts.map +1 -0
  500. package/node_modules/@noble/hashes/esm/_assert.js +15 -0
  501. package/node_modules/@noble/hashes/esm/_assert.js.map +1 -0
  502. package/node_modules/@noble/hashes/esm/_blake.d.ts +14 -0
  503. package/node_modules/@noble/hashes/esm/_blake.d.ts.map +1 -0
  504. package/node_modules/@noble/hashes/esm/_blake.js +45 -0
  505. package/node_modules/@noble/hashes/esm/_blake.js.map +1 -0
  506. package/node_modules/@noble/hashes/esm/_md.d.ts +51 -0
  507. package/node_modules/@noble/hashes/esm/_md.d.ts.map +1 -0
  508. package/node_modules/@noble/hashes/esm/_md.js +155 -0
  509. package/node_modules/@noble/hashes/esm/_md.js.map +1 -0
  510. package/node_modules/@noble/hashes/esm/_u64.d.ts +55 -0
  511. package/node_modules/@noble/hashes/esm/_u64.d.ts.map +1 -0
  512. package/node_modules/@noble/hashes/esm/_u64.js +67 -0
  513. package/node_modules/@noble/hashes/esm/_u64.js.map +1 -0
  514. package/node_modules/@noble/hashes/esm/argon2.d.ts +32 -0
  515. package/node_modules/@noble/hashes/esm/argon2.d.ts.map +1 -0
  516. package/node_modules/@noble/hashes/esm/argon2.js +392 -0
  517. package/node_modules/@noble/hashes/esm/argon2.js.map +1 -0
  518. package/node_modules/@noble/hashes/esm/blake1.d.ts +106 -0
  519. package/node_modules/@noble/hashes/esm/blake1.d.ts.map +1 -0
  520. package/node_modules/@noble/hashes/esm/blake1.js +452 -0
  521. package/node_modules/@noble/hashes/esm/blake1.js.map +1 -0
  522. package/node_modules/@noble/hashes/esm/blake2.d.ts +116 -0
  523. package/node_modules/@noble/hashes/esm/blake2.d.ts.map +1 -0
  524. package/node_modules/@noble/hashes/esm/blake2.js +413 -0
  525. package/node_modules/@noble/hashes/esm/blake2.js.map +1 -0
  526. package/node_modules/@noble/hashes/esm/blake2b.d.ts +11 -0
  527. package/node_modules/@noble/hashes/esm/blake2b.d.ts.map +1 -0
  528. package/node_modules/@noble/hashes/esm/blake2b.js +11 -0
  529. package/node_modules/@noble/hashes/esm/blake2b.js.map +1 -0
  530. package/node_modules/@noble/hashes/esm/blake2s.d.ts +20 -0
  531. package/node_modules/@noble/hashes/esm/blake2s.d.ts.map +1 -0
  532. package/node_modules/@noble/hashes/esm/blake2s.js +21 -0
  533. package/node_modules/@noble/hashes/esm/blake2s.js.map +1 -0
  534. package/node_modules/@noble/hashes/esm/blake3.d.ts +54 -0
  535. package/node_modules/@noble/hashes/esm/blake3.d.ts.map +1 -0
  536. package/node_modules/@noble/hashes/esm/blake3.js +251 -0
  537. package/node_modules/@noble/hashes/esm/blake3.js.map +1 -0
  538. package/node_modules/@noble/hashes/esm/crypto.d.ts +2 -0
  539. package/node_modules/@noble/hashes/esm/crypto.d.ts.map +1 -0
  540. package/node_modules/@noble/hashes/esm/crypto.js +2 -0
  541. package/node_modules/@noble/hashes/esm/crypto.js.map +1 -0
  542. package/node_modules/@noble/hashes/esm/cryptoNode.d.ts +2 -0
  543. package/node_modules/@noble/hashes/esm/cryptoNode.d.ts.map +1 -0
  544. package/node_modules/@noble/hashes/esm/cryptoNode.js +15 -0
  545. package/node_modules/@noble/hashes/esm/cryptoNode.js.map +1 -0
  546. package/node_modules/@noble/hashes/esm/eskdf.d.ts +47 -0
  547. package/node_modules/@noble/hashes/esm/eskdf.d.ts.map +1 -0
  548. package/node_modules/@noble/hashes/esm/eskdf.js +160 -0
  549. package/node_modules/@noble/hashes/esm/eskdf.js.map +1 -0
  550. package/node_modules/@noble/hashes/esm/hkdf.d.ts +36 -0
  551. package/node_modules/@noble/hashes/esm/hkdf.d.ts.map +1 -0
  552. package/node_modules/@noble/hashes/esm/hkdf.js +82 -0
  553. package/node_modules/@noble/hashes/esm/hkdf.js.map +1 -0
  554. package/node_modules/@noble/hashes/esm/hmac.d.ts +35 -0
  555. package/node_modules/@noble/hashes/esm/hmac.d.ts.map +1 -0
  556. package/node_modules/@noble/hashes/esm/hmac.js +86 -0
  557. package/node_modules/@noble/hashes/esm/hmac.js.map +1 -0
  558. package/node_modules/@noble/hashes/esm/index.d.ts +2 -0
  559. package/node_modules/@noble/hashes/esm/index.d.ts.map +1 -0
  560. package/node_modules/@noble/hashes/esm/index.js +33 -0
  561. package/node_modules/@noble/hashes/esm/index.js.map +1 -0
  562. package/node_modules/@noble/hashes/esm/legacy.d.ts +71 -0
  563. package/node_modules/@noble/hashes/esm/legacy.d.ts.map +1 -0
  564. package/node_modules/@noble/hashes/esm/legacy.js +281 -0
  565. package/node_modules/@noble/hashes/esm/legacy.js.map +1 -0
  566. package/node_modules/@noble/hashes/esm/package.json +10 -0
  567. package/node_modules/@noble/hashes/esm/pbkdf2.d.ts +23 -0
  568. package/node_modules/@noble/hashes/esm/pbkdf2.d.ts.map +1 -0
  569. package/node_modules/@noble/hashes/esm/pbkdf2.js +97 -0
  570. package/node_modules/@noble/hashes/esm/pbkdf2.js.map +1 -0
  571. package/node_modules/@noble/hashes/esm/ripemd160.d.ts +13 -0
  572. package/node_modules/@noble/hashes/esm/ripemd160.d.ts.map +1 -0
  573. package/node_modules/@noble/hashes/esm/ripemd160.js +13 -0
  574. package/node_modules/@noble/hashes/esm/ripemd160.js.map +1 -0
  575. package/node_modules/@noble/hashes/esm/scrypt.d.ts +34 -0
  576. package/node_modules/@noble/hashes/esm/scrypt.d.ts.map +1 -0
  577. package/node_modules/@noble/hashes/esm/scrypt.js +228 -0
  578. package/node_modules/@noble/hashes/esm/scrypt.js.map +1 -0
  579. package/node_modules/@noble/hashes/esm/sha1.d.ts +11 -0
  580. package/node_modules/@noble/hashes/esm/sha1.d.ts.map +1 -0
  581. package/node_modules/@noble/hashes/esm/sha1.js +11 -0
  582. package/node_modules/@noble/hashes/esm/sha1.js.map +1 -0
  583. package/node_modules/@noble/hashes/esm/sha2.d.ts +159 -0
  584. package/node_modules/@noble/hashes/esm/sha2.d.ts.map +1 -0
  585. package/node_modules/@noble/hashes/esm/sha2.js +375 -0
  586. package/node_modules/@noble/hashes/esm/sha2.js.map +1 -0
  587. package/node_modules/@noble/hashes/esm/sha256.d.ts +20 -0
  588. package/node_modules/@noble/hashes/esm/sha256.d.ts.map +1 -0
  589. package/node_modules/@noble/hashes/esm/sha256.js +20 -0
  590. package/node_modules/@noble/hashes/esm/sha256.js.map +1 -0
  591. package/node_modules/@noble/hashes/esm/sha3-addons.d.ts +142 -0
  592. package/node_modules/@noble/hashes/esm/sha3-addons.d.ts.map +1 -0
  593. package/node_modules/@noble/hashes/esm/sha3-addons.js +393 -0
  594. package/node_modules/@noble/hashes/esm/sha3-addons.js.map +1 -0
  595. package/node_modules/@noble/hashes/esm/sha3.d.ts +53 -0
  596. package/node_modules/@noble/hashes/esm/sha3.d.ts.map +1 -0
  597. package/node_modules/@noble/hashes/esm/sha3.js +234 -0
  598. package/node_modules/@noble/hashes/esm/sha3.js.map +1 -0
  599. package/node_modules/@noble/hashes/esm/sha512.d.ts +26 -0
  600. package/node_modules/@noble/hashes/esm/sha512.d.ts.map +1 -0
  601. package/node_modules/@noble/hashes/esm/sha512.js +26 -0
  602. package/node_modules/@noble/hashes/esm/sha512.js.map +1 -0
  603. package/node_modules/@noble/hashes/esm/utils.d.ts +161 -0
  604. package/node_modules/@noble/hashes/esm/utils.d.ts.map +1 -0
  605. package/node_modules/@noble/hashes/esm/utils.js +281 -0
  606. package/node_modules/@noble/hashes/esm/utils.js.map +1 -0
  607. package/node_modules/@noble/hashes/hkdf.d.ts +36 -0
  608. package/node_modules/@noble/hashes/hkdf.d.ts.map +1 -0
  609. package/node_modules/@noble/hashes/hkdf.js +88 -0
  610. package/node_modules/@noble/hashes/hkdf.js.map +1 -0
  611. package/node_modules/@noble/hashes/hmac.d.ts +35 -0
  612. package/node_modules/@noble/hashes/hmac.d.ts.map +1 -0
  613. package/node_modules/@noble/hashes/hmac.js +91 -0
  614. package/node_modules/@noble/hashes/hmac.js.map +1 -0
  615. package/node_modules/@noble/hashes/index.d.ts +1 -0
  616. package/node_modules/@noble/hashes/index.d.ts.map +1 -0
  617. package/node_modules/@noble/hashes/index.js +33 -0
  618. package/node_modules/@noble/hashes/index.js.map +1 -0
  619. package/node_modules/@noble/hashes/legacy.d.ts +71 -0
  620. package/node_modules/@noble/hashes/legacy.d.ts.map +1 -0
  621. package/node_modules/@noble/hashes/legacy.js +287 -0
  622. package/node_modules/@noble/hashes/legacy.js.map +1 -0
  623. package/node_modules/@noble/hashes/package.json +266 -0
  624. package/node_modules/@noble/hashes/pbkdf2.d.ts +23 -0
  625. package/node_modules/@noble/hashes/pbkdf2.d.ts.map +1 -0
  626. package/node_modules/@noble/hashes/pbkdf2.js +101 -0
  627. package/node_modules/@noble/hashes/pbkdf2.js.map +1 -0
  628. package/node_modules/@noble/hashes/ripemd160.d.ts +13 -0
  629. package/node_modules/@noble/hashes/ripemd160.d.ts.map +1 -0
  630. package/node_modules/@noble/hashes/ripemd160.js +16 -0
  631. package/node_modules/@noble/hashes/ripemd160.js.map +1 -0
  632. package/node_modules/@noble/hashes/scrypt.d.ts +34 -0
  633. package/node_modules/@noble/hashes/scrypt.d.ts.map +1 -0
  634. package/node_modules/@noble/hashes/scrypt.js +232 -0
  635. package/node_modules/@noble/hashes/scrypt.js.map +1 -0
  636. package/node_modules/@noble/hashes/sha1.d.ts +11 -0
  637. package/node_modules/@noble/hashes/sha1.d.ts.map +1 -0
  638. package/node_modules/@noble/hashes/sha1.js +14 -0
  639. package/node_modules/@noble/hashes/sha1.js.map +1 -0
  640. package/node_modules/@noble/hashes/sha2.d.ts +159 -0
  641. package/node_modules/@noble/hashes/sha2.d.ts.map +1 -0
  642. package/node_modules/@noble/hashes/sha2.js +384 -0
  643. package/node_modules/@noble/hashes/sha2.js.map +1 -0
  644. package/node_modules/@noble/hashes/sha256.d.ts +20 -0
  645. package/node_modules/@noble/hashes/sha256.d.ts.map +1 -0
  646. package/node_modules/@noble/hashes/sha256.js +23 -0
  647. package/node_modules/@noble/hashes/sha256.js.map +1 -0
  648. package/node_modules/@noble/hashes/sha3-addons.d.ts +142 -0
  649. package/node_modules/@noble/hashes/sha3-addons.d.ts.map +1 -0
  650. package/node_modules/@noble/hashes/sha3-addons.js +402 -0
  651. package/node_modules/@noble/hashes/sha3-addons.js.map +1 -0
  652. package/node_modules/@noble/hashes/sha3.d.ts +53 -0
  653. package/node_modules/@noble/hashes/sha3.d.ts.map +1 -0
  654. package/node_modules/@noble/hashes/sha3.js +239 -0
  655. package/node_modules/@noble/hashes/sha3.js.map +1 -0
  656. package/node_modules/@noble/hashes/sha512.d.ts +26 -0
  657. package/node_modules/@noble/hashes/sha512.d.ts.map +1 -0
  658. package/node_modules/@noble/hashes/sha512.js +29 -0
  659. package/node_modules/@noble/hashes/sha512.js.map +1 -0
  660. package/node_modules/@noble/hashes/src/_assert.ts +22 -0
  661. package/node_modules/@noble/hashes/src/_blake.ts +50 -0
  662. package/node_modules/@noble/hashes/src/_md.ts +176 -0
  663. package/node_modules/@noble/hashes/src/_u64.ts +91 -0
  664. package/node_modules/@noble/hashes/src/argon2.ts +497 -0
  665. package/node_modules/@noble/hashes/src/blake1.ts +534 -0
  666. package/node_modules/@noble/hashes/src/blake2.ts +486 -0
  667. package/node_modules/@noble/hashes/src/blake2b.ts +10 -0
  668. package/node_modules/@noble/hashes/src/blake2s.ts +20 -0
  669. package/node_modules/@noble/hashes/src/blake3.ts +272 -0
  670. package/node_modules/@noble/hashes/src/crypto.ts +9 -0
  671. package/node_modules/@noble/hashes/src/cryptoNode.ts +15 -0
  672. package/node_modules/@noble/hashes/src/eskdf.ts +187 -0
  673. package/node_modules/@noble/hashes/src/hkdf.ts +88 -0
  674. package/node_modules/@noble/hashes/src/hmac.ts +94 -0
  675. package/node_modules/@noble/hashes/src/index.ts +31 -0
  676. package/node_modules/@noble/hashes/src/legacy.ts +293 -0
  677. package/node_modules/@noble/hashes/src/pbkdf2.ts +122 -0
  678. package/node_modules/@noble/hashes/src/ripemd160.ts +12 -0
  679. package/node_modules/@noble/hashes/src/scrypt.ts +257 -0
  680. package/node_modules/@noble/hashes/src/sha1.ts +10 -0
  681. package/node_modules/@noble/hashes/src/sha2.ts +402 -0
  682. package/node_modules/@noble/hashes/src/sha256.ts +24 -0
  683. package/node_modules/@noble/hashes/src/sha3-addons.ts +499 -0
  684. package/node_modules/@noble/hashes/src/sha3.ts +258 -0
  685. package/node_modules/@noble/hashes/src/sha512.ts +34 -0
  686. package/node_modules/@noble/hashes/src/utils.ts +395 -0
  687. package/node_modules/@noble/hashes/utils.d.ts +161 -0
  688. package/node_modules/@noble/hashes/utils.d.ts.map +1 -0
  689. package/node_modules/@noble/hashes/utils.js +313 -0
  690. package/node_modules/@noble/hashes/utils.js.map +1 -0
  691. package/package.json +179 -8
  692. package/schemas/catalog.schema.json +357 -0
  693. package/src/align.ts +239 -0
  694. package/src/audio-init-parser.ts +189 -0
  695. package/src/audio-ring-buffer.ts +120 -0
  696. package/src/authored-timing.ts +63 -0
  697. package/src/block-policy.ts +903 -0
  698. package/src/carp-catalog.ts +1065 -0
  699. package/src/catalog-fec-params.ts +729 -0
  700. package/src/catalog-network-source.ts +74 -0
  701. package/src/catalog-validator.ts +34 -0
  702. package/src/cmaf-block-assembler.ts +1255 -0
  703. package/src/cmaf-group-batcher.ts +104 -0
  704. package/src/cmcd-producer.ts +329 -0
  705. package/src/codec-utils.ts +1984 -0
  706. package/src/conceal-timeline.ts +293 -0
  707. package/src/delivery-gap.ts +147 -0
  708. package/src/duplicate-ledger.ts +372 -0
  709. package/src/fec-codec.ts +61 -0
  710. package/src/fec-manager.ts +4298 -0
  711. package/src/fec-starvation-detector.ts +128 -0
  712. package/src/fec-state.ts +219 -0
  713. package/src/fec-worker-setup.ts +283 -0
  714. package/src/fmp4-completion.ts +47 -0
  715. package/src/fmp4-reader.ts +112 -0
  716. package/src/index.ts +590 -21
  717. package/src/iso-block-locator.ts +329 -0
  718. package/src/iso-bmff-timing.ts +813 -0
  719. package/src/loc.ts +128 -154
  720. package/src/manifest-auth-plan.ts +107 -0
  721. package/src/media-router.ts +841 -0
  722. package/src/mfu-reassembler.ts +3480 -155
  723. package/src/mfu-reassembly-policy.ts +134 -0
  724. package/src/mmtp-container-parser.ts +2380 -0
  725. package/src/mmtp-decode-pipeline.ts +406 -0
  726. package/src/mmtp-router.ts +4860 -0
  727. package/src/mmtp-to-cmaf.ts +977 -0
  728. package/src/multicast-auth-catalog.ts +340 -0
  729. package/src/multicast-input.ts +793 -0
  730. package/src/multicast-manager.ts +2783 -0
  731. package/src/multicast-transport.ts +1058 -0
  732. package/src/multicast-unwrap.ts +132 -0
  733. package/src/no-modules.ts +21 -0
  734. package/src/phase14-catalog-override.ts +336 -0
  735. package/src/repair-fetch.ts +772 -0
  736. package/src/repair-layers.ts +533 -0
  737. package/src/sample-combiner.ts +938 -0
  738. package/src/signaling.ts +78 -0
  739. package/src/source-auth.ts +1 -0
  740. package/src/switching-set-alignment.ts +109 -0
  741. package/src/timestamp-codec.ts +265 -0
  742. package/src/track-pipeline-setup.ts +205 -0
  743. package/src/track-pipeline.ts +332 -0
  744. package/src/track-session.ts +1010 -0
  745. package/src/transport-pool.ts +128 -0
  746. package/src/wasm-mfu-reassembler.ts +405 -0
  747. package/src/wasm-mmtp-container-parser.ts +23 -0
  748. package/test-vectors/align.json +199 -0
  749. package/test-vectors/catalog/README.md +106 -0
  750. package/test-vectors/catalog/negative/archive-origin-with-path.json +33 -0
  751. package/test-vectors/catalog/negative/archive-unknown-field.json +34 -0
  752. package/test-vectors/catalog/negative/fec-block-profile-missing.json +51 -0
  753. package/test-vectors/catalog/negative/fec-block-profile-unknown.json +52 -0
  754. package/test-vectors/catalog/negative/fec-enhancement-repair-removed.json +28 -0
  755. package/test-vectors/catalog/negative/fec-repair-layer-geometry.json +33 -0
  756. package/test-vectors/catalog/negative/fec-repair-layer-missing-symbols.json +31 -0
  757. package/test-vectors/catalog/negative/fec-repair-multiple-depends.json +32 -0
  758. package/test-vectors/catalog/negative/fec-repair-overlay-with-layer.json +34 -0
  759. package/test-vectors/catalog/negative/fec-repair-priority-out-of-band.json +24 -0
  760. package/test-vectors/catalog/negative/fec-repair-source-symbols-without-scope.json +33 -0
  761. package/test-vectors/catalog/negative/legacy-selection-params.json +15 -0
  762. package/test-vectors/catalog/negative/media-track-repair-layer.json +16 -0
  763. package/test-vectors/catalog/negative/missing-mmtp-fields.json +12 -0
  764. package/test-vectors/catalog/negative/multicast-auth-padded-key.json +37 -0
  765. package/test-vectors/catalog/negative/multicast-auth-reused-track-format.json +53 -0
  766. package/test-vectors/catalog/negative/multicast-auth-trailing-pad-bits.json +37 -0
  767. package/test-vectors/catalog/negative/multicast-endpoint-missing-protocol-and-source.json +24 -0
  768. package/test-vectors/catalog/negative/multicast-network-source-empty.json +44 -0
  769. package/test-vectors/catalog/negative/multicast-packet-id-signaling.json +26 -0
  770. package/test-vectors/catalog/negative/network-source-object.json +25 -0
  771. package/test-vectors/catalog/negative/raptorq-source-symbols-over-max.json +24 -0
  772. package/test-vectors/catalog/negative/raptorq-unaligned-symbol.json +27 -0
  773. package/test-vectors/catalog/negative/repair-track-legacy-shape.json +19 -0
  774. package/test-vectors/catalog/negative/track-role-empty.json +16 -0
  775. package/test-vectors/catalog/negative/track-role-non-string.json +16 -0
  776. package/test-vectors/catalog/positive/archive-origin.json +34 -0
  777. package/test-vectors/catalog/positive/fec-iso-ssbg1.json +52 -0
  778. package/test-vectors/catalog/positive/fec-layered-repair.json +106 -0
  779. package/test-vectors/catalog/positive/fec-multicast.json +52 -0
  780. package/test-vectors/catalog/positive/flat-av.json +30 -0
  781. package/test-vectors/catalog/positive/multicast-auth-rotation.json +55 -0
  782. package/test-vectors/catalog/positive/multicast-native-ssm-no-network-source.json +43 -0
  783. package/test-vectors/catalog/positive/ticks-and-mixed-timescales.json +39 -0
  784. package/test-vectors/catalog/positive/track-role.json +49 -0
  785. package/test-vectors/catalog/releases/moqcast-native-v16-v1/catalog.json +65 -0
  786. package/test-vectors/catalog/releases/moqcast-native-v16-v1.archive.sha256 +1 -0
  787. package/test-vectors/catalog-multicast-auth-v1.json +26 -0
  788. package/test-vectors/catalog-validation.json +732 -0
  789. package/test-vectors/catalog-validator-public-api.mjs +25 -0
  790. package/test-vectors/generate-source-auth-fixture.mjs +114 -0
  791. package/test-vectors/hevc-x265-repeat-headers-v1.json +40 -0
  792. package/test-vectors/source-auth-v1.json +61 -0
  793. package/test-vectors/source-contiguity-v1.json +131 -0
  794. package/test-vectors/subsample-placement-v1.json +230 -0
  795. package/dist/mmtp.d.ts +0 -73
  796. package/dist/mmtp.d.ts.map +0 -1
  797. package/dist/mmtp.js +0 -210
  798. package/dist/mmtp.js.map +0 -1
  799. package/src/mmtp.ts +0 -277
@@ -0,0 +1,1255 @@
1
+ /**
2
+ * FEC-aware CMAF sample assembler for MSE multicast.
3
+ *
4
+ * Emits source frames on arrival and FEC-recovered frames in media order.
5
+ * Nothing is synthesised for a lost video block: the sink holds the last good
6
+ * frame (HoldLastTimeline). A lost audio span is concealed only when libmmt's
7
+ * release gate decided it (`gapBefore` with reason `audio-gap`), by repeating
8
+ * the last good access unit into each missing slot (AudioGapConcealer).
9
+ *
10
+ * One assembler instance per track (video or audio). MulticastManager owns
11
+ * these instances and calls them directly with SBN/ESI from the FEC pipeline.
12
+ */
13
+
14
+ import {
15
+ encodeDataSegment,
16
+ buildVideoInitSegment,
17
+ buildHevcVideoInitSegment,
18
+ buildAudioInitSegment,
19
+ normalizeAacSampleForCmaf,
20
+ } from './mmtp-to-cmaf.js'
21
+ import { AudioGapConcealer } from './conceal-timeline.js'
22
+ import type { FrameGapDecision } from './block-policy.js'
23
+ import {
24
+ classifyH264Keyframe,
25
+ detectH264Keyframe,
26
+ hevcNalUnitType,
27
+ isAnnexB,
28
+ isCompleteAvccSample,
29
+ prepareHevcCmafSample,
30
+ splitAnnexBNalUnits,
31
+ splitAvccNalUnits,
32
+ splitH264SampleNalUnits,
33
+ videoCodecFamily,
34
+ videoSampleEntryFromCodecString,
35
+ type VideoCodecFamily,
36
+ type VideoSampleEntry,
37
+ } from './codec-utils.js'
38
+ import {
39
+ scaleAuthoredTicks,
40
+ scaleAuthoredTiming,
41
+ type AuthoredTiming,
42
+ } from './authored-timing.js'
43
+ import type { MmtpDeliveryProvenance } from './mfu-reassembler.js'
44
+
45
+ const INT32_MIN = -0x80000000
46
+ const INT32_MAX = 0x7fffffff
47
+
48
+ interface BlockFrame {
49
+ data: Uint8Array
50
+ timestamp: number
51
+ keyframe: boolean
52
+ /** True only for locally generated concealment frames. */
53
+ synthetic?: boolean
54
+ /** Raw MMTP short-NTP header timestamp; never used for CMAF timing. */
55
+ mmtpTimestamp?: bigint
56
+ /** Exact ISO-BMFF timing retained from the parser for FEC/source ordering. */
57
+ authoredTiming?: AuthoredTiming
58
+ /** MMTP packet_sequence_number identifying the delivered access unit. */
59
+ packetSequenceNumber?: number
60
+ /** Every authoritative MMTP source-packet sequence that formed this sample. */
61
+ packetSequenceNumbers?: number[]
62
+ /** Subset of packetSequenceNumbers reconstructed by FEC. */
63
+ repairedPacketSequenceNumbers?: number[]
64
+ /** Native MMTP MPU group coordinate retained across source/FEC ordering. */
65
+ mpuSequenceNumber?: number
66
+ /** Timed-MFU sample identity; absent when the MFU header is untimed. */
67
+ movieFragmentSequenceNumber?: number
68
+ sampleNumber?: number
69
+ catalogTrackName?: string
70
+ /**
71
+ * Whole-frame delivery verdict folded across every contributing fragment.
72
+ * Absent means no caller declared one; it is never an implied 'multicast'.
73
+ */
74
+ deliveryProvenance?: MmtpDeliveryProvenance
75
+ /** libmmt's stall/conceal decision for the gap before this frame. */
76
+ gapBefore?: FrameGapDecision
77
+ }
78
+
79
+ export interface CmafBlockSample {
80
+ data: Uint8Array
81
+ timestamp: number
82
+ duration: number
83
+ keyframe: boolean
84
+ /**
85
+ * True only for locally generated concealment samples. These samples carry
86
+ * codec bytes and a media timestamp, but no authored MMTP identity; object
87
+ * consumers must not validate them as source MFUs.
88
+ */
89
+ synthetic?: boolean
90
+ /**
91
+ * Raw MMTP short-NTP header timestamp retained for timing telemetry.
92
+ * This is intentionally separate from the authored media timestamp above.
93
+ */
94
+ mmtpTimestamp?: bigint
95
+ /** Signed PTS-DTS offset in the configured CMAF timescale. */
96
+ compositionTimeOffset?: number
97
+ /** Exact ISO-BMFF timing in the media track's native timescale. */
98
+ authoredTiming?: AuthoredTiming
99
+ /** MMTP packet_sequence_number identifying the delivered access unit. */
100
+ packetSequenceNumber?: number
101
+ /** Every authoritative MMTP source-packet sequence that formed this sample. */
102
+ packetSequenceNumbers?: number[]
103
+ /** Subset of packetSequenceNumbers reconstructed by FEC. */
104
+ repairedPacketSequenceNumbers?: number[]
105
+ /** Native MMTP MPU group coordinate retained for exact replay selection. */
106
+ mpuSequenceNumber?: number
107
+ /**
108
+ * Timed-MFU sample identity `(movie_fragment_sequence_number,
109
+ * sample_number)` from the MFU data-unit header, carried alongside
110
+ * `mpuSequenceNumber` so a consumer can address the sample by its native
111
+ * MMTP coordinates. Absent when the MFU header is untimed.
112
+ */
113
+ movieFragmentSequenceNumber?: number
114
+ sampleNumber?: number
115
+ /** Immutable catalog identity supplied by the owning ingress subscription. */
116
+ catalogTrackName?: string
117
+ /**
118
+ * Whole-frame delivery verdict, carried so MSE `onSample` consumers can see
119
+ * the same evidence the non-MSE frame path gets. Without it the MSE branch
120
+ * silently loses a computed 'mixed' or 'multicast' finding.
121
+ */
122
+ deliveryProvenance?: MmtpDeliveryProvenance
123
+ /**
124
+ * libmmt's stall/conceal decision for the gap before this sample
125
+ * (`RoutedFrameMeta.gapBefore`). MSE sinks feed it to HoldLastTimeline.
126
+ */
127
+ gapBefore?: FrameGapDecision
128
+ }
129
+
130
+ export type CmafSampleOrderPolicy =
131
+ | { mode: 'arrival' }
132
+ | {
133
+ /** Release samples according to media progression, without a wall clock. */
134
+ mode: 'media-window'
135
+ /** Delivery window in the same units as CmafBlockSample.timestamp. */
136
+ deliveryWindow: number
137
+ /** Optional modulo period for wrapped input timestamps, in timestamp units. */
138
+ timestampWrapPeriod?: number
139
+ }
140
+
141
+ export interface CmafSampleOrderStats {
142
+ staleSamples: number
143
+ duplicateSamples: number
144
+ preRapDeadlineDrops: number
145
+ noRapFlushDrops: number
146
+ forcedReleases: number
147
+ /**
148
+ * Samples refused because they carried `authoredTiming` while this track's
149
+ * `admitAuthoredTiming` was false. Non-zero means the contract rollback
150
+ * switch is engaged AND the producer is still sending authored batches —
151
+ * a rollback is meant to be paired with that producer reverting to raw.
152
+ */
153
+ unadmittedAuthoredSamples: number
154
+ /**
155
+ * Video samples refused because their bitstream could not be read: HEVC
156
+ * whose framing is neither a complete 4-byte length-prefixed sample nor
157
+ * Annex B, or that holds no NAL unit to write. Writing them would put bytes
158
+ * the hvcC's lengthSizeMinusOne = 3 does not describe into the mdat.
159
+ */
160
+ unreadableVideoSamples: number
161
+ }
162
+
163
+ /**
164
+ * Cumulative counters of what the assembler emitted and which block events
165
+ * it saw. `emits` counts emit calls (one per direct frame, recovered block,
166
+ * recovered drain or block flush); `samples` and `keyframes` count the
167
+ * samples those calls carried.
168
+ */
169
+ export interface CmafEmitStats {
170
+ emits: number
171
+ samples: number
172
+ keyframes: number
173
+ addedFrames: number
174
+ recoveredBlocks: number
175
+ completedBlocks: number
176
+ failedBlocks: number
177
+ }
178
+
179
+ /**
180
+ * Cumulative audio gap concealment counters since construction. Every audio
181
+ * gap decision the assembler sees lands in exactly one of the gap counters.
182
+ */
183
+ export interface CmafAudioConcealStats {
184
+ /** Last-good AUs written into the slots of `audio-gap` decisions. */
185
+ repeatedUnits: number
186
+ /**
187
+ * Gap decisions re-anchored at the next AU by design: an
188
+ * `audio-discontinuity`, or no good AU emitted yet.
189
+ */
190
+ reanchoredGaps: number
191
+ /**
192
+ * `audio-gap` decisions that could not be sized and were re-anchored
193
+ * instead: the AU after the gap, or the last good AU, carried no authored
194
+ * ISO-BMFF timing, or the two were authored in different media timescales.
195
+ * libmmt only decides an `audio-gap` from authored ticks (`decideGap`), so
196
+ * non-zero means a caller handed the assembler a decision without the
197
+ * timing it was computed from.
198
+ */
199
+ untimedGaps: number
200
+ }
201
+
202
+ export interface BlockAssemblerConfig {
203
+ /** Number of source symbols per FEC block */
204
+ k: number
205
+ /** Timescale for CMAF segments (default 1_000_000 = microseconds) */
206
+ timescale?: number
207
+ /** ISO track ID (default 1) */
208
+ trackId?: number
209
+ /** Track type — determines init segment format and audio concealment */
210
+ trackType: 'video' | 'audio'
211
+ /** Video/audio codec string (e.g. 'avc1.64002a', 'mp4a.40.2'). */
212
+ codec?: string
213
+ // Video config (required when trackType='video')
214
+ /** Raw avcC payload from catalog description — for the init segment */
215
+ avcC?: Uint8Array
216
+ /** Raw hvcC payload for an HEVC init segment (e.g. built from in-band
217
+ * VPS/SPS/PPS by `generateHvcCFromParameterSets`). Requires `codec` to name
218
+ * the `hev1` or `hvc1` sample entry. */
219
+ hvcC?: Uint8Array
220
+ /** Video width in pixels */
221
+ width?: number
222
+ /** Video height in pixels */
223
+ height?: number
224
+ // Audio config (required when trackType='audio')
225
+ /** Audio codec string (e.g. 'mp4a.40.2', 'opus') */
226
+ audioCodec?: string
227
+ /** Audio sample rate (e.g. 48000) */
228
+ sampleRate?: number
229
+ /** Audio channel count (e.g. 1 or 2) */
230
+ channels?: number
231
+ /** Raw AudioSpecificConfig from catalog */
232
+ asc?: Uint8Array
233
+ // Shared
234
+ /** Frames per second — fallback for duration estimation */
235
+ fps?: number
236
+ /** Explicit sample ordering policy. Datagram/FEC callers use media-window. */
237
+ sampleOrder?: CmafSampleOrderPolicy
238
+ /**
239
+ * Bounded sample reorder depth for callback mode.
240
+ *
241
+ * Default 0 preserves immediate emission. When set on video tracks with
242
+ * onSample enabled, samples are sorted by timestamp and the oldest sample is
243
+ * emitted only after this many newer samples are available.
244
+ * @deprecated Use sampleOrder with an explicit policy.
245
+ */
246
+ sampleReorderWindow?: number
247
+ /**
248
+ * Authored-timing admission for this track (default `true` — admitted).
249
+ *
250
+ * This is the rollback switch named by the authored-audio-CTS contract's
251
+ * removal gate (BLO-30397). Assemblers are keyed on
252
+ * `(packetId, catalogTrackName)` (`mmtp-router.ts` `#mseAssemblerKey`), so
253
+ * this switch is per **track**. A producer feeding several tracks must be
254
+ * de-admitted on each of them: nothing applies it across a track set
255
+ * (BLO-34821).
256
+ *
257
+ * Set `false` and a sample carrying `authoredTiming` is **rejected**, not
258
+ * zeroed: the contract forbids rolling back "by zeroing already-authored
259
+ * offsets", because a zeroed offset is byte-indistinguishable from a feed
260
+ * that authored nothing (BLO-30401 measured both as 0 A/V skew). Raw samples
261
+ * — those with no `authoredTiming` at all — are unaffected and keep emitting
262
+ * a v0 trun with no composition-offset field.
263
+ */
264
+ admitAuthoredTiming?: boolean
265
+ }
266
+
267
+ interface OrderedSample extends CmafBlockSample {
268
+ advancesHorizon: boolean
269
+ }
270
+
271
+ export class CmafBlockAssembler {
272
+ #config: Required<
273
+ Pick<
274
+ BlockAssemblerConfig,
275
+ 'k' | 'timescale' | 'trackId' | 'trackType' | 'admitAuthoredTiming'
276
+ >
277
+ >
278
+ #pendingRecovered = new Map<number, BlockFrame>()
279
+ #sequence = 1
280
+ #baseTs = -1
281
+ /**
282
+ * Last decoder-proven audio AU, repeated into slots a gap decision names.
283
+ * It is noted and planned on the AU's authored clock (`AuthoredTiming`
284
+ * ticks), never on this assembler's CMAF timescale: on the default
285
+ * 1_000_000 an AAC AU is 1024e6 / sampleRate µs, which is not an integer.
286
+ */
287
+ #audioConcealer = new AudioGapConcealer<Uint8Array>()
288
+ /**
289
+ * Media timescale of the AU the concealer holds; `'untimed'` when the last
290
+ * emitted audio AU carried no authored timing, `null` before any AU.
291
+ */
292
+ #audioConcealClock: number | 'untimed' | null = null
293
+ #audioConcealStats: CmafAudioConcealStats = {
294
+ repeatedUnits: 0,
295
+ reanchoredGaps: 0,
296
+ untimedGaps: 0,
297
+ }
298
+ #frameDuration: number
299
+ #lastEmittedTs = -1
300
+ #lastSourceTs = -1
301
+ #sampleReorderWindow = 0
302
+ #sampleOrder: CmafSampleOrderPolicy = { mode: 'arrival' }
303
+ #sampleOrderCapacity = 0
304
+ #sampleReorderQueue: OrderedSample[] = []
305
+ #recoveredHorizonTs = -1
306
+ #sampleOrderStats: CmafSampleOrderStats = {
307
+ staleSamples: 0,
308
+ duplicateSamples: 0,
309
+ preRapDeadlineDrops: 0,
310
+ noRapFlushDrops: 0,
311
+ forcedReleases: 0,
312
+ unadmittedAuthoredSamples: 0,
313
+ unreadableVideoSamples: 0,
314
+ }
315
+ /** Codec family whose bitstream keyframe rule overrides the metadata flag
316
+ * (AVC IDR, HEVC IRAP), or null when the bitstream is not validated. */
317
+ #videoKeyframeFamily: VideoCodecFamily | null = null
318
+ /** HEVC sample entry chosen from the catalog codec string. */
319
+ #hevcSampleEntry: 'hev1' | 'hvc1' | null = null
320
+ #keyframeRejectDumpCount = 0
321
+
322
+ /** Callback: emits a complete moof+mdat CMAF segment */
323
+ onSegment: ((segment: Uint8Array) => void) | null = null
324
+ /** Callback: emits a gated/deduped raw sample for callers that already own the MSE timeline. */
325
+ onSample: ((sample: CmafBlockSample) => void) | null = null
326
+ /** Callback: emits an init segment (ftyp+moov) */
327
+ onInitSegment: ((init: Uint8Array) => void) | null = null
328
+
329
+ // Video keyframe gate (BLO-3035 layer 3): Chrome's CHUNK_DEMUXER rejects a
330
+ // moof+mdat whose first sample is non-sync with no prior reference frames
331
+ // ("CHUNK_DEMUXER_ERROR_APPEND_FAILED: Failed to prepare video sample for
332
+ // decode") and detaches the SourceBuffer for the rest of the session.
333
+ // Mid-stream join almost guarantees the first FEC blocks are mid-GOP — all
334
+ // delta frames. Gate emission until the first block containing an IDR;
335
+ // within that block, splice samples to start at the IDR index. Audio passes
336
+ // unconditionally — valid for the codecs supported here (AAC, Opus) where
337
+ // every frame is independently decodable. SBR-only AAC, USAC, or HE-AAC v2
338
+ // with PCE re-entry would need a similar gate.
339
+ #armedVideo = false
340
+
341
+ /** Truncate `frames` to start at the first keyframe for video tracks before
342
+ * the first emission. Returns the (possibly spliced) frames, or null to
343
+ * drop the block entirely. Audio + already-armed video: identity. */
344
+ #applyVideoKeyframeGate<T extends { data: Uint8Array; keyframe: boolean }>(frames: T[]): T[] | null {
345
+ const keyedFrames = this.#normalizeVideoKeyframes(frames)
346
+ if (this.#config.trackType !== 'video' || this.#armedVideo) return keyedFrames
347
+ const firstKfIdx = keyedFrames.findIndex(f => f.keyframe)
348
+ if (firstKfIdx < 0) return null
349
+ return firstKfIdx === 0 ? keyedFrames : keyedFrames.slice(firstKfIdx)
350
+ }
351
+
352
+ #normalizeVideoKeyframes<T extends { data: Uint8Array; keyframe: boolean }>(frames: T[]): T[] {
353
+ if (this.#config.trackType !== 'video' || this.#videoKeyframeFamily === null) return frames
354
+ const out: T[] = []
355
+ for (const frame of frames) {
356
+ const effective = this.#withEffectiveVideoKeyframe(frame)
357
+ if (effective !== null) out.push(effective)
358
+ }
359
+ return out
360
+ }
361
+
362
+ /** The frame with its bitstream keyframe (and, for HEVC, mdat framing);
363
+ * null when the frame is refused and must not be emitted. */
364
+ #withEffectiveVideoKeyframe<T extends { data: Uint8Array; keyframe: boolean }>(frame: T): T | null {
365
+ if (this.#config.trackType !== 'video' || this.#videoKeyframeFamily === null) return frame
366
+ if (this.#videoKeyframeFamily === 'hevc') {
367
+ // HEVC keyframe = IRAP (H.265 Table 7-1). The mdat carries 4-byte
368
+ // length-prefixed NAL units to match the hvcC's lengthSizeMinusOne = 3;
369
+ // normalization is idempotent, so a frame seen twice is unchanged. A
370
+ // frame that cannot be read is refused, not written as-is and not
371
+ // passed off as a delta frame.
372
+ const prepared = prepareHevcCmafSample(frame.data, this.#hevcSampleEntry!)
373
+ if (prepared === null) {
374
+ this.#sampleOrderStats.unreadableVideoSamples++
375
+ return null
376
+ }
377
+ const { keyframe, data } = prepared
378
+ if (!keyframe) this.#dumpRejectedVideoKeyframe(frame.data, frame.keyframe)
379
+ return keyframe === frame.keyframe && data === frame.data ? frame : { ...frame, keyframe, data }
380
+ }
381
+ const keyframe = detectH264Keyframe(frame.data)
382
+ if (!keyframe) this.#dumpRejectedVideoKeyframe(frame.data, frame.keyframe)
383
+ return keyframe === frame.keyframe ? frame : { ...frame, keyframe }
384
+ }
385
+
386
+ #dumpRejectedVideoKeyframe(data: Uint8Array, metadataKeyframe: boolean): void {
387
+ if (this.#keyframeRejectDumpCount >= 12) return
388
+ this.#keyframeRejectDumpCount++
389
+ if (this.#videoKeyframeFamily === 'hevc') {
390
+ const nals = isCompleteAvccSample(data)
391
+ ? splitAvccNalUnits(data)
392
+ : isAnnexB(data) ? splitAnnexBNalUnits(data) : []
393
+ console.log(
394
+ `[L4-KF-GATE] reject#${this.#keyframeRejectDumpCount} len=${data.length} ` +
395
+ `metadataKf=${metadataKeyframe} family=hevc ` +
396
+ `nalTypes=[${nals.slice(0, 16).map((nal) => (nal.length >= 2 ? hevcNalUnitType(nal) : -1)).join(',')}]`,
397
+ )
398
+ return
399
+ }
400
+ const sample = splitH264SampleNalUnits(data)
401
+ const nalTypes = describeH264NalTypes(sample.nals)
402
+ const classify = classifyH264Keyframe(data)
403
+ const hex = Array.from(data.subarray(0, Math.min(48, data.length)))
404
+ .map(b => (b as number).toString(16).padStart(2, '0'))
405
+ .join(' ')
406
+ console.log(
407
+ `[L4-KF-GATE] reject#${this.#keyframeRejectDumpCount} len=${data.length} ` +
408
+ `metadataKf=${metadataKeyframe} classify=${classify} format=${sample.format} ` +
409
+ `nalTypes=[${nalTypes.join(',')}] first48=[${hex}]`,
410
+ )
411
+ }
412
+
413
+ /** Mark video as already synchronized by an external decoder path.
414
+ * Used by MoQ→multicast MSE continuity when MoQ has already appended a
415
+ * keyframe to the same SourceBuffer timeline before multicast takeover. */
416
+ markVideoSynced(): void {
417
+ if (this.#config.trackType === 'video') this.#armedVideo = true
418
+ }
419
+
420
+ /** Emit each frame as its own single-sample moof+mdat segment. Matches the
421
+ * case-20 path (`MmtpToCmaf.wrapVideoSample` → `encodeDataSegment`) byte-
422
+ * for-byte per frame. Working hypothesis (pending Chromium-source
423
+ * validation against `media/filters/chunk_demuxer.cc`):
424
+ * `encodeMultiSampleSegment` blobs are accepted by ChunkDemuxer in this
425
+ * pipeline but only the first sample renders for live, possibly because
426
+ * the pipeline expects per-frame moof boundaries. Track in BLO-3035.
427
+ *
428
+ * Stale-tfdt defense-in-depth: drops any frame whose timestamp is older
429
+ * than `#lastEmittedTs`. The SBN watermark already prevents out-of-order
430
+ * FEC-block emissions, but `addBypassFrame` (oversized MFU / no-FEC path)
431
+ * doesn't touch the watermark — a bypass frame at t=T followed by a FEC
432
+ * block whose frames precede T would otherwise inject earlier tfdt and
433
+ * detach the SourceBuffer. */
434
+ #ordersSamples(): boolean {
435
+ return this.#sampleOrder.mode === 'media-window' || this.#sampleReorderWindow > 0
436
+ }
437
+
438
+ #unwrapTimestamp(timestamp: number): number {
439
+ const wrapPeriod = this.#sampleOrder.mode === 'media-window'
440
+ ? this.#sampleOrder.timestampWrapPeriod
441
+ : undefined
442
+ if (!wrapPeriod) return timestamp
443
+ const reference = this.#lastSourceTs >= 0
444
+ ? this.#lastSourceTs
445
+ : this.#recoveredHorizonTs >= 0
446
+ ? this.#recoveredHorizonTs
447
+ : this.#lastEmittedTs
448
+ if (reference < 0) return timestamp
449
+ return timestamp + Math.round((reference - timestamp) / wrapPeriod) * wrapPeriod
450
+ }
451
+
452
+ #emitSample(
453
+ data: Uint8Array,
454
+ timestamp: number,
455
+ duration: number,
456
+ keyframe: boolean,
457
+ advancesHorizon: boolean,
458
+ catalogTrackName: string | undefined,
459
+ mpuSequenceNumber: number | undefined,
460
+ packetSequenceNumber: number | undefined,
461
+ packetSequenceNumbers: number[] | undefined,
462
+ repairedPacketSequenceNumbers: number[] | undefined,
463
+ authoredTiming: AuthoredTiming | undefined,
464
+ // Required, not optional: an omitted optional argument is silently
465
+ // undefined, which is exactly how this field went missing from the
466
+ // recovered path in the first place. Callers with nothing to declare pass
467
+ // `undefined` on purpose.
468
+ deliveryProvenance: MmtpDeliveryProvenance | undefined,
469
+ /** Raw MMTP short-NTP header timestamp for telemetry only. */
470
+ mmtpTimestamp: bigint | undefined,
471
+ // Same rule as deliveryProvenance: required so a caller cannot drop the
472
+ // timed-MFU identity by omission. Untimed MFUs pass `undefined`.
473
+ movieFragmentSequenceNumber: number | undefined,
474
+ sampleNumber: number | undefined,
475
+ /** True only for locally generated concealment samples. */
476
+ synthetic: boolean | undefined,
477
+ /** libmmt's decision for the gap before this sample, carried to sinks. */
478
+ gapBefore: FrameGapDecision | undefined,
479
+ ): void {
480
+ // Authored-timing admission — the rollback switch the BLO-30397 removal
481
+ // gate names. Refuse the sample outright rather than stripping its offset:
482
+ // the contract forbids rolling back "by zeroing already-authored offsets",
483
+ // and BLO-30401 measured why — a zeroed offset and a never-authored one are
484
+ // behaviourally identical downstream (same buffered ranges, same duration,
485
+ // no diagnostic), so a silent strip would look exactly like success while
486
+ // audio ran early forever. A de-admitted producer is expected to revert to
487
+ // raw batches, which are untouched by this branch.
488
+ if (authoredTiming !== undefined && !this.#config.admitAuthoredTiming) {
489
+ this.#sampleOrderStats.unadmittedAuthoredSamples++
490
+ return
491
+ }
492
+ const scaledTiming = authoredTiming === undefined
493
+ ? null
494
+ : scaleAuthoredTiming(authoredTiming, this.#config.timescale)
495
+ if (authoredTiming !== undefined && scaledTiming === null) return
496
+ const authoredTimestamp = scaledTiming?.timestamp ?? timestamp
497
+ const authoredDuration = scaledTiming?.duration ?? duration
498
+ let compositionTimeOffset: number | undefined
499
+ if (authoredTiming !== undefined) {
500
+ const scaledOffset = scaleAuthoredTicks(
501
+ authoredTiming.presentationTime - authoredTiming.decodeTime,
502
+ authoredTiming.mediaTimescale,
503
+ this.#config.timescale,
504
+ )
505
+ if (scaledOffset === null) return
506
+ // trun stores composition offsets as integer target-timescale ticks.
507
+ // Preserve the nearest representable tick, then enforce the signed
508
+ // int32 serialization range on the rounded value.
509
+ const roundedOffset = Math.round(scaledOffset)
510
+ if (
511
+ !Number.isSafeInteger(roundedOffset) ||
512
+ roundedOffset < INT32_MIN ||
513
+ roundedOffset > INT32_MAX
514
+ ) return
515
+ compositionTimeOffset = roundedOffset
516
+ }
517
+ const unwrappedTimestamp = this.#unwrapTimestamp(authoredTimestamp)
518
+ if (unwrappedTimestamp <= this.#lastEmittedTs) {
519
+ this.#sampleOrderStats.staleSamples++
520
+ return
521
+ }
522
+
523
+ const sample = this.#withEffectiveVideoKeyframe({
524
+ data,
525
+ timestamp: unwrappedTimestamp,
526
+ duration: authoredDuration,
527
+ keyframe,
528
+ ...(mmtpTimestamp === undefined ? {} : { mmtpTimestamp }),
529
+ ...(compositionTimeOffset === undefined ? {} : { compositionTimeOffset }),
530
+ advancesHorizon,
531
+ ...(authoredTiming === undefined ? {} : { authoredTiming }),
532
+ ...(packetSequenceNumber === undefined ? {} : { packetSequenceNumber }),
533
+ ...(packetSequenceNumbers === undefined ? {} : { packetSequenceNumbers }),
534
+ ...(repairedPacketSequenceNumbers === undefined
535
+ ? {}
536
+ : { repairedPacketSequenceNumbers }),
537
+ ...(mpuSequenceNumber === undefined ? {} : { mpuSequenceNumber }),
538
+ ...(movieFragmentSequenceNumber === undefined ? {} : { movieFragmentSequenceNumber }),
539
+ ...(sampleNumber === undefined ? {} : { sampleNumber }),
540
+ ...(catalogTrackName === undefined ? {} : { catalogTrackName }),
541
+ ...(deliveryProvenance === undefined ? {} : { deliveryProvenance }),
542
+ ...(synthetic === undefined ? {} : { synthetic }),
543
+ ...(gapBefore === undefined ? {} : { gapBefore }),
544
+ })
545
+ if (sample === null) return
546
+ if (advancesHorizon && unwrappedTimestamp > this.#lastSourceTs) {
547
+ this.#lastSourceTs = unwrappedTimestamp
548
+ } else if (!advancesHorizon && unwrappedTimestamp > this.#recoveredHorizonTs) {
549
+ this.#recoveredHorizonTs = unwrappedTimestamp
550
+ }
551
+
552
+ if (this.#ordersSamples()) {
553
+ this.#queueSample(sample)
554
+ return
555
+ }
556
+ this.#emitArrivalOrdered(sample)
557
+ }
558
+
559
+ #emitArrivalOrdered(sample: OrderedSample): void {
560
+ if (this.#config.trackType === 'video' && !this.#armedVideo && !sample.keyframe) {
561
+ this.#sampleOrderStats.preRapDeadlineDrops++
562
+ return
563
+ }
564
+ this.#emitSampleNow(sample)
565
+ }
566
+
567
+ #queueSample(sample: OrderedSample): void {
568
+ if (this.#sampleReorderQueue.some(s => s.timestamp === sample.timestamp)) {
569
+ this.#sampleOrderStats.duplicateSamples++
570
+ return
571
+ }
572
+ this.#sampleReorderQueue.push(sample)
573
+ this.#sampleReorderQueue.sort((a, b) => a.timestamp - b.timestamp)
574
+ this.#drainSampleReorder(false)
575
+ this.#enforceSampleOrderCapacity()
576
+ }
577
+
578
+ #releaseHorizon(): number {
579
+ return this.#lastSourceTs >= 0 ? this.#lastSourceTs : this.#recoveredHorizonTs
580
+ }
581
+
582
+ #sampleIsReleasable(sample: OrderedSample, flushAll: boolean): boolean {
583
+ if (flushAll) return true
584
+ if (this.#sampleOrder.mode === 'media-window') {
585
+ const horizon = this.#releaseHorizon()
586
+ return horizon >= 0 && sample.timestamp < horizon - this.#sampleOrder.deliveryWindow
587
+ }
588
+ return this.#sampleReorderQueue.length > this.#sampleReorderWindow
589
+ }
590
+
591
+ #dropPreRapSamples(flushAll: boolean): boolean {
592
+ if (this.#config.trackType !== 'video' || this.#armedVideo) return false
593
+
594
+ const firstRap = this.#sampleReorderQueue.findIndex(
595
+ sample => sample.keyframe && this.#sampleIsReleasable(sample, flushAll),
596
+ )
597
+ if (firstRap >= 0) {
598
+ if (firstRap > 0) {
599
+ this.#sampleOrderStats.preRapDeadlineDrops += firstRap
600
+ this.#sampleReorderQueue.splice(0, firstRap)
601
+ }
602
+ return false
603
+ }
604
+
605
+ let dropped = 0
606
+ while (
607
+ this.#sampleReorderQueue[0] &&
608
+ this.#sampleIsReleasable(this.#sampleReorderQueue[0]!, flushAll)
609
+ ) {
610
+ this.#sampleReorderQueue.shift()
611
+ dropped++
612
+ }
613
+ if (flushAll) this.#sampleOrderStats.noRapFlushDrops += dropped
614
+ else this.#sampleOrderStats.preRapDeadlineDrops += dropped
615
+ return dropped > 0
616
+ }
617
+
618
+ #drainSampleReorder(flushAll: boolean): void {
619
+ while (this.#sampleReorderQueue.length > 0) {
620
+ if (this.#dropPreRapSamples(flushAll) && this.#sampleReorderQueue.length === 0) return
621
+ const sample = this.#sampleReorderQueue[0]
622
+ if (!sample || !this.#sampleIsReleasable(sample, flushAll)) return
623
+ this.#sampleReorderQueue.shift()
624
+ this.#emitQueuedSample(sample)
625
+ }
626
+ }
627
+
628
+ #emitQueuedSample(sample: OrderedSample): void {
629
+ const next = this.#sampleReorderQueue.find(s => s.timestamp > sample.timestamp)
630
+ const duration = sample.authoredTiming
631
+ ? sample.duration
632
+ : next ? next.timestamp - sample.timestamp : sample.duration
633
+ this.#emitSampleNow({
634
+ ...sample,
635
+ duration: duration > 0
636
+ ? duration
637
+ : sample.authoredTiming ? sample.duration : this.#frameDuration,
638
+ })
639
+ }
640
+
641
+ #enforceSampleOrderCapacity(): void {
642
+ if (this.#sampleOrder.mode !== 'media-window') return
643
+ while (this.#sampleReorderQueue.length > this.#sampleOrderCapacity) {
644
+ const sample = this.#sampleReorderQueue.shift()
645
+ if (!sample) return
646
+ this.#sampleOrderStats.forcedReleases++
647
+ console.warn(
648
+ `[CmafBlockAssembler] ${this.#config.trackType} media-window queue exceeded ` +
649
+ `${this.#sampleOrderCapacity} samples; force-releasing timestamp=${sample.timestamp}`,
650
+ )
651
+ if (this.#config.trackType === 'video' && !this.#armedVideo && !sample.keyframe) {
652
+ this.#sampleOrderStats.preRapDeadlineDrops++
653
+ continue
654
+ }
655
+ this.#emitQueuedSample(sample)
656
+ }
657
+ }
658
+
659
+ #emitSampleNow(sample: CmafBlockSample): void {
660
+ if (sample.timestamp <= this.#lastEmittedTs) {
661
+ this.#sampleOrderStats.staleSamples++
662
+ return
663
+ }
664
+ this.#concealAudioGapBefore(sample)
665
+ this.#writeSampleNow(sample, true)
666
+ }
667
+
668
+ #writeSampleNow(sample: CmafBlockSample, rememberAudio: boolean): void {
669
+ const { timestamp, duration, keyframe } = sample
670
+ this.#lastEmittedTs = timestamp
671
+ if (this.#config.trackType === 'video' && keyframe) this.#armedVideo = true
672
+ const data = this.#normalizeSampleData(sample.data)
673
+ if (this.#config.trackType === 'audio' && rememberAudio && data.length > 0) {
674
+ // Keep decoder-proven codec data for concealment of a later gap that
675
+ // libmmt's release gate decided, on the AU's own authored clock.
676
+ this.#noteAudioAccessUnit(data, sample.authoredTiming)
677
+ }
678
+ if (this.onSample) {
679
+ this.onSample(data === sample.data ? sample : { ...sample, data })
680
+ } else {
681
+ const baseTime = this.#rebase(timestamp)
682
+ const segment = encodeDataSegment(
683
+ data,
684
+ baseTime,
685
+ duration,
686
+ keyframe,
687
+ this.#sequence++,
688
+ this.#config.trackId,
689
+ sample.compositionTimeOffset,
690
+ )
691
+ this.onSegment?.(segment)
692
+ }
693
+ }
694
+
695
+ /**
696
+ * Record an emitted audio AU for concealment in its authored media ticks —
697
+ * the clock libmmt's `audio-gap` decision was computed in, where an AAC AU
698
+ * is exactly 1024 ticks. An AU with no authored timing has no exact clock,
699
+ * so nothing is held for it and a later `audio-gap` is counted as untimed.
700
+ */
701
+ #noteAudioAccessUnit(data: Uint8Array, timing: AuthoredTiming | undefined): void {
702
+ if (timing === undefined) {
703
+ this.#audioConcealer.reset()
704
+ this.#audioConcealClock = 'untimed'
705
+ return
706
+ }
707
+ this.#audioConcealer.note({
708
+ payload: data,
709
+ pts: timing.presentationTime,
710
+ duration: timing.durationTicks,
711
+ })
712
+ this.#audioConcealClock = timing.mediaTimescale
713
+ }
714
+
715
+ /**
716
+ * Repeat the last good AU into exactly the slots an `audio-gap` decision
717
+ * names. A synthesised AAC access unit is not portable across every
718
+ * AudioSpecificConfig, so only known-good encoded audio is repeated; with
719
+ * no good AU yet, or on `audio-discontinuity`, the sink re-anchors at the
720
+ * next sample and nothing is written.
721
+ *
722
+ * The gap is sized in authored ticks and each slot is mapped onto this
723
+ * assembler's timescale by `scaleAuthoredTiming`, the conversion every
724
+ * source AU goes through, so a slot lands exactly where the AU it replaces
725
+ * would have. Nothing here can throw into the packet path: a gap that
726
+ * cannot be sized exactly is re-anchored and counted.
727
+ */
728
+ #concealAudioGapBefore(sample: CmafBlockSample): void {
729
+ const decision = sample.gapBefore
730
+ if (this.#config.trackType !== 'audio' || !decision || decision.trackKind !== 'audio') return
731
+ const timing = sample.authoredTiming
732
+ const clock = this.#audioConcealClock
733
+ if (
734
+ timing === undefined ||
735
+ clock === 'untimed' ||
736
+ (clock !== null && clock !== timing.mediaTimescale)
737
+ ) {
738
+ // No single authored clock covers both this AU and the one held, so
739
+ // the gap has no exact size in ticks.
740
+ if (decision.reason === 'audio-gap') this.#audioConcealStats.untimedGaps++
741
+ else this.#audioConcealStats.reanchoredGaps++
742
+ return
743
+ }
744
+ const plan = this.#audioConcealer.plan(decision, { pts: timing.presentationTime })
745
+ if (plan.kind !== 'conceal') {
746
+ this.#audioConcealStats.reanchoredGaps++
747
+ return
748
+ }
749
+ for (const slot of plan.repeat) {
750
+ // Every input here is one this sample's own timing already scaled
751
+ // successfully (same media timescale and duration, an earlier pts), so
752
+ // the conversion cannot fail for a slot.
753
+ const scaled = scaleAuthoredTiming({
754
+ decodeTime: slot.pts,
755
+ presentationTime: slot.pts,
756
+ durationTicks: slot.duration,
757
+ mediaTimescale: timing.mediaTimescale,
758
+ }, this.#config.timescale)
759
+ if (scaled === null) continue
760
+ const slotTimestamp = this.#unwrapTimestamp(scaled.timestamp)
761
+ if (slotTimestamp <= this.#lastEmittedTs || slotTimestamp >= sample.timestamp) continue
762
+ this.#writeSampleNow({
763
+ data: slot.payload.slice(),
764
+ timestamp: slotTimestamp,
765
+ duration: scaled.duration,
766
+ keyframe: true,
767
+ synthetic: true,
768
+ }, false)
769
+ this.#audioConcealStats.repeatedUnits++
770
+ }
771
+ }
772
+
773
+ #emitPerSample(
774
+ frames: BlockFrame[],
775
+ audioDurationOverride?: number,
776
+ advancesHorizon = false,
777
+ ): void {
778
+ for (let i = 0; i < frames.length; i++) {
779
+ const f = frames[i]!
780
+ // Per-frame duration from delta to next frame, or fallback.
781
+ let duration: number
782
+ if (this.#config.trackType === 'audio') {
783
+ duration = audioDurationOverride ?? this.#frameDuration
784
+ } else if (i < frames.length - 1) {
785
+ duration = frames[i + 1]!.timestamp - f.timestamp
786
+ } else if (i > 0) {
787
+ duration = f.timestamp - frames[i - 1]!.timestamp
788
+ } else {
789
+ duration = audioDurationOverride ?? this.#frameDuration
790
+ }
791
+ if (duration <= 0) duration = audioDurationOverride ?? this.#frameDuration
792
+ this.#emitSample(
793
+ f.data,
794
+ f.timestamp,
795
+ duration,
796
+ f.keyframe,
797
+ advancesHorizon,
798
+ f.catalogTrackName,
799
+ f.mpuSequenceNumber,
800
+ f.packetSequenceNumber,
801
+ f.packetSequenceNumbers,
802
+ f.repairedPacketSequenceNumbers,
803
+ f.authoredTiming,
804
+ f.deliveryProvenance,
805
+ f.mmtpTimestamp,
806
+ f.movieFragmentSequenceNumber,
807
+ f.sampleNumber,
808
+ f.synthetic,
809
+ f.gapBefore,
810
+ )
811
+ }
812
+ }
813
+
814
+ // Cumulative emit counters (see emitStats). They replace the BLO-3035 L4
815
+ // diagnostics, which hashed and hex-dumped every video keyframe and ran a
816
+ // 1 s setInterval console aggregate on the MSE path (BLO-36599).
817
+ #emitStats: CmafEmitStats = {
818
+ emits: 0,
819
+ samples: 0,
820
+ keyframes: 0,
821
+ addedFrames: 0,
822
+ recoveredBlocks: 0,
823
+ completedBlocks: 0,
824
+ failedBlocks: 0,
825
+ }
826
+
827
+ #countEmit(samples: ReadonlyArray<{ keyframe: boolean }>): void {
828
+ this.#emitStats.emits++
829
+ this.#emitStats.samples += samples.length
830
+ for (const sample of samples) if (sample.keyframe) this.#emitStats.keyframes++
831
+ }
832
+
833
+ constructor(config: BlockAssemblerConfig) {
834
+ this.#config = {
835
+ k: config.k,
836
+ timescale: config.timescale ?? 1_000_000,
837
+ trackId: config.trackId ?? 1,
838
+ trackType: config.trackType,
839
+ admitAuthoredTiming: config.admitAuthoredTiming ?? true,
840
+ }
841
+
842
+ // Compute default frame duration from fps (updated from timestamp deltas at runtime)
843
+ if (config.fps && config.fps > 0) {
844
+ this.#frameDuration = Math.round(this.#config.timescale / config.fps)
845
+ } else if (config.trackType === 'audio' && config.sampleRate) {
846
+ this.#frameDuration = Math.round(this.#config.timescale * 1024 / config.sampleRate)
847
+ } else {
848
+ // No fps info — will be refined from actual timestamp deltas
849
+ this.#frameDuration = 33333
850
+ }
851
+
852
+ const sampleReorderWindow = config.sampleReorderWindow ?? 0
853
+ if (!Number.isFinite(sampleReorderWindow) || sampleReorderWindow < 0) {
854
+ throw new Error('[CmafBlockAssembler] sampleReorderWindow must be finite and non-negative')
855
+ }
856
+ if (config.sampleOrder && sampleReorderWindow > 0) {
857
+ throw new Error('[CmafBlockAssembler] configure sampleOrder or sampleReorderWindow, not both')
858
+ }
859
+ this.#sampleReorderWindow = Math.floor(sampleReorderWindow)
860
+ this.#sampleOrder = config.sampleOrder ?? { mode: 'arrival' }
861
+ if (this.#sampleOrder.mode === 'media-window') {
862
+ const { deliveryWindow, timestampWrapPeriod } = this.#sampleOrder
863
+ if (!Number.isSafeInteger(deliveryWindow) || deliveryWindow <= 0) {
864
+ throw new Error(
865
+ '[CmafBlockAssembler] media-window deliveryWindow must be a positive safe integer',
866
+ )
867
+ }
868
+ if (
869
+ timestampWrapPeriod !== undefined &&
870
+ (!Number.isSafeInteger(timestampWrapPeriod) || timestampWrapPeriod <= deliveryWindow * 2)
871
+ ) {
872
+ throw new Error(
873
+ '[CmafBlockAssembler] timestampWrapPeriod must be a safe integer larger than two delivery windows',
874
+ )
875
+ }
876
+ const samplesPerSecond = config.trackType === 'audio' && config.sampleRate
877
+ ? config.sampleRate / 1024
878
+ : config.fps
879
+ if (!samplesPerSecond || !Number.isFinite(samplesPerSecond) || samplesPerSecond <= 0) {
880
+ throw new Error(
881
+ '[CmafBlockAssembler] media-window ordering requires catalog-derived media cadence',
882
+ )
883
+ }
884
+ this.#sampleOrderCapacity =
885
+ Math.ceil(deliveryWindow * samplesPerSecond / this.#config.timescale) + 1
886
+ }
887
+ const videoSampleEntry = config.trackType === 'video' ? resolveVideoSampleEntry(config) : null
888
+ this.#videoKeyframeFamily = videoSampleEntry === null
889
+ ? null
890
+ : videoSampleEntry === 'unvalidated' ? null : videoCodecFamily(videoSampleEntry)
891
+ this.#hevcSampleEntry = videoSampleEntry === 'hev1' || videoSampleEntry === 'hvc1' ? videoSampleEntry : null
892
+ if (config.trackType === 'video') {
893
+ console.log(
894
+ `[L4-KF-CONFIG] validate=${this.#videoKeyframeFamily ?? false} ` +
895
+ `codec=${config.codec ?? ''} avcC=${config.avcC?.length ?? 0} hvcC=${config.hvcC?.length ?? 0}`,
896
+ )
897
+ }
898
+
899
+ // Store config for init segment generation
900
+ this._videoConfig = config.trackType === 'video' && config.avcC
901
+ ? { avcC: config.avcC, width: config.width ?? 0, height: config.height ?? 0 }
902
+ : config.trackType === 'video' && config.hvcC && this.#hevcSampleEntry
903
+ ? {
904
+ hvcC: config.hvcC,
905
+ hevcSampleEntry: this.#hevcSampleEntry,
906
+ width: config.width ?? 0,
907
+ height: config.height ?? 0,
908
+ }
909
+ : null
910
+ this._audioConfig = config.trackType === 'audio' && config.sampleRate && config.channels
911
+ ? { sampleRate: config.sampleRate, channels: config.channels, asc: config.asc }
912
+ : null
913
+ }
914
+
915
+ private _videoConfig: {
916
+ avcC?: Uint8Array
917
+ hvcC?: Uint8Array
918
+ hevcSampleEntry?: 'hev1' | 'hvc1'
919
+ width: number
920
+ height: number
921
+ } | null
922
+ private _audioConfig: { sampleRate: number; channels: number; asc?: Uint8Array } | null
923
+
924
+ get sampleOrderStats(): Readonly<CmafSampleOrderStats> {
925
+ return { ...this.#sampleOrderStats }
926
+ }
927
+
928
+ /** Cumulative emit and block-event counters since construction. */
929
+ get emitStats(): Readonly<CmafEmitStats> {
930
+ return { ...this.#emitStats }
931
+ }
932
+
933
+ /** Cumulative audio gap concealment counters since construction. */
934
+ get audioConcealStats(): Readonly<CmafAudioConcealStats> {
935
+ return { ...this.#audioConcealStats }
936
+ }
937
+
938
+ /** Emit a single frame immediately as a one-sample moof+mdat segment.
939
+ *
940
+ * BLO-3035 layer 4 (4b): the prior SBN-grouped buffering scheme stranded
941
+ * frames whenever a multi-packet frame spanned FEC block boundaries —
942
+ * intermediate SBNs had packets-but-no-frames and got `completeBlock`
943
+ * events that landed on empty `#blocks` (→ `pendingFlush` leak), while
944
+ * the SBN where the multi-packet frame finally completed received the
945
+ * `addFrame` but its `trackBlock` count never reached K (→ `pendingBlocks`
946
+ * leak). Result: ~50% of received frames never reached MSE.
947
+ *
948
+ * This path now mirrors `addBypassFrame` — emit on arrival, no buffering.
949
+ * FEC recovery (`addRecoveredBlock`) keeps its SBN-watermark dedup against
950
+ * the same SBN being re-emitted from two paths. Out-of-order regression
951
+ * is guarded by the per-frame `lastEmittedTs` check (also enforced in
952
+ * `#emitPerSample`). The `sbn`/`esi` parameters are kept for the call-site
953
+ * signature but no longer affect routing. */
954
+ addFrame(
955
+ sbn: number,
956
+ esi: number,
957
+ data: Uint8Array,
958
+ timestamp: number,
959
+ keyframe: boolean,
960
+ catalogTrackName?: string,
961
+ mpuSequenceNumber?: number,
962
+ packetSequenceNumber?: number,
963
+ packetSequenceNumbers?: number[],
964
+ repairedPacketSequenceNumbers?: number[],
965
+ authoredTiming?: AuthoredTiming,
966
+ deliveryProvenance?: MmtpDeliveryProvenance,
967
+ mmtpTimestamp?: bigint,
968
+ movieFragmentSequenceNumber?: number,
969
+ sampleNumber?: number,
970
+ gapBefore?: FrameGapDecision,
971
+ ): void {
972
+ void sbn; void esi
973
+ this.#emitStats.addedFrames++
974
+
975
+ if (!this.#ordersSamples()) this.#drainRecoveredUpTo(timestamp)
976
+
977
+ // Per-frame duration: default to catalog-derived `#frameDuration`. For
978
+ // variable-rate content Chrome refines duration from the next sample's
979
+ // DTS at append time, so a fallback here is safe.
980
+ this.#emitSample(
981
+ data,
982
+ timestamp,
983
+ this.#frameDuration,
984
+ keyframe,
985
+ true,
986
+ catalogTrackName,
987
+ mpuSequenceNumber,
988
+ packetSequenceNumber,
989
+ packetSequenceNumbers,
990
+ repairedPacketSequenceNumbers,
991
+ authoredTiming,
992
+ deliveryProvenance,
993
+ mmtpTimestamp,
994
+ movieFragmentSequenceNumber,
995
+ sampleNumber,
996
+ undefined,
997
+ gapBefore,
998
+ )
999
+
1000
+ this.#countEmit([{ keyframe }])
1001
+ }
1002
+
1003
+ /** Mark a block as complete (all K source symbols received or FEC recovery succeeded).
1004
+ * If all frames are already buffered, flushes immediately. Otherwise sets pending-flush. */
1005
+ completeBlock(sbn: number): void {
1006
+ void sbn
1007
+ this.#emitStats.completedBlocks++
1008
+ // Source samples are emitted directly from addFrame(). A clean FEC block
1009
+ // completion is still useful for stats, but it must not enqueue stale
1010
+ // pending flushes from the retired block-buffered path.
1011
+ }
1012
+
1013
+ /**
1014
+ * Record an unrecoverable block. Nothing is synthesised: the release gate
1015
+ * attaches the stall/conceal decision to the next released frame, and the
1016
+ * sink holds the last good frame (video) or repeats the last good AU into
1017
+ * the decided slots (audio).
1018
+ */
1019
+ failBlock(sbn: number): void {
1020
+ void sbn
1021
+ this.#emitStats.failedBlocks++
1022
+ }
1023
+
1024
+ /** Add all frames from a FEC-recovered block at once and emit immediately. */
1025
+ addRecoveredBlock(sbn: number, frames: BlockFrame[]): void {
1026
+ void sbn
1027
+ this.#emitStats.recoveredBlocks++
1028
+
1029
+ if (frames.length === 0) return
1030
+ const normalized = this.#normalizeVideoKeyframes(frames)
1031
+ if (normalized.length === 0) return
1032
+ this.#countEmit(normalized)
1033
+ if (this.#ordersSamples()) {
1034
+ this.#emitPerSample(normalized, undefined, false)
1035
+ return
1036
+ }
1037
+
1038
+ // Arrival mode preserves the legacy protection against future recovered
1039
+ // samples advancing past source media. Explicit media-window mode routes
1040
+ // both paths through one queue instead.
1041
+ if (this.#lastSourceTs >= 0) {
1042
+ this.#enqueueRecovered(normalized)
1043
+ this.#drainRecoveredUpTo(this.#lastSourceTs)
1044
+ } else {
1045
+ const gated = this.#applyVideoKeyframeGate(normalized)
1046
+ if (gated) this.#emitPerSample(gated, undefined, false)
1047
+ }
1048
+ }
1049
+
1050
+ /** Emit a single frame immediately as a one-sample segment (for oversized packets bypassing FEC). */
1051
+ addBypassFrame(
1052
+ data: Uint8Array,
1053
+ timestamp: number,
1054
+ keyframe: boolean,
1055
+ catalogTrackName?: string,
1056
+ mpuSequenceNumber?: number,
1057
+ packetSequenceNumber?: number,
1058
+ packetSequenceNumbers?: number[],
1059
+ repairedPacketSequenceNumbers?: number[],
1060
+ authoredTiming?: AuthoredTiming,
1061
+ deliveryProvenance?: MmtpDeliveryProvenance,
1062
+ mmtpTimestamp?: bigint,
1063
+ movieFragmentSequenceNumber?: number,
1064
+ sampleNumber?: number,
1065
+ gapBefore?: FrameGapDecision,
1066
+ ): void {
1067
+ if (!this.#ordersSamples()) this.#drainRecoveredUpTo(timestamp)
1068
+ this.#emitSample(
1069
+ data,
1070
+ timestamp,
1071
+ this.#frameDuration,
1072
+ keyframe,
1073
+ true,
1074
+ catalogTrackName,
1075
+ mpuSequenceNumber,
1076
+ packetSequenceNumber,
1077
+ packetSequenceNumbers,
1078
+ repairedPacketSequenceNumbers,
1079
+ authoredTiming,
1080
+ deliveryProvenance,
1081
+ mmtpTimestamp,
1082
+ movieFragmentSequenceNumber,
1083
+ sampleNumber,
1084
+ undefined,
1085
+ gapBefore,
1086
+ )
1087
+ }
1088
+
1089
+ /** Build and emit init segment from catalog config. */
1090
+ emitInit(): void {
1091
+ let init: Uint8Array | null = null
1092
+ if (this._videoConfig?.avcC) {
1093
+ init = buildVideoInitSegment(
1094
+ this._videoConfig.avcC,
1095
+ this._videoConfig.width,
1096
+ this._videoConfig.height,
1097
+ this.#config.timescale,
1098
+ this.#config.trackId,
1099
+ )
1100
+ } else if (this._videoConfig?.hvcC && this._videoConfig.hevcSampleEntry) {
1101
+ init = buildHevcVideoInitSegment(
1102
+ this._videoConfig.hevcSampleEntry,
1103
+ this._videoConfig.hvcC,
1104
+ this._videoConfig.width,
1105
+ this._videoConfig.height,
1106
+ this.#config.timescale,
1107
+ this.#config.trackId,
1108
+ )
1109
+ } else if (this._audioConfig) {
1110
+ init = buildAudioInitSegment(
1111
+ this._audioConfig.sampleRate,
1112
+ this._audioConfig.channels,
1113
+ this._audioConfig.asc,
1114
+ this.#config.timescale,
1115
+ this.#config.trackId,
1116
+ )
1117
+ }
1118
+ if (init) this.onInitSegment?.(init)
1119
+ }
1120
+
1121
+ /** Drain all ordered samples at end-of-stream or before reconfiguration. */
1122
+ flush(): void {
1123
+ if (this.#ordersSamples()) {
1124
+ this.#drainSampleReorder(true)
1125
+ return
1126
+ }
1127
+ if (this.#pendingRecovered.size === 0) return
1128
+ const frames = [...this.#pendingRecovered.values()].sort((a, b) => a.timestamp - b.timestamp)
1129
+ this.#pendingRecovered.clear()
1130
+ const gated = this.#applyVideoKeyframeGate(frames)
1131
+ if (gated) this.#emitPerSample(gated, undefined, false)
1132
+ else if (this.#config.trackType === 'video') {
1133
+ this.#sampleOrderStats.noRapFlushDrops += frames.length
1134
+ }
1135
+ }
1136
+
1137
+ /** Drop all queued state and begin a fresh timestamp epoch. */
1138
+ reset(): void {
1139
+ this.#pendingRecovered.clear()
1140
+ this.#sequence = 1
1141
+ this.#baseTs = -1
1142
+ this.#lastEmittedTs = -1
1143
+ this.#lastSourceTs = -1
1144
+ this.#recoveredHorizonTs = -1
1145
+ this.#audioConcealer.reset()
1146
+ this.#audioConcealClock = null
1147
+ this.#armedVideo = false
1148
+ this.#sampleReorderQueue = []
1149
+ }
1150
+
1151
+ dispose(): void {
1152
+ this.reset()
1153
+ this.onSegment = null
1154
+ this.onSample = null
1155
+ this.onInitSegment = null
1156
+ }
1157
+
1158
+ // ── Private ──
1159
+
1160
+ /** Rebase an absolute timestamp to relative media time (starting near 0). */
1161
+ #rebase(timestamp: number): number {
1162
+ if (this.#baseTs < 0) this.#baseTs = timestamp
1163
+ return timestamp - this.#baseTs
1164
+ }
1165
+
1166
+ #normalizeSampleData(data: Uint8Array): Uint8Array {
1167
+ return this.#config.trackType === 'audio' ? normalizeAacSampleForCmaf(data) : data
1168
+ }
1169
+
1170
+ #enqueueRecovered(frames: BlockFrame[]): void {
1171
+ for (const frame of frames) {
1172
+ if (this.#lastEmittedTs >= 0 && frame.timestamp <= this.#lastEmittedTs) {
1173
+ this.#sampleOrderStats.staleSamples++
1174
+ continue
1175
+ }
1176
+ if (this.#pendingRecovered.has(frame.timestamp)) {
1177
+ this.#sampleOrderStats.duplicateSamples++
1178
+ continue
1179
+ }
1180
+ this.#pendingRecovered.set(frame.timestamp, frame)
1181
+ }
1182
+ }
1183
+
1184
+ #drainRecoveredUpTo(horizonTs: number): void {
1185
+ if (this.#pendingRecovered.size === 0) return
1186
+ const ready = [...this.#pendingRecovered.values()]
1187
+ .filter(frame => frame.timestamp <= horizonTs)
1188
+ .sort((a, b) => a.timestamp - b.timestamp)
1189
+
1190
+ for (const frame of ready) {
1191
+ this.#pendingRecovered.delete(frame.timestamp)
1192
+ this.#emitSample(
1193
+ frame.data,
1194
+ frame.timestamp,
1195
+ this.#frameDuration,
1196
+ frame.keyframe,
1197
+ false,
1198
+ frame.catalogTrackName,
1199
+ frame.mpuSequenceNumber,
1200
+ frame.packetSequenceNumber,
1201
+ frame.packetSequenceNumbers,
1202
+ frame.repairedPacketSequenceNumbers,
1203
+ frame.authoredTiming,
1204
+ frame.deliveryProvenance,
1205
+ frame.mmtpTimestamp,
1206
+ frame.movieFragmentSequenceNumber,
1207
+ frame.sampleNumber,
1208
+ frame.synthetic,
1209
+ frame.gapBefore,
1210
+ )
1211
+ this.#countEmit([frame])
1212
+ }
1213
+ }
1214
+ }
1215
+
1216
+ /**
1217
+ * Video sample entry whose bitstream keyframe rule the assembler enforces,
1218
+ * selected from the catalog codec string (never sniffed):
1219
+ *
1220
+ * - `avc1`/`avc3`/`hev1`/`hvc1` from `config.codec`.
1221
+ * - No codec string: `avc1` (the legacy H.264 contract, which an avcC
1222
+ * confirms). An hvcC without a codec string is refused because the sample
1223
+ * entry (hev1 vs hvc1) cannot be chosen without it.
1224
+ * - Any other video codec (AV1, VP9): 'unvalidated' — its metadata keyframe
1225
+ * flag is trusted, as before.
1226
+ *
1227
+ * A configuration record that contradicts the codec family is refused.
1228
+ */
1229
+ function resolveVideoSampleEntry(config: BlockAssemblerConfig): VideoSampleEntry | 'unvalidated' {
1230
+ if (!config.codec) {
1231
+ if (config.hvcC) {
1232
+ throw new Error('[CmafBlockAssembler] hvcC requires a catalog codec string naming hev1 or hvc1')
1233
+ }
1234
+ return 'avc1'
1235
+ }
1236
+ const fourCc = config.codec.split('.')[0]
1237
+ if (fourCc !== 'avc1' && fourCc !== 'avc3' && fourCc !== 'hev1' && fourCc !== 'hvc1') {
1238
+ if (config.avcC || config.hvcC) {
1239
+ throw new Error(`[CmafBlockAssembler] codec ${config.codec} contradicts the supplied avcC/hvcC`)
1240
+ }
1241
+ return 'unvalidated'
1242
+ }
1243
+ const sampleEntry = videoSampleEntryFromCodecString(config.codec)
1244
+ const family = videoCodecFamily(sampleEntry)
1245
+ if ((family === 'avc' && config.hvcC) || (family === 'hevc' && config.avcC)) {
1246
+ throw new Error(`[CmafBlockAssembler] codec ${config.codec} contradicts the supplied avcC/hvcC`)
1247
+ }
1248
+ return sampleEntry
1249
+ }
1250
+
1251
+ function describeH264NalTypes(nals: Uint8Array[]): number[] {
1252
+ return nals.slice(0, 16).map((nal) => (
1253
+ nal[0] !== undefined ? nal[0] & 0x1f : -1
1254
+ ))
1255
+ }