帧内预测1

 

帧内预测

static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_inter )

{

ount++;*/

 

通过一个标志位来决定帧内或帧间

const unsigned int flags = h->sh.i_type == SLICE_TYPE_I ? h->param.analyse.intra : h->param.analyse.inter;

 

这里跟我想的很不一样,我分析的是第一个IDR帧,我想这个时候p_dst要么应该是空的要么初值应该和p_src是相同的,但是打印出来并不是这么回事。p_src没有说的就是第一个像素块的地址

pixel *p_src = h->mb.pic.p_fenc[0];

pixel *p_dst = h->mb.pic.p_fdec[0];

 

    static const int8_t intra_analysis_shortcut[2][2][2][5] =

    {

        {{{I_PRED_4x4_HU, -1, -1, -1, -1},

          {I_PRED_4x4_DDL, I_PRED_4x4_VL, -1, -1, -1}},

         {{I_PRED_4x4_DDR, I_PRED_4x4_HD, I_PRED_4x4_HU, -1, -1},

          {I_PRED_4x4_DDL, I_PRED_4x4_DDR, I_PRED_4x4_VR, I_PRED_4x4_VL, -1}}},

        {{{I_PRED_4x4_HU, -1, -1, -1, -1},

          {-1, -1, -1, -1, -1}},

         {{I_PRED_4x4_DDR, I_PRED_4x4_HD, I_PRED_4x4_HU, -1, -1},

          {I_PRED_4x4_DDR, I_PRED_4x4_VR, -1, -1, -1}}},

    };

 

//下面有对这个函数的详细分析,大致说就是通过传递过来的h->mb.i_neighbour_intra这个参数可以决定当前的帧块附近(上,左,上左)是否有宏块存在

const int8_t *predict_mode = predict_16x16_mode_available( h->mb.i_neighbour_intra );

 

/* Not heavily tuned */  没看懂这两行

static const uint8_t i16x16_thresh_lut[11] = { 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4 };

int i16x16_thresh = a->b_fast_intra ? (i16x16_thresh_lut[h->mb.i_subpel_refine]*i_satd_inter)>>1 : COST_MAX;

 

 

这个接前面那个通过上面的predict_16x16_mode_available函数可以定位到使用哪几个预测函数,周围宏块数的不同可以使用的个数也不同

 

由于分析的是IDR帧  这个if先没有分析 直接跳到else  后面有详细解释为什么这里不会执行到,就是因为predict_16x16_mode_available函数

if( !h->mb.b_lossless && predict_mode[3] >= 0 )

    {

        h->pixf.intra_mbcmp_x3_16x16( p_src, p_dst, a->i_satd_i16x16_dir );

        a->i_satd_i16x16_dir[0] += lambda * bs_size_ue(0);

        a->i_satd_i16x16_dir[1] += lambda * bs_size_ue(1);

        a->i_satd_i16x16_dir[2] += lambda * bs_size_ue(2);

        COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[0], a->i_predict16x16, 0 );

        COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[1], a->i_predict16x16, 1 );

        COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[2], a->i_predict16x16, 2 );

 

        /* Plane is expensive, so don't check it unless one of the previous modes was useful. */

        if( a->i_satd_i16x16 <= i16x16_thresh )

        {

            h->predict_16x16[I_PRED_16x16_P]( p_dst );

            a->i_satd_i16x16_dir[I_PRED_16x16_P] = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE );

            a->i_satd_i16x16_dir[I_PRED_16x16_P] += lambda * bs_size_ue(3);

            COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[I_PRED_16x16_P], a->i_predict16x16, 3 );

        }

}

直接跳到这里 如果是第一个IDR帧的话,预测方式只有一种

else

    {

        for( ; *predict_mode >= 0; predict_mode++ )

        {

            int i_satd;

            int i_mode = *predict_mode;

 

           

            if( h->mb.b_lossless )

                x264_predict_lossless_16x16( h, 0, i_mode );

            else

                h->predict_16x16[i_mode]( p_dst );          

 

            i_satd = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE ) +

                     lambda * bs_size_ue( x264_mb_pred_mode16x16_fix[i_mode] );

            COPY2_IF_LT( a->i_satd_i16x16, i_satd, a->i_predict16x16, i_mode );

            a->i_satd_i16x16_dir[i_mode] = i_satd;

        }

    }

 

 

}

 

static ALWAYS_INLINE const int8_t *predict_16x16_mode_available( int i_neighbour )

{

这里首先通过传递过来的i_neighbour 变量和本来定义好的结构体macroblock_position_e做与操作,然后可以得到一个标记idx,这个idx可以标记有多少个宏块,然后再次定位

int idx = i_neighbour & (MB_TOP|MB_LEFT|MB_TOPLEFT);

其实主要是为了得到这个idx ,通过它可以直接定位可以用多少种预测方法,但是书上说就四种对于16x16,但是这里冒出来五种,貌似对于IDR的第一个宏块有特殊处理,就是那个I_PRED_16x16_DC_128

    idx = (idx == (MB_TOP|MB_LEFT|MB_TOPLEFT)) ? 4 : idx & (MB_TOP|MB_LEFT);

得到idx然后通过可以的预测模式就可以得到能使用多少中预测方法了。

    return i16x16_mode_available[idx];

}

举个例子 IDR的第一个(第一行第一列)宏块传过来的是i_neighbour传过来的是0,通过两次操作最后得到是0,所以他的预测模式就是 下面二位数组的第一个{I_PRED_16x16_DC_128, -1, -1, -1, -1},里面只有一种可用的预测模式。

第二行的第一个宏块传递过来的i_neighbour是6,通过两次相与操作后,idx的值为1,所以可用的预测模式就是{I_PRED_16x16_DC_LEFT, I_PRED_16x16_H, -1, -1, -1}

第二行的第二个到倒数第二个所含的宏块i_neighbour都是15可以以此类推。

第二行的最后一个i_neighbour的值为11

比较特殊的就这几个,由于IDR就是I帧,所以可以推测所有的宏块i_neighbour类型

 

 

static const int8_t i16x16_mode_available[5][5] =

{

    {I_PRED_16x16_DC_128, -1, -1, -1, -1},

    {I_PRED_16x16_DC_LEFT, I_PRED_16x16_H, -1, -1, -1},

    {I_PRED_16x16_DC_TOP, I_PRED_16x16_V, -1, -1, -1},

    {I_PRED_16x16_V, I_PRED_16x16_H, I_PRED_16x16_DC, -1, -1},

    {I_PRED_16x16_V, I_PRED_16x16_H, I_PRED_16x16_DC, I_PRED_16x16_P, -1},

};

 

enum macroblock_position_e

{

    MB_LEFT     = 0x01,

    MB_TOP      = 0x02,

    MB_TOPRIGHT = 0x04,

    MB_TOPLEFT  = 0x08,

 

    MB_PRIVATE  = 0x10,

 

    ALL_NEIGHBORS = 0xf,

};

 

 

 

 

posted on 2012-04-13 17:42  hatreds  阅读(836)  评论(1编辑  收藏  举报