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

Steve Borho steve at borho.org
Wed May 13 17:01:35 CEST 2015


On 05/13, Deepthi Nandakumar wrote:
> Thanks, will queue these for overnight testing.
> 
> We discussed more improvements.
> 
> 1. At 8x8, add the parent CU's corresponding lowres MV.
> 2. At higher depths, should we add an average of all child lowres MVs? Or
> add all child lowres MVs to the motion candidate list?

For now I would just use one lowres MV per PU that maps to the middle of
the PU, so add 1/2 the block width and height and use the lowres MV that
maps to that location (instead of the CU start position). This should do
reasonable things for 32x32 and 64x64 and rectangluar and AMP partitions
and not require too much additional math.

> On Wed, May 13, 2015 at 12:39 PM, <gopu at multicorewareinc.com> wrote:
> 
> > # HG changeset patch
> > # User Gopu Govindaswamy <gopu at multicorewareinc.com>
> > # Date 1431500901 -19800
> > #      Wed May 13 12:38:21 2015 +0530
> > # Node ID a8addf6307f7da8d28857297d8de08b255e6610b
> > # Parent  6a8b7e35213670b6c4803bd1b1a0c16e57205968
> > search: add lowres MV into search mv candidate list for search ME
> >
> > 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 6a8b7e352136 -r a8addf6307f7 source/encoder/search.cpp
> > --- a/source/encoder/search.cpp Tue May 12 10:45:38 2015 -0500
> > +++ b/source/encoder/search.cpp Wed May 13 12:38:21 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.pu,
> > pme.puIdx, 0, meId, pme.cuGeom);
> >          else
> > -            slave.singleMotionEstimation(*this, pme.mode, pme.pu,
> > pme.puIdx, 1, meId - m_slice->m_numRefIdx[0]);
> > +            slave.singleMotionEstimation(*this, pme.mode, pme.pu,
> > pme.puIdx, 1, meId - m_slice->m_numRefIdx[0], pme.cuGeom);
> >
> >          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 PredictionUnit& pu, int part, int list, int ref, const CUGeom& cuGeom)
> >  {
> >      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);
> > +    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);
> > +                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, pu, puIdx, 0, 0,
> > cuGeom); /* 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);
> > +                    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,37 @@
> >              cu.setQPSubParts(cu.getRefQP(0), 0, cuGeom.depth);
> >      }
> >  }
> > +
> > +MV Search::getLowresMV(const CUData& cu, const CUGeom& cuGeom, int list)
> > +{
> > +    MV lmv;
> > +    if (g_maxCUSize >> cuGeom.depth == 16)
> > +    {
> > +        int curPoc = m_slice->m_poc;
> > +        int refPoc = m_slice->m_refPicList[list][0]->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_frame->m_fencPic->m_picWidth + (16 - 1))
> > / 16;
> > +
> > +            uint32_t idx = ((block_y / 16) * stride) + (block_x / 16);
> > +            /* check whether this motion search was performed by
> > lookahead */
> > +            if (mv[idx].x != 0x7FFF)
> > +                lmv = mv[idx];
> > +            else
> > +                lmv = 0;
> > +        }
> > +        else
> > +            lmv = 0;
> > +    }
> > +    else
> > +        lmv = 0;
> > +
> > +    return lmv;
> > +}
> > diff -r 6a8b7e352136 -r a8addf6307f7 source/encoder/search.h
> > --- a/source/encoder/search.h   Tue May 12 10:45:38 2015 -0500
> > +++ b/source/encoder/search.h   Wed May 13 12:38:21 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);
> > +
> >      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 PredictionUnit& pu, int part, int list, int ref, const CUGeom&
> > cuGeom);
> >
> >  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