前些时间,我在知识星球上创建了一个音视频技术社群:关键帧的音视频开发圈,在这里群友们会一起做一些打卡任务。比如:周期性地整理音视频相关的面试题,汇集一份音视频面试题集锦,你可以看看《音视频面试题集锦 2022.04》。再比如:循序渐进地归纳总结音视频技术知识,绘制一幅音视频知识图谱。
下面是 2022.04 月知识图谱新增的内容节选:
1)图谱路径:采集/音频采集/声音三要素/响度
- 主观计量
- 响度,反映人耳感受到的声音强弱。
- 响度级,两个声音在听觉上认为是相同的响度时,就可以把 1000 Hz 纯音的这个声压级规定为该频率纯音的「响度级」。单位:方(Phon)。
- 客观计量
- 声能,声音在介质中传播时,使媒介附加的能量。质点振动动能和质点偏离平衡位置所具有的势能的总和。单位:瓦。
- 声强,单位时间内通过垂直于声波传播方向的单位面积的平均声能。单位:瓦/平方米。
- 声强级,人耳允许的声强范围太大;心理物理学的研究表明,人对声音强弱的感觉并不是与声强成正比,而是与其对数成正比。因此引入「声强级」。
- 声压,声波通过媒质时,由振动所产生的压强改变量。单位:牛顿/平方米、帕斯卡。实际中更多使用声压来代表声波的振幅表现:人耳表现为压力敏感组织;压力或压强具有相对容易进行实地测量。
- 声压级,人耳允许的声压范围太大;人对声音的强弱的感觉是与声压的对数成正比。因此引入「声压级」。通常我们说声音大小有多少分贝,说的就是「声压级」。
2)图谱路径:采集/音频采集/声音三要素/音调
- 主观计量
- 音调,人耳对声音高低的主观感受。单位:美(mel)。取频率 1000Hz、声压级为 40 分贝的纯音的音调作标准,称为 1000 美。另一些纯音,听起来调子高一倍的称为 2000 美,调子低一倍的称为 500 美,依此类推,可建立起整个可听频率内的音调标度。
- 科学音调记号法,两个音符之间若频率相差整数倍,则听起来非常相似。因此,我们将这些音放在同一个「音调集合」中。两个音符间若相差一倍的频率,则我们称两者之间相差一个八度。
- 客观计量
- 频率,声音振动的快慢。单位:赫兹。
3)图谱路径:采集/音频采集/声音数字化/采样率
- 奈奎斯特采样定理:一般实际应用中保证采样频率为信号最高频率的 2.56~4 倍。
- 人类发声在 5kHz 内,听觉范围是 20~20kHz 内。数字音频的采样率需要在 40k 以上。
- 44100Hz 由来:最早的数字录音由一台录像机加上一部 PCM 编码器制作的,由于当时使用的是 PAL 录像制式(帕制,与之对应的有 NTSC),场频 50 Hz,可用扫描线数 294 条,一条视频扫描线的磁迹中记录 3 个音频数据块,把它们相乘,就得到了 44100 这个奇葩数字。
4)图谱路径:采集/音频采集/声音数字化/量化位深
- 对模拟音频信号的幅度轴进行数字化,它决定了模拟信号数字化以后的动态范围。
- 8 bit 位深对应 48 分贝的动态范围(最大声压级 = 20 * lg(2^8) = 48.16),16 bit 位深对应 96 分贝的动态范围,24 bit 位深对应 144 分贝的动态范围。
5)图谱路径:采集/视频采集/图像/颜色模型
- CIE RGB 颜色模型:基于人眼视觉感知三原色理论,CIE 通过大量实验数据建立了 RGB 颜色模型,标准化了 RGB 表示。
- CIE XYZ 颜色模型:为了解决 RGB 模型中与负光混合所带来的种种问题,CIE 从数学上定义了三种标准基色 XYZ,形成了 CIE XYZ 颜色模型。
- NTSC YIQ 颜色模型:在模拟电视时代,RGB 工业显示器要求一幅彩色图像由分开的 R、G、B 信号组成,而电视显示器则需要混合信号输入,为了实现对这两种标准的兼容,NTSC 基于 XYZ 模型制定了 YIQ 颜色模型,实现了彩色电视和黑白电视的信号兼容。
- PAL YUV 颜色模型:为了解决 NTSC YIQ 的组合模拟视频信号中分配给色度信息的带宽较低而影响了图像颜色质量的问题,PAL 引入了 YUV 颜色模型,支持用不同的采样格式来调整传输的色度信息量。
- ITU-R YCbCr 颜色模型:进入数字电视时代,ITU-R 为数字视频转换制定了 YCbCr 颜色模型,成为我们现在最常使用的颜色模型。
- 伽马校正:在早年 CRT 显示器流行的年代,我们遇到了显示伽马问题,从而引入了伽马校正过程并延用至今。
6)图谱路径:采集/视频采集/纹理/数据与纹理转换/纹理转数据(GPU → CPU)/Android 方案
- glReadPixels
- OpenGL ES 2.0 和 3.0 均支持,兼容性较好。
- 会影响 CPU 时钟周期,同时 GPU 会等待当前帧绘制完成,读取像素完成之后,才开始下一帧的计算,造成渲染管线停滞。
- 读取的是当前绑定 FBO 的颜色缓冲区图像,所以当使用多个 FBO(帧缓冲区对象)时,需要确定好我们要读那个 FBO 的颜色缓冲区。
- 在大分辨率图像的读取时性能略差。目前通用的优化方法是在 shader 中将处理完成的 RGBA 转成 YUV (一般是 YUYV 格式),然后基于 RGBA 的格式读出 YUV 图像,这样传输数据量会降低一半,性能提升明显。
- PBO(Pixel Buffer Object,像素缓冲区对象)
- OpenGL ES 3.0 才支持,在 Android 上有兼容性问题。
- PBO 类似于 VBO(顶点缓冲区对象),开辟的也是 GPU 缓存,而存储的是图像数据。PBO 不连接到纹理,且与 FBO (帧缓冲区对象)无关。
- PBO 可以在 GPU 的缓存间快速传递像素数据,不影响 CPU 时钟周期,支持异步,主要用于异步像素传输。
- 以空间换时间,通常需要多个 PBO 交替配合使用来提升性能。
- ImageReader
- ImageReader 是 Android SDK 提供的 Java 层对象,其内部会创建一个 Surface 对象。
- EGL 创建 OpenGL 上下文环境时,eglCreateWindowSurface 需要传入 ANativeWindow 对象,而 ANativeWindow 又基于 Surface 对象创建的。可以利用 ImageReader 对象的 Surface 对象作为 OpenGL 展示渲染结果的 Window Surface ,每次渲染的结果可以通过 ImageReader 对象的回调获取。
- HardwareBuffer
- 一个更底层的对象,代表可由各种硬件单元(GPU、传感器或上下文集线器或其他辅助处理单元)访问的缓冲区。Native 层叫 AHardwareBuffer,AHardwareBuffer 读取显存(纹理)图像数据时,需要与 GLEXT 和 EGLEXT 配合使用。
- HardwareBuffer 是 Android 8 API >= 26 提供的用于替换 GraphicBuffer 的接口,在 API <= 25 时可以使用 GraphicBuffer。两者在使用步骤上基本一致,均可以用于快速读取显存(纹理)图像数据,但是 HardwareBuffer 还可以访问其他硬件的存储器,使用更广泛。
- 性能和实现选择
- 大分辨率情况,ImageReader、PBO、HardwareBuffer 明显优于 glReadPixels 方式。一般 HardwareBuffer、ImageReader、PBO 三种方式性能相差不大,HardwareBuffer 理论上性能最优。
- Native 层建议选择 PBO 方式,超大分辨率建议尝试 HardwareBuffer 方式,Java 层建议使用 ImageReader 方式。
下面是 2022.04 月的知识图谱新增内容快照(图片被平台压缩不够清晰,可以加文章后面微信索要清晰原图):
2022.04 知识图谱新增内容