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

📄 analyse.c

📁 H.264改进解码软件
💻 C
📖 第 1 页 / 共 5 页
字号:
                                        int *mode, int *pi_count )
{
    int b_l = i_neighbour & MB_LEFT;
    int b_t = i_neighbour & MB_TOP;

    if( b_l && b_t )//
    {
        *pi_count = 6;
        *mode++ = I_PRED_4x4_DC;
        *mode++ = I_PRED_4x4_H;
        *mode++ = I_PRED_4x4_V;
        *mode++ = I_PRED_4x4_DDL;
        if( i_neighbour & MB_TOPLEFT )
        {
            *mode++ = I_PRED_4x4_DDR;
            *mode++ = I_PRED_4x4_VR;
            *mode++ = I_PRED_4x4_HD;
            *pi_count += 3;
        }
        *mode++ = I_PRED_4x4_VL;
        *mode++ = I_PRED_4x4_HU;
    }
    else if( b_l )
    {
        *mode++ = I_PRED_4x4_DC_LEFT;
        *mode++ = I_PRED_4x4_H;
        *mode++ = I_PRED_4x4_HU;
        *pi_count = 3;
    }
    else if( b_t )
    {
        *mode++ = I_PRED_4x4_DC_TOP;
        *mode++ = I_PRED_4x4_V;
        *mode++ = I_PRED_4x4_DDL;
        *mode++ = I_PRED_4x4_VL;
        *pi_count = 4;
    }
    else
    {
        *mode++ = I_PRED_4x4_DC_128;
        *pi_count = 1;
    }
}

static void x264_mb_analyse_intra_chroma( x264_t *h, x264_mb_analysis_t *a )
{
    int i;

    int i_max;
    int predict_mode[9];

    uint8_t *p_dstc[2], *p_srcc[2];

    if( a->i_sad_i8x8chroma < COST_MAX )//已经做过色度预测分析
        return;

    /* 8x8 prediction selection for chroma */
    p_dstc[0] = h->mb.pic.p_fdec[1];
    p_dstc[1] = h->mb.pic.p_fdec[2];
    p_srcc[0] = h->mb.pic.p_fenc[1];
    p_srcc[1] = h->mb.pic.p_fenc[2];

    predict_8x8chroma_mode_available( h->mb.i_neighbour, predict_mode, &i_max );
    a->i_sad_i8x8chroma = COST_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_8x8c[i_mode]( p_dstc[0] );
        h->predict_8x8c[i_mode]( p_dstc[1] );

        /* we calculate the cost */
        i_sad = h->pixf.mbcmp[PIXEL_8x8]( p_dstc[0], FDEC_STRIDE,
                                          p_srcc[0], FENC_STRIDE ) +
                h->pixf.mbcmp[PIXEL_8x8]( p_dstc[1], FDEC_STRIDE,
                                          p_srcc[1], FENC_STRIDE ) +
                a->i_lambda * bs_size_ue( x264_mb_pred_mode8x8c_fix[i_mode] );

        /* if i_score is lower it is better */
        if( a->i_sad_i8x8chroma > i_sad )
        {
            a->i_predict8x8chroma = i_mode;
            a->i_sad_i8x8chroma   = i_sad;
        }
    }

    h->mb.i_chroma_pred_mode = a->i_predict8x8chroma;
}

static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_cost_inter )
{
    const unsigned int flags = h->sh.i_type == SLICE_TYPE_I ? h->param.analyse.intra : h->param.analyse.inter;
    uint8_t  *p_src = h->mb.pic.p_fenc[0];
    uint8_t  *p_dst = h->mb.pic.p_fdec[0];
    int      f8_satd_rd_ratio = 0;

    int i, idx;
    int i_max;
    int predict_mode[9];
    int i_satd_thresh;

   /* if( h->sh.i_type == SLICE_TYPE_B )
        i_satd_thresh = a->i_best_satd * 9/8;
    else*/
        i_satd_thresh = a->i_best_satd * 5/4 ;//+ a->i_lambda * 10;

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

    /* 16x16 prediction selection */
    predict_16x16_mode_available( h->mb.i_neighbour, predict_mode, &i_max );//根据相邻宏块数据的信息确定可用的16*16帧内预测模式
    for( i = 0; i < i_max; i++ )//i_max表示有效模式数组的长度
    {
        int i_sad;
        int i_mode;

        i_mode = predict_mode[i];
        h->predict_16x16[i_mode]( p_dst );// h->predict_16x16为函数名数组//根据h->mb.pic.p_fdec中的相邻数据用i_mode预测当前
		                                  //宏块数据,预测值同样写入h->mb.pic.p_fdec解码重建宏块缓存(相应位置)
        i_sad = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE );// +
                //a->i_lambda * bs_size_ue( x264_mb_pred_mode16x16_fix[i_mode] );//rdo代价计算
        if( a->i_sad_i16x16 > i_sad )
        {
            a->i_predict16x16 = i_mode;//更新当前最佳16*16帧内预测模式和代价
            a->i_sad_i16x16   = i_sad;
        }
    }

    if( a->b_mbrd )
    {
        f8_satd_rd_ratio = ((unsigned)i_cost_inter << 8) / a->i_best_satd + 1;
        x264_mb_analyse_intra_chroma( h, a );
        if( h->mb.b_chroma_me )
            a->i_sad_i16x16 += a->i_sad_i8x8chroma;
        if( a->i_sad_i16x16 < i_satd_thresh )
        {
            h->mb.i_type = I_16x16;
            h->mb.i_intra16x16_pred_mode = a->i_predict16x16;
//            a->i_sad_i16x16 = x264_rd_cost_mb( h, a->i_lambda2 );
        }
        else
            a->i_sad_i16x16 = a->i_sad_i16x16 * f8_satd_rd_ratio >> 8;
    }
    else
    {
        if( h->sh.i_type == SLICE_TYPE_B )
            /* cavlc mb type prefix */
            a->i_sad_i16x16 += a->i_lambda * i_mb_b_cost_table[I_16x16];
        if( a->b_fast_intra && a->i_sad_i16x16 > 2*i_cost_inter )//什么物理概念?16*16帧内预测值过大时返回?
            return;
    }

    /* 4x4 prediction selection */
    if( flags & X264_ANALYSE_I4x4 )
    {
        a->i_sad_i4x4 = 0;
        for( idx = 0; idx < 16; idx++ )//对16个4*4做
        {
            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, idx );//根据邻块预测当前4*4块的可能预测模式,与计算rdo代价有关
            x = block_idx_x[idx];//4*4块的宏块内坐标
            y = block_idx_y[idx];

            p_src_by = p_src + 4 * x + 4 * y * FENC_STRIDE;//确定当前4*4块首像素在宏块缓存中的位置
            p_dst_by = p_dst + 4 * x + 4 * y * FDEC_STRIDE;//32,表示宏块解码缓存对一宏块行,存储了32个像素

            i_best = COST_MAX;
            predict_4x4_mode_available( h->mb.i_neighbour4[idx], predict_mode, &i_max );//确定可用的4*4帧内预测模式
            if( (h->mb.i_neighbour4[idx] & (MB_TOPRIGHT|MB_TOP)) == MB_TOP )//上邻4*4有效,右上邻无效时
                /* emulate missing topright samples *///右上邻像素值=上邻的最后一像素值*0x01010101(乘这个数字什么概念?)
                *(uint32_t*) &p_dst_by[4 - FDEC_STRIDE] = p_dst_by[3 - FDEC_STRIDE] * 0x01010101U;

            for( i = 0; i < i_max; i++ )//对每种有效预测模式做,同上面的16*16方式
            {
                int i_sad;
                int i_mode;

                i_mode = predict_mode[i];
                h->predict_4x4[i_mode]( p_dst_by );// h->predict_16x16为函数名数组//根据h->mb.pic.p_fdec中的相邻数据用i_mode预测当前
		                                           //宏块数据,预测值同样写入h->mb.pic.p_fdec宏块解码缓存(相应位置)
                i_sad = h->pixf.mbcmp[PIXEL_4x4]( p_dst_by, FDEC_STRIDE,
                                                  p_src_by, FENC_STRIDE );
                     // + a->i_lambda * (i_pred_mode == x264_mb_pred_mode4x4_fix(i_mode) ? 1 : 4);

                if( i_best > i_sad )//更新该4*4最小预测代价和最佳预测模式
                {
                    a->i_predict4x4[x][y] = i_mode;
                    i_best = i_sad;
                }
            }
            a->i_sad_i4x4 += i_best;//累计宏块的各4*4块最小预测代价作为宏块的最小预测代价

			//下面在最佳模式下预测当前4*4块,最后更新fdec缓存(因为前面的fdec缓存中预测值是不断刷新的)
            /* we need to encode this block now (for next ones) */
            h->predict_4x4[a->i_predict4x4[x][y]]( p_dst_by );

            x264_mb_encode_i4x4( h, idx, a->i_qp );//求亮度数据的重构值,写回宏块解码缓存fdec[]相应位置

            h->mb.cache.intra4x4_pred_mode[x264_scan8[idx]] = a->i_predict4x4[x][y];//最佳模式写入h
        }

        a->i_sad_i4x4 += a->i_lambda * 24;    /* from JVT (SATD0) *///??
        if( a->b_mbrd )
        {
            if( h->mb.b_chroma_me )
                a->i_sad_i4x4 += a->i_sad_i8x8chroma;
            if( a->i_sad_i4x4 < i_satd_thresh )
            {
                h->mb.i_type = I_4x4;
//                a->i_sad_i4x4 = x264_rd_cost_mb( h, a->i_lambda2 );
            }
            else
                a->i_sad_i4x4 = a->i_sad_i4x4 * f8_satd_rd_ratio >> 8;
        }
        else
        {
            if( h->sh.i_type == SLICE_TYPE_B )
                a->i_sad_i4x4 += a->i_lambda * i_mb_b_cost_table[I_4x4];
        }
    }

    /* 8x8 prediction selection */
    if( flags & X264_ANALYSE_I8x8 )
    {
        a->i_sad_i8x8 = 0;
        for( idx = 0; idx < 4; idx++ )//4个8*8块
        {
            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, 4*idx );
            x = idx&1;
            y = idx>>1;

            p_src_by = p_src + 8 * x + 8 * y * FENC_STRIDE;
            p_dst_by = p_dst + 8 * x + 8 * y * FDEC_STRIDE;

            i_best = COST_MAX;
            predict_4x4_mode_available( h->mb.i_neighbour8[idx], predict_mode, &i_max );
            for( i = 0; i < i_max; i++ )
            {
                int i_sad;
                int i_mode;

                i_mode = predict_mode[i];
                h->predict_8x8[i_mode]( p_dst_by, h->mb.i_neighbour8[idx] );

                /* could use sa8d, but it doesn't seem worth the speed cost (without mmx at least) */
                i_sad = h->pixf.mbcmp[PIXEL_8x8]( p_dst_by, FDEC_STRIDE,
                                                  p_src_by, FENC_STRIDE );
                      //+ a->i_lambda * (i_pred_mode == x264_mb_pred_mode4x4_fix(i_mode) ? 1 : 4);

                if( i_best > i_sad )
                {
                    a->i_predict8x8[x][y] = i_mode;
                    i_best = i_sad;
                }
            }
            a->i_sad_i8x8 += i_best;

            /* we need to encode this block now (for next ones) */
            h->predict_8x8[a->i_predict8x8[x][y]]( p_dst_by, h->mb.i_neighbour8[idx] );
            x264_mb_encode_i8x8( h, idx, a->i_qp );

            x264_macroblock_cache_intra8x8_pred( h, 2*x, 2*y, a->i_predict8x8[x][y] );//没有看
        }

        if( a->b_mbrd )
        {
            if( h->mb.b_chroma_me )
                a->i_sad_i8x8 += a->i_sad_i8x8chroma;
            if( a->i_sad_i8x8 < i_satd_thresh )
            {
                h->mb.i_type = I_8x8;
//                a->i_sad_i8x8 = x264_rd_cost_mb( h, a->i_lambda2 );
            }
            else
                a->i_sad_i8x8 = a->i_sad_i8x8 * f8_satd_rd_ratio >> 8;
        }
        else
        {
            // FIXME some bias like in i4x4?
            if( h->sh.i_type == SLICE_TYPE_B )
                a->i_sad_i8x8 += a->i_lambda * i_mb_b_cost_table[I_8x8];
        }
    }
}

#define LOAD_FENC( m, src, xoff, yoff) \
    (m)->i_stride[0] = h->mb.pic.i_stride[0]; \
    (m)->i_stride[1] = h->mb.pic.i_stride[1]; \
    (m)->p_fenc[0] = &(src)[0][(xoff)+(yoff)*FENC_STRIDE]; \
    (m)->p_fenc[1] = &(src)[1][((xoff)>>1)+((yoff)>>1)*FENC_STRIDE]; \
    (m)->p_fenc[2] = &(src)[2][((xoff)>>1)+((yoff)>>1)*FENC_STRIDE];

#define LOAD_HPELS(m, src, list, ref, xoff, yoff) \
    (m)->p_fref[0] = &(src)[0][(xoff)+(yoff)*(m)->i_stride[0]]; \
    (m)->p_fref[1] = &(src)[1][(xoff)+(yoff)*(m)->i_stride[0]]; \
    (m)->p_fref[2] = &(src)[2][(xoff)+(yoff)*(m)->i_stride[0]]; \
    (m)->p_fref[3] = &(src)[3][(xoff)+(yoff)*(m)->i_stride[0]]; \
    (m)->p_fref[4] = &(src)[4][((xoff)>>1)+((yoff)>>1)*(m)->i_stride[1]]; \
    (m)->p_fref[5] = &(src)[5][((xoff)>>1)+((yoff)>>1)*(m)->i_stride[1]]; \
    (m)->integral = &h->mb.pic.p_integral[list][ref][(xoff)+(yoff)*(m)->i_stride[0]];

#define REF_COST(list, ref) \
    (a->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l##list##_active - 1, ref ))

static void x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a )
{
    x264_me_t m;
    int i_ref;
    int mvc[7][2], i_mvc;
    int i_halfpel_thresh = INT_MAX;
    int *p_halfpel_thresh = h->i_ref0>1 ? &i_halfpel_thresh : NULL;

    /* 16x16 Search on all ref frame */
    m.i_pixel = PIXEL_16x16;
    m.p_cost_mv = a->p_cost_mv;
    LOAD_FENC( &m, h->mb.pic.p_fenc, 0, 0 );//将待编码宏块数据从宏块缓存拷贝到运动估计结构体m->p_fenc[0],[1],[2]

    a->l0.me16x16.cost = INT_MAX;
    for( i_ref = 0; i_ref < h->i_ref0; i_ref++ )
    {
        const int i_ref_cost = REF_COST( 0, i_ref );//参考帧远近距离代价
        i_halfpel_thresh -= i_ref_cost;
        m.i_ref_cost = i_ref_cost;
        m.i_ref = i_ref;

        /* search with ref */
        LOAD_HPELS( &m, h->mb.pic.p_fref[0][i_ref], 0, i_ref, 0, 0 );//从参考帧中读入y,u,v数据到m.p_fref[6],其实是指针赋值
        x264_mb_predict_mv_16x16( h, 0, i_ref, m.mvp );//根据邻块信息计算当前宏块的预测矢量mvp
        x264_mb_predict_mv_ref16x16( h, 0, i_ref, mvc, &i_mvc );//相邻宏块,参考帧中同空间位置的块运动矢量等信息写mvc[],即可能的预测矢量
        x264_me_search_ref( h, &m, mvc, i_mvc, p_halfpel_thresh );//寻找确定搜索中心,然后搜索最佳整像素,半像素和1/4像素点,将最佳矢量和代价信息写入m

        /* early termination
         * SSD threshold would probably be better than SATD */
        if( i_ref == 0 && a->b_try_pskip && m.cost-m.cost_mv < 300*a->i_lambda )
        {
            int mvskip[2];
            x264_mb_predict_mv_pskip( h, mvskip );
            if( abs(m.mv[0]-mvskip[0]) + abs(m.mv[1]-mvskip[1]) <= 1
                && x264_macroblock_probe_pskip( h ) )
            {
                h->mb.i_type = P_SKIP;
                x264_analyse_update_cache( h, a );//Update MB from the analysis 根据分析结果,填写宏块解码相关二维表格信息
                return;
            }
        }

        m.cost += i_ref_cost;
        i_halfpel_thresh += i_ref_cost;

        if( m.cost < a->l0.me16x16.cost )//更新P16*16模式最佳代价

⌨️ 快捷键说明

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