[x265] [PATCH] rc: implement Adaptive Quantization

Steve Borho steve at borho.org
Thu Oct 17 10:30:01 CEST 2013


On Thu, Oct 17, 2013 at 2:22 AM, <aarthi at multicorewareinc.com> wrote:

> # HG changeset patch
> # User Aarthi Thirumalai<aarthi at multicorewareinc.com>
> # Date 1381994486 -19800
> #      Thu Oct 17 12:51:26 2013 +0530
> # Node ID 4e56bc9c1fbbc0ed9cbdb13de6af14d55eb2715e
> # Parent  aad785763f1d38473177e3f1293d3012d79239ca
> rc: implement Adaptive Quantization.
>
> added functions to compute AC Energy per CU for all planes,
> calculate qpAqOffset for each CU
>

Looks good; I'll queue this one so you only need to resend the first


>
> diff -r aad785763f1d -r 4e56bc9c1fbb source/encoder/encoder.cpp
> --- a/source/encoder/encoder.cpp        Thu Oct 17 11:31:33 2013 +0530
> +++ b/source/encoder/encoder.cpp        Thu Oct 17 12:51:26 2013 +0530
> @@ -185,6 +185,8 @@
>
>          // Encoder holds a reference count until collecting stats
>          ATOMIC_INC(&pic->m_countRefEncoders);
> +        if (param.rc.aqMode)
> +            m_rateControl->calcAdaptiveQuantFrame(pic);
>          m_lookahead->addPicture(pic, pic_in->sliceType);
>      }
>
> diff -r aad785763f1d -r 4e56bc9c1fbb source/encoder/ratecontrol.cpp
> --- a/source/encoder/ratecontrol.cpp    Thu Oct 17 11:31:33 2013 +0530
> +++ b/source/encoder/ratecontrol.cpp    Thu Oct 17 12:51:26 2013 +0530
> @@ -50,6 +50,85 @@
>      return 0.85 * pow(2.0, (qp - 12.0) / 6.0);
>  }
>
> +/* Compute variance to derive AC energy of each block */
> +static inline uint32_t acEnergyVar(uint64_t sum_ssd, int shift)
> +{
> +    uint32_t sum = (uint32_t)sum_ssd;
> +    uint32_t ssd = (uint32_t)(sum_ssd >> 32);
> +
> +    return ssd - ((uint64_t)sum * sum >> shift);
> +}
> +
> +/* Find the energy of each block in Y/Cb/Cr plane */
> +static inline uint32_t acEnergyPlane(pixel* src, int srcStride, int
> bChroma)
> +{
> +    int blockStride = FENC_STRIDE >> 3;
> +
> +    if (bChroma)
> +    {
> +        ALIGN_VAR_8(pixel, pix[8 * 8]);
> +        primitives.blockcpy_pp(8, 8, pix, blockStride, src, srcStride);
> +        return acEnergyVar(primitives.var[PARTITION_8x8](pix,
> blockStride), 6);
> +    }
> +    else
> +        return acEnergyVar(primitives.var[PARTITION_16x16](src,
> srcStride), 8);
> +}
> +
> +/* Find the total AC energy of each CU in all planes */
> +double RateControl::acEnergyCu(TComPic* pic, uint32_t cuAddr)
> +{
> +    uint32_t var = 0;
> +    double avgQp = 0;
> +    pixel* srcLuma = pic->getPicYuvOrg()->getLumaAddr(cuAddr);
> +    pixel* srcCb = pic->getPicYuvOrg()->getCbAddr(cuAddr);
> +    pixel* srcCr = pic->getPicYuvOrg()->getCrAddr(cuAddr);
> +    UInt blockWidth = g_maxCUWidth >> 2;
> +    UInt blockHeight = g_maxCUHeight >> 2;
> +    UInt frameStride = pic->getPicYuvOrg()->getStride();
> +    UInt cStride = pic->getPicYuvOrg()->getCStride();
> +
> +    // Calculate Qp offset for each 16x16 block in the CU and average
> them over entire CU
> +    for (UInt h = 0, cnt = 0; h < g_maxCUHeight; h += blockHeight)
> +    {
> +        for (UInt w = 0; w < g_maxCUWidth; w += blockWidth, cnt++)
> +        {
> +            UInt blockOffsetLuma = w + (h * frameStride);
> +            UInt blockOffsetChroma = (w >> 1) + ((h >> 1) * cStride);
> +            var = acEnergyPlane(srcLuma + blockOffsetLuma, frameStride,
> 0);
> +            var += acEnergyPlane(srcCb + blockOffsetChroma, cStride, 1);
> +            var += acEnergyPlane(srcCr + blockOffsetChroma, cStride, 1);
> +            avgQp += cfg->param.rc.aqStrength * (X265_LOG2(X265_MAX(var,
> 1)) - (14.427f));
> +        }
> +    }
> +
> +    avgQp /= 16;
> +    x265_emms();
> +    return avgQp;
> +}
> +
> +void RateControl::calcAdaptiveQuantFrame(TComPic *pic)
> +{
> +    double strength;
> +
> +    /* Actual adaptive quantization */
> +    if (cfg->param.rc.aqMode)
> +    {
> +        strength = cfg->param.rc.aqStrength * 1.0397f;
> +        int maxRows = pic->getPicSym()->getFrameHeightInCU();
> +        int maxCols = pic->getPicSym()->getFrameWidthInCU();
> +        for (int cu_y = 0; cu_y < maxRows; cu_y++)
> +        {
> +            for (int cu_x = 0; cu_x < maxCols; cu_x++)
> +            {
> +                double qp_adj;
> +                int cu_xy = maxCols * cu_y + cu_x;
> +                qp_adj = acEnergyCu(pic, cu_xy);
> +                pic->m_qpAqOffset[cu_xy] = qp_adj;
> +            }
> +        }
> +    }
> +}
> +
>  RateControl::RateControl(TEncCfg * _cfg)
>  {
>      this->cfg = _cfg;
> diff -r aad785763f1d -r 4e56bc9c1fbb source/encoder/ratecontrol.h
> --- a/source/encoder/ratecontrol.h      Thu Oct 17 11:31:33 2013 +0530
> +++ b/source/encoder/ratecontrol.h      Thu Oct 17 12:51:26 2013 +0530
> @@ -80,7 +80,7 @@
>
>      // to be called for each frame to process RateCOntrol and set QP
>      void rateControlStart(TComPic* pic, Lookahead *, RateControlEntry*
> rce);
> -
> +    void calcAdaptiveQuantFrame(TComPic *pic);
>      int rateControlEnd(int64_t bits, RateControlEntry* rce);
>
>  protected:
> @@ -88,6 +88,7 @@
>      double getQScale(RateControlEntry *rce, double rateFactor);
>      double rateEstimateQscale(RateControlEntry *rce); // main logic for
> calculating QP based on ABR
>      void accumPQpUpdate();
> +    double acEnergyCu(TComPic* pic, uint32_t cuAddr);
>  };
>  }
>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>



-- 
Steve Borho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20131017/8b7f8079/attachment-0001.html>


More information about the x265-devel mailing list