天天看點

從 FFmpeg 性能加速到端雲一體媒體系統優化

衆所周知,FFmpeg 作為開源音視訊處理的瑞士軍刀,以其開源免費、功能強大、友善易用的特點而十分流行。音視訊處理的高計算複雜度使得性能加速成為 FFmpeg 開發永恒的主題。阿裡雲視訊雲媒體處理系統廣泛借鑒了開源 FFmpeg 在性能加速方面的經驗,同時根據自身産品和架構進行了端雲一體媒體系統架構設計與優化,打造出高性能、高畫質、低延時的端雲協同的實時媒體服務。

從 FFmpeg 性能加速到端雲一體媒體系統優化

阿裡雲智能視訊雲進階技術專家李忠,目前負責阿裡雲視訊雲 RTC 雲端媒體處理服務以及端雲一體的媒體處理性能優化,是 FFmpeg 官方代碼的維護者及技術委員會委員,參與過多個音視訊開源軟體的開發。

本次分享的議題是《從 FFmpeg 性能加速到端雲一體媒體系統優化》,主要介紹三個方面的内容:

一、FFmpeg 中常見的性能加速方法

二、雲端媒體處理系統

三、端 + 雲的協同媒體處理系統

FFmpeg 中常見的性能加速方法

音視訊開發者目前主要面臨的挑戰之一是對計算量的高需求,它不隻是單任務算法優化,還涉及到很多硬體、軟體、排程、業務層,以及不同業務場景的挑戰。其次端、雲、不同裝置、不同網絡,這些綜合的複雜性現狀,要求開發者要做系統性的架構開發與優化。

FFmpeg 是一個非常強大的軟體,包括音視訊的解碼編碼、各種音視訊的 Filter 、各種協定的支援。作為一個開源軟體 FFmpeg 主要的 License 是 GPL 或者 LGPL,程式設計語言是 C 和彙編。它還提供了很多打開即用的指令行工具,比如轉碼的 ffmpeg 、音視訊解析的 ffprobe、播放器 ffplayer。其核心的 Library 有負責編解碼的 libavcodec、處理音視訊的 libavfilter 、支援各種協定的 libavformat。

從 FFmpeg 性能加速到端雲一體媒體系統優化

FFmpeg 開發社群中,音視訊性能優化是一個永恒的主題,其開源代碼裡也提供了非常多的經典性能優化的實作方法,主要是通用加速、CPU 指令加速、GPU 硬體加速。

從 FFmpeg 性能加速到端雲一體媒體系統優化

通用加速

通用加速主要是算法優化、IO 讀寫優化、多線程優化。算法優化的目标是在不增加 CPU Usage 的前提下提高性能。最典型是編解碼器的各種快速搜尋算法,它可以在精度隻有少數損失的情況下,大幅優化編碼速度。各種前後處理 Filter 的算法也有類似的方法,也可以通過算法合并來減少備援的計算,達到性能優化的目的。

下圖是一種典型的降噪與銳化卷積模闆,它需要做 3 乘 3 的矩陣卷積。我們可以看到,這裡的銳化模闆跟平滑模闆是類似的,對于同時要做降噪和銳化的操作,隻要在平滑的模闆的基礎上面做減法可以達到銳化化模闆的結果,可以減少備援的計算,提升性能。當然算法優化也存在局限性,比如編解碼算法有精度上的損失,還可能需要犧牲空間複雜度換取時間複雜度。

從 FFmpeg 性能加速到端雲一體媒體系統優化

第二種性能優化的方法是 IO 讀寫優化,常見方法是利用 CPU 預讀取來改善 Cache Miss 。上圖是通過兩種讀寫的方法達到相同的運算結果,按行讀寫的方法比按列讀寫快,主要原因是 CPU 在按行讀寫時可做預讀取,在處理目前像素的時候,CPU 已經預讀本行的其他像素,可以大大加速 IO 讀寫的速度,提高性能。另外可以盡量減少 Memory Copy,因為視訊處理 YUV 非常大,每讀一幀對性能的損耗比較大。

從 FFmpeg 性能加速到端雲一體媒體系統優化

通用加速的多線程優化主要是利用 CPU 多核做多線程的并行加速來大幅提升性能。上圖中左下角的圖表表明随着線程數的增加,性能提升了 8 倍。随之也會産生一個問題,普遍被使用的多線程加速,線程數是不是越多越好呢?

答案是 No 。

首先,因為 CPU 核數限制,多線程等待和排程,多線程優化會碰到性能瓶頸。以左下角的圖表為例,線程數等于 10 的加速比跟線程數等于 11 時非常接近,可以看出多線程優化存在邊際效應的遞減,同時也會帶來延時和記憶體消耗的增加(尤其是普遍使用的幀間多線程)。

第二,幀間(Frame level)多線程需要建立 Frame Buffer Pool 進行多線程并行,這需要緩沖很多幀,對于延遲非常敏感的媒體處理,比如低延時直播、RTC ,會帶來比較大的負面效應。與之對應的是,FFmpeg 支援幀内(Slice level)的多線程,可以把一幀劃分成多個 Slice,然後做并行處理,這樣能夠有效避免幀間的 Buffer 延遲。

第三,當線程數增多,線程同步和排程的成本也會增加。以右下圖的一個 FFmpeg Filter 加速為例,随着線程數的增加,CPU Cost 也在明顯增加, 且圖表曲線末端開始往上傾斜,這表明其成本的增加變得更明顯。

CPU 指令加速

CPU 指令加速即 SIMD(單指令多資料流)指令加速。傳統通用的寄存器和指令,一條指令處理一個元素。但一條 SIMD 指令可以處理一個數組中的多個元素,進而達到非常顯著的加速效果。

現在主流的 CPU 架構都有對應的 SIMD 指令集。X86 架構 SIMD 指令包括 MMX 指令、SSE 指令、AVX2、AVX-512 指令。其中 AVX-512 的一條指令可處理 512 個 bits,加速效果非常明顯。

從 FFmpeg 性能加速到端雲一體媒體系統優化

FFmpeg 社群的 SIMD 指令寫法包括内聯彙編、手寫彙編。FFmpeg 社群不允許使用 intrinsic 程式設計,原因是它對編譯器的版本存在依賴,不同編譯器編譯出的代碼及其加速效果也是不一緻的。

雖然 SIMD 指令有好的加速效果,但它也存在一定的局限性。

首先,很多的算法不是并行處理的,不能進行 SIMD 指令優化。

其次,程式設計難度比較大。彙編程式設計的難度就要大些,另外 SIMD 指令對程式設計有一些特殊的要求,比如 Memory 對齊。AVX-512 要求 Memory 最好能夠做到 64 位元組對齊,如果沒有對齊的話,可能會有性能上的損耗,甚至會引起程式的 Crash。

我們看到不同的 CPU 廠商都在做指令集競賽,支援的位寬越來越多,從 SSE 到 AVX2 再到 AVX-512 ,位寬顯著增加。那位寬是不是越寬越好?上圖可以看到 X265 編碼 AVX 512 相對 AVX 2 的提速情況,AVX 512 的位寬是 AVX 2 位寬的兩倍,但性能提升實際上往往遠達不到一倍,甚至達不到 10%。在某些情況下,AVX 512 的性能會比 AVX 2 還要低。

原因是什麼呢?

首先,一次性的資料輸入可能并沒有 512 bits 這麼多,可能隻有 128 bits 或者是 256 bits。

第二,有很多的複雜運算步驟(如編碼器)不能做指令集的并行。

第三,AVX 512 功耗較高,會引起 CPU 的降頻,導緻 CPU 整體處理的速度會有所下降。我們看上圖的 X265 ultrafast 檔次編碼,AVX 512 的編碼比 AVX 2 還要慢。(詳見:

https://networkbuilders.intel.com/docs/accelerating-x265-the-hevc-encoder-with-intel-advanced-vector-extensions-512.pdf

硬體加速

FFmpeg 比較主流的硬體加速是 GPU 加速。硬體加速接口分為兩大塊,一是硬體廠商提供不同的加速接口。英特爾主要提供 QSV 和 VAAPI 的接口,英偉達提供 NVENC、CUVID、NVDEC 、VDPAU,AMD 提供 AMF 和 VAAPI 的接口。二是不同的 OS 廠商提供不同的加速接口和方案,比如 Windows 的 DXVA2,安卓的 MediaCodec ,蘋果的 VideoToolbox 。

從 FFmpeg 性能加速到端雲一體媒體系統優化

硬體加速可以顯著提升媒體處理的性能,但是它也會帶來一些問題。

第一,硬體的編碼品質受限于硬體的設計及成本,硬體編碼的品質往往是會比軟體編碼品質差。但硬體編碼有非常明顯的性能優勢,可以用性能去換編碼品質。下圖的例子可看出,硬體編碼器運動搜尋的視窗比較小,導緻編碼品質的下降。其解決方法是 HME 算法,在搜尋視窗比較小的情況下,先把比較大的 Picture 縮放到非常小的 Picture,在這個 Picture 上做運動搜尋,再逐級做搜尋和放大,這樣可以顯著提高運動搜尋的範圍,然後找到最比對的塊,進而改善編碼品質。

從 FFmpeg 性能加速到端雲一體媒體系統優化

第二,硬體加速的 CPU 和 GPU 的 Memory Copy 性能互動會帶來性能的下降。

從 FFmpeg 性能加速到端雲一體媒體系統優化

CPU 和 GPU 的互動不僅僅是簡單的資料搬移過程,實際上要做對應的像素的格式轉換,比如 CPU 是 I420 linear 格式,GPU 擅長矩陣運算,采用 NV12 Tiled 格式。

這種記憶體格式的轉化,會帶來明顯的性能損耗。可以通過建構純硬體的 Pipeline ,有效的規避 CPU/GPU Memory 互動的問題。當 CPU 和 GPU 必須互動的情況下,可以采取 Fast Memory Copy 的方式,采用 GPU 去做 Memory Copy ,加速這一過程。

下圖是性能優化的總結大圖。除了前面提到一些優化方法外,用戶端上的媒體處理還有一些特殊性,比如手機 CPU 是大小核架構,線程排程如果排程到小核上,它的性能會明顯比大核要差,導緻性能的不穩定。

從 FFmpeg 性能加速到端雲一體媒體系統優化

另外很多的算法不管如何優化,在某些機型上就是無法跑通,這時要在業務政策上面做優化,比如制定黑白名單,不在支援名單的機器就不開啟該算法。

雲端媒體處理系統優化

對于媒體處理來說分為兩大挑戰,一是雲端的成本優化,二是用戶端裝置适配及相容。下圖是雲端媒體處理的典型系統:包括單機層、叢集排程層、業務層。

從 FFmpeg 性能加速到端雲一體媒體系統優化

單機層包括 FFmpeg Pipeline 處理架構、編解碼、硬體層。以雲端轉碼系統為例,它的核心技術名額包括畫質、處理速度、延時、成本。畫質方面,阿裡雲視訊雲獨創了窄帶高清的技術以及 S265 編碼技術,可以顯著改善編碼畫質。處理速度和延時優化方面,我們廣泛借鑒 FFmpeg 性能加速方法,比如 SIMD 指令、多線程加速以及異構計算的支援。成本是一個比較複雜的系統,它會包括排程層、單機層、業務層,需要進行快速的彈性擴縮容,單機資源精确畫像,減少單任務的計算成本。

雲端成本優化

雲端成本優化的核心是圍繞三條曲線去做優化,針對單任務實際資源消耗、單任務資源預估配置設定、總資源池這三條曲線分别做對應的優化。在優化過程中需要面對四個現實的問題:

第一,在視訊雲的業務裡,業務多樣性的趨勢會越來越明顯,業務包括點播、直播、RTC、 AI 編輯部、雲剪輯。業務多樣性帶來的挑戰是如何将多種業務共用一個資源池做混跑。

第二,大顆粒的任務越來越多,幾年前主流視訊是 480P,而現在的主流是 720P、1080P 的處理任務,未來可以預見 4K、8K、VR 這樣的媒體處理會越來越越多,這帶來挑戰是對單機性能的渴求會越來越大。

第三,排程層需要預估每個任務的資源消耗,但單機任務的實際消耗會受到非常多因素的影響。視訊内容的複雜度,不同算法參數,多程序的切換,都會影響任務資源消耗。

第四,編碼的前處理會越來越多,同時一個轉碼任務需要做多碼率或者多分辨的輸出。各種前處理(畫質增強 / ROI 識别 / 超幀率 / 超分等)都會大幅增加的處理成本。

我們看下從整體思路來看怎麼去優化這三條曲線。

從 FFmpeg 性能加速到端雲一體媒體系統優化

實際任務的資源消耗優化,主要方法是每個任務的性能優化、算法的性能優化、Pipeline 架構優化。

資源的配置設定核心目标就是使上圖的黃色曲線能夠不斷地貼近黑色曲線,減少資源配置設定的浪費。當資源配置設定不足的情況下,可以做算法的自動升降級,以免線上任務出現卡頓,比如編碼器的 preset 從 medium 檔降低為 fast 檔。

對于總資源池優化,首先可以看到黃色曲線有波峰波谷,如果目前點播任務處在波谷的狀态,可以把直播的任務調過來,這樣可以在整個池子的峰值沒有變化的情況下跑更多的任務。第二,總資源池怎麼樣能夠快速的彈性,在一定時間視窗内能夠快速釋放掉資源,降低資源池消耗,這也是排程需要考慮的成本優化的核心。

下面展開談下一些優化方法。

從 FFmpeg 性能加速到端雲一體媒體系統優化

CPU 機型優化的主要目标是增加 CPU 單機的吞吐量,減少 CPU 碎片。上圖描述了多核 CPU 帶來的優勢。但多核 CPU 也可能會帶來多個 NUMA node 直接的記憶體通路,進而導緻性能下降。

單機資源精确畫像

單機資源精确畫像主要目标是能夠精确知道每個任務它需要多少資源,它是一個系統性的工具,需要有畫質評估的工具、計算資源統計的工具、需要包括各種多場景複雜的視訊集、以及能夠去做各種計算資源和疊代回報,修正成本計算的消耗,指導算法的自适應升降級。

從 FFmpeg 性能加速到端雲一體媒體系統優化

1-N 架構優化

一個轉碼任務可能要輸出不同的分辨率和碼率,傳統的方法是起 N 個獨立的一轉一的程序。這樣的架構顯而易見會有一些問題,比如備援的解碼計算和編碼前處理。一個優化方法是把這些任務做整合,從 N 到 N 的轉碼變成一到 N 的轉碼。這樣視訊解碼和編碼前處理都隻需要做一次,進而達到成本優化的目标。

從 FFmpeg 性能加速到端雲一體媒體系統優化

1-N 轉碼也會帶來新的挑戰。FFmpeg 轉碼工具支援 1-N 轉碼,但是各子產品是串行處理的,單個一轉 N 任務的速度會比單個一轉一的任務慢。第二,排程的挑戰,單任務資源顆粒度會更大,所需要資源的配置設定也更難估計。第三,算法效果的差異,因為有的視訊的前處理可能是在 Scale 之後,對于一到 N 的轉碼架構會把前處理放到 Scale 之前。媒體處理的流程變化會引起算法效果的差别(通常這個問題不是特别大,因為在 Scale 前處理沒有畫質損失,在 Scale 前做處理反而是更好的)。

端 + 雲的協同媒體處理系統

端側媒體處理的優勢是可利用手機端現成的算力來降低成本,是以理想情況是充分利用各種端側的算力,每個算法都做非常好的性能優化、端側的适配,在每個端都能零成本的落地。

但是理想很美滿,現實很骨感。會有四大現實問題:

第一,端側适配的困難。需要大量的 OS 硬體機型适配。

第二,算法接入的困難。現實情況下不可能把所有的算法在所有端上都進行優化,是以端側的性能瓶頸會導緻算法落地困難。

第三,體驗優化的困難。客戶會有不同的 SDK ,或者說阿裡雲的 SDK 也會有不同的版本,SDK 本身存在碎片化導緻一些方案難以落地。比如非标的 H264 編碼,實際上 H265 編解碼算法的落地也遇到挑戰,一些裝置并不支援 H265。

第四,使用者接入的困難,客戶更新 SDK 或替換 SDK 的周期比較漫長。

面對這樣的現實,我們提出雲和端協同的媒體處了解決方案。主要思路是通過雲上處理 + 端側渲染的方案,達到比較好的使用者體驗。

從 FFmpeg 性能加速到端雲一體媒體系統優化

雲和端的協同的媒體處理主要類型是轉碼類和預覽類。轉碼類是單向的資料流。預覽類需要把各種流先推到雲端,再加各種特效,然後再拉回來給主播看效果是不是符合他的預期,最後再從 CDN 推到觀衆端。

這樣的方案也會碰到一些挑戰。首先,雲端處理會有計算成本的增加(當然可以有各種方式優化,因為用戶端沒有直接體感)。第二,延時會增加,雲端的處理增加了鍊路的延時。

随着 RTC 技術越來越成熟,通過 RTC 低延時的傳輸協定,再加雲端的各種成本優化,可以低成本 / 低延時地支援雲上的媒體處理,打造一個雲加端的實時媒體處理服務。阿裡雲視訊雲建構的 RTC 實時媒體處理服務 RMS,可以做到高性能、低成本、高畫質、低延時、更智能的雲端協同媒體處理的方案。

從 FFmpeg 性能加速到端雲一體媒體系統優化

上面的左圖是 RMS 整體架構圖,分為 Pipeline 層、子產品層、硬體适配層,硬體層。Pipeline 可以做各種業務場景的組裝子產品層,子產品層是音視訊處理的核心,實作各種 AI 或者是低延時高畫質的效果。

端加雲的協同媒體處理:賦能 RTC+

以剪輯雲渲染為例,傳統的剪輯方案要保證多端體驗一緻性及流暢的性能是比較困難的。我們的思路是端上隻做指令的下發,視訊的合成、渲染都是在雲上實作,可以支援非常多的特效,也能夠保證多端的效果一緻性。

從 FFmpeg 性能加速到端雲一體媒體系統優化

我們看下剪輯雲渲染的 Pipeline。雲渲染的網頁負責信令下發,通過排程層把剪輯指令轉發到 RMS 媒體處理引擎做雲上媒體處理的渲染,合成之後再編碼通過 SFU 推流,最後在剪輯的網頁端看剪輯效果。上圖的 Demo 可以看到,網頁把很多 Track 合成一個 Track ,4 乘 4 的宮格在端上處理的話,在低端機跑起來是比較費力的,但雲能夠輕易跑出這樣的效果。

高碼率低清晰度的視訊流到雲端後,通過阿裡雲視訊雲的雲端窄帶高清技術處理,可以達到更高清晰度更低碼率的目标。下圖 Demo 中啟用窄帶高清後,視訊的清晰度有明顯的提升(碼率也有顯著下降)。

從 FFmpeg 性能加速到端雲一體媒體系統優化

同時利用 RTC 低延時,再加 AI 特效的處理,可以産生很多有意思的場景。把真人的流推到雲端,雲端做卡通人像的輸出處理,然後輸出卡通人像做實時的交流,在會場的觀衆互相看到的是各自的卡通人像。

搭配雲端的摳圖技術很容易就能實作虛拟的教育場景和虛拟的會議室場景。比如虛拟課堂,可以把人像摳到 PPT 裡增加整個效果示範的沉浸感。虛拟會議室裡不同的參會者通過摳圖把他們排列到虛拟的會議室場景裡來,達到虛拟會議室的效果。

掃碼入群和作者一起探讨音視訊技術

擷取更多視訊雲行業最新資訊👇

從 FFmpeg 性能加速到端雲一體媒體系統優化
「視訊雲技術」你最值得關注的音視訊技術公衆号,每周推送來自阿裡雲一線的實踐技術文章,在這裡與音視訊領域一流工程師交流切磋。公衆号背景回複【技術】可加入阿裡雲視訊雲産品技術交流群,和業内大咖一起探讨音視訊技術,擷取更多行業最新資訊。

繼續閱讀