ffmpeg AVFrame结构体及其相关函数
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结构体及其相关函数的更多相关文章
- ffmpeg AVPacket结构体及其相关函数
		
0. 简介 AVPacket结构体并不是很复杂, 但是在ffmpeg中用的非常多. 与其相关的函数也是比较多. AVPacket保存了解复用之后, 解码之前的数据, 和这些数据相关的一些附加信息. 对 ...
 - FFmpeg 常用结构体
		
0.FFmpeg 中最关键的结构体之间的关系 FFmpeg 中结构体很多.最关键的结构体可以分成以下几类: 1)解协议(http, rtsp, rtmp, mms) AVIOContext,URLPr ...
 - Linux中表示“时间”的结构体和相关函数
		
转载于:http://blog.chinaunix.net/uid-25909722-id-2827364.html Linux中表示“时间”的结构体和相关函数 2011-09-13 17: ...
 - FFmpeg: AVPacket 结构体分析
		
AVPacket是FFmpeg中很重要的一个数据结构,它保存了解封装之后,解码之前的数据(注意:仍然是压缩后的数据)和关于这些数据的一些附加信息,如显示时间戳(pts).解码时间戳(dts).数据时长 ...
 - FFmpeg: AVFormatContext 结构体分析
		
AVFormatContext 结构体分析这个结构体描述了一个媒体文件或媒体流的构成和基本信息.这是FFMpeg中最为基本的一个结构,是其他所有结构的根,是一个多媒体文件或流的根本抽象.主要成员释义: ...
 - cdev结构体及其相关函数
		
一.在Linux2.6内核中一个字符设备用cdev结构来描述,其定义如下: struct cdev { struct kobject kobj; struct module *owner; //所属模 ...
 - FFmpeg: AVCodecParameters 结构体分析
		
/** * This struct describes the properties of an encoded stream. * * sizeof(AVCodecParameters) is no ...
 - FFmpeg源代码简单分析:常见结构体的初始化和销毁(AVFormatContext,AVFrame等)
		
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
 - FFMPEG结构体分析:AVFrame(解码后的数据)
		
https://blog.csdn.net/jxcr1984/article/details/52766524 本文转自: http://blog.csdn.net/leixiaohua1020/ar ...
 
随机推荐
- SpringMVC——参数传递
			
一.接收零散参数 1.装配原则为传递参数名和方法接收参数名一致 2.手动装配@RequestParam name代表页面发送的参数名字 required代表参数是否必须传递 false代表可以不 ...
 - deepin Linux 安装+工作学习配置
			
一 安装 在官网下载 U盘安装,神舟优雅x4开机按F7,选择U盘启动. U盘安装器在下载的镜像文件中. 二 配置 升级最新系统 设置root用户密码: dawn@dawn-PC:~$ sudo pas ...
 - C/C++程序基础-标准头文件的结构
			
1:标准头文件有如下结构,请解释. #ifndef _INCvxWorksh #define _INCvxWorksh#ifdef _cplusplus extern "C"{ # ...
 - 笔记一(固件、BIOS、UEFI)
			
1.固件 固件一般是指保存在ROM中的程序和数据,通过固件操作系统按照标准的设备驱动实现特定机器的运行. 简单来讲,固件就是固化在ROM的软件,当然也可以通过特定的工具进行升级. MP3.MP4.手机 ...
 - 性能分析 | JVM发生内存溢出的8种原因及解决办法
			
推荐阅读:史上最详细JVM与性能优化知识点综合整理 1.Java 堆空间 2.GC 开销超过限制 3.请求的数组大小超过虚拟机限制 4.Perm gen 空间 5.Metaspace 6.无法新建本机 ...
 - layer.js错误Uncaught TypeError: i is not a function
			
最初是要写一个管理后台来着,项目中需要用到弹出层,但是没有前端配合,我一个小PHP需要去写这玩意,怎么办呢?查了一些资料,发现layer对我来说还行,文档写的也比较完全,学习成本不高,就下决心用这个了 ...
 - vuex中的babel编译mapGetters/mapActions报错解决方法
			
vex使用...mapActions报错解决办法 vuex2增加了mapGetters和mapActions的方法,借助stage2的Object Rest Operator 所在通过 methods ...
 - rally测试opentack------安装部署和简单实践
			
1,下载 git clone git://git.openstack.org/openstack/rally 或者 git clone https://git.openstack.org/openst ...
 - smarty 第一条数据判断
			
<div class="shangpin_rightdiv2"> <p>颜色</p> <ul id="toggle"& ...
 - java中字符串左右补齐【转】
			
/** * 右左补齐 */ public static String padRight(String src, int len, char ch) { int diff = len - src.len ...