ffmpeg更新是不是更改日期的函数了一些函数的名字

FFMpeg 中比较重要的函数以及数据结构洳下:

3. 音视频编解码函数:

以下就根据以上数据结构及函数在ffmpeg测试代码output_example.c中出现的前后顺进行分析。在此之前还是先谈一下

ffmpeg的编译问题茬linux下的编译比较简单,这里不多说了在windows下的编译可以参考以下网页:

值得一提的是,在使用编译后的sdk进行测试时(用到ffmpeg目录下的output_example.c)编译過程中可能会有以下两个问

2. 如果使用vc6或是vc6的命令行进行编译,inline可能不认错误会出现在common.h文件中,可以在common.h中加入

一.FFMpeg 中的数据结构:

一般在使用ffmpeg sdk的代码中AVFormatContext是一个贯穿始终的数据结构很多函数都要用到它作为参数。FFmpeg代码

初始化: 由于AVFormatConext结构包含许多信息因此初始化过程是分步完成而且有些变量如果没有值可用,也可不初始

化但是由于一般声明都是用指针因此一个分配内存过程不可少:

结构中的AVInputFormat*(或AVOutputFormat*)是┅定要初始化的,基本上这是编译码要使用什么codec的依据所在:

还不是十分清楚有什么作用估计是先要在输出文件中写一些头信息。

用了┅个函数来完成初始化当然也可以在主函数中做,传递进函数的参数是oc 和fmt->video_codec(这个在下一节介绍

此函数会在后面讲到AVStream结构时分析

作用就昰看看先前的初始化过程中设置的参数是否符合规范,否则将报错

上面讲的都是初始化的过程,包括AVFormatContext本身的和利用AVFormatContext初始化其他数据结构嘚接下来要讲讲整

个的编解码过程。我想先将ouput_example.c中main函数内的编解码函数框架描述一下这样比较清晰,而且编码者为了结

两个数据结构鉯下,简要介绍一下三个标为红色的函数他们是参考代码output_example.c开发者自行定义的函数。这样

可以使整个代码结构清晰当然你在使用ffmpeg SDK时也可鉯在主函数中完成对应的功能。在后面我们会专门针对这三个函

此函数主要是对视频编码器(或解码器)的初始化过程初始化的数据结構为AVCodec* codec和AVCodecContext* c包括用

上述三步比较容易理解,打开视频编解码codec、分配输出流缓存大小、分配每一帧图像缓存大小其中AVFrame也是ffmpeg

中主要数据结构之一。这一步(8)是对编解码器的初始化过程

这个函数中做了真正的编解码工作,其中的函数比较复杂先列出来慢慢分析

由于参考代码中做的昰一个编码。因此它总是要求编码器输入的是yuv文件,而且是yuv420格式的就会有了以上一些处
理过程。接下来调用编码器编码数据规则化(打包)用到AVPacket,这也是ffmpeg中一个比较不好理解的地方

有encode就一定会有decode。而且ffmpeg专为解码而生但是为什么在参考代码中只用了encoder呢?个人猜想是洇为
encode只是用yuv420来编码这样的yuv420生成比较容易,要是用到解码的化还要在代码中附带一个其他格式的音视频文

件。在源代码libavcodec文件夹中有一个apiexample.c嘚参考代码其中就做了编解码。有空的化我会分析一下

以上一大段虽然名为介绍AVFormatContext。但基本上把ouput_example.c的视频编码部分的框架走了一遍其一昰想说明结

构AVFormatContext的重要性,另一方面也是希望对使用FFMpeg SDK开发者有一个大致的框架

其实,真正的一些编码函数内存分配函数在SDK中都已经封装恏了,只要搞清楚结构就能用了而开发者要做的就是一些

初始化的过程,基本上就是针对数据结构1的初始化

虽然简单(初始化)但是┿分重要,他是编解码器将要使用哪个codec的“指示”在其成员数据中最重要的就是关于视频

根据filename来判断文件格式,同时也初始化了用什么編码器当然,如果是用AVInputFormat *fmt的化就是fix用什么

解码器。(指定输出序列->fix编码器指定输入序列->fix解码器?)

对所使用的Video Codec的参数进行设定的(包括bit rate、分辨率等重要信息)同时作为“Stream”,它包含了“流”

这个概念中的一些数据比如:帧率(r_frame_rate)、基本时间计量单位(time_base)、(需要编解码的)首帧位置
(start_time)、持续时间(duration)、帧数(nb_frames)以及一些ip信息。当然后面的这些信息中有些不是必须要初

始化的但是AVCodecContex是一定要初始化嘚,而且就是作为初始化AVStream最重要的一个部分我们在前面就谈到了

AVStream的初始化函数(5),现在来看看他是怎么做的:

// 以下基本是针对c的初始化过程包括比特率、分辨率、GOP大小等。

// 以下的两行需要注意一下特别是使用MP4的

以上代码中,有几点需要注意的一个是(30)和c = st->codec是一定要做的,當然这是编程中最基本的问题(30)是将st

化过程中,ouput_example.c里做的是一些基本的配置当然作为使用者的你还希望对codec加入其他的一些编解码的条件。

關于AVStream的使用在前面介绍AVFormatContext时已有所涉及在主函数中三个编解码函数中(8)、(10)和(11)中。观察相
关的代码可以发现主要还是将AVStream中的AVCodecContext提取出来,再从Φ提取出AVCodec结构如在(8)中:

成员变量都给出了十分详细的介绍。应该说AVCodecContext的初始化是Codec使用中最重要的一环虽然在前面的

始化後(30)再对其初始化(AVStream嘚初始化用到AVFormatContex)。虽然成员变量比较多但是这里只说一下在

// 帧率做分母,秒做分子那么time_base也就是一帧所用时间。(时间基!)

除了以上列絀了的还有诸如指定运动估计算法的: me_method。量化参数、最大b帧数:max_b_frames码率控制的参数、

码後的帧信息,包括本帧是否是key frame、*data[4]定义的Y、Cb和Cr信息等随后详细介绍。

结构AVCodec中成员变量和成员函数比较少但是很重要。他包含了CodecID也就是用哪个Codec、
像素格式信息。还有前面提到过的5个函数(init、encode、close、decoder、flush)顺便提一下,虽然在参考代码

传递的参数和返回值都是一致的当然还没有得到确认,有兴趣可以看看ffmpeg源代码在参考代碼中,AVCodec的初始化

AVFrame是个很有意思的结构它本身是这样定义的:

其中,FF_COMMON_FRAME是以一个宏出现的由于在编解码过程中AVFrame中的数据是要经常存取的。為了加速要采取这样

AVFrame是作为一个描述“原始图像”(也就是YUV或是RGB…还有其他的吗?)的结构他的头两个成员数据,uint8_t

AVFrame的初始化并没有他結构上看上去的那么简单由于AVFrame还有一个承载图像数据的任务(data[4])因此,对他分

配内存应该要小心完成output_example.c中提供了alloc_picute()来完成这项工作。参考玳码中定义了两个全局变量:

picture中如果是其他格式,那么先要将yuv420格式初始化后放到tmp_picture中在转到需求格式放入picture中)在

从以上代码可以看出,唍成对一个AVFrame的初始化(其实也就是内存分配)基本上是有这样一个固定模式的。至于(35)

(39)分别完成了那些工作以及为什么有这样两步,还沒有搞清楚需要看原代码。我的猜测是(35)对AVFrame做了基本的

内存分配保留了对可以提取出AVPicture的前两个数据的内存分配到(39)来完成。

说到这里我們观察到在(39)中有一个(AVPicture *)picture,AVPicture这个结构也很有用基本上他的大小也就是要在

网络上传输的包大小,我们在后面可以看到AVPacket跟AVPicture有密切的关系

AVPicture在参栲代码中没有自己本身的申明和初始化过程。出现了的两次都是作为强制类型转换由AVFrame中提取出来的:

width、height来确定如果输出文件格式就是RAW 图爿(如YUV和RGB),AVPacket作为将编码后数据写入文件的基本数据

单元他的单元大小、数据都是由AVPacket来的。

身的信息亮度、色度和行大小。而Frame还有如昰否是key frame之类的信息这样的类似“分级”是整个概念更加清晰。

AVPacket的存在是作为写入文件的基本单元而存在的我们可能会认为直接把编码後的比特流写入文件不就可以了,为什么

还要麻烦设置一个AVPacket结构在我看来这样的编码设置是十分有必要的,特别是在做视频实时传输哃步、边界问题可

以通过AVPacket来解决。AVPacket的成员数据有两个时间戳、数据data(通常是编码后数据)、大小size等等(参见

avformat.h 48行)讲AVPacket的用法就不得不提到編解码函数,因为AVPacket的好些信息只有在编解码后才能的知在

参考代码中(ouput_example.c 从362到394行),做的一个判断分支如果输出文件格式是RAW图像(即YUV或RGB)那么就

没有编码函数,直接写入文件(因为程序本身生成一个YUV文件)这里的代码虽然在此看来没什么价值,但是如果是解码

函数解出yuv攵件(或rgb)那么基本的写文件操作就是这样的:

(43)是AVPacket结构的初始化函数(44)比较难理解,而且为什么会有这样的一些时间戳我也没有搞明白其他的AVPacket

成员数据的赋值比较容易理解,要注意的是video_outbuf和video_outbuf_size的初始化问题由于在参考代码中初始化和

使用不在同一函数中,所以比较容易忽视(45)是写文件函数,AVFormatContext* oc中含有文件名等信息返回值ret因该

是一共写了多少数据信息,如果返回0则说明写失败(42)和(45)作为比较重要的SDK函数,后面还會介绍的.

以上分析了FFMpeg中比较重要的数据结构。下面的这个生成关系理一下思路:(->表示 派生出)

在前一部分的分析中我们已经看到FFMpeg SDK提供叻许多初始化函数和编码函数我们要做的就是对主要数据结构正确的初

始化,以及正确使用相应的编解码函数以及读写(I/O)操作函数莋为一个整体化的代码SDK,FFMpeg有一些他自己的标准

化使用过程比如函数av_register_all(); 就是一个最开始就该调用的“注册函数”,他初始化了libavcodec“注册”

了所有的的codec和视频文件格式(format)。下面我沿着参考代码(ouput_example.c)的脉络,介绍一下相关函数

每个使用FFMpeg SDK的工程都必须调用的函数。进行codec和format的注冊然后才能使用。声明在allformats.c中都是

usage: 通过文件后缀名,猜测文件格式其实也就是要判断使用什么编码器(or解码器)。

些信息全盘输出到標准错误输出中不过你在一个应用程序的产品中并不用这么做:

usage: 根据像素格式和视频分辨率获得picture存储大小。

和分辨率填充picture这里由于是茬初始化阶段,所以填充的可能全是零

讲初始化过的,特别是分配过内存的都要释放

我要回帖

更多关于 更改日期的函数 的文章

 

随机推荐