admin管理员组

文章数量:1585030

本文作者:朱思达 飞书技术团队

HEVC 的现状

背景简介

什么是 HEVC ?简单说就是一种比 H264 压缩效率更高的现代视频编码格式,它支持 8K,支持 HDR,支持广色域,支持最高 16bit 的色彩深度,最高 YUV444 的色彩抽样,总之一句话,是一种用来取代现有 H264 的更高效、现代的视频编码格式,且目前已经被各类硬件广泛支持。

然而因为版权和技术派别等原因,这种格式一直没有被浏览器很好支持,尤其是目前市占率最高的 Chrome,一月初看到了一条 B 站用户吐槽 HEVC 解码性能/发热问题的新闻(感谢 B 站在 HEVC WASM 解码方案上的探索),考虑到这也是困扰业界很久的问题,大量依赖 HEVC 的 Web 项目均被迫产出了各种各样 Workaround 方案,但效果一直都不是最理想的,心想不如帮 Chromium 实现一下 HEVC 硬解吧。

本文简述了 Web 解码方案现状,介绍了作者为 Chromium 浏览器实现 & 完善硬解过程中遇到的问题和实现原理,并在文末附加了测试结果,预编译版本供参考,希望可以解决 FrontEnd 苦 HEVC 久矣的问题。

也可以提前下载 Chrome Canary(https://www.google/chrome/canary/) ,体验 HEVC 硬解功能(ChromeOS、Android、Mac、Windows 需要添加启动参数 --enable-features=PlatformHEVCDecoderSupport,Linux 版本暂未支持)。

主流设备早已支持且广泛使用

在 2015 年,苹果的 iPhone6s 就已经在其 A9 芯片内首次实现了 HEVC 硬解能力,同年,Intel 在第六代 Skylake 的 HD500 系列核显上,NVIDIA 在 GTX900 系列独显上,也先后支持了 HEVC 硬解。

在 2017 年发布的 iOS11, macOS 10.13 上,苹果继续完成了其 VideoToolbox 编解码框架对 HEVC 编解码能力的支持,微软也发布了 HEVC Video Extension 作为 Windows PC 环境 HEVC 解码的能力对标。

从此 HEVC 成为苹果,安卓默认视频格式,成为绝大多数单反 / 无人机 / 摄像设备的主推格式。

直到今年,也就是 2022 年,iPhone 已经出到了 13,芯片技术已经提升到了 5 纳米,然而我们所使用的大部分浏览器依然无法播放 HEVC 视频。

硬解的必要性

更低的发热

所谓硬解,即指使用 GPU 内专用于解码的芯片来处理解码工作,由于 GPU 多核心低频且专一的优势,在解码视频时发热和功耗显著低于 CPU。

更好的性能

通过将 CPU 从繁重的解码工作中解放,可极大程度降低系统卡顿。

且 GPU 天生适合进行图形解码工作,解码性能秒杀 CPU,视频分辨率越高,显卡解码越可以做到不掉帧输出,因此“永远不要指望单纯靠 CPU 软解可以流畅播放 8K 60 帧的 HEVC 视频”。

总结

HEVC 是目前桌面端或手机端播放器最主流的编码格式,考虑到其编码复杂度高,解码更耗费资源,因此为其实现硬解非常必要。

HEVC 解码的方案

浏览器解码现状

首先先来看看 Web 侧解码的现状:

Windows

macOS

​目前业内常用的 Web HEVC 解码方案大致可以分为两种:“换浏览器” 或 “WASM 软解”,他们各自有各自的优势和使用场景。

浏览器-Edge (硬解,仅 Windows)

Chromium 内核的 Edge 在 Windows 系统下,额外支持了硬解 HEVC 视频,但必须满足如下条件:

  1. 操作系统版本必须为 Windows 10 1709(16299.0)及以后版本。

  2. 安装付费的 HEVC 视频扩展或免费的来自设备制造商的 HEVC 视频扩展且版本号必须大于等于 1.0.50361.0(由于一个存在了一年半以上的 Bug,老版本存在抖动的 Bug,Issue:https://techcommunity.microsoft/t5/discussions/hevc-video-decoding-broken-with-b-frames/td-p/2077247/page/4)。

​3. 版本号必须大于等于 Edge 99 。

​在安装插件后,进入 edge://gpu 页面,可以查看 Edge 对于 HEVC 硬解支持的 Profile:

​出现上图所示的字样,则证明硬解开启成功。

指标:

  1. 分辨率最高支持 8192px * 8192px。

  2. 支持 HEVC Main / Main10 / Main Still Picture Profile。

优势:

  1. 在显卡支持的情况,性能是最好的。

  2. HTMLVideoElement、MSE 等原生 API 的直接支持。

劣势:

  1. 不支持 Windows 8 和老版本 Windows 10。

  2. 需要手动装插件。

  3. HDR 支持不够好。

浏览器-Safari (硬解,仅 macOS)

由于 Apple 是 HEVC 标准的主要推动者,因此早在 17 年的 Safari 11 即完成了 HEVC 视频硬解的支持,无需安装任何插件开箱即用。

指标:

  1. 分辨率最高支持 8192px * 8192px。

  2. 支持 HEVC Main / Main10 Profile,M1+ 机型支持部分 HEVC Rext Profile。

优势:

  1. 在显卡支持的情况,性能是最好的。

  2. HTMLVideoElement、MSE 等原生 API 的直接支持。

  3. 开箱即用,无需装插件。

  4. HDR 支持最好(比如:杜比视界 Profile5,杜比全景声)。

劣势:

  1. 生态不足,缺乏大量 Chromium 内核下“可用、好用的”插件。

  2. Safari 俗称“下一个 IE”,其浏览器 API 兼容性与实现,相比 Chromium 仍有差距。

  3. 部分 HEVC 视频莫名其妙无法播放,哪怕视频本身没问题。

前端解码-WASM(软解,任何平台)

此类方案绝大部分基于 WASM + FFMPEG 编译实现,支持所有支持 WASM 的浏览器。

指标:

  1. 支持 FFMPEG 支持的所有分辨率和 Profile。

优势:

  1. 不挑浏览器,是纯前端的技术实现。

劣势:

  1. 需要依赖所在版本浏览器 WASM 的稳定性。

  2. 不支持硬解,因为软解+性能损耗的缘故,性能有其天花板,4K 以上视频即使使用 5950X 这样的顶级 CPU 也会卡顿掉帧。

  3. 非 HTML Video Element、MSE、EME 原生 API,需要手动用 js 初始化视频播放,使用有成本。

浏览器-本文方案(硬 / 软解,Windows / macOS / Linux)

本文尝试直接为 Chromium 实现硬解,因为尽管 Safari 和 Edge 均已经实现了 HEVC 硬解,但它们均为闭源软件,无法被各种开源框架集成,而因为 Chromium 是开源的,这可以确保所有人可自行编译支持 Windows / macOS / Linux 硬解的 Chromium / Electron / CEF,考虑到实现原理部分较长,因此如果你感兴趣,可直接下载预编译版本(https://github/StaZhu/enable-chromium-hevc-hardware-decoding/releases)进行测试(未来会被包含在 Chrome 正式版本内,预编译版本可供大家尝鲜提前试用,也可下载 Chrome Canary),或跳到测评部分查看与 Edge / Safari 的对比。

HEVC 硬解的实现原理

正是因为如上瓶颈,“让专业的人做专业的事”这句话同样适用视频解码,GPU 硬解是很有必要的。GPU 解码的存在正是为了让解码工作可以充分利用显卡内部专用芯片,分担 CPU 解码时的压力,因此支持更多格式的硬解能力,已然成为众多显卡厂商的一大卖点。

首先我们需要做一些调研,研究下目前硬解框架是如何存在,并支持哪些“系统” or “GPU”。

下表来自 FFMPEG 项目对不同解码框架硬解支持情况的总结(来源:https://trac.ffmpeg/wiki/HWAccelIntro)

​硬解框架的支持情况,表格内容来自 FFmpeg 官网

可以看到硬解框架五花八门,不同的显卡厂商和设备有各自的专用解码框架,操作系统也有定义好的通用解码框架,由于显卡厂商众多,因此大部分播放器一般均基于通用框架实现硬解,少部分播放器在人力充裕的情况可能会为了更好的性能(显卡厂商自己的框架一般比通用框架性能更好,但也不绝对)额外对专用框架二次实现。

其中 Windows 平台通用的解码框架有 Media Foundation, Direct3D 11, DXVA2, 以及 OpenCL。macOS 平台通用的解码框架只有一个,也就是苹果自己的 VideoToolbox。Linux 平台的通用解码框架有 VAAPI 和 OpenCL。

显然,对于 Chrome 而言,为了更好的兼容性和稳定性,基于通用硬解框架实现硬解,更符合最小成本最大收益的目标,并提升了可维护性。

理解 Chromium 解码流程

根据 Chromium Media 模块简介可知,浏览器将音视频播放一共抽象成三种类型,我们比较常见的有:Video Element 标签,MSE API。此外还有支持加密视频播放的 EME API,这三种在底层又存在多种复用关系。

​Chromium 的解码流程,图片来自 Chromium 代码仓库

那么到了最底层的解码模块,整体逻辑大概可以简述为:

  1. 浏览器会从列表中依次按照顺序查找 Decoder,通常来说优先级最高的是硬解 Decoder, 然后会尝试软解 Decoder。

  2. 如有命中其中的某个 Decoder 则执行后续解码逻辑。

  3. 如没有命中的 Decoder,则解码失败,中止。

因此,为了实现 HEVC 硬解,我们首先需要找到各个平台的通用硬解 Decoder:

  • 对于 Windows,根据操作系统以及显卡驱动版本,分为两种:D3D11VideoDecoder 和 VDAVideoDecoder,前者在大于 Windows8 且支持 D3D11 的系统默认被使用,后者则在前者不被使用时(比如 Windows 7)作为 Backup 方案被使用。

  • 对于 macOS,为 VDAVideoDecoder。

  • 对于 Linux,为 VAAPIVideoDecoder。

macOS 的硬解

在了解了大致背景后,便可以开始探索实现 HEVC 硬解实现了,考虑到 Apple 其最新 Apple Silicon 芯片专门实现了支持 H.264、HEVC 和 ProRes 的专用编解码媒体处理引擎,看在 Apple 这么努力的份上,我首先挑选了 macOS 平台来进行尝试

本文标签: 原理指南HDRChromiumHevc