[x265] [PATCH] search: add lowres MV into search mv candidate list for search ME(CHANGESOUTPUT)

Steve Borho steve at borho.org
Thu May 14 16:42:06 CEST 2015


On 05/14, Deepthi Nandakumar wrote:
> Ran the smoke test on this, the results were mixed - on some commandlines,
> the encode efficiency benefits were really good though.

the results I've seen show loss of effiency at slower presets, which is
a real head-scratcher since it should help them most. Adding an
additional motion candidate shouldn't reduce efficiency.

I think I'd like to see a general solution for this (not just 16x16 CUs)
before it gets pushed.  I think passing the PU to the function and
sampling the lowres MV array at the PU center rather than the CU origin
would be adequate (just add half PU width to block_x and half PU height
to block_y).

> On Thu, May 14, 2015 at 10:53 AM, <gopu at multicorewareinc.com> wrote:
> 
> > # HG changeset patch
> > # User Gopu Govindaswamy <gopu at multicorewareinc.com>
> > # Date 1431581025 -19800
> > #      Thu May 14 10:53:45 2015 +0530
> > # Node ID def132fbcf33352b18a31015dfefff79e95d21d7
> > # Parent  479087422e29a672d6e9bc8d0cd2a65649d71fe2
> > search: add lowres MV into search mv candidate list for search
> > ME(CHANGESOUTPUT)
> >
> > Add one more mv (lowres MV) into MV candidates list and this extra
> > candidates
> > applicable only for depth 2, the lowres MV's are calculated 16x16 blocks
> >
> > diff -r 479087422e29 -r def132fbcf33 source/encoder/search.cpp
> > --- a/source/encoder/search.cpp Wed May 13 16:52:59 2015 -0700
> > +++ b/source/encoder/search.cpp Thu May 14 10:53:45 2015 +0530
> > @@ -1930,9 +1930,9 @@
> >      do
> >      {
> >          if (meId < m_slice->m_numRefIdx[0])
> > -            slave.singleMotionEstimation(*this, pme.mode, pme.pu,
> > pme.puIdx, 0, meId);
> > +            slave.singleMotionEstimation(*this, pme.mode, pme.cuGeom,
> > pme.pu, pme.puIdx, 0, meId);
> >          else
> > -            slave.singleMotionEstimation(*this, pme.mode, pme.pu,
> > pme.puIdx, 1, meId - m_slice->m_numRefIdx[0]);
> > +            slave.singleMotionEstimation(*this, pme.mode, pme.cuGeom,
> > pme.pu, pme.puIdx, 1, meId - m_slice->m_numRefIdx[0]);
> >
> >          meId = -1;
> >          pme.m_lock.acquire();
> > @@ -1943,20 +1943,25 @@
> >      while (meId >= 0);
> >  }
> >
> > -void Search::singleMotionEstimation(Search& master, Mode& interMode,
> > const PredictionUnit& pu, int part, int list, int ref)
> > +void Search::singleMotionEstimation(Search& master, Mode& interMode,
> > const CUGeom& cuGeom, const PredictionUnit& pu, int part, int list, int ref)
> >  {
> >      uint32_t bits = master.m_listSelBits[list] + MVP_IDX_BITS;
> >      bits += getTUBits(ref, m_slice->m_numRefIdx[list]);
> >
> >      MotionData* bestME = interMode.bestME[part];
> >
> > -    MV  mvc[(MD_ABOVE_LEFT + 1) * 2 + 1];
> > +    // 12 mv candidates including lowresMV
> > +    MV  mvc[(MD_ABOVE_LEFT + 1) * 2 + 2];
> >      int numMvc = interMode.cu.getPMV(interMode.interNeighbours, list,
> > ref, interMode.amvpCand[list][ref], mvc);
> >
> >      const MV* amvp = interMode.amvpCand[list][ref];
> >      int mvpIdx = selectMVP(interMode.cu, pu, amvp, list, ref);
> >      MV mvmin, mvmax, outmv, mvp = amvp[mvpIdx];
> >
> > +    MV lmv = getLowresMV(interMode.cu, cuGeom, list, ref);
> > +    if (lmv.notZero())
> > +        mvc[numMvc++] = lmv;
> > +
> >      setSearchRange(interMode.cu, mvp, m_param->searchRange, mvmin, mvmax);
> >
> >      int satdCost = m_me.motionEstimate(&m_slice->m_mref[list][ref],
> > mvmin, mvmax, mvp, numMvc, mvc, m_param->searchRange, outmv);
> > @@ -1990,7 +1995,8 @@
> >      CUData& cu = interMode.cu;
> >      Yuv* predYuv = &interMode.predYuv;
> >
> > -    MV mvc[(MD_ABOVE_LEFT + 1) * 2 + 1];
> > +    // 12 mv candidates including lowresMV
> > +    MV mvc[(MD_ABOVE_LEFT + 1) * 2 + 2];
> >
> >      const Slice *slice = m_slice;
> >      int numPart     = cu.getNumPartInter();
> > @@ -2039,6 +2045,10 @@
> >                  int mvpIdx = selectMVP(cu, pu, amvp, list, ref);
> >                  MV mvmin, mvmax, outmv, mvp = amvp[mvpIdx];
> >
> > +                MV lmv = getLowresMV(cu, cuGeom, list, ref);
> > +                if (lmv.notZero())
> > +                    mvc[numMvc++] = lmv;
> > +
> >                  setSearchRange(cu, mvp, m_param->searchRange, mvmin,
> > mvmax);
> >                  int satdCost =
> > m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvp, numMvc,
> > mvc, m_param->searchRange, outmv);
> >
> > @@ -2070,7 +2080,7 @@
> >              {
> >                  processPME(pme, *this);
> >
> > -                singleMotionEstimation(*this, interMode, pu, puIdx, 0,
> > 0); /* L0-0 */
> > +                singleMotionEstimation(*this, interMode, cuGeom, pu,
> > puIdx, 0, 0); /* L0-0 */
> >
> >                  bDoUnidir = false;
> >
> > @@ -2096,6 +2106,10 @@
> >                      int mvpIdx = selectMVP(cu, pu, amvp, list, ref);
> >                      MV mvmin, mvmax, outmv, mvp = amvp[mvpIdx];
> >
> > +                    MV lmv = getLowresMV(cu, cuGeom, list, ref);
> > +                    if (lmv.notZero())
> > +                        mvc[numMvc++] = lmv;
> > +
> >                      setSearchRange(cu, mvp, m_param->searchRange, mvmin,
> > mvmax);
> >                      int satdCost =
> > m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvp, numMvc,
> > mvc, m_param->searchRange, outmv);
> >
> > @@ -3444,3 +3458,31 @@
> >              cu.setQPSubParts(cu.getRefQP(0), 0, cuGeom.depth);
> >      }
> >  }
> > +
> > +MV Search::getLowresMV(const CUData& cu, const CUGeom& cuGeom, int list,
> > int ref)
> > +{
> > +    MV lmv = 0;
> > +    if (g_maxCUSize >> cuGeom.depth == 16)
> > +    {
> > +        int curPoc = m_slice->m_poc;
> > +        int refPoc = m_slice->m_refPicList[list][ref]->m_poc;
> > +        int diffPoc = abs(curPoc - refPoc);
> > +
> > +        if (diffPoc <= m_param->bframes + 1)
> > +        {
> > +            MV *mv = m_frame->m_lowres.lowresMvs[list][diffPoc - 1];
> > +            uint32_t block_x = cu.m_cuPelX +
> > g_zscanToPelX[cuGeom.absPartIdx];
> > +            uint32_t block_y = cu.m_cuPelY +
> > g_zscanToPelY[cuGeom.absPartIdx];
> > +
> > +            /* number of blocks per row in lowres*/
> > +            uint32_t stride = ((m_param->sourceWidth / 2) +
> > X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;
> > +
> > +            uint32_t idx = ((block_y / 16) * stride) + (block_x / 16);
> > +            /* check whether this motion search was performed by
> > lookahead */
> > +            if (mv[0].x != 0x7FFF)
> > +                lmv = mv[idx];
> >
> 
> The only change I made was to move this check up.
> 
> +        }
> > +    }
> > +
> > +    return lmv;
> > +}
> > diff -r 479087422e29 -r def132fbcf33 source/encoder/search.h
> > --- a/source/encoder/search.h   Wed May 13 16:52:59 2015 -0700
> > +++ b/source/encoder/search.h   Thu May 14 10:53:45 2015 +0530
> > @@ -319,6 +319,8 @@
> >      void checkDQP(Mode& mode, const CUGeom& cuGeom);
> >      void checkDQPForSplitPred(Mode& mode, const CUGeom& cuGeom);
> >
> > +    MV getLowresMV(const CUData& cu, const CUGeom& cuGeom, int list, int
> > ref);
> > +
> >      class PME : public BondedTaskGroup
> >      {
> >      public:
> > @@ -339,7 +341,7 @@
> >      };
> >
> >      void     processPME(PME& pme, Search& slave);
> > -    void     singleMotionEstimation(Search& master, Mode& interMode,
> > const PredictionUnit& pu, int part, int list, int ref);
> > +    void     singleMotionEstimation(Search& master, Mode& interMode,
> > const CUGeom& cuGeom, const PredictionUnit& pu, int part, int list, int
> > ref);
> >
> >  protected:
> >
> > _______________________________________________
> > x265-devel mailing list
> > x265-devel at videolan.org
> > https://mailman.videolan.org/listinfo/x265-devel
> >

> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel


-- 
Steve Borho


More information about the x265-devel mailing list