FFmpeg AVIO 内存输入/输出

FFmpeg AVIO 内存输入/输出

学习FFmpeg过程中看到这篇文章ffmpeg avio 内存输入和内存输出,有一些疑惑的地方,问了deepseek清晰了不少,让deepseek根据我的疑问总结了一份笔记,方便回顾学习。

📌 核心概念

AVIO(自定义I/O):允许FFmpeg从非传统文件源(内存、网络、数据库等)读取数据,通过回调函数机制实现。


🔧 基本工作流程

1. 传统文件I/O vs AVIO自定义I/O

特性传统文件I/OAVIO自定义I/O
数据源直接读磁盘文件内存缓冲区、网络流、加密数据等
性能受磁盘IO限制内存速度,更快
内存占用低(缓冲区小)高(可能需加载整个文件)
灵活性固定(只能文件)高(可自定义数据源)

2. 代码结构概览

// 1. 定义自定义数据结构
struct buffer_data {
    uint8_t* ptr;     // 内存缓冲区指针
    size_t size;      // 剩余数据大小
};

// 2. 实现读回调函数
static int read_packet(void* opaque, uint8_t* buf, int buf_size) {
    struct buffer_data* bd = (struct buffer_data*)opaque;
    // 从内存复制数据到FFmpeg缓冲区
    memcpy(buf, bd->ptr, buf_size);
    bd->ptr += buf_size;
    bd->size -= buf_size;
    return buf_size;
}

// 3. 主函数中使用
int main() {
    // 加载文件到内存
    av_file_map("input.mp4", &buffer, &buffer_size, 0, NULL);
    
    // 创建AVIOContext并绑定回调
    avio_ctx = avio_alloc_context(buffer, buffer_size, 0, &bd, &read_packet, NULL, NULL);
    fmt_ctx->pb = avio_ctx;  // 关联到格式上下文
    
    // 正常使用FFmpeg API
    avformat_open_input(&fmt_ctx, NULL, NULL, NULL);
    // ... 其他操作
}

🔄 回调函数调用时机

FFmpeg操作与回调触发关系

FFmpeg函数调用read_packet目的读取数据量
avformat_open_input()解析容器格式头信息几百字节到几KB
avformat_find_stream_info()探测流信息,尝试解码几十KB到几MB
av_read_frame()读取音视频数据包每个数据包大小不等

验证调试技巧

read_packet中添加日志:

printf("read_packet: 请求大小=%d, 剩余数据=%zu\n", buf_size, bd->size);

🎯 回调机制原理

1. 绑定过程

// 创建AVIOContext时绑定回调函数
avio_ctx = avio_alloc_context(
    avio_ctx_buffer,      // 内部缓冲区
    avio_ctx_buffer_size, // 缓冲区大小
    0,                    // 写入标志(0=只读)
    &bd,                  // 用户数据(opaque指针)
    &read_packet,         // ⭐读回调函数指针⭐
    NULL,                 // 写回调(不需要)
    NULL                  // seek回调(不需要)
);

2. 内部调用链

av_read_frame() 
    → avio_read()           // FFmpeg通用读取接口
        → avio_ctx->read_packet()  // 通过函数指针调用
            → read_packet() // 你的自定义函数

3. 关键技术点

  • 函数指针:FFmpeg通过函数指针调用用户注册的回调
  • opaque参数:传递用户自定义数据(如buffer_data结构体)
  • 设计模式:典型的回调(Callback)模式

💡 核心优势与应用场景

优势

  1. 性能优化:避免磁盘IO瓶颈,直接从内存操作
  2. 灵活性:支持各种数据源(网络流、加密数据、数据库等)
  3. 内存处理:适合处理需要先加载到内存的数据

典型应用场景

  • ✅ 网络流媒体处理(RTMP、HTTP流等)
  • ✅ 加密媒体文件解密播放
  • ✅ 数据库存储的媒体数据处理
  • ✅ 性能敏感的小文件处理

⚠️ 注意事项

内存管理

// 必须正确释放资源
av_file_unmap(buffer, buffer_size);    // 释放文件映射
av_freep(&avio_ctx->buffer);          // 释放AVIO缓冲区
avio_context_free(&avio_ctx);         // 释放AVIO上下文

性能权衡

  • 内存换速度:需要将整个文件加载到内存,占用较大内存空间
  • 适合场景:中小文件或需要高性能处理的场景

🎓 关键总结

  1. AVIO核心:通过回调函数让FFmpeg从自定义数据源读取数据
  2. 绑定时机avio_alloc_context()调用时注册回调函数
  3. 调用机制:FFmpeg通过函数指针在需要读写数据时回调用户函数
  4. 适用场景:需要高性能或特殊数据源处理的场景
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值