|
|
|
@ -163,7 +163,7 @@ void RcInitSequenceParameter (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iSkipFrameNum = 0;
|
|
|
|
|
pWelsSvcRc->iGomSize = (pWelsSvcRc->iNumberMbFrame + pWelsSvcRc->iNumberMbGom - 1) / pWelsSvcRc->iNumberMbGom;
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->bEnableGomQp = true;
|
|
|
|
|
|
|
|
|
|
RcInitLayerMemory (pWelsSvcRc, pEncCtx->pMemAlign, 1 + pEncCtx->pSvcParam->sDependencyLayers[j].iHighestTemporalId);
|
|
|
|
|
|
|
|
|
@ -281,7 +281,7 @@ void RcInitRefreshParameter (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
//I frame R-Q Model
|
|
|
|
|
pWelsSvcRc->iIntraComplexity = 0;
|
|
|
|
|
pWelsSvcRc->iIntraMbCount = 0;
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iIntraComplxMean = 0;
|
|
|
|
|
//P frame R-Q Model
|
|
|
|
|
for (i = 0; i <= kiHighestTid; i++) {
|
|
|
|
|
pTOverRc[i].iPFrameNum = 0;
|
|
|
|
@ -399,7 +399,6 @@ void RcInitIdrQp (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
pDLayerParam->iVideoHeight);
|
|
|
|
|
else
|
|
|
|
|
dBpp = 0.1;
|
|
|
|
|
|
|
|
|
|
//Area*2
|
|
|
|
|
if (pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight <= 28800) // 90p video:160*90
|
|
|
|
|
iBppIndex = 0;
|
|
|
|
@ -420,6 +419,10 @@ void RcInitIdrQp (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp;
|
|
|
|
|
pWelsSvcRc->iQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp);
|
|
|
|
|
pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp;
|
|
|
|
|
pWelsSvcRc->iMinFrameQp = WELS_CLIP3 (pEncCtx->iGlobalQp - DELTA_QP_BGD_THD, pEncCtx->pSvcParam->iMinQp,
|
|
|
|
|
pEncCtx->pSvcParam->iMaxQp);
|
|
|
|
|
pWelsSvcRc->iMaxFrameQp = WELS_CLIP3 (pEncCtx->iGlobalQp + DELTA_QP_BGD_THD, pEncCtx->pSvcParam->iMinQp,
|
|
|
|
|
pEncCtx->pSvcParam->iMaxQp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RcCalculateIdrQp (sWelsEncCtx* pEncCtx) {
|
|
|
|
@ -429,12 +432,21 @@ void RcCalculateIdrQp (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
pWelsSvcRc->iIntraComplexity = pWelsSvcRc->iIntraComplexity * pWelsSvcRc->iNumberMbFrame /
|
|
|
|
|
pWelsSvcRc->iIntraMbCount;
|
|
|
|
|
}
|
|
|
|
|
pWelsSvcRc->iInitialQp = RcConvertQStep2Qp (WELS_DIV_ROUND (pWelsSvcRc->iIntraComplexity,
|
|
|
|
|
pWelsSvcRc->iTargetBits));
|
|
|
|
|
|
|
|
|
|
int64_t iCmplxRatio = WELS_DIV_ROUND64 (pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity * INT_MULTIPLY,
|
|
|
|
|
pWelsSvcRc->iIntraComplxMean);
|
|
|
|
|
iCmplxRatio = WELS_CLIP3 (iCmplxRatio, INT_MULTIPLY - FRAME_CMPLX_RATIO_RANGE, INT_MULTIPLY + FRAME_CMPLX_RATIO_RANGE);
|
|
|
|
|
pWelsSvcRc->iQStep = WELS_DIV_ROUND ((pWelsSvcRc->iIntraComplexity * iCmplxRatio),
|
|
|
|
|
(pWelsSvcRc->iTargetBits * INT_MULTIPLY));
|
|
|
|
|
pWelsSvcRc->iInitialQp = RcConvertQStep2Qp (pWelsSvcRc->iQStep);
|
|
|
|
|
pWelsSvcRc->iInitialQp = WELS_CLIP3 (pWelsSvcRc->iInitialQp, pEncCtx->pSvcParam->iMinQp, pEncCtx->pSvcParam->iMaxQp);
|
|
|
|
|
pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp;
|
|
|
|
|
pWelsSvcRc->iQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp);
|
|
|
|
|
pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp;
|
|
|
|
|
pWelsSvcRc->iMinFrameQp = WELS_CLIP3 (pEncCtx->iGlobalQp - DELTA_QP_BGD_THD, pEncCtx->pSvcParam->iMinQp,
|
|
|
|
|
pEncCtx->pSvcParam->iMaxQp);
|
|
|
|
|
pWelsSvcRc->iMaxFrameQp = WELS_CLIP3 (pEncCtx->iGlobalQp + DELTA_QP_BGD_THD, pEncCtx->pSvcParam->iMinQp,
|
|
|
|
|
pEncCtx->pSvcParam->iMaxQp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -443,36 +455,22 @@ void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
int32_t iTl = pEncCtx->uiTemporalId;
|
|
|
|
|
SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[iTl];
|
|
|
|
|
int32_t iLumaQp = 0;
|
|
|
|
|
|
|
|
|
|
int32_t iDeltaQpTemporal = 0;
|
|
|
|
|
if (0 == pTOverRc->iPFrameNum) {
|
|
|
|
|
iLumaQp = pWelsSvcRc->iInitialQp;
|
|
|
|
|
} else if (pWelsSvcRc->iCurrentBitsLevel == BITS_EXCEEDED) {
|
|
|
|
|
iLumaQp = MAX_LOW_BR_QP;
|
|
|
|
|
iLumaQp = pWelsSvcRc->iLastCalculatedQScale + DELTA_QP_BGD_THD;
|
|
|
|
|
//limit QP
|
|
|
|
|
int32_t iLastIdxCodecInVGop = pWelsSvcRc->iFrameCodedInVGop - 1;
|
|
|
|
|
if (iLastIdxCodecInVGop < 0)
|
|
|
|
|
iLastIdxCodecInVGop += VGOP_SIZE;
|
|
|
|
|
int32_t iTlLast = pWelsSvcRc->iTlOfFrames[iLastIdxCodecInVGop];
|
|
|
|
|
int32_t iDeltaQpTemporal = iTl - iTlLast;
|
|
|
|
|
iDeltaQpTemporal = iTl - iTlLast;
|
|
|
|
|
if (0 == iTlLast && iTl > 0)
|
|
|
|
|
iDeltaQpTemporal += 3;
|
|
|
|
|
iDeltaQpTemporal += 1;
|
|
|
|
|
else if (0 == iTl && iTlLast > 0)
|
|
|
|
|
iDeltaQpTemporal -= 3;
|
|
|
|
|
iDeltaQpTemporal -= 1;
|
|
|
|
|
|
|
|
|
|
iLumaQp = WELS_CLIP3 (iLumaQp,
|
|
|
|
|
pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower + iDeltaQpTemporal,
|
|
|
|
|
pWelsSvcRc->iLastCalculatedQScale + pWelsSvcRc->iFrameDeltaQpUpper + iDeltaQpTemporal);
|
|
|
|
|
iLumaQp = WELS_CLIP3 (iLumaQp, pTOverRc->iMinQp, pTOverRc->iMaxQp);
|
|
|
|
|
|
|
|
|
|
if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) {
|
|
|
|
|
iLumaQp = WELS_CLIP3 ((iLumaQp * INT_MULTIPLY - pEncCtx->pVaa->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp) /
|
|
|
|
|
INT_MULTIPLY, pTOverRc->iMinQp, pTOverRc->iMaxQp);
|
|
|
|
|
}
|
|
|
|
|
pWelsSvcRc->iQStep = RcConvertQp2QStep (iLumaQp);
|
|
|
|
|
pWelsSvcRc->iLastCalculatedQScale = iLumaQp;
|
|
|
|
|
pEncCtx->iGlobalQp = iLumaQp;
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
int64_t iCmplxRatio = WELS_DIV_ROUND64 (pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity * INT_MULTIPLY,
|
|
|
|
|
pTOverRc->iFrameCmplxMean);
|
|
|
|
@ -480,7 +478,9 @@ void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iQStep = WELS_DIV_ROUND ((pTOverRc->iLinearCmplx * iCmplxRatio), (pWelsSvcRc->iTargetBits * INT_MULTIPLY));
|
|
|
|
|
iLumaQp = RcConvertQStep2Qp (pWelsSvcRc->iQStep);
|
|
|
|
|
|
|
|
|
|
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
|
|
|
|
|
"iCmplxRatio = %d,frameComplexity = %lld,iFrameCmplxMean = %d,iQStep = %d,iLumaQp = %d", (int)iCmplxRatio,
|
|
|
|
|
pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity, pTOverRc->iFrameCmplxMean, pWelsSvcRc->iQStep, iLumaQp);
|
|
|
|
|
//limit QP
|
|
|
|
|
int32_t iLastIdxCodecInVGop = pWelsSvcRc->iFrameCodedInVGop - 1;
|
|
|
|
|
if (iLastIdxCodecInVGop < 0)
|
|
|
|
@ -488,21 +488,22 @@ void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
int32_t iTlLast = pWelsSvcRc->iTlOfFrames[iLastIdxCodecInVGop];
|
|
|
|
|
int32_t iDeltaQpTemporal = iTl - iTlLast;
|
|
|
|
|
if (0 == iTlLast && iTl > 0)
|
|
|
|
|
iDeltaQpTemporal += 3;
|
|
|
|
|
iDeltaQpTemporal += 1;
|
|
|
|
|
else if (0 == iTl && iTlLast > 0)
|
|
|
|
|
iDeltaQpTemporal -= 3;
|
|
|
|
|
|
|
|
|
|
iLumaQp = WELS_CLIP3 (iLumaQp,
|
|
|
|
|
pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower + iDeltaQpTemporal,
|
|
|
|
|
pWelsSvcRc->iLastCalculatedQScale + pWelsSvcRc->iFrameDeltaQpUpper + iDeltaQpTemporal);
|
|
|
|
|
iDeltaQpTemporal -= 1;
|
|
|
|
|
}
|
|
|
|
|
pWelsSvcRc->iMinFrameQp = WELS_CLIP3 (pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower +
|
|
|
|
|
iDeltaQpTemporal, pTOverRc->iMinQp, pTOverRc->iMaxQp) ;
|
|
|
|
|
pWelsSvcRc->iMaxFrameQp = WELS_CLIP3 (pWelsSvcRc->iLastCalculatedQScale + pWelsSvcRc->iFrameDeltaQpUpper +
|
|
|
|
|
iDeltaQpTemporal, pTOverRc->iMinQp, pTOverRc->iMaxQp);
|
|
|
|
|
|
|
|
|
|
iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iMinFrameQp, pWelsSvcRc->iMaxFrameQp);
|
|
|
|
|
|
|
|
|
|
iLumaQp = WELS_CLIP3 (iLumaQp, pTOverRc->iMinQp, pTOverRc->iMaxQp);
|
|
|
|
|
if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) {
|
|
|
|
|
|
|
|
|
|
iLumaQp = WELS_DIV_ROUND (iLumaQp * INT_MULTIPLY - pEncCtx->pVaa->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp,
|
|
|
|
|
INT_MULTIPLY);
|
|
|
|
|
iLumaQp = WELS_CLIP3 (iLumaQp, pTOverRc->iMinQp, pTOverRc->iMaxQp);
|
|
|
|
|
iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iMinFrameQp, pWelsSvcRc->iMaxFrameQp);
|
|
|
|
|
}
|
|
|
|
|
pWelsSvcRc->iQStep = RcConvertQp2QStep (iLumaQp);
|
|
|
|
|
pWelsSvcRc->iLastCalculatedQScale = iLumaQp;
|
|
|
|
@ -554,6 +555,57 @@ void RcDecideTargetBits (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
pWelsSvcRc->iRemainingWeights -= pTOverRc->iTlayerWeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RcDecideTargetBitsTimestamp (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
//decide one frame bits allocated
|
|
|
|
|
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
|
|
|
|
|
SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId];
|
|
|
|
|
int32_t iTl = pEncCtx->uiTemporalId;
|
|
|
|
|
SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[iTl];
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iCurrentBitsLevel = BITS_NORMAL;
|
|
|
|
|
if (pEncCtx->eSliceType == I_SLICE) {
|
|
|
|
|
int32_t iBufferTh = static_cast<int32_t> (pWelsSvcRc->iBufferSizeSkip - pWelsSvcRc->iBufferFullnessSkip);
|
|
|
|
|
if (iBufferTh <= 0) {
|
|
|
|
|
pWelsSvcRc->iCurrentBitsLevel = BITS_EXCEEDED;
|
|
|
|
|
pWelsSvcRc->iTargetBits = pTOverRc->iMinBitsTl;
|
|
|
|
|
} else {
|
|
|
|
|
int32_t iMaxTh = iBufferTh * 3 / 4;
|
|
|
|
|
int32_t iMinTh = static_cast<int32_t> (iBufferTh * 2 / pDLayerParam->fFrameRate);
|
|
|
|
|
pWelsSvcRc->iTargetBits = static_cast<int32_t> (((double) (pDLayerParam->iSpatialBitrate) / (double) (
|
|
|
|
|
pDLayerParam->fFrameRate) * IDR_BITRATE_RATIO));
|
|
|
|
|
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
|
|
|
|
|
"iMaxTh = %d,iMinTh = %d,pWelsSvcRc->iTargetBits = %d,pWelsSvcRc->iBufferSizeSkip = %d, pWelsSvcRc->iBufferFullnessSkip= %"
|
|
|
|
|
PRId64 ,
|
|
|
|
|
iMaxTh, iMinTh, pWelsSvcRc->iTargetBits, pWelsSvcRc->iBufferSizeSkip, pWelsSvcRc->iBufferFullnessSkip);
|
|
|
|
|
pWelsSvcRc->iTargetBits = WELS_CLIP3 (pWelsSvcRc->iTargetBits, iMinTh, iMaxTh);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
int32_t iBufferTh = static_cast<int32_t> (pWelsSvcRc->iBufferSizeSkip - pWelsSvcRc->iBufferFullnessSkip);
|
|
|
|
|
if (iBufferTh <= 0) {
|
|
|
|
|
pWelsSvcRc->iCurrentBitsLevel = BITS_EXCEEDED;
|
|
|
|
|
pWelsSvcRc->iTargetBits = pTOverRc->iMinBitsTl;
|
|
|
|
|
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
|
|
|
|
|
"iMaxTh = %d,pWelsSvcRc->iTargetBits = %d,pWelsSvcRc->iBufferSizeSkip = %d, pWelsSvcRc->iBufferFullnessSkip= %" PRId64,
|
|
|
|
|
iBufferTh, pWelsSvcRc->iTargetBits, pWelsSvcRc->iBufferSizeSkip, pWelsSvcRc->iBufferFullnessSkip);
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];
|
|
|
|
|
const int32_t kiGopSize = (1 << pDLayerParamInternal->iDecompositionStages);
|
|
|
|
|
int32_t iAverageFrameSize = (int32_t) ((double) (pDLayerParam->iSpatialBitrate) / (double) (pDLayerParam->fFrameRate));
|
|
|
|
|
const int32_t kiGopBits = iAverageFrameSize * kiGopSize;
|
|
|
|
|
pWelsSvcRc->iTargetBits = WELS_DIV_ROUND (pTOverRc->iTlayerWeight * kiGopBits, INT_MULTIPLY * 10 * 2);
|
|
|
|
|
|
|
|
|
|
int32_t iMaxTh = iBufferTh / 2;
|
|
|
|
|
int32_t iMinTh = (int32_t) (iBufferTh * 2 / pDLayerParam->fFrameRate);
|
|
|
|
|
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
|
|
|
|
|
"iMaxTh = %d,iMinTh = %d,pWelsSvcRc->iTargetBits = %d,pWelsSvcRc->iBufferSizeSkip = %d, pWelsSvcRc->iBufferFullnessSkip= % "
|
|
|
|
|
PRId64,
|
|
|
|
|
iMaxTh, iMinTh, pWelsSvcRc->iTargetBits, pWelsSvcRc->iBufferSizeSkip, pWelsSvcRc->iBufferFullnessSkip);
|
|
|
|
|
pWelsSvcRc->iTargetBits = WELS_CLIP3 (pWelsSvcRc->iTargetBits, iMinTh, iMaxTh);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RcInitGomParameters (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
SSlice* pSliceInLayer = pEncCtx->pCurDqLayer->sLayerInfo.pSliceInLayer;
|
|
|
|
@ -563,8 +615,6 @@ void RcInitGomParameters (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
const int32_t kiGlobalQp = pEncCtx->iGlobalQp;
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iAverageFrameQp = 0;
|
|
|
|
|
pWelsSvcRc->iMinFrameQp = 51;
|
|
|
|
|
pWelsSvcRc->iMaxFrameQp = 0;
|
|
|
|
|
for (int32_t i = 0; i < kiSliceNum; ++i) {
|
|
|
|
|
pSOverRc = &pSliceInLayer[i].sSlicingOverRc;
|
|
|
|
|
pSOverRc->iComplexityIndexSlice = 0;
|
|
|
|
@ -581,11 +631,11 @@ void RcCalculateMbQp (sWelsEncCtx* pEncCtx, SMB* pCurMb, const int32_t kiSliceId
|
|
|
|
|
|
|
|
|
|
int32_t iLumaQp = pSOverRc->iCalculatedQpSlice;
|
|
|
|
|
SDqLayer* pCurLayer = pEncCtx->pCurDqLayer;
|
|
|
|
|
SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[pEncCtx->uiTemporalId];
|
|
|
|
|
const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
|
|
|
|
|
if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) {
|
|
|
|
|
iLumaQp = (int8_t)WELS_CLIP3 (iLumaQp +
|
|
|
|
|
pEncCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp[pCurMb->iMbXY], pTOverRc->iMinQp, pTOverRc->iMaxQp);
|
|
|
|
|
pEncCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp[pCurMb->iMbXY], pWelsSvcRc->iMinFrameQp,
|
|
|
|
|
pWelsSvcRc->iMaxFrameQp);
|
|
|
|
|
}
|
|
|
|
|
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (iLumaQp + kuiChromaQpIndexOffset)];
|
|
|
|
|
pCurMb->uiLumaQp = iLumaQp;
|
|
|
|
@ -637,15 +687,15 @@ void RcGomTargetBits (sWelsEncCtx* pEncCtx, const int32_t kiSliceId) {
|
|
|
|
|
} else {
|
|
|
|
|
pWelsSvcRc_Base = RcJudgeBaseUsability (pEncCtx);
|
|
|
|
|
pWelsSvcRc_Base = (pWelsSvcRc_Base) ? pWelsSvcRc_Base : pWelsSvcRc;
|
|
|
|
|
for (i = kiComplexityIndex; i <= iLastGomIndex; i++) {
|
|
|
|
|
for (i = kiComplexityIndex + 1; i <= iLastGomIndex; i++) {
|
|
|
|
|
iSumSad += pWelsSvcRc_Base->pCurrentFrameGomSad[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (0 == iSumSad)
|
|
|
|
|
iAllocateBits = WELS_DIV_ROUND (iLeftBits, (iLastGomIndex - kiComplexityIndex));
|
|
|
|
|
else
|
|
|
|
|
iAllocateBits = WELS_DIV_ROUND ((int64_t)iLeftBits * pWelsSvcRc_Base->pCurrentFrameGomSad[kiComplexityIndex + 1],
|
|
|
|
|
iSumSad);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
pSOverRc->iGomTargetBits = iAllocateBits;
|
|
|
|
|
}
|
|
|
|
@ -660,7 +710,6 @@ void RcCalculateGomQp (sWelsEncCtx* pEncCtx, SMB* pCurMb, int32_t iSliceId) {
|
|
|
|
|
|
|
|
|
|
int64_t iLeftBits = pSOverRc->iTargetBitsSlice - pSOverRc->iFrameBitsSlice;
|
|
|
|
|
int64_t iTargetLeftBits = iLeftBits + pSOverRc->iGomBitsSlice - pSOverRc->iGomTargetBits;
|
|
|
|
|
|
|
|
|
|
if ((iLeftBits <= 0) || (iTargetLeftBits <= 0)) {
|
|
|
|
|
pSOverRc->iCalculatedQpSlice += 2;
|
|
|
|
|
} else {
|
|
|
|
@ -675,8 +724,9 @@ void RcCalculateGomQp (sWelsEncCtx* pEncCtx, SMB* pCurMb, int32_t iSliceId) {
|
|
|
|
|
else if (iBitsRatio > 11900) //2^(1.5/6)*10000
|
|
|
|
|
pSOverRc->iCalculatedQpSlice -= 2;
|
|
|
|
|
}
|
|
|
|
|
pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp);
|
|
|
|
|
|
|
|
|
|
pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, pWelsSvcRc->iMinFrameQp,
|
|
|
|
|
pWelsSvcRc->iMaxFrameQp);
|
|
|
|
|
// WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,"iCalculatedQpSlice =%d,iBitsRatio = %d\n",pSOverRc->iCalculatedQpSlice,iBitsRatio);
|
|
|
|
|
pSOverRc->iGomBitsSlice = 0;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
@ -707,6 +757,9 @@ void RcVBufferCalculationSkip (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
|| (dIncPercent > pWelsSvcRc->iRcVaryPercentage)) {
|
|
|
|
|
pWelsSvcRc->bSkipFlag = true;
|
|
|
|
|
}
|
|
|
|
|
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
|
|
|
|
|
"[Rc] VBV_Skip,dIncPercent = %f,iRcVaryPercentage = %d,pWelsSvcRc->bSkipFlag = %d", dIncPercent,
|
|
|
|
|
pWelsSvcRc->iRcVaryPercentage, pWelsSvcRc->bSkipFlag);
|
|
|
|
|
}
|
|
|
|
|
void CheckFrameSkipBasedMaxbr (sWelsEncCtx* pEncCtx, const long long uiTimeStamp, int32_t iDidIdx) {
|
|
|
|
|
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[iDidIdx];
|
|
|
|
@ -769,7 +822,7 @@ void CheckFrameSkipBasedMaxbr (sWelsEncCtx* pEncCtx, const long long uiTimeStamp
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WelsRcCheckFrameStatus (sWelsEncCtx* pEncCtx, long long uiTimeStamp, int32_t iSpatialNum,int32_t iCurDid) {
|
|
|
|
|
bool WelsRcCheckFrameStatus (sWelsEncCtx* pEncCtx, long long uiTimeStamp, int32_t iSpatialNum, int32_t iCurDid) {
|
|
|
|
|
|
|
|
|
|
bool bSkipMustFlag = false;
|
|
|
|
|
|
|
|
|
@ -787,7 +840,7 @@ bool WelsRcCheckFrameStatus (sWelsEncCtx* pEncCtx, long long uiTimeStamp, int32_
|
|
|
|
|
}
|
|
|
|
|
//check max_br skip
|
|
|
|
|
if (pEncCtx->pFuncList->pfRc.pfWelsCheckSkipBasedMaxbr) {
|
|
|
|
|
if ((!bSkipMustFlag)&&(pEncCtx->pSvcParam->sSpatialLayers[iDidIdx].iMaxSpatialBitrate != UNSPECIFIED_BIT_RATE)) {
|
|
|
|
|
if ((!bSkipMustFlag) && (pEncCtx->pSvcParam->sSpatialLayers[iDidIdx].iMaxSpatialBitrate != UNSPECIFIED_BIT_RATE)) {
|
|
|
|
|
pEncCtx->pFuncList->pfRc.pfWelsCheckSkipBasedMaxbr (pEncCtx, uiTimeStamp, iDidIdx);
|
|
|
|
|
if (true == pEncCtx->pWelsSvcRc[iDidIdx].bSkipFlag) {
|
|
|
|
|
bSkipMustFlag = true;
|
|
|
|
@ -810,11 +863,11 @@ bool WelsRcCheckFrameStatus (sWelsEncCtx* pEncCtx, long long uiTimeStamp, int32_
|
|
|
|
|
pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge (pEncCtx, uiTimeStamp, iDidIdx);
|
|
|
|
|
}
|
|
|
|
|
if (true == pEncCtx->pWelsSvcRc[iDidIdx].bSkipFlag) {
|
|
|
|
|
bSkipMustFlag = true;
|
|
|
|
|
bSkipMustFlag = true;
|
|
|
|
|
}
|
|
|
|
|
//check max_br skip
|
|
|
|
|
if (pEncCtx->pFuncList->pfRc.pfWelsCheckSkipBasedMaxbr) {
|
|
|
|
|
if ((!bSkipMustFlag)&&(pEncCtx->pSvcParam->sSpatialLayers[iDidIdx].iMaxSpatialBitrate != UNSPECIFIED_BIT_RATE)) {
|
|
|
|
|
if ((!bSkipMustFlag) && (pEncCtx->pSvcParam->sSpatialLayers[iDidIdx].iMaxSpatialBitrate != UNSPECIFIED_BIT_RATE)) {
|
|
|
|
|
pEncCtx->pFuncList->pfRc.pfWelsCheckSkipBasedMaxbr (pEncCtx, uiTimeStamp, iDidIdx);
|
|
|
|
|
if (true == pEncCtx->pWelsSvcRc[iDidIdx].bSkipFlag) {
|
|
|
|
|
bSkipMustFlag = true;
|
|
|
|
@ -847,7 +900,7 @@ void UpdateBufferWhenFrameSkipped (sWelsEncCtx* pEncCtx, int32_t iCurDid) {
|
|
|
|
|
pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] -= kiOutputMaxBits;
|
|
|
|
|
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
|
|
|
|
|
"[Rc] iDid = %d,bits in buffer = %" PRId64 ", bits in Max bitrate buffer = %" PRId64,
|
|
|
|
|
iCurDid,pWelsSvcRc->iBufferFullnessSkip, pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW]);
|
|
|
|
|
iCurDid, pWelsSvcRc->iBufferFullnessSkip, pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW]);
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iBufferFullnessSkip = WELS_MAX (pWelsSvcRc->iBufferFullnessSkip, 0);
|
|
|
|
|
|
|
|
|
@ -859,7 +912,7 @@ void UpdateBufferWhenFrameSkipped (sWelsEncCtx* pEncCtx, int32_t iCurDid) {
|
|
|
|
|
//output a warning when iContinualSkipFrames is large enough, which may indicate subjective quality problem
|
|
|
|
|
//note that here iContinualSkipFrames must be >0, so the log output will be 3/6/....
|
|
|
|
|
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_WARNING, "[Rc] iDid = %d,iContinualSkipFrames(%d) is large",
|
|
|
|
|
iCurDid,pWelsSvcRc->iContinualSkipFrames);
|
|
|
|
|
iCurDid, pWelsSvcRc->iContinualSkipFrames);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void UpdateMaxBrCheckWindowStatus (sWelsEncCtx* pEncCtx, int32_t iSpatialNum, const long long uiTimeStamp) {
|
|
|
|
@ -992,10 +1045,22 @@ void RcUpdateIntraComplexity (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
if (iAlpha < (INT_MULTIPLY / 4)) iAlpha = INT_MULTIPLY / 4;
|
|
|
|
|
int32_t iQStep = RcConvertQp2QStep (pWelsSvcRc->iAverageFrameQp);
|
|
|
|
|
int64_t iIntraCmplx = iQStep * static_cast<int64_t> (pWelsSvcRc->iFrameDqBits);
|
|
|
|
|
pWelsSvcRc->iIntraComplexity = WELS_DIV_ROUND (((INT_MULTIPLY - iAlpha) * pWelsSvcRc->iIntraComplexity + iAlpha *
|
|
|
|
|
iIntraCmplx), INT_MULTIPLY);
|
|
|
|
|
pWelsSvcRc->iIntraMbCount = pWelsSvcRc->iNumberMbFrame;
|
|
|
|
|
if (pWelsSvcRc->iIdrNum == 0) {
|
|
|
|
|
pWelsSvcRc->iIntraComplexity = iIntraCmplx;
|
|
|
|
|
pWelsSvcRc->iIntraComplxMean = pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity;
|
|
|
|
|
} else {
|
|
|
|
|
pWelsSvcRc->iIntraComplexity = WELS_DIV_ROUND (((LINEAR_MODEL_DECAY_FACTOR) * pWelsSvcRc->iIntraComplexity +
|
|
|
|
|
(INT_MULTIPLY - LINEAR_MODEL_DECAY_FACTOR) *
|
|
|
|
|
iIntraCmplx), INT_MULTIPLY);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iIntraComplxMean = WELS_DIV_ROUND64 (((LINEAR_MODEL_DECAY_FACTOR) * static_cast<int64_t>
|
|
|
|
|
(pWelsSvcRc->iIntraComplxMean)
|
|
|
|
|
+ (INT_MULTIPLY - LINEAR_MODEL_DECAY_FACTOR) * (pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity)),
|
|
|
|
|
INT_MULTIPLY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iIntraMbCount = pWelsSvcRc->iNumberMbFrame;
|
|
|
|
|
pWelsSvcRc->iIdrNum++;
|
|
|
|
|
if (pWelsSvcRc->iIdrNum > 255)
|
|
|
|
|
pWelsSvcRc->iIdrNum = 255;
|
|
|
|
@ -1011,20 +1076,21 @@ void RcUpdateFrameComplexity (sWelsEncCtx* pEncCtx) {
|
|
|
|
|
SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[kiTl];
|
|
|
|
|
|
|
|
|
|
int32_t iQStep = RcConvertQp2QStep (pWelsSvcRc->iAverageFrameQp);
|
|
|
|
|
if (0 == pTOverRc->iPFrameNum) {
|
|
|
|
|
pTOverRc->iLinearCmplx = ((int64_t)pWelsSvcRc->iFrameDqBits) * iQStep;
|
|
|
|
|
} else {
|
|
|
|
|
pTOverRc->iLinearCmplx = WELS_DIV_ROUND64 ((LINEAR_MODEL_DECAY_FACTOR * (int64_t)pTOverRc->iLinearCmplx
|
|
|
|
|
+ (INT_MULTIPLY - LINEAR_MODEL_DECAY_FACTOR) * ((int64_t)pWelsSvcRc->iFrameDqBits * iQStep)),
|
|
|
|
|
INT_MULTIPLY);
|
|
|
|
|
}
|
|
|
|
|
int32_t iAlpha = WELS_DIV_ROUND (INT_MULTIPLY, (1 + pTOverRc->iPFrameNum));
|
|
|
|
|
if (iAlpha < SMOOTH_FACTOR_MIN_VALUE)
|
|
|
|
|
iAlpha = SMOOTH_FACTOR_MIN_VALUE;
|
|
|
|
|
pTOverRc->iFrameCmplxMean = WELS_DIV_ROUND ((LINEAR_MODEL_DECAY_FACTOR * static_cast<int64_t>
|
|
|
|
|
(pTOverRc->iFrameCmplxMean)
|
|
|
|
|
+ (INT_MULTIPLY - LINEAR_MODEL_DECAY_FACTOR) * pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity),
|
|
|
|
|
INT_MULTIPLY);
|
|
|
|
|
if (0 == pTOverRc->iPFrameNum) {
|
|
|
|
|
pTOverRc->iLinearCmplx = ((int64_t)pWelsSvcRc->iFrameDqBits) * iQStep;
|
|
|
|
|
pTOverRc->iFrameCmplxMean = (int32_t)pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity;
|
|
|
|
|
} else {
|
|
|
|
|
pTOverRc->iLinearCmplx = WELS_DIV_ROUND64 (((LINEAR_MODEL_DECAY_FACTOR) * (int64_t)pTOverRc->iLinearCmplx
|
|
|
|
|
+ (INT_MULTIPLY - LINEAR_MODEL_DECAY_FACTOR) * ((int64_t)pWelsSvcRc->iFrameDqBits * iQStep)),
|
|
|
|
|
INT_MULTIPLY);
|
|
|
|
|
pTOverRc->iFrameCmplxMean = WELS_DIV_ROUND (((LINEAR_MODEL_DECAY_FACTOR) * static_cast<int64_t>
|
|
|
|
|
(pTOverRc->iFrameCmplxMean)
|
|
|
|
|
+ (INT_MULTIPLY - LINEAR_MODEL_DECAY_FACTOR) * pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity),
|
|
|
|
|
INT_MULTIPLY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pTOverRc->iPFrameNum++;
|
|
|
|
@ -1066,7 +1132,19 @@ void WelsRcPictureInitGom (sWelsEncCtx* pEncCtx, long long uiTimeStamp) {
|
|
|
|
|
if (pEncCtx->uiTemporalId == 0) {
|
|
|
|
|
RcUpdateTemporalZero (pEncCtx);
|
|
|
|
|
}
|
|
|
|
|
RcDecideTargetBits (pEncCtx);
|
|
|
|
|
if (pEncCtx->pSvcParam->iRCMode == RC_TIMESTAMP_MODE) {
|
|
|
|
|
RcDecideTargetBitsTimestamp (pEncCtx);
|
|
|
|
|
pWelsSvcRc->uiLastTimeStamp = uiTimeStamp;
|
|
|
|
|
} else {
|
|
|
|
|
RcDecideTargetBits (pEncCtx);
|
|
|
|
|
}
|
|
|
|
|
//turn off GOM QP when slicenum is larger 1
|
|
|
|
|
if ((pWelsSvcRc->iSliceNum > 1) || ((pEncCtx->pSvcParam->iRCMode == RC_BITRATE_MODE)
|
|
|
|
|
&& (pEncCtx->eSliceType == I_SLICE))) {
|
|
|
|
|
pWelsSvcRc->bEnableGomQp = false;
|
|
|
|
|
} else
|
|
|
|
|
pWelsSvcRc->bEnableGomQp = true;
|
|
|
|
|
|
|
|
|
|
//decide globe_qp
|
|
|
|
|
if (pEncCtx->eSliceType == I_SLICE) {
|
|
|
|
|
if (0 == pWelsSvcRc->iIdrNum)
|
|
|
|
@ -1079,7 +1157,6 @@ void WelsRcPictureInitGom (sWelsEncCtx* pEncCtx, long long uiTimeStamp) {
|
|
|
|
|
}
|
|
|
|
|
RcInitSliceInformation (pEncCtx);
|
|
|
|
|
RcInitGomParameters (pEncCtx);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WelsRcPictureInfoUpdateGom (sWelsEncCtx* pEncCtx, int32_t iLayerSize) {
|
|
|
|
@ -1114,21 +1191,22 @@ void WelsRcMbInitGom (sWelsEncCtx* pEncCtx, SMB* pCurMb, SSlice* pSlice) {
|
|
|
|
|
const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;
|
|
|
|
|
|
|
|
|
|
pSOverRc->iBsPosSlice = pEncCtx->pFuncList->pfGetBsPosition (pSlice);
|
|
|
|
|
if ((pEncCtx->pSvcParam->iRCMode == RC_BITRATE_MODE) && (pEncCtx->eSliceType == I_SLICE)) {
|
|
|
|
|
if (pWelsSvcRc->bEnableGomQp) {
|
|
|
|
|
//calculate gom qp and target bits at the beginning of gom
|
|
|
|
|
if (0 == (pCurMb->iMbXY % pWelsSvcRc->iNumberMbGom)) {
|
|
|
|
|
if (pCurMb->iMbXY != pSOverRc->iStartMbSlice) {
|
|
|
|
|
pSOverRc->iComplexityIndexSlice++;
|
|
|
|
|
RcCalculateGomQp (pEncCtx, pCurMb, kiSliceId);
|
|
|
|
|
}
|
|
|
|
|
RcGomTargetBits (pEncCtx, kiSliceId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RcCalculateMbQp (pEncCtx, pCurMb, kiSliceId);
|
|
|
|
|
} else {
|
|
|
|
|
pCurMb->uiLumaQp = pEncCtx->iGlobalQp;
|
|
|
|
|
pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
//calculate gom qp and target bits at the beginning of gom
|
|
|
|
|
if (0 == (pCurMb->iMbXY % pWelsSvcRc->iNumberMbGom)) {
|
|
|
|
|
if (pCurMb->iMbXY != pSOverRc->iStartMbSlice) {
|
|
|
|
|
pSOverRc->iComplexityIndexSlice++;
|
|
|
|
|
RcCalculateGomQp (pEncCtx, pCurMb, kiSliceId);
|
|
|
|
|
}
|
|
|
|
|
RcGomTargetBits (pEncCtx, kiSliceId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RcCalculateMbQp (pEncCtx, pCurMb, kiSliceId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WelsRcMbInfoUpdateGom (sWelsEncCtx* pEncCtx, SMB* pCurMb, int32_t iCostLuma, SSlice* pSlice) {
|
|
|
|
@ -1144,9 +1222,6 @@ void WelsRcMbInfoUpdateGom (sWelsEncCtx* pEncCtx, SMB* pCurMb, int32_t iCostLuma
|
|
|
|
|
pSOverRc->iGomBitsSlice += iCurMbBits;
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->pGomCost[kiComplexityIndex] += iCostLuma;
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iMinFrameQp = WELS_MIN (pWelsSvcRc->iMinFrameQp, pCurMb->uiLumaQp);
|
|
|
|
|
pWelsSvcRc->iMaxFrameQp = WELS_MAX (pWelsSvcRc->iMaxFrameQp, pCurMb->uiLumaQp);
|
|
|
|
|
if (iCurMbBits > 0) {
|
|
|
|
|
pSOverRc->iTotalQpSlice += pCurMb->uiLumaQp;
|
|
|
|
|
pSOverRc->iTotalMbSlice++;
|
|
|
|
@ -1326,7 +1401,8 @@ void WelsRcFrameDelayJudgeTimeStamp (sWelsEncCtx* pEncCtx, long long uiTimeStamp
|
|
|
|
|
pWelsSvcRc->iBufferSizePadding = WELS_DIV_ROUND (pDLayerConfig->iSpatialBitrate * PADDING_BUFFER_RATIO, INT_MULTIPLY);
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iBufferFullnessSkip -= iSentBits;
|
|
|
|
|
pWelsSvcRc->iBufferFullnessSkip = WELS_MAX (0, pWelsSvcRc->iBufferFullnessSkip);
|
|
|
|
|
pWelsSvcRc->iBufferFullnessSkip = WELS_MAX ((-1) * (pDLayerConfig->iSpatialBitrate / 4),
|
|
|
|
|
pWelsSvcRc->iBufferFullnessSkip);
|
|
|
|
|
|
|
|
|
|
if (pEncCtx->pSvcParam->bEnableFrameSkip) {
|
|
|
|
|
pWelsSvcRc->bSkipFlag = true;
|
|
|
|
@ -1340,121 +1416,10 @@ void WelsRcFrameDelayJudgeTimeStamp (sWelsEncCtx* pEncCtx, long long uiTimeStamp
|
|
|
|
|
}
|
|
|
|
|
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
|
|
|
|
|
"WelsRcFrameDelayJudgeTimeStamp iDidIdx = %d,iSkipFrameNum = %d,buffer = %" PRId64
|
|
|
|
|
",threadhold = %d,bitrate = %d,iSentBits = %d,lasttimestamp = %lld,timestamp=%lld\n", iDidIdx,
|
|
|
|
|
",threadhold = %d,bitrate = %d,iSentBits = %d,lasttimestamp = %lld,timestamp=%lld", iDidIdx,
|
|
|
|
|
pWelsSvcRc->iSkipFrameNum, pWelsSvcRc->iBufferFullnessSkip, pWelsSvcRc->iBufferSizeSkip, iBitRate, iSentBits,
|
|
|
|
|
pWelsSvcRc->uiLastTimeStamp, uiTimeStamp);
|
|
|
|
|
}
|
|
|
|
|
void WelsRcPictureInitGomTimeStamp (sWelsEncCtx* pEncCtx, long long uiTimeStamp) {
|
|
|
|
|
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
|
|
|
|
|
SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId];
|
|
|
|
|
int32_t iLumaQp = pWelsSvcRc->iLastCalculatedQScale;
|
|
|
|
|
int32_t iTl = pEncCtx->uiTemporalId;
|
|
|
|
|
SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[iTl];
|
|
|
|
|
if (pEncCtx->eSliceType == I_SLICE) {
|
|
|
|
|
if (0 == pWelsSvcRc->iIdrNum) { //iIdrNum == 0 means encoder has been initialed
|
|
|
|
|
RcInitRefreshParameter (pEncCtx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (RcJudgeBitrateFpsUpdate (pEncCtx)) {
|
|
|
|
|
RcUpdateBitrateFps (pEncCtx);
|
|
|
|
|
}
|
|
|
|
|
if (pEncCtx->uiTemporalId == 0) {
|
|
|
|
|
RcUpdateTemporalZero (pEncCtx);
|
|
|
|
|
}
|
|
|
|
|
//decide one frame bits allocated
|
|
|
|
|
if (pEncCtx->eSliceType == I_SLICE) {
|
|
|
|
|
if (0 == pWelsSvcRc->iIdrNum) { //iIdrNum == 0 means encoder has been initialed
|
|
|
|
|
RcInitIdrQp (pEncCtx);
|
|
|
|
|
iLumaQp = pWelsSvcRc->iInitialQp;
|
|
|
|
|
pWelsSvcRc->iTargetBits = static_cast<int32_t> (((double) (pDLayerParam->iSpatialBitrate) / (double) (
|
|
|
|
|
pDLayerParam->fFrameRate) *
|
|
|
|
|
IDR_BITRATE_RATIO));
|
|
|
|
|
|
|
|
|
|
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
|
|
|
|
|
"[Rc] First IDR iSpatialBitrate = %d,iBufferFullnessSkip = %" PRId64 ",iTargetBits= %d,initQp = %d",
|
|
|
|
|
pDLayerParam->iSpatialBitrate, pWelsSvcRc->iBufferFullnessSkip, pWelsSvcRc->iTargetBits,
|
|
|
|
|
pWelsSvcRc->iInitialQp);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
int32_t iMaxTh = static_cast<int32_t> (pWelsSvcRc->iBufferSizeSkip - pWelsSvcRc->iBufferFullnessSkip);
|
|
|
|
|
int32_t iMinTh = iMaxTh / 2;
|
|
|
|
|
pWelsSvcRc->iTargetBits = static_cast<int32_t> (((double) (pDLayerParam->iSpatialBitrate) / (double) (
|
|
|
|
|
pDLayerParam->fFrameRate) *
|
|
|
|
|
IDR_BITRATE_RATIO));
|
|
|
|
|
if (iMaxTh > 0) {
|
|
|
|
|
pWelsSvcRc->iTargetBits = WELS_CLIP3 (pWelsSvcRc->iTargetBits, iMinTh, iMaxTh);
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iQStep = WELS_DIV_ROUND (pWelsSvcRc->iIntraComplexity, pWelsSvcRc->iTargetBits);
|
|
|
|
|
iLumaQp = RcConvertQStep2Qp (pWelsSvcRc->iQStep);
|
|
|
|
|
|
|
|
|
|
iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iLastCalculatedQScale - DELTA_QP_BGD_THD,
|
|
|
|
|
pWelsSvcRc->iLastCalculatedQScale + DELTA_QP_BGD_THD);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
iLumaQp = pEncCtx->iGlobalQp + DELTA_QP_BGD_THD;
|
|
|
|
|
}
|
|
|
|
|
iLumaQp = WELS_CLIP3 (iLumaQp, pTOverRc->iMinQp, pTOverRc->iMaxQp);
|
|
|
|
|
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
|
|
|
|
|
"[Rc]I iLumaQp = %d,iQStep = %d,iTargetBits = %d,iBufferFullnessSkip =%" PRId64
|
|
|
|
|
",iMaxTh=%d,iMinTh = %d,iFrameComplexity= %" PRId64,
|
|
|
|
|
iLumaQp, pWelsSvcRc->iQStep, pWelsSvcRc->iTargetBits, pWelsSvcRc->iBufferFullnessSkip, iMaxTh, iMinTh,
|
|
|
|
|
pWelsSvcRc->iIntraComplexity);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
int32_t iMaxTh = static_cast<int32_t> (pWelsSvcRc->iBufferSizeSkip - pWelsSvcRc->iBufferFullnessSkip);
|
|
|
|
|
int32_t iMinTh = iMaxTh / (iTl + 2);
|
|
|
|
|
|
|
|
|
|
SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];
|
|
|
|
|
const int32_t kiGopSize = (1 << pDLayerParamInternal->iDecompositionStages);
|
|
|
|
|
int32_t iAverageFrameSize = (int32_t) ((double) (pDLayerParam->iSpatialBitrate) / (double) (pDLayerParam->fFrameRate));
|
|
|
|
|
const int32_t kiGopBits = iAverageFrameSize * kiGopSize;
|
|
|
|
|
int64_t iCmplxRatio = WELS_DIV_ROUND64 (pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity * INT_MULTIPLY,
|
|
|
|
|
pTOverRc->iFrameCmplxMean);
|
|
|
|
|
iCmplxRatio = WELS_CLIP3 (iCmplxRatio, INT_MULTIPLY - FRAME_CMPLX_RATIO_RANGE, INT_MULTIPLY + FRAME_CMPLX_RATIO_RANGE);
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iTargetBits = WELS_DIV_ROUND (pTOverRc->iTlayerWeight * kiGopBits, INT_MULTIPLY * 10 * 2);
|
|
|
|
|
if (iMaxTh > 0) {
|
|
|
|
|
pWelsSvcRc->iTargetBits = WELS_CLIP3 (pWelsSvcRc->iTargetBits, iMinTh, iMaxTh);
|
|
|
|
|
if (0 == pTOverRc->iPFrameNum)
|
|
|
|
|
iLumaQp = pWelsSvcRc->iInitialQp + DELTA_QP_BGD_THD;
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iQStep = WELS_DIV_ROUND ((pTOverRc->iLinearCmplx * iCmplxRatio), (pWelsSvcRc->iTargetBits * INT_MULTIPLY));
|
|
|
|
|
iLumaQp = RcConvertQStep2Qp (pWelsSvcRc->iQStep);
|
|
|
|
|
iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iLastCalculatedQScale - DELTA_QP_BGD_THD,
|
|
|
|
|
pWelsSvcRc->iLastCalculatedQScale + DELTA_QP_BGD_THD);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
iLumaQp = pEncCtx->iGlobalQp + DELTA_QP_BGD_THD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
iLumaQp = WELS_CLIP3 (iLumaQp, pTOverRc->iMinQp, pTOverRc->iMaxQp);
|
|
|
|
|
|
|
|
|
|
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
|
|
|
|
|
"[Rc]P iTl = %d,iLumaQp = %d,iQStep = %d,iTargetBits = %d,iBufferFullnessSkip =%" PRId64
|
|
|
|
|
",iMaxTh=%d,iMinTh = %d,iFrameComplexity= %lld,iCmplxRatio=%" PRId64,
|
|
|
|
|
iTl, iLumaQp, pWelsSvcRc->iQStep, pWelsSvcRc->iTargetBits, pWelsSvcRc->iBufferFullnessSkip, iMaxTh, iMinTh,
|
|
|
|
|
pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity, iCmplxRatio);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pWelsSvcRc->iQStep = RcConvertQp2QStep (iLumaQp);
|
|
|
|
|
pWelsSvcRc->iLastCalculatedQScale = iLumaQp;
|
|
|
|
|
pEncCtx->iGlobalQp = iLumaQp;
|
|
|
|
|
|
|
|
|
|
RcInitSliceInformation (pEncCtx);
|
|
|
|
|
RcInitGomParameters (pEncCtx);
|
|
|
|
|
float fInstantFps = (uiTimeStamp - pWelsSvcRc->uiLastTimeStamp) > 0 ? (1000.0f / (uiTimeStamp -
|
|
|
|
|
pWelsSvcRc->uiLastTimeStamp)) : 0;
|
|
|
|
|
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
|
|
|
|
|
"[Rc]Tid = %d,Did = %d,pEncCtx->iGlobalQp= %d,iLumaQp = %d,uiTimeStamp = %lld,uiLastTimeStamp = %lld,InstantFps = %f,settingFps = %f",
|
|
|
|
|
pEncCtx->uiTemporalId, pEncCtx->uiDependencyId,
|
|
|
|
|
pEncCtx->iGlobalQp, iLumaQp, uiTimeStamp, pWelsSvcRc->uiLastTimeStamp,
|
|
|
|
|
fInstantFps, pDLayerParam->fFrameRate);
|
|
|
|
|
pWelsSvcRc->uiLastTimeStamp = uiTimeStamp;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WelsRcPictureInfoUpdateGomTimeStamp (sWelsEncCtx* pEncCtx, int32_t iLayerSize) {
|
|
|
|
|
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
|
|
|
|
@ -1531,7 +1496,7 @@ void WelsRcInitFuncPointers (sWelsEncCtx* pEncCtx, RC_MODES iRcMode) {
|
|
|
|
|
pRcf->pfWelsRcMbInfoUpdate = WelsRcMbInfoUpdateDisable;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
pRcf->pfWelsRcPictureInit = WelsRcPictureInitGomTimeStamp;
|
|
|
|
|
pRcf->pfWelsRcPictureInit = WelsRcPictureInitGom;
|
|
|
|
|
pRcf->pfWelsRcPictureInfoUpdate = WelsRcPictureInfoUpdateGomTimeStamp;
|
|
|
|
|
pRcf->pfWelsRcMbInit = WelsRcMbInitGom;
|
|
|
|
|
pRcf->pfWelsRcMbInfoUpdate = WelsRcMbInfoUpdateGom;
|
|
|
|
|