shithub: openh264

Download patch

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;
   }
 }