<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Mar 9, 2018 at 7:12 PM,  <span dir="ltr"><<a href="mailto:bhavna@multicorewareinc.com" target="_blank">bhavna@multicorewareinc.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""># HG changeset patch<br>
# User Bhavna Hariharan <<a href="mailto:bhavna@multicorewareinc.com">bhavna@multicorewareinc.com</a>><br>
# Date 1520595579 -19800<br>
#      Fri Mar 09 17:09:39 2018 +0530<br>
</span># Node ID e5425bd33176d6366f34d93e80f9cb<wbr>1c9c4ebe6f<br>
<span class=""># Parent  d292dacb81d8607ce0b2fb106b7383<wbr>b360863e9d<br>
dynamic-refine: enable switching between inter refinement levels 0-3<br>
based on the content and the encoder properties.<br>
<br>
The algorithm has 2 parts<br>
1) Training - Encode frames with refine-inter 3 and calulate corresponding<br>
feature values until saturation of values. The training restarts when a scenecut<br>
is encountered.<br>
2) Classification - Based on the prior probability calculated from the training<br>
data and the feature metric of the current CU an appropriate refine-inter level<br>
is chosen for the CU.<br>
<br>
</span>diff -r d292dacb81d8 -r e5425bd33176 source/common/cudata.cpp<br>
<span class="">--- a/source/common/cudata.cpp  Fri Mar 09 09:44:53 2018 +0530<br>
+++ b/source/common/cudata.cpp  Fri Mar 09 17:09:39 2018 +0530<br>
@@ -317,6 +317,16 @@<br>
     m_cuAboveLeft = (m_cuLeft && m_cuAbove) ? m_encData->getPicCTU(m_cuAddr - widthInCU - 1) : NULL;<br>
     m_cuAboveRight = (m_cuAbove && ((m_cuAddr % widthInCU) < (widthInCU - 1))) ? m_encData->getPicCTU(m_cuAddr - widthInCU + 1) : NULL;<br>
     memset(m_distortion, 0, m_numPartitions * sizeof(sse_t));<br>
+<br>
+    if (m_encData->m_param-><wbr>bDynamicRefine)<br>
+    {<br>
+        int size = m_encData->m_param->maxCUDepth * X265_REFINE_INTER_LEVELS;<br>
+        CHECKED_MALLOC_ZERO(m_<wbr>collectCURd, uint64_t, size);<br>
+        CHECKED_MALLOC_ZERO(m_<wbr>collectCUVariance, uint32_t, size);<br>
+        CHECKED_MALLOC_ZERO(m_<wbr>collectCUCount, uint32_t, size);<br>
+    }<br>
+fail:<br>
+    return;<br>
 }<br>
<br>
 // initialize Sub partition<br>
</span>diff -r d292dacb81d8 -r e5425bd33176 source/common/cudata.h<br>
<span class="">--- a/source/common/cudata.h    Fri Mar 09 09:44:53 2018 +0530<br>
+++ b/source/common/cudata.h    Fri Mar 09 17:09:39 2018 +0530<br>
@@ -224,6 +224,11 @@<br>
     uint64_t      m_fAc_den[3];<br>
     uint64_t      m_fDc_den[3];<br>
<br>
+    /* Feature values per CTU for dynamic refinement */<br>
+    uint64_t*       m_collectCURd;<br>
+    uint32_t*       m_collectCUVariance;<br>
+    uint32_t*       m_collectCUCount;<br>
+<br>
     CUData();<br>
<br>
     void     initialize(const CUDataMemPool& dataPool, uint32_t depth, const x265_param& param, int instance);<br>
</span>diff -r d292dacb81d8 -r e5425bd33176 source/common/frame.cpp<br>
<div><div class="h5">--- a/source/common/frame.cpp   Fri Mar 09 09:44:53 2018 +0530<br>
+++ b/source/common/frame.cpp   Fri Mar 09 17:09:39 2018 +0530<br>
@@ -53,6 +53,7 @@<br>
     m_addOnDepth = NULL;<br>
     m_addOnCtuInfo = NULL;<br>
     m_addOnPrevChange = NULL;<br>
+    m_classifyFrame = false;<br>
 }<br>
<br>
 bool Frame::create(x265_param *param, float* quantOffsets)<br>
@@ -85,6 +86,14 @@<br>
         m_analysis2Pass.<wbr>analysisFramedata = NULL;<br>
     }<br>
<br>
+    if (param->bDynamicRefine)<br>
+    {<br>
+        int size = m_param->maxCUDepth * X265_REFINE_INTER_LEVELS;<br>
+        CHECKED_MALLOC_ZERO(m_<wbr>classifyRd, uint64_t, size);<br>
+        CHECKED_MALLOC_ZERO(m_<wbr>classifyVariance, uint64_t, size);<br>
+        CHECKED_MALLOC_ZERO(m_<wbr>classifyCount, uint32_t, size);<br>
+    }<br>
+<br>
     if (m_fencPic->create(param, !!m_param->bCopyPicToFrame) && m_lowres.create(m_fencPic, param->bframes, !!param->rc.aqMode || !!param->bAQMotion, param->rc.qgSize))<br>
     {<br>
         X265_CHECK((m_reconColCount == NULL), "m_reconColCount was initialized");<br>
@@ -226,4 +235,11 @@<br>
     }<br>
     m_lowres.destroy();<br>
     X265_FREE(m_rcData);<br>
+<br>
+    if (m_param->bDynamicRefine)<br>
+    {<br>
+        X265_FREE_ZERO(m_classifyRd);<br>
+        X265_FREE_ZERO(m_<wbr>classifyVariance);<br>
+        X265_FREE_ZERO(m_<wbr>classifyCount);<br>
+    }<br>
 }<br>
</div></div>diff -r d292dacb81d8 -r e5425bd33176 source/common/frame.h<br>
<span class="">--- a/source/common/frame.h     Fri Mar 09 09:44:53 2018 +0530<br>
+++ b/source/common/frame.h     Fri Mar 09 17:09:39 2018 +0530<br>
@@ -122,6 +122,14 @@<br>
     uint8_t**              m_addOnDepth;<br>
     uint8_t**              m_addOnCtuInfo;<br>
     int**                  m_addOnPrevChange;<br>
+<br>
+    /* Average feature values of frames being considered for classification */<br>
+    uint64_t*              m_classifyRd;<br>
+    uint64_t*              m_classifyVariance;<br>
+    uint32_t*              m_classifyCount;<br>
+<br>
+    bool                   m_classifyFrame;<br>
+<br>
     Frame();<br>
<br>
     bool create(x265_param *param, float* quantOffsets);<br>
</span>diff -r d292dacb81d8 -r e5425bd33176 source/common/lowres.cpp<br>
<span class="">--- a/source/common/lowres.cpp  Fri Mar 09 09:44:53 2018 +0530<br>
+++ b/source/common/lowres.cpp  Fri Mar 09 17:09:39 2018 +0530<br>
@@ -59,10 +59,12 @@<br>
         CHECKED_MALLOC_ZERO(<wbr>qpAqMotionOffset, double, cuCountFullRes);<br>
         CHECKED_MALLOC_ZERO(<wbr>invQscaleFactor, int, cuCountFullRes);<br>
         CHECKED_MALLOC_ZERO(<wbr>qpCuTreeOffset, double, cuCountFullRes);<br>
-        CHECKED_MALLOC_ZERO(<wbr>blockVariance, uint32_t, cuCountFullRes);<br>
         if (qgSize == 8)<br>
             CHECKED_MALLOC_ZERO(<wbr>invQscaleFactor8x8, int, cuCount);<br>
     }<br>
+<br>
</span>+    if (origPic->m_param-><wbr>bDynamicRefine)<br>
<span class="">+        CHECKED_MALLOC_ZERO(<wbr>blockVariance, uint32_t, cuCountFullRes);<br>
     CHECKED_MALLOC(propagateCost, uint16_t, cuCount);<br>
<br>
     /* allocate lowres buffers */<br>
</span>diff -r d292dacb81d8 -r e5425bd33176 source/encoder/analysis.cpp<br>
<div><div class="h5">--- a/source/encoder/analysis.cpp       Fri Mar 09 09:44:53 2018 +0530<br>
+++ b/source/encoder/analysis.cpp       Fri Mar 09 17:09:39 2018 +0530<br>
@@ -1184,7 +1184,7 @@<br>
<br>
         if (m_evaluateInter)<br>
         {<br>
-            if (m_param->interRefine == 2)<br>
+            if (m_refineLevel == 2)<br>
             {<br>
                 if (parentCTU.m_predMode[cuGeom.<wbr>absPartIdx] == MODE_SKIP)<br>
                     skipModes = true;<br>
@@ -1307,7 +1307,7 @@<br>
             md.pred[PRED_SKIP].cu.<wbr>initSubCU(parentCTU, cuGeom, qp);<br>
             checkMerge2Nx2N_rd0_4(md.pred[<wbr>PRED_SKIP], md.pred[PRED_MERGE], cuGeom);<br>
             if (m_param->rdLevel)<br>
-                skipModes = (m_param->bEnableEarlySkip || m_param->interRefine == 2)<br>
+                skipModes = (m_param->bEnableEarlySkip || m_refineLevel == 2)<br>
                 && md.bestMode && md.bestMode->cu.isSkipped(0); // TODO: sa8d threshold per depth<br>
         }<br>
         if (md.bestMode && m_param->bEnableRecursionSkip && !bCtuInfoCheck && !(m_param->bMVType && m_param->analysisReuseLevel == 7 && (m_modeFlag[0] || m_modeFlag[1])))<br>
@@ -1874,7 +1874,7 @@<br>
<br>
         if (m_evaluateInter)<br>
         {<br>
-            if (m_param->interRefine == 2)<br>
+            if (m_refineLevel == 2)<br>
             {<br>
                 if (parentCTU.m_predMode[cuGeom.<wbr>absPartIdx] == MODE_SKIP)<br>
                     skipModes = true;<br>
@@ -2004,7 +2004,7 @@<br>
             md.pred[PRED_SKIP].cu.<wbr>initSubCU(parentCTU, cuGeom, qp);<br>
             md.pred[PRED_MERGE].cu.<wbr>initSubCU(parentCTU, cuGeom, qp);<br>
             checkMerge2Nx2N_rd5_6(md.pred[<wbr>PRED_SKIP], md.pred[PRED_MERGE], cuGeom);<br>
-            skipModes = (m_param->bEnableEarlySkip || m_param->interRefine == 2) &&<br>
+            skipModes = (m_param->bEnableEarlySkip || m_refineLevel == 2) &&<br>
                 md.bestMode && !md.bestMode->cu.getQtRootCbf(<wbr>0);<br>
             refMasks[0] = allSplitRefs;<br>
             md.pred[PRED_2Nx2N].cu.<wbr>initSubCU(parentCTU, cuGeom, qp);<br>
@@ -2413,7 +2413,16 @@<br>
     bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);<br>
     bool bDecidedDepth = parentCTU.m_cuDepth[cuGeom.<wbr>absPartIdx] == depth;<br>
<br>
-    int split = (m_param->interRefine && cuGeom.log2CUSize == (uint32_t)(g_log2Size[m_param-<wbr>>minCUSize] + 1) && bDecidedDepth);<br>
+    TrainingData td;<br>
+    td.init(parentCTU, cuGeom);<br>
+<br>
+    if (!m_param->bDynamicRefine)<br>
+        m_refineLevel = m_param->interRefine;<br>
+    else<br>
+        m_refineLevel = m_frame->m_classifyFrame ? 0 : 3;<br>
+<br>
+    int split = (m_refineLevel && cuGeom.log2CUSize == (uint32_t)(g_log2Size[m_param-<wbr>>minCUSize] + 1) && bDecidedDepth);<br>
+    td.split = split;<br>
<br>
     if (bDecidedDepth)<br>
     {<br>
@@ -2423,7 +2432,7 @@<br>
         md.bestMode = &mode;<br>
         mode.cu.initSubCU(parentCTU, cuGeom, qp);<br>
         PartSize size = (PartSize)parentCTU.m_<wbr>partSize[cuGeom.absPartIdx];<br>
-        if (parentCTU.isIntra(cuGeom.<wbr>absPartIdx) && m_param->interRefine < 2)<br>
+        if (parentCTU.isIntra(cuGeom.<wbr>absPartIdx) && m_refineLevel < 2)<br>
         {<br>
             if (m_param->intraRefine == 4)<br>
                 compressIntraCU(parentCTU, cuGeom, qp);<br>
@@ -2439,7 +2448,7 @@<br>
                 checkIntra(mode, cuGeom, size);<br>
             }<br>
         }<br>
-        else if (!parentCTU.isIntra(cuGeom.<wbr>absPartIdx) && m_param->interRefine < 2)<br>
+        else if (!parentCTU.isIntra(cuGeom.<wbr>absPartIdx) && m_refineLevel < 2)<br>
         {<br>
             mode.cu.copyFromPic(parentCTU, cuGeom, m_csp, false);<br>
             uint32_t numPU = parentCTU.getNumPartInter(<wbr>cuGeom.absPartIdx);<br>
@@ -2501,7 +2510,7 @@<br>
                 }<br>
                 motionCompensation(<a href="http://mode.cu" rel="noreferrer" target="_blank">mode.cu</a>, pu, mode.predYuv, true, (m_csp != X265_CSP_I400 && m_frame->m_fencPic->m_picCsp != X265_CSP_I400));<br>
             }<br>
-            if (!m_param->interRefine && parentCTU.isSkipped(cuGeom.<wbr>absPartIdx))<br>
+            if (!m_param->interRefine && !m_param->bDynamicRefine && parentCTU.isSkipped(cuGeom.<wbr>absPartIdx))<br>
                 encodeResAndCalcRdSkipCU(mode)<wbr>;<br>
             else<br>
                 encodeResAndCalcRdInterCU(<wbr>mode, cuGeom);<br>
@@ -2512,7 +2521,7 @@<br>
                 checkDQP(mode, cuGeom);<br>
         }<br>
<br>
-        if (m_param->interRefine < 2)<br>
+        if (m_refineLevel < 2)<br>
         {<br>
             if (m_bTryLossless)<br>
                 tryLossless(cuGeom);<br>
@@ -2540,7 +2549,10 @@<br>
             }<br>
         }<br>
<br>
-        if (m_param->interRefine > 1 || (m_param->interRefine && parentCTU.m_predMode[cuGeom.<wbr>absPartIdx] == MODE_SKIP  && !mode.cu.isSkipped(0)))<br>
+        if (m_param->bDynamicRefine)<br>
+            classifyCU(parentCTU,cuGeom, *md.bestMode, td);<br>
+<br>
+        if (m_refineLevel > 1 || (m_refineLevel && parentCTU.m_predMode[cuGeom.<wbr>absPartIdx] == MODE_SKIP  && !mode.cu.isSkipped(0)))<br>
         {<br>
             m_evaluateInter = 1;<br>
             m_param->rdLevel > 4 ? compressInterCU_rd5_6(<wbr>parentCTU, cuGeom, qp) : compressInterCU_rd0_4(<wbr>parentCTU, cuGeom, qp);<br>
@@ -2599,7 +2611,7 @@<br>
         else<br>
             updateModeCost(*splitPred);<br>
<br>
-        if (m_param->interRefine)<br>
+        if (m_refineLevel)<br>
         {<br>
             if (m_param->rdLevel > 1)<br>
                 checkBestMode(*splitPred, cuGeom.depth);<br>
@@ -2613,6 +2625,83 @@<br>
         md.bestMode->cu.copyToPic(<wbr>depth);<br>
         md.bestMode->reconYuv.<wbr>copyToPicYuv(*m_frame->m_<wbr>reconPic, parentCTU.m_cuAddr, cuGeom.absPartIdx);<br>
     }<br>
+    if (m_param->bDynamicRefine && bDecidedDepth)<br>
+        trainCU(parentCTU, cuGeom, *md.bestMode, td);<br>
+}<br>
+<br>
+void Analysis::classifyCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData)<br>
+{<br>
+    uint32_t depth = cuGeom.depth;<br>
+    trainData.cuVariance = calculateCUVariance(ctu, cuGeom);<br>
+    if (m_frame->m_classifyFrame)<br>
+    {<br>
+        uint64_t diffRefine[X265_REFINE_INTER_<wbr>LEVELS];<br>
+        uint64_t diffRefineRd[X265_REFINE_<wbr>INTER_LEVELS];<br>
+        float probRefine[X265_REFINE_INTER_<wbr>LEVELS] = { 0 };<br>
+        uint8_t varRefineLevel = 0;<br>
+        uint8_t rdRefineLevel = 0;<br>
+        uint64_t cuCost = bestMode.rdCost;<br>
+<br>
+        int offset = (depth * X265_REFINE_INTER_LEVELS) + 1;<br>
+        if (cuCost < m_frame->m_classifyRd[offset])<br>
+            m_refineLevel = 1;<br>
+        else<br>
+        {<br>
+            uint64_t trainingCount = 0;<br>
+            for (uint8_t i = 0; i < X265_REFINE_INTER_LEVELS; i++)<br>
+            {<br>
+                offset = (depth * X265_REFINE_INTER_LEVELS) + i;<br>
+                trainingCount += m_frame->m_classifyCount[<wbr>offset];<br>
+            }<br>
+            for (uint8_t i = 0; i < X265_REFINE_INTER_LEVELS; i++)<br>
+            {<br>
+                offset = (depth * X265_REFINE_INTER_LEVELS) + i;<br>
+                /* Calculate distance values */<br>
+                diffRefine[i] = abs((int64_t)(trainData.<wbr>cuVariance - m_frame->m_classifyVariance[<wbr>offset]));<br>
+                diffRefineRd[i] = abs((int64_t)(cuCost - m_frame->m_classifyRd[offset])<wbr>);<br>
+<br>
+                /* Calculate prior probability - ranges between 0 and 1 */<br>
+                if (trainingCount)<br>
+                    probRefine[i] = ((float)m_frame->m_<wbr>classifyCount[offset] / (float)trainingCount);<br>
+<br>
+                /* Bayesian classification - P(c|x)P(x) = P(x|c)P(c)<br>
+                P(c|x) is the posterior probability of class given predictor.<br>
+                P(c) is the prior probability of class.<br>
+                P(x|c) is the likelihood which is the probability of predictor given class.<br>
+                P(x) is the prior probability of predictor.*/<br>
+                if ((diffRefine[i] * probRefine[m_refineLevel]) < (diffRefine[m_refineLevel] * probRefine[i]))<br>
+                    varRefineLevel = i;<br>
+                if ((diffRefineRd[i] * probRefine[m_refineLevel]) < (diffRefineRd[m_refineLevel] * probRefine[i]))<br>
+                    rdRefineLevel = i;<br>
+            }<br>
+            m_refineLevel = X265_MAX(varRefineLevel, rdRefineLevel);<br>
+        }<br>
+    }<br>
+}<br>
+<br>
+void Analysis::trainCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData)<br>
+{<br>
+    uint32_t depth = cuGeom.depth;<br>
+    int classify = 0;<br>
+    if (!m_frame->m_classifyFrame)<br>
+    {<br>
+        if (trainData.predMode == ctu.m_predMode[cuGeom.<wbr>absPartIdx] && trainData.partSize == ctu.m_partSize[cuGeom.<wbr>absPartIdx]<br>
+            && trainData.mergeFlag == ctu.m_mergeFlag[cuGeom.<wbr>absPartIdx])<br>
+            classify = 0;<br>
+        else if ((depth == m_param->maxCUDepth - 1) && trainData.split)<br>
+            classify = 1;<br>
+        else if (trainData.partSize == SIZE_2Nx2N && trainData.partSize == ctu.m_partSize[cuGeom.<wbr>absPartIdx])<br>
+            classify = 2;<br>
+        else<br>
+            classify = 3;<br>
+    }<br>
+    else<br>
+        classify = m_refineLevel;<br>
+    uint64_t cuCost = bestMode.rdCost;<br>
+    int offset = (depth * X265_REFINE_INTER_LEVELS) + classify;<br>
+    ctu.m_collectCURd[offset] += cuCost;<br>
+    ctu.m_collectCUVariance[<wbr>offset] += trainData.cuVariance;<br>
+    ctu.m_collectCUCount[offset]++<wbr>;<br>
 }<br>
<br>
 /* sets md.bestMode if a valid merge candidate is found, else leaves it NULL */<br>
@@ -3414,6 +3503,33 @@<br>
     return false;<br>
 }<br>
<br>
+uint32_t Analysis::calculateCUVariance(<wbr>const CUData& ctu, const CUGeom& cuGeom)<br>
+{<br>
+    uint32_t cuVariance = 0;<br>
+    uint32_t *blockVariance = m_frame->m_lowres.<wbr>blockVariance;<br>
+    int loopIncr = (m_param->rc.qgSize == 8) ? 8 : 16;<br>
+<br>
+    uint32_t width = m_frame->m_fencPic->m_<wbr>picWidth;<br>
+    uint32_t height = m_frame->m_fencPic->m_<wbr>picHeight;<br>
+    uint32_t block_x = ctu.m_cuPelX + g_zscanToPelX[cuGeom.<wbr>absPartIdx];<br>
+    uint32_t block_y = ctu.m_cuPelY + g_zscanToPelY[cuGeom.<wbr>absPartIdx];<br>
+    uint32_t maxCols = (m_frame->m_fencPic->m_<wbr>picWidth + (loopIncr - 1)) / loopIncr;<br>
+    uint32_t blockSize = m_param->maxCUSize >> cuGeom.depth;<br>
+    uint32_t cnt = 0;<br>
+<br>
+    for (uint32_t block_yy = block_y; block_yy < block_y + blockSize && block_yy < height; block_yy += loopIncr)<br>
+    {<br>
+        for (uint32_t block_xx = block_x; block_xx < block_x + blockSize && block_xx < width; block_xx += loopIncr)<br>
+        {<br>
+            uint32_t idx = ((block_yy / loopIncr) * (maxCols)) + (block_xx / loopIncr);<br>
+            cuVariance += blockVariance[idx];<br>
+            cnt++;<br>
+        }<br>
+    }<br>
+<br>
+    return cuVariance / cnt;<br>
+}<br>
+<br>
 int Analysis::<wbr>calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom, int32_t complexCheck, double baseQp)<br>
 {<br>
     FrameData& curEncData = *m_frame->m_encData;<br>
</div></div>diff -r d292dacb81d8 -r e5425bd33176 source/encoder/analysis.h<br>
<div><div class="h5">--- a/source/encoder/analysis.h Fri Mar 09 09:44:53 2018 +0530<br>
+++ b/source/encoder/analysis.h Fri Mar 09 17:09:39 2018 +0530<br>
@@ -142,8 +142,29 @@<br>
     uint8_t*                m_multipassModes;<br>
<br>
     uint8_t                 m_evaluateInter;<br>
+    int32_t                 m_refineLevel;<br>
+<br>
     uint8_t*                m_additionalCtuInfo;<br>
     int*                    m_prevCtuInfoChange;<br>
+<br>
+    struct TrainingData<br>
+    {<br>
+        uint32_t cuVariance;<br>
+        uint8_t predMode;<br>
+        uint8_t partSize;<br>
+        uint8_t mergeFlag;<br>
+        int split;<br>
+<br>
+        void init(const CUData& parentCTU, const CUGeom& cuGeom)<br>
+        {<br>
+            cuVariance = 0;<br>
+            predMode = parentCTU.m_predMode[cuGeom.<wbr>absPartIdx];<br>
+            partSize = parentCTU.m_partSize[cuGeom.<wbr>absPartIdx];<br>
+            mergeFlag = parentCTU.m_mergeFlag[cuGeom.<wbr>absPartIdx];<br>
+            split = 0;<br>
+        }<br>
+    };<br>
+<br>
     /* refine RD based on QP for rd-levels 5 and 6 */<br>
     void qprdRefine(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, int32_t lqp);<br>
<br>
@@ -182,6 +203,10 @@<br>
     void encodeResidue(const CUData& parentCTU, const CUGeom& cuGeom);<br>
<br>
     int calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom, int32_t complexCheck = 0, double baseQP = -1);<br>
+    uint32_t calculateCUVariance(const CUData& ctu, const CUGeom& cuGeom);<br>
+<br>
+    void classifyCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData);<br>
+    void trainCU(const CUData& ctu, const CUGeom& cuGeom, const Mode& bestMode, TrainingData& trainData);<br>
<br>
     void calculateNormFactor(CUData& ctu, int qp);<br>
     void normFactor(const pixel* src, uint32_t blockSize, CUData& ctu, int qp, TextType ttype);<br>
</div></div>diff -r d292dacb81d8 -r e5425bd33176 source/encoder/encoder.cpp<br>
<div><div class="h5">--- a/source/encoder/encoder.cpp        Fri Mar 09 09:44:53 2018 +0530<br>
+++ b/source/encoder/encoder.cpp        Fri Mar 09 17:09:39 2018 +0530<br>
@@ -96,6 +96,7 @@<br>
 #endif<br>
<br>
     m_prevTonemapPayload.payload = NULL;<br>
+    m_startPoint = 0;<br>
 }<br>
 inline char *strcatFilename(const char *input, const char *suffix)<br>
 {<br>
@@ -412,6 +413,17 @@<br>
     if (m_bToneMap)<br>
         m_numCimInfo = m_hdr10plus_api->hdr10plus_<wbr>json_to_movie_cim(m_param-><wbr>toneMapFile, m_cim);<br>
 #endif<br>
+<br>
+    if (m_param->bDynamicRefine)<br>
+    {<br>
+        int size = m_param->totalFrames * m_param->maxCUDepth * X265_REFINE_INTER_LEVELS;<br>
+        CHECKED_MALLOC_ZERO(m_<wbr>variance, uint64_t, size);<br>
+        CHECKED_MALLOC_ZERO(m_rdCost, uint64_t, size);<br>
+        CHECKED_MALLOC_ZERO(m_<wbr>trainingCount, uint32_t, size);<br>
+        return;<br>
+    fail:<br>
+        m_aborted = true;<br>
+    }<br>
 }<br>
<br>
 void Encoder::stopJobs()<br>
@@ -697,7 +709,13 @@<br>
     if (m_bToneMap)<br>
         m_hdr10plus_api->hdr10plus_<wbr>clear_movie(m_cim, m_numCimInfo);<br>
 #endif<br>
-<br>
+<br>
+    if (m_param->bDynamicRefine)<br>
+    {<br>
+        X265_FREE(m_variance);<br>
+        X265_FREE(m_rdCost);<br>
+        X265_FREE(m_trainingCount);<br>
+    }<br>
     if (m_exportedPic)<br>
     {<br>
         ATOMIC_DEC(&m_exportedPic->m_<wbr>countRefEncoders);<br>
</div></div>diff -r d292dacb81d8 -r e5425bd33176 source/encoder/encoder.h<br>
<span class="">--- a/source/encoder/encoder.h  Fri Mar 09 09:44:53 2018 +0530<br>
+++ b/source/encoder/encoder.h  Fri Mar 09 17:09:39 2018 +0530<br>
@@ -221,6 +221,13 @@<br>
<br>
     x265_sei_payload        m_prevTonemapPayload;<br>
<br>
+    /* Collect frame level feature data */<br>
+    uint64_t*               m_rdCost;<br>
+    uint64_t*               m_variance;<br>
+    uint32_t*               m_trainingCount;<br>
+    int32_t                 m_startPoint;<br>
+    Lock                    m_dynamicRefineLock;<br>
+<br>
     Encoder();<br>
     ~Encoder()<br>
     {<br>
</span>diff -r d292dacb81d8 -r e5425bd33176 source/encoder/frameencoder.<wbr>cpp<br>
<span class="">--- a/source/encoder/frameencoder.<wbr>cpp   Fri Mar 09 09:44:53 2018 +0530<br>
+++ b/source/encoder/frameencoder.<wbr>cpp   Fri Mar 09 17:09:39 2018 +0530<br>
@@ -736,6 +736,9 @@<br>
             m_top->m_rateControl->m_<wbr>startEndOrder.incr(); // faked rateControlEnd calls for negative frames<br>
     }<br>
<br>
+    if (m_param->bDynamicRefine)<br>
</span>+        computeAvgTrainingData();<br>
<div><div class="h5">+<br>
     /* Analyze CTU rows, most of the hard work is done here.  Frame is<br>
      * compressed in a wave-front pattern if WPP is enabled. Row based loop<br>
      * filters runs behind the CTU compression and reconstruction */<br>
@@ -1457,6 +1460,30 @@<br>
         // Does all the CU analysis, returns best top level mode decision<br>
         Mode& best = tld.analysis.compressCTU(*ctu, *m_frame, m_cuGeoms[m_ctuGeomMap[cuAddr]<wbr>], rowCoder);<br>
<br>
+        if (m_param->bDynamicRefine)<br>
+        {<br>
+            {<br>
+                ScopedLock dynLock(m_top->m_<wbr>dynamicRefineLock);<br>
+                for (uint32_t i = 0; i < X265_REFINE_INTER_LEVELS; i++)<br>
+                {<br>
+                    for (uint32_t depth = 0; depth < m_param->maxCUDepth; depth++)<br>
+                    {<br>
+                        int offset = (depth * X265_REFINE_INTER_LEVELS) + i;<br>
+                        int index = (m_frame->m_encodeOrder * X265_REFINE_INTER_LEVELS * m_param->maxCUDepth) + offset;<br>
+                        if (ctu->m_collectCUCount[offset]<wbr>)<br>
+                        {<br>
+                            m_top->m_variance[index] += ctu->m_collectCUVariance[<wbr>offset];<br>
+                            m_top->m_rdCost[index] += ctu->m_collectCURd[offset];<br>
+                            m_top->m_trainingCount[index] += ctu->m_collectCUCount[offset];<br>
+                        }<br>
+                    }<br>
+                }<br>
+            }<br>
+            X265_FREE_ZERO(ctu->m_<wbr>collectCUVariance);<br>
+            X265_FREE_ZERO(ctu->m_<wbr>collectCURd);<br>
+            X265_FREE_ZERO(ctu->m_<wbr>collectCUCount);<br>
+        }<br>
+<br>
         // take a sample of the current active worker count<br>
         ATOMIC_ADD(&m_<wbr>totalActiveWorkerCount, m_activeWorkerCount);<br>
         ATOMIC_INC(&m_<wbr>activeWorkerCountSamples);<br>
@@ -1839,6 +1866,58 @@<br>
         m_completionEvent.trigger();<br>
 }<br>
<br>
</div></div>+void FrameEncoder::<wbr>computeAvgTrainingData()<br>
<div><div class="h5">+{<br>
+    if (m_frame->m_lowres.bScenecut)<br>
+        m_top->m_startPoint = m_frame->m_encodeOrder;<br>
+<br>
+    if (m_frame->m_encodeOrder - m_top->m_startPoint < 2 * m_param->frameNumThreads)<br>
+        m_frame->m_classifyFrame = false;<br>
+    else<br>
+        m_frame->m_classifyFrame = true;<br>
+<br>
+    int size = m_param->maxCUDepth * X265_REFINE_INTER_LEVELS;<br>
+    memset(m_frame->m_classifyRd, 0, size * sizeof(uint64_t));<br>
+    memset(m_frame->m_<wbr>classifyVariance, 0, size * sizeof(uint64_t));<br>
+    memset(m_frame->m_<wbr>classifyCount, 0, size * sizeof(uint32_t));<br>
+<br>
+    if (m_frame->m_classifyFrame)<br>
+    {<br>
+        uint32_t limit = m_frame->m_encodeOrder - m_param->frameNumThreads - 1;<br>
+        for (uint32_t i = m_top->m_startPoint + 1; i < limit; i++)<br>
+        {<br>
+            for (uint32_t j = 0; j < X265_REFINE_INTER_LEVELS; j++)<br>
+            {<br>
+                for (uint32_t depth = 0; depth < m_param->maxCUDepth; depth++)<br>
+                {<br>
+                    int offset = (depth * X265_REFINE_INTER_LEVELS) + j;<br>
+                    int index = (i* X265_REFINE_INTER_LEVELS * m_param->maxCUDepth) + offset;<br>
+                    if (m_top->m_trainingCount[index]<wbr>)<br>
+                    {<br>
+                        m_frame->m_classifyRd[offset] += m_top->m_rdCost[index] / m_top->m_trainingCount[index];<br>
+                        m_frame->m_classifyVariance[<wbr>offset] += m_top->m_variance[index] / m_top->m_trainingCount[index];<br>
+                        m_frame->m_classifyCount[<wbr>offset] += m_top->m_trainingCount[index];<br>
+                    }<br>
+                }<br>
+            }<br>
+        }<br>
+        /* Calculates the average feature values of historic frames that are being considered for the current frame */<br>
+        int historyCount = m_frame->m_encodeOrder - m_param->frameNumThreads - m_top->m_startPoint - 1;<br>
+        if (historyCount)<br>
+        {<br>
+            for (uint32_t j = 0; j < X265_REFINE_INTER_LEVELS; j++)<br>
+            {<br>
+                for (uint32_t depth = 0; depth < m_param->maxCUDepth; depth++)<br>
+                {<br>
+                    int offset = (depth * X265_REFINE_INTER_LEVELS) + j;<br>
+                    m_frame->m_classifyRd[offset] /= historyCount;<br>
+                    m_frame->m_classifyVariance[<wbr>offset] /= historyCount;<br>
+                }<br>
+            }<br>
+        }<br>
+    }<br>
+}<br>
+<br>
 /* collect statistics about CU coding decisions, return total QP */<br>
 int FrameEncoder::<wbr>collectCTUStatistics(const CUData& ctu, FrameStats* log)<br>
 {<br>
</div></div>diff -r d292dacb81d8 -r e5425bd33176 source/encoder/frameencoder.h<br>
<span class="">--- a/source/encoder/frameencoder.<wbr>h     Fri Mar 09 09:44:53 2018 +0530<br>
+++ b/source/encoder/frameencoder.<wbr>h     Fri Mar 09 17:09:39 2018 +0530<br>
@@ -230,6 +230,7 @@<br>
     void threadMain();<br>
     int  collectCTUStatistics(const CUData& ctu, FrameStats* frameLog);<br>
     void noiseReductionUpdate();<br>
</span>+    void computeAvgTrainingData();<br>
<span class=""><br>
     /* Called by WaveFront::findJob() */<br>
     virtual void processRow(int row, int threadId);<br>
</span>diff -r d292dacb81d8 -r e5425bd33176 source/encoder/slicetype.cpp<br>
<div class="HOEnZb"><div class="h5">--- a/source/encoder/slicetype.cpp      Fri Mar 09 09:44:53 2018 +0530<br>
+++ b/source/encoder/slicetype.cpp      Fri Mar 09 17:09:39 2018 +0530<br>
@@ -178,12 +178,12 @@<br>
             }<br>
         }<br>
<br>
-        /* Need variance data for weighted prediction */<br>
+        /* Need variance data for weighted prediction and dynamic refinement*/<br>
         if (param->bEnableWeightedPred || param->bEnableWeightedBiPred)<br>
-        {<br>
+        {<br>
             for (blockY = 0; blockY < maxRow; blockY += loopIncr)<br>
-                for (blockX = 0; blockX < maxCol; blockX += loopIncr)<br>
-                    acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);<br>
+                for (blockX = 0; blockX < maxCol; blockX += loopIncr)<br>
+                    acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);<br>
         }<br>
     }<br>
     else<br>
@@ -240,7 +240,7 @@<br>
                 else<br>
                 {<br>
                     uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp,param->rc.<wbr>qgSize);<br>
-                    qp_adj = strength * (X265_LOG2(X265_MAX(energy, 1)) - (modeOneConst + 2 * (X265_DEPTH - 8)));<br>
+                    qp_adj = strength * (X265_LOG2(X265_MAX(energy, 1)) - (modeOneConst + 2 * (X265_DEPTH - 8)));<br>
                 }<br>
<br>
                 if (param->bHDROpt)<br>
@@ -308,6 +308,17 @@<br>
             curFrame->m_lowres.wp_ssd[i] = ssd - (sum * sum + (width[i] * height[i]) / 2) / (width[i] * height[i]);<br>
         }<br>
     }<br>
+<br>
+    if (param->bDynamicRefine)<br>
+    {<br>
+        blockXY = 0;<br>
+        for (blockY = 0; blockY < maxRow; blockY += loopIncr)<br>
+            for (blockX = 0; blockX < maxCol; blockX += loopIncr)<br>
+            {<br>
+                curFrame->m_lowres.<wbr>blockVariance[blockXY] = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize);<br>
+                blockXY++;<br>
+            }<br>
+    }<br>
 }<br>
<br>
 void LookaheadTLD::<wbr>lowresIntraEstimate(Lowres& fenc, uint32_t qgSize)<br>
</div></div><br>______________________________<wbr>_________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/<wbr>listinfo/x265-devel</a><br>
<br></blockquote></div><br></div><div class="gmail_extra">Pushed.</div></div>