Android直播软件搭建从入门到精通之视频编码技术概述
前言
视频编码技术主要是将采集到的图片模拟信号转成数字信号,然后对数字信号进行编码,生成压缩数据,便于存储和网络传输,用户播放视频格式的文件或流时,会将压缩数据进行解码,还原成原始数据,送到显示设备播放。
一.视频采集
图像采集功能由图像传感器实现,目前市场上用得做多的是CMOS传感器。
大家都知道颜色是由RGB三原色组成,所以采集图像最简单的方法就是用三块滤镜,红色的滤镜透过红色的波长,绿色的滤镜透过绿色的波长,蓝色的滤镜透过蓝色的波长。但这样价格昂贵,且不好制造,因为三块滤镜都必须保证每一个像素点都对齐。
1974年,柯达公司科学家Bryce Bayer发明了拜耳阵列,后来被广泛运用数字图像。它的原理就是在镜头下加上色彩滤波器(就像一个个红绿蓝的点)
光经过色彩滤波器过滤后会形成一个个RGB阵列
每个点的真实颜色由周围的RGB插值运算出来。由于人眼对绿色最敏感,所以它采样了一半的G,RB各1/4。
光通过镜头,在色彩滤波器过滤之后,投射到感光元件上,生成电荷数据,经过放大器及A/D转换电路,最终转换成数字信号。
采集到的图像一般还需要经过其他处理如色彩校正、伽马校正、白平衡等,这里就不介绍了。
二.视频编码
2.1 为什么要对视频进行编码?
视频采集设备输出的是原始的YUV数据,假如分辨率为1920x1080,一帧的数据就是3.1M,一般视频为30fps。我们可以算一下,如果不经压缩,我们想在线看1080p的视频,需要93MB/s的带宽;存储一部2小时的电影需要672G!这显然是无法接受的。
2.2 视频为什么可以被压缩?
视频信息之所以存在大量可以被压缩的空间,是因为其中本身就存在大量的数据冗余。其主要类型有:
时间冗余:视频相邻的两帧之间内容相似,存在运动关系
空间冗余:视频的某一帧内部的相邻像素存在相似性
编码冗余:视频中不同数据出现的概率不同
视觉冗余:观众的视觉系统对视频中不同的部分敏感度不同
2.3 视频编码框图
如上图所示,一个视频编码器分为3个主要功能单位:时域模型、空域模型、熵编码。
时域模型的输入是原始视频,输出是残差和运动向量。通常一个视频相邻的帧之间有很大的相似性,利用这个特性我们可以通过当前帧的前面或后面的帧作为参考来预测当前帧。
我们通过对比当前帧和参考帧的差异,用一组运动向量来表示这个参考帧到预测帧的运动信息,这个过程也叫运动估计。
预测帧一般跟当前帧(真实数据)有差异,这个差异部分就叫残差,计算残差的过程过程叫运动补偿。我们可以用两个公式来表示:
//运动估计过程
参考帧 + 运动向量 = 预测帧
//运动补偿过程
当前帧(真实数据) - 预测帧 = 残差
复制代码
频域模型的输入是残差。残差图像一般都是一些纹理细节,在空间上有很多的冗余。我们可以通过图片压缩技术(详情见[JPEG编解码原理](https://juejin.im/post/6844904083904544781)),对图像进行频域变换,再经过量化,得到压缩后的残差系数,它与量化系数一起作为频域模型的输出。
熵编码,将输入的二进制数据进一步压缩,消除统计冗余。如哈夫曼编码(出现概率高的数据用短二进制码表示)、游程编码(用一个游标来描述连续多个0的二进制),输出为编码后的二进制数据,这个过程是无损的。
2.4 时域模型
时域模型的作用是消除连续帧之间的时域冗余。上文提到过,利用相邻帧来预测当生成预测帧,这种整个帧的模型,残差数据量依然很大,一般不采用。现在通用的编码规范,如H264和MPEG-4都是用宏块的方式来建立时域模型。步骤如下:
- 将图片分成许多 M * N 大小的块
- 在参考帧中以预测宏块位置为中心,找到最佳匹配的 M * N 块(常见做法是计算当前块和比较块的残差能量,能量最小的就是最佳匹配块),这个过程就叫运动估计
- 最佳匹配块减去预测块得到 M * N 的残差块(运动补偿)
2.4.1 基于宏块的运动估计
运动估计
2.4.2 基于宏块的运动补偿
参考帧
残差(16 x 16单位的运动补偿)
残差(4 x 4单位的运动补偿)
可见宏块单位越小,运动估计越精准,得到的残差能量就越小。
16x16宏块运动矢量图
2.4 频域模型
频域模式跟图片压缩原理相似,可以参考这篇文章:JPEG编解码原理
2.5 帧内预测
前文讲了相邻帧之间的预测,其实大多数时候一副图像的相邻像素之间也存在关联性,我们可以根据相邻的像素推导出这就叫帧内预测。例如下图:我们可以根据A、B、C三个像素点的来推测X
//编码侧
预测公式 P(X) = (2A + B + C)/4
残差 R(X) = X − P(X)
//残差和预测公式一起作为编码数据传输
//解码侧
解析预测公式 P(X) = (2A + B + C)/4
根绝预测公式和残差一起重建X像素 X = R(X) + P(X)
复制代码
H.264 4x4宏块支持如下9种帧内预测模式
2.6 熵编码
熵参考这篇文章:熵编码
2.7 视频编码小结
其实业界发布的视频标准规范大多遵循统一的设计模型,包括运动估计和补偿、变换编码和熵编码等技术。这个模型又常常被称为DPCM/DCT视频编解码器混合模型。H.261、H.263、H.264、MPEG-1、MPEG-2、MPEG-4都遵循该模型。下图就是一个典型的DPCM/DCT编码器
上图编码器有两条主要的数据流路径:从左到有(编码),从右到左(重建)。
编码数据流如下:
1.以16x16宏块为单位,对输入视频帧进行编码;
2.运动估计函数从参考帧中寻找当前宏块的相似区域,该区域和当前宏块的位移即为运动矢量MV;
3.根据MV生成运动补偿的预测P宏块(16x16区域);
4.用当前宏块减去P生成残差;
5.将D划分成8x8或4x4的子块,分别进行DCT变换;
6.子块量化(X);
7.子块的DCT系数重新排序,再进行游程编码;
8.编码后的系数、运动矢量和宏块头信息经过熵编码后生成压缩的比特流。
重建数据流如下:
1.每个量化后的宏块X经过尺寸变换,反DCT变换生成解码后的残差。注意和原宏块会有差异,因为量化过程损失了精度;
2.残差与运动补偿预测宏块P相加得到重建宏块,所有重建宏块一起得到重建帧。
重建帧可以用来作为参考帧,用于的编码。
三.视频解码
视频解码就是视频编码的逆向过程。
解码器数据流:
1.熵解码器从压缩比特流中解码出变换系数、运动矢量和宏块头信息;
2.游程解码并重排序之后,得到量化的变换宏块X;
3.X经过尺寸变换、反向DCT变换生成解码后的残差;
4.根据运动矢量,在解码器重建的参考帧中找到16x16的匹配区域,作为运动补偿的预测宏块P;
5.残差与P相加得到重建宏块,所有重建宏块一起得到重建帧。
可以用来显示或作为下一帧的参考帧。
下一篇: 音视频系列技术之SDL播放PCM