帧内块三种形状4x4,8x8(颜色),16x16
4X4有9重预测方式
16x16有4种
水平和垂直预测就是像素直接复制一样的,然后和原来的块做satd运算。稍微复杂点的就是DC和Plane预测。
先看看DC预测
void x264_predict_8x8c_dc_c( pixel *src )
{
int s0 = 0, s1 = 0, s2 = 0, s3 = 0;
/*
s0 s1
s2
s3
*/
for( int i = 0; i < 4; i++ )
{
s0 += src[i - FDEC_STRIDE];
s1 += src[i + 4 - FDEC_STRIDE];
s2 += src[-1 + i * FDEC_STRIDE];
s3 += src[-1 + (i+4)*FDEC_STRIDE];
}
/*
dc0 dc1
dc2 dc3
*/
pixel4 dc0 = PIXEL_SPLAT_X4( ( s0 + s2 + 4 ) >> 3 );//计算均值,作为4x4块的所有值
pixel4 dc1 = PIXEL_SPLAT_X4( ( s1 + 2 ) >> 2 );//计算均值,作为4x4块的所有值
pixel4 dc2 = PIXEL_SPLAT_X4( ( s3 + 2 ) >> 2 );//计算均值,作为4x4块的所有值
pixel4 dc3 = PIXEL_SPLAT_X4( ( s1 + s3 + 4 ) >> 3 );//计算均值,作为4x4块的所有值
for( int y = 0; y < 4; y++ )
{
MPIXEL_X4( src+0 ) = dc0;
MPIXEL_X4( src+4 ) = dc1;
src += FDEC_STRIDE;
}
for( int y = 0; y < 4; y++ )
{
MPIXEL_X4( src+0 ) = dc2;
MPIXEL_X4( src+4 ) = dc3;
src += FDEC_STRIDE;
}
}
总结就是先根据最上面一行计算两个均值,然后根据最左边一列计算两个均值,然后通过简单的平均计算出来dc0,dc1,dc2,dc3。分别填充到4个4x4的k块里面。
| S0 | S1 |
S2 | dc0 | dc1 |
S3 | dc2 | dc3 |
下面看plane预测
P(-1, -1) | H0 | H1 | H2 | H3 | H4 | H5 | H6 | H7 |
V0 |
|
|
|
|
|
|
|
|
V1 |
|
|
|
|
|
|
|
|
V2 |
|
|
|
|
|
|
|
|
V3 |
|
|
|
|
|
|
|
|
V4 |
|
|
|
|
|
|
|
|
V5 |
|
|
|
|
|
|
|
|
V6 |
|
|
|
|
|
|
|
|
V7 |
|
|
|
|
|
|
|
|
SumH = (H[4] - H[2]) + 2 * (H[5] - H[1]) + 3 * (H[6] - H[0]) + 4 * (H[7] - P);
SumV = (V[4] - V[2]) + 2 * (V[5] - V[1]) + 3 * (V[6] - V[0]) + 4 * (V[7] - P);
通过公式计算得到下面的4个常量值
int a =16*( src[-1+7*FDEC_STRIDE]+ src[7- FDEC_STRIDE]);
int b =(17* H +16)>>5;
int c =(17* V +16)>>5;
int i00 = a -3*b -3*c +16;
然后根据标准的公式计算出每一个像素值
/src[x][y] = 16 * (V[7] + H[7]) + m * ((H[4]-H[2]) + 2*(H[5]-H[1]) + 3*(H[6]-H[0]) + 4*(H[7]-H[1])) + n * ((V[4] - V[2]) + 2 * (V[5] - V[1]) + 3 * (V[6] - V[0]) + 4 * (V[7] - V[1])) + 16
for(int y =0; y <8; y++){
int pix = i00;
for(int x =0; x <8; x++){
src[x]=x264_clip_pixel( pix>>5);
pix += b;
}
src += FDEC_STRIDE;
i00 += c;
}