大家好,我是騰訊云的趙軍,同時(shí)我也是FFmpeg決策委員會(huì)委員、開源愛好者。在2018年成為FFmpeg maintainer,2019年入選 FFmpeg 決策委員會(huì)(voting committee),具備豐富的基于Linux 的Router/Gateway 開發(fā)經(jīng)驗(yàn),并持續(xù)關(guān)注Linux 在網(wǎng)絡(luò)方面發(fā)展。曾開發(fā)基于Linux 的高清/ 標(biāo)清H.264/MPEG2視頻解碼器及圖像處理平臺(tái)。曾在Intel DCG/NPG 負(fù)責(zé)基于FFmpeg以及Intel平臺(tái)上的視頻編碼/解碼/轉(zhuǎn)碼、視頻后處理、視頻分析的硬件加速的工作。目前在騰訊云負(fù)責(zé)視頻云的系統(tǒng)優(yōu)化相關(guān)工作,除去支持公司內(nèi)部的項(xiàng)目開發(fā)以外,也在持續(xù)向FFmpeg社區(qū)提交patch,同時(shí)也倡導(dǎo)引領(lǐng)同事以開放的心態(tài)擁抱開源。
今天的演講將分為明眸、智眸、云剪和開源四個(gè)部分來講解,其中明眸主要針對(duì)音視頻編解碼與畫質(zhì)增強(qiáng)方案,智眸主要涉及智能媒體檢索、分析和審核方案,云剪主要提供在線媒體內(nèi)容生產(chǎn)方案,而開源則是本次演講中將重點(diǎn)介紹的內(nèi)容。
音視頻發(fā)展現(xiàn)狀
在騰訊云團(tuán)隊(duì)看來,目前音視頻技術(shù)的發(fā)展現(xiàn)狀更偏向于清晰、流暢和品質(zhì)這三者的博弈,對(duì)于視頻來說,體育賽事、游戲等領(lǐng)域?qū)χ辈デ逦纫蟛粩嗵嵘瑖艺咭苍诠膭?lì)4K和8K的增長,這些因素使得超高清晰度視頻內(nèi)容成為音視頻技術(shù)發(fā)展的重要方向,與此同時(shí),人們開始追求更多的趣味性和附加能力,但硬件計(jì)算能力或者軟件性能并沒完全跟上,這使得成像品質(zhì)以及其他附屬能力所需要的計(jì)算能力也位于了問題之列;一如既往的,無論是4G還是即將到來的5G時(shí)代,網(wǎng)絡(luò)的制約在能預(yù)計(jì)的時(shí)間內(nèi),依然也還是一個(gè)不可忽視的影響因素之一。
1. 音視頻技術(shù)+AI,打造從內(nèi)容生產(chǎn)、極速高清到視頻識(shí)別分析全鏈路產(chǎn)品
1.1 明眸:極速高清-智能動(dòng)態(tài)編碼
提到極速高清就不得不聊聊視頻編碼,上圖從Codec和系統(tǒng)工具的角度,以MPEG組織為基準(zhǔn)描述了發(fā)展歷史,圖片下方是容器格式,做過工程的人都了解,很多時(shí)候相比Codec,容器格式有時(shí)會(huì)暴露很多的工程問題。圖中色塊分別代表不同階段的技術(shù)發(fā)展,紅色部分已經(jīng)是歷史,橙色部分表示過渡,藍(lán)色部分更像是現(xiàn)在和不遠(yuǎn)的將來的交界。
明眸主體由場(chǎng)景識(shí)別、前置處理和編碼算法動(dòng)態(tài)優(yōu)化三部分組成,場(chǎng)景識(shí)別主要是對(duì)場(chǎng)景進(jìn)行切分,根據(jù)場(chǎng)景預(yù)設(shè)編碼模板。其次前置處理主要解決的問題是多次轉(zhuǎn)碼帶來的副作用,最后在基于以上兩部分的前提下做編碼算法的動(dòng)態(tài)優(yōu)化。
當(dāng)場(chǎng)景識(shí)別、前置處理和編碼算法動(dòng)態(tài)優(yōu)化三部分做完之后,我們可以得到一些基本的結(jié)論,由于直播客戶更在意主觀質(zhì)量,明眸以VMAF為目標(biāo)做開發(fā)。簡(jiǎn)單提及一下,騰訊云在對(duì)VMAF和PSNR做比較時(shí)發(fā)現(xiàn),如果VMAF的分?jǐn)?shù)在70分左右甚至更高,VMAF的分?jǐn)?shù)會(huì)與PSNR正相關(guān),倍數(shù)關(guān)系大概在2.5-3倍之間,反之,我們也發(fā)現(xiàn),PSNR分?jǐn)?shù)比較高時(shí),VMAF的分?jǐn)?shù)不一定高,所以我們認(rèn)為,以VMAF為目標(biāo)的優(yōu)化也大概率的涵蓋了PSNR的目標(biāo)值。明眸可以在相同碼率下將VMAF評(píng)分提升10+,同VMAF分下碼率節(jié)省可以達(dá)到30%左右。當(dāng)然VMAF也存在一些問題,比如對(duì)小分辨率的適配并不是很好,這可能與Netflix自身由點(diǎn)播內(nèi)容居多,并且片源的質(zhì)量都非常高有關(guān)。
1.2 智眸:智能媒體生產(chǎn)平臺(tái)
從上圖可以看到目前視頻AI比較通用的流程,視頻源從左向右邊,解碼之后如果要做對(duì)象探測(cè)會(huì)有一個(gè)Scale和CSC,如果做Tracking會(huì)向下走,如果做ROI coordinates會(huì)向上進(jìn)行正常的解碼。這個(gè)流程圖看似簡(jiǎn)單,但在工程中需要各種各樣的考量,其中的每一個(gè)點(diǎn)都可能會(huì)成為潛在的性能瓶頸。
以上是智眸的一些基本能力,包括人像、聲音/文字、圖像以及基本物體的識(shí)別、智能分析和審核,它可以根據(jù)需求靈活組合,圖中也列出了很多的應(yīng)用場(chǎng)景。
在客戶使用和對(duì)接時(shí),基本上是以Rest API做對(duì)接,圖中清晰展示了整個(gè)流程運(yùn)行起來的全貌。
以上是騰訊云在視頻識(shí)別和視頻分析中要解決的問題,其中智能拆條需要根據(jù)內(nèi)容或關(guān)鍵人物出現(xiàn)進(jìn)行拆分,智能集錦應(yīng)用在體育場(chǎng)景中較多,比如制作進(jìn)球或得分集錦。
1.3 云剪:助力提升視頻生產(chǎn)效能
如果將視頻當(dāng)作一條鏈路來考慮,可以看到視頻從最初上傳到制作處理,再到內(nèi)容管理、傳輸分發(fā),最后在終端播放,其中制作與處理部分騰訊云存在一些技術(shù)缺失,因此騰訊云做了云剪來彌補(bǔ)這部分的功能,主要目的是讓用戶實(shí)現(xiàn)在云端不需要SDK就可以對(duì)視頻數(shù)據(jù)做處理,這種場(chǎng)景中比較具有代表性的是電競(jìng)行業(yè),它的素材可能在PC端已經(jīng)做好,不用在移動(dòng)端進(jìn)行處理。
云剪目前也是一個(gè)把騰訊云已有的能力打包,用以解決行業(yè)痛點(diǎn)的一個(gè)綜合性質(zhì)的產(chǎn)品。
2. 擁抱開源,以開放的心態(tài)加速技術(shù)升級(jí)
2.1 FFmpeg簡(jiǎn)介
從事多媒體行業(yè),基本沒有人可以完全忽視 FFmpeg這個(gè)開源界中最流行的多媒體庫,F(xiàn)Fmpeg庫有著多平臺(tái)的支持,無論是服務(wù)器Linux、移動(dòng)端Android、PC 端的MAC以及Windows都可以使用,使用方式分為tools和C libraries兩種,tools包括ffmpeg、ffplay、ffprobe等,另一種方式則是C libraries,但C libraries場(chǎng)景時(shí)候,我們也發(fā)現(xiàn)它在某些場(chǎng)景下缺乏一定的靈活性。
2.2 開源與協(xié)同
在剛進(jìn)騰訊云時(shí),大的部門中有38個(gè)repo都叫FFmpeg,這可能也是業(yè)務(wù)快速發(fā)展過程中所經(jīng)歷的一些痛處。我們開始嘗試做一個(gè)統(tǒng)一版本,嘗試將部門將不同repo中,比較有價(jià)值的部分提煉出來,構(gòu)造一個(gè)內(nèi)部完整而統(tǒng)一的Repo;另一方面,我們認(rèn)為,既然使用的FFmpeg來自開源,我們?cè)谒厦娴墓ぷ鞒晒,也?yīng)該讓它最終返回到開源社區(qū)去。這樣,一方面可以使得原來內(nèi)部的FFmpeg庫統(tǒng)一,減少內(nèi)部的重復(fù)性工作,另一方面對(duì)于社區(qū)來說騰訊云及時(shí)將Feature、Bug Fix、性能優(yōu)化、文檔更新和samples反饋給它,在這個(gè)過程中,也順勢(shì)打造了一個(gè)非常完整流暢的工作流程,用于支持內(nèi)部的開發(fā),也用于反饋給開源社區(qū)。
2.3 接口與框架
提及接口和框架的問題,首先想到的是上面這段話,簡(jiǎn)單說來,猶如為院子造墻,什么放在墻外,什么放在墻內(nèi),門開在什么地方,還要提防想著把墻推倒的人;在實(shí)際的項(xiàng)目中,也有類似的問題,如果項(xiàng)目要和別人合作,首先需要明確兩人的職責(zé),這是最容易出問題的部分;具體到FFmpeg,一方面,它需要解決怎么屏蔽不同的Os、硬件平臺(tái)和Codec細(xì)節(jié),并保持使用過程中能靈活構(gòu)建media pipeline的能力,與此同時(shí),在AI大潮中,它也面臨著是否需要集成Deep Learning框架到AVFilter模塊的這種現(xiàn)實(shí)問題。
2.4 性能之痛
性能在多媒體技術(shù)中一直是一個(gè)永恒的話題,例如壓縮技術(shù)在十年間可以提升50%的壓縮率,但復(fù)雜度卻會(huì)提升10倍以上,這對(duì)計(jì)算能力提出了一個(gè)非常大的挑戰(zhàn)。我們知道,所有優(yōu)化的前提是理解算法與數(shù)據(jù)流向,并且有Profiling的數(shù)據(jù)作為支撐,除了算法上面的提升以外,也需要更好更充分的利用已有的硬件資源。大部分情況下,硬件性能優(yōu)化是在CPU和GPU上完成。以FFmpeg為例,它的CPU優(yōu)化在上體現(xiàn)在多線程和SIMD優(yōu)化兩個(gè)方面,在解碼過程中使用了基于Frame和Slice的線程以及更為底層的SIMD優(yōu)化,在Filter中只用了基于Slice的線程與SIMD。GPU一般來說有二個(gè)優(yōu)化方向,一個(gè)是專有硬件,比如Intel GPU中的QSV部分,一塊是通用計(jì)算加速和3D渲染,分別是CUDA,以及嘗試和CUDA對(duì)抗的OpenCL,還有歷史悠久的OpenGL以及它的繼任者Vulkan。
2.4.1 CPU加速
CPU的加速中,首先想到的是線程,本質(zhì)上說,使用線程能力優(yōu)化是想充分釋放多核的能力,目前對(duì)于大部分的PC來說以4線程或8線程居多,但對(duì)于Sever來說核數(shù)可能會(huì)更多,目前的環(huán)境多以48或96線程為主,因此在不互相影響的前提下調(diào)動(dòng)多核的積極性是CPU加速所要解決的首要問題。在FFmpeg中,以AVFilter為例,他有一個(gè)AVFILTER_FLAG_SLICE_THREADS的標(biāo)識(shí),很多實(shí)現(xiàn)上,是把一個(gè)Frame中不相關(guān)的數(shù)據(jù)以行或者列的方式做加速,以我的經(jīng)驗(yàn)來看,如果程序出現(xiàn)性能問題,首先應(yīng)該考慮的問題是是否使用了CPU的多線程能力。第二種CPU加速方式是SIMD加速,SIMD匯編優(yōu)化形式一般有intrinsics、inline assembly、hand-written assembly三種,F(xiàn)Fmpeg匯編優(yōu)化以第三種為主,這是由于intrinsics在封裝是有些潛在的性能損失,相同的功能用intrinsics和hand-written assembly去解決,前者可能會(huì)引入一些性能損失;而inline assembly的問題在于比較難以跨平臺(tái),比如Linux和Windows,而FFmpeg的跨平臺(tái)是它的目標(biāo)之一。所以,現(xiàn)在FFmpeg社區(qū)更偏向于hand-written assembly方式,另外,大部分的hand-written assembly匯編優(yōu)化其實(shí)是以x264的匯編優(yōu)化庫為基礎(chǔ)做的,并且選擇nasm為匯編器(不選擇yasm是由于它沒有支持最新的一些CPU指令)。
提及了多線程優(yōu)化,我們也以使用者的角度看著,使用FFmpeg API的時(shí)候,如何設(shè)置線程。對(duì)于FFmpeg來說,大部分的情況下可能并未考慮在高負(fù)載/重耦合場(chǎng)景下運(yùn)行的情況,F(xiàn)Fmpeg在解碼時(shí)的默認(rèn)策略是根據(jù)CPU的核數(shù)創(chuàng)建線程,目前大部分的PC設(shè)備都是四核八線程的配置,但一個(gè)典型的數(shù)據(jù)中心的Server有48核96線程,但解碼器實(shí)際上并沒法同時(shí)使用這么多的核,這種情況下,需要自己控制解碼線程,而非使用FFmpeg的默認(rèn)策略,我們也遇到過使用FFmpeg API時(shí)候,默認(rèn)創(chuàng)建超過1200個(gè)線程的問題。第三個(gè)是BUG的問題,F(xiàn)Fmpeg集成時(shí)很多時(shí)候只在PC端測(cè)試過,并未在擁有這么多核的服務(wù)器上測(cè)試,使得FFmpeg的VP9encoder當(dāng)時(shí)甚至?xí)诙嗪朔魃蟘rash,種種事情表明,在多核服務(wù)器下使用FFmpeg,需要在多線程上做更細(xì)致的控制,而僅僅只使用其默認(rèn)線程策略。另外,還有一點(diǎn)要提及,線程并不只是影響性能,它也會(huì)影響圖像質(zhì)量,我們也發(fā)現(xiàn),在編碼時(shí)候,隨著編碼器使用的線程數(shù)目的增加,其VMAF分?jǐn)?shù)可能會(huì)降低。在服務(wù)器端,使用FFmpeg這類框架時(shí)候,如何在保證性能以及圖像質(zhì)量的前提下,怎么更好的控制線程(使用CPU的計(jì)算能力),是個(gè)非常有趣的問題。
在性能優(yōu)化過程中,SIMD優(yōu)化也面臨著一些挑戰(zhàn),一是在使用SIMD優(yōu)化時(shí)需要將算法改造成適合SIMD的算法,這并不總是一件容易的事情,其次需要考慮不同硬件之間的移植性。另外,對(duì)于SIMD一般都有內(nèi)容對(duì)齊的需求,且算法上要盡量避免分支使得數(shù)據(jù)可以流化,同時(shí),算法上的一些操作并不都被SIMD指令支持(相較而言x86的SIMD指令要比arm更為豐富一些);另外,還有考慮不同硬件之間浮點(diǎn)算法的精確性,種種挑戰(zhàn),使得SIMD的優(yōu)化的使用上并不特別的便利。
2.4.2 GPU優(yōu)化
當(dāng)時(shí)我基于英特爾的GPU做整個(gè)轉(zhuǎn)碼鏈路的優(yōu)化,Codec解碼主要有兩套plugins,一套是基于MSDK,類似FFmpeg集成x264后依賴第三方去做解碼。第二套思路是基于VAAPI的interface去做,使得整個(gè)硬件加速Codec是FFmpeg自身的一部分。除了做Codec的加速以外,團(tuán)隊(duì)同時(shí)還用OpenCL做了一些AVFiltrer的優(yōu)化,這兩種優(yōu)化之間各有優(yōu)勢(shì)。順帶提及一句,即使GPU已經(jīng)加速,在API的角度依然無法判斷是否使用了GPU資源,這個(gè)問題目前只能歸結(jié)到FFmpeg API的設(shè)計(jì)缺陷。另外,關(guān)于更多GPU的優(yōu)化問題,可以參考我之前的一些文章(FFmpeg在Intel GPU上的硬件加速與優(yōu)化)。