FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx

上传人:b****2 文档编号:4570953 上传时间:2023-05-03 格式:DOCX 页数:27 大小:28.23KB
下载 相关 举报
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第1页
第1页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第2页
第2页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第3页
第3页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第4页
第4页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第5页
第5页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第6页
第6页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第7页
第7页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第8页
第8页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第9页
第9页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第10页
第10页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第11页
第11页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第12页
第12页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第13页
第13页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第14页
第14页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第15页
第15页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第16页
第16页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第17页
第17页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第18页
第18页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第19页
第19页 / 共27页
FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx_第20页
第20页 / 共27页
亲,该文档总共27页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx

《FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx》由会员分享,可在线阅读,更多相关《FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx(27页珍藏版)》请在冰点文库上搜索。

FFMpeg 库中比较重要的函数以及数据结构Word文件下载.docx

在此之前还是先谈一下

ffmpeg的编译问题。

在linux下的编译比较简单,这里不多说了。

在windows下的编译可以参考以下网页:

http:

//bbs.chinavideo.org/viewthread.php?

tid=1897&

extra=page%3D1

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

题:

1.Output_example.c用到了snprintf.h这个头文件。

然而这个头文件在win下和linux下有所不同。

具体在win下

可以用以下方法解决:

//www.ijs.si/software/snprintf/

2.如果使用vc6,或是vc6的命令行进行编译,inline可能不认。

错误会出现在common.h文件中,可以在common.h中加入

#ifdef_MSC_VAR

#defineinline__inline

#endif

交待完毕进入正题。

一.FFMpeg中的数据结构:

I.AVFormatContext

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

FFmpeg代码

中对这个数据结构的注释是:

formatI/Ocontext

此结构包含了一个视频流的格式内容。

其中存有了AVInputFormat(orAVOutputFormat同一时间AVFormatContext内只能存

在其中一个),和AVStream、AVPacket这几个重要的数据结构以及一些其他的相关信息,比如title,author,copyright等。

还有一些可能在编解码中会用到的信息,诸如:

duration,file_size,bit_rate等。

参考avformat.h头文件。

Useage:

声明:

AVFormatContext*oc;

(1)

初始化:

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

化。

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

oc=av_alloc_format_context();

(2)

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

oc->

oformat=fmt;

oroc->

iformat=fmt;

(3)

其中AVOutputFormat*fmt或AVInputFormat*fmt。

(AVInputFormatandAVOutputFormat的初始化在后面介绍。

随后在参

考代码output_example.c中有一行:

snprintf(oc-filename,sizeof(oc->

filename),“%s”,filename);

(4)

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

在完成以上步骤後,(初始化完毕AVInputFormat*(或AVOutputFormat*)以及AVFormatContext)接下来就是要利用oc初始

化本节开始讲到的AVFormatContext中的第二个重要结构。

AVStream(假设已经有了声明AVStream*video_st。

参考代码中

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

video_codec(这个在下一节介绍

(29)):

vdeo_st=add_video_stream(oc,fmt->

video_codec);

(5)

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

AVFormatContext最后的一个设置工作是:

if(av_set_paramters(oc,NULL)<

0){(6)

//handleerror;

}

dump_format(oc,0,filename,1);

(7)

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

上面讲的都是初始化的过程,包括AVFormatContext本身的和利用AVFormatContext初始化其他数据结构的。

接下来要讲讲整

个的编解码过程。

我想先将ouput_example.c中main函数内的编解码函数框架描述一下。

这样比较清晰,而且编码者为了结

构清晰,在写ouput_example.c的过程中也基本上在main函数中只保持AVFormatContext和AVStream两个数据结构

(AVOutputFormat其实也在但是包含在AVFormatContext中了)。

//openvideocodecandallocatethenecessaryencodebuffers

if(video_st)

open_video(oc,video_st);

(8)

//writethestreamheader,ifany

av_write_header(oc);

(9)

//encodeanddecodeprocess

for(;

;

){

write_video_frame(oc,video_st);

(10)

//breakcondition…here

//closecodec

close_video(oc,video_st);

(11)

//writethetrailer,ifany

av_write_trailer(oc);

(12)

//freethestreams

for(i=0;

i<

b_streams;

i++){

av_freep(&

streams[i]->

codec);

(13)

streams[i]);

(14)

//closetheouputfile

if(!

(fmt->

flags&

AVFMT_NOFILE)){

url_fclose(&

pb);

(15)

av_free(oc);

(16)

通过以上的一串代码,就可以清晰地看出AVFormatContex*oc和AVStream*video_st是在使用ffmpegSDK开发时贯穿始终的

两个数据结构。

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

这样

可以使整个代码结构清晰,当然你在使用ffmpegSDK时也可以在主函数中完成对应的功能。

在后面我们会专门针对这三个函

数做分析。

1.open_video(oc,video_st);

此函数主要是对视频编码器(或解码器)的初始化过程。

初始化的数据结构为AVCodec*codec和AVCodecContext*c包括用

到了的SDK函数有:

c=st->

codec;

codec=avcodec_find_encoder(c->

codec_id);

//编码时,找编码器(17)

codec=avcodec_find_decoder(c->

//解码时,找解码器(18)

AVCodecContex是结构AVStream中的一个数据结构,因此在AVStream初始化後(5)直接复值给c。

//internalopenvideocodec

avcodec_open(c,codec);

(19)

//allocatevideostreambuffer

//AVFrame*picture

//uint8_t*video_outbuf

video_outbuf_size=200000;

video_outbuf=av_maloc(video_outbuf_size);

(20)

//allocatevideoframebuffer

picture=alloc_picture(c->

pix_fmt,c->

width,c->

height);

(21)

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

其中AVFrame也是ffmpeg

中主要数据结构之一。

这一步(8)是对编解码器的初始化过程。

2.write_video_frame(AVFormatContext*oc,AVStream*st)

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

用到的数据结构有AVCodecContext*c,SwsContext*img_convert_ctx。

其中SwsContext是用来变换图像格式的。

比如

yuv422变到yuv420等,当然也用到函数,见下面列表。

fill_yuv_image(tmp_picture,frame_count,c->

(22)

sws_scale(img_convert_ctx,tmp_picture->

tmp_picture->

linesize,

0,c->

height,picture->

data,picture->

linesize);

(23)

img_convert_ctx=sws_getContxt(c->

height,PIX_FMT_YUV420P,(24)

c->

heigth,c->

pix_fmt,sws_flags,NULL,NULL,NULL);

由于参考代码中做的是一个编码。

因此,它总是要求编码器输入的是yuv文件,而且是yuv420格式的。

就会有了以上一些处

理过程。

接下来调用编码器编码,数据规则化(打包)用到AVPacket,这也是ffmpeg中一个比较不好理解的地方。

out_size=avcodec_encode_video(c,video_outbuf,video_outbuf_size,picture);

(25)

AVPacketpkt;

av_init_packet(&

pkt);

(26)

//……handlepktprocess,wewillanalyzelater

ret=av_write_frame(oc,&

(27)

有encode就一定会有decode。

而且ffmpeg专为解码而生,但是为什么在参考代码中只用了encoder呢?

个人猜想是因为

encode只是用yuv420来编码,这样的yuv420生成比较容易,要是用到解码的化,还要在代码中附带一个其他格式的音视频文

件。

在源代码libavcodec文件夹中有一个apiexample.c的参考代码,其中就做了编解码。

有空的化我会分析一下。

3.close_video(AVFormatContext*oc,AVStream*st)

avcodec_close(st->

av_free(picture->

data[0]);

av_free(picture);

av_free(video_outbuf);

比较容易理解,不多说了。

以上一大段虽然名为介绍AVFormatContext。

但基本上把ouput_example.c的视频编码部分的框架走了一遍,其一是想说明结

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

其实,真正的一些编码函数,内存分配函数在SDK中都已经封装好了,只要搞清楚结构就能用了。

而开发者要做的就是一些

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

II.AVOutputFormat

虽然简单(初始化)但是十分重要,他是编解码器将要使用哪个codec的“指示”。

在其成员数据中最重要的就是关于视频

codec的了:

enumCodecIDvideo_codec;

AVOutputFormat*fmt;

fmt=guess_format(NULL,filename,NULL);

(28)

根据filename来判断文件格式,同时也初始化了用什么编码器。

当然,如果是用AVInputFormat*fmt的化,就是fix用什么

解码器。

(指定输出序列->

fix编码器,指定输入序列->

fix解码器?

III.AVStream

AVStream作为继AVFormatContext後第二个贯穿始终的结构是有其理由的。

他的成员数据中有AVCodecContext这基本的上是

对所使用的VideoCodec的参数进行设定的(包括bitrate、分辨率等重要信息)。

同时作为“Stream”,它包含了“流”

这个概念中的一些数据,比如:

帧率(r_frame_rate)、基本时间计量单位(time_base)、(需要编解码的)首帧位置

(start_time)、持续时间(duration)、帧数(nb_frames)以及一些ip信息。

当然后面的这些信息中有些不是必须要初

始化的,但是AVCodecContex是一定要初始化的,而且就是作为初始化AVStream最重要的一个部分。

我们在前面就谈到了

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

//declaration

AVStream*video_st;

video_st=add_video_stream(oc,fmt->

staticAVStream*add_video_stream(AVFormatContex*oc,intcodec_id){(29)

AVCodecContext*c;

//memberofAVStream,whichwillbeinitializedhere

AVStream*st;

//temporarydata,willbereturned

st=av_new_stream(oc,0);

(30)

//以下基本是针对c的初始化过程。

包括比特率、分辨率、GOP大小等。

……

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

strcmp(oc->

oformat->

name,“mp4”)||!

name,“mov”)||!

name,

“3gp”))

flags|=CODEC_FLAG_GLOBAL_HEADER;

//将st传给video_st;

returnst;

以上代码中,有几点需要注意的。

一个是(30)和c=st->

codec是一定要做的,当然这是编程中最基本的问题,(30)是将st

这个AVSteam绑定到AVFormatContext*oc上。

后面的c=st->

codec是将c绑定到st的AVCodecContext上。

其二是对c的初始

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

可以参考avcodec.h里关于AVCodecContext结构的介绍,注释比较详细的。

关于AVStream的使用在前面介绍AVFormatContext时已有所涉及,在主函数中三个编解码函数中(8)、(10)和(11)中。

观察相

关的代码,可以发现主要还是将AVStream中的AVCodecContext提取出来,再从中提取出AVCodec结构如在(8)中:

//open_video(oc,video_st);

//AVFormatContext*oc,AVStream*st

AVCodec*codec;

(31)

//openthecodec

avcodec_open(c,codec);

(32)

同样,我们可以看到在(10)(write_video_frame())中AVFrame也是做为传递AVCodecContext结构的载体而存在。

(11)

(close_video())比较简单,不熬述。

IV.AVCodecContext

此结构在FfmpegSDK中的注释是:

mainexternalapistructure其重要性可见一斑。

而且在avcodec它的定义处,对其每个

成员变量,都给出了十分详细的介绍。

应该说AVCodecContext的初始化是Codec使用中最重要的一环。

虽然在前面的

AVStream中已经有所提及,但是这里还是要在说一遍。

AVCodecContext作为Avstream的一个成员结构,必须要在Avstream初

始化後(30)再对其初始化(AVStream的初始化用到AVFormatContex)。

虽然成员变量比较多,但是这里只说一下在

output_example.c中用到了,其他的请查阅avcodec.h文件中介绍。

//staticAVStream*add_video_stream(AVFormatContext*oc,intcodec_id)

codec_id=codec_id;

codec_type=CODEC_TYPE_VIDEO;

bit_rate=400000;

//400kbits/s

width=352;

height=288;

//CIF

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

(时间基!

time_base.den=STREAM_FRAME_RATE;

time_base.num=1;

gop_size=12;

//heredefine:

//#defineSTREAM_PIX_FMTPIX_FMT_YUV420P

//pixelformat,seePIX_FMT_xxx

//-encoding:

setbyuser.

//-decoding:

setbylavc.

pix_fmt=STREAM_PIX_FMT;

除了以上列出了的。

还有诸如指定运动估计算法的:

me_method。

量化参数、最大b帧数:

max_b_frames。

码率控制的参数、

差错掩盖error_concealment、模式判断模式:

mb_decision(这个参数蛮有意思的,可以看看avcodec.h1566行)、

Lagrangemultipler参数:

lmin&

lmax和宏块级Lagrangemultipler参数:

mb_lmin&

mb_lmax、constant

quantizationparameterratecontrolmethod:

cqp等。

值得一提的是在AVCodecContext中有两个成员数据结构:

AVCodec、AVFrame。

AVCodec记录了所要使用的Codec信息并且含有

5个函数:

init、encoder、close、decode、flush来完成编解码工作(参见avcode.h2072行)。

AVFrame中主要是包含了编

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

初始化後,可以说AVCodecContext在(8)&

(10)中大显身手。

先在(8)open_video()中初始化AVCodec*codec以及AVFrame*

picture:

//AVCodecContext*c;

picture=alloc_picture(PIX_FMT_YUV420P,c->

後在writer_video_frame(AVFormatContext*oc,AVStream*st)中作为一个编解码器的主要参数被利用:

V.AVCodec

结构AVCodec中成员变量和成员函数比较少,但是很重要。

他包含了CodecID,也就是用哪个Codec、

像素格式信息。

还有前面提到过的5个函数(init、encode、close、decoder、flush)。

顺便提一下,虽然在参考代码

output_example.c中的编码函数用的是avcodec_encode_video(),我怀疑在其中就是调用了AVCodec的encode函数,他们

传递的参数和返回值都是一致的,当然还没有得到确认,有兴趣可以看看ffmpeg源代码。

在参考代码中,AVCodec的初始化

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2