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 ...
随机推荐
- 常用css模板
段落超出显示省略号(可单行多行) .p-content{ overflow:hidden; text-overflow:ellipsis; display:-webkit-box; -webkit-b ...
- PIMPL(private implementantion)模式(转载)
前记:请搜索PIMPL(private implementantion)模式和桥接模式, PIMPL是桥接模式的一种典型实现 以下转自:http://blog.csdn.net/nrc_douning ...
- Flutter移动电商实战 --(8)dio基础_伪造请求头获取数据
在很多时候,后端为了安全都会有一些请求头的限制,只有请求头对了,才能正确返回数据.这虽然限制了一些人恶意请求数据,但是对于我们聪明的程序员来说,就是形同虚设.这篇文章就以极客时间 为例,讲一下通过伪造 ...
- 实体类(VO,DO,DTO)的划分
实体类(VO,DO,DTO)的划分 (2011-12-21 15:50:27) 转载▼ 标签: it 经常会接触到VO,DO,DTO的概念,本文从领域建模中的实体划分和项目中的实际应用情况两个角度 ...
- 对每个CheckBox的循环
$("input[name='ck2']").each(function(){ if(this.checked == false){ $(this).parent().parent ...
- 让 Nginx 支持 WAF 防护功能实战
ngx_lua_waf 安装说明文档 作者github地址: https://github.com/loveshell/ngx_lua_waf ———————————————————————————— ...
- CentOS 7 最小化安装后的注意事项
http://blog.csdn.net/f_srion/article/details/54910943 在VM虚拟机中安装CentOS 7 时 有时候顾虑到电脑硬件性能,我们需要最小化安装,而最小 ...
- Qt编写自定义控件16-魔法老鼠
前言 五一期间一直忙着大屏电子看板软件的开发,没有再去整理控件,今天已经将大屏电子看板的所有子窗口都实现了任意停靠和双击独立再次双击最大化等功能,过阵子有空再写一篇文章介绍其中的技术点.魔法老鼠控件, ...
- Java泛型(1):概述
通常而言,我们使用一种容器来存储一种类型的对象.而泛型的主要目的之一就是用来指定这个容器要持有什么类型的对象.因此,与其使用Object,我们可以暂时不指定类型. 看下面3个例子: (1) 我们有时候 ...
- ELK故障处理,不知道成功否
上周?还是上上周??发现ELK的数据都没有更新了,考虑到这个系统目前不重要,就没有理会.今日再次登陆,发现没有数据更新了!!! system overview 没有主机,没有数据. 登陆系统检查状态, ...