diff --git a/codec/encoder/core/inc/rc.h b/codec/encoder/core/inc/rc.h index 099da7d1..20f79e50 100644 --- a/codec/encoder/core/inc/rc.h +++ b/codec/encoder/core/inc/rc.h @@ -122,7 +122,7 @@ enum { #define SKIP_RATIO 50 // *INT_MULTIPLY #define PADDING_BUFFER_RATIO 50 // *INT_MULTIPLY #define PADDING_THRESHOLD 5 //*INT_MULTIPLY - + typedef struct TagRCSlicing { int32_t iComplexityIndexSlice; int32_t iCalculatedQpSlice; @@ -137,7 +137,7 @@ int32_t iGomBitsSlice; int32_t iGomTargetBits; //int32_t gom_coded_mb; } SRCSlicing; - + typedef struct TagRCTemporal { int32_t iMinBitsTl; int32_t iMaxBitsTl; @@ -147,13 +147,13 @@ int32_t iGopBitsDq; int64_t iLinearCmplx; // *INT_MULTIPLY int32_t iPFrameNum; int32_t iFrameCmplxMean; - + } SRCTemporal; - + typedef struct TagWelsRc { int32_t iRcVaryPercentage; int32_t iRcVaryRatio; - + int32_t iInitialQp; //initial qp int32_t iBitRate; int32_t iPreviousBitrate; @@ -161,31 +161,33 @@ int32_t iPreviousGopSize; double fFrameRate; int32_t iBitsPerFrame; // *INT_MULTIPLY double dPreviousFps; - + // bits allocation and status int32_t iRemainingBits; int32_t iTargetBits; int32_t iCurrentBitsLevel;//0:normal; 1:limited; 2:exceeded. - + int32_t iIdrNum; int32_t iIntraComplexity; int32_t iIntraMbCount; - + int8_t iTlOfFrames[VGOP_SIZE]; int32_t iRemainingWeights; int32_t iFrameDqBits; - + double* pGomComplexity; int32_t* pGomForegroundBlockNum; int32_t* pCurrentFrameGomSad; int32_t* pGomCost; - + int32_t iAverageFrameQp; +int32_t iMinFrameQp; +int32_t iMaxFrameQp; int32_t iNumberMbFrame; int32_t iNumberMbGom; int32_t iSliceNum; int32_t iGomSize; - + int32_t iSkipFrameNum; int32_t iFrameCodedInVGop; int32_t iSkipFrameInVGop; @@ -238,9 +240,9 @@ PWelsRCMBInitFunc pfWelsRcMbInit; PWelsRCMBInfoUpdateFunc pfWelsRcMbInfoUpdate; } SWelsRcFunc; +void RcTraceFrameBits (void* pEncCtx, long long uiTimeStamp); void WelsRcInitModule (void* pCtx, RC_MODES iRcMode); void WelsRcFreeMemory (void* pCtx); } #endif //RC_H - \ No newline at end of file diff --git a/codec/encoder/core/src/encoder_ext.cpp b/codec/encoder/core/src/encoder_ext.cpp index 69148a25..d22ecd5b 100644 --- a/codec/encoder/core/src/encoder_ext.cpp +++ b/codec/encoder/core/src/encoder_ext.cpp @@ -167,6 +167,12 @@ int32_t ParamValidation (SLogContext* pLogCtx, SWelsSvcCodingParam* pCfg) { pSpatialLayer->iSpatialBitrate); return ENC_RETURN_INVALIDINPUT; } + if (pSpatialLayer->iMaxSpatialBitrate < pSpatialLayer->iSpatialBitrate * 1.1f) { + WelsLog (pLogCtx, WELS_LOG_WARNING, + "MaxSpatialBitrate (%d) should set be larger than 1.1 times of SpatialBitrate (%d)", + pSpatialLayer->iMaxSpatialBitrate, pSpatialLayer->iSpatialBitrate); + // pSpatialLayer->iSpatialBitrate = (int32_t) (pSpatialLayer->iMaxSpatialBitrate/1.1f); + } } if (iTotalBitrate > pCfg->iTargetBitrate) { WelsLog (pLogCtx, WELS_LOG_ERROR, @@ -3032,18 +3038,21 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour 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 = %8d, skip one frame",pSrcPic->uiTimeStamp); return ENC_RETURN_SUCCESS; } eFrameType = DecideFrameType (pCtx, iSpatialNum); if (eFrameType == videoFrameTypeSkip) { pFbi->eFrameType = eFrameType; + WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,"[Rc] Frame timestamp = %8d, skip one frame",pSrcPic->uiTimeStamp); return ENC_RETURN_SUCCESS; } //loop each layer to check if have skip frame when RC and frame skip enable if (CheckFrameSkipBasedMaxbr (pCtx, iSpatialNum, eFrameType, (uint32_t)pSrcPic->uiTimeStamp)) { pFbi->eFrameType = videoFrameTypeSkip; + WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,"[Rc] Frame timestamp = %8d, skip one frame",pSrcPic->uiTimeStamp); return ENC_RETURN_SUCCESS; } @@ -3427,6 +3436,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour } pCtx->pFuncList->pfRc.pfWelsRcPictureInfoUpdate (pCtx, iLayerSize); + RcTraceFrameBits (pCtx,pSrcPic->uiTimeStamp); pCtx->pDecPic->iFrameAverageQp = pCtx->pWelsSvcRc->iAverageFrameQp; //update scc related diff --git a/codec/encoder/core/src/ratectl.cpp b/codec/encoder/core/src/ratectl.cpp index bb1ab52a..6d8e7314 100644 --- a/codec/encoder/core/src/ratectl.cpp +++ b/codec/encoder/core/src/ratectl.cpp @@ -575,6 +575,8 @@ void RcInitGomParameters (sWelsEncCtx* pEncCtx) { 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; @@ -699,6 +701,7 @@ void RcVBufferCalculationSkip (sWelsEncCtx* pEncCtx) { const int32_t kiOutputBits = WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame, 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); //condition 2: VGOP bits constraint int32_t iVGopBitsPred = 0; for (int32_t i = pWelsSvcRc->iFrameCodedInVGop + 1; i < VGOP_SIZE; i++) @@ -712,14 +715,13 @@ void RcVBufferCalculationSkip (sWelsEncCtx* pEncCtx) { || (dIncPercent > pWelsSvcRc->iRcVaryPercentage)) { pEncCtx->iSkipFrameFlag = 1; pWelsSvcRc->iBufferFullnessSkip = pWelsSvcRc->iBufferFullnessSkip - kiOutputBits; - WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_INFO, "skip one frame"); + WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,"[Rc] bits in buffer = %3d",pWelsSvcRc->iBufferFullnessSkip); } - if (pWelsSvcRc->iBufferFullnessSkip < 0) - pWelsSvcRc->iBufferFullnessSkip = 0; + pWelsSvcRc->iBufferFullnessSkip = WELS_MAX (pWelsSvcRc->iBufferFullnessSkip, 0); if (pEncCtx->iSkipFrameFlag == 1) { - pWelsSvcRc->iRemainingBits += WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY); + pWelsSvcRc->iRemainingBits += kiOutputBits; pWelsSvcRc->iSkipFrameNum++; pWelsSvcRc->iSkipFrameInVGop++; } @@ -739,6 +741,7 @@ void WelsRcFrameDelayJudge (void* pCtx, EVideoFrameType eFrameType, long long ui pWelsSvcRc->iSkipFrameNum++; pWelsSvcRc->iSkipFrameInVGop++; pWelsSvcRc->iBufferFullnessSkip -= iSentBits; + WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,"[Rc] bits in buffer = %3d",pWelsSvcRc->iBufferFullnessSkip); pWelsSvcRc->iBufferFullnessSkip = WELS_MAX (pWelsSvcRc->iBufferFullnessSkip, 0); } } @@ -759,14 +762,17 @@ void RcVBufferCalculationPadding (sWelsEncCtx* pEncCtx) { } -void RcTraceFrameBits (sWelsEncCtx* pEncCtx) { +void RcTraceFrameBits (void* pCtx, long long uiTimeStamp) { + sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx; SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG, - "[Rc] encoding_qp%d, qp = %3d, index = %8d, iTid = %1d, used = %8d, target = %8d, remaingbits = %8d", - pEncCtx->uiDependencyId, pWelsSvcRc->iAverageFrameQp, pEncCtx->iFrameIndex, pEncCtx->uiTemporalId, - pWelsSvcRc->iFrameDqBits, - pWelsSvcRc->iTargetBits, pWelsSvcRc->iRemainingBits); + "[Rc] Frame timestamp = %8d, 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", + (uint32_t)uiTimeStamp,pEncCtx->eSliceType, pEncCtx->uiDependencyId, pWelsSvcRc->iAverageFrameQp,pWelsSvcRc->iMaxFrameQp,pWelsSvcRc->iMinFrameQp, + pEncCtx->iFrameIndex, pEncCtx->uiTemporalId, pWelsSvcRc->iFrameDqBits,WELS_DIV_ROUND (pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY), + pWelsSvcRc->iTargetBits, pWelsSvcRc->iRemainingBits, pWelsSvcRc->iBufferSizeSkip); + } void RcUpdatePictureQpBits (sWelsEncCtx* pEncCtx, int32_t iCodedBits) { @@ -891,8 +897,6 @@ void WelsRcPictureInfoUpdateGom (void* pCtx, int32_t iLayerSize) { } pWelsSvcRc->iRemainingBits -= pWelsSvcRc->iFrameDqBits; - RcTraceFrameBits (pEncCtx); - if (pEncCtx->pSvcParam->bEnableFrameSkip /*&& pEncCtx->uiDependencyId == pEncCtx->pSvcParam->iSpatialLayerNum - 1*/) { RcVBufferCalculationSkip (pEncCtx); @@ -945,13 +949,15 @@ void WelsRcMbInfoUpdateGom (void* pCtx, SMB* pCurMb, int32_t iCostLuma, SSlice* SRCSlicing* pSOverRc = &pWelsSvcRc->pSlicingOverRc[iSliceId]; const int32_t kiComplexityIndex = pSOverRc->iComplexityIndexSlice; - int32_t cur_mb_bits = BsGetBitsPos (bs) - pSOverRc->iBsPosSlice; - pSOverRc->iFrameBitsSlice += cur_mb_bits; - pSOverRc->iGomBitsSlice += cur_mb_bits; + int32_t iCurMbBits = BsGetBitsPos (bs) - pSOverRc->iBsPosSlice; + pSOverRc->iFrameBitsSlice += iCurMbBits; + pSOverRc->iGomBitsSlice += iCurMbBits; pWelsSvcRc->pGomCost[kiComplexityIndex] += iCostLuma; - if (cur_mb_bits > 0) { + pWelsSvcRc->iMinFrameQp = WELS_MIN(pWelsSvcRc->iMinFrameQp,pCurMb->uiLumaQp); + pWelsSvcRc->iMaxFrameQp = WELS_MAX(pWelsSvcRc->iMaxFrameQp,pCurMb->uiLumaQp); + if (iCurMbBits > 0) { pSOverRc->iTotalQpSlice += pCurMb->uiLumaQp; pSOverRc->iTotalMbSlice++; }