[x265] [PATCH] stats: report counts of each CU partition size/mode per frame
Divya Manivannan
divya at multicorewareinc.com
Mon May 25 08:44:20 CEST 2015
# HG changeset patch
# User Divya Manivannan <divya at multicorewareinc.com>
# Date 1432535853 -19800
# Mon May 25 12:07:33 2015 +0530
# Node ID 05579078c8faf0f4c3dbe10805d1b83048db1e96
# Parent a7bf7a150a705489cb63d0454c59ec599bad8c93
stats: report counts of each CU partition size/mode per frame
diff -r a7bf7a150a70 -r 05579078c8fa source/common/param.cpp
--- a/source/common/param.cpp Fri May 22 14:29:35 2015 +0530
+++ b/source/common/param.cpp Mon May 25 12:07:33 2015 +0530
@@ -104,6 +104,7 @@
param->csvfn = NULL;
param->rc.lambdaFileName = NULL;
param->bLogCuStats = 0;
+ param->bLogFrameStats = 0;
param->decodedPictureHashSEI = 0;
/* Quality Measurement Metrics */
@@ -582,6 +583,7 @@
}
}
OPT("cu-stats") p->bLogCuStats = atobool(value);
+ OPT("frame-stats") p->bLogFrameStats = atobool(value);
OPT("annexb") p->bAnnexB = atobool(value);
OPT("repeat-headers") p->bRepeatHeaders = atobool(value);
OPT("wpp") p->bEnableWavefront = atobool(value);
diff -r a7bf7a150a70 -r 05579078c8fa source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Fri May 22 14:29:35 2015 +0530
+++ b/source/encoder/encoder.cpp Mon May 25 12:07:33 2015 +0530
@@ -73,6 +73,7 @@
m_numDelayedPic = 0;
m_outputCount = 0;
m_csvfpt = NULL;
+ m_csvfptFrame = NULL;
m_param = NULL;
m_latestParam = NULL;
m_cuOffsetY = NULL;
@@ -254,6 +255,20 @@
}
}
+ if (m_param->bLogFrameStats)
+ {
+ m_csvfptFrame = fopen("FrameLog.csv", "wb");
+ if (m_csvfptFrame)
+ {
+ fprintf(m_csvfptFrame, "POC, SLICE TYPE, 64x64 CU%% , 32x32 CU%%, 16x16 CU%%, 8x8 CU%%, 4x4 prediction%%, Intra CU%%, Inter CU%%, Skip CU%%\n");
+ }
+ else
+ {
+ x265_log(m_param, X265_LOG_ERROR, "Unable to open CSV log file FrameLog.csv, aborting\n");
+ m_aborted = true;
+ }
+ }
+
int numRows = (m_param->sourceHeight + g_maxCUSize - 1) / g_maxCUSize;
int numCols = (m_param->sourceWidth + g_maxCUSize - 1) / g_maxCUSize;
for (int i = 0; i < m_param->frameNumThreads; i++)
@@ -367,6 +382,8 @@
fclose(m_analysisFile);
if (m_csvfpt)
fclose(m_csvfpt);
+ if (m_csvfptFrame)
+ fclose(m_csvfptFrame);
if (m_param)
{
@@ -1465,6 +1482,16 @@
fprintf(m_csvfpt, "\n");
fflush(stderr);
}
+
+ if (m_param->bLogFrameStats && m_csvfptFrame)
+ {
+ fprintf(m_csvfptFrame, "%d, %c-SLICE,", poc, c);
+ fprintf(m_csvfptFrame, " %.2lf, %.2lf, %.2lf,", curEncoder->m_frameStats.cuStat.percentCuDepth[0], curEncoder->m_frameStats.cuStat.percentCuDepth[1], curEncoder->m_frameStats.cuStat.percentCuDepth[2]);
+ fprintf(m_csvfptFrame, " %.2lf, %.2lf, %.2lf,", curEncoder->m_frameStats.cuStat.percentCuDepth[3], curEncoder->m_frameStats.cuStat.percentIntraNxN, curEncoder->m_frameStats.cuStat.percentIntraCu);
+ fprintf(m_csvfptFrame, " %.2lf, %.2lf", curEncoder->m_frameStats.cuStat.percentInterCu, curEncoder->m_frameStats.cuStat.percentSkipCu);
+ fprintf(m_csvfptFrame, "\n");
+ fflush(stderr);
+ }
}
#if defined(_MSC_VER)
diff -r a7bf7a150a70 -r 05579078c8fa source/encoder/encoder.h
--- a/source/encoder/encoder.h Fri May 22 14:29:35 2015 +0530
+++ b/source/encoder/encoder.h Mon May 25 12:07:33 2015 +0530
@@ -106,6 +106,7 @@
EncStats m_analyzeP;
EncStats m_analyzeB;
FILE* m_csvfpt;
+ FILE* m_csvfptFrame;
int64_t m_encodeStartTime;
// weighted prediction
diff -r a7bf7a150a70 -r 05579078c8fa source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp Fri May 22 14:29:35 2015 +0530
+++ b/source/encoder/frameencoder.cpp Mon May 25 12:07:33 2015 +0530
@@ -552,7 +552,7 @@
}
}
- if (m_param->rc.bStatWrite)
+ if (m_param->rc.bStatWrite || m_param->bLogFrameStats)
{
int totalI = 0, totalP = 0, totalSkip = 0;
@@ -562,14 +562,30 @@
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.cuStat.cntInterCu += m_rows[i].rowStats.cuStat.cntInterCu;
+ m_frameStats.cuStat.cntIntraCu += m_rows[i].rowStats.cuStat.cntIntraCu;
+ m_frameStats.cuStat.cntIntraNxN += m_rows[i].rowStats.cuStat.cntIntraNxN;
+ m_frameStats.cuStat.cntSkipCu += m_rows[i].rowStats.cuStat.cntSkipCu;
+ m_frameStats.cuStat.totalCu += m_rows[i].rowStats.cuStat.totalCu;
totalI += m_rows[i].rowStats.iCuCnt;
totalP += m_rows[i].rowStats.pCuCnt;
totalSkip += m_rows[i].rowStats.skipCuCnt;
+
+ for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+ {
+ m_frameStats.cuStat.cntCuDepth[depth] += m_rows[i].rowStats.cuStat.cntCuDepth[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.cuStat.percentIntraNxN = (double)(m_frameStats.cuStat.cntIntraNxN * 100) / m_frameStats.cuStat.totalCu;
+ m_frameStats.cuStat.percentIntraCu = (double)(m_frameStats.cuStat.cntIntraCu * 100) / m_frameStats.cuStat.totalCu;
+ m_frameStats.cuStat.percentInterCu = (double)(m_frameStats.cuStat.cntInterCu * 100) / m_frameStats.cuStat.totalCu;
+ m_frameStats.cuStat.percentSkipCu = (double)(m_frameStats.cuStat.cntSkipCu * 100) / m_frameStats.cuStat.totalCu;
+ for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+ m_frameStats.cuStat.percentCuDepth[depth] = (double)(m_frameStats.cuStat.cntCuDepth[depth] * 100) / m_frameStats.cuStat.totalCu;
}
m_bs.resetBits();
@@ -904,17 +920,22 @@
// Completed CU processing
curRow.completed++;
- if (m_param->bLogCuStats || m_param->rc.bStatWrite)
+ if (m_param->bLogCuStats || m_param->rc.bStatWrite || m_param->bLogFrameStats)
curEncData.m_rowStat[row].sumQpAq += collectCTUStatistics(*ctu, qTreeInterCnt, qTreeIntraCnt, qTreeSkipCnt);
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->bLogFrameStats)
{
curRow.rowStats.mvBits += best.mvBits;
curRow.rowStats.coeffBits += best.coeffBits;
curRow.rowStats.miscBits += best.totalBits - (best.mvBits + best.coeffBits);
+ curRow.rowStats.cuStat.cntInterCu += m_cuStatistic.cntInterCu;
+ curRow.rowStats.cuStat.cntIntraCu += m_cuStatistic.cntIntraCu;
+ curRow.rowStats.cuStat.cntIntraNxN += m_cuStatistic.cntIntraNxN;
+ curRow.rowStats.cuStat.cntSkipCu += m_cuStatistic.cntSkipCu;
+ curRow.rowStats.cuStat.totalCu += m_cuStatistic.totalCu;
for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
{
@@ -923,10 +944,12 @@
curRow.rowStats.iCuCnt += qTreeIntraCnt[depth] << shift;
curRow.rowStats.pCuCnt += qTreeInterCnt[depth] << shift;
curRow.rowStats.skipCuCnt += qTreeSkipCnt[depth] << shift;
+ curRow.rowStats.cuStat.cntCuDepth[depth] += m_cuStatistic.cntCuDepth[depth];
// clear the row cu data from thread local object
qTreeIntraCnt[depth] = qTreeInterCnt[depth] = qTreeSkipCnt[depth] = 0;
}
+ memset(&m_cuStatistic, 0, sizeof(CuStatistic));
}
curEncData.m_cuStat[cuAddr].totalBits = best.totalBits;
@@ -1106,6 +1129,7 @@
int FrameEncoder::collectCTUStatistics(const CUData& ctu, uint32_t* qtreeInterCnt, uint32_t* qtreeIntraCnt, uint32_t* qtreeSkipCnt)
{
StatisticLog* log = &m_sliceTypeLog[ctu.m_slice->m_sliceType];
+ CuStatistic* cuLog = &m_cuStatistic;
int totQP = 0;
if (ctu.m_slice->m_sliceType == I_SLICE)
@@ -1117,6 +1141,9 @@
log->totalCu++;
log->cntIntra[depth]++;
+ cuLog->cntCuDepth[depth]++;
+ cuLog->cntIntraCu++;
+ cuLog->totalCu++;
qtreeIntraCnt[depth]++;
totQP += ctu.m_qp[absPartIdx] * (ctu.m_numPartitions >> (depth * 2));
@@ -1124,6 +1151,9 @@
{
log->totalCu--;
log->cntIntra[depth]--;
+ cuLog->cntCuDepth[depth]--;
+ cuLog->cntIntraCu--;
+ cuLog->totalCu--;
qtreeIntraCnt[depth]--;
}
else if (ctu.m_partSize[absPartIdx] != SIZE_2Nx2N)
@@ -1132,6 +1162,8 @@
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]--;
+ cuLog->cntIntraNxN++;
+ cuLog->cntCuDepth[depth]--;
}
else if (ctu.m_lumaIntraDir[absPartIdx] > 1)
log->cuIntraDistribution[depth][ANGULAR_MODE_ID]++;
@@ -1148,22 +1180,28 @@
log->totalCu++;
log->cntTotalCu[depth]++;
+ cuLog->cntCuDepth[depth]++;
+ cuLog->totalCu++;
totQP += ctu.m_qp[absPartIdx] * (ctu.m_numPartitions >> (depth * 2));
if (ctu.m_predMode[absPartIdx] == MODE_NONE)
{
log->totalCu--;
log->cntTotalCu[depth]--;
+ cuLog->cntCuDepth[depth]--;
+ cuLog->totalCu--;
}
else if (ctu.isSkipped(absPartIdx))
{
log->totalCu--;
log->cntSkipCu[depth]++;
+ cuLog->cntSkipCu++;
qtreeSkipCnt[depth]++;
}
else if (ctu.isInter(absPartIdx))
{
log->cntInter[depth]++;
+ cuLog->cntInterCu++;
qtreeInterCnt[depth]++;
if (ctu.m_partSize[absPartIdx] < AMP_ID)
@@ -1174,6 +1212,7 @@
else if (ctu.isIntra(absPartIdx))
{
log->cntIntra[depth]++;
+ cuLog->cntIntraCu++;
qtreeIntraCnt[depth]++;
if (ctu.m_partSize[absPartIdx] != SIZE_2Nx2N)
@@ -1181,6 +1220,8 @@
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]--;
+ cuLog->cntIntraNxN++;
+ cuLog->cntCuDepth[depth]--;
/* TODO: log intra modes at absPartIdx +0 to +3 */
}
else if (ctu.m_lumaIntraDir[absPartIdx] > 1)
diff -r a7bf7a150a70 -r 05579078c8fa source/encoder/frameencoder.h
--- a/source/encoder/frameencoder.h Fri May 22 14:29:35 2015 +0530
+++ b/source/encoder/frameencoder.h Mon May 25 12:07:33 2015 +0530
@@ -157,6 +157,7 @@
uint32_t m_crc[3];
uint32_t m_checksum[3];
StatisticLog m_sliceTypeLog[3]; // per-slice type CU statistics
+ CuStatistic m_cuStatistic; // stats of current CU
FrameStats m_frameStats; // stats of current frame for multi-pass encodes
volatile int m_activeWorkerCount; // count of workers currently encoding or filtering CTUs
diff -r a7bf7a150a70 -r 05579078c8fa source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Fri May 22 14:29:35 2015 +0530
+++ b/source/encoder/ratecontrol.h Mon May 25 12:07:33 2015 +0530
@@ -46,6 +46,27 @@
#define MIN_AMORTIZE_FRACTION 0.2
#define CLIP_DURATION(f) x265_clip3(MIN_FRAME_DURATION, MAX_FRAME_DURATION, f)
+struct CuStatistic
+{
+ uint64_t cntCuDepth[4];
+ uint64_t cntIntraNxN;
+ uint64_t cntSkipCu;
+ uint64_t cntIntraCu;
+ uint64_t cntInterCu;
+ uint64_t totalCu;
+
+ double percentCuDepth[4];
+ double percentIntraNxN;
+ double percentSkipCu;
+ double percentIntraCu;
+ double percentInterCu;
+
+ CuStatistic()
+ {
+ memset(this, 0, sizeof(CuStatistic));
+ }
+};
+
/* Current frame stats for 2 pass */
struct FrameStats
{
@@ -61,6 +82,8 @@
double percentIntra;
double percentInter;
double percentSkip;
+
+ CuStatistic cuStat;
};
struct Predictor
diff -r a7bf7a150a70 -r 05579078c8fa source/x265.h
--- a/source/x265.h Fri May 22 14:29:35 2015 +0530
+++ b/source/x265.h Mon May 25 12:07:33 2015 +0530
@@ -443,6 +443,9 @@
* modes during mode decision. Default disabled */
int bLogCuStats;
+ /* Enable logging of frame level data. Default is disabled*/
+ int bLogFrameStats;
+
/* Enable the measurement and reporting of PSNR. Default is enabled */
int bEnablePsnr;
diff -r a7bf7a150a70 -r 05579078c8fa source/x265cli.h
--- a/source/x265cli.h Fri May 22 14:29:35 2015 +0530
+++ b/source/x265cli.h Mon May 25 12:07:33 2015 +0530
@@ -56,6 +56,8 @@
{ "csv", required_argument, NULL, 0 },
{ "no-cu-stats", no_argument, NULL, 0 },
{ "cu-stats", no_argument, NULL, 0 },
+ { "no-frame-stats", no_argument, NULL, 0 },
+ { "frame-stats", no_argument, NULL, 0 },
{ "y4m", no_argument, NULL, 0 },
{ "no-progress", no_argument, NULL, 0 },
{ "output", required_argument, NULL, 'o' },
@@ -248,6 +250,7 @@
H0(" --log-level <string> Logging level: none error warning info debug full. Default %s\n", x265::logLevelNames[param->logLevel + 1]);
H0(" --no-progress Disable CLI progress reports\n");
H0(" --[no-]cu-stats Enable logging stats about distribution of cu across all modes. Default %s\n",OPT(param->bLogCuStats));
+ H0(" --[no-]frame-stats Enable logging stats about frames. Default %s\n", OPT(param->bLogFrameStats));
H1(" --csv <filename> Comma separated log file, log level >= 3 frame log, else one line per run\n");
H0("\nInput Options:\n");
H0(" --input <filename> Raw YUV or Y4M input file name. `-` for stdin\n");
More information about the x265-devel
mailing list