changeset 12661:516a5796ccdc

Store histogram of Y, U, V and Y's edge in analysis file. Enables the library to compute Y Histogram and store Histogram of Y, U, V Channel and Y's Edge in analysis file at all reuse levels when --hist-scenecut is enabled.
author Soundariya <soundariya@multicorewareinc.com>
date Tue, 21 Apr 2020 11:04:30 +0530
parents d5695e28999e
children 04275ae58030
files source/CMakeLists.txt source/encoder/encoder.cpp source/encoder/encoder.h source/x265.h
diffstat 4 files changed, 92 insertions(+-), 27 deletions(-) [+]
line wrap: on
line diff
--- a/source/CMakeLists.txt	Thu May 14 13:00:56 2020 +0530
+++ b/source/CMakeLists.txt	Tue Apr 21 11:04:30 2020 +0530
@@ -29,7 +29,7 @@ option(NATIVE_BUILD "Target the build CP
 option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)
 mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)
 # X265_BUILD must be incremented each time the public API is changed
-set(X265_BUILD 192)
+set(X265_BUILD 193)
 configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
                "${PROJECT_BINARY_DIR}/x265.def")
 configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
--- a/source/encoder/encoder.cpp	Thu May 14 13:00:56 2020 +0530
+++ b/source/encoder/encoder.cpp	Tue Apr 21 11:04:30 2020 +0530
@@ -1437,7 +1437,6 @@ bool Encoder::computeHistograms(x265_pic
     }
 
     size_t bufSize = sizeof(pixel) * m_planeSizes[0];
-    int32_t planeCount = x265_cli_csps[m_param->internalCsp].planes;
     memset(m_edgePic, 0, bufSize);
 
     if (!computeEdge(m_edgePic, src, NULL, pic->width, pic->height, pic->width, false, 1))
@@ -1448,47 +1447,46 @@ bool Encoder::computeHistograms(x265_pic
 
     pixel pixelVal;
     int32_t *edgeHist = m_curEdgeHist;
-    memset(edgeHist, 0, 2 * sizeof(int32_t));
-    for (int64_t i = 0; i < m_planeSizes[0]; i++)
+    memset(edgeHist, 0, EDGE_BINS * sizeof(int32_t));
+    for (uint32_t i = 0; i < m_planeSizes[0]; i++)
     {
         if (!m_edgePic[i])
            edgeHist[0]++;
         else
            edgeHist[1]++;
     }
+    /* Y Histogram Calculation */
+    int32_t* yHist = m_curYUVHist[0];
+    memset(yHist, 0, HISTOGRAM_BINS * sizeof(int32_t));
+    for (uint32_t i = 0; i < m_planeSizes[0]; i++)
+    {
+        pixelVal = src[i];
+        yHist[pixelVal]++;
+    }
 
     if (pic->colorSpace != X265_CSP_I400)
     {
         /* U Histogram Calculation */
-        int32_t *uHist = m_curUVHist[0];
+        int32_t *uHist = m_curYUVHist[1];
         memset(uHist, 0, HISTOGRAM_BINS * sizeof(int32_t));
-
-        for (int64_t i = 0; i < m_planeSizes[1]; i++)
+        for (uint32_t i = 0; i < m_planeSizes[1]; i++)
         {
             pixelVal = planeU[i];
             uHist[pixelVal]++;
         }
 
         /* V Histogram Calculation */
-        if (planeCount == 3)
-        {
-            pixelVal = 0;
-            int32_t *vHist = m_curUVHist[1];
-            memset(vHist, 0, HISTOGRAM_BINS * sizeof(int32_t));
-
-            for (int64_t i = 0; i < m_planeSizes[2]; i++)
-            {
-                pixelVal = planeV[i];
-                vHist[pixelVal]++;
-            }
-            for (int i = 0; i < HISTOGRAM_BINS; i++)
-            {
-                m_curMaxUVHist[i] = x265_max(uHist[i], vHist[i]);
-            }
-        }
-        else
-        {   /* in case of bi planar color space */
-            memcpy(m_curMaxUVHist, m_curUVHist[0], HISTOGRAM_BINS * sizeof(int32_t));
+        pixelVal = 0;
+        int32_t *vHist = m_curYUVHist[2];
+        memset(vHist, 0, HISTOGRAM_BINS * sizeof(int32_t));
+        for (uint32_t i = 0; i < m_planeSizes[2]; i++)
+        {
+            pixelVal = planeV[i];
+            vHist[pixelVal]++;
+        }
+        for (int i = 0; i < HISTOGRAM_BINS; i++)
+        {
+            m_curMaxUVHist[i] = x265_max(uHist[i], vHist[i]);
         }
     }
     return true;
@@ -1794,6 +1792,16 @@ int Encoder::encode(const x265_picture* 
         {
             inFrame->m_lowres.bScenecut = (inputPic->frameData.bScenecut == 1) ? true : false;
         }
+        if (m_param->bHistBasedSceneCut && m_param->analysisSave)
+        {
+            memcpy(inFrame->m_analysisData.edgeHist, m_curEdgeHist, EDGE_BINS * sizeof(int32_t));
+            memcpy(inFrame->m_analysisData.yuvHist[0], m_curYUVHist[0], HISTOGRAM_BINS *sizeof(int32_t));
+            if (inputPic->colorSpace != X265_CSP_I400)
+            {
+                memcpy(inFrame->m_analysisData.yuvHist[1], m_curYUVHist[1], HISTOGRAM_BINS * sizeof(int32_t));
+                memcpy(inFrame->m_analysisData.yuvHist[2], m_curYUVHist[2], HISTOGRAM_BINS * sizeof(int32_t));
+            }
+        }
         inFrame->m_forceqp   = inputPic->forceqp;
         inFrame->m_param     = (m_reconfigure || m_reconfigureRc) ? m_latestParam : m_param;
         inFrame->m_picStruct = inputPic->picStruct;
@@ -1999,6 +2007,16 @@ int Encoder::encode(const x265_picture* 
                     pic_out->analysisData.poc = pic_out->poc;
                     pic_out->analysisData.sliceType = pic_out->sliceType;
                     pic_out->analysisData.bScenecut = outFrame->m_lowres.bScenecut;
+                    if (m_param->bHistBasedSceneCut)
+                    {
+                        memcpy(pic_out->analysisData.edgeHist, outFrame->m_analysisData.edgeHist, EDGE_BINS * sizeof(int32_t));
+                        memcpy(pic_out->analysisData.yuvHist[0], outFrame->m_analysisData.yuvHist[0], HISTOGRAM_BINS * sizeof(int32_t));
+                        if (pic_out->colorSpace != X265_CSP_I400)
+                        {
+                            memcpy(pic_out->analysisData.yuvHist[1], outFrame->m_analysisData.yuvHist[1], HISTOGRAM_BINS * sizeof(int32_t));
+                            memcpy(pic_out->analysisData.yuvHist[2], outFrame->m_analysisData.yuvHist[2], HISTOGRAM_BINS * sizeof(int32_t));
+                        }
+                    }
                     pic_out->analysisData.satdCost  = outFrame->m_lowres.satdCost;
                     pic_out->analysisData.numCUsInFrame = outFrame->m_analysisData.numCUsInFrame;
                     pic_out->analysisData.numPartitions = outFrame->m_analysisData.numPartitions;
@@ -4312,6 +4330,16 @@ void Encoder::readAnalysisFile(x265_anal
     analysis->frameRecordSize = frameRecordSize;
     X265_FREAD(&analysis->sliceType, sizeof(int), 1, m_analysisFileIn, &(picData->sliceType));
     X265_FREAD(&analysis->bScenecut, sizeof(int), 1, m_analysisFileIn, &(picData->bScenecut));
+    if (m_param->bHistBasedSceneCut)
+    {
+        X265_FREAD(&analysis->edgeHist, sizeof(int32_t), EDGE_BINS, m_analysisFileIn, &m_curEdgeHist);
+        X265_FREAD(&analysis->yuvHist[0], sizeof(int32_t), HISTOGRAM_BINS, m_analysisFileIn, &m_curYUVHist[0]);
+        if (m_param->internalCsp != X265_CSP_I400)
+        {
+            X265_FREAD(&analysis->yuvHist[1], sizeof(int32_t), HISTOGRAM_BINS, m_analysisFileIn, &m_curYUVHist[1]);
+            X265_FREAD(&analysis->yuvHist[2], sizeof(int32_t), HISTOGRAM_BINS, m_analysisFileIn, &m_curYUVHist[2]);
+        }
+    }
     X265_FREAD(&analysis->satdCost, sizeof(int64_t), 1, m_analysisFileIn, &(picData->satdCost));
     X265_FREAD(&numCUsLoad, sizeof(int), 1, m_analysisFileIn, &(picData->numCUsInFrame));
     X265_FREAD(&analysis->numPartitions, sizeof(int), 1, m_analysisFileIn, &(picData->numPartitions));
@@ -4634,6 +4662,16 @@ void Encoder::readAnalysisFile(x265_anal
     analysis->frameRecordSize = frameRecordSize;
     X265_FREAD(&analysis->sliceType, sizeof(int), 1, m_analysisFileIn, &(picData->sliceType));
     X265_FREAD(&analysis->bScenecut, sizeof(int), 1, m_analysisFileIn, &(picData->bScenecut));
+    if (m_param->bHistBasedSceneCut)
+    {
+        X265_FREAD(&analysis->edgeHist, sizeof(int32_t), EDGE_BINS, m_analysisFileIn, &m_curEdgeHist);
+        X265_FREAD(&analysis->yuvHist[0], sizeof(int32_t), HISTOGRAM_BINS, m_analysisFileIn, &m_curYUVHist[0]);
+        if (m_param->internalCsp != X265_CSP_I400)
+        {
+            X265_FREAD(&analysis->yuvHist[1], sizeof(int32_t), HISTOGRAM_BINS, m_analysisFileIn, &m_curYUVHist[1]);
+            X265_FREAD(&analysis->yuvHist[2], sizeof(int32_t), HISTOGRAM_BINS, m_analysisFileIn, &m_curYUVHist[2]);
+        }
+    }
     X265_FREAD(&analysis->satdCost, sizeof(int64_t), 1, m_analysisFileIn, &(picData->satdCost));
     X265_FREAD(&analysis->numCUsInFrame, sizeof(int), 1, m_analysisFileIn, &(picData->numCUsInFrame));
     X265_FREAD(&analysis->numPartitions, sizeof(int), 1, m_analysisFileIn, &(picData->numPartitions));
@@ -5399,6 +5437,17 @@ void Encoder::writeAnalysisFile(x265_ana
     /* calculate frameRecordSize */
     analysis->frameRecordSize = sizeof(analysis->frameRecordSize) + sizeof(depthBytes) + sizeof(analysis->poc) + sizeof(analysis->sliceType) +
                       sizeof(analysis->numCUsInFrame) + sizeof(analysis->numPartitions) + sizeof(analysis->bScenecut) + sizeof(analysis->satdCost);
+    if (m_param->bHistBasedSceneCut)
+    {
+        analysis->frameRecordSize += sizeof(analysis->edgeHist);
+        analysis->frameRecordSize += sizeof(int32_t) * HISTOGRAM_BINS;
+        if (m_param->internalCsp != X265_CSP_I400)
+        {
+            analysis->frameRecordSize += sizeof(int32_t) * HISTOGRAM_BINS;
+            analysis->frameRecordSize += sizeof(int32_t) * HISTOGRAM_BINS;
+        }
+    }
+
     if (analysis->sliceType > X265_TYPE_I)
     {
         numDir = (analysis->sliceType == X265_TYPE_P) ? 1 : 2;
@@ -5543,6 +5592,17 @@ void Encoder::writeAnalysisFile(x265_ana
     X265_FWRITE(&analysis->poc, sizeof(int), 1, m_analysisFileOut);
     X265_FWRITE(&analysis->sliceType, sizeof(int), 1, m_analysisFileOut);
     X265_FWRITE(&analysis->bScenecut, sizeof(int), 1, m_analysisFileOut);
+    if (m_param->bHistBasedSceneCut)
+    {
+        X265_FWRITE(&analysis->edgeHist, sizeof(int32_t), EDGE_BINS, m_analysisFileOut);
+        X265_FWRITE(&analysis->yuvHist[0], sizeof(int32_t), HISTOGRAM_BINS, m_analysisFileOut);
+        if (m_param->internalCsp != X265_CSP_I400)
+        {
+            X265_FWRITE(&analysis->yuvHist[1], sizeof(int32_t), HISTOGRAM_BINS, m_analysisFileOut);
+            X265_FWRITE(&analysis->yuvHist[2], sizeof(int32_t), HISTOGRAM_BINS, m_analysisFileOut);
+        }
+    }
+
     X265_FWRITE(&analysis->satdCost, sizeof(int64_t), 1, m_analysisFileOut);
     X265_FWRITE(&analysis->numCUsInFrame, sizeof(int), 1, m_analysisFileOut);
     X265_FWRITE(&analysis->numPartitions, sizeof(int), 1, m_analysisFileOut);
--- a/source/encoder/encoder.h	Thu May 14 13:00:56 2020 +0530
+++ b/source/encoder/encoder.h	Tue Apr 21 11:04:30 2020 +0530
@@ -256,7 +256,7 @@ public:
     /* For histogram based scene-cut detection */
     pixel*             m_edgePic;
     pixel*             m_inputPic[3];
-    int32_t            m_curUVHist[2][HISTOGRAM_BINS];
+    int32_t            m_curYUVHist[3][HISTOGRAM_BINS];
     int32_t            m_curMaxUVHist[HISTOGRAM_BINS];
     int32_t            m_prevMaxUVHist[HISTOGRAM_BINS];
     int32_t            m_curEdgeHist[2];
--- a/source/x265.h	Thu May 14 13:00:56 2020 +0530
+++ b/source/x265.h	Tue Apr 21 11:04:30 2020 +0530
@@ -204,6 +204,9 @@ typedef struct x265_analysis_distortion_
 }x265_analysis_distortion_data;
 
 #define MAX_NUM_REF 16
+#define EDGE_BINS 2
+#define MAX_HIST_BINS 1024
+
 /* Stores all analysis data for a single frame */
 typedef struct x265_analysis_data
 {
@@ -214,6 +217,8 @@ typedef struct x265_analysis_data
     uint32_t                          numCUsInFrame;
     uint32_t                          numPartitions;
     uint32_t                          depthBytes;
+    int32_t                           edgeHist[EDGE_BINS];
+    int32_t                           yuvHist[3][MAX_HIST_BINS];
     int                               bScenecut;
     x265_weight_param*                wt;
     x265_analysis_inter_data*         interData;