[x265] [PATCH] stats: add average luma and chroma distortion statistics per frame

Divya Manivannan divya at multicorewareinc.com
Fri Jun 5 15:04:36 CEST 2015


# HG changeset patch
# User Divya Manivannan <divya at multicorewareinc.com>
# Date 1433509334 -19800
#      Fri Jun 05 18:32:14 2015 +0530
# Node ID e9449ac3d40f0605e0a27db7d19f8e70b3df8e28
# Parent  69ddf6001b990130e6b03d1126c1b7c4103af8db
stats: add average luma and chroma distortion statistics per frame

diff -r 69ddf6001b99 -r e9449ac3d40f source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Fri Jun 05 18:29:59 2015 +0530
+++ b/source/encoder/encoder.cpp	Fri Jun 05 18:32:14 2015 +0530
@@ -1088,7 +1088,9 @@
 {
     if (frameStatsSize >= sizeof(frameStats))
     {
-        frameStats->percentIntraNxN = curEncoder->m_frameStats.percentIntraNxN;
+        frameStats->percentIntraNxN     = curEncoder->m_frameStats.percentIntraNxN;
+        frameStats->avgChromaDistortion = curEncoder->m_frameStats.avgChromaDistortion;
+        frameStats->avgLumaDistortion   = curEncoder->m_frameStats.avgLumaDistortion;
         for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
         {
             frameStats->percentInterCu[depth] = curEncoder->m_frameStats.percentInterCu[depth];
diff -r 69ddf6001b99 -r e9449ac3d40f source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp	Fri Jun 05 18:29:59 2015 +0530
+++ b/source/encoder/frameencoder.cpp	Fri Jun 05 18:32:14 2015 +0530
@@ -559,14 +559,17 @@
         // accumulate intra,inter,skip cu count per frame for 2 pass
         for (uint32_t i = 0; i < m_numRows; i++)
         {
-            m_frameStats.mvBits      += m_rows[i].rowStats.mvBits;
-            m_frameStats.coeffBits   += m_rows[i].rowStats.coeffBits;
-            m_frameStats.miscBits    += m_rows[i].rowStats.miscBits;
-            m_frameStats.cntIntraNxN += m_rows[i].rowStats.cntIntraNxN;
-            m_frameStats.totalCu     += m_rows[i].rowStats.totalCu;
-            totalI                   += m_rows[i].rowStats.intra8x8Cnt;
-            totalP                   += m_rows[i].rowStats.inter8x8Cnt;
-            totalSkip                += m_rows[i].rowStats.skip8x8Cnt;
+            m_frameStats.mvBits           += m_rows[i].rowStats.mvBits;
+            m_frameStats.coeffBits        += m_rows[i].rowStats.coeffBits;
+            m_frameStats.miscBits         += m_rows[i].rowStats.miscBits;
+            m_frameStats.cntIntraNxN      += m_rows[i].rowStats.cntIntraNxN;
+            m_frameStats.totalCu          += m_rows[i].rowStats.totalCu;
+            m_frameStats.totalCtu         += m_rows[i].rowStats.totalCtu;
+            m_frameStats.lumaDistortion   += m_rows[i].rowStats.lumaDistortion;
+            m_frameStats.chromaDistortion += m_rows[i].rowStats.chromaDistortion;
+            totalI                        += m_rows[i].rowStats.intra8x8Cnt;
+            totalP                        += m_rows[i].rowStats.inter8x8Cnt;
+            totalSkip                     += m_rows[i].rowStats.skip8x8Cnt;
 
             for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
             {
@@ -576,11 +579,13 @@
                 m_frameStats.cntTotalCu[depth] += m_rows[i].rowStats.cntTotalCu[depth];
             }
         }
-        int totalCuCount             = totalI + totalP + totalSkip;
-        m_frameStats.percentIntra    = (double)totalI / totalCuCount;
-        m_frameStats.percentInter    = (double)totalP / totalCuCount;
-        m_frameStats.percentSkip     = (double)totalSkip / totalCuCount;
-        m_frameStats.percentIntraNxN = (double)(m_frameStats.cntIntraNxN * 100) / m_frameStats.totalCu;
+        int totalCuCount                 = totalI + totalP + totalSkip;
+        m_frameStats.percentIntra        = (double)totalI / totalCuCount;
+        m_frameStats.percentInter        = (double)totalP / totalCuCount;
+        m_frameStats.percentSkip         = (double)totalSkip / totalCuCount;
+        m_frameStats.percentIntraNxN     = (double)(m_frameStats.cntIntraNxN * 100) / m_frameStats.totalCu;
+        m_frameStats.avgLumaDistortion   = (double)(m_frameStats.lumaDistortion / m_frameStats.totalCtu);
+        m_frameStats.avgChromaDistortion = (double)(m_frameStats.chromaDistortion / m_frameStats.totalCtu);
 
         for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
         {
@@ -931,6 +936,9 @@
             curRow.rowStats.miscBits    += best.totalBits - (best.mvBits + best.coeffBits);
             curRow.rowStats.cntIntraNxN += log.cntIntraNxN;
             curRow.rowStats.totalCu     += log.totalCu;
+            curRow.rowStats.totalCtu++;
+            curRow.rowStats.lumaDistortion   += best.lumaDistortion;
+            curRow.rowStats.chromaDistortion += best.chromaDistortion;
 
             for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
             {
diff -r 69ddf6001b99 -r e9449ac3d40f source/encoder/frameencoder.h
--- a/source/encoder/frameencoder.h	Fri Jun 05 18:29:59 2015 +0530
+++ b/source/encoder/frameencoder.h	Fri Jun 05 18:32:14 2015 +0530
@@ -76,12 +76,17 @@
     uint64_t    totalCu;
     uint64_t    cuInterDistribution[4][INTER_MODES];
     uint64_t    cuIntraDistribution[4][INTRA_MODES];
+    uint64_t    totalCtu;
+    uint64_t    lumaDistortion;
+    uint64_t    chromaDistortion;
 
     double      percentIntraCu[4];
     double      percentInterCu[4];
     double      percentSkipCu[4];
     double      percentIntraNxN;
     double      percentTotalCu[4];
+    double      avgLumaDistortion;
+    double      avgChromaDistortion;
 };
 
 /* manages the state of encoding one row of CTU blocks.  When
diff -r 69ddf6001b99 -r e9449ac3d40f source/encoder/search.cpp
--- a/source/encoder/search.cpp	Fri Jun 05 18:29:59 2015 +0530
+++ b/source/encoder/search.cpp	Fri Jun 05 18:32:14 2015 +0530
@@ -1162,8 +1162,9 @@
     cu.getIntraTUQtDepthRange(tuDepthRange, 0);
 
     intraMode.initCosts();
-    intraMode.distortion += estIntraPredQT(intraMode, cuGeom, tuDepthRange, sharedModes);
-    intraMode.distortion += estIntraPredChromaQT(intraMode, cuGeom, sharedChromaModes);
+    intraMode.lumaDistortion += estIntraPredQT(intraMode, cuGeom, tuDepthRange, sharedModes);
+    intraMode.chromaDistortion += estIntraPredChromaQT(intraMode, cuGeom, sharedChromaModes);
+    intraMode.distortion += intraMode.lumaDistortion + intraMode.chromaDistortion;
 
     m_entropyCoder.resetBits();
     if (m_slice->m_pps->bTransquantBypassEnabled)
@@ -1378,8 +1379,9 @@
     codeIntraLumaQT(intraMode, cuGeom, 0, 0, false, icosts, tuDepthRange);
     extractIntraResultQT(cu, *reconYuv, 0, 0);
 
-    intraMode.distortion = icosts.distortion;
-    intraMode.distortion += estIntraPredChromaQT(intraMode, cuGeom, NULL);
+    intraMode.lumaDistortion = icosts.distortion;
+    intraMode.chromaDistortion = estIntraPredChromaQT(intraMode, cuGeom, NULL);
+    intraMode.distortion = intraMode.lumaDistortion + intraMode.chromaDistortion;
 
     m_entropyCoder.resetBits();
     if (m_slice->m_pps->bTransquantBypassEnabled)
@@ -2460,10 +2462,11 @@
 
     // Luma
     int part = partitionFromLog2Size(cu.m_log2CUSize[0]);
-    interMode.distortion = primitives.cu[part].sse_pp(fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size);
+    interMode.lumaDistortion = primitives.cu[part].sse_pp(fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size);
     // Chroma
-    interMode.distortion += m_rdCost.scaleChromaDist(1, primitives.chroma[m_csp].cu[part].sse_pp(fencYuv->m_buf[1], fencYuv->m_csize, reconYuv->m_buf[1], reconYuv->m_csize));
-    interMode.distortion += m_rdCost.scaleChromaDist(2, primitives.chroma[m_csp].cu[part].sse_pp(fencYuv->m_buf[2], fencYuv->m_csize, reconYuv->m_buf[2], reconYuv->m_csize));
+    interMode.chromaDistortion = m_rdCost.scaleChromaDist(1, primitives.chroma[m_csp].cu[part].sse_pp(fencYuv->m_buf[1], fencYuv->m_csize, reconYuv->m_buf[1], reconYuv->m_csize));
+    interMode.chromaDistortion += m_rdCost.scaleChromaDist(2, primitives.chroma[m_csp].cu[part].sse_pp(fencYuv->m_buf[2], fencYuv->m_csize, reconYuv->m_buf[2], reconYuv->m_csize));
+    interMode.distortion = interMode.lumaDistortion + interMode.chromaDistortion;
 
     m_entropyCoder.load(m_rqt[depth].cur);
     m_entropyCoder.resetBits();
@@ -2584,14 +2587,16 @@
         reconYuv->copyFromYuv(*predYuv);
 
     // update with clipped distortion and cost (qp estimation loop uses unclipped values)
-    uint32_t bestDist = primitives.cu[sizeIdx].sse_pp(fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size);
-    bestDist += m_rdCost.scaleChromaDist(1, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[1], fencYuv->m_csize, reconYuv->m_buf[1], reconYuv->m_csize));
-    bestDist += m_rdCost.scaleChromaDist(2, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[2], fencYuv->m_csize, reconYuv->m_buf[2], reconYuv->m_csize));
+    uint32_t bestLumaDist = primitives.cu[sizeIdx].sse_pp(fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size);
+    uint32_t bestChromaDist = m_rdCost.scaleChromaDist(1, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[1], fencYuv->m_csize, reconYuv->m_buf[1], reconYuv->m_csize));
+    bestChromaDist += m_rdCost.scaleChromaDist(2, primitives.chroma[m_csp].cu[sizeIdx].sse_pp(fencYuv->m_buf[2], fencYuv->m_csize, reconYuv->m_buf[2], reconYuv->m_csize));
     if (m_rdCost.m_psyRd)
         interMode.psyEnergy = m_rdCost.psyCost(sizeIdx, fencYuv->m_buf[0], fencYuv->m_size, reconYuv->m_buf[0], reconYuv->m_size);
 
     interMode.totalBits = bits;
-    interMode.distortion = bestDist;
+    interMode.lumaDistortion = bestLumaDist;
+    interMode.chromaDistortion = bestChromaDist;
+    interMode.distortion = bestLumaDist + bestChromaDist;
     interMode.coeffBits = coeffBits;
     interMode.mvBits = bits - coeffBits;
     updateModeCost(interMode);
diff -r 69ddf6001b99 -r e9449ac3d40f source/encoder/search.h
--- a/source/encoder/search.h	Fri Jun 05 18:29:59 2015 +0530
+++ b/source/encoder/search.h	Fri Jun 05 18:32:14 2015 +0530
@@ -109,6 +109,8 @@
     uint64_t   sa8dCost;   // sum of partition sa8d distortion costs   (sa8d(fenc, pred) + lambda * bits)
     uint32_t   sa8dBits;   // signal bits used in sa8dCost calculation
     uint32_t   psyEnergy;  // sum of partition psycho-visual energy difference
+    uint32_t   lumaDistortion;
+    uint32_t   chromaDistortion;
     uint32_t   distortion; // sum of partition SSE distortion
     uint32_t   totalBits;  // sum of partition bits (mv + coeff)
     uint32_t   mvBits;     // Mv bits + Ref + block type (or intra mode)
@@ -120,6 +122,8 @@
         sa8dCost = 0;
         sa8dBits = 0;
         psyEnergy = 0;
+        lumaDistortion = 0;
+        chromaDistortion = 0;
         distortion = 0;
         totalBits = 0;
         mvBits = 0;
@@ -133,6 +137,8 @@
         sa8dCost = UINT64_MAX / 2;
         sa8dBits = MAX_UINT / 2;
         psyEnergy = MAX_UINT / 2;
+        lumaDistortion = MAX_UINT / 2;
+        chromaDistortion = MAX_UINT / 2;
         distortion = MAX_UINT / 2;
         totalBits = MAX_UINT / 2;
         mvBits = MAX_UINT / 2;
@@ -145,6 +151,8 @@
                  sa8dCost >= UINT64_MAX / 2 ||
                  sa8dBits >= MAX_UINT / 2 ||
                  psyEnergy >= MAX_UINT / 2 ||
+                 lumaDistortion >= MAX_UINT / 2 ||
+                 chromaDistortion >= MAX_UINT / 2 ||
                  distortion >= MAX_UINT / 2 ||
                  totalBits >= MAX_UINT / 2 ||
                  mvBits >= MAX_UINT / 2 ||
@@ -159,6 +167,8 @@
         sa8dCost += subMode.sa8dCost;
         sa8dBits += subMode.sa8dBits;
         psyEnergy += subMode.psyEnergy;
+        lumaDistortion += subMode.lumaDistortion;
+        chromaDistortion += subMode.chromaDistortion;
         distortion += subMode.distortion;
         totalBits += subMode.totalBits;
         mvBits += subMode.mvBits;
diff -r 69ddf6001b99 -r e9449ac3d40f source/x265.h
--- a/source/x265.h	Fri Jun 05 18:29:59 2015 +0530
+++ b/source/x265.h	Fri Jun 05 18:32:14 2015 +0530
@@ -108,6 +108,8 @@
     double      percentSkipCu[4];
     double      percentIntraNxN;
     double      percentTotalCu[4];
+    double      avgLumaDistortion;
+    double      avgChromaDistortion;
 } x265_frame_stats;
 
 /* Used to pass pictures into the encoder, and to get picture data back out of


More information about the x265-devel mailing list