[x265] [PATCH] motion: Modify "--refine-mv" option

pooja at multicorewareinc.com pooja at multicorewareinc.com
Wed Jul 3 12:35:21 CEST 2019


# HG changeset patch
# User Pooja Venkatesan <pooja at multicorewareinc.com>
# Date 1561361420 -19800
#      Mon Jun 24 13:00:20 2019 +0530
# Node ID 7611cad0015151d1cfe076d9f40719afb327ef9c
# Parent  a46ded2c14116af1cafacdc1fb98be43259dc7d6
motion: Modify "--refine-mv" option

Add MV refinement level 1,2 and 3.
Based on the MV refinement level, number of search increases.

diff -r a46ded2c1411 -r 7611cad00151 doc/reST/cli.rst
--- a/doc/reST/cli.rst	Tue May 28 14:01:54 2019 +0800
+++ b/doc/reST/cli.rst	Mon Jun 24 13:00:20 2019 +0530
@@ -996,11 +996,16 @@
 	the encoder settings. It is recommended to use :option:`--refine-intra` 4 with dynamic 
 	refinement. Default disabled.
 
-.. option:: --refine-mv
-	
+.. option:: --refine-mv <0..3>
+
 	Enables refinement of motion vector for scaled video. Evaluates the best 
-	motion vector by searching the surrounding eight integer and subpel pixel
-	positions.
+	motion vector based on the level selected. Default 0 - disabled.
+
+	Level 1 - Search around scaled MV.
+
+	Level 2 - Level 1 + Search around best AMVP cand.
+
+	Level 3 - Level 2 + Search around the other AMVP cand.
 
 Options which affect the transform unit quad-tree, sometimes referred to
 as the residual quad-tree (RQT).
diff -r a46ded2c1411 -r 7611cad00151 source/common/param.cpp
--- a/source/common/param.cpp	Tue May 28 14:01:54 2019 +0800
+++ b/source/common/param.cpp	Mon Jun 24 13:00:20 2019 +0530
@@ -1195,7 +1195,7 @@
         OPT("scale-factor") p->scaleFactor = atoi(value);
         OPT("refine-intra")p->intraRefine = atoi(value);
         OPT("refine-inter")p->interRefine = atoi(value);
-        OPT("refine-mv")p->mvRefine = atobool(value);
+        OPT("refine-mv")p->mvRefine = atoi(value);
         OPT("force-flush")p->forceFlush = atoi(value);
         OPT("splitrd-skip") p->bEnableSplitRdSkip = atobool(value);
         OPT("lowpass-dct") p->bLowPassDct = atobool(value);
@@ -1614,6 +1614,8 @@
           "Strict-cbr cannot be applied without specifying target bitrate or vbv bufsize");
     CHECK((param->analysisSave || param->analysisLoad) && (param->analysisReuseLevel < 1 || param->analysisReuseLevel > 10),
         "Invalid analysis refine level. Value must be between 1 and 10 (inclusive)");
+    CHECK(param->analysisLoad && (param->mvRefine < 0 || param->mvRefine > 3),
+        "Invalid mv refinement level. Value must be between 0 and 3 (inclusive)");
     CHECK(param->scaleFactor > 2, "Invalid scale-factor. Supports factor <= 2");
     CHECK(param->rc.qpMax < QP_MIN || param->rc.qpMax > QP_MAX_MAX,
         "qpmax exceeds supported range (0 to 69)");
diff -r a46ded2c1411 -r 7611cad00151 source/encoder/analysis.cpp
--- a/source/encoder/analysis.cpp	Tue May 28 14:01:54 2019 +0800
+++ b/source/encoder/analysis.cpp	Mon Jun 24 13:00:20 2019 +0530
@@ -2488,14 +2488,18 @@
                             MV mvp;
 
                             int numMvc = mode.cu.getPMV(mode.interNeighbours, list, ref, mode.amvpCand[list][ref], mvc);
-                            if (m_param->interRefine != 1)
-                                mvp = mode.amvpCand[list][ref][mode.cu.m_mvpIdx[list][pu.puAbsPartIdx]];
-                            else
-                                mvp = interDataCTU->mv[list][cuIdx + part].word;
+                            mvp = mode.amvpCand[list][ref][mode.cu.m_mvpIdx[list][pu.puAbsPartIdx]];
                             if (m_param->mvRefine || m_param->interRefine == 1)
                             {
-                                MV outmv;
-                                searchMV(mode, pu, list, ref, outmv, mvp, numMvc, mvc);
+                                MV outmv, mvpSelect[3];
+                                mvpSelect[0] = interDataCTU->mv[list][cuIdx + part].word;
+                                switch (m_param->mvRefine)
+                                {
+                                case 3: mvpSelect[2] = mode.amvpCand[list][ref][!(mode.cu.m_mvpIdx[list][pu.puAbsPartIdx])];
+                                case 2: mvpSelect[1] = mvp;
+                                default: break;
+                                }
+                                searchMV(mode, list, ref, outmv, mvpSelect, numMvc, mvc);
                                 mode.cu.setPUMv(list, outmv, pu.puAbsPartIdx, part);
                             }
                             mode.cu.m_mvd[list][pu.puAbsPartIdx] = mode.cu.m_mv[list][pu.puAbsPartIdx] - mode.amvpCand[list][ref][mode.cu.m_mvpIdx[list][pu.puAbsPartIdx]]/*mvp*/;
diff -r a46ded2c1411 -r 7611cad00151 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Tue May 28 14:01:54 2019 +0800
+++ b/source/encoder/encoder.cpp	Mon Jun 24 13:00:20 2019 +0530
@@ -2983,11 +2983,11 @@
             x265_log(p, X265_LOG_WARNING, "MV refinement requires analysis load, analysis-reuse-level 10. Disabling MV refine.\n");
             p->mvRefine = 0;
         }
-        else if (p->interRefine >= 2)
-        {
-            x265_log(p, X265_LOG_WARNING, "MVs are recomputed when refine-inter >= 2. MV refinement not applicable. Disabling MV refine\n");
-            p->mvRefine = 0;
-        }
+    }
+    if (p->scaleFactor && p->analysisLoad && p->interRefine && p->analysisReuseLevel == 10 && !p->mvRefine)
+    {
+        x265_log(p, X265_LOG_WARNING, "Enabling MV refinement level 1 with scaling and analysis-reuse-level=10.\n");
+        p->mvRefine = 1;
     }
 
     if (p->ctuDistortionRefine == CTU_DISTORTION_INTERNAL)
diff -r a46ded2c1411 -r 7611cad00151 source/encoder/search.cpp
--- a/source/encoder/search.cpp	Tue May 28 14:01:54 2019 +0800
+++ b/source/encoder/search.cpp	Mon Jun 24 13:00:20 2019 +0530
@@ -2132,23 +2132,27 @@
         bestME[list].mvCost  = mvCost;
     }
 }
-void Search::searchMV(Mode& interMode, const PredictionUnit& pu, int list, int ref, MV& outmv, MV mvp, int numMvc, MV* mvc)
+void Search::searchMV(Mode& interMode, int list, int ref, MV& outmv, MV mvp[3], int numMvc, MV* mvc)
 {
     CUData& cu = interMode.cu;
-    const Slice *slice = m_slice;
-    MV mv;
-    if (m_param->interRefine == 1)
-        mv = mvp;
-    else
-        mv = cu.m_mv[list][pu.puAbsPartIdx];
+    MV mv, mvmin, mvmax;
     cu.clipMv(mv);
-    MV mvmin, mvmax;
-    setSearchRange(cu, mv, m_param->searchRange, mvmin, mvmax);
-    if (m_param->interRefine == 1)
-        m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mv, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices,
+    int cand = 0, bestcost = INT_MAX;
+    do
+    {
+        if (cand && (mvp[cand] == mvp[cand - 1] || (cand == 2 && mvp[cand] == mvp[cand - 2])))
+            continue;
+        MV bestMV;
+        mv = mvp[cand];
+        setSearchRange(cu, mv, m_param->searchRange, mvmin, mvmax);
+        int cost = m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mv, numMvc, mvc, m_param->searchRange, bestMV, m_param->maxSlices,
         m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0);
-    else
-        m_me.refineMV(&slice->m_mref[list][ref], mvmin, mvmax, mv, outmv);
+        if (bestcost > cost)
+        {
+            bestcost = cost;
+            outmv = bestMV;
+        }
+    }while (++cand < m_param->mvRefine);
 }
 /* find the best inter prediction for each PU of specified mode */
 void Search::predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChromaMC, uint32_t refMasks[2])
@@ -2209,7 +2213,6 @@
                 int ref = -1;
                 if (useAsMVP)
                     ref = interDataCTU->refIdx[list][cuIdx + puIdx];
-
                 else
                     ref = bestME[list].ref;
                 if (ref < 0)
@@ -2223,7 +2226,7 @@
                 const MV* amvp = interMode.amvpCand[list][ref];
                 int mvpIdx = selectMVP(cu, pu, amvp, list, ref);
                 MV mvmin, mvmax, outmv, mvp;
-                if (useAsMVP)
+                if (useAsMVP && !m_param->mvRefine)
                 {
                     mvp = interDataCTU->mv[list][cuIdx + puIdx].word;
                     mvpIdx = interDataCTU->mvpIdx[list][cuIdx + puIdx];
@@ -2239,11 +2242,44 @@
                 }
                 setSearchRange(cu, mvp, m_param->searchRange, mvmin, mvmax);
                 MV mvpIn = mvp;
+                int satdCost;
                 if (m_param->analysisMultiPassRefine && m_param->rc.bStatRead && mvpIdx == bestME[list].mvpIdx)
                     mvpIn = bestME[list].mv;
-                    
-                int satdCost = m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvpIn, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices, 
-                  m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0);
+                if (useAsMVP && m_param->mvRefine)
+                {
+                    MV bestmv, mvpSel[3];
+                    int mvpIdxSel[3];
+                    satdCost = m_me.COST_MAX;
+                    switch (m_param->mvRefine)
+                    {
+                    case 3: mvpSel[2] = interMode.amvpCand[list][ref][!mvpIdx];
+                            mvpIdxSel[2] = !mvpIdx;
+                    case 2: mvpSel[1] = interMode.amvpCand[list][ref][mvpIdx];
+                            mvpIdxSel[1] = mvpIdx;
+                    case 1: mvpSel[0] = interDataCTU->mv[list][cuIdx + puIdx].word;
+                            mvpIdxSel[0] = interDataCTU->mvpIdx[list][cuIdx + puIdx];
+                    }
+                    for (int cand = 0; cand < m_param->mvRefine; cand++)
+                    {
+                        if (cand && (mvpSel[cand] == mvpSel[cand - 1] || (cand == 2 && mvpSel[cand] == mvpSel[cand - 2])))
+                            continue;
+                        setSearchRange(cu, mvp, m_param->searchRange, mvmin, mvmax);
+                        int bcost = m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mvpSel[cand], numMvc, mvc, m_param->searchRange, bestmv, m_param->maxSlices,
+                            m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0);
+                        if (satdCost > bcost)
+                        {
+                            satdCost = bcost;
+                            outmv = bestmv;
+                            mvp = mvpSel[cand];
+                            mvpIdx = mvpIdxSel[cand];
+                        }
+                    }
+                }
+                else
+                {
+                    satdCost = m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvpIn, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices,
+                        m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0);
+                }
 
                 /* Get total cost of partition, but only include MV bit cost once */
                 bits += m_me.bitcost(outmv);
diff -r a46ded2c1411 -r 7611cad00151 source/encoder/search.h
--- a/source/encoder/search.h	Tue May 28 14:01:54 2019 +0800
+++ b/source/encoder/search.h	Mon Jun 24 13:00:20 2019 +0530
@@ -310,7 +310,7 @@
 
     // estimation inter prediction (non-skip)
     void     predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChromaMC, uint32_t masks[2]);
-    void     searchMV(Mode& interMode, const PredictionUnit& pu, int list, int ref, MV& outmv, MV mvp, int numMvc, MV* mvc);
+    void     searchMV(Mode& interMode, int list, int ref, MV& outmv, MV mvp[3], int numMvc, MV* mvc);
     // encode residual and compute rd-cost for inter mode
     void     encodeResAndCalcRdInterCU(Mode& interMode, const CUGeom& cuGeom);
     void     encodeResAndCalcRdSkipCU(Mode& interMode);
diff -r a46ded2c1411 -r 7611cad00151 source/x265cli.h
--- a/source/x265cli.h	Tue May 28 14:01:54 2019 +0800
+++ b/source/x265cli.h	Mon Jun 24 13:00:20 2019 +0530
@@ -294,8 +294,7 @@
     { "dhdr10-opt",           no_argument, NULL, 0},
     { "no-dhdr10-opt",        no_argument, NULL, 0},
     { "dolby-vision-profile",  required_argument, NULL, 0 },
-    { "refine-mv",            no_argument, NULL, 0 },
-    { "no-refine-mv",         no_argument, NULL, 0 },
+    { "refine-mv",      required_argument, NULL, 0 },
     { "refine-ctu-distortion", required_argument, NULL, 0 },
     { "force-flush",    required_argument, NULL, 0 },
     { "splitrd-skip",         no_argument, NULL, 0 },
@@ -544,7 +543,7 @@
         "                                    - 3 : Functionality of (1) + irrespective of size evaluate all inter modes.\n"
         "                                Default:%d\n", param->interRefine);
     H0("   --[no-]dynamic-refine         Dynamically changes refine-inter level for each CU. Default %s\n", OPT(param->bDynamicRefine));
-    H0("   --[no-]refine-mv              Enable mv refinement for load mode. Default %s\n", OPT(param->mvRefine));
+    H0("   --refine-mv <0..3>            Enable mv refinement for load mode. Default %d\n", param->mvRefine);
     H0("   --refine-ctu-distortion       Store/normalize ctu distortion in analysis-save/load.\n"
         "                                    - 0 : Disabled.\n"
         "                                    - 1 : Store/Load ctu distortion to/from the file specified in analysis-save/load.\n"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: x265.patch
Type: text/x-patch
Size: 13358 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20190703/26dd791d/attachment-0001.bin>


More information about the x265-devel mailing list