[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