<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Oct 1, 2013 at 7:07 AM, 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:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"># HG changeset patch<br>
# User Aarthi Thirumalai<br>
# Date 1380629233 -19800<br>
#      Tue Oct 01 17:37:13 2013 +0530<br>
# Node ID bc38d51440330519f411e46d34cf176e7b728069<br>
# Parent  fc225ea42650867a229d15f41e1f2a495629bb7d<br>
primitives :added C primitives to compute SSIM<br></blockquote><div><br></div><div>nit: space goes after the colon (primitives: ) </div><div><br></div><div>put a blank line between the summary line and the rest of the commit message</div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
ssim_4x4x2_core_hb( for high bit depth enabled) , ssim_4x4x2_core_lb(for high bit depth disabled)<br></blockquote><div><br></div><div>This looks much better, but I think it still needs work</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

diff -r fc225ea42650 -r bc38d5144033 source/common/pixel.cpp<br>
--- a/source/common/pixel.cpp   Tue Oct 01 17:28:19 2013 +0530<br>
+++ b/source/common/pixel.cpp   Tue Oct 01 17:37:13 2013 +0530<br>
@@ -636,6 +636,69 @@<br>
     }<br>
 }<br>
<br>
+ /* structural similarity metric */<br></blockquote><div><br></div><div>extra space before the comment</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

+template<class T1><br>
+void ssim_4x4x2_core(const pixel *pix1, intptr_t stride1, const pixel *pix2, intptr_t stride2, T1 sums[2][4])<br>
+{<br>
+    for (int z = 0; z < 2; z++)<br>
+    {<br>
+        T1 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>
+template<class T1><br>
+float ssim_end_4(T1 sum0[5][4], T1 sum1[5][4], int width)<br>
+{<br>
+    float ssim = 0.0;<br>
+    for (int i = 0; i < width; i++)<br>
+        ssim += ssim_end_1(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>
+template<class T1><br>
+float ssim_end_1(T1 s1, T1 s2, T1 ss, T1 s12)<br>
+{<br>
+    static const uint16_t pixelMax = (1 << X265_DEPTH)-1;<br>
+#if HIGH_BIT_DEPTH<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>
+    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></blockquote><div><br></div><div>I think it would be cleaner to simply write two versions of this function; even with HIGH_BIT_DEPTH you don't want to do unnecessary float-to-int conversions if they're not needed.  Even high bit depth builds might need to use the int version.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+    T1 fs1 = s1;<br>
+    T1 fs2 = s2;<br>
+    T1 fss = ss;<br>
+    T1 fs12 = s12;<br>
+    T1 vars = fss * 64 - fs1 * fs1 - fs2 * fs2;<br>
+    T1 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></blockquote><div><br></div><div>this undef is unnecessary</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

+}<br>
+<br>
+<br>
+<br></blockquote><div><br></div><div>unnecessary blank lines</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

 }  // end anonymous namespace<br>
<br>
 namespace x265 {<br>
@@ -851,5 +914,10 @@<br>
     p.scale1D_128to64 = scale1D_128to64;<br>
     p.scale2D_64to32 = scale2D_64to32;<br>
     p.frame_init_lowres_core = frame_init_lowres_core;<br>
+<br>
+    p.ssim_4x4x2_core_hb = ssim_4x4x2_core<float>;<br>
+    p.ssim_4x4x2_core_lb = ssim_4x4x2_core<int>;<br>
+    p.ssim_end4_hb     = ssim_end_4<float>;<br>
+    p.ssim_end4_lb     = ssim_end_4<int>;<br>
 }<br>
 }<br>
diff -r fc225ea42650 -r bc38d5144033 source/common/primitives.h<br>
--- a/source/common/primitives.h        Tue Oct 01 17:28:19 2013 +0530<br>
+++ b/source/common/primitives.h        Tue Oct 01 17:37:13 2013 +0530<br>
@@ -233,6 +233,10 @@<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_lb_t)(const pixel *pix1, intptr_t stride1, const pixel *pix2, intptr_t stride2, int sums[2][4]);<br>
+typedef void (*ssim_4x4x2_core_hb_t)(const pixel *pix1, intptr_t stride1, const pixel *pix2, intptr_t stride2, float sums[2][4]);<br>
+typedef float (*ssim_end4_lb_t)(int sum0[5][4], int sum1[5][4], int width);<br>
+typedef float (*ssim_end4_hb_t)(float sum0[5][4], float sum1[5][4], int width);<br>
<br>
 /* Define a structure containing function pointers to optimized encoder<br>
  * primitives.  Each pointer can reference either an assembly routine,<br>
@@ -297,6 +301,11 @@<br>
     scale_t         scale1D_128to64;<br>
     scale_t         scale2D_64to32;<br>
     downscale_t     frame_init_lowres_core;<br>
+<br>
+    ssim_4x4x2_core_lb_t   ssim_4x4x2_core_lb;<br>
+    ssim_4x4x2_core_hb_t   ssim_4x4x2_core_hb;<br>
+    ssim_end4_lb_t         ssim_end4_lb;<br>
+    ssim_end4_hb_t         ssim_end4_hb;<br>
 };<br></blockquote><div><br></div><div>lb and hb are new acronyms, we don't use those anywhere else.  these would be better as:</div><div><br></div><div>+    ssim_4x4x2_core_int_t   ssim_4x4x2_core_int;<br>+    ssim_4x4x2_core_float_t   ssim_4x4x2_core_float;<br>
</div></div></div></div>