本文主要是介绍FFmpeg:浅谈 AVFrame 结构体,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
成员变量
struct AVFrame 是一个很基础的类型,顾名思义,主要用来管理解码后的音视频数据:
- 视频:一个
AVFrame对象可存储一帧图像。 - 音频:一个
AVFrame对象可存储若干个采样点。
个人理解,AVFrame 主要的成员变量按照功能可划分为四部分:
- 数据部分,这是最核心的部分啦,存储了解码后的音视频数据
uint8_t *data[AV_NUM_DATA_POINTERS]:存储音视频数据int linesize[AV_NUM_DATA_POINTERS];:描述数据长度。具体含义取决于数据格式。uint8_t **extended_data;:data的补充字段。当data不够用时,可用该字段存储。AVBufferRef *buf[AV_NUM_DATA_POINTERS];:和data对应的引用计数器。buf[i]和data[i]一一对应。当buf全为nullptr时,说明该对应未启用引用计数功能。AVBufferRef **extended_buf;:和extended_data对应的引用计数器。int nb_extended_buf;:extended_buf的长度。
- 辅助部分,用于解析数据部分,这里仅列出了一部分
- 视频部分:
int width, height;:宽高int key_frame;:1 → keyframe, 0 → notenum AVPictureType pict_type;:类型。I,P,B,S,SI,SP,BI。AVRational sample_aspect_ratio;:注释没看懂,度娘说是单个像素的宽高比。int coded_picture_number;:比特流中的编码序列号。int display_picture_number;:播放序列号。int repeat_pict;:延迟参数,extra_delay = repeat_pict / (2*fps),未使用过。
- 音频部分:
int nb_samples;:采样点的数量。int sample_rate;:采样率。uint64_t channel_layout;:声道布局。单声道,立体声,5.1 等等,详见函数av_bprint_channel_layout。channels:声道数量。
- 共用:
int format;:其值为enum AVPixelFormat(对应视频) 或enum AVSampleFormat(对应音频)int64_t pts;:渲染时间,单位记录在time_base中。按个人经验看,有些解码器未给出该值,还是从对应的AVStream中取妥当。int64_t pkt_dts;:该帧的解包时间。AVRational time_base;:时间单位。int quality;:取值范围在[1,FF_LAMBDA_MAX],越小越好。
- 视频部分:
- 用户相关部分:
AVBufferRef *opaque_ref;:用户可以放一些自定义数据在这。av_frame_*等相关函数会维护其生命周期。void *opaque:也是用户自定义的数据,但用户需自己维护生命周期。
codec相关部分,一些codec依赖的字段,具体怎么用还不清楚,先记录在这里AVFrameSideData **side_data;:具体怎么用还不清楚。int nb_side_data;:side_data的长度。AVBufferRef *private_ref;AVBufferRef *hw_frames_ctx;AVDictionary *metadata;:用户和codec可通过此字段传递各种类型的 KV 数据。
个人感觉,较难理清的是 data,extened_data,buf,extended_buf 之间的关系,这里记录下 av_frame_get_buffer 如何初始化上述四个变量。
根据音视频数据是 packed 或者 planar 格式,使用方法略有差异。
视频的 packed 格式有
AV_PIX_FMT_YUYV422,AV_PIX_FMT_UYYVYY411等。
视频的 planar 格式有AV_PIX_FMT_YUV420P,AV_PIX_FMT_YUV444P等。
音频的 packed 格式有AV_SAMPLE_FMT_U8,AV_SAMPLE_FMT_FLT等。
音频的 planar 格式有AV_SAMPLE_FMT_S32P,AV_SAMPLE_FMT_FLTP等。
简单概括,后缀为P的则为 planar 格式,反之为 packed 格式。
当数据为 packed 格式时:
extended_buf:未使用,初始化后值为nullptr。buf:仅使用buf[0],其余均为空。data:- 当数据为音频时,仅使用
data[0],值为buf[0]->data; - 当数据为视频时,根据
AVFrame::format字段决定。
- 当数据为音频时,仅使用
extended_data:指向data。
下图是 AVFrame::format 为 AV_PIX_FMT_YUYV422 时的情形:

当数据为 planar 格式时,设 c 为 planar 的数量:
buf:使用buf[0..min(7,c-1)]。extend_buf:当 c > 8 c\gt 8 c>8 时启用,指向一段新分配的内存,该内存存储了长度为 c − 8 c-8 c−8 的指针数组。data:使用buf[0..min(7,c-1)]。extended_data:- 当 c ≤ 8 c\le 8 c≤8 时,指向
data。 - 当 c > 8 c\gt 8 c>8 时,新分配一段内存,该内存存储了长度为 c c c 的指针数组。
- 当 c ≤ 8 c\le 8 c≤8 时,指向
下图以 c = 10 c = 10 c=10 的音频数据为例:

相关函数
AVFrame *av_frame_alloc(void)
分配一段内存,用于存储一个 AVFrame 对象。
void av_frame_free(AVFrame **frame)
释放相关内存。
int av_frame_ref(AVFrame *dst, const AVFrame *src)
该函数会处理所有字段,该复制的复制,该引用的引用。
void av_frame_unref(AVFrame *frame)
重置 AVFrame。可复用重置后的 AVFrame 对象,避免重复的分配回收内存。
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
该函数不会处理 AVFrame::buf 和 AVFrame::extended_buf。
int av_frame_get_buffer(AVFrame *frame, int align)
该函数会根据初始化 data、extended_data、 buf、extended_buf 等字段。
这篇关于FFmpeg:浅谈 AVFrame 结构体的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!