[x265] [PATCH 4 of 5] added C primitives to compute SSIM

Steve Borho steve at borho.org
Mon Sep 30 22:09:45 CEST 2013


On Fri, Sep 27, 2013 at 11:52 PM, Aarthi Thirumalai <
aarthi at multicorewareinc.com> wrote:

> # HG changeset patch
> # User Aarthi Thirumalai
> # Date 1380343703 -19800
> #      Sat Sep 28 10:18:23 2013 +0530
> # Node ID a8b00de495520f00a4648dac5d111e40b5570ca3
> # Parent  1d27b6c649ab4580b1fef5ff8b65bb3e1ffa83b6
> added C primitives to compute SSIM
>
> diff -r 1d27b6c649ab -r a8b00de49552 source/common/pixel.cpp
> --- a/source/common/pixel.cpp   Sat Sep 28 10:12:44 2013 +0530
> +++ b/source/common/pixel.cpp   Sat Sep 28 10:18:23 2013 +0530
> @@ -636,7 +636,76 @@
>      }
>  }
>
> -}  // end anonymous namespace
> +
>
> +/****************************************************************************
> + * structural similarity metric
> +
> ****************************************************************************/
> +void ssim4x4x2Core( const pixel *pix1, intptr_t stride1,
> +                             const pixel *pix2, intptr_t stride2,
> +                             int sums[2][4] )

+{
> +    for( int z = 0; z < 2; z++ )
>

coding style (whole function)


> +    {
> +        uint32_t s1 = 0, s2 = 0, ss = 0, s12 = 0;
> +        for( int y = 0; y < 4; y++ )
> +            for( int x = 0; x < 4; x++ )
> +            {
> +                int a = pix1[x + y * stride1];
> +                int b = pix2[x + y * stride2];
> +                s1  += a;
> +                s2  += b;
> +                ss  += a*a;
> +                ss  += b*b;
> +                s12 += a*b;
> +            }
> +        sums[z][0] = s1;
> +        sums[z][1] = s2;
> +        sums[z][2] = ss;
> +        sums[z][3] = s12;
> +        pix1 += 4;
> +        pix2 += 4;
> +    }
> +}
> +
>


x264 knows at compile time what the size of their pixels will be (8 or 10).
 We don't have that luxury, so we will need to define a float and an int
version of this primitive and pick the appropriate one at runtime.


> + float ssim_end1( int s1, int s2, int ss, int s12 )
> +{
> +/* Maximum value for 10-bit is: ss*64 = (2^10-1)^2*16*4*64 = 4286582784,
> which will overflow in some cases.
> + * s1*s1, s2*s2, and s1*s2 also obtain this value for edge cases:
> ((2^10-1)*16*4)^2 = 4286582784.
> + * Maximum value for 9-bit is: ss*64 = (2^9-1)^2*16*4*64 = 1069551616,
> which will not overflow. */
> +    static const uint16_t pixelMax = (1 << X265_DEPTH)-1;
> +#if BIT_DEPTH > 9
> +#define type float
> +    static const float ssim_c1 = .01 * .01 * pixelMax * pixelMax * 64;
> +    static const float ssim_c2 = .03 * .03 * pixelMax * pixelMax * 64 *
> 63;
> +#else
> +#define type int
> +    static const int ssim_c1 = (int)(.01 *.01 * pixelMax * pixelMax * 64
> + .5);
> +    static const int ssim_c2 = (int)(.03*.03 * pixelMax * pixelMax * 64 *
> 63 + .5);
> +#endif
> +    type fs1 = s1;
> +    type fs2 = s2;
> +    type fss = ss;
> +    type fs12 = s12;
> +    type vars = fss * 64 - fs1 * fs1 - fs2 * fs2;
> +    type covar = fs12 * 64 - fs1 * fs2;
> +    return (float)(2 * fs1 * fs2 + ssim_c1) * (float)(2 * covar + ssim_c2)
> +         / ((float)(fs1 * fs1 + fs2 * fs2 + ssim_c1) * (float)(vars +
> ssim_c2));
> +#undef type
> +}
> +
> + float ssimEnd4( int sum0[5][4], int sum1[5][4], int width )
> +{
> +    float ssim = 0.0;
> +    for( int i = 0; i < width; i++ )
> +        ssim += ssim_end1( sum0[i][0] + sum0[i+1][0] + sum1[i][0] +
> sum1[i+1][0],
> +                           sum0[i][1] + sum0[i+1][1] + sum1[i][1] +
> sum1[i+1][1],
> +                           sum0[i][2] + sum0[i+1][2] + sum1[i][2] +
> sum1[i+1][2],
> +                           sum0[i][3] + sum0[i+1][3] + sum1[i][3] +
> sum1[i+1][3] );
> +    return ssim;
> +}
> +
> +
> +}  // end anonymous namespace
>
>  namespace x265 {
>  // x265 private namespace
> @@ -851,5 +920,7 @@
>      p.scale1D_128to64 = scale1D_128to64;
>      p.scale2D_64to32 = scale2D_64to32;
>      p.frame_init_lowres_core = frame_init_lowres_core;
> +    p.ssim4x4x2Core = ssim4x4x2Core;
> +    p.ssimEnd4 = ssimEnd4;
>  }
>  }
> diff -r 1d27b6c649ab -r a8b00de49552 source/common/primitives.h
> --- a/source/common/primitives.h        Sat Sep 28 10:12:44 2013 +0530
> +++ b/source/common/primitives.h        Sat Sep 28 10:18:23 2013 +0530
> @@ -233,6 +233,9 @@
>  typedef void (*scale_t)(pixel *dst, pixel *src, intptr_t stride);
>  typedef void (*downscale_t)(pixel *src0, pixel *dstf, pixel *dsth, pixel
> *dstv, pixel *dstc,
>                              intptr_t src_stride, intptr_t dst_stride, int
> width, int height);
> +typedef void (*ssim_4x4x2_core)( const pixel *pix1, intptr_t stride1,
> const pixel *pix2, intptr_t stride2, int sums[2][4] );
> +typedef float (*ssim_end4)( int sum0[5][4], int sum1[5][4], int width );
>

white-space, please add _t suffixes to function typedefs


> +
>
>  /* Define a structure containing function pointers to optimized encoder
>   * primitives.  Each pointer can reference either an assembly routine,
> @@ -297,6 +300,10 @@
>      scale_t         scale1D_128to64;
>      scale_t         scale2D_64to32;
>      downscale_t     frame_init_lowres_core;
> +
> +    ssim_4x4x2_core ssim4x4x2Core;
> +    ssim_end4       ssimEnd4;
> +
>  };
>
>  /* This copy of the table is what gets used by the encoder.
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>



-- 
Steve Borho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20130930/76bd1ba0/attachment.html>


More information about the x265-devel mailing list