shithub: openh264

Download patch

ref: be94bf9ffa58103ce0d87c6b1d4e9cfa2461a125
parent: 7b461e109eea843e0b8795fbdbc64e19cd8f6727
parent: de3990479ea944f98a15d692002fe01184f15eda
author: huili2 <[email protected]>
date: Wed Jun 25 13:29:29 EDT 2014

Merge pull request #1006 from ruil2/bug_fix

    fix defect7654 that  the encoder won't generate IDR when temporal layer setting changes

--- a/codec/encoder/core/inc/au_set.h
+++ b/codec/encoder/core/inc/au_set.h
@@ -45,7 +45,7 @@
 #include "bit_stream.h"
 #include "parameter_sets.h"
 #include "param_svc.h"
-
+#include "utils.h"
 namespace WelsSVCEnc {
 /*!
  *************************************************************************************
@@ -139,6 +139,6 @@
                      const uint32_t kuiPpsId,
                      const bool kbDeblockingFilterPresentFlag,
                      const bool kbUsingSubsetSps);
-
+int32_t WelsCheckRefFrameLimitation(SLogContext* pLogCtx,SWelsSvcCodingParam* pParam);
 }
 #endif//WELS_ACCESS_UNIT_PARSER_H__
--- a/codec/encoder/core/inc/param_svc.h
+++ b/codec/encoder/core/inc/param_svc.h
@@ -116,8 +116,8 @@
   iCountThreadsNum;                       //              # derived from disable_multiple_slice_idc (=0 or >1) means;
 
   int8_t		iDecompStages;		// GOP size dependency
+  int32_t  iMaxNumRefFrame;
 
-
  public:
   TagWelsSvcCodingParam() {
     FillDefault();
@@ -190,7 +190,7 @@
   void FillDefault() {
     FillDefault (*this);
     uiGopSize			= 1;			// GOP size (at maximal frame rate: 16)
-
+    iMaxNumRefFrame = 1;
     SUsedPicRect.iLeft	=
       SUsedPicRect.iTop	=
         SUsedPicRect.iWidth	=
@@ -369,6 +369,8 @@
         iNumRefFrame		= WELS_CLIP3 (iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM);
       }
     }
+    if (iNumRefFrame > iMaxNumRefFrame)
+      iMaxNumRefFrame = iNumRefFrame;
     iLtrMarkPeriod  = pCodingParam.iLtrMarkPeriod;
 
     bPrefixNalAddingCtrl	= pCodingParam.bPrefixNalAddingCtrl;
@@ -391,8 +393,8 @@
       float fLayerFrameRate	= WELS_CLIP3 (pCodingParam.sSpatialLayers[iIdxSpatial].fFrameRate,
                                           MIN_FRAME_RATE, fParamMaxFrameRate);
       pSpatialLayer->fFrameRate =
-      pDlp->fInputFrameRate	=
-        pDlp->fOutputFrameRate	= WELS_CLIP3 (fLayerFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);
+        pDlp->fInputFrameRate	=
+          pDlp->fOutputFrameRate	= WELS_CLIP3 (fLayerFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);
       if (pDlp->fInputFrameRate > fMaxFr + EPSN)
         fMaxFr = pDlp->fInputFrameRate;
 
--- a/codec/encoder/core/src/au_set.cpp
+++ b/codec/encoder/core/src/au_set.cpp
@@ -40,6 +40,7 @@
 
 #include "au_set.h"
 #include "svc_enc_golomb.h"
+#include "macros.h"
 namespace WelsSVCEnc {
 
 
@@ -102,6 +103,44 @@
 
 }
 
+int32_t WelsCheckRefFrameLimitation (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam) {
+  int32_t i = 0;
+  int32_t iRefFrame = 1;
+  //get the number of reference frame according to level limitation.
+  for (i = 0; i < pParam->iSpatialLayerNum; ++ i) {
+    SSpatialLayerConfig* pSpatialLayer = &pParam->sSpatialLayers[i];
+    uint32_t uiPicInMBs = ((pSpatialLayer->iVideoHeight + 15) >> 4) * ((pSpatialLayer->iVideoWidth + 15) >> 4);
+    if (pSpatialLayer->uiLevelIdc == LEVEL_UNKNOWN) {
+      pSpatialLayer->uiLevelIdc = LEVEL_5_0;
+      WelsLog (pLogCtx, WELS_LOG_WARNING, "change level to level5.0\n");
+    }
+    iRefFrame = g_ksLevelLimit[pSpatialLayer->uiLevelIdc - 1].uiMaxDPBMB / uiPicInMBs;
+    if (iRefFrame < pParam->iMaxNumRefFrame)
+      pParam->iMaxNumRefFrame = iRefFrame;
+    if (pParam->iMaxNumRefFrame < 1) {
+      pParam->iMaxNumRefFrame = 1;
+      WelsLog (pLogCtx, WELS_LOG_ERROR, "error Level setting (%d)\n", pSpatialLayer->uiLevelIdc);
+      return ENC_RETURN_UNSUPPORTED_PARA;
+    }
+  }
+  //check temporal layer number according to the number of reference frame
+  int32_t iMaxTemporalLayer = pParam->iNumRefFrame - pParam->iLTRRefNum;
+  if (iMaxTemporalLayer < 1) {
+    iMaxTemporalLayer = 1;
+    WelsLog (pLogCtx, WELS_LOG_ERROR, "Invalid the number of reference frame ltr num(%d)\n", pParam->iLTRRefNum);
+    return ENC_RETURN_UNSUPPORTED_PARA;
+  }
+  if (pParam->iTemporalLayerNum > iMaxTemporalLayer)
+    pParam->iTemporalLayerNum = iMaxTemporalLayer;
+
+  //get the maximum num of reference frame according to temporal Layer
+  iRefFrame = WELS_CLIP3 ((pParam->iTemporalLayerNum + pParam->iLTRRefNum), MIN_REF_PIC_COUNT,
+                          MAX_REFERENCE_REORDER_COUNT_NUM);
+  if (pParam->iMaxNumRefFrame < iRefFrame)
+    pParam->iMaxNumRefFrame = iRefFrame;
+
+  return ENC_RETURN_SUCCESS;
+}
 static inline int32_t WelsGetLevelIdc (const SWelsSPS* kpSps, float fFrameRate, int32_t iTargetBitRate) {
   int32_t iOrder;
   for (iOrder = 0; iOrder < LEVEL_NUMBER; iOrder++) {
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -156,7 +156,7 @@
     }
 
   }
-  return ENC_RETURN_SUCCESS;
+  return WelsCheckRefFrameLimitation (pLogCtx, pCfg);
 }
 
 
@@ -753,7 +753,7 @@
   pMa		= (*ppCtx)->pMemAlign;
   pParam	= (*ppCtx)->pSvcParam;
   iDlayerCount	= pParam->iSpatialLayerNum;
-  iNumRef	= pParam->iNumRefFrame;
+  iNumRef	= pParam->iMaxNumRefFrame;
 
   const int32_t kiFeatureStrategyIndex = FME_DEFAULT_FEATURE_INDEX;
   const int32_t kiMe16x16 = ME_DIA_CROSS;
@@ -927,7 +927,8 @@
 
     // Need port pSps/pPps initialization due to spatial scalability changed
     if (!bUseSubsetSps) {
-      WelsInitSps (pSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod, pParam->iNumRefFrame,
+      WelsInitSps (pSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
+                   pParam->iMaxNumRefFrame,
                    iSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE);
 
       if (iDlayerCount > 1) {
@@ -937,7 +938,7 @@
       }
     } else {
       WelsInitSubsetSps (pSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
-                         pParam->iNumRefFrame,
+                         pParam->iMaxNumRefFrame,
                          iSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE);
     }
 
@@ -1420,7 +1421,7 @@
   if (pParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {
     (*ppCtx)->pVaa	= (SVAAFrameInfoExt*)pMa->WelsMallocz (sizeof (SVAAFrameInfoExt), "pVaa");
     WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pVaa), FreeMemorySvc (ppCtx))
-    if (RequestMemoryVaaScreen ((*ppCtx)->pVaa, pMa, (*ppCtx)->pSvcParam->iNumRefFrame, iCountMaxMbNum << 2)) {
+    if (RequestMemoryVaaScreen ((*ppCtx)->pVaa, pMa, (*ppCtx)->pSvcParam->iMaxNumRefFrame, iCountMaxMbNum << 2)) {
       WelsLog (*ppCtx, WELS_LOG_WARNING, "RequestMemorySvc(), RequestMemoryVaaScreen failed!");
       FreeMemorySvc (ppCtx);
       return 1;
@@ -1674,7 +1675,7 @@
               FreePicture (pMa, &pRefList->pRef[iRef]);
             }
             ++ iRef;
-          } while (iRef < 1 + pParam->iNumRefFrame);
+          } while (iRef < 1 + pParam->iMaxNumRefFrame);
 
           pMa->WelsFree (pCtx->ppRefPicListExt[ilayer], "ppRefPicListExt[]");
           pCtx->ppRefPicListExt[ilayer] = NULL;
@@ -1727,7 +1728,7 @@
         pCtx->pVaa->sVaaCalcInfo.pMad8x8	= NULL;
       }
       if (pCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME)
-        ReleaseMemoryVaaScreen (pCtx->pVaa, pMa, pCtx->pSvcParam->iNumRefFrame);
+        ReleaseMemoryVaaScreen (pCtx->pVaa, pMa, pCtx->pSvcParam->iMaxNumRefFrame);
       pMa->WelsFree (pCtx->pVaa, "pVaa");
       pCtx->pVaa = NULL;
     }
@@ -3583,10 +3584,7 @@
   /* Decide whether need reset for IDR frame based on adjusting prarameters changed */
   /* Temporal levels, spatial settings and/ or quality settings changed need update parameter sets related. */
   bNeedReset	=	(pOldParam == NULL) ||
-                (pOldParam->iTemporalLayerNum != pNewParam->iTemporalLayerNum) ||
-                (pOldParam->uiGopSize != pNewParam->uiGopSize) ||
                 (pOldParam->iSpatialLayerNum != pNewParam->iSpatialLayerNum) ||
-                (pOldParam->iDecompStages != pNewParam->iDecompStages) ||
                 (pOldParam->iPicWidth != pNewParam->iPicWidth
                  || pOldParam->iPicHeight != pNewParam->iPicHeight) ||
                 (pOldParam->SUsedPicRect.iWidth != pNewParam->SUsedPicRect.iWidth
@@ -3593,6 +3591,11 @@
                  || pOldParam->SUsedPicRect.iHeight != pNewParam->SUsedPicRect.iHeight) ||
                 (pOldParam->bEnableLongTermReference != pNewParam->bEnableLongTermReference) ||
                 (pOldParam->iLTRRefNum != pNewParam->iLTRRefNum);
+  if (pNewParam->iMaxNumRefFrame > pOldParam->iMaxNumRefFrame) {
+    pNewParam->iMaxNumRefFrame = pOldParam->iMaxNumRefFrame;
+    bNeedReset = true;
+  }
+
   if (!bNeedReset) {	// Check its picture resolutions/quality settings respectively in each dependency layer
     iIndexD = 0;
     assert (pOldParam->iSpatialLayerNum == pNewParam->iSpatialLayerNum);
@@ -3630,12 +3633,6 @@
         bNeedReset = true;
         break;
       }
-
-      if (kpOldDlp->iHighestTemporalId != kpNewDlp->iHighestTemporalId) {
-        bNeedReset = true;
-        break;
-      }
-
       ++ iIndexD;
     } while (iIndexD < pOldParam->iSpatialLayerNum);
   }
--- a/codec/encoder/plus/src/welsEncoderExt.cpp
+++ b/codec/encoder/plus/src/welsEncoderExt.cpp
@@ -371,7 +371,8 @@
       pCfg->iNumRefFrame		= WELS_CLIP3 (pCfg->iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM);
     }
   }
-
+  if (pCfg->iNumRefFrame > pCfg->iMaxNumRefFrame)
+    pCfg->iMaxNumRefFrame = pCfg->iNumRefFrame;
   if (pCfg->iLtrMarkPeriod == 0) {
     pCfg->iLtrMarkPeriod = 30;
   }
@@ -559,12 +560,12 @@
   pLayerInfo->uiProfileIdc = uiProfileIdc;
   if ((iLayer == SPATIAL_LAYER_0) && (uiProfileIdc != PRO_BASELINE)) {
     pLayerInfo->uiProfileIdc = PRO_BASELINE;
-    WelsLog (m_pEncContext, WELS_LOG_WARNING, "doesn't support profile(%d),change to baseline profile", uiProfileIdc);
+    WelsLog (m_pEncContext, WELS_LOG_WARNING, "doesn't support profile(%d),change to baseline profile\n", uiProfileIdc);
   }
   if (iLayer > SPATIAL_LAYER_0) {
     if ((uiProfileIdc != PRO_BASELINE) || (uiProfileIdc != PRO_SCALABLE_BASELINE)) {
       pLayerInfo->uiProfileIdc = PRO_BASELINE;
-      WelsLog (m_pEncContext, WELS_LOG_WARNING, "doesn't support profile(%d),change to baseline profile", uiProfileIdc);
+      WelsLog (m_pEncContext, WELS_LOG_WARNING, "doesn't support profile(%d),change to baseline profile\n", uiProfileIdc);
     }
   }
 }
@@ -571,11 +572,18 @@
 void CWelsH264SVCEncoder::CheckLevelSetting (int32_t iLayer, ELevelIdc uiLevelIdc) {
   SSpatialLayerConfig* pLayerInfo = &m_pEncContext->pSvcParam->sSpatialLayers[iLayer];
   pLayerInfo->uiLevelIdc = uiLevelIdc;
-  //TBD
+  if ((uiLevelIdc < LEVEL_1_0) || (uiLevelIdc > LEVEL_5_2)) {
+    pLayerInfo->uiLevelIdc = LEVEL_5_2;
+    WelsLog (m_pEncContext, WELS_LOG_WARNING, "doesn't support level(%d) change to LEVEL_5_2\n", uiLevelIdc);
+  }
 }
 void CWelsH264SVCEncoder::CheckReferenceNumSetting (int32_t iNumRef) {
   m_pEncContext->pSvcParam->iNumRefFrame = iNumRef;
-  //TBD
+  if ((iNumRef < MIN_REF_PIC_COUNT) || (iNumRef > MAX_REFERENCE_PICTURE_COUNT_NUM)) {
+    m_pEncContext->pSvcParam->iNumRefFrame = AUTO_REF_PIC_COUNT;
+    WelsLog (m_pEncContext, WELS_LOG_WARNING,
+             "doesn't support the number of reference frame(%d) change to auto select mode\n", iNumRef);
+  }
 }
 /************************************************************************
 * InDataFormat, IDRInterval, SVC Encode Param, Frame Rate, Bitrate,..
@@ -936,7 +944,7 @@
   }
   break;
   case ENCODER_OPTION_DELIVERY_STATUS: {
-    SDeliveryStatus *pValue = (static_cast<SDeliveryStatus*>(pOption));
+    SDeliveryStatus* pValue = (static_cast<SDeliveryStatus*> (pOption));
     m_pEncContext->iDropNumber = pValue->iDropNum;
   }
   break;