Coverage Report

Created: 2025-07-23 08:18

/src/openh264/codec/processing/src/complexityanalysis/ComplexityAnalysis.cpp
Line
Count
Source (jump to first uncovered line)
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
43
0
CComplexityAnalysis::CComplexityAnalysis (int32_t iCpuFlag) {
44
0
  m_eMethod   = METHOD_COMPLEXITY_ANALYSIS;
45
0
  m_pfGomSad   = NULL;
46
0
  WelsMemset (&m_sComplexityAnalysisParam, 0, sizeof (m_sComplexityAnalysisParam));
47
0
}
48
49
0
CComplexityAnalysis::~CComplexityAnalysis() {
50
0
}
51
52
0
EResult CComplexityAnalysis::Process (int32_t iType, SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {
53
0
  EResult eReturn = RET_SUCCESS;
54
55
0
  switch (m_sComplexityAnalysisParam.iComplexityAnalysisMode) {
56
0
  case FRAME_SAD:
57
0
    AnalyzeFrameComplexityViaSad (pSrcPixMap, pRefPixMap);
58
0
    break;
59
0
  case GOM_SAD:
60
0
    AnalyzeGomComplexityViaSad (pSrcPixMap, pRefPixMap);
61
0
    break;
62
0
  case GOM_VAR:
63
0
    AnalyzeGomComplexityViaVar (pSrcPixMap, pRefPixMap);
64
0
    break;
65
0
  default:
66
0
    eReturn = RET_INVALIDPARAM;
67
0
    break;
68
0
  }
69
70
0
  return eReturn;
71
0
}
72
73
74
0
EResult CComplexityAnalysis::Set (int32_t iType, void* pParam) {
75
0
  if (pParam == NULL) {
76
0
    return RET_INVALIDPARAM;
77
0
  }
78
79
0
  m_sComplexityAnalysisParam = * (SComplexityAnalysisParam*)pParam;
80
81
0
  return RET_SUCCESS;
82
0
}
83
84
0
EResult CComplexityAnalysis::Get (int32_t iType, void* pParam) {
85
0
  if (pParam == NULL) {
86
0
    return RET_INVALIDPARAM;
87
0
  }
88
89
0
  SComplexityAnalysisParam* sComplexityAnalysisParam = (SComplexityAnalysisParam*)pParam;
90
91
0
  sComplexityAnalysisParam->iFrameComplexity = m_sComplexityAnalysisParam.iFrameComplexity;
92
93
0
  return RET_SUCCESS;
94
0
}
95
96
97
///////////////////////////////////////////////////////////////////////////////////////////////
98
0
void CComplexityAnalysis::AnalyzeFrameComplexityViaSad (SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {
99
0
  SVAACalcResult*     pVaaCalcResults = NULL;
100
0
  pVaaCalcResults = m_sComplexityAnalysisParam.pCalcResult;
101
102
0
  m_sComplexityAnalysisParam.iFrameComplexity = pVaaCalcResults->iFrameSad;
103
104
0
  if (m_sComplexityAnalysisParam.iCalcBgd) { //BGD control
105
0
    m_sComplexityAnalysisParam.iFrameComplexity = GetFrameSadExcludeBackground (pSrcPixMap, pRefPixMap);
106
0
  }
107
0
}
108
109
0
int32_t CComplexityAnalysis::GetFrameSadExcludeBackground (SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {
110
0
  int32_t iWidth     = pSrcPixMap->sRect.iRectWidth;
111
0
  int32_t iHeight    = pSrcPixMap->sRect.iRectHeight;
112
0
  int32_t iMbWidth  = iWidth  >> 4;
113
0
  int32_t iMbHeight = iHeight >> 4;
114
0
  int32_t iMbNum    = iMbWidth * iMbHeight;
115
116
0
  int32_t iMbNumInGom = m_sComplexityAnalysisParam.iMbNumInGom;
117
0
  int32_t iGomMbNum = (iMbNum + iMbNumInGom - 1) / iMbNumInGom;
118
0
  int32_t iGomMbStartIndex = 0, iGomMbEndIndex = 0;
119
120
0
  uint8_t* pBackgroundMbFlag = (uint8_t*)m_sComplexityAnalysisParam.pBackgroundMbFlag;
121
0
  uint32_t* uiRefMbType = (uint32_t*)m_sComplexityAnalysisParam.uiRefMbType;
122
0
  SVAACalcResult* pVaaCalcResults = m_sComplexityAnalysisParam.pCalcResult;
123
0
  int32_t*  pGomForegroundBlockNum = m_sComplexityAnalysisParam.pGomForegroundBlockNum;
124
125
0
  uint32_t uiFrameSad = 0;
126
0
  for (int32_t j = 0; j < iGomMbNum; j ++) {
127
0
    iGomMbStartIndex = j * iMbNumInGom;
128
0
    iGomMbEndIndex = WELS_MIN ((j + 1) * iMbNumInGom, iMbNum);
129
130
0
    for (int32_t i = iGomMbStartIndex; i < iGomMbEndIndex; i ++) {
131
0
      if (pBackgroundMbFlag[i] == 0 || IS_INTRA (uiRefMbType[i])) {
132
0
        pGomForegroundBlockNum[j]++;
133
0
        uiFrameSad += pVaaCalcResults->pSad8x8[i][0];
134
0
        uiFrameSad += pVaaCalcResults->pSad8x8[i][1];
135
0
        uiFrameSad += pVaaCalcResults->pSad8x8[i][2];
136
0
        uiFrameSad += pVaaCalcResults->pSad8x8[i][3];
137
0
      }
138
0
    }
139
0
  }
140
141
0
  return (uiFrameSad);
142
0
}
143
144
145
0
void InitGomSadFunc (PGOMSadFunc& pfGomSad, uint8_t iCalcBgd) {
146
0
  pfGomSad = GomSampleSad;
147
148
0
  if (iCalcBgd) {
149
0
    pfGomSad = GomSampleSadExceptBackground;
150
0
  }
151
0
}
152
153
0
void GomSampleSad (uint32_t* pGomSad, int32_t* pGomForegroundBlockNum, int32_t* pSad8x8, uint8_t pBackgroundMbFlag) {
154
0
  (*pGomForegroundBlockNum) ++;
155
0
  *pGomSad += pSad8x8[0];
156
0
  *pGomSad += pSad8x8[1];
157
0
  *pGomSad += pSad8x8[2];
158
0
  *pGomSad += pSad8x8[3];
159
0
}
160
161
void GomSampleSadExceptBackground (uint32_t* pGomSad, int32_t* pGomForegroundBlockNum, int32_t* pSad8x8,
162
0
                                   uint8_t pBackgroundMbFlag) {
163
0
  if (pBackgroundMbFlag == 0) {
164
0
    (*pGomForegroundBlockNum) ++;
165
0
    *pGomSad += pSad8x8[0];
166
0
    *pGomSad += pSad8x8[1];
167
0
    *pGomSad += pSad8x8[2];
168
0
    *pGomSad += pSad8x8[3];
169
0
  }
170
0
}
171
172
0
void CComplexityAnalysis::AnalyzeGomComplexityViaSad (SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {
173
0
  int32_t iWidth     = pSrcPixMap->sRect.iRectWidth;
174
0
  int32_t iHeight    = pSrcPixMap->sRect.iRectHeight;
175
0
  int32_t iMbWidth  = iWidth  >> 4;
176
0
  int32_t iMbHeight = iHeight >> 4;
177
0
  int32_t iMbNum    = iMbWidth * iMbHeight;
178
179
0
  int32_t iMbNumInGom = m_sComplexityAnalysisParam.iMbNumInGom;
180
0
  int32_t iGomMbNum = (iMbNum + iMbNumInGom - 1) / iMbNumInGom;
181
182
0
  int32_t iGomMbStartIndex = 0, iGomMbEndIndex = 0, iGomMbRowNum = 0;
183
0
  int32_t iMbStartIndex = 0, iMbEndIndex = 0;
184
185
0
  uint8_t* pBackgroundMbFlag = (uint8_t*)m_sComplexityAnalysisParam.pBackgroundMbFlag;
186
0
  uint32_t* uiRefMbType = (uint32_t*)m_sComplexityAnalysisParam.uiRefMbType;
187
0
  SVAACalcResult* pVaaCalcResults = m_sComplexityAnalysisParam.pCalcResult;
188
0
  int32_t*  pGomForegroundBlockNum = (int32_t*)m_sComplexityAnalysisParam.pGomForegroundBlockNum;
189
0
  int32_t*  pGomComplexity = (int32_t*)m_sComplexityAnalysisParam.pGomComplexity;
190
191
0
  uint32_t uiGomSad = 0, uiFrameSad = 0;
192
0
  InitGomSadFunc (m_pfGomSad, m_sComplexityAnalysisParam.iCalcBgd);
193
194
0
  for (int32_t j = 0; j < iGomMbNum; j ++) {
195
0
    uiGomSad = 0;
196
197
0
    iGomMbStartIndex = j * iMbNumInGom;
198
0
    iGomMbEndIndex = WELS_MIN ((j + 1) * iMbNumInGom, iMbNum);
199
0
    iGomMbRowNum = (iGomMbEndIndex + iMbWidth - 1) / iMbWidth  - iGomMbStartIndex / iMbWidth;
200
201
0
    iMbStartIndex = iGomMbStartIndex;
202
0
    iMbEndIndex = WELS_MIN ((iMbStartIndex / iMbWidth + 1) * iMbWidth, iGomMbEndIndex);
203
204
0
    do {
205
0
      for (int32_t i = iMbStartIndex; i < iMbEndIndex; i ++) {
206
0
        m_pfGomSad (&uiGomSad, pGomForegroundBlockNum + j, pVaaCalcResults->pSad8x8[i], pBackgroundMbFlag[i]
207
0
                    && !IS_INTRA (uiRefMbType[i]));
208
0
      }
209
210
0
      iMbStartIndex = iMbEndIndex;
211
0
      iMbEndIndex = WELS_MIN (iMbEndIndex + iMbWidth , iGomMbEndIndex);
212
213
0
    } while (--iGomMbRowNum);
214
0
    pGomComplexity[j] = uiGomSad;
215
0
    uiFrameSad += pGomComplexity[j];
216
0
  }
217
0
  m_sComplexityAnalysisParam.iFrameComplexity = uiFrameSad;
218
0
}
219
220
221
0
void CComplexityAnalysis::AnalyzeGomComplexityViaVar (SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {
222
0
  int32_t iWidth     = pSrcPixMap->sRect.iRectWidth;
223
0
  int32_t iHeight    = pSrcPixMap->sRect.iRectHeight;
224
0
  int32_t iMbWidth  = iWidth  >> 4;
225
0
  int32_t iMbHeight = iHeight >> 4;
226
0
  int32_t iMbNum    = iMbWidth * iMbHeight;
227
228
0
  int32_t iMbNumInGom = m_sComplexityAnalysisParam.iMbNumInGom;
229
0
  int32_t iGomMbNum = (iMbNum + iMbNumInGom - 1) / iMbNumInGom;
230
0
  int32_t iGomSampleNum = 0;
231
232
0
  int32_t iGomMbStartIndex = 0, iGomMbEndIndex = 0, iGomMbRowNum = 0;
233
0
  int32_t iMbStartIndex = 0, iMbEndIndex = 0;
234
235
0
  SVAACalcResult* pVaaCalcResults = m_sComplexityAnalysisParam.pCalcResult;
236
0
  int32_t*  pGomComplexity = (int32_t*)m_sComplexityAnalysisParam.pGomComplexity;
237
0
  uint32_t  uiFrameSad = 0;
238
239
0
  uint32_t uiSampleSum = 0, uiSquareSum = 0;
240
241
0
  for (int32_t j = 0; j < iGomMbNum; j ++) {
242
0
    uiSampleSum = 0;
243
0
    uiSquareSum = 0;
244
245
0
    iGomMbStartIndex = j * iMbNumInGom;
246
0
    iGomMbEndIndex = WELS_MIN ((j + 1) * iMbNumInGom, iMbNum);
247
0
    iGomMbRowNum = (iGomMbEndIndex + iMbWidth - 1) / iMbWidth  - iGomMbStartIndex / iMbWidth;
248
249
0
    iMbStartIndex = iGomMbStartIndex;
250
0
    iMbEndIndex = WELS_MIN ((iMbStartIndex / iMbWidth + 1) * iMbWidth, iGomMbEndIndex);
251
252
0
    iGomSampleNum = (iMbEndIndex - iMbStartIndex) * MB_WIDTH_LUMA * MB_WIDTH_LUMA;
253
254
0
    do {
255
0
      for (int32_t i = iMbStartIndex; i < iMbEndIndex; i ++) {
256
0
        uiSampleSum += pVaaCalcResults->pSum16x16[i];
257
0
        uiSquareSum += pVaaCalcResults->pSumOfSquare16x16[i];
258
0
      }
259
260
0
      iMbStartIndex = iMbEndIndex;
261
0
      iMbEndIndex = WELS_MIN (iMbEndIndex + iMbWidth, iGomMbEndIndex);
262
263
0
    } while (--iGomMbRowNum);
264
265
0
    pGomComplexity[j] = uiSquareSum - (uiSampleSum * uiSampleSum / iGomSampleNum);
266
0
    uiFrameSad += pGomComplexity[j];
267
0
  }
268
0
  m_sComplexityAnalysisParam.iFrameComplexity = uiFrameSad;
269
0
}
270
271
272
0
CComplexityAnalysisScreen::CComplexityAnalysisScreen (int32_t iCpuFlag) {
273
0
  m_eMethod   = METHOD_COMPLEXITY_ANALYSIS_SCREEN;
274
0
  WelsMemset (&m_ComplexityAnalysisParam, 0, sizeof (m_ComplexityAnalysisParam));
275
276
0
  m_pSadFunc = WelsSampleSad16x16_c;
277
0
  m_pIntraFunc[0] = WelsI16x16LumaPredV_c;
278
0
  m_pIntraFunc[1] = WelsI16x16LumaPredH_c;
279
0
#ifdef X86_ASM
280
0
  if (iCpuFlag & WELS_CPU_SSE2) {
281
0
    m_pSadFunc = WelsSampleSad16x16_sse2;
282
0
    m_pIntraFunc[0] = WelsI16x16LumaPredV_sse2;
283
0
    m_pIntraFunc[1] = WelsI16x16LumaPredH_sse2;
284
285
0
  }
286
0
#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
0
}
312
313
0
CComplexityAnalysisScreen::~CComplexityAnalysisScreen() {
314
0
}
315
316
0
EResult CComplexityAnalysisScreen::Process (int32_t nType, SPixMap* pSrc, SPixMap* pRef) {
317
0
  bool bScrollFlag = m_ComplexityAnalysisParam.sScrollResult.bScrollDetectFlag;
318
0
  int32_t iIdrFlag    = m_ComplexityAnalysisParam.iIdrFlag;
319
0
  int32_t iScrollMvX = m_ComplexityAnalysisParam.sScrollResult.iScrollMvX;
320
0
  int32_t iScrollMvY = m_ComplexityAnalysisParam.sScrollResult.iScrollMvY;
321
322
0
  if (m_ComplexityAnalysisParam.iMbRowInGom <= 0)
323
0
    return RET_INVALIDPARAM;
324
0
  if (!iIdrFlag && pRef == NULL)
325
0
    return RET_INVALIDPARAM;
326
327
0
  if (iIdrFlag || pRef == NULL) {
328
0
    GomComplexityAnalysisIntra (pSrc);
329
0
  } else if (!bScrollFlag || ((iScrollMvX == 0) && (iScrollMvY == 0))) {
330
0
    GomComplexityAnalysisInter (pSrc, pRef, 0);
331
0
  } else {
332
0
    GomComplexityAnalysisInter (pSrc, pRef, 1);
333
0
  }
334
335
0
  return RET_SUCCESS;
336
0
}
337
338
339
0
EResult CComplexityAnalysisScreen::Set (int32_t nType, void* pParam) {
340
0
  if (pParam == NULL)
341
0
    return RET_INVALIDPARAM;
342
343
0
  m_ComplexityAnalysisParam = * (SComplexityAnalysisScreenParam*)pParam;
344
345
0
  return RET_SUCCESS;
346
0
}
347
348
0
EResult CComplexityAnalysisScreen::Get (int32_t nType, void* pParam) {
349
0
  if (pParam == NULL)
350
0
    return RET_INVALIDPARAM;
351
352
0
  * (SComplexityAnalysisScreenParam*)pParam = m_ComplexityAnalysisParam;
353
354
0
  return RET_SUCCESS;
355
0
}
356
357
0
void CComplexityAnalysisScreen::GomComplexityAnalysisIntra (SPixMap* pSrc) {
358
0
  int32_t iWidth                  = pSrc->sRect.iRectWidth;
359
0
  int32_t iHeight                 = pSrc->sRect.iRectHeight;
360
0
  int32_t iBlockWidth             = iWidth  >> 4;
361
0
  int32_t iBlockHeight            = iHeight >> 4;
362
363
0
  int32_t iBlockSadH, iBlockSadV, iGomSad = 0;
364
0
  int32_t iIdx = 0;
365
366
0
  uint8_t* pPtrY = NULL;
367
0
  int32_t iStrideY = 0;
368
0
  int32_t iRowStrideY = 0;
369
370
0
  uint8_t* pTmpCur = NULL;
371
372
0
  ENFORCE_STACK_ALIGN_1D (uint8_t, iMemPredMb, 256, 16)
373
374
0
  pPtrY = (uint8_t*)pSrc->pPixel[0];
375
376
0
  iStrideY  = pSrc->iStride[0];
377
0
  iRowStrideY = iStrideY << 4;
378
379
0
  m_ComplexityAnalysisParam.iFrameComplexity = 0;
380
381
0
  for (int32_t j = 0; j < iBlockHeight; j ++) {
382
0
    pTmpCur = pPtrY;
383
384
0
    for (int32_t i = 0; i < iBlockWidth; i++) {
385
0
      iBlockSadH = iBlockSadV = 0x7fffffff; // INT_MAX
386
0
      if (j > 0) {
387
0
        m_pIntraFunc[0] (iMemPredMb, pTmpCur, iStrideY);
388
0
        iBlockSadH = m_pSadFunc (pTmpCur, iStrideY, iMemPredMb, 16);
389
0
      }
390
0
      if (i > 0) {
391
0
        m_pIntraFunc[1] (iMemPredMb, pTmpCur, iStrideY);
392
0
        iBlockSadV = m_pSadFunc (pTmpCur, iStrideY, iMemPredMb, 16);
393
0
      }
394
0
      if (i || j)
395
0
        iGomSad += WELS_MIN (iBlockSadH, iBlockSadV);
396
397
0
      pTmpCur += 16;
398
399
0
      if (i == iBlockWidth - 1 && ((j + 1) % m_ComplexityAnalysisParam.iMbRowInGom == 0 || j == iBlockHeight - 1)) {
400
0
        m_ComplexityAnalysisParam.pGomComplexity[iIdx] = iGomSad;
401
0
        m_ComplexityAnalysisParam.iFrameComplexity += iGomSad;
402
0
        iIdx++;
403
0
        iGomSad = 0;
404
0
      }
405
0
    }
406
407
0
    pPtrY += iRowStrideY;
408
0
  }
409
0
  m_ComplexityAnalysisParam.iGomNumInFrame = iIdx;
410
0
}
411
412
413
0
void CComplexityAnalysisScreen::GomComplexityAnalysisInter (SPixMap* pSrc, SPixMap* pRef, bool bScrollFlag) {
414
0
  int32_t iWidth                  = pSrc->sRect.iRectWidth;
415
0
  int32_t iHeight                 = pSrc->sRect.iRectHeight;
416
0
  int32_t iBlockWidth             = iWidth  >> 4;
417
0
  int32_t iBlockHeight            = iHeight >> 4;
418
419
0
  int32_t iInterSad, iScrollSad, iBlockSadH, iBlockSadV, iGomSad = 0;
420
0
  int32_t iIdx = 0;
421
422
0
  int32_t iScrollMvX = m_ComplexityAnalysisParam.sScrollResult.iScrollMvX;
423
0
  int32_t iScrollMvY = m_ComplexityAnalysisParam.sScrollResult.iScrollMvY;
424
425
0
  uint8_t* pPtrX = NULL, *pPtrY = NULL;
426
0
  int32_t iStrideX = 0, iStrideY = 0;
427
0
  int32_t iRowStrideX = 0, iRowStrideY = 0;
428
429
0
  uint8_t* pTmpRef = NULL, *pTmpCur = NULL, *pTmpRefScroll = NULL;
430
431
0
  ENFORCE_STACK_ALIGN_1D (uint8_t, iMemPredMb, 256, 16)
432
433
0
  pPtrX = (uint8_t*)pRef->pPixel[0];
434
0
  pPtrY = (uint8_t*)pSrc->pPixel[0];
435
436
0
  iStrideX  = pRef->iStride[0];
437
0
  iStrideY  = pSrc->iStride[0];
438
439
0
  iRowStrideX  = pRef->iStride[0] << 4;
440
0
  iRowStrideY  = pSrc->iStride[0] << 4;
441
442
0
  m_ComplexityAnalysisParam.iFrameComplexity = 0;
443
444
0
  for (int32_t j = 0; j < iBlockHeight; j ++) {
445
0
    pTmpRef  = pPtrX;
446
0
    pTmpCur  = pPtrY;
447
448
0
    for (int32_t i = 0; i < iBlockWidth; i++) {
449
0
      int32_t iBlockPointX = i << 4;
450
0
      int32_t iBlockPointY = j << 4;
451
452
0
      iInterSad = m_pSadFunc (pTmpCur, iStrideY, pTmpRef, iStrideX);
453
0
      if (bScrollFlag) {
454
0
        if ((iInterSad != 0) &&
455
0
            (iBlockPointX + iScrollMvX >= 0) && (iBlockPointX + iScrollMvX <= iWidth - 8) &&
456
0
            (iBlockPointY + iScrollMvY >= 0) && (iBlockPointY + iScrollMvY <= iHeight - 8)) {
457
0
          pTmpRefScroll = pTmpRef - iScrollMvY * iStrideX + iScrollMvX;
458
0
          iScrollSad = m_pSadFunc (pTmpCur, iStrideY, pTmpRefScroll, iStrideX);
459
460
0
          if (iScrollSad < iInterSad) {
461
0
            iInterSad = iScrollSad;
462
0
          }
463
0
        }
464
465
0
      }
466
467
0
      iBlockSadH = iBlockSadV = 0x7fffffff; // INT_MAX
468
469
0
      if (j > 0) {
470
0
        m_pIntraFunc[0] (iMemPredMb, pTmpCur, iStrideY);
471
0
        iBlockSadH = m_pSadFunc (pTmpCur, iStrideY, iMemPredMb, 16);
472
0
      }
473
0
      if (i > 0) {
474
0
        m_pIntraFunc[1] (iMemPredMb, pTmpCur, iStrideY);
475
0
        iBlockSadV = m_pSadFunc (pTmpCur, iStrideY, iMemPredMb, 16);
476
0
      }
477
478
0
      iGomSad += WELS_MIN (WELS_MIN (iBlockSadH, iBlockSadV), iInterSad);
479
480
0
      if (i == iBlockWidth - 1 && ((j + 1) % m_ComplexityAnalysisParam.iMbRowInGom == 0 || j == iBlockHeight - 1)) {
481
0
        m_ComplexityAnalysisParam.pGomComplexity[iIdx] = iGomSad;
482
0
        m_ComplexityAnalysisParam.iFrameComplexity += iGomSad;
483
0
        iIdx++;
484
0
        iGomSad = 0;
485
0
      }
486
487
0
      pTmpRef += 16;
488
0
      pTmpCur += 16;
489
0
    }
490
0
    pPtrX += iRowStrideX;
491
0
    pPtrY += iRowStrideY;
492
0
  }
493
0
  m_ComplexityAnalysisParam.iGomNumInFrame = iIdx;
494
0
}
495
496
WELSVP_NAMESPACE_END