<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>