ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ffmpeg AVFrame结构体及其相关函数

2019-08-07 19:03:56  阅读:311  来源: 互联网

标签:CH ffmpeg int FMT AV AVFrame frame 函数


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

 

标签:CH,ffmpeg,int,FMT,AV,AVFrame,frame,函数
来源: https://www.cnblogs.com/changdingfang/p/11313139.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有