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 ...
随机推荐
- JetBrains IDE 基本快捷键
转载自:https://nextfe.com/jetbrains-ide-shortcuts/ 一个好的手艺人很熟悉他的工具.软件开发者也不例外.所以,在编程的过程中,值得了解一些键盘快捷键,以免因为 ...
- 「BZOJ 2653」middle「主席树」「二分」
题意 一个长度为\(n\)的序列\(a\),设其排过序之后为\(b\),其中位数定义为\(b[n/2]\),其中\(a,b\)从\(0\)开始标号,除法取下整.给你一个长度为\(n\)的序列\(s\) ...
- 「BZOJ 5161」最长上升子序列「状压DP」
题意 求一个\(1\sim n\)的排列LIS的期望长度,\(n\leq 28\) 题解 考虑朴素的LIS:\(f[i] = min(f[j]) + 1\) 记\(mx[i]\)为\(f\)的前缀最大 ...
- 刚注册blog,先来刷个存在
我想以后能够走数字ic设计的道路,努力复习考研,努力提升专业素养,2017加油!青春加油!
- 【java设计模式】-06原型模式
原型模式简述 定义: 使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象 ,也就是通过复制现有对象实例产生新的对象,也就是所谓的"克隆" 实现方式: 1.实现Cl ...
- centos6.9实现双网卡绑定
1.创建bond0文件 # vi /etc/sysconfig/network-scripts/ifcfg-bond0 DEVICE=bond0 NM_CONTROLLED=no #是否由networ ...
- spring boot通过自定义注解和AOP拦截指定的请求
一 准备工作 1.1 添加依赖 通过spring boot创建好工程后,添加如下依赖,不然工程中无法使用切面的注解,就无法对制定的方法进行拦截 <dependency> <group ...
- 10分钟梳理MySQL核心知识点
数据库的使用,是开发人员的基本功,对它掌握越清晰越深入,你能做的事情就越多. 做业务,要懂基本的SQL语句:做性能优化,要懂索引,懂引擎:做分库分表,要懂主从,懂读写分离... 今天我们用10分钟,重 ...
- 解决:安装jenkins时web界面出现jenkins实例似乎已离线问题
https://blog.51cto.com/8593714/2318144?tdsourcetag=s_pctim_aiomsg Windows下环境也可以解决:
- mapReduce的优化-combiner
mr的合成器,本质上就是reduce,在map端执行,称之为map端reduce,或者预聚合. 例子: job.setCombinerClass(WordCountCombiner.class);