@osmo.inc/cli 0.1.15

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 (949) hide show
  1. package/DEPLOY.md +87 -0
  2. package/README.md +243 -0
  3. package/RELEASE.md +164 -0
  4. package/SETUP.md +60 -0
  5. package/THIRD_PARTY_NOTICES.md +18 -0
  6. package/bin/osmo.mjs +12 -0
  7. package/dist/osmo.js +7817 -0
  8. package/node_modules/@esbuild/darwin-arm64/README.md +3 -0
  9. package/node_modules/@esbuild/darwin-arm64/bin/esbuild +0 -0
  10. package/node_modules/@esbuild/darwin-arm64/package.json +20 -0
  11. package/node_modules/esbuild/LICENSE.md +21 -0
  12. package/node_modules/esbuild/README.md +3 -0
  13. package/node_modules/esbuild/bin/esbuild +223 -0
  14. package/node_modules/esbuild/install.js +289 -0
  15. package/node_modules/esbuild/lib/main.d.ts +716 -0
  16. package/node_modules/esbuild/lib/main.js +2532 -0
  17. package/node_modules/esbuild/package.json +49 -0
  18. package/node_modules/fflate/LICENSE +21 -0
  19. package/node_modules/fflate/esm/index.mjs +2710 -0
  20. package/node_modules/fflate/package.json +128 -0
  21. package/node_modules/typescript/LICENSE.txt +55 -0
  22. package/node_modules/typescript/ThirdPartyNoticeText.txt +193 -0
  23. package/node_modules/typescript/lib/lib.d.ts +22 -0
  24. package/node_modules/typescript/lib/lib.decorators.d.ts +384 -0
  25. package/node_modules/typescript/lib/lib.decorators.legacy.d.ts +22 -0
  26. package/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +41 -0
  27. package/node_modules/typescript/lib/lib.dom.d.ts +39429 -0
  28. package/node_modules/typescript/lib/lib.dom.iterable.d.ts +571 -0
  29. package/node_modules/typescript/lib/lib.es2015.collection.d.ts +147 -0
  30. package/node_modules/typescript/lib/lib.es2015.core.d.ts +597 -0
  31. package/node_modules/typescript/lib/lib.es2015.d.ts +28 -0
  32. package/node_modules/typescript/lib/lib.es2015.generator.d.ts +77 -0
  33. package/node_modules/typescript/lib/lib.es2015.iterable.d.ts +605 -0
  34. package/node_modules/typescript/lib/lib.es2015.promise.d.ts +81 -0
  35. package/node_modules/typescript/lib/lib.es2015.proxy.d.ts +128 -0
  36. package/node_modules/typescript/lib/lib.es2015.reflect.d.ts +144 -0
  37. package/node_modules/typescript/lib/lib.es2015.symbol.d.ts +46 -0
  38. package/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +326 -0
  39. package/node_modules/typescript/lib/lib.es2016.array.include.d.ts +116 -0
  40. package/node_modules/typescript/lib/lib.es2016.d.ts +21 -0
  41. package/node_modules/typescript/lib/lib.es2016.full.d.ts +23 -0
  42. package/node_modules/typescript/lib/lib.es2016.intl.d.ts +31 -0
  43. package/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +21 -0
  44. package/node_modules/typescript/lib/lib.es2017.d.ts +26 -0
  45. package/node_modules/typescript/lib/lib.es2017.date.d.ts +31 -0
  46. package/node_modules/typescript/lib/lib.es2017.full.d.ts +23 -0
  47. package/node_modules/typescript/lib/lib.es2017.intl.d.ts +44 -0
  48. package/node_modules/typescript/lib/lib.es2017.object.d.ts +49 -0
  49. package/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +135 -0
  50. package/node_modules/typescript/lib/lib.es2017.string.d.ts +45 -0
  51. package/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +53 -0
  52. package/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +77 -0
  53. package/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +53 -0
  54. package/node_modules/typescript/lib/lib.es2018.d.ts +24 -0
  55. package/node_modules/typescript/lib/lib.es2018.full.d.ts +24 -0
  56. package/node_modules/typescript/lib/lib.es2018.intl.d.ts +83 -0
  57. package/node_modules/typescript/lib/lib.es2018.promise.d.ts +30 -0
  58. package/node_modules/typescript/lib/lib.es2018.regexp.d.ts +37 -0
  59. package/node_modules/typescript/lib/lib.es2019.array.d.ts +79 -0
  60. package/node_modules/typescript/lib/lib.es2019.d.ts +24 -0
  61. package/node_modules/typescript/lib/lib.es2019.full.d.ts +24 -0
  62. package/node_modules/typescript/lib/lib.es2019.intl.d.ts +23 -0
  63. package/node_modules/typescript/lib/lib.es2019.object.d.ts +33 -0
  64. package/node_modules/typescript/lib/lib.es2019.string.d.ts +37 -0
  65. package/node_modules/typescript/lib/lib.es2019.symbol.d.ts +24 -0
  66. package/node_modules/typescript/lib/lib.es2020.bigint.d.ts +765 -0
  67. package/node_modules/typescript/lib/lib.es2020.d.ts +27 -0
  68. package/node_modules/typescript/lib/lib.es2020.date.d.ts +42 -0
  69. package/node_modules/typescript/lib/lib.es2020.full.d.ts +24 -0
  70. package/node_modules/typescript/lib/lib.es2020.intl.d.ts +474 -0
  71. package/node_modules/typescript/lib/lib.es2020.number.d.ts +28 -0
  72. package/node_modules/typescript/lib/lib.es2020.promise.d.ts +47 -0
  73. package/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +99 -0
  74. package/node_modules/typescript/lib/lib.es2020.string.d.ts +44 -0
  75. package/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +41 -0
  76. package/node_modules/typescript/lib/lib.es2021.d.ts +23 -0
  77. package/node_modules/typescript/lib/lib.es2021.full.d.ts +24 -0
  78. package/node_modules/typescript/lib/lib.es2021.intl.d.ts +166 -0
  79. package/node_modules/typescript/lib/lib.es2021.promise.d.ts +48 -0
  80. package/node_modules/typescript/lib/lib.es2021.string.d.ts +33 -0
  81. package/node_modules/typescript/lib/lib.es2021.weakref.d.ts +78 -0
  82. package/node_modules/typescript/lib/lib.es2022.array.d.ts +121 -0
  83. package/node_modules/typescript/lib/lib.es2022.d.ts +25 -0
  84. package/node_modules/typescript/lib/lib.es2022.error.d.ts +75 -0
  85. package/node_modules/typescript/lib/lib.es2022.full.d.ts +24 -0
  86. package/node_modules/typescript/lib/lib.es2022.intl.d.ts +145 -0
  87. package/node_modules/typescript/lib/lib.es2022.object.d.ts +26 -0
  88. package/node_modules/typescript/lib/lib.es2022.regexp.d.ts +39 -0
  89. package/node_modules/typescript/lib/lib.es2022.string.d.ts +25 -0
  90. package/node_modules/typescript/lib/lib.es2023.array.d.ts +924 -0
  91. package/node_modules/typescript/lib/lib.es2023.collection.d.ts +21 -0
  92. package/node_modules/typescript/lib/lib.es2023.d.ts +22 -0
  93. package/node_modules/typescript/lib/lib.es2023.full.d.ts +24 -0
  94. package/node_modules/typescript/lib/lib.es2023.intl.d.ts +56 -0
  95. package/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +65 -0
  96. package/node_modules/typescript/lib/lib.es2024.collection.d.ts +29 -0
  97. package/node_modules/typescript/lib/lib.es2024.d.ts +26 -0
  98. package/node_modules/typescript/lib/lib.es2024.full.d.ts +24 -0
  99. package/node_modules/typescript/lib/lib.es2024.object.d.ts +29 -0
  100. package/node_modules/typescript/lib/lib.es2024.promise.d.ts +35 -0
  101. package/node_modules/typescript/lib/lib.es2024.regexp.d.ts +25 -0
  102. package/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +68 -0
  103. package/node_modules/typescript/lib/lib.es2024.string.d.ts +29 -0
  104. package/node_modules/typescript/lib/lib.es5.d.ts +4601 -0
  105. package/node_modules/typescript/lib/lib.es6.d.ts +23 -0
  106. package/node_modules/typescript/lib/lib.esnext.array.d.ts +35 -0
  107. package/node_modules/typescript/lib/lib.esnext.collection.d.ts +96 -0
  108. package/node_modules/typescript/lib/lib.esnext.d.ts +29 -0
  109. package/node_modules/typescript/lib/lib.esnext.decorators.d.ts +28 -0
  110. package/node_modules/typescript/lib/lib.esnext.disposable.d.ts +193 -0
  111. package/node_modules/typescript/lib/lib.esnext.error.d.ts +24 -0
  112. package/node_modules/typescript/lib/lib.esnext.float16.d.ts +445 -0
  113. package/node_modules/typescript/lib/lib.esnext.full.d.ts +24 -0
  114. package/node_modules/typescript/lib/lib.esnext.intl.d.ts +21 -0
  115. package/node_modules/typescript/lib/lib.esnext.iterator.d.ts +148 -0
  116. package/node_modules/typescript/lib/lib.esnext.promise.d.ts +34 -0
  117. package/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +25 -0
  118. package/node_modules/typescript/lib/lib.scripthost.d.ts +322 -0
  119. package/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +41 -0
  120. package/node_modules/typescript/lib/lib.webworker.d.ts +13150 -0
  121. package/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +23 -0
  122. package/node_modules/typescript/lib/lib.webworker.iterable.d.ts +340 -0
  123. package/node_modules/typescript/lib/typescript.js +382 -0
  124. package/node_modules/typescript/package.json +57 -0
  125. package/package.json +54 -0
  126. package/release.json +136 -0
  127. package/runtime/apps/native/tools/compile.mjs +217 -0
  128. package/runtime/packages/scene/scripts/validate-strict.mjs +246 -0
  129. package/runtime/packages/scene/src/clip.d.mts +14 -0
  130. package/runtime/packages/scene/src/clip.mjs +15 -0
  131. package/runtime/packages/scene/src/color-value.d.mts +5 -0
  132. package/runtime/packages/scene/src/color-value.mjs +19 -0
  133. package/runtime/packages/scene/src/color.ts +1 -0
  134. package/runtime/packages/scene/src/effects.ts +213 -0
  135. package/runtime/packages/scene/src/elements.ts +491 -0
  136. package/runtime/packages/scene/src/evaluate.ts +919 -0
  137. package/runtime/packages/scene/src/index.ts +69 -0
  138. package/runtime/packages/scene/src/jsx-runtime.ts +73 -0
  139. package/runtime/packages/scene/src/knob-schema.ts +115 -0
  140. package/runtime/packages/scene/src/knobs.ts +118 -0
  141. package/runtime/packages/scene/src/mask.d.mts +6 -0
  142. package/runtime/packages/scene/src/mask.mjs +17 -0
  143. package/runtime/packages/scene/src/metadata.d.mts +23 -0
  144. package/runtime/packages/scene/src/metadata.mjs +44 -0
  145. package/runtime/packages/scene/src/motion-sampling.d.mts +2 -0
  146. package/runtime/packages/scene/src/motion-sampling.mjs +50 -0
  147. package/runtime/packages/scene/src/motion.ts +121 -0
  148. package/runtime/packages/scene/src/shader.ts +57 -0
  149. package/src/resource-examples/example-image/landscape.svg +7 -0
  150. package/src/resource-examples/example-image/resource.json +8 -0
  151. package/src/resource-examples/example-model/gem.glb +0 -0
  152. package/src/resource-examples/example-model/preview.svg +1 -0
  153. package/src/resource-examples/example-model/resource.json +7 -0
  154. package/src/resource-examples/example-scene/resource.json +1 -0
  155. package/src/resource-examples/example-scene/scene.tsx +8 -0
  156. package/src/resource-examples/example-shader/effect.wgsl +7 -0
  157. package/src/resource-examples/example-shader/preview.svg +1 -0
  158. package/src/resource-examples/example-shader/resource.json +27 -0
  159. package/src/resource-examples/example-shader/tint.wgsl +7 -0
  160. package/src/resource-examples/example-video/ambient.mp4 +0 -0
  161. package/src/resource-examples/example-video/resource.json +9 -0
  162. package/src/starter/scene.tsx +20 -0
  163. package/studio/index.html +2 -0
  164. package/studio/public/check-circle-filled.svg +3 -0
  165. package/studio/public/comment-cursor/active-outer.svg +3 -0
  166. package/studio/public/comment-cursor/default.svg +6 -0
  167. package/studio/public/osmo-studio-logo.svg +12 -0
  168. package/studio/public/pencil-simple.svg +5 -0
  169. package/studio/src/active-outer-TVYUEURE.svg +3 -0
  170. package/studio/src/app.css +4 -0
  171. package/studio/src/app.js +705 -0
  172. package/studio/src/default-6CTRH4V5.svg +6 -0
  173. package/studio/src/engine_bg.wasm +0 -0
  174. package/studio/src/inter-cyrillic-ext-wght-normal-IYF56FF6.woff2 +0 -0
  175. package/studio/src/inter-cyrillic-wght-normal-JEOLYBOO.woff2 +0 -0
  176. package/studio/src/inter-greek-ext-wght-normal-EOVOK2B5.woff2 +0 -0
  177. package/studio/src/inter-greek-wght-normal-IRE366VL.woff2 +0 -0
  178. package/studio/src/inter-latin-ext-wght-normal-HA22NDSG.woff2 +0 -0
  179. package/studio/src/inter-latin-wght-normal-NRMW37G5.woff2 +0 -0
  180. package/studio/src/inter-vietnamese-wght-normal-CE5GGD3W.woff2 +0 -0
  181. package/studio/src/osmo-studio-logo-D5R2V77B.svg +12 -0
  182. package/third-party/cargo/adler2@2.0.1/Cargo.toml +91 -0
  183. package/third-party/cargo/adler2@2.0.1/LICENSE-0BSD +12 -0
  184. package/third-party/cargo/adler2@2.0.1/LICENSE-APACHE +201 -0
  185. package/third-party/cargo/adler2@2.0.1/LICENSE-MIT +23 -0
  186. package/third-party/cargo/allocator-api2@0.2.21/Cargo.toml +48 -0
  187. package/third-party/cargo/allocator-api2@0.2.21/LICENSE-APACHE +176 -0
  188. package/third-party/cargo/allocator-api2@0.2.21/LICENSE-MIT +23 -0
  189. package/third-party/cargo/arrayref@0.3.9/Cargo.toml +23 -0
  190. package/third-party/cargo/arrayref@0.3.9/LICENSE +26 -0
  191. package/third-party/cargo/arrayvec@0.7.8/Cargo.toml +112 -0
  192. package/third-party/cargo/arrayvec@0.7.8/LICENSE-APACHE +201 -0
  193. package/third-party/cargo/arrayvec@0.7.8/LICENSE-MIT +25 -0
  194. package/third-party/cargo/ascii@1.1.0/Cargo.toml +41 -0
  195. package/third-party/cargo/ascii@1.1.0/LICENSE-APACHE +201 -0
  196. package/third-party/cargo/ascii@1.1.0/LICENSE-MIT +22 -0
  197. package/third-party/cargo/ash@0.38.0+1.3.281/Cargo.toml +66 -0
  198. package/third-party/cargo/ash@0.38.0+1.3.281/LICENSE-APACHE +67 -0
  199. package/third-party/cargo/ash@0.38.0+1.3.281/LICENSE-MIT +25 -0
  200. package/third-party/cargo/autocfg@1.5.1/Cargo.toml +75 -0
  201. package/third-party/cargo/autocfg@1.5.1/LICENSE-APACHE +201 -0
  202. package/third-party/cargo/autocfg@1.5.1/LICENSE-MIT +25 -0
  203. package/third-party/cargo/base64@0.13.1/Cargo.toml +53 -0
  204. package/third-party/cargo/base64@0.13.1/LICENSE-APACHE +201 -0
  205. package/third-party/cargo/base64@0.13.1/LICENSE-MIT +21 -0
  206. package/third-party/cargo/base64@0.22.1/Cargo.toml +85 -0
  207. package/third-party/cargo/base64@0.22.1/LICENSE-APACHE +201 -0
  208. package/third-party/cargo/base64@0.22.1/LICENSE-MIT +21 -0
  209. package/third-party/cargo/bit-set@0.10.0/Cargo.toml +108 -0
  210. package/third-party/cargo/bit-set@0.10.0/LICENSE-APACHE +201 -0
  211. package/third-party/cargo/bit-set@0.10.0/LICENSE-MIT +25 -0
  212. package/third-party/cargo/bit-vec@0.9.1/Cargo.toml +94 -0
  213. package/third-party/cargo/bit-vec@0.9.1/LICENSE-APACHE +201 -0
  214. package/third-party/cargo/bit-vec@0.9.1/LICENSE-MIT +25 -0
  215. package/third-party/cargo/bitflags@2.13.0/Cargo.toml +120 -0
  216. package/third-party/cargo/bitflags@2.13.0/LICENSE-APACHE +201 -0
  217. package/third-party/cargo/bitflags@2.13.0/LICENSE-MIT +25 -0
  218. package/third-party/cargo/block2@0.6.2/Cargo.toml +115 -0
  219. package/third-party/cargo/block2@0.6.2/MIT-terms.txt +22 -0
  220. package/third-party/cargo/block2@0.6.2/madsmtm-objc2-b4167b582b2f-LICENSE.md +34 -0
  221. package/third-party/cargo/bumpalo@3.20.3/Cargo.toml +99 -0
  222. package/third-party/cargo/bumpalo@3.20.3/LICENSE-APACHE +201 -0
  223. package/third-party/cargo/bumpalo@3.20.3/LICENSE-MIT +25 -0
  224. package/third-party/cargo/bytemuck@1.25.1/Cargo.toml +153 -0
  225. package/third-party/cargo/bytemuck@1.25.1/LICENSE-APACHE +61 -0
  226. package/third-party/cargo/bytemuck@1.25.1/LICENSE-MIT +9 -0
  227. package/third-party/cargo/bytemuck@1.25.1/LICENSE-ZLIB +11 -0
  228. package/third-party/cargo/bytemuck_derive@1.11.0/Cargo.toml +60 -0
  229. package/third-party/cargo/bytemuck_derive@1.11.0/LICENSE-APACHE +61 -0
  230. package/third-party/cargo/bytemuck_derive@1.11.0/LICENSE-MIT +9 -0
  231. package/third-party/cargo/bytemuck_derive@1.11.0/LICENSE-ZLIB +11 -0
  232. package/third-party/cargo/byteorder-lite@0.1.0/Cargo.toml +57 -0
  233. package/third-party/cargo/byteorder-lite@0.1.0/LICENSE-MIT +21 -0
  234. package/third-party/cargo/byteorder-lite@0.1.0/UNLICENSE +24 -0
  235. package/third-party/cargo/byteorder@1.5.0/COPYING +3 -0
  236. package/third-party/cargo/byteorder@1.5.0/Cargo.toml +54 -0
  237. package/third-party/cargo/byteorder@1.5.0/LICENSE-MIT +21 -0
  238. package/third-party/cargo/byteorder@1.5.0/UNLICENSE +24 -0
  239. package/third-party/cargo/cfg-if@1.0.4/Cargo.toml +47 -0
  240. package/third-party/cargo/cfg-if@1.0.4/LICENSE-APACHE +201 -0
  241. package/third-party/cargo/cfg-if@1.0.4/LICENSE-MIT +25 -0
  242. package/third-party/cargo/cfg_aliases@0.2.1/Cargo.toml +43 -0
  243. package/third-party/cargo/cfg_aliases@0.2.1/LICENSE +9 -0
  244. package/third-party/cargo/chunked_transfer@1.5.0/Cargo.toml +27 -0
  245. package/third-party/cargo/chunked_transfer@1.5.0/LICENSE-APACHE +201 -0
  246. package/third-party/cargo/chunked_transfer@1.5.0/LICENSE-MIT +22 -0
  247. package/third-party/cargo/codespan-reporting@0.13.1/Cargo.toml +115 -0
  248. package/third-party/cargo/codespan-reporting@0.13.1/LICENSE +201 -0
  249. package/third-party/cargo/color_quant@1.1.0/Cargo.toml +20 -0
  250. package/third-party/cargo/color_quant@1.1.0/LICENSE +21 -0
  251. package/third-party/cargo/console_error_panic_hook@0.1.7/Cargo.toml +27 -0
  252. package/third-party/cargo/console_error_panic_hook@0.1.7/LICENSE-APACHE +201 -0
  253. package/third-party/cargo/console_error_panic_hook@0.1.7/LICENSE-MIT +25 -0
  254. package/third-party/cargo/core_maths@0.1.1/Cargo.toml +37 -0
  255. package/third-party/cargo/core_maths@0.1.1/LICENSE +21 -0
  256. package/third-party/cargo/cosmic-text@0.19.0/Cargo.toml +214 -0
  257. package/third-party/cargo/cosmic-text@0.19.0/LICENSE-APACHE +201 -0
  258. package/third-party/cargo/cosmic-text@0.19.0/LICENSE-MIT +21 -0
  259. package/third-party/cargo/crc32fast@1.5.0/Cargo.toml +68 -0
  260. package/third-party/cargo/crc32fast@1.5.0/LICENSE-APACHE +202 -0
  261. package/third-party/cargo/crc32fast@1.5.0/LICENSE-MIT +21 -0
  262. package/third-party/cargo/data-url@0.3.2/Cargo.toml +63 -0
  263. package/third-party/cargo/data-url@0.3.2/LICENSE-APACHE +201 -0
  264. package/third-party/cargo/data-url@0.3.2/LICENSE-MIT +25 -0
  265. package/third-party/cargo/dispatch2@0.3.1/Cargo.toml +122 -0
  266. package/third-party/cargo/dispatch2@0.3.1/MIT-terms.txt +22 -0
  267. package/third-party/cargo/dispatch2@0.3.1/madsmtm-objc2-8852b424193c-LICENSE.md +34 -0
  268. package/third-party/cargo/dlib@0.5.3/Cargo.toml +43 -0
  269. package/third-party/cargo/dlib@0.5.3/LICENSE.txt +19 -0
  270. package/third-party/cargo/document-features@0.2.12/Cargo.toml +51 -0
  271. package/third-party/cargo/document-features@0.2.12/LICENSE-APACHE +73 -0
  272. package/third-party/cargo/document-features@0.2.12/LICENSE-MIT +19 -0
  273. package/third-party/cargo/equivalent@1.0.2/Cargo.toml +37 -0
  274. package/third-party/cargo/equivalent@1.0.2/LICENSE-APACHE +201 -0
  275. package/third-party/cargo/equivalent@1.0.2/LICENSE-MIT +25 -0
  276. package/third-party/cargo/errno@0.3.14/Cargo.toml +67 -0
  277. package/third-party/cargo/errno@0.3.14/LICENSE-APACHE +201 -0
  278. package/third-party/cargo/errno@0.3.14/LICENSE-MIT +25 -0
  279. package/third-party/cargo/etagere@0.3.0/Cargo.toml +57 -0
  280. package/third-party/cargo/etagere@0.3.0/LICENSE-APACHE +13 -0
  281. package/third-party/cargo/etagere@0.3.0/LICENSE-MIT +20 -0
  282. package/third-party/cargo/euclid@0.22.14/COPYRIGHT +5 -0
  283. package/third-party/cargo/euclid@0.22.14/Cargo.toml +66 -0
  284. package/third-party/cargo/euclid@0.22.14/LICENSE-APACHE +201 -0
  285. package/third-party/cargo/euclid@0.22.14/LICENSE-MIT +25 -0
  286. package/third-party/cargo/fastrand@2.5.0/Cargo.toml +89 -0
  287. package/third-party/cargo/fastrand@2.5.0/LICENSE-APACHE +201 -0
  288. package/third-party/cargo/fastrand@2.5.0/LICENSE-MIT +23 -0
  289. package/third-party/cargo/fdeflate@0.3.7/Cargo.toml +55 -0
  290. package/third-party/cargo/fdeflate@0.3.7/LICENSE-APACHE +177 -0
  291. package/third-party/cargo/fdeflate@0.3.7/LICENSE-MIT +25 -0
  292. package/third-party/cargo/flate2@1.1.9/Cargo.toml +274 -0
  293. package/third-party/cargo/flate2@1.1.9/LICENSE-APACHE +201 -0
  294. package/third-party/cargo/flate2@1.1.9/LICENSE-MIT +25 -0
  295. package/third-party/cargo/float-cmp@0.9.0/Cargo.toml +39 -0
  296. package/third-party/cargo/float-cmp@0.9.0/LICENSE +19 -0
  297. package/third-party/cargo/float_next_after@1.0.0/Cargo.toml +43 -0
  298. package/third-party/cargo/float_next_after@1.0.0/LICENSE +23 -0
  299. package/third-party/cargo/foldhash@0.2.0/Cargo.toml +80 -0
  300. package/third-party/cargo/foldhash@0.2.0/LICENSE +19 -0
  301. package/third-party/cargo/font-types@0.11.3/Cargo.toml +55 -0
  302. package/third-party/cargo/font-types@0.11.3/LICENSE-APACHE +67 -0
  303. package/third-party/cargo/font-types@0.11.3/LICENSE-MIT +25 -0
  304. package/third-party/cargo/fontdb@0.23.0/Cargo.toml +83 -0
  305. package/third-party/cargo/fontdb@0.23.0/LICENSE +21 -0
  306. package/third-party/cargo/futures-core@0.3.32/Cargo.toml +66 -0
  307. package/third-party/cargo/futures-core@0.3.32/LICENSE-APACHE +202 -0
  308. package/third-party/cargo/futures-core@0.3.32/LICENSE-MIT +26 -0
  309. package/third-party/cargo/futures-task@0.3.32/Cargo.toml +58 -0
  310. package/third-party/cargo/futures-task@0.3.32/LICENSE-APACHE +202 -0
  311. package/third-party/cargo/futures-task@0.3.32/LICENSE-MIT +26 -0
  312. package/third-party/cargo/futures-util@0.3.32/Cargo.toml +181 -0
  313. package/third-party/cargo/futures-util@0.3.32/LICENSE-APACHE +202 -0
  314. package/third-party/cargo/futures-util@0.3.32/LICENSE-MIT +26 -0
  315. package/third-party/cargo/getrandom@0.4.3/Cargo.toml +165 -0
  316. package/third-party/cargo/getrandom@0.4.3/LICENSE-APACHE +201 -0
  317. package/third-party/cargo/getrandom@0.4.3/LICENSE-MIT +26 -0
  318. package/third-party/cargo/gif@0.14.2/Cargo.toml +84 -0
  319. package/third-party/cargo/gif@0.14.2/LICENSE-APACHE +201 -0
  320. package/third-party/cargo/gif@0.14.2/LICENSE-MIT +21 -0
  321. package/third-party/cargo/glam@0.33.2/Cargo.toml +354 -0
  322. package/third-party/cargo/glam@0.33.2/LICENSE-APACHE +201 -0
  323. package/third-party/cargo/glam@0.33.2/LICENSE-MIT +23 -0
  324. package/third-party/cargo/glow@0.17.0/Cargo.toml +122 -0
  325. package/third-party/cargo/glow@0.17.0/LICENSE-APACHE +201 -0
  326. package/third-party/cargo/glow@0.17.0/LICENSE-MIT +23 -0
  327. package/third-party/cargo/glow@0.17.0/LICENSE-ZLIB +15 -0
  328. package/third-party/cargo/gltf-derive@1.4.1/Cargo.toml +34 -0
  329. package/third-party/cargo/gltf-derive@1.4.1/LICENSE-APACHE +202 -0
  330. package/third-party/cargo/gltf-derive@1.4.1/LICENSE-MIT +26 -0
  331. package/third-party/cargo/gltf-json@1.4.1/Cargo.toml +50 -0
  332. package/third-party/cargo/gltf-json@1.4.1/LICENSE-APACHE +202 -0
  333. package/third-party/cargo/gltf-json@1.4.1/LICENSE-MIT +26 -0
  334. package/third-party/cargo/gltf@1.4.1/Cargo.toml +122 -0
  335. package/third-party/cargo/gltf@1.4.1/LICENSE-APACHE +202 -0
  336. package/third-party/cargo/gltf@1.4.1/LICENSE-MIT +26 -0
  337. package/third-party/cargo/glyphon@0.12.0/Cargo.toml +35 -0
  338. package/third-party/cargo/glyphon@0.12.0/LICENSE-APACHE +201 -0
  339. package/third-party/cargo/glyphon@0.12.0/LICENSE-MIT +23 -0
  340. package/third-party/cargo/glyphon@0.12.0/LICENSE-ZLIB +15 -0
  341. package/third-party/cargo/gpu-allocator@0.28.0/Cargo.toml +180 -0
  342. package/third-party/cargo/gpu-allocator@0.28.0/LICENSE-APACHE +201 -0
  343. package/third-party/cargo/gpu-allocator@0.28.0/LICENSE-MIT +7 -0
  344. package/third-party/cargo/grid@1.0.1/Cargo.toml +77 -0
  345. package/third-party/cargo/grid@1.0.1/LICENSE +21 -0
  346. package/third-party/cargo/half@2.7.1/Cargo.toml +137 -0
  347. package/third-party/cargo/half@2.7.1/LICENSE-APACHE +176 -0
  348. package/third-party/cargo/half@2.7.1/LICENSE-MIT +19 -0
  349. package/third-party/cargo/harfrust@0.5.2/Cargo.toml +115 -0
  350. package/third-party/cargo/harfrust@0.5.2/harfbuzz-harfrust-efdae3142ab7-LICENSE +22 -0
  351. package/third-party/cargo/hashbrown@0.16.1/Cargo.toml +180 -0
  352. package/third-party/cargo/hashbrown@0.16.1/LICENSE-APACHE +201 -0
  353. package/third-party/cargo/hashbrown@0.16.1/LICENSE-MIT +25 -0
  354. package/third-party/cargo/hashbrown@0.17.1/Cargo.toml +201 -0
  355. package/third-party/cargo/hashbrown@0.17.1/LICENSE-APACHE +201 -0
  356. package/third-party/cargo/hashbrown@0.17.1/LICENSE-MIT +25 -0
  357. package/third-party/cargo/httpdate@1.0.3/Cargo.toml +35 -0
  358. package/third-party/cargo/httpdate@1.0.3/LICENSE-APACHE +201 -0
  359. package/third-party/cargo/httpdate@1.0.3/LICENSE-MIT +19 -0
  360. package/third-party/cargo/image-webp@0.2.4/Cargo.toml +63 -0
  361. package/third-party/cargo/image-webp@0.2.4/LICENSE-APACHE +177 -0
  362. package/third-party/cargo/image-webp@0.2.4/LICENSE-MIT +25 -0
  363. package/third-party/cargo/image@0.25.10/Cargo.toml +248 -0
  364. package/third-party/cargo/image@0.25.10/LICENSE-APACHE +177 -0
  365. package/third-party/cargo/image@0.25.10/LICENSE-MIT +25 -0
  366. package/third-party/cargo/imagesize@0.14.0/Cargo.toml +104 -0
  367. package/third-party/cargo/imagesize@0.14.0/LICENSE +21 -0
  368. package/third-party/cargo/indexmap@2.14.0/Cargo.toml +167 -0
  369. package/third-party/cargo/indexmap@2.14.0/LICENSE-APACHE +201 -0
  370. package/third-party/cargo/indexmap@2.14.0/LICENSE-MIT +25 -0
  371. package/third-party/cargo/inflections@1.1.1/Cargo.toml +21 -0
  372. package/third-party/cargo/inflections@1.1.1/LICENSE +20 -0
  373. package/third-party/cargo/itoa@1.0.18/Cargo.toml +66 -0
  374. package/third-party/cargo/itoa@1.0.18/LICENSE-APACHE +176 -0
  375. package/third-party/cargo/itoa@1.0.18/LICENSE-MIT +23 -0
  376. package/third-party/cargo/js-sys@0.3.103/Cargo.toml +98 -0
  377. package/third-party/cargo/js-sys@0.3.103/LICENSE-APACHE +201 -0
  378. package/third-party/cargo/js-sys@0.3.103/LICENSE-MIT +25 -0
  379. package/third-party/cargo/khronos-egl@6.0.0/Cargo.toml +82 -0
  380. package/third-party/cargo/khronos-egl@6.0.0/LICENSE-APACHE +201 -0
  381. package/third-party/cargo/khronos-egl@6.0.0/LICENSE-MIT +23 -0
  382. package/third-party/cargo/kurbo@0.13.1/Cargo.toml +230 -0
  383. package/third-party/cargo/kurbo@0.13.1/LICENSE-APACHE +202 -0
  384. package/third-party/cargo/kurbo@0.13.1/LICENSE-MIT +25 -0
  385. package/third-party/cargo/lazy_static@1.5.0/Cargo.toml +46 -0
  386. package/third-party/cargo/lazy_static@1.5.0/LICENSE-APACHE +201 -0
  387. package/third-party/cargo/lazy_static@1.5.0/LICENSE-MIT +25 -0
  388. package/third-party/cargo/libc@0.2.186/Cargo.toml +229 -0
  389. package/third-party/cargo/libc@0.2.186/LICENSE-APACHE +176 -0
  390. package/third-party/cargo/libc@0.2.186/LICENSE-MIT +25 -0
  391. package/third-party/cargo/libloading@0.8.9/Cargo.toml +90 -0
  392. package/third-party/cargo/libloading@0.8.9/LICENSE +12 -0
  393. package/third-party/cargo/libm@0.2.16/Cargo.toml +61 -0
  394. package/third-party/cargo/libm@0.2.16/LICENSE.txt +258 -0
  395. package/third-party/cargo/linebender_resource_handle@0.1.1/Cargo.toml +107 -0
  396. package/third-party/cargo/linebender_resource_handle@0.1.1/LICENSE-APACHE +176 -0
  397. package/third-party/cargo/linebender_resource_handle@0.1.1/LICENSE-MIT +19 -0
  398. package/third-party/cargo/litrs@1.0.0/Cargo.toml +63 -0
  399. package/third-party/cargo/litrs@1.0.0/LICENSE-APACHE +176 -0
  400. package/third-party/cargo/litrs@1.0.0/LICENSE-MIT +25 -0
  401. package/third-party/cargo/lock_api@0.4.14/Cargo.toml +68 -0
  402. package/third-party/cargo/lock_api@0.4.14/LICENSE-APACHE +201 -0
  403. package/third-party/cargo/lock_api@0.4.14/LICENSE-MIT +25 -0
  404. package/third-party/cargo/log@0.4.33/Cargo.toml +152 -0
  405. package/third-party/cargo/log@0.4.33/LICENSE-APACHE +201 -0
  406. package/third-party/cargo/log@0.4.33/LICENSE-MIT +25 -0
  407. package/third-party/cargo/lru@0.16.4/Cargo.toml +47 -0
  408. package/third-party/cargo/lru@0.16.4/LICENSE +21 -0
  409. package/third-party/cargo/lyon_geom@1.0.19/Cargo.toml +69 -0
  410. package/third-party/cargo/lyon_geom@1.0.19/nical-lyon-56219c95c658-LICENSE-APACHE +13 -0
  411. package/third-party/cargo/lyon_geom@1.0.19/nical-lyon-56219c95c658-LICENSE-MIT +20 -0
  412. package/third-party/cargo/lyon_path@1.0.19/Cargo.toml +58 -0
  413. package/third-party/cargo/lyon_path@1.0.19/nical-lyon-56219c95c658-LICENSE-APACHE +13 -0
  414. package/third-party/cargo/lyon_path@1.0.19/nical-lyon-56219c95c658-LICENSE-MIT +20 -0
  415. package/third-party/cargo/lyon_tessellation@1.0.20/Cargo.toml +71 -0
  416. package/third-party/cargo/lyon_tessellation@1.0.20/nical-lyon-7fa75ea8eea3-LICENSE-APACHE +13 -0
  417. package/third-party/cargo/lyon_tessellation@1.0.20/nical-lyon-7fa75ea8eea3-LICENSE-MIT +20 -0
  418. package/third-party/cargo/memchr@2.8.3/COPYING +3 -0
  419. package/third-party/cargo/memchr@2.8.3/Cargo.toml +89 -0
  420. package/third-party/cargo/memchr@2.8.3/LICENSE-MIT +21 -0
  421. package/third-party/cargo/memchr@2.8.3/UNLICENSE +24 -0
  422. package/third-party/cargo/memmap2@0.9.11/Cargo.toml +59 -0
  423. package/third-party/cargo/memmap2@0.9.11/LICENSE-APACHE +201 -0
  424. package/third-party/cargo/memmap2@0.9.11/LICENSE-MIT +26 -0
  425. package/third-party/cargo/miniz_oxide@0.8.9/Cargo.toml +91 -0
  426. package/third-party/cargo/miniz_oxide@0.8.9/LICENSE +25 -0
  427. package/third-party/cargo/miniz_oxide@0.8.9/LICENSE-APACHE.md +177 -0
  428. package/third-party/cargo/miniz_oxide@0.8.9/LICENSE-MIT.md +24 -0
  429. package/third-party/cargo/miniz_oxide@0.8.9/LICENSE-ZLIB.md +14 -0
  430. package/third-party/cargo/moxcms@0.8.1/Cargo.toml +113 -0
  431. package/third-party/cargo/moxcms@0.8.1/LICENSE-APACHE.md +201 -0
  432. package/third-party/cargo/moxcms@0.8.1/LICENSE.md +26 -0
  433. package/third-party/cargo/naga-types@30.0.0/Cargo.toml +94 -0
  434. package/third-party/cargo/naga-types@30.0.0/LICENSE.APACHE +176 -0
  435. package/third-party/cargo/naga-types@30.0.0/LICENSE.MIT +21 -0
  436. package/third-party/cargo/naga@30.0.0/Cargo.toml +246 -0
  437. package/third-party/cargo/naga@30.0.0/LICENSE.APACHE +176 -0
  438. package/third-party/cargo/naga@30.0.0/LICENSE.MIT +21 -0
  439. package/third-party/cargo/num-traits@0.2.19/Cargo.toml +54 -0
  440. package/third-party/cargo/num-traits@0.2.19/LICENSE-APACHE +201 -0
  441. package/third-party/cargo/num-traits@0.2.19/LICENSE-MIT +25 -0
  442. package/third-party/cargo/objc2-core-foundation@0.3.2/Cargo.toml +221 -0
  443. package/third-party/cargo/objc2-core-foundation@0.3.2/MIT-terms.txt +22 -0
  444. package/third-party/cargo/objc2-core-foundation@0.3.2/madsmtm-objc2-7b1abfd750a2-LICENSE.md +34 -0
  445. package/third-party/cargo/objc2-core-graphics@0.3.2/Cargo.toml +331 -0
  446. package/third-party/cargo/objc2-core-graphics@0.3.2/MIT-terms.txt +22 -0
  447. package/third-party/cargo/objc2-core-graphics@0.3.2/madsmtm-objc2-7b1abfd750a2-LICENSE.md +34 -0
  448. package/third-party/cargo/objc2-encode@4.1.0/Cargo.toml +81 -0
  449. package/third-party/cargo/objc2-encode@4.1.0/MIT-terms.txt +22 -0
  450. package/third-party/cargo/objc2-encode@4.1.0/madsmtm-objc2-8d214f547736-LICENSE.md +34 -0
  451. package/third-party/cargo/objc2-foundation@0.3.2/Cargo.toml +529 -0
  452. package/third-party/cargo/objc2-foundation@0.3.2/MIT-terms.txt +22 -0
  453. package/third-party/cargo/objc2-foundation@0.3.2/madsmtm-objc2-7b1abfd750a2-LICENSE.md +34 -0
  454. package/third-party/cargo/objc2-io-surface@0.3.2/Cargo.toml +139 -0
  455. package/third-party/cargo/objc2-io-surface@0.3.2/MIT-terms.txt +22 -0
  456. package/third-party/cargo/objc2-io-surface@0.3.2/madsmtm-objc2-7b1abfd750a2-LICENSE.md +34 -0
  457. package/third-party/cargo/objc2-metal@0.3.2/Cargo.toml +601 -0
  458. package/third-party/cargo/objc2-metal@0.3.2/MIT-terms.txt +22 -0
  459. package/third-party/cargo/objc2-metal@0.3.2/madsmtm-objc2-7b1abfd750a2-LICENSE.md +34 -0
  460. package/third-party/cargo/objc2-quartz-core@0.3.2/Cargo.toml +302 -0
  461. package/third-party/cargo/objc2-quartz-core@0.3.2/MIT-terms.txt +22 -0
  462. package/third-party/cargo/objc2-quartz-core@0.3.2/madsmtm-objc2-7b1abfd750a2-LICENSE.md +34 -0
  463. package/third-party/cargo/objc2@0.6.4/Cargo.toml +232 -0
  464. package/third-party/cargo/objc2@0.6.4/MIT-terms.txt +22 -0
  465. package/third-party/cargo/objc2@0.6.4/madsmtm-objc2-8852b424193c-LICENSE.md +34 -0
  466. package/third-party/cargo/once_cell@1.21.4/Cargo.toml +119 -0
  467. package/third-party/cargo/once_cell@1.21.4/LICENSE-APACHE +201 -0
  468. package/third-party/cargo/once_cell@1.21.4/LICENSE-MIT +23 -0
  469. package/third-party/cargo/ordered-float@5.3.0/Cargo.toml +162 -0
  470. package/third-party/cargo/ordered-float@5.3.0/LICENSE-MIT +25 -0
  471. package/third-party/cargo/parking_lot@0.12.5/Cargo.toml +87 -0
  472. package/third-party/cargo/parking_lot@0.12.5/LICENSE-APACHE +201 -0
  473. package/third-party/cargo/parking_lot@0.12.5/LICENSE-MIT +25 -0
  474. package/third-party/cargo/parking_lot_core@0.9.12/Cargo.toml +72 -0
  475. package/third-party/cargo/parking_lot_core@0.9.12/LICENSE-APACHE +201 -0
  476. package/third-party/cargo/parking_lot_core@0.9.12/LICENSE-MIT +25 -0
  477. package/third-party/cargo/pico-args@0.5.0/Cargo.toml +32 -0
  478. package/third-party/cargo/pico-args@0.5.0/LICENSE +20 -0
  479. package/third-party/cargo/pin-project-lite@0.2.17/Cargo.toml +198 -0
  480. package/third-party/cargo/pin-project-lite@0.2.17/LICENSE-APACHE +177 -0
  481. package/third-party/cargo/pin-project-lite@0.2.17/LICENSE-MIT +23 -0
  482. package/third-party/cargo/pkg-config@0.3.33/Cargo.toml +43 -0
  483. package/third-party/cargo/pkg-config@0.3.33/LICENSE-APACHE +201 -0
  484. package/third-party/cargo/pkg-config@0.3.33/LICENSE-MIT +25 -0
  485. package/third-party/cargo/png@0.18.1/Cargo.toml +130 -0
  486. package/third-party/cargo/png@0.18.1/LICENSE-APACHE +201 -0
  487. package/third-party/cargo/png@0.18.1/LICENSE-MIT +25 -0
  488. package/third-party/cargo/pollster@0.4.0/Cargo.toml +53 -0
  489. package/third-party/cargo/pollster@0.4.0/LICENSE-APACHE +201 -0
  490. package/third-party/cargo/pollster@0.4.0/LICENSE-MIT +25 -0
  491. package/third-party/cargo/polycool@0.4.0/Cargo.toml +83 -0
  492. package/third-party/cargo/polycool@0.4.0/LICENSE-APACHE +202 -0
  493. package/third-party/cargo/polycool@0.4.0/LICENSE-MIT +25 -0
  494. package/third-party/cargo/pp-rs@0.2.1/Cargo.toml +23 -0
  495. package/third-party/cargo/pp-rs@0.2.1/LICENSE +29 -0
  496. package/third-party/cargo/presser@0.3.1/Cargo.toml +58 -0
  497. package/third-party/cargo/presser@0.3.1/LICENSE-APACHE +201 -0
  498. package/third-party/cargo/presser@0.3.1/LICENSE-MIT +25 -0
  499. package/third-party/cargo/proc-macro2@1.0.106/Cargo.toml +105 -0
  500. package/third-party/cargo/proc-macro2@1.0.106/LICENSE-APACHE +176 -0
  501. package/third-party/cargo/proc-macro2@1.0.106/LICENSE-MIT +23 -0
  502. package/third-party/cargo/profiling@1.0.18/Cargo.toml +96 -0
  503. package/third-party/cargo/profiling@1.0.18/aclysma-profiling-8271551172eb-LICENSE-APACHE +201 -0
  504. package/third-party/cargo/profiling@1.0.18/aclysma-profiling-8271551172eb-LICENSE-MIT +21 -0
  505. package/third-party/cargo/pxfm@0.1.30/Cargo.toml +53 -0
  506. package/third-party/cargo/pxfm@0.1.30/LICENSE-APACHE.md +201 -0
  507. package/third-party/cargo/pxfm@0.1.30/LICENSE.md +26 -0
  508. package/third-party/cargo/quick-error@2.0.1/Cargo.toml +24 -0
  509. package/third-party/cargo/quick-error@2.0.1/LICENSE-APACHE +202 -0
  510. package/third-party/cargo/quick-error@2.0.1/LICENSE-MIT +19 -0
  511. package/third-party/cargo/quote@1.0.46/Cargo.toml +70 -0
  512. package/third-party/cargo/quote@1.0.46/LICENSE-APACHE +176 -0
  513. package/third-party/cargo/quote@1.0.46/LICENSE-MIT +23 -0
  514. package/third-party/cargo/rangemap@1.7.1/Cargo.toml +91 -0
  515. package/third-party/cargo/rangemap@1.7.1/LICENSE-APACHE +191 -0
  516. package/third-party/cargo/rangemap@1.7.1/LICENSE-MIT +7 -0
  517. package/third-party/cargo/raw-window-handle@0.6.2/Cargo.toml +56 -0
  518. package/third-party/cargo/raw-window-handle@0.6.2/LICENSE-APACHE.md +177 -0
  519. package/third-party/cargo/raw-window-handle@0.6.2/LICENSE-MIT.md +21 -0
  520. package/third-party/cargo/raw-window-handle@0.6.2/LICENSE-ZLIB.md +11 -0
  521. package/third-party/cargo/raw-window-metal@1.1.0/Cargo.toml +111 -0
  522. package/third-party/cargo/raw-window-metal@1.1.0/LICENSE-APACHE +202 -0
  523. package/third-party/cargo/raw-window-metal@1.1.0/LICENSE-MIT +17 -0
  524. package/third-party/cargo/read-fonts@0.37.0/Cargo.toml +95 -0
  525. package/third-party/cargo/read-fonts@0.37.0/LICENSE-APACHE +67 -0
  526. package/third-party/cargo/read-fonts@0.37.0/LICENSE-MIT +25 -0
  527. package/third-party/cargo/read-fonts@0.39.2/Cargo.toml +96 -0
  528. package/third-party/cargo/read-fonts@0.39.2/LICENSE-APACHE +67 -0
  529. package/third-party/cargo/read-fonts@0.39.2/LICENSE-MIT +25 -0
  530. package/third-party/cargo/renderdoc-sys@1.1.0/Cargo.toml +39 -0
  531. package/third-party/cargo/renderdoc-sys@1.1.0/LICENSE-APACHE +201 -0
  532. package/third-party/cargo/renderdoc-sys@1.1.0/LICENSE-MIT +25 -0
  533. package/third-party/cargo/resvg@0.47.0/Cargo.toml +112 -0
  534. package/third-party/cargo/resvg@0.47.0/LICENSE-APACHE +176 -0
  535. package/third-party/cargo/resvg@0.47.0/LICENSE-MIT +25 -0
  536. package/third-party/cargo/rgb@0.8.53/Cargo.toml +110 -0
  537. package/third-party/cargo/rgb@0.8.53/LICENSE +21 -0
  538. package/third-party/cargo/roxmltree@0.21.1/Cargo.toml +75 -0
  539. package/third-party/cargo/roxmltree@0.21.1/LICENSE-APACHE +201 -0
  540. package/third-party/cargo/roxmltree@0.21.1/LICENSE-MIT +21 -0
  541. package/third-party/cargo/rustc-hash@1.1.0/Cargo.toml +25 -0
  542. package/third-party/cargo/rustc-hash@1.1.0/LICENSE-APACHE +201 -0
  543. package/third-party/cargo/rustc-hash@1.1.0/LICENSE-MIT +23 -0
  544. package/third-party/cargo/rustc-hash@2.1.3/Cargo.toml +50 -0
  545. package/third-party/cargo/rustc-hash@2.1.3/LICENSE-APACHE +176 -0
  546. package/third-party/cargo/rustc-hash@2.1.3/LICENSE-MIT +23 -0
  547. package/third-party/cargo/rustix@1.1.4/COPYRIGHT +29 -0
  548. package/third-party/cargo/rustix@1.1.4/Cargo.toml +292 -0
  549. package/third-party/cargo/rustix@1.1.4/LICENSE-APACHE +201 -0
  550. package/third-party/cargo/rustix@1.1.4/LICENSE-Apache-2.0_WITH_LLVM-exception +220 -0
  551. package/third-party/cargo/rustix@1.1.4/LICENSE-MIT +23 -0
  552. package/third-party/cargo/rustversion@1.0.23/Cargo.toml +69 -0
  553. package/third-party/cargo/rustversion@1.0.23/LICENSE-APACHE +176 -0
  554. package/third-party/cargo/rustversion@1.0.23/LICENSE-MIT +23 -0
  555. package/third-party/cargo/rustybuzz@0.20.1/Cargo.toml +110 -0
  556. package/third-party/cargo/rustybuzz@0.20.1/LICENSE +22 -0
  557. package/third-party/cargo/scopeguard@1.2.0/Cargo.toml +43 -0
  558. package/third-party/cargo/scopeguard@1.2.0/LICENSE-APACHE +201 -0
  559. package/third-party/cargo/scopeguard@1.2.0/LICENSE-MIT +25 -0
  560. package/third-party/cargo/self_cell@1.2.2/Cargo.toml +33 -0
  561. package/third-party/cargo/self_cell@1.2.2/LICENSE-APACHE +201 -0
  562. package/third-party/cargo/self_cell@1.2.2/LICENSE-GPLv2 +339 -0
  563. package/third-party/cargo/self_cell@1.3.0/Cargo.toml +33 -0
  564. package/third-party/cargo/self_cell@1.3.0/LICENSE-APACHE +201 -0
  565. package/third-party/cargo/self_cell@1.3.0/LICENSE-GPLv2 +339 -0
  566. package/third-party/cargo/serde@1.0.228/Cargo.toml +84 -0
  567. package/third-party/cargo/serde@1.0.228/LICENSE-APACHE +176 -0
  568. package/third-party/cargo/serde@1.0.228/LICENSE-MIT +23 -0
  569. package/third-party/cargo/serde_core@1.0.228/Cargo.toml +87 -0
  570. package/third-party/cargo/serde_core@1.0.228/LICENSE-APACHE +176 -0
  571. package/third-party/cargo/serde_core@1.0.228/LICENSE-MIT +23 -0
  572. package/third-party/cargo/serde_derive@1.0.228/Cargo.toml +87 -0
  573. package/third-party/cargo/serde_derive@1.0.228/LICENSE-APACHE +176 -0
  574. package/third-party/cargo/serde_derive@1.0.228/LICENSE-MIT +23 -0
  575. package/third-party/cargo/serde_json@1.0.150/Cargo.toml +162 -0
  576. package/third-party/cargo/serde_json@1.0.150/LICENSE-APACHE +176 -0
  577. package/third-party/cargo/serde_json@1.0.150/LICENSE-MIT +23 -0
  578. package/third-party/cargo/simd-adler32@0.3.10/Cargo.toml +68 -0
  579. package/third-party/cargo/simd-adler32@0.3.10/LICENSE.md +21 -0
  580. package/third-party/cargo/simplecss@0.2.2/Cargo.toml +146 -0
  581. package/third-party/cargo/simplecss@0.2.2/LICENSE-APACHE +201 -0
  582. package/third-party/cargo/simplecss@0.2.2/LICENSE-MIT +21 -0
  583. package/third-party/cargo/siphasher@1.0.3/COPYING +7 -0
  584. package/third-party/cargo/siphasher@1.0.3/Cargo.toml +64 -0
  585. package/third-party/cargo/skrifa@0.40.0/Cargo.toml +86 -0
  586. package/third-party/cargo/skrifa@0.40.0/LICENSE-APACHE +67 -0
  587. package/third-party/cargo/skrifa@0.40.0/LICENSE-MIT +25 -0
  588. package/third-party/cargo/skrifa@0.42.1/Cargo.toml +86 -0
  589. package/third-party/cargo/skrifa@0.42.1/LICENSE-APACHE +67 -0
  590. package/third-party/cargo/skrifa@0.42.1/LICENSE-MIT +25 -0
  591. package/third-party/cargo/slab@0.4.12/Cargo.toml +67 -0
  592. package/third-party/cargo/slab@0.4.12/LICENSE +25 -0
  593. package/third-party/cargo/slotmap@1.1.1/Cargo.toml +83 -0
  594. package/third-party/cargo/slotmap@1.1.1/LICENSE +19 -0
  595. package/third-party/cargo/smallvec@1.15.2/Cargo.toml +103 -0
  596. package/third-party/cargo/smallvec@1.15.2/LICENSE-APACHE +201 -0
  597. package/third-party/cargo/smallvec@1.15.2/LICENSE-MIT +25 -0
  598. package/third-party/cargo/smol_str@0.3.6/Cargo.toml +155 -0
  599. package/third-party/cargo/smol_str@0.3.6/LICENSE-APACHE +201 -0
  600. package/third-party/cargo/smol_str@0.3.6/LICENSE-MIT +23 -0
  601. package/third-party/cargo/spirv@0.4.0+sdk-1.4.341.0/Cargo.toml +56 -0
  602. package/third-party/cargo/spirv@0.4.0+sdk-1.4.341.0/gfx-rs-rspirv-8afc3d0ac8e1-LICENSE +202 -0
  603. package/third-party/cargo/static_assertions@1.1.0/Cargo.toml +39 -0
  604. package/third-party/cargo/static_assertions@1.1.0/LICENSE-APACHE +202 -0
  605. package/third-party/cargo/static_assertions@1.1.0/LICENSE-MIT +21 -0
  606. package/third-party/cargo/strict-num@0.1.1/Cargo.toml +35 -0
  607. package/third-party/cargo/strict-num@0.1.1/LICENSE +19 -0
  608. package/third-party/cargo/svgtypes@0.16.1/Cargo.toml +57 -0
  609. package/third-party/cargo/svgtypes@0.16.1/LICENSE-APACHE +201 -0
  610. package/third-party/cargo/svgtypes@0.16.1/LICENSE-MIT +20 -0
  611. package/third-party/cargo/swash@0.2.9/Cargo.toml +93 -0
  612. package/third-party/cargo/swash@0.2.9/LICENSE-APACHE +201 -0
  613. package/third-party/cargo/swash@0.2.9/LICENSE-MIT +25 -0
  614. package/third-party/cargo/syn@2.0.118/Cargo.toml +272 -0
  615. package/third-party/cargo/syn@2.0.118/LICENSE-APACHE +176 -0
  616. package/third-party/cargo/syn@2.0.118/LICENSE-MIT +23 -0
  617. package/third-party/cargo/sys-locale@0.3.2/Cargo.toml +73 -0
  618. package/third-party/cargo/sys-locale@0.3.2/LICENSE-APACHE +201 -0
  619. package/third-party/cargo/sys-locale@0.3.2/LICENSE-MIT +21 -0
  620. package/third-party/cargo/taffy@0.12.1/Cargo.toml +171 -0
  621. package/third-party/cargo/taffy@0.12.1/DioxusLabs-taffy-1c9e37a0a1cf-LICENSE.md +25 -0
  622. package/third-party/cargo/tempfile@3.27.0/Cargo.toml +105 -0
  623. package/third-party/cargo/tempfile@3.27.0/LICENSE-APACHE +201 -0
  624. package/third-party/cargo/tempfile@3.27.0/LICENSE-MIT +25 -0
  625. package/third-party/cargo/termcolor@1.4.1/COPYING +3 -0
  626. package/third-party/cargo/termcolor@1.4.1/Cargo.toml +40 -0
  627. package/third-party/cargo/termcolor@1.4.1/LICENSE-MIT +21 -0
  628. package/third-party/cargo/termcolor@1.4.1/UNLICENSE +24 -0
  629. package/third-party/cargo/thiserror-impl@2.0.18/Cargo.toml +52 -0
  630. package/third-party/cargo/thiserror-impl@2.0.18/LICENSE-APACHE +176 -0
  631. package/third-party/cargo/thiserror-impl@2.0.18/LICENSE-MIT +23 -0
  632. package/third-party/cargo/thiserror@2.0.18/Cargo.toml +119 -0
  633. package/third-party/cargo/thiserror@2.0.18/LICENSE-APACHE +176 -0
  634. package/third-party/cargo/thiserror@2.0.18/LICENSE-MIT +23 -0
  635. package/third-party/cargo/tiny-skia-path@0.12.0/Cargo.toml +58 -0
  636. package/third-party/cargo/tiny-skia-path@0.12.0/LICENSE +30 -0
  637. package/third-party/cargo/tiny-skia@0.12.0/Cargo.toml +116 -0
  638. package/third-party/cargo/tiny-skia@0.12.0/LICENSE +30 -0
  639. package/third-party/cargo/tiny_http@0.12.0/Cargo.toml +82 -0
  640. package/third-party/cargo/tiny_http@0.12.0/LICENSE-APACHE +201 -0
  641. package/third-party/cargo/tiny_http@0.12.0/LICENSE-MIT +25 -0
  642. package/third-party/cargo/tinyvec@1.12.0/Cargo.toml +184 -0
  643. package/third-party/cargo/tinyvec@1.12.0/LICENSE-APACHE.md +202 -0
  644. package/third-party/cargo/tinyvec@1.12.0/LICENSE-MIT.md +5 -0
  645. package/third-party/cargo/tinyvec@1.12.0/LICENSE-ZLIB.md +11 -0
  646. package/third-party/cargo/tinyvec_macros@0.1.1/Cargo.toml +19 -0
  647. package/third-party/cargo/tinyvec_macros@0.1.1/LICENSE-APACHE.md +202 -0
  648. package/third-party/cargo/tinyvec_macros@0.1.1/LICENSE-MIT.md +21 -0
  649. package/third-party/cargo/tinyvec_macros@0.1.1/LICENSE-ZLIB.md +20 -0
  650. package/third-party/cargo/ttf-parser@0.25.1/Cargo.toml +101 -0
  651. package/third-party/cargo/ttf-parser@0.25.1/LICENSE-APACHE +201 -0
  652. package/third-party/cargo/ttf-parser@0.25.1/LICENSE-MIT +20 -0
  653. package/third-party/cargo/unicode-bidi-mirroring@0.4.0/Cargo.toml +22 -0
  654. package/third-party/cargo/unicode-bidi-mirroring@0.4.0/LICENSE-APACHE +201 -0
  655. package/third-party/cargo/unicode-bidi-mirroring@0.4.0/LICENSE-MIT +21 -0
  656. package/third-party/cargo/unicode-bidi@0.3.18/COPYRIGHT +8 -0
  657. package/third-party/cargo/unicode-bidi@0.3.18/Cargo.toml +90 -0
  658. package/third-party/cargo/unicode-bidi@0.3.18/LICENSE-APACHE +201 -0
  659. package/third-party/cargo/unicode-bidi@0.3.18/LICENSE-MIT +25 -0
  660. package/third-party/cargo/unicode-ccc@0.4.0/Cargo.toml +22 -0
  661. package/third-party/cargo/unicode-ccc@0.4.0/LICENSE-APACHE +201 -0
  662. package/third-party/cargo/unicode-ccc@0.4.0/LICENSE-MIT +21 -0
  663. package/third-party/cargo/unicode-ident@1.0.24/Cargo.toml +84 -0
  664. package/third-party/cargo/unicode-ident@1.0.24/LICENSE-APACHE +176 -0
  665. package/third-party/cargo/unicode-ident@1.0.24/LICENSE-MIT +23 -0
  666. package/third-party/cargo/unicode-ident@1.0.24/LICENSE-UNICODE +39 -0
  667. package/third-party/cargo/unicode-linebreak@0.1.5/Cargo.toml +32 -0
  668. package/third-party/cargo/unicode-linebreak@0.1.5/LICENSE +201 -0
  669. package/third-party/cargo/unicode-properties@0.1.4/COPYRIGHT +7 -0
  670. package/third-party/cargo/unicode-properties@0.1.4/Cargo.toml +65 -0
  671. package/third-party/cargo/unicode-properties@0.1.4/LICENSE-APACHE +201 -0
  672. package/third-party/cargo/unicode-properties@0.1.4/LICENSE-MIT +25 -0
  673. package/third-party/cargo/unicode-script@0.5.8/Cargo.toml +63 -0
  674. package/third-party/cargo/unicode-script@0.5.8/LICENSE-APACHE +201 -0
  675. package/third-party/cargo/unicode-script@0.5.8/LICENSE-MIT +27 -0
  676. package/third-party/cargo/unicode-segmentation@1.13.3/COPYRIGHT +7 -0
  677. package/third-party/cargo/unicode-segmentation@1.13.3/Cargo.toml +91 -0
  678. package/third-party/cargo/unicode-segmentation@1.13.3/LICENSE-APACHE +201 -0
  679. package/third-party/cargo/unicode-segmentation@1.13.3/LICENSE-MIT +25 -0
  680. package/third-party/cargo/unicode-vo@0.1.0/Cargo.toml +22 -0
  681. package/third-party/cargo/unicode-vo@0.1.0/LICENSE-APACHE +201 -0
  682. package/third-party/cargo/unicode-vo@0.1.0/LICENSE-MIT +21 -0
  683. package/third-party/cargo/unicode-width@0.2.2/COPYRIGHT +7 -0
  684. package/third-party/cargo/unicode-width@0.2.2/Cargo.toml +77 -0
  685. package/third-party/cargo/unicode-width@0.2.2/LICENSE-APACHE +201 -0
  686. package/third-party/cargo/unicode-width@0.2.2/LICENSE-MIT +25 -0
  687. package/third-party/cargo/unicode-xid@0.2.6/COPYRIGHT +7 -0
  688. package/third-party/cargo/unicode-xid@0.2.6/Cargo.toml +65 -0
  689. package/third-party/cargo/unicode-xid@0.2.6/LICENSE-APACHE +201 -0
  690. package/third-party/cargo/unicode-xid@0.2.6/LICENSE-MIT +25 -0
  691. package/third-party/cargo/urlencoding@2.1.3/Cargo.toml +41 -0
  692. package/third-party/cargo/urlencoding@2.1.3/LICENSE +20 -0
  693. package/third-party/cargo/usvg@0.47.0/Cargo.toml +138 -0
  694. package/third-party/cargo/usvg@0.47.0/LICENSE-APACHE +176 -0
  695. package/third-party/cargo/usvg@0.47.0/LICENSE-MIT +25 -0
  696. package/third-party/cargo/version_check@0.9.5/Cargo.toml +38 -0
  697. package/third-party/cargo/version_check@0.9.5/LICENSE-APACHE +201 -0
  698. package/third-party/cargo/version_check@0.9.5/LICENSE-MIT +19 -0
  699. package/third-party/cargo/wasm-bindgen-futures@0.4.76/Cargo.toml +88 -0
  700. package/third-party/cargo/wasm-bindgen-futures@0.4.76/LICENSE-APACHE +201 -0
  701. package/third-party/cargo/wasm-bindgen-futures@0.4.76/LICENSE-MIT +25 -0
  702. package/third-party/cargo/wasm-bindgen-macro-support@0.2.126/Cargo.toml +83 -0
  703. package/third-party/cargo/wasm-bindgen-macro-support@0.2.126/LICENSE-APACHE +201 -0
  704. package/third-party/cargo/wasm-bindgen-macro-support@0.2.126/LICENSE-MIT +25 -0
  705. package/third-party/cargo/wasm-bindgen-macro@0.2.126/Cargo.toml +73 -0
  706. package/third-party/cargo/wasm-bindgen-macro@0.2.126/LICENSE-APACHE +201 -0
  707. package/third-party/cargo/wasm-bindgen-macro@0.2.126/LICENSE-MIT +25 -0
  708. package/third-party/cargo/wasm-bindgen-shared@0.2.126/Cargo.toml +66 -0
  709. package/third-party/cargo/wasm-bindgen-shared@0.2.126/LICENSE-APACHE +201 -0
  710. package/third-party/cargo/wasm-bindgen-shared@0.2.126/LICENSE-MIT +25 -0
  711. package/third-party/cargo/wasm-bindgen@0.2.126/Cargo.toml +122 -0
  712. package/third-party/cargo/wasm-bindgen@0.2.126/LICENSE-APACHE +201 -0
  713. package/third-party/cargo/wasm-bindgen@0.2.126/LICENSE-MIT +25 -0
  714. package/third-party/cargo/wayland-sys@0.31.11/Cargo.toml +81 -0
  715. package/third-party/cargo/wayland-sys@0.31.11/LICENSE.txt +19 -0
  716. package/third-party/cargo/web-sys@0.3.103/Cargo.toml +2823 -0
  717. package/third-party/cargo/web-sys@0.3.103/LICENSE-APACHE +201 -0
  718. package/third-party/cargo/web-sys@0.3.103/LICENSE-MIT +25 -0
  719. package/third-party/cargo/weezl@0.1.12/Cargo.toml +120 -0
  720. package/third-party/cargo/weezl@0.1.12/LICENSE-APACHE +201 -0
  721. package/third-party/cargo/weezl@0.1.12/LICENSE-MIT +22 -0
  722. package/third-party/cargo/wgpu-core-deps-apple@30.0.0/Cargo.toml +53 -0
  723. package/third-party/cargo/wgpu-core-deps-apple@30.0.0/LICENSE.APACHE +176 -0
  724. package/third-party/cargo/wgpu-core-deps-apple@30.0.0/LICENSE.MIT +21 -0
  725. package/third-party/cargo/wgpu-core@30.0.0/Cargo.toml +237 -0
  726. package/third-party/cargo/wgpu-core@30.0.0/LICENSE.APACHE +176 -0
  727. package/third-party/cargo/wgpu-core@30.0.0/LICENSE.MIT +21 -0
  728. package/third-party/cargo/wgpu-hal@30.0.0/Cargo.toml +541 -0
  729. package/third-party/cargo/wgpu-hal@30.0.0/LICENSE.APACHE +176 -0
  730. package/third-party/cargo/wgpu-hal@30.0.0/LICENSE.MIT +21 -0
  731. package/third-party/cargo/wgpu-naga-bridge@30.0.0/Cargo.toml +46 -0
  732. package/third-party/cargo/wgpu-naga-bridge@30.0.0/LICENSE.APACHE +176 -0
  733. package/third-party/cargo/wgpu-naga-bridge@30.0.0/LICENSE.MIT +21 -0
  734. package/third-party/cargo/wgpu-types@30.0.0/Cargo.toml +161 -0
  735. package/third-party/cargo/wgpu-types@30.0.0/LICENSE.APACHE +176 -0
  736. package/third-party/cargo/wgpu-types@30.0.0/LICENSE.MIT +21 -0
  737. package/third-party/cargo/wgpu@30.0.0/Cargo.toml +278 -0
  738. package/third-party/cargo/wgpu@30.0.0/LICENSE.APACHE +176 -0
  739. package/third-party/cargo/wgpu@30.0.0/LICENSE.MIT +21 -0
  740. package/third-party/cargo/xmlwriter@0.1.0/Cargo.toml +23 -0
  741. package/third-party/cargo/xmlwriter@0.1.0/LICENSE +21 -0
  742. package/third-party/cargo/yazi@0.2.1/Cargo.toml +45 -0
  743. package/third-party/cargo/yazi@0.2.1/LICENSE-APACHE +201 -0
  744. package/third-party/cargo/yazi@0.2.1/LICENSE-MIT +19 -0
  745. package/third-party/cargo/zeno@0.3.3/Cargo.toml +65 -0
  746. package/third-party/cargo/zeno@0.3.3/LICENSE-APACHE +201 -0
  747. package/third-party/cargo/zeno@0.3.3/LICENSE-MIT +25 -0
  748. package/third-party/cargo/zerocopy-derive@0.8.54/Cargo.toml +209 -0
  749. package/third-party/cargo/zerocopy-derive@0.8.54/LICENSE-APACHE +202 -0
  750. package/third-party/cargo/zerocopy-derive@0.8.54/LICENSE-BSD +24 -0
  751. package/third-party/cargo/zerocopy-derive@0.8.54/LICENSE-MIT +26 -0
  752. package/third-party/cargo/zerocopy@0.8.54/Cargo.toml +419 -0
  753. package/third-party/cargo/zerocopy@0.8.54/LICENSE-APACHE +202 -0
  754. package/third-party/cargo/zerocopy@0.8.54/LICENSE-BSD +24 -0
  755. package/third-party/cargo/zerocopy@0.8.54/LICENSE-MIT +26 -0
  756. package/third-party/cargo/zmij@1.0.23/Cargo.toml +90 -0
  757. package/third-party/cargo/zmij@1.0.23/LICENSE-MIT +23 -0
  758. package/third-party/cargo/zune-core@0.5.1/Cargo.toml +47 -0
  759. package/third-party/cargo/zune-core@0.5.1/LICENSE-APACHE +201 -0
  760. package/third-party/cargo/zune-core@0.5.1/LICENSE-MIT +21 -0
  761. package/third-party/cargo/zune-core@0.5.1/LICENSE-ZLIB +19 -0
  762. package/third-party/cargo/zune-jpeg@0.5.15/Cargo.toml +67 -0
  763. package/third-party/cargo/zune-jpeg@0.5.15/LICENSE-APACHE +201 -0
  764. package/third-party/cargo/zune-jpeg@0.5.15/LICENSE-MIT +21 -0
  765. package/third-party/cargo/zune-jpeg@0.5.15/LICENSE-ZLIB +19 -0
  766. package/third-party/inventory.json +3614 -0
  767. package/third-party/npm/@esbuild__darwin-arm64@0.27.4/esbuild-0.27.4-LICENSE.md +21 -0
  768. package/third-party/npm/@esbuild__darwin-arm64@0.27.4/go-LICENSE +27 -0
  769. package/third-party/npm/@esbuild__darwin-arm64@0.27.4/golang-x-sys-c0bba94af5f8-LICENSE +27 -0
  770. package/third-party/npm/@esbuild__darwin-arm64@0.27.4/package.json +20 -0
  771. package/third-party/npm/@floating-ui__core@1.7.5/LICENSE +20 -0
  772. package/third-party/npm/@floating-ui__core@1.7.5/package.json +63 -0
  773. package/third-party/npm/@floating-ui__dom@1.7.6/LICENSE +20 -0
  774. package/third-party/npm/@floating-ui__dom@1.7.6/package.json +71 -0
  775. package/third-party/npm/@floating-ui__react-dom@2.1.8/LICENSE +20 -0
  776. package/third-party/npm/@floating-ui__react-dom@2.1.8/package.json +76 -0
  777. package/third-party/npm/@floating-ui__utils@0.2.11/LICENSE +20 -0
  778. package/third-party/npm/@floating-ui__utils@0.2.11/package.json +70 -0
  779. package/third-party/npm/@radix-ui__primitive@1.1.7/LICENSE +21 -0
  780. package/third-party/npm/@radix-ui__primitive@1.1.7/package.json +79 -0
  781. package/third-party/npm/@radix-ui__react-arrow@1.1.15/LICENSE +21 -0
  782. package/third-party/npm/@radix-ui__react-arrow@1.1.15/package.json +68 -0
  783. package/third-party/npm/@radix-ui__react-collection@1.1.15/LICENSE +21 -0
  784. package/third-party/npm/@radix-ui__react-collection@1.1.15/package.json +71 -0
  785. package/third-party/npm/@radix-ui__react-compose-refs@1.1.5/LICENSE +21 -0
  786. package/third-party/npm/@radix-ui__react-compose-refs@1.1.5/package.json +60 -0
  787. package/third-party/npm/@radix-ui__react-context-menu@2.3.7/LICENSE +21 -0
  788. package/third-party/npm/@radix-ui__react-context-menu@2.3.7/package.json +73 -0
  789. package/third-party/npm/@radix-ui__react-context@1.2.2/LICENSE +21 -0
  790. package/third-party/npm/@radix-ui__react-context@1.2.2/package.json +60 -0
  791. package/third-party/npm/@radix-ui__react-direction@1.1.4/LICENSE +21 -0
  792. package/third-party/npm/@radix-ui__react-direction@1.1.4/package.json +60 -0
  793. package/third-party/npm/@radix-ui__react-dismissable-layer@1.1.19/LICENSE +21 -0
  794. package/third-party/npm/@radix-ui__react-dismissable-layer@1.1.19/package.json +74 -0
  795. package/third-party/npm/@radix-ui__react-focus-guards@1.1.6/LICENSE +21 -0
  796. package/third-party/npm/@radix-ui__react-focus-guards@1.1.6/package.json +60 -0
  797. package/third-party/npm/@radix-ui__react-focus-scope@1.1.16/LICENSE +21 -0
  798. package/third-party/npm/@radix-ui__react-focus-scope@1.1.16/package.json +71 -0
  799. package/third-party/npm/@radix-ui__react-id@1.1.4/LICENSE +21 -0
  800. package/third-party/npm/@radix-ui__react-id@1.1.4/package.json +63 -0
  801. package/third-party/npm/@radix-ui__react-menu@2.1.24/LICENSE +21 -0
  802. package/third-party/npm/@radix-ui__react-menu@2.1.24/package.json +86 -0
  803. package/third-party/npm/@radix-ui__react-popper@1.3.7/LICENSE +21 -0
  804. package/third-party/npm/@radix-ui__react-popper@1.3.7/package.json +78 -0
  805. package/third-party/npm/@radix-ui__react-portal@1.1.17/LICENSE +21 -0
  806. package/third-party/npm/@radix-ui__react-portal@1.1.17/package.json +69 -0
  807. package/third-party/npm/@radix-ui__react-presence@1.1.10/LICENSE +21 -0
  808. package/third-party/npm/@radix-ui__react-presence@1.1.10/package.json +68 -0
  809. package/third-party/npm/@radix-ui__react-primitive@2.1.10/LICENSE +21 -0
  810. package/third-party/npm/@radix-ui__react-primitive@2.1.10/package.json +68 -0
  811. package/third-party/npm/@radix-ui__react-roving-focus@1.1.19/LICENSE +21 -0
  812. package/third-party/npm/@radix-ui__react-roving-focus@1.1.19/package.json +78 -0
  813. package/third-party/npm/@radix-ui__react-slot@1.3.3/LICENSE +21 -0
  814. package/third-party/npm/@radix-ui__react-slot@1.3.3/package.json +63 -0
  815. package/third-party/npm/@radix-ui__react-use-callback-ref@1.1.4/LICENSE +21 -0
  816. package/third-party/npm/@radix-ui__react-use-callback-ref@1.1.4/package.json +60 -0
  817. package/third-party/npm/@radix-ui__react-use-controllable-state@1.2.6/LICENSE +21 -0
  818. package/third-party/npm/@radix-ui__react-use-controllable-state@1.2.6/package.json +65 -0
  819. package/third-party/npm/@radix-ui__react-use-effect-event@0.0.5/LICENSE +21 -0
  820. package/third-party/npm/@radix-ui__react-use-effect-event@0.0.5/package.json +65 -0
  821. package/third-party/npm/@radix-ui__react-use-is-hydrated@0.1.3/LICENSE +21 -0
  822. package/third-party/npm/@radix-ui__react-use-is-hydrated@0.1.3/package.json +61 -0
  823. package/third-party/npm/@radix-ui__react-use-layout-effect@1.1.4/LICENSE +21 -0
  824. package/third-party/npm/@radix-ui__react-use-layout-effect@1.1.4/package.json +60 -0
  825. package/third-party/npm/@radix-ui__react-use-size@1.1.4/LICENSE +21 -0
  826. package/third-party/npm/@radix-ui__react-use-size@1.1.4/package.json +63 -0
  827. package/third-party/npm/aria-hidden@1.2.6/LICENSE +21 -0
  828. package/third-party/npm/aria-hidden@1.2.6/package.json +71 -0
  829. package/third-party/npm/detect-node-es@1.1.0/LICENSE +21 -0
  830. package/third-party/npm/detect-node-es@1.1.0/package.json +29 -0
  831. package/third-party/npm/esbuild@0.27.4/LICENSE.md +21 -0
  832. package/third-party/npm/esbuild@0.27.4/package.json +49 -0
  833. package/third-party/npm/fflate@0.8.3/LICENSE +21 -0
  834. package/third-party/npm/fflate@0.8.3/package.json +128 -0
  835. package/third-party/npm/get-nonce@1.0.1/LICENSE +21 -0
  836. package/third-party/npm/get-nonce@1.0.1/package.json +68 -0
  837. package/third-party/npm/mediabunny@1.52.2/LICENSE +373 -0
  838. package/third-party/npm/mediabunny@1.52.2/package.json +136 -0
  839. package/third-party/npm/mediabunny@1.52.2/source/LICENSE +373 -0
  840. package/third-party/npm/mediabunny@1.52.2/source/package.json +136 -0
  841. package/third-party/npm/mediabunny@1.52.2/source/src/adts/adts-demuxer.ts +400 -0
  842. package/third-party/npm/mediabunny@1.52.2/source/src/adts/adts-muxer.ts +124 -0
  843. package/third-party/npm/mediabunny@1.52.2/source/src/adts/adts-reader.ts +85 -0
  844. package/third-party/npm/mediabunny@1.52.2/source/src/aes.ts +307 -0
  845. package/third-party/npm/mediabunny@1.52.2/source/src/codec-data.ts +3178 -0
  846. package/third-party/npm/mediabunny@1.52.2/source/src/codec.ts +1154 -0
  847. package/third-party/npm/mediabunny@1.52.2/source/src/conversion.ts +2042 -0
  848. package/third-party/npm/mediabunny@1.52.2/source/src/custom-coder.ts +212 -0
  849. package/third-party/npm/mediabunny@1.52.2/source/src/decode.ts +263 -0
  850. package/third-party/npm/mediabunny@1.52.2/source/src/demuxer.ts +43 -0
  851. package/third-party/npm/mediabunny@1.52.2/source/src/encode.ts +1412 -0
  852. package/third-party/npm/mediabunny@1.52.2/source/src/flac/flac-demuxer.ts +813 -0
  853. package/third-party/npm/mediabunny@1.52.2/source/src/flac/flac-misc.ts +165 -0
  854. package/third-party/npm/mediabunny@1.52.2/source/src/flac/flac-muxer.ts +350 -0
  855. package/third-party/npm/mediabunny@1.52.2/source/src/hls/hls-demuxer.ts +995 -0
  856. package/third-party/npm/mediabunny@1.52.2/source/src/hls/hls-misc.ts +81 -0
  857. package/third-party/npm/mediabunny@1.52.2/source/src/hls/hls-muxer.ts +1529 -0
  858. package/third-party/npm/mediabunny@1.52.2/source/src/hls/hls-segmented-input.ts +772 -0
  859. package/third-party/npm/mediabunny@1.52.2/source/src/id3.ts +972 -0
  860. package/third-party/npm/mediabunny@1.52.2/source/src/index.ts +319 -0
  861. package/third-party/npm/mediabunny@1.52.2/source/src/input-format.ts +819 -0
  862. package/third-party/npm/mediabunny@1.52.2/source/src/input-track.ts +1141 -0
  863. package/third-party/npm/mediabunny@1.52.2/source/src/input.ts +571 -0
  864. package/third-party/npm/mediabunny@1.52.2/source/src/isobmff/isobmff-boxes.ts +1911 -0
  865. package/third-party/npm/mediabunny@1.52.2/source/src/isobmff/isobmff-demuxer.ts +3953 -0
  866. package/third-party/npm/mediabunny@1.52.2/source/src/isobmff/isobmff-misc.ts +90 -0
  867. package/third-party/npm/mediabunny@1.52.2/source/src/isobmff/isobmff-muxer.ts +1595 -0
  868. package/third-party/npm/mediabunny@1.52.2/source/src/isobmff/isobmff-reader.ts +91 -0
  869. package/third-party/npm/mediabunny@1.52.2/source/src/logging.ts +120 -0
  870. package/third-party/npm/mediabunny@1.52.2/source/src/matroska/ebml.ts +770 -0
  871. package/third-party/npm/mediabunny@1.52.2/source/src/matroska/matroska-demuxer.ts +2598 -0
  872. package/third-party/npm/mediabunny@1.52.2/source/src/matroska/matroska-misc.ts +29 -0
  873. package/third-party/npm/mediabunny@1.52.2/source/src/matroska/matroska-muxer.ts +1360 -0
  874. package/third-party/npm/mediabunny@1.52.2/source/src/media-sink.ts +2589 -0
  875. package/third-party/npm/mediabunny@1.52.2/source/src/media-source.ts +3041 -0
  876. package/third-party/npm/mediabunny@1.52.2/source/src/metadata.ts +335 -0
  877. package/third-party/npm/mediabunny@1.52.2/source/src/misc.ts +1336 -0
  878. package/third-party/npm/mediabunny@1.52.2/source/src/mp3/mp3-demuxer.ts +469 -0
  879. package/third-party/npm/mediabunny@1.52.2/source/src/mp3/mp3-muxer.ts +169 -0
  880. package/third-party/npm/mediabunny@1.52.2/source/src/mp3/mp3-reader.ts +61 -0
  881. package/third-party/npm/mediabunny@1.52.2/source/src/mp3/mp3-writer.ts +121 -0
  882. package/third-party/npm/mediabunny@1.52.2/source/src/mpeg-ts/mpeg-ts-demuxer.ts +2519 -0
  883. package/third-party/npm/mediabunny@1.52.2/source/src/mpeg-ts/mpeg-ts-misc.ts +32 -0
  884. package/third-party/npm/mediabunny@1.52.2/source/src/mpeg-ts/mpeg-ts-muxer.ts +842 -0
  885. package/third-party/npm/mediabunny@1.52.2/source/src/muxer.ts +80 -0
  886. package/third-party/npm/mediabunny@1.52.2/source/src/node.ts +11 -0
  887. package/third-party/npm/mediabunny@1.52.2/source/src/ogg/ogg-demuxer.ts +1087 -0
  888. package/third-party/npm/mediabunny@1.52.2/source/src/ogg/ogg-misc.ts +116 -0
  889. package/third-party/npm/mediabunny@1.52.2/source/src/ogg/ogg-muxer.ts +527 -0
  890. package/third-party/npm/mediabunny@1.52.2/source/src/ogg/ogg-reader.ts +93 -0
  891. package/third-party/npm/mediabunny@1.52.2/source/src/output-format.ts +1425 -0
  892. package/third-party/npm/mediabunny@1.52.2/source/src/output.ts +940 -0
  893. package/third-party/npm/mediabunny@1.52.2/source/src/packet.ts +287 -0
  894. package/third-party/npm/mediabunny@1.52.2/source/src/pcm.ts +112 -0
  895. package/third-party/npm/mediabunny@1.52.2/source/src/reader.ts +391 -0
  896. package/third-party/npm/mediabunny@1.52.2/source/src/resample.ts +287 -0
  897. package/third-party/npm/mediabunny@1.52.2/source/src/sample.ts +3231 -0
  898. package/third-party/npm/mediabunny@1.52.2/source/src/segmented-input.ts +575 -0
  899. package/third-party/npm/mediabunny@1.52.2/source/src/source.ts +2588 -0
  900. package/third-party/npm/mediabunny@1.52.2/source/src/subtitles.ts +131 -0
  901. package/third-party/npm/mediabunny@1.52.2/source/src/target.ts +871 -0
  902. package/third-party/npm/mediabunny@1.52.2/source/src/tsconfig.json +16 -0
  903. package/third-party/npm/mediabunny@1.52.2/source/src/wave/riff-writer.ts +36 -0
  904. package/third-party/npm/mediabunny@1.52.2/source/src/wave/wave-demuxer.ts +583 -0
  905. package/third-party/npm/mediabunny@1.52.2/source/src/wave/wave-muxer.ts +375 -0
  906. package/third-party/npm/mediabunny@1.52.2/source/src/writer.ts +128 -0
  907. package/third-party/npm/react-dom@19.3.0/LICENSE +21 -0
  908. package/third-party/npm/react-dom@19.3.0/package.json +117 -0
  909. package/third-party/npm/react-remove-scroll-bar@2.3.8/package.json +85 -0
  910. package/third-party/npm/react-remove-scroll-bar@2.3.8/react-remove-scroll-bar-LICENSE +21 -0
  911. package/third-party/npm/react-remove-scroll@2.7.2/LICENSE +21 -0
  912. package/third-party/npm/react-remove-scroll@2.7.2/package.json +98 -0
  913. package/third-party/npm/react-style-singleton@2.2.3/LICENSE +21 -0
  914. package/third-party/npm/react-style-singleton@2.2.3/package.json +90 -0
  915. package/third-party/npm/react@19.3.0/LICENSE +21 -0
  916. package/third-party/npm/react@19.3.0/package.json +51 -0
  917. package/third-party/npm/scheduler@0.28.0/LICENSE +21 -0
  918. package/third-party/npm/scheduler@0.28.0/package.json +27 -0
  919. package/third-party/npm/tslib@2.8.1/LICENSE.txt +12 -0
  920. package/third-party/npm/tslib@2.8.1/package.json +47 -0
  921. package/third-party/npm/typescript@5.9.3/LICENSE.txt +55 -0
  922. package/third-party/npm/typescript@5.9.3/ThirdPartyNoticeText.txt +193 -0
  923. package/third-party/npm/typescript@5.9.3/package.json +120 -0
  924. package/third-party/npm/use-callback-ref@1.3.3/LICENSE +21 -0
  925. package/third-party/npm/use-callback-ref@1.3.3/package.json +85 -0
  926. package/third-party/npm/use-sidecar@1.1.3/LICENSE +21 -0
  927. package/third-party/npm/use-sidecar@1.1.3/package.json +93 -0
  928. package/third-party/packages/render-engine/assets/OFL.txt +93 -0
  929. package/third-party/packages/studio/public/fonts/OFL.txt +93 -0
  930. package/third-party/packages/studio/vendor/osmo-icons/LICENSE +21 -0
  931. package/third-party/packages/studio/vendor/shadcn/LICENSE +21 -0
  932. package/third-party/repository-notices.md +41 -0
  933. package/third-party/rust-standard-library/COPYRIGHT-library.html +5556 -0
  934. package/third-party/rust-standard-library/licenses/Apache-2.0.txt +73 -0
  935. package/third-party/rust-standard-library/licenses/BSD-2-Clause.txt +9 -0
  936. package/third-party/rust-standard-library/licenses/CC-BY-SA-4.0.txt +427 -0
  937. package/third-party/rust-standard-library/licenses/GCC-exception-3.1.txt +30 -0
  938. package/third-party/rust-standard-library/licenses/GPL-2.0-only.txt +133 -0
  939. package/third-party/rust-standard-library/licenses/GPL-3.0-or-later.txt +202 -0
  940. package/third-party/rust-standard-library/licenses/ISC.txt +7 -0
  941. package/third-party/rust-standard-library/licenses/LLVM-exception.txt +15 -0
  942. package/third-party/rust-standard-library/licenses/MIT.txt +9 -0
  943. package/third-party/rust-standard-library/licenses/NCSA.txt +29 -0
  944. package/third-party/rust-standard-library/licenses/OFL-1.1.txt +43 -0
  945. package/third-party/rust-standard-library/licenses/Unicode-3.0.txt +39 -0
  946. package/third-party/rust-standard-library/version.txt +1 -0
  947. package/vendor/osmo-lite +0 -0
  948. package/vendor/osmo-scene-0.1.0.tgz +0 -0
  949. package/vendor/platform.json +1 -0
@@ -0,0 +1,2598 @@
1
+ /*!
2
+ * Copyright (c) 2026-present, Vanilagy and contributors
3
+ *
4
+ * This Source Code Form is subject to the terms of the Mozilla Public
5
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
9
+ import { TrackType } from '../output';
10
+ import {
11
+ extractAv1CodecInfoFromPacket,
12
+ extractAvcDecoderConfigurationRecord,
13
+ extractHevcDecoderConfigurationRecord,
14
+ extractVp9CodecInfoFromPacket,
15
+ } from '../codec-data';
16
+ import {
17
+ AacCodecInfo,
18
+ AudioCodec,
19
+ extractAudioCodecString,
20
+ extractVideoCodecString,
21
+ MediaCodec,
22
+ OPUS_SAMPLE_RATE,
23
+ PRORES_FOURCCS,
24
+ ProresFourCc,
25
+ VideoCodec,
26
+ } from '../codec';
27
+ import { Demuxer } from '../demuxer';
28
+ import { Input } from '../input';
29
+ import { Logging } from '../logging';
30
+ import {
31
+ InputAudioTrackBacking,
32
+ InputTrackBacking,
33
+ InputVideoTrackBacking,
34
+ } from '../input-track';
35
+ import { AttachedFile, DEFAULT_TRACK_DISPOSITION, MetadataTags, TrackDisposition } from '../metadata';
36
+ import { PacketRetrievalOptions } from '../media-sink';
37
+ import {
38
+ assert,
39
+ binarySearchLessOrEqual,
40
+ COLOR_PRIMARIES_MAP_INVERSE,
41
+ findLastIndex,
42
+ isIso639Dash2LanguageCode,
43
+ last,
44
+ MATRIX_COEFFICIENTS_MAP_INVERSE,
45
+ normalizeRotation,
46
+ Rotation,
47
+ roundIfAlmostInteger,
48
+ textDecoder,
49
+ toDataView,
50
+ TRANSFER_CHARACTERISTICS_MAP_INVERSE,
51
+ UNDETERMINED_LANGUAGE,
52
+ } from '../misc';
53
+ import { EncodedPacket, EncodedPacketSideData, PLACEHOLDER_DATA } from '../packet';
54
+ import {
55
+ assertDefinedSize,
56
+ CODEC_STRING_MAP,
57
+ EBMLId,
58
+ LEVEL_0_AND_1_EBML_IDS,
59
+ LEVEL_1_EBML_IDS,
60
+ MAX_HEADER_SIZE,
61
+ MIN_HEADER_SIZE,
62
+ readAsciiString,
63
+ readUnicodeString,
64
+ readElementHeader,
65
+ readElementId,
66
+ readFloat,
67
+ readUnsignedInt,
68
+ readVarInt,
69
+ resync,
70
+ searchForNextElementId,
71
+ readUnsignedBigInt,
72
+ } from './ebml';
73
+ import { buildMatroskaMimeType } from './matroska-misc';
74
+ import { FileSlice, readBytes, Reader, readI16Be, readU8 } from '../reader';
75
+
76
+ type Segment = {
77
+ seekHeadSeen: boolean;
78
+ infoSeen: boolean;
79
+ tracksSeen: boolean;
80
+ cuesSeen: boolean;
81
+ attachmentsSeen: boolean;
82
+ tagsSeen: boolean;
83
+
84
+ timestampScale: number;
85
+ timestampFactor: number;
86
+ duration: number;
87
+ seekEntries: SeekEntry[];
88
+ tracks: InternalTrack[];
89
+ cuePoints: CuePoint[];
90
+
91
+ dataStartPos: number;
92
+ elementEndPos: number | null;
93
+ clusterSeekStartPos: number;
94
+
95
+ /**
96
+ * Caches the last cluster that was read. Based on the assumption that there will be multiple reads to the
97
+ * same cluster in quick succession.
98
+ */
99
+ lastReadCluster: Cluster | null;
100
+
101
+ metadataTags: MetadataTags;
102
+ metadataTagsCollected: boolean;
103
+ };
104
+
105
+ type SeekEntry = {
106
+ id: number;
107
+ segmentPosition: number;
108
+ };
109
+
110
+ type Cluster = {
111
+ segment: Segment;
112
+ elementStartPos: number;
113
+ elementEndPos: number;
114
+ dataStartPos: number;
115
+ timestamp: number;
116
+ trackData: Map<number, ClusterTrackData>;
117
+ };
118
+
119
+ type ClusterTrackData = {
120
+ track: InternalTrack;
121
+ startTimestamp: number;
122
+ endTimestamp: number;
123
+ firstKeyFrameTimestamp: number | null;
124
+ blocks: ClusterBlock[];
125
+ presentationTimestamps: {
126
+ timestamp: number;
127
+ blockIndex: number;
128
+ }[];
129
+ };
130
+
131
+ enum BlockLacing {
132
+ None,
133
+ Xiph,
134
+ FixedSize,
135
+ Ebml,
136
+ }
137
+
138
+ type ClusterBlock = {
139
+ timestamp: number;
140
+ duration: number;
141
+ isKeyFrame: boolean;
142
+ data: Uint8Array;
143
+ lacing: BlockLacing;
144
+ decoded: boolean;
145
+ postProcessed: boolean; // For codec-specific processing
146
+ mainAdditional: Uint8Array | null;
147
+ };
148
+
149
+ type CuePoint = {
150
+ time: number;
151
+ trackId: number;
152
+ clusterPosition: number;
153
+ };
154
+
155
+ enum ContentEncodingScope {
156
+ Block = 1,
157
+ Private = 2,
158
+ Next = 4,
159
+ }
160
+
161
+ enum ContentCompAlgo {
162
+ Zlib,
163
+ Bzlib,
164
+ lzo1x,
165
+ HeaderStripping,
166
+ }
167
+
168
+ type DecodingInstruction = {
169
+ order: number;
170
+ scope: ContentEncodingScope;
171
+ data: {
172
+ type: 'decompress';
173
+ algorithm: ContentCompAlgo | null;
174
+ settings: Uint8Array | null;
175
+ } | {
176
+ type: 'decrypt';
177
+ // Don't store more yet since this operation is unsupported
178
+ } | null;
179
+ };
180
+
181
+ type InternalTrack = {
182
+ id: number;
183
+ demuxer: MatroskaDemuxer;
184
+ segment: Segment;
185
+ /**
186
+ * List of all encountered cluster offsets alongside their timestamps. This list never gets truncated, but memory
187
+ * consumption should be negligible.
188
+ */
189
+ clusterPositionCache: {
190
+ elementStartPos: number;
191
+ startTimestamp: number;
192
+ }[];
193
+ cuePoints: CuePoint[];
194
+
195
+ disposition: TrackDisposition;
196
+ trackBacking: InputTrackBacking | null;
197
+ codecId: string | null;
198
+ codecPrivate: Uint8Array | null;
199
+ defaultDuration: number | null;
200
+ defaultDurationNs: number | null;
201
+ name: string | null;
202
+ languageCode: string;
203
+ hasLanguageBcp47: boolean;
204
+ decodingInstructions: DecodingInstruction[];
205
+
206
+ info:
207
+ | null
208
+ | {
209
+ type: 'video';
210
+ width: number;
211
+ height: number;
212
+ displayWidth: number | null;
213
+ displayHeight: number | null;
214
+ displayUnit: number | null;
215
+ squarePixelWidth: number;
216
+ squarePixelHeight: number;
217
+ rotation: Rotation;
218
+ codec: VideoCodec | null;
219
+ codecDescription: Uint8Array | null;
220
+ colorSpace: VideoColorSpaceInit | null;
221
+ alphaMode: boolean;
222
+ proresFormat: ProresFourCc | null;
223
+ }
224
+ | {
225
+ type: 'audio';
226
+ numberOfChannels: number;
227
+ sampleRate: number;
228
+ bitDepth: number;
229
+ codec: AudioCodec | null;
230
+ codecDescription: Uint8Array | null;
231
+ aacCodecInfo: AacCodecInfo | null;
232
+ };
233
+ };
234
+ type InternalVideoTrack = InternalTrack & { info: { type: 'video' } };
235
+ type InternalAudioTrack = InternalTrack & { info: { type: 'audio' } };
236
+
237
+ const METADATA_ELEMENTS = [
238
+ { id: EBMLId.SeekHead, flag: 'seekHeadSeen' },
239
+ { id: EBMLId.Info, flag: 'infoSeen' },
240
+ { id: EBMLId.Tracks, flag: 'tracksSeen' },
241
+ { id: EBMLId.Cues, flag: 'cuesSeen' },
242
+ ] as const;
243
+ const MAX_RESYNC_LENGTH = 10 * 2 ** 20; // 10 MiB
244
+
245
+ export class MatroskaDemuxer extends Demuxer {
246
+ reader: Reader;
247
+
248
+ readMetadataPromise: Promise<void> | null = null;
249
+
250
+ segments: Segment[] = [];
251
+ currentSegment: Segment | null = null;
252
+ currentTrack: InternalTrack | null = null;
253
+ currentCluster: Cluster | null = null;
254
+ currentBlock: ClusterBlock | null = null;
255
+ currentBlockAdditional: {
256
+ addId: number;
257
+ data: Uint8Array | null;
258
+ } | null = null;
259
+
260
+ currentCueTime: number | null = null;
261
+ currentDecodingInstruction: DecodingInstruction | null = null;
262
+ currentTagTargetIsMovie: boolean = true;
263
+ currentSimpleTagName: string | null = null;
264
+ currentAttachedFile: {
265
+ fileUid: bigint | null;
266
+ fileName: string | null;
267
+ fileMediaType: string | null;
268
+ fileData: Uint8Array | null;
269
+ fileDescription: string | null;
270
+ } | null = null;
271
+
272
+ isWebM = false;
273
+
274
+ constructor(input: Input) {
275
+ super(input);
276
+
277
+ this.reader = input._reader;
278
+ }
279
+
280
+ async getTrackBackings() {
281
+ await this.readMetadata();
282
+ return this.segments.flatMap(segment => segment.tracks.map(track => track.trackBacking!));
283
+ }
284
+
285
+ override async getMimeType() {
286
+ await this.readMetadata();
287
+
288
+ const backings = await this.getTrackBackings();
289
+ const codecStrings = await Promise.all(backings.map(
290
+ x => x.getDecoderConfig().then(c => c?.codec ?? null),
291
+ ));
292
+
293
+ return buildMatroskaMimeType({
294
+ isWebM: this.isWebM,
295
+ hasVideo: this.segments.some(segment => segment.tracks.some(x => x.info?.type === 'video')),
296
+ hasAudio: this.segments.some(segment => segment.tracks.some(x => x.info?.type === 'audio')),
297
+ codecStrings: codecStrings.filter(Boolean) as string[],
298
+ });
299
+ }
300
+
301
+ async getMetadataTags() {
302
+ await this.readMetadata();
303
+
304
+ // Load metadata tags from each segment lazily (only once)
305
+ for (const segment of this.segments) {
306
+ if (!segment.metadataTagsCollected) {
307
+ if (this.reader.fileSize !== null) {
308
+ await this.loadSegmentMetadata(segment);
309
+ } else {
310
+ // The seeking would be too crazy, let's not
311
+ }
312
+
313
+ segment.metadataTagsCollected = true;
314
+ }
315
+ }
316
+
317
+ // This is kinda handwavy, and how we handle multiple segments isn't suuuuper well-defined anyway; so we just
318
+ // shallow-merge metadata tags from all (usually just one) segments.
319
+ let metadataTags: MetadataTags = {};
320
+ for (const segment of this.segments) {
321
+ metadataTags = { ...metadataTags, ...segment.metadataTags };
322
+ }
323
+
324
+ return metadataTags;
325
+ }
326
+
327
+ readMetadata() {
328
+ return this.readMetadataPromise ??= (async () => {
329
+ let currentPos = 0;
330
+
331
+ // Loop over all top-level elements in the file
332
+ while (true) {
333
+ let slice = this.reader.requestSliceRange(currentPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
334
+ if (slice instanceof Promise) slice = await slice;
335
+ if (!slice) break;
336
+
337
+ const header = readElementHeader(slice);
338
+ if (!header) {
339
+ break; // Zero padding at the end of the file triggers this, for example
340
+ }
341
+
342
+ const id = header.id;
343
+ let size = header.size;
344
+ const dataStartPos = slice.filePos;
345
+
346
+ if (id === EBMLId.EBML) {
347
+ assertDefinedSize(size);
348
+
349
+ let slice = this.reader.requestSlice(dataStartPos, size);
350
+ if (slice instanceof Promise) slice = await slice;
351
+ if (!slice) break;
352
+
353
+ this.readContiguousElements(slice);
354
+ } else if (id === EBMLId.Segment) { // Segment found!
355
+ await this.readSegment(dataStartPos, size);
356
+
357
+ if (size === undefined) {
358
+ // Segment sizes can be undefined (common in livestreamed files), so assume this is the last
359
+ // and only segment
360
+ break;
361
+ }
362
+
363
+ if (this.reader.fileSize === null) {
364
+ break; // Stop at the first segment
365
+ }
366
+ } else if (id === EBMLId.Cluster) {
367
+ if (this.reader.fileSize === null) {
368
+ break; // Shouldn't be reached anyway, since we stop at the first segment
369
+ }
370
+
371
+ // Clusters are not a top-level element in Matroska, but some files contain a Segment whose size
372
+ // doesn't contain any of the clusters that follow it. In the case, we apply the following logic: if
373
+ // we find a top-level cluster, attribute it to the previous segment.
374
+
375
+ if (size === undefined) {
376
+ // Just in case this is one of those weird sizeless clusters, let's do our best and still try to
377
+ // determine its size.
378
+ const nextElementPos = await searchForNextElementId(
379
+ this.reader,
380
+ dataStartPos,
381
+ LEVEL_0_AND_1_EBML_IDS,
382
+ this.reader.fileSize,
383
+ );
384
+ size = nextElementPos.pos - dataStartPos;
385
+ }
386
+
387
+ const lastSegment = last(this.segments);
388
+ if (lastSegment) {
389
+ // Extend the previous segment's size
390
+ lastSegment.elementEndPos = dataStartPos + size;
391
+ }
392
+ }
393
+
394
+ assertDefinedSize(size);
395
+ currentPos = dataStartPos + size;
396
+ }
397
+ })();
398
+ }
399
+
400
+ async readSegment(segmentDataStart: number, dataSize: number | undefined) {
401
+ this.currentSegment = {
402
+ seekHeadSeen: false,
403
+ infoSeen: false,
404
+ tracksSeen: false,
405
+ cuesSeen: false,
406
+ tagsSeen: false,
407
+ attachmentsSeen: false,
408
+
409
+ timestampScale: -1,
410
+ timestampFactor: -1,
411
+ duration: -1,
412
+ seekEntries: [],
413
+ tracks: [],
414
+ cuePoints: [],
415
+
416
+ dataStartPos: segmentDataStart,
417
+ elementEndPos: dataSize === undefined
418
+ ? null // Assume it goes until the end of the file
419
+ : segmentDataStart + dataSize,
420
+ clusterSeekStartPos: segmentDataStart,
421
+
422
+ lastReadCluster: null,
423
+
424
+ metadataTags: {},
425
+ metadataTagsCollected: false,
426
+ };
427
+ this.segments.push(this.currentSegment);
428
+
429
+ let currentPos = segmentDataStart;
430
+
431
+ while (this.currentSegment.elementEndPos === null || currentPos < this.currentSegment.elementEndPos) {
432
+ let slice = this.reader.requestSliceRange(currentPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
433
+ if (slice instanceof Promise) slice = await slice;
434
+ if (!slice) break;
435
+
436
+ const elementStartPos = currentPos;
437
+ const header = readElementHeader(slice);
438
+
439
+ if (!header || (!LEVEL_1_EBML_IDS.includes(header.id) && header.id !== EBMLId.Void)) {
440
+ // Potential junk. Let's try to resync
441
+
442
+ const nextPos = await resync(
443
+ this.reader,
444
+ elementStartPos,
445
+ LEVEL_1_EBML_IDS,
446
+ Math.min(this.currentSegment.elementEndPos ?? Infinity, elementStartPos + MAX_RESYNC_LENGTH),
447
+ );
448
+
449
+ if (nextPos) {
450
+ currentPos = nextPos;
451
+ continue;
452
+ } else {
453
+ break; // Resync failed
454
+ }
455
+ }
456
+
457
+ const { id, size } = header;
458
+ const dataStartPos = slice.filePos;
459
+
460
+ const metadataElementIndex = METADATA_ELEMENTS.findIndex(x => x.id === id);
461
+ if (metadataElementIndex !== -1) {
462
+ const field = METADATA_ELEMENTS[metadataElementIndex]!.flag;
463
+ this.currentSegment[field] = true;
464
+
465
+ assertDefinedSize(size);
466
+
467
+ let slice = this.reader.requestSlice(dataStartPos, size);
468
+ if (slice instanceof Promise) slice = await slice;
469
+
470
+ if (slice) {
471
+ this.readContiguousElements(slice);
472
+ }
473
+ } else if (id === EBMLId.Tags || id === EBMLId.Attachments) {
474
+ // Metadata found at the beginning of the segment, great, let's parse it
475
+ if (id === EBMLId.Tags) {
476
+ this.currentSegment.tagsSeen = true;
477
+ } else {
478
+ this.currentSegment.attachmentsSeen = true;
479
+ }
480
+
481
+ assertDefinedSize(size);
482
+
483
+ let slice = this.reader.requestSlice(dataStartPos, size);
484
+ if (slice instanceof Promise) slice = await slice;
485
+
486
+ if (slice) {
487
+ this.readContiguousElements(slice);
488
+ }
489
+ } else if (id === EBMLId.Cluster) {
490
+ this.currentSegment.clusterSeekStartPos = elementStartPos;
491
+ break; // Stop at the first cluster
492
+ }
493
+
494
+ if (size === undefined) {
495
+ break;
496
+ } else {
497
+ currentPos = dataStartPos + size;
498
+ }
499
+ }
500
+
501
+ // Sort the seek entries by file position so reading them exhibits a sequential pattern
502
+ this.currentSegment.seekEntries.sort((a, b) => a.segmentPosition - b.segmentPosition);
503
+
504
+ if (this.reader.fileSize !== null) {
505
+ // Use the seek head to read missing metadata elements
506
+ for (const seekEntry of this.currentSegment.seekEntries) {
507
+ const target = METADATA_ELEMENTS.find(x => x.id === seekEntry.id);
508
+ if (!target) {
509
+ continue;
510
+ }
511
+
512
+ if (this.currentSegment[target.flag]) continue;
513
+
514
+ let slice = this.reader.requestSliceRange(
515
+ segmentDataStart + seekEntry.segmentPosition,
516
+ MIN_HEADER_SIZE,
517
+ MAX_HEADER_SIZE,
518
+ );
519
+ if (slice instanceof Promise) slice = await slice;
520
+ if (!slice) continue;
521
+
522
+ const header = readElementHeader(slice);
523
+ if (!header) continue;
524
+
525
+ const { id, size } = header;
526
+ if (id !== target.id) continue;
527
+
528
+ assertDefinedSize(size);
529
+
530
+ this.currentSegment[target.flag] = true;
531
+
532
+ let dataSlice = this.reader.requestSlice(slice.filePos, size);
533
+ if (dataSlice instanceof Promise) dataSlice = await dataSlice;
534
+ if (!dataSlice) continue;
535
+
536
+ this.readContiguousElements(dataSlice);
537
+ }
538
+ }
539
+
540
+ if (this.currentSegment.timestampScale === -1) {
541
+ // TimestampScale element is missing. Technically an invalid file, but let's default to the typical value,
542
+ // which is 1e6.
543
+ this.currentSegment.timestampScale = 1e6;
544
+ this.currentSegment.timestampFactor = 1e9 / 1e6;
545
+ }
546
+
547
+ // Compute default duration for all tracks now that we have the timestamp factor
548
+ for (const track of this.currentSegment.tracks) {
549
+ if (track.defaultDurationNs !== null) {
550
+ track.defaultDuration = (this.currentSegment.timestampFactor * track.defaultDurationNs) / 1e9;
551
+ }
552
+ }
553
+
554
+ // Now, let's distribute the cue points to the tracks
555
+ const idToTrack = new Map(this.currentSegment.tracks.map(x => [x.id, x]));
556
+
557
+ // Assign cue points to their respective tracks
558
+ for (const cuePoint of this.currentSegment.cuePoints) {
559
+ const track = idToTrack.get(cuePoint.trackId);
560
+ if (track) {
561
+ track.cuePoints.push(cuePoint);
562
+ }
563
+ }
564
+
565
+ for (const track of this.currentSegment.tracks) {
566
+ // Sort cue points by time
567
+ track.cuePoints.sort((a, b) => a.time - b.time);
568
+
569
+ // Remove multiple cue points for the same time
570
+ for (let i = 0; i < track.cuePoints.length - 1; i++) {
571
+ const cuePoint1 = track.cuePoints[i]!;
572
+ const cuePoint2 = track.cuePoints[i + 1]!;
573
+
574
+ if (cuePoint1.time === cuePoint2.time) {
575
+ track.cuePoints.splice(i + 1, 1);
576
+ i--;
577
+ }
578
+ }
579
+ }
580
+
581
+ let trackWithMostCuePoints: InternalTrack | null = null;
582
+ let maxCuePointCount = -Infinity;
583
+ for (const track of this.currentSegment.tracks) {
584
+ if (track.cuePoints.length > maxCuePointCount) {
585
+ maxCuePointCount = track.cuePoints.length;
586
+ trackWithMostCuePoints = track;
587
+ }
588
+ }
589
+
590
+ // For every track that has received 0 cue points (can happen, often only the video track receives cue points),
591
+ // we still want to have better seeking. Therefore, let's give it the cue points of the track with the most cue
592
+ // points, which should provide us with the most fine-grained seeking.
593
+ for (const track of this.currentSegment.tracks) {
594
+ if (track.cuePoints.length === 0) {
595
+ track.cuePoints = trackWithMostCuePoints!.cuePoints;
596
+ }
597
+ }
598
+
599
+ this.currentSegment = null;
600
+ }
601
+
602
+ async readCluster(startPos: number, segment: Segment) {
603
+ if (segment.lastReadCluster?.elementStartPos === startPos) {
604
+ return segment.lastReadCluster;
605
+ }
606
+
607
+ let headerSlice = this.reader.requestSliceRange(startPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
608
+ if (headerSlice instanceof Promise) headerSlice = await headerSlice;
609
+ assert(headerSlice);
610
+
611
+ const elementStartPos = startPos;
612
+ const elementHeader = readElementHeader(headerSlice);
613
+ assert(elementHeader);
614
+
615
+ const id = elementHeader.id;
616
+ assert(id === EBMLId.Cluster);
617
+
618
+ let size = elementHeader.size;
619
+ const dataStartPos = headerSlice.filePos;
620
+
621
+ if (size === undefined) {
622
+ // The cluster's size is undefined (can happen in livestreamed files). We'd still like to know the size of
623
+ // it, so we have no other choice but to iterate over the EBML structure until we find an element at level
624
+ // 0 or 1, indicating the end of the cluster (all elements inside the cluster are at level 2).
625
+ const nextElementPos = await searchForNextElementId(
626
+ this.reader,
627
+ dataStartPos,
628
+ LEVEL_0_AND_1_EBML_IDS,
629
+ segment.elementEndPos,
630
+ );
631
+
632
+ size = nextElementPos.pos - dataStartPos;
633
+ }
634
+
635
+ // Load the entire cluster
636
+ let dataSlice = this.reader.requestSlice(dataStartPos, size);
637
+ if (dataSlice instanceof Promise) dataSlice = await dataSlice;
638
+
639
+ const cluster: Cluster = {
640
+ segment,
641
+ elementStartPos,
642
+ elementEndPos: dataStartPos + size,
643
+ dataStartPos,
644
+ timestamp: -1,
645
+ trackData: new Map(),
646
+ };
647
+ this.currentCluster = cluster;
648
+
649
+ if (dataSlice) {
650
+ // Read the children of the cluster, stopping early at level 0 or 1 EBML elements. We do this because some
651
+ // clusters have incorrect sizes that are too large
652
+ const endPos = this.readContiguousElements(dataSlice, LEVEL_0_AND_1_EBML_IDS);
653
+ cluster.elementEndPos = endPos;
654
+ }
655
+
656
+ for (const [, trackData] of cluster.trackData) {
657
+ const track = trackData.track;
658
+
659
+ // This must hold, as track datas only get created if a block for that track is encountered
660
+ assert(trackData.blocks.length > 0);
661
+
662
+ let hasLacedBlocks = false;
663
+
664
+ for (let i = 0; i < trackData.blocks.length; i++) {
665
+ const block = trackData.blocks[i]!;
666
+ block.timestamp += cluster.timestamp;
667
+
668
+ hasLacedBlocks ||= block.lacing !== BlockLacing.None;
669
+ }
670
+
671
+ trackData.presentationTimestamps = trackData.blocks
672
+ .map((block, i) => ({ timestamp: block.timestamp, blockIndex: i }))
673
+ .sort((a, b) => a.timestamp - b.timestamp);
674
+
675
+ for (let i = 0; i < trackData.presentationTimestamps.length; i++) {
676
+ const currentEntry = trackData.presentationTimestamps[i]!;
677
+ const currentBlock = trackData.blocks[currentEntry.blockIndex]!;
678
+
679
+ if (trackData.firstKeyFrameTimestamp === null && currentBlock.isKeyFrame) {
680
+ trackData.firstKeyFrameTimestamp = currentBlock.timestamp;
681
+ }
682
+
683
+ if (i < trackData.presentationTimestamps.length - 1) {
684
+ // Update block durations based on presentation order
685
+ const nextEntry = trackData.presentationTimestamps[i + 1]!;
686
+ currentBlock.duration = nextEntry.timestamp - currentBlock.timestamp;
687
+ } else if (currentBlock.duration === 0) {
688
+ if (track.defaultDuration != null) {
689
+ if (currentBlock.lacing === BlockLacing.None) {
690
+ currentBlock.duration = track.defaultDuration;
691
+ } else {
692
+ // Handled by the lace resolution code
693
+ }
694
+ }
695
+ }
696
+ }
697
+
698
+ if (hasLacedBlocks) {
699
+ // Perform lace resolution. Here, we expand each laced block into multiple blocks where each contains
700
+ // one frame of the lace. We do this after determining block timestamps so we can properly distribute
701
+ // the block's duration across the laced frames.
702
+ this.expandLacedBlocks(trackData.blocks, track);
703
+
704
+ // Recompute since blocks have changed
705
+ trackData.presentationTimestamps = trackData.blocks
706
+ .map((block, i) => ({ timestamp: block.timestamp, blockIndex: i }))
707
+ .sort((a, b) => a.timestamp - b.timestamp);
708
+ }
709
+
710
+ const firstBlock = trackData.blocks[trackData.presentationTimestamps[0]!.blockIndex]!;
711
+ const lastBlock = trackData.blocks[last(trackData.presentationTimestamps)!.blockIndex]!;
712
+
713
+ trackData.startTimestamp = firstBlock.timestamp;
714
+ trackData.endTimestamp = lastBlock.timestamp + lastBlock.duration;
715
+
716
+ // Let's remember that a cluster with a given timestamp is here, speeding up future lookups if no cues exist
717
+ const insertionIndex = binarySearchLessOrEqual(
718
+ track.clusterPositionCache,
719
+ trackData.startTimestamp,
720
+ x => x.startTimestamp,
721
+ );
722
+ if (
723
+ insertionIndex === -1
724
+ || track.clusterPositionCache[insertionIndex]!.elementStartPos !== elementStartPos
725
+ ) {
726
+ track.clusterPositionCache.splice(insertionIndex + 1, 0, {
727
+ elementStartPos: cluster.elementStartPos,
728
+ startTimestamp: trackData.startTimestamp,
729
+ });
730
+ }
731
+ }
732
+
733
+ segment.lastReadCluster = cluster;
734
+ return cluster;
735
+ }
736
+
737
+ getTrackDataInCluster(cluster: Cluster, trackNumber: number) {
738
+ let trackData = cluster.trackData.get(trackNumber);
739
+ if (!trackData) {
740
+ const track = cluster.segment.tracks.find(x => x.id === trackNumber);
741
+ if (!track) {
742
+ return null;
743
+ }
744
+
745
+ trackData = {
746
+ track,
747
+ startTimestamp: 0,
748
+ endTimestamp: 0,
749
+ firstKeyFrameTimestamp: null,
750
+ blocks: [],
751
+ presentationTimestamps: [],
752
+ };
753
+ cluster.trackData.set(trackNumber, trackData);
754
+ }
755
+
756
+ return trackData;
757
+ }
758
+
759
+ expandLacedBlocks(blocks: ClusterBlock[], track: InternalTrack) {
760
+ // https://www.matroska.org/technical/notes.html#block-lacing
761
+
762
+ for (let blockIndex = 0; blockIndex < blocks.length; blockIndex++) {
763
+ const originalBlock = blocks[blockIndex]!;
764
+ if (originalBlock.lacing === BlockLacing.None) {
765
+ continue;
766
+ }
767
+
768
+ // Decode the block data if it hasn't been decoded yet (needed for lacing expansion)
769
+ if (!originalBlock.decoded) {
770
+ originalBlock.data = this.decodeBlockData(track, originalBlock.data);
771
+ originalBlock.decoded = true;
772
+ }
773
+
774
+ const slice = FileSlice.tempFromBytes(originalBlock.data);
775
+
776
+ const frameSizes: number[] = [];
777
+ const frameCount = readU8(slice) + 1;
778
+
779
+ switch (originalBlock.lacing) {
780
+ case BlockLacing.Xiph: {
781
+ let totalUsedSize = 0;
782
+
783
+ // Xiph lacing, just like in Ogg
784
+ for (let i = 0; i < frameCount - 1; i++) {
785
+ let frameSize = 0;
786
+
787
+ while (slice.bufferPos < slice.length) {
788
+ const value = readU8(slice);
789
+ frameSize += value;
790
+
791
+ if (value < 255) {
792
+ frameSizes.push(frameSize);
793
+ totalUsedSize += frameSize;
794
+
795
+ break;
796
+ }
797
+ }
798
+ }
799
+
800
+ // Compute the last frame's size from whatever's left
801
+ frameSizes.push(slice.length - (slice.bufferPos + totalUsedSize));
802
+ }; break;
803
+
804
+ case BlockLacing.FixedSize: {
805
+ // Fixed size lacing: all frames have same size
806
+ const totalDataSize = slice.length - 1; // Minus the frame count byte
807
+ const frameSize = Math.floor(totalDataSize / frameCount);
808
+
809
+ for (let i = 0; i < frameCount; i++) {
810
+ frameSizes.push(frameSize);
811
+ }
812
+ }; break;
813
+
814
+ case BlockLacing.Ebml: {
815
+ // EBML lacing: first size absolute, subsequent ones are coded as signed differences from the last
816
+ const firstResult = readVarInt(slice);
817
+ assert(firstResult !== null); // Assume it's not an invalid VINT
818
+
819
+ let currentSize = firstResult;
820
+ frameSizes.push(currentSize);
821
+
822
+ let totalUsedSize = currentSize;
823
+
824
+ for (let i = 1; i < frameCount - 1; i++) {
825
+ const startPos = slice.bufferPos;
826
+ const diffResult = readVarInt(slice);
827
+ assert(diffResult !== null);
828
+
829
+ const unsignedDiff = diffResult;
830
+ const width = slice.bufferPos - startPos;
831
+ const bias = (1 << (width * 7 - 1)) - 1; // Typo-corrected version of 2^((7*n)-1)^-1
832
+ const diff = unsignedDiff - bias;
833
+
834
+ currentSize += diff;
835
+ frameSizes.push(currentSize);
836
+
837
+ totalUsedSize += currentSize;
838
+ }
839
+
840
+ // Compute the last frame's size from whatever's left
841
+ frameSizes.push(slice.length - (slice.bufferPos + totalUsedSize));
842
+ }; break;
843
+
844
+ default: assert(false);
845
+ }
846
+
847
+ assert(frameSizes.length === frameCount);
848
+
849
+ blocks.splice(blockIndex, 1); // Remove the original block
850
+
851
+ const blockDuration = originalBlock.duration || frameCount * (track.defaultDuration ?? 0);
852
+
853
+ // Now, let's insert each frame as its own block
854
+ for (let i = 0; i < frameCount; i++) {
855
+ const frameSize = frameSizes[i]!;
856
+ const frameData = readBytes(slice, frameSize);
857
+
858
+ // Distribute timestamps evenly across the block duration
859
+ const frameTimestamp = originalBlock.timestamp + (blockDuration * i / frameCount);
860
+ const frameDuration = blockDuration / frameCount;
861
+
862
+ blocks.splice(blockIndex + i, 0, {
863
+ timestamp: frameTimestamp,
864
+ duration: frameDuration,
865
+ isKeyFrame: originalBlock.isKeyFrame,
866
+ data: frameData,
867
+ lacing: BlockLacing.None,
868
+ decoded: true,
869
+ postProcessed: false,
870
+ mainAdditional: originalBlock.mainAdditional,
871
+ });
872
+ }
873
+
874
+ blockIndex += frameCount; // Skip the blocks we just added
875
+ blockIndex--;
876
+ }
877
+ }
878
+
879
+ async loadSegmentMetadata(segment: Segment) {
880
+ for (const seekEntry of segment.seekEntries) {
881
+ if (seekEntry.id === EBMLId.Tags && !segment.tagsSeen) {
882
+ // We need to load the tags
883
+ } else if (seekEntry.id === EBMLId.Attachments && !segment.attachmentsSeen) {
884
+ // We need to load the attachments
885
+ } else {
886
+ continue;
887
+ }
888
+
889
+ let slice = this.reader.requestSliceRange(
890
+ segment.dataStartPos + seekEntry.segmentPosition,
891
+ MIN_HEADER_SIZE,
892
+ MAX_HEADER_SIZE,
893
+ );
894
+ if (slice instanceof Promise) slice = await slice;
895
+ if (!slice) continue;
896
+
897
+ const header = readElementHeader(slice);
898
+ if (!header || header.id !== seekEntry.id) continue;
899
+
900
+ const { size } = header;
901
+ assertDefinedSize(size);
902
+
903
+ assert(!this.currentSegment);
904
+ this.currentSegment = segment;
905
+
906
+ let dataSlice = this.reader.requestSlice(slice.filePos, size);
907
+ if (dataSlice instanceof Promise) dataSlice = await dataSlice;
908
+ if (dataSlice) {
909
+ this.readContiguousElements(dataSlice);
910
+ }
911
+
912
+ this.currentSegment = null;
913
+
914
+ // Mark as seen
915
+ if (seekEntry.id === EBMLId.Tags) {
916
+ segment.tagsSeen = true;
917
+ } else if (seekEntry.id === EBMLId.Attachments) {
918
+ segment.attachmentsSeen = true;
919
+ }
920
+ }
921
+ }
922
+
923
+ readContiguousElements(slice: FileSlice, stopIds?: number[]) {
924
+ while (slice.remainingLength >= MIN_HEADER_SIZE) {
925
+ const startPos = slice.filePos;
926
+ const foundElement = this.traverseElement(slice, stopIds);
927
+
928
+ if (!foundElement) {
929
+ return startPos;
930
+ }
931
+ }
932
+
933
+ return slice.filePos;
934
+ }
935
+
936
+ traverseElement(slice: FileSlice, stopIds?: number[]): boolean {
937
+ const header = readElementHeader(slice);
938
+ if (!header) {
939
+ return false;
940
+ }
941
+
942
+ if (stopIds && stopIds.includes(header.id)) {
943
+ return false;
944
+ }
945
+
946
+ const { id, size } = header;
947
+ const dataStartPos = slice.filePos;
948
+ assertDefinedSize(size);
949
+
950
+ switch (id) {
951
+ case EBMLId.DocType: {
952
+ this.isWebM = readAsciiString(slice, size) === 'webm';
953
+ }; break;
954
+
955
+ case EBMLId.Seek: {
956
+ if (!this.currentSegment) break;
957
+ const seekEntry: SeekEntry = { id: -1, segmentPosition: -1 };
958
+ this.currentSegment.seekEntries.push(seekEntry);
959
+ this.readContiguousElements(slice.slice(dataStartPos, size));
960
+
961
+ if (seekEntry.id === -1 || seekEntry.segmentPosition === -1) {
962
+ this.currentSegment.seekEntries.pop();
963
+ }
964
+ }; break;
965
+
966
+ case EBMLId.SeekID: {
967
+ const lastSeekEntry = this.currentSegment?.seekEntries[this.currentSegment.seekEntries.length - 1];
968
+ if (!lastSeekEntry) break;
969
+
970
+ lastSeekEntry.id = readUnsignedInt(slice, size);
971
+ }; break;
972
+
973
+ case EBMLId.SeekPosition: {
974
+ const lastSeekEntry = this.currentSegment?.seekEntries[this.currentSegment.seekEntries.length - 1];
975
+ if (!lastSeekEntry) break;
976
+
977
+ lastSeekEntry.segmentPosition = readUnsignedInt(slice, size);
978
+ }; break;
979
+
980
+ case EBMLId.TimestampScale: {
981
+ if (!this.currentSegment) break;
982
+
983
+ this.currentSegment.timestampScale = readUnsignedInt(slice, size);
984
+ this.currentSegment.timestampFactor = 1e9 / this.currentSegment.timestampScale;
985
+ }; break;
986
+
987
+ case EBMLId.Duration: {
988
+ if (!this.currentSegment) break;
989
+
990
+ this.currentSegment.duration = readFloat(slice, size);
991
+ }; break;
992
+
993
+ case EBMLId.TrackEntry: {
994
+ if (!this.currentSegment) break;
995
+
996
+ this.currentTrack = {
997
+ id: -1,
998
+ segment: this.currentSegment,
999
+ demuxer: this,
1000
+ clusterPositionCache: [],
1001
+ cuePoints: [],
1002
+
1003
+ disposition: {
1004
+ ...DEFAULT_TRACK_DISPOSITION,
1005
+ primary: false,
1006
+ },
1007
+ trackBacking: null,
1008
+ codecId: null,
1009
+ codecPrivate: null,
1010
+ defaultDuration: null,
1011
+ defaultDurationNs: null,
1012
+ name: null,
1013
+ languageCode: 'eng', // The default in Matroska
1014
+ hasLanguageBcp47: false,
1015
+ decodingInstructions: [],
1016
+
1017
+ info: null,
1018
+ };
1019
+
1020
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1021
+
1022
+ // Check if track was disabled during parsing (e.g., by FlagEnabled being 0)
1023
+ if (!this.currentTrack) {
1024
+ break;
1025
+ }
1026
+
1027
+ if (this.currentTrack.decodingInstructions.some((instruction) => {
1028
+ return instruction.data?.type !== 'decompress'
1029
+ || instruction.scope !== ContentEncodingScope.Block
1030
+ || instruction.data.algorithm !== ContentCompAlgo.HeaderStripping;
1031
+ })) {
1032
+ Logging._warn(`Track #${this.currentTrack.id} has an unsupported content encoding; dropping.`);
1033
+ this.currentTrack = null;
1034
+ }
1035
+
1036
+ if (
1037
+ this.currentTrack
1038
+ && this.currentTrack.id !== -1
1039
+ && this.currentTrack.codecId
1040
+ && this.currentTrack.info
1041
+ ) {
1042
+ const slashIndex = this.currentTrack.codecId.indexOf('/');
1043
+ const codecIdWithoutSuffix = slashIndex === -1
1044
+ ? this.currentTrack.codecId
1045
+ : this.currentTrack.codecId.slice(0, slashIndex);
1046
+
1047
+ if (
1048
+ this.currentTrack.info.type === 'video'
1049
+ && this.currentTrack.info.width !== -1
1050
+ && this.currentTrack.info.height !== -1
1051
+ ) {
1052
+ this.currentTrack.info.squarePixelWidth = this.currentTrack.info.width;
1053
+ this.currentTrack.info.squarePixelHeight = this.currentTrack.info.height;
1054
+
1055
+ if (
1056
+ this.currentTrack.info.displayWidth !== null
1057
+ && this.currentTrack.info.displayHeight !== null
1058
+ ) {
1059
+ const num = this.currentTrack.info.displayWidth * this.currentTrack.info.height;
1060
+ const den = this.currentTrack.info.displayHeight * this.currentTrack.info.width;
1061
+
1062
+ if (num > 0 && den > 0) {
1063
+ if (num > den) {
1064
+ this.currentTrack.info.squarePixelWidth = Math.round(
1065
+ this.currentTrack.info.width * num / den,
1066
+ );
1067
+ } else {
1068
+ this.currentTrack.info.squarePixelHeight = Math.round(
1069
+ this.currentTrack.info.height * den / num,
1070
+ );
1071
+ }
1072
+ }
1073
+ }
1074
+
1075
+ if (this.currentTrack.codecId === CODEC_STRING_MAP.avc) {
1076
+ this.currentTrack.info.codec = 'avc';
1077
+ this.currentTrack.info.codecDescription = this.currentTrack.codecPrivate;
1078
+ } else if (this.currentTrack.codecId === CODEC_STRING_MAP.hevc) {
1079
+ this.currentTrack.info.codec = 'hevc';
1080
+ this.currentTrack.info.codecDescription = this.currentTrack.codecPrivate;
1081
+ } else if (codecIdWithoutSuffix === CODEC_STRING_MAP.vp8) {
1082
+ this.currentTrack.info.codec = 'vp8';
1083
+ } else if (codecIdWithoutSuffix === CODEC_STRING_MAP.vp9) {
1084
+ this.currentTrack.info.codec = 'vp9';
1085
+ } else if (codecIdWithoutSuffix === CODEC_STRING_MAP.av1) {
1086
+ this.currentTrack.info.codec = 'av1';
1087
+ } else if (codecIdWithoutSuffix === CODEC_STRING_MAP.prores) {
1088
+ const format = this.currentTrack.codecPrivate
1089
+ ? textDecoder.decode(this.currentTrack.codecPrivate)
1090
+ : '';
1091
+
1092
+ if ((PRORES_FOURCCS as readonly string[]).includes(format)) {
1093
+ this.currentTrack.info.codec = 'prores';
1094
+ this.currentTrack.info.proresFormat = format as ProresFourCc;
1095
+ } else {
1096
+ // Either an invalid string or ProRes RAW, which we don't support yet (it's a
1097
+ // different codec).
1098
+ }
1099
+ }
1100
+
1101
+ const videoTrack = this.currentTrack as InternalVideoTrack;
1102
+ this.currentTrack.trackBacking = new MatroskaVideoTrackBacking(videoTrack);
1103
+ this.currentSegment.tracks.push(this.currentTrack);
1104
+ } else if (this.currentTrack.info.type === 'audio') {
1105
+ if (codecIdWithoutSuffix === CODEC_STRING_MAP.aac) {
1106
+ this.currentTrack.info.codec = 'aac';
1107
+ this.currentTrack.info.aacCodecInfo = {
1108
+ isMpeg2: this.currentTrack.codecId.includes('MPEG2'),
1109
+ objectType: null,
1110
+ };
1111
+ this.currentTrack.info.codecDescription = this.currentTrack.codecPrivate;
1112
+ } else if (this.currentTrack.codecId === CODEC_STRING_MAP.mp3) {
1113
+ this.currentTrack.info.codec = 'mp3';
1114
+ } else if (codecIdWithoutSuffix === CODEC_STRING_MAP.opus) {
1115
+ this.currentTrack.info.codec = 'opus';
1116
+ this.currentTrack.info.codecDescription = this.currentTrack.codecPrivate;
1117
+ this.currentTrack.info.sampleRate = OPUS_SAMPLE_RATE; // Always the same
1118
+ } else if (codecIdWithoutSuffix === CODEC_STRING_MAP.vorbis) {
1119
+ this.currentTrack.info.codec = 'vorbis';
1120
+ this.currentTrack.info.codecDescription = this.currentTrack.codecPrivate;
1121
+ } else if (codecIdWithoutSuffix === CODEC_STRING_MAP.flac) {
1122
+ this.currentTrack.info.codec = 'flac';
1123
+ this.currentTrack.info.codecDescription = this.currentTrack.codecPrivate;
1124
+ } else if (codecIdWithoutSuffix === CODEC_STRING_MAP.ac3) {
1125
+ this.currentTrack.info.codec = 'ac3';
1126
+ this.currentTrack.info.codecDescription = this.currentTrack.codecPrivate;
1127
+ } else if (codecIdWithoutSuffix === CODEC_STRING_MAP.eac3) {
1128
+ this.currentTrack.info.codec = 'eac3';
1129
+ this.currentTrack.info.codecDescription = this.currentTrack.codecPrivate;
1130
+ } else if (this.currentTrack.codecId === 'A_PCM/INT/LIT') {
1131
+ if (this.currentTrack.info.bitDepth === 8) {
1132
+ this.currentTrack.info.codec = 'pcm-u8';
1133
+ } else if (this.currentTrack.info.bitDepth === 16) {
1134
+ this.currentTrack.info.codec = 'pcm-s16';
1135
+ } else if (this.currentTrack.info.bitDepth === 24) {
1136
+ this.currentTrack.info.codec = 'pcm-s24';
1137
+ } else if (this.currentTrack.info.bitDepth === 32) {
1138
+ this.currentTrack.info.codec = 'pcm-s32';
1139
+ }
1140
+ } else if (this.currentTrack.codecId === 'A_PCM/INT/BIG') {
1141
+ if (this.currentTrack.info.bitDepth === 8) {
1142
+ this.currentTrack.info.codec = 'pcm-u8';
1143
+ } else if (this.currentTrack.info.bitDepth === 16) {
1144
+ this.currentTrack.info.codec = 'pcm-s16be';
1145
+ } else if (this.currentTrack.info.bitDepth === 24) {
1146
+ this.currentTrack.info.codec = 'pcm-s24be';
1147
+ } else if (this.currentTrack.info.bitDepth === 32) {
1148
+ this.currentTrack.info.codec = 'pcm-s32be';
1149
+ }
1150
+ } else if (this.currentTrack.codecId === 'A_PCM/FLOAT/IEEE') {
1151
+ if (this.currentTrack.info.bitDepth === 32) {
1152
+ this.currentTrack.info.codec = 'pcm-f32';
1153
+ } else if (this.currentTrack.info.bitDepth === 64) {
1154
+ this.currentTrack.info.codec = 'pcm-f64';
1155
+ }
1156
+ }
1157
+
1158
+ const audioTrack = this.currentTrack as InternalAudioTrack;
1159
+ this.currentTrack.trackBacking = new MatroskaAudioTrackBacking(audioTrack);
1160
+ this.currentSegment.tracks.push(this.currentTrack);
1161
+ }
1162
+ }
1163
+
1164
+ this.currentTrack = null;
1165
+ }; break;
1166
+
1167
+ case EBMLId.TrackNumber: {
1168
+ if (!this.currentTrack) break;
1169
+
1170
+ this.currentTrack.id = readUnsignedInt(slice, size);
1171
+ }; break;
1172
+
1173
+ case EBMLId.TrackType: {
1174
+ if (!this.currentTrack) break;
1175
+
1176
+ const type = readUnsignedInt(slice, size);
1177
+ if (type === 1) {
1178
+ this.currentTrack.info = {
1179
+ type: 'video',
1180
+ width: -1,
1181
+ height: -1,
1182
+ displayWidth: null,
1183
+ displayHeight: null,
1184
+ displayUnit: null,
1185
+ squarePixelWidth: -1,
1186
+ squarePixelHeight: -1,
1187
+ rotation: 0,
1188
+ codec: null,
1189
+ codecDescription: null,
1190
+ colorSpace: null,
1191
+ alphaMode: false,
1192
+ proresFormat: null,
1193
+ };
1194
+ } else if (type === 2) {
1195
+ this.currentTrack.info = {
1196
+ type: 'audio',
1197
+ numberOfChannels: 1, // Default value
1198
+ sampleRate: 8000, // Default value
1199
+ bitDepth: -1,
1200
+ codec: null,
1201
+ codecDescription: null,
1202
+ aacCodecInfo: null,
1203
+ };
1204
+ }
1205
+ }; break;
1206
+
1207
+ case EBMLId.FlagEnabled: {
1208
+ if (!this.currentTrack) break;
1209
+
1210
+ const enabled = readUnsignedInt(slice, size);
1211
+ if (!enabled) {
1212
+ this.currentTrack = null;
1213
+ }
1214
+ }; break;
1215
+
1216
+ case EBMLId.FlagDefault: {
1217
+ if (!this.currentTrack) break;
1218
+
1219
+ this.currentTrack.disposition.default = !!readUnsignedInt(slice, size);
1220
+ }; break;
1221
+
1222
+ case EBMLId.FlagForced: {
1223
+ if (!this.currentTrack) break;
1224
+
1225
+ this.currentTrack.disposition.forced = !!readUnsignedInt(slice, size);
1226
+ }; break;
1227
+
1228
+ case EBMLId.FlagOriginal: {
1229
+ if (!this.currentTrack) break;
1230
+
1231
+ this.currentTrack.disposition.original = !!readUnsignedInt(slice, size);
1232
+ }; break;
1233
+
1234
+ case EBMLId.FlagHearingImpaired: {
1235
+ if (!this.currentTrack) break;
1236
+
1237
+ this.currentTrack.disposition.hearingImpaired = !!readUnsignedInt(slice, size);
1238
+ }; break;
1239
+
1240
+ case EBMLId.FlagVisualImpaired: {
1241
+ if (!this.currentTrack) break;
1242
+
1243
+ this.currentTrack.disposition.visuallyImpaired = !!readUnsignedInt(slice, size);
1244
+ }; break;
1245
+
1246
+ case EBMLId.FlagCommentary: {
1247
+ if (!this.currentTrack) break;
1248
+
1249
+ this.currentTrack.disposition.commentary = !!readUnsignedInt(slice, size);
1250
+ }; break;
1251
+
1252
+ case EBMLId.CodecID: {
1253
+ if (!this.currentTrack) break;
1254
+
1255
+ this.currentTrack.codecId = readAsciiString(slice, size);
1256
+ }; break;
1257
+
1258
+ case EBMLId.CodecPrivate: {
1259
+ if (!this.currentTrack) break;
1260
+
1261
+ this.currentTrack.codecPrivate = readBytes(slice, size);
1262
+ }; break;
1263
+
1264
+ case EBMLId.DefaultDuration: {
1265
+ if (!this.currentTrack) break;
1266
+ this.currentTrack.defaultDurationNs = readUnsignedInt(slice, size);
1267
+ }; break;
1268
+
1269
+ case EBMLId.Name: {
1270
+ if (!this.currentTrack) break;
1271
+
1272
+ this.currentTrack.name = readUnicodeString(slice, size);
1273
+ }; break;
1274
+
1275
+ case EBMLId.Language: {
1276
+ if (!this.currentTrack) break;
1277
+ if (this.currentTrack.hasLanguageBcp47) {
1278
+ // LanguageBCP47 was present, which takes precedence
1279
+ break;
1280
+ }
1281
+
1282
+ this.currentTrack.languageCode = readAsciiString(slice, size);
1283
+
1284
+ if (!isIso639Dash2LanguageCode(this.currentTrack.languageCode)) {
1285
+ this.currentTrack.languageCode = UNDETERMINED_LANGUAGE;
1286
+ }
1287
+ }; break;
1288
+
1289
+ case EBMLId.LanguageBCP47: {
1290
+ if (!this.currentTrack) break;
1291
+
1292
+ const bcp47 = readAsciiString(slice, size);
1293
+ const languageSubtag = bcp47.split('-')[0];
1294
+
1295
+ if (languageSubtag) {
1296
+ // Technically invalid, for now: The language subtag might be a language code from ISO 639-1,
1297
+ // ISO 639-2, ISO 639-3, ISO 639-5 or some other thing (source: Wikipedia). But, `languageCode` is
1298
+ // documented as ISO 639-2. Changing the definition would be a breaking change. This will get
1299
+ // cleaned up in the future by defining languageCode to be BCP 47 instead.
1300
+ this.currentTrack.languageCode = languageSubtag;
1301
+ } else {
1302
+ this.currentTrack.languageCode = UNDETERMINED_LANGUAGE;
1303
+ }
1304
+
1305
+ this.currentTrack.hasLanguageBcp47 = true;
1306
+ }; break;
1307
+
1308
+ case EBMLId.Video: {
1309
+ if (this.currentTrack?.info?.type !== 'video') break;
1310
+
1311
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1312
+ }; break;
1313
+
1314
+ case EBMLId.PixelWidth: {
1315
+ if (this.currentTrack?.info?.type !== 'video') break;
1316
+
1317
+ this.currentTrack.info.width = readUnsignedInt(slice, size);
1318
+ }; break;
1319
+
1320
+ case EBMLId.PixelHeight: {
1321
+ if (this.currentTrack?.info?.type !== 'video') break;
1322
+
1323
+ this.currentTrack.info.height = readUnsignedInt(slice, size);
1324
+ }; break;
1325
+
1326
+ case EBMLId.DisplayWidth: {
1327
+ if (this.currentTrack?.info?.type !== 'video') break;
1328
+
1329
+ this.currentTrack.info.displayWidth = readUnsignedInt(slice, size);
1330
+ }; break;
1331
+
1332
+ case EBMLId.DisplayHeight: {
1333
+ if (this.currentTrack?.info?.type !== 'video') break;
1334
+
1335
+ this.currentTrack.info.displayHeight = readUnsignedInt(slice, size);
1336
+ }; break;
1337
+
1338
+ case EBMLId.DisplayUnit: {
1339
+ if (this.currentTrack?.info?.type !== 'video') break;
1340
+
1341
+ this.currentTrack.info.displayUnit = readUnsignedInt(slice, size);
1342
+ }; break;
1343
+
1344
+ case EBMLId.AlphaMode: {
1345
+ if (this.currentTrack?.info?.type !== 'video') break;
1346
+
1347
+ this.currentTrack.info.alphaMode = readUnsignedInt(slice, size) === 1;
1348
+ }; break;
1349
+
1350
+ case EBMLId.Colour: {
1351
+ if (this.currentTrack?.info?.type !== 'video') break;
1352
+
1353
+ this.currentTrack.info.colorSpace = {};
1354
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1355
+ }; break;
1356
+
1357
+ case EBMLId.MatrixCoefficients: {
1358
+ if (this.currentTrack?.info?.type !== 'video' || !this.currentTrack.info.colorSpace) break;
1359
+
1360
+ const matrixCoefficients = readUnsignedInt(slice, size);
1361
+ const mapped = MATRIX_COEFFICIENTS_MAP_INVERSE[matrixCoefficients] ?? null;
1362
+ this.currentTrack.info.colorSpace.matrix = mapped as VideoColorSpaceInit['matrix'];
1363
+ }; break;
1364
+
1365
+ case EBMLId.Range: {
1366
+ if (this.currentTrack?.info?.type !== 'video' || !this.currentTrack.info.colorSpace) break;
1367
+
1368
+ this.currentTrack.info.colorSpace.fullRange = readUnsignedInt(slice, size) === 2;
1369
+ }; break;
1370
+
1371
+ case EBMLId.TransferCharacteristics: {
1372
+ if (this.currentTrack?.info?.type !== 'video' || !this.currentTrack.info.colorSpace) break;
1373
+
1374
+ const transferCharacteristics = readUnsignedInt(slice, size);
1375
+ const mapped = TRANSFER_CHARACTERISTICS_MAP_INVERSE[transferCharacteristics] ?? null;
1376
+ this.currentTrack.info.colorSpace.transfer = mapped as VideoColorSpaceInit['transfer'];
1377
+ }; break;
1378
+
1379
+ case EBMLId.Primaries: {
1380
+ if (this.currentTrack?.info?.type !== 'video' || !this.currentTrack.info.colorSpace) break;
1381
+
1382
+ const primaries = readUnsignedInt(slice, size);
1383
+ const mapped = COLOR_PRIMARIES_MAP_INVERSE[primaries] ?? null;
1384
+ this.currentTrack.info.colorSpace.primaries = mapped as VideoColorSpaceInit['primaries'];
1385
+ }; break;
1386
+
1387
+ case EBMLId.Projection: {
1388
+ if (this.currentTrack?.info?.type !== 'video') break;
1389
+
1390
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1391
+ }; break;
1392
+
1393
+ case EBMLId.ProjectionPoseRoll: {
1394
+ if (this.currentTrack?.info?.type !== 'video') break;
1395
+
1396
+ const rotation = readFloat(slice, size);
1397
+ const flippedRotation = -rotation; // Convert counter-clockwise to clockwise
1398
+
1399
+ try {
1400
+ this.currentTrack.info.rotation = normalizeRotation(flippedRotation);
1401
+ } catch {
1402
+ // It wasn't a valid rotation
1403
+ }
1404
+ }; break;
1405
+
1406
+ case EBMLId.Audio: {
1407
+ if (this.currentTrack?.info?.type !== 'audio') break;
1408
+
1409
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1410
+ }; break;
1411
+
1412
+ case EBMLId.SamplingFrequency: {
1413
+ if (this.currentTrack?.info?.type !== 'audio') break;
1414
+
1415
+ this.currentTrack.info.sampleRate = readFloat(slice, size);
1416
+ }; break;
1417
+
1418
+ case EBMLId.Channels: {
1419
+ if (this.currentTrack?.info?.type !== 'audio') break;
1420
+
1421
+ this.currentTrack.info.numberOfChannels = readUnsignedInt(slice, size);
1422
+ }; break;
1423
+
1424
+ case EBMLId.BitDepth: {
1425
+ if (this.currentTrack?.info?.type !== 'audio') break;
1426
+
1427
+ this.currentTrack.info.bitDepth = readUnsignedInt(slice, size);
1428
+ }; break;
1429
+
1430
+ case EBMLId.CuePoint: {
1431
+ if (!this.currentSegment) break;
1432
+
1433
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1434
+ this.currentCueTime = null;
1435
+ }; break;
1436
+
1437
+ case EBMLId.CueTime: {
1438
+ this.currentCueTime = readUnsignedInt(slice, size);
1439
+ }; break;
1440
+
1441
+ case EBMLId.CueTrackPositions: {
1442
+ if (this.currentCueTime === null) break;
1443
+ assert(this.currentSegment);
1444
+
1445
+ const cuePoint: CuePoint = { time: this.currentCueTime, trackId: -1, clusterPosition: -1 };
1446
+ this.currentSegment.cuePoints.push(cuePoint);
1447
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1448
+
1449
+ if (cuePoint.trackId === -1 || cuePoint.clusterPosition === -1) {
1450
+ this.currentSegment.cuePoints.pop();
1451
+ }
1452
+ }; break;
1453
+
1454
+ case EBMLId.CueTrack: {
1455
+ const lastCuePoint = this.currentSegment?.cuePoints[this.currentSegment.cuePoints.length - 1];
1456
+ if (!lastCuePoint) break;
1457
+
1458
+ lastCuePoint.trackId = readUnsignedInt(slice, size);
1459
+ }; break;
1460
+
1461
+ case EBMLId.CueClusterPosition: {
1462
+ const lastCuePoint = this.currentSegment?.cuePoints[this.currentSegment.cuePoints.length - 1];
1463
+ if (!lastCuePoint) break;
1464
+
1465
+ assert(this.currentSegment);
1466
+ lastCuePoint.clusterPosition = this.currentSegment.dataStartPos + readUnsignedInt(slice, size);
1467
+ }; break;
1468
+
1469
+ case EBMLId.Timestamp: {
1470
+ if (!this.currentCluster) break;
1471
+
1472
+ this.currentCluster.timestamp = readUnsignedInt(slice, size);
1473
+ }; break;
1474
+
1475
+ case EBMLId.SimpleBlock: {
1476
+ if (!this.currentCluster) break;
1477
+
1478
+ const trackNumber = readVarInt(slice);
1479
+ if (trackNumber === null) break;
1480
+
1481
+ const trackData = this.getTrackDataInCluster(this.currentCluster, trackNumber);
1482
+ if (!trackData) break; // Not a track we care about
1483
+
1484
+ const relativeTimestamp = readI16Be(slice);
1485
+
1486
+ const flags = readU8(slice);
1487
+ const lacing = (flags >> 1) & 0x3 as BlockLacing; // If the block is laced, we'll expand it later
1488
+
1489
+ let isKeyFrame = !!(flags & 0x80);
1490
+ if (trackData.track.info?.type === 'audio' && trackData.track.info.codec) {
1491
+ // Some files don't mark their audio packets as key packets (I'm looking at you, Firefox). But, we
1492
+ // can fix this in most cases: if we recognize the codec of the track, then we know every packet is
1493
+ // necessarily a key packet, no matter what the container says.
1494
+ // https://github.com/Vanilagy/mediabunny/issues/192
1495
+ isKeyFrame = true;
1496
+ }
1497
+
1498
+ const blockData = readBytes(slice, size - (slice.filePos - dataStartPos));
1499
+ const hasDecodingInstructions = trackData.track.decodingInstructions.length > 0;
1500
+
1501
+ trackData.blocks.push({
1502
+ timestamp: relativeTimestamp, // We'll add the cluster's timestamp to this later
1503
+ duration: 0, // Will set later
1504
+ isKeyFrame,
1505
+ data: blockData,
1506
+ lacing,
1507
+ decoded: !hasDecodingInstructions,
1508
+ postProcessed: false,
1509
+ mainAdditional: null,
1510
+ });
1511
+ }; break;
1512
+
1513
+ case EBMLId.BlockGroup: {
1514
+ if (!this.currentCluster) break;
1515
+
1516
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1517
+
1518
+ this.currentBlock = null;
1519
+ }; break;
1520
+
1521
+ case EBMLId.Block: {
1522
+ if (!this.currentCluster) break;
1523
+
1524
+ const trackNumber = readVarInt(slice);
1525
+ if (trackNumber === null) break;
1526
+
1527
+ const trackData = this.getTrackDataInCluster(this.currentCluster, trackNumber);
1528
+ if (!trackData) break;
1529
+
1530
+ const relativeTimestamp = readI16Be(slice);
1531
+
1532
+ const flags = readU8(slice);
1533
+ const lacing = (flags >> 1) & 0x3 as BlockLacing; // If the block is laced, we'll expand it later
1534
+
1535
+ const blockData = readBytes(slice, size - (slice.filePos - dataStartPos));
1536
+ const hasDecodingInstructions = trackData.track.decodingInstructions.length > 0;
1537
+
1538
+ this.currentBlock = {
1539
+ timestamp: relativeTimestamp, // We'll add the cluster's timestamp to this later
1540
+ duration: 0, // Will set later
1541
+ isKeyFrame: true,
1542
+ data: blockData,
1543
+ lacing,
1544
+ decoded: !hasDecodingInstructions,
1545
+ postProcessed: false,
1546
+ mainAdditional: null,
1547
+ };
1548
+ trackData.blocks.push(this.currentBlock);
1549
+ }; break;
1550
+
1551
+ case EBMLId.BlockAdditions: {
1552
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1553
+ }; break;
1554
+
1555
+ case EBMLId.BlockMore: {
1556
+ if (!this.currentBlock) break;
1557
+
1558
+ this.currentBlockAdditional = {
1559
+ addId: 1,
1560
+ data: null,
1561
+ };
1562
+
1563
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1564
+
1565
+ if (this.currentBlockAdditional.data && this.currentBlockAdditional.addId === 1) {
1566
+ this.currentBlock.mainAdditional = this.currentBlockAdditional.data;
1567
+ }
1568
+ this.currentBlockAdditional = null;
1569
+ }; break;
1570
+
1571
+ case EBMLId.BlockAdditional: {
1572
+ if (!this.currentBlockAdditional) break;
1573
+
1574
+ this.currentBlockAdditional.data = readBytes(slice, size);
1575
+ }; break;
1576
+
1577
+ case EBMLId.BlockAddID: {
1578
+ if (!this.currentBlockAdditional) break;
1579
+
1580
+ this.currentBlockAdditional.addId = readUnsignedInt(slice, size);
1581
+ }; break;
1582
+
1583
+ case EBMLId.BlockDuration: {
1584
+ if (!this.currentBlock) break;
1585
+
1586
+ this.currentBlock.duration = readUnsignedInt(slice, size);
1587
+ }; break;
1588
+
1589
+ case EBMLId.ReferenceBlock: {
1590
+ if (!this.currentBlock) break;
1591
+
1592
+ this.currentBlock.isKeyFrame = false;
1593
+ // We ignore the actual value here, we just use the reference as an indicator for "not a key frame".
1594
+ // This is in line with FFmpeg's behavior.
1595
+ }; break;
1596
+
1597
+ case EBMLId.Tag: {
1598
+ this.currentTagTargetIsMovie = true;
1599
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1600
+ }; break;
1601
+
1602
+ case EBMLId.Targets: {
1603
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1604
+ }; break;
1605
+
1606
+ case EBMLId.TargetTypeValue: {
1607
+ const targetTypeValue = readUnsignedInt(slice, size);
1608
+ if (targetTypeValue !== 50) {
1609
+ this.currentTagTargetIsMovie = false;
1610
+ }
1611
+ }; break;
1612
+
1613
+ case EBMLId.TagTrackUID:
1614
+ case EBMLId.TagEditionUID:
1615
+ case EBMLId.TagChapterUID:
1616
+ case EBMLId.TagAttachmentUID: {
1617
+ this.currentTagTargetIsMovie = false;
1618
+ }; break;
1619
+
1620
+ case EBMLId.SimpleTag: {
1621
+ if (!this.currentTagTargetIsMovie) break;
1622
+
1623
+ this.currentSimpleTagName = null;
1624
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1625
+ }; break;
1626
+
1627
+ case EBMLId.TagName: {
1628
+ this.currentSimpleTagName = readUnicodeString(slice, size);
1629
+ }; break;
1630
+
1631
+ case EBMLId.TagString: {
1632
+ if (!this.currentSimpleTagName) break;
1633
+
1634
+ const value = readUnicodeString(slice, size);
1635
+ this.processTagValue(this.currentSimpleTagName, value);
1636
+ }; break;
1637
+
1638
+ case EBMLId.TagBinary: {
1639
+ if (!this.currentSimpleTagName) break;
1640
+
1641
+ const value = readBytes(slice, size);
1642
+ this.processTagValue(this.currentSimpleTagName, value);
1643
+ }; break;
1644
+
1645
+ case EBMLId.AttachedFile: {
1646
+ if (!this.currentSegment) break;
1647
+
1648
+ this.currentAttachedFile = {
1649
+ fileUid: null,
1650
+ fileName: null,
1651
+ fileMediaType: null,
1652
+ fileData: null,
1653
+ fileDescription: null,
1654
+ };
1655
+
1656
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1657
+
1658
+ const tags = this.currentSegment.metadataTags;
1659
+
1660
+ if (this.currentAttachedFile.fileUid && this.currentAttachedFile.fileData) {
1661
+ // All attached files get surfaced in the `raw` metadata tags
1662
+ tags.raw ??= {};
1663
+ tags.raw[this.currentAttachedFile.fileUid.toString()] = new AttachedFile(
1664
+ this.currentAttachedFile.fileData,
1665
+ this.currentAttachedFile.fileMediaType ?? undefined,
1666
+ this.currentAttachedFile.fileName ?? undefined,
1667
+ this.currentAttachedFile.fileDescription ?? undefined,
1668
+ );
1669
+ }
1670
+
1671
+ // Only process image attachments
1672
+ if (this.currentAttachedFile.fileMediaType?.startsWith('image/') && this.currentAttachedFile.fileData) {
1673
+ const fileName = this.currentAttachedFile.fileName;
1674
+ let kind: 'coverFront' | 'coverBack' | 'unknown' = 'unknown';
1675
+
1676
+ if (fileName) {
1677
+ const lowerName = fileName.toLowerCase();
1678
+ if (lowerName.startsWith('cover.')) {
1679
+ kind = 'coverFront';
1680
+ } else if (lowerName.startsWith('back.')) {
1681
+ kind = 'coverBack';
1682
+ }
1683
+ }
1684
+
1685
+ tags.images ??= [];
1686
+ tags.images.push({
1687
+ data: this.currentAttachedFile.fileData,
1688
+ mimeType: this.currentAttachedFile.fileMediaType,
1689
+ kind,
1690
+ name: this.currentAttachedFile.fileName ?? undefined,
1691
+ description: this.currentAttachedFile.fileDescription ?? undefined,
1692
+ });
1693
+ }
1694
+
1695
+ this.currentAttachedFile = null;
1696
+ }; break;
1697
+
1698
+ case EBMLId.FileUID: {
1699
+ if (!this.currentAttachedFile) break;
1700
+
1701
+ this.currentAttachedFile.fileUid = readUnsignedBigInt(slice, size);
1702
+ }; break;
1703
+
1704
+ case EBMLId.FileName: {
1705
+ if (!this.currentAttachedFile) break;
1706
+
1707
+ this.currentAttachedFile.fileName = readUnicodeString(slice, size);
1708
+ }; break;
1709
+
1710
+ case EBMLId.FileMediaType: {
1711
+ if (!this.currentAttachedFile) break;
1712
+
1713
+ this.currentAttachedFile.fileMediaType = readAsciiString(slice, size);
1714
+ }; break;
1715
+
1716
+ case EBMLId.FileData: {
1717
+ if (!this.currentAttachedFile) break;
1718
+
1719
+ this.currentAttachedFile.fileData = readBytes(slice, size);
1720
+ }; break;
1721
+
1722
+ case EBMLId.FileDescription: {
1723
+ if (!this.currentAttachedFile) break;
1724
+
1725
+ this.currentAttachedFile.fileDescription = readUnicodeString(slice, size);
1726
+ }; break;
1727
+
1728
+ case EBMLId.ContentEncodings: {
1729
+ if (!this.currentTrack) break;
1730
+
1731
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1732
+
1733
+ // "**MUST** start with the `ContentEncoding` with the highest `ContentEncodingOrder`"
1734
+ this.currentTrack.decodingInstructions.sort((a, b) => b.order - a.order);
1735
+ }; break;
1736
+
1737
+ case EBMLId.ContentEncoding: {
1738
+ this.currentDecodingInstruction = {
1739
+ order: 0,
1740
+ scope: ContentEncodingScope.Block,
1741
+ data: null,
1742
+ };
1743
+
1744
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1745
+
1746
+ if (this.currentDecodingInstruction.data) {
1747
+ this.currentTrack!.decodingInstructions.push(this.currentDecodingInstruction);
1748
+ }
1749
+
1750
+ this.currentDecodingInstruction = null;
1751
+ }; break;
1752
+
1753
+ case EBMLId.ContentEncodingOrder: {
1754
+ if (!this.currentDecodingInstruction) break;
1755
+
1756
+ this.currentDecodingInstruction.order = readUnsignedInt(slice, size);
1757
+ }; break;
1758
+
1759
+ case EBMLId.ContentEncodingScope: {
1760
+ if (!this.currentDecodingInstruction) break;
1761
+
1762
+ this.currentDecodingInstruction.scope = readUnsignedInt(slice, size);
1763
+ }; break;
1764
+
1765
+ case EBMLId.ContentCompression: {
1766
+ if (!this.currentDecodingInstruction) break;
1767
+
1768
+ this.currentDecodingInstruction.data = {
1769
+ type: 'decompress',
1770
+ algorithm: ContentCompAlgo.Zlib,
1771
+ settings: null,
1772
+ };
1773
+
1774
+ this.readContiguousElements(slice.slice(dataStartPos, size));
1775
+ }; break;
1776
+
1777
+ case EBMLId.ContentCompAlgo: {
1778
+ if (this.currentDecodingInstruction?.data?.type !== 'decompress') break;
1779
+
1780
+ this.currentDecodingInstruction.data.algorithm = readUnsignedInt(slice, size);
1781
+ }; break;
1782
+
1783
+ case EBMLId.ContentCompSettings: {
1784
+ if (this.currentDecodingInstruction?.data?.type !== 'decompress') break;
1785
+
1786
+ this.currentDecodingInstruction.data.settings = readBytes(slice, size);
1787
+ }; break;
1788
+
1789
+ case EBMLId.ContentEncryption: {
1790
+ if (!this.currentDecodingInstruction) break;
1791
+
1792
+ this.currentDecodingInstruction.data = {
1793
+ type: 'decrypt',
1794
+ };
1795
+ }; break;
1796
+ }
1797
+
1798
+ slice.filePos = dataStartPos + size;
1799
+ return true;
1800
+ }
1801
+
1802
+ decodeBlockData(track: InternalTrack, rawData: Uint8Array) {
1803
+ assert(track.decodingInstructions.length > 0); // This method shouldn't be called otherwise
1804
+
1805
+ let currentData = rawData;
1806
+
1807
+ for (const instruction of track.decodingInstructions) {
1808
+ assert(instruction.data);
1809
+
1810
+ switch (instruction.data.type) {
1811
+ case 'decompress': {
1812
+ switch (instruction.data.algorithm) {
1813
+ case ContentCompAlgo.HeaderStripping: {
1814
+ if (instruction.data.settings && instruction.data.settings.length > 0) {
1815
+ const prefix = instruction.data.settings;
1816
+ const newData = new Uint8Array(prefix.length + currentData.length);
1817
+
1818
+ newData.set(prefix, 0);
1819
+ newData.set(currentData, prefix.length);
1820
+
1821
+ currentData = newData;
1822
+ }
1823
+ }; break;
1824
+
1825
+ default: {
1826
+ // Unhandled
1827
+ };
1828
+ }
1829
+ }; break;
1830
+
1831
+ default: {
1832
+ // Unhandled
1833
+ };
1834
+ }
1835
+ }
1836
+
1837
+ return currentData;
1838
+ }
1839
+
1840
+ processTagValue(name: string, value: string | Uint8Array) {
1841
+ if (!this.currentSegment?.metadataTags) return;
1842
+
1843
+ const metadataTags = this.currentSegment.metadataTags;
1844
+ metadataTags.raw ??= {};
1845
+ metadataTags.raw[name] ??= value;
1846
+
1847
+ if (typeof value === 'string') {
1848
+ switch (name.toLowerCase()) {
1849
+ case 'title': {
1850
+ metadataTags.title ??= value;
1851
+ }; break;
1852
+
1853
+ case 'description': {
1854
+ metadataTags.description ??= value;
1855
+ }; break;
1856
+
1857
+ case 'artist': {
1858
+ metadataTags.artist ??= value;
1859
+ }; break;
1860
+
1861
+ case 'album': {
1862
+ metadataTags.album ??= value;
1863
+ }; break;
1864
+
1865
+ case 'album_artist': {
1866
+ metadataTags.albumArtist ??= value;
1867
+ }; break;
1868
+
1869
+ case 'genre': {
1870
+ metadataTags.genre ??= value;
1871
+ }; break;
1872
+
1873
+ case 'comment': {
1874
+ metadataTags.comment ??= value;
1875
+ }; break;
1876
+
1877
+ case 'lyrics': {
1878
+ metadataTags.lyrics ??= value;
1879
+ }; break;
1880
+
1881
+ case 'date': {
1882
+ const date = new Date(value);
1883
+ if (!Number.isNaN(date.getTime())) {
1884
+ metadataTags.date ??= date;
1885
+ }
1886
+ }; break;
1887
+
1888
+ case 'track_number':
1889
+ case 'part_number': {
1890
+ const parts = value.split('/');
1891
+ const trackNum = Number.parseInt(parts[0]!, 10);
1892
+ const tracksTotal = parts[1] && Number.parseInt(parts[1], 10);
1893
+
1894
+ if (Number.isInteger(trackNum) && trackNum > 0) {
1895
+ metadataTags.trackNumber ??= trackNum;
1896
+ }
1897
+ if (tracksTotal && Number.isInteger(tracksTotal) && tracksTotal > 0) {
1898
+ metadataTags.tracksTotal ??= tracksTotal;
1899
+ }
1900
+ }; break;
1901
+
1902
+ case 'disc_number':
1903
+ case 'disc': {
1904
+ const discParts = value.split('/');
1905
+ const discNum = Number.parseInt(discParts[0]!, 10);
1906
+ const discsTotal = discParts[1] && Number.parseInt(discParts[1], 10);
1907
+
1908
+ if (Number.isInteger(discNum) && discNum > 0) {
1909
+ metadataTags.discNumber ??= discNum;
1910
+ }
1911
+ if (discsTotal && Number.isInteger(discsTotal) && discsTotal > 0) {
1912
+ metadataTags.discsTotal ??= discsTotal;
1913
+ }
1914
+ }; break;
1915
+ }
1916
+ }
1917
+ }
1918
+ }
1919
+
1920
+ abstract class MatroskaTrackBacking implements InputTrackBacking {
1921
+ packetToClusterLocation = new WeakMap<EncodedPacket, {
1922
+ cluster: Cluster;
1923
+ blockIndex: number;
1924
+ }>();
1925
+
1926
+ constructor(public internalTrack: InternalTrack) {}
1927
+
1928
+ abstract getType(): TrackType;
1929
+ abstract getDecoderConfig(): Promise<VideoDecoderConfig | AudioDecoderConfig | null>;
1930
+
1931
+ getId() {
1932
+ return this.internalTrack.id;
1933
+ }
1934
+
1935
+ getNumber() {
1936
+ const demuxer = this.internalTrack.demuxer;
1937
+ const trackType = this.internalTrack.trackBacking!.getType();
1938
+
1939
+ let number = 0;
1940
+ for (const segment of demuxer.segments) {
1941
+ for (const track of segment.tracks) {
1942
+ if (track.trackBacking!.getType() === trackType) {
1943
+ number++;
1944
+ }
1945
+
1946
+ if (track === this.internalTrack) {
1947
+ break;
1948
+ }
1949
+ }
1950
+ }
1951
+
1952
+ return number;
1953
+ }
1954
+
1955
+ getCodec(): MediaCodec | null {
1956
+ throw new Error('Not implemented on base class.');
1957
+ }
1958
+
1959
+ getInternalCodecId() {
1960
+ return this.internalTrack.codecId;
1961
+ }
1962
+
1963
+ getName() {
1964
+ return this.internalTrack.name;
1965
+ }
1966
+
1967
+ getLanguageCode() {
1968
+ return this.internalTrack.languageCode;
1969
+ }
1970
+
1971
+ getTimeResolution() {
1972
+ return this.internalTrack.segment.timestampFactor;
1973
+ }
1974
+
1975
+ isRelativeToUnixEpoch() {
1976
+ return false;
1977
+ }
1978
+
1979
+ getUnixTimeForTimestamp() {
1980
+ return null;
1981
+ }
1982
+
1983
+ getDisposition() {
1984
+ return this.internalTrack.disposition;
1985
+ }
1986
+
1987
+ getPairingMask() {
1988
+ return 1n;
1989
+ }
1990
+
1991
+ getBitrate() {
1992
+ return null;
1993
+ }
1994
+
1995
+ getAverageBitrate() {
1996
+ return null;
1997
+ }
1998
+
1999
+ async getDurationFromMetadata() {
2000
+ const segment = this.internalTrack.segment;
2001
+ if (segment.duration <= 0) {
2002
+ return null;
2003
+ }
2004
+
2005
+ let endTimestamp = segment.duration / segment.timestampFactor;
2006
+
2007
+ const firstPacket = await this.getFirstPacket({ metadataOnly: true });
2008
+ endTimestamp += firstPacket?.timestamp ?? 0;
2009
+
2010
+ return endTimestamp;
2011
+ }
2012
+
2013
+ async getLiveRefreshInterval() {
2014
+ return null;
2015
+ }
2016
+
2017
+ async getFirstPacket(options: PacketRetrievalOptions) {
2018
+ return this.performClusterLookup(
2019
+ null,
2020
+ (cluster) => {
2021
+ const trackData = cluster.trackData.get(this.internalTrack.id);
2022
+ if (trackData) {
2023
+ return {
2024
+ blockIndex: 0,
2025
+ correctBlockFound: true,
2026
+ };
2027
+ }
2028
+
2029
+ return {
2030
+ blockIndex: -1,
2031
+ correctBlockFound: false,
2032
+ };
2033
+ },
2034
+ -Infinity, // Use -Infinity as a search timestamp to avoid using the cues
2035
+ Infinity,
2036
+ options,
2037
+ );
2038
+ }
2039
+
2040
+ private intoTimescale(timestamp: number) {
2041
+ // Do a little rounding to catch cases where the result is very close to an integer. If it is, it's likely
2042
+ // that the number was originally an integer divided by the timescale. For stability, it's best
2043
+ // to return the integer in this case.
2044
+ return roundIfAlmostInteger(timestamp * this.internalTrack.segment.timestampFactor);
2045
+ }
2046
+
2047
+ async getPacket(timestamp: number, options: PacketRetrievalOptions) {
2048
+ const timestampInTimescale = this.intoTimescale(timestamp);
2049
+
2050
+ return this.performClusterLookup(
2051
+ null,
2052
+ (cluster) => {
2053
+ const trackData = cluster.trackData.get(this.internalTrack.id);
2054
+ if (!trackData) {
2055
+ return { blockIndex: -1, correctBlockFound: false };
2056
+ }
2057
+
2058
+ const index = binarySearchLessOrEqual(
2059
+ trackData.presentationTimestamps,
2060
+ timestampInTimescale,
2061
+ x => x.timestamp,
2062
+ );
2063
+
2064
+ const blockIndex = index !== -1 ? trackData.presentationTimestamps[index]!.blockIndex : -1;
2065
+ const correctBlockFound = index !== -1 && timestampInTimescale < trackData.endTimestamp;
2066
+
2067
+ return { blockIndex, correctBlockFound };
2068
+ },
2069
+ timestampInTimescale,
2070
+ timestampInTimescale,
2071
+ options,
2072
+ );
2073
+ }
2074
+
2075
+ async getNextPacket(packet: EncodedPacket, options: PacketRetrievalOptions) {
2076
+ const locationInCluster = this.packetToClusterLocation.get(packet);
2077
+ if (locationInCluster === undefined) {
2078
+ throw new Error('Packet was not created from this track.');
2079
+ }
2080
+
2081
+ return this.performClusterLookup(
2082
+ locationInCluster.cluster,
2083
+ (cluster) => {
2084
+ if (cluster === locationInCluster.cluster) {
2085
+ const trackData = cluster.trackData.get(this.internalTrack.id)!;
2086
+ if (locationInCluster.blockIndex + 1 < trackData.blocks.length) {
2087
+ // We can simply take the next block in the cluster
2088
+ return {
2089
+ blockIndex: locationInCluster.blockIndex + 1,
2090
+ correctBlockFound: true,
2091
+ };
2092
+ }
2093
+ } else {
2094
+ const trackData = cluster.trackData.get(this.internalTrack.id);
2095
+ if (trackData) {
2096
+ return {
2097
+ blockIndex: 0,
2098
+ correctBlockFound: true,
2099
+ };
2100
+ }
2101
+ }
2102
+
2103
+ return {
2104
+ blockIndex: -1,
2105
+ correctBlockFound: false,
2106
+ };
2107
+ },
2108
+ -Infinity, // Use -Infinity as a search timestamp to avoid using the cues
2109
+ Infinity,
2110
+ options,
2111
+ );
2112
+ }
2113
+
2114
+ async getKeyPacket(timestamp: number, options: PacketRetrievalOptions) {
2115
+ const timestampInTimescale = this.intoTimescale(timestamp);
2116
+
2117
+ return this.performClusterLookup(
2118
+ null,
2119
+ (cluster) => {
2120
+ const trackData = cluster.trackData.get(this.internalTrack.id);
2121
+ if (!trackData) {
2122
+ return { blockIndex: -1, correctBlockFound: false };
2123
+ }
2124
+
2125
+ const index = findLastIndex(trackData.presentationTimestamps, (x) => {
2126
+ const block = trackData.blocks[x.blockIndex]!;
2127
+ return block.isKeyFrame && x.timestamp <= timestampInTimescale;
2128
+ });
2129
+
2130
+ const blockIndex = index !== -1 ? trackData.presentationTimestamps[index]!.blockIndex : -1;
2131
+ const correctBlockFound = index !== -1 && timestampInTimescale < trackData.endTimestamp;
2132
+
2133
+ return { blockIndex, correctBlockFound };
2134
+ },
2135
+ timestampInTimescale,
2136
+ timestampInTimescale,
2137
+ options,
2138
+ );
2139
+ }
2140
+
2141
+ async getNextKeyPacket(packet: EncodedPacket, options: PacketRetrievalOptions) {
2142
+ const locationInCluster = this.packetToClusterLocation.get(packet);
2143
+ if (locationInCluster === undefined) {
2144
+ throw new Error('Packet was not created from this track.');
2145
+ }
2146
+
2147
+ return this.performClusterLookup(
2148
+ locationInCluster.cluster,
2149
+ (cluster) => {
2150
+ if (cluster === locationInCluster.cluster) {
2151
+ const trackData = cluster.trackData.get(this.internalTrack.id)!;
2152
+ const nextKeyFrameIndex = trackData.blocks.findIndex(
2153
+ (x, i) => x.isKeyFrame && i > locationInCluster.blockIndex,
2154
+ );
2155
+
2156
+ if (nextKeyFrameIndex !== -1) {
2157
+ // We can simply take the next key frame in the cluster
2158
+ return {
2159
+ blockIndex: nextKeyFrameIndex,
2160
+ correctBlockFound: true,
2161
+ };
2162
+ }
2163
+ } else {
2164
+ const trackData = cluster.trackData.get(this.internalTrack.id);
2165
+ if (trackData && trackData.firstKeyFrameTimestamp !== null) {
2166
+ const keyFrameIndex = trackData.blocks.findIndex(x => x.isKeyFrame);
2167
+ assert(keyFrameIndex !== -1); // There must be one
2168
+
2169
+ return {
2170
+ blockIndex: keyFrameIndex,
2171
+ correctBlockFound: true,
2172
+ };
2173
+ }
2174
+ }
2175
+
2176
+ return {
2177
+ blockIndex: -1,
2178
+ correctBlockFound: false,
2179
+ };
2180
+ },
2181
+ -Infinity, // Use -Infinity as a search timestamp to avoid using the cues
2182
+ Infinity,
2183
+ options,
2184
+ );
2185
+ }
2186
+
2187
+ private async fetchPacketInCluster(cluster: Cluster, blockIndex: number, options: PacketRetrievalOptions) {
2188
+ if (blockIndex === -1) {
2189
+ return null;
2190
+ }
2191
+
2192
+ const trackData = cluster.trackData.get(this.internalTrack.id)!;
2193
+ const block = trackData.blocks[blockIndex];
2194
+ assert(block);
2195
+
2196
+ // Perform lazy decoding if needed
2197
+ if (!block.decoded) {
2198
+ block.data = this.internalTrack.demuxer.decodeBlockData(this.internalTrack, block.data);
2199
+ block.decoded = true;
2200
+ }
2201
+
2202
+ if (!block.postProcessed) {
2203
+ if (this.internalTrack.info?.codec === 'prores') {
2204
+ // For some reason, ProRes packets are stored in Matroska without the frame container atom. FFmpeg cites
2205
+ // the "Matroska spec" but the actual spec says nothing about this.
2206
+
2207
+ const hasFrameContainer = block.data.length >= 8
2208
+ && block.data[4] === 105 // 'i'
2209
+ && block.data[5] === 99 // 'c'
2210
+ && block.data[6] === 112 // 'p'
2211
+ && block.data[7] === 102; // 'f'
2212
+
2213
+ if (!hasFrameContainer) {
2214
+ // Wrap the frame in a frame container
2215
+ const newData = new Uint8Array(block.data.length + 8);
2216
+ const newDataView = toDataView(newData);
2217
+
2218
+ newDataView.setUint32(0, newData.length, false);
2219
+ newData[4] = 105; // 'i'
2220
+ newData[5] = 99; // 'c'
2221
+ newData[6] = 112; // 'p'
2222
+ newData[7] = 102; // 'f'
2223
+ newData.set(block.data, 8);
2224
+ block.data = newData;
2225
+ }
2226
+ }
2227
+
2228
+ block.postProcessed = true;
2229
+ }
2230
+
2231
+ const data = options.metadataOnly ? PLACEHOLDER_DATA : block.data;
2232
+ const timestamp = block.timestamp / this.internalTrack.segment.timestampFactor;
2233
+ const duration = block.duration / this.internalTrack.segment.timestampFactor;
2234
+
2235
+ const sideData: EncodedPacketSideData = {};
2236
+ if (block.mainAdditional && this.internalTrack.info?.type === 'video' && this.internalTrack.info.alphaMode) {
2237
+ sideData.alpha = options.metadataOnly ? PLACEHOLDER_DATA : block.mainAdditional;
2238
+ sideData.alphaByteLength = block.mainAdditional.byteLength;
2239
+ }
2240
+
2241
+ const packet = new EncodedPacket(
2242
+ data,
2243
+ block.isKeyFrame ? 'key' : 'delta',
2244
+ timestamp,
2245
+ duration,
2246
+ cluster.dataStartPos + blockIndex,
2247
+ block.data.byteLength,
2248
+ sideData,
2249
+ );
2250
+
2251
+ this.packetToClusterLocation.set(packet, { cluster, blockIndex });
2252
+
2253
+ return packet;
2254
+ }
2255
+
2256
+ /** Looks for a packet in the clusters while trying to load as few clusters as possible to retrieve it. */
2257
+ private async performClusterLookup(
2258
+ // The cluster where we start looking
2259
+ startCluster: Cluster | null,
2260
+ // This function returns the best-matching block in a given cluster
2261
+ getMatchInCluster: (cluster: Cluster) => { blockIndex: number; correctBlockFound: boolean },
2262
+ // The timestamp with which we can search the lookup table
2263
+ searchTimestamp: number,
2264
+ // The timestamp for which we know the correct block will not come after it
2265
+ latestTimestamp: number,
2266
+ options: PacketRetrievalOptions,
2267
+ ): Promise<EncodedPacket | null> {
2268
+ const { demuxer, segment } = this.internalTrack;
2269
+
2270
+ let currentCluster: Cluster | null = null;
2271
+ let bestCluster: Cluster | null = null;
2272
+ let bestBlockIndex = -1;
2273
+
2274
+ if (startCluster) {
2275
+ const { blockIndex, correctBlockFound } = getMatchInCluster(startCluster);
2276
+
2277
+ if (correctBlockFound) {
2278
+ return this.fetchPacketInCluster(startCluster, blockIndex, options);
2279
+ }
2280
+
2281
+ if (blockIndex !== -1) {
2282
+ bestCluster = startCluster;
2283
+ bestBlockIndex = blockIndex;
2284
+ }
2285
+ }
2286
+
2287
+ // Search for a cue point; this way, we won't need to start searching from the start of the file
2288
+ // but can jump right into the correct cluster (or at least nearby).
2289
+ const cuePointIndex = binarySearchLessOrEqual(
2290
+ this.internalTrack.cuePoints,
2291
+ searchTimestamp,
2292
+ x => x.time,
2293
+ );
2294
+ const cuePoint = cuePointIndex !== -1
2295
+ ? this.internalTrack.cuePoints[cuePointIndex]!
2296
+ : null;
2297
+
2298
+ // Also check the position cache
2299
+ const positionCacheIndex = binarySearchLessOrEqual(
2300
+ this.internalTrack.clusterPositionCache,
2301
+ searchTimestamp,
2302
+ x => x.startTimestamp,
2303
+ );
2304
+ const positionCacheEntry = positionCacheIndex !== -1
2305
+ ? this.internalTrack.clusterPositionCache[positionCacheIndex]!
2306
+ : null;
2307
+
2308
+ const lookupEntryPosition = Math.max(
2309
+ cuePoint?.clusterPosition ?? 0,
2310
+ positionCacheEntry?.elementStartPos ?? 0,
2311
+ ) || null;
2312
+
2313
+ let currentPos: number;
2314
+
2315
+ if (!startCluster) {
2316
+ currentPos = lookupEntryPosition ?? segment.clusterSeekStartPos;
2317
+ } else {
2318
+ if (lookupEntryPosition === null || startCluster.elementStartPos >= lookupEntryPosition) {
2319
+ currentPos = startCluster.elementEndPos;
2320
+ currentCluster = startCluster;
2321
+ } else {
2322
+ // Use the lookup entry
2323
+ currentPos = lookupEntryPosition;
2324
+ }
2325
+ }
2326
+
2327
+ while (segment.elementEndPos === null || currentPos <= segment.elementEndPos - MIN_HEADER_SIZE) {
2328
+ if (currentCluster) {
2329
+ const trackData = currentCluster.trackData.get(this.internalTrack.id);
2330
+ if (trackData && trackData.startTimestamp > latestTimestamp) {
2331
+ // We're already past the upper bound, no need to keep searching
2332
+ break;
2333
+ }
2334
+ }
2335
+
2336
+ // Load the header
2337
+ let slice = demuxer.reader.requestSliceRange(currentPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
2338
+ if (slice instanceof Promise) slice = await slice;
2339
+ if (!slice) break;
2340
+
2341
+ const elementStartPos = currentPos;
2342
+ const elementHeader = readElementHeader(slice);
2343
+
2344
+ if (
2345
+ !elementHeader
2346
+ || (!LEVEL_1_EBML_IDS.includes(elementHeader.id) && elementHeader.id !== EBMLId.Void)
2347
+ ) {
2348
+ // There's an element here that shouldn't be here. Might be garbage. In this case, let's
2349
+ // try and resync to the next valid element.
2350
+ const nextPos = await resync(
2351
+ demuxer.reader,
2352
+ elementStartPos,
2353
+ LEVEL_1_EBML_IDS,
2354
+ Math.min(segment.elementEndPos ?? Infinity, elementStartPos + MAX_RESYNC_LENGTH),
2355
+ );
2356
+
2357
+ if (nextPos) {
2358
+ currentPos = nextPos;
2359
+ continue;
2360
+ } else {
2361
+ break; // Resync failed
2362
+ }
2363
+ }
2364
+
2365
+ const id = elementHeader.id;
2366
+ let size = elementHeader.size;
2367
+ const dataStartPos = slice.filePos;
2368
+
2369
+ if (id === EBMLId.Cluster) {
2370
+ currentCluster = await demuxer.readCluster(elementStartPos, segment);
2371
+ // readCluster computes the proper size even if it's undefined in the header, so let's use that instead
2372
+ size = currentCluster.elementEndPos - dataStartPos;
2373
+
2374
+ const { blockIndex, correctBlockFound } = getMatchInCluster(currentCluster);
2375
+ if (correctBlockFound) {
2376
+ return this.fetchPacketInCluster(currentCluster, blockIndex, options);
2377
+ }
2378
+
2379
+ if (blockIndex !== -1) {
2380
+ bestCluster = currentCluster;
2381
+ bestBlockIndex = blockIndex;
2382
+ }
2383
+ }
2384
+
2385
+ if (size === undefined) {
2386
+ // Undefined element size (can happen in livestreamed files). In this case, we need to do some
2387
+ // searching to determine the actual size of the element.
2388
+
2389
+ assert(id !== EBMLId.Cluster); // Undefined cluster sizes are fixed further up
2390
+
2391
+ // Search for the next element at level 0 or 1
2392
+ const nextElementPos = await searchForNextElementId(
2393
+ demuxer.reader,
2394
+ dataStartPos,
2395
+ LEVEL_0_AND_1_EBML_IDS,
2396
+ segment.elementEndPos,
2397
+ );
2398
+
2399
+ size = nextElementPos.pos - dataStartPos;
2400
+ }
2401
+
2402
+ const endPos = dataStartPos + size;
2403
+ if (segment.elementEndPos === null) {
2404
+ // Check the next element. If it's a new segment, we know this segment ends here. The new
2405
+ // segment is just ignored, since we're likely in a livestreamed file and thus only care about
2406
+ // the first segment.
2407
+
2408
+ let slice = demuxer.reader.requestSliceRange(endPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
2409
+ if (slice instanceof Promise) slice = await slice;
2410
+ if (!slice) break;
2411
+
2412
+ const elementId = readElementId(slice);
2413
+ if (elementId === EBMLId.Segment) {
2414
+ segment.elementEndPos = endPos; // We now know the segment's size
2415
+ break;
2416
+ }
2417
+ }
2418
+
2419
+ currentPos = endPos;
2420
+ }
2421
+
2422
+ // Catch faulty cue points
2423
+ if (cuePoint && (!bestCluster || bestCluster.elementStartPos < cuePoint.clusterPosition)) {
2424
+ // The cue point lied to us! We found a cue point but no cluster there that satisfied the match. In this
2425
+ // case, let's search again but using the cue point before that.
2426
+ const previousCuePoint = this.internalTrack.cuePoints[cuePointIndex - 1];
2427
+ assert(!previousCuePoint || previousCuePoint.time < cuePoint.time);
2428
+
2429
+ const newSearchTimestamp = previousCuePoint?.time ?? -Infinity;
2430
+ return this.performClusterLookup(null, getMatchInCluster, newSearchTimestamp, latestTimestamp, options);
2431
+ }
2432
+
2433
+ if (bestCluster) {
2434
+ // If we finished looping but didn't find a perfect match, still return the best match we found
2435
+ return this.fetchPacketInCluster(bestCluster, bestBlockIndex, options);
2436
+ }
2437
+
2438
+ return null;
2439
+ }
2440
+ }
2441
+
2442
+ class MatroskaVideoTrackBacking extends MatroskaTrackBacking implements InputVideoTrackBacking {
2443
+ override internalTrack: InternalVideoTrack;
2444
+ decoderConfigPromise: Promise<VideoDecoderConfig> | null = null;
2445
+
2446
+ constructor(internalTrack: InternalVideoTrack) {
2447
+ super(internalTrack);
2448
+ this.internalTrack = internalTrack;
2449
+ }
2450
+
2451
+ getType() {
2452
+ return 'video' as const;
2453
+ }
2454
+
2455
+ override getCodec(): VideoCodec | null {
2456
+ return this.internalTrack.info.codec;
2457
+ }
2458
+
2459
+ getCodedWidth() {
2460
+ return this.internalTrack.info.width;
2461
+ }
2462
+
2463
+ getCodedHeight() {
2464
+ return this.internalTrack.info.height;
2465
+ }
2466
+
2467
+ getSquarePixelWidth() {
2468
+ return this.internalTrack.info.squarePixelWidth;
2469
+ }
2470
+
2471
+ getSquarePixelHeight() {
2472
+ return this.internalTrack.info.squarePixelHeight;
2473
+ }
2474
+
2475
+ getRotation() {
2476
+ return this.internalTrack.info.rotation;
2477
+ }
2478
+
2479
+ async getColorSpace(): Promise<VideoColorSpaceInit> {
2480
+ return {
2481
+ primaries: this.internalTrack.info.colorSpace?.primaries,
2482
+ transfer: this.internalTrack.info.colorSpace?.transfer,
2483
+ matrix: this.internalTrack.info.colorSpace?.matrix,
2484
+ fullRange: this.internalTrack.info.colorSpace?.fullRange,
2485
+ };
2486
+ }
2487
+
2488
+ async canBeTransparent() {
2489
+ return this.internalTrack.info.alphaMode || (
2490
+ this.internalTrack.info.codec === 'prores' && (
2491
+ this.internalTrack.info.proresFormat === 'ap4h'
2492
+ || this.internalTrack.info.proresFormat === 'ap4x'
2493
+ )
2494
+ );
2495
+ }
2496
+
2497
+ async getDecoderConfig(): Promise<VideoDecoderConfig | null> {
2498
+ if (!this.internalTrack.info.codec) {
2499
+ return null;
2500
+ }
2501
+
2502
+ return this.decoderConfigPromise ??= (async (): Promise<VideoDecoderConfig> => {
2503
+ let firstPacket: EncodedPacket | null = null;
2504
+ const needsPacketForAdditionalInfo
2505
+ = this.internalTrack.info.codec === 'vp9'
2506
+ || this.internalTrack.info.codec === 'av1'
2507
+ // Packets are in Annex B format:
2508
+ || (this.internalTrack.info.codec === 'avc' && !this.internalTrack.info.codecDescription)
2509
+ // Packets are in Annex B format:
2510
+ || (this.internalTrack.info.codec === 'hevc' && !this.internalTrack.info.codecDescription);
2511
+
2512
+ if (needsPacketForAdditionalInfo) {
2513
+ firstPacket = await this.getFirstPacket({});
2514
+ }
2515
+
2516
+ const config: VideoDecoderConfig = {
2517
+ codec: extractVideoCodecString({
2518
+ width: this.internalTrack.info.width,
2519
+ height: this.internalTrack.info.height,
2520
+ codec: this.internalTrack.info.codec,
2521
+ codecDescription: this.internalTrack.info.codecDescription,
2522
+ colorSpace: this.internalTrack.info.colorSpace,
2523
+ avcType: 1, // We don't know better (or do we?) so just assume 'avc1'
2524
+ avcCodecInfo: this.internalTrack.info.codec === 'avc' && firstPacket
2525
+ ? extractAvcDecoderConfigurationRecord(firstPacket.data)
2526
+ : null,
2527
+ hevcCodecInfo: this.internalTrack.info.codec === 'hevc' && firstPacket
2528
+ ? extractHevcDecoderConfigurationRecord(firstPacket.data)
2529
+ : null,
2530
+ vp9CodecInfo: this.internalTrack.info.codec === 'vp9' && firstPacket
2531
+ ? extractVp9CodecInfoFromPacket(firstPacket.data)
2532
+ : null,
2533
+ av1CodecInfo: this.internalTrack.info.codec === 'av1' && firstPacket
2534
+ ? extractAv1CodecInfoFromPacket(firstPacket.data)
2535
+ : null,
2536
+ proresFormat: this.internalTrack.info.proresFormat,
2537
+ }),
2538
+ codedWidth: this.internalTrack.info.width,
2539
+ codedHeight: this.internalTrack.info.height,
2540
+ description: this.internalTrack.info.codecDescription ?? undefined,
2541
+ colorSpace: this.internalTrack.info.colorSpace ?? undefined,
2542
+ };
2543
+
2544
+ if (
2545
+ this.internalTrack.info.width !== this.internalTrack.info.squarePixelWidth
2546
+ || this.internalTrack.info.height !== this.internalTrack.info.squarePixelHeight
2547
+ ) {
2548
+ config.displayAspectWidth = this.internalTrack.info.squarePixelWidth;
2549
+ config.displayAspectHeight = this.internalTrack.info.squarePixelHeight;
2550
+ }
2551
+
2552
+ return config;
2553
+ })();
2554
+ }
2555
+ }
2556
+
2557
+ class MatroskaAudioTrackBacking extends MatroskaTrackBacking implements InputAudioTrackBacking {
2558
+ override internalTrack: InternalAudioTrack;
2559
+ decoderConfig: AudioDecoderConfig | null = null;
2560
+
2561
+ constructor(internalTrack: InternalAudioTrack) {
2562
+ super(internalTrack);
2563
+ this.internalTrack = internalTrack;
2564
+ }
2565
+
2566
+ getType() {
2567
+ return 'audio' as const;
2568
+ }
2569
+
2570
+ override getCodec(): AudioCodec | null {
2571
+ return this.internalTrack.info.codec;
2572
+ }
2573
+
2574
+ getNumberOfChannels() {
2575
+ return this.internalTrack.info.numberOfChannels;
2576
+ }
2577
+
2578
+ getSampleRate() {
2579
+ return this.internalTrack.info.sampleRate;
2580
+ }
2581
+
2582
+ async getDecoderConfig(): Promise<AudioDecoderConfig | null> {
2583
+ if (!this.internalTrack.info.codec) {
2584
+ return null;
2585
+ }
2586
+
2587
+ return this.decoderConfig ??= {
2588
+ codec: extractAudioCodecString({
2589
+ codec: this.internalTrack.info.codec,
2590
+ codecDescription: this.internalTrack.info.codecDescription,
2591
+ aacCodecInfo: this.internalTrack.info.aacCodecInfo,
2592
+ }),
2593
+ numberOfChannels: this.internalTrack.info.numberOfChannels,
2594
+ sampleRate: this.internalTrack.info.sampleRate,
2595
+ description: this.internalTrack.info.codecDescription ?? undefined,
2596
+ };
2597
+ }
2598
+ }