1 /*
2 * Copyright 2011 The LibYuv Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <stdlib.h>
12 #include <string.h>
13 #include <time.h>
14
15 #include "../unit_test/unit_test.h"
16 #include "libyuv/basic_types.h"
17 #include "libyuv/compare.h"
18 #include "libyuv/cpu_id.h"
19 #include "libyuv/video_common.h"
20
21 #ifdef ENABLE_ROW_TESTS
22 #include "libyuv/compare_row.h" /* For HammingDistance_C */
23 #endif
24
25 namespace libyuv {
26
27 // hash seed of 5381 recommended.
ReferenceHashDjb2(const uint8_t * src,uint64_t count,uint32_t seed)28 static uint32_t ReferenceHashDjb2(const uint8_t* src,
29 uint64_t count,
30 uint32_t seed) {
31 uint32_t hash = seed;
32 if (count > 0) {
33 do {
34 hash = hash * 33 + *src++;
35 } while (--count);
36 }
37 return hash;
38 }
39
TEST_F(LibYUVCompareTest,Djb2_Test)40 TEST_F(LibYUVCompareTest, Djb2_Test) {
41 const int kMaxTest = benchmark_width_ * benchmark_height_;
42 align_buffer_page_end(src_a, kMaxTest);
43 align_buffer_page_end(src_b, kMaxTest);
44
45 const char* fox =
46 "The quick brown fox jumps over the lazy dog"
47 " and feels as if he were in the seventh heaven of typography"
48 " together with Hermann Zapf";
49 uint32_t foxhash = HashDjb2(reinterpret_cast<const uint8_t*>(fox), 131, 5381);
50 const uint32_t kExpectedFoxHash = 2611006483u;
51 EXPECT_EQ(kExpectedFoxHash, foxhash);
52
53 for (int i = 0; i < kMaxTest; ++i) {
54 src_a[i] = (fastrand() & 0xff);
55 src_b[i] = (fastrand() & 0xff);
56 }
57 // Compare different buffers. Expect hash is different.
58 uint32_t h1 = HashDjb2(src_a, kMaxTest, 5381);
59 uint32_t h2 = HashDjb2(src_b, kMaxTest, 5381);
60 EXPECT_NE(h1, h2);
61
62 // Make last half same. Expect hash is different.
63 memcpy(src_a + kMaxTest / 2, src_b + kMaxTest / 2, kMaxTest / 2);
64 h1 = HashDjb2(src_a, kMaxTest, 5381);
65 h2 = HashDjb2(src_b, kMaxTest, 5381);
66 EXPECT_NE(h1, h2);
67
68 // Make first half same. Expect hash is different.
69 memcpy(src_a + kMaxTest / 2, src_a, kMaxTest / 2);
70 memcpy(src_b + kMaxTest / 2, src_b, kMaxTest / 2);
71 memcpy(src_a, src_b, kMaxTest / 2);
72 h1 = HashDjb2(src_a, kMaxTest, 5381);
73 h2 = HashDjb2(src_b, kMaxTest, 5381);
74 EXPECT_NE(h1, h2);
75
76 // Make same. Expect hash is same.
77 memcpy(src_a, src_b, kMaxTest);
78 h1 = HashDjb2(src_a, kMaxTest, 5381);
79 h2 = HashDjb2(src_b, kMaxTest, 5381);
80 EXPECT_EQ(h1, h2);
81
82 // Mask seed different. Expect hash is different.
83 memcpy(src_a, src_b, kMaxTest);
84 h1 = HashDjb2(src_a, kMaxTest, 5381);
85 h2 = HashDjb2(src_b, kMaxTest, 1234);
86 EXPECT_NE(h1, h2);
87
88 // Make one byte different in middle. Expect hash is different.
89 memcpy(src_a, src_b, kMaxTest);
90 ++src_b[kMaxTest / 2];
91 h1 = HashDjb2(src_a, kMaxTest, 5381);
92 h2 = HashDjb2(src_b, kMaxTest, 5381);
93 EXPECT_NE(h1, h2);
94
95 // Make first byte different. Expect hash is different.
96 memcpy(src_a, src_b, kMaxTest);
97 ++src_b[0];
98 h1 = HashDjb2(src_a, kMaxTest, 5381);
99 h2 = HashDjb2(src_b, kMaxTest, 5381);
100 EXPECT_NE(h1, h2);
101
102 // Make last byte different. Expect hash is different.
103 memcpy(src_a, src_b, kMaxTest);
104 ++src_b[kMaxTest - 1];
105 h1 = HashDjb2(src_a, kMaxTest, 5381);
106 h2 = HashDjb2(src_b, kMaxTest, 5381);
107 EXPECT_NE(h1, h2);
108
109 // Make a zeros. Test different lengths. Expect hash is different.
110 memset(src_a, 0, kMaxTest);
111 h1 = HashDjb2(src_a, kMaxTest, 5381);
112 h2 = HashDjb2(src_a, kMaxTest / 2, 5381);
113 EXPECT_NE(h1, h2);
114
115 // Make a zeros and seed of zero. Test different lengths. Expect hash is same.
116 memset(src_a, 0, kMaxTest);
117 h1 = HashDjb2(src_a, kMaxTest, 0);
118 h2 = HashDjb2(src_a, kMaxTest / 2, 0);
119 EXPECT_EQ(h1, h2);
120
121 free_aligned_buffer_page_end(src_a);
122 free_aligned_buffer_page_end(src_b);
123 }
124
TEST_F(LibYUVCompareTest,BenchmarkDjb2_Opt)125 TEST_F(LibYUVCompareTest, BenchmarkDjb2_Opt) {
126 const int kMaxTest = benchmark_width_ * benchmark_height_;
127 align_buffer_page_end(src_a, kMaxTest);
128
129 for (int i = 0; i < kMaxTest; ++i) {
130 src_a[i] = i;
131 }
132 uint32_t h2 = ReferenceHashDjb2(src_a, kMaxTest, 5381);
133 uint32_t h1;
134 for (int i = 0; i < benchmark_iterations_; ++i) {
135 h1 = HashDjb2(src_a, kMaxTest, 5381);
136 }
137 EXPECT_EQ(h1, h2);
138 free_aligned_buffer_page_end(src_a);
139 }
140
TEST_F(LibYUVCompareTest,BenchmarkDjb2_Unaligned)141 TEST_F(LibYUVCompareTest, BenchmarkDjb2_Unaligned) {
142 const int kMaxTest = benchmark_width_ * benchmark_height_;
143 align_buffer_page_end(src_a, kMaxTest + 1);
144 for (int i = 0; i < kMaxTest; ++i) {
145 src_a[i + 1] = i;
146 }
147 uint32_t h2 = ReferenceHashDjb2(src_a + 1, kMaxTest, 5381);
148 uint32_t h1;
149 for (int i = 0; i < benchmark_iterations_; ++i) {
150 h1 = HashDjb2(src_a + 1, kMaxTest, 5381);
151 }
152 EXPECT_EQ(h1, h2);
153 free_aligned_buffer_page_end(src_a);
154 }
155
TEST_F(LibYUVCompareTest,BenchmarkARGBDetect_Opt)156 TEST_F(LibYUVCompareTest, BenchmarkARGBDetect_Opt) {
157 uint32_t fourcc;
158 const int kMaxTest = benchmark_width_ * benchmark_height_ * 4;
159 align_buffer_page_end(src_a, kMaxTest);
160 for (int i = 0; i < kMaxTest; ++i) {
161 src_a[i] = 255;
162 }
163
164 src_a[0] = 0;
165 fourcc = ARGBDetect(src_a, benchmark_width_ * 4, benchmark_width_,
166 benchmark_height_);
167 EXPECT_EQ(static_cast<uint32_t>(libyuv::FOURCC_BGRA), fourcc);
168 src_a[0] = 255;
169 src_a[3] = 0;
170 fourcc = ARGBDetect(src_a, benchmark_width_ * 4, benchmark_width_,
171 benchmark_height_);
172 EXPECT_EQ(static_cast<uint32_t>(libyuv::FOURCC_ARGB), fourcc);
173 src_a[3] = 255;
174
175 for (int i = 0; i < benchmark_iterations_; ++i) {
176 fourcc = ARGBDetect(src_a, benchmark_width_ * 4, benchmark_width_,
177 benchmark_height_);
178 }
179 EXPECT_EQ(0u, fourcc);
180
181 free_aligned_buffer_page_end(src_a);
182 }
183
TEST_F(LibYUVCompareTest,BenchmarkARGBDetect_Unaligned)184 TEST_F(LibYUVCompareTest, BenchmarkARGBDetect_Unaligned) {
185 uint32_t fourcc;
186 const int kMaxTest = benchmark_width_ * benchmark_height_ * 4 + 1;
187 align_buffer_page_end(src_a, kMaxTest);
188 for (int i = 1; i < kMaxTest; ++i) {
189 src_a[i] = 255;
190 }
191
192 src_a[0 + 1] = 0;
193 fourcc = ARGBDetect(src_a + 1, benchmark_width_ * 4, benchmark_width_,
194 benchmark_height_);
195 EXPECT_EQ(static_cast<uint32_t>(libyuv::FOURCC_BGRA), fourcc);
196 src_a[0 + 1] = 255;
197 src_a[3 + 1] = 0;
198 fourcc = ARGBDetect(src_a + 1, benchmark_width_ * 4, benchmark_width_,
199 benchmark_height_);
200 EXPECT_EQ(static_cast<uint32_t>(libyuv::FOURCC_ARGB), fourcc);
201 src_a[3 + 1] = 255;
202
203 for (int i = 0; i < benchmark_iterations_; ++i) {
204 fourcc = ARGBDetect(src_a + 1, benchmark_width_ * 4, benchmark_width_,
205 benchmark_height_);
206 }
207 EXPECT_EQ(0u, fourcc);
208
209 free_aligned_buffer_page_end(src_a);
210 }
211
212 #ifdef ENABLE_ROW_TESTS
TEST_F(LibYUVCompareTest,BenchmarkHammingDistance_Opt)213 TEST_F(LibYUVCompareTest, BenchmarkHammingDistance_Opt) {
214 const int kMaxWidth = 4096 * 3;
215 align_buffer_page_end(src_a, kMaxWidth);
216 align_buffer_page_end(src_b, kMaxWidth);
217 memset(src_a, 0, kMaxWidth);
218 memset(src_b, 0, kMaxWidth);
219
220 // Test known value
221 memcpy(src_a, "test0123test4567", 16);
222 memcpy(src_b, "tick0123tock4567", 16);
223 uint32_t h1 = HammingDistance_C(src_a, src_b, 16);
224 EXPECT_EQ(16u, h1);
225
226 // Test C vs OPT on random buffer
227 MemRandomize(src_a, kMaxWidth);
228 MemRandomize(src_b, kMaxWidth);
229
230 uint32_t h0 = HammingDistance_C(src_a, src_b, kMaxWidth);
231
232 int count =
233 benchmark_iterations_ *
234 ((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth);
235 for (int i = 0; i < count; ++i) {
236 #if defined(HAS_HAMMINGDISTANCE_NEON)
237 h1 = HammingDistance_NEON(src_a, src_b, kMaxWidth);
238 #elif defined(HAS_HAMMINGDISTANCE_AVX2)
239 int has_avx2 = TestCpuFlag(kCpuHasAVX2);
240 if (has_avx2) {
241 h1 = HammingDistance_AVX2(src_a, src_b, kMaxWidth);
242 } else {
243 int has_sse42 = TestCpuFlag(kCpuHasSSE42);
244 if (has_sse42) {
245 h1 = HammingDistance_SSE42(src_a, src_b, kMaxWidth);
246 } else {
247 int has_ssse3 = TestCpuFlag(kCpuHasSSSE3);
248 if (has_ssse3) {
249 h1 = HammingDistance_SSSE3(src_a, src_b, kMaxWidth);
250 } else {
251 h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
252 }
253 }
254 }
255 #elif defined(HAS_HAMMINGDISTANCE_SSE42)
256 int has_sse42 = TestCpuFlag(kCpuHasSSE42);
257 if (has_sse42) {
258 h1 = HammingDistance_SSE42(src_a, src_b, kMaxWidth);
259 } else {
260 h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
261 }
262 #else
263 h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
264 #endif
265 }
266 EXPECT_EQ(h0, h1);
267
268 free_aligned_buffer_page_end(src_a);
269 free_aligned_buffer_page_end(src_b);
270 }
271
TEST_F(LibYUVCompareTest,BenchmarkHammingDistance_C)272 TEST_F(LibYUVCompareTest, BenchmarkHammingDistance_C) {
273 const int kMaxWidth = 4096 * 3;
274 align_buffer_page_end(src_a, kMaxWidth);
275 align_buffer_page_end(src_b, kMaxWidth);
276 memset(src_a, 0, kMaxWidth);
277 memset(src_b, 0, kMaxWidth);
278
279 // Test known value
280 memcpy(src_a, "test0123test4567", 16);
281 memcpy(src_b, "tick0123tock4567", 16);
282 uint32_t h1 = HammingDistance_C(src_a, src_b, 16);
283 EXPECT_EQ(16u, h1);
284
285 // Test C vs OPT on random buffer
286 MemRandomize(src_a, kMaxWidth);
287 MemRandomize(src_b, kMaxWidth);
288
289 uint32_t h0 = HammingDistance_C(src_a, src_b, kMaxWidth);
290
291 int count =
292 benchmark_iterations_ *
293 ((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth);
294 for (int i = 0; i < count; ++i) {
295 h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
296 }
297
298 EXPECT_EQ(h0, h1);
299
300 free_aligned_buffer_page_end(src_a);
301 free_aligned_buffer_page_end(src_b);
302 }
303
TEST_F(LibYUVCompareTest,BenchmarkHammingDistance)304 TEST_F(LibYUVCompareTest, BenchmarkHammingDistance) {
305 const int kMaxWidth = 4096 * 3;
306 align_buffer_page_end(src_a, kMaxWidth);
307 align_buffer_page_end(src_b, kMaxWidth);
308 memset(src_a, 0, kMaxWidth);
309 memset(src_b, 0, kMaxWidth);
310
311 memcpy(src_a, "test0123test4567", 16);
312 memcpy(src_b, "tick0123tock4567", 16);
313 uint64_t h1 = ComputeHammingDistance(src_a, src_b, 16);
314 EXPECT_EQ(16u, h1);
315
316 // Test C vs OPT on random buffer
317 MemRandomize(src_a, kMaxWidth);
318 MemRandomize(src_b, kMaxWidth);
319
320 uint32_t h0 = HammingDistance_C(src_a, src_b, kMaxWidth);
321
322 int count =
323 benchmark_iterations_ *
324 ((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth);
325 for (int i = 0; i < count; ++i) {
326 h1 = ComputeHammingDistance(src_a, src_b, kMaxWidth);
327 }
328
329 EXPECT_EQ(h0, h1);
330
331 free_aligned_buffer_page_end(src_a);
332 free_aligned_buffer_page_end(src_b);
333 }
334
335 // Tests low levels match reference C for specified size.
336 // The opt implementations have size limitations
337 // For NEON the counters are 16 bit so the shorts overflow after 65536 bytes.
338 // So doing one less iteration of the loop is the maximum.
339 #if defined(HAS_HAMMINGDISTANCE_NEON)
340 static const int kMaxOptCount = 65536 - 32; // 65504
341 #else
342 static const int kMaxOptCount = (1 << (32 - 3)) - 64; // 536870848
343 #endif
344
TEST_F(LibYUVCompareTest,TestHammingDistance_Opt)345 TEST_F(LibYUVCompareTest, TestHammingDistance_Opt) {
346 uint32_t h1 = 0;
347 const int kMaxWidth = (benchmark_width_ * benchmark_height_ + 63) & ~63;
348 align_buffer_page_end(src_a, kMaxWidth);
349 align_buffer_page_end(src_b, kMaxWidth);
350 memset(src_a, 255u, kMaxWidth);
351 memset(src_b, 0u, kMaxWidth);
352
353 uint64_t h0 = ComputeHammingDistance(src_a, src_b, kMaxWidth);
354 EXPECT_EQ(kMaxWidth * 8ULL, h0);
355
356 for (int i = 0; i < benchmark_iterations_; ++i) {
357 #if defined(HAS_HAMMINGDISTANCE_NEON)
358 h1 = HammingDistance_NEON(src_a, src_b, kMaxWidth);
359 #elif defined(HAS_HAMMINGDISTANCE_AVX2)
360 int has_avx2 = TestCpuFlag(kCpuHasAVX2);
361 if (has_avx2) {
362 h1 = HammingDistance_AVX2(src_a, src_b, kMaxWidth);
363 } else {
364 int has_sse42 = TestCpuFlag(kCpuHasSSE42);
365 if (has_sse42) {
366 h1 = HammingDistance_SSE42(src_a, src_b, kMaxWidth);
367 } else {
368 int has_ssse3 = TestCpuFlag(kCpuHasSSSE3);
369 if (has_ssse3) {
370 h1 = HammingDistance_SSSE3(src_a, src_b, kMaxWidth);
371 } else {
372 h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
373 }
374 }
375 }
376 #elif defined(HAS_HAMMINGDISTANCE_SSE42)
377 int has_sse42 = TestCpuFlag(kCpuHasSSE42);
378 if (has_sse42) {
379 h1 = HammingDistance_SSE42(src_a, src_b, kMaxWidth);
380 } else {
381 h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
382 }
383 #else
384 h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
385 #endif
386 }
387
388 // A large count will cause the low level to potentially overflow so the
389 // result can not be expected to be correct.
390 // TODO(fbarchard): Consider expecting the low 16 bits to match.
391 if (kMaxWidth <= kMaxOptCount) {
392 EXPECT_EQ(kMaxWidth * 8U, h1);
393 } else {
394 if (kMaxWidth * 8ULL != static_cast<uint64_t>(h1)) {
395 printf(
396 "warning - HammingDistance_Opt %u does not match %llu "
397 "but length of %u is longer than guaranteed.\n",
398 h1, kMaxWidth * 8ULL, kMaxWidth);
399 } else {
400 printf(
401 "warning - HammingDistance_Opt %u matches but length of %u "
402 "is longer than guaranteed.\n",
403 h1, kMaxWidth);
404 }
405 }
406
407 free_aligned_buffer_page_end(src_a);
408 free_aligned_buffer_page_end(src_b);
409 }
410 #endif // ENABLE_ROW_TESTS
411
TEST_F(LibYUVCompareTest,TestHammingDistance)412 TEST_F(LibYUVCompareTest, TestHammingDistance) {
413 align_buffer_page_end(src_a, benchmark_width_ * benchmark_height_);
414 align_buffer_page_end(src_b, benchmark_width_ * benchmark_height_);
415 memset(src_a, 255u, benchmark_width_ * benchmark_height_);
416 memset(src_b, 0, benchmark_width_ * benchmark_height_);
417
418 uint64_t h1 = 0;
419 for (int i = 0; i < benchmark_iterations_; ++i) {
420 h1 = ComputeHammingDistance(src_a, src_b,
421 benchmark_width_ * benchmark_height_);
422 }
423 EXPECT_EQ(benchmark_width_ * benchmark_height_ * 8ULL, h1);
424
425 free_aligned_buffer_page_end(src_a);
426 free_aligned_buffer_page_end(src_b);
427 }
428
TEST_F(LibYUVCompareTest,BenchmarkSumSquareError_Opt)429 TEST_F(LibYUVCompareTest, BenchmarkSumSquareError_Opt) {
430 const int kMaxWidth = 4096 * 3;
431 align_buffer_page_end(src_a, kMaxWidth);
432 align_buffer_page_end(src_b, kMaxWidth);
433 memset(src_a, 0, kMaxWidth);
434 memset(src_b, 0, kMaxWidth);
435
436 memcpy(src_a, "test0123test4567", 16);
437 memcpy(src_b, "tick0123tock4567", 16);
438 uint64_t h1 = ComputeSumSquareError(src_a, src_b, 16);
439 EXPECT_EQ(790u, h1);
440
441 for (int i = 0; i < kMaxWidth; ++i) {
442 src_a[i] = i;
443 src_b[i] = i;
444 }
445 memset(src_a, 0, kMaxWidth);
446 memset(src_b, 0, kMaxWidth);
447
448 int count =
449 benchmark_iterations_ *
450 ((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth);
451 for (int i = 0; i < count; ++i) {
452 h1 = ComputeSumSquareError(src_a, src_b, kMaxWidth);
453 }
454
455 EXPECT_EQ(0u, h1);
456
457 free_aligned_buffer_page_end(src_a);
458 free_aligned_buffer_page_end(src_b);
459 }
460
TEST_F(LibYUVCompareTest,SumSquareError)461 TEST_F(LibYUVCompareTest, SumSquareError) {
462 const int kMaxWidth = 4096 * 3;
463 align_buffer_page_end(src_a, kMaxWidth);
464 align_buffer_page_end(src_b, kMaxWidth);
465 memset(src_a, 0, kMaxWidth);
466 memset(src_b, 0, kMaxWidth);
467
468 uint64_t err;
469 err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
470
471 EXPECT_EQ(0u, err);
472
473 memset(src_a, 1, kMaxWidth);
474 err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
475
476 EXPECT_EQ(static_cast<int>(err), kMaxWidth);
477
478 memset(src_a, 190, kMaxWidth);
479 memset(src_b, 193, kMaxWidth);
480 err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
481
482 EXPECT_EQ(static_cast<int>(err), kMaxWidth * 3 * 3);
483
484 for (int i = 0; i < kMaxWidth; ++i) {
485 src_a[i] = (fastrand() & 0xff);
486 src_b[i] = (fastrand() & 0xff);
487 }
488
489 MaskCpuFlags(disable_cpu_flags_);
490 uint64_t c_err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
491
492 MaskCpuFlags(benchmark_cpu_info_);
493 uint64_t opt_err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
494
495 EXPECT_EQ(c_err, opt_err);
496
497 free_aligned_buffer_page_end(src_a);
498 free_aligned_buffer_page_end(src_b);
499 }
500
TEST_F(LibYUVCompareTest,BenchmarkPsnr_Opt)501 TEST_F(LibYUVCompareTest, BenchmarkPsnr_Opt) {
502 align_buffer_page_end(src_a, benchmark_width_ * benchmark_height_);
503 align_buffer_page_end(src_b, benchmark_width_ * benchmark_height_);
504 for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
505 src_a[i] = i;
506 src_b[i] = i;
507 }
508
509 MaskCpuFlags(benchmark_cpu_info_);
510
511 double opt_time = get_time();
512 for (int i = 0; i < benchmark_iterations_; ++i) {
513 CalcFramePsnr(src_a, benchmark_width_, src_b, benchmark_width_,
514 benchmark_width_, benchmark_height_);
515 }
516
517 opt_time = (get_time() - opt_time) / benchmark_iterations_;
518 printf("BenchmarkPsnr_Opt - %8.2f us opt\n", opt_time * 1e6);
519
520 EXPECT_EQ(0, 0);
521
522 free_aligned_buffer_page_end(src_a);
523 free_aligned_buffer_page_end(src_b);
524 }
525
TEST_F(LibYUVCompareTest,BenchmarkPsnr_Unaligned)526 TEST_F(LibYUVCompareTest, BenchmarkPsnr_Unaligned) {
527 align_buffer_page_end(src_a, benchmark_width_ * benchmark_height_ + 1);
528 align_buffer_page_end(src_b, benchmark_width_ * benchmark_height_);
529 for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
530 src_a[i + 1] = i;
531 src_b[i] = i;
532 }
533
534 MaskCpuFlags(benchmark_cpu_info_);
535
536 double opt_time = get_time();
537 for (int i = 0; i < benchmark_iterations_; ++i) {
538 CalcFramePsnr(src_a + 1, benchmark_width_, src_b, benchmark_width_,
539 benchmark_width_, benchmark_height_);
540 }
541
542 opt_time = (get_time() - opt_time) / benchmark_iterations_;
543 printf("BenchmarkPsnr_Opt - %8.2f us opt\n", opt_time * 1e6);
544
545 EXPECT_EQ(0, 0);
546
547 free_aligned_buffer_page_end(src_a);
548 free_aligned_buffer_page_end(src_b);
549 }
550
TEST_F(LibYUVCompareTest,Psnr)551 TEST_F(LibYUVCompareTest, Psnr) {
552 const int kSrcWidth = benchmark_width_;
553 const int kSrcHeight = benchmark_height_;
554 const int b = 128;
555 const int kSrcPlaneSize = (kSrcWidth + b * 2) * (kSrcHeight + b * 2);
556 const int kSrcStride = 2 * b + kSrcWidth;
557 align_buffer_page_end(src_a, kSrcPlaneSize);
558 align_buffer_page_end(src_b, kSrcPlaneSize);
559 memset(src_a, 0, kSrcPlaneSize);
560 memset(src_b, 0, kSrcPlaneSize);
561
562 double err;
563 err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
564 src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
565 kSrcHeight);
566
567 EXPECT_EQ(err, kMaxPsnr);
568
569 memset(src_a, 255, kSrcPlaneSize);
570
571 err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
572 src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
573 kSrcHeight);
574
575 EXPECT_EQ(err, 0.0);
576
577 memset(src_a, 1, kSrcPlaneSize);
578
579 err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
580 src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
581 kSrcHeight);
582
583 EXPECT_GT(err, 48.0);
584 EXPECT_LT(err, 49.0);
585
586 for (int i = 0; i < kSrcPlaneSize; ++i) {
587 src_a[i] = i;
588 }
589
590 err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
591 src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
592 kSrcHeight);
593
594 EXPECT_GT(err, 2.0);
595 if (kSrcWidth * kSrcHeight >= 256) {
596 EXPECT_LT(err, 6.0);
597 }
598
599 memset(src_a, 0, kSrcPlaneSize);
600 memset(src_b, 0, kSrcPlaneSize);
601
602 for (int i = b; i < (kSrcHeight + b); ++i) {
603 for (int j = b; j < (kSrcWidth + b); ++j) {
604 src_a[(i * kSrcStride) + j] = (fastrand() & 0xff);
605 src_b[(i * kSrcStride) + j] = (fastrand() & 0xff);
606 }
607 }
608
609 MaskCpuFlags(disable_cpu_flags_);
610 double c_err, opt_err;
611
612 c_err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
613 src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
614 kSrcHeight);
615
616 MaskCpuFlags(benchmark_cpu_info_);
617
618 opt_err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
619 src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
620 kSrcHeight);
621
622 EXPECT_EQ(opt_err, c_err);
623
624 free_aligned_buffer_page_end(src_a);
625 free_aligned_buffer_page_end(src_b);
626 }
627
TEST_F(LibYUVCompareTest,DISABLED_BenchmarkSsim_Opt)628 TEST_F(LibYUVCompareTest, DISABLED_BenchmarkSsim_Opt) {
629 align_buffer_page_end(src_a, benchmark_width_ * benchmark_height_);
630 align_buffer_page_end(src_b, benchmark_width_ * benchmark_height_);
631 for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
632 src_a[i] = i;
633 src_b[i] = i;
634 }
635
636 MaskCpuFlags(benchmark_cpu_info_);
637
638 double opt_time = get_time();
639 for (int i = 0; i < benchmark_iterations_; ++i) {
640 CalcFrameSsim(src_a, benchmark_width_, src_b, benchmark_width_,
641 benchmark_width_, benchmark_height_);
642 }
643
644 opt_time = (get_time() - opt_time) / benchmark_iterations_;
645 printf("BenchmarkSsim_Opt - %8.2f us opt\n", opt_time * 1e6);
646
647 EXPECT_EQ(0, 0); // Pass if we get this far.
648
649 free_aligned_buffer_page_end(src_a);
650 free_aligned_buffer_page_end(src_b);
651 }
652
TEST_F(LibYUVCompareTest,Ssim)653 TEST_F(LibYUVCompareTest, Ssim) {
654 const int kSrcWidth = benchmark_width_;
655 const int kSrcHeight = benchmark_height_;
656 const int b = 128;
657 const int kSrcPlaneSize = (kSrcWidth + b * 2) * (kSrcHeight + b * 2);
658 const int kSrcStride = 2 * b + kSrcWidth;
659 align_buffer_page_end(src_a, kSrcPlaneSize);
660 align_buffer_page_end(src_b, kSrcPlaneSize);
661 memset(src_a, 0, kSrcPlaneSize);
662 memset(src_b, 0, kSrcPlaneSize);
663
664 if (kSrcWidth <= 8 || kSrcHeight <= 8) {
665 printf("warning - Ssim size too small. Testing function executes.\n");
666 }
667
668 double err;
669 err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
670 src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
671 kSrcHeight);
672
673 if (kSrcWidth > 8 && kSrcHeight > 8) {
674 EXPECT_EQ(err, 1.0);
675 }
676
677 memset(src_a, 255, kSrcPlaneSize);
678
679 err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
680 src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
681 kSrcHeight);
682
683 if (kSrcWidth > 8 && kSrcHeight > 8) {
684 EXPECT_LT(err, 0.0001);
685 }
686
687 memset(src_a, 1, kSrcPlaneSize);
688
689 err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
690 src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
691 kSrcHeight);
692
693 if (kSrcWidth > 8 && kSrcHeight > 8) {
694 EXPECT_GT(err, 0.0001);
695 EXPECT_LT(err, 0.9);
696 }
697
698 for (int i = 0; i < kSrcPlaneSize; ++i) {
699 src_a[i] = i;
700 }
701
702 err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
703 src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
704 kSrcHeight);
705
706 if (kSrcWidth > 8 && kSrcHeight > 8) {
707 EXPECT_GT(err, 0.0);
708 EXPECT_LT(err, 0.01);
709 }
710
711 for (int i = b; i < (kSrcHeight + b); ++i) {
712 for (int j = b; j < (kSrcWidth + b); ++j) {
713 src_a[(i * kSrcStride) + j] = (fastrand() & 0xff);
714 src_b[(i * kSrcStride) + j] = (fastrand() & 0xff);
715 }
716 }
717
718 MaskCpuFlags(disable_cpu_flags_);
719 double c_err, opt_err;
720
721 c_err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
722 src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
723 kSrcHeight);
724
725 MaskCpuFlags(benchmark_cpu_info_);
726
727 opt_err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
728 src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
729 kSrcHeight);
730
731 if (kSrcWidth > 8 && kSrcHeight > 8) {
732 EXPECT_EQ(opt_err, c_err);
733 }
734
735 free_aligned_buffer_page_end(src_a);
736 free_aligned_buffer_page_end(src_b);
737 }
738
739 } // namespace libyuv
740