0、FFmpeg 中最关键的结构体之间的关系

FFmpeg 中结构体很多。最关键的结构体可以分成以下几类:

1)解协议(http, rtsp, rtmp, mms)

AVIOContext,URLProtocol,URLContext 主要存储音视频使用的协议的类型以及状态。URLProtocol 存储输入音视频使用的封装格式。每种协议都对应一个 URLProtocol 结构。(注意:FFmpeg 中文件也被当做一种协议 “file”)

2)解封装(flv, avi, rmvb, mp4)

AVFormatContext 主要存储音视频封装格式中包含的信息;AVInputFormat 存储输入音视频使用的封装格式。每种音视频封装格式都对应一个 AVInputFormat 结构。

3)解码(h264, mpeg2, aac, mp3)

每个 AVStream 存储一个视频/音频流的相关数据;每个 AVStream 对应一个 AVCodecContext,存储该视频/音频流使用解码方式的相关数据;每个 AVCodecContext 中对应一个 AVCodec,包含该视频/音频对应的解码器。每种解码器都对应一个 AVCodec 结构。

4)存数据

视频的话,每个结构一般是存一帧;音频可能有好几帧。解码前数据:AVPacket;解码后数据:AVFrame。

它们之间的对应关系如下所示:

一、AVFrame

AVFrame 结构体一般用于存储原始数据(即非压缩数据,例如对视频来说是 YUV,RGB,对音频来说是 PCM),此外还包含了一些相关的信息。比如说,解码的时候存储了宏块类型表,QP 表,运动矢量表等数据。编码的时候也存储了相关的数据。因此在使用 FFmpeg 进行码流分析的时候,AVFrame 是一个很重要的结构体。

下面看几个主要变量的作用(在这里考虑解码的情况):

uint8_t *data[AV_NUM_DATA_POINTERS]; // 解码后原始数据(对视频来说是YUV,RGB,对音频来说是PCM)

int linesize[AV_NUM_DATA_POINTERS]; // data中“一行”数据的大小。注意:未必等于图像的宽,一般大于图像的宽。

int width, height; // 视频帧宽和高(1920x1080,1280x720...)

int nb_samples; // 音频的一个AVFrame中可能包含多个音频帧,在此标记包含了几个

int format; // 解码后原始数据类型(YUV420,YUV422,RGB24...)

int key_frame; // 是否是关键帧

enum AVPictureType pict_type; // 帧类型(I,B,P...)

AVRational sample_aspect_ratio; // 宽高比(16:9,4:3...)

int64_t pts; // 显示时间戳

int coded_picture_number; // 编码帧序号

int display_picture_number; // 显示帧序号

int8_t *qscale_table; // QP表

uint8_t *mbskip_table; // 跳过宏块表

int16_t (*motion_val[2])[2]; // 运动矢量表

uint32_t *mb_type; // 宏块类型表

short *dct_coeff; // DCT系数,这个没有提取过

int8_t *ref_index[2]; // 运动估计参考帧列表(貌似H.264这种比较新的标准才会涉及到多参考帧)

int interlaced_frame; // 是否是隔行扫描

uint8_t motion_subsample_log2; // 一个宏块中的运动矢量采样个数,取log的

如果想了解这些变量具体的含义,请看:FFMPEG结构体分析:AVFrame

二、AVFormatContext

AVFormatContext 是存储音视频封装格式中包含的信息的结构体。下面看几个主要变量的作用(在这里考虑解码的情况):

struct AVInputFormat *iformat; // 输入数据的封装格式

AVIOContext *pb; // 输入数据的缓存

unsigned int nb_streams; // 音视频流的个数

AVStream **streams; // 音视频流

char filename[1024]; // 文件名

int64_t duration; // 时长(单位:微秒us,转换为秒需要除以1000000)

int bit_rate; // 比特率(单位bps,转换为kbps需要除以1000)

AVDictionary *metadata; // 元数据

三、AVCodecContext

AVCodecContext 是一个描述编解码器上下文的结构体,包含了众多编解码器需要的参数信息。下面挑一些关键的变量来看看(这里只考虑解码)。

enum AVMediaType codec_type; // 编解码器的类型(视频,音频...)

struct AVCodec  *codec; // 采用的解码器AVCodec(H.264,MPEG2...)

int bit_rate; // 平均比特率

uint8_t *extradata; int extradata_size; // 针对特定编码器包含的附加信息(例如对于H.264解码器来说,存储SPS,PPS等)

AVRational time_base; // 根据该参数,可以把PTS转化为实际的时间(单位为秒s)

int width, height; // 如果是视频的话,代表宽和高

int refs; // 运动估计参考帧的个数(H.264的话会有多帧,MPEG2这类的一般就没有了)

int sample_rate; // 采样率(音频)

int channels; // 声道数(音频)

enum AVSampleFormat sample_fmt; // 采样格式

int profile; // 型(H.264里面就有,其他编码标准应该也有)

int level; // 级(和profile差不太多)

在这里需要注意:AVCodecContext 中很多的参数是编码的时候使用的,而不是解码的时候使用的。如果想了解这些变量具体的含义,请看:FFMPEG结构体分析:AVCodecContext

四、AVIOContext

AVIOContext 是 FFmpeg 管理输入输出数据的结构体。其重要的变量如下所示:

unsigned char *buffer; // 缓存开始位置

int buffer_size; // 缓存大小(默认32768)

unsigned char *buf_ptr; // 当前指针读取到的位置

unsigned char *buf_end; // 缓存结束的位置

void *opaque; // URLContext结构体

在解码的情况下,buffer 用于存储 FFmpeg 读入的数据。例如打开一个视频文件的时候,先把数据从硬盘读入 buffer,然后在送给解码器用于解码。

五、AVCodec

AVCodec 是存储编码器信息的结构体。其重要的变量如下所示:

const char *name; // 编解码器的名字的简称

const char *long_name; // 编解码器名字的全称

enum AVMediaType type; // 指明了类型,是视频,音频,还是字幕

enum AVCodecID id; // ID,不重复

const AVRational *supported_framerates; // 支持的帧率(仅视频)

const enum AVPixelFormat *pix_fmts; // 支持的像素格式(仅视频),如RGB24、YUV420P等。

const int *supported_samplerates; // 支持的采样率(仅音频)

const enum AVSampleFormat *sample_fmts; // 支持的采样格式(仅音频)

const uint64_t *channel_layouts; // 支持的声道数(仅音频)

int priv_data_size; // 私有数据的大小

如果想了解这些变量具体的含义,请看:FFMPEG结构体分析:AVCodec

每一个编解码器对应一个该结构体,查看一下 ffmpeg 的源代码,我们可以看一下 H.264 解码器的结构体如下所示(h264.c):

AVCodec ff_h264_decoder = {
.name = "h264",
.type = AVMEDIA_TYPE_VIDEO,
.id = CODEC_ID_H264,
.priv_data_size = sizeof(H264Context),
.init = ff_h264_decode_init,
.close = ff_h264_decode_end,
.decode = decode_frame,
.capabilities = /*CODEC_CAP_DRAW_HORIZ_BAND |*/ CODEC_CAP_DR1 | CODEC_CAP_DELAY |
CODEC_CAP_SLICE_THREADS | CODEC_CAP_FRAME_THREADS,
.flush= flush_dpb,
.long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
.init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
.update_thread_context = ONLY_IF_THREADS_ENABLED(decode_update_thread_context),
.profiles = NULL_IF_CONFIG_SMALL(profiles),
.priv_class = &h264_class,
};

六、AVStream

AVStream 是存储每一个音频/视频流信息的结构体。其重要的变量如下所示:

int index; // 标识该视频/音频流

AVCodecContext *codec; // 指向该视频/音频流的AVCodecContext(它们是一一对应的关系)

AVRational time_base; // 时基。通过该值可以把PTS,DTS转化为真正的时间。FFMPEG其他结构体中也有这个字段,但是根据我的经验,只有AVStream中的time_base是可用的。PTS*time_base=真正的时间

int64_t duration; // 该视频/音频流长度

AVDictionary *metadata; // 元数据信息

AVRational avg_frame_rate; // 帧率(注:对视频来说,这个挺重要的)

AVPacket attached_pic; // 附带的图片。比如说一些MP3,AAC音频文件附带的专辑封面。

七、AVPacket

AVPacket 是存储压缩编码数据相关信息的结构体。其重要的变量如下所示:

uint8_t *data; // 压缩编码的数据。

/* 例如对于H.264来说。1个AVPacket的data通常对应一个NAL。

注意:在这里只是对应,而不是一模一样。他们之间有微小的差别:使用FFMPEG类库分离出多媒体文件中的H.264码流。因此在使用FFMPEG进行音视频处理的时候,常常可以将得到的AVPacket的data数据直接写成文件,从而得到音视频的码流文件。*/

int   size; // data的大小

int64_t pts; // 显示时间戳

int64_t dts; // 解码时间戳

int   stream_index; // 标识该AVPacket所属的视频/音频流。

参考:

雷霄骅大神的几篇关于 ffmpeg 结构体的文章:

FFMPEG中最关键的结构体之间的关系

FFMPEG结构体分析:AVFrame

FFMPEG结构体分析:AVFormatContext

FFMPEG结构体分析:AVCodecContext

FFMPEG结构体分析:AVIOContext

FFMPEG结构体分析:AVCodec

FFMPEG结构体分析:AVStream

FFMPEG结构体分析:AVPacket

FFmpeg 常用结构体的更多相关文章

  1. 从头开始-07.Foundation框架常用结构体

    一.Foundation框架常用结构体NSRange\CGRange.NSPoint\CGPoint.NSSize\CGSize. NSRect\CGRect 的使用 1.  基本使用: //NSRa ...

  2. iOS Foundation框架简介 -1.常用结构体的用法和输出

    1.安装Xcode工具后会自带开发中常用的框架,存放的地址路径是: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.plat ...

  3. Foudation框架之一些常用结构体和常用类

    表示范围作用的结构体:NSRange:       有三种方式创建新的NSRange: 1.NSRange range:            range.location = 17;         ...

  4. iOS Foundation框架 -1.常用结构体的用法和输出

    1.安装Xcode工具后会自带开发中常用的框架,存放的地址路径是: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.plat ...

  5. FFmpeg: AVPacket 结构体分析

    AVPacket是FFmpeg中很重要的一个数据结构,它保存了解封装之后,解码之前的数据(注意:仍然是压缩后的数据)和关于这些数据的一些附加信息,如显示时间戳(pts).解码时间戳(dts).数据时长 ...

  6. FFmpeg: AVFormatContext 结构体分析

    AVFormatContext 结构体分析这个结构体描述了一个媒体文件或媒体流的构成和基本信息.这是FFMpeg中最为基本的一个结构,是其他所有结构的根,是一个多媒体文件或流的根本抽象.主要成员释义: ...

  7. ffmpeg AVPacket结构体及其相关函数

    0. 简介 AVPacket结构体并不是很复杂, 但是在ffmpeg中用的非常多. 与其相关的函数也是比较多. AVPacket保存了解复用之后, 解码之前的数据, 和这些数据相关的一些附加信息. 对 ...

  8. ffmpeg AVFrame结构体及其相关函数

    0. 简介 AVFrame中存储的是原始数据(例如视频的YUV, RGB, 音频的PCM), 此外还包含了一些相关的信息, 例如: 解码的时候存储了宏块类型表, QP表, 运动矢量等数据. 编码的时候 ...

  9. [OC Foundation框架 - 1] 常用结构体

    底层封装是使用了typedef定义的结构体 typedef struct _NSString{ xxx xxx } NSString;   1. NSRange 结构体 #注意结构体不是对象 3种定义 ...

随机推荐

  1. postman请求数据库方法(Omysql)

    一.github 地址: https://github.com/liyinchigithub/Omysql 二.效果 三.使用方式 如果你电脑已经安装配置 Git.node 环境,可以直接按下面步骤进 ...

  2. Python之基本运算符

    基本运算符 1.算符运算符 运算符 描述 例子 + 两个对象相加 a+b - 两个对象相减 a-b * 两个数相乘或返回一个被重复若干次的字符串 a*b / 两个数相除 a/b % 取模,返回除法的余 ...

  3. 愉快地使用Groovy Shell

    这是一篇有关Groovy Shell的帖子,以及它如何在日常工作中为您提供帮助(只要您是软件开发人员).无论您使用哪种编程语言或技术,都可以从Groovy Shell中受益.唯一真正的要求是您能够编写 ...

  4. Django多进程滚动日志的问题

    使用RotatingFileHandler控制日志文件的大小 # settings.py LOGGING = { ... 'handlers': { ... 'file': { 'level': 'I ...

  5. flex布局和边框阴影

    "妄"眼欲穿-CSS之flex布局和边框阴影 妄:狂妄: 不会的东西只有怀着一颗狂妄的心,假装能把它看穿吧. flex布局 main axis:主轴:cross axis:交叉轴 ...

  6. asp.net core web api 生成 swagger 文档

    asp.net core web api 生成 swagger 文档 Intro 在前后端分离的开发模式下,文档就显得比较重要,哪个接口要传哪些参数,如果一两个接口还好,口头上直接沟通好就可以了,如果 ...

  7. node.js中this指向失效解决

    问题:在外部单独使用类实例对象的方法,this没有指向该类实例对象 代码如下 class CQH { hello() { let name = this.name(); console.log(`He ...

  8. GO Slice

    一.切片(Slice) 1.1 什么是切片 Go 语言切片是对数组的抽象. Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数 ...

  9. sftp-server 搭建编译

    下载开源代码 https://github.com/zwx230741/openssh-portable 编译 # autoconf # ./configure --prefix=xxx # make ...

  10. iOS 常用算法之设计一个算法,验证某字符是否为合法IPV4字符

    浅析 : 一个IPV4字符由3个大于0小于255的数字 以及 3个点构成, 所有我们需要判断小数点数量是否满足条件, 以及小数点隔开的每部分是否满足条件即可. 思路: 1. 校验是否有3个小数点; 2 ...