<div dir="ltr">From 9da061411f9e3ef18f4f111e808286de488e5cec Mon Sep 17 00:00:00 2001<br>From: AnusuyaKumarasamy <<a href="mailto:anusuya.kumarasamy@multicorewareinc.com" target="_blank">anusuya.kumarasamy@multicorewareinc.com</a>><br>Date: Fri, 12 Jul 2024 17:03:03 +0530<br>Subject: [PATCH] Add mv constraint<br><br>---<br> source/encoder/frameencoder.cpp |  4 ++--<br> source/encoder/motion.cpp       |  8 ++++++++<br> source/encoder/motion.h         |  2 +-<br> source/encoder/search.cpp       | 26 +++++++++++++++++++-------<br> source/encoder/search.h         |  2 ++<br> source/encoder/slicetype.cpp    |  4 ++--<br> 6 files changed, 34 insertions(+), 12 deletions(-)<br><br>diff --git a/source/encoder/frameencoder.cpp b/source/encoder/frameencoder.cpp<br>index 97d033fb6..19d61ec35 100644<br>--- a/source/encoder/frameencoder.cpp<br>+++ b/source/encoder/frameencoder.cpp<br>@@ -1159,8 +1159,8 @@ void FrameEncoder::compressFrame(int layer)<br>     /* rateControlEnd may also block for earlier frames to call rateControlUpdateStats */<br>     if (!layer && m_top->m_rateControl->rateControlEnd(m_frame[layer], m_accessUnitBits[layer], &m_rce, &filler) < 0)<br>         m_top->m_aborted = true;<br>-    if (layer)<br>-        m_frame[layer]->m_encData->m_avgQpAq = m_frame[0]->m_encData->m_avgQpAq;<br>+    if (!layer)<br>+        m_frame[1]->m_encData->m_avgQpAq = m_frame[layer]->m_encData->m_avgQpAq;<br> <br>     if (filler > 0)<br>     {<br>diff --git a/source/encoder/motion.cpp b/source/encoder/motion.cpp<br>index 2bb613ec0..58e943652 100644<br>--- a/source/encoder/motion.cpp<br>+++ b/source/encoder/motion.cpp<br>@@ -770,6 +770,7 @@ int MotionEstimate::motionEstimate(ReferencePlanes *ref,<br>                                    int              merange,<br>                                    MV &             outQMv,<br>                                    uint32_t         maxSlices,<br>+                                    bool            m_vertRestriction,<br>                                    pixel *          srcReferencePlane)<br> {<br>     ALIGN_VAR_16(int, costs[16]);<br>@@ -794,6 +795,13 @@ int MotionEstimate::motionEstimate(ReferencePlanes *ref,<br> <br>     // measure SAD cost at clipped QPEL MVP<br>     MV pmv = qmvp.clipped(qmvmin, qmvmax);<br>+    if (m_vertRestriction)<br>+    {<br>+        if (pmv.y > mvmax.y << 2)<br>+        {<br>+            pmv.y = (mvmax.y << 2);<br>+        }<br>+    }<br>     MV bestpre = pmv;<br>     int bprecost;<br> <br>diff --git a/source/encoder/motion.h b/source/encoder/motion.h<br>index 790bc5fb4..c9fe86c82 100644<br>--- a/source/encoder/motion.h<br>+++ b/source/encoder/motion.h<br>@@ -95,7 +95,7 @@ public:<br>     }<br> <br>     void refineMV(ReferencePlanes* ref, const MV& mvmin, const MV& mvmax, const MV& qmvp, MV& outQMv);<br>-    int motionEstimate(ReferencePlanes* ref, const MV & mvmin, const MV & mvmax, const MV & qmvp, int numCandidates, const MV * mvc, int merange, MV & outQMv, uint32_t maxSlices, pixel *srcReferencePlane = 0);<br>+    int motionEstimate(ReferencePlanes* ref, const MV & mvmin, const MV & mvmax, const MV & qmvp, int numCandidates, const MV * mvc, int merange, MV & outQMv, uint32_t maxSlices, bool m_vertRestriction, pixel *srcReferencePlane = 0);<br> <br>     int subpelCompare(ReferencePlanes* ref, const MV &qmv, pixelcmp_t);<br> <br>diff --git a/source/encoder/search.cpp b/source/encoder/search.cpp<br>index 9dc5f90c5..954ec54d2 100644<br>--- a/source/encoder/search.cpp<br>+++ b/source/encoder/search.cpp<br>@@ -2109,16 +2109,17 @@ void Search::singleMotionEstimation(Search& master, Mode& interMode, const Predi<br>             mvp_lowres = lmv;<br>     }<br> <br>+    m_vertRestriction = interMode.cu.m_slice->m_refPOCList[list][ref] == interMode.cu.m_slice->m_poc;<br>     setSearchRange(interMode.cu, mvp, m_param->searchRange, mvmin, mvmax);<br> <br>-    int satdCost = m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mvp, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices, <br>+    int satdCost = m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mvp, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices, m_vertRestriction,<br>       m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0);<br> <br>     if (m_param->bEnableHME && mvp_lowres.notZero() && mvp_lowres != mvp)<br>     {<br>         MV outmv_lowres;<br>         setSearchRange(interMode.cu, mvp_lowres, m_param->searchRange, mvmin, mvmax);<br>-        int lowresMvCost = m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mvp_lowres, numMvc, mvc, m_param->searchRange, outmv_lowres, m_param->maxSlices,<br>+        int lowresMvCost = m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mvp_lowres, numMvc, mvc, m_param->searchRange, outmv_lowres, m_param->maxSlices, m_vertRestriction,<br>             m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0);<br>         if (lowresMvCost < satdCost)<br>         {<br>@@ -2168,8 +2169,9 @@ void Search::searchMV(Mode& interMode, int list, int ref, MV& outmv, MV mvp[3],<br>         MV bestMV;<br>         mv = mvp[cand++];<br>         cu.clipMv(mv);<br>+        m_vertRestriction = cu.m_slice->m_refPOCList[list][ref] == cu.m_slice->m_poc;<br>         setSearchRange(cu, mv, m_param->searchRange, mvmin, mvmax);<br>-        int cost = m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mv, numMvc, mvc, m_param->searchRange, bestMV, m_param->maxSlices,<br>+        int cost = m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mv, numMvc, mvc, m_param->searchRange, bestMV, m_param->maxSlices, m_vertRestriction,<br>         m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0);<br>         if (bestcost > cost)<br>         {<br>@@ -2289,7 +2291,7 @@ void Search::predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChroma<br>                         if (cand && (mvpSel[cand] == mvpSel[cand - 1] || (cand == 2 && mvpSel[cand] == mvpSel[cand - 2])))<br>                             continue;<br>                         setSearchRange(cu, mvpSel[cand], m_param->searchRange, mvmin, mvmax);<br>-                        int bcost = m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mvpSel[cand], numMvc, mvc, m_param->searchRange, bestmv, m_param->maxSlices,<br>+                        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_vertRestriction,<br>                             m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0);<br>                         if (satdCost > bcost)<br>                         {<br>@@ -2303,7 +2305,7 @@ void Search::predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChroma<br>                 }<br>                 else<br>                 {<br>-                    satdCost = m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvpIn, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices,<br>+                    satdCost = m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvpIn, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices, m_vertRestriction,<br>                         m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0);<br>                 }<br> <br>@@ -2427,15 +2429,16 @@ void Search::predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChroma<br>                         for (int planes = 0; planes < INTEGRAL_PLANE_NUM; planes++)<br>                             m_me.integral[planes] = interMode.fencYuv->m_integral[list][ref][planes] + puX * pu.width + puY * pu.height * m_slice->m_refFrameList[list][ref]->m_reconPic->m_stride;<br>                     }<br>+                    m_vertRestriction = cu.m_slice->m_refPOCList[list][ref] == cu.m_slice->m_poc;<br>                     setSearchRange(cu, mvp, m_param->searchRange, mvmin, mvmax);<br>-                    int satdCost = m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvp, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices, <br>+                    int satdCost = m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvp, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices, m_vertRestriction,<br>                       m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0);<br> <br>                     if (m_param->bEnableHME && mvp_lowres.notZero() && mvp_lowres != mvp)<br>                     {<br>                         MV outmv_lowres;<br>                         setSearchRange(cu, mvp_lowres, m_param->searchRange, mvmin, mvmax);<br>-                        int lowresMvCost = m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvp_lowres, numMvc, mvc, m_param->searchRange, outmv_lowres, m_param->maxSlices,<br>+                        int lowresMvCost = m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvp_lowres, numMvc, mvc, m_param->searchRange, outmv_lowres, m_param->maxSlices, m_vertRestriction,<br>                             m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0);<br>                         if (lowresMvCost < satdCost)<br>                         {<br>@@ -2729,6 +2732,15 @@ void Search::setSearchRange(const CUData& cu, const MV& mvp, int merange, MV& mv<br>     mvmin = mvp - dist;<br>     mvmax = mvp + dist;<br> <br>+    if (m_vertRestriction)<br>+    {<br>+        int mvRestricted = (56 - 1) << 2; // -1 to consider subpel search<br>+        if (mvmax.y >= mvRestricted)<br>+        {<br>+            mvmax.y = mvRestricted; //only positive side is restricted<br>+        }<br>+    }<br>+<br>     cu.clipMv(mvmin);<br>     cu.clipMv(mvmax);<br> <br>diff --git a/source/encoder/search.h b/source/encoder/search.h<br>index 02bd6e647..ea3fae02f 100644<br>--- a/source/encoder/search.h<br>+++ b/source/encoder/search.h<br>@@ -286,6 +286,8 @@ public:<br>     int32_t         m_sliceMaxY;<br>     int32_t         m_sliceMinY;<br> <br>+    bool            m_vertRestriction;<br>+<br> #if DETAILED_CU_STATS<br>     /* Accumulate CU statistics separately for each frame encoder */<br>     CUStats         m_stats[X265_MAX_FRAME_THREADS];<br>diff --git a/source/encoder/slicetype.cpp b/source/encoder/slicetype.cpp<br>index 429f0b475..46c6dd4d5 100644<br>--- a/source/encoder/slicetype.cpp<br>+++ b/source/encoder/slicetype.cpp<br>@@ -4160,9 +4160,9 @@ void CostEstimateGroup::estimateCUCost(LookaheadTLD& tld, int cuX, int cuY, int<br>         /* ME will never return a cost larger than the cost @MVP, so we do not<br>          * have to check that ME cost is more than the estimated merge cost */<br>         if(!hme)<br>-            fencCost = tld.me.motionEstimate(fref, mvmin, mvmax, mvp, 0, NULL, searchRange, *fencMV, m_lookahead.m_param->maxSlices);<br>+            fencCost = tld.me.motionEstimate(fref, mvmin, mvmax, mvp, 0, NULL, searchRange, *fencMV, m_lookahead.m_param->maxSlices, 0);<br>         else<br>-            fencCost = tld.me.motionEstimate(fref, mvmin, mvmax, mvp, 0, NULL, searchRange, *fencMV, m_lookahead.m_param->maxSlices, fref->lowerResPlane[0]);<br>+            fencCost = tld.me.motionEstimate(fref, mvmin, mvmax, mvp, 0, NULL, searchRange, *fencMV, m_lookahead.m_param->maxSlices, 0, fref->lowerResPlane[0]);<br>         if (skipCost < 64 && skipCost < fencCost && bBidir)<br>         {<br>             fencCost = skipCost;<br>-- <br>2.36.0.windows.1<br><br></div>