shithub: openh264

Download patch

ref: 7f3f397706835dfa376ead7b5a5d222507d31a6c
parent: 1e3b015a6f95ae87ce83d28304445770f35fec2e
parent: 80ae4cb7d8cbf7503b03dada6161ca79469fa893
author: huili2 <[email protected]>
date: Sat May 17 17:49:07 EDT 2014

Merge pull request #831 from sijchen/md_merge144

[Encoder ME] Add ME function assignment for Screen Content Coding

--- a/codec/encoder/core/inc/svc_motion_estimate.h
+++ b/codec/encoder/core/inc/svc_motion_estimate.h
@@ -90,6 +90,8 @@
   SMVUnitXY          sMvBase;
   SMVUnitXY          sDirectionalMv;
 
+  SScreenBlockFeatureStorage* pRefFeatureStorage;
+
   /* output */
   SMVUnitXY          sMv;
 } SWelsME;
@@ -220,7 +222,10 @@
                                      const int32_t kiMinPos, const int32_t kiMaxPos,
                                      const bool bVerticalSearch);
 #endif
-void WelsMotionCrossSearch (SWelsFuncPtrList* pFuncList,  SDqLayer* pCurLayer, SWelsME* pMe, const SSlice* pSlice);
+void WelsMotionCrossSearch (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice,
+                            const int32_t kiEncStride, const int32_t kiRefStride);
+void WelsDiamondCrossSearch (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice,
+                             const int32_t kiEncStride, const int32_t kiRefStride);
 
 // Feature Search Basics
 #define LIST_SIZE_SUM_16x16 0x0FF01  //(256*255+1)
@@ -255,6 +260,9 @@
                            SScreenBlockFeatureStorage* pScreenBlockFeatureStorage);
 void UpdateFMESwitch (SDqLayer* pCurLayer);
 void UpdateFMESwitchNull (SDqLayer* pCurLayer);
+
+void WelsDiamondCrossFeatureSearch (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice,
+                                    const int32_t kiEncStride, const int32_t kiRefStride);
 
 //inline functions
 inline void SetMvWithinIntegerMvRange (const int32_t kiMbWidth, const int32_t kiMbHeight, const int32_t kiMbX,
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -2428,8 +2428,38 @@
   pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3 =
     pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3Satd;
 }
+bool SetMeMethod (const uint8_t uiMethod, PSearchMethodFunc& pSearchMethodFunc) {
+  switch (uiMethod) {
+  case  ME_DIA:
+    pSearchMethodFunc  = WelsDiamondSearch;
+    break;
+  case  ME_CROSS:
+    pSearchMethodFunc = WelsMotionCrossSearch;
+    break;
+  case  ME_DIA_CROSS:
+    pSearchMethodFunc = WelsDiamondCrossSearch;
+    break;
+  case  ME_DIA_CROSS_FME:
+    pSearchMethodFunc = WelsDiamondCrossFeatureSearch;
+    break;
+  case ME_FULL:
+#ifdef HAVE_MMX
+    // make sure your cpu can support x86 sse4.1 instruction set if try it
+    //pSearchMethodFunc = WelsFullSearch;
+#else
+    pSearchMethodFunc = WelsDiamondSearch;
+    return false;
+#endif//HAVE_MMX
+    break;
+  default:
+    pSearchMethodFunc = WelsDiamondSearch;
+    return false;
+  }
+  return true;
+}
 
 
+
 void PreprocessSliceCoding (sWelsEncCtx* pCtx) {
   SDqLayer* pCurLayer		= pCtx->pCurDqLayer;
   //const bool kbBaseAvail	= pCurLayer->bBaseLayerAvailableFlag;
@@ -2465,13 +2495,19 @@
   return;
   //to init at each frame will be needed when dealing with hybrid content (camera+screen)
   if (pCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {
-    SFeatureSearchPreparation* pFeatureSearchPreparation = pCurLayer->pFeatureSearchPreparation;
-    if (pFeatureSearchPreparation) {
-      pFeatureSearchPreparation->iHighFreMbCount = 0;
+    if (P_SLICE == pCtx->eSliceType) {
+      //MD related func pointers
+      pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaaOnScreen;
 
-      if (P_SLICE == pCtx->eSliceType) {
-        //MD related func pointers
-        pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaaOnScreen;
+      //ME related func pointers
+      //ME16x16
+      if (!SetMeMethod (ME_DIA_CROSS, pFuncList->pfSearchMethod[BLOCK_16x16])) {
+        WelsLog (pCtx, WELS_LOG_WARNING, "SetMeMethod(BLOCK_16x16) ME_DIA_CROSS unsuccessful, switched to default search\n");
+      }
+      //ME8x8
+      SFeatureSearchPreparation* pFeatureSearchPreparation = pCurLayer->pFeatureSearchPreparation;
+      if (pFeatureSearchPreparation) {
+        pFeatureSearchPreparation->iHighFreMbCount = 0;
 
         //calculate bFMESwitchFlag
         SVAAFrameInfoExt* pVaaExt		= static_cast<SVAAFrameInfoExt*> (pCtx->pVaa);
@@ -2491,8 +2527,11 @@
         }
 
         //assign ME pointer
-        if (pScreenBlockFeatureStorage->bRefBlockFeatureCalculated) {
-          //TBC int32_t iIs16x16 = pScreenBlockFeatureStorage->iIs16x16;
+        if (pFeatureSearchPreparation->bFMESwitchFlag && pScreenBlockFeatureStorage->bRefBlockFeatureCalculated
+            && (!pScreenBlockFeatureStorage->iIs16x16)) {
+          if (!SetMeMethod (ME_DIA_CROSS_FME, pFuncList->pfSearchMethod[BLOCK_8x8])) {
+            WelsLog (pCtx, WELS_LOG_WARNING, "SetMeMethod(BLOCK_8x8) ME_DIA_CROSS_FME unsuccessful, switched to default search\n");
+          }
         }
 
         //assign UpdateFMESwitch pointer
@@ -2501,11 +2540,11 @@
         } else {
           pFuncList->pfUpdateFMESwitch = UpdateFMESwitchNull;
         }
-      } else {
-        //reset some status when at I_SLICE
-        pFeatureSearchPreparation->bFMESwitchFlag = true;
-        pFeatureSearchPreparation->uiFMEGoodFrameCount = FMESWITCH_DEFAULT_GOODFRAME_NUM;
-      }
+      }//if (pFeatureSearchPreparation)
+    } else {
+      //reset some status when at I_SLICE
+      pCurLayer->pFeatureSearchPreparation->bFMESwitchFlag = true;
+      pCurLayer->pFeatureSearchPreparation->uiFMEGoodFrameCount = FMESWITCH_DEFAULT_GOODFRAME_NUM;
     }
   }
 }
--- a/codec/encoder/core/src/svc_base_layer_md.cpp
+++ b/codec/encoder/core/src/svc_base_layer_md.cpp
@@ -971,6 +971,7 @@
 }
 
 static inline void InitMe (const SWelsMD& sWelsMd, const int32_t iBlockSize, uint8_t* pEnc, uint8_t* pRef,
+                           SScreenBlockFeatureStorage* pRefFeatureStorage,
                            SWelsME& sWelsMe) {
   sWelsMe.iCurMeBlockPixX = sWelsMd.iMbPixX;
   sWelsMe.iCurMeBlockPixY = sWelsMd.iMbPixY;
@@ -979,6 +980,8 @@
 
   sWelsMe.pEncMb = pEnc;
   sWelsMe.pRefMb = sWelsMe.pColoRefMb = pRef;
+
+  sWelsMe.pRefFeatureStorage = pRefFeatureStorage;
 }
 
 int32_t WelsMdP16x16 (SWelsFuncPtrList* pFunc, SDqLayer* pCurLayer, SWelsMD* pWelsMd, SSlice* pSlice, SMB* pCurMb) {
@@ -988,6 +991,7 @@
   const int32_t kiMbWidth	= pCurLayer->iMbWidth;	// for assign once
   const int32_t kiMbHeight	= pCurLayer->iMbHeight;
   InitMe (*pWelsMd, BLOCK_16x16, pMbCache->SPicData.pEncMb[0], pMbCache->SPicData.pRefMb[0],
+          pCurLayer->pRefPic->pScreenBlockFeatureStorage,
           *pMe16x16);
   //not putting the line below into InitMe to avoid judging mode in InitMe
   pMe16x16->uSadPredISatd.uiSadPred = pWelsMd->iSadPredMb;
@@ -1038,6 +1042,7 @@
     InitMe (*pWelsMd, BLOCK_16x8,
             pMbCache->SPicData.pEncMb[0] + (iPixelY * iStrideEnc),
             pMbCache->SPicData.pRefMb[0] + (iPixelY * iStrideRef),
+            pCurDqLayer->pRefPic->pScreenBlockFeatureStorage,
             *sMe16x8);
     //not putting the lines below into InitMe to avoid judging mode in InitMe
     sMe16x8->iCurMeBlockPixY = pWelsMd->iMbPixY + iPixelY;
@@ -1065,6 +1070,7 @@
     InitMe (*pWelsMd, BLOCK_8x16,
             pMbCache->SPicData.pEncMb[0] + iPixelX,
             pMbCache->SPicData.pRefMb[0] + iPixelX,
+            pCurLayer->pRefPic->pScreenBlockFeatureStorage,
             *sMe8x16);
     //not putting the lines below into InitMe to avoid judging mode in InitMe
     sMe8x16->iCurMeBlockPixX = pWelsMd->iMbPixX + iPixelX;
@@ -1100,6 +1106,7 @@
     InitMe (*pWelsMd, BLOCK_8x8,
             pMbCache->SPicData.pEncMb[0] + iStrideEnc,
             pMbCache->SPicData.pRefMb[0] + iStrideRef,
+            pCurDqLayer->pRefPic->pScreenBlockFeatureStorage,
             *sMe8x8);
     //not putting these three lines below into InitMe to avoid judging mode in InitMe
     sMe8x8->iCurMeBlockPixX = pWelsMd->iMbPixX + iPixelX;
--- a/codec/encoder/core/src/svc_motion_estimate.cpp
+++ b/codec/encoder/core/src/svc_motion_estimate.cpp
@@ -492,8 +492,8 @@
   }
 }
 
-void WelsMotionCrossSearch (SWelsFuncPtrList* pFuncList,  SWelsME* pMe,
-                            const SSlice* pSlice, const int32_t kiEncStride,  const int32_t kiRefStride) {
+void WelsMotionCrossSearch (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice,
+                            const int32_t kiEncStride,  const int32_t kiRefStride) {
   PLineFullSearchFunc pfVerticalFullSearchFunc = pFuncList->pfVerticalFullSearch;
   PLineFullSearchFunc pfHorizontalFullSearchFunc = pFuncList->pfHorizontalFullSearch;
 
@@ -709,7 +709,7 @@
   }
 }
 
-void CalculateFeatureOfBlock (SWelsFuncPtrList* pFunc, SPicture* pRef,
+bool CalculateFeatureOfBlock (SWelsFuncPtrList* pFunc, SPicture* pRef,
                               SScreenBlockFeatureStorage* pScreenBlockFeatureStorage) {
   uint16_t* pFeatureOfBlock = pScreenBlockFeatureStorage->pFeatureOfBlockPointer;
   uint32_t* pTimesOfFeatureValue = pScreenBlockFeatureStorage->pTimesOfFeatureValue;
@@ -716,6 +716,11 @@
   uint16_t** pLocationOfFeature  = pScreenBlockFeatureStorage->pLocationOfFeature;
   uint16_t* pBuf = pScreenBlockFeatureStorage->pLocationPointer;
 
+  if (NULL == pFeatureOfBlock || NULL == pTimesOfFeatureValue || NULL == pLocationOfFeature || NULL == pBuf
+      || NULL == pRef->pData[0]) {
+    return false;
+  }
+
   uint8_t* pRefData = pRef->pData[0];
   const int32_t iRefStride = pRef->iLineSize[0];
   int32_t iIs16x16 = pScreenBlockFeatureStorage->iIs16x16;
@@ -735,25 +740,28 @@
 
   //assign each pixel's pLocationOfFeature
   FillQpelLocationByFeatureValue_c (pFeatureOfBlock, iWidth, kiHeight, pFeatureValuePointerList);
+  return true;
 }
 
 void PerformFMEPreprocess (SWelsFuncPtrList* pFunc, SPicture* pRef, uint16_t*	pFeatureOfBlock,
                            SScreenBlockFeatureStorage* pScreenBlockFeatureStorage) {
   pScreenBlockFeatureStorage->pFeatureOfBlockPointer = pFeatureOfBlock;
-  CalculateFeatureOfBlock (pFunc, pRef, pScreenBlockFeatureStorage);
-  pScreenBlockFeatureStorage->bRefBlockFeatureCalculated = true;
+  pScreenBlockFeatureStorage->bRefBlockFeatureCalculated = CalculateFeatureOfBlock (pFunc, pRef,
+      pScreenBlockFeatureStorage);
 
-  uint32_t uiRefPictureAvgQstepx16 = QStepx16ByQp[WelsMedian (0, pRef->iFrameAverageQp, 51)];
-  uint32_t uiSadCostThreshold16x16 = ((30 * (uiRefPictureAvgQstepx16 + 160)) >> 3);
-  pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_16x16] = uiSadCostThreshold16x16;
-  pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_8x8] = (uiSadCostThreshold16x16 >> 2);
-  pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_16x8]
-    = pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_8x16]
-      = pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_4x4] = UINT_MAX;
+  if (pScreenBlockFeatureStorage->bRefBlockFeatureCalculated) {
+    uint32_t uiRefPictureAvgQstepx16 = QStepx16ByQp[WelsMedian (0, pRef->iFrameAverageQp, 51)];
+    uint32_t uiSadCostThreshold16x16 = ((30 * (uiRefPictureAvgQstepx16 + 160)) >> 3);
+    pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_16x16] = uiSadCostThreshold16x16;
+    pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_8x8] = (uiSadCostThreshold16x16 >> 2);
+    pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_16x8]
+      = pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_8x16]
+        = pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_4x4] = UINT_MAX;
+  }
 }
 
 //search related
-void SetFeatureSearchIn (SWelsFuncPtrList* pFunc,  const SWelsME& sMe,
+bool SetFeatureSearchIn (SWelsFuncPtrList* pFunc,  const SWelsME& sMe,
                          const SSlice* pSlice, SScreenBlockFeatureStorage* pRefFeatureStorage,
                          const int32_t kiEncStride, const int32_t kiRefStride,
                          SFeatureSearchIn* pFeatureSearchIn) {
@@ -781,6 +789,12 @@
   pFeatureSearchIn->iMinQpelY = pFeatureSearchIn->iCurPixYQpel + ((pSlice->sMvStartMin.iMvY) << 2);
   pFeatureSearchIn->iMaxQpelX = pFeatureSearchIn->iCurPixXQpel + ((pSlice->sMvStartMax.iMvX) << 2);
   pFeatureSearchIn->iMaxQpelY = pFeatureSearchIn->iCurPixYQpel + ((pSlice->sMvStartMax.iMvY) << 2);
+
+  if (NULL == pFeatureSearchIn->pSad || NULL == pFeatureSearchIn->pTimesOfFeature
+      || NULL == pFeatureSearchIn->pQpelLocationOfFeature) {
+    return false;
+  }
+  return true;
 }
 void SaveFeatureSearchOut (const SMVUnitXY sBestMv, const uint32_t uiBestSadCost, uint8_t* pRef,
                            SFeatureSearchOut* pFeatureSearchOut) {
@@ -922,8 +936,7 @@
   WelsDiamondSearch (pFunc, pMe, pSlice, kiEncStride, kiRefStride);
 
   //  Step 2: CROSS search
-  SScreenBlockFeatureStorage pRefBlockFeature; //TODO: use this structure from Ref
-  pMe->uiSadCostThreshold = pRefBlockFeature.uiSadCostThreshold[pMe->uiBlockSize];
+  pMe->uiSadCostThreshold = pMe->pRefFeatureStorage->uiSadCostThreshold[pMe->uiBlockSize];
   if (pMe->uiSadCost >= pMe->uiSadCostThreshold) {
     WelsMotionCrossSearch (pFunc, pMe, pSlice, kiEncStride, kiRefStride);
   }
@@ -937,14 +950,13 @@
   if (pMe->uiSadCost >= pMe->uiSadCostThreshold) {
     pSlice->uiSliceFMECostDown += pMe->uiSadCost;
 
-    SScreenBlockFeatureStorage tmpScreenBlockFeatureStorage; //TODO: use this structure from Ref
     uint32_t uiMaxSearchPoint = INT_MAX;//TODO: change it according to computational-complexity setting
     SFeatureSearchIn sFeatureSearchIn = {0};
-    SetFeatureSearchIn (pFunc, *pMe, pSlice, &tmpScreenBlockFeatureStorage,
-                        kiEncStride, kiRefStride,
-                        &sFeatureSearchIn);
-    MotionEstimateFeatureFullSearch (sFeatureSearchIn, uiMaxSearchPoint, pMe);
-
+    if (SetFeatureSearchIn (pFunc, *pMe, pSlice, pMe->pRefFeatureStorage,
+                            kiEncStride, kiRefStride,
+                            &sFeatureSearchIn)) {
+      MotionEstimateFeatureFullSearch (sFeatureSearchIn, uiMaxSearchPoint, pMe);
+    }
     pSlice->uiSliceFMECostDown -= pMe->uiSadCost;
   }
 }