[x265] [PATCH] dqp: add logic to encode DQP at depth zero and above as well

Deepthi Nandakumar deepthi at multicorewareinc.com
Fri Mar 6 05:25:05 CET 2015


Thanks, looks good. THis patch is not expected to change outputs in any way
- so we need to watch out for regressions.

When the RDO cost of DQP bits is included, the mode costs should be updated
after the checkDQP and checkDQPForSplitPred functions, not before.

On Thu, Mar 5, 2015 at 1:03 PM, <gopu at multicorewareinc.com> wrote:

> # HG changeset patch
> # User Gopu Govindaswamy <gopu at multicorewareinc.com>
> # Date 1425540797 -19800
> #      Thu Mar 05 13:03:17 2015 +0530
> # Node ID ce2bd9e51497631f038110c227e164fe0ffcb5bf
> # Parent  ea9bdb10353fcb06cea1045ba0186c22c448df63
> dqp: add logic to encode DQP at depth zero and above as well
>
> Added the logic to check dqp for all sub-CU level
> checkDQP function moved into base class search
>
> diff -r ea9bdb10353f -r ce2bd9e51497 source/encoder/analysis.cpp
> --- a/source/encoder/analysis.cpp       Wed Mar 04 13:20:55 2015 +0530
> +++ b/source/encoder/analysis.cpp       Thu Mar 05 13:03:17 2015 +0530
> @@ -312,11 +312,11 @@
>              addSplitFlagCost(*splitPred, cuGeom.depth);
>          else
>              updateModeCost(*splitPred);
> +
> +        checkDQPForSplitPred(splitPred->cu, cuGeom);
>          checkBestMode(*splitPred, depth);
>      }
>
> -    checkDQP(md.bestMode->cu, cuGeom);
> -
>      /* Copy best data to encData CTU and recon */
>      md.bestMode->cu.copyToPic(depth);
>      if (md.bestMode != &md.pred[PRED_SPLIT])
> @@ -711,6 +711,7 @@
>          else
>              updateModeCost(*splitPred);
>
> +        checkDQPForSplitPred(splitPred->cu, cuGeom);
>          checkBestMode(*splitPred, depth);
>      }
>
> @@ -724,8 +725,6 @@
>          cuStat.avgCost[depth] = (temp + md.bestMode->rdCost) /
> cuStat.count[depth];
>      }
>
> -    checkDQP(md.bestMode->cu, cuGeom);
> -
>      /* Copy best data to encData CTU and recon */
>      md.bestMode->cu.copyToPic(depth);
>      if (md.bestMode != &md.pred[PRED_SPLIT])
> @@ -996,8 +995,9 @@
>              checkBestMode(*splitPred, cuGeom.depth);
>          else if (splitPred->sa8dCost < md.bestMode->sa8dCost)
>              md.bestMode = splitPred;
> +
> +        checkDQPForSplitPred(md.bestMode->cu, cuGeom);
>      }
> -
>      if (mightNotSplit)
>      {
>          /* early-out statistics */
> @@ -1008,8 +1008,6 @@
>          cuStat.avgCost[depth] = (temp + md.bestMode->rdCost) /
> cuStat.count[depth];
>      }
>
> -    checkDQP(md.bestMode->cu, cuGeom);
> -
>      /* Copy best data to encData CTU and recon */
>      md.bestMode->cu.copyToPic(depth);
>      if (md.bestMode != &md.pred[PRED_SPLIT] && m_param->rdLevel)
> @@ -1184,11 +1182,10 @@
>          else
>              updateModeCost(*splitPred);
>
> +        checkDQPForSplitPred(splitPred->cu, cuGeom);
>          checkBestMode(*splitPred, depth);
>      }
>
> -    checkDQP(md.bestMode->cu, cuGeom);
> -
>      /* Copy best data to encData CTU and recon */
>      md.bestMode->cu.copyToPic(depth);
>      if (md.bestMode != &md.pred[PRED_SPLIT])
> @@ -1296,6 +1293,7 @@
>      bestPred->cu.setPUMv(1, candMvField[bestSadCand][1].mv, 0, 0);
>      bestPred->cu.setPURefIdx(0,
> (int8_t)candMvField[bestSadCand][0].refIdx, 0, 0);
>      bestPred->cu.setPURefIdx(1,
> (int8_t)candMvField[bestSadCand][1].refIdx, 0, 0);
> +    checkDQP(bestPred->cu, cuGeom);
>  }
>
>  /* sets md.bestMode if a valid merge candidate is found, else leaves it
> NULL */
> @@ -1432,6 +1430,7 @@
>          if (m_param->analysisMode == X265_ANALYSIS_SAVE)
>              *m_reuseBestMergeCand = bestPred->cu.m_mvpIdx[0][0];
>      }
> +    checkDQP(bestPred->cu, cuGeom);
>  }
>
>  void Analysis::checkInter_rd0_4(Mode& interMode, const CUGeom& cuGeom,
> PartSize partSize)
> @@ -1759,7 +1758,6 @@
>                                                           predV,
> predYuv.m_csize);
>      }
>
> -    checkDQP(cu, cuGeom);
>      cu.updatePic(cuGeom.depth);
>  }
>
> @@ -1788,34 +1786,6 @@
>      }
>  }
>
> -void Analysis::checkDQP(CUData& cu, const CUGeom& cuGeom)
> -{
> -    if (m_slice->m_pps->bUseDQP && cuGeom.depth <=
> m_slice->m_pps->maxCuDQPDepth)
> -    {
> -        if (cu.m_cuDepth[0] > cuGeom.depth) // detect splits
> -        {
> -            bool hasResidual = false;
> -            for (uint32_t absPartIdx = 0; absPartIdx <
> cu.m_numPartitions; absPartIdx++)
> -            {
> -                if (cu.getQtRootCbf(absPartIdx))
> -                {
> -                    hasResidual = true;
> -                    break;
> -                }
> -            }
> -            if (hasResidual)
> -                cu.setQPSubCUs(cu.getRefQP(0), 0, cuGeom.depth);
> -            else
> -                cu.setQPSubParts(cu.getRefQP(0), 0, cuGeom.depth);
> -        }
> -        else
> -        {
> -            if (!cu.getCbf(0, TEXT_LUMA, 0) && !cu.getCbf(0,
> TEXT_CHROMA_U, 0) && !cu.getCbf(0, TEXT_CHROMA_V, 0))
> -                cu.setQPSubParts(cu.getRefQP(0), 0, cuGeom.depth);
> -        }
> -    }
> -}
> -
>  uint32_t Analysis::topSkipMinDepth(const CUData& parentCTU, const CUGeom&
> cuGeom)
>  {
>      /* Do not attempt to code a block larger than the largest block in the
> diff -r ea9bdb10353f -r ce2bd9e51497 source/encoder/analysis.h
> --- a/source/encoder/analysis.h Wed Mar 04 13:20:55 2015 +0530
> +++ b/source/encoder/analysis.h Thu Mar 05 13:03:17 2015 +0530
> @@ -132,9 +132,6 @@
>      /* add the RD cost of coding a split flag (0 or 1) to the given mode
> */
>      void addSplitFlagCost(Mode& mode, uint32_t depth);
>
> -    /* update CBF flags and QP values to be internally consistent */
> -    void checkDQP(CUData& cu, const CUGeom& cuGeom);
> -
>      /* work-avoidance heuristics for RD levels < 5 */
>      uint32_t topSkipMinDepth(const CUData& parentCTU, const CUGeom&
> cuGeom);
>      bool recursionDepthCheck(const CUData& parentCTU, const CUGeom&
> cuGeom, const Mode& bestMode);
> diff -r ea9bdb10353f -r ce2bd9e51497 source/encoder/search.cpp
> --- a/source/encoder/search.cpp Wed Mar 04 13:20:55 2015 +0530
> +++ b/source/encoder/search.cpp Thu Mar 05 13:03:17 2015 +0530
> @@ -1184,8 +1184,8 @@
>          const Yuv* fencYuv = intraMode.fencYuv;
>          intraMode.psyEnergy = m_rdCost.psyCost(cuGeom.log2CUSize - 2,
> fencYuv->m_buf[0], fencYuv->m_size, intraMode.reconYuv.m_buf[0],
> intraMode.reconYuv.m_size);
>      }
> -
>      updateModeCost(intraMode);
> +    checkDQP(cu, cuGeom);
>  }
>
>  /* Note that this function does not save the best intra prediction, it
> must
> @@ -1404,6 +1404,7 @@
>
>      m_entropyCoder.store(intraMode.contexts);
>      updateModeCost(intraMode);
> +    checkDQP(intraMode.cu, cuGeom);
>  }
>
>  uint32_t Search::estIntraPredQT(Mode &intraMode, const CUGeom& cuGeom,
> const uint32_t depthRange[2], uint8_t* sharedModes)
> @@ -2627,6 +2628,7 @@
>      interMode.coeffBits = coeffBits;
>      interMode.mvBits = bits - coeffBits;
>      updateModeCost(interMode);
> +    checkDQP(interMode.cu, cuGeom);
>  }
>
>  void Search::residualTransformQuantInter(Mode& mode, const CUGeom&
> cuGeom, uint32_t absPartIdx, uint32_t tuDepth, const uint32_t depthRange[2])
> @@ -3444,3 +3446,49 @@
>          candModeList[maxIndex] = mode;
>      }
>  }
> +
> +void Search::checkDQP(CUData& cu, const CUGeom& cuGeom)
> +{
> +    if (cu.m_slice->m_pps->bUseDQP && cuGeom.depth <=
> cu.m_slice->m_pps->maxCuDQPDepth)
> +    {
> +        if (cu.getQtRootCbf(0))
> +        {
> +            /* When analysing RDO with DQP bits, the entropy encoder
> should add the cost of DQP bits here
> +             * i.e Encode QP */
> +        }
> +        else
> +        {
> +            cu.setQPSubParts(cu.getRefQP(0), 0, cuGeom.depth);
> +        }
> +    }
> +}
> +
> +void Search::checkDQPForSplitPred(CUData& cu, const CUGeom& cuGeom)
> +{
> +    if ((cuGeom.depth == cu.m_slice->m_pps->maxCuDQPDepth) &&
> cu.m_slice->m_pps->bUseDQP)
> +    {
> +        bool hasResidual = false;
> +
> +        /* Check if any sub-CU has a non-zero QP */
> +        for (uint32_t blkIdx = 0; blkIdx < cuGeom.numPartitions; blkIdx++)
> +        {
> +            if (cu.getQtRootCbf(blkIdx))
> +            {
> +                hasResidual = true;
> +                break;
> +            }
> +        }
> +        if (hasResidual)
> +        {
> +            /* TODO: Encode QP, and recalculate RD cost of splitPred */
> +            /* For all zero CBF sub-CUs, reset QP to RefQP (so that
> deltaQP is not signalled).
> +            When the non-zero CBF sub-CU is found, stop */
> +            bool ret = false;
> +            ret = cu.setQPSubCUs(cu.getRefQP(0), 0, cuGeom.depth);
> +            X265_CHECK(ret, "set sub QP CU failed\n");
> +        }
> +        else
> +            /* No residual within this CU or subCU, so reset QP to RefQP
> */
> +            cu.setQPSubParts(cu.getRefQP(0), 0, cuGeom.depth);
> +    }
> +}
> diff -r ea9bdb10353f -r ce2bd9e51497 source/encoder/search.h
> --- a/source/encoder/search.h   Wed Mar 04 13:20:55 2015 +0530
> +++ b/source/encoder/search.h   Thu Mar 05 13:03:17 2015 +0530
> @@ -281,6 +281,10 @@
>      // pick be chroma mode from available using just sa8d costs
>      void     getBestIntraModeChroma(Mode& intraMode, const CUGeom&
> cuGeom);
>
> +    /* update CBF flags and QP values to be internally consistent */
> +    void checkDQP(CUData& cu, const CUGeom& cuGeom);
> +    void checkDQPForSplitPred(CUData& cu, const CUGeom& cuGeom);
> +
>      class PME : public BondedTaskGroup
>      {
>      public:
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20150306/9f09eb9b/attachment-0001.html>


More information about the x265-devel mailing list