@blockcast/mmt-container 0.1.0 → 0.3.0

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,1966 @@
1
+ // src/mmtp-to-cmaf.ts
2
+ function box(type, ...children) {
3
+ let size = 8;
4
+ for (const c of children) size += c.length;
5
+ const buf = new Uint8Array(size);
6
+ new DataView(buf.buffer).setUint32(0, size);
7
+ buf[4] = type.charCodeAt(0);
8
+ buf[5] = type.charCodeAt(1);
9
+ buf[6] = type.charCodeAt(2);
10
+ buf[7] = type.charCodeAt(3);
11
+ let pos = 8;
12
+ for (const c of children) {
13
+ buf.set(c, pos);
14
+ pos += c.length;
15
+ }
16
+ return buf;
17
+ }
18
+ function fullBox(type, version, flags, ...children) {
19
+ let size = 12;
20
+ for (const c of children) size += c.length;
21
+ const buf = new Uint8Array(size);
22
+ const dv = new DataView(buf.buffer);
23
+ dv.setUint32(0, size);
24
+ buf[4] = type.charCodeAt(0);
25
+ buf[5] = type.charCodeAt(1);
26
+ buf[6] = type.charCodeAt(2);
27
+ buf[7] = type.charCodeAt(3);
28
+ dv.setUint32(8, version << 24 | flags & 16777215);
29
+ let pos = 12;
30
+ for (const c of children) {
31
+ buf.set(c, pos);
32
+ pos += c.length;
33
+ }
34
+ return buf;
35
+ }
36
+ function u32(v) {
37
+ const b = new Uint8Array(4);
38
+ new DataView(b.buffer).setUint32(0, v);
39
+ return b;
40
+ }
41
+ var KEYFRAME_FLAGS = 33554432;
42
+ var DELTA_FLAGS = 16842752;
43
+ var UINT32_MAX = 4294967295;
44
+ var MAX_TRACK_ID = UINT32_MAX - 1;
45
+ var INT32_MIN = -2147483648;
46
+ var INT32_MAX = 2147483647;
47
+ function assertTrackId(trackId, label) {
48
+ if (!Number.isInteger(trackId) || trackId <= 0 || trackId > MAX_TRACK_ID) {
49
+ throw new RangeError(`${label} must be an integer in 1..${MAX_TRACK_ID}, got ${trackId}`);
50
+ }
51
+ }
52
+ function assertTimescale(timescale, label) {
53
+ if (!Number.isInteger(timescale) || timescale <= 0 || timescale > UINT32_MAX) {
54
+ throw new RangeError(`${label} must be an integer in 1..${UINT32_MAX}, got ${timescale}`);
55
+ }
56
+ }
57
+ function assertCompositionTimeOffsets(samples) {
58
+ for (let i = 0; i < samples.length; i++) {
59
+ const offset = samples[i].compositionTimeOffset;
60
+ if (offset !== void 0 && (!Number.isInteger(offset) || offset < INT32_MIN || offset > INT32_MAX)) {
61
+ throw new RangeError(
62
+ `sample ${i} compositionTimeOffset must be an integer in ${INT32_MIN}..${INT32_MAX}, got ${offset}`
63
+ );
64
+ }
65
+ }
66
+ }
67
+ function encodeMultiSampleSegment(samples, baseDecodeTime, sequence, trackId = 1) {
68
+ if (samples.length === 0) return new Uint8Array(0);
69
+ assertTrackId(trackId, "trackId");
70
+ assertCompositionTimeOffsets(samples);
71
+ const mfhd = fullBox("mfhd", 0, 0, u32(sequence));
72
+ const tfhd = fullBox("tfhd", 0, 131072, u32(trackId));
73
+ const tfdtBody = new Uint8Array(8);
74
+ const tfdtView = new DataView(tfdtBody.buffer);
75
+ tfdtView.setUint32(0, Math.floor(baseDecodeTime / 4294967296));
76
+ tfdtView.setUint32(4, baseDecodeTime >>> 0);
77
+ const tfdt = fullBox("tfdt", 1, 0, tfdtBody);
78
+ const hasCompositionTimeOffset = samples.some((sample) => sample.compositionTimeOffset !== void 0);
79
+ const trunVersion = hasCompositionTimeOffset ? 1 : 0;
80
+ const trunFlags = 1793 | (hasCompositionTimeOffset ? 2048 : 0);
81
+ const sampleCount = samples.length;
82
+ const sampleEntrySize = hasCompositionTimeOffset ? 16 : 12;
83
+ const trunBody = new Uint8Array(8 + sampleCount * sampleEntrySize);
84
+ const trunView = new DataView(trunBody.buffer);
85
+ trunView.setUint32(0, sampleCount);
86
+ trunView.setUint32(4, 0);
87
+ for (let i = 0; i < sampleCount; i++) {
88
+ const s = samples[i];
89
+ const off = 8 + i * sampleEntrySize;
90
+ trunView.setUint32(off, s.duration >>> 0);
91
+ trunView.setUint32(off + 4, s.data.length);
92
+ trunView.setUint32(off + 8, s.keyframe ? KEYFRAME_FLAGS : DELTA_FLAGS);
93
+ if (hasCompositionTimeOffset) {
94
+ trunView.setInt32(off + 12, s.compositionTimeOffset ?? 0);
95
+ }
96
+ }
97
+ const trun = fullBox("trun", trunVersion, trunFlags, trunBody);
98
+ const traf = box("traf", tfhd, tfdt, trun);
99
+ const moof = box("moof", mfhd, traf);
100
+ let mdatSize = 0;
101
+ for (const s of samples) mdatSize += s.data.length;
102
+ const mdatPayload = new Uint8Array(mdatSize);
103
+ let pos = 0;
104
+ for (const s of samples) {
105
+ mdatPayload.set(s.data, pos);
106
+ pos += s.data.length;
107
+ }
108
+ const mdat = box("mdat", mdatPayload);
109
+ const dataOffsetPos = 8 + mfhd.length + 8 + tfhd.length + tfdt.length + 12 + 4;
110
+ new DataView(moof.buffer).setUint32(dataOffsetPos, moof.length + 8);
111
+ const result = new Uint8Array(moof.length + mdat.length);
112
+ result.set(moof, 0);
113
+ result.set(mdat, moof.length);
114
+ return result;
115
+ }
116
+ function normalizeAacSampleForCmaf(data) {
117
+ if (data.length < 7 || data[0] !== 255 || (data[1] & 246) !== 240) {
118
+ return data;
119
+ }
120
+ const headerLength = data[1] & 1 ? 7 : 9;
121
+ if (data.length <= headerLength) return data;
122
+ const frameLength = (data[3] & 3) << 11 | data[4] << 3 | (data[5] & 224) >>> 5;
123
+ if (frameLength !== data.length || frameLength <= headerLength) return data;
124
+ return data.subarray(headerLength);
125
+ }
126
+ function encodeDataSegment(data, timestamp, duration, keyframe, sequence, trackId = 1, compositionTimeOffset) {
127
+ assertTrackId(trackId, "trackId");
128
+ assertCompositionTimeOffsets([{ compositionTimeOffset }]);
129
+ if (compositionTimeOffset !== void 0) {
130
+ return encodeMultiSampleSegment(
131
+ [{ data, duration, keyframe, compositionTimeOffset }],
132
+ timestamp,
133
+ sequence,
134
+ trackId
135
+ );
136
+ }
137
+ const sampleFlags = keyframe ? KEYFRAME_FLAGS : DELTA_FLAGS;
138
+ const mfhd = fullBox("mfhd", 0, 0, u32(sequence));
139
+ const tfhd = fullBox("tfhd", 0, 131072, u32(trackId));
140
+ const tfdtBody = new Uint8Array(8);
141
+ const tfdtView = new DataView(tfdtBody.buffer);
142
+ tfdtView.setUint32(0, Math.floor(timestamp / 4294967296));
143
+ tfdtView.setUint32(4, timestamp >>> 0);
144
+ const tfdt = fullBox("tfdt", 1, 0, tfdtBody);
145
+ const trunBody = new Uint8Array(20);
146
+ const trunView = new DataView(trunBody.buffer);
147
+ trunView.setUint32(0, 1);
148
+ trunView.setUint32(4, 0);
149
+ trunView.setUint32(8, duration >>> 0);
150
+ trunView.setUint32(12, data.length);
151
+ trunView.setUint32(16, sampleFlags);
152
+ const trun = fullBox("trun", 0, 1793, trunBody);
153
+ const traf = box("traf", tfhd, tfdt, trun);
154
+ const moof = box("moof", mfhd, traf);
155
+ const mdat = box("mdat", data);
156
+ const dataOffsetPos = 8 + mfhd.length + 8 + tfhd.length + tfdt.length + 12 + 4;
157
+ new DataView(moof.buffer).setUint32(dataOffsetPos, moof.length + 8);
158
+ const result = new Uint8Array(moof.length + mdat.length);
159
+ result.set(moof, 0);
160
+ result.set(mdat, moof.length);
161
+ return result;
162
+ }
163
+ function buildVideoInitSegment(avcC, width, height, timescale = 1e6, trackId = 1) {
164
+ return buildVisualInitSegment("avc1", "avcC", avcC, width, height, timescale, trackId);
165
+ }
166
+ function buildHevcVideoInitSegment(sampleEntry, hvcC, width, height, timescale, trackId) {
167
+ if (sampleEntry !== "hev1" && sampleEntry !== "hvc1") {
168
+ throw new Error(`HEVC init segment requires an hev1 or hvc1 sample entry, got ${String(sampleEntry)}`);
169
+ }
170
+ return buildVisualInitSegment(sampleEntry, "hvcC", hvcC, width, height, timescale, trackId);
171
+ }
172
+ function buildVisualInitSegment(sampleEntryType, configBoxType, configRecord, width, height, timescale, trackId) {
173
+ assertTrackId(trackId, "video trackId");
174
+ assertTimescale(timescale, "video timescale");
175
+ const ftyp = box("ftyp", new Uint8Array([
176
+ 105,
177
+ 115,
178
+ 111,
179
+ 109,
180
+ 0,
181
+ 0,
182
+ 2,
183
+ 0,
184
+ 105,
185
+ 115,
186
+ 111,
187
+ 109,
188
+ 105,
189
+ 115,
190
+ 111,
191
+ 54,
192
+ 109,
193
+ 112,
194
+ 52,
195
+ 49
196
+ ]));
197
+ const configBox = box(configBoxType, configRecord);
198
+ const sampleEntryBody = new Uint8Array(78 + configBox.length);
199
+ const sampleEntryView = new DataView(sampleEntryBody.buffer);
200
+ sampleEntryView.setUint16(6, 1);
201
+ sampleEntryView.setUint16(24, width);
202
+ sampleEntryView.setUint16(26, height);
203
+ sampleEntryView.setUint32(28, 4718592);
204
+ sampleEntryView.setUint32(32, 4718592);
205
+ sampleEntryView.setUint16(40, 1);
206
+ sampleEntryView.setUint16(74, 24);
207
+ sampleEntryView.setInt16(76, -1);
208
+ sampleEntryBody.set(configBox, 78);
209
+ const visualSampleEntry = box(sampleEntryType, sampleEntryBody);
210
+ const stsd = fullBox("stsd", 0, 0, u32(1), visualSampleEntry);
211
+ const stbl = box(
212
+ "stbl",
213
+ stsd,
214
+ fullBox("stts", 0, 0, u32(0)),
215
+ fullBox("stsc", 0, 0, u32(0)),
216
+ fullBox("stsz", 0, 0, u32(0), u32(0)),
217
+ fullBox("stco", 0, 0, u32(0))
218
+ );
219
+ const dinf = box("dinf", fullBox("dref", 0, 0, u32(1), fullBox("url ", 0, 1)));
220
+ const minf = box("minf", fullBox("vmhd", 0, 1, new Uint8Array(8)), dinf, stbl);
221
+ const hdlr = fullBox("hdlr", 0, 0, new Uint8Array([
222
+ 0,
223
+ 0,
224
+ 0,
225
+ 0,
226
+ 118,
227
+ 105,
228
+ 100,
229
+ 101,
230
+ 0,
231
+ 0,
232
+ 0,
233
+ 0,
234
+ 0,
235
+ 0,
236
+ 0,
237
+ 0,
238
+ 0,
239
+ 0,
240
+ 0,
241
+ 0,
242
+ 86,
243
+ 105,
244
+ 100,
245
+ 101,
246
+ 111,
247
+ 0
248
+ ]));
249
+ const mdhdBody = new Uint8Array(20);
250
+ new DataView(mdhdBody.buffer).setUint32(8, timescale);
251
+ const mdhd = fullBox("mdhd", 0, 0, mdhdBody);
252
+ const mdia = box("mdia", mdhd, hdlr, minf);
253
+ const tkhdBody = new Uint8Array(80);
254
+ const tkhdView = new DataView(tkhdBody.buffer);
255
+ tkhdView.setUint32(8, trackId);
256
+ tkhdView.setUint32(36, 65536);
257
+ tkhdView.setUint32(52, 65536);
258
+ tkhdView.setUint32(64, 1073741824);
259
+ tkhdView.setUint32(72, width << 16);
260
+ tkhdView.setUint32(76, height << 16);
261
+ const tkhd = fullBox("tkhd", 0, 3, tkhdBody);
262
+ const trak = box("trak", tkhd, mdia);
263
+ const mvhdBody = new Uint8Array(96);
264
+ const mvhdView = new DataView(mvhdBody.buffer);
265
+ mvhdView.setUint32(8, timescale);
266
+ mvhdView.setUint32(16, 65536);
267
+ mvhdView.setUint16(20, 256);
268
+ mvhdView.setUint32(32, 65536);
269
+ mvhdView.setUint32(48, 65536);
270
+ mvhdView.setUint32(60, 1073741824);
271
+ mvhdView.setUint32(92, trackId + 1);
272
+ const mvhd = fullBox("mvhd", 0, 0, mvhdBody);
273
+ const trexBody = new Uint8Array(20);
274
+ new DataView(trexBody.buffer).setUint32(0, trackId);
275
+ new DataView(trexBody.buffer).setUint32(4, 1);
276
+ const mvex = box("mvex", fullBox("trex", 0, 0, trexBody));
277
+ const moov = box("moov", mvhd, trak, mvex);
278
+ const result = new Uint8Array(ftyp.length + moov.length);
279
+ result.set(ftyp, 0);
280
+ result.set(moov, ftyp.length);
281
+ return result;
282
+ }
283
+ function buildAudioInitSegment(sampleRate, channels, asc, timescale, trackId = 1) {
284
+ assertTrackId(trackId, "audio trackId");
285
+ const ts = timescale ?? sampleRate;
286
+ assertTimescale(ts, "audio timescale");
287
+ if (!asc) {
288
+ const freqTable = [96e3, 88200, 64e3, 48e3, 44100, 32e3, 24e3, 22050, 16e3, 12e3, 11025, 8e3, 7350];
289
+ const fi = freqTable.indexOf(sampleRate);
290
+ const freqIdx = fi >= 0 ? fi : 15;
291
+ if (freqIdx <= 14) {
292
+ const v = 2 << 11 | freqIdx << 7 | channels << 3;
293
+ asc = new Uint8Array([v >> 8 & 255, v & 255]);
294
+ } else {
295
+ asc = new Uint8Array([
296
+ 2 << 3 | 7,
297
+ (8 | sampleRate >> 20 & 7) & 255,
298
+ sampleRate >> 12 & 255,
299
+ sampleRate >> 4 & 255,
300
+ ((sampleRate & 15) << 4 | channels << 0) & 255
301
+ ]);
302
+ }
303
+ }
304
+ const dsi = new Uint8Array(2 + asc.length);
305
+ dsi[0] = 5;
306
+ dsi[1] = asc.length;
307
+ dsi.set(asc, 2);
308
+ const dcdBody = new Uint8Array(13 + dsi.length);
309
+ dcdBody[0] = 64;
310
+ dcdBody[1] = 21;
311
+ dcdBody.set(dsi, 13);
312
+ const dcd = new Uint8Array(2 + dcdBody.length);
313
+ dcd[0] = 4;
314
+ dcd[1] = dcdBody.length;
315
+ dcd.set(dcdBody, 2);
316
+ const esBody = new Uint8Array(3 + dcd.length);
317
+ esBody[0] = 0;
318
+ esBody[1] = 1;
319
+ esBody[2] = 0;
320
+ esBody.set(dcd, 3);
321
+ const es = new Uint8Array(2 + esBody.length);
322
+ es[0] = 3;
323
+ es[1] = esBody.length;
324
+ es.set(esBody, 2);
325
+ const esdsBox = fullBox("esds", 0, 0, es);
326
+ const mp4aBody = new Uint8Array(28 + esdsBox.length);
327
+ const mp4aView = new DataView(mp4aBody.buffer);
328
+ mp4aView.setUint16(6, 1);
329
+ mp4aView.setUint16(16, channels);
330
+ mp4aView.setUint16(18, 16);
331
+ mp4aView.setUint32(24, sampleRate << 16);
332
+ mp4aBody.set(esdsBox, 28);
333
+ const mp4a = box("mp4a", mp4aBody);
334
+ const stsd = fullBox("stsd", 0, 0, u32(1), mp4a);
335
+ const stbl = box(
336
+ "stbl",
337
+ stsd,
338
+ fullBox("stts", 0, 0, u32(0)),
339
+ fullBox("stsc", 0, 0, u32(0)),
340
+ fullBox("stsz", 0, 0, u32(0), u32(0)),
341
+ fullBox("stco", 0, 0, u32(0))
342
+ );
343
+ const dinf = box("dinf", fullBox("dref", 0, 0, u32(1), fullBox("url ", 0, 1)));
344
+ const minf = box("minf", fullBox("smhd", 0, 0, new Uint8Array(4)), dinf, stbl);
345
+ const hdlr = fullBox("hdlr", 0, 0, new Uint8Array([
346
+ 0,
347
+ 0,
348
+ 0,
349
+ 0,
350
+ 115,
351
+ 111,
352
+ 117,
353
+ 110,
354
+ 0,
355
+ 0,
356
+ 0,
357
+ 0,
358
+ 0,
359
+ 0,
360
+ 0,
361
+ 0,
362
+ 0,
363
+ 0,
364
+ 0,
365
+ 0,
366
+ 83,
367
+ 111,
368
+ 117,
369
+ 110,
370
+ 100,
371
+ 0
372
+ ]));
373
+ const mdhdBody = new Uint8Array(20);
374
+ new DataView(mdhdBody.buffer).setUint32(8, ts);
375
+ const mdhd = fullBox("mdhd", 0, 0, mdhdBody);
376
+ const mdia = box("mdia", mdhd, hdlr, minf);
377
+ const tkhdBody = new Uint8Array(80);
378
+ const tkhdView = new DataView(tkhdBody.buffer);
379
+ tkhdView.setUint32(8, trackId);
380
+ tkhdView.setUint32(36, 65536);
381
+ tkhdView.setUint32(52, 65536);
382
+ tkhdView.setUint32(64, 1073741824);
383
+ const tkhd = fullBox("tkhd", 0, 3, tkhdBody);
384
+ const trak = box("trak", tkhd, mdia);
385
+ const mvhdBody = new Uint8Array(96);
386
+ const mvhdView = new DataView(mvhdBody.buffer);
387
+ mvhdView.setUint32(8, ts);
388
+ mvhdView.setUint32(16, 65536);
389
+ mvhdView.setUint16(20, 256);
390
+ mvhdView.setUint32(32, 65536);
391
+ mvhdView.setUint32(48, 65536);
392
+ mvhdView.setUint32(60, 1073741824);
393
+ mvhdView.setUint32(92, trackId + 1);
394
+ const mvhd = fullBox("mvhd", 0, 0, mvhdBody);
395
+ const trexBody = new Uint8Array(20);
396
+ new DataView(trexBody.buffer).setUint32(0, trackId);
397
+ new DataView(trexBody.buffer).setUint32(4, 1);
398
+ const mvex = box("mvex", fullBox("trex", 0, 0, trexBody));
399
+ const moov = box("moov", mvhd, trak, mvex);
400
+ const ftyp = box("ftyp", new Uint8Array([
401
+ 105,
402
+ 115,
403
+ 111,
404
+ 109,
405
+ 0,
406
+ 0,
407
+ 2,
408
+ 0,
409
+ 105,
410
+ 115,
411
+ 111,
412
+ 109,
413
+ 105,
414
+ 115,
415
+ 111,
416
+ 54,
417
+ 109,
418
+ 112,
419
+ 52,
420
+ 49
421
+ ]));
422
+ const result = new Uint8Array(ftyp.length + moov.length);
423
+ result.set(ftyp, 0);
424
+ result.set(moov, ftyp.length);
425
+ return result;
426
+ }
427
+
428
+ // src/conceal-timeline.ts
429
+ var AudioGapConcealer = class {
430
+ #last = null;
431
+ #stats = { rejectedUnits: 0 };
432
+ get stats() {
433
+ return { ...this.#stats };
434
+ }
435
+ /**
436
+ * Record a good access unit as it is emitted. An AU whose duration is not
437
+ * whole media ticks is refused and counted (`stats.rejectedUnits`), and the
438
+ * concealer forgets its previous AU: that one no longer precedes the gap, so
439
+ * sizing from it would misplace every slot. Refusing here keeps `plan()`
440
+ * total, so a bad AU never throws out of the packet path.
441
+ */
442
+ note(au) {
443
+ if (!Number.isSafeInteger(au.duration) || au.duration <= 0) {
444
+ this.#stats.rejectedUnits++;
445
+ this.#last = null;
446
+ return;
447
+ }
448
+ this.#last = au;
449
+ }
450
+ plan(decision, next) {
451
+ if (!decision || decision.trackKind !== "audio") return { kind: "none" };
452
+ const missing = decision.missingFrames;
453
+ if (decision.reason !== "audio-gap" || missing === null || !Number.isSafeInteger(missing) || missing <= 0) {
454
+ return { kind: "re-anchor", pts: next.pts };
455
+ }
456
+ const last = this.#last;
457
+ if (last === null) return { kind: "re-anchor", pts: next.pts };
458
+ const duration = BigInt(last.duration);
459
+ const repeat = [];
460
+ for (let slot = 1; slot <= missing; slot++) {
461
+ repeat.push({
462
+ payload: last.payload,
463
+ pts: last.pts + BigInt(slot) * duration,
464
+ duration: last.duration
465
+ });
466
+ }
467
+ return { kind: "conceal", repeat, silenceTicks: BigInt(missing) * duration };
468
+ }
469
+ reset() {
470
+ this.#last = null;
471
+ }
472
+ };
473
+
474
+ // src/codec-utils.ts
475
+ function videoSampleEntryFromCodecString(codec) {
476
+ const fourCc = codec.split(".")[0];
477
+ if (fourCc === "avc1" || fourCc === "avc3" || fourCc === "hev1" || fourCc === "hvc1") return fourCc;
478
+ throw new Error(`Unsupported video codec family in codec string ${JSON.stringify(codec)}`);
479
+ }
480
+ function videoCodecFamily(sampleEntry) {
481
+ return sampleEntry === "avc1" || sampleEntry === "avc3" ? "avc" : "hevc";
482
+ }
483
+ var HEVC_NAL_UNIT_TYPE = {
484
+ TRAIL_R: 1,
485
+ /** First IRAP type. */
486
+ BLA_W_LP: 16,
487
+ IDR_W_RADL: 19,
488
+ IDR_N_LP: 20,
489
+ CRA_NUT: 21,
490
+ /** Last IRAP type (reserved IRAP VCL). */
491
+ RSV_IRAP_VCL23: 23,
492
+ /** Last VCL type; 32..=63 are non-VCL. */
493
+ LAST_VCL: 31,
494
+ VPS_NUT: 32,
495
+ SPS_NUT: 33,
496
+ PPS_NUT: 34,
497
+ AUD_NUT: 35,
498
+ PREFIX_SEI_NUT: 39,
499
+ SUFFIX_SEI_NUT: 40
500
+ };
501
+ var HEVC_NAL_HEADER_LENGTH = 2;
502
+ function hevcNalUnitType(nal) {
503
+ return nal[0] >> 1 & 63;
504
+ }
505
+ function isHevcIrapNalUnitType(nalUnitType) {
506
+ return nalUnitType >= HEVC_NAL_UNIT_TYPE.BLA_W_LP && nalUnitType <= HEVC_NAL_UNIT_TYPE.RSV_IRAP_VCL23;
507
+ }
508
+ function removeEmulationPrevention(rbsp) {
509
+ const out = [];
510
+ let zeros = 0;
511
+ for (let i = 0; i < rbsp.length; i++) {
512
+ const b = rbsp[i];
513
+ if (zeros >= 2 && b === 3) {
514
+ zeros = 0;
515
+ continue;
516
+ }
517
+ out.push(b);
518
+ zeros = b === 0 ? zeros + 1 : 0;
519
+ }
520
+ return Uint8Array.from(out);
521
+ }
522
+ function splitHevcSample(data) {
523
+ if (isCompleteAvccSample(data)) return { nals: splitAvccNalUnits(data), lengthPrefixed: true };
524
+ if (isAnnexB(data)) return { nals: splitAnnexBNalUnits(data), lengthPrefixed: false };
525
+ return null;
526
+ }
527
+ function hevcNalUnitsContainIrap(nals) {
528
+ let sawNal = false;
529
+ for (const nal of nals) {
530
+ if (nal.length < HEVC_NAL_HEADER_LENGTH) continue;
531
+ sawNal = true;
532
+ if (isHevcIrapNalUnitType(hevcNalUnitType(nal))) return true;
533
+ }
534
+ return sawNal ? false : void 0;
535
+ }
536
+ function prepareHevcCmafSample(data, sampleEntry) {
537
+ const split = splitHevcSample(data);
538
+ if (split === null) return null;
539
+ const keyframe = hevcNalUnitsContainIrap(split.nals);
540
+ if (keyframe === void 0) return null;
541
+ const normalized = hevcNalUnitsToLengthPrefixed(data, split.nals, split.lengthPrefixed, sampleEntry);
542
+ return normalized === null ? null : { keyframe, data: normalized };
543
+ }
544
+ function hevcNalUnitsToLengthPrefixed(data, nals, lengthPrefixed, sampleEntry) {
545
+ const kept = sampleEntry === "hvc1" ? nals.filter((nal) => {
546
+ const t = hevcNalUnitType(nal);
547
+ return t !== HEVC_NAL_UNIT_TYPE.VPS_NUT && t !== HEVC_NAL_UNIT_TYPE.SPS_NUT && t !== HEVC_NAL_UNIT_TYPE.PPS_NUT;
548
+ }) : nals;
549
+ if (kept.length === 0) return null;
550
+ if (lengthPrefixed && kept.length === nals.length) return data;
551
+ const out = new Uint8Array(kept.reduce((sum, nal) => sum + 4 + nal.length, 0));
552
+ let w = 0;
553
+ for (const nal of kept) {
554
+ w = writeNalLength(out, w, nal.length);
555
+ out.set(nal, w);
556
+ w += nal.length;
557
+ }
558
+ return out;
559
+ }
560
+ function splitAvccNalUnits(data, lengthSize = 4) {
561
+ const nals = [];
562
+ let i = 0;
563
+ while (i + lengthSize <= data.length) {
564
+ let len = 0;
565
+ for (let k = 0; k < lengthSize; k++) len = len << 8 | data[i + k];
566
+ i += lengthSize;
567
+ if (len <= 0 || i + len > data.length) break;
568
+ nals.push(data.subarray(i, i + len));
569
+ i += len;
570
+ }
571
+ return nals;
572
+ }
573
+ function isCompleteAvccSample(data, lengthSize = 4) {
574
+ let i = 0;
575
+ let count = 0;
576
+ while (i + lengthSize <= data.length) {
577
+ let len = 0;
578
+ for (let k = 0; k < lengthSize; k++) len = len << 8 | data[i + k];
579
+ i += lengthSize;
580
+ if (len <= 0 || i + len > data.length) return false;
581
+ i += len;
582
+ count++;
583
+ }
584
+ return count > 0 && i === data.length;
585
+ }
586
+ function splitH264SampleNalUnits(data, options = {}) {
587
+ if (isCompleteAvccSample(data)) return { nals: splitAvccNalUnits(data), format: "avcc" };
588
+ if (isAnnexB(data)) return { nals: splitAnnexBNalUnits(data), format: "annexb" };
589
+ if (options.allowPartialAvcc === true) {
590
+ const partial = splitPartialAvccNalUnits(data);
591
+ if (partial.length > 0) return { nals: partial, format: "partial-avcc" };
592
+ }
593
+ if (isLikelyRawH264NalUnit(data)) return { nals: [data], format: "raw-nal" };
594
+ const nals = splitAvccNalUnits(data);
595
+ return { nals, format: nals.length > 0 ? "avcc" : "unknown" };
596
+ }
597
+ function isAnnexB(data) {
598
+ if (data.length >= 4 && data[0] === 0 && data[1] === 0 && (data[2] === 1 || data[2] === 0 && data[3] === 1)) {
599
+ return true;
600
+ }
601
+ return false;
602
+ }
603
+ function splitAnnexBNalUnits(data) {
604
+ const nalUnits = [];
605
+ let i = 0;
606
+ while (i < data.length - 3) {
607
+ if (data[i] === 0 && data[i + 1] === 0) {
608
+ let scLen = 0;
609
+ if (data[i + 2] === 1) scLen = 3;
610
+ else if (data[i + 2] === 0 && i + 3 < data.length && data[i + 3] === 1) scLen = 4;
611
+ if (scLen > 0) {
612
+ const nalStart = i + scLen;
613
+ let nalEnd = data.length;
614
+ for (let j = nalStart + 1; j < data.length - 2; j++) {
615
+ if (data[j] === 0 && data[j + 1] === 0 && (data[j + 2] === 1 || data[j + 2] === 0 && j + 3 < data.length && data[j + 3] === 1)) {
616
+ nalEnd = j;
617
+ break;
618
+ }
619
+ }
620
+ if (nalEnd > nalStart) nalUnits.push(data.subarray(nalStart, nalEnd));
621
+ i = nalEnd;
622
+ continue;
623
+ }
624
+ }
625
+ i++;
626
+ }
627
+ return nalUnits;
628
+ }
629
+ function classifyH264Keyframe(data, options = {}) {
630
+ const nals = h264NalUnitsForKeyframeDetection(data, options);
631
+ if (nals.length === 0) return void 0;
632
+ let sawIntraSlice = false;
633
+ let sawNonIntraVcl = false;
634
+ let sawNal = false;
635
+ for (const nal of nals) {
636
+ sawNal = true;
637
+ const nalType = nal[0] !== void 0 ? nal[0] & 31 : -1;
638
+ if (nalType === 5 || nalType === 7) return true;
639
+ if (nalType === 1) {
640
+ if (isH264IntraSlice(nal)) sawIntraSlice = true;
641
+ else sawNonIntraVcl = true;
642
+ }
643
+ }
644
+ if (sawIntraSlice && !sawNonIntraVcl) return true;
645
+ return sawNal ? false : void 0;
646
+ }
647
+ function detectH264Keyframe(data, options = {}) {
648
+ return classifyH264Keyframe(data, options) === true;
649
+ }
650
+ function writeNalLength(buf, offset, len) {
651
+ buf[offset] = len >> 24 & 255;
652
+ buf[offset + 1] = len >> 16 & 255;
653
+ buf[offset + 2] = len >> 8 & 255;
654
+ buf[offset + 3] = len & 255;
655
+ return offset + 4;
656
+ }
657
+ function h264NalUnitsForKeyframeDetection(data, options) {
658
+ return splitH264SampleNalUnits(data, options).nals;
659
+ }
660
+ function splitPartialAvccNalUnits(data, lengthSize = 4) {
661
+ const nals = [];
662
+ let i = 0;
663
+ while (i + lengthSize < data.length) {
664
+ let len = 0;
665
+ for (let k = 0; k < lengthSize; k++) len = len << 8 | data[i + k];
666
+ i += lengthSize;
667
+ if (len <= 0 || i >= data.length) break;
668
+ const end = Math.min(i + len, data.length);
669
+ nals.push(data.subarray(i, end));
670
+ if (end < i + len) break;
671
+ i = end;
672
+ }
673
+ return nals;
674
+ }
675
+ function isLikelyRawH264NalUnit(data) {
676
+ if (data.length === 0) return false;
677
+ const header = data[0];
678
+ if ((header & 128) !== 0) return false;
679
+ const nalType = header & 31;
680
+ return nalType > 0 && nalType < 24;
681
+ }
682
+ function isH264IntraSlice(nal) {
683
+ const sliceType = readH264SliceType(nal);
684
+ return sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9;
685
+ }
686
+ function readH264SliceType(nal) {
687
+ if (nal.length < 2 || (nal[0] & 31) !== 1) return null;
688
+ const rbsp = removeEmulationPrevention(nal.subarray(1));
689
+ const state = { bitOffset: 0 };
690
+ if (readUnsignedExpGolomb(rbsp, state) === null) return null;
691
+ return readUnsignedExpGolomb(rbsp, state);
692
+ }
693
+ function readUnsignedExpGolomb(data, state) {
694
+ let leadingZeroBits = 0;
695
+ while (true) {
696
+ const bit = readBit(data, state);
697
+ if (bit === null) return null;
698
+ if (bit === 1) break;
699
+ leadingZeroBits++;
700
+ if (leadingZeroBits > 30) return null;
701
+ }
702
+ let suffix = 0;
703
+ for (let i = 0; i < leadingZeroBits; i++) {
704
+ const bit = readBit(data, state);
705
+ if (bit === null) return null;
706
+ suffix = suffix << 1 | bit;
707
+ }
708
+ return (1 << leadingZeroBits) - 1 + suffix;
709
+ }
710
+ function readBit(data, state) {
711
+ if (state.bitOffset >= data.length * 8) return null;
712
+ const byte = data[state.bitOffset >> 3];
713
+ const bit = byte >> 7 - (state.bitOffset & 7) & 1;
714
+ state.bitOffset++;
715
+ return bit;
716
+ }
717
+ if (void 0) {
718
+ const { describe, test, expect } = void 0;
719
+ describe("codec-utils", () => {
720
+ describe("isAnnexB", () => {
721
+ test("4-byte start code", () => {
722
+ expect(isAnnexB(new Uint8Array([0, 0, 0, 1, 101]))).toBe(true);
723
+ });
724
+ test("3-byte start code", () => {
725
+ expect(isAnnexB(new Uint8Array([0, 0, 1, 101]))).toBe(true);
726
+ });
727
+ test("rejects AVCC", () => {
728
+ expect(isAnnexB(new Uint8Array([0, 0, 0, 10, 101]))).toBe(false);
729
+ });
730
+ });
731
+ describe("findAnnexBStartCode", () => {
732
+ test("at offset 0", () => {
733
+ expect(findAnnexBStartCode(new Uint8Array([0, 0, 0, 1, 101]))).toBe(0);
734
+ });
735
+ test("at offset 5", () => {
736
+ expect(findAnnexBStartCode(new Uint8Array([170, 187, 204, 221, 238, 0, 0, 1, 101]))).toBe(5);
737
+ });
738
+ test("returns -1 when none", () => {
739
+ expect(findAnnexBStartCode(new Uint8Array([170, 187, 204]))).toBe(-1);
740
+ });
741
+ });
742
+ describe("splitAnnexBNalUnits", () => {
743
+ test("splits two NALs", () => {
744
+ const data = new Uint8Array([0, 0, 0, 1, 101, 170, 187, 0, 0, 0, 1, 65, 204]);
745
+ const nals = splitAnnexBNalUnits(data);
746
+ expect(nals.length).toBe(2);
747
+ expect(nals[0]).toEqual(new Uint8Array([101, 170, 187]));
748
+ expect(nals[1]).toEqual(new Uint8Array([65, 204]));
749
+ });
750
+ test("handles 3-byte start codes", () => {
751
+ const nals = splitAnnexBNalUnits(new Uint8Array([0, 0, 1, 103, 66, 0, 0, 1, 104, 1]));
752
+ expect(nals.length).toBe(2);
753
+ });
754
+ });
755
+ describe("annexBToAvcc", () => {
756
+ test("converts single NAL", () => {
757
+ const annexB = new Uint8Array([0, 0, 0, 1, 65, 170, 187]);
758
+ const avcc = annexBToAvcc(annexB);
759
+ expect(avcc[3]).toBe(3);
760
+ expect(avcc[4]).toBe(65);
761
+ });
762
+ test("prepends SPS/PPS", () => {
763
+ const annexB = new Uint8Array([0, 0, 0, 1, 101, 1]);
764
+ const avcc = annexBToAvcc(annexB, { sps: new Uint8Array([103, 66]), pps: new Uint8Array([104, 1]) });
765
+ expect(avcc[3]).toBe(2);
766
+ expect(avcc[4]).toBe(103);
767
+ });
768
+ });
769
+ describe("detectH264Keyframe", () => {
770
+ test("IDR in Annex-B", () => {
771
+ expect(detectH264Keyframe(new Uint8Array([0, 0, 0, 1, 101]))).toBe(true);
772
+ });
773
+ test("SPS in Annex-B", () => {
774
+ expect(detectH264Keyframe(new Uint8Array([0, 0, 0, 1, 103]))).toBe(true);
775
+ });
776
+ test("IDR in AVCC", () => {
777
+ expect(detectH264Keyframe(new Uint8Array([0, 0, 0, 5, 101, 1, 2, 3, 4]))).toBe(true);
778
+ });
779
+ test("IDR after AVCC AUD", () => {
780
+ expect(detectH264Keyframe(new Uint8Array([
781
+ 0,
782
+ 0,
783
+ 0,
784
+ 1,
785
+ 9,
786
+ 0,
787
+ 0,
788
+ 0,
789
+ 2,
790
+ 101,
791
+ 170
792
+ ]))).toBe(true);
793
+ });
794
+ test("non-IDR AVC I-slice in AVCC", () => {
795
+ expect(detectH264Keyframe(new Uint8Array([
796
+ 0,
797
+ 0,
798
+ 0,
799
+ 2,
800
+ 65,
801
+ 136
802
+ ]))).toBe(true);
803
+ });
804
+ test("raw H.264 IDR NAL", () => {
805
+ expect(detectH264Keyframe(new Uint8Array([101, 136, 132]))).toBe(true);
806
+ });
807
+ test("raw H.264 non-IDR I-slice NAL", () => {
808
+ expect(detectH264Keyframe(new Uint8Array([65, 136]))).toBe(true);
809
+ });
810
+ test("classifies partial length-prefixed IDR only when requested", () => {
811
+ const partial = new Uint8Array([0, 0, 32, 0, 101]);
812
+ expect(classifyH264Keyframe(partial)).toBeUndefined();
813
+ expect(classifyH264Keyframe(partial, { allowPartialAvcc: true })).toBe(true);
814
+ });
815
+ test("rejects P-frame", () => {
816
+ expect(detectH264Keyframe(new Uint8Array([0, 0, 0, 1, 65]))).toBe(false);
817
+ });
818
+ test("rejects AVCC sample with only non-IDR slices", () => {
819
+ expect(detectH264Keyframe(new Uint8Array([
820
+ 0,
821
+ 0,
822
+ 0,
823
+ 2,
824
+ 65,
825
+ 192,
826
+ 0,
827
+ 0,
828
+ 0,
829
+ 2,
830
+ 65,
831
+ 192
832
+ ]))).toBe(false);
833
+ });
834
+ });
835
+ describe("avccToAnnexB", () => {
836
+ test("converts with SPS/PPS on keyframe", () => {
837
+ const avcc = new Uint8Array([0, 0, 0, 3, 101, 170, 187]);
838
+ const spsPps = { sps: new Uint8Array([103, 66]), pps: new Uint8Array([104, 1]) };
839
+ const annexB = avccToAnnexB(avcc, true, spsPps);
840
+ expect(annexB[3]).toBe(1);
841
+ expect(annexB[4]).toBe(103);
842
+ });
843
+ });
844
+ describe("codecStringFromAvcC", () => {
845
+ test("derives avc1.64002a", () => {
846
+ expect(codecStringFromAvcC(new Uint8Array([1, 100, 0, 42]))).toBe("avc1.64002a");
847
+ });
848
+ });
849
+ describe("extractAacAscFromInitSegment", () => {
850
+ function buildMinimalAacInit(asc) {
851
+ const box2 = (type, payload) => {
852
+ const sz = 8 + payload.length;
853
+ const out = new Uint8Array(sz);
854
+ out[0] = sz >>> 24 & 255;
855
+ out[1] = sz >>> 16 & 255;
856
+ out[2] = sz >>> 8 & 255;
857
+ out[3] = sz & 255;
858
+ out[4] = type.charCodeAt(0);
859
+ out[5] = type.charCodeAt(1);
860
+ out[6] = type.charCodeAt(2);
861
+ out[7] = type.charCodeAt(3);
862
+ out.set(payload, 8);
863
+ return out;
864
+ };
865
+ const concat = (...arrs) => {
866
+ const total = arrs.reduce((n, a) => n + a.length, 0);
867
+ const out = new Uint8Array(total);
868
+ let off = 0;
869
+ for (const a of arrs) {
870
+ out.set(a, off);
871
+ off += a.length;
872
+ }
873
+ return out;
874
+ };
875
+ const ftyp = box2("ftyp", new Uint8Array([
876
+ 105,
877
+ 115,
878
+ 111,
879
+ 53,
880
+ // 'iso5'
881
+ 0,
882
+ 0,
883
+ 2,
884
+ 0,
885
+ // minor 0x200
886
+ 105,
887
+ 115,
888
+ 111,
889
+ 53,
890
+ // 'iso5'
891
+ 105,
892
+ 115,
893
+ 111,
894
+ 54
895
+ // 'iso6'
896
+ ]));
897
+ const dsi = new Uint8Array(2 + asc.length);
898
+ dsi[0] = 5;
899
+ dsi[1] = asc.length;
900
+ dsi.set(asc, 2);
901
+ const dcd = new Uint8Array(2 + 13 + dsi.length);
902
+ dcd[0] = 4;
903
+ dcd[1] = 13 + dsi.length;
904
+ dcd[2] = 64;
905
+ dcd[3] = 5 << 2 | 1;
906
+ dcd.set(dsi, 15);
907
+ const esd = new Uint8Array(2 + 3 + dcd.length);
908
+ esd[0] = 3;
909
+ esd[1] = 3 + dcd.length;
910
+ esd.set(dcd, 5);
911
+ const esdsPayload = new Uint8Array(4 + esd.length);
912
+ esdsPayload.set(esd, 4);
913
+ const esds = box2("esds", esdsPayload);
914
+ const mp4aFixed = new Uint8Array(28);
915
+ mp4aFixed[7] = 1;
916
+ mp4aFixed[16] = 0;
917
+ mp4aFixed[17] = 1;
918
+ mp4aFixed[18] = 0;
919
+ mp4aFixed[19] = 16;
920
+ mp4aFixed[24] = 187;
921
+ mp4aFixed[25] = 128;
922
+ const mp4a = box2("mp4a", concat(mp4aFixed, esds));
923
+ const stsdPayload = new Uint8Array(8 + mp4a.length);
924
+ stsdPayload[7] = 1;
925
+ stsdPayload.set(mp4a, 8);
926
+ const stsd = box2("stsd", stsdPayload);
927
+ const stbl = box2("stbl", stsd);
928
+ const minf = box2("minf", stbl);
929
+ const mdia = box2("mdia", minf);
930
+ const trak = box2("trak", mdia);
931
+ const moov = box2("moov", trak);
932
+ return concat(ftyp, moov);
933
+ }
934
+ test("extracts AAC-LC mono 48k ASC and derives codec", () => {
935
+ const asc = new Uint8Array([17, 136]);
936
+ const init = buildMinimalAacInit(asc);
937
+ const result = extractAacAscFromInitSegment(init);
938
+ expect(result).toBeDefined();
939
+ expect(result.codec).toBe("mp4a.40.2");
940
+ expect(Array.from(result.description)).toEqual([17, 136]);
941
+ });
942
+ test("derives AOT 5 (HE-AAC) from ASC[0] >> 3", () => {
943
+ const asc = new Uint8Array([41, 136]);
944
+ const init = buildMinimalAacInit(asc);
945
+ expect(extractAacAscFromInitSegment(init)?.codec).toBe("mp4a.40.5");
946
+ });
947
+ test("rejects data without ftyp/moov magic", () => {
948
+ expect(extractAacAscFromInitSegment(new Uint8Array(64))).toBeUndefined();
949
+ });
950
+ test("rejects ftyp+moov with no audio (no mp4a sample entry)", () => {
951
+ const ftyp = new Uint8Array([
952
+ 0,
953
+ 0,
954
+ 0,
955
+ 24,
956
+ 102,
957
+ 116,
958
+ 121,
959
+ 112,
960
+ 105,
961
+ 115,
962
+ 111,
963
+ 53,
964
+ 0,
965
+ 0,
966
+ 2,
967
+ 0,
968
+ 105,
969
+ 115,
970
+ 111,
971
+ 53,
972
+ 105,
973
+ 115,
974
+ 111,
975
+ 54
976
+ ]);
977
+ const moov = new Uint8Array([0, 0, 0, 8, 109, 111, 111, 118]);
978
+ const cat = new Uint8Array(ftyp.length + moov.length);
979
+ cat.set(ftyp);
980
+ cat.set(moov, ftyp.length);
981
+ expect(extractAacAscFromInitSegment(cat)).toBeUndefined();
982
+ });
983
+ });
984
+ describe("hevc", () => {
985
+ const vps = new Uint8Array([
986
+ 64,
987
+ 1,
988
+ 12,
989
+ 1,
990
+ 255,
991
+ 255,
992
+ 1,
993
+ 96,
994
+ 0,
995
+ 0,
996
+ 3,
997
+ 0,
998
+ 144,
999
+ 0,
1000
+ 0,
1001
+ 3,
1002
+ 0,
1003
+ 0,
1004
+ 3,
1005
+ 0,
1006
+ 60,
1007
+ 146,
1008
+ 128,
1009
+ 144
1010
+ ]);
1011
+ const sps = new Uint8Array([
1012
+ 66,
1013
+ 1,
1014
+ 1,
1015
+ 1,
1016
+ 96,
1017
+ 0,
1018
+ 0,
1019
+ 3,
1020
+ 0,
1021
+ 144,
1022
+ 0,
1023
+ 0,
1024
+ 3,
1025
+ 0,
1026
+ 0,
1027
+ 3,
1028
+ 0,
1029
+ 60,
1030
+ 160,
1031
+ 10,
1032
+ 8,
1033
+ 15,
1034
+ 22,
1035
+ 89,
1036
+ 42,
1037
+ 73,
1038
+ 50,
1039
+ 188,
1040
+ 5,
1041
+ 160,
1042
+ 32,
1043
+ 0,
1044
+ 0,
1045
+ 3,
1046
+ 0,
1047
+ 32,
1048
+ 0,
1049
+ 0,
1050
+ 3,
1051
+ 3,
1052
+ 193
1053
+ ]);
1054
+ const pps = new Uint8Array([68, 1, 193, 114, 180, 98, 64]);
1055
+ const idr = new Uint8Array([38, 1, 175, 6]);
1056
+ const lp = (...nals) => {
1057
+ const parts = [];
1058
+ for (const n of nals) {
1059
+ parts.push(n.length >> 24 & 255, n.length >> 16 & 255, n.length >> 8 & 255, n.length & 255, ...n);
1060
+ }
1061
+ return Uint8Array.from(parts);
1062
+ };
1063
+ test("isHevcCodec", () => {
1064
+ expect(isHevcCodec("hev1.1.6.L93.B0")).toBe(true);
1065
+ expect(isHevcCodec("hvc1.1.6.L93.B0")).toBe(true);
1066
+ expect(isHevcCodec("avc1.640033")).toBe(false);
1067
+ });
1068
+ test("removeEmulationPrevention strips 0x03", () => {
1069
+ expect(Array.from(removeEmulationPrevention(new Uint8Array([0, 0, 3, 1])))).toEqual([0, 0, 1]);
1070
+ expect(Array.from(removeEmulationPrevention(new Uint8Array([170, 187])))).toEqual([170, 187]);
1071
+ });
1072
+ test("splitAvccNalUnits splits length-prefixed NALs", () => {
1073
+ const nals = splitAvccNalUnits(lp(vps, sps));
1074
+ expect(nals.length).toBe(2);
1075
+ expect(nals[0]).toEqual(vps);
1076
+ expect(nals[1]).toEqual(sps);
1077
+ });
1078
+ test("isCompleteAvccSample accepts complete length-prefixed NAL samples", () => {
1079
+ expect(isCompleteAvccSample(lp(new Uint8Array([9]), idr))).toBe(true);
1080
+ });
1081
+ test("isCompleteAvccSample rejects Annex-B start-code samples", () => {
1082
+ expect(isCompleteAvccSample(new Uint8Array([0, 0, 0, 1, 101, 170]))).toBe(false);
1083
+ });
1084
+ test("isCompleteAvccSample rejects truncated length-prefixed samples", () => {
1085
+ expect(isCompleteAvccSample(new Uint8Array([0, 0, 0, 4, 101, 170]))).toBe(false);
1086
+ });
1087
+ test("normalizeH264SampleToAvcc leaves complete AVCC samples unchanged", () => {
1088
+ const avcc = lp(new Uint8Array([9]), idr);
1089
+ const normalized = normalizeH264SampleToAvcc(avcc);
1090
+ expect(normalized.format).toBe("avcc");
1091
+ expect(normalized.data).toBe(avcc);
1092
+ });
1093
+ test("normalizeH264SampleToAvcc converts a single raw H.264 NAL to AVCC", () => {
1094
+ const raw = new Uint8Array([101, 136, 132]);
1095
+ const normalized = normalizeH264SampleToAvcc(raw);
1096
+ expect(normalized.format).toBe("raw-nal");
1097
+ expect(normalized.data).toEqual(new Uint8Array([0, 0, 0, 3, 101, 136, 132]));
1098
+ });
1099
+ test("splitH264SampleNalUnits exposes Annex-B NALs without AVCC conversion", () => {
1100
+ const annexB = new Uint8Array([0, 0, 0, 1, 101, 136, 132]);
1101
+ const sample = splitH264SampleNalUnits(annexB);
1102
+ expect(sample.format).toBe("annexb");
1103
+ expect(sample.nals).toHaveLength(1);
1104
+ expect(sample.nals[0]).toEqual(new Uint8Array([101, 136, 132]));
1105
+ });
1106
+ test("splitH264SampleNalUnits exposes single raw H.264 NALs without wrapping", () => {
1107
+ const raw = new Uint8Array([101, 136, 132]);
1108
+ const sample = splitH264SampleNalUnits(raw);
1109
+ expect(sample.format).toBe("raw-nal");
1110
+ expect(sample.nals).toEqual([raw]);
1111
+ });
1112
+ test("splitH264SampleNalUnits can expose partial AVCC NAL headers", () => {
1113
+ const partial = new Uint8Array([0, 0, 0, 5, 101, 136]);
1114
+ const sample = splitH264SampleNalUnits(partial, { allowPartialAvcc: true });
1115
+ expect(sample.format).toBe("partial-avcc");
1116
+ expect(sample.nals).toHaveLength(1);
1117
+ expect(sample.nals[0]).toEqual(new Uint8Array([101, 136]));
1118
+ });
1119
+ test("extractHevcParameterSets finds VPS/SPS/PPS (length-prefixed)", () => {
1120
+ const sets = extractHevcParameterSets(lp(vps, sps, pps, idr));
1121
+ expect(sets.vps).toEqual(vps);
1122
+ expect(sets.sps).toEqual(sps);
1123
+ expect(sets.pps).toEqual(pps);
1124
+ });
1125
+ test("extractHevcParameterSets finds VPS/SPS/PPS (Annex-B)", () => {
1126
+ const sc = new Uint8Array([0, 0, 0, 1]);
1127
+ const annexb = Uint8Array.from([...sc, ...vps, ...sc, ...sps, ...sc, ...pps, ...sc, ...idr]);
1128
+ const sets = extractHevcParameterSets(annexb);
1129
+ expect(sets.vps).toEqual(vps);
1130
+ expect(sets.sps).toEqual(sps);
1131
+ expect(sets.pps).toEqual(pps);
1132
+ });
1133
+ test("generateHvcCFromParameterSets builds a valid hvcC", () => {
1134
+ const hvcc = generateHvcCFromParameterSets({ vps, sps, pps });
1135
+ expect(hvcc).not.toBeNull();
1136
+ expect(hvcc[0]).toBe(1);
1137
+ expect(hvcc[1]).toBe(sps[3]);
1138
+ expect(hvcc[22]).toBe(3);
1139
+ expect(hvcc[23] & 63).toBe(32);
1140
+ expect(hvcc[24] << 8 | hvcc[25]).toBe(1);
1141
+ });
1142
+ test("generateHvcCFromParameterSets returns null without SPS/PPS", () => {
1143
+ expect(generateHvcCFromParameterSets({ vps })).toBeNull();
1144
+ });
1145
+ test("extractHevcCodecDescription end-to-end from keyframe", () => {
1146
+ const desc = extractHevcCodecDescription(lp(vps, sps, pps, idr));
1147
+ expect(desc).not.toBeNull();
1148
+ expect(desc[0]).toBe(1);
1149
+ });
1150
+ test("hevcVclOnly strips parameter-set NALs, keeps VCL", () => {
1151
+ const stripped = hevcVclOnly(lp(vps, sps, pps, idr));
1152
+ const nals = splitAvccNalUnits(stripped);
1153
+ expect(nals.length).toBe(1);
1154
+ expect(nals[0]).toEqual(idr);
1155
+ });
1156
+ test("hevcVclOnly is a no-op for VCL-only length-prefixed input", () => {
1157
+ const vclOnly = lp(idr);
1158
+ expect(hevcVclOnly(vclOnly)).toBe(vclOnly);
1159
+ });
1160
+ });
1161
+ });
1162
+ }
1163
+
1164
+ // src/authored-timing.ts
1165
+ function scaleAuthoredTicks(ticks, mediaTimescale, targetTimescale) {
1166
+ if (!Number.isSafeInteger(mediaTimescale) || mediaTimescale <= 0 || !Number.isSafeInteger(targetTimescale) || targetTimescale <= 0) return null;
1167
+ const negative = ticks < 0n;
1168
+ const numerator = (negative ? -ticks : ticks) * BigInt(targetTimescale);
1169
+ const denominator = BigInt(mediaTimescale);
1170
+ const whole = numerator / denominator;
1171
+ const remainder = numerator % denominator;
1172
+ if (whole > BigInt(Number.MAX_SAFE_INTEGER)) return null;
1173
+ const value = Number(whole) + Number(remainder) / mediaTimescale;
1174
+ return Number.isFinite(value) ? negative ? -value : value : null;
1175
+ }
1176
+ function scaleAuthoredTiming(timing, targetTimescale) {
1177
+ if (!Number.isSafeInteger(timing.durationTicks) || timing.durationTicks <= 0) return null;
1178
+ const timestamp = scaleAuthoredTicks(
1179
+ timing.presentationTime,
1180
+ timing.mediaTimescale,
1181
+ targetTimescale
1182
+ );
1183
+ const duration = scaleAuthoredTicks(
1184
+ BigInt(timing.durationTicks),
1185
+ timing.mediaTimescale,
1186
+ targetTimescale
1187
+ );
1188
+ if (timestamp === null || duration === null || duration <= 0) return null;
1189
+ return { timestamp, duration };
1190
+ }
1191
+
1192
+ // src/cmaf-block-assembler.ts
1193
+ var INT32_MIN2 = -2147483648;
1194
+ var INT32_MAX2 = 2147483647;
1195
+ var CmafBlockAssembler = class {
1196
+ constructor(config) {
1197
+ this.#pendingRecovered = /* @__PURE__ */ new Map();
1198
+ this.#sequence = 1;
1199
+ this.#baseTs = -1;
1200
+ /**
1201
+ * Last decoder-proven audio AU, repeated into slots a gap decision names.
1202
+ * It is noted and planned on the AU's authored clock (`AuthoredTiming`
1203
+ * ticks), never on this assembler's CMAF timescale: on the default
1204
+ * 1_000_000 an AAC AU is 1024e6 / sampleRate µs, which is not an integer.
1205
+ */
1206
+ this.#audioConcealer = new AudioGapConcealer();
1207
+ /**
1208
+ * Media timescale of the AU the concealer holds; `'untimed'` when the last
1209
+ * emitted audio AU carried no authored timing, `null` before any AU.
1210
+ */
1211
+ this.#audioConcealClock = null;
1212
+ this.#audioConcealStats = {
1213
+ repeatedUnits: 0,
1214
+ reanchoredGaps: 0,
1215
+ untimedGaps: 0
1216
+ };
1217
+ this.#lastEmittedTs = -1;
1218
+ this.#lastSourceTs = -1;
1219
+ this.#sampleReorderWindow = 0;
1220
+ this.#sampleOrder = { mode: "arrival" };
1221
+ this.#sampleOrderCapacity = 0;
1222
+ this.#sampleReorderQueue = [];
1223
+ this.#recoveredHorizonTs = -1;
1224
+ this.#sampleOrderStats = {
1225
+ staleSamples: 0,
1226
+ duplicateSamples: 0,
1227
+ preRapDeadlineDrops: 0,
1228
+ noRapFlushDrops: 0,
1229
+ forcedReleases: 0,
1230
+ unadmittedAuthoredSamples: 0,
1231
+ unreadableVideoSamples: 0
1232
+ };
1233
+ /** Codec family whose bitstream keyframe rule overrides the metadata flag
1234
+ * (AVC IDR, HEVC IRAP), or null when the bitstream is not validated. */
1235
+ this.#videoKeyframeFamily = null;
1236
+ /** HEVC sample entry chosen from the catalog codec string. */
1237
+ this.#hevcSampleEntry = null;
1238
+ this.#keyframeRejectDumpCount = 0;
1239
+ /** Callback: emits a complete moof+mdat CMAF segment */
1240
+ this.onSegment = null;
1241
+ /** Callback: emits a gated/deduped raw sample for callers that already own the MSE timeline. */
1242
+ this.onSample = null;
1243
+ /** Callback: emits an init segment (ftyp+moov) */
1244
+ this.onInitSegment = null;
1245
+ // Video keyframe gate (BLO-3035 layer 3): Chrome's CHUNK_DEMUXER rejects a
1246
+ // moof+mdat whose first sample is non-sync with no prior reference frames
1247
+ // ("CHUNK_DEMUXER_ERROR_APPEND_FAILED: Failed to prepare video sample for
1248
+ // decode") and detaches the SourceBuffer for the rest of the session.
1249
+ // Mid-stream join almost guarantees the first FEC blocks are mid-GOP — all
1250
+ // delta frames. Gate emission until the first block containing an IDR;
1251
+ // within that block, splice samples to start at the IDR index. Audio passes
1252
+ // unconditionally — valid for the codecs supported here (AAC, Opus) where
1253
+ // every frame is independently decodable. SBR-only AAC, USAC, or HE-AAC v2
1254
+ // with PCE re-entry would need a similar gate.
1255
+ this.#armedVideo = false;
1256
+ // Cumulative emit counters (see emitStats). They replace the BLO-3035 L4
1257
+ // diagnostics, which hashed and hex-dumped every video keyframe and ran a
1258
+ // 1 s setInterval console aggregate on the MSE path (BLO-36599).
1259
+ this.#emitStats = {
1260
+ emits: 0,
1261
+ samples: 0,
1262
+ keyframes: 0,
1263
+ addedFrames: 0,
1264
+ recoveredBlocks: 0,
1265
+ completedBlocks: 0,
1266
+ failedBlocks: 0
1267
+ };
1268
+ this.#config = {
1269
+ k: config.k,
1270
+ timescale: config.timescale ?? 1e6,
1271
+ trackId: config.trackId ?? 1,
1272
+ trackType: config.trackType,
1273
+ admitAuthoredTiming: config.admitAuthoredTiming ?? true
1274
+ };
1275
+ if (config.fps && config.fps > 0) {
1276
+ this.#frameDuration = Math.round(this.#config.timescale / config.fps);
1277
+ } else if (config.trackType === "audio" && config.sampleRate) {
1278
+ this.#frameDuration = Math.round(this.#config.timescale * 1024 / config.sampleRate);
1279
+ } else {
1280
+ this.#frameDuration = 33333;
1281
+ }
1282
+ const sampleReorderWindow = config.sampleReorderWindow ?? 0;
1283
+ if (!Number.isFinite(sampleReorderWindow) || sampleReorderWindow < 0) {
1284
+ throw new Error("[CmafBlockAssembler] sampleReorderWindow must be finite and non-negative");
1285
+ }
1286
+ if (config.sampleOrder && sampleReorderWindow > 0) {
1287
+ throw new Error("[CmafBlockAssembler] configure sampleOrder or sampleReorderWindow, not both");
1288
+ }
1289
+ this.#sampleReorderWindow = Math.floor(sampleReorderWindow);
1290
+ this.#sampleOrder = config.sampleOrder ?? { mode: "arrival" };
1291
+ if (this.#sampleOrder.mode === "media-window") {
1292
+ const { deliveryWindow, timestampWrapPeriod } = this.#sampleOrder;
1293
+ if (!Number.isSafeInteger(deliveryWindow) || deliveryWindow <= 0) {
1294
+ throw new Error(
1295
+ "[CmafBlockAssembler] media-window deliveryWindow must be a positive safe integer"
1296
+ );
1297
+ }
1298
+ if (timestampWrapPeriod !== void 0 && (!Number.isSafeInteger(timestampWrapPeriod) || timestampWrapPeriod <= deliveryWindow * 2)) {
1299
+ throw new Error(
1300
+ "[CmafBlockAssembler] timestampWrapPeriod must be a safe integer larger than two delivery windows"
1301
+ );
1302
+ }
1303
+ const samplesPerSecond = config.trackType === "audio" && config.sampleRate ? config.sampleRate / 1024 : config.fps;
1304
+ if (!samplesPerSecond || !Number.isFinite(samplesPerSecond) || samplesPerSecond <= 0) {
1305
+ throw new Error(
1306
+ "[CmafBlockAssembler] media-window ordering requires catalog-derived media cadence"
1307
+ );
1308
+ }
1309
+ this.#sampleOrderCapacity = Math.ceil(deliveryWindow * samplesPerSecond / this.#config.timescale) + 1;
1310
+ }
1311
+ const videoSampleEntry = config.trackType === "video" ? resolveVideoSampleEntry(config) : null;
1312
+ this.#videoKeyframeFamily = videoSampleEntry === null ? null : videoSampleEntry === "unvalidated" ? null : videoCodecFamily(videoSampleEntry);
1313
+ this.#hevcSampleEntry = videoSampleEntry === "hev1" || videoSampleEntry === "hvc1" ? videoSampleEntry : null;
1314
+ if (config.trackType === "video") {
1315
+ console.log(
1316
+ `[L4-KF-CONFIG] validate=${this.#videoKeyframeFamily ?? false} codec=${config.codec ?? ""} avcC=${config.avcC?.length ?? 0} hvcC=${config.hvcC?.length ?? 0}`
1317
+ );
1318
+ }
1319
+ this._videoConfig = config.trackType === "video" && config.avcC ? { avcC: config.avcC, width: config.width ?? 0, height: config.height ?? 0 } : config.trackType === "video" && config.hvcC && this.#hevcSampleEntry ? {
1320
+ hvcC: config.hvcC,
1321
+ hevcSampleEntry: this.#hevcSampleEntry,
1322
+ width: config.width ?? 0,
1323
+ height: config.height ?? 0
1324
+ } : null;
1325
+ this._audioConfig = config.trackType === "audio" && config.sampleRate && config.channels ? { sampleRate: config.sampleRate, channels: config.channels, asc: config.asc } : null;
1326
+ }
1327
+ #config;
1328
+ #pendingRecovered;
1329
+ #sequence;
1330
+ #baseTs;
1331
+ #audioConcealer;
1332
+ #audioConcealClock;
1333
+ #audioConcealStats;
1334
+ #frameDuration;
1335
+ #lastEmittedTs;
1336
+ #lastSourceTs;
1337
+ #sampleReorderWindow;
1338
+ #sampleOrder;
1339
+ #sampleOrderCapacity;
1340
+ #sampleReorderQueue;
1341
+ #recoveredHorizonTs;
1342
+ #sampleOrderStats;
1343
+ #videoKeyframeFamily;
1344
+ #hevcSampleEntry;
1345
+ #keyframeRejectDumpCount;
1346
+ #armedVideo;
1347
+ /** Truncate `frames` to start at the first keyframe for video tracks before
1348
+ * the first emission. Returns the (possibly spliced) frames, or null to
1349
+ * drop the block entirely. Audio + already-armed video: identity. */
1350
+ #applyVideoKeyframeGate(frames) {
1351
+ const keyedFrames = this.#normalizeVideoKeyframes(frames);
1352
+ if (this.#config.trackType !== "video" || this.#armedVideo) return keyedFrames;
1353
+ const firstKfIdx = keyedFrames.findIndex((f) => f.keyframe);
1354
+ if (firstKfIdx < 0) return null;
1355
+ return firstKfIdx === 0 ? keyedFrames : keyedFrames.slice(firstKfIdx);
1356
+ }
1357
+ #normalizeVideoKeyframes(frames) {
1358
+ if (this.#config.trackType !== "video" || this.#videoKeyframeFamily === null) return frames;
1359
+ const out = [];
1360
+ for (const frame of frames) {
1361
+ const effective = this.#withEffectiveVideoKeyframe(frame);
1362
+ if (effective !== null) out.push(effective);
1363
+ }
1364
+ return out;
1365
+ }
1366
+ /** The frame with its bitstream keyframe (and, for HEVC, mdat framing);
1367
+ * null when the frame is refused and must not be emitted. */
1368
+ #withEffectiveVideoKeyframe(frame) {
1369
+ if (this.#config.trackType !== "video" || this.#videoKeyframeFamily === null) return frame;
1370
+ if (this.#videoKeyframeFamily === "hevc") {
1371
+ const prepared = prepareHevcCmafSample(frame.data, this.#hevcSampleEntry);
1372
+ if (prepared === null) {
1373
+ this.#sampleOrderStats.unreadableVideoSamples++;
1374
+ return null;
1375
+ }
1376
+ const { keyframe: keyframe2, data } = prepared;
1377
+ if (!keyframe2) this.#dumpRejectedVideoKeyframe(frame.data, frame.keyframe);
1378
+ return keyframe2 === frame.keyframe && data === frame.data ? frame : { ...frame, keyframe: keyframe2, data };
1379
+ }
1380
+ const keyframe = detectH264Keyframe(frame.data);
1381
+ if (!keyframe) this.#dumpRejectedVideoKeyframe(frame.data, frame.keyframe);
1382
+ return keyframe === frame.keyframe ? frame : { ...frame, keyframe };
1383
+ }
1384
+ #dumpRejectedVideoKeyframe(data, metadataKeyframe) {
1385
+ if (this.#keyframeRejectDumpCount >= 12) return;
1386
+ this.#keyframeRejectDumpCount++;
1387
+ if (this.#videoKeyframeFamily === "hevc") {
1388
+ const nals = isCompleteAvccSample(data) ? splitAvccNalUnits(data) : isAnnexB(data) ? splitAnnexBNalUnits(data) : [];
1389
+ console.log(
1390
+ `[L4-KF-GATE] reject#${this.#keyframeRejectDumpCount} len=${data.length} metadataKf=${metadataKeyframe} family=hevc nalTypes=[${nals.slice(0, 16).map((nal) => nal.length >= 2 ? hevcNalUnitType(nal) : -1).join(",")}]`
1391
+ );
1392
+ return;
1393
+ }
1394
+ const sample = splitH264SampleNalUnits(data);
1395
+ const nalTypes = describeH264NalTypes(sample.nals);
1396
+ const classify = classifyH264Keyframe(data);
1397
+ const hex = Array.from(data.subarray(0, Math.min(48, data.length))).map((b) => b.toString(16).padStart(2, "0")).join(" ");
1398
+ console.log(
1399
+ `[L4-KF-GATE] reject#${this.#keyframeRejectDumpCount} len=${data.length} metadataKf=${metadataKeyframe} classify=${classify} format=${sample.format} nalTypes=[${nalTypes.join(",")}] first48=[${hex}]`
1400
+ );
1401
+ }
1402
+ /** Mark video as already synchronized by an external decoder path.
1403
+ * Used by MoQ→multicast MSE continuity when MoQ has already appended a
1404
+ * keyframe to the same SourceBuffer timeline before multicast takeover. */
1405
+ markVideoSynced() {
1406
+ if (this.#config.trackType === "video") this.#armedVideo = true;
1407
+ }
1408
+ /** Emit each frame as its own single-sample moof+mdat segment. Matches the
1409
+ * case-20 path (`MmtpToCmaf.wrapVideoSample` → `encodeDataSegment`) byte-
1410
+ * for-byte per frame. Working hypothesis (pending Chromium-source
1411
+ * validation against `media/filters/chunk_demuxer.cc`):
1412
+ * `encodeMultiSampleSegment` blobs are accepted by ChunkDemuxer in this
1413
+ * pipeline but only the first sample renders for live, possibly because
1414
+ * the pipeline expects per-frame moof boundaries. Track in BLO-3035.
1415
+ *
1416
+ * Stale-tfdt defense-in-depth: drops any frame whose timestamp is older
1417
+ * than `#lastEmittedTs`. The SBN watermark already prevents out-of-order
1418
+ * FEC-block emissions, but `addBypassFrame` (oversized MFU / no-FEC path)
1419
+ * doesn't touch the watermark — a bypass frame at t=T followed by a FEC
1420
+ * block whose frames precede T would otherwise inject earlier tfdt and
1421
+ * detach the SourceBuffer. */
1422
+ #ordersSamples() {
1423
+ return this.#sampleOrder.mode === "media-window" || this.#sampleReorderWindow > 0;
1424
+ }
1425
+ #unwrapTimestamp(timestamp) {
1426
+ const wrapPeriod = this.#sampleOrder.mode === "media-window" ? this.#sampleOrder.timestampWrapPeriod : void 0;
1427
+ if (!wrapPeriod) return timestamp;
1428
+ const reference = this.#lastSourceTs >= 0 ? this.#lastSourceTs : this.#recoveredHorizonTs >= 0 ? this.#recoveredHorizonTs : this.#lastEmittedTs;
1429
+ if (reference < 0) return timestamp;
1430
+ return timestamp + Math.round((reference - timestamp) / wrapPeriod) * wrapPeriod;
1431
+ }
1432
+ #emitSample(data, timestamp, duration, keyframe, advancesHorizon, catalogTrackName, mpuSequenceNumber, packetSequenceNumber, packetSequenceNumbers, repairedPacketSequenceNumbers, authoredTiming, deliveryProvenance, mmtpTimestamp, movieFragmentSequenceNumber, sampleNumber, synthetic, gapBefore) {
1433
+ if (authoredTiming !== void 0 && !this.#config.admitAuthoredTiming) {
1434
+ this.#sampleOrderStats.unadmittedAuthoredSamples++;
1435
+ return;
1436
+ }
1437
+ const scaledTiming = authoredTiming === void 0 ? null : scaleAuthoredTiming(authoredTiming, this.#config.timescale);
1438
+ if (authoredTiming !== void 0 && scaledTiming === null) return;
1439
+ const authoredTimestamp = scaledTiming?.timestamp ?? timestamp;
1440
+ const authoredDuration = scaledTiming?.duration ?? duration;
1441
+ let compositionTimeOffset;
1442
+ if (authoredTiming !== void 0) {
1443
+ const scaledOffset = scaleAuthoredTicks(
1444
+ authoredTiming.presentationTime - authoredTiming.decodeTime,
1445
+ authoredTiming.mediaTimescale,
1446
+ this.#config.timescale
1447
+ );
1448
+ if (scaledOffset === null) return;
1449
+ const roundedOffset = Math.round(scaledOffset);
1450
+ if (!Number.isSafeInteger(roundedOffset) || roundedOffset < INT32_MIN2 || roundedOffset > INT32_MAX2) return;
1451
+ compositionTimeOffset = roundedOffset;
1452
+ }
1453
+ const unwrappedTimestamp = this.#unwrapTimestamp(authoredTimestamp);
1454
+ if (unwrappedTimestamp <= this.#lastEmittedTs) {
1455
+ this.#sampleOrderStats.staleSamples++;
1456
+ return;
1457
+ }
1458
+ const sample = this.#withEffectiveVideoKeyframe({
1459
+ data,
1460
+ timestamp: unwrappedTimestamp,
1461
+ duration: authoredDuration,
1462
+ keyframe,
1463
+ ...mmtpTimestamp === void 0 ? {} : { mmtpTimestamp },
1464
+ ...compositionTimeOffset === void 0 ? {} : { compositionTimeOffset },
1465
+ advancesHorizon,
1466
+ ...authoredTiming === void 0 ? {} : { authoredTiming },
1467
+ ...packetSequenceNumber === void 0 ? {} : { packetSequenceNumber },
1468
+ ...packetSequenceNumbers === void 0 ? {} : { packetSequenceNumbers },
1469
+ ...repairedPacketSequenceNumbers === void 0 ? {} : { repairedPacketSequenceNumbers },
1470
+ ...mpuSequenceNumber === void 0 ? {} : { mpuSequenceNumber },
1471
+ ...movieFragmentSequenceNumber === void 0 ? {} : { movieFragmentSequenceNumber },
1472
+ ...sampleNumber === void 0 ? {} : { sampleNumber },
1473
+ ...catalogTrackName === void 0 ? {} : { catalogTrackName },
1474
+ ...deliveryProvenance === void 0 ? {} : { deliveryProvenance },
1475
+ ...synthetic === void 0 ? {} : { synthetic },
1476
+ ...gapBefore === void 0 ? {} : { gapBefore }
1477
+ });
1478
+ if (sample === null) return;
1479
+ if (advancesHorizon && unwrappedTimestamp > this.#lastSourceTs) {
1480
+ this.#lastSourceTs = unwrappedTimestamp;
1481
+ } else if (!advancesHorizon && unwrappedTimestamp > this.#recoveredHorizonTs) {
1482
+ this.#recoveredHorizonTs = unwrappedTimestamp;
1483
+ }
1484
+ if (this.#ordersSamples()) {
1485
+ this.#queueSample(sample);
1486
+ return;
1487
+ }
1488
+ this.#emitArrivalOrdered(sample);
1489
+ }
1490
+ #emitArrivalOrdered(sample) {
1491
+ if (this.#config.trackType === "video" && !this.#armedVideo && !sample.keyframe) {
1492
+ this.#sampleOrderStats.preRapDeadlineDrops++;
1493
+ return;
1494
+ }
1495
+ this.#emitSampleNow(sample);
1496
+ }
1497
+ #queueSample(sample) {
1498
+ if (this.#sampleReorderQueue.some((s) => s.timestamp === sample.timestamp)) {
1499
+ this.#sampleOrderStats.duplicateSamples++;
1500
+ return;
1501
+ }
1502
+ this.#sampleReorderQueue.push(sample);
1503
+ this.#sampleReorderQueue.sort((a, b) => a.timestamp - b.timestamp);
1504
+ this.#drainSampleReorder(false);
1505
+ this.#enforceSampleOrderCapacity();
1506
+ }
1507
+ #releaseHorizon() {
1508
+ return this.#lastSourceTs >= 0 ? this.#lastSourceTs : this.#recoveredHorizonTs;
1509
+ }
1510
+ #sampleIsReleasable(sample, flushAll) {
1511
+ if (flushAll) return true;
1512
+ if (this.#sampleOrder.mode === "media-window") {
1513
+ const horizon = this.#releaseHorizon();
1514
+ return horizon >= 0 && sample.timestamp < horizon - this.#sampleOrder.deliveryWindow;
1515
+ }
1516
+ return this.#sampleReorderQueue.length > this.#sampleReorderWindow;
1517
+ }
1518
+ #dropPreRapSamples(flushAll) {
1519
+ if (this.#config.trackType !== "video" || this.#armedVideo) return false;
1520
+ const firstRap = this.#sampleReorderQueue.findIndex(
1521
+ (sample) => sample.keyframe && this.#sampleIsReleasable(sample, flushAll)
1522
+ );
1523
+ if (firstRap >= 0) {
1524
+ if (firstRap > 0) {
1525
+ this.#sampleOrderStats.preRapDeadlineDrops += firstRap;
1526
+ this.#sampleReorderQueue.splice(0, firstRap);
1527
+ }
1528
+ return false;
1529
+ }
1530
+ let dropped = 0;
1531
+ while (this.#sampleReorderQueue[0] && this.#sampleIsReleasable(this.#sampleReorderQueue[0], flushAll)) {
1532
+ this.#sampleReorderQueue.shift();
1533
+ dropped++;
1534
+ }
1535
+ if (flushAll) this.#sampleOrderStats.noRapFlushDrops += dropped;
1536
+ else this.#sampleOrderStats.preRapDeadlineDrops += dropped;
1537
+ return dropped > 0;
1538
+ }
1539
+ #drainSampleReorder(flushAll) {
1540
+ while (this.#sampleReorderQueue.length > 0) {
1541
+ if (this.#dropPreRapSamples(flushAll) && this.#sampleReorderQueue.length === 0) return;
1542
+ const sample = this.#sampleReorderQueue[0];
1543
+ if (!sample || !this.#sampleIsReleasable(sample, flushAll)) return;
1544
+ this.#sampleReorderQueue.shift();
1545
+ this.#emitQueuedSample(sample);
1546
+ }
1547
+ }
1548
+ #emitQueuedSample(sample) {
1549
+ const next = this.#sampleReorderQueue.find((s) => s.timestamp > sample.timestamp);
1550
+ const duration = sample.authoredTiming ? sample.duration : next ? next.timestamp - sample.timestamp : sample.duration;
1551
+ this.#emitSampleNow({
1552
+ ...sample,
1553
+ duration: duration > 0 ? duration : sample.authoredTiming ? sample.duration : this.#frameDuration
1554
+ });
1555
+ }
1556
+ #enforceSampleOrderCapacity() {
1557
+ if (this.#sampleOrder.mode !== "media-window") return;
1558
+ while (this.#sampleReorderQueue.length > this.#sampleOrderCapacity) {
1559
+ const sample = this.#sampleReorderQueue.shift();
1560
+ if (!sample) return;
1561
+ this.#sampleOrderStats.forcedReleases++;
1562
+ console.warn(
1563
+ `[CmafBlockAssembler] ${this.#config.trackType} media-window queue exceeded ${this.#sampleOrderCapacity} samples; force-releasing timestamp=${sample.timestamp}`
1564
+ );
1565
+ if (this.#config.trackType === "video" && !this.#armedVideo && !sample.keyframe) {
1566
+ this.#sampleOrderStats.preRapDeadlineDrops++;
1567
+ continue;
1568
+ }
1569
+ this.#emitQueuedSample(sample);
1570
+ }
1571
+ }
1572
+ #emitSampleNow(sample) {
1573
+ if (sample.timestamp <= this.#lastEmittedTs) {
1574
+ this.#sampleOrderStats.staleSamples++;
1575
+ return;
1576
+ }
1577
+ this.#concealAudioGapBefore(sample);
1578
+ this.#writeSampleNow(sample, true);
1579
+ }
1580
+ #writeSampleNow(sample, rememberAudio) {
1581
+ const { timestamp, duration, keyframe } = sample;
1582
+ this.#lastEmittedTs = timestamp;
1583
+ if (this.#config.trackType === "video" && keyframe) this.#armedVideo = true;
1584
+ const data = this.#normalizeSampleData(sample.data);
1585
+ if (this.#config.trackType === "audio" && rememberAudio && data.length > 0) {
1586
+ this.#noteAudioAccessUnit(data, sample.authoredTiming);
1587
+ }
1588
+ if (this.onSample) {
1589
+ this.onSample(data === sample.data ? sample : { ...sample, data });
1590
+ } else {
1591
+ const baseTime = this.#rebase(timestamp);
1592
+ const segment = encodeDataSegment(
1593
+ data,
1594
+ baseTime,
1595
+ duration,
1596
+ keyframe,
1597
+ this.#sequence++,
1598
+ this.#config.trackId,
1599
+ sample.compositionTimeOffset
1600
+ );
1601
+ this.onSegment?.(segment);
1602
+ }
1603
+ }
1604
+ /**
1605
+ * Record an emitted audio AU for concealment in its authored media ticks —
1606
+ * the clock libmmt's `audio-gap` decision was computed in, where an AAC AU
1607
+ * is exactly 1024 ticks. An AU with no authored timing has no exact clock,
1608
+ * so nothing is held for it and a later `audio-gap` is counted as untimed.
1609
+ */
1610
+ #noteAudioAccessUnit(data, timing) {
1611
+ if (timing === void 0) {
1612
+ this.#audioConcealer.reset();
1613
+ this.#audioConcealClock = "untimed";
1614
+ return;
1615
+ }
1616
+ this.#audioConcealer.note({
1617
+ payload: data,
1618
+ pts: timing.presentationTime,
1619
+ duration: timing.durationTicks
1620
+ });
1621
+ this.#audioConcealClock = timing.mediaTimescale;
1622
+ }
1623
+ /**
1624
+ * Repeat the last good AU into exactly the slots an `audio-gap` decision
1625
+ * names. A synthesised AAC access unit is not portable across every
1626
+ * AudioSpecificConfig, so only known-good encoded audio is repeated; with
1627
+ * no good AU yet, or on `audio-discontinuity`, the sink re-anchors at the
1628
+ * next sample and nothing is written.
1629
+ *
1630
+ * The gap is sized in authored ticks and each slot is mapped onto this
1631
+ * assembler's timescale by `scaleAuthoredTiming`, the conversion every
1632
+ * source AU goes through, so a slot lands exactly where the AU it replaces
1633
+ * would have. Nothing here can throw into the packet path: a gap that
1634
+ * cannot be sized exactly is re-anchored and counted.
1635
+ */
1636
+ #concealAudioGapBefore(sample) {
1637
+ const decision = sample.gapBefore;
1638
+ if (this.#config.trackType !== "audio" || !decision || decision.trackKind !== "audio") return;
1639
+ const timing = sample.authoredTiming;
1640
+ const clock = this.#audioConcealClock;
1641
+ if (timing === void 0 || clock === "untimed" || clock !== null && clock !== timing.mediaTimescale) {
1642
+ if (decision.reason === "audio-gap") this.#audioConcealStats.untimedGaps++;
1643
+ else this.#audioConcealStats.reanchoredGaps++;
1644
+ return;
1645
+ }
1646
+ const plan = this.#audioConcealer.plan(decision, { pts: timing.presentationTime });
1647
+ if (plan.kind !== "conceal") {
1648
+ this.#audioConcealStats.reanchoredGaps++;
1649
+ return;
1650
+ }
1651
+ for (const slot of plan.repeat) {
1652
+ const scaled = scaleAuthoredTiming({
1653
+ decodeTime: slot.pts,
1654
+ presentationTime: slot.pts,
1655
+ durationTicks: slot.duration,
1656
+ mediaTimescale: timing.mediaTimescale
1657
+ }, this.#config.timescale);
1658
+ if (scaled === null) continue;
1659
+ const slotTimestamp = this.#unwrapTimestamp(scaled.timestamp);
1660
+ if (slotTimestamp <= this.#lastEmittedTs || slotTimestamp >= sample.timestamp) continue;
1661
+ this.#writeSampleNow({
1662
+ data: slot.payload.slice(),
1663
+ timestamp: slotTimestamp,
1664
+ duration: scaled.duration,
1665
+ keyframe: true,
1666
+ synthetic: true
1667
+ }, false);
1668
+ this.#audioConcealStats.repeatedUnits++;
1669
+ }
1670
+ }
1671
+ #emitPerSample(frames, audioDurationOverride, advancesHorizon = false) {
1672
+ for (let i = 0; i < frames.length; i++) {
1673
+ const f = frames[i];
1674
+ let duration;
1675
+ if (this.#config.trackType === "audio") {
1676
+ duration = audioDurationOverride ?? this.#frameDuration;
1677
+ } else if (i < frames.length - 1) {
1678
+ duration = frames[i + 1].timestamp - f.timestamp;
1679
+ } else if (i > 0) {
1680
+ duration = f.timestamp - frames[i - 1].timestamp;
1681
+ } else {
1682
+ duration = audioDurationOverride ?? this.#frameDuration;
1683
+ }
1684
+ if (duration <= 0) duration = audioDurationOverride ?? this.#frameDuration;
1685
+ this.#emitSample(
1686
+ f.data,
1687
+ f.timestamp,
1688
+ duration,
1689
+ f.keyframe,
1690
+ advancesHorizon,
1691
+ f.catalogTrackName,
1692
+ f.mpuSequenceNumber,
1693
+ f.packetSequenceNumber,
1694
+ f.packetSequenceNumbers,
1695
+ f.repairedPacketSequenceNumbers,
1696
+ f.authoredTiming,
1697
+ f.deliveryProvenance,
1698
+ f.mmtpTimestamp,
1699
+ f.movieFragmentSequenceNumber,
1700
+ f.sampleNumber,
1701
+ f.synthetic,
1702
+ f.gapBefore
1703
+ );
1704
+ }
1705
+ }
1706
+ #emitStats;
1707
+ #countEmit(samples) {
1708
+ this.#emitStats.emits++;
1709
+ this.#emitStats.samples += samples.length;
1710
+ for (const sample of samples) if (sample.keyframe) this.#emitStats.keyframes++;
1711
+ }
1712
+ get sampleOrderStats() {
1713
+ return { ...this.#sampleOrderStats };
1714
+ }
1715
+ /** Cumulative emit and block-event counters since construction. */
1716
+ get emitStats() {
1717
+ return { ...this.#emitStats };
1718
+ }
1719
+ /** Cumulative audio gap concealment counters since construction. */
1720
+ get audioConcealStats() {
1721
+ return { ...this.#audioConcealStats };
1722
+ }
1723
+ /** Emit a single frame immediately as a one-sample moof+mdat segment.
1724
+ *
1725
+ * BLO-3035 layer 4 (4b): the prior SBN-grouped buffering scheme stranded
1726
+ * frames whenever a multi-packet frame spanned FEC block boundaries —
1727
+ * intermediate SBNs had packets-but-no-frames and got `completeBlock`
1728
+ * events that landed on empty `#blocks` (→ `pendingFlush` leak), while
1729
+ * the SBN where the multi-packet frame finally completed received the
1730
+ * `addFrame` but its `trackBlock` count never reached K (→ `pendingBlocks`
1731
+ * leak). Result: ~50% of received frames never reached MSE.
1732
+ *
1733
+ * This path now mirrors `addBypassFrame` — emit on arrival, no buffering.
1734
+ * FEC recovery (`addRecoveredBlock`) keeps its SBN-watermark dedup against
1735
+ * the same SBN being re-emitted from two paths. Out-of-order regression
1736
+ * is guarded by the per-frame `lastEmittedTs` check (also enforced in
1737
+ * `#emitPerSample`). The `sbn`/`esi` parameters are kept for the call-site
1738
+ * signature but no longer affect routing. */
1739
+ addFrame(sbn, esi, data, timestamp, keyframe, catalogTrackName, mpuSequenceNumber, packetSequenceNumber, packetSequenceNumbers, repairedPacketSequenceNumbers, authoredTiming, deliveryProvenance, mmtpTimestamp, movieFragmentSequenceNumber, sampleNumber, gapBefore) {
1740
+ void sbn;
1741
+ void esi;
1742
+ this.#emitStats.addedFrames++;
1743
+ if (!this.#ordersSamples()) this.#drainRecoveredUpTo(timestamp);
1744
+ this.#emitSample(
1745
+ data,
1746
+ timestamp,
1747
+ this.#frameDuration,
1748
+ keyframe,
1749
+ true,
1750
+ catalogTrackName,
1751
+ mpuSequenceNumber,
1752
+ packetSequenceNumber,
1753
+ packetSequenceNumbers,
1754
+ repairedPacketSequenceNumbers,
1755
+ authoredTiming,
1756
+ deliveryProvenance,
1757
+ mmtpTimestamp,
1758
+ movieFragmentSequenceNumber,
1759
+ sampleNumber,
1760
+ void 0,
1761
+ gapBefore
1762
+ );
1763
+ this.#countEmit([{ keyframe }]);
1764
+ }
1765
+ /** Mark a block as complete (all K source symbols received or FEC recovery succeeded).
1766
+ * If all frames are already buffered, flushes immediately. Otherwise sets pending-flush. */
1767
+ completeBlock(sbn) {
1768
+ void sbn;
1769
+ this.#emitStats.completedBlocks++;
1770
+ }
1771
+ /**
1772
+ * Record an unrecoverable block. Nothing is synthesised: the release gate
1773
+ * attaches the stall/conceal decision to the next released frame, and the
1774
+ * sink holds the last good frame (video) or repeats the last good AU into
1775
+ * the decided slots (audio).
1776
+ */
1777
+ failBlock(sbn) {
1778
+ void sbn;
1779
+ this.#emitStats.failedBlocks++;
1780
+ }
1781
+ /** Add all frames from a FEC-recovered block at once and emit immediately. */
1782
+ addRecoveredBlock(sbn, frames) {
1783
+ void sbn;
1784
+ this.#emitStats.recoveredBlocks++;
1785
+ if (frames.length === 0) return;
1786
+ const normalized = this.#normalizeVideoKeyframes(frames);
1787
+ if (normalized.length === 0) return;
1788
+ this.#countEmit(normalized);
1789
+ if (this.#ordersSamples()) {
1790
+ this.#emitPerSample(normalized, void 0, false);
1791
+ return;
1792
+ }
1793
+ if (this.#lastSourceTs >= 0) {
1794
+ this.#enqueueRecovered(normalized);
1795
+ this.#drainRecoveredUpTo(this.#lastSourceTs);
1796
+ } else {
1797
+ const gated = this.#applyVideoKeyframeGate(normalized);
1798
+ if (gated) this.#emitPerSample(gated, void 0, false);
1799
+ }
1800
+ }
1801
+ /** Emit a single frame immediately as a one-sample segment (for oversized packets bypassing FEC). */
1802
+ addBypassFrame(data, timestamp, keyframe, catalogTrackName, mpuSequenceNumber, packetSequenceNumber, packetSequenceNumbers, repairedPacketSequenceNumbers, authoredTiming, deliveryProvenance, mmtpTimestamp, movieFragmentSequenceNumber, sampleNumber, gapBefore) {
1803
+ if (!this.#ordersSamples()) this.#drainRecoveredUpTo(timestamp);
1804
+ this.#emitSample(
1805
+ data,
1806
+ timestamp,
1807
+ this.#frameDuration,
1808
+ keyframe,
1809
+ true,
1810
+ catalogTrackName,
1811
+ mpuSequenceNumber,
1812
+ packetSequenceNumber,
1813
+ packetSequenceNumbers,
1814
+ repairedPacketSequenceNumbers,
1815
+ authoredTiming,
1816
+ deliveryProvenance,
1817
+ mmtpTimestamp,
1818
+ movieFragmentSequenceNumber,
1819
+ sampleNumber,
1820
+ void 0,
1821
+ gapBefore
1822
+ );
1823
+ }
1824
+ /** Build and emit init segment from catalog config. */
1825
+ emitInit() {
1826
+ let init = null;
1827
+ if (this._videoConfig?.avcC) {
1828
+ init = buildVideoInitSegment(
1829
+ this._videoConfig.avcC,
1830
+ this._videoConfig.width,
1831
+ this._videoConfig.height,
1832
+ this.#config.timescale,
1833
+ this.#config.trackId
1834
+ );
1835
+ } else if (this._videoConfig?.hvcC && this._videoConfig.hevcSampleEntry) {
1836
+ init = buildHevcVideoInitSegment(
1837
+ this._videoConfig.hevcSampleEntry,
1838
+ this._videoConfig.hvcC,
1839
+ this._videoConfig.width,
1840
+ this._videoConfig.height,
1841
+ this.#config.timescale,
1842
+ this.#config.trackId
1843
+ );
1844
+ } else if (this._audioConfig) {
1845
+ init = buildAudioInitSegment(
1846
+ this._audioConfig.sampleRate,
1847
+ this._audioConfig.channels,
1848
+ this._audioConfig.asc,
1849
+ this.#config.timescale,
1850
+ this.#config.trackId
1851
+ );
1852
+ }
1853
+ if (init) this.onInitSegment?.(init);
1854
+ }
1855
+ /** Drain all ordered samples at end-of-stream or before reconfiguration. */
1856
+ flush() {
1857
+ if (this.#ordersSamples()) {
1858
+ this.#drainSampleReorder(true);
1859
+ return;
1860
+ }
1861
+ if (this.#pendingRecovered.size === 0) return;
1862
+ const frames = [...this.#pendingRecovered.values()].sort((a, b) => a.timestamp - b.timestamp);
1863
+ this.#pendingRecovered.clear();
1864
+ const gated = this.#applyVideoKeyframeGate(frames);
1865
+ if (gated) this.#emitPerSample(gated, void 0, false);
1866
+ else if (this.#config.trackType === "video") {
1867
+ this.#sampleOrderStats.noRapFlushDrops += frames.length;
1868
+ }
1869
+ }
1870
+ /** Drop all queued state and begin a fresh timestamp epoch. */
1871
+ reset() {
1872
+ this.#pendingRecovered.clear();
1873
+ this.#sequence = 1;
1874
+ this.#baseTs = -1;
1875
+ this.#lastEmittedTs = -1;
1876
+ this.#lastSourceTs = -1;
1877
+ this.#recoveredHorizonTs = -1;
1878
+ this.#audioConcealer.reset();
1879
+ this.#audioConcealClock = null;
1880
+ this.#armedVideo = false;
1881
+ this.#sampleReorderQueue = [];
1882
+ }
1883
+ dispose() {
1884
+ this.reset();
1885
+ this.onSegment = null;
1886
+ this.onSample = null;
1887
+ this.onInitSegment = null;
1888
+ }
1889
+ // ── Private ──
1890
+ /** Rebase an absolute timestamp to relative media time (starting near 0). */
1891
+ #rebase(timestamp) {
1892
+ if (this.#baseTs < 0) this.#baseTs = timestamp;
1893
+ return timestamp - this.#baseTs;
1894
+ }
1895
+ #normalizeSampleData(data) {
1896
+ return this.#config.trackType === "audio" ? normalizeAacSampleForCmaf(data) : data;
1897
+ }
1898
+ #enqueueRecovered(frames) {
1899
+ for (const frame of frames) {
1900
+ if (this.#lastEmittedTs >= 0 && frame.timestamp <= this.#lastEmittedTs) {
1901
+ this.#sampleOrderStats.staleSamples++;
1902
+ continue;
1903
+ }
1904
+ if (this.#pendingRecovered.has(frame.timestamp)) {
1905
+ this.#sampleOrderStats.duplicateSamples++;
1906
+ continue;
1907
+ }
1908
+ this.#pendingRecovered.set(frame.timestamp, frame);
1909
+ }
1910
+ }
1911
+ #drainRecoveredUpTo(horizonTs) {
1912
+ if (this.#pendingRecovered.size === 0) return;
1913
+ const ready = [...this.#pendingRecovered.values()].filter((frame) => frame.timestamp <= horizonTs).sort((a, b) => a.timestamp - b.timestamp);
1914
+ for (const frame of ready) {
1915
+ this.#pendingRecovered.delete(frame.timestamp);
1916
+ this.#emitSample(
1917
+ frame.data,
1918
+ frame.timestamp,
1919
+ this.#frameDuration,
1920
+ frame.keyframe,
1921
+ false,
1922
+ frame.catalogTrackName,
1923
+ frame.mpuSequenceNumber,
1924
+ frame.packetSequenceNumber,
1925
+ frame.packetSequenceNumbers,
1926
+ frame.repairedPacketSequenceNumbers,
1927
+ frame.authoredTiming,
1928
+ frame.deliveryProvenance,
1929
+ frame.mmtpTimestamp,
1930
+ frame.movieFragmentSequenceNumber,
1931
+ frame.sampleNumber,
1932
+ frame.synthetic,
1933
+ frame.gapBefore
1934
+ );
1935
+ this.#countEmit([frame]);
1936
+ }
1937
+ }
1938
+ };
1939
+ function resolveVideoSampleEntry(config) {
1940
+ if (!config.codec) {
1941
+ if (config.hvcC) {
1942
+ throw new Error("[CmafBlockAssembler] hvcC requires a catalog codec string naming hev1 or hvc1");
1943
+ }
1944
+ return "avc1";
1945
+ }
1946
+ const fourCc = config.codec.split(".")[0];
1947
+ if (fourCc !== "avc1" && fourCc !== "avc3" && fourCc !== "hev1" && fourCc !== "hvc1") {
1948
+ if (config.avcC || config.hvcC) {
1949
+ throw new Error(`[CmafBlockAssembler] codec ${config.codec} contradicts the supplied avcC/hvcC`);
1950
+ }
1951
+ return "unvalidated";
1952
+ }
1953
+ const sampleEntry = videoSampleEntryFromCodecString(config.codec);
1954
+ const family = videoCodecFamily(sampleEntry);
1955
+ if (family === "avc" && config.hvcC || family === "hevc" && config.avcC) {
1956
+ throw new Error(`[CmafBlockAssembler] codec ${config.codec} contradicts the supplied avcC/hvcC`);
1957
+ }
1958
+ return sampleEntry;
1959
+ }
1960
+ function describeH264NalTypes(nals) {
1961
+ return nals.slice(0, 16).map((nal) => nal[0] !== void 0 ? nal[0] & 31 : -1);
1962
+ }
1963
+ export {
1964
+ CmafBlockAssembler
1965
+ };
1966
+ //# sourceMappingURL=cmaf-block-assembler.js.map