FFMPEG流程分析教學(xué)文稿_第1頁
FFMPEG流程分析教學(xué)文稿_第2頁
FFMPEG流程分析教學(xué)文稿_第3頁
FFMPEG流程分析教學(xué)文稿_第4頁
FFMPEG流程分析教學(xué)文稿_第5頁
已閱讀5頁,還剩37頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、Good is good, but better carries it.精益求精,善益求善。FFMPEG流程分析-FFMPEG架構(gòu)分析1.簡介FFmpeg是一個集錄製、轉(zhuǎn)換、音/視頻編碼解碼功能為一體的完整的開源解決方案。FFmpeg的開發(fā)是基於Linux操作系統(tǒng),但是可以在大多數(shù)操作系統(tǒng)中編譯和使用。FFmpeg支持MPEG、DivX、MPEG4、AC3、DV、FLV等40多種編碼,AVI、MPEG、OGG、Matroska、ASF等90多種解碼.TCPMP,VLC,MPlayer等開源播放器都用到了FFmpeg。FFmpeg主目錄下主要有l(wèi)ibavcodec、libavformat和lib

2、avutil等子目錄。其中l(wèi)ibavcodec用於存放各個encode/decode模塊,libavformat用於存放muxer/demuxer模塊,libavutil用於存放內(nèi)存操作等輔助性模塊。以flashmovie的flv文件格式為例,muxer/demuxer的flvenc.c和flvdec.c文件在libavformat目錄下,encode/decode的mpegvideo.c和h263de.c在libavcodec目錄下。2.muxer/demuxer與encoder/decoder定義與初始化muxer/demuxer和encoder/decoder在FFmpeg中的實(shí)現(xiàn)代碼裡

3、,有許多相同的地方,而二者最大的差別是muxer和demuxer分別是不同的結(jié)構(gòu)AVOutputFormat與AVInputFormat,而encoder和decoder都是用的AVCodec結(jié)構(gòu)。muxer/demuxer和encoder/decoder在FFmpeg中相同的地方有:二者都是在main()開始的av_register_all()函數(shù)內(nèi)初始化的二者都是以鍊錶的形式保存在全局變量中的muxer/demuxer是分別保存在全局變量AVOutputFormat*first_oformat與AVInputFormat*first_iformat中的。encoder/decoder都是保

4、存在全局變量AVCodec*first_avcodec中的。二者都用函數(shù)指針的方式作為開放的公共接口demuxer開放的接口有:int(*read_probe)(AVProbeData*);int(*read_header)(structAVFormatContext*,AVFormatParameters*ap);int(*read_packet)(structAVFormatContext*,AVPacket*pkt);int(*read_close)(structAVFormatContext*);int(*read_seek)(structAVFormatContext*,intstr

5、eam_index,int64_ttimestamp,intflags);muxer開放的接口有:int(*write_header)(structAVFormatContext*);int(*write_packet)(structAVFormatContext*,AVPacket*pkt);int(*write_trailer)(structAVFormatContext*);encoder/decoder的接口是一樣的,只不過二者分別只實(shí)現(xiàn)encoder和decoder函數(shù):int(*init)(AVCodecContext*);int(*encode)(AVCodecContext*,

6、uint8_t*buf,intbuf_size,void*data);int(*close)(AVCodecContext*);int(*decode)(AVCodecContext*,void*outdata,int*outdata_size,uint8_t*buf,intbuf_size);仍以flv文件為例來說明muxer/demuxer的初始化。在libavformatallformats.c文件的av_register_all(void)函數(shù)中,通過執(zhí)行REGISTER_MUXDEMUX(FLV,flv);將支持flv格式的flv_muxer與flv_demuxer變量分別註冊到全局

7、變量first_oformat與first_iformat鍊錶的最後位置。其中flv_muxer在libavformatflvenc.c中定義如下:AVOutputFormatflv_muxer=flv,flvformat,video/x-flv,flv,sizeof(FLVContext),#ifdefCONFIG_LIBMP3LAMECODEC_ID_MP3,#else/CONFIG_LIBMP3LAMECODEC_ID_NONE,CODEC_ID_FLV1,flv_write_header,flv_write_packet,flv_write_trailer,.codec_tag=(co

8、nstAVCodecTag*)flv_video_codec_ids,flv_audio_codec_ids,0,AVOutputFormat結(jié)構(gòu)的定義如下:typedefstructAVOutputFormatconstchar*name;constchar*long_name;constchar*mime_type;constchar*extensions;/*commaseparatedfilenameextensions*/*sizeofprivatedatasothatitcanbeallocatedinthewrapper*/intpriv_data_size;/*outputsu

9、pport*/enumCodecIDaudio_codec;/*defaultaudiocodec*/enumCodecIDvideo_codec;/*AVStream*st-AVCodecContext*codec-structAVCodec*codec與AVOutputStream-AVStream*st-AVCodecContext*codec-structAVCodec*codec變量。4.其他主要數(shù)據(jù)結(jié)構(gòu)4.1AVFormatContextAVFormatContext是FFMpeg格式轉(zhuǎn)換過程中實(shí)現(xiàn)輸入和輸出功能、保存相關(guān)數(shù)據(jù)的主要結(jié)構(gòu)。每一個輸入和輸出文件,都在如下定義的指針數(shù)組

10、全局變量中有對應(yīng)的實(shí)體。staticAVFormatContext*output_filesMAX_FILES;staticAVFormatContext*input_filesMAX_FILES;對於輸入和輸出,因?yàn)楣灿玫氖峭粋€結(jié)構(gòu)體,所以需要分別對該結(jié)構(gòu)中如下定義的iformat或oformat成員賦值。structAVInputFormat*iformat;structAVOutputFormat*oformat;對一個AVFormatContext來說,這二個成員不能同時有值,即一個AVFormatContext不能同時含有demuxer和muxer。在main()函數(shù)開頭的pars

11、e_options()函數(shù)中找到了匹配的muxer和demuxer之後,根據(jù)傳入的argv參數(shù),初始化每個輸入和輸出的AVFormatContext結(jié)構(gòu),並保存在相應(yīng)的output_files和input_files指針數(shù)組中。在av_encode()函數(shù)中,output_files和input_files是作為函數(shù)參數(shù)傳入後,在其他地方就沒有用到了。4.2AVCodecContext保存AVCodec指針和與codec相關(guān)數(shù)據(jù),如video的width、height,audio的samplerate等。AVCodecContext中的codec_type,codec_id二個變量對於enco

12、der/decoder的匹配來說,最為重要。enumCodecTypecodec_type;/*seeCODEC_TYPE_xxx*/enumCodecIDcodec_id;/*seeCODEC_ID_xxx*/如上所示,codec_type保存的是CODEC_TYPE_VIDEO,CODEC_TYPE_AUDIO等媒體類型,codec_id保存的是CODEC_ID_FLV1,CODEC_ID_VP6F等編碼方式。以支持flv格式為例,在前述的av_open_input_file()函數(shù)中,匹配到正確的AVInputFormatdemuxer後,通過av_open_input_stream()

13、函數(shù)中調(diào)用AVInputFormat的read_header接口來執(zhí)行flvdec.c中的flv_read_header()函數(shù)。在flv_read_header()函數(shù)內(nèi),根據(jù)文件頭中的數(shù)據(jù),創(chuàng)建相應(yīng)的視頻或音頻AVStream,並設(shè)置AVStream中AVCodecContext的正確的codec_type值。codec_id值是在解碼過程中flv_read_packet()函數(shù)執(zhí)行時根據(jù)每一個packet頭中的數(shù)據(jù)來設(shè)置的。4.3AVStreamAVStream結(jié)構(gòu)保存與數(shù)據(jù)流相關(guān)的編解碼器,數(shù)據(jù)段等信息。比較重要的有如下二個成員:AVCodecContext*codec;/*priv_

14、data=asf_st;4.4AVInputStream/AVOutputStream根據(jù)輸入和輸出流的不同,前述的AVStream結(jié)構(gòu)都是封裝在AVInputStream和AVOutputStream結(jié)構(gòu)中,在av_encode()函數(shù)中使用。AVInputStream中還保存的有與時間有關(guān)的信息。AVOutputStream中還保存有與音視頻同步等相關(guān)的信息。4.5AVPacketAVPacket結(jié)構(gòu)定義如下,其是用於保存讀取的packet數(shù)據(jù)。typedefstructAVPacketint64_tpts;/presentationtimestampintime_baseunitsint

15、64_tdts;/decompressiontimestampintime_baseunitsuint8_t*data;intsize;intstream_index;intflags;intduration;/presentationdurationintime_baseunits(0ifnotavailable)void(*destruct)(structAVPacket*);void*priv;int64_tpos;/bytepositioninstream,-1ifunknownAVPacket;在av_encode()函數(shù)中,調(diào)用AVInputFormat的(*read_packet

16、)(structAVFormatContext*,AVPacket*pkt)接口,讀取輸入文件的一幀數(shù)據(jù)保存在當(dāng)前輸入AVFormatContext的AVPacket成員中。-FFMPEG是目前被應(yīng)用最廣泛的編解碼軟件庫,支持多種流行的編解碼器,它是C語言實(shí)現(xiàn)的,不僅被集成到各種PC軟件,也經(jīng)常被移植到多種嵌入式設(shè)備中。使用面向?qū)ο蟮霓k法來設(shè)想這樣一個編解碼庫,首先讓人想到的是構(gòu)造各種編解碼器的類,然後對於它們的抽象基類確定運(yùn)行數(shù)據(jù)流的規(guī)則,根據(jù)算法轉(zhuǎn)換輸入輸出對象。在實(shí)際的代碼,將這些編解碼器分成encoder/decoder,muxer/demuxer和device三種對象,分別對應(yīng)於編解

17、碼,輸入輸出格式和設(shè)備。在main函數(shù)的開始,就是初始化這三類對象。在avcodec_register_all中,很多編解碼器被註冊,包括視頻的H.264解碼器和X264編碼器等,REGISTER_DECODER(H264,h264);REGISTER_ENCODER(LIBX264,libx264);找到相關(guān)的宏代碼如下#defineREGISTER_ENCODER(X,x)externAVCodecx#_encoder;if(CONFIG_#X#_ENCODER)avcodec_register(&x#_encoder);#defineREGISTER_DECODER(X,x)extern

18、AVCodecx#_decoder;if(CONFIG_#X#_DECODER)avcodec_register(&x#_decoder);這樣就實(shí)際在代碼中根據(jù)CONFIG_#X#_ENCODER這樣的編譯選項(xiàng)來註冊libx264_encoder和h264_decoder,註冊的過程發(fā)生在avcodec_register(AVCodec*codec)函數(shù)中,實(shí)際上就是向全局鍊錶first_avcodec中加入libx264_encoder、h264_decoder特定的編解碼器,輸入?yún)?shù)AVCodec是一個結(jié)構(gòu)體,可以理解為編解碼器的基類,其中不僅包含了名稱,id等屬性,而且包含瞭如下函數(shù)指

19、針,讓每個具體的編解碼器擴(kuò)展類實(shí)現(xiàn)。int(*init)(AVCodecContext*);int(*encode)(AVCodecContext*,uint8_t*buf,intbuf_size,void*data);int(*close)(AVCodecContext*);int(*decode)(AVCodecContext*,void*outdata,int*outdata_size,constuint8_t*buf,intbuf_size);void(*flush)(AVCodecContext*);繼續(xù)追蹤libx264,也就是X264的靜態(tài)編碼庫,它在FFMPEG編譯的時候被引入

20、作為H.264編碼器。在libx264.c中有如下代碼AVCodeclibx264_encoder=.name=libx264,.type=CODEC_TYPE_VIDEO,.id=CODEC_ID_H264,.priv_data_size=sizeof(X264Context),.init=X264_init,.encode=X264_frame,.close=X264_close,.capabilities=CODEC_CAP_DELAY,.pix_fmts=(enumPixelFormat)PIX_FMT_YUV420P,PIX_FMT_NONE,.long_name=NULL_IF_C

21、ONFIG_SMALL(libx264H.264/AVC/MPEG-4AVC/MPEG-4part10),;這裡具體對來自AVCodec得屬性和方法賦值。其中.init=X264_init,.encode=X264_frame,.close=X264_close,將函數(shù)指針指向了具體函數(shù),這三個函數(shù)將使用libx264靜態(tài)庫中提供的API,也就是X264的主要接口函數(shù)進(jìn)行具體實(shí)現(xiàn)。pix_fmts定義了所支持的輸入格式,這裡4:2:0PIX_FMT_YUV420P,/codec=codec;avctx-codec_id=codec-id;avctx-frame_number=0;if(avct

22、x-codec-init)ret=avctx-codec-init(avctx);進(jìn)行具體適配的編解碼器初始化,而這裡的avctx-codec-init(avctx)就是調(diào)用AVCodec中函數(shù)指針定義的具體初始化函數(shù),例如X264_init。在avcodec_encode_video()和avcodec_encode_audio()被output_packet()調(diào)用進(jìn)行音視頻編碼,將同樣利用函數(shù)指針avctx-codec-encode()調(diào)用適配編碼器的編碼函數(shù),如X264_frame進(jìn)行具體工作。從上面的分析,我們可以看到FFMPEG怎麼利用面向?qū)ο髞沓橄缶幗獯a器行為,通過組合和繼承關(guān)係

23、具體化每個編解碼器實(shí)體。設(shè)想要在FFMPEG中加入新的解碼器H265,要做的事情如下:1.在config編譯配置中加入CONFIG_H265_DECODER2.利用宏註冊H265解碼器3.定義AVCodec265_decoder變量,初始化屬性和函數(shù)指針4.利用解碼器API具體化265_decoder的init等函數(shù)指針完成以上步驟,就可以把新的解碼器放入FFMPEG,外部的匹配和運(yùn)行規(guī)則由基類的多態(tài)實(shí)現(xiàn)了。4.X264架構(gòu)分析X264是一款從2004年有法國大學(xué)生髮起的開源H.264編碼器,對PC進(jìn)行彙編級代碼優(yōu)化,捨棄了片組和多參考幀等性能效率比不高的功能來提高編碼效率,它被FFMPEG作

24、為引入的.264編碼庫,也被移植到很多DSP嵌入平臺。前面第三節(jié)已經(jīng)對FFMPEG中的X264進(jìn)行舉例分析,這裡將繼續(xù)結(jié)合X264框架加深相關(guān)內(nèi)容的了解。查看代碼前,還是思考一下對於一款具體的編碼器,怎麼面向?qū)ο蠓治瞿??對熵編碼部分對不同算法的抽象,還有幀內(nèi)或幀間編碼各種估計算法的抽象,都可以作為類來構(gòu)建。在X264中,我們看到的對外API和上下文變量都聲明在X264.h中,API函數(shù)中,關(guān)於輔助功能的函數(shù)在common.c中定義voidx264_picture_alloc(x264_picture_t*pic,inti_csp,inti_width,inti_height);voidx264

25、_picture_clean(x264_picture_t*pic);intx264_nal_encode(void*,int*,intb_annexeb,x264_nal_t*nal);而編碼功能函數(shù)定義在encoder.cx264_t*x264_encoder_open(x264_param_t*);intx264_encoder_reconfig(x264_t*,x264_param_t*);intx264_encoder_headers(x264_t*,x264_nal_t*,int*);intx264_encoder_encode(x264_t*,x264_nal_t*,int*,x

26、264_picture_t*,x264_picture_t*);voidx264_encoder_close(x264_t*);在x264.c文件中,有程序的main函數(shù),可以看作做API使用的例子,它也是通過調(diào)用X264.h中的API和上下文變量來實(shí)現(xiàn)實(shí)際功能。X264最重要的記錄上下文數(shù)據(jù)的結(jié)構(gòu)體x264_t定義在common.h中,它包含了從線程控制變量到具體的SPS、PPS、量化矩陣、cabac上下文等所有的H.264編碼相關(guān)變量。其中包含如下的結(jié)構(gòu)體x264_predict_tpredict_16x1643;x264_predict_tpredict_8x8c43;x264_pred

27、ict8x8_tpredict_8x893;x264_predict_tpredict_4x493;x264_predict_8x8_filter_tpredict_8x8_filter;x264_pixel_function_tpixf;x264_mc_functions_tmc;x264_dct_function_tdctf;x264_zigzag_function_tzigzagf;x264_quant_function_tquantf;x264_deblock_function_tloopf;跟蹤查看可以看到它們或是一個函數(shù)指針,或是由函數(shù)指針組成的結(jié)構(gòu),這樣的用法很想面向?qū)ο裰械膇n

28、terface接口聲明。這些函數(shù)指針將在x264_encoder_open()函數(shù)中被初始化,這裡的初始化首先根據(jù)CPU的不同提供不同的函數(shù)實(shí)現(xiàn)代碼段,很多與可能是彙編實(shí)現(xiàn),以提高代碼運(yùn)行效率。其次把功能相似的函數(shù)集中管理,例如類似intra16的4種和intra4的九種預(yù)測函數(shù)都被用函數(shù)指針數(shù)組管理起來。x264_encoder_encode()是負(fù)責(zé)編碼的主要函數(shù),而其內(nèi)包含的x264_slice_write()負(fù)責(zé)片層一下的具體編碼,包括了幀內(nèi)和幀間宏塊編碼。在這裡,cabac和cavlc的行為是根據(jù)h-param.b_cabac來區(qū)別的,分別運(yùn)行x264_macroblock_writ

29、e_cabac()和x264_macroblock_write_cavlc()來寫碼流,在這一部分,功能函數(shù)按文件定義歸類,基本按照編碼流程圖運(yùn)行,看起來更像面向過程的寫法,在已經(jīng)初始化了具體的函數(shù)指針,程序就一直按編碼過程的邏輯實(shí)現(xiàn)。如果從整體架構(gòu)來看,x264利用這種類似接口的形式實(shí)現(xiàn)了弱耦合和可重用,利用x264_t這個貫穿始終的上下文,實(shí)現(xiàn)信息封裝和多態(tài)。本文大概分析了FFMPEG/X264的代碼架構(gòu),重點(diǎn)探討用C語言來實(shí)現(xiàn)面向?qū)ο缶幋a,雖不至於強(qiáng)行向C靠攏,但是也各有實(shí)現(xiàn)特色,保證實(shí)用性。值得規(guī)劃C語言軟件項(xiàng)目所借鑒?!緟⒖嘉墨I(xiàn)】1.“用例子說明面向?qū)ο蠛忘I向過程的區(qū)別”2.liyu

30、ming1978,“l(fā)iyuming1978的專欄”3.“FFMpeg框架代碼閱讀”UsinglibavformatandlibavcodecMartinBhme(boehmeinb.uni-luebeckREMOVETHIS.de)February18,2004Update(January232009):Bynow,thesearticlesarequiteoutofdate.unfortunately,Ihaventfoundthetimetoupdatethem,butthankfully,othershavejumpedin.StephenDrangerhasamorerecenttu

31、torial,hasanupdatedversionofthecode,andDavidHoerlhasamorerecentupdate.Update(July222004):IdiscoveredthatthecodeIoriginallypresentedcontainedamemoryleak(av_free_packet()wasntbeingcalled).Myapologies-Iveupdatedthedemoprogramandthecodeinthearticletoeliminatetheleak.Update(July212004):Theresanewprerelea

32、seofffmpeg(0.4.9-pre1).Idescribethechangestothelibavformat/libavcodecAPIinthisarticle.Thelibavformatandlibavcodeclibrariesthatcomewithffmpegareagreatwayofaccessingalargevarietyofvideofileformats.Unfortunately,thereisnorealdocumentationonusingtheselibrariesinyourownprograms(atleastIcouldntfindany),an

33、dtheexampleprogramsarentreallyveryhelpfuleither.Thissituationmeantthat,whenIusedlibavformat/libavcodeconarecentproject,ittookquitealotofexperimentationtofindouthowtousethem.HereswhatIlearned-hopefullyIllbeabletosaveothersfromhavingtogothroughthesametrial-and-errorprocess.Theresalsoasmalldemoprogramt

34、hatyoucandownload.ThecodeIllpresentworkswithlibavformat/libavcodecasincludedinversion0.4.8offfmpeg(themostrecentversionasImwritingthis).Ifyoufindthatlaterversionsbreakthecode,pleaseletmeknow.Inthisdocument,Illonlycoverhowtoreadvideostreamsfromafile;audiostreamsworkprettymuchthesameway,butIhaventactu

35、allyusedthem,soIcantpresentanyexamplecode.Incaseyourewonderingwhytherearetwolibraries,libavformatandlibavcodec:Manyvideofileformats(AVIbeingaprimeexample)dontactuallyspecifywhichcodec(s)shouldbeusedtoencodeaudioandvideodata;theymerelydefinehowanaudioandavideostream(or,potentially,severalaudio/videos

36、treams)shouldbecombinedintoasinglefile.Thisiswhysometimes,whenyouopenanAVIfile,yougetonlysound,butnopicture-becausetherightvideocodecisntinstalledonyoursystem.Thus,libavformatdealswithparsingvideofilesandseparatingthestreamscontainedinthem,andlibavcodecdealswithdecodingrawaudioandvideostreams.Openin

37、gaVideoFileFirstthingsfirst-letslookathowtoopenavideofileandgetatthestreamscontainedinit.Thefirstthingweneedtodoistoinitializelibavformat/libavcodec:av_register_all();Thisregistersallavailablefileformatsandcodecswiththelibrarysotheywillbeusedautomaticallywhenafilewiththecorrespondingformat/codecisop

38、ened.Notethatyouonlyneedtocallav_register_all()once,soitsprobablybesttodothissomewhereinyourstartupcode.Ifyoulike,itspossibletoregisteronlycertainindividualfileformatsandcodecs,buttheresusuallynoreasonwhyyouwouldhavetodothat.Nextoff,openingthefile:AVFormatContext*pFormatCtx;constchar*filename=myvide

39、o.mpg;/Openvideofileif(av_open_input_file(&pFormatCtx,filename,NULL,0,NULL)!=0)handle_error();/CouldntopenfileThelastthreeparametersspecifythefileformat,buffersizeandformatparameters;bysimplyspecifyingNULLor0weasklibavformattoauto-detecttheformatanduseadefaultbuffersize.Replacehandle_error()withappr

40、opriateerrorhandlingcodeforyourapplication.Next,weneedtoretrieveinformationaboutthestreamscontainedinthefile:/Retrievestreaminformationif(av_find_stream_info(pFormatCtx)0)handle_error();/CouldntfindstreaminformationThisfillsthestreamsfieldoftheAVFormatContextwithvalidinformation.Asadebuggingaid,well

41、dumpthisinformationontostandarderror,butofcourseyoudonthavetodothisinaproductionapplication:dump_format(pFormatCtx,0,filename,false);Asmentionedintheintroduction,wellhandleonlyvideostreams,notaudiostreams.Tomakethingsniceandeasy,wesimplyusethefirstvideostreamwefind:inti,videoStream;AVCodecContext*pC

42、odecCtx;/FindthefirstvideostreamvideoStream=-1;for(i=0;inb_streams;i)if(pFormatCtx-streamsi-codec.codec_type=CODEC_TYPE_VIDEO)videoStream=i;break;if(videoStream=-1)handle_error();/Didntfindavideostream/GetapointertothecodeccontextforthevideostreampCodecCtx=&pFormatCtx-streamsvideoStream-codec;OK,son

43、owwevegotapointertotheso-calledcodeccontextforourvideostream,butwestillhavetofindtheactualcodecandopenit:AVCodec*pCodec;/FindthedecoderforthevideostreampCodec=avcodec_find_decoder(pCodecCtx-codec_id);if(pCodec=NULL)handle_error();/Codecnotfound/Informthecodecthatwecanhandletruncatedbitstreams-ie,/bi

44、tstreamswhereframeboundariescanfallinthemiddleofpacketsif(pCodec-capabilities&CODEC_CAP_TRUNCATED)pCodecCtx-flags|=CODEC_FLAG_TRUNCATED;/Opencodecif(avcodec_open(pCodecCtx,pCodec)frame_rateandthedenominatorinpCodecCtx-frame_rate_base.Whiletestingthelibrarywithdifferentvideofiles,Inoticedthatsomecode

45、cs(notablyASF)seemtofillthesefieldsincorrectly(frame_rate_basecontains1insteadof1000).Thefollowinghackfixesthis:/Hacktocorrectwrongframeratesthatseemtobegeneratedbysome/codecsif(pCodecCtx-frame_rate1000&pCodecCtx-frame_rate_base=1)pCodecCtx-frame_rate_base=1000;Notethatitshouldntbeaproblemtoleavethi

46、sfixinplaceevenifthebugiscorrectedsomeday-itsunlikelythatavideowouldhaveaframerateofmorethan1000fps.Onemorethinglefttodo:Allocateavideoframetostorethedecodedimagesin:AVFrame*pFrame;pFrame=avcodec_alloc_frame();Thatsit!Nowletsstartdecodingsomevideo.DecodingVideoFramesAsIvealreadymentioned,avideofilec

47、ancontainseveralaudioandvideostreams,andeachofthosestreamsissplitupintopacketsofaparticularsize.Ourjobistoreadthesepacketsonebyoneusinglibavformat,filteroutallthosethatarentpartofthevideostreamwereinterestedin,andhandthemontolibavcodecfordecoding.Indoingthis,wellhavetotakecareofthefactthattheboundar

48、ybetweentwoframescanoccurinthemiddleofapacket.Soundcomplicated?Lucikly,wecanencapsulatethiswholeprocessinaroutinethatsimplyreturnsthenextvideoframe:boolGetNextFrame(AVFormatContext*pFormatCtx,AVCodecContext*pCodecCtx,intvideoStream,AVFrame*pFrame)staticAVPacketpacket;staticintbytesRemaining=0;static

49、uint8_t*rawData;staticboolfFirstTime=true;intbytesDecoded;intframeFinished;/Firsttimewerecalled,setpacket.datatoNULLtoindicateit/doesnthavetobefreedif(fFirstTime)fFirstTime=false;packet.data=NULL;/Decodepacketsuntilwehavedecodedacompleteframewhile(true)/Workonthecurrentpacketuntilwehavedecodedallofi

50、twhile(bytesRemaining0)/DecodethenextchunkofdatabytesDecoded=avcodec_decode_video(pCodecCtx,pFrame,&frameFinished,rawData,bytesRemaining);/Wasthereanerror?if(bytesDecoded0)fprintf(stderr,Errorwhiledecodingframen);returnfalse;bytesRemaining-=bytesDecoded;rawData=bytesDecoded;/Didwefinishthecurrentfra

51、me?Thenwecanreturnif(frameFinished)returntrue;/Readthenextpacket,skippingallpacketsthatarentforthis/streamdo/Freeoldpacketif(packet.data!=NULL)av_free_packet(&packet);/Readnewpacketif(av_read_packet(pFormatCtx,&packet)pix_fmt,pCodecCtx-width,pCodecCtx-height);/Processthevideoframe(savetodisketc.)DoS

52、omethingWithTheImage(pFrameRGB);TheRGBimagepFrameRGB(oftypeAVFrame*)isallocatedlikethis:AVFrame*pFrameRGB;intnumBytes;uint8_t*buffer;/AllocateanAVFramestructurepFrameRGB=avcodec_alloc_frame();if(pFrameRGB=NULL)handle_error();/DeterminerequiredbuffersizeandallocatebuffernumBytes=avpicture_get_size(PI

53、X_FMT_RGB24,pCodecCtx-width,pCodecCtx-height);buffer=newuint8_tnumBytes;/AssignappropriatepartsofbuffertoimageplanesinpFrameRGBavpicture_fill(AVPicture*)pFrameRGB,buffer,PIX_FMT_RGB24,pCodecCtx-width,pCodecCtx-height);CleaningupOK,wevereadandprocessedourvideo,nowallthatsleftforustodoiscleanupafterou

54、rselves:/FreetheRGBimagedeletebuffer;av_free(pFrameRGB);/FreetheYUVframeav_free(pFrame);/Closethecodecavcodec_close(pCodecCtx);/Closethevideofileav_close_input_file(pFormatCtx);Done!SampleCodeAsampleappthatwrapsallofthiscodeupincompilableformishere.Ifyouhaveanyadditionalcomments,pleasecontactmeatboe

55、hmeinb.uni-luebeckREMOVETHIS.de.Standarddisclaimer:Iassumenoliabilityforthecorrectfunctioningofthecodeandtechniquespresentedinthisarticle.聆聽以拼音方式閱讀av_encode函數(shù)主要流程(ffmpeg)av_encode()函數(shù)是FFMpeg中最重要的函數(shù),編解碼和輸出等大部分功能都在此函數(shù)內(nèi)完成,因此有必要詳細(xì)描述一下這個函數(shù)的主要流程。1.inputstreamsinitializing2.outputstreamsinitializing3.encod

56、ersanddecodersinitializing4.setmetadatainformationfrominputfileifrequired.(ex:mp3的id3,在ffmpeg中也叫metadata)5.writeoutputfilesheader6.loopofhandlingeachframea.readframefrominputfile:b.decodeframedatac.encodenewframedatad.writenewframetooutputfile7.writeoutputfilestrailer8.closeeachencoderanddecoderFFMP

57、EGjigufnx1.JinjiFFmpegshygjlzh,zhunhun,yn/shpnbinmjimgngnngwiytdewnzhngdekiyunjijufngn.FFmpegdeKifshjyLinuxcozuxtng,dnshkyziddushcozuxtngzhngbinyhshyng.FFmpegzhchMPEG,DivX,MPEG4,AC3,DV,FLVdng40duzhngbinm,AVI,MPEG,OGG,Matroska,ASFdng90duzhngjim.TCPMP,VLC,MPlayerdngkiyunbfngqduyngdoleFFmpeg.FFmpegzhml

58、xizhyoyulibavcodec,libavformathlibavutildngzml.QzhnglibavcodecyngYcnfngggeencode/decodemkui,libavformatyngycnfngmuxer/demuxermkui,libavutilyngyCnfngnicncozudngfzhxngmkui.Yflashmoviedeflvwnjingshwil,muxer/demuxerdeflvenc.Chflvdec.CwnjinZilibavformatmlxi,encode/decodedempegvideo.Chh263de.Czilibavcodec

59、mlxi.2.Muxer/demuxeryencoder/decoderdngyychshhuMuxer/demuxerhencoder/decoderziFFmpegzhngdeshxindimli,yuxduxingtngddfng,rrzhzuDdechbishmuxerhdemuxerfnbishbtngdejiguAVOutputFormatyAVInputFormat,rencoderHdecoderdushyngdeAVCodecjigu.Muxer/demuxerhencoder/decoderziFFmpegzhngxingtngddfngyu:rzhdushzimain()

60、kishdeav_register_all()hnshnichshhuderzhdushylinbiodexngshbocnziqunjbinlingzhngdeMuxer/demuxershfnbibocnziqunjbinlingAVOutputFormat*first_oformatyAVInputFormat*first_iformatzhngde.Encoder/decoderdushbocnziqunjbinlingAVCodec*first_avcodeczhngde.rzhduynghnshzhzhndefngshzuwikifngdegnggngjikuDemuxerkifn

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論