[x265] [PATCH] analysis: re-order RD 0/4 analysis to do splits before ME or intra
Steve Borho
steve at borho.org
Wed May 20 02:08:39 CEST 2015
On 05/19, Steve Borho wrote:
> On 05/19, ashok at multicorewareinc.com wrote:
> > # HG changeset patch
> > # User Ashok Kumar Mishra<ashok at multicorewareinc.com>
> > # Date 1431933378 -19800
> > # Mon May 18 12:46:18 2015 +0530
> > # Node ID 1e2e70f90e4484b32217c7579bca98180929cf72
> > # Parent d7b100e51e828833eee006f1da93e499ac161d28
> > analysis: re-order RD 0/4 analysis to do splits before ME or intra
> >
> > diff -r d7b100e51e82 -r 1e2e70f90e44 source/encoder/analysis.cpp
> > --- a/source/encoder/analysis.cpp Mon May 18 18:24:08 2015 -0500
> > +++ b/source/encoder/analysis.cpp Mon May 18 12:46:18 2015 +0530
> > @@ -756,19 +756,79 @@
> > bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);
> > bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);
> > uint32_t minDepth = topSkipMinDepth(parentCTU, cuGeom);
> > -
> > + bool earlyskip = false;
> > if (mightNotSplit && depth >= minDepth)
> > {
> > - bool bTryIntra = m_slice->m_sliceType != B_SLICE || m_param->bIntraInBFrames;
> > -
> > /* Compute Merge Cost */
> > md.pred[PRED_MERGE].cu.initSubCU(parentCTU, cuGeom, qp);
> > md.pred[PRED_SKIP].cu.initSubCU(parentCTU, cuGeom, qp);
> > checkMerge2Nx2N_rd0_4(md.pred[PRED_SKIP], md.pred[PRED_MERGE], cuGeom);
> > -
> > - bool earlyskip = false;
> > if (m_param->rdLevel)
> > earlyskip = m_param->bEnableEarlySkip && md.bestMode && md.bestMode->cu.isSkipped(0); // TODO: sa8d threshold per depth
> > + }
> > +
> > + bool bNoSplit = false;
> > + if (md.bestMode)
> > + {
> > + bNoSplit = md.bestMode->cu.isSkipped(0);
> > + if (mightSplit && depth && depth >= minDepth && !bNoSplit)
> > + bNoSplit = recursionDepthCheck(parentCTU, cuGeom, *md.bestMode);
> > + }
> > +
> > + if (mightSplit && !bNoSplit)
> > + {
> > + Mode* splitPred = &md.pred[PRED_SPLIT];
> > + splitPred->initCosts();
> > + CUData* splitCU = &splitPred->cu;
> > + splitCU->initSubCU(parentCTU, cuGeom, qp);
> > +
> > + uint32_t nextDepth = depth + 1;
> > + ModeDepth& nd = m_modeDepth[nextDepth];
> > + invalidateContexts(nextDepth);
> > + Entropy* nextContext = &m_rqt[depth].cur;
> > + int nextQP = qp;
> > +
> > + for (uint32_t subPartIdx = 0; subPartIdx < 4; subPartIdx++)
> > + {
> > + const CUGeom& childGeom = *(&cuGeom + cuGeom.childOffset + subPartIdx);
> > + if (childGeom.flags & CUGeom::PRESENT)
> > + {
> > + m_modeDepth[0].fencYuv.copyPartToYuv(nd.fencYuv, childGeom.absPartIdx);
> > + m_rqt[nextDepth].cur.load(*nextContext);
> > +
> > + if (m_slice->m_pps->bUseDQP && nextDepth <= m_slice->m_pps->maxCuDQPDepth)
> > + nextQP = setLambdaFromQP(parentCTU, calculateQpforCuSize(parentCTU, childGeom));
> > +
> > + compressInterCU_rd0_4(parentCTU, childGeom, nextQP);
> > +
> > + // Save best CU and pred data for this sub CU
> > + splitCU->copyPartFrom(nd.bestMode->cu, childGeom, subPartIdx);
> > + splitPred->addSubCosts(*nd.bestMode);
> > +
> > + if (m_param->rdLevel)
> > + nd.bestMode->reconYuv.copyToPartYuv(splitPred->reconYuv, childGeom.numPartitions * subPartIdx);
> > + else
> > + nd.bestMode->predYuv.copyToPartYuv(splitPred->predYuv, childGeom.numPartitions * subPartIdx);
> > + if (m_param->rdLevel > 1)
> > + nextContext = &nd.bestMode->contexts;
> > + }
> > + else
> > + splitCU->setEmptyPart(childGeom, subPartIdx);
> > + }
> > + nextContext->store(splitPred->contexts);
> > +
> > + if (mightNotSplit)
> > + addSplitFlagCost(*splitPred, cuGeom.depth);
> > + else if (m_param->rdLevel > 1)
> > + updateModeCost(*splitPred);
> > + else
> > + splitPred->sa8dCost = m_rdCost.calcRdSADCost(splitPred->distortion, splitPred->sa8dBits);
> > + }
> > +
> > + if (mightNotSplit && depth >= minDepth)
> > + {
> > + if (m_slice->m_pps->bUseDQP && depth <= m_slice->m_pps->maxCuDQPDepth && m_slice->m_pps->maxCuDQPDepth != 0)
> > + setLambdaFromQP(parentCTU, qp);
>
> This could likely be optimized as:
>
> if (m_rdCost->m_qp != qp)
> setLambdaFromQP(parentCTU, qp);
actually, it would be better to call setLambdaFromQP() unconditionally
here, then have it early-out if the passed in QP matches m_qp (and init
m_qp to an invalid QP in the rdcost constructor). This way we also save
work when AQ did not specify a change in QP.
> > if (!earlyskip)
> > {
> > @@ -834,7 +894,7 @@
> > bestInter = &md.pred[PRED_nRx2N];
> > }
> > }
> > -
> > + bool bTryIntra = m_slice->m_sliceType != B_SLICE || m_param->bIntraInBFrames;
> > if (m_param->rdLevel >= 3)
> > {
> > /* Calculate RD cost of best inter option */
> > @@ -950,63 +1010,19 @@
> > addSplitFlagCost(*md.bestMode, cuGeom.depth);
> > }
> >
> > - bool bNoSplit = false;
> > - if (md.bestMode)
> > + if (mightNotSplit && md.bestMode)
> > {
> > - bNoSplit = md.bestMode->cu.isSkipped(0);
> > - if (mightSplit && depth && depth >= minDepth && !bNoSplit)
> > - bNoSplit = recursionDepthCheck(parentCTU, cuGeom, *md.bestMode);
> > + /* early-out statistics */
> > + FrameData& curEncData = *m_frame->m_encData;
> > + FrameData::RCStatCU& cuStat = curEncData.m_cuStat[parentCTU.m_cuAddr];
> > + uint64_t temp = cuStat.avgCost[depth] * cuStat.count[depth];
> > + cuStat.count[depth] += 1;
> > + cuStat.avgCost[depth] = (temp + md.bestMode->rdCost) / cuStat.count[depth];
> > }
> >
> > if (mightSplit && !bNoSplit)
> > {
> > Mode* splitPred = &md.pred[PRED_SPLIT];
> > - splitPred->initCosts();
> > - CUData* splitCU = &splitPred->cu;
> > - splitCU->initSubCU(parentCTU, cuGeom, qp);
> > -
> > - uint32_t nextDepth = depth + 1;
> > - ModeDepth& nd = m_modeDepth[nextDepth];
> > - invalidateContexts(nextDepth);
> > - Entropy* nextContext = &m_rqt[depth].cur;
> > - int nextQP = qp;
> > -
> > - for (uint32_t subPartIdx = 0; subPartIdx < 4; subPartIdx++)
> > - {
> > - const CUGeom& childGeom = *(&cuGeom + cuGeom.childOffset + subPartIdx);
> > - if (childGeom.flags & CUGeom::PRESENT)
> > - {
> > - m_modeDepth[0].fencYuv.copyPartToYuv(nd.fencYuv, childGeom.absPartIdx);
> > - m_rqt[nextDepth].cur.load(*nextContext);
> > -
> > - if (m_slice->m_pps->bUseDQP && nextDepth <= m_slice->m_pps->maxCuDQPDepth)
> > - nextQP = setLambdaFromQP(parentCTU, calculateQpforCuSize(parentCTU, childGeom));
> > -
> > - compressInterCU_rd0_4(parentCTU, childGeom, nextQP);
> > -
> > - // Save best CU and pred data for this sub CU
> > - splitCU->copyPartFrom(nd.bestMode->cu, childGeom, subPartIdx);
> > - splitPred->addSubCosts(*nd.bestMode);
> > -
> > - if (m_param->rdLevel)
> > - nd.bestMode->reconYuv.copyToPartYuv(splitPred->reconYuv, childGeom.numPartitions * subPartIdx);
> > - else
> > - nd.bestMode->predYuv.copyToPartYuv(splitPred->predYuv, childGeom.numPartitions * subPartIdx);
> > - if (m_param->rdLevel > 1)
> > - nextContext = &nd.bestMode->contexts;
> > - }
> > - else
> > - splitCU->setEmptyPart(childGeom, subPartIdx);
> > - }
> > - nextContext->store(splitPred->contexts);
> > -
> > - if (mightNotSplit)
> > - addSplitFlagCost(*splitPred, cuGeom.depth);
> > - else if (m_param->rdLevel > 1)
> > - updateModeCost(*splitPred);
> > - else
> > - splitPred->sa8dCost = m_rdCost.calcRdSADCost(splitPred->distortion, splitPred->sa8dBits);
> > -
> > if (!md.bestMode)
> > md.bestMode = splitPred;
> > else if (m_param->rdLevel > 1)
> > @@ -1016,21 +1032,11 @@
> >
> > checkDQPForSplitPred(*md.bestMode, cuGeom);
> > }
> > - if (mightNotSplit)
> > - {
> > - /* early-out statistics */
> > - FrameData& curEncData = *m_frame->m_encData;
> > - FrameData::RCStatCU& cuStat = curEncData.m_cuStat[parentCTU.m_cuAddr];
> > - uint64_t temp = cuStat.avgCost[depth] * cuStat.count[depth];
> > - cuStat.count[depth] += 1;
> > - cuStat.avgCost[depth] = (temp + md.bestMode->rdCost) / cuStat.count[depth];
> > - }
> >
> > /* Copy best data to encData CTU and recon */
> > X265_CHECK(md.bestMode->ok(), "best mode is not ok");
> > md.bestMode->cu.copyToPic(depth);
> > - if (md.bestMode != &md.pred[PRED_SPLIT] && m_param->rdLevel)
> > - md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic, cuAddr, cuGeom.absPartIdx);
> > + md.bestMode->reconYuv.copyToPicYuv(*m_frame->m_reconPic, cuAddr, cuGeom.absPartIdx);
> > }
> >
> > void Analysis::compressInterCU_rd5_6(const CUData& parentCTU, const CUGeom& cuGeom, uint32_t &zOrder, int32_t qp)
> > _______________________________________________
> > x265-devel mailing list
> > x265-devel at videolan.org
> > https://mailman.videolan.org/listinfo/x265-devel
>
> --
> Steve Borho
--
Steve Borho
More information about the x265-devel
mailing list