From b932547fe8c7c9c9ebcd4c7ad7bad9314d283ed4 Mon Sep 17 00:00:00 2001 From: ruil2 Date: Tue, 16 Dec 2014 15:16:09 +0800 Subject: [PATCH] astyle two files --- codec/encoder/core/src/encoder_ext.cpp | 41 +- codec/encoder/core/src/ratectl.cpp | 1392 ++++++++++++------------ 2 files changed, 726 insertions(+), 707 deletions(-) diff --git a/codec/encoder/core/src/encoder_ext.cpp b/codec/encoder/core/src/encoder_ext.cpp index cf1333fc..cee581bb 100644 --- a/codec/encoder/core/src/encoder_ext.cpp +++ b/codec/encoder/core/src/encoder_ext.cpp @@ -95,8 +95,8 @@ int32_t WelsBitRateVerification (SLogContext* pLogCtx, SSpatialLayerConfig* pLay pLayerParam->iMaxSpatialBitrate); } WelsLog (pLogCtx, WELS_LOG_INFO, - "Level is changed from (%d) to (%d) according to the maxbitrate", - iCurLevel, pLayerParam->uiLevelIdc); + "Level is changed from (%d) to (%d) according to the maxbitrate", + iCurLevel, pLayerParam->uiLevelIdc); } if (pLayerParam->iMaxSpatialBitrate < pLayerParam->iSpatialBitrate) { WelsLog (pLogCtx, WELS_LOG_ERROR, @@ -533,18 +533,19 @@ int32_t WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pPar } return ENC_RETURN_SUCCESS; } -int32_t WelsEncoderApplyBitVaryRang(SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int32_t iRang){ - SSpatialLayerConfig* pLayerParam; - const int32_t iNumLayers = pParam->iSpatialLayerNum; - for (int32_t i = 0; i < iNumLayers; i++) { - pLayerParam = & (pParam->sSpatialLayers[i]); - pLayerParam->iMaxSpatialBitrate = WELS_MIN((int) (pLayerParam->iSpatialBitrate * (1+ iRang/100.0)),pLayerParam->iMaxSpatialBitrate); - if (WelsBitRateVerification (pLogCtx, pLayerParam, i) != ENC_RETURN_SUCCESS) - return ENC_RETURN_UNSUPPORTED_PARA; - WelsLog (pLogCtx, WELS_LOG_INFO, - "WelsEncoderApplyBitVaryRang:UpdateMaxBitrate layerId= %d,iMaxSpatialBitrate = %d", i, pLayerParam->iMaxSpatialBitrate); - } - return ENC_RETURN_SUCCESS; +int32_t WelsEncoderApplyBitVaryRang (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int32_t iRang) { + SSpatialLayerConfig* pLayerParam; + const int32_t iNumLayers = pParam->iSpatialLayerNum; + for (int32_t i = 0; i < iNumLayers; i++) { + pLayerParam = & (pParam->sSpatialLayers[i]); + pLayerParam->iMaxSpatialBitrate = WELS_MIN ((int) (pLayerParam->iSpatialBitrate * (1 + iRang / 100.0)), + pLayerParam->iMaxSpatialBitrate); + if (WelsBitRateVerification (pLogCtx, pLayerParam, i) != ENC_RETURN_SUCCESS) + return ENC_RETURN_UNSUPPORTED_PARA; + WelsLog (pLogCtx, WELS_LOG_INFO, + "WelsEncoderApplyBitVaryRang:UpdateMaxBitrate layerId= %d,iMaxSpatialBitrate = %d", i, pLayerParam->iMaxSpatialBitrate); + } + return ENC_RETURN_SUCCESS; } /*! @@ -2293,8 +2294,8 @@ void WelsUninitEncoderExt (sWelsEncCtx** ppCtx) { WelsEventSignal (& (*ppCtx)->pSliceThreading->pThreadMasterEvent[iThreadIdx]); res = WelsThreadJoin ((*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx]); // waiting thread exit WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_INFO, "WelsUninitEncoderExt(), pthread_join(pThreadHandles%d) return %d..", - iThreadIdx, - res); + iThreadIdx, + res); (*ppCtx)->pSliceThreading->pThreadHandles[iThreadIdx] = 0; } ++ iThreadIdx; @@ -3101,7 +3102,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour iSpatialNum = pCtx->pVpp->BuildSpatialPicList (pCtx, pSrcPic); if (pCtx->pSvcParam->bEnableFrameSkip) { - UpdateMaxBrCheckWindowStatus(pCtx, iSpatialNum, pSrcPic->uiTimeStamp); + UpdateMaxBrCheckWindowStatus (pCtx, iSpatialNum, pSrcPic->uiTimeStamp); } if (iSpatialNum < 1) { // skip due to temporal layer settings (different frame rate) @@ -3114,10 +3115,10 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour eFrameType = DecideFrameType (pCtx, iSpatialNum); if (eFrameType == videoFrameTypeSkip) { - UpdateBufferWhenFrameSkipped(pCtx, iSpatialNum); + UpdateBufferWhenFrameSkipped (pCtx, iSpatialNum); pFbi->eFrameType = eFrameType; WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %lld, skip one frame, continual skipped %d frames", - pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames); + pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames); return ENC_RETURN_SUCCESS; } @@ -3125,7 +3126,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour if (CheckFrameSkipBasedMaxbr (pCtx, iSpatialNum, eFrameType, (uint32_t)pSrcPic->uiTimeStamp)) { pFbi->eFrameType = videoFrameTypeSkip; WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %lld, skip one frame, continual skipped %d frames", - pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames); + pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames); return ENC_RETURN_SUCCESS; } diff --git a/codec/encoder/core/src/ratectl.cpp b/codec/encoder/core/src/ratectl.cpp index 0bcab61c..592da20c 100644 --- a/codec/encoder/core/src/ratectl.cpp +++ b/codec/encoder/core/src/ratectl.cpp @@ -52,742 +52,753 @@ namespace WelsEnc { #define VIRTUAL_BUFFER_LOW_TH 120 //*INT_MULTIPLY #define VIRTUAL_BUFFER_HIGH_TH 180 //*INT_MULTIPLY - + #define _BITS_RANGE 0 const int32_t g_kiQpToQstepTable[52] = { 63, 71, 79, 89, 100, 112, 126, 141, 159, 178, - 200, 224, 252, 283, 317, 356, 400, 449, 504, 566, - 635, 713, 800, 898, 1008, 1131, 1270, 1425, 1600, 1796, - 2016, 2263, 2540, 2851, 3200, 3592, 4032, 4525, 5080, 5702, - 6400, 7184, 8063, 9051, 10159, 11404, 12800, 14368, 16127, 18102, - 20319, 22807 - }; //WELS_ROUND(INT_MULTIPLY*pow (2.0, (iQP - 4.0) / 6.0)) - +200, 224, 252, 283, 317, 356, 400, 449, 504, 566, +635, 713, 800, 898, 1008, 1131, 1270, 1425, 1600, 1796, +2016, 2263, 2540, 2851, 3200, 3592, 4032, 4525, 5080, 5702, +6400, 7184, 8063, 9051, 10159, 11404, 12800, 14368, 16127, 18102, +20319, 22807 +}; //WELS_ROUND(INT_MULTIPLY*pow (2.0, (iQP - 4.0) / 6.0)) + void RcInitLayerMemory (SWelsSvcRc* pWelsSvcRc, CMemoryAlign* pMA, const int32_t kiMaxTl) { - const int32_t kiSliceNum = pWelsSvcRc->iSliceNum; - const int32_t kiGomSize = pWelsSvcRc->iGomSize; - const int32_t kiGomSizeD = kiGomSize * sizeof (double); - const int32_t kiGomSizeI = kiGomSize * sizeof (int32_t); - const int32_t kiLayerRcSize = kiGomSizeD + (kiGomSizeI * 3) + sizeof (SRCTemporal) * kiMaxTl; - uint8_t* pBaseMem = (uint8_t*)pMA->WelsMalloc (kiLayerRcSize, "pWelsSvcRc->pTemporalOverRc"); - - if (NULL == pBaseMem) - return; - - pWelsSvcRc->pTemporalOverRc = (SRCTemporal*)pBaseMem; - pBaseMem += sizeof (SRCTemporal) * kiMaxTl; - pWelsSvcRc->pGomComplexity = (double*)pBaseMem; - pBaseMem += kiGomSizeD; - pWelsSvcRc->pGomForegroundBlockNum = (int32_t*)pBaseMem; - pBaseMem += kiGomSizeI; - pWelsSvcRc->pCurrentFrameGomSad = (int32_t*)pBaseMem; - pBaseMem += kiGomSizeI; - pWelsSvcRc->pGomCost = (int32_t*)pBaseMem; - - pWelsSvcRc->pSlicingOverRc = (SRCSlicing*)pMA->WelsMalloc (sizeof (SRCSlicing) * kiSliceNum, "SlicingOverRC"); +const int32_t kiSliceNum = pWelsSvcRc->iSliceNum; +const int32_t kiGomSize = pWelsSvcRc->iGomSize; +const int32_t kiGomSizeD = kiGomSize * sizeof (double); +const int32_t kiGomSizeI = kiGomSize * sizeof (int32_t); +const int32_t kiLayerRcSize = kiGomSizeD + (kiGomSizeI * 3) + sizeof (SRCTemporal) * kiMaxTl; +uint8_t* pBaseMem = (uint8_t*)pMA->WelsMalloc (kiLayerRcSize, "pWelsSvcRc->pTemporalOverRc"); + +if (NULL == pBaseMem) +return; + +pWelsSvcRc->pTemporalOverRc = (SRCTemporal*)pBaseMem; +pBaseMem += sizeof (SRCTemporal) * kiMaxTl; +pWelsSvcRc->pGomComplexity = (double*)pBaseMem; +pBaseMem += kiGomSizeD; +pWelsSvcRc->pGomForegroundBlockNum = (int32_t*)pBaseMem; +pBaseMem += kiGomSizeI; +pWelsSvcRc->pCurrentFrameGomSad = (int32_t*)pBaseMem; +pBaseMem += kiGomSizeI; +pWelsSvcRc->pGomCost = (int32_t*)pBaseMem; + +pWelsSvcRc->pSlicingOverRc = (SRCSlicing*)pMA->WelsMalloc (sizeof (SRCSlicing) * kiSliceNum, "SlicingOverRC"); } - + void RcFreeLayerMemory (SWelsSvcRc* pWelsSvcRc, CMemoryAlign* pMA) { - if (pWelsSvcRc != NULL && pWelsSvcRc->pSlicingOverRc != NULL) { - pMA->WelsFree (pWelsSvcRc->pSlicingOverRc, "SlicingOverRC"); - pWelsSvcRc->pSlicingOverRc = NULL; - } - if (pWelsSvcRc != NULL && pWelsSvcRc->pTemporalOverRc != NULL) { - pMA->WelsFree (pWelsSvcRc->pTemporalOverRc, "pWelsSvcRc->pTemporalOverRc"); - pWelsSvcRc->pTemporalOverRc = NULL; - pWelsSvcRc->pGomComplexity = NULL; - pWelsSvcRc->pGomForegroundBlockNum = NULL; - pWelsSvcRc->pCurrentFrameGomSad = NULL; - pWelsSvcRc->pGomCost = NULL; - } +if (pWelsSvcRc != NULL && pWelsSvcRc->pSlicingOverRc != NULL) { +pMA->WelsFree (pWelsSvcRc->pSlicingOverRc, "SlicingOverRC"); +pWelsSvcRc->pSlicingOverRc = NULL; } - +if (pWelsSvcRc != NULL && pWelsSvcRc->pTemporalOverRc != NULL) { +pMA->WelsFree (pWelsSvcRc->pTemporalOverRc, "pWelsSvcRc->pTemporalOverRc"); +pWelsSvcRc->pTemporalOverRc = NULL; +pWelsSvcRc->pGomComplexity = NULL; +pWelsSvcRc->pGomForegroundBlockNum = NULL; +pWelsSvcRc->pCurrentFrameGomSad = NULL; +pWelsSvcRc->pGomCost = NULL; +} +} + static inline int32_t RcConvertQp2QStep (int32_t iQP) { - return g_kiQpToQstepTable[iQP]; +return g_kiQpToQstepTable[iQP]; } static inline int32_t RcConvertQStep2Qp (int32_t iQpStep) { - return WELS_ROUND ((6 * log (iQpStep * 1.0f / INT_MULTIPLY) / log (2.0) + 4.0)); +return WELS_ROUND ((6 * log (iQpStep * 1.0f / INT_MULTIPLY) / log (2.0) + 4.0)); } - + void RcInitSequenceParameter (sWelsEncCtx* pEncCtx) { - SWelsSvcRc* pWelsSvcRc = NULL; - SSpatialLayerConfig* pDLayerParam = NULL; - - int32_t j = 0; - int32_t iMbWidth = 0; - - bool bMultiSliceMode = false; - int32_t iGomRowMode0 = 1, iGomRowMode1 = 1; - for (j = 0; j < pEncCtx->pSvcParam->iSpatialLayerNum; j++) { - SSliceCtx* pSliceCtx = &pEncCtx->pSliceCtxList[j]; - pWelsSvcRc = &pEncCtx->pWelsSvcRc[j]; - pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[j]; - iMbWidth = (pDLayerParam->iVideoWidth >> 4); - pWelsSvcRc->iNumberMbFrame = iMbWidth * (pDLayerParam->iVideoHeight >> 4); - pWelsSvcRc->iSliceNum = pSliceCtx->iSliceNumInFrame; - - pWelsSvcRc->iRcVaryPercentage = pEncCtx->pSvcParam->iBitsVaryPercentage; // % -- for temp - pWelsSvcRc->iRcVaryRatio = pWelsSvcRc->iRcVaryPercentage; - - pWelsSvcRc->iSkipBufferRatio = SKIP_RATIO; - - pWelsSvcRc->iQpRangeUpperInFrame = (QP_RANGE_UPPER_MODE1 * MAX_BITS_VARY_PERCENTAGE - (( - QP_RANGE_UPPER_MODE1 - QP_RANGE_MODE0) * - pWelsSvcRc->iRcVaryRatio)) / MAX_BITS_VARY_PERCENTAGE; - pWelsSvcRc->iQpRangeLowerInFrame = (QP_RANGE_LOWER_MODE1 * MAX_BITS_VARY_PERCENTAGE - (( - QP_RANGE_LOWER_MODE1 - QP_RANGE_MODE0) * - pWelsSvcRc->iRcVaryRatio)) / MAX_BITS_VARY_PERCENTAGE; - - if (iMbWidth <= MB_WIDTH_THRESHOLD_90P) { - pWelsSvcRc->iSkipQpValue = SKIP_QP_90P; - iGomRowMode0 = GOM_ROW_MODE0_90P; - iGomRowMode1 = GOM_ROW_MODE1_90P; - } else if (iMbWidth <= MB_WIDTH_THRESHOLD_180P) { - pWelsSvcRc->iSkipQpValue = SKIP_QP_180P; - iGomRowMode0 = GOM_ROW_MODE0_180P; - iGomRowMode1 = GOM_ROW_MODE1_180P; - } else if (iMbWidth <= MB_WIDTH_THRESHOLD_360P) { - pWelsSvcRc->iSkipQpValue = SKIP_QP_360P; - iGomRowMode0 = GOM_ROW_MODE0_360P; - iGomRowMode1 = GOM_ROW_MODE1_360P; - } else { - pWelsSvcRc->iSkipQpValue = SKIP_QP_720P; - iGomRowMode0 = GOM_ROW_MODE0_720P; - iGomRowMode1 = GOM_ROW_MODE1_720P; - } - iGomRowMode0 = iGomRowMode1 + ((iGomRowMode0 - iGomRowMode1) * pWelsSvcRc->iRcVaryRatio / MAX_BITS_VARY_PERCENTAGE); - - pWelsSvcRc->iNumberMbGom = iMbWidth * iGomRowMode0; - - pWelsSvcRc->iMinQp = GOM_MIN_QP_MODE; - pWelsSvcRc->iMaxQp = GOM_MAX_QP_MODE; - - pWelsSvcRc->iFrameDeltaQpUpper = LAST_FRAME_QP_RANGE_UPPER_MODE1 - ((LAST_FRAME_QP_RANGE_UPPER_MODE1 - - LAST_FRAME_QP_RANGE_UPPER_MODE0) * pWelsSvcRc->iRcVaryRatio / MAX_BITS_VARY_PERCENTAGE); - pWelsSvcRc->iFrameDeltaQpLower = LAST_FRAME_QP_RANGE_LOWER_MODE1 - ((LAST_FRAME_QP_RANGE_LOWER_MODE1 - - LAST_FRAME_QP_RANGE_LOWER_MODE0) * pWelsSvcRc->iRcVaryRatio / MAX_BITS_VARY_PERCENTAGE); - - pWelsSvcRc->iSkipFrameNum = 0; - pWelsSvcRc->iGomSize = (pWelsSvcRc->iNumberMbFrame + pWelsSvcRc->iNumberMbGom - 1) / pWelsSvcRc->iNumberMbGom; - - - RcInitLayerMemory (pWelsSvcRc, pEncCtx->pMemAlign, 1 + pEncCtx->pSvcParam->sDependencyLayers[j].iHighestTemporalId); - - bMultiSliceMode = ((SM_RASTER_SLICE == pDLayerParam->sSliceCfg.uiSliceMode) || - (SM_ROWMB_SLICE == pDLayerParam->sSliceCfg.uiSliceMode) || - (SM_DYN_SLICE == pDLayerParam->sSliceCfg.uiSliceMode)); - if (bMultiSliceMode) - pWelsSvcRc->iNumberMbGom = pWelsSvcRc->iNumberMbFrame; - } +SWelsSvcRc* pWelsSvcRc = NULL; +SSpatialLayerConfig* pDLayerParam = NULL; + +int32_t j = 0; +int32_t iMbWidth = 0; + +bool bMultiSliceMode = false; +int32_t iGomRowMode0 = 1, iGomRowMode1 = 1; +for (j = 0; j < pEncCtx->pSvcParam->iSpatialLayerNum; j++) { +SSliceCtx* pSliceCtx = &pEncCtx->pSliceCtxList[j]; +pWelsSvcRc = &pEncCtx->pWelsSvcRc[j]; +pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[j]; +iMbWidth = (pDLayerParam->iVideoWidth >> 4); +pWelsSvcRc->iNumberMbFrame = iMbWidth * (pDLayerParam->iVideoHeight >> 4); +pWelsSvcRc->iSliceNum = pSliceCtx->iSliceNumInFrame; + +pWelsSvcRc->iRcVaryPercentage = pEncCtx->pSvcParam->iBitsVaryPercentage; // % -- for temp +pWelsSvcRc->iRcVaryRatio = pWelsSvcRc->iRcVaryPercentage; + +pWelsSvcRc->iSkipBufferRatio = SKIP_RATIO; + +pWelsSvcRc->iQpRangeUpperInFrame = (QP_RANGE_UPPER_MODE1 * MAX_BITS_VARY_PERCENTAGE - (( +QP_RANGE_UPPER_MODE1 - QP_RANGE_MODE0) * +pWelsSvcRc->iRcVaryRatio)) / MAX_BITS_VARY_PERCENTAGE; +pWelsSvcRc->iQpRangeLowerInFrame = (QP_RANGE_LOWER_MODE1 * MAX_BITS_VARY_PERCENTAGE - (( +QP_RANGE_LOWER_MODE1 - QP_RANGE_MODE0) * +pWelsSvcRc->iRcVaryRatio)) / MAX_BITS_VARY_PERCENTAGE; + +if (iMbWidth <= MB_WIDTH_THRESHOLD_90P) { +pWelsSvcRc->iSkipQpValue = SKIP_QP_90P; +iGomRowMode0 = GOM_ROW_MODE0_90P; +iGomRowMode1 = GOM_ROW_MODE1_90P; +} else if (iMbWidth <= MB_WIDTH_THRESHOLD_180P) { +pWelsSvcRc->iSkipQpValue = SKIP_QP_180P; +iGomRowMode0 = GOM_ROW_MODE0_180P; +iGomRowMode1 = GOM_ROW_MODE1_180P; +} else if (iMbWidth <= MB_WIDTH_THRESHOLD_360P) { +pWelsSvcRc->iSkipQpValue = SKIP_QP_360P; +iGomRowMode0 = GOM_ROW_MODE0_360P; +iGomRowMode1 = GOM_ROW_MODE1_360P; +} else { +pWelsSvcRc->iSkipQpValue = SKIP_QP_720P; +iGomRowMode0 = GOM_ROW_MODE0_720P; +iGomRowMode1 = GOM_ROW_MODE1_720P; } - - +iGomRowMode0 = iGomRowMode1 + ((iGomRowMode0 - iGomRowMode1) * pWelsSvcRc->iRcVaryRatio / MAX_BITS_VARY_PERCENTAGE); + +pWelsSvcRc->iNumberMbGom = iMbWidth * iGomRowMode0; + +pWelsSvcRc->iMinQp = GOM_MIN_QP_MODE; +pWelsSvcRc->iMaxQp = GOM_MAX_QP_MODE; + +pWelsSvcRc->iFrameDeltaQpUpper = LAST_FRAME_QP_RANGE_UPPER_MODE1 - ((LAST_FRAME_QP_RANGE_UPPER_MODE1 - +LAST_FRAME_QP_RANGE_UPPER_MODE0) * pWelsSvcRc->iRcVaryRatio / MAX_BITS_VARY_PERCENTAGE); +pWelsSvcRc->iFrameDeltaQpLower = LAST_FRAME_QP_RANGE_LOWER_MODE1 - ((LAST_FRAME_QP_RANGE_LOWER_MODE1 - +LAST_FRAME_QP_RANGE_LOWER_MODE0) * pWelsSvcRc->iRcVaryRatio / MAX_BITS_VARY_PERCENTAGE); + +pWelsSvcRc->iSkipFrameNum = 0; +pWelsSvcRc->iGomSize = (pWelsSvcRc->iNumberMbFrame + pWelsSvcRc->iNumberMbGom - 1) / pWelsSvcRc->iNumberMbGom; + + +RcInitLayerMemory (pWelsSvcRc, pEncCtx->pMemAlign, 1 + pEncCtx->pSvcParam->sDependencyLayers[j].iHighestTemporalId); + +bMultiSliceMode = ((SM_RASTER_SLICE == pDLayerParam->sSliceCfg.uiSliceMode) || +(SM_ROWMB_SLICE == pDLayerParam->sSliceCfg.uiSliceMode) || +(SM_DYN_SLICE == pDLayerParam->sSliceCfg.uiSliceMode)); +if (bMultiSliceMode) +pWelsSvcRc->iNumberMbGom = pWelsSvcRc->iNumberMbFrame; +} +} + + void RcInitTlWeight (sWelsEncCtx* pEncCtx) { - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc; - SSpatialLayerInternal* pDLayerParam = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId]; - const int32_t kiDecompositionStages = pDLayerParam->iDecompositionStages; - const int32_t kiHighestTid = pDLayerParam->iHighestTemporalId; - - //Index 0:Virtual GOP size, Index 1:Frame rate - //double WeightArray[4][4] = { {1.0, 0, 0, 0}, {0.6, 0.4, 0, 0}, {0.4, 0.3, 0.15, 0}, {0.25, 0.15, 0.125, 0.0875}}; - int32_t iWeightArray[4][4] = { {2000, 0, 0, 0}, {1200, 800, 0, 0}, {800, 600, 300, 0}, {500, 300, 250, 175}}; // original*WEIGHT_MULTIPLY - const int32_t kiGopSize = (1 << kiDecompositionStages); - int32_t i, k, n; - - n = 0; - while (n <= kiHighestTid) { - pTOverRc[n].iTlayerWeight = iWeightArray[kiDecompositionStages][n]; - ++ n; - } - //Calculate the frame index for the current frame and its reference frame - for (n = 0; n < VGOP_SIZE; n += kiGopSize) { - pWelsSvcRc->iTlOfFrames[n] = 0; - for (i = 1; i <= kiDecompositionStages; i++) { - for (k = 1 << (kiDecompositionStages - i); k < kiGopSize; k += (kiGopSize >> (i - 1))) { - pWelsSvcRc->iTlOfFrames[k + n] = i; - } - } - } - pWelsSvcRc->iPreviousGopSize = kiGopSize; - pWelsSvcRc->iGopNumberInVGop = VGOP_SIZE / kiGopSize; +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc; +SSpatialLayerInternal* pDLayerParam = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId]; +const int32_t kiDecompositionStages = pDLayerParam->iDecompositionStages; +const int32_t kiHighestTid = pDLayerParam->iHighestTemporalId; + +//Index 0:Virtual GOP size, Index 1:Frame rate +//double WeightArray[4][4] = { {1.0, 0, 0, 0}, {0.6, 0.4, 0, 0}, {0.4, 0.3, 0.15, 0}, {0.25, 0.15, 0.125, 0.0875}}; +int32_t iWeightArray[4][4] = { {2000, 0, 0, 0}, {1200, 800, 0, 0}, {800, 600, 300, 0}, {500, 300, 250, 175}}; // original*WEIGHT_MULTIPLY +const int32_t kiGopSize = (1 << kiDecompositionStages); +int32_t i, k, n; + +n = 0; +while (n <= kiHighestTid) { +pTOverRc[n].iTlayerWeight = iWeightArray[kiDecompositionStages][n]; +++ n; } - +//Calculate the frame index for the current frame and its reference frame +for (n = 0; n < VGOP_SIZE; n += kiGopSize) { +pWelsSvcRc->iTlOfFrames[n] = 0; +for (i = 1; i <= kiDecompositionStages; i++) { +for (k = 1 << (kiDecompositionStages - i); k < kiGopSize; k += (kiGopSize >> (i - 1))) { +pWelsSvcRc->iTlOfFrames[k + n] = i; +} +} +} +pWelsSvcRc->iPreviousGopSize = kiGopSize; +pWelsSvcRc->iGopNumberInVGop = VGOP_SIZE / kiGopSize; +} + void RcUpdateBitrateFps (sWelsEncCtx* pEncCtx) { - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc; - - SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId]; - SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId]; - const int32_t kiGopSize = (1 << pDLayerParamInternal->iDecompositionStages); - const int32_t kiHighestTid = pDLayerParamInternal->iHighestTemporalId; - int64_t input_iBitsPerFrame = WELS_ROUND64 (((int64_t)pDLayerParam->iSpatialBitrate) * INT_MULTIPLY / - pDLayerParamInternal->fInputFrameRate); - const int32_t kiGopBits = WELS_DIV_ROUND (input_iBitsPerFrame * kiGopSize, INT_MULTIPLY); - int32_t i; - - pWelsSvcRc->iBitRate = pDLayerParam->iSpatialBitrate; - pWelsSvcRc->fFrameRate = pDLayerParamInternal->fInputFrameRate; - - int32_t iTargetVaryRange = FRAME_iTargetBits_VARY_RANGE * (MAX_BITS_VARY_PERCENTAGE - pWelsSvcRc->iRcVaryRatio); - int32_t iMinBitsRatio = (MAX_BITS_VARY_PERCENTAGE) * INT_MULTIPLY - iTargetVaryRange; - int32_t iMaxBitsRatio = (MAX_BITS_VARY_PERCENTAGE) * (INT_MULTIPLY + FRAME_iTargetBits_VARY_RANGE); - - for (i = 0; i <= kiHighestTid; i++) { - const int64_t kdConstraitBits = kiGopBits * pTOverRc[i].iTlayerWeight; - pTOverRc[i].iMinBitsTl = WELS_DIV_ROUND (kdConstraitBits * iMinBitsRatio, - INT_MULTIPLY * MAX_BITS_VARY_PERCENTAGE * WEIGHT_MULTIPLY); - pTOverRc[i].iMaxBitsTl = WELS_DIV_ROUND (kdConstraitBits * iMaxBitsRatio, - INT_MULTIPLY * MAX_BITS_VARY_PERCENTAGE * WEIGHT_MULTIPLY); - } - //When bitrate is changed, pBuffer size should be updated - pWelsSvcRc->iBufferSizeSkip = WELS_DIV_ROUND (pWelsSvcRc->iBitRate * pWelsSvcRc->iSkipBufferRatio, INT_MULTIPLY); - pWelsSvcRc->iBufferSizePadding = WELS_DIV_ROUND (pWelsSvcRc->iBitRate * PADDING_BUFFER_RATIO, INT_MULTIPLY); - - //change remaining bits - if (pWelsSvcRc->iBitsPerFrame > REMAIN_BITS_TH) - pWelsSvcRc->iRemainingBits = (int32_t) (pWelsSvcRc->iRemainingBits * input_iBitsPerFrame / pWelsSvcRc->iBitsPerFrame); - pWelsSvcRc->iBitsPerFrame = input_iBitsPerFrame; - pWelsSvcRc->iMaxBitsPerFrame = WELS_DIV_ROUND64 ((pDLayerParam->iMaxSpatialBitrate) * INT_MULTIPLY, - pDLayerParamInternal->fInputFrameRate); +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc; + +SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId]; +SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId]; +const int32_t kiGopSize = (1 << pDLayerParamInternal->iDecompositionStages); +const int32_t kiHighestTid = pDLayerParamInternal->iHighestTemporalId; +int64_t input_iBitsPerFrame = WELS_ROUND64 (((int64_t)pDLayerParam->iSpatialBitrate) * INT_MULTIPLY / +pDLayerParamInternal->fInputFrameRate); +const int32_t kiGopBits = WELS_DIV_ROUND (input_iBitsPerFrame * kiGopSize, INT_MULTIPLY); +int32_t i; + +pWelsSvcRc->iBitRate = pDLayerParam->iSpatialBitrate; +pWelsSvcRc->fFrameRate = pDLayerParamInternal->fInputFrameRate; + +int32_t iTargetVaryRange = FRAME_iTargetBits_VARY_RANGE * (MAX_BITS_VARY_PERCENTAGE - pWelsSvcRc->iRcVaryRatio); +int32_t iMinBitsRatio = (MAX_BITS_VARY_PERCENTAGE) * INT_MULTIPLY - iTargetVaryRange; +int32_t iMaxBitsRatio = (MAX_BITS_VARY_PERCENTAGE) * (INT_MULTIPLY + FRAME_iTargetBits_VARY_RANGE); + +for (i = 0; i <= kiHighestTid; i++) { +const int64_t kdConstraitBits = kiGopBits * pTOverRc[i].iTlayerWeight; +pTOverRc[i].iMinBitsTl = WELS_DIV_ROUND (kdConstraitBits * iMinBitsRatio, +INT_MULTIPLY * MAX_BITS_VARY_PERCENTAGE * WEIGHT_MULTIPLY); +pTOverRc[i].iMaxBitsTl = WELS_DIV_ROUND (kdConstraitBits * iMaxBitsRatio, +INT_MULTIPLY * MAX_BITS_VARY_PERCENTAGE * WEIGHT_MULTIPLY); } - - +//When bitrate is changed, pBuffer size should be updated +pWelsSvcRc->iBufferSizeSkip = WELS_DIV_ROUND (pWelsSvcRc->iBitRate * pWelsSvcRc->iSkipBufferRatio, INT_MULTIPLY); +pWelsSvcRc->iBufferSizePadding = WELS_DIV_ROUND (pWelsSvcRc->iBitRate * PADDING_BUFFER_RATIO, INT_MULTIPLY); + +//change remaining bits +if (pWelsSvcRc->iBitsPerFrame > REMAIN_BITS_TH) +pWelsSvcRc->iRemainingBits = (int32_t) (pWelsSvcRc->iRemainingBits * input_iBitsPerFrame / pWelsSvcRc->iBitsPerFrame); +pWelsSvcRc->iBitsPerFrame = input_iBitsPerFrame; +pWelsSvcRc->iMaxBitsPerFrame = WELS_DIV_ROUND64 ((pDLayerParam->iMaxSpatialBitrate) * INT_MULTIPLY, +pDLayerParamInternal->fInputFrameRate); +} + + void RcInitVGop (sWelsEncCtx* pEncCtx) { - const int32_t kiDid = pEncCtx->uiDependencyId; - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[kiDid]; - SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc; - const int32_t kiHighestTid = pEncCtx->pSvcParam->sDependencyLayers[kiDid].iHighestTemporalId; - - pWelsSvcRc->iRemainingBits = WELS_DIV_ROUND (VGOP_SIZE * pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY); - pWelsSvcRc->iRemainingWeights = pWelsSvcRc->iGopNumberInVGop * WEIGHT_MULTIPLY; - - pWelsSvcRc->iFrameCodedInVGop = 0; - pWelsSvcRc->iGopIndexInVGop = 0; - - for (int32_t i = 0; i <= kiHighestTid; ++ i) - pTOverRc[i].iGopBitsDq = 0; - pWelsSvcRc->iSkipFrameInVGop = 0; +const int32_t kiDid = pEncCtx->uiDependencyId; +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[kiDid]; +SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc; +const int32_t kiHighestTid = pEncCtx->pSvcParam->sDependencyLayers[kiDid].iHighestTemporalId; + +pWelsSvcRc->iRemainingBits = WELS_DIV_ROUND (VGOP_SIZE * pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY); +pWelsSvcRc->iRemainingWeights = pWelsSvcRc->iGopNumberInVGop * WEIGHT_MULTIPLY; + +pWelsSvcRc->iFrameCodedInVGop = 0; +pWelsSvcRc->iGopIndexInVGop = 0; + +for (int32_t i = 0; i <= kiHighestTid; ++ i) +pTOverRc[i].iGopBitsDq = 0; +pWelsSvcRc->iSkipFrameInVGop = 0; } - + void RcInitRefreshParameter (sWelsEncCtx* pEncCtx) { - const int32_t kiDid = pEncCtx->uiDependencyId; - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[kiDid]; - SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc; - SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[kiDid]; - SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[kiDid]; - const int32_t kiHighestTid = pDLayerParamInternal->iHighestTemporalId; - int32_t i; - - //I frame R-Q Model - pWelsSvcRc->iIntraComplexity = 0; - pWelsSvcRc->iIntraMbCount = 0; - - //P frame R-Q Model - for (i = 0; i <= kiHighestTid; i++) { - pTOverRc[i].iPFrameNum = 0; - pTOverRc[i].iLinearCmplx = 0; - pTOverRc[i].iFrameCmplxMean = 0; - } - - pWelsSvcRc->iBufferFullnessSkip = 0; - pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] = 0; - pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] = 0; - pWelsSvcRc->iPredFrameBit = 0; - pWelsSvcRc->iBufferFullnessPadding = 0; - - pWelsSvcRc->iGopIndexInVGop = 0; - pWelsSvcRc->iRemainingBits = 0; - pWelsSvcRc->iBitsPerFrame = 0; - - //Backup the initial bitrate and fps - pWelsSvcRc->iPreviousBitrate = pDLayerParam->iSpatialBitrate; - pWelsSvcRc->dPreviousFps = pDLayerParamInternal->fInputFrameRate; - - memset (pWelsSvcRc->pCurrentFrameGomSad, 0, pWelsSvcRc->iGomSize * sizeof (int32_t)); - - RcInitTlWeight (pEncCtx); - RcUpdateBitrateFps (pEncCtx); - RcInitVGop (pEncCtx); +const int32_t kiDid = pEncCtx->uiDependencyId; +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[kiDid]; +SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc; +SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[kiDid]; +SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[kiDid]; +const int32_t kiHighestTid = pDLayerParamInternal->iHighestTemporalId; +int32_t i; + +//I frame R-Q Model +pWelsSvcRc->iIntraComplexity = 0; +pWelsSvcRc->iIntraMbCount = 0; + +//P frame R-Q Model +for (i = 0; i <= kiHighestTid; i++) { +pTOverRc[i].iPFrameNum = 0; +pTOverRc[i].iLinearCmplx = 0; +pTOverRc[i].iFrameCmplxMean = 0; } - + +pWelsSvcRc->iBufferFullnessSkip = 0; +pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] = 0; +pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] = 0; +pWelsSvcRc->iPredFrameBit = 0; +pWelsSvcRc->iBufferFullnessPadding = 0; + +pWelsSvcRc->iGopIndexInVGop = 0; +pWelsSvcRc->iRemainingBits = 0; +pWelsSvcRc->iBitsPerFrame = 0; + +//Backup the initial bitrate and fps +pWelsSvcRc->iPreviousBitrate = pDLayerParam->iSpatialBitrate; +pWelsSvcRc->dPreviousFps = pDLayerParamInternal->fInputFrameRate; + +memset (pWelsSvcRc->pCurrentFrameGomSad, 0, pWelsSvcRc->iGomSize * sizeof (int32_t)); + +RcInitTlWeight (pEncCtx); +RcUpdateBitrateFps (pEncCtx); +RcInitVGop (pEncCtx); +} + bool RcJudgeBitrateFpsUpdate (sWelsEncCtx* pEncCtx) { - int32_t iCurDid = pEncCtx->uiDependencyId; - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[iCurDid]; - SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[iCurDid]; - SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[iCurDid]; - - if ((pWelsSvcRc->iPreviousBitrate != pDLayerParam->iSpatialBitrate) || - (pWelsSvcRc->dPreviousFps - pDLayerParamInternal->fInputFrameRate) > EPSN || - (pWelsSvcRc->dPreviousFps - pDLayerParamInternal->fInputFrameRate) < -EPSN) { - pWelsSvcRc->iPreviousBitrate = pDLayerParam->iSpatialBitrate; - pWelsSvcRc->dPreviousFps = pDLayerParamInternal->fInputFrameRate; - return true; - } else - return false; +int32_t iCurDid = pEncCtx->uiDependencyId; +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[iCurDid]; +SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[iCurDid]; +SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[iCurDid]; + +if ((pWelsSvcRc->iPreviousBitrate != pDLayerParam->iSpatialBitrate) || +(pWelsSvcRc->dPreviousFps - pDLayerParamInternal->fInputFrameRate) > EPSN || +(pWelsSvcRc->dPreviousFps - pDLayerParamInternal->fInputFrameRate) < -EPSN) { +pWelsSvcRc->iPreviousBitrate = pDLayerParam->iSpatialBitrate; +pWelsSvcRc->dPreviousFps = pDLayerParamInternal->fInputFrameRate; +return true; +} else +return false; } - + #if GOM_TRACE_FLAG void RcTraceVGopBitrate (sWelsEncCtx* pEncCtx) { - const int32_t kiDid = pEncCtx->uiDependencyId; - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[kiDid]; - - if (pWelsSvcRc->iFrameCodedInVGop) { - const int32_t kiHighestTid = pEncCtx->pSvcParam->sDependencyLayers[kiDid].iHighestTemporalId; - SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc; - int32_t iVGopBitrate = 0; - int32_t iTotalBits = pWelsSvcRc->iPaddingBitrateStat; - int32_t iTid = 0; - while (iTid <= kiHighestTid) { - iTotalBits += pTOverRc[iTid].iGopBitsDq; - ++ iTid; - } - int32_t iFrameInVGop = pWelsSvcRc->iFrameCodedInVGop + pWelsSvcRc->iSkipFrameInVGop; - if (0 != iFrameInVGop) - iVGopBitrate = WELS_ROUND (iTotalBits / iFrameInVGop * pWelsSvcRc->fFrameRate); - WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_INFO, "[Rc] VGOPbitrate%d: %d ", kiDid, iVGopBitrate); - if (iTotalBits > 0) { - iTid = 0; - while (iTid <= kiHighestTid) { - WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_INFO, "T%d=%8.3f ", iTid, (double) (pTOverRc[iTid].iGopBitsDq / iTotalBits)); - ++ iTid; - } - } - } +const int32_t kiDid = pEncCtx->uiDependencyId; +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[kiDid]; + +if (pWelsSvcRc->iFrameCodedInVGop) { +const int32_t kiHighestTid = pEncCtx->pSvcParam->sDependencyLayers[kiDid].iHighestTemporalId; +SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc; +int32_t iVGopBitrate = 0; +int32_t iTotalBits = pWelsSvcRc->iPaddingBitrateStat; +int32_t iTid = 0; +while (iTid <= kiHighestTid) { +iTotalBits += pTOverRc[iTid].iGopBitsDq; +++ iTid; +} +int32_t iFrameInVGop = pWelsSvcRc->iFrameCodedInVGop + pWelsSvcRc->iSkipFrameInVGop; +if (0 != iFrameInVGop) +iVGopBitrate = WELS_ROUND (iTotalBits / iFrameInVGop * pWelsSvcRc->fFrameRate); +WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_INFO, "[Rc] VGOPbitrate%d: %d ", kiDid, iVGopBitrate); +if (iTotalBits > 0) { +iTid = 0; +while (iTid <= kiHighestTid) { +WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_INFO, "T%d=%8.3f ", iTid, (double) (pTOverRc[iTid].iGopBitsDq / iTotalBits)); +++ iTid; +} +} +} } #endif - + void RcUpdateTemporalZero (sWelsEncCtx* pEncCtx) { - const int32_t kiDid = pEncCtx->uiDependencyId; - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[kiDid]; - SSpatialLayerInternal* pDLayerParam = &pEncCtx->pSvcParam->sDependencyLayers[kiDid]; - const int32_t kiGopSize = (1 << pDLayerParam->iDecompositionStages); - - if (pWelsSvcRc->iPreviousGopSize != kiGopSize) { +const int32_t kiDid = pEncCtx->uiDependencyId; +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[kiDid]; +SSpatialLayerInternal* pDLayerParam = &pEncCtx->pSvcParam->sDependencyLayers[kiDid]; +const int32_t kiGopSize = (1 << pDLayerParam->iDecompositionStages); + +if (pWelsSvcRc->iPreviousGopSize != kiGopSize) { #if GOM_TRACE_FLAG - RcTraceVGopBitrate (pEncCtx); +RcTraceVGopBitrate (pEncCtx); #endif - RcInitTlWeight (pEncCtx); - RcInitVGop (pEncCtx); - } else if (pWelsSvcRc->iGopIndexInVGop == pWelsSvcRc->iGopNumberInVGop || pEncCtx->eSliceType == I_SLICE) { +RcInitTlWeight (pEncCtx); +RcInitVGop (pEncCtx); +} else if (pWelsSvcRc->iGopIndexInVGop == pWelsSvcRc->iGopNumberInVGop || pEncCtx->eSliceType == I_SLICE) { #if GOM_TRACE_FLAG - RcTraceVGopBitrate (pEncCtx); +RcTraceVGopBitrate (pEncCtx); #endif - RcInitVGop (pEncCtx); - } - pWelsSvcRc->iGopIndexInVGop++; +RcInitVGop (pEncCtx); } - - +pWelsSvcRc->iGopIndexInVGop++; +} + + void RcInitIdrQp (sWelsEncCtx* pEncCtx) { - double dBpp = 0; - int32_t i; - - //64k@6fps for 90p: bpp 0.74 QP:24 - //192k@12fps for 180p: bpp 0.28 QP:26 - //512k@24fps for 360p: bpp 0.09 QP:30 - //1500k@30fps for 720p: bpp 0.05 QP:32 - double dBppArray[4][3] = {{0.5, 0.75, 1.0}, {0.2, 0.3, 0.4}, {0.05, 0.09, 0.13}, {0.03, 0.06, 0.1}}; - int32_t dInitialQPArray[4][4] = {{28, 26, 24, 22}, {30, 28, 26, 24}, {32, 30, 28, 26}, {34, 32, 30, 28}}; - int32_t iBppIndex = 0; - - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId]; - - if (pDLayerParam->fFrameRate > EPSN && pDLayerParam->iVideoWidth && pDLayerParam->iVideoHeight) - dBpp = (double) (pDLayerParam->iSpatialBitrate) / (double) (pDLayerParam->fFrameRate * pDLayerParam->iVideoWidth * - pDLayerParam->iVideoHeight); - else - dBpp = 0.1; - - //Area*2 - if (pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight <= 28800) // 90p video:160*90 - iBppIndex = 0; - else if (pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight <= 115200) // 180p video:320*180 - iBppIndex = 1; - else if (pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight <= 460800) // 360p video:640*360 - iBppIndex = 2; - else - iBppIndex = 3; - - //Search - for (i = 0; i < 3; i++) { - if (dBpp <= dBppArray[iBppIndex][i]) - break; - } - pWelsSvcRc->iInitialQp = dInitialQPArray[iBppIndex][i]; - pWelsSvcRc->iInitialQp = WELS_CLIP3 (pWelsSvcRc->iInitialQp, MIN_IDR_QP, MAX_IDR_QP); - pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp; - pWelsSvcRc->iQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp); - pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp; +double dBpp = 0; +int32_t i; + +//64k@6fps for 90p: bpp 0.74 QP:24 +//192k@12fps for 180p: bpp 0.28 QP:26 +//512k@24fps for 360p: bpp 0.09 QP:30 +//1500k@30fps for 720p: bpp 0.05 QP:32 +double dBppArray[4][3] = {{0.5, 0.75, 1.0}, {0.2, 0.3, 0.4}, {0.05, 0.09, 0.13}, {0.03, 0.06, 0.1}}; +int32_t dInitialQPArray[4][4] = {{28, 26, 24, 22}, {30, 28, 26, 24}, {32, 30, 28, 26}, {34, 32, 30, 28}}; +int32_t iBppIndex = 0; + +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId]; + +if (pDLayerParam->fFrameRate > EPSN && pDLayerParam->iVideoWidth && pDLayerParam->iVideoHeight) +dBpp = (double) (pDLayerParam->iSpatialBitrate) / (double) (pDLayerParam->fFrameRate * pDLayerParam->iVideoWidth * +pDLayerParam->iVideoHeight); +else +dBpp = 0.1; + +//Area*2 +if (pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight <= 28800) // 90p video:160*90 +iBppIndex = 0; +else if (pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight <= 115200) // 180p video:320*180 +iBppIndex = 1; +else if (pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight <= 460800) // 360p video:640*360 +iBppIndex = 2; +else +iBppIndex = 3; + +//Search +for (i = 0; i < 3; i++) { +if (dBpp <= dBppArray[iBppIndex][i]) +break; } - +pWelsSvcRc->iInitialQp = dInitialQPArray[iBppIndex][i]; +pWelsSvcRc->iInitialQp = WELS_CLIP3 (pWelsSvcRc->iInitialQp, MIN_IDR_QP, MAX_IDR_QP); +pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp; +pWelsSvcRc->iQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp); +pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp; +} + void RcCalculateIdrQp (sWelsEncCtx* pEncCtx) { - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - //obtain the idr qp using previous idr complexity - if (pWelsSvcRc->iNumberMbFrame != pWelsSvcRc->iIntraMbCount) { - pWelsSvcRc->iIntraComplexity = pWelsSvcRc->iIntraComplexity * pWelsSvcRc->iNumberMbFrame / - pWelsSvcRc->iIntraMbCount; - } - pWelsSvcRc->iInitialQp = RcConvertQStep2Qp (pWelsSvcRc->iIntraComplexity / - pWelsSvcRc->iTargetBits); - pWelsSvcRc->iInitialQp = WELS_CLIP3 (pWelsSvcRc->iInitialQp, MIN_IDR_QP, MAX_IDR_QP); - pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp; - pWelsSvcRc->iQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp); - pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp; +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +//obtain the idr qp using previous idr complexity +if (pWelsSvcRc->iNumberMbFrame != pWelsSvcRc->iIntraMbCount) { +pWelsSvcRc->iIntraComplexity = pWelsSvcRc->iIntraComplexity * pWelsSvcRc->iNumberMbFrame / +pWelsSvcRc->iIntraMbCount; } - - +pWelsSvcRc->iInitialQp = RcConvertQStep2Qp (pWelsSvcRc->iIntraComplexity / +pWelsSvcRc->iTargetBits); +pWelsSvcRc->iInitialQp = WELS_CLIP3 (pWelsSvcRc->iInitialQp, MIN_IDR_QP, MAX_IDR_QP); +pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp; +pWelsSvcRc->iQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp); +pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp; +} + + void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) { - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - int32_t iTl = pEncCtx->uiTemporalId; - SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[iTl]; - int32_t iLumaQp = 0; - - if (0 == pTOverRc->iPFrameNum) { - iLumaQp = pWelsSvcRc->iInitialQp; - } else if (pWelsSvcRc->iCurrentBitsLevel == BITS_EXCEEDED) { - iLumaQp = MAX_LOW_BR_QP; - //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; - if (0 == iTlLast && iTl > 0) - iDeltaQpTemporal += 3; - else if (0 == iTl && iTlLast > 0) - iDeltaQpTemporal -= 3; - - iLumaQp = WELS_CLIP3 (iLumaQp, - pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower + iDeltaQpTemporal, - pWelsSvcRc->iLastCalculatedQScale + pWelsSvcRc->iFrameDeltaQpUpper + iDeltaQpTemporal); - iLumaQp = WELS_CLIP3 (iLumaQp, GOM_MIN_QP_MODE, MAX_LOW_BR_QP); - - pWelsSvcRc->iQStep = RcConvertQp2QStep (iLumaQp); - pWelsSvcRc->iLastCalculatedQScale = iLumaQp; - - if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) { - iLumaQp = WELS_CLIP3 ((iLumaQp * INT_MULTIPLY - pEncCtx->pVaa->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp) / - INT_MULTIPLY, GOM_MIN_QP_MODE, MAX_LOW_BR_QP); - } - - pEncCtx->iGlobalQp = iLumaQp; - - return; - } else { - 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->iQStep = WELS_DIV_ROUND ((pTOverRc->iLinearCmplx * iCmplxRatio), (pWelsSvcRc->iTargetBits * INT_MULTIPLY)); - iLumaQp = RcConvertQStep2Qp (pWelsSvcRc->iQStep); - - //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; - if (0 == iTlLast && iTl > 0) - iDeltaQpTemporal += 3; - else if (0 == iTl && iTlLast > 0) - iDeltaQpTemporal -= 3; - - iLumaQp = WELS_CLIP3 (iLumaQp, - pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower + iDeltaQpTemporal, - pWelsSvcRc->iLastCalculatedQScale + pWelsSvcRc->iFrameDeltaQpUpper + iDeltaQpTemporal); - } - - iLumaQp = WELS_CLIP3 (iLumaQp, GOM_MIN_QP_MODE, GOM_MAX_QP_MODE); - - pWelsSvcRc->iQStep = RcConvertQp2QStep (iLumaQp); - pWelsSvcRc->iLastCalculatedQScale = iLumaQp; - if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) { - - iLumaQp = WELS_DIV_ROUND (iLumaQp * INT_MULTIPLY - pEncCtx->pVaa->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp, - INT_MULTIPLY); - - if (! ((pEncCtx->pSvcParam->iRCMode == RC_BITRATE_MODE) && (pEncCtx->pSvcParam->bEnableFrameSkip == false))) - iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); - - } - pEncCtx->iGlobalQp = iLumaQp; +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +int32_t iTl = pEncCtx->uiTemporalId; +SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[iTl]; +int32_t iLumaQp = 0; + +if (0 == pTOverRc->iPFrameNum) { +iLumaQp = pWelsSvcRc->iInitialQp; +} else if (pWelsSvcRc->iCurrentBitsLevel == BITS_EXCEEDED) { +iLumaQp = MAX_LOW_BR_QP; +//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; +if (0 == iTlLast && iTl > 0) +iDeltaQpTemporal += 3; +else if (0 == iTl && iTlLast > 0) +iDeltaQpTemporal -= 3; + +iLumaQp = WELS_CLIP3 (iLumaQp, +pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower + iDeltaQpTemporal, +pWelsSvcRc->iLastCalculatedQScale + pWelsSvcRc->iFrameDeltaQpUpper + iDeltaQpTemporal); +iLumaQp = WELS_CLIP3 (iLumaQp, GOM_MIN_QP_MODE, MAX_LOW_BR_QP); + +pWelsSvcRc->iQStep = RcConvertQp2QStep (iLumaQp); +pWelsSvcRc->iLastCalculatedQScale = iLumaQp; + +if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) { +iLumaQp = WELS_CLIP3 ((iLumaQp * INT_MULTIPLY - pEncCtx->pVaa->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp) / +INT_MULTIPLY, GOM_MIN_QP_MODE, MAX_LOW_BR_QP); } - + +pEncCtx->iGlobalQp = iLumaQp; + +return; +} else { +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->iQStep = WELS_DIV_ROUND ((pTOverRc->iLinearCmplx * iCmplxRatio), (pWelsSvcRc->iTargetBits * INT_MULTIPLY)); +iLumaQp = RcConvertQStep2Qp (pWelsSvcRc->iQStep); + +//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; +if (0 == iTlLast && iTl > 0) +iDeltaQpTemporal += 3; +else if (0 == iTl && iTlLast > 0) +iDeltaQpTemporal -= 3; + +iLumaQp = WELS_CLIP3 (iLumaQp, +pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower + iDeltaQpTemporal, +pWelsSvcRc->iLastCalculatedQScale + pWelsSvcRc->iFrameDeltaQpUpper + iDeltaQpTemporal); +} + +iLumaQp = WELS_CLIP3 (iLumaQp, GOM_MIN_QP_MODE, GOM_MAX_QP_MODE); + +pWelsSvcRc->iQStep = RcConvertQp2QStep (iLumaQp); +pWelsSvcRc->iLastCalculatedQScale = iLumaQp; +if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) { + +iLumaQp = WELS_DIV_ROUND (iLumaQp * INT_MULTIPLY - pEncCtx->pVaa->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp, +INT_MULTIPLY); + +if (! ((pEncCtx->pSvcParam->iRCMode == RC_BITRATE_MODE) && (pEncCtx->pSvcParam->bEnableFrameSkip == false))) +iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); + +} +pEncCtx->iGlobalQp = iLumaQp; +} + void RcInitSliceInformation (sWelsEncCtx* pEncCtx) { - SSliceCtx* pCurSliceCtx = pEncCtx->pCurDqLayer->pSliceEncCtx; - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[0]; - const int32_t kiSliceNum = pWelsSvcRc->iSliceNum; - const int32_t kiBitsPerMb = WELS_DIV_ROUND (pWelsSvcRc->iTargetBits * INT_MULTIPLY, pWelsSvcRc->iNumberMbFrame); - - for (int32_t i = 0; i < kiSliceNum; i++) { - pSOverRc->iStartMbSlice = - pSOverRc->iEndMbSlice = pCurSliceCtx->pFirstMbInSlice[i]; - pSOverRc->iEndMbSlice += (pCurSliceCtx->pCountMbNumInSlice[i] - 1); - pSOverRc->iTotalQpSlice = 0; - pSOverRc->iTotalMbSlice = 0; - pSOverRc->iTargetBitsSlice = WELS_DIV_ROUND (kiBitsPerMb * pCurSliceCtx->pCountMbNumInSlice[i], INT_MULTIPLY); - pSOverRc->iFrameBitsSlice = 0; - pSOverRc->iGomBitsSlice = 0; - ++ pSOverRc; - } +SSliceCtx* pCurSliceCtx = pEncCtx->pCurDqLayer->pSliceEncCtx; +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[0]; +const int32_t kiSliceNum = pWelsSvcRc->iSliceNum; +const int32_t kiBitsPerMb = WELS_DIV_ROUND (pWelsSvcRc->iTargetBits * INT_MULTIPLY, pWelsSvcRc->iNumberMbFrame); + +for (int32_t i = 0; i < kiSliceNum; i++) { +pSOverRc->iStartMbSlice = +pSOverRc->iEndMbSlice = pCurSliceCtx->pFirstMbInSlice[i]; +pSOverRc->iEndMbSlice += (pCurSliceCtx->pCountMbNumInSlice[i] - 1); +pSOverRc->iTotalQpSlice = 0; +pSOverRc->iTotalMbSlice = 0; +pSOverRc->iTargetBitsSlice = WELS_DIV_ROUND (kiBitsPerMb * pCurSliceCtx->pCountMbNumInSlice[i], INT_MULTIPLY); +pSOverRc->iFrameBitsSlice = 0; +pSOverRc->iGomBitsSlice = 0; +++ pSOverRc; } - +} + void RcDecideTargetBits (sWelsEncCtx* pEncCtx) { - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[pEncCtx->uiTemporalId]; - - pWelsSvcRc->iCurrentBitsLevel = BITS_NORMAL; - //allocate bits - if (pEncCtx->eSliceType == I_SLICE) { - pWelsSvcRc->iTargetBits = WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame * IDR_BITRATE_RATIO, INT_MULTIPLY); - } else { - if (pWelsSvcRc->iRemainingWeights > pTOverRc->iTlayerWeight) - pWelsSvcRc->iTargetBits = (int32_t) ((int64_t)pWelsSvcRc->iRemainingBits * pTOverRc->iTlayerWeight / - pWelsSvcRc->iRemainingWeights); - else //this case should be not hit. needs to more test case to verify this - pWelsSvcRc->iTargetBits = pWelsSvcRc->iRemainingBits; - if ((pWelsSvcRc->iTargetBits <= 0) && ((pEncCtx->pSvcParam->iRCMode == RC_BITRATE_MODE) - && (pEncCtx->pSvcParam->bEnableFrameSkip == false))) { - pWelsSvcRc->iCurrentBitsLevel = BITS_EXCEEDED; - } - pWelsSvcRc->iTargetBits = WELS_CLIP3 (pWelsSvcRc->iTargetBits, pTOverRc->iMinBitsTl, pTOverRc->iMaxBitsTl); - } - pWelsSvcRc->iRemainingWeights -= pTOverRc->iTlayerWeight; +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[pEncCtx->uiTemporalId]; + +pWelsSvcRc->iCurrentBitsLevel = BITS_NORMAL; +//allocate bits +if (pEncCtx->eSliceType == I_SLICE) { +pWelsSvcRc->iTargetBits = WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame * IDR_BITRATE_RATIO, INT_MULTIPLY); +} else { +if (pWelsSvcRc->iRemainingWeights > pTOverRc->iTlayerWeight) +pWelsSvcRc->iTargetBits = (int32_t) ((int64_t)pWelsSvcRc->iRemainingBits * pTOverRc->iTlayerWeight / +pWelsSvcRc->iRemainingWeights); +else //this case should be not hit. needs to more test case to verify this +pWelsSvcRc->iTargetBits = pWelsSvcRc->iRemainingBits; +if ((pWelsSvcRc->iTargetBits <= 0) && ((pEncCtx->pSvcParam->iRCMode == RC_BITRATE_MODE) +&& (pEncCtx->pSvcParam->bEnableFrameSkip == false))) { +pWelsSvcRc->iCurrentBitsLevel = BITS_EXCEEDED; } - - +pWelsSvcRc->iTargetBits = WELS_CLIP3 (pWelsSvcRc->iTargetBits, pTOverRc->iMinBitsTl, pTOverRc->iMaxBitsTl); +} +pWelsSvcRc->iRemainingWeights -= pTOverRc->iTlayerWeight; +} + + void RcInitGomParameters (sWelsEncCtx* pEncCtx) { - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[0]; - const int32_t kiSliceNum = pWelsSvcRc->iSliceNum; - const int32_t kiGlobalQp = pEncCtx->iGlobalQp; - - pWelsSvcRc->iAverageFrameQp = 0; - pWelsSvcRc->iMinFrameQp = 51;; - pWelsSvcRc->iMaxFrameQp = 0; - for (int32_t i = 0; i < kiSliceNum; ++i) { - pSOverRc->iComplexityIndexSlice = 0; - pSOverRc->iCalculatedQpSlice = kiGlobalQp; - ++ pSOverRc; - } - memset (pWelsSvcRc->pGomComplexity, 0, pWelsSvcRc->iGomSize * sizeof (double)); - memset (pWelsSvcRc->pGomCost, 0, pWelsSvcRc->iGomSize * sizeof (int32_t)); +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[0]; +const int32_t kiSliceNum = pWelsSvcRc->iSliceNum; +const int32_t kiGlobalQp = pEncCtx->iGlobalQp; + +pWelsSvcRc->iAverageFrameQp = 0; +pWelsSvcRc->iMinFrameQp = 51;; +pWelsSvcRc->iMaxFrameQp = 0; +for (int32_t i = 0; i < kiSliceNum; ++i) { +pSOverRc->iComplexityIndexSlice = 0; +pSOverRc->iCalculatedQpSlice = kiGlobalQp; +++ pSOverRc; } - +memset (pWelsSvcRc->pGomComplexity, 0, pWelsSvcRc->iGomSize * sizeof (double)); +memset (pWelsSvcRc->pGomCost, 0, pWelsSvcRc->iGomSize * sizeof (int32_t)); +} + void RcCalculateMbQp (sWelsEncCtx* pEncCtx, SMB* pCurMb, const int32_t kiSliceId) { - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[kiSliceId]; - int32_t iLumaQp = pSOverRc->iCalculatedQpSlice; - SDqLayer* pCurLayer = pEncCtx->pCurDqLayer; - const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset; - if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) { - iLumaQp = (int8_t)WELS_CLIP3 (iLumaQp + - pEncCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp[pCurMb->iMbXY], pWelsSvcRc->iMinQp, 51); - } - pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (iLumaQp + kuiChromaQpIndexOffset)]; - pCurMb->uiLumaQp = iLumaQp; +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[kiSliceId]; +int32_t iLumaQp = pSOverRc->iCalculatedQpSlice; +SDqLayer* pCurLayer = pEncCtx->pCurDqLayer; +const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset; +if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) { +iLumaQp = (int8_t)WELS_CLIP3 (iLumaQp + +pEncCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp[pCurMb->iMbXY], pWelsSvcRc->iMinQp, 51); } - +pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (iLumaQp + kuiChromaQpIndexOffset)]; +pCurMb->uiLumaQp = iLumaQp; +} + SWelsSvcRc* RcJudgeBaseUsability (sWelsEncCtx* pEncCtx) { - SWelsSvcRc* pWelsSvcRc = NULL, *pWelsSvcRc_Base = NULL; - SSpatialLayerConfig* pDlpBase = NULL, *pDLayerParam = NULL; - SSpatialLayerInternal* pDlpBaseInternal = NULL; - if (pEncCtx->uiDependencyId <= 0) - return NULL; - pDlpBaseInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId - 1]; - pDlpBase = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId - 1]; - pWelsSvcRc_Base = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId - 1]; - if (pEncCtx->uiTemporalId <= pDlpBaseInternal->iDecompositionStages) { - pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - pWelsSvcRc_Base = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId - 1]; - pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId]; - pDlpBase = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId - 1]; - if ((pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight / pWelsSvcRc->iNumberMbGom) == - (pDlpBase->iVideoWidth * pDlpBase->iVideoHeight / pWelsSvcRc_Base->iNumberMbGom)) - return pWelsSvcRc_Base; - else - return NULL; - } else - return NULL; +SWelsSvcRc* pWelsSvcRc = NULL, *pWelsSvcRc_Base = NULL; +SSpatialLayerConfig* pDlpBase = NULL, *pDLayerParam = NULL; +SSpatialLayerInternal* pDlpBaseInternal = NULL; +if (pEncCtx->uiDependencyId <= 0) +return NULL; +pDlpBaseInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId - 1]; +pDlpBase = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId - 1]; +pWelsSvcRc_Base = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId - 1]; +if (pEncCtx->uiTemporalId <= pDlpBaseInternal->iDecompositionStages) { +pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +pWelsSvcRc_Base = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId - 1]; +pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId]; +pDlpBase = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId - 1]; +if ((pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight / pWelsSvcRc->iNumberMbGom) == +(pDlpBase->iVideoWidth * pDlpBase->iVideoHeight / pWelsSvcRc_Base->iNumberMbGom)) +return pWelsSvcRc_Base; +else +return NULL; +} else +return NULL; } - + void RcGomTargetBits (sWelsEncCtx* pEncCtx, const int32_t kiSliceId) { - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - SWelsSvcRc* pWelsSvcRc_Base = NULL; - SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[kiSliceId]; - - int32_t iAllocateBits = 0; - int32_t iSumSad = 0; - int32_t iLastGomIndex = 0; - int32_t iLeftBits = 0; - const int32_t kiComplexityIndex = pSOverRc->iComplexityIndexSlice; - int32_t i; - - iLastGomIndex = pSOverRc->iEndMbSlice / pWelsSvcRc->iNumberMbGom; - iLeftBits = pSOverRc->iTargetBitsSlice - pSOverRc->iFrameBitsSlice; - - if (iLeftBits <= 0) { - pSOverRc->iGomTargetBits = 0; - return; - } else if (kiComplexityIndex >= iLastGomIndex) { - iAllocateBits = iLeftBits; - } else { - pWelsSvcRc_Base = RcJudgeBaseUsability (pEncCtx); - pWelsSvcRc_Base = (pWelsSvcRc_Base) ? pWelsSvcRc_Base : pWelsSvcRc; - for (i = kiComplexityIndex; 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; +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +SWelsSvcRc* pWelsSvcRc_Base = NULL; +SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[kiSliceId]; + +int32_t iAllocateBits = 0; +int32_t iSumSad = 0; +int32_t iLastGomIndex = 0; +int32_t iLeftBits = 0; +const int32_t kiComplexityIndex = pSOverRc->iComplexityIndexSlice; +int32_t i; + +iLastGomIndex = pSOverRc->iEndMbSlice / pWelsSvcRc->iNumberMbGom; +iLeftBits = pSOverRc->iTargetBitsSlice - pSOverRc->iFrameBitsSlice; + +if (iLeftBits <= 0) { +pSOverRc->iGomTargetBits = 0; +return; +} else if (kiComplexityIndex >= iLastGomIndex) { +iAllocateBits = iLeftBits; +} else { +pWelsSvcRc_Base = RcJudgeBaseUsability (pEncCtx); +pWelsSvcRc_Base = (pWelsSvcRc_Base) ? pWelsSvcRc_Base : pWelsSvcRc; +for (i = kiComplexityIndex; 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; +} + + + void RcCalculateGomQp (sWelsEncCtx* pEncCtx, SMB* pCurMb, int32_t iSliceId) { - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[iSliceId]; - int64_t iBitsRatio = 1; - - int64_t iLeftBits = pSOverRc->iTargetBitsSlice - pSOverRc->iFrameBitsSlice; - int64_t iTargetLeftBits = iLeftBits + pSOverRc->iGomBitsSlice - pSOverRc->iGomTargetBits; - - if (iLeftBits <= 0) { - pSOverRc->iCalculatedQpSlice += 2; - } else { - //globe decision - iBitsRatio = 10000 * iLeftBits / (iTargetLeftBits + 1); - if (iBitsRatio < 8409) //2^(-1.5/6)*10000 - pSOverRc->iCalculatedQpSlice += 2; - else if (iBitsRatio < 9439) //2^(-0.5/6)*10000 - pSOverRc->iCalculatedQpSlice += 1; - else if (iBitsRatio > 10600) //2^(0.5/6)*10000 - pSOverRc->iCalculatedQpSlice -= 1; - else if (iBitsRatio > 11900) //2^(1.5/6)*10000 - pSOverRc->iCalculatedQpSlice -= 2; - } - - pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, - pEncCtx->iGlobalQp - pWelsSvcRc->iQpRangeLowerInFrame, pEncCtx->iGlobalQp + pWelsSvcRc->iQpRangeUpperInFrame); - if (! ((pEncCtx->pSvcParam->iRCMode == RC_BITRATE_MODE) && (pEncCtx->pSvcParam->bEnableFrameSkip == false))) - pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); - - pSOverRc->iGomBitsSlice = 0; - +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[iSliceId]; +int64_t iBitsRatio = 1; + +int64_t iLeftBits = pSOverRc->iTargetBitsSlice - pSOverRc->iFrameBitsSlice; +int64_t iTargetLeftBits = iLeftBits + pSOverRc->iGomBitsSlice - pSOverRc->iGomTargetBits; + +if (iLeftBits <= 0) { +pSOverRc->iCalculatedQpSlice += 2; +} else { +//globe decision +iBitsRatio = 10000 * iLeftBits / (iTargetLeftBits + 1); +if (iBitsRatio < 8409) //2^(-1.5/6)*10000 +pSOverRc->iCalculatedQpSlice += 2; +else if (iBitsRatio < 9439) //2^(-0.5/6)*10000 +pSOverRc->iCalculatedQpSlice += 1; +else if (iBitsRatio > 10600) //2^(0.5/6)*10000 +pSOverRc->iCalculatedQpSlice -= 1; +else if (iBitsRatio > 11900) //2^(1.5/6)*10000 +pSOverRc->iCalculatedQpSlice -= 2; } - + +pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, +pEncCtx->iGlobalQp - pWelsSvcRc->iQpRangeLowerInFrame, pEncCtx->iGlobalQp + pWelsSvcRc->iQpRangeUpperInFrame); +if (! ((pEncCtx->pSvcParam->iRCMode == RC_BITRATE_MODE) && (pEncCtx->pSvcParam->bEnableFrameSkip == false))) +pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); + +pSOverRc->iGomBitsSlice = 0; + +} + void RcVBufferCalculationSkip (sWelsEncCtx* pEncCtx) { - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc; - const int32_t kiOutputBits = WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY); - const int32_t kiOutputMaxBits = WELS_DIV_ROUND (pWelsSvcRc->iMaxBitsPerFrame, INT_MULTIPLY); - //condition 1: whole pBuffer fullness - pWelsSvcRc->iBufferFullnessSkip += (pWelsSvcRc->iFrameDqBits - kiOutputBits); - pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] += (pWelsSvcRc->iFrameDqBits - kiOutputMaxBits); - pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] += (pWelsSvcRc->iFrameDqBits - kiOutputMaxBits); - - WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,"[Rc] bits in buffer = %d, bits in Max bitrate buffer = %d", - pWelsSvcRc->iBufferFullnessSkip,pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW]); - //condition 2: VGOP bits constraint - int32_t iVGopBitsPred = 0; - for (int32_t i = pWelsSvcRc->iFrameCodedInVGop + 1; i < VGOP_SIZE; i++) - iVGopBitsPred += pTOverRc[pWelsSvcRc->iTlOfFrames[i]].iMinBitsTl; - iVGopBitsPred -= pWelsSvcRc->iRemainingBits; - double dIncPercent = iVGopBitsPred * 100.0 * INT_MULTIPLY / (pWelsSvcRc->iBitsPerFrame * VGOP_SIZE) - - (double)VGOP_BITS_PERCENTAGE_DIFF; - - if ((pWelsSvcRc->iBufferFullnessSkip > pWelsSvcRc->iBufferSizeSkip - && pWelsSvcRc->iAverageFrameQp > pWelsSvcRc->iSkipQpValue) - || (dIncPercent > pWelsSvcRc->iRcVaryPercentage)) { - pEncCtx->iSkipFrameFlag = 1; - } +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc; +const int32_t kiOutputBits = WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY); +const int32_t kiOutputMaxBits = WELS_DIV_ROUND (pWelsSvcRc->iMaxBitsPerFrame, INT_MULTIPLY); +//condition 1: whole pBuffer fullness +pWelsSvcRc->iBufferFullnessSkip += (pWelsSvcRc->iFrameDqBits - kiOutputBits); +pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] += (pWelsSvcRc->iFrameDqBits - kiOutputMaxBits); +pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] += (pWelsSvcRc->iFrameDqBits - kiOutputMaxBits); + +WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] bits in buffer = %d, bits in Max bitrate buffer = %d", +pWelsSvcRc->iBufferFullnessSkip, pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW]); +//condition 2: VGOP bits constraint +int32_t iVGopBitsPred = 0; +for (int32_t i = pWelsSvcRc->iFrameCodedInVGop + 1; i < VGOP_SIZE; i++) +iVGopBitsPred += pTOverRc[pWelsSvcRc->iTlOfFrames[i]].iMinBitsTl; +iVGopBitsPred -= pWelsSvcRc->iRemainingBits; +double dIncPercent = iVGopBitsPred * 100.0 * INT_MULTIPLY / (pWelsSvcRc->iBitsPerFrame * VGOP_SIZE) - +(double)VGOP_BITS_PERCENTAGE_DIFF; + +if ((pWelsSvcRc->iBufferFullnessSkip > pWelsSvcRc->iBufferSizeSkip +&& pWelsSvcRc->iAverageFrameQp > pWelsSvcRc->iSkipQpValue) +|| (dIncPercent > pWelsSvcRc->iRcVaryPercentage)) { +pEncCtx->iSkipFrameFlag = 1; } - +} + void WelsRcFrameDelayJudge (void* pCtx, EVideoFrameType eFrameType, long long uiTimeStamp) { - sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx; - SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; - SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId]; - SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId]; +sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx; +SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; +SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId]; +SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId]; + +const int32_t iSentBits = WELS_ROUND (pDLayerParam->iSpatialBitrate / pDLayerParamInternal->fOutputFrameRate); +const int32_t kiOutputMaxBits = WELS_DIV_ROUND (pWelsSvcRc->iMaxBitsPerFrame, INT_MULTIPLY); + +//estimate allowed continual skipped frames in the sequence +const int32_t iPredSkipFramesTarBr = (WELS_DIV_ROUND (pWelsSvcRc->iBufferFullnessSkip, iSentBits) + 1) >> 1; +const int32_t iPredSkipFramesMaxBr = (WELS_MAX (WELS_DIV_ROUND (pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW], +kiOutputMaxBits), 0) + 1) >> 1; + +//calculate the remaining bits in TIME_CHECK_WINDOW +const int32_t iAvailableBitsInTimeWindow = WELS_DIV_ROUND ((TIME_CHECK_WINDOW - pEncCtx->iCheckWindowInterval) * +pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId].iMaxSpatialBitrate, 1000); +const int32_t iAvailableBitsInShiftTimeWindow = WELS_DIV_ROUND ((TIME_CHECK_WINDOW - pEncCtx->iCheckWindowIntervalShift) +* +pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId].iMaxSpatialBitrate, 1000); + +bool bJudgeMaxBRbSkip[TIME_WINDOW_TOTAL];//0: EVEN_TIME_WINDOW; 1: ODD_TIME_WINDOW + +/* 4 cases for frame skipping +1:skipping when buffer size larger than target threshold and current continual skip frames is allowed +2:skipping when MaxBr buffer size + predict frame size - remaining bits in time window < 0 and current continual skip frames is allowed +3:if in last ODD_TIME_WINDOW the MAX Br is overflowed, make more strict skipping conditions +4:such as case 3 in the other window +*/ +bool bJudgeBufferFullSkip = (pEncCtx->iContinualSkipFrames <= iPredSkipFramesTarBr) + && (pWelsSvcRc->iBufferFullnessSkip > pWelsSvcRc->iBufferSizeSkip); +bool bJudgeMaxBRbufferFullSkip = (pEncCtx->iContinualSkipFrames <= iPredSkipFramesMaxBr) + && (pEncCtx->iCheckWindowInterval > TIME_CHECK_WINDOW / 2) + && (pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] + pWelsSvcRc->iPredFrameBit - iAvailableBitsInTimeWindow > 0); +bJudgeMaxBRbSkip[EVEN_TIME_WINDOW] = (pEncCtx->iCheckWindowInterval > TIME_CHECK_WINDOW / 2) + && (pWelsSvcRc->bNeedShiftWindowCheck[EVEN_TIME_WINDOW]) + && (pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] + pWelsSvcRc->iPredFrameBit - iAvailableBitsInTimeWindow + + kiOutputMaxBits > 0); +bJudgeMaxBRbSkip[ODD_TIME_WINDOW] = (pEncCtx->iCheckWindowIntervalShift > TIME_CHECK_WINDOW / 2) + && (pWelsSvcRc->bNeedShiftWindowCheck[ODD_TIME_WINDOW]) + && (pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] + pWelsSvcRc->iPredFrameBit - iAvailableBitsInShiftTimeWindow + + kiOutputMaxBits > 0); - const int32_t iSentBits = WELS_ROUND (pDLayerParam->iSpatialBitrate / pDLayerParamInternal->fOutputFrameRate); - const int32_t kiOutputMaxBits = WELS_DIV_ROUND (pWelsSvcRc->iMaxBitsPerFrame, INT_MULTIPLY); - - //estimate allowed continual skipped frames in the sequence - const int32_t iPredSkipFramesTarBr = (WELS_DIV_ROUND(pWelsSvcRc->iBufferFullnessSkip, iSentBits) + 1) >> 1; - const int32_t iPredSkipFramesMaxBr = (WELS_MAX(WELS_DIV_ROUND(pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW], kiOutputMaxBits), 0) + 1) >> 1; - - //calculate the remaining bits in TIME_CHECK_WINDOW - const int32_t iAvailableBitsInTimeWindow = WELS_DIV_ROUND ((TIME_CHECK_WINDOW - pEncCtx->iCheckWindowInterval)* - pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId].iMaxSpatialBitrate, 1000); - const int32_t iAvailableBitsInShiftTimeWindow = WELS_DIV_ROUND ((TIME_CHECK_WINDOW - pEncCtx->iCheckWindowIntervalShift)* - pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId].iMaxSpatialBitrate, 1000); - - bool bJudgeMaxBRbSkip[TIME_WINDOW_TOTAL];//0: EVEN_TIME_WINDOW; 1: ODD_TIME_WINDOW - - /* 4 cases for frame skipping - 1:skipping when buffer size larger than target threshold and current continual skip frames is allowed - 2:skipping when MaxBr buffer size + predict frame size - remaining bits in time window < 0 and current continual skip frames is allowed - 3:if in last ODD_TIME_WINDOW the MAX Br is overflowed, make more strict skipping conditions - 4:such as case 3 in the other window - */ - bool bJudgeBufferFullSkip = (pEncCtx->iContinualSkipFrames <= iPredSkipFramesTarBr) && (pWelsSvcRc->iBufferFullnessSkip > pWelsSvcRc->iBufferSizeSkip); - bool bJudgeMaxBRbufferFullSkip = (pEncCtx->iContinualSkipFrames <= iPredSkipFramesMaxBr) && (pEncCtx->iCheckWindowInterval > TIME_CHECK_WINDOW / 2) - && (pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] + pWelsSvcRc->iPredFrameBit - iAvailableBitsInTimeWindow > 0); - bJudgeMaxBRbSkip[EVEN_TIME_WINDOW] = (pEncCtx->iCheckWindowInterval > TIME_CHECK_WINDOW / 2) && (pWelsSvcRc->bNeedShiftWindowCheck[EVEN_TIME_WINDOW]) - && (pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] + pWelsSvcRc->iPredFrameBit - iAvailableBitsInTimeWindow + kiOutputMaxBits > 0); - bJudgeMaxBRbSkip[ODD_TIME_WINDOW] = (pEncCtx->iCheckWindowIntervalShift > TIME_CHECK_WINDOW / 2) && (pWelsSvcRc->bNeedShiftWindowCheck[ODD_TIME_WINDOW]) - && (pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] + pWelsSvcRc->iPredFrameBit - iAvailableBitsInShiftTimeWindow + kiOutputMaxBits > 0); - - pWelsSvcRc->bSkipFlag = false; - if (bJudgeBufferFullSkip || bJudgeMaxBRbufferFullSkip || bJudgeMaxBRbSkip[EVEN_TIME_WINDOW] || bJudgeMaxBRbSkip[ODD_TIME_WINDOW]) { - pWelsSvcRc->bSkipFlag = true; - pWelsSvcRc->iSkipFrameNum++; - pWelsSvcRc->iSkipFrameInVGop++; - pWelsSvcRc->iBufferFullnessSkip -= iSentBits; - pWelsSvcRc->iRemainingBits += iSentBits; - pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] -= kiOutputMaxBits; - pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] -= kiOutputMaxBits; - WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,"[Rc] bits in buffer = %d, bits in Max bitrate buffer = %d, Predict skip frames = %d and %d", - pWelsSvcRc->iBufferFullnessSkip, pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW], iPredSkipFramesTarBr, iPredSkipFramesMaxBr); - pWelsSvcRc->iBufferFullnessSkip = WELS_MAX (pWelsSvcRc->iBufferFullnessSkip, 0); - } +pWelsSvcRc->bSkipFlag = false; +if (bJudgeBufferFullSkip || bJudgeMaxBRbufferFullSkip || bJudgeMaxBRbSkip[EVEN_TIME_WINDOW] + || bJudgeMaxBRbSkip[ODD_TIME_WINDOW]) { + pWelsSvcRc->bSkipFlag = true; + pWelsSvcRc->iSkipFrameNum++; + pWelsSvcRc->iSkipFrameInVGop++; + pWelsSvcRc->iBufferFullnessSkip -= iSentBits; + pWelsSvcRc->iRemainingBits += iSentBits; + pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] -= kiOutputMaxBits; + pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] -= kiOutputMaxBits; + WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG, + "[Rc] bits in buffer = %d, bits in Max bitrate buffer = %d, Predict skip frames = %d and %d", + pWelsSvcRc->iBufferFullnessSkip, pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW], iPredSkipFramesTarBr, + iPredSkipFramesMaxBr); + pWelsSvcRc->iBufferFullnessSkip = WELS_MAX (pWelsSvcRc->iBufferFullnessSkip, 0); +} } //loop each layer to check if have skip frame when RC and frame skip enable (maxbr>0) bool CheckFrameSkipBasedMaxbr (void* pCtx, int32_t iSpatialNum, EVideoFrameType eFrameType, - const uint32_t uiTimeStamp) { - sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx; - SSpatialPicIndex* pSpatialIndexMap = &pEncCtx->sSpatialIndexMap[0]; - bool bSkipMustFlag = false; - if (pEncCtx->pSvcParam->bEnableFrameSkip) { - if ((RC_QUALITY_MODE == pEncCtx->pSvcParam->iRCMode) || (RC_BITRATE_MODE == pEncCtx->pSvcParam->iRCMode)) { + const uint32_t uiTimeStamp) { + sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx; + SSpatialPicIndex* pSpatialIndexMap = &pEncCtx->sSpatialIndexMap[0]; + bool bSkipMustFlag = false; + if (pEncCtx->pSvcParam->bEnableFrameSkip) { + if ((RC_QUALITY_MODE == pEncCtx->pSvcParam->iRCMode) || (RC_BITRATE_MODE == pEncCtx->pSvcParam->iRCMode)) { - for (int32_t i = 0; i < iSpatialNum; i++) { - if (UNSPECIFIED_BIT_RATE == pEncCtx->pSvcParam->sSpatialLayers[i].iMaxSpatialBitrate) { - break; - } - pEncCtx->uiDependencyId = (uint8_t) (pSpatialIndexMap + i)->iDid; - pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge (pEncCtx, eFrameType, uiTimeStamp); - if (true == pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId].bSkipFlag) { - bSkipMustFlag = true; - pEncCtx->iContinualSkipFrames++; - break; - } + for (int32_t i = 0; i < iSpatialNum; i++) { + if (UNSPECIFIED_BIT_RATE == pEncCtx->pSvcParam->sSpatialLayers[i].iMaxSpatialBitrate) { + break; + } + pEncCtx->uiDependencyId = (uint8_t) (pSpatialIndexMap + i)->iDid; + pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge (pEncCtx, eFrameType, uiTimeStamp); + if (true == pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId].bSkipFlag) { + bSkipMustFlag = true; + pEncCtx->iContinualSkipFrames++; + break; } } } - return bSkipMustFlag; + } + return bSkipMustFlag; } -void UpdateBufferWhenFrameSkipped(void* pCtx, int32_t iSpatialNum) { +void UpdateBufferWhenFrameSkipped (void* pCtx, int32_t iSpatialNum) { sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx; SSpatialPicIndex* pSpatialIndexMap = &pEncCtx->sSpatialIndexMap[0]; @@ -799,8 +810,8 @@ void UpdateBufferWhenFrameSkipped(void* pCtx, int32_t iSpatialNum) { pWelsSvcRc->iBufferFullnessSkip = pWelsSvcRc->iBufferFullnessSkip - kiOutputBits; pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] -= kiOutputMaxBits; pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] -= kiOutputMaxBits; - WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,"[Rc] bits in buffer = %d, bits in Max bitrate buffer = %d", - pWelsSvcRc->iBufferFullnessSkip,pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW]); + WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] bits in buffer = %d, bits in Max bitrate buffer = %d", + pWelsSvcRc->iBufferFullnessSkip, pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW]); pWelsSvcRc->iBufferFullnessSkip = WELS_MAX (pWelsSvcRc->iBufferFullnessSkip, 0); @@ -812,21 +823,23 @@ void UpdateBufferWhenFrameSkipped(void* pCtx, int32_t iSpatialNum) { pEncCtx->iContinualSkipFrames++; } -void UpdateMaxBrCheckWindowStatus(void* pCtx, int32_t iSpatialNum, const long long uiTimeStamp) { +void UpdateMaxBrCheckWindowStatus (void* pCtx, int32_t iSpatialNum, const long long uiTimeStamp) { sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx; SSpatialPicIndex* pSpatialIndexMap = &pEncCtx->sSpatialIndexMap[0]; - if(pEncCtx->bCheckWindowStatusRefreshFlag) { + if (pEncCtx->bCheckWindowStatusRefreshFlag) { pEncCtx->iCheckWindowCurrentTs = uiTimeStamp; } else { pEncCtx->iCheckWindowCurrentTs = pEncCtx->iCheckWindowStartTs = uiTimeStamp; pEncCtx->bCheckWindowStatusRefreshFlag = true; } pEncCtx->iCheckWindowInterval = (int32_t) (pEncCtx->iCheckWindowCurrentTs - pEncCtx->iCheckWindowStartTs); - if(pEncCtx->iCheckWindowInterval >= (TIME_CHECK_WINDOW >> 1) && !pEncCtx->bCheckWindowShiftResetFlag) { + if (pEncCtx->iCheckWindowInterval >= (TIME_CHECK_WINDOW >> 1) && !pEncCtx->bCheckWindowShiftResetFlag) { pEncCtx->bCheckWindowShiftResetFlag = true; for (int32_t i = 0; i < iSpatialNum; i++) { int32_t iCurDid = (pSpatialIndexMap + i)->iDid; - if (pEncCtx->pWelsSvcRc[iCurDid].iBufferMaxBRFullness[ODD_TIME_WINDOW] > 0 && pEncCtx->pWelsSvcRc[iCurDid].iBufferMaxBRFullness[ODD_TIME_WINDOW] != pEncCtx->pWelsSvcRc[iCurDid].iBufferMaxBRFullness[0]) { + if (pEncCtx->pWelsSvcRc[iCurDid].iBufferMaxBRFullness[ODD_TIME_WINDOW] > 0 + && pEncCtx->pWelsSvcRc[iCurDid].iBufferMaxBRFullness[ODD_TIME_WINDOW] != + pEncCtx->pWelsSvcRc[iCurDid].iBufferMaxBRFullness[0]) { pEncCtx->pWelsSvcRc[iCurDid].bNeedShiftWindowCheck[EVEN_TIME_WINDOW] = true; } else { pEncCtx->pWelsSvcRc[iCurDid].bNeedShiftWindowCheck[EVEN_TIME_WINDOW] = false; @@ -835,9 +848,9 @@ void UpdateMaxBrCheckWindowStatus(void* pCtx, int32_t iSpatialNum, const long lo } } pEncCtx->iCheckWindowIntervalShift = pEncCtx->iCheckWindowInterval >= (TIME_CHECK_WINDOW >> 1) ? - pEncCtx->iCheckWindowInterval - (TIME_CHECK_WINDOW >> 1) : pEncCtx->iCheckWindowInterval + (TIME_CHECK_WINDOW >> 1); + pEncCtx->iCheckWindowInterval - (TIME_CHECK_WINDOW >> 1) : pEncCtx->iCheckWindowInterval + (TIME_CHECK_WINDOW >> 1); - if(pEncCtx->iCheckWindowInterval >= TIME_CHECK_WINDOW || pEncCtx->iCheckWindowInterval == 0) { + if (pEncCtx->iCheckWindowInterval >= TIME_CHECK_WINDOW || pEncCtx->iCheckWindowInterval == 0) { pEncCtx->iCheckWindowStartTs = pEncCtx->iCheckWindowCurrentTs; pEncCtx->iCheckWindowInterval = 0; pEncCtx->bCheckWindowShiftResetFlag = false; @@ -875,16 +888,19 @@ void RcTraceFrameBits (void* pCtx, long long uiTimeStamp) { SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; if (pWelsSvcRc->iPredFrameBit != 0) - pWelsSvcRc->iPredFrameBit = (int32_t) (LAST_FRAME_PREDICT_WEIGHT * pWelsSvcRc->iFrameDqBits + (1 - LAST_FRAME_PREDICT_WEIGHT) * pWelsSvcRc->iPredFrameBit); + pWelsSvcRc->iPredFrameBit = (int32_t) (LAST_FRAME_PREDICT_WEIGHT * pWelsSvcRc->iFrameDqBits + + (1 - LAST_FRAME_PREDICT_WEIGHT) * pWelsSvcRc->iPredFrameBit); else pWelsSvcRc->iPredFrameBit = pWelsSvcRc->iFrameDqBits; WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG, - "[Rc] Frame timestamp = %lld, Frame type =%d, encoding_qp%d, average qp = %3d, max qp = %3d, min qp = %3d, index = %8d,\ + "[Rc] Frame timestamp = %lld, Frame type =%d, encoding_qp%d, average qp = %3d, max qp = %3d, min qp = %3d, index = %8d,\ iTid = %1d, used = %8d, bitsperframe = %8d, target = %8d, remaingbits = %8d, skipbuffersize = %8d", - uiTimeStamp,pEncCtx->eSliceType, pEncCtx->uiDependencyId, pWelsSvcRc->iAverageFrameQp,pWelsSvcRc->iMaxFrameQp,pWelsSvcRc->iMinFrameQp, - pEncCtx->iFrameIndex, pEncCtx->uiTemporalId, pWelsSvcRc->iFrameDqBits,WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY), - pWelsSvcRc->iTargetBits, pWelsSvcRc->iRemainingBits, pWelsSvcRc->iBufferSizeSkip); + uiTimeStamp, pEncCtx->eSliceType, pEncCtx->uiDependencyId, pWelsSvcRc->iAverageFrameQp, pWelsSvcRc->iMaxFrameQp, + pWelsSvcRc->iMinFrameQp, + pEncCtx->iFrameIndex, pEncCtx->uiTemporalId, pWelsSvcRc->iFrameDqBits, WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame, + INT_MULTIPLY), + pWelsSvcRc->iTargetBits, pWelsSvcRc->iRemainingBits, pWelsSvcRc->iBufferSizeSkip); } @@ -1062,8 +1078,8 @@ void WelsRcMbInfoUpdateGom (void* pCtx, SMB* pCurMb, int32_t iCostLuma, SSlice* pWelsSvcRc->pGomCost[kiComplexityIndex] += iCostLuma; - pWelsSvcRc->iMinFrameQp = WELS_MIN(pWelsSvcRc->iMinFrameQp,pCurMb->uiLumaQp); - pWelsSvcRc->iMaxFrameQp = WELS_MAX(pWelsSvcRc->iMaxFrameQp,pCurMb->uiLumaQp); + 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++; @@ -1161,7 +1177,7 @@ void WelRcPictureInitScc (void* pCtx) { pEncCtx->iGlobalQp = WELS_CLIP3 (iQp, MIN_IDR_QP, MAX_IDR_QP); } else { int32_t iTargetBits = WELS_ROUND (((float)iBitRate / pDLayerConfig->fFrameRate)); //iBitRate / 10; - int32_t iQstep = (int32_t)(WELS_DIV_ROUND64 (iFrameCplx * pWelsSvcRc->iAvgCost2Bits, iTargetBits)); + int32_t iQstep = (int32_t) (WELS_DIV_ROUND64 (iFrameCplx * pWelsSvcRc->iAvgCost2Bits, iTargetBits)); int32_t iQp = RcConvertQStep2Qp (iQstep); iDeltaQp = iQp - iBaseQp; if (pWelsSvcRc->iBufferFullnessSkip > iBitRate) { @@ -1215,7 +1231,7 @@ void WelsRcFrameDelayJudgeScc (void* pCtx, EVideoFrameType eFrameType, long long iSentBits = WELS_MAX (iSentBits, 0); const int32_t iVbufferThRatio = (eFrameType == videoFrameTypeI - || eFrameType == videoFrameTypeIDR) ? VIRTUAL_BUFFER_HIGH_TH : VIRTUAL_BUFFER_LOW_TH; + || eFrameType == videoFrameTypeIDR) ? VIRTUAL_BUFFER_HIGH_TH : VIRTUAL_BUFFER_LOW_TH; const int32_t iVbufferTh = WELS_DIV_ROUND ((((int64_t)iBitRate) * iVbufferThRatio), INT_MULTIPLY); pWelsSvcRc->iBufferFullnessSkip -= iSentBits; @@ -1227,7 +1243,9 @@ void WelsRcFrameDelayJudgeScc (void* pCtx, EVideoFrameType eFrameType, long long } if (pWelsSvcRc->bSkipFlag) { pWelsSvcRc->iSkipFrameNum++; - WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_INFO, "SCC iSkipFrameNum = %d,buffer = %d,threadhold = %d,bitrate = %d,timestamp=%lld\n", pWelsSvcRc->iSkipFrameNum,pWelsSvcRc->iBufferFullnessSkip,iVbufferTh,iBitRate,uiTimeStamp); + WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_INFO, + "SCC iSkipFrameNum = %d,buffer = %d,threadhold = %d,bitrate = %d,timestamp=%lld\n", pWelsSvcRc->iSkipFrameNum, + pWelsSvcRc->iBufferFullnessSkip, iVbufferTh, iBitRate, uiTimeStamp); } pWelsSvcRc->uiLastTimeStamp = uiTimeStamp; }