FFmpeg AVIO 内存输入/输出
学习FFmpeg过程中看到这篇文章ffmpeg avio 内存输入和内存输出,有一些疑惑的地方,问了deepseek清晰了不少,让deepseek根据我的疑问总结了一份笔记,方便回顾学习。
📌 核心概念
AVIO(自定义I/O):允许FFmpeg从非传统文件源(内存、网络、数据库等)读取数据,通过回调函数机制实现。
🔧 基本工作流程
1. 传统文件I/O vs AVIO自定义I/O
| 特性 | 传统文件I/O | AVIO自定义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)模式
💡 核心优势与应用场景
优势
- 性能优化:避免磁盘IO瓶颈,直接从内存操作
- 灵活性:支持各种数据源(网络流、加密数据、数据库等)
- 内存处理:适合处理需要先加载到内存的数据
典型应用场景
- ✅ 网络流媒体处理(RTMP、HTTP流等)
- ✅ 加密媒体文件解密播放
- ✅ 数据库存储的媒体数据处理
- ✅ 性能敏感的小文件处理
⚠️ 注意事项
内存管理
// 必须正确释放资源
av_file_unmap(buffer, buffer_size); // 释放文件映射
av_freep(&avio_ctx->buffer); // 释放AVIO缓冲区
avio_context_free(&avio_ctx); // 释放AVIO上下文
性能权衡
- 内存换速度:需要将整个文件加载到内存,占用较大内存空间
- 适合场景:中小文件或需要高性能处理的场景
🎓 关键总结
- AVIO核心:通过回调函数让FFmpeg从自定义数据源读取数据
- 绑定时机:
avio_alloc_context()调用时注册回调函数 - 调用机制:FFmpeg通过函数指针在需要读写数据时回调用户函数
- 适用场景:需要高性能或特殊数据源处理的场景

1313

被折叠的 条评论
为什么被折叠?



