• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*!
2  * \copy
3  *     Copyright (c)  2013, Cisco Systems
4  *     All rights reserved.
5  *
6  *     Redistribution and use in source and binary forms, with or without
7  *     modification, are permitted provided that the following conditions
8  *     are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *
13  *        * Redistributions in binary form must reproduce the above copyright
14  *          notice, this list of conditions and the following disclaimer in
15  *          the documentation and/or other materials provided with the
16  *          distribution.
17  *
18  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26  *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28  *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  *     POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 #include "ComplexityAnalysis.h"
34 #include "cpu.h"
35 #include "macros.h"
36 #include "intra_pred_common.h"
37 #include "sad_common.h"
38 
39 WELSVP_NAMESPACE_BEGIN
40 
41 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
42 
CComplexityAnalysis(int32_t iCpuFlag)43 CComplexityAnalysis::CComplexityAnalysis (int32_t iCpuFlag) {
44   m_eMethod   = METHOD_COMPLEXITY_ANALYSIS;
45   m_pfGomSad   = NULL;
46   WelsMemset (&m_sComplexityAnalysisParam, 0, sizeof (m_sComplexityAnalysisParam));
47 }
48 
~CComplexityAnalysis()49 CComplexityAnalysis::~CComplexityAnalysis() {
50 }
51 
Process(int32_t iType,SPixMap * pSrcPixMap,SPixMap * pRefPixMap)52 EResult CComplexityAnalysis::Process (int32_t iType, SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {
53   EResult eReturn = RET_SUCCESS;
54 
55   switch (m_sComplexityAnalysisParam.iComplexityAnalysisMode) {
56   case FRAME_SAD:
57     AnalyzeFrameComplexityViaSad (pSrcPixMap, pRefPixMap);
58     break;
59   case GOM_SAD:
60     AnalyzeGomComplexityViaSad (pSrcPixMap, pRefPixMap);
61     break;
62   case GOM_VAR:
63     AnalyzeGomComplexityViaVar (pSrcPixMap, pRefPixMap);
64     break;
65   default:
66     eReturn = RET_INVALIDPARAM;
67     break;
68   }
69 
70   return eReturn;
71 }
72 
73 
Set(int32_t iType,void * pParam)74 EResult CComplexityAnalysis::Set (int32_t iType, void* pParam) {
75   if (pParam == NULL) {
76     return RET_INVALIDPARAM;
77   }
78 
79   m_sComplexityAnalysisParam = * (SComplexityAnalysisParam*)pParam;
80 
81   return RET_SUCCESS;
82 }
83 
Get(int32_t iType,void * pParam)84 EResult CComplexityAnalysis::Get (int32_t iType, void* pParam) {
85   if (pParam == NULL) {
86     return RET_INVALIDPARAM;
87   }
88 
89   SComplexityAnalysisParam* sComplexityAnalysisParam = (SComplexityAnalysisParam*)pParam;
90 
91   sComplexityAnalysisParam->iFrameComplexity = m_sComplexityAnalysisParam.iFrameComplexity;
92 
93   return RET_SUCCESS;
94 }
95 
96 
97 ///////////////////////////////////////////////////////////////////////////////////////////////
AnalyzeFrameComplexityViaSad(SPixMap * pSrcPixMap,SPixMap * pRefPixMap)98 void CComplexityAnalysis::AnalyzeFrameComplexityViaSad (SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {
99   SVAACalcResult*     pVaaCalcResults = NULL;
100   pVaaCalcResults = m_sComplexityAnalysisParam.pCalcResult;
101 
102   m_sComplexityAnalysisParam.iFrameComplexity = pVaaCalcResults->iFrameSad;
103 
104   if (m_sComplexityAnalysisParam.iCalcBgd) { //BGD control
105     m_sComplexityAnalysisParam.iFrameComplexity = GetFrameSadExcludeBackground (pSrcPixMap, pRefPixMap);
106   }
107 }
108 
GetFrameSadExcludeBackground(SPixMap * pSrcPixMap,SPixMap * pRefPixMap)109 int32_t CComplexityAnalysis::GetFrameSadExcludeBackground (SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {
110   int32_t iWidth     = pSrcPixMap->sRect.iRectWidth;
111   int32_t iHeight    = pSrcPixMap->sRect.iRectHeight;
112   int32_t iMbWidth  = iWidth  >> 4;
113   int32_t iMbHeight = iHeight >> 4;
114   int32_t iMbNum    = iMbWidth * iMbHeight;
115 
116   int32_t iMbNumInGom = m_sComplexityAnalysisParam.iMbNumInGom;
117   int32_t iGomMbNum = (iMbNum + iMbNumInGom - 1) / iMbNumInGom;
118   int32_t iGomMbStartIndex = 0, iGomMbEndIndex = 0;
119 
120   uint8_t* pBackgroundMbFlag = (uint8_t*)m_sComplexityAnalysisParam.pBackgroundMbFlag;
121   uint32_t* uiRefMbType = (uint32_t*)m_sComplexityAnalysisParam.uiRefMbType;
122   SVAACalcResult* pVaaCalcResults = m_sComplexityAnalysisParam.pCalcResult;
123   int32_t*  pGomForegroundBlockNum = m_sComplexityAnalysisParam.pGomForegroundBlockNum;
124 
125   uint32_t uiFrameSad = 0;
126   for (int32_t j = 0; j < iGomMbNum; j ++) {
127     iGomMbStartIndex = j * iMbNumInGom;
128     iGomMbEndIndex = WELS_MIN ((j + 1) * iMbNumInGom, iMbNum);
129 
130     for (int32_t i = iGomMbStartIndex; i < iGomMbEndIndex; i ++) {
131       if (pBackgroundMbFlag[i] == 0 || IS_INTRA (uiRefMbType[i])) {
132         pGomForegroundBlockNum[j]++;
133         uiFrameSad += pVaaCalcResults->pSad8x8[i][0];
134         uiFrameSad += pVaaCalcResults->pSad8x8[i][1];
135         uiFrameSad += pVaaCalcResults->pSad8x8[i][2];
136         uiFrameSad += pVaaCalcResults->pSad8x8[i][3];
137       }
138     }
139   }
140 
141   return (uiFrameSad);
142 }
143 
144 
InitGomSadFunc(PGOMSadFunc & pfGomSad,uint8_t iCalcBgd)145 void InitGomSadFunc (PGOMSadFunc& pfGomSad, uint8_t iCalcBgd) {
146   pfGomSad = GomSampleSad;
147 
148   if (iCalcBgd) {
149     pfGomSad = GomSampleSadExceptBackground;
150   }
151 }
152 
GomSampleSad(uint32_t * pGomSad,int32_t * pGomForegroundBlockNum,int32_t * pSad8x8,uint8_t pBackgroundMbFlag)153 void GomSampleSad (uint32_t* pGomSad, int32_t* pGomForegroundBlockNum, int32_t* pSad8x8, uint8_t pBackgroundMbFlag) {
154   (*pGomForegroundBlockNum) ++;
155   *pGomSad += pSad8x8[0];
156   *pGomSad += pSad8x8[1];
157   *pGomSad += pSad8x8[2];
158   *pGomSad += pSad8x8[3];
159 }
160 
GomSampleSadExceptBackground(uint32_t * pGomSad,int32_t * pGomForegroundBlockNum,int32_t * pSad8x8,uint8_t pBackgroundMbFlag)161 void GomSampleSadExceptBackground (uint32_t* pGomSad, int32_t* pGomForegroundBlockNum, int32_t* pSad8x8,
162                                    uint8_t pBackgroundMbFlag) {
163   if (pBackgroundMbFlag == 0) {
164     (*pGomForegroundBlockNum) ++;
165     *pGomSad += pSad8x8[0];
166     *pGomSad += pSad8x8[1];
167     *pGomSad += pSad8x8[2];
168     *pGomSad += pSad8x8[3];
169   }
170 }
171 
AnalyzeGomComplexityViaSad(SPixMap * pSrcPixMap,SPixMap * pRefPixMap)172 void CComplexityAnalysis::AnalyzeGomComplexityViaSad (SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {
173   int32_t iWidth     = pSrcPixMap->sRect.iRectWidth;
174   int32_t iHeight    = pSrcPixMap->sRect.iRectHeight;
175   int32_t iMbWidth  = iWidth  >> 4;
176   int32_t iMbHeight = iHeight >> 4;
177   int32_t iMbNum    = iMbWidth * iMbHeight;
178 
179   int32_t iMbNumInGom = m_sComplexityAnalysisParam.iMbNumInGom;
180   int32_t iGomMbNum = (iMbNum + iMbNumInGom - 1) / iMbNumInGom;
181 
182   int32_t iGomMbStartIndex = 0, iGomMbEndIndex = 0, iGomMbRowNum = 0;
183   int32_t iMbStartIndex = 0, iMbEndIndex = 0;
184 
185   uint8_t* pBackgroundMbFlag = (uint8_t*)m_sComplexityAnalysisParam.pBackgroundMbFlag;
186   uint32_t* uiRefMbType = (uint32_t*)m_sComplexityAnalysisParam.uiRefMbType;
187   SVAACalcResult* pVaaCalcResults = m_sComplexityAnalysisParam.pCalcResult;
188   int32_t*  pGomForegroundBlockNum = (int32_t*)m_sComplexityAnalysisParam.pGomForegroundBlockNum;
189   int32_t*  pGomComplexity = (int32_t*)m_sComplexityAnalysisParam.pGomComplexity;
190 
191   uint32_t uiGomSad = 0, uiFrameSad = 0;
192   InitGomSadFunc (m_pfGomSad, m_sComplexityAnalysisParam.iCalcBgd);
193 
194   for (int32_t j = 0; j < iGomMbNum; j ++) {
195     uiGomSad = 0;
196 
197     iGomMbStartIndex = j * iMbNumInGom;
198     iGomMbEndIndex = WELS_MIN ((j + 1) * iMbNumInGom, iMbNum);
199     iGomMbRowNum = (iGomMbEndIndex + iMbWidth - 1) / iMbWidth  - iGomMbStartIndex / iMbWidth;
200 
201     iMbStartIndex = iGomMbStartIndex;
202     iMbEndIndex = WELS_MIN ((iMbStartIndex / iMbWidth + 1) * iMbWidth, iGomMbEndIndex);
203 
204     do {
205       for (int32_t i = iMbStartIndex; i < iMbEndIndex; i ++) {
206         m_pfGomSad (&uiGomSad, pGomForegroundBlockNum + j, pVaaCalcResults->pSad8x8[i], pBackgroundMbFlag[i]
207                     && !IS_INTRA (uiRefMbType[i]));
208       }
209 
210       iMbStartIndex = iMbEndIndex;
211       iMbEndIndex = WELS_MIN (iMbEndIndex + iMbWidth , iGomMbEndIndex);
212 
213     } while (--iGomMbRowNum);
214     pGomComplexity[j] = uiGomSad;
215     uiFrameSad += pGomComplexity[j];
216   }
217   m_sComplexityAnalysisParam.iFrameComplexity = uiFrameSad;
218 }
219 
220 
AnalyzeGomComplexityViaVar(SPixMap * pSrcPixMap,SPixMap * pRefPixMap)221 void CComplexityAnalysis::AnalyzeGomComplexityViaVar (SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {
222   int32_t iWidth     = pSrcPixMap->sRect.iRectWidth;
223   int32_t iHeight    = pSrcPixMap->sRect.iRectHeight;
224   int32_t iMbWidth  = iWidth  >> 4;
225   int32_t iMbHeight = iHeight >> 4;
226   int32_t iMbNum    = iMbWidth * iMbHeight;
227 
228   int32_t iMbNumInGom = m_sComplexityAnalysisParam.iMbNumInGom;
229   int32_t iGomMbNum = (iMbNum + iMbNumInGom - 1) / iMbNumInGom;
230   int32_t iGomSampleNum = 0;
231 
232   int32_t iGomMbStartIndex = 0, iGomMbEndIndex = 0, iGomMbRowNum = 0;
233   int32_t iMbStartIndex = 0, iMbEndIndex = 0;
234 
235   SVAACalcResult* pVaaCalcResults = m_sComplexityAnalysisParam.pCalcResult;
236   int32_t*  pGomComplexity = (int32_t*)m_sComplexityAnalysisParam.pGomComplexity;
237   uint32_t  uiFrameSad = 0;
238 
239   uint32_t uiSampleSum = 0, uiSquareSum = 0;
240 
241   for (int32_t j = 0; j < iGomMbNum; j ++) {
242     uiSampleSum = 0;
243     uiSquareSum = 0;
244 
245     iGomMbStartIndex = j * iMbNumInGom;
246     iGomMbEndIndex = WELS_MIN ((j + 1) * iMbNumInGom, iMbNum);
247     iGomMbRowNum = (iGomMbEndIndex + iMbWidth - 1) / iMbWidth  - iGomMbStartIndex / iMbWidth;
248 
249     iMbStartIndex = iGomMbStartIndex;
250     iMbEndIndex = WELS_MIN ((iMbStartIndex / iMbWidth + 1) * iMbWidth, iGomMbEndIndex);
251 
252     iGomSampleNum = (iMbEndIndex - iMbStartIndex) * MB_WIDTH_LUMA * MB_WIDTH_LUMA;
253 
254     do {
255       for (int32_t i = iMbStartIndex; i < iMbEndIndex; i ++) {
256         uiSampleSum += pVaaCalcResults->pSum16x16[i];
257         uiSquareSum += pVaaCalcResults->pSumOfSquare16x16[i];
258       }
259 
260       iMbStartIndex = iMbEndIndex;
261       iMbEndIndex = WELS_MIN (iMbEndIndex + iMbWidth, iGomMbEndIndex);
262 
263     } while (--iGomMbRowNum);
264 
265     pGomComplexity[j] = uiSquareSum - (uiSampleSum * uiSampleSum / iGomSampleNum);
266     uiFrameSad += pGomComplexity[j];
267   }
268   m_sComplexityAnalysisParam.iFrameComplexity = uiFrameSad;
269 }
270 
271 
CComplexityAnalysisScreen(int32_t iCpuFlag)272 CComplexityAnalysisScreen::CComplexityAnalysisScreen (int32_t iCpuFlag) {
273   m_eMethod   = METHOD_COMPLEXITY_ANALYSIS_SCREEN;
274   WelsMemset (&m_ComplexityAnalysisParam, 0, sizeof (m_ComplexityAnalysisParam));
275 
276   m_pSadFunc = WelsSampleSad16x16_c;
277   m_pIntraFunc[0] = WelsI16x16LumaPredV_c;
278   m_pIntraFunc[1] = WelsI16x16LumaPredH_c;
279 #ifdef X86_ASM
280   if (iCpuFlag & WELS_CPU_SSE2) {
281     m_pSadFunc = WelsSampleSad16x16_sse2;
282     m_pIntraFunc[0] = WelsI16x16LumaPredV_sse2;
283     m_pIntraFunc[1] = WelsI16x16LumaPredH_sse2;
284 
285   }
286 #endif
287 
288 #if defined (HAVE_NEON)
289   if (iCpuFlag & WELS_CPU_NEON) {
290     m_pSadFunc = WelsSampleSad16x16_neon;
291     m_pIntraFunc[0] = WelsI16x16LumaPredV_neon;
292     m_pIntraFunc[1] = WelsI16x16LumaPredH_neon;
293 
294   }
295 #endif
296 
297 #if defined (HAVE_NEON_AARCH64)
298   if (iCpuFlag & WELS_CPU_NEON) {
299     m_pSadFunc = WelsSampleSad16x16_AArch64_neon;
300     m_pIntraFunc[0] =  WelsI16x16LumaPredV_AArch64_neon;
301     m_pIntraFunc[1] = WelsI16x16LumaPredH_AArch64_neon;
302   }
303 #endif
304 
305 #if defined (HAVE_LASX)
306   if (iCpuFlag & WELS_CPU_LASX) {
307     m_pSadFunc = WelsSampleSad16x16_lasx;
308   }
309 #endif
310 
311 }
312 
~CComplexityAnalysisScreen()313 CComplexityAnalysisScreen::~CComplexityAnalysisScreen() {
314 }
315 
Process(int32_t nType,SPixMap * pSrc,SPixMap * pRef)316 EResult CComplexityAnalysisScreen::Process (int32_t nType, SPixMap* pSrc, SPixMap* pRef) {
317   bool bScrollFlag = m_ComplexityAnalysisParam.sScrollResult.bScrollDetectFlag;
318   int32_t iIdrFlag    = m_ComplexityAnalysisParam.iIdrFlag;
319   int32_t iScrollMvX = m_ComplexityAnalysisParam.sScrollResult.iScrollMvX;
320   int32_t iScrollMvY = m_ComplexityAnalysisParam.sScrollResult.iScrollMvY;
321 
322   if (m_ComplexityAnalysisParam.iMbRowInGom <= 0)
323     return RET_INVALIDPARAM;
324   if (!iIdrFlag && pRef == NULL)
325     return RET_INVALIDPARAM;
326 
327   if (iIdrFlag || pRef == NULL) {
328     GomComplexityAnalysisIntra (pSrc);
329   } else if (!bScrollFlag || ((iScrollMvX == 0) && (iScrollMvY == 0))) {
330     GomComplexityAnalysisInter (pSrc, pRef, 0);
331   } else {
332     GomComplexityAnalysisInter (pSrc, pRef, 1);
333   }
334 
335   return RET_SUCCESS;
336 }
337 
338 
Set(int32_t nType,void * pParam)339 EResult CComplexityAnalysisScreen::Set (int32_t nType, void* pParam) {
340   if (pParam == NULL)
341     return RET_INVALIDPARAM;
342 
343   m_ComplexityAnalysisParam = * (SComplexityAnalysisScreenParam*)pParam;
344 
345   return RET_SUCCESS;
346 }
347 
Get(int32_t nType,void * pParam)348 EResult CComplexityAnalysisScreen::Get (int32_t nType, void* pParam) {
349   if (pParam == NULL)
350     return RET_INVALIDPARAM;
351 
352   * (SComplexityAnalysisScreenParam*)pParam = m_ComplexityAnalysisParam;
353 
354   return RET_SUCCESS;
355 }
356 
GomComplexityAnalysisIntra(SPixMap * pSrc)357 void CComplexityAnalysisScreen::GomComplexityAnalysisIntra (SPixMap* pSrc) {
358   int32_t iWidth                  = pSrc->sRect.iRectWidth;
359   int32_t iHeight                 = pSrc->sRect.iRectHeight;
360   int32_t iBlockWidth             = iWidth  >> 4;
361   int32_t iBlockHeight            = iHeight >> 4;
362 
363   int32_t iBlockSadH, iBlockSadV, iGomSad = 0;
364   int32_t iIdx = 0;
365 
366   uint8_t* pPtrY = NULL;
367   int32_t iStrideY = 0;
368   int32_t iRowStrideY = 0;
369 
370   uint8_t* pTmpCur = NULL;
371 
372   ENFORCE_STACK_ALIGN_1D (uint8_t, iMemPredMb, 256, 16)
373 
374   pPtrY = (uint8_t*)pSrc->pPixel[0];
375 
376   iStrideY  = pSrc->iStride[0];
377   iRowStrideY = iStrideY << 4;
378 
379   m_ComplexityAnalysisParam.iFrameComplexity = 0;
380 
381   for (int32_t j = 0; j < iBlockHeight; j ++) {
382     pTmpCur = pPtrY;
383 
384     for (int32_t i = 0; i < iBlockWidth; i++) {
385       iBlockSadH = iBlockSadV = 0x7fffffff; // INT_MAX
386       if (j > 0) {
387         m_pIntraFunc[0] (iMemPredMb, pTmpCur, iStrideY);
388         iBlockSadH = m_pSadFunc (pTmpCur, iStrideY, iMemPredMb, 16);
389       }
390       if (i > 0) {
391         m_pIntraFunc[1] (iMemPredMb, pTmpCur, iStrideY);
392         iBlockSadV = m_pSadFunc (pTmpCur, iStrideY, iMemPredMb, 16);
393       }
394       if (i || j)
395         iGomSad += WELS_MIN (iBlockSadH, iBlockSadV);
396 
397       pTmpCur += 16;
398 
399       if (i == iBlockWidth - 1 && ((j + 1) % m_ComplexityAnalysisParam.iMbRowInGom == 0 || j == iBlockHeight - 1)) {
400         m_ComplexityAnalysisParam.pGomComplexity[iIdx] = iGomSad;
401         m_ComplexityAnalysisParam.iFrameComplexity += iGomSad;
402         iIdx++;
403         iGomSad = 0;
404       }
405     }
406 
407     pPtrY += iRowStrideY;
408   }
409   m_ComplexityAnalysisParam.iGomNumInFrame = iIdx;
410 }
411 
412 
GomComplexityAnalysisInter(SPixMap * pSrc,SPixMap * pRef,bool bScrollFlag)413 void CComplexityAnalysisScreen::GomComplexityAnalysisInter (SPixMap* pSrc, SPixMap* pRef, bool bScrollFlag) {
414   int32_t iWidth                  = pSrc->sRect.iRectWidth;
415   int32_t iHeight                 = pSrc->sRect.iRectHeight;
416   int32_t iBlockWidth             = iWidth  >> 4;
417   int32_t iBlockHeight            = iHeight >> 4;
418 
419   int32_t iInterSad, iScrollSad, iBlockSadH, iBlockSadV, iGomSad = 0;
420   int32_t iIdx = 0;
421 
422   int32_t iScrollMvX = m_ComplexityAnalysisParam.sScrollResult.iScrollMvX;
423   int32_t iScrollMvY = m_ComplexityAnalysisParam.sScrollResult.iScrollMvY;
424 
425   uint8_t* pPtrX = NULL, *pPtrY = NULL;
426   int32_t iStrideX = 0, iStrideY = 0;
427   int32_t iRowStrideX = 0, iRowStrideY = 0;
428 
429   uint8_t* pTmpRef = NULL, *pTmpCur = NULL, *pTmpRefScroll = NULL;
430 
431   ENFORCE_STACK_ALIGN_1D (uint8_t, iMemPredMb, 256, 16)
432 
433   pPtrX = (uint8_t*)pRef->pPixel[0];
434   pPtrY = (uint8_t*)pSrc->pPixel[0];
435 
436   iStrideX  = pRef->iStride[0];
437   iStrideY  = pSrc->iStride[0];
438 
439   iRowStrideX  = pRef->iStride[0] << 4;
440   iRowStrideY  = pSrc->iStride[0] << 4;
441 
442   m_ComplexityAnalysisParam.iFrameComplexity = 0;
443 
444   for (int32_t j = 0; j < iBlockHeight; j ++) {
445     pTmpRef  = pPtrX;
446     pTmpCur  = pPtrY;
447 
448     for (int32_t i = 0; i < iBlockWidth; i++) {
449       int32_t iBlockPointX = i << 4;
450       int32_t iBlockPointY = j << 4;
451 
452       iInterSad = m_pSadFunc (pTmpCur, iStrideY, pTmpRef, iStrideX);
453       if (bScrollFlag) {
454         if ((iInterSad != 0) &&
455             (iBlockPointX + iScrollMvX >= 0) && (iBlockPointX + iScrollMvX <= iWidth - 8) &&
456             (iBlockPointY + iScrollMvY >= 0) && (iBlockPointY + iScrollMvY <= iHeight - 8)) {
457           pTmpRefScroll = pTmpRef - iScrollMvY * iStrideX + iScrollMvX;
458           iScrollSad = m_pSadFunc (pTmpCur, iStrideY, pTmpRefScroll, iStrideX);
459 
460           if (iScrollSad < iInterSad) {
461             iInterSad = iScrollSad;
462           }
463         }
464 
465       }
466 
467       iBlockSadH = iBlockSadV = 0x7fffffff; // INT_MAX
468 
469       if (j > 0) {
470         m_pIntraFunc[0] (iMemPredMb, pTmpCur, iStrideY);
471         iBlockSadH = m_pSadFunc (pTmpCur, iStrideY, iMemPredMb, 16);
472       }
473       if (i > 0) {
474         m_pIntraFunc[1] (iMemPredMb, pTmpCur, iStrideY);
475         iBlockSadV = m_pSadFunc (pTmpCur, iStrideY, iMemPredMb, 16);
476       }
477 
478       iGomSad += WELS_MIN (WELS_MIN (iBlockSadH, iBlockSadV), iInterSad);
479 
480       if (i == iBlockWidth - 1 && ((j + 1) % m_ComplexityAnalysisParam.iMbRowInGom == 0 || j == iBlockHeight - 1)) {
481         m_ComplexityAnalysisParam.pGomComplexity[iIdx] = iGomSad;
482         m_ComplexityAnalysisParam.iFrameComplexity += iGomSad;
483         iIdx++;
484         iGomSad = 0;
485       }
486 
487       pTmpRef += 16;
488       pTmpCur += 16;
489     }
490     pPtrX += iRowStrideX;
491     pPtrY += iRowStrideY;
492   }
493   m_ComplexityAnalysisParam.iGomNumInFrame = iIdx;
494 }
495 
496 WELSVP_NAMESPACE_END
497