H.265/HEVC Web端直播播放器內核開發解密


H5視頻播放器內核的開發對於前端工程師來說算是一個比較少涉足的領域,恰好工作中有所研究,分享出來給感興趣的同學。簡單的說,播放器內核的功能類似於一個video標簽,它負責視頻資源的解封裝、解碼和播放。

視頻播放器架構

 

 
圖1 視頻播放器架構

一個典型的現代播放器可以分為三個部分:UI、多媒體引擎和解碼器[1] 。本文要講的視頻播放器內核,其主要工作在圖1中處於下面兩層,主要包括:解碼器、渲染器、網絡管理引擎和媒體管理引擎。

相關背景技術

直播是目前最流行的一種信息傳播和社交方式,區別於錄制的點播視頻,它要求播放器可以實時的獲取並播放流式視頻數據。為了實現直播播放,播放器內核需要借助一些HTML5的技術。如下圖所示:

 
圖2 播放器內核主要模塊與依賴的背景技術

其中Audio MSE Controller依賴於Media Source Extension API,Stream Loader依賴於Stream標准,H.265 Decoder依賴於WebAssembly技術,而各個模塊被划分在不同的線程中,依賴於Web Workers。具體來說:

Media Source Extensions(簡稱MSE), 提供了實現無插件且基於 Web 的流媒體的功能。使用MSE API(主要包括:Media Source,Source Buffer等),媒體流能夠通過 JavaScript 創建,並且能通過HTMLMediaElement元素(包括:video和audio元素)進行播放。IE11(win8+)及其他現代瀏覽器都支持。

Streams[2]標准提供了一套API,來創建和操作流數據,具體地,包括ReadableStream, WritableStream, 以及TransformStream。這允許我們可以增量地處理數據,而不必將所有數據緩存到內存中統一處理。我們可以采用Fetch API[4] 獲取視頻數據,返回的body是一個ReadableStream對象。該對象代表一個數據源,內部維護了一個隊列來記錄尚未被讀取的底層數據源。可以通過ReadableStream的getReader()接口讀取內部隊列中chunk數據。

Web Workers[4] 讓單線程的JavaScript具備了多線程編程的能力,讓視頻播放器內核可以分離解復用、解碼、渲染、UI操作監聽等任務到不同的線程中,並行地處理計算密集型任務和界面顯示等。worker間通信是通過MessageChannel進行。IE10+及其他現代瀏覽器都支持。

WebAssembly[5] 是Web端的字節碼技術,它定義了一個通用的、體積緊湊、加載迅捷的二進制格式為編譯目標,能發揮通用硬件的性能,以更接近原生應用的速度運行。在瀏覽器中對H.265編碼的視頻進行軟件解碼,是一項對性能非常有挑戰的任務,JavaScript等腳本語言無法勝任此項工作。因此可以將C/C++語言編寫的高性能解碼庫編譯成字節碼,再通過JavaScript調用來運行。目前此項技術在Chrome、Firefox、Safari和Edge瀏覽器的較新版本中都可以使用(如Chrome57+,Firefox 52+)。

H.265/HEVC編碼與硬解平台支持

隨着 4K 視頻越來越流行,Apple公司的最新的操作系統版本(Mac Hight Sierra和iOS 11)迎來了 HEVC (高效視頻編碼,也稱 H.265) 這一新的行業標准[6]。與現行的 H.264 視頻壓縮標准相比,它的視頻壓縮率最高可提升 40% 之多。使用H.265,在保持視頻畫質不變的情況下,視頻流媒體傳輸效果更好。而在相同碼率下,能給質量帶來近兩倍的提升。下圖是兩張相同碼率相同分辨率(400kpbs 1080p)的圖片,左邊的采用H.265編碼,右邊的采用H.264編碼。

 
圖3 相同數據量下H.265和H.264圖像質量對比

一般來說操作系統借助硬件(顯卡)進行H.265編碼視頻的解碼工作,其好處是硬解的功耗低,解碼速度快。但目前H.265編碼在瀏覽器中的硬件解碼支持情況並不普及。經測試只在定制的Chromium[7] 及Edge 14瀏覽器中支持,可以通過此頁面,測試瀏覽器對H.265編碼的點播視頻的播放情況。下圖是H.265視頻在Chromium 64中播放的截圖。

 
圖4 H.265視頻文件播放

需要注意的是硬件解碼需要用戶的顯卡支持H.265 codec, 目前支持H.265解碼的顯卡主要包括:Intel HD Graphic 4400/4600/5000/5500/6000/620, Iris Graphics 5100/5200/6100,NVIDIA GeForce GTX 745, GTX 750, GTX 750 Ti, GTX 850M, GTX 860M,GeForce 830M, 840M,GeForce GTX 970, GTX 980, GTX 970M, GTX 980M,GeForce GTX TITAN X, GeForce GTX 980 Ti, GeForce GTX 750 SE, GTX 950, GTX 960, GeForce GTX 1070, GTX 1080, GeForce GTX 1060, NVIDIA TITAN XP, GeForce GTX 1050, GTX 1050 Ti

在直播場景下,視頻流需要通過MSE接口發送給HTMLMediaElement播放,因而需要MediaSource接口也支持H.265的媒體類型字符串。目前只有Edge瀏覽器宣稱支持H.265編碼的流媒體播放,實測MediaSource.isTypeSupported('video/mp4; codecs="hvc1.xxx"')也確實返回true,但實際通過video標簽播放H.265編碼mp4封裝的視頻數據時,黑屏無畫面。另外測試了其他兩個宣傳支持HEVC編碼的Web播放器Radiant Media Player[9] 和Bitmovin Video Player[10],也是同樣的現象。

Web端軟解方案

由於直播的Web端硬解方案目前限於瀏覽器支持情況無法實現,軟件解碼便成為了唯一的選擇。由於H.265視頻的解碼是一個對性能要求很高的CPU密集任務,Web端腳本語言實現的解碼器的性能很難達到要求。我們團隊之前嘗試過基於Flash的H.265解碼方案,即通過FlasCC[11]編譯器把C語言編寫的解碼器編譯成swc庫,然后在Flash播放器中用Action Script調用swc庫。測試結果顯示1080p高清視頻每秒只能解碼渲染10幀左右,無法達到應用要求。

另一種方案是基於HTML5的,即通過WebAssembly技術將金山雲自研的高性能解碼器編譯為wasm庫,wasm文件是以二進制形式存在的,其中包含平台無關的虛擬指令(類似匯編指令)。目前WebAssembly技術已經被四大主流瀏覽器的新版本所支持。基於該技術的播放器內核的實現如下圖所示(圖中虛線表示對象引用關系,實現表示數據傳遞):

 
圖5 H.265直播播放器實現

該實現中包含4個線程,分別是轉封裝/轉復用worker(TransmuxingWorker)、解碼worker(H265decodingWorker)、顏色空間轉換worker(RGBConvertingWorker)和負責渲染和播放控制的主線程。在TransmuxingWorker中,通過DownloadController下載流式媒體數據(在Safari、Chrome和Edge瀏覽器中我們使用Stream API實現下載,而在Firefox中可以基於XMLHttpRequest下載數據),然后根據視頻封裝格式的不同通過解復用器(Demuxer)分離音視頻數據(http-flv流的解復用方法可參照flv.js相關代碼,HLS流的解復用請參考hls.js相關代碼[12])。之后將音頻數據重新封裝成Fragmented MP4格式[13](其媒體類型為mp4a)。最后將mp4a音頻數據發回主線程交給AudioMSEController,AudioMSEController將音頻數據通過MSE接口傳遞給audio標簽並播放。

另一方面,解封裝出的視頻數據通過MessageChannel發送到解碼worker(H265decodingWorker),放入H265Decoder的待解碼數據隊列。H265Decoder基於WebAssembly技術調用底層解碼器解碼,輸出YUV[14]數據。然后再發送給RGBConvertingWorker中的RGBConverter,進行YUV到RGB顏色空間的轉換。最后將RGB數據幀發送給主線程中的音視頻同步渲染器(AVSyncRender),保存到待渲染隊列中。

音視頻同步渲染采用視頻同步到音頻的策略,即音頻正常播放,不斷地檢查待渲染視頻隊列中隊首的視頻幀,比較視頻幀的展示時間戳(pts)與音頻當前時間戳(currentTime),如果視頻時間戳小於音頻時間戳,就渲染當前待渲染隊列隊首的視頻幀。否則要等到滿足上述條件時再渲染該幀視頻。如果待渲染隊列空了,則等待固定時間(例如10ms)再恢復前述操作。這里的圖像渲染是在canvas上渲染,目前在主流瀏覽器上canvas渲染是有GPU硬件加速的。經測試其渲染幀率在該場景下,甚至優於WebGL[15]渲染。另外出於性能上的原因,在worker間通信傳遞數據時需要采用零拷貝方式(又稱Transferable Objects[16])。

播放效果如下圖所示:

 
圖6 Chrome上拉流播放效果

對於畫面比較簡單的高清(1080p)視頻,在Mac筆記本上(配置見圖7)能夠渲染到每秒40幾幀。

 
圖7 測試環境機器配置

這里需要說明一下的是,由於Adobe的FLV格式並沒有對H.265編碼的官方支持,我們聯合友商對FLV容器格式進行了擴展,並以草案的形式發布,參見HVCPacketTypeffmpeg patch)。

本文介紹了Web端直播播放器的相關背景技術,及H.265 codec的Web端軟硬解方案的探索,並對軟解方案的一種實現進行了說明。分享於此,拋磚引玉,不詳之處歡迎留言交流,也可加入金山雲技術交流QQ群:574179720。

from:https://www.jianshu.com/p/5f0ff9013bdb


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM