[x265] [PATCH] Insert additional fields in csv file

bhavna at multicorewareinc.com bhavna at multicorewareinc.com
Fri May 19 18:14:26 CEST 2017


# HG changeset patch
# User Bhavna Hariharan <bhavna at multicorewareinc.com>
# Date 1495196452 -19800
#      Fri May 19 17:50:52 2017 +0530
# Node ID ae26889bf40babc8f002e5fac1231fe37828de0a
# Parent  afdca6b5f90d1e4708466671871d378952e95fbc
Insert additional fields in csv file

diff -r afdca6b5f90d -r ae26889bf40b doc/reST/cli.rst
--- a/doc/reST/cli.rst	Wed May 17 18:38:51 2017 +0530
+++ b/doc/reST/cli.rst	Fri May 19 17:50:52 2017 +0530
@@ -83,9 +83,30 @@
 	it adds one line per run. If :option:`--csv-log-level` is greater than
 	0, it writes one line per frame. Default none
 
-	Several frame performance statistics are available when 
-	:option:`--csv-log-level` is greater than or equal to 2:
-
+	Several statistics about the encoded bitstream and encoder performance are 
+	available when :option:`--csv-log-level` is greater than or equal to 2:
+	
+	**Analysis statistics:**
+	
+	**CU Statistics** percentage of CU modes.
+	
+	**Distortion** Average luma and chroma distortion. Calculated as
+	SSE is done on fenc and recon(after quantization).
+	
+	**Psy Energy **  Average psy energy calculated as the sum of absolute
+	difference between source and recon energy. Energy is measured by sa8d
+	minus SAD.
+	
+	**Residual Energy** Average residual energy. SSE is calculated on fenc 
+	and pred(before quantization).
+	
+	**Luma/Chroma Values** minumum, maximum and average(averaged by area)
+	luma and chroma values of source for each frame.
+	
+	**PU Statistics** percentage of PU modes at each depth.
+	
+	**Performance statistics:**
+	
 	**DecideWait ms** number of milliseconds the frame encoder had to
 	wait, since the previous frame was retrieved by the API thread,
 	before a new frame has been given to it. This is the latency
diff -r afdca6b5f90d -r ae26889bf40b source/common/framedata.h
--- a/source/common/framedata.h	Wed May 17 18:38:51 2017 +0530
+++ b/source/common/framedata.h	Fri May 19 17:50:52 2017 +0530
@@ -78,6 +78,15 @@
     uint64_t    cuInterDistribution[NUM_CU_DEPTH][INTER_MODES];
     uint64_t    cuIntraDistribution[NUM_CU_DEPTH][INTRA_MODES];
 
+
+    uint64_t    totalPu[NUM_CU_DEPTH + 1];
+    uint64_t    cntSkipPu[NUM_CU_DEPTH];
+    uint64_t    cntIntraPu[NUM_CU_DEPTH];
+    uint64_t    cntAmp[NUM_CU_DEPTH];
+    uint64_t    cnt4x4;
+    uint64_t    cntInterPu[NUM_CU_DEPTH][INTER_MODES - 1];
+    uint64_t    cntMergePu[NUM_CU_DEPTH][INTER_MODES - 1];
+
     FrameStats()
     {
         memset(this, 0, sizeof(FrameStats));
diff -r afdca6b5f90d -r ae26889bf40b source/common/picyuv.cpp
--- a/source/common/picyuv.cpp	Wed May 17 18:38:51 2017 +0530
+++ b/source/common/picyuv.cpp	Fri May 19 17:50:52 2017 +0530
@@ -46,6 +46,23 @@
 
     m_maxLumaLevel = 0;
     m_avgLumaLevel = 0;
+
+    m_maxChromaULevel = 0;
+    m_avgChromaULevel = 0;
+
+    m_maxChromaVLevel = 0;
+    m_avgChromaVLevel = 0;
+
+#if (X265_DEPTH > 8)
+    m_minLumaLevel = 0xFFFF;
+    m_minChromaULevel = 0xFFFF;
+    m_minChromaVLevel = 0xFFFF;
+#else
+    m_minLumaLevel = 0xFF;
+    m_minChromaULevel = 0xFF;
+    m_minChromaVLevel = 0xFF;
+#endif
+
     m_stride = 0;
     m_strideC = 0;
     m_hChromaShift = 0;
@@ -210,6 +227,11 @@
 
     X265_CHECK(pic.bitDepth >= 8, "pic.bitDepth check failure");
 
+    uint64_t lumaSum;
+    uint64_t cbSum;
+    uint64_t crSum;
+    lumaSum = cbSum = crSum = 0;
+
     if (pic.bitDepth == 8)
     {
 #if (X265_DEPTH > 8)
@@ -314,6 +336,44 @@
     pixel *U = m_picOrg[1];
     pixel *V = m_picOrg[2];
 
+    if (param.logLevel >= 2)
+    {
+        pixel *yPic = m_picOrg[0];
+        pixel *uPic = m_picOrg[1];
+        pixel *vPic = m_picOrg[2];
+
+        for (int r = 0; r < height; r++)
+        {
+            for (int c = 0; c < width; c++)
+            {
+                m_maxLumaLevel = X265_MAX(yPic[c], m_maxLumaLevel);
+                m_minLumaLevel = X265_MIN(yPic[c], m_minLumaLevel);
+                lumaSum += yPic[c];
+            }
+            yPic += m_stride;
+        }
+        m_avgLumaLevel = (double)lumaSum / (m_picHeight * m_picWidth);
+
+        for (int r = 0; r < height >> m_vChromaShift; r++)
+        {
+            for (int c = 0; c < width >> m_hChromaShift; c++)
+            {
+                m_maxChromaULevel = X265_MAX(uPic[c], m_maxChromaULevel);
+                m_minChromaULevel = X265_MIN(uPic[c], m_minChromaULevel);
+                cbSum += uPic[c];
+
+                m_maxChromaVLevel = X265_MAX(vPic[c], m_maxChromaVLevel);
+                m_minChromaVLevel = X265_MIN(vPic[c], m_minChromaVLevel);
+                crSum += vPic[c];
+            }
+
+            uPic += m_strideC;
+            vPic += m_strideC;
+        }
+        m_avgChromaULevel = (double)cbSum / ((height >> m_vChromaShift) * (width >> m_hChromaShift));
+        m_avgChromaVLevel = (double)crSum / ((height >> m_vChromaShift) * (width >> m_hChromaShift));
+    }
+
 #if HIGH_BIT_DEPTH
     bool calcHDRParams = !!param.minLuma || (param.maxLuma != PIXEL_MAX);
     /* Apply min/max luma bounds for HDR pixel manipulations */
diff -r afdca6b5f90d -r ae26889bf40b source/common/picyuv.h
--- a/source/common/picyuv.h	Wed May 17 18:38:51 2017 +0530
+++ b/source/common/picyuv.h	Fri May 19 17:50:52 2017 +0530
@@ -60,8 +60,17 @@
     uint32_t m_chromaMarginX;
     uint32_t m_chromaMarginY;
 
-    pixel m_maxLumaLevel;
-    double   m_avgLumaLevel;
+    pixel   m_maxLumaLevel;
+    pixel   m_minLumaLevel;
+    double  m_avgLumaLevel;
+
+    pixel   m_maxChromaULevel;
+    pixel   m_minChromaULevel;
+    double  m_avgChromaULevel;
+
+    pixel   m_maxChromaVLevel;
+    pixel   m_minChromaVLevel;
+    double  m_avgChromaVLevel;
 
     PicYuv();
 
diff -r afdca6b5f90d -r ae26889bf40b source/encoder/analysis.cpp
--- a/source/encoder/analysis.cpp	Wed May 17 18:38:51 2017 +0530
+++ b/source/encoder/analysis.cpp	Fri May 19 17:50:52 2017 +0530
@@ -280,9 +280,69 @@
     if (m_param->bEnableRdRefine || m_param->bOptCUDeltaQP)
         qprdRefine(ctu, cuGeom, qp, qp);
 
+    if (m_param->logLevel >= 2)
+        collectPUStatistics(ctu, cuGeom);
+
     return *m_modeDepth[0].bestMode;
 }
 
+void Analysis::collectPUStatistics(const CUData& ctu, const CUGeom& cuGeom)
+{
+    uint8_t depth = 0;
+    uint8_t partSize = 0;
+    for (uint32_t absPartIdx = 0; absPartIdx < ctu.m_numPartitions; absPartIdx += ctu.m_numPartitions >> (depth * 2))
+    {
+        depth = ctu.m_cuDepth[absPartIdx];
+        partSize = ctu.m_partSize[absPartIdx];
+        uint32_t numPU = nbPartsTable[(int)partSize];
+        int shift = 2 * (g_maxCUDepth + 1 - depth);
+        for (uint32_t puIdx = 0; puIdx < numPU; puIdx++)
+        {
+            PredictionUnit pu(ctu, cuGeom, puIdx);
+            int puabsPartIdx = ctu.getPUOffset(puIdx, absPartIdx);
+            int mode = 1;
+            if (ctu.m_partSize[puabsPartIdx + absPartIdx] == SIZE_Nx2N || ctu.m_partSize[puabsPartIdx + absPartIdx] == SIZE_2NxN)
+                mode = 2;
+            else if (ctu.m_partSize[puabsPartIdx + absPartIdx] == SIZE_2NxnU || ctu.m_partSize[puabsPartIdx + absPartIdx] == SIZE_2NxnD || ctu.m_partSize[puabsPartIdx + absPartIdx] == SIZE_nLx2N || ctu.m_partSize[puabsPartIdx + absPartIdx] == SIZE_nRx2N)
+                 mode = 3;
+
+            if (ctu.m_predMode[puabsPartIdx + absPartIdx] == MODE_SKIP)
+            {
+                ctu.m_encData->m_frameStats.cntSkipPu[depth] += (uint64_t)(1 << shift);
+                ctu.m_encData->m_frameStats.totalPu[depth] += (uint64_t)(1 << shift);
+            }
+            else if (ctu.m_predMode[puabsPartIdx + absPartIdx] == MODE_INTRA)
+            {
+                if (ctu.m_partSize[puabsPartIdx + absPartIdx] == SIZE_NxN)
+                {
+                    ctu.m_encData->m_frameStats.cnt4x4++;
+                    ctu.m_encData->m_frameStats.totalPu[4]++;
+                }
+                else
+                {
+                    ctu.m_encData->m_frameStats.cntIntraPu[depth] += (uint64_t)(1 << shift);
+                    ctu.m_encData->m_frameStats.totalPu[depth] += (uint64_t)(1 << shift);
+                }
+            }
+            else if (mode == 3)
+            {
+                ctu.m_encData->m_frameStats.cntAmp[depth] += (uint64_t)(1 << shift);
+                ctu.m_encData->m_frameStats.totalPu[depth] += (uint64_t)(1 << shift);
+                break;
+            }
+            else
+            {
+                if (ctu.m_mergeFlag[puabsPartIdx + absPartIdx])
+                    ctu.m_encData->m_frameStats.cntMergePu[depth][ctu.m_partSize[puabsPartIdx + absPartIdx]] += (1 << shift) / mode;
+                else
+                    ctu.m_encData->m_frameStats.cntInterPu[depth][ctu.m_partSize[puabsPartIdx + absPartIdx]] += (1 << shift) / mode;
+
+                ctu.m_encData->m_frameStats.totalPu[depth] += (1 << shift) / mode;
+            }
+        }
+    }
+}
+
 int32_t Analysis::loadTUDepth(CUGeom cuGeom, CUData parentCTU)
 {
     float predDepth = 0;
diff -r afdca6b5f90d -r ae26889bf40b source/encoder/analysis.h
--- a/source/encoder/analysis.h	Wed May 17 18:38:51 2017 +0530
+++ b/source/encoder/analysis.h	Fri May 19 17:50:52 2017 +0530
@@ -181,6 +181,9 @@
 
     void calculateNormFactor(CUData& ctu, int qp);
     void normFactor(const pixel* src, uint32_t blockSize, CUData& ctu, int qp, TextType ttype);
+
+    void collectPUStatistics(const CUData& ctu, const CUGeom& cuGeom);
+
     /* check whether current mode is the new best */
     inline void checkBestMode(Mode& mode, uint32_t depth)
     {
diff -r afdca6b5f90d -r ae26889bf40b source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Wed May 17 18:38:51 2017 +0530
+++ b/source/encoder/encoder.cpp	Fri May 19 17:50:52 2017 +0530
@@ -1762,6 +1762,16 @@
         frameStats->avgResEnergy            = curFrame->m_encData->m_frameStats.avgResEnergy;
         frameStats->avgLumaLevel            = curFrame->m_fencPic->m_avgLumaLevel;
         frameStats->maxLumaLevel            = curFrame->m_fencPic->m_maxLumaLevel;
+        frameStats->minLumaLevel            = curFrame->m_fencPic->m_minLumaLevel;
+
+        frameStats->maxChromaULevel = curFrame->m_fencPic->m_maxChromaULevel;
+        frameStats->minChromaULevel = curFrame->m_fencPic->m_minChromaULevel;
+        frameStats->avgChromaULevel = curFrame->m_fencPic->m_avgChromaULevel;
+
+        frameStats->maxChromaVLevel = curFrame->m_fencPic->m_maxChromaVLevel;
+        frameStats->minChromaVLevel = curFrame->m_fencPic->m_minChromaVLevel;
+        frameStats->avgChromaVLevel = curFrame->m_fencPic->m_avgChromaVLevel;
+
         for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
         {
             frameStats->cuStats.percentSkipCu[depth]  = curFrame->m_encData->m_frameStats.percentSkipCu[depth];
@@ -1772,6 +1782,36 @@
             for (int n = 0; n < INTRA_MODES; n++)
                 frameStats->cuStats.percentIntraDistribution[depth][n] = curFrame->m_encData->m_frameStats.percentIntraDistribution[depth][n];
         }
+
+        if (curFrame->m_encData->m_frameStats.totalPu[4] == 0)
+            frameStats->puStats.percentNxN = 0;
+        else
+            frameStats->puStats.percentNxN = (double)(curFrame->m_encData->m_frameStats.cnt4x4 / (double)curFrame->m_encData->m_frameStats.totalPu[4]) * 100;
+        for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+        {
+            if (curFrame->m_encData->m_frameStats.totalPu[depth] == 0)
+            {
+                frameStats->puStats.percentSkipPu[depth] = 0;
+                frameStats->puStats.percentIntraPu[depth] = 0;
+                frameStats->puStats.percentAmpPu[depth] = 0;
+                for (int i = 0; i < INTER_MODES - 1; i++)
+                {
+                    frameStats->puStats.percentInterPu[depth][i] = 0;
+                    frameStats->puStats.percentMergePu[depth][i] = 0;
+                }
+            }
+            else
+            {
+                frameStats->puStats.percentSkipPu[depth] = (double)(curFrame->m_encData->m_frameStats.cntSkipPu[depth] / (double)curFrame->m_encData->m_frameStats.totalPu[depth]) * 100;
+                frameStats->puStats.percentIntraPu[depth] = (double)(curFrame->m_encData->m_frameStats.cntIntraPu[depth] / (double)curFrame->m_encData->m_frameStats.totalPu[depth]) * 100;
+                frameStats->puStats.percentAmpPu[depth] = (double)(curFrame->m_encData->m_frameStats.cntAmp[depth] / (double)curFrame->m_encData->m_frameStats.totalPu[depth]) * 100;
+                for (int i = 0; i < INTER_MODES - 1; i++)
+                {
+                    frameStats->puStats.percentInterPu[depth][i] = (double)(curFrame->m_encData->m_frameStats.cntInterPu[depth][i] / (double)curFrame->m_encData->m_frameStats.totalPu[depth]) * 100;
+                    frameStats->puStats.percentMergePu[depth][i] = (double)(curFrame->m_encData->m_frameStats.cntMergePu[depth][i] / (double)curFrame->m_encData->m_frameStats.totalPu[depth]) * 100;
+                }
+            }
+        }
     }
 }
 
diff -r afdca6b5f90d -r ae26889bf40b source/x265-extras.cpp
--- a/source/x265-extras.cpp	Wed May 17 18:38:51 2017 +0530
+++ b/source/x265-extras.cpp	Fri May 19 17:50:52 2017 +0530
@@ -110,11 +110,35 @@
                     fprintf(csvfp, ", Merge %dx%d", size, size);
                     size /= 2;
                 }
-                fprintf(csvfp, ", Avg Luma Distortion, Avg Chroma Distortion, Avg psyEnergy, Avg Luma Level, Max Luma Level, Avg Residual Energy");
+                fprintf(csvfp, ", Avg Luma Distortion, Avg Chroma Distortion, Avg psyEnergy, Avg Residual Energy,"
+                               " Min Luma Level, Max Luma Level, Avg Luma Level");
+                fprintf(csvfp, ", Min Cb Level, Max Cb Level, Avg Cb Level, Min Cr Level, Max Cr Level, Avg Cr Level");
 
-                /* detailed performance statistics */
                 if (level >= 2)
-                    fprintf(csvfp, ", DecideWait (ms), Row0Wait (ms), Wall time (ms), Ref Wait Wall (ms), Total CTU time (ms), Stall Time (ms), Total frame time (ms), Avg WPP, Row Blocks");
+                {
+                    /* PU statistics */
+                    size = param.maxCUSize;
+                    for (uint32_t i = 0; i< g_maxLog2CUSize - (uint32_t)g_log2Size[param.minCUSize] + 1; i++)
+                    {
+                        fprintf(csvfp, ", Intra %dx%d", size, size);
+                        fprintf(csvfp, ", Skip %dx%d", size, size);
+                        fprintf(csvfp, ", AMP %d", size);
+                        fprintf(csvfp, ", Inter %dx%d", size, size);
+                        fprintf(csvfp, ", Merge %dx%d", size, size);
+                        fprintf(csvfp, ", Inter %dx%d", size, size / 2);
+                        fprintf(csvfp, ", Merge %dx%d", size, size / 2);
+                        fprintf(csvfp, ", Inter %dx%d", size / 2, size);
+                        fprintf(csvfp, ", Merge %dx%d", size / 2, size);
+                        size /= 2;
+                    }
+
+                    if ((uint32_t)g_log2Size[param.minCUSize] == 3)
+                        fprintf(csvfp, ", 4x4");
+
+                    /* detailed performance statistics */
+                    fprintf(csvfp, ", DecideWait (ms), Row0Wait (ms), Wall time (ms), Ref Wait Wall (ms), Total CTU time (ms),"
+                    "Stall Time (ms), Total frame time (ms), Avg WPP, Row Blocks");
+                }
                 fprintf(csvfp, "\n");
             }
             else
@@ -131,7 +155,8 @@
         return;
 
     const x265_frame_stats* frameStats = &pic.frameData;
-    fprintf(csvfp, "%d, %c-SLICE, %4d, %2.2lf, %10d, %d,", frameStats->encoderOrder, frameStats->sliceType, frameStats->poc, frameStats->qp, (int)frameStats->bits, frameStats->bScenecut);
+    fprintf(csvfp, "%d, %c-SLICE, %4d, %2.2lf, %10d, %d,", frameStats->encoderOrder, frameStats->sliceType, frameStats->poc, 
+                                                           frameStats->qp, (int)frameStats->bits, frameStats->bScenecut);
     if (param.rc.rateControlMode == X265_RC_CRF)
         fprintf(csvfp, "%.3lf,", frameStats->rateFactor);
     if (param.rc.vbvBufferSize)
@@ -160,13 +185,16 @@
             fputs(" -,", csvfp);
     }
     for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
-        fprintf(csvfp, "%5.2lf%%, %5.2lf%%, %5.2lf%%,", frameStats->cuStats.percentIntraDistribution[depth][0], frameStats->cuStats.percentIntraDistribution[depth][1], frameStats->cuStats.percentIntraDistribution[depth][2]);
+        fprintf(csvfp, "%5.2lf%%, %5.2lf%%, %5.2lf%%,", frameStats->cuStats.percentIntraDistribution[depth][0],
+                                                        frameStats->cuStats.percentIntraDistribution[depth][1],
+                                                        frameStats->cuStats.percentIntraDistribution[depth][2]);
     fprintf(csvfp, "%5.2lf%%", frameStats->cuStats.percentIntraNxN);
     if (param.bEnableRectInter)
     {
         for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
         {
-            fprintf(csvfp, ", %5.2lf%%, %5.2lf%%", frameStats->cuStats.percentInterDistribution[depth][0], frameStats->cuStats.percentInterDistribution[depth][1]);
+            fprintf(csvfp, ", %5.2lf%%, %5.2lf%%", frameStats->cuStats.percentInterDistribution[depth][0],
+                                                   frameStats->cuStats.percentInterDistribution[depth][1]);
             if (param.bEnableAMP)
                 fprintf(csvfp, ", %5.2lf%%", frameStats->cuStats.percentInterDistribution[depth][2]);
         }
@@ -180,11 +208,37 @@
         fprintf(csvfp, ", %5.2lf%%", frameStats->cuStats.percentSkipCu[depth]);
     for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
         fprintf(csvfp, ", %5.2lf%%", frameStats->cuStats.percentMergeCu[depth]);
-    fprintf(csvfp, ", %.2lf, %.2lf, %.2lf, %.2lf, %d, %.2lf", frameStats->avgLumaDistortion, frameStats->avgChromaDistortion, frameStats->avgPsyEnergy, frameStats->avgLumaLevel, frameStats->maxLumaLevel, frameStats->avgResEnergy);
+
+    fprintf(csvfp, ", %.2lf, %.2lf, %.2lf, %.2lf ", frameStats->avgLumaDistortion,
+                                                    frameStats->avgChromaDistortion,
+                                                    frameStats->avgPsyEnergy,
+                                                    frameStats->avgResEnergy);
+
+    fprintf(csvfp, ", %d, %d, %.2lf", frameStats->minLumaLevel, frameStats->maxLumaLevel, frameStats->avgLumaLevel);
+    fprintf(csvfp, ", %d, %d, %.2lf", frameStats->minChromaULevel, frameStats->maxChromaULevel, frameStats->avgChromaULevel);
+    fprintf(csvfp, ", %d, %d, %.2lf", frameStats->minChromaVLevel, frameStats->maxChromaVLevel, frameStats->avgChromaVLevel);
 
     if (level >= 2)
     {
-        fprintf(csvfp, ", %.1lf, %.1lf, %.1lf, %.1lf, %.1lf, %.1lf, %.1lf,", frameStats->decideWaitTime, frameStats->row0WaitTime, frameStats->wallTime, frameStats->refWaitWallTime, frameStats->totalCTUTime, frameStats->stallTime, frameStats->totalFrameTime);
+        for (uint32_t i = 0; i < g_maxLog2CUSize - (uint32_t)g_log2Size[param.minCUSize] + 1; i++)
+        {
+            fprintf(csvfp, ", %.2lf%%", frameStats->puStats.percentIntraPu[i]);
+            fprintf(csvfp, ", %.2lf%%", frameStats->puStats.percentSkipPu[i]);
+            fprintf(csvfp, ",%.2lf%%", frameStats->puStats.percentAmpPu[i]);
+            for (uint32_t j = 0; j < 3; j++)
+            {
+                fprintf(csvfp, ", %.2lf%%", frameStats->puStats.percentInterPu[i][j]);
+                fprintf(csvfp, ", %.2lf%%", frameStats->puStats.percentMergePu[i][j]);
+            }
+        }
+        if ((uint32_t)g_log2Size[param.minCUSize] == 3)
+            fprintf(csvfp, ",%.2lf%%", frameStats->puStats.percentNxN);
+
+        fprintf(csvfp, ", %.1lf, %.1lf, %.1lf, %.1lf, %.1lf, %.1lf, %.1lf,", frameStats->decideWaitTime, frameStats->row0WaitTime,
+                                                                             frameStats->wallTime, frameStats->refWaitWallTime,
+                                                                             frameStats->totalCTUTime, frameStats->stallTime,
+                                                                             frameStats->totalFrameTime);
+
         fprintf(csvfp, " %.3lf, %d", frameStats->avgWPP, frameStats->countRowBlocks);
     }
     fprintf(csvfp, "\n");
diff -r afdca6b5f90d -r ae26889bf40b source/x265.h
--- a/source/x265.h	Wed May 17 18:38:51 2017 +0530
+++ b/source/x265.h	Fri May 19 17:50:52 2017 +0530
@@ -117,6 +117,20 @@
 } x265_cu_stats;
 
 
+/* pu statistics */
+typedef struct x265_pu_stats
+{
+    double      percentSkipPu[4];               // Percentage of skip cu in all depths
+    double      percentIntraPu[4];              // Percentage of intra modes in all depths
+    double      percentAmpPu[4];                // Percentage of amp modes in all depths
+    double      percentInterPu[4][3];           // Percentage of inter 2nx2n, 2nxn and nx2n in all depths
+    double      percentMergePu[4][3];           // Percentage of merge 2nx2n, 2nxn and nx2n in all depth
+    double      percentNxN;
+
+    /* All the above values will add up to 100%. */
+} x265_pu_stats;
+
+
 typedef struct x265_analysis_2Pass
 {
     uint32_t      poc;
@@ -154,12 +168,25 @@
     int              list0POC[16];
     int              list1POC[16];
     uint16_t         maxLumaLevel;
+    uint16_t         minLumaLevel;
+
+    uint16_t         maxChromaULevel;
+    uint16_t         minChromaULevel;
+    double           avgChromaULevel;
+
+
+    uint16_t         maxChromaVLevel;
+    uint16_t         minChromaVLevel;
+    double           avgChromaVLevel;
+
     char             sliceType;
     int              bScenecut;
     int              frameLatency;
     x265_cu_stats    cuStats;
+    x265_pu_stats    puStats;
     double           totalFrameTime;
 } x265_frame_stats;
+
 typedef struct x265_ctu_info_t
 {
     int32_t ctuAddress;


More information about the x265-devel mailing list