本文作者:蔡斯杰,字节跳动互娱前端业务负责人

公司内容生产端最近(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视频播放相关推荐

  1. 【miscellaneous】最新HEVC/H.265 4K视频,显卡解码测试

    转载自:http://bbs.zol.com.cn/diybbs/d34441_76103.html 4K这个概念也在最近几年开始流行了起来,无论是4K显示器.4K电视盒子,还是4K游戏对硬件的要求也 ...

  2. 让CEF支持HEVC(H.265)视频播放

    HEVC(H.265)有高昂的版权费用这个是众所周知的,所以现在绝大多数浏览器默认都不具备HEVC解码能力,这一点可以通过caniuse.com看到: 可以看到,基本上只有Apple是HEVC的主要支 ...

  3. ubuntu20.04修改编译chromium源码实战

    首先,利用vmware搭建ubuntu20.04的虚拟机 由于chromium的源码比较大,在git的时候需要分配数据交换的大小,如果小了就下不下来.所以最好给这台虚拟机分配12G内存以上.存储100 ...

  4. 高效视频编码 (HEVC) -H.265(结构解析)

    版本 HEVC (H.265) 规范的第一个版本于 2013 年 4 月发布.该标准的版本如下: ITU-T H.265 (V1) (04/2013) http://handle.itu.int/11 ...

  5. HEVC/H.265(1)——入门初步了解

    一.引子 说到H.265,个人的初始印象就是比H.264高端了那么一些的编码标准,再就是在学校的BT上下的那个好多播放器都播放不了,只有potplayer等一小部分未来播放器能播放的权利的游戏HEVC ...

  6. 转载:浏览器开发系列第一篇:如何获取最新chromium源码

    背景:      最近摊上一个事儿,领导非要让写一篇技术文章,思来想去,自己接触chrome浏览器时间也不短了,干脆就总结一下吧.于是乎,本文顺理成章.由于有些细节必需描述清楚,所以这次先讲如何拿到c ...

  7. uboot修改linux源码中参数,将自定义参数从uboot传入kernel的并读取的方法【转】

    希望朋友们多多指点,好的技术或心得一起分享: uboot向kernel传参机制以及kernel如何解析cmdline参数大家可以参考其他前辈的博文,这方面的讲解十分详尽. 在这里我总结以下自己在ubo ...

  8. 修改marathon源码后,如何编译,部署到集群中?

    首先,marathon源码是由scala语言编写,由sbt进行项目构建的:与spark不同,spark是由maven进行项目构建: 方案一:使用intellij idea导入marathon源码[目前 ...

  9. 修改gh-ost源码实现两表在线高速复制

    修改gh-ost源码实现两表在线高速复制 一.问题起源 笔者所在的公司的需要对核心业务表tb_doc 进行表分区,目前该表的记录数为190,522,155. 由于该表没有分区,新增分区需要创建影子表, ...

最新文章

  1. 1010 Radix
  2. Redisbook学习笔记(1)跳跃表
  3. File类与FileInfo类的区别
  4. 自动转换开关(ATS)在数据中心配电系统中的应用
  5. plsql打开sql窗口快捷键_巧用Navicat for MySQL的快捷键
  6. centos8 安装geany
  7. 财富信息不需要传userID后台会根据保存的session提供数据
  8. Android Studio(7)---从模板添加代码
  9. buffer string builder简单说明
  10. Linux系统分区及LVM使用(一)
  11. Delphi手机短信
  12. python爬取热门新闻每日排行_用python查看百度搜索中今日热点事件排行榜
  13. POP介绍与使用实践(快速上手动画)
  14. WinAVI FLV Converter v1.0 注册码
  15. alter table add column多个字段_element中el-table单行暂无数据和整体暂无数据的默认修改...
  16. 小用lambda表达式,查询数组里大于80的个数
  17. 【Excel学习笔记8】“定位”可以用来干嘛?
  18. (10.2.1)15款优秀移动APP产品原型设计工具
  19. 阿里云个人镜像仓库日常基本使用
  20. python通过路径找文件_Python寻找路径和查找文件路径的示例

热门文章

  1. Hive 10、Hive的UDF、UDAF、UDTF
  2. 基于Echarts实现可视化数据大屏大数据看板
  3. 7-16 然后是几点(15 分)
  4. 高斯坐标反算公式——python实现
  5. Mac下载Bilibili视频
  6. 升学教育过程中:关于收费、退费的规定
  7. 文本溢出隐藏显示... 鼠标移动到元素显示全部内容
  8. python 自动生成word文档,用 Python 自动生成 Word 文档
  9. viper4android io错误,golang常用库之配置文件解析库-viper使用详解
  10. CUBA China 最新进展