




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Good is good, but better carries it.精益求精,善益求善。FFMPEG流程分析-FFMPEG架構分析1.簡介FFmpeg是一個集錄製、轉換、音/視頻編碼解碼功能為一體的完整的開源解決方案。FFmpeg的開發是基於Linux操作系統,但是可以在大多數操作系統中編譯和使用。FFmpeg支持MPEG、DivX、MPEG4、AC3、DV、FLV等40多種編碼,AVI、MPEG、OGG、Matroska、ASF等90多種解碼.TCPMP,VLC,MPlayer等開源播放器都用到了FFmpeg。FFmpeg主目錄下主要有libavcodec、libavformat和lib
2、avutil等子目錄。其中libavcodec用於存放各個encode/decode模塊,libavformat用於存放muxer/demuxer模塊,libavutil用於存放內存操作等輔助性模塊。以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中的實現代碼裡
3、,有許多相同的地方,而二者最大的差別是muxer和demuxer分別是不同的結構AVOutputFormat與AVInputFormat,而encoder和decoder都是用的AVCodec結構。muxer/demuxer和encoder/decoder在FFmpeg中相同的地方有:二者都是在main()開始的av_register_all()函數內初始化的二者都是以鍊錶的形式保存在全局變量中的muxer/demuxer是分別保存在全局變量AVOutputFormat*first_oformat與AVInputFormat*first_iformat中的。encoder/decoder都是保
4、存在全局變量AVCodec*first_avcodec中的。二者都用函數指針的方式作為開放的公共接口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的接口是一樣的,只不過二者分別只實現encoder和decoder函數: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)函數中,通過執行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結構的定義如下: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.其他主要數據結構4.1AVFormatContextAVFormatContext是FFMpeg格式轉換過程中實現輸入和輸出功能、保存相關數據的主要結構。每一個輸入和輸出文件,都在如下定義的指針數組
10、全局變量中有對應的實體。staticAVFormatContext*output_filesMAX_FILES;staticAVFormatContext*input_filesMAX_FILES;對於輸入和輸出,因為共用的是同一個結構體,所以需要分別對該結構中如下定義的iformat或oformat成員賦值。structAVInputFormat*iformat;structAVOutputFormat*oformat;對一個AVFormatContext來說,這二個成員不能同時有值,即一個AVFormatContext不能同時含有demuxer和muxer。在main()函數開頭的pars
11、e_options()函數中找到了匹配的muxer和demuxer之後,根據傳入的argv參數,初始化每個輸入和輸出的AVFormatContext結構,並保存在相應的output_files和input_files指針數組中。在av_encode()函數中,output_files和input_files是作為函數參數傳入後,在其他地方就沒有用到了。4.2AVCodecContext保存AVCodec指針和與codec相關數據,如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()函數中,匹配到正確的AVInputFormatdemuxer後,通過av_open_input_stream()
13、函數中調用AVInputFormat的read_header接口來執行flvdec.c中的flv_read_header()函數。在flv_read_header()函數內,根據文件頭中的數據,創建相應的視頻或音頻AVStream,並設置AVStream中AVCodecContext的正確的codec_type值。codec_id值是在解碼過程中flv_read_packet()函數執行時根據每一個packet頭中的數據來設置的。4.3AVStreamAVStream結構保存與數據流相關的編解碼器,數據段等信息。比較重要的有如下二個成員:AVCodecContext*codec;/*priv_
14、data=asf_st;4.4AVInputStream/AVOutputStream根據輸入和輸出流的不同,前述的AVStream結構都是封裝在AVInputStream和AVOutputStream結構中,在av_encode()函數中使用。AVInputStream中還保存的有與時間有關的信息。AVOutputStream中還保存有與音視頻同步等相關的信息。4.5AVPacketAVPacket結構定義如下,其是用於保存讀取的packet數據。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()函數中,調用AVInputFormat的(*read_packet
16、)(structAVFormatContext*,AVPacket*pkt)接口,讀取輸入文件的一幀數據保存在當前輸入AVFormatContext的AVPacket成員中。-FFMPEG是目前被應用最廣泛的編解碼軟件庫,支持多種流行的編解碼器,它是C語言實現的,不僅被集成到各種PC軟件,也經常被移植到多種嵌入式設備中。使用面向對象的辦法來設想這樣一個編解碼庫,首先讓人想到的是構造各種編解碼器的類,然後對於它們的抽象基類確定運行數據流的規則,根據算法轉換輸入輸出對象。在實際的代碼,將這些編解碼器分成encoder/decoder,muxer/demuxer和device三種對象,分別對應於編解
17、碼,輸入輸出格式和設備。在main函數的開始,就是初始化這三類對象。在avcodec_register_all中,很多編解碼器被註冊,包括視頻的H.264解碼器和X264編碼器等,REGISTER_DECODER(H264,h264);REGISTER_ENCODER(LIBX264,libx264);找到相關的宏代碼如下#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);這樣就實際在代碼中根據CONFIG_#X#_ENCODER這樣的編譯選項來註冊libx264_encoder和h264_decoder,註冊的過程發生在avcodec_register(AVCodec*codec)函數中,實際上就是向全局鍊錶first_avcodec中加入libx264_encoder、h264_decoder特定的編解碼器,輸入參數AVCodec是一個結構體,可以理解為編解碼器的基類,其中不僅包含了名稱,id等屬性,而且包含瞭如下函數指
19、針,讓每個具體的編解碼器擴展類實現。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*);繼續追踪libx264,也就是X264的靜態編碼庫,它在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,將函數指針指向了具體函數,這三個函數將使用libx264靜態庫中提供的API,也就是X264的主要接口函數進行具體實現。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);進行具體適配的編解碼器初始化,而這裡的avctx-codec-init(avctx)就是調用AVCodec中函數指針定義的具體初始化函數,例如X264_init。在avcodec_encode_video()和avcodec_encode_audio()被output_packet()調用進行音視頻編碼,將同樣利用函數指針avctx-codec-encode()調用適配編碼器的編碼函數,如X264_frame進行具體工作。從上面的分析,我們可以看到FFMPEG怎麼利用面向對象來抽象編解碼器行為,通過組合和繼承關係
23、具體化每個編解碼器實體。設想要在FFMPEG中加入新的解碼器H265,要做的事情如下:1.在config編譯配置中加入CONFIG_H265_DECODER2.利用宏註冊H265解碼器3.定義AVCodec265_decoder變量,初始化屬性和函數指針4.利用解碼器API具體化265_decoder的init等函數指針完成以上步驟,就可以把新的解碼器放入FFMPEG,外部的匹配和運行規則由基類的多態實現了。4.X264架構分析X264是一款從2004年有法國大學生髮起的開源H.264編碼器,對PC進行彙編級代碼優化,捨棄了片組和多參考幀等性能效率比不高的功能來提高編碼效率,它被FFMPEG作
24、為引入的.264編碼庫,也被移植到很多DSP嵌入平台。前面第三節已經對FFMPEG中的X264進行舉例分析,這裡將繼續結合X264框架加深相關內容的了解。查看代碼前,還是思考一下對於一款具體的編碼器,怎麼面向對象分析呢?對熵編碼部分對不同算法的抽象,還有幀內或幀間編碼各種估計算法的抽象,都可以作為類來構建。在X264中,我們看到的對外API和上下文變量都聲明在X264.h中,API函數中,關於輔助功能的函數在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);而編碼功能函數定義在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函數,可以看作做API使用的例子,它也是通過調用X264.h中的API和上下文變量來實現實際功能。X264最重要的記錄上下文數據的結構體x264_t定義在common.h中,它包含了從線程控制變量到具體的SPS、PPS、量化矩陣、cabac上下文等所有的H.264編碼相關變量。其中包含如下的結構體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;跟踪查看可以看到它們或是一個函數指針,或是由函數指針組成的結構,這樣的用法很想面向對像中的in
28、terface接口聲明。這些函數指針將在x264_encoder_open()函數中被初始化,這裡的初始化首先根據CPU的不同提供不同的函數實現代碼段,很多與可能是彙編實現,以提高代碼運行效率。其次把功能相似的函數集中管理,例如類似intra16的4種和intra4的九種預測函數都被用函數指針數組管理起來。x264_encoder_encode()是負責編碼的主要函數,而其內包含的x264_slice_write()負責片層一下的具體編碼,包括了幀內和幀間宏塊編碼。在這裡,cabac和cavlc的行為是根據h-param.b_cabac來區別的,分別運行x264_macroblock_writ
29、e_cabac()和x264_macroblock_write_cavlc()來寫碼流,在這一部分,功能函數按文件定義歸類,基本按照編碼流程圖運行,看起來更像面向過程的寫法,在已經初始化了具體的函數指針,程序就一直按編碼過程的邏輯實現。如果從整體架構來看,x264利用這種類似接口的形式實現了弱耦合和可重用,利用x264_t這個貫穿始終的上下文,實現信息封裝和多態。本文大概分析了FFMPEG/X264的代碼架構,重點探討用C語言來實現面向對象編碼,雖不至於強行向C靠攏,但是也各有實現特色,保證實用性。值得規劃C語言軟件項目所借鑒。【參考文獻】1.“用例子說明面向對象和麵向過程的區別”2.liyu
30、ming1978,“liyuming1978的專欄”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函數主要流程(ffmpeg)av_encode()函數是FFMpeg中最重要的函數,編解碼和輸出等大部分功能都在此函數內完成,因此有必要詳細描述一下這個函數的主要流程。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. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 讲述“活着”的中国法制史知到智慧树章节测试课后答案2024年秋曲阜师范大学
- 广州医保知识培训课件
- 2025四川湖山电器股份有限公司招聘化专员等岗位79人笔试参考题库附带答案详解
- 2024重庆水务环境控股集团有限公司招聘6人笔试参考题库附带答案详解
- 2024福建省轻纺(控股)有限责任公司秋季招聘3人笔试参考题库附带答案详解
- 2025年上半年兰州市安宁区政务服务中心招考编外聘用人员易考易错模拟试题(共500题)试卷后附参考答案
- 2025年上半年信阳市新县事业单位招考工作人员和公安文职人员易考易错模拟试题(共500题)试卷后附参考答案
- 2025年上半年佛山市社会组织培育发展中心招考易考易错模拟试题(共500题)试卷后附参考答案
- 2025年上半年人民日报社图书馆招聘2人易考易错模拟试题(共500题)试卷后附参考答案
- 2025年上半年云南红河州开远市事业单位招聘工作人员人员易考易错模拟试题(共500题)试卷后附参考答案
- 2024年环北部湾广西水资源配置有限公司招聘考试真题
- 2025年黑龙江建筑职业技术学院单招职业技能测试题库完美版
- 第16课《有为有不为 》课件-2024-2025学年统编版语文七年级下册
- 第一单元时、分、秒(说课稿)-2024-2025学年三年级上册数学人教版
- 地理-浙江省杭州八县市2024学年高二第一学期期末学业水平测试试题和答案
- 《康复工程学》课件-第一讲 康复工程概论
- DeepSeek:从入门到精通
- 天津2025年天津中德应用技术大学辅导员岗位招聘7人笔试历年参考题库附带答案详解
- 2025年无锡职业技术学院高职单招职业适应性测试近5年常考版参考题库含答案解析
- 2025年铜材拉丝项目可行性研究报告
- 2025四川宜宾市高县县属国企业第一次招聘3人易考易错模拟试题(共500题)试卷后附参考答案
评论
0/150
提交评论