热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ffmpegAVFrame结构体及其相关函数

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

0. 简介

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

 

1. AVFrame 数据结构定义

FFmpeg 版本3.4.1

struct AVFrame 定义于

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

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, ///4 AV_PIX_FMT_YUYV422, ///5 AV_PIX_FMT_RGB24, ///6 AV_PIX_FMT_BGR24, ///7 AV_PIX_FMT_YUV422P, ///8 AV_PIX_FMT_YUV444P, /// ... ...
};

 

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

1 enum AVSampleFormat {
2 AV_SAMPLE_FMT_NOnE= -1,
3 AV_SAMPLE_FMT_U8, /// 4 AV_SAMPLE_FMT_S16, /// 5 AV_SAMPLE_FMT_S32, /// 6 AV_SAMPLE_FMT_FLT, /// 7 AV_SAMPLE_FMT_DBL, /// 8
9 AV_SAMPLE_FMT_U8P, ///10 AV_SAMPLE_FMT_S16P, ///11 AV_SAMPLE_FMT_S32P, ///12 AV_SAMPLE_FMT_FLTP, ///13 AV_SAMPLE_FMT_DBLP, ///14 AV_SAMPLE_FMT_S64, ///15 AV_SAMPLE_FMT_S64P, ///16
17 AV_SAMPLE_FMT_NB ///18 };

 

 


  • int key_frame;

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

 


  • enum AVPictureType pict_type;

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

enum AVPictureType结构:

1 enum AVPictureType {
2 AV_PICTURE_TYPE_NOnE= 0, /// 3 AV_PICTURE_TYPE_I, /// 4 AV_PICTURE_TYPE_P, /// 5 AV_PICTURE_TYPE_B, /// 6 AV_PICTURE_TYPE_S, /// 7 AV_PICTURE_TYPE_SI, /// 8 AV_PICTURE_TYPE_SP, /// 9 AV_PICTURE_TYPE_BI, ///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

对于视频来说, 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

 


推荐阅读
author-avatar
用巛户khm8pcnjp9
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有