shithub: openh264

Download patch

ref: 4fab8c2ee72b10615b0e45832a1c5c60a4654d96
parent: 292d2511e2f91ffc00a1b9addf0876a0bcad271e
author: Sijia Chen <sijchen@cisco.com>
date: Tue Oct 28 12:58:59 EDT 2014

for reference selection under screen:
1, ref_list_mgr_svc.cpp, Ln314: fix a wrong DeleteLTRFromLongList which should not be used under screen strategy
2, ref_list_mgr_svc.cpp, Ln910: remove the frame which is furthest in distance to the current frame in ref list
3, wels_preprocess.cpp: use scene LTR ref list when the current frame is scene LTR
-, ref_list_mgr_svc.cpp, Ln811: add DEBUG trace
reviewed at: https://rbcommons.com/s/OpenH264/r/870/

--- a/codec/common/inc/macros.h
+++ b/codec/common/inc/macros.h
@@ -272,6 +272,9 @@
 #define WELS_GCC_UNUSED
 #endif
 
+inline bool CheckInRangeCloseOpen (const int16_t kiCurrent, const int16_t kiMin, const int16_t kiMax) {
+return ((kiCurrent >= kiMin) && (kiCurrent < kiMax));
+}
 
 
 #endif//WELS_MACRO_UTILIZATIONS_H__
--- a/codec/encoder/core/inc/svc_motion_estimate.h
+++ b/codec/encoder/core/inc/svc_motion_estimate.h
@@ -342,12 +342,9 @@
 pMvMax->iMvY = WELS_MIN (((kiMbHeight - kiMbY) << 4) - INTPEL_NEEDED_MARGIN, kiMaxMvRange);
 }
 
-inline bool CheckMvInRange (const int16_t kiCurrentMv, const int16_t kiMinMv, const int16_t kiMaxMv) {
-return ((kiCurrentMv >= kiMinMv) && (kiCurrentMv < kiMaxMv));
-}
 inline bool CheckMvInRange (const SMVUnitXY ksCurrentMv, const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv) {
-return (CheckMvInRange (ksCurrentMv.iMvX, ksMinMv.iMvX, ksMaxMv.iMvX)
-        && CheckMvInRange (ksCurrentMv.iMvY, ksMinMv.iMvY, ksMaxMv.iMvY));
+return (CheckInRangeCloseOpen (ksCurrentMv.iMvX, ksMinMv.iMvX, ksMaxMv.iMvX)
+        && CheckInRangeCloseOpen (ksCurrentMv.iMvY, ksMinMv.iMvY, ksMaxMv.iMvY));
 }
 //FME switch related
 inline bool CalcFMESwitchFlag (const uint8_t uiFMEGoodFrameCount, const int32_t iHighFreMbPrecentage,
--- a/codec/encoder/core/inc/wels_preprocess.h
+++ b/codec/encoder/core/inc/wels_preprocess.h
@@ -106,7 +106,8 @@
 typedef struct SVAAFrameInfoExt_t: public SVAAFrameInfo {
   SComplexityAnalysisScreenParam    sComplexityScreenParam;
   SScrollDetectionParam    sScrollDetectInfo;
-  SRefInfoParam    sVaaStrBestRefCandidate[MAX_REF_PIC_COUNT];   //TOP3_BEST_REF_NO_TID
+  SRefInfoParam    sVaaStrBestRefCandidate[MAX_REF_PIC_COUNT];
+  SRefInfoParam    sVaaLtrBestRefCandidate[MAX_REF_PIC_COUNT];
   int32_t    iNumOfAvailableRef;
 
   int32_t     iVaaBestRefFrameNum;
@@ -127,7 +128,7 @@
   int32_t AnalyzeSpatialPic (sWelsEncCtx* pEncCtx, const int32_t kiDIdx);
   int32_t UpdateSpatialPictures (sWelsEncCtx* pEncCtx, SWelsSvcCodingParam* pParam, const int8_t iCurTid,
                                  const int32_t d_idx);
-  int32_t GetRefFrameInfo (int32_t iRefIdx, SPicture*& pRefOri);
+  int32_t GetRefFrameInfo (int32_t iRefIdx, bool bCurrentFrameIsSceneLtr, SPicture*& pRefOri);
   void    AnalyzePictureComplexity (sWelsEncCtx* pCtx, SPicture* pCurPicture, SPicture* pRefPicture,
                                     const int32_t kiDependencyId, const bool kbCalculateBGD);
   int32_t UpdateBlockIdcForScreen (uint8_t*  pCurBlockStaticPointer, const SPicture* kpRefPic, const SPicture* kpSrcPic);
--- a/codec/encoder/core/src/ref_list_mgr_svc.cpp
+++ b/codec/encoder/core/src/ref_list_mgr_svc.cpp
@@ -106,6 +106,7 @@
     SPicture* pRef = pRefList->pLongRefList[i];
     if (pRef != NULL &&  pRef->bUsedAsRef && pRef->bIsLongRef && (!pRef->bIsSceneLTR) &&
         (pCtx->uiTemporalId < pRef->uiTemporalId || pCtx->bCurFrameMarkedAsSceneLtr)) {
+      //this is our strategy to Unref all non-sceneLTR when the the current frame is sceneLTR
       pRef->SetUnref();
       DeleteLTRFromLongList (pCtx, i);
       i--;
@@ -310,12 +311,13 @@
   int32_t iLtrIdx =  pCtx->pDecPic->iLongTermPicNum;
   pCtx->pVaa->uiMarkLongTermPicIdx = pCtx->pDecPic->iLongTermPicNum;
 
+  assert (CheckInRangeCloseOpen (iLtrIdx, 0, MAX_REF_PIC_COUNT));
   if (pLongRefList[iLtrIdx] != NULL) {
     pLongRefList[iLtrIdx]->SetUnref();
-    DeleteLTRFromLongList (pCtx, iLtrIdx);
+  } else {
+    pRefList->uiLongRefCount++;
   }
   pLongRefList[iLtrIdx] = pCtx->pDecPic;
-  pRefList->uiLongRefCount++;
 }
 
 static void PrefetchNextBuffer (void* pEncCtx) {
@@ -773,7 +775,7 @@
     int iLtrRefIdx = 0;
     SPicture* pRefOri = NULL;
     for (int idx = 0; idx < pVaaExt->iNumOfAvailableRef; idx++) {
-      iLtrRefIdx = pCtx->pVpp->GetRefFrameInfo (idx, pRefOri);
+      iLtrRefIdx = pCtx->pVpp->GetRefFrameInfo (idx, pCtx->bCurFrameMarkedAsSceneLtr, pRefOri);
       if (iLtrRefIdx >= 0 && iLtrRefIdx <= pParam->iLTRRefNum) {
         SPicture* pRefPic = pRefList->pLongRefList[iLtrRefIdx];
         if (pRefPic != NULL && pRefPic->bUsedAsRef && pRefPic->bIsLongRef) {
@@ -805,6 +807,29 @@
         }
       }
     } // end of (int idx = 0; idx < pVaaExt->iNumOfAvailableRef; idx++)
+
+    WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
+             "WelsBuildRefListScreen(), CurrentFramePoc=%d, isLTR=%d", iPOC, pCtx->bCurFrameMarkedAsSceneLtr);
+    for (int j = 0; j < iNumRef; j++) {
+      SPicture*	 pARefPicture = pRefList->pLongRefList[j];
+      if (pARefPicture != NULL) {
+        WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
+                 "WelsBuildRefListScreen()\tRefLot[%d]: iPoc=%d, iPictureType=%d, bUsedAsRef=%d, bIsLongRef=%d, bIsSceneLTR=%d, uiTemporalId=%d, iFrameNum=%d, iMarkFrameNum=%d, iLongTermPicNum=%d, uiRecieveConfirmed=%d",
+                 j,
+                 pARefPicture->iFramePoc,
+                 pARefPicture->iPictureType,
+                 pARefPicture->bUsedAsRef,
+                 pARefPicture->bIsLongRef,
+                 pARefPicture->bIsSceneLTR,
+                 pARefPicture->uiTemporalId,
+                 pARefPicture->iFrameNum,
+                 pARefPicture->iMarkFrameNum,
+                 pARefPicture->iLongTermPicNum,
+                 pARefPicture->uiRecieveConfirmed);
+      } else {
+        WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, "WelsBuildRefListScreen()\tRefLot[%d]: NULL", j);
+      }
+    }
   } else {
     // dealing with IDR
     WelsResetRefList (pCtx);  //for IDR, SHOULD reset pRef list.
@@ -817,6 +842,11 @@
 
   return (pCtx->iNumRef0 > 0 || pCtx->eSliceType == I_SLICE) ? (true) : (false);
 }
+
+static inline bool IsValidFrameNum (const int32_t kiFrameNum) {
+  return (kiFrameNum < (1 << 30)); // TODO: use the original judge first, may be improved
+}
+
 void WelsMarkPicScreen (void* pEncCtx) {
 #define STR_ROOM 1
   sWelsEncCtx* pCtx     = (sWelsEncCtx*)pEncCtx;
@@ -853,7 +883,6 @@
           }
         }
       } else {
-        int32_t iMinSTRframe_num = 1 << 30; // is big enough
         int32_t iRefNum_t[MAX_TEMPORAL_LAYER_NUM] =	 {0};
         for (i = 0 ; i < pRefList->uiLongRefCount ; ++i) {
           if (ppLongRefList[i]->bUsedAsRef && ppLongRefList[i]->bIsLongRef && (!ppLongRefList[i]->bIsSceneLTR))	{
@@ -867,11 +896,20 @@
             iMaxMultiRefTid = i;
           }
         }
+        int32_t iLongestDeltaFrameNum = -1;
+        int32_t iMaxFrameNum = (1 << pCtx->pSps->uiLog2MaxFrameNum);
+
         for (i = 0 ; i < pRefList->uiLongRefCount ; ++i) {
           if (ppLongRefList[i]->bUsedAsRef && ppLongRefList[i]->bIsLongRef && (!ppLongRefList[i]->bIsSceneLTR)
               && iMaxMultiRefTid == ppLongRefList[i]->uiTemporalId)	{
-            if (ppLongRefList[i]->iFrameNum < iMinSTRframe_num) {
+            assert (IsValidFrameNum (ppLongRefList[i]->iFrameNum)); // pLtr->iCurLtrIdx must have a value
+            int32_t iDeltaFrameNum = (pCtx->iFrameNum >= ppLongRefList[i]->iFrameNum)
+                                     ? (pCtx->iFrameNum - ppLongRefList[i]->iFrameNum)
+                                     : (pCtx->iFrameNum + iMaxFrameNum - ppLongRefList[i]->iFrameNum);
+
+            if (iDeltaFrameNum > iLongestDeltaFrameNum) {
               pLtr->iCurLtrIdx = ppLongRefList[i]->iLongTermPicNum;
+              iLongestDeltaFrameNum = iDeltaFrameNum;
             }
           }
         }
--- a/codec/encoder/core/src/wels_preprocess.cpp
+++ b/codec/encoder/core/src/wels_preprocess.cpp
@@ -219,7 +219,8 @@
 
   if (pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {
     SVAAFrameInfoExt* pVaaExt			= static_cast<SVAAFrameInfoExt*> (m_pEncCtx->pVaa);
-    SRefInfoParam* BestRefCandidateParam = & (pVaaExt->sVaaStrBestRefCandidate[0]);
+    SRefInfoParam* BestRefCandidateParam = (pCtx->bCurFrameMarkedAsSceneLtr) ? (& (pVaaExt->sVaaLtrBestRefCandidate[0])) :
+                                           (& (pVaaExt->sVaaStrBestRefCandidate[0]));
     SPicture* pRefPic = m_pSpatialPic[0][BestRefCandidateParam->iSrcListIdx];
 
     VaaCalculation (pCtx->pVaa, pCurPic, pRefPic, false, bCalculateVar, bCalculateBGD);
@@ -1116,8 +1117,8 @@
   pVaaExt->iVaaBestRefFrameNum = sLtrSaved.pRefPicture->iFrameNum;
   pVaaExt->pVaaBestBlockStaticIdc = sLtrSaved.pBestBlockStaticIdc;
 
-  if (0 == iAvailableSceneRefNum) {
-    SaveBestRefToVaa (sSceneLtrSaved, & (pVaaExt->sVaaStrBestRefCandidate[1]));
+  if (0 < iAvailableSceneRefNum) {
+    SaveBestRefToVaa (sSceneLtrSaved, & (pVaaExt->sVaaLtrBestRefCandidate[0]));
   }
 
   pVaaExt->iNumOfAvailableRef = 1;
@@ -1124,13 +1125,13 @@
   return static_cast<ESceneChangeIdc> (iVaaFrameSceneChangeIdc);
 }
 
-int32_t CWelsPreProcess::GetRefFrameInfo (int32_t iRefIdx, SPicture*& pRefOri) {
+int32_t CWelsPreProcess::GetRefFrameInfo (int32_t iRefIdx, bool bCurrentFrameIsSceneLtr, SPicture*& pRefOri) {
   const int32_t iTargetDid = m_pEncCtx->pSvcParam->iSpatialLayerNum - 1;
   SVAAFrameInfoExt* pVaaExt			= static_cast<SVAAFrameInfoExt*> (m_pEncCtx->pVaa);
-  SRefInfoParam* BestRefCandidateParam = & (pVaaExt->sVaaStrBestRefCandidate[iRefIdx]);
-  int32_t iLtrRefIdx = m_pSpatialPic[iTargetDid][BestRefCandidateParam->iSrcListIdx]->iLongTermPicNum;
-  pRefOri = m_pSpatialPic[iTargetDid][BestRefCandidateParam->iSrcListIdx];
-  return iLtrRefIdx;
+  SRefInfoParam* pBestRefCandidateParam = (bCurrentFrameIsSceneLtr) ? (& (pVaaExt->sVaaLtrBestRefCandidate[iRefIdx])) :
+                                          (& (pVaaExt->sVaaStrBestRefCandidate[iRefIdx]));
+  pRefOri = m_pSpatialPic[iTargetDid][pBestRefCandidateParam->iSrcListIdx];
+  return (m_pSpatialPic[iTargetDid][pBestRefCandidateParam->iSrcListIdx]->iLongTermPicNum);
 }
 void  CWelsPreProcess::Padding (uint8_t* pSrcY, uint8_t* pSrcU, uint8_t* pSrcV, int32_t iStrideY, int32_t iStrideUV,
                                 int32_t iActualWidth, int32_t iPaddingWidth, int32_t iActualHeight, int32_t iPaddingHeight) {
--- a/test/api/encoder_test.cpp
+++ b/test/api/encoder_test.cpp
@@ -129,7 +129,7 @@
   //for different strategy
   {
     "res/Cisco_Absolute_Power_1280x720_30fps.yuv",
-    "868f327765dc8e705ad6a9a942bfc7e32c03c791", SCREEN_CONTENT_REAL_TIME, 1280, 720, 30.0f, SM_DYN_SLICE, false, 1, true, true, false
+    "6a7fc060a4d9dc0ec397987f02df0cf4d96181e6", SCREEN_CONTENT_REAL_TIME, 1280, 720, 30.0f, SM_DYN_SLICE, false, 1, true, true, false
   },
   {
     "res/CiscoVT2people_320x192_12fps.yuv",