记录下ffmpeg常用的一些函数和数据结构
环境:ffmpeg-6.1
1、ffmpeg库
libavcodec
音视频编解码核心库
libavformat
音视频容器格式的封装和解析
libavutil
音视频工具库,包含了常见的通用工具和各类算法库,其中通用工具包括字典操作、日志记录、缓存交互、线程处理,以及加解密库aes、md5、sha、base64、等;各类算法包括排队算法fifo、排序算法qsort、哈希表hash、二叉树tree等等。除此以外,avutil也囊括了色彩空间、音频采样等方面的公共函数
libavfilter
音视频滤镜库,提供了音频特效和视频特效的处理,如视频加水印、音频变声
libavdevice
输入输出设备库,提供设备数据的输入与输出,和硬件设备交互。其中输入设备指的是采集音视频信号的设备,输出设备指的是渲染音视频画面的设备。FFmpeg不会直接操作设备硬件,而是通过第三方的软件包去实现,比如采集媒体信号用到了Windows平台的VFW捕捉器(VFW全称Video for Windows),以及VFW的升级版DirectShow捕捉器;渲染媒体画面用到了Windows平台的GDI接收器(GDI全称Graphics Device Interface),以及跨平台的SDL2媒体开发库(SDL全称Simple DirectMedia Layer)。当然,FFmpeg也支持音效处理库OpenAL(全称Open Audio Library)和图形处理库OpenGL(全称Open Graphics Library)
libswresample
音频重采样库
libswscale
视频图像转换库,主要用于图像缩放、色彩空间转换等功能,其中色彩空间转换有时也被称作像素格式转换,比如把视频帧从YUV格式转换为RGB格式
libpostproc
用于进行后期处理,使用AVFilter的时候需要打开该模块的开关,因为Filter中会使用到该模块的一些基础函数
2、ffmpeg常用函数
av_register_all()
注册所有组件,4.0已经弃用
avdevice_register_all()
对设备进行注册,比如V4L2等。
avformat_network_init()
初始化网络库以及网络加密协议相关的库(比如openssl)
2.1 封装格式相关
avformat_alloc_context()
负责申请一个AVFormatContext结构的内存,并进行简单初始化
avformat_free_context()
释放该结构里的所有东西以及该结构本身
avformat_open_input()
打开输入音视频文件
avformat_close_input()
关闭解复用器。关闭后就不再需要使用avformat_free_context 进行释放
avformat_find_stream_info()
获取音视频文件信息
avformat_alloc_output_context2()
创建输出AVFormatContext,根据指定的输出格式名称和文件名创建 AVFormatContext 结构体,并且可以自动选择输出封装器(muxer)
avformat_new_stream()
创建输出码流的AVStream
avio_open()
打开输出文件
avformat_write_header()
写文件头(对于某些没有文件头的封装格式,不需要此函数。比如说MPEG2TS)
av_interleaved_write_frame()
将AVPacket(存储视频压缩码流数据)写入文件
av_write_trailer()
写文件尾(对于某些没有文件头的封装格式,不需要此函数。比如说MPEG2TS)
av_read_frame()
读取音视频包AVPacket
avformat_seek_file()
定位文件(可通过时间定位)
av_seek_frame()
定位文件(可通过文件大小定位)
2.2 解码器相关
avcodec_alloc_context3()
分配解码器上下文
avcodec_parameters_to_context()
码流中的编解码器信息拷贝到AVCodecContext
avcodec_find_decoder()
根据ID查找解码器
avcodec_find_decoder_by_name()
根据解码器名字查找解码器
avcodec_open2()
打开编解码器
avcodec_decode_video2()
解码一帧视频数据(废弃)
avcodec_decode_audio4()
解码一帧音频数据(废弃)
avcodec_send_packet()
发送编码数据包
avcodec_receive_frame()
接收解码后数据
avcodec_free_context()
释放解码器上下文,包含了avcodec_close()
avcodec_close()
关闭解码器
2.3 组件注册
FFmepg内部去做,不需要用户调用API去注册。
对于demuxer/muxer 则对应
libavformat/muxer_list.c
libavformat/demuxer_list.c
这两个文件是在configure的时候生成的。
在libavformat/allformats.c将demuxer_list[]和muexr_list[]以链表的方式组织。
其他组件也是类似的方式
muxer_list.c
static const FFOutputFormat * const muxer_list[] = {
&ff_a64_muxer,
...
NULL };
demuxer_list.c
static const AVInputFormat * const demuxer_list[] = {
&ff_aa_demuxer,
...
NULL };
allformats.c
const AVOutputFormat *av_muxer_iterate(void **opaque)
{
static const uintptr_t size = sizeof(muxer_list)/sizeof(muxer_list[0]) - 1;
uintptr_t i = (uintptr_t)*opaque;
const FFOutputFormat *f = NULL;
uintptr_t tmp;
if (i < size) {
f = muxer_list[i];
} else if (tmp = atomic_load_explicit(&outdev_list_intptr, memory_order_relaxed)) {
const FFOutputFormat *const *outdev_list = (const FFOutputFormat *const *)tmp;
f = outdev_list[i - size];
}
if (f) {
*opaque = (void*)(i + 1);
return &f->p;
}
return NULL;
}
const AVInputFormat *av_demuxer_iterate(void **opaque)
{
static const uintptr_t size = sizeof(demuxer_list)/sizeof(demuxer_list[0]) - 1;
uintptr_t i = (uintptr_t)*opaque;
const AVInputFormat *f = NULL;
uintptr_t tmp;
if (i < size) {
f = demuxer_list[i];
} else if (tmp = atomic_load_explicit(&indev_list_intptr, memory_order_relaxed)) {
const AVInputFormat *const *indev_list = (const AVInputFormat *const *)tmp;
f = indev_list[i - size];
}
if (f)
*opaque = (void*)(i + 1);
return f;
}
3、ffmpeg常用数据结构
AVFormatContext
封装格式上下文结构体,也是统领全局的结构体,保存了音视频文件封装格式相关信息。
部分字段说明:
iformat | 输入媒体的AVInputFormat,比如指向AVInputFormatff_flv_demuxer |
nb_streams | 输入媒体的AVStream 个数 |
streams | 输入媒体的AVStream []数组 |
duration | 输入媒体的时长(以微秒为单位),计算方式可以参考av_dump_format()函数 |
bit_rate | 输入媒体的码率 |
AVInputFormat
输入文件封装格式,每种封装格式对应一个AVInputFormat 结构体
部分字段说明:
name | 封装格式名称 |
extensions | 封装格式的扩展名 |
一些封装格式处理的接口函数 | 比如read_packet() |
AVOutputFormat
输出文件封装格式,每种封装格式对应一个AVOutputFormat 结构体
AVStream
视频文件中每个视频(音频)流对应一个该结构体
部分字段说明:
index | 标识该视频/音频流 |
time_base | 该流的时基, PTS*time_base=真正的时间(秒) |
avg_frame_rate | 该流的帧率 |
duration | 该视频/音频流长度 |
codecpar | 编解码器参数属性 |
AVCodecParameters
保存音视频流的基本参数信息。该结构体通常会在AVCodecContext中被填充并使用
部分字段说明:
codec_type | 媒体类型,比如AVMEDIA_TYPE_VIDEO AVMEDIA_TYPE_AUDIO等 |
codec_id | 编解码器类型, 比如AV_CODEC_ID_H264 AV_CODEC_ID_AAC |
AVCodecContext
编解码器上下文结构体,保存了视频(音频)编解码相关信息
部分字段说明:
codec | 编解码器的AVCodec,比如指向AVCodec ff_aac_latm_decoder |
width, height | 图像的宽高(只针对视频) |
pix_fmt | 像素格式(只针对视频) |
sample_rate | 采样率(只针对音频) |
channels | 声道数(只针对音频) |
sample_fmt | 采样格式(只针对音频 |
AVCodec
每种视频(音频)编解码器(例如H.264解码器)对应一个该结构体
部分字段说明:
name | 编解码器名称 |
type | 媒体类型 |
id | 编解码器ID |
一些编解码的接口函数 | 比如int (*decode)() |
AVPacket
存储一帧压缩编码数据
部分字段说明:
pts | 显示时间戳 |
dts | 解码时间戳 |
data | 压缩编码数据 |
size | 压缩编码数据大小 |
pos | 数据的偏移地址 |
stream_index | 所属的AVStream |
AVFrame
存储一帧解码后yuv图像(采样)数据
部分字段说明:
data | 解码后的图像像素数据(音频采样数据) |
linesize | 对视频来说是图像中一行像素的大小;对音频来说是整个音频帧的大小 |
width, height | 图像的宽高(只针对视频) |
key_frame | 是否为关键帧(只针对视频) |
pict_type | 帧类型(只针对视频) 。例如I, P, B |
sample_rate | 音频采样率(只针对音频) |
nb_samples | 音频每通道采样数(只针对音频) |
pts | 显示时间戳 |
3.1 数据结构关系
AVFormatContext,AVStream和AVCodecContext之间的关系
AVPacket和AVFrame之间的关系