1095 lines · 45.8 KB · C++
RawDownload
/*! * \copy *     Copyright (c)  2009-2013, Cisco Systems *     All rights reserved. * *     Redistribution and use in source and binary forms, with or without *     modification, are permitted provided that the following conditions *     are met: * *        * Redistributions of source code must retain the above copyright *          notice, this list of conditions and the following disclaimer. * *        * Redistributions in binary form must reproduce the above copyright *          notice, this list of conditions and the following disclaimer in *          the documentation and/or other materials provided with the *          distribution. * *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *     POSSIBILITY OF SUCH DAMAGE. * * * \file  svc motion estimate.c * * \brief  Interfaces introduced in svc mb motion estimation * * \date  08/11/2009 Created * ************************************************************************************* */ #include "cpu_core.h"#include "ls_defines.h"#include "svc_motion_estimate.h"#include "wels_transpose_matrix.h" namespace WelsEnc { const int32_t QStepx16ByQp[52] = {  /* save QStep<<4 for int32_t */  10,  11,  13,  14,  16,  18,  /* 0~5   */  20,  22,  26,  28,  32,  36,  /* 6~11  */  40,  44,  52,  56,  64,  72,  /* 12~17 */  80,  88,  104, 112, 128, 144, /* 18~23 */  160, 176, 208, 224, 256, 288, /* 24~29 */  320, 352, 416, 448, 512, 576, /* 30~35 */  640, 704, 832, 896, 1024, 1152, /* 36~41 */  1280, 1408, 1664, 1792, 2048, 2304, /* 42~47 */  2560, 2816, 3328, 3584     /* 48~51 */}; static inline void UpdateMeResults (const SMVUnitXY ksBestMv, const uint32_t kiBestSadCost, uint8_t* pRef,                                    SWelsME* pMe) {  pMe->sMv = ksBestMv;  pMe->pRefMb = pRef;  pMe->uiSadCost = kiBestSadCost;}static inline void MeEndIntepelSearch (SWelsME* pMe) {  /* -> qpel mv */  pMe->sMv.iMvX <<= 2;  pMe->sMv.iMvY <<= 2;  pMe->uiSatdCost = pMe->uiSadCost;} void WelsInitMeFunc (SWelsFuncPtrList* pFuncList, uint32_t uiCpuFlag, bool bScreenContent) {  pFuncList->pfUpdateFMESwitch = UpdateFMESwitchNull;   if (!bScreenContent) {    pFuncList->pfCheckDirectionalMv = CheckDirectionalMvFalse;    pFuncList->pfCalculateBlockFeatureOfFrame[0] =      pFuncList->pfCalculateBlockFeatureOfFrame[1] = NULL;    pFuncList->pfCalculateSingleBlockFeature[0] =      pFuncList->pfCalculateSingleBlockFeature[1] = NULL;   } else {    pFuncList->pfCheckDirectionalMv = CheckDirectionalMv;     //for cross serarch    pFuncList->pfVerticalFullSearch = LineFullSearch_c;    pFuncList->pfHorizontalFullSearch = LineFullSearch_c; #if defined (X86_ASM)    if (uiCpuFlag & WELS_CPU_SSE41) {      pFuncList->pfSampleSadHor8[0] = SampleSad8x8Hor8_sse41;      pFuncList->pfSampleSadHor8[1] = SampleSad16x16Hor8_sse41;      pFuncList->pfVerticalFullSearch = VerticalFullSearchUsingSSE41;      pFuncList->pfHorizontalFullSearch = HorizontalFullSearchUsingSSE41;    }#endif     //for feature search    pFuncList->pfInitializeHashforFeature = InitializeHashforFeature_c;    pFuncList->pfFillQpelLocationByFeatureValue = FillQpelLocationByFeatureValue_c;    pFuncList->pfCalculateBlockFeatureOfFrame[0] = SumOf8x8BlockOfFrame_c;    pFuncList->pfCalculateBlockFeatureOfFrame[1] = SumOf16x16BlockOfFrame_c;    //TODO: it is possible to differentiate width that is times of 8, so as to accelerate the speed when width is times of 8?    pFuncList->pfCalculateSingleBlockFeature[0] = SumOf8x8SingleBlock_c;    pFuncList->pfCalculateSingleBlockFeature[1] = SumOf16x16SingleBlock_c;#if defined (X86_ASM)    if (uiCpuFlag & WELS_CPU_SSE2) {      //for feature search      pFuncList->pfInitializeHashforFeature = InitializeHashforFeature_sse2;      pFuncList->pfFillQpelLocationByFeatureValue = FillQpelLocationByFeatureValue_sse2;      pFuncList->pfCalculateBlockFeatureOfFrame[0] = SumOf8x8BlockOfFrame_sse2;      pFuncList->pfCalculateBlockFeatureOfFrame[1] = SumOf16x16BlockOfFrame_sse2;      //TODO: it is possible to differentiate width that is times of 8, so as to accelerate the speed when width is times of 8?      pFuncList->pfCalculateSingleBlockFeature[0] = SumOf8x8SingleBlock_sse2;      pFuncList->pfCalculateSingleBlockFeature[1] = SumOf16x16SingleBlock_sse2;    }    if (uiCpuFlag & WELS_CPU_SSE41) {      //for feature search      pFuncList->pfCalculateBlockFeatureOfFrame[0] = SumOf8x8BlockOfFrame_sse4;      pFuncList->pfCalculateBlockFeatureOfFrame[1] = SumOf16x16BlockOfFrame_sse4;    }#endif #if defined (HAVE_NEON)    if (uiCpuFlag & WELS_CPU_NEON) {      //for feature search      pFuncList->pfInitializeHashforFeature = InitializeHashforFeature_neon;      pFuncList->pfFillQpelLocationByFeatureValue = FillQpelLocationByFeatureValue_neon;      pFuncList->pfCalculateBlockFeatureOfFrame[0] = SumOf8x8BlockOfFrame_neon;      pFuncList->pfCalculateBlockFeatureOfFrame[1] = SumOf16x16BlockOfFrame_neon;      //TODO: it is possible to differentiate width that is times of 8, so as to accelerate the speed when width is times of 8?      pFuncList->pfCalculateSingleBlockFeature[0] = SumOf8x8SingleBlock_neon;      pFuncList->pfCalculateSingleBlockFeature[1] = SumOf16x16SingleBlock_neon;    }#endif #if defined (HAVE_NEON_AARCH64)    if (uiCpuFlag & WELS_CPU_NEON) {      //for feature search      pFuncList->pfInitializeHashforFeature = InitializeHashforFeature_AArch64_neon;      pFuncList->pfFillQpelLocationByFeatureValue = FillQpelLocationByFeatureValue_AArch64_neon;      pFuncList->pfCalculateBlockFeatureOfFrame[0] = SumOf8x8BlockOfFrame_AArch64_neon;      pFuncList->pfCalculateBlockFeatureOfFrame[1] = SumOf16x16BlockOfFrame_AArch64_neon;      //TODO: it is possible to differentiate width that is times of 8, so as to accelerate the speed when width is times of 8?      pFuncList->pfCalculateSingleBlockFeature[0] = SumOf8x8SingleBlock_AArch64_neon;      pFuncList->pfCalculateSingleBlockFeature[1] = SumOf16x16SingleBlock_AArch64_neon;    }#endif  }} /*! * \brief  BL mb motion estimate search * * \param  enc      Wels encoder context * \param  pMe          Wels me information * * \return  NONE */ void WelsMotionEstimateSearch (SWelsFuncPtrList* pFuncList, void* pLplayer, void* pLpme, void* pLpslice) {  SDqLayer* pCurDqLayer      = (SDqLayer*)pLplayer;  SWelsME* pMe            = (SWelsME*)pLpme;  SSlice* pSlice          = (SSlice*)pLpslice;  const int32_t kiStrideEnc = pCurDqLayer->iEncStride[0];  const int32_t kiStrideRef = pCurDqLayer->pRefPic->iLineSize[0];   //  Step 1: Initial point prediction  if (!WelsMotionEstimateInitialPoint (pFuncList, pMe, pSlice, kiStrideEnc, kiStrideRef)) {    pFuncList->pfSearchMethod[pMe->uiBlockSize] (pFuncList, pMe, pSlice, kiStrideEnc, kiStrideRef);    MeEndIntepelSearch (pMe);  }   pFuncList->pfCalculateSatd (pFuncList->sSampleDealingFuncs.pfSampleSatd[pMe->uiBlockSize], pMe, kiStrideEnc,                              kiStrideRef);} void WelsMotionEstimateSearchStatic (SWelsFuncPtrList* pFuncList, void* pLplayer, void* pLpme, void* pLpslice) {  SDqLayer* pCurDqLayer      = (SDqLayer*)pLplayer;  SWelsME* pMe            = (SWelsME*)pLpme;  const int32_t kiStrideEnc = pCurDqLayer->iEncStride[0];  const int32_t kiStrideRef = pCurDqLayer->pRefPic->iLineSize[0];   pMe->sMv.iMvX = pMe->sMv.iMvY = 0;  pMe->uiSadCost =    pFuncList->sSampleDealingFuncs.pfSampleSad[pMe->uiBlockSize] (pMe->pEncMb, kiStrideEnc, pMe->pRefMb, kiStrideRef) ;  pMe->uiSadCost += COST_MVD (pMe->pMvdCost, - pMe->sMvp.iMvX, - pMe->sMvp.iMvY);  MeEndIntepelSearch (pMe);  pFuncList->pfCalculateSatd (pFuncList->sSampleDealingFuncs.pfSampleSatd[pMe->uiBlockSize], pMe, kiStrideEnc,                              kiStrideRef);} void WelsMotionEstimateSearchScrolled (SWelsFuncPtrList* pFuncList, void* pLplayer, void* pLpme, void* pLpslice) {  SDqLayer* pCurDqLayer      = (SDqLayer*)pLplayer;  SWelsME* pMe            = (SWelsME*)pLpme;  const int32_t kiStrideEnc = pCurDqLayer->iEncStride[0];  const int32_t kiStrideRef = pCurDqLayer->pRefPic->iLineSize[0];   pMe->sMv = pMe->sDirectionalMv;  pMe->pRefMb = pMe->pColoRefMb + pMe->sMv.iMvY * kiStrideRef + pMe->sMv.iMvX;  pMe->uiSadCost =    pFuncList->sSampleDealingFuncs.pfSampleSad[pMe->uiBlockSize] (pMe->pEncMb, kiStrideEnc, pMe->pRefMb, kiStrideRef)    + COST_MVD (pMe->pMvdCost, (pMe->sMv.iMvX << 2) - pMe->sMvp.iMvX, (pMe->sMv.iMvY << 2) - pMe->sMvp.iMvY);  MeEndIntepelSearch (pMe);  pFuncList->pfCalculateSatd (pFuncList->sSampleDealingFuncs.pfSampleSatd[pMe->uiBlockSize], pMe, kiStrideEnc,                              kiStrideRef);}/*! * \brief  EL mb motion estimate initial point testing * * \param  pix_pFuncList  SSampleDealingFunc * \param  pMe          Wels me information * \param  mv_range  search range in motion estimate * \param  point      the best match point in motion estimation * * \return  NONE */bool WelsMotionEstimateInitialPoint (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice, int32_t iStrideEnc,                                     int32_t iStrideRef) {  PSampleSadSatdCostFunc pSad    = pFuncList->sSampleDealingFuncs.pfSampleSad[pMe->uiBlockSize];  const uint16_t* kpMvdCost  = pMe->pMvdCost;  uint8_t* const kpEncMb    = pMe->pEncMb;  int16_t iMvc0, iMvc1;  int32_t iSadCost;  int32_t iBestSadCost;  uint8_t* pRefMb;  uint8_t* pFref2;  uint32_t i;  const uint32_t kuiMvcNum    = pSlice->uiMvcNum;  const SMVUnitXY* kpMvcList  = &pSlice->sMvc[0];  const SMVUnitXY ksMvStartMin    = pSlice->sMvStartMin;  const SMVUnitXY ksMvStartMax    = pSlice->sMvStartMax;  const SMVUnitXY ksMvp    = pMe->sMvp;  SMVUnitXY sMv;   //  Step 1: Initial point prediction  // init with sMvp  sMv.iMvX  = WELS_CLIP3 ((2 + ksMvp.iMvX) >> 2, ksMvStartMin.iMvX, ksMvStartMax.iMvX);  sMv.iMvY  = WELS_CLIP3 ((2 + ksMvp.iMvY) >> 2, ksMvStartMin.iMvY, ksMvStartMax.iMvY);   pRefMb = &pMe->pRefMb[sMv.iMvY * iStrideRef + sMv.iMvX];   iBestSadCost = pSad (kpEncMb, iStrideEnc, pRefMb, iStrideRef);  iBestSadCost += COST_MVD (kpMvdCost, ((sMv.iMvX) << 2) - ksMvp.iMvX, ((sMv.iMvY) << 2) - ksMvp.iMvY);   for (i = 0; i < kuiMvcNum; i++) {    //clipping here is essential since some pOut-of-range MVC may happen here (i.e., refer to baseMV)    iMvc0 = WELS_CLIP3 ((2 + kpMvcList[i].iMvX) >> 2, ksMvStartMin.iMvX, ksMvStartMax.iMvX);    iMvc1 = WELS_CLIP3 ((2 + kpMvcList[i].iMvY) >> 2, ksMvStartMin.iMvY, ksMvStartMax.iMvY);     if (((iMvc0 - sMv.iMvX) || (iMvc1 - sMv.iMvY))) {      pFref2 = &pMe->pRefMb[iMvc1 * iStrideRef + iMvc0];       iSadCost = pSad (kpEncMb, iStrideEnc, pFref2, iStrideRef) +                 COST_MVD (kpMvdCost, (iMvc0 << 2) - ksMvp.iMvX, (iMvc1 << 2) - ksMvp.iMvY);       if (iSadCost < iBestSadCost) {        sMv.iMvX = iMvc0;        sMv.iMvY = iMvc1;        pRefMb = pFref2;        iBestSadCost = iSadCost;      }    }  }   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    MeEndIntepelSearch (pMe);    return true;  }  return false;} void CalculateSatdCost (PSampleSadSatdCostFunc pSatd, void* vpMe,                        const int32_t kiEncStride, const int32_t kiRefStride) {  SWelsME* pMe             = static_cast<SWelsME*> (vpMe);  pMe->uSadPredISatd.uiSatd = pSatd (pMe->pEncMb, kiEncStride, pMe->pRefMb, kiRefStride);  pMe->uiSatdCost = pMe->uSadPredISatd.uiSatd + COST_MVD (pMe->pMvdCost, pMe->sMv.iMvX - pMe->sMvp.iMvX,                    pMe->sMv.iMvY - pMe->sMvp.iMvY);}void NotCalculateSatdCost (PSampleSadSatdCostFunc pSatd, void* vpMe,                           const int32_t kiEncStride, const int32_t kiRefStride) {}  /////////////////////////// Diamond Search Basics/////////////////////////bool WelsMeSadCostSelect (int32_t* iSadCost, const uint16_t* kpMvdCost, int32_t* pBestCost, const int32_t kiDx,                          const int32_t kiDy, int32_t* pIx, int32_t* pIy) {  int32_t iTempSadCost[4];  int32_t iInputSadCost = *pBestCost;  iTempSadCost[0] = iSadCost[0] + COST_MVD (kpMvdCost, kiDx, kiDy - 4);  iTempSadCost[1] = iSadCost[1] + COST_MVD (kpMvdCost, kiDx, kiDy + 4);  iTempSadCost[2] = iSadCost[2] + COST_MVD (kpMvdCost, kiDx - 4, kiDy);  iTempSadCost[3] = iSadCost[3] + COST_MVD (kpMvdCost, kiDx + 4, kiDy);   if (iTempSadCost[0] < *pBestCost) {    *pBestCost = iTempSadCost[0];    *pIx = 0;    *pIy = 1;  }   if (iTempSadCost[1] < *pBestCost) {    *pBestCost = iTempSadCost[1];    *pIx = 0;    *pIy = -1;  }   if (iTempSadCost[2] < *pBestCost) {    *pBestCost = iTempSadCost[2];    *pIx = 1;    *pIy = 0;  }   if (iTempSadCost[3] < *pBestCost) {    *pBestCost = iTempSadCost[3];    *pIx = -1;    *pIy = 0;  }  return (*pBestCost == iInputSadCost);} void WelsDiamondSearch (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice,                        const int32_t kiStrideEnc,  const int32_t kiStrideRef) {  PSample4SadCostFunc      pSad          =  pFuncList->sSampleDealingFuncs.pfSample4Sad[pMe->uiBlockSize];   uint8_t* pFref = pMe->pRefMb;  uint8_t* const kpEncMb = pMe->pEncMb;  const uint16_t* kpMvdCost = pMe->pMvdCost;   const SMVUnitXY ksMvStartMin    = pSlice->sMvStartMin;  const SMVUnitXY ksMvStartMax    = pSlice->sMvStartMax;   int32_t iMvDx = ((pMe->sMv.iMvX) << 2) - pMe->sMvp.iMvX;  int32_t iMvDy = ((pMe->sMv.iMvY) << 2) - pMe->sMvp.iMvY;   uint8_t* pRefMb = pFref;  int32_t iBestCost = (pMe->uiSadCost);   int32_t iTimeThreshold = ITERATIVE_TIMES;  ENFORCE_STACK_ALIGN_1D (int32_t, iSadCosts, 4, 16)   while (iTimeThreshold--) {    pMe->sMv.iMvX = (iMvDx + pMe->sMvp.iMvX) >> 2;    pMe->sMv.iMvY = (iMvDy + pMe->sMvp.iMvY) >> 2;    if (!CheckMvInRange (pMe->sMv, ksMvStartMin, ksMvStartMax))      continue;    pSad (kpEncMb, kiStrideEnc, pRefMb, kiStrideRef, &iSadCosts[0]);     int32_t iX, iY;     const bool kbIsBestCostWorse = WelsMeSadCostSelect (iSadCosts, kpMvdCost, &iBestCost, iMvDx, iMvDy, &iX, &iY);    if (kbIsBestCostWorse)      break;     iMvDx -= iX << 2 ;    iMvDy -= iY << 2 ;     pRefMb -= (iX + iY * kiStrideRef);   }   /* integer-pel mv */  pMe->sMv.iMvX = (iMvDx + pMe->sMvp.iMvX) >> 2;  pMe->sMv.iMvY = (iMvDy + pMe->sMvp.iMvY) >> 2;  pMe->uiSatdCost = pMe->uiSadCost = (iBestCost);  pMe->pRefMb = pRefMb;} /////////////////////////// DirectionalMv Basics/////////////////////////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->uiBlockSize) //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;} /////////////////////////// Cross Search Basics/////////////////////////#if defined (X86_ASM)void CalcMvdCostx8_c (uint16_t* pMvdCost, const int32_t kiStartMv, uint16_t* pMvdTable, const uint16_t kiFixedCost) {  uint16_t* pBaseCost  = pMvdCost;  const int32_t kiOffset = (kiStartMv << 2);  uint16_t* pMvd  = pMvdTable + kiOffset;  for (int32_t i = 0; i < 8; ++ i) {    pBaseCost[i] = ((*pMvd) + kiFixedCost);    pMvd += 4;  }}void VerticalFullSearchUsingSSE41 (SWelsFuncPtrList* pFuncList, SWelsME* pMe,                                   uint16_t* pMvdTable,                                   const int32_t kiEncStride, const int32_t kiRefStride,                                   const int16_t kiMinMv, const int16_t kiMaxMv,                                   const bool bVerticalSearch) {  uint8_t*  kpEncMb = pMe->pEncMb;  const int32_t kiCurMeBlockPix = pMe->iCurMeBlockPixY;  uint8_t* pRef         = &pMe->pColoRefMb[kiMinMv * kiRefStride];   const int32_t kiCurMeBlockPixY = pMe->iCurMeBlockPixY;   int32_t iMinPos = kiCurMeBlockPixY + kiMinMv;  int32_t iMaxPos = kiCurMeBlockPixY + kiMaxMv;  int32_t iFixedMvd = * (pMvdTable - pMe->sMvp.iMvX);  uint16_t* pMvdCost  = & (pMvdTable[ (kiMinMv << 2) - pMe->sMvp.iMvY]);  int16_t iStartMv = 0;    const int32_t kIsBlock16x16 = pMe->uiBlockSize == BLOCK_16x16;  const int32_t kiEdgeBlocks = kIsBlock16x16 ? 16 : 8;  PSampleSadHor8Func pSampleSadHor8 = pFuncList->pfSampleSadHor8[kIsBlock16x16];  PSampleSadSatdCostFunc pSad = pFuncList->sSampleDealingFuncs.pfSampleSad[pMe->uiBlockSize];  PTransposeMatrixBlockFunc TransposeMatrixBlock = kIsBlock16x16 ? TransposeMatrixBlock16x16_sse2 :      TransposeMatrixBlock8x8_mmx;  PTransposeMatrixBlocksFunc TransposeMatrixBlocks = kIsBlock16x16 ? TransposeMatrixBlocksx16_sse2 :      TransposeMatrixBlocksx8_mmx;   const int32_t kiDiff   = iMaxPos - iMinPos;  const int32_t kiRowNum  = WELS_ALIGN ((kiDiff - kiEdgeBlocks + 1), kiEdgeBlocks);  const int32_t kiBlocksNum  = kIsBlock16x16 ? (kiRowNum >> 4) : (kiRowNum >> 3);  int32_t iCountLoop8  = (kiRowNum - kiEdgeBlocks) >> 3;  const int32_t kiRemainingVectors  = kiDiff - (iCountLoop8 << 3);  const int32_t kiMatrixStride  = MAX_VERTICAL_MV_RANGE;  ENFORCE_STACK_ALIGN_2D (uint8_t, uiMatrixRef, 16, kiMatrixStride, 16);  // transpose matrix result for ref  ENFORCE_STACK_ALIGN_2D (uint8_t, uiMatrixEnc, 16, 16, 16);     // transpose matrix result for enc  assert (kiRowNum <= kiMatrixStride); // make sure effective memory   TransposeMatrixBlock (&uiMatrixEnc[0][0], 16, kpEncMb, kiEncStride);  TransposeMatrixBlocks (&uiMatrixRef[0][0], kiMatrixStride, pRef, kiRefStride, kiBlocksNum);  ENFORCE_STACK_ALIGN_1D (uint16_t, uiBaseCost, 8, 16);  int32_t iTargetPos   = iMinPos;  int16_t iBestPos    = pMe->sMv.iMvX;  uint32_t uiBestCost   = pMe->uiSadCost;  uint32_t uiCostMin;  int32_t iIndexMinPos;  kpEncMb = &uiMatrixEnc[0][0];  pRef = &uiMatrixRef[0][0];   while (iCountLoop8 > 0) {    CalcMvdCostx8_c (uiBaseCost, iStartMv, pMvdCost, iFixedMvd);    uiCostMin = pSampleSadHor8 (kpEncMb, 16, pRef, kiMatrixStride, uiBaseCost, &iIndexMinPos);    if (uiCostMin < uiBestCost) {      uiBestCost = uiCostMin;      iBestPos  = iTargetPos + iIndexMinPos;    }    iTargetPos += 8;    pRef += 8;    iStartMv += 8;    -- iCountLoop8;  }  if (kiRemainingVectors > 0) {    kpEncMb = pMe->pEncMb;    pRef = &pMe->pColoRefMb[ (iTargetPos - kiCurMeBlockPix) * kiRefStride];    while (iTargetPos < iMaxPos) {      const uint16_t uiMvdCost = pMvdCost[iStartMv << 2];      uint32_t uiSadCost = pSad (kpEncMb, kiEncStride, pRef, kiRefStride) + (iFixedMvd + uiMvdCost);      if (uiSadCost < uiBestCost) {        uiBestCost = uiSadCost;        iBestPos = iTargetPos;      }      iStartMv++;      pRef += kiRefStride;      ++iTargetPos;    }  }  if (uiBestCost < pMe->uiSadCost) {    SMVUnitXY sBestMv;

Lines 1–500 of 1095.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t