[x265-commits] [x265] TEncSearch: be pedantic about setting cu fields [CHANGES ...

Steve Borho steve at borho.org
Fri Mar 14 00:32:33 CET 2014


details:   http://hg.videolan.org/x265/rev/ebb3a25a7ad8
branches:  
changeset: 6497:ebb3a25a7ad8
user:      Steve Borho <steve at borho.org>
date:      Thu Mar 13 17:36:31 2014 -0500
description:
TEncSearch: be pedantic about setting cu fields [CHANGES OUTPUTS]

It is somewhat unfortunate that this changes outputs, it means I had introduced
a bug in an earlier commit
Subject: [x265] TEncSearch: inline xGetTemplateCost()

details:   http://hg.videolan.org/x265/rev/387471b8ec63
branches:  
changeset: 6498:387471b8ec63
user:      Steve Borho <steve at borho.org>
date:      Thu Mar 13 03:41:10 2014 -0500
description:
TEncSearch: inline xGetTemplateCost()
Subject: [x265] TEncSearch: inline xRestrictBipredMergeCand

details:   http://hg.videolan.org/x265/rev/80952375aff1
branches:  
changeset: 6499:80952375aff1
user:      Steve Borho <steve at borho.org>
date:      Thu Mar 13 03:45:25 2014 -0500
description:
TEncSearch: inline xRestrictBipredMergeCand
Subject: [x265] TEncSearch: cleanup xGetBlkBits

details:   http://hg.videolan.org/x265/rev/dc4af8a48dc8
branches:  
changeset: 6500:dc4af8a48dc8
user:      Steve Borho <steve at borho.org>
date:      Thu Mar 13 03:47:27 2014 -0500
description:
TEncSearch: cleanup xGetBlkBits
Subject: [x265] TEncSearch: inline MVP selection from AMVP candidates

details:   http://hg.videolan.org/x265/rev/81911e5df59c
branches:  
changeset: 6501:81911e5df59c
user:      Steve Borho <steve at borho.org>
date:      Thu Mar 13 03:57:31 2014 -0500
description:
TEncSearch: inline MVP selection from AMVP candidates
Subject: [x265] TEncSearch: combine motion candidate search into AMVP search loop

details:   http://hg.videolan.org/x265/rev/32eaed85f7c0
branches:  
changeset: 6502:32eaed85f7c0
user:      Steve Borho <steve at borho.org>
date:      Thu Mar 13 03:59:34 2014 -0500
description:
TEncSearch: combine motion candidate search into AMVP search loop
Subject: [x265] TEncSearch: keep merge data together in a struct

details:   http://hg.videolan.org/x265/rev/ebf86c054d05
branches:  
changeset: 6503:ebf86c054d05
user:      Steve Borho <steve at borho.org>
date:      Thu Mar 13 04:26:08 2014 -0500
description:
TEncSearch: keep merge data together in a struct

This is for clarity, convenience, and to avoid some redundant work
Subject: [x265] TEncSearch: remove redundant temp buffer

details:   http://hg.videolan.org/x265/rev/bb1ecd4f154d
branches:  
changeset: 6504:bb1ecd4f154d
user:      Steve Borho <steve at borho.org>
date:      Thu Mar 13 15:18:54 2014 -0500
description:
TEncSearch: remove redundant temp buffer

TComPrediction (which TEncSearch derives from) already has m_predTempYuv
Subject: [x265] motion: remove unused file static array

details:   http://hg.videolan.org/x265/rev/7b5699e6bb75
branches:  
changeset: 6505:7b5699e6bb75
user:      Steve Borho <steve at borho.org>
date:      Thu Mar 13 18:29:54 2014 -0500
description:
motion: remove unused file static array

diffstat:

 source/Lib/TLibCommon/TComPrediction.h |    2 +-
 source/Lib/TLibEncoder/TEncSearch.cpp  |  254 ++++++++++++--------------------
 source/Lib/TLibEncoder/TEncSearch.h    |   44 +++-
 source/encoder/motion.cpp              |    1 -
 4 files changed, 129 insertions(+), 172 deletions(-)

diffs (truncated from 521 to 300 lines):

diff -r 879151f65962 -r 7b5699e6bb75 source/Lib/TLibCommon/TComPrediction.h
--- a/source/Lib/TLibCommon/TComPrediction.h	Thu Mar 13 03:25:06 2014 -0500
+++ b/source/Lib/TLibCommon/TComPrediction.h	Thu Mar 13 18:29:54 2014 -0500
@@ -65,7 +65,7 @@ protected:
 
     // references sample for IntraPrediction
     TComYuv   m_predYuv[2];
-    ShortYuv m_predShortYuv[2];
+    ShortYuv  m_predShortYuv[2];
     TComYuv   m_predTempYuv;
 
     int16_t*  m_immedVals;
diff -r 879151f65962 -r 7b5699e6bb75 source/Lib/TLibEncoder/TEncSearch.cpp
--- a/source/Lib/TLibEncoder/TEncSearch.cpp	Thu Mar 13 03:25:06 2014 -0500
+++ b/source/Lib/TLibEncoder/TEncSearch.cpp	Thu Mar 13 18:29:54 2014 -0500
@@ -102,7 +102,6 @@ TEncSearch::~TEncSearch()
     delete[] m_qtTempCoeffCr;
     delete[] m_qtTempShortYuv;
     m_qtTempTransformSkipYuv.destroy();
-    m_tmpYuvPred.destroy();
 }
 
 bool TEncSearch::init(Encoder* cfg, TComRdCost* rdCost, TComTrQuant* trQuant)
@@ -145,8 +144,7 @@ bool TEncSearch::init(Encoder* cfg, TCom
     CHECKED_MALLOC(m_qtTempTUCoeffCb, TCoeff, MAX_TS_WIDTH * MAX_TS_HEIGHT);
     CHECKED_MALLOC(m_qtTempTUCoeffCr, TCoeff, MAX_TS_WIDTH * MAX_TS_HEIGHT);
 
-    return m_qtTempTransformSkipYuv.create(g_maxCUSize, g_maxCUSize, cfg->param->internalCsp) &&
-           m_tmpYuvPred.create(MAX_CU_SIZE, MAX_CU_SIZE, cfg->param->internalCsp);
+    return m_qtTempTransformSkipYuv.create(g_maxCUSize, g_maxCUSize, cfg->param->internalCsp);
 
 fail:
     return false;
@@ -2091,60 +2089,60 @@ void TEncSearch::IPCMSearch(TComDataCU* 
 
 /** estimation of best merge coding
  * \param cu
- * \param fencYuv
  * \param puIdx
- * \param interDir
- * \param pacMvField
- * \param mergeIndex
- * \param outCost
- * \param outBits
- * \param neighCands
+ * \param m
  * \returns void
  */
-void TEncSearch::xMergeEstimation(TComDataCU* cu, int puIdx, uint32_t& interDir, TComMvField* mvField, uint32_t& mergeIndex,
-                                  uint32_t& outCost, uint32_t& outbits, TComMvField* mvFieldNeighbours, uint8_t* interDirNeighbours,
-                                  int& numValidMergeCand)
+uint32_t TEncSearch::xMergeEstimation(TComDataCU* cu, int puIdx, MergeData& m)
 {
-    uint32_t absPartIdx = 0;
-    int width = 0;
-    int height = 0;
-
-    cu->getPartIndexAndSize(puIdx, absPartIdx, width, height);
-    uint32_t depth = cu->getDepth(absPartIdx);
+    uint32_t depth    = cu->getDepth(m.absPartIdx);
     PartSize partSize = cu->getPartitionSize(0);
+
     if (cu->getSlice()->getPPS()->getLog2ParallelMergeLevelMinus2() && partSize != SIZE_2Nx2N && cu->getCUSize(0) <= 8)
     {
         cu->setPartSizeSubParts(SIZE_2Nx2N, 0, depth);
         if (puIdx == 0)
         {
-            cu->getInterMergeCandidates(0, 0, mvFieldNeighbours, interDirNeighbours, numValidMergeCand);
+            cu->getInterMergeCandidates(0, 0, m.mvFieldNeighbours, m.interDirNeighbours, m.numValidMergeCand);
         }
         cu->setPartSizeSubParts(partSize, 0, depth);
     }
     else
     {
-        cu->getInterMergeCandidates(absPartIdx, puIdx, mvFieldNeighbours, interDirNeighbours, numValidMergeCand);
+        cu->getInterMergeCandidates(m.absPartIdx, puIdx, m.mvFieldNeighbours, m.interDirNeighbours, m.numValidMergeCand);
     }
-    xRestrictBipredMergeCand(cu, mvFieldNeighbours, interDirNeighbours, numValidMergeCand);
-
-    outCost = MAX_UINT;
-    for (uint32_t mergeCand = 0; mergeCand < numValidMergeCand; ++mergeCand)
+    /* convert bidir merge candidates into unidir
+     * TODO: why did the HM do this?, why use MV pairs below? */
+    if (cu->isBipredRestriction())
+    {
+        for (uint32_t mergeCand = 0; mergeCand < m.numValidMergeCand; ++mergeCand)
+        {
+            if (m.interDirNeighbours[mergeCand] == 3)
+            {
+                m.interDirNeighbours[mergeCand] = 1;
+                m.mvFieldNeighbours[(mergeCand << 1) + 1].setMvField(MV(0, 0), -1);
+            }
+        }
+    }
+
+    uint32_t outCost = MAX_UINT;
+    for (uint32_t mergeCand = 0; mergeCand < m.numValidMergeCand; ++mergeCand)
     {
         /* Prevent TMVP candidates from using unavailable reference pixels */
         if (m_cfg->param->frameNumThreads > 1 &&
-            (mvFieldNeighbours[0 + 2 * mergeCand].mv.y >= (m_cfg->param->searchRange + 1) * 4 ||
-             mvFieldNeighbours[1 + 2 * mergeCand].mv.y >= (m_cfg->param->searchRange + 1) * 4))
+            (m.mvFieldNeighbours[0 + 2 * mergeCand].mv.y >= (m_cfg->param->searchRange + 1) * 4 ||
+             m.mvFieldNeighbours[1 + 2 * mergeCand].mv.y >= (m_cfg->param->searchRange + 1) * 4))
         {
             continue;
         }
 
-        cu->getCUMvField(REF_PIC_LIST_0)->m_mv[absPartIdx] = mvFieldNeighbours[0 + 2 * mergeCand].mv;
-        cu->getCUMvField(REF_PIC_LIST_0)->m_refIdx[absPartIdx] = mvFieldNeighbours[0 + 2 * mergeCand].refIdx;
-        cu->getCUMvField(REF_PIC_LIST_1)->m_mv[absPartIdx] = mvFieldNeighbours[1 + 2 * mergeCand].mv;
-        cu->getCUMvField(REF_PIC_LIST_1)->m_refIdx[absPartIdx] = mvFieldNeighbours[1 + 2 * mergeCand].refIdx;
-
-        motionCompensation(cu, &m_tmpYuvPred, REF_PIC_LIST_X, puIdx, true, false);
-        uint32_t costCand = m_me.bufSATD(m_tmpYuvPred.getLumaAddr(absPartIdx), m_tmpYuvPred.getStride());
+        cu->getCUMvField(REF_PIC_LIST_0)->m_mv[m.absPartIdx] = m.mvFieldNeighbours[0 + 2 * mergeCand].mv;
+        cu->getCUMvField(REF_PIC_LIST_0)->m_refIdx[m.absPartIdx] = m.mvFieldNeighbours[0 + 2 * mergeCand].refIdx;
+        cu->getCUMvField(REF_PIC_LIST_1)->m_mv[m.absPartIdx] = m.mvFieldNeighbours[1 + 2 * mergeCand].mv;
+        cu->getCUMvField(REF_PIC_LIST_1)->m_refIdx[m.absPartIdx] = m.mvFieldNeighbours[1 + 2 * mergeCand].refIdx;
+
+        motionCompensation(cu, &m_predTempYuv, REF_PIC_LIST_X, puIdx, true, false);
+        uint32_t costCand = m_me.bufSATD(m_predTempYuv.getLumaAddr(m.absPartIdx), m_predTempYuv.getStride());
         uint32_t bitsCand = mergeCand + 1;
         if (mergeCand == m_cfg->param->maxNumMergeCand - 1)
         {
@@ -2154,36 +2152,15 @@ void TEncSearch::xMergeEstimation(TComDa
         if (costCand < outCost)
         {
             outCost = costCand;
-            outbits = bitsCand;
-            mvField[0] = mvFieldNeighbours[0 + 2 * mergeCand];
-            mvField[1] = mvFieldNeighbours[1 + 2 * mergeCand];
-            interDir = interDirNeighbours[mergeCand];
-            mergeIndex = mergeCand;
+            m.bits = bitsCand;
+            m.mvField[0] = m.mvFieldNeighbours[0 + 2 * mergeCand];
+            m.mvField[1] = m.mvFieldNeighbours[1 + 2 * mergeCand];
+            m.interDir = m.interDirNeighbours[mergeCand];
+            m.index = mergeCand;
         }
     }
-}
-
-/** convert bi-pred merge candidates to uni-pred
- * \param cu
- * \param puIdx
- * \param mvFieldNeighbours
- * \param interDirNeighbours
- * \param numValidMergeCand
- * \returns void
- */
-void TEncSearch::xRestrictBipredMergeCand(TComDataCU* cu, TComMvField* mvFieldNeighbours, uint8_t* interDirNeighbours, int numValidMergeCand)
-{
-    if (cu->isBipredRestriction())
-    {
-        for (uint32_t mergeCand = 0; mergeCand < numValidMergeCand; ++mergeCand)
-        {
-            if (interDirNeighbours[mergeCand] == 3)
-            {
-                interDirNeighbours[mergeCand] = 1;
-                mvFieldNeighbours[(mergeCand << 1) + 1].setMvField(MV(0, 0), -1);
-            }
-        }
-    }
+
+    return outCost;
 }
 
 /** search of the best candidate for inter prediction
@@ -2197,11 +2174,6 @@ bool TEncSearch::predInterSearch(TComDat
 {
     AMVPInfo amvpInfo[2][MAX_NUM_REF];
 
-    /* merge candidate data, cached between calls to xMergeEstimation */
-    TComMvField mvFieldNeighbours[MRG_MAX_NUM_CANDS << 1];
-    uint8_t     interDirNeighbours[MRG_MAX_NUM_CANDS];
-    int         numValidMergeCand = 0;
-
     TComPicYuv *fenc    = cu->getSlice()->getPic()->getPicYuvOrg();
     PartSize partSize   = cu->getPartitionSize(0);
     int      numPart    = cu->getNumPartInter();
@@ -2209,6 +2181,9 @@ bool TEncSearch::predInterSearch(TComDat
     uint32_t lastMode = 0;
     int      totalmebits = 0;
 
+    MergeData merge;
+    memset(&merge, 0, sizeof(merge));
+
     for (int partIdx = 0; partIdx < numPart; partIdx++)
     {
         uint32_t partAddr;
@@ -2218,17 +2193,15 @@ bool TEncSearch::predInterSearch(TComDat
         Pel* pu = fenc->getLumaAddr(cu->getAddr(), cu->getZorderIdxInCU() + partAddr);
         m_me.setSourcePU(pu - fenc->getLumaAddr(), roiWidth, roiHeight);
 
+        uint32_t mrgCost = MAX_UINT;
+
         /* find best cost merge candidate */
-        TComMvField mrgMvField[2];
-        uint32_t mrgInterDir = 0;
-        uint32_t mrgIndex = MAX_UINT;
-        uint32_t mrgCost = MAX_UINT;
-        uint32_t mrgBits = 0;
-
         if (cu->getPartitionSize(partAddr) != SIZE_2Nx2N)
         {
-            xMergeEstimation(cu, partIdx, mrgInterDir, mrgMvField, mrgIndex, mrgCost, mrgBits, mvFieldNeighbours,
-                             interDirNeighbours, numValidMergeCand);
+            merge.absPartIdx = partAddr;
+            merge.width = roiWidth;
+            merge.height = roiHeight;
+            mrgCost = xMergeEstimation(cu, partIdx, merge);
 
             if (bMergeOnly && cu->getCUSize(0) > 8)
             {
@@ -2240,26 +2213,17 @@ bool TEncSearch::predInterSearch(TComDat
                 }
                 // set merge result
                 cu->setMergeFlag(partAddr, true);
-                cu->setMergeIndex(partAddr, mrgIndex);
-                cu->setInterDirSubParts(mrgInterDir, partAddr, partIdx, cu->getDepth(partAddr));
-                cu->getCUMvField(REF_PIC_LIST_0)->setAllMvField(mrgMvField[0], partSize, partAddr, 0, partIdx);
-                cu->getCUMvField(REF_PIC_LIST_1)->setAllMvField(mrgMvField[1], partSize, partAddr, 0, partIdx);
-                totalmebits += mrgBits;
+                cu->setMergeIndex(partAddr, merge.index);
+                cu->setInterDirSubParts(merge.interDir, partAddr, partIdx, cu->getDepth(partAddr));
+                cu->getCUMvField(REF_PIC_LIST_0)->setAllMvField(merge.mvField[0], partSize, partAddr, 0, partIdx);
+                cu->getCUMvField(REF_PIC_LIST_1)->setAllMvField(merge.mvField[1], partSize, partAddr, 0, partIdx);
+                totalmebits += merge.bits;
 
                 motionCompensation(cu, predYuv, REF_PIC_LIST_X, partIdx, true, bChroma);
                 continue;
             }
         }
 
-        struct MotionData
-        {
-            MV  mv;
-            MV  mvp;
-            int mvpIdx;
-            int ref;
-            uint32_t cost;
-            int bits;
-        };
         MotionData list[2];
         MotionData bidir[2];
         uint32_t listSelBits[3]; // cost in bits of selecting a particular ref list
@@ -2283,20 +2247,36 @@ bool TEncSearch::predInterSearch(TComDat
                     if (ref == cu->getSlice()->getNumRefIdx(l) - 1)
                         bits--;
                 }
-                MV mvmin, mvmax, outmv, mvp;
-                xEstimateMvPredAMVP(cu, partIdx, l, ref, mvp, &amvpInfo[l][ref]);
-                int mvpIdx = cu->getMVPIdx(l, partAddr);
-
-                /* pass non-zero MVP candidates as motion candidates */
+
+                cu->fillMvpCand(partIdx, partAddr, l, ref, &amvpInfo[l][ref]);
+
+                // Pick the best possible MVP from AMVP candidates based on least residual
                 MV mvc[AMVP_MAX_NUM_CANDS];
+                uint32_t bestCost = MAX_INT;
+                int mvpIdx;
                 int numMvc = 0;
                 for (int i = 0; i < amvpInfo[l][ref].m_num; i++)
                 {
-                    MV& mv = amvpInfo[l][ref].m_mvCand[i];
-                    if (mv.notZero())
-                        mvc[numMvc++] = mv;
+                    MV mvCand = amvpInfo[l][ref].m_mvCand[i];
+                    if (mvCand.notZero())
+                        mvc[numMvc++] = mvCand;
+
+                    // TODO: skip mvCand if Y is > merange and -FN>1
+                    cu->clipMv(mvCand);
+
+                    xPredInterLumaBlk(cu, cu->getSlice()->getRefPic(l, ref)->getPicYuvRec(), partAddr, &mvCand, roiWidth, roiHeight, &m_predTempYuv);
+                    uint32_t cost = m_me.bufSAD(m_predTempYuv.getLumaAddr(partAddr), m_predTempYuv.getStride());
+                    cost = m_rdCost->calcRdSADCost(cost, MVP_IDX_BITS);
+
+                    if (bestCost > cost)
+                    {
+                        bestCost = cost;
+                        mvpIdx  = i;
+                    }
                 }
 
+                MV mvmin, mvmax, outmv, mvp = amvpInfo[l][ref].m_mvCand[mvpIdx];
+
                 int merange = m_cfg->param->searchRange;
                 xSetSearchRange(cu, mvp, merange, mvmin, mvmax);
                 int satdCost = m_me.motionEstimate(m_mref[l][ref], mvmin, mvmax, mvp, numMvc, mvc, merange, outmv);
@@ -2392,17 +2372,20 @@ bool TEncSearch::predInterSearch(TComDat
         if (mrgCost < bidirCost && mrgCost < list[0].cost && mrgCost < list[1].cost)
         {
             cu->setMergeFlag(partAddr, true);
-            cu->setMergeIndex(partAddr, mrgIndex);
-            cu->setInterDirSubParts(mrgInterDir, partAddr, partIdx, cu->getDepth(partAddr));
-            cu->getCUMvField(REF_PIC_LIST_0)->setAllMvField(mrgMvField[0], partSize, partAddr, 0, partIdx);
-            cu->getCUMvField(REF_PIC_LIST_1)->setAllMvField(mrgMvField[1], partSize, partAddr, 0, partIdx);


More information about the x265-commits mailing list