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,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BitStreamFilterAPI - High-level wrapper for bitstream filtering
|
|
3
|
+
*
|
|
4
|
+
* Simplifies FFmpeg's bitstream filter API with automatic initialization,
|
|
5
|
+
* parameter configuration, and packet processing.
|
|
6
|
+
*
|
|
7
|
+
* Handles filter context lifecycle, packet buffering, and flushing.
|
|
8
|
+
* Useful for format conversion, metadata extraction, and stream modifications.
|
|
9
|
+
*
|
|
10
|
+
* @module api/bitstream-filter
|
|
11
|
+
*/
|
|
12
|
+
import { Packet } from '../lib/index.js';
|
|
13
|
+
import type { Stream } from '../lib/index.js';
|
|
14
|
+
/**
|
|
15
|
+
* High-level bitstream filter for packet processing.
|
|
16
|
+
*
|
|
17
|
+
* Handles filter initialization, packet processing, and cleanup.
|
|
18
|
+
* Designed for simple, efficient packet filtering workflows.
|
|
19
|
+
*
|
|
20
|
+
* Manages filter context lifecycle and provides automatic cleanup.
|
|
21
|
+
* Supports packet-by-packet and stream processing modes.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Create filter for H.264 stream
|
|
26
|
+
* const media = await MediaInput.open('video.mp4');
|
|
27
|
+
* const stream = media.video();
|
|
28
|
+
* const bsf = await BitStreamFilterAPI.create('h264_mp4toannexb', stream);
|
|
29
|
+
*
|
|
30
|
+
* // Process packets
|
|
31
|
+
* for await (const packet of media.packets()) {
|
|
32
|
+
* if (packet.streamIndex === stream.index) {
|
|
33
|
+
* const filtered = await bsf.process(packet);
|
|
34
|
+
* for (const outPacket of filtered) {
|
|
35
|
+
* // Write to output or process further
|
|
36
|
+
* await output.writePacket(outPacket);
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
* }
|
|
40
|
+
*
|
|
41
|
+
* // Flush and cleanup
|
|
42
|
+
* const remaining = await bsf.flush();
|
|
43
|
+
* bsf.dispose();
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* // Process packet stream
|
|
49
|
+
* const bsf = await BitStreamFilterAPI.create('extract_extradata', stream);
|
|
50
|
+
*
|
|
51
|
+
* for await (const filtered of bsf.packets(media.packets())) {
|
|
52
|
+
* // Filtered packets are automatically processed
|
|
53
|
+
* await output.writePacket(filtered);
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare class BitStreamFilterAPI implements Disposable {
|
|
58
|
+
private ctx;
|
|
59
|
+
private filter;
|
|
60
|
+
private stream;
|
|
61
|
+
private isDisposed;
|
|
62
|
+
/**
|
|
63
|
+
* Private constructor - use BitStreamFilterAPI.create() instead.
|
|
64
|
+
*
|
|
65
|
+
* @param filter - The bitstream filter
|
|
66
|
+
* @param ctx - Initialized filter context
|
|
67
|
+
* @param stream - The stream this filter is for
|
|
68
|
+
*/
|
|
69
|
+
private constructor();
|
|
70
|
+
/**
|
|
71
|
+
* Create a bitstream filter for a specific stream.
|
|
72
|
+
*
|
|
73
|
+
* Factory method that handles filter discovery, context setup,
|
|
74
|
+
* and initialization.
|
|
75
|
+
*
|
|
76
|
+
* @param filterName - Name of the bitstream filter (e.g., 'h264_mp4toannexb')
|
|
77
|
+
* @param stream - Stream to filter
|
|
78
|
+
*
|
|
79
|
+
* @returns Promise resolving to configured BitStreamFilterAPI
|
|
80
|
+
*
|
|
81
|
+
* @throws {Error} If filter unavailable or initialization fails
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const media = await MediaInput.open('video.mp4');
|
|
86
|
+
* const stream = media.video();
|
|
87
|
+
* const bsf = await BitStreamFilterAPI.create('h264_mp4toannexb', stream);
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
static create(filterName: string, stream: Stream): Promise<BitStreamFilterAPI>;
|
|
91
|
+
/**
|
|
92
|
+
* Get the filter name.
|
|
93
|
+
*
|
|
94
|
+
* @returns The name of the bitstream filter
|
|
95
|
+
*/
|
|
96
|
+
get name(): string;
|
|
97
|
+
/**
|
|
98
|
+
* Get the associated stream.
|
|
99
|
+
*
|
|
100
|
+
* @returns The stream this filter was created for
|
|
101
|
+
*/
|
|
102
|
+
get streamInfo(): Stream;
|
|
103
|
+
/**
|
|
104
|
+
* Get output codec parameters.
|
|
105
|
+
*
|
|
106
|
+
* Returns the output codec parameters after filter initialization.
|
|
107
|
+
* These may differ from input parameters depending on the filter.
|
|
108
|
+
*
|
|
109
|
+
* @returns Output codec parameters, or null if not available
|
|
110
|
+
*/
|
|
111
|
+
get outputCodecParameters(): import("../lib/codec-parameters.js").CodecParameters | null;
|
|
112
|
+
/**
|
|
113
|
+
* Get output time base.
|
|
114
|
+
*
|
|
115
|
+
* Returns the output time base after filter initialization.
|
|
116
|
+
*
|
|
117
|
+
* @returns Output time base, or null if not available
|
|
118
|
+
*/
|
|
119
|
+
get outputTimeBase(): import("../lib/rational.js").Rational | null;
|
|
120
|
+
/**
|
|
121
|
+
* Process a single packet through the filter.
|
|
122
|
+
*
|
|
123
|
+
* Sends a packet to the filter and retrieves all output packets.
|
|
124
|
+
* One input packet may produce zero, one, or multiple output packets.
|
|
125
|
+
*
|
|
126
|
+
* @param packet - Packet to filter, or null to signal EOF
|
|
127
|
+
*
|
|
128
|
+
* @returns Array of filtered packets (may be empty)
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* const inputPacket = await media.readPacket();
|
|
133
|
+
* const filtered = await bsf.process(inputPacket);
|
|
134
|
+
*
|
|
135
|
+
* for (const packet of filtered) {
|
|
136
|
+
* console.log(`Filtered packet: size=${packet.size}`);
|
|
137
|
+
* await output.writePacket(packet);
|
|
138
|
+
* }
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
process(packet: Packet | null): Promise<Packet[]>;
|
|
142
|
+
/**
|
|
143
|
+
* Process a stream of packets through the filter.
|
|
144
|
+
*
|
|
145
|
+
* Async generator that processes packets lazily and yields filtered results.
|
|
146
|
+
* Automatically handles EOF and cleanup.
|
|
147
|
+
*
|
|
148
|
+
* @param packets - Async iterable of packets to filter
|
|
149
|
+
*
|
|
150
|
+
* @yields Filtered packets
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* const bsf = await BitStreamFilterAPI.create('h264_mp4toannexb', stream);
|
|
155
|
+
*
|
|
156
|
+
* // Filter only video packets
|
|
157
|
+
* async function* videoPackets() {
|
|
158
|
+
* for await (const packet of media.packets()) {
|
|
159
|
+
* if (packet.streamIndex === stream.index) {
|
|
160
|
+
* yield packet;
|
|
161
|
+
* }
|
|
162
|
+
* }
|
|
163
|
+
* }
|
|
164
|
+
*
|
|
165
|
+
* for await (const filtered of bsf.packets(videoPackets())) {
|
|
166
|
+
* await output.writePacket(filtered);
|
|
167
|
+
* }
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
packets(packets: AsyncIterable<Packet>): AsyncGenerator<Packet>;
|
|
171
|
+
/**
|
|
172
|
+
* Flush the filter and retrieve remaining packets.
|
|
173
|
+
*
|
|
174
|
+
* Sends EOF to the filter and retrieves any buffered packets.
|
|
175
|
+
* Should be called when all input packets have been processed.
|
|
176
|
+
*
|
|
177
|
+
* @returns Array of remaining packets (may be empty)
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```typescript
|
|
181
|
+
* // After processing all packets
|
|
182
|
+
* const remaining = await bsf.flush();
|
|
183
|
+
* for (const packet of remaining) {
|
|
184
|
+
* await output.writePacket(packet);
|
|
185
|
+
* }
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
flush(): Promise<Packet[]>;
|
|
189
|
+
/**
|
|
190
|
+
* Flush the filter and yield remaining packets.
|
|
191
|
+
*
|
|
192
|
+
* Async generator that sends EOF to the filter and yields any buffered packets.
|
|
193
|
+
* Provides a convenient way to process all remaining packets after input is complete.
|
|
194
|
+
*
|
|
195
|
+
* @yields Remaining packets from the filter
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```typescript
|
|
199
|
+
* // Process all remaining packets with generator
|
|
200
|
+
* for await (const packet of bsf.flushPackets()) {
|
|
201
|
+
* await output.writePacket(packet);
|
|
202
|
+
* using _ = packet; // Auto cleanup
|
|
203
|
+
* }
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
flushPackets(): AsyncGenerator<Packet>;
|
|
207
|
+
/**
|
|
208
|
+
* Get the stream this filter was created for.
|
|
209
|
+
* Used for determining stream configuration in pipeline.
|
|
210
|
+
*/
|
|
211
|
+
getStream(): Stream;
|
|
212
|
+
/**
|
|
213
|
+
* Reset the filter state.
|
|
214
|
+
*
|
|
215
|
+
* Clears internal buffers and resets the filter to initial state.
|
|
216
|
+
* Useful when seeking or switching between streams.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* // When seeking in the input
|
|
221
|
+
* await media.seek(timestamp);
|
|
222
|
+
* bsf.reset(); // Clear filter state
|
|
223
|
+
* // Continue processing from new position
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
reset(): void;
|
|
227
|
+
/**
|
|
228
|
+
* Dispose of the filter resources.
|
|
229
|
+
*
|
|
230
|
+
* Automatically called when using the `using` statement.
|
|
231
|
+
* Frees all associated FFmpeg resources.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```typescript
|
|
235
|
+
* {
|
|
236
|
+
* using bsf = await BitStreamFilterAPI.create('h264_mp4toannexb', stream);
|
|
237
|
+
* // ... use filter
|
|
238
|
+
* } // Automatically disposed when leaving scope
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
dispose(): void;
|
|
242
|
+
/**
|
|
243
|
+
* Symbol.dispose implementation for using statement.
|
|
244
|
+
*/
|
|
245
|
+
[Symbol.dispose](): void;
|
|
246
|
+
}
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BitStreamFilterAPI - High-level wrapper for bitstream filtering
|
|
3
|
+
*
|
|
4
|
+
* Simplifies FFmpeg's bitstream filter API with automatic initialization,
|
|
5
|
+
* parameter configuration, and packet processing.
|
|
6
|
+
*
|
|
7
|
+
* Handles filter context lifecycle, packet buffering, and flushing.
|
|
8
|
+
* Useful for format conversion, metadata extraction, and stream modifications.
|
|
9
|
+
*
|
|
10
|
+
* @module api/bitstream-filter
|
|
11
|
+
*/
|
|
12
|
+
import { AVERROR_EAGAIN, AVERROR_EOF, BitStreamFilter, BitStreamFilterContext, FFmpegError, Packet } from '../lib/index.js';
|
|
13
|
+
/**
|
|
14
|
+
* High-level bitstream filter for packet processing.
|
|
15
|
+
*
|
|
16
|
+
* Handles filter initialization, packet processing, and cleanup.
|
|
17
|
+
* Designed for simple, efficient packet filtering workflows.
|
|
18
|
+
*
|
|
19
|
+
* Manages filter context lifecycle and provides automatic cleanup.
|
|
20
|
+
* Supports packet-by-packet and stream processing modes.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Create filter for H.264 stream
|
|
25
|
+
* const media = await MediaInput.open('video.mp4');
|
|
26
|
+
* const stream = media.video();
|
|
27
|
+
* const bsf = await BitStreamFilterAPI.create('h264_mp4toannexb', stream);
|
|
28
|
+
*
|
|
29
|
+
* // Process packets
|
|
30
|
+
* for await (const packet of media.packets()) {
|
|
31
|
+
* if (packet.streamIndex === stream.index) {
|
|
32
|
+
* const filtered = await bsf.process(packet);
|
|
33
|
+
* for (const outPacket of filtered) {
|
|
34
|
+
* // Write to output or process further
|
|
35
|
+
* await output.writePacket(outPacket);
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
*
|
|
40
|
+
* // Flush and cleanup
|
|
41
|
+
* const remaining = await bsf.flush();
|
|
42
|
+
* bsf.dispose();
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* // Process packet stream
|
|
48
|
+
* const bsf = await BitStreamFilterAPI.create('extract_extradata', stream);
|
|
49
|
+
*
|
|
50
|
+
* for await (const filtered of bsf.packets(media.packets())) {
|
|
51
|
+
* // Filtered packets are automatically processed
|
|
52
|
+
* await output.writePacket(filtered);
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export class BitStreamFilterAPI {
|
|
57
|
+
ctx;
|
|
58
|
+
filter;
|
|
59
|
+
stream;
|
|
60
|
+
isDisposed = false;
|
|
61
|
+
/**
|
|
62
|
+
* Private constructor - use BitStreamFilterAPI.create() instead.
|
|
63
|
+
*
|
|
64
|
+
* @param filter - The bitstream filter
|
|
65
|
+
* @param ctx - Initialized filter context
|
|
66
|
+
* @param stream - The stream this filter is for
|
|
67
|
+
*/
|
|
68
|
+
constructor(filter, ctx, stream) {
|
|
69
|
+
this.filter = filter;
|
|
70
|
+
this.ctx = ctx;
|
|
71
|
+
this.stream = stream;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Create a bitstream filter for a specific stream.
|
|
75
|
+
*
|
|
76
|
+
* Factory method that handles filter discovery, context setup,
|
|
77
|
+
* and initialization.
|
|
78
|
+
*
|
|
79
|
+
* @param filterName - Name of the bitstream filter (e.g., 'h264_mp4toannexb')
|
|
80
|
+
* @param stream - Stream to filter
|
|
81
|
+
*
|
|
82
|
+
* @returns Promise resolving to configured BitStreamFilterAPI
|
|
83
|
+
*
|
|
84
|
+
* @throws {Error} If filter unavailable or initialization fails
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const media = await MediaInput.open('video.mp4');
|
|
89
|
+
* const stream = media.video();
|
|
90
|
+
* const bsf = await BitStreamFilterAPI.create('h264_mp4toannexb', stream);
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
static async create(filterName, stream) {
|
|
94
|
+
if (!stream) {
|
|
95
|
+
throw new Error('Stream is required');
|
|
96
|
+
}
|
|
97
|
+
// Find the bitstream filter
|
|
98
|
+
const filter = BitStreamFilter.getByName(filterName);
|
|
99
|
+
if (!filter) {
|
|
100
|
+
throw new Error(`Bitstream filter '${filterName}' not found`);
|
|
101
|
+
}
|
|
102
|
+
// Create and allocate context
|
|
103
|
+
const ctx = new BitStreamFilterContext();
|
|
104
|
+
const allocRet = ctx.alloc(filter);
|
|
105
|
+
FFmpegError.throwIfError(allocRet, 'Failed to allocate bitstream filter context');
|
|
106
|
+
try {
|
|
107
|
+
// Copy codec parameters from stream
|
|
108
|
+
if (!ctx.inputCodecParameters) {
|
|
109
|
+
throw new Error('Failed to get input codec parameters from filter context');
|
|
110
|
+
}
|
|
111
|
+
stream.codecpar.copy(ctx.inputCodecParameters);
|
|
112
|
+
// Set time base
|
|
113
|
+
ctx.inputTimeBase = stream.timeBase;
|
|
114
|
+
// Initialize the filter
|
|
115
|
+
const initRet = ctx.init();
|
|
116
|
+
FFmpegError.throwIfError(initRet, 'Failed to initialize bitstream filter');
|
|
117
|
+
return new BitStreamFilterAPI(filter, ctx, stream);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
// Clean up on error
|
|
121
|
+
ctx.free();
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Get the filter name.
|
|
127
|
+
*
|
|
128
|
+
* @returns The name of the bitstream filter
|
|
129
|
+
*/
|
|
130
|
+
get name() {
|
|
131
|
+
return this.filter.name ?? 'unknown';
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Get the associated stream.
|
|
135
|
+
*
|
|
136
|
+
* @returns The stream this filter was created for
|
|
137
|
+
*/
|
|
138
|
+
get streamInfo() {
|
|
139
|
+
return this.stream;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get output codec parameters.
|
|
143
|
+
*
|
|
144
|
+
* Returns the output codec parameters after filter initialization.
|
|
145
|
+
* These may differ from input parameters depending on the filter.
|
|
146
|
+
*
|
|
147
|
+
* @returns Output codec parameters, or null if not available
|
|
148
|
+
*/
|
|
149
|
+
get outputCodecParameters() {
|
|
150
|
+
return this.ctx.outputCodecParameters;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get output time base.
|
|
154
|
+
*
|
|
155
|
+
* Returns the output time base after filter initialization.
|
|
156
|
+
*
|
|
157
|
+
* @returns Output time base, or null if not available
|
|
158
|
+
*/
|
|
159
|
+
get outputTimeBase() {
|
|
160
|
+
return this.ctx.outputTimeBase;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Process a single packet through the filter.
|
|
164
|
+
*
|
|
165
|
+
* Sends a packet to the filter and retrieves all output packets.
|
|
166
|
+
* One input packet may produce zero, one, or multiple output packets.
|
|
167
|
+
*
|
|
168
|
+
* @param packet - Packet to filter, or null to signal EOF
|
|
169
|
+
*
|
|
170
|
+
* @returns Array of filtered packets (may be empty)
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* const inputPacket = await media.readPacket();
|
|
175
|
+
* const filtered = await bsf.process(inputPacket);
|
|
176
|
+
*
|
|
177
|
+
* for (const packet of filtered) {
|
|
178
|
+
* console.log(`Filtered packet: size=${packet.size}`);
|
|
179
|
+
* await output.writePacket(packet);
|
|
180
|
+
* }
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
async process(packet) {
|
|
184
|
+
if (this.isDisposed) {
|
|
185
|
+
throw new Error('BitStreamFilterAPI is disposed');
|
|
186
|
+
}
|
|
187
|
+
const outputPackets = [];
|
|
188
|
+
// Send packet to filter
|
|
189
|
+
const sendRet = await this.ctx.sendPacket(packet);
|
|
190
|
+
if (sendRet < 0 && sendRet !== AVERROR_EAGAIN) {
|
|
191
|
+
FFmpegError.throwIfError(sendRet, 'Failed to send packet to bitstream filter');
|
|
192
|
+
}
|
|
193
|
+
// Receive all output packets
|
|
194
|
+
while (true) {
|
|
195
|
+
const outPacket = new Packet();
|
|
196
|
+
outPacket.alloc();
|
|
197
|
+
const recvRet = await this.ctx.receivePacket(outPacket);
|
|
198
|
+
if (recvRet === AVERROR_EAGAIN || recvRet === AVERROR_EOF) {
|
|
199
|
+
outPacket.unref();
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
if (recvRet < 0) {
|
|
203
|
+
outPacket.unref();
|
|
204
|
+
FFmpegError.throwIfError(recvRet, 'Failed to receive packet from bitstream filter');
|
|
205
|
+
}
|
|
206
|
+
outputPackets.push(outPacket);
|
|
207
|
+
}
|
|
208
|
+
return outputPackets;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Process a stream of packets through the filter.
|
|
212
|
+
*
|
|
213
|
+
* Async generator that processes packets lazily and yields filtered results.
|
|
214
|
+
* Automatically handles EOF and cleanup.
|
|
215
|
+
*
|
|
216
|
+
* @param packets - Async iterable of packets to filter
|
|
217
|
+
*
|
|
218
|
+
* @yields Filtered packets
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```typescript
|
|
222
|
+
* const bsf = await BitStreamFilterAPI.create('h264_mp4toannexb', stream);
|
|
223
|
+
*
|
|
224
|
+
* // Filter only video packets
|
|
225
|
+
* async function* videoPackets() {
|
|
226
|
+
* for await (const packet of media.packets()) {
|
|
227
|
+
* if (packet.streamIndex === stream.index) {
|
|
228
|
+
* yield packet;
|
|
229
|
+
* }
|
|
230
|
+
* }
|
|
231
|
+
* }
|
|
232
|
+
*
|
|
233
|
+
* for await (const filtered of bsf.packets(videoPackets())) {
|
|
234
|
+
* await output.writePacket(filtered);
|
|
235
|
+
* }
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
async *packets(packets) {
|
|
239
|
+
if (this.isDisposed) {
|
|
240
|
+
throw new Error('BitStreamFilterAPI is disposed');
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
// Process all input packets
|
|
244
|
+
for await (const packet of packets) {
|
|
245
|
+
const filtered = await this.process(packet);
|
|
246
|
+
for (const outPacket of filtered) {
|
|
247
|
+
yield outPacket;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// Send EOF and get remaining packets
|
|
251
|
+
const remaining = await this.flush();
|
|
252
|
+
for (const packet of remaining) {
|
|
253
|
+
yield packet;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
// Ensure cleanup on error
|
|
258
|
+
this.ctx.flush();
|
|
259
|
+
throw error;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Flush the filter and retrieve remaining packets.
|
|
264
|
+
*
|
|
265
|
+
* Sends EOF to the filter and retrieves any buffered packets.
|
|
266
|
+
* Should be called when all input packets have been processed.
|
|
267
|
+
*
|
|
268
|
+
* @returns Array of remaining packets (may be empty)
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* ```typescript
|
|
272
|
+
* // After processing all packets
|
|
273
|
+
* const remaining = await bsf.flush();
|
|
274
|
+
* for (const packet of remaining) {
|
|
275
|
+
* await output.writePacket(packet);
|
|
276
|
+
* }
|
|
277
|
+
* ```
|
|
278
|
+
*/
|
|
279
|
+
async flush() {
|
|
280
|
+
if (this.isDisposed) {
|
|
281
|
+
throw new Error('BitStreamFilterAPI is disposed');
|
|
282
|
+
}
|
|
283
|
+
// Send EOF
|
|
284
|
+
const filtered = await this.process(null);
|
|
285
|
+
// Also flush the context to reset internal state
|
|
286
|
+
this.ctx.flush();
|
|
287
|
+
return filtered;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Flush the filter and yield remaining packets.
|
|
291
|
+
*
|
|
292
|
+
* Async generator that sends EOF to the filter and yields any buffered packets.
|
|
293
|
+
* Provides a convenient way to process all remaining packets after input is complete.
|
|
294
|
+
*
|
|
295
|
+
* @yields Remaining packets from the filter
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* ```typescript
|
|
299
|
+
* // Process all remaining packets with generator
|
|
300
|
+
* for await (const packet of bsf.flushPackets()) {
|
|
301
|
+
* await output.writePacket(packet);
|
|
302
|
+
* using _ = packet; // Auto cleanup
|
|
303
|
+
* }
|
|
304
|
+
* ```
|
|
305
|
+
*/
|
|
306
|
+
async *flushPackets() {
|
|
307
|
+
if (this.isDisposed) {
|
|
308
|
+
throw new Error('BitStreamFilterAPI is disposed');
|
|
309
|
+
}
|
|
310
|
+
const remaining = await this.flush();
|
|
311
|
+
for (const packet of remaining) {
|
|
312
|
+
yield packet;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Get the stream this filter was created for.
|
|
317
|
+
* Used for determining stream configuration in pipeline.
|
|
318
|
+
*/
|
|
319
|
+
getStream() {
|
|
320
|
+
return this.stream;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Reset the filter state.
|
|
324
|
+
*
|
|
325
|
+
* Clears internal buffers and resets the filter to initial state.
|
|
326
|
+
* Useful when seeking or switching between streams.
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* ```typescript
|
|
330
|
+
* // When seeking in the input
|
|
331
|
+
* await media.seek(timestamp);
|
|
332
|
+
* bsf.reset(); // Clear filter state
|
|
333
|
+
* // Continue processing from new position
|
|
334
|
+
* ```
|
|
335
|
+
*/
|
|
336
|
+
reset() {
|
|
337
|
+
if (this.isDisposed) {
|
|
338
|
+
throw new Error('BitStreamFilterAPI is disposed');
|
|
339
|
+
}
|
|
340
|
+
this.ctx.flush();
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Dispose of the filter resources.
|
|
344
|
+
*
|
|
345
|
+
* Automatically called when using the `using` statement.
|
|
346
|
+
* Frees all associated FFmpeg resources.
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* ```typescript
|
|
350
|
+
* {
|
|
351
|
+
* using bsf = await BitStreamFilterAPI.create('h264_mp4toannexb', stream);
|
|
352
|
+
* // ... use filter
|
|
353
|
+
* } // Automatically disposed when leaving scope
|
|
354
|
+
* ```
|
|
355
|
+
*/
|
|
356
|
+
dispose() {
|
|
357
|
+
if (!this.isDisposed) {
|
|
358
|
+
this.ctx.free();
|
|
359
|
+
this.isDisposed = true;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Symbol.dispose implementation for using statement.
|
|
364
|
+
*/
|
|
365
|
+
[Symbol.dispose]() {
|
|
366
|
+
this.dispose();
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
//# sourceMappingURL=bitstream-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bitstream-filter.js","sourceRoot":"","sources":["../../src/api/bitstream-filter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAI5H;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,OAAO,kBAAkB;IACrB,GAAG,CAAyB;IAC5B,MAAM,CAAkB;IACxB,MAAM,CAAS;IACf,UAAU,GAAG,KAAK,CAAC;IAE3B;;;;;;OAMG;IACH,YAAoB,MAAuB,EAAE,GAA2B,EAAE,MAAc;QACtF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAkB,EAAE,MAAc;QACpD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,4BAA4B;QAC5B,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,qBAAqB,UAAU,aAAa,CAAC,CAAC;QAChE,CAAC;QAED,8BAA8B;QAC9B,MAAM,GAAG,GAAG,IAAI,sBAAsB,EAAE,CAAC;QACzC,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACnC,WAAW,CAAC,YAAY,CAAC,QAAQ,EAAE,6CAA6C,CAAC,CAAC;QAElF,IAAI,CAAC;YACH,oCAAoC;YACpC,IAAI,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;gBAC9B,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAC9E,CAAC;YACD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YAE/C,gBAAgB;YAChB,GAAG,CAAC,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC;YAEpC,wBAAwB;YACxB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;YAC3B,WAAW,CAAC,YAAY,CAAC,OAAO,EAAE,uCAAuC,CAAC,CAAC;YAE3E,OAAO,IAAI,kBAAkB,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QACrD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,oBAAoB;YACpB,GAAG,CAAC,IAAI,EAAE,CAAC;YACX,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,SAAS,CAAC;IACvC,CAAC;IAED;;;;OAIG;IACH,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;;;;;;OAOG;IACH,IAAI,qBAAqB;QACvB,OAAO,IAAI,CAAC,GAAG,CAAC,qBAAqB,CAAC;IACxC,CAAC;IAED;;;;;;OAMG;IACH,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC;IACjC,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,KAAK,CAAC,OAAO,CAAC,MAAqB;QACjC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,aAAa,GAAa,EAAE,CAAC;QAEnC,wBAAwB;QACxB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAClD,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,KAAK,cAAc,EAAE,CAAC;YAC9C,WAAW,CAAC,YAAY,CAAC,OAAO,EAAE,2CAA2C,CAAC,CAAC;QACjF,CAAC;QAED,6BAA6B;QAC7B,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,SAAS,GAAG,IAAI,MAAM,EAAE,CAAC;YAC/B,SAAS,CAAC,KAAK,EAAE,CAAC;YAElB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YAExD,IAAI,OAAO,KAAK,cAAc,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;gBAC1D,SAAS,CAAC,KAAK,EAAE,CAAC;gBAClB,MAAM;YACR,CAAC;YAED,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;gBAChB,SAAS,CAAC,KAAK,EAAE,CAAC;gBAClB,WAAW,CAAC,YAAY,CAAC,OAAO,EAAE,gDAAgD,CAAC,CAAC;YACtF,CAAC;YAED,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAChC,CAAC;QAED,OAAO,aAAa,CAAC;IACvB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,KAAK,CAAC,CAAC,OAAO,CAAC,OAA8B;QAC3C,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,CAAC;YACH,4BAA4B;YAC5B,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBACnC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC5C,KAAK,MAAM,SAAS,IAAI,QAAQ,EAAE,CAAC;oBACjC,MAAM,SAAS,CAAC;gBAClB,CAAC;YACH,CAAC;YAED,qCAAqC;YACrC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;YACrC,KAAK,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC;gBAC/B,MAAM,MAAM,CAAC;YACf,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,0BAA0B;YAC1B,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;QAED,WAAW;QACX,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE1C,iDAAiD;QACjD,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QAEjB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,KAAK,CAAC,CAAC,YAAY;QACjB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACrC,KAAK,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC;YAC/B,MAAM,MAAM,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YAChB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,CAAC,MAAM,CAAC,OAAO,CAAC;QACd,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;CACF"}
|