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 ...
随机推荐
- elastic search&logstash&kibana 学习历程(三)Logstash使用场景和安装部署
Logstash基本介绍和使用场景 自我认为:logstash就是日志的采集收集,日志的搬运工,实时去采集日志.读取不同的数据源,并进行过滤,开发者自定义规范输出到目的地.日志的来源很多,如系统日志, ...
- AcWing:240. 食物链(扩展域并查集 or 带边权并查集)
动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形. A吃B, B吃C,C吃A. 现有N个动物,以1-N编号. 每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用 ...
- codeforces#1165 F2. Microtransactions (hard version) (二分+贪心)
题目链接: https://codeforces.com/contest/1165/problem/F2 题意: 需要买$n$种物品,每种物品$k_i$个,每个物品需要两个硬币 每天获得一个硬币 有$ ...
- Qt5.11.2 VS2015编译activemq发送程序 _ITERATOR_DEBUG_LEVEL错误和崩溃解决
1.问题描述: 运行环境是 win10 64位系统,开发环境是VS2015 ,Qt 5.11.2.开发activemq发送程序,遇到问题 (1)Qt5AxContainer.lib error LNK ...
- Elasticsearch删除数据之_delete_by_query
es参考版本:elasticsearch:5.5 _delete_by_query会删除所有query语句匹配上的文档,用法如下: curl -X POST "localhost:9200/ ...
- Go 通道(channel)与协程间通信
协程间通信 协程中可以使用共享变量来通信,但是很不提倡这样做,因为这种方式给所有的共享内存的多线程都带来了困难. 在 Go 中有一种特殊的类型,通道(channel),就像一个可以用于发送类型化数据的 ...
- 【Spring Boot】 Spring Boot 2.x 版本 CacheManager 配置方式
Spring Boot 1.X RedisCacheManager 配置方式 @Bean public CacheManager cacheManager(RedisTemplate redisTem ...
- css 能改变input type radio和checkbox 圆圈或方框的大小
把input隐藏,外面套label,再里面加个span,样式写在span上,让label覆盖在span上面,js去改active的class <label for="remember& ...
- easyUI之window窗口
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...
- kafka整合springboot
1.pom.xml添加依赖 <dependency> <groupId>org.springframework.kafka</groupId> <artifa ...