webcodecs-node 0.2.2 → 0.5.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 (246) hide show
  1. package/README.md +4 -0
  2. package/dist/__tests__/AudioData.test.js +2 -1
  3. package/dist/__tests__/AudioData.test.js.map +1 -1
  4. package/dist/__tests__/AudioDecoder.test.js +8 -8
  5. package/dist/__tests__/AudioDecoder.test.js.map +1 -1
  6. package/dist/__tests__/AudioEncoder.test.js +3 -3
  7. package/dist/__tests__/AudioEncoder.test.js.map +1 -1
  8. package/dist/__tests__/EncodedChunks.test.js +3 -2
  9. package/dist/__tests__/EncodedChunks.test.js.map +1 -1
  10. package/dist/__tests__/HardwareAcceleration.test.js +2 -1
  11. package/dist/__tests__/HardwareAcceleration.test.js.map +1 -1
  12. package/dist/__tests__/ImageDecoder.test.js +16 -45
  13. package/dist/__tests__/ImageDecoder.test.js.map +1 -1
  14. package/dist/__tests__/ImageDecoder.wpt.test.d.ts +8 -0
  15. package/dist/__tests__/ImageDecoder.wpt.test.d.ts.map +1 -0
  16. package/dist/__tests__/ImageDecoder.wpt.test.js +135 -0
  17. package/dist/__tests__/ImageDecoder.wpt.test.js.map +1 -0
  18. package/dist/__tests__/NodeAvDecoder.test.d.ts +2 -0
  19. package/dist/__tests__/NodeAvDecoder.test.d.ts.map +1 -0
  20. package/dist/__tests__/NodeAvDecoder.test.js +206 -0
  21. package/dist/__tests__/NodeAvDecoder.test.js.map +1 -0
  22. package/dist/__tests__/NodeAvEncoder.test.d.ts +2 -0
  23. package/dist/__tests__/NodeAvEncoder.test.d.ts.map +1 -0
  24. package/dist/__tests__/NodeAvEncoder.test.js +176 -0
  25. package/dist/__tests__/NodeAvEncoder.test.js.map +1 -0
  26. package/dist/__tests__/VideoDecoder.test.js +5 -5
  27. package/dist/__tests__/VideoDecoder.test.js.map +1 -1
  28. package/dist/__tests__/VideoEncoder.test.js +3 -3
  29. package/dist/__tests__/VideoEncoder.test.js.map +1 -1
  30. package/dist/__tests__/VideoFrame.test.js +4 -1
  31. package/dist/__tests__/VideoFrame.test.js.map +1 -1
  32. package/dist/backends/index.d.ts +3 -0
  33. package/dist/backends/index.d.ts.map +1 -0
  34. package/dist/backends/index.js +2 -0
  35. package/dist/backends/index.js.map +1 -0
  36. package/dist/backends/types.d.ts +168 -0
  37. package/dist/backends/types.d.ts.map +1 -0
  38. package/dist/backends/types.js +25 -0
  39. package/dist/backends/types.js.map +1 -0
  40. package/dist/codec-utils/audio-codecs.d.ts +60 -0
  41. package/dist/codec-utils/audio-codecs.d.ts.map +1 -0
  42. package/dist/codec-utils/audio-codecs.js +117 -0
  43. package/dist/codec-utils/audio-codecs.js.map +1 -0
  44. package/dist/codec-utils/formats.d.ts +42 -0
  45. package/dist/codec-utils/formats.d.ts.map +1 -0
  46. package/dist/codec-utils/formats.js +147 -0
  47. package/dist/codec-utils/formats.js.map +1 -0
  48. package/dist/codec-utils/index.d.ts +9 -0
  49. package/dist/codec-utils/index.d.ts.map +1 -0
  50. package/dist/codec-utils/index.js +12 -0
  51. package/dist/codec-utils/index.js.map +1 -0
  52. package/dist/codec-utils/types.d.ts +87 -0
  53. package/dist/codec-utils/types.d.ts.map +1 -0
  54. package/dist/codec-utils/types.js +10 -0
  55. package/dist/codec-utils/types.js.map +1 -0
  56. package/dist/containers/Demuxer.d.ts +114 -0
  57. package/dist/containers/Demuxer.d.ts.map +1 -0
  58. package/dist/containers/Demuxer.js +256 -0
  59. package/dist/containers/Demuxer.js.map +1 -0
  60. package/dist/containers/Muxer.d.ts +142 -0
  61. package/dist/containers/Muxer.d.ts.map +1 -0
  62. package/dist/containers/Muxer.js +295 -0
  63. package/dist/containers/Muxer.js.map +1 -0
  64. package/dist/containers/extract.d.ts +25 -0
  65. package/dist/containers/extract.d.ts.map +1 -0
  66. package/dist/containers/extract.js +64 -0
  67. package/dist/containers/extract.js.map +1 -0
  68. package/dist/containers/index.d.ts +40 -0
  69. package/dist/containers/index.d.ts.map +1 -0
  70. package/dist/containers/index.js +41 -0
  71. package/dist/containers/index.js.map +1 -0
  72. package/dist/containers/transcode.d.ts +138 -0
  73. package/dist/containers/transcode.d.ts.map +1 -0
  74. package/dist/containers/transcode.js +536 -0
  75. package/dist/containers/transcode.js.map +1 -0
  76. package/dist/core/AudioData.d.ts +5 -1
  77. package/dist/core/AudioData.d.ts.map +1 -1
  78. package/dist/core/AudioData.js +69 -13
  79. package/dist/core/AudioData.js.map +1 -1
  80. package/dist/core/EncodedAudioChunk.d.ts +1 -1
  81. package/dist/core/EncodedAudioChunk.d.ts.map +1 -1
  82. package/dist/core/EncodedAudioChunk.js +1 -1
  83. package/dist/core/EncodedAudioChunk.js.map +1 -1
  84. package/dist/core/EncodedVideoChunk.d.ts.map +1 -1
  85. package/dist/core/EncodedVideoChunk.js +3 -19
  86. package/dist/core/EncodedVideoChunk.js.map +1 -1
  87. package/dist/core/VideoFrame.d.ts +31 -11
  88. package/dist/core/VideoFrame.d.ts.map +1 -1
  89. package/dist/core/VideoFrame.js +244 -81
  90. package/dist/core/VideoFrame.js.map +1 -1
  91. package/dist/decoders/AudioDecoder.d.ts +14 -12
  92. package/dist/decoders/AudioDecoder.d.ts.map +1 -1
  93. package/dist/decoders/AudioDecoder.js +113 -173
  94. package/dist/decoders/AudioDecoder.js.map +1 -1
  95. package/dist/decoders/ImageDecoder.d.ts +1 -3
  96. package/dist/decoders/ImageDecoder.d.ts.map +1 -1
  97. package/dist/decoders/ImageDecoder.js +39 -192
  98. package/dist/decoders/ImageDecoder.js.map +1 -1
  99. package/dist/decoders/VideoDecoder.d.ts +14 -13
  100. package/dist/decoders/VideoDecoder.d.ts.map +1 -1
  101. package/dist/decoders/VideoDecoder.js +115 -166
  102. package/dist/decoders/VideoDecoder.js.map +1 -1
  103. package/dist/demos/demo-1080p-transcode.d.ts +8 -0
  104. package/dist/demos/demo-1080p-transcode.d.ts.map +1 -0
  105. package/dist/demos/demo-1080p-transcode.js +188 -0
  106. package/dist/demos/demo-1080p-transcode.js.map +1 -0
  107. package/dist/demos/demo-containers.d.ts +7 -0
  108. package/dist/demos/demo-containers.d.ts.map +1 -0
  109. package/dist/demos/demo-containers.js +140 -0
  110. package/dist/demos/demo-containers.js.map +1 -0
  111. package/dist/demos/demo-conversion.js +2 -2
  112. package/dist/demos/demo-conversion.js.map +1 -1
  113. package/dist/demos/demo-four-corners.d.ts +6 -0
  114. package/dist/demos/demo-four-corners.d.ts.map +1 -0
  115. package/dist/demos/demo-four-corners.js +218 -0
  116. package/dist/demos/demo-four-corners.js.map +1 -0
  117. package/dist/demos/demo-hwaccel-conversion.js +1 -1
  118. package/dist/demos/demo-hwaccel-conversion.js.map +1 -1
  119. package/dist/demos/demo-hwaccel.js +1 -1
  120. package/dist/demos/demo-hwaccel.js.map +1 -1
  121. package/dist/demos/demo-samples.js +232 -68
  122. package/dist/demos/demo-samples.js.map +1 -1
  123. package/dist/demos/demo-streaming.js +6 -6
  124. package/dist/demos/demo-streaming.js.map +1 -1
  125. package/dist/encoders/AudioEncoder.d.ts +14 -13
  126. package/dist/encoders/AudioEncoder.d.ts.map +1 -1
  127. package/dist/encoders/AudioEncoder.js +138 -228
  128. package/dist/encoders/AudioEncoder.js.map +1 -1
  129. package/dist/encoders/VideoEncoder.d.ts +13 -14
  130. package/dist/encoders/VideoEncoder.d.ts.map +1 -1
  131. package/dist/encoders/VideoEncoder.js +92 -161
  132. package/dist/encoders/VideoEncoder.js.map +1 -1
  133. package/dist/ffmpeg/index.d.ts +3 -2
  134. package/dist/ffmpeg/index.d.ts.map +1 -1
  135. package/dist/ffmpeg/index.js +3 -3
  136. package/dist/ffmpeg/index.js.map +1 -1
  137. package/dist/formats/conversions/batch-converter.d.ts +61 -0
  138. package/dist/formats/conversions/batch-converter.d.ts.map +1 -0
  139. package/dist/formats/conversions/batch-converter.js +274 -0
  140. package/dist/formats/conversions/batch-converter.js.map +1 -0
  141. package/dist/formats/conversions/frame-converter.d.ts +17 -0
  142. package/dist/formats/conversions/frame-converter.d.ts.map +1 -1
  143. package/dist/formats/conversions/frame-converter.js +144 -10
  144. package/dist/formats/conversions/frame-converter.js.map +1 -1
  145. package/dist/formats/conversions/index.d.ts +2 -0
  146. package/dist/formats/conversions/index.d.ts.map +1 -1
  147. package/dist/formats/conversions/index.js +4 -0
  148. package/dist/formats/conversions/index.js.map +1 -1
  149. package/dist/hardware/decoder-args.d.ts +2 -7
  150. package/dist/hardware/decoder-args.d.ts.map +1 -1
  151. package/dist/hardware/decoder-args.js +2 -32
  152. package/dist/hardware/decoder-args.js.map +1 -1
  153. package/dist/hardware/detection.d.ts +1 -1
  154. package/dist/hardware/detection.d.ts.map +1 -1
  155. package/dist/hardware/detection.js +54 -27
  156. package/dist/hardware/detection.js.map +1 -1
  157. package/dist/hardware/encoder-args.d.ts +2 -11
  158. package/dist/hardware/encoder-args.d.ts.map +1 -1
  159. package/dist/hardware/encoder-args.js +2 -71
  160. package/dist/hardware/encoder-args.js.map +1 -1
  161. package/dist/hardware/index.d.ts +2 -2
  162. package/dist/hardware/index.d.ts.map +1 -1
  163. package/dist/hardware/index.js +2 -2
  164. package/dist/hardware/index.js.map +1 -1
  165. package/dist/index.d.ts +5 -7
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.js +5 -6
  168. package/dist/index.js.map +1 -1
  169. package/dist/mediabunny/FFmpegAudioDecoder.d.ts +4 -17
  170. package/dist/mediabunny/FFmpegAudioDecoder.d.ts.map +1 -1
  171. package/dist/mediabunny/FFmpegAudioDecoder.js +57 -185
  172. package/dist/mediabunny/FFmpegAudioDecoder.js.map +1 -1
  173. package/dist/mediabunny/FFmpegAudioEncoder.d.ts +6 -39
  174. package/dist/mediabunny/FFmpegAudioEncoder.d.ts.map +1 -1
  175. package/dist/mediabunny/FFmpegAudioEncoder.js +66 -329
  176. package/dist/mediabunny/FFmpegAudioEncoder.js.map +1 -1
  177. package/dist/mediabunny/FFmpegVideoDecoder.d.ts +5 -38
  178. package/dist/mediabunny/FFmpegVideoDecoder.d.ts.map +1 -1
  179. package/dist/mediabunny/FFmpegVideoDecoder.js +39 -283
  180. package/dist/mediabunny/FFmpegVideoDecoder.js.map +1 -1
  181. package/dist/mediabunny/FFmpegVideoEncoder.d.ts +9 -37
  182. package/dist/mediabunny/FFmpegVideoEncoder.d.ts.map +1 -1
  183. package/dist/mediabunny/FFmpegVideoEncoder.js +49 -336
  184. package/dist/mediabunny/FFmpegVideoEncoder.js.map +1 -1
  185. package/dist/node-av/HardwarePipeline.d.ts +36 -0
  186. package/dist/node-av/HardwarePipeline.d.ts.map +1 -0
  187. package/dist/node-av/HardwarePipeline.js +243 -0
  188. package/dist/node-av/HardwarePipeline.js.map +1 -0
  189. package/dist/node-av/NodeAvAudioDecoder.d.ts +46 -0
  190. package/dist/node-av/NodeAvAudioDecoder.d.ts.map +1 -0
  191. package/dist/node-av/NodeAvAudioDecoder.js +350 -0
  192. package/dist/node-av/NodeAvAudioDecoder.js.map +1 -0
  193. package/dist/node-av/NodeAvAudioEncoder.d.ts +50 -0
  194. package/dist/node-av/NodeAvAudioEncoder.d.ts.map +1 -0
  195. package/dist/node-av/NodeAvAudioEncoder.js +506 -0
  196. package/dist/node-av/NodeAvAudioEncoder.js.map +1 -0
  197. package/dist/node-av/NodeAvImageDecoder.d.ts +114 -0
  198. package/dist/node-av/NodeAvImageDecoder.d.ts.map +1 -0
  199. package/dist/node-av/NodeAvImageDecoder.js +406 -0
  200. package/dist/node-av/NodeAvImageDecoder.js.map +1 -0
  201. package/dist/node-av/NodeAvVideoDecoder.d.ts +43 -0
  202. package/dist/node-av/NodeAvVideoDecoder.d.ts.map +1 -0
  203. package/dist/node-av/NodeAvVideoDecoder.js +365 -0
  204. package/dist/node-av/NodeAvVideoDecoder.js.map +1 -0
  205. package/dist/node-av/NodeAvVideoEncoder.d.ts +56 -0
  206. package/dist/node-av/NodeAvVideoEncoder.d.ts.map +1 -0
  207. package/dist/node-av/NodeAvVideoEncoder.js +509 -0
  208. package/dist/node-av/NodeAvVideoEncoder.js.map +1 -0
  209. package/dist/polyfill.d.ts.map +1 -1
  210. package/dist/polyfill.js +11 -9
  211. package/dist/polyfill.js.map +1 -1
  212. package/dist/utils/aac.d.ts.map +1 -1
  213. package/dist/utils/aac.js +6 -0
  214. package/dist/utils/aac.js.map +1 -1
  215. package/dist/utils/buffer-pool.d.ts +109 -0
  216. package/dist/utils/buffer-pool.d.ts.map +1 -0
  217. package/dist/utils/buffer-pool.js +278 -0
  218. package/dist/utils/buffer-pool.js.map +1 -0
  219. package/dist/utils/codec-cache.d.ts +65 -0
  220. package/dist/utils/codec-cache.d.ts.map +1 -0
  221. package/dist/utils/codec-cache.js +116 -0
  222. package/dist/utils/codec-cache.js.map +1 -0
  223. package/dist/utils/errors.d.ts +62 -0
  224. package/dist/utils/errors.d.ts.map +1 -0
  225. package/dist/utils/errors.js +84 -0
  226. package/dist/utils/errors.js.map +1 -0
  227. package/dist/utils/event-target.d.ts +42 -0
  228. package/dist/utils/event-target.d.ts.map +1 -0
  229. package/dist/utils/event-target.js +96 -0
  230. package/dist/utils/event-target.js.map +1 -0
  231. package/dist/utils/hardware-pool.d.ts +88 -0
  232. package/dist/utils/hardware-pool.d.ts.map +1 -0
  233. package/dist/utils/hardware-pool.js +266 -0
  234. package/dist/utils/hardware-pool.js.map +1 -0
  235. package/dist/utils/index.d.ts +6 -0
  236. package/dist/utils/index.d.ts.map +1 -1
  237. package/dist/utils/index.js +12 -0
  238. package/dist/utils/index.js.map +1 -1
  239. package/dist/utils/timeout.d.ts +44 -0
  240. package/dist/utils/timeout.d.ts.map +1 -0
  241. package/dist/utils/timeout.js +73 -0
  242. package/dist/utils/timeout.js.map +1 -0
  243. package/dist/utils/type-guards.d.ts +11 -1
  244. package/dist/utils/type-guards.d.ts.map +1 -1
  245. package/dist/utils/type-guards.js.map +1 -1
  246. package/package.json +20 -34
@@ -0,0 +1,243 @@
1
+ /**
2
+ * HardwarePipeline - Intelligent filter chain selection for hardware video processing
3
+ *
4
+ * Automatically detects hardware capabilities and builds optimal filter chains
5
+ * for format conversion, preferring GPU-side operations when possible.
6
+ */
7
+ import { FilterAPI } from 'node-av/api';
8
+ import { createLogger } from '../utils/logger.js';
9
+ const logger = createLogger('HardwarePipeline');
10
+ /**
11
+ * Known capabilities for each hardware type
12
+ * These are the theoretical capabilities - actual support depends on driver version
13
+ */
14
+ const HARDWARE_CAPABILITIES = {
15
+ cuda: {
16
+ scaleFilter: 'scale_cuda',
17
+ gpuOutputFormats: ['nv12', 'yuv420p', 'p010le', 'yuv444p', 'bgra', 'rgba'],
18
+ supportsRgbOutput: true,
19
+ },
20
+ vaapi: {
21
+ scaleFilter: 'scale_vaapi',
22
+ gpuOutputFormats: ['nv12', 'p010'],
23
+ supportsRgbOutput: false,
24
+ },
25
+ qsv: {
26
+ scaleFilter: 'vpp_qsv', // vpp_qsv is more capable than scale_qsv
27
+ gpuOutputFormats: ['nv12', 'p010', 'bgra'], // bgra on some drivers
28
+ supportsRgbOutput: false, // Conservative - driver dependent
29
+ },
30
+ videotoolbox: {
31
+ scaleFilter: 'scale_vt',
32
+ gpuOutputFormats: ['nv12', 'p010', 'bgra'],
33
+ supportsRgbOutput: true,
34
+ },
35
+ drm: {
36
+ scaleFilter: '', // No GPU scale filter for DRM
37
+ gpuOutputFormats: ['nv12'],
38
+ supportsRgbOutput: false,
39
+ },
40
+ v4l2m2m: {
41
+ scaleFilter: '', // No GPU scale filter for V4L2
42
+ gpuOutputFormats: ['nv12', 'yuv420p'],
43
+ supportsRgbOutput: false,
44
+ },
45
+ software: {
46
+ scaleFilter: '',
47
+ gpuOutputFormats: [],
48
+ supportsRgbOutput: false,
49
+ },
50
+ };
51
+ /**
52
+ * Cache for probed filter chains
53
+ * Maps: hardwareType -> outputFormat -> working filter chain (or null if none work)
54
+ */
55
+ const filterChainCache = new Map();
56
+ /**
57
+ * Test if a filter chain works by trying to create it
58
+ * Note: This only tests creation, not actual processing. Some filters may create
59
+ * successfully but fail during processing (e.g., vpp_qsv with missing MFX loader).
60
+ */
61
+ function probeFilterChain(filterDescription, hardware) {
62
+ try {
63
+ const filter = FilterAPI.create(filterDescription, {
64
+ hardware: hardware ?? undefined,
65
+ });
66
+ filter.close();
67
+ return true;
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ }
73
+ /**
74
+ * Mark a filter chain as failed (discovered during actual processing)
75
+ */
76
+ export function markFilterChainFailed(hwType, outputFormat, isHardwareFrame) {
77
+ const cacheKey = isHardwareFrame ? outputFormat : `sw_${outputFormat}`;
78
+ let hwCache = filterChainCache.get(hwType);
79
+ if (!hwCache) {
80
+ hwCache = new Map();
81
+ filterChainCache.set(hwType, hwCache);
82
+ }
83
+ // Mark current chain as failed by setting to null
84
+ hwCache.set(cacheKey, null);
85
+ // Also mark it in failed chains set
86
+ failedFilterChains.add(`${hwType}:${cacheKey}`);
87
+ }
88
+ /**
89
+ * Set of filter chains that failed during actual processing
90
+ */
91
+ const failedFilterChains = new Set();
92
+ /**
93
+ * Check if a specific chain has been marked as failed
94
+ */
95
+ function isChainFailed(hwType, outputFormat, isHardwareFrame) {
96
+ const cacheKey = isHardwareFrame ? outputFormat : `sw_${outputFormat}`;
97
+ return failedFilterChains.has(`${hwType}:${cacheKey}`);
98
+ }
99
+ /**
100
+ * Get cached filter chain or null if not cached
101
+ */
102
+ function getCachedFilterChain(hwType, outputFormat) {
103
+ const hwCache = filterChainCache.get(hwType);
104
+ if (!hwCache)
105
+ return undefined;
106
+ return hwCache.get(outputFormat);
107
+ }
108
+ /**
109
+ * Cache a filter chain result
110
+ */
111
+ function cacheFilterChain(hwType, outputFormat, chain) {
112
+ let hwCache = filterChainCache.get(hwType);
113
+ if (!hwCache) {
114
+ hwCache = new Map();
115
+ filterChainCache.set(hwType, hwCache);
116
+ }
117
+ hwCache.set(outputFormat, chain);
118
+ }
119
+ /**
120
+ * Build candidate filter chains in order of preference (best first)
121
+ */
122
+ function buildCandidateChains(hwType, outputFormat, isHardwareFrame) {
123
+ const candidates = [];
124
+ const caps = HARDWARE_CAPABILITIES[hwType];
125
+ if (!isHardwareFrame) {
126
+ // Software frame - just format conversion
127
+ candidates.push(`format=${outputFormat}`);
128
+ return candidates;
129
+ }
130
+ // Hardware frame - try various strategies
131
+ // Strategy 1: GPU-side conversion if supported (best - no CPU conversion)
132
+ if (caps.scaleFilter && caps.gpuOutputFormats.includes(outputFormat)) {
133
+ // Full GPU: scale on GPU to target format, then download
134
+ candidates.push(`${caps.scaleFilter}=format=${outputFormat},hwdownload,format=${outputFormat}`);
135
+ }
136
+ // Strategy 2: GPU conversion to intermediate, then CPU conversion
137
+ // Try bgra/nv12 as intermediates since they're widely supported
138
+ if (caps.scaleFilter) {
139
+ for (const intermediate of ['bgra', 'nv12']) {
140
+ if (caps.gpuOutputFormats.includes(intermediate) && intermediate !== outputFormat) {
141
+ candidates.push(`${caps.scaleFilter}=format=${intermediate},hwdownload,format=${intermediate},format=${outputFormat}`);
142
+ }
143
+ }
144
+ }
145
+ // Strategy 3: Simple hwdownload then CPU conversion (most compatible)
146
+ candidates.push(`hwdownload,format=nv12,format=${outputFormat}`);
147
+ // Strategy 4: hwdownload with auto format detection
148
+ candidates.push(`hwdownload,format=${outputFormat}`);
149
+ return candidates;
150
+ }
151
+ /**
152
+ * Track which chain index we're on for each hw/format combo (for fallback iteration)
153
+ */
154
+ const chainIndexMap = new Map();
155
+ /**
156
+ * Select the best filter chain for the given hardware and output format.
157
+ * Uses probing to verify the chain works on this specific hardware/driver.
158
+ * If a chain fails during actual processing, call getNextFilterChain() to try the next one.
159
+ */
160
+ export function selectBestFilterChain(hardware, outputFormat, isHardwareFrame) {
161
+ const hwType = hardware?.deviceTypeName ?? 'software';
162
+ const cacheKey = `${hwType}:${isHardwareFrame ? outputFormat : `sw_${outputFormat}`}`;
163
+ // Build candidates in preference order
164
+ const candidates = buildCandidateChains(hwType, outputFormat, isHardwareFrame);
165
+ // Get current index (which chain we're trying)
166
+ const currentIndex = chainIndexMap.get(cacheKey) ?? 0;
167
+ // If we've exhausted all candidates, use the most compatible fallback
168
+ if (currentIndex >= candidates.length) {
169
+ const fallback = `hwdownload,format=nv12,format=${outputFormat}`;
170
+ logger.debug(`All chains exhausted for ${hwType}/${outputFormat}, using final fallback`);
171
+ return fallback;
172
+ }
173
+ const chain = candidates[currentIndex];
174
+ logger.debug(`Trying chain ${currentIndex + 1}/${candidates.length} for ${hwType}/${outputFormat}: ${chain}`);
175
+ return chain;
176
+ }
177
+ /**
178
+ * Move to the next filter chain after the current one failed.
179
+ * Returns the next chain to try, or null if all chains have been exhausted.
180
+ */
181
+ export function getNextFilterChain(hardware, outputFormat, isHardwareFrame) {
182
+ const hwType = hardware?.deviceTypeName ?? 'software';
183
+ const cacheKey = `${hwType}:${isHardwareFrame ? outputFormat : `sw_${outputFormat}`}`;
184
+ // Increment the chain index
185
+ const currentIndex = (chainIndexMap.get(cacheKey) ?? 0) + 1;
186
+ chainIndexMap.set(cacheKey, currentIndex);
187
+ // Build candidates
188
+ const candidates = buildCandidateChains(hwType, outputFormat, isHardwareFrame);
189
+ if (currentIndex >= candidates.length) {
190
+ logger.debug(`All ${candidates.length} chains failed for ${hwType}/${outputFormat}`);
191
+ return null;
192
+ }
193
+ const chain = candidates[currentIndex];
194
+ logger.debug(`Falling back to chain ${currentIndex + 1}/${candidates.length}: ${chain}`);
195
+ return chain;
196
+ }
197
+ /**
198
+ * Get human-readable description of the selected pipeline
199
+ */
200
+ export function describePipeline(filterChain, hwType) {
201
+ const parts = [];
202
+ if (filterChain.includes('scale_cuda')) {
203
+ parts.push('CUDA GPU scaling');
204
+ }
205
+ else if (filterChain.includes('scale_vaapi')) {
206
+ parts.push('VAAPI GPU scaling');
207
+ }
208
+ else if (filterChain.includes('vpp_qsv')) {
209
+ parts.push('QSV GPU processing');
210
+ }
211
+ else if (filterChain.includes('scale_vt')) {
212
+ parts.push('VideoToolbox GPU scaling');
213
+ }
214
+ if (filterChain.includes('hwdownload')) {
215
+ parts.push('GPU→CPU transfer');
216
+ }
217
+ const formatMatches = filterChain.match(/format=(\w+)/g);
218
+ if (formatMatches && formatMatches.length > 0) {
219
+ const lastFormat = formatMatches[formatMatches.length - 1].replace('format=', '');
220
+ parts.push(`output: ${lastFormat}`);
221
+ }
222
+ return parts.join(' → ') || filterChain;
223
+ }
224
+ /**
225
+ * Clear the filter chain cache (useful for testing or after hardware changes)
226
+ */
227
+ export function clearPipelineCache() {
228
+ filterChainCache.clear();
229
+ }
230
+ /**
231
+ * Get current cache status for debugging
232
+ */
233
+ export function getPipelineCacheStatus() {
234
+ const result = {};
235
+ for (const [hwType, formats] of filterChainCache) {
236
+ result[hwType] = {};
237
+ for (const [format, chain] of formats) {
238
+ result[hwType][format] = chain;
239
+ }
240
+ }
241
+ return result;
242
+ }
243
+ //# sourceMappingURL=HardwarePipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HardwarePipeline.js","sourceRoot":"","sources":["../../src/node-av/HardwarePipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * NodeAvAudioDecoder - Audio decoder using node-av native bindings
3
+ *
4
+ * Implements the AudioDecoderBackend interface for decoding audio streams
5
+ * using FFmpeg's libav* libraries via node-av.
6
+ */
7
+ import { EventEmitter } from 'events';
8
+ import type { AudioDecoderBackend, AudioDecoderBackendConfig } from '../backends/types.js';
9
+ /**
10
+ * NodeAV-backed audio decoder implementing AudioDecoderBackend interface
11
+ */
12
+ export declare class NodeAvAudioDecoder extends EventEmitter implements AudioDecoderBackend {
13
+ private decoder;
14
+ private formatContext;
15
+ private stream;
16
+ private filter;
17
+ private config;
18
+ private queue;
19
+ private processing;
20
+ private processingPromise;
21
+ private shuttingDown;
22
+ private packetIndex;
23
+ private frameIndex;
24
+ private packetTimeBase;
25
+ private outputSampleFormat;
26
+ private filterDescription;
27
+ private outputFormat;
28
+ get isHealthy(): boolean;
29
+ startDecoder(config: AudioDecoderBackendConfig): void;
30
+ write(data: Buffer | Uint8Array): boolean;
31
+ end(): void;
32
+ kill(): void;
33
+ shutdown(): Promise<void>;
34
+ private processQueue;
35
+ private ensureDecoder;
36
+ private parseOutputFormat;
37
+ private decodeBuffer;
38
+ private drainFrames;
39
+ private canPassThrough;
40
+ private toOutputBuffer;
41
+ private convertPlanarToInterleaved;
42
+ private getChannelLayout;
43
+ private finish;
44
+ private cleanup;
45
+ }
46
+ //# sourceMappingURL=NodeAvAudioDecoder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NodeAvAudioDecoder.d.ts","sourceRoot":"","sources":["../../src/node-av/NodeAvAudioDecoder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAmCtC,OAAO,KAAK,EACV,mBAAmB,EACnB,yBAAyB,EAE1B,MAAM,sBAAsB,CAAC;AAU9B;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,YAAa,YAAW,mBAAmB;IACjF,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,cAAc,CAAkD;IACxE,OAAO,CAAC,kBAAkB,CAAqC;IAC/D,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,YAAY,CAA4B;IAEhD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,YAAY,CAAC,MAAM,EAAE,yBAAyB,GAAG,IAAI;IAOrD,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO;IAWzC,GAAG,IAAI,IAAI;IAMX,IAAI,IAAI,IAAI;IAMN,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YAIjB,YAAY;YAyBZ,aAAa;IAmC3B,OAAO,CAAC,iBAAiB;YAKX,YAAY;YAqBZ,WAAW;IAkCzB,OAAO,CAAC,cAAc;YAIR,cAAc;IAyC5B,OAAO,CAAC,0BAA0B;IAyBlC,OAAO,CAAC,gBAAgB;YAiBV,MAAM;IAmBpB,OAAO,CAAC,OAAO;CAShB"}
@@ -0,0 +1,350 @@
1
+ /**
2
+ * NodeAvAudioDecoder - Audio decoder using node-av native bindings
3
+ *
4
+ * Implements the AudioDecoderBackend interface for decoding audio streams
5
+ * using FFmpeg's libav* libraries via node-av.
6
+ */
7
+ import { EventEmitter } from 'events';
8
+ import { Decoder, FilterAPI } from 'node-av/api';
9
+ import { FormatContext, Packet, Rational } from 'node-av/lib';
10
+ import { AVMEDIA_TYPE_AUDIO, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8P, AV_CODEC_ID_AAC, AV_CODEC_ID_OPUS, AV_CODEC_ID_MP3, AV_CODEC_ID_FLAC, AV_CODEC_ID_VORBIS, AV_CODEC_ID_PCM_S16LE, AV_CODEC_ID_PCM_S24LE, AV_CODEC_ID_PCM_S32LE, AV_CODEC_ID_PCM_F32LE, AV_CODEC_ID_PCM_U8, AV_CODEC_ID_PCM_MULAW, AV_CODEC_ID_PCM_ALAW, AV_CHANNEL_ORDER_NATIVE, AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT1, AV_CH_LAYOUT_7POINT1, } from 'node-av/constants';
11
+ import { createLogger } from '../utils/logger.js';
12
+ import { toUint8Array } from '../utils/buffer.js';
13
+ const logger = createLogger('NodeAvAudioDecoder');
14
+ /** Default sample rate for audio decoding */
15
+ const DEFAULT_SAMPLE_RATE = 48000;
16
+ /**
17
+ * NodeAV-backed audio decoder implementing AudioDecoderBackend interface
18
+ */
19
+ export class NodeAvAudioDecoder extends EventEmitter {
20
+ decoder = null;
21
+ formatContext = null;
22
+ stream = null;
23
+ filter = null;
24
+ config = null;
25
+ queue = [];
26
+ processing = false;
27
+ processingPromise = null;
28
+ shuttingDown = false;
29
+ packetIndex = 0;
30
+ frameIndex = 0;
31
+ packetTimeBase = new Rational(1, DEFAULT_SAMPLE_RATE);
32
+ outputSampleFormat = AV_SAMPLE_FMT_FLT;
33
+ filterDescription = null;
34
+ outputFormat = 'f32';
35
+ get isHealthy() {
36
+ return !this.shuttingDown;
37
+ }
38
+ startDecoder(config) {
39
+ this.config = { ...config };
40
+ this.packetTimeBase = new Rational(1, config.sampleRate);
41
+ this.outputFormat = this.parseOutputFormat(config);
42
+ this.outputSampleFormat = mapSampleFormat(this.outputFormat);
43
+ }
44
+ write(data) {
45
+ if (!this.config || this.shuttingDown) {
46
+ return false;
47
+ }
48
+ // Pass raw data directly - extradata is set on the decoder context
49
+ this.queue.push(Buffer.from(data));
50
+ void this.processQueue();
51
+ return true;
52
+ }
53
+ end() {
54
+ if (this.shuttingDown)
55
+ return;
56
+ this.shuttingDown = true;
57
+ void this.finish().catch((err) => this.emit('error', err));
58
+ }
59
+ kill() {
60
+ this.shuttingDown = true;
61
+ this.cleanup();
62
+ this.emit('close', null);
63
+ }
64
+ async shutdown() {
65
+ this.end();
66
+ }
67
+ async processQueue() {
68
+ if (this.processingPromise) {
69
+ return this.processingPromise;
70
+ }
71
+ this.processingPromise = (async () => {
72
+ if (this.processing)
73
+ return;
74
+ this.processing = true;
75
+ try {
76
+ while (this.queue.length > 0) {
77
+ const data = this.queue.shift();
78
+ await this.decodeBuffer(data);
79
+ }
80
+ }
81
+ catch (err) {
82
+ this.emit('error', err instanceof Error ? err : new Error(String(err)));
83
+ }
84
+ finally {
85
+ this.processing = false;
86
+ this.processingPromise = null;
87
+ }
88
+ })();
89
+ return this.processingPromise;
90
+ }
91
+ async ensureDecoder() {
92
+ if (this.decoder || !this.config) {
93
+ return;
94
+ }
95
+ const codecId = mapCodecId(this.config.codec);
96
+ if (!codecId) {
97
+ throw new Error(`Unsupported audio codec: ${this.config.codec}`);
98
+ }
99
+ this.formatContext = new FormatContext();
100
+ this.formatContext.allocContext();
101
+ this.stream = this.formatContext.newStream();
102
+ this.stream.timeBase = this.packetTimeBase;
103
+ const params = this.stream.codecpar;
104
+ params.codecType = AVMEDIA_TYPE_AUDIO;
105
+ params.codecId = codecId;
106
+ params.sampleRate = this.config.sampleRate;
107
+ params.channelLayout = this.getChannelLayout(this.config.numberOfChannels);
108
+ params.channels = this.config.numberOfChannels;
109
+ // Set extradata if we have description (e.g., AudioSpecificConfig for AAC)
110
+ if (this.config.description) {
111
+ const bytes = toUint8Array(this.config.description);
112
+ params.extradata = Buffer.from(bytes);
113
+ }
114
+ this.decoder = await Decoder.create(this.stream, {
115
+ exitOnError: true,
116
+ });
117
+ logger.info(`Created decoder for codec: ${this.config.codec}`);
118
+ }
119
+ parseOutputFormat(config) {
120
+ const defaultFormat = 'f32';
121
+ return config.outputFormat ?? defaultFormat;
122
+ }
123
+ async decodeBuffer(buffer) {
124
+ await this.ensureDecoder();
125
+ if (!this.decoder || !this.stream) {
126
+ throw new Error('Decoder not initialized');
127
+ }
128
+ const packet = new Packet();
129
+ packet.alloc();
130
+ packet.streamIndex = this.stream.index;
131
+ packet.pts = BigInt(this.packetIndex);
132
+ packet.dts = BigInt(this.packetIndex);
133
+ packet.timeBase = this.packetTimeBase;
134
+ packet.data = buffer;
135
+ packet.duration = 1n;
136
+ await this.decoder.decode(packet);
137
+ packet.unref();
138
+ await this.drainFrames();
139
+ this.packetIndex++;
140
+ }
141
+ async drainFrames() {
142
+ if (!this.decoder)
143
+ return;
144
+ let frame = await this.decoder.receive();
145
+ while (frame) {
146
+ const nbSamples = frame.nbSamples;
147
+ if (nbSamples > 0) {
148
+ const passthrough = this.canPassThrough(frame);
149
+ if (passthrough) {
150
+ this.emit('frame', {
151
+ nativeFrame: frame,
152
+ numberOfFrames: nbSamples,
153
+ timestamp: this.frameIndex,
154
+ });
155
+ this.frameIndex += nbSamples;
156
+ }
157
+ else {
158
+ const converted = await this.toOutputBuffer(frame);
159
+ frame.unref();
160
+ if (converted) {
161
+ this.emit('frame', {
162
+ data: converted,
163
+ numberOfFrames: nbSamples,
164
+ timestamp: this.frameIndex,
165
+ });
166
+ this.frameIndex += nbSamples;
167
+ }
168
+ }
169
+ }
170
+ else {
171
+ frame.unref();
172
+ }
173
+ frame = await this.decoder.receive();
174
+ }
175
+ }
176
+ canPassThrough(frame) {
177
+ return frame.format === this.outputSampleFormat;
178
+ }
179
+ async toOutputBuffer(frame) {
180
+ const frameFormat = frame.format;
181
+ const frameChannels = frame.channels || this.config?.numberOfChannels || 2;
182
+ const nbSamples = frame.nbSamples;
183
+ // If frame already matches requested format, just export
184
+ if (frameFormat === this.outputSampleFormat) {
185
+ return frame.toBuffer();
186
+ }
187
+ // For multi-channel audio (>2 channels), the filter has issues with channel layouts
188
+ // Convert manually from planar float to interleaved float if needed
189
+ if (frameChannels > 2 && frameFormat === AV_SAMPLE_FMT_FLTP && this.outputSampleFormat === AV_SAMPLE_FMT_FLT) {
190
+ return this.convertPlanarToInterleaved(frame, nbSamples, frameChannels);
191
+ }
192
+ // For stereo/mono, use filter for conversion
193
+ const outputFormatName = sampleFormatToFFmpegName(this.outputSampleFormat);
194
+ const description = `aformat=sample_fmts=${outputFormatName}`;
195
+ if (!this.filter || this.filterDescription !== description) {
196
+ this.filter?.close();
197
+ this.filter = FilterAPI.create(description, {});
198
+ this.filterDescription = description;
199
+ }
200
+ await this.filter.process(frame);
201
+ let filtered = await this.filter.receive();
202
+ while (filtered === null) {
203
+ filtered = await this.filter.receive();
204
+ }
205
+ if (!filtered) {
206
+ return null;
207
+ }
208
+ const buffer = filtered.toBuffer();
209
+ filtered.unref();
210
+ return buffer;
211
+ }
212
+ convertPlanarToInterleaved(frame, nbSamples, numChannels) {
213
+ // Get planar buffer from frame - each channel is stored separately
214
+ const planarBuffer = frame.toBuffer();
215
+ const bytesPerSample = 4; // float32
216
+ const planeSize = nbSamples * bytesPerSample;
217
+ // Create interleaved output
218
+ const outputSize = nbSamples * numChannels * bytesPerSample;
219
+ const output = Buffer.alloc(outputSize);
220
+ // Convert from planar (LLLLLLLL RRRRRRRR ...) to interleaved (LRLRLRLR ...)
221
+ const inputView = new Float32Array(planarBuffer.buffer, planarBuffer.byteOffset, planarBuffer.byteLength / 4);
222
+ const outputView = new Float32Array(output.buffer, output.byteOffset, output.byteLength / 4);
223
+ for (let s = 0; s < nbSamples; s++) {
224
+ for (let ch = 0; ch < numChannels; ch++) {
225
+ const srcIdx = ch * nbSamples + s;
226
+ const dstIdx = s * numChannels + ch;
227
+ outputView[dstIdx] = inputView[srcIdx];
228
+ }
229
+ }
230
+ return output;
231
+ }
232
+ getChannelLayout(numChannels) {
233
+ // Standard channel layouts as ChannelLayout objects
234
+ // Order 1 = AV_CHANNEL_ORDER_NATIVE (required for FFmpeg)
235
+ switch (numChannels) {
236
+ case 1:
237
+ return { nbChannels: 1, order: AV_CHANNEL_ORDER_NATIVE, mask: AV_CH_LAYOUT_MONO };
238
+ case 2:
239
+ return { nbChannels: 2, order: AV_CHANNEL_ORDER_NATIVE, mask: AV_CH_LAYOUT_STEREO };
240
+ case 6:
241
+ return { nbChannels: 6, order: AV_CHANNEL_ORDER_NATIVE, mask: AV_CH_LAYOUT_5POINT1 };
242
+ case 8:
243
+ return { nbChannels: 8, order: AV_CHANNEL_ORDER_NATIVE, mask: AV_CH_LAYOUT_7POINT1 };
244
+ default:
245
+ return { nbChannels: numChannels, order: AV_CHANNEL_ORDER_NATIVE, mask: BigInt((1 << numChannels) - 1) };
246
+ }
247
+ }
248
+ async finish() {
249
+ await this.processQueue();
250
+ if (this.processingPromise) {
251
+ await this.processingPromise;
252
+ }
253
+ if (this.decoder) {
254
+ try {
255
+ await this.decoder.flush();
256
+ await this.drainFrames();
257
+ }
258
+ catch (err) {
259
+ this.emit('error', err instanceof Error ? err : new Error(String(err)));
260
+ }
261
+ }
262
+ this.emit('close', 0);
263
+ this.cleanup();
264
+ }
265
+ cleanup() {
266
+ this.filter?.close();
267
+ this.filter = null;
268
+ this.decoder?.close();
269
+ this.decoder = null;
270
+ this.formatContext = null;
271
+ this.stream = null;
272
+ this.queue = [];
273
+ }
274
+ }
275
+ function mapCodecId(codec) {
276
+ const codecBase = codec.split('.')[0].toLowerCase();
277
+ switch (codecBase) {
278
+ case 'mp4a':
279
+ case 'aac':
280
+ return AV_CODEC_ID_AAC;
281
+ case 'opus':
282
+ return AV_CODEC_ID_OPUS;
283
+ case 'mp3':
284
+ return AV_CODEC_ID_MP3;
285
+ case 'flac':
286
+ return AV_CODEC_ID_FLAC;
287
+ case 'vorbis':
288
+ return AV_CODEC_ID_VORBIS;
289
+ case 'pcm-s16':
290
+ return AV_CODEC_ID_PCM_S16LE;
291
+ case 'pcm-s24':
292
+ return AV_CODEC_ID_PCM_S24LE;
293
+ case 'pcm-s32':
294
+ return AV_CODEC_ID_PCM_S32LE;
295
+ case 'pcm-f32':
296
+ return AV_CODEC_ID_PCM_F32LE;
297
+ case 'pcm-u8':
298
+ return AV_CODEC_ID_PCM_U8;
299
+ case 'ulaw':
300
+ return AV_CODEC_ID_PCM_MULAW;
301
+ case 'alaw':
302
+ return AV_CODEC_ID_PCM_ALAW;
303
+ default:
304
+ return null;
305
+ }
306
+ }
307
+ function mapSampleFormat(format) {
308
+ switch (format) {
309
+ case 'u8':
310
+ return AV_SAMPLE_FMT_U8;
311
+ case 'u8-planar':
312
+ return AV_SAMPLE_FMT_U8P;
313
+ case 's16':
314
+ return AV_SAMPLE_FMT_S16;
315
+ case 's16-planar':
316
+ return AV_SAMPLE_FMT_S16P;
317
+ case 's32':
318
+ return AV_SAMPLE_FMT_S32;
319
+ case 's32-planar':
320
+ return AV_SAMPLE_FMT_S32P;
321
+ case 'f32':
322
+ return AV_SAMPLE_FMT_FLT;
323
+ case 'f32-planar':
324
+ return AV_SAMPLE_FMT_FLTP;
325
+ default:
326
+ return AV_SAMPLE_FMT_FLT;
327
+ }
328
+ }
329
+ function sampleFormatToFFmpegName(fmt) {
330
+ switch (fmt) {
331
+ case AV_SAMPLE_FMT_U8:
332
+ return 'u8';
333
+ case AV_SAMPLE_FMT_U8P:
334
+ return 'u8p';
335
+ case AV_SAMPLE_FMT_S16:
336
+ return 's16';
337
+ case AV_SAMPLE_FMT_S16P:
338
+ return 's16p';
339
+ case AV_SAMPLE_FMT_S32:
340
+ return 's32';
341
+ case AV_SAMPLE_FMT_S32P:
342
+ return 's32p';
343
+ case AV_SAMPLE_FMT_FLTP:
344
+ return 'fltp';
345
+ case AV_SAMPLE_FMT_FLT:
346
+ default:
347
+ return 'flt';
348
+ }
349
+ }
350
+ //# sourceMappingURL=NodeAvAudioDecoder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NodeAvAudioDecoder.js","sourceRoot":"","sources":["../../src/node-av/NodeAvAudioDecoder.ts"],"names":[],"mappings":"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"}