/**
 * API 调用执行器，提供成功和失败的回调。
 *
 * @public
 */
export declare interface AgoraApiExecutor<T> {
    onSuccess: (result: T) => void;
    onError: (err: Error) => void;
}

/**
 * 音频插件基类。
 *
 * 主线程上的 AudioExtension 只承载控制面状态和生命周期。实时音频处理放在
 * extensionDefinition 指向的 AudioWorklet 侧插件中；框架每次把 128 采样
 * 直接传给 worklet 侧插件的 processAudioFrame()。
 *
 * @public
 */
export declare abstract class AudioExtension extends Extension implements IAudioExtension {
    get kind(): Kind;
    /**
     * 框架级兼容性检测：音频实时处理依赖 AudioWorklet。
     *
     * 静态方法，集成方可在不实例化插件的前提下直接调用（`MyAudioExtension.checkCompatibility()`）。
     * 检测 `AudioWorkletNode` 与 `AudioContext`（含 `webkitAudioContext`）的 `audioWorklet`
     * 能力是否存在。具体插件可覆写并调用 `super.checkCompatibility()` 叠加自身依赖（如 WebAssembly、SIMD）。
     */
    static checkCompatibility(): boolean;
    /**
     * 创建一个绑定到给定音频 track 的 `AudioExtensionManager`。
     *
     * Escape hatch：供宿主 SDK 在**不对框架做 value import** 的前提下，经"业务传入的插件
     * 构造器"触达框架运行时。内部委派到 globalThis 单例（见 `singleton.ts` 的
     * `ensureRuntime`），因此即便页面上存在多份框架副本，全页面也只有一份活跃 runtime。
     *
     * 注意：manager 是 **track 级**、托管该 track 上所有插件的对象，与调用该静态方法的具体
     * 插件构造器实例无关——这里只是把构造器当作框架运行时的入口句柄。
     */
    static createAudioExtensionManager(track: AudioTrackLike): AudioExtensionManager;
    protected _audioContext: AudioContext | null;
    protected _sampleRate: number;
    init(context: AudioExtensionContext): void;
    destroy(options?: ExtensionDestroyOptions): void;
    applyEffect(): any;
}

/**
 * 音频插件构造器类型。
 * @public
 */
export declare interface AudioExtensionConstructor<T extends IAudioExtension = IAudioExtension> {
    new (...args: any[]): T;
    readonly extensionDefinition?: AudioExtensionDefinition;
    /**
     * 静态兼容性检测：可在不实例化插件的前提下直接调用，例如
     * `if (!MyAudioExtension.checkCompatibility()) { ... } else { manager.useExtension(MyAudioExtension); }`。
     * 由 `AudioExtension` 基类提供默认实现（AudioWorklet 检测），子类可覆写叠加自身依赖。
     */
    checkCompatibility?(): boolean;
    /**
     * 创建一个绑定到给定音频 track 的 `AudioExtensionManager`。
     *
     * 由 `AudioExtension` 基类提供的静态方法（子类继承），委派到框架的 globalThis 单例运行时。
     * 宿主 SDK 可借此在**仅做类型依赖**的前提下创建 manager，无需 value import 框架。
     * 详见 `extension_audio.ts` 中的实现与 `singleton.ts`。
     */
    createAudioExtensionManager(track: AudioTrackLike): AudioExtensionManager;
}

/**
 * 音频插件的上下文信息，包含 AudioContext 和采样率。
 *
 * @public
 */
export declare type AudioExtensionContext = {
    audioContext: AudioContext;
    sampleRate: number;
    /** 用户通过 useExtension() 传入的插件初始化选项。 */
    extensionOptions?: Record<string, unknown>;
};

/**
 * 框架在 AudioWorklet 中实例化插件所需的元数据。
 *
 * moduleURL 会先通过 audioContext.audioWorklet.addModule() 加载。该模块需要调用
 * registerAudioWorkletExtension(registrationName, WorkletExtensionCtor)，随后框架
 * 通过 registrationName 从 Worklet 全局注册表中创建插件实例。
 *
 * @public
 */
export declare type AudioExtensionDefinition = {
    moduleURL: string;
    registrationName: string;
};

/**
 * 单个音频 Track 的插件管理器。
 *
 * 每个实例绑定到一个输入音频 Track，负责该 Track 上插件链的注册、启用、
 * 销毁与参考 Track 接入。第一个插件注册时自动启动处理链，最后一个插件
 * 销毁后自动停止；中间过程可以热增删插件而无需重建管线。
 */
export declare class AudioExtensionManager {
    private _audioTrack;
    private _extensions;
    private _extensionCtors;
    private _extensionIds;
    private _extensionOptions;
    private _extensionEventCleanups;
    private _extensionsByCtor;
    private _extensionInitPromises;
    private _pendingRemovals;
    private _nextExtensionId;
    private _loadedWorkletModuleURLs;
    private _referenceTracks;
    private _referenceSourceNodes;
    private _context?;
    private _workletNode?;
    private _sourceNode?;
    private _destNode?;
    private _isRunning;
    private _outputTrack?;
    private _workletRegistered;
    private _destroyed;
    onOutputTrackChanged?: (track: MediaStreamTrack | undefined) => void;
    constructor(audioTrack: AudioTrackLike);
    /** 是否仍有处于活跃状态的音频插件。 */
    get hasExtensions(): boolean;
    /**
     * 为指定音频插件构造器创建或复用主线程控制面实例。
     * 同一个构造器始终返回同一个实例。
     */
    useExtension<T extends IAudioExtension>(ctor: AudioExtensionConstructor<T>, extensionOptions?: Record<string, unknown>): T;
    /**
     * 初始化插件的主线程控制面，并将其挂载到处理链上。
     *
     * 首次注册插件时会同时启动整条处理链；后续注册走热添加路径，仅加载该插件
     * 的 worklet 模块并通过 postMessage 通知 worklet 端实例化。
     */
    private _initAndRegister;
    /**
     * 整体启用或禁用音频处理链。
     * 禁用状态下 worklet 直接透传输入到输出，不调用任何插件的 processAudioFrame。
     */
    setEnabled(enabled: boolean): void;
    /**
     * 从处理链中移除并销毁指定插件。
     * 如果是最后一个插件，会自动停止整条处理链；返回值指示插件是否真的被移除。
     */
    removeExtension(extension: IAudioExtension): boolean;
    /**
     * 添加一个参考 Track，作为额外的 worklet 输入接入到 1..N 端口。
     *
     * 用于回声消除等需要远端音频做参考的算法。如果链路尚未启动，仅记录到
     * `_referenceTracks` 列表，等待 `_startProcessing` 阶段一并接入。
     */
    addReferenceTrack(track: AudioTrackLike): void;
    /**
     * 移除已添加的参考 Track，并断开其在 worklet 上的输入端口。
     * 若 track 未注册，返回 false。
     */
    removeReferenceTrack(track: AudioTrackLike): boolean;
    /** 停止处理链，销毁所有插件并清空内部映射。整体不可恢复，重新使用须新建 manager。 */
    destroy(): void;
    /** 懒创建共享 AudioContext 并缓存采样率。失败时记录错误并保持 `_context` 为 undefined。 */
    private _initContext;
    /**
     * 把 worklet 端上报的插件错误打印到主线程控制台。
     *
     * worklet 内的 `console.*` 不会出现在主线程控制台，因此插件在 worklet 里的
     * init / processAudioFrame 异常必须通过 port 消息回传。这里把 worklet id 映射回
     * 插件名，优先打印 stack（定位到插件 bundle 内的具体位置），并标注来源阶段
     * （`source`）与节流窗口内的累计次数（`occurrences`）。
     */
    private _reportWorkletError;
    /** 按 worklet 分配的数字 id 反查插件名（用于错误日志定位）。 */
    private _extensionNameById;
    /** 清理单个扩展的所有主线程记录，可选择调用 extension.destroy()。 */
    private _cleanupExtensionRecord;
    /**
     * 将单个插件连接到 worklet。
     *
     * 插件必须通过 extensionDefinition 提供 AudioWorklet 侧实现，
     * 框架在 worklet 中实例化插件并直接传递 128 采样进行同步处理。
     */
    private _connectExtension;
    /**
     * 启动 AudioWorklet 处理链。
     *
     * 步骤：
     * 1. 为所有已注册插件加载各自的 worklet 模块；
     * 2. 注册框架 worklet 处理器（每个 AudioContext 只注册一次）；
     * 3. 构造 AudioWorkletNode，并把它与源 Track / 参考 Tracks 连接到对应的端口；
     * 4. 通知 worklet 端实例化各插件；
     * 5. 通过 `MediaStreamAudioDestinationNode` 把输出转回 MediaStream Track；
     * 6. 发送 enable 消息，让 worklet 真正开始转发到插件。
     *
     * 启动过程中任意一步抛错都会把 `_isRunning` 回退到 false，避免半启动状态。
     */
    private _startProcessing;
    /**
     * 关闭处理链：先让 worklet 进入 disable（透传），再断开主线程上的所有 AudioNode，
     * 并把输出 Track 置空通知宿主。再次启动需要重新走 `_startProcessing`。
     */
    private _stopProcessing;
    /** 断开所有参考 Track 对应的 AudioNode，并清空缓存。 */
    private _disconnectReferences;
    /**
     * 按需通过 `audioWorklet.addModule` 加载某个插件提供的 worklet 模块。
     * 同一个 moduleURL 只会被加载一次（用 `_loadedWorkletModuleURLs` 去重）。
     */
    private _loadExtensionWorkletModule;
    /**
     * 把主线程控制面实例的 `enabled` / `disabled` 事件桥接到 worklet 端：
     * 主线程上插件被 enable/disable 时，会通过 postMessage 通知 worklet 切换该插件的开关，
     * 而无需把整条链路重启。
     */
    private _bindExtensionEvents;
    /** 解绑由 `_bindExtensionEvents` 注册的所有事件回调。 */
    private _cleanupExtensionEvents;
}

/**
 * 运行时框架使用的音频 Track 抽象接口。
 *
 * @public
 */
export declare interface AudioTrackLike {
    readonly mediaStreamTrack: MediaStreamTrack;
}

/**
 * AudioWorklet 侧插件构造器。
 *
 * @public
 */
export declare interface AudioWorkletExtensionConstructor<T extends IAudioWorkletExtension = IAudioWorkletExtension> {
    new (...args: any[]): T;
}

/**
 * AudioWorklet 侧插件的初始化上下文。
 *
 * @public
 */
export declare type AudioWorkletExtensionContext = {
    sampleRate: number;
    extensionOptions?: Record<string, unknown>;
};

/**
 * `EventEmitter` 类提供了定义、触发和处理事件的方式。
 *
 * @public
 */
export declare class EventEmitter {
    /**
     * 存储所有已注册事件及其对应监听器列表的映射表。
     */
    private _events;
    /**
     * 单个事件允许的最大监听器数量。超过此数量时会输出警告（可能存在内存泄漏）。
     * 设为 0 表示不限制。
     */
    private _maxListeners;
    /**
     * 设置单个事件允许的最大监听器数量。
     *
     * @param n - 最大监听器数量，0 表示不限制。
     */
    setMaxListeners(n: number): void;
    /**
     * 指定一个事件名，获取当前所有监听这个事件的回调函数。
     *
     * @param event - 事件名称。
     * @returns 该事件的所有回调函数数组，如果没有监听器则返回空数组。
     */
    getListeners(event: string): Function[];
    /**
     * 监听一个指定的事件，当事件触发时会调用传入的回调函数。
     *
     * @param event - 指定事件的名称。
     * @param listener - 传入的回调函数。
     */
    on(event: string, listener: Function): void;
    /* Excluded from this release type: addListener */
    /**
     * 监听一个指定的事件，当事件触发时会调用传入的回调函数。
     *
     * 当监听后事件第一次触发时，该监听和回调函数就会被立刻移除，也就是只监听一次指定事件。
     *
     * @param event - 指定事件的名称。
     * @param listener - 传入的回调函数。
     */
    once(event: string, listener: Function): void;
    /**
     * 取消一个指定事件的监听。
     *
     * @param event - 指定事件的名称。
     * @param listener - 监听事件时传入的回调函数。
     */
    off(event: string, listener: Function): void;
    /**
     * 指定一个事件，取消其所有的监听。
     *
     * @param event - 指定事件的名称，如果没有指定事件，则取消所有事件的所有监听。
     */
    removeAllListeners(event?: string): void;
    /**
     * 触发一个指定的事件，依次调用该事件的所有监听器。
     *
     * 如果监听器是通过 {@link EventEmitter.once | once} 注册的，触发后会被自动移除。
     *
     * @param event - 要触发的事件名称。
     * @param args - 传递给监听器回调函数的参数。
     */
    emit(event: string, ...args: any[]): void;
    /* Excluded from this release type: safeEmit */
    /**
     * 在监听器数组中查找指定回调函数的索引。
     *
     * @param listeners - 监听器数组。
     * @param listener - 要查找的回调函数。
     * @returns 回调函数在数组中的索引，如果未找到则返回 `-1`。
     */
    private _indexOfListener;
}

/**
 * 插件基类，提供了插件的基本生命周期管理和事件机制。
 *
 * @public
 */
export declare abstract class Extension extends EventEmitter implements IExtension {
    abstract name: string;
    protected _enabled: boolean;
    readonly ID: string;
    /* Excluded from this release type: __logger */
    abstract get kind(): Kind;
    get enabled(): boolean;
    constructor();
    init(context: any): void;
    destroy(_options?: ExtensionDestroyOptions): void;
    enable(): Promise<void>;
    protected onEnable(): Promise<void>;
    disable(): Promise<void>;
    protected onDisable(): Promise<void>;
    /**
     * 检测当前运行环境是否支持该插件（静态版本）。
     *
     * 设计为**静态方法**，以便集成方在**不实例化插件**的前提下于主线程直接调用，例如
     * `if (!MyVideoExtension.checkCompatibility()) { ... } else { manager.useExtension(MyVideoExtension); }`。
     * 基类默认返回 `true`；`VideoExtension` / `AudioExtension` 覆写为框架级检测
     * （WebGL2 / AudioWorklet），具体插件可进一步覆写叠加自身依赖（如 WebAssembly、SIMD）。
     */
    static checkCompatibility(): boolean;
    /**
     * 检测当前运行环境是否支持该插件（实例版本）。
     *
     * 默认委派到构造器上的同名静态方法，因此子类只需覆写静态方法即可同时影响静态与实例调用。
     * 推荐直接用静态形式 `MyExtension.checkCompatibility()`，无需先创建实例。
     */
    checkCompatibility(): boolean;
    abstract applyEffect(frame: any): any;
}

/**
 * 销毁插件时传入的原因/选项。
 *
 * @public
 */
export declare type ExtensionDestroyOptions = {
    reason?: "normal" | "context-loss";
};

/**
 * {@link ExtensionEvents.ERROR} 事件的负载。
 *
 * @public
 */
export declare type ExtensionErrorEvent = {
    /**
     * 失败来源标签，便于区分场景。例如：
     * - `"worker-fallback"`：框架共享 worker 不可用，整条 track 已切到插件自有 worker
     *   （仍在运行，只是更低效），此时 `degraded` 为 `false`；
     * - `"applyEffect"`：逐帧处理失败（worker 或主线程）；
     * - `"contextRestore.reinit"` / `"contextLoss.cpuInit"`：context 恢复/回退失败。
     */
    source: string;
    /** 归一化后的错误信息。`name`/`message` 来自原始错误，`stack` 尽量保留以便定位。 */
    error: {
        name: string;
        message: string;
        stack?: string;
    };
    /**
     * 是否为"退化但仍在运行"的状态：例如逐帧失败时框架会透传原始帧，
     * 画面可用但插件效果缺失。业务可据此决定是否提示用户或停用插件。
     */
    degraded: boolean;
    /** 节流窗口内该错误的累计次数（逐帧错误会聚合上报）。默认为 1。 */
    occurrences?: number;
};

/**
 * 插件事件枚举，定义了插件可能触发的事件。
 */
export declare enum ExtensionEvents {
    /**
     * 插件被启用时触发。
     */
    ENABLED = "enabled",
    /**
     * 插件被禁用时触发。
     */
    DISABLED = "disabled",
    /**
     * 插件运行期间发生失败时触发（业务侧可观测的失败信号）。
     *
     * 与 `enable()`/`setOptions()` 等调用直接 reject 的"操作级"错误不同，本事件覆盖
     * 那些只在控制台打印、业务侧无法从调用处感知的失败，典型来源：
     * - worker / 主线程逐帧 `applyEffect` 失败（插件已在静默透传 passthrough）；
     * - WebGL context 丢失后的重建 / 配置重放失败。
     *
     * 监听器收到的参数形状见 {@link ExtensionErrorEvent}。该事件**不**取代调用处的
     * try/catch；它是补充的"带外"信号，便于业务做降级提示或埋点。
     */
    ERROR = "error"
}

/**
 * useExtension 的选项。
 * @public
 */
export declare type ExtensionOptions = {
    /**
     * 渲染模式。
     * - "auto"（默认）：优先 GPU（WebGL2），不可用时降级到 CPU
     * - "gpu"：强制 GPU 模式，WebGL2 不可用时抛错
     * - "cpu"：强制 CPU 模式，即使 WebGL2 可用也走 CPU 路径
     */
    renderMode?: "auto" | "gpu" | "cpu";
    /**
     * 线程模式。
     * - "auto"（默认）：优先 Worker（需要流 API 支持），不可用时降级到主线程
     * - "worker"：强制 Worker 模式，流 API 不可用时抛错
     * - "main"：强制主线程模式
     *
     * Worker 模式下 GPU 处理通过 OffscreenCanvas + WebGL2 在 Worker 内执行，
     * CPU 处理通过 TransformStream 在 Worker 内执行。
     * 两种情况都不阻塞主线程。
     */
    threadMode?: "auto" | "worker" | "main";
    /**
     * 插件的初始业务配置。
     *
     * 框架会在插件 `init()` 完成后，自动用这份配置调用一次 `setOptions(extensionOptions)`，
     * 因此调用方无需在 `useExtension()` 之后再手动调一次 `setOptions`。
     * 后续运行时更新配置请直接调用代理上的 `setOptions(...)`。
     *
     * 仅在首次创建该插件代理时消费；同一插件代理已存在时，重复传入的
     * `extensionOptions` 会被忽略（要改配置请用 `setOptions`）。
     *
     * 与 `renderMode` / `threadMode` 正交：这是纯业务数据，框架只透传不解读，
     * 在 worker-gpu / worker-cpu / main-gpu 各后端下传给插件的内容完全一致。
     */
    extensionOptions?: Record<string, unknown>;
    /**
     * 显式指定插件产物的可加载 URL（Worker 会 `import()` 它）。
     *
     * 这是给集成方的“逃生舱”：当插件被二次打包进宿主 bundle、走 CDN、或自定义
     * 部署路径，导致插件构造器里写死的 `import.meta.url` 解析不到独立产物文件时，
     * 集成方可以在 `useExtension` 时直接提供真实可访问的 URL。
     *
     * 优先级：本字段 > 构造器静态 `extensionDefinition.moduleURL`。
     * 缺省时回退到构造器静态字段（行为与历史一致，向后兼容）。
     *
     * 典型用法（让打包器算出独立资源 URL，避免硬编码）：
     * ```ts
     * import url from "my-extension/dist/index.esm.js?url"; // Vite
     * useExtension(MyExtension, { moduleURL: url });
     * ```
     * 或直接给 CDN / 静态目录地址：
     * ```ts
     * useExtension(MyExtension, { moduleURL: "https://cdn.example.com/my-extension.esm.js" });
     * ```
     *
     * 注意：仅在首次创建该插件代理时消费；跨源 URL 需服务端带 CORS 头。
     */
    moduleURL?: string;
    /**
     * 与 {@link moduleURL} 配套的注册名，对应插件产物顶层
     * `registerVideoExtension(registrationName, Ctor)` 使用的名字。
     *
     * 通常无需提供：缺省时回退到构造器静态 `extensionDefinition.registrationName`，
     * 因此集成方一般只需传 `moduleURL` 即可。仅当插件构造器未声明
     * `extensionDefinition` 时，才需要连同 `moduleURL` 一起显式提供。
     */
    registrationName?: string;
};

/**
 * 框架 Worker 与插件**自有 fallback worker** 脚本之间的 process-only 消息协议。
 *
 * 仅用于 routed 子模式（框架共享 worker 的 `import(moduleURL)` 失败后，整条 track 改用
 * 各插件自带的 worker 处理）。**老插件模式：每个插件 worker 自有 `MSTP→处理→MSTG` 管线**，
 * 由主线程用原生 `MediaStreamTrackProcessor`/`MediaStreamTrackGenerator` 在主线程侧搭桥
 * （`capture → MSTP → 插件1 → track → MSTP → 插件2 → … → 输出 track`）。
 *
 * 帧通道用**原生 MSTP/MSTG**而非普通 transferable stream：把 VideoFrame 写入跨 realm 的普通
 * `TransformStream` 会**克隆**（不转移所有权）导致发送侧泄漏；而 `MSTP.readable`（worker 内读）
 * 与 `MSTG.writable`（worker 内写）是原生帧通道，不克隆/不泄漏。因此 `connect-frame-pipe` 把
 * 主线程建的输入 `readable`（MSTP）+ 可选输出 `writable`（Chrome 的 MSTG）交进插件 worker；
 * Safari 无 `MediaStreamTrackGenerator`，插件 worker 自建 `VideoTrackGenerator` 并在回复里把
 * `{ track }` 交回主线程作为该段输出。
 *
 * 插件提供的 worker 脚本（通常由框架的 `runPluginFallbackWorker` helper 实现）必须响应：
 * - init-plugin: 初始化插件实例（gpu 模式下创建该 worker 自己的 GL context）
 * - connect-frame-pipe: 接入输入/输出端，建立本段 `readable.pipeThrough(处理).pipeTo(writable)`
 *   （重建帧链时再次下发以换用新端；Safari 回复携带自建 VTG 的 `track`）
 * - set-options: 声明式下发配置
 * - enable / disable: 启用 / 禁用（禁用时直通）
 * - destroy: 释放资源
 *
 * 注：`type` 的字符串值与框架内部的 `WorkerMessageType` 枚举一致；每条请求都带 `requestId`，
 * worker 回复同 `requestId` 表示完成（见 `ExtensionWorkerResponse`）。
 *
 * @public
 */
export declare type ExtensionWorkerMessage = {
    type: "init-plugin";
    mode: VideoExtensionBackend;
    enabled?: boolean;
    extensionOptions?: Record<string, unknown>;
    requestId?: string;
    data?: any;
} | {
    type: "connect-frame-pipe";
    readable: ReadableStream;
    writable?: WritableStream;
    requestId?: string;
} | {
    type: "set-options";
    options: Record<string, unknown>;
    requestId?: string;
} | {
    type: "enable";
    requestId?: string;
} | {
    type: "disable";
    requestId?: string;
} | {
    type: "destroy";
    requestId?: string;
} | {
    type: "simulate-context-loss";
    requestId?: string;
} | {
    type: "simulate-context-restore";
    requestId?: string;
};

/**
 * 插件自有 fallback worker 脚本回复给框架的消息。
 *
 * 应答类（带 `requestId`）回执同类型表示完成；`connect-frame-pipe` 的回复在 Safari 下携带
 * 自建 `VideoTrackGenerator` 的 `track`。主动上行：`on-emit`（插件出站事件）、`async-error`
 * （逐帧/context 恢复失败，节流）、`error`（init 等控制路径失败）、`log`（日志转发）。
 * @public
 */
export declare type ExtensionWorkerResponse = {
    type: "init-plugin";
    requestId?: string;
} | {
    type: "connect-frame-pipe";
    track?: MediaStreamTrack;
    requestId?: string;
} | {
    type: "set-options";
    requestId?: string;
} | {
    type: "enable";
    requestId?: string;
} | {
    type: "disable";
    requestId?: string;
} | {
    type: "destroy";
    requestId?: string;
} | {
    type: "simulate-context-loss";
    requestId?: string;
} | {
    type: "simulate-context-restore";
    requestId?: string;
} | {
    type: "on-emit";
    name: string;
    data?: any;
} | {
    type: "async-error";
    extensionId?: string;
    sourceType?: string;
    name?: string;
    message?: string;
    stack?: string;
    occurrences?: number;
} | {
    type: "error";
    requestId?: string;
    sourceType?: string;
    name?: string;
    message: string;
    stack?: string;
};

/**
 * 插件处理输入帧的统一抽象。
 *
 * @public
 */
export declare type Frame = ({
    kind: "gpu";
    videoFrame?: undefined;
} & VideoFrameTextures) | {
    kind: "cpu";
    width: number;
    height: number;
    input?: undefined;
    output?: undefined;
    videoFrame: VideoFrame;
};

/**
 * 从音频插件构造器读取 AudioWorklet 实例化元数据。
 *
 * @public
 */
export declare function getAudioExtensionDefinition(ctor: AudioExtensionConstructor): AudioExtensionDefinition | undefined;

/**
 * 从视频插件构造器读取 Worker 实例化元数据。
 *
 * @public
 */
export declare function getVideoExtensionDefinition(ctor: VideoExtensionConstructor): VideoExtensionDefinition | undefined;

/**
 * 音频插件接口。
 *
 * 主线程上的 AudioExtension 只承载控制面状态和生命周期。真正的实时音频处理由
 * extensionDefinition 指向的 AudioWorklet 侧插件完成。
 *
 * 框架每次将 128 采样直接传给 AudioWorklet 侧插件的 processAudioFrame()，
 * 插件处理完返回 128 采样，再传给下一个插件，最终输出到音频图。
 *
 * @public
 */
export declare interface IAudioExtension extends IExtension {
    readonly enabled: boolean;
    /**
     * 初始化插件。
     */
    init(context: AudioExtensionContext): void | Promise<void>;
    /**
     * 销毁插件并释放相关资源。
     */
    destroy(options?: ExtensionDestroyOptions): void;
}

/**
 * AudioWorklet 侧插件实例。
 *
 * 实例运行在 AudioWorkletProcessor 所在的实时音频线程中，processAudioFrame()
 * 必须同步、低分配、不可 await。需要更大帧长或 WASM 资源的插件应在 init()
 * 中准备资源，并在实例内部缓冲，把 128 sample quantum 和算法帧长解耦。
 *
 * @public
 */
export declare interface IAudioWorkletExtension {
    init?(context: AudioWorkletExtensionContext): void | Promise<void>;
    destroy?(): void;
    enable?(): void;
    disable?(): void;
    processAudioFrame(input: Float32Array, referenceInputs?: Float32Array[]): Float32Array;
}

/**
 * 插件接口，定义了插件的基本结构和生命周期方法。
 *
 * @public
 */
export declare interface IExtension {
    /**
     * 插件的名称，只读属性。
     */
    readonly name: string;
    /**
     * 插件处理的媒体类型。
     */
    kind: Kind;
    /**
     * 初始化插件。
     *
     * @param context - 插件初始化时的上下文信息。
     */
    init(context: any): void | Promise<void>;
    /**
     * 启用插件。
     */
    enable(): void | Promise<void>;
    /**
     * 禁用插件。
     */
    disable(): void | Promise<void>;
    /**
     * 销毁插件并释放相关资源。
     */
    destroy(options?: ExtensionDestroyOptions): void;
    /**
     * 检测当前运行环境是否支持该插件，供集成方在使用前做统一的兼容性自检。
     *
     * 返回 `true` 表示当前浏览器/环境满足插件运行所需能力；`false` 表示不满足，
     * 集成方应避免启用该插件并给出降级提示。基类提供默认实现（video 检测 WebGL2、
     * audio 检测 AudioWorklet），具体插件可覆写以叠加自身依赖（如 WebAssembly、SIMD 等）。
     *
     * @returns 当前环境是否兼容该插件。
     */
    checkCompatibility?(): boolean;
}

/**
 * 插件日志接口，定义了日志输出的方法。
 *
 * @public
 */
export declare interface IExtensionLogger {
    debug(...args: any): void;
    info(...args: any): void;
    warning(...args: any): void;
    error(...args: any): void;
    setLogLevel(level: number): void;
}

/**
 * 插件上报接口，定义了 API 调用上报的方法。
 *
 * @public
 */
export declare interface IExtensionReporter {
    reportApiInvoke<T>(params: ReportApiInvokeParams, throttleTime?: number): AgoraApiExecutor<T>;
}

/**
 * 视频插件接口。
 *
 * 框架调度策略：
 * 1. 收集所有 enabled 插件，按 useExtension 顺序排列
 * 2. 按顺序 ping-pong 执行每个插件的 applyEffect
 * 3. 最终结果 blit 到 canvas 输出
 *
 * 常见插件路径：
 * - 纯 GPU 路径：input texture → output texture。零额外 CPU 拷贝，效率最高。
 *   例：SuperClarity、Beauty。所有新插件优先采用这一模式。
 * - VideoFrame 兼容路径：框架 blit texture → canvas → VideoFrame → 插件
 *   → 插件返回 VideoFrame → 框架 texImage2D 回 texture。会增加 CPU↔GPU 往返。
 *   仅建议用于无法适配 TEXTURE 模式的存量插件迁移。
 * - Worker 后端：框架把帧 I/O 放到 Worker，中间仍复用同一套 Extension 接口。
 *
 * ─── 与业务侧的双向通信 ───
 *
 * - 入站（业务 → 插件）：唯一入口是 {@link IVideoExtension.setOptions | setOptions}。
 *   配置、甚至水印图片等都通过它声明式地下发，框架自动把图片 / ArrayBuffer 等
 *   不可克隆数据转成 Transferable 后跨 Worker 边界传递。
 * - 出站（插件 → 业务）：插件调用继承自 {@link EventEmitter} 的 `emit(name, data)`，
 *   框架把它转发到主线程代理，业务侧通过代理的 `on(name, handler)` 监听
 *   （例如逐帧 face landmark 数据）。
 *
 * @typeParam TOptions - 该插件 `setOptions` 接受的配置形状。
 *
 * @public
 */
export declare interface IVideoExtension<TOptions = Record<string, unknown>> extends IExtension {
    readonly enabled: boolean;
    readonly mode: VideoExtensionMode;
    /**
     * 插件是否支持 CPU 回退模式。
     *
     * 当 WebGL context 丢失时，框架会对 supportsCPUMode=true 的插件
     * 调用 `applyEffect({ kind: "cpu" })` 进行 CPU 回退处理。
     * 不支持 CPU 模式的插件在 context 丢失期间会被跳过。
     * 默认 false。
     */
    readonly supportsCPUMode: boolean;
    init(context: VideoExtensionContext): void | Promise<void>;
    destroy(options?: ExtensionDestroyOptions): void;
    /**
     * 唯一的入站配置入口（声明式）。
     *
     * 业务侧的所有配置更新都经由此方法下发：插件根据传入的配置自行 diff 并应用。
     * 配置中的图片（HTMLImageElement / ImageBitmap）、ArrayBuffer 等不可结构化克隆
     * 的数据，会由框架在跨 Worker 边界前自动转换为 Transferable，插件无需手动序列化。
     *
     * 框架在插件 `init()` 完成后会用 `useExtension()` 的初始 `extensionOptions`
     * 自动调用一次本方法，因此「初始配置」与「运行时更新」走同一段代码路径。
     *
     * 返回的 Promise 在配置应用完成（worker 模式下为 Worker 内应用完成）后 resolve，
     * 出错时 reject，业务侧可 await 并 try/catch。
     *
     * ─── 重放（context loss / worker 重启）：框架自动深合并，作者无需配合 ───
     *
     * 框架会缓存每次下发的 options，用于 WebGL context 丢失 / Worker 重启后重建实例时
     * **自动重放**配置。缓存合并由框架统一处理（见 `internal/options_merge.ts`）：
     *
     * - **普通对象（plain object）子树会被深合并**：先 `setOptions({ beauty: { smoothness } })`
     *   再 `setOptions({ beauty: { whitening } })`，重放时 `smoothness` 与 `whitening` 都在。
     *   分片下发的配置天然保真，插件作者**无需**在实例内部自行累积，也无需把完整状态
     *   每次整体传入。
     * - **数组整体替换**：`setOptions({ watermarks: [...] })` 传入新列表即替换旧列表，
     *   不会把多次传入的数组元素并起来。这保留了"传入完整列表即替换全部"的声明式语义。
     * - **类实例 / ImageBitmap / ArrayBuffer 等非普通对象整体替换**（不深克隆）。
     *
     * 即：嵌套对象会累积、数组会替换。绝大多数配置形状都能直接得到符合直觉的重放结果，
     * 无需任何额外约定。
     */
    setOptions(options: Partial<TOptions>): void | Promise<void>;
    /** 统一处理入口：GPU 模式传入纹理帧，CPU 模式传入 VideoFrame。 */
    applyEffect(frame: Frame): Promise<void | VideoFrame>;
    /**
     * VIDEO_FRAME 模式的处理方法。
     * 在 GPU 管线中，框架自动做 texture ↔ VideoFrame 转换后调用此方法。
     * 在 CPU 管线中，直接收到 VideoFrame。
     *
     * 也可以通过 applyEffect(frame) 处理 kind === "cpu" 来替代。
     */
    processVideoFrame?(frame: VideoFrame): Promise<VideoFrame>;
}

/**
 * 媒体类型，表示视频或音频。
 *
 * @public
 */
export declare type Kind = "video" | "audio";

/**
 * 日志管理器，提供不同级别的日志输出能力。
 *
 * @public
 */
export declare class Logger implements IExtensionLogger {
    private logLevel;
    private hookLog?;
    /**
     * 设置 SDK 的日志输出级别
     * @param level - SDK 日志级别依次为 NONE(4)，ERROR(3)，WARNING(2)，INFO(1)，DEBUG(0)。选择一个级别，
     * 你就可以看到在该级别及该级别以上所有级别的日志信息。
     *
     * 例如，如果你输入代码 Logger.setLogLevel(1);，就可以看到 INFO，ERROR 和 WARNING 级别的日志信息。
     */
    setLogLevel(level: number): void;
    /** 以 DEBUG 级别输出日志。 */
    debug(...args: any): void;
    /** 以 INFO 级别输出日志。 */
    info(...args: any): void;
    /** 以 WARNING 级别输出日志。 */
    warning(...args: any): void;
    /** 以 ERROR 级别输出日志。 */
    error(...args: any): void;
    /**
     * 真正写日志的内部入口。
     * - 第一个参数为日志级别（0-4），其余为透传给 console 的内容。
     * - 启动后 100ms 内的日志会被延后输出，避免用户尚未来得及调用
     *   `setLogLevel` 关闭日志时仍打印初始消息。
     * - 同步触发 `hookLog`（如果设置），供 Worker 侧把日志转发到主线程。
     * - 仅当级别 ≥ 当前 `logLevel` 时才输出到 console。
     */
    private log;
}

export declare const logger: Logger;

/**
 * 在 AudioWorklet 模块中注册音频插件类。
 *
 * 插件的 worklet 侧产物在顶层调用一次本函数，把处理类按 `registrationName` 写入挂在
 * `globalThis` 上的注册表。框架 `addModule()` 加载该产物触发此注册后，按 definition 里的
 * `registrationName` 取出处理类并实例化。
 *
 * 注册表挂在 `globalThis`（而非模块级变量）：插件 bundle 与 AudioWorklet 是两个独立 realm，
 * 各自持有自己的模块实例，只能通过共享的全局对象对接。
 *
 * @public
 */
export declare function registerAudioWorkletExtension(registrationName: string, ctor: AudioWorkletExtensionConstructor): void;

/**
 * 在 Worker 模块中注册视频插件类。
 *
 * 插件产物（ESM/UMD）在顶层调用一次本函数，把插件类按 `registrationName` 写入挂在
 * `globalThis` 上的注册表。框架 `import()` 该产物触发此注册后，按 definition 里的
 * `registrationName` 取出插件类并实例化。
 *
 * 注册表挂在 `globalThis`（而非模块级变量）：插件 bundle 与框架 Worker bundle 是两份
 * 独立产物，各自持有自己的模块实例，只能通过共享的全局对象对接。
 *
 * @public
 */
export declare function registerVideoExtension(registrationName: string, ctor: VideoExtensionConstructor): void;

/**
 * API 调用上报参数。
 *
 * @public
 */
export declare interface ReportApiInvokeParams {
    name: string;
    options: any;
    reportResult?: boolean;
    timeout?: number;
}

/**
 * 上报器，用于收集和上报 API 调用信息。
 *
 * @public
 */
export declare class Reporter implements IExtensionReporter {
    /**
     * 在 `hookApiInvoke` 尚未注入前积压待上报消息。
     * 一旦宿主侧（如 RTC SDK）注入 hook，则把队列与最新消息一起刷新出去，
     * 之后队列保持为空。
     */
    private apiInvokeMsgQueue;
    /** 由宿主 SDK 注入的实际上报实现；未注入时消息会被缓存到 `apiInvokeMsgQueue`。 */
    private hookApiInvoke?;
    /**
     * 上报一次 API 调用，返回一个执行器，调用方在异步操作完成后调用
     * `onSuccess` / `onError` 即可触发上报。
     *
     * 默认行为：
     * - `params.timeout`：默认 60s。超时未结束自动以 `API_INVOKE_TIMEOUT` 上报失败。
     * - `params.reportResult`：默认为 true，会把 `onSuccess` 接收到的结果一并上报。
     * - 同一个执行器只能结束一次；二次调用 `onSuccess`/`onError` 会抛出。
     *
     * @typeParam T - `onSuccess` 接收到的结果类型。
     */
    reportApiInvoke<T>(params: ReportApiInvokeParams): AgoraApiExecutor<T>;
    /**
     * 将一条上报消息派发出去。
     *
     * 若宿主 SDK 已注入 `hookApiInvoke`，则连同积压队列一起送出后清空队列；
     * 否则把消息压入队列，等待后续 hook 注入时再 flush。
     */
    private sendApiInvoke;
}

/**
 * 全局 Reporter 单例，用于上报 API 调用信息。
 *
 * @public
 */
export declare const reporter: Reporter;

/**
 * 在插件自有 worker 内启动 process-only 运行时（原生 MSTP/MSTG 帧通道）。
 *
 * @param Ctor 插件构造器（与主线程 `useExtension` 用的是同一个类）。
 * @param scope 控制/出站通道端点；默认 `self`（worker 全局，连到插件主线程）。
 */
export declare function runPluginFallbackWorker(Ctor: VideoExtensionConstructor, scope?: {
    postMessage: (msg: any, transfer?: Transferable[]) => void;
    onmessage: ((ev: MessageEvent) => void) | null;
}): void;

/** 框架版本号。构建期由 rollup `@rollup/plugin-replace` 把 `__VERSION__` 替换为 package.json version。
 *
 * @public
 */
export declare const VERSION: string;

/**
 * 视频插件基类，提供共享的 WebGL 工具方法。
 *
 * 子类只需关注 WASM 初始化和调用，通用的 GL 操作（直通渲染、
 * texture 拷贝、FBO 管理等）由基类提供。
 *
 * 业务侧通过 `setOptions` 下发配置（声明式，子类覆写实现），通过继承自
 * `EventEmitter` 的 `emit` 向业务侧推送数据（框架自动跨线程转发）。
 *
 * @typeParam TOptions - 该插件 `setOptions` 接受的配置形状。
 *
 * @public
 */
export declare abstract class VideoExtension<TOptions = Record<string, unknown>> extends Extension implements IVideoExtension<TOptions> {
    get kind(): Kind;
    /**
     * 创建一个绑定到给定视频 track 的 `VideoExtensionManager`。
     *
     * Escape hatch：供宿主 SDK 在**不对框架做 value import** 的前提下，经"业务传入的插件
     * 构造器"触达框架运行时。内部委派到 globalThis 单例（见 `singleton.ts` 的
     * `ensureRuntime`），因此即便页面上存在多份框架副本，全页面也只有一份活跃 runtime。
     *
     * 注意：manager 是 **track 级**、托管该 track 上所有插件的对象，与调用该静态方法的具体
     * 插件构造器实例无关——这里只是把构造器当作框架运行时的入口句柄。
     */
    static createVideoExtensionManager(track: VideoTrackLike): VideoExtensionManager;
    /**
     * 默认为 TEXTURE 模式。子类可覆写为 VIDEO_FRAME。
     */
    get mode(): VideoExtensionMode;
    /**
     * 默认不支持 CPU 回退模式。支持的子类覆写返回 true。
     * 当 WebGL context 丢失时，框架会对 supportsCPUMode=true 的插件
     * 调用 `applyEffect({ kind: "cpu" })` 进行 CPU 回退处理。
     */
    get supportsCPUMode(): boolean;
    /**
     * 框架级兼容性检测：视频管线依赖 WebGL2。
     *
     * 静态方法，集成方可在不实例化插件的前提下直接调用（`MyVideoExtension.checkCompatibility()`）。
     * 在主线程（`HTMLCanvasElement`）或 Worker（`OffscreenCanvas`）下尝试获取 `webgl2`
     * 上下文，任一可用即视为兼容。具体插件可覆写并调用 `super.checkCompatibility()`
     * 叠加自身依赖（如 WebAssembly、特定 GL 扩展等）。
     */
    static checkCompatibility(): boolean;
    protected _gl: WebGL2RenderingContext | null;
    protected _canvas: HTMLCanvasElement | OffscreenCanvas | null;
    /** 直通 shader program，用于原样拷贝 texture。 */
    protected _passthroughProgram: WebGLProgram | null;
    private _vertexBuffer;
    private _vertexArray;
    /** blitTexture 使用的 FBO 缓存，避免每帧 create/delete。 */
    private _blitReadFbo;
    private _blitDrawFbo;
    /**
     * 按 GL context 缓存共享资源，避免多个插件共用同一个 GL context 时
     * 重复编译 shader 和创建 buffer。
     */
    private static _glCache;
    /**
     * 清理指定 GL context 的资源缓存，context loss/restore 后需要调用。
     */
    static clearGLCache(gl: WebGL2RenderingContext): void;
    /**
     * 初始化共享 GL 资源。子类覆写时必须调用 super.init(context)。
     */
    init(context: VideoExtensionContext): void;
    /**
     * 释放 GL 资源引用和事件监听。子类覆写时必须调用 super.destroy()。
     */
    destroy(options?: ExtensionDestroyOptions): void;
    /** 当前 WebGL context 是否已丢失。 */
    private _contextLost;
    /** 当前 WebGL context 是否已丢失，供子类和框架只读访问。 */
    get contextLost(): boolean;
    private _onContextLost;
    private _onContextRestored;
    /**
     * WebGL context 恢复后调用。子类可覆写此方法，重新初始化自己的
     * GL 资源，例如 shader program、texture、FBO 等。
     *
     * 在调用此方法前，基类已经重新初始化共享 GL 资源
     * （直通 shader、vertex buffer 等）。
     *
     * 默认实现为空。
     */
    protected onContextRestored(): void;
    /**
     * TEXTURE 模式的处理方法。子类覆写此方法实现 GPU texture 处理。
     * 默认实现：直接拷贝 input → output（直通）。
     */
    applyEffect(frame: Frame): Promise<void | VideoFrame>;
    /**
     * VIDEO_FRAME 模式的处理方法。子类覆写此方法实现 VideoFrame 处理。
     * 默认实现：返回原始帧（直通）。
     *
     * 在 GPU 管线中，框架会自动做 texture → VideoFrame → 插件 → texture 的转换。
     * 在 CPU 管线中，插件直接收到 VideoFrame。
     *
     * 也可以通过 applyEffect(frame) 处理 kind === "cpu" 的帧来替代此方法。
     */
    processVideoFrame(frame: VideoFrame): Promise<VideoFrame>;
    /**
     * 声明式配置入口。默认实现为空（no-op），需要配置的子类覆写此方法，
     * 根据传入的 `options` 自行 diff 并应用（例如更新水印列表）。
     *
     * 框架在 `init()` 之后会用 `useExtension()` 的初始 `extensionOptions`
     * 自动调用一次本方法，之后业务侧每次 `setOptions(...)` 也走到这里。
     */
    setOptions(_options: Partial<TOptions>): void | Promise<void>;
    /**
     * 将 srcTexture 的内容通过直通 shader 绘制到 fbo 上。
     */
    protected drawTextureToFbo(texture: WebGLTexture, fbo: WebGLFramebuffer, width: number, height: number): void;
    /**
     * 通过 blitFramebuffer 将一个 texture 的内容拷贝到另一个 texture。
     * 要求 GL context 的 antialias 为 false。
     * FBO 被缓存复用以避免每帧 create/delete 的开销。
     */
    protected blitTexture(src: WebGLTexture, dst: WebGLTexture, width: number, height: number): void;
    /**
     * 将像素坐标（左上角原点）转换为框架纹理空间中的 GL NDC 坐标。
     *
     * 框架的纹理方向约定：图像顶部在帧缓冲底部（GL y=0），框架在最终输出时
     * 执行 Y 翻转。因此像素 y 坐标映射到 GL y 时方向与标准 GL 相反。
     *
     * @param px - 像素 x 坐标（0 = 左边缘）
     * @param py - 像素 y 坐标（0 = 上边缘）
     * @param frameWidth - 帧宽度（像素）
     * @param frameHeight - 帧高度（像素）
     * @returns [glX, glY] — GL NDC 坐标，范围 [-1, +1]
     *
     * 用法示例（定位水印中心）：
     * ```ts
     * const [cx, cy] = this.pixelToGL(
     *   watermark.x + watermark.width / 2,
     *   watermark.y + watermark.height / 2,
     *   frameWidth, frameHeight
     * );
     * ```
     */
    protected pixelToGL(px: number, py: number, frameWidth: number, frameHeight: number): [number, number];
    /**
     * 创建一个指定尺寸的 RGBA texture。
     */
    protected createTexture(width: number, height: number): WebGLTexture;
    /**
     * 创建一个绑定到指定 texture 的 FBO。
     */
    protected createFbo(texture: WebGLTexture): WebGLFramebuffer;
    /**
     * 编译并链接一个 shader program。
     */
    protected compileProgram(vertSrc: string, fragSrc: string): WebGLProgram | null;
    private _initSharedGL;
    private _drawWithProgram;
}

/** @public */
export declare type VideoExtensionBackend = "gpu" | "cpu";

/**
 * 视频插件构造器，可携带 Worker 实例化元数据。
 *
 * @public
 */
export declare interface VideoExtensionConstructor<T extends IVideoExtension = IVideoExtension> {
    new (...args: any[]): T;
    readonly extensionDefinition?: VideoExtensionDefinition;
    /**
     * 静态兼容性检测：可在不实例化插件的前提下于主线程直接调用，例如
     * `if (!MyVideoExtension.checkCompatibility()) { ... } else { manager.useExtension(MyVideoExtension); }`。
     * 由 `VideoExtension` 基类提供默认实现（WebGL2 检测），子类可覆写叠加自身依赖（如 WebAssembly）。
     */
    checkCompatibility?(): boolean;
    /**
     * 创建该插件**自有的 fallback worker**（process-only）。
     *
     * 当框架共享 worker 的 `import(moduleURL)` 失败时，整条 track 会改用各插件自带的 worker
     * 处理帧。该工厂在**主线程**调用，返回插件自己打包的 worker（推荐用 inline-blob，
     * 不依赖 `import.meta.url` / `new URL`，避免重蹈触发 fallback 的同类 URL 解析失败）。
     *
     * 允许返回 `Promise<Worker>`：插件通常用**动态 import** 把（可能很大、含 WASM 的）
     * inline-blob 拆成懒加载 chunk（仅在 fallback 真正触发时才加载），避免它被静态内联进
     * 主包（尤其当下游以源码方式消费插件时会显著膨胀甚至 OOM）。
     *
     * **必填**：`useExtension` 只接受声明了本字段的构造器，未声明的插件在编译期即报错，
     * 因此每个插件天然具备 fallback 能力，"插件没有 fallback worker"不是运行时状态。
     *
     * **运行时装配约定（重要）**：插件类文件**不应**直接 `import` 自己生成的 inline-blob
     * 模块——那会与 fallback worker 自身形成“类 → 生成 blob → blob 内含该类”的自包含循环，
     * 并把巨大的 base64 静态内联进主包（曾导致打包 OOM）。因此实际工厂在插件**包入口**
     * （barrel `index.ts`）用**动态 import** 副作用装配（懒加载 chunk）。这意味着本字段的
     * 运行时值依赖“插件从其包入口被消费”：若下游绕过入口、深路径直接 import 插件类文件，
     * 本工厂将缺失（`undefined`），框架据此判定 terminal 并打出可操作的报错。集成方务必从
     * 插件包入口消费插件，不要深路径 import 类文件。
     */
    readonly createFallbackWorker: () => Worker | Promise<Worker>;
    /**
     * 创建一个绑定到给定视频 track 的 `VideoExtensionManager`。
     *
     * 由 `VideoExtension` 基类提供的静态方法（子类继承），委派到框架的 globalThis 单例运行时。
     * 宿主 SDK 可借此在**仅做类型依赖**的前提下创建 manager，无需 value import 框架。
     * 详见 `extension_video.ts` 中的实现与 `singleton.ts`。
     */
    createVideoExtensionManager(track: VideoTrackLike): VideoExtensionManager;
}

/**
 * 视频插件的上下文信息，包含画布和 WebGL 渲染上下文。
 * @public
 */
export declare type VideoExtensionContext = {
    backend: VideoExtensionBackend;
    threadMode: VideoExtensionThreadMode;
    canvas?: HTMLCanvasElement | OffscreenCanvas;
    gl?: WebGL2RenderingContext;
};

/**
 * 框架在共享管线 Worker 内实例化插件类所需的模块元数据。
 *
 * `moduleURL` 指向插件产物（ESM 或 UMD 均可）；Worker 会动态 `import()` 它，
 * 触发该模块顶层的 `registerVideoExtension(registrationName, Ctor)` 自注册副作用。
 * 随后框架按 `registrationName` 从 Worker 全局注册表中取出插件类并实例化。
 *
 * 框架不从模块 URL 解析具名导出，因此不耦合集成产物的格式（ESM/UMD）、导出名或全局名。
 *
 * @public
 */
export declare type VideoExtensionDefinition = {
    moduleURL: string;
    registrationName: string;
};

/**
 * 视频插件运行时的对外入口（由宿主 SDK 暴露给业务侧）。
 *
 * - 一个 `VideoExtensionManager` 实例绑定到一个视频 Track 上，托管其所有插件的生命周期。
 * - 业务通过 {@link VideoExtensionManager.useExtension | useExtension} 获取插件代理；
 *   代理对外暴露 `enable/disable/destroy`、声明式配置入口 `setOptions`，以及
 *   `on/off` 事件监听，背后通过 {@link VEMMain} 或 {@link VEMWorker} 实际驱动插件运行。
 * - `onOutputTrackChanged` 在输出 Track 变化时被调用；`onEmpty` 在最后一个插件销毁后触发，
 *   宿主可以借此把输出 Track 切回原始源 Track。
 *
 * 后端选择在首次 `useExtension` 时锁定，后续不同的 `renderMode/threadMode` 会被忽略并打 warning。
 */
export declare class VideoExtensionManager {
    private _track;
    private _options?;
    private _backend?;
    private _states;
    private _main?;
    private _worker?;
    private _disposing;
    private _disposed;
    /** routed fallback 单次切换守卫：第一个失败的插件触发切换，其余 reject 合流到此 promise。 */
    private _fallingBack?;
    /** 整条 track 是否已进入 routed fallback（插件自有 worker）。 */
    private _routed;
    /** routed fallback 的 loud 日志去重：整条 track 降级只 loud log 一次（track 级状态）。 */
    private _fallbackLogged;
    private _outputTrack?;
    /** `track-updated` 监听器引用，构造时订阅、`_destroyRuntime` 时解除。 */
    private _onTrackUpdated?;
    onOutputTrackChanged?: (track: MediaStreamTrack | undefined) => void;
    onEmpty?: () => void;
    constructor(track: VideoTrackLike);
    /** 是否仍有未销毁的插件代理。宿主可据此判断是否要把输出 Track 切回原始源。 */
    get hasExtensions(): boolean;
    /**
     * 当前处理后的输出 track（未启动管线时为 `undefined`）。
     *
     * 供宿主在换源后把发布/播放重新指回处理后的输出，而不是停在裸 origin
     *（见 `LocalVideoTrack._updateOriginMediaStreamTrack` 的 extension 分支）。
     */
    get currentOutputTrack(): MediaStreamTrack | undefined;
    /**
     * 为指定插件构造器创建（或复用）一个代理。
     *
     * - 同一个构造器在销毁前重复调用会返回同一个代理；初始 `extensionOptions`
     *   只在首次创建时消费，重复调用传入的 `extensionOptions` 会被忽略
     *   （要更新配置请调用代理的 `setOptions(...)`）。
     * - 首次调用时根据 `options` 解析后端并锁定，后续插件会被强制并入同一条管线。
     * - Worker 模式下要求构造器带 `extensionDefinition`，否则抛错。
     */
    useExtension<T extends VideoExtensionConstructor>(ctor: T, options?: ExtensionOptions): InstanceType<T>;
    /**
     * 源 Track 被替换时调用。生产路径由构造函数订阅的 `track-updated` 事件驱动并显式传入新源；
     * 也可由外部直接调用（不传则回读 `this._track.mediaStreamTrack`，供测试/兜底）。
     *
     * `track-updated` 被宿主 SDK 双向复用：既表示「框架输出写回（框架 → SDK）」，又表示
     * 「源变更（SDK → 框架）」。本方法据「新源是否等于框架当前输出 track」区分两者：
     *
     * - 没有插件 / 正在销毁时为 no-op；
     * - **输出写回（`next === this._outputTrack`）**：这是框架自己的输出 track 被写回（宿主把处理后的
     *   输出赋给 `_mediaStreamTrack`，其 setter 再次 `emit("track-updated")`）。这不是真正的源变更，
     *   **静默忽略**——既避免把自身输出当输入形成自反馈环，也消除了过去每次启用插件都误报的 ERROR；
     * - **真正的源变更**：转发给当前后端，由后端**只替换上游输入、保持输出 track 不变**（运行时不变量），
     *   随后把当前输出 track 经 `onOutputTrackChanged` 重新落回宿主，确保换源后发布/播放仍走处理后的输出。
     */
    updateSourceTrack(newTrack?: MediaStreamTrack): void;
    /**
     * 移除单个插件：销毁其代理并从内部状态表移除。
     * 与 {@link AudioExtensionManager.removeExtension} 对称，供 SDK Track 调用，
     * 避免外部反向访问私有 `_states`。代理 `destroy()` 会同步从 `_states` 删除该
     * 插件并在清空后异步释放后端，因此调用方随后读取 `hasExtensions` 即为最新值。
     *
     * @param extension 由 `useExtension` 返回的插件代理。
     * @returns 找到并移除返回 `true`；未注册返回 `false`。
     */
    removeExtension(extension: IVideoExtension): boolean;
    /**
     * 强制销毁整个 manager：所有代理 state 标记为 destroyed，
     * 主线程 / Worker 后端依次释放，输出 Track 重置为 undefined。
     * Worker 销毁是异步的，但本方法立即清空状态，避免 race condition。
     */
    destroy(): void;
    /** 调试：把 context 丢失请求转发给当前后端，便于校验 CPU 回退路径。 */
    simulateContextLoss(): void;
    /** 调试：触发 context 恢复，等同于真实事件。常与 `simulateContextLoss` 成对使用。 */
    simulateContextRestore(): void;
    /* Excluded from this release type: enableStats */
    /* Excluded from this release type: getStats */
    /* Excluded from this release type: resetStats */
    /**
     * 在首次 `useExtension` 调用时解析并锁定运行时后端；
     * 后续调用若传入与首次不一致的 renderMode/threadMode，会打 warning 但仍沿用已选后端。
     *
     * 还会针对“auto + Worker 能力足够但缺少 extensionDefinition”的常见配置错误
     * 给出主动提示。
     */
    private _ensureBackend;
    /**
     * 串行化单个 proxy 的控制操作，同时保证一次失败不会毒化后续操作队列。
     * 普通操作默认只在前序成功后执行；清理类操作可传 `runAfterFailure=true`。
     */
    private _enqueueStateOp;
    /**
     * 把一个插件失败信号通过其代理以 {@link ExtensionEvents.ERROR} 事件派发给业务侧
     * （与出站数据同一条 on/emit 通道）。这是补充的"带外"可观测信号，不取代调用处的
     * try/catch。`safeEmit` 会吞掉 listener 自身的异常。
     */
    private _emitExtensionError;
    /**
     * 启动期 reject 的分诊（auto-enable 链失败时调用）。
     *
     * worker 后端的「import 失败 → 插件自有 worker fallback」已在 `_addWorker` 内联处理
     *（state.ready 直接反映 re-home 结果），因此正常 fallback 路径不会走到这里。
     * 所有失败的可观测性都由 loud `logger.error` 承载（不依赖业务订阅，见类型/集成指南的
     * 「log 为主通道」约定）；本方法只在该插件尚处 `Pending` 时把它推进到 `Terminal`，
     * 维持「最终启动信号只产出一次」不变量：已离开 `Pending` 的插件（已被 re-home 认领
     * 或已 Terminal）其遗留的 auto-enable reject 在此被直接吞掉，避免重复处理。
     */
    private _onStartupReject;
    /**
     * routed fallback 的目标处理模式：worker-cpu 后端 → "cpu"，其余（worker-gpu）→ "gpu"。
     * 多处 re-home 共用，避免散落的三元判断漂移。
     */
    private _routedMode;
    /**
     * 「未被认领的运行中插件」谓词：仍处 `Pending`（尚未被各自 `_addWorker` 或本轮 sweep 认领）
     * 的存活插件。`_engageTrackFallback` 据此快照要 re-home 的运行中插件。
     */
    private _isUnclaimedRunningPlugin;
    /**
     * 「活跃 routed 插件」谓词：已成功切到插件自有 worker（`Routed`）的存活插件。
     * `_commitRoutedChain` 据此收敛帧链到当前插件集合。
     */
    private _isRoutedPlugin;
    /**
     * 单次触发整条 track 的 fallback，并 re-home **其余正在运行的插件**（那些已在框架共享 worker
     * 注册成功、正在运行的插件）。触发它的那个失败插件由其自己的 `_addWorker` 内联 re-home
     * （见 `_rehomePlugin`），不在这里重复处理（靠 `startup` 状态认领去重）。
     *
     * 认领协同：失败插件在 `_addWorker` 先认领自己（`startup` 离开 `Pending`），再调本方法；
     * 本方法只处理仍处 `Pending` 的运行中插件，每个插件在 `_rehomePlugin` 内同步推进出 `Pending`
     * 完成认领，从而与失败插件、与并发的多失败 sweep 互斥，保证每个插件最多 re-home 一次。
     *
     * 不改 `this._backend`（仍为 worker-*），不动 capture/output/pump（输出 track 稳定）。
     */
    private _engageTrackFallback;
    /**
     * 把一个**正在共享 worker 上运行的插件**重置并 re-home 到它自有的 worker。
     *
     * 该插件的 `state.ready` 此前已 resolve；这里用一个 deferred 把 `state.ready` 重置为「本次
     * re-home」：在 re-home 落定前，它后续排队的代理操作（setOptions/enable 等）都会 await
     * 这个新的 ready，从而不会撞上一条「指向旧共享-worker 实例」的已 resolve promise。
     * 先 `await prevReady` 排空其在途操作，再 re-home；成功则 resolve 并按 `desiredEnabled`
     * 重新启用，失败则 reject。
     */
    private _rehomeRunningPlugin;
    /**
     * 用当前注册顺序中所有已切到自有 worker 的插件（重）建 routed 帧链。
     * 新增/注销插件后调用，把帧链收敛到当前插件集合。
     */
    private _commitRoutedChain;
    /**
     * 把单个插件接到它自有的 worker 上，并产出最终启动信号。
     * 返回 true=成功切到插件自有 worker（`Routed`）；false=terminal（环境原因，插件没跑起来）。
     *
     * 同步认领该插件（`startup`：`Pending` → `Routing`）以与 sweep 互斥；不在此 enable
     *（由调用方按各自语义处理：失败插件靠 auto-enable，运行中插件由 `_engageTrackFallback` 重新 enable）。
     *
     * @param announce 是否为该插件派发可订阅的 `worker-fallback` ERROR 事件。仅对「因降级被迫
     *   从共享 worker 迁走」的插件（触发者 + 当时在跑的其他插件）置 true；之后**新加入**已降级
     *   track 的插件置 false——它自己没经历失败，静默接入即可，不应收到「伪失败」事件。
     */
    private _rehomePlugin;
    /** 整条 track 首次降级时 loud log 一次（track 级状态，避免按插件数量重复刷屏）。 */
    private _logFellBackOnce;
    /**
     * 调用插件的 `createFallbackWorker()` 工厂创建其自有 worker。
     * 工厂抛错（terminal）时打 loud log 并返回 `undefined`，由调用方据此判定 terminal。
     */
    private _createPluginWorker;
    /** 按 worker 分配的插件 id 找到对应的 proxy state（用于把 worker 侧失败映射回代理）。 */
    private _findStateById;
    /** 按主线程实例找到对应的 proxy state（用于把 main-gpu 侧失败映射回代理）。 */
    private _findStateByInstance;
    /** 销毁当前运行时后端并重置 backend/options 锁，供最后一个插件移除后重新选择后端。 */
    private _destroyRuntime;
    /**
     * 构造插件代理：
     * - 把 enable/disable/destroy 替换为串行化的、跨进程透明的版本；
     *   并由代理（而非插件实例）作为生命周期事件 ENABLED/DISABLED 的唯一来源，
     *   在对应操作的 `state.op` 确认后再 emit，保证事件时序与 await 一致；
     * - 提供声明式配置入口 `setOptions`：main-gpu 模式直接调本地实例，
     *   worker 模式经 `VEMWorker.setOptions` → `SET_OPTIONS` 消息转发到 Worker；
     * - 共享同一份 `state` 对象，保证业务侧多次 await 的执行顺序一致。
     *
     * 注：插件入站配置（含图片等不可克隆数据）由 `preprocessMessage` 在发送前
     * 转成 Transferable；插件出站数据由插件 `emit`，经 `ON_EMIT` 转发回代理。
     */
    private _createProxy;
    /**
     * Worker/main proxy 都只桥接框架生命周期与 setOptions。保留插件自定义便捷方法，
     * 但要求它们在【同步执行段内】最终调用 `this.setOptions(...)` 转发配置；否则立即
     * 以 rejected promise 报错，避免方法体在空 proxy 上静默执行却让业务以为配置已生效。
     *
     * 判定只看方法的**同步段**：空 proxy 上 await 之后的副作用本就是无意义 no-op，
     * 真正有效的转发只可能发生在同步段（`return this.setOptions(...)`）。每次调用持有
     * 独立 `frame` 且仅在自身同步段内活跃，保证并发的两个自定义方法各自独立判定。
     */
    private _installCustomMethodGuards;
    /** 懒创建主线程 VEMMain 实例，并连接其输出 Track 回调到对外的 `onOutputTrackChanged`。 */
    private _ensureMain;
    /**
     * 懒创建 VEMWorker 实例。把 Worker 侧的 `on-emit` 通知派发到对应代理上，
     * 让业务侧能像主线程模式一样监听插件事件。
     */
    private _ensureWorker;
    /**
     * 主线程模式下注册插件：实例化、把插件 `emit` 转发到代理事件、调用 `VEMMain.registerExtension`，
     * 并用初始 `extensionOptions` 调用一次插件 `setOptions`。
     * 注册完成后由 `useExtension()` 自动通过代理 enable() 进入帧链。
     */
    private _addMain;
    /**
     * Worker 模式下注册插件：把生效的 moduleURL/registrationName 透传给 Worker，
     * 由 Worker 动态 import 并实例化插件。`definition` 在 `useExtension` 时已解析
     * （集成方 options 覆盖优先于构造器静态 `extensionDefinition`）。
     * 初始 `extensionOptions` 随注册消息一并下发，由 Worker 在 init 后调用插件 `setOptions`。
     */
    private _addWorker;
}

/**
 * 视频插件的处理模式。
 * @public
 */
export declare enum VideoExtensionMode {
    /** GPU Texture 模式（推荐）：插件在共享 GL context 上操作 texture，零 CPU 拷贝。 */
    TEXTURE = "texture",
    /**
     * VideoFrame 模式：插件接收/返回 VideoFrame。
     *
     * ⚠️ 性能注意：在 GPU 管线中，此模式每个插件每帧产生两次 GPU↔CPU 拷贝
     * （texture → canvas → VideoFrame → 插件处理 → texImage2D 回 texture），
     * 在 1080p 下约增加 5-10ms/帧延迟。
     *
     * 适用于需要访问原始像素数据的插件（如基于 CPU/WASM 的图像处理），
     * 或无法适配 TEXTURE 模式的场景。
     * 纯 GPU 处理的新插件推荐使用 TEXTURE 模式以获得最佳性能。
     */
    VIDEO_FRAME = "videoFrame"
}

/** @public */
export declare type VideoExtensionThreadMode = "worker" | "main";

/**
 * 传递给 TEXTURE 模式插件的帧数据。
 *
 * 所有 TEXTURE 模式插件的标准 I/O 契约：
 * - 输入：textures.input（WebGLTexture，只读）
 * - 输出：textures.output（WebGLTexture，插件必须写入处理结果）
 *
 * ─── 纹理坐标系与方向约定 ───
 *
 * 框架使用 texImage2D 将视频帧上传到 input texture，**不设置 UNPACK_FLIP_Y_WEBGL**。
 * 这意味着图像的第一行（视觉上的顶部）存储在纹理坐标 v=0 处（即 GL 帧缓冲的底部）。
 *
 * 框架在最终输出时会执行一次 Y 翻转的 blitFramebuffer：
 *   blitFramebuffer(0, 0, w, h, 0, h, w, 0)
 * 将帧缓冲底部映射到画布顶部，从而使视频正确显示。
 *
 * 对插件的影响：
 * - 如果插件只做全帧处理（如超分、美颜），直接操作 input/output texture 即可，
 *   无需关心方向——输入输出保持一致的方向即可。
 * - 如果插件需要在特定像素位置绘制内容（如水印、贴纸），必须注意：
 *   在 output texture 中，GL 帧缓冲的 y=0（底部）对应最终显示的顶部。
 *   因此，像素坐标 (px, py)（左上角原点）转换为 GL NDC 坐标时应使用：
 *     glX = px / width * 2 - 1          （左→右 对应 -1→+1）
 *     glY = py / height * 2 - 1         （上→下 对应 -1→+1，注意：非标准 GL 方向）
 *   而不是通常的 glY = 1 - py / height * 2。
 * - 如果插件通过 readPixels 读取 input texture，返回的像素数据行序为：
 *   第一行 = 图像顶部（因为图像顶部在帧缓冲底部，readPixels 从底部开始读取）。
 *   这与 Canvas 2D 的 getImageData() 行序一致。
 * - 如果插件的 WASM 模块渲染到默认帧缓冲（canvas）并使用标准 GL 坐标系
 *   （y+ = 上 = 视觉顶部），则需要在写入 output texture 时执行一次 Y 翻转 blit：
 *     blitFramebuffer(0, 0, w, h, 0, h, w, 0)
 *   以匹配框架的纹理方向约定。
 *
 * 插件设计者须知：
 * 1. 纯 GPU 插件（如 SuperClarity）：直接读 input texture，写 output texture。
 *    这是最高效的路径，零 CPU 拷贝。
 * 3. 渲染到 canvas 的插件：如果 WASM 渲染到共享 canvas（如通过 glfwSwapBuffers），
 *    插件需要自行 texImage2D(canvas) → output texture。
 *
 * @public
 */
export declare type VideoFrameTextures = {
    /** 当前帧的输入纹理（只读）。 */
    input: WebGLTexture;
    /** 插件必须将处理结果写入此纹理。 */
    output: WebGLTexture;
    /**
     * 当前帧宽度（偶数对齐）。
     * 框架会将奇数尺寸向下对齐到偶数，以避免 YUV 色度子采样（NV12/I420）
     * 在编解码链路中产生绿屏。插件收到的 width/height 与 texture 尺寸一致。
     */
    width: number;
    /**
     * 当前帧高度（偶数对齐）。
     * @see width
     */
    height: number;
};

/**
 * 运行时框架使用的 Track 抽象接口。
 *
 * SDK（如 rtcn.js）的 LocalVideoTrack / RemoteVideoTrack 等天然满足此接口，
 * 无需额外适配。
 *
 * @public
 */
export declare interface VideoTrackLike {
    readonly mediaStreamTrack: MediaStreamTrack;
    /**
     * 可选事件订阅（宿主 SDK 的 Track 继承自 EventEmitter，天然满足）。框架用它监听
     * `"track-updated"` 以在换源时只替换上游输入。非 EventEmitter 的 track-like 可不实现，
     * 此时框架跳过自动订阅，仍可由外部显式调用 `updateSourceTrack(newTrack)`。
     */
    on?(event: string, listener: (...args: any[]) => void): void;
    off?(event: string, listener: (...args: any[]) => void): void;
}

/**
 * Worker 消息协议类型枚举。
 *
 * 主线程与 Worker 之间所有 postMessage 通信的消息类型统一在此定义。
 * 命名规范：kebab-case。
 */
export declare enum WorkerMessageType {
    START = "start",
    START_VTG = "start-vtg",
    STOP = "stop",
    DESTROY = "destroy",
    /**
     * 主线程 → Worker（local 模式换源，Chrome）：只换输入,保留输出。
     * 携带新源的 `readableStream`（主线程为新 origin 新建的 MSTP.readable，transfer 进来）。
     * Worker 先 abort 旧输入 pipe（**保留** `state.writable` 不 abort/close），再用新 readable
     * 重接到同一个 generator.writable —— 输出 track 身份不变，无需 `onOutputTrackChanged`。
     */
    SWAP_INPUT = "swap-input",
    /**
     * 主线程 → Worker（local 模式换源，Safari VTG）：只换输入,保留 VideoTrackGenerator 输出。
     * 携带新源 `mediaTrack`（clone 后 transfer）。Worker stop 旧 sourceTrack、用新 track 自建
     * MSTP，重接到同一个 VTG.writable —— VTG.track 身份不变，无需 `onOutputTrackChanged`。
     */
    SWAP_INPUT_VTG = "swap-input-vtg",
    REGISTER_EXTENSION = "register-extension",
    UNREGISTER_EXTENSION = "unregister-extension",
    ENABLE = "enable",
    DISABLE = "disable",
    /** 主线程 → Worker：下发插件配置（setOptions） */
    SET_OPTIONS = "set-options",
    /** Worker → 主线程：插件通过 emit 向外推送数据 */
    ON_EMIT = "on-emit",
    /**
     * 主线程 → 插件 worker：把该插件在帧链中那一段的**输入/输出端**交给它。
     *
     * 帧传输用**原生 MSTP/MSTG**（与本框架本地路径、与老插件模式同一套，已验证不克隆/不泄漏）：
     * - `readable`（**Chrome**）：主线程为该 stage 建的 `MediaStreamTrackProcessor.readable`（其源是
     *   上一段的输出 track，或首段的 capture track），转移进插件 worker，由插件 worker **原生读取**帧。
     * - `writable`（**Chrome**）：主线程建的 `MediaStreamTrackGenerator.writable`，转移进插件
     *   worker，由插件 worker **原生写入**结果帧；其 `.track` 在主线程作为该 stage 的输出，桥接到
     *   下一段的 MSTP。
     * - **Safari**：MSTP/VTG 仅在 Worker 作用域可用，主线程建不了 MSTP，故不带 `readable`/`writable`，
     *   改带 `mediaTrack`（本段输入 track，preprocessMessage 会 clone 后 transfer）。插件 worker 内
     *   自建 `MediaStreamTrackProcessor`（输入）+ `VideoTrackGenerator`（输出），在**回复**里把
     *   `{ track }` 交回主线程作为该 stage 输出（Safari 无 `MediaStreamTrackGenerator`）。
     *
     * 插件 worker 内部 `readable.pipeThrough(processFrame).pipeTo(writable)` 全在本 realm，
     * 不写入任何**跨 realm 的普通 stream**（那才会克隆 VideoFrame）。重建链路时再次下发以换用
     * 新的输入/输出端（插件 worker 先 abort 旧 pipe）。
     */
    CONNECT_FRAME_PIPE = "connect-frame-pipe",
    /**
     * 主线程/共享 worker → 插件 worker：初始化插件实例与（GPU 模式下）其自有 GL context。
     * 携带 mode（gpu/cpu）。
     */
    INIT_PLUGIN = "init-plugin",
    SIMULATE_CONTEXT_LOSS = "simulate-context-loss",
    SIMULATE_CONTEXT_RESTORE = "simulate-context-restore",
    /** 主线程 → Worker：开启/关闭逐帧性能采样（调试统计）。 */
    ENABLE_STATS = "enable-stats",
    /** 主线程 → Worker：清零累计的帧/插件耗时统计。 */
    RESET_STATS = "reset-stats",
    LOG = "log",
    ERROR = "error",
    ASYNC_ERROR = "async-error",
    /**
     * Worker → 主线程：节流推送的逐帧性能统计快照（调试）。
     * 主线程缓存最近一次快照，供同步 `getStats()` 读取（worker 路径无法同步回读累加量，
     * 故用「worker 周期推送 + 主线程缓存」替代请求-响应）。
     */
    STATS = "stats"
}

export { }
