[x265] [PATCH] search: make bMergeOnly argument to predInterSearch more of a suggestion

Steve Borho steve at borho.org
Mon Feb 23 16:42:31 CET 2015


# HG changeset patch
# User Steve Borho <steve at borho.org>
# Date 1424705753 21600
#      Mon Feb 23 09:35:53 2015 -0600
# Node ID da0d17f7866297d5b69fb901535f761986d3d2e7
# Parent  81c0dc7d05f7688319da8bea4c174adae21febf1
search: make bMergeOnly argument to predInterSearch more of a suggestion

predInterSearch() will only check merge candidates for PUs when bMergeOnly is
true, and currently returns false when no merge candidates are available. This
changes the logic to simply fall into uni-directional and bi-directional motion
estimation when no merge candidates are available and ignore the 'merge-only'
flag in these cases.

bMergeOnly is only used for AMP modes with 64x64 partitions, a performance
optimization from the HM which we have kept. It is perfectly valid to use ME for
these partitions, and better to have predInterSearch() always return an inter
mode rather than having to handle rare error conditions.

diff -r 81c0dc7d05f7 -r da0d17f78662 source/encoder/analysis.cpp
--- a/source/encoder/analysis.cpp	Mon Feb 23 16:54:42 2015 +0530
+++ b/source/encoder/analysis.cpp	Mon Feb 23 09:35:53 2015 -0600
@@ -1521,38 +1521,33 @@
             }
         }
     }
-    if (predInterSearch(interMode, cuGeom, false, m_bChromaSa8d))
+
+    predInterSearch(interMode, cuGeom, false, m_bChromaSa8d);
+
+    /* predInterSearch sets interMode.sa8dBits */
+    const Yuv& fencYuv = *interMode.fencYuv;
+    Yuv& predYuv = interMode.predYuv;
+    int part = partitionFromLog2Size(cuGeom.log2CUSize);
+    interMode.distortion = primitives.cu[part].sa8d(fencYuv.m_buf[0], fencYuv.m_size, predYuv.m_buf[0], predYuv.m_size);
+    if (m_bChromaSa8d)
     {
-        /* predInterSearch sets interMode.sa8dBits */
-        const Yuv& fencYuv = *interMode.fencYuv;
-        Yuv& predYuv = interMode.predYuv;
-        int part = partitionFromLog2Size(cuGeom.log2CUSize);
-        interMode.distortion = primitives.cu[part].sa8d(fencYuv.m_buf[0], fencYuv.m_size, predYuv.m_buf[0], predYuv.m_size);
-        if (m_bChromaSa8d)
+        interMode.distortion += primitives.chroma[m_csp].cu[part].sa8d(fencYuv.m_buf[1], fencYuv.m_csize, predYuv.m_buf[1], predYuv.m_csize);
+        interMode.distortion += primitives.chroma[m_csp].cu[part].sa8d(fencYuv.m_buf[2], fencYuv.m_csize, predYuv.m_buf[2], predYuv.m_csize);
+    }
+    interMode.sa8dCost = m_rdCost.calcRdSADCost(interMode.distortion, interMode.sa8dBits);
+
+    if (m_param->analysisMode == X265_ANALYSIS_SAVE && m_reuseInterDataCTU)
+    {
+        for (uint32_t puIdx = 0; puIdx < interMode.cu.getNumPartInter(); puIdx++)
         {
-            interMode.distortion += primitives.chroma[m_csp].cu[part].sa8d(fencYuv.m_buf[1], fencYuv.m_csize, predYuv.m_buf[1], predYuv.m_csize);
-            interMode.distortion += primitives.chroma[m_csp].cu[part].sa8d(fencYuv.m_buf[2], fencYuv.m_csize, predYuv.m_buf[2], predYuv.m_csize);
-        }
-        interMode.sa8dCost = m_rdCost.calcRdSADCost(interMode.distortion, interMode.sa8dBits);
-
-        if (m_param->analysisMode == X265_ANALYSIS_SAVE && m_reuseInterDataCTU)
-        {
-            for (uint32_t puIdx = 0; puIdx < interMode.cu.getNumPartInter(); puIdx++)
+            MotionData* bestME = interMode.bestME[puIdx];
+            for (int32_t i = 0; i < numPredDir; i++)
             {
-                MotionData* bestME = interMode.bestME[puIdx];
-                for (int32_t i = 0; i < numPredDir; i++)
-                {
-                    *m_reuseRef = bestME[i].ref;
-                    m_reuseRef++;
-                }
+                *m_reuseRef = bestME[i].ref;
+                m_reuseRef++;
             }
         }
     }
-    else
-    {
-        interMode.distortion = MAX_UINT;
-        interMode.sa8dCost = MAX_INT64;
-    }
 }
 
 void Analysis::checkInter_rd5_6(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, bool bMergeOnly)
@@ -1574,29 +1569,24 @@
             }
         }
     }
-    if (predInterSearch(interMode, cuGeom, bMergeOnly, true))
+
+    predInterSearch(interMode, cuGeom, bMergeOnly, true);
+
+    /* predInterSearch sets interMode.sa8dBits, but this is ignored */
+    encodeResAndCalcRdInterCU(interMode, cuGeom);
+
+    if (m_param->analysisMode == X265_ANALYSIS_SAVE && m_reuseInterDataCTU)
     {
-        /* predInterSearch sets interMode.sa8dBits, but this is ignored */
-        encodeResAndCalcRdInterCU(interMode, cuGeom);
-
-        if (m_param->analysisMode == X265_ANALYSIS_SAVE && m_reuseInterDataCTU)
+        for (uint32_t puIdx = 0; puIdx < interMode.cu.getNumPartInter(); puIdx++)
         {
-            for (uint32_t puIdx = 0; puIdx < interMode.cu.getNumPartInter(); puIdx++)
+            MotionData* bestME = interMode.bestME[puIdx];
+            for (int32_t i = 0; i < numPredDir; i++)
             {
-                MotionData* bestME = interMode.bestME[puIdx];
-                for (int32_t i = 0; i < numPredDir; i++)
-                {
-                    *m_reuseRef = bestME[i].ref;
-                    m_reuseRef++;
-                }
+                *m_reuseRef = bestME[i].ref;
+                m_reuseRef++;
             }
         }
     }
-    else
-    {
-        interMode.distortion = MAX_UINT;
-        interMode.rdCost = MAX_INT64;
-    }
 }
 
 void Analysis::checkBidir2Nx2N(Mode& inter2Nx2N, Mode& bidir2Nx2N, const CUGeom& cuGeom)
diff -r 81c0dc7d05f7 -r da0d17f78662 source/encoder/search.cpp
--- a/source/encoder/search.cpp	Mon Feb 23 16:54:42 2015 +0530
+++ b/source/encoder/search.cpp	Mon Feb 23 09:35:53 2015 -0600
@@ -1926,9 +1926,8 @@
     }
 }
 
-/* search of the best candidate for inter prediction
- * returns true if predYuv was filled with a motion compensated prediction */
-bool Search::predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bMergeOnly, bool bChromaSA8D)
+/* find the best inter prediction for each PU of specified mode */
+void Search::predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bMergeOnly, bool bChromaSA8D)
 {
     ProfileCUScope(interMode.cu, motionEstimationElapsedTime, countMotionEstimate);
 
@@ -1969,15 +1968,8 @@
             merge.height     = m_puHeight;
             mrgCost = mergeEstimation(cu, cuGeom, puIdx, merge);
 
-            if (bMergeOnly)
+            if (bMergeOnly && mrgCost != MAX_UINT)
             {
-                if (mrgCost == MAX_UINT)
-                {
-                    /* No valid merge modes were found, there is no possible way to
-                     * perform a valid motion compensation prediction, so early-exit */
-                    return false;
-                }
-                // set merge result
                 cu.m_mergeFlag[m_puAbsPartIdx] = true;
                 cu.m_mvpIdx[0][m_puAbsPartIdx] = merge.index; // merge candidate ID is stored in L0 MVP idx
                 cu.setPUInterDir(merge.interDir, m_puAbsPartIdx, puIdx);
@@ -2359,7 +2351,6 @@
     }
 
     interMode.sa8dBits += totalmebits;
-    return true;
 }
 
 void Search::getBlkBits(PartSize cuMode, bool bPSlice, int partIdx, uint32_t lastMode, uint32_t blockBit[3])
diff -r 81c0dc7d05f7 -r da0d17f78662 source/encoder/search.h
--- a/source/encoder/search.h	Mon Feb 23 16:54:42 2015 +0530
+++ b/source/encoder/search.h	Mon Feb 23 09:35:53 2015 -0600
@@ -257,7 +257,7 @@
     void     encodeIntraInInter(Mode& intraMode, const CUGeom& cuGeom);
 
     // estimation inter prediction (non-skip)
-    bool     predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bMergeOnly, bool bChroma);
+    void     predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bMergeOnly, bool bChroma);
 
     // encode residual and compute rd-cost for inter mode
     void     encodeResAndCalcRdInterCU(Mode& interMode, const CUGeom& cuGeom);


More information about the x265-devel mailing list