随着5G的成熟和普遍商用,带宽已经愈来愈高,传输视频变得更加容易。设备特别是移动设备算力的提高、存储容量的提高,使得视频技术的应用愈来愈普遍,不管是流媒体、泛娱乐、实时通讯,视频都带给了用户更加丰富的体验。git
视频相关的技术,特别是视频压缩,因其专业性,深刻开发的门槛较高。具体到视频实时通讯场景,视频压缩技术面临更严峻的挑战,由于实时通讯场景下,对时延要求很是高,对设备适配的要求也很是高,对带宽适应的要求也很是高,开发一款知足实时通讯要求的编解码器,难度也很高。以前的文章中,咱们已经在《深刻浅出理解视频编解码技术》一文中简要介绍了视频编解码基本框架,今天咱们将深刻剖析其中的预测模块,便于你们更好地理解视频编解码技术。github
01算法
颜色空间markdown
开始进入主题以前,先简单看一下视频是如何在计算机中进行表达的。视频是由一系列图片按照时间顺序排列而成,每一张图片为一帧。每一帧能够理解为一个二维矩阵,矩阵的每一个元素为一个像素。一个像素一般由三个颜色进行表达,例如用RGB颜色空间表示时,每个像素由三个颜色份量组成。每个颜色份量用1个字节来表达,其取值范围就是0~255。编码中经常使用的YUV格式与之相似,这里不做展开。框架
图一
复制代码
以1280x720@60fps的视频序列为例,十秒钟的视频有128072036010 = 1.6GB,如此大量的数据,不管是存储仍是传输,都面临巨大的挑战。视频压缩或者编码的目的,也是为了保证视频质量的前提下,将视频减少,以利于传输和存储。同时,为了能正确还原视频,须要将其解码。从最先的H.261开始,视频编解码的框架都采用了这一结构,如图所示。主要的模块分为帧内/帧间预测、(反)变换、(反)量化、熵编码、环内滤波。一帧视频数据,首先被分割成一系列的方块,按照从左到右从上到下的方式,逐个进行处理,最后获得码流。ide
图二
复制代码
02oop
帧内预测性能
视频数据被划分红方块以后,相邻的方块的像素,以及方块内的像素,颜色每每是逐渐变化的,他们之间有比较强的有类似性。这种类似性,就是空间冗余。既然存在冗余,就能够用更少的数据量来表达这样的特征。好比,先传输第一个像素的值,再传输第二个像素相对于第一个像素的变化值,这个变化值每每取值范围变小了许多,原来要8个bit来表达的像素值,可能只须要少于8个bit就足够了。一样的道理,以像素块为基本单位,也能够进行相似的“差分”操做。咱们从示例图中,来更加直观地感觉一下这样的类似性。优化
图三
复制代码
如图中所标出的两个8x8的块,其亮度份量(Y)沿着“左上到右下”的方向,具备连续性,变化不大。假如咱们设计某种特定的“模式”,使其利用左边的块来“预测”右边的块,那么“原始像素”减去“预测像素”就能够减小传输所须要的数据量,同时将该“模式”写入最终的码流,解码器即可以利用左侧的块来“重建”右侧的块。极端一点讲,假如左侧的块的像素值通过必定的运算能够彻底和右侧的块相同,那么编码器只要用一个“模式”的代价,传输右侧的块。固然,视频中的纹理多种多样,单一的模式很难对全部的纹理都适用,所以标准中也设计了多种多样的帧内预测模式,以充分利用像素间的相关性,达到压缩的目的。例以下图 (From Vcodex)所示的H.264中9种帧内预测方向。以模式0(竖直预测)为例,上方块的每一个像素值(重建)各复制一列,获得帧内预测值。其它各类模式也采用相似的方法,不过,生成预测值的方式稍有不一样。有这么多的模式,就产生了一个问题,对于一个块而言,咱们应该采用哪一种模式来进行编码呢?最佳的选择方式,就是遍历全部的模式进行尝试,计算其编码的所需的比特数和产生的质量损失,即率失真优化,这样明显很是复杂,于是也有不少种其它的方式来推断哪一种模式更好,例如基于SATD或者边缘检测等。编码
从H.264的9种预测模式,到AV1的56种帧内方向预测模式,愈来愈多的模式也是为了更加精准地预测未编码的块,可是模式的增长,一方面增长了传输模式的码率开销,另外一方面,从如此重多的模式中选一个最优的模式来编码,使其能达到更高的压缩比,这对编码器的设计和实现也提出了更高的要求。
图四
复制代码
03
帧间预测
如下5张图片是一段视频的前5帧,能够看出,图片中只有Mario和砖块在运动,其他的场景大可能是类似的,这种类似性就称之为时间冗余。编码的时候,咱们先将第一帧图片经过前文所述的帧内预测方式进行编码传输,再将后续帧的Mario、砖块的运动方向进行传输,解码的时候,就能够将运动信息和第一帧一块儿来合成后续的帧,这样就大大减小了传输所需的bit数。这种利用时间冗余来进行压缩的技术,就是运动补偿技术。该技术早在H.261标准中,就已经被采用。
图五
复制代码
细心地读者可能已经发现,Mario和砖块这样的物体怎么描述,才能让它仅凭运动信息就能完整地呈现出来?其实视频编码中并不须要知道运动的物体的形状,而是将整帧图像划分红像素块,每一个像素块使用一个运动信息。即基于块的运动补偿。下图中红色圈出的白色箭头即编码砖块和Mario时的运动信息,它们都指向了前一帧中所在的位置。Mario和砖块都有两个箭头,说明它们都被划分在了两个块中,每个块都有单独的运动信息。这些运动信息就是运动矢量。运动矢量有水平和竖直两个份量,表明是的一个块相对于其参考帧的位置变化。参考帧就是已经编码过的某一(多)个帧。
图六
复制代码
固然,传输运动矢量自己就要占用不少 bit,为了提升运动矢量的传输效率,一方面,能够尽量得将块划分变大,共用一个运动矢量,由于平坦区域或者较大的物体,他们的运动多是比较一致的,从 H.264 开始,可变块大小的运动补偿技术被普遍采用;另外一方面,相邻的块之间的运动每每也有比较高的类似性,其运动矢量也有较高的类似性,运动矢量自己也能够根据相邻的块运动矢量来进行预测,即运动矢量预测技术;最后,运动矢量在表达物体运动的时候,有精度的取舍。像素是离散化的表达,现实中物体的运动显然不是以像素为单位进行运动的,为了精确地表达物体的运动,须要选择合适的精度来定义运动矢量。各视频编解码标准都定义了运动矢量的精度,运动矢量精度越高,越能精确地表达运动,可是代价就是传输运动矢量须要花费更多的bit。H.261中运动矢量是以整像素为精度的,H.264中运动矢量是以四分之一像素为精度的,AV1中还增长了八分之一精度。通常状况,时间上越近的帧,它们之间的类似性越高,也有例外,例如往复运动的场景等,可能相隔几帧,甚至更远的帧,会有更高的类似度。为了充分利用已经编码过的帧来提升运动补偿的准确度,从H.264开始引入了多参考帧技术,即,一个块能够从已经编码过的不少个参考帧中进行运动匹配,将匹配的帧索引和运动矢量信息都进行传输。
那么如何获得一个块的运动信息呢?最朴素的想法就是,将一个块,在其参考帧中,逐个位置进行匹配检查,匹配度最高的,就是最终的运动矢量。匹配度,经常使用的有SAD(Sum of Absolute Difference)、SSD(Sum of Squared Difference)等。逐个位置进行匹配度检查,即常说的全搜索运动估计,其计算复杂度可想而知是很是高的。为了加快运动估计,咱们能够减小搜索的位置数,相似的有不少算法,经常使用的如钻石搜索、六边形搜索、非对称十字型多层次六边形格点搜索算法等。以钻石搜索为例,如图所示,以起始的蓝色点为中心的9个匹配位置,分别计算这9个位置的SAD,若是SAD最小的是中心位置,下一步搜索中心点更近的周围4个绿色点的SAD,选择其中SAD最小的位置,继续缩小范围进行搜索;若是第一步中SAD最小的点不在中心,那么以该位置为中心,增长褐色的5或者3个点,继续计算SAD,如此迭代,直到找到最佳匹配位置。
图七
复制代码
编码器在实现时,可根据实际的应用场景,对搜索算法进行选择。例如,在实时通讯场景下,计算复杂度是相对有限的,运动估计模块要选择计算量较小的算法,以平衡复杂度和编码效率。固然,运动估计与运动补偿的复杂度还与块的大小,参考帧的个数,亚像素的计算等有关,在此再也不深刻展开。
04
总结
本文介绍的预测技术,充分利用了视频信号空间上和时间上的相关性,经过多种设计精巧的预测模式,达到了去除冗余的目的,这是视频压缩高达千倍比例的关键之一。纵观视频编解码技术的发展历史,预测模式愈来愈多,预测的精确度愈来愈高,带来的压缩比也愈来愈高。如何快速高效地使用这些预测模式,也必然成为设计实现的重中之重,成为H.265/H.266/AV1这些新标准发挥其高效压缩性能的关键。关注拍乐云Pano,咱们将在后面的文章中为你们分享《视频编解码系列》的更多技术干货。
图片出处:
图一:
图四:
H.264/AVC Intra Prediction