美文网首页
(七)宏块的satd计算

(七)宏块的satd计算

作者: 奔向火星005 | 来源:发表于2018-08-29 13:13 被阅读0次

    satd算法可以用于计算两个宏块之间相似度,它先对待编码宏块与预测宏块相减,得到矩阵Q,然后对矩阵Q进行hadamard变换,再对矩阵元素绝对值求和,就得到两个宏块的satd值。hadamard变换是指分别对该矩阵左右乘矩阵H,如4阶矩阵H和变换公式如下:


    hadamard00.png

    x264中的Hadamard左乘实现如下:

    //d0 = s0 + s1 + s2 + s3;
    //d1 = s0 - s1 + s2 - s3;
    //d2 = s0 + s1 - s2 - s3;
    //d3 = s0 - s1 - s2 + s3;
    #define HADAMARD4(d0, d1, d2, d3, s0, s1, s2, s3) {\
        sum2_t t0 = s0 + s1;\
        sum2_t t1 = s0 - s1;\
        sum2_t t2 = s2 + s3;\
        sum2_t t3 = s2 - s3;\
        d0 = t0 + t2;\
        d2 = t0 - t2;\
        d1 = t1 + t3;\
        d3 = t1 - t3;\
    }
    

    该宏定义实现了4x4的H与4x1矩阵相乘。

    下面看下源码中两个宏块的satd是如何求得:

    #define PIXEL_SATD_C( w, h, sub )\
    static int x264_pixel_satd_##w##x##h( pixel *pix1, intptr_t i_pix1, pixel *pix2, intptr_t i_pix2 )\
    {\
        int sum = sub( pix1, i_pix1, pix2, i_pix2 )\
                + sub( pix1+4*i_pix1, i_pix1, pix2+4*i_pix2, i_pix2 );\
        if( w==16 )\
            sum+= sub( pix1+8, i_pix1, pix2+8, i_pix2 )\
                + sub( pix1+8+4*i_pix1, i_pix1, pix2+8+4*i_pix2, i_pix2 );\
        if( h==16 )\
            sum+= sub( pix1+8*i_pix1, i_pix1, pix2+8*i_pix2, i_pix2 )\
                + sub( pix1+12*i_pix1, i_pix1, pix2+12*i_pix2, i_pix2 );\
        if( w==16 && h==16 )\
            sum+= sub( pix1+8+8*i_pix1, i_pix1, pix2+8+8*i_pix2, i_pix2 )\
                + sub( pix1+8+12*i_pix1, i_pix1, pix2+8+12*i_pix2, i_pix2 );\
        return sum;\
    }
    PIXEL_SATD_C( 16, 16, x264_pixel_satd_8x4 )
    PIXEL_SATD_C( 16, 8,  x264_pixel_satd_8x4 )
    PIXEL_SATD_C( 8,  16, x264_pixel_satd_8x4 )
    PIXEL_SATD_C( 8,  8,  x264_pixel_satd_8x4 )
    PIXEL_SATD_C( 4,  16, x264_pixel_satd_4x4 )
    PIXEL_SATD_C( 4,  8,  x264_pixel_satd_4x4 )
    
    

    以8x8宏块为例,它其实是调用了两次x264_pixel_satd_8x4函数,实现如下:

    static NOINLINE int x264_pixel_satd_8x4( pixel *pix1, intptr_t i_pix1, pixel *pix2, intptr_t i_pix2 )
    {
        sum2_t tmp[4][4];
        sum2_t a0, a1, a2, a3;
        sum2_t sum = 0;
    
        for( int i = 0; i < 4; i++, pix1 += i_pix1, pix2 += i_pix2 )
        {
            a0 = (pix1[0] - pix2[0]) + ((sum2_t)(pix1[4] - pix2[4]) << BITS_PER_SUM);  //1.pix1和pix2宏块的差值
            a1 = (pix1[1] - pix2[1]) + ((sum2_t)(pix1[5] - pix2[5]) << BITS_PER_SUM);
            a2 = (pix1[2] - pix2[2]) + ((sum2_t)(pix1[6] - pix2[6]) << BITS_PER_SUM);
            a3 = (pix1[3] - pix2[3]) + ((sum2_t)(pix1[7] - pix2[7]) << BITS_PER_SUM);
            HADAMARD4( tmp[i][0], tmp[i][1], tmp[i][2], tmp[i][3], a0,a1,a2,a3 );  //2.左乘H
        }
        for( int i = 0; i < 4; i++ )
        {
            HADAMARD4( a0, a1, a2, a3, tmp[0][i], tmp[1][i], tmp[2][i], tmp[3][i] );  //3.右乘H
            sum += abs2(a0) + abs2(a1) + abs2(a2) + abs2(a3);  //4.绝对值的和
        }
        return (((sum_t)sum) + (sum>>BITS_PER_SUM)) >> 1;
    }
    

    相关文章

      网友评论

          本文标题:(七)宏块的satd计算

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