@blockcast/mmt-container 0.1.0-main.149f78a4adae

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (678) hide show
  1. package/README.md +432 -0
  2. package/dist/.build-stamp +0 -0
  3. package/dist/__tests__/test-utils.d.ts +71 -0
  4. package/dist/__tests__/test-utils.d.ts.map +1 -0
  5. package/dist/align.d.ts +148 -0
  6. package/dist/align.d.ts.map +1 -0
  7. package/dist/align.js +88 -0
  8. package/dist/align.js.map +7 -0
  9. package/dist/audio-init-parser.d.ts +66 -0
  10. package/dist/audio-init-parser.d.ts.map +1 -0
  11. package/dist/audio-init-parser.js +118 -0
  12. package/dist/audio-init-parser.js.map +7 -0
  13. package/dist/audio-ring-buffer.d.ts +50 -0
  14. package/dist/audio-ring-buffer.d.ts.map +1 -0
  15. package/dist/audio-ring-buffer.js +93 -0
  16. package/dist/audio-ring-buffer.js.map +7 -0
  17. package/dist/authored-timing.d.ts +32 -0
  18. package/dist/authored-timing.d.ts.map +1 -0
  19. package/dist/authored-timing.js +32 -0
  20. package/dist/authored-timing.js.map +7 -0
  21. package/dist/browser-runtime.js +17109 -0
  22. package/dist/browser-runtime.js.map +7 -0
  23. package/dist/carp-catalog.d.ts +318 -0
  24. package/dist/carp-catalog.d.ts.map +1 -0
  25. package/dist/carp-catalog.js +549 -0
  26. package/dist/carp-catalog.js.map +7 -0
  27. package/dist/catalog-fec-params.d.ts +82 -0
  28. package/dist/catalog-fec-params.d.ts.map +1 -0
  29. package/dist/catalog-fec-params.js +66 -0
  30. package/dist/catalog-fec-params.js.map +7 -0
  31. package/dist/catalog-network-source.d.ts +19 -0
  32. package/dist/catalog-network-source.d.ts.map +1 -0
  33. package/dist/catalog-network-source.js +22 -0
  34. package/dist/catalog-network-source.js.map +7 -0
  35. package/dist/catalog-validator.d.ts +18 -0
  36. package/dist/catalog-validator.d.ts.map +1 -0
  37. package/dist/catalog-validator.js +7747 -0
  38. package/dist/catalog-validator.js.map +7 -0
  39. package/dist/cmaf-block-assembler.d.ts +168 -0
  40. package/dist/cmaf-block-assembler.d.ts.map +1 -0
  41. package/dist/cmaf-block-assembler.js +1755 -0
  42. package/dist/cmaf-block-assembler.js.map +7 -0
  43. package/dist/cmaf-group-batcher.d.ts +38 -0
  44. package/dist/cmaf-group-batcher.d.ts.map +1 -0
  45. package/dist/cmaf-group-batcher.js +195 -0
  46. package/dist/cmaf-group-batcher.js.map +7 -0
  47. package/dist/cmcd-producer.d.ts +104 -0
  48. package/dist/cmcd-producer.d.ts.map +1 -0
  49. package/dist/cmcd-producer.js +207 -0
  50. package/dist/cmcd-producer.js.map +7 -0
  51. package/dist/codec-utils.d.ts +235 -0
  52. package/dist/codec-utils.d.ts.map +1 -0
  53. package/dist/codec-utils.js +1225 -0
  54. package/dist/codec-utils.js.map +7 -0
  55. package/dist/fec-codec.d.ts +32 -0
  56. package/dist/fec-codec.d.ts.map +1 -0
  57. package/dist/fec-codec.js +47 -0
  58. package/dist/fec-codec.js.map +7 -0
  59. package/dist/fec-manager.d.ts +266 -0
  60. package/dist/fec-manager.d.ts.map +1 -0
  61. package/dist/fec-manager.js +1447 -0
  62. package/dist/fec-manager.js.map +7 -0
  63. package/dist/fec-starvation-detector.d.ts +59 -0
  64. package/dist/fec-starvation-detector.d.ts.map +1 -0
  65. package/dist/fec-starvation-detector.js +75 -0
  66. package/dist/fec-starvation-detector.js.map +7 -0
  67. package/dist/fec-worker-setup.d.ts +76 -0
  68. package/dist/fec-worker-setup.d.ts.map +1 -0
  69. package/dist/fec-worker-setup.js +603 -0
  70. package/dist/fec-worker-setup.js.map +7 -0
  71. package/dist/fmp4-completion.d.ts +30 -0
  72. package/dist/fmp4-completion.d.ts.map +1 -0
  73. package/dist/fmp4-completion.js +21 -0
  74. package/dist/fmp4-completion.js.map +7 -0
  75. package/dist/fmp4-reader.d.ts +37 -0
  76. package/dist/fmp4-reader.d.ts.map +1 -0
  77. package/dist/fmp4-reader.js +100 -0
  78. package/dist/fmp4-reader.js.map +7 -0
  79. package/dist/index.d.ts +47 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +330 -0
  82. package/dist/index.js.map +7 -0
  83. package/dist/iso-bmff-timing.d.ts +47 -0
  84. package/dist/iso-bmff-timing.d.ts.map +1 -0
  85. package/dist/iso-bmff-timing.js +526 -0
  86. package/dist/iso-bmff-timing.js.map +7 -0
  87. package/dist/loc.d.ts +68 -0
  88. package/dist/loc.d.ts.map +1 -0
  89. package/dist/loc.js +143 -0
  90. package/dist/loc.js.map +7 -0
  91. package/dist/manifest-auth-plan.d.ts +30 -0
  92. package/dist/manifest-auth-plan.d.ts.map +1 -0
  93. package/dist/manifest-auth-plan.js +1267 -0
  94. package/dist/manifest-auth-plan.js.map +7 -0
  95. package/dist/media-router.d.ts +338 -0
  96. package/dist/media-router.d.ts.map +1 -0
  97. package/dist/media-router.js +802 -0
  98. package/dist/media-router.js.map +7 -0
  99. package/dist/mfu-reassembler.d.ts +264 -0
  100. package/dist/mfu-reassembler.d.ts.map +1 -0
  101. package/dist/mfu-reassembler.js +2668 -0
  102. package/dist/mfu-reassembler.js.map +7 -0
  103. package/dist/mfu-reassembly-policy.d.ts +24 -0
  104. package/dist/mfu-reassembly-policy.d.ts.map +1 -0
  105. package/dist/mfu-reassembly-policy.js +99 -0
  106. package/dist/mfu-reassembly-policy.js.map +7 -0
  107. package/dist/mmtp-container-parser.d.ts +304 -0
  108. package/dist/mmtp-container-parser.d.ts.map +1 -0
  109. package/dist/mmtp-container-parser.js +5378 -0
  110. package/dist/mmtp-container-parser.js.map +7 -0
  111. package/dist/mmtp-container-parser.no-modules.js +7853 -0
  112. package/dist/mmtp-container-parser.no-modules.js.map +7 -0
  113. package/dist/mmtp-decode-pipeline.d.ts +96 -0
  114. package/dist/mmtp-decode-pipeline.d.ts.map +1 -0
  115. package/dist/mmtp-decode-pipeline.js +5589 -0
  116. package/dist/mmtp-decode-pipeline.js.map +7 -0
  117. package/dist/mmtp-router.d.ts +383 -0
  118. package/dist/mmtp-router.d.ts.map +1 -0
  119. package/dist/mmtp-router.js +8384 -0
  120. package/dist/mmtp-router.js.map +7 -0
  121. package/dist/mmtp-to-cmaf.d.ts +166 -0
  122. package/dist/mmtp-to-cmaf.d.ts.map +1 -0
  123. package/dist/mmtp-to-cmaf.js +781 -0
  124. package/dist/mmtp-to-cmaf.js.map +7 -0
  125. package/dist/multicast-auth-catalog.d.ts +115 -0
  126. package/dist/multicast-auth-catalog.d.ts.map +1 -0
  127. package/dist/multicast-auth-catalog.js +202 -0
  128. package/dist/multicast-auth-catalog.js.map +7 -0
  129. package/dist/multicast-input.d.ts +107 -0
  130. package/dist/multicast-input.d.ts.map +1 -0
  131. package/dist/multicast-input.js +256 -0
  132. package/dist/multicast-input.js.map +7 -0
  133. package/dist/multicast-manager.d.ts +330 -0
  134. package/dist/multicast-manager.d.ts.map +1 -0
  135. package/dist/multicast-manager.js +11032 -0
  136. package/dist/multicast-manager.js.map +7 -0
  137. package/dist/multicast-transport.d.ts +62 -0
  138. package/dist/multicast-transport.d.ts.map +1 -0
  139. package/dist/multicast-transport.js +338 -0
  140. package/dist/multicast-transport.js.map +7 -0
  141. package/dist/multicast-unwrap.d.ts +57 -0
  142. package/dist/multicast-unwrap.d.ts.map +1 -0
  143. package/dist/multicast-unwrap.js +384 -0
  144. package/dist/multicast-unwrap.js.map +7 -0
  145. package/dist/no-modules.d.ts +9 -0
  146. package/dist/no-modules.d.ts.map +1 -0
  147. package/dist/no-modules.js +7819 -0
  148. package/dist/no-modules.js.map +7 -0
  149. package/dist/phase14-catalog-override.d.ts +126 -0
  150. package/dist/phase14-catalog-override.d.ts.map +1 -0
  151. package/dist/phase14-catalog-override.js +155 -0
  152. package/dist/phase14-catalog-override.js.map +7 -0
  153. package/dist/repair-fetch.d.ts +58 -0
  154. package/dist/repair-fetch.d.ts.map +1 -0
  155. package/dist/repair-fetch.js +117 -0
  156. package/dist/repair-fetch.js.map +7 -0
  157. package/dist/sample-combiner.d.ts +182 -0
  158. package/dist/sample-combiner.d.ts.map +1 -0
  159. package/dist/sample-combiner.js +571 -0
  160. package/dist/sample-combiner.js.map +7 -0
  161. package/dist/signaling.d.ts +29 -0
  162. package/dist/signaling.d.ts.map +1 -0
  163. package/dist/signaling.js +232 -0
  164. package/dist/signaling.js.map +7 -0
  165. package/dist/source-auth.d.ts +2 -0
  166. package/dist/source-auth.d.ts.map +1 -0
  167. package/dist/source-auth.js +1220 -0
  168. package/dist/source-auth.js.map +7 -0
  169. package/dist/switching-set-alignment.d.ts +61 -0
  170. package/dist/switching-set-alignment.d.ts.map +1 -0
  171. package/dist/switching-set-alignment.js +85 -0
  172. package/dist/switching-set-alignment.js.map +7 -0
  173. package/dist/timestamp-codec.d.ts +34 -0
  174. package/dist/timestamp-codec.d.ts.map +1 -0
  175. package/dist/timestamp-codec.js +456 -0
  176. package/dist/timestamp-codec.js.map +7 -0
  177. package/dist/track-pipeline-setup.d.ts +72 -0
  178. package/dist/track-pipeline-setup.d.ts.map +1 -0
  179. package/dist/track-pipeline-setup.js +306 -0
  180. package/dist/track-pipeline-setup.js.map +7 -0
  181. package/dist/track-pipeline.d.ts +121 -0
  182. package/dist/track-pipeline.d.ts.map +1 -0
  183. package/dist/track-pipeline.js +229 -0
  184. package/dist/track-pipeline.js.map +7 -0
  185. package/dist/track-session.d.ts +269 -0
  186. package/dist/track-session.d.ts.map +1 -0
  187. package/dist/track-session.js +597 -0
  188. package/dist/track-session.js.map +7 -0
  189. package/dist/transport-pool.d.ts +69 -0
  190. package/dist/transport-pool.d.ts.map +1 -0
  191. package/dist/transport-pool.js +88 -0
  192. package/dist/transport-pool.js.map +7 -0
  193. package/dist/wasm-mfu-reassembler.d.ts +81 -0
  194. package/dist/wasm-mfu-reassembler.d.ts.map +1 -0
  195. package/dist/wasm-mfu-reassembler.js +1915 -0
  196. package/dist/wasm-mfu-reassembler.js.map +7 -0
  197. package/dist/wasm-mmtp-container-parser.d.ts +10 -0
  198. package/dist/wasm-mmtp-container-parser.d.ts.map +1 -0
  199. package/dist/wasm-mmtp-container-parser.js +5635 -0
  200. package/dist/wasm-mmtp-container-parser.js.map +7 -0
  201. package/node_modules/@blockcast/fec-worker/README.md +213 -0
  202. package/node_modules/@blockcast/fec-worker/dist/.build-stamp +0 -0
  203. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts +80 -0
  204. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.d.ts.map +1 -0
  205. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js +270 -0
  206. package/node_modules/@blockcast/fec-worker/dist/fec-worker-client.js.map +1 -0
  207. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts +252 -0
  208. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts.map +1 -0
  209. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js +11 -0
  210. package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.js.map +1 -0
  211. package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts +14 -0
  212. package/node_modules/@blockcast/fec-worker/dist/fec-worker.d.ts.map +1 -0
  213. package/node_modules/@blockcast/fec-worker/dist/fec-worker.js +565 -0
  214. package/node_modules/@blockcast/fec-worker/dist/fec-worker.js.map +7 -0
  215. package/node_modules/@blockcast/fec-worker/dist/index.d.ts +10 -0
  216. package/node_modules/@blockcast/fec-worker/dist/index.d.ts.map +1 -0
  217. package/node_modules/@blockcast/fec-worker/dist/index.js +8 -0
  218. package/node_modules/@blockcast/fec-worker/dist/index.js.map +1 -0
  219. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts +20 -0
  220. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.d.ts.map +1 -0
  221. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js +349 -0
  222. package/node_modules/@blockcast/fec-worker/dist/shred-fec-worker.js.map +7 -0
  223. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts +104 -0
  224. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.d.ts.map +1 -0
  225. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js +181 -0
  226. package/node_modules/@blockcast/fec-worker/dist/shred-worker-client.js.map +1 -0
  227. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts +179 -0
  228. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.d.ts.map +1 -0
  229. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js +47 -0
  230. package/node_modules/@blockcast/fec-worker/dist/shred-worker-types.js.map +1 -0
  231. package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts +9 -0
  232. package/node_modules/@blockcast/fec-worker/dist/transfer.d.ts.map +1 -0
  233. package/node_modules/@blockcast/fec-worker/dist/transfer.js +13 -0
  234. package/node_modules/@blockcast/fec-worker/dist/transfer.js.map +1 -0
  235. package/node_modules/@blockcast/fec-worker/package.json +59 -0
  236. package/node_modules/@blockcast/fec-worker/src/fec-worker-client.ts +309 -0
  237. package/node_modules/@blockcast/fec-worker/src/fec-worker-types.ts +268 -0
  238. package/node_modules/@blockcast/fec-worker/src/fec-worker.ts +1048 -0
  239. package/node_modules/@blockcast/fec-worker/src/index.ts +32 -0
  240. package/node_modules/@blockcast/fec-worker/src/shred-fec-worker.ts +558 -0
  241. package/node_modules/@blockcast/fec-worker/src/shred-worker-client.ts +222 -0
  242. package/node_modules/@blockcast/fec-worker/src/shred-worker-types.ts +194 -0
  243. package/node_modules/@blockcast/fec-worker/src/transfer.ts +12 -0
  244. package/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
  245. package/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
  246. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
  247. package/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
  248. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
  249. package/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
  250. package/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
  251. package/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
  252. package/node_modules/@blockcast/mmt-base/README.md +120 -0
  253. package/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
  254. package/node_modules/@blockcast/mmt-base/dist/index.d.ts +2 -0
  255. package/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
  256. package/node_modules/@blockcast/mmt-base/dist/index.js +2 -0
  257. package/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
  258. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +275 -0
  259. package/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
  260. package/node_modules/@blockcast/mmt-base/dist/mmtp.js +644 -0
  261. package/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
  262. package/node_modules/@blockcast/mmt-base/package.json +49 -0
  263. package/node_modules/@blockcast/mmt-base/src/index.ts +1 -0
  264. package/node_modules/@blockcast/mmt-base/src/mmtp.ts +898 -0
  265. package/node_modules/@blockcast/mmt-fec/README.md +270 -0
  266. package/node_modules/@blockcast/mmt-fec/dist/.build-stamp +0 -0
  267. package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts +80 -0
  268. package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts.map +1 -0
  269. package/node_modules/@blockcast/mmt-fec/dist/block-manager.js +294 -0
  270. package/node_modules/@blockcast/mmt-fec/dist/block-manager.js.map +1 -0
  271. package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts +72 -0
  272. package/node_modules/@blockcast/mmt-fec/dist/block-processor.d.ts.map +1 -0
  273. package/node_modules/@blockcast/mmt-fec/dist/block-processor.js +192 -0
  274. package/node_modules/@blockcast/mmt-fec/dist/block-processor.js.map +1 -0
  275. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts +46 -0
  276. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.d.ts.map +1 -0
  277. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js +96 -0
  278. package/node_modules/@blockcast/mmt-fec/dist/cmaf-recovery.js.map +1 -0
  279. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts +33 -0
  280. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.d.ts.map +1 -0
  281. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js +57 -0
  282. package/node_modules/@blockcast/mmt-fec/dist/cmaf-symbols.js.map +1 -0
  283. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts +185 -0
  284. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts.map +1 -0
  285. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js +273 -0
  286. package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js.map +1 -0
  287. package/node_modules/@blockcast/mmt-fec/dist/index.d.ts +22 -0
  288. package/node_modules/@blockcast/mmt-fec/dist/index.d.ts.map +1 -0
  289. package/node_modules/@blockcast/mmt-fec/dist/index.js +22 -0
  290. package/node_modules/@blockcast/mmt-fec/dist/index.js.map +1 -0
  291. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts +20 -0
  292. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.d.ts.map +1 -0
  293. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js +28 -0
  294. package/node_modules/@blockcast/mmt-fec/dist/loc-symbols.js.map +1 -0
  295. package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts +174 -0
  296. package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts.map +1 -0
  297. package/node_modules/@blockcast/mmt-fec/dist/oti.js +256 -0
  298. package/node_modules/@blockcast/mmt-fec/dist/oti.js.map +1 -0
  299. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts +41 -0
  300. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.d.ts.map +1 -0
  301. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js +81 -0
  302. package/node_modules/@blockcast/mmt-fec/dist/reorder-buffer.js.map +1 -0
  303. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/README.md +181 -0
  304. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/.build-stamp +0 -0
  305. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts +57 -0
  306. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.d.ts.map +1 -0
  307. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js +115 -0
  308. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/dist/index.js.map +1 -0
  309. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/package.json +50 -0
  310. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-alta-parse/src/index.ts +136 -0
  311. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/README.md +120 -0
  312. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/.build-stamp +0 -0
  313. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts +2 -0
  314. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.d.ts.map +1 -0
  315. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js +2 -0
  316. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/index.js.map +1 -0
  317. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts +275 -0
  318. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.d.ts.map +1 -0
  319. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js +644 -0
  320. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/dist/mmtp.js.map +1 -0
  321. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/package.json +49 -0
  322. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/index.ts +1 -0
  323. package/node_modules/@blockcast/mmt-fec/node_modules/@blockcast/mmt-base/src/mmtp.ts +898 -0
  324. package/node_modules/@blockcast/mmt-fec/package.json +79 -0
  325. package/node_modules/@blockcast/mmt-fec/src/block-manager.ts +369 -0
  326. package/node_modules/@blockcast/mmt-fec/src/block-processor.ts +277 -0
  327. package/node_modules/@blockcast/mmt-fec/src/cmaf-recovery.ts +127 -0
  328. package/node_modules/@blockcast/mmt-fec/src/cmaf-symbols.ts +68 -0
  329. package/node_modules/@blockcast/mmt-fec/src/fec-block-mapper.ts +332 -0
  330. package/node_modules/@blockcast/mmt-fec/src/index.ts +77 -0
  331. package/node_modules/@blockcast/mmt-fec/src/loc-symbols.ts +34 -0
  332. package/node_modules/@blockcast/mmt-fec/src/oti.ts +319 -0
  333. package/node_modules/@blockcast/mmt-fec/src/reorder-buffer.ts +101 -0
  334. package/node_modules/@blockcast/mmt-manifest-verify/dist/.build-stamp +0 -0
  335. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts +28 -0
  336. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.d.ts.map +1 -0
  337. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js +128 -0
  338. package/node_modules/@blockcast/mmt-manifest-verify/dist/admission.js.map +1 -0
  339. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts +4 -0
  340. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.d.ts.map +1 -0
  341. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js +4 -0
  342. package/node_modules/@blockcast/mmt-manifest-verify/dist/index.js.map +1 -0
  343. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts +37 -0
  344. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.d.ts.map +1 -0
  345. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js +179 -0
  346. package/node_modules/@blockcast/mmt-manifest-verify/dist/source-auth.js.map +1 -0
  347. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts +90 -0
  348. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts.map +1 -0
  349. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js +462 -0
  350. package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js.map +1 -0
  351. package/node_modules/@blockcast/mmt-manifest-verify/package.json +45 -0
  352. package/node_modules/@blockcast/mmt-manifest-verify/src/admission.ts +171 -0
  353. package/node_modules/@blockcast/mmt-manifest-verify/src/index.ts +3 -0
  354. package/node_modules/@blockcast/mmt-manifest-verify/src/source-auth.ts +230 -0
  355. package/node_modules/@blockcast/mmt-manifest-verify/src/verifier.ts +636 -0
  356. package/node_modules/@noble/hashes/LICENSE +21 -0
  357. package/node_modules/@noble/hashes/README.md +521 -0
  358. package/node_modules/@noble/hashes/_assert.d.ts +17 -0
  359. package/node_modules/@noble/hashes/_assert.d.ts.map +1 -0
  360. package/node_modules/@noble/hashes/_assert.js +18 -0
  361. package/node_modules/@noble/hashes/_assert.js.map +1 -0
  362. package/node_modules/@noble/hashes/_blake.d.ts +14 -0
  363. package/node_modules/@noble/hashes/_blake.d.ts.map +1 -0
  364. package/node_modules/@noble/hashes/_blake.js +50 -0
  365. package/node_modules/@noble/hashes/_blake.js.map +1 -0
  366. package/node_modules/@noble/hashes/_md.d.ts +51 -0
  367. package/node_modules/@noble/hashes/_md.d.ts.map +1 -0
  368. package/node_modules/@noble/hashes/_md.js +162 -0
  369. package/node_modules/@noble/hashes/_md.js.map +1 -0
  370. package/node_modules/@noble/hashes/_u64.d.ts +55 -0
  371. package/node_modules/@noble/hashes/_u64.d.ts.map +1 -0
  372. package/node_modules/@noble/hashes/_u64.js +90 -0
  373. package/node_modules/@noble/hashes/_u64.js.map +1 -0
  374. package/node_modules/@noble/hashes/argon2.d.ts +32 -0
  375. package/node_modules/@noble/hashes/argon2.d.ts.map +1 -0
  376. package/node_modules/@noble/hashes/argon2.js +401 -0
  377. package/node_modules/@noble/hashes/argon2.js.map +1 -0
  378. package/node_modules/@noble/hashes/blake1.d.ts +106 -0
  379. package/node_modules/@noble/hashes/blake1.d.ts.map +1 -0
  380. package/node_modules/@noble/hashes/blake1.js +459 -0
  381. package/node_modules/@noble/hashes/blake1.js.map +1 -0
  382. package/node_modules/@noble/hashes/blake2.d.ts +116 -0
  383. package/node_modules/@noble/hashes/blake2.d.ts.map +1 -0
  384. package/node_modules/@noble/hashes/blake2.js +420 -0
  385. package/node_modules/@noble/hashes/blake2.js.map +1 -0
  386. package/node_modules/@noble/hashes/blake2b.d.ts +11 -0
  387. package/node_modules/@noble/hashes/blake2b.d.ts.map +1 -0
  388. package/node_modules/@noble/hashes/blake2b.js +14 -0
  389. package/node_modules/@noble/hashes/blake2b.js.map +1 -0
  390. package/node_modules/@noble/hashes/blake2s.d.ts +20 -0
  391. package/node_modules/@noble/hashes/blake2s.d.ts.map +1 -0
  392. package/node_modules/@noble/hashes/blake2s.js +24 -0
  393. package/node_modules/@noble/hashes/blake2s.js.map +1 -0
  394. package/node_modules/@noble/hashes/blake3.d.ts +54 -0
  395. package/node_modules/@noble/hashes/blake3.d.ts.map +1 -0
  396. package/node_modules/@noble/hashes/blake3.js +255 -0
  397. package/node_modules/@noble/hashes/blake3.js.map +1 -0
  398. package/node_modules/@noble/hashes/crypto.d.ts +2 -0
  399. package/node_modules/@noble/hashes/crypto.d.ts.map +1 -0
  400. package/node_modules/@noble/hashes/crypto.js +5 -0
  401. package/node_modules/@noble/hashes/crypto.js.map +1 -0
  402. package/node_modules/@noble/hashes/cryptoNode.d.ts +2 -0
  403. package/node_modules/@noble/hashes/cryptoNode.d.ts.map +1 -0
  404. package/node_modules/@noble/hashes/cryptoNode.js +18 -0
  405. package/node_modules/@noble/hashes/cryptoNode.js.map +1 -0
  406. package/node_modules/@noble/hashes/eskdf.d.ts +47 -0
  407. package/node_modules/@noble/hashes/eskdf.d.ts.map +1 -0
  408. package/node_modules/@noble/hashes/eskdf.js +166 -0
  409. package/node_modules/@noble/hashes/eskdf.js.map +1 -0
  410. package/node_modules/@noble/hashes/esm/_assert.d.ts +17 -0
  411. package/node_modules/@noble/hashes/esm/_assert.d.ts.map +1 -0
  412. package/node_modules/@noble/hashes/esm/_assert.js +15 -0
  413. package/node_modules/@noble/hashes/esm/_assert.js.map +1 -0
  414. package/node_modules/@noble/hashes/esm/_blake.d.ts +14 -0
  415. package/node_modules/@noble/hashes/esm/_blake.d.ts.map +1 -0
  416. package/node_modules/@noble/hashes/esm/_blake.js +45 -0
  417. package/node_modules/@noble/hashes/esm/_blake.js.map +1 -0
  418. package/node_modules/@noble/hashes/esm/_md.d.ts +51 -0
  419. package/node_modules/@noble/hashes/esm/_md.d.ts.map +1 -0
  420. package/node_modules/@noble/hashes/esm/_md.js +155 -0
  421. package/node_modules/@noble/hashes/esm/_md.js.map +1 -0
  422. package/node_modules/@noble/hashes/esm/_u64.d.ts +55 -0
  423. package/node_modules/@noble/hashes/esm/_u64.d.ts.map +1 -0
  424. package/node_modules/@noble/hashes/esm/_u64.js +67 -0
  425. package/node_modules/@noble/hashes/esm/_u64.js.map +1 -0
  426. package/node_modules/@noble/hashes/esm/argon2.d.ts +32 -0
  427. package/node_modules/@noble/hashes/esm/argon2.d.ts.map +1 -0
  428. package/node_modules/@noble/hashes/esm/argon2.js +392 -0
  429. package/node_modules/@noble/hashes/esm/argon2.js.map +1 -0
  430. package/node_modules/@noble/hashes/esm/blake1.d.ts +106 -0
  431. package/node_modules/@noble/hashes/esm/blake1.d.ts.map +1 -0
  432. package/node_modules/@noble/hashes/esm/blake1.js +452 -0
  433. package/node_modules/@noble/hashes/esm/blake1.js.map +1 -0
  434. package/node_modules/@noble/hashes/esm/blake2.d.ts +116 -0
  435. package/node_modules/@noble/hashes/esm/blake2.d.ts.map +1 -0
  436. package/node_modules/@noble/hashes/esm/blake2.js +413 -0
  437. package/node_modules/@noble/hashes/esm/blake2.js.map +1 -0
  438. package/node_modules/@noble/hashes/esm/blake2b.d.ts +11 -0
  439. package/node_modules/@noble/hashes/esm/blake2b.d.ts.map +1 -0
  440. package/node_modules/@noble/hashes/esm/blake2b.js +11 -0
  441. package/node_modules/@noble/hashes/esm/blake2b.js.map +1 -0
  442. package/node_modules/@noble/hashes/esm/blake2s.d.ts +20 -0
  443. package/node_modules/@noble/hashes/esm/blake2s.d.ts.map +1 -0
  444. package/node_modules/@noble/hashes/esm/blake2s.js +21 -0
  445. package/node_modules/@noble/hashes/esm/blake2s.js.map +1 -0
  446. package/node_modules/@noble/hashes/esm/blake3.d.ts +54 -0
  447. package/node_modules/@noble/hashes/esm/blake3.d.ts.map +1 -0
  448. package/node_modules/@noble/hashes/esm/blake3.js +251 -0
  449. package/node_modules/@noble/hashes/esm/blake3.js.map +1 -0
  450. package/node_modules/@noble/hashes/esm/crypto.d.ts +2 -0
  451. package/node_modules/@noble/hashes/esm/crypto.d.ts.map +1 -0
  452. package/node_modules/@noble/hashes/esm/crypto.js +2 -0
  453. package/node_modules/@noble/hashes/esm/crypto.js.map +1 -0
  454. package/node_modules/@noble/hashes/esm/cryptoNode.d.ts +2 -0
  455. package/node_modules/@noble/hashes/esm/cryptoNode.d.ts.map +1 -0
  456. package/node_modules/@noble/hashes/esm/cryptoNode.js +15 -0
  457. package/node_modules/@noble/hashes/esm/cryptoNode.js.map +1 -0
  458. package/node_modules/@noble/hashes/esm/eskdf.d.ts +47 -0
  459. package/node_modules/@noble/hashes/esm/eskdf.d.ts.map +1 -0
  460. package/node_modules/@noble/hashes/esm/eskdf.js +160 -0
  461. package/node_modules/@noble/hashes/esm/eskdf.js.map +1 -0
  462. package/node_modules/@noble/hashes/esm/hkdf.d.ts +36 -0
  463. package/node_modules/@noble/hashes/esm/hkdf.d.ts.map +1 -0
  464. package/node_modules/@noble/hashes/esm/hkdf.js +82 -0
  465. package/node_modules/@noble/hashes/esm/hkdf.js.map +1 -0
  466. package/node_modules/@noble/hashes/esm/hmac.d.ts +35 -0
  467. package/node_modules/@noble/hashes/esm/hmac.d.ts.map +1 -0
  468. package/node_modules/@noble/hashes/esm/hmac.js +86 -0
  469. package/node_modules/@noble/hashes/esm/hmac.js.map +1 -0
  470. package/node_modules/@noble/hashes/esm/index.d.ts +2 -0
  471. package/node_modules/@noble/hashes/esm/index.d.ts.map +1 -0
  472. package/node_modules/@noble/hashes/esm/index.js +33 -0
  473. package/node_modules/@noble/hashes/esm/index.js.map +1 -0
  474. package/node_modules/@noble/hashes/esm/legacy.d.ts +71 -0
  475. package/node_modules/@noble/hashes/esm/legacy.d.ts.map +1 -0
  476. package/node_modules/@noble/hashes/esm/legacy.js +281 -0
  477. package/node_modules/@noble/hashes/esm/legacy.js.map +1 -0
  478. package/node_modules/@noble/hashes/esm/package.json +10 -0
  479. package/node_modules/@noble/hashes/esm/pbkdf2.d.ts +23 -0
  480. package/node_modules/@noble/hashes/esm/pbkdf2.d.ts.map +1 -0
  481. package/node_modules/@noble/hashes/esm/pbkdf2.js +97 -0
  482. package/node_modules/@noble/hashes/esm/pbkdf2.js.map +1 -0
  483. package/node_modules/@noble/hashes/esm/ripemd160.d.ts +13 -0
  484. package/node_modules/@noble/hashes/esm/ripemd160.d.ts.map +1 -0
  485. package/node_modules/@noble/hashes/esm/ripemd160.js +13 -0
  486. package/node_modules/@noble/hashes/esm/ripemd160.js.map +1 -0
  487. package/node_modules/@noble/hashes/esm/scrypt.d.ts +34 -0
  488. package/node_modules/@noble/hashes/esm/scrypt.d.ts.map +1 -0
  489. package/node_modules/@noble/hashes/esm/scrypt.js +228 -0
  490. package/node_modules/@noble/hashes/esm/scrypt.js.map +1 -0
  491. package/node_modules/@noble/hashes/esm/sha1.d.ts +11 -0
  492. package/node_modules/@noble/hashes/esm/sha1.d.ts.map +1 -0
  493. package/node_modules/@noble/hashes/esm/sha1.js +11 -0
  494. package/node_modules/@noble/hashes/esm/sha1.js.map +1 -0
  495. package/node_modules/@noble/hashes/esm/sha2.d.ts +159 -0
  496. package/node_modules/@noble/hashes/esm/sha2.d.ts.map +1 -0
  497. package/node_modules/@noble/hashes/esm/sha2.js +375 -0
  498. package/node_modules/@noble/hashes/esm/sha2.js.map +1 -0
  499. package/node_modules/@noble/hashes/esm/sha256.d.ts +20 -0
  500. package/node_modules/@noble/hashes/esm/sha256.d.ts.map +1 -0
  501. package/node_modules/@noble/hashes/esm/sha256.js +20 -0
  502. package/node_modules/@noble/hashes/esm/sha256.js.map +1 -0
  503. package/node_modules/@noble/hashes/esm/sha3-addons.d.ts +142 -0
  504. package/node_modules/@noble/hashes/esm/sha3-addons.d.ts.map +1 -0
  505. package/node_modules/@noble/hashes/esm/sha3-addons.js +393 -0
  506. package/node_modules/@noble/hashes/esm/sha3-addons.js.map +1 -0
  507. package/node_modules/@noble/hashes/esm/sha3.d.ts +53 -0
  508. package/node_modules/@noble/hashes/esm/sha3.d.ts.map +1 -0
  509. package/node_modules/@noble/hashes/esm/sha3.js +234 -0
  510. package/node_modules/@noble/hashes/esm/sha3.js.map +1 -0
  511. package/node_modules/@noble/hashes/esm/sha512.d.ts +26 -0
  512. package/node_modules/@noble/hashes/esm/sha512.d.ts.map +1 -0
  513. package/node_modules/@noble/hashes/esm/sha512.js +26 -0
  514. package/node_modules/@noble/hashes/esm/sha512.js.map +1 -0
  515. package/node_modules/@noble/hashes/esm/utils.d.ts +161 -0
  516. package/node_modules/@noble/hashes/esm/utils.d.ts.map +1 -0
  517. package/node_modules/@noble/hashes/esm/utils.js +281 -0
  518. package/node_modules/@noble/hashes/esm/utils.js.map +1 -0
  519. package/node_modules/@noble/hashes/hkdf.d.ts +36 -0
  520. package/node_modules/@noble/hashes/hkdf.d.ts.map +1 -0
  521. package/node_modules/@noble/hashes/hkdf.js +88 -0
  522. package/node_modules/@noble/hashes/hkdf.js.map +1 -0
  523. package/node_modules/@noble/hashes/hmac.d.ts +35 -0
  524. package/node_modules/@noble/hashes/hmac.d.ts.map +1 -0
  525. package/node_modules/@noble/hashes/hmac.js +91 -0
  526. package/node_modules/@noble/hashes/hmac.js.map +1 -0
  527. package/node_modules/@noble/hashes/index.d.ts +1 -0
  528. package/node_modules/@noble/hashes/index.d.ts.map +1 -0
  529. package/node_modules/@noble/hashes/index.js +33 -0
  530. package/node_modules/@noble/hashes/index.js.map +1 -0
  531. package/node_modules/@noble/hashes/legacy.d.ts +71 -0
  532. package/node_modules/@noble/hashes/legacy.d.ts.map +1 -0
  533. package/node_modules/@noble/hashes/legacy.js +287 -0
  534. package/node_modules/@noble/hashes/legacy.js.map +1 -0
  535. package/node_modules/@noble/hashes/package.json +266 -0
  536. package/node_modules/@noble/hashes/pbkdf2.d.ts +23 -0
  537. package/node_modules/@noble/hashes/pbkdf2.d.ts.map +1 -0
  538. package/node_modules/@noble/hashes/pbkdf2.js +101 -0
  539. package/node_modules/@noble/hashes/pbkdf2.js.map +1 -0
  540. package/node_modules/@noble/hashes/ripemd160.d.ts +13 -0
  541. package/node_modules/@noble/hashes/ripemd160.d.ts.map +1 -0
  542. package/node_modules/@noble/hashes/ripemd160.js +16 -0
  543. package/node_modules/@noble/hashes/ripemd160.js.map +1 -0
  544. package/node_modules/@noble/hashes/scrypt.d.ts +34 -0
  545. package/node_modules/@noble/hashes/scrypt.d.ts.map +1 -0
  546. package/node_modules/@noble/hashes/scrypt.js +232 -0
  547. package/node_modules/@noble/hashes/scrypt.js.map +1 -0
  548. package/node_modules/@noble/hashes/sha1.d.ts +11 -0
  549. package/node_modules/@noble/hashes/sha1.d.ts.map +1 -0
  550. package/node_modules/@noble/hashes/sha1.js +14 -0
  551. package/node_modules/@noble/hashes/sha1.js.map +1 -0
  552. package/node_modules/@noble/hashes/sha2.d.ts +159 -0
  553. package/node_modules/@noble/hashes/sha2.d.ts.map +1 -0
  554. package/node_modules/@noble/hashes/sha2.js +384 -0
  555. package/node_modules/@noble/hashes/sha2.js.map +1 -0
  556. package/node_modules/@noble/hashes/sha256.d.ts +20 -0
  557. package/node_modules/@noble/hashes/sha256.d.ts.map +1 -0
  558. package/node_modules/@noble/hashes/sha256.js +23 -0
  559. package/node_modules/@noble/hashes/sha256.js.map +1 -0
  560. package/node_modules/@noble/hashes/sha3-addons.d.ts +142 -0
  561. package/node_modules/@noble/hashes/sha3-addons.d.ts.map +1 -0
  562. package/node_modules/@noble/hashes/sha3-addons.js +402 -0
  563. package/node_modules/@noble/hashes/sha3-addons.js.map +1 -0
  564. package/node_modules/@noble/hashes/sha3.d.ts +53 -0
  565. package/node_modules/@noble/hashes/sha3.d.ts.map +1 -0
  566. package/node_modules/@noble/hashes/sha3.js +239 -0
  567. package/node_modules/@noble/hashes/sha3.js.map +1 -0
  568. package/node_modules/@noble/hashes/sha512.d.ts +26 -0
  569. package/node_modules/@noble/hashes/sha512.d.ts.map +1 -0
  570. package/node_modules/@noble/hashes/sha512.js +29 -0
  571. package/node_modules/@noble/hashes/sha512.js.map +1 -0
  572. package/node_modules/@noble/hashes/src/_assert.ts +22 -0
  573. package/node_modules/@noble/hashes/src/_blake.ts +50 -0
  574. package/node_modules/@noble/hashes/src/_md.ts +176 -0
  575. package/node_modules/@noble/hashes/src/_u64.ts +91 -0
  576. package/node_modules/@noble/hashes/src/argon2.ts +497 -0
  577. package/node_modules/@noble/hashes/src/blake1.ts +534 -0
  578. package/node_modules/@noble/hashes/src/blake2.ts +486 -0
  579. package/node_modules/@noble/hashes/src/blake2b.ts +10 -0
  580. package/node_modules/@noble/hashes/src/blake2s.ts +20 -0
  581. package/node_modules/@noble/hashes/src/blake3.ts +272 -0
  582. package/node_modules/@noble/hashes/src/crypto.ts +9 -0
  583. package/node_modules/@noble/hashes/src/cryptoNode.ts +15 -0
  584. package/node_modules/@noble/hashes/src/eskdf.ts +187 -0
  585. package/node_modules/@noble/hashes/src/hkdf.ts +88 -0
  586. package/node_modules/@noble/hashes/src/hmac.ts +94 -0
  587. package/node_modules/@noble/hashes/src/index.ts +31 -0
  588. package/node_modules/@noble/hashes/src/legacy.ts +293 -0
  589. package/node_modules/@noble/hashes/src/pbkdf2.ts +122 -0
  590. package/node_modules/@noble/hashes/src/ripemd160.ts +12 -0
  591. package/node_modules/@noble/hashes/src/scrypt.ts +257 -0
  592. package/node_modules/@noble/hashes/src/sha1.ts +10 -0
  593. package/node_modules/@noble/hashes/src/sha2.ts +402 -0
  594. package/node_modules/@noble/hashes/src/sha256.ts +24 -0
  595. package/node_modules/@noble/hashes/src/sha3-addons.ts +499 -0
  596. package/node_modules/@noble/hashes/src/sha3.ts +258 -0
  597. package/node_modules/@noble/hashes/src/sha512.ts +34 -0
  598. package/node_modules/@noble/hashes/src/utils.ts +395 -0
  599. package/node_modules/@noble/hashes/utils.d.ts +161 -0
  600. package/node_modules/@noble/hashes/utils.d.ts.map +1 -0
  601. package/node_modules/@noble/hashes/utils.js +313 -0
  602. package/node_modules/@noble/hashes/utils.js.map +1 -0
  603. package/package.json +203 -0
  604. package/schemas/catalog.schema.json +283 -0
  605. package/src/align.ts +235 -0
  606. package/src/audio-init-parser.ts +189 -0
  607. package/src/audio-ring-buffer.ts +120 -0
  608. package/src/authored-timing.ts +63 -0
  609. package/src/carp-catalog.ts +776 -0
  610. package/src/catalog-fec-params.ts +167 -0
  611. package/src/catalog-network-source.ts +49 -0
  612. package/src/catalog-validator.ts +34 -0
  613. package/src/cmaf-block-assembler.ts +1058 -0
  614. package/src/cmaf-group-batcher.ts +104 -0
  615. package/src/cmcd-producer.ts +329 -0
  616. package/src/codec-utils.ts +1539 -0
  617. package/src/fec-codec.ts +61 -0
  618. package/src/fec-manager.ts +1939 -0
  619. package/src/fec-starvation-detector.ts +128 -0
  620. package/src/fec-worker-setup.ts +177 -0
  621. package/src/fmp4-completion.ts +47 -0
  622. package/src/fmp4-reader.ts +112 -0
  623. package/src/index.ts +443 -0
  624. package/src/iso-bmff-timing.ts +688 -0
  625. package/src/loc.ts +181 -0
  626. package/src/manifest-auth-plan.ts +107 -0
  627. package/src/media-router.ts +1185 -0
  628. package/src/mfu-reassembler.ts +2842 -0
  629. package/src/mfu-reassembly-policy.ts +134 -0
  630. package/src/mmtp-container-parser.ts +1498 -0
  631. package/src/mmtp-decode-pipeline.ts +315 -0
  632. package/src/mmtp-router.ts +3027 -0
  633. package/src/mmtp-to-cmaf.ts +956 -0
  634. package/src/multicast-auth-catalog.ts +340 -0
  635. package/src/multicast-input.ts +439 -0
  636. package/src/multicast-manager.ts +1503 -0
  637. package/src/multicast-transport.ts +320 -0
  638. package/src/multicast-unwrap.ts +132 -0
  639. package/src/no-modules.ts +20 -0
  640. package/src/phase14-catalog-override.ts +336 -0
  641. package/src/repair-fetch.ts +217 -0
  642. package/src/sample-combiner.ts +846 -0
  643. package/src/signaling.ts +78 -0
  644. package/src/source-auth.ts +1 -0
  645. package/src/switching-set-alignment.ts +109 -0
  646. package/src/timestamp-codec.ts +265 -0
  647. package/src/track-pipeline-setup.ts +189 -0
  648. package/src/track-pipeline.ts +332 -0
  649. package/src/track-session.ts +778 -0
  650. package/src/transport-pool.ts +128 -0
  651. package/src/wasm-mfu-reassembler.ts +372 -0
  652. package/src/wasm-mmtp-container-parser.ts +23 -0
  653. package/test-vectors/align.json +199 -0
  654. package/test-vectors/catalog/README.md +25 -0
  655. package/test-vectors/catalog/negative/legacy-selection-params.json +15 -0
  656. package/test-vectors/catalog/negative/missing-mmtp-fields.json +12 -0
  657. package/test-vectors/catalog/negative/multicast-auth-padded-key.json +37 -0
  658. package/test-vectors/catalog/negative/multicast-auth-reused-track-format.json +53 -0
  659. package/test-vectors/catalog/negative/multicast-auth-trailing-pad-bits.json +37 -0
  660. package/test-vectors/catalog/negative/multicast-endpoint-missing-protocol-and-source.json +24 -0
  661. package/test-vectors/catalog/negative/network-source-object.json +25 -0
  662. package/test-vectors/catalog/negative/raptorq-unaligned-symbol.json +26 -0
  663. package/test-vectors/catalog/negative/repair-track-legacy-shape.json +18 -0
  664. package/test-vectors/catalog/negative/track-role-empty.json +16 -0
  665. package/test-vectors/catalog/negative/track-role-non-string.json +16 -0
  666. package/test-vectors/catalog/positive/fec-multicast.json +51 -0
  667. package/test-vectors/catalog/positive/flat-av.json +30 -0
  668. package/test-vectors/catalog/positive/multicast-auth-rotation.json +55 -0
  669. package/test-vectors/catalog/positive/ticks-and-mixed-timescales.json +39 -0
  670. package/test-vectors/catalog/positive/track-role.json +49 -0
  671. package/test-vectors/catalog/releases/moqcast-native-v16-v1/catalog.json +65 -0
  672. package/test-vectors/catalog/releases/moqcast-native-v16-v1.archive.sha256 +1 -0
  673. package/test-vectors/catalog-multicast-auth-v1.json +26 -0
  674. package/test-vectors/catalog-validation.json +148 -0
  675. package/test-vectors/catalog-validator-public-api.mjs +25 -0
  676. package/test-vectors/generate-source-auth-fixture.mjs +114 -0
  677. package/test-vectors/source-auth-v1.json +61 -0
  678. package/test-vectors/subsample-placement-v1.json +230 -0
@@ -0,0 +1,1755 @@
1
+ var __typeError = (msg) => {
2
+ throw TypeError(msg);
3
+ };
4
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
5
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
6
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
7
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
8
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
9
+ var __privateWrapper = (obj, member, setter, getter) => ({
10
+ set _(value) {
11
+ __privateSet(obj, member, value, setter);
12
+ },
13
+ get _() {
14
+ return __privateGet(obj, member, getter);
15
+ }
16
+ });
17
+
18
+ // src/mmtp-to-cmaf.ts
19
+ function box(type, ...children) {
20
+ let size = 8;
21
+ for (const c of children) size += c.length;
22
+ const buf = new Uint8Array(size);
23
+ new DataView(buf.buffer).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
+ let pos = 8;
29
+ for (const c of children) {
30
+ buf.set(c, pos);
31
+ pos += c.length;
32
+ }
33
+ return buf;
34
+ }
35
+ function fullBox(type, version, flags, ...children) {
36
+ let size = 12;
37
+ for (const c of children) size += c.length;
38
+ const buf = new Uint8Array(size);
39
+ const dv = new DataView(buf.buffer);
40
+ dv.setUint32(0, size);
41
+ buf[4] = type.charCodeAt(0);
42
+ buf[5] = type.charCodeAt(1);
43
+ buf[6] = type.charCodeAt(2);
44
+ buf[7] = type.charCodeAt(3);
45
+ dv.setUint32(8, version << 24 | flags & 16777215);
46
+ let pos = 12;
47
+ for (const c of children) {
48
+ buf.set(c, pos);
49
+ pos += c.length;
50
+ }
51
+ return buf;
52
+ }
53
+ function u32(v) {
54
+ const b = new Uint8Array(4);
55
+ new DataView(b.buffer).setUint32(0, v);
56
+ return b;
57
+ }
58
+ var KEYFRAME_FLAGS = 33554432;
59
+ var DELTA_FLAGS = 16842752;
60
+ var UINT32_MAX = 4294967295;
61
+ var MAX_TRACK_ID = UINT32_MAX - 1;
62
+ var INT32_MIN = -2147483648;
63
+ var INT32_MAX = 2147483647;
64
+ function assertTrackId(trackId, label) {
65
+ if (!Number.isInteger(trackId) || trackId <= 0 || trackId > MAX_TRACK_ID) {
66
+ throw new RangeError(`${label} must be an integer in 1..${MAX_TRACK_ID}, got ${trackId}`);
67
+ }
68
+ }
69
+ function assertTimescale(timescale, label) {
70
+ if (!Number.isInteger(timescale) || timescale <= 0 || timescale > UINT32_MAX) {
71
+ throw new RangeError(`${label} must be an integer in 1..${UINT32_MAX}, got ${timescale}`);
72
+ }
73
+ }
74
+ function assertCompositionTimeOffsets(samples) {
75
+ for (let i = 0; i < samples.length; i++) {
76
+ const offset = samples[i].compositionTimeOffset;
77
+ if (offset !== void 0 && (!Number.isInteger(offset) || offset < INT32_MIN || offset > INT32_MAX)) {
78
+ throw new RangeError(
79
+ `sample ${i} compositionTimeOffset must be an integer in ${INT32_MIN}..${INT32_MAX}, got ${offset}`
80
+ );
81
+ }
82
+ }
83
+ }
84
+ function encodeMultiSampleSegment(samples, baseDecodeTime, sequence, trackId = 1) {
85
+ if (samples.length === 0) return new Uint8Array(0);
86
+ assertTrackId(trackId, "trackId");
87
+ assertCompositionTimeOffsets(samples);
88
+ const mfhd = fullBox("mfhd", 0, 0, u32(sequence));
89
+ const tfhd = fullBox("tfhd", 0, 131072, u32(trackId));
90
+ const tfdtBody = new Uint8Array(8);
91
+ const tfdtView = new DataView(tfdtBody.buffer);
92
+ tfdtView.setUint32(0, Math.floor(baseDecodeTime / 4294967296));
93
+ tfdtView.setUint32(4, baseDecodeTime >>> 0);
94
+ const tfdt = fullBox("tfdt", 1, 0, tfdtBody);
95
+ const hasCompositionTimeOffset = samples.some((sample) => sample.compositionTimeOffset !== void 0);
96
+ const trunVersion = hasCompositionTimeOffset ? 1 : 0;
97
+ const trunFlags = 1793 | (hasCompositionTimeOffset ? 2048 : 0);
98
+ const sampleCount = samples.length;
99
+ const sampleEntrySize = hasCompositionTimeOffset ? 16 : 12;
100
+ const trunBody = new Uint8Array(8 + sampleCount * sampleEntrySize);
101
+ const trunView = new DataView(trunBody.buffer);
102
+ trunView.setUint32(0, sampleCount);
103
+ trunView.setUint32(4, 0);
104
+ for (let i = 0; i < sampleCount; i++) {
105
+ const s = samples[i];
106
+ const off = 8 + i * sampleEntrySize;
107
+ trunView.setUint32(off, s.duration >>> 0);
108
+ trunView.setUint32(off + 4, s.data.length);
109
+ trunView.setUint32(off + 8, s.keyframe ? KEYFRAME_FLAGS : DELTA_FLAGS);
110
+ if (hasCompositionTimeOffset) {
111
+ trunView.setInt32(off + 12, s.compositionTimeOffset ?? 0);
112
+ }
113
+ }
114
+ const trun = fullBox("trun", trunVersion, trunFlags, trunBody);
115
+ const traf = box("traf", tfhd, tfdt, trun);
116
+ const moof = box("moof", mfhd, traf);
117
+ let mdatSize = 0;
118
+ for (const s of samples) mdatSize += s.data.length;
119
+ const mdatPayload = new Uint8Array(mdatSize);
120
+ let pos = 0;
121
+ for (const s of samples) {
122
+ mdatPayload.set(s.data, pos);
123
+ pos += s.data.length;
124
+ }
125
+ const mdat = box("mdat", mdatPayload);
126
+ const dataOffsetPos = 8 + mfhd.length + 8 + tfhd.length + tfdt.length + 12 + 4;
127
+ new DataView(moof.buffer).setUint32(dataOffsetPos, moof.length + 8);
128
+ const result = new Uint8Array(moof.length + mdat.length);
129
+ result.set(moof, 0);
130
+ result.set(mdat, moof.length);
131
+ return result;
132
+ }
133
+ function generateGreenFillNAL(avcC, width, height) {
134
+ if (avcC.length < 8) return new Uint8Array(0);
135
+ const lengthSize = (avcC[4] & 3) + 1;
136
+ let offset = 5;
137
+ const numSPS = avcC[offset++] & 31;
138
+ const nals = [];
139
+ for (let i = 0; i < numSPS; i++) {
140
+ if (offset + 2 > avcC.length) break;
141
+ const spsLen = avcC[offset] << 8 | avcC[offset + 1];
142
+ offset += 2;
143
+ if (offset + spsLen > avcC.length) break;
144
+ const sps = avcC.subarray(offset, offset + spsLen);
145
+ const framed = new Uint8Array(4 + sps.length);
146
+ new DataView(framed.buffer).setUint32(0, sps.length);
147
+ framed.set(sps, 4);
148
+ nals.push(framed);
149
+ offset += spsLen;
150
+ }
151
+ if (offset < avcC.length) {
152
+ const numPPS = avcC[offset++];
153
+ for (let i = 0; i < numPPS; i++) {
154
+ if (offset + 2 > avcC.length) break;
155
+ const ppsLen = avcC[offset] << 8 | avcC[offset + 1];
156
+ offset += 2;
157
+ if (offset + ppsLen > avcC.length) break;
158
+ const pps = avcC.subarray(offset, offset + ppsLen);
159
+ const framed = new Uint8Array(4 + pps.length);
160
+ new DataView(framed.buffer).setUint32(0, pps.length);
161
+ framed.set(pps, 4);
162
+ nals.push(framed);
163
+ offset += ppsLen;
164
+ }
165
+ }
166
+ const mbWidth = Math.ceil(width / 16);
167
+ const mbHeight = Math.ceil(height / 16);
168
+ const totalMBs = mbWidth * mbHeight;
169
+ const idrSlice = new Uint8Array([
170
+ 101,
171
+ // nal_ref_idc=3, nal_type=5 (IDR)
172
+ 136,
173
+ // slice header: first_mb_in_slice=0, slice_type=7 (I)
174
+ 128,
175
+ // pps_id=0, frame_num=0, idr_pic_id=0
176
+ 64
177
+ // slice data: mb_skip_run covering remaining MBs
178
+ // Truncated — decoder will error-conceal remaining MBs as green/gray
179
+ ]);
180
+ const idrFramed = new Uint8Array(4 + idrSlice.length);
181
+ new DataView(idrFramed.buffer).setUint32(0, idrSlice.length);
182
+ idrFramed.set(idrSlice, 4);
183
+ nals.push(idrFramed);
184
+ let totalLen = 0;
185
+ for (const n of nals) totalLen += n.length;
186
+ const result = new Uint8Array(totalLen);
187
+ let p = 0;
188
+ for (const n of nals) {
189
+ result.set(n, p);
190
+ p += n.length;
191
+ }
192
+ return result;
193
+ }
194
+ function normalizeAacSampleForCmaf(data) {
195
+ if (data.length < 7 || data[0] !== 255 || (data[1] & 246) !== 240) {
196
+ return data;
197
+ }
198
+ const headerLength = data[1] & 1 ? 7 : 9;
199
+ if (data.length <= headerLength) return data;
200
+ const frameLength = (data[3] & 3) << 11 | data[4] << 3 | (data[5] & 224) >>> 5;
201
+ if (frameLength !== data.length || frameLength <= headerLength) return data;
202
+ return data.subarray(headerLength);
203
+ }
204
+ function encodeDataSegment(data, timestamp, duration, keyframe, sequence, trackId = 1, compositionTimeOffset) {
205
+ assertTrackId(trackId, "trackId");
206
+ assertCompositionTimeOffsets([{ compositionTimeOffset }]);
207
+ if (compositionTimeOffset !== void 0) {
208
+ return encodeMultiSampleSegment(
209
+ [{ data, duration, keyframe, compositionTimeOffset }],
210
+ timestamp,
211
+ sequence,
212
+ trackId
213
+ );
214
+ }
215
+ const sampleFlags = keyframe ? KEYFRAME_FLAGS : DELTA_FLAGS;
216
+ const mfhd = fullBox("mfhd", 0, 0, u32(sequence));
217
+ const tfhd = fullBox("tfhd", 0, 131072, u32(trackId));
218
+ const tfdtBody = new Uint8Array(8);
219
+ const tfdtView = new DataView(tfdtBody.buffer);
220
+ tfdtView.setUint32(0, Math.floor(timestamp / 4294967296));
221
+ tfdtView.setUint32(4, timestamp >>> 0);
222
+ const tfdt = fullBox("tfdt", 1, 0, tfdtBody);
223
+ const trunBody = new Uint8Array(20);
224
+ const trunView = new DataView(trunBody.buffer);
225
+ trunView.setUint32(0, 1);
226
+ trunView.setUint32(4, 0);
227
+ trunView.setUint32(8, duration >>> 0);
228
+ trunView.setUint32(12, data.length);
229
+ trunView.setUint32(16, sampleFlags);
230
+ const trun = fullBox("trun", 0, 1793, trunBody);
231
+ const traf = box("traf", tfhd, tfdt, trun);
232
+ const moof = box("moof", mfhd, traf);
233
+ const mdat = box("mdat", data);
234
+ const dataOffsetPos = 8 + mfhd.length + 8 + tfhd.length + tfdt.length + 12 + 4;
235
+ new DataView(moof.buffer).setUint32(dataOffsetPos, moof.length + 8);
236
+ const result = new Uint8Array(moof.length + mdat.length);
237
+ result.set(moof, 0);
238
+ result.set(mdat, moof.length);
239
+ return result;
240
+ }
241
+ function buildVideoInitSegment(avcC, width, height, timescale = 1e6, trackId = 1) {
242
+ assertTrackId(trackId, "video trackId");
243
+ assertTimescale(timescale, "video timescale");
244
+ const ftyp = box("ftyp", new Uint8Array([
245
+ 105,
246
+ 115,
247
+ 111,
248
+ 109,
249
+ 0,
250
+ 0,
251
+ 2,
252
+ 0,
253
+ 105,
254
+ 115,
255
+ 111,
256
+ 109,
257
+ 105,
258
+ 115,
259
+ 111,
260
+ 54,
261
+ 109,
262
+ 112,
263
+ 52,
264
+ 49
265
+ ]));
266
+ const avcCBox = box("avcC", avcC);
267
+ const avc1Body = new Uint8Array(78 + avcCBox.length);
268
+ const avc1View = new DataView(avc1Body.buffer);
269
+ avc1View.setUint16(6, 1);
270
+ avc1View.setUint16(24, width);
271
+ avc1View.setUint16(26, height);
272
+ avc1View.setUint32(28, 4718592);
273
+ avc1View.setUint32(32, 4718592);
274
+ avc1View.setUint16(40, 1);
275
+ avc1View.setUint16(74, 24);
276
+ avc1View.setInt16(76, -1);
277
+ avc1Body.set(avcCBox, 78);
278
+ const avc1 = box("avc1", avc1Body);
279
+ const stsd = fullBox("stsd", 0, 0, u32(1), avc1);
280
+ const stbl = box(
281
+ "stbl",
282
+ stsd,
283
+ fullBox("stts", 0, 0, u32(0)),
284
+ fullBox("stsc", 0, 0, u32(0)),
285
+ fullBox("stsz", 0, 0, u32(0), u32(0)),
286
+ fullBox("stco", 0, 0, u32(0))
287
+ );
288
+ const dinf = box("dinf", fullBox("dref", 0, 0, u32(1), fullBox("url ", 0, 1)));
289
+ const minf = box("minf", fullBox("vmhd", 0, 1), dinf, stbl);
290
+ const hdlr = fullBox("hdlr", 0, 0, new Uint8Array([
291
+ 0,
292
+ 0,
293
+ 0,
294
+ 0,
295
+ 118,
296
+ 105,
297
+ 100,
298
+ 101,
299
+ 0,
300
+ 0,
301
+ 0,
302
+ 0,
303
+ 0,
304
+ 0,
305
+ 0,
306
+ 0,
307
+ 0,
308
+ 0,
309
+ 0,
310
+ 0,
311
+ 86,
312
+ 105,
313
+ 100,
314
+ 101,
315
+ 111,
316
+ 0
317
+ ]));
318
+ const mdhdBody = new Uint8Array(20);
319
+ new DataView(mdhdBody.buffer).setUint32(8, timescale);
320
+ const mdhd = fullBox("mdhd", 0, 0, mdhdBody);
321
+ const mdia = box("mdia", mdhd, hdlr, minf);
322
+ const tkhdBody = new Uint8Array(80);
323
+ const tkhdView = new DataView(tkhdBody.buffer);
324
+ tkhdView.setUint32(8, trackId);
325
+ tkhdView.setUint32(36, 65536);
326
+ tkhdView.setUint32(52, 65536);
327
+ tkhdView.setUint32(64, 1073741824);
328
+ tkhdView.setUint32(72, width << 16);
329
+ tkhdView.setUint32(76, height << 16);
330
+ const tkhd = fullBox("tkhd", 0, 3, tkhdBody);
331
+ const trak = box("trak", tkhd, mdia);
332
+ const mvhdBody = new Uint8Array(96);
333
+ const mvhdView = new DataView(mvhdBody.buffer);
334
+ mvhdView.setUint32(8, timescale);
335
+ mvhdView.setUint32(16, 65536);
336
+ mvhdView.setUint16(20, 256);
337
+ mvhdView.setUint32(32, 65536);
338
+ mvhdView.setUint32(48, 65536);
339
+ mvhdView.setUint32(60, 1073741824);
340
+ mvhdView.setUint32(92, trackId + 1);
341
+ const mvhd = fullBox("mvhd", 0, 0, mvhdBody);
342
+ const trexBody = new Uint8Array(20);
343
+ new DataView(trexBody.buffer).setUint32(0, trackId);
344
+ new DataView(trexBody.buffer).setUint32(4, 1);
345
+ const mvex = box("mvex", fullBox("trex", 0, 0, trexBody));
346
+ const moov = box("moov", mvhd, trak, mvex);
347
+ const result = new Uint8Array(ftyp.length + moov.length);
348
+ result.set(ftyp, 0);
349
+ result.set(moov, ftyp.length);
350
+ return result;
351
+ }
352
+ function buildAudioInitSegment(sampleRate, channels, asc, timescale, trackId = 1) {
353
+ assertTrackId(trackId, "audio trackId");
354
+ const ts = timescale ?? sampleRate;
355
+ if (!asc) {
356
+ const freqTable = [96e3, 88200, 64e3, 48e3, 44100, 32e3, 24e3, 22050, 16e3, 12e3, 11025, 8e3, 7350];
357
+ const fi = freqTable.indexOf(sampleRate);
358
+ const freqIdx = fi >= 0 ? fi : 15;
359
+ if (freqIdx <= 14) {
360
+ const v = 2 << 11 | freqIdx << 7 | channels << 3;
361
+ asc = new Uint8Array([v >> 8 & 255, v & 255]);
362
+ } else {
363
+ asc = new Uint8Array([
364
+ 2 << 3 | 7,
365
+ (8 | sampleRate >> 20 & 7) & 255,
366
+ sampleRate >> 12 & 255,
367
+ sampleRate >> 4 & 255,
368
+ ((sampleRate & 15) << 4 | channels << 0) & 255
369
+ ]);
370
+ }
371
+ }
372
+ const dsi = new Uint8Array(2 + asc.length);
373
+ dsi[0] = 5;
374
+ dsi[1] = asc.length;
375
+ dsi.set(asc, 2);
376
+ const dcdBody = new Uint8Array(13 + dsi.length);
377
+ dcdBody[0] = 64;
378
+ dcdBody[1] = 21;
379
+ dcdBody.set(dsi, 13);
380
+ const dcd = new Uint8Array(2 + dcdBody.length);
381
+ dcd[0] = 4;
382
+ dcd[1] = dcdBody.length;
383
+ dcd.set(dcdBody, 2);
384
+ const esBody = new Uint8Array(3 + dcd.length);
385
+ esBody[0] = 0;
386
+ esBody[1] = 1;
387
+ esBody[2] = 0;
388
+ esBody.set(dcd, 3);
389
+ const es = new Uint8Array(2 + esBody.length);
390
+ es[0] = 3;
391
+ es[1] = esBody.length;
392
+ es.set(esBody, 2);
393
+ const esdsBox = fullBox("esds", 0, 0, es);
394
+ const mp4aBody = new Uint8Array(28 + esdsBox.length);
395
+ const mp4aView = new DataView(mp4aBody.buffer);
396
+ mp4aView.setUint16(6, 1);
397
+ mp4aView.setUint16(16, channels);
398
+ mp4aView.setUint16(18, 16);
399
+ mp4aView.setUint32(24, sampleRate << 16);
400
+ mp4aBody.set(esdsBox, 28);
401
+ const mp4a = box("mp4a", mp4aBody);
402
+ const stsd = fullBox("stsd", 0, 0, u32(1), mp4a);
403
+ const stbl = box(
404
+ "stbl",
405
+ stsd,
406
+ fullBox("stts", 0, 0, u32(0)),
407
+ fullBox("stsc", 0, 0, u32(0)),
408
+ fullBox("stsz", 0, 0, u32(0), u32(0)),
409
+ fullBox("stco", 0, 0, u32(0))
410
+ );
411
+ const dinf = box("dinf", fullBox("dref", 0, 0, u32(1), fullBox("url ", 0, 1)));
412
+ const minf = box("minf", fullBox("smhd", 0, 0, new Uint8Array(4)), dinf, stbl);
413
+ const hdlr = fullBox("hdlr", 0, 0, new Uint8Array([
414
+ 0,
415
+ 0,
416
+ 0,
417
+ 0,
418
+ 115,
419
+ 111,
420
+ 117,
421
+ 110,
422
+ 0,
423
+ 0,
424
+ 0,
425
+ 0,
426
+ 0,
427
+ 0,
428
+ 0,
429
+ 0,
430
+ 0,
431
+ 0,
432
+ 0,
433
+ 0,
434
+ 83,
435
+ 111,
436
+ 117,
437
+ 110,
438
+ 100,
439
+ 0
440
+ ]));
441
+ const mdhdBody = new Uint8Array(20);
442
+ new DataView(mdhdBody.buffer).setUint32(8, ts);
443
+ const mdhd = fullBox("mdhd", 0, 0, mdhdBody);
444
+ const mdia = box("mdia", mdhd, hdlr, minf);
445
+ const tkhdBody = new Uint8Array(80);
446
+ const tkhdView = new DataView(tkhdBody.buffer);
447
+ tkhdView.setUint32(8, trackId);
448
+ tkhdView.setUint32(36, 65536);
449
+ tkhdView.setUint32(52, 65536);
450
+ tkhdView.setUint32(64, 1073741824);
451
+ const tkhd = fullBox("tkhd", 0, 3, tkhdBody);
452
+ const trak = box("trak", tkhd, mdia);
453
+ const mvhdBody = new Uint8Array(96);
454
+ const mvhdView = new DataView(mvhdBody.buffer);
455
+ mvhdView.setUint32(8, ts);
456
+ mvhdView.setUint32(16, 65536);
457
+ mvhdView.setUint16(20, 256);
458
+ mvhdView.setUint32(32, 65536);
459
+ mvhdView.setUint32(48, 65536);
460
+ mvhdView.setUint32(60, 1073741824);
461
+ mvhdView.setUint32(92, trackId + 1);
462
+ const mvhd = fullBox("mvhd", 0, 0, mvhdBody);
463
+ const trexBody = new Uint8Array(20);
464
+ new DataView(trexBody.buffer).setUint32(0, trackId);
465
+ new DataView(trexBody.buffer).setUint32(4, 1);
466
+ const mvex = box("mvex", fullBox("trex", 0, 0, trexBody));
467
+ const moov = box("moov", mvhd, trak, mvex);
468
+ const ftyp = box("ftyp", new Uint8Array([
469
+ 105,
470
+ 115,
471
+ 111,
472
+ 109,
473
+ 0,
474
+ 0,
475
+ 2,
476
+ 0,
477
+ 105,
478
+ 115,
479
+ 111,
480
+ 109,
481
+ 105,
482
+ 115,
483
+ 111,
484
+ 54,
485
+ 109,
486
+ 112,
487
+ 52,
488
+ 49
489
+ ]));
490
+ const result = new Uint8Array(ftyp.length + moov.length);
491
+ result.set(ftyp, 0);
492
+ result.set(moov, ftyp.length);
493
+ return result;
494
+ }
495
+
496
+ // src/codec-utils.ts
497
+ function removeEmulationPrevention(rbsp) {
498
+ const out = [];
499
+ let zeros = 0;
500
+ for (let i = 0; i < rbsp.length; i++) {
501
+ const b = rbsp[i];
502
+ if (zeros >= 2 && b === 3 && i + 1 < rbsp.length && rbsp[i + 1] <= 3) {
503
+ zeros = 0;
504
+ continue;
505
+ }
506
+ out.push(b);
507
+ zeros = b === 0 ? zeros + 1 : 0;
508
+ }
509
+ return Uint8Array.from(out);
510
+ }
511
+ function splitAvccNalUnits(data, lengthSize = 4) {
512
+ const nals = [];
513
+ let i = 0;
514
+ while (i + lengthSize <= data.length) {
515
+ let len = 0;
516
+ for (let k = 0; k < lengthSize; k++) len = len << 8 | data[i + k];
517
+ i += lengthSize;
518
+ if (len <= 0 || i + len > data.length) break;
519
+ nals.push(data.subarray(i, i + len));
520
+ i += len;
521
+ }
522
+ return nals;
523
+ }
524
+ function isCompleteAvccSample(data, lengthSize = 4) {
525
+ let i = 0;
526
+ let count = 0;
527
+ while (i + lengthSize <= data.length) {
528
+ let len = 0;
529
+ for (let k = 0; k < lengthSize; k++) len = len << 8 | data[i + k];
530
+ i += lengthSize;
531
+ if (len <= 0 || i + len > data.length) return false;
532
+ i += len;
533
+ count++;
534
+ }
535
+ return count > 0 && i === data.length;
536
+ }
537
+ function splitH264SampleNalUnits(data, options = {}) {
538
+ if (isCompleteAvccSample(data)) return { nals: splitAvccNalUnits(data), format: "avcc" };
539
+ if (isAnnexB(data)) return { nals: splitAnnexBNalUnits(data), format: "annexb" };
540
+ if (options.allowPartialAvcc === true) {
541
+ const partial = splitPartialAvccNalUnits(data);
542
+ if (partial.length > 0) return { nals: partial, format: "partial-avcc" };
543
+ }
544
+ if (isLikelyRawH264NalUnit(data)) return { nals: [data], format: "raw-nal" };
545
+ const nals = splitAvccNalUnits(data);
546
+ return { nals, format: nals.length > 0 ? "avcc" : "unknown" };
547
+ }
548
+ function isAnnexB(data) {
549
+ if (data.length >= 4 && data[0] === 0 && data[1] === 0 && (data[2] === 1 || data[2] === 0 && data[3] === 1)) {
550
+ return true;
551
+ }
552
+ return false;
553
+ }
554
+ function splitAnnexBNalUnits(data) {
555
+ const nalUnits = [];
556
+ let i = 0;
557
+ while (i < data.length - 3) {
558
+ if (data[i] === 0 && data[i + 1] === 0) {
559
+ let scLen = 0;
560
+ if (data[i + 2] === 1) scLen = 3;
561
+ else if (data[i + 2] === 0 && i + 3 < data.length && data[i + 3] === 1) scLen = 4;
562
+ if (scLen > 0) {
563
+ const nalStart = i + scLen;
564
+ let nalEnd = data.length;
565
+ for (let j = nalStart + 1; j < data.length - 2; j++) {
566
+ if (data[j] === 0 && data[j + 1] === 0 && (data[j + 2] === 1 || data[j + 2] === 0 && j + 3 < data.length && data[j + 3] === 1)) {
567
+ nalEnd = j;
568
+ break;
569
+ }
570
+ }
571
+ if (nalEnd > nalStart) nalUnits.push(data.subarray(nalStart, nalEnd));
572
+ i = nalEnd;
573
+ continue;
574
+ }
575
+ }
576
+ i++;
577
+ }
578
+ return nalUnits;
579
+ }
580
+ function classifyH264Keyframe(data, options = {}) {
581
+ const nals = h264NalUnitsForKeyframeDetection(data, options);
582
+ if (nals.length === 0) return void 0;
583
+ let sawIntraSlice = false;
584
+ let sawNonIntraVcl = false;
585
+ let sawNal = false;
586
+ for (const nal of nals) {
587
+ sawNal = true;
588
+ const nalType = nal[0] !== void 0 ? nal[0] & 31 : -1;
589
+ if (nalType === 5 || nalType === 7) return true;
590
+ if (nalType === 1) {
591
+ if (isH264IntraSlice(nal)) sawIntraSlice = true;
592
+ else sawNonIntraVcl = true;
593
+ }
594
+ }
595
+ if (sawIntraSlice && !sawNonIntraVcl) return true;
596
+ return sawNal ? false : void 0;
597
+ }
598
+ function detectH264Keyframe(data, options = {}) {
599
+ return classifyH264Keyframe(data, options) === true;
600
+ }
601
+ function h264NalUnitsForKeyframeDetection(data, options) {
602
+ return splitH264SampleNalUnits(data, options).nals;
603
+ }
604
+ function splitPartialAvccNalUnits(data, lengthSize = 4) {
605
+ const nals = [];
606
+ let i = 0;
607
+ while (i + lengthSize < data.length) {
608
+ let len = 0;
609
+ for (let k = 0; k < lengthSize; k++) len = len << 8 | data[i + k];
610
+ i += lengthSize;
611
+ if (len <= 0 || i >= data.length) break;
612
+ const end = Math.min(i + len, data.length);
613
+ nals.push(data.subarray(i, end));
614
+ if (end < i + len) break;
615
+ i = end;
616
+ }
617
+ return nals;
618
+ }
619
+ function isLikelyRawH264NalUnit(data) {
620
+ if (data.length === 0) return false;
621
+ const header = data[0];
622
+ if ((header & 128) !== 0) return false;
623
+ const nalType = header & 31;
624
+ return nalType > 0 && nalType < 24;
625
+ }
626
+ function isH264IntraSlice(nal) {
627
+ const sliceType = readH264SliceType(nal);
628
+ return sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9;
629
+ }
630
+ function readH264SliceType(nal) {
631
+ if (nal.length < 2 || (nal[0] & 31) !== 1) return null;
632
+ const rbsp = removeEmulationPrevention(nal.subarray(1));
633
+ const state = { bitOffset: 0 };
634
+ if (readUnsignedExpGolomb(rbsp, state) === null) return null;
635
+ return readUnsignedExpGolomb(rbsp, state);
636
+ }
637
+ function readUnsignedExpGolomb(data, state) {
638
+ let leadingZeroBits = 0;
639
+ while (true) {
640
+ const bit = readBit(data, state);
641
+ if (bit === null) return null;
642
+ if (bit === 1) break;
643
+ leadingZeroBits++;
644
+ if (leadingZeroBits > 30) return null;
645
+ }
646
+ let suffix = 0;
647
+ for (let i = 0; i < leadingZeroBits; i++) {
648
+ const bit = readBit(data, state);
649
+ if (bit === null) return null;
650
+ suffix = suffix << 1 | bit;
651
+ }
652
+ return (1 << leadingZeroBits) - 1 + suffix;
653
+ }
654
+ function readBit(data, state) {
655
+ if (state.bitOffset >= data.length * 8) return null;
656
+ const byte = data[state.bitOffset >> 3];
657
+ const bit = byte >> 7 - (state.bitOffset & 7) & 1;
658
+ state.bitOffset++;
659
+ return bit;
660
+ }
661
+ if (void 0) {
662
+ const { describe, test, expect } = void 0;
663
+ describe("codec-utils", () => {
664
+ describe("isAnnexB", () => {
665
+ test("4-byte start code", () => {
666
+ expect(isAnnexB(new Uint8Array([0, 0, 0, 1, 101]))).toBe(true);
667
+ });
668
+ test("3-byte start code", () => {
669
+ expect(isAnnexB(new Uint8Array([0, 0, 1, 101]))).toBe(true);
670
+ });
671
+ test("rejects AVCC", () => {
672
+ expect(isAnnexB(new Uint8Array([0, 0, 0, 10, 101]))).toBe(false);
673
+ });
674
+ });
675
+ describe("findAnnexBStartCode", () => {
676
+ test("at offset 0", () => {
677
+ expect(findAnnexBStartCode(new Uint8Array([0, 0, 0, 1, 101]))).toBe(0);
678
+ });
679
+ test("at offset 5", () => {
680
+ expect(findAnnexBStartCode(new Uint8Array([170, 187, 204, 221, 238, 0, 0, 1, 101]))).toBe(5);
681
+ });
682
+ test("returns -1 when none", () => {
683
+ expect(findAnnexBStartCode(new Uint8Array([170, 187, 204]))).toBe(-1);
684
+ });
685
+ });
686
+ describe("splitAnnexBNalUnits", () => {
687
+ test("splits two NALs", () => {
688
+ const data = new Uint8Array([0, 0, 0, 1, 101, 170, 187, 0, 0, 0, 1, 65, 204]);
689
+ const nals = splitAnnexBNalUnits(data);
690
+ expect(nals.length).toBe(2);
691
+ expect(nals[0]).toEqual(new Uint8Array([101, 170, 187]));
692
+ expect(nals[1]).toEqual(new Uint8Array([65, 204]));
693
+ });
694
+ test("handles 3-byte start codes", () => {
695
+ const nals = splitAnnexBNalUnits(new Uint8Array([0, 0, 1, 103, 66, 0, 0, 1, 104, 1]));
696
+ expect(nals.length).toBe(2);
697
+ });
698
+ });
699
+ describe("annexBToAvcc", () => {
700
+ test("converts single NAL", () => {
701
+ const annexB = new Uint8Array([0, 0, 0, 1, 65, 170, 187]);
702
+ const avcc = annexBToAvcc(annexB);
703
+ expect(avcc[3]).toBe(3);
704
+ expect(avcc[4]).toBe(65);
705
+ });
706
+ test("prepends SPS/PPS", () => {
707
+ const annexB = new Uint8Array([0, 0, 0, 1, 101, 1]);
708
+ const avcc = annexBToAvcc(annexB, { sps: new Uint8Array([103, 66]), pps: new Uint8Array([104, 1]) });
709
+ expect(avcc[3]).toBe(2);
710
+ expect(avcc[4]).toBe(103);
711
+ });
712
+ });
713
+ describe("detectH264Keyframe", () => {
714
+ test("IDR in Annex-B", () => {
715
+ expect(detectH264Keyframe(new Uint8Array([0, 0, 0, 1, 101]))).toBe(true);
716
+ });
717
+ test("SPS in Annex-B", () => {
718
+ expect(detectH264Keyframe(new Uint8Array([0, 0, 0, 1, 103]))).toBe(true);
719
+ });
720
+ test("IDR in AVCC", () => {
721
+ expect(detectH264Keyframe(new Uint8Array([0, 0, 0, 5, 101, 1, 2, 3, 4]))).toBe(true);
722
+ });
723
+ test("IDR after AVCC AUD", () => {
724
+ expect(detectH264Keyframe(new Uint8Array([
725
+ 0,
726
+ 0,
727
+ 0,
728
+ 1,
729
+ 9,
730
+ 0,
731
+ 0,
732
+ 0,
733
+ 2,
734
+ 101,
735
+ 170
736
+ ]))).toBe(true);
737
+ });
738
+ test("non-IDR AVC I-slice in AVCC", () => {
739
+ expect(detectH264Keyframe(new Uint8Array([
740
+ 0,
741
+ 0,
742
+ 0,
743
+ 2,
744
+ 65,
745
+ 136
746
+ ]))).toBe(true);
747
+ });
748
+ test("raw H.264 IDR NAL", () => {
749
+ expect(detectH264Keyframe(new Uint8Array([101, 136, 132]))).toBe(true);
750
+ });
751
+ test("raw H.264 non-IDR I-slice NAL", () => {
752
+ expect(detectH264Keyframe(new Uint8Array([65, 136]))).toBe(true);
753
+ });
754
+ test("classifies partial length-prefixed IDR only when requested", () => {
755
+ const partial = new Uint8Array([0, 0, 32, 0, 101]);
756
+ expect(classifyH264Keyframe(partial)).toBeUndefined();
757
+ expect(classifyH264Keyframe(partial, { allowPartialAvcc: true })).toBe(true);
758
+ });
759
+ test("rejects P-frame", () => {
760
+ expect(detectH264Keyframe(new Uint8Array([0, 0, 0, 1, 65]))).toBe(false);
761
+ });
762
+ test("rejects AVCC sample with only non-IDR slices", () => {
763
+ expect(detectH264Keyframe(new Uint8Array([
764
+ 0,
765
+ 0,
766
+ 0,
767
+ 2,
768
+ 65,
769
+ 192,
770
+ 0,
771
+ 0,
772
+ 0,
773
+ 2,
774
+ 65,
775
+ 192
776
+ ]))).toBe(false);
777
+ });
778
+ });
779
+ describe("avccToAnnexB", () => {
780
+ test("converts with SPS/PPS on keyframe", () => {
781
+ const avcc = new Uint8Array([0, 0, 0, 3, 101, 170, 187]);
782
+ const spsPps = { sps: new Uint8Array([103, 66]), pps: new Uint8Array([104, 1]) };
783
+ const annexB = avccToAnnexB(avcc, true, spsPps);
784
+ expect(annexB[3]).toBe(1);
785
+ expect(annexB[4]).toBe(103);
786
+ });
787
+ });
788
+ describe("codecStringFromAvcC", () => {
789
+ test("derives avc1.64002a", () => {
790
+ expect(codecStringFromAvcC(new Uint8Array([1, 100, 0, 42]))).toBe("avc1.64002a");
791
+ });
792
+ });
793
+ describe("extractAacAscFromInitSegment", () => {
794
+ function buildMinimalAacInit(asc) {
795
+ const box2 = (type, payload) => {
796
+ const sz = 8 + payload.length;
797
+ const out = new Uint8Array(sz);
798
+ out[0] = sz >>> 24 & 255;
799
+ out[1] = sz >>> 16 & 255;
800
+ out[2] = sz >>> 8 & 255;
801
+ out[3] = sz & 255;
802
+ out[4] = type.charCodeAt(0);
803
+ out[5] = type.charCodeAt(1);
804
+ out[6] = type.charCodeAt(2);
805
+ out[7] = type.charCodeAt(3);
806
+ out.set(payload, 8);
807
+ return out;
808
+ };
809
+ const concat = (...arrs) => {
810
+ const total = arrs.reduce((n, a) => n + a.length, 0);
811
+ const out = new Uint8Array(total);
812
+ let off = 0;
813
+ for (const a of arrs) {
814
+ out.set(a, off);
815
+ off += a.length;
816
+ }
817
+ return out;
818
+ };
819
+ const ftyp = box2("ftyp", new Uint8Array([
820
+ 105,
821
+ 115,
822
+ 111,
823
+ 53,
824
+ // 'iso5'
825
+ 0,
826
+ 0,
827
+ 2,
828
+ 0,
829
+ // minor 0x200
830
+ 105,
831
+ 115,
832
+ 111,
833
+ 53,
834
+ // 'iso5'
835
+ 105,
836
+ 115,
837
+ 111,
838
+ 54
839
+ // 'iso6'
840
+ ]));
841
+ const dsi = new Uint8Array(2 + asc.length);
842
+ dsi[0] = 5;
843
+ dsi[1] = asc.length;
844
+ dsi.set(asc, 2);
845
+ const dcd = new Uint8Array(2 + 13 + dsi.length);
846
+ dcd[0] = 4;
847
+ dcd[1] = 13 + dsi.length;
848
+ dcd[2] = 64;
849
+ dcd[3] = 5 << 2 | 1;
850
+ dcd.set(dsi, 15);
851
+ const esd = new Uint8Array(2 + 3 + dcd.length);
852
+ esd[0] = 3;
853
+ esd[1] = 3 + dcd.length;
854
+ esd.set(dcd, 5);
855
+ const esdsPayload = new Uint8Array(4 + esd.length);
856
+ esdsPayload.set(esd, 4);
857
+ const esds = box2("esds", esdsPayload);
858
+ const mp4aFixed = new Uint8Array(28);
859
+ mp4aFixed[7] = 1;
860
+ mp4aFixed[16] = 0;
861
+ mp4aFixed[17] = 1;
862
+ mp4aFixed[18] = 0;
863
+ mp4aFixed[19] = 16;
864
+ mp4aFixed[24] = 187;
865
+ mp4aFixed[25] = 128;
866
+ const mp4a = box2("mp4a", concat(mp4aFixed, esds));
867
+ const stsdPayload = new Uint8Array(8 + mp4a.length);
868
+ stsdPayload[7] = 1;
869
+ stsdPayload.set(mp4a, 8);
870
+ const stsd = box2("stsd", stsdPayload);
871
+ const stbl = box2("stbl", stsd);
872
+ const minf = box2("minf", stbl);
873
+ const mdia = box2("mdia", minf);
874
+ const trak = box2("trak", mdia);
875
+ const moov = box2("moov", trak);
876
+ return concat(ftyp, moov);
877
+ }
878
+ test("extracts AAC-LC mono 48k ASC and derives codec", () => {
879
+ const asc = new Uint8Array([17, 136]);
880
+ const init = buildMinimalAacInit(asc);
881
+ const result = extractAacAscFromInitSegment(init);
882
+ expect(result).toBeDefined();
883
+ expect(result.codec).toBe("mp4a.40.2");
884
+ expect(Array.from(result.description)).toEqual([17, 136]);
885
+ });
886
+ test("derives AOT 5 (HE-AAC) from ASC[0] >> 3", () => {
887
+ const asc = new Uint8Array([41, 136]);
888
+ const init = buildMinimalAacInit(asc);
889
+ expect(extractAacAscFromInitSegment(init)?.codec).toBe("mp4a.40.5");
890
+ });
891
+ test("rejects data without ftyp/moov magic", () => {
892
+ expect(extractAacAscFromInitSegment(new Uint8Array(64))).toBeUndefined();
893
+ });
894
+ test("rejects ftyp+moov with no audio (no mp4a sample entry)", () => {
895
+ const ftyp = new Uint8Array([
896
+ 0,
897
+ 0,
898
+ 0,
899
+ 24,
900
+ 102,
901
+ 116,
902
+ 121,
903
+ 112,
904
+ 105,
905
+ 115,
906
+ 111,
907
+ 53,
908
+ 0,
909
+ 0,
910
+ 2,
911
+ 0,
912
+ 105,
913
+ 115,
914
+ 111,
915
+ 53,
916
+ 105,
917
+ 115,
918
+ 111,
919
+ 54
920
+ ]);
921
+ const moov = new Uint8Array([0, 0, 0, 8, 109, 111, 111, 118]);
922
+ const cat = new Uint8Array(ftyp.length + moov.length);
923
+ cat.set(ftyp);
924
+ cat.set(moov, ftyp.length);
925
+ expect(extractAacAscFromInitSegment(cat)).toBeUndefined();
926
+ });
927
+ });
928
+ describe("hevc", () => {
929
+ const vps = new Uint8Array([64, 1, 12, 1, 255, 255]);
930
+ const sps = new Uint8Array([66, 1, 1, 1, 96, 0, 0, 0, 144, 0, 0, 0, 0, 0, 60, 160, 5, 2]);
931
+ const pps = new Uint8Array([68, 1, 193, 114, 180, 98]);
932
+ const idr = new Uint8Array([38, 1, 175, 6]);
933
+ const lp = (...nals) => {
934
+ const parts = [];
935
+ for (const n of nals) {
936
+ parts.push(n.length >> 24 & 255, n.length >> 16 & 255, n.length >> 8 & 255, n.length & 255, ...n);
937
+ }
938
+ return Uint8Array.from(parts);
939
+ };
940
+ test("isHevcCodec", () => {
941
+ expect(isHevcCodec("hev1.1.6.L93.B0")).toBe(true);
942
+ expect(isHevcCodec("hvc1.1.6.L93.B0")).toBe(true);
943
+ expect(isHevcCodec("avc1.640033")).toBe(false);
944
+ });
945
+ test("removeEmulationPrevention strips 0x03", () => {
946
+ expect(Array.from(removeEmulationPrevention(new Uint8Array([0, 0, 3, 1])))).toEqual([0, 0, 1]);
947
+ expect(Array.from(removeEmulationPrevention(new Uint8Array([170, 187])))).toEqual([170, 187]);
948
+ });
949
+ test("splitAvccNalUnits splits length-prefixed NALs", () => {
950
+ const nals = splitAvccNalUnits(lp(vps, sps));
951
+ expect(nals.length).toBe(2);
952
+ expect(nals[0]).toEqual(vps);
953
+ expect(nals[1]).toEqual(sps);
954
+ });
955
+ test("isCompleteAvccSample accepts complete length-prefixed NAL samples", () => {
956
+ expect(isCompleteAvccSample(lp(new Uint8Array([9]), idr))).toBe(true);
957
+ });
958
+ test("isCompleteAvccSample rejects Annex-B start-code samples", () => {
959
+ expect(isCompleteAvccSample(new Uint8Array([0, 0, 0, 1, 101, 170]))).toBe(false);
960
+ });
961
+ test("isCompleteAvccSample rejects truncated length-prefixed samples", () => {
962
+ expect(isCompleteAvccSample(new Uint8Array([0, 0, 0, 4, 101, 170]))).toBe(false);
963
+ });
964
+ test("normalizeH264SampleToAvcc leaves complete AVCC samples unchanged", () => {
965
+ const avcc = lp(new Uint8Array([9]), idr);
966
+ const normalized = normalizeH264SampleToAvcc(avcc);
967
+ expect(normalized.format).toBe("avcc");
968
+ expect(normalized.data).toBe(avcc);
969
+ });
970
+ test("normalizeH264SampleToAvcc converts a single raw H.264 NAL to AVCC", () => {
971
+ const raw = new Uint8Array([101, 136, 132]);
972
+ const normalized = normalizeH264SampleToAvcc(raw);
973
+ expect(normalized.format).toBe("raw-nal");
974
+ expect(normalized.data).toEqual(new Uint8Array([0, 0, 0, 3, 101, 136, 132]));
975
+ });
976
+ test("splitH264SampleNalUnits exposes Annex-B NALs without AVCC conversion", () => {
977
+ const annexB = new Uint8Array([0, 0, 0, 1, 101, 136, 132]);
978
+ const sample = splitH264SampleNalUnits(annexB);
979
+ expect(sample.format).toBe("annexb");
980
+ expect(sample.nals).toHaveLength(1);
981
+ expect(sample.nals[0]).toEqual(new Uint8Array([101, 136, 132]));
982
+ });
983
+ test("splitH264SampleNalUnits exposes single raw H.264 NALs without wrapping", () => {
984
+ const raw = new Uint8Array([101, 136, 132]);
985
+ const sample = splitH264SampleNalUnits(raw);
986
+ expect(sample.format).toBe("raw-nal");
987
+ expect(sample.nals).toEqual([raw]);
988
+ });
989
+ test("splitH264SampleNalUnits can expose partial AVCC NAL headers", () => {
990
+ const partial = new Uint8Array([0, 0, 0, 5, 101, 136]);
991
+ const sample = splitH264SampleNalUnits(partial, { allowPartialAvcc: true });
992
+ expect(sample.format).toBe("partial-avcc");
993
+ expect(sample.nals).toHaveLength(1);
994
+ expect(sample.nals[0]).toEqual(new Uint8Array([101, 136]));
995
+ });
996
+ test("extractHevcParameterSets finds VPS/SPS/PPS (length-prefixed)", () => {
997
+ const sets = extractHevcParameterSets(lp(vps, sps, pps, idr));
998
+ expect(sets.vps).toEqual(vps);
999
+ expect(sets.sps).toEqual(sps);
1000
+ expect(sets.pps).toEqual(pps);
1001
+ });
1002
+ test("extractHevcParameterSets finds VPS/SPS/PPS (Annex-B)", () => {
1003
+ const sc = new Uint8Array([0, 0, 0, 1]);
1004
+ const annexb = Uint8Array.from([...sc, ...vps, ...sc, ...sps, ...sc, ...pps, ...sc, ...idr]);
1005
+ const sets = extractHevcParameterSets(annexb);
1006
+ expect(sets.vps).toEqual(vps);
1007
+ expect(sets.sps).toEqual(sps);
1008
+ expect(sets.pps).toEqual(pps);
1009
+ });
1010
+ test("generateHvcCFromParameterSets builds a valid hvcC", () => {
1011
+ const hvcc = generateHvcCFromParameterSets({ vps, sps, pps });
1012
+ expect(hvcc).not.toBeNull();
1013
+ expect(hvcc[0]).toBe(1);
1014
+ expect(hvcc[1]).toBe(sps[3]);
1015
+ expect(hvcc[22]).toBe(3);
1016
+ expect(hvcc[23] & 63).toBe(32);
1017
+ expect(hvcc[24] << 8 | hvcc[25]).toBe(1);
1018
+ });
1019
+ test("generateHvcCFromParameterSets returns null without SPS/PPS", () => {
1020
+ expect(generateHvcCFromParameterSets({ vps })).toBeNull();
1021
+ });
1022
+ test("extractHevcCodecDescription end-to-end from keyframe", () => {
1023
+ const desc = extractHevcCodecDescription(lp(vps, sps, pps, idr));
1024
+ expect(desc).not.toBeNull();
1025
+ expect(desc[0]).toBe(1);
1026
+ });
1027
+ test("hevcVclOnly strips parameter-set NALs, keeps VCL", () => {
1028
+ const stripped = hevcVclOnly(lp(vps, sps, pps, idr));
1029
+ const nals = splitAvccNalUnits(stripped);
1030
+ expect(nals.length).toBe(1);
1031
+ expect(nals[0]).toEqual(idr);
1032
+ });
1033
+ test("hevcVclOnly is a no-op for VCL-only length-prefixed input", () => {
1034
+ const vclOnly = lp(idr);
1035
+ expect(hevcVclOnly(vclOnly)).toBe(vclOnly);
1036
+ });
1037
+ });
1038
+ });
1039
+ }
1040
+
1041
+ // src/authored-timing.ts
1042
+ function scaleAuthoredTicks(ticks, mediaTimescale, targetTimescale) {
1043
+ if (!Number.isSafeInteger(mediaTimescale) || mediaTimescale <= 0 || !Number.isSafeInteger(targetTimescale) || targetTimescale <= 0) return null;
1044
+ const negative = ticks < 0n;
1045
+ const numerator = (negative ? -ticks : ticks) * BigInt(targetTimescale);
1046
+ const denominator = BigInt(mediaTimescale);
1047
+ const whole = numerator / denominator;
1048
+ const remainder = numerator % denominator;
1049
+ if (whole > BigInt(Number.MAX_SAFE_INTEGER)) return null;
1050
+ const value = Number(whole) + Number(remainder) / mediaTimescale;
1051
+ return Number.isFinite(value) ? negative ? -value : value : null;
1052
+ }
1053
+ function scaleAuthoredTiming(timing, targetTimescale) {
1054
+ if (!Number.isSafeInteger(timing.durationTicks) || timing.durationTicks <= 0) return null;
1055
+ const timestamp = scaleAuthoredTicks(
1056
+ timing.presentationTime,
1057
+ timing.mediaTimescale,
1058
+ targetTimescale
1059
+ );
1060
+ const duration = scaleAuthoredTicks(
1061
+ BigInt(timing.durationTicks),
1062
+ timing.mediaTimescale,
1063
+ targetTimescale
1064
+ );
1065
+ if (timestamp === null || duration === null || duration <= 0) return null;
1066
+ return { timestamp, duration };
1067
+ }
1068
+
1069
+ // src/cmaf-block-assembler.ts
1070
+ var INT32_MIN2 = -2147483648;
1071
+ var INT32_MAX2 = 2147483647;
1072
+ var _config, _blocks, _pendingFlush, _pendingRecovered, _sequence, _baseTs, _fillFrame, _lastDecodableAudioFrame, _frameDuration, _lastEmittedTs, _lastSourceTs, _sampleReorderWindow, _sampleOrder, _sampleOrderCapacity, _sampleReorderQueue, _recoveredHorizonTs, _sampleOrderStats, _validateH264Keyframes, _keyframeRejectDumpCount, _armedVideo, _lastEmittedSbn, _CmafBlockAssembler_instances, claimSbnEmission_fn, applyVideoKeyframeGate_fn, normalizeVideoKeyframes_fn, withEffectiveVideoKeyframe_fn, dumpRejectedVideoKeyframe_fn, ordersSamples_fn, unwrapTimestamp_fn, emitSample_fn, emitArrivalOrdered_fn, queueSample_fn, releaseHorizon_fn, sampleIsReleasable_fn, dropPreRapSamples_fn, drainSampleReorder_fn, emitQueuedSample_fn, enforceSampleOrderCapacity_fn, emitSampleNow_fn, writeSampleNow_fn, emitAudioGapFillNowBefore_fn, emitPerSample_fn, _dumpCount, _emitCount, _sampleCount, _keyframeCount, _addFrameCount, _recoveredBlockCount, _completeBlockCount, _failBlockCount, _aggregateTimer, startAggregateTimer_fn, dumpEmit_fn, rebase_fn, normalizeSampleData_fn, enqueueRecovered_fn, drainRecoveredUpTo_fn, flushBlock_fn, flushBlockWithFill_fn;
1073
+ var CmafBlockAssembler = class {
1074
+ constructor(config) {
1075
+ __privateAdd(this, _CmafBlockAssembler_instances);
1076
+ __privateAdd(this, _config);
1077
+ __privateAdd(this, _blocks, /* @__PURE__ */ new Map());
1078
+ __privateAdd(this, _pendingFlush, /* @__PURE__ */ new Set());
1079
+ __privateAdd(this, _pendingRecovered, /* @__PURE__ */ new Map());
1080
+ __privateAdd(this, _sequence, 1);
1081
+ __privateAdd(this, _baseTs, -1);
1082
+ __privateAdd(this, _fillFrame);
1083
+ __privateAdd(this, _lastDecodableAudioFrame, null);
1084
+ __privateAdd(this, _frameDuration);
1085
+ __privateAdd(this, _lastEmittedTs, -1);
1086
+ __privateAdd(this, _lastSourceTs, -1);
1087
+ __privateAdd(this, _sampleReorderWindow, 0);
1088
+ __privateAdd(this, _sampleOrder, { mode: "arrival" });
1089
+ __privateAdd(this, _sampleOrderCapacity, 0);
1090
+ __privateAdd(this, _sampleReorderQueue, []);
1091
+ __privateAdd(this, _recoveredHorizonTs, -1);
1092
+ __privateAdd(this, _sampleOrderStats, {
1093
+ staleSamples: 0,
1094
+ duplicateSamples: 0,
1095
+ preRapDeadlineDrops: 0,
1096
+ noRapFlushDrops: 0,
1097
+ forcedReleases: 0
1098
+ });
1099
+ __privateAdd(this, _validateH264Keyframes, false);
1100
+ __privateAdd(this, _keyframeRejectDumpCount, 0);
1101
+ /** Callback: emits a complete moof+mdat CMAF segment */
1102
+ this.onSegment = null;
1103
+ /** Callback: emits a gated/deduped raw sample for callers that already own the MSE timeline. */
1104
+ this.onSample = null;
1105
+ /** Callback: emits an init segment (ftyp+moov) */
1106
+ this.onInitSegment = null;
1107
+ // Video keyframe gate (BLO-3035 layer 3): Chrome's CHUNK_DEMUXER rejects a
1108
+ // moof+mdat whose first sample is non-sync with no prior reference frames
1109
+ // ("CHUNK_DEMUXER_ERROR_APPEND_FAILED: Failed to prepare video sample for
1110
+ // decode") and detaches the SourceBuffer for the rest of the session.
1111
+ // Mid-stream join almost guarantees the first FEC blocks are mid-GOP — all
1112
+ // delta frames. Gate emission until the first block containing an IDR;
1113
+ // within that block, splice samples to start at the IDR index. Audio passes
1114
+ // unconditionally — valid for the codecs supported here (AAC, Opus) where
1115
+ // every frame is independently decodable. SBR-only AAC, USAC, or HE-AAC v2
1116
+ // with PCE re-entry would need a similar gate.
1117
+ __privateAdd(this, _armedVideo, false);
1118
+ // Legacy SBN emission watermark for the old block-buffered path. Direct
1119
+ // source emission is now timestamp-ordered instead; recovered frames are
1120
+ // queued by media timestamp so they can fill gaps without racing ahead of
1121
+ // source frames.
1122
+ __privateAdd(this, _lastEmittedSbn, -1);
1123
+ // [BLO-3035-LAYER4-DIAG] Byte-dump for the first 6 video emits + 1Hz
1124
+ // aggregate counters that survive the whole run. The counters tell us
1125
+ // whether "emits=low" (assembler emits too few segments) or
1126
+ // "addFrame=low" (parser delivers too few frames) — which routes the
1127
+ // root-cause hunt to assembler vs router vs publisher.
1128
+ __privateAdd(this, _dumpCount, 0);
1129
+ __privateAdd(this, _emitCount, 0);
1130
+ __privateAdd(this, _sampleCount, 0);
1131
+ __privateAdd(this, _keyframeCount, 0);
1132
+ __privateAdd(this, _addFrameCount, 0);
1133
+ __privateAdd(this, _recoveredBlockCount, 0);
1134
+ __privateAdd(this, _completeBlockCount, 0);
1135
+ __privateAdd(this, _failBlockCount, 0);
1136
+ __privateAdd(this, _aggregateTimer, null);
1137
+ __privateSet(this, _config, {
1138
+ k: config.k,
1139
+ timescale: config.timescale ?? 1e6,
1140
+ trackId: config.trackId ?? 1,
1141
+ trackType: config.trackType
1142
+ });
1143
+ if (config.fps && config.fps > 0) {
1144
+ __privateSet(this, _frameDuration, Math.round(__privateGet(this, _config).timescale / config.fps));
1145
+ } else if (config.trackType === "audio" && config.sampleRate) {
1146
+ __privateSet(this, _frameDuration, Math.round(__privateGet(this, _config).timescale * 1024 / config.sampleRate));
1147
+ } else {
1148
+ __privateSet(this, _frameDuration, 33333);
1149
+ }
1150
+ if (config.trackType === "video" && config.avcC && config.width && config.height) {
1151
+ __privateSet(this, _fillFrame, generateGreenFillNAL(config.avcC, config.width, config.height));
1152
+ } else {
1153
+ __privateSet(this, _fillFrame, new Uint8Array(0));
1154
+ }
1155
+ const sampleReorderWindow = config.sampleReorderWindow ?? 0;
1156
+ if (!Number.isFinite(sampleReorderWindow) || sampleReorderWindow < 0) {
1157
+ throw new Error("[CmafBlockAssembler] sampleReorderWindow must be finite and non-negative");
1158
+ }
1159
+ if (config.sampleOrder && sampleReorderWindow > 0) {
1160
+ throw new Error("[CmafBlockAssembler] configure sampleOrder or sampleReorderWindow, not both");
1161
+ }
1162
+ __privateSet(this, _sampleReorderWindow, Math.floor(sampleReorderWindow));
1163
+ __privateSet(this, _sampleOrder, config.sampleOrder ?? { mode: "arrival" });
1164
+ if (__privateGet(this, _sampleOrder).mode === "media-window") {
1165
+ const { deliveryWindow, timestampWrapPeriod } = __privateGet(this, _sampleOrder);
1166
+ if (!Number.isSafeInteger(deliveryWindow) || deliveryWindow <= 0) {
1167
+ throw new Error(
1168
+ "[CmafBlockAssembler] media-window deliveryWindow must be a positive safe integer"
1169
+ );
1170
+ }
1171
+ if (timestampWrapPeriod !== void 0 && (!Number.isSafeInteger(timestampWrapPeriod) || timestampWrapPeriod <= deliveryWindow * 2)) {
1172
+ throw new Error(
1173
+ "[CmafBlockAssembler] timestampWrapPeriod must be a safe integer larger than two delivery windows"
1174
+ );
1175
+ }
1176
+ const samplesPerSecond = config.trackType === "audio" && config.sampleRate ? config.sampleRate / 1024 : config.fps;
1177
+ if (!samplesPerSecond || !Number.isFinite(samplesPerSecond) || samplesPerSecond <= 0) {
1178
+ throw new Error(
1179
+ "[CmafBlockAssembler] media-window ordering requires catalog-derived media cadence"
1180
+ );
1181
+ }
1182
+ __privateSet(this, _sampleOrderCapacity, Math.ceil(deliveryWindow * samplesPerSecond / __privateGet(this, _config).timescale) + 1);
1183
+ }
1184
+ __privateSet(this, _validateH264Keyframes, config.trackType === "video" && (!!config.avcC || !config.codec || isH264Codec(config.codec)));
1185
+ if (config.trackType === "video") {
1186
+ console.log(
1187
+ `[L4-KF-CONFIG] validate=${__privateGet(this, _validateH264Keyframes)} codec=${config.codec ?? ""} avcC=${config.avcC?.length ?? 0}`
1188
+ );
1189
+ }
1190
+ this._videoConfig = config.trackType === "video" && config.avcC ? { avcC: config.avcC, width: config.width ?? 0, height: config.height ?? 0 } : null;
1191
+ this._audioConfig = config.trackType === "audio" && config.sampleRate && config.channels ? { sampleRate: config.sampleRate, channels: config.channels, asc: config.asc } : null;
1192
+ }
1193
+ /** Mark video as already synchronized by an external decoder path.
1194
+ * Used by MoQ→multicast MSE continuity when MoQ has already appended a
1195
+ * keyframe to the same SourceBuffer timeline before multicast takeover. */
1196
+ markVideoSynced() {
1197
+ if (__privateGet(this, _config).trackType === "video") __privateSet(this, _armedVideo, true);
1198
+ }
1199
+ get sampleOrderStats() {
1200
+ return { ...__privateGet(this, _sampleOrderStats) };
1201
+ }
1202
+ /** Emit a single frame immediately as a one-sample moof+mdat segment.
1203
+ *
1204
+ * BLO-3035 layer 4 (4b): the prior SBN-grouped buffering scheme stranded
1205
+ * frames whenever a multi-packet frame spanned FEC block boundaries —
1206
+ * intermediate SBNs had packets-but-no-frames and got `completeBlock`
1207
+ * events that landed on empty `#blocks` (→ `pendingFlush` leak), while
1208
+ * the SBN where the multi-packet frame finally completed received the
1209
+ * `addFrame` but its `trackBlock` count never reached K (→ `pendingBlocks`
1210
+ * leak). Result: ~50% of received frames never reached MSE.
1211
+ *
1212
+ * This path now mirrors `addBypassFrame` — emit on arrival, no buffering.
1213
+ * FEC recovery (`addRecoveredBlock`) keeps its SBN-watermark dedup against
1214
+ * the same SBN being re-emitted from two paths. Out-of-order regression
1215
+ * is guarded by the per-frame `lastEmittedTs` check (also enforced in
1216
+ * `#emitPerSample`). The `sbn`/`esi` parameters are kept for the call-site
1217
+ * signature but no longer affect routing. */
1218
+ addFrame(sbn, esi, data, timestamp, keyframe, catalogTrackName, mpuSequenceNumber, packetSequenceNumber, packetSequenceNumbers, repairedPacketSequenceNumbers, authoredTiming, deliveryProvenance) {
1219
+ void sbn;
1220
+ void esi;
1221
+ __privateWrapper(this, _addFrameCount)._++;
1222
+ __privateMethod(this, _CmafBlockAssembler_instances, startAggregateTimer_fn).call(this);
1223
+ if (!__privateMethod(this, _CmafBlockAssembler_instances, ordersSamples_fn).call(this)) __privateMethod(this, _CmafBlockAssembler_instances, drainRecoveredUpTo_fn).call(this, timestamp);
1224
+ __privateMethod(this, _CmafBlockAssembler_instances, emitSample_fn).call(this, data, timestamp, __privateGet(this, _frameDuration), keyframe, true, catalogTrackName, mpuSequenceNumber, packetSequenceNumber, packetSequenceNumbers, repairedPacketSequenceNumbers, authoredTiming, deliveryProvenance);
1225
+ __privateMethod(this, _CmafBlockAssembler_instances, dumpEmit_fn).call(this, "addFrame-direct", [{ data, timestamp, keyframe }]);
1226
+ }
1227
+ /** Mark a block as complete (all K source symbols received or FEC recovery succeeded).
1228
+ * If all frames are already buffered, flushes immediately. Otherwise sets pending-flush. */
1229
+ completeBlock(sbn) {
1230
+ void sbn;
1231
+ __privateWrapper(this, _completeBlockCount)._++;
1232
+ __privateMethod(this, _CmafBlockAssembler_instances, startAggregateTimer_fn).call(this);
1233
+ }
1234
+ /** Handle block timeout — emit whatever frames we have + fill for missing slots. */
1235
+ failBlock(sbn) {
1236
+ __privateWrapper(this, _failBlockCount)._++;
1237
+ __privateMethod(this, _CmafBlockAssembler_instances, startAggregateTimer_fn).call(this);
1238
+ __privateGet(this, _pendingFlush).delete(sbn);
1239
+ const block = __privateGet(this, _blocks).get(sbn);
1240
+ if (!block || block.size === 0) {
1241
+ __privateGet(this, _blocks).delete(sbn);
1242
+ return;
1243
+ }
1244
+ __privateMethod(this, _CmafBlockAssembler_instances, flushBlockWithFill_fn).call(this, sbn);
1245
+ }
1246
+ /** Add all frames from a FEC-recovered block at once and emit immediately. */
1247
+ addRecoveredBlock(sbn, frames) {
1248
+ void sbn;
1249
+ __privateWrapper(this, _recoveredBlockCount)._++;
1250
+ __privateMethod(this, _CmafBlockAssembler_instances, startAggregateTimer_fn).call(this);
1251
+ __privateGet(this, _pendingFlush).delete(sbn);
1252
+ __privateGet(this, _blocks).delete(sbn);
1253
+ if (frames.length === 0) return;
1254
+ const normalized = __privateMethod(this, _CmafBlockAssembler_instances, normalizeVideoKeyframes_fn).call(this, frames);
1255
+ __privateMethod(this, _CmafBlockAssembler_instances, dumpEmit_fn).call(this, "addRecoveredBlock", normalized, sbn);
1256
+ if (__privateMethod(this, _CmafBlockAssembler_instances, ordersSamples_fn).call(this)) {
1257
+ __privateMethod(this, _CmafBlockAssembler_instances, emitPerSample_fn).call(this, normalized, void 0, false);
1258
+ return;
1259
+ }
1260
+ if (__privateGet(this, _lastSourceTs) >= 0) {
1261
+ __privateMethod(this, _CmafBlockAssembler_instances, enqueueRecovered_fn).call(this, normalized);
1262
+ __privateMethod(this, _CmafBlockAssembler_instances, drainRecoveredUpTo_fn).call(this, __privateGet(this, _lastSourceTs));
1263
+ } else {
1264
+ const gated = __privateMethod(this, _CmafBlockAssembler_instances, applyVideoKeyframeGate_fn).call(this, normalized);
1265
+ if (gated) __privateMethod(this, _CmafBlockAssembler_instances, emitPerSample_fn).call(this, gated, void 0, false);
1266
+ }
1267
+ }
1268
+ /** Emit a single frame immediately as a one-sample segment (for oversized packets bypassing FEC). */
1269
+ addBypassFrame(data, timestamp, keyframe, catalogTrackName, mpuSequenceNumber, packetSequenceNumber, packetSequenceNumbers, repairedPacketSequenceNumbers, authoredTiming, deliveryProvenance) {
1270
+ if (!__privateMethod(this, _CmafBlockAssembler_instances, ordersSamples_fn).call(this)) __privateMethod(this, _CmafBlockAssembler_instances, drainRecoveredUpTo_fn).call(this, timestamp);
1271
+ __privateMethod(this, _CmafBlockAssembler_instances, emitSample_fn).call(this, data, timestamp, __privateGet(this, _frameDuration), keyframe, true, catalogTrackName, mpuSequenceNumber, packetSequenceNumber, packetSequenceNumbers, repairedPacketSequenceNumbers, authoredTiming, deliveryProvenance);
1272
+ }
1273
+ /** Build and emit init segment from catalog config. */
1274
+ emitInit() {
1275
+ let init = null;
1276
+ if (this._videoConfig?.avcC) {
1277
+ init = buildVideoInitSegment(
1278
+ this._videoConfig.avcC,
1279
+ this._videoConfig.width,
1280
+ this._videoConfig.height,
1281
+ __privateGet(this, _config).timescale,
1282
+ __privateGet(this, _config).trackId
1283
+ );
1284
+ } else if (this._audioConfig) {
1285
+ init = buildAudioInitSegment(
1286
+ this._audioConfig.sampleRate,
1287
+ this._audioConfig.channels,
1288
+ this._audioConfig.asc,
1289
+ __privateGet(this, _config).timescale,
1290
+ __privateGet(this, _config).trackId
1291
+ );
1292
+ }
1293
+ if (init) this.onInitSegment?.(init);
1294
+ }
1295
+ /** Drain all ordered samples at end-of-stream or before reconfiguration. */
1296
+ flush() {
1297
+ if (__privateMethod(this, _CmafBlockAssembler_instances, ordersSamples_fn).call(this)) {
1298
+ __privateMethod(this, _CmafBlockAssembler_instances, drainSampleReorder_fn).call(this, true);
1299
+ return;
1300
+ }
1301
+ if (__privateGet(this, _pendingRecovered).size === 0) return;
1302
+ const frames = [...__privateGet(this, _pendingRecovered).values()].sort((a, b) => a.timestamp - b.timestamp);
1303
+ __privateGet(this, _pendingRecovered).clear();
1304
+ const gated = __privateMethod(this, _CmafBlockAssembler_instances, applyVideoKeyframeGate_fn).call(this, frames);
1305
+ if (gated) __privateMethod(this, _CmafBlockAssembler_instances, emitPerSample_fn).call(this, gated, void 0, false);
1306
+ else if (__privateGet(this, _config).trackType === "video") {
1307
+ __privateGet(this, _sampleOrderStats).noRapFlushDrops += frames.length;
1308
+ }
1309
+ }
1310
+ /** Drop all queued state and begin a fresh timestamp epoch. */
1311
+ reset() {
1312
+ __privateGet(this, _blocks).clear();
1313
+ __privateGet(this, _pendingFlush).clear();
1314
+ __privateGet(this, _pendingRecovered).clear();
1315
+ __privateSet(this, _sequence, 1);
1316
+ __privateSet(this, _baseTs, -1);
1317
+ __privateSet(this, _lastEmittedTs, -1);
1318
+ __privateSet(this, _lastSourceTs, -1);
1319
+ __privateSet(this, _recoveredHorizonTs, -1);
1320
+ __privateSet(this, _lastDecodableAudioFrame, null);
1321
+ __privateSet(this, _armedVideo, false);
1322
+ __privateSet(this, _lastEmittedSbn, -1);
1323
+ __privateSet(this, _sampleReorderQueue, []);
1324
+ }
1325
+ dispose() {
1326
+ this.reset();
1327
+ this.onSegment = null;
1328
+ this.onSample = null;
1329
+ this.onInitSegment = null;
1330
+ if (__privateGet(this, _aggregateTimer)) {
1331
+ clearInterval(__privateGet(this, _aggregateTimer));
1332
+ __privateSet(this, _aggregateTimer, null);
1333
+ }
1334
+ }
1335
+ };
1336
+ _config = new WeakMap();
1337
+ _blocks = new WeakMap();
1338
+ _pendingFlush = new WeakMap();
1339
+ _pendingRecovered = new WeakMap();
1340
+ _sequence = new WeakMap();
1341
+ _baseTs = new WeakMap();
1342
+ _fillFrame = new WeakMap();
1343
+ _lastDecodableAudioFrame = new WeakMap();
1344
+ _frameDuration = new WeakMap();
1345
+ _lastEmittedTs = new WeakMap();
1346
+ _lastSourceTs = new WeakMap();
1347
+ _sampleReorderWindow = new WeakMap();
1348
+ _sampleOrder = new WeakMap();
1349
+ _sampleOrderCapacity = new WeakMap();
1350
+ _sampleReorderQueue = new WeakMap();
1351
+ _recoveredHorizonTs = new WeakMap();
1352
+ _sampleOrderStats = new WeakMap();
1353
+ _validateH264Keyframes = new WeakMap();
1354
+ _keyframeRejectDumpCount = new WeakMap();
1355
+ _armedVideo = new WeakMap();
1356
+ _lastEmittedSbn = new WeakMap();
1357
+ _CmafBlockAssembler_instances = new WeakSet();
1358
+ /** Attempt to claim emission for `sbn`. Returns true if `sbn` is past
1359
+ * the watermark (and advances it); false if this sbn has already been
1360
+ * claimed or is older (caller should drop). */
1361
+ claimSbnEmission_fn = function(sbn) {
1362
+ if (sbn <= __privateGet(this, _lastEmittedSbn)) return false;
1363
+ __privateSet(this, _lastEmittedSbn, sbn);
1364
+ return true;
1365
+ };
1366
+ /** Truncate `frames` to start at the first keyframe for video tracks before
1367
+ * the first emission. Returns the (possibly spliced) frames, or null to
1368
+ * drop the block entirely. Audio + already-armed video: identity. */
1369
+ applyVideoKeyframeGate_fn = function(frames) {
1370
+ const keyedFrames = __privateMethod(this, _CmafBlockAssembler_instances, normalizeVideoKeyframes_fn).call(this, frames);
1371
+ if (__privateGet(this, _config).trackType !== "video" || __privateGet(this, _armedVideo)) return keyedFrames;
1372
+ const firstKfIdx = keyedFrames.findIndex((f) => f.keyframe);
1373
+ if (firstKfIdx < 0) return null;
1374
+ return firstKfIdx === 0 ? keyedFrames : keyedFrames.slice(firstKfIdx);
1375
+ };
1376
+ normalizeVideoKeyframes_fn = function(frames) {
1377
+ if (__privateGet(this, _config).trackType !== "video" || !__privateGet(this, _validateH264Keyframes)) return frames;
1378
+ return frames.map((frame) => __privateMethod(this, _CmafBlockAssembler_instances, withEffectiveVideoKeyframe_fn).call(this, frame));
1379
+ };
1380
+ withEffectiveVideoKeyframe_fn = function(frame) {
1381
+ if (__privateGet(this, _config).trackType !== "video" || !__privateGet(this, _validateH264Keyframes)) return frame;
1382
+ const keyframe = detectH264Keyframe(frame.data);
1383
+ if (!keyframe) __privateMethod(this, _CmafBlockAssembler_instances, dumpRejectedVideoKeyframe_fn).call(this, frame.data, frame.keyframe);
1384
+ return keyframe === frame.keyframe ? frame : { ...frame, keyframe };
1385
+ };
1386
+ dumpRejectedVideoKeyframe_fn = function(data, metadataKeyframe) {
1387
+ if (__privateGet(this, _keyframeRejectDumpCount) >= 12) return;
1388
+ __privateWrapper(this, _keyframeRejectDumpCount)._++;
1389
+ const sample = splitH264SampleNalUnits(data);
1390
+ const nalTypes = describeH264NalTypes(sample.nals);
1391
+ const classify = classifyH264Keyframe(data);
1392
+ const hex = Array.from(data.subarray(0, Math.min(48, data.length))).map((b) => b.toString(16).padStart(2, "0")).join(" ");
1393
+ console.log(
1394
+ `[L4-KF-GATE] reject#${__privateGet(this, _keyframeRejectDumpCount)} len=${data.length} metadataKf=${metadataKeyframe} classify=${classify} format=${sample.format} nalTypes=[${nalTypes.join(",")}] first48=[${hex}]`
1395
+ );
1396
+ };
1397
+ /** Emit each frame as its own single-sample moof+mdat segment. Matches the
1398
+ * case-20 path (`MmtpToCmaf.wrapVideoSample` → `encodeDataSegment`) byte-
1399
+ * for-byte per frame. Working hypothesis (pending Chromium-source
1400
+ * validation against `media/filters/chunk_demuxer.cc`):
1401
+ * `encodeMultiSampleSegment` blobs are accepted by ChunkDemuxer in this
1402
+ * pipeline but only the first sample renders for live, possibly because
1403
+ * the pipeline expects per-frame moof boundaries. Track in BLO-3035.
1404
+ *
1405
+ * Stale-tfdt defense-in-depth: drops any frame whose timestamp is older
1406
+ * than `#lastEmittedTs`. The SBN watermark already prevents out-of-order
1407
+ * FEC-block emissions, but `addBypassFrame` (oversized MFU / no-FEC path)
1408
+ * doesn't touch the watermark — a bypass frame at t=T followed by a FEC
1409
+ * block whose frames precede T would otherwise inject earlier tfdt and
1410
+ * detach the SourceBuffer. */
1411
+ ordersSamples_fn = function() {
1412
+ return __privateGet(this, _sampleOrder).mode === "media-window" || __privateGet(this, _sampleReorderWindow) > 0;
1413
+ };
1414
+ unwrapTimestamp_fn = function(timestamp) {
1415
+ const wrapPeriod = __privateGet(this, _sampleOrder).mode === "media-window" ? __privateGet(this, _sampleOrder).timestampWrapPeriod : void 0;
1416
+ if (!wrapPeriod) return timestamp;
1417
+ const reference = __privateGet(this, _lastSourceTs) >= 0 ? __privateGet(this, _lastSourceTs) : __privateGet(this, _recoveredHorizonTs) >= 0 ? __privateGet(this, _recoveredHorizonTs) : __privateGet(this, _lastEmittedTs);
1418
+ if (reference < 0) return timestamp;
1419
+ return timestamp + Math.round((reference - timestamp) / wrapPeriod) * wrapPeriod;
1420
+ };
1421
+ emitSample_fn = function(data, timestamp, duration, keyframe, advancesHorizon, catalogTrackName, mpuSequenceNumber, packetSequenceNumber, packetSequenceNumbers, repairedPacketSequenceNumbers, authoredTiming, deliveryProvenance) {
1422
+ const scaledTiming = authoredTiming === void 0 ? null : scaleAuthoredTiming(authoredTiming, __privateGet(this, _config).timescale);
1423
+ if (authoredTiming !== void 0 && scaledTiming === null) return;
1424
+ const authoredTimestamp = scaledTiming?.timestamp ?? timestamp;
1425
+ const authoredDuration = scaledTiming?.duration ?? duration;
1426
+ let compositionTimeOffset;
1427
+ if (authoredTiming !== void 0) {
1428
+ const scaledOffset = scaleAuthoredTicks(
1429
+ authoredTiming.presentationTime - authoredTiming.decodeTime,
1430
+ authoredTiming.mediaTimescale,
1431
+ __privateGet(this, _config).timescale
1432
+ );
1433
+ if (scaledOffset === null) return;
1434
+ const roundedOffset = Math.round(scaledOffset);
1435
+ if (!Number.isSafeInteger(roundedOffset) || roundedOffset < INT32_MIN2 || roundedOffset > INT32_MAX2) return;
1436
+ compositionTimeOffset = roundedOffset;
1437
+ }
1438
+ const unwrappedTimestamp = __privateMethod(this, _CmafBlockAssembler_instances, unwrapTimestamp_fn).call(this, authoredTimestamp);
1439
+ if (unwrappedTimestamp <= __privateGet(this, _lastEmittedTs)) {
1440
+ __privateGet(this, _sampleOrderStats).staleSamples++;
1441
+ return;
1442
+ }
1443
+ const sample = __privateMethod(this, _CmafBlockAssembler_instances, withEffectiveVideoKeyframe_fn).call(this, {
1444
+ data,
1445
+ timestamp: unwrappedTimestamp,
1446
+ duration: authoredDuration,
1447
+ keyframe,
1448
+ ...compositionTimeOffset === void 0 ? {} : { compositionTimeOffset },
1449
+ advancesHorizon,
1450
+ ...authoredTiming === void 0 ? {} : { authoredTiming },
1451
+ ...packetSequenceNumber === void 0 ? {} : { packetSequenceNumber },
1452
+ ...packetSequenceNumbers === void 0 ? {} : { packetSequenceNumbers },
1453
+ ...repairedPacketSequenceNumbers === void 0 ? {} : { repairedPacketSequenceNumbers },
1454
+ ...mpuSequenceNumber === void 0 ? {} : { mpuSequenceNumber },
1455
+ ...catalogTrackName === void 0 ? {} : { catalogTrackName },
1456
+ ...deliveryProvenance === void 0 ? {} : { deliveryProvenance }
1457
+ });
1458
+ if (advancesHorizon && unwrappedTimestamp > __privateGet(this, _lastSourceTs)) {
1459
+ __privateSet(this, _lastSourceTs, unwrappedTimestamp);
1460
+ } else if (!advancesHorizon && unwrappedTimestamp > __privateGet(this, _recoveredHorizonTs)) {
1461
+ __privateSet(this, _recoveredHorizonTs, unwrappedTimestamp);
1462
+ }
1463
+ if (__privateMethod(this, _CmafBlockAssembler_instances, ordersSamples_fn).call(this)) {
1464
+ __privateMethod(this, _CmafBlockAssembler_instances, queueSample_fn).call(this, sample);
1465
+ return;
1466
+ }
1467
+ __privateMethod(this, _CmafBlockAssembler_instances, emitArrivalOrdered_fn).call(this, sample);
1468
+ };
1469
+ emitArrivalOrdered_fn = function(sample) {
1470
+ if (__privateGet(this, _config).trackType === "video" && !__privateGet(this, _armedVideo) && !sample.keyframe) {
1471
+ __privateGet(this, _sampleOrderStats).preRapDeadlineDrops++;
1472
+ return;
1473
+ }
1474
+ __privateMethod(this, _CmafBlockAssembler_instances, emitSampleNow_fn).call(this, sample);
1475
+ };
1476
+ queueSample_fn = function(sample) {
1477
+ if (__privateGet(this, _sampleReorderQueue).some((s) => s.timestamp === sample.timestamp)) {
1478
+ __privateGet(this, _sampleOrderStats).duplicateSamples++;
1479
+ return;
1480
+ }
1481
+ __privateGet(this, _sampleReorderQueue).push(sample);
1482
+ __privateGet(this, _sampleReorderQueue).sort((a, b) => a.timestamp - b.timestamp);
1483
+ __privateMethod(this, _CmafBlockAssembler_instances, drainSampleReorder_fn).call(this, false);
1484
+ __privateMethod(this, _CmafBlockAssembler_instances, enforceSampleOrderCapacity_fn).call(this);
1485
+ };
1486
+ releaseHorizon_fn = function() {
1487
+ return __privateGet(this, _lastSourceTs) >= 0 ? __privateGet(this, _lastSourceTs) : __privateGet(this, _recoveredHorizonTs);
1488
+ };
1489
+ sampleIsReleasable_fn = function(sample, flushAll) {
1490
+ if (flushAll) return true;
1491
+ if (__privateGet(this, _sampleOrder).mode === "media-window") {
1492
+ const horizon = __privateMethod(this, _CmafBlockAssembler_instances, releaseHorizon_fn).call(this);
1493
+ return horizon >= 0 && sample.timestamp < horizon - __privateGet(this, _sampleOrder).deliveryWindow;
1494
+ }
1495
+ return __privateGet(this, _sampleReorderQueue).length > __privateGet(this, _sampleReorderWindow);
1496
+ };
1497
+ dropPreRapSamples_fn = function(flushAll) {
1498
+ if (__privateGet(this, _config).trackType !== "video" || __privateGet(this, _armedVideo)) return false;
1499
+ const firstRap = __privateGet(this, _sampleReorderQueue).findIndex(
1500
+ (sample) => sample.keyframe && __privateMethod(this, _CmafBlockAssembler_instances, sampleIsReleasable_fn).call(this, sample, flushAll)
1501
+ );
1502
+ if (firstRap >= 0) {
1503
+ if (firstRap > 0) {
1504
+ __privateGet(this, _sampleOrderStats).preRapDeadlineDrops += firstRap;
1505
+ __privateGet(this, _sampleReorderQueue).splice(0, firstRap);
1506
+ }
1507
+ return false;
1508
+ }
1509
+ let dropped = 0;
1510
+ while (__privateGet(this, _sampleReorderQueue)[0] && __privateMethod(this, _CmafBlockAssembler_instances, sampleIsReleasable_fn).call(this, __privateGet(this, _sampleReorderQueue)[0], flushAll)) {
1511
+ __privateGet(this, _sampleReorderQueue).shift();
1512
+ dropped++;
1513
+ }
1514
+ if (flushAll) __privateGet(this, _sampleOrderStats).noRapFlushDrops += dropped;
1515
+ else __privateGet(this, _sampleOrderStats).preRapDeadlineDrops += dropped;
1516
+ return dropped > 0;
1517
+ };
1518
+ drainSampleReorder_fn = function(flushAll) {
1519
+ while (__privateGet(this, _sampleReorderQueue).length > 0) {
1520
+ if (__privateMethod(this, _CmafBlockAssembler_instances, dropPreRapSamples_fn).call(this, flushAll) && __privateGet(this, _sampleReorderQueue).length === 0) return;
1521
+ const sample = __privateGet(this, _sampleReorderQueue)[0];
1522
+ if (!sample || !__privateMethod(this, _CmafBlockAssembler_instances, sampleIsReleasable_fn).call(this, sample, flushAll)) return;
1523
+ __privateGet(this, _sampleReorderQueue).shift();
1524
+ __privateMethod(this, _CmafBlockAssembler_instances, emitQueuedSample_fn).call(this, sample);
1525
+ }
1526
+ };
1527
+ emitQueuedSample_fn = function(sample) {
1528
+ const next = __privateGet(this, _sampleReorderQueue).find((s) => s.timestamp > sample.timestamp);
1529
+ const duration = sample.authoredTiming ? sample.duration : next ? next.timestamp - sample.timestamp : sample.duration;
1530
+ __privateMethod(this, _CmafBlockAssembler_instances, emitSampleNow_fn).call(this, {
1531
+ ...sample,
1532
+ duration: duration > 0 ? duration : sample.authoredTiming ? sample.duration : __privateGet(this, _frameDuration)
1533
+ });
1534
+ };
1535
+ enforceSampleOrderCapacity_fn = function() {
1536
+ if (__privateGet(this, _sampleOrder).mode !== "media-window") return;
1537
+ while (__privateGet(this, _sampleReorderQueue).length > __privateGet(this, _sampleOrderCapacity)) {
1538
+ const sample = __privateGet(this, _sampleReorderQueue).shift();
1539
+ if (!sample) return;
1540
+ __privateGet(this, _sampleOrderStats).forcedReleases++;
1541
+ console.warn(
1542
+ `[CmafBlockAssembler] ${__privateGet(this, _config).trackType} media-window queue exceeded ${__privateGet(this, _sampleOrderCapacity)} samples; force-releasing timestamp=${sample.timestamp}`
1543
+ );
1544
+ if (__privateGet(this, _config).trackType === "video" && !__privateGet(this, _armedVideo) && !sample.keyframe) {
1545
+ __privateGet(this, _sampleOrderStats).preRapDeadlineDrops++;
1546
+ continue;
1547
+ }
1548
+ __privateMethod(this, _CmafBlockAssembler_instances, emitQueuedSample_fn).call(this, sample);
1549
+ }
1550
+ };
1551
+ emitSampleNow_fn = function(sample) {
1552
+ if (sample.timestamp <= __privateGet(this, _lastEmittedTs)) {
1553
+ __privateGet(this, _sampleOrderStats).staleSamples++;
1554
+ return;
1555
+ }
1556
+ __privateMethod(this, _CmafBlockAssembler_instances, emitAudioGapFillNowBefore_fn).call(this, sample.timestamp);
1557
+ __privateMethod(this, _CmafBlockAssembler_instances, writeSampleNow_fn).call(this, sample, true);
1558
+ };
1559
+ writeSampleNow_fn = function(sample, rememberAudio) {
1560
+ const { timestamp, duration, keyframe } = sample;
1561
+ __privateSet(this, _lastEmittedTs, timestamp);
1562
+ if (__privateGet(this, _config).trackType === "video" && keyframe) __privateSet(this, _armedVideo, true);
1563
+ const data = __privateMethod(this, _CmafBlockAssembler_instances, normalizeSampleData_fn).call(this, sample.data);
1564
+ if (__privateGet(this, _config).trackType === "audio" && rememberAudio && data.length > 0) {
1565
+ __privateSet(this, _lastDecodableAudioFrame, data.slice());
1566
+ }
1567
+ if (this.onSample) {
1568
+ this.onSample(data === sample.data ? sample : { ...sample, data });
1569
+ } else {
1570
+ const baseTime = __privateMethod(this, _CmafBlockAssembler_instances, rebase_fn).call(this, timestamp);
1571
+ const segment = encodeDataSegment(
1572
+ data,
1573
+ baseTime,
1574
+ duration,
1575
+ keyframe,
1576
+ __privateWrapper(this, _sequence)._++,
1577
+ __privateGet(this, _config).trackId,
1578
+ sample.compositionTimeOffset
1579
+ );
1580
+ this.onSegment?.(segment);
1581
+ }
1582
+ };
1583
+ emitAudioGapFillNowBefore_fn = function(timestamp) {
1584
+ if (__privateGet(this, _config).trackType !== "audio" || __privateGet(this, _lastEmittedTs) < 0 || __privateGet(this, _lastDecodableAudioFrame) === null) return;
1585
+ const gap = timestamp - __privateGet(this, _lastEmittedTs);
1586
+ if (gap <= __privateGet(this, _frameDuration) * 1.5) return;
1587
+ const missingFrames = Math.max(0, Math.round(gap / __privateGet(this, _frameDuration)) - 1);
1588
+ for (let i = 0; i < missingFrames; i++) {
1589
+ const fillTs = __privateGet(this, _lastEmittedTs) + __privateGet(this, _frameDuration);
1590
+ __privateMethod(this, _CmafBlockAssembler_instances, writeSampleNow_fn).call(this, {
1591
+ data: __privateGet(this, _lastDecodableAudioFrame).slice(),
1592
+ timestamp: fillTs,
1593
+ duration: __privateGet(this, _frameDuration),
1594
+ keyframe: true
1595
+ }, false);
1596
+ }
1597
+ };
1598
+ emitPerSample_fn = function(frames, audioDurationOverride, advancesHorizon = false) {
1599
+ for (let i = 0; i < frames.length; i++) {
1600
+ const f = frames[i];
1601
+ let duration;
1602
+ if (__privateGet(this, _config).trackType === "audio") {
1603
+ duration = audioDurationOverride ?? __privateGet(this, _frameDuration);
1604
+ } else if (i < frames.length - 1) {
1605
+ duration = frames[i + 1].timestamp - f.timestamp;
1606
+ } else if (i > 0) {
1607
+ duration = f.timestamp - frames[i - 1].timestamp;
1608
+ } else {
1609
+ duration = audioDurationOverride ?? __privateGet(this, _frameDuration);
1610
+ }
1611
+ if (duration <= 0) duration = audioDurationOverride ?? __privateGet(this, _frameDuration);
1612
+ __privateMethod(this, _CmafBlockAssembler_instances, emitSample_fn).call(this, f.data, f.timestamp, duration, f.keyframe, advancesHorizon, f.catalogTrackName, f.mpuSequenceNumber, f.packetSequenceNumber, f.packetSequenceNumbers, f.repairedPacketSequenceNumbers, f.authoredTiming, f.deliveryProvenance);
1613
+ }
1614
+ };
1615
+ _dumpCount = new WeakMap();
1616
+ _emitCount = new WeakMap();
1617
+ _sampleCount = new WeakMap();
1618
+ _keyframeCount = new WeakMap();
1619
+ _addFrameCount = new WeakMap();
1620
+ _recoveredBlockCount = new WeakMap();
1621
+ _completeBlockCount = new WeakMap();
1622
+ _failBlockCount = new WeakMap();
1623
+ _aggregateTimer = new WeakMap();
1624
+ startAggregateTimer_fn = function() {
1625
+ if (__privateGet(this, _aggregateTimer)) return;
1626
+ __privateSet(this, _aggregateTimer, setInterval(() => {
1627
+ console.log(
1628
+ `[L4-AGG-${__privateGet(this, _config).trackType}] emits=${__privateGet(this, _emitCount)} samples=${__privateGet(this, _sampleCount)} kf=${__privateGet(this, _keyframeCount)} addFrame=${__privateGet(this, _addFrameCount)} recovered=${__privateGet(this, _recoveredBlockCount)} complete=${__privateGet(this, _completeBlockCount)} fail=${__privateGet(this, _failBlockCount)} pendingBlocks=${__privateGet(this, _blocks).size} pendingFlushes=${__privateGet(this, _pendingFlush).size} armedVideo=${__privateGet(this, _armedVideo)}`
1629
+ );
1630
+ __privateSet(this, _emitCount, 0);
1631
+ __privateSet(this, _sampleCount, 0);
1632
+ __privateSet(this, _keyframeCount, 0);
1633
+ __privateSet(this, _addFrameCount, 0);
1634
+ __privateSet(this, _recoveredBlockCount, 0);
1635
+ __privateSet(this, _completeBlockCount, 0);
1636
+ __privateSet(this, _failBlockCount, 0);
1637
+ }, 1e3));
1638
+ };
1639
+ dumpEmit_fn = function(path, samples, sbn) {
1640
+ __privateWrapper(this, _emitCount)._++;
1641
+ __privateSet(this, _sampleCount, __privateGet(this, _sampleCount) + samples.length);
1642
+ __privateSet(this, _keyframeCount, __privateGet(this, _keyframeCount) + samples.filter((s) => s.keyframe).length);
1643
+ const anyKf = __privateGet(this, _config).trackType === "video" && samples.some((s) => s.keyframe);
1644
+ if (__privateGet(this, _config).trackType !== "video" || __privateGet(this, _dumpCount) >= 6 && !anyKf) return;
1645
+ __privateWrapper(this, _dumpCount)._++;
1646
+ const s0 = samples[0];
1647
+ if (!s0) return;
1648
+ const d = s0.data;
1649
+ const hex = Array.from(d.subarray(0, Math.min(48, d.length))).map((b) => b.toString(16).padStart(2, "0")).join(" ");
1650
+ let h = 5381;
1651
+ for (let i = 0; i < d.length; i++) h = h * 33 + d[i] | 0;
1652
+ const hash = (h >>> 0).toString(16).padStart(8, "0");
1653
+ const ts0 = s0.timestamp ?? -1;
1654
+ const tsN = samples[samples.length - 1]?.timestamp ?? -1;
1655
+ console.log(
1656
+ `[L4-DIAG] EMIT#${__privateGet(this, _dumpCount)} path=${path}${sbn !== void 0 ? ` sbn=${sbn}` : ""} samples=${samples.length} s0.kf=${s0.keyframe} s0.len=${d.length} ts0=${ts0} tsN=${tsN} dur=${tsN - ts0} hash=${hash} first48=[${hex}]`
1657
+ );
1658
+ };
1659
+ // ── Private ──
1660
+ /** Rebase an absolute timestamp to relative media time (starting near 0). */
1661
+ rebase_fn = function(timestamp) {
1662
+ if (__privateGet(this, _baseTs) < 0) __privateSet(this, _baseTs, timestamp);
1663
+ return timestamp - __privateGet(this, _baseTs);
1664
+ };
1665
+ normalizeSampleData_fn = function(data) {
1666
+ return __privateGet(this, _config).trackType === "audio" ? normalizeAacSampleForCmaf(data) : data;
1667
+ };
1668
+ enqueueRecovered_fn = function(frames) {
1669
+ for (const frame of frames) {
1670
+ if (__privateGet(this, _lastEmittedTs) >= 0 && frame.timestamp <= __privateGet(this, _lastEmittedTs)) {
1671
+ __privateGet(this, _sampleOrderStats).staleSamples++;
1672
+ continue;
1673
+ }
1674
+ if (__privateGet(this, _pendingRecovered).has(frame.timestamp)) {
1675
+ __privateGet(this, _sampleOrderStats).duplicateSamples++;
1676
+ continue;
1677
+ }
1678
+ __privateGet(this, _pendingRecovered).set(frame.timestamp, frame);
1679
+ }
1680
+ };
1681
+ drainRecoveredUpTo_fn = function(horizonTs) {
1682
+ if (__privateGet(this, _pendingRecovered).size === 0) return;
1683
+ const ready = [...__privateGet(this, _pendingRecovered).values()].filter((frame) => frame.timestamp <= horizonTs).sort((a, b) => a.timestamp - b.timestamp);
1684
+ for (const frame of ready) {
1685
+ __privateGet(this, _pendingRecovered).delete(frame.timestamp);
1686
+ __privateMethod(this, _CmafBlockAssembler_instances, emitSample_fn).call(this, frame.data, frame.timestamp, __privateGet(this, _frameDuration), frame.keyframe, false, frame.catalogTrackName, frame.mpuSequenceNumber, frame.packetSequenceNumber, frame.packetSequenceNumbers, frame.repairedPacketSequenceNumbers, frame.authoredTiming, frame.deliveryProvenance);
1687
+ __privateMethod(this, _CmafBlockAssembler_instances, dumpEmit_fn).call(this, "recovered-drain", [frame]);
1688
+ }
1689
+ };
1690
+ /** Flush a block's buffered frames as a multi-sample CMAF segment. */
1691
+ flushBlock_fn = function(sbn) {
1692
+ const block = __privateGet(this, _blocks).get(sbn);
1693
+ if (!block || block.size === 0) {
1694
+ __privateGet(this, _blocks).delete(sbn);
1695
+ return;
1696
+ }
1697
+ const entries = [...block.entries()].sort((a, b) => a[0] - b[0]);
1698
+ const sortedFrames = entries.map(([, f]) => f);
1699
+ __privateGet(this, _blocks).delete(sbn);
1700
+ if (!__privateMethod(this, _CmafBlockAssembler_instances, claimSbnEmission_fn).call(this, sbn)) return;
1701
+ const frames = __privateMethod(this, _CmafBlockAssembler_instances, applyVideoKeyframeGate_fn).call(this, sortedFrames);
1702
+ if (!frames) return;
1703
+ __privateMethod(this, _CmafBlockAssembler_instances, dumpEmit_fn).call(this, "flushBlock", frames, sbn);
1704
+ __privateMethod(this, _CmafBlockAssembler_instances, emitPerSample_fn).call(this, frames);
1705
+ };
1706
+ /** Flush a block with fill frames for missing ESI slots (FEC timeout path). */
1707
+ flushBlockWithFill_fn = function(sbn) {
1708
+ const block = __privateGet(this, _blocks).get(sbn);
1709
+ if (!block) return;
1710
+ const k = __privateGet(this, _config).k;
1711
+ const isVideo = __privateGet(this, _config).trackType === "video";
1712
+ const firstAudioFrame = !isVideo ? [...block.values()].sort((a, b) => a.timestamp - b.timestamp)[0]?.data : void 0;
1713
+ const audioConcealmentFrame = __privateGet(this, _lastDecodableAudioFrame) ?? firstAudioFrame;
1714
+ const allFrames = [];
1715
+ let lastRealTs = -1;
1716
+ let firstRealTs = -1;
1717
+ for (const [, f] of block) {
1718
+ if (firstRealTs < 0 || f.timestamp < firstRealTs) firstRealTs = f.timestamp;
1719
+ if (f.timestamp > lastRealTs) lastRealTs = f.timestamp;
1720
+ }
1721
+ const estimatedBlockDuration = block.size > 1 ? (lastRealTs - firstRealTs) / (block.size - 1) * k : __privateGet(this, _frameDuration) * k;
1722
+ for (let esi = 0; esi < k; esi++) {
1723
+ const real = block.get(esi);
1724
+ if (real) {
1725
+ allFrames.push(real);
1726
+ } else {
1727
+ const interpolatedTs = firstRealTs >= 0 ? firstRealTs + Math.round(esi * estimatedBlockDuration / k) : __privateGet(this, _lastEmittedTs) >= 0 ? __privateGet(this, _lastEmittedTs) + __privateGet(this, _frameDuration) * (esi + 1) : 0;
1728
+ allFrames.push({
1729
+ // A synthesized AAC access unit is not portable across every
1730
+ // AudioSpecificConfig. Repeat known-good encoded audio instead;
1731
+ // if this is the first block, use its earliest received sample.
1732
+ data: isVideo ? __privateGet(this, _fillFrame) : audioConcealmentFrame?.slice() ?? new Uint8Array(0),
1733
+ timestamp: interpolatedTs,
1734
+ // Video: first fill is keyframe (IDR). Audio: all fill marked keyframe.
1735
+ keyframe: isVideo ? !block.has(0) && esi === 0 : true
1736
+ });
1737
+ }
1738
+ }
1739
+ __privateGet(this, _blocks).delete(sbn);
1740
+ if (!__privateMethod(this, _CmafBlockAssembler_instances, claimSbnEmission_fn).call(this, sbn)) return;
1741
+ const gatedFrames = __privateMethod(this, _CmafBlockAssembler_instances, applyVideoKeyframeGate_fn).call(this, allFrames);
1742
+ if (!gatedFrames) return;
1743
+ __privateMethod(this, _CmafBlockAssembler_instances, emitPerSample_fn).call(this, gatedFrames);
1744
+ };
1745
+ function isH264Codec(codec) {
1746
+ const c = codec?.toLowerCase();
1747
+ return c?.startsWith("avc1") === true || c?.startsWith("avc3") === true;
1748
+ }
1749
+ function describeH264NalTypes(nals) {
1750
+ return nals.slice(0, 16).map((nal) => nal[0] !== void 0 ? nal[0] & 31 : -1);
1751
+ }
1752
+ export {
1753
+ CmafBlockAssembler
1754
+ };
1755
+ //# sourceMappingURL=cmaf-block-assembler.js.map