@revizly/node-av 5.2.2-beta.1

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 (254) hide show
  1. package/BUILD_LINUX.md +61 -0
  2. package/LICENSE.md +22 -0
  3. package/README.md +662 -0
  4. package/build_mac_local.sh +69 -0
  5. package/dist/api/audio-frame-buffer.d.ts +205 -0
  6. package/dist/api/audio-frame-buffer.js +287 -0
  7. package/dist/api/audio-frame-buffer.js.map +1 -0
  8. package/dist/api/bitstream-filter.d.ts +820 -0
  9. package/dist/api/bitstream-filter.js +1242 -0
  10. package/dist/api/bitstream-filter.js.map +1 -0
  11. package/dist/api/constants.d.ts +44 -0
  12. package/dist/api/constants.js +45 -0
  13. package/dist/api/constants.js.map +1 -0
  14. package/dist/api/data/test_av1.ivf +0 -0
  15. package/dist/api/data/test_h264.h264 +0 -0
  16. package/dist/api/data/test_hevc.h265 +0 -0
  17. package/dist/api/data/test_mjpeg.mjpeg +0 -0
  18. package/dist/api/data/test_vp8.ivf +0 -0
  19. package/dist/api/data/test_vp9.ivf +0 -0
  20. package/dist/api/decoder.d.ts +1088 -0
  21. package/dist/api/decoder.js +1775 -0
  22. package/dist/api/decoder.js.map +1 -0
  23. package/dist/api/demuxer.d.ts +1219 -0
  24. package/dist/api/demuxer.js +2081 -0
  25. package/dist/api/demuxer.js.map +1 -0
  26. package/dist/api/device.d.ts +586 -0
  27. package/dist/api/device.js +961 -0
  28. package/dist/api/device.js.map +1 -0
  29. package/dist/api/encoder.d.ts +1132 -0
  30. package/dist/api/encoder.js +1988 -0
  31. package/dist/api/encoder.js.map +1 -0
  32. package/dist/api/filter-complex.d.ts +821 -0
  33. package/dist/api/filter-complex.js +1604 -0
  34. package/dist/api/filter-complex.js.map +1 -0
  35. package/dist/api/filter-presets.d.ts +1286 -0
  36. package/dist/api/filter-presets.js +2152 -0
  37. package/dist/api/filter-presets.js.map +1 -0
  38. package/dist/api/filter.d.ts +1234 -0
  39. package/dist/api/filter.js +1976 -0
  40. package/dist/api/filter.js.map +1 -0
  41. package/dist/api/fmp4-stream.d.ts +426 -0
  42. package/dist/api/fmp4-stream.js +739 -0
  43. package/dist/api/fmp4-stream.js.map +1 -0
  44. package/dist/api/hardware.d.ts +651 -0
  45. package/dist/api/hardware.js +1260 -0
  46. package/dist/api/hardware.js.map +1 -0
  47. package/dist/api/index.d.ts +17 -0
  48. package/dist/api/index.js +32 -0
  49. package/dist/api/index.js.map +1 -0
  50. package/dist/api/io-stream.d.ts +307 -0
  51. package/dist/api/io-stream.js +282 -0
  52. package/dist/api/io-stream.js.map +1 -0
  53. package/dist/api/muxer.d.ts +957 -0
  54. package/dist/api/muxer.js +2002 -0
  55. package/dist/api/muxer.js.map +1 -0
  56. package/dist/api/pipeline.d.ts +607 -0
  57. package/dist/api/pipeline.js +1145 -0
  58. package/dist/api/pipeline.js.map +1 -0
  59. package/dist/api/utilities/async-queue.d.ts +120 -0
  60. package/dist/api/utilities/async-queue.js +211 -0
  61. package/dist/api/utilities/async-queue.js.map +1 -0
  62. package/dist/api/utilities/audio-sample.d.ts +117 -0
  63. package/dist/api/utilities/audio-sample.js +112 -0
  64. package/dist/api/utilities/audio-sample.js.map +1 -0
  65. package/dist/api/utilities/channel-layout.d.ts +76 -0
  66. package/dist/api/utilities/channel-layout.js +80 -0
  67. package/dist/api/utilities/channel-layout.js.map +1 -0
  68. package/dist/api/utilities/electron-shared-texture.d.ts +328 -0
  69. package/dist/api/utilities/electron-shared-texture.js +503 -0
  70. package/dist/api/utilities/electron-shared-texture.js.map +1 -0
  71. package/dist/api/utilities/image.d.ts +207 -0
  72. package/dist/api/utilities/image.js +213 -0
  73. package/dist/api/utilities/image.js.map +1 -0
  74. package/dist/api/utilities/index.d.ts +12 -0
  75. package/dist/api/utilities/index.js +25 -0
  76. package/dist/api/utilities/index.js.map +1 -0
  77. package/dist/api/utilities/media-type.d.ts +49 -0
  78. package/dist/api/utilities/media-type.js +53 -0
  79. package/dist/api/utilities/media-type.js.map +1 -0
  80. package/dist/api/utilities/pixel-format.d.ts +89 -0
  81. package/dist/api/utilities/pixel-format.js +97 -0
  82. package/dist/api/utilities/pixel-format.js.map +1 -0
  83. package/dist/api/utilities/sample-format.d.ts +129 -0
  84. package/dist/api/utilities/sample-format.js +141 -0
  85. package/dist/api/utilities/sample-format.js.map +1 -0
  86. package/dist/api/utilities/scheduler.d.ts +138 -0
  87. package/dist/api/utilities/scheduler.js +98 -0
  88. package/dist/api/utilities/scheduler.js.map +1 -0
  89. package/dist/api/utilities/streaming.d.ts +186 -0
  90. package/dist/api/utilities/streaming.js +309 -0
  91. package/dist/api/utilities/streaming.js.map +1 -0
  92. package/dist/api/utilities/timestamp.d.ts +193 -0
  93. package/dist/api/utilities/timestamp.js +206 -0
  94. package/dist/api/utilities/timestamp.js.map +1 -0
  95. package/dist/api/utilities/whisper-model.d.ts +310 -0
  96. package/dist/api/utilities/whisper-model.js +528 -0
  97. package/dist/api/utilities/whisper-model.js.map +1 -0
  98. package/dist/api/utils.d.ts +19 -0
  99. package/dist/api/utils.js +39 -0
  100. package/dist/api/utils.js.map +1 -0
  101. package/dist/api/whisper.d.ts +324 -0
  102. package/dist/api/whisper.js +362 -0
  103. package/dist/api/whisper.js.map +1 -0
  104. package/dist/constants/channel-layouts.d.ts +53 -0
  105. package/dist/constants/channel-layouts.js +57 -0
  106. package/dist/constants/channel-layouts.js.map +1 -0
  107. package/dist/constants/constants.d.ts +2325 -0
  108. package/dist/constants/constants.js +1887 -0
  109. package/dist/constants/constants.js.map +1 -0
  110. package/dist/constants/decoders.d.ts +633 -0
  111. package/dist/constants/decoders.js +641 -0
  112. package/dist/constants/decoders.js.map +1 -0
  113. package/dist/constants/encoders.d.ts +295 -0
  114. package/dist/constants/encoders.js +308 -0
  115. package/dist/constants/encoders.js.map +1 -0
  116. package/dist/constants/hardware.d.ts +26 -0
  117. package/dist/constants/hardware.js +27 -0
  118. package/dist/constants/hardware.js.map +1 -0
  119. package/dist/constants/index.d.ts +5 -0
  120. package/dist/constants/index.js +6 -0
  121. package/dist/constants/index.js.map +1 -0
  122. package/dist/ffmpeg/index.d.ts +99 -0
  123. package/dist/ffmpeg/index.js +115 -0
  124. package/dist/ffmpeg/index.js.map +1 -0
  125. package/dist/ffmpeg/utils.d.ts +31 -0
  126. package/dist/ffmpeg/utils.js +68 -0
  127. package/dist/ffmpeg/utils.js.map +1 -0
  128. package/dist/ffmpeg/version.d.ts +6 -0
  129. package/dist/ffmpeg/version.js +7 -0
  130. package/dist/ffmpeg/version.js.map +1 -0
  131. package/dist/index.d.ts +4 -0
  132. package/dist/index.js +9 -0
  133. package/dist/index.js.map +1 -0
  134. package/dist/lib/audio-fifo.d.ts +399 -0
  135. package/dist/lib/audio-fifo.js +431 -0
  136. package/dist/lib/audio-fifo.js.map +1 -0
  137. package/dist/lib/binding.d.ts +228 -0
  138. package/dist/lib/binding.js +60 -0
  139. package/dist/lib/binding.js.map +1 -0
  140. package/dist/lib/bitstream-filter-context.d.ts +379 -0
  141. package/dist/lib/bitstream-filter-context.js +441 -0
  142. package/dist/lib/bitstream-filter-context.js.map +1 -0
  143. package/dist/lib/bitstream-filter.d.ts +140 -0
  144. package/dist/lib/bitstream-filter.js +154 -0
  145. package/dist/lib/bitstream-filter.js.map +1 -0
  146. package/dist/lib/codec-context.d.ts +1071 -0
  147. package/dist/lib/codec-context.js +1354 -0
  148. package/dist/lib/codec-context.js.map +1 -0
  149. package/dist/lib/codec-parameters.d.ts +616 -0
  150. package/dist/lib/codec-parameters.js +761 -0
  151. package/dist/lib/codec-parameters.js.map +1 -0
  152. package/dist/lib/codec-parser.d.ts +201 -0
  153. package/dist/lib/codec-parser.js +213 -0
  154. package/dist/lib/codec-parser.js.map +1 -0
  155. package/dist/lib/codec.d.ts +586 -0
  156. package/dist/lib/codec.js +713 -0
  157. package/dist/lib/codec.js.map +1 -0
  158. package/dist/lib/device.d.ts +291 -0
  159. package/dist/lib/device.js +324 -0
  160. package/dist/lib/device.js.map +1 -0
  161. package/dist/lib/dictionary.d.ts +333 -0
  162. package/dist/lib/dictionary.js +372 -0
  163. package/dist/lib/dictionary.js.map +1 -0
  164. package/dist/lib/error.d.ts +242 -0
  165. package/dist/lib/error.js +303 -0
  166. package/dist/lib/error.js.map +1 -0
  167. package/dist/lib/fifo.d.ts +416 -0
  168. package/dist/lib/fifo.js +453 -0
  169. package/dist/lib/fifo.js.map +1 -0
  170. package/dist/lib/filter-context.d.ts +712 -0
  171. package/dist/lib/filter-context.js +789 -0
  172. package/dist/lib/filter-context.js.map +1 -0
  173. package/dist/lib/filter-graph-segment.d.ts +160 -0
  174. package/dist/lib/filter-graph-segment.js +171 -0
  175. package/dist/lib/filter-graph-segment.js.map +1 -0
  176. package/dist/lib/filter-graph.d.ts +641 -0
  177. package/dist/lib/filter-graph.js +704 -0
  178. package/dist/lib/filter-graph.js.map +1 -0
  179. package/dist/lib/filter-inout.d.ts +198 -0
  180. package/dist/lib/filter-inout.js +257 -0
  181. package/dist/lib/filter-inout.js.map +1 -0
  182. package/dist/lib/filter.d.ts +243 -0
  183. package/dist/lib/filter.js +272 -0
  184. package/dist/lib/filter.js.map +1 -0
  185. package/dist/lib/format-context.d.ts +1254 -0
  186. package/dist/lib/format-context.js +1379 -0
  187. package/dist/lib/format-context.js.map +1 -0
  188. package/dist/lib/frame-utils.d.ts +116 -0
  189. package/dist/lib/frame-utils.js +98 -0
  190. package/dist/lib/frame-utils.js.map +1 -0
  191. package/dist/lib/frame.d.ts +1222 -0
  192. package/dist/lib/frame.js +1435 -0
  193. package/dist/lib/frame.js.map +1 -0
  194. package/dist/lib/hardware-device-context.d.ts +362 -0
  195. package/dist/lib/hardware-device-context.js +383 -0
  196. package/dist/lib/hardware-device-context.js.map +1 -0
  197. package/dist/lib/hardware-frames-context.d.ts +419 -0
  198. package/dist/lib/hardware-frames-context.js +477 -0
  199. package/dist/lib/hardware-frames-context.js.map +1 -0
  200. package/dist/lib/index.d.ts +35 -0
  201. package/dist/lib/index.js +60 -0
  202. package/dist/lib/index.js.map +1 -0
  203. package/dist/lib/input-format.d.ts +249 -0
  204. package/dist/lib/input-format.js +306 -0
  205. package/dist/lib/input-format.js.map +1 -0
  206. package/dist/lib/io-context.d.ts +696 -0
  207. package/dist/lib/io-context.js +769 -0
  208. package/dist/lib/io-context.js.map +1 -0
  209. package/dist/lib/log.d.ts +174 -0
  210. package/dist/lib/log.js +184 -0
  211. package/dist/lib/log.js.map +1 -0
  212. package/dist/lib/native-types.d.ts +946 -0
  213. package/dist/lib/native-types.js +2 -0
  214. package/dist/lib/native-types.js.map +1 -0
  215. package/dist/lib/option.d.ts +927 -0
  216. package/dist/lib/option.js +1583 -0
  217. package/dist/lib/option.js.map +1 -0
  218. package/dist/lib/output-format.d.ts +180 -0
  219. package/dist/lib/output-format.js +213 -0
  220. package/dist/lib/output-format.js.map +1 -0
  221. package/dist/lib/packet.d.ts +501 -0
  222. package/dist/lib/packet.js +590 -0
  223. package/dist/lib/packet.js.map +1 -0
  224. package/dist/lib/rational.d.ts +251 -0
  225. package/dist/lib/rational.js +278 -0
  226. package/dist/lib/rational.js.map +1 -0
  227. package/dist/lib/software-resample-context.d.ts +552 -0
  228. package/dist/lib/software-resample-context.js +592 -0
  229. package/dist/lib/software-resample-context.js.map +1 -0
  230. package/dist/lib/software-scale-context.d.ts +344 -0
  231. package/dist/lib/software-scale-context.js +366 -0
  232. package/dist/lib/software-scale-context.js.map +1 -0
  233. package/dist/lib/stream.d.ts +379 -0
  234. package/dist/lib/stream.js +526 -0
  235. package/dist/lib/stream.js.map +1 -0
  236. package/dist/lib/sync-queue.d.ts +179 -0
  237. package/dist/lib/sync-queue.js +197 -0
  238. package/dist/lib/sync-queue.js.map +1 -0
  239. package/dist/lib/types.d.ts +34 -0
  240. package/dist/lib/types.js +2 -0
  241. package/dist/lib/types.js.map +1 -0
  242. package/dist/lib/utilities.d.ts +1127 -0
  243. package/dist/lib/utilities.js +1225 -0
  244. package/dist/lib/utilities.js.map +1 -0
  245. package/dist/utils/electron.d.ts +49 -0
  246. package/dist/utils/electron.js +63 -0
  247. package/dist/utils/electron.js.map +1 -0
  248. package/dist/utils/index.d.ts +4 -0
  249. package/dist/utils/index.js +5 -0
  250. package/dist/utils/index.js.map +1 -0
  251. package/install/check.js +121 -0
  252. package/install/ffmpeg.js +66 -0
  253. package/jellyfin-ffmpeg.patch +181 -0
  254. package/package.json +129 -0
@@ -0,0 +1,1435 @@
1
+ import { AV_NOPTS_VALUE, AV_PIX_FMT_BGRA, AV_TIME_BASE_Q, AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_UNKNOWN, AVMEDIA_TYPE_VIDEO } from '../constants/constants.js';
2
+ import { bindings } from './binding.js';
3
+ import { FFmpegError } from './error.js';
4
+ import { HardwareFramesContext } from './hardware-frames-context.js';
5
+ import { Rational } from './rational.js';
6
+ import { Dictionary } from './dictionary.js';
7
+ /**
8
+ * Container for uncompressed audio/video data.
9
+ *
10
+ * Stores decoded audio samples or video pixels. Each frame contains raw data
11
+ * for a single video frame or a set of audio samples. Includes format information,
12
+ * timing data, and metadata. Supports both software and hardware (GPU) frames.
13
+ * Essential for decoding, encoding, and filter operations.
14
+ *
15
+ * Direct mapping to FFmpeg's AVFrame.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { Frame, FFmpegError } from 'node-av';
20
+ * import { AV_PIX_FMT_YUV420P } from 'node-av/constants';
21
+ *
22
+ * // Create and allocate frame
23
+ * const frame = new Frame();
24
+ * frame.alloc();
25
+ *
26
+ * // Configure video frame
27
+ * frame.format = AV_PIX_FMT_YUV420P;
28
+ * frame.width = 1920;
29
+ * frame.height = 1080;
30
+ * const ret = frame.allocBuffer();
31
+ * FFmpegError.throwIfError(ret, 'allocBuffer');
32
+ *
33
+ * // Receive decoded frame
34
+ * const ret2 = await codecContext.receiveFrame(frame);
35
+ * if (ret2 >= 0) {
36
+ * console.log(`Frame PTS: ${frame.pts}`);
37
+ * console.log(`Frame type: ${frame.pictType}`);
38
+ * console.log(`Keyframe: ${frame.keyFrame}`);
39
+ * }
40
+ *
41
+ * // Cleanup
42
+ * frame.unref();
43
+ * ```
44
+ *
45
+ * @see [AVFrame](https://ffmpeg.org/doxygen/trunk/structAVFrame.html) - FFmpeg Doxygen
46
+ * @see {@link CodecContext} For encoding/decoding frames
47
+ * @see {@link FilterContext} For filtering frames
48
+ */
49
+ export class Frame {
50
+ native;
51
+ _hwFramesCtx; // Cache for hardware frames context wrapper
52
+ constructor() {
53
+ this.native = new bindings.Frame();
54
+ }
55
+ /**
56
+ * Create a video frame from a buffer with pixel data.
57
+ *
58
+ * Allocates frame buffers, sets properties, and copies buffer data.
59
+ * Convenience factory method that combines frame allocation and data copy.
60
+ *
61
+ * @param buffer - Buffer containing raw pixel data
62
+ *
63
+ * @param props - Video Frame properties
64
+ *
65
+ * @returns Allocated frame with data from buffer
66
+ *
67
+ * @throws {FFmpegError} If allocation or buffer copy fails
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * import { Frame, AV_PIX_FMT_RGBA, FFmpegError } from 'node-av';
72
+ *
73
+ * const rawPixels = Buffer.alloc(1920 * 1080 * 4); // RGBA data
74
+ * using frame = Frame.fromVideoBuffer(rawPixels, {
75
+ * width: 1920,
76
+ * height: 1080,
77
+ * format: AV_PIX_FMT_RGBA,
78
+ * timeBase: { num: 1, den: 30 }
79
+ * });
80
+ * ```
81
+ */
82
+ static fromVideoBuffer(buffer, props) {
83
+ const frame = new Frame();
84
+ frame.alloc();
85
+ frame.width = props.width;
86
+ frame.height = props.height;
87
+ frame.format = props.format;
88
+ frame.pts = props.pts ?? AV_NOPTS_VALUE;
89
+ if (props.timeBase) {
90
+ frame.timeBase = new Rational(props.timeBase.num, props.timeBase.den);
91
+ }
92
+ else {
93
+ frame.timeBase = Rational.fromObject(AV_TIME_BASE_Q);
94
+ }
95
+ if (props.sampleAspectRatio) {
96
+ frame.sampleAspectRatio = new Rational(props.sampleAspectRatio.num, props.sampleAspectRatio.den);
97
+ }
98
+ const ret = frame.getBuffer();
99
+ FFmpegError.throwIfError(ret, 'Failed to allocate frame buffers');
100
+ const copyRet = frame.fromBuffer(buffer);
101
+ FFmpegError.throwIfError(copyRet, 'Failed to copy buffer to frame');
102
+ return frame;
103
+ }
104
+ /**
105
+ * Create an audio frame from a buffer with sample data.
106
+ *
107
+ * Allocates frame buffers, sets properties, and copies buffer data.
108
+ * Convenience factory method that combines frame allocation and data copy.
109
+ *
110
+ * @param buffer - Buffer containing raw audio samples
111
+ *
112
+ * @param props - Frame properties
113
+ *
114
+ * @returns Allocated frame with data from buffer
115
+ *
116
+ * @throws {FFmpegError} If allocation or buffer copy fails
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * import { Frame, AV_SAMPLE_FMT_FLT, AV_CH_LAYOUT_STEREO, FFmpegError } from 'node-av';
121
+ *
122
+ * const samples = Buffer.alloc(960 * 2 * 4); // 960 samples, stereo, float32
123
+ * using frame = Frame.fromAudioBuffer(samples, {
124
+ * nbSamples: 960,
125
+ * format: AV_SAMPLE_FMT_FLT,
126
+ * sampleRate: 48000,
127
+ * channelLayout: AV_CH_LAYOUT_STEREO,
128
+ * timeBase: { num: 1, den: 48000 }
129
+ * });
130
+ * ```
131
+ */
132
+ static fromAudioBuffer(buffer, props) {
133
+ const frame = new Frame();
134
+ frame.alloc();
135
+ frame.nbSamples = props.nbSamples;
136
+ frame.format = props.format;
137
+ frame.sampleRate = props.sampleRate;
138
+ frame.channelLayout = props.channelLayout;
139
+ frame.pts = props.pts ?? AV_NOPTS_VALUE;
140
+ if (props.timeBase) {
141
+ frame.timeBase = new Rational(props.timeBase.num, props.timeBase.den);
142
+ }
143
+ else {
144
+ frame.timeBase = Rational.fromObject(AV_TIME_BASE_Q);
145
+ }
146
+ const ret = frame.getBuffer();
147
+ FFmpegError.throwIfError(ret, 'Failed to allocate frame buffers');
148
+ const copyRet = frame.fromBuffer(buffer);
149
+ FFmpegError.throwIfError(copyRet, 'Failed to copy buffer to frame');
150
+ return frame;
151
+ }
152
+ /**
153
+ * Create a hardware frame from an IOSurface handle (macOS only).
154
+ *
155
+ * Zero-copy: the frame references the same GPU memory as the IOSurface.
156
+ * Width and height are auto-detected from the IOSurface.
157
+ *
158
+ * @param ioSurface - IOSurfaceRef pointer as Buffer
159
+ *
160
+ * @param props - Hardware context and timing options
161
+ *
162
+ * @returns Hardware frame referencing the IOSurface GPU memory
163
+ *
164
+ * @throws {FFmpegError} If the import fails (e.g., invalid handle, wrong platform)
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * import { Frame, HardwareFramesContext } from 'node-av/lib';
169
+ *
170
+ * const frame = Frame.fromIOSurface(ioSurfaceBuffer, {
171
+ * hwFramesCtx,
172
+ * pts: 0n,
173
+ * timeBase: { num: 1, den: 90000 },
174
+ * });
175
+ * ```
176
+ */
177
+ static fromIOSurface(ioSurface, props) {
178
+ const frame = new Frame();
179
+ frame.alloc();
180
+ frame.pts = props.pts ?? AV_NOPTS_VALUE;
181
+ if (props.timeBase) {
182
+ frame.timeBase = new Rational(props.timeBase.num, props.timeBase.den);
183
+ }
184
+ const ret = frame.native.importIOSurface(ioSurface, props.hwFramesCtx.getNative());
185
+ FFmpegError.throwIfError(ret, 'Failed to import IOSurface');
186
+ return frame;
187
+ }
188
+ /**
189
+ * Create a hardware frame from a D3D11 shared texture (Windows only).
190
+ *
191
+ * Zero-copy: the frame references the shared GPU texture.
192
+ * Width and height are auto-detected from the texture descriptor.
193
+ *
194
+ * @param handle - D3D11 shared texture handle as Buffer
195
+ *
196
+ * @param props - Hardware context and timing options
197
+ *
198
+ * @returns Hardware frame referencing the D3D11 texture
199
+ *
200
+ * @throws {FFmpegError} If the import fails (e.g., invalid handle, wrong platform)
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * import { Frame, HardwareDeviceContext } from 'node-av/lib';
205
+ *
206
+ * const frame = Frame.fromD3D11Texture(sharedTextureHandle, {
207
+ * hwDeviceCtx,
208
+ * pts: 0n,
209
+ * timeBase: { num: 1, den: 90000 },
210
+ * });
211
+ * ```
212
+ */
213
+ static fromD3D11Texture(handle, props) {
214
+ const frame = new Frame();
215
+ frame.alloc();
216
+ frame.pts = props.pts ?? AV_NOPTS_VALUE;
217
+ if (props.timeBase) {
218
+ frame.timeBase = new Rational(props.timeBase.num, props.timeBase.den);
219
+ }
220
+ const ret = frame.native.importD3D11Texture(handle, props.hwDeviceCtx.getNative());
221
+ FFmpegError.throwIfError(ret, 'Failed to import D3D11 shared texture');
222
+ return frame;
223
+ }
224
+ /**
225
+ * Create a DRM PRIME frame from DMA-BUF file descriptors (Linux only).
226
+ *
227
+ * Zero-copy: the frame references the DMA-BUF GPU memory.
228
+ *
229
+ * @param dmaBuf - DMA-BUF plane descriptors
230
+ *
231
+ * @param props - Dimensions and timing options
232
+ *
233
+ * @returns Hardware frame referencing the DMA-BUF memory
234
+ *
235
+ * @throws {FFmpegError} If the import fails (e.g., invalid descriptors, wrong platform)
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * import { Frame } from 'node-av/lib';
240
+ *
241
+ * // Create DRM PRIME frame from DMA-BUF
242
+ * const drmFrame = Frame.fromDmaBuf(dmaBufPlanes, {
243
+ * width: 1920,
244
+ * height: 1080,
245
+ * pts: 0n,
246
+ * timeBase: { num: 1, den: 90000 },
247
+ * });
248
+ * ```
249
+ */
250
+ static fromDmaBuf(dmaBuf, props) {
251
+ const frame = new Frame();
252
+ frame.alloc();
253
+ frame.pts = props.pts ?? AV_NOPTS_VALUE;
254
+ if (props.timeBase) {
255
+ frame.timeBase = new Rational(props.timeBase.num, props.timeBase.den);
256
+ }
257
+ const swFormat = props.swFormat ?? AV_PIX_FMT_BGRA;
258
+ const ret = frame.native.importDmaBuf(dmaBuf.planes, props.width, props.height, BigInt(dmaBuf.modifier), swFormat);
259
+ FFmpegError.throwIfError(ret, 'Failed to import DMA-BUF');
260
+ return frame;
261
+ }
262
+ /**
263
+ * Pixel format for video frames or sample format for audio.
264
+ *
265
+ * Direct mapping to AVFrame->format.
266
+ */
267
+ get format() {
268
+ return this.native.format;
269
+ }
270
+ set format(value) {
271
+ this.native.format = value;
272
+ }
273
+ /**
274
+ * Width of video frame in pixels.
275
+ *
276
+ * Direct mapping to AVFrame->width.
277
+ */
278
+ get width() {
279
+ return this.native.width;
280
+ }
281
+ set width(value) {
282
+ this.native.width = value;
283
+ }
284
+ /**
285
+ * Height of video frame in pixels.
286
+ *
287
+ * Direct mapping to AVFrame->height.
288
+ */
289
+ get height() {
290
+ return this.native.height;
291
+ }
292
+ set height(value) {
293
+ this.native.height = value;
294
+ }
295
+ /**
296
+ * Number of audio samples per channel.
297
+ *
298
+ * Direct mapping to AVFrame->nb_samples.
299
+ */
300
+ get nbSamples() {
301
+ return this.native.nbSamples;
302
+ }
303
+ set nbSamples(value) {
304
+ this.native.nbSamples = value;
305
+ }
306
+ /**
307
+ * Presentation timestamp.
308
+ *
309
+ * Time when the frame should be presented.
310
+ * In time base units. AV_NOPTS_VALUE if unknown.
311
+ *
312
+ * Direct mapping to AVFrame->pts.
313
+ */
314
+ get pts() {
315
+ return this.native.pts;
316
+ }
317
+ set pts(value) {
318
+ this.native.pts = value;
319
+ }
320
+ /**
321
+ * DTS from the packet that produced this frame.
322
+ *
323
+ * Copy of packet DTS for reference.
324
+ * In time base units. AV_NOPTS_VALUE if unknown.
325
+ *
326
+ * Direct mapping to AVFrame->pkt_dts.
327
+ */
328
+ get pktDts() {
329
+ return this.native.pktDts;
330
+ }
331
+ set pktDts(value) {
332
+ this.native.pktDts = value;
333
+ }
334
+ /**
335
+ * Best effort timestamp.
336
+ *
337
+ * Frame timestamp estimated using various heuristics.
338
+ * In time base units.
339
+ *
340
+ * Direct mapping to AVFrame->best_effort_timestamp.
341
+ */
342
+ get bestEffortTimestamp() {
343
+ return this.native.bestEffortTimestamp;
344
+ }
345
+ set bestEffortTimestamp(value) {
346
+ this.native.bestEffortTimestamp = value;
347
+ }
348
+ /**
349
+ * Time base for timestamps.
350
+ *
351
+ * Defines the unit of the timestamps (seconds per tick).
352
+ *
353
+ * Direct mapping to AVFrame->time_base.
354
+ */
355
+ get timeBase() {
356
+ const tb = this.native.timeBase;
357
+ return new Rational(tb.num, tb.den);
358
+ }
359
+ set timeBase(value) {
360
+ this.native.timeBase = { num: value.num, den: value.den };
361
+ }
362
+ /**
363
+ * Whether this frame is a keyframe.
364
+ *
365
+ * 1 if keyframe, 0 otherwise.
366
+ *
367
+ * Direct mapping to AVFrame->key_frame.
368
+ */
369
+ get keyFrame() {
370
+ return this.native.keyFrame;
371
+ }
372
+ set keyFrame(value) {
373
+ this.native.keyFrame = value;
374
+ }
375
+ /**
376
+ * Picture type of the frame.
377
+ *
378
+ * Type of frame (I, P, B, etc.).
379
+ *
380
+ * Direct mapping to AVFrame->pict_type.
381
+ */
382
+ get pictType() {
383
+ return this.native.pictType;
384
+ }
385
+ set pictType(value) {
386
+ this.native.pictType = value;
387
+ }
388
+ /**
389
+ * Quality (between 1 (good) and FF_LAMBDA_MAX (bad)).
390
+ *
391
+ * Set by libavcodec for some coded frames.
392
+ * Can be set before encoding to specify desired quality for encoders that support it.
393
+ * Used by FFmpeg CLI's frame_encode() to propagate encoder's global_quality setting.
394
+ *
395
+ * Direct mapping to AVFrame->quality.
396
+ */
397
+ get quality() {
398
+ return this.native.quality;
399
+ }
400
+ set quality(value) {
401
+ this.native.quality = value;
402
+ }
403
+ /**
404
+ * Sample aspect ratio.
405
+ *
406
+ * Pixel width/height ratio. 0/1 if unknown.
407
+ *
408
+ * Direct mapping to AVFrame->sample_aspect_ratio.
409
+ */
410
+ get sampleAspectRatio() {
411
+ const sar = this.native.sampleAspectRatio;
412
+ return new Rational(sar.num || 0, sar.den || 1);
413
+ }
414
+ set sampleAspectRatio(value) {
415
+ this.native.sampleAspectRatio = { num: value.num, den: value.den };
416
+ }
417
+ /**
418
+ * Audio sample rate.
419
+ *
420
+ * Number of samples per second.
421
+ *
422
+ * Direct mapping to AVFrame->sample_rate.
423
+ */
424
+ get sampleRate() {
425
+ return this.native.sampleRate;
426
+ }
427
+ set sampleRate(value) {
428
+ this.native.sampleRate = value;
429
+ }
430
+ /**
431
+ * Audio channel layout.
432
+ *
433
+ * Describes the channel configuration.
434
+ *
435
+ * Direct mapping to AVFrame->ch_layout.
436
+ */
437
+ get channelLayout() {
438
+ return this.native.channelLayout;
439
+ }
440
+ set channelLayout(value) {
441
+ this.native.channelLayout = value;
442
+ }
443
+ /**
444
+ * Number of audio channels.
445
+ *
446
+ * Derived from channel layout.
447
+ */
448
+ get channels() {
449
+ return this.native.channels;
450
+ }
451
+ /**
452
+ * Line sizes for each plane.
453
+ *
454
+ * Number of bytes per line for each data plane.
455
+ *
456
+ * Direct mapping to AVFrame->linesize.
457
+ */
458
+ get linesize() {
459
+ return this.native.linesize;
460
+ }
461
+ /**
462
+ * Color range.
463
+ *
464
+ * MPEG (limited) or JPEG (full) range.
465
+ *
466
+ * Direct mapping to AVFrame->color_range.
467
+ */
468
+ get colorRange() {
469
+ return this.native.colorRange;
470
+ }
471
+ set colorRange(value) {
472
+ this.native.colorRange = value;
473
+ }
474
+ /**
475
+ * Color primaries.
476
+ *
477
+ * Chromaticity coordinates of the source primaries.
478
+ *
479
+ * Direct mapping to AVFrame->color_primaries.
480
+ */
481
+ get colorPrimaries() {
482
+ return this.native.colorPrimaries;
483
+ }
484
+ set colorPrimaries(value) {
485
+ this.native.colorPrimaries = value;
486
+ }
487
+ /**
488
+ * Color transfer characteristic.
489
+ *
490
+ * Transfer function (gamma).
491
+ *
492
+ * Direct mapping to AVFrame->color_trc.
493
+ */
494
+ get colorTrc() {
495
+ return this.native.colorTrc;
496
+ }
497
+ set colorTrc(value) {
498
+ this.native.colorTrc = value;
499
+ }
500
+ /**
501
+ * YUV color space.
502
+ *
503
+ * Color space type for YUV content.
504
+ *
505
+ * Direct mapping to AVFrame->colorspace.
506
+ */
507
+ get colorSpace() {
508
+ return this.native.colorSpace;
509
+ }
510
+ set colorSpace(value) {
511
+ this.native.colorSpace = value;
512
+ }
513
+ /**
514
+ * Chroma sample location.
515
+ *
516
+ * Position of chroma samples.
517
+ *
518
+ * Direct mapping to AVFrame->chroma_location.
519
+ */
520
+ get chromaLocation() {
521
+ return this.native.chromaLocation;
522
+ }
523
+ set chromaLocation(value) {
524
+ this.native.chromaLocation = value;
525
+ }
526
+ /**
527
+ * Raw frame data planes.
528
+ *
529
+ * Array of buffers containing the frame data.
530
+ * One buffer per plane (e.g., Y, U, V for YUV420P).
531
+ *
532
+ * Direct mapping to AVFrame->data.
533
+ */
534
+ get data() {
535
+ return this.native.data;
536
+ }
537
+ /**
538
+ * Extended data planes.
539
+ *
540
+ * For audio with >8 channels or planar audio.
541
+ * Points to data planes beyond the first 8.
542
+ *
543
+ * Direct mapping to AVFrame->extended_data.
544
+ */
545
+ get extendedData() {
546
+ return this.native.extendedData;
547
+ }
548
+ /**
549
+ * Check if frame data is writable.
550
+ *
551
+ * True if the frame data can be modified.
552
+ */
553
+ get isWritable() {
554
+ return this.native.isWritable;
555
+ }
556
+ /**
557
+ * Hardware frames context.
558
+ *
559
+ * Reference to hardware frames context for GPU frames.
560
+ * Null for software frames.
561
+ *
562
+ * Direct mapping to AVFrame->hw_frames_ctx.
563
+ */
564
+ get hwFramesCtx() {
565
+ // Return cached wrapper if we already have one
566
+ if (this._hwFramesCtx !== undefined) {
567
+ return this._hwFramesCtx;
568
+ }
569
+ const native = this.native.hwFramesCtx;
570
+ if (!native) {
571
+ this._hwFramesCtx = null;
572
+ return null;
573
+ }
574
+ // Create and cache the wrapper
575
+ const frames = Object.create(HardwareFramesContext.prototype);
576
+ frames.native = native;
577
+ this._hwFramesCtx = frames;
578
+ return frames;
579
+ }
580
+ set hwFramesCtx(value) {
581
+ this.native.hwFramesCtx = value?.getNative() ?? null;
582
+ // Clear the cache as the underlying context has changed
583
+ this._hwFramesCtx = undefined;
584
+ }
585
+ /**
586
+ * Frame flags.
587
+ *
588
+ * Combination of AVFrameFlags (e.g., AV_FRAME_FLAG_CORRUPT, AV_FRAME_FLAG_KEY).
589
+ *
590
+ * Direct mapping to AVFrame->flags.
591
+ */
592
+ get flags() {
593
+ return this.native.flags;
594
+ }
595
+ set flags(value) {
596
+ this.native.flags = value;
597
+ }
598
+ /**
599
+ * Decode error flags.
600
+ *
601
+ * Indicates errors detected during decoding.
602
+ * Non-zero value means the frame may be corrupted.
603
+ *
604
+ * Direct mapping to AVFrame->decode_error_flags.
605
+ */
606
+ get decodeErrorFlags() {
607
+ return this.native.decodeErrorFlags;
608
+ }
609
+ set decodeErrorFlags(value) {
610
+ this.native.decodeErrorFlags = value;
611
+ }
612
+ /**
613
+ * Frame duration.
614
+ *
615
+ * Duration of this frame in units of time_base.
616
+ * This is FFmpeg's best guess for how long the frame should be displayed.
617
+ * May be 0 if unknown or unavailable.
618
+ *
619
+ * Direct mapping to AVFrame->duration.
620
+ */
621
+ get duration() {
622
+ return this.native.duration;
623
+ }
624
+ set duration(value) {
625
+ this.native.duration = value;
626
+ }
627
+ /**
628
+ * Number of fields in this frame that should be repeated.
629
+ *
630
+ * For interlaced video, indicates how many times the frame should be repeated
631
+ * when displayed. For progressive video, this is typically 0.
632
+ * Formula: display_time = (repeat_pict / (2*fps))
633
+ *
634
+ * Direct mapping to AVFrame->repeat_pict.
635
+ */
636
+ get repeatPict() {
637
+ return this.native.repeatPict;
638
+ }
639
+ set repeatPict(value) {
640
+ this.native.repeatPict = value;
641
+ }
642
+ /**
643
+ * Set frame flags.
644
+ *
645
+ * Sets one or more flags using bitwise OR. Allows setting multiple flags
646
+ * without manually performing bitwise operations.
647
+ *
648
+ * @param flags - One or more flag values to set
649
+ *
650
+ * @example
651
+ * ```typescript
652
+ * import { AV_FRAME_FLAG_KEY } from 'node-av/constants';
653
+ *
654
+ * // Mark frame as key frame
655
+ * frame.setFlags(AV_FRAME_FLAG_KEY);
656
+ * ```
657
+ *
658
+ * @see {@link clearFlags} To unset flags
659
+ * @see {@link hasFlags} To check flags
660
+ * @see {@link flags} For direct flag access
661
+ */
662
+ setFlags(...flags) {
663
+ for (const flag of flags) {
664
+ this.native.flags |= flag;
665
+ }
666
+ }
667
+ /**
668
+ * Clear frame flags.
669
+ *
670
+ * Clears one or more flags using bitwise AND NOT. Allows clearing multiple
671
+ * flags without manually performing bitwise operations.
672
+ *
673
+ * @param flags - One or more flag values to clear
674
+ *
675
+ * @example
676
+ * ```typescript
677
+ * import { AV_FRAME_FLAG_CORRUPT } from 'node-av/constants';
678
+ *
679
+ * // Clear corrupt flag
680
+ * frame.clearFlags(AV_FRAME_FLAG_CORRUPT);
681
+ * ```
682
+ *
683
+ * @see {@link setFlags} To set flags
684
+ * @see {@link hasFlags} To check flags
685
+ * @see {@link flags} For direct flag access
686
+ */
687
+ clearFlags(...flags) {
688
+ for (const flag of flags) {
689
+ this.native.flags &= ~flag;
690
+ }
691
+ }
692
+ /**
693
+ * Check if frame has specific flags.
694
+ *
695
+ * Tests whether all specified flags are set using bitwise AND.
696
+ *
697
+ * @param flags - One or more flag values to check
698
+ *
699
+ * @returns true if all specified flags are set, false otherwise
700
+ *
701
+ * @example
702
+ * ```typescript
703
+ * import { AV_FRAME_FLAG_CORRUPT } from 'node-av/constants';
704
+ *
705
+ * if (frame.hasFlags(AV_FRAME_FLAG_CORRUPT)) {
706
+ * console.log('Frame is corrupted');
707
+ * }
708
+ * ```
709
+ *
710
+ * @see {@link setFlags} To set flags
711
+ * @see {@link clearFlags} To unset flags
712
+ * @see {@link flags} For direct flag access
713
+ */
714
+ hasFlags(...flags) {
715
+ for (const flag of flags) {
716
+ if ((this.native.flags & flag) !== flag) {
717
+ return false;
718
+ }
719
+ }
720
+ return true;
721
+ }
722
+ /**
723
+ * Check if frame has decode errors.
724
+ *
725
+ * Tests whether all specified decode error flags are set using bitwise AND.
726
+ *
727
+ * @param flags - One or more decode error flag values to check
728
+ *
729
+ * @returns true if all specified error flags are set, false otherwise
730
+ *
731
+ * @example
732
+ * ```typescript
733
+ * import { FF_DECODE_ERROR_INVALID_BITSTREAM } from 'node-av/constants';
734
+ *
735
+ * if (frame.hasDecodeErrorFlags(FF_DECODE_ERROR_INVALID_BITSTREAM)) {
736
+ * console.log('Frame has invalid bitstream error');
737
+ * }
738
+ * ```
739
+ *
740
+ * @see {@link decodeErrorFlags} For direct error flag access
741
+ */
742
+ hasDecodeErrorFlags(...flags) {
743
+ for (const flag of flags) {
744
+ if ((this.native.decodeErrorFlags & flag) !== flag) {
745
+ return false;
746
+ }
747
+ }
748
+ return true;
749
+ }
750
+ /**
751
+ * Check if this is a video frame.
752
+ *
753
+ * Video frames have width and height > 0.
754
+ *
755
+ * @returns true if this is a video frame
756
+ *
757
+ * @example
758
+ * ```typescript
759
+ * if (frame.isVideo()) {
760
+ * console.log(`Video frame: ${frame.width}x${frame.height}`);
761
+ * }
762
+ * ```
763
+ */
764
+ isVideo() {
765
+ return this.width > 0 && this.height > 0;
766
+ }
767
+ /**
768
+ * Check if this is an audio frame.
769
+ *
770
+ * Audio frames have sampleRate > 0 and nbSamples > 0.
771
+ *
772
+ * @returns true if this is an audio frame
773
+ *
774
+ * @example
775
+ * ```typescript
776
+ * if (frame.isAudio()) {
777
+ * console.log(`Audio frame: ${frame.sampleRate}Hz, ${frame.nbSamples} samples`);
778
+ * }
779
+ * ```
780
+ */
781
+ isAudio() {
782
+ return this.sampleRate > 0 && this.nbSamples > 0;
783
+ }
784
+ /**
785
+ * Get the media type of this frame.
786
+ *
787
+ * @returns AVMEDIA_TYPE_VIDEO for video frames, AVMEDIA_TYPE_AUDIO for audio frames, or AVMEDIA_TYPE_UNKNOWN
788
+ *
789
+ * @example
790
+ * ```typescript
791
+ * const type = frame.getMediaType();
792
+ * console.log(`Frame type: ${type}`);
793
+ * ```
794
+ */
795
+ getMediaType() {
796
+ if (this.isVideo())
797
+ return AVMEDIA_TYPE_VIDEO;
798
+ if (this.isAudio())
799
+ return AVMEDIA_TYPE_AUDIO;
800
+ return AVMEDIA_TYPE_UNKNOWN;
801
+ }
802
+ /**
803
+ * Allocate a new frame.
804
+ *
805
+ * Allocates the frame structure. Must be called before using the frame
806
+ * unless it was created by another function (e.g., clone()).
807
+ *
808
+ * Direct mapping to av_frame_alloc().
809
+ *
810
+ * @throws {Error} If allocation fails (ENOMEM)
811
+ *
812
+ * @example
813
+ * ```typescript
814
+ * const frame = new Frame();
815
+ * frame.alloc();
816
+ * // Frame structure is now ready
817
+ * ```
818
+ *
819
+ * @see {@link allocBuffer} To allocate data buffers
820
+ * @see {@link free} To deallocate the frame
821
+ */
822
+ alloc() {
823
+ this.native.alloc();
824
+ }
825
+ /**
826
+ * Free the frame.
827
+ *
828
+ * Deallocates the frame and its data. The frame becomes invalid after this.
829
+ *
830
+ * Direct mapping to av_frame_free().
831
+ *
832
+ * @example
833
+ * ```typescript
834
+ * frame.free();
835
+ * // Frame is now invalid
836
+ * ```
837
+ *
838
+ * @see {@link unref} To only free data, keeping structure
839
+ */
840
+ free() {
841
+ this.native.free();
842
+ }
843
+ /**
844
+ * Create a reference to another frame.
845
+ *
846
+ * Sets up this frame as a reference to the source frame's data.
847
+ * Both frames will share the same data buffers.
848
+ *
849
+ * Direct mapping to av_frame_ref().
850
+ *
851
+ * @param src - Source frame to reference
852
+ *
853
+ * @returns 0 on success, negative AVERROR on error:
854
+ * - AVERROR_ENOMEM: Memory allocation failure
855
+ * - AVERROR_EINVAL: Invalid parameters
856
+ *
857
+ * @example
858
+ * ```typescript
859
+ * import { FFmpegError } from 'node-av';
860
+ *
861
+ * const frame2 = new Frame();
862
+ * frame2.alloc();
863
+ * const ret = frame2.ref(frame1);
864
+ * FFmpegError.throwIfError(ret, 'ref');
865
+ * // frame2 now references frame1's data
866
+ * ```
867
+ *
868
+ * @see {@link unref} To remove reference
869
+ * @see {@link clone} To create independent copy
870
+ */
871
+ ref(src) {
872
+ return this.native.ref(src.getNative());
873
+ }
874
+ /**
875
+ * Unreference the frame.
876
+ *
877
+ * Frees the frame data if this was the last reference.
878
+ * The frame structure remains allocated and can be reused.
879
+ *
880
+ * Direct mapping to av_frame_unref().
881
+ *
882
+ * @example
883
+ * ```typescript
884
+ * frame.unref();
885
+ * // Frame data is freed, structure can be reused
886
+ * ```
887
+ *
888
+ * @see {@link ref} To create reference
889
+ * @see {@link free} To free everything
890
+ */
891
+ unref() {
892
+ this.native.unref();
893
+ }
894
+ /**
895
+ * Clone the frame.
896
+ *
897
+ * Creates an independent copy of the frame with its own data buffers.
898
+ * The new frame has the same content but can be modified independently.
899
+ *
900
+ * Direct mapping to av_frame_clone().
901
+ *
902
+ * @returns New frame instance, or null on allocation failure
903
+ *
904
+ * @example
905
+ * ```typescript
906
+ * const copy = frame.clone();
907
+ * if (copy) {
908
+ * // Modify copy without affecting original
909
+ * copy.pts = frame.pts + 1000n;
910
+ * }
911
+ * ```
912
+ *
913
+ * @see {@link ref} To create reference instead of copy
914
+ * @see {@link copy} To copy into existing frame
915
+ */
916
+ clone() {
917
+ const cloned = this.native.clone();
918
+ if (!cloned) {
919
+ return null;
920
+ }
921
+ // Wrap the native cloned frame
922
+ const frame = Object.create(Frame.prototype);
923
+ frame.native = cloned;
924
+ return frame;
925
+ }
926
+ /**
927
+ * Get required buffer size for the frame.
928
+ *
929
+ * Calculates the required buffer size based on frame parameters.
930
+ * Must set format, width/height (video) or format, nb_samples, channel_layout (audio) first.
931
+ *
932
+ * Direct mapping to av_frame_get_buffer().
933
+ *
934
+ * @param align - Buffer size alignment (0 for default)
935
+ *
936
+ * @returns Required buffer size in bytes, or negative AVERROR:
937
+ * - AVERROR_EINVAL: Invalid frame parameters
938
+ *
939
+ * @example
940
+ * ```typescript
941
+ * import { FFmpegError } from 'node-av';
942
+ *
943
+ * const size = frame.getBuffer();
944
+ * FFmpegError.throwIfError(size, 'getBuffer');
945
+ * console.log(`Buffer size: ${size} bytes`);
946
+ * ```
947
+ *
948
+ * @see {@link allocBuffer} To allocate the buffer
949
+ */
950
+ getBuffer(align = 0) {
951
+ return this.native.getBuffer(align);
952
+ }
953
+ /**
954
+ * Allocate data buffers for the frame.
955
+ *
956
+ * Allocates buffers based on frame format and dimensions.
957
+ * Frame parameters must be set before calling.
958
+ *
959
+ * Direct mapping to av_frame_get_buffer().
960
+ *
961
+ * @returns 0 on success, negative AVERROR on error:
962
+ * - AVERROR_EINVAL: Invalid frame parameters
963
+ * - AVERROR_ENOMEM: Memory allocation failure
964
+ *
965
+ * @example
966
+ * ```typescript
967
+ * import { FFmpegError } from 'node-av';
968
+ * import { AV_PIX_FMT_YUV420P } from 'node-av/constants';
969
+ *
970
+ * frame.format = AV_PIX_FMT_YUV420P;
971
+ * frame.width = 1920;
972
+ * frame.height = 1080;
973
+ * const ret = frame.allocBuffer();
974
+ * FFmpegError.throwIfError(ret, 'allocBuffer');
975
+ * ```
976
+ *
977
+ * @see {@link getBuffer} To get required size
978
+ */
979
+ allocBuffer() {
980
+ return this.native.allocBuffer();
981
+ }
982
+ /**
983
+ * Ensure frame data is writable.
984
+ *
985
+ * Creates a private copy of the data if it's shared with other frames.
986
+ * Call before modifying frame data to avoid affecting other references.
987
+ *
988
+ * Direct mapping to av_frame_make_writable().
989
+ *
990
+ * @returns 0 on success, negative AVERROR on error:
991
+ * - AVERROR_ENOMEM: Memory allocation failure
992
+ * - AVERROR_EINVAL: Invalid frame
993
+ *
994
+ * @example
995
+ * ```typescript
996
+ * import { FFmpegError } from 'node-av';
997
+ *
998
+ * // Ensure we can safely modify data
999
+ * const ret = frame.makeWritable();
1000
+ * FFmpegError.throwIfError(ret, 'makeWritable');
1001
+ * // Now safe to modify frame.data
1002
+ * ```
1003
+ */
1004
+ makeWritable() {
1005
+ return this.native.makeWritable();
1006
+ }
1007
+ /**
1008
+ * Copy non-layout frame properties without copying data.
1009
+ *
1010
+ * Copies metadata like timestamp, duration, etc., but not the actual data.
1011
+ * Layout-defining properties, such as width, height, channel count, format, etc., are not copied.
1012
+ * Useful for preparing output frames with same properties.
1013
+ *
1014
+ * Direct mapping to av_frame_copy_props().
1015
+ *
1016
+ * @param src - Source frame to copy properties from
1017
+ *
1018
+ * @returns 0 on success, negative AVERROR on error:
1019
+ * - AVERROR_ENOMEM: Memory allocation failure
1020
+ *
1021
+ * @example
1022
+ * ```typescript
1023
+ * import { FFmpegError } from 'node-av';
1024
+ *
1025
+ * const ret = dstFrame.copyProps(srcFrame);
1026
+ * FFmpegError.throwIfError(ret, 'copyProps');
1027
+ * // dstFrame now has same non-layout properties as srcFrame
1028
+ * ```
1029
+ *
1030
+ * @see {@link copy} To copy data
1031
+ */
1032
+ copyProps(src) {
1033
+ return this.native.copyProps(src.getNative());
1034
+ }
1035
+ /**
1036
+ * Copy frame data.
1037
+ *
1038
+ * Copies only data (but not metadata) from source frame.
1039
+ * Destination must have allocated buffers of correct size.
1040
+ *
1041
+ * Direct mapping to av_frame_copy().
1042
+ *
1043
+ * @param src - Source frame to copy from
1044
+ *
1045
+ * @returns 0 on success, negative AVERROR on error:
1046
+ * - AVERROR_EINVAL: Incompatible frames
1047
+ *
1048
+ * @example
1049
+ * ```typescript
1050
+ * import { FFmpegError } from 'node-av';
1051
+ *
1052
+ * // Allocate destination with same format
1053
+ * dstFrame.format = srcFrame.format;
1054
+ * dstFrame.width = srcFrame.width;
1055
+ * dstFrame.height = srcFrame.height;
1056
+ * dstFrame.allocBuffer();
1057
+ *
1058
+ * const ret = dstFrame.copy(srcFrame);
1059
+ * FFmpegError.throwIfError(ret, 'copy');
1060
+ * ```
1061
+ *
1062
+ * @see {@link copyProps} To copy non-format metadata
1063
+ * @see {@link clone} To create new frame with copy
1064
+ */
1065
+ copy(src) {
1066
+ return this.native.copy(src.getNative());
1067
+ }
1068
+ /**
1069
+ * Fill frame data from buffer.
1070
+ *
1071
+ * Copies data from buffer into frame data planes.
1072
+ * Frame must have allocated buffers.
1073
+ *
1074
+ * @param buffer - Source buffer with frame data
1075
+ *
1076
+ * @returns 0 on success, negative AVERROR on error:
1077
+ * - AVERROR_EINVAL: Invalid parameters
1078
+ *
1079
+ * @example
1080
+ * ```typescript
1081
+ * import { FFmpegError } from 'node-av';
1082
+ *
1083
+ * const buffer = Buffer.from(rawVideoData);
1084
+ * const ret = frame.fromBuffer(buffer);
1085
+ * FFmpegError.throwIfError(ret, 'fromBuffer');
1086
+ * ```
1087
+ */
1088
+ fromBuffer(buffer) {
1089
+ return this.native.fromBuffer(buffer);
1090
+ }
1091
+ /**
1092
+ * Convert frame data to buffer.
1093
+ *
1094
+ * Copies frame data into a single contiguous buffer.
1095
+ * For video frames, converts all planes into packed format.
1096
+ * For audio frames, handles both planar and interleaved formats.
1097
+ * Cannot be used with hardware frames - use hwframeTransferData first.
1098
+ *
1099
+ * @returns Buffer containing frame data
1100
+ *
1101
+ * @throws {Error} If frame is not allocated, has no data, or is a hardware frame
1102
+ *
1103
+ * @example Video frame to buffer
1104
+ * ```typescript
1105
+ * // Get YUV420P video frame as buffer
1106
+ * const buffer = frame.toBuffer();
1107
+ * console.log(`Frame buffer size: ${buffer.length} bytes`);
1108
+ * // Buffer contains Y plane, then U plane, then V plane
1109
+ * ```
1110
+ *
1111
+ * @example Audio frame to buffer
1112
+ * ```typescript
1113
+ * // Get audio samples as buffer
1114
+ * const audioBuffer = frame.toBuffer();
1115
+ * console.log(`Audio buffer size: ${audioBuffer.length} bytes`);
1116
+ * // For planar audio: channel 0 samples, then channel 1 samples, etc.
1117
+ * // For interleaved audio: sample0_ch0, sample0_ch1, sample1_ch0, sample1_ch1, etc.
1118
+ * ```
1119
+ *
1120
+ * @example Error handling
1121
+ * ```typescript
1122
+ * try {
1123
+ * const buffer = frame.toBuffer();
1124
+ * // Process buffer...
1125
+ * } catch (error) {
1126
+ * if (frame.isHwFrame()) {
1127
+ * // Transfer to software first
1128
+ * const swFrame = new Frame();
1129
+ * swFrame.alloc();
1130
+ * await frame.hwframeTransferData(swFrame);
1131
+ * const buffer = swFrame.toBuffer();
1132
+ * }
1133
+ * }
1134
+ * ```
1135
+ *
1136
+ * @see {@link fromBuffer} To create frame from buffer
1137
+ * @see {@link hwframeTransferData} To transfer hardware frames to software
1138
+ * @see {@link isHwFrame} To check if frame is hardware
1139
+ * @see {@link data} To access individual planes
1140
+ */
1141
+ toBuffer() {
1142
+ return this.native.toBuffer();
1143
+ }
1144
+ /**
1145
+ * Transfer data between hardware and software frames.
1146
+ *
1147
+ * Copies frame data between GPU and system memory.
1148
+ * Direction depends on source and destination frame types.
1149
+ *
1150
+ * Direct mapping to av_hwframe_transfer_data().
1151
+ *
1152
+ * @param dst - Destination frame (software or hardware)
1153
+ *
1154
+ * @param flags - Transfer flags (0 for default)
1155
+ *
1156
+ * @returns 0 on success, negative AVERROR on error:
1157
+ * - AVERROR_EINVAL: Invalid parameters
1158
+ * - AVERROR_ENOMEM: Memory allocation failure
1159
+ *
1160
+ * @example
1161
+ * ```typescript
1162
+ * import { FFmpegError } from 'node-av';
1163
+ *
1164
+ * // Download from GPU to CPU
1165
+ * const swFrame = new Frame();
1166
+ * swFrame.alloc();
1167
+ * const ret = await hwFrame.hwframeTransferData(swFrame);
1168
+ * FFmpegError.throwIfError(ret, 'hwframeTransferData');
1169
+ * ```
1170
+ *
1171
+ * @see {@link isHwFrame} To check if frame is hardware
1172
+ * @see {@link isSwFrame} To check if frame is software
1173
+ */
1174
+ async hwframeTransferData(dst, flags) {
1175
+ return await this.native.hwframeTransferData(dst.getNative(), flags ?? 0);
1176
+ }
1177
+ /**
1178
+ * Transfer data between hardware and software frames synchronously.
1179
+ * Synchronous version of hwframeTransferData.
1180
+ *
1181
+ * Copies frame data between GPU and system memory.
1182
+ * Direction depends on source and destination frame types.
1183
+ *
1184
+ * Direct mapping to av_hwframe_transfer_data().
1185
+ *
1186
+ * @param dst - Destination frame (software or hardware)
1187
+ *
1188
+ * @param flags - Transfer flags (0 for default)
1189
+ *
1190
+ * @returns 0 on success, negative AVERROR on error:
1191
+ * - AVERROR_EINVAL: Invalid parameters
1192
+ * - AVERROR_ENOMEM: Memory allocation failure
1193
+ *
1194
+ * @example
1195
+ * ```typescript
1196
+ * import { FFmpegError } from 'node-av';
1197
+ *
1198
+ * // Download from GPU to CPU
1199
+ * const swFrame = new Frame();
1200
+ * swFrame.alloc();
1201
+ * const ret = hwFrame.hwframeTransferData(swFrame);
1202
+ * FFmpegError.throwIfError(ret, 'hwframeTransferData');
1203
+ * ```
1204
+ *
1205
+ * @see {@link hwframeTransferData} For async version
1206
+ */
1207
+ hwframeTransferDataSync(dst, flags) {
1208
+ return this.native.hwframeTransferDataSync(dst.getNative(), flags ?? 0);
1209
+ }
1210
+ /**
1211
+ * Check if this is a hardware frame.
1212
+ *
1213
+ * Returns true if frame data is in GPU memory.
1214
+ *
1215
+ * @returns True if hardware frame, false otherwise
1216
+ *
1217
+ * @example
1218
+ * ```typescript
1219
+ * if (frame.isHwFrame()) {
1220
+ * console.log('Frame is in GPU memory');
1221
+ * }
1222
+ * ```
1223
+ *
1224
+ * @see {@link isSwFrame} To check for software frame
1225
+ * @see {@link hwframeTransferData} To transfer between GPU/CPU
1226
+ */
1227
+ isHwFrame() {
1228
+ return this.native.isHwFrame();
1229
+ }
1230
+ /**
1231
+ * Check if this is a software frame.
1232
+ *
1233
+ * Returns true if frame data is in system memory.
1234
+ *
1235
+ * @returns True if software frame, false otherwise
1236
+ *
1237
+ * @example
1238
+ * ```typescript
1239
+ * if (frame.isSwFrame()) {
1240
+ * console.log('Frame is in system memory');
1241
+ * }
1242
+ * ```
1243
+ *
1244
+ * @see {@link isHwFrame} To check for hardware frame
1245
+ * @see {@link hwframeTransferData} To transfer between GPU/CPU
1246
+ */
1247
+ isSwFrame() {
1248
+ return this.native.isSwFrame();
1249
+ }
1250
+ /**
1251
+ * Get frame side data.
1252
+ *
1253
+ * Retrieves additional data associated with the frame
1254
+ * (e.g., motion vectors, film grain, HDR metadata).
1255
+ *
1256
+ * Direct mapping to av_frame_get_side_data().
1257
+ *
1258
+ * @param type - Type of side data to retrieve
1259
+ *
1260
+ * @returns Side data buffer, or null if not present
1261
+ *
1262
+ * @example
1263
+ * ```typescript
1264
+ * import { AV_FRAME_DATA_MOTION_VECTORS } from 'node-av/constants';
1265
+ *
1266
+ * const motionVectors = frame.getSideData(AV_FRAME_DATA_MOTION_VECTORS);
1267
+ * if (motionVectors) {
1268
+ * console.log(`Motion data size: ${motionVectors.length} bytes`);
1269
+ * }
1270
+ * ```
1271
+ *
1272
+ * @see {@link newSideData} To add side data
1273
+ * @see {@link removeSideData} To remove side data
1274
+ */
1275
+ getSideData(type) {
1276
+ return this.native.getSideData(type);
1277
+ }
1278
+ /**
1279
+ * Allocate new side data.
1280
+ *
1281
+ * Allocates side data buffer attached to the frame.
1282
+ * Returns buffer that can be written to directly.
1283
+ *
1284
+ * Direct mapping to av_frame_new_side_data().
1285
+ *
1286
+ * @param type - Type of side data
1287
+ *
1288
+ * @param size - Size in bytes to allocate
1289
+ *
1290
+ * @returns Allocated buffer for writing
1291
+ *
1292
+ * @throws {Error} If allocation fails
1293
+ *
1294
+ * @example
1295
+ * ```typescript
1296
+ * import { AV_FRAME_DATA_MASTERING_DISPLAY_METADATA } from 'node-av/constants';
1297
+ *
1298
+ * // Allocate and write HDR metadata
1299
+ * const hdrData = frame.newSideData(
1300
+ * AV_FRAME_DATA_MASTERING_DISPLAY_METADATA,
1301
+ * 40
1302
+ * );
1303
+ * // Write metadata to buffer...
1304
+ * ```
1305
+ *
1306
+ * @see {@link getSideData} To retrieve side data
1307
+ * @see {@link removeSideData} To remove side data
1308
+ */
1309
+ newSideData(type, size) {
1310
+ return this.native.newSideData(type, size);
1311
+ }
1312
+ /**
1313
+ * Remove side data from frame.
1314
+ *
1315
+ * Removes specific type of side data.
1316
+ *
1317
+ * Direct mapping to av_frame_remove_side_data().
1318
+ *
1319
+ * @param type - Type of side data to remove
1320
+ *
1321
+ * @example
1322
+ * ```typescript
1323
+ * import { AV_FRAME_DATA_MOTION_VECTORS } from 'node-av/constants';
1324
+ *
1325
+ * frame.removeSideData(AV_FRAME_DATA_MOTION_VECTORS);
1326
+ * // Motion vectors removed
1327
+ * ```
1328
+ *
1329
+ * @see {@link getSideData} To retrieve side data
1330
+ * @see {@link newSideData} To add side data
1331
+ */
1332
+ removeSideData(type) {
1333
+ this.native.removeSideData(type);
1334
+ }
1335
+ /**
1336
+ * Get frame metadata dictionary.
1337
+ *
1338
+ * Returns metadata attached to the frame by filters or demuxers.
1339
+ * Metadata is stored as key-value pairs in a Dictionary.
1340
+ * Useful for reading filter-generated metadata (e.g., whisper transcription).
1341
+ *
1342
+ * Direct mapping to AVFrame->metadata.
1343
+ *
1344
+ * @returns Dictionary containing frame metadata
1345
+ *
1346
+ * @example
1347
+ * ```typescript
1348
+ * // Read whisper filter metadata
1349
+ * const metadata = frame.getMetadata();
1350
+ * const text = metadata.get('lavfi.whisper.text');
1351
+ * const duration = metadata.get('lavfi.whisper.duration');
1352
+ *
1353
+ * if (text) {
1354
+ * console.log(`Transcribed: ${text}`);
1355
+ * console.log(`Duration: ${duration}s`);
1356
+ * }
1357
+ * ```
1358
+ *
1359
+ * @example
1360
+ * ```typescript
1361
+ * // Read scene detection metadata
1362
+ * const metadata = frame.getMetadata();
1363
+ * const score = metadata.get('lavfi.scene_score');
1364
+ * if (score) {
1365
+ * console.log(`Scene change score: ${score}`);
1366
+ * }
1367
+ * ```
1368
+ *
1369
+ * @see {@link Dictionary} For metadata dictionary operations
1370
+ */
1371
+ getMetadata() {
1372
+ return Dictionary.fromNative(this.native.getMetadata());
1373
+ }
1374
+ /**
1375
+ * Apply cropping to the frame.
1376
+ *
1377
+ * Crops the frame according to its crop metadata (AVFrame crop fields).
1378
+ * This adjusts the frame dimensions and data pointers to reflect the cropped region.
1379
+ * The cropped-out area is discarded, reducing frame size.
1380
+ *
1381
+ * Direct mapping to av_frame_apply_cropping().
1382
+ *
1383
+ * @param flags - Cropping flags (default: AV_FRAME_CROP_UNALIGNED = 1)
1384
+ * AV_FRAME_CROP_UNALIGNED allows unaligned cropping for lavfi compatibility
1385
+ *
1386
+ * @returns 0 on success, negative error code on failure
1387
+ *
1388
+ * @example
1389
+ * ```typescript
1390
+ * import { Frame, FFmpegError } from 'node-av';
1391
+ *
1392
+ * const frame = new Frame();
1393
+ * // ... decode frame with crop metadata ...
1394
+ *
1395
+ * // Apply cropping based on metadata
1396
+ * const ret = frame.applyCropping();
1397
+ * FFmpegError.throwIfError(ret, 'Failed to apply cropping');
1398
+ *
1399
+ * // Frame dimensions are now updated to cropped size
1400
+ * console.log(`Cropped to ${frame.width}x${frame.height}`);
1401
+ * ```
1402
+ */
1403
+ applyCropping(flags) {
1404
+ return this.native.applyCropping(flags);
1405
+ }
1406
+ /**
1407
+ * Get the underlying native Frame object.
1408
+ *
1409
+ * @returns The native Frame binding object
1410
+ *
1411
+ * @internal
1412
+ */
1413
+ getNative() {
1414
+ return this.native;
1415
+ }
1416
+ /**
1417
+ * Dispose of the frame.
1418
+ *
1419
+ * Implements the Disposable interface for automatic cleanup.
1420
+ * Equivalent to calling free().
1421
+ *
1422
+ * @example
1423
+ * ```typescript
1424
+ * {
1425
+ * using frame = new Frame();
1426
+ * frame.alloc();
1427
+ * // Use frame...
1428
+ * } // Automatically freed when leaving scope
1429
+ * ```
1430
+ */
1431
+ [Symbol.dispose]() {
1432
+ this.native[Symbol.dispose]();
1433
+ }
1434
+ }
1435
+ //# sourceMappingURL=frame.js.map