3.7.1 打开文件的方式
下面提供一个简单的示例代码,演示了两种读取文件的方法:一种是直接使用 avformat_open_input 打开文件,另一种是通过创建自定义的 AVIOContext 进行文件读取。请注意,这个示例只是为了说明概念,实际使用中可能需要添加更多的错误处理和资源释放代码。
#include <libavformat/avformat.h>
// 读取文件的回调函数
int custom_read(void* opaque, uint8_t* buf, int buf_size) {
// 在这里实现自定义的文件读取逻辑
// 将文件数据拷贝到 buf 中,并返回实际读取的字节数
// 如果到达文件末尾,返回 0 表示结束
// 返回负值表示出现错误
// 示例中直接返回 0,表示文件结束
return 0;
}
int main() {
// 方法1: 直接使用 avformat_open_input 打开文件
AVFormatContext* format_ctx1 = avformat_alloc_context();
int ret1 = avformat_open_input(&format_ctx1, "input_file.mp4", NULL, NULL);
...
avformat_close_input(&format_ctx1);
// 方法2: 使用自定义的 AVIOContext 打开文件
AVFormatContext* format_ctx2 = avformat_alloc_context();
// 创建自定义的 AVIOContext
AVIOContext* avio_ctx = avio_alloc_context(
malloc(4096), // 缓冲区
4096, // 缓冲区大小
0, // 是否自动释放缓冲区
fd, // 用户数据,这里可以传递自定义结构体 FILE *fd = fread();
custom_read, // 读取数据的回调函数
NULL, // 写入数据的回调函数,这里不需要写入
NULL // 定位文件指针的回调函数,这里不需要定位
);
format_ctx2->pb = avio_ctx;
int ret2 = avformat_open_input(&format_ctx2, NULL, NULL, NULL);
if (ret2 < 0) {
// 错误处理
fprintf(stderr, "Error opening file using custom AVIOContext: %s\n", av_err2str(ret2));
return ret2;
}
// 处理 format_ctx2,例如读取音视频流等...
// 释放资源
avformat_close_input(&format_ctx2);
av_freep(&avio_ctx->buffer); // 释放缓冲区
avio_context_free(&avio_ctx); // 释放 AVIOContext
return 0;
}
在这个示例中,第一种方法直接使用 avformat_open_input 打开文件,而第二种方法通过创建自定义的 AVIOContext 并关联到 AVFormatContext 中,实现了自定义的文件读取逻辑。在实际使用中,你需要根据具体的需求来实现自定义的文件读取逻辑,并根据情况调整缓冲区大小、对齐等参数。
3.7.2 其余接口
AVIOContext 是 FFmpeg 中用于输入/输出(I/O)操作的上下文结构体。以下是与 AVIOContext 相关的一些主要接口和函数:
-
avio_alloc_context:AVIOContext *avio_alloc_context( unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t (*seek)(void *opaque, int64_t offset, int whence) );用于分配并初始化一个
AVIOContext结构体。可以指定读写标志、缓冲区等参数,以及一些回调函数,如读取、写入、定位等。 -
avio_open:int avio_open(AVIOContext **s, const char *url, int flags); s: 一个指向 AVIOContext 结构体指针的指针,用于存储创建的输入/输出上下文。 url: 表示要打开的文件的 URL 或路径。 flags: 表示打开文件的模式,可以是 AVIO_FLAG_READ(读取模式)、AVIO_FLAG_WRITE(写入模式)等 // 使用方法 AVFormatContext *fmt_ctx = avformat_alloc_context(); ret = avio_open(&fmt_ctx->pb, filename, AVIO_FLAG_WRITE);用于打开输入/输出上下文,通常用于文件或网络流。将创建的
AVIOContext存储在s指针指向的位置。 -
avio_close:int avio_close(AVIOContext *s);用于关闭输入/输出上下文,并释放相关资源。
-
avio_read:int avio_read(AVIOContext *s, unsigned char *buf, int size);从输入上下文读取数据到缓冲区。
-
avio_write:int avio_write(AVIOContext *s, const unsigned char *buf, int size);将数据写入输出上下文。
-
avio_seek:int64_t avio_seek(AVIOContext *s, int64_t offset, int whence);用于定位输入/输出上下文中的位置。
-
avio_flush:void avio_flush(AVIOContext *s);刷新缓冲区,确保所有缓冲的数据被写入。
-
avio_feof:int avio_feof(const AVIOContext *s);检查是否已经到达输入流的末尾。
这些函数提供了对 AVIOContext 结构体的常用操作,使得 FFmpeg 可以与不同的数据源进行交互,包括文件、网络流等。在使用这些函数时,需要根据具体的需求和场景选择合适的参数和回调函数。