1237 lines · 48.0 KB · C++
RawDownload
/*! * \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 {  #define VIRTUAL_BUFFER_LOW_TH   120 //*INT_MULTIPLY#define VIRTUAL_BUFFER_HIGH_TH  180 //*INT_MULTIPLY //#define _TEST_TEMP_RC_#ifdef _TEST_TEMP_RC_//#define _NOT_USE_AQ_FOR_TEST_FILE* fp_test_rc = NULL;FILE* fp_vgop = NULL;#endif#define _BITS_RANGE 0const 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 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;}} static inline int32_t RcConvertQp2QStep (int32_t 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));} 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;#ifdef _TEST_TEMP_RC_fp_test_rc = fopen ("testRC.dat", "w");fp_vgop = fopen ("vgop.dat", "w");#endiffor (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 = _BITS_RANGE;	// % -- for temppWelsSvcRc->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_MULTIPLYconst 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 framefor (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;int32_t input_iBitsPerFrame = WELS_ROUND (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 updatedpWelsSvcRc->iBufferSizeSkip = WELS_DIV_ROUND (pWelsSvcRc->iBitRate * pWelsSvcRc->iSkipBufferRatio, INT_MULTIPLY);pWelsSvcRc->iBufferSizePadding = WELS_DIV_ROUND (pWelsSvcRc->iBitRate * PADDING_BUFFER_RATIO, INT_MULTIPLY); //change remaining bitsif (pWelsSvcRc->iBitsPerFrame > REMAIN_BITS_TH)pWelsSvcRc->iRemainingBits = pWelsSvcRc->iRemainingBits * input_iBitsPerFrame / pWelsSvcRc->iBitsPerFrame;pWelsSvcRc->iBitsPerFrame = input_iBitsPerFrame;}  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;} 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 ModelpWelsSvcRc->iIntraComplexity = 0;pWelsSvcRc->iIntraMbCount = 0; //P frame R-Q Modelfor (i = 0; i <= kiHighestTid; i++) {pTOverRc[i].iPFrameNum = 0;pTOverRc[i].iLinearCmplx = 0;pTOverRc[i].iFrameCmplxMean = 0;} pWelsSvcRc->iBufferFullnessSkip = 0;pWelsSvcRc->iBufferFullnessPadding = 0; pWelsSvcRc->iGopIndexInVGop = 0;pWelsSvcRc->iRemainingBits = 0;pWelsSvcRc->iBitsPerFrame	= 0; //Backup the initial bitrate and fpspWelsSvcRc->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;} elsereturn 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);#ifdef _TEST_TEMP_Rc_fprintf (fp_vgop, "%d\n", WELS_ROUND ((double)iTotalBits / iFrameInVGop));#endifWelsLog (& (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) {#if GOM_TRACE_FLAGRcTraceVGopBitrate (pEncCtx);#endifRcInitTlWeight (pEncCtx);RcInitVGop (pEncCtx);} else if (pWelsSvcRc->iGopIndexInVGop == pWelsSvcRc->iGopNumberInVGop || pEncCtx->eSliceType == I_SLICE) {#if GOM_TRACE_FLAGRcTraceVGopBitrate (pEncCtx);#endifRcInitVGop (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:32double 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);elsedBpp = 0.1; //Area*2if (pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight <= 28800) // 90p video:160*90iBppIndex = 0;else if (pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight <= 115200) // 180p video:320*180iBppIndex = 1;else if (pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight <= 460800) // 360p video:640*360iBppIndex = 2;elseiBppIndex = 3; //Searchfor (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 complexityif (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 QPint32_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 QPint32_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;

Lines 1–500 of 1237.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t