shithub: openh264

Download patch

ref: e375a70c0377b69155d689cb2ea04a9b2b6ab044
parent: 8d11b28690d47d0e7a0c70beaadc06d96d3c47a5
parent: 99f3bd69c453ba81ca5be15bd4c77a4cfe590ee4
author: Licai Guo <licaguo@cisco.com>
date: Mon Mar 24 10:30:15 EDT 2014

Merge pull request #564 from sijchen/me_rfr56

[Encoder ME] Add checking directional MV in ME initial point

--- a/codec/encoder/core/inc/svc_motion_estimate.h
+++ b/codec/encoder/core/inc/svc_motion_estimate.h
@@ -140,6 +140,12 @@
 
 void CalculateSatdCost( PSampleSadSatdCostFunc pSatd, void * vpMe, const int32_t kiEncStride, const int32_t kiRefStride );
 void NotCalculateSatdCost( PSampleSadSatdCostFunc pSatd, void * vpMe, const int32_t kiEncStride, const int32_t kiRefStride );
+bool CheckDirectionalMv(PSampleSadSatdCostFunc pSad, void * vpMe,
+                      const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv, const int32_t kiEncStride, const int32_t kiRefStride,
+                      int32_t& iBestSadCost);
+bool CheckDirectionalMvFalse(PSampleSadSatdCostFunc pSad, void * vpMe,
+                      const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv, const int32_t kiEncStride, const int32_t kiRefStride,
+                      int32_t& iBestSadCost);
 
 inline void SetMvWithinMvRange( const int32_t kiMbWidth, const int32_t kiMbHeight, const int32_t kiMbX, const int32_t kiMbY,
                         const int32_t kiMaxMvRange,
@@ -151,6 +157,14 @@
   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));
+}
 }
 #endif
--- a/codec/encoder/core/inc/wels_func_ptr_def.h
+++ b/codec/encoder/core/inc/wels_func_ptr_def.h
@@ -136,6 +136,9 @@
 typedef void (*PMotionSearchFunc) (SWelsFuncPtrList* pFuncList, void* pCurDqLayer, void* pMe,
                                    void* pSlice);  // here after reset all function pointers, will set as right parameter type
 typedef void (*PCalculateSatdFunc) ( PSampleSadSatdCostFunc pSatd, void * vpMe, const int32_t kiEncStride, const int32_t kiRefStride );
+typedef bool (*PCheckDirectionalMv) (PSampleSadSatdCostFunc pSad, void * vpMe,
+                      const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv, const int32_t kiEncStride, const int32_t kiRefStride,
+                      int32_t& iBestSadCost);
 
 #define     MAX_BLOCK_TYPE 5 // prev 7
 typedef struct TagSampleDealingFunc {
@@ -188,6 +191,7 @@
   PMotionSearchFunc
   pfMotionSearch; //svc_encode_slice.c svc_mode_decision.c svc_enhance_layer_md.c svc_base_layer_md.c
   PCalculateSatdFunc pfCalculateSatd;
+  PCheckDirectionalMv pfCheckDirectionalMv;
 
   PCopyFunc      pfCopy16x16Aligned;		//svc_encode_slice.c svc_mode_decision.c svc_base_layer_md.c
   PCopyFunc      pfCopy16x16NotAligned;	//md.c
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -2515,6 +2515,7 @@
     pFuncList->pfMotionSearch  = WelsMotionEstimateSearch;
     pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode;
     pFuncList->sSampleDealingFuncs.pfMeCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSatd;
+    pFuncList->pfCheckDirectionalMv = CheckDirectionalMvFalse;
     if (kbHighestSpatialLayer) {
       pFuncList->pfCalculateSatd = NotCalculateSatdCost;
       pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaa;
--- a/codec/encoder/core/src/svc_base_layer_md.cpp
+++ b/codec/encoder/core/src/svc_base_layer_md.cpp
@@ -970,24 +970,31 @@
   WelsMdIntraSecondaryModesEnc (pEncCtx, pWelsMd, pCurMb, pMbCache);
 }
 
+static inline void InitMe(const SWelsMD& sWelsMd, const int32_t iBlockSize, uint8_t* pEnc, uint8_t* pRef,
+                   SWelsME& sWelsMe )
+{
+  sWelsMe.iCurMeBlockPixX = sWelsMd.iMbPixX;
+  sWelsMe.iCurMeBlockPixY = sWelsMd.iMbPixY;
+  sWelsMe.uiPixel = iBlockSize;
+  sWelsMe.pMvdCost = sWelsMd.pMvdCost;
+
+  sWelsMe.pEncMb = pEnc;
+  sWelsMe.pRefMb = sWelsMe.pColoRefMb = pRef;
+}
+
 int32_t WelsMdP16x16 (SWelsFuncPtrList* pFunc, SDqLayer* pCurLayer, SWelsMD* pWelsMd, SSlice* pSlice, SMB* pCurMb) {
   SMbCache* pMbCache = &pSlice->sMbCacheInfo;
-  SWelsME* sMe16x16 = &pWelsMd->sMe.sMe16x16;
+  SWelsME* pMe16x16 = &pWelsMd->sMe.sMe16x16;
   uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail;
   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],
+                   *pMe16x16 );
+  //not putting the line below into InitMe to avoid judging mode in InitMe
+  pMe16x16->uSadPredISatd.uiSadPred = pWelsMd->iSadPredMb;
 
-  sMe16x16->iCurMeBlockPixX = pWelsMd->iMbPixX;
-  sMe16x16->iCurMeBlockPixY = pWelsMd->iMbPixY;
-  sMe16x16->uiPixel = BLOCK_16x16;
-  sMe16x16->pMvdCost = pWelsMd->pMvdCost;
-
-  sMe16x16->pEncMb  = pMbCache->SPicData.pEncMb[0];
-  sMe16x16->pRefMb  = pMbCache->SPicData.pRefMb[0];
-  sMe16x16->uSadPredISatd.uiSadPred = pWelsMd->iSadPredMb;
-
   pSlice->uiMvcNum = 0;
-  pSlice->sMvc[pSlice->uiMvcNum++] = sMe16x16->sMvBase;
+  pSlice->sMvc[pSlice->uiMvcNum++] = pMe16x16->sMvBase;
   //spatial motion vector predictors
   if (uiNeighborAvail & LEFT_MB_POS) { //left available
     pSlice->sMvc[pSlice->uiMvcNum++] = (pCurMb - 1)->sP16x16Mv;
@@ -1011,14 +1018,14 @@
     }
   }
 
-  PredMv (&pMbCache->sMvComponents, 0, 4, 0, & (sMe16x16->sMvp));
-  pFunc->pfMotionSearch (pFunc, pCurLayer, sMe16x16, pSlice);
-//	update_p16x16_motion2cache(pMbCache, pWelsMd->uiRef, &(sMe16x16->mv));
+  PredMv (&pMbCache->sMvComponents, 0, 4, 0, & (pMe16x16->sMvp));
+  pFunc->pfMotionSearch (pFunc, pCurLayer, pMe16x16, pSlice);
+//	update_p16x16_motion2cache(pMbCache, pWelsMd->uiRef, &(pMe16x16->mv));
 
-  pCurMb->sP16x16Mv = sMe16x16->sMv;
-  pCurLayer->pDecPic->sMvList[pCurMb->iMbXY] = sMe16x16->sMv;
+  pCurMb->sP16x16Mv = pMe16x16->sMv;
+  pCurLayer->pDecPic->sMvList[pCurMb->iMbXY] = pMe16x16->sMv;
 
-  return sMe16x16->uiSatdCost;
+  return pMe16x16->uiSatdCost;
 }
 int32_t WelsMdP16x8 (SWelsFuncPtrList* pFunc, SDqLayer* pCurDqLayer, SWelsMD* pWelsMd, SSlice* pSlice) {
   SMbCache* pMbCache = &pSlice->sMbCacheInfo;
@@ -1025,16 +1032,17 @@
   int32_t iStrideEnc = pCurDqLayer->iEncStride[0];
   int32_t iStrideRef = pCurDqLayer->pRefPic->iLineSize[0];
   SWelsME* sMe16x8;
-  int32_t i = 0;
+  int32_t i = 0, iPixelY;
   int32_t iCostP16x8 = 0;
   do {
     sMe16x8 = &pWelsMd->sMe.sMe16x8[i];
-
-    sMe16x8->uiPixel = BLOCK_16x8;
-    sMe16x8->pMvdCost	 = pWelsMd->pMvdCost;
-
-    sMe16x8->pEncMb       = pMbCache->SPicData.pEncMb[0] + ((i << 3) * iStrideEnc);
-    sMe16x8->pRefMb       = pMbCache->SPicData.pRefMb[0] + ((i << 3) * iStrideRef);
+    iPixelY = (i << 3);
+    InitMe(*pWelsMd, BLOCK_16x8,
+      pMbCache->SPicData.pEncMb[0] + (iPixelY * iStrideEnc),
+      pMbCache->SPicData.pRefMb[0] + (iPixelY * iStrideRef),
+      *sMe16x8 );
+    //not putting the lines below into InitMe to avoid judging mode in InitMe
+    sMe16x8->iCurMeBlockPixY = pWelsMd->iMbPixY + iPixelY;
     sMe16x8->uSadPredISatd.uiSadPred = pWelsMd->iSadPredMb >> 1;
 
     pSlice->sMvc[0]	= sMe16x8->sMvBase;
@@ -1051,16 +1059,17 @@
 int32_t WelsMdP8x16 (SWelsFuncPtrList* pFunc, SDqLayer* pCurLayer, SWelsMD* pWelsMd, SSlice* pSlice) {
   SMbCache* pMbCache = &pSlice->sMbCacheInfo;
   SWelsME* sMe8x16;
-  int32_t i = 0;
+  int32_t i = 0, iPixelX;
   int32_t iCostP8x16 = 0;
   do {
+    iPixelX = (i << 3);
     sMe8x16 = &pWelsMd->sMe.sMe8x16[i];
-
-    sMe8x16->uiPixel = BLOCK_8x16;
-    sMe8x16->pMvdCost     = pWelsMd->pMvdCost;
-
-    sMe8x16->pEncMb       = pMbCache->SPicData.pEncMb[0] + (i << 3);
-    sMe8x16->pRefMb       = pMbCache->SPicData.pRefMb[0] + (i << 3);
+    InitMe(*pWelsMd, BLOCK_8x16,
+      pMbCache->SPicData.pEncMb[0] + iPixelX,
+      pMbCache->SPicData.pRefMb[0] + iPixelX,
+      *sMe8x16 );
+    //not putting the lines below into InitMe to avoid judging mode in InitMe
+    sMe8x16->iCurMeBlockPixX = pWelsMd->iMbPixX + iPixelX;
     sMe8x16->uSadPredISatd.uiSadPred = pWelsMd->iSadPredMb >> 1;
 
     pSlice->sMvc[0] = sMe8x16->sMvBase;
@@ -1091,16 +1100,16 @@
     iStrideRef = iPixelX + ( iPixelY * iLineSizeRef);
 
     sMe8x8 = &pWelsMd->sMe.sMe8x8[i];
-
+    InitMe(*pWelsMd, BLOCK_8x8,
+      pMbCache->SPicData.pEncMb[0] + iStrideEnc,
+      pMbCache->SPicData.pRefMb[0] + iStrideRef,
+      *sMe8x8 );
+    //not putting these three lines below into InitMe to avoid judging mode in InitMe
     sMe8x8->iCurMeBlockPixX = pWelsMd->iMbPixX + iPixelX;
     sMe8x8->iCurMeBlockPixY = pWelsMd->iMbPixY + iPixelY;
-    sMe8x8->uiPixel = BLOCK_8x8;
-    sMe8x8->pMvdCost = pWelsMd->pMvdCost;
-
-    sMe8x8->pEncMb       = pMbCache->SPicData.pEncMb[0] + iStrideEnc;
-    sMe8x8->pRefMb       = pMbCache->SPicData.pRefMb[0] + iStrideRef;
     sMe8x8->uSadPredISatd.uiSadPred = pWelsMd->iSadPredMb >> 2;
 
+
     pSlice->sMvc[0] = sMe8x8->sMvBase;
     pSlice->uiMvcNum = 1;
 
@@ -1855,5 +1864,7 @@
   WelsIMbChromaEncode (pEncCtx, pCurMb, pMbCache);  //add pEnc&rec to MD--2010.3.15
   pCurMb->pSadCost[0] = 0;
 }
+
+
 
 } // namespace WelsSVCEnc
--- a/codec/encoder/core/src/svc_motion_estimate.cpp
+++ b/codec/encoder/core/src/svc_motion_estimate.cpp
@@ -39,7 +39,7 @@
  */
 
 
-
+#include "sample.h"
 #include "svc_motion_estimate.h"
 
 namespace WelsSVCEnc {
@@ -141,6 +141,13 @@
     }
   }
 
+  if ( pFuncList->pfCheckDirectionalMv
+    (pSad, pMe, ksMvStartMin, ksMvStartMax, iStrideEnc, iStrideRef, iSadCost) ) {
+      sMv = pMe->sDirectionalMv;
+      pRefMb =  &pMe->pColoRefMb[sMv.iMvY * iStrideRef + sMv.iMvX];
+      iBestSadCost = iSadCost;
+  }
+
   UpdateMeResults( sMv, iBestSadCost, pRefMb, pMe );
   if ( iBestSadCost < static_cast<int32_t>(pMe->uSadPredISatd.uiSadPred) ) {
     //Initial point early Stop
@@ -235,6 +242,39 @@
 }
 void NotCalculateSatdCost( PSampleSadSatdCostFunc pSatd, void * vpMe, const int32_t kiEncStride, const int32_t kiRefStride )
 {
+}
+
+
+bool CheckDirectionalMv(PSampleSadSatdCostFunc pSad, void * vpMe,
+                      const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv, const int32_t kiEncStride, const int32_t kiRefStride,
+                      int32_t& iBestSadCost)
+{
+  SWelsME* pMe						 = static_cast<SWelsME *>(vpMe);
+  const int16_t kiMvX = pMe->sDirectionalMv.iMvX;
+  const int16_t kiMvY = pMe->sDirectionalMv.iMvY;
+
+  //Check MV from scrolling detection
+  if ( (BLOCK_16x16!=pMe->uiPixel) //scrolled_MV with P16x16 is checked SKIP checking function
+    && ( kiMvX | kiMvY ) //(0,0) checked in ordinary initial point checking
+    && CheckMvInRange( pMe->sDirectionalMv, ksMinMv, ksMaxMv ) )
+  {
+    uint8_t* pRef = &pMe->pColoRefMb[kiMvY * kiRefStride + kiMvX];
+    uint32_t uiCurrentSadCost = pSad( pMe->pEncMb, kiEncStride,  pRef, kiRefStride ) +
+      COST_MVD(pMe->pMvdCost, (kiMvX<<2) - pMe->sMvp.iMvX, (kiMvY<<2) - pMe->sMvp.iMvY );
+    if( uiCurrentSadCost < pMe->uiSadCost )
+    {
+      iBestSadCost = uiCurrentSadCost;
+      return true;
+    }
+  }
+  return false;
+}
+
+bool CheckDirectionalMvFalse(PSampleSadSatdCostFunc pSad, void * vpMe,
+                      const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv, const int32_t kiEncStride, const int32_t kiRefStride,
+                      int32_t& iBestSadCost)
+{
+  return false;
 }
 
 } // namespace WelsSVCEnc