1043 lines · 42.1 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 WelsSVCEnc { //#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, "rc_layer_memory");   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, "rc_layer_memory");    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");#endif  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 = _BITS_RANGE;	// % -- 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;} 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 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 = 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 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->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;} #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));#endif    WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_INFO, "[Rc] VGOPbitrate%d: %d \n", kiDid, iVGopBitrate);    if (iTotalBits > 0) {      iTid = 0;      while (iTid <= kiHighestTid) {        WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_INFO, "T%d=%8.3f \n", 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 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;} 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;}  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,

Lines 1–500 of 1043.

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