x265码率控制代码梳理

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;
    }
}

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值