📄 analyse.c
字号:
i_satd += res->i_lambda * bs_size_ue( 2 );
break;
case D_L0_4x4:
i_satd += res->i_lambda * bs_size_ue( 3 );
break;
default:
fprintf( stderr, "internal error (invalid sub type)\n" );
break;
}
if( i_b_satd == -1 || i_b_satd > i_satd )
{
i_b_satd = i_satd;
res->i_sub_partition_p8x8[i] = test8x8_mode[i_test];;
for( i_sub = 0; i_sub < x264_mb_partition_count_table[test8x8_mode[i_test]]; i_sub++ )
{
res->i_mv_p8x8[i][i_sub][0] = mv[i_sub][0];
res->i_mv_p8x8[i][i_sub][1] = mv[i_sub][1];
}
}
}
res->i_sad_p8x8 += i_b_satd;
/* needed for the next block */
mb->i_sub_partition[i] = res->i_sub_partition_p8x8[i];
for( i_sub = 0; i_sub < x264_mb_partition_count_table[res->i_sub_partition_p8x8[i]]; i_sub++ )
{
x264_mb_partition_set( mb, 0, i, i_sub,
res->i_ref_p8x8,
res->i_mv_p8x8[i][i_sub][0],
res->i_mv_p8x8[i][i_sub][1] );
}
}
res->i_sad_p8x8 += 4*res->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l0_active - 1, i_ref );
}
static void x264_mb_analyse_inter_p( x264_t *h, x264_macroblock_t *mb, x264_mb_analysis_t *res )
{
x264_mb_context_t *ctx = mb->context;
int i_ref;
/* int res */
res->i_sad_p16x16 = -1;
res->i_sad_p16x8 = -1;
res->i_sad_p8x16 = -1;
res->i_sad_p8x8 = -1;
/* 16x16 Search on all ref frame */
mb->i_type = P_L0; /* beurk fix that */
mb->i_partition = D_16x16;
for( i_ref = 0; i_ref < h->i_ref0; i_ref++ )
{
int i_sad;
int mvp[2];
int mvx, mvy;
/* Get the predicted MV */
x264_mb_partition_set( mb, 0, 0, 0, i_ref, 0, 0 );
x264_mb_predict_mv( mb, 0, 0, 0, mvp );
mvx = mvp[0]; mvy = mvp[1];
i_sad = h->me( h, ctx->p_fref0[i_ref][0], ctx->i_fref0[i_ref][0],
ctx->p_img[0], ctx->i_img[0],
PIXEL_16x16, res->i_lambda, &mvx, &mvy );
if( mvx == mvp[0] && mvy == mvp[1] )
{
i_sad -= 16 * res->i_lambda;
}
i_sad += res->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l0_active - 1, i_ref );
if( res->i_sad_p16x16 == -1 || i_sad < res->i_sad_p16x16 )
{
res->i_sad_p16x16 = i_sad;
res->i_ref_p16x16 = i_ref;
res->i_mv_p16x16[0] = mvx;
res->i_mv_p16x16[1] = mvy;
}
}
/* Now do the rafinement (using the ref found in 16x16 mode) */
i_ref = res->i_ref_p16x16;
x264_mb_partition_set( mb, 0, 0, 0, i_ref, 0, 0 );
/* try 16x8 */
/* XXX we test i_predict16x16 to try shape with the same direction than edge
* We should do a better algo of course (the one with edge dectection to be used
* for intra mode too)
* */
if( res->i_predict16x16 != I_PRED_16x16_V )
{
int mvp[2][2];
mb->i_partition = D_16x8;
res->i_ref_p16x8 = i_ref;
x264_mb_predict_mv( mb, 0, 0, 0, mvp[0] );
x264_mb_predict_mv( mb, 0, 1, 0, mvp[1] );
res->i_mv_p16x8[0][0] = mvp[0][0]; res->i_mv_p16x8[0][1] = mvp[0][1];
res->i_mv_p16x8[1][0] = mvp[1][0]; res->i_mv_p16x8[1][1] = mvp[1][1];
res->i_sad_p16x8 = h->me( h,
ctx->p_fref0[i_ref][0], ctx->i_fref0[i_ref][0],
ctx->p_img[0], ctx->i_img[0],
PIXEL_16x8,
res->i_lambda,
&res->i_mv_p16x8[0][0], &res->i_mv_p16x8[0][1] ) +
h->me( h,
&ctx->p_fref0[i_ref][0][8*ctx->i_fref0[i_ref][0]], ctx->i_fref0[i_ref][0],
&ctx->p_img[0][8*ctx->i_img[0]], ctx->i_img[0],
PIXEL_16x8,
res->i_lambda,
&res->i_mv_p16x8[1][0], &res->i_mv_p16x8[1][1] );
res->i_sad_p16x8 += 2*res->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l0_active - 1, i_ref );
}
/* try 8x16 */
if( res->i_predict16x16 != I_PRED_16x16_H )
{
int mvp[2][2];
mb->i_partition = D_8x16;
res->i_ref_p8x16 = i_ref;
x264_mb_predict_mv( mb, 0, 0, 0, mvp[0] );
x264_mb_predict_mv( mb, 0, 1, 0, mvp[1] );
res->i_mv_p8x16[0][0] = mvp[0][0]; res->i_mv_p8x16[0][1] = mvp[0][1];
res->i_mv_p8x16[1][0] = mvp[1][0]; res->i_mv_p8x16[1][1] = mvp[1][1];
res->i_sad_p8x16 = h->me( h,
ctx->p_fref0[i_ref][0], ctx->i_fref0[i_ref][0],
ctx->p_img[0], ctx->i_img[0],
PIXEL_8x16,
res->i_lambda,
&res->i_mv_p8x16[0][0], &res->i_mv_p8x16[0][1] ) +
h->me( h,
&ctx->p_fref0[i_ref][0][8], ctx->i_fref0[i_ref][0],
&ctx->p_img[0][8], ctx->i_img[0],
PIXEL_8x16,
res->i_lambda,
&res->i_mv_p8x16[1][0], &res->i_mv_p8x16[1][1] );
res->i_sad_p8x16 += 2*res->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l0_active - 1, i_ref );
}
/* a bit heuristique : if 4x4 is prefered, the block is probably not homegenous
* for now disabled because too slow for too few bits saved */
if( res->i_sad_i4x4 < res->i_sad_i16x16 )
{
x264_mb_analyse_inter_p_p8x8( h,mb, res );
}
}
static void x264_mb_analyse_inter_b( x264_t *h, x264_macroblock_t *mb, x264_mb_analysis_t *res )
{
x264_mb_context_t *ctx = mb->context;
uint8_t pix1[16*16], pix2[16*16];
int i_ref;
/* int i_ref0, i_ref1; */
int mvp[2];
res->i_sad_b16x16_l0 = -1;
res->i_sad_b16x16_l1 = -1;
res->i_sad_b16x16_bi = -1;
/* 16x16 L0 Search on all ref frame */
mb->i_type = B_L0_L0; /* beurk fix that */
mb->i_partition = D_16x16;
for( i_ref = 0; i_ref < h->i_ref0; i_ref++ )
{
int i_sad;
int mvx, mvy;
/* Get the predicted MV */
x264_mb_partition_set( mb, 0, 0, 0, i_ref, 0, 0 );
x264_mb_predict_mv( mb, 0, 0, 0, mvp );
mvx = mvp[0]; mvy = mvp[1];
i_sad = h->me( h, ctx->p_fref0[i_ref][0], ctx->i_fref0[i_ref][0],
ctx->p_img[0], ctx->i_img[0],
PIXEL_16x16, res->i_lambda, &mvx, &mvy );
i_sad += res->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l0_active - 1, i_ref );
if( res->i_sad_b16x16_l0 == -1 || i_sad < res->i_sad_b16x16_l0 )
{
res->i_sad_b16x16_l0 = i_sad;
res->i_ref_b16x16_l0 = i_ref;
res->i_mv_b16x16_l0[0] = mvx;
res->i_mv_b16x16_l0[1] = mvy;
}
}
/* 16x16 L1 Search on all ref frame */
mb->i_type = B_L1_L1; /* beurk fix that */
mb->i_partition = D_16x16;
for( i_ref = 0; i_ref < h->i_ref1; i_ref++ )
{
int i_sad;
int mvx, mvy;
/* Get the predicted MV */
x264_mb_partition_set( mb, 1, 0, 0, i_ref, 0, 0 );
x264_mb_predict_mv( mb, 1, 0, 0, mvp );
mvx = mvp[0]; mvy = mvp[1];
i_sad = h->me( h, ctx->p_fref1[i_ref][0], ctx->i_fref1[i_ref][0],
ctx->p_img[0], ctx->i_img[0],
PIXEL_16x16, res->i_lambda, &mvx, &mvy );
i_sad += res->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l1_active - 1, i_ref );
if( res->i_sad_b16x16_l1 == -1 || i_sad < res->i_sad_b16x16_l1 )
{
res->i_sad_b16x16_l1 = i_sad;
res->i_ref_b16x16_l1 = i_ref;
res->i_mv_b16x16_l1[0] = mvx;
res->i_mv_b16x16_l1[1] = mvy;
}
}
/* calculate i_sad_b16x16_bi */
h->mc[MC_LUMA]( ctx->p_fref0[res->i_ref_b16x16_l0][0], ctx->i_fref0[res->i_ref_b16x16_l0][0],
pix1, 16,
res->i_mv_b16x16_l0[0],
res->i_mv_b16x16_l0[1],
16, 16 );
h->mc[MC_LUMA]( ctx->p_fref1[res->i_ref_b16x16_l1][0], ctx->i_fref1[res->i_ref_b16x16_l1][0],
pix2, 16,
res->i_mv_b16x16_l1[0],
res->i_mv_b16x16_l1[1],
16, 16 );
h->pixf.avg[PIXEL_16x16]( pix1, 16, pix2, 16 );
res->i_sad_b16x16_bi = h->pixf.sad[PIXEL_16x16]( ctx->p_img[0], ctx->i_img[0], pix1, 16 );
x264_mb_partition_set( mb, 0, 0, 0, res->i_ref_b16x16_l0, res->i_mv_b16x16_l0[0], res->i_mv_b16x16_l0[1] );
x264_mb_partition_set( mb, 1, 0, 0, res->i_ref_b16x16_l1, res->i_mv_b16x16_l1[0], res->i_mv_b16x16_l1[1] );
x264_mb_predict_mv( mb, 0, 0, 0, mvp );
res->i_sad_b16x16_bi += res->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l0_active - 1, res->i_ref_b16x16_l0 );
x264_mb_predict_mv( mb, 1, 0, 0, mvp );
res->i_sad_b16x16_bi += res->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l1_active - 1, res->i_ref_b16x16_l1 );
#if 0
/* Now do the rafinement (using the ref found in 16x16 mode) */
i_ref0 = res->i_ref_b16x16_l0;
i_ref1 = res->i_ref_b16x16_l1;
x264_mb_partition_set( mb, 0, 0, 0, i_ref0, 0, 0 );
x264_mb_partition_set( mb, 1, 0, 0, i_ref1, 0, 0 );
/* now do 16x8 */
#endif
}
/*****************************************************************************
* x264_macroblock_analyse:
*****************************************************************************/
void x264_macroblock_analyse( x264_t *h, x264_macroblock_t *mb )
{
x264_mb_analysis_t analysis;
int i;
/* qp TODO */
mb->i_qp = x264_clip3( h->pps->i_pic_init_qp + h->sh.i_qp_delta + 0, 0, 51 );
/* init analysis */
analysis.i_qp = mb->i_qp;
analysis.i_lambda = i_qp0_cost_table[analysis.i_qp];
/*--------------------------- Do the analysis ---------------------------*/
x264_mb_analyse_intra( h, mb, &analysis );
if( h->sh.i_type == SLICE_TYPE_P )
{
x264_mb_analyse_inter_p( h, mb, &analysis );
}
else if( h->sh.i_type == SLICE_TYPE_B )
{
x264_mb_analyse_inter_b( h, mb, &analysis );
}
/*-------------------- Chose the macroblock mode ------------------------*/
#define BEST_TYPE( type, partition, satd ) \
if( satd != -1 && satd < i_satd ) \
{ \
i_satd = satd; \
mb->i_type = type; \
mb->i_partition = partition; \
}
if( h->sh.i_type == SLICE_TYPE_I )
{
mb->i_type = analysis.i_sad_i4x4 < analysis.i_sad_i16x16 ? I_4x4 : I_16x16;
}
else if( h->sh.i_type == SLICE_TYPE_P )
{
int i_satd = analysis.i_sad_i4x4;
mb->i_type = I_4x4;
BEST_TYPE( I_16x16, -1, analysis.i_sad_i16x16 );
BEST_TYPE( P_L0, D_16x16, analysis.i_sad_p16x16 );
BEST_TYPE( P_L0, D_16x8 , analysis.i_sad_p16x8 );
BEST_TYPE( P_L0, D_8x16 , analysis.i_sad_p8x16 );
BEST_TYPE( P_8x8, D_8x8 , analysis.i_sad_p8x8 );
}
else /* B */
{
int i_satd = analysis.i_sad_i4x4;
mb->i_type = I_4x4;
BEST_TYPE( I_16x16, -1, analysis.i_sad_i16x16 );
BEST_TYPE( B_L0_L0, D_16x16, analysis.i_sad_b16x16_l0 );
BEST_TYPE( B_L1_L1, D_16x16, analysis.i_sad_b16x16_l1 );
BEST_TYPE( B_BI_BI, D_16x16, analysis.i_sad_b16x16_bi );
}
#undef BEST_TYPE
if( IS_INTRA( mb->i_type ) )
{
x264_mb_analyse_intra_chroma( h, mb, &analysis );
}
/*-------------------- Update MB from the analysis ----------------------*/
switch( mb->i_type )
{
case I_4x4:
for( i = 0; i < 16; i++ )
{
mb->block[i].i_intra4x4_pred_mode = analysis.i_predict4x4[block_idx_x[i]][block_idx_y[i]];
}
mb->i_chroma_pred_mode = analysis.i_predict8x8;
break;
case I_16x16:
mb->i_intra16x16_pred_mode = analysis.i_predict16x16;
mb->i_chroma_pred_mode = analysis.i_predict8x8;
break;
case P_L0:
switch( mb->i_partition )
{
case D_16x16:
x264_mb_partition_set( mb, 0, 0, 0, analysis.i_ref_p16x16, analysis.i_mv_p16x16[0], analysis.i_mv_p16x16[1] );
break;
case D_16x8:
x264_mb_partition_set( mb, 0, 0, 0, analysis.i_ref_p16x8, analysis.i_mv_p16x8[0][0], analysis.i_mv_p16x8[0][1] );
x264_mb_partition_set( mb, 0, 1, 0, analysis.i_ref_p16x8, analysis.i_mv_p16x8[1][0], analysis.i_mv_p16x8[1][1] );
break;
case D_8x16:
x264_mb_partition_set( mb, 0, 0, 0, analysis.i_ref_p8x16, analysis.i_mv_p8x16[0][0], analysis.i_mv_p8x16[0][1] );
x264_mb_partition_set( mb, 0, 1, 0, analysis.i_ref_p8x16, analysis.i_mv_p8x16[1][0], analysis.i_mv_p8x16[1][1] );
break;
default:
fprintf( stderr, "internal error\n" );
break;
}
break;
case P_8x8:
for( i = 0; i < 4; i++ )
{
int i_sub;
mb->i_sub_partition[i] = analysis.i_sub_partition_p8x8[i];
for( i_sub = 0; i_sub < x264_mb_partition_count_table[mb->i_sub_partition[i]]; i_sub++ )
{
x264_mb_partition_set( mb, 0, i, i_sub,
analysis.i_ref_p8x8,
analysis.i_mv_p8x8[i][i_sub][0],
analysis.i_mv_p8x8[i][i_sub][1] );
}
}
break;
case B_L0_L0:
switch( mb->i_partition )
{
case D_16x16:
x264_mb_partition_set( mb, 0, 0, 0, analysis.i_ref_b16x16_l0, analysis.i_mv_b16x16_l0[0], analysis.i_mv_b16x16_l0[1] );
/* l1 not used/avaiable */
x264_mb_partition_set( mb, 1, 0, 0, -1, 0, 0 );
break;
default:
fprintf( stderr, "internal error\n" );
break;
}
break;
case B_L1_L1:
switch( mb->i_partition )
{
case D_16x16:
/* l0 not used/avaiable */
x264_mb_partition_set( mb, 0, 0, 0, -1, 0, 0 );
x264_mb_partition_set( mb, 1, 0, 0, analysis.i_ref_b16x16_l1, analysis.i_mv_b16x16_l1[0], analysis.i_mv_b16x16_l1[1] );
break;
default:
fprintf( stderr, "internal error\n" );
break;
}
break;
case B_BI_BI:
switch( mb->i_partition )
{
case D_16x16:
x264_mb_partition_set( mb, 0, 0, 0, analysis.i_ref_b16x16_l0, analysis.i_mv_b16x16_l0[0], analysis.i_mv_b16x16_l0[1] );
x264_mb_partition_set( mb, 1, 0, 0, analysis.i_ref_b16x16_l1, analysis.i_mv_b16x16_l1[0], analysis.i_mv_b16x16_l1[1] );
break;
default:
fprintf( stderr, "internal error\n" );
break;
}
break;
default:
fprintf( stderr, "internal error\n" );
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -