[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