[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