case X264_ME_DIA:
i = 0;
do
{
DIA1_ITER( bmx, bmy ); 菱形搜索算法
if( (bmx == omx) & (bmy == omy) )避免搜索重复循环
break;
if( !CHECK_MVRANGE(bmx, bmy) )检查是否越界
break;
} while( ++i < i_me_range );
break;
#define DIA1_ITER( mx, my )\
{\
omx = mx; omy = my;\ omx,omy为旧的MV
COST_MV_X4( 0,-1, 0,1, -1,0, 1,0 );\ 调用COST_MV_X4计算小菱形的4个顶点的cost,并与中心点比较出最小的cost点
}
#define COST_MV_X4( m0x, m0y, m1x, m1y, m2x, m2y, m3x, m3y )\
{\
uint8_t *pix_base = p_fref + omx + omy*m->i_stride[0];\找到具体像素点
h->pixf.fpelcmp_x4[i_pixel]( m->p_fenc[0],\函数调用,后面详细讲
pix_base + (m0x) + (m0y)*m->i_stride[0],\
pix_base + (m1x) + (m1y)*m->i_stride[0],\
pix_base + (m2x) + (m2y)*m->i_stride[0],\
pix_base + (m3x) + (m3y)*m->i_stride[0],\
m->i_stride[0], costs );\
costs[0] += BITS_MVD( omx+(m0x), omy+(m0y) );\
costs[1] += BITS_MVD( omx+(m1x), omy+(m1y) );\
costs[2] += BITS_MVD( omx+(m2x), omy+(m2y) );\
costs[3] += BITS_MVD( omx+(m3x), omy+(m3y) );\
COPY3_IF_LT( bcost, costs[0], bmx, omx+(m0x), bmy, omy+(m0y) );\
COPY3_IF_LT( bcost, costs[1], bmx, omx+(m1x), bmy, omy+(m1y) );\
COPY3_IF_LT( bcost, costs[2], bmx, omx+(m2x), bmy, omy+(m2y) );\
COPY3_IF_LT( bcost, costs[3], bmx, omx+(m3x), bmy, omy+(m3y) );\
如果计算出的代价costs[]比原来预测的的代价bcost小的话,则将bcost赋值为costs[],并改变运动矢量omx+(m0x),omy+(m0y)
}
pixel.h
x264_pixel_cmp_x4_t fpelcmp_x4[7]; x264_pixel_cmp_x4_t其实就是一函数指针
typedef void (*x264_pixel_cmp_x4_t) ( uint8_t *, uint8_t *, uint8_t *, uint8_t *, uint8_t *, int, int[4] );
x264_pixel_cmp_x3_t satd_x3[7]; x264_pixel_cmp_x4_t satd_x4[7];
encoder.c
memcpy( h->pixf.fpelcmp_x4, satd ? h->pixf.satd_x4 : h->pixf.sad_x4, sizeof(h->pixf.fpelcmp_x4) );
就是说fpelcmp_x4要么用的是satd_x4算法,要么是sad_x4算法
整象素搜索用SAD,而亚象素用SATD,帧内模式选择要用SATD
static void x264_pixel_sad_x4_##size( uint8_t *fenc, uint8_t *pix0, uint8_t *pix1, uint8_t *pix2, uint8_t *pix3, int i_stride, int scores[4] )\
{\
scores[0] = x264_pixel_sad_##size( fenc, FENC_STRIDE, pix0, i_stride );\
scores[1] = x264_pixel_sad_##size( fenc, FENC_STRIDE, pix1, i_stride );\
scores[2] = x264_pixel_sad_##size( fenc, FENC_STRIDE, pix2, i_stride );\
scores[3] = x264_pixel_sad_##size( fenc, FENC_STRIDE, pix3, i_stride );\
}
针对不同块大小的SAD
PIXEL_SAD_C( x264_pixel_sad_16x16, 16, 16 )
PIXEL_SAD_C( x264_pixel_sad_16x8, 16, 8 )
PIXEL_SAD_C( x264_pixel_sad_8x16, 8, 16 )
PIXEL_SAD_C( x264_pixel_sad_8x8, 8, 8 )
PIXEL_SAD_C( x264_pixel_sad_8x4, 8, 4 )
PIXEL_SAD_C( x264_pixel_sad_4x8, 4, 8 )
PIXEL_SAD_C( x264_pixel_sad_4x4, 4, 4 )
#define PIXEL_SAD_C( name, lx, ly ) \
static int name( uint8_t *pix1, int i_stride_pix1, \
uint8_t *pix2, int i_stride_pix2 ) \
{ \
int i_sum = 0; \
int x, y; \
for( y = 0; y < ly; y++ ) \
{ \
for( x = 0; x < lx; x++ ) \
{ \
i_sum += abs( pix1[x] - pix2[x] ); \具体计算差值当前帧和重构帧
} \
pix1 += i_stride_pix1; \
pix2 += i_stride_pix2; \
} \
return i_sum; \
}