shithub: openh264

Download patch

ref: 7e14400b0be303d1ba7f450d9faee3e6c2c2d696
parent: c423a80ba4dbcb755e42c7e4b56624c302c33eca
author: Karina <[email protected]>
date: Thu Mar 31 12:58:20 EDT 2016

refine the workflow for encode one frame

--- a/codec/encoder/core/inc/rc.h
+++ b/codec/encoder/core/inc/rc.h
@@ -237,7 +237,7 @@
 } SWelsSvcRc;
 
 typedef  void (*PWelsRCPictureInitFunc) (sWelsEncCtx* pCtx,long long uiTimeStamp);
-typedef  void (*PWelsRCPictureDelayJudgeFunc) (sWelsEncCtx* pCtx, EVideoFrameType eFrameType, long long uiTimeStamp);
+typedef  void (*PWelsRCPictureDelayJudgeFunc) (sWelsEncCtx* pCtx, EVideoFrameType eFrameType, long long uiTimeStamp,int32_t iDidIdx);
 typedef  void (*PWelsRCPictureInfoUpdateFunc) (sWelsEncCtx* pCtx, int32_t iLayerSize);
 typedef  void (*PWelsRCMBInfoUpdateFunc) (sWelsEncCtx* pCtx, SMB* pCurMb, int32_t iCostLuma, SSlice* pSlice);
 typedef  void (*PWelsRCMBInitFunc) (sWelsEncCtx* pCtx, SMB* pCurMb, SSlice* pSlice);
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -3750,7 +3750,84 @@
   pFbi->iLayerNum = 0;
   pFbi->iFrameSizeInBytes = 0;
 }
+EVideoFrameType PrepareEncodeFrame (sWelsEncCtx* pCtx, SLayerBSInfo*& pLayerBsInfo, int32_t iSpatialNum ,
+                                    int8_t& iCurDid, int32_t& iCurTid,
+                                    int32_t& iLayerNum, int32_t& iFrameSize, long long uiTimeStamp) {
+  SWelsSvcCodingParam* pSvcParam        = pCtx->pSvcParam;
+  SSpatialPicIndex* pSpatialIndexMap = &pCtx->sSpatialIndexMap[0];
 
+  if (!pSvcParam->bSimulcastAVC) {
+    pCtx->iSkipFrameFlag = false;
+    for (int32_t iDid = 0; iDid < iSpatialNum; iDid++) {
+      if (pCtx->pSvcParam->sDependencyLayers[ (pSpatialIndexMap + iDid)->iDid].iSkipFrameFlag)
+        pCtx->iSkipFrameFlag = 1;
+    }
+  }
+
+
+  EVideoFrameType eFrameType = DecideFrameType (pCtx, iSpatialNum, iCurDid);
+
+  if (eFrameType == videoFrameTypeSkip) {
+    WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
+             "[Rc] Frame timestamp = %lld, skip one frame due to target_br, continual skipped %d frames",
+             uiTimeStamp, pCtx->iContinualSkipFrames);
+    if (pSvcParam->bSimulcastAVC) {
+      if (pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip)
+        pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip (pCtx, iCurDid);
+    }
+
+    else {
+      if (pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip) {
+        for (int32_t i = 0; i < iSpatialNum; i++) {
+          pCtx->pSvcParam->sDependencyLayers[i].iSkipFrameFlag = false;
+          pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip (pCtx, (pSpatialIndexMap + i)->iDid);
+        }
+      }
+    }
+
+  } else {
+    if (pCtx->pFuncList->pfRc.pfWelsCheckSkipBasedMaxbr) {
+      bool bSkip = pCtx->pFuncList->pfRc.pfWelsCheckSkipBasedMaxbr (pCtx, iSpatialNum, eFrameType,
+                   (uint32_t)uiTimeStamp);
+      if (bSkip) {
+        eFrameType = videoFrameTypeSkip;
+        pLayerBsInfo->eFrameType = videoFrameTypeSkip;
+        WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
+                 "[Rc] Frame timestamp = %lld, skip one frame due to max_br, continual skipped %d frames",
+                 uiTimeStamp, pCtx->iContinualSkipFrames);
+      }
+    }
+  }
+
+  if (eFrameType != videoFrameTypeSkip) {
+    SSpatialLayerInternal* pParamInternal = &pSvcParam->sDependencyLayers[iCurDid];
+    pCtx->iContinualSkipFrames = 0;
+    iCurTid = GetTemporalLevel (&pSvcParam->sDependencyLayers[iCurDid], pParamInternal->iCodingIndex,
+                                pSvcParam->uiGopSize);
+    pCtx->uiTemporalId = iCurTid;
+    if (eFrameType == videoFrameTypeIDR) {
+      // write parameter sets bitstream or SEI/SSEI (if any) here
+      // TODO: use function pointer instead
+      if (! (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
+        if (pSvcParam->bSimulcastAVC) {
+          pCtx->iEncoderError = WriteSavcParaset (pCtx, iCurDid, pLayerBsInfo, iLayerNum, iFrameSize);
+          ++ pCtx->uiIdrPicId;
+        } else {
+          pCtx->iEncoderError = WriteSsvcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
+          ++ pCtx->uiIdrPicId;
+        }
+      } else {
+        pCtx->iEncoderError = WriteSavcParaset_Listing (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
+
+        ++ pCtx->uiIdrPicId;
+      }
+    }
+
+  }
+
+
+  return eFrameType;
+}
 /*!
  * \brief   core svc encoding process
  *
@@ -3788,7 +3865,6 @@
   int32_t iCurTid                = 0;
   bool bAvcBased                = false;
   SLogContext* pLogCtx = & (pCtx->sLogCtx);
-  bool bFinishedWriteHeader = false;
 #if defined(ENABLE_PSNR_CALC)
   float fSnrY = .0f, fSnrU = .0f, fSnrV = .0f;
 #endif//ENABLE_PSNR_CALC
@@ -3816,6 +3892,7 @@
       SSpatialLayerInternal* pParamInternal = &pSvcParam->sDependencyLayers[iDidIdx];
       pParamInternal->iCodingIndex ++;
     }
+    pFbi->eFrameType = videoFrameTypeSkip;
     pLayerBsInfo->eFrameType = videoFrameTypeSkip;
     WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
              "[Rc] Frame timestamp = %lld, skip one frame due to preprocessing return (temporal layer settings or else), continual skipped %d frames",
@@ -3822,13 +3899,6 @@
              pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames);
     return ENC_RETURN_SUCCESS;
   }
-  if (!pSvcParam->bSimulcastAVC) {
-    pCtx->iSkipFrameFlag = false;
-    for (int32_t iDid = 0; iDid < iSpatialNum; iDid++) {
-      if (pCtx->pSvcParam->sDependencyLayers[iDid].iSkipFrameFlag)
-        pCtx->iSkipFrameFlag = 1;
-    }
-  }
 
   InitBitStream (pCtx);
   pLayerBsInfo->pBsBuf = pCtx->pFrameBs ;
@@ -3836,14 +3906,24 @@
 
   pCtx->pCurDqLayer             = pCtx->ppDqLayerList[pSpatialIndexMap->iDid];
   pCtx->pCurDqLayer->pRefLayer  = NULL;
+  if (!pSvcParam->bSimulcastAVC) {
+    eFrameType = PrepareEncodeFrame (pCtx, pLayerBsInfo, iSpatialNum , iCurDid, iCurTid, iLayerNum, iFrameSize,
+                                     pFbi->uiTimeStamp);
+    if (eFrameType == videoFrameTypeSkip) {
+      pFbi->eFrameType = videoFrameTypeSkip;
+      pLayerBsInfo->eFrameType = videoFrameTypeSkip;
 
+      return ENC_RETURN_SUCCESS;
+    }
+  }
+
   while (iSpatialIdx < pSvcParam->iSpatialLayerNum) {
-    const int32_t iDidIdx  = (pSpatialIndexMap + iSpatialIdx)->iDid;
-    SSpatialLayerConfig* pParam = &pSvcParam->sSpatialLayers[iDidIdx];
-    SSpatialLayerInternal* pParamInternal = &pSvcParam->sDependencyLayers[iDidIdx];
-    int32_t  iDecompositionStages = pSvcParam->sDependencyLayers[iDidIdx].iDecompositionStages;
-    pCtx->pCurDqLayer           = pCtx->ppDqLayerList[iDidIdx];
-    pCtx->uiDependencyId        = iCurDid = (int8_t)iDidIdx;
+    iCurDid  = (pSpatialIndexMap + iSpatialIdx)->iDid;
+    SSpatialLayerConfig* pParam = &pSvcParam->sSpatialLayers[iCurDid];
+    SSpatialLayerInternal* pParamInternal = &pSvcParam->sDependencyLayers[iCurDid];
+    int32_t  iDecompositionStages = pSvcParam->sDependencyLayers[iCurDid].iDecompositionStages;
+    pCtx->pCurDqLayer           = pCtx->ppDqLayerList[iCurDid];
+    pCtx->uiDependencyId        =  iCurDid;
     //skip this spatial layer
     if (GetTemporalLevel (pParamInternal, pParamInternal->iCodingIndex, pSvcParam->uiGopSize) == INVALID_TEMPORAL_ID) {
       ++iSpatialIdx;
@@ -3850,75 +3930,18 @@
       pParamInternal->iCodingIndex ++;
       continue;
     }
-    eFrameType = DecideFrameType (pCtx, iSpatialNum, iDidIdx);
-    if (eFrameType == videoFrameTypeSkip) {
-      eFrameType = videoFrameTypeSkip;
-      pLayerBsInfo->eFrameType = eFrameType;
-      WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
-               "[Rc] Frame timestamp = %lld, skip one frame due to target_br, continual skipped %d frames",
-               pFbi->uiTimeStamp, pCtx->iContinualSkipFrames);
-      ++ iSpatialIdx;
-      if (pSvcParam->bSimulcastAVC) {
-        if (pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip)
-          pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip (pCtx, iDidIdx);
+    if (pSvcParam->bSimulcastAVC) {
+      eFrameType = PrepareEncodeFrame (pCtx, pLayerBsInfo, iSpatialNum , iCurDid, iCurTid, iLayerNum, iFrameSize,
+                                       pFbi->uiTimeStamp);
+      if (eFrameType == videoFrameTypeSkip) {
+        pLayerBsInfo->eFrameType = videoFrameTypeSkip;
+        ++iSpatialIdx;
         continue;
       }
-
-      else {
-        if (pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip) {
-          for (int32_t i = 0; i < iSpatialNum; i++) {
-            pCtx->pSvcParam->sDependencyLayers[i].iSkipFrameFlag = false;
-            pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip (pCtx, (pSpatialIndexMap + i)->iDid);
-          }
-        }
-        return ENC_RETURN_SUCCESS;
-      }
     }
-    //loop each layer to check if have skip frame when RC and frame skip enable
-    if (pCtx->pFuncList->pfRc.pfWelsCheckSkipBasedMaxbr) {
-      bool bSkip = pCtx->pFuncList->pfRc.pfWelsCheckSkipBasedMaxbr (pCtx, iSpatialNum, eFrameType,
-                   (uint32_t)pFbi->uiTimeStamp);
-      if (bSkip) {
-        eFrameType = videoFrameTypeSkip;
-        pLayerBsInfo->eFrameType = videoFrameTypeSkip;
-        WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
-                 "[Rc] Frame timestamp = %lld, skip one frame due to max_br, continual skipped %d frames",
-                 pFbi->uiTimeStamp, pCtx->iContinualSkipFrames);
-        ++ iSpatialIdx;
-        if (pSvcParam->bSimulcastAVC)
-          continue;
-        else
-          return ENC_RETURN_SUCCESS;
-      }
-    }
-    pCtx->iContinualSkipFrames = 0;
-    iCurTid = GetTemporalLevel (&pSvcParam->sDependencyLayers[iDidIdx], pParamInternal->iCodingIndex,
-                                pSvcParam->uiGopSize);
-    pCtx->uiTemporalId = iCurTid;
-    InitFrameCoding (pCtx, eFrameType, iDidIdx);
+    InitFrameCoding (pCtx, eFrameType, iCurDid);
+    pCtx->pVpp->AnalyzeSpatialPic (pCtx, iCurDid);
 
-    if (eFrameType == videoFrameTypeIDR) {
-      // write parameter sets bitstream or SEI/SSEI (if any) here
-      // TODO: use function pointer instead
-      if (! (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
-        if (pSvcParam->bSimulcastAVC) {
-          pCtx->iEncoderError = WriteSavcParaset (pCtx, iCurDid, pLayerBsInfo, iLayerNum, iFrameSize);
-          ++ pCtx->uiIdrPicId;
-        } else if (!bFinishedWriteHeader) {
-          pCtx->iEncoderError = WriteSsvcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
-          ++ pCtx->uiIdrPicId;
-          bFinishedWriteHeader = true;
-        }
-      } else if (!bFinishedWriteHeader) {
-        pCtx->iEncoderError = WriteSavcParaset_Listing (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
-        bFinishedWriteHeader = true;
-        ++ pCtx->uiIdrPicId;
-      }
-      WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
-    }
-
-    pCtx->pVpp->AnalyzeSpatialPic (pCtx, iDidIdx);
-
     pCtx->pEncPic               = pEncPic = (pSpatialIndexMap + iSpatialIdx)->pSrc;
     pCtx->pEncPic->iPictureType = pCtx->eSliceType;
     pCtx->pEncPic->iFramePoc    = pParamInternal->iPOC;
@@ -4237,8 +4260,8 @@
     if (
       (!pCtx->pCurDqLayer->bDeblockingParallelFlag) &&
 #if !defined(ENABLE_FRAME_DUMP)
-      ((eNalRefIdc != NRI_PRI_LOWEST) && (pSvcParam->sDependencyLayers[iDidIdx].iHighestTemporalId == 0
-                                          || iCurTid < pSvcParam->sDependencyLayers[iDidIdx].iHighestTemporalId)) &&
+      ((eNalRefIdc != NRI_PRI_LOWEST) && (pSvcParam->sDependencyLayers[iCurDid].iHighestTemporalId == 0
+                                          || iCurTid < pSvcParam->sDependencyLayers[iCurDid].iHighestTemporalId)) &&
 #endif//!ENABLE_FRAME_DUMP
       true
     ) {
@@ -4247,7 +4270,7 @@
 
     pCtx->pFuncList->pfRc.pfWelsRcPictureInfoUpdate (pCtx, iLayerSize);
     RcTraceFrameBits (pCtx, pFbi->uiTimeStamp);
-    pCtx->pDecPic->iFrameAverageQp = pCtx->pWelsSvcRc[iDidIdx].iAverageFrameQp;
+    pCtx->pDecPic->iFrameAverageQp = pCtx->pWelsSvcRc[iCurDid].iAverageFrameQp;
 
     //update scc related
     pCtx->pFuncList->pfUpdateFMESwitch (pCtx->pCurDqLayer);
@@ -4405,7 +4428,7 @@
 #endif//#if defined(MT_DEBUG)
     }
 
-    pCtx->eLastNalPriority[iDidIdx] = eNalRefIdc;
+    pCtx->eLastNalPriority[iCurDid] = eNalRefIdc;
     ++ iSpatialIdx;
 
     if (iCurDid + 1 < pSvcParam->iSpatialLayerNum) {
@@ -4413,7 +4436,7 @@
       WelsSwapDqLayers (pCtx, (pSpatialIndexMap + iSpatialIdx)->iDid);
     }
 
-    if (pCtx->pVpp->UpdateSpatialPictures (pCtx, pSvcParam, iCurTid, iDidIdx) != 0) {
+    if (pCtx->pVpp->UpdateSpatialPictures (pCtx, pSvcParam, iCurTid, iCurDid) != 0) {
       ForceCodingIDR (pCtx);
       WelsLog (pLogCtx, WELS_LOG_WARNING,
                "WelsEncoderEncodeExt(), Logic Error Found in Preprocess updating. ForceCodingIDR!");
@@ -4425,7 +4448,7 @@
 
     if (pSvcParam->bEnableLongTermReference && ((pCtx->pLtr[pCtx->uiDependencyId].bLTRMarkingFlag
         && (pCtx->pLtr[pCtx->uiDependencyId].iLTRMarkMode == LTR_DIRECT_MARK)) || eFrameType == videoFrameTypeIDR)) {
-      pCtx->bRefOfCurTidIsLtr[iDidIdx][iCurTid] = true;
+      pCtx->bRefOfCurTidIsLtr[iCurDid][iCurTid] = true;
     }
     ++ pParamInternal->iCodingIndex;
   }//end of (iSpatialIdx/iSpatialNum)
--- a/codec/encoder/core/src/ratectl.cpp
+++ b/codec/encoder/core/src/ratectl.cpp
@@ -707,9 +707,9 @@
     pDLayerParamInternal->iSkipFrameFlag = 1;
   }
 }
-void WelsRcFrameDelayJudge (sWelsEncCtx* pEncCtx, EVideoFrameType eFrameType, long long uiTimeStamp) {
-  SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
-  SSpatialLayerConfig* pDLayerParam     = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId];
+void WelsRcFrameDelayJudge (sWelsEncCtx* pEncCtx, EVideoFrameType eFrameType, long long uiTimeStamp,int32_t iDidIdx) {
+  SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[iDidIdx];
+  SSpatialLayerConfig* pDLayerParam     = &pEncCtx->pSvcParam->sSpatialLayers[iDidIdx];
   //SSpatialLayerInternal* pDLayerParamInternal     = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];
   if (!pEncCtx->pSvcParam->bEnableFrameSkip)
     return;
@@ -773,14 +773,15 @@
 bool CheckFrameSkipBasedMaxbr (sWelsEncCtx* pEncCtx, int32_t iSpatialNum, EVideoFrameType eFrameType,
                                const uint32_t uiTimeStamp) {
   bool bSkipMustFlag = false;
+  int32_t iDidIdx = pEncCtx->uiDependencyId;
+  SSpatialPicIndex* pSpatialIndexMap = &pEncCtx->sSpatialIndexMap[0];
   if (!pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge)
     return false;
   if( pEncCtx->pSvcParam->bSimulcastAVC){
-      int32_t iDidIdx = pEncCtx->uiDependencyId;
     if (UNSPECIFIED_BIT_RATE == pEncCtx->pSvcParam->sSpatialLayers[iDidIdx].iMaxSpatialBitrate)
       return false;
 
-    pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge (pEncCtx, eFrameType, uiTimeStamp);
+    pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge (pEncCtx, eFrameType, uiTimeStamp,iDidIdx);
     if (true == pEncCtx->pWelsSvcRc[iDidIdx].bSkipFlag) {
        bSkipMustFlag = true;
        pEncCtx->pWelsSvcRc[iDidIdx].uiLastTimeStamp = uiTimeStamp;
@@ -790,8 +791,8 @@
     for(int32_t i = 0;i<iSpatialNum;i++){
       if (UNSPECIFIED_BIT_RATE == pEncCtx->pSvcParam->sSpatialLayers[i].iMaxSpatialBitrate)
         break;
-
-       pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge (pEncCtx, eFrameType, uiTimeStamp);
+       iDidIdx = (pSpatialIndexMap + i)->iDid;
+       pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge (pEncCtx, eFrameType, uiTimeStamp,iDidIdx);
        if (true == pEncCtx->pWelsSvcRc[i].bSkipFlag) {
          bSkipMustFlag = true;
          pEncCtx->pWelsSvcRc[i].uiLastTimeStamp = uiTimeStamp;
@@ -1285,9 +1286,9 @@
   pWelsSvcRc->iAvgCost2Bits = 1;
   pWelsSvcRc->iSkipBufferRatio  = SKIP_RATIO;
 }
-void WelsRcFrameDelayJudgeTimeStamp (sWelsEncCtx* pEncCtx, EVideoFrameType eFrameType, long long uiTimeStamp) {
+void WelsRcFrameDelayJudgeTimeStamp (sWelsEncCtx* pEncCtx, EVideoFrameType eFrameType, long long uiTimeStamp,int32_t iDidIdx) {
   SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
-  SSpatialLayerConfig* pDLayerConfig   = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId];
+  SSpatialLayerConfig* pDLayerConfig   = &pEncCtx->pSvcParam->sSpatialLayers[iDidIdx];
 
   if (pDLayerConfig->iSpatialBitrate > pDLayerConfig->iMaxSpatialBitrate)
     pDLayerConfig->iSpatialBitrate = pDLayerConfig->iMaxSpatialBitrate;