Hi Alex, This patch is to re-encode some separated gops to improve the compression efficiency.
Thanks, Mahesh On Fri, Aug 6, 2021 at 6:30 AM Alex Giladi <alex.gil...@gmail.com> wrote: > Hi Mahesh, > What is the actual modification of crf in the patch? > Best, > Alex > > > On Thu, Aug 5, 2021, 2:15 AM Mahesh Pittala <mah...@multicorewareinc.com> > wrote: > >> 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 >> >> _______________________________________________ >> x265-devel mailing list >> x265-devel@videolan.org >> https://mailman.videolan.org/listinfo/x265-devel >> > _______________________________________________ > x265-devel mailing list > x265-devel@videolan.org > https://mailman.videolan.org/listinfo/x265-devel >
_______________________________________________ x265-devel mailing list x265-devel@videolan.org https://mailman.videolan.org/listinfo/x265-devel