[x265] [PATCH] analysis: introduce analysis refinement level for analysis save/load feature

sagar at multicorewareinc.com sagar at multicorewareinc.com
Tue Apr 12 14:35:50 CEST 2016


# HG changeset patch
# User Sagar Kotecha<sagar at multicorewareinc.com>
# Date 1460440996 -19800
#      Tue Apr 12 11:33:16 2016 +0530
# Node ID 710856d0242825e49b7dbf967d9b715c4b0e8c39
# Parent  40afead3177d7c128066334bfe075042388e86b0
analysis: introduce analysis refinement level for analysis save/load feature

Amount of information stored/reused is distributed across levels.
Higher the value, Lesser the information stored/reused.

diff -r 40afead3177d -r 710856d02428 doc/reST/cli.rst
--- a/doc/reST/cli.rst	Sat Apr 09 19:32:28 2016 +0530
+++ b/doc/reST/cli.rst	Tue Apr 12 11:33:16 2016 +0530
@@ -791,6 +791,27 @@
 
 	**Values:** off(0), save(1): dump analysis data, load(2): read analysis data
 
+.. option:: --analysis-refine-level <1..5>
+
+	Amount of information stored/reused in :option:`--analysis-mode` is distributed across levels.
+	Higher the value, Lesser the information stored/reused, Slower the encode. Default 5.
+	
+	Note that --analysis-refine-level must be paired with analysis-mode.
+
+	+-------+---------------------------------------------------------------+
+	| Level | Description                                                   |
+	+=======+===============================================================+
+	| 1     | Currently same as 3                                           |
+	+-------+---------------------------------------------------------------+
+	| 2     | Currently same as 3                                           |
+	+-------+---------------------------------------------------------------+
+	| 3     | Lookahead information, Intra and inter modes, ref's, rect-amp |
+	+-------+---------------------------------------------------------------+
+	| 4     | Lookahead information, Intra and inter modes, ref's           |
+	+-------+---------------------------------------------------------------+
+	| 5     | Lookahead information                                         |
+	+-------+---------------------------------------------------------------+
+
 .. option:: --analysis-file <filename>
 
 	Specify a filename for analysis data (see :option:`--analysis-mode`)
diff -r 40afead3177d -r 710856d02428 source/CMakeLists.txt
--- a/source/CMakeLists.txt	Sat Apr 09 19:32:28 2016 +0530
+++ b/source/CMakeLists.txt	Tue Apr 12 11:33:16 2016 +0530
@@ -30,7 +30,7 @@
 mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)
 
 # X265_BUILD must be incremented each time the public API is changed
-set(X265_BUILD 83)
+set(X265_BUILD 84)
 configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
                "${PROJECT_BINARY_DIR}/x265.def")
 configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff -r 40afead3177d -r 710856d02428 source/common/param.cpp
--- a/source/common/param.cpp	Sat Apr 09 19:32:28 2016 +0530
+++ b/source/common/param.cpp	Tue Apr 12 11:33:16 2016 +0530
@@ -188,6 +188,7 @@
     param->psyRd = 2.0;
     param->psyRdoq = 0.0;
     param->analysisMode = 0;
+    param->analysisRefineLevel = 0;
     param->analysisFileName = NULL;
     param->bIntraInBFrames = 0;
     param->bLossless = 0;
@@ -787,6 +788,7 @@
     OPT("me")        p->searchMethod = parseName(value, x265_motion_est_names, bError);
     OPT("cutree")    p->rc.cuTree = atobool(value);
     OPT("slow-firstpass") p->rc.bEnableSlowFirstPass = atobool(value);
+    OPT("analysis-refine-level") p->analysisRefineLevel = atoi(value);
     OPT("strict-cbr")
     {
         p->rc.bStrictCbr = atobool(value);
@@ -1202,6 +1204,7 @@
           "Strict-cbr cannot be applied without specifying target bitrate or vbv bufsize");
     CHECK(param->analysisMode && (param->analysisMode < X265_ANALYSIS_OFF || param->analysisMode > X265_ANALYSIS_LOAD),
         "Invalid analysis mode. Analysis mode 0: OFF 1: SAVE : 2 LOAD");
+    CHECK((param->analysisMode == X265_ANALYSIS_OFF) && param->analysisRefineLevel, "Provide analysis mode");
     return check_failed;
 }
 
diff -r 40afead3177d -r 710856d02428 source/encoder/analysis.cpp
--- a/source/encoder/analysis.cpp	Sat Apr 09 19:32:28 2016 +0530
+++ b/source/encoder/analysis.cpp	Tue Apr 12 11:33:16 2016 +0530
@@ -142,15 +142,18 @@
     m_modeDepth[0].fencYuv.copyFromPicYuv(*m_frame->m_fencPic, ctu.m_cuAddr, 0);
 
     uint32_t numPartition = ctu.m_numPartitions;
-    if (m_param->analysisMode && m_slice->m_sliceType != I_SLICE)
+    if (m_param->analysisRefineLevel != 5 && m_param->analysisMode && m_slice->m_sliceType != I_SLICE)
     {
         int numPredDir = m_slice->isInterP() ? 1 : 2;
         m_reuseInterDataCTU = (analysis_inter_data*)m_frame->m_analysisData.interData;
         m_reuseRef = &m_reuseInterDataCTU->ref[ctu.m_cuAddr * X265_MAX_PRED_MODE_PER_CTU * numPredDir];
-        m_reuseDepth = &m_reuseInterDataCTU->depth[ctu.m_cuAddr * ctu.m_numPartitions];
+        m_reuseDepth = &m_reuseInterDataCTU->depth[ctu.m_cuAddr * ctu.m_numPartitions];        
         m_reuseModes = &m_reuseInterDataCTU->modes[ctu.m_cuAddr * ctu.m_numPartitions];
-        m_reusePartSize = &m_reuseInterDataCTU->partSize[ctu.m_cuAddr * ctu.m_numPartitions];
-        m_reuseMergeFlag = &m_reuseInterDataCTU->mergeFlag[ctu.m_cuAddr * ctu.m_numPartitions];
+        if (m_param->analysisRefineLevel < 4)
+        {
+            m_reusePartSize = &m_reuseInterDataCTU->partSize[ctu.m_cuAddr * ctu.m_numPartitions];
+            m_reuseMergeFlag = &m_reuseInterDataCTU->mergeFlag[ctu.m_cuAddr * ctu.m_numPartitions];
+        }
         if (m_param->analysisMode == X265_ANALYSIS_SAVE)
             for (int i = 0; i < X265_MAX_PRED_MODE_PER_CTU * numPredDir; i++)
                 m_reuseRef[i] = -1;
@@ -160,7 +163,7 @@
     if (m_slice->m_sliceType == I_SLICE)
     {
         analysis_intra_data* intraDataCTU = (analysis_intra_data*)m_frame->m_analysisData.intraData;
-        if (m_param->analysisMode == X265_ANALYSIS_LOAD)
+        if (m_param->analysisRefineLevel != 5 && m_param->analysisMode == X265_ANALYSIS_LOAD)
         {
             memcpy(ctu.m_cuDepth, &intraDataCTU->depth[ctu.m_cuAddr * numPartition], sizeof(uint8_t) * numPartition);
             memcpy(ctu.m_lumaIntraDir, &intraDataCTU->modes[ctu.m_cuAddr * numPartition], sizeof(uint8_t) * numPartition);
@@ -905,7 +908,7 @@
     }
 
     bool foundSkip = false;
-    if (m_param->analysisMode == X265_ANALYSIS_LOAD)
+    if (m_param->analysisRefineLevel != 5 && m_param->analysisMode == X265_ANALYSIS_LOAD)
     {
         if (mightNotSplit && depth == m_reuseDepth[cuGeom.absPartIdx])
         {
@@ -919,7 +922,8 @@
                 if (m_param->rdLevel)
                     earlyskip = md.bestMode && m_param->bEnableEarlySkip;
             }
-            if (m_reusePartSize[cuGeom.absPartIdx] == SIZE_2Nx2N)
+
+            if ((m_param->analysisRefineLevel < 4) && m_reusePartSize[cuGeom.absPartIdx] == SIZE_2Nx2N)
             {
                 if (m_reuseModes[cuGeom.absPartIdx] != MODE_INTRA  && m_reuseModes[cuGeom.absPartIdx] != 4)
                 {
@@ -1410,7 +1414,7 @@
         md.pred[PRED_2Nx2N].rdCost = 0;
     }
 
-    if (m_param->analysisMode == X265_ANALYSIS_LOAD)
+    if (m_param->analysisRefineLevel != 5 && m_param->analysisMode == X265_ANALYSIS_LOAD)
     {
         if (mightNotSplit && depth == m_reuseDepth[cuGeom.absPartIdx])
         {
@@ -1423,7 +1427,7 @@
                 foundSkip = true;
                 earlyskip = !!m_param->bEnableEarlySkip;
             }
-            if (m_reusePartSize[cuGeom.absPartIdx] == SIZE_2Nx2N)
+            if (m_param->analysisRefineLevel < 4 && m_reusePartSize[cuGeom.absPartIdx] == SIZE_2Nx2N)
                 skipRectAmp = true && !!md.bestMode;
         }
     }
@@ -2106,7 +2110,7 @@
     interMode.cu.setPredModeSubParts(MODE_INTER);
     int numPredDir = m_slice->isInterP() ? 1 : 2;
 
-    if (m_param->analysisMode == X265_ANALYSIS_LOAD && m_reuseInterDataCTU)
+    if (m_param->analysisRefineLevel != 5 && m_param->analysisMode == X265_ANALYSIS_LOAD && m_reuseInterDataCTU)
     {
         int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2;
         int index = 0;
@@ -2133,7 +2137,7 @@
     }
     interMode.sa8dCost = m_rdCost.calcRdSADCost((uint32_t)interMode.distortion, interMode.sa8dBits);
 
-    if (m_param->analysisMode == X265_ANALYSIS_SAVE && m_reuseInterDataCTU)
+    if (m_param->analysisRefineLevel != 5 && m_param->analysisMode == X265_ANALYSIS_SAVE && m_reuseInterDataCTU)
     {
         int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2;
         int index = 0;
@@ -2155,7 +2159,7 @@
     interMode.cu.setPredModeSubParts(MODE_INTER);
     int numPredDir = m_slice->isInterP() ? 1 : 2;
 
-    if (m_param->analysisMode == X265_ANALYSIS_LOAD && m_reuseInterDataCTU)
+    if (m_param->analysisRefineLevel != 5 && m_param->analysisMode == X265_ANALYSIS_LOAD && m_reuseInterDataCTU)
     {
         int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2;
         int index = 0;
@@ -2173,7 +2177,7 @@
     /* predInterSearch sets interMode.sa8dBits, but this is ignored */
     encodeResAndCalcRdInterCU(interMode, cuGeom);
 
-    if (m_param->analysisMode == X265_ANALYSIS_SAVE && m_reuseInterDataCTU)
+    if (m_param->analysisRefineLevel != 5 && m_param->analysisMode == X265_ANALYSIS_SAVE && m_reuseInterDataCTU)
     {
         int refOffset = cuGeom.geomRecurId * 16 * numPredDir + partSize * numPredDir * 2;
         int index = 0;
diff -r 40afead3177d -r 710856d02428 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Sat Apr 09 19:32:28 2016 +0530
+++ b/source/encoder/encoder.cpp	Tue Apr 12 11:33:16 2016 +0530
@@ -328,6 +328,9 @@
             x265_log(NULL, X265_LOG_ERROR, "Analysis load/save: failed to open file %s\n", name);
             m_aborted = true;
         }
+
+        if (!m_param->analysisRefineLevel)
+            m_param->analysisRefineLevel = 5;
     }
 
     m_bZeroLatency = !m_param->bframes && !m_param->lookaheadDepth && m_param->frameNumThreads == 1;
@@ -1863,6 +1866,7 @@
     if (p->bDistributeModeAnalysis && p->analysisMode)
     {
         p->analysisMode = X265_ANALYSIS_OFF;
+        p->analysisRefineLevel = 0;
         x265_log(p, X265_LOG_WARNING, "Analysis save and load mode not supported for distributed mode analysis\n");
     }
     if (p->bEnableRdRefine && (p->rdLevel < 5 || !p->rc.aqMode))
@@ -1977,26 +1981,38 @@
 {
     X265_CHECK(analysis->sliceType, "invalid slice type\n");
     analysis->interData = analysis->intraData = NULL;
+
+
     if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
     {
-        analysis_intra_data *intraData = (analysis_intra_data*)analysis->intraData;
-        CHECKED_MALLOC_ZERO(intraData, analysis_intra_data, 1);
-        CHECKED_MALLOC(intraData->depth, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
-        CHECKED_MALLOC(intraData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
-        CHECKED_MALLOC(intraData->partSizes, char, analysis->numPartitions * analysis->numCUsInFrame);
-        CHECKED_MALLOC(intraData->chromaModes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
-        analysis->intraData = intraData;
+        if (m_param->analysisRefineLevel != 5)
+        {
+            analysis_intra_data *intraData = (analysis_intra_data*)analysis->intraData;
+            CHECKED_MALLOC_ZERO(intraData, analysis_intra_data, 1);
+            CHECKED_MALLOC(intraData->depth, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
+            CHECKED_MALLOC(intraData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
+            CHECKED_MALLOC(intraData->partSizes, char, analysis->numPartitions * analysis->numCUsInFrame);
+            CHECKED_MALLOC(intraData->chromaModes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
+            analysis->intraData = intraData;
+        }
     }
     else
     {
+
         int numDir = analysis->sliceType == X265_TYPE_P ? 1 : 2;
         analysis_inter_data *interData = (analysis_inter_data*)analysis->interData;
         CHECKED_MALLOC_ZERO(interData, analysis_inter_data, 1);
-        CHECKED_MALLOC_ZERO(interData->ref, int32_t, analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir);
-        CHECKED_MALLOC(interData->depth, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
-        CHECKED_MALLOC(interData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
-        CHECKED_MALLOC(interData->partSize, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
-        CHECKED_MALLOC(interData->mergeFlag, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
+        if (m_param->analysisRefineLevel != 5)
+        {
+            CHECKED_MALLOC_ZERO(interData->ref, int32_t, analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir);
+            CHECKED_MALLOC(interData->depth, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
+            CHECKED_MALLOC(interData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
+            if (m_param->analysisRefineLevel < 4)
+            {
+                CHECKED_MALLOC(interData->partSize, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
+                CHECKED_MALLOC(interData->mergeFlag, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);
+            }
+        }
         CHECKED_MALLOC_ZERO(interData->wt, WeightParam, 3 * numDir);
         analysis->interData = interData;
     }
@@ -2017,7 +2033,7 @@
         X265_FREE(((analysis_intra_data*)analysis->intraData)->chromaModes);
         X265_FREE(analysis->intraData);
     }
-    else
+    else if (analysis->interData)
     {
         X265_FREE(((analysis_inter_data*)analysis->interData)->ref);
         X265_FREE(((analysis_inter_data*)analysis->interData)->depth);
@@ -2035,10 +2051,10 @@
 #define X265_FREAD(val, size, readSize, fileOffset)\
     if (fread(val, size, readSize, fileOffset) != readSize)\
     {\
-        x265_log(NULL, X265_LOG_ERROR, "Error reading analysis data\n");\
-        freeAnalysis(analysis);\
-        m_aborted = true;\
-        return;\
+        x265_log(NULL, X265_LOG_ERROR, "Error reading analysis data\n"); \
+        freeAnalysis(analysis); \
+        m_aborted = true; \
+        return; \
     }\
 
     static uint64_t consumedBytes = 0;
@@ -2046,7 +2062,8 @@
     uint32_t depthBytes = 0;
     fseeko(m_analysisFile, totalConsumedBytes, SEEK_SET);
 
-    int poc; uint32_t frameRecordSize;
+    int poc, refineLevel;
+    uint32_t frameRecordSize;
     X265_FREAD(&frameRecordSize, sizeof(uint32_t), 1, m_analysisFile);
     X265_FREAD(&depthBytes, sizeof(uint32_t), 1, m_analysisFile);
     X265_FREAD(&poc, sizeof(int), 1, m_analysisFile);
@@ -2078,63 +2095,96 @@
     X265_FREAD(&analysis->satdCost, sizeof(int64_t), 1, m_analysisFile);
     X265_FREAD(&analysis->numCUsInFrame, sizeof(int), 1, m_analysisFile);
     X265_FREAD(&analysis->numPartitions, sizeof(int), 1, m_analysisFile);
+    X265_FREAD(&refineLevel, sizeof(int), 1, m_analysisFile);
+
+    if (refineLevel != m_param->analysisRefineLevel)
+    {
+        x265_log(NULL, X265_LOG_ERROR, "analysis refine level between save-load must match\n");
+        freeAnalysis(analysis);
+        m_aborted = true;
+        return;
+    }
+
+    int numDir;
+    if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
+    {
+        numDir = 0;
+        consumedBytes += frameRecordSize;
+    }
+    else
+        numDir = analysis->sliceType == X265_TYPE_P ? 1 : 2;
 
     /* Memory is allocated for inter and intra analysis data based on the slicetype */
     allocAnalysis(analysis);
 
-    if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
+    if (!numDir)
     {
-        uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSizes = NULL;
+        if (refineLevel < 5)
+        {
+            uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSizes = NULL;
 
-        tempBuf = X265_MALLOC(uint8_t, depthBytes * 3);
-        X265_FREAD(tempBuf, sizeof(uint8_t), depthBytes * 3, m_analysisFile);
+            tempBuf = X265_MALLOC(uint8_t, depthBytes * 3);
+            X265_FREAD(tempBuf, sizeof(uint8_t), depthBytes * 3, m_analysisFile);
 
-        depthBuf = tempBuf;
-        modeBuf = tempBuf + depthBytes;
-        partSizes = tempBuf + 2 * depthBytes;
+            depthBuf = tempBuf;
+            modeBuf = tempBuf + depthBytes;
+            partSizes = tempBuf + 2 * depthBytes;
 
-        size_t count = 0;
-        for (uint32_t d = 0; d < depthBytes; d++)
+            size_t count = 0;
+            for (uint32_t d = 0; d < depthBytes; d++)
+            {
+                int bytes = analysis->numPartitions >> (depthBuf[d] * 2);
+                memset(&((analysis_intra_data *)analysis->intraData)->depth[count], depthBuf[d], bytes);
+                memset(&((analysis_intra_data *)analysis->intraData)->chromaModes[count], modeBuf[d], bytes);
+                memset(&((analysis_intra_data *)analysis->intraData)->partSizes[count], partSizes[d], bytes);
+                count += bytes;
+            }
+            X265_FREAD(((analysis_intra_data *)analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFile);
+            X265_FREE(tempBuf);
+        }
+        analysis->sliceType = X265_TYPE_I;
+    }
+    else
+    {
+        if (refineLevel < 5)
         {
-            int bytes = analysis->numPartitions >> (depthBuf[d] * 2);
-            memset(&((analysis_intra_data *)analysis->intraData)->depth[count], depthBuf[d], bytes);
-            memset(&((analysis_intra_data *)analysis->intraData)->chromaModes[count], modeBuf[d], bytes);
-            memset(&((analysis_intra_data *)analysis->intraData)->partSizes[count], partSizes[d], bytes);
-            count += bytes;
+            int numSharedData = 4;
+            if (m_param->analysisRefineLevel == 4)
+                numSharedData = 2;
+            uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSize = NULL, *mergeFlag = NULL;
+
+            tempBuf = X265_MALLOC(uint8_t, depthBytes * numSharedData);
+            X265_FREAD(tempBuf, sizeof(uint8_t), depthBytes * numSharedData, m_analysisFile);
+
+            depthBuf = tempBuf;
+            modeBuf = tempBuf + depthBytes;
+
+            if (m_param->analysisRefineLevel < 4)
+            {
+                partSize = modeBuf + depthBytes;
+                mergeFlag = partSize + depthBytes;
+            }
+
+            size_t count = 0;
+            for (uint32_t d = 0; d < depthBytes; d++)
+            {
+                int bytes = analysis->numPartitions >> (depthBuf[d] * 2);
+                memset(&((analysis_inter_data *)analysis->interData)->depth[count], depthBuf[d], bytes);
+                memset(&((analysis_inter_data *)analysis->interData)->modes[count], modeBuf[d], bytes);
+                if (m_param->analysisRefineLevel < 4)
+                {
+                    memset(&((analysis_inter_data *)analysis->interData)->partSize[count], partSize[d], bytes);
+                    memset(&((analysis_inter_data *)analysis->interData)->mergeFlag[count], mergeFlag[d], bytes);
+                }
+                count += bytes;
+            }
+            X265_FREE(tempBuf);
+            X265_FREAD(((analysis_inter_data *)analysis->interData)->ref, sizeof(int32_t), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir, m_analysisFile);
         }
-        X265_FREAD(((analysis_intra_data *)analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFile);
-        X265_FREE(tempBuf);
-        analysis->sliceType = X265_TYPE_I;
-        consumedBytes += frameRecordSize;
     }
 
-    else
+    if (numDir)
     {
-        uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSize = NULL, *mergeFlag = NULL;
-
-        tempBuf = X265_MALLOC(uint8_t, depthBytes * 4);
-        X265_FREAD(tempBuf, sizeof(uint8_t), depthBytes * 4, m_analysisFile);
-
-        depthBuf = tempBuf;
-        modeBuf = tempBuf + depthBytes;
-        partSize = modeBuf + depthBytes;
-        mergeFlag = partSize + depthBytes;
-
-        size_t count = 0;
-        for (uint32_t d = 0; d < depthBytes; d++)
-        {
-            int bytes = analysis->numPartitions >> (depthBuf[d] * 2);
-            memset(&((analysis_inter_data *)analysis->interData)->depth[count], depthBuf[d], bytes);
-            memset(&((analysis_inter_data *)analysis->interData)->modes[count], modeBuf[d], bytes);
-            memset(&((analysis_inter_data *)analysis->interData)->partSize[count], partSize[d], bytes);
-            memset(&((analysis_inter_data *)analysis->interData)->mergeFlag[count], mergeFlag[d], bytes);
-            count += bytes;
-        }
-
-        X265_FREE(tempBuf);
-
-        int numDir = analysis->sliceType == X265_TYPE_P ? 1 : 2;
-        X265_FREAD(((analysis_inter_data *)analysis->interData)->ref, sizeof(int32_t), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir, m_analysisFile);
         uint32_t numPlanes = m_param->internalCsp == X265_CSP_I400 ? 1 : 3;
         X265_FREAD(((analysis_inter_data *)analysis->interData)->wt, sizeof(WeightParam), numPlanes * numDir, m_analysisFile);
         consumedBytes += frameRecordSize;
@@ -2156,80 +2206,91 @@
         return;\
     }\
 
+    int numDir;
+    if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
+        numDir = 0;
+    else
+        numDir = analysis->sliceType == X265_TYPE_P ? 1 : 2;
+
     uint32_t depthBytes = 0;
-    if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
+    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) + sizeof(m_param->analysisRefineLevel);
+
+    int numSharedData = 4;
+    if (m_param->analysisRefineLevel == 4)
+        numSharedData = 2;
+
+    if (m_param->analysisRefineLevel != 5)
     {
-        for (uint32_t cuAddr = 0; cuAddr < analysis->numCUsInFrame; cuAddr++)
+        if (!numDir)
         {
-            uint8_t depth = 0;
-            uint8_t mode = 0;
-            uint8_t partSize = 0;
+            for (uint32_t cuAddr = 0; cuAddr < analysis->numCUsInFrame; cuAddr++)
+            {
+                uint8_t depth = 0;
+                uint8_t mode = 0;
+                uint8_t partSize = 0;
 
-            CUData* ctu = curEncData.getPicCTU(cuAddr);
-            analysis_intra_data* intraDataCTU = (analysis_intra_data*)analysis->intraData;
+                CUData* ctu = curEncData.getPicCTU(cuAddr);
+                analysis_intra_data* intraDataCTU = (analysis_intra_data*)analysis->intraData;
 
-            for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions; depthBytes++)
+                for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions; depthBytes++)
+                {
+                    depth = ctu->m_cuDepth[absPartIdx];
+                    intraDataCTU->depth[depthBytes] = depth;
+
+                    mode = ctu->m_chromaIntraDir[absPartIdx];
+                    intraDataCTU->chromaModes[depthBytes] = mode;
+
+                    partSize = ctu->m_partSize[absPartIdx];
+                    intraDataCTU->partSizes[depthBytes] = partSize;
+
+                    absPartIdx += ctu->m_numPartitions >> (depth * 2);
+                }
+                memcpy(&intraDataCTU->modes[ctu->m_cuAddr * ctu->m_numPartitions], ctu->m_lumaIntraDir, sizeof(uint8_t)* ctu->m_numPartitions);
+            }
+            analysis->frameRecordSize += sizeof(uint8_t)* analysis->numCUsInFrame * analysis->numPartitions + depthBytes * 3;
+        }
+        else
+        {
+            for (uint32_t cuAddr = 0; cuAddr < analysis->numCUsInFrame; cuAddr++)
             {
-                depth = ctu->m_cuDepth[absPartIdx];
-                intraDataCTU->depth[depthBytes] = depth;
+                uint8_t depth = 0;
+                uint8_t predMode = 0;
+                uint8_t partSize = 0;
+                uint8_t mergeFlag = 0;
 
-                mode = ctu->m_chromaIntraDir[absPartIdx];
-                intraDataCTU->chromaModes[depthBytes] = mode;
+                CUData* ctu = curEncData.getPicCTU(cuAddr);
+                analysis_inter_data* interDataCTU = (analysis_inter_data*)analysis->interData;
 
-                partSize = ctu->m_partSize[absPartIdx];
-                intraDataCTU->partSizes[depthBytes] = partSize;
+                for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions; depthBytes++)
+                {
+                    depth = ctu->m_cuDepth[absPartIdx];
+                    interDataCTU->depth[depthBytes] = depth;
 
-                absPartIdx += ctu->m_numPartitions >> (depth * 2);
+                    predMode = ctu->m_predMode[absPartIdx];
+                    if (ctu->m_refIdx[1][absPartIdx] != -1)
+                        predMode = 4; // used as indiacator if the block is coded as bidir
+
+                    interDataCTU->modes[depthBytes] = predMode;
+
+                    if (m_param->analysisRefineLevel < 4)
+                    {
+                        partSize = ctu->m_partSize[absPartIdx];
+                        interDataCTU->partSize[depthBytes] = partSize;
+
+                        mergeFlag = ctu->m_mergeFlag[absPartIdx];
+                        interDataCTU->mergeFlag[depthBytes] = mergeFlag;
+                    }
+
+                    absPartIdx += ctu->m_numPartitions >> (depth * 2);
+                }
             }
-            memcpy(&intraDataCTU->modes[ctu->m_cuAddr * ctu->m_numPartitions], ctu->m_lumaIntraDir, sizeof(uint8_t)* ctu->m_numPartitions);
+            analysis->frameRecordSize += depthBytes * numSharedData;
+            analysis->frameRecordSize += sizeof(int32_t)* analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir;
         }
-    }
-    else
-    {
-        for (uint32_t cuAddr = 0; cuAddr < analysis->numCUsInFrame; cuAddr++)
-        {
-            uint8_t depth = 0;
-            uint8_t predMode = 0;
-            uint8_t partSize = 0;
-            uint8_t mergeFlag = 0;
+   }
+    analysis->frameRecordSize += sizeof(WeightParam) * 3 * numDir;
 
-            CUData* ctu = curEncData.getPicCTU(cuAddr);
-            analysis_inter_data* interDataCTU = (analysis_inter_data*)analysis->interData;
-
-            for (uint32_t absPartIdx = 0; absPartIdx < ctu->m_numPartitions; depthBytes++)
-            {
-                depth = ctu->m_cuDepth[absPartIdx];
-                interDataCTU->depth[depthBytes] = depth;
-
-                predMode = ctu->m_predMode[absPartIdx];
-                if (ctu->m_refIdx[1][absPartIdx] != -1)
-                    predMode = 4; // used as indiacator if the block is coded as bidir
-
-                interDataCTU->modes[depthBytes] = predMode;
-
-                partSize = ctu->m_partSize[absPartIdx];
-                interDataCTU->partSize[depthBytes] = partSize;
-
-                mergeFlag = ctu->m_mergeFlag[absPartIdx];
-                interDataCTU->mergeFlag[depthBytes] = mergeFlag;
-
-                absPartIdx += ctu->m_numPartitions >> (depth * 2);
-            }
-        }
-    }
-
-    /* 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 (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
-        analysis->frameRecordSize += sizeof(uint8_t)* analysis->numCUsInFrame * analysis->numPartitions + depthBytes * 3;
-    else
-    {
-        int numDir = (analysis->sliceType == X265_TYPE_P) ? 1 : 2;
-        analysis->frameRecordSize += depthBytes * 4;
-        analysis->frameRecordSize += sizeof(int32_t)* analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir;
-        analysis->frameRecordSize += sizeof(WeightParam)* 3 * numDir;
-    }
     X265_FWRITE(&analysis->frameRecordSize, sizeof(uint32_t), 1, m_analysisFile);
     X265_FWRITE(&depthBytes, sizeof(uint32_t), 1, m_analysisFile);
     X265_FWRITE(&analysis->poc, sizeof(int), 1, m_analysisFile);
@@ -2238,25 +2299,36 @@
     X265_FWRITE(&analysis->satdCost, sizeof(int64_t), 1, m_analysisFile);
     X265_FWRITE(&analysis->numCUsInFrame, sizeof(int), 1, m_analysisFile);
     X265_FWRITE(&analysis->numPartitions, sizeof(int), 1, m_analysisFile);
+    X265_FWRITE(&m_param->analysisRefineLevel, sizeof(int), 1, m_analysisFile);
 
-    if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
+    if (m_param->analysisRefineLevel != 5)
     {
-        X265_FWRITE(((analysis_intra_data*)analysis->intraData)->depth, sizeof(uint8_t), depthBytes, m_analysisFile);
-        X265_FWRITE(((analysis_intra_data*)analysis->intraData)->chromaModes, sizeof(uint8_t), depthBytes, m_analysisFile);
-        X265_FWRITE(((analysis_intra_data*)analysis->intraData)->partSizes, sizeof(char), depthBytes, m_analysisFile);
-        X265_FWRITE(((analysis_intra_data*)analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFile);
+        if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)
+        {
+            X265_FWRITE(((analysis_intra_data*)analysis->intraData)->depth, sizeof(uint8_t), depthBytes, m_analysisFile);
+            X265_FWRITE(((analysis_intra_data*)analysis->intraData)->chromaModes, sizeof(uint8_t), depthBytes, m_analysisFile);
+            X265_FWRITE(((analysis_intra_data*)analysis->intraData)->partSizes, sizeof(char), depthBytes, m_analysisFile);
+            X265_FWRITE(((analysis_intra_data*)analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFile);
+        }
+        else
+        {
+            X265_FWRITE(((analysis_inter_data*)analysis->interData)->depth, sizeof(uint8_t), depthBytes, m_analysisFile);
+            X265_FWRITE(((analysis_inter_data*)analysis->interData)->modes, sizeof(uint8_t), depthBytes, m_analysisFile); 
+            if (m_param->analysisRefineLevel < 4)
+            {
+                X265_FWRITE(((analysis_inter_data*)analysis->interData)->partSize, sizeof(uint8_t), depthBytes, m_analysisFile);
+                X265_FWRITE(((analysis_inter_data*)analysis->interData)->mergeFlag, sizeof(uint8_t), depthBytes, m_analysisFile);
+            }
+            X265_FWRITE(((analysis_inter_data*)analysis->interData)->ref, sizeof(int32_t), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir, m_analysisFile);
+        }
     }
-    else
+
+    if (numDir)
     {
-        int numDir = analysis->sliceType == X265_TYPE_P ? 1 : 2;
-        X265_FWRITE(((analysis_inter_data*)analysis->interData)->depth, sizeof(uint8_t), depthBytes, m_analysisFile);
-        X265_FWRITE(((analysis_inter_data*)analysis->interData)->modes, sizeof(uint8_t), depthBytes, m_analysisFile);
-        X265_FWRITE(((analysis_inter_data*)analysis->interData)->partSize, sizeof(uint8_t), depthBytes, m_analysisFile);
-        X265_FWRITE(((analysis_inter_data*)analysis->interData)->mergeFlag, sizeof(uint8_t), depthBytes, m_analysisFile);
-        X265_FWRITE(((analysis_inter_data*)analysis->interData)->ref, sizeof(int32_t), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir, m_analysisFile);
         uint32_t numPlanes = m_param->internalCsp == X265_CSP_I400 ? 1 : 3;
         X265_FWRITE(((analysis_inter_data*)analysis->interData)->wt, sizeof(WeightParam), numPlanes * numDir, m_analysisFile);
     }
+
 #undef X265_FWRITE
 }
 
diff -r 40afead3177d -r 710856d02428 source/encoder/search.cpp
--- a/source/encoder/search.cpp	Sat Apr 09 19:32:28 2016 +0530
+++ b/source/encoder/search.cpp	Tue Apr 12 11:33:16 2016 +0530
@@ -2083,7 +2083,7 @@
         cu.getNeighbourMV(puIdx, pu.puAbsPartIdx, interMode.interNeighbours);
 
         /* Uni-directional prediction */
-        if (m_param->analysisMode == X265_ANALYSIS_LOAD)
+        if (m_param->analysisRefineLevel != 5 && m_param->analysisMode == X265_ANALYSIS_LOAD)
         {
             for (int list = 0; list < numPredDir; list++)
             {
diff -r 40afead3177d -r 710856d02428 source/x265.h
--- a/source/x265.h	Sat Apr 09 19:32:28 2016 +0530
+++ b/source/x265.h	Tue Apr 12 11:33:16 2016 +0530
@@ -992,6 +992,11 @@
      * the encoder must perform. Default X265_ANALYSIS_OFF */
     int       analysisMode;
 
+    /* A value between 1 and 5 (both inclusive) which determines the level of
+    * information stored/reused between save and load mode. Higher the analysis refine
+    * level lesser the informtion stored/reused. Default is 5 */
+    int       analysisRefineLevel;
+
     /* Filename for analysisMode save/load. Default name is "x265_analysis.dat" */
     const char* analysisFileName;
 
diff -r 40afead3177d -r 710856d02428 source/x265cli.h
--- a/source/x265cli.h	Sat Apr 09 19:32:28 2016 +0530
+++ b/source/x265cli.h	Tue Apr 12 11:33:16 2016 +0530
@@ -222,6 +222,7 @@
     { "slow-firstpass",       no_argument, NULL, 0 },
     { "no-slow-firstpass",    no_argument, NULL, 0 },
     { "analysis-mode",  required_argument, NULL, 0 },
+    { "analysis-refine-level", required_argument, NULL, 0 },
     { "analysis-file",  required_argument, NULL, 0 },
     { "strict-cbr",           no_argument, NULL, 0 },
     { "temporal-layers",      no_argument, NULL, 0 },
@@ -375,6 +376,7 @@
     H0("   --[no-]slow-firstpass         Enable a slow first pass in a multipass rate control mode. Default %s\n", OPT(param->rc.bEnableSlowFirstPass));
     H0("   --[no-]strict-cbr             Enable stricter conditions and tolerance for bitrate deviations in CBR mode. Default %s\n", OPT(param->rc.bStrictCbr));
     H0("   --analysis-mode <string|int>  save - Dump analysis info into file, load - Load analysis buffers from the file. Default %d\n", param->analysisMode);
+    H0("   --analysis-refine-level <1..5>Level of information stored/reused in analysis save/load mode 1:least....5:most. Default %d\n", param->analysisRefineLevel);
     H0("   --analysis-file <filename>    Specify file name used for either dumping or reading analysis data.\n");
     H0("   --aq-mode <integer>           Mode for Adaptive Quantization - 0:none 1:uniform AQ 2:auto variance 3:auto variance with bias to dark scenes. Default %d\n", param->rc.aqMode);
     H0("   --aq-strength <float>         Reduces blocking and blurring in flat and textured areas (0 to 3.0). Default %.2f\n", param->rc.aqStrength);


More information about the x265-devel mailing list