import { CodecContext } from '../lib/codec-context.js';
import { Codec } from '../lib/codec.js';
import { Frame } from '../lib/frame.js';
import { Packet } from '../lib/packet.js';
import { SchedulerControl } from './utilities/scheduler.js';
import type { AVCodecFlag, AVCodecID, AVThreadType, EncoderOptionsFor, EOFSignal, FFEncoderCodec } from '../constants/index.js';
import type { Decoder } from './decoder.js';
import type { FilterComplexAPI } from './filter-complex.js';
import type { FilterAPI } from './filter.js';
import type { Muxer } from './muxer.js';
/**
 * Options for encoder creation.
 */
export interface EncoderOptions<C = unknown> {
    /**
     * Target bitrate.
     *
     * Can be specified as number, bigint, or string with suffix (e.g., '5M', '128k').
     * Used for rate control in video and audio encoding.
     *
     * @default 128k for audio, 1M for video
     */
    bitrate?: number | bigint | string;
    /**
     * Minimum bitrate for rate control.
     *
     * Can be specified as number, bigint, or string with suffix (e.g., '5M', '128k').
     * Used with variable bitrate encoding to enforce quality floor.
     */
    minRate?: number | bigint | string;
    /**
     * Maximum bitrate for rate control.
     *
     * Can be specified as number, bigint, or string with suffix (e.g., '5M', '128k').
     * Used with variable bitrate encoding to enforce bitrate ceiling.
     */
    maxRate?: number | bigint | string;
    /**
     * Rate control buffer size.
     *
     * Can be specified as number, bigint, or string with suffix (e.g., '5M', '128k').
     * Determines the decoder buffer model size for rate control.
     */
    bufSize?: number | bigint | string;
    /**
     * Group of Pictures (GOP) size.
     *
     * Number of frames between keyframes.
     * Larger GOP improves compression but reduces seekability.
     */
    gopSize?: number;
    /**
     * Maximum number of consecutive B-frames.
     *
     * B-frames improve compression but increase encoding complexity.
     * Maximum B-frames allowed between I or P frames.
     */
    maxBFrames?: number;
    /**
     * Optional decoder reference for metadata extraction.
     *
     * Used to extract bits_per_raw_sample and other decoder-specific properties.
     * Helps maintain quality during transcoding.
     */
    decoder?: Decoder;
    /**
     * Optional filter reference for metadata extraction.
     *
     * Used to extract filter output parameters.
     * Ensures encoder matches filter output characteristics.
     */
    filter?: FilterAPI | FilterComplexAPI;
    /**
     * Number of threads to use for encoding.
     *
     * Set to 0 to auto-detect based on CPU cores.
     *
     * @default 1
     */
    threadCount?: number;
    /**
     * Type of threading to use for encoding.
     *
     * - `FF_THREAD_FRAME` (1): Encode multiple frames in parallel.
     *   Higher throughput but adds latency (1 frame delay per thread).
     *
     * - `FF_THREAD_SLICE` (2): Encode parts of a single frame in parallel.
     *   Lower latency, suitable for real-time encoding.
     *
     * @default FFmpeg default (both methods, codec chooses best)
     */
    threadType?: AVThreadType;
    /**
     * Automatically resample incoming audio to a format the codec supports.
     *
     * Audio encoders only accept specific sample rates, sample formats, and channel
     * layouts (e.g. libmp3lame rejects 96 kHz; AAC needs planar `fltp`). When `true`,
     * the encoder transparently converts each frame to the nearest supported
     * sample rate / sample format / channel layout (like `ffmpeg`'s automatic
     * `aresample`). When `false` (default), an unsupported input raises a descriptive
     * error instead — keeping behaviour explicit and 1:1 with the codec.
     *
     * Has no effect on video.
     *
     * @default false
     */
    autoResample?: boolean;
    /**
     * Automatically convert incoming video to a pixel format the codec supports.
     *
     * Video encoders only accept specific pixel formats (e.g. libx264 wants planar
     * YUV like `yuv420p` and rejects `rgb24`). When `true`, the encoder transparently
     * converts each frame to the least-loss supported pixel format via swscale (like
     * `ffmpeg`'s automatic `format` filter), keeping the same resolution. When `false`
     * (default), an unsupported input raises a descriptive error instead — keeping
     * behaviour explicit and 1:1 with the codec.
     *
     * Resolution is never changed (the encoder already adopts the frame's dimensions),
     * and hardware frames are left untouched (their format is negotiated via the
     * hardware frames context). Has no effect on audio.
     *
     * @default false
     */
    autoFormat?: boolean;
    /**
     * Additional codec-specific options.
     *
     * Key-value pairs of FFmpeg private codec options, passed directly to the encoder.
     * When the codec is created from a branded constant (e.g. `FF_ENCODER_LIBX264`),
     * these are strongly typed to that codec's known options (autocomplete + validation);
     * otherwise any string/number/boolean values are accepted.
     */
    options?: EncoderOptionsFor<C>;
    /**
     * AbortSignal for cancellation.
     *
     * When aborted, async generators stop yielding and async methods throw AbortError.
     */
    signal?: AbortSignal;
}
/**
 * High-level encoder for audio and video streams.
 *
 * Provides a simplified interface for encoding media frames to packets.
 * Handles codec initialization, hardware acceleration setup, and packet management.
 * Supports both synchronous frame-by-frame encoding and async iteration over packets.
 * Essential component in media processing pipelines for converting raw frames to compressed data.
 *
 * @example
 * ```typescript
 * import { Encoder } from 'node-av/api';
 * import { AV_CODEC_ID_H264, FF_ENCODER_LIBX264 } from 'node-av/constants';
 *
 * // Create H.264 encoder
 * const encoder = await Encoder.create(FF_ENCODER_LIBX264, {
 *   type: 'video',
 *   width: 1920,
 *   height: 1080,
 *   pixelFormat: AV_PIX_FMT_YUV420P,
 *   timeBase: { num: 1, den: 30 },
 *   frameRate: { num: 30, den: 1 }
 * }, {
 *   bitrate: '5M',
 *   gopSize: 60
 * });
 *
 * // Encode frames
 * const packet = await encoder.encode(frame);
 * if (packet) {
 *   await output.writePacket(packet);
 *   packet.free();
 * }
 * ```
 *
 * @example
 * ```typescript
 * // Hardware-accelerated encoding with lazy initialization
 * import { HardwareContext } from 'node-av/api';
 * import { FF_ENCODER_H264_VIDEOTOOLBOX } from 'node-av/constants';
 *
 * const hw = HardwareContext.auto();
 * const encoderCodec = hw?.getEncoderCodec('h264') ?? FF_ENCODER_H264_VIDEOTOOLBOX;
 * const encoder = await Encoder.create(encoderCodec, {
 *   timeBase: video.timeBase,
 *   bitrate: '10M'
 * });
 *
 * // Hardware context will be detected from first frame's hw_frames_ctx
 * for await (const packet of encoder.packets(frames)) {
 *   await output.writePacket(packet);
 *   packet.free();
 * }
 * ```
 *
 * @see {@link Decoder} For decoding packets to frames
 * @see {@link Muxer} For writing encoded packets
 * @see {@link HardwareContext} For GPU acceleration
 */
export declare class Encoder implements Disposable {
    private codecContext;
    private packet;
    private codec;
    private initializePromise;
    private initialized;
    private isClosed;
    private opts?;
    private options;
    private audioFrameBuffer?;
    private autoResample;
    private audioResampler?;
    private resampledFrame?;
    private audioInputLayout?;
    private autoFormat;
    private videoScaler?;
    private scaledFrame?;
    private videoTargetFormat?;
    private supportsParamChange?;
    private encoderChannels?;
    private inputQueue;
    private outputQueue;
    private workerPromise;
    private pipeToPromise;
    private signal?;
    /**
     * @param codecContext - Configured codec context
     *
     * @param codec - Encoder codec
     *
     * @param options - Encoder options
     *
     * @param opts - Encoder options as Dictionary
     *
     * @internal
     */
    private constructor();
    /**
     * Create an encoder with specified codec and options.
     *
     * Initializes an encoder with the appropriate codec and configuration.
     * Uses lazy initialization - encoder is opened when first frame is received.
     * Hardware context will be automatically detected from first frame if not provided.
     *
     * Direct mapping to avcodec_find_encoder_by_name() or avcodec_find_encoder().
     *
     * @param encoderCodec - Codec name, ID, or instance to use for encoding
     *
     * @param options - Optional encoder configuration options including required timeBase
     *
     * @returns Configured encoder instance
     *
     * @throws {Error} If encoder not found
     *
     * @example
     * ```typescript
     * // From decoder stream info
     * const encoder = await Encoder.create(FF_ENCODER_LIBX264, {
     *   timeBase: video.timeBase,
     *   bitrate: '5M',
     *   gopSize: 60,
     *   options: {
     *     preset: 'fast',
     *     crf: '23'
     *   }
     * });
     * ```
     *
     * @example
     * ```typescript
     * // With custom stream info
     * const encoder = await Encoder.create(FF_ENCODER_AAC, {
     *   timeBase: audio.timeBase,
     *   bitrate: '192k'
     * });
     * ```
     *
     * @example
     * ```typescript
     * // Hardware encoder
     * const hw = HardwareContext.auto();
     * const encoderCodec = hw?.getEncoderCodec('h264') ?? FF_ENCODER_H264_VIDEOTOOLBOX;
     * const encoder = await Encoder.create(encoderCodec, {
     *   timeBase: video.timeBase,
     *   bitrate: '8M'
     * });
     * ```
     *
     * @see {@link EncoderOptions} For configuration options
     * @see {@link createSync} For synchronous version
     */
    static create<const C extends FFEncoderCodec | AVCodecID | Codec>(encoderCodec: C, options?: EncoderOptions<C>): Promise<Encoder>;
    /**
     * Create an encoder with specified codec and options synchronously.
     * Synchronous version of create.
     *
     * Initializes an encoder with the appropriate codec and configuration.
     * Uses lazy initialization - encoder is opened when first frame is received.
     * Hardware context will be automatically detected from first frame if not provided.
     *
     * Direct mapping to avcodec_find_encoder_by_name() or avcodec_find_encoder().
     *
     * @param encoderCodec - Codec name, ID, or instance to use for encoding
     *
     * @param options - Optional encoder configuration options including required timeBase
     *
     * @returns Configured encoder instance
     *
     * @throws {Error} If encoder not found or timeBase not provided
     *
     * @throws {FFmpegError} If codec allocation fails
     *
     * @example
     * ```typescript
     * // From decoder stream info
     * const encoder = await Encoder.create(FF_ENCODER_LIBX264, {
     *   timeBase: video.timeBase,
     *   bitrate: '5M',
     *   gopSize: 60,
     *   options: {
     *     preset: 'fast',
     *     crf: '23'
     *   }
     * });
     * ```
     *
     * @example
     * ```typescript
     * // With custom stream info
     * const encoder = await Encoder.create(FF_ENCODER_AAC, {
     *   timeBase: audio.timeBase,
     *   bitrate: '192k'
     * });
     * ```
     *
     * @example
     * ```typescript
     * // Hardware encoder
     * const hw = HardwareContext.auto();
     * const encoderCodec = hw?.getEncoderCodec('h264') ?? FF_ENCODER_H264_VIDEOTOOLBOX;
     * const encoder = await Encoder.create(encoderCodec, {
     *   timeBase: video.timeBase,
     *   bitrate: '8M'
     * });
     * ```
     *
     * @see {@link EncoderOptions} For configuration options
     * @see {@link create} For async version
     */
    static createSync<const C extends FFEncoderCodec | AVCodecID | Codec>(encoderCodec: C, options?: EncoderOptions<C>): Encoder;
    /**
     * Encode a single frame into a self-contained image buffer.
     *
     * One-shot, stateless helper for intra-only image codecs (MJPEG, PNG, WebP, ...).
     * Creates a fresh encoder, encodes the frame, flushes and frees everything in one call.
     * The encoder adopts dimensions, pixel format and hardware context from the frame,
     * so any frame size works without reconfiguration.
     *
     * @param encoderCodec - Encoder codec (name, ID, branded constant, or Codec)
     *
     * @param frame - Frame to encode
     *
     * @param options - Optional encoder configuration (e.g. `{ options: { q: 3 } }` for MJPEG quality)
     *
     * @returns Encoded image bytes
     *
     * @throws {FFmpegError} If the encoder is not found or encoding fails
     *
     * @throws {Error} If the encoder produced no output
     *
     * @example
     * ```typescript
     * const jpeg = await Encoder.encodeOne(FF_ENCODER_MJPEG, frame, { options: { q: 3 } });
     * ```
     *
     * @see {@link EncoderPool} For reusing encoders across recurring resolutions
     */
    static encodeOne<const C extends FFEncoderCodec | AVCodecID | Codec>(encoderCodec: C, frame: Frame, options?: EncoderOptions<C>): Promise<Buffer>;
    /**
     * Encode a single frame into a self-contained image buffer synchronously.
     * Synchronous version of encodeOne.
     *
     * One-shot, stateless helper for intra-only image codecs (MJPEG, PNG, WebP, ...).
     * Creates a fresh encoder, encodes the frame, flushes and frees everything in one call.
     * The encoder adopts dimensions, pixel format and hardware context from the frame,
     * so any frame size works without reconfiguration.
     *
     * @param encoderCodec - Encoder codec (name, ID, branded constant, or Codec)
     *
     * @param frame - Frame to encode
     *
     * @param options - Optional encoder configuration (e.g. `{ options: { q: 3 } }` for MJPEG quality)
     *
     * @returns Encoded image bytes
     *
     * @throws {FFmpegError} If the encoder is not found or encoding fails
     *
     * @throws {Error} If the encoder produced no output
     *
     * @example
     * ```typescript
     * const jpeg = Encoder.encodeOneSync(FF_ENCODER_MJPEG, frame, { options: { q: 3 } });
     * ```
     *
     * @see {@link encodeOne} For async version
     * @see {@link EncoderPool} For reusing encoders across recurring resolutions
     */
    static encodeOneSync<const C extends FFEncoderCodec | AVCodecID | Codec>(encoderCodec: C, frame: Frame, options?: EncoderOptions<C>): Buffer;
    /**
     * Check if encoder is open.
     *
     * @example
     * ```typescript
     * if (encoder.isEncoderOpen) {
     *   const packet = await encoder.encode(frame);
     * }
     * ```
     */
    get isEncoderOpen(): boolean;
    /**
     * Check if encoder has been initialized.
     *
     * Returns true after first frame has been processed and encoder opened.
     * Useful for checking if encoder has received frame properties.
     *
     * @returns true if encoder has been initialized with frame data
     *
     * @example
     * ```typescript
     * if (!encoder.isEncoderInitialized) {
     *   console.log('Encoder will initialize on first frame');
     * }
     * ```
     */
    get isEncoderInitialized(): boolean;
    /**
     * Codec flags.
     *
     * @returns Current codec flags
     *
     * @throws {Error} If encoder is closed
     *
     * @example
     * ```typescript
     * const flags = encoder.codecFlags;
     * console.log('Current flags:', flags);
     * ```
     *
     * @see {@link setCodecFlags} To set flags
     * @see {@link clearCodecFlags} To clear flags
     * @see {@link hasCodecFlags} To check flags
     */
    get codecFlags(): AVCodecFlag;
    /**
     * Set codec flags.
     *
     * @param flags - One or more flag values to set
     *
     * @throws {Error} If encoder is already initialized or closed
     *
     * @example
     * ```typescript
     * import { AV_CODEC_FLAG_GLOBAL_HEADER, AV_CODEC_FLAG_QSCALE } from 'node-av/constants';
     *
     * // Set multiple flags before initialization
     * encoder.setCodecFlags(AV_CODEC_FLAG_GLOBAL_HEADER, AV_CODEC_FLAG_QSCALE);
     * ```
     *
     * @see {@link clearCodecFlags} To clear flags
     * @see {@link hasCodecFlags} To check flags
     * @see {@link codecFlags} For direct flag access
     */
    setCodecFlags(...flags: AVCodecFlag[]): void;
    /**
     * Clear codec flags.
     *
     * @param flags - One or more flag values to clear
     *
     * @throws {Error} If encoder is already initialized or closed
     *
     * @example
     * ```typescript
     * import { AV_CODEC_FLAG_QSCALE } from 'node-av/constants';
     *
     * // Clear specific flag before initialization
     * encoder.clearCodecFlags(AV_CODEC_FLAG_QSCALE);
     * ```
     *
     * @see {@link setCodecFlags} To set flags
     * @see {@link hasCodecFlags} To check flags
     * @see {@link codecFlags} For direct flag access
     */
    clearCodecFlags(...flags: AVCodecFlag[]): void;
    /**
     * Check if codec has specific flags.
     *
     * Tests whether all specified codec flags are set using bitwise AND.
     *
     * @param flags - One or more flag values to check
     *
     * @returns true if all specified flags are set, false otherwise
     *
     * @throws {Error} If encoder is closed
     *
     * @example
     * ```typescript
     * import { AV_CODEC_FLAG_GLOBAL_HEADER } from 'node-av/constants';
     *
     * if (encoder.hasCodecFlags(AV_CODEC_FLAG_GLOBAL_HEADER)) {
     *   console.log('Global header flag is set');
     * }
     * ```
     *
     * @see {@link setCodecFlags} To set flags
     * @see {@link clearCodecFlags} To clear flags
     * @see {@link codecFlags} For direct flag access
     */
    hasCodecFlags(...flags: AVCodecFlag[]): boolean;
    /**
     * Check if encoder uses hardware acceleration.
     *
     * @returns true if hardware-accelerated
     *
     * @example
     * ```typescript
     * if (encoder.isHardware()) {
     *   console.log('Using GPU acceleration');
     * }
     * ```
     *
     * @see {@link HardwareContext} For hardware setup
     */
    isHardware(): boolean;
    /**
     * Check if encoder is ready for processing.
     *
     * @returns true if initialized and ready
     *
     * @example
     * ```typescript
     * if (encoder.isReady()) {
     *   const packet = await encoder.encode(frame);
     * }
     * ```
     */
    isReady(): boolean;
    /**
     * Send a frame to the encoder.
     *
     * Sends a raw frame to the encoder for encoding.
     * Does not return encoded packets - use {@link receive} to retrieve packets.
     * On first frame, automatically initializes encoder with frame properties.
     * A single frame can produce zero, one, or multiple packets depending on codec buffering.
     *
     * **Important**: This method only SENDS the frame to the encoder.
     * You must call {@link receive} separately (potentially multiple times) to get encoded packets.
     *
     * Direct mapping to avcodec_send_frame().
     *
     * @param frame - Raw frame to send to encoder, or null to flush
     *
     * @throws {FFmpegError} If sending frame fails
     *
     * @example
     * ```typescript
     * // Send frame and receive packets
     * await encoder.encode(frame);
     *
     * // Receive all available packets
     * while (true) {
     *   const packet = await encoder.receive();
     *   if (!packet) break;
     *   console.log(`Encoded packet with PTS: ${packet.pts}`);
     *   await output.writePacket(packet);
     *   packet.free();
     * }
     * ```
     *
     * @example
     * ```typescript
     * for await (const frame of decoder.frames(input.packets())) {
     *   // Send frame
     *   await encoder.encode(frame);
     *
     *   // Receive available packets
     *   let packet;
     *   while ((packet = await encoder.receive())) {
     *     await output.writePacket(packet);
     *     packet.free();
     *   }
     *   frame.free();
     * }
     * ```
     *
     * @see {@link receive} For receiving encoded packets
     * @see {@link encodeAll} For combined send+receive operation
     * @see {@link packets} For automatic frame iteration
     * @see {@link flush} For end-of-stream handling
     * @see {@link encodeSync} For synchronous version
     */
    encode(frame: Frame | null): Promise<void>;
    /**
     * Send a frame to the encoder synchronously.
     * Synchronous version of encode.
     *
     * Sends a raw frame to the encoder for encoding.
     * Does not return encoded packets - use {@link receiveSync} to retrieve packets.
     * On first frame, automatically initializes encoder with frame properties.
     * A single frame can produce zero, one, or multiple packets depending on codec buffering.
     *
     * **Important**: This method only SENDS the frame to the encoder.
     * You must call {@link receiveSync} separately (potentially multiple times) to get encoded packets.
     *
     * Direct mapping to avcodec_send_frame().
     *
     * @param frame - Raw frame to send to encoder, or null to flush
     *
     * @throws {FFmpegError} If sending frame fails
     *
     * @example
     * ```typescript
     * // Send frame and receive packets
     * encoder.encodeSync(frame);
     *
     * // Receive all available packets
     * let packet;
     * while ((packet = encoder.receiveSync())) {
     *   console.log(`Encoded packet with PTS: ${packet.pts}`);
     *   output.writePacketSync(packet);
     *   packet.free();
     * }
     * ```
     *
     * @see {@link receiveSync} For receiving encoded packets
     * @see {@link encodeAllSync} For combined send+receive operation
     * @see {@link packetsSync} For automatic frame iteration
     * @see {@link flushSync} For end-of-stream handling
     * @see {@link encode} For async version
     */
    encodeSync(frame: Frame | null): void;
    /**
     * Encode a frame to packets.
     *
     * Sends a frame to the encoder and receives all available encoded packets.
     * Returns array of packets - may be empty if encoder needs more data.
     * On first frame, automatically initializes encoder with frame properties.
     * One frame can produce zero, one, or multiple packets depending on codec.
     *
     * Direct mapping to avcodec_send_frame() and avcodec_receive_packet().
     *
     * @param frame - Raw frame to encode (or null to flush)
     *
     * @returns Array of encoded packets (empty if more data needed or encoder is closed)
     *
     * @throws {FFmpegError} If encoding fails
     *
     * @example
     * ```typescript
     * const packets = await encoder.encodeAll(frame);
     * for (const packet of packets) {
     *   console.log(`Encoded packet with PTS: ${packet.pts}`);
     *   await output.writePacket(packet);
     *   packet.free();
     * }
     * ```
     *
     * @example
     * ```typescript
     * // Encode loop
     * for await (const frame of decoder.frames(input.packets())) {
     *   const packets = await encoder.encodeAll(frame);
     *   for (const packet of packets) {
     *     await output.writePacket(packet);
     *     packet.free();
     *   }
     *   frame.free();
     * }
     * ```
     *
     * @see {@link encode} For single packet encoding
     * @see {@link packets} For automatic frame iteration
     * @see {@link flush} For end-of-stream handling
     * @see {@link encodeAllSync} For synchronous version
     */
    encodeAll(frame: Frame | null): Promise<Packet[]>;
    /**
     * Encode a frame to packets synchronously.
     * Synchronous version of encodeAll.
     *
     * Sends a frame to the encoder and receives all available encoded packets.
     * Returns array of packets - may be empty if encoder needs more data.
     * On first frame, automatically initializes encoder with frame properties.
     * One frame can produce zero, one, or multiple packets depending on codec.
     *
     * Direct mapping to avcodec_send_frame() and avcodec_receive_packet().
     *
     * @param frame - Raw frame to encode (or null to flush)
     *
     * @returns Array of encoded packets (empty if more data needed or encoder is closed)
     *
     * @throws {FFmpegError} If encoding fails
     *
     * @example
     * ```typescript
     * const packets = encoder.encodeAllSync(frame);
     * for (const packet of packets) {
     *   console.log(`Encoded packet with PTS: ${packet.pts}`);
     *   output.writePacketSync(packet);
     *   packet.free();
     * }
     * ```
     *
     * @example
     * ```typescript
     * // Encode loop
     * for (const frame of decoder.framesSync(packets)) {
     *   const packets = encoder.encodeAllSync(frame);
     *   for (const packet of packets) {
     *     output.writePacketSync(packet);
     *     packet.free();
     *   }
     *   frame.free();
     * }
     * ```
     *
     * @see {@link encodeSync} For single packet encoding
     * @see {@link packetsSync} For automatic frame iteration
     * @see {@link flushSync} For end-of-stream handling
     * @see {@link encodeAll} For async version
     */
    encodeAllSync(frame: Frame | null): Packet[];
    /**
     * Encode frame stream to packet stream.
     *
     * High-level async generator for complete encoding pipeline.
     * Encoder is only flushed when EOF (null) signal is explicitly received.
     * Primary interface for stream-based encoding.
     *
     * **EOF Handling:**
     * - Send null to flush encoder and get remaining buffered packets
     * - Generator yields null after flushing when null is received
     * - No automatic flushing - encoder stays open until EOF or close()
     *
     * @param frames - Async iterable of frames, single frame, or null to flush
     *
     * @yields {Packet | null} Encoded packets, followed by null when explicitly flushed
     *
     * @throws {FFmpegError} If encoding fails
     *
     * @example
     * ```typescript
     * // Stream of frames with automatic EOF propagation
     * for await (const packet of encoder.packets(decoder.frames(input.packets()))) {
     *   if (packet === null) {
     *     console.log('Encoder flushed');
     *     break;
     *   }
     *   await output.writePacket(packet);
     *   packet.free(); // Must free output packets
     * }
     * ```
     *
     * @example
     * ```typescript
     * // Single frame - no automatic flush
     * for await (const packet of encoder.packets(singleFrame)) {
     *   await output.writePacket(packet);
     *   packet.free();
     * }
     * // Encoder remains open, buffered packets not flushed
     * ```
     *
     * @example
     * ```typescript
     * // Explicit flush with EOF
     * for await (const packet of encoder.packets(null)) {
     *   if (packet === null) {
     *     console.log('All buffered packets flushed');
     *     break;
     *   }
     *   console.log('Buffered packet:', packet.pts);
     *   await output.writePacket(packet);
     *   packet.free();
     * }
     * ```
     *
     * @see {@link encode} For single frame encoding
     * @see {@link Decoder.frames} For frame source
     * @see {@link packetsSync} For sync version
     */
    packets(frames: AsyncIterable<Frame | null> | Frame | null): AsyncGenerator<Packet | null>;
    /**
     * Encode frame stream to packet stream synchronously.
     * Synchronous version of packets.
     *
     * High-level sync generator for complete encoding pipeline.
     * Encoder is only flushed when EOF (null) signal is explicitly received.
     * Primary interface for stream-based encoding.
     *
     * **EOF Handling:**
     * - Send null to flush encoder and get remaining buffered packets
     * - Generator yields null after flushing when null is received
     * - No automatic flushing - encoder stays open until EOF or close()
     *
     * @param frames - Iterable of frames, single frame, or null to flush
     *
     * @yields {Packet | null} Encoded packets, followed by null when explicitly flushed
     *
     * @throws {FFmpegError} If encoding fails
     *
     * @example
     * ```typescript
     * // Stream of frames with automatic EOF propagation
     * for (const packet of encoder.packetsSync(decoder.framesSync(packets))) {
     *   if (packet === null) {
     *     console.log('Encoder flushed');
     *     break;
     *   }
     *   output.writePacketSync(packet);
     *   packet.free(); // Must free output packets
     * }
     * ```
     *
     * @example
     * ```typescript
     * // Single frame - no automatic flush
     * for (const packet of encoder.packetsSync(singleFrame)) {
     *   output.writePacketSync(packet);
     *   packet.free();
     * }
     * // Encoder remains open, buffered packets not flushed
     * ```
     *
     * @example
     * ```typescript
     * // Explicit flush with EOF
     * for (const packet of encoder.packetsSync(null)) {
     *   if (packet === null) {
     *     console.log('All buffered packets flushed');
     *     break;
     *   }
     *   console.log('Buffered packet:', packet.pts);
     *   output.writePacketSync(packet);
     *   packet.free();
     * }
     * ```
     *
     * @see {@link encodeSync} For single frame encoding
     * @see {@link Decoder.framesSync} For frame source
     * @see {@link packets} For async version
     */
    packetsSync(frames: Iterable<Frame | null> | Frame | null): Generator<Packet | null>;
    /**
     * Flush encoder and signal end-of-stream.
     *
     * Sends null frame to encoder to signal end-of-stream.
     * Does nothing if encoder was never initialized or is closed.
     * Must call receive() to get remaining buffered packets.
     *
     * Direct mapping to avcodec_send_frame(NULL).
     *
     * @example
     * ```typescript
     * // Signal end of stream
     * await encoder.flush();
     *
     * // Then get remaining packets
     * let packet;
     * while ((packet = await encoder.receive()) !== null) {
     *   console.log('Got buffered packet');
     *   await output.writePacket(packet);
     *   packet.free();
     * }
     * ```
     *
     * @see {@link flushPackets} For async iteration
     * @see {@link receive} For getting buffered packets
     * @see {@link flushSync} For synchronous version
     */
    flush(): Promise<void>;
    /**
     * Flush encoder and signal end-of-stream synchronously.
     * Synchronous version of flush.
     *
     * Sends null frame to encoder to signal end-of-stream.
     * Does nothing if encoder was never initialized or is closed.
     * Must call receiveSync() to get remaining buffered packets.
     *
     * Direct mapping to avcodec_send_frame(NULL).
     *
     * @example
     * ```typescript
     * // Signal end of stream
     * encoder.flushSync();
     *
     * // Then get remaining packets
     * let packet;
     * while ((packet = encoder.receiveSync()) !== null) {
     *   console.log('Got buffered packet');
     *   output.writePacketSync(packet);
     *   packet.free();
     * }
     * ```
     *
     * @see {@link flushPacketsSync} For sync iteration
     * @see {@link receiveSync} For getting buffered packets
     * @see {@link flush} For async version
     */
    flushSync(): void;
    /**
     * Flush all buffered packets as async generator.
     *
     * Convenient async iteration over remaining packets.
     * Automatically handles flush and repeated receive calls.
     * Returns immediately if encoder was never initialized or is closed.
     *
     * @yields {Packet} Buffered packets
     *
     * @example
     * ```typescript
     * // Flush at end of encoding
     * for await (const packet of encoder.flushPackets()) {
     *   console.log('Processing buffered packet');
     *   await output.writePacket(packet);
     *   packet.free();
     * }
     * ```
     *
     * @see {@link encode} For sending frames and receiving packets
     * @see {@link flush} For signaling end-of-stream
     * @see {@link flushPacketsSync} For synchronous version
     */
    flushPackets(): AsyncGenerator<Packet>;
    /**
     * Flush all buffered packets as generator synchronously.
     * Synchronous version of flushPackets.
     *
     * Convenient sync iteration over remaining packets.
     * Automatically handles flush and repeated receive calls.
     * Returns immediately if encoder was never initialized or is closed.
     *
     * @yields {Packet} Buffered packets
     *
     * @example
     * ```typescript
     * // Flush at end of encoding
     * for (const packet of encoder.flushPacketsSync()) {
     *   console.log('Processing buffered packet');
     *   output.writePacketSync(packet);
     *   packet.free();
     * }
     * ```
     *
     * @see {@link encodeSync} For sending frames and receiving packets
     * @see {@link flushSync} For signaling end-of-stream
     * @see {@link flushPackets} For async version
     */
    flushPacketsSync(): Generator<Packet>;
    /**
     * Receive packet from encoder.
     *
     * Gets encoded packets from the codec's internal buffer.
     * Handles packet cloning and error checking.
     * Implements FFmpeg's send/receive pattern.
     *
     * **Return Values:**
     * - `Packet` - Successfully encoded packet (AVERROR >= 0)
     * - `null` - Need more input frames (AVERROR_EAGAIN), or encoder not initialized
     * - `undefined` - End of stream reached (AVERROR_EOF), or encoder is closed
     *
     * Direct mapping to avcodec_receive_packet().
     *
     * @returns Cloned packet, null if need more data, or undefined if stream ended
     *
     * @throws {FFmpegError} If receive fails with error other than AVERROR_EAGAIN or AVERROR_EOF
     *
     * @throws {Error} If packet cloning fails (out of memory)
     *
     * @example
     * ```typescript
     * // Process all buffered packets
     * while (true) {
     *   const packet = await encoder.receive();
     *   if (!packet) break; // Stop on EAGAIN or EOF
     *   console.log(`Got packet with PTS: ${packet.pts}`);
     *   await output.writePacket(packet);
     *   packet.free();
     * }
     * ```
     *
     * @example
     * ```typescript
     * // Handle each return value explicitly
     * const packet = await encoder.receive();
     * if (packet === EOF) {
     *   console.log('Encoder stream ended');
     * } else if (packet === null) {
     *   console.log('Need more input frames');
     * } else {
     *   console.log(`Got packet: pts=${packet.pts}`);
     *   await output.writePacket(packet);
     *   packet.free();
     * }
     * ```
     *
     * @see {@link encode} For sending frames and receiving packets
     * @see {@link flush} For signaling end-of-stream
     * @see {@link receiveSync} For synchronous version
     * @see {@link EOF} For end-of-stream signal
     */
    receive(): Promise<Packet | EOFSignal | null>;
    /**
     * Receive packet from encoder synchronously.
     * Synchronous version of receive.
     *
     * Gets encoded packets from the codec's internal buffer.
     * Handles packet cloning and error checking.
     * Implements FFmpeg's send/receive pattern.
     *
     * **Return Values:**
     * - `Packet` - Successfully encoded packet (AVERROR >= 0)
     * - `null` - Need more input frames (AVERROR_EAGAIN), or encoder not initialized
     * - `undefined` - End of stream reached (AVERROR_EOF), or encoder is closed
     *
     * Direct mapping to avcodec_receive_packet().
     *
     * @returns Cloned packet, null if need more data, or undefined if stream ended
     *
     * @throws {FFmpegError} If receive fails with error other than AVERROR_EAGAIN or AVERROR_EOF
     *
     * @throws {Error} If packet cloning fails (out of memory)
     *
     * @example
     * ```typescript
     * // Process all buffered packets
     * while (true) {
     *   const packet = encoder.receiveSync();
     *   if (!packet) break; // Stop on EAGAIN or EOF
     *   console.log(`Got packet with PTS: ${packet.pts}`);
     *   output.writePacketSync(packet);
     *   packet.free();
     * }
     * ```
     *
     * @example
     * ```typescript
     * // Handle each return value explicitly
     * const packet = encoder.receiveSync();
     * if (packet === EOF) {
     *   console.log('Encoder stream ended');
     * } else if (packet === null) {
     *   console.log('Need more input frames');
     * } else {
     *   console.log(`Got packet: pts=${packet.pts}`);
     *   output.writePacketSync(packet);
     *   packet.free();
     * }
     * ```
     *
     * @see {@link encodeSync} For sending frames and receiving packets
     * @see {@link flushSync} For signaling end-of-stream
     * @see {@link receive} For async version
     * @see {@link EOF} For end-of-stream signal
     */
    receiveSync(): Packet | EOFSignal | null;
    /**
     * Pipe encoded packets to muxer.
     *
     * @param target - Media output component to write packets to
     *
     * @param streamIndex - Stream index to write packets to
     *
     * @returns Scheduler for continued chaining
     *
     * @example
     * ```typescript
     * decoder.pipeTo(filter).pipeTo(encoder)
     * ```
     */
    pipeTo(target: Muxer, streamIndex: number): SchedulerControl<Frame>;
    /**
     * Close encoder and free resources.
     *
     * Releases codec context and internal packet buffer.
     * Safe to call multiple times.
     * Automatically called by Symbol.dispose.
     *
     * @example
     * ```typescript
     * const encoder = await Encoder.create(FF_ENCODER_LIBX264, { ... });
     * try {
     *   // Use encoder
     * } finally {
     *   encoder.close();
     * }
     * ```
     *
     * @see {@link Symbol.dispose} For automatic cleanup
     */
    close(): void;
    /**
     * Get encoder codec.
     *
     * Returns the codec used by this encoder.
     * Useful for checking codec capabilities and properties.
     *
     * @returns Codec instance
     *
     * @internal
     *
     * @see {@link Codec} For codec details
     */
    getCodec(): Codec;
    /**
     * Get underlying codec context.
     *
     * Returns the codec context for advanced operations.
     * Useful for accessing low-level codec properties and settings.
     * Returns null if encoder is closed or not initialized.
     *
     * @returns Codec context or null if closed/not initialized
     *
     * @internal
     *
     * @see {@link CodecContext} For context details
     */
    getCodecContext(): CodecContext | null;
    /**
     * Worker loop for push-based processing.
     *
     * @internal
     */
    private runWorker;
    /**
     * Send frame to input queue or flush the pipeline.
     *
     * When frame is provided, queues it for encoding.
     * When null is provided, triggers flush sequence:
     * - Closes input queue
     * - Waits for worker completion
     * - Flushes encoder and sends remaining packets to output queue
     * - Closes output queue
     * - Waits for pipeTo task completion (writes to muxer)
     *
     * Used by scheduler system for pipeline control.
     *
     * @param frame - Frame to send, or null to flush
     *
     * @internal
     */
    private sendToQueue;
    /**
     * Receive packet from output queue.
     *
     * @returns Packet from output queue
     *
     * @internal
     */
    private receiveFromQueue;
    /**
     * Initialize encoder from first frame.
     *
     * Sets codec context parameters from frame properties.
     * Configures hardware context if present in frame.
     * Opens encoder with accumulated options.
     *
     * @param frame - First frame to encode
     *
     * @throws {FFmpegError} If encoder open fails
     *
     * @internal
     */
    private initialize;
    /**
     * Initialize encoder from first frame synchronously.
     * Synchronous version of initialize.
     *
     * Sets codec context parameters from frame properties.
     * Configures hardware context if present in frame.
     * Opens encoder with accumulated options.
     *
     * @param frame - First frame to encode
     *
     * @throws {FFmpegError} If encoder open fails
     *
     * @internal
     *
     * @see {@link initialize} For async version
     */
    private initializeSync;
    /**
     * Setup hardware acceleration for encoder.
     *
     * Implements FFmpeg's hw_device_setup_for_encode logic.
     * Validates hardware frames context format and codec support.
     * Falls back to device context if frames context is incompatible.
     *
     * @param frame - Frame to get hardware context from
     *
     * @internal
     */
    private setupHardwareAcceleration;
    /**
     * Configure the codec context's audio parameters from the first frame.
     *
     * Audio encoders only accept specific sample rates / sample formats / channel
     * layouts. This picks codec-supported targets; if they differ from the input it
     * either sets up a resampler (when `autoResample`) or throws a descriptive error.
     *
     * @param frame - First audio frame
     *
     * @throws {Error} If the input is unsupported and `autoResample` is disabled
     *
     * @throws {FFmpegError} If the resampler fails to configure
     *
     * @internal
     */
    private setupAudioParams;
    /**
     * Lazily allocate the reused resampler output frame.
     *
     * @returns The allocated output frame
     *
     * @internal
     */
    private getResampleFrame;
    /**
     * Resample an incoming audio frame to the codec's target format.
     *
     * Reuses a single output frame; `swr_convert_frame` allocates/sizes its buffer.
     * The (fixed-frame-size) audio FIFO copies the samples and re-stamps PTS, so the
     * reused frame and its carried timing are only relevant on the non-FIFO path.
     *
     * @param frame - Source audio frame
     *
     * @returns The resampled frame (owned by the encoder, reused across calls)
     *
     * @internal
     */
    private resampleAudio;
    /**
     * Drain samples buffered inside the resampler (rate-conversion delay) into the
     * encoder path. Returns the drained frame if any, else null.
     *
     * @returns The drained frame (reused), or null when the resampler is empty
     *
     * @internal
     */
    private drainResampler;
    /**
     * Configure the codec context's pixel format from the first video frame.
     *
     * Video encoders only accept specific pixel formats. This keeps the input format
     * when the codec accepts it; otherwise it either sets up a swscale converter to
     * the least-loss supported format (when `autoFormat`) or throws a descriptive
     * error. Hardware frames are left untouched - their format is negotiated through
     * the hardware frames context, not swscale.
     *
     * @param frame - First video frame
     *
     * @throws {Error} If the input is unsupported and `autoFormat` is disabled
     *
     * @throws {FFmpegError} If the converter fails to configure
     *
     * @internal
     */
    private setupVideoFormat;
    /**
     * Lazily allocate the reused scaler output frame.
     *
     * @returns The allocated output frame
     *
     * @internal
     */
    private getScaledFrame;
    /**
     * Convert an incoming video frame to the codec's target pixel format.
     *
     * Reuses a single output frame; `sws_scale_frame` allocates/sizes its buffer.
     * Resolution is unchanged - only the pixel format differs. Timing is carried over
     * explicitly so the encoder's PTS rescale stays correct.
     *
     * @param frame - Source video frame
     *
     * @returns The converted frame (owned by the encoder, reused across calls)
     *
     * @internal
     */
    private scaleVideo;
    /**
     * Prepare frame for encoding.
     *
     * Implements FFmpeg's frame_encode() pre-encoding logic:
     * 1. Video: Sets frame.quality from encoder's globalQuality (like -qscale)
     * 2. Audio: Validates channel count consistency for encoders without PARAM_CHANGE capability
     *
     * This matches FFmpeg CLI behavior where these properties are automatically managed.
     *
     * @param frame - Frame to prepare for encoding
     *
     * @throws {Error} If audio channel count changed and encoder doesn't support parameter changes
     *
     * @internal
     */
    private prepareFrameForEncoding;
    /**
     * Dispose of encoder.
     *
     * Implements Disposable interface for automatic cleanup.
     * Equivalent to calling close().
     *
     * @example
     * ```typescript
     * {
     *   using encoder = await Encoder.create(FF_ENCODER_LIBX264, { ... });
     *   // Encode frames...
     * } // Automatically closed
     * ```
     *
     * @see {@link close} For manual cleanup
     */
    [Symbol.dispose](): void;
}
