FFmpeg常用结构体介绍
AVFormatContext是一个贯穿全局的数据结构。
AVInputFormat是FFmpeg的解复用器对象。表示输入文件容器格式。
AVStream是存储每一个视频/音频流信息的结构体。解复用器的目的就是从容器中分离(解析出来)不同的流,FFmpeg中的流对象为AVStream。它是由解复用器的read_header函数创建的,并保存在AVFormatContext的nb_streams(容器中的流条数)及streams数组中。
AVCodecContext这是一个描述编解码器上下文的数据结构,包含了众多编解码器需要的参数信息。
AVPacket,用AVPacket来存放编码后的视频帧数据,AVPacket保存了解复用之后、解码之前的数据(仍然是压缩后的数据)和关于这些数据的一些附加信息,如显示时间戳(PTS)、解码时间戳(DPS)、数据时长、所在媒体流的索引等。
AVCodec是存储编解码器信息的结构体。
AVFrame结构体一般用于存储原始数据(即非压缩数据,例如对视频来说是YUV、RGB,对音频来说是PCM),此外还包含了一些包含相关信息。比如说,解码的时候存储了宏块类型表、QP表、运动尺量表等数据。编码的时候也存储了相关数据。
AVFrame存放从AVPacket中解码出来的原始数据,其必须通过av_frame_alloc来创建,通过av_frame_free来释放。AVFrame描述解码出的音视频数据。
AVIOContext,协议(文件)操作顶层结构是AVIOContext,这个对象实现了带缓冲的读/写操作。FFmpeg的输入对象AVFormat的pb字段指向一个AVIOContext。
URLProtocol是FFmpeg操作文件的结构(包括文件、网络数据流等),包括open、close、read、write、seek等操作。URLProtocol为协议操作对象,针对每种协议会有一个这样的对象,每个协议操作对象和一个协议对象关联。
URLContext对象封装了协议对象及协议操作对象,URLContext在avio.c中通过url_alloc_for_protocol进行初始化,并且分配空间。
FFmpeg关键函数介绍
av_register_all函数
libavformat是用来处理多媒体格式的,主要有两个作用,一个是分离音视频,一个是反向合成具体的媒体格式。同时也支持I/O模块,支持一系列的协议获取数据(文件、TCP、HTTP等),在使用libavformat之前,需要先调用av_register_all函数来注册所有编译的muxers、demuxers及protocols,如果要使用libavformat的网络接口,需要使用avformat_network_init接口。Ffplay.c的av_register_all函数调用后的时序图如下:
avformat_alloc_context函数
该函数的作用是,当使用AVFormatContext时,需要对AVFormatContext分配内存空间。
av_open函数
该函数用于打开FFmpeg的输入/输出文件。
avformat_open_input函数
avformat_open_input主要功能是打开一个文件,读取header,不会涉及打开解码器。与之对应的通过avformat_close_input函数关闭文件。
avformat_find_stream_info函数
该函数可以读取一部分音视频频数据并且获得一些相关的信息。要不断的读取数据包,解码获得相应的信息。主要是读一些包(packets ),然后从中提取初流的信息。有一些文件格式没有头,比如说MPEG格式的,这个时候,这个函数就很有用,因为它可以从读取到的包中获得到流的信息。在MPEG-2重复帧模式的情况下,该函数还计算真实的帧率。
av_read_frame函数
FFmpeg中的av_read_frame函数的作用是读取码流中的若干音频帧或者1帧视频。例如,在解码视频的时候,每解码一个视频帧,需要先调用av_read_frame获得1帧视频的压缩数据,然后才能对该数据进行解码(例如,H.264中1帧压缩数据通常对应一个NAL)。
av_write_frame函数
FFmpeg调用avformat_write_header函数写头部信息,调用av_write_frame函数写1帧数据,调用av_write_trailer函数写尾部信息。
avcodec_decode_video2函数
该函数将解码AVPacket的数据,将解码后的数据填充到AVFrame中,AVFrame保存的是解码后的原始数据。
FFPlay
FFPlay是 FFmpeg中拥有播放功能的可执行程序,它主要的源文件是 ffplay.c文件,在该文件中播放一个视频的步骤如下。
(1)注册所有容器格式和 Codec: av_register_all。注册所有编解码器、解复用器、协议。
(2)打开文件:av_open_input_file。
(3)从文件中提取流信息:av_find_stream_info。
(4)遍历所有的数据流,查找其中的数据流种类:CODEC_TYPE_VIDEO(表示视频流)。
(5)查找对应的解码器:avcodec_find_decoder。
(6)打开编解码器:avcodec_open。
(7)为解码帧分配内存:avcodec_alloc_frame。
(8)不停地从码流中提取出帧数据:av_read_frame。
(9)判断帧的类型,调用视频帧:avcodec_decode_video。
(10)解码完成后,释放解码器:avcodec_close。
(11)关闭输入文件:av_close_input_file。
感谢各位关注