美文网首页
(六)帧内宏块预测3:v,h,dc和plane预测模式

(六)帧内宏块预测3:v,h,dc和plane预测模式

作者: 奔向火星005 | 来源:发表于2018-08-27 20:16 被阅读0次
    我们在帧内宏块预测(一)中的白皮书翻译中曾提到,16x16宏块有4种预测模式,在这里再把图展示一下: 帧内预测图5.png

    为了简单期间,这里以8x8宏块为例说明一下源码中的实现。

    void x264_predict_8x8c_dc_c( pixel *src )
    {
        int s0 = 0, s1 = 0, s2 = 0, s3 = 0;
    
        /*
              s0 s1
           s2
           s3
        */
        for( int i = 0; i < 4; i++ )
        {
            s0 += src[i - FDEC_STRIDE];      //s0 = src[-32] + src[-31] + src[-30] + src[-29]
            s1 += src[i + 4 - FDEC_STRIDE];  //s1 = src[-28] + src[-27] + src[-26] + src[-25]
            s2 += src[-1 + i * FDEC_STRIDE]; //s2 = src[31] + src[63] + src[95] + src[127]
            s3 += src[-1 + (i+4)*FDEC_STRIDE];  //s3 = ...
        }
        /*
           dc0 dc1
           dc2 dc3
         */
        pixel4 dc0 = PIXEL_SPLAT_X4( ( s0 + s2 + 4 ) >> 3 ); //(s0 + s2 + 4) / 8 * 0x01010101U
        pixel4 dc1 = PIXEL_SPLAT_X4( ( s1 + 2 ) >> 2 );      //(s1 + 2) / 4 * 0x01010101U
        pixel4 dc2 = PIXEL_SPLAT_X4( ( s3 + 2 ) >> 2 );      //(s3 + 2) / 4 * 0x01010101U
        pixel4 dc3 = PIXEL_SPLAT_X4( ( s1 + s3 + 4 ) >> 3 ); //(s1 + s3 + 4) / 8 * 0x01010101U
    
        for( int y = 0; y < 4; y++ )
        {
            MPIXEL_X4( src+0 ) = dc0;
            MPIXEL_X4( src+4 ) = dc1;
            src += FDEC_STRIDE;
        }
    
        for( int y = 0; y < 4; y++ )
        {
            MPIXEL_X4( src+0 ) = dc2;
            MPIXEL_X4( src+4 ) = dc3;
            src += FDEC_STRIDE;
        }
    }
    

    从源码看出dc预测很简单,实际上就是求左方和上方像素的平均值。简单画了个图:


    dc预测00.png

    水平,垂直预测更简单,就不做分析了,贴下代码:

    void x264_predict_8x8c_h_c( pixel *src )
    {
        for( int i = 0; i < 8; i++ )
        {
            pixel4 v = PIXEL_SPLAT_X4( src[-1] );
            MPIXEL_X4( src+0 ) = v;
            MPIXEL_X4( src+4 ) = v;
            src += FDEC_STRIDE;
        }
    }
    void x264_predict_8x8c_v_c( pixel *src )
    {
        pixel4 v0 = MPIXEL_X4( src+0-FDEC_STRIDE );
        pixel4 v1 = MPIXEL_X4( src+4-FDEC_STRIDE );
    
        for( int i = 0; i < 8; i++ )
        {
            MPIXEL_X4( src+0 ) = v0;
            MPIXEL_X4( src+4 ) = v1;
            src += FDEC_STRIDE;
        }
    }
    

    plane模式稍微复杂些,源码如下:

    void x264_predict_8x8c_p_c( pixel *src )
    {
        int H = 0, V = 0;
    
        for( int i = 0; i < 4; i++ )
        {
            //H = (H[4] - H[2]) + 2 * (H[5] - H[1]) + 3 * (H[6] - H[0]) + 4 * (H[7] - H[1])
            //V = (V[4] - V[2]) + 2 * (V[5] - V[1]) + 3 * (V[6] - V[0]) + 4 * (V[7] - V[1])
            H += ( i + 1 ) * ( src[4+i - FDEC_STRIDE] - src[2 - i -FDEC_STRIDE] );
            V += ( i + 1 ) * ( src[-1 +(i+4)*FDEC_STRIDE] - src[-1+(2-i)*FDEC_STRIDE] );
        }
    
        //a = 16 * (V[7] + H[7])
        int a = 16 * ( src[-1+7*FDEC_STRIDE] + src[7 - FDEC_STRIDE] );
        int b = ( 17 * H + 16 ) >> 5;
        int c = ( 17 * V + 16 ) >> 5;
        int i00 = a -3*b -3*c + 16;
    
        //src[x][y] = 16 * (V[7] + H[7]) + m * ((H[4]-H[2]) + 2*(H[5]-H[1]) + 3*(H[6]-H[0]) + 4*(H[7]-H[1])) + n * ((V[4] - V[2]) + 2 * (V[5] - V[1]) + 3 * (V[6] - V[0]) + 4 * (V[7] - V[1])) + 16
        for( int y = 0; y < 8; y++ )
        {
            int pix = i00;
            for( int x = 0; x < 8; x++ )
            {
                src[x] = x264_clip_pixel( pix>>5 );
                pix += b;
            }
            src += FDEC_STRIDE;
            i00 += c;
        }
    }
    

    源码中,H的值大小代表宏块上方靠右边的像素与左边像素的差值,V的值大小宏块左方靠下方的像素与靠上方像素的差值,src[x][y]是预测宏块的值,m和n是一个系数,它的大小跟x和y有关,当x越大时,m的值越大,表示水平方向的差值占的权重越大,当y越大时,n的值越大,表示垂直方向的差值占的权重越大。

    相关文章

      网友评论

          本文标题:(六)帧内宏块预测3:v,h,dc和plane预测模式

          本文链接:https://www.haomeiwen.com/subject/tyntwftx.html