[x265] [PATCH] primitives: added C primitives to compute SSIM

Aarthi Thirumalai aarthi at multicorewareinc.com
Sun Oct 6 22:41:24 CEST 2013


# HG changeset patch
# User Aarthi Thirumalai
# Date 1381091976 -19800
#      Mon Oct 07 02:09:36 2013 +0530
# Node ID e58bbff11696e0f6f4f5b2975d1b449174e9e839
# Parent  c010342f7605c86867824f5b525a8f84c0d2de1c
primitives: added C primitives to compute SSIM

diff -r c010342f7605 -r e58bbff11696 source/common/pixel.cpp
--- a/source/common/pixel.cpp	Sun Oct 06 02:09:00 2013 -0500
+++ b/source/common/pixel.cpp	Mon Oct 07 02:09:36 2013 +0530
@@ -653,6 +653,74 @@
     }
 }
 
+/* structural similarity metric */
+template<class T1>
+void ssim_4x4x2_core(const pixel *pix1, intptr_t stride1, const pixel *pix2, intptr_t stride2, T1 sums[2][4])
+{
+    for (int z = 0; z < 2; z++)
+    {
+        T1 s1 = 0, s2 = 0, ss = 0, s12 = 0;
+        for (int y = 0; y < 4; y++)
+        {
+            for (int x = 0; x < 4; x++)
+            {
+                T1 a = pix1[x + y * stride1];
+                T1 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;
+    }
+}
+
+template<class T1>
+float ssim_end_4(T1 sum0[5][4], T1 sum1[5][4], int width)
+{
+    float ssim = 0.0;
+
+    for (int i = 0; i < width; i++)
+    {
+        ssim += ssim_end_1(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;
+}
+
+float ssim_end_1(int32_t s1, int32_t s2, int32_t ss, int32_t s12)
+{
+    static const uint32_t pixelMax = (1 << X265_DEPTH) - 1;
+    static const int32_t ssim_c1 = (int32_t)(.01 * .01 * pixelMax * pixelMax * 64 + .5);
+    static const int32_t ssim_c2 = (int32_t)(.03 * .03 * pixelMax * pixelMax * 64 * 63 + .5);
+    int32_t vars = ss * 64 - s1 * s1 - s2 * s2;
+    int32_t covar = s12 * 64 - s1 * s2;
+    return (float)(2 * s1 * s2 + ssim_c1) * (float)(2 * covar + ssim_c2)
+           / ((float)(s1 * s1 + s2 * s2 + ssim_c1) * (float)(vars + ssim_c2));
+}
+
+float ssim_end_1(int64_t s1, int64_t s2, int64_t ss, int64_t s12)
+{
+    static const int64_t pixelMax = (1 << X265_DEPTH) - 1;
+    static const int64_t ssim_c1 = (int64_t)(.01 * .01 * pixelMax * pixelMax * 64 + .5);
+    static const int64_t ssim_c2 = (int64_t)(.03 * .03 * pixelMax * pixelMax * 64 * 63 + .5);
+    int64_t vars = ss * 64 - s1 * s1 - s2 * s2;
+    int64_t covar = s12 * 64 - s1 * s2;
+
+    return (float)(2 * s1 * s2 + ssim_c1) * (float)(2 * covar + ssim_c2)
+           / ((float)(s1 * s1 + s2 * s2 + ssim_c1) * (float)(vars + ssim_c2));
+}
 }  // end anonymous namespace
 
 namespace x265 {
@@ -870,5 +938,10 @@
     p.scale1D_128to64 = scale1D_128to64;
     p.scale2D_64to32 = scale2D_64to32;
     p.frame_init_lowres_core = frame_init_lowres_core;
+
+    p.ssim_4x4x2_core_int32 = ssim_4x4x2_core<int32_t>;
+    p.ssim_4x4x2_core_int64 = ssim_4x4x2_core<int64_t>;
+    p.ssim_end4_int32       = ssim_end_4<int32_t>;
+    p.ssim_end4_int64       = ssim_end_4<int64_t>;
 }
 }
diff -r c010342f7605 -r e58bbff11696 source/common/primitives.h
--- a/source/common/primitives.h	Sun Oct 06 02:09:00 2013 -0500
+++ b/source/common/primitives.h	Mon Oct 07 02:09:36 2013 +0530
@@ -235,6 +235,10 @@
 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_int32_t)(const pixel *pix1, intptr_t stride1, const pixel *pix2, intptr_t stride2, int32_t sums[2][4]);
+typedef void (*ssim_4x4x2_core_int64_t)(const pixel *pix1, intptr_t stride1, const pixel *pix2, intptr_t stride2, int64_t sums[2][4]);
+typedef float (*ssim_end4_int32_t)(int32_t sum0[5][4], int32_t sum1[5][4], int width);
+typedef float (*ssim_end4_int64_t)(int64_t sum0[5][4], int64_t sum1[5][4], int width);
 
 /* Define a structure containing function pointers to optimized encoder
  * primitives.  Each pointer can reference either an assembly routine,
@@ -301,6 +305,11 @@
     scale_t         scale1D_128to64;
     scale_t         scale2D_64to32;
     downscale_t     frame_init_lowres_core;
+
+    ssim_4x4x2_core_int32_t   ssim_4x4x2_core_int32;
+    ssim_4x4x2_core_int64_t   ssim_4x4x2_core_int64;
+    ssim_end4_int32_t         ssim_end4_int32;
+    ssim_end4_int64_t         ssim_end4_int64;
 };
 
 /* This copy of the table is what gets used by the encoder.


More information about the x265-devel mailing list