目录
帧间预测
块大小
参考帧和运动矢量
运动矢量
运动搜索
1、全搜索算法
2、钻石搜索算法(菱形搜索算法)
3、六边形搜索算法
搜索起始点的确定
快速搜索与全搜索的优缺点
非整像素的处理
亚像素差值
亚像素精度运动搜索
运动矢量预测
SKIP模式
视频编码流程
前后两帧图像变化比较小,视频的时间相关性。比较容易从前一帧中找到一个跟当前编码块差距很小的块作为预测块,这样编码块减去预测块得到的残差块的像素值很多都是0,压缩效率很高。
通过在已经编码的帧里找到一个块来预测待编码的像素,从而达到减少时间冗余的目的。
帧间预测可以在多个已经编码的图像里去寻找参考像素块,称之为多参考。单参考和多参考其底层原理是一样的,只是多参考需要多搜索去寻找参考块。
帧间预测的帧类型
P帧,只要参考前面的帧;
B帧 既可以参考前面的图像也可以参考后面的图像。B帧一个编码块可以有两个预测块,这两个预测块分别由两个参数预测得到。最后加权得到最终预测的块。
下面看下P帧单参考帧的预测原理
相比帧内预测,帧间预测的块划分类型要很多。
宏块大小16x16,可以划分为 16x8 8x16 8x8三种。其中8x8 可以继续划分为 8x4,4x8和 4x4,这是亮度块的划分。
在YUV 4:2:0中,色度快宽高大小都是亮度块的一半。亮度宏块的划分方式如下图所示。
在H264标准中,P帧最多支持16个参考帧中选出一个作为编码块的参考帧,其中一个帧中的不同块可以选择不同的参考帧,这就是多参考。
通常在RTC场景中,P帧中的所有块都参考同一个参考帧,并且一般会选择当前编码帧的前一帧作为参考帧。
表示编码帧中编码块和参考帧中预测块之间位置的差值
目标在参考帧中找到一个块,称之为预测块,并且这个预测块与编码块的差距最小。
运动搜索的方法
逐个像素遍历,一定能找到最相似的预测块
缺点:浪费时间
搜索块的左上角像素点
以一个菱形的模式去寻找最优预测块。
思想:以搜索的起始点作为菱形的中心点开始。以该中心点为左上角像素的16X16的块作为预测块,求得残差块并求得像素绝对值之和。
之和对菱形4个点分布做同样的操作,求得SAD(残差块像素值绝对值之和),选择最小的为最佳匹配点。
如果最佳匹配点再菱形中心,则终止搜索;
如果不是菱形中心,则以当前最佳匹配点为中心点,继续搜索,直到找到最佳匹配点。
思想:
搜索起始点作为六边形中心点,求得中心点左上角像素的预测块的SAD,之后对六边形角上的点做同样的操作求得SAD,得到最小的SAD,为最佳匹配点。
如果最佳匹配点为中心点,测以改中心点的菱形和正方形各进行一次精细化搜索。找到中心点,菱形四个点和正方形四个点中最小的SAD为最佳匹配点。
如果最佳匹配点不是六边形的中心点,则以当前最佳匹配点为六边形的中心,继续搜索。直到找到为止。
当前编码块的左边块,右边块,左上角块,右上角块的的运动矢量。一般会通过相邻已经编码块的运动矢量来预测当前块的运动矢量,这个预测的运动矢量也常用作搜索起点。
快速搜索速度快很多,但预测到的块不一定是全局最优预测块,有可能是局部最优预测块。
快速搜索算法相比全搜索算法压缩性能下降很小,速度却块十几倍到几十倍。一般选择快速搜索。
如何物体运动不是整像素如何处理?
运动0.5像素或者0.25像素,预测块是与编码块的小车位置相差0.5或者0.25像素,得到的残差会大,压缩效率低一些。
解决办法:用差值的方式将半像素和1/4像素算出来,也当一个像素。
通过已经有的像素点经过一定的加权计算得到要求得的像素。
先通过整像素差值得到半像素,然后再通过半像素和整像素差值得到1/4像素。
半像素差值在参考帧中差值得到一辆新的小车,从而就可以解决之前预测块和编码块位置不重合问题。但插值得到的小车跟原始的小车的对应像素点的像素值并不是完全一样(插值得到的像素点是利用滤波算法加权平均得到)
因此 半像素差值得到的预测块并不一定比整像素预测块的残差小,只是多了选择块
在整像素预测块、半像素预测块和1/4预测块里选择一个最好的。
在整像素运动搜索的基础上,再做一次精细的亚像素运动搜索。
1、先通过快速搜索算法进行像素运动搜索算法得到整像素的运动矢量
2、对参考帧进行半像素和1/4像素差值
3、以整像素运动矢量指向的整像素为起点,进行砖石搜索算法。分别求得中线点及上、下左右
四个半像素点对应预测的残差块,得到SAD值,取SAD值最小的点为最佳匹配点
4,以半像素运动搜索的最佳匹配点为起点,分别求得上下左右四个1/4像素点对应预测块的残差块,得到SAD值,取得最小的点为最佳匹配点。
运动矢量直接编码到码流中吗?不是的
运动矢量先用周围相邻快的运动矢量预测一个预测的运动矢量,称为MVP。将当前运动矢量与MVP的残差称之为MVD,然后编码到码流中去。MVP+MVD就是运动矢量了。
思想:
取当前块左边块A,上边块B,右上块C。如果右上块不存在或者参考帧与当前编码宏块不同,则使用左上块D替代C。
求得A,B,C块的参考帧有多少个与当前编码块的参考帧相同,即为count
如果count > 1,则取A,B,C块运动矢量的中值
如果count = 1,则直接将这个块的运动矢量作为MVP
如果 count=1,并且B,C都不存在,则直接将A作为运动矢量为MVP
如果上述条件不满足,则取A,B,C块运动矢量的中值。
运动矢量MVP,也就是说MVD为(0,0),同时残差块经过变化量化后系数都是等于0,那么当前编码的模式是SKIP
压缩效率特别高
帧间预测算法过程如下(以单参考帧为例)
1、先判断当前宏块是不是可以作为SKIP块(通过相邻已经编码的块是不是存在SKIP块,和当前块使用MVP做运动矢量之后,残差块变换量化后是不是都是0等算法来判断)如果可以作为SKIP块则模式选择结束。
2、宏块大小16x16,先不划分宏块,直接使用16X16大小的块,在参考帧中进行运动搜索,得到运动矢量和预测块,通过MVP求得MVD,通过预测块得到残差块,并求得残差块的SATD值(残差块经过Hadamard变换之后求得绝对值再求和),估计MVD的编码后占用的字节数,将两个值加起来作为cost16x16
3、将16x16块划分为4个8x8的子块,分别进行运动搜索,并求得每一个8X8子块的MVD和残差块,最后分别得到4个cost8x8
1)如果4个8x8子块之和小于16x16块的cost16x16的话,再分别对每一个8x8子块划分成4个4x4子块,再进行运动搜索,得到每一个4x4子块的cost4x4
如果4个costx4x之和小于cost8x8,则将8x8划分成4x8 和 8x4两种子块,分别求得cost4x8和cost8x4,再根据4个cost4x4和2个cost4x8 2个cost8x4的大小,选择最终的8x8划分的方式,并将对应的cost值更新到cost8x8
否则不进行划分。
2)如果4个8x8子块的最新的cost8x8之和还是小于cost16x16的话,再将16x16划分成两个8x16和16x8子块,并分别求得cost8x16和cost16x8,对比x8x 8x16 16x8的值,并最终确定16x16块的划分方式。
否则不进行划分。
4,得到了编码宏块的帧间模式之后,还需要对编码块进行帧内模式的选择。在p帧和B帧的宏块也是可以使用帧内模式。需要看帧间模式cost更小还是帧内模式cost更小。选择其中小的一个。一般来说P帧和B帧宏块大多数是帧间模式小。