ref: 99aaf3198cdb03bd4d3ff2ac7c74e52772f4a7cc
parent: 9be80c088dec4d068e671b58e8b0da232f75d60e
author: Sijia Chen <sijchen@cisco.com>
date: Tue Jun 23 13:04:02 EDT 2015
first version of post-frame skipping for rate control (not enabled)
--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -285,7 +285,8 @@
RC_BITRATE_MODE = 1, ///< bitrate mode
RC_BUFFERBASED_MODE = 2, ///< no bitrate control,only using buffer status,adjust the video quality
RC_TIMESTAMP_MODE = 3, //rate control based timestamp
- RC_OFF_MODE = -1 ///< rate control off mode
+ RC_BITRATE_MODE_POST_SKIP = 4, ///< this is in-building RC MODE, WILL BE DELETED after algorithm tuning!
+ RC_OFF_MODE = -1, ///< rate control off mode
} RC_MODES;
/**
--- a/codec/encoder/core/inc/rc.h
+++ b/codec/encoder/core/inc/rc.h
@@ -260,6 +260,7 @@
const uint32_t uiTimeStamp);
typedef void (*PWelsUpdateBufferWhenFrameSkippedFunc)(sWelsEncCtx* pCtx, int32_t iSpatialNum);
typedef void (*PWelsUpdateMaxBrCheckWindowStatusFunc)(sWelsEncCtx* pCtx, int32_t iSpatialNum, const long long uiTimeStamp);
+typedef bool (*PWelsRCPostFrameSkippingFunc)(sWelsEncCtx* pCtx, const int32_t iDid, const long long uiTimeStamp);
typedef struct WelsRcFunc_s {
PWelsRCPictureInitFunc pfWelsRcPictureInit;
@@ -270,6 +271,8 @@
PWelsCheckFrameSkipBasedMaxbrFunc pfWelsCheckSkipBasedMaxbr;
PWelsUpdateBufferWhenFrameSkippedFunc pfWelsUpdateBufferWhenSkip;
PWelsUpdateMaxBrCheckWindowStatusFunc pfWelsUpdateMaxBrWindowStatus;
+
+PWelsRCPostFrameSkippingFunc pfWelsRcPostFrameSkipping;
} SWelsRcFunc;
bool CheckFrameSkipBasedMaxbr (sWelsEncCtx* pCtx, int32_t iSpatialNum, EVideoFrameType eFrameType,
@@ -276,6 +279,9 @@
const uint32_t uiTimeStamp);
void UpdateBufferWhenFrameSkipped(sWelsEncCtx* pCtx, int32_t iSpatialNum);
void UpdateMaxBrCheckWindowStatus(sWelsEncCtx* pCtx, int32_t iSpatialNum, const long long uiTimeStamp);
+bool WelsRcPostFrameSkipping(sWelsEncCtx* pCtx, const int32_t iDid, const long long uiTimeStamp);
+void WelsRcPostFrameSkippedUpdate (sWelsEncCtx* pCtx, const int32_t iDid);
+
void RcTraceFrameBits (sWelsEncCtx* pEncCtx, long long uiTimeStamp);
void WelsRcInitModule (sWelsEncCtx* pCtx, RC_MODES iRcMode);
void WelsRcInitFuncPointers (sWelsEncCtx* pEncCtx, RC_MODES iRcMode);
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -3655,6 +3655,57 @@
return iReturn;
}
+void StackBackEncoderStatus (sWelsEncCtx* pEncCtx,
+ EVideoFrameType keFrameType) {
+ // for bitstream writing
+ pEncCtx->iPosBsBuffer = 0; // reset bs pBuffer position
+ pEncCtx->pOut->iNalIndex = 0; // reset NAL index
+
+ InitBits (&pEncCtx->pOut->sBsWrite, pEncCtx->pOut->pBsBuffer, pEncCtx->pOut->uiSize);
+ if ((keFrameType == videoFrameTypeP) || (keFrameType == videoFrameTypeI)) {
+ pEncCtx->iFrameIndex --;
+ if (pEncCtx->iPOC != 0) {
+ pEncCtx->iPOC -= 2;
+ } else {
+ pEncCtx->iPOC = (1 << pEncCtx->pSps->iLog2MaxPocLsb) - 2;
+ }
+
+ if (pEncCtx->eLastNalPriority != 0) {
+ if (pEncCtx->iFrameNum != 0) {
+ pEncCtx->iFrameNum --;
+ } else {
+ pEncCtx->iFrameNum = (1 << pEncCtx->pSps->uiLog2MaxFrameNum) - 1;
+ }
+ }
+
+ pEncCtx->eNalType = NAL_UNIT_CODED_SLICE;
+ pEncCtx->eSliceType = P_SLICE;
+ pEncCtx->eNalPriority = pEncCtx->eLastNalPriority;
+ } else if (keFrameType == videoFrameTypeIDR) {
+ pEncCtx->uiIdrPicId --;
+
+ //set the next frame to be IDR
+ ForceCodingIDR (pEncCtx);
+ } else { // B pictures are not supported now, any else?
+ assert (0);
+ }
+
+ // no need to stack back RC info since the info is still useful for later RQ model calculation
+ // no need to stack back MB slicing info for dynamic balancing, since the info is still refer-able
+}
+
+void ClearFrameBsInfo (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi) {
+ pFbi->sLayerInfo[0].pBsBuf = pCtx->pFrameBs;
+ pFbi->sLayerInfo[0].pNalLengthInByte = pCtx->pOut->pNalLen;
+
+ for (int i = 0; i < pFbi->iLayerNum; i++) {
+ pFbi->sLayerInfo[i].iNalCount = 0;
+ }
+ pFbi->iLayerNum = 0;
+ pFbi->iFrameSizeInBytes = 0;
+ pFbi->eFrameType = videoFrameTypeSkip;
+}
+
/*!
* \brief core svc encoding process
*
@@ -4098,6 +4149,28 @@
pLayerBsInfo->uiQualityId = 0;
pLayerBsInfo->iNalCount = iNalIdxInLayer;
}
+ }
+
+ if (NULL != pCtx->pFuncList->pfRc.pfWelsRcPostFrameSkipping
+ && pCtx->pFuncList->pfRc.pfWelsRcPostFrameSkipping (pCtx, iCurDid, pSrcPic->uiTimeStamp)) {
+
+ StackBackEncoderStatus (pCtx, eFrameType);
+ ClearFrameBsInfo (pCtx, pFbi);
+
+ iFrameSize = 0;
+ iLayerSize = 0;
+ iLayerNum = 0;
+
+ if (pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip) {
+ pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip (pCtx, iSpatialNum);
+ }
+
+ WelsRcPostFrameSkippedUpdate(pCtx, iCurDid);
+ WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
+ "[Rc] Frame timestamp = %lld, skip one frame due to post skip, continual skipped %d frames",
+ pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames);
+ pCtx->iEncoderError = ENC_RETURN_SUCCESS;
+ return ENC_RETURN_SUCCESS;
}
// deblocking filter
--- a/codec/encoder/core/src/ratectl.cpp
+++ b/codec/encoder/core/src/ratectl.cpp
@@ -822,6 +822,12 @@
}
pEncCtx->iContinualSkipFrames++;
+ if ( ( pEncCtx->iContinualSkipFrames % 3 ) == 0 ) {
+ //output a warning when iContinualSkipFrames is large enough, which may indicate subjective quality problem
+ //note that here iContinualSkipFrames must be >0, so the log output will be 3/6/....
+ WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_WARNING, "[Rc] iContinualSkipFrames(%d) is large",
+ pEncCtx->iContinualSkipFrames);
+ }
}
void UpdateMaxBrCheckWindowStatus (sWelsEncCtx* pEncCtx, int32_t iSpatialNum, const long long uiTimeStamp) {
SSpatialPicIndex* pSpatialIndexMap = &pEncCtx->sSpatialIndexMap[0];
@@ -875,6 +881,16 @@
return;
}
+bool WelsRcPostFrameSkipping (sWelsEncCtx* pCtx, const int32_t iDid, const long long uiTimeStamp) {
+ //TODO: put in the decision of rate-control
+ return false;
+}
+
+void WelsRcPostFrameSkippedUpdate (sWelsEncCtx* pCtx, const int32_t iDid) {
+ //TODO: do something to update buffers after post-skipping is done
+ //let RC know post-skipping happened and adjust strategy accordingly
+}
+
void RcVBufferCalculationPadding (sWelsEncCtx* pEncCtx) {
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
const int32_t kiOutputBits = pWelsSvcRc->iBitsPerFrame;
@@ -1433,6 +1449,7 @@
pRcf->pfWelsCheckSkipBasedMaxbr = NULL;
pRcf->pfWelsUpdateBufferWhenSkip = NULL;
pRcf->pfWelsUpdateMaxBrWindowStatus = NULL;
+ pRcf->pfWelsRcPostFrameSkipping = NULL;
break;
case RC_BUFFERBASED_MODE:
pRcf->pfWelsRcPictureInit = WelRcPictureInitBufferBasedQp;
@@ -1443,6 +1460,7 @@
pRcf->pfWelsCheckSkipBasedMaxbr = NULL;
pRcf->pfWelsUpdateBufferWhenSkip = NULL;
pRcf->pfWelsUpdateMaxBrWindowStatus = NULL;
+ pRcf->pfWelsRcPostFrameSkipping = NULL;
break;
case RC_BITRATE_MODE:
pRcf->pfWelsRcPictureInit = WelsRcPictureInitGom;
@@ -1453,7 +1471,19 @@
pRcf->pfWelsCheckSkipBasedMaxbr = CheckFrameSkipBasedMaxbr;
pRcf->pfWelsUpdateBufferWhenSkip = UpdateBufferWhenFrameSkipped;
pRcf->pfWelsUpdateMaxBrWindowStatus = UpdateMaxBrCheckWindowStatus;
+ pRcf->pfWelsRcPostFrameSkipping = WelsRcPostFrameSkipping;
break;
+ case RC_BITRATE_MODE_POST_SKIP:
+ pRcf->pfWelsRcPictureInit = WelsRcPictureInitGom;
+ pRcf->pfWelsRcPicDelayJudge = WelsRcFrameDelayJudge;
+ pRcf->pfWelsRcPictureInfoUpdate = WelsRcPictureInfoUpdateGom;
+ pRcf->pfWelsRcMbInit = WelsRcMbInitGom;
+ pRcf->pfWelsRcMbInfoUpdate = WelsRcMbInfoUpdateGom;
+ pRcf->pfWelsCheckSkipBasedMaxbr = CheckFrameSkipBasedMaxbr;
+ pRcf->pfWelsUpdateBufferWhenSkip = UpdateBufferWhenFrameSkipped;
+ pRcf->pfWelsUpdateMaxBrWindowStatus = UpdateMaxBrCheckWindowStatus;
+ pRcf->pfWelsRcPostFrameSkipping = WelsRcPostFrameSkipping;
+ break;
case RC_TIMESTAMP_MODE:
if (pEncCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {
pRcf->pfWelsRcPictureInit = WelRcPictureInitScc;
@@ -1471,6 +1501,7 @@
pRcf->pfWelsCheckSkipBasedMaxbr = CheckFrameSkipBasedMaxbr;
pRcf->pfWelsUpdateBufferWhenSkip = NULL;
pRcf->pfWelsUpdateMaxBrWindowStatus = NULL;
+ pRcf->pfWelsRcPostFrameSkipping = NULL;
InitRcModuleTimeStamp (pEncCtx);
break;
case RC_QUALITY_MODE:
@@ -1483,7 +1514,7 @@
pRcf->pfWelsCheckSkipBasedMaxbr = CheckFrameSkipBasedMaxbr;
pRcf->pfWelsUpdateBufferWhenSkip = UpdateBufferWhenFrameSkipped;
pRcf->pfWelsUpdateMaxBrWindowStatus = UpdateMaxBrCheckWindowStatus;
-
+ pRcf->pfWelsRcPostFrameSkipping = NULL;
break;
}
}