<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Oct 8, 2013 at 6:43 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:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Aarthi Thirumalai<br>
# Date 1381232542 -19800<br>
#      Tue Oct 08 17:12:22 2013 +0530<br>
# Node ID 3ba555e98be2c0641d92d14155c6fb303c0003d9<br>
# Parent  47286888d5a293234340153112810ce2a4f81546<br>
calculate SSIM for each Row after deblock, sao<br></blockquote><div><br></div><div>I've queued this and the other patch after fixing more nits</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
diff -r 47286888d5a2 -r 3ba555e98be2 source/Lib/TLibEncoder/TEncTop.cpp<br>
--- a/source/Lib/TLibEncoder/TEncTop.cpp        Tue Oct 08 17:06:57 2013 +0530<br>
+++ b/source/Lib/TLibEncoder/TEncTop.cpp        Tue Oct 08 17:12:22 2013 +0530<br>
@@ -513,7 +513,7 @@<br>
     int width  = recon->getWidth() - getPad(0);<br>
     int height = recon->getHeight() - getPad(1);<br>
     int size = width * height;<br>
-<br>
+    double ssim = 0;<br>
     UInt64 ssdY = computeSSD(orig->getLumaAddr(), recon->getLumaAddr(), stride, width, height);<br>
<br>
     height >>= 1;<br>
@@ -604,7 +604,14 @@<br>
     {<br>
         m_analyzeB.addResult(psnrY, psnrU, psnrV, (double)bits);<br>
     }<br>
-<br>
+    if (param.bEnableSsim)<br>
+    {<br>
+        if(pic->getSlice()->m_ssimCnt > 0)<br></blockquote><div>white-space </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+        {<br>
+            ssim += pic->getSlice()->m_ssim / pic->getSlice()->m_ssimCnt;<br></blockquote><div>I declared double ssim = pic->.. here since `ssim' is used nowhere else </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

+            m_globalSsim += ssim;<br>
+        }<br>
+    }<br>
     if (param.logLevel >= X265_LOG_DEBUG)<br>
     {<br>
         char c = (slice->isIntra() ? 'I' : slice->isInterP() ? 'P' : 'B');<br>
diff -r 47286888d5a2 -r 3ba555e98be2 source/encoder/frameencoder.cpp<br>
--- a/source/encoder/frameencoder.cpp   Tue Oct 08 17:06:57 2013 +0530<br>
+++ b/source/encoder/frameencoder.cpp   Tue Oct 08 17:12:22 2013 +0530<br>
@@ -92,7 +92,7 @@<br>
     }<br>
<br>
     m_frameFilter.destroy();<br>
-<br>
+    X265_FREE(ssimBuf);<br></blockquote><div><br></div><div>renamed ssimBuf to m_ssimBuf to follow class member naming convention</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

     // wait for worker thread to exit<br>
     stop();<br>
 }<br>
@@ -111,6 +111,9 @@<br>
         m_rows[i].create(top);<br>
     }<br>
<br>
+    if (m_cfg->param.bEnableSsim)<br>
+        CHECKED_MALLOC(ssimBuf, ssim_t, 8 * (m_cfg->param.sourceWidth / 4 + 3));<br></blockquote><div><br></div><div>It's actually *safer* to not use CHECKED_MALLOC here.  You're already checking for NULL pointer below before using the buffer, so all the checked malloc does here is skip the rest of the class initialization, including the part that starts the worker thread.. so instead of a bad malloc causing no SSIM results to be displayed, it would cause the encoder to deadlock.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
     // NOTE: 2 times of numRows because both Encoder and Filter in same queue<br>
     if (!WaveFront::init(m_numRows * 2))<br>
     {<br>
@@ -168,6 +171,8 @@<br>
         assert(0);<br>
     }<br>
     start();<br>
+fail:<br>
+    return;<br>
 }<br>
<br>
 int FrameEncoder::getStreamHeaders(NALUnitEBSP **nalunits)<br>
@@ -535,6 +540,31 @@<br>
         slice->setSaoEnabledFlag((saoParam->bSaoFlag[0] == 1) ? true : false);<br>
     }<br>
<br>
+    /*Compute SSIM if enabled*/<br></blockquote><div><br></div><div>added spaces within /* and */ </div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

+    if (m_cfg->param.bEnableSsim && ssimBuf)<br>
+    {<br>
+        pixel *rec = (pixel*)m_pic->getPicYuvRec()->getLumaAddr();<br>
+        pixel *org = (pixel*)m_pic->getPicYuvOrg()->getLumaAddr();<br>
+        int stride1 = m_pic->getPicYuvOrg()->getStride();<br>
+        int stride2 = m_pic->getPicYuvRec()->getStride();<br>
+        for (int row = 0; row < m_numRows; row++)<br>
+        {<br>
+            int bEnd = ((row + 1) == (this->m_numRows - 1));<br>
+            int bStart = (row == 0);<br>
+            int minPixY = row * 64 - 4 * !bStart;<br>
+            int maxPixY = (row + 1) * 64 - 4 * !bEnd;<br>
+            int ssim_cnt;<br>
+            x265_emms();<br>
+<br>
+            /* SSIM is done for each row in blocks of 4x4 . The First blocks are offset by 2 pixels to the right<br>
+            * to avoid alignment of ssim blocks with DCT blocks. */<br>
+            minPixY += bStart ? 2 : -6;<br>
+            slice->m_ssim += calculateSSIM(rec + 2 + minPixY * stride1, stride1, org + 2 + minPixY * stride2, stride2,<br>
+                m_cfg->param.sourceWidth - 2, maxPixY - minPixY, ssimBuf, &ssim_cnt);<br></blockquote><div><br></div><div>lined up the second line of arguments with the first</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

+            slice->m_ssimCnt += ssim_cnt;<br>
+        }<br>
+    }<br>
+<br>
     entropyCoder->setBitstream(NULL);<br>
<br>
     // Reconstruction slice<br>
@@ -681,6 +711,39 @@<br>
     delete bitstreamRedirect;<br>
 }<br>
<br>
+/* Function to calculate SSIM for each row */<br>
+float FrameEncoder::calculateSSIM(pixel *pix1, intptr_t stride1, pixel *pix2, intptr_t stride2, int width, int height, void *buf, int *cnt)<br>
+{<br>
+    int z = 0;<br>
+    float ssim = 0.0;<br>
+    ssim_t(*sum0)[4] = (ssim_t(*)[4])buf;<br>
+    ssim_t(*sum1)[4] = sum0 + (width >> 2) + 3;<br>
+    width >>= 2;<br>
+    height >>= 2;<br>
+<br>
+    for (int y = 1; y < height; y++)<br>
+    {<br>
+        for (; z <= y; z++)<br>
+        {<br>
+            void* swap = sum0;<br>
+            sum0 = sum1;<br>
+            sum1 = (ssim_t(*)[4])swap;<br>
+            for (int x = 0; x < width; x += 2)<br>
+            {<br>
+                primitives.ssim_4x4x2_core(&pix1[(4 * x + (z * stride1))], stride1, &pix2[(4 * x + (z * stride2))], stride2, &sum0[x]);<br>
+            }<br>
+        }<br>
+<br>
+        for (int x = 0; x < width - 1; x += 4)<br>
+        {<br>
+            ssim += primitives.ssim_end_4(sum0 + x, sum1 + x, X265_MIN(4, width - x - 1));<br>
+        }<br>
+    }<br>
+<br>
+    *cnt = (height - 1) * (width - 1);<br>
+    return ssim;<br>
+}<br>
+<br>
 void FrameEncoder::encodeSlice(TComOutputBitstream* substreams)<br>
 {<br>
     // choose entropy coder<br>
diff -r 47286888d5a2 -r 3ba555e98be2 source/encoder/frameencoder.h<br>
--- a/source/encoder/frameencoder.h     Tue Oct 08 17:06:57 2013 +0530<br>
+++ b/source/encoder/frameencoder.h     Tue Oct 08 17:12:22 2013 +0530<br>
@@ -145,6 +145,9 @@<br>
     /* called by compressFrame to perform wave-front compression analysis */<br>
     void compressCTURows();<br>
<br>
+    /* called by compressFrame to calculate SSIM for each row . */<br></blockquote><div><br></div><div>fixed white-space in the comment</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

+    float calculateSSIM(pixel *pix1, intptr_t stride1, pixel *pix2, intptr_t stride2, int width, int height, void *buf, int *cnt);<br>
+<br>
     void encodeSlice(TComOutputBitstream* substreams);<br>
<br>
     /* blocks until worker thread is done, returns encoded picture and bitstream */<br>
@@ -185,7 +188,10 @@<br>
     int                      m_filterRowDelay;<br>
     CTURow*                  m_rows;<br>
     Event                    m_completionEvent;<br>
+<br>
+    /* Temp Storage for ssim computation that doesnt need repeated malloc */<br></blockquote><div><br></div><div>make Storage lower case, added apostrophe to doesn't</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

+    void *                   ssimBuf;<br></blockquote><div><br></div><div>removed space between void and *, renamed to m_ssimBuf</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

 };<br>
 }<br>
<br>
-#endif // ifndef X265_FRAMEENCODER_H<br>
+#endif // ifndef X265_FRAMEENCODER_H<br>
\ No newline at end of file<br></blockquote><div><br></div><div>now there's a newline</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
_______________________________________________<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>