1. 数据结构定义
1.1 相关基础概念
在阅读 AVFrame 数据结构之前,需要先了解与之相关的几个基础概念(此处只考虑视频相关):
pixel_format:像素格式,图像像素在内存中的排列格式。一种像素格式包含有色彩空间、采样方式、存储模式、位深等信息。
bit_depth: 位深,指每个分量(Y、U、V、R、G、B 等)单个采样点所占的位宽度。
plane: 存储图像中一个或多个分量的一片内存区域。planar 存储模式中,至少有一个分量占用单独的一个 plane,planar 存储模式至少有两个 plane,具体到 yuv420p 格式有 Y、U、V 三个 plane,nv12 格式有 Y、UV 两个 plane,gbrap 格式有 G、B、R、A 四个 plane。packed 存储模式中,因为所有分量的像素是交织存放的,所以 packed 存储模式只有一个 plane。
slice: 图像中一片连续的行,必须是连续的,顺序由顶部到底部或由底部到顶部
stride/pitch: 一行图像中某个分量(如亮度分量或色度分量)所占的字节数, 也就是一个 plane 中一行数据的宽度。有对齐要求,计算公式如下:
stride 值 = 图像宽度 * 分量数 * 单样本位宽度 / 水平子采样因子 / 8
其中,图像宽度表示图像宽度是多少个像素,分量数指当前 plane 包含多少个分量(如 rgb24 格式一个 plane 有 R、G、B 三个分量),单位本位宽度指某分量的一个样本在考虑对齐后在内存中占用的实际位数(例如位深 8 占 8 位宽,位深 10 实际占 16 位宽,对齐值与平台相关),水平子采样因子指在水平方向上每多少个像素采样出一个色度样本(亮度样本不进行下采样,所以采样因子总是 1)。
上述概念的详细说明可参考“色彩空间与像素格式”一文第 4 节。
1.2 AVFrame 数据结构
struct AVFrame 定义于 <libavutil/frame.h>
struct AVFrame frame;
AVFrame 中存储的是经过解码后的原始数据。在解码中,AVFrame 是解码器的输出;在编码中,AVFrame 是编码器的输入。下图中,“decoded frames”的数据类型就是 AVFrame:
_______ ______________ | | | | | input | demuxer | encoded data | decoder | file | ---------> | packets | -----+ |_______| |______________| | v _________ | | | decoded | | frames | |_________| ________ ______________ | | | | | | | output | <-------- | encoded data | <----+ | file | muxer | packets | encoder |________| |______________|
AVFrame 数据结构非常重要,它的成员非常多,导致数据结构定义篇幅很长。下面引用的数据结构定义中省略冗长的注释以及大部分成员,先总体说明 AVFrame 的用法,然后再将一些重要成员摘录出来单独进行说明:
/**
* This structure describes decoded (raw) audio or video data.
*
* AVFrame must be allocated using av_frame_alloc(). Note that this only
* allocates the AVFrame itself, the buffers for the data must be managed
* through other means (see below).
* AVFrame must be freed with av_frame_free().
*
* AVFrame is typically allocated once and then reused multiple times to hold
* different data (e.g. a single AVFrame to hold frames received from a
* decoder). In such a case, av_frame_unref() will free any references held by
* the frame and reset it to its original clean state before it
* is reused again.
*
* The data described by an AVFrame is usually reference counted through the
* AVBuffer API. The underlying buffer references are stored in AVFrame.buf /
* AVFrame.extended_buf. An AVFrame is considered to be reference counted if at
* least one reference is set, i.e. if AVFrame.buf[0] != NULL. In such a case,
* every single data plane must be contained in one of the buffers in
* AVFrame.buf or AVFrame.extended_buf.
* There may be a single buffer for all the data, or one separate buffer for
* each plane, or anything in between.
*
* sizeof(AVFrame) is not a part of the public ABI, so new fields may be added
* to the end with a minor bump.
*
* Fields can be accessed through AVOptions, the name string used, matches the
* C structure field name for fields accessible through AVOptions. The AVClass
* for AVFrame can be obtained from avcodec_get_frame_class()
*/
typedef struct AVFrame {
uint8_t *data[AV_NUM_DATA_POINTERS];
int linesize[AV_NUM_DATA_POINTERS];
uint8_t **extended_data;
int width, height;
int nb_samples;
int format;
int key_frame;
enum AVPictureType pict_type;
AVRational sample_aspect_ratio;
int64_t pts;
......
} AVFrame;
AVFrame 的用法:
-
AVFrame 对象必须调用 av_frame_alloc() 在堆上分配,注意此处指的是 AVFrame 对象本身,AVFrame 对象必须调用 av_frame_free() 进行销毁。
-
AVFrame 中包含的数据缓冲区是
-
AVFrame 通常只需分配一次,然后可以多次重用,每次重用前应调用 av_frame_unref() 将 frame 复位到原始的干净可用的状态。
下面将一些重要的成员摘录出来进行说明: data
/**
* pointer to the picture/channel planes.
* This might be different from the first allocated byte
*
* Some decoders access areas outside 0,0 - width,height, please
* see avcodec_align_dimensions2(). Some filters and swscale can read
* up to 16 bytes beyond the planes, if these filters are to be used,
* then 16 extra bytes must be allocated.
*
* NOTE: Except for hwaccel formats, pointers not needed by the format
* MUST be set to NULL.
*/
uint8_t *data[AV_NUM_DATA_POINTERS];
存储原始帧数据(未编码的原始图像或音频格式,作为解码器的输出或编码器的输入)。
data 是一个指针数组,数组的每一个元素是一个指针,指向视频中图像的某一 plane 或音频中某一声道的 plan