H.265/HEVC Web端直播播放器內(nèi)核開發(fā)解密

H5視頻播放器內(nèi)核的開發(fā)對(duì)于前端工程師來(lái)說(shuō)算是一個(gè)比較少涉足的領(lǐng)域,恰好工作中有所研究,分享出來(lái)給感興趣的同學(xué)。簡(jiǎn)單的說(shuō),播放器內(nèi)核的功能類似于一個(gè)video標(biāo)簽,它負(fù)責(zé)視頻資源的解封裝、解碼和播放。

視頻播放器架構(gòu)


圖1 視頻播放器架構(gòu)

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

相關(guān)背景技術(shù)

直播是目前最流行的一種信息傳播和社交方式,區(qū)別于錄制的點(diǎn)播視頻,它要求播放器可以實(shí)時(shí)的獲取并播放流式視頻數(shù)據(jù)。為了實(shí)現(xiàn)直播播放,播放器內(nèi)核需要借助一些HTML5的技術(shù)。如下圖所示:

圖2 播放器內(nèi)核主要模塊與依賴的背景技術(shù)

其中Audio MSE Controller依賴于Media Source Extension API,Stream Loader依賴于Stream標(biāo)準(zhǔn),H.265 Decoder依賴于WebAssembly技術(shù),而各個(gè)模塊被劃分在不同的線程中,依賴于Web Workers。具體來(lái)說(shuō):

Media Source Extensions(簡(jiǎn)稱MSE),?提供了實(shí)現(xiàn)無(wú)插件且基于 Web 的流媒體的功能。使用MSE API(主要包括:Media Source,Source Buffer等),媒體流能夠通過(guò) JavaScript 創(chuàng)建,并且能通過(guò)HTMLMediaElement元素(包括:video和audio元素)進(jìn)行播放。IE11(win8+)及其他現(xiàn)代瀏覽器都支持。

Streams[2]標(biāo)準(zhǔn)提供了一套API,來(lái)創(chuàng)建和操作流數(shù)據(jù),具體地,包括ReadableStream, WritableStream, 以及TransformStream。這允許我們可以增量地處理數(shù)據(jù),而不必將所有數(shù)據(jù)緩存到內(nèi)存中統(tǒng)一處理。我們可以采用Fetch API[4] 獲取視頻數(shù)據(jù),返回的body是一個(gè)ReadableStream對(duì)象。該對(duì)象代表一個(gè)數(shù)據(jù)源,內(nèi)部維護(hù)了一個(gè)隊(duì)列來(lái)記錄尚未被讀取的底層數(shù)據(jù)源??梢酝ㄟ^(guò)ReadableStream的getReader()接口讀取內(nèi)部隊(duì)列中chunk數(shù)據(jù)。

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

WebAssembly[5]?是Web端的字節(jié)碼技術(shù),它定義了一個(gè)通用的、體積緊湊、加載迅捷的二進(jìn)制格式為編譯目標(biāo),能發(fā)揮通用硬件的性能,以更接近原生應(yīng)用的速度運(yùn)行。在瀏覽器中對(duì)H.265編碼的視頻進(jìn)行軟件解碼,是一項(xiàng)對(duì)性能非常有挑戰(zhàn)的任務(wù),JavaScript等腳本語(yǔ)言無(wú)法勝任此項(xiàng)工作。因此可以將C/C++語(yǔ)言編寫的高性能解碼庫(kù)編譯成字節(jié)碼,再通過(guò)JavaScript調(diào)用來(lái)運(yùn)行。目前此項(xiàng)技術(shù)在Chrome、Firefox、Safari和Edge瀏覽器的較新版本中都可以使用(如Chrome57+,F(xiàn)irefox 52+)。

H.265/HEVC編碼與硬解平臺(tái)支持

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

圖3 相同數(shù)據(jù)量下H.265和H.264圖像質(zhì)量對(duì)比

一般來(lái)說(shuō)操作系統(tǒng)借助硬件(顯卡)進(jìn)行H.265編碼視頻的解碼工作,其好處是硬解的功耗低,解碼速度快。但目前H.265編碼在瀏覽器中的硬件解碼支持情況并不普及。經(jīng)測(cè)試只在定制的Chromium[7] 及Edge 14瀏覽器中支持,可以通過(guò)此頁(yè)面,測(cè)試瀏覽器對(duì)H.265編碼的點(diǎn)播視頻的播放情況。下圖是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。

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

Web端軟解方案

由于直播的Web端硬解方案目前限于瀏覽器支持情況無(wú)法實(shí)現(xiàn),軟件解碼便成為了唯一的選擇。由于H.265視頻的解碼是一個(gè)對(duì)性能要求很高的CPU密集任務(wù),Web端腳本語(yǔ)言實(shí)現(xiàn)的解碼器的性能很難達(dá)到要求。我們團(tuán)隊(duì)之前嘗試過(guò)基于Flash的H.265解碼方案,即通過(guò)FlasCC[11]編譯器把C語(yǔ)言編寫的解碼器編譯成swc庫(kù),然后在Flash播放器中用Action Script調(diào)用swc庫(kù)。測(cè)試結(jié)果顯示1080p高清視頻每秒只能解碼渲染10幀左右,無(wú)法達(dá)到應(yīng)用要求。

另一種方案是基于HTML5的,即通過(guò)WebAssembly技術(shù)將金山云自研的高性能解碼器編譯為wasm庫(kù),wasm文件是以二進(jìn)制形式存在的,其中包含平臺(tái)無(wú)關(guān)的虛擬指令(類似匯編指令)。目前WebAssembly技術(shù)已經(jīng)被四大主流瀏覽器的新版本所支持。基于該技術(shù)的播放器內(nèi)核的實(shí)現(xiàn)如下圖所示(圖中虛線表示對(duì)象引用關(guān)系,實(shí)現(xiàn)表示數(shù)據(jù)傳遞):

圖5 H.265直播播放器實(shí)現(xiàn)

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

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

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

播放效果如下圖所示:

圖6 Chrome上拉流播放效果

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

圖7 測(cè)試環(huán)境機(jī)器配置

這里需要說(shuō)明一下的是,由于Adobe的FLV格式并沒(méi)有對(duì)H.265編碼的官方支持,我們聯(lián)合友商對(duì)FLV容器格式進(jìn)行了擴(kuò)展,并以草案的形式發(fā)布,參見HVCPacketTypeffmpeg patch)。

本文介紹了Web端直播播放器的相關(guān)背景技術(shù),及H.265 codec的Web端軟硬解方案的探索,并對(duì)軟解方案的一種實(shí)現(xiàn)進(jìn)行了說(shuō)明。分享于此,拋磚引玉,不詳之處歡迎留言交流,也可加入金山云技術(shù)交流QQ群:574179720。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容