[x265] [PATCH] PSNR Row wise calculation
Steve Borho
steve at borho.org
Tue Oct 15 09:57:06 CEST 2013
On Tue, Oct 15, 2013 at 1:56 AM, <santhoshini at multicorewareinc.com> wrote:
> # HG changeset patch
> # User Santhoshini Sekar <santhoshini at multicorewareinc.com>
> # Date 1381817138 -19800
> # Tue Oct 15 11:35:38 2013 +0530
> # Node ID 957578be76da25eeab8fb0cf5eaf2a5d0471dd24
> # Parent 8ae52f2b159c8378e981e369aa15c4c36db48f7c
> PSNR Row wise calculation
>
> diff -r 8ae52f2b159c -r 957578be76da source/encoder/encoder.cpp
> --- a/source/encoder/encoder.cpp Thu Oct 10 01:15:11 2013 -0500
> +++ b/source/encoder/encoder.cpp Tue Oct 15 11:35:38 2013 +0530
> @@ -362,109 +362,6 @@
> // (we do not yet have a switch to disable PSNR reporting)
> // 2 - it would be better to accumulate SSD of each CTU at the end of
> processCTU() while it is cache-hot
> // in fact, we almost certainly are already measuring the CTU
> distortion and not accumulating it
> -static UInt64 computeSSD(Pel *fenc, Pel *rec, int stride, int width, int
> height)
> -{
> - UInt64 ssd = 0;
> -
> - if ((width | height) & 3)
> - {
> - /* Slow Path */
> - for (int y = 0; y < height; y++)
> - {
> - for (int x = 0; x < width; x++)
> - {
> - int diff = (int)(fenc[x] - rec[x]);
> - ssd += diff * diff;
> - }
> -
> - fenc += stride;
> - rec += stride;
> - }
> -
> - return ssd;
> - }
> -
> - int y = 0;
> - /* Consume Y in chunks of 64 */
> - for (; y + 64 <= height; y += 64)
> - {
> - int x = 0;
> -
> - if (!(stride & 31))
> - for (; x + 64 <= width; x += 64)
> - {
> - ssd += primitives.sse_pp[PARTITION_64x64](fenc + x,
> stride, rec + x, stride);
> - }
> -
> - if (!(stride & 15))
> - for (; x + 16 <= width; x += 16)
> - {
> - ssd += primitives.sse_pp[PARTITION_16x64](fenc + x,
> stride, rec + x, stride);
> - }
> -
> - for (; x + 4 <= width; x += 4)
> - {
> - ssd += primitives.sse_pp[PARTITION_4x64](fenc + x, stride,
> rec + x, stride);
> - }
> -
> - fenc += stride * 64;
> - rec += stride * 64;
> - }
> -
> - /* Consume Y in chunks of 16 */
> - for (; y + 16 <= height; y += 16)
> - {
> - int x = 0;
> -
> - if (!(stride & 31))
> - for (; x + 64 <= width; x += 64)
> - {
> - ssd += primitives.sse_pp[PARTITION_64x16](fenc + x,
> stride, rec + x, stride);
> - }
> -
> - if (!(stride & 15))
> - for (; x + 16 <= width; x += 16)
> - {
> - ssd += primitives.sse_pp[PARTITION_16x16](fenc + x,
> stride, rec + x, stride);
> - }
> -
> - for (; x + 4 <= width; x += 4)
> - {
> - ssd += primitives.sse_pp[PARTITION_4x16](fenc + x, stride,
> rec + x, stride);
> - }
> -
> - fenc += stride * 16;
> - rec += stride * 16;
> - }
> -
> - /* Consume Y in chunks of 4 */
> - for (; y + 4 <= height; y += 4)
> - {
> - int x = 0;
> -
> - if (!(stride & 31))
> - for (; x + 64 <= width; x += 64)
> - {
> - ssd += primitives.sse_pp[PARTITION_64x4](fenc + x,
> stride, rec + x, stride);
> - }
> -
> - if (!(stride & 15))
> - for (; x + 16 <= width; x += 16)
> - {
> - ssd += primitives.sse_pp[PARTITION_16x4](fenc + x,
> stride, rec + x, stride);
> - }
> -
> - for (; x + 4 <= width; x += 4)
> - {
> - ssd += primitives.sse_pp[PARTITION_4x4](fenc + x, stride, rec
> + x, stride);
> - }
> -
> - fenc += stride * 4;
> - rec += stride * 4;
> - }
> -
> - return ssd;
> -}
>
> /**
> * Produce an ascii(hex) representation of picture digest.
> @@ -496,27 +393,17 @@
> uint64_t Encoder::calculateHashAndPSNR(TComPic* pic, NALUnitEBSP
> **nalunits)
> {
> TComPicYuv* recon = pic->getPicYuvRec();
> - TComPicYuv* orig = pic->getPicYuvOrg();
>
> - //===== calculate PSNR =====
> - int stride = recon->getStride();
> int width = recon->getWidth() - getPad(0);
> int height = recon->getHeight() - getPad(1);
> int size = width * height;
>
> - UInt64 ssdY = computeSSD(orig->getLumaAddr(), recon->getLumaAddr(),
> stride, width, height);
> -
> - height >>= 1;
> - width >>= 1;
> - stride = recon->getCStride();
> -
> - UInt64 ssdU = computeSSD(orig->getCbAddr(), recon->getCbAddr(),
> stride, width, height);
> - UInt64 ssdV = computeSSD(orig->getCrAddr(), recon->getCrAddr(),
> stride, width, height);
> -
> int maxvalY = 255 << (X265_DEPTH - 8);
> int maxvalC = 255 << (X265_DEPTH - 8);
> double refValueY = (double)maxvalY * maxvalY * size;
> double refValueC = (double)maxvalC * maxvalC * size / 4.0;
> + UInt64 ssdY,ssdU,ssdV;
>
white-space
+ m_frameEncoder->reportStatistics(ssdY, ssdU, ssdV);
>
the problem is here, m_frameEncoder is pointing to the *next" frame encoder
by this point, not the one which encoded this picture.
I recommend moving the YUV SSD accumulators from frameFilter to TComPic and
then right here you can dereference TComPic->m_SSDY, etc. I think this
will simplify a few other things.
> double psnrY = (ssdY ? 10.0 * log10(refValueY / (double)ssdY) :
> 99.99);
> double psnrU = (ssdU ? 10.0 * log10(refValueC / (double)ssdU) :
> 99.99);
> double psnrV = (ssdV ? 10.0 * log10(refValueC / (double)ssdV) :
> 99.99);
> diff -r 8ae52f2b159c -r 957578be76da source/encoder/frameencoder.cpp
> --- a/source/encoder/frameencoder.cpp Thu Oct 10 01:15:11 2013 -0500
> +++ b/source/encoder/frameencoder.cpp Tue Oct 15 11:35:38 2013 +0530
> @@ -1115,3 +1115,10 @@
>
> return NULL;
> }
> +
> +void FrameEncoder::reportStatistics(UInt64 &ssdY, UInt64 &ssdU, UInt64
> &ssdV)
> +{
> + ssdY = m_frameFilter.m_SSDY;
> + ssdU = m_frameFilter.m_SSDU;
> + ssdV = m_frameFilter.m_SSDV;
> +}
> diff -r 8ae52f2b159c -r 957578be76da source/encoder/frameencoder.h
> --- a/source/encoder/frameencoder.h Thu Oct 10 01:15:11 2013 -0500
> +++ b/source/encoder/frameencoder.h Tue Oct 15 11:35:38 2013 +0530
> @@ -113,6 +113,8 @@
> }
> }
>
> + void reportStatistics(UInt64 &ssdY, UInt64 &ssdU, UInt64 &ssdV);
> +
> TEncEntropy* getEntropyCoder(int row) { return
> &this->m_rows[row].m_entropyCoder; }
>
> TEncSbac* getSbacCoder(int row) { return
> &this->m_rows[row].m_sbacCoder; }
> diff -r 8ae52f2b159c -r 957578be76da source/encoder/framefilter.cpp
> --- a/source/encoder/framefilter.cpp Thu Oct 10 01:15:11 2013 -0500
> +++ b/source/encoder/framefilter.cpp Tue Oct 15 11:35:38 2013 +0530
> @@ -36,6 +36,9 @@
> : m_cfg(NULL)
> , m_pic(NULL)
> {
> + m_SSDY = 0;
> + m_SSDU = 0;
> + m_SSDV = 0;
> }
>
> void FrameFilter::destroy()
> @@ -86,6 +89,9 @@
> m_entropyCoder.setEntropyCoder(&m_rdGoOnSbacCoder, pic->getSlice());
> m_entropyCoder.setBitstream(&m_bitCounter);
> m_rdGoOnBinCodersCABAC.m_fracBits = 0;
> + m_SSDY=0;
> + m_SSDU=0;
> + m_SSDV=0;
>
white-space
> if (m_cfg->param.bEnableSAO)
> {
> @@ -264,6 +270,144 @@
> {
> m_pic->m_reconRowWait.trigger();
> }
> +
> + if (m_cfg->param.bEnablePsnr)
> + {
> + calculatePSNR(lineStartCUAddr, row);
> + }
> +}
> +
> +static UInt64 computeSSD(pixel *fenc, pixel *rec, int stride, int width,
> int height)
> +{
> + UInt64 ssd = 0;
> +
> + if ((width | height) & 3)
> + {
> + /* Slow Path */
> + for (int y = 0; y < height; y++)
> + {
> + for (int x = 0; x < width; x++)
> + {
> + int diff = (int)(fenc[x] - rec[x]);
> + ssd += diff * diff;
> + }
> +
> + fenc += stride;
> + rec += stride;
> + }
> +
> + return ssd;
> + }
> +
> + int y = 0;
> + /* Consume Y in chunks of 64 */
> + for (; y + 64 <= height; y += 64)
> + {
> + int x = 0;
> +
> + if (!(stride & 31))
> + for (; x + 64 <= width; x += 64)
> + {
> + ssd += primitives.sse_pp[PARTITION_64x64](fenc + x,
> stride, rec + x, stride);
> + }
> +
> + if (!(stride & 15))
> + for (; x + 16 <= width; x += 16)
> + {
> + ssd += primitives.sse_pp[PARTITION_16x64](fenc + x,
> stride, rec + x, stride);
> + }
> +
> + for (; x + 4 <= width; x += 4)
> + {
> + ssd += primitives.sse_pp[PARTITION_4x64](fenc + x, stride,
> rec + x, stride);
> + }
> +
> + fenc += stride * 64;
> + rec += stride * 64;
> + }
> +
> + /* Consume Y in chunks of 16 */
> + for (; y + 16 <= height; y += 16)
> + {
> + int x = 0;
> +
> + if (!(stride & 31))
> + for (; x + 64 <= width; x += 64)
> + {
> + ssd += primitives.sse_pp[PARTITION_64x16](fenc + x,
> stride, rec + x, stride);
> + }
> +
> + if (!(stride & 15))
> + for (; x + 16 <= width; x += 16)
> + {
> + ssd += primitives.sse_pp[PARTITION_16x16](fenc + x,
> stride, rec + x, stride);
> + }
> +
> + for (; x + 4 <= width; x += 4)
> + {
> + ssd += primitives.sse_pp[PARTITION_4x16](fenc + x, stride,
> rec + x, stride);
> + }
> +
> + fenc += stride * 16;
> + rec += stride * 16;
> + }
> +
> + /* Consume Y in chunks of 4 */
> + for (; y + 4 <= height; y += 4)
> + {
> + int x = 0;
> +
> + if (!(stride & 31))
> + for (; x + 64 <= width; x += 64)
> + {
> + ssd += primitives.sse_pp[PARTITION_64x4](fenc + x,
> stride, rec + x, stride);
> + }
> +
> + if (!(stride & 15))
> + for (; x + 16 <= width; x += 16)
> + {
> + ssd += primitives.sse_pp[PARTITION_16x4](fenc + x,
> stride, rec + x, stride);
> + }
> +
> + for (; x + 4 <= width; x += 4)
> + {
> + ssd += primitives.sse_pp[PARTITION_4x4](fenc + x, stride, rec
> + x, stride);
> + }
> +
> + fenc += stride * 4;
> + rec += stride * 4;
> + }
> +
> + return ssd;
> +}
> +
> +void FrameFilter::calculatePSNR(uint32_t cuAddr, int row)
> +{
> + TComPicYuv* recon = m_pic->getPicYuvRec();
> + TComPicYuv* orig = m_pic->getPicYuvOrg();
> +
> + //===== calculate PSNR =====
> + int stride = recon->getStride();
> +
> + int width = recon->getWidth() - m_cfg->getPad(0);
> + int height;
> + if (row == m_numRows - 1)
> + height = ((recon->getHeight() % g_maxCUHeight) ?
> (recon->getHeight() % g_maxCUHeight) : g_maxCUHeight);
> + else
> + height = g_maxCUHeight;
> +
> + UInt64 ssdY = computeSSD(orig->getLumaAddr(cuAddr),
> recon->getLumaAddr(cuAddr), stride, width, height);
> +
> + height >>= 1;
> + width >>= 1;
> + stride = recon->getCStride();
> +
> + UInt64 ssdU = computeSSD(orig->getCbAddr(cuAddr),
> recon->getCbAddr(cuAddr), stride, width, height);
> + UInt64 ssdV = computeSSD(orig->getCrAddr(cuAddr),
> recon->getCrAddr(cuAddr), stride, width, height);
> +
> + m_SSDY += ssdY;
> + m_SSDU += ssdU;
> + m_SSDV += ssdV;
> }
>
> void FrameFilter::processSao(int row)
> diff -r 8ae52f2b159c -r 957578be76da source/encoder/framefilter.h
> --- a/source/encoder/framefilter.h Thu Oct 10 01:15:11 2013 -0500
> +++ b/source/encoder/framefilter.h Tue Oct 15 11:35:38 2013 +0530
> @@ -53,7 +53,7 @@
> void processRow(int row);
> void processRowPost(int row);
> void processSao(int row);
> -
> + void calculatePSNR(uint32_t cu, int row);
> protected:
>
> TEncCfg* m_cfg;
> @@ -72,6 +72,9 @@
> TEncBinCABACCounter m_rdGoOnBinCodersCABAC;
> TComBitCounter m_bitCounter;
> TEncSbac* m_rdGoOnSbacCoderRow0; // for bitstream
> exact only, depends on HM's bug
> + UInt64 m_SSDY;
> + UInt64 m_SSDU;
> + UInt64 m_SSDV;
> };
> }
>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
--
Steve Borho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20131015/4782ed85/attachment-0001.html>
More information about the x265-devel
mailing list