node-av-lgpl 0.0.0 → 7.1.0-beta.2

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 (311) hide show
  1. package/LICENSE.md +22 -0
  2. package/README.md +711 -0
  3. package/dist/api/audio-frame-buffer.d.ts +636 -0
  4. package/dist/api/audio-frame-buffer.js +1027 -0
  5. package/dist/api/audio-frame-buffer.js.map +1 -0
  6. package/dist/api/bitstream-filter.d.ts +938 -0
  7. package/dist/api/bitstream-filter.js +1427 -0
  8. package/dist/api/bitstream-filter.js.map +1 -0
  9. package/dist/api/constants.d.ts +44 -0
  10. package/dist/api/constants.js +45 -0
  11. package/dist/api/constants.js.map +1 -0
  12. package/dist/api/data/test_av1.ivf +0 -0
  13. package/dist/api/data/test_h264.h264 +0 -0
  14. package/dist/api/data/test_hevc.h265 +0 -0
  15. package/dist/api/data/test_mjpeg.mjpeg +0 -0
  16. package/dist/api/data/test_vp8.ivf +0 -0
  17. package/dist/api/data/test_vp9.ivf +0 -0
  18. package/dist/api/decoder.d.ts +1413 -0
  19. package/dist/api/decoder.js +2367 -0
  20. package/dist/api/decoder.js.map +1 -0
  21. package/dist/api/demuxer.d.ts +1295 -0
  22. package/dist/api/demuxer.js +2344 -0
  23. package/dist/api/demuxer.js.map +1 -0
  24. package/dist/api/device.d.ts +589 -0
  25. package/dist/api/device.js +964 -0
  26. package/dist/api/device.js.map +1 -0
  27. package/dist/api/encoder-pool.d.ts +262 -0
  28. package/dist/api/encoder-pool.js +397 -0
  29. package/dist/api/encoder-pool.js.map +1 -0
  30. package/dist/api/encoder.d.ts +1509 -0
  31. package/dist/api/encoder.js +2619 -0
  32. package/dist/api/encoder.js.map +1 -0
  33. package/dist/api/filter-complex.d.ts +828 -0
  34. package/dist/api/filter-complex.js +1661 -0
  35. package/dist/api/filter-complex.js.map +1 -0
  36. package/dist/api/filter-presets.d.ts +800 -0
  37. package/dist/api/filter-presets.js +1554 -0
  38. package/dist/api/filter-presets.js.map +1 -0
  39. package/dist/api/filter.d.ts +1339 -0
  40. package/dist/api/filter.js +2075 -0
  41. package/dist/api/filter.js.map +1 -0
  42. package/dist/api/fmp4-stream.d.ts +797 -0
  43. package/dist/api/fmp4-stream.js +1428 -0
  44. package/dist/api/fmp4-stream.js.map +1 -0
  45. package/dist/api/hardware.d.ts +677 -0
  46. package/dist/api/hardware.js +1300 -0
  47. package/dist/api/hardware.js.map +1 -0
  48. package/dist/api/index.d.ts +21 -0
  49. package/dist/api/index.js +38 -0
  50. package/dist/api/index.js.map +1 -0
  51. package/dist/api/io-stream.d.ts +308 -0
  52. package/dist/api/io-stream.js +358 -0
  53. package/dist/api/io-stream.js.map +1 -0
  54. package/dist/api/muxer.d.ts +1311 -0
  55. package/dist/api/muxer.js +2672 -0
  56. package/dist/api/muxer.js.map +1 -0
  57. package/dist/api/pipeline.d.ts +801 -0
  58. package/dist/api/pipeline.js +1344 -0
  59. package/dist/api/pipeline.js.map +1 -0
  60. package/dist/api/probe.d.ts +128 -0
  61. package/dist/api/probe.js +227 -0
  62. package/dist/api/probe.js.map +1 -0
  63. package/dist/api/rtp-stream.d.ts +497 -0
  64. package/dist/api/rtp-stream.js +1131 -0
  65. package/dist/api/rtp-stream.js.map +1 -0
  66. package/dist/api/scaler.d.ts +561 -0
  67. package/dist/api/scaler.js +918 -0
  68. package/dist/api/scaler.js.map +1 -0
  69. package/dist/api/types.d.ts +17 -0
  70. package/dist/api/types.js +2 -0
  71. package/dist/api/types.js.map +1 -0
  72. package/dist/api/utilities/async-queue.d.ts +149 -0
  73. package/dist/api/utilities/async-queue.js +254 -0
  74. package/dist/api/utilities/async-queue.js.map +1 -0
  75. package/dist/api/utilities/audio-sample.d.ts +117 -0
  76. package/dist/api/utilities/audio-sample.js +112 -0
  77. package/dist/api/utilities/audio-sample.js.map +1 -0
  78. package/dist/api/utilities/audio-transcode.d.ts +20 -0
  79. package/dist/api/utilities/audio-transcode.js +27 -0
  80. package/dist/api/utilities/audio-transcode.js.map +1 -0
  81. package/dist/api/utilities/channel-layout.d.ts +76 -0
  82. package/dist/api/utilities/channel-layout.js +80 -0
  83. package/dist/api/utilities/channel-layout.js.map +1 -0
  84. package/dist/api/utilities/codec-format.d.ts +87 -0
  85. package/dist/api/utilities/codec-format.js +117 -0
  86. package/dist/api/utilities/codec-format.js.map +1 -0
  87. package/dist/api/utilities/context-options.d.ts +25 -0
  88. package/dist/api/utilities/context-options.js +23 -0
  89. package/dist/api/utilities/context-options.js.map +1 -0
  90. package/dist/api/utilities/electron-shared-texture.d.ts +368 -0
  91. package/dist/api/utilities/electron-shared-texture.js +540 -0
  92. package/dist/api/utilities/electron-shared-texture.js.map +1 -0
  93. package/dist/api/utilities/image.d.ts +207 -0
  94. package/dist/api/utilities/image.js +213 -0
  95. package/dist/api/utilities/image.js.map +1 -0
  96. package/dist/api/utilities/index.d.ts +14 -0
  97. package/dist/api/utilities/index.js +27 -0
  98. package/dist/api/utilities/index.js.map +1 -0
  99. package/dist/api/utilities/live-decoding.d.ts +15 -0
  100. package/dist/api/utilities/live-decoding.js +32 -0
  101. package/dist/api/utilities/live-decoding.js.map +1 -0
  102. package/dist/api/utilities/media-type.d.ts +49 -0
  103. package/dist/api/utilities/media-type.js +53 -0
  104. package/dist/api/utilities/media-type.js.map +1 -0
  105. package/dist/api/utilities/packet-age-watchdog.d.ts +198 -0
  106. package/dist/api/utilities/packet-age-watchdog.js +594 -0
  107. package/dist/api/utilities/packet-age-watchdog.js.map +1 -0
  108. package/dist/api/utilities/pixel-format.d.ts +89 -0
  109. package/dist/api/utilities/pixel-format.js +97 -0
  110. package/dist/api/utilities/pixel-format.js.map +1 -0
  111. package/dist/api/utilities/sample-format.d.ts +129 -0
  112. package/dist/api/utilities/sample-format.js +141 -0
  113. package/dist/api/utilities/sample-format.js.map +1 -0
  114. package/dist/api/utilities/scale-size.d.ts +51 -0
  115. package/dist/api/utilities/scale-size.js +55 -0
  116. package/dist/api/utilities/scale-size.js.map +1 -0
  117. package/dist/api/utilities/scheduler.d.ts +138 -0
  118. package/dist/api/utilities/scheduler.js +98 -0
  119. package/dist/api/utilities/scheduler.js.map +1 -0
  120. package/dist/api/utilities/streaming.d.ts +186 -0
  121. package/dist/api/utilities/streaming.js +309 -0
  122. package/dist/api/utilities/streaming.js.map +1 -0
  123. package/dist/api/utilities/timestamp.d.ts +193 -0
  124. package/dist/api/utilities/timestamp.js +206 -0
  125. package/dist/api/utilities/timestamp.js.map +1 -0
  126. package/dist/api/utilities/video-transcode.d.ts +218 -0
  127. package/dist/api/utilities/video-transcode.js +624 -0
  128. package/dist/api/utilities/video-transcode.js.map +1 -0
  129. package/dist/api/utilities/whisper-model.d.ts +330 -0
  130. package/dist/api/utilities/whisper-model.js +587 -0
  131. package/dist/api/utilities/whisper-model.js.map +1 -0
  132. package/dist/api/utils.d.ts +19 -0
  133. package/dist/api/utils.js +39 -0
  134. package/dist/api/utils.js.map +1 -0
  135. package/dist/api/webrtc-stream.d.ts +294 -0
  136. package/dist/api/webrtc-stream.js +546 -0
  137. package/dist/api/webrtc-stream.js.map +1 -0
  138. package/dist/api/whisper.d.ts +326 -0
  139. package/dist/api/whisper.js +402 -0
  140. package/dist/api/whisper.js.map +1 -0
  141. package/dist/constants/bsf-options.d.ts +364 -0
  142. package/dist/constants/bsf-options.js +7 -0
  143. package/dist/constants/bsf-options.js.map +1 -0
  144. package/dist/constants/channel-layouts.d.ts +53 -0
  145. package/dist/constants/channel-layouts.js +57 -0
  146. package/dist/constants/channel-layouts.js.map +1 -0
  147. package/dist/constants/constants.d.ts +2435 -0
  148. package/dist/constants/constants.js +1989 -0
  149. package/dist/constants/constants.js.map +1 -0
  150. package/dist/constants/decoders.d.ts +651 -0
  151. package/dist/constants/decoders.js +641 -0
  152. package/dist/constants/decoders.js.map +1 -0
  153. package/dist/constants/encoders.d.ts +314 -0
  154. package/dist/constants/encoders.js +309 -0
  155. package/dist/constants/encoders.js.map +1 -0
  156. package/dist/constants/filter-options.d.ts +12099 -0
  157. package/dist/constants/filter-options.js +7 -0
  158. package/dist/constants/filter-options.js.map +1 -0
  159. package/dist/constants/format-options.d.ts +4319 -0
  160. package/dist/constants/format-options.js +7 -0
  161. package/dist/constants/format-options.js.map +1 -0
  162. package/dist/constants/formats.d.ts +18 -0
  163. package/dist/constants/formats.js +7 -0
  164. package/dist/constants/formats.js.map +1 -0
  165. package/dist/constants/hardware.d.ts +26 -0
  166. package/dist/constants/hardware.js +27 -0
  167. package/dist/constants/hardware.js.map +1 -0
  168. package/dist/constants/index.d.ts +10 -0
  169. package/dist/constants/index.js +6 -0
  170. package/dist/constants/index.js.map +1 -0
  171. package/dist/constants/options.d.ts +6217 -0
  172. package/dist/constants/options.js +7 -0
  173. package/dist/constants/options.js.map +1 -0
  174. package/dist/ffmpeg/index.d.ts +101 -0
  175. package/dist/ffmpeg/index.js +161 -0
  176. package/dist/ffmpeg/index.js.map +1 -0
  177. package/dist/ffmpeg/version.d.ts +6 -0
  178. package/dist/ffmpeg/version.js +7 -0
  179. package/dist/ffmpeg/version.js.map +1 -0
  180. package/dist/index.d.ts +4 -0
  181. package/dist/index.js +9 -0
  182. package/dist/index.js.map +1 -0
  183. package/dist/lib/audio-fifo.d.ts +399 -0
  184. package/dist/lib/audio-fifo.js +431 -0
  185. package/dist/lib/audio-fifo.js.map +1 -0
  186. package/dist/lib/binding.d.ts +242 -0
  187. package/dist/lib/binding.js +102 -0
  188. package/dist/lib/binding.js.map +1 -0
  189. package/dist/lib/bitstream-filter-context.d.ts +381 -0
  190. package/dist/lib/bitstream-filter-context.js +443 -0
  191. package/dist/lib/bitstream-filter-context.js.map +1 -0
  192. package/dist/lib/bitstream-filter.d.ts +140 -0
  193. package/dist/lib/bitstream-filter.js +154 -0
  194. package/dist/lib/bitstream-filter.js.map +1 -0
  195. package/dist/lib/codec-context.d.ts +1069 -0
  196. package/dist/lib/codec-context.js +1336 -0
  197. package/dist/lib/codec-context.js.map +1 -0
  198. package/dist/lib/codec-parameters.d.ts +664 -0
  199. package/dist/lib/codec-parameters.js +813 -0
  200. package/dist/lib/codec-parameters.js.map +1 -0
  201. package/dist/lib/codec-parser.d.ts +201 -0
  202. package/dist/lib/codec-parser.js +213 -0
  203. package/dist/lib/codec-parser.js.map +1 -0
  204. package/dist/lib/codec.d.ts +617 -0
  205. package/dist/lib/codec.js +746 -0
  206. package/dist/lib/codec.js.map +1 -0
  207. package/dist/lib/device.d.ts +294 -0
  208. package/dist/lib/device.js +326 -0
  209. package/dist/lib/device.js.map +1 -0
  210. package/dist/lib/dictionary.d.ts +333 -0
  211. package/dist/lib/dictionary.js +372 -0
  212. package/dist/lib/dictionary.js.map +1 -0
  213. package/dist/lib/error.d.ts +311 -0
  214. package/dist/lib/error.js +395 -0
  215. package/dist/lib/error.js.map +1 -0
  216. package/dist/lib/fifo.d.ts +416 -0
  217. package/dist/lib/fifo.js +453 -0
  218. package/dist/lib/fifo.js.map +1 -0
  219. package/dist/lib/filter-context.d.ts +714 -0
  220. package/dist/lib/filter-context.js +783 -0
  221. package/dist/lib/filter-context.js.map +1 -0
  222. package/dist/lib/filter-graph-segment.d.ts +161 -0
  223. package/dist/lib/filter-graph-segment.js +172 -0
  224. package/dist/lib/filter-graph-segment.js.map +1 -0
  225. package/dist/lib/filter-graph.d.ts +641 -0
  226. package/dist/lib/filter-graph.js +704 -0
  227. package/dist/lib/filter-graph.js.map +1 -0
  228. package/dist/lib/filter-inout.d.ts +202 -0
  229. package/dist/lib/filter-inout.js +261 -0
  230. package/dist/lib/filter-inout.js.map +1 -0
  231. package/dist/lib/filter.d.ts +243 -0
  232. package/dist/lib/filter.js +272 -0
  233. package/dist/lib/filter.js.map +1 -0
  234. package/dist/lib/format-context.d.ts +1335 -0
  235. package/dist/lib/format-context.js +1455 -0
  236. package/dist/lib/format-context.js.map +1 -0
  237. package/dist/lib/frame-utils.d.ts +116 -0
  238. package/dist/lib/frame-utils.js +98 -0
  239. package/dist/lib/frame-utils.js.map +1 -0
  240. package/dist/lib/frame.d.ts +1315 -0
  241. package/dist/lib/frame.js +1535 -0
  242. package/dist/lib/frame.js.map +1 -0
  243. package/dist/lib/hardware-device-context.d.ts +362 -0
  244. package/dist/lib/hardware-device-context.js +383 -0
  245. package/dist/lib/hardware-device-context.js.map +1 -0
  246. package/dist/lib/hardware-frames-context.d.ts +418 -0
  247. package/dist/lib/hardware-frames-context.js +471 -0
  248. package/dist/lib/hardware-frames-context.js.map +1 -0
  249. package/dist/lib/index.d.ts +35 -0
  250. package/dist/lib/index.js +60 -0
  251. package/dist/lib/index.js.map +1 -0
  252. package/dist/lib/input-format.d.ts +249 -0
  253. package/dist/lib/input-format.js +306 -0
  254. package/dist/lib/input-format.js.map +1 -0
  255. package/dist/lib/io-context.d.ts +698 -0
  256. package/dist/lib/io-context.js +771 -0
  257. package/dist/lib/io-context.js.map +1 -0
  258. package/dist/lib/log.d.ts +174 -0
  259. package/dist/lib/log.js +184 -0
  260. package/dist/lib/log.js.map +1 -0
  261. package/dist/lib/native-types.d.ts +1024 -0
  262. package/dist/lib/native-types.js +2 -0
  263. package/dist/lib/native-types.js.map +1 -0
  264. package/dist/lib/option.d.ts +953 -0
  265. package/dist/lib/option.js +1607 -0
  266. package/dist/lib/option.js.map +1 -0
  267. package/dist/lib/output-format.d.ts +222 -0
  268. package/dist/lib/output-format.js +259 -0
  269. package/dist/lib/output-format.js.map +1 -0
  270. package/dist/lib/packet.d.ts +521 -0
  271. package/dist/lib/packet.js +613 -0
  272. package/dist/lib/packet.js.map +1 -0
  273. package/dist/lib/rational.d.ts +251 -0
  274. package/dist/lib/rational.js +278 -0
  275. package/dist/lib/rational.js.map +1 -0
  276. package/dist/lib/software-resample-context.d.ts +552 -0
  277. package/dist/lib/software-resample-context.js +592 -0
  278. package/dist/lib/software-resample-context.js.map +1 -0
  279. package/dist/lib/software-scale-context.d.ts +344 -0
  280. package/dist/lib/software-scale-context.js +366 -0
  281. package/dist/lib/software-scale-context.js.map +1 -0
  282. package/dist/lib/stream.d.ts +384 -0
  283. package/dist/lib/stream.js +525 -0
  284. package/dist/lib/stream.js.map +1 -0
  285. package/dist/lib/sync-queue.d.ts +179 -0
  286. package/dist/lib/sync-queue.js +197 -0
  287. package/dist/lib/sync-queue.js.map +1 -0
  288. package/dist/lib/types.d.ts +34 -0
  289. package/dist/lib/types.js +2 -0
  290. package/dist/lib/types.js.map +1 -0
  291. package/dist/lib/utilities.d.ts +1198 -0
  292. package/dist/lib/utilities.js +1302 -0
  293. package/dist/lib/utilities.js.map +1 -0
  294. package/dist/utils/electron.d.ts +49 -0
  295. package/dist/utils/electron.js +63 -0
  296. package/dist/utils/electron.js.map +1 -0
  297. package/dist/utils/index.d.ts +6 -0
  298. package/dist/utils/index.js +7 -0
  299. package/dist/utils/index.js.map +1 -0
  300. package/dist/utils/libc.d.ts +11 -0
  301. package/dist/utils/libc.js +35 -0
  302. package/dist/utils/libc.js.map +1 -0
  303. package/dist/utils/variant.d.ts +26 -0
  304. package/dist/utils/variant.js +31 -0
  305. package/dist/utils/variant.js.map +1 -0
  306. package/dist/webrtc/index.d.ts +4 -0
  307. package/dist/webrtc/index.js +7 -0
  308. package/dist/webrtc/index.js.map +1 -0
  309. package/install/check.js +124 -0
  310. package/install/ffmpeg.js +66 -0
  311. package/package.json +165 -3
@@ -0,0 +1,1300 @@
1
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose, inner;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ if (async) inner = dispose;
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
16
+ env.stack.push({ value: value, dispose: dispose, async: async });
17
+ }
18
+ else if (async) {
19
+ env.stack.push({ async: true });
20
+ }
21
+ return value;
22
+ };
23
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
24
+ return function (env) {
25
+ function fail(e) {
26
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
27
+ env.hasError = true;
28
+ }
29
+ var r, s = 0;
30
+ function next() {
31
+ while (r = env.stack.pop()) {
32
+ try {
33
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
34
+ if (r.dispose) {
35
+ var result = r.dispose.call(r.value);
36
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
37
+ }
38
+ else s |= 1;
39
+ }
40
+ catch (e) {
41
+ fail(e);
42
+ }
43
+ }
44
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
45
+ if (env.hasError) throw env.error;
46
+ }
47
+ return next();
48
+ };
49
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
50
+ var e = new Error(message);
51
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
+ });
53
+ import { readFileSync } from 'node:fs';
54
+ import { join } from 'node:path';
55
+ import { AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX, AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, AV_CODEC_ID_AV1, AV_CODEC_ID_H263, AV_CODEC_ID_H264, AV_CODEC_ID_HEVC, AV_CODEC_ID_MJPEG, AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_MPEG4, AV_CODEC_ID_PRORES, AV_CODEC_ID_VP8, AV_CODEC_ID_VP9, AV_HWDEVICE_TYPE_CUDA, AV_HWDEVICE_TYPE_D3D11VA, AV_HWDEVICE_TYPE_D3D12VA, AV_HWDEVICE_TYPE_DRM, AV_HWDEVICE_TYPE_DXVA2, AV_HWDEVICE_TYPE_MEDIACODEC, AV_HWDEVICE_TYPE_NONE, AV_HWDEVICE_TYPE_OPENCL, AV_HWDEVICE_TYPE_QSV, AV_HWDEVICE_TYPE_RKMPP, AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_VDPAU, AV_HWDEVICE_TYPE_VIDEOTOOLBOX, AV_HWDEVICE_TYPE_VULKAN, AV_PIX_FMT_CUDA, AV_PIX_FMT_D3D11, AV_PIX_FMT_D3D12, AV_PIX_FMT_DRM_PRIME, AV_PIX_FMT_DXVA2_VLD, AV_PIX_FMT_MEDIACODEC, AV_PIX_FMT_NV12, AV_PIX_FMT_OPENCL, AV_PIX_FMT_QSV, AV_PIX_FMT_VAAPI, AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_VULKAN, } from '../constants/constants.js';
56
+ import { Codec } from '../lib/codec.js';
57
+ import { Dictionary } from '../lib/dictionary.js';
58
+ import { FFmpegError } from '../lib/error.js';
59
+ import { HardwareDeviceContext } from '../lib/hardware-device-context.js';
60
+ import { Stream } from '../lib/stream.js';
61
+ import { avGetHardwareDeviceTypeFromName, avIsHardwarePixelFormat } from '../lib/utilities.js';
62
+ import { getDirname } from '../utils/electron.js';
63
+ import { Decoder } from './decoder.js';
64
+ import { Demuxer } from './demuxer.js';
65
+ import { Encoder } from './encoder.js';
66
+ import { FilterAPI } from './filter.js';
67
+ const __dirname = getDirname(import.meta.url);
68
+ const h264Data = join(__dirname, 'data', 'test_h264.h264');
69
+ const hevcData = join(__dirname, 'data', 'test_hevc.h265');
70
+ const vp8Data = join(__dirname, 'data', 'test_vp8.ivf');
71
+ const vp9Data = join(__dirname, 'data', 'test_vp9.ivf');
72
+ const av1Data = join(__dirname, 'data', 'test_av1.ivf');
73
+ const mjpegData = join(__dirname, 'data', 'test_mjpeg.mjpeg');
74
+ /**
75
+ * High-level hardware acceleration management.
76
+ *
77
+ * Provides automatic detection and configuration of hardware acceleration for media processing.
78
+ * Manages device contexts for GPU-accelerated encoding and decoding operations.
79
+ * Supports various hardware types including VideoToolbox, CUDA, VAAPI, D3D11VA, and more.
80
+ * Essential for high-performance video processing with reduced CPU usage.
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * import { HardwareContext } from 'node-av/api';
85
+ * import { AV_HWDEVICE_TYPE_CUDA } from 'node-av/constants';
86
+ *
87
+ * // Auto-detect best available hardware
88
+ * const hw = HardwareContext.auto();
89
+ * if (hw) {
90
+ * console.log(`Using hardware: ${hw.deviceTypeName}`);
91
+ * const decoder = await Decoder.create(stream, { hardware: hw });
92
+ * }
93
+ * ```
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * // Use specific hardware type
98
+ * const hw = HardwareContext.create(AV_HWDEVICE_TYPE_CUDA);
99
+ * const encoderCodec = hw?.getEncoderCodec('h264') ?? FF_ENCODER_LIBX264;
100
+ * const encoder = await Encoder.create(encoderCodec, { ... });
101
+ * hw.dispose();
102
+ * ```
103
+ *
104
+ * @see {@link Decoder} For hardware-accelerated decoding
105
+ * @see {@link Encoder} For hardware-accelerated encoding
106
+ */
107
+ export class HardwareContext {
108
+ static _autoTested = false;
109
+ static _autoCachedType = AV_HWDEVICE_TYPE_NONE;
110
+ static _rockchip;
111
+ _deviceContext;
112
+ _deviceType;
113
+ _deviceTypeName;
114
+ _devicePixelFormat;
115
+ _isDisposed = false;
116
+ /**
117
+ * @param deviceContext - Initialized hardware device context
118
+ *
119
+ * @param deviceType - Hardware device type enum
120
+ *
121
+ * @param deviceTypeName - Human-readable device type name
122
+ *
123
+ * @internal
124
+ */
125
+ constructor(deviceContext, deviceType, deviceTypeName) {
126
+ this._deviceContext = deviceContext;
127
+ this._deviceType = deviceType;
128
+ this._deviceTypeName = deviceTypeName;
129
+ this._devicePixelFormat = this.getHardwareDecoderPixelFormat();
130
+ }
131
+ /**
132
+ * Auto-detect and create the best available hardware context.
133
+ *
134
+ * Tries hardware types in order of preference based on platform.
135
+ * Returns null if no hardware acceleration is available.
136
+ * Platform-specific preference order ensures optimal performance.
137
+ *
138
+ * @param options - Optional hardware configuration
139
+ *
140
+ * @returns Hardware context or null if unavailable
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const hw = HardwareContext.auto();
145
+ * if (hw) {
146
+ * console.log(`Auto-detected: ${hw.deviceTypeName}`);
147
+ * // Use for decoder/encoder
148
+ * }
149
+ * ```
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * // With specific device
154
+ * const hw = HardwareContext.auto({
155
+ * deviceName: '/dev/dri/renderD128'
156
+ * });
157
+ * ```
158
+ *
159
+ * @example
160
+ * ```typescript
161
+ * // Prioritise VAAPI over the platform default (e.g. ahead of QSV on Intel)
162
+ * const hw = HardwareContext.auto({ prefer: AV_HWDEVICE_TYPE_VAAPI });
163
+ * ```
164
+ *
165
+ * @see {@link create} For specific hardware type
166
+ * @see {@link listAvailable} To check available types
167
+ */
168
+ static auto(options = {}) {
169
+ const prefer = options.prefer === undefined ? undefined : Array.isArray(options.prefer) ? options.prefer : [options.prefer];
170
+ const hasOptions = options.device ?? options.options ?? prefer;
171
+ // Use cached device type if no custom options and already tested
172
+ if (!hasOptions && this._autoTested) {
173
+ // No hardware was found during testing
174
+ if (this._autoCachedType === AV_HWDEVICE_TYPE_NONE) {
175
+ return null;
176
+ }
177
+ // Create new instance using cached device type
178
+ return this.create(this._autoCachedType, options.device, options.options);
179
+ }
180
+ // Platform-specific preference order, with any user preference first
181
+ const preferenceOrder = this.getPreferenceOrder(prefer);
182
+ for (const deviceType of preferenceOrder) {
183
+ try {
184
+ let device = options.device;
185
+ if (deviceType === AV_HWDEVICE_TYPE_VAAPI && !device) {
186
+ device = '/dev/dri/renderD128'; // Default VAAPI render node
187
+ }
188
+ const hwCtx = this.createFromType(deviceType, device, options.options);
189
+ const isSupported = hwCtx.testDecoder();
190
+ if (!isSupported) {
191
+ hwCtx.dispose();
192
+ continue;
193
+ }
194
+ // Cache device type if no custom options
195
+ if (!hasOptions) {
196
+ this._autoTested = true;
197
+ this._autoCachedType = deviceType;
198
+ }
199
+ return hwCtx;
200
+ }
201
+ catch {
202
+ // Try next device type
203
+ continue;
204
+ }
205
+ }
206
+ // Cache "no hardware" if no custom options
207
+ if (!hasOptions) {
208
+ this._autoTested = true;
209
+ this._autoCachedType = AV_HWDEVICE_TYPE_NONE;
210
+ }
211
+ return null;
212
+ }
213
+ /**
214
+ * Reset the auto-detection cache.
215
+ *
216
+ * Forces the next call to auto() to re-test hardware availability.
217
+ * Useful for testing or if hardware availability may have changed.
218
+ *
219
+ * @example
220
+ * ```typescript
221
+ * HardwareContext.resetAutoCache();
222
+ * const hw = HardwareContext.auto(); // Will re-test
223
+ * ```
224
+ */
225
+ static resetAutoCache() {
226
+ this._autoCachedType = AV_HWDEVICE_TYPE_NONE;
227
+ this._autoTested = false;
228
+ }
229
+ /**
230
+ * Create a hardware context for a specific device type.
231
+ *
232
+ * Creates and initializes a hardware device context.
233
+ * Throws if the device type is not supported or initialization fails.
234
+ *
235
+ * Direct mapping to av_hwdevice_ctx_create().
236
+ *
237
+ * @param deviceType - Hardware device type from AVHWDeviceType
238
+ *
239
+ * @param device - Optional device specifier (e.g., GPU index, device path)
240
+ *
241
+ * @param options - Optional device initialization options
242
+ *
243
+ * @returns Initialized hardware context or null if HardwareContext could not be created
244
+ *
245
+ * @example
246
+ * ```typescript
247
+ * import { AV_HWDEVICE_TYPE_CUDA } from 'node-av/constants';
248
+ *
249
+ * // CUDA with specific GPU
250
+ * const cuda = HardwareContext.create(AV_HWDEVICE_TYPE_CUDA, '0');
251
+ * ```
252
+ *
253
+ * @example
254
+ * ```typescript
255
+ * import { AV_HWDEVICE_TYPE_VAAPI } from 'node-av/constants';
256
+ *
257
+ * // VAAPI with render device
258
+ * const vaapi = HardwareContext.create(
259
+ * AV_HWDEVICE_TYPE_VAAPI,
260
+ * '/dev/dri/renderD128'
261
+ * );
262
+ * ```
263
+ *
264
+ * @see {@link auto} For automatic detection
265
+ * @see {@link HardwareDeviceContext} For low-level API
266
+ */
267
+ static create(deviceType, device, options) {
268
+ if (typeof deviceType === 'string') {
269
+ deviceType = avGetHardwareDeviceTypeFromName(deviceType);
270
+ }
271
+ if (deviceType === AV_HWDEVICE_TYPE_NONE) {
272
+ return null;
273
+ }
274
+ let hw;
275
+ try {
276
+ hw = this.createFromType(deviceType, device, options);
277
+ }
278
+ catch {
279
+ return null;
280
+ }
281
+ return hw;
282
+ }
283
+ /**
284
+ * Create a derived hardware device context.
285
+ *
286
+ * Creates a new hardware context derived from an existing one.
287
+ * Allows creating contexts on different device types that can share
288
+ * memory or resources with the source device. Useful for cross-device
289
+ * pipelines (e.g., VAAPI → OpenCL, CUDA → Vulkan).
290
+ *
291
+ * Direct mapping to av_hwdevice_ctx_create_derived().
292
+ *
293
+ * @param source - Source hardware context to derive from
294
+ *
295
+ * @param targetType - Target device type to create
296
+ *
297
+ * @returns New hardware context or null if derivation fails
298
+ *
299
+ * @example
300
+ * ```typescript
301
+ * import { AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_OPENCL } from 'node-av/constants';
302
+ *
303
+ * // Create VAAPI device for decoding
304
+ * const vaapi = HardwareContext.create(AV_HWDEVICE_TYPE_VAAPI);
305
+ *
306
+ * // Derive OpenCL device for filtering (shares memory with VAAPI)
307
+ * const opencl = HardwareContext.derive(vaapi, AV_HWDEVICE_TYPE_OPENCL);
308
+ *
309
+ * if (opencl) {
310
+ * // Decode with VAAPI
311
+ * const decoder = await Decoder.create(stream, { hardware: vaapi });
312
+ *
313
+ * // Filter with OpenCL (overrides frame's VAAPI context)
314
+ * const filter = FilterAPI.create('program_opencl=...', { hardware: opencl });
315
+ *
316
+ * for await (const frame of decoder.frames()) {
317
+ * // frame has VAAPI context, but filter uses OpenCL
318
+ * const filtered = await filter.apply(frame);
319
+ * }
320
+ * }
321
+ * ```
322
+ *
323
+ * @example
324
+ * ```typescript
325
+ * // CUDA → Vulkan derivation
326
+ * const cuda = HardwareContext.create(AV_HWDEVICE_TYPE_CUDA);
327
+ * const vulkan = HardwareContext.derive(cuda, AV_HWDEVICE_TYPE_VULKAN);
328
+ * ```
329
+ *
330
+ * @see {@link create} For creating independent device
331
+ */
332
+ static derive(source, targetType) {
333
+ if (!source || source.isDisposed) {
334
+ return null;
335
+ }
336
+ if (typeof targetType === 'string') {
337
+ targetType = avGetHardwareDeviceTypeFromName(targetType);
338
+ }
339
+ if (targetType === AV_HWDEVICE_TYPE_NONE) {
340
+ return null;
341
+ }
342
+ try {
343
+ const derivedDeviceCtx = new HardwareDeviceContext();
344
+ const ret = derivedDeviceCtx.createDerived(source.deviceContext, targetType);
345
+ if (FFmpegError.isFFmpegError(ret)) {
346
+ derivedDeviceCtx.free();
347
+ return null;
348
+ }
349
+ const deviceTypeName = HardwareDeviceContext.getTypeName(targetType);
350
+ if (!deviceTypeName) {
351
+ derivedDeviceCtx.free();
352
+ return null;
353
+ }
354
+ return new HardwareContext(derivedDeviceCtx, targetType, deviceTypeName);
355
+ }
356
+ catch {
357
+ return null;
358
+ }
359
+ }
360
+ /**
361
+ * List all available hardware device types.
362
+ *
363
+ * Enumerates all hardware types supported by the FFmpeg build.
364
+ * Useful for checking hardware capabilities at runtime.
365
+ *
366
+ * Direct mapping to av_hwdevice_iterate_types().
367
+ *
368
+ * @returns Array of available device type names
369
+ *
370
+ * @example
371
+ * ```typescript
372
+ * const available = HardwareContext.listAvailable();
373
+ * console.log('Available hardware:', available.join(', '));
374
+ * // Output: "cuda, vaapi, videotoolbox"
375
+ * ```
376
+ *
377
+ * @see {@link auto} For automatic selection
378
+ */
379
+ static listAvailable() {
380
+ const types = HardwareDeviceContext.iterateTypes();
381
+ const available = [];
382
+ for (const type of types) {
383
+ const name = HardwareDeviceContext.getTypeName(type);
384
+ if (name) {
385
+ available.push(name);
386
+ }
387
+ }
388
+ return available;
389
+ }
390
+ /**
391
+ * Get the hardware device context.
392
+ *
393
+ * Used internally by encoders and decoders for hardware acceleration.
394
+ * Can be assigned to CodecContext.hwDeviceCtx.
395
+ *
396
+ * @example
397
+ * ```typescript
398
+ * codecContext.hwDeviceCtx = hw.deviceContext;
399
+ * ```
400
+ */
401
+ get deviceContext() {
402
+ return this._deviceContext;
403
+ }
404
+ /**
405
+ * Get the device type enum value.
406
+ *
407
+ * @example
408
+ * ```typescript
409
+ * if (hw.deviceType === AV_HWDEVICE_TYPE_CUDA) {
410
+ * console.log('Using NVIDIA GPU');
411
+ * }
412
+ * ```
413
+ */
414
+ get deviceType() {
415
+ return this._deviceType;
416
+ }
417
+ /**
418
+ * Get the hardware device type name.
419
+ *
420
+ * Human-readable device type string.
421
+ *
422
+ * @example
423
+ * ```typescript
424
+ * console.log(`Hardware type: ${hw.deviceTypeName}`);
425
+ * // Output: "cuda" or "videotoolbox" etc.
426
+ * ```
427
+ */
428
+ get deviceTypeName() {
429
+ return this._deviceTypeName;
430
+ }
431
+ /**
432
+ * Get the device pixel format.
433
+ *
434
+ * Hardware-specific pixel format for frame allocation.
435
+ *
436
+ * @example
437
+ * ```typescript
438
+ * frame.format = hw.devicePixelFormat;
439
+ * ```
440
+ */
441
+ get devicePixelFormat() {
442
+ return this._devicePixelFormat;
443
+ }
444
+ /**
445
+ * Check if this hardware context has been disposed.
446
+ *
447
+ * @example
448
+ * ```typescript
449
+ * if (!hw.isDisposed) {
450
+ * hw.dispose();
451
+ * }
452
+ * ```
453
+ */
454
+ get isDisposed() {
455
+ return this._isDisposed;
456
+ }
457
+ /**
458
+ * Get hardware frame constraints.
459
+ *
460
+ * Returns the resolution limits and supported pixel formats for this hardware device.
461
+ * Essential for validating encoder/decoder parameters before initialization.
462
+ *
463
+ * Direct mapping to av_hwdevice_get_hwframe_constraints().
464
+ *
465
+ * @param hwconfig - Optional hardware configuration pointer
466
+ *
467
+ * @returns Constraints object with resolution limits and formats, or null if not available
468
+ *
469
+ * @example
470
+ * ```typescript
471
+ * const hw = HardwareContext.auto();
472
+ * if (hw) {
473
+ * const constraints = hw.getFrameConstraints();
474
+ * if (constraints) {
475
+ * console.log(`Resolution: ${constraints.minWidth}x${constraints.minHeight} to ${constraints.maxWidth}x${constraints.maxHeight}`);
476
+ * console.log('Hardware formats:', constraints.validHwFormats);
477
+ * console.log('Software formats:', constraints.validSwFormats);
478
+ * }
479
+ * }
480
+ * ```
481
+ *
482
+ * @example
483
+ * ```typescript
484
+ * import { AV_HWDEVICE_TYPE_VIDEOTOOLBOX } from 'node-av/constants';
485
+ *
486
+ * // VideoToolbox has resolution limits
487
+ * const hw = HardwareContext.create(AV_HWDEVICE_TYPE_VIDEOTOOLBOX);
488
+ * const constraints = hw?.getFrameConstraints();
489
+ * if (constraints && (width > constraints.maxWidth || height > constraints.maxHeight)) {
490
+ * console.log('Resolution exceeds hardware limits, falling back to software encoder');
491
+ * }
492
+ * ```
493
+ *
494
+ * @see {@link HardwareDeviceContext.getHwframeConstraints} For low-level API
495
+ */
496
+ getFrameConstraints(hwconfig) {
497
+ if (this._isDisposed) {
498
+ return null;
499
+ }
500
+ return this._deviceContext.getHwframeConstraints(hwconfig);
501
+ }
502
+ /**
503
+ * Check if this hardware type supports a specific codec.
504
+ *
505
+ * Queries FFmpeg's codec configurations to verify hardware support.
506
+ * Checks both decoder and encoder support based on parameters.
507
+ *
508
+ * Direct mapping to avcodec_get_hw_config().
509
+ *
510
+ * @param codecId - Codec ID from AVCodecID enum
511
+ *
512
+ * @param isEncoder - Check for encoder support (default: decoder)
513
+ *
514
+ * @returns true if codec is supported
515
+ *
516
+ * @example
517
+ * ```typescript
518
+ * import { AV_CODEC_ID_H264 } from 'node-av/constants';
519
+ *
520
+ * if (hw.supportsCodec(AV_CODEC_ID_H264, true)) {
521
+ * // Can use hardware H.264 encoder
522
+ * }
523
+ * ```
524
+ *
525
+ * @see {@link findSupportedCodecs} For all supported codecs
526
+ */
527
+ supportsCodec(codecId, isEncoder = false) {
528
+ const codecs = Codec.getCodecList();
529
+ for (const codec of codecs) {
530
+ if (codec.id !== codecId)
531
+ continue;
532
+ if (isEncoder && !codec.isEncoder())
533
+ continue;
534
+ if (!isEncoder && !codec.isDecoder())
535
+ continue;
536
+ if (isEncoder ? codec.isHardwareAcceleratedEncoder(this._deviceType) : codec.isHardwareAcceleratedDecoder(this._deviceType)) {
537
+ return true;
538
+ }
539
+ }
540
+ return false;
541
+ }
542
+ /**
543
+ * Check if this hardware supports a specific pixel format for a codec.
544
+ *
545
+ * Verifies pixel format compatibility with hardware codec.
546
+ * Important for ensuring format compatibility in pipelines.
547
+ *
548
+ * @param codecId - Codec ID from AVCodecID enum
549
+ *
550
+ * @param pixelFormat - Pixel format to check
551
+ *
552
+ * @param isEncoder - Check for encoder (default: decoder)
553
+ *
554
+ * @returns true if pixel format is supported
555
+ *
556
+ * @example
557
+ * ```typescript
558
+ * import { AV_CODEC_ID_H264, AV_PIX_FMT_NV12 } from 'node-av/constants';
559
+ *
560
+ * if (hw.supportsPixelFormat(AV_CODEC_ID_H264, AV_PIX_FMT_NV12)) {
561
+ * // Can use NV12 format with H.264
562
+ * }
563
+ * ```
564
+ *
565
+ * @see {@link supportsCodec} For basic codec support
566
+ */
567
+ supportsPixelFormat(codecId, pixelFormat, isEncoder = false) {
568
+ const codecs = Codec.getCodecList();
569
+ for (const codec of codecs) {
570
+ if (codec.id !== codecId)
571
+ continue;
572
+ if (isEncoder && !codec.isEncoder())
573
+ continue;
574
+ if (!isEncoder && !codec.isDecoder())
575
+ continue;
576
+ if (isEncoder ? codec.isHardwareAcceleratedEncoder(this._deviceType) : codec.isHardwareAcceleratedDecoder(this._deviceType)) {
577
+ const pixelFormats = codec.pixelFormats ?? [];
578
+ if (pixelFormats.some((fmt) => fmt === pixelFormat)) {
579
+ return true;
580
+ }
581
+ }
582
+ }
583
+ return false;
584
+ }
585
+ /**
586
+ * Get the appropriate encoder codec for a given base codec name.
587
+ *
588
+ * Maps generic codec names to hardware-specific encoder implementations.
589
+ * Returns null if no hardware encoder is available for the codec.
590
+ * Automatically tests encoder viability before returning.
591
+ *
592
+ * @param codecOrStream - Generic codec name (e.g., 'h264', 'hevc', 'av1'), AVCodecID or Stream
593
+ *
594
+ * @param validate - Whether to validate encoder by testing (default: false)
595
+ *
596
+ * @returns Hardware encoder codec or null if unsupported
597
+ *
598
+ * @example
599
+ * ```typescript
600
+ * const encoderCodec = hw.getEncoderCodec('h264');
601
+ * if (encoderCodec) {
602
+ * console.log(`Using encoder: ${encoderCodec.name}`);
603
+ * // e.g., "h264_nvenc" for CUDA
604
+ * }
605
+ * ```
606
+ *
607
+ * @example
608
+ * ```typescript
609
+ * // Use with Encoder.create
610
+ * const codec = hw.getEncoderCodec('hevc');
611
+ * if (codec) {
612
+ * const encoder = await Encoder.create(codec, { ... });
613
+ * }
614
+ * ```
615
+ *
616
+ * @see {@link Encoder.create} For using the codec
617
+ */
618
+ getEncoderCodec(codecOrStream, validate) {
619
+ // Build the encoder name
620
+ let codecBaseName = null;
621
+ let encoderSuffix = '';
622
+ if (codecOrStream instanceof Stream) {
623
+ const codecParams = codecOrStream.codecpar;
624
+ codecBaseName = this.getBaseCodecName(codecParams.codecId) ?? null;
625
+ }
626
+ else if (typeof codecOrStream === 'number') {
627
+ codecBaseName = this.getBaseCodecName(codecOrStream) ?? null;
628
+ }
629
+ else {
630
+ codecBaseName = codecOrStream;
631
+ }
632
+ if (!codecBaseName) {
633
+ return null;
634
+ }
635
+ const decoderCodecId = this.getCodecIDFromBaseName(codecBaseName);
636
+ // We might only have hardware decode capabilities (d3d11va, d3d12va etc)
637
+ // So we need to check for other hardware encoders
638
+ const getAlternativeEncoder = () => {
639
+ const nvencCodecName = `${codecBaseName}_nvenc`;
640
+ const qsvCodecName = `${codecBaseName}_qsv`;
641
+ const amfCodecName = `${codecBaseName}_amf`;
642
+ const codecNames = [nvencCodecName, qsvCodecName, amfCodecName];
643
+ let suffix = '';
644
+ for (const name of codecNames) {
645
+ const encoderCodec = Codec.findEncoderByName(name);
646
+ if (!encoderCodec) {
647
+ continue;
648
+ }
649
+ suffix = name.split('_')[1]; // Get suffix after underscore
650
+ if (!suffix) {
651
+ return null;
652
+ }
653
+ return suffix;
654
+ }
655
+ return null;
656
+ };
657
+ switch (this._deviceType) {
658
+ case AV_HWDEVICE_TYPE_CUDA:
659
+ // CUDA uses NVENC for encoding
660
+ encoderSuffix = 'nvenc';
661
+ break;
662
+ case AV_HWDEVICE_TYPE_D3D11VA:
663
+ case AV_HWDEVICE_TYPE_DXVA2:
664
+ encoderSuffix = getAlternativeEncoder() ?? '';
665
+ break;
666
+ case AV_HWDEVICE_TYPE_OPENCL:
667
+ case AV_HWDEVICE_TYPE_VDPAU:
668
+ case AV_HWDEVICE_TYPE_DRM:
669
+ encoderSuffix = getAlternativeEncoder() ?? '';
670
+ break;
671
+ default:
672
+ // Use the device type name as suffix
673
+ encoderSuffix = this._deviceTypeName;
674
+ }
675
+ if (!encoderSuffix) {
676
+ return null;
677
+ }
678
+ // Construct the encoder name
679
+ const encoderName = `${codecBaseName}_${encoderSuffix}`;
680
+ const encoderCodec = Codec.findEncoderByName(encoderName);
681
+ if (!encoderCodec?.isHardwareAcceleratedEncoder()) {
682
+ return null;
683
+ }
684
+ if (validate && decoderCodecId !== null) {
685
+ const isValid = this.testEncoder(decoderCodecId, encoderCodec);
686
+ if (!isValid) {
687
+ return null;
688
+ }
689
+ }
690
+ return encoderCodec;
691
+ }
692
+ /**
693
+ * Get the appropriate decoder codec for a given base codec name.
694
+ *
695
+ * Maps generic codec names to hardware-specific decoder implementations.
696
+ * Returns null if no hardware decoder is available for the codec.
697
+ * Automatically searches for decoders that support this hardware device type.
698
+ *
699
+ * @param codec - Generic codec name (e.g., 'h264', 'hevc', 'av1') or AVCodecID
700
+ *
701
+ * @returns Hardware decoder codec or null if unsupported
702
+ *
703
+ * @example
704
+ * ```typescript
705
+ * const decoderCodec = hw.getDecoderCodec('hevc');
706
+ * if (decoderCodec) {
707
+ * console.log(`Using decoder: ${decoderCodec.name}`);
708
+ * // e.g., "hevc_qsv" for QSV
709
+ * }
710
+ * ```
711
+ *
712
+ * @example
713
+ * ```typescript
714
+ * // Use with Decoder.create
715
+ * const codec = hw.getDecoderCodec(AV_CODEC_ID_H264);
716
+ * if (codec) {
717
+ * const decoder = await Decoder.create(stream, { hardware: hw });
718
+ * }
719
+ * ```
720
+ *
721
+ * @see {@link Decoder.create} For using the codec
722
+ * @see {@link getEncoderCodec} For hardware encoders
723
+ */
724
+ getDecoderCodec(codec) {
725
+ // Get codec ID
726
+ let codecId = null;
727
+ if (typeof codec === 'number') {
728
+ codecId = codec;
729
+ }
730
+ else {
731
+ codecId = this.getCodecIDFromBaseName(codec);
732
+ }
733
+ if (codecId === null) {
734
+ return null;
735
+ }
736
+ // Find all decoders for this codec
737
+ const codecs = Codec.getCodecList();
738
+ for (const decoderCodec of codecs) {
739
+ // Skip if not a decoder
740
+ if (!decoderCodec.isDecoder()) {
741
+ continue;
742
+ }
743
+ // Skip if wrong codec ID
744
+ if (decoderCodec.id !== codecId) {
745
+ continue;
746
+ }
747
+ // Check if this decoder supports our hardware device type
748
+ for (let i = 0;; i++) {
749
+ const config = decoderCodec.getHwConfig(i);
750
+ if (!config)
751
+ break;
752
+ // Accept both HW_DEVICE_CTX and HW_FRAMES_CTX methods
753
+ const supportsDeviceCtx = (config.methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) !== 0;
754
+ const supportsFramesCtx = (config.methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX) !== 0;
755
+ if ((supportsDeviceCtx || supportsFramesCtx) && config.deviceType === this._deviceType) {
756
+ // Found a hardware decoder that supports this device type
757
+ return decoderCodec;
758
+ }
759
+ }
760
+ }
761
+ return null;
762
+ }
763
+ /**
764
+ * Test if hardware acceleration is working by decoding a test frame.
765
+ *
766
+ * Creates a simple decoder and attempts to decode with hardware acceleration.
767
+ * Returns true if hardware decoding succeeds, false otherwise.
768
+ * Useful for validating hardware setup before processing.
769
+ *
770
+ * @param codecId - Codec ID to test (default: H.264)
771
+ *
772
+ * @returns Promise that resolves to true if hardware works
773
+ *
774
+ * @example
775
+ * ```typescript
776
+ * const hw = HardwareContext.auto();
777
+ * if (hw && await hw.testDecoder()) {
778
+ * console.log('Hardware acceleration working!');
779
+ * // Proceed with hardware decoding/encoding
780
+ * } else {
781
+ * console.log('Hardware acceleration not available');
782
+ * // Fall back to software
783
+ * }
784
+ * ```
785
+ *
786
+ * @example
787
+ * ```typescript
788
+ * // Test specific hardware
789
+ * const cuda = HardwareContext.create(AV_HWDEVICE_TYPE_CUDA);
790
+ * if (cuda && await cuda.testDecoder()) {
791
+ * console.log('CUDA acceleration works');
792
+ * }
793
+ * ```
794
+ *
795
+ * @see {@link supportsCodec} For checking codec support
796
+ */
797
+ testDecoder(codecId = AV_CODEC_ID_H264) {
798
+ try {
799
+ if (!this.supportsCodec(codecId, false)) {
800
+ return false;
801
+ }
802
+ return this.testCodec(codecId);
803
+ }
804
+ catch {
805
+ return false;
806
+ }
807
+ }
808
+ /**
809
+ * Test if hardware encoding works with a specific codec pair.
810
+ *
811
+ * Attempts to decode and re-encode a test frame using hardware acceleration.
812
+ * Validates both decoding and encoding paths for the given codecs.
813
+ *
814
+ * @param decoderCodec - Codec name, ID, or instance to use for decoding
815
+ *
816
+ * @param encoderCodec - Codec name or instance to use for encoding
817
+ *
818
+ * @returns true if both decoding and encoding succeed
819
+ *
820
+ * @example
821
+ * ```typescript
822
+ * import { AV_CODEC_ID_H264 } from 'node-av/constants';
823
+ *
824
+ * const hw = HardwareContext.auto();
825
+ * if (hw && hw.testEncoder(AV_CODEC_ID_H264, AV_CODEC_ID_H264)) {
826
+ * console.log('Hardware H.264 encoding works!');
827
+ * }
828
+ * ```
829
+ *
830
+ * @see {@link getEncoderCodec} For obtaining hardware encoder codec
831
+ */
832
+ testEncoder(decoderCodec, encoderCodec) {
833
+ const isSupported = this.testCodec(decoderCodec, encoderCodec);
834
+ if (!isSupported) {
835
+ return false;
836
+ }
837
+ return true;
838
+ }
839
+ /**
840
+ * Find all codecs that support this hardware device.
841
+ *
842
+ * Iterates through all available codecs and checks hardware compatibility.
843
+ * Useful for discovering available hardware acceleration options.
844
+ *
845
+ * Direct mapping to av_codec_iterate() with hardware config checks.
846
+ *
847
+ * @param isEncoder - Find encoders (true) or decoders (false)
848
+ *
849
+ * @returns Array of codec names that support this hardware
850
+ *
851
+ * @example
852
+ * ```typescript
853
+ * const decoders = hw.findSupportedCodecs(false);
854
+ * console.log('Hardware decoders:', decoders);
855
+ * // ["h264_cuvid", "hevc_cuvid", ...]
856
+ *
857
+ * const encoders = hw.findSupportedCodecs(true);
858
+ * console.log('Hardware encoders:', encoders);
859
+ * // ["h264_nvenc", "hevc_nvenc", ...]
860
+ * ```
861
+ *
862
+ * @see {@link supportsCodec} For checking specific codec
863
+ */
864
+ findSupportedCodecs(isEncoder = false) {
865
+ const supportedCodecs = [];
866
+ const codecs = Codec.getCodecList();
867
+ for (const codec of codecs) {
868
+ // Skip if wrong type (encoder vs decoder)
869
+ if (isEncoder && !codec.isEncoder())
870
+ continue;
871
+ if (!isEncoder && !codec.isDecoder())
872
+ continue;
873
+ // Check if this codec supports our hardware device type
874
+ for (let i = 0;; i++) {
875
+ const config = codec.getHwConfig(i);
876
+ if (!config)
877
+ break;
878
+ // Accept both HW_DEVICE_CTX and HW_FRAMES_CTX methods
879
+ const supportsDeviceCtx = (config.methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) !== 0;
880
+ const supportsFramesCtx = (config.methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX) !== 0;
881
+ if ((supportsDeviceCtx || supportsFramesCtx) && config.deviceType === this._deviceType) {
882
+ if (codec.name) {
883
+ supportedCodecs.push(codec.name);
884
+ }
885
+ break; // Found support, move to next codec
886
+ }
887
+ }
888
+ }
889
+ return supportedCodecs;
890
+ }
891
+ /**
892
+ * Clean up and free hardware resources.
893
+ *
894
+ * Releases the hardware device context.
895
+ * Safe to call multiple times.
896
+ * Automatically called by Symbol.dispose.
897
+ *
898
+ * @example
899
+ * ```typescript
900
+ * const hw = HardwareContext.auto();
901
+ * try {
902
+ * // Use hardware
903
+ * } finally {
904
+ * hw?.dispose();
905
+ * }
906
+ * ```
907
+ *
908
+ * @see {@link Symbol.dispose} For automatic cleanup
909
+ */
910
+ dispose() {
911
+ if (this._isDisposed) {
912
+ return;
913
+ }
914
+ this._deviceContext.free();
915
+ this._isDisposed = true;
916
+ }
917
+ /**
918
+ * Test hardware decoding with a specific codec.
919
+ *
920
+ * @param decoderCodec - Decoder codec name, ID, or instance to test
921
+ *
922
+ * @param encoderCodec - Optional encoder codec name or instance to test
923
+ *
924
+ * @param useFilter - Whether to test hwdownload filter (default: true)
925
+ *
926
+ * @returns true if decoding succeeds
927
+ *
928
+ * @internal
929
+ */
930
+ testCodec(decoderCodec, encoderCodec, useFilter = true) {
931
+ try {
932
+ const env_1 = { stack: [], error: void 0, hasError: false };
933
+ try {
934
+ let codecDecoder = null;
935
+ let codecEncoder = null;
936
+ if (decoderCodec instanceof Codec) {
937
+ codecDecoder = decoderCodec;
938
+ }
939
+ else if (typeof decoderCodec === 'string') {
940
+ codecDecoder = Codec.findDecoderByName(decoderCodec);
941
+ }
942
+ else {
943
+ codecDecoder = Codec.findDecoder(decoderCodec);
944
+ }
945
+ if (!codecDecoder) {
946
+ throw new Error('Decoder codec not found');
947
+ }
948
+ // Select appropriate test file based on codec
949
+ let testFilePath;
950
+ switch (codecDecoder.id) {
951
+ case AV_CODEC_ID_HEVC:
952
+ testFilePath = hevcData;
953
+ break;
954
+ case AV_CODEC_ID_VP8:
955
+ testFilePath = vp8Data;
956
+ break;
957
+ case AV_CODEC_ID_VP9:
958
+ testFilePath = vp9Data;
959
+ break;
960
+ case AV_CODEC_ID_AV1:
961
+ testFilePath = av1Data;
962
+ break;
963
+ case AV_CODEC_ID_MJPEG:
964
+ testFilePath = mjpegData;
965
+ break;
966
+ case AV_CODEC_ID_H264:
967
+ default:
968
+ testFilePath = h264Data;
969
+ break;
970
+ }
971
+ // Read test bitstream
972
+ const input = __addDisposableResource(env_1, Demuxer.openSync(testFilePath), false);
973
+ const videoStream = input.video();
974
+ const decoder = __addDisposableResource(env_1, Decoder.createSync(videoStream, {
975
+ hardware: this,
976
+ }), false);
977
+ const packetGenerator = input.packetsSync();
978
+ const hwFrameGenerator = decoder.framesSync(packetGenerator);
979
+ // Resolve encoder codec if provided
980
+ if (encoderCodec) {
981
+ if (encoderCodec instanceof Codec) {
982
+ codecEncoder = encoderCodec;
983
+ }
984
+ else if (typeof encoderCodec === 'string') {
985
+ codecEncoder = Codec.findEncoderByName(encoderCodec);
986
+ }
987
+ else {
988
+ codecEncoder = Codec.findEncoder(encoderCodec);
989
+ }
990
+ if (!codecEncoder) {
991
+ return false;
992
+ }
993
+ }
994
+ // VAAPI, Vulkan and D3D12 encoders list no software format and refuse downloaded frames
995
+ const encoderFormats = codecEncoder?.pixelFormats ?? [];
996
+ const takesDeviceFramesOnly = encoderFormats.length > 0 && encoderFormats.every((format) => avIsHardwarePixelFormat(format));
997
+ // Optionally create hwdownload filter to test hardware → software transfer
998
+ const filter = __addDisposableResource(env_1, useFilter && !takesDeviceFramesOnly
999
+ ? FilterAPI.create('hwdownload,format=nv12', {
1000
+ framerate: videoStream.avgFrameRate,
1001
+ hardware: this,
1002
+ })
1003
+ : null, false);
1004
+ const frameGenerator = filter ? filter.framesSync(hwFrameGenerator) : hwFrameGenerator;
1005
+ const encoder = __addDisposableResource(env_1, codecEncoder
1006
+ ? Encoder.createSync(codecEncoder, {
1007
+ decoder,
1008
+ filter: filter ?? undefined,
1009
+ })
1010
+ : null, false);
1011
+ const outputGenerator = encoder ? encoder.packetsSync(frameGenerator) : frameGenerator;
1012
+ let hasData = false;
1013
+ for (const _1 of outputGenerator) {
1014
+ const env_2 = { stack: [], error: void 0, hasError: false };
1015
+ try {
1016
+ const _ = __addDisposableResource(env_2, _1, false);
1017
+ if (!_)
1018
+ continue;
1019
+ hasData = true;
1020
+ break;
1021
+ }
1022
+ catch (e_1) {
1023
+ env_2.error = e_1;
1024
+ env_2.hasError = true;
1025
+ }
1026
+ finally {
1027
+ __disposeResources(env_2);
1028
+ }
1029
+ }
1030
+ return hasData;
1031
+ }
1032
+ catch (e_2) {
1033
+ env_1.error = e_2;
1034
+ env_1.hasError = true;
1035
+ }
1036
+ finally {
1037
+ __disposeResources(env_1);
1038
+ }
1039
+ }
1040
+ catch {
1041
+ return false;
1042
+ }
1043
+ }
1044
+ /**
1045
+ * Map AVCodecID to base codec name for hardware encoder lookup.
1046
+ *
1047
+ * Converts codec IDs to generic codec names used for encoder naming.
1048
+ * Used internally to find hardware-specific encoder implementations.
1049
+ *
1050
+ * @param codecId - AVCodecID enum value
1051
+ *
1052
+ * @returns Base codec name or null if unsupported
1053
+ *
1054
+ * @internal
1055
+ */
1056
+ getBaseCodecName(codecId) {
1057
+ switch (codecId) {
1058
+ case AV_CODEC_ID_AV1:
1059
+ return 'av1';
1060
+ case AV_CODEC_ID_H264:
1061
+ return 'h264';
1062
+ case AV_CODEC_ID_HEVC:
1063
+ return 'hevc';
1064
+ case AV_CODEC_ID_H263:
1065
+ return 'h263';
1066
+ case AV_CODEC_ID_MPEG2VIDEO:
1067
+ return 'mpeg2';
1068
+ case AV_CODEC_ID_MPEG4:
1069
+ return 'mpeg4';
1070
+ case AV_CODEC_ID_VP8:
1071
+ return 'vp8';
1072
+ case AV_CODEC_ID_VP9:
1073
+ return 'vp9';
1074
+ case AV_CODEC_ID_MJPEG:
1075
+ return 'mjpeg';
1076
+ case AV_CODEC_ID_PRORES:
1077
+ return 'prores';
1078
+ default:
1079
+ return null;
1080
+ }
1081
+ }
1082
+ /**
1083
+ * Map base codec name to AVCodecID for internal use.
1084
+ *
1085
+ * Converts generic codec names to AVCodecID enum values.
1086
+ * Used internally for codec testing and validation.
1087
+ *
1088
+ * @param codecBaseName - Base codec name string
1089
+ *
1090
+ * @returns Corresponding AVCodecID or null if unsupported
1091
+ *
1092
+ * @internal
1093
+ */
1094
+ getCodecIDFromBaseName(codecBaseName) {
1095
+ switch (codecBaseName) {
1096
+ case 'av1':
1097
+ return AV_CODEC_ID_AV1;
1098
+ case 'h264':
1099
+ return AV_CODEC_ID_H264;
1100
+ case 'hevc':
1101
+ return AV_CODEC_ID_HEVC;
1102
+ case 'h263':
1103
+ return AV_CODEC_ID_H263;
1104
+ case 'mpeg2':
1105
+ return AV_CODEC_ID_MPEG2VIDEO;
1106
+ case 'mpeg4':
1107
+ return AV_CODEC_ID_MPEG4;
1108
+ case 'vp8':
1109
+ return AV_CODEC_ID_VP8;
1110
+ case 'vp9':
1111
+ return AV_CODEC_ID_VP9;
1112
+ case 'mjpeg':
1113
+ return AV_CODEC_ID_MJPEG;
1114
+ case 'prores':
1115
+ return AV_CODEC_ID_PRORES;
1116
+ default:
1117
+ return null;
1118
+ }
1119
+ }
1120
+ /**
1121
+ * Get the hardware decoder pixel format for this device type.
1122
+ *
1123
+ * Maps device types to their corresponding pixel formats.
1124
+ * Used internally for frame format configuration.
1125
+ *
1126
+ * @returns Hardware-specific pixel format
1127
+ *
1128
+ * @internal
1129
+ */
1130
+ getHardwareDecoderPixelFormat() {
1131
+ switch (this._deviceType) {
1132
+ case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
1133
+ return AV_PIX_FMT_VIDEOTOOLBOX;
1134
+ case AV_HWDEVICE_TYPE_VAAPI:
1135
+ return AV_PIX_FMT_VAAPI;
1136
+ case AV_HWDEVICE_TYPE_CUDA:
1137
+ return AV_PIX_FMT_CUDA;
1138
+ case AV_HWDEVICE_TYPE_QSV:
1139
+ return AV_PIX_FMT_QSV;
1140
+ case AV_HWDEVICE_TYPE_D3D11VA:
1141
+ return AV_PIX_FMT_D3D11;
1142
+ case AV_HWDEVICE_TYPE_DXVA2:
1143
+ return AV_PIX_FMT_DXVA2_VLD;
1144
+ case AV_HWDEVICE_TYPE_DRM:
1145
+ return AV_PIX_FMT_DRM_PRIME;
1146
+ case AV_HWDEVICE_TYPE_OPENCL:
1147
+ return AV_PIX_FMT_OPENCL;
1148
+ case AV_HWDEVICE_TYPE_MEDIACODEC:
1149
+ return AV_PIX_FMT_MEDIACODEC;
1150
+ case AV_HWDEVICE_TYPE_VULKAN:
1151
+ return AV_PIX_FMT_VULKAN;
1152
+ case AV_HWDEVICE_TYPE_D3D12VA:
1153
+ return AV_PIX_FMT_D3D12;
1154
+ case AV_HWDEVICE_TYPE_RKMPP:
1155
+ return AV_PIX_FMT_DRM_PRIME; // RKMPP uses DRM Prime buffers
1156
+ default:
1157
+ return AV_PIX_FMT_NV12; // Common hardware format
1158
+ }
1159
+ }
1160
+ /**
1161
+ * Create hardware context from device type.
1162
+ *
1163
+ * Internal factory method using av_hwdevice_ctx_create().
1164
+ *
1165
+ * @param deviceType - AVHWDeviceType enum value
1166
+ *
1167
+ * @param device - Optional device specifier
1168
+ *
1169
+ * @param options - Optional device options
1170
+ *
1171
+ * @returns Hardware context or null if creation fails
1172
+ *
1173
+ * @internal
1174
+ */
1175
+ static createFromType(deviceType, device, options) {
1176
+ // Set environment variables for Vulkan to enable video support on older gpus
1177
+ if (deviceType === AV_HWDEVICE_TYPE_VULKAN) {
1178
+ process.env.ANV_DEBUG ??= 'video-decode,video-encode';
1179
+ process.env.RADV_PERFTEST ??= 'video_decode,video_encode';
1180
+ }
1181
+ const deviceCtx = new HardwareDeviceContext();
1182
+ // Convert options to Dictionary if provided
1183
+ let optionsDict = null;
1184
+ if (options && Object.keys(options).length > 0) {
1185
+ optionsDict = Dictionary.fromObject(options);
1186
+ }
1187
+ const ret = deviceCtx.create(deviceType, device, optionsDict);
1188
+ // Clean up dictionary if used
1189
+ if (optionsDict) {
1190
+ optionsDict.free();
1191
+ }
1192
+ const deviceTypeName = HardwareDeviceContext.getTypeName(deviceType);
1193
+ if (ret < 0 || !deviceTypeName) {
1194
+ deviceCtx.free();
1195
+ FFmpegError.throwIfError(ret);
1196
+ throw new Error('Unknown error creating hardware device context');
1197
+ }
1198
+ return new HardwareContext(deviceCtx, deviceType, deviceTypeName);
1199
+ }
1200
+ static isRockchip() {
1201
+ if (this._rockchip === undefined) {
1202
+ try {
1203
+ this._rockchip = readFileSync('/proc/device-tree/compatible', 'utf8').includes('rockchip');
1204
+ }
1205
+ catch {
1206
+ this._rockchip = false;
1207
+ }
1208
+ }
1209
+ return this._rockchip;
1210
+ }
1211
+ /**
1212
+ * Get platform-specific preference order for hardware types.
1213
+ *
1214
+ * Returns available hardware types sorted by platform preference. Any
1215
+ * caller-supplied preferred types are placed first (in the given order),
1216
+ * followed by the platform default order and finally any remaining available
1217
+ * types. Unavailable types are dropped.
1218
+ *
1219
+ * @param prefer - Hardware types to try first, in priority order
1220
+ *
1221
+ * @returns Array of AVHWDeviceType values in preference order
1222
+ *
1223
+ * @internal
1224
+ */
1225
+ static getPreferenceOrder(prefer) {
1226
+ // Get all available hardware types on this system
1227
+ const available = HardwareDeviceContext.iterateTypes();
1228
+ if (available.length === 0) {
1229
+ return [];
1230
+ }
1231
+ const platform = process.platform;
1232
+ let preferenceOrder;
1233
+ if (platform === 'darwin') {
1234
+ preferenceOrder = [AV_HWDEVICE_TYPE_VIDEOTOOLBOX];
1235
+ }
1236
+ else if (platform === 'win32') {
1237
+ preferenceOrder = [
1238
+ AV_HWDEVICE_TYPE_CUDA,
1239
+ AV_HWDEVICE_TYPE_QSV,
1240
+ AV_HWDEVICE_TYPE_D3D11VA,
1241
+ AV_HWDEVICE_TYPE_D3D12VA,
1242
+ AV_HWDEVICE_TYPE_DXVA2,
1243
+ AV_HWDEVICE_TYPE_VULKAN,
1244
+ AV_HWDEVICE_TYPE_OPENCL,
1245
+ ];
1246
+ }
1247
+ else {
1248
+ // Linux/Unix platforms
1249
+ const isARM = process.arch === 'arm64' || process.arch === 'arm';
1250
+ if (isARM) {
1251
+ preferenceOrder = [AV_HWDEVICE_TYPE_RKMPP, AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_CUDA, AV_HWDEVICE_TYPE_DRM, AV_HWDEVICE_TYPE_VULKAN, AV_HWDEVICE_TYPE_OPENCL];
1252
+ }
1253
+ else {
1254
+ preferenceOrder = [AV_HWDEVICE_TYPE_CUDA, AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_QSV, AV_HWDEVICE_TYPE_DRM, AV_HWDEVICE_TYPE_VULKAN, AV_HWDEVICE_TYPE_OPENCL];
1255
+ }
1256
+ }
1257
+ // Probing rkmpp on a board that is not Rockchip makes librockchip_mpp print
1258
+ // its device-tree failure straight to stderr, past any log callback. Skip it
1259
+ // unless the caller asked for it by name.
1260
+ const skip = new Set();
1261
+ if (!this.isRockchip())
1262
+ skip.add(AV_HWDEVICE_TYPE_RKMPP);
1263
+ prefer?.forEach((type) => skip.delete(type));
1264
+ // Build the final order: user preference first, then the platform default,
1265
+ // then any remaining available types. Keep only available types, no dupes.
1266
+ const availableSet = new Set(available);
1267
+ const seen = new Set();
1268
+ const sortedAvailable = [];
1269
+ const push = (type) => {
1270
+ if (availableSet.has(type) && !seen.has(type) && !skip.has(type)) {
1271
+ seen.add(type);
1272
+ sortedAvailable.push(type);
1273
+ }
1274
+ };
1275
+ prefer?.forEach(push);
1276
+ preferenceOrder.forEach(push);
1277
+ available.forEach(push);
1278
+ return sortedAvailable;
1279
+ }
1280
+ /**
1281
+ * Dispose of hardware context.
1282
+ *
1283
+ * Implements Disposable interface for automatic cleanup.
1284
+ * Equivalent to calling dispose().
1285
+ *
1286
+ * @example
1287
+ * ```typescript
1288
+ * {
1289
+ * using hw = HardwareContext.auto();
1290
+ * // Use hardware context...
1291
+ * } // Automatically disposed
1292
+ * ```
1293
+ *
1294
+ * @see {@link dispose} For manual cleanup
1295
+ */
1296
+ [Symbol.dispose]() {
1297
+ this.dispose();
1298
+ }
1299
+ }
1300
+ //# sourceMappingURL=hardware.js.map