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