[x265] [PATCH] motion: Modify "--refine-mv" option
pooja at multicorewareinc.com
pooja at multicorewareinc.com
Wed Sep 4 09:30:51 CEST 2019
# HG changeset patch
# User Pooja Venkatesan
# Date 1566540185 -19800
# Fri Aug 23 11:33:05 2019 +0530
# Node ID 3be8c9b76ee56a4688899913b159f853137fd860
# Parent e4dd472b4bff110c15962213682b88c7f81f8d42
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 e4dd472b4bff -r 3be8c9b76ee5 doc/reST/cli.rst
--- a/doc/reST/cli.rst Wed May 08 09:28:02 2019 +0900
+++ b/doc/reST/cli.rst Fri Aug 23 11:33:05 2019 +0530
@@ -997,11 +997,14 @@
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 e4dd472b4bff -r 3be8c9b76ee5 source/common/param.cpp
--- a/source/common/param.cpp Wed May 08 09:28:02 2019 +0900
+++ b/source/common/param.cpp Fri Aug 23 11:33:05 2019 +0530
@@ -1209,7 +1209,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);
@@ -1650,6 +1650,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 e4dd472b4bff -r 3be8c9b76ee5 source/encoder/analysis.cpp
--- a/source/encoder/analysis.cpp Wed May 08 09:28:02 2019 +0900
+++ b/source/encoder/analysis.cpp Fri Aug 23 11:33:05 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 e4dd472b4bff -r 3be8c9b76ee5 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Wed May 08 09:28:02 2019 +0900
+++ b/source/encoder/encoder.cpp Fri Aug 23 11:33:05 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 e4dd472b4bff -r 3be8c9b76ee5 source/encoder/search.cpp
--- a/source/encoder/search.cpp Wed May 08 09:28:02 2019 +0900
+++ b/source/encoder/search.cpp Fri Aug 23 11:33:05 2019 +0530
@@ -2152,23 +2152,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])
@@ -2229,7 +2233,6 @@
int ref = -1;
if (useAsMVP)
ref = interDataCTU->refIdx[list][cuIdx + puIdx];
-
else
ref = bestME[list].ref;
if (ref < 0)
@@ -2243,7 +2246,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];
@@ -2259,11 +2262,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 e4dd472b4bff -r 3be8c9b76ee5 source/encoder/search.h
--- a/source/encoder/search.h Wed May 08 09:28:02 2019 +0900
+++ b/source/encoder/search.h Fri Aug 23 11:33:05 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 e4dd472b4bff -r 3be8c9b76ee5 source/x265cli.h
--- a/source/x265cli.h Wed May 08 09:28:02 2019 +0900
+++ b/source/x265cli.h Fri Aug 23 11:33:05 2019 +0530
@@ -297,8 +297,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 },
@@ -549,7 +548,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: 13325 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20190904/a7531b51/attachment-0001.bin>
More information about the x265-devel
mailing list