<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 1380343885 -19800<br>
# Sat Sep 28 10:21:25 2013 +0530<br>
# Node ID b1539ccab7bab1708433a9b8b18f5f8c090b1810<br>
# Parent a8b00de495520f00a4648dac5d111e40b5570ca3<br>
integrated ssim computation for each CTURow<br>
<br>
diff -r a8b00de49552 -r b1539ccab7ba source/encoder/frameencoder.cpp<br>
--- a/source/encoder/frameencoder.cpp Sat Sep 28 10:18:23 2013 +0530<br>
+++ b/source/encoder/frameencoder.cpp Sat Sep 28 10:21:25 2013 +0530<br>
@@ -91,6 +91,9 @@<br>
delete[] m_rows;<br>
}<br>
<br>
+ if (tempBuf)<br></blockquote><div><br></div><div>X265_FREE does the NULL check for you</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ X265_FREE(tempBuf);<br>
+<br>
m_frameFilter.destroy();<br>
<br>
// wait for worker thread to exit<br>
@@ -106,6 +109,8 @@<br>
2 : (m_cfg->param.bEnableSAO || m_cfg->param.bEnableLoopFilter ? 1 : 0);<br>
<br>
m_rows = new CTURow[m_numRows];<br>
+ if(m_cfg->param.bEnableSsim)<br></blockquote><div><br></div><div>white-space</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ CHECKED_MALLOC(tempBuf, int, m_cfg->param.bEnableSsim * 8 * (m_cfg->param.sourceWidth/4 + 3));<br>
for (int i = 0; i < m_numRows; ++i)<br>
{<br>
m_rows[i].create(top);<br>
@@ -168,6 +173,8 @@<br>
assert(0);<br>
}<br>
start();<br>
+fail:<br>
+ return;<br>
}<br>
<br>
int FrameEncoder::getStreamHeaders(NALUnitEBSP **nalunits)<br>
@@ -540,6 +547,31 @@<br>
slice->setSaoEnabledFlag((saoParam->bSaoFlag[0] == 1) ? true : false);<br>
}<br>
<br>
+ /*Compute SSIM if enabled*/<br>
+ if(m_cfg->param.bEnableSsim)<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>
+ pixel *rec = (pixel*)m_pic->getPicYuvRec()->getLumaAddr();<br>
+ pixel *org = (pixel*)m_pic->getPicYuvOrg()->getLumaAddr();<br>
+ int stride = m_pic->getPicYuvOrg()->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>
+ /* offset by 2 pixels to avoid alignment of ssim blocks with dct blocks,<br>
+ * and overlap by 4 */<br></blockquote><div><br></div><div>do you understand what this comment implies? I don't and we probably should</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ minPixY += bStart ? 2 : -6;<br>
+ slice->m_ssim +=<br>
+ calculateSSIM(<br>
+ rec + 2 + minPixY * stride, stride,<br>
+ org + 2 + minPixY * stride, stride,<br>
+ m_cfg->param.sourceWidth-2, maxPixY - minPixY, tempBuf, &ssim_cnt );<br></blockquote><div><br></div><div>formatting</div><div> </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>
entropyCoder->setBitstream(NULL);<br>
<br>
// Reconstruction slice<br>
@@ -687,6 +719,38 @@<br>
delete bitstreamRedirect;<br>
}<br>
<br>
+/* Function to calculate SSIM for each row */<br>
+float FrameEncoder::calculateSSIM( pixel *pix1, intptr_t stride1,<br>
+ pixel *pix2, intptr_t stride2,<br>
+ int width, int height, void *buf, int *cnt )<br></blockquote><div>coding-style </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+{<br>
+ int z = 0;<br>
+ float ssim = 0.0;<br>
+ int (*sum0)[4] = (int (*)[4]) buf;<br>
+ int (*sum1)[4] = sum0 + (width >> 2) + 3;<br>
+ width >>= 2;<br>
+ height >>= 2;<br>
+ for( int y = 1; y < height; y++ )<br>
+ {<br>
+ for( ; z <= y; z++ )<br>
+ {<br>
+ void* swap = sum0;<br>
+ sum0 = sum1;<br>
+ sum1 = (int (*)[4])swap;<br>
+ for( int x = 0; x < width; x+=2 )<br>
+ {<br>
+ if(m_pic->getPicYuvRec() == 0 || x== 98){<br>
+ int nullaalret = 1; nullaalret++;<br>
+ }<br>
+ primitives.ssim4x4x2Core( &pix1[4*(x+z*stride1)], stride1, &pix2[4*(x+z*stride2)], stride2, &sum0[x] );<br>
+ }<br>
+ }<br>
+ for( int x = 0; x < width-1; x += 4 )<br>
+ ssim += primitives.ssimEnd4( sum0+x, sum1+x, X265_MIN(4,width-x-1) );<br>
+ }<br>
+ *cnt = (height-1) * (width-1);<br>
+ return ssim;<br>
+}<br>
void FrameEncoder::encodeSlice(TComOutputBitstream* substreams)<br>
{<br>
// choose entropy coder<br>
diff -r a8b00de49552 -r b1539ccab7ba source/encoder/frameencoder.h<br>
--- a/source/encoder/frameencoder.h Sat Sep 28 10:18:23 2013 +0530<br>
+++ b/source/encoder/frameencoder.h Sat Sep 28 10:21:25 2013 +0530<br>
@@ -153,6 +153,10 @@<br>
// worker thread<br>
void threadMain();<br>
<br>
+ /* called by compressFrame to calculate SSIM for each row after applying deblock filter and SAO. */<br>
+ float calculateSSIM(pixel *pix1, intptr_t stride1,pixel *pix2, intptr_t stride2,<br>
+ int width, int height, void *buf, int *cnt );<br>
+<br>
Event m_enable;<br>
Event m_done;<br>
bool m_threadActive;<br>
@@ -185,6 +189,9 @@<br>
int m_filterRowDelay;<br>
CTURow* m_rows;<br>
Event m_completionEvent;<br>
+<br>
+ /* Temp Storage that doesnt need repeated malloc */<br>
+ void * tempBuf;<br>
};<br>
}<br>
<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>