本文主要是介绍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 结构体的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!