[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