node-av 0.0.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.
- package/CHANGELOG.md +8 -0
- package/LICENSE.md +22 -0
- package/README.md +377 -0
- package/binding.gyp +78 -0
- package/dist/api/bitstream-filter.d.ts +246 -0
- package/dist/api/bitstream-filter.js +369 -0
- package/dist/api/bitstream-filter.js.map +1 -0
- package/dist/api/decoder.d.ts +257 -0
- package/dist/api/decoder.js +424 -0
- package/dist/api/decoder.js.map +1 -0
- package/dist/api/encoder.d.ts +298 -0
- package/dist/api/encoder.js +574 -0
- package/dist/api/encoder.js.map +1 -0
- package/dist/api/filter.d.ts +457 -0
- package/dist/api/filter.js +876 -0
- package/dist/api/filter.js.map +1 -0
- package/dist/api/hardware.d.ts +318 -0
- package/dist/api/hardware.js +558 -0
- package/dist/api/hardware.js.map +1 -0
- package/dist/api/index.d.ts +12 -0
- package/dist/api/index.js +20 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/io-stream.d.ts +109 -0
- package/dist/api/io-stream.js +124 -0
- package/dist/api/io-stream.js.map +1 -0
- package/dist/api/media-input.d.ts +295 -0
- package/dist/api/media-input.js +456 -0
- package/dist/api/media-input.js.map +1 -0
- package/dist/api/media-output.d.ts +274 -0
- package/dist/api/media-output.js +486 -0
- package/dist/api/media-output.js.map +1 -0
- package/dist/api/pipeline.d.ts +117 -0
- package/dist/api/pipeline.js +836 -0
- package/dist/api/pipeline.js.map +1 -0
- package/dist/api/types.d.ts +440 -0
- package/dist/api/types.js +2 -0
- package/dist/api/types.js.map +1 -0
- package/dist/api/utilities/audio-sample.d.ts +115 -0
- package/dist/api/utilities/audio-sample.js +110 -0
- package/dist/api/utilities/audio-sample.js.map +1 -0
- package/dist/api/utilities/channel-layout.d.ts +83 -0
- package/dist/api/utilities/channel-layout.js +87 -0
- package/dist/api/utilities/channel-layout.js.map +1 -0
- package/dist/api/utilities/image.d.ts +177 -0
- package/dist/api/utilities/image.js +183 -0
- package/dist/api/utilities/image.js.map +1 -0
- package/dist/api/utilities/index.d.ts +8 -0
- package/dist/api/utilities/index.js +17 -0
- package/dist/api/utilities/index.js.map +1 -0
- package/dist/api/utilities/media-type.d.ts +56 -0
- package/dist/api/utilities/media-type.js +60 -0
- package/dist/api/utilities/media-type.js.map +1 -0
- package/dist/api/utilities/pixel-format.d.ts +94 -0
- package/dist/api/utilities/pixel-format.js +102 -0
- package/dist/api/utilities/pixel-format.js.map +1 -0
- package/dist/api/utilities/sample-format.d.ts +132 -0
- package/dist/api/utilities/sample-format.js +144 -0
- package/dist/api/utilities/sample-format.js.map +1 -0
- package/dist/api/utilities/streaming.d.ts +104 -0
- package/dist/api/utilities/streaming.js +137 -0
- package/dist/api/utilities/streaming.js.map +1 -0
- package/dist/api/utilities/timestamp.d.ts +187 -0
- package/dist/api/utilities/timestamp.js +200 -0
- package/dist/api/utilities/timestamp.js.map +1 -0
- package/dist/api/utils.d.ts +61 -0
- package/dist/api/utils.js +330 -0
- package/dist/api/utils.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/audio-fifo.d.ts +339 -0
- package/dist/lib/audio-fifo.js +365 -0
- package/dist/lib/audio-fifo.js.map +1 -0
- package/dist/lib/binding.d.ts +192 -0
- package/dist/lib/binding.js +70 -0
- package/dist/lib/binding.js.map +1 -0
- package/dist/lib/bitstream-filter-context.d.ts +345 -0
- package/dist/lib/bitstream-filter-context.js +407 -0
- package/dist/lib/bitstream-filter-context.js.map +1 -0
- package/dist/lib/bitstream-filter.d.ts +124 -0
- package/dist/lib/bitstream-filter.js +138 -0
- package/dist/lib/bitstream-filter.js.map +1 -0
- package/dist/lib/channel-layouts.d.ts +51 -0
- package/dist/lib/channel-layouts.js +55 -0
- package/dist/lib/channel-layouts.js.map +1 -0
- package/dist/lib/codec-context.d.ts +763 -0
- package/dist/lib/codec-context.js +974 -0
- package/dist/lib/codec-context.js.map +1 -0
- package/dist/lib/codec-parameters.d.ts +362 -0
- package/dist/lib/codec-parameters.js +460 -0
- package/dist/lib/codec-parameters.js.map +1 -0
- package/dist/lib/codec-parser.d.ts +185 -0
- package/dist/lib/codec-parser.js +193 -0
- package/dist/lib/codec-parser.js.map +1 -0
- package/dist/lib/codec.d.ts +432 -0
- package/dist/lib/codec.js +492 -0
- package/dist/lib/codec.js.map +1 -0
- package/dist/lib/constants.d.ts +2037 -0
- package/dist/lib/constants.js +1659 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/dictionary.d.ts +371 -0
- package/dist/lib/dictionary.js +406 -0
- package/dist/lib/dictionary.js.map +1 -0
- package/dist/lib/error.d.ts +216 -0
- package/dist/lib/error.js +254 -0
- package/dist/lib/error.js.map +1 -0
- package/dist/lib/filter-context.d.ts +445 -0
- package/dist/lib/filter-context.js +505 -0
- package/dist/lib/filter-context.js.map +1 -0
- package/dist/lib/filter-graph.d.ts +556 -0
- package/dist/lib/filter-graph.js +608 -0
- package/dist/lib/filter-graph.js.map +1 -0
- package/dist/lib/filter-inout.d.ts +205 -0
- package/dist/lib/filter-inout.js +264 -0
- package/dist/lib/filter-inout.js.map +1 -0
- package/dist/lib/filter.d.ts +231 -0
- package/dist/lib/filter.js +260 -0
- package/dist/lib/filter.js.map +1 -0
- package/dist/lib/format-context.d.ts +798 -0
- package/dist/lib/format-context.js +845 -0
- package/dist/lib/format-context.js.map +1 -0
- package/dist/lib/frame.d.ts +784 -0
- package/dist/lib/frame.js +933 -0
- package/dist/lib/frame.js.map +1 -0
- package/dist/lib/hardware-device-context.d.ts +407 -0
- package/dist/lib/hardware-device-context.js +429 -0
- package/dist/lib/hardware-device-context.js.map +1 -0
- package/dist/lib/hardware-frames-context.d.ts +374 -0
- package/dist/lib/hardware-frames-context.js +430 -0
- package/dist/lib/hardware-frames-context.js.map +1 -0
- package/dist/lib/index.d.ts +31 -0
- package/dist/lib/index.js +54 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/input-format.d.ts +216 -0
- package/dist/lib/input-format.js +246 -0
- package/dist/lib/input-format.js.map +1 -0
- package/dist/lib/io-context.d.ts +495 -0
- package/dist/lib/io-context.js +550 -0
- package/dist/lib/io-context.js.map +1 -0
- package/dist/lib/log.d.ts +201 -0
- package/dist/lib/log.js +219 -0
- package/dist/lib/log.js.map +1 -0
- package/dist/lib/native-types.d.ts +719 -0
- package/dist/lib/native-types.js +2 -0
- package/dist/lib/native-types.js.map +1 -0
- package/dist/lib/option.d.ts +589 -0
- package/dist/lib/option.js +853 -0
- package/dist/lib/option.js.map +1 -0
- package/dist/lib/output-format.d.ts +179 -0
- package/dist/lib/output-format.js +205 -0
- package/dist/lib/output-format.js.map +1 -0
- package/dist/lib/packet.d.ts +487 -0
- package/dist/lib/packet.js +558 -0
- package/dist/lib/packet.js.map +1 -0
- package/dist/lib/rational.d.ts +210 -0
- package/dist/lib/rational.js +233 -0
- package/dist/lib/rational.js.map +1 -0
- package/dist/lib/software-resample-context.d.ts +572 -0
- package/dist/lib/software-resample-context.js +610 -0
- package/dist/lib/software-resample-context.js.map +1 -0
- package/dist/lib/software-scale-context.d.ts +290 -0
- package/dist/lib/software-scale-context.js +308 -0
- package/dist/lib/software-scale-context.js.map +1 -0
- package/dist/lib/stream.d.ts +322 -0
- package/dist/lib/stream.js +408 -0
- package/dist/lib/stream.js.map +1 -0
- package/dist/lib/types.d.ts +59 -0
- package/dist/lib/types.js +8 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/utilities.d.ts +346 -0
- package/dist/lib/utilities.js +424 -0
- package/dist/lib/utilities.js.map +1 -0
- package/install/check.js +113 -0
- package/install/ffmpeg.js +163 -0
- package/package.json +107 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decoder - High-level wrapper for media decoding
|
|
3
|
+
*
|
|
4
|
+
* Simplifies FFmpeg's decoding API with automatic codec selection,
|
|
5
|
+
* parameter configuration, and frame management.
|
|
6
|
+
*
|
|
7
|
+
* Handles codec initialization, packet decoding, and frame output.
|
|
8
|
+
* Supports hardware acceleration and zero-copy transcoding.
|
|
9
|
+
*
|
|
10
|
+
* @module api/decoder
|
|
11
|
+
*/
|
|
12
|
+
import { CodecContext, Frame } from '../lib/index.js';
|
|
13
|
+
import type { Packet, Stream } from '../lib/index.js';
|
|
14
|
+
import type { DecoderOptions } from './types.js';
|
|
15
|
+
/**
|
|
16
|
+
* High-level decoder for media streams.
|
|
17
|
+
*
|
|
18
|
+
* Handles codec initialization, packet decoding, and frame output.
|
|
19
|
+
* Designed for simple, efficient decoding workflows.
|
|
20
|
+
*
|
|
21
|
+
* Manages codec context lifecycle and provides automatic cleanup.
|
|
22
|
+
* Supports hardware acceleration with zero-copy frame sharing.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* // Create decoder for video stream
|
|
27
|
+
* const media = await MediaInput.open('video.mp4');
|
|
28
|
+
* const stream = media.video(); // Get video stream
|
|
29
|
+
* const decoder = await Decoder.create(stream);
|
|
30
|
+
*
|
|
31
|
+
* // Decode packets
|
|
32
|
+
* for await (const packet of media.packets()) {
|
|
33
|
+
* if (packet.streamIndex === stream.index) {
|
|
34
|
+
* const frame = await decoder.decode(packet);
|
|
35
|
+
* if (frame) {
|
|
36
|
+
* console.log(`Decoded frame: ${frame.width}x${frame.height}`);
|
|
37
|
+
* // Process frame...
|
|
38
|
+
* }
|
|
39
|
+
* }
|
|
40
|
+
* }
|
|
41
|
+
*
|
|
42
|
+
* // Flush decoder
|
|
43
|
+
* const lastFrame = await decoder.flush();
|
|
44
|
+
* decoder.close();
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* // With hardware acceleration
|
|
50
|
+
* const hw = await HardwareContext.auto();
|
|
51
|
+
* const stream = media.video();
|
|
52
|
+
* const decoder = await Decoder.create(stream, {
|
|
53
|
+
* hardware: hw
|
|
54
|
+
* });
|
|
55
|
+
* // ... use decoder
|
|
56
|
+
* decoder.close();
|
|
57
|
+
* hw?.dispose(); // Safe to call again (no-op)
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare class Decoder implements Disposable {
|
|
61
|
+
private codecContext;
|
|
62
|
+
private frame;
|
|
63
|
+
private streamIndex;
|
|
64
|
+
private stream;
|
|
65
|
+
private isOpen;
|
|
66
|
+
private hardware?;
|
|
67
|
+
/**
|
|
68
|
+
* Private constructor - use Decoder.create() instead.
|
|
69
|
+
*
|
|
70
|
+
* Initializes the decoder with a codec context and allocates a frame buffer.
|
|
71
|
+
*
|
|
72
|
+
* @param codecContext - Initialized codec context
|
|
73
|
+
* @param stream - The stream this decoder is for
|
|
74
|
+
* @param hardware - Optional hardware context for auto-sharing frames context
|
|
75
|
+
*/
|
|
76
|
+
private constructor();
|
|
77
|
+
/**
|
|
78
|
+
* Create a decoder for a specific stream.
|
|
79
|
+
*
|
|
80
|
+
* Factory method that handles codec discovery, context setup,
|
|
81
|
+
* and initialization.
|
|
82
|
+
*
|
|
83
|
+
* Uses avcodec_find_decoder() to locate the appropriate codec,
|
|
84
|
+
* then initializes and opens the codec context.
|
|
85
|
+
*
|
|
86
|
+
* @param stream - Stream to decode
|
|
87
|
+
* @param options - Decoder configuration options
|
|
88
|
+
*
|
|
89
|
+
* @returns Promise resolving to configured Decoder
|
|
90
|
+
*
|
|
91
|
+
* @throws {Error} If codec unavailable
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const media = await MediaInput.open('video.mp4');
|
|
96
|
+
* const stream = media.video();
|
|
97
|
+
* const decoder = await Decoder.create(stream);
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
static create(stream: Stream, options?: DecoderOptions): Promise<Decoder>;
|
|
101
|
+
/**
|
|
102
|
+
* Check if decoder is open.
|
|
103
|
+
*/
|
|
104
|
+
get isDecoderOpen(): boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Decode a packet and return a frame if available.
|
|
107
|
+
*
|
|
108
|
+
* Sends packet to decoder and attempts to receive a frame.
|
|
109
|
+
* May return null if decoder needs more data.
|
|
110
|
+
*
|
|
111
|
+
* Uses avcodec_send_packet() and avcodec_receive_frame() internally.
|
|
112
|
+
* The decoder may buffer packets before producing frames.
|
|
113
|
+
*
|
|
114
|
+
* @param packet - Packet to decode
|
|
115
|
+
*
|
|
116
|
+
* @returns Promise resolving to Frame or null
|
|
117
|
+
*
|
|
118
|
+
* @throws {Error} If decoder is closed or decode fails
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```typescript
|
|
122
|
+
* const frame = await decoder.decode(packet);
|
|
123
|
+
* if (frame) {
|
|
124
|
+
* // Process frame
|
|
125
|
+
* }
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
decode(packet: Packet): Promise<Frame | null>;
|
|
129
|
+
/**
|
|
130
|
+
* Flush decoder and get remaining frames.
|
|
131
|
+
*
|
|
132
|
+
* Sends null packet to trigger flush mode.
|
|
133
|
+
* Call repeatedly until it returns null.
|
|
134
|
+
*
|
|
135
|
+
* Uses avcodec_send_packet(NULL) to signal end of stream.
|
|
136
|
+
* Retrieves buffered frames from the decoder.
|
|
137
|
+
*
|
|
138
|
+
* @returns Promise resolving to Frame or null
|
|
139
|
+
*
|
|
140
|
+
* @throws {Error} If decoder is closed
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* // Flush all remaining frames
|
|
145
|
+
* let frame;
|
|
146
|
+
* while ((frame = await decoder.flush()) !== null) {
|
|
147
|
+
* // Process final frames
|
|
148
|
+
* }
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
flush(): Promise<Frame | null>;
|
|
152
|
+
/**
|
|
153
|
+
* Flush decoder and yield all remaining frames as a generator.
|
|
154
|
+
*
|
|
155
|
+
* More convenient than calling flush() in a loop.
|
|
156
|
+
* Automatically sends flush signal and yields all buffered frames.
|
|
157
|
+
*
|
|
158
|
+
* IMPORTANT: The yielded frames MUST be freed by the caller!
|
|
159
|
+
* Use 'using' statement or manually call frame.free() to avoid memory leaks.
|
|
160
|
+
*
|
|
161
|
+
* @returns Async generator of remaining frames
|
|
162
|
+
*
|
|
163
|
+
* @throws {Error} If decoder is closed
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```typescript
|
|
167
|
+
* // Process all remaining frames with generator
|
|
168
|
+
* for await (const frame of decoder.flushFrames()) {
|
|
169
|
+
* // Process final frame
|
|
170
|
+
* using _ = frame; // Auto cleanup
|
|
171
|
+
* }
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
flushFrames(): AsyncGenerator<Frame>;
|
|
175
|
+
/**
|
|
176
|
+
* Async iterator that decodes packets and yields frames.
|
|
177
|
+
*
|
|
178
|
+
* Filters packets for this decoder's stream and yields decoded frames.
|
|
179
|
+
* Automatically handles packet cleanup and decoder flushing.
|
|
180
|
+
*
|
|
181
|
+
* Processes packets in sequence, decoding each and yielding frames.
|
|
182
|
+
* After all packets are processed, flushes the decoder for remaining frames.
|
|
183
|
+
*
|
|
184
|
+
* IMPORTANT: The yielded frames MUST be freed by the caller!
|
|
185
|
+
* Use 'using' statement or manually call frame.free() to avoid memory leaks.
|
|
186
|
+
*
|
|
187
|
+
* @param packets - Async iterable of packets (e.g., from MediaInput.packets())
|
|
188
|
+
*
|
|
189
|
+
* @yields Decoded frames (ownership transferred to caller)
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```typescript
|
|
193
|
+
* // RECOMMENDED: Use 'using' for automatic cleanup
|
|
194
|
+
* for await (using frame of decoder.frames(media.packets())) {
|
|
195
|
+
* console.log(`Frame: ${frame.width}x${frame.height}`);
|
|
196
|
+
* // Frame is automatically freed at end of iteration
|
|
197
|
+
* }
|
|
198
|
+
*
|
|
199
|
+
* // OR: Manual cleanup
|
|
200
|
+
* for await (const frame of decoder.frames(media.packets())) {
|
|
201
|
+
* console.log(`Frame: ${frame.width}x${frame.height}`);
|
|
202
|
+
* // Process frame...
|
|
203
|
+
* frame.free(); // MUST call free()!
|
|
204
|
+
* }
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
frames(packets: AsyncIterable<Packet>): AsyncGenerator<Frame>;
|
|
208
|
+
/**
|
|
209
|
+
* Close decoder and free resources.
|
|
210
|
+
*
|
|
211
|
+
* After closing, the decoder cannot be used again.
|
|
212
|
+
*
|
|
213
|
+
* Frees the frame buffer and codec context.
|
|
214
|
+
* Note: Does NOT dispose the HardwareContext - caller is responsible for that.
|
|
215
|
+
*/
|
|
216
|
+
close(): void;
|
|
217
|
+
/**
|
|
218
|
+
* Get the stream index this decoder is for.
|
|
219
|
+
*/
|
|
220
|
+
getStreamIndex(): number;
|
|
221
|
+
/**
|
|
222
|
+
* Get the original stream this decoder was created from.
|
|
223
|
+
* Used for stream-copy operations in pipeline.
|
|
224
|
+
*/
|
|
225
|
+
getStream(): Stream;
|
|
226
|
+
/**
|
|
227
|
+
* Get codec context for advanced configuration.
|
|
228
|
+
*
|
|
229
|
+
* Use with caution - direct manipulation may cause issues.
|
|
230
|
+
*
|
|
231
|
+
* Provides access to the underlying AVCodecContext for advanced operations.
|
|
232
|
+
*
|
|
233
|
+
* @returns CodecContext or null if closed
|
|
234
|
+
*
|
|
235
|
+
* @internal
|
|
236
|
+
*/
|
|
237
|
+
getCodecContext(): CodecContext | null;
|
|
238
|
+
/**
|
|
239
|
+
* Receive a frame from the decoder (internal).
|
|
240
|
+
*
|
|
241
|
+
* Internal method to receive decoded frames without conversion.
|
|
242
|
+
*
|
|
243
|
+
* Uses avcodec_receive_frame() to get decoded frames from the codec.
|
|
244
|
+
* Clones the frame for the user to prevent internal buffer corruption.
|
|
245
|
+
*
|
|
246
|
+
* @returns Frame or null if no frame available
|
|
247
|
+
* @internal
|
|
248
|
+
*/
|
|
249
|
+
private receiveFrameInternal;
|
|
250
|
+
/**
|
|
251
|
+
* Symbol.dispose for automatic cleanup.
|
|
252
|
+
*
|
|
253
|
+
* Implements the Disposable interface for automatic resource management.
|
|
254
|
+
* Calls close() to free all resources.
|
|
255
|
+
*/
|
|
256
|
+
[Symbol.dispose](): void;
|
|
257
|
+
}
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decoder - High-level wrapper for media decoding
|
|
3
|
+
*
|
|
4
|
+
* Simplifies FFmpeg's decoding API with automatic codec selection,
|
|
5
|
+
* parameter configuration, and frame management.
|
|
6
|
+
*
|
|
7
|
+
* Handles codec initialization, packet decoding, and frame output.
|
|
8
|
+
* Supports hardware acceleration and zero-copy transcoding.
|
|
9
|
+
*
|
|
10
|
+
* @module api/decoder
|
|
11
|
+
*/
|
|
12
|
+
import { AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX, AVERROR_EAGAIN, AVERROR_EOF, Codec, CodecContext, FFmpegError, Frame } from '../lib/index.js';
|
|
13
|
+
/**
|
|
14
|
+
* High-level decoder for media streams.
|
|
15
|
+
*
|
|
16
|
+
* Handles codec initialization, packet decoding, and frame output.
|
|
17
|
+
* Designed for simple, efficient decoding workflows.
|
|
18
|
+
*
|
|
19
|
+
* Manages codec context lifecycle and provides automatic cleanup.
|
|
20
|
+
* Supports hardware acceleration with zero-copy frame sharing.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Create decoder for video stream
|
|
25
|
+
* const media = await MediaInput.open('video.mp4');
|
|
26
|
+
* const stream = media.video(); // Get video stream
|
|
27
|
+
* const decoder = await Decoder.create(stream);
|
|
28
|
+
*
|
|
29
|
+
* // Decode packets
|
|
30
|
+
* for await (const packet of media.packets()) {
|
|
31
|
+
* if (packet.streamIndex === stream.index) {
|
|
32
|
+
* const frame = await decoder.decode(packet);
|
|
33
|
+
* if (frame) {
|
|
34
|
+
* console.log(`Decoded frame: ${frame.width}x${frame.height}`);
|
|
35
|
+
* // Process frame...
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
*
|
|
40
|
+
* // Flush decoder
|
|
41
|
+
* const lastFrame = await decoder.flush();
|
|
42
|
+
* decoder.close();
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* // With hardware acceleration
|
|
48
|
+
* const hw = await HardwareContext.auto();
|
|
49
|
+
* const stream = media.video();
|
|
50
|
+
* const decoder = await Decoder.create(stream, {
|
|
51
|
+
* hardware: hw
|
|
52
|
+
* });
|
|
53
|
+
* // ... use decoder
|
|
54
|
+
* decoder.close();
|
|
55
|
+
* hw?.dispose(); // Safe to call again (no-op)
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export class Decoder {
|
|
59
|
+
codecContext;
|
|
60
|
+
frame;
|
|
61
|
+
streamIndex;
|
|
62
|
+
stream;
|
|
63
|
+
isOpen = true;
|
|
64
|
+
hardware; // Reference to hardware context for auto-sharing frames context
|
|
65
|
+
/**
|
|
66
|
+
* Private constructor - use Decoder.create() instead.
|
|
67
|
+
*
|
|
68
|
+
* Initializes the decoder with a codec context and allocates a frame buffer.
|
|
69
|
+
*
|
|
70
|
+
* @param codecContext - Initialized codec context
|
|
71
|
+
* @param stream - The stream this decoder is for
|
|
72
|
+
* @param hardware - Optional hardware context for auto-sharing frames context
|
|
73
|
+
*/
|
|
74
|
+
constructor(codecContext, stream, hardware) {
|
|
75
|
+
this.codecContext = codecContext;
|
|
76
|
+
this.stream = stream;
|
|
77
|
+
this.streamIndex = stream.index;
|
|
78
|
+
this.hardware = hardware;
|
|
79
|
+
this.frame = new Frame();
|
|
80
|
+
this.frame.alloc();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Create a decoder for a specific stream.
|
|
84
|
+
*
|
|
85
|
+
* Factory method that handles codec discovery, context setup,
|
|
86
|
+
* and initialization.
|
|
87
|
+
*
|
|
88
|
+
* Uses avcodec_find_decoder() to locate the appropriate codec,
|
|
89
|
+
* then initializes and opens the codec context.
|
|
90
|
+
*
|
|
91
|
+
* @param stream - Stream to decode
|
|
92
|
+
* @param options - Decoder configuration options
|
|
93
|
+
*
|
|
94
|
+
* @returns Promise resolving to configured Decoder
|
|
95
|
+
*
|
|
96
|
+
* @throws {Error} If codec unavailable
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* const media = await MediaInput.open('video.mp4');
|
|
101
|
+
* const stream = media.video();
|
|
102
|
+
* const decoder = await Decoder.create(stream);
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
static async create(stream, options = {}) {
|
|
106
|
+
if (!stream) {
|
|
107
|
+
throw new Error('Stream is required');
|
|
108
|
+
}
|
|
109
|
+
// Find decoder for this codec
|
|
110
|
+
const codec = Codec.findDecoder(stream.codecpar.codecId);
|
|
111
|
+
if (!codec) {
|
|
112
|
+
throw new Error(`Decoder not found for codec ${stream.codecpar.codecId}`);
|
|
113
|
+
}
|
|
114
|
+
// Allocate and configure codec context
|
|
115
|
+
const codecContext = new CodecContext();
|
|
116
|
+
codecContext.allocContext3(codec);
|
|
117
|
+
// Copy codec parameters to context
|
|
118
|
+
const ret = codecContext.parametersToContext(stream.codecpar);
|
|
119
|
+
if (ret < 0) {
|
|
120
|
+
codecContext.freeContext();
|
|
121
|
+
FFmpegError.throwIfError(ret, 'Failed to copy codec parameters');
|
|
122
|
+
}
|
|
123
|
+
// Set packet time base
|
|
124
|
+
codecContext.pktTimebase = stream.timeBase;
|
|
125
|
+
// Apply options
|
|
126
|
+
if (options.threads !== undefined) {
|
|
127
|
+
codecContext.threadCount = options.threads;
|
|
128
|
+
}
|
|
129
|
+
// Check if this decoder supports hardware acceleration
|
|
130
|
+
let supportsHardware = false;
|
|
131
|
+
if (options.hardware) {
|
|
132
|
+
// Check decoder's hardware configurations
|
|
133
|
+
for (let i = 0;; i++) {
|
|
134
|
+
const config = codec.getHwConfig(i);
|
|
135
|
+
if (!config)
|
|
136
|
+
break;
|
|
137
|
+
// Check if decoder supports HW_DEVICE_CTX method with matching device type
|
|
138
|
+
if ((config.methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) !== 0 && config.deviceType === options.hardware.deviceType) {
|
|
139
|
+
supportsHardware = true;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Only apply hardware acceleration if the decoder supports it
|
|
144
|
+
if (supportsHardware) {
|
|
145
|
+
codecContext.hwDeviceCtx = options.hardware.deviceContext;
|
|
146
|
+
}
|
|
147
|
+
// Silently ignore hardware for software decoders
|
|
148
|
+
}
|
|
149
|
+
// Apply codec-specific options via AVOptions
|
|
150
|
+
if (options.options) {
|
|
151
|
+
for (const [key, value] of Object.entries(options.options)) {
|
|
152
|
+
codecContext.setOption(key, value.toString());
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Open codec
|
|
156
|
+
const openRet = await codecContext.open2(codec, null);
|
|
157
|
+
if (openRet < 0) {
|
|
158
|
+
codecContext.freeContext();
|
|
159
|
+
FFmpegError.throwIfError(openRet, 'Failed to open codec');
|
|
160
|
+
}
|
|
161
|
+
const decoder = new Decoder(codecContext, stream, options.hardware);
|
|
162
|
+
return decoder;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Check if decoder is open.
|
|
166
|
+
*/
|
|
167
|
+
get isDecoderOpen() {
|
|
168
|
+
return this.isOpen;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Decode a packet and return a frame if available.
|
|
172
|
+
*
|
|
173
|
+
* Sends packet to decoder and attempts to receive a frame.
|
|
174
|
+
* May return null if decoder needs more data.
|
|
175
|
+
*
|
|
176
|
+
* Uses avcodec_send_packet() and avcodec_receive_frame() internally.
|
|
177
|
+
* The decoder may buffer packets before producing frames.
|
|
178
|
+
*
|
|
179
|
+
* @param packet - Packet to decode
|
|
180
|
+
*
|
|
181
|
+
* @returns Promise resolving to Frame or null
|
|
182
|
+
*
|
|
183
|
+
* @throws {Error} If decoder is closed or decode fails
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```typescript
|
|
187
|
+
* const frame = await decoder.decode(packet);
|
|
188
|
+
* if (frame) {
|
|
189
|
+
* // Process frame
|
|
190
|
+
* }
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
async decode(packet) {
|
|
194
|
+
if (!this.isOpen) {
|
|
195
|
+
throw new Error('Decoder is closed');
|
|
196
|
+
}
|
|
197
|
+
// Send packet to decoder
|
|
198
|
+
const sendRet = await this.codecContext.sendPacket(packet);
|
|
199
|
+
if (sendRet < 0 && sendRet !== AVERROR_EOF) {
|
|
200
|
+
// Decoder might be full, try to receive first
|
|
201
|
+
const frame = await this.receiveFrameInternal();
|
|
202
|
+
if (frame) {
|
|
203
|
+
return frame;
|
|
204
|
+
}
|
|
205
|
+
// If still failing, it's an error
|
|
206
|
+
if (sendRet !== AVERROR_EAGAIN) {
|
|
207
|
+
FFmpegError.throwIfError(sendRet, 'Failed to send packet');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Try to receive frame
|
|
211
|
+
const frame = await this.receiveFrameInternal();
|
|
212
|
+
return frame;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Flush decoder and get remaining frames.
|
|
216
|
+
*
|
|
217
|
+
* Sends null packet to trigger flush mode.
|
|
218
|
+
* Call repeatedly until it returns null.
|
|
219
|
+
*
|
|
220
|
+
* Uses avcodec_send_packet(NULL) to signal end of stream.
|
|
221
|
+
* Retrieves buffered frames from the decoder.
|
|
222
|
+
*
|
|
223
|
+
* @returns Promise resolving to Frame or null
|
|
224
|
+
*
|
|
225
|
+
* @throws {Error} If decoder is closed
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```typescript
|
|
229
|
+
* // Flush all remaining frames
|
|
230
|
+
* let frame;
|
|
231
|
+
* while ((frame = await decoder.flush()) !== null) {
|
|
232
|
+
* // Process final frames
|
|
233
|
+
* }
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
async flush() {
|
|
237
|
+
if (!this.isOpen) {
|
|
238
|
+
throw new Error('Decoder is closed');
|
|
239
|
+
}
|
|
240
|
+
// Send flush packet (null)
|
|
241
|
+
await this.codecContext.sendPacket(null);
|
|
242
|
+
// Receive frame
|
|
243
|
+
const frame = await this.receiveFrameInternal();
|
|
244
|
+
return frame;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Flush decoder and yield all remaining frames as a generator.
|
|
248
|
+
*
|
|
249
|
+
* More convenient than calling flush() in a loop.
|
|
250
|
+
* Automatically sends flush signal and yields all buffered frames.
|
|
251
|
+
*
|
|
252
|
+
* IMPORTANT: The yielded frames MUST be freed by the caller!
|
|
253
|
+
* Use 'using' statement or manually call frame.free() to avoid memory leaks.
|
|
254
|
+
*
|
|
255
|
+
* @returns Async generator of remaining frames
|
|
256
|
+
*
|
|
257
|
+
* @throws {Error} If decoder is closed
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```typescript
|
|
261
|
+
* // Process all remaining frames with generator
|
|
262
|
+
* for await (const frame of decoder.flushFrames()) {
|
|
263
|
+
* // Process final frame
|
|
264
|
+
* using _ = frame; // Auto cleanup
|
|
265
|
+
* }
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
async *flushFrames() {
|
|
269
|
+
if (!this.isOpen) {
|
|
270
|
+
throw new Error('Decoder is closed');
|
|
271
|
+
}
|
|
272
|
+
let frame;
|
|
273
|
+
while ((frame = await this.flush()) !== null) {
|
|
274
|
+
yield frame;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Async iterator that decodes packets and yields frames.
|
|
279
|
+
*
|
|
280
|
+
* Filters packets for this decoder's stream and yields decoded frames.
|
|
281
|
+
* Automatically handles packet cleanup and decoder flushing.
|
|
282
|
+
*
|
|
283
|
+
* Processes packets in sequence, decoding each and yielding frames.
|
|
284
|
+
* After all packets are processed, flushes the decoder for remaining frames.
|
|
285
|
+
*
|
|
286
|
+
* IMPORTANT: The yielded frames MUST be freed by the caller!
|
|
287
|
+
* Use 'using' statement or manually call frame.free() to avoid memory leaks.
|
|
288
|
+
*
|
|
289
|
+
* @param packets - Async iterable of packets (e.g., from MediaInput.packets())
|
|
290
|
+
*
|
|
291
|
+
* @yields Decoded frames (ownership transferred to caller)
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```typescript
|
|
295
|
+
* // RECOMMENDED: Use 'using' for automatic cleanup
|
|
296
|
+
* for await (using frame of decoder.frames(media.packets())) {
|
|
297
|
+
* console.log(`Frame: ${frame.width}x${frame.height}`);
|
|
298
|
+
* // Frame is automatically freed at end of iteration
|
|
299
|
+
* }
|
|
300
|
+
*
|
|
301
|
+
* // OR: Manual cleanup
|
|
302
|
+
* for await (const frame of decoder.frames(media.packets())) {
|
|
303
|
+
* console.log(`Frame: ${frame.width}x${frame.height}`);
|
|
304
|
+
* // Process frame...
|
|
305
|
+
* frame.free(); // MUST call free()!
|
|
306
|
+
* }
|
|
307
|
+
* ```
|
|
308
|
+
*/
|
|
309
|
+
async *frames(packets) {
|
|
310
|
+
if (!this.isOpen) {
|
|
311
|
+
throw new Error('Decoder is closed');
|
|
312
|
+
}
|
|
313
|
+
// Process packets
|
|
314
|
+
for await (const packet of packets) {
|
|
315
|
+
try {
|
|
316
|
+
// Only process packets for our stream
|
|
317
|
+
if (packet.streamIndex === this.streamIndex) {
|
|
318
|
+
const frame = await this.decode(packet);
|
|
319
|
+
if (frame) {
|
|
320
|
+
yield frame;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
finally {
|
|
325
|
+
// Free the input packet after processing
|
|
326
|
+
packet.free();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
// Flush decoder after all packets
|
|
330
|
+
let frame;
|
|
331
|
+
while ((frame = await this.flush()) !== null) {
|
|
332
|
+
yield frame;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Close decoder and free resources.
|
|
337
|
+
*
|
|
338
|
+
* After closing, the decoder cannot be used again.
|
|
339
|
+
*
|
|
340
|
+
* Frees the frame buffer and codec context.
|
|
341
|
+
* Note: Does NOT dispose the HardwareContext - caller is responsible for that.
|
|
342
|
+
*/
|
|
343
|
+
close() {
|
|
344
|
+
if (!this.isOpen)
|
|
345
|
+
return;
|
|
346
|
+
this.frame.free();
|
|
347
|
+
this.codecContext.freeContext();
|
|
348
|
+
// NOTE: We do NOT dispose the hardware context here
|
|
349
|
+
// The caller who created the HardwareContext is responsible for disposing it
|
|
350
|
+
// This allows reusing the same HardwareContext for multiple decoders
|
|
351
|
+
this.isOpen = false;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Get the stream index this decoder is for.
|
|
355
|
+
*/
|
|
356
|
+
getStreamIndex() {
|
|
357
|
+
return this.streamIndex;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Get the original stream this decoder was created from.
|
|
361
|
+
* Used for stream-copy operations in pipeline.
|
|
362
|
+
*/
|
|
363
|
+
getStream() {
|
|
364
|
+
return this.stream;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Get codec context for advanced configuration.
|
|
368
|
+
*
|
|
369
|
+
* Use with caution - direct manipulation may cause issues.
|
|
370
|
+
*
|
|
371
|
+
* Provides access to the underlying AVCodecContext for advanced operations.
|
|
372
|
+
*
|
|
373
|
+
* @returns CodecContext or null if closed
|
|
374
|
+
*
|
|
375
|
+
* @internal
|
|
376
|
+
*/
|
|
377
|
+
getCodecContext() {
|
|
378
|
+
return this.isOpen ? this.codecContext : null;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Receive a frame from the decoder (internal).
|
|
382
|
+
*
|
|
383
|
+
* Internal method to receive decoded frames without conversion.
|
|
384
|
+
*
|
|
385
|
+
* Uses avcodec_receive_frame() to get decoded frames from the codec.
|
|
386
|
+
* Clones the frame for the user to prevent internal buffer corruption.
|
|
387
|
+
*
|
|
388
|
+
* @returns Frame or null if no frame available
|
|
389
|
+
* @internal
|
|
390
|
+
*/
|
|
391
|
+
async receiveFrameInternal() {
|
|
392
|
+
// Clear previous frame data
|
|
393
|
+
this.frame.unref();
|
|
394
|
+
const ret = await this.codecContext.receiveFrame(this.frame);
|
|
395
|
+
if (ret === 0) {
|
|
396
|
+
// Set hw_frames_ctx from frame for other components to share
|
|
397
|
+
// This is THE moment when hw_frames_ctx becomes available
|
|
398
|
+
if (this.hardware && this.frame.hwFramesCtx) {
|
|
399
|
+
this.hardware.framesContext = this.frame.hwFramesCtx;
|
|
400
|
+
}
|
|
401
|
+
// Got a frame, clone it for the user
|
|
402
|
+
return this.frame.clone();
|
|
403
|
+
}
|
|
404
|
+
else if (ret === AVERROR_EAGAIN || ret === AVERROR_EOF) {
|
|
405
|
+
// Need more data or end of stream
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
// Error
|
|
410
|
+
FFmpegError.throwIfError(ret, 'Failed to receive frame');
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Symbol.dispose for automatic cleanup.
|
|
416
|
+
*
|
|
417
|
+
* Implements the Disposable interface for automatic resource management.
|
|
418
|
+
* Calls close() to free all resources.
|
|
419
|
+
*/
|
|
420
|
+
[Symbol.dispose]() {
|
|
421
|
+
this.close();
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
//# sourceMappingURL=decoder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoder.js","sourceRoot":"","sources":["../../src/api/decoder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,uCAAuC,EAAE,cAAc,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAMhJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,OAAO,OAAO;IACV,YAAY,CAAe;IAC3B,KAAK,CAAQ;IACb,WAAW,CAAS;IACpB,MAAM,CAAS;IACf,MAAM,GAAG,IAAI,CAAC;IACd,QAAQ,CAA0B,CAAC,gEAAgE;IAE3G;;;;;;;;OAQG;IACH,YAAoB,YAA0B,EAAE,MAAc,EAAE,QAAiC;QAC/F,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC;QAChC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,UAA0B,EAAE;QAC9D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,8BAA8B;QAC9B,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACzD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,+BAA+B,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5E,CAAC;QAED,uCAAuC;QACvC,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;QACxC,YAAY,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAElC,mCAAmC;QACnC,MAAM,GAAG,GAAG,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9D,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;YACZ,YAAY,CAAC,WAAW,EAAE,CAAC;YAC3B,WAAW,CAAC,YAAY,CAAC,GAAG,EAAE,iCAAiC,CAAC,CAAC;QACnE,CAAC;QAED,uBAAuB;QACvB,YAAY,CAAC,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC;QAE3C,gBAAgB;QAChB,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAClC,YAAY,CAAC,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;QAC7C,CAAC;QAED,uDAAuD;QACvD,IAAI,gBAAgB,GAAG,KAAK,CAAC;QAC7B,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,0CAA0C;YAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,GAAI,CAAC,EAAE,EAAE,CAAC;gBACtB,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;gBACpC,IAAI,CAAC,MAAM;oBAAE,MAAM;gBAEnB,2EAA2E;gBAC3E,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,uCAAuC,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;oBAC1H,gBAAgB,GAAG,IAAI,CAAC;oBACxB,MAAM;gBACR,CAAC;YACH,CAAC;YAED,8DAA8D;YAC9D,IAAI,gBAAgB,EAAE,CAAC;gBACrB,YAAY,CAAC,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;YAC5D,CAAC;YACD,iDAAiD;QACnD,CAAC;QAED,6CAA6C;QAC7C,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3D,YAAY,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;QAED,aAAa;QACb,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACtD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAChB,YAAY,CAAC,WAAW,EAAE,CAAC;YAC3B,WAAW,CAAC,YAAY,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpE,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,MAAM,CAAC,MAAc;QACzB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QAED,yBAAyB;QACzB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC3D,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;YAC3C,8CAA8C;YAC9C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAChD,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,KAAK,CAAC;YACf,CAAC;YAED,kCAAkC;YAClC,IAAI,OAAO,KAAK,cAAc,EAAE,CAAC;gBAC/B,WAAW,CAAC,YAAY,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;QAED,uBAAuB;QACvB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QAED,2BAA2B;QAC3B,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAEzC,gBAAgB;QAChB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,KAAK,CAAC,CAAC,WAAW;QAChB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QAED,IAAI,KAAK,CAAC;QACV,OAAO,CAAC,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;YAC7C,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,KAAK,CAAC,CAAC,MAAM,CAAC,OAA8B;QAC1C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QAED,kBAAkB;QAClB,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YACnC,IAAI,CAAC;gBACH,sCAAsC;gBACtC,IAAI,MAAM,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;oBAC5C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;oBACxC,IAAI,KAAK,EAAE,CAAC;wBACV,MAAM,KAAK,CAAC;oBACd,CAAC;gBACH,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,yCAAyC;gBACzC,MAAM,CAAC,IAAI,EAAE,CAAC;YAChB,CAAC;QACH,CAAC;QAED,kCAAkC;QAClC,IAAI,KAAK,CAAC;QACV,OAAO,CAAC,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;YAC7C,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QAEzB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAClB,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;QAEhC,oDAAoD;QACpD,6EAA6E;QAC7E,qEAAqE;QAErE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;;;;;;;;;OAUG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC;IAChD,CAAC;IAED;;;;;;;;;;OAUG;IACK,KAAK,CAAC,oBAAoB;QAChC,4BAA4B;QAC5B,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAEnB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE7D,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;YACd,6DAA6D;YAC7D,0DAA0D;YAC1D,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;gBAC5C,IAAI,CAAC,QAAQ,CAAC,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;YACvD,CAAC;YAED,qCAAqC;YACrC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAC5B,CAAC;aAAM,IAAI,GAAG,KAAK,cAAc,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YACzD,kCAAkC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;aAAM,CAAC;YACN,QAAQ;YACR,WAAW,CAAC,YAAY,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAC;YACzD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,CAAC,MAAM,CAAC,OAAO,CAAC;QACd,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;CACF"}
|