FFmpeg 基本API avio_open函数内部调用流程分析

1、avio_open 函数定义

avio_open() 是 FFmpeg 的一个工具函数,用于打开一个用于读写的 AVIOContext,即 FFmpeg 的 I/O 上下文对象。它的主要作用是:

  • 初始化一个 AVIOContext
  • 调用 FFmpeg 协议层(如 file, http, tcp, udp)进行 URL 打开
  • 设置好 read_packet / write_packet / seek 等函数指针
  • 在 avformat_open_input() 中,如果没有提供自定义 AVIOContext,就会调用它打开默认的AVIOContext结构。
    函数原型如下:
cpp 复制代码
int avio_open(AVIOContext **s, const char *filename, int flags) {
    // 调用avio_open2 函数
    return avio_open2(s, filename, flags, NULL, NULL);
}
int avio_open2(AVIOContext **s, const char *filename, int flags,
               const AVIOInterruptCB *int_cb, AVDictionary **options)
{
    // 调用ffio_open_whitelist 函数
    return ffio_open_whitelist(s, filename, flags, int_cb, options, NULL, NULL);
}
int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags,
                        const AVIOInterruptCB *int_cb, AVDictionary **options,
                        const char *whitelist, const char *blacklist)
{
    URLContext *h;
    *s = NULL;
    // 1.分配URLContext结构体(根据文件名判断协议类型)
    err = ffurl_open_whitelist(&h, filename, 
    	flags, int_cb, options, whitelist, blacklist, NULL);
    // 2.根据URLContext结构体分配AVIOContext结构体
    err = ffio_fdopen(s, h);
    return 0;
}

参数说明:

  • AVIOContext **s:这是一个指向指针的指针(二级指针)。函数成功执行后,会分配并初始化一个新的 AVIOContext 结构体,并通过这个参数将其地址返回。AVIOContext 是 FFmpeg I/O 操作的核心数据结构,它封装了所有关于数据读写的操作和信息。

  • const char *url:要打开的资源定位符,也就是"文件名"或"URL"。支持多种协议,FFmpeg 会根据 URL 的前缀(如 http://, file:, rtmp://)自动选择对应的协议处理器。

复制代码
     "input.mp4" (本地文件)
     "file:input.mp4" (明确指定本地文件)
     "http://example.com/video.mpd" (HTTP 流)
     "rtmp://live.example.com/app/streamkey" (RTMP 推流)
  • int flags

    打开模式的标志位。指定读取数据还是写入数据。常用标志:

    AVIO_FLAG_READ:以只读方式打开。用于解复用(解码) ------ 从文件/网络流中读取数据。

    AVIO_FLAG_WRITE:以只写方式打开。用于复用(编码) ------ 将数据写入文件/网络流。

    AVIO_FLAG_READ_WRITE:以读写方式打开(较少使用)。

  • 返回值:

  • 成功:返回 >= 0 的值(通常是 0)。

  • 失败:返回一个负数的错误码(如 AVERROR(EACCES) 表示权限不足,AVERROR(ENOENT) 表示文件不存在)。

2、avio_open函数内部调用流程

  • 1.avio_open() → avio_open2()

    • 入口函数,验证参数后调用 avio_open2()。
  • 2.avio_open2() → ffio_open_whitelist()

    • 设置协议白名单(安全限制),传递协议处理函数列表。
  • 3.ffio_open_whitelist() → ffurl_open_whitelist()

    • 核心步骤:打开底层协议(如文件、TCP、HTTP等):
    • ffurl_alloc():
      • 遍历已注册协议(URLProtocol 链表),匹配 URL 的协议头(如 file://, http://)。
      • 为匹配的协议分配 URLContext 结构体,关联协议操作函数(URLProtocol)。
    • ffurl_connect():
      • 调用协议特定的 url_open() 方法(如 tcp_open(), file_open())。
      • 执行实际连接操作(如打开文件、建立套接字连接)。
    1. 初始化 AVIOContext
    • ffio_init_context():
      • 创建 AVIOContext 并绑定缓冲区。
    • 设置关键回调函数:
      • read_packet → url_read()
      • write_packet → url_write()
      • seek → url_seek()
        这些回调通过 URLContext 调用具体协议的读写方法。

3、avio_open调用时序图

相关推荐
爱吃生蚝的于勒4 小时前
【Linux】深入理解进程(一)
java·linux·运维·服务器·数据结构·c++·蓝桥杯
chuyanghong4 小时前
Ubuntu下VIM安装及配置
c++
boss-dog5 小时前
崩溃信息追溯——backward-cpp
c++·debug·backward-cpp
Hankin_Liu的技术研究室5 小时前
深入理解 C++ happens-before:高级并发程序员的必修课
c++
liu****6 小时前
20.哈希
开发语言·数据结构·c++·算法·哈希算法
Damon小智6 小时前
RedPlayer 视频播放器在 HarmonyOS 应用中的实践
音视频·harmonyos·鸿蒙·小红书·三方库·redplayer
爱和冰阔落6 小时前
【C++多态】虚函数/虚表机制与协变 、override和final关键字全解析
开发语言·c++·面试·腾讯云ai代码助手
码住懒羊羊6 小时前
【C++】stack|queue|deque
java·开发语言·c++
“αβ”6 小时前
了解“网络协议”
linux·服务器·网络·c++·网络协议·tcp/ip·tcp