文章目录
-
- [🌟 前置说明:FFmpeg 中 AVFormatContext 是什么?](#🌟 前置说明:FFmpeg 中 AVFormatContext 是什么?)
- [🧩 1. `avformat_alloc_context`](#🧩 1.
avformat_alloc_context
) - [🧩 2. `avformat_open_input`](#🧩 2.
avformat_open_input
) - [🧩 3. `avformat_find_stream_info`](#🧩 3.
avformat_find_stream_info
) - [🧩 4. `av_read_frame`](#🧩 4.
av_read_frame
) - [🧩 5. `av_seek_frame` 和 `avformat_seek_file`](#🧩 5.
av_seek_frame
和avformat_seek_file
) -
- [🔹 `av_seek_frame`](#🔹
av_seek_frame
) - [🔹 `avformat_seek_file`](#🔹
avformat_seek_file
)
- [🔹 `av_seek_frame`](#🔹
- [🧩 6. `avformat_close_input`](#🧩 6.
avformat_close_input
) - [🧩 7. `avformat_free_context`](#🧩 7.
avformat_free_context
) - [🧪 一个最简 FFmpeg 读取流程(伪代码)](#🧪 一个最简 FFmpeg 读取流程(伪代码))
🌟 前置说明:FFmpeg 中 AVFormatContext 是什么?
AVFormatContext
是 FFmpeg 中用于描述一个媒体文件或媒体流(如视频文件、直播流)的结构体 ,包含了解码器、流信息、文件路径、数据缓冲等信息。
几乎所有操作媒体文件的函数都围绕这个结构体展开。
🧩 1. avformat_alloc_context
功能:
分配并初始化一个空的 AVFormatContext
结构体。
c
AVFormatContext *avformat_alloc_context(void);
场景:
如果你手动构建 AVFormatContext
,可以用它。但通常我们更常用的是 avformat_open_input
来自动分配。
🧩 2. avformat_open_input
功能:
打开一个输入媒体文件,并填充 AVFormatContext
(即打开文件并准备读取媒体信息)。
c
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);
说明:
ps
:传入的AVFormatContext*
的指针(通常为NULL
,内部自动分配)。url
:媒体文件路径或流地址(如"test.mp4"
或"rtmp://..."
)fmt
:一般为NULL
,FFmpeg 自动判断格式。options
:解封装选项,一般也是NULL
。
返回值:
- 0 表示成功
- 负数表示失败
🧩 3. avformat_find_stream_info
功能:
从媒体文件中读取流信息,比如视频流、音频流、字幕流等。
c
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
说明:
调用后,可以通过 AVFormatContext->streams[i]
获取流信息,比如帧率、分辨率、码率、时长等。
🧩 4. av_read_frame
功能:
读取一个包(packet),即从文件或流中读取一帧音视频数据。
c
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
说明:
- 数据读出后存放在
AVPacket
中。 - 每次读取的包可能来自视频、音频或其他流。
- 你需要检查
pkt->stream_index
来判断属于哪个流。
🧩 5. av_seek_frame
和 avformat_seek_file
这两个都用于跳转到某个时间位置,但用法略有不同。
🔹 av_seek_frame
c
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags);
stream_index
:选择参考哪个流(通常是视频流)timestamp
:跳转到的时间戳(单位是该流的 time_base)flags
:AVSEEK_FLAG_BACKWARD
:向后查找关键帧AVSEEK_FLAG_ANY
:允许跳非关键帧AVSEEK_FLAG_FRAME
:单位是帧,而不是时间戳
🔹 avformat_seek_file
c
int avformat_seek_file(AVFormatContext *s, int stream_index,
int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
这个函数更灵活,允许设置查找时间戳范围 [min_ts, max_ts]
,适合更复杂的跳转需求。
🧩 6. avformat_close_input
功能:
关闭输入文件并释放相关资源。
c
void avformat_close_input(AVFormatContext **ps);
注意:
- 会释放内部的 I/O 缓冲区和文件句柄
- 不会释放
AVFormatContext
本体,需要用avformat_free_context
(如果你手动分配了)
🧩 7. avformat_free_context
功能:
释放 AVFormatContext
结构体本身。
c
void avformat_free_context(AVFormatContext *s);
如果你使用了
avformat_alloc_context
创建的 AVFormatContext,那么用它来释放。
🧪 一个最简 FFmpeg 读取流程(伪代码)
c
AVFormatContext *fmt_ctx = NULL;
if (avformat_open_input(&fmt_ctx, "test.mp4", NULL, NULL) < 0) {
// 打开失败
}
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
// 获取流信息失败
}
AVPacket pkt;
while (av_read_frame(fmt_ctx, &pkt) >= 0) {
// 处理pkt
av_packet_unref(&pkt);
}
avformat_close_input(&fmt_ctx); // 释放文件相关资源
// 如果你手动alloc了 fmt_ctx,需要再:
avformat_free_context(fmt_ctx);