[x265] [PATCH 5 of 5] integrated ssim computation for each CTURow

Aarthi Thirumalai aarthi at multicorewareinc.com
Sat Sep 28 06:52:51 CEST 2013


# HG changeset patch
# User Aarthi Thirumalai
# Date 1380343885 -19800
#      Sat Sep 28 10:21:25 2013 +0530
# Node ID b1539ccab7bab1708433a9b8b18f5f8c090b1810
# Parent  a8b00de495520f00a4648dac5d111e40b5570ca3
integrated ssim computation for each CTURow

diff -r a8b00de49552 -r b1539ccab7ba source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp	Sat Sep 28 10:18:23 2013 +0530
+++ b/source/encoder/frameencoder.cpp	Sat Sep 28 10:21:25 2013 +0530
@@ -91,6 +91,9 @@
         delete[] m_rows;
     }
 
+    if (tempBuf)
+        X265_FREE(tempBuf);
+
     m_frameFilter.destroy();
 
     // wait for worker thread to exit
@@ -106,6 +109,8 @@
                         2 : (m_cfg->param.bEnableSAO || m_cfg->param.bEnableLoopFilter ? 1 : 0);
 
     m_rows = new CTURow[m_numRows];
+    if(m_cfg->param.bEnableSsim)
+        CHECKED_MALLOC(tempBuf, int, m_cfg->param.bEnableSsim * 8 * (m_cfg->param.sourceWidth/4 + 3));
     for (int i = 0; i < m_numRows; ++i)
     {
         m_rows[i].create(top);
@@ -168,6 +173,8 @@
         assert(0);
     }
     start();
+fail:
+    return;
 }
 
 int FrameEncoder::getStreamHeaders(NALUnitEBSP **nalunits)
@@ -540,6 +547,31 @@
         slice->setSaoEnabledFlag((saoParam->bSaoFlag[0] == 1) ? true : false);
     }
 
+    /*Compute SSIM if enabled*/
+       if(m_cfg->param.bEnableSsim)
+       {
+            pixel *rec = (pixel*)m_pic->getPicYuvRec()->getLumaAddr();
+            pixel *org = (pixel*)m_pic->getPicYuvOrg()->getLumaAddr();
+            int stride = m_pic->getPicYuvOrg()->getStride();
+           for(int row = 0; row < m_numRows; row++)
+           {
+               int bEnd = ((row + 1) == (this->m_numRows - 1));
+               int bStart = (row == 0);
+               int minPixY = row * 64 - 4 * !bStart;
+               int maxPixY = (row + 1)* 64 - 4 * !bEnd;
+               int ssim_cnt;
+               x265_emms();
+               /* offset by 2 pixels to avoid alignment of ssim blocks with dct blocks,
+               * and overlap by 4 */
+                minPixY += bStart ? 2 : -6;
+                slice->m_ssim += 
+                calculateSSIM( 
+                rec + 2 + minPixY * stride, stride,
+                org + 2 + minPixY * stride, stride,
+                m_cfg->param.sourceWidth-2, maxPixY - minPixY, tempBuf, &ssim_cnt );
+                slice->m_ssimCnt += ssim_cnt;
+            }
+       }
     entropyCoder->setBitstream(NULL);
 
     // Reconstruction slice
@@ -687,6 +719,38 @@
     delete bitstreamRedirect;
 }
 
+/* Function to calculate SSIM for each row */
+float FrameEncoder::calculateSSIM( pixel *pix1, intptr_t stride1,
+                                   pixel *pix2, intptr_t stride2,
+                                   int width, int height, void *buf, int *cnt )
+{
+    int z = 0;
+    float ssim = 0.0;
+    int (*sum0)[4] = (int (*)[4]) buf;
+    int (*sum1)[4] = sum0 + (width >> 2) + 3;
+    width >>= 2;
+    height >>= 2;
+    for( int y = 1; y < height; y++ )
+    {
+        for( ; z <= y; z++ )
+        {
+            void* swap = sum0;
+            sum0 = sum1;
+            sum1 = (int (*)[4])swap;
+            for( int x = 0; x < width; x+=2 )
+            {
+                if(m_pic->getPicYuvRec() == 0 || x== 98){
+                    int nullaalret = 1; nullaalret++;
+                }
+                primitives.ssim4x4x2Core( &pix1[4*(x+z*stride1)], stride1, &pix2[4*(x+z*stride2)], stride2, &sum0[x] );
+            }
+        }
+        for( int x = 0; x < width-1; x += 4 )
+            ssim += primitives.ssimEnd4( sum0+x, sum1+x, X265_MIN(4,width-x-1) );
+    }
+    *cnt = (height-1) * (width-1);
+    return ssim;
+}
 void FrameEncoder::encodeSlice(TComOutputBitstream* substreams)
 {
     // choose entropy coder
diff -r a8b00de49552 -r b1539ccab7ba source/encoder/frameencoder.h
--- a/source/encoder/frameencoder.h	Sat Sep 28 10:18:23 2013 +0530
+++ b/source/encoder/frameencoder.h	Sat Sep 28 10:21:25 2013 +0530
@@ -153,6 +153,10 @@
     // worker thread
     void threadMain();
 
+    /* called by compressFrame to calculate SSIM for each row after applying deblock filter and SAO. */
+    float calculateSSIM(pixel *pix1, intptr_t stride1,pixel *pix2, intptr_t stride2,
+                        int width, int height, void *buf, int *cnt );
+
     Event                    m_enable;
     Event                    m_done;
     bool                     m_threadActive;
@@ -185,6 +189,9 @@
     int                      m_filterRowDelay;
     CTURow*                  m_rows;
     Event                    m_completionEvent;
+
+    /* Temp Storage that doesnt need repeated malloc */
+    void *                   tempBuf;
 };
 }
 


More information about the x265-devel mailing list