1 #include <gtest/gtest.h>
2 
3 #include "../../codec/decoder/core/inc/deblocking.h"
4 #include "../../codec/common/inc/deblocking_common.h"
5 
6 using namespace WelsDec;
7 
8 /* extern pure C functions */
9 extern void DeblockLumaLt4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta,
10                               int8_t* pTc);
11 extern void DeblockLumaEq4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta);
12 extern void DeblockChromaLt4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha,
13                                 int32_t iBeta, int8_t* pTc);
14 extern void DeblockChromaEq4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha,
15                                 int32_t iBeta);
16 namespace WelsDec {
17 extern void FilteringEdgeChromaHV (PDqLayer pCurDqLayer, PDeblockingFilter  pFilter, int32_t iBoundryFlag);
18 extern void FilteringEdgeLumaHV (PDqLayer pCurDqLayer, PDeblockingFilter  pFilter, int32_t iBoundryFlag);
19 }
20 
21 /* Macros body */
22 #define GENERATE_DATA_DEBLOCKING(pBase, pRef, iWidth) \
23 if (iNum==0) { \
24   iAlpha = 255; \
25   iBeta = 18; \
26   iTc[0] = iTc[1] = iTc[2] = iTc[3] = 25; \
27   pBase[0] = pRef[0] = 128; \
28   for (int i = 1; i < iWidth*iWidth; i++) { \
29   pBase[i] = pRef[i] = WelsClip3( pBase[i-1] -16 + rand()%32, 0, 255 ); \
30   } \
31 } else if (iNum==1) { \
32   iAlpha = 4; \
33   iBeta = 2; \
34   iTc[0] = iTc[1] = iTc[2] = iTc[3] = 9; \
35   pBase[0] = pRef[0] = 128; \
36   for (int i = 1; i < iWidth*iWidth; i++) { \
37   pBase[i] = pRef[i] = WelsClip3( pBase[i-1] -4 + rand()%8, 0, 255 ); \
38   } \
39 } else { \
40   iAlpha = rand() % 256; \
41   iBeta = rand() % 19; \
42   for (int i=0; i<4; i++) { \
43   iTc[i] = rand() % 26; \
44   } \
45   for (int i = 0; i < iWidth*iWidth; i++) { \
46   pBase[i] = pRef[i] = rand() % 256; \
47   } \
48 }
49 
50 /* NULL functions, for null call */
UT_DeblockingFuncInterface(PDqLayer pCurDqLayer,PDeblockingFilter filter,int32_t boundry_flag)51 void UT_DeblockingFuncInterface (PDqLayer pCurDqLayer, PDeblockingFilter  filter, int32_t boundry_flag) {
52   return;
53 }
54 
55 /* Set deblocking functions to NULL */
UT_DeblockingFuncLumaLT4Func(uint8_t * iSampleY,int32_t iStride,int32_t iAlpha,int32_t iBeta,int8_t * iTc)56 void UT_DeblockingFuncLumaLT4Func (uint8_t* iSampleY, int32_t iStride, int32_t iAlpha, int32_t iBeta, int8_t* iTc) {
57   if (iAlpha > 0 || iBeta > 0) {
58     iSampleY[0]++;
59   }
60   return;
61 }
62 
UT_DeblockingFuncLumaEQ4Func(uint8_t * iSampleY,int32_t iStride,int32_t iAlpha,int32_t iBeta)63 void UT_DeblockingFuncLumaEQ4Func (uint8_t* iSampleY, int32_t iStride, int32_t iAlpha, int32_t iBeta) {
64   if (iAlpha > 0 || iBeta > 0) {
65     iSampleY[0]++;
66   }
67   return;
68 }
69 
UT_DeblockingFuncChromaLT4Func(uint8_t * iSampleCb,uint8_t * iSampleCr,int32_t iStride,int32_t iAlpha,int32_t iBeta,int8_t * iTc)70 void UT_DeblockingFuncChromaLT4Func (uint8_t* iSampleCb, uint8_t* iSampleCr, int32_t iStride, int32_t iAlpha,
71                                      int32_t iBeta, int8_t* iTc) {
72   if (iAlpha > 0 || iBeta > 0) {
73     iSampleCb[0]++;
74     iSampleCr[0]++;
75   }
76   return;
77 }
78 
UT_DeblockingFuncChromaEQ4Func(uint8_t * iSampleCb,uint8_t * iSampleCr,int32_t iStride,int32_t iAlpha,int32_t iBeta)79 void UT_DeblockingFuncChromaEQ4Func (uint8_t* iSampleCb, uint8_t* iSampleCr, int32_t iStride, int32_t iAlpha,
80                                      int32_t iBeta) {
81   if (iAlpha > 0 || iBeta > 0) {
82     iSampleCb[0]++;
83     iSampleCr[0]++;
84   }
85   return;
86 }
87 
88 /* Public function for local test */
89 
90 /* Anchor functions body, some directly from the current code */
anchor_DeblockingLumaNormal(uint8_t * pPix,int32_t iStrideX,int32_t iStrideY,int32_t iAlpha,int32_t iBeta,int8_t * pTc)91 void anchor_DeblockingLumaNormal (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta,
92                                   int8_t* pTc) {
93   // void DeblockLumaLt4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta, int8_t* pTc)
94   // bS<4, Section 8.7.2.3
95 
96   int32_t p[3];
97   int32_t q[3];
98   int32_t iTc;
99   int32_t iDelta;
100   int32_t iIndexTc;
101   for (int iLine = 0; iLine < 16; iLine++) {
102     iIndexTc = iLine >> 2;
103 
104     iTc = pTc[iIndexTc];
105     for (int m = 0; m < 3; m++) {
106       p[m] = pPix[iStrideX * -1 * (m + 1)];
107       q[m] = pPix[iStrideX * m];
108     }// for
109 
110     // filterSampleFlag, 8-460
111     if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
112       // 8-470
113       if (abs (p[2] - p[0]) < iBeta) {
114         pPix[iStrideX * -2] = WELS_CLIP3 (p[1] + WELS_CLIP3 (((p[2] + ((p[0] + q[0] + 1) >> 1) - (p[1] << 1)) >> 1),
115                                           -1 * pTc[iIndexTc], pTc[iIndexTc]), 0, 255);
116         iTc++;
117       }
118       // 8-472
119       if (abs (q[2] - q[0]) < iBeta) {
120         pPix[iStrideX * 1] = WELS_CLIP3 (q[1] + WELS_CLIP3 (((q[2] + ((p[0] + q[0] + 1) >> 1) - (q[1] << 1)) >> 1),
121                                          -1 * pTc[iIndexTc],  pTc[iIndexTc]), 0, 255);
122         iTc++;
123       }
124       // 8-467,468,469
125       iDelta = WELS_CLIP3 (((((q[0] - p[0]) * (1 << 2)) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
126       pPix[iStrideX * -1] = WELS_CLIP3 ((p[0] + iDelta), 0, 255);
127       pPix[0] = WELS_CLIP3 ((q[0] - iDelta), 0, 255);
128     }
129 
130     // Next line
131     pPix += iStrideY;
132   }
133 }
134 
anchor_DeblockingLumaIntra(uint8_t * pPix,int32_t iStrideX,int32_t iStrideY,int32_t iAlpha,int32_t iBeta)135 void anchor_DeblockingLumaIntra (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta) {
136   // void DeblockLumaEq4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta)
137   // bS==4, Section 8.7.2.4
138 
139   int32_t p[4], q[4];
140   for (int iLine = 0; iLine < 16; iLine++) {
141 
142     for (int m = 0; m < 4; m++) {
143       p[m] = pPix[iStrideX * -1 * (m + 1)];
144       q[m] = pPix[iStrideX * m];
145     }
146 
147     // filterSampleFlag, 8-460
148     if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
149 
150       // 8-476
151       if (abs (p[2] - p[0]) < iBeta && abs (p[0] - q[0]) < ((iAlpha >> 2) + 2)) {
152         // 8-477,478, 479
153         pPix[iStrideX * -1] = (p[2] + 2 * p[1] + 2 * p[0] + 2 * q[0] + q[1] + 4) >> 3;
154         pPix[iStrideX * -2] = (p[2] + p[1] + p[0] + q[0] + 2) >> 2;
155         pPix[iStrideX * -3] = (2 * p[3] + 3 * p[2] + p[1] + p[0] + q[0] + 4) >> 3;
156       } else {
157         // 8-480
158         pPix[iStrideX * -1] = (2 * p[1] + p[0] + q[1] + 2) >> 2;
159       }
160 
161       // 8-483
162       if (abs (q[2] - q[0]) < iBeta && abs (p[0] - q[0]) < ((iAlpha >> 2) + 2)) {
163         // 8-484,485,486
164         pPix[ 0           ] = (p[1] + 2 * p[0] + 2 * q[0] + 2 * q[1] + q[2] + 4) >> 3;
165         pPix[1 * iStrideX ] = (p[0] + q[0] + q[1] + q[2] + 2) >> 2;
166         pPix[2 * iStrideX ] = (2 * q[3] + 3 * q[2] + q[1] + q[0] + p[0] + 4) >> 3;
167       } else {
168         // 8-487
169         pPix[0 * iStrideX ] = (2 * q[1] + q[0] + p[1] + 2) >> 2;
170       }
171     }
172     // Next line
173     pPix += iStrideY;
174   }
175 }
176 
anchor_DeblockingChromaNormal(uint8_t * pPixCb,uint8_t * pPixCr,int32_t iStrideX,int32_t iStrideY,int32_t iAlpha,int32_t iBeta,int8_t * pTc)177 void anchor_DeblockingChromaNormal (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY,
178                                     int32_t iAlpha, int32_t iBeta, int8_t* pTc) {
179   // void DeblockChromaLt4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta, int8_t* pTc)
180   // Section 8.7.2.3
181   int32_t p[2], q[2];
182   int32_t iIndexTc;
183   int32_t iDelta;
184   int32_t iTc;
185   for (int iLine = 0; iLine < 8; iLine++) {
186     iIndexTc = iLine >> 1;
187     iTc = pTc[iIndexTc];
188     /* for Cb */
189     for (int m = 0; m < 2; m++) {
190       p[m] = pPixCb[iStrideX * -1 * (m + 1)];
191       q[m] = pPixCb[iStrideX * m];
192     }
193 
194     // filterSampleFlag, 8-460
195     if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
196       // 8-467, 468, 469
197       iDelta = WELS_CLIP3 (((((q[0] - p[0]) * (1 << 2)) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
198       pPixCb[iStrideX * -1] = WELS_CLIP3 ((p[0] + iDelta), 0, 255);
199       pPixCb[iStrideX * 0 ] = WELS_CLIP3 ((q[0] - iDelta), 0, 255);
200     }
201     pPixCb += iStrideY;
202 
203     /* for Cr */
204     for (int m = 0; m < 2; m++) {
205       p[m] = pPixCr[iStrideX * -1 * (m + 1)];
206       q[m] = pPixCr[iStrideX * m];
207     }
208 
209     // filterSampleFlag, 8-460
210     if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
211       // 8-467, 468, 469
212       iDelta = WELS_CLIP3 (((((q[0] - p[0]) * (1 << 2)) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
213       pPixCr[iStrideX * -1] = WELS_CLIP3 ((p[0] + iDelta), 0, 255);
214       pPixCr[iStrideX * 0 ] = WELS_CLIP3 ((q[0] - iDelta), 0, 255);
215     }
216     pPixCr += iStrideY;
217   }
218 }
219 
anchor_DeblockingChromaIntra(uint8_t * pPixCb,uint8_t * pPixCr,int32_t iStrideX,int32_t iStrideY,int32_t iAlpha,int32_t iBeta)220 void anchor_DeblockingChromaIntra (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha,
221                                    int32_t iBeta) {
222   //void DeblockChromaEq4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta)
223   // Section 8.7.2.4
224   int32_t p[2], q[2];
225 
226   for (int iLine = 0; iLine < 8; iLine++) {
227     /* for Cb */
228     for (int m = 0; m < 2; m++) {
229       p[m] = pPixCb[iStrideX * -1 * (m + 1)];
230       q[m] = pPixCb[iStrideX * m];
231     }
232 
233     // filterSampleFlag, 8-460
234     if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
235       // 8-480, 487
236       pPixCb[iStrideX * -1] = WELS_CLIP3 ((2 * p[1] + p[0] + q[1] + 2) >> 2, 0, 255);
237       pPixCb[iStrideX * 0 ] = WELS_CLIP3 ((2 * q[1] + q[0] + p[1] + 2) >> 2, 0, 255);
238     }
239     pPixCb += iStrideY;
240 
241     /* for Cr */
242     for (int m = 0; m < 2; m++) {
243       p[m] = pPixCr[iStrideX * -1 * (m + 1)];
244       q[m] = pPixCr[iStrideX * m];
245     }
246 
247     // filterSampleFlag, 8-460
248     if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
249       // 8-480, 487
250       pPixCr[iStrideX * -1] = WELS_CLIP3 ((2 * p[1] + p[0] + q[1] + 2) >> 2, 0, 255);
251       pPixCr[iStrideX * 0 ] = WELS_CLIP3 ((2 * q[1] + q[0] + p[1] + 2) >> 2, 0, 255);
252     }
253     pPixCr += iStrideY;
254   }
255 }
256 
257 /* Unit test functions body */
TEST(DeblockingCommon,DeblockLumaLt4_c)258 TEST (DeblockingCommon, DeblockLumaLt4_c) {
259   // void DeblockLumaLt4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta, int8_t* pTc)
260 
261 #define TEST_CYCLE 1000
262   ENFORCE_STACK_ALIGN_1D (uint8_t, iPixBase, 16 * 16, 16);
263   ENFORCE_STACK_ALIGN_1D (uint8_t, iPixRef, 16 * 16, 16);
264 
265   int32_t iAlpha, iBeta;
266 
267   ENFORCE_STACK_ALIGN_1D (int8_t,  iTc,   4, 16);
268 
269   for (int iNum = 0; iNum < TEST_CYCLE; iNum++) {
270     /* Horizontal */
271     GENERATE_DATA_DEBLOCKING (iPixBase, iPixRef, 16)
272 
273     anchor_DeblockingLumaNormal (&iPixBase[8 * 1], 1, 16, iAlpha, iBeta, iTc);
274     DeblockLumaLt4_c (&iPixRef[8 * 1], 1, 16, iAlpha, iBeta, iTc);
275 
276     for (int i = 0; i < 16 * 16; i++) {
277       ASSERT_FALSE (iPixBase[i] != iPixRef[i]) << "Horizontal Error, (Pos, Base, Ref)-(" << i << "," <<
278           (uint32_t)iPixBase[i] << "," << (uint32_t)iPixRef[i] << ")";
279     }
280 
281     /* Vertical */
282     GENERATE_DATA_DEBLOCKING (iPixBase, iPixRef, 16)
283 
284     anchor_DeblockingLumaNormal (&iPixBase[8 * 16], 16, 1, iAlpha, iBeta, iTc);
285     DeblockLumaLt4_c (&iPixRef[8 * 16], 16, 1, iAlpha, iBeta, iTc);
286 
287     for (int i = 0; i < 16 * 16; i++) {
288       ASSERT_FALSE (iPixBase[i] != iPixRef[i]) << "Vertical Error, (Pos, Base, Ref)-(" << i << "," <<
289           (uint32_t)iPixBase[i] << "," << (uint32_t)iPixRef[i] << ")";
290     }
291   }
292 }
TEST(DeblockingCommon,DeblockLumaEq4_c)293 TEST (DeblockingCommon, DeblockLumaEq4_c) {
294   //void DeblockLumaEq4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta)
295 #define TEST_CYCLE 1000
296   ENFORCE_STACK_ALIGN_1D (uint8_t, iPixBase, 16 * 16, 16);
297   ENFORCE_STACK_ALIGN_1D (uint8_t, iPixRef, 16 * 16, 16);
298 
299   int32_t iAlpha, iBeta;
300 
301   /* NOT used here */
302   ENFORCE_STACK_ALIGN_1D (int8_t,  iTc,   4, 16);
303 
304   for (int iNum = 0; iNum < TEST_CYCLE; iNum++) {
305     /* Horizontal */
306     GENERATE_DATA_DEBLOCKING (iPixBase, iPixRef, 16)
307 
308     anchor_DeblockingLumaIntra (&iPixBase[8 * 1], 1, 16, iAlpha, iBeta);
309     DeblockLumaEq4_c (&iPixRef[8 * 1], 1, 16, iAlpha, iBeta);
310 
311     for (int i = 0; i < 16 * 16; i++) {
312       ASSERT_FALSE (iPixBase[i] != iPixRef[i]) << "Horizontal Error, (Pos, Base, Ref)-(" << i << "," <<
313           (uint32_t)iPixBase[i] << "," << (uint32_t)iPixRef[i] << ")";
314     }
315 
316     /* Vertical */
317     GENERATE_DATA_DEBLOCKING (iPixBase, iPixRef, 16)
318 
319     anchor_DeblockingLumaIntra (&iPixBase[8 * 16], 16, 1, iAlpha, iBeta);
320     DeblockLumaEq4_c (&iPixRef[8 * 16], 16, 1, iAlpha, iBeta);
321 
322     for (int i = 0; i < 16 * 16; i++) {
323       ASSERT_FALSE (iPixBase[i] != iPixRef[i]) << "Vertical Error, (Pos, Base, Ref)-(" << i << "," <<
324           (uint32_t)iPixBase[i] << "," << (uint32_t)iPixRef[i] << ")";
325     }
326   }
327 }
328 
TEST(DeblockingCommon,DeblockChromaLt4_c)329 TEST (DeblockingCommon, DeblockChromaLt4_c) {
330   // void DeblockChromaLt4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta, int8_t* pTc)
331 #define TEST_CYCLE 1000
332   ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCbBase, 8 * 8, 16);
333   ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCrBase, 8 * 8, 16);
334   ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCbRef, 8 * 8, 16);
335   ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCrRef, 8 * 8, 16);
336 
337   int32_t iAlpha, iBeta;
338 
339   ENFORCE_STACK_ALIGN_1D (int8_t,  iTc,   4, 16);
340 
341   for (int iNum = 0; iNum < TEST_CYCLE; iNum++) {
342     /* Horizontal */
343     GENERATE_DATA_DEBLOCKING (iPixCbBase, iPixCbRef, 8)
344     GENERATE_DATA_DEBLOCKING (iPixCrBase, iPixCrRef, 8)
345 
346     anchor_DeblockingChromaNormal (&iPixCbBase[4 * 1], &iPixCrBase[4 * 1], 1, 8, iAlpha, iBeta, iTc);
347     DeblockChromaLt4_c (&iPixCbRef[4 * 1], &iPixCrRef[4 * 1], 1, 8, iAlpha, iBeta, iTc);
348 
349     for (int i = 0; i < 8 * 8; i++) {
350       ASSERT_FALSE (iPixCbBase[i] != iPixCbRef[i]
351                     ||  iPixCrBase[i] != iPixCrRef[i]) << "Horizontal Error, (pos, CbBase, CbRef, CrBase, CrRef)-(" << i << "," <<
352                         (uint32_t)iPixCbBase[i] << "," << (uint32_t)iPixCbRef[i] << "," << (uint32_t)iPixCrBase[i] << "," <<
353                         (uint32_t)iPixCrRef[i] << ")";
354     }
355 
356     /* Vertical */
357     GENERATE_DATA_DEBLOCKING (iPixCbBase, iPixCbRef, 8)
358     GENERATE_DATA_DEBLOCKING (iPixCrBase, iPixCrRef, 8)
359 
360     anchor_DeblockingChromaNormal (&iPixCbBase[4 * 8], &iPixCrBase[4 * 8], 8, 1, iAlpha, iBeta, iTc);
361     DeblockChromaLt4_c (&iPixCbRef[4 * 8], &iPixCrRef[4 * 8], 8, 1, iAlpha, iBeta, iTc);
362 
363     for (int i = 0; i < 8 * 8; i++) {
364       ASSERT_FALSE (iPixCbBase[i] != iPixCbRef[i]
365                     ||  iPixCrBase[i] != iPixCrRef[i]) << "Vertical Error, (pos, CbBase, CbRef, CrBase, CrRef)-(" << i << "," <<
366                         (uint32_t)iPixCbBase[i] << "," << (uint32_t)iPixCbRef[i] << "," << (uint32_t)iPixCrBase[i] << "," <<
367                         (uint32_t)iPixCrRef[i] << ")";
368     }
369   }
370 }
371 
TEST(DeblockingCommon,DeblockChromaEq4_c)372 TEST (DeblockingCommon, DeblockChromaEq4_c) {
373   // void DeblockChromaEq4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int32_t iStrideY, int32_t iAlpha, int32_t iBeta)
374 #define TEST_CYCLE 1000
375   ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCbBase, 8 * 8, 16);
376   ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCrBase, 8 * 8, 16);
377   ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCbRef, 8 * 8, 16);
378   ENFORCE_STACK_ALIGN_1D (uint8_t, iPixCrRef, 8 * 8, 16);
379 
380   int32_t iAlpha, iBeta;
381 
382   /* NOT used here*/
383   ENFORCE_STACK_ALIGN_1D (int8_t,  iTc,   4, 16);
384 
385   for (int iNum = 0; iNum < TEST_CYCLE; iNum++) {
386     /* Horizontal */
387     GENERATE_DATA_DEBLOCKING (iPixCbBase, iPixCbRef, 8)
388     GENERATE_DATA_DEBLOCKING (iPixCrBase, iPixCrRef, 8)
389 
390     anchor_DeblockingChromaIntra (&iPixCbBase[4 * 1], &iPixCrBase[4 * 1], 1, 8, iAlpha, iBeta);
391     DeblockChromaEq4_c (&iPixCbRef[4 * 1], &iPixCrRef[4 * 1], 1, 8, iAlpha, iBeta);
392 
393     for (int i = 0; i < 8 * 8; i++) {
394       ASSERT_FALSE (iPixCbBase[i] != iPixCbRef[i]
395                     ||  iPixCrBase[i] != iPixCrRef[i]) << "Horizontal Error, (pos, CbBase, CbRef, CrBase, CrRef)-(" << i << "," <<
396                         (uint32_t)iPixCbBase[i] << "," << (uint32_t)iPixCbRef[i] << "," << (uint32_t)iPixCrBase[i] << "," <<
397                         (uint32_t)iPixCrRef[i] << ")";
398     }
399 
400     /* Vertical */
401     GENERATE_DATA_DEBLOCKING (iPixCbBase, iPixCbRef, 8)
402     GENERATE_DATA_DEBLOCKING (iPixCrBase, iPixCrRef, 8)
403 
404     anchor_DeblockingChromaIntra (&iPixCbBase[4 * 8], &iPixCrBase[4 * 8], 8, 1, iAlpha, iBeta);
405     DeblockChromaEq4_c (&iPixCbRef[4 * 8], &iPixCrRef[4 * 8], 8, 1, iAlpha, iBeta);
406 
407     for (int i = 0; i < 8 * 8; i++) {
408       ASSERT_FALSE (iPixCbBase[i] != iPixCbRef[i]
409                     ||  iPixCrBase[i] != iPixCrRef[i]) << "Vertical Error, (pos, CbBase, CbRef, CrBase, CrRef)-(" << i << "," <<
410                         (uint32_t)iPixCbBase[i] << "," << (uint32_t)iPixCbRef[i] << "," << (uint32_t)iPixCrBase[i] << "," <<
411                         (uint32_t)iPixCrRef[i] << ")";
412     }
413   }
414 }
415 
416 /////////// Logic call functions
TEST(DecoderDeblocking,DeblockingAvailableNoInterlayer)417 TEST (DecoderDeblocking, DeblockingAvailableNoInterlayer) {
418   // DeblockingAvailableNoInterlayer (PDqLayer pCurDqLayer, int32_t iFilterIdc)
419   SDqLayer sLayer;
420   int32_t iFilterIdc;
421   int32_t iSliceIdc[9];
422 
423   sLayer.pSliceIdc = iSliceIdc;
424 
425   /* iFilterIdc only support 0 and 2, which is related with the encode configuration */
426   /* Using 3x3 grids to simulate the different situations */
427 
428 #define UT_DBAvailable_idc_0(iX, iY, iExpect) \
429   iFilterIdc = 0; \
430   sLayer.iMbX = iX; \
431   sLayer.iMbY = iY; \
432   sLayer.iMbXyIndex =  sLayer.iMbX + sLayer.iMbY*3; \
433   sLayer.iMbWidth = 3; \
434   EXPECT_TRUE(DeblockingAvailableNoInterlayer (&sLayer, iFilterIdc)==iExpect);
435 
436 #define UT_DBAvailable_idc_2_same_slice(iX, iY, iExpect) \
437   iFilterIdc = 2; \
438   sLayer.iMbX = iX; \
439   sLayer.iMbY = iY; \
440   sLayer.iMbXyIndex =  sLayer.iMbX + sLayer.iMbY*3; \
441   sLayer.iMbWidth = 3; \
442   iSliceIdc[0] = rand()%10; \
443   for (int i=1; i<9; i++) { \
444     iSliceIdc[i] = iSliceIdc[0]; \
445   } \
446   EXPECT_TRUE(DeblockingAvailableNoInterlayer (&sLayer, iFilterIdc)==iExpect)<<"Same Slice";
447 
448 #define UT_DBAvailable_idc_2_diff_slice(iX, iY, iExpect) \
449   iFilterIdc = 2; \
450   sLayer.iMbX = iX; \
451   sLayer.iMbY = iY; \
452   sLayer.iMbXyIndex =  sLayer.iMbX + sLayer.iMbY*3; \
453   sLayer.iMbWidth = 3; \
454   for (int i=0; i<9; i++) { \
455     iSliceIdc[i] = i; \
456   } \
457   EXPECT_TRUE(DeblockingAvailableNoInterlayer (&sLayer, iFilterIdc)==iExpect)<<"Different Slice";
458 
459   // (1) idc==0
460   UT_DBAvailable_idc_0 (0, 0, 0x00)
461   UT_DBAvailable_idc_0 (0, 1, 0x02)
462   UT_DBAvailable_idc_0 (0, 2, 0x02)
463   UT_DBAvailable_idc_0 (1, 0, 0x01)
464   UT_DBAvailable_idc_0 (1, 1, 0x03)
465   UT_DBAvailable_idc_0 (1, 2, 0x03)
466   UT_DBAvailable_idc_0 (2, 0, 0x01)
467   UT_DBAvailable_idc_0 (2, 1, 0x03)
468   UT_DBAvailable_idc_0 (2, 2, 0x03)
469 
470   // (2) idc==2, same slice
471   UT_DBAvailable_idc_2_same_slice (0, 0, 0x00)
472   UT_DBAvailable_idc_2_same_slice (0, 1, 0x02)
473   UT_DBAvailable_idc_2_same_slice (0, 2, 0x02)
474   UT_DBAvailable_idc_2_same_slice (1, 0, 0x01)
475   UT_DBAvailable_idc_2_same_slice (1, 1, 0x03)
476   UT_DBAvailable_idc_2_same_slice (1, 2, 0x03)
477   UT_DBAvailable_idc_2_same_slice (2, 0, 0x01)
478   UT_DBAvailable_idc_2_same_slice (2, 1, 0x03)
479   UT_DBAvailable_idc_2_same_slice (2, 2, 0x03)
480 
481   // (3) idc==3, diff slice
482   UT_DBAvailable_idc_2_diff_slice (0, 0, 0x00)
483   UT_DBAvailable_idc_2_diff_slice (0, 1, 0x00)
484   UT_DBAvailable_idc_2_diff_slice (0, 2, 0x00)
485   UT_DBAvailable_idc_2_diff_slice (1, 0, 0x00)
486   UT_DBAvailable_idc_2_diff_slice (1, 1, 0x00)
487   UT_DBAvailable_idc_2_diff_slice (1, 2, 0x00)
488   UT_DBAvailable_idc_2_diff_slice (2, 0, 0x00)
489   UT_DBAvailable_idc_2_diff_slice (2, 1, 0x00)
490   UT_DBAvailable_idc_2_diff_slice (2, 2, 0x00)
491 }
492 
TEST(DecoderDeblocking,DeblockingInit)493 TEST (DecoderDeblocking, DeblockingInit) {
494   // void  DeblockingInit (PDeblockingFunc pDeblockingFunc,  int32_t iCpu)
495   SDeblockingFunc sDBFunc;
496   memset (&sDBFunc, 0, sizeof (SDeblockingFunc));
497 
498 #define DB_FUNC_CPUFLAG(idx) \
499   EXPECT_TRUE(sDBFunc.pfLumaDeblockingLT4Ver == &DeblockLumaLt4V_##idx); \
500   EXPECT_TRUE(sDBFunc.pfLumaDeblockingEQ4Ver == &DeblockLumaEq4V_##idx); \
501   EXPECT_TRUE(sDBFunc.pfLumaDeblockingLT4Hor == &DeblockLumaLt4H_##idx); \
502   EXPECT_TRUE(sDBFunc.pfLumaDeblockingEQ4Hor == &DeblockLumaEq4H_##idx); \
503   EXPECT_TRUE(sDBFunc.pfChromaDeblockingLT4Ver == &DeblockChromaLt4V_##idx); \
504   EXPECT_TRUE(sDBFunc.pfChromaDeblockingEQ4Ver == &DeblockChromaEq4V_##idx); \
505   EXPECT_TRUE(sDBFunc.pfChromaDeblockingLT4Hor == &DeblockChromaLt4H_##idx); \
506   EXPECT_TRUE(sDBFunc.pfChromaDeblockingEQ4Hor == &DeblockChromaEq4H_##idx);
507 
508 #ifndef X86_ASM
509   // pure C
510   DeblockingInit (&sDBFunc, 0x00000000);
511   DB_FUNC_CPUFLAG (c)
512 #endif
513 
514 #ifdef X86_ASM
515   // pure C
516   DeblockingInit (&sDBFunc, 0x00000000);
517   DB_FUNC_CPUFLAG (c)
518 
519   // SSE3
520   DeblockingInit (&sDBFunc, 0x00000200);
521   DB_FUNC_CPUFLAG (ssse3)
522 #endif
523 
524 #ifdef HAVE_NEON
525   // pure C
526   DeblockingInit (&sDBFunc, 0x00000000);
527   DB_FUNC_CPUFLAG (c)
528 
529   // NEON
530   DeblockingInit (&sDBFunc, 0x000004);
531   DB_FUNC_CPUFLAG (neon)
532 #endif
533 
534 #ifdef HAVE_NEON_AARCH64
535   // pure C
536   DeblockingInit (&sDBFunc, 0x00000000);
537   DB_FUNC_CPUFLAG (c)
538 
539   // NEON_AARCH64
540   DeblockingInit (&sDBFunc, 0x000004);
541   DB_FUNC_CPUFLAG (AArch64_neon)
542 #endif
543 
544 #ifdef HAVE_MMI
545   // pure C
546   DeblockingInit (&sDBFunc, 0x00000000);
547   DB_FUNC_CPUFLAG (c)
548 
549   // mmi
550   DeblockingInit (&sDBFunc, 0x00000001);
551   DB_FUNC_CPUFLAG (mmi)
552 #endif
553 
554 }
555 
TEST(DecoderDeblocking,WelsDeblockingFilterSlice)556 TEST (DecoderDeblocking, WelsDeblockingFilterSlice) {
557   // void WelsDeblockingFilterSlice (PWelsDecoderContext pCtx, PDeblockingFilterMbFunc pDeblockMb)
558 
559   /* NOT support FMO now */
560   SWelsDecoderContext sCtx;
561   SDqLayer sDqLayer;
562   SSps sSPS;
563   SPps sPPS;
564   SPicture sDec;
565   PDeblockingFilterMbFunc pDeblockMb = &UT_DeblockingFuncInterface;
566 
567   /* NOT do actual deblocking process, set related parameters to null */
568   sCtx.pDec = &sDec;
569   sCtx.pDec->iLinesize[0] = sCtx.pDec->iLinesize[1] = sCtx.pDec->iLinesize[2] = 0;
570   sCtx.pDec->pData[0] = sCtx.pDec->pData[1] = sCtx.pDec->pData[2] = NULL;
571 
572   /* As no FMO in encoder now, the multi slicegroups has not been set */
573   sCtx.pFmo = NULL;
574 
575   sCtx.pCurDqLayer = &sDqLayer;
576   /* As void return, using iMbXyIndex to reflect whether the all MBs have been passed. */
577   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice = 0;
578   sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = 0;
579 
580   // whether disable Deblocking Filter Idc
581   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.uiDisableDeblockingFilterIdc = 0;
582   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iSliceAlphaC0Offset = 0;
583   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iSliceBetaOffset = 0;
584 
585   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps = &sSPS;
586   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount = 0;
587 
588   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pPps = &sPPS;
589   /* Only test one slicegroup, not reflect the FMO func */
590   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pPps->uiNumSliceGroups = 1;
591 
592   // (1) Normal case, the iTotalMbInCurSlice == pSps->uiTotalMbCount
593   sDqLayer.iMbX = sDqLayer.iMbY = 0;
594   sDqLayer.iMbXyIndex = 0;
595   sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = 1 + rand() % 256; // at least one MB
596   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount =
597     sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice;
598   sDqLayer.iMbWidth = 1 + rand() % 128;
599   WelsDeblockingFilterSlice (&sCtx, pDeblockMb);
600   EXPECT_TRUE ((sDqLayer.iMbXyIndex + 1) == sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice) << sDqLayer.iMbXyIndex
601       << " " << sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice;
602 
603   // (2) Normal case, multi slices, iTotalMbInCurSlice <= pSps->uiTotalMbCount
604   sDqLayer.iMbX = sDqLayer.iMbY = 0;
605   sDqLayer.iMbXyIndex = 0;
606   sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = 1 + rand() % 256;
607   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount =
608     sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice + rand() % 256;
609   sDqLayer.iMbWidth = 1 + rand() % 128;
610   WelsDeblockingFilterSlice (&sCtx, pDeblockMb);
611   EXPECT_TRUE ((sDqLayer.iMbXyIndex + 1) == sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice);
612 
613   // (3) Special case, iTotalMbInCurSlice >= pSps->uiTotalMbCount, JUST FOR TEST
614   sDqLayer.iMbX = sDqLayer.iMbY = 0;
615   sDqLayer.iMbXyIndex = 0;
616   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount = 1 + rand() % 256;
617   sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice =
618     sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount + rand() % 256;
619   sDqLayer.iMbWidth = 1 + rand() % 128;
620   WelsDeblockingFilterSlice (&sCtx, pDeblockMb);
621   EXPECT_TRUE ((uint32_t) (sDqLayer.iMbXyIndex + 1) ==
622                sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount);
623 
624   // (4) Special case, uiDisableDeblockingFilterIdc==1, disable deblocking
625   sDqLayer.iMbX = sDqLayer.iMbY = 0;
626   sDqLayer.iMbXyIndex = 0;
627   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.uiDisableDeblockingFilterIdc = 1;
628   sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice = 1 + rand() % 256;
629   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->uiTotalMbCount =
630     sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice;
631   sDqLayer.iMbWidth = 1 + rand() % 128;
632   WelsDeblockingFilterSlice (&sCtx, pDeblockMb);
633   EXPECT_TRUE (sDqLayer.iMbXyIndex == 0) << sDqLayer.iMbXyIndex << " " <<
634                                          sDqLayer.sLayerInfo.sSliceInLayer.iTotalMbInCurSlice;
635 
636 }
637 
TEST(DecoderDeblocking,FilteringEdgeChromaHV)638 TEST (DecoderDeblocking, FilteringEdgeChromaHV) {
639   // void FilteringEdgeChromaHV (PDqLayer pCurDqLayer, PDeblockingFilter  pFilter, int32_t iBoundryFlag)
640   SDqLayer sDqLayer;
641   SDeblockingFilter sFilter;
642   int32_t iBoundryFlag = 0x01;
643   int32_t iQP;
644 
645   memset (&sDqLayer, 0, sizeof (SDqLayer));
646   memset (&sFilter, 0, sizeof (SDeblockingFilter));
647 
648   SDeblockingFunc sDBFunc;
649   sFilter.pLoopf = &sDBFunc;
650   sFilter.pLoopf->pfChromaDeblockingLT4Hor = &UT_DeblockingFuncChromaLT4Func;
651   sFilter.pLoopf->pfChromaDeblockingLT4Ver = &UT_DeblockingFuncChromaLT4Func;
652   sFilter.pLoopf->pfChromaDeblockingEQ4Hor = &UT_DeblockingFuncChromaEQ4Func;
653   sFilter.pLoopf->pfChromaDeblockingEQ4Ver = &UT_DeblockingFuncChromaEQ4Func;
654 
655   int8_t iChromaQP[9][2];
656   sDqLayer.pChromaQp = iChromaQP;
657 
658   uint8_t iCb[9] = {0};
659   uint8_t iCr[9] = {0};
660   sFilter.pCsData[1] = iCb;
661   sFilter.pCsData[2] = iCr;
662   sFilter.iCsStride[0] = sFilter.iCsStride[1] = 2;
663 
664   sDqLayer.iMbX = 0;
665   sDqLayer.iMbY = 0; //Only for test easy
666   sDqLayer.iMbXyIndex = 1;  // this function has NO iMbXyIndex validation
667 
668 #define UT_DB_CHROMA_TEST(iFlag, iQP, iV0, iV1, iV2) \
669   iBoundryFlag = iFlag; \
670   memset(iChromaQP, iQP, sizeof(int8_t)*9*2); \
671   memset(iCb, 0, sizeof(uint8_t)*9); \
672   memset(iCr, 0, sizeof(uint8_t)*9); \
673   FilteringEdgeChromaHV(&sDqLayer, &sFilter, iBoundryFlag); \
674   EXPECT_TRUE(iCb[0]==iV0 && iCr[0]==iV0); \
675   EXPECT_TRUE(iCb[2<<1]==iV1 && iCr[2<<1]==iV1); \
676   EXPECT_TRUE(iCb[(2<<1)*sFilter.iCsStride[1]]==iV2 && iCr[(2<<1)*sFilter.iCsStride[1]]==iV2);
677 
678   // QP<=15, iAlpha == iBeta == 0, TOP & LEFT
679   iQP = rand() % 16;
680   UT_DB_CHROMA_TEST (0x03, iQP, 0, 0, 0)
681 
682   // QP>=16, iAlpha>0 && iBeta>0, TOP & LEFT
683   iQP = 16 + rand() % 35;
684   UT_DB_CHROMA_TEST (0x03, iQP, 2, 1, 1)
685 
686   // QP<=15, iAlpha == iBeta == 0, TOP | LEFT
687   iQP = rand() % 16;
688   UT_DB_CHROMA_TEST (0x01, iQP, 0, 0, 0)
689   iQP = rand() % 16;
690   UT_DB_CHROMA_TEST (0x02, iQP, 0, 0, 0)
691 
692   // QP>=16, iAlpha>0 && iBeta>0, TOP | LEFT
693   iQP = 16 + rand() % 35;
694   UT_DB_CHROMA_TEST (0x01, iQP, 1, 1, 1)
695   iQP = 16 + rand() % 35;
696   UT_DB_CHROMA_TEST (0x02, iQP, 1, 1, 1)
697 
698   // QP<=15, iAlpha == iBeta == 0, !TOP & !LEFT
699   iQP = rand() % 16;
700   UT_DB_CHROMA_TEST (0x00, iQP, 0, 0, 0)
701 
702   // QP>=16, iAlpha>0 && iBeta>0, !TOP & !LEFT
703   iQP = 16 + rand() % 35;
704   UT_DB_CHROMA_TEST (0x00, iQP, 0, 1, 1)
705 }
706 
TEST(DecoderDeblocking,FilteringEdgeLumaHV)707 TEST (DecoderDeblocking, FilteringEdgeLumaHV) {
708   // void FilteringEdgeLumaHV (PDqLayer pCurDqLayer, PDeblockingFilter  pFilter, int32_t iBoundryFlag)
709   SDqLayer sDqLayer;
710   SDeblockingFilter sFilter;
711   int32_t iBoundryFlag = 0x03;
712   int32_t iQP;
713 
714   memset (&sDqLayer, 0, sizeof (SDqLayer));
715   memset (&sFilter, 0, sizeof (SDeblockingFilter));
716 
717   SDeblockingFunc sDBFunc;
718   sFilter.pLoopf = &sDBFunc;
719   sFilter.pLoopf->pfLumaDeblockingLT4Hor = &UT_DeblockingFuncLumaLT4Func;
720   sFilter.pLoopf->pfLumaDeblockingEQ4Hor = &UT_DeblockingFuncLumaEQ4Func;
721   sFilter.pLoopf->pfLumaDeblockingLT4Ver = &UT_DeblockingFuncLumaLT4Func;
722   sFilter.pLoopf->pfLumaDeblockingEQ4Ver = &UT_DeblockingFuncLumaEQ4Func;
723 
724   int8_t iLumaQP[50];
725   sDqLayer.pLumaQp = iLumaQP;
726 
727   uint8_t iY[50] = {0};
728   sFilter.pCsData[0] = iY;
729   sFilter.iCsStride[0] = sFilter.iCsStride[1] = 4;
730 
731   sDqLayer.iMbX = 0;
732   sDqLayer.iMbY = 0; //Only for test easy
733   sDqLayer.iMbXyIndex = 1;  // this function has NO iMbXyIndex validation
734 
735   bool bTSize8x8Flag[50] = {false};
736   sDqLayer.pTransformSize8x8Flag = bTSize8x8Flag;
737   sDqLayer.pTransformSize8x8Flag[sDqLayer.iMbXyIndex] = false;
738 
739 #define UT_DB_LUMA_TEST(iFlag, iQP, iV0, iV1, iV2) \
740   iBoundryFlag = iFlag; \
741   memset(iLumaQP, iQP, sizeof(int8_t)*50); \
742   memset(iY, 0, sizeof(uint8_t)*50); \
743   FilteringEdgeLumaHV(&sDqLayer, &sFilter, iBoundryFlag); \
744   EXPECT_TRUE(iY[0]==iV0); \
745   EXPECT_TRUE(iY[1<<2]==iV1 && iY[2<<2]==iV1 && iY[3<<2]==iV1); \
746   EXPECT_TRUE(iY[(1 << 2)*sFilter.iCsStride[0]]==iV2 && iY[(2 << 2)*sFilter.iCsStride[0]]==iV2 && iY[(3 << 2)*sFilter.iCsStride[0]]==iV2);
747 
748   // QP<=15, iAlpha == iBeta == 0, TOP & LEFT
749   iQP = rand() % 16;
750   UT_DB_LUMA_TEST (0x03, iQP, 0, 0, 0)
751 
752   // QP>=16, iAlpha>0 && iBeta>0, TOP & LEFT
753   iQP = 16 + rand() % 35;
754   UT_DB_LUMA_TEST (0x03, iQP, 2, 1, 1)
755 
756   // QP<=15, iAlpha == iBeta == 0, TOP | LEFT
757   iQP = rand() % 16;
758   UT_DB_LUMA_TEST (0x01, iQP, 0, 0, 0)
759   iQP = rand() % 16;
760   UT_DB_LUMA_TEST (0x02, iQP, 0, 0, 0)
761 
762   // QP>=16, iAlpha>0 && iBeta>0, TOP | LEFT
763   iQP = 16 + rand() % 35;
764   UT_DB_LUMA_TEST (0x01, iQP, 1, 1, 1)
765   iQP = 16 + rand() % 35;
766   UT_DB_LUMA_TEST (0x02, iQP, 1, 1, 1)
767 
768   // QP<=15, iAlpha == iBeta == 0, !TOP & !LEFT
769   iQP = rand() % 16;
770   UT_DB_LUMA_TEST (0x00, iQP, 0, 0, 0)
771 
772   // QP>=16, iAlpha>0 && iBeta>0, !TOP & !LEFT
773   iQP = 16 + rand() % 35;
774   UT_DB_LUMA_TEST (0x00, iQP, 0, 1, 1)
775 }
776 
777 /////////// Bs calculation functions
TEST(DecoderDeblocking,DeblockingBsMarginalMBAvcbase)778 TEST (DecoderDeblocking, DeblockingBsMarginalMBAvcbase) {
779   // uint32_t DeblockingBsMarginalMBAvcbase (PDeblockingFilter pFilter, PDqLayer pCurDqLayer, int32_t iEdge, int32_t iNeighMb, int32_t iMbXy)
780   /* Calculate the Bs equal to 2 or 1 */
781   SDqLayer sDqLayer;
782   SDeblockingFilter sFilter;
783   int i;
784 
785   // Only define 2 MBs here
786   int8_t iNoZeroCount[24 * 2]; // (*pNzc)[24]
787   int8_t iLayerRefIndex[2][16 * 2]; // (*pRefIndex[LIST_A])[MB_BLOCK4x4_NUM];
788   int16_t iLayerMv[2][16 * 2][2]; //(*pMv[LIST_A])[MB_BLOCK4x4_NUM][MV_A];
789   uint32_t uiBSx4;
790   uint8_t* pBS = (uint8_t*) (&uiBSx4);
791 
792   PPicture iFilterPics[2][MAX_DPB_COUNT]; // Dummy reference pictures list
793 
794   sDqLayer.pNzc = (int8_t (*)[24])iNoZeroCount;
795   sDqLayer.pRefIndex[0] = (int8_t (*)[16])&iLayerRefIndex[0];
796   sDqLayer.pRefIndex[1] = (int8_t (*)[16])&iLayerRefIndex[1];
797 
798   sDqLayer.pMv[0] = (int16_t (*) [16][2])&iLayerMv[0];
799   sDqLayer.pMv[1] = (int16_t (*) [16][2])&iLayerMv[1];
800 
801   bool bTSize8x8Flag[50] = {false};
802   sDqLayer.pTransformSize8x8Flag = bTSize8x8Flag;
803   memset (bTSize8x8Flag, 0, sizeof (bool) * 50);
804   // Dummy picture list pointers to 1..MAX_DPB_COUNT
805   // the pointer values don't need to be valid, just different
806   for (i = 0; i < MAX_DPB_COUNT; i++)
807     iFilterPics[0][i] = iFilterPics[1][i] = (PPicture) (iFilterPics[0] + i);
808 
809   sFilter.pRefPics[0] = iFilterPics[0];
810   sFilter.pRefPics[1] = iFilterPics[1];
811   sDqLayer.pDec = NULL;
812 #define UT_DB_CLEAN_STATUS \
813   memset(iNoZeroCount, 0, sizeof(int8_t)*24*2); \
814   memset(iLayerRefIndex, 0, sizeof(int8_t)*2*16*2); \
815   memset(iLayerMv, 0, sizeof(int16_t)*2*16*2*2);
816 
817 #define SET_REF_VALUE(value, pos) \
818   uiBSx4 = 0; \
819   pBS[pos] = value;
820 
821   int32_t iCurrBlock, iNeighborBlock;
822 
823   /* Cycle for each block and its neighboring block */
824   for (int iEdge = 0; iEdge < 2; iEdge++) { // Vertical and Horizontal
825     for (int iPos = 0; iPos < 4; iPos++) { // Four different blocks on the edge
826       iCurrBlock = (iEdge == 0 ? 4 * iPos : iPos);
827       iNeighborBlock = (iEdge == 0 ? (3 + iPos * 4) : (12 + iPos));
828 
829       // (1) iEdge == 0, current block NoZeroCount != 0
830       UT_DB_CLEAN_STATUS
831       iNoZeroCount[0 * 24 + iCurrBlock] = 1; // Current MB_block position
832       SET_REF_VALUE (2, iPos);
833       EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sFilter, &sDqLayer, iEdge, 1,
834                    0) == uiBSx4) << iEdge << " " << iPos << " NoZeroCount!=0";
835 
836       // (2) iEdge == 0, neighbor block NoZeroCount != 0
837       UT_DB_CLEAN_STATUS
838       iNoZeroCount[1 * 24 + iNeighborBlock ] = 1; // Neighbor MB_block position
839       SET_REF_VALUE (2, iPos);
840       EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sFilter, &sDqLayer, iEdge, 1,
841                    0) == uiBSx4) << iEdge << " " << iPos << " NoZeroCount!=0";
842 
843       // (3) iEdge == 0, reference idx diff
844       UT_DB_CLEAN_STATUS
845       iLayerRefIndex[0][0 * 16 + iCurrBlock] = 0;
846       iLayerRefIndex[0][1 * 16 + iNeighborBlock] = 1;
847       SET_REF_VALUE (1, iPos);
848       EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sFilter, &sDqLayer, iEdge, 1,
849                    0) == uiBSx4) << iEdge << " " << iPos << " Ref idx diff";
850 
851       // (4) iEdge == 0, abs(mv diff) < 4
852       UT_DB_CLEAN_STATUS
853       iLayerMv[0][0 * 16 + iCurrBlock][0] = rand() % 4;
854       EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sFilter, &sDqLayer, iEdge, 1,
855                    0) == 0) << iEdge << " " << iPos << " diff_mv < 4";
856 
857       UT_DB_CLEAN_STATUS
858       iLayerMv[0][0 * 16 + iCurrBlock][1] = rand() % 4;
859       EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sFilter, &sDqLayer, iEdge, 1,
860                    0) == 0) << iEdge << " " << iPos << " diff_mv < 4";
861 
862       UT_DB_CLEAN_STATUS
863       iLayerMv[0][1 * 16 + iNeighborBlock][0] = rand() % 4;
864       EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sFilter, &sDqLayer, iEdge, 1,
865                    0) == 0) << iEdge << " " << iPos << " diff_mv < 4";
866 
867       UT_DB_CLEAN_STATUS
868       iLayerMv[0][1 * 16 + iNeighborBlock][1] = rand() % 4;
869       EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sFilter, &sDqLayer, iEdge, 1,
870                    0) == 0) << iEdge << " " << iPos << " diff_mv < 4";
871 
872       // (5) iEdge == 0, abs(mv diff) > 4
873       UT_DB_CLEAN_STATUS
874       iLayerMv[0][0 * 16 + iCurrBlock][0] = 4;
875       SET_REF_VALUE (1, iPos);
876       EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sFilter, &sDqLayer, iEdge, 1,
877                    0) == uiBSx4) << iEdge << " " << iPos << " diff_mv == 4";
878 
879       UT_DB_CLEAN_STATUS
880       iLayerMv[0][0 * 16 + iCurrBlock][1] = 4;
881       SET_REF_VALUE (1, iPos);
882       EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sFilter, &sDqLayer, iEdge, 1,
883                    0) == uiBSx4) << iEdge << " " << iPos << " diff_mv == 4";
884 
885       UT_DB_CLEAN_STATUS
886       iLayerMv[0][1 * 16 + iNeighborBlock][0] = 4;
887       SET_REF_VALUE (1, iPos);
888       EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sFilter, &sDqLayer, iEdge, 1,
889                    0) == uiBSx4) << iEdge << " " << iPos << " diff_mv == 4";
890 
891       UT_DB_CLEAN_STATUS
892       iLayerMv[0][1 * 16 + iNeighborBlock][1] = 4;
893       SET_REF_VALUE (1, iPos);
894       EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sFilter, &sDqLayer, iEdge, 1,
895                    0) == uiBSx4) << iEdge << " " << iPos << " diff_mv == 4";
896 
897       UT_DB_CLEAN_STATUS
898       iLayerMv[0][0 * 16 + iCurrBlock][0] = -2048;
899       iLayerMv[0][1 * 16 + iNeighborBlock][0] = 2047;
900       SET_REF_VALUE (1, iPos);
901       EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sFilter, &sDqLayer, iEdge, 1,
902                    0) == uiBSx4) << iEdge << " " << iPos << " diff_mv == maximum";
903 
904       UT_DB_CLEAN_STATUS
905       iLayerMv[0][0 * 16 + iCurrBlock][1] = -2048;
906       iLayerMv[0][1 * 16 + iNeighborBlock][1] = 2047;
907       SET_REF_VALUE (1, iPos);
908       EXPECT_TRUE (DeblockingBsMarginalMBAvcbase (&sFilter, &sDqLayer, iEdge, 1,
909                    0) == uiBSx4) << iEdge << " " << iPos << " diff_mv == maximum";
910     }
911   }
912 }
913 
TEST(Deblocking,WelsDeblockingMb)914 TEST (Deblocking, WelsDeblockingMb) {
915   // void WelsDeblockingMb (PDqLayer pCurDqLayer, PDeblockingFilter  pFilter, int32_t iBoundryFlag)
916   /* Deblock one MB, calculate the Bs inside the function, only consider the intra / intra block */
917   SDqLayer sDqLayer;
918   sDqLayer.sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.eSliceType = P_SLICE;
919   sDqLayer.pDec = NULL;
920   SDeblockingFilter sFilter;
921   SDeblockingFunc sDBFunc;
922   sFilter.pLoopf = &sDBFunc;
923   sFilter.pLoopf->pfChromaDeblockingLT4Hor = &UT_DeblockingFuncChromaLT4Func;
924   sFilter.pLoopf->pfChromaDeblockingLT4Ver = &UT_DeblockingFuncChromaLT4Func;
925   sFilter.pLoopf->pfChromaDeblockingEQ4Hor = &UT_DeblockingFuncChromaEQ4Func;
926   sFilter.pLoopf->pfChromaDeblockingEQ4Ver = &UT_DeblockingFuncChromaEQ4Func;
927   sFilter.pLoopf->pfLumaDeblockingLT4Hor = &UT_DeblockingFuncLumaLT4Func;
928   sFilter.pLoopf->pfLumaDeblockingEQ4Hor = &UT_DeblockingFuncLumaEQ4Func;
929   sFilter.pLoopf->pfLumaDeblockingLT4Ver = &UT_DeblockingFuncLumaLT4Func;
930   sFilter.pLoopf->pfLumaDeblockingEQ4Ver = &UT_DeblockingFuncLumaEQ4Func;
931   sFilter.pRefPics[0] = sFilter.pRefPics[1] = NULL; // Don't need Ref pics for intra tests
932 
933   sDqLayer.iMbX = sDqLayer.iMbY = 0;
934   sDqLayer.iMbXyIndex = 1;
935   sDqLayer.iMbWidth = 1;
936 
937   bool bTSize8x8Flag[50] = {false};
938   sDqLayer.pTransformSize8x8Flag = bTSize8x8Flag;
939   memset (bTSize8x8Flag, 0, sizeof (bool) * 50);
940 
941   uint8_t iY[50] = {0};
942   sFilter.pCsData[0] = iY;
943   sFilter.iCsStride[0] = 4;
944 
945   uint8_t iCb[9] = {0};
946   uint8_t iCr[9] = {0};
947   sFilter.pCsData[1] = iCb;
948   sFilter.pCsData[2] = iCr;
949   sFilter.iCsStride[1] = 2;
950 
951   int8_t iLumaQP[50] = {0};
952   int8_t iChromaQP[9][2] = {{0, 0}};
953   sDqLayer.pLumaQp = iLumaQP;
954   sDqLayer.pChromaQp = iChromaQP;
955 
956   uint32_t iMbType[2];
957   sDqLayer.pMbType = iMbType;
958   sDqLayer.pMbType[0] = MB_TYPE_INTRA4x4;
959   sDqLayer.pMbType[1] = MB_TYPE_INTRA4x4;
960 
961   sFilter.iSliceAlphaC0Offset = 0;
962   sFilter.iSliceBetaOffset = 0;
963 
964   int32_t iQP;
965 
966 #define UT_DB_MACROBLOCK_TEST( iBoundFlag, iQP, iLumaV0, iLumaV1, iLumaV2, iChromaV0, iChromaV1, iChromaV2 ) \
967   memset(sDqLayer.pLumaQp, iQP, sizeof(int8_t)*50); \
968   memset(sDqLayer.pChromaQp, iQP, sizeof(int8_t)*9*2); \
969   memset(sFilter.pCsData[0], 0, sizeof(int8_t)*50); \
970   memset(sFilter.pCsData[1], 0, sizeof(int8_t)*9); \
971   memset(sFilter.pCsData[2], 0, sizeof(int8_t)*9); \
972   WelsDeblockingMb(&sDqLayer, &sFilter, iBoundFlag ); \
973   EXPECT_TRUE(iY[0]==iLumaV0)<<iQP<<" "<<sDqLayer.pMbType[1]; \
974   EXPECT_TRUE(iY[1<<2]==iLumaV1 && iY[2<<2]==iLumaV1 && iY[3<<2]==iLumaV1)<<iQP<<" "<<sDqLayer.pMbType[1]; \
975   EXPECT_TRUE(iY[(1 << 2)*sFilter.iCsStride[0]]==iLumaV2 && iY[(2 << 2)*sFilter.iCsStride[0]]==iLumaV2 && iY[(3 << 2)*sFilter.iCsStride[0]]==iLumaV2)<<iQP<<" "<<sDqLayer.pMbType[1]; \
976   EXPECT_TRUE(iCb[0]==iChromaV0 && iCr[0]==iChromaV0)<<iQP<<" "<<sDqLayer.pMbType[1]; \
977   EXPECT_TRUE(iCb[2<<1]==iChromaV1 && iCr[2<<1]==iChromaV1)<<iQP<<" "<<sDqLayer.pMbType[1]; \
978   EXPECT_TRUE(iCb[(2<<1)*sFilter.iCsStride[1]]==iChromaV2 && iCr[(2<<1)*sFilter.iCsStride[1]]==iChromaV2)<<iQP<<" "<<sDqLayer.pMbType[1];
979 
980   // QP>16, LEFT & TOP, Intra mode MB_TYPE_INTRA4x4
981   iQP = 16 + rand() % 35;
982   sDqLayer.pMbType[1] = MB_TYPE_INTRA4x4;
983   UT_DB_MACROBLOCK_TEST (0x03, iQP, 2, 1, 1, 2, 1, 1)
984 
985   // QP>16, LEFT & TOP, Intra mode MB_TYPE_INTRA16x16
986   iQP = 16 + rand() % 35;
987   sDqLayer.pMbType[1] = MB_TYPE_INTRA16x16;
988   UT_DB_MACROBLOCK_TEST (0x03, iQP, 2, 1, 1, 2, 1, 1)
989 
990   // MbType==0x03, Intra8x8 has not been supported now.
991 
992   // QP>16, LEFT & TOP, Intra mode MB_TYPE_INTRA_PCM
993   iQP = 16 + rand() % 35;
994   sDqLayer.pMbType[1] = MB_TYPE_INTRA_PCM;
995   UT_DB_MACROBLOCK_TEST (0x03, iQP, 2, 1, 1, 2, 1, 1)
996 
997   // QP>16, LEFT & TOP, neighbor is Intra
998   iQP = 16 + rand() % 35;
999   sDqLayer.pMbType[0] = MB_TYPE_INTRA16x16;
1000   sDqLayer.pMbType[1] = MB_TYPE_SKIP; // Internal SKIP, Bs==0
1001   UT_DB_MACROBLOCK_TEST (0x03, iQP, 2, 0, 0, 2, 0, 0)
1002 
1003   // QP<15, no output
1004   iQP = rand() % 16;
1005   sDqLayer.pMbType[1] = MB_TYPE_INTRA_PCM;
1006   UT_DB_MACROBLOCK_TEST (0x03, iQP, 0, 0, 0, 0, 0, 0)
1007 }
1008