X-Git-Url: https://git.piment-noir.org/?p=deb_x265.git;a=blobdiff_plain;f=source%2Fencoder%2Fratecontrol.cpp;h=4f31fe18d31e1dd2ff250524a610f207edf8bf11;hp=f54b1015c4c01af94d7cd30732e1c33d71bb27da;hb=b53f7c52d8280ab63876efd6eb292c21430ac607;hpb=5c9b45285dd64723ad1dac380b98a7b1f3095674 diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp index f54b101..4f31fe1 100644 --- a/source/encoder/ratecontrol.cpp +++ b/source/encoder/ratecontrol.cpp @@ -40,8 +40,7 @@ using namespace x265; /* Amortize the partial cost of I frames over the next N frames */ -const double RateControl::s_amortizeFraction = 0.85; -const int RateControl::s_amortizeFrames = 75; + const int RateControl::s_slidingWindowFrames = 20; const char *RateControl::s_defaultStatFileName = "x265_2pass.log"; @@ -173,8 +172,8 @@ static inline uint32_t acEnergyPlane(Frame *curFrame, pixel* src, intptr_t srcSt /* Find the total AC energy of each block in all planes */ uint32_t RateControl::acEnergyCu(Frame* curFrame, uint32_t block_x, uint32_t block_y) { - intptr_t stride = curFrame->m_origPicYuv->m_stride; - intptr_t cStride = curFrame->m_origPicYuv->m_strideC; + intptr_t stride = curFrame->m_fencPic->m_stride; + intptr_t cStride = curFrame->m_fencPic->m_strideC; intptr_t blockOffsetLuma = block_x + (block_y * stride); int colorFormat = m_param->internalCsp; int hShift = CHROMA_H_SHIFT(colorFormat); @@ -183,9 +182,9 @@ uint32_t RateControl::acEnergyCu(Frame* curFrame, uint32_t block_x, uint32_t blo uint32_t var; - var = acEnergyPlane(curFrame, curFrame->m_origPicYuv->m_picOrg[0] + blockOffsetLuma, stride, 0, colorFormat); - var += acEnergyPlane(curFrame, curFrame->m_origPicYuv->m_picOrg[1] + blockOffsetChroma, cStride, 1, colorFormat); - var += acEnergyPlane(curFrame, curFrame->m_origPicYuv->m_picOrg[2] + blockOffsetChroma, cStride, 2, colorFormat); + var = acEnergyPlane(curFrame, curFrame->m_fencPic->m_picOrg[0] + blockOffsetLuma, stride, 0, colorFormat); + var += acEnergyPlane(curFrame, curFrame->m_fencPic->m_picOrg[1] + blockOffsetChroma, cStride, 1, colorFormat); + var += acEnergyPlane(curFrame, curFrame->m_fencPic->m_picOrg[2] + blockOffsetChroma, cStride, 2, colorFormat); x265_emms(); return var; } @@ -193,8 +192,8 @@ uint32_t RateControl::acEnergyCu(Frame* curFrame, uint32_t block_x, uint32_t blo void RateControl::calcAdaptiveQuantFrame(Frame *curFrame) { /* Actual adaptive quantization */ - int maxCol = curFrame->m_origPicYuv->m_picWidth; - int maxRow = curFrame->m_origPicYuv->m_picHeight; + int maxCol = curFrame->m_fencPic->m_picWidth; + int maxRow = curFrame->m_fencPic->m_picHeight; for (int y = 0; y < 3; y++) { @@ -323,6 +322,12 @@ RateControl::RateControl(x265_param *p) m_bTerminated = false; m_finalFrameCount = 0; m_numEntries = 0; + m_amortizeFraction = 0.85; + m_amortizeFrames = 75; + if (m_param->totalFrames <= 2 * m_fps) + { + m_amortizeFraction = m_amortizeFrames = 0; + } if (m_param->rc.rateControlMode == X265_RC_CRF) { m_param->rc.qp = (int)m_param->rc.rfConstant; @@ -494,12 +499,12 @@ bool RateControl::init(const SPS *sps) /* Frame Predictors and Row predictors used in vbv */ for (int i = 0; i < 5; i++) { - m_pred[i].coeff = 2.0; + m_pred[i].coeff = 1.5; m_pred[i].count = 1.0; m_pred[i].decay = 0.5; m_pred[i].offset = 0.0; } - m_predBfromP = m_pred[0]; + m_pred[0].coeff = 1.0; if (!m_statFileOut && (m_param->rc.bStatWrite || m_param->rc.bStatRead)) { /* If the user hasn't defined the stat filename, use the default value */ @@ -1157,7 +1162,7 @@ int RateControl::rateControlStart(Frame* curFrame, RateControlEntry* rce, Encode rce->leadingNoBSatd = m_leadingNoBSatd; if (curFrame->m_forceqp) { - m_qp = int32_t(curFrame->m_forceqp + 0.5) - 1; + m_qp = (int32_t)(curFrame->m_forceqp + 0.5) - 1; m_qp = Clip3(QP_MIN, QP_MAX_MAX, m_qp); rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = m_qp; } @@ -1343,6 +1348,25 @@ fail: return false; } +double RateControl::tuneAbrQScaleFromFeedback(double qScale) +{ + double abrBuffer = 2 * m_param->rc.rateTolerance * m_bitrate; + if (m_currentSatd) + { + /* use framesDone instead of POC as poc count is not serial with bframes enabled */ + double overflow = 1.0; + double timeDone = (double)(m_framesDone - m_param->frameNumThreads + 1) * m_frameDuration; + double wantedBits = timeDone * m_bitrate; + if (wantedBits > 0 && m_totalBits > 0 && !m_partialResidualFrames) + { + abrBuffer *= X265_MAX(1, sqrt(timeDone)); + overflow = Clip3(.5, 2.0, 1.0 + (m_totalBits - wantedBits) / abrBuffer); + qScale *= overflow; + } + } + return qScale; +} + double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce) { double q; @@ -1415,17 +1439,25 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce) q += m_pbOffset / 2; else q += m_pbOffset; - rce->qpNoVbv = q; - double qScale = x265_qp2qScale(q); - if (!m_2pass && m_isVbv) + double qScale = x265_qp2qScale(q); + if (m_isCbr) { - if (m_leadingBframes > 5) + qScale = tuneAbrQScaleFromFeedback(qScale); + if (!m_isAbrReset) { - qScale = clipQscale(curFrame, rce, qScale); - m_lastQScaleFor[m_sliceType] = qScale; + double lmin = m_lastQScaleFor[P_SLICE] / m_lstep; + double lmax = m_lastQScaleFor[P_SLICE] * m_lstep; + qScale = Clip3(lmin, lmax, qScale); } - rce->frameSizePlanned = predictSize(&m_predBfromP, qScale, (double)m_leadingNoBSatd); + q = x265_qScale2qp(qScale); + } + rce->qpNoVbv = q; + if (!m_2pass && m_isVbv) + { + qScale = clipQscale(curFrame, rce, qScale); + m_lastQScaleFor[m_sliceType] = qScale; + rce->frameSizePlanned = predictSize(&m_pred[m_sliceType], qScale, (double)m_currentSatd); } else if (m_2pass && m_isVbv) { @@ -1508,7 +1540,7 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce) * tradeoff between quality and bitrate precision. But at large * tolerances, the bit distribution approaches that of 2pass. */ - double wantedBits, overflow = 1; + double overflow = 1; m_shortTermCplxSum *= 0.5; m_shortTermCplxCount *= 0.5; @@ -1528,25 +1560,10 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce) { if (!m_param->rc.bStatRead) checkAndResetABR(rce, false); - q = getQScale(rce, m_wantedBitsWindow / m_cplxrSum); - - /* ABR code can potentially be counterproductive in CBR, so just - * don't bother. Don't run it if the frame complexity is zero - * either. */ - if (!m_isCbr && m_currentSatd) - { - /* use framesDone instead of POC as poc count is not serial with bframes enabled */ - double timeDone = (double)(m_framesDone - m_param->frameNumThreads + 1) * m_frameDuration; - wantedBits = timeDone * m_bitrate; - if (wantedBits > 0 && m_totalBits > 0 && !m_partialResidualFrames) - { - abrBuffer *= X265_MAX(1, sqrt(timeDone)); - overflow = Clip3(.5, 2.0, 1.0 + (m_totalBits - wantedBits) / abrBuffer); - q *= overflow; - } - } + double initialQScale = getQScale(rce, m_wantedBitsWindow / m_cplxrSum); + q = tuneAbrQScaleFromFeedback(initialQScale); + overflow = q / initialQScale; } - if (m_sliceType == I_SLICE && m_param->keyframeMax > 1 && m_lastNonBPictType != I_SLICE && !m_isAbrReset) { @@ -1574,7 +1591,7 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce) { q = x265_qp2qScale(CRF_INIT_QP) / fabs(m_param->rc.ipFactor); } - else if (m_framesDone == 0 && !m_isVbv) + else if (m_framesDone == 0 && !m_isVbv && m_param->rc.rateControlMode == X265_RC_ABR) { /* for ABR alone, clip the first I frame qp */ double lqmax = x265_qp2qScale(ABR_INIT_QP_MAX) * m_lstep; @@ -1615,8 +1632,8 @@ void RateControl::rateControlUpdateStats(RateControlEntry* rce) if (m_partialResidualFrames) rce->rowTotalBits += m_partialResidualCost * m_partialResidualFrames; - m_partialResidualFrames = X265_MIN(s_amortizeFrames, m_param->keyframeMax); - m_partialResidualCost = (int)((rce->rowTotalBits * s_amortizeFraction) /m_partialResidualFrames); + m_partialResidualFrames = X265_MIN(m_amortizeFrames, m_param->keyframeMax); + m_partialResidualCost = (int)((rce->rowTotalBits * m_amortizeFraction) /m_partialResidualFrames); rce->rowTotalBits -= m_partialResidualCost * m_partialResidualFrames; } else if (m_partialResidualFrames) @@ -1725,13 +1742,11 @@ double RateControl::clipQscale(Frame* curFrame, RateControlEntry* rce, double q) { double frameQ[3]; double curBits; - if (m_sliceType == B_SLICE) - curBits = predictSize(&m_predBfromP, q, (double)m_currentSatd); - else - curBits = predictSize(&m_pred[m_sliceType], q, (double)m_currentSatd); + curBits = predictSize(&m_pred[m_sliceType], q, (double)m_currentSatd); double bufferFillCur = m_bufferFill - curBits; double targetFill; - double totalDuration = 0; + double totalDuration = m_frameDuration; + bool isIFramePresent = m_sliceType == I_SLICE ? true : false; frameQ[P_SLICE] = m_sliceType == I_SLICE ? q * m_param->rc.ipFactor : (m_sliceType == B_SLICE ? q / m_param->rc.pbFactor : q); frameQ[B_SLICE] = frameQ[P_SLICE] * m_param->rc.pbFactor; frameQ[I_SLICE] = frameQ[P_SLICE] / m_param->rc.ipFactor; @@ -1747,20 +1762,23 @@ double RateControl::clipQscale(Frame* curFrame, RateControlEntry* rce, double q) bufferFillCur += wantedFrameSize; int64_t satd = curFrame->m_lowres.plannedSatd[j] >> (X265_DEPTH - 8); type = IS_X265_TYPE_I(type) ? I_SLICE : IS_X265_TYPE_B(type) ? B_SLICE : P_SLICE; + if (type == I_SLICE) + isIFramePresent = true; curBits = predictSize(&m_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(m_bufferFill + totalDuration * m_vbvMaxRate * 0.5, m_bufferSize * 0.5); + /* Try to get the buffer no more than 80% filled, but don't set an impossible goal. */ + double tol = isIFramePresent ? 1 / totalDuration : totalDuration < 0.5 ? 2 : 1; + targetFill = X265_MIN(m_bufferFill + totalDuration * m_vbvMaxRate * 0.5 , m_bufferSize * (1 - 0.8 * totalDuration * tol)); if (bufferFillCur < targetFill) { q *= 1.01; loopTerminate |= 1; continue; } - /* Try to get the buffer no more than 80% filled, but don't set an impossible goal. */ - targetFill = Clip3(m_bufferSize * 0.8, m_bufferSize, m_bufferFill - totalDuration * m_vbvMaxRate * 0.5); + /* Try to get the buffer atleast 50% filled, but don't set an impossible goal. */ + targetFill = Clip3(m_bufferSize - (m_bufferSize * totalDuration * 0.5), m_bufferSize, m_bufferFill - totalDuration * m_vbvMaxRate * 0.5); if (m_isCbr && bufferFillCur > targetFill) { q /= 1.01; @@ -1810,25 +1828,6 @@ double RateControl::clipQscale(Frame* curFrame, RateControlEntry* rce, double q) if (pbits > rce->frameSizeMaximum) q *= pbits / rce->frameSizeMaximum; - // Check B-frame complexity, and use up any bits that would - // overflow before the next P-frame. - if (m_leadingBframes <= 5 && m_sliceType == P_SLICE && !m_singleFrameVbv) - { - int nb = m_leadingBframes; - double bits = predictSize(&m_pred[m_sliceType], q, (double)m_currentSatd); - double bbits = predictSize(&m_predBfromP, q * m_param->rc.pbFactor, (double)m_currentSatd); - double space; - if (bbits > m_bufferRate) - nb = 0; - double pbbits = nb * bbits; - - space = m_bufferFill + (1 + nb) * m_bufferRate - m_bufferSize; - if (pbbits < space) - q *= X265_MAX(pbbits / space, bits / (0.5 * m_bufferSize)); - - q = X265_MAX(q0 / 2, q); - } - if (!m_isCbr || (m_isAbr && m_currentSatd >= rce->movingAvgSum && q <= q0 / 2)) q = X265_MAX(q0, q); @@ -1899,22 +1898,24 @@ double RateControl::predictRowsSizeSum(Frame* curFrame, RateControlEntry* rce, d && refQScale > 0 && refRowSatdCost > 0) { - if (abs(int32_t(refRowSatdCost - satdCostForPendingCus)) < (int32_t)satdCostForPendingCus / 2) + if (abs((int32_t)(refRowSatdCost - satdCostForPendingCus)) < (int32_t)satdCostForPendingCus / 2) { double predTotal = refRowBits * satdCostForPendingCus / refRowSatdCost * refQScale / qScale; - totalSatdBits += int32_t((pred_s + predTotal) * 0.5); + totalSatdBits += (int32_t)((pred_s + predTotal) * 0.5); continue; } } - totalSatdBits += int32_t(pred_s); + totalSatdBits += (int32_t)pred_s; } - else + else if (picType == P_SLICE) { /* Our QP is lower than the reference! */ double pred_intra = predictSize(rce->rowPred[1], qScale, intraCost); /* Sum: better to overestimate than underestimate by using only one of the two predictors. */ - totalSatdBits += int32_t(pred_intra + pred_s); + totalSatdBits += (int32_t)(pred_intra + pred_s); } + else + totalSatdBits += (int32_t)pred_s; } } @@ -1969,16 +1970,8 @@ int RateControl::rowDiagonalVbvRateControl(Frame* curFrame, uint32_t row, RateCo if (row < sps.numCuInHeight - 1) { - /* B-frames shouldn't use lower QP than their reference frames. */ - if (rce->sliceType == B_SLICE) - { - Frame* refSlice1 = curEncData.m_slice->m_refPicList[0][0]; - Frame* refSlice2 = curEncData.m_slice->m_refPicList[1][0]; - qpMin = X265_MAX(qpMin, X265_MAX(refSlice1->m_encData->m_rowStat[row].diagQp, refSlice2->m_encData->m_rowStat[row].diagQp)); - qpVbv = X265_MAX(qpVbv, qpMin); - } /* More threads means we have to be more cautious in letting ratecontrol use up extra bits. */ - double rcTol = bufferLeftPlanned / m_param->frameNumThreads * m_param->rc.rateTolerance; + double rcTol = (bufferLeftPlanned * 0.2) / m_param->frameNumThreads * m_param->rc.rateTolerance; int32_t encodedBitsSoFar = 0; double accFrameBits = predictRowsSizeSum(curFrame, rce, qpVbv, encodedBitsSoFar); @@ -1996,7 +1989,7 @@ int RateControl::rowDiagonalVbvRateControl(Frame* curFrame, uint32_t row, RateCo while (qpVbv < qpMax && ((accFrameBits > rce->frameSizePlanned + rcTol) || - (rce->bufferFill - accFrameBits < bufferLeftPlanned * 0.5) || + (rce->bufferFill - accFrameBits < bufferLeftPlanned * 0.2) || (accFrameBits > rce->frameSizePlanned && qpVbv < rce->qpNoVbv))) { qpVbv += stepSize; @@ -2085,7 +2078,7 @@ void RateControl::updatePredictor(Predictor *p, double q, double var, double bit { if (var < 10) return; - const double range = 1.5; + const double range = 2; double old_coeff = p->coeff / p->count; double new_coeff = bits * q / var; double new_coeff_clipped = Clip3(old_coeff / range, old_coeff * range, new_coeff); @@ -2220,8 +2213,8 @@ int RateControl::rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry* /* previous I still had a residual; roll it into the new loan */ if (m_residualFrames) bits += m_residualCost * m_residualFrames; - m_residualFrames = X265_MIN(s_amortizeFrames, m_param->keyframeMax); - m_residualCost = (int)((bits * s_amortizeFraction) / m_residualFrames); + m_residualFrames = X265_MIN(m_amortizeFrames, m_param->keyframeMax); + m_residualCost = (int)((bits * m_amortizeFraction) / m_residualFrames); bits -= m_residualCost * m_residualFrames; } else if (m_residualFrames) @@ -2257,16 +2250,6 @@ int RateControl::rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry* if (m_isVbv) { - if (rce->sliceType == B_SLICE) - { - m_bframeBits += actualBits; - if (rce->bLastMiniGopBFrame) - { - if (rce->bframes != 0) - updatePredictor(&m_predBfromP, x265_qp2qScale(rce->qpaRc), (double)rce->leadingNoBSatd, (double)m_bframeBits / rce->bframes); - m_bframeBits = 0; - } - } updateVbv(actualBits, rce); if (m_param->bEmitHRDSEI)