涉及硬件的音视频能力,比如采集、渲染、硬件编码、硬件解码,通常是与客户端操作系统强相关的,就算是跨平台的多媒体框架也必须使用平台原生语言的模块来支持这些功能
本系列文章将详细讲述移动端音视频的采集、渲染、硬件编码、硬件解码这些涉及硬件的能力该如何实现,其中的示例代码,在我们的 Github 仓库 MediaPlayground 中都能找到,与文章结合着一起食用,味道更棒哦
本文为该系列文章的第 4 篇,将详细讲述在 iOS 平台下如何使用 OpenGL 实现视频画面的渲染,对应了我们 MediaPlayground 项目中 SceneVCVideoRenderOpenGLES 涉及到的内容
往期精彩内容,可参考
音视频基础能力之 iOS 视频篇(一):视频采集
音视频基础能力之 iOS 视频篇(二):视频硬件编码
音视频基础能力之 iOS 视频篇(三):视频硬件解码
前言
之前讲了视频采集和硬件编码,得到的数据都是未编码的原始图像数据,那要如何将这些数据显示到手机屏幕上呢,就要用到渲染引擎了
iOS 中的渲染引擎有 2 种,分别是 OpenGL 和 Metal。有经验的小伙伴应该知道,Apple 从 iOS 12 开始就把 OpenGL 标记为废弃了,转而推荐使用 Metal,为的是在 iOS 设备上能有更好的图像性能表现,但 OpenGL 毕竟是跨平台的渲染引擎,在音视频这种对跨平台需求比较强烈的业务场景中,还是有用武之地的,不能一棒子打死,Android 和华为的纯血鸿蒙都还在使用 OpenGL
这么多年在各大厂的经验,笔者也亲眼见过许多改不动的老项目还在用 OpenGL,不是改不了 Metal,而是风险太大,收益太小,投入产出比不足以推动开发人员在 iOS 平台上把 OpenGL 的内容用 Metal 全部重新实现一遍,因此 OpenGL 还是值得拿出来讲一讲的
简单介绍OpenGL
OpenGL 是什么,全称 Open Graphics Library,简单理解就是一套用来操作图像的接口规范,最早的 1.0 版本是在 1992 年 6 月 30 号发布的,内部的具体逻辑是由各个操作系统平台的显卡生产商自行实现的,例如 Apple 生态中的 OpenGL 就是由 Apple 进行实现的
iOS 中使用的 OpenGL,严格来说应该叫 OpenGL ES,也就是 OpenGL for Embedded Systems,是针对手机、游戏主机等嵌入式设备进行设计的,算是 OpenGL 的子集
介绍就先讲这么多,更多 OpenGL 的历史背景,可以自行 google
学习思路
正常的逻辑思维中,要上手 OpenGL,首先要学习一大堆的基础知识,比如 OpenGL 中的各种概念(纹理、着色器、帧缓存、顶点坐标、纹理坐标),再上手编程
笔者也走过这条路,发现这条路异常的难走,因为最开始要积累的基础知识太多了,等学完并深入理解,可能几天就过去了,等到要串起来使用的时候,发现有些知识都忘记了,还得回头再看概念,效率比较低。因此本文会换个角度,先从宏观视角告诉大家怎样把 OpenGL 中的各种概念串联起来,实现图像的渲染,再去深挖各个环节中的细节
在阅读的过程中,大家可能会针对某个环节的某个操作产生各种疑问,没关系,本篇文章先教大家怎么做,下篇文章会根据本文中的技术点进行更详细的剖析,来解释为什么要这么做
宏观流程
在开始之前,要知道一个概念,就是执行图像渲染的模块,我们称之为渲染管线,这在不同的渲染引擎中都是类似的
如果把 OpenGL 的渲染管线想象成一个黑盒,支持输入一份图像数据 A,输出一份图像数据 B。图像渲染的过程,其实就是图像 A 经过 OpenGL 渲染管线之后变成了图像 B 的过程
我们把图像渲染,想象成手工绘画,必需的物理元素有画板、画纸、画笔、颜料,还有个最关键的元素,就是我们人脑中的创意
简单来说绘画的流程,就是我们把人脑中的创意用画笔 + 颜料等工具绘制到画纸的过程。那如果把图像渲染跟绘画进行类比,就会有如下的对应关系
- 人脑中的创意 => 作为输入的图像 A
- 画纸 => 作为输出的图像 B
- 画板 => OpenGL 的帧缓存
- 画纸上能画的区域 => OpenGL 中的顶点坐标
- 人脑中的图像要画上画纸的区域(可能选一部分画,也可能全部都画) => OpenGL 中的纹理坐标
- 人脑中对于图像的色彩分配 => OpenGL 中的着色器程序
这里引入了顶点坐标、纹理坐标、着色器程序、帧缓存的概念,都是图像渲染过程的必需要素,需要记住它们在绘画例子中的对应关系,图像渲染的数据流程,就变成了这样。理解了宏观流程,我们就可以开始看微观细节了
微观细节
下面讲用一个例子来展开讲 OpenGL 渲染的细节
场景:将视频采集之后得到的 NV12 图像数据渲染在屏幕上
注意:因为原始图像数据的格式是 NV12,根据 NV12 格式的特点,数据会分为 Y 和 UV 两个平面,因此要有 2 个输入图像才能正常进行渲染,宏观流程会变成这个样子