热门标签 | HotTags
当前位置:  开发笔记 > 程序员 > 正文

修改Chromium源码,实现HEVC/H.2654K视频播放

作为H.264的后继产品,HEVCH.265是一种高级视频压缩标准,能够节省50%的比特率,带来惊人的视觉质量。例如,在Converter的DivXHEVC配置文件中编码的视频,不

作为 H.264 的后继产品,HEVC/H.265 是一种高级视频压缩标准,能够节省 50%的比特率,带来惊人的视觉质量。例如,在 Converter 的 DivX HEVC 配置文件中编码的视频,不仅保持了 DivX Plus 配置文件的高质量,文件还更小。即使在拥挤的网络环境中,HEVC 对于传输高质量视频也至关重要,并且是将 4K 内容传输到 4K/Ultra HD 显示器的驱动因素。本文作者分享了其公司推广 HECV/H.265 的经验,并介绍了该技术的相关背景。


 

公司内容生产端最近(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),这个不是很确定,需要进一步深入调研,或许会在下一篇文章介绍。



 


硬件支持



  • 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 的能力,经过一番调查,发现仍然不是最佳方案。虽然 c++ 代码能提供最佳的解码性能,但是 addon 里无法直接调用渲染接口(涉及到 addon 的机制,即使能实现也非常 Hack),需要把数据回调到 JS 堆让后通过调用 canvas 实现渲染。这种方案相比上面理论上有提升,仍然意犹未尽。想了解更多 chromium 关于 video 的实现参考 chromium 的官方文章 Audio / Video Playback,这里面借用它的图片直接敲重点:

 



  • 架构设计上支持 任何音视频编码。



  • 文章解释了设计的一些初衷和思考,包括为了避免版权放弃了一些相对成熟的实现方案。



 

 

所以我就在想,直接修改 chromium 源码,参考 video 对 h.264 的实现机制完成 HEVC 的播放需求,相当于连硬件解码的能力也打通了(调研尝试中),于是另一种实现方案呼之欲出。

 


修改 Chromium 实现真 4K HEVC 播放

修改 Chromium 源码的方案,原来 chromium 里面已经实现了 HEVC 解码逻辑,只是加了开关禁止了相关代码,一切比想象的简单。最大的门槛其实是网络(无奈),不包含历史数据的源码(–no-history),零零总总就有接近 2GB,FQ软件不稳定的入坑需谨慎,尝试过中间断掉需要重新开始的。还好公司网络给力,30MB+/s,我用的是 windows 机器,如何安装看这篇 Checking out and Building Chromium for Windows。

 

注:macOS 里面我也尝试过,比 windows 简单多了,具体看 Checking out and building Chromium for Mac。

 

拿到源码过了一遍 video 相关的官方文档,总体了解对后面定位和排查问题有很大帮助:

 



  • chromium/src/media:



  • https://chromium.googlesource.com/chromium/src/media/



  • audio-video:



  • https://www.chromium.org/audio-video



  • media playback:



  • https://www.chromium.org/developers/design-documents/video



 

如果上网搜索一下实现方案,引用最多的就是 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 重合直接整合列出来了)。

 

注 1:构建过程可以随时中断,下一次编译就接着上一次的进度,而且 VS 里面的构建和官方命令行 autoninja -C out/debug chrome 是等价互通的。

 

注 2: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 的下一代技术 VVC/H.266 以及 AV1 的 下一代 AV2 也被提上日程。之前 AVC 一家独大的时代已经一去不复返,视频编码技术背后是一个非常大的竞争格局 (视频多大的市场!),尤其具有代表性的是拥有硬件手机 Android + Chrome + Youtube 的 Google VS Apple,后者拥有硬件手机 + iOS + Safari + ?内容生态,加上各个视频云厂商、内容平台、互联网和短视频等大佬,视频编解码技术后续发展甚至关系到互联网格局和权力的更替!让我们拭目以待。

 

原文链接:

 

https://segmentfault.com/a/1190000020711813



推荐阅读
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 无损压缩算法专题——LZSS算法实现
    本文介绍了基于无损压缩算法专题的LZSS算法实现。通过Python和C两种语言的代码实现了对任意文件的压缩和解压功能。详细介绍了LZSS算法的原理和实现过程,以及代码中的注释。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • HTML学习02 图像标签的使用和属性
    本文介绍了HTML中图像标签的使用和属性,包括定义图像、定义图像地图、使用源属性和替换文本属性。同时提供了相关实例和注意事项,帮助读者更好地理解和应用图像标签。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 本文总结了在开发中使用gulp时的一些技巧,包括如何使用gulp.dest自动创建目录、如何使用gulp.src复制具名路径的文件以及保留文件夹路径的方法等。同时介绍了使用base选项和通配符来保留文件夹路径的技巧,并提到了解决带文件夹的复制问题的方法,即使用gulp-flatten插件。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 第四章高阶函数(参数传递、高阶函数、lambda表达式)(python进阶)的讲解和应用
    本文主要讲解了第四章高阶函数(参数传递、高阶函数、lambda表达式)的相关知识,包括函数参数传递机制和赋值机制、引用传递的概念和应用、默认参数的定义和使用等内容。同时介绍了高阶函数和lambda表达式的概念,并给出了一些实例代码进行演示。对于想要进一步提升python编程能力的读者来说,本文将是一个不错的学习资料。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
author-avatar
DomeSmart
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有