Rate control refine to fit MAX bitrate requirement
This commit is contained in:
parent
ea93f3943e
commit
c01606c28a
@ -169,7 +169,14 @@ typedef struct TagWelsEncCtx {
|
||||
|
||||
// Rate control routine
|
||||
SWelsSvcRc* pWelsSvcRc;
|
||||
bool bCheckWindowStatusRefreshFlag;
|
||||
int64_t iCheckWindowStartTs;
|
||||
int64_t iCheckWindowCurrentTs;
|
||||
int32_t iCheckWindowInterval;
|
||||
int32_t iCheckWindowIntervalShift;
|
||||
bool bCheckWindowShiftResetFlag;
|
||||
int32_t iSkipFrameFlag; //_GOM_RC_
|
||||
int32_t iContinualSkipFrames;
|
||||
int32_t iGlobalQp; // global qp
|
||||
|
||||
// VAA
|
||||
|
@ -119,10 +119,18 @@ enum {
|
||||
#define SMOOTH_FACTOR_MIN_VALUE 2 // *INT_MULTIPLY
|
||||
//#define VGOP_BITS_MIN_RATIO 0.8
|
||||
//skip and padding
|
||||
#define TIME_CHECK_WINDOW 5000 // ms
|
||||
#define SKIP_RATIO 50 // *INT_MULTIPLY
|
||||
#define LAST_FRAME_PREDICT_WEIGHT 0.5
|
||||
#define PADDING_BUFFER_RATIO 50 // *INT_MULTIPLY
|
||||
#define PADDING_THRESHOLD 5 //*INT_MULTIPLY
|
||||
|
||||
enum {
|
||||
EVEN_TIME_WINDOW =0,
|
||||
ODD_TIME_WINDOW =1,
|
||||
TIME_WINDOW_TOTAL =2
|
||||
};
|
||||
|
||||
typedef struct TagRCSlicing {
|
||||
int32_t iComplexityIndexSlice;
|
||||
int32_t iCalculatedQpSlice;
|
||||
@ -152,7 +160,7 @@ int32_t iFrameCmplxMean;
|
||||
|
||||
typedef struct TagWelsRc {
|
||||
int32_t iRcVaryPercentage;
|
||||
int32_t iRcVaryRatio;
|
||||
int32_t iRcVaryRatio;
|
||||
|
||||
int32_t iInitialQp; //initial qp
|
||||
int32_t iBitRate;
|
||||
@ -160,6 +168,7 @@ int32_t iPreviousBitrate;
|
||||
int32_t iPreviousGopSize;
|
||||
double fFrameRate;
|
||||
int64_t iBitsPerFrame; // *INT_MULTIPLY
|
||||
int64_t iMaxBitsPerFrame; // *INT_MULTIPLY
|
||||
double dPreviousFps;
|
||||
|
||||
// bits allocation and status
|
||||
@ -185,7 +194,7 @@ int32_t iMinFrameQp;
|
||||
int32_t iMaxFrameQp;
|
||||
int32_t iNumberMbFrame;
|
||||
int32_t iNumberMbGom;
|
||||
int32_t iSliceNum;
|
||||
int32_t iSliceNum;
|
||||
int32_t iGomSize;
|
||||
|
||||
int32_t iSkipFrameNum;
|
||||
@ -201,15 +210,18 @@ int32_t iMinQp;
|
||||
int32_t iMaxQp;
|
||||
//int32_t delta_adaptive_qp;
|
||||
int32_t iSkipBufferRatio;
|
||||
|
||||
|
||||
int32_t iQStep; // *INT_MULTIPLY
|
||||
int32_t iFrameDeltaQpUpper;
|
||||
int32_t iFrameDeltaQpLower;
|
||||
int32_t iLastCalculatedQScale;
|
||||
|
||||
|
||||
//for skip frame and padding
|
||||
int32_t iBufferSizeSkip;
|
||||
int32_t iBufferFullnessSkip;
|
||||
int32_t iBufferMaxBRFullness[TIME_WINDOW_TOTAL];//0: EVEN_TIME_WINDOW; 1: ODD_TIME_WINDOW
|
||||
int32_t iPredFrameBit;
|
||||
bool bNeedShiftWindowCheck[TIME_WINDOW_TOTAL];
|
||||
int32_t iBufferSizePadding;
|
||||
int32_t iBufferFullnessPadding;
|
||||
int32_t iPaddingSize;
|
||||
@ -244,6 +256,10 @@ PWelsRCMBInitFunc pfWelsRcMbInit;
|
||||
PWelsRCMBInfoUpdateFunc pfWelsRcMbInfoUpdate;
|
||||
} SWelsRcFunc;
|
||||
|
||||
bool CheckFrameSkipBasedMaxbr (void* pCtx, int32_t iSpatialNum, EVideoFrameType eFrameType,
|
||||
const uint32_t uiTimeStamp);
|
||||
void UpdateBufferWhenFrameSkipped(void* pCtx, int32_t iSpatialNum);
|
||||
void UpdateMaxBrCheckWindowStatus(void* pCtx, int32_t iSpatialNum, const long long uiTimeStamp);
|
||||
void RcTraceFrameBits (void* pEncCtx, long long uiTimeStamp);
|
||||
void WelsRcInitModule (void* pCtx, RC_MODES iRcMode);
|
||||
void WelsRcFreeMemory (void* pCtx);
|
||||
|
@ -3035,29 +3035,6 @@ int32_t GetSubSequenceId (sWelsEncCtx* pCtx, EVideoFrameType eFrameType) {
|
||||
return iSubSeqId;
|
||||
}
|
||||
|
||||
//loop each layer to check if have skip frame when RC and frame skip enable (maxbr>0)
|
||||
bool CheckFrameSkipBasedMaxbr (sWelsEncCtx* pCtx, int32_t iSpatialNum, EVideoFrameType eFrameType,
|
||||
const long long uiTimeStamp) {
|
||||
SSpatialPicIndex* pSpatialIndexMap = &pCtx->sSpatialIndexMap[0];
|
||||
bool bSkipMustFlag = false;
|
||||
if (pCtx->pSvcParam->bEnableFrameSkip) {
|
||||
if ((RC_QUALITY_MODE == pCtx->pSvcParam->iRCMode) || (RC_BITRATE_MODE == pCtx->pSvcParam->iRCMode)) {
|
||||
for (int32_t i = 0; i < iSpatialNum; i++) {
|
||||
if (UNSPECIFIED_BIT_RATE == pCtx->pSvcParam->sSpatialLayers[i].iMaxSpatialBitrate) {
|
||||
break;
|
||||
}
|
||||
pCtx->uiDependencyId = (uint8_t) (pSpatialIndexMap + i)->iDid;
|
||||
pCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge (pCtx, eFrameType, uiTimeStamp);
|
||||
if (true == pCtx->pWelsSvcRc[pCtx->uiDependencyId].bSkipFlag) {
|
||||
bSkipMustFlag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bSkipMustFlag;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief core svc encoding process
|
||||
*
|
||||
@ -3108,29 +3085,37 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
|
||||
pFbi->uiTimeStamp = pSrcPic->uiTimeStamp;
|
||||
// perform csc/denoise/downsample/padding, generate spatial layers
|
||||
iSpatialNum = pCtx->pVpp->BuildSpatialPicList (pCtx, pSrcPic);
|
||||
|
||||
if (pCtx->pSvcParam->bEnableFrameSkip) {
|
||||
UpdateMaxBrCheckWindowStatus(pCtx, iSpatialNum, pSrcPic->uiTimeStamp);
|
||||
}
|
||||
|
||||
if (iSpatialNum < 1) { // skip due to temporal layer settings (different frame rate)
|
||||
++ pCtx->iCodingIndex;
|
||||
pFbi->eFrameType = videoFrameTypeSkip;
|
||||
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %lld, Frame type =%d",
|
||||
pSrcPic->uiTimeStamp, pFbi->eFrameType);
|
||||
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %lld, skip one frame, continual skipped %d frames",
|
||||
pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames);
|
||||
return ENC_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
eFrameType = DecideFrameType (pCtx, iSpatialNum);
|
||||
if (eFrameType == videoFrameTypeSkip) {
|
||||
UpdateBufferWhenFrameSkipped(pCtx, iSpatialNum);
|
||||
pFbi->eFrameType = eFrameType;
|
||||
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %lld, Frame type =%d",
|
||||
pSrcPic->uiTimeStamp, pFbi->eFrameType);
|
||||
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %lld, skip one frame, continual skipped %d frames",
|
||||
pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames);
|
||||
return ENC_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
//loop each layer to check if have skip frame when RC and frame skip enable
|
||||
if (CheckFrameSkipBasedMaxbr (pCtx, iSpatialNum, eFrameType, pSrcPic->uiTimeStamp)) {
|
||||
if (CheckFrameSkipBasedMaxbr (pCtx, iSpatialNum, eFrameType, (uint32_t)pSrcPic->uiTimeStamp)) {
|
||||
pFbi->eFrameType = videoFrameTypeSkip;
|
||||
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %lld, Frame type =%d",
|
||||
pSrcPic->uiTimeStamp, pFbi->eFrameType);
|
||||
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "[Rc] Frame timestamp = %lld, skip one frame, continual skipped %d frames",
|
||||
pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames);
|
||||
return ENC_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
pCtx->iContinualSkipFrames = 0;
|
||||
InitFrameCoding (pCtx, eFrameType);
|
||||
|
||||
iCurTid = GetTemporalLevel (&pSvcParam->sDependencyLayers[pSpatialIndexMap->iDid], pCtx->iCodingIndex,
|
||||
|
@ -247,6 +247,8 @@ void RcUpdateBitrateFps (sWelsEncCtx* pEncCtx) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -288,6 +290,9 @@ void RcInitRefreshParameter (sWelsEncCtx* pEncCtx) {
|
||||
}
|
||||
|
||||
pWelsSvcRc->iBufferFullnessSkip = 0;
|
||||
pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] = 0;
|
||||
pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] = 0;
|
||||
pWelsSvcRc->iPredFrameBit = 0;
|
||||
pWelsSvcRc->iBufferFullnessPadding = 0;
|
||||
|
||||
pWelsSvcRc->iGopIndexInVGop = 0;
|
||||
@ -682,9 +687,14 @@ void RcVBufferCalculationSkip (sWelsEncCtx* pEncCtx) {
|
||||
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
|
||||
SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc;
|
||||
const int32_t kiOutputBits = WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY);
|
||||
const int32_t kiOutputMaxBits = WELS_DIV_ROUND (pWelsSvcRc->iMaxBitsPerFrame, INT_MULTIPLY);
|
||||
//condition 1: whole pBuffer fullness
|
||||
pWelsSvcRc->iBufferFullnessSkip += (pWelsSvcRc->iFrameDqBits - kiOutputBits);
|
||||
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,"[Rc] bits in buffer = %3d",pWelsSvcRc->iBufferFullnessSkip);
|
||||
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++)
|
||||
@ -697,16 +707,6 @@ void RcVBufferCalculationSkip (sWelsEncCtx* pEncCtx) {
|
||||
&& pWelsSvcRc->iAverageFrameQp > pWelsSvcRc->iSkipQpValue)
|
||||
|| (dIncPercent > pWelsSvcRc->iRcVaryPercentage)) {
|
||||
pEncCtx->iSkipFrameFlag = 1;
|
||||
pWelsSvcRc->iBufferFullnessSkip = pWelsSvcRc->iBufferFullnessSkip - kiOutputBits;
|
||||
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,"[Rc] bits in buffer = %3d",pWelsSvcRc->iBufferFullnessSkip);
|
||||
}
|
||||
|
||||
pWelsSvcRc->iBufferFullnessSkip = WELS_MAX (pWelsSvcRc->iBufferFullnessSkip, 0);
|
||||
|
||||
if (pEncCtx->iSkipFrameFlag == 1) {
|
||||
pWelsSvcRc->iRemainingBits += kiOutputBits;
|
||||
pWelsSvcRc->iSkipFrameNum++;
|
||||
pWelsSvcRc->iSkipFrameInVGop++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -716,19 +716,144 @@ void WelsRcFrameDelayJudge (void* pCtx, EVideoFrameType eFrameType, long long ui
|
||||
SSpatialLayerConfig* pDLayerParam = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId];
|
||||
SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];
|
||||
|
||||
int32_t iSentBits = WELS_ROUND (pDLayerParam->iSpatialBitrate / pDLayerParamInternal->fOutputFrameRate);
|
||||
const int32_t iSentBits = WELS_ROUND (pDLayerParam->iSpatialBitrate / pDLayerParamInternal->fOutputFrameRate);
|
||||
const int32_t kiOutputMaxBits = WELS_DIV_ROUND (pWelsSvcRc->iMaxBitsPerFrame, INT_MULTIPLY);
|
||||
|
||||
//estimate allowed continual skipped frames in the sequence
|
||||
const int32_t iPredSkipFramesTarBr = (WELS_DIV_ROUND(pWelsSvcRc->iBufferFullnessSkip, iSentBits) + 1) >> 1;
|
||||
const int32_t iPredSkipFramesMaxBr = (WELS_MAX(WELS_DIV_ROUND(pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW], kiOutputMaxBits), 0) + 1) >> 1;
|
||||
|
||||
//calculate the remaining bits in TIME_CHECK_WINDOW
|
||||
const int32_t iAvailableBitsInTimeWindow = WELS_DIV_ROUND ((TIME_CHECK_WINDOW - pEncCtx->iCheckWindowInterval)*
|
||||
pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId].iMaxSpatialBitrate, 1000);
|
||||
const int32_t iAvailableBitsInShiftTimeWindow = WELS_DIV_ROUND ((TIME_CHECK_WINDOW - pEncCtx->iCheckWindowIntervalShift)*
|
||||
pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId].iMaxSpatialBitrate, 1000);
|
||||
|
||||
bool bJudgeMaxBRbSkip[TIME_WINDOW_TOTAL];//0: EVEN_TIME_WINDOW; 1: ODD_TIME_WINDOW
|
||||
|
||||
/* 4 cases for frame skipping
|
||||
1:skipping when buffer size larger than target threshold and current continual skip frames is allowed
|
||||
2:skipping when MaxBr buffer size + predict frame size - remaining bits in time window < 0 and current continual skip frames is allowed
|
||||
3:if in last ODD_TIME_WINDOW the MAX Br is overflowed, make more strict skipping conditions
|
||||
4:such as case 3 in the other window
|
||||
*/
|
||||
bool bJudgeBufferFullSkip = (pEncCtx->iContinualSkipFrames <= iPredSkipFramesTarBr) && (pWelsSvcRc->iBufferFullnessSkip > pWelsSvcRc->iBufferSizeSkip);
|
||||
bool bJudgeMaxBRbufferFullSkip = (pEncCtx->iContinualSkipFrames <= iPredSkipFramesMaxBr) && (pEncCtx->iCheckWindowInterval > TIME_CHECK_WINDOW / 2)
|
||||
&& (pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] + pWelsSvcRc->iPredFrameBit - iAvailableBitsInTimeWindow > 0);
|
||||
bJudgeMaxBRbSkip[EVEN_TIME_WINDOW] = (pEncCtx->iCheckWindowInterval > TIME_CHECK_WINDOW / 2) && (pWelsSvcRc->bNeedShiftWindowCheck[EVEN_TIME_WINDOW])
|
||||
&& (pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] + pWelsSvcRc->iPredFrameBit - iAvailableBitsInTimeWindow + kiOutputMaxBits > 0);
|
||||
bJudgeMaxBRbSkip[ODD_TIME_WINDOW] = (pEncCtx->iCheckWindowIntervalShift > TIME_CHECK_WINDOW / 2) && (pWelsSvcRc->bNeedShiftWindowCheck[ODD_TIME_WINDOW])
|
||||
&& (pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] + pWelsSvcRc->iPredFrameBit - iAvailableBitsInShiftTimeWindow + kiOutputMaxBits > 0);
|
||||
|
||||
pWelsSvcRc->bSkipFlag = false;
|
||||
if (pWelsSvcRc->iBufferFullnessSkip > pWelsSvcRc->iBufferSizeSkip) {
|
||||
if (bJudgeBufferFullSkip || bJudgeMaxBRbufferFullSkip || bJudgeMaxBRbSkip[EVEN_TIME_WINDOW] || bJudgeMaxBRbSkip[ODD_TIME_WINDOW]) {
|
||||
pWelsSvcRc->bSkipFlag = true;
|
||||
pWelsSvcRc->iSkipFrameNum++;
|
||||
pWelsSvcRc->iSkipFrameInVGop++;
|
||||
pWelsSvcRc->iBufferFullnessSkip -= iSentBits;
|
||||
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,"[Rc] bits in buffer = %3d",pWelsSvcRc->iBufferFullnessSkip);
|
||||
pWelsSvcRc->iRemainingBits += iSentBits;
|
||||
pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] -= kiOutputMaxBits;
|
||||
pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] -= kiOutputMaxBits;
|
||||
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,"[Rc] bits in buffer = %d, bits in Max bitrate buffer = %d, Predict skip frames = %d and %d",
|
||||
pWelsSvcRc->iBufferFullnessSkip, pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW], iPredSkipFramesTarBr, iPredSkipFramesMaxBr);
|
||||
pWelsSvcRc->iBufferFullnessSkip = WELS_MAX (pWelsSvcRc->iBufferFullnessSkip, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//loop each layer to check if have skip frame when RC and frame skip enable (maxbr>0)
|
||||
bool CheckFrameSkipBasedMaxbr (void* pCtx, int32_t iSpatialNum, EVideoFrameType eFrameType,
|
||||
const uint32_t uiTimeStamp) {
|
||||
sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx;
|
||||
SSpatialPicIndex* pSpatialIndexMap = &pEncCtx->sSpatialIndexMap[0];
|
||||
bool bSkipMustFlag = false;
|
||||
if (pEncCtx->pSvcParam->bEnableFrameSkip) {
|
||||
if ((RC_QUALITY_MODE == pEncCtx->pSvcParam->iRCMode) || (RC_BITRATE_MODE == pEncCtx->pSvcParam->iRCMode)) {
|
||||
|
||||
for (int32_t i = 0; i < iSpatialNum; i++) {
|
||||
if (UNSPECIFIED_BIT_RATE == pEncCtx->pSvcParam->sSpatialLayers[i].iMaxSpatialBitrate) {
|
||||
break;
|
||||
}
|
||||
pEncCtx->uiDependencyId = (uint8_t) (pSpatialIndexMap + i)->iDid;
|
||||
pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge (pEncCtx, eFrameType, uiTimeStamp);
|
||||
if (true == pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId].bSkipFlag) {
|
||||
bSkipMustFlag = true;
|
||||
pEncCtx->iContinualSkipFrames++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bSkipMustFlag;
|
||||
}
|
||||
|
||||
void UpdateBufferWhenFrameSkipped(void* pCtx, int32_t iSpatialNum) {
|
||||
sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx;
|
||||
SSpatialPicIndex* pSpatialIndexMap = &pEncCtx->sSpatialIndexMap[0];
|
||||
|
||||
for (int32_t i = 0; i < iSpatialNum; i++) {
|
||||
int32_t iCurDid = (pSpatialIndexMap + i)->iDid;
|
||||
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[iCurDid];
|
||||
const int32_t kiOutputBits = WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY);
|
||||
const int32_t kiOutputMaxBits = WELS_DIV_ROUND (pWelsSvcRc->iMaxBitsPerFrame, INT_MULTIPLY);
|
||||
pWelsSvcRc->iBufferFullnessSkip = pWelsSvcRc->iBufferFullnessSkip - kiOutputBits;
|
||||
pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] -= kiOutputMaxBits;
|
||||
pWelsSvcRc->iBufferMaxBRFullness[ODD_TIME_WINDOW] -= kiOutputMaxBits;
|
||||
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,"[Rc] bits in buffer = %d, bits in Max bitrate buffer = %d",
|
||||
pWelsSvcRc->iBufferFullnessSkip,pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW]);
|
||||
|
||||
pWelsSvcRc->iBufferFullnessSkip = WELS_MAX (pWelsSvcRc->iBufferFullnessSkip, 0);
|
||||
|
||||
pWelsSvcRc->iRemainingBits += kiOutputBits;
|
||||
pWelsSvcRc->iSkipFrameNum++;
|
||||
pWelsSvcRc->iSkipFrameInVGop++;
|
||||
|
||||
}
|
||||
pEncCtx->iContinualSkipFrames++;
|
||||
}
|
||||
|
||||
void UpdateMaxBrCheckWindowStatus(void* pCtx, int32_t iSpatialNum, const long long uiTimeStamp) {
|
||||
sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx;
|
||||
SSpatialPicIndex* pSpatialIndexMap = &pEncCtx->sSpatialIndexMap[0];
|
||||
if(pEncCtx->bCheckWindowStatusRefreshFlag) {
|
||||
pEncCtx->iCheckWindowCurrentTs = uiTimeStamp;
|
||||
} else {
|
||||
pEncCtx->iCheckWindowCurrentTs = pEncCtx->iCheckWindowStartTs = uiTimeStamp;
|
||||
pEncCtx->bCheckWindowStatusRefreshFlag = true;
|
||||
}
|
||||
pEncCtx->iCheckWindowInterval = pEncCtx->iCheckWindowCurrentTs - pEncCtx->iCheckWindowStartTs;
|
||||
if(pEncCtx->iCheckWindowInterval >= (TIME_CHECK_WINDOW >> 1) && !pEncCtx->bCheckWindowShiftResetFlag) {
|
||||
pEncCtx->bCheckWindowShiftResetFlag = true;
|
||||
for (int32_t i = 0; i < iSpatialNum; i++) {
|
||||
int32_t iCurDid = (pSpatialIndexMap + i)->iDid;
|
||||
if (pEncCtx->pWelsSvcRc[iCurDid].iBufferMaxBRFullness[ODD_TIME_WINDOW] > 0 && pEncCtx->pWelsSvcRc[iCurDid].iBufferMaxBRFullness[ODD_TIME_WINDOW] != pEncCtx->pWelsSvcRc[iCurDid].iBufferMaxBRFullness[0]) {
|
||||
pEncCtx->pWelsSvcRc[iCurDid].bNeedShiftWindowCheck[EVEN_TIME_WINDOW] = true;
|
||||
} else {
|
||||
pEncCtx->pWelsSvcRc[iCurDid].bNeedShiftWindowCheck[EVEN_TIME_WINDOW] = false;
|
||||
}
|
||||
pEncCtx->pWelsSvcRc[iCurDid].iBufferMaxBRFullness[ODD_TIME_WINDOW] = 0;
|
||||
}
|
||||
}
|
||||
pEncCtx->iCheckWindowIntervalShift = pEncCtx->iCheckWindowInterval >= (TIME_CHECK_WINDOW >> 1) ?
|
||||
pEncCtx->iCheckWindowInterval - (TIME_CHECK_WINDOW >> 1) : pEncCtx->iCheckWindowInterval + (TIME_CHECK_WINDOW >> 1);
|
||||
|
||||
if(pEncCtx->iCheckWindowInterval >= TIME_CHECK_WINDOW || pEncCtx->iCheckWindowInterval == 0) {
|
||||
pEncCtx->iCheckWindowStartTs = pEncCtx->iCheckWindowCurrentTs;
|
||||
pEncCtx->iCheckWindowInterval = 0;
|
||||
pEncCtx->bCheckWindowShiftResetFlag = false;
|
||||
for (int32_t i = 0; i < iSpatialNum; i++) {
|
||||
int32_t iCurDid = (pSpatialIndexMap + i)->iDid;
|
||||
if (pEncCtx->pWelsSvcRc[iCurDid].iBufferMaxBRFullness[EVEN_TIME_WINDOW] > 0) {
|
||||
pEncCtx->pWelsSvcRc[iCurDid].bNeedShiftWindowCheck[ODD_TIME_WINDOW] = true;
|
||||
} else {
|
||||
pEncCtx->pWelsSvcRc[iCurDid].bNeedShiftWindowCheck[ODD_TIME_WINDOW] = false;
|
||||
}
|
||||
pEncCtx->pWelsSvcRc[iCurDid].iBufferMaxBRFullness[EVEN_TIME_WINDOW] = 0;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void RcVBufferCalculationPadding (sWelsEncCtx* pEncCtx) {
|
||||
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
|
||||
const int32_t kiOutputBits = WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY);
|
||||
@ -749,6 +874,11 @@ void RcTraceFrameBits (void* pCtx, long long uiTimeStamp) {
|
||||
sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx;
|
||||
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
|
||||
|
||||
if (pWelsSvcRc->iPredFrameBit != 0)
|
||||
pWelsSvcRc->iPredFrameBit = LAST_FRAME_PREDICT_WEIGHT * pWelsSvcRc->iFrameDqBits + (1 - LAST_FRAME_PREDICT_WEIGHT) * pWelsSvcRc->iPredFrameBit;
|
||||
else
|
||||
pWelsSvcRc->iPredFrameBit = pWelsSvcRc->iFrameDqBits;
|
||||
|
||||
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
|
||||
"[Rc] Frame timestamp = %lld, Frame type =%d, encoding_qp%d, average qp = %3d, max qp = %3d, min qp = %3d, index = %8d,\
|
||||
iTid = %1d, used = %8d, bitsperframe = %8d, target = %8d, remaingbits = %8d, skipbuffersize = %8d",
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user