ffmpeg AVFrame结构体及其相关函数

0. 简介

AVFrame中存储的是原始数据(例如视频的YUV, RGB, 音频的PCM), 此外还包含了一些相关的信息, 例如: 解码的时候存储了宏块类型表, QP表, 运动矢量等数据. 编码的时候也存储了相关的数据.

 

1. AVFrame 数据结构定义

FFmpeg 版本3.4.1

struct AVFrame 定义于<libavutil/frame.h>

结构体源码(我去除了注释):

  1 typedef struct AVFrame {
  2 #define AV_NUM_DATA_POINTERS 8
  3 
  4     uint8_t *data[AV_NUM_DATA_POINTERS];
  5 
  6     int linesize[AV_NUM_DATA_POINTERS];
  7 
  8     uint8_t **extended_data;
  9 
 10     int width, height;
 11  
 12     int nb_samples;
 13 
 14     int format;
 15 
 16     int key_frame;
 17 
 18     enum AVPictureType pict_type;
 19 
 20     AVRational sample_aspect_ratio;
 21 
 22     int64_t pts;
 23 
 24 #if FF_API_PKT_PTS
 25 
 26     attribute_deprecated
 27     int64_t pkt_pts;
 28 #endif
 29 
 30     int64_t pkt_dts;
 31 
 32     int coded_picture_number;
 33 
 34     int display_picture_number;
 35 
 36     int quality;
 37 
 38     void *opaque;
 39 
 40 #if FF_API_ERROR_FRAME
 41 
 42     attribute_deprecated
 43     uint64_t error[AV_NUM_DATA_POINTERS];
 44 #endif
 45 
 46     int repeat_pict;
 47 
 48     int interlaced_frame;
 49 
 50     int top_field_first;
 51 
 52     int palette_has_changed;
 53 
 54     int64_t reordered_opaque;
 55 
 56     int sample_rate;
 57 
 58     uint64_t channel_layout;
 59 
 60     AVBufferRef *buf[AV_NUM_DATA_POINTERS];
 61 
 62     AVBufferRef **extended_buf;
 63    
 64     int        nb_extended_buf;
 65 
 66     AVFrameSideData **side_data;
 67     int            nb_side_data;
 68 
 69 #define AV_FRAME_FLAG_CORRUPT       (1 << 0)
 70 
 71 #define AV_FRAME_FLAG_DISCARD   (1 << 2)
 72 
 73     int flags;
 74 
 75     enum AVColorRange color_range;
 76 
 77     enum AVColorPrimaries color_primaries;
 78 
 79     enum AVColorTransferCharacteristic color_trc;
 80 
 81     enum AVColorSpace colorspace;
 82 
 83     enum AVChromaLocation chroma_location;
 84 
 85     int64_t best_effort_timestamp;
 86 
 87     int64_t pkt_pos;
 88 
 89     int64_t pkt_duration;
 90 
 91     AVDictionary *metadata;
 92 
 93     int decode_error_flags;
 94 #define FF_DECODE_ERROR_INVALID_BITSTREAM   1
 95 #define FF_DECODE_ERROR_MISSING_REFERENCE   2
 96 
 97     int channels;
 98 
 99     int pkt_size;
100 
101 #if FF_API_FRAME_QP
102     attribute_deprecated
103     int8_t *qscale_table;
104    
105     attribute_deprecated
106     int qstride;
107 
108     attribute_deprecated
109     int qscale_type;
110 
111     AVBufferRef *qp_table_buf;
112 #endif
113 
114     AVBufferRef *hw_frames_ctx;
115 
116     AVBufferRef *opaque_ref;
117 
118     size_t crop_top;
119     size_t crop_bottom;
120     size_t crop_left;
121     size_t crop_right;
122 } AVFrame;
  • 带有#if ...  #end包含的字段, 都是将要被弃用或已经弃用的. 不再进行解释.

 

  • 必须使用av_frame_alloc()分配AVFrame, 这只是分配AVFram本身.
  • 必须使用av_frame_free()释放.

 

  • uint8_t *data[AV_NUM_DATA_POINTERS];

原始数据(对视频来说是YUB, RGB, 对音频来说是PCM)

data是一个指针数组, 数组的每一个元素都是一个指针. 指向视频中图像的某一plane或者音频中某一声道的plane.

对于packed格式, 一个YUV图像的Y, U, V交织存储在一个plane中, 例如: YUVYUVYUV... ..., data[0]指向这个plane;

一个双声道的音频帧有左声道L和右声道R, 它们交织存储在一个plane中, 例如: LRLRLR... ..., data[0]指向这个plane.

对于planar格式, 一个YUV图像有Y, U, V三个plane, data[0]指向Y plane, data[1]质量U plane, data[2]指向V plane.

一个双声道的音频帧有左声道L和右声道R两个plane, data[0]指向L plane, data[1]指向R plane

 

  • int linesize[AV_NUM_DATA_POINTERS];

对于视频来说, linesize是每行图像的大小(字节数, 有字节对齐).

对于音频来说, linesize是每个plane的大小(字节数). 音频只是用linesize[0]. 对于planar音频来说, 每个plane的大小必须一样.

linesize可能会因为性能上的考虑而填充一些额外的数据, 因此linesize可能比实际对应的音视频数据尺寸要大.

 

  • uint8_t **extended_data;

  指向数据plane

 

 

  • int width, height;

视频帧像素宽和高.

 

  • int nb_samples;

音频帧中单个声道包含的采样点数.

 

  • int format;

帧格式. 如果是未知格式或未设置, 值为-1.

对于视频帧, 值对应enum AVPixelFormat结构:

1 enum AVPixelFormat {
2     AV_PIX_FMT_NONE = -1,
3     AV_PIX_FMT_YUV420P,   ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
4     AV_PIX_FMT_YUYV422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
5     AV_PIX_FMT_RGB24,     ///< packed RGB 8:8:8, 24bpp, RGBRGB...
6     AV_PIX_FMT_BGR24,     ///< packed RGB 8:8:8, 24bpp, BGRBGR...
7     AV_PIX_FMT_YUV422P,   ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
8     AV_PIX_FMT_YUV444P,   ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
... ...
};

 

对于音频帧, 值对应于enum AVSampleFormat结构:

 1 enum AVSampleFormat {
 2     AV_SAMPLE_FMT_NONE = -1,
 3     AV_SAMPLE_FMT_U8,          ///< unsigned 8 bits
 4     AV_SAMPLE_FMT_S16,         ///< signed 16 bits
 5     AV_SAMPLE_FMT_S32,         ///< signed 32 bits
 6     AV_SAMPLE_FMT_FLT,         ///< float
 7     AV_SAMPLE_FMT_DBL,         ///< double
 8 
 9     AV_SAMPLE_FMT_U8P,         ///< unsigned 8 bits, planar
10     AV_SAMPLE_FMT_S16P,        ///< signed 16 bits, planar
11     AV_SAMPLE_FMT_S32P,        ///< signed 32 bits, planar
12     AV_SAMPLE_FMT_FLTP,        ///< float, planar
13     AV_SAMPLE_FMT_DBLP,        ///< double, planar
14     AV_SAMPLE_FMT_S64,         ///< signed 64 bits
15     AV_SAMPLE_FMT_S64P,        ///< signed 64 bits, planar
16 
17     AV_SAMPLE_FMT_NB           ///< Number of sample formats. DO NOT USE if linking dynamically
18 };

 

 

  • int key_frame;

视频帧是否是关键帧的标识, 1: 关键帧; 0: 非关键帧.

 

  • enum AVPictureType pict_type;

视频帧类型(I, B, P等)

enum AVPictureType结构:

 1 enum AVPictureType {
 2     AV_PICTURE_TYPE_NONE = 0, ///< Undefined
 3     AV_PICTURE_TYPE_I,     ///< Intra
 4     AV_PICTURE_TYPE_P,     ///< Predicted
 5     AV_PICTURE_TYPE_B,     ///< Bi-dir predicted
 6     AV_PICTURE_TYPE_S,     ///< S(GMC)-VOP MPEG-4
 7     AV_PICTURE_TYPE_SI,    ///< Switching Intra
 8     AV_PICTURE_TYPE_SP,    ///< Switching Predicted
 9     AV_PICTURE_TYPE_BI,    ///< BI type
10 };

 

 

  • AVRational sample_aspect_ratio;

视频帧的宽高比.

 

  • int64_t pts;

显示时间戳. 单位是time_base.

 

  • int64_t pkt_dts;

对应packet中的解码时间戳. 是从对应pacekt中拷贝得到此值.

如果对应的packet中只有dts而未设置pts, 则此值也是frame的pts.

 

  • int coded_picture_number;

编码帧序号.

 

  • int display_picture_number;

显示帧序号

 

  • int quality;

品质(介于1(最好)和FF_LAMBDA_MAX(坏)之间)

 

  • void *opaque;

用户私有信息.

 

  • int repeat_pict;

解码时, 每帧图片的延迟时间.

extra_delay = repeat_pict / (2*fps)

 

  • int interlaced_frame;

是否是隔行扫描.

 

  • int top_field_first;

图像的top field first变量. 如果内容是隔行的, 则首先显示顶部字段.

 

  • int palette_has_changed;

告诉用户应用程序调色板已从上一帧更改

 

  • int sample_rate;

音频采样率.

 

  • uint64_t channel_layout;

音频声道布局. 每bit代表一个特定的声道.

参考源码channel_layout.h中定义: 

 1 #define AV_CH_FRONT_LEFT             0x00000001
 2 #define AV_CH_FRONT_RIGHT            0x00000002
 3 #define AV_CH_FRONT_CENTER           0x00000004
 4 #define AV_CH_LOW_FREQUENCY          0x00000008
 5 #define AV_CH_BACK_LEFT              0x00000010
 6 ...   ...
 7 
 8 #define AV_CH_LAYOUT_MONO              (AV_CH_FRONT_CENTER)
 9 #define AV_CH_LAYOUT_STEREO            (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT)
10 #define AV_CH_LAYOUT_2POINT1           (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY)
11 #define AV_CH_LAYOUT_2_1               (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER)
12 #define AV_CH_LAYOUT_SURROUND          (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER)
13 #define AV_CH_LAYOUT_3POINT1           (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY)
14 ...   ...

 

 

 

  • AVBufferRef *buf[AV_NUM_DATA_POINTERS];

此帧的数据可以由AVBufferRef管理, AVBufferRef提供AVBuffer引用机制.

如果buf[]的所有元素都为NULL, 则此帧不会被引用计数.

必须连续填充buf[], 如果buf[i]为非NULL, 则对所有的j < i, 也必须有b[j]必须为非NULL.

对于视频来说, buf[]包含所有的AVBufferRef指针.

对于具有多于AV_NUM_DATA_POINTERS个声道的planar音频来说, 可能buf[]存不下所有的AVBufferRef指针, 多出的AVBufferRef指针存储在extended_buf数组中.

 

  • AVBufferRef **extended_buf;

对于具有多于AV_NUM_DATA_POINTERS个声道的planar音频来说, 可能buf[]存不下所有的AVBufferRef指针, 多出的AVBufferRef指针存储在extended_buf数组中.

 

  • int nb_extended_buf;

extended_buf中元素的数目.

 

  • AVFrameSideData **side_data;

边缘数据

 

  • int nb_side_data;

边缘数据的数目

 

  • int64_t best_effort_timestamp;

在流时间基中估计帧时间戳.

编码时未使用

解码时由解码器设置. 用户读取.

 

  • int64_t pkt_pos;

记录最后一个扔进解码器的packet在输入文件中的位置偏移量.

 

  • int64_t pkt_duration;

对应packet的时长, 单位是AVStream->time_base.

 

  • int channels;

音频声道数量.

 

  • int pkt_size;

对应packet的大小.

 

 

size_t crop_top;
size_t crop_bottom;
size_t crop_left;
size_t crop_right;

用于视频帧图像裁切. 四个值分别为从frame的上/下/左/右边界裁切的像素数.

 
  • 这写成员暂时没有找到完美的解释(可能也不是很重要或不太常用)

int flags;

enum AVColorRange color_range;

enum AVColorPrimaries color_primaries;

enum AVColorTransferCharacteristic color_trc;

enum AVColorSpace colorspace;

enum AVChromaLocation chroma_location;

AVDictionary *metadata;

int decode_error_flags;

AVBufferRef *hw_frames_ctx;

AVBufferRef *opaque_ref;

 

2. 相关函数 

  • AVFrame *av_frame_alloc(void);

构造一个AVFrame, 对象成员被设为默认值.

此函数只分配AVFrame对象本身, 而不分配AVFrame中的数据缓存区.

 

  • void av_frame_free(AVFrame **frame);

释放AVFrame.

 

  • int av_frame_ref(AVFrame *dst, const AVFrame *src);

为src中的数据建立一个新的引用.

将src中帧的各属性拷到dst中, 并且为src中每个AVBufferRef创建一个新的引用.

如果src未使用引用计数, 则dst中会分配新的数据缓存区, 将src中缓存区的数据拷贝到dst中的缓存区.

 

  • AVFrame *av_frame_clone(const AVFrame *src);

创建一个新的AVFrame, 新的AVFrame和src使用统一数据缓存区, 缓存区管理使用引用计数机制.

 

  • void av_frame_unref(AVFrame *frame);

解除本AVFrame对AVFrame中所有缓存区的引用, 并复位AVFrame中的各成员.

 

  • void av_frame_move_ref(AVFrame *dst, AVFrame *src);

将src中所有数据拷贝到dst中, 并复位src.

为避免内存泄漏, 在调用av_frame_move_ref(dst, src)之前应先调用av_frame_unref(dst);

 

  • int av_frame_get_buffer(AVFrame *frame, int align); 

为音频或视频数据分配新的缓冲区.

调用本函数前, 帧中的以下成员必须先设置好:

    • format
    • width, height
    • nb_samples, channel_layout

本函数会填充AVFrame.data和AVFrame.buf数组, 如果有需要, 还会分配和填充AVFrame.extended_data和AVFrame.extended_buf.

对于planar格式, 回味每个plane分配一个缓冲区.

 

  • int av_frame_copy(AVFrame *dst, const AVFrame *src);

将src中的帧数据拷贝到dst中.

本函数并不会有任何分配缓冲区的动作, 调用此函数前dst必须已经使用了和src同样的参数完成了初始化.

本函数只拷贝帧中的数据缓冲区的内容, 而不涉及帧中的其它属性.

 

参考

[1] 雷霄骅博士结构体分析:AVFrame  https://blog.csdn.net/leixiaohua1020/article/details/14214577

[2] 叶余 FFmpeg数据结构AVFrame https://www.cnblogs.com/leisure_chn/p/10404502.html

[3]YelloLayne FFmpeg结构体:AVFrame https://www.jianshu.com/p/25a329b20078

 

上一篇:ffmepg AVFrame用法


下一篇:FFmpeg数据结构AVFrame