<div dir="ltr">pls ignore the previous patch. It has a few bugs while merging.<div>here is the fixed one :</div><div><br></div><div><br></div><div><div># HG changeset patch</div><div># User Divya Manivannan <<a href="mailto:divya@multicorewareinc.com">divya@multicorewareinc.com</a>></div><div># Date 1448267770 -19800</div><div># Mon Nov 23 14:06:10 2015 +0530</div><div># Branch stable</div><div># Node ID 0c49c9cc75e4c1ef9534a28b49b97b9107636f5d</div><div># Parent 6b308775b6f065ea5002a76a40aa6f5d81e8ee50</div><div>rc: implement 2 pass CRF, when vbv is enabled.</div><div><br></div><div>Allow CRF with VBV in 2nd pass to increase the quality of capped CRF in the first pass.</div><div><br></div><div>diff -r 6b308775b6f0 -r 0c49c9cc75e4 source/common/param.cpp</div><div>--- a/source/common/param.cpp<span class="" style="white-space:pre"> </span>Mon Nov 23 12:26:45 2015 +0530</div><div>+++ b/source/common/param.cpp<span class="" style="white-space:pre"> </span>Mon Nov 23 14:06:10 2015 +0530</div><div>@@ -1170,7 +1170,7 @@</div><div> CHECK(0 > param->noiseReductionIntra || param->noiseReductionIntra > 2000, "Valid noise reduction range 0 - 2000");</div><div> if (param->noiseReductionInter)</div><div> CHECK(0 > param->noiseReductionInter || param->noiseReductionInter > 2000, "Valid noise reduction range 0 - 2000");</div><div>- CHECK(param->rc.rateControlMode == X265_RC_CRF && param->rc.bStatRead,</div><div>+ CHECK(param->rc.rateControlMode == X265_RC_CRF && param->rc.bStatRead && param->rc.vbvMaxBitrate == 0,</div><div> "Constant rate-factor is incompatible with 2pass");</div><div> CHECK(param->rc.rateControlMode == X265_RC_CQP && param->rc.bStatRead,</div><div> "Constant QP is incompatible with 2pass");</div><div>diff -r 6b308775b6f0 -r 0c49c9cc75e4 source/encoder/ratecontrol.cpp</div><div>--- a/source/encoder/ratecontrol.cpp<span class="" style="white-space:pre"> </span>Mon Nov 23 12:26:45 2015 +0530</div><div>+++ b/source/encoder/ratecontrol.cpp<span class="" style="white-space:pre"> </span>Mon Nov 23 14:06:10 2015 +0530</div><div>@@ -142,6 +142,8 @@</div><div> rce->expectedVbv = rce2Pass->expectedVbv;</div><div> rce->blurredComplexity = rce2Pass->blurredComplexity;</div><div> rce->sliceType = rce2Pass->sliceType;</div><div>+ rce->qpNoVbv = rce2Pass->qpNoVbv;</div><div>+ rce->newQp = rce2Pass->newQp;</div><div> }</div><div> </div><div> } // end anonymous namespace</div><div>@@ -205,7 +207,7 @@</div><div> m_rateFactorMaxDecrement = m_param->rc.rfConstant - m_param->rc.rfConstantMin;</div><div> }</div><div> m_isAbr = m_param->rc.rateControlMode != X265_RC_CQP && !m_param->rc.bStatRead;</div><div>- m_2pass = m_param->rc.rateControlMode == X265_RC_ABR && m_param->rc.bStatRead;</div><div>+ m_2pass = (m_param->rc.rateControlMode == X265_RC_ABR || m_param->rc.vbvMaxBitrate > 0) && m_param->rc.bStatRead;</div><div> m_bitrate = m_param->rc.bitrate * 1000;</div><div> m_frameDuration = (double)m_param->fpsDenom / m_param->fpsNum;</div><div> m_qp = m_param->rc.qp;</div><div>@@ -488,6 +490,12 @@</div><div> x265_log(m_param, X265_LOG_ERROR, "Rce Entries for 2 pass cannot be allocated\n");</div><div> return false;</div><div> }</div><div>+ m_encOrder = X265_MALLOC(int, m_numEntries);</div><div>+ if (!m_encOrder)</div><div>+ {</div><div>+ x265_log(m_param, X265_LOG_ERROR, "Encode order for 2 pass cannot be allocated\n");</div><div>+ return false;</div><div>+ }</div><div> /* init all to skipped p frames */</div><div> for (int i = 0; i < m_numEntries; i++)</div><div> {</div><div>@@ -504,6 +512,7 @@</div><div> {</div><div> RateControlEntry *rce;</div><div> int frameNumber;</div><div>+ int encodeOrder;</div><div> char picType;</div><div> int e;</div><div> char *next;</div><div>@@ -511,13 +520,14 @@</div><div> next = strstr(p, ";");</div><div> if (next)</div><div> *next++ = 0;</div><div>- e = sscanf(p, " in:%d ", &frameNumber);</div><div>+ e = sscanf(p, " in:%d out:%d", &frameNumber, &encodeOrder);</div><div> if (frameNumber < 0 || frameNumber >= m_numEntries)</div><div> {</div><div> x265_log(m_param, X265_LOG_ERROR, "bad frame number (%d) at stats line %d\n", frameNumber, i);</div><div> return false;</div><div> }</div><div>- rce = &m_rce2Pass[frameNumber];</div><div>+ rce = &m_rce2Pass[encodeOrder];</div><div>+ m_encOrder[frameNumber] = encodeOrder;</div><div> e += sscanf(p, " in:%*d out:%*d type:%c q:%lf q-aq:%lf q-noVbv:%lf tex:%d mv:%d misc:%d icu:%lf pcu:%lf scu:%lf",</div><div> &picType, &qpRc, &qpAq, &qNoVbv, &rce->coeffBits,</div><div> &rce->mvBits, &rce->miscBits, &rce->iCuCount, &rce->pCuCount,</div><div>@@ -538,7 +548,7 @@</div><div> x265_log(m_param, X265_LOG_ERROR, "statistics are damaged at line %d, parser out=%d\n", i, e);</div><div> return false;</div><div> }</div><div>- rce->qScale = x265_qp2qScale(qpRc);</div><div>+ rce->qScale = rce->newQScale = x265_qp2qScale(qpRc);</div><div> totalQpAq += qpAq;</div><div> rce->qpNoVbv = qNoVbv;</div><div> rce->qpaRc = qpRc;</div><div>@@ -546,8 +556,7 @@</div><div> p = next;</div><div> }</div><div> X265_FREE(statsBuf);</div><div>-</div><div>- if (m_param->rc.rateControlMode == X265_RC_ABR)</div><div>+ if (m_param->rc.rateControlMode == X265_RC_ABR || m_param->rc.vbvMaxBitrate > 0)</div><div> {</div><div> if (!initPass2())</div><div> return false;</div><div>@@ -630,11 +639,8 @@</div><div> </div><div> #undef MAX_DURATION</div><div> }</div><div>-</div><div>-bool RateControl::initPass2()</div><div>+bool RateControl::analyseABR2Pass(int startIndex, int endIndex, uint64_t allAvailableBits)</div><div> {</div><div>- uint64_t allConstBits = 0;</div><div>- uint64_t allAvailableBits = uint64_t(m_param->rc.bitrate * 1000. * m_numEntries * m_frameDuration);</div><div> double rateFactor, stepMult;</div><div> double qBlur = m_param->rc.qblur;</div><div> double cplxBlur = m_param->rc.complexityBlur;</div><div>@@ -643,30 +649,19 @@</div><div> double *qScale, *blurredQscale;</div><div> double baseCplx = m_ncu * (m_param->bframes ? 120 : 80);</div><div> double clippedDuration = CLIP_DURATION(m_frameDuration) / BASE_FRAME_DURATION;</div><div>-</div><div>- /* find total/average complexity & const_bits */</div><div>- for (int i = 0; i < m_numEntries; i++)</div><div>- allConstBits += m_rce2Pass[i].miscBits;</div><div>-</div><div>- if (allAvailableBits < allConstBits)</div><div>- {</div><div>- x265_log(m_param, X265_LOG_ERROR, "requested bitrate is too low. estimated minimum is %d kbps\n",</div><div>- (int)(allConstBits * m_fps / m_numEntries * 1000.));</div><div>- return false;</div><div>- }</div><div>-</div><div>+ int framesCount = endIndex - startIndex + 1;</div><div> /* Blur complexities, to reduce local fluctuation of QP.</div><div> * We don't blur the QPs directly, because then one very simple frame</div><div> * could drag down the QP of a nearby complex frame and give it more</div><div> * bits than intended. */</div><div>- for (int i = 0; i < m_numEntries; i++)</div><div>+ for (int i = startIndex; i <= endIndex; i++)</div><div> {</div><div> double weightSum = 0;</div><div> double cplxSum = 0;</div><div> double weight = 1.0;</div><div> double gaussianWeight;</div><div> /* weighted average of cplx of future frames */</div><div>- for (int j = 1; j < cplxBlur * 2 && j < m_numEntries - i; j++)</div><div>+ for (int j = 1; j < cplxBlur * 2 && j <= endIndex - i; j++)</div><div> {</div><div> RateControlEntry *rcj = &m_rce2Pass[i + j];</div><div> weight *= 1 - pow(rcj->iCuCount / m_ncu, 2);</div><div>@@ -690,11 +685,10 @@</div><div> }</div><div> m_rce2Pass[i].blurredComplexity = cplxSum / weightSum;</div><div> }</div><div>-</div><div>- CHECKED_MALLOC(qScale, double, m_numEntries);</div><div>+ CHECKED_MALLOC(qScale, double, framesCount);</div><div> if (filterSize > 1)</div><div> {</div><div>- CHECKED_MALLOC(blurredQscale, double, m_numEntries);</div><div>+ CHECKED_MALLOC(blurredQscale, double, framesCount);</div><div> }</div><div> else</div><div> blurredQscale = qScale;</div><div>@@ -705,9 +699,8 @@</div><div> * because qscale2bits is not invertible, but we can start with the simple</div><div> * approximation of scaling the 1st pass by the ratio of bitrates.</div><div> * The search range is probably overkill, but speed doesn't matter here. */</div><div>-</div><div> expectedBits = 1;</div><div>- for (int i = 0; i < m_numEntries; i++)</div><div>+ for (int i = startIndex; i <= endIndex; i++)</div><div> {</div><div> RateControlEntry* rce = &m_rce2Pass[i];</div><div> double q = getQScale(rce, 1.0);</div><div>@@ -784,12 +777,10 @@</div><div> X265_FREE(qScale);</div><div> if (filterSize > 1)</div><div> X265_FREE(blurredQscale);</div><div>-</div><div> if (m_isVbv)</div><div>- if (!vbv2Pass(allAvailableBits))</div><div>+ if (!vbv2Pass(allAvailableBits, endIndex, startIndex))</div><div> return false;</div><div>- expectedBits = countExpectedBits();</div><div>-</div><div>+ expectedBits = countExpectedBits(startIndex, endIndex);</div><div> if (fabs(expectedBits / allAvailableBits - 1.0) > 0.01)</div><div> {</div><div> double avgq = 0;</div><div>@@ -822,7 +813,125 @@</div><div> return false;</div><div> }</div><div> </div><div>-bool RateControl::vbv2Pass(uint64_t allAvailableBits)</div><div>+bool RateControl::initPass2()</div><div>+{</div><div>+ uint64_t allConstBits = 0, allCodedBits = 0;</div><div>+ uint64_t allAvailableBits = uint64_t(m_param->rc.bitrate * 1000. * m_numEntries * m_frameDuration);</div><div>+ int startIndex, framesCount, endIndex, cnt;</div><div>+ int fps = (int)(m_fps + 0.5);</div><div>+ startIndex = endIndex = framesCount = 0;</div><div>+ allAvailableBits = uint64_t(m_param->rc.vbvMaxBitrate * 1000. * m_numEntries * m_frameDuration);</div><div>+ bool isQpModified = true;</div><div>+ int diffQp = 0;</div><div>+ int64_t targetBits = 0;</div><div>+ int64_t expectedBits = 0;</div><div>+ for (startIndex = 0, endIndex = 0; endIndex < m_numEntries; endIndex++)</div><div>+ {</div><div>+ allConstBits += m_rce2Pass[endIndex].miscBits;</div><div>+ allCodedBits += m_rce2Pass[endIndex].coeffBits + m_rce2Pass[endIndex].mvBits;</div><div>+ if (m_param->rc.rateControlMode == X265_RC_CRF)</div><div>+ {</div><div>+ framesCount = endIndex - startIndex + 1;</div><div>+ diffQp += int (m_rce2Pass[endIndex].qpaRc - m_rce2Pass[endIndex].qpNoVbv);</div><div>+ if (framesCount > fps)</div><div>+ diffQp -= int (m_rce2Pass[endIndex - fps].qpaRc - m_rce2Pass[endIndex - fps].qpNoVbv);</div><div>+ if (framesCount >= fps)</div><div>+ {</div><div>+ if (diffQp >= 1)</div><div>+ {</div><div>+ if (!isQpModified && endIndex > fps)</div><div>+ {</div><div>+ double factor = 2;</div><div>+ double step = 0;</div><div>+ for (int start = endIndex; start <= endIndex + fps - 1 && start < m_numEntries; start++)</div><div>+ {</div><div>+ RateControlEntry *rce = &m_rce2Pass[start];</div><div>+ targetBits += qScale2bits(rce, x265_qp2qScale(rce->qpNoVbv));</div><div>+ expectedBits += qScale2bits(rce, rce->qScale);</div><div>+ }</div><div>+ if (expectedBits < 0.95 * targetBits)</div><div>+ {</div><div>+ isQpModified = true;</div><div>+ while (endIndex + fps < m_numEntries)</div><div>+ {</div><div>+ step = pow(2, factor / 6.0);</div><div>+ expectedBits = 0;</div><div>+ for (int start = endIndex; start <= endIndex + fps - 1; start++)</div><div>+ {</div><div>+ RateControlEntry *rce = &m_rce2Pass[start];</div><div>+ rce->newQScale = rce->qScale / step;</div><div>+ X265_CHECK(rce->newQScale >= 0, "new Qscale is negative\n");</div><div>+ expectedBits += qScale2bits(rce, rce->newQScale);</div><div>+ rce->newQp = x265_qScale2qp(rce->newQScale);</div><div>+ }</div><div>+ if (expectedBits >= targetBits && step > 1)</div><div>+ factor *= 0.90;</div><div>+ else</div><div>+ break;</div><div>+ }</div><div>+</div><div>+ if (m_isVbv && endIndex + fps < m_numEntries)</div><div>+ if (!vbv2Pass(targetBits, endIndex + fps - 1, endIndex))</div><div>+ return false;</div><div>+</div><div>+ double prevFactor = factor;</div><div>+ targetBits = 0;</div><div>+ expectedBits = 0;</div><div>+</div><div>+ for (int start = endIndex - fps; start <= endIndex - 1; start++)</div><div>+ {</div><div>+ RateControlEntry *rce = &m_rce2Pass[start];</div><div>+ targetBits += qScale2bits(rce, x265_qp2qScale(rce->qpNoVbv));</div><div>+ }</div><div>+ while (1)</div><div>+ {</div><div>+ step = pow(2, factor / 6.0);</div><div>+ expectedBits = 0;</div><div>+ for (int start = endIndex - fps; start <= endIndex - 1; start++)</div><div>+ {</div><div>+ RateControlEntry *rce = &m_rce2Pass[start];</div><div>+ rce->newQScale = rce->qScale * step;</div><div>+ X265_CHECK(rce->newQScale >= 0, "new Qscale is negative\n");</div><div>+ expectedBits += qScale2bits(rce, rce->newQScale);</div><div>+ rce->newQp = x265_qScale2qp(rce->newQScale);</div><div>+ }</div><div>+ if (expectedBits > targetBits && step > 1)</div><div>+ factor *= 1.1;</div><div>+ else</div><div>+ break;</div><div>+ }</div><div>+ if (m_isVbv)</div><div>+ if (!vbv2Pass(targetBits, endIndex - 1, endIndex - fps))</div><div>+ return false;</div><div>+ diffQp = 0;</div><div>+ startIndex = endIndex + 1;</div><div>+ targetBits = expectedBits = 0;</div><div>+ }</div><div>+ else</div><div>+ targetBits = expectedBits = 0;</div><div>+ }</div><div>+ }</div><div>+ else</div><div>+ isQpModified = false;</div><div>+ }</div><div>+ }</div><div>+ }</div><div>+</div><div>+ if (m_param->rc.rateControlMode == X265_RC_ABR)</div><div>+ {</div><div>+ if (allAvailableBits < allConstBits)</div><div>+ {</div><div>+ x265_log(m_param, X265_LOG_ERROR, "requested bitrate is too low. estimated minimum is %d kbps\n",</div><div>+ (int)(allConstBits * m_fps / framesCount * 1000.));</div><div>+ return false;</div><div>+ }</div><div>+ if (!analyseABR2Pass(0, m_numEntries - 1, allAvailableBits))</div><div>+ return false;</div><div>+ }</div><div>+ return true;</div><div>+}</div><div>+</div><div>+bool RateControl::vbv2Pass(uint64_t allAvailableBits, int endPos, int startPos)</div><div> {</div><div> /* for each interval of bufferFull .. underflow, uniformly increase the qp of all</div><div> * frames in the interval until either buffer is full at some intermediate frame or the</div><div>@@ -848,10 +957,10 @@</div><div> { /* not first iteration */</div><div> adjustment = X265_MAX(X265_MIN(expectedBits / allAvailableBits, 0.999), 0.9);</div><div> fills[-1] = m_bufferSize * m_param->rc.vbvBufferInit;</div><div>- t0 = 0;</div><div>+ t0 = startPos;</div><div> /* fix overflows */</div><div> adjMin = 1;</div><div>- while (adjMin && findUnderflow(fills, &t0, &t1, 1))</div><div>+ while (adjMin && findUnderflow(fills, &t0, &t1, 1, endPos))</div><div> {</div><div> adjMin = fixUnderflow(t0, t1, adjustment, MIN_QPSCALE, MAX_MAX_QPSCALE);</div><div> t0 = t1;</div><div>@@ -862,20 +971,16 @@</div><div> t0 = 0;</div><div> /* fix underflows -- should be done after overflow, as we'd better undersize target than underflowing VBV */</div><div> adjMax = 1;</div><div>- while (adjMax && findUnderflow(fills, &t0, &t1, 0))</div><div>+ while (adjMax && findUnderflow(fills, &t0, &t1, 0, endPos))</div><div> adjMax = fixUnderflow(t0, t1, 1.001, MIN_QPSCALE, MAX_MAX_QPSCALE );</div><div>-</div><div>- expectedBits = countExpectedBits();</div><div>+ expectedBits = countExpectedBits(startPos, endPos);</div><div> }</div><div>- while ((expectedBits < .995 * allAvailableBits) && ((int64_t)(expectedBits+.5) > (int64_t)(prevBits+.5)));</div><div>-</div><div>+ while ((expectedBits < .995 * allAvailableBits) && ((int64_t)(expectedBits+.5) > (int64_t)(prevBits+.5)) && !(m_param->rc.rateControlMode == X265_RC_CRF));</div><div> if (!adjMax)</div><div> x265_log(m_param, X265_LOG_WARNING, "vbv-maxrate issue, qpmax or vbv-maxrate too low\n");</div><div>-</div><div> /* store expected vbv filling values for tracking when encoding */</div><div>- for (int i = 0; i < m_numEntries; i++)</div><div>+ for (int i = startPos; i <= endPos; i++)</div><div> m_rce2Pass[i].expectedVbv = m_bufferSize - fills[i];</div><div>-</div><div> X265_FREE(fills - 1);</div><div> return true;</div><div> </div><div>@@ -915,9 +1020,10 @@</div><div> m_param->bframes = 1;</div><div> return X265_TYPE_AUTO;</div><div> }</div><div>- int frameType = m_rce2Pass[frameNum].sliceType == I_SLICE ? (frameNum > 0 && m_param->bOpenGOP ? X265_TYPE_I : X265_TYPE_IDR)</div><div>- : m_rce2Pass[frameNum].sliceType == P_SLICE ? X265_TYPE_P</div><div>- : (m_rce2Pass[frameNum].sliceType == B_SLICE && m_rce2Pass[frameNum].keptAsRef? X265_TYPE_BREF : X265_TYPE_B);</div><div>+ int index = m_encOrder[frameNum];</div><div>+ int frameType = m_rce2Pass[index].sliceType == I_SLICE ? (frameNum > 0 && m_param->bOpenGOP ? X265_TYPE_I : X265_TYPE_IDR)</div><div>+ : m_rce2Pass[index].sliceType == P_SLICE ? X265_TYPE_P</div><div>+ : (m_rce2Pass[index].sliceType == B_SLICE && m_rce2Pass[index].keptAsRef ? X265_TYPE_BREF : X265_TYPE_B);</div><div> return frameType;</div><div> }</div><div> else</div><div>@@ -968,7 +1074,8 @@</div><div> if (m_param->rc.bStatRead)</div><div> {</div><div> X265_CHECK(rce->poc >= 0 && rce->poc < m_numEntries, "bad encode ordinal\n");</div><div>- copyRceData(rce, &m_rce2Pass[rce->poc]);</div><div>+ int index = m_encOrder[rce->poc];</div><div>+ copyRceData(rce, &m_rce2Pass[index]);</div><div> }</div><div> rce->isActive = true;</div><div> bool isRefFrameScenecut = m_sliceType!= I_SLICE && m_curSlice->m_refPicList[0][0]->m_lowres.bScenecut == 1;</div><div>@@ -1032,6 +1139,16 @@</div><div> }</div><div> }</div><div> }</div><div>+ if (!m_isAbr && m_2pass && m_param->rc.rateControlMode == X265_RC_CRF)</div><div>+ {</div><div>+ rce->qScale = rce->newQScale;</div><div>+ rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = x265_qScale2qp(rce->newQScale);</div><div>+ m_qp = int(rce->qpaRc + 0.5);</div><div>+ rce->frameSizePlanned = qScale2bits(rce, rce->qScale);</div><div>+ m_framesDone++;</div><div>+ return m_qp;</div><div>+ }</div><div>+</div><div> if (m_isAbr || m_2pass) // ABR,CRF</div><div> {</div><div> if (m_isAbr || m_isVbv)</div><div>@@ -1203,11 +1320,10 @@</div><div> }</div><div> return q;</div><div> }</div><div>-</div><div>-double RateControl::countExpectedBits()</div><div>+double RateControl::countExpectedBits(int startPos, int endPos)</div><div> {</div><div> double expectedBits = 0;</div><div>- for( int i = 0; i < m_numEntries; i++ )</div><div>+ for (int i = startPos; i <= endPos; i++)</div><div> {</div><div> RateControlEntry *rce = &m_rce2Pass[i];</div><div> rce->expectedBits = (uint64_t)expectedBits;</div><div>@@ -1215,8 +1331,7 @@</div><div> }</div><div> return expectedBits;</div><div> }</div><div>-</div><div>-bool RateControl::findUnderflow(double *fills, int *t0, int *t1, int over)</div><div>+bool RateControl::findUnderflow(double *fills, int *t0, int *t1, int over, int endPos)</div><div> {</div><div> /* find an interval ending on an overflow or underflow (depending on whether</div><div> * we're adding or removing bits), and starting on the earliest frame that</div><div>@@ -1226,7 +1341,7 @@</div><div> double fill = fills[*t0 - 1];</div><div> double parity = over ? 1. : -1.;</div><div> int start = -1, end = -1;</div><div>- for (int i = *t0; i < m_numEntries; i++)</div><div>+ for (int i = *t0; i <= endPos; i++)</div><div> {</div><div> fill += (m_frameDuration * m_vbvMaxRate -</div><div> qScale2bits(&m_rce2Pass[i], m_rce2Pass[i].newQScale)) * parity;</div><div>@@ -1263,12 +1378,11 @@</div><div> }</div><div> return adjusted;</div><div> }</div><div>-</div><div> bool RateControl::cuTreeReadFor2Pass(Frame* frame)</div><div> {</div><div>- uint8_t sliceTypeActual = (uint8_t)m_rce2Pass[frame->m_poc].sliceType;</div><div>-</div><div>- if (m_rce2Pass[frame->m_poc].keptAsRef)</div><div>+ int index = m_encOrder[frame->m_poc];</div><div>+ uint8_t sliceTypeActual = (uint8_t)m_rce2Pass[index].sliceType;</div><div>+ if (m_rce2Pass[index].keptAsRef)</div><div> {</div><div> /* TODO: We don't need pre-lookahead to measure AQ offsets, but there is currently</div><div> * no way to signal this */</div><div>@@ -1948,6 +2062,8 @@</div><div> </div><div> int RateControl::rowDiagonalVbvRateControl(Frame* curFrame, uint32_t row, RateControlEntry* rce, double& qpVbv)</div><div> {</div><div>+ if (m_param->rc.bStatRead && m_param->rc.rateControlMode == X265_RC_CRF)</div><div>+ return 0;</div><div> FrameData& curEncData = *curFrame->m_encData;</div><div> double qScaleVbv = x265_qp2qScale(qpVbv);</div><div> uint64_t rowSatdCost = curEncData.m_rowStat[row].diagSatd;</div><div>@@ -2195,7 +2311,7 @@</div><div> </div><div> if (m_param->rc.aqMode || m_isVbv)</div><div> {</div><div>- if (m_isVbv)</div><div>+ if (m_isVbv && !(m_2pass && m_param->rc.rateControlMode == X265_RC_CRF))</div><div> {</div><div> /* determine avg QP decided by VBV rate control */</div><div> for (uint32_t i = 0; i < slice->m_sps->numCuInHeight; i++)</div><div>diff -r 6b308775b6f0 -r 0c49c9cc75e4 source/encoder/ratecontrol.h</div><div>--- a/source/encoder/ratecontrol.h<span class="" style="white-space:pre"> </span>Mon Nov 23 12:26:45 2015 +0530</div><div>+++ b/source/encoder/ratecontrol.h<span class="" style="white-space:pre"> </span>Mon Nov 23 14:06:10 2015 +0530</div><div>@@ -205,8 +205,8 @@</div><div> double m_lastAccumPNorm;</div><div> double m_expectedBitsSum; /* sum of qscale2bits after rceq, ratefactor, and overflow, only includes finished frames */</div><div> int64_t m_predictedBits;</div><div>+ int *m_encOrder;</div><div> RateControlEntry* m_rce2Pass;</div><div>-</div><div> struct</div><div> {</div><div> uint16_t *qpBuffer[2]; /* Global buffers for converting MB-tree quantizer data. */</div><div>@@ -258,11 +258,12 @@</div><div> void checkAndResetABR(RateControlEntry* rce, bool isFrameDone);</div><div> double predictRowsSizeSum(Frame* pic, RateControlEntry* rce, double qpm, int32_t& encodedBits);</div><div> bool initPass2();</div><div>+ bool analyseABR2Pass(int startPoc, int endPoc, uint64_t allAvailableBits);</div><div> void initFramePredictors();</div><div> double getDiffLimitedQScale(RateControlEntry *rce, double q);</div><div>- double countExpectedBits();</div><div>- bool vbv2Pass(uint64_t allAvailableBits);</div><div>- bool findUnderflow(double *fills, int *t0, int *t1, int over);</div><div>+ double countExpectedBits(int startPos, int framesCount);</div><div>+ bool vbv2Pass(uint64_t allAvailableBits, int frameCount, int startPos);</div><div>+ bool findUnderflow(double *fills, int *t0, int *t1, int over, int framesCount);</div><div> bool fixUnderflow(int t0, int t1, double adjustment, double qscaleMin, double qscaleMax);</div><div> };</div><div> }</div></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Nov 23, 2015 at 2:16 PM, <span dir="ltr"><<a href="mailto:aarthi@multicorewareinc.com" target="_blank">aarthi@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 Divya Manivannan <<a href="mailto:divya@multicorewareinc.com">divya@multicorewareinc.com</a>><br>
# Date 1448267770 -19800<br>
# Mon Nov 23 14:06:10 2015 +0530<br>
# Branch stable<br>
# Node ID ffb0111298cdfcf6fe77d143089144c23b644b2d<br>
# Parent 6b308775b6f065ea5002a76a40aa6f5d81e8ee50<br>
rc: implement 2 pass CRF, when vbv is enabled.<br>
<br>
Allow CRF with VBV in 2nd pass to increase the quality of capped CRF in the first pass.<br>
<br>
diff -r 6b308775b6f0 -r ffb0111298cd source/common/param.cpp<br>
--- a/source/common/param.cpp Mon Nov 23 12:26:45 2015 +0530<br>
+++ b/source/common/param.cpp Mon Nov 23 14:06:10 2015 +0530<br>
@@ -1170,7 +1170,7 @@<br>
CHECK(0 > param->noiseReductionIntra || param->noiseReductionIntra > 2000, "Valid noise reduction range 0 - 2000");<br>
if (param->noiseReductionInter)<br>
CHECK(0 > param->noiseReductionInter || param->noiseReductionInter > 2000, "Valid noise reduction range 0 - 2000");<br>
- CHECK(param->rc.rateControlMode == X265_RC_CRF && param->rc.bStatRead,<br>
+ CHECK(param->rc.rateControlMode == X265_RC_CRF && param->rc.bStatRead && param->rc.vbvMaxBitrate == 0,<br>
"Constant rate-factor is incompatible with 2pass");<br>
CHECK(param->rc.rateControlMode == X265_RC_CQP && param->rc.bStatRead,<br>
"Constant QP is incompatible with 2pass");<br>
diff -r 6b308775b6f0 -r ffb0111298cd source/encoder/ratecontrol.cpp<br>
--- a/source/encoder/ratecontrol.cpp Mon Nov 23 12:26:45 2015 +0530<br>
+++ b/source/encoder/ratecontrol.cpp Mon Nov 23 14:06:10 2015 +0530<br>
@@ -142,6 +142,8 @@<br>
rce->expectedVbv = rce2Pass->expectedVbv;<br>
rce->blurredComplexity = rce2Pass->blurredComplexity;<br>
rce->sliceType = rce2Pass->sliceType;<br>
+ rce->qpNoVbv = rce2Pass->qpNoVbv;<br>
+ rce->newQp = rce2Pass->newQp;<br>
}<br>
<br>
} // end anonymous namespace<br>
@@ -205,7 +207,7 @@<br>
m_rateFactorMaxDecrement = m_param->rc.rfConstant - m_param->rc.rfConstantMin;<br>
}<br>
m_isAbr = m_param->rc.rateControlMode != X265_RC_CQP && !m_param->rc.bStatRead;<br>
- m_2pass = m_param->rc.rateControlMode == X265_RC_ABR && m_param->rc.bStatRead;<br>
+ m_2pass = (m_param->rc.rateControlMode == X265_RC_ABR || m_param->rc.vbvMaxBitrate > 0) && m_param->rc.bStatRead;<br>
m_bitrate = m_param->rc.bitrate * 1000;<br>
m_frameDuration = (double)m_param->fpsDenom / m_param->fpsNum;<br>
m_qp = m_param->rc.qp;<br>
@@ -488,6 +490,12 @@<br>
x265_log(m_param, X265_LOG_ERROR, "Rce Entries for 2 pass cannot be allocated\n");<br>
return false;<br>
}<br>
+ m_encOrder = X265_MALLOC(int, m_numEntries);<br>
+ if (!m_encOrder)<br>
+ {<br>
+ x265_log(m_param, X265_LOG_ERROR, "Encode order for 2 pass cannot be allocated\n");<br>
+ return false;<br>
+ }<br>
/* init all to skipped p frames */<br>
for (int i = 0; i < m_numEntries; i++)<br>
{<br>
@@ -504,6 +512,7 @@<br>
{<br>
RateControlEntry *rce;<br>
int frameNumber;<br>
+ int encodeOrder;<br>
char picType;<br>
int e;<br>
char *next;<br>
@@ -511,13 +520,14 @@<br>
next = strstr(p, ";");<br>
if (next)<br>
*next++ = 0;<br>
- e = sscanf(p, " in:%d ", &frameNumber);<br>
+ e = sscanf(p, " in:%d out:%d", &frameNumber, &encodeOrder);<br>
if (frameNumber < 0 || frameNumber >= m_numEntries)<br>
{<br>
x265_log(m_param, X265_LOG_ERROR, "bad frame number (%d) at stats line %d\n", frameNumber, i);<br>
return false;<br>
}<br>
- rce = &m_rce2Pass[frameNumber];<br>
+ rce = &m_rce2Pass[encodeOrder];<br>
+ m_encOrder[frameNumber] = encodeOrder;<br>
e += sscanf(p, " in:%*d out:%*d type:%c q:%lf q-aq:%lf q-noVbv:%lf tex:%d mv:%d misc:%d icu:%lf pcu:%lf scu:%lf",<br>
&picType, &qpRc, &qpAq, &qNoVbv, &rce->coeffBits,<br>
&rce->mvBits, &rce->miscBits, &rce->iCuCount, &rce->pCuCount,<br>
@@ -546,8 +556,7 @@<br>
p = next;<br>
}<br>
X265_FREE(statsBuf);<br>
-<br>
- if (m_param->rc.rateControlMode == X265_RC_ABR)<br>
+ if (m_param->rc.rateControlMode == X265_RC_ABR || m_param->rc.vbvMaxBitrate > 0)<br>
{<br>
if (!initPass2())<br>
return false;<br>
@@ -630,11 +639,8 @@<br>
<br>
#undef MAX_DURATION<br>
}<br>
-<br>
-bool RateControl::initPass2()<br>
+bool RateControl::analyseABR2Pass(int startIndex, int endIndex, uint64_t allAvailableBits)<br>
{<br>
- uint64_t allConstBits = 0;<br>
- uint64_t allAvailableBits = uint64_t(m_param->rc.bitrate * 1000. * m_numEntries * m_frameDuration);<br>
double rateFactor, stepMult;<br>
double qBlur = m_param->rc.qblur;<br>
double cplxBlur = m_param->rc.complexityBlur;<br>
@@ -643,30 +649,19 @@<br>
double *qScale, *blurredQscale;<br>
double baseCplx = m_ncu * (m_param->bframes ? 120 : 80);<br>
double clippedDuration = CLIP_DURATION(m_frameDuration) / BASE_FRAME_DURATION;<br>
-<br>
- /* find total/average complexity & const_bits */<br>
- for (int i = 0; i < m_numEntries; i++)<br>
- allConstBits += m_rce2Pass[i].miscBits;<br>
-<br>
- if (allAvailableBits < allConstBits)<br>
- {<br>
- x265_log(m_param, X265_LOG_ERROR, "requested bitrate is too low. estimated minimum is %d kbps\n",<br>
- (int)(allConstBits * m_fps / m_numEntries * 1000.));<br>
- return false;<br>
- }<br>
-<br>
+ int framesCount = endIndex - startIndex + 1;<br>
/* Blur complexities, to reduce local fluctuation of QP.<br>
* We don't blur the QPs directly, because then one very simple frame<br>
* could drag down the QP of a nearby complex frame and give it more<br>
* bits than intended. */<br>
- for (int i = 0; i < m_numEntries; i++)<br>
+ for (int i = startIndex; i <= endIndex; i++)<br>
{<br>
double weightSum = 0;<br>
double cplxSum = 0;<br>
double weight = 1.0;<br>
double gaussianWeight;<br>
/* weighted average of cplx of future frames */<br>
- for (int j = 1; j < cplxBlur * 2 && j < m_numEntries - i; j++)<br>
+ for (int j = 1; j < cplxBlur * 2 && j <= endIndex - i; j++)<br>
{<br>
RateControlEntry *rcj = &m_rce2Pass[i + j];<br>
weight *= 1 - pow(rcj->iCuCount / m_ncu, 2);<br>
@@ -690,11 +685,10 @@<br>
}<br>
m_rce2Pass[i].blurredComplexity = cplxSum / weightSum;<br>
}<br>
-<br>
- CHECKED_MALLOC(qScale, double, m_numEntries);<br>
+ CHECKED_MALLOC(qScale, double, framesCount);<br>
if (filterSize > 1)<br>
{<br>
- CHECKED_MALLOC(blurredQscale, double, m_numEntries);<br>
+ CHECKED_MALLOC(blurredQscale, double, framesCount);<br>
}<br>
else<br>
blurredQscale = qScale;<br>
@@ -705,9 +699,8 @@<br>
* because qscale2bits is not invertible, but we can start with the simple<br>
* approximation of scaling the 1st pass by the ratio of bitrates.<br>
* The search range is probably overkill, but speed doesn't matter here. */<br>
-<br>
expectedBits = 1;<br>
- for (int i = 0; i < m_numEntries; i++)<br>
+ for (int i = startIndex; i <= endIndex; i++)<br>
{<br>
RateControlEntry* rce = &m_rce2Pass[i];<br>
double q = getQScale(rce, 1.0);<br>
@@ -784,12 +777,10 @@<br>
X265_FREE(qScale);<br>
if (filterSize > 1)<br>
X265_FREE(blurredQscale);<br>
-<br>
if (m_isVbv)<br>
- if (!vbv2Pass(allAvailableBits))<br>
+ if (!vbv2Pass(allAvailableBits, endIndex, startIndex))<br>
return false;<br>
- expectedBits = countExpectedBits();<br>
-<br>
+ expectedBits = countExpectedBits(startIndex, endIndex);<br>
if (fabs(expectedBits / allAvailableBits - 1.0) > 0.01)<br>
{<br>
double avgq = 0;<br>
@@ -822,7 +813,127 @@<br>
return false;<br>
}<br>
<br>
-bool RateControl::vbv2Pass(uint64_t allAvailableBits)<br>
+bool RateControl::initPass2()<br>
+{<br>
+ uint64_t allConstBits = 0, allCodedBits = 0;<br>
+ uint64_t allAvailableBits = uint64_t(m_param->rc.bitrate * 1000. * m_numEntries * m_frameDuration);<br>
+ int startIndex, framesCount, endIndex, cnt;<br>
+ int fps = (int)(m_fps + 0.5);<br>
+ startIndex = endIndex = framesCount = 0;<br>
+ allAvailableBits = uint64_t(m_param->rc.vbvMaxBitrate * 1000. * m_numEntries * m_frameDuration);<br>
+ bool isQpModified = true;<br>
+ int diffQp = 0;<br>
+ int64_t targetBits = 0;<br>
+ int64_t expectedBits = 0;<br>
+ for (startIndex = 0, endIndex = 0; endIndex < m_numEntries; endIndex++)<br>
+ {<br>
+ allConstBits += m_rce2Pass[endIndex].miscBits;<br>
+ allCodedBits += m_rce2Pass[endIndex].coeffBits + m_rce2Pass[endIndex].mvBits;<br>
+ if (m_param->rc.rateControlMode == X265_RC_CRF)<br>
+ {<br>
+ framesCount = endIndex - startIndex + 1;<br>
+ if (m_rce2Pass[endIndex].newQScale < 0)<br>
+ m_rce2Pass[endIndex].newQScale = m_rce2Pass[endIndex].qScale;<br>
+ diffQp += int (m_rce2Pass[endIndex].qpaRc - m_rce2Pass[endIndex].qpNoVbv);<br>
+ if (framesCount > fps)<br>
+ diffQp -= int (m_rce2Pass[endIndex - fps].qpaRc - m_rce2Pass[endIndex - fps].qpNoVbv);<br>
+ if (framesCount >= fps)<br>
+ {<br>
+ if (diffQp >= 1)<br>
+ {<br>
+ if (!isQpModified && endIndex > fps)<br>
+ {<br>
+ double factor = 2;<br>
+ double step = 0;<br>
+ for (int start = endIndex; start <= endIndex + fps - 1 && start < m_numEntries; start++)<br>
+ {<br>
+ RateControlEntry *rce = &m_rce2Pass[start];<br>
+ targetBits += qScale2bits(rce, x265_qp2qScale(rce->qpNoVbv));<br>
+ expectedBits += qScale2bits(rce, rce->qScale);<br>
+ }<br>
+ if (expectedBits < 0.95 * targetBits)<br>
+ {<br>
+ isQpModified = true;<br>
+ while (endIndex + fps < m_numEntries)<br>
+ {<br>
+ step = pow(2, factor / 6.0);<br>
+ expectedBits = 0;<br>
+ for (int start = endIndex; start <= endIndex + fps - 1; start++)<br>
+ {<br>
+ RateControlEntry *rce = &m_rce2Pass[start];<br>
+ rce->newQScale = rce->qScale / step;<br>
+ X265_CHECK(rce->newQScale >= 0, "new Qscale is negative\n");<br>
+ expectedBits += qScale2bits(rce, rce->newQScale);<br>
+ rce->newQp = x265_qScale2qp(rce->newQScale);<br>
+ }<br>
+ if (expectedBits >= targetBits && step > 1)<br>
+ factor *= 0.90;<br>
+ else<br>
+ break;<br>
+ }<br>
+<br>
+ if (m_isVbv && endIndex + fps < m_numEntries)<br>
+ if (!vbv2Pass(targetBits, endIndex + fps - 1, endIndex))<br>
+ return false;<br>
+<br>
+ double prevFactor = factor;<br>
+ targetBits = 0;<br>
+ expectedBits = 0;<br>
+<br>
+ for (int start = endIndex - fps; start <= endIndex - 1; start++)<br>
+ {<br>
+ RateControlEntry *rce = &m_rce2Pass[start];<br>
+ targetBits += qScale2bits(rce, x265_qp2qScale(rce->qpNoVbv));<br>
+ }<br>
+ while (1)<br>
+ {<br>
+ step = pow(2, factor / 6.0);<br>
+ expectedBits = 0;<br>
+ for (int start = endIndex - fps; start <= endIndex - 1; start++)<br>
+ {<br>
+ RateControlEntry *rce = &m_rce2Pass[start];<br>
+ rce->newQScale = rce->qScale * step;<br>
+ X265_CHECK(rce->newQScale >= 0, "new Qscale is negative\n");<br>
+ expectedBits += qScale2bits(rce, rce->newQScale);<br>
+ rce->newQp = x265_qScale2qp(rce->newQScale);<br>
+ }<br>
+ if (expectedBits > targetBits && step > 1)<br>
+ factor *= 1.1;<br>
+ else<br>
+ break;<br>
+ }<br>
+ if (m_isVbv)<br>
+ if (!vbv2Pass(targetBits, endIndex - 1, endIndex - fps))<br>
+ return false;<br>
+ diffQp = 0;<br>
+ startIndex = endIndex + 1;<br>
+ targetBits = expectedBits = 0;<br>
+ }<br>
+ else<br>
+ targetBits = expectedBits = 0;<br>
+ }<br>
+ }<br>
+ else<br>
+ isQpModified = false;<br>
+ }<br>
+ }<br>
+ }<br>
+<br>
+ if (m_param->rc.rateControlMode == X265_RC_ABR)<br>
+ {<br>
+ if (allAvailableBits < allConstBits)<br>
+ {<br>
+ x265_log(m_param, X265_LOG_ERROR, "requested bitrate is too low. estimated minimum is %d kbps\n",<br>
+ (int)(allConstBits * m_fps / framesCount * 1000.));<br>
+ return false;<br>
+ }<br>
+ if (!analyseABR2Pass(0, m_numEntries - 1, allAvailableBits))<br>
+ return false;<br>
+ }<br>
+ return true;<br>
+}<br>
+<br>
+bool RateControl::vbv2Pass(uint64_t allAvailableBits, int endPos, int startPos)<br>
{<br>
/* for each interval of bufferFull .. underflow, uniformly increase the qp of all<br>
* frames in the interval until either buffer is full at some intermediate frame or the<br>
@@ -848,10 +959,10 @@<br>
{ /* not first iteration */<br>
adjustment = X265_MAX(X265_MIN(expectedBits / allAvailableBits, 0.999), 0.9);<br>
fills[-1] = m_bufferSize * m_param->rc.vbvBufferInit;<br>
- t0 = 0;<br>
+ t0 = startPos;<br>
/* fix overflows */<br>
adjMin = 1;<br>
- while (adjMin && findUnderflow(fills, &t0, &t1, 1))<br>
+ while (adjMin && findUnderflow(fills, &t0, &t1, 1, endPos))<br>
{<br>
adjMin = fixUnderflow(t0, t1, adjustment, MIN_QPSCALE, MAX_MAX_QPSCALE);<br>
t0 = t1;<br>
@@ -862,20 +973,16 @@<br>
t0 = 0;<br>
/* fix underflows -- should be done after overflow, as we'd better undersize target than underflowing VBV */<br>
adjMax = 1;<br>
- while (adjMax && findUnderflow(fills, &t0, &t1, 0))<br>
+ while (adjMax && findUnderflow(fills, &t0, &t1, 0, endPos))<br>
adjMax = fixUnderflow(t0, t1, 1.001, MIN_QPSCALE, MAX_MAX_QPSCALE );<br>
-<br>
- expectedBits = countExpectedBits();<br>
+ expectedBits = countExpectedBits(startPos, endPos);<br>
}<br>
- while ((expectedBits < .995 * allAvailableBits) && ((int64_t)(expectedBits+.5) > (int64_t)(prevBits+.5)));<br>
-<br>
+ while ((expectedBits < .995 * allAvailableBits) && ((int64_t)(expectedBits+.5) > (int64_t)(prevBits+.5)) && !(m_param->rc.rateControlMode == X265_RC_CRF));<br>
if (!adjMax)<br>
x265_log(m_param, X265_LOG_WARNING, "vbv-maxrate issue, qpmax or vbv-maxrate too low\n");<br>
-<br>
/* store expected vbv filling values for tracking when encoding */<br>
- for (int i = 0; i < m_numEntries; i++)<br>
+ for (int i = startPos; i <= endPos; i++)<br>
m_rce2Pass[i].expectedVbv = m_bufferSize - fills[i];<br>
-<br>
X265_FREE(fills - 1);<br>
return true;<br>
<br>
@@ -915,9 +1022,10 @@<br>
m_param->bframes = 1;<br>
return X265_TYPE_AUTO;<br>
}<br>
- int frameType = m_rce2Pass[frameNum].sliceType == I_SLICE ? (frameNum > 0 && m_param->bOpenGOP ? X265_TYPE_I : X265_TYPE_IDR)<br>
- : m_rce2Pass[frameNum].sliceType == P_SLICE ? X265_TYPE_P<br>
- : (m_rce2Pass[frameNum].sliceType == B_SLICE && m_rce2Pass[frameNum].keptAsRef? X265_TYPE_BREF : X265_TYPE_B);<br>
+ int index = m_encOrder[frameNum];<br>
+ int frameType = m_rce2Pass[index].sliceType == I_SLICE ? (frameNum > 0 && m_param->bOpenGOP ? X265_TYPE_I : X265_TYPE_IDR)<br>
+ : m_rce2Pass[index].sliceType == P_SLICE ? X265_TYPE_P<br>
+ : (m_rce2Pass[index].sliceType == B_SLICE && m_rce2Pass[index].keptAsRef ? X265_TYPE_BREF : X265_TYPE_B);<br>
return frameType;<br>
}<br>
else<br>
@@ -968,7 +1076,8 @@<br>
if (m_param->rc.bStatRead)<br>
{<br>
X265_CHECK(rce->poc >= 0 && rce->poc < m_numEntries, "bad encode ordinal\n");<br>
- copyRceData(rce, &m_rce2Pass[rce->poc]);<br>
+ int index = m_encOrder[rce->poc];<br>
+ copyRceData(rce, &m_rce2Pass[index]);<br>
}<br>
rce->isActive = true;<br>
bool isRefFrameScenecut = m_sliceType!= I_SLICE && m_curSlice->m_refPicList[0][0]->m_lowres.bScenecut == 1;<br>
@@ -1032,6 +1141,16 @@<br>
}<br>
}<br>
}<br>
+ if (!m_isAbr && m_2pass && m_param->rc.rateControlMode == X265_RC_CRF)<br>
+ {<br>
+ rce->qScale = rce->newQScale;<br>
+ rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = x265_qScale2qp(rce->newQScale);<br>
+ m_qp = int(rce->qpaRc + 0.5);<br>
+ rce->frameSizePlanned = qScale2bits(rce, rce->qScale);<br>
+ m_framesDone++;<br>
+ return m_qp;<br>
+ }<br>
+<br>
if (m_isAbr || m_2pass) // ABR,CRF<br>
{<br>
if (m_isAbr || m_isVbv)<br>
@@ -1203,11 +1322,10 @@<br>
}<br>
return q;<br>
}<br>
-<br>
-double RateControl::countExpectedBits()<br>
+double RateControl::countExpectedBits(int startPos, int endPos)<br>
{<br>
double expectedBits = 0;<br>
- for( int i = 0; i < m_numEntries; i++ )<br>
+ for (int i = startPos; i <= endPos; i++)<br>
{<br>
RateControlEntry *rce = &m_rce2Pass[i];<br>
rce->expectedBits = (uint64_t)expectedBits;<br>
@@ -1215,8 +1333,7 @@<br>
}<br>
return expectedBits;<br>
}<br>
-<br>
-bool RateControl::findUnderflow(double *fills, int *t0, int *t1, int over)<br>
+bool RateControl::findUnderflow(double *fills, int *t0, int *t1, int over, int endPos)<br>
{<br>
/* find an interval ending on an overflow or underflow (depending on whether<br>
* we're adding or removing bits), and starting on the earliest frame that<br>
@@ -1226,7 +1343,7 @@<br>
double fill = fills[*t0 - 1];<br>
double parity = over ? 1. : -1.;<br>
int start = -1, end = -1;<br>
- for (int i = *t0; i < m_numEntries; i++)<br>
+ for (int i = *t0; i <= endPos; i++)<br>
{<br>
fill += (m_frameDuration * m_vbvMaxRate -<br>
qScale2bits(&m_rce2Pass[i], m_rce2Pass[i].newQScale)) * parity;<br>
@@ -1263,12 +1380,11 @@<br>
}<br>
return adjusted;<br>
}<br>
-<br>
bool RateControl::cuTreeReadFor2Pass(Frame* frame)<br>
{<br>
- uint8_t sliceTypeActual = (uint8_t)m_rce2Pass[frame->m_poc].sliceType;<br>
-<br>
- if (m_rce2Pass[frame->m_poc].keptAsRef)<br>
+ int index = m_encOrder[frame->m_poc];<br>
+ uint8_t sliceTypeActual = (uint8_t)m_rce2Pass[index].sliceType;<br>
+ if (m_rce2Pass[index].keptAsRef)<br>
{<br>
/* TODO: We don't need pre-lookahead to measure AQ offsets, but there is currently<br>
* no way to signal this */<br>
@@ -1948,6 +2064,8 @@<br>
<br>
int RateControl::rowDiagonalVbvRateControl(Frame* curFrame, uint32_t row, RateControlEntry* rce, double& qpVbv)<br>
{<br>
+ if (m_param->rc.bStatRead && m_param->rc.rateControlMode == X265_RC_CRF)<br>
+ return 0;<br>
FrameData& curEncData = *curFrame->m_encData;<br>
double qScaleVbv = x265_qp2qScale(qpVbv);<br>
uint64_t rowSatdCost = curEncData.m_rowStat[row].diagSatd;<br>
@@ -2195,7 +2313,7 @@<br>
<br>
if (m_param->rc.aqMode || m_isVbv)<br>
{<br>
- if (m_isVbv)<br>
+ if (m_isVbv && !(m_2pass && m_param->rc.rateControlMode == X265_RC_CRF))<br>
{<br>
/* determine avg QP decided by VBV rate control */<br>
for (uint32_t i = 0; i < slice->m_sps->numCuInHeight; i++)<br>
diff -r 6b308775b6f0 -r ffb0111298cd source/encoder/ratecontrol.h<br>
--- a/source/encoder/ratecontrol.h Mon Nov 23 12:26:45 2015 +0530<br>
+++ b/source/encoder/ratecontrol.h Mon Nov 23 14:06:10 2015 +0530<br>
@@ -205,8 +205,8 @@<br>
double m_lastAccumPNorm;<br>
double m_expectedBitsSum; /* sum of qscale2bits after rceq, ratefactor, and overflow, only includes finished frames */<br>
int64_t m_predictedBits;<br>
+ int *m_encOrder;<br>
RateControlEntry* m_rce2Pass;<br>
-<br>
struct<br>
{<br>
uint16_t *qpBuffer[2]; /* Global buffers for converting MB-tree quantizer data. */<br>
@@ -258,11 +258,12 @@<br>
void checkAndResetABR(RateControlEntry* rce, bool isFrameDone);<br>
double predictRowsSizeSum(Frame* pic, RateControlEntry* rce, double qpm, int32_t& encodedBits);<br>
bool initPass2();<br>
+ bool analyseABR2Pass(int startPoc, int endPoc, uint64_t allAvailableBits);<br>
void initFramePredictors();<br>
double getDiffLimitedQScale(RateControlEntry *rce, double q);<br>
- double countExpectedBits();<br>
- bool vbv2Pass(uint64_t allAvailableBits);<br>
- bool findUnderflow(double *fills, int *t0, int *t1, int over);<br>
+ double countExpectedBits(int startPos, int framesCount);<br>
+ bool vbv2Pass(uint64_t allAvailableBits, int frameCount, int startPos);<br>
+ bool findUnderflow(double *fills, int *t0, int *t1, int over, int framesCount);<br>
bool fixUnderflow(int t0, int t1, double adjustment, double qscaleMin, double qscaleMax);<br>
};<br>
}<br>
</blockquote></div><br></div>