• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <gtest/gtest.h>
2 #include "codec_def.h"
3 #include "macros.h"
4 #include "mc.h"
5 #include "cpu.h"
6 using namespace WelsCommon;
7 
8 #define MC_BUFF_SRC_STRIDE 32
9 #define MC_BUFF_DST_STRIDE 32
10 #define MC_BUFF_HEIGHT 30
11 
12 /**********************MC Unit Test Anchor Code Begin******************************/
13 static bool bQpelNeeded[4][4] = {
14   { false, true, false, true },
15   { true,  true,  true, true },
16   { false, true, false, true },
17   { true,  true,  true, true }
18 };
19 static int32_t iHpelRef0Array[4][4] = {
20   { 0, 1, 1, 1 },
21   { 0, 1, 1, 1 },
22   { 2, 3, 3, 3 },
23   { 0, 1, 1, 1 }
24 };
25 static int32_t iHpelRef1Array[4][4] = {
26   { 0, 0, 0, 0 },
27   { 2, 2, 3, 2 },
28   { 2, 2, 3, 2 },
29   { 2, 2, 3, 2 }
30 };
31 #define FILTER6TAP(pPixBuff, x, iStride) ((pPixBuff)[x-2*iStride] + (pPixBuff)[x+3*iStride] - 5*((pPixBuff)[x-iStride] + (pPixBuff)[x+2*iStride]) + 20*((pPixBuff)[x] + (pPixBuff)[x+iStride]))
Clip255(int32_t x)32 static inline uint8_t Clip255 (int32_t x) {
33   return ((x & ~255) ? (-x) >> 31 & 255 : x);
34 }
35 
MCCopyAnchor(uint8_t * pSrc,int32_t iSrcStride,uint8_t * pDst,int32_t iDstStride,int32_t iWidth,int32_t iHeight)36 static void MCCopyAnchor (uint8_t* pSrc, int32_t iSrcStride, uint8_t* pDst, int32_t iDstStride, int32_t iWidth,
37                           int32_t iHeight) {
38   for (int32_t y = 0; y < iHeight; y++) {
39     memcpy (pDst, pSrc, iWidth * sizeof (uint8_t));
40     pSrc += iSrcStride;
41     pDst += iDstStride;
42   }
43 }
44 
MCHalfPelFilterAnchor(uint8_t * pDstH,uint8_t * pDstV,uint8_t * pDstHV,uint8_t * pSrc,int32_t iStride,int32_t iWidth,int32_t iHeight,int16_t * pBuf)45 static void MCHalfPelFilterAnchor (uint8_t* pDstH, uint8_t* pDstV, uint8_t* pDstHV, uint8_t* pSrc,
46                                    int32_t iStride, int32_t iWidth, int32_t iHeight, int16_t* pBuf) {
47   for (int32_t y = 0; y < iHeight; y++) {
48     for (int32_t x = 0; x < iWidth; x++)
49       pDstH[x] = Clip255 ((FILTER6TAP (pSrc, x, 1) + 16) >> 5);
50     for (int32_t x = -2; x < iWidth + 3; x++) {
51       int32_t v = FILTER6TAP (pSrc, x, iStride);
52       if (x >= 0 && x < iWidth)
53         pDstV[x] = Clip255 ((v + 16) >> 5);
54       pBuf[x + 2] = v;
55     }
56     for (int32_t x = 0; x < iWidth; x++)
57       pDstHV[x] = Clip255 ((FILTER6TAP (pBuf + 2, x, 1) + 512) >> 10);
58     pDstH += iStride;
59     pDstV += iStride;
60     pDstHV += iStride;
61     pSrc += iStride;
62   }
63 }
64 
PixelAvgAnchor(uint8_t * pDst,int32_t iDstStride,uint8_t * pSrc1,int32_t iSrc1Stride,uint8_t * pSrc2,int32_t iSrc2Stride,int32_t iWidth,int32_t iHeight)65 static void PixelAvgAnchor (uint8_t* pDst,  int32_t iDstStride,
66                             uint8_t* pSrc1, int32_t iSrc1Stride,
67                             uint8_t* pSrc2, int32_t iSrc2Stride, int32_t iWidth, int32_t iHeight) {
68   for (int32_t y = 0; y < iHeight; y++) {
69     for (int32_t x = 0; x < iWidth; x++)
70       pDst[x] = (pSrc1[x] + pSrc2[x] + 1) >> 1;
71     pDst  += iDstStride;
72     pSrc1 += iSrc1Stride;
73     pSrc2 += iSrc2Stride;
74   }
75 }
76 
MCLumaAnchor(uint8_t * pDst,int32_t iDstStride,uint8_t * pSrc[4],int32_t iSrcStride,int32_t iMvX,int32_t iMvY,int32_t iWidth,int32_t iHeight)77 static void MCLumaAnchor (uint8_t* pDst, int32_t iDstStride, uint8_t* pSrc[4], int32_t iSrcStride,
78                           int32_t iMvX, int32_t iMvY, int32_t iWidth, int32_t iHeight) {
79   int32_t iMvXIdx = iMvX & 3;
80   int32_t iMvYIdx = iMvY & 3;
81   int32_t iOffset = (iMvY >> 2) * iSrcStride + (iMvX >> 2);
82   uint8_t* pSrc1 = pSrc[iHpelRef0Array[iMvYIdx][iMvXIdx]] + iOffset + ((iMvYIdx) == 3) * iSrcStride;
83 
84   if (bQpelNeeded[iMvYIdx][iMvXIdx]) {
85     uint8_t* pSrc2 = pSrc[iHpelRef1Array[iMvYIdx][iMvXIdx]] + iOffset + ((iMvXIdx) == 3);
86     PixelAvgAnchor (pDst, iDstStride, pSrc1, iSrcStride, pSrc2, iSrcStride, iWidth, iHeight);
87   } else {
88     MCCopyAnchor (pSrc1, iSrcStride, pDst, iDstStride, iWidth, iHeight);
89   }
90 }
91 
MCChromaAnchor(uint8_t * pDstU,uint8_t * pDstV,int32_t iDstStride,uint8_t * pSrc,int32_t iSrcStride,int32_t iMvX,int32_t iMvY,int32_t iWidth,int32_t iHeight)92 static void MCChromaAnchor (uint8_t* pDstU, uint8_t* pDstV, int32_t iDstStride, uint8_t* pSrc, int32_t iSrcStride,
93                             int32_t iMvX, int32_t iMvY, int32_t iWidth, int32_t iHeight) {
94   uint8_t* pSrcTmp;
95   pSrc += (iMvY >> 3) * iSrcStride + (iMvX >> 3) * 2;
96   pSrcTmp = &pSrc[iSrcStride];
97 
98   int32_t iMvXIdx = iMvX & 0x07;
99   int32_t iMvYIdx = iMvY & 0x07;
100   int32_t iBiPara0 = (8 - iMvXIdx) * (8 - iMvYIdx);
101   int32_t iBiPara1 = iMvXIdx    * (8 - iMvYIdx);
102   int32_t iBiPara2 = (8 - iMvXIdx) * iMvYIdx;
103   int32_t iBiPara3 = iMvXIdx    * iMvYIdx;
104   for (int32_t y = 0; y < iHeight; y++) {
105     for (int32_t x = 0; x < iWidth; x++) {
106       pDstU[x] = (iBiPara0 * pSrc[2 * x]  + iBiPara1 * pSrc[2 * x + 2] +
107                   iBiPara2 * pSrcTmp[2 * x] + iBiPara3 * pSrcTmp[2 * x + 2] + 32) >> 6;
108       pDstV[x] = (iBiPara0 * pSrc[2 * x + 1]  + iBiPara1 * pSrc[2 * x + 3] +
109                   iBiPara2 * pSrcTmp[2 * x + 1] + iBiPara3 * pSrcTmp[2 * x + 3] + 32) >> 6;
110     }
111     pSrc   = pSrcTmp;
112     pSrcTmp += iSrcStride;
113     pDstU += iDstStride;
114     pDstV += iDstStride;
115   }
116 }
117 
118 /**********************MC Unit Test OPENH264 Code Begin******************************/
119 #define DEF_MCCOPYTEST(iW,iH) \
120 TEST(McCopy_c,iW##x##iH) \
121 {                             \
122     SMcFunc sMcFunc;      \
123     int32_t iCpuCores = 1; \
124     uint32_t uiCpuFlag;\
125     for(int32_t k =0; k<2; k++)\
126     {\
127       if(k==0)\
128       {\
129         uiCpuFlag = 0;\
130       }else \
131       {\
132         uiCpuFlag = WelsCPUFeatureDetect (&iCpuCores); \
133       }\
134       InitMcFunc(&sMcFunc, uiCpuFlag); \
135       uint8_t uSrcAnchor[MC_BUFF_HEIGHT][MC_BUFF_SRC_STRIDE]; \
136       uint8_t uSrcTest[MC_BUFF_HEIGHT][MC_BUFF_SRC_STRIDE];    \
137       ENFORCE_STACK_ALIGN_2D(uint8_t, uDstAnchor, MC_BUFF_HEIGHT, MC_BUFF_DST_STRIDE, 16); \
138       ENFORCE_STACK_ALIGN_2D(uint8_t, uDstTest, MC_BUFF_HEIGHT, MC_BUFF_DST_STRIDE, 16); \
139       for(int32_t j=0;j<MC_BUFF_HEIGHT;j++)                    \
140       {                                                         \
141         for(int32_t i=0;i<MC_BUFF_SRC_STRIDE;i++)                  \
142         {                                                       \
143           uSrcAnchor[j][i] = uSrcTest[j][i] = rand()%256;      \
144         }                                                         \
145       }                                                              \
146       memset(uDstAnchor,0,sizeof(uint8_t)*MC_BUFF_HEIGHT*MC_BUFF_DST_STRIDE);\
147       memset(uDstTest,0,sizeof(uint8_t)*MC_BUFF_HEIGHT*MC_BUFF_DST_STRIDE);  \
148       MCCopyAnchor(uSrcAnchor[0],MC_BUFF_SRC_STRIDE,uDstAnchor[0],MC_BUFF_DST_STRIDE,iW,iH);   \
149       sMcFunc.pMcLumaFunc(uSrcTest[0],MC_BUFF_SRC_STRIDE,uDstTest[0],MC_BUFF_DST_STRIDE,0,0,iW,iH); \
150       for(int32_t j=0;j<MC_BUFF_HEIGHT;j++)   \
151       {                                                                             \
152         for(int32_t i=0;i<MC_BUFF_DST_STRIDE;i++)                                  \
153         {                                                                           \
154           ASSERT_EQ(uDstAnchor[j][i],uDstTest[j][i]);                              \
155         }                                                                             \
156       }                                                                                 \
157     }\
158 }
159 
160 DEF_MCCOPYTEST (2, 2)
161 DEF_MCCOPYTEST (2, 4)
162 DEF_MCCOPYTEST (4, 2)
163 DEF_MCCOPYTEST (4, 4)
164 DEF_MCCOPYTEST (4, 8)
165 DEF_MCCOPYTEST (8, 4)
166 DEF_MCCOPYTEST (8, 8)
167 DEF_MCCOPYTEST (16, 8)
168 DEF_MCCOPYTEST (8, 16)
169 DEF_MCCOPYTEST (16, 16)
170 
171 #define DEF_LUMA_MCTEST(iW, iH, cpu_flags, name_suffix) \
172 TEST(McHorVer, iW##x##iH##_##name_suffix) \
173 {                       \
174     for (int32_t a = 0; a < 4; a++) { \
175     for (int32_t b = 0; b < 4; b++) { \
176     SMcFunc sMcFunc;  \
177     uint8_t uSrcAnchor[4][MC_BUFF_HEIGHT][MC_BUFF_SRC_STRIDE]; \
178     uint8_t uSrcTest[MC_BUFF_HEIGHT][MC_BUFF_SRC_STRIDE];      \
179     ENFORCE_STACK_ALIGN_2D(uint8_t, uDstAnchor, MC_BUFF_HEIGHT, MC_BUFF_DST_STRIDE, 16); \
180     ENFORCE_STACK_ALIGN_2D(uint8_t, uDstTest, MC_BUFF_HEIGHT, MC_BUFF_DST_STRIDE, 16); \
181     uint8_t* uSrcInputAnchor[4];                              \
182     int16_t pBuf[MC_BUFF_DST_STRIDE]; \
183     uSrcInputAnchor[0] = &uSrcAnchor[0][4][4]; \
184     uSrcInputAnchor[1] = &uSrcAnchor[1][4][4]; \
185     uSrcInputAnchor[2] = &uSrcAnchor[2][4][4]; \
186     uSrcInputAnchor[3] = &uSrcAnchor[3][4][4]; \
187     for(int32_t j=0;j<MC_BUFF_HEIGHT;j++)   \
188     {\
189       for(int32_t i=0;i<MC_BUFF_SRC_STRIDE;i++)   \
190       {\
191         uSrcAnchor[0][j][i] = uSrcTest[j][i] = rand()%256;  \
192       }\
193     }\
194     InitMcFunc(&sMcFunc, WelsCPUFeatureDetect (0) & (cpu_flags)); \
195     memset(uDstAnchor,0,sizeof(uint8_t)*MC_BUFF_HEIGHT*MC_BUFF_DST_STRIDE); \
196     memset(uDstTest,0,sizeof(uint8_t)*MC_BUFF_HEIGHT*MC_BUFF_DST_STRIDE); \
197     MCHalfPelFilterAnchor(uSrcInputAnchor[1],uSrcInputAnchor[2],uSrcInputAnchor[3],uSrcInputAnchor[0],MC_BUFF_SRC_STRIDE,iW+1,iH+1,pBuf+4); \
198     MCLumaAnchor(uDstAnchor[0],MC_BUFF_DST_STRIDE,uSrcInputAnchor,MC_BUFF_SRC_STRIDE,a,b,iW,iH); \
199     sMcFunc.pMcLumaFunc(&uSrcTest[4][4],MC_BUFF_SRC_STRIDE,uDstTest[0],MC_BUFF_DST_STRIDE,a,b,iW,iH);\
200     for(int32_t j=0;j<MC_BUFF_HEIGHT;j++)   \
201     {                                                                             \
202         for(int32_t i=0;i<MC_BUFF_DST_STRIDE;i++)                                  \
203         {                                                                           \
204             ASSERT_EQ(uDstAnchor[j][i],uDstTest[j][i]);                              \
205         }                                                                             \
206     }                                                                                \
207     }\
208     }\
209 }
210 
211 #define DEF_LUMA_MCTESTS(cpu_flags, name_suffix) \
212     DEF_LUMA_MCTEST ( 4,  4, cpu_flags, name_suffix) \
213     DEF_LUMA_MCTEST ( 4,  8, cpu_flags, name_suffix) \
214     DEF_LUMA_MCTEST ( 8,  4, cpu_flags, name_suffix) \
215     DEF_LUMA_MCTEST ( 8,  8, cpu_flags, name_suffix) \
216     DEF_LUMA_MCTEST (16,  8, cpu_flags, name_suffix) \
217     DEF_LUMA_MCTEST ( 8, 16, cpu_flags, name_suffix) \
218     DEF_LUMA_MCTEST (16, 16, cpu_flags, name_suffix)
219 
220 DEF_LUMA_MCTESTS(0, c)
221 DEF_LUMA_MCTESTS(~0, native)
222 #ifdef X86_ASM
DEF_LUMA_MCTESTS(WELS_CPU_SSE2,sse2)223 DEF_LUMA_MCTESTS(WELS_CPU_SSE2, sse2)
224 DEF_LUMA_MCTESTS(WELS_CPU_SSE2 | WELS_CPU_SSSE3, ssse3)
225 #ifdef HAVE_AVX2
226 DEF_LUMA_MCTESTS(WELS_CPU_SSE2 | WELS_CPU_SSSE3 | WELS_CPU_AVX2, avx2)
227 #endif
228 #endif
229 
230 #define DEF_CHROMA_MCTEST(iW,iH) \
231 TEST(McChroma,iW##x##iH)  \
232 {                       \
233     for (int32_t a = 0; a < 8; a++) { \
234     for (int32_t b = 0; b < 8; b++) { \
235     SMcFunc sMcFunc;  \
236     uint8_t uSrcAnchor[MC_BUFF_HEIGHT][MC_BUFF_SRC_STRIDE*2]; \
237     uint8_t uSrcTest[MC_BUFF_HEIGHT][MC_BUFF_SRC_STRIDE];      \
238     ENFORCE_STACK_ALIGN_2D(uint8_t, uDstAnchor1, MC_BUFF_HEIGHT, MC_BUFF_DST_STRIDE, 16); \
239     ENFORCE_STACK_ALIGN_2D(uint8_t, uDstAnchor2, MC_BUFF_HEIGHT, MC_BUFF_DST_STRIDE, 16); \
240     ENFORCE_STACK_ALIGN_2D(uint8_t, uDstTest, MC_BUFF_HEIGHT, MC_BUFF_DST_STRIDE, 16); \
241     for(int32_t j=0;j<MC_BUFF_HEIGHT;j++)   \
242     {\
243       for(int32_t i=0;i<MC_BUFF_SRC_STRIDE;i++)   \
244       {\
245         uSrcAnchor[j][i*2] = uSrcTest[j][i] = rand()%256;  \
246       }\
247     }\
248     int32_t iCpuCores = 1; \
249     uint32_t uiCpuFlag;\
250     for(int32_t k =0; k<2; k++)\
251     {\
252       if(k==0)\
253       {\
254         uiCpuFlag = 0;\
255       }else \
256       {\
257         uiCpuFlag = WelsCPUFeatureDetect (&iCpuCores); \
258       }\
259       InitMcFunc(&sMcFunc,uiCpuFlag);\
260       memset(uDstAnchor1,0,sizeof(uint8_t)*MC_BUFF_HEIGHT*MC_BUFF_DST_STRIDE); \
261       memset(uDstAnchor2,0,sizeof(uint8_t)*MC_BUFF_HEIGHT*MC_BUFF_DST_STRIDE); \
262       memset(uDstTest,0,sizeof(uint8_t)*MC_BUFF_HEIGHT*MC_BUFF_DST_STRIDE);     \
263       MCChromaAnchor(uDstAnchor1[0],uDstAnchor2[0],MC_BUFF_DST_STRIDE,uSrcAnchor[0],MC_BUFF_SRC_STRIDE*2,a,b,iW,iH); \
264       sMcFunc.pMcChromaFunc(uSrcTest[0],MC_BUFF_SRC_STRIDE,uDstTest[0],MC_BUFF_DST_STRIDE,a,b,iW,iH);\
265       for(int32_t j=0;j<MC_BUFF_HEIGHT;j++)   \
266       {                                                                             \
267           for(int32_t i=0;i<MC_BUFF_DST_STRIDE;i++)                                  \
268           {                                                                           \
269               ASSERT_EQ(uDstAnchor1[j][i],uDstTest[j][i]);                             \
270           }                                                                             \
271       }                                                                                 \
272     }\
273     }\
274     }\
275 }
276 
277 DEF_CHROMA_MCTEST (2, 2)
278 DEF_CHROMA_MCTEST (2, 4)
279 DEF_CHROMA_MCTEST (4, 2)
280 DEF_CHROMA_MCTEST (4, 4)
281 DEF_CHROMA_MCTEST (4, 8)
282 DEF_CHROMA_MCTEST (8, 4)
283 DEF_CHROMA_MCTEST (8, 8)
284 
285 TEST (EncMcAvg, PixelAvg) {
286   SMcFunc sMcFunc;
287   for (int32_t k = 0; k < 2; k++) {
288     for (int32_t w = 0; w < 2; w++) {
289       int32_t width = 8 << w;
290       int32_t height = 16;
291       uint32_t uiCpuFlag = k == 0 ? 0 : WelsCPUFeatureDetect (NULL);
292       InitMcFunc (&sMcFunc, uiCpuFlag);
293       uint8_t uSrc1[MC_BUFF_HEIGHT][MC_BUFF_SRC_STRIDE];
294       uint8_t uSrc2[MC_BUFF_HEIGHT][MC_BUFF_SRC_STRIDE];
295       ENFORCE_STACK_ALIGN_2D (uint8_t, uDstAnchor, MC_BUFF_HEIGHT, MC_BUFF_DST_STRIDE, 16);
296       ENFORCE_STACK_ALIGN_2D (uint8_t, uDstTest, MC_BUFF_HEIGHT, MC_BUFF_DST_STRIDE, 16);
297       for (int32_t j = 0; j < MC_BUFF_HEIGHT; j++) {
298         for (int32_t i = 0; i < MC_BUFF_SRC_STRIDE; i++) {
299           uSrc1[j][i] = rand() % 256;
300           uSrc2[j][i] = rand() % 256;
301         }
302       }
303       PixelAvgAnchor (uDstAnchor[0], MC_BUFF_DST_STRIDE, uSrc1[0], MC_BUFF_SRC_STRIDE, uSrc2[0], MC_BUFF_SRC_STRIDE, width,
304                       height);
305       sMcFunc.pfSampleAveraging (uDstTest[0], MC_BUFF_DST_STRIDE, uSrc1[0], MC_BUFF_SRC_STRIDE, uSrc2[0],
306                                  MC_BUFF_SRC_STRIDE, width, height);
307       for (int32_t j = 0; j < height; j++) {
308         for (int32_t i = 0; i < width; i++) {
309           ASSERT_EQ (uDstAnchor[j][i], uDstTest[j][i]);
310         }
311       }
312     }
313   }
314 }
315 
316 #define DEF_HALFPEL_MCTEST(iW, iH, cpu_flags, name_suffix) \
317 TEST (EncMcHalfpel, iW##x##iH##_##name_suffix) { \
318     SMcFunc sMcFunc; \
319     for (int32_t w = 0; w < 2; w++) { \
320         int32_t width = iW ; \
321         int32_t height = iH; \
322         uint8_t uAnchor[4][MC_BUFF_HEIGHT][MC_BUFF_SRC_STRIDE]; \
323         uint8_t uSrcTest[MC_BUFF_HEIGHT][MC_BUFF_SRC_STRIDE]; \
324         uint8_t uRand[MC_BUFF_HEIGHT][MC_BUFF_DST_STRIDE]; \
325         ENFORCE_STACK_ALIGN_2D (uint8_t, uDstTest, MC_BUFF_HEIGHT, MC_BUFF_DST_STRIDE, 16); \
326         uint8_t* uAnchors[4]; \
327         int16_t pBuf[MC_BUFF_DST_STRIDE]; \
328         uAnchors[0] = &uAnchor[0][4][4]; \
329         uAnchors[1] = &uAnchor[1][4][4]; \
330         uAnchors[2] = &uAnchor[2][4][4]; \
331         uAnchors[3] = &uAnchor[3][4][4]; \
332          \
333         memset (uAnchor, 0, 4 * sizeof (uint8_t)*MC_BUFF_HEIGHT * MC_BUFF_SRC_STRIDE); \
334         memset (uDstTest, 0, sizeof (uint8_t)*MC_BUFF_HEIGHT * MC_BUFF_DST_STRIDE); \
335         for (int32_t j = 0; j < MC_BUFF_HEIGHT; j++) { \
336             for (int32_t i = 0; i < MC_BUFF_SRC_STRIDE; i++) { \
337                 uAnchor[0][j][i] = uSrcTest[j][i] = rand() % 256; \
338                 uRand[j][i] = rand() % 256; \
339             } \
340         } \
341          \
342         InitMcFunc (&sMcFunc, WelsCPUFeatureDetect (0) & (cpu_flags)); \
343          \
344         MCHalfPelFilterAnchor (uAnchors[1], uAnchors[2], uAnchors[3], uAnchors[0], MC_BUFF_SRC_STRIDE, width + 1, height + 1, pBuf + 4); \
345         memcpy (&uDstTest[0][0], &uRand[0][0], sizeof uRand); \
346         sMcFunc.pfLumaHalfpelHor (&uSrcTest[4][4], MC_BUFF_SRC_STRIDE, uDstTest[0], MC_BUFF_DST_STRIDE, width + 1, height); \
347         for (int32_t j = 0; j < height; j++) { \
348             for (int32_t i = 0; i < width + 1; i++) { \
349                 ASSERT_EQ (uAnchor[1][4 + j][4 + i], uDstTest[j][i]); \
350             } \
351         } \
352         for (int32_t j = 0; j < MC_BUFF_HEIGHT; j++) { \
353             for (int32_t i = j < height ? width + 1 : 0; i < MC_BUFF_DST_STRIDE; i++) { \
354                 ASSERT_EQ (uRand[j][i], uDstTest[j][i]); \
355             } \
356         } \
357         memcpy (&uDstTest[0][0], &uRand[0][0], sizeof uRand); \
358         sMcFunc.pfLumaHalfpelVer (&uSrcTest[4][4], MC_BUFF_SRC_STRIDE, uDstTest[0], MC_BUFF_DST_STRIDE, width, height + 1); \
359         for (int32_t j = 0; j < height + 1; j++) { \
360             for (int32_t i = 0; i < width; i++) { \
361                 ASSERT_EQ (uAnchor[2][4 + j][4 + i], uDstTest[j][i]); \
362             } \
363         } \
364         for (int32_t j = 0; j < MC_BUFF_HEIGHT; j++) { \
365             for (int32_t i = j < height + 1 ? width : 0; i < MC_BUFF_DST_STRIDE; i++) { \
366                 ASSERT_EQ (uRand[j][i], uDstTest[j][i]); \
367             } \
368         } \
369         memcpy (&uDstTest[0][0], &uRand[0][0], sizeof uRand); \
370         sMcFunc.pfLumaHalfpelCen (&uSrcTest[4][4], MC_BUFF_SRC_STRIDE, uDstTest[0], MC_BUFF_DST_STRIDE, width + 1, height + 1); \
371         for (int32_t j = 0; j < height + 1; j++) { \
372             for (int32_t i = 0; i < width + 1; i++) { \
373                 ASSERT_EQ (uAnchor[3][4 + j][4 + i], uDstTest[j][i]); \
374             } \
375         } \
376         for (int32_t j = 0; j < MC_BUFF_HEIGHT; j++) { \
377             for (int32_t i = j < height + 1 ? width + 1 : 0; i < MC_BUFF_DST_STRIDE; i++) { \
378                 ASSERT_EQ (uRand[j][i], uDstTest[j][i]); \
379             } \
380         } \
381     } \
382 }
383 
384 #define DEF_HALFPEL_MCTESTS(cpu_flags, name_suffix) \
385     DEF_HALFPEL_MCTEST( 4 , 4, cpu_flags, name_suffix) \
386     DEF_HALFPEL_MCTEST( 4,  8, cpu_flags, name_suffix) \
387     DEF_HALFPEL_MCTEST( 8,  4, cpu_flags, name_suffix) \
388     DEF_HALFPEL_MCTEST( 8,  8, cpu_flags, name_suffix) \
389     DEF_HALFPEL_MCTEST( 8, 16, cpu_flags, name_suffix) \
390     DEF_HALFPEL_MCTEST(16,  8, cpu_flags, name_suffix) \
391     DEF_HALFPEL_MCTEST(16, 16, cpu_flags, name_suffix)
392 
393 DEF_HALFPEL_MCTESTS(0, c)
394 DEF_HALFPEL_MCTESTS(~0, native)
395 #ifdef X86_ASM
396 DEF_HALFPEL_MCTESTS(WELS_CPU_SSE2, sse2)
397 DEF_HALFPEL_MCTESTS(WELS_CPU_SSE2 | WELS_CPU_SSSE3, ssse3)
398 #ifdef HAVE_AVX2
399 DEF_HALFPEL_MCTESTS(WELS_CPU_SSE2 | WELS_CPU_SSSE3 | WELS_CPU_AVX2, avx2)
400 #endif
401 #endif
402