[x265] [PATCH] stats: collect count of each CU partition mode per frame

Divya Manivannan divya at multicorewareinc.com
Fri Jun 5 14:59:15 CEST 2015


# HG changeset patch
# User Divya Manivannan <divya at multicorewareinc.com>
# Date 1433508913 -19800
#      Fri Jun 05 18:25:13 2015 +0530
# Node ID 98e0e6e63c8a7884379e62c051054fc9e197fbf0
# Parent  e566df2db7b679f306e805ce7da01e388eb86852
stats: collect count of each CU partition mode per frame

diff -r e566df2db7b6 -r 98e0e6e63c8a source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp	Fri Jun 05 18:23:45 2015 +0530
+++ b/source/encoder/frameencoder.cpp	Fri Jun 05 18:25:13 2015 +0530
@@ -552,24 +552,43 @@
         }
     }
 
-    if (m_param->rc.bStatWrite)
+    if (m_param->rc.bStatWrite || m_param->logLevel >= X265_LOG_DEBUG)
     {
         int totalI = 0, totalP = 0, totalSkip = 0;
 
         // 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;
-            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;
+            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++)
+            {
+                m_frameStats.cntInter[depth]   += m_rows[i].rowStats.cntInter[depth];
+                m_frameStats.cntIntra[depth]   += m_rows[i].rowStats.cntIntra[depth];
+                m_frameStats.cntSkipCu[depth]  += m_rows[i].rowStats.cntSkipCu[depth];
+                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;
+        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;
+
+        for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+        {
+            m_frameStats.percentIntraCu[depth] = (double)(m_frameStats.cntIntra[depth] * 100) / m_frameStats.totalCu;
+            m_frameStats.percentInterCu[depth] = (double)(m_frameStats.cntInter[depth] * 100) / m_frameStats.totalCu;
+            m_frameStats.percentSkipCu[depth]  = (double)(m_frameStats.cntSkipCu[depth] * 100) / m_frameStats.totalCu;
+            m_frameStats.percentTotalCu[depth] = (double)(m_frameStats.cntTotalCu[depth] * 100) / m_frameStats.totalCu;
+        }
     }
 
     m_bs.resetBits();
@@ -826,13 +845,6 @@
     const uint32_t lineStartCUAddr = row * numCols;
     bool bIsVbv = m_param->rc.vbvBufferSize > 0 && m_param->rc.vbvMaxBitrate > 0;
 
-    /* These store the count of inter, intra and skip cus within quad tree structure of each CTU */
-    uint32_t qTreeInterCnt[NUM_CU_DEPTH];
-    uint32_t qTreeIntraCnt[NUM_CU_DEPTH];
-    uint32_t qTreeSkipCnt[NUM_CU_DEPTH];
-    for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
-        qTreeIntraCnt[depth] = qTreeInterCnt[depth] = qTreeSkipCnt[depth] = 0;
-
     while (curRow.completed < numCols)
     {
         ProfileScopeEvent(encodeCTU);
@@ -904,28 +916,36 @@
         // Completed CU processing
         curRow.completed++;
 
-        if (m_param->rc.bStatWrite)
-            curEncData.m_rowStat[row].sumQpAq += collectCTUStatistics(*ctu, qTreeInterCnt, qTreeIntraCnt, qTreeSkipCnt);
+        FrameStats log;
+        memset(&log, 0, sizeof(log));
+        if (m_param->rc.bStatWrite || m_param->logLevel >= X265_LOG_DEBUG)
+            curEncData.m_rowStat[row].sumQpAq += collectCTUStatistics(*ctu, &log);
         else if (m_param->rc.aqMode)
             curEncData.m_rowStat[row].sumQpAq += calcCTUQP(*ctu);
 
         // copy no. of intra, inter Cu cnt per row into frame stats for 2 pass
-        if (m_param->rc.bStatWrite)
+        if (m_param->rc.bStatWrite || m_param->logLevel >= X265_LOG_DEBUG)
         {
-            curRow.rowStats.mvBits += best.mvBits;
-            curRow.rowStats.coeffBits += best.coeffBits;
-            curRow.rowStats.miscBits += best.totalBits - (best.mvBits + best.coeffBits);
+            curRow.rowStats.mvBits      += best.mvBits;
+            curRow.rowStats.coeffBits   += best.coeffBits;
+            curRow.rowStats.miscBits    += best.totalBits - (best.mvBits + best.coeffBits);
+            curRow.rowStats.cntIntraNxN += log.cntIntraNxN;
+            curRow.rowStats.totalCu     += log.totalCu;
 
             for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
             {
                 /* 1 << shift == number of 8x8 blocks at current depth */
                 int shift = 2 * (g_maxCUDepth - depth);
-                curRow.rowStats.intra8x8Cnt += qTreeIntraCnt[depth] << shift;
-                curRow.rowStats.inter8x8Cnt += qTreeInterCnt[depth] << shift;
-                curRow.rowStats.skip8x8Cnt  += qTreeSkipCnt[depth] << shift;
-
-                // clear the row cu data from thread local object
-                qTreeIntraCnt[depth] = qTreeInterCnt[depth] = qTreeSkipCnt[depth] = 0;
+                if (depth != 3)
+                    curRow.rowStats.intra8x8Cnt   += (int)(log.cntIntra[depth] << shift);
+                else
+                    curRow.rowStats.intra8x8Cnt   += (int)(log.cntIntra[depth] + log.cntIntraNxN);
+                curRow.rowStats.inter8x8Cnt       += (int)(log.cntInter[depth] << shift);
+                curRow.rowStats.skip8x8Cnt        += (int)(log.cntSkipCu[depth] << shift);
+                curRow.rowStats.cntInter[depth]   += log.cntInter[depth];
+                curRow.rowStats.cntIntra[depth]   += log.cntIntra[depth];
+                curRow.rowStats.cntSkipCu[depth]  += log.cntSkipCu[depth];
+                curRow.rowStats.cntTotalCu[depth] += log.cntTotalCu[depth];
             }
         }
 
@@ -1103,9 +1123,8 @@
 }
 
 /* collect statistics about CU coding decisions, return total QP */
-int FrameEncoder::collectCTUStatistics(const CUData& ctu, uint32_t* qtreeInterCnt, uint32_t* qtreeIntraCnt, uint32_t* qtreeSkipCnt)
+int FrameEncoder::collectCTUStatistics(const CUData& ctu, FrameStats* log)
 {
-    StatisticLog* log = &m_sliceTypeLog[ctu.m_slice->m_sliceType];
     int totQP = 0;
 
     if (ctu.m_slice->m_sliceType == I_SLICE)
@@ -1116,15 +1135,15 @@
             depth = ctu.m_cuDepth[absPartIdx];
 
             log->totalCu++;
+            log->cntTotalCu[depth]++;
             log->cntIntra[depth]++;
-            qtreeIntraCnt[depth]++;
             totQP += ctu.m_qp[absPartIdx] * (ctu.m_numPartitions >> (depth * 2));
 
             if (ctu.m_predMode[absPartIdx] == MODE_NONE)
             {
                 log->totalCu--;
+                log->cntTotalCu[depth]--;
                 log->cntIntra[depth]--;
-                qtreeIntraCnt[depth]--;
             }
             else if (ctu.m_partSize[absPartIdx] != SIZE_2Nx2N)
             {
@@ -1132,6 +1151,7 @@
                 X265_CHECK(ctu.m_log2CUSize[absPartIdx] == 3 && ctu.m_slice->m_sps->quadtreeTULog2MinSize < 3, "Intra NxN found at improbable depth\n");
                 log->cntIntraNxN++;
                 log->cntIntra[depth]--;
+                log->cntTotalCu[depth]--;
             }
             else if (ctu.m_lumaIntraDir[absPartIdx] > 1)
                 log->cuIntraDistribution[depth][ANGULAR_MODE_ID]++;
@@ -1157,14 +1177,11 @@
             }
             else if (ctu.isSkipped(absPartIdx))
             {
-                log->totalCu--;
                 log->cntSkipCu[depth]++;
-                qtreeSkipCnt[depth]++;
             }
             else if (ctu.isInter(absPartIdx))
             {
                 log->cntInter[depth]++;
-                qtreeInterCnt[depth]++;
 
                 if (ctu.m_partSize[absPartIdx] < AMP_ID)
                     log->cuInterDistribution[depth][ctu.m_partSize[absPartIdx]]++;
@@ -1174,13 +1191,13 @@
             else if (ctu.isIntra(absPartIdx))
             {
                 log->cntIntra[depth]++;
-                qtreeIntraCnt[depth]++;
 
                 if (ctu.m_partSize[absPartIdx] != SIZE_2Nx2N)
                 {
                     X265_CHECK(ctu.m_log2CUSize[absPartIdx] == 3 && ctu.m_slice->m_sps->quadtreeTULog2MinSize < 3, "Intra NxN found at improbable depth\n");
                     log->cntIntraNxN++;
                     log->cntIntra[depth]--;
+                    log->cntTotalCu[depth]--;
                     /* TODO: log intra modes at absPartIdx +0 to +3 */
                 }
                 else if (ctu.m_lumaIntraDir[absPartIdx] > 1)
diff -r e566df2db7b6 -r 98e0e6e63c8a source/encoder/frameencoder.h
--- a/source/encoder/frameencoder.h	Fri Jun 05 18:23:45 2015 +0530
+++ b/source/encoder/frameencoder.h	Fri Jun 05 18:25:13 2015 +0530
@@ -67,23 +67,21 @@
     double      percentIntra;
     double      percentInter;
     double      percentSkip;
-};
 
-struct StatisticLog
-{
-    uint64_t cntInter[4];
-    uint64_t cntIntra[4];
-    uint64_t cuInterDistribution[4][INTER_MODES];
-    uint64_t cuIntraDistribution[4][INTRA_MODES];
-    uint64_t cntIntraNxN;
-    uint64_t cntSkipCu[4];
-    uint64_t cntTotalCu[4];
-    uint64_t totalCu;
+    uint64_t    cntInter[4];
+    uint64_t    cntIntra[4];
+    uint64_t    cntIntraNxN;
+    uint64_t    cntSkipCu[4];
+    uint64_t    cntTotalCu[4];
+    uint64_t    totalCu;
+    uint64_t    cuInterDistribution[4][INTER_MODES];
+    uint64_t    cuIntraDistribution[4][INTRA_MODES];
 
-    StatisticLog()
-    {
-        memset(this, 0, sizeof(StatisticLog));
-    }
+    double      percentIntraCu[4];
+    double      percentInterCu[4];
+    double      percentSkipCu[4];
+    double      percentIntraNxN;
+    double      percentTotalCu[4];
 };
 
 /* manages the state of encoding one row of CTU blocks.  When
@@ -173,7 +171,6 @@
     MD5Context               m_state[3];
     uint32_t                 m_crc[3];
     uint32_t                 m_checksum[3];
-    StatisticLog             m_sliceTypeLog[3];     // per-slice type CU statistics
     FrameStats               m_frameStats;          // stats of current frame for multi-pass encodes
 
     volatile int             m_activeWorkerCount;        // count of workers currently encoding or filtering CTUs
@@ -238,7 +235,7 @@
     void encodeSlice();
 
     void threadMain();
-    int  collectCTUStatistics(const CUData& ctu, uint32_t* qtreeInterCnt, uint32_t* qtreeIntraCnt, uint32_t* qtreeSkipCnt);
+    int  collectCTUStatistics(const CUData& ctu, FrameStats* log);
     int  calcCTUQP(const CUData& ctu);
     void noiseReductionUpdate();
 


More information about the x265-devel mailing list