[x265] [PATCH] collect global stats of psnr and ssim
Steve Borho
steve at borho.org
Mon Nov 4 06:45:01 CET 2013
On Sun, Nov 3, 2013 at 9:11 PM, <santhoshini at multicorewareinc.com> wrote:
> # HG changeset patch
> # User Santhoshini Sekar <santhoshini at multicorewareinc.com>
> # Date 1383209712 -19800
> # Thu Oct 31 14:25:12 2013 +0530
> # Node ID 8bed3004d0b92ce257f68569a7d3c7532e141d9e
> # Parent ec6b4d35f11053b06d0e1ea46df798ff89a4c127
> collect global stats of psnr and ssim
>
> diff -r ec6b4d35f110 -r 8bed3004d0b9 source/Lib/TLibCommon/TComPic.cpp
> --- a/source/Lib/TLibCommon/TComPic.cpp Thu Oct 31 00:09:49 2013 -0500
> +++ b/source/Lib/TLibCommon/TComPic.cpp Thu Oct 31 14:25:12 2013 +0530
> @@ -65,6 +65,8 @@
> m_SSDY = 0;
> m_SSDU = 0;
> m_SSDV = 0;
> + m_ssim = 0;
> + m_ssimCnt = 0;
> m_frameTime = 0.0;
> m_elapsedCompressTime = 0.0;
> }
> diff -r ec6b4d35f110 -r 8bed3004d0b9 source/Lib/TLibCommon/TComPic.h
> --- a/source/Lib/TLibCommon/TComPic.h Thu Oct 31 00:09:49 2013 -0500
> +++ b/source/Lib/TLibCommon/TComPic.h Thu Oct 31 14:25:12 2013 +0530
> @@ -93,9 +93,13 @@
> double m_elapsedCompressTime;
> double m_frameTime;
> MD5Context m_state[3];
> - uint32_t m_crc[3];
> - uint32_t m_checksum[3];
> -
> + uint32_t m_crc[3];
> + uint32_t m_checksum[3];
> +
> + /* SSIM values per frame */
> + double m_ssim;
> + int m_ssimCnt;
> +
> TComPic();
> virtual ~TComPic();
>
> diff -r ec6b4d35f110 -r 8bed3004d0b9 source/Lib/TLibCommon/TComSlice.cpp
> --- a/source/Lib/TLibCommon/TComSlice.cpp Thu Oct 31 00:09:49 2013
> -0500
> +++ b/source/Lib/TLibCommon/TComSlice.cpp Thu Oct 31 14:25:12 2013
> +0530
> @@ -120,8 +120,6 @@
> m_cabacInitFlag = false;
> m_numEntryPointOffsets = 0;
> m_enableTMVPFlag = true;
> - m_ssim = 0;
> - m_ssimCnt = 0;
> m_numWPRefs = 0;
> }
>
> diff -r ec6b4d35f110 -r 8bed3004d0b9 source/Lib/TLibCommon/TComSlice.h
> --- a/source/Lib/TLibCommon/TComSlice.h Thu Oct 31 00:09:49 2013 -0500
> +++ b/source/Lib/TLibCommon/TComSlice.h Thu Oct 31 14:25:12 2013 +0530
> @@ -1341,10 +1341,6 @@
> wpScalingParam m_weightPredTable[2][MAX_NUM_REF][3]; //
> [REF_PIC_LIST_0 or REF_PIC_LIST_1][refIdx][0:Y, 1:U, 2:V]
> int m_numWPRefs; // number of
> references for which unidirectional weighted prediction is used
>
> - /* SSIM values per frame */
> - double m_ssim;
> - int m_ssimCnt;
> -
> TComSlice();
> virtual ~TComSlice();
> void initSlice();
>
when a file is deleted you must remove it from its cmake list
> diff -r ec6b4d35f110 -r 8bed3004d0b9 source/Lib/TLibEncoder/TEncAnalyze.h
> --- a/source/Lib/TLibEncoder/TEncAnalyze.h Thu Oct 31 00:09:49 2013
> -0500
> +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
> @@ -1,157 +0,0 @@
> -/* The copyright in this software is being made available under the BSD
> - * License, included below. This software may be subject to other third
> party
> - * and contributor rights, including patent rights, and no such rights are
> - * granted under this license.
> - *
> - * Copyright (c) 2010-2013, ITU/ISO/IEC
> - * All rights reserved.
> - *
> - * Redistribution and use in source and binary forms, with or without
> - * modification, are permitted provided that the following conditions are
> met:
> - *
> - * * Redistributions of source code must retain the above copyright
> notice,
> - * this list of conditions and the following disclaimer.
> - * * Redistributions in binary form must reproduce the above copyright
> notice,
> - * this list of conditions and the following disclaimer in the
> documentation
> - * and/or other materials provided with the distribution.
> - * * Neither the name of the ITU/ISO/IEC nor the names of its
> contributors may
> - * be used to endorse or promote products derived from this software
> without
> - * specific prior written permission.
> - *
> - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> "AS IS"
> - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> THE
> - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> PURPOSE
> - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
> - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> BUSINESS
> - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> - * THE POSSIBILITY OF SUCH DAMAGE.
> - */
> -
> -/** \file TEncAnalyze.h
> - \brief encoder analyzer class (header)
> -*/
> -
> -#ifndef X265_TENCANALYZE_H
> -#define X265_TENCANALYZE_H
> -
> -#include "TLibCommon/CommonDef.h"
> -
> -#include <stdio.h>
> -#include <memory.h>
> -#include <assert.h>
> -
> -namespace x265 {
> -// private namespace
> -
> -/// encoder analyzer class
> -class TEncAnalyze
> -{
> -private:
> -
> - double m_psnrSumY;
> - double m_psnrSumU;
> - double m_psnrSumV;
> - double m_accBits;
> - uint32_t m_numPics;
> -
> -public:
> -
> - TEncAnalyze() { m_psnrSumY = m_psnrSumU = m_psnrSumV = m_accBits =
> m_numPics = 0; }
> -
> - void addResult(double psnrY, double psnrU, double psnrV, double bits)
> - {
> - m_psnrSumY += psnrY;
> - m_psnrSumU += psnrU;
> - m_psnrSumV += psnrV;
> - m_accBits += bits;
> - m_numPics++;
> - }
> -
> - double getPsnrY() { return m_psnrSumY; }
> -
> - double getPsnrU() { return m_psnrSumU; }
> -
> - double getPsnrV() { return m_psnrSumV; }
> -
> - double getBits() { return m_accBits; }
> -
> - uint32_t getNumPic() { return m_numPics; }
> -
> - void clear() { m_psnrSumY = m_psnrSumU = m_psnrSumV = m_accBits =
> m_numPics = 0; }
> -
> - void printOut(char delim, double fps)
> - {
> - double scale = fps / 1000 / (double)m_numPics;
> -
> - if (m_numPics == 0)
> - return;
> -
> - if (delim == 'a')
> - fprintf(stderr, "x265 [info]: global: ");
> - else
> - fprintf(stderr, "x265 [info]: frame %c:%-6d ", delim - 32,
> m_numPics);
> - fprintf(stderr, "kb/s: %-8.2lf PSNR Mean: Y:%.3lf U:%.3lf
> V:%.3lf\n",
> - getBits() * scale,
> - getPsnrY() / (double)getNumPic(),
> - getPsnrU() / (double)getNumPic(),
> - getPsnrV() / (double)getNumPic());
> - }
> -
> - void printSummaryOut(double fps)
> - {
> - FILE* fp = fopen("summaryTotal.txt", "at");
> -
> - if (fp)
> - {
> - double scale = fps / 1000 / (double)m_numPics;
> -
> - fprintf(fp, "%f\t %f\t %f\t %f\n", getBits() * scale,
> - getPsnrY() / (double)getNumPic(),
> - getPsnrU() / (double)getNumPic(),
> - getPsnrV() / (double)getNumPic());
> -
> - fclose(fp);
> - }
> - }
> -
> - void printSummary(char ch, double fps)
> - {
> - FILE* fp = NULL;
> -
> - switch (ch)
> - {
> - case 'I':
> - fp = fopen("summary_I.txt", "at");
> - break;
> - case 'P':
> - fp = fopen("summary_P.txt", "at");
> - break;
> - case 'B':
> - fp = fopen("summary_B.txt", "at");
> - break;
> - default:
> - assert(0);
> - return;
> - }
> -
> - if (fp)
> - {
> - double scale = fps / 1000 / (double)m_numPics;
> -
> - fprintf(fp, "%f\t %f\t %f\t %f\n",
> - getBits() * scale,
> - getPsnrY() / (double)getNumPic(),
> - getPsnrU() / (double)getNumPic(),
> - getPsnrV() / (double)getNumPic());
> -
> - fclose(fp);
> - }
> - }
> -};
> -}
> -
> -#endif // ifndef X265_TENCANALYZE_H
> diff -r ec6b4d35f110 -r 8bed3004d0b9 source/encoder/encoder.cpp
> --- a/source/encoder/encoder.cpp Thu Oct 31 00:09:49 2013 -0500
> +++ b/source/encoder/encoder.cpp Thu Oct 31 14:25:12 2013 +0530
> @@ -57,7 +57,6 @@
> m_frameEncoder = NULL;
> m_rateControl = NULL;
> m_dpb = NULL;
> - m_globalSsim = 0;
> m_nals = NULL;
> m_packetData = NULL;
> m_outputCount = 0;
> @@ -315,20 +314,98 @@
> return ret;
> }
>
> +void EncStats::addPsnr(double psnrY, double psnrU, double psnrV)
> +{
> + m_psnrSumY += psnrY;
> + m_psnrSumU += psnrU;
> + m_psnrSumV += psnrV;
> +}
> +
> +void EncStats::addBits(double bits)
> +{
> + m_accBits += bits;
> + m_numPics++;
> +}
> +
> +void EncStats::addSsim(double ssim)
> +{
> + m_globalSsim += ssim;
> +}
> +
> void Encoder::printSummary()
> {
> double fps = (double)param.frameRate;
>
> if (param.logLevel >= X265_LOG_INFO)
> {
> - m_analyzeI.printOut('i', fps);
> - m_analyzeP.printOut('p', fps);
> - m_analyzeB.printOut('b', fps);
> - m_analyzeAll.printOut('a', fps);
>
this is a gob of code repeated three times. This should be a helper method
> + double scale = fps / 1000 / (double)m_analyzeI.m_numPics;
> +
> + fprintf(stderr, "\n x265 [info]: frame %c:%-6d ", 'i' - 32,
> m_analyzeI.m_numPics);
>
why is there a leading line feed and space? The 'i'-32 is just making a
capital I
> + fprintf(stderr, "kb/s: %-8.2lf", m_analyzeI.m_accBits * scale);
> + if (param.bEnablePsnr)
> + {
> + fprintf(stderr, " PSNR Mean: Y:%.3lf U:%.3lf V:%.3lf",
> + m_analyzeI.m_psnrSumY / (double)m_analyzeI.m_numPics,
> + m_analyzeI.m_psnrSumU / (double)m_analyzeI.m_numPics,
> + m_analyzeI.m_psnrSumV / (double)m_analyzeI.m_numPics);
> + }
> + if (param.bEnableSsim)
> + {
> + fprintf(stderr, " SSIM Mean: %.3lf \n",
> + m_analyzeI.m_globalSsim / (double)m_analyzeI.m_numPics);
> + }
> + scale = fps / 1000 / (double)m_analyzeP.m_numPics;
>
why is there only a trailing line fee if SSIM is enabled?
This should be boiled down to something like:
if (m_analyzeI.m_numPics)
fprintf(stderr, "\x265 [info]: frame I: %s\n", m_analyzeP.statsString());
if (m_analyzeP.m_numPics)
fprintf(stderr, "\x265 [info]: frame P: %s\n", m_analyzeP.statsString());
if (m_analyzeP.m_numPics)
fprintf(stderr, "\x265 [info]: frame B: %s\n", m_analyzeB.statsString());
+
> + fprintf(stderr, "\n x265 [info]: frame %c:%-6d ", 'p' - 32,
> m_analyzeP.m_numPics);
> + fprintf(stderr, "kb/s: %-8.2lf", m_analyzeP.m_accBits * scale);
> + if (param.bEnablePsnr)
> + {
> + fprintf(stderr, " PSNR Mean: Y:%.3lf U:%.3lf V:%.3lf",
> + m_analyzeP.m_psnrSumY / (double)m_analyzeP.m_numPics,
> + m_analyzeP.m_psnrSumU / (double)m_analyzeP.m_numPics,
> + m_analyzeP.m_psnrSumV / (double)m_analyzeP.m_numPics);
> + }
> + if (param.bEnableSsim)
> + {
> + fprintf(stderr, " SSIM Mean: %.3lf \n",
> + m_analyzeP.m_globalSsim / (double)m_analyzeP.m_numPics);
> + }
> + scale = fps / 1000 / (double)m_analyzeB.m_numPics;
> +
> + fprintf(stderr, "\n x265 [info]: frame %c:%-6d ", 'b' - 32,
> m_analyzeB.m_numPics);
> + fprintf(stderr, "kb/s: %-8.2lf", m_analyzeB.m_accBits * scale);
> + if (param.bEnablePsnr)
> + {
> + fprintf(stderr, " PSNR Mean: Y:%.3lf U:%.3lf V:%.3lf",
> + m_analyzeB.m_psnrSumY / (double)m_analyzeB.m_numPics,
> + m_analyzeB.m_psnrSumU / (double)m_analyzeB.m_numPics,
> + m_analyzeB.m_psnrSumV / (double)m_analyzeB.m_numPics);
> + }
> + if (param.bEnableSsim)
> + {
> + fprintf(stderr, " SSIM Mean: %.3lf \n",
> + m_analyzeB.m_globalSsim / (double)m_analyzeB.m_numPics);
> + }
> + scale = fps / 1000 / (double)m_analyzeAll.m_numPics;
> +
> + fprintf(stderr, "\n x265 [info]: global: ");
> + fprintf(stderr, "kb/s: %-8.2lf", m_analyzeAll.m_accBits * scale);
> + if (param.bEnablePsnr)
> + {
> + fprintf(stderr, " PSNR Mean: Y:%.3lf U:%.3lf V:%.3lf",
> + m_analyzeAll.m_psnrSumY /
> (double)m_analyzeAll.m_numPics,
> + m_analyzeAll.m_psnrSumU /
> (double)m_analyzeAll.m_numPics,
> + m_analyzeAll.m_psnrSumV /
> (double)m_analyzeAll.m_numPics);
> + }
> + if (param.bEnableSsim)
> + {
> + fprintf(stderr, " SSIM Mean: %.3lf \n",
> + m_analyzeAll.m_globalSsim /
> (double)m_analyzeAll.m_numPics);
> + }
> }
> if (param.bEnableWeightedPred)
> {
> - int numPFrames = m_analyzeP.getNumPic();
> + int numPFrames = m_analyzeP.m_numPics;
> x265_log(¶m, X265_LOG_INFO, "%d of %d (%.2f%%) P frames
> weighted\n",
> m_numWPFrames, numPFrames, (float) 100.0 * m_numWPFrames
> / numPFrames);
> }
> @@ -336,16 +413,16 @@
>
> void Encoder::fetchStats(x265_stats *stats)
> {
> - stats->globalPsnrY = m_analyzeAll.getPsnrY();
> - stats->globalPsnrU = m_analyzeAll.getPsnrU();
> - stats->globalPsnrV = m_analyzeAll.getPsnrV();
> - stats->encodedPictureCount = m_analyzeAll.getNumPic();
> + stats->globalPsnrY = m_analyzeAll.m_psnrSumY;
> + stats->globalPsnrU = m_analyzeAll.m_psnrSumU;
> + stats->globalPsnrV = m_analyzeAll.m_psnrSumV;
> + stats->encodedPictureCount = m_analyzeAll.m_numPics;
> stats->totalWPFrames = m_numWPFrames;
> - stats->accBits = m_analyzeAll.getBits();
> + stats->accBits = m_analyzeAll.m_accBits;
> stats->elapsedEncodeTime = (double)(x265_mdate() - m_encodeStartTime)
> / 1000000;
> if (stats->encodedPictureCount > 0)
> {
> - stats->globalSsim = m_globalSsim / stats->encodedPictureCount;
> + stats->globalSsim = m_analyzeAll.m_globalSsim /
> stats->encodedPictureCount;
> stats->globalPsnr = (stats->globalPsnrY * 6 + stats->globalPsnrU
> + stats->globalPsnrV) / (8 * stats->encodedPictureCount);
> stats->elapsedVideoTime = (double)stats->encodedPictureCount /
> param.frameRate;
> stats->bitrate = (0.001f * stats->accBits) /
> stats->elapsedVideoTime;
> @@ -527,27 +604,60 @@
>
> uint32_t bits = numRBSPBytes * 8;
>
> - //===== add PSNR =====
> - m_analyzeAll.addResult(psnrY, psnrU, psnrV, (double)bits);
> - TComSlice* slice = pic->getSlice();
> - if (slice->isIntra())
> - {
> - m_analyzeI.addResult(psnrY, psnrU, psnrV, (double)bits);
> - }
> - if (slice->isInterP())
> - {
> - m_analyzeP.addResult(psnrY, psnrU, psnrV, (double)bits);
> - }
> - if (slice->isInterB())
> - {
> - m_analyzeB.addResult(psnrY, psnrU, psnrV, (double)bits);
> - }
> - double ssim = 0.0;
> - if (param.bEnableSsim && pic->getSlice()->m_ssimCnt > 0)
> - {
> - ssim = pic->getSlice()->m_ssim / pic->getSlice()->m_ssimCnt;
> - m_globalSsim += ssim;
> - }
> + TComSlice* slice = pic->getSlice();
> +
> + //===== add Bits and number of pics =====
>
why is Bits capitalized?
> + m_analyzeAll.addBits((double)bits);
> + if (slice->isIntra())
> + {
> + m_analyzeI.addBits((double)bits);
this logic should be combined so that within this if it does:
if (param.bEnablePsnr) m_analyzeI.addPsnr(psnrY, psnrU, psnrV);
if (param.bEnableSsim) m_analyzeI.addSsim(ssim);
> + }
> + if (slice->isInterP())
>
else if
> + {
> + m_analyzeP.addBits((double)bits);
> + }
> + if (slice->isInterB())
>
else if
> + {
> + m_analyzeB.addBits((double)bits);
> + }
> + //===== add PSNR =====
> + if (param.bEnablePsnr)
> + {
> + m_analyzeAll.addPsnr(psnrY, psnrU, psnrV);
> +
> + if (slice->isIntra())
> + {
> + m_analyzeI.addPsnr(psnrY, psnrU, psnrV);
> + }
> + if (slice->isInterP())
> + {
> + m_analyzeP.addPsnr(psnrY, psnrU, psnrV);
> + }
> + if (slice->isInterB())
> + {
> + m_analyzeB.addPsnr(psnrY, psnrU, psnrV);
> + }
> + }
> + //===== add SSIM =====
> + double ssim = 0.0;
> + if (param.bEnableSsim && pic->m_ssimCnt > 0)
> + {
> + ssim = pic->m_ssim / pic->m_ssimCnt;
> + m_analyzeAll.addSsim(ssim);
> +
> + if (slice->isIntra())
> + {
> + m_analyzeI.addSsim(ssim);
> + }
> + if (slice->isInterP())
> + {
> + m_analyzeP.addSsim(ssim);
> + }
> + if (slice->isInterB())
> + {
> + m_analyzeB.addSsim(ssim);
> + }
> + }
>
> // if debug log level is enabled, per frame logging is performed
> if (param.logLevel >= X265_LOG_DEBUG)
> diff -r ec6b4d35f110 -r 8bed3004d0b9 source/encoder/encoder.h
> --- a/source/encoder/encoder.h Thu Oct 31 00:09:49 2013 -0500
> +++ b/source/encoder/encoder.h Thu Oct 31 14:25:12 2013 +0530
> @@ -27,12 +27,33 @@
> #include "x265.h"
>
> #include "TLibEncoder/TEncCfg.h"
> -#include "TLibEncoder/TEncAnalyze.h"
>
> #include "piclist.h"
>
> struct x265_encoder {};
>
> +struct EncStats
> +{
> + double m_psnrSumY;
> + double m_psnrSumU;
> + double m_psnrSumV;
> + double m_accBits;
> + double m_globalSsim;
> + uint32_t m_numPics;
> +
> + EncStats()
> + {
> + m_psnrSumY = m_psnrSumU = m_psnrSumV = m_accBits = m_numPics = 0;
> + m_globalSsim = 0;
> + }
> +
> + void addPsnr(double psnrY, double psnrU, double psnrV);
> +
> + void addBits(double bits);
> +
> + void addSsim(double ssim);
> +};
> +
> namespace x265 {
> // private namespace
>
> @@ -61,11 +82,10 @@
> int m_curEncoder;
>
> /* Collect statistics globally */
> - TEncAnalyze m_analyzeAll;
> - TEncAnalyze m_analyzeI;
> - TEncAnalyze m_analyzeP;
> - TEncAnalyze m_analyzeB;
> - double m_globalSsim;
> + EncStats m_analyzeAll;
> + EncStats m_analyzeI;
> + EncStats m_analyzeP;
> + EncStats m_analyzeB;
> FILE* m_csvfpt;
> int64_t m_encodeStartTime;
>
> diff -r ec6b4d35f110 -r 8bed3004d0b9 source/encoder/framefilter.cpp
> --- a/source/encoder/framefilter.cpp Thu Oct 31 00:09:49 2013 -0500
> +++ b/source/encoder/framefilter.cpp Thu Oct 31 14:25:12 2013 +0530
> @@ -317,9 +317,9 @@
> /* SSIM is done for each row in blocks of 4x4 . The First blocks
> are offset by 2 pixels to the right
> * to avoid alignment of ssim blocks with DCT blocks. */
> minPixY += bStart ? 2 : -6;
> - m_pic->getSlice()->m_ssim += calculateSSIM(rec + 2 + minPixY *
> stride1, stride1, org + 2 + minPixY * stride2, stride2,
> + m_pic->m_ssim += calculateSSIM(rec + 2 + minPixY * stride1,
> stride1, org + 2 + minPixY * stride2, stride2,
>
> m_cfg->param.sourceWidth - 2, maxPixY - minPixY, m_ssimBuf, &ssim_cnt);
> - m_pic->getSlice()->m_ssimCnt += ssim_cnt;
> + m_pic->m_ssimCnt += ssim_cnt;
> }
> if (m_cfg->param.decodedPictureHashSEI == 1)
> {
> _______________________________________________
> 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/20131103/439d0f67/attachment-0001.html>
More information about the x265-devel
mailing list