[x265] [PATCH 1 of 3] ratecontrol: avoid clipping QP multiple times when VBV is not enabled

Steve Borho steve at borho.org
Tue May 6 22:27:56 CEST 2014


On Tue, May 6, 2014 at 5:18 AM,  <deepthi at multicorewareinc.com> wrote:
> # HG changeset patch
> # User Deepthi Nandakumar <deepthi at multicorewareinc.com>
> # Date 1399370478 -19800
> # Node ID 33772b1766588c9088dbf7c3c7f6f6e92b92d27d
> # Parent  075705aa41a9144bb1a4d7f12d837169767630e1
> ratecontrol: avoid clipping QP multiple times when VBV is not enabled.
>
> diff -r 075705aa41a9 -r 33772b176658 source/encoder/ratecontrol.cpp
> --- a/source/encoder/ratecontrol.cpp    Mon May 05 23:26:59 2014 -0500
> +++ b/source/encoder/ratecontrol.cpp    Tue May 06 15:31:18 2014 +0530
> @@ -588,7 +588,8 @@
>          q = Clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);
>          qpNoVbv = x265_qScale2qp(q);
>
> -        q = clipQscale(pic, q);
> +        if(isVbv && currentSatd > 0)

queued with a white-space fixup

> +            q = clipQscale(pic, q);
>
>          lastQScaleFor[sliceType] = q;
>
> @@ -642,117 +643,112 @@
>
>  double RateControl::clipQscale(TComPic* pic, double q)
>  {
> -    double q0 = q;
> -
>      // B-frames are not directly subject to VBV,
>      // since they are controlled by the P-frames' QPs.
> -    if (isVbv && currentSatd > 0)
> +    double q0 = q;
> +    if (param->lookaheadDepth)
>      {
> -        if (param->lookaheadDepth)
> +        int terminate = 0;
> +
> +        /* Avoid an infinite loop. */
> +        for (int iterations = 0; iterations < 1000 && terminate != 3; iterations++)
>          {
> -            int terminate = 0;
> -
> -            /* Avoid an infinite loop. */
> -            for (int iterations = 0; iterations < 1000 && terminate != 3; iterations++)
> +            double frameQ[3];
> +            double curBits = predictSize(&pred[sliceType], q, (double)currentSatd);
> +            double bufferFillCur = bufferFill - curBits;
> +            double targetFill;
> +            double totalDuration = 0;
> +            frameQ[P_SLICE] = sliceType == I_SLICE ? q * param->rc.ipFactor : q;
> +            frameQ[B_SLICE] = frameQ[P_SLICE] * param->rc.pbFactor;
> +            frameQ[I_SLICE] = frameQ[P_SLICE] / param->rc.ipFactor;
> +            /* Loop over the planned future frames. */
> +            for (int j = 0; bufferFillCur >= 0 && bufferFillCur <= bufferSize; j++)
>              {
> -                double frameQ[3];
> -                double curBits = predictSize(&pred[sliceType], q, (double)currentSatd);
> -                double bufferFillCur = bufferFill - curBits;
> -                double targetFill;
> -                double totalDuration = 0;
> -                frameQ[P_SLICE] = sliceType == I_SLICE ? q * param->rc.ipFactor : q;
> -                frameQ[B_SLICE] = frameQ[P_SLICE] * param->rc.pbFactor;
> -                frameQ[I_SLICE] = frameQ[P_SLICE] / param->rc.ipFactor;
> -                /* Loop over the planned future frames. */
> -                for (int j = 0; bufferFillCur >= 0 && bufferFillCur <= bufferSize; j++)
> -                {
> -                    totalDuration += frameDuration;
> -                    bufferFillCur += vbvMaxRate * frameDuration;
> -                    int type = pic->m_lowres.plannedType[j];
> -                    int64_t satd = pic->m_lowres.plannedSatd[j] >> (X265_DEPTH - 8);
> -                    if (type == X265_TYPE_AUTO)
> -                        break;
> -                    type = IS_X265_TYPE_I(type) ? I_SLICE : IS_X265_TYPE_B(type) ? B_SLICE : P_SLICE;
> -                    curBits = predictSize(&pred[type], frameQ[type], (double)satd);
> -                    bufferFillCur -= curBits;
> -                }
> -
> -                /* Try to get the buffer at least 50% filled, but don't set an impossible goal. */
> -                targetFill = X265_MIN(bufferFill + totalDuration * vbvMaxRate * 0.5, bufferSize * 0.5);
> -                if (bufferFillCur < targetFill)
> -                {
> -                    q *= 1.01;
> -                    terminate |= 1;
> -                    continue;
> -                }
> -                /* Try to get the buffer no more than 80% filled, but don't set an impossible goal. */
> -                targetFill = Clip3(bufferSize * 0.8, bufferSize, bufferFill - totalDuration * vbvMaxRate * 0.5);
> -                if (vbvMinRate && bufferFillCur > targetFill)
> -                {
> -                    q /= 1.01;
> -                    terminate |= 2;
> -                    continue;
> -                }
> -                break;
> -            }
> -        }
> -        else
> -        {
> -            if ((sliceType == P_SLICE ||
> -                 (sliceType == I_SLICE && lastNonBPictType == I_SLICE)) &&
> -                bufferFill / bufferSize < 0.5)
> -            {
> -                q /= Clip3(0.5, 1.0, 2.0 * bufferFill / bufferSize);
> +                totalDuration += frameDuration;
> +                bufferFillCur += vbvMaxRate * frameDuration;
> +                int type = pic->m_lowres.plannedType[j];
> +                int64_t satd = pic->m_lowres.plannedSatd[j] >> (X265_DEPTH - 8);
> +                if (type == X265_TYPE_AUTO)
> +                    break;
> +                type = IS_X265_TYPE_I(type) ? I_SLICE : IS_X265_TYPE_B(type) ? B_SLICE : P_SLICE;
> +                curBits = predictSize(&pred[type], frameQ[type], (double)satd);
> +                bufferFillCur -= curBits;
>              }
>
> -            // Now a hard threshold to make sure the frame fits in VBV.
> -            // This one is mostly for I-frames.
> -            double bits = predictSize(&pred[sliceType], q, (double)currentSatd);
> -
> -            // For small VBVs, allow the frame to use up the entire VBV.
> -            double maxFillFactor;
> -            maxFillFactor = bufferSize >= 5 * bufferRate ? 2 : 1;
> -            // For single-frame VBVs, request that the frame use up the entire VBV.
> -            double minFillFactor = singleFrameVbv ? 1 : 2;
> -
> -            for (int iterations = 0; iterations < 10; iterations++)
> +            /* Try to get the buffer at least 50% filled, but don't set an impossible goal. */
> +            targetFill = X265_MIN(bufferFill + totalDuration * vbvMaxRate * 0.5, bufferSize * 0.5);
> +            if (bufferFillCur < targetFill)
>              {
> -                double qf = 1.0;
> -                if (bits > bufferFill / maxFillFactor)
> -                    qf = Clip3(0.2, 1.0, bufferFill / (maxFillFactor * bits));
> -                q /= qf;
> -                bits *= qf;
> -                if (bits < bufferRate / minFillFactor)
> -                    q *= bits * minFillFactor / bufferRate;
> -                bits = predictSize(&pred[sliceType], q, (double)currentSatd);
> +                q *= 1.01;
> +                terminate |= 1;
> +                continue;
>              }
> -
> -            q = X265_MAX(q0, q);
> +            /* Try to get the buffer no more than 80% filled, but don't set an impossible goal. */
> +            targetFill = Clip3(bufferSize * 0.8, bufferSize, bufferFill - totalDuration * vbvMaxRate * 0.5);
> +            if (vbvMinRate && bufferFillCur > targetFill)
> +            {
> +                q /= 1.01;
> +                terminate |= 2;
> +                continue;
> +            }
> +            break;
> +        }
> +    }
> +    else
> +    {
> +        if ((sliceType == P_SLICE ||
> +                (sliceType == I_SLICE && lastNonBPictType == I_SLICE)) &&
> +            bufferFill / bufferSize < 0.5)
> +        {
> +            q /= Clip3(0.5, 1.0, 2.0 * bufferFill / bufferSize);
>          }
>
> -        // Check B-frame complexity, and use up any bits that would
> -        // overflow before the next P-frame.
> -        if (sliceType == P_SLICE)
> +        // Now a hard threshold to make sure the frame fits in VBV.
> +        // This one is mostly for I-frames.
> +        double bits = predictSize(&pred[sliceType], q, (double)currentSatd);
> +
> +        // For small VBVs, allow the frame to use up the entire VBV.
> +        double maxFillFactor;
> +        maxFillFactor = bufferSize >= 5 * bufferRate ? 2 : 1;
> +        // For single-frame VBVs, request that the frame use up the entire VBV.
> +        double minFillFactor = singleFrameVbv ? 1 : 2;
> +
> +        for (int iterations = 0; iterations < 10; iterations++)
>          {
> -            int nb = bframes;
> -            double bits = predictSize(&pred[sliceType], q, (double)currentSatd);
> -            double bbits = predictSize(&predBfromP, q * param->rc.pbFactor, (double)currentSatd);
> -            double space;
> -            if (bbits > bufferRate)
> -                nb = 0;
> -            double pbbits = nb * bbits;
> +            double qf = 1.0;
> +            if (bits > bufferFill / maxFillFactor)
> +                qf = Clip3(0.2, 1.0, bufferFill / (maxFillFactor * bits));
> +            q /= qf;
> +            bits *= qf;
> +            if (bits < bufferRate / minFillFactor)
> +                q *= bits * minFillFactor / bufferRate;
> +            bits = predictSize(&pred[sliceType], q, (double)currentSatd);
> +        }
>
> -            space = bufferFill + (1 + nb) * bufferRate - bufferSize;
> -            if (pbbits < space)
> -            {
> -                q *= X265_MAX(pbbits / space, bits / (0.5 * bufferSize));
> -            }
> -            q = X265_MAX(q0 / 2, q);
> -        }
> -        if (!vbvMinRate)
> -            q = X265_MAX(q0, q);
> +        q = X265_MAX(q0, q);
>      }
>
> +    // Check B-frame complexity, and use up any bits that would
> +    // overflow before the next P-frame.
> +    if (sliceType == P_SLICE)
> +    {
> +        int nb = bframes;
> +        double bits = predictSize(&pred[sliceType], q, (double)currentSatd);
> +        double bbits = predictSize(&predBfromP, q * param->rc.pbFactor, (double)currentSatd);
> +        double space;
> +        if (bbits > bufferRate)
> +            nb = 0;
> +        double pbbits = nb * bbits;
> +
> +        space = bufferFill + (1 + nb) * bufferRate - bufferSize;
> +        if (pbbits < space)
> +        {
> +            q *= X265_MAX(pbbits / space, bits / (0.5 * bufferSize));
> +        }
> +        q = X265_MAX(q0 / 2, q);
> +    }
> +    if (!vbvMinRate)
> +        q = X265_MAX(q0, q);
>      return Clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);
>  }
>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel



-- 
Steve Borho


More information about the x265-devel mailing list