导读:WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音对话或视频对话的 API。W3C 和 IETF 在2021年1月26日共同宣布 WebRTC 1.0 定稿,促使 WebRTC 从事实上的互联网通信标准成为了官方标准,其在不同场景的应用将得到更为广泛的普及。WebRTC 提供了视频会议的核心技术,包括音视频的采集、编解码、网络传输、显示等功能,并且还支持跨平台:Windows,Mac,iOS,Android。本文主要介绍各个平台的视频渲染技术。
目前业界还没有关于 WebRTC 各个平台视频渲染技术的总结,同时本人最近主要从事视频后处理超分在移动端落地的相关工作,会涉及到视频渲染模块的联动,因此刚好趁这个机会把相关的知识点进行总结一下,希望能够帮助大家更容易的理解 WebRTC 的视频渲染技术。
视频渲染需要支持视频采集、视频前处理、视频后处理、视频解码输出的视频格式。
- 随后视频控制器会按照 VSync 信号逐行读取帧缓冲区的数据,经过可能的数模转换传递给显示器显示
1. 平台视频渲染技术介绍
主要介绍 Apple、Google、Microsoft 三大平台在视频渲染方面的支持。
由以上的介绍可知,目前在终端实现的渲染技术有跨平台的 OpenGL、Vulkan,以及 Apple 平台特有的 Metal、Windows 平台特有的 Direct3D,总共4种渲染方式。
2. 详细介绍视频渲染技术
OpenGL 介绍
OpenGL(Open Graphics Library)是一个跨语言、跨平台的编程图形程序接口,它可用于二维、三维图像的渲染,是一个功能强大,调用方便的底层图形库。OpenGL ES(OpenGL for Embedded Systems)是 OpenGL 三维图形 API 的子集,针对手机、Pad 和游戏而设计,去除了很多不必要和性能较低的 API。因此在 iPhone 和 Android 手机上使用的都是 OpenGL ES。
什么是 EGL
EGL 是 OpenGL ES 和本地窗口系统(Native Window System)之间的通信接口,它的主要作用:
OpenGL ES 的平台无关性正是借助 EGL 实现的,EGL 屏蔽了不同平台的差异。
- 在 macOS 平台下提供 NSOpenGL、CGL 等接口来创建和管理 OpenGL 环境。NSOpenGLView 是一个轻量级的 NSView 子类封装,方便地提供了 OpenGL 绘制环境的创建与管理。在其内部维护了 [NSOpenGLPixelFormat] 和 [NSOpenGLContext] 对象,用户可以方便的对其进行访问和管理。
在 Android 平台上开发 OpenGL ES 应用时,类 GLSurfaceView 已经为我们提供了对 Display , Surface , Context 的管理,即 GLSurfaceView 内部实现了对 EGL 的封装,可以很方便地利用接口 GLSurfaceView.Renderer 的实现,使用 OpenGL ES API 进行渲染绘制,很大程度上提升了 OpenGL ES 开发的便利性。
创建 OpenGL View
- 在 iOS 中,有两种展示层,一种是 GLKView,另一种是 CAEAGLLayer。WebRTC 中使用 GLKView 进行展示。GLKit 框架提供了视图和视图控制器类,它们消除了绘制和动画 OpenGL ES 内容所需的设置和维护代码。本 GLKView 类管理 OpenGL ES 的基础设施,为您的绘制代码提供一个场所,GLKViewController 类提供了在 GLKit 视图的 OpenGL ES 内容的流畅的动画渲染循环。这些类扩展了用于绘制视图内容和管理视图呈现的标准 UIKit 设计模式。因此,您可以将精力主要集中在 OpenGL ES 渲染代码上,并使您的应用程序快速启动和运行。GLKit 框架还提供了其他特性来简化 OpenGL ES 2.0 和 3.0 的开发。
- 在macOS平台下提供了NSOpenGLView,在其内部维护了 NSOpenGLPixelFormat 和 NSOpenGLContext 对象。
- 在 Android 平台下提供 GLSurfaceView,GLSurfaceView 继承了 SurfaceView,实现了 SurfaceHolder.Callback2 接口。SurfaceView 在 View 的基础上是创建了独立的 Surface,拥有 SurfaceHolder 来管理它的 Surface,渲染的工作可以不再在主线程中做了。可以通过 SurfaceHolder 得到 Canvas,在单独的线程中,利用 Canvas 绘制需要显示的内容,然后更新到 Surface 上。 GLSurfaceView 主要是在 SurfaceView 的基础上实现了一个 GLThread(EGLContext 创建 GL 环境所在线程即为 GL 线程),绘制的工作直接通过 OpenGL 来进行,绘制的内容默认情况下依旧是绘制到 SurfaceView 所提供的 Surface 上。
具体运用
目前网易云信第二代实时音视频 iOS 和 Mac 的整体渲染框架,如下图:
目前网易云信第二代实时音视频 iOS 和 Mac 的 OpenGL 渲染架构,如下图:
Metal介绍
Metal 框架支持 GPU 加速的先进的 3D 图形渲染和并行数据计算。Metal 提供了一系列现代化且高效的 API,用于在细粒度和低层次上组织、处理、提交图形绘制指令和并行计算指令,并管理和这些指令相关联的数据和资源。Metal 的一个主要目标是最小化 GPU 执行这些计算时必要的 CPU 开销。
Metal 框架提供以下内容:
- 高效的接口:Metal 被设计来消除“隐蔽”的性能瓶颈,比如隐式状态校验。你可以控制 GPU 的异步行为,可以高效的使用多线程特性来并行创建和提交 command buffer。
- 内存和资源管理机制:Metal 框架描述了 buffer 和 texture 对象,这两种对象对应着 GPU 内存的分配。Texture 对象具有特殊的像素格式,并且可以被用作纹理图片或者附件(attachments)。
- 对图形渲染和并行计算的统一支持:Metal 使用同样的数据结构和资源(比如 buffers, textures, and command queues)来支持图形和计算。另外,Metal 还定义了一个相应的着色语言来实现图形渲染着色程序和并行计算程序。Metal 框架允许数据在运行时(runtime interface)、图形着色器(graphics shaders)、并行计算程序(compute functions)之间共享。
- 预编译的着色器:Metal 着色器可以在 Build 阶段连同你的 App 代码被编译,然后在运行时加载。这种工作流提供更好的代码生成以及简单的着色代码的调试(Metal 也支持运行时编译着色器代码)。
MTLCommandBuffer 提供的 Encoder 类型:
- MTLRenderCommandEncoder ,该类型的 Encoder 为一个渲染 pass 编码 3D 图形渲染指令。
- MTLComputeCommandEncoder ,该类型的 Encoder 编码并行数据计算任务。
- MTLBlitCommandEncoder ,该类型的 Encoder 支持在 buffer 和 texture 之间进行简单的拷贝操作,以及类似 mipmap 生成操作。
- MTLParallelRenderCommandEncoder 对象可以允许一个渲染 pass 被打散成多个子 Encoder 并分配到多个线程进行操作。
多线程 Metal Command Buffers
具体运用
目前网易云信第二代实时音视频 iOS 和 Mac 的 Metal 渲染架构,拓展了纹理输入渲染,如下图:
Vulkan 介绍
Vulkan 是一个用于图形和计算设备的编程接口,Vulkan 是一个跨平台的 2D 和 3D 绘图应用程序接口(API)。同 OpenGL® 一样,Vulkan™ 也由 Khronos 集团开发。它是 AMD Mantle 的后续版本,继承了前者强大的低开销架构,使软件开发人员能够全面获取 Radeon™ GPU 与多核 CPU 的性能、效率和功能。相对于 OpenGL,Vulkan™ 大幅降低了 CPU 在提供重要特性、性能和影像质量时的“API 开销” (CPU 在分析游戏的硬件需求时所执行的后台工作),而且可以使用通常通过 OpenGL 无法访问的 GPU 硬件特性。独特的跨 OS 支持:Vulkan™ 能够支持深入硬件底层的控制,为 Windows® 7、Windows® 8.1、Windows® 10 和 Linux® 带来更快的性能和更高的影像质量。Vulkan™API 还提供超高的 OS 兼容性、渲染特性和硬件效率。自动兼容 GCN 架构:目前只有基于 GCN 架构 的 Radeon™ 显卡拥有强大的“异步计算”功能,使显卡得以并行处理 3D 几何图形与计算工作量。
这个流程和 OpenGL 的使用流程很像,就是找到设备——创建上下文——创建命令队列——准备任务——发送执行。
Vulkan 的窗口系统
注意到,在移动设备上使用 OpenGL 时,我们必须通过 EGL 的 API 先准备好 Surface 和 Context,而在 Vulkan 标准里面,WSI 只是为Command Buffer 提供了 VkFrameBuffer,这个是图形渲染的输出。
Direct3D 介绍
Direct3D 是一种低级别的 API,用于通过呈现管道绘制基元,或用于通过计算着色器执行并行操作。Direct3D 9.0 使用 HLSL(全称 High Level Shading Language)编写 Vertex Shader 和 Pixel Shader,有助于着色器的编写和所产生代码的效率,并且大幅地缩短设计时间。Direct3D 10 着眼在高级绘图程序,全新的 graphics pipeline;新的 resource type: constant buffer、texture array。Texture array 可容许最多 512 个 Texture;resource 引进 view 的概念;guaranteed feature set;GPU 呈现多任务(multitasking)。Direct3D 11 新增以下的功能:镶嵌(Tessellation, 即曲面细分);多线程渲染(Multithread Render); 计算着色器(Compute Shader),支持 GPGPU,提供新版 HLSL 语言,与 nVidia 的 CUDA 或 OpenCL 功能类似。其他还有面向对象化的 Shader Model 5 等功能。之前 DirectX 10 还是单线程,文件访问与绘图指令共用同一个线程,容易造成画面迟缓的现象,与 DirectX 10 相比,Direct3D 11 有了更好的解决方案。DirectX 11 的 pipeline 新增 Hull Shader、Tessellator、Domain Shader 来实现 tessellation, 可以快速让成像 3D 的小三角型快速增加。至于 Computer ShadeWindows U 的实现,以 GPU 的平行处理能力与浮点运算能力来实现 CPU 的运算,能够同时支持 ATI 以及 Nvidia 的显卡,不受绘图流程的限制。DirectX11 还支持 Intel 的支持 Ray Tracing(光线跟踪)与 Rasterization(光栅化)技术,使 3D 效果更真实,更加逼真。
from《Direct3D 11.3 Functional Specification》from 《Direct3D 11.3 Functional Specification》随着 AR/VR 的发展,对高效的视频渲染技术提出了更高的要求。Apple 在 WWDC 2018 上宣称 iOS 12、macOS 10.14 之后弃用 OpenGL ES,系统的一些框架全面改成默认 Metal 支持;以及多家硬件厂商(高通、英伟达等)都致力于打造新一代渲染技术 Vulkan,包括谷歌也已经明确 Android 会支持 Vulkan;而微软一直努力开发 Direct3D。Vulkan、Metal、Direct3D 其三者背后设计的理念都是一致的,都是朝着高性能的图形渲染技术发展。并行计算架构、可扩展的渲染管线、GPU 驱动的渲染管线都将是发展的重要方向。因此我认为此后的发展必将形成一个三足鼎立的态势。
陶金亮,网易云信资深音视频客户端开发工程师;2016年2月加入网易,2017年8月加入网易云信团队,负责直播、短视频、IM、RTC SDK 的开发工作。
参考文献
- OpenGL ES Programming Guide