预测宏块是由原宏块的左方和上方的像素构成的,在x264_slicetype_mb_cost函数中可以验证这一点,我在该源码中摘取一段:
static void x264_slicetype_mb_cost( x264_t *h, x264_mb_analysis_t *a,
x264_frame_t **frames, int p0, int p1, int b,
int dist_scale_factor, int do_search[2], const x264_weight_t *w,
int *output_inter, int *output_intra )
{
//......
lowres_intra_mb:
if( !fenc->b_intra_calculated )
{
ALIGNED_ARRAY_16( pixel, edge,[36] ); //pixel edge[36]
pixel *pix = &pix1[8+FDEC_STRIDE];
pixel *src = &fenc->lowres[0][i_pel_offset]; //i_pel_offset = 8 * (i_mb_x + i_mb_y * i_stride);说明src指向低分辨率子图像的某个宏块
const int intra_penalty = 5 * a->i_lambda;
int satds[3]; //存放satds计算结果
int pixoff = 4 / sizeof(pixel); //pixoff等于4;
/* Avoid store forwarding stalls by writing larger chunks */
//1.拷贝宏块的正上方一行的像素到pix。
memcpy( pix-FDEC_STRIDE, src-i_stride, 16 * sizeof(pixel) );
//2.拷贝宏块左边边缘的像素到pix。
for( int i = -1; i < 8; i++ )
M32( &pix[i*FDEC_STRIDE-pixoff] ) = M32( &src[i*i_stride-pixoff] );
//3.对8*8宏块进行satds计算。
h->pixf.intra_mbcmp_x3_8x8c( h->mb.pic.p_fenc[0], pix, satds );
int i_icost = X264_MIN3( satds[0], satds[1], satds[2] );
//......
}
//......
}
我们先看第1,2步实际上是先将fenc->lowres中一个8*8宏块附近的内存拷贝到pix1内存块中,如下图:
lowres_copy.png
从图中我们看到,其实拷贝的是宏块左边和上方的像素值,后面我们将看到,x264会将对这些像素进行平均来构造新的宏块,然后跟原图像求差值,再进行Hadamard变换,然后求得satds。
网友评论