<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Feb 12, 2014 at 1:33 AM,  <span dir="ltr"><<a href="mailto:santhoshini@multicorewareinc.com" target="_blank">santhoshini@multicorewareinc.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Santhoshini Sekar <<a href="mailto:santhoshini@multicorewareinc.com">santhoshini@multicorewareinc.com</a>><br>
# Date 1392189204 -19800<br>
#      Wed Feb 12 12:43:24 2014 +0530<br>
# Node ID e83af58ed0f3a9308dacf64f79b9ddad47cd0170<br>
# Parent  699f2aa335e9995e32a07181eb70bd1ed1dfb7e9<br>
vbv: lookahead<br>
<br>
diff -r 699f2aa335e9 -r e83af58ed0f3 source/common/lowres.h<br>
--- a/source/common/lowres.h    Tue Feb 11 13:06:43 2014 +0530<br>
+++ b/source/common/lowres.h    Wed Feb 12 12:43:24 2014 +0530<br>
@@ -121,6 +121,8 @@<br>
     uint16_t(*lowresCosts[X265_BFRAME_MAX + 2][X265_BFRAME_MAX + 2]);<br>
     int32_t*  lowresMvCosts[2][X265_BFRAME_MAX + 1];<br>
     MV*       lowresMvs[2][X265_BFRAME_MAX + 1];<br>
+    int       plannedType[X265_LOOKAHEAD_MAX+1];<br>
+    int64_t   plannedSatd[X265_LOOKAHEAD_MAX+1];<br>
<br>
     /* rate control / adaptive quant data */<br>
     double*   qpAqOffset;      // qp Aq offset values for each Cu<br>
diff -r 699f2aa335e9 -r e83af58ed0f3 source/encoder/ratecontrol.cpp<br>
--- a/source/encoder/ratecontrol.cpp    Tue Feb 11 13:06:43 2014 +0530<br>
+++ b/source/encoder/ratecontrol.cpp    Wed Feb 12 12:43:24 2014 +0530<br>
@@ -384,7 +384,7 @@<br>
     {<br>
         lastSatd = l->getEstimatedPictureCost(pic);<br>
         rce->lastSatd = lastSatd;<br>
-        double q = qScale2qp(rateEstimateQscale(rce));<br>
+        double q = qScale2qp(rateEstimateQscale(pic, rce));<br>
         qp = Clip3(MIN_QP, MAX_MAX_QP, (int)(q + 0.5));<br>
         rce->qpaRc = q;<br>
         /* copy value of lastRceq into thread local rce struct *to be used in RateControlEnd() */<br>
@@ -416,7 +416,7 @@<br>
         accumPQp += qp;<br>
 }<br>
<br>
-double RateControl::rateEstimateQscale(RateControlEntry *rce)<br>
+double RateControl::rateEstimateQscale(TComPic* pic, RateControlEntry *rce)<br>
 {<br>
     double q;<br>
<br>
@@ -558,7 +558,7 @@<br>
         double lmax1 = lmax[sliceType];<br>
         q = Clip3(lmin1, lmax1, q);<br>
<br>
-        q = clipQscale(q);<br>
+        q = clipQscale(pic, q);<br>
<br>
         lastQScaleFor[sliceType] = q;<br>
<br>
@@ -614,7 +614,7 @@<br>
     return (p->coeff * var + p->offset) / (q * p->count);<br>
 }<br>
<br>
-double RateControl::clipQscale(double q)<br>
+double RateControl::clipQscale(TComPic* pic, double q)<br>
 {<br>
     double lmin1 = lmin[sliceType];<br>
     double lmax1 = lmax[sliceType];<br>
@@ -624,8 +624,55 @@<br>
     // since they are controlled by the P-frames' QPs.<br>
     if (isVbv && lastSatd > 0)<br>
     {<br>
-        //if (lookahead){} //for lookahead<br>
-        //else<br>
+       if (cfg->param.lookaheadDepth)<br></blockquote><div><br></div><div>white-space</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+        {<br>
+            int terminate = 0;<br>
+<br>
+            /* Avoid an infinite loop. */<br>
+            for (int iterations = 0; iterations < 1000 && terminate != 3; iterations++)<br>
+            {<br>
+                double frameQ[3];<br>
+                double curBits = predictSize(&pred[sliceType], q, (double)lastSatd);<br>
+                double bufferFillCur = bufferFill - curBits;<br>
+                double targetFill;<br>
+                double totalDuration = 0;<br>
+                frameQ[0] = sliceType == I_SLICE ? q * cfg->param.rc.ipFactor : q;<br>
+                frameQ[1] = frameQ[0] * cfg->param.rc.pbFactor;<br>
+                frameQ[2] = frameQ[0] / cfg->param.rc.ipFactor;<br>
+<br>
+                /* Loop over the planned future frames. */<br>
+                for (int j = 0; bufferFillCur >= 0 && bufferFillCur <= bufferSize; j++)<br>
+                {<br>
+                    totalDuration += frameDuration;<br>
+                    bufferFillCur += vbvMaxRate * frameDuration;<br>
+                    int type = pic->m_lowres.plannedType[j];<br>
+                    int64_t satd = pic->m_lowres.plannedSatd[j];<br>
+                    if (type == X265_TYPE_AUTO)<br>
+                        break;<br>
+                    type = IS_X265_TYPE_I(type) ? I_SLICE : IS_X265_TYPE_B(type) ? B_SLICE : P_SLICE;<br>
+                    curBits = predictSize(&pred[type], frameQ[type], (double)satd);<br>
+                    bufferFillCur -= curBits;<br>
+                }<br>
+                /* Try to get the buffer at least 50% filled, but don't set an impossible goal. */<br>
+                targetFill = X265_MIN(bufferFill + totalDuration * vbvMaxRate * 0.5, bufferSize * 0.5);<br>
+                if (bufferFillCur < targetFill)<br>
+                {<br>
+                    q *= 1.01;<br>
+                    terminate |= 1;<br>
+                    continue;<br>
+                }<br>
+                /* Try to get the buffer no more than 80% filled, but don't set an impossible goal. */<br>
+                targetFill = Clip3(bufferFill - totalDuration * vbvMaxRate * 0.5, bufferSize * 0.8, bufferSize);<br>
+                if (vbvMinRate && bufferFillCur > targetFill)<br>
+                {<br>
+                    q /= 1.01;<br>
+                    terminate |= 2;<br>
+                    continue;<br>
+                }<br>
+                break;<br>
+            }<br>
+        }<br>
+        else<br>
         {<br>
             if ((sliceType == P_SLICE ||<br>
                  (sliceType == I_SLICE && lastNonBPictType == I_SLICE)) &&<br>
diff -r 699f2aa335e9 -r e83af58ed0f3 source/encoder/ratecontrol.h<br>
--- a/source/encoder/ratecontrol.h      Tue Feb 11 13:06:43 2014 +0530<br>
+++ b/source/encoder/ratecontrol.h      Wed Feb 12 12:43:24 2014 +0530<br>
@@ -129,13 +129,13 @@<br>
 protected:<br>
<br>
     double getQScale(RateControlEntry *rce, double rateFactor);<br>
-    double rateEstimateQscale(RateControlEntry *rce); // main logic for calculating QP based on ABR<br>
+    double rateEstimateQscale(TComPic* pic, RateControlEntry *rce); // main logic for calculating QP based on ABR<br>
     void accumPQpUpdate();<br>
     uint32_t acEnergyCu(TComPic* pic, uint32_t block_x, uint32_t block_y);<br>
<br>
     void updateVbv(int64_t bits, RateControlEntry* rce);<br>
     void updatePredictor(Predictor *p, double q, double var, double bits);<br>
-    double clipQscale(double q);<br>
+    double clipQscale(TComPic* pic, double q);<br>
     void updateVbvPlan(Encoder* enc);<br>
     double predictSize(Predictor *p, double q, double var);<br>
     void checkAndResetABR(RateControlEntry* rce);<br>
diff -r 699f2aa335e9 -r e83af58ed0f3 source/encoder/slicetype.cpp<br>
--- a/source/encoder/slicetype.cpp      Tue Feb 11 13:06:43 2014 +0530<br>
+++ b/source/encoder/slicetype.cpp      Wed Feb 12 12:43:24 2014 +0530<br>
@@ -373,13 +373,57 @@<br>
     }<br>
 }<br>
<br>
+void Lookahead::vbvLookahead(Lowres **frames, int numFrames, int keyframe)<br>
+{<br>
+    int prevNonB = 0, curNonB = 1, idx = 0;<br>
+    while (curNonB < numFrames && frames[curNonB]->sliceType == X265_TYPE_B)<br>
+        curNonB++;<br>
+    int nextNonB = keyframe ? prevNonB : curNonB;<br>
+<br>
+    while (curNonB < numFrames)<br>
+    {<br>
+        /* P/I cost: This shouldn't include the cost of nextNonB */<br>
+        if (nextNonB != curNonB)<br>
+        {<br>
+            int p0 = IS_X265_TYPE_I(frames[curNonB]->sliceType) ? curNonB : prevNonB;<br>
+            frames[nextNonB]->plannedSatd[idx] = vbvFrameCost(frames, p0, curNonB, curNonB);<br>
+            frames[nextNonB]->plannedType[idx] = frames[curNonB]->sliceType;<br>
+            idx++;<br>
+        }<br>
+        /* Handle the B-frames: coded order */<br>
+        for (int i = prevNonB+1; i < curNonB; i++, idx++)<br>
+        {<br>
+            frames[nextNonB]->plannedSatd[idx] = vbvFrameCost(frames, prevNonB, curNonB, i);<br>
+            frames[nextNonB]->plannedType[idx] = X265_TYPE_B;<br>
+        }<br>
+        prevNonB = curNonB;<br>
+        curNonB++;<br>
+        while (curNonB <= numFrames && frames[curNonB]->sliceType == X265_TYPE_B)<br>
+            curNonB++;<br>
+    }<br>
+    frames[nextNonB]->plannedType[idx] = X265_TYPE_AUTO;<br>
+}<br>
+<br>
+int64_t Lookahead::vbvFrameCost(Lowres **frames, int p0, int p1, int b)<br>
+{<br>
+    int64_t cost = est.estimateFrameCost(frames, p0, p1, b, 0);<br>
+    if (cfg->param.rc.aqMode)<br>
+    {<br>
+        if (cfg->param.rc.cuTree)<br>
+            return frameCostRecalculate(frames, p0, p1, b);<br>
+        else<br>
+            return frames[b]->costEstAq[b-p0][p1-b];<br>
+    }<br>
+    return cost;<br>
+}<br>
+<br>
 void Lookahead::slicetypeAnalyse(Lowres **frames, bool bKeyframe)<br>
 {<br>
     int numFrames, origNumFrames, keyintLimit, framecnt;<br>
     int maxSearch = X265_MIN(cfg->param.lookaheadDepth, X265_LOOKAHEAD_MAX);<br>
     int cuCount = NUM_CUS;<br>
     int resetStart;<br>
-<br>
+    int isVbvLookahead = cfg->param.rc.vbvBufferSize && cfg->param.lookaheadDepth;<br></blockquote><div><br></div><div>we generally use bools for this:</div><div><br></div><div>bool bIsVbvLookahead</div><div>
 </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
     if (!lastNonB)<br>
         return;<br>
<br>
@@ -403,7 +447,9 @@<br>
     keyintLimit = cfg->param.keyframeMax - frames[0]->frameNum + lastKeyframe - 1;<br>
     origNumFrames = numFrames = X265_MIN(framecnt, keyintLimit);<br>
<br>
-    if (cfg->param.bOpenGOP && numFrames < framecnt)<br>
+    if (isVbvLookahead)<br>
+        numFrames = framecnt;<br>
+    else if (cfg->param.bOpenGOP && numFrames < framecnt)<br>
         numFrames++;<br>
     else if (numFrames == 0)<br>
     {<br>
@@ -538,6 +584,9 @@<br>
         resetStart = X265_MIN(resetStart, j + 1);<br>
     }<br>
<br>
+        if (isVbvLookahead)<br></blockquote><div><br></div><div>white-space</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+        vbvLookahead(frames, numFrames, bKeyframe);<br>
+<br>
     /* Restore frametypes for all frames that haven't actually been decided yet. */<br>
     for (int j = resetStart; j <= numFrames; j++)<br>
     {<br>
diff -r 699f2aa335e9 -r e83af58ed0f3 source/encoder/slicetype.h<br>
--- a/source/encoder/slicetype.h        Tue Feb 11 13:06:43 2014 +0530<br>
+++ b/source/encoder/slicetype.h        Wed Feb 12 12:43:24 2014 +0530<br>
@@ -151,6 +151,8 @@<br>
     bool    scenecutInternal(Lowres **frames, int p0, int p1, bool bRealScenecut);<br>
     void    slicetypePath(Lowres **frames, int length, char(*best_paths)[X265_LOOKAHEAD_MAX + 1]);<br>
     int64_t slicetypePathCost(Lowres **frames, char *path, int64_t threshold);<br>
+    int64_t vbvFrameCost(Lowres **frames, int p0, int p1, int b);<br>
+    void vbvLookahead(Lowres **frames, int numFrames, int keyframes);<br></blockquote><div><br></div><div>line-up the function names</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
     /* called by slicetypeAnalyse() to effect cuTree adjustments to adaptive<br>
      * quant offsets */<br>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>Steve Borho
</div></div>