node-av 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/README.md +51 -59
  2. package/dist/api/bitstream-filter.d.ts +183 -123
  3. package/dist/api/bitstream-filter.js +185 -127
  4. package/dist/api/bitstream-filter.js.map +1 -1
  5. package/dist/api/decoder.d.ts +282 -130
  6. package/dist/api/decoder.js +290 -142
  7. package/dist/api/decoder.js.map +1 -1
  8. package/dist/api/encoder.d.ts +249 -160
  9. package/dist/api/encoder.js +276 -207
  10. package/dist/api/encoder.js.map +1 -1
  11. package/dist/api/filter-presets.d.ts +1944 -96
  12. package/dist/api/filter-presets.js +2059 -105
  13. package/dist/api/filter-presets.js.map +1 -1
  14. package/dist/api/filter.d.ts +264 -200
  15. package/dist/api/filter.js +269 -231
  16. package/dist/api/filter.js.map +1 -1
  17. package/dist/api/hardware.d.ts +246 -117
  18. package/dist/api/hardware.js +440 -217
  19. package/dist/api/hardware.js.map +1 -1
  20. package/dist/api/index.d.ts +3 -3
  21. package/dist/api/index.js +1 -1
  22. package/dist/api/index.js.map +1 -1
  23. package/dist/api/io-stream.d.ts +65 -55
  24. package/dist/api/io-stream.js +43 -40
  25. package/dist/api/io-stream.js.map +1 -1
  26. package/dist/api/media-input.d.ts +242 -139
  27. package/dist/api/media-input.js +205 -103
  28. package/dist/api/media-input.js.map +1 -1
  29. package/dist/api/media-output.d.ts +208 -126
  30. package/dist/api/media-output.js +212 -126
  31. package/dist/api/media-output.js.map +1 -1
  32. package/dist/api/pipeline.d.ts +361 -38
  33. package/dist/api/pipeline.js +255 -14
  34. package/dist/api/pipeline.js.map +1 -1
  35. package/dist/api/types.d.ts +26 -187
  36. package/dist/api/utilities/audio-sample.d.ts +0 -8
  37. package/dist/api/utilities/audio-sample.js +0 -8
  38. package/dist/api/utilities/audio-sample.js.map +1 -1
  39. package/dist/api/utilities/channel-layout.d.ts +0 -8
  40. package/dist/api/utilities/channel-layout.js +0 -8
  41. package/dist/api/utilities/channel-layout.js.map +1 -1
  42. package/dist/api/utilities/image.d.ts +0 -8
  43. package/dist/api/utilities/image.js +0 -8
  44. package/dist/api/utilities/image.js.map +1 -1
  45. package/dist/api/utilities/index.d.ts +3 -3
  46. package/dist/api/utilities/index.js +3 -3
  47. package/dist/api/utilities/index.js.map +1 -1
  48. package/dist/api/utilities/media-type.d.ts +1 -9
  49. package/dist/api/utilities/media-type.js +1 -9
  50. package/dist/api/utilities/media-type.js.map +1 -1
  51. package/dist/api/utilities/pixel-format.d.ts +1 -9
  52. package/dist/api/utilities/pixel-format.js +1 -9
  53. package/dist/api/utilities/pixel-format.js.map +1 -1
  54. package/dist/api/utilities/sample-format.d.ts +1 -9
  55. package/dist/api/utilities/sample-format.js +1 -9
  56. package/dist/api/utilities/sample-format.js.map +1 -1
  57. package/dist/api/utilities/streaming.d.ts +0 -8
  58. package/dist/api/utilities/streaming.js +0 -8
  59. package/dist/api/utilities/streaming.js.map +1 -1
  60. package/dist/api/utilities/timestamp.d.ts +0 -8
  61. package/dist/api/utilities/timestamp.js +0 -8
  62. package/dist/api/utilities/timestamp.js.map +1 -1
  63. package/dist/api/utils.d.ts +1 -2
  64. package/dist/api/utils.js +11 -0
  65. package/dist/api/utils.js.map +1 -1
  66. package/dist/constants/constants.d.ts +1 -1
  67. package/dist/constants/constants.js +2 -0
  68. package/dist/constants/constants.js.map +1 -1
  69. package/dist/lib/audio-fifo.d.ts +127 -170
  70. package/dist/lib/audio-fifo.js +130 -173
  71. package/dist/lib/audio-fifo.js.map +1 -1
  72. package/dist/lib/binding.d.ts +1 -0
  73. package/dist/lib/binding.js +7 -0
  74. package/dist/lib/binding.js.map +1 -1
  75. package/dist/lib/bitstream-filter-context.d.ts +139 -184
  76. package/dist/lib/bitstream-filter-context.js +139 -188
  77. package/dist/lib/bitstream-filter-context.js.map +1 -1
  78. package/dist/lib/bitstream-filter.d.ts +68 -54
  79. package/dist/lib/bitstream-filter.js +68 -54
  80. package/dist/lib/bitstream-filter.js.map +1 -1
  81. package/dist/lib/codec-context.d.ts +316 -380
  82. package/dist/lib/codec-context.js +316 -381
  83. package/dist/lib/codec-context.js.map +1 -1
  84. package/dist/lib/codec-parameters.d.ts +160 -170
  85. package/dist/lib/codec-parameters.js +162 -172
  86. package/dist/lib/codec-parameters.js.map +1 -1
  87. package/dist/lib/codec-parser.d.ts +91 -104
  88. package/dist/lib/codec-parser.js +92 -103
  89. package/dist/lib/codec-parser.js.map +1 -1
  90. package/dist/lib/codec.d.ts +266 -283
  91. package/dist/lib/codec.js +270 -287
  92. package/dist/lib/codec.js.map +1 -1
  93. package/dist/lib/dictionary.d.ts +149 -203
  94. package/dist/lib/dictionary.js +158 -212
  95. package/dist/lib/dictionary.js.map +1 -1
  96. package/dist/lib/error.d.ts +96 -130
  97. package/dist/lib/error.js +98 -128
  98. package/dist/lib/error.js.map +1 -1
  99. package/dist/lib/filter-context.d.ts +284 -218
  100. package/dist/lib/filter-context.js +290 -227
  101. package/dist/lib/filter-context.js.map +1 -1
  102. package/dist/lib/filter-graph.d.ts +251 -292
  103. package/dist/lib/filter-graph.js +253 -294
  104. package/dist/lib/filter-graph.js.map +1 -1
  105. package/dist/lib/filter-inout.d.ts +87 -95
  106. package/dist/lib/filter-inout.js +87 -95
  107. package/dist/lib/filter-inout.js.map +1 -1
  108. package/dist/lib/filter.d.ts +93 -111
  109. package/dist/lib/filter.js +93 -111
  110. package/dist/lib/filter.js.map +1 -1
  111. package/dist/lib/format-context.d.ts +320 -428
  112. package/dist/lib/format-context.js +313 -385
  113. package/dist/lib/format-context.js.map +1 -1
  114. package/dist/lib/frame.d.ts +262 -405
  115. package/dist/lib/frame.js +263 -408
  116. package/dist/lib/frame.js.map +1 -1
  117. package/dist/lib/hardware-device-context.d.ts +149 -203
  118. package/dist/lib/hardware-device-context.js +149 -203
  119. package/dist/lib/hardware-device-context.js.map +1 -1
  120. package/dist/lib/hardware-frames-context.d.ts +170 -180
  121. package/dist/lib/hardware-frames-context.js +171 -181
  122. package/dist/lib/hardware-frames-context.js.map +1 -1
  123. package/dist/lib/index.d.ts +3 -2
  124. package/dist/lib/index.js +3 -3
  125. package/dist/lib/index.js.map +1 -1
  126. package/dist/lib/input-format.d.ts +89 -117
  127. package/dist/lib/input-format.js +89 -117
  128. package/dist/lib/input-format.js.map +1 -1
  129. package/dist/lib/io-context.d.ts +209 -241
  130. package/dist/lib/io-context.js +220 -252
  131. package/dist/lib/io-context.js.map +1 -1
  132. package/dist/lib/log.d.ts +85 -119
  133. package/dist/lib/log.js +85 -122
  134. package/dist/lib/log.js.map +1 -1
  135. package/dist/lib/native-types.d.ts +118 -106
  136. package/dist/lib/native-types.js +0 -7
  137. package/dist/lib/native-types.js.map +1 -1
  138. package/dist/lib/option.d.ts +437 -218
  139. package/dist/lib/option.js +462 -226
  140. package/dist/lib/option.js.map +1 -1
  141. package/dist/lib/output-format.d.ts +77 -101
  142. package/dist/lib/output-format.js +77 -101
  143. package/dist/lib/output-format.js.map +1 -1
  144. package/dist/lib/packet.d.ts +172 -240
  145. package/dist/lib/packet.js +172 -241
  146. package/dist/lib/packet.js.map +1 -1
  147. package/dist/lib/rational.d.ts +0 -2
  148. package/dist/lib/rational.js +0 -2
  149. package/dist/lib/rational.js.map +1 -1
  150. package/dist/lib/software-resample-context.d.ts +241 -325
  151. package/dist/lib/software-resample-context.js +242 -326
  152. package/dist/lib/software-resample-context.js.map +1 -1
  153. package/dist/lib/software-scale-context.d.ts +129 -173
  154. package/dist/lib/software-scale-context.js +131 -175
  155. package/dist/lib/software-scale-context.js.map +1 -1
  156. package/dist/lib/stream.d.ts +87 -197
  157. package/dist/lib/stream.js +87 -197
  158. package/dist/lib/stream.js.map +1 -1
  159. package/dist/lib/utilities.d.ts +435 -181
  160. package/dist/lib/utilities.js +438 -182
  161. package/dist/lib/utilities.js.map +1 -1
  162. package/install/check.js +0 -1
  163. package/install/ffmpeg.js +0 -11
  164. package/package.json +25 -18
  165. package/release_notes.md +24 -59
  166. package/CHANGELOG.md +0 -8
@@ -1,107 +1,108 @@
1
- /**
2
- * HardwareContext - High-level Hardware Acceleration API
3
- *
4
- * Provides simplified access to hardware acceleration features.
5
- * Automatically detects and configures hardware devices for encoding/decoding.
6
- *
7
- * Wraps the low-level HardwareDeviceContext.
8
- * Manages lifecycle of hardware resources with automatic cleanup.
9
- *
10
- * @module api/hardware
11
- */
12
- import { AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX, AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, 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';
13
- import { Codec, Dictionary, HardwareDeviceContext } from '../lib/index.js';
1
+ 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';
2
+ import { Codec, CodecContext, Dictionary, HardwareDeviceContext, Rational } from '../lib/index.js';
14
3
  import { HardwareFilterPresets } from './filter-presets.js';
15
4
  /**
16
- * HardwareContext - Simplified hardware acceleration management.
17
- *
18
- * Provides automatic detection and configuration of hardware acceleration.
19
- * Manages device contexts and frame contexts for hardware encoding/decoding.
5
+ * High-level hardware acceleration management.
20
6
  *
21
- * Supports various hardware types including VideoToolbox (macOS), CUDA,
22
- * VAAPI (Linux), D3D11VA/D3D12VA (Windows), and more.
7
+ * Provides automatic detection and configuration of hardware acceleration for media processing.
8
+ * Manages device contexts for GPU-accelerated encoding and decoding operations.
9
+ * Supports various hardware types including VideoToolbox, CUDA, VAAPI, D3D11VA, and more.
10
+ * Essential for high-performance video processing with reduced CPU usage.
23
11
  *
24
12
  * @example
25
13
  * ```typescript
26
14
  * import { HardwareContext } from 'node-av/api';
15
+ * import { AV_HWDEVICE_TYPE_CUDA } from 'node-av/constants';
27
16
  *
28
17
  * // Auto-detect best available hardware
29
- * const hw = await HardwareContext.auto();
18
+ * const hw = HardwareContext.auto();
30
19
  * if (hw) {
31
- * console.log(`Using hardware: ${hw.deviceType}`);
32
- * decoder.hwDeviceCtx = hw.deviceContext;
20
+ * console.log(`Using hardware: ${hw.deviceTypeName}`);
21
+ * const decoder = await Decoder.create(stream, { hardware: hw });
33
22
  * }
23
+ * ```
34
24
  *
35
- * // Use specific hardware
36
- * const cuda = await HardwareContext.create(AV_HWDEVICE_TYPE_CUDA);
37
- * encoder.hwDeviceCtx = cuda.deviceContext;
38
- *
39
- * // Clean up when done
40
- * hw?.dispose();
25
+ * @example
26
+ * ```typescript
27
+ * // Use specific hardware type
28
+ * const cuda = HardwareContext.create(AV_HWDEVICE_TYPE_CUDA);
29
+ * const encoder = await Encoder.create('h264_nvenc', streamInfo, {
30
+ * hardware: cuda
31
+ * });
41
32
  * cuda.dispose();
42
33
  * ```
34
+ *
35
+ * @see {@link Decoder} For hardware-accelerated decoding
36
+ * @see {@link Encoder} For hardware-accelerated encoding
37
+ * @see {@link HardwareFilterPresets} For hardware filter operations
43
38
  */
44
39
  export class HardwareContext {
45
- _deviceContext;
46
- _deviceType;
47
- _deviceTypeName;
48
- _devicePixelFormat;
49
- _isDisposed = false;
50
40
  /**
51
41
  * Hardware-specific filter presets for this device.
52
42
  * Provides convenient filter builders for hardware-accelerated operations.
53
43
  */
54
44
  filterPresets;
45
+ _deviceContext;
46
+ _deviceType;
47
+ _deviceTypeName;
48
+ _devicePixelFormat;
49
+ _isDisposed = false;
55
50
  /**
56
- * Create a new HardwareContext instance.
57
- *
58
- * Private constructor - use HardwareContext.create() or HardwareContext.auto() to create instances.
59
- *
60
- * Stores the device context and type for later use.
61
- *
62
51
  * @param deviceContext - Initialized hardware device context
63
- * @param deviceType - Hardware device type
64
- * @param deviceName - Optional device name/identifier
52
+ * @param deviceType - Hardware device type enum
53
+ * @param deviceTypeName - Human-readable device type name
54
+ * @internal
65
55
  */
66
- constructor(deviceContext, deviceType, deviceName) {
56
+ constructor(deviceContext, deviceType, deviceTypeName) {
67
57
  this._deviceContext = deviceContext;
68
58
  this._deviceType = deviceType;
69
- this._deviceTypeName = deviceName ?? HardwareDeviceContext.getTypeName(this._deviceType);
70
- this._devicePixelFormat = this.getHardwarePixelFormat();
71
- this.filterPresets = new HardwareFilterPresets(deviceType, deviceName);
59
+ this._deviceTypeName = deviceTypeName;
60
+ this._devicePixelFormat = this.getHardwareDecoderPixelFormat();
61
+ this.filterPresets = new HardwareFilterPresets(deviceType, deviceTypeName);
72
62
  }
73
63
  /**
74
64
  * Auto-detect and create the best available hardware context.
75
65
  *
76
66
  * Tries hardware types in order of preference based on platform.
77
67
  * Returns null if no hardware acceleration is available.
78
- *
79
- * Platform-specific preferences:
80
- * - macOS: VideoToolbox
81
- * - Windows: D3D12VA, D3D11VA, DXVA2, QSV, CUDA
82
- * - Linux: VAAPI, VDPAU, CUDA, Vulkan, DRM
68
+ * Platform-specific preference order ensures optimal performance.
83
69
  *
84
70
  * @param options - Optional hardware configuration
85
- *
86
- * @returns Promise resolving to HardwareContext or null
71
+ * @returns Hardware context or null if unavailable
87
72
  *
88
73
  * @example
89
74
  * ```typescript
90
- * const hw = await HardwareContext.auto();
75
+ * const hw = HardwareContext.auto();
91
76
  * if (hw) {
92
77
  * console.log(`Auto-detected: ${hw.deviceTypeName}`);
78
+ * // Use for decoder/encoder
93
79
  * }
94
80
  * ```
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * // With specific device
85
+ * const hw = HardwareContext.auto({
86
+ * deviceName: '/dev/dri/renderD128'
87
+ * });
88
+ * ```
89
+ *
90
+ * @see {@link create} For specific hardware type
91
+ * @see {@link listAvailable} To check available types
95
92
  */
96
- static async auto(options = {}) {
93
+ static auto(options = {}) {
97
94
  // Platform-specific preference order
98
95
  const preferenceOrder = this.getPreferenceOrder();
99
96
  for (const deviceType of preferenceOrder) {
100
97
  try {
101
- const hw = await this.createFromType(deviceType, options.deviceName, options.options);
98
+ const hw = this.createFromType(deviceType, options.device, options.options);
102
99
  if (hw) {
103
100
  return hw;
104
101
  }
102
+ else {
103
+ // Try next device type
104
+ continue;
105
+ }
105
106
  }
106
107
  catch {
107
108
  // Try next device type
@@ -113,41 +114,57 @@ export class HardwareContext {
113
114
  /**
114
115
  * Create a hardware context for a specific device type.
115
116
  *
116
- * Creates and initializes a hardware device context using FFmpeg's
117
- * av_hwdevice_ctx_create() internally.
117
+ * Creates and initializes a hardware device context.
118
+ * Throws if the device type is not supported or initialization fails.
118
119
  *
119
- * @param device - Device type name (e.g., AV_HWDEVICE_TYPE_CUDA, AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_VIDEOTOOLBOX)
120
- * @param deviceName - Optional device name/index
120
+ * Direct mapping to av_hwdevice_ctx_create().
121
+ *
122
+ * @param deviceType - Hardware device type from AVHWDeviceType
123
+ * @param device - Optional device specifier (e.g., GPU index, device path)
121
124
  * @param options - Optional device initialization options
125
+ * @returns Initialized hardware context
126
+ *
127
+ * @throws {Error} If device type unsupported or initialization fails
122
128
  *
123
- * @returns Promise resolving to HardwareContext
129
+ * @example
130
+ * ```typescript
131
+ * import { AV_HWDEVICE_TYPE_CUDA } from 'node-av/constants';
124
132
  *
125
- * @throws {Error} If device type is not supported or initialization fails
133
+ * // CUDA with specific GPU
134
+ * const cuda = HardwareContext.create(AV_HWDEVICE_TYPE_CUDA, '0');
135
+ * ```
126
136
  *
127
137
  * @example
128
138
  * ```typescript
129
- * // Create CUDA context
130
- * const cuda = await HardwareContext.create(AV_HWDEVICE_TYPE_CUDA, '0');
139
+ * import { AV_HWDEVICE_TYPE_VAAPI } from 'node-av/constants';
131
140
  *
132
- * // Create VAAPI context
133
- * const vaapi = await HardwareContext.create(AV_HWDEVICE_TYPE_VAAPI, '/dev/dri/renderD128');
141
+ * // VAAPI with render device
142
+ * const vaapi = HardwareContext.create(
143
+ * AV_HWDEVICE_TYPE_VAAPI,
144
+ * '/dev/dri/renderD128'
145
+ * );
134
146
  * ```
147
+ *
148
+ * @see {@link auto} For automatic detection
149
+ * @see {@link HardwareDeviceContext} For low-level API
135
150
  */
136
- static async create(device, deviceName, options) {
137
- if (device === AV_HWDEVICE_TYPE_NONE) {
138
- throw new Error(`Unknown hardware device type: ${device}`);
151
+ static create(deviceType, device, options) {
152
+ if (deviceType === AV_HWDEVICE_TYPE_NONE) {
153
+ throw new Error('Cannot create hardware context for unknown hardware device type');
139
154
  }
140
- const hw = await this.createFromType(device, deviceName, options);
155
+ const hw = this.createFromType(deviceType, device, options);
141
156
  if (!hw) {
142
- throw new Error(`Failed to create hardware context for ${device}`);
157
+ throw new Error(`Failed to create hardware context for ${HardwareDeviceContext.getTypeName(deviceType) ?? 'unknown'} hardware`);
143
158
  }
144
159
  return hw;
145
160
  }
146
161
  /**
147
162
  * List all available hardware device types.
148
163
  *
149
- * Uses av_hwdevice_iterate_types() internally to enumerate
150
- * all hardware types supported by the FFmpeg build.
164
+ * Enumerates all hardware types supported by the FFmpeg build.
165
+ * Useful for checking hardware capabilities at runtime.
166
+ *
167
+ * Direct mapping to av_hwdevice_iterate_types().
151
168
  *
152
169
  * @returns Array of available device type names
153
170
  *
@@ -155,7 +172,10 @@ export class HardwareContext {
155
172
  * ```typescript
156
173
  * const available = HardwareContext.listAvailable();
157
174
  * console.log('Available hardware:', available.join(', '));
175
+ * // Output: "cuda, vaapi, videotoolbox"
158
176
  * ```
177
+ *
178
+ * @see {@link auto} For automatic selection
159
179
  */
160
180
  static listAvailable() {
161
181
  const types = HardwareDeviceContext.iterateTypes();
@@ -171,9 +191,13 @@ export class HardwareContext {
171
191
  /**
172
192
  * Get the hardware device context.
173
193
  *
174
- * This can be assigned to CodecContext.hwDeviceCtx for hardware acceleration.
194
+ * Used internally by encoders and decoders for hardware acceleration.
195
+ * Can be assigned to CodecContext.hwDeviceCtx.
175
196
  *
176
- * @returns Hardware device context
197
+ * @example
198
+ * ```typescript
199
+ * codecContext.hwDeviceCtx = hw.deviceContext;
200
+ * ```
177
201
  */
178
202
  get deviceContext() {
179
203
  return this._deviceContext;
@@ -181,7 +205,12 @@ export class HardwareContext {
181
205
  /**
182
206
  * Get the device type enum value.
183
207
  *
184
- * @returns AVHWDeviceType enum value
208
+ * @example
209
+ * ```typescript
210
+ * if (hw.deviceType === AV_HWDEVICE_TYPE_CUDA) {
211
+ * console.log('Using NVIDIA GPU');
212
+ * }
213
+ * ```
185
214
  */
186
215
  get deviceType() {
187
216
  return this._deviceType;
@@ -189,9 +218,13 @@ export class HardwareContext {
189
218
  /**
190
219
  * Get the hardware device type name.
191
220
  *
192
- * Uses FFmpeg's native av_hwdevice_get_type_name() function.
221
+ * Human-readable device type string.
193
222
  *
194
- * @returns Device type name as string (e.g., 'cuda', 'videotoolbox')
223
+ * @example
224
+ * ```typescript
225
+ * console.log(`Hardware type: ${hw.deviceTypeName}`);
226
+ * // Output: "cuda" or "videotoolbox" etc.
227
+ * ```
195
228
  */
196
229
  get deviceTypeName() {
197
230
  return this._deviceTypeName;
@@ -199,7 +232,12 @@ export class HardwareContext {
199
232
  /**
200
233
  * Get the device pixel format.
201
234
  *
202
- * @returns Device pixel format
235
+ * Hardware-specific pixel format for frame allocation.
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * frame.format = hw.devicePixelFormat;
240
+ * ```
203
241
  */
204
242
  get devicePixelFormat() {
205
243
  return this._devicePixelFormat;
@@ -207,61 +245,38 @@ export class HardwareContext {
207
245
  /**
208
246
  * Check if this hardware context has been disposed.
209
247
  *
210
- * @returns True if disposed
248
+ * @example
249
+ * ```typescript
250
+ * if (!hw.isDisposed) {
251
+ * hw.dispose();
252
+ * }
253
+ * ```
211
254
  */
212
255
  get isDisposed() {
213
256
  return this._isDisposed;
214
257
  }
215
- /**
216
- * Get the hardware pixel format for this device type.
217
- *
218
- * Maps device types to their corresponding pixel formats.
219
- *
220
- * Returns the appropriate AV_PIX_FMT_* constant for the hardware type.
221
- *
222
- * @returns Hardware pixel format
223
- */
224
- getHardwarePixelFormat() {
225
- switch (this._deviceType) {
226
- case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
227
- return AV_PIX_FMT_VIDEOTOOLBOX;
228
- case AV_HWDEVICE_TYPE_VAAPI:
229
- return AV_PIX_FMT_VAAPI;
230
- case AV_HWDEVICE_TYPE_CUDA:
231
- return AV_PIX_FMT_CUDA;
232
- case AV_HWDEVICE_TYPE_QSV:
233
- return AV_PIX_FMT_QSV;
234
- case AV_HWDEVICE_TYPE_D3D11VA:
235
- return AV_PIX_FMT_D3D11;
236
- case AV_HWDEVICE_TYPE_DXVA2:
237
- return AV_PIX_FMT_DXVA2_VLD;
238
- case AV_HWDEVICE_TYPE_DRM:
239
- return AV_PIX_FMT_DRM_PRIME;
240
- case AV_HWDEVICE_TYPE_OPENCL:
241
- return AV_PIX_FMT_OPENCL;
242
- case AV_HWDEVICE_TYPE_MEDIACODEC:
243
- return AV_PIX_FMT_MEDIACODEC;
244
- case AV_HWDEVICE_TYPE_VULKAN:
245
- return AV_PIX_FMT_VULKAN;
246
- case AV_HWDEVICE_TYPE_D3D12VA:
247
- return AV_PIX_FMT_D3D12;
248
- case AV_HWDEVICE_TYPE_RKMPP:
249
- return AV_PIX_FMT_DRM_PRIME; // RKMPP uses DRM Prime buffers
250
- default:
251
- return AV_PIX_FMT_NV12; // Common hardware format
252
- }
253
- }
254
258
  /**
255
259
  * Check if this hardware type supports a specific codec.
256
260
  *
257
- * Checks both decoder and encoder support by querying FFmpeg's codec configurations.
261
+ * Queries FFmpeg's codec configurations to verify hardware support.
262
+ * Checks both decoder and encoder support based on parameters.
258
263
  *
259
- * Uses avcodec_get_hw_config() internally to check hardware support.
264
+ * Direct mapping to avcodec_get_hw_config().
260
265
  *
261
266
  * @param codecId - Codec ID from AVCodecID enum
262
- * @param isEncoder - Check for encoder support (default: false for decoder)
267
+ * @param isEncoder - Check for encoder support (default: decoder)
268
+ * @returns true if codec is supported
269
+ *
270
+ * @example
271
+ * ```typescript
272
+ * import { AV_CODEC_ID_H264 } from 'node-av/constants';
263
273
  *
264
- * @returns True if codec is supported by this hardware
274
+ * if (hw.supportsCodec(AV_CODEC_ID_H264, true)) {
275
+ * // Can use hardware H.264 encoder
276
+ * }
277
+ * ```
278
+ *
279
+ * @see {@link findSupportedCodecs} For all supported codecs
265
280
  */
266
281
  supportsCodec(codecId, isEncoder = false) {
267
282
  // Try to find the codec
@@ -269,30 +284,34 @@ export class HardwareContext {
269
284
  if (!codec) {
270
285
  return false;
271
286
  }
272
- // Check hardware configurations
273
- for (let i = 0;; i++) {
274
- const config = codec.getHwConfig(i);
275
- if (!config) {
276
- break; // No more configurations
277
- }
278
- // Check if this hardware device type is supported
279
- // Accept both HW_DEVICE_CTX and HW_FRAMES_CTX methods
280
- const supportsDeviceCtx = (config.methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) !== 0;
281
- const supportsFramesCtx = (config.methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX) !== 0;
282
- if ((supportsDeviceCtx || supportsFramesCtx) && config.deviceType === this._deviceType) {
283
- return true;
284
- }
287
+ if (isEncoder) {
288
+ return codec.isHardwareAcceleratedEncoder(this._deviceType);
289
+ }
290
+ else {
291
+ return codec.isHardwareAcceleratedDecoder(this._deviceType);
285
292
  }
286
- return false;
287
293
  }
288
294
  /**
289
- * Check if this hardware device type supports a specific pixel format.
295
+ * Check if this hardware supports a specific pixel format for a codec.
296
+ *
297
+ * Verifies pixel format compatibility with hardware codec.
298
+ * Important for ensuring format compatibility in pipelines.
290
299
  *
291
300
  * @param codecId - Codec ID from AVCodecID enum
292
301
  * @param pixelFormat - Pixel format to check
293
- * @param isEncoder - Check for encoder support (default: false for decoder)
302
+ * @param isEncoder - Check for encoder (default: decoder)
303
+ * @returns true if pixel format is supported
304
+ *
305
+ * @example
306
+ * ```typescript
307
+ * import { AV_CODEC_ID_H264, AV_PIX_FMT_NV12 } from 'node-av/constants';
308
+ *
309
+ * if (hw.supportsPixelFormat(AV_CODEC_ID_H264, AV_PIX_FMT_NV12)) {
310
+ * // Can use NV12 format with H.264
311
+ * }
312
+ * ```
294
313
  *
295
- * @returns True if pixel format is supported by this hardware
314
+ * @see {@link supportsCodec} For basic codec support
296
315
  */
297
316
  supportsPixelFormat(codecId, pixelFormat, isEncoder = false) {
298
317
  const codec = isEncoder ? Codec.findEncoder(codecId) : Codec.findDecoder(codecId);
@@ -306,77 +325,131 @@ export class HardwareContext {
306
325
  return pixelFormats.some((fmt) => fmt === pixelFormat);
307
326
  }
308
327
  /**
309
- * Get the appropriate hardware encoder name for a given codec.
328
+ * Get the appropriate encoder codec for a given base codec name.
310
329
  *
311
- * Maps generic codec names and hardware types to their specific encoder implementations.
312
- * For example, 'h264' with VideoToolbox returns 'h264_videotoolbox'.
330
+ * Maps generic codec names to hardware-specific encoder implementations.
331
+ * Returns null if no hardware encoder is available for the codec.
332
+ * Automatically tests encoder viability before returning.
313
333
  *
314
- * @param codecName - Generic codec name (e.g., 'h264', 'hevc', 'av1')
315
- *
316
- * @returns Hardware encoder name or null if not supported
334
+ * @param codec - Generic codec name (e.g., 'h264', 'hevc', 'av1') or AVCodecID
335
+ * @returns Hardware encoder codec or null if unsupported
317
336
  *
318
337
  * @example
319
338
  * ```typescript
320
- * const hw = await HardwareContext.auto();
321
- * const encoderName = hw.getEncoderName('h264');
322
- * // Returns 'h264_videotoolbox' on macOS, 'h264_nvenc' with CUDA, etc.
339
+ * const encoderCodec = await hw.getEncoderCodec('h264');
340
+ * if (encoderCodec) {
341
+ * console.log(`Using encoder: ${encoderCodec.name}`);
342
+ * // e.g., "h264_nvenc" for CUDA
343
+ * }
344
+ * ```
323
345
  *
324
- * // Use the encoder
325
- * const encoder = Codec.findEncoderByName(encoderName);
346
+ * @example
347
+ * ```typescript
348
+ * // Use with Encoder.create
349
+ * const codec = await hw.getEncoderCodec('hevc');
350
+ * if (codec) {
351
+ * const encoder = await Encoder.create(codec, streamInfo, {
352
+ * hardware: hw
353
+ * });
354
+ * }
326
355
  * ```
356
+ *
357
+ * @see {@link Encoder.create} For using the codec
327
358
  */
328
- getEncoderCodec(codecName) {
329
- // Get the hardware device type name from FFmpeg
330
- const deviceTypeName = HardwareDeviceContext.getTypeName(this._deviceType);
331
- if (!deviceTypeName)
332
- return null;
359
+ async getEncoderCodec(codec) {
333
360
  // Build the encoder name
334
- let encoderSuffix;
335
- switch (deviceTypeName) {
336
- case 'cuda':
361
+ let codecBaseName = '';
362
+ let encoderSuffix = '';
363
+ if (typeof codec === 'number') {
364
+ codecBaseName = this.getBaseCodecName(codec) ?? '';
365
+ }
366
+ else {
367
+ codecBaseName = codec;
368
+ }
369
+ if (!codecBaseName) {
370
+ return null;
371
+ }
372
+ // We might only have hardware decode capabilities (d3d11va, d3d12va etc)
373
+ // So we need to check for other hardware encoders
374
+ const getAlternativeEncoder = () => {
375
+ const nvencCodecName = `${codecBaseName}_nvenc`;
376
+ const qsvCodecName = `${codecBaseName}_qsv`;
377
+ const amfCodecName = `${codecBaseName}_amf`;
378
+ const codecNames = [nvencCodecName, qsvCodecName, amfCodecName];
379
+ let suffix = '';
380
+ for (const name of codecNames) {
381
+ const encoderCodec = Codec.findEncoderByName(name);
382
+ if (!encoderCodec) {
383
+ continue;
384
+ }
385
+ suffix = name.split('_')[1]; // Get suffix after underscore
386
+ }
387
+ if (!suffix) {
388
+ return null;
389
+ }
390
+ return suffix;
391
+ };
392
+ switch (this._deviceType) {
393
+ case AV_HWDEVICE_TYPE_CUDA:
337
394
  // CUDA uses NVENC for encoding
338
395
  encoderSuffix = 'nvenc';
339
396
  break;
340
- case 'd3d11va':
341
- case 'dxva2':
342
- // D3D11VA and DXVA2 are decode-only APIs
343
- // Cannot encode with these hardware contexts
344
- // Need nvenc, qsv or amf for encoding
345
- return null;
346
- case 'd3d12va':
397
+ case AV_HWDEVICE_TYPE_D3D11VA:
398
+ case AV_HWDEVICE_TYPE_DXVA2:
399
+ encoderSuffix = getAlternativeEncoder() ?? '';
400
+ break;
401
+ case AV_HWDEVICE_TYPE_D3D12VA:
347
402
  // D3D12VA currently only supports HEVC encoding
348
- if (codecName === 'hevc') {
403
+ if (codecBaseName === 'hevc') {
349
404
  encoderSuffix = 'd3d12va';
350
405
  }
351
- return null;
352
- case 'opencl':
353
- case 'vdpau':
354
- case 'drm':
355
- // These don't have dedicated encoders
356
- return null;
406
+ else {
407
+ encoderSuffix = getAlternativeEncoder() ?? '';
408
+ }
409
+ break;
410
+ case AV_HWDEVICE_TYPE_OPENCL:
411
+ case AV_HWDEVICE_TYPE_VDPAU:
412
+ case AV_HWDEVICE_TYPE_DRM:
413
+ encoderSuffix = getAlternativeEncoder() ?? '';
414
+ break;
357
415
  default:
358
416
  // Use the device type name as suffix
359
- encoderSuffix = deviceTypeName;
417
+ encoderSuffix = this._deviceTypeName;
418
+ }
419
+ if (!encoderSuffix) {
420
+ return null;
360
421
  }
361
422
  // Construct the encoder name
362
- const encoderName = `${codecName}_${encoderSuffix}`;
363
- const codec = Codec.findEncoderByName(encoderName);
364
- if (codec?.name) {
365
- return codec.name;
423
+ const encoderName = `${codecBaseName}_${encoderSuffix}`;
424
+ const encoderCodec = Codec.findEncoderByName(encoderName);
425
+ if (!encoderCodec || !(await this.testHardwareEncoder(encoderName))) {
426
+ return null;
366
427
  }
367
- return null;
428
+ return encoderCodec;
368
429
  }
369
430
  /**
370
431
  * Find all codecs that support this hardware device.
371
432
  *
372
- * Uses FFmpeg's native codec list to find compatible codecs.
433
+ * Iterates through all available codecs and checks hardware compatibility.
434
+ * Useful for discovering available hardware acceleration options.
373
435
  *
374
- * Iterates through all codecs using av_codec_iterate() and checks
375
- * their hardware configurations.
436
+ * Direct mapping to av_codec_iterate() with hardware config checks.
376
437
  *
377
438
  * @param isEncoder - Find encoders (true) or decoders (false)
378
- *
379
439
  * @returns Array of codec names that support this hardware
440
+ *
441
+ * @example
442
+ * ```typescript
443
+ * const decoders = hw.findSupportedCodecs(false);
444
+ * console.log('Hardware decoders:', decoders);
445
+ * // ["h264_cuvid", "hevc_cuvid", ...]
446
+ *
447
+ * const encoders = hw.findSupportedCodecs(true);
448
+ * console.log('Hardware encoders:', encoders);
449
+ * // ["h264_nvenc", "hevc_nvenc", ...]
450
+ * ```
451
+ *
452
+ * @see {@link supportsCodec} For checking specific codec
380
453
  */
381
454
  findSupportedCodecs(isEncoder = false) {
382
455
  const supportedCodecs = [];
@@ -408,100 +481,250 @@ export class HardwareContext {
408
481
  /**
409
482
  * Clean up and free hardware resources.
410
483
  *
411
- * Safe to call multiple times - subsequent calls are no-ops.
412
- * Called automatically by Decoder/Encoder on close.
484
+ * Releases the hardware device context.
485
+ * Safe to call multiple times.
486
+ * Automatically called by Symbol.dispose.
413
487
  *
414
- * Frees both frames context (if created) and device context.
415
- * Notifies any waiting components that disposal occurred.
488
+ * @example
489
+ * ```typescript
490
+ * const hw = HardwareContext.auto();
491
+ * try {
492
+ * // Use hardware
493
+ * } finally {
494
+ * hw?.dispose();
495
+ * }
496
+ * ```
497
+ *
498
+ * @see {@link Symbol.dispose} For automatic cleanup
416
499
  */
417
500
  dispose() {
418
501
  if (this._isDisposed) {
419
- return; // Already disposed, safe to return
502
+ return;
420
503
  }
421
504
  this._deviceContext.free();
422
505
  this._isDisposed = true;
423
506
  }
507
+ /**
508
+ * Map AVCodecID to base codec name for hardware encoder lookup.
509
+ *
510
+ * Converts codec IDs to generic codec names used for encoder naming.
511
+ * Used internally to find hardware-specific encoder implementations.
512
+ *
513
+ * @param codecId - AVCodecID enum value
514
+ * @returns Base codec name or null if unsupported
515
+ *
516
+ * @internal
517
+ */
518
+ getBaseCodecName(codecId) {
519
+ switch (codecId) {
520
+ case AV_CODEC_ID_AV1:
521
+ return 'av1';
522
+ case AV_CODEC_ID_H264:
523
+ return 'h264';
524
+ case AV_CODEC_ID_HEVC:
525
+ return 'hevc';
526
+ case AV_CODEC_ID_H263:
527
+ return 'h263';
528
+ case AV_CODEC_ID_MPEG2VIDEO:
529
+ return 'mpeg2';
530
+ case AV_CODEC_ID_MPEG4:
531
+ return 'mpeg4';
532
+ case AV_CODEC_ID_VP8:
533
+ return 'vp8';
534
+ case AV_CODEC_ID_VP9:
535
+ return 'vp9';
536
+ case AV_CODEC_ID_MJPEG:
537
+ return 'mjpeg';
538
+ case AV_CODEC_ID_PRORES:
539
+ return 'prores';
540
+ default:
541
+ return null;
542
+ }
543
+ }
544
+ /**
545
+ * Get the hardware decoder pixel format for this device type.
546
+ *
547
+ * Maps device types to their corresponding pixel formats.
548
+ * Used internally for frame format configuration.
549
+ *
550
+ * @returns Hardware-specific pixel format
551
+ *
552
+ * @internal
553
+ */
554
+ getHardwareDecoderPixelFormat() {
555
+ switch (this._deviceType) {
556
+ case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
557
+ return AV_PIX_FMT_VIDEOTOOLBOX;
558
+ case AV_HWDEVICE_TYPE_VAAPI:
559
+ return AV_PIX_FMT_VAAPI;
560
+ case AV_HWDEVICE_TYPE_CUDA:
561
+ return AV_PIX_FMT_CUDA;
562
+ case AV_HWDEVICE_TYPE_QSV:
563
+ return AV_PIX_FMT_QSV;
564
+ case AV_HWDEVICE_TYPE_D3D11VA:
565
+ return AV_PIX_FMT_D3D11;
566
+ case AV_HWDEVICE_TYPE_DXVA2:
567
+ return AV_PIX_FMT_DXVA2_VLD;
568
+ case AV_HWDEVICE_TYPE_DRM:
569
+ return AV_PIX_FMT_DRM_PRIME;
570
+ case AV_HWDEVICE_TYPE_OPENCL:
571
+ return AV_PIX_FMT_OPENCL;
572
+ case AV_HWDEVICE_TYPE_MEDIACODEC:
573
+ return AV_PIX_FMT_MEDIACODEC;
574
+ case AV_HWDEVICE_TYPE_VULKAN:
575
+ return AV_PIX_FMT_VULKAN;
576
+ case AV_HWDEVICE_TYPE_D3D12VA:
577
+ return AV_PIX_FMT_D3D12;
578
+ case AV_HWDEVICE_TYPE_RKMPP:
579
+ return AV_PIX_FMT_DRM_PRIME; // RKMPP uses DRM Prime buffers
580
+ default:
581
+ return AV_PIX_FMT_NV12; // Common hardware format
582
+ }
583
+ }
584
+ /**
585
+ * Test if a hardware encoder can be created.
586
+ *
587
+ * Attempts to initialize the encoder to verify support.
588
+ * Used internally by getEncoderCodec.
589
+ *
590
+ * @param encoderCodec - Encoder to test
591
+ *
592
+ * @returns true if encoder can be initialized
593
+ *
594
+ * @internal
595
+ */
596
+ async testHardwareEncoder(encoderCodec) {
597
+ let codec = null;
598
+ if (encoderCodec instanceof Codec) {
599
+ codec = encoderCodec;
600
+ }
601
+ else if (typeof encoderCodec === 'string') {
602
+ codec = Codec.findEncoderByName(encoderCodec);
603
+ }
604
+ else {
605
+ codec = Codec.findEncoder(encoderCodec);
606
+ }
607
+ if (!codec?.pixelFormats || !codec.isHardwareAcceleratedEncoder()) {
608
+ return false;
609
+ }
610
+ const codecContext = new CodecContext();
611
+ codecContext.allocContext3(codec);
612
+ codecContext.hwDeviceCtx = this._deviceContext;
613
+ codecContext.timeBase = new Rational(1, 30);
614
+ codecContext.pixelFormat = codec.pixelFormats[0];
615
+ codecContext.width = 100;
616
+ codecContext.height = 100;
617
+ const ret = await codecContext.open2(codec);
618
+ codecContext.freeContext();
619
+ return ret >= 0;
620
+ }
424
621
  /**
425
622
  * Create hardware context from device type.
426
623
  *
427
624
  * Internal factory method using av_hwdevice_ctx_create().
428
625
  *
429
626
  * @param deviceType - AVHWDeviceType enum value
430
- * @param deviceName - Optional device name/index
627
+ * @param device - Optional device specifier
431
628
  * @param options - Optional device options
432
629
  *
433
- * @returns HardwareContext or null if creation fails
630
+ * @returns Hardware context or null if creation fails
631
+ *
632
+ * @internal
434
633
  */
435
- static async createFromType(deviceType, deviceName, options) {
436
- const device = new HardwareDeviceContext();
634
+ static createFromType(deviceType, device, options) {
635
+ const deviceCtx = new HardwareDeviceContext();
437
636
  // Convert options to Dictionary if provided
438
637
  let optionsDict = null;
439
638
  if (options && Object.keys(options).length > 0) {
440
639
  optionsDict = Dictionary.fromObject(options);
441
640
  }
442
- const ret = device.create(deviceType, deviceName ?? null, optionsDict);
641
+ const ret = deviceCtx.create(deviceType, device, optionsDict);
443
642
  // Clean up dictionary if used
444
643
  if (optionsDict) {
445
644
  optionsDict.free();
446
645
  }
447
- if (ret < 0) {
448
- device.free();
646
+ const deviceTypeName = HardwareDeviceContext.getTypeName(deviceType);
647
+ if (ret < 0 || !deviceTypeName) {
648
+ deviceCtx.free();
449
649
  return null;
450
650
  }
451
- return new HardwareContext(device, deviceType, deviceName);
651
+ return new HardwareContext(deviceCtx, deviceType, deviceTypeName);
452
652
  }
453
653
  /**
454
654
  * Get platform-specific preference order for hardware types.
455
655
  *
456
- * Returns the optimal hardware types for the current platform.
656
+ * Returns available hardware types sorted by platform preference.
657
+ * Ensures optimal hardware selection for each platform.
457
658
  *
458
659
  * @returns Array of AVHWDeviceType values in preference order
660
+ *
661
+ * @internal
459
662
  */
460
663
  static getPreferenceOrder() {
664
+ // Get all available hardware types on this system
665
+ const available = HardwareDeviceContext.iterateTypes();
666
+ if (available.length === 0) {
667
+ return [];
668
+ }
461
669
  const platform = process.platform;
670
+ let preferenceOrder;
462
671
  if (platform === 'darwin') {
463
672
  // macOS: VideoToolbox is preferred
464
- return [AV_HWDEVICE_TYPE_VIDEOTOOLBOX, AV_HWDEVICE_TYPE_VULKAN, AV_HWDEVICE_TYPE_OPENCL];
673
+ preferenceOrder = [AV_HWDEVICE_TYPE_VIDEOTOOLBOX];
465
674
  }
466
675
  else if (platform === 'win32') {
467
- // Windows: D3D12VA (newest), D3D11VA, DXVA2, QSV, CUDA
468
- return [
469
- AV_HWDEVICE_TYPE_D3D12VA,
470
- AV_HWDEVICE_TYPE_D3D11VA,
676
+ // Windows: Match FFmpeg's hw_configs order
677
+ // DXVA2 → D3D11VA → D3D12VA → NVDEC (CUDA)
678
+ preferenceOrder = [
471
679
  AV_HWDEVICE_TYPE_DXVA2,
472
- AV_HWDEVICE_TYPE_QSV,
680
+ AV_HWDEVICE_TYPE_D3D11VA,
681
+ AV_HWDEVICE_TYPE_D3D12VA,
473
682
  AV_HWDEVICE_TYPE_CUDA,
683
+ AV_HWDEVICE_TYPE_QSV,
474
684
  AV_HWDEVICE_TYPE_VULKAN,
475
685
  AV_HWDEVICE_TYPE_OPENCL,
476
686
  ];
477
687
  }
478
688
  else {
479
- // Linux: RKMPP (for ARM/Rockchip), VAAPI, VDPAU, CUDA, Vulkan, DRM
480
- return [
481
- AV_HWDEVICE_TYPE_RKMPP,
482
- AV_HWDEVICE_TYPE_VAAPI,
483
- AV_HWDEVICE_TYPE_VDPAU,
484
- AV_HWDEVICE_TYPE_CUDA,
485
- AV_HWDEVICE_TYPE_VULKAN,
486
- AV_HWDEVICE_TYPE_DRM,
487
- AV_HWDEVICE_TYPE_OPENCL,
488
- ];
689
+ // Linux: Match FFmpeg's hw_configs order
690
+ // NVDEC (CUDA) → VAAPI → VDPAU → Vulkan
691
+ // RKMPP is platform-specific for ARM/Rockchip
692
+ const isARM = process.arch === 'arm64' || process.arch === 'arm';
693
+ if (isARM) {
694
+ // ARM platforms: Prioritize RKMPP for Rockchip SoCs
695
+ preferenceOrder = [AV_HWDEVICE_TYPE_RKMPP, AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_VULKAN, AV_HWDEVICE_TYPE_DRM, AV_HWDEVICE_TYPE_OPENCL];
696
+ }
697
+ else {
698
+ // x86_64 Linux: CUDA → VAAPI → VDPAU → Vulkan
699
+ preferenceOrder = [AV_HWDEVICE_TYPE_CUDA, AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_VDPAU, AV_HWDEVICE_TYPE_VULKAN, AV_HWDEVICE_TYPE_DRM, AV_HWDEVICE_TYPE_OPENCL];
700
+ }
489
701
  }
702
+ // Filter preference order to only include available types
703
+ const availableSet = new Set(available);
704
+ const sortedAvailable = preferenceOrder.filter((type) => availableSet.has(type));
705
+ // Add any available types not in our preference list at the end
706
+ for (const type of available) {
707
+ if (!preferenceOrder.includes(type)) {
708
+ sortedAvailable.push(type);
709
+ }
710
+ }
711
+ return sortedAvailable;
490
712
  }
491
713
  /**
492
- * Automatic cleanup when using 'using' statement.
493
- *
494
- * Implements the Disposable interface for automatic cleanup.
714
+ * Dispose of hardware context.
495
715
  *
496
- * Calls dispose() to free hardware resources.
716
+ * Implements Disposable interface for automatic cleanup.
717
+ * Equivalent to calling dispose().
497
718
  *
498
719
  * @example
499
720
  * ```typescript
500
721
  * {
501
- * using hw = await HardwareContext.auto();
722
+ * using hw = HardwareContext.auto();
502
723
  * // Use hardware context...
503
724
  * } // Automatically disposed
504
725
  * ```
726
+ *
727
+ * @see {@link dispose} For manual cleanup
505
728
  */
506
729
  [Symbol.dispose]() {
507
730
  this.dispose();