⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 analyse.c

📁 H.264编码器
💻 C
📖 第 1 页 / 共 2 页
字号:
                    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 + -