compressFrame()//调用rateControlStart()函数
{
//计算估计当前帧应用的量化参数 ,在当前帧预编码完成之后才调用
int qp = m_top->m_rateControl->rateControlStart(m_frame, &m_rce, m_top);
processRowEncoder();
}
// to be called for each curFrame to process RateControl and set QP
rateControlStart()//调用rateEstimateQscale()
{
if (!curFrame)
{
// faked rateControlStart calls when the encoder is flushing
m_startEndOrder.incr();
//若预编码未完成,则返回
return 0;
}
//若是2pass的crf模式
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;
}
if (m_isAbr || m_2pass) // ABR,CRF
{
if (m_isAbr || m_isVbv)
{
}
//基于ABR计算QP
double q = x265_qScale2qp(rateEstimateQscale(curFrame, rce));///////////////////
q = x265_clip3((double)QP_MIN, (double)QP_MAX_MAX, q);
m_qp = int(q + 0.5);
}
else//CQP
{
}
m_framesDone++;
return m_qp;
}
rateEstimateQscale()//调用getQScale()计算Qp
{
if (m_2pass)
{
//若为2 pass判断上一pass的sliceType和当前sliceType是否一致,否则报错
}
else
{
if (m_isAbr)
}
//B帧没有独立的码控,只能通过相邻的两个P帧QP的平均值 + offset所得
if (m_sliceType == B_SLICE)
{
//根据前后I帧、P帧插值得到p
double qScale = x265_qp2qScale(q);
rce->qpNoVbv = q;
rce->newQScale = qScale;
return qScale;
}
else
{
if (m_2pass)
{
q = rce->newQScale;
x265_zone* zone = getZone();
q /= x265_clip3(0.5, 2.0, (double)(abrBuffer - diff) / abrBuffer);
rce->qpNoVbv = x265_qScale2qp(q);
if (m_isVbv)
{
}
q = x265_clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);
}
else
{
/* 1pass ABR */
/* coeffBits to be used in 2-pass */
rce->coeffBits = (int)m_currentSatd;
rce->blurredComplexity = m_shortTermCplxSum / m_shortTermCplxCount;
rce->mvBits = 0;
rce->sliceType = m_sliceType;
if (m_param->rc.rateControlMode == X265_RC_CRF)
{
q = getQScale(rce, m_rateFactorConstant);//////////////////////
x265_zone* zone = getZone();
}
else
{
if (!m_param->rc.bStatRead)
checkAndResetABR(rce, false);
double initialQScale = getQScale(rce, m_wantedBitsWindow / m_cplxrSum);/////////////////
//rateFactor = m_wantedBitsWindow/m_cplxrSum,使得计算得到的QScale与已编码视频的复杂度成正比
x265_zone* zone = getZone();
double tunedQScale = tuneAbrQScaleFromFeedback(initialQScale);
q = !m_partialResidualFrames? tunedQScale : initialQScale;
bool isEncodeEnd = (m_param->totalFrames &&
m_framesDone > 0.75 * m_param->totalFrames) ? 1 : 0;
}
}
m_lastQScaleFor[m_sliceType] = q;
rce->frameSizeEstimated = rce->frameSizePlanned;
rce->newQScale = q;
return q;
}
}
/* modify the bitrate curve from pass1 for one frame */
/*函数功能:在1pass中只在非B帧应用获取预测的qscale如果有对应zone信息对qcale进行修正、
在2pass中对所有帧应用获取预测的qscale如果有对应zone信息对qcale进行修正*/
/* 调用范围:只在initPass2()和rateEstimateQscale(只在非B帧应用)函数中被调用
注意:1pass中只在rateEstimateQscale函数中调用 ,2pass中只在initPass2()调用
返回 :返回qscale值*/
/*参数 rateFactor:参数因子在initPass2():1.0 rateFactor 在rateEstimateQscale:
在非B帧中进入 CRF:m_rateFactorConstant ABR:m_wantedBitsWindow / m_cplxrSum
(当前需要的总bits/(已编码bits*qscale/m_lastRceq))*/
double RateControl::getQScale(RateControlEntry *rce, double rateFactor)
{
double q;
if (m_param->rc.cuTree)
{
// Scale and units are obtained from rateNum and rateDenom for videos with fixed frame rates.
//播放一帧时间的一半, 1000/(2 * 25000)
double timescale = (double)m_param->fpsDenom / (2 * m_param->fpsNum);
//值:(fps/25)^(1 - m_param->rc.qCompress)
q = pow(BASE_FRAME_DURATION / CLIP_DURATION(2 * timescale), 1 - m_param->rc.qCompress);
}
else
q = pow(rce->blurredComplexity, 1 - m_param->rc.qCompress);
// avoid NaN's in the Rceq
if (rce->coeffBits + rce->mvBits == 0)//很少有此情况
q = m_lastQScaleFor[rce->sliceType];
else
{
m_lastRceq = q;
q /= rateFactor;
}
return q;
}
/*rc.qCompress默认是0.6,也就是说量化步长是blurredComplexity的0.4次幂,
blurredComplexity越大,量化步长越大。blurredComplexity是图像的预测残差的SATD。
根据图像复杂度初步计算出QScale后,还须除以ratefactor。
CRF和ABR调用getQScale时给的rateFactor的参数不同,CRF时是常数,
ABR等于m_wantedBitsWindow / m_cplxrSum,使得计算得到的QScale与已编码视频的复杂度成正比。*/
上述为代码流程梳理,只列出了主要代码,省略大部分;
下面给出RateControlStart()和rateEstimateQscale()代码详细注释
// to be called for each curFrame to process RateControl and set QP
int RateControl::rateControlStart(Frame* curFrame, RateControlEntry* rce, Encoder* enc)
{
int orderValue = m_startEndOrder.get();//编码序号
int startOrdinal = rce->encodeOrder * 2;
while (orderValue < startOrdinal && !m_bTerminated)//与进程相关
orderValue = m_startEndOrder.waitForChange(orderValue);
if (!curFrame)//??若为预编码则退出?
{
// faked rateControlStart calls when the encoder is flushing
m_startEndOrder.incr();
return 0;
}
FrameData& curEncData = *curFrame->m_encData;
m_curSlice = curEncData.m_slice;
m_sliceType = m_curSlice->m_sliceType;
rce->sliceType = m_sliceType;
if (!m_2pass)//如果不是2 pass,判断当前帧是否为参考帧并存储供后续pass使用
rce->keptAsRef = IS_REFERENCED(curFrame);
//根据curFrame->m_lowres.sliceType判断是否为参考B帧,若是则返回3(X265_TYPE_P),or返回slicetype
m_predType = getPredictorType(curFrame->m_lowres.sliceType, m_sliceType);
rce->poc = m_curSlice->m_poc;
if (m_param->rc.bStatRead)//若为>1的pass,则需读取上一pass的数据
{
//确保当前poc帧比输入数据帧小,否则没有数据可读
X265_CHECK(rce->poc >= 0 && rce->poc < m_numEntries, "bad encode ordinal\n");
int index = m_encOrder[rce->poc];
copyRceData(rce, &m_rce2Pass[index]);//copy数据
}
rce->isActive = true;
rce->scenecut = false;
//参考帧是否为非I帧场景切换帧
bool isRefFrameScenecut = m_sliceType!= I_SLICE && m_curSlice->m_refFrameList[0][0]->m_lowres.bScenecut;
m_isFirstMiniGop = m_sliceType == I_SLICE ? true : m_isFirstMiniGop;
//如果当前帧是场景切换帧,则把当前为止最后一个帧预测器设置为当前帧的编码顺序,并初始化帧预测器(即清空之前的数据)
if (curFrame->m_lowres.bScenecut)
{
m_isSceneTransition = true;
rce->scenecut = true;
m_lastPredictorReset = rce->encodeOrder;
initFramePredictors();
}
else if (m_sliceType != B_SLICE && !isRefFrameScenecut)
m_isSceneTransition = false;
if (rce->encodeOrder < m_lastPredictorReset + m_param->frameNumThreads)
{
rce->rowPreds[0][0].count = 0;
}
rce->bLastMiniGopBFrame = curFrame->m_lowres.bLastMiniGopBFrame;
rce->bufferRate = m_bufferRate;
rce->rowCplxrSum = 0.0;
rce->rowTotalBits = 0;
if (m_isVbv)
{
if (rce->rowPreds[0][0].count == 0)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
rce->rowPreds[i][j].coeffMin = 0.25 / 4;
rce->rowPreds[i][j].coeff = 0.25;
rce->rowPreds[i][j].count = 1.0;
rce->rowPreds[i][j].decay = 0.5;
rce->rowPreds[i][j].offset = 0.0;
}
}
}
rce->rowPred[0] = &rce->rowPreds[m_sliceType][0];
rce->rowPred[1] = &rce->rowPreds[m_sliceType][1];
m_predictedBits = m_totalBits;
updateVbvPlan(enc);
rce->bufferFill = m_bufferFill;
int mincr = enc->m_vps.ptl.minCrForLevel;
/* Profiles above Main10 don't require maxAU size check, so just set the maximum to a large value. */
if (enc->m_vps.ptl.profileIdc > Profile::MAIN10 || enc->m_vps.ptl.levelIdc == Level::NONE)
rce->frameSizeMaximum = 1e9;
else
{
/* The spec has a special case for the first frame. */
if (rce->encodeOrder == 0)
{
/* 1.5 * (Max( PicSizeInSamplesY, fR * MaxLumaSr) + MaxLumaSr * (AuCpbRemovalTime[ 0 ] -AuNominalRemovalTime[ 0 ])) ? MinCr */
double fr = 1. / 300;
int picSizeInSamplesY = m_param->sourceWidth * m_param->sourceHeight;
rce->frameSizeMaximum = 8 * 1.5 * X265_MAX(picSizeInSamplesY, fr * enc->m_vps.ptl.maxLumaSrForLevel) / mincr;
}
else
{
/* 1.5 * MaxLumaSr * (AuCpbRemovalTime[ n ] - AuCpbRemovalTime[ n - 1 ]) / MinCr */
rce->frameSizeMaximum = 8 * 1.5 * enc->m_vps.ptl.maxLumaSrForLevel * m_frameDuration / mincr;
}
}
}
//2 pass的crf模式时,使用上一pass数据返回m_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;
}
//2 pass的任何模式或1 pass的ABR模式
//m_isAbr = m_param->rc.rateControlMode != X265_RC_CQP && !m_param->rc.bStatRead;
//m_isAbr:不是CQP模式,且是1pass(即不读取数据)
//first pass & second pass
if (m_isAbr || m_2pass) // ABR,CRF
{
//m_isVbv:m_param->rc.vbvMaxBitrate > 0 && m_param->rc.vbvBufferSize > 0
//m_isVbv:即是否设缓冲区
if (m_isAbr || m_isVbv)
{
m_currentSatd = curFrame->m_lowres.satdCost >> (X265_DEPTH - 8);
/* Update rce for use in rate control VBV later */
rce->lastSatd = m_currentSatd;
X265_CHECK(rce->lastSatd, "satdcost cannot be zero\n");
/* Detect a pattern for B frames with same SATDcost to identify a series of static frames
* and the P frame at the end of the series marks a possible case for ABR reset logic */
if (m_param->bframes)
{
if (m_sliceType != B_SLICE && m_numBframesInPattern > m_param->bframes)
{
m_isPatternPresent = true;
}
else if (m_sliceType == B_SLICE && !IS_REFERENCED(curFrame))
{
if (m_currentSatd != m_lastBsliceSatdCost && !rce->bLastMiniGopBFrame)
{
m_isPatternPresent = false;
m_lastBsliceSatdCost = m_currentSatd;
m_numBframesInPattern = 0;
}
else if (m_currentSatd == m_lastBsliceSatdCost)
m_numBframesInPattern++;
}
}
}
/* For a scenecut that occurs within the mini-gop, enable scene transition
* switch until the next mini-gop to ensure a min qp for all the frames within
* the scene-transition mini-gop */
//first pass & second pass的m_qp出处
double q = x265_qScale2qp(rateEstimateQscale(curFrame, rce));
q = x265_clip3((double)QP_MIN, (double)QP_MAX_MAX, q);
m_qp = int(q + 0.5);
q = m_isGrainEnabled ? m_qp : q;
rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = q;
/* copy value of lastRceq into thread local rce struct *to be used in RateControlEnd() */
rce->qRceq = m_lastRceq;
accumPQpUpdate();
}
else // CQP
{
if (m_sliceType == B_SLICE && IS_REFERENCED(curFrame))
m_qp = (m_qpConstant[B_SLICE] + m_qpConstant[P_SLICE]) / 2;
else
m_qp = m_qpConstant[m_sliceType];
curEncData.m_avgQpAq = curEncData.m_avgQpRc = m_qp;
x265_zone* zone = getZone();
if (zone)
{
if (zone->bForceQp)
m_qp += zone->qp - m_qpConstant[P_SLICE];
else
m_qp -= (int)(6.0 * X265_LOG2(zone->bitrateFactor));
}
}
if (m_sliceType != B_SLICE)
{
m_lastNonBPictType = m_sliceType;
m_leadingNoBSatd = m_currentSatd;
}
rce->leadingNoBSatd = m_leadingNoBSatd;
if (curFrame->m_forceqp)
{
m_qp = (int32_t)(curFrame->m_forceqp + 0.5) - 1;
m_qp = x265_clip3(QP_MIN, QP_MAX_MAX, m_qp);
rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = m_qp;
if (m_isAbr || m_2pass)
{
rce->qpNoVbv = rce->qpaRc;
m_lastQScaleFor[m_sliceType] = x265_qp2qScale(rce->qpaRc);
if (rce->poc == 0)
m_lastQScaleFor[P_SLICE] = m_lastQScaleFor[m_sliceType] * fabs(m_param->rc.ipFactor);
rce->frameSizePlanned = predictSize(&m_pred[m_predType], m_qp, (double)m_currentSatd);
}
}
m_framesDone++;
return m_qp;
}
//返回Qscale
double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)
{
double q;
if (m_2pass)//second pass
{
//若为2 pass判断上一pass的sliceType和当前sliceType是否一致,否则报错
if (m_sliceType != rce->sliceType)
{
x265_log(m_param, X265_LOG_ERROR, "slice=%c but 2pass stats say %c\n",
g_sliceTypeToChar[m_sliceType], g_sliceTypeToChar[rce->sliceType]);
}
}
else//first pass
{
if (m_isAbr)
{
int pos = m_sliderPos % s_slidingWindowFrames;
int addPos = (pos + s_slidingWindowFrames - 1) % s_slidingWindowFrames;
if (m_sliderPos > s_slidingWindowFrames)
{
const static double base = pow(0.5, s_slidingWindowFrames - 1);
m_movingAvgSum -= m_lastRemovedSatdCost * base;
m_movingAvgSum *= 0.5;
m_movingAvgSum += m_satdCostWindow[addPos];
}
else if (m_sliderPos == s_slidingWindowFrames)
{
m_movingAvgSum += m_satdCostWindow[addPos];
}
else if (m_sliderPos > 0)
{
m_movingAvgSum += m_satdCostWindow[addPos];
m_movingAvgSum *= 0.5;
}
rce->movingAvgSum = m_movingAvgSum;
m_lastRemovedSatdCost = m_satdCostWindow[pos];
m_satdCostWindow[pos] = rce->lastSatd;
m_sliderPos++;
}
}
//B帧没有独立的码控,只能通过相邻的两个P帧QP的平均值 + offset所得
if (m_sliceType == B_SLICE)
{
/* B-frames don't have independent rate control, but rather get the
* average QP of the two adjacent P-frames + an offset */
Slice* prevRefSlice = m_curSlice->m_refFrameList[0][0]->m_encData->m_slice;
Slice* nextRefSlice = m_curSlice->m_refFrameList[1][0]->m_encData->m_slice;
double q0 = m_curSlice->m_refFrameList[0][0]->m_encData->m_avgQpRc;
double q1 = m_curSlice->m_refFrameList[1][0]->m_encData->m_avgQpRc;
bool i0 = prevRefSlice->m_sliceType == I_SLICE;
bool i1 = nextRefSlice->m_sliceType == I_SLICE;
int dt0 = abs(m_curSlice->m_poc - prevRefSlice->m_poc);
int dt1 = abs(m_curSlice->m_poc - nextRefSlice->m_poc);
// Skip taking a reference frame before the Scenecut if ABR has been reset.
if (m_lastAbrResetPoc >= 0)
{
if (prevRefSlice->m_sliceType == P_SLICE && prevRefSlice->m_poc < m_lastAbrResetPoc)
{
i0 = i1;
dt0 = dt1;
q0 = q1;
}
}
if (prevRefSlice->m_sliceType == B_SLICE && IS_REFERENCED(m_curSlice->m_refFrameList[0][0]))
q0 -= m_pbOffset / 2;
if (nextRefSlice->m_sliceType == B_SLICE && IS_REFERENCED(m_curSlice->m_refFrameList[1][0]))
q1 -= m_pbOffset / 2;
if (i0 && i1)
q = (q0 + q1) / 2 + m_ipOffset;
else if (i0)
q = q1;
else if (i1)
q = q0;
else if(m_isGrainEnabled && !m_2pass)
q = q1;
else
q = (q0 * dt1 + q1 * dt0) / (dt0 + dt1);
if (IS_REFERENCED(curFrame))
q += m_pbOffset / 2;
else
q += m_pbOffset;
/* Set a min qp at scenechanges and transitions */
if (m_isSceneTransition)
{
q = X265_MAX(ABR_SCENECUT_INIT_QP_MIN, q);
double minScenecutQscale =x265_qp2qScale(ABR_SCENECUT_INIT_QP_MIN);
m_lastQScaleFor[P_SLICE] = X265_MAX(minScenecutQscale, m_lastQScaleFor[P_SLICE]);
}
double qScale = x265_qp2qScale(q);
rce->qpNoVbv = q;
double lmin = 0, lmax = 0;
if (m_isGrainEnabled && m_isFirstMiniGop)//m_isGrainEnabled = false
{
lmin = m_lastQScaleFor[P_SLICE] / m_lstep;
lmax = m_lastQScaleFor[P_SLICE] * m_lstep;
double tunedQscale = tuneAbrQScaleFromFeedback(qScale);
double overflow = tunedQscale / qScale;
if (!m_isAbrReset)
qScale = x265_clip3(lmin, lmax, qScale);
m_avgPFrameQp = m_avgPFrameQp == 0 ? rce->qpNoVbv : m_avgPFrameQp;
if (overflow != 1)
{
qScale = tuneQScaleForGrain(overflow);
q = x265_qScale2qp(qScale);
}
rce->qpNoVbv = q;
}
if (m_isVbv)//second pass B frame
{
lmin = m_lastQScaleFor[P_SLICE] / m_lstep;
lmax = m_lastQScaleFor[P_SLICE] * m_lstep;
if (m_isCbr && !m_isGrainEnabled)
{
qScale = tuneAbrQScaleFromFeedback(qScale);
if (!m_isAbrReset)
qScale = x265_clip3(lmin, lmax, qScale);
q = x265_qScale2qp(qScale);
}
if (!m_2pass)
{
qScale = clipQscale(curFrame, rce, qScale);
/* clip qp to permissible range after vbv-lookahead estimation to avoid possible
* mispredictions by initial frame size predictors */
if (m_pred[m_predType].count == 1)
qScale = x265_clip3(lmin, lmax, qScale);
m_lastQScaleFor[m_sliceType] = qScale;
rce->frameSizePlanned = predictSize(&m_pred[m_predType], qScale, (double)m_currentSatd);
}
else
rce->frameSizePlanned = qScale2bits(rce, qScale);
/* Limit planned size by MinCR */
rce->frameSizePlanned = X265_MIN(rce->frameSizePlanned, rce->frameSizeMaximum);
rce->frameSizeEstimated = rce->frameSizePlanned;
}
rce->newQScale = qScale;
if(rce->bLastMiniGopBFrame)
{
if (m_isFirstMiniGop && m_isGrainEnabled)
{
m_avgPFrameQp = (m_avgPFrameQp + rce->qpNoVbv) / 2;
m_lastQScaleFor[P_SLICE] = x265_qp2qScale(m_avgPFrameQp);
}
m_isFirstMiniGop = false;
}
return qScale;
}
else
{
double abrBuffer = 2 * m_rateTolerance * m_bitrate;
if (m_2pass)
{
int64_t diff;
if (!m_isVbv)
{
m_predictedBits = m_totalBits;
if (rce->encodeOrder < m_param->frameNumThreads)
m_predictedBits += (int64_t)(rce->encodeOrder * m_bitrate / m_fps);
else
m_predictedBits += (int64_t)(m_param->frameNumThreads * m_bitrate / m_fps);
}
/* Adjust ABR buffer based on distance to the end of the video. */
if (m_numEntries > rce->encodeOrder)
{
uint64_t finalBits = m_rce2Pass[m_numEntries - 1].expectedBits;
double videoPos = (double)rce->expectedBits / finalBits;
double scaleFactor = sqrt((1 - videoPos) * m_numEntries);
abrBuffer *= 0.5 * X265_MAX(scaleFactor, 0.5);
}
diff = m_predictedBits - (int64_t)rce->expectedBits;
q = rce->newQScale;
x265_zone* zone = getZone();
if (zone)
{
if (zone->bForceQp)
q = x265_qp2qScale(zone->qp);
else
q /= zone->bitrateFactor;
}
q /= x265_clip3(0.5, 2.0, (double)(abrBuffer - diff) / abrBuffer);
if (m_expectedBitsSum > 0)
{
/* Adjust quant based on the difference between
* achieved and expected bitrate so far */
double curTime = (double)rce->encodeOrder / m_numEntries;
double w = x265_clip3(0.0, 1.0, curTime * 100);
q *= pow((double)m_totalBits / m_expectedBitsSum, w);
}
if (m_framesDone == 0 && m_param->rc.rateControlMode == X265_RC_ABR && m_isGrainEnabled)
q = X265_MIN(x265_qp2qScale(ABR_INIT_QP_GRAIN_MAX), q);
rce->qpNoVbv = x265_qScale2qp(q);
if (m_isVbv)
{
/* Do not overflow vbv */
double expectedSize = qScale2bits(rce, q);
double expectedVbv = m_bufferFill + m_bufferRate - expectedSize;
double expectedFullness = rce->expectedVbv / m_bufferSize;
double qmax = q * (2 - expectedFullness);
double sizeConstraint = 1 + expectedFullness;
qmax = X265_MAX(qmax, rce->newQScale);
if (expectedFullness < .05)
qmax = MAX_MAX_QPSCALE;
qmax = X265_MIN(qmax, MAX_MAX_QPSCALE);
while (((expectedVbv < rce->expectedVbv/sizeConstraint) && (q < qmax)) ||
((expectedVbv < 0) && (q < MAX_MAX_QPSCALE)))
{
q *= 1.05;
expectedSize = qScale2bits(rce, q);
expectedVbv = m_bufferFill + m_bufferRate - expectedSize;
}
}
q = x265_clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);
}
else
{
//1 pass
/* 1pass ABR */
/* Calculate the quantizer which would have produced the desired
* average bitrate if it had been applied to all frames so far.
* Then modulate that quant based on the current frame's complexity
* relative to the average complexity so far (using the 2pass RCEQ).
* Then bias the quant up or down if total size so far was far from
* the target.
* Result: Depending on the value of rate_tolerance, there is a
* trade-off between quality and bitrate precision. But at large
* tolerances, the bit distribution approaches that of 2pass. */
double overflow = 1;
double lqmin = MIN_QPSCALE, lqmax = MAX_MAX_QPSCALE;
m_shortTermCplxSum *= 0.5;
m_shortTermCplxCount *= 0.5;
m_shortTermCplxSum += m_currentSatd / (CLIP_DURATION(m_frameDuration) / BASE_FRAME_DURATION);
m_shortTermCplxCount++;
/* coeffBits to be used in 2-pass */
rce->coeffBits = (int)m_currentSatd;
rce->blurredComplexity = m_shortTermCplxSum / m_shortTermCplxCount;
rce->mvBits = 0;
rce->sliceType = m_sliceType;
if (m_param->rc.rateControlMode == X265_RC_CRF)
{
q = getQScale(rce, m_rateFactorConstant);
x265_zone* zone = getZone();
if (zone)
{
if (zone->bForceQp)
q = x265_qp2qScale(zone->qp);
else
q /= zone->bitrateFactor;
}
}
else
{
if (!m_param->rc.bStatRead)
checkAndResetABR(rce, false);
double initialQScale = getQScale(rce, m_wantedBitsWindow / m_cplxrSum);
x265_zone* zone = getZone();
if (zone)
{
if (zone->bForceQp)
initialQScale = x265_qp2qScale(zone->qp);
else
initialQScale /= zone->bitrateFactor;
}
double tunedQScale = tuneAbrQScaleFromFeedback(initialQScale);
overflow = tunedQScale / initialQScale;
q = !m_partialResidualFrames? tunedQScale : initialQScale;
bool isEncodeEnd = (m_param->totalFrames &&
m_framesDone > 0.75 * m_param->totalFrames) ? 1 : 0;
bool isEncodeBeg = m_framesDone < (int)(m_fps + 0.5);
if (m_isGrainEnabled)
{
if(m_sliceType!= I_SLICE && m_framesDone && !isEncodeEnd &&
((overflow < 1.05 && overflow > 0.95) || isEncodeBeg))
{
q = tuneQScaleForGrain(overflow);
}
}
}
if ((m_sliceType == I_SLICE && m_param->keyframeMax > 1
&& m_lastNonBPictType != I_SLICE && !m_isAbrReset) || (m_isNextGop && !m_framesDone))
{
if (!m_param->rc.bStrictCbr)
q = x265_qp2qScale(m_accumPQp / m_accumPNorm);
q /= fabs(m_param->rc.ipFactor);
m_avgPFrameQp = 0;
}
else if (m_framesDone > 0)
{
if (m_param->rc.rateControlMode != X265_RC_CRF)
{
lqmin = m_lastQScaleFor[m_sliceType] / m_lstep;
lqmax = m_lastQScaleFor[m_sliceType] * m_lstep;
if (!m_partialResidualFrames || m_isGrainEnabled)
{
if (overflow > 1.1 && m_framesDone > 3)
lqmax *= m_lstep;
else if (overflow < 0.9)
lqmin /= m_lstep;
}
q = x265_clip3(lqmin, lqmax, q);
}
}
else if (m_qCompress != 1 && m_param->rc.rateControlMode == X265_RC_CRF)
{
q = x265_qp2qScale(CRF_INIT_QP) / fabs(m_param->rc.ipFactor);
}
else if (m_framesDone == 0 && !m_isVbv && m_param->rc.rateControlMode == X265_RC_ABR)
{
/* for ABR alone, clip the first I frame qp */
lqmax = (m_lstep * m_isGrainEnabled) ? x265_qp2qScale(ABR_INIT_QP_GRAIN_MAX) :
x265_qp2qScale(ABR_INIT_QP_MAX);
q = X265_MIN(lqmax, q);
}
q = x265_clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);
/* Set a min qp at scenechanges and transitions */
if (m_isSceneTransition)
{
double minScenecutQscale =x265_qp2qScale(ABR_SCENECUT_INIT_QP_MIN);
q = X265_MAX(minScenecutQscale, q);
m_lastQScaleFor[P_SLICE] = X265_MAX(minScenecutQscale, m_lastQScaleFor[P_SLICE]);
}
rce->qpNoVbv = x265_qScale2qp(q);
if(m_sliceType == P_SLICE)
{
m_avgPFrameQp = m_avgPFrameQp == 0 ? rce->qpNoVbv : m_avgPFrameQp;
m_avgPFrameQp = (m_avgPFrameQp + rce->qpNoVbv) / 2;
}
q = clipQscale(curFrame, rce, q);
/* clip qp to permissible range after vbv-lookahead estimation to avoid possible
* mispredictions by initial frame size predictors, after each scenecut */
bool isFrameAfterScenecut = m_sliceType!= I_SLICE && m_curSlice->m_refFrameList[0][0]->m_lowres.bScenecut;
if (!m_2pass && m_isVbv && isFrameAfterScenecut)
q = x265_clip3(lqmin, lqmax, q);
}
m_lastQScaleFor[m_sliceType] = q;
if ((m_curSlice->m_poc == 0 || m_lastQScaleFor[P_SLICE] < q) && !(m_2pass && !m_isVbv))
m_lastQScaleFor[P_SLICE] = q * fabs(m_param->rc.ipFactor);
if (m_2pass && m_isVbv)
rce->frameSizePlanned = qScale2bits(rce, q);
else
rce->frameSizePlanned = predictSize(&m_pred[m_predType], q, (double)m_currentSatd);
/* Always use up the whole VBV in this case. */
if (m_singleFrameVbv)
rce->frameSizePlanned = m_bufferRate;
/* Limit planned size by MinCR */
if (m_isVbv)
rce->frameSizePlanned = X265_MIN(rce->frameSizePlanned, rce->frameSizeMaximum);
rce->frameSizeEstimated = rce->frameSizePlanned;
rce->newQScale = q;
return q;
}
}