帧内预测是视频编码中非常重要的一环,H.264的帧内预测包括亮度预测和色度预测,其中亮度预测有四种类型:Intra_4x4,Intra_8x8,Intra_16x16和I_PCM。这里主要讲解Intra_4x4和Intra_16x16。需要注意的是用于帧内预测的相邻像素必须是在做去块滤波之前。同时,所有预测函数的调用实际上都是在模式决策这一环进行的,模式决策是个比较复杂且耗时的过程,有机会再仔细研究。
Intra_4x4
下图是Intra_4x4预测是示意图,其中小写字母a-p是当前要进行帧内预测的4x4块,而大写字母则是预测时需要用到的13个相邻像素,且它们均是编码后重新解码得到的像素值(即并非是原始像素值)。这些像素的可用性由上一篇文章说到的get4x4Neighbour()函数得到,额外需要注意的几点是:
- 如果相邻4x4块当前还未编码则不可用(按照标准的编码顺序会出现这种情况)。
- 当UseConstrainedIntraPred的值为真时帧间编码的像素也不能用于进行帧内预测。
- 若E-H像素不可用,可以使用D的值代替这几个像素的值。
Intra_4x4共有9种预测模式,以0-8表示,分别对应了不同的方向,如图所示。这些预测模式所利用到的相邻像素有所不同,若需要的相邻像素不可用,则表明该预测模式不可用,这种情况在第一行/列宏块中尤为严重,需要注意。这些预测模式的对像素值的计算方法均是一种线性关系,具体公式可以参考标准,此处不做赘述。编码时会从可用的模式中选取最佳的预测模式,编码最佳预测模式Mode的方法如下:
- 先根据标准中的方法从左邻块和上邻块的帧内预测模式估计出一个最可能的预测模式MPM。
- 若MPM=Mode,则直接编码一个1作为标志位即可。
- 若MPM!=Mode,则先编码一个0作为标志位,然后编码固定的三位来表示最佳预测模式。
- 固定三位的编码方法是:若MPM>Mode,则编码结果为Mode所代表的序号的二进制表示(由前提条件知道其值最大不超过8,故三位即可表示);若MPM<Mode,则编码结果为Mode-1所代表的序号的二进制表示(由前提条件知道其值最大可能为9-1=8,最小为1-1=0,仍然可以用三位表示)。
1 | int mode_decision_for_I4x4_blocks_JM_High (Macroblock *currMB, int b8, int b4, int lambda, distblk* min_cost) |
该函数在rd_intra_jm.c中,是在模式决策时进行调用的,包含了完整Intra_4x4预测模式的计算与决策。
1 | void set_intrapred_4x4(Macroblock *currMB, ColorPlane pl, int img_x,int img_y, int *left_available, int *up_available, int *all_available) |
该函数在intra4x4.c中,用于判断相邻4x4块像素的可用性并赋值。
1 | void get_intrapred_4x4(Macroblock *currMB, ColorPlane pl, int i4x4_mode, int img_x, int img_y, int left_available, int up_available) |
该函数在intra4x4.c中,用于调用不同预测模式的计算方法。
1 | void generate_pred_error_4x4(imgpel **cur_img, imgpel **prd_img, imgpel **cur_prd, int **m7, int pic_opix_x, int block_x) |
该函数在intra4x4.c中,用于计算像素的预测误差,用于后续编码。
Intra_16x16
Intra_16x16是对整个宏块进行预测,因此相对简单,共有四种预测模式,与Intra_4x4有些相似,用到了上方宏块的16个像素和左方宏块的16个像素,详见标准。其预测模式的编码比较特别,并非是单独编码,而是与CBP元素一起联合编码的,具体可参考标准的表格。
1 | int mode_decision_for_I16x16_MB (Macroblock* currMB, int lambda) |
以上两个函数位于rd_intra_jm.c中,是在模式决策时进行调用的,流程和Intra4x4也是一样的。
1 | distblk find_sad_16x16_JM(Macroblock *currMB) |
该函数在intra16x16.c中,与Intra4x4的相应函数相似,但这里主要用的是SAD作为最佳模式的衡量值(当然,如果有特别设置的情况下也是可以使用RDO作为度量的),但实际计算的一般是SATD,这点没有深究。