0. 简介

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

1. AVFrame 数据结构定义

FFmpeg 版本3.4.1

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

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

   typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8 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; #if FF_API_PKT_PTS attribute_deprecated
int64_t pkt_pts;
#endif int64_t pkt_dts; int coded_picture_number; int display_picture_number; int quality; void *opaque; #if FF_API_ERROR_FRAME attribute_deprecated
uint64_t error[AV_NUM_DATA_POINTERS];
#endif int repeat_pict; int interlaced_frame; int top_field_first; int palette_has_changed; int64_t reordered_opaque; int sample_rate; uint64_t channel_layout; AVBufferRef *buf[AV_NUM_DATA_POINTERS]; AVBufferRef **extended_buf; int nb_extended_buf; AVFrameSideData **side_data;
int nb_side_data; #define AV_FRAME_FLAG_CORRUPT (1 << 0) #define AV_FRAME_FLAG_DISCARD (1 << 2) int flags; enum AVColorRange color_range; enum AVColorPrimaries color_primaries; enum AVColorTransferCharacteristic color_trc; enum AVColorSpace colorspace; enum AVChromaLocation chroma_location; int64_t best_effort_timestamp; int64_t pkt_pos; int64_t pkt_duration; AVDictionary *metadata; int decode_error_flags;
#define FF_DECODE_ERROR_INVALID_BITSTREAM 1
#define FF_DECODE_ERROR_MISSING_REFERENCE 2 int channels; int pkt_size; #if FF_API_FRAME_QP
attribute_deprecated
int8_t *qscale_table; attribute_deprecated
int qstride; attribute_deprecated
int qscale_type; AVBufferRef *qp_table_buf;
#endif AVBufferRef *hw_frames_ctx; AVBufferRef *opaque_ref; size_t crop_top;
size_t crop_bottom;
size_t crop_left;
size_t crop_right;
} 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结构:

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

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

 enum AVSampleFormat {
AV_SAMPLE_FMT_NONE = -,
AV_SAMPLE_FMT_U8, ///< unsigned 8 bits
AV_SAMPLE_FMT_S16, ///< signed 16 bits
AV_SAMPLE_FMT_S32, ///< signed 32 bits
AV_SAMPLE_FMT_FLT, ///< float
AV_SAMPLE_FMT_DBL, ///< double AV_SAMPLE_FMT_U8P, ///< unsigned 8 bits, planar
AV_SAMPLE_FMT_S16P, ///< signed 16 bits, planar
AV_SAMPLE_FMT_S32P, ///< signed 32 bits, planar
AV_SAMPLE_FMT_FLTP, ///< float, planar
AV_SAMPLE_FMT_DBLP, ///< double, planar
AV_SAMPLE_FMT_S64, ///< signed 64 bits
AV_SAMPLE_FMT_S64P, ///< signed 64 bits, planar AV_SAMPLE_FMT_NB ///< Number of sample formats. DO NOT USE if linking dynamically
};
  • int key_frame;

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

  • enum AVPictureType pict_type;

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

enum AVPictureType结构:

 enum AVPictureType {
AV_PICTURE_TYPE_NONE = , ///< Undefined
AV_PICTURE_TYPE_I, ///< Intra
AV_PICTURE_TYPE_P, ///< Predicted
AV_PICTURE_TYPE_B, ///< Bi-dir predicted
AV_PICTURE_TYPE_S, ///< S(GMC)-VOP MPEG-4
AV_PICTURE_TYPE_SI, ///< Switching Intra
AV_PICTURE_TYPE_SP, ///< Switching Predicted
AV_PICTURE_TYPE_BI, ///< BI type
};
  • 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中定义:

 #define AV_CH_FRONT_LEFT             0x00000001
#define AV_CH_FRONT_RIGHT 0x00000002
#define AV_CH_FRONT_CENTER 0x00000004
#define AV_CH_LOW_FREQUENCY 0x00000008
#define AV_CH_BACK_LEFT 0x00000010
... ... #define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER)
#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT)
#define AV_CH_LAYOUT_2POINT1 (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY)
#define AV_CH_LAYOUT_2_1 (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER)
#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER)
#define AV_CH_LAYOUT_3POINT1 (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY)
... ...
  • 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

ffmpeg AVFrame结构体及其相关函数的更多相关文章

  1. ffmpeg AVPacket结构体及其相关函数

    0. 简介 AVPacket结构体并不是很复杂, 但是在ffmpeg中用的非常多. 与其相关的函数也是比较多. AVPacket保存了解复用之后, 解码之前的数据, 和这些数据相关的一些附加信息. 对 ...

  2. FFmpeg 常用结构体

    0.FFmpeg 中最关键的结构体之间的关系 FFmpeg 中结构体很多.最关键的结构体可以分成以下几类: 1)解协议(http, rtsp, rtmp, mms) AVIOContext,URLPr ...

  3. Linux中表示“时间”的结构体和相关函数

    转载于:http://blog.chinaunix.net/uid-25909722-id-2827364.html      Linux中表示“时间”的结构体和相关函数 2011-09-13 17: ...

  4. FFmpeg: AVPacket 结构体分析

    AVPacket是FFmpeg中很重要的一个数据结构,它保存了解封装之后,解码之前的数据(注意:仍然是压缩后的数据)和关于这些数据的一些附加信息,如显示时间戳(pts).解码时间戳(dts).数据时长 ...

  5. FFmpeg: AVFormatContext 结构体分析

    AVFormatContext 结构体分析这个结构体描述了一个媒体文件或媒体流的构成和基本信息.这是FFMpeg中最为基本的一个结构,是其他所有结构的根,是一个多媒体文件或流的根本抽象.主要成员释义: ...

  6. cdev结构体及其相关函数

    一.在Linux2.6内核中一个字符设备用cdev结构来描述,其定义如下: struct cdev { struct kobject kobj; struct module *owner; //所属模 ...

  7. FFmpeg: AVCodecParameters 结构体分析

    /** * This struct describes the properties of an encoded stream. * * sizeof(AVCodecParameters) is no ...

  8. FFmpeg源代码简单分析:常见结构体的初始化和销毁(AVFormatContext,AVFrame等)

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  9. FFMPEG结构体分析:AVFrame(解码后的数据)

    https://blog.csdn.net/jxcr1984/article/details/52766524 本文转自: http://blog.csdn.net/leixiaohua1020/ar ...

随机推荐

  1. GC 老年代 新生代

    参考资料: http://blog.csdn.net/flamezyg/article/details/44673951 http://www.blogjava.net/ldwblog/archive ...

  2. 数据结构实验之链表八:Farey序列(SDUT 3331)

    #include <bits/stdc++.h> using namespace std; typedef struct node { int data2; int data1;//mu ...

  3. P2089 烤鸡

    题目背景 猪猪hanke得到了一只鸡 题目描述 猪猪Hanke特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke吃鸡很特别,为什么特别呢?因为他有10种配料(芥末.孜然等),每种配料可以放1—3克, ...

  4. oracle面试题2

    1.题目要求 为管理岗位业务培训信息,建立3个表:S (S#,SN,SD,SA) S#,SN,SD,SA 分别代表学号.学员姓名.所属单位.学员年龄C (C#,CN ) C#,CN 分别代表课程编号. ...

  5. CodeForces 631D Messenger —— (kmp的应用)

    这题是一个kmp的应用,思路是有,但是代码实现能力太弱,细节考虑不全,敲了很长时间才AC.. 题意:字符串用如下的方法表示,例如aaabbbbcc表示为3-a,4-b,2-c.那么问t串在s串中出现了 ...

  6. RSA加密算法c++简单实现

    RSA是一种非对称加密算法,在公开密钥和电子商业中RSA被广泛使用.它是基于一个很简单的数论事实,两个素数相乘很容易,对两素数乘积因式分解很困难.原理就不再阐述了,我谈谈算法的编程实现过程. 一.RS ...

  7. 转载:在Excel中将数据库字段转换成驼峰式

    转载地址 在Excel中将数据库字段转换成驼峰式 1.将数据库字段复制到Excel表格第一列: 2.在第二列顶部输入=PROPER(A1)命令: 3.在第三列顶部输入=SUBSTITUTE(B1,&q ...

  8. jsp页面,使用Struts2标签,传递和获取Action类里的参数,注意事项。<s:a action><s:iterator><s:param>ognl表达式

    在编写SSH2项目的时候,除了使用<s:form>表单标签向Action类跳转并传递参数之外,很更多时候还需要用到<s:a action="XXX.action" ...

  9. Nginx数据结构之散列表

    1. 散列表(即哈希表概念) 散列表是根据元素的关键码值而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录, 以加快查找速度.这个映射函数 f 叫做散列方法,存放记录的数 ...

  10. ELK(elasticsearch+logstash+kibana)入门到熟练-从0开始搭建日志分析系统教程

    #此文篇幅较长,涵盖了elk从搭建到运行的知识,看此文档,你需要会点linux,还要看得懂点正则表达式,还有一个聪明的大脑,如果你没有漏掉步骤的话,还搭建不起来elk,你来打我. ELK使用elast ...