<div dir="ltr"><div>Thanks, looks good. THis patch is not expected to change outputs in any way - so we need to watch out for regressions. <br><br></div>When the RDO cost of DQP bits is included, the mode costs should be updated after the checkDQP and checkDQPForSplitPred functions, not before.<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Mar 5, 2015 at 1:03 PM,  <span dir="ltr"><<a href="mailto:gopu@multicorewareinc.com" target="_blank">gopu@multicorewareinc.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Gopu Govindaswamy <<a href="mailto:gopu@multicorewareinc.com">gopu@multicorewareinc.com</a>><br>
# Date 1425540797 -19800<br>
#      Thu Mar 05 13:03:17 2015 +0530<br>
# Node ID ce2bd9e51497631f038110c227e164fe0ffcb5bf<br>
# Parent  ea9bdb10353fcb06cea1045ba0186c22c448df63<br>
dqp: add logic to encode DQP at depth zero and above as well<br>
<br>
Added the logic to check dqp for all sub-CU level<br>
checkDQP function moved into base class search<br>
<br>
diff -r ea9bdb10353f -r ce2bd9e51497 source/encoder/analysis.cpp<br>
--- a/source/encoder/analysis.cpp       Wed Mar 04 13:20:55 2015 +0530<br>
+++ b/source/encoder/analysis.cpp       Thu Mar 05 13:03:17 2015 +0530<br>
@@ -312,11 +312,11 @@<br>
             addSplitFlagCost(*splitPred, cuGeom.depth);<br>
         else<br>
             updateModeCost(*splitPred);<br>
+<br>
+        checkDQPForSplitPred(splitPred->cu, cuGeom);<br>
         checkBestMode(*splitPred, depth);<br>
     }<br>
<br>
-    checkDQP(md.bestMode->cu, cuGeom);<br>
-<br>
     /* Copy best data to encData CTU and recon */<br>
     md.bestMode->cu.copyToPic(depth);<br>
     if (md.bestMode != &md.pred[PRED_SPLIT])<br>
@@ -711,6 +711,7 @@<br>
         else<br>
             updateModeCost(*splitPred);<br>
<br>
+        checkDQPForSplitPred(splitPred->cu, cuGeom);<br>
         checkBestMode(*splitPred, depth);<br>
     }<br>
<br>
@@ -724,8 +725,6 @@<br>
         cuStat.avgCost[depth] = (temp + md.bestMode->rdCost) / cuStat.count[depth];<br>
     }<br>
<br>
-    checkDQP(md.bestMode->cu, cuGeom);<br>
-<br>
     /* Copy best data to encData CTU and recon */<br>
     md.bestMode->cu.copyToPic(depth);<br>
     if (md.bestMode != &md.pred[PRED_SPLIT])<br>
@@ -996,8 +995,9 @@<br>
             checkBestMode(*splitPred, cuGeom.depth);<br>
         else if (splitPred->sa8dCost < md.bestMode->sa8dCost)<br>
             md.bestMode = splitPred;<br>
+<br>
+        checkDQPForSplitPred(md.bestMode->cu, cuGeom);<br>
     }<br>
-<br>
     if (mightNotSplit)<br>
     {<br>
         /* early-out statistics */<br>
@@ -1008,8 +1008,6 @@<br>
         cuStat.avgCost[depth] = (temp + md.bestMode->rdCost) / cuStat.count[depth];<br>
     }<br>
<br>
-    checkDQP(md.bestMode->cu, cuGeom);<br>
-<br>
     /* Copy best data to encData CTU and recon */<br>
     md.bestMode->cu.copyToPic(depth);<br>
     if (md.bestMode != &md.pred[PRED_SPLIT] && m_param->rdLevel)<br>
@@ -1184,11 +1182,10 @@<br>
         else<br>
             updateModeCost(*splitPred);<br>
<br>
+        checkDQPForSplitPred(splitPred->cu, cuGeom);<br>
         checkBestMode(*splitPred, depth);<br>
     }<br>
<br>
-    checkDQP(md.bestMode->cu, cuGeom);<br>
-<br>
     /* Copy best data to encData CTU and recon */<br>
     md.bestMode->cu.copyToPic(depth);<br>
     if (md.bestMode != &md.pred[PRED_SPLIT])<br>
@@ -1296,6 +1293,7 @@<br>
     bestPred->cu.setPUMv(1, candMvField[bestSadCand][1].mv, 0, 0);<br>
     bestPred->cu.setPURefIdx(0, (int8_t)candMvField[bestSadCand][0].refIdx, 0, 0);<br>
     bestPred->cu.setPURefIdx(1, (int8_t)candMvField[bestSadCand][1].refIdx, 0, 0);<br>
+    checkDQP(bestPred->cu, cuGeom);<br>
 }<br>
<br>
 /* sets md.bestMode if a valid merge candidate is found, else leaves it NULL */<br>
@@ -1432,6 +1430,7 @@<br>
         if (m_param->analysisMode == X265_ANALYSIS_SAVE)<br>
             *m_reuseBestMergeCand = bestPred->cu.m_mvpIdx[0][0];<br>
     }<br>
+    checkDQP(bestPred->cu, cuGeom);<br>
 }<br>
<br>
 void Analysis::checkInter_rd0_4(Mode& interMode, const CUGeom& cuGeom, PartSize partSize)<br>
@@ -1759,7 +1758,6 @@<br>
                                                          predV, predYuv.m_csize);<br>
     }<br>
<br>
-    checkDQP(cu, cuGeom);<br>
     cu.updatePic(cuGeom.depth);<br>
 }<br>
<br>
@@ -1788,34 +1786,6 @@<br>
     }<br>
 }<br>
<br>
-void Analysis::checkDQP(CUData& cu, const CUGeom& cuGeom)<br>
-{<br>
-    if (m_slice->m_pps->bUseDQP && cuGeom.depth <= m_slice->m_pps->maxCuDQPDepth)<br>
-    {<br>
-        if (cu.m_cuDepth[0] > cuGeom.depth) // detect splits<br>
-        {<br>
-            bool hasResidual = false;<br>
-            for (uint32_t absPartIdx = 0; absPartIdx < cu.m_numPartitions; absPartIdx++)<br>
-            {<br>
-                if (cu.getQtRootCbf(absPartIdx))<br>
-                {<br>
-                    hasResidual = true;<br>
-                    break;<br>
-                }<br>
-            }<br>
-            if (hasResidual)<br>
-                cu.setQPSubCUs(cu.getRefQP(0), 0, cuGeom.depth);<br>
-            else<br>
-                cu.setQPSubParts(cu.getRefQP(0), 0, cuGeom.depth);<br>
-        }<br>
-        else<br>
-        {<br>
-            if (!cu.getCbf(0, TEXT_LUMA, 0) && !cu.getCbf(0, TEXT_CHROMA_U, 0) && !cu.getCbf(0, TEXT_CHROMA_V, 0))<br>
-                cu.setQPSubParts(cu.getRefQP(0), 0, cuGeom.depth);<br>
-        }<br>
-    }<br>
-}<br>
-<br>
 uint32_t Analysis::topSkipMinDepth(const CUData& parentCTU, const CUGeom& cuGeom)<br>
 {<br>
     /* Do not attempt to code a block larger than the largest block in the<br>
diff -r ea9bdb10353f -r ce2bd9e51497 source/encoder/analysis.h<br>
--- a/source/encoder/analysis.h Wed Mar 04 13:20:55 2015 +0530<br>
+++ b/source/encoder/analysis.h Thu Mar 05 13:03:17 2015 +0530<br>
@@ -132,9 +132,6 @@<br>
     /* add the RD cost of coding a split flag (0 or 1) to the given mode */<br>
     void addSplitFlagCost(Mode& mode, uint32_t depth);<br>
<br>
-    /* update CBF flags and QP values to be internally consistent */<br>
-    void checkDQP(CUData& cu, const CUGeom& cuGeom);<br>
-<br>
     /* work-avoidance heuristics for RD levels < 5 */<br>
     uint32_t topSkipMinDepth(const CUData& parentCTU, const CUGeom& cuGeom);<br>
     bool recursionDepthCheck(const CUData& parentCTU, const CUGeom& cuGeom, const Mode& bestMode);<br>
diff -r ea9bdb10353f -r ce2bd9e51497 source/encoder/search.cpp<br>
--- a/source/encoder/search.cpp Wed Mar 04 13:20:55 2015 +0530<br>
+++ b/source/encoder/search.cpp Thu Mar 05 13:03:17 2015 +0530<br>
@@ -1184,8 +1184,8 @@<br>
         const Yuv* fencYuv = intraMode.fencYuv;<br>
         intraMode.psyEnergy = m_rdCost.psyCost(cuGeom.log2CUSize - 2, fencYuv->m_buf[0], fencYuv->m_size, intraMode.reconYuv.m_buf[0], intraMode.reconYuv.m_size);<br>
     }<br>
-<br>
     updateModeCost(intraMode);<br>
+    checkDQP(cu, cuGeom);<br>
 }<br>
<br>
 /* Note that this function does not save the best intra prediction, it must<br>
@@ -1404,6 +1404,7 @@<br>
<br>
     m_entropyCoder.store(intraMode.contexts);<br>
     updateModeCost(intraMode);<br>
+    checkDQP(intraMode.cu, cuGeom);<br>
 }<br>
<br>
 uint32_t Search::estIntraPredQT(Mode &intraMode, const CUGeom& cuGeom, const uint32_t depthRange[2], uint8_t* sharedModes)<br>
@@ -2627,6 +2628,7 @@<br>
     interMode.coeffBits = coeffBits;<br>
     interMode.mvBits = bits - coeffBits;<br>
     updateModeCost(interMode);<br>
+    checkDQP(interMode.cu, cuGeom);<br>
 }<br>
<br>
 void Search::residualTransformQuantInter(Mode& mode, const CUGeom& cuGeom, uint32_t absPartIdx, uint32_t tuDepth, const uint32_t depthRange[2])<br>
@@ -3444,3 +3446,49 @@<br>
         candModeList[maxIndex] = mode;<br>
     }<br>
 }<br>
+<br>
+void Search::checkDQP(CUData& cu, const CUGeom& cuGeom)<br>
+{<br>
+    if (cu.m_slice->m_pps->bUseDQP && cuGeom.depth <= cu.m_slice->m_pps->maxCuDQPDepth)<br>
+    {<br>
+        if (cu.getQtRootCbf(0))<br>
+        {<br>
+            /* When analysing RDO with DQP bits, the entropy encoder should add the cost of DQP bits here<br>
+             * i.e Encode QP */<br>
+        }<br>
+        else<br>
+        {<br>
+            cu.setQPSubParts(cu.getRefQP(0), 0, cuGeom.depth);<br>
+        }<br>
+    }<br>
+}<br>
+<br>
+void Search::checkDQPForSplitPred(CUData& cu, const CUGeom& cuGeom)<br>
+{<br>
+    if ((cuGeom.depth == cu.m_slice->m_pps->maxCuDQPDepth) && cu.m_slice->m_pps->bUseDQP)<br>
+    {<br>
+        bool hasResidual = false;<br>
+<br>
+        /* Check if any sub-CU has a non-zero QP */<br>
+        for (uint32_t blkIdx = 0; blkIdx < cuGeom.numPartitions; blkIdx++)<br>
+        {<br>
+            if (cu.getQtRootCbf(blkIdx))<br>
+            {<br>
+                hasResidual = true;<br>
+                break;<br>
+            }<br>
+        }<br>
+        if (hasResidual)<br>
+        {<br>
+            /* TODO: Encode QP, and recalculate RD cost of splitPred */<br>
+            /* For all zero CBF sub-CUs, reset QP to RefQP (so that deltaQP is not signalled).<br>
+            When the non-zero CBF sub-CU is found, stop */<br>
+            bool ret = false;<br>
+            ret = cu.setQPSubCUs(cu.getRefQP(0), 0, cuGeom.depth);<br>
+            X265_CHECK(ret, "set sub QP CU failed\n");<br>
+        }<br>
+        else<br>
+            /* No residual within this CU or subCU, so reset QP to RefQP */<br>
+            cu.setQPSubParts(cu.getRefQP(0), 0, cuGeom.depth);<br>
+    }<br>
+}<br>
diff -r ea9bdb10353f -r ce2bd9e51497 source/encoder/search.h<br>
--- a/source/encoder/search.h   Wed Mar 04 13:20:55 2015 +0530<br>
+++ b/source/encoder/search.h   Thu Mar 05 13:03:17 2015 +0530<br>
@@ -281,6 +281,10 @@<br>
     // pick be chroma mode from available using just sa8d costs<br>
     void     getBestIntraModeChroma(Mode& intraMode, const CUGeom& cuGeom);<br>
<br>
+    /* update CBF flags and QP values to be internally consistent */<br>
+    void checkDQP(CUData& cu, const CUGeom& cuGeom);<br>
+    void checkDQPForSplitPred(CUData& cu, const CUGeom& cuGeom);<br>
+<br>
     class PME : public BondedTaskGroup<br>
     {<br>
     public:<br>
_______________________________________________<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" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</blockquote></div><br></div>