[x265] [PATCH RFC] 1. Bug fix - improved quality drop for low resolution videos in ABR by 5%
Sumalatha Polureddy
sumalatha at multicorewareinc.com
Fri Sep 13 13:57:05 CEST 2013
since changed commit message - sending it as new patch. ignore the
previous mail
On Fri, Sep 13, 2013 at 4:51 PM, Sumalatha Polureddy <
sumalatha at multicorewareinc.com> wrote:
> modified according to comments in this thread
>
>
>
> # HG changeset patch
> # User sumalatha polureddy
> # Date 1379070966 -19800
> # Node ID 540be38baa71ba76e8502dbae8b8f4a4024cdb8d
> # Parent 64cde4a0b1759e2033d99bec709db6acfbe0f07a
> ratecontrol: Tweak to better handle short term compensation
> Increase the coefficient cplxrSum is adjusted by so that short term
> compensation does not suffer as much.
>
> Also, clip the QP for the first frame.
>
> Overall improvement is about 5%.
>
> diff -r 64cde4a0b175 -r 540be38baa71 source/encoder/ratecontrol.cpp
> --- a/source/encoder/ratecontrol.cpp Fri Sep 13 16:40:56 2013 +0530
> +++ b/source/encoder/ratecontrol.cpp Fri Sep 13 16:46:06 2013 +0530
> @@ -72,11 +72,12 @@
> shortTermCplxCount = 0;
> if (rateControlMode == X265_RC_ABR)
> {
> - //TODO : confirm this value. obtained it from x264 when crf is
> disabled , abr enabled.
> - //h->param.rc.i_rc_method == X264_RC_CRF ?
> h->param.rc.f_rf_constant : 24 -- can be tweaked for x265.
> -#define ABR_INIT_QP (24 + QP_BD_OFFSET)
> +
> + //introduced to margin QP for first frame to an optimum level in
> order to stabilize the quality.
> +#define ABR_INIT_QP_MIN (24 + QP_BD_OFFSET)
> +#define ABR_INIT_QP_MAX (38 + QP_BD_OFFSET)
> accumPNorm = .01;
> - accumPQp = (ABR_INIT_QP)*accumPNorm;
> + accumPQp = (ABR_INIT_QP_MIN) * accumPNorm;
> /* estimated ratio that produces a reasonable QP for the first
> I-frame */
> cplxrSum = .01 * pow(7.0e5, qCompress) * pow(2 *ncu, 0.5);
> wantedBitsWindow = bitrate * frameDuration;
> @@ -86,7 +87,7 @@
> pbOffset = 6.0 * (float)(X265_LOG2(param->rc.pbFactor));
> for (int i = 0; i < 3; i++)
> {
> - lastQScaleFor[i] = qp2qScale(ABR_INIT_QP);
> + lastQScaleFor[i] = qp2qScale(ABR_INIT_QP_MIN);
> lmin[i] = qp2qScale(MIN_QP);
> lmax[i] = qp2qScale(MAX_QP);
> }
> @@ -111,15 +112,15 @@
> switch (rateControlMode)
> {
> case X265_RC_ABR:
> - {
> - lastSatd = l->getEstimatedPictureCost(pic);
> - double q = qScale2qp(rateEstimateQscale(rce));
> - qp = Clip3(MIN_QP, MAX_QP, (int)(q + 0.5));
> - rce->qpaRc = qpm = q;
> - rce->newQp = qp;
> - accumPQpUpdate();
> - break;
> - }
> + {
> + lastSatd = l->getEstimatedPictureCost(pic);
> + double q = qScale2qp(rateEstimateQscale(rce));
> + qp = Clip3(MIN_QP, MAX_QP, (int)(q + 0.5));
> + rce->qpaRc = qpm = q;
> + rce->newQp = qp;
> + accumPQpUpdate();
> + break;
> + }
>
> case X265_RC_CQP:
> qp = qpConstant[frameType];
> @@ -160,16 +161,19 @@
> {
> /* B-frames don't have independent rate control, but rather get
> the
> * average QP of the two adjacent P-frames + an offset */
> + TComSlice* prevRefSlice = curFrame->getRefPic(REF_PIC_LIST_0,
> 0)->getSlice();
> + TComSlice* nextRefSlice = curFrame->getRefPic(REF_PIC_LIST_1,
> 0)->getSlice();
> + bool i0 = prevRefSlice->getSliceType() == I_SLICE;
> + bool i1 = nextRefSlice->getSliceType() == I_SLICE;
> + int dt0 = abs(curFrame->getPOC() - prevRefSlice->getPOC());
> + int dt1 = abs(curFrame->getPOC() - nextRefSlice->getPOC());
> + double q0 = prevRefSlice->getSliceQp();
> + double q1 = nextRefSlice->getSliceQp();
>
> - int i0 = curFrame->getRefPic(REF_PIC_LIST_0,
> 0)->getSlice()->getSliceType() == I_SLICE;
> - int i1 = curFrame->getRefPic(REF_PIC_LIST_1,
> 0)->getSlice()->getSliceType() == I_SLICE;
> - int dt0 = abs(curFrame->getPOC() -
> curFrame->getRefPic(REF_PIC_LIST_0, 0)->getPOC());
> - int dt1 = abs(curFrame->getPOC() -
> curFrame->getRefPic(REF_PIC_LIST_1, 0)->getPOC());
> -
> - //TODO:need to figure out this
> - double q0 = curFrame->getRefPic(REF_PIC_LIST_0,
> 0)->getSlice()->getSliceQp();
> - double q1 = curFrame->getRefPic(REF_PIC_LIST_1,
> 0)->getSlice()->getSliceQp();
> -
> + if (prevRefSlice->getSliceType() == B_SLICE &&
> prevRefSlice->isReferenced())
> + q0 -= pbOffset / 2;
> + if (nextRefSlice->getSliceType() == B_SLICE &&
> nextRefSlice->isReferenced())
> + q1 -= pbOffset / 2;
> if (i0 && i1)
> q = (q0 + q1) / 2 + ipOffset;
> else if (i0)
> @@ -183,12 +187,8 @@
> q += pbOffset / 2;
> else
> q += pbOffset;
> -
> - double qScale = qp2qScale(q);
>
> - lastQScaleFor[P_SLICE] = lastQScale = qScale/pbFactor;
> -
> - return qScale;
> + return qp2qScale(q);
> }
> else
> {
> @@ -242,21 +242,32 @@
> q = qp2qScale(accumPQp / accumPNorm);
> q /= fabs(ipFactor);
> }
> - else if (curFrame->getPOC() > 0)
> + if (rateControlMode != X265_RC_CRF)
> {
> - if (rateControlMode != X265_RC_CRF)
> + double lqmin = 0, lqmax = 0;
> +
> + /* Clip the qp of 1st frame to ensure it doesnt detoriate the
> quality */
> + if (curFrame->getPOC() == 0)
> {
> - /* Asymmetric clipping, because symmetric would prevent
> - * overflow control in areas of rapidly oscillating
> complexity */
> - double lqmin = lastQScaleFor[pictType] / lstep;
> - double lqmax = lastQScaleFor[pictType] * lstep;
> - if (overflow > 1.1 && curFrame->getPOC() > 3)
> - lqmax *= lstep;
> - else if (overflow < 0.9)
> - lqmin /= lstep;
> + lqmin = qp2qScale(ABR_INIT_QP_MIN) / lstep;
> + lqmax = qp2qScale(ABR_INIT_QP_MAX) * lstep;
> + double l1 = qScale2qp(lqmin);
> + double l2 = qScale2qp(lqmax);
> + l1=l2;
> + }
> + /* Asymmetric clipping, because symmetric would prevent
> + * overflow control in areas of rapidly oscillating
> complexity */
> + else if (curFrame->getPOC() > 0)
> + {
> + lqmin = lastQScaleFor[pictType] / lstep;
> + lqmax = lastQScaleFor[pictType] * lstep;
> + }
> + if (overflow > 1.1 && curFrame->getPOC() > 3)
> + lqmax *= lstep;
> + else if (overflow < 0.9)
> + lqmin /= lstep;
>
> - q = Clip3(lqmin, lqmax, q);
> - }
> + q = Clip3(lqmin, lqmax, q);
> }
>
> //FIXME use get_diff_limited_q() ?
> @@ -300,16 +311,18 @@
> if (rateControlMode == X265_RC_ABR)
> {
> if (frameType != B_SLICE)
> - cplxrSum += 1.1 *bits * qp2qScale(rce->qpaRc) /
> rce->lastRceq;
> + /* The factor 1.5 is to tune up the actual bits, otherwise
> the cplxrSum is scaled too low
> + * to improve short term compensation for next frame. */
> + cplxrSum += 1.5 *bits * qp2qScale(rce->qpaRc) / rce->lastRceq;
> else
> {
> /* Depends on the fact that B-frame's QP is an offset from
> the following P-frame's.
> * Not perfectly accurate with B-refs, but good enough. */
> - cplxrSum += bits * qp2qScale(rce->qpaRc) / (rce->lastRceq *
> fabs(0.5 * pbFactor));
> + cplxrSum += bits * qp2qScale(rce->qpaRc) / (rce->lastRceq *
> fabs(pbFactor));
> }
> cplxrSum *= cbrDecay;
> wantedBitsWindow += frameDuration * bitrate;
> - wantedBitsWindow *= cbrDecay;
> + wantedBitsWindow *= cbrDecay;
> rce = NULL;
> }
> totalBits += bits;
>
>
>
> On Fri, Sep 13, 2013 at 4:23 PM, Derek Buitenhuis <
> derek.buitenhuis at gmail.com> wrote:
>
>> On 9/13/2013 11:50 AM, Aarthi Priya Thirumalai wrote:
>> > The qscale values are clipped(for P frames) depending on the
>> lastQScaleFor[] at the end to ensure qps dont increase too high/low. they
>> are updated in rateEstimateQScale for non B frames. The above change was
>> introduced so that qp for P frames can adapt based on the qp of preceding
>> B frames too - to see if its improves RateControl. Since it didnt give
>> any big improvements, removing the change.
>>
>> Ah, OK then.
>>
>> - Derek
>> _______________________________________________
>> 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/20130913/79ec7ffa/attachment-0001.html>
More information about the x265-devel
mailing list