[x265] [PATCH] analysis: fix blocking artifacts while sharing best merge candidate

gopu at multicorewareinc.com gopu at multicorewareinc.com
Mon Jun 15 11:02:30 CEST 2015


# HG changeset patch
# User Gopu Govindaswamy <gopu at multicorewareinc.com>
# Date 1434358942 -19800
#      Mon Jun 15 14:32:22 2015 +0530
# Node ID 9bab83c89429b8be40d3114b79e8d939f7ea5643
# Parent  32590b25678b5b87bf6beed4c3074ec3837d35da
analysis: fix blocking artifacts while sharing best merge candidate

While ecoding with --analysis-mode=load mode noticed there will blocking
artifacts, this issue is while sharing best merge candidate,

when sharing the merge candidate before selecting the best mode (SKIP MODE),
first encode merge with residual (no skip) and if this mode hasCbf then try
merge without residual(skip) then select the best mode (SKIP MODE) from this two

diff -r 32590b25678b -r 9bab83c89429 source/encoder/analysis.cpp
--- a/source/encoder/analysis.cpp	Fri Jun 12 16:48:06 2015 +0530
+++ b/source/encoder/analysis.cpp	Mon Jun 15 14:32:22 2015 +0530
@@ -1428,7 +1428,7 @@
 }
 
 /* sets md.bestMode if a valid merge candidate is found, else leaves it NULL */
-void Analysis::checkMerge2Nx2N_rd5_6(Mode& skip, Mode& merge, const CUGeom& cuGeom, bool isSkipMode)
+void Analysis::checkMerge2Nx2N_rd5_6(Mode& skip, Mode& merge, const CUGeom& cuGeom, bool isShareMergeCand)
 {
     uint32_t depth = cuGeom.depth;
 
@@ -1456,91 +1456,82 @@
     bool triedPZero = false, triedBZero = false;
     bestPred->rdCost = MAX_INT64;
 
-    if (isSkipMode)
+    uint32_t first = 0, last = numMergeCand;
+    if (isShareMergeCand)
+    {
+        first = *m_reuseBestMergeCand;
+        last = first + 1;
+    }
+
+    for (uint32_t i = first; i < last; i++)
     {
-        uint32_t i = *m_reuseBestMergeCand;
-        bestPred->cu.m_mvpIdx[0][0] = (uint8_t)i;
-        bestPred->cu.m_interDir[0] = candDir[i];
-        bestPred->cu.m_mv[0][0] = candMvField[i][0].mv;
-        bestPred->cu.m_mv[1][0] = candMvField[i][1].mv;
-        bestPred->cu.m_refIdx[0][0] = (int8_t)candMvField[i][0].refIdx;
-        bestPred->cu.m_refIdx[1][0] = (int8_t)candMvField[i][1].refIdx;
+        if (m_bFrameParallel &&
+            (candMvField[i][0].mv.y >= (m_param->searchRange + 1) * 4 ||
+            candMvField[i][1].mv.y >= (m_param->searchRange + 1) * 4))
+            continue;
 
-        motionCompensation(bestPred->cu, pu, bestPred->predYuv, true, true);
-        encodeResAndCalcRdSkipCU(*bestPred);
-    }
-    else
-    {
-        for (uint32_t i = 0; i < numMergeCand; i++)
+        /* the merge candidate list is packed with MV(0,0) ref 0 when it is not full */
+        if (candDir[i] == 1 && !candMvField[i][0].mv.word && !candMvField[i][0].refIdx)
         {
-            if (m_bFrameParallel &&
-                (candMvField[i][0].mv.y >= (m_param->searchRange + 1) * 4 ||
-                candMvField[i][1].mv.y >= (m_param->searchRange + 1) * 4))
+            if (triedPZero)
                 continue;
+            triedPZero = true;
+        }
+        else if (candDir[i] == 3 &&
+            !candMvField[i][0].mv.word && !candMvField[i][0].refIdx &&
+            !candMvField[i][1].mv.word && !candMvField[i][1].refIdx)
+        {
+            if (triedBZero)
+                continue;
+            triedBZero = true;
+        }
 
-            /* the merge candidate list is packed with MV(0,0) ref 0 when it is not full */
-            if (candDir[i] == 1 && !candMvField[i][0].mv.word && !candMvField[i][0].refIdx)
+        tempPred->cu.m_mvpIdx[0][0] = (uint8_t)i;    /* merge candidate ID is stored in L0 MVP idx */
+        tempPred->cu.m_interDir[0] = candDir[i];
+        tempPred->cu.m_mv[0][0] = candMvField[i][0].mv;
+        tempPred->cu.m_mv[1][0] = candMvField[i][1].mv;
+        tempPred->cu.m_refIdx[0][0] = (int8_t)candMvField[i][0].refIdx;
+        tempPred->cu.m_refIdx[1][0] = (int8_t)candMvField[i][1].refIdx;
+        tempPred->cu.setPredModeSubParts(MODE_INTER); /* must be cleared between encode iterations */
+
+        motionCompensation(tempPred->cu, pu, tempPred->predYuv, true, true);
+
+        uint8_t hasCbf = true;
+        bool swapped = false;
+        if (!foundCbf0Merge)
+        {
+            /* if the best prediction has CBF (not a skip) then try merge with residual */
+
+            encodeResAndCalcRdInterCU(*tempPred, cuGeom);
+            hasCbf = tempPred->cu.getQtRootCbf(0);
+            foundCbf0Merge = !hasCbf;
+
+            if (tempPred->rdCost < bestPred->rdCost)
             {
-                if (triedPZero)
-                    continue;
-                triedPZero = true;
+                std::swap(tempPred, bestPred);
+                swapped = true;
             }
-            else if (candDir[i] == 3 &&
-                !candMvField[i][0].mv.word && !candMvField[i][0].refIdx &&
-                !candMvField[i][1].mv.word && !candMvField[i][1].refIdx)
+        }
+        if (!m_param->bLossless && hasCbf)
+        {
+            /* try merge without residual (skip), if not lossless coding */
+
+            if (swapped)
             {
-                if (triedBZero)
-                    continue;
-                triedBZero = true;
+                tempPred->cu.m_mvpIdx[0][0] = (uint8_t)i;
+                tempPred->cu.m_interDir[0] = candDir[i];
+                tempPred->cu.m_mv[0][0] = candMvField[i][0].mv;
+                tempPred->cu.m_mv[1][0] = candMvField[i][1].mv;
+                tempPred->cu.m_refIdx[0][0] = (int8_t)candMvField[i][0].refIdx;
+                tempPred->cu.m_refIdx[1][0] = (int8_t)candMvField[i][1].refIdx;
+                tempPred->cu.setPredModeSubParts(MODE_INTER);
+                tempPred->predYuv.copyFromYuv(bestPred->predYuv);
             }
 
-            tempPred->cu.m_mvpIdx[0][0] = (uint8_t)i;    /* merge candidate ID is stored in L0 MVP idx */
-            tempPred->cu.m_interDir[0] = candDir[i];
-            tempPred->cu.m_mv[0][0] = candMvField[i][0].mv;
-            tempPred->cu.m_mv[1][0] = candMvField[i][1].mv;
-            tempPred->cu.m_refIdx[0][0] = (int8_t)candMvField[i][0].refIdx;
-            tempPred->cu.m_refIdx[1][0] = (int8_t)candMvField[i][1].refIdx;
-            tempPred->cu.setPredModeSubParts(MODE_INTER); /* must be cleared between encode iterations */
+            encodeResAndCalcRdSkipCU(*tempPred);
 
-            motionCompensation(tempPred->cu, pu, tempPred->predYuv, true, true);
-
-            uint8_t hasCbf = true;
-            bool swapped = false;
-            if (!foundCbf0Merge)
-            {
-                /* if the best prediction has CBF (not a skip) then try merge with residual */
-
-                encodeResAndCalcRdInterCU(*tempPred, cuGeom);
-                hasCbf = tempPred->cu.getQtRootCbf(0);
-                foundCbf0Merge = !hasCbf;
-
-                if (tempPred->rdCost < bestPred->rdCost)
-                {
-                    std::swap(tempPred, bestPred);
-                    swapped = true;
-                }
-            }
-            if (!m_param->bLossless && hasCbf)
-            {
-                /* try merge without residual (skip), if not lossless coding */
-
-                if (swapped)
-                {
-                    tempPred->cu.m_mvpIdx[0][0] = (uint8_t)i;
-                    tempPred->cu.m_interDir[0] = candDir[i];
-                    tempPred->cu.m_mv[0][0] = candMvField[i][0].mv;
-                    tempPred->cu.m_mv[1][0] = candMvField[i][1].mv;
-                    tempPred->cu.m_refIdx[0][0] = (int8_t)candMvField[i][0].refIdx;
-                    tempPred->cu.m_refIdx[1][0] = (int8_t)candMvField[i][1].refIdx;
-                    tempPred->cu.setPredModeSubParts(MODE_INTER);
-                    tempPred->predYuv.copyFromYuv(bestPred->predYuv);
-                }
-
-                encodeResAndCalcRdSkipCU(*tempPred);
-
-                if (tempPred->rdCost < bestPred->rdCost)
-                    std::swap(tempPred, bestPred);
-            }
+            if (tempPred->rdCost < bestPred->rdCost)
+                std::swap(tempPred, bestPred);
         }
     }
 
diff -r 32590b25678b -r 9bab83c89429 source/encoder/analysis.h
--- a/source/encoder/analysis.h	Fri Jun 12 16:48:06 2015 +0530
+++ b/source/encoder/analysis.h	Mon Jun 15 14:32:22 2015 +0530
@@ -118,7 +118,7 @@
 
     /* measure merge and skip */
     void checkMerge2Nx2N_rd0_4(Mode& skip, Mode& merge, const CUGeom& cuGeom);
-    void checkMerge2Nx2N_rd5_6(Mode& skip, Mode& merge, const CUGeom& cuGeom, bool isSkipMode);
+    void checkMerge2Nx2N_rd5_6(Mode& skip, Mode& merge, const CUGeom& cuGeom, bool isShareMergeCand);
 
     /* measure inter options */
     void checkInter_rd0_4(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, uint32_t refmask[2]);


More information about the x265-devel mailing list