node-av 1.1.0 → 1.2.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.
- package/README.md +51 -38
- package/dist/api/bitstream-filter.d.ts +180 -123
- package/dist/api/bitstream-filter.js +180 -125
- package/dist/api/bitstream-filter.js.map +1 -1
- package/dist/api/decoder.d.ts +279 -132
- package/dist/api/decoder.js +285 -142
- package/dist/api/decoder.js.map +1 -1
- package/dist/api/encoder.d.ts +246 -162
- package/dist/api/encoder.js +272 -208
- package/dist/api/encoder.js.map +1 -1
- package/dist/api/filter-presets.d.ts +690 -94
- package/dist/api/filter-presets.js +686 -102
- package/dist/api/filter-presets.js.map +1 -1
- package/dist/api/filter.d.ts +249 -213
- package/dist/api/filter.js +252 -242
- package/dist/api/filter.js.map +1 -1
- package/dist/api/hardware.d.ts +224 -117
- package/dist/api/hardware.js +380 -214
- package/dist/api/hardware.js.map +1 -1
- package/dist/api/index.d.ts +3 -3
- package/dist/api/index.js +1 -1
- package/dist/api/index.js.map +1 -1
- package/dist/api/io-stream.d.ts +65 -61
- package/dist/api/io-stream.js +43 -46
- package/dist/api/io-stream.js.map +1 -1
- package/dist/api/media-input.d.ts +242 -140
- package/dist/api/media-input.js +205 -103
- package/dist/api/media-input.js.map +1 -1
- package/dist/api/media-output.d.ts +206 -128
- package/dist/api/media-output.js +210 -128
- package/dist/api/media-output.js.map +1 -1
- package/dist/api/pipeline.d.ts +168 -38
- package/dist/api/pipeline.js +238 -14
- package/dist/api/pipeline.js.map +1 -1
- package/dist/api/types.d.ts +21 -187
- package/dist/api/utils.d.ts +1 -2
- package/dist/api/utils.js +9 -0
- package/dist/api/utils.js.map +1 -1
- package/dist/lib/audio-fifo.d.ts +127 -170
- package/dist/lib/audio-fifo.js +130 -173
- package/dist/lib/audio-fifo.js.map +1 -1
- package/dist/lib/binding.js +5 -0
- package/dist/lib/binding.js.map +1 -1
- package/dist/lib/bitstream-filter-context.d.ts +139 -184
- package/dist/lib/bitstream-filter-context.js +139 -188
- package/dist/lib/bitstream-filter-context.js.map +1 -1
- package/dist/lib/bitstream-filter.d.ts +68 -54
- package/dist/lib/bitstream-filter.js +68 -54
- package/dist/lib/bitstream-filter.js.map +1 -1
- package/dist/lib/codec-context.d.ts +316 -380
- package/dist/lib/codec-context.js +316 -381
- package/dist/lib/codec-context.js.map +1 -1
- package/dist/lib/codec-parameters.d.ts +160 -170
- package/dist/lib/codec-parameters.js +162 -172
- package/dist/lib/codec-parameters.js.map +1 -1
- package/dist/lib/codec-parser.d.ts +91 -104
- package/dist/lib/codec-parser.js +92 -103
- package/dist/lib/codec-parser.js.map +1 -1
- package/dist/lib/codec.d.ts +264 -281
- package/dist/lib/codec.js +268 -285
- package/dist/lib/codec.js.map +1 -1
- package/dist/lib/dictionary.d.ts +149 -203
- package/dist/lib/dictionary.js +158 -212
- package/dist/lib/dictionary.js.map +1 -1
- package/dist/lib/error.d.ts +96 -130
- package/dist/lib/error.js +98 -128
- package/dist/lib/error.js.map +1 -1
- package/dist/lib/filter-context.d.ts +284 -218
- package/dist/lib/filter-context.js +290 -227
- package/dist/lib/filter-context.js.map +1 -1
- package/dist/lib/filter-graph.d.ts +251 -292
- package/dist/lib/filter-graph.js +253 -294
- package/dist/lib/filter-graph.js.map +1 -1
- package/dist/lib/filter-inout.d.ts +87 -95
- package/dist/lib/filter-inout.js +87 -95
- package/dist/lib/filter-inout.js.map +1 -1
- package/dist/lib/filter.d.ts +93 -111
- package/dist/lib/filter.js +93 -111
- package/dist/lib/filter.js.map +1 -1
- package/dist/lib/format-context.d.ts +320 -428
- package/dist/lib/format-context.js +313 -385
- package/dist/lib/format-context.js.map +1 -1
- package/dist/lib/frame.d.ts +262 -405
- package/dist/lib/frame.js +263 -408
- package/dist/lib/frame.js.map +1 -1
- package/dist/lib/hardware-device-context.d.ts +149 -203
- package/dist/lib/hardware-device-context.js +149 -203
- package/dist/lib/hardware-device-context.js.map +1 -1
- package/dist/lib/hardware-frames-context.d.ts +170 -180
- package/dist/lib/hardware-frames-context.js +171 -181
- package/dist/lib/hardware-frames-context.js.map +1 -1
- package/dist/lib/index.d.ts +2 -1
- package/dist/lib/index.js +2 -2
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/input-format.d.ts +89 -117
- package/dist/lib/input-format.js +89 -117
- package/dist/lib/input-format.js.map +1 -1
- package/dist/lib/io-context.d.ts +209 -241
- package/dist/lib/io-context.js +220 -252
- package/dist/lib/io-context.js.map +1 -1
- package/dist/lib/log.d.ts +85 -119
- package/dist/lib/log.js +85 -122
- package/dist/lib/log.js.map +1 -1
- package/dist/lib/native-types.d.ts +117 -106
- package/dist/lib/native-types.js +0 -7
- package/dist/lib/native-types.js.map +1 -1
- package/dist/lib/option.d.ts +284 -241
- package/dist/lib/option.js +309 -249
- package/dist/lib/option.js.map +1 -1
- package/dist/lib/output-format.d.ts +77 -101
- package/dist/lib/output-format.js +77 -101
- package/dist/lib/output-format.js.map +1 -1
- package/dist/lib/packet.d.ts +172 -240
- package/dist/lib/packet.js +172 -241
- package/dist/lib/packet.js.map +1 -1
- package/dist/lib/rational.d.ts +0 -2
- package/dist/lib/rational.js +0 -2
- package/dist/lib/rational.js.map +1 -1
- package/dist/lib/software-resample-context.d.ts +241 -325
- package/dist/lib/software-resample-context.js +242 -326
- package/dist/lib/software-resample-context.js.map +1 -1
- package/dist/lib/software-scale-context.d.ts +129 -173
- package/dist/lib/software-scale-context.js +131 -175
- package/dist/lib/software-scale-context.js.map +1 -1
- package/dist/lib/stream.d.ts +87 -197
- package/dist/lib/stream.js +87 -197
- package/dist/lib/stream.js.map +1 -1
- package/dist/lib/utilities.d.ts +372 -181
- package/dist/lib/utilities.js +373 -182
- package/dist/lib/utilities.js.map +1 -1
- package/install/check.js +0 -1
- package/package.json +21 -12
- package/release_notes.md +43 -59
- package/CHANGELOG.md +0 -8
package/dist/api/hardware.js
CHANGED
|
@@ -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
1
|
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';
|
|
2
|
+
import { Codec, CodecContext, Dictionary, HardwareDeviceContext, Rational } from '../lib/index.js';
|
|
14
3
|
import { HardwareFilterPresets } from './filter-presets.js';
|
|
15
4
|
/**
|
|
16
|
-
*
|
|
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
|
-
*
|
|
22
|
-
*
|
|
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 =
|
|
18
|
+
* const hw = HardwareContext.auto();
|
|
30
19
|
* if (hw) {
|
|
31
|
-
* console.log(`Using hardware: ${hw.
|
|
32
|
-
* decoder
|
|
20
|
+
* console.log(`Using hardware: ${hw.deviceTypeName}`);
|
|
21
|
+
* const decoder = await Decoder.create(stream, { hardware: hw });
|
|
33
22
|
* }
|
|
23
|
+
* ```
|
|
34
24
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
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
|
|
52
|
+
* @param deviceType - Hardware device type enum
|
|
53
|
+
* @param deviceTypeName - Human-readable device type name
|
|
54
|
+
* @internal
|
|
65
55
|
*/
|
|
66
|
-
constructor(deviceContext, deviceType,
|
|
56
|
+
constructor(deviceContext, deviceType, deviceTypeName) {
|
|
67
57
|
this._deviceContext = deviceContext;
|
|
68
58
|
this._deviceType = deviceType;
|
|
69
|
-
this._deviceTypeName =
|
|
70
|
-
this._devicePixelFormat = this.
|
|
71
|
-
this.filterPresets = new HardwareFilterPresets(deviceType,
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
117
|
-
*
|
|
117
|
+
* Creates and initializes a hardware device context.
|
|
118
|
+
* Throws if the device type is not supported or initialization fails.
|
|
119
|
+
*
|
|
120
|
+
* Direct mapping to av_hwdevice_ctx_create().
|
|
118
121
|
*
|
|
119
|
-
* @param
|
|
120
|
-
* @param
|
|
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
|
-
* @
|
|
129
|
+
* @example
|
|
130
|
+
* ```typescript
|
|
131
|
+
* import { AV_HWDEVICE_TYPE_CUDA } from 'node-av/constants';
|
|
124
132
|
*
|
|
125
|
-
*
|
|
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
|
-
*
|
|
130
|
-
* const cuda = await HardwareContext.create(AV_HWDEVICE_TYPE_CUDA, '0');
|
|
139
|
+
* import { AV_HWDEVICE_TYPE_VAAPI } from 'node-av/constants';
|
|
131
140
|
*
|
|
132
|
-
* //
|
|
133
|
-
* const vaapi =
|
|
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
|
|
137
|
-
if (
|
|
138
|
-
throw new Error(
|
|
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 =
|
|
155
|
+
const hw = this.createFromType(deviceType, device, options);
|
|
141
156
|
if (!hw) {
|
|
142
|
-
throw new Error(`Failed to create hardware context for ${
|
|
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
|
-
*
|
|
150
|
-
*
|
|
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
|
-
*
|
|
194
|
+
* Used internally by encoders and decoders for hardware acceleration.
|
|
195
|
+
* Can be assigned to CodecContext.hwDeviceCtx.
|
|
175
196
|
*
|
|
176
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
*
|
|
221
|
+
* Human-readable device type string.
|
|
193
222
|
*
|
|
194
|
-
* @
|
|
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
|
-
*
|
|
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
|
-
* @
|
|
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
|
-
*
|
|
261
|
+
* Queries FFmpeg's codec configurations to verify hardware support.
|
|
262
|
+
* Checks both decoder and encoder support based on parameters.
|
|
258
263
|
*
|
|
259
|
-
*
|
|
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:
|
|
267
|
+
* @param isEncoder - Check for encoder support (default: decoder)
|
|
268
|
+
* @returns true if codec is supported
|
|
263
269
|
*
|
|
264
|
-
* @
|
|
270
|
+
* @example
|
|
271
|
+
* ```typescript
|
|
272
|
+
* import { AV_CODEC_ID_H264 } from 'node-av/constants';
|
|
273
|
+
*
|
|
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
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
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
|
|
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
|
|
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';
|
|
294
308
|
*
|
|
295
|
-
*
|
|
309
|
+
* if (hw.supportsPixelFormat(AV_CODEC_ID_H264, AV_PIX_FMT_NV12)) {
|
|
310
|
+
* // Can use NV12 format with H.264
|
|
311
|
+
* }
|
|
312
|
+
* ```
|
|
313
|
+
*
|
|
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,121 @@ export class HardwareContext {
|
|
|
306
325
|
return pixelFormats.some((fmt) => fmt === pixelFormat);
|
|
307
326
|
}
|
|
308
327
|
/**
|
|
309
|
-
* Get the appropriate
|
|
328
|
+
* Get the appropriate encoder codec for a given base codec name.
|
|
310
329
|
*
|
|
311
|
-
* Maps generic codec names
|
|
312
|
-
*
|
|
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
334
|
* @param codecName - Generic codec name (e.g., 'h264', 'hevc', 'av1')
|
|
315
|
-
*
|
|
316
|
-
* @returns Hardware encoder name or null if not supported
|
|
335
|
+
* @returns Hardware encoder codec or null if unsupported
|
|
317
336
|
*
|
|
318
337
|
* @example
|
|
319
338
|
* ```typescript
|
|
320
|
-
* const
|
|
321
|
-
*
|
|
322
|
-
*
|
|
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
|
-
*
|
|
325
|
-
*
|
|
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(codecName) {
|
|
333
360
|
// Build the encoder name
|
|
334
|
-
let encoderSuffix;
|
|
335
|
-
|
|
336
|
-
|
|
361
|
+
let encoderSuffix = '';
|
|
362
|
+
// We might only have hardware decode capabilities (d3d11va, d3d12va etc)
|
|
363
|
+
// So we need to check for other hardware encoders
|
|
364
|
+
const getAlternativeEncoder = () => {
|
|
365
|
+
const nvencCodecName = `${codecName}_nvenc`;
|
|
366
|
+
const qsvCodecName = `${codecName}_qsv`;
|
|
367
|
+
const amfCodecName = `${codecName}_amf`;
|
|
368
|
+
const codecNames = [nvencCodecName, qsvCodecName, amfCodecName];
|
|
369
|
+
let suffix = '';
|
|
370
|
+
for (const name of codecNames) {
|
|
371
|
+
const encoderCodec = Codec.findEncoderByName(name);
|
|
372
|
+
if (!encoderCodec) {
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
suffix = name.split('_')[1]; // Get suffix after underscore
|
|
376
|
+
}
|
|
377
|
+
if (!suffix) {
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
return suffix;
|
|
381
|
+
};
|
|
382
|
+
switch (this._deviceType) {
|
|
383
|
+
case AV_HWDEVICE_TYPE_CUDA:
|
|
337
384
|
// CUDA uses NVENC for encoding
|
|
338
385
|
encoderSuffix = 'nvenc';
|
|
339
386
|
break;
|
|
340
|
-
case
|
|
341
|
-
case
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
return null;
|
|
346
|
-
case 'd3d12va':
|
|
387
|
+
case AV_HWDEVICE_TYPE_D3D11VA:
|
|
388
|
+
case AV_HWDEVICE_TYPE_DXVA2:
|
|
389
|
+
encoderSuffix = getAlternativeEncoder() ?? '';
|
|
390
|
+
break;
|
|
391
|
+
case AV_HWDEVICE_TYPE_D3D12VA:
|
|
347
392
|
// D3D12VA currently only supports HEVC encoding
|
|
348
393
|
if (codecName === 'hevc') {
|
|
349
394
|
encoderSuffix = 'd3d12va';
|
|
350
395
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
396
|
+
else {
|
|
397
|
+
encoderSuffix = getAlternativeEncoder() ?? '';
|
|
398
|
+
}
|
|
399
|
+
break;
|
|
400
|
+
case AV_HWDEVICE_TYPE_OPENCL:
|
|
401
|
+
case AV_HWDEVICE_TYPE_VDPAU:
|
|
402
|
+
case AV_HWDEVICE_TYPE_DRM:
|
|
403
|
+
encoderSuffix = getAlternativeEncoder() ?? '';
|
|
404
|
+
break;
|
|
357
405
|
default:
|
|
358
406
|
// Use the device type name as suffix
|
|
359
|
-
encoderSuffix =
|
|
407
|
+
encoderSuffix = this._deviceTypeName;
|
|
408
|
+
}
|
|
409
|
+
if (!encoderSuffix) {
|
|
410
|
+
return null;
|
|
360
411
|
}
|
|
361
412
|
// Construct the encoder name
|
|
362
413
|
const encoderName = `${codecName}_${encoderSuffix}`;
|
|
363
|
-
const
|
|
364
|
-
if (
|
|
365
|
-
return
|
|
414
|
+
const encoderCodec = Codec.findEncoderByName(encoderName);
|
|
415
|
+
if (!encoderCodec || !(await this.testHardwareEncoder(encoderName))) {
|
|
416
|
+
return null;
|
|
366
417
|
}
|
|
367
|
-
return
|
|
418
|
+
return encoderCodec;
|
|
368
419
|
}
|
|
369
420
|
/**
|
|
370
421
|
* Find all codecs that support this hardware device.
|
|
371
422
|
*
|
|
372
|
-
*
|
|
423
|
+
* Iterates through all available codecs and checks hardware compatibility.
|
|
424
|
+
* Useful for discovering available hardware acceleration options.
|
|
373
425
|
*
|
|
374
|
-
*
|
|
375
|
-
* their hardware configurations.
|
|
426
|
+
* Direct mapping to av_codec_iterate() with hardware config checks.
|
|
376
427
|
*
|
|
377
428
|
* @param isEncoder - Find encoders (true) or decoders (false)
|
|
378
|
-
*
|
|
379
429
|
* @returns Array of codec names that support this hardware
|
|
430
|
+
*
|
|
431
|
+
* @example
|
|
432
|
+
* ```typescript
|
|
433
|
+
* const decoders = hw.findSupportedCodecs(false);
|
|
434
|
+
* console.log('Hardware decoders:', decoders);
|
|
435
|
+
* // ["h264_cuvid", "hevc_cuvid", ...]
|
|
436
|
+
*
|
|
437
|
+
* const encoders = hw.findSupportedCodecs(true);
|
|
438
|
+
* console.log('Hardware encoders:', encoders);
|
|
439
|
+
* // ["h264_nvenc", "hevc_nvenc", ...]
|
|
440
|
+
* ```
|
|
441
|
+
*
|
|
442
|
+
* @see {@link supportsCodec} For checking specific codec
|
|
380
443
|
*/
|
|
381
444
|
findSupportedCodecs(isEncoder = false) {
|
|
382
445
|
const supportedCodecs = [];
|
|
@@ -408,100 +471,203 @@ export class HardwareContext {
|
|
|
408
471
|
/**
|
|
409
472
|
* Clean up and free hardware resources.
|
|
410
473
|
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
474
|
+
* Releases the hardware device context.
|
|
475
|
+
* Safe to call multiple times.
|
|
476
|
+
* Automatically called by Symbol.dispose.
|
|
413
477
|
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
478
|
+
* @example
|
|
479
|
+
* ```typescript
|
|
480
|
+
* const hw = HardwareContext.auto();
|
|
481
|
+
* try {
|
|
482
|
+
* // Use hardware
|
|
483
|
+
* } finally {
|
|
484
|
+
* hw?.dispose();
|
|
485
|
+
* }
|
|
486
|
+
* ```
|
|
487
|
+
*
|
|
488
|
+
* @see {@link Symbol.dispose} For automatic cleanup
|
|
416
489
|
*/
|
|
417
490
|
dispose() {
|
|
418
491
|
if (this._isDisposed) {
|
|
419
|
-
return;
|
|
492
|
+
return;
|
|
420
493
|
}
|
|
421
494
|
this._deviceContext.free();
|
|
422
495
|
this._isDisposed = true;
|
|
423
496
|
}
|
|
497
|
+
/**
|
|
498
|
+
* Get the hardware decoder pixel format for this device type.
|
|
499
|
+
*
|
|
500
|
+
* Maps device types to their corresponding pixel formats.
|
|
501
|
+
* Used internally for frame format configuration.
|
|
502
|
+
*
|
|
503
|
+
* @returns Hardware-specific pixel format
|
|
504
|
+
*/
|
|
505
|
+
getHardwareDecoderPixelFormat() {
|
|
506
|
+
switch (this._deviceType) {
|
|
507
|
+
case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
|
|
508
|
+
return AV_PIX_FMT_VIDEOTOOLBOX;
|
|
509
|
+
case AV_HWDEVICE_TYPE_VAAPI:
|
|
510
|
+
return AV_PIX_FMT_VAAPI;
|
|
511
|
+
case AV_HWDEVICE_TYPE_CUDA:
|
|
512
|
+
return AV_PIX_FMT_CUDA;
|
|
513
|
+
case AV_HWDEVICE_TYPE_QSV:
|
|
514
|
+
return AV_PIX_FMT_QSV;
|
|
515
|
+
case AV_HWDEVICE_TYPE_D3D11VA:
|
|
516
|
+
return AV_PIX_FMT_D3D11;
|
|
517
|
+
case AV_HWDEVICE_TYPE_DXVA2:
|
|
518
|
+
return AV_PIX_FMT_DXVA2_VLD;
|
|
519
|
+
case AV_HWDEVICE_TYPE_DRM:
|
|
520
|
+
return AV_PIX_FMT_DRM_PRIME;
|
|
521
|
+
case AV_HWDEVICE_TYPE_OPENCL:
|
|
522
|
+
return AV_PIX_FMT_OPENCL;
|
|
523
|
+
case AV_HWDEVICE_TYPE_MEDIACODEC:
|
|
524
|
+
return AV_PIX_FMT_MEDIACODEC;
|
|
525
|
+
case AV_HWDEVICE_TYPE_VULKAN:
|
|
526
|
+
return AV_PIX_FMT_VULKAN;
|
|
527
|
+
case AV_HWDEVICE_TYPE_D3D12VA:
|
|
528
|
+
return AV_PIX_FMT_D3D12;
|
|
529
|
+
case AV_HWDEVICE_TYPE_RKMPP:
|
|
530
|
+
return AV_PIX_FMT_DRM_PRIME; // RKMPP uses DRM Prime buffers
|
|
531
|
+
default:
|
|
532
|
+
return AV_PIX_FMT_NV12; // Common hardware format
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Test if a hardware encoder can be created.
|
|
537
|
+
*
|
|
538
|
+
* Attempts to initialize the encoder to verify support.
|
|
539
|
+
* Used internally by getEncoderCodec.
|
|
540
|
+
*
|
|
541
|
+
* @param encoderCodec - Encoder to test
|
|
542
|
+
* @returns true if encoder can be initialized
|
|
543
|
+
*/
|
|
544
|
+
async testHardwareEncoder(encoderCodec) {
|
|
545
|
+
let codec = null;
|
|
546
|
+
if (encoderCodec instanceof Codec) {
|
|
547
|
+
codec = encoderCodec;
|
|
548
|
+
}
|
|
549
|
+
else if (typeof encoderCodec === 'string') {
|
|
550
|
+
codec = Codec.findEncoderByName(encoderCodec);
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
codec = Codec.findEncoder(encoderCodec);
|
|
554
|
+
}
|
|
555
|
+
if (!codec?.pixelFormats || !codec.isHardwareAcceleratedEncoder()) {
|
|
556
|
+
return false;
|
|
557
|
+
}
|
|
558
|
+
const codecContext = new CodecContext();
|
|
559
|
+
codecContext.allocContext3(codec);
|
|
560
|
+
codecContext.hwDeviceCtx = this._deviceContext;
|
|
561
|
+
codecContext.timeBase = new Rational(1, 30);
|
|
562
|
+
codecContext.pixelFormat = codec.pixelFormats[0];
|
|
563
|
+
codecContext.width = 100;
|
|
564
|
+
codecContext.height = 100;
|
|
565
|
+
const ret = await codecContext.open2(codec);
|
|
566
|
+
codecContext.freeContext();
|
|
567
|
+
return ret >= 0;
|
|
568
|
+
}
|
|
424
569
|
/**
|
|
425
570
|
* Create hardware context from device type.
|
|
426
571
|
*
|
|
427
572
|
* Internal factory method using av_hwdevice_ctx_create().
|
|
428
573
|
*
|
|
429
574
|
* @param deviceType - AVHWDeviceType enum value
|
|
430
|
-
* @param
|
|
575
|
+
* @param device - Optional device specifier
|
|
431
576
|
* @param options - Optional device options
|
|
432
|
-
*
|
|
433
|
-
* @returns HardwareContext or null if creation fails
|
|
577
|
+
* @returns Hardware context or null if creation fails
|
|
434
578
|
*/
|
|
435
|
-
static
|
|
436
|
-
const
|
|
579
|
+
static createFromType(deviceType, device, options) {
|
|
580
|
+
const deviceCtx = new HardwareDeviceContext();
|
|
437
581
|
// Convert options to Dictionary if provided
|
|
438
582
|
let optionsDict = null;
|
|
439
583
|
if (options && Object.keys(options).length > 0) {
|
|
440
584
|
optionsDict = Dictionary.fromObject(options);
|
|
441
585
|
}
|
|
442
|
-
const ret =
|
|
586
|
+
const ret = deviceCtx.create(deviceType, device, optionsDict);
|
|
443
587
|
// Clean up dictionary if used
|
|
444
588
|
if (optionsDict) {
|
|
445
589
|
optionsDict.free();
|
|
446
590
|
}
|
|
447
|
-
|
|
448
|
-
|
|
591
|
+
const deviceTypeName = HardwareDeviceContext.getTypeName(deviceType);
|
|
592
|
+
if (ret < 0 || !deviceTypeName) {
|
|
593
|
+
deviceCtx.free();
|
|
449
594
|
return null;
|
|
450
595
|
}
|
|
451
|
-
return new HardwareContext(
|
|
596
|
+
return new HardwareContext(deviceCtx, deviceType, deviceTypeName);
|
|
452
597
|
}
|
|
453
598
|
/**
|
|
454
599
|
* Get platform-specific preference order for hardware types.
|
|
455
600
|
*
|
|
456
|
-
* Returns
|
|
601
|
+
* Returns available hardware types sorted by platform preference.
|
|
602
|
+
* Ensures optimal hardware selection for each platform.
|
|
457
603
|
*
|
|
458
604
|
* @returns Array of AVHWDeviceType values in preference order
|
|
459
605
|
*/
|
|
460
606
|
static getPreferenceOrder() {
|
|
607
|
+
// Get all available hardware types on this system
|
|
608
|
+
const available = HardwareDeviceContext.iterateTypes();
|
|
609
|
+
if (available.length === 0) {
|
|
610
|
+
return [];
|
|
611
|
+
}
|
|
461
612
|
const platform = process.platform;
|
|
613
|
+
let preferenceOrder;
|
|
462
614
|
if (platform === 'darwin') {
|
|
463
615
|
// macOS: VideoToolbox is preferred
|
|
464
|
-
|
|
616
|
+
preferenceOrder = [AV_HWDEVICE_TYPE_VIDEOTOOLBOX];
|
|
465
617
|
}
|
|
466
618
|
else if (platform === 'win32') {
|
|
467
|
-
// Windows:
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
AV_HWDEVICE_TYPE_D3D11VA,
|
|
619
|
+
// Windows: Match FFmpeg's hw_configs order
|
|
620
|
+
// DXVA2 → D3D11VA → D3D12VA → NVDEC (CUDA)
|
|
621
|
+
preferenceOrder = [
|
|
471
622
|
AV_HWDEVICE_TYPE_DXVA2,
|
|
472
|
-
|
|
623
|
+
AV_HWDEVICE_TYPE_D3D11VA,
|
|
624
|
+
AV_HWDEVICE_TYPE_D3D12VA,
|
|
473
625
|
AV_HWDEVICE_TYPE_CUDA,
|
|
626
|
+
AV_HWDEVICE_TYPE_QSV,
|
|
474
627
|
AV_HWDEVICE_TYPE_VULKAN,
|
|
475
628
|
AV_HWDEVICE_TYPE_OPENCL,
|
|
476
629
|
];
|
|
477
630
|
}
|
|
478
631
|
else {
|
|
479
|
-
// Linux:
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
AV_HWDEVICE_TYPE_VULKAN,
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
632
|
+
// Linux: Match FFmpeg's hw_configs order
|
|
633
|
+
// NVDEC (CUDA) → VAAPI → VDPAU → Vulkan
|
|
634
|
+
// RKMPP is platform-specific for ARM/Rockchip
|
|
635
|
+
const isARM = process.arch === 'arm64' || process.arch === 'arm';
|
|
636
|
+
if (isARM) {
|
|
637
|
+
// ARM platforms: Prioritize RKMPP for Rockchip SoCs
|
|
638
|
+
preferenceOrder = [AV_HWDEVICE_TYPE_RKMPP, AV_HWDEVICE_TYPE_VAAPI, AV_HWDEVICE_TYPE_VULKAN, AV_HWDEVICE_TYPE_DRM, AV_HWDEVICE_TYPE_OPENCL];
|
|
639
|
+
}
|
|
640
|
+
else {
|
|
641
|
+
// x86_64 Linux: CUDA → VAAPI → VDPAU → Vulkan
|
|
642
|
+
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];
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
// Filter preference order to only include available types
|
|
646
|
+
const availableSet = new Set(available);
|
|
647
|
+
const sortedAvailable = preferenceOrder.filter((type) => availableSet.has(type));
|
|
648
|
+
// Add any available types not in our preference list at the end
|
|
649
|
+
for (const type of available) {
|
|
650
|
+
if (!preferenceOrder.includes(type)) {
|
|
651
|
+
sortedAvailable.push(type);
|
|
652
|
+
}
|
|
489
653
|
}
|
|
654
|
+
return sortedAvailable;
|
|
490
655
|
}
|
|
491
656
|
/**
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
* Implements the Disposable interface for automatic cleanup.
|
|
657
|
+
* Dispose of hardware context.
|
|
495
658
|
*
|
|
496
|
-
*
|
|
659
|
+
* Implements Disposable interface for automatic cleanup.
|
|
660
|
+
* Equivalent to calling dispose().
|
|
497
661
|
*
|
|
498
662
|
* @example
|
|
499
663
|
* ```typescript
|
|
500
664
|
* {
|
|
501
|
-
* using hw =
|
|
665
|
+
* using hw = HardwareContext.auto();
|
|
502
666
|
* // Use hardware context...
|
|
503
667
|
* } // Automatically disposed
|
|
504
668
|
* ```
|
|
669
|
+
*
|
|
670
|
+
* @see {@link dispose} For manual cleanup
|
|
505
671
|
*/
|
|
506
672
|
[Symbol.dispose]() {
|
|
507
673
|
this.dispose();
|