>From 5065d31b4bfe36e05c94dd79db119cd1fd23aa23 Mon Sep 17 00:00:00 2001 From: lwWang <li...@multicorewareinc.com> Date: Fri, 25 Jun 2021 17:17:03 +0800 Subject: [PATCH] Modify the crf 2 pass
Signed-off-by: lwWang <li...@multicorewareinc.com> --- source/common/frame.h | 1 + source/encoder/encoder.cpp | 1 + source/encoder/ratecontrol.cpp | 235 ++++++++++++++++----------------- source/encoder/ratecontrol.h | 3 + 4 files changed, 119 insertions(+), 121 deletions(-) diff --git a/source/common/frame.h b/source/common/frame.h index dc5bbacf7..ac1185e81 100644 --- a/source/common/frame.h +++ b/source/common/frame.h @@ -70,6 +70,7 @@ struct RcStats double count[4]; double offset[4]; double bufferFillFinal; + int64_t currentSatd; }; class Frame diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp index 003011554..227933e8a 100644 --- a/source/encoder/encoder.cpp +++ b/source/encoder/encoder.cpp @@ -2216,6 +2216,7 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out) outFrame->m_rcData->iCuCount = outFrame->m_encData->m_frameStats.percent8x8Intra * m_rateControl->m_ncu; outFrame->m_rcData->pCuCount = outFrame->m_encData->m_frameStats.percent8x8Inter * m_rateControl->m_ncu; outFrame->m_rcData->skipCuCount = outFrame->m_encData->m_frameStats.percent8x8Skip * m_rateControl->m_ncu; + outFrame->m_rcData->currentSatd = curEncoder->m_rce.coeffBits; } /* Allow this frame to be recycled if no frame encoders are using it for reference */ diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp index e9ceccc24..28345a1e9 100644 --- a/source/encoder/ratecontrol.cpp +++ b/source/encoder/ratecontrol.cpp @@ -1116,123 +1116,106 @@ bool RateControl::initPass2() uint64_t allAvailableBits = uint64_t(m_param->rc.bitrate * 1000. * m_numEntries * m_frameDuration); int startIndex, framesCount, endIndex; int fps = X265_MIN(m_param->keyframeMax, (int)(m_fps + 0.5)); + int distance = fps << 1; + distance = distance > m_param->keyframeMax ? (m_param->keyframeMax << 1) : m_param->keyframeMax; startIndex = endIndex = framesCount = 0; - int diffQp = 0; double targetBits = 0; double expectedBits = 0; - for (startIndex = m_start, endIndex = m_start; endIndex < m_numEntries; endIndex++) + double targetBits2 = 0; + double expectedBits2 = 0; + double cpxSum = 0; + double cpxSum2 = 0; + + if (m_param->rc.rateControlMode == X265_RC_ABR) { - allConstBits += m_rce2Pass[endIndex].miscBits; - allCodedBits += m_rce2Pass[endIndex].coeffBits + m_rce2Pass[endIndex].mvBits; - if (m_param->rc.rateControlMode == X265_RC_CRF) + for (startIndex = m_start, endIndex = m_start; endIndex < m_numEntries; endIndex++) { - framesCount = endIndex - startIndex + 1; - diffQp += int (m_rce2Pass[endIndex].qpaRc - m_rce2Pass[endIndex].qpNoVbv); - if (framesCount > fps) - diffQp -= int (m_rce2Pass[endIndex - fps].qpaRc - m_rce2Pass[endIndex - fps].qpNoVbv); - if (framesCount >= fps) - { - if (diffQp >= 1) - { - if (!m_isQpModified && endIndex > fps) - { - double factor = 2; - double step = 0; - if (endIndex + fps >= m_numEntries) - { - m_start = endIndex - (endIndex % fps); - return true; - } - for (int start = endIndex + 1; start <= endIndex + fps && start < m_numEntries; start++) - { - RateControlEntry *rce = &m_rce2Pass[start]; - targetBits += qScale2bits(rce, x265_qp2qScale(rce->qpNoVbv)); - expectedBits += qScale2bits(rce, rce->qScale); - } - if (expectedBits < 0.95 * targetBits) - { - m_isQpModified = true; - m_isGopReEncoded = true; - while (endIndex + fps < m_numEntries) - { - step = pow(2, factor / 6.0); - expectedBits = 0; - for (int start = endIndex + 1; start <= endIndex + fps; start++) - { - RateControlEntry *rce = &m_rce2Pass[start]; - rce->newQScale = rce->qScale / step; - X265_CHECK(rce->newQScale >= 0, "new Qscale is negative\n"); - expectedBits += qScale2bits(rce, rce->newQScale); - rce->newQp = x265_qScale2qp(rce->newQScale); - } - if (expectedBits >= targetBits && step > 1) - factor *= 0.90; - else - break; - } - - if (m_isVbv && endIndex + fps < m_numEntries) - if (!vbv2Pass((uint64_t)targetBits, endIndex + fps, endIndex + 1)) - return false; - - targetBits = 0; - expectedBits = 0; - - for (int start = endIndex - fps + 1; start <= endIndex; start++) - { - RateControlEntry *rce = &m_rce2Pass[start]; - targetBits += qScale2bits(rce, x265_qp2qScale(rce->qpNoVbv)); - } - while (1) - { - step = pow(2, factor / 6.0); - expectedBits = 0; - for (int start = endIndex - fps + 1; start <= endIndex; start++) - { - RateControlEntry *rce = &m_rce2Pass[start]; - rce->newQScale = rce->qScale * step; - X265_CHECK(rce->newQScale >= 0, "new Qscale is negative\n"); - expectedBits += qScale2bits(rce, rce->newQScale); - rce->newQp = x265_qScale2qp(rce->newQScale); - } - if (expectedBits > targetBits && step > 1) - factor *= 1.1; - else - break; - } - if (m_isVbv) - if (!vbv2Pass((uint64_t)targetBits, endIndex, endIndex - fps + 1)) - return false; - diffQp = 0; - m_reencode = endIndex - fps + 1; - endIndex = endIndex + fps; - startIndex = endIndex + 1; - m_start = startIndex; - targetBits = expectedBits = 0; - } - else - targetBits = expectedBits = 0; - } - } - else - m_isQpModified = false; - } + allConstBits += m_rce2Pass[endIndex].miscBits; + allCodedBits += m_rce2Pass[endIndex].coeffBits + m_rce2Pass[endIndex].mvBits; } - } - if (m_param->rc.rateControlMode == X265_RC_ABR) - { if (allAvailableBits < allConstBits) { x265_log(m_param, X265_LOG_ERROR, "requested bitrate is too low. estimated minimum is %d kbps\n", - (int)(allConstBits * m_fps / framesCount * 1000.)); + (int)(allConstBits * m_fps / framesCount * 1000.)); return false; } if (!analyseABR2Pass(allAvailableBits)) return false; + + return true; } - m_start = X265_MAX(m_start, endIndex - fps); + if (m_param->rc.rateControlMode != X265_RC_CRF) + { + return true; + } + + if (m_isQpModified) + { + return true; + } + + if (m_start + (fps << 1) > m_numEntries) + { + return true; + } + + for (startIndex = m_start, endIndex = m_numEntries - 1; startIndex < endIndex; startIndex++, endIndex--) + { + cpxSum += m_rce2Pass[startIndex].qScale / m_rce2Pass[startIndex].coeffBits; + cpxSum2 += m_rce2Pass[endIndex].qScale / m_rce2Pass[endIndex].coeffBits; + + RateControlEntry *rce = &m_rce2Pass[startIndex]; + targetBits += qScale2bits(rce, x265_qp2qScale(rce->qpNoVbv)); + expectedBits += qScale2bits(rce, rce->qScale); + + rce = &m_rce2Pass[endIndex]; + targetBits2 += qScale2bits(rce, x265_qp2qScale(rce->qpNoVbv)); + expectedBits2 += qScale2bits(rce, rce->qScale); + } + + if (expectedBits < 0.95 * targetBits || expectedBits2 < 0.95 * targetBits2) + { + if (cpxSum/cpxSum2 < 0.95 || cpxSum2 / cpxSum < 0.95) + { + m_isQpModified = true; + m_isGopReEncoded = true; + + m_shortTermCplxSum = 0; + m_shortTermCplxCount = 0; + m_framesDone = m_start; + + for (startIndex = m_start; startIndex < m_numEntries; startIndex++) + { + m_shortTermCplxSum *= 0.5; + m_shortTermCplxCount *= 0.5; + m_shortTermCplxSum += m_rce2Pass[startIndex].currentSatd / (CLIP_DURATION(m_frameDuration) / BASE_FRAME_DURATION); + m_shortTermCplxCount++; + } + + m_bufferFill = m_rce2Pass[m_start - 1].bufferFill; + m_bufferFillFinal = m_rce2Pass[m_start - 1].bufferFillFinal; + m_bufferFillActual = m_rce2Pass[m_start - 1].bufferFillActual; + + m_reencode = m_start; + m_start = m_numEntries; + } + else + { + + m_isQpModified = false; + m_isGopReEncoded = false; + } + } + else + { + + m_isQpModified = false; + m_isGopReEncoded = false; + } + + m_start = X265_MAX(m_start, m_numEntries - distance + m_param->keyframeMax); return true; } @@ -1505,15 +1488,34 @@ int RateControl::rateControlStart(Frame* curFrame, RateControlEntry* rce, Encode rce->frameSizeMaximum *= m_param->maxAUSizeFactor; } } + + ///< regenerate the qp if (!m_isAbr && m_2pass && m_param->rc.rateControlMode == X265_RC_CRF) { - rce->qpPrev = x265_qScale2qp(rce->qScale); - rce->qScale = rce->newQScale; - rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = x265_qScale2qp(rce->newQScale); - m_qp = int(rce->qpaRc + 0.5); - rce->frameSizePlanned = qScale2bits(rce, rce->qScale); - m_framesDone++; - return m_qp; + int index = m_encOrder[rce->poc]; + index++; + double totalDuration = m_frameDuration; + for (int j = 0; totalDuration < 1.0; j++) + { + switch (m_rce2Pass[index].sliceType) + { + case B_SLICE: + curFrame->m_lowres.plannedType[j] = m_rce2Pass[index].keptAsRef ? X265_TYPE_BREF : X265_TYPE_B; + break; + case P_SLICE: + curFrame->m_lowres.plannedType[j] = X265_TYPE_P; + break; + case I_SLICE: + curFrame->m_lowres.plannedType[j] = m_param->bOpenGOP ? X265_TYPE_I : X265_TYPE_IDR; + break; + default: + break; + } + + curFrame->m_lowres.plannedSatd[j] = m_rce2Pass[index].currentSatd; + totalDuration += m_frameDuration; + index++; + } } if (m_isAbr || m_2pass) // ABR,CRF @@ -2019,7 +2021,7 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce) qScale = x265_clip3(lqmin, lqmax, qScale); } - if (!m_2pass || m_param->bliveVBV2pass) + if (!m_2pass || m_param->bliveVBV2pass || (m_2pass && m_param->rc.rateControlMode == X265_RC_CRF)) { /* clip qp to permissible range after vbv-lookahead estimation to avoid possible * mispredictions by initial frame size predictors */ @@ -2056,7 +2058,7 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce) else { double abrBuffer = 2 * m_rateTolerance * m_bitrate; - if (m_2pass) + if (m_2pass && m_param->rc.rateControlMode != X265_RC_CRF) { double lmin = m_lmin[m_sliceType]; double lmax = m_lmax[m_sliceType]; @@ -2947,7 +2949,7 @@ int RateControl::rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry* if (m_param->rc.aqMode || m_isVbv || m_param->bAQMotion || bEnableDistOffset) { - if (m_isVbv && !(m_2pass && m_param->rc.rateControlMode == X265_RC_CRF)) + if (m_isVbv) { double avgQpRc = 0; /* determine avg QP decided by VBV rate control */ @@ -2981,16 +2983,7 @@ int RateControl::rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry* if (m_param->rc.rateControlMode == X265_RC_CRF) { double crfVal, qpRef = curEncData.m_avgQpRc; - bool is2passCrfChange = false; - if (m_2pass) - { - if (fabs(curEncData.m_avgQpRc - rce->qpPrev) > 0.1) - { - qpRef = rce->qpPrev; - is2passCrfChange = true; - } - } - if (is2passCrfChange || fabs(qpRef - rce->qpNoVbv) > 0.5) + if (fabs(qpRef - rce->qpNoVbv) > 0.5) { double crfFactor = rce->qRceq /x265_qp2qScale(qpRef); double baseCplx = m_ncu * (m_param->bframes ? 120 : 80); diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h index a0b555f8a..666025823 100644 --- a/source/encoder/ratecontrol.h +++ b/source/encoder/ratecontrol.h @@ -74,6 +74,7 @@ struct RateControlEntry Predictor rowPreds[3][2]; Predictor* rowPred[2]; + int64_t currentSatd; int64_t lastSatd; /* Contains the picture cost of the previous frame, required for resetAbr and VBV */ int64_t leadingNoBSatd; int64_t rowTotalBits; /* update cplxrsum and totalbits at the end of 2 rows */ @@ -88,6 +89,8 @@ struct RateControlEntry double rowCplxrSum; double qpNoVbv; double bufferFill; + double bufferFillFinal; + double bufferFillActual; double targetFill; bool vbvEndAdj; double frameDuration; -- 2.22.0.windows.1
0001-x265-Modify-the-crf-2-pass.patch
Description: Binary data
_______________________________________________ x265-devel mailing list x265-devel@videolan.org https://mailman.videolan.org/listinfo/x265-devel