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.
- package/README.md +51 -59
- package/dist/api/bitstream-filter.d.ts +183 -123
- package/dist/api/bitstream-filter.js +185 -127
- package/dist/api/bitstream-filter.js.map +1 -1
- package/dist/api/decoder.d.ts +282 -130
- package/dist/api/decoder.js +290 -142
- package/dist/api/decoder.js.map +1 -1
- package/dist/api/encoder.d.ts +249 -160
- package/dist/api/encoder.js +276 -207
- package/dist/api/encoder.js.map +1 -1
- package/dist/api/filter-presets.d.ts +1944 -96
- package/dist/api/filter-presets.js +2059 -105
- package/dist/api/filter-presets.js.map +1 -1
- package/dist/api/filter.d.ts +264 -200
- package/dist/api/filter.js +269 -231
- package/dist/api/filter.js.map +1 -1
- package/dist/api/hardware.d.ts +246 -117
- package/dist/api/hardware.js +440 -217
- 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 -55
- package/dist/api/io-stream.js +43 -40
- package/dist/api/io-stream.js.map +1 -1
- package/dist/api/media-input.d.ts +242 -139
- package/dist/api/media-input.js +205 -103
- package/dist/api/media-input.js.map +1 -1
- package/dist/api/media-output.d.ts +208 -126
- package/dist/api/media-output.js +212 -126
- package/dist/api/media-output.js.map +1 -1
- package/dist/api/pipeline.d.ts +361 -38
- package/dist/api/pipeline.js +255 -14
- package/dist/api/pipeline.js.map +1 -1
- package/dist/api/types.d.ts +26 -187
- package/dist/api/utilities/audio-sample.d.ts +0 -8
- package/dist/api/utilities/audio-sample.js +0 -8
- package/dist/api/utilities/audio-sample.js.map +1 -1
- package/dist/api/utilities/channel-layout.d.ts +0 -8
- package/dist/api/utilities/channel-layout.js +0 -8
- package/dist/api/utilities/channel-layout.js.map +1 -1
- package/dist/api/utilities/image.d.ts +0 -8
- package/dist/api/utilities/image.js +0 -8
- package/dist/api/utilities/image.js.map +1 -1
- package/dist/api/utilities/index.d.ts +3 -3
- package/dist/api/utilities/index.js +3 -3
- package/dist/api/utilities/index.js.map +1 -1
- package/dist/api/utilities/media-type.d.ts +1 -9
- package/dist/api/utilities/media-type.js +1 -9
- package/dist/api/utilities/media-type.js.map +1 -1
- package/dist/api/utilities/pixel-format.d.ts +1 -9
- package/dist/api/utilities/pixel-format.js +1 -9
- package/dist/api/utilities/pixel-format.js.map +1 -1
- package/dist/api/utilities/sample-format.d.ts +1 -9
- package/dist/api/utilities/sample-format.js +1 -9
- package/dist/api/utilities/sample-format.js.map +1 -1
- package/dist/api/utilities/streaming.d.ts +0 -8
- package/dist/api/utilities/streaming.js +0 -8
- package/dist/api/utilities/streaming.js.map +1 -1
- package/dist/api/utilities/timestamp.d.ts +0 -8
- package/dist/api/utilities/timestamp.js +0 -8
- package/dist/api/utilities/timestamp.js.map +1 -1
- package/dist/api/utils.d.ts +1 -2
- package/dist/api/utils.js +11 -0
- package/dist/api/utils.js.map +1 -1
- package/dist/constants/constants.d.ts +1 -1
- package/dist/constants/constants.js +2 -0
- package/dist/constants/constants.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.d.ts +1 -0
- package/dist/lib/binding.js +7 -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 +266 -283
- package/dist/lib/codec.js +270 -287
- 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 +3 -2
- package/dist/lib/index.js +3 -3
- 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 +118 -106
- package/dist/lib/native-types.js +0 -7
- package/dist/lib/native-types.js.map +1 -1
- package/dist/lib/option.d.ts +437 -218
- package/dist/lib/option.js +462 -226
- 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 +435 -181
- package/dist/lib/utilities.js +438 -182
- package/dist/lib/utilities.js.map +1 -1
- package/install/check.js +0 -1
- package/install/ffmpeg.js +0 -11
- package/package.json +25 -18
- package/release_notes.md +24 -59
- package/CHANGELOG.md +0 -8
package/dist/api/hardware.js
CHANGED
|
@@ -1,107 +1,108 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
-
*
|
|
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.
|
|
118
119
|
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
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
|
-
* @
|
|
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
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* ```typescript
|
|
272
|
+
* import { AV_CODEC_ID_H264 } from 'node-av/constants';
|
|
263
273
|
*
|
|
264
|
-
*
|
|
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';
|
|
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
|
-
* @
|
|
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
|
|
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
|
-
* @param
|
|
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
|
|
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(
|
|
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
|
|
335
|
-
|
|
336
|
-
|
|
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
|
|
341
|
-
case
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
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 (
|
|
403
|
+
if (codecBaseName === 'hevc') {
|
|
349
404
|
encoderSuffix = 'd3d12va';
|
|
350
405
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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 =
|
|
417
|
+
encoderSuffix = this._deviceTypeName;
|
|
418
|
+
}
|
|
419
|
+
if (!encoderSuffix) {
|
|
420
|
+
return null;
|
|
360
421
|
}
|
|
361
422
|
// Construct the encoder name
|
|
362
|
-
const encoderName = `${
|
|
363
|
-
const
|
|
364
|
-
if (
|
|
365
|
-
return
|
|
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
|
|
428
|
+
return encoderCodec;
|
|
368
429
|
}
|
|
369
430
|
/**
|
|
370
431
|
* Find all codecs that support this hardware device.
|
|
371
432
|
*
|
|
372
|
-
*
|
|
433
|
+
* Iterates through all available codecs and checks hardware compatibility.
|
|
434
|
+
* Useful for discovering available hardware acceleration options.
|
|
373
435
|
*
|
|
374
|
-
*
|
|
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
|
-
*
|
|
412
|
-
*
|
|
484
|
+
* Releases the hardware device context.
|
|
485
|
+
* Safe to call multiple times.
|
|
486
|
+
* Automatically called by Symbol.dispose.
|
|
413
487
|
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
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;
|
|
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
|
|
627
|
+
* @param device - Optional device specifier
|
|
431
628
|
* @param options - Optional device options
|
|
432
629
|
*
|
|
433
|
-
* @returns
|
|
630
|
+
* @returns Hardware context or null if creation fails
|
|
631
|
+
*
|
|
632
|
+
* @internal
|
|
434
633
|
*/
|
|
435
|
-
static
|
|
436
|
-
const
|
|
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 =
|
|
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
|
-
|
|
448
|
-
|
|
646
|
+
const deviceTypeName = HardwareDeviceContext.getTypeName(deviceType);
|
|
647
|
+
if (ret < 0 || !deviceTypeName) {
|
|
648
|
+
deviceCtx.free();
|
|
449
649
|
return null;
|
|
450
650
|
}
|
|
451
|
-
return new HardwareContext(
|
|
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
|
|
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
|
-
|
|
673
|
+
preferenceOrder = [AV_HWDEVICE_TYPE_VIDEOTOOLBOX];
|
|
465
674
|
}
|
|
466
675
|
else if (platform === 'win32') {
|
|
467
|
-
// Windows:
|
|
468
|
-
|
|
469
|
-
|
|
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
|
-
|
|
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:
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
AV_HWDEVICE_TYPE_VULKAN,
|
|
486
|
-
|
|
487
|
-
|
|
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
|
-
*
|
|
493
|
-
*
|
|
494
|
-
* Implements the Disposable interface for automatic cleanup.
|
|
714
|
+
* Dispose of hardware context.
|
|
495
715
|
*
|
|
496
|
-
*
|
|
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 =
|
|
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();
|