4.FFMPEG-AVFrame
在ffmpeg中,解码前的数据结构体为AVPacket(参考:3.AVPacket使用),而解码后的数据为AVFrame(视频的YUV, RGB, 音频的PCM,数据量更大)
1.AVFrame介绍
- AVFrame必须使用av_frame_alloc()来分配。注意,这只是分配AVFrame本身,缓冲区的数据(解码成功后的数据)必须通过其他途径被管理.
- 因为AVFrame通常只分配一次,然后多次复用来保存不同类型的数据,复用的时候需要调用av_frame_unref()将其重置到它前面的原始清洁状态.
- 注意调用avcodec_receive_frame()时会自动引用减1后再获取frame,所以解码过程中无需每次调用
- 释放的时候必须用av_frame_free()释放。
2.常用函数使用
AVFrame *av_frame_alloc(void);
// 初始化
void av_frame_unref(AVFrame *frame);
//引用减1.若为0则释放缓冲区数据,注意调用avcodec_receive_frame()时会自动引用减1后再获取frame,所以解码过程中无需每次调用
void av_frame_free(AVFrame **frame);
//释放frame本身
av_frame_ref(AVFrame *dst, const AVFrame *src);
//从src复制到一个初始化好的dst中,并引用+1
av_frame_clone(const AVFrame *src);
//创建并返回一个复制好的AVPacket(在音视频同步处理中用到该函数) //获取frame相关函数
int avcodec_send_packet(pCodecCtx, pPacket);
//发送要解码的数据到解码队列中,并引用+1.返回0表示发送成功 int avcodec_receive_frame(pCodecCtx, pFrame);
//从解码队列中获取一帧AVFrame,并且获取的AVFrame是已经通过pts排列好的数据,返回0表示获取成功
注意事项:
由于DTS和PTS的顺序可能是不一致的.所以每次视频解码完成后,可能还有几帧frame未显示,
我们需要在末尾通过avcodec_send_packet()传入NULL来将最后几帧取出来
2.AVFrame结构体
AVFrame结构体中有很多成员,常见的成员如下所示,注释已替换:
typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8
uint8_t *data[AV_NUM_DATA_POINTERS];
//存储原始帧数据(视频的YUV, RGB, 音频的PCM),数组的每一个元素是一个指针,指向了AVBufferRef *buf中的data
//对于packet格式,都存在data[0]中,比如yuv,data[0]中就存的是yuvyuvyuv...,pcm则是lrlrlrlr...
//对于planar格式,则是分开存储,比如yuv,data[0]存y,data[1]存u,data[2]存v,pcm则是data[0]存L,data[1]存R
int linesize[AV_NUM_DATA_POINTERS];
//对于视频,linesize是每个图像的一行(宽)数据大小(字节数)。注意有对齐要求(16或32对齐)
//对于音频,则是每个data[]通道里的字节大小,并且每个通道(一般就两通道:L和R)的字节数相同
uint8_t **extended_data;
//extended_data:*extended_data始终等于data[0]里的成员。
//之所以取名为extended_data,是因为data[]最大只能8个通道.
//比如planar格式的pcm的通道数超过了8个,那么就只能使用extended_data来获取数据.
int width, height;
//视频帧的尺寸(以像素为单位)
//用户可以通过if (frame->width > 0 && frame->height > 0)来判断是否为视频流
int nb_samples;
//音频帧的单通道样本数据数量(不是以字节为单位,以单个音频数据为单位)
//比如frame的linesize[0]=8192,LR双通道,format为float planar格式(4字节),那么nb_samples=8192/2/4=1024
int format;
//帧的格式,如果未知或未设置为-1
//对于视频帧,参考AVPixelFormat枚举值,比如:AV_PIX_FMT_YUV420P
//对于音频帧,参考AVSampleFormat枚举值,比如:AV_SAMPLE_FMT_U8
int key_frame;
//是否为一幅完整的画面,关键帧(I帧)的标识
//1->关键帧,0->非关键帧
enum AVPictureType pict_type;
//视频帧类型(I、B、P等),比如:AV_PICTURE_TYPE_I(I帧)
//I帧:一幅完整的画面
//B帧:参考前面和后面两帧的数据加上本帧的变化而得出的本帧数据
//P帧:参考前面而得出的本帧数据.
//如果I帧不完整,那么整个GOP(Group of Picture)都是花屏的.
/**
* Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
*/
AVRational sample_aspect_ratio;
//像素的宽高比,通过av_q2d()来获取值,如果未知/未指定,为0/1。
/**
* Presentation timestamp in time_base units (time when frame should be shown to user).
*/
int64_t pts;
//显示时间戳,表示当前为第几帧,如果要换算为时分秒,则需要AVStream的time_base时基来一起换算
//比如:
//int timeVal=av_q2d(pFormatCtx->streams[videoindex]->time_base) * pFrame->pts*100;
//int hour = timeVal/360000;
//int minute = timeVal%360000/6000;
//int second = timeVal%6000/100;
//int msec = timeVal%100*10;
#if FF_API_PKT_PTS
/**
* PTS copied from the AVPacket that was decoded to produce this frame.
* @deprecated use the pts field instead
*/
int64_t pkt_pts; //使用pts字段代替(pts=pkt_pts)
#endif
int64_t pkt_dts;
//pkt_dts:解码时间戳,等于AVPacket的dts,如果AVPacket只有dts而未设置pts,此值也是此frame的pts
//比如mjpeg格式的视频,就只有I帧,不需要对pts进行排序,所以dts和pts值一样
int coded_picture_number;
//编码顺序的图像
int display_picture_number;
//播放顺序的图像
/**
* quality (between 1 (good) and FF_LAMBDA_MAX (bad))
*/
int quality;
//视频质量,值越小越好
int repeat_pict;
//当解码时,这表示图片必须延迟多少.extra_delay = repeat_pict / (2*fps)
int interlaced_frame;
//图像逐行/隔行模式标识。
int top_field_first;
//如果内容是隔行模式扫描,则首先显示顶部字段。
int palette_has_changed;
//用来告诉应用程序,调色板已从前一帧更改。
int64_t reordered_opaque;
//重新排序的不透明64位(通常是整数或双精度浮点PTS,但可以是任何东西)。
int sample_rate;
//音频数据的采样率。
uint64_t channel_layout;
//音频数据的通道布局,参考channel_layout.h
//比如AV_CH_FRONT_LEFT:表示前左声道
/**
* AVBuffer references backing the data for this frame. If all elements of
* this array are NULL, then this frame is not reference counted. This array
* must be filled contiguously -- if buf[i] is non-NULL then buf[j] must
* also be non-NULL for all j < i.
*
* There may be at most one AVBuffer per data plane, so for video this array
* always contains all the references. For planar audio with more than
* AV_NUM_DATA_POINTERS channels, there may be more buffers than can fit in
* this array. Then the extra AVBufferRef pointers are stored in the
* extended_buf array.
*/
AVBufferRef *buf[AV_NUM_DATA_POINTERS];
//通过引用计数,使该AVBufferRef来间接使用AVBuffer缓冲区,也就是data[]指向的原始数据.
//用户不应直接使用data成员,应通过buf成员间接使用data成员
//如果buf[]的所有元素都为NULL,则此帧不会被引用计数。必须连续填充buf[] - 如果buf[i]为非NULL,则对于所有j<i,buf[j]也必须为非NULL
AVBufferRef **extended_buf;
int nb_extended_buf;
//和extended_data类似,因为buf最多存储8通道.
//extended_buf和AVFrame.extended_data唯一不同在于:extended_data包含所有指向各plane的指针,而extended_buf只包含buf中装不下的指针。
AVFrameSideData **side_data;
int nb_side_data;
//边缘数据和数目
/**
* @defgroup lavu_frame_flags AV_FRAME_FLAGS
* @ingroup lavu_frame
* Flags describing additional frame properties.
*
* @{
*/
#define AV_FRAME_FLAG_CORRUPT (1 << 0)
//标记需要解码但不应该输出的帧的标志。帧数据可能被损坏,例如由于解码错误
#define AV_FRAME_FLAG_DISCARD (1 << 2)
//标记需要解码但不应该输出的帧的标志。
int flags; //编解码失败后,用户可以通过该flag查看是否为AV_FRAME_FLAG_CORRUPT或者AV_FRAME_FLAG_DISCARD
enum AVColorRange color_range; //图像的编码格式(MPEG/JPEG),解码时,由库设置,编码时,由用户来设置
enum AVColorPrimaries color_primaries; //图像源初选的色度坐标
enum AVColorTransferCharacteristic color_trc; //图像颜色传输特性
/**
* YUV colorspace type.
* - encoding: Set by user
* - decoding: Set by libavcodec
*/
enum AVColorSpace colorspace;
//图像彩色空间类型,解码时,由库设置,编码时,由用户来设置
//比如等于AVCOL_SPC_RGB时,那么color_trc等于AVCOL_TRC_IEC61966_2_1
enum AVChromaLocation chroma_location;
//储存的颜色色度样品的位置
/**
* reordered pos from the last AVPacket that has been input into the decoder
* - encoding: unused
* - decoding: Read by user.
*/
int64_t pkt_pos;
//标记最后一个解码的packet在输入文件中的位置偏移量。
int64_t pkt_duration;
//该帧的持续时间,需要通过AVStream的time_base时基来换算
/**
* metadata.
* - encoding: Set by user.
* - decoding: Set by libavcodec.
*/
AVDictionary *metadata;
int decode_error_flags; //解码帧的错误标志
#define FF_DECODE_ERROR_INVALID_BITSTREAM 1
#define FF_DECODE_ERROR_MISSING_REFERENCE 2
#define FF_DECODE_ERROR_CONCEALMENT_ACTIVE 4
#define FF_DECODE_ERROR_DECODE_SLICES 8
int channels;
//音频通道数量,仅用于音频
//用户可以通过 if (frame->nb_samples > 0 && (frame->channel_layout || frame->channels > 0))来判断该frame是否为音频
int pkt_size;
//压缩帧的相应数据包的大小。
size_t crop_top;
size_t crop_bottom;
size_t crop_left;
size_t crop_right;
//用于裁剪视频帧图像用的。四个值分别为从frame的上/下/左/右边界裁切的像素数。
//...
}AVFrame;
4.FFMPEG-AVFrame的更多相关文章
- ffmpeg AVFrame结构体及其相关函数
0. 简介 AVFrame中存储的是原始数据(例如视频的YUV, RGB, 音频的PCM), 此外还包含了一些相关的信息, 例如: 解码的时候存储了宏块类型表, QP表, 运动矢量等数据. 编码的时候 ...
- FFmpeg——AVFrame中 的 data
AVFrame中 的 data 的定义如下: typedef struct AVFrame { #define AV_NUM_DATA_POINTERS 8 /** * pointer to the ...
- 在iOS平台使用ffmpeg解码h264视频流(转)
在iOS平台使用ffmpeg解码h264视频流,有需要的朋友可以参考下. 对于视频文件和rtsp之类的主流视频传输协议,ffmpeg提供avformat_open_input接口,直接将文件路径或UR ...
- 在iOS平台使用ffmpeg解码h264视频流
来源:http://www.aichengxu.com/view/37145 在iOS平台使用ffmpeg解码h264视频流,有需要的朋友可以参考下. 对于视频文件和rtsp之类的主流视频传输协议,f ...
- ffmpeg从AVFrame取出yuv数据到保存到char*中
ffmpeg从AVFrame取出yuv数据到保存到char*中 很多人一直不知道怎么利用ffmpeg从AVFrame取出yuv数据到保存到char*中,下面代码将yuv420p和yuv422p的数 ...
- ffmpeg中avframe的YUV格式数据到OpenCV中Mat的BGR格式转换
ffmpeg实现音视频编解码是非常常用的工具,视频解码出来的raw数据是yuv格式,用来进行后续的图像处理一般是RGB格式的.所以需要从yuv到rgb或者bgr的转换,ffmpeg提供了相应的转换AP ...
- FFmpeg源代码简单分析:常见结构体的初始化和销毁(AVFormatContext,AVFrame等)
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- FFMPEG结构体分析:AVFrame
注:写了一系列的结构体的分析的文章,在这里列一个列表: FFMPEG结构体分析:AVFrameFFMPEG结构体分析:AVFormatContextFFMPEG结构体分析:AVCodecContext ...
- FFmpeg 结构体学习(四): AVFrame 分析
在上文FFmpeg 结构体学习(三): AVPacket 分析我们学习了AVPacket结构体的相关内容.本文,我们将讲述一下AVFrame. AVFrame是包含码流参数较多的结构体.下面我们来分析 ...
- FFmpeg数据结构AVFrame
本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10404502.html 本文基于FFmpeg 4.1版本. 1. 数据结构定义 stru ...
随机推荐
- AI顶会
自己如何学习CV paper with code(每周) 基石方向 1.image classification 这个肯定要关注,这个往往都是backbone https://paperswithco ...
- XCTF-WEB-高手进阶区-Web_python_template_injection-笔记
Web_python_template_injection o(╥﹏╥)o从这里开始题目就变得有点诡谲了 网上搜索相关教程的确是一知半解,大概参考了如下和最后的WP: http://shaobaoba ...
- java 的API及Object类
一 Java的API Java 的API(API: Application(应用) Programming(程序) Interface(接口)) Java API就是JDK中提供给我们使用的类,这些类 ...
- 2020-06-27:ACID是什么?描述一下?
福哥答案2020-06-27: 福哥口诀法:事原一隔持(事务属性ACID:原子性.一致性.隔离性.持久性) 用银行数据库来举例子解释一下这四个特性 原子性: 一个事务可能会包含多种操作,比如转账操作包 ...
- C#开发笔记之04-如何用C#优雅的计算个人所得税?
C#开发笔记概述 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/960 访问. 首先,要对个人所得税的计算方式了解之后再 ...
- 设计模式实战系列之@Builder和建造者模式
前言 备受争议的Lombok,有的人喜欢它让代码更整洁,有的人不喜欢它,巴拉巴拉一堆原因.在我看来Lombok唯一的缺点可能就是需要安装插件了,但是对于业务开发的项目来说,它的优点远远超过缺点. 我们 ...
- js获取当前地址信息
var url = window.location.href; //获取当前窗口的Url; 结果:http://localhost:61768/Home/Index?id=2&age=18 v ...
- ES6系列之项目中常用的新特性
ES6系列之项目中常用的新特性 ES6常用特性 平时项目开发中灵活运用ES6+语法可以让开发者减少很多开发时间,提高工作效率.ES6版本提供了很多新的特性,接下来我列举项目中常用的ES6+的特性: l ...
- CF 1383B GameGame
传送门 题目:给定长度为n的数组a,A和B轮流拿走一个数,开始时A和B拥有的v为0,A和B每次拿走一个数时,他的v = v^ ai,A和B都很聪明,问都按照最优的情况考虑,拿完所有数之后A和B的v的大 ...
- 【ZJOI2012】灾难 - LCA+拓扑排序
题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过生物的阿米巴告 ...