OneVPL与FFmpeg/GStreamer硬件编解码器
相對軟件Codec來說,人們對硬件Codec的應用并不太熟悉。本次LiveVideoStackCon 2021 上海站大會我們邀請到了來自英特爾的媒體工程師——許廣新,來為我們分享Intel在硬件編解碼器中的最新研發進展。
文 / 許廣新
整理 / LiveVideoStack
謝謝大家,下午來參加討論。我是Intel開發者軟件工程部門的工程師許廣新,我們team主要負責多媒體框架,我們與開源FFmpeg/GStreamer社區有良好的合作關系。FFmpeg官方Twitter曾經贊揚過我們說:“如果這些大公司都能像Intel一樣,都能給他們貢獻pacth,該有多好。”我們team也有GStreamer在中國的第一個maintainer。
今天我們先給大家做一些基本的介紹,然后討論Intel最新的硬件功能,第三,會讓大家看一下Intel的獨立顯卡在HEVC的transcode的質量和性能。第四,我會簡單介紹一下FFmpeg的hardwork codecs的工作流程。第五,介紹我們提供的兩個Post Process,一個是FFmpeg DNN,一個是LibXCam。最后我會介紹如何在Intel的GPU上面,搭建一個優化的硬件視頻pipeline,怎么發現硬件管線的問題。
圖中就是一個基本的FFmpeg/GStreamer的pipeline,一般會包括一個基本的輸入、video parser、video decoder、video process、video encoder,以及最后的輸出。今天我們會分享video parser和video codec的內容。
接下來簡單介紹一下,為什么會使用硬件codec?其中一個好處是,低延時和高吞吐。我記得我年輕的時候,解碼一個VCD 352*240分辨率,就需要買一個單獨的解碼卡,但是現在買一個筆記本,解碼幾十路、近百路的1080p視頻,可能一點問題都沒有。硬件codec還有一個好處是,CPU的使用率會降低,會大量節省電源的消耗。但是它也有不好的地方。一個是,它很難跟軟件encoder的最高質量模式競爭。因為客戶對一般硬件編碼器不是很熟悉,有很多廠商從下到下都是閉環的,很難去做定制化。但是,在Intel的平臺上,我們從上到下,從driver到中間件、FFmpeg都是開源的,能在一定程度上幫助大家。大家需要對Intel硬件有一定的了解,才能去做定制化。所以,硬件codec大概的用途有video play,現在市面上看到的播放器都會用硬件來播放,很少用軟件,否則CPU就會全部占用了。還有流媒體、云游戲的用途,以及對時延要求非常高的video encoder。
圖中是對Intel在Linux上的媒體API的簡單介紹,在介紹后面內容之前需要對此有個基本的了解。最下面是軟件層,是video driver。在此之上,我們提供了一個叫VAAPI的接口,這就是Intel在Linux上面的硬件抽象層。基本上Linux系統都會有這個硬件抽象層,比如Android、Chrome上都有。但是,這個硬件抽象層,一般人會覺得非常復雜,因為需要做surface管理,最后要decode到slice 層,才能使用到這個API。所以,Intel又提供了另外一套API,就是oneVPL,你可以認為它就是以前的MediaSDK。這一層主要的接口就是,一幀的碼流進去,然后一幀解碼后的數據出來,因為它是基于VAAPI的二次開發,所以它能夠提供更強大的編碼參數,并做了一些跟硬件相關的質量調整,能夠提供更高質量的編碼碼流。
從去年到今年,我們可以看到的Intel硬件可能都是基于Xe的lowPower架構的產品,這個架構有三種平臺。一種是Tiger Lake,或者是其續任產品,它就是我們的集成顯卡。另外一種是獨立顯卡DG1,一些筆記本上可能會使用到,他也有單獨的顯卡。還有一種是SG1,它其實就是4個DG1,是專門給服務器用的,所以可以期待有3~4倍的DG1的性能。
對于這一代的Xe LowPower的媒體引擎來說,我們有什么改進呢?比如,達到了以前兩倍以上的encode和decode的輸入和輸出,新加了AV1的硬件decode,也加了HEVC SCC的擴展,可以達到4K~8K的60fps的視頻播放,也支持HDR/杜比、12bit端到端的視頻pipeline。
圖中就是Tiger Lake、DG1和SG1所有支持的功能。對于基本上市面上能見到的decoder,它們都能支持。對于encoder來說,它們也能支持。特別是針對HEVC,功能比前幾代都有很大的提升,后面我會詳細介紹。對于VPP來說,它們基本上都能支持。
接下來,我們看看獨立顯卡DG1的transcode的質量。圖中縱軸的原點是x265 medium,縱軸是bit-rate的節省,意思是比x265 medium好5%左右。橫軸就是我們測的27個碼流,在各個碼流上DG1的表現。我們在DG1上提供了兩種編碼器。一種是VDENC,這其實是固定管線的、不可配置的,又把它叫作Low power模式,會節約電力。另一種是VME,是用處理單元去做一些事情,最后可以得到更好的碼率。從這27個碼流看來,碼率基本上都會比x265 medium要好,有的會好到30%。
左圖是對27個碼流做了加權平均值,有很多點很有趣。第一個點是,前幾代的產品,Intel以前賣過叫作VCA卡的產品。我們這一代的DG1相比VCA卡,最差的情況也會好37%以上,然后平均下來,所有的點都會比x265 medium都要好。第一個點是VDENC的high Quality模式,這個點上要比x265 medium要好5.1%左右。右圖是transcode能到達的路數,即比x265 medium好5.1%的情況下,可以達到13路的1080p的30fps。如果你愿意犧牲2~3%的bit-rate的話,就使用Balanced模式,對應于第二個柱狀圖,大概能夠達到18路的1080p的30fps。第一個柱狀圖是最好的,其實跟x265 slow差不多,大概差1、2點,在這個點上,可以達到2路的1080p的30fps。
接下來我們簡單介紹FFmpeg VAAPI和VPL,圖中是架構圖。最底下是Graphic HW,然后是driver,以及硬件抽象層。在硬件抽象層的基礎上,FFmpeg會提供VAAPI的backend,直接調用VAAPI。然后,我們也會做一些硬件相關優化,就提供了一個oneVPL或media SDK,然后會被QSV plugin調用。它們都會被libavcodec接口調用,最后FFmpeg提供統一的接口給外部使用。
圖中展示了一些細節。左邊是decode,一般一個碼流進來,會經過Demux、video decode、video Fliter等。Decode細化來說,先會接受到AVpacket,其就是一個bitstream,之后會判斷有沒有硬件decode,如果沒有,就會走軟件程序流程。軟件decode會解碼SPS、PPS,將整幀分成不同的slice,然后解碼slice,之后就會輸出一幀一幀的數據。如果發現有硬件decode,就會走硬件流程。硬件decode就是調用decode_params,把SPS、PPS都送給driver,然后有start_frame告訴driver,它要解碼這一幀數據。然后,decode_slice將一個個slice的數據送給driver,送完之后,它就會調用end_frame。end_frame就是告訴driver可以解碼了,之后就把數據放到AVFrame的data[3]上。這就是一個Graphic Video memory surface。如果要使用的話,要拿出data[3]。右邊是encode,基本上是一個相反的過程。它會接受一個AVFrame,通過encode后,會變換成一個AVpacket數據,就是bitstream數據,會送給Muxer。這里列出了兩個接口,一個是VAAPI,一個是QSV。如果調用了VAAPI,就會調用send_frame/receive_packet,之后是encode_issue,它認為參數數據都有了,就會調用vaBeginPicture,它與start_frame是一一對應的,之后就用vaRender把數據都傳給driver,再調用EndPicture,就是告訴driver,整幀已經送完。然后調用encode_output,要求做完encode,輸出bitstream,并放入AVPacket里面。如果是調用QSV,就簡化很多,即調用兩個接口即可。一個是EncodeFrameAsync,它是一個異步接口,把幀送給它之后,它在后臺編碼。或者把當前幀送到FIFO里去,隔幾個buffer將幀從FIFO里取出來。之后經過一個SyncOperation,之后就可以拿到bitstream。
除了傳統的FFmpeg encode和decode以外,我們還提供了一些FFmpeg DNN、filter相關的功能。FFmpeg DNN提供了一些基于深度神經網絡的功能,可以做到傳統filter做不到的事情,比如超分、把雨點去掉、基于DNN的降噪等。我們現在正在做的是基于DNN的detection和分類,以后很多事情都可以在FFmpeg里面完成。所有filter都會調用一個公共的DNN interface,這個interface會被下面三個backend實現。一個是Tensorflow backend,一個是FFmpeg自帶的Native backend,還有一個是Intel的OpenVINO backend。不同的backend依賴于不同的外部庫。Tensorflow backend依賴于Tensorflow C library,可以調用NVIDIA GPU。OpenVINO backend可以調用Intel GPU等。
我們還提供了一個視頻處理庫,叫作LibXCam,里面包括360 video stitching、數字降抖動、wavelet denoise以及HDR的處理,還提供了FFmpeg和GStreamer 的filter。這個庫在GPU和CPU上做過大量優化,所以對于360 stitching,它能做到大概3個4k,到1個8k的ERP,就是說把三個不同方向上采集到的圖像轉換成一個環繞360圖像。GPU是通過GLES和Vulkan優化的,CPU是通過AVX512優化的。
接下來是搭建優化的pipeline。圖中列出了我們開發硬件管線的一些經驗。比如很多人會去access decode的幀,把幀取出來后做后處理、編碼等操作,然后用CPU訪問這些decode的幀。這樣做的話,速度就會很慢。主要原因在于,一方面是集成顯卡會使用tiled memory,雖然在主存里,但是它沒有cache,當CPU去訪問它的時候,就是用沒有cache的方式。經過我們的測試,訪問這個內存,1080p大概會慢30倍左右。另一方面,對于獨立顯卡,情況就會更加糟糕,因為它會訪問總線內存。在這種情況下,最好就是不要去讀GPU內存,可以使用GPU上的操作去訪問GPU內存,必然可以使用OpenCL,或者OpenGL、Vulkan來進行這些事情。一個簡單的例子就是background aware subtitles,因為一個subtitles要根據后面的視頻信息合成起來,如果用CPU去訪問就會非常慢,但如果用OpenCL的話,因為它們都在GPU上面,速度就會快非常多。如果實在是要這樣操作的話,可以使用我們提供的vpp。你可以認為vpp就是DMA的操作,可以從沒有cache的內存里面,搬到一塊有內存的cache里,這樣去訪問就會快很多。還有一種方法是用AVX512指令,一次搬運512個字節,或者用AVX2搬運256個字節,搬到有cache的內存里,這樣速度就會快很多。
圖中列出了一些工具,可以幫助大家觀察GPU的狀態。因為各種客戶的應用場景不一樣,有些客戶會反映說,負載太低,或者fps太低,這時候就可以用開源工具來觀察。針對Intel-GPU-Top,上面是GPU的頻率,可能因為各種各樣的原因,GPU的頻率太低,不能達到要求。中間是引擎。第一個是Render引擎,包含了3D、OpenCL和vpp等,如果同時用3D和vpp操作,這個引擎的占用率就會很高。第二個是Blitter引擎,包含在CPU和GPU之間互相復制數據的操作,占用率一般不會很高。第三個引擎是Video,包含了decoder和encoder的硬件操作,盡量用滿,硬件的功能才能完全發揮。第四個引擎是VideoEnhance,如果發現Render使用率過高,我們還提供了一個LowPower的方式,雖然質量稍低,但是可以做Video post process這些操作,把這些負載都移到這邊,那么整體的負載就會均衡一些。像這張圖一樣,你會發現,任何引擎的使用率都不高,那就說明系統里有一些相互依賴的關系,要么去解決這些依賴關系,要么就多開一些實例把某一個引擎占滿,那這個引擎就會成為你的系統瓶頸。
最后是參考文獻,大家有空可以看看。
謝謝大家!
詳情請掃描圖中二維碼或點擊閱讀原文了解大會更多信息。
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的OneVPL与FFmpeg/GStreamer硬件编解码器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 音视频技术开发周刊 | 200
- 下一篇: IETF访谈: HTTP/3全球份额持续