shithub: openh264

Download patch

ref: 68fed53687643cc213e19947f9b86874ce9ffa5c
parent: 007fb470046337f06fcf695a5006f7446d12e48f
author: Sijia Chen <[email protected]>
date: Tue Sep 30 13:54:24 EDT 2014

add checking of frame rate and temporal layer setting for encoder input param
Reviewed at https://rbcommons.com/s/OpenH264/r/836/

--- a/codec/encoder/core/inc/param_svc.h
+++ b/codec/encoder/core/inc/param_svc.h
@@ -284,6 +284,7 @@
     iUsageType = pCodingParam.iUsageType;
     iPicWidth   = pCodingParam.iPicWidth;
     iPicHeight  = pCodingParam.iPicHeight;
+    fMaxFrameRate = fParamMaxFrameRate;
     iComplexityMode = pCodingParam.iComplexityMode;
 
     SUsedPicRect.iLeft = 0;
@@ -381,7 +382,6 @@
 
     SSpatialLayerInternal* pDlp		= &sDependencyLayers[0];
     SSpatialLayerConfig* pSpatialLayer = &sSpatialLayers[0];
-    float fMaxFr			= .0f;
     EProfileIdc uiProfileIdc		= PRO_BASELINE;
     int8_t iIdxSpatial	= 0;
     while (iIdxSpatial < iSpatialLayerNum) {
@@ -392,11 +392,9 @@
 
       float fLayerFrameRate	= WELS_CLIP3 (pCodingParam.sSpatialLayers[iIdxSpatial].fFrameRate,
                                           MIN_FRAME_RATE, fParamMaxFrameRate);
+      pDlp->fInputFrameRate	= fParamMaxFrameRate;
       pSpatialLayer->fFrameRate =
-        pDlp->fInputFrameRate	=
-          pDlp->fOutputFrameRate	= WELS_CLIP3 (fLayerFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);
-      if (pDlp->fInputFrameRate > fMaxFr + EPSN)
-        fMaxFr = pDlp->fInputFrameRate;
+        pDlp->fOutputFrameRate	= WELS_CLIP3 (fLayerFrameRate, MIN_FRAME_RATE, fParamMaxFrameRate);
 
 #ifdef ENABLE_FRAME_DUMP
       pDlp->sRecFileName[0]	= '\0';	// file to be constructed
@@ -427,8 +425,6 @@
       ++ iIdxSpatial;
     }
 
-    fMaxFrameRate	= fMaxFr;
-
     SetActualPicResolution();
 
     return 0;
@@ -454,7 +450,7 @@
   * \param	SWelsSvcCodingParam, and carried with known GOP size, max, input and output frame rate of each spatial
   * \return	NONE (should ensure valid parameter before this procedure)
   */
-  void DetermineTemporalSettings() {
+  int32_t DetermineTemporalSettings() {
     const int32_t iDecStages		= WELS_LOG2 (
                                     uiGopSize);	// (int8_t)GetLogFactor(1.0f, 1.0f * pcfg->uiGopSize);	//log2(uiGopSize)
     const uint8_t* pTemporalIdList	= &g_kuiTemporalIdListTable[iDecStages][0];
@@ -466,6 +462,9 @@
     while (i < iSpatialLayerNum) {
       const uint32_t kuiLogFactorInOutRate	= GetLogFactor (pDlp->fOutputFrameRate, pDlp->fInputFrameRate);
       const uint32_t kuiLogFactorMaxInRate	= GetLogFactor (pDlp->fInputFrameRate, fMaxFrameRate);
+      if (UINT_MAX == kuiLogFactorInOutRate || UINT_MAX == kuiLogFactorMaxInRate) {
+        return ENC_RETURN_INVALIDINPUT;
+      }
       int32_t iNotCodedMask = 0;
       int8_t iMaxTemporalId = 0;
 
@@ -486,6 +485,9 @@
       pDlp->iHighestTemporalId	= iMaxTemporalId;
       pDlp->iTemporalResolution	= kuiLogFactorMaxInRate + kuiLogFactorInOutRate;
       pDlp->iDecompositionStages	= iDecStages - kuiLogFactorMaxInRate - kuiLogFactorInOutRate;
+      if (pDlp->iDecompositionStages < 0) {
+        return ENC_RETURN_INVALIDINPUT;
+      }
 
       uiProfileIdc	= PRO_SCALABLE_BASELINE;
       ++ pDlp;
@@ -493,6 +495,7 @@
       ++ i;
     }
     iDecompStages = (int8_t)iDecStages;
+    return ENC_RETURN_SUCCESS;
   }
 
 } SWelsSvcCodingParam;
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -75,7 +75,6 @@
  * \return	successful - 0; otherwise none 0 for failed
  */
 int32_t ParamValidation (SLogContext* pLogCtx, SWelsSvcCodingParam* pCfg) {
-  float fMaxFrameRate = 0.0f;
   const float fEpsn = 0.000001f;
   int32_t i = 0;
 
@@ -128,25 +127,13 @@
       return ENC_RETURN_INVALIDINPUT;
     }
     if (UINT_MAX == GetLogFactor (fDlp->fOutputFrameRate, fDlp->fInputFrameRate)) {
-      WelsLog (pLogCtx, WELS_LOG_ERROR,
-               "Invalid settings in input frame rate(%.6f) and output frame rate(%.6f) of layer #%d config file: iResult of output frame rate divided by input frame rate should be power of 2(i.e,in/pOut=2^n)..",
-               fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i);
-      return ENC_RETURN_INVALIDINPUT;
+      WelsLog (pLogCtx, WELS_LOG_WARNING,
+               "AUTO CORRECT: Invalid settings in input frame rate(%.6f) and output frame rate(%.6f) of layer #%d config file: iResult of output frame rate divided by input frame rate should be power of 2(i.e,in/pOut=2^n). \n Auto correcting Output Framerate to Input Framerate %f!\n",
+               fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i, fDlp->fInputFrameRate);
+      fDlp->fOutputFrameRate = fDlp->fInputFrameRate;
     }
   }
 
-  for (i = 0; i < pCfg->iSpatialLayerNum; ++ i) {
-    SSpatialLayerInternal* fDlp = &pCfg->sDependencyLayers[i];
-    if (fDlp->fInputFrameRate > fMaxFrameRate)
-      fMaxFrameRate	= fDlp->fInputFrameRate;
-  }
-
-  if (fMaxFrameRate > fEpsn && (fMaxFrameRate - pCfg->fMaxFrameRate > fEpsn
-                                || fMaxFrameRate - pCfg->fMaxFrameRate < -fEpsn)) {
-    pCfg->fMaxFrameRate	= fMaxFrameRate;
-  }
-
-
   if ((pCfg->iRCMode != RC_OFF_MODE) && (pCfg->iRCMode != RC_QUALITY_MODE) && (pCfg->iRCMode != RC_BUFFERBASED_MODE)
       && (pCfg->iRCMode != RC_BITRATE_MODE)) {
     WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidation(),Invalid iRCMode = %d", pCfg->iRCMode);
@@ -2026,6 +2013,11 @@
     WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), ParamValidationExt failed return %d.", iRet);
     return iRet;
   }
+  iRet	=	pCodingParam->DetermineTemporalSettings();
+  if (iRet != ENC_RETURN_SUCCESS) {
+    WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), DetermineTemporalSettings failed return %d (check in/out frame rate and temporal layer setting!)", iRet);
+    return iRet;
+  }
   iRet = GetMultipleThreadIdc (pLogCtx, pCodingParam, iSliceNum, iCacheLineSize, uiCpuFeatureFlags);
   if (iRet != 0) {
     WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), GetMultipleThreadIdc failed return %d.", iRet);
@@ -2045,7 +2037,6 @@
   pCtx->pMemAlign = new CMemoryAlign (iCacheLineSize);
   WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pCtx->pMemAlign), FreeMemorySvc (&pCtx))
 
-  pCodingParam->DetermineTemporalSettings();
   iRet = AllocCodingParam (&pCtx->pSvcParam, pCtx->pMemAlign);
   if (iRet != 0) {
     FreeMemorySvc (&pCtx);
--- a/codec/encoder/plus/src/welsEncoderExt.cpp
+++ b/codec/encoder/plus/src/welsEncoderExt.cpp
@@ -346,6 +346,10 @@
   TraceParamInfo (pCfg);
   if (WelsInitEncoderExt (&m_pEncContext, pCfg, &m_pWelsTrace->m_sLogCtx)) {
     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), WelsInitEncoderExt failed.");
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_DEBUG,
+             "Problematic Input Base Param: iUsageType=%d, Resolution=%dx%d, FR=%f, TLayerNum=%d, DLayerNum=%d",
+             pCfg->iUsageType, pCfg->iPicWidth, pCfg->iPicHeight, pCfg->fMaxFrameRate, pCfg->iTemporalLayerNum,
+             pCfg->iSpatialLayerNum);
     Uninitialize();
     return cmInitParaError;
   }
@@ -519,7 +523,8 @@
   }
 }
 void CWelsH264SVCEncoder::CheckReferenceNumSetting (int32_t iNumRef) {
-  int32_t iRefUpperBound = (m_pEncContext->pSvcParam->iUsageType == CAMERA_VIDEO_REAL_TIME)?MAX_REFERENCE_PICTURE_COUNT_NUM_CAMERA:MAX_REFERENCE_PICTURE_COUNT_NUM_SCREEN;
+  int32_t iRefUpperBound = (m_pEncContext->pSvcParam->iUsageType == CAMERA_VIDEO_REAL_TIME) ?
+                           MAX_REFERENCE_PICTURE_COUNT_NUM_CAMERA : MAX_REFERENCE_PICTURE_COUNT_NUM_SCREEN;
   m_pEncContext->pSvcParam->iNumRefFrame = iNumRef;
   if ((iNumRef < MIN_REF_PIC_COUNT) || (iNumRef > iRefUpperBound)) {
     m_pEncContext->pSvcParam->iNumRefFrame = AUTO_REF_PIC_COUNT;
@@ -663,6 +668,11 @@
     if (sConfig.iSpatialLayerNum < 1) {
       return cmInitParaError;
     }
+    if (sConfig.DetermineTemporalSettings()) {
+      return cmInitParaError;
+    }
+
+    /* New configuration available here */
     iTargetWidth	= sConfig.iPicWidth;
     iTargetHeight	= sConfig.iPicHeight;
     if (m_iMaxPicWidth != iTargetWidth
@@ -676,9 +686,6 @@
              m_uiCountFrameNum, m_iCspInternal);
 #endif//REC_FRAME_COUNT
 
-    /* New configuration available here */
-    sConfig.DetermineTemporalSettings();
-
     /* Check every field whether there is new request for memory block changed or else, Oct. 24, 2008 */
     WelsEncoderParamAdjust (&m_pEncContext, &sConfig);
   }
@@ -906,12 +913,12 @@
   }
   break;
   case ENCODER_OPTION_COMPLEXITY: {
-    int32_t iValue = * (static_cast<int32_t*>(pOption));
+    int32_t iValue = * (static_cast<int32_t*> (pOption));
     m_pEncContext->pSvcParam->iComplexityMode = (ECOMPLEXITY_MODE)iValue;
   }
   break;
   case ENCODER_OPTION_IS_LOSSLESS_LINK: {
-    bool bValue = * (static_cast<bool*>(pOption));
+    bool bValue = * (static_cast<bool*> (pOption));
     m_pEncContext->pSvcParam->bIsLosslessLink = bValue;
   }
   break;