<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Oct 4, 2013 at 6:21 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 1380885604 -19800<br>
# Fri Oct 04 16:50:04 2013 +0530<br>
# Node ID ed4f57163274364e419dabfa4f864aa5a48cab6b<br>
# Parent 92641f3d3195b8da2275cfc44b1921d8f81a54bc<br>
calculate SSIM for each Row after deblock, sao.<br>
<br>
diff -r 92641f3d3195 -r ed4f57163274 source/Lib/TLibEncoder/TEncTop.cpp<br>
--- a/source/Lib/TLibEncoder/TEncTop.cpp Fri Oct 04 16:46:15 2013 +0530<br>
+++ b/source/Lib/TLibEncoder/TEncTop.cpp Fri Oct 04 16:50:04 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,11 @@<br>
{<br>
m_analyzeB.addResult(psnrY, psnrU, psnrV, (double)bits);<br>
}<br>
-<br>
+ if (param.bEnableSsim)<br>
+ {<br>
+ ssim += pic->getSlice()->m_ssim / pic->getSlice()->m_ssimCnt;<br></blockquote><div><br></div><div>is m_ssimCnt always non-zero?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ m_globalSsim += ssim;<br>
+ }<br>
if (param.logLevel >= X265_LOG_DEBUG)<br>
{<br>
char c = (slice->isIntra() ? 'I' : slice->isInterP() ? 'P' : 'B');<br>
diff -r 92641f3d3195 -r ed4f57163274 source/encoder/frameencoder.cpp<br>
--- a/source/encoder/frameencoder.cpp Fri Oct 04 16:46:15 2013 +0530<br>
+++ b/source/encoder/frameencoder.cpp Fri Oct 04 16:50:04 2013 +0530<br>
@@ -111,6 +111,9 @@<br>
m_rows[i].create(top);<br>
}<br>
<br>
+ if (m_cfg->param.bEnableSsim)<br>
+ CHECKED_MALLOC(tempBuf, int, m_cfg->param.bEnableSsim * 8 * (m_cfg->param.sourceWidth / 4 + 3));<br>
+<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,10 @@<br>
assert(0);<br>
}<br>
start();<br>
+ return;<br>
+fail:<br>
+ X265_FREE(tempBuf);<br>
+ tempBuf = 0;<br></blockquote><div><br></div><div>this looks quite backwards, you only free tempBuf on malloc failure? the buffer doesn't appear to be used?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
}<br>
<br>
int FrameEncoder::getStreamHeaders(NALUnitEBSP **nalunits)<br>
@@ -540,6 +547,32 @@<br>
slice->setSaoEnabledFlag((saoParam->bSaoFlag[0] == 1) ? true : false);<br>
}<br>
<br>
+ /*Compute SSIM if enabled*/<br>
+ if (m_cfg->param.bEnableSsim)<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 +=<br>
+ calculateSSIM(rec + 2 + minPixY * stride1, stride1, org + 2 + minPixY * stride2, stride2,<br>
+ m_cfg->param.sourceWidth - 2, maxPixY - minPixY, tempBuf, &ssim_cnt);<br>
+ slice->m_ssimCnt += ssim_cnt;<br>
+ }<br>
+ }<br>
+<br>
entropyCoder->setBitstream(NULL);<br>
<br>
// Reconstruction slice<br>
@@ -687,6 +720,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>
+<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>
+ primitives.ssim_4x4x2_core_int(&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_end4_int(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 92641f3d3195 -r ed4f57163274 source/encoder/frameencoder.h<br>
--- a/source/encoder/frameencoder.h Fri Oct 04 16:46:15 2013 +0530<br>
+++ b/source/encoder/frameencoder.h Fri Oct 04 16:50:04 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>
+ 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,6 +188,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>