<div dir="ltr">From cd1f18eb201c50a63bf15a5ac1d972ae1ca8ceb4 Mon Sep 17 00:00:00 2001<br>From: Srikanth Kurapati <<a href="mailto:srikanth.kurapati@multicorewareinc.com">srikanth.kurapati@multicorewareinc.com</a>><br>Date: Wed, 30 Dec 2020 17:00:08 +0530<br>Subject: [PATCH] fix: corrects output mismatch for cutree enabled analysis<br> save/load encodes with reuse-levels in between 1 to 10 for similar encoder<br> settings.<br><br>- updates the documentation for the analysis save/load options.<br>---<br> doc/reST/cli.rst             |  34 ++++-----<br> source/abrEncApp.cpp         |  16 ++++-<br> source/common/common.h       |   4 ++<br> source/common/cudata.h       |   2 +-<br> source/encoder/analysis.cpp  |  32 ++++++++-<br> source/encoder/analysis.h    |   1 +<br> source/encoder/api.cpp       |  28 +++++++-<br> source/encoder/encoder.cpp   | 130 ++++++++++++++++++++++++++---------<br> source/encoder/slicetype.cpp |   2 +-<br> source/x265.h                |   4 +-<br> 10 files changed, 190 insertions(+), 63 deletions(-)<br><br>diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst<br>index 94c2a5175..bb1396e8a 100755<br>--- a/doc/reST/cli.rst<br>+++ b/doc/reST/cli.rst<br>@@ -934,14 +934,14 @@ will not reuse analysis if slice type parameters do not match.<br> .. option:: --analysis-save <filename><br> <br>      Encoder outputs analysis information of each frame. Analysis data from save mode is<br>-  written to the file specified. Requires cutree, pmode to be off. Default disabled.<br>+   written to the file specified. Requires pmode to be off. Default disabled.<br>   <br>     The amount of analysis data stored is determined by :option:`--analysis-save-reuse-level`.<br>   <br> .. option:: --analysis-load <filename><br> <br>         Encoder reuses analysis information from the file specified. By reading the analysis data written by<br>- an earlier encode of the same sequence, substantial redundant work may be avoided. Requires cutree, pmode<br>+    an earlier encode of the same sequence, substantial redundant work may be avoided. Requires pmode<br>    to be off. Default disabled.<br> <br>     The amount of analysis data reused is determined by :option:`--analysis-load-reuse-level`.<br>@@ -961,21 +961,21 @@ will not reuse analysis if slice type parameters do not match.<br>     Note that :option:`--analysis-save-reuse-level` and :option:`--analysis-load-reuse-level` must be paired<br>     with :option:`--analysis-save` and :option:`--analysis-load` respectively.<br> <br>-       +--------------+------------------------------------------+<br>-  | Level        | Description                              |<br>-       +==============+==========================================+<br>-  | 1            | Lookahead information                    |<br>-  +--------------+------------------------------------------+<br>-  | 2 to 4       | Level 1 + intra/inter modes, ref's       |<br>-        +--------------+------------------------------------------+<br>-  | 5 and 6      | Level 2 + rect-amp                       |<br>-    +--------------+------------------------------------------+<br>-  | 7            | Level 5 + AVC size CU refinement         |<br>-        +--------------+------------------------------------------+<br>-  | 8 and 9      | Level 5 + AVC size Full CU analysis-info |<br>-       +--------------+------------------------------------------+<br>-  | 10           | Level 5 + Full CU analysis-info          |<br>-        +--------------+------------------------------------------+<br>+  +--------------+----------------------------------------------------+<br>+        | Level        | Description                                        |<br>+        +==============+====================================================+<br>+        | 1            | Lookahead information                              |<br>+   +--------------+----------------------------------------------------+<br>+        | 2 to 4       | Level 1 + intra/inter modes, ref's, cutree offsets |<br>+ +--------------+----------------------------------------------------+<br>+        | 5 and 6      | Level 2 + rect-amp                                 |<br>+     +--------------+----------------------------------------------------+<br>+        | 7            | Level 5 + AVC size CU refinement                   |<br>+ +--------------+----------------------------------------------------+<br>+        | 8 and 9      | Level 5 + AVC size Full CU analysis-info           |<br>+        +--------------+----------------------------------------------------+<br>+        | 10           | Level 5 + Full CU analysis-info                    |<br>+ +--------------+----------------------------------------------------+<br> <br> .. option:: --refine-mv-type <string><br> <br>diff --git a/source/abrEncApp.cpp b/source/abrEncApp.cpp<br>index fa62ebf63..4c6964cfb 100644<br>--- a/source/abrEncApp.cpp<br>+++ b/source/abrEncApp.cpp<br>@@ -99,6 +99,8 @@ namespace X265_NS {<br>             }<br> <br>             m_analysisBuffer[pass] = X265_MALLOC(x265_analysis_data, m_queueSize);<br>+            if (m_analysisBuffer[pass])<br>+                memset(m_analysisBuffer[pass], 0, sizeof(x265_analysis_data) * m_queueSize);<br>             m_picIdxReadCnt[pass] = new ThreadSafeInteger[m_queueSize];<br>             m_analysisWrite[pass] = new ThreadSafeInteger[m_queueSize];<br>             m_analysisRead[pass] = new ThreadSafeInteger[m_queueSize];<br>@@ -340,7 +342,12 @@ namespace X265_NS {<br>             memcpy(intraDst->partSizes, intraSrc->partSizes, sizeof(char) * src->depthBytes);<br>             memcpy(intraDst->chromaModes, intraSrc->chromaModes, sizeof(uint8_t) * src->depthBytes);<br>             if (m_param->rc.cuTree)<br>-                memcpy(intraDst->cuQPOff, intraSrc->cuQPOff, sizeof(int8_t) * src->depthBytes);<br>+            {<br>+                if (m_param->analysisSaveReuseLevel == 10)<br>+                    memcpy(intraDst->cuQPOff, intraSrc->cuQPOff, sizeof(int8_t) * src->depthBytes);<br>+                else<br>+                    memcpy(intraDst->cuQPOff, intraSrc->cuQPOff, sizeof(int8_t) * src->numCUsInFrame * X265_MAX_CTU_SPLITS(m_param->maxCUSize, m_param->minCUSize));<br>+            }<br>         }<br>         else<br>         {<br>@@ -355,7 +362,12 @@ namespace X265_NS {<br>             memcpy(interDst->depth, interSrc->depth, sizeof(uint8_t) * src->depthBytes);<br>             memcpy(interDst->modes, interSrc->modes, sizeof(uint8_t) * src->depthBytes);<br>             if (m_param->rc.cuTree)<br>-                memcpy(interDst->cuQPOff, interSrc->cuQPOff, sizeof(int8_t) * src->depthBytes);<br>+            {<br>+                if (m_param->analysisSaveReuseLevel == 10)<br>+                    memcpy(interDst->cuQPOff, interSrc->cuQPOff, sizeof(int8_t) * src->depthBytes);<br>+                else<br>+                    memcpy(interDst->cuQPOff, interSrc->cuQPOff, sizeof(int8_t) * src->numCUsInFrame * X265_MAX_CTU_SPLITS(m_param->maxCUSize, m_param->minCUSize));<br>+            }<br>             if (m_param->analysisSaveReuseLevel > 4)<br>             {<br>                 memcpy(interDst->partSize, interSrc->partSize, sizeof(uint8_t) * src->depthBytes);<br>diff --git a/source/common/common.h b/source/common/common.h<br>index 8c06cd79e..a8f3ae71a 100644<br>--- a/source/common/common.h<br>+++ b/source/common/common.h<br>@@ -343,6 +343,10 @@ typedef int16_t  coeff_t;      // transform coefficient<br> <br> namespace X265_NS {<br> <br>+const uint8_t g_maxCtuSplits[MIN_LOG2_CU_SIZE + 1] = { 1, 5, 21, 85 }; /* max ctu partitions as per min max cu configurations */<br>+<br>+#define X265_MAX_CTU_SPLITS(maxcusize, mincusize) (g_maxCtuSplits[g_log2Size[maxcusize] - g_log2Size[mincusize]])<br>+<br> enum { SAO_NUM_OFFSET = 4 };<br> <br> enum SaoMergeMode<br>diff --git a/source/common/cudata.h b/source/common/cudata.h<br>index 8397f0568..c7d9a1972 100644<br>--- a/source/common/cudata.h<br>+++ b/source/common/cudata.h<br>@@ -371,7 +371,7 @@ struct CUDataMemPool<br>             CHECKED_MALLOC(trCoeffMemBlock, coeff_t, (sizeL) * numInstances);<br>         }<br>         else<br>-        {            <br>+        {<br>             uint32_t sizeC = sizeL >> (CHROMA_H_SHIFT(csp) + CHROMA_V_SHIFT(csp));<br>             CHECKED_MALLOC(trCoeffMemBlock, coeff_t, (sizeL + sizeC * 2) * numInstances);<br>         }<br>diff --git a/source/encoder/analysis.cpp b/source/encoder/analysis.cpp<br>index aabf386ca..6e1d5c730 100644<br>--- a/source/encoder/analysis.cpp<br>+++ b/source/encoder/analysis.cpp<br>@@ -74,6 +74,7 @@ Analysis::Analysis()<br> {<br>     m_reuseInterDataCTU = NULL;<br>     m_reuseRef = NULL;<br>+    m_reuseQPOff = NULL;<br>     m_bHD = false;<br>     m_modeFlag[0] = false;<br>     m_modeFlag[1] = false;<br>@@ -220,6 +221,9 @@ Mode& Analysis::compressCTU(CUData& ctu, Frame& frame, const CUGeom& cuGeom, con<br>         if (m_param->analysisSave && !m_param->analysisLoad)<br>             for (int i = 0; i < X265_MAX_PRED_MODE_PER_CTU * numPredDir; i++)<br>                 m_reuseRef[i] = -1;<br>+<br>+        if (m_param->rc.cuTree)<br>+            m_reuseQPOff = &m_reuseInterDataCTU->cuQPOff[ctu.m_cuAddr * X265_MAX_CTU_SPLITS(m_param->maxCUSize, m_param->minCUSize)];<br>     }<br>     ProfileCUScope(ctu, totalCTUTime, totalCTUs);<br> <br>@@ -233,6 +237,8 @@ Mode& Analysis::compressCTU(CUData& ctu, Frame& frame, const CUGeom& cuGeom, con<br>             memcpy(ctu.m_partSize, &intraDataCTU->partSizes[ctu.m_cuAddr * numPartition], sizeof(char) * numPartition);<br>             memcpy(ctu.m_chromaIntraDir, &intraDataCTU->chromaModes[ctu.m_cuAddr * numPartition], sizeof(uint8_t) * numPartition);<br>         }<br>+        if (m_param->rc.cuTree && reuseLevel > 1 && reuseLevel < 10)<br>+            m_reuseQPOff = &intraDataCTU->cuQPOff[ctu.m_cuAddr * X265_MAX_CTU_SPLITS(m_param->maxCUSize, m_param->minCUSize)];<br>         compressIntraCU(ctu, cuGeom, qp);<br>     }<br>     else<br>@@ -520,6 +526,9 @@ uint64_t Analysis::compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom<br>     bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);<br>     bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);<br> <br>+    if (m_param->rc.cuTree  && m_param->analysisSaveReuseLevel > 1 && m_param->analysisSaveReuseLevel < 10)<br>+        m_reuseQPOff[cuGeom.geomRecurId] = (int8_t)(qp - (int32_t)(m_frame->m_encData->m_cuStat[parentCTU.m_cuAddr].baseQp + 0.5));<br>+<br>     bool bAlreadyDecided = m_param->intraRefine != 4 && parentCTU.m_lumaIntraDir[cuGeom.absPartIdx] != (uint8_t)ALL_IDX && !(m_param->bAnalysisType == HEVC_INFO);<br>     bool bDecidedDepth = m_param->intraRefine != 4 && parentCTU.m_cuDepth[cuGeom.absPartIdx] == depth;<br>     int split = 0;<br>@@ -870,6 +879,9 @@ uint32_t Analysis::compressInterCU_dist(const CUData& parentCTU, const CUGeom& c<br>     uint32_t minDepth = m_param->rdLevel <= 4 ? topSkipMinDepth(parentCTU, cuGeom) : 0;<br>     uint32_t splitRefs[4] = { 0, 0, 0, 0 };<br> <br>+    if (m_param->rc.cuTree && m_param->analysisSaveReuseLevel > 1 && m_param->analysisSaveReuseLevel < 10)<br>+        m_reuseQPOff[cuGeom.geomRecurId] = (int8_t)(qp - (int32_t)(m_frame->m_encData->m_cuStat[parentCTU.m_cuAddr].baseQp + 0.5));<br>+<br>     X265_CHECK(m_param->rdLevel >= 2, "compressInterCU_dist does not support RD 0 or 1\n");<br> <br>     PMODE pmode(*this, cuGeom);<br>@@ -1152,6 +1164,8 @@ SplitData Analysis::compressInterCU_rd0_4(const CUData& parentCTU, const CUGeom&<br>     uint32_t cuAddr = parentCTU.m_cuAddr;<br>     ModeDepth& md = m_modeDepth[depth];<br> <br>+    if (m_param->rc.cuTree && m_param->analysisSaveReuseLevel > 1 && m_param->analysisSaveReuseLevel < 10)<br>+        m_reuseQPOff[cuGeom.geomRecurId] = (int8_t)(qp - (int32_t)(m_frame->m_encData->m_cuStat[parentCTU.m_cuAddr].baseQp + 0.5));<br> <br>     if (m_param->searchMethod == X265_SEA)<br>     {<br>@@ -1856,6 +1870,9 @@ SplitData Analysis::compressInterCU_rd5_6(const CUData& parentCTU, const CUGeom&<br>     ModeDepth& md = m_modeDepth[depth];<br>     md.bestMode = NULL;<br> <br>+    if (m_param->rc.cuTree && m_param->analysisSaveReuseLevel > 1 && m_param->analysisSaveReuseLevel < 10)<br>+        m_reuseQPOff[cuGeom.geomRecurId] = (int8_t)(qp - (int32_t)(m_frame->m_encData->m_cuStat[parentCTU.m_cuAddr].baseQp + 0.5));<br>+<br>     if (m_param->searchMethod == X265_SEA)<br>     {<br>         int numPredDir = m_slice->isInterP() ? 1 : 2;<br>@@ -3647,11 +3664,20 @@ int Analysis::calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom, int3<br> <br>     if (m_param->analysisLoadReuseLevel >= 2 && m_param->rc.cuTree)<br>     {<br>-        int cuIdx = (ctu.m_cuAddr * ctu.m_numPartitions) + cuGeom.absPartIdx;<br>+        int cuIdx;<br>+        int8_t cuQPOffSet = 0;<br>+<br>+        if (m_param->scaleFactor == 2 || m_param->analysisLoadReuseLevel == 10)<br>+            cuIdx = (ctu.m_cuAddr * ctu.m_numPartitions) + cuGeom.absPartIdx;<br>+        else<br>+            cuIdx = (ctu.m_cuAddr * X265_MAX_CTU_SPLITS(m_param->maxCUSize, m_param->minCUSize)) + cuGeom.geomRecurId;<br>+<br>         if (ctu.m_slice->m_sliceType == I_SLICE)<br>-            return x265_clip3(m_param->rc.qpMin, m_param->rc.qpMax, (int32_t)(qp + 0.5 + ((x265_analysis_intra_data*)m_frame->m_analysisData.intraData)->cuQPOff[cuIdx]));<br>+            cuQPOffSet = ((x265_analysis_intra_data*)m_frame->m_analysisData.intraData)->cuQPOff[cuIdx];<br>         else<br>-            return x265_clip3(m_param->rc.qpMin, m_param->rc.qpMax, (int32_t)(qp + 0.5 + ((x265_analysis_inter_data*)m_frame->m_analysisData.interData)->cuQPOff[cuIdx]));<br>+            cuQPOffSet = ((x265_analysis_inter_data*)m_frame->m_analysisData.interData)->cuQPOff[cuIdx];<br>+<br>+        return x265_clip3(m_param->rc.qpMin, m_param->rc.qpMax, (int32_t)(qp + 0.5 + cuQPOffSet));<br>     }<br>     if (m_param->rc.hevcAq)<br>     {<br>diff --git a/source/encoder/analysis.h b/source/encoder/analysis.h<br>index 3bcb56bc3..de01f9789 100644<br>--- a/source/encoder/analysis.h<br>+++ b/source/encoder/analysis.h<br>@@ -126,6 +126,7 @@ protected:<br>     int32_t*                   m_reuseRef;<br>     uint8_t*                   m_reuseDepth;<br>     uint8_t*                   m_reuseModes;<br>+    int8_t*                    m_reuseQPOff; // array of QP values for analysis reuse at reuse levels > 1 and < 10 when cutree is enabled<br>     uint8_t*                   m_reusePartSize;<br>     uint8_t*                   m_reuseMergeFlag;<br>     x265_analysis_MV*          m_reuseMv[2];<br>diff --git a/source/encoder/api.cpp b/source/encoder/api.cpp<br>index a986355e0..c263e2a87 100644<br>--- a/source/encoder/api.cpp<br>+++ b/source/encoder/api.cpp<br>@@ -825,7 +825,16 @@ void x265_alloc_analysis_data(x265_param *param, x265_analysis_data* analysis)<br>         CHECKED_MALLOC_ZERO(intraData->partSizes, char, analysis->numPartitions * analysis->numCUsInFrame);<br>         CHECKED_MALLOC_ZERO(intraData->chromaModes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);<br>         if (param->rc.cuTree)<br>-            CHECKED_MALLOC_ZERO(intraData->cuQPOff, int8_t, analysis->numPartitions * analysis->numCUsInFrame);<br>+        {<br>+            if (maxReuseLevel == 10)<br>+            {<br>+                CHECKED_MALLOC_ZERO(intraData->cuQPOff, int8_t, analysis->numPartitions * analysis->numCUsInFrame);<br>+            }<br>+            else<br>+            {<br>+                CHECKED_MALLOC_ZERO(intraData->cuQPOff, int8_t, X265_MAX_CTU_SPLITS(param->maxCUSize, param->minCUSize) * analysis->numCUsInFrame);<br>+            }<br>+        }<br>     }<br>     analysis->intraData = intraData;<br> <br>@@ -837,7 +846,16 @@ void x265_alloc_analysis_data(x265_param *param, x265_analysis_data* analysis)<br>         CHECKED_MALLOC_ZERO(interData->modes, uint8_t, analysis->numPartitions * analysis->numCUsInFrame);<br> <br>         if (param->rc.cuTree && !isMultiPassOpt)<br>-            CHECKED_MALLOC_ZERO(interData->cuQPOff, int8_t, analysis->numPartitions * analysis->numCUsInFrame);<br>+        {<br>+            if (maxReuseLevel == 10)<br>+            {<br>+                CHECKED_MALLOC_ZERO(interData->cuQPOff, int8_t, analysis->numPartitions * analysis->numCUsInFrame);<br>+            }<br>+            else<br>+            {<br>+                CHECKED_MALLOC_ZERO(interData->cuQPOff, int8_t, X265_MAX_CTU_SPLITS(param->maxCUSize, param->minCUSize) * analysis->numCUsInFrame);<br>+            }<br>+        }<br>         CHECKED_MALLOC_ZERO(interData->mvpIdx[0], uint8_t, analysis->numPartitions * analysis->numCUsInFrame);<br>         CHECKED_MALLOC_ZERO(interData->mvpIdx[1], uint8_t, analysis->numPartitions * analysis->numCUsInFrame);<br>         CHECKED_MALLOC_ZERO(interData->mv[0], x265_analysis_MV, analysis->numPartitions * analysis->numCUsInFrame);<br>@@ -919,7 +937,9 @@ void x265_free_analysis_data(x265_param *param, x265_analysis_data* analysis)<br>             X265_FREE((analysis->intraData)->partSizes);<br>             X265_FREE((analysis->intraData)->chromaModes);<br>             if (param->rc.cuTree)<br>-                X265_FREE((analysis->intraData)->cuQPOff);<br>+            {<br>+                X265_FREE_ZERO((analysis->intraData)->cuQPOff);<br>+            }<br>         }<br>         X265_FREE(analysis->intraData);<br>         analysis->intraData = NULL;<br>@@ -931,7 +951,9 @@ void x265_free_analysis_data(x265_param *param, x265_analysis_data* analysis)<br>         X265_FREE((analysis->interData)->depth);<br>         X265_FREE((analysis->interData)->modes);<br>         if (!isMultiPassOpt && param->rc.cuTree)<br>+        {<br>             X265_FREE((analysis->interData)->cuQPOff);<br>+        }<br>         X265_FREE((analysis->interData)->mvpIdx[0]);<br>         X265_FREE((analysis->interData)->mvpIdx[1]);<br>         X265_FREE((analysis->interData)->mv[0]);<br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index 1f710e1ce..d64b07848 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -4444,6 +4444,17 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>             }<br>         }<br>     }<br>+<br>+    int8_t *cuQPBuf = NULL;<br>+    uint32_t reuseBufSize = 0;<br>+    if (m_param->rc.cuTree)<br>+    {<br>+        if (m_param->analysisLoadReuseLevel == 10)<br>+            cuQPBuf = X265_MALLOC(int8_t, depthBytes);<br>+        else if (m_param->analysisLoadReuseLevel > 1)<br>+            reuseBufSize = X265_MAX_CTU_SPLITS(m_param->maxCUSize, m_param->minCUSize) * analysis->numCUsInFrame;<br>+    }<br>+<br>     if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)<br>     {<br>         if (m_param->bAnalysisType == HEVC_INFO)<br>@@ -4452,19 +4463,26 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>             return;<br> <br>         uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSizes = NULL;<br>-        int8_t *cuQPBuf = NULL;<br> <br>         tempBuf = X265_MALLOC(uint8_t, depthBytes * 3);<br>         depthBuf = tempBuf;<br>         modeBuf = tempBuf + depthBytes;<br>         partSizes = tempBuf + 2 * depthBytes;<br>-        if (m_param->rc.cuTree)<br>-            cuQPBuf = X265_MALLOC(int8_t, depthBytes);<br> <br>         X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->depth);<br>         X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->chromaModes);<br>         X265_FREAD(partSizes, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->partSizes);<br>-        if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, intraPic->cuQPOff); }<br>+        if (m_param->rc.cuTree)<br>+        {<br>+            if (m_param->analysisLoadReuseLevel == 10)<br>+            {<br>+                X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, intraPic->cuQPOff);<br>+            }<br>+            else if (m_param->analysisLoadReuseLevel > 1)<br>+            {<br>+                X265_FREAD(analysis->intraData->cuQPOff, sizeof(int8_t), reuseBufSize, m_analysisFileIn, intraPic->cuQPOff);<br>+            }<br>+        }<br> <br>         size_t count = 0;<br>         for (uint32_t d = 0; d < depthBytes; d++)<br>@@ -4480,7 +4498,7 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>             memset(&(analysis->intraData)->depth[count], depthBuf[d], bytes);<br>             memset(&(analysis->intraData)->chromaModes[count], modeBuf[d], bytes);<br>             memset(&(analysis->intraData)->partSizes[count], partSizes[d], bytes);<br>-            if (m_param->rc.cuTree)<br>+            if (m_param->rc.cuTree && m_param->analysisLoadReuseLevel == 10)<br>                 memset(&(analysis->intraData)->cuQPOff[count], cuQPBuf[d], bytes);<br>             count += bytes;<br>         }<br>@@ -4497,7 +4515,7 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>                 memset(&(analysis->intraData)->modes[cnt], tempLumaBuf[ctu32Idx], factor);<br>             X265_FREE(tempLumaBuf);<br>         }<br>-        if (m_param->rc.cuTree)<br>+        if (m_param->rc.cuTree && m_param->analysisLoadReuseLevel == 10)<br>             X265_FREE(cuQPBuf);<br>         X265_FREE(tempBuf);<br>         consumedBytes += frameRecordSize;<br>@@ -4515,7 +4533,6 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>         uint8_t *interDir = NULL, *chromaDir = NULL, *mvpIdx[2];<br>         MV* mv[2];<br>         int8_t* refIdx[2];<br>-        int8_t* cuQPBuf = NULL;<br> <br>         int numBuf = m_param->analysisLoadReuseLevel > 4 ? 4 : 2;<br>         bool bIntraInInter = false;<br>@@ -4535,12 +4552,20 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>             tempBuf = X265_MALLOC(uint8_t, depthBytes * numBuf);<br>             depthBuf = tempBuf;<br>             modeBuf = tempBuf + depthBytes;<br>-            if (m_param->rc.cuTree)<br>-                cuQPBuf = X265_MALLOC(int8_t, depthBytes);<br> <br>             X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->depth);<br>             X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->modes);<br>-            if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->cuQPOff); }<br>+            if (m_param->rc.cuTree)<br>+            {<br>+                if (m_param->analysisLoadReuseLevel == 10)<br>+                {<br>+                    X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->cuQPOff);<br>+                }<br>+                else if (m_param->analysisLoadReuseLevel > 1)<br>+                {<br>+                    X265_FREAD(analysis->interData->cuQPOff, sizeof(int8_t), reuseBufSize, m_analysisFileIn, interPic->cuQPOff);<br>+                }<br>+            }<br> <br>             if (m_param->analysisLoadReuseLevel > 4)<br>             {<br>@@ -4578,7 +4603,7 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>                     depthBuf[d] = 1;<br>                 memset(&(analysis->interData)->depth[count], depthBuf[d], bytes);<br>                 memset(&(analysis->interData)->modes[count], modeBuf[d], bytes);<br>-                if (m_param->rc.cuTree)<br>+                if (m_param->rc.cuTree && m_param->analysisLoadReuseLevel == 10)<br>                     memset(&(analysis->interData)->cuQPOff[count], cuQPBuf[d], bytes);<br>                 if (m_param->analysisLoadReuseLevel > 4)<br>                 {<br>@@ -4612,7 +4637,7 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>                 count += bytes;<br>             }<br> <br>-            if (m_param->rc.cuTree)<br>+            if (m_param->rc.cuTree && m_param->analysisLoadReuseLevel == 10)<br>                 X265_FREE(cuQPBuf);<br>             X265_FREE(tempBuf);<br>         }<br>@@ -4736,7 +4761,7 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>     int numPartitions = analysis->numPartitions;<br>     int numCUsInFrame = analysis->numCUsInFrame;<br>     int numCuInHeight = analysis->numCuInHeight;<br>-    /* Allocate memory for scaled resoultion's numPartitions and numCUsInFrame*/<br>+    /* Allocate memory for scaled resolution's numPartitions and numCUsInFrame */<br>     analysis->numPartitions = m_param->num4x4Partitions;<br>     analysis->numCUsInFrame = cuLoc.heightInCU * cuLoc.widthInCU;<br>     analysis->numCuInHeight = cuLoc.heightInCU;<br>@@ -4808,25 +4833,42 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>         X265_FREE(vbvCostBuf);<br>     }<br> <br>+    uint32_t reuseBufSize = 0;<br>+    int8_t *cuQPBuf = NULL;<br>+    if (m_param->rc.cuTree)<br>+    {<br>+        if (m_param->analysisLoadReuseLevel == 10)<br>+            cuQPBuf = X265_MALLOC(int8_t, depthBytes);<br>+        else if (m_param->analysisLoadReuseLevel > 1)<br>+            reuseBufSize = (X265_MAX_CTU_SPLITS(m_param->maxCUSize, m_param->minCUSize) / factor) * (analysis->numCUsInFrame);<br>+    }<br>+<br>     if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)<br>     {<br>         if (m_param->analysisLoadReuseLevel < 2)<br>             return;<br> <br>         uint8_t *tempBuf = NULL, *depthBuf = NULL, *modeBuf = NULL, *partSizes = NULL;<br>-        int8_t *cuQPBuf = NULL;<br> <br>         tempBuf = X265_MALLOC(uint8_t, depthBytes * 3);<br>         depthBuf = tempBuf;<br>         modeBuf = tempBuf + depthBytes;<br>         partSizes = tempBuf + 2 * depthBytes;<br>-        if (m_param->rc.cuTree)<br>-            cuQPBuf = X265_MALLOC(int8_t, depthBytes);<br> <br>         X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->depth);<br>         X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->chromaModes);<br>         X265_FREAD(partSizes, sizeof(uint8_t), depthBytes, m_analysisFileIn, intraPic->partSizes);<br>-        if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, intraPic->cuQPOff); }<br>+        if (m_param->rc.cuTree)<br>+        {<br>+            if (m_param->analysisLoadReuseLevel == 10)<br>+            {<br>+                X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, intraPic->cuQPOff);<br>+            }<br>+            else if (m_param->analysisLoadReuseLevel > 1)<br>+            {<br>+                X265_FREAD(analysis->intraData->cuQPOff, sizeof(int8_t), reuseBufSize, m_analysisFileIn, intraPic->cuQPOff);<br>+            }<br>+        }<br> <br>         uint32_t count = 0;<br>         for (uint32_t d = 0; d < depthBytes; d++)<br>@@ -4848,7 +4890,7 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>                 memset(&(analysis->intraData)->depth[count], depthBuf[d], bytes);<br>                 memset(&(analysis->intraData)->chromaModes[count], modeBuf[d], bytes);<br>                 memset(&(analysis->intraData)->partSizes[count], partSizes[d], bytes);<br>-                if (m_param->rc.cuTree)<br>+                if (m_param->rc.cuTree && m_param->analysisLoadReuseLevel == 10)<br>                     memset(&(analysis->intraData)->cuQPOff[count], cuQPBuf[d], bytes);<br>                 count += bytes;<br>                 d += getCUIndex(&cuLoc, &count, bytes, 1);<br>@@ -4868,7 +4910,7 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>             ctu32Idx += getCUIndex(&cuLoc, &cnt, factor, 0);<br>         }<br>         X265_FREE(tempLumaBuf);<br>-        if (m_param->rc.cuTree)<br>+        if (m_param->rc.cuTree && m_param->analysisLoadReuseLevel == 10)<br>             X265_FREE(cuQPBuf);<br>         X265_FREE(tempBuf);<br>         consumedBytes += frameRecordSize;<br>@@ -4886,7 +4928,6 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>         uint8_t *interDir = NULL, *chromaDir = NULL, *mvpIdx[2];<br>         MV* mv[2];<br>         int8_t* refIdx[2];<br>-        int8_t* cuQPBuf = NULL;<br> <br>         int numBuf = m_param->analysisLoadReuseLevel > 4 ? 4 : 2;<br>         bool bIntraInInter = false;<br>@@ -4900,12 +4941,21 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>         tempBuf = X265_MALLOC(uint8_t, depthBytes * numBuf);<br>         depthBuf = tempBuf;<br>         modeBuf = tempBuf + depthBytes;<br>-        if (m_param->rc.cuTree)<br>-            cuQPBuf = X265_MALLOC(int8_t, depthBytes);<br> <br>         X265_FREAD(depthBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->depth);<br>         X265_FREAD(modeBuf, sizeof(uint8_t), depthBytes, m_analysisFileIn, interPic->modes);<br>-        if (m_param->rc.cuTree) { X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->cuQPOff); }<br>+        if (m_param->rc.cuTree)<br>+        {<br>+            if (m_param->analysisLoadReuseLevel == 10)<br>+            {<br>+                X265_FREAD(cuQPBuf, sizeof(int8_t), depthBytes, m_analysisFileIn, interPic->cuQPOff);<br>+            }<br>+            else if (m_param->analysisLoadReuseLevel > 1)<br>+            {<br>+                X265_FREAD(analysis->interData->cuQPOff, sizeof(int8_t), reuseBufSize, m_analysisFileIn, interPic->cuQPOff);<br>+            }<br>+        }<br>+<br>         if (m_param->analysisLoadReuseLevel > 4)<br>         {<br>             partSize = modeBuf + depthBytes;<br>@@ -4954,7 +5004,7 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>             {<br>                 memset(&(analysis->interData)->depth[count], writeDepth, bytes);<br>                 memset(&(analysis->interData)->modes[count], modeBuf[d], bytes);<br>-                if (m_param->rc.cuTree)<br>+                if (m_param->rc.cuTree && m_param->analysisLoadReuseLevel == 10)<br>                     memset(&(analysis->interData)->cuQPOff[count], cuQPBuf[d], bytes);<br>                 if (m_param->analysisLoadReuseLevel == 10 && bIntraInInter)<br>                     memset(&(analysis->intraData)->chromaModes[count], chromaDir[d], bytes);<br>@@ -5016,7 +5066,7 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>             }<br>         }<br> <br>-        if (m_param->rc.cuTree)<br>+        if (m_param->rc.cuTree && m_param->analysisLoadReuseLevel == 10)<br>             X265_FREE(cuQPBuf);<br>         X265_FREE(tempBuf);<br> <br>@@ -5046,7 +5096,9 @@ void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x<br>             }<br>         }<br>         else<br>+        {<br>             X265_FREAD((analysis->interData)->ref, sizeof(int32_t), analysis->numCUsInFrame * X265_MAX_PRED_MODE_PER_CTU * numDir, m_analysisFileIn, interPic->ref);<br>+        }<br> <br>         consumedBytes += frameRecordSize;<br>         if (numDir == 1)<br>@@ -5510,8 +5562,11 @@ void Encoder::writeAnalysisFile(x265_analysis_data* analysis, FrameData &curEncD<br>         analysis->frameRecordSize += analysis->numCUsInFrame * sizeof(sse_t);<br>     }<br> <br>+    uint32_t reuseQPBufsize = 0;<br>     if (m_param->analysisSaveReuseLevel > 1)<br>     {<br>+        if (m_param->rc.cuTree)<br>+            reuseQPBufsize = X265_MAX_CTU_SPLITS(m_param->maxCUSize, m_param->minCUSize) * analysis->numCUsInFrame;<br> <br>         if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)<br>         {<br>@@ -5536,12 +5591,15 @@ void Encoder::writeAnalysisFile(x265_analysis_data* analysis, FrameData &curEncD<br>                     partSize = ctu->m_partSize[absPartIdx];<br>                     intraDataCTU->partSizes[depthBytes] = partSize;<br> <br>-                    if (m_param->rc.cuTree)<br>+                    if (m_param->rc.cuTree && m_param->analysisSaveReuseLevel == 10)<br>                         intraDataCTU->cuQPOff[depthBytes] = (int8_t)(ctu->m_qpAnalysis[absPartIdx] - baseQP);<br>                     absPartIdx += ctu->m_numPartitions >> (depth * 2);<br>                 }<br>+<br>                 memcpy(&intraDataCTU->modes[ctu->m_cuAddr * ctu->m_numPartitions], ctu->m_lumaIntraDir, sizeof(uint8_t)* ctu->m_numPartitions);<br>             }<br>+            if (m_param->rc.cuTree && m_param->analysisSaveReuseLevel == 10)<br>+                reuseQPBufsize = depthBytes;<br>         }<br>         else<br>         {<br>@@ -5567,7 +5625,7 @@ void Encoder::writeAnalysisFile(x265_analysis_data* analysis, FrameData &curEncD<br>                         predMode = 4; // used as indicator if the block is coded as bidir<br> <br>                     interDataCTU->modes[depthBytes] = predMode;<br>-                    if (m_param->rc.cuTree)<br>+                    if (m_param->rc.cuTree && m_param->analysisSaveReuseLevel == 10)<br>                         interDataCTU->cuQPOff[depthBytes] = (int8_t)(ctu->m_qpAnalysis[absPartIdx] - baseQP);<br> <br>                     if (m_param->analysisSaveReuseLevel > 4)<br>@@ -5599,21 +5657,25 @@ void Encoder::writeAnalysisFile(x265_analysis_data* analysis, FrameData &curEncD<br>                     }<br>                     absPartIdx += ctu->m_numPartitions >> (depth * 2);<br>                 }<br>+<br>                 if (m_param->analysisSaveReuseLevel == 10 && bIntraInInter)<br>                     memcpy(&intraDataCTU->modes[ctu->m_cuAddr * ctu->m_numPartitions], ctu->m_lumaIntraDir, sizeof(uint8_t)* ctu->m_numPartitions);<br>             }<br>+            if (m_param->rc.cuTree && m_param->analysisSaveReuseLevel == 10)<br>+                reuseQPBufsize = depthBytes;<br>         }<br> <br>-        if ((analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) && m_param->rc.cuTree)<br>-            analysis->frameRecordSize += sizeof(uint8_t)* analysis->numCUsInFrame * analysis->numPartitions + depthBytes * 3 + (sizeof(int8_t) * depthBytes);<br>+        if ((analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I) && (m_param->rc.cuTree && m_param->analysisSaveReuseLevel > 1))<br>+            analysis->frameRecordSize += sizeof(uint8_t)* analysis->numCUsInFrame * analysis->numPartitions + depthBytes * 3 + (sizeof(int8_t) * reuseQPBufsize);<br>         else if (analysis->sliceType == X265_TYPE_IDR || analysis->sliceType == X265_TYPE_I)<br>             analysis->frameRecordSize += sizeof(uint8_t)* analysis->numCUsInFrame * analysis->numPartitions + depthBytes * 3;<br>         else<br>         {<br>             /* Add sizeof depth, modes, partSize, cuQPOffset, mergeFlag */<br>             analysis->frameRecordSize += depthBytes * 2;<br>-            if (m_param->rc.cuTree)<br>-            analysis->frameRecordSize += (sizeof(int8_t) * depthBytes);<br>+            if (m_param->rc.cuTree && m_param->analysisSaveReuseLevel > 1)<br>+                analysis->frameRecordSize += (sizeof(int8_t) * reuseQPBufsize);<br>+<br>             if (m_param->analysisSaveReuseLevel > 4)<br>                 analysis->frameRecordSize += (depthBytes * 2);<br> <br>@@ -5669,7 +5731,7 @@ void Encoder::writeAnalysisFile(x265_analysis_data* analysis, FrameData &curEncD<br>         X265_FWRITE((analysis->intraData)->chromaModes, sizeof(uint8_t), depthBytes, m_analysisFileOut);<br>         X265_FWRITE((analysis->intraData)->partSizes, sizeof(char), depthBytes, m_analysisFileOut);<br>         if (m_param->rc.cuTree)<br>-            X265_FWRITE((analysis->intraData)->cuQPOff, sizeof(int8_t), depthBytes, m_analysisFileOut);<br>+            X265_FWRITE((analysis->intraData)->cuQPOff, sizeof(int8_t), reuseQPBufsize, m_analysisFileOut);<br>         X265_FWRITE((analysis->intraData)->modes, sizeof(uint8_t), analysis->numCUsInFrame * analysis->numPartitions, m_analysisFileOut);<br>     }<br>     else<br>@@ -5677,7 +5739,7 @@ void Encoder::writeAnalysisFile(x265_analysis_data* analysis, FrameData &curEncD<br>         X265_FWRITE((analysis->interData)->depth, sizeof(uint8_t), depthBytes, m_analysisFileOut);<br>         X265_FWRITE((analysis->interData)->modes, sizeof(uint8_t), depthBytes, m_analysisFileOut);<br>         if (m_param->rc.cuTree)<br>-            X265_FWRITE((analysis->interData)->cuQPOff, sizeof(int8_t), depthBytes, m_analysisFileOut);<br>+            X265_FWRITE((analysis->interData)->cuQPOff, sizeof(int8_t), reuseQPBufsize, m_analysisFileOut);<br>         if (m_param->analysisSaveReuseLevel > 4)<br>         {<br>             X265_FWRITE((analysis->interData)->partSize, sizeof(uint8_t), depthBytes, m_analysisFileOut);<br>@@ -5762,7 +5824,7 @@ void Encoder::writeAnalysisFileRefine(x265_analysis_data* analysis, FrameData &c<br>                     interData->mv[1][depthBytes].word = ctu->m_mv[1][absPartIdx].word;<br>                     interData->mvpIdx[1][depthBytes] = ctu->m_mvpIdx[1][absPartIdx];<br>                     ref[1][depthBytes] = ctu->m_refIdx[1][absPartIdx];<br>-                    predMode = 4; // used as indiacator if the block is coded as bidir<br>+                    predMode = 4; // used as indicator if the block is coded as bidir<br>                 }<br>                 interData->modes[depthBytes] = predMode;<br> <br>diff --git a/source/encoder/slicetype.cpp b/source/encoder/slicetype.cpp<br>index 0adb0d0db..9bee58192 100644<br>--- a/source/encoder/slicetype.cpp<br>+++ b/source/encoder/slicetype.cpp<br>@@ -1894,7 +1894,7 @@ void Lookahead::slicetypeAnalyse(Lowres **frames, bool bKeyframe)<br> <br>     if (!framecnt)<br>     {<br>-        if (m_param->rc.cuTree)<br>+        if (m_param->rc.cuTree && (!m_param->analysisLoad || (m_param->analysisLoad && m_param->analysisLoadReuseLevel == 1)))<br>             cuTree(frames, 0, bKeyframe);<br>         return;<br>     }<br>diff --git a/source/x265.h b/source/x265.h<br>index f44040ba7..8d7a75826 100644<br>--- a/source/x265.h<br>+++ b/source/x265.h<br>@@ -144,7 +144,7 @@ typedef struct x265_analysis_intra_data<br>     uint8_t*  modes;<br>     char*     partSizes;<br>     uint8_t*  chromaModes;<br>-    int8_t*    cuQPOff;<br>+    int8_t*   cuQPOff;<br> }x265_analysis_intra_data;<br> <br> typedef struct x265_analysis_MV<br>@@ -167,7 +167,7 @@ typedef struct x265_analysis_inter_data<br>     uint8_t*    interDir;<br>     uint8_t*    mvpIdx[2];<br>     int8_t*     refIdx[2];<br>-    x265_analysis_MV*         mv[2];<br>+    x265_analysis_MV* mv[2];<br>     int64_t*     sadCost;<br>     int8_t*    cuQPOff;<br> }x265_analysis_inter_data;<br>-- <br>2.20.1.windows.1<br><br><div><br></div>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><b style="background-color:rgb(255,255,255)"><font color="#0b5394">With Regards,</font></b><div><b style="background-color:rgb(255,255,255)"><font color="#0b5394">Srikanth Kurapati.</font></b></div></div></div></div>