/*! * \copy * Copyright (c) 2009-2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * * ratectl.c * * Abstract * Rate Control * * History * 9/8/2009 Created * 12/26/2011 Modified * * * *************************************************************************/#include "rc.h"#include "encoder_context.h"#include "utils.h"#include "svc_enc_golomb.h" namespace WelsEnc { 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)) void RcInitLayerMemory (SWelsSvcRc* pWelsSvcRc, CMemoryAlign* pMA, const int32_t kiMaxTl) { 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; } void RcFreeLayerMemory (SWelsSvcRc* pWelsSvcRc, CMemoryAlign* pMA) { 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];}static inline int32_t RcConvertQStep2Qp (int32_t iQpStep) { if (iQpStep <= g_kiQpToQstepTable[0]) //Qp step too small, return qp=0 return 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++) { pWelsSvcRc = &pEncCtx->pWelsSvcRc[j]; pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[j]; iMbWidth = (pDLayerParam->iVideoWidth >> 4); pWelsSvcRc->iNumberMbFrame = iMbWidth * (pDLayerParam->iVideoHeight >> 4); pWelsSvcRc->iRcVaryPercentage = pEncCtx->pSvcParam->iBitsVaryPercentage; // % -- for temp pWelsSvcRc->iRcVaryRatio = pWelsSvcRc->iRcVaryPercentage; pWelsSvcRc->iBufferFullnessSkip = 0; pWelsSvcRc->uiLastTimeStamp = 0; pWelsSvcRc->iCost2BitsIntra = 1; pWelsSvcRc->iAvgCost2Bits = 1; pWelsSvcRc->iSkipBufferRatio = SKIP_RATIO; pWelsSvcRc->iContinualSkipFrames = 0; 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 = pEncCtx->pSvcParam->iMinQp; pWelsSvcRc->iMaxQp = pEncCtx->pSvcParam->iMaxQp; 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; pWelsSvcRc->bEnableGomQp = true; RcInitLayerMemory (pWelsSvcRc, pEncCtx->pMemAlign, 1 + pEncCtx->pSvcParam->sDependencyLayers[j].iHighestTemporalId); bMultiSliceMode = ((SM_RASTER_SLICE == pDLayerParam->sSliceArgument.uiSliceMode) || (SM_SIZELIMITED_SLICE == pDLayerParam->sSliceArgument.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]; pTOverRc[n].iMinQp = pWelsSvcRc->iMinQp + (n << 1); pTOverRc[n].iMinQp = WELS_CLIP3 (pTOverRc[n].iMinQp, 0, 51); pTOverRc[n].iMaxQp = pWelsSvcRc->iMaxQp + (n << 1); pTOverRc[n].iMaxQp = WELS_CLIP3 (pTOverRc[n].iMaxQp, pTOverRc[n].iMinQp, 51); ++ 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; const int32_t input_iBitsPerFrame = WELS_DIV_ROUND (pDLayerParam->iSpatialBitrate, pDLayerParamInternal->fOutputFrameRate); const int64_t kiGopBits = input_iBitsPerFrame * kiGopSize; int32_t i; pWelsSvcRc->iBitRate = pDLayerParam->iSpatialBitrate; pWelsSvcRc->fFrameRate = pDLayerParamInternal->fOutputFrameRate; int32_t iTargetVaryRange = ((MAX_BITS_VARY_PERCENTAGE - pWelsSvcRc->iRcVaryRatio) >> 1); int32_t iMinBitsRatio = MAX_BITS_VARY_PERCENTAGE - iTargetVaryRange; int32_t iMaxBitsRatio = MAX_BITS_VARY_PERCENTAGE_x3d2; for (i = 0; i <= kiHighestTid; i++) { const int64_t kdConstraitBits = kiGopBits * pTOverRc[i].iTlayerWeight; pTOverRc[i].iMinBitsTl = WELS_DIV_ROUND (kdConstraitBits * iMinBitsRatio, MAX_BITS_VARY_PERCENTAGE * WEIGHT_MULTIPLY); pTOverRc[i].iMaxBitsTl = WELS_DIV_ROUND (kdConstraitBits * iMaxBitsRatio, 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 = WELS_DIV_ROUND (static_cast<int64_t> (pWelsSvcRc->iRemainingBits) * input_iBitsPerFrame, pWelsSvcRc->iBitsPerFrame); } pWelsSvcRc->iBitsPerFrame = input_iBitsPerFrame; pWelsSvcRc->iMaxBitsPerFrame = WELS_DIV_ROUND (pDLayerParam->iMaxSpatialBitrate, pDLayerParamInternal->fOutputFrameRate);} 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 = VGOP_SIZE * pWelsSvcRc->iBitsPerFrame; 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; pWelsSvcRc->iIntraComplxMean = 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->fOutputFrameRate; 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->fOutputFrameRate) > EPSN || (pWelsSvcRc->dPreviousFps - pDLayerParamInternal->fOutputFrameRate) < -EPSN) { pWelsSvcRc->iPreviousBitrate = pDLayerParam->iSpatialBitrate; pWelsSvcRc->dPreviousFps = pDLayerParamInternal->fOutputFrameRate; return true; } else return false;} #if GOM_TRACE_FLAGvoid 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_DEBUG, "[Rc] VGOPbitrate%d: %d ", kiDid, iVGopBitrate); if (iTotalBits > 0) { iTid = 0; while (iTid <= kiHighestTid) { WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG, "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) {#if GOM_TRACE_FLAG RcTraceVGopBitrate (pEncCtx);#endif RcInitTlWeight (pEncCtx); RcInitVGop (pEncCtx); } else if (pWelsSvcRc->iGopIndexInVGop == pWelsSvcRc->iGopNumberInVGop || pEncCtx->eSliceType == I_SLICE) {#if GOM_TRACE_FLAG RcTraceVGopBitrate (pEncCtx);#endif RcInitVGop (pEncCtx); } pWelsSvcRc->iGopIndexInVGop++;} void RcCalculateIdrQp (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; int32_t iQpRangeArray[4][2] = {{37, 25}, {36, 24}, {35, 23}, {34, 22}}; int64_t iFrameComplexity = pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity; if (pEncCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) { SVAAFrameInfoExt* pVaa = static_cast<SVAAFrameInfoExt*> (pEncCtx->pVaa); iFrameComplexity = pVaa->sComplexityScreenParam.iFrameComplexity; } SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId]; SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId]; if (pDLayerParamInternal->fOutputFrameRate > EPSN && pDLayerParam->iVideoWidth && pDLayerParam->iVideoHeight) dBpp = (double) (pDLayerParam->iSpatialBitrate) / (double) (pDLayerParamInternal->fOutputFrameRate * 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; } int32_t iMaxQp = iQpRangeArray[i][0]; int32_t iMinQp = iQpRangeArray[i][1]; iMinQp = WELS_CLIP3 (iMinQp, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); iMaxQp = WELS_CLIP3 (iMaxQp, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); if (0 == pWelsSvcRc->iIdrNum) { //the first IDR frame pWelsSvcRc->iInitialQp = dInitialQPArray[iBppIndex][i]; } else { //obtain the idr qp using previous idr complexity if (pWelsSvcRc->iNumberMbFrame != pWelsSvcRc->iIntraMbCount) { pWelsSvcRc->iIntraComplexity = pWelsSvcRc->iIntraComplexity * pWelsSvcRc->iNumberMbFrame / pWelsSvcRc->iIntraMbCount; } int64_t iCmplxRatio = WELS_DIV_ROUND64 (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, iMinQp, iMaxQp); pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp; pWelsSvcRc->iQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp); pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp; pWelsSvcRc->iMinFrameQp = WELS_CLIP3 (pEncCtx->iGlobalQp - DELTA_QP_BGD_THD, iMinQp, iMaxQp); pWelsSvcRc->iMaxFrameQp = WELS_CLIP3 (pEncCtx->iGlobalQp + DELTA_QP_BGD_THD, iMinQp, iMaxQp); } void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) { SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; int32_t iTl = pEncCtx->uiTemporalId; SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[iTl]; int32_t iLumaQp = 0; int32_t iDeltaQpTemporal = 0; int64_t iFrameComplexity = pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity; if (pEncCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) { SVAAFrameInfoExt* pVaa = static_cast<SVAAFrameInfoExt*> (pEncCtx->pVaa); iFrameComplexity = pVaa->sComplexityScreenParam.iFrameComplexity; } if (0 == pTOverRc->iPFrameNum) { iLumaQp = pWelsSvcRc->iInitialQp; } else if (pWelsSvcRc->iCurrentBitsLevel == BITS_EXCEEDED) { 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]; iDeltaQpTemporal = iTl - iTlLast; if (0 == iTlLast && iTl > 0) iDeltaQpTemporal += 1; else if (0 == iTl && iTlLast > 0) iDeltaQpTemporal -= 1; } else { int64_t iCmplxRatio = WELS_DIV_ROUND64 (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); WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG, "iCmplxRatio = %d,frameComplexity = %" PRId64 ",iFrameCmplxMean = %" PRId64 ",iQStep = %d,iLumaQp = %d", (int)iCmplxRatio, iFrameComplexity, pTOverRc->iFrameCmplxMean, pWelsSvcRc->iQStep, iLumaQp);//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 += 1; else if (0 == iTl && iTlLast > 0) iDeltaQpTemporal -= 1; } pWelsSvcRc->iMinFrameQp = WELS_CLIP3 (pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower +Lines 1–500 of 1556. Load more
/*! * \copy * Copyright (c) 2009-2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * * ratectl.c * * Abstract * Rate Control * * History * 9/8/2009 Created * 12/26/2011 Modified * * * *************************************************************************/ #include "rc.h" #include "encoder_context.h" #include "utils.h" #include "svc_enc_golomb.h" namespace WelsEnc { 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)) void RcInitLayerMemory (SWelsSvcRc* pWelsSvcRc, CMemoryAlign* pMA, const int32_t kiMaxTl) { 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; } void RcFreeLayerMemory (SWelsSvcRc* pWelsSvcRc, CMemoryAlign* pMA) { 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]; } static inline int32_t RcConvertQStep2Qp (int32_t iQpStep) { if (iQpStep <= g_kiQpToQstepTable[0]) //Qp step too small, return qp=0 return 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++) { pWelsSvcRc = &pEncCtx->pWelsSvcRc[j]; pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[j]; iMbWidth = (pDLayerParam->iVideoWidth >> 4); pWelsSvcRc->iNumberMbFrame = iMbWidth * (pDLayerParam->iVideoHeight >> 4); pWelsSvcRc->iRcVaryPercentage = pEncCtx->pSvcParam->iBitsVaryPercentage; // % -- for temp pWelsSvcRc->iRcVaryRatio = pWelsSvcRc->iRcVaryPercentage; pWelsSvcRc->iBufferFullnessSkip = 0; pWelsSvcRc->uiLastTimeStamp = 0; pWelsSvcRc->iCost2BitsIntra = 1; pWelsSvcRc->iAvgCost2Bits = 1; pWelsSvcRc->iSkipBufferRatio = SKIP_RATIO; pWelsSvcRc->iContinualSkipFrames = 0; 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 = pEncCtx->pSvcParam->iMinQp; pWelsSvcRc->iMaxQp = pEncCtx->pSvcParam->iMaxQp; 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; pWelsSvcRc->bEnableGomQp = true; RcInitLayerMemory (pWelsSvcRc, pEncCtx->pMemAlign, 1 + pEncCtx->pSvcParam->sDependencyLayers[j].iHighestTemporalId); bMultiSliceMode = ((SM_RASTER_SLICE == pDLayerParam->sSliceArgument.uiSliceMode) || (SM_SIZELIMITED_SLICE == pDLayerParam->sSliceArgument.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]; pTOverRc[n].iMinQp = pWelsSvcRc->iMinQp + (n << 1); pTOverRc[n].iMinQp = WELS_CLIP3 (pTOverRc[n].iMinQp, 0, 51); pTOverRc[n].iMaxQp = pWelsSvcRc->iMaxQp + (n << 1); pTOverRc[n].iMaxQp = WELS_CLIP3 (pTOverRc[n].iMaxQp, pTOverRc[n].iMinQp, 51); ++ 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; const int32_t input_iBitsPerFrame = WELS_DIV_ROUND (pDLayerParam->iSpatialBitrate, pDLayerParamInternal->fOutputFrameRate); const int64_t kiGopBits = input_iBitsPerFrame * kiGopSize; int32_t i; pWelsSvcRc->iBitRate = pDLayerParam->iSpatialBitrate; pWelsSvcRc->fFrameRate = pDLayerParamInternal->fOutputFrameRate; int32_t iTargetVaryRange = ((MAX_BITS_VARY_PERCENTAGE - pWelsSvcRc->iRcVaryRatio) >> 1); int32_t iMinBitsRatio = MAX_BITS_VARY_PERCENTAGE - iTargetVaryRange; int32_t iMaxBitsRatio = MAX_BITS_VARY_PERCENTAGE_x3d2; for (i = 0; i <= kiHighestTid; i++) { const int64_t kdConstraitBits = kiGopBits * pTOverRc[i].iTlayerWeight; pTOverRc[i].iMinBitsTl = WELS_DIV_ROUND (kdConstraitBits * iMinBitsRatio, MAX_BITS_VARY_PERCENTAGE * WEIGHT_MULTIPLY); pTOverRc[i].iMaxBitsTl = WELS_DIV_ROUND (kdConstraitBits * iMaxBitsRatio, 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 = WELS_DIV_ROUND (static_cast<int64_t> (pWelsSvcRc->iRemainingBits) * input_iBitsPerFrame, pWelsSvcRc->iBitsPerFrame); } pWelsSvcRc->iBitsPerFrame = input_iBitsPerFrame; pWelsSvcRc->iMaxBitsPerFrame = WELS_DIV_ROUND (pDLayerParam->iMaxSpatialBitrate, pDLayerParamInternal->fOutputFrameRate); } 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 = VGOP_SIZE * pWelsSvcRc->iBitsPerFrame; 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; pWelsSvcRc->iIntraComplxMean = 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->fOutputFrameRate; 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->fOutputFrameRate) > EPSN || (pWelsSvcRc->dPreviousFps - pDLayerParamInternal->fOutputFrameRate) < -EPSN) { pWelsSvcRc->iPreviousBitrate = pDLayerParam->iSpatialBitrate; pWelsSvcRc->dPreviousFps = pDLayerParamInternal->fOutputFrameRate; 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_DEBUG, "[Rc] VGOPbitrate%d: %d ", kiDid, iVGopBitrate); if (iTotalBits > 0) { iTid = 0; while (iTid <= kiHighestTid) { WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG, "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) { #if GOM_TRACE_FLAG RcTraceVGopBitrate (pEncCtx); #endif RcInitTlWeight (pEncCtx); RcInitVGop (pEncCtx); } else if (pWelsSvcRc->iGopIndexInVGop == pWelsSvcRc->iGopNumberInVGop || pEncCtx->eSliceType == I_SLICE) { #if GOM_TRACE_FLAG RcTraceVGopBitrate (pEncCtx); #endif RcInitVGop (pEncCtx); } pWelsSvcRc->iGopIndexInVGop++; } void RcCalculateIdrQp (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; int32_t iQpRangeArray[4][2] = {{37, 25}, {36, 24}, {35, 23}, {34, 22}}; int64_t iFrameComplexity = pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity; if (pEncCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) { SVAAFrameInfoExt* pVaa = static_cast<SVAAFrameInfoExt*> (pEncCtx->pVaa); iFrameComplexity = pVaa->sComplexityScreenParam.iFrameComplexity; } SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId]; SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId]; if (pDLayerParamInternal->fOutputFrameRate > EPSN && pDLayerParam->iVideoWidth && pDLayerParam->iVideoHeight) dBpp = (double) (pDLayerParam->iSpatialBitrate) / (double) (pDLayerParamInternal->fOutputFrameRate * 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; } int32_t iMaxQp = iQpRangeArray[i][0]; int32_t iMinQp = iQpRangeArray[i][1]; iMinQp = WELS_CLIP3 (iMinQp, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); iMaxQp = WELS_CLIP3 (iMaxQp, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); if (0 == pWelsSvcRc->iIdrNum) { //the first IDR frame pWelsSvcRc->iInitialQp = dInitialQPArray[iBppIndex][i]; } else { //obtain the idr qp using previous idr complexity if (pWelsSvcRc->iNumberMbFrame != pWelsSvcRc->iIntraMbCount) { pWelsSvcRc->iIntraComplexity = pWelsSvcRc->iIntraComplexity * pWelsSvcRc->iNumberMbFrame / pWelsSvcRc->iIntraMbCount; } int64_t iCmplxRatio = WELS_DIV_ROUND64 (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, iMinQp, iMaxQp); pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp; pWelsSvcRc->iQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp); pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp; pWelsSvcRc->iMinFrameQp = WELS_CLIP3 (pEncCtx->iGlobalQp - DELTA_QP_BGD_THD, iMinQp, iMaxQp); pWelsSvcRc->iMaxFrameQp = WELS_CLIP3 (pEncCtx->iGlobalQp + DELTA_QP_BGD_THD, iMinQp, iMaxQp); } void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) { SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; int32_t iTl = pEncCtx->uiTemporalId; SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[iTl]; int32_t iLumaQp = 0; int32_t iDeltaQpTemporal = 0; int64_t iFrameComplexity = pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity; if (pEncCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) { SVAAFrameInfoExt* pVaa = static_cast<SVAAFrameInfoExt*> (pEncCtx->pVaa); iFrameComplexity = pVaa->sComplexityScreenParam.iFrameComplexity; } if (0 == pTOverRc->iPFrameNum) { iLumaQp = pWelsSvcRc->iInitialQp; } else if (pWelsSvcRc->iCurrentBitsLevel == BITS_EXCEEDED) { 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]; iDeltaQpTemporal = iTl - iTlLast; if (0 == iTlLast && iTl > 0) iDeltaQpTemporal += 1; else if (0 == iTl && iTlLast > 0) iDeltaQpTemporal -= 1; } else { int64_t iCmplxRatio = WELS_DIV_ROUND64 (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); WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG, "iCmplxRatio = %d,frameComplexity = %" PRId64 ",iFrameCmplxMean = %" PRId64 ",iQStep = %d,iLumaQp = %d", (int)iCmplxRatio, iFrameComplexity, pTOverRc->iFrameCmplxMean, pWelsSvcRc->iQStep, iLumaQp); //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 += 1; else if (0 == iTl && iTlLast > 0) iDeltaQpTemporal -= 1; } pWelsSvcRc->iMinFrameQp = WELS_CLIP3 (pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower +