<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jun 5, 2017 at 3:45 PM, <span dir="ltr"><<a href="mailto:ashok@multicorewareinc.com" target="_blank">ashok@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 Ashok Kumar Mishra <<a href="mailto:ashok@multicorewareinc.com">ashok@multicorewareinc.com</a>><br>
# Date 1496656244 -19800<br>
# Mon Jun 05 15:20:44 2017 +0530<br>
# Node ID c04d02d71f206431b6b6e60460b81d<wbr>cc85fc5db5<br>
# Parent de49a722b256d94c9ba30b5d884590<wbr>26bea528b8<br>
MV refinement for multipass encoding<br></blockquote><div><br></div><div>Pushed to default branch</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
diff -r de49a722b256 -r c04d02d71f20 doc/reST/cli.rst<br>
--- a/doc/reST/cli.rst Wed May 24 20:01:59 2017 +0530<br>
+++ b/doc/reST/cli.rst Mon Jun 05 15:20:44 2017 +0530<br>
@@ -911,6 +911,12 @@<br>
inter modes for blocks of size one smaller than the min-cu-size of the<br>
incoming analysis data from the previous encode. Default disabled.<br>
<br>
+.. option:: --refine-mv<br>
+<br>
+ Enables refinement of motion vector for scaled video. Evaluates the best<br>
+ motion vector by searching the surrounding eight integer and subpel pixel<br>
+ positions.<br>
+<br>
Options which affect the transform unit quad-tree, sometimes referred to<br>
as the residual quad-tree (RQT).<br>
<br>
diff -r de49a722b256 -r c04d02d71f20 source/CMakeLists.txt<br>
--- a/source/CMakeLists.txt Wed May 24 20:01:59 2017 +0530<br>
+++ b/source/CMakeLists.txt Mon Jun 05 15:20:44 2017 +0530<br>
@@ -29,7 +29,7 @@<br>
option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)<br>
mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)<br>
# X265_BUILD must be incremented each time the public API is changed<br>
-set(X265_BUILD 120)<br>
+set(X265_BUILD 121)<br>
configure_file("${PROJECT_<wbr>SOURCE_DIR}/<a href="http://x265.def.in" rel="noreferrer" target="_blank">x265.def.in</a>"<br>
"${PROJECT_BINARY_DIR}/x265.<wbr>def")<br>
configure_file("${PROJECT_<wbr>SOURCE_DIR}/<a href="http://x265_config.h.in" rel="noreferrer" target="_blank">x265_config.h.in</a>"<br>
diff -r de49a722b256 -r c04d02d71f20 source/common/param.cpp<br>
--- a/source/common/param.cpp Wed May 24 20:01:59 2017 +0530<br>
+++ b/source/common/param.cpp Mon Jun 05 15:20:44 2017 +0530<br>
@@ -280,6 +280,7 @@<br>
param->scaleFactor = 0;<br>
param->intraRefine = 0;<br>
param->interRefine = 0;<br>
+ param->mvRefine = 0;<br>
}<br>
<br>
int x265_param_default_preset(<wbr>x265_param* param, const char* preset, const char* tune)<br>
@@ -963,6 +964,7 @@<br>
OPT("scale-factor") p->scaleFactor = atoi(value);<br>
OPT("refine-intra")p-><wbr>intraRefine = atobool(value);<br>
OPT("refine-inter")p-><wbr>interRefine = atobool(value);<br>
+ OPT("refine-mv")p->mvRefine = atobool(value);<br>
else<br>
return X265_PARAM_BAD_NAME;<br>
}<br>
@@ -1685,6 +1687,7 @@<br>
s += sprintf(s, " scale-factor=%d", p->scaleFactor);<br>
s += sprintf(s, " refine-intra=%d", p->intraRefine);<br>
s += sprintf(s, " refine-inter=%d", p->interRefine);<br>
+ s += sprintf(s, " refine-mv=%d", p->mvRefine);<br>
BOOL(p->bLimitSAO, "limit-sao");<br>
s += sprintf(s, " ctu-info=%d", p->bCTUInfo);<br>
#undef BOOL<br>
diff -r de49a722b256 -r c04d02d71f20 source/encoder/analysis.cpp<br>
--- a/source/encoder/analysis.cpp Wed May 24 20:01:59 2017 +0530<br>
+++ b/source/encoder/analysis.cpp Mon Jun 05 15:20:44 2017 +0530<br>
@@ -2267,14 +2267,16 @@<br>
int cuIdx = (mode.cu.m_cuAddr * parentCTU.m_numPartitions) + cuGeom.absPartIdx;<br>
mode.cu.m_mergeFlag[pu.<wbr>puAbsPartIdx] = interDataCTU->mergeFlag[cuIdx + part];<br>
mode.cu.setPUInterDir(<wbr>interDataCTU->interDir[cuIdx + part], pu.puAbsPartIdx, part);<br>
- for (int dir = 0; dir < m_slice->isInterB() + 1; dir++)<br>
+ for (int list = 0; list < m_slice->isInterB() + 1; list++)<br>
{<br>
- mode.cu.setPUMv(dir, interDataCTU->mv[dir][cuIdx + part], pu.puAbsPartIdx, part);<br>
- mode.cu.setPURefIdx(dir, interDataCTU->refIdx[dir][<wbr>cuIdx + part], pu.puAbsPartIdx, part);<br>
- mode.cu.m_mvpIdx[dir][pu.<wbr>puAbsPartIdx] = interDataCTU->mvpIdx[dir][<wbr>cuIdx + part];<br>
+ mode.cu.setPUMv(list, interDataCTU->mv[list][cuIdx + part], pu.puAbsPartIdx, part);<br>
+ mode.cu.setPURefIdx(list, interDataCTU->refIdx[list][<wbr>cuIdx + part], pu.puAbsPartIdx, part);<br>
+ mode.cu.m_mvpIdx[list][pu.<wbr>puAbsPartIdx] = interDataCTU->mvpIdx[list][<wbr>cuIdx + part];<br>
}<br>
if (!mode.cu.m_mergeFlag[pu.<wbr>puAbsPartIdx])<br>
{<br>
+ if (m_param->mvRefine)<br>
+ m_me.setSourcePU(*mode.<wbr>fencYuv, pu.ctuAddr, pu.cuAbsPartIdx, pu.puAbsPartIdx, pu.width, pu.height, m_param->searchMethod, m_param->subpelRefine, false);<br>
//AMVP<br>
MV mvc[(MD_ABOVE_LEFT + 1) * 2 + 2];<br>
mode.cu.getNeighbourMV(part, pu.puAbsPartIdx, mode.interNeighbours);<br>
@@ -2285,6 +2287,12 @@<br>
continue;<br>
mode.cu.getPMV(mode.<wbr>interNeighbours, list, ref, mode.amvpCand[list][ref], mvc);<br>
MV mvp = mode.amvpCand[list][ref][mode.<wbr>cu.m_mvpIdx[list][pu.<wbr>puAbsPartIdx]];<br>
+ if (m_param->mvRefine)<br>
+ {<br>
+ MV outmv;<br>
+ searchMV(mode, pu, list, ref, outmv);<br>
+ mode.cu.setPUMv(list, outmv, pu.puAbsPartIdx, part);<br>
+ }<br>
mode.cu.m_mvd[list][pu.<wbr>puAbsPartIdx] = mode.cu.m_mv[list][pu.<wbr>puAbsPartIdx] - mvp;<br>
}<br>
}<br>
@@ -2293,7 +2301,6 @@<br>
MVField candMvField[MRG_MAX_NUM_CANDS]<wbr>[2]; // double length for mv of both lists<br>
uint8_t candDir[MRG_MAX_NUM_CANDS];<br>
<a href="http://mode.cu">mode.cu</a>.<wbr>getInterMergeCandidates(pu.<wbr>puAbsPartIdx, part, candMvField, candDir);<br>
- mode.cu.m_mvpIdx[0][pu.<wbr>puAbsPartIdx] = interDataCTU->mvpIdx[0][cuIdx + part];<br>
uint8_t mvpIdx = mode.cu.m_mvpIdx[0][pu.<wbr>puAbsPartIdx];<br>
mode.cu.setPUInterDir(candDir[<wbr>mvpIdx], pu.puAbsPartIdx, part);<br>
mode.cu.setPUMv(0, candMvField[mvpIdx][0].mv, pu.puAbsPartIdx, part);<br>
diff -r de49a722b256 -r c04d02d71f20 source/encoder/encoder.cpp<br>
--- a/source/encoder/encoder.cpp Wed May 24 20:01:59 2017 +0530<br>
+++ b/source/encoder/encoder.cpp Mon Jun 05 15:20:44 2017 +0530<br>
@@ -2310,6 +2310,15 @@<br>
x265_log(p, X265_LOG_WARNING, "Inter refinement does not support limitTU. Disabling limitTU.\n");<br>
p->limitTU = 0;<br>
}<br>
+<br>
+ if (p->mvRefine)<br>
+ {<br>
+ if (p->analysisMode != X265_ANALYSIS_LOAD || p->analysisRefineLevel < 10 || !p->scaleFactor)<br>
+ {<br>
+ x265_log(p, X265_LOG_WARNING, "MV refinement requires analysis load, refine-level 10, scale factor. Disabling inter refine.\n");<br>
+ p->mvRefine = 0;<br>
+ }<br>
+ }<br>
<br>
if ((p->analysisMultiPassRefine || p-><wbr>analysisMultiPassDistortion) && (p->bDistributeModeAnalysis || p-><wbr>bDistributeMotionEstimation))<br>
{<br>
diff -r de49a722b256 -r c04d02d71f20 source/encoder/motion.cpp<br>
--- a/source/encoder/motion.cpp Wed May 24 20:01:59 2017 +0530<br>
+++ b/source/encoder/motion.cpp Mon Jun 05 15:20:44 2017 +0530<br>
@@ -598,6 +598,139 @@<br>
}<br>
}<br>
<br>
+void MotionEstimate::refineMV(<wbr>ReferencePlanes* ref,<br>
+ const MV& mvmin,<br>
+ const MV& mvmax,<br>
+ const MV& qmvp,<br>
+ MV& outQMv)<br>
+{<br>
+ ALIGN_VAR_16(int, costs[16]);<br>
+ if (ctuAddr >= 0)<br>
+ blockOffset = ref->reconPic->getLumaAddr(<wbr>ctuAddr, absPartIdx) - ref->reconPic->getLumaAddr(0);<br>
+ intptr_t stride = ref->lumaStride;<br>
+ pixel* fenc = fencPUYuv.m_buf[0];<br>
+ pixel* fref = ref->fpelPlane[0] + blockOffset;<br>
+<br>
+ setMVP(qmvp);<br>
+<br>
+ MV qmvmin = mvmin.toQPel();<br>
+ MV qmvmax = mvmax.toQPel();<br>
+<br>
+ /* The term cost used here means satd/sad values for that particular search.<br>
+ * The costs used in ME integer search only includes the SAD cost of motion<br>
+ * residual and sqrtLambda times MVD bits. The subpel refine steps use SATD<br>
+ * cost of residual and sqrtLambda * MVD bits.<br>
+ */<br>
+<br>
+ // measure SATD cost at clipped QPEL MVP<br>
+ MV pmv = qmvp.clipped(qmvmin, qmvmax);<br>
+ MV bestpre = pmv;<br>
+ int bprecost;<br>
+<br>
+ bprecost = subpelCompare(ref, pmv, sad);<br>
+<br>
+ /* re-measure full pel rounded MVP with SAD as search start point */<br>
+ MV bmv = pmv.roundToFPel();<br>
+ int bcost = bprecost;<br>
+ if (pmv.isSubpel())<br>
+ bcost = sad(fenc, FENC_STRIDE, fref + bmv.x + bmv.y * stride, stride) + mvcost(bmv << 2);<br>
+<br>
+ /* square refine */<br>
+ int dir = 0;<br>
+ COST_MV_X4_DIR(0, -1, 0, 1, -1, 0, 1, 0, costs);<br>
+ if ((bmv.y - 1 >= mvmin.y) & (bmv.y - 1 <= mvmax.y))<br>
+ COPY2_IF_LT(bcost, costs[0], dir, 1);<br>
+ if ((bmv.y + 1 >= mvmin.y) & (bmv.y + 1 <= mvmax.y))<br>
+ COPY2_IF_LT(bcost, costs[1], dir, 2);<br>
+ COPY2_IF_LT(bcost, costs[2], dir, 3);<br>
+ COPY2_IF_LT(bcost, costs[3], dir, 4);<br>
+ COST_MV_X4_DIR(-1, -1, -1, 1, 1, -1, 1, 1, costs);<br>
+ if ((bmv.y - 1 >= mvmin.y) & (bmv.y - 1 <= mvmax.y))<br>
+ COPY2_IF_LT(bcost, costs[0], dir, 5);<br>
+ if ((bmv.y + 1 >= mvmin.y) & (bmv.y + 1 <= mvmax.y))<br>
+ COPY2_IF_LT(bcost, costs[1], dir, 6);<br>
+ if ((bmv.y - 1 >= mvmin.y) & (bmv.y - 1 <= mvmax.y))<br>
+ COPY2_IF_LT(bcost, costs[2], dir, 7);<br>
+ if ((bmv.y + 1 >= mvmin.y) & (bmv.y + 1 <= mvmax.y))<br>
+ COPY2_IF_LT(bcost, costs[3], dir, 8);<br>
+ bmv += square1[dir];<br>
+<br>
+ if (bprecost < bcost)<br>
+ {<br>
+ bmv = bestpre;<br>
+ bcost = bprecost;<br>
+ }<br>
+ else<br>
+ bmv = bmv.toQPel(); // promote search bmv to qpel<br>
+<br>
+ // TO DO: Change SubpelWorkload to fine tune MV<br>
+ // Now it is set to 5 for experiment.<br>
+ // const SubpelWorkload& wl = workload[this->subpelRefine];<br>
+ const SubpelWorkload& wl = workload[5];<br>
+<br>
+ pixelcmp_t hpelcomp;<br>
+<br>
+ if (wl.hpel_satd)<br>
+ {<br>
+ bcost = subpelCompare(ref, bmv, satd) + mvcost(bmv);<br>
+ hpelcomp = satd;<br>
+ }<br>
+ else<br>
+ hpelcomp = sad;<br>
+<br>
+ for (int iter = 0; iter < wl.hpel_iters; iter++)<br>
+ {<br>
+ int bdir = 0;<br>
+ for (int i = 1; i <= wl.hpel_dirs; i++)<br>
+ {<br>
+ MV qmv = bmv + square1[i] * 2;<br>
+<br>
+ // check mv range for slice bound<br>
+ if ((qmv.y < qmvmin.y) | (qmv.y > qmvmax.y))<br>
+ continue;<br>
+<br>
+ int cost = subpelCompare(ref, qmv, hpelcomp) + mvcost(qmv);<br>
+ COPY2_IF_LT(bcost, cost, bdir, i);<br>
+ }<br>
+<br>
+ if (bdir)<br>
+ bmv += square1[bdir] * 2;<br>
+ else<br>
+ break;<br>
+ }<br>
+<br>
+ /* if HPEL search used SAD, remeasure with SATD before QPEL */<br>
+ if (!wl.hpel_satd)<br>
+ bcost = subpelCompare(ref, bmv, satd) + mvcost(bmv);<br>
+<br>
+ for (int iter = 0; iter < wl.qpel_iters; iter++)<br>
+ {<br>
+ int bdir = 0;<br>
+ for (int i = 1; i <= wl.qpel_dirs; i++)<br>
+ {<br>
+ MV qmv = bmv + square1[i];<br>
+<br>
+ // check mv range for slice bound<br>
+ if ((qmv.y < qmvmin.y) | (qmv.y > qmvmax.y))<br>
+ continue;<br>
+<br>
+ int cost = subpelCompare(ref, qmv, satd) + mvcost(qmv);<br>
+ COPY2_IF_LT(bcost, cost, bdir, i);<br>
+ }<br>
+<br>
+ if (bdir)<br>
+ bmv += square1[bdir];<br>
+ else<br>
+ break;<br>
+ }<br>
+<br>
+ // check mv range for slice bound<br>
+ X265_CHECK(((pmv.y >= qmvmin.y) & (pmv.y <= qmvmax.y)), "mv beyond range!");<br>
+<br>
+ x265_emms();<br>
+ outQMv = bmv;<br>
+}<br>
+<br>
int MotionEstimate::<wbr>motionEstimate(ReferencePlanes *ref,<br>
const MV & mvmin,<br>
const MV & mvmax,<br>
diff -r de49a722b256 -r c04d02d71f20 source/encoder/motion.h<br>
--- a/source/encoder/motion.h Wed May 24 20:01:59 2017 +0530<br>
+++ b/source/encoder/motion.h Mon Jun 05 15:20:44 2017 +0530<br>
@@ -92,6 +92,7 @@<br>
chromaSatd(refYuv.getCrAddr(<wbr>puPartIdx), refYuv.m_csize, fencPUYuv.m_buf[2], fencPUYuv.m_csize);<br>
}<br>
<br>
+ void refineMV(ReferencePlanes* ref, const MV& mvmin, const MV& mvmax, const MV& qmvp, MV& outQMv);<br>
int motionEstimate(<wbr>ReferencePlanes* ref, const MV & mvmin, const MV & mvmax, const MV & qmvp, int numCandidates, const MV * mvc, int merange, MV & outQMv, pixel *srcReferencePlane = 0);<br>
<br>
int subpelCompare(ReferencePlanes* ref, const MV &qmv, pixelcmp_t);<br>
diff -r de49a722b256 -r c04d02d71f20 source/encoder/search.cpp<br>
--- a/source/encoder/search.cpp Wed May 24 20:01:59 2017 +0530<br>
+++ b/source/encoder/search.cpp Mon Jun 05 15:20:44 2017 +0530<br>
@@ -2108,6 +2108,17 @@<br>
}<br>
}<br>
<br>
+void Search::searchMV(Mode& interMode, const PredictionUnit& pu, int list, int ref, MV& outmv)<br>
+{<br>
+ CUData& cu = interMode.cu;<br>
+ const Slice *slice = m_slice;<br>
+ MV mv = cu.m_mv[list][pu.puAbsPartIdx]<wbr>;<br>
+ cu.clipMv(mv);<br>
+ MV mvmin, mvmax;<br>
+ setSearchRange(cu, mv, m_param->searchRange, mvmin, mvmax);<br>
+ m_me.refineMV(&slice->m_mref[<wbr>list][ref], mvmin, mvmax, mv, outmv);<br>
+}<br>
+<br>
/* find the best inter prediction for each PU of specified mode */<br>
void Search::predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChromaMC, uint32_t refMasks[2])<br>
{<br>
diff -r de49a722b256 -r c04d02d71f20 source/encoder/search.h<br>
--- a/source/encoder/search.h Wed May 24 20:01:59 2017 +0530<br>
+++ b/source/encoder/search.h Mon Jun 05 15:20:44 2017 +0530<br>
@@ -311,6 +311,7 @@<br>
// estimation inter prediction (non-skip)<br>
void predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChromaMC, uint32_t masks[2]);<br>
<br>
+ void searchMV(Mode& interMode, const PredictionUnit& pu, int list, int ref, MV& outmv);<br>
// encode residual and compute rd-cost for inter mode<br>
void encodeResAndCalcRdInterCU(<wbr>Mode& interMode, const CUGeom& cuGeom);<br>
void encodeResAndCalcRdSkipCU(Mode& interMode);<br>
diff -r de49a722b256 -r c04d02d71f20 source/x265.h<br>
--- a/source/x265.h Wed May 24 20:01:59 2017 +0530<br>
+++ b/source/x265.h Mon Jun 05 15:20:44 2017 +0530<br>
@@ -1449,6 +1449,9 @@<br>
/* Enable inter refinement in load mode*/<br>
int interRefine;<br>
<br>
+ /* Enable motion vector refinement in load mode*/<br>
+ int mvRefine;<br>
+<br>
} x265_param;<br>
<br>
/* x265_param_alloc:<br>
diff -r de49a722b256 -r c04d02d71f20 source/x265cli.h<br>
--- a/source/x265cli.h Wed May 24 20:01:59 2017 +0530<br>
+++ b/source/x265cli.h Mon Jun 05 15:20:44 2017 +0530<br>
@@ -277,6 +277,8 @@<br>
{ "dhdr10-info", required_argument, NULL, 0 },<br>
{ "dhdr10-opt", no_argument, NULL, 0},<br>
{ "no-dhdr10-opt", no_argument, NULL, 0},<br>
+ { "refine-mv", no_argument, NULL, 0 },<br>
+ { "no-refine-mv", no_argument, NULL, 0 },<br>
{ 0, 0, 0, 0 },<br>
{ 0, 0, 0, 0 },<br>
{ 0, 0, 0, 0 },<br>
@@ -448,6 +450,7 @@<br>
H0(" --scale-factor <int> Specify factor by which input video is scaled down for analysis save mode. Default %d\n", param->scaleFactor);<br>
H0(" --[no-]refine-intra Enable intra refinement for load mode. Default %s\n", OPT(param->intraRefine));<br>
H0(" --[no-]refine-inter Enable inter refinement for load mode. Default %s\n", OPT(param->interRefine));<br>
+ H0(" --[no-]refine-mv Enable mv refinement for load mode. Default %s\n", OPT(param->mvRefine));<br>
H0(" --aq-mode <integer> Mode for Adaptive Quantization - 0:none 1:uniform AQ 2:auto variance 3:auto variance with bias to dark scenes. Default %d\n", param->rc.aqMode);<br>
H0(" --aq-strength <float> Reduces blocking and blurring in flat and textured areas (0 to 3.0). Default %.2f\n", param->rc.aqStrength);<br>
H0(" --[no-]aq-motion Adaptive Quantization based on the relative motion of each CU w.r.t., frame. Default %s\n", OPT(param->bOptCUDeltaQP));<br>
______________________________<wbr>_________________<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" rel="noreferrer" target="_blank">https://mailman.videolan.org/<wbr>listinfo/x265-devel</a><br>
</blockquote></div><br></div></div>