FFMPEG结构体分析
FFMPEG结构体分析
附录:参考文献
[1] 结构体分析:https://www.cnblogs.com/linuxAndMcu/p/12041578.html#_label2
[2] 音视频入门系列
FFmpeg结构体主要分为三个层次:
- 协议层(Protocol:http, rtsp, rtmp,file)
AVIOContext,URLProtocol,URLContext
主要存储音视频使用的协议的类型以及状态。URLProtocol 存储输入音视频使用的封装格式。每种协议都对应一个 URLProtocol 结构。- 封装层(Format:flv, avi, rmvb, mp4)
- AVFormatContext 主要存储音视频封装格式中包含的信息;AVInputFormat 存储输入音视频使用的封装格式。每种音视频封装格式都对应一个 AVInputFormat 结构。
- 解码层(Codec:h264, mpeg2, aac, mp3)
- 每个 AVStream 存储一个视频/音频流的相关数据;每个 AVStream 对应一个 AVCodecContext,存储该视频/音频流使用解码方式的相关数据;每个 AVCodecContext 中对应一个 AVCodec,包含该视频/音频对应的解码器。每种解码器都对应一个 AVCodec 结构。
1 AVFormatContext
描述媒体文件或媒体流的构成和基本信息,贯穿ffmpeg使用整个流程
表示一个多媒体文件或流的全局上下文信息。它包含输入输出格式、媒体流信息,以及操作文件或流所需的状态。
avformat_open_input()
- 用于打开媒体文件或流,初始化
AVFormatContext
。
avformat_alloc_output_context2()
创建一个新的输出
AVFormatContext
。
AVFormatContext
用于描述目标输出文件的格式和流。**
avformat_find_stream_info()
**获取媒体流信息(如视频流、音频流等)。
AVFormatContext
用于存储和返回文件的流信息。**
av_read_frame()
**从媒体文件中读取一个数据包(帧)。
- 使用
AVFormatContext
来获取流信息和文件数据。…许多API函数都使用到该结构体
//基本信息成员
AVInputFormat *iformat、AVOutputFormat *oformat://输入或者输出流的格式(只能存在一个)
char *url://文件名
//IO操作成员
AVIOContext *pb://管理输入输出数据(缓存)
//流媒体相关成员
unsigned int nb_streams://音视频流的个数
AVStream **streams://音视频流
//时间和同步
int64_t duration://时长
//其它
int bit_rate://比特率(单位bite/s)
AVDictionary *metadata://元数据(查看元数据:ffprobe filename)
2 AVInputFormat
表示输入媒体文件或流的封装格式。它定义了如何读取、解析、和处理特定格式的媒体文件或流,例如 MP4、MKV、FLV 等。
av_find_input_format、avformat_open_input
AVInputFormat *av_find_input_format(const char *short_name);
根据指定的格式名称查找\打开
AVInputFormat
。
avformat_find_stream_info
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
函数内部会根据输入格式(通过
AVInputFormat
)对媒体文件进行处理,提取其中的流信息。
char* name://封装格式的名字
char* long_name://封装格式的长名字
char* extensions://文件扩展名,例如 "mp4,mov"。
3 AVIOContext->URLContext->URLProtocol
3.1 AVIOContext
文件(协议)操作的顶层对象,用于管理媒体文件或流的输入输出操作。它提供了一套通用的接口,用于读取和写入文件、网络流、内存缓冲区等数据源或数据目标。
avio_alloc_context
AVIOContext *avio_alloc_context(...)
- 分配一个
AVIOContext
,用来进行 I/O 操作
//IO 缓冲区
unsigned char *buffer://缓冲开始位置
int buffer_size://缓冲区大小(默认32768)
unsigned char *buf_ptr://当前指针读取到的位置
unsigned char *buf_end://缓存结束的位置
//其它
void *opaque://URLContext结构体,通常传递到回调函数中,允许用户存储自定义上下文信息。
//读写回调函数
(*read_packet)(...)://自定义的读取函数回调。
(*write_packet)(...)://自定义的写入函数回调。
(*read_pause)(...)://网络流媒体协议的暂停或恢复播放函数指针
3.2 URLContext
用于抽象和管理底层的 I/O 操作。它为各种协议(如文件系统、网络协议等)提供了统一的访问接口。
URLContext
是AVIOContext
的底层实现之一。通过URLContext
,FFmpeg 可以对文件、网络流、管道等不同类型的数据源或目标进行操作,而用户通常通过更高级别的AVIOContext
接口与之交互。
url_open
int url_open(URLContext **puc, const char *filename, int flags)
打开一个 URL 或文件。
char* name://协议名称
const struct URLProtocol *prot://协议操作对象(ff_file_protocol、ff_librtmp_protocol...)
void *priv_data://协议对象(FileContext、LibRTMPContext)
3.3 URLProtocol
用于实现协议层抽象的结构体,负责定义如何与特定协议(如文件系统、HTTP、RTSP 等)交互。
4 AVStream
存储音频流或视频流的结构体
//其它
int index://流的索引值,唯一标识容器中的每个流。
AVRational avg_frame_rate://平均帧率
//元数据相关
AVCodecParameters *codecpar://解码器参数,例如编码类型(音频、视频、字幕),采样率,分辨率等。
int64_t duration://流的持续时间
AVRational time_base://流的时间基,用于将时间戳转换为秒。
5 AVCodecParameter 和 AVCodecContext
新的 ffmpeg 中
AVStream.codecpar(struct AVCodecParameter)
代替
AVStream.codec(struct AVCodecContext)
; AVCodecParameter 是由 AVCodecContext 分离出来的,AVCodecParameter中没有函数
AVCodecContext 结构体仍然是编解码时不可或缺的结构体:avcodec_send_packet 和 avcodec_receive_frame 使用 AVCodecContext
5.1 AVCodecContext
用于表示编解码器的静态描述信息。
5.2 AVCodecParameters
用于存储与媒体流(如音频、视频或字幕)相关的编码参数。ffmpeg3.1引入,用来分离编解码器的参数信息与解码器/编码器的具体实现。
6 AVCodec
表示编解码器的静态描述信息,每一个解码器对应一个AVCodec结构体
1. 查找编解码器
- 使用
avcodec_find_decoder()
或avcodec_find_encoder()
,通过AVCodec
获取解码器或编码器。2. 编解码器初始化
- 在
AVCodecContext
中,通过关联AVCodec
来完成初始化。
const char *name://编解码器短名字(形如:"h264")
const char *long_name://编解码器全称(形如:"H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10")
enum AVMediaType type://媒体类型:视频、音频或字母
enum AVCodecID id://标示特定的编码器
const AVRational *supported_framerates://支持的帧率(仅视频)
const enum AVPixelFormat *pix_fmts://支持的像素格式(仅视频)
const int *supported_samplerates://支持的采样率(仅音频)
const enum AVSampleFormat *sample_fmts://支持的采样格式(仅音频)
const uint64_t *channel_layouts://支持的声道数(仅音频)
7 AVPacket
存储压缩编码数据相关信息的结构体;
例如 从解复用器(
av_read_frame
)读取压缩数据包。 将数据包发送到解码器(
avcodec_send_packet
)。 解码器将解码后的帧输出为
AVFrame
。
AVBufferRef *buf://管理data指向的数据
uint8_t *data: //压缩编码的数据
int size: //data的大小
int64_t pts: //显示时间戳
int64_t dts: //解码时间戳
int stream_index://标识该AVPacket所属的视频/音频流
8 AVFrame
用于存储原始数据(即非压缩数据,例如对视频来说是 YUV,RGB,对音频来说是 PCM),此外还包含了一些相关的信息。
1. 初始化和分配
av_frame_alloc()
分配一个新的AVFrame
。2. 释放资源
av_frame_unref(AVFrame *frame)
释放帧数据,清空AVFrame
的内容。av_frame_free(AVFrame **frame)
释放AVFrame
的内存。3. 数据管理
av_frame_get_buffer(AVFrame *frame, int align)
为AVFrame
分配缓冲区。av_frame_make_writable(AVFrame *frame)
确保AVFrame
可写,如果当前数据不可写,会分配新的缓冲区。
uint8_t *data[AV_NUM_DATA_POINTERS]://解码后原始数据(对视频来说是YUV,RGB,对音频来说是PCM)
int linesize[AV_NUM_DATA_POINTERS]://data中“一行”数据的大小。注意:未必等于图像的宽,一般大于图像的宽。
int width, height://视频帧宽和高(1920x1080,1280x720...)
int nb_samples://音频的一个AVFrame中可能包含多个音频帧,在此标记包含了几个
int format://解码后原始数据类型(YUV420,YUV422,RGB24...)
int key_frame://是否是关键帧
enum AVPictureType pict_type://帧类型(I,B,P...)
AVRational sample_aspect_ratio://图像宽高比(16:9,4:3...)
int64_t pts://显示时间戳
int coded_picture_number://编码帧序号
int display_picture_number://显示帧序号