修改Chromium源码实现HEVC/H.265 4K视频播放
本文作者:蔡斯杰,字節跳動互娛前端業務負責人
公司內容生產端最近(2019/10)在推廣 HEVC/H.265 的使用,這種視頻編碼格式對比H.264更加先進且節省帶寬,雖然先進但是因為專利費的問題,在普及度,軟硬件方面的支持都遠不及預期(可以看知乎這篇)。視頻技術水深,還是先把了解的背景給大家整理羅列一下。
HEVC軟硬件的支持
瀏覽器
Can I use 測試基本全軍覆沒,除了 iOS 11 以上的移動端 safari 和 chrome。
系統原生支持
Native 支持的情況已經相當不錯,這里的支持是操作系統提供了 HEVC 編解碼的 api,底層實現會根據硬件條件優先硬解否則軟解,當然移動端機型也會因為系統定制,專利,性能考量等原因屏蔽支持(猜測)還要用黑名單控制一下。
Android:Android 5.0+,代碼:os_version >= 5.0 && app_version >= 570 && device_model not in blacklist
iOS:iOS 11+,代碼:os_vesion >= 11 && minMajorModelVersion >= 8 && device_model not in blacklist
macOS:macOS High Sierra+
Windows:DirectX Video Acceleration (DXVA),這個不是很確定,需要進一步深入調研,或許會在下一篇文章介紹。
硬件支持
左邊的鏈接基本就是官方或者wiki 聲明的支持度,數據相對權威。
Intel :支持較好,在第六代 Skylake 架構 cpu 及以上實現 HEVC 8-bit 編解碼。
Nvidia GPU:Nvidia 900 Series GPUs (GeForce GTX 960 或者 950) 以上都支持。
AMD GPU :具體的支持度配合查看 Unified Video Decoder:比較完整的支持需要到 UVD 6.0 以上。
蘋果A :A9 及型號或者以上,A11 及以上支持 10-bit HEVC 編解碼。
華為麒麟):使用 Mali 的GPU,2014年以后都支持硬解,10-bit 超高清視頻 + (HDR) + wide color gamut coverage。
高通曉龍 Qualcomm Snapdragon :805, 810, 820, 835 支持 4K HEVC decoding. 615,410, 208 或以上芯片支持硬解。
聯發科 MediaTek):同樣使用 Mali GPU。
編解碼技術
我們說的 HEVC 是一種編碼技術的標準,真正應用和落地的時候還有大量的優化工作,這里面從全球最權威的MSU視頻編碼大賽2018的報告中,中國的軍團獨占風騷,華為,騰訊和金山的表現都相當搶眼,可以說是站在了世界一流的梯隊中,當然有宋利提出國外有高手并未參賽,不管如何,如今2019年已經接近尾聲,相信會有新的一輪比拼和報告出現。這里面開源的有:
X265,編碼器,主要由MulticoreWare公司管理開發,并擁有著作權和商標權,開源協議是GNU GPL v2 license
openHevc,解碼器,開發語言 C ? 基于ffmpeg/libav框架。
libde265,解碼器,發布在Github上,采用LGPL許可證授權。那這些編碼的SDK我們能用嗎,據我了解到這里面都是商家的核心技術,性能都是大幅領先開源編解碼器,這里列出來做一個對標和選型參考。向我了解到字節跳動的視頻架構組也有自研的編解碼器,據說性能也是相當不錯~
競爭格局
說起這個,不得不提起 HEVC 那惡心的專利費,許多內容提供商不愿意部署跟進 HEVC 的最主要原因是,當前有三個不同專利聯盟開黑在嗷嗷收錢,每個聯盟背后代表的公司也不一樣。包括 MPEG LA,HEVC Advance,Velos Media,這個錯綜復雜的關系感興趣可以看看這篇文章。簡單說又貴又麻煩風險不可控(對互聯網企業最怕的就是養肥再殺的這一招),所以必然導致發展緩慢替代品出現。重點來了,蘋果是HEVC專利擁有著,所以一直高調支持 HEVC;Google 不在開黑聯盟里面,沒什么專利,底下 Youtube 就是頭大肥羊,是堅決不用 HEVC 的,目前 Google 用自研的 VP9;2015 年成立了一個新聯盟叫 AOM(Alliance for Open Media)開放媒體聯盟,主要研發 AV1 的編碼格式用于替代 HEVC 和 VP9,并且完全免費!機智的蘋果一邊收 HEVC 的費用,一邊過來站隊,還混了個 AOM 管理成員的職位,大佬畢竟還是大佬。
瀏覽器支持 HEVC 解碼現有方案
那在Web前端技術標準之上的方案,在最近幾年各個前端團隊也都經過深入探索和總結,其中淘寶前端團隊的方案比較有代表性,大體的思路就是:
JS 實現解封裝
ffmpeg 模塊轉換成 WebAssemblly,用來實現高效音視頻解碼。
引入 WebWorker 改善解碼模塊性能。
分離的視頻解碼后用 canvas 繪制,音頻用 audio 播放。
優缺點:性能相對好,但是和C實現的還有較大差距,如果替換成更好的解碼器會更快(比如金山點播的web實現,不免費),工作量大,無法硬件加速,要支持 4K 還是比較難。
具體大家可以看淘寶那片文章,各家的技術會在某些流程上做局部優化,這里就不多深入介紹了。而我目前要解決的場景,主要問題就是性能和穩定性,所以我嘗試尋找一個在 c++ 層面的實現。當時第一個考慮的是Electron,Electron集成了Node.js,因此可以使用 c++ addon 的能力,經過一番調查,發現仍然不是最佳方案,addon 能提供最佳的解碼性能,但是addon代碼里面無法直接調用渲染的接口,需要把數據回調到 JS 堆讓后通過調用 canvas 實現渲染,這種方案相比上面理論上有提升,但是仍然有些別扭,所以我就在想,直接修改 chromium 源碼,參考 video 對 h.264 的實現機制完成 HEVC 的播放需求,相當連硬件解碼的能力也打通了,于是另一種實現方案呼之欲出。
修改 Chromium 實現真 4K HEVC 的播放
修改 Chromium 源碼的方案,原來 chromium 里面已經實現了 HEVC 解碼邏輯,只是加了開關禁止了相關代碼,一切比想象的簡單。最大的門檻其實是網絡(無·奈),不包含歷史數據的源碼(--no-history),零零總總就有接近2GB,翻墻軟件不穩定的入坑需謹慎,嘗試過中間斷掉需要重新開始的。還好公司網絡給力,30MB+/s,我用的是 windows 機器,如何安裝看這篇 Checking out and Building Chromium for Windows,細心點看懂了再動手,一步一步穩著走是最快的方式。
注:macOS 里面我也嘗試過,比 windows 簡單多了,具體看 Checking out and building Chromium for Mac
拿到源碼過了一遍 video 相關的官方文檔,總體了解對后面定位和排查問題有很大幫助:
chromium/src/media
audio-video
media playback
如果上網搜索一下實現方案,引用最多的就是這 henrypp/chromium,他列出了相對完整的修改代碼,可惜版本比較老,一步一步改完后編譯出來的版本仍然不能播放HEVC/H.265 的 MP4 視頻。心情反倒輕松了,哪有這么容易的事,開啟 debug 編譯,準備用 visual studio 調試看看哪一步漏了。
在 src 目錄里面,用這個命令生產構建工程。
gn gen?--ide=vs2019?--filters=//chrome;//media/* --no-deps out\debug --args="is_component_build = true enable_nacl = false is_debug = true blink_symbol_level = 0"
--ide=vs2019,指明生產 visual studio 2019 的solution,這樣方便我們使用 VS 強大的debug工具,但實際上如果在項目里點擊構建,內部還是是用gn的配置。--filters=//chrome;//media/*,//chrome是入口,必須包含,因為不關心入口里面具體項目,所以沒有用 //chrome/\*。我們重點調式 media 相關的源碼。
打開 out/debug/all.solution 之后,把 chrome 項目設置為啟動項目,點擊調試
因為 chromium 的進程模型,每一個tab都在單獨的子進程里面,并且一般有多個線程,所以需要手動附加到所有的線程。這里一個比較笨的方法是,關掉正常的 Chrome 瀏覽器,然后把能附加的 chrome.exe 全都加上就可以了。
調試的過程也是一個推理和學習的過程,還是相當有趣的,調試和構建一個GB級別以上的項目技能點亮。這里的過程就不一一列舉了,直接放出修改源碼(這里面有部分和 henrypp 重合直接整合列出來了)。
*注:構建過程可以隨時中斷,下一次編譯就接著上一次的進度,而且VS里面的構建和官方命令行 autoninja -C out/debug chrome 是等價互通的。
注:debug編譯結果需要占用~30GB的空間,主要用來存放debug相關的.pdb文件和編譯結果,第一次編譯的時候比較慢,后續再修改就會相對比較快
源碼修改
這里面不是文章的重點,但還是放出來給喜歡折騰的人嘗試一下。提醒一下,HEVC 是需要專利授權的,Google 也對 chromium 的修改分發有一定的限制,大家修改作何用途自行評估。
筆者編譯出來的版本是 79.0.3928.0 修改這個文件,找到下面條件判斷并修改代碼:
src/third_party/ffmpeg/ffmpeg_generated.gni
if?((is_mac)?||?(is_win)?||?(use_linux_config))?{
??ffmpeg_c_sources?+=?[
????"libavcodec/autorename_libavcodec_hpeldsp.c",
????"libavcodec/autorename_libavcodec_videodsp.c",
????"libavcodec/autorename_libavcodec_vp3dsp.c",
????"libavcodec/autorename_libavcodec_vp8dsp.c",
????"libavcodec/h264pred.c",
????"libavcodec/vp3.c",
????"libavcodec/vp3_parser.c",
????"libavcodec/vp56rac.c",
????"libavcodec/vp8.c",
????"libavcodec/vp8_parser.c",
??]
??ffmpeg_c_sources?+=?[
????"libavcodec/bswapdsp.c",
????"libavcodec/autorename_libavcodec_hevcdec.c",
????"libavcodec/hevc_cabac.c",
????"libavcodec/hevc_data.c",
????"libavcodec/hevc_filter.c",
????"libavcodec/hevc_mvs.c",
????"libavcodec/hevc_parse.c",
????"libavcodec/hevc_parser.c",
????"libavcodec/hevc_ps.c",
????"libavcodec/hevc_refs.c",
????"libavcodec/hevc_sei.c",
????"libavcodec/hevcdsp.c",
????"libavcodec/hevcpred.c",
????"libavcodec/x86/bswapdsp_init.c",
????"libavcodec/x86/hevcdsp_init.c",
????"libavformat/autorename_libavformat_hevc.c",
????"libavformat/hevcdec.c",
??]
??ffmpeg_asm_sources?+=?[
????"libavcodec/x86/bswapdsp.asm",
????"libavcodec/x86/hevc_deblock.asm",
????"libavcodec/x86/hevc_idct.asm",
????"libavcodec/x86/hevc_mc.asm",
????"libavcodec/x86/hevc_add_res.asm",
????"libavcodec/x86/hevc_sao.asm",
????"libavcodec/x86/hevc_sao_10bit.asm",
??]
}
復制并重命名這個文件里面的兩個文件 src/third_party/ffmpeg:
libavcodec/hevcdec.c to libavcodec/autorename_libavcodec_hevcdec.c
libavformat/hevc.c to libavformat/autorename_libavformat_hevc.c
修改這兩個文件,YOUR_BRAND就是 chromium,YOUR_ARCH 像我用 Windows 就是 x64:
src/third_party/ffmpeg/chromium/config/YOUR_BRAND/win/YOUR_ARCH/config.asm
src/third_party/ffmpeg/chromium/config/YOUR_BRAND/win/YOUR_ARCH/config.h
把下面幾個的值配成 1:
#define?CONFIG_HEVC_DECODER 1
#define?CONFIG_HEVC_DEMUXER 1
#define?CONFIG_HEVC_PARSER 1
在這個文件添加一項:
src/third_party/ffmpeg/chromium/config/YOUR_BRAND/win/YOUR_ARCH/libavcodec/codec_list.c
&ff_hevc_decoder
同樣的添加一項:
src/third_party/ffmpeg/chromium/config/YOUR_BRAND/win/YOUR_ARCH/libavcodec/parser_list.c
&ff_hevc_parser
同樣的添加一項:
src/third_party/ffmpeg/chromium/config/YOUR_BRAND/win/YOUR_ARCH/libavformat/demuxer_list.c
&ff_hevc_demuxer
修改文件 /build/config/features.gni
# Note:?this?flag is used by WebRTC which is DEPSed into Chrome.?Moving it
# out?of?//build will require using the build_overrides directory.
-?proprietary_codecs?=?is_chrome_branded?||?is_chromecast
+?proprietary_codecs?=?true
修改文件 /media/media_options.gni
# Enable HEVC/H265 demuxing.?Actual decoding must be provided by the
# platform.?Enabled by?default?for?Chromecast.
-?enable_platform_hevc?=?proprietary_codecs?&&?is_chromecast
+?enable_platform_hevc?=?true
去掉這個文件里面的一個判斷
/media/BUILD.gn
if?(proprietary_codecs?&&?media_use_ffmpeg)?{
-?assert(
-?ffmpeg_branding?!=?"Chromium",
-?"proprietary codecs and ffmpeg_branding set to Chromium are incompatible")
+?#?assert(
+?# ffmpeg_branding?!=?"Chromium",
+?#?"proprietary codecs and ffmpeg_branding set to Chromium are incompatible")
}
修改文件
/media/base/supported_types.cc
bool?IsDefaultSupportedVideoType(const?VideoType&?type)?{
//...
switch?(type.codec)?{
??// ....
??case?kCodecH264:
+?case?kCodecHEVC:
??case?kCodecVP8:
??case?kCodecTheora:
??????return?true;
??case?kUnknownVideoCodec:
??case?kCodecVC1:
??case?kCodecMPEG2:
-?case?kCodecHEVC:
??case?kCodecDolbyVision:
??????return?false;
??// ...
}
修改完成,在 src 文件夾里面執行如下命令編譯 release 版本
gn gen out/release?--args="is_component_build = false enable_nacl = false is_debug = false symbol_level = 0 blink_symbol_level = 0"
autoninja?-C out/release chrome
大概喝20杯咖啡時間,就開始在瀏覽器里面欣賞 4K 高清 HEVC/H.265 的視頻了。畢竟是C++實現,性能比web端實現的軟解方案不知道高到哪去了。筆者機器 ryzen 3600 + 垃圾 Radeom 5700顯卡表現:
4K性能表現
不準確測試幀率測試:
內存和CPU占用:
后續補充
GPU 加速測試
直接在 chromium 源碼修改一個最強大之處是,后續可以調用 GPU 加速,因為筆者電腦顯卡不支持(支持的顯卡在本文開始鏈接有相應資料),目前在準備硬件,后續測試后更新性能表現。
實現 m3u8|flv & HEVC
這個難度較高,需要更多的技術投入和開發。
最后
修改 chromium 實現的方式并不具有普適性,但是對部分 B 端項目確實能收到起效,性能表現 HEVC 專利問題,VP9 孤掌難鳴,AV1 又姍姍來遲,視頻編碼的新格局將會在在下一代的編碼技術中競爭共存。其實以 HEVC/H.265 的下一代技術 VVC/H.266 以及 AV1 的 下一代 AV2。向之前 AVC/H.264 一家獨大的時代已經一去不復返,視頻編碼技術背后是一個非常大的競爭格局(視頻多大的市場!),尤其為代表性的是擁有硬件手機 Android + Chrome + Youtube 的 Google VS Apple,后者擁有 硬件手機 + iOS + Safari + ?內容生態。還有各個視頻云廠商,內容平臺,互聯網和短視頻等大佬,視頻編解碼技術后續發展甚至關系到互聯網格局和權力的更替!
另外打一個小小的招聘廣告,歡迎一起來共同學習成長。
文章競爭格局里面的圖摘錄自:這篇文章.
關于奇舞周刊
《奇舞周刊》是360公司專業前端團隊「奇舞團」運營的前端技術社區。關注公眾號后,直接發送鏈接到后臺即可給我們投稿。
總結
以上是生活随笔為你收集整理的修改Chromium源码实现HEVC/H.265 4K视频播放的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux下的软件包
- 下一篇: matlab 路由表,闭关修炼之zigb