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

📄 analyse.c

📁 H.264编码器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* analyse.c: h264 encoder library */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "stdint.h"
#include <math.h>

#include "common.h"
#include "me.h"

static const uint8_t block_idx_x[16] = { 0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3 };
static const uint8_t block_idx_y[16] = { 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3 };

/*
 * Handle intra mb
 */
/* Max = 4 */
static void predict_16x16_mode_available( x264_macroblock_t *mb, int *mode, int *pi_count )
{
    if( ( mb->i_neighbour & (MB_LEFT|MB_TOP) ) == (MB_LEFT|MB_TOP) )
    {
        /* top and left avaible */
        *mode++ = I_PRED_16x16_V;
        *mode++ = I_PRED_16x16_H;
        *mode++ = I_PRED_16x16_DC;
        *mode++ = I_PRED_16x16_P;
        *pi_count = 4;
    }
    else if( ( mb->i_neighbour & MB_LEFT ) )
    {
        /* left available*/
        *mode++ = I_PRED_16x16_DC_LEFT;
        *mode++ = I_PRED_16x16_H;
        *pi_count = 2;
    }
    else if( ( mb->i_neighbour & MB_TOP ) )
    {
        /* top available*/
        *mode++ = I_PRED_16x16_DC_TOP;
        *mode++ = I_PRED_16x16_V;
        *pi_count = 2;
    }
    else
    {
        /* none avaible */
        *mode = I_PRED_16x16_DC_128;
        *pi_count = 1;
    }
}

/* Max = 4 */
static void predict_8x8_mode_available( x264_macroblock_t *mb, int *mode, int *pi_count )
{
    if( ( mb->i_neighbour & (MB_LEFT|MB_TOP) ) == (MB_LEFT|MB_TOP) )
    {
        /* top and left avaible */
        *mode++ = I_PRED_CHROMA_V;
        *mode++ = I_PRED_CHROMA_H;
        *mode++ = I_PRED_CHROMA_DC;
        *mode++ = I_PRED_CHROMA_P;
        *pi_count = 4;
    }
    else if( ( mb->i_neighbour & MB_LEFT ) )
    {
        /* left available*/
        *mode++ = I_PRED_CHROMA_DC_LEFT;
        *mode++ = I_PRED_CHROMA_H;
        *pi_count = 2;
    }
    else if( ( mb->i_neighbour & MB_TOP ) )
    {
        /* top available*/
        *mode++ = I_PRED_CHROMA_DC_TOP;
        *mode++ = I_PRED_CHROMA_V;
        *pi_count = 2;
    }
    else
    {
        /* none avaible */
        *mode = I_PRED_CHROMA_DC_128;
        *pi_count = 1;
    }
}

/* MAX = 8 */
static void predict_4x4_mode_available( x264_macroblock_t *mb, int idx, int *mode, int *pi_count )
{
    int b_a, b_b, b_c;
    static const int needmb[16] =
    {
        MB_LEFT|MB_TOP, MB_TOP,
        MB_LEFT,        MB_PRIVATE,
        MB_TOP,         MB_TOP|MB_TOPRIGHT,
        0,              MB_PRIVATE,
        MB_LEFT,        0,
        MB_LEFT,        MB_PRIVATE,
        0,              MB_PRIVATE,
        0,              MB_PRIVATE
    };

    /* FIXME even when b_c == 0 there is some case where missing pixels
     * are emulated and thus more mode are available TODO
     * analysis and encode should be fixed too */
    b_a = (needmb[idx]&mb->i_neighbour&MB_LEFT) == (needmb[idx]&MB_LEFT);
    b_b = (needmb[idx]&mb->i_neighbour&MB_TOP) == (needmb[idx]&MB_TOP);
    b_c = (needmb[idx]&mb->i_neighbour&(MB_TOPRIGHT|MB_PRIVATE)) == (needmb[idx]&(MB_TOPRIGHT|MB_PRIVATE));

    if( b_a && b_b )
    {
        *mode++ = I_PRED_4x4_DC;
        *mode++ = I_PRED_4x4_H;
        *mode++ = I_PRED_4x4_V;
        *mode++ = I_PRED_4x4_DDR;
        *mode++ = I_PRED_4x4_VR;
        *mode++ = I_PRED_4x4_HD;
        *mode++ = I_PRED_4x4_HU;

        *pi_count = 7;

        if( b_c )
        {
            *mode++ = I_PRED_4x4_DDL;
            *mode++ = I_PRED_4x4_VL;
            (*pi_count) += 2;
        }
    }
    else if( b_a && !b_b )
    {
        *mode++ = I_PRED_4x4_DC_LEFT;
        *mode++ = I_PRED_4x4_H;
        *pi_count = 2;
    }
    else if( !b_a && b_b )
    {
        *mode++ = I_PRED_4x4_DC_TOP;
        *mode++ = I_PRED_4x4_V;
        *pi_count = 2;
    }
    else
    {
        *mode++ = I_PRED_4x4_DC_128;
        *pi_count = 1;
    }
}

typedef struct
{
    /* conduct the analysis using this lamda and QP */
    int i_lambda;
    int i_qp;


    /* I: Intra part */
    /* Luma part 16x16 and 4x4 modes stats */
    int i_sad_i16x16;
    int i_predict16x16;

    int i_sad_i4x4;
    int i_predict4x4[4][4];

    /* Chroma part */
    int i_sad_i8x8;
    int i_predict8x8;

    /* II: Inter part P frame */
    int i_sad_p16x16;
    int i_ref_p16x16;
    int i_mv_p16x16[2];

    int i_sad_p16x8;
    int i_ref_p16x8;
    int i_mv_p16x8[2][2];

    int i_sad_p8x16;
    int i_ref_p8x16;
    int i_mv_p8x16[2][2];

    int i_sad_p8x8;
    int i_ref_p8x8;
    int i_sub_partition_p8x8[4];
    int i_mv_p8x8[4][4][2];

    /* II: Inter part B frame */
    int i_sad_b16x16_l0;
    int i_ref_b16x16_l0;
    int i_mv_b16x16_l0[2];

    int i_sad_b16x16_l1;
    int i_ref_b16x16_l1;
    int i_mv_b16x16_l1[2];

    int i_sad_b16x16_bi;    /* used the same ref and mv as l0 and l1 (at least for now) */

    int i_sad_b16x8_l0;
    int i_ref_b16x8_l0;
    int i_mv_b16x8_l0[2];

    int i_sad_b8x16_l0;
    int i_ref_b8x16_l0;
    int i_mv_b8x16_l0[2];



} x264_mb_analysis_t;


static const int i_qp0_cost_table[52] =
{
   1, 1, 1, 1, 1, 1, 1, 1,
   1, 1, 1, 1,
   1, 1, 1, 1, 2, 2, 2, 2,
   3, 3, 3, 4, 4, 4, 5, 6,
   6, 7, 8, 9,10,11,13,14,
  16,18,20,23,25,29,32,36,
  40,45,51,57,64,72,81,91
};

static void x264_mb_analyse_intra_chroma( x264_t *h, x264_macroblock_t *mb, x264_mb_analysis_t *res )
{
    x264_mb_context_t *ctx = mb->context;

    int i;

    int i_max;
    int predict_mode[9];

    uint8_t *p_dstc[2], *p_srcc[2];
    int      i_dstc[2], i_srcc[2];

    /* 8x8 prediction selection for chroma */
    p_dstc[0] = ctx->p_fdec[1]; i_dstc[0] = ctx->i_fdec[1];
    p_dstc[1] = ctx->p_fdec[2]; i_dstc[1] = ctx->i_fdec[2];
    p_srcc[0] = ctx->p_img[1];  i_srcc[0] = ctx->i_img[1];
    p_srcc[1] = ctx->p_img[2];  i_srcc[1] = ctx->i_img[2];

    predict_8x8_mode_available( mb, predict_mode, &i_max );
    res->i_sad_i8x8 = -1;
    for( i = 0; i < i_max; i++ )
    {
        int i_sad;
        int i_mode;

        i_mode = predict_mode[i];

        /* we do the prediction */
        h->predict_8x8[i_mode]( p_dstc[0], i_dstc[0] );
        h->predict_8x8[i_mode]( p_dstc[1], i_dstc[1] );

        /* we calculate the cost */
        i_sad = h->pixf.satd[PIXEL_8x8]( p_dstc[0], i_dstc[0], p_srcc[0], i_srcc[0] ) +
                h->pixf.satd[PIXEL_8x8]( p_dstc[1], i_dstc[1], p_srcc[1], i_srcc[1] ) +
                res->i_lambda * bs_size_ue( x264_mb_pred_mode8x8_fix[i_mode] );

        /* if i_score is lower it is better */
        if( res->i_sad_i8x8 == -1 || res->i_sad_i8x8 > i_sad )
        {
            res->i_predict8x8 = i_mode;
            res->i_sad_i8x8     = i_sad;
        }
    }
}


static void x264_mb_analyse_intra( x264_t *h, x264_macroblock_t *mb, x264_mb_analysis_t *res )
{
    int i, idx;

    int i_max;
    int predict_mode[9];

    uint8_t *p_dst, *p_src;
    int      i_dst, i_src;

    p_dst = mb->context->p_fdec[0]; i_dst = mb->context->i_fdec[0];
    p_src = mb->context->p_img[0];  i_src = mb->context->i_img[0];

    /*---------------- Try all mode and calculate their score ---------------*/

    /* 16x16 prediction selection */
    mb->i_type = I_16x16;
    res->i_sad_i16x16 = -1;
    predict_16x16_mode_available( mb, predict_mode, &i_max );
    for( i = 0; i < i_max; i++ )
    {
        int i_sad;
        int i_mode;

        i_mode = predict_mode[i];

        /* we do the prediction */
        h->predict_16x16[i_mode]( p_dst, i_dst );

        /* we calculate the diff and get the square sum of the diff */
        i_sad = h->pixf.satd[PIXEL_16x16]( p_dst, i_dst, p_src, i_src ) +
                res->i_lambda * bs_size_ue( x264_mb_pred_mode16x16_fix[i_mode] );
        /* if i_score is lower it is better */
        if( res->i_sad_i16x16 == -1 || res->i_sad_i16x16 > i_sad )
        {
            res->i_predict16x16 = i_mode;
            res->i_sad_i16x16     = i_sad;
        }
    }

    /* 4x4 prediction selection */
    mb->i_type = I_4x4;
    res->i_sad_i4x4 = 0;
    for( idx = 0; idx < 16; idx++ )
    {
        uint8_t *p_src_by;
        uint8_t *p_dst_by;
        int     i_best;
        int x, y;
        int i_pred_mode;

        i_pred_mode= x264_mb_predict_intra4x4_mode( h, mb, idx );
        x = block_idx_x[idx];
        y = block_idx_y[idx];

        p_src_by = p_src + 4 * x + 4 * y * i_src;
        p_dst_by = p_dst + 4 * x + 4 * y * i_dst;

        i_best = -1;
        predict_4x4_mode_available( mb, idx, predict_mode, &i_max );
        for( i = 0; i < i_max; i++ )
        {
            int i_sad;
            int i_mode;

            i_mode = predict_mode[i];

            /* we do the prediction */
            h->predict_4x4[i_mode]( p_dst_by, i_dst );

            /* we calculate diff and get the square sum of the diff */
            i_sad = h->pixf.satd[PIXEL_4x4]( p_dst_by, i_dst, p_src_by, i_src );

            i_sad += res->i_lambda * (i_pred_mode == x264_mb_pred_mode4x4_fix[i_mode] ? 1 : 4);

            /* if i_score is lower it is better */
            if( i_best == -1 || i_best > i_sad )
            {
                res->i_predict4x4[x][y] = i_mode;
                i_best = i_sad;
            }
        }
        res->i_sad_i4x4 += i_best;

        /* we need to encode this mb now (for next ones) */
        mb->block[idx].i_intra4x4_pred_mode = res->i_predict4x4[x][y];
        h->predict_4x4[res->i_predict4x4[x][y]]( p_dst_by, i_dst );
        x264_mb_encode_i4x4( h, mb, idx, res->i_qp );
    }
    res->i_sad_i4x4 += res->i_lambda * 24;    /* from JVT (SATD0) */
}

static void x264_mb_analyse_inter_p_p8x8( x264_t *h, x264_macroblock_t *mb, x264_mb_analysis_t *res )
{
    x264_mb_context_t *ctx = mb->context;
    int i_ref = res->i_ref_p16x16;

    uint8_t *p_fref = ctx->p_fref0[i_ref][0];
    int      i_fref = ctx->i_fref0[i_ref][0];
    uint8_t *p_img  = ctx->p_img[0];
    int      i_img  = ctx->i_img[0];

    int i;

    res->i_ref_p8x8 = i_ref;
    res->i_sad_p8x8 = 0;
    mb->i_partition = D_8x8;

    for( i = 0; i < 4; i++ )
    {
        static const int test8x8_mode[4] = { D_L0_8x8, D_L0_8x4, D_L0_4x8, D_L0_4x4 };
        static const int test8x8_pix[4]  = { PIXEL_8x8, PIXEL_8x4, PIXEL_4x8, PIXEL_4x4 };
        static const int test8x8_pos_x[4][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 4, 0, 0 }, { 0, 4, 0, 4 } };
        static const int test8x8_pos_y[4][4] = { { 0, 0, 0, 0 }, { 0, 4, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 4, 4 } };
        int i_test;
        int mvp[4][2];
        int mv[4][2];

        int x, y;
        int i_sub;
        int i_b_satd;

        y = 8 * (i / 2);
        x = 8 * (i % 2);
        i_b_satd = -1;

        i_test = 0;
        /* FIXME as it's tooooooo slow test only 8x8 */
        //for( i_test = 0; i_test < 4; i_test++ )
        {
            int i_satd;

            i_satd = 0;

            mb->i_sub_partition[i] = test8x8_mode[i_test];

            for( i_sub = 0; i_sub < x264_mb_partition_count_table[test8x8_mode[i_test]]; i_sub++ )
            {
                x264_mb_predict_mv( mb, 0, i, i_sub, mvp[i_sub] );
                mv[i_sub][0] = mvp[i_sub][0];
                mv[i_sub][1] = mvp[i_sub][1];

                i_satd += h->me( h,
                                 &p_fref[(y+test8x8_pos_y[i_test][i_sub])*i_fref +x+test8x8_pos_x[i_test][i_sub]], i_fref,
                                 &p_img[(y+test8x8_pos_y[i_test][i_sub])*i_img +x+test8x8_pos_x[i_test][i_sub]], i_img,
                                 test8x8_pix[i_test],
                                 res->i_lambda,
                                 &mv[i_sub][0], &mv[i_sub][1] );
            }

            switch( test8x8_mode[i_test] )
            {
                case D_L0_8x8:
                    i_satd += res->i_lambda * bs_size_ue( 0 );
                    break;
                case D_L0_8x4:
                    i_satd += res->i_lambda * bs_size_ue( 1 );
                    break;
                case D_L0_4x8:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -