FFmpeg深度學(xué)習(xí)模塊2019年小結(jié)

FFmpeg是什么,通俗的說(shuō),在看片子的時(shí)候,需要用到視頻播放器,而很多視頻播放器的底層用的就是FFmpeg。這是我在2019年在FFmpeg深度學(xué)習(xí)模塊中所做事情的總結(jié),由于我在19年是這個(gè)模塊的主要貢獻(xiàn)者,所以,這個(gè)總結(jié)也差不多就是FFmpeg深度學(xué)習(xí)模塊的現(xiàn)狀總結(jié)了。

在2018年的時(shí)候,Pedro Arthur (bygrandao@gmail.com)帶著學(xué)生Sergey Lavrushkin (dualfal@gmail.com)完成了一個(gè)GSoC項(xiàng)目,將TensorFlow引入FFmpeg,并且增加了一個(gè)超分辨率(super resolution)的video filer(vf_sr.c),來(lái)演示如何使用深度學(xué)習(xí)模型。

這里簡(jiǎn)單介紹一下GSoC,即Google Summer of Code,是Google公司贊助的項(xiàng)目,每年一次,到2020年將是第16次,用來(lái)鼓勵(lì)學(xué)生參與各種開(kāi)源項(xiàng)目的實(shí)際代碼開(kāi)發(fā)(不限于Google的開(kāi)源項(xiàng)目,當(dāng)然此項(xiàng)目也需要Google的同意),還有一定的經(jīng)濟(jì)資助。如果你是學(xué)生身份,強(qiáng)烈建議盡量參加。

回到FFmpeg,在18年的時(shí)候,我參與了這個(gè)模塊的討論,當(dāng)時(shí)我的想法是,支持各種深度學(xué)習(xí)框架的模型,根據(jù)傳入模型的類(lèi)型,再調(diào)用相應(yīng)的深度學(xué)習(xí)框架在后端加載執(zhí)行。在今天事后來(lái)看,這個(gè)建議存在的一個(gè)問(wèn)題是,有些深度學(xué)習(xí)框架沒(méi)有提供C接口(可能提供了C++接口),而FFmpeg社區(qū)要求使用C接口,這個(gè)問(wèn)題我現(xiàn)在也還沒(méi)有解決方法。另外,我當(dāng)時(shí)還建議把這個(gè)作為單獨(dú)的模塊,或者起碼放在libavutil中,但是,最終還是放在了libavfilter目錄下面,因?yàn)榭紤]到目前主要是被filter調(diào)用。

最后完成的代碼支持深度學(xué)習(xí)框架TensorFlow,F(xiàn)Fmpeg可以接受TensorFlow的網(wǎng)絡(luò)模型文件(.pb),準(zhǔn)備好輸入輸出后,再在后端調(diào)用TensorFlow的C庫(kù)文件加載并執(zhí)行這個(gè)模型。另外,考慮到某些系統(tǒng)可能沒(méi)有TensorFlow,所以,在FFmpeg中增加了native cpu path的支持,即可以fallback到cpu path,這個(gè)native后端也定義了一套模型文件格式,即native model。為什么在native模式下不是直接接受.pb文件呢,因?yàn)樵诓皇褂玫谌綆?kù)(比如protobuf)的情況下解析加載pb文件也是挺麻煩的事情,需要很多的代碼支持,沒(méi)必要也不應(yīng)該在FFmpeg中增加這樣的代碼。

由于其中不少代碼都是hard code形式寫(xiě)死的,所以,我在2019年的時(shí)候,開(kāi)始發(fā)patch來(lái)改進(jìn)這里的代碼,并且思考和實(shí)踐如何讓FFmpeg的用戶(hù)將深度學(xué)習(xí)的相關(guān)功能用起來(lái)。大致總結(jié)如下。

  • 調(diào)整了深度學(xué)習(xí)模塊的目錄結(jié)構(gòu)

雖然我把這個(gè)寫(xiě)在第一點(diǎn),剛好可以順便先做一個(gè)框架性的介紹。但是,實(shí)際是在發(fā)了不少patch被社區(qū)初步信任后,才做的目錄調(diào)整,這也是參加開(kāi)源社區(qū)工作的一個(gè)經(jīng)驗(yàn),僅供參考。

原先所有的代碼文件都直接放在libavfilter目錄下面,考慮到支持native mode將會(huì)需要很多代碼,所以,在libavfilter目錄下創(chuàng)建了子目錄dnn,除了將dnn_interface.h這個(gè)接口文件繼續(xù)直接放在libavfilter目錄下,其他的dnn相關(guān)文件都被移到了dnn子目錄中,當(dāng)然,基于dnn的filter文件還是直接在libavfilter目錄中。如下圖所示。


FFmpeg中深度學(xué)習(xí)架構(gòu)圖

其中,vf_sr.c就是前面介紹的2018年GSoC完成的超分辨率filter;而去除雨點(diǎn)等功能的vf_derain.c則是劉歧(網(wǎng)名悟空,Steven Liu lq@chinaffmpeg.org)帶著學(xué)生Xuewei Meng (xwmeng96@gmail.com)完成的GSoC2019項(xiàng)目;vf_dnn_processing.c是我做的基于dnn模型的一個(gè)通用的圖像處理filter,希望所有只改變AVFrame內(nèi)容的功能都可以用這一個(gè)filter來(lái)實(shí)現(xiàn),目前已支持RGB和Gray等格式,而YUV相關(guān)格式的支持還在完成中;vf_dnn_analytic.c則是我設(shè)想中的filter,可以基于dnn模型從frame中提取一些信息,比如目標(biāo)檢測(cè)、人臉識(shí)別等等,可能會(huì)擴(kuò)展成多個(gè)不同用途的filter,初步計(jì)劃在2020年完成。

在libavfilter/dnn目錄下,目前有兩部分的內(nèi)容,一是調(diào)用TensorFlow C library的接口層,二是實(shí)現(xiàn)native layer的代碼,如果以后有需要,還可以增加更多的深度學(xué)習(xí)框架的C庫(kù)支持。因?yàn)镈NN interface接口層的存在,dnn的實(shí)現(xiàn)和基于dnn的filter之間是解耦的。

我在2019年在FFmpeg中的主要工作,除了從頭開(kāi)始支持ROI encoding外,就是從dnn filter到DNN interface再到dnn實(shí)現(xiàn)的全覆蓋。filter和dnn實(shí)現(xiàn)互為表里,相互促進(jìn),目前兩者都還處于比較初始的階段,我希望可以做好初始推動(dòng)力的作用,使得兩者可以盡快形成良性循環(huán)正反饋,可以吸引更多的開(kāi)發(fā)者和用戶(hù)參加進(jìn)來(lái),也歡迎您的參與!

  • 模型文件轉(zhuǎn)換的python腳本

在初始代碼中,native模型文件的生成方法,是根據(jù)相應(yīng)的TensorFlow模型,手工一句句地寫(xiě)代碼將模型導(dǎo)出到文件中。如果TF模型略有調(diào)整,也必須手工修改相應(yīng)的代碼,再重新生成native模型文件。這樣的方法,無(wú)法擴(kuò)展也不實(shí)用。所以,我寫(xiě)了個(gè)python腳本,輸入是TF模型文件,輸出是native模型文件,并且在native模型文件中增加了文件頭和版本號(hào)等信息。這個(gè)腳本文件目前只支持當(dāng)前FFmpeg支持的layer,需要繼續(xù)完善。

  • native layer代碼的重構(gòu)

在原來(lái)代碼中,native模型的加載由一個(gè)函數(shù)完成,我將其拆分為了一個(gè)入口函數(shù)和若干子函數(shù),每個(gè)子函數(shù)對(duì)應(yīng)一個(gè)layer的加載。在原來(lái)代碼中,所有nativer layer的執(zhí)行函數(shù)放在一個(gè)文件中。我為每個(gè)layer在libavfilter/dnn目錄下創(chuàng)建了一個(gè)新文件,對(duì)應(yīng)的加載函數(shù)和執(zhí)行函數(shù)都放在這個(gè)文件中,實(shí)現(xiàn)了不同layer之間在文件級(jí)別的隔離。在入口函數(shù)中,則用函數(shù)指針數(shù)組的方式來(lái)直接調(diào)用相應(yīng)layer的函數(shù),不使用if/else或者switch的方式,避免了大量的重復(fù)代碼。

所以,現(xiàn)在如果要修改某個(gè)layer的實(shí)現(xiàn),只需要修改相應(yīng)的一個(gè)文件即可,不太會(huì)造成side effect。如果要增加一個(gè)layer,則只需要增加一個(gè)新的代碼文件(.c和.h),然后注冊(cè)到函數(shù)指針數(shù)組中即可,也不會(huì)存在誤操作影響到已有代碼的功能。

  • 增加FATE測(cè)試

FATE (FFmpeg Automated Testing Environment) 是FFmpeg社區(qū)開(kāi)發(fā)的自動(dòng)化測(cè)試框架,要持續(xù)維護(hù)一個(gè)良好質(zhì)量的軟件項(xiàng)目,快速的自動(dòng)化測(cè)試(包括單元測(cè)試、回歸測(cè)試等等)都是必不可少的看門(mén)人角色,非常重要。基于FATE框架,我為每一個(gè)navier layer都增加了單元測(cè)試,以后有新的layer加入,只要依葫蘆畫(huà)瓢再增加就可以了。我也為vf_dnn_processing增加了測(cè)試。由于當(dāng)前native layer中的卷積層conv2d的性能不佳,所以,還無(wú)法為vf_sr和vf_derain增加FATE測(cè)試,否則,耗時(shí)太久,反而影響了自動(dòng)化測(cè)試的初始目的。

  • DNN interface接口調(diào)整

    • 在使用TF后端的時(shí)候,之前代碼要求模型的輸入變量的名字必須是x,輸出變量名字必須是y。我調(diào)整了接口,輸入輸出變量名字可以在filter層次指定。
    • 在使用native后端的時(shí)候,之前代碼將第一個(gè)layer的輸入作為模型的輸入,將最后一個(gè)layer的輸出作為模型的輸出。我增加了name的支持,可以通過(guò)name字符串來(lái)找到模型的輸入輸出變量,也使得行為和TF一致。
    • 之前代碼假設(shè)模型的輸入輸出都是float32格式的數(shù)據(jù)。我調(diào)整了數(shù)據(jù)結(jié)構(gòu),使得float32和uint8格式都可以指定。
    • 將native模型的輸出變量從一個(gè)增加到了多個(gè),以適合目標(biāo)檢測(cè)等模型的要求。
    • 增加了一個(gè)查詢(xún)接口,在模型文件被加載后,F(xiàn)Fmpeg就可以查詢(xún)模型的輸入格式,比如width、height、channel和format等信息,方便檢查模型文件是否正確,或者做一些諸如圖片縮放等預(yù)處理。
  • 增加了更多native layer的支持

為了上述DNN接口層的調(diào)整,需要有實(shí)際的例子來(lái)表明這些調(diào)整是需要的,也為了不產(chǎn)生regression問(wèn)題,需要增加更多nativer layer。另外,從項(xiàng)目本身來(lái)說(shuō),增加更多的nativer layer以支持更多的深度學(xué)習(xí)模型,比如目標(biāo)檢測(cè)等模型,也是題中應(yīng)有之義。在19年下半年,帶了上海交大密歇根學(xué)院5位同學(xué)的本科畢業(yè)設(shè)計(jì)課程,增加了一些native layer的實(shí)現(xiàn),但沒(méi)有upstream。

  • 為native mode引入Operand的概念

在之前的代碼中,nativer layer是依次順序排列,第i層的輸出就是第i+1層的輸入,無(wú)法支持一個(gè)層的輸出作為多個(gè)層的輸入,也不支持一個(gè)層的輸入來(lái)自多個(gè)層。增加了Operand操作數(shù)概念后,層和層之間用Operand連接,就可以實(shí)現(xiàn)這些分支合并功能。如何使得Operand更好的節(jié)約內(nèi)存、減少內(nèi)存拷貝,目前還只有想法,尚未代碼實(shí)現(xiàn)。

  • 已有代碼的一些bug的fix等

這部分工作,趙軍Jun Zhao (barryjzhao@tencent.com)、劉歧Steven Liu( lq@chinaffmpeg.org)還有l(wèi)eozhang (leozhang@qiyi.com)、Zhao Zhili (quinkblack@foxmail.com)等也做了不少貢獻(xiàn)。話(huà)說(shuō)這樣的統(tǒng)計(jì)功能怎么做啊,我是手工地肉眼看了一遍,大概率會(huì)遺漏什么,,,如有漏人,請(qǐng)告訴我。

最后,感謝老板的支持和社區(qū)的認(rèn)可,我在2019年底成為了FFmpeg深度學(xué)習(xí)模塊的maintainer。另外,我的大部分代碼都是Pedro Arthur (bygrandao@gmail.com) review的,在此也表示感謝。

以上內(nèi)容是本人業(yè)余時(shí)間興趣之作,限于水平,差錯(cuò)難免,僅代表個(gè)人觀(guān)點(diǎn),和本人任職公司無(wú)關(guān)。

本文首發(fā)于微信公眾號(hào):那遁去的一

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,197評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,415評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,104評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,884評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,647評(píng)論 6 408
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,130評(píng)論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,366評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,887評(píng)論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,737評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,939評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,174評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,586評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,827評(píng)論 1 283
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,608評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,914評(píng)論 2 372

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