当前位置: 首页 > news >正文

AVFormatContext 再分析二

说明 :将 avfromatContext 的变量依次打印分析,根据ffmpeg 给的说明,猜测,结合网上的文章字节写测试代码分析二。

37 AVInputFormat *iformat;

    /**
     * The input container format.
     *
     * Demuxing only, set by avformat_open_input().
     */
    ff_const59 struct AVInputFormat *iformat;

AVInputFormat 再分析-CSDN博客

38 AVFormatInternal *internal; 对开发者隐藏,但是对于阅读ffmpeg源码有用。

    /**
     * An opaque field for libavformat internal usage.
     * Must not be accessed in any way by callers.
     */
    AVFormatInternal *internal;

*libavformat内部使用的不透明字段。
*使用不得以任何方式访问。

AVFormatContext 中的 AVFormatInternal *internal 字段是 FFmpeg 内部用于存储与解封装/封装过程相关的私有状态数据的结构体7。以下是其核心特性的总结:


1. 设计目的

  • 内部数据隔离‌:internal 封装了 AVFormatContext 运行时的临时状态和中间数据,避免用户直接操作导致的结构不稳定或版本兼容性问题7。
  • 模块化扩展‌:通过独立结构体管理内部状态,方便 FFmpeg 在不同版本中扩展或修改内部实现逻辑,而无需修改 AVFormatContext 的公开接口7。

2. 关键特性

  1. 不透明性‌:

    • AVFormatInternal 的具体定义未在公共头文件(如 avformat.h)中公开,开发者无法直接访问其内部字段7。
    • 所有操作需通过 FFmpeg 提供的 API 完成(如 avformat_open_input()av_read_frame() 等)78。
  2. 生命周期管理‌:

    • internal 的内存分配与释放由 FFmpeg 内部自动完成,用户无需手动干预(例如在调用 avformat_close_input() 时会自动清理)7。
    • 初始化时,internal 通常通过 avformat_alloc_context() 函数间接创建7。

3. 关联功能

  • 流探测缓冲‌:缓存输入数据的部分内容,用于格式探测(如 avformat_find_stream_info() 中的流参数分析)8。
  • 中间状态存储‌:
    • 封装/解封装过程中的临时数据包队列3。
    • 时间戳校正、流交错(interleaving)等算法所需的上下文信息38。

4. 开发者注意事项

  • 禁止直接访问‌:由于 FFmpeg 不保证 AVFormatInternal 的跨版本二进制兼容性,直接操作其字段可能导致程序崩溃或未定义行为7。
  • 调试限制‌:若需调试内部状态,通常需结合 FFmpeg 源码中的日志输出或使用调试器跟踪相关函数调用7。

与类似字段的对比

字段作用域可见性管理方式
priv_data格式私有数据半公开(需API)由 AVInputFormat/AVOutputFormat 管理14
internal全局运行时完全内部FFmpeg 内部自动管理7

此设计模式体现了 FFmpeg 对“接口稳定”和“实现灵活”的平衡,确保用户仅通过规范 API 即可安全使用核心功能78。

39.AVIOInterruptCB interrupt_callback

    /**
     * Custom interrupt callbacks for the I/O layer.
     *
     * demuxing: set by the user before avformat_open_input().
     * muxing: set by the user before avformat_write_header()
     * (mainly useful for AVFMT_NOFILE formats). The callback
     * should also be passed to avio_open2() if it's used to
     * open the file.
     */
    AVIOInterruptCB interrupt_callback;

/**
 * Callback for checking whether to abort blocking functions.
 * AVERROR_EXIT is returned in this case by the interrupted
 * function. During blocking operations, callback is called with
 * opaque as parameter. If the callback returns 1, the
 * blocking operation will be aborted.
 *
 * No members can be added to this struct without a major bump, if
 * new elements have been added after this struct in AVFormatContext
 * or AVIOContext.
 */
typedef struct AVIOInterruptCB {
    int (*callback)(void*);
    void *opaque;
} AVIOInterruptCB;

AVFormatContext 中的 interrupt_callback 字段用于实现自定义 I/O 中断控制机制,主要解决网络流处理时的阻塞问题‌。以下是其核心功能与使用方法的总结:


1. 功能与作用

  • 阻塞中断‌:在 avformat_open_input() 或 av_read_frame() 等操作中,若因网络延迟、设备断开或无数据导致长时间阻塞,可通过回调函数强制终止等待12。
  • 超时控制‌:允许开发者设置最大等待时间,避免程序无响应(如 RTSP 流超时断开)48。
  • 跨协议兼容‌:适用于 RTSP、RTMP 等网络协议,弥补某些协议(如 RTMP)不支持超时参数的缺陷16。

2. 结构体定义

interrupt_callback 是 AVFormatContext 的成员,类型为 AVIOInterruptCB,包含两个关键字段:

  • callback‌:函数指针,指向用户定义的中断检测函数。
  • opaque‌:用户自定义的上下文指针(如对象实例、计时器等),传递给回调函数。
typedef struct AVIOInterruptCB {int (*callback)(void*);  // 中断检测函数void *opaque;            // 用户上下文数据
} AVIOInterruptCB;


3. 回调函数实现

回调函数需返回 ‌1(中断)‌ 或 ‌0(继续等待)‌。典型实现逻辑:

  1. 通过 opaque 获取上下文数据(如超时起始时间)。
  2. 计算当前时间与起始时间的差值。
  3. 若超过预设阈值(如 5 秒),返回 1 终止操作。
 
// 示例:超时检测回调
int interrupt_cb(void *ctx) {int64_t start_time = *(int64_t*)ctx;  // 通过 opaque 传递起始时间int64_t current_time = av_gettime();  // 获取当前时间(微秒)return (current_time - start_time > 5000000) ? 1 : 0;  // 超过5秒则中断
}

4. 设置步骤

  1. 分配上下文‌:创建 AVFormatContext 实例。
  2. 绑定回调‌:设置 interrupt_callback 的 callback 和 opaque
  3. 启动计时‌:在关键操作前记录起始时间(如 av_gettime())。
  4. 打开输入流‌:调用 avformat_open_input(),阻塞操作将触发回调检测。
AVFormatContext *fmt_ctx = avformat_alloc_context();
int64_t timeout_start = av_gettime();  // 记录起始时间// 设置回调函数及上下文
fmt_ctx->interrupt_callback.callback = interrupt_cb;
fmt_ctx->interrupt_callback.opaque = &timeout_start;// 打开输入流(如 RTSP)
if (avformat_open_input(&fmt_ctx, "rtsp://example.com", NULL, NULL) < 0) {// 错误处理
}


5. 注意事项

  • 协议差异‌:对于 RTSP,可同时设置 stimeout 参数(单位:微秒)增强超时控制68:
     

    cCopy Code

    AVDictionary *options = NULL; av_dict_set(&options, "stimeout", "2000000", 0); // 2秒超时 avformat_open_input(&fmt_ctx, url, NULL, &options);

  • 线程安全‌:回调函数需确保线程安全,避免竞态条件8。
  • 资源释放‌:无需手动释放 interrupt_callback,其生命周期与 AVFormatContext 绑定5。

6. 典型问题与调试

  • 回调未触发‌:检查是否在 avformat_open_input() 前正确设置回调8。
  • 误中断‌:调整超时阈值,或在回调中增加状态判断(如网络重连尝试次数)6。

40 回调函数 io_open

谨慎

    /**
     * A callback for opening new IO streams.
     *
     * Whenever a muxer or a demuxer needs to open an IO stream (typically from
     * avformat_open_input() for demuxers, but for certain formats can happen at
     * other times as well), it will call this callback to obtain an IO context.
     *
     * @param s the format context
     * @param pb on success, the newly opened IO context should be returned here
     * @param url the url to open
     * @param flags a combination of AVIO_FLAG_*
     * @param options a dictionary of additional options, with the same
     *                semantics as in avio_open2()
     * @return 0 on success, a negative AVERROR code on failure
     *
     * @note Certain muxers and demuxers do nesting, i.e. they open one or more
     * additional internal format contexts. Thus the AVFormatContext pointer
     * passed to this callback may be different from the one facing the caller.
     * It will, however, have the same 'opaque' field.
     */
    int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url,
                   int flags, AVDictionary **options);

目前看的信息是:avformatContext 的 io_open 回调函数 在默认情况下叫 io_open_default,在解复用的 avformat_open_input 方法中一定会调用。

io_open_default 是 FFmpeg 中用于初始化输入/输出上下文 (AVIOContext) 的关键函数,主要在解封装流程中处理协议检测与连接。以下是其核心机制与作用解析:


一、功能定位

  1. 协议初始化入口
    在 avformat_open_input() 调用流程中,io_open_default 作为默认的 I/O 上下文初始化函数,负责根据输入 URL 的协议类型(如 HTTP、HLS、文件)创建对应的 AVIOContext,并绑定底层协议实现1。

  2. 协议白名单校验
    通过调用 ffio_open_whitelist,该函数会校验协议是否在允许范围内,防止加载未授权的协议实现(如自定义或非标准协议),确保安全性1。

  3. 多层封装调用链
    其执行链路为:
    avformat_open_input → init_input → io_open_default → ffio_open_whitelist → ffurl_open_whitelist → ffurl_connect → 具体协议实现(如 http_open)1。
    最终通过系统调用(如 socket)建立网络连接或打开本地文件12。


二、实现机制

  1. 协议适配层
    io_open_default 通过协议前缀(如 http://file://)匹配对应的 URLProtocol 实现(如 ff_http_protocol),并初始化协议上下文 (URLContext),最终关联到 AVIOContext 的 opaque 字段15。

  2. 缓冲与回调设置
    自动配置读写缓冲区大小,并设置默认的 read_packetwrite_packet 等回调函数,确保数据通过协议层高效传输至解封装模块17。

  3. 错误处理
    若协议检测失败(如 URL 无效或协议未注册),函数返回错误码并终止后续流程,触发 avformat_open_input 的异常处理逻辑1。


三、应用场景

  • 标准协议处理‌:自动处理 HTTP、RTMP、HLS 等协议连接的初始化,无需手动创建 AVIOContext15。
  • 安全限制场景‌:通过白名单机制限制可访问的协议类型,适用于需严格管控输入源的场景(如嵌入式设备)1。

四、扩展性

  • 自定义协议支持‌:若需支持私有协议,需绕过 io_open_default,通过 avio_alloc_context 手动创建 AVIOContext 并注册自定义协议实现37。

41 回调函数io_close

    /**
     * A callback for closing the streams opened with AVFormatContext.io_open().
     */
    void (*io_close)(struct AVFormatContext *s, AVIOContext *pb);

42 int io_repositioned;

    /**
     * IO repositioned flag.
     * This is set by avformat when the underlaying IO context read pointer
     * is repositioned, for example when doing byte based seeking.
     * Demuxers can use the flag to detect such changes.
     */
    int io_repositioned;

io_repositioned 是 FFmpeg 中 AVFormatContext 结构体的一个标志字段,用于指示底层 I/O 上下文的读指针是否发生了位置重置。其核心作用与应用场景如下:


一、功能定义

  1. 标志位作用
    io_repositioned 由 FFmpeg 的解封装模块(avformat)自动设置,主要用于标识底层 I/O 上下文(如 AVIOContext)的读指针是否被显式重定位。例如,在基于字节的随机访问(byte-based seeking)时,该标志会被触发。

  2. 触发条件
    当调用 av_seek_frame() 或类似函数导致底层 I/O 缓冲区的读指针位置发生变化时,io_repositioned 会被设置为非零值,表示发生了位置重置。


二、应用场景

  1. 解封装逻辑适配
    解复用器(Demuxer)可通过检查 io_repositioned 标志判断是否需要重新同步内部状态(如重新解析流头信息或调整时间戳计算逻辑),以应对底层 I/O 位置突变带来的数据不一致问题。

  2. 性能优化
    在处理网络流或大文件时,通过检测 io_repositioned 标志,可避免无效的缓存数据读取,确保后续操作基于最新的 I/O 位置执行1。


三、实现关联

  • 与 AVIOContext 的交互
    io_repositioned 直接关联 AVIOContext 的 seek 操作,若用户代码通过 avio_seek() 手动调整读指针位置,也会触发该标志的更新

打印值是0

   avformatContext->io_repositioned;cout << "avformatContext->io_repositioned = " << avformatContext->io_repositioned << endl;

43 const uint8_t *key; 作用未知

    const uint8_t *key;
    int keylen;

44     int keylen;作用未知

    const uint8_t *key;
    int keylen;

45    int max_chunk_duration;

    /**
     * Max chunk time in microseconds.
     * Note, not all formats support this and unpredictable things may happen if it is used when not supported.
     * - encoding: Set by user
     * - decoding: unused
     */
    int max_chunk_duration;

用于设置流媒体传输中的最大块持续时间。在FFmpeg的RTMP协议中,这个参数定义了每个RTMP消息的最大持续时间。如果超过这个时间,FFmpeg会自动将数据分成多个块进行传输,以确保流媒体的稳定性和效率。

max_chunk_duration的作用和重要性

  1. 稳定性‌:通过限制每个数据块的大小,max_chunk_duration有助于确保流媒体的稳定性。如果数据块过大,可能会导致网络延迟或丢包,影响观看体验。
  2. 效率‌:合理设置max_chunk_duration可以提高传输效率,减少缓冲时间,提升用户体验。
  3. 兼容性‌:不同的设备和网络环境对数据块的大小有不同的要求,合理设置max_chunk_duration可以增强兼容性。

如何设置max_chunk_duration

在FFmpeg的命令行中,可以通过-max_chunk_duration选项来设置

46

47

48

49

50

相关文章:

  • 【Mytais系列】Myatis的设计模式
  • 基于51单片机小型风扇设计—红外遥控
  • MySQL基础关键_006_DQL(五)
  • Vue3学习笔记2——路由守卫
  • 如何用CSS实现HTML元素的旋转效果:从基础到高阶应用
  • c++26新功能——gcc15.1的支持
  • Java大师成长计划之第11天:Java Memory Model与Volatile关键字
  • NVMe控制器之完成信息解析模块
  • 单片机嵌入式字符流数据解析库
  • c++ 二级指针 vs 指针引用
  • AI生成视频检测方法及其相关研究
  • 【电路笔记】-自耦变压器
  • java学习之数据结构:三、八大排序
  • 生成式 AI 的重要性
  • 在MySQL中建索引时需要注意哪些事项?
  • 【Linux知识】find命令行使用详解
  • 《ATPL地面培训教材13:飞行原理》——第5章:升力
  • 生物化学笔记:神经生物学概论08 运动系统 人类逐渐建立运动技能 不同层次的运动发起
  • 【AutoDL】云服务器配置指南
  • 架构师-金丝雀与蓝绿发布
  • “五一”假期第四天,全社会跨区域人员流动量预计超2.7亿人次
  • 习近平给谢依特小学戍边支教西部计划志愿者服务队队员的回信
  • 谢震业领衔挑战世界顶尖高手,这场长三角田径钻石赛值得期待
  • 德雷克海峡发生7.4级地震,震源深度10千米
  • 五一假期首日,省级党政“一把手”夜访商业街区
  • 韩国代总统、国务总理韩德洙宣布辞职