<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Sep 27, 2013 at 11:52 PM, Aarthi Thirumalai <span dir="ltr"><<a href="mailto:aarthi@multicorewareinc.com" target="_blank">aarthi@multicorewareinc.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Aarthi Thirumalai<br>
# Date 1380343703 -19800<br>
#      Sat Sep 28 10:18:23 2013 +0530<br>
# Node ID a8b00de495520f00a4648dac5d111e40b5570ca3<br>
# Parent  1d27b6c649ab4580b1fef5ff8b65bb3e1ffa83b6<br>
added C primitives to compute SSIM<br>
<br>
diff -r 1d27b6c649ab -r a8b00de49552 source/common/pixel.cpp<br>
--- a/source/common/pixel.cpp   Sat Sep 28 10:12:44 2013 +0530<br>
+++ b/source/common/pixel.cpp   Sat Sep 28 10:18:23 2013 +0530<br>
@@ -636,7 +636,76 @@<br>
     }<br>
 }<br>
<br>
-}  // end anonymous namespace<br>
+<br>
+/****************************************************************************<br>
+ * structural similarity metric<br>
+ ****************************************************************************/<br>
+void ssim4x4x2Core( const pixel *pix1, intptr_t stride1,<br>
+                             const pixel *pix2, intptr_t stride2,<br>
+                             int sums[2][4] ) </blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+{<br>
+    for( int z = 0; z < 2; z++ )<br></blockquote><div><br></div><div>coding style (whole function)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

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

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