ref: c3de0f99c5fab19d469737fcc9c1af8446831c2e
parent: afd82b2cfad086137126d5a83157a066569e5b14
parent: 3ae2507c994c2a928589e7956a92b018eebce8d2
author: sijchen <sijchen@cisco.com>
date: Fri Dec 19 08:27:52 EST 2014
Merge pull request #1653 from ruil2/framerate remove macro definition to the header file
--- a/codec/encoder/core/inc/rc.h
+++ b/codec/encoder/core/inc/rc.h
@@ -125,6 +125,11 @@
#define PADDING_BUFFER_RATIO 50 // *INT_MULTIPLY
#define PADDING_THRESHOLD 5 //*INT_MULTIPLY
+#define VIRTUAL_BUFFER_LOW_TH 120 //*INT_MULTIPLY
+#define VIRTUAL_BUFFER_HIGH_TH 180 //*INT_MULTIPLY
+
+#define _BITS_RANGE 0
+
enum {
EVEN_TIME_WINDOW =0,
ODD_TIME_WINDOW =1,
--- a/codec/encoder/core/src/ratectl.cpp
+++ b/codec/encoder/core/src/ratectl.cpp
@@ -49,726 +49,722 @@
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
+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 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->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->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;
+ 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;
+ }
}
-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;
-
+ 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;
-}
+ 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;
+ 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;
}
-}
-}
-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);
-}
+ 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);
-
+ 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);
+ 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;
-
+ 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->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;
-
+ 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);
+ 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;
+ 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;
+ }
+ }
+ }
}
-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);
+ RcInitVGop (pEncCtx);
+ }
+ pWelsSvcRc->iGopIndexInVGop++;
}
-pWelsSvcRc->iGopIndexInVGop++;
-}
-
-
+
+
void RcInitIdrQp (sWelsEncCtx* pEncCtx) {
-double dBpp = 0;
-int32_t i;
-
+ 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;
-
+ 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;
-
+ 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;
+ 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;
}
-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];
+ 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;
+ 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;
}
-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;
+ 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);
-
+ 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);
+ 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;
}
-
-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;
+ 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;
+ 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;
}
-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;
+ 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));
}
-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);
+ 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;
}
-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];
+ 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;
}
-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 {
+ 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;
+ 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;
+
}
-
-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);
+ 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]);
+ 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;
+ 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];
-
-const int32_t iSentBits = WELS_ROUND (pDLayerParam->iSpatialBitrate / pDLayerParamInternal->fOutputFrameRate);
-const int32_t kiOutputMaxBits = WELS_DIV_ROUND (pWelsSvcRc->iMaxBitsPerFrame, INT_MULTIPLY);
-
+ 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;
-
+ 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 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);
-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);
-}
+ 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);
+ }
}