FFMPEG 3.4.2 - ffmpeg源代碼分析 (一)

1 命令行解析

1.1 命令行例子

  • 命令行包括三個部分:輸入?yún)?shù),輸出參數(shù)凳宙,和全局選項儿捧。
  • -i /home/ron/music/avm.mp4是輸入?yún)?shù),a.mp4是輸出參數(shù)上遥。輸入/輸出參數(shù)可以有專屬的選項,這些選項應(yīng)該緊挨著放在輸入輸出參數(shù)前面争涌。如-vf “split [main][tmp]...[main][flip]”就是輸出參數(shù)a.mp4的選項粉楚。
  • 全局選項的位置不需要限定,因為選項是以選項名字查找的。
  • 可以有多組輸入?yún)?shù)和多組輸出參數(shù)模软。

1.2 解析命令行

split_commandline()負責(zé)解析命令行伟骨。

int split_commandline(OptionParseContext *octx, int argc, char *argv[],
const OptionDef *options,
const OptionGroupDef *groups, int nb_groups);

解析的結(jié)果保存在OptionParseContext中燃异。解析時需要參考OptionDef和OptionGroupDef携狭。OptonDef[]是支持ffmpeg的選項列表,OptionGroupDef[]是支持的組列表回俐,包括輸入類和輸出類逛腿,前者以-i開頭,加上設(shè)備名仅颇。后者只有文件名单默。

下面的類圖顯示了涉及的類:

  • OptionGroup保存一個輸入(或輸出)和它的選項列表。Option表示一個選項忘瓦。
  • OptionParseContext中包括多個OptionGroup搁廓。全局選項保存在global_opts中。所有輸入設(shè)備的選項保存在一個OptionGroupList實例中耕皮,所有輸出設(shè)備的選項保存在另一個實例中境蜕。兩者合起來組成數(shù)組groups.

1.3 split_commandline()

split_commandline()在一個循環(huán)中解析命令行,主要涉及如下函數(shù)凌停。

函數(shù) 功能
find_option() 查詢支持的option列表粱年,檢查當(dāng)前元素是否一個option
add_option() 將option加入一個臨時組。(因為option先于group出現(xiàn)罚拟,還不知道應(yīng)該加入到哪個組逼泣。)
match_group_separator() 查詢支持的group列表,檢查當(dāng)前元素是否是一個Group
finish_group() 設(shè)置臨時組的參數(shù)舟舒,并用它填充OptionParseContext.groups(現(xiàn)在知道應(yīng)該加入哪個組了)

1.4 parse_optgroup()

parse_optgroup()負責(zé)將OptionGroup轉(zhuǎn)換成OptionsContext。

int parse_optgroup(void *optctx, OptionGroup *g)嗜憔;
  • OptionGroup保存的選項值是字符串秃励,而OptionsContext保存的值是由OptionDef定義的實際類型。parse_optgroup()的第一個參數(shù)optctx實際上是OptonsContext吉捶。

下面的類圖顯示了涉及的類:

  • SpecifierOpt保存實際類型的選項夺鲜。OptionsContext有若干個SpecifierOpt數(shù)組的成員。每個specfier數(shù)組保存一類選項呐舔。如filters保存”filter”選項币励。但filter可以是”filter:v”,屬于video珊拼,也可以是“filter:a”食呻,屬于audio。SpecifierOpt.specifier成員就是用來標(biāo)記這個選項應(yīng)該屬于誰的。對于”filter:v”仅胞,SpecifierOpt.specifier就是”v”每辟。
  • 這里順便提一下AVDictionary。解析過程沒有用到它干旧。用戶設(shè)置的選項可能不成功渠欺,而選項的最終值會保存在這里。用av_dict_set()函數(shù)設(shè)置它椎眯。

1.5 parse_optgroup()

parse_optgroup()函數(shù)遍歷OptonGroup中的Option挠将,調(diào)用write_option()將其寫入OptionsContext。

  • 對于基本的選項编整,它的OptionDef中定義了它在OptionsContext的偏移舔稀,所以將字符串轉(zhuǎn)化后,直接寫入就好了闹击。比如”filter:v”镶蹋。
  • 有的選項可能是其他選項的別名。這時它的OptionDef指定了一個回調(diào)函數(shù)赏半。這個函數(shù)會重定向到所指向的選項上去贺归。如”vf”就是”filter:v”的別名,它的OptionDef指定了回調(diào)函數(shù)opt_video_filter()断箫。這個函數(shù)會調(diào)用parse_option()和find_option()查找”filter:v”對應(yīng)的OptionDef拂酣,并再次調(diào)用write_option()。
  • 全局選項仲义。它的OptionDef也定義了一個回調(diào)函數(shù)婶熬。這個函數(shù)直接設(shè)置全局變量。如loglevel埃撵,它的OptionDef定義了opt_loglevel()赵颅。這個函數(shù)調(diào)用av_log_set_level()設(shè)置日志輸出等級。

1.6 MATCH_PER_XXX_OPT()

宏MATCH_PER_TYPE_OPT()和MATCH_PER_STREAM_OPT()用于從OptionsContext讀值暂刘。

  • 前者指定參數(shù)mediatype饺谬,用它跟OptionsContext.spcifier比較,找出option并讀出谣拣。后者指定參數(shù)AVStream募寨,調(diào)用check_stream_specifier(),用AVStream的屬性與OptionContext.specifier匹配森缠,找出option并讀出拔鹰。

2 vf選項解析

2.1 avfilter_graph_parse2()

avfilter_graph_parse2()負責(zé)解析vf選項內(nèi)容。

int avfilter_graph_parse2 (AVFilterGraph *graph, 
const char *filters,
AVFilterInOut **inputs,
AVFilterInOut **outputs);

輸入?yún)?shù)filters是vf選項內(nèi)容贵涵。輸出參數(shù)Inputs是導(dǎo)出的輸入接口列肢,outputs是filters導(dǎo)出的輸出接口恰画。

2.2 filters

如下是filters的一個例子。它來自ffmpeg的文檔:

http://ffmpeg.org/ffmpeg-filters.html#Filtergraph-description

ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT

對應(yīng)FilterGraph的結(jié)構(gòu)示意圖如下例书。 矩形框內(nèi)是vf的內(nèi)容對應(yīng)的部分锣尉。其中split應(yīng)該導(dǎo)出到inputs中,overlay應(yīng)該導(dǎo)出到outputs中决采。

2.3 vf術(shù)語

描述vf的解析過程需要使用一些術(shù)語自沧。其中一部分是關(guān)于vf語法的,另外一部分是關(guān)于生成的FilterGraph結(jié)構(gòu)的树瞭。

上圖標(biāo)出了vf語法的術(shù)語拇厢。

  • 過濾器。過濾器用紅色標(biāo)出晒喷,包括它的名字和參數(shù)孝偎。如”split”,只有名字凉敲。又如”overlay=0:H/2”衣盾,overlay是名字,”0:H/2”是參數(shù)爷抓。名字和參數(shù)用 = 連接副女。
  • 位置點霉祸。有兩類位置點歉眷,有名的和無名的缭裆。有名位置點用綠色標(biāo)出,名字用 [] 包住渤昌,如main, flip, tmp虽抄。無名位置點不必標(biāo)出。
  • 路徑独柑。路徑是一條從位置點開始迈窟,中間過濾器和位置點交錯,在位置點結(jié)束的處理流程忌栅。多條路徑組成整個filtergraph菠隆。中間的位置點都是無名的,開始和結(jié)束的位置點應(yīng)該是有名的狂秘,除非這條路徑在filtergraph的開始和結(jié)束位置。路徑之間用 ; 隔開躯肌。如 [tmp] crop=iw:ih/2:0:0, vflip [flip]者春。以tmp開始,中間包括crop和vflip和一個無名位置點清女,在flip結(jié)束钱烟。有名位置點是該路徑與其他路徑的連接點,所以需要有一個名字來標(biāo)記,而無名位置點只存在該路徑內(nèi)部的兩個過濾器之間拴袭,是隱含的读第,所以不需要名字。

下圖是FilterGraph的結(jié)構(gòu)圖拥刻。

  • FilterGraph是由一系列的過濾器怜瞒,Pad和Pad Link構(gòu)成的。
  • 過濾器來自FilterGraph語法中的過濾器般哼,它有一組In Pad和一組OutPad, Pad與語法中的位置點對應(yīng)吴汪。過濾器之間通過Pad聯(lián)系,Pad Link用來將一個In Pad連接到一個OutPad蒸眠。Pad Link沒有對應(yīng)的語法元素漾橙。
  • Input/Output用于解析過程,也用于保存整個解析的結(jié)果楞卡,以返回給調(diào)用者霜运。open_inputs標(biāo)記當(dāng)前還沒有解析(與其他OutPad連接)的InPad,open_outputs標(biāo)記當(dāng)前還沒有解析的OutPad蒋腮,curr_inputs標(biāo)記當(dāng)前將要解析的InPad淘捡。

2.4 avfilter_graph_parse2()

avfilter_graph_parse2()主要調(diào)用四個函數(shù)進行解析。

函數(shù) 功能
parse_input() 選取若干open_outputs徽惋,以更新curr_inputs
parse_filter() 解析過濾器
link_filter_inouts() 將新的過濾器連入當(dāng)前的curr_inputs案淋,并更新curr_inputs
parse_output() 結(jié)束當(dāng)前的curr_inputs,加入open_outputs险绘。

2.5 解析過程

下面的圖描述了上述語法的解析過程踢京。圖上部的xxx()是當(dāng)前步驟調(diào)用的函數(shù),下面的字符串是語法宦棺,當(dāng)前變色的部分是正在解析的部分瓣距。

  • 解析split
  • 將split連入curr_inputs,當(dāng)前的curr_inputs原來為空代咸,所以更新為split的兩個out pads蹈丸。Pads的數(shù)量可以來自split class指定的默認(rèn)值,或者split的參數(shù)呐芥。這里是前者逻杖。
  • 給split的outpads命名,以便后面引用思瘟。
  • 從open_outputs中選取tmp位置開始一段分支路徑荸百。將tmp標(biāo)記為curr_inputs。
  • 解析crop滨攻。
  • 將crop連入curr_inputs够话。更新curr_inputs蓝翰,指向crop的out pads。
  • 解析vflip女嘲。
  • 將vflip連入curr_inputs畜份。
  • 給vflip的out pads命名為flip,以便后面引用欣尼。當(dāng)前分支路徑結(jié)束爆雹。
  • 從open_outputs中選取main和flip,開始新路徑媒至。
  • 解析overlay顶别。Overlay的pads來自overlay class的默認(rèn)值。
  • 將overlay連入curr_inputs拒啰。
  • 沒有更多的語法元素了驯绎,結(jié)束前將curr_inputs標(biāo)記為open_outputs。注意split的in pads一直沒有解析谋旦,所以它是open_inputs剩失。將open_inputs和open_outputs返回調(diào)用者。

2.6 FilterGraph類

下面的類圖顯示了FilterGraph各元素對應(yīng)的類册着。

  • AVFilterContext表示過濾器拴孤。AVFilter是它的屬性類。
  • AVFilterPad是Pad類甲捏。一個AVFilterContext實例包括AVFilterPad的一組In Pad實例和一組Out Pad實例演熟。AVFilterLink是Pad Link類,它連接兩個AVFilterPad實例司顿。
  • AVFilterLink有一個FFFrameQueue芒粹,用于保存過濾的中間結(jié)果。這時一個frame的數(shù)據(jù)通道大溜。
  • AVFilterContext有一個空間化漆,用于保存該特定類型Filter的私有信息,可以是CropContext钦奋,SplitContext或其他filter的一種座云。
  • AVFilterInOut用于解析過程標(biāo)記open_iputs, open_ouputs和curr_inputs。它沒有直接引用AVFilterPad付材,而是引用AVFilterContext朦拖,和用序號間接指向AVFilterPad。
  • AVFilterGraph和FilterGraph是代表整個FilterGraph的容器類厌衔。

2.7 avfilter_graph_parse2()

下圖是avfilter_graph_parse2()的函數(shù)調(diào)用關(guān)系贞谓。

相關(guān)鏈接

FFMPEG 3.4.2 - ffmpeg源代碼分析 (一)
FFMPEG 3.4.2 - ffmpeg源代碼分析 (二)
FFMPEG 3.4.2 - ffmpeg源代碼分析 (三)
FFMPEG 3.4.2 - ffmpeg源代碼分析 (四)- x264
FFMPEG 3.4.2 - ffplay源代碼分析 (一)
FFMPEG 3.4.2 - ffplay源代碼分析 (二)
FFMPEG 3.4.2 - ffplay源代碼分析 (三)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市葵诈,隨后出現(xiàn)的幾起案子裸弦,更是在濱河造成了極大的恐慌,老刑警劉巖作喘,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件理疙,死亡現(xiàn)場離奇詭異,居然都是意外死亡泞坦,警方通過查閱死者的電腦和手機窖贤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贰锁,“玉大人赃梧,你說我怎么就攤上這事⊥阆ǎ” “怎么了授嘀?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長锣险。 經(jīng)常有香客問我蹄皱,道長,這世上最難降的妖魔是什么芯肤? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任巷折,我火速辦了婚禮,結(jié)果婚禮上崖咨,老公的妹妹穿的比我還像新娘锻拘。我一直安慰自己,他們只是感情好击蹲,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布署拟。 她就那樣靜靜地躺著,像睡著了一般际邻。 火紅的嫁衣襯著肌膚如雪芯丧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天世曾,我揣著相機與錄音缨恒,去河邊找鬼。 笑死轮听,一個胖子當(dāng)著我的面吹牛骗露,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播血巍,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼萧锉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了述寡?” 一聲冷哼從身側(cè)響起柿隙,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤叶洞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后禀崖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衩辟,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年波附,在試婚紗的時候發(fā)現(xiàn)自己被綠了艺晴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡掸屡,死狀恐怖封寞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仅财,我是刑警寧澤狈究,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站满着,受9級特大地震影響谦炒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜风喇,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一宁改、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧魂莫,春花似錦还蹲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至倦始,卻和暖如春斗遏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鞋邑。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工诵次, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人枚碗。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓逾一,卻偏偏與公主長得像,于是被迫代替她去往敵國和親肮雨。 傳聞我的和親對象是個殘疾皇子遵堵,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容