Imported Upstream version 1.4
[deb_x265.git] / source / test / mbdstharness.cpp
CommitLineData
72b9787e
JB
1/*****************************************************************************
2 * Copyright (C) 2013 x265 project
3 *
4 * Authors: Steve Borho <steve@borho.org>
5 * Min Chen <min.chen@multicorewareinc.com>
6 * Praveen Kumar Tiwari <praveen@multicorewareinc.com>
7 * Nabajit Deka <nabajit@multicorewareinc.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
22 *
23 * This program is also available under a commercial proprietary license.
24 * For more information, contact us at license @ x265.com.
25 *****************************************************************************/
26
27#include "common.h"
28#include "mbdstharness.h"
29
30using namespace x265;
31
32struct DctConf
33{
34 const char *name;
35 int width;
36};
37
38const DctConf dctInfo[] =
39{
40 { "dst4x4\t", 4 },
41 { "dct4x4\t", 4 },
42 { "dct8x8\t", 8 },
43 { "dct16x16", 16 },
44 { "dct32x32", 32 },
45};
46
47const DctConf idctInfo[] =
48{
49 { "idst4x4\t", 4 },
50 { "idct4x4\t", 4 },
51 { "idct8x8\t", 8 },
52 { "idct16x16", 16 },
53 { "idct32x32", 32 },
54};
55
56MBDstHarness::MBDstHarness()
57{
58 const int idct_max = (1 << (BIT_DEPTH + 4)) - 1;
59
60 /* [0] --- Random values
61 * [1] --- Minimum
62 * [2] --- Maximum */
63 for (int i = 0; i < TEST_BUF_SIZE; i++)
64 {
65 short_test_buff[0][i] = (rand() & PIXEL_MAX) - (rand() & PIXEL_MAX);
66 int_test_buff[0][i] = rand() % PIXEL_MAX;
67 int_idct_test_buff[0][i] = (rand() % (SHORT_MAX - SHORT_MIN)) - SHORT_MAX;
68 int_denoise_test_buff1[0][i] = int_denoise_test_buff2[0][i] = (rand() & UNSIGNED_SHORT_MAX) - (rand() & UNSIGNED_SHORT_MAX);
69
70 short_test_buff[1][i] = -PIXEL_MAX;
71 int_test_buff[1][i] = -PIXEL_MAX;
72 int_idct_test_buff[1][i] = SHORT_MIN;
73 int_denoise_test_buff1[1][i] = int_denoise_test_buff2[1][i] = -UNSIGNED_SHORT_MAX;
74
75 short_test_buff[2][i] = PIXEL_MAX;
76 int_test_buff[2][i] = PIXEL_MAX;
77 int_idct_test_buff[2][i] = SHORT_MAX;
78 int_denoise_test_buff1[2][i] = int_denoise_test_buff2[2][i] = UNSIGNED_SHORT_MAX;
79
80 mbuf1[i] = rand() & PIXEL_MAX;
81 mbufdct[i] = (rand() & PIXEL_MAX) - (rand() & PIXEL_MAX);
82 mbufidct[i] = (rand() & idct_max);
83 }
84
85#if _DEBUG
86 memset(mshortbuf2, 0, MAX_TU_SIZE * sizeof(int16_t));
87 memset(mshortbuf3, 0, MAX_TU_SIZE * sizeof(int16_t));
88
89 memset(mintbuf1, 0, MAX_TU_SIZE * sizeof(int));
90 memset(mintbuf2, 0, MAX_TU_SIZE * sizeof(int));
91 memset(mintbuf3, 0, MAX_TU_SIZE * sizeof(int));
92 memset(mintbuf4, 0, MAX_TU_SIZE * sizeof(int));
93#endif // if _DEBUG
94}
95
96bool MBDstHarness::check_dct_primitive(dct_t ref, dct_t opt, intptr_t width)
97{
98 int j = 0;
99 intptr_t cmp_size = sizeof(int) * width * width;
100
101 for (int i = 0; i < ITERS; i++)
102 {
103 int index = rand() % TEST_CASES;
104
105 ref(short_test_buff[index] + j, mintbuf3, width);
106 checked(opt, short_test_buff[index] + j, mintbuf4, width);
107
108 if (memcmp(mintbuf3, mintbuf4, cmp_size))
109 return false;
110
111 reportfail();
112 j += INCR;
113 }
114
115 return true;
116}
117
118bool MBDstHarness::check_idct_primitive(idct_t ref, idct_t opt, intptr_t width)
119{
120 int j = 0;
121 intptr_t cmp_size = sizeof(int16_t) * width * width;
122
123 for (int i = 0; i < ITERS; i++)
124 {
125 int index = rand() % TEST_CASES;
126
127 ref(int_idct_test_buff[index] + j, mshortbuf2, width);
128 checked(opt, int_idct_test_buff[index] + j, mshortbuf3, width);
129
130 if (memcmp(mshortbuf2, mshortbuf3, cmp_size))
131 return false;
132
133 reportfail();
134 j += INCR;
135 }
136
137 return true;
138}
139
140bool MBDstHarness::check_dequant_primitive(dequant_normal_t ref, dequant_normal_t opt)
141{
142 int j = 0;
143
144 for (int i = 0; i < ITERS; i++)
145 {
146 int index = rand() % TEST_CASES;
147 int log2TrSize = (rand() % 4) + 2;
148
149 int width = (1 << log2TrSize);
150 int height = width;
151 int qp = rand() % (QP_MAX_SPEC + QP_BD_OFFSET + 1);
152 int per = qp / 6;
153 int rem = qp % 6;
154 static const int invQuantScales[6] = { 40, 45, 51, 57, 64, 72 };
155 int scale = invQuantScales[rem] << per;
156 int transformShift = MAX_TR_DYNAMIC_RANGE - X265_DEPTH - log2TrSize;
157 int shift = QUANT_IQUANT_SHIFT - QUANT_SHIFT - transformShift;
158
159 ref(short_test_buff[index] + j, mintbuf3, width * height, scale, shift);
160 checked(opt, short_test_buff[index] + j, mintbuf4, width * height, scale, shift);
161
162 if (memcmp(mintbuf3, mintbuf4, sizeof(int) * height * width))
163 return false;
164
165 reportfail();
166 j += INCR;
167 }
168
169 return true;
170}
171
172bool MBDstHarness::check_dequant_primitive(dequant_scaling_t ref, dequant_scaling_t opt)
173{
174 int j = 0;
175
176 for (int i = 0; i < ITERS; i++)
177 {
178 int log2TrSize = (rand() % 4) + 2;
179
180 int width = (1 << log2TrSize);
181 int height = width;
182
183 int qp = rand() % (QP_MAX_SPEC + QP_BD_OFFSET + 1);
184 int per = qp / 6;
185 int transformShift = MAX_TR_DYNAMIC_RANGE - X265_DEPTH - log2TrSize;
186 int shift = QUANT_IQUANT_SHIFT - QUANT_SHIFT - transformShift;
187
188 int cmp_size = sizeof(int) * height * width;
189 int index1 = rand() % TEST_CASES;
190
191 ref(short_test_buff[index1] + j, mintbuf3, mintbuf1, width * height, per, shift);
192 checked(opt, short_test_buff[index1] + j, mintbuf4, mintbuf2, width * height, per, shift);
193
194 if (memcmp(mintbuf1, mintbuf2, cmp_size))
195 return false;
196
197 reportfail();
198 j += INCR;
199 }
200
201 return true;
202}
203
204bool MBDstHarness::check_quant_primitive(quant_t ref, quant_t opt)
205{
206 int j = 0;
207
208 for (int i = 0; i < ITERS; i++)
209 {
210 int width = (rand() % 4 + 1) * 4;
211 int height = width;
212
213 uint32_t optReturnValue = 0;
214 uint32_t refReturnValue = 0;
215
216 int bits = (rand() % 24) + 8;
217 int valueToAdd = rand() % (1 << bits);
218 int cmp_size = sizeof(int) * height * width;
219 int cmp_size1 = sizeof(short) * height * width;
220 int numCoeff = height * width;
221
222 int index1 = rand() % TEST_CASES;
223 int index2 = rand() % TEST_CASES;
224
225 refReturnValue = ref(int_test_buff[index1] + j, int_test_buff[index2] + j, mintbuf1, mshortbuf2, bits, valueToAdd, numCoeff);
226 optReturnValue = (uint32_t)checked(opt, int_test_buff[index1] + j, int_test_buff[index2] + j, mintbuf3, mshortbuf3, bits, valueToAdd, numCoeff);
227
228 if (memcmp(mintbuf1, mintbuf3, cmp_size))
229 return false;
230
231 if (memcmp(mshortbuf2, mshortbuf3, cmp_size1))
232 return false;
233
234 if (optReturnValue != refReturnValue)
235 return false;
236
237 reportfail();
238 j += INCR;
239 }
240
241 return true;
242}
243
244bool MBDstHarness::check_nquant_primitive(nquant_t ref, nquant_t opt)
245{
246 int j = 0;
247
248 for (int i = 0; i < ITERS; i++)
249 {
250 int width = (rand() % 4 + 1) * 4;
251 int height = width;
252
253 uint32_t optReturnValue = 0;
254 uint32_t refReturnValue = 0;
255
256 int bits = rand() % 32;
257 int valueToAdd = rand() % (1 << bits);
258 int cmp_size = sizeof(short) * height * width;
259 int numCoeff = height * width;
260
261 int index1 = rand() % TEST_CASES;
262 int index2 = rand() % TEST_CASES;
263
264 refReturnValue = ref(int_test_buff[index1] + j, int_test_buff[index2] + j, mshortbuf2, bits, valueToAdd, numCoeff);
265 optReturnValue = (uint32_t)checked(opt, int_test_buff[index1] + j, int_test_buff[index2] + j, mshortbuf3, bits, valueToAdd, numCoeff);
266
267 if (memcmp(mshortbuf2, mshortbuf3, cmp_size))
268 return false;
269
270 if (optReturnValue != refReturnValue)
271 return false;
272
273 reportfail();
274 j += INCR;
275 }
276
277 return true;
278}
279
280bool MBDstHarness::check_count_nonzero_primitive(count_nonzero_t ref, count_nonzero_t opt)
281{
282 ALIGN_VAR_32(int16_t, qcoeff[32 * 32]);
283
284 for (int i = 0; i < 4; i++)
285 {
286 int log2TrSize = i + 2;
287 int num = 1 << (log2TrSize * 2);
288 int mask = num - 1;
289
290 for (int n = 0; n <= num; n++)
291 {
292 memset(qcoeff, 0, num * sizeof(int16_t));
293
294 for (int j = 0; j < n; j++)
295 {
296 int k = rand() & mask;
297 while (qcoeff[k])
298 {
299 k = (k + 11) & mask;
300 }
301
302 qcoeff[k] = (int16_t)rand() - RAND_MAX / 2;
303 }
304
305 int refval = ref(qcoeff, num);
306 int optval = (int)checked(opt, qcoeff, num);
307
308 if (refval != optval)
309 return false;
310
311 reportfail();
312 }
313 }
314
315 return true;
316}
317
318bool MBDstHarness::check_denoise_dct_primitive(denoiseDct_t ref, denoiseDct_t opt)
319{
320 int j = 0;
321
322 for (int s = 0; s < 4; s++)
323 {
324 int log2TrSize = s + 2;
325 int num = 1 << (log2TrSize * 2);
326 int cmp_size = sizeof(int) * num;
327
328 for (int i = 0; i < ITERS; i++)
329 {
330 memset(mubuf1, 0, num * sizeof(uint32_t));
331 memset(mubuf2, 0, num * sizeof(uint32_t));
332 memset(mushortbuf1, 0, num * sizeof(uint16_t));
333
334 for (int k = 0; k < num; k++)
335 mushortbuf1[k] = rand() % UNSIGNED_SHORT_MAX;
336
337 int index = rand() % TEST_CASES;
338
339 ref(int_denoise_test_buff1[index] + j, mubuf1, mushortbuf1, num);
340 checked(opt, int_denoise_test_buff2[index] + j, mubuf2, mushortbuf1, num);
341
342 if (memcmp(int_denoise_test_buff1[index] + j, int_denoise_test_buff2[index] + j, cmp_size))
343 return false;
344
345 if (memcmp(mubuf1, mubuf2, cmp_size))
346 return false;
347
348 reportfail();
349 j += INCR;
350 }
351 j = 0;
352 }
353
354 return true;
355}
356
357
358bool MBDstHarness::testCorrectness(const EncoderPrimitives& ref, const EncoderPrimitives& opt)
359{
360 for (int i = 0; i < NUM_DCTS; i++)
361 {
362 if (opt.dct[i])
363 {
364 if (!check_dct_primitive(ref.dct[i], opt.dct[i], dctInfo[i].width))
365 {
366 printf("\n%s failed\n", dctInfo[i].name);
367 return false;
368 }
369 }
370 }
371
372 for (int i = 0; i < NUM_IDCTS; i++)
373 {
374 if (opt.idct[i])
375 {
376 if (!check_idct_primitive(ref.idct[i], opt.idct[i], idctInfo[i].width))
377 {
378 printf("%s failed\n", idctInfo[i].name);
379 return false;
380 }
381 }
382 }
383
384 if (opt.dequant_normal)
385 {
386 if (!check_dequant_primitive(ref.dequant_normal, opt.dequant_normal))
387 {
388 printf("dequant: Failed!\n");
389 return false;
390 }
391 }
392
393 if (opt.dequant_scaling)
394 {
395 if (!check_dequant_primitive(ref.dequant_scaling, opt.dequant_scaling))
396 {
397 printf("dequant_scaling: Failed!\n");
398 return false;
399 }
400 }
401
402 if (opt.quant)
403 {
404 if (!check_quant_primitive(ref.quant, opt.quant))
405 {
406 printf("quant: Failed!\n");
407 return false;
408 }
409 }
410
411 if (opt.nquant)
412 {
413 if (!check_nquant_primitive(ref.nquant, opt.nquant))
414 {
415 printf("nquant: Failed!\n");
416 return false;
417 }
418 }
419
420 if (opt.count_nonzero)
421 {
422 if (!check_count_nonzero_primitive(ref.count_nonzero, opt.count_nonzero))
423 {
424 printf("count_nonzero: Failed!\n");
425 return false;
426 }
427 }
428
429 if (opt.dequant_scaling)
430 {
431 if (!check_dequant_primitive(ref.dequant_scaling, opt.dequant_scaling))
432 {
433 printf("dequant_scaling: Failed!\n");
434 return false;
435 }
436 }
437
438 if (opt.denoiseDct)
439 {
440 if (!check_denoise_dct_primitive(ref.denoiseDct, opt.denoiseDct))
441 {
442 printf("denoiseDct: Failed!\n");
443 return false;
444 }
445 }
446
447 return true;
448}
449
450void MBDstHarness::measureSpeed(const EncoderPrimitives& ref, const EncoderPrimitives& opt)
451{
452 for (int value = 0; value < NUM_DCTS; value++)
453 {
454 if (opt.dct[value])
455 {
456 printf("%s\t", dctInfo[value].name);
457 REPORT_SPEEDUP(opt.dct[value], ref.dct[value], mbuf1, mintbuf3, dctInfo[value].width);
458 }
459 }
460
461 for (int value = 0; value < NUM_IDCTS; value++)
462 {
463 if (opt.idct[value])
464 {
465 printf("%s\t", idctInfo[value].name);
466 REPORT_SPEEDUP(opt.idct[value], ref.idct[value], mbufidct, mshortbuf2, idctInfo[value].width);
467 }
468 }
469
470 if (opt.dequant_normal)
471 {
472 printf("dequant_normal\t");
473 REPORT_SPEEDUP(opt.dequant_normal, ref.dequant_normal, short_test_buff[0], mintbuf3, 32 * 32, 70, 1);
474 }
475
476 if (opt.dequant_scaling)
477 {
478 printf("dequant_scaling\t");
479 REPORT_SPEEDUP(opt.dequant_scaling, ref.dequant_scaling, short_test_buff[0], mintbuf3, mintbuf4, 32 * 32, 5, 1);
480 }
481
482 if (opt.quant)
483 {
484 printf("quant\t\t");
485 REPORT_SPEEDUP(opt.quant, ref.quant, int_test_buff[0], int_test_buff[1], mintbuf3, mshortbuf2, 23, 23785, 32 * 32);
486 }
487
488 if (opt.nquant)
489 {
490 printf("nquant\t\t");
491 REPORT_SPEEDUP(opt.nquant, ref.nquant, int_test_buff[0], int_test_buff[1], mshortbuf2, 23, 23785, 32 * 32);
492 }
493
494 if (opt.count_nonzero)
495 {
496 for (int i = 4; i <= 32; i <<= 1)
497 {
498 printf("count_nonzero[%dx%d]", i, i);
499 REPORT_SPEEDUP(opt.count_nonzero, ref.count_nonzero, mbuf1, i * i)
500 }
501 }
502
503 if (opt.denoiseDct)
504 {
505 printf("denoiseDct\t");
506 REPORT_SPEEDUP(opt.denoiseDct, ref.denoiseDct, int_denoise_test_buff1[0], mubuf1, mushortbuf1, 32 * 32);
507 }
508
509}