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
20 namespace libyuv {
21
22 // hash seed of 5381 recommended.
ReferenceHashDjb2(const uint8 * src,uint64 count,uint32 seed)23 static uint32 ReferenceHashDjb2(const uint8* src, uint64 count, uint32 seed) {
24 uint32 hash = seed;
25 if (count > 0) {
26 do {
27 hash = hash * 33 + *src++;
28 } while (--count);
29 }
30 return hash;
31 }
32
TEST_F(libyuvTest,TestDjb2)33 TEST_F(libyuvTest, TestDjb2) {
34 const int kMaxTest = 2049;
35 align_buffer_16(src_a, kMaxTest)
36
37 for (int i = 0; i < kMaxTest; ++i) {
38 src_a[i] = i;
39 }
40 for (int i = 0; i < kMaxTest; ++i) {
41 uint32 h1 = HashDjb2(src_a, kMaxTest, 5381);
42 uint32 h2 = ReferenceHashDjb2(src_a, kMaxTest, 5381);
43 EXPECT_EQ(h1, h2);
44 }
45 // Hash constant generator using for tables in compare
46 int h = 1;
47 for (int i = 0; i <= 16 ; ++i) {
48 printf("%08x ", h);
49 h *= 33;
50 }
51 printf("\n");
52
53 free_aligned_buffer_16(src_a)
54 }
55
TEST_F(libyuvTest,BenchmakDjb2_C)56 TEST_F(libyuvTest, BenchmakDjb2_C) {
57 const int kMaxTest = 1280 * 720;
58 align_buffer_16(src_a, kMaxTest)
59
60 for (int i = 0; i < kMaxTest; ++i) {
61 src_a[i] = i;
62 }
63 uint32 h2 = ReferenceHashDjb2(src_a, kMaxTest, 5381);
64 uint32 h1;
65 MaskCpuFlags(kCpuInitialized);
66 for (int i = 0; i < benchmark_iterations_; ++i) {
67 h1 = HashDjb2(src_a, kMaxTest, 5381);
68 }
69 MaskCpuFlags(-1);
70 EXPECT_EQ(h1, h2);
71 free_aligned_buffer_16(src_a)
72 }
73
TEST_F(libyuvTest,BenchmakDjb2_OPT)74 TEST_F(libyuvTest, BenchmakDjb2_OPT) {
75 const int kMaxTest = 1280 * 720;
76 align_buffer_16(src_a, kMaxTest)
77
78 for (int i = 0; i < kMaxTest; ++i) {
79 src_a[i] = i;
80 }
81 uint32 h2 = ReferenceHashDjb2(src_a, kMaxTest, 5381);
82 uint32 h1;
83 for (int i = 0; i < benchmark_iterations_; ++i) {
84 h1 = HashDjb2(src_a, kMaxTest, 5381);
85 }
86 EXPECT_EQ(h1, h2);
87 free_aligned_buffer_16(src_a)
88 }
89
TEST_F(libyuvTest,BenchmakDjb2_Unaligned_OPT)90 TEST_F(libyuvTest, BenchmakDjb2_Unaligned_OPT) {
91 const int kMaxTest = 1280 * 720;
92 align_buffer_16(src_a, kMaxTest + 1)
93
94 for (int i = 0; i < kMaxTest; ++i) {
95 src_a[i + 1] = i;
96 }
97 uint32 h2 = ReferenceHashDjb2(src_a + 1, kMaxTest, 5381);
98 uint32 h1;
99 for (int i = 0; i < benchmark_iterations_; ++i) {
100 h1 = HashDjb2(src_a + 1, kMaxTest, 5381);
101 }
102 EXPECT_EQ(h1, h2);
103 free_aligned_buffer_16(src_a)
104 }
105
TEST_F(libyuvTest,BenchmarkSumSquareError_C)106 TEST_F(libyuvTest, BenchmarkSumSquareError_C) {
107 const int kMaxWidth = 4096 * 3;
108 align_buffer_16(src_a, kMaxWidth)
109 align_buffer_16(src_b, kMaxWidth)
110
111 for (int i = 0; i < kMaxWidth; ++i) {
112 src_a[i] = i;
113 src_b[i] = i;
114 }
115
116 MaskCpuFlags(kCpuInitialized);
117 for (int i = 0; i < benchmark_iterations_; ++i) {
118 ComputeSumSquareError(src_a, src_b, kMaxWidth);
119 }
120
121 MaskCpuFlags(-1);
122
123 EXPECT_EQ(0, 0);
124
125 free_aligned_buffer_16(src_a)
126 free_aligned_buffer_16(src_b)
127 }
128
TEST_F(libyuvTest,BenchmarkSumSquareError_OPT)129 TEST_F(libyuvTest, BenchmarkSumSquareError_OPT) {
130 const int kMaxWidth = 4096 * 3;
131 align_buffer_16(src_a, kMaxWidth)
132 align_buffer_16(src_b, kMaxWidth)
133
134 for (int i = 0; i < kMaxWidth; ++i) {
135 src_a[i] = i;
136 src_b[i] = i;
137 }
138
139 for (int i = 0; i < benchmark_iterations_; ++i) {
140 ComputeSumSquareError(src_a, src_b, kMaxWidth);
141 }
142
143 EXPECT_EQ(0, 0);
144
145 free_aligned_buffer_16(src_a)
146 free_aligned_buffer_16(src_b)
147 }
148
TEST_F(libyuvTest,SumSquareError)149 TEST_F(libyuvTest, SumSquareError) {
150 const int kMaxWidth = 4096 * 3;
151 align_buffer_16(src_a, kMaxWidth)
152 align_buffer_16(src_b, kMaxWidth)
153
154 memset(src_a, 0, kMaxWidth);
155 memset(src_b, 0, kMaxWidth);
156
157 uint64 err;
158 err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
159
160 EXPECT_EQ(err, 0);
161
162 memset(src_a, 1, kMaxWidth);
163 err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
164
165 EXPECT_EQ(err, kMaxWidth);
166
167 memset(src_a, 190, kMaxWidth);
168 memset(src_b, 193, kMaxWidth);
169 err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
170
171 EXPECT_EQ(err, (kMaxWidth * 3 * 3));
172
173 srandom(time(NULL));
174
175 for (int i = 0; i < kMaxWidth; ++i) {
176 src_a[i] = (random() & 0xff);
177 src_b[i] = (random() & 0xff);
178 }
179
180 MaskCpuFlags(kCpuInitialized);
181 uint64 c_err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
182
183 MaskCpuFlags(-1);
184 uint64 opt_err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
185
186 EXPECT_EQ(c_err, opt_err);
187
188 free_aligned_buffer_16(src_a)
189 free_aligned_buffer_16(src_b)
190 }
191
TEST_F(libyuvTest,BenchmarkPsnr_C)192 TEST_F(libyuvTest, BenchmarkPsnr_C) {
193 align_buffer_16(src_a, benchmark_width_ * benchmark_height_)
194 align_buffer_16(src_b, benchmark_width_ * benchmark_height_)
195
196 for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
197 src_a[i] = i;
198 src_b[i] = i;
199 }
200
201 MaskCpuFlags(kCpuInitialized);
202
203 double c_time = get_time();
204 for (int i = 0; i < benchmark_iterations_; ++i)
205 CalcFramePsnr(src_a, benchmark_width_,
206 src_b, benchmark_width_,
207 benchmark_width_, benchmark_height_);
208
209 c_time = (get_time() - c_time) / benchmark_iterations_;
210 printf("BenchmarkPsnr_C - %8.2f us c\n", c_time * 1e6);
211
212 MaskCpuFlags(-1);
213
214 EXPECT_EQ(0, 0);
215
216 free_aligned_buffer_16(src_a)
217 free_aligned_buffer_16(src_b)
218 }
219
TEST_F(libyuvTest,BenchmarkPsnr_OPT)220 TEST_F(libyuvTest, BenchmarkPsnr_OPT) {
221 align_buffer_16(src_a, benchmark_width_ * benchmark_height_)
222 align_buffer_16(src_b, benchmark_width_ * benchmark_height_)
223
224 for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
225 src_a[i] = i;
226 src_b[i] = i;
227 }
228
229 MaskCpuFlags(-1);
230
231 double opt_time = get_time();
232 for (int i = 0; i < benchmark_iterations_; ++i)
233 CalcFramePsnr(src_a, benchmark_width_,
234 src_b, benchmark_width_,
235 benchmark_width_, benchmark_height_);
236
237 opt_time = (get_time() - opt_time) / benchmark_iterations_;
238 printf("BenchmarkPsnr_OPT - %8.2f us opt\n", opt_time * 1e6);
239
240 EXPECT_EQ(0, 0);
241
242 free_aligned_buffer_16(src_a)
243 free_aligned_buffer_16(src_b)
244 }
245
TEST_F(libyuvTest,Psnr)246 TEST_F(libyuvTest, Psnr) {
247 const int kSrcWidth = 1280;
248 const int kSrcHeight = 720;
249 const int b = 128;
250 const int kSrcPlaneSize = (kSrcWidth + b * 2) * (kSrcHeight + b * 2);
251 const int kSrcStride = 2 * b + kSrcWidth;
252 align_buffer_16(src_a, kSrcPlaneSize)
253 align_buffer_16(src_b, kSrcPlaneSize)
254
255 memset(src_a, 0, kSrcPlaneSize);
256 memset(src_b, 0, kSrcPlaneSize);
257
258 double err;
259 err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
260 src_b + kSrcStride * b + b, kSrcStride,
261 kSrcWidth, kSrcHeight);
262
263 EXPECT_EQ(err, kMaxPsnr);
264
265 memset(src_a, 255, kSrcPlaneSize);
266
267 err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
268 src_b + kSrcStride * b + b, kSrcStride,
269 kSrcWidth, kSrcHeight);
270
271 EXPECT_EQ(err, 0.0);
272
273 memset(src_a, 1, kSrcPlaneSize);
274
275 err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
276 src_b + kSrcStride * b + b, kSrcStride,
277 kSrcWidth, kSrcHeight);
278
279 EXPECT_GT(err, 48.0);
280 EXPECT_LT(err, 49.0);
281
282 for (int i = 0; i < kSrcPlaneSize; ++i)
283 src_a[i] = i;
284
285 err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
286 src_b + kSrcStride * b + b, kSrcStride,
287 kSrcWidth, kSrcHeight);
288
289 EXPECT_GT(err, 4.0);
290 EXPECT_LT(err, 5.0);
291
292 srandom(time(NULL));
293
294 memset(src_a, 0, kSrcPlaneSize);
295 memset(src_b, 0, kSrcPlaneSize);
296
297 for (int i = b; i < (kSrcHeight + b); ++i) {
298 for (int j = b; j < (kSrcWidth + b); ++j) {
299 src_a[(i * kSrcStride) + j] = (random() & 0xff);
300 src_b[(i * kSrcStride) + j] = (random() & 0xff);
301 }
302 }
303
304 MaskCpuFlags(kCpuInitialized);
305 double c_err, opt_err;
306
307 c_err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
308 src_b + kSrcStride * b + b, kSrcStride,
309 kSrcWidth, kSrcHeight);
310
311 MaskCpuFlags(-1);
312
313 opt_err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
314 src_b + kSrcStride * b + b, kSrcStride,
315 kSrcWidth, kSrcHeight);
316
317 EXPECT_EQ(opt_err, c_err);
318
319 free_aligned_buffer_16(src_a)
320 free_aligned_buffer_16(src_b)
321 }
322
TEST_F(libyuvTest,BenchmarkSsim_C)323 TEST_F(libyuvTest, BenchmarkSsim_C) {
324 align_buffer_16(src_a, benchmark_width_ * benchmark_height_)
325 align_buffer_16(src_b, benchmark_width_ * benchmark_height_)
326
327 for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
328 src_a[i] = i;
329 src_b[i] = i;
330 }
331
332 MaskCpuFlags(kCpuInitialized);
333
334 double c_time = get_time();
335 for (int i = 0; i < benchmark_iterations_; ++i)
336 CalcFrameSsim(src_a, benchmark_width_,
337 src_b, benchmark_width_,
338 benchmark_width_, benchmark_height_);
339
340 c_time = (get_time() - c_time) / benchmark_iterations_;
341 printf("BenchmarkSsim_C - %8.2f us c\n", c_time * 1e6);
342
343 MaskCpuFlags(-1);
344
345 EXPECT_EQ(0, 0);
346
347 free_aligned_buffer_16(src_a)
348 free_aligned_buffer_16(src_b)
349 }
350
TEST_F(libyuvTest,BenchmarkSsim_OPT)351 TEST_F(libyuvTest, BenchmarkSsim_OPT) {
352 align_buffer_16(src_a, benchmark_width_ * benchmark_height_)
353 align_buffer_16(src_b, benchmark_width_ * benchmark_height_)
354
355 for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
356 src_a[i] = i;
357 src_b[i] = i;
358 }
359
360 MaskCpuFlags(-1);
361
362 double opt_time = get_time();
363 for (int i = 0; i < benchmark_iterations_; ++i)
364 CalcFrameSsim(src_a, benchmark_width_,
365 src_b, benchmark_width_,
366 benchmark_width_, benchmark_height_);
367
368 opt_time = (get_time() - opt_time) / benchmark_iterations_;
369 printf("BenchmarkPsnr_OPT - %8.2f us opt\n", opt_time * 1e6);
370
371 EXPECT_EQ(0, 0);
372
373 free_aligned_buffer_16(src_a)
374 free_aligned_buffer_16(src_b)
375 }
376
TEST_F(libyuvTest,Ssim)377 TEST_F(libyuvTest, Ssim) {
378 const int kSrcWidth = 1280;
379 const int kSrcHeight = 720;
380 const int b = 128;
381 const int kSrcPlaneSize = (kSrcWidth + b * 2) * (kSrcHeight + b * 2);
382 const int kSrcStride = 2 * b + kSrcWidth;
383 align_buffer_16(src_a, kSrcPlaneSize)
384 align_buffer_16(src_b, kSrcPlaneSize)
385
386 memset(src_a, 0, kSrcPlaneSize);
387 memset(src_b, 0, kSrcPlaneSize);
388
389 double err;
390 err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
391 src_b + kSrcStride * b + b, kSrcStride,
392 kSrcWidth, kSrcHeight);
393
394 EXPECT_EQ(err, 1.0);
395
396 memset(src_a, 255, kSrcPlaneSize);
397
398 err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
399 src_b + kSrcStride * b + b, kSrcStride,
400 kSrcWidth, kSrcHeight);
401
402 EXPECT_LT(err, 0.0001);
403
404 memset(src_a, 1, kSrcPlaneSize);
405
406 err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
407 src_b + kSrcStride * b + b, kSrcStride,
408 kSrcWidth, kSrcHeight);
409
410 EXPECT_GT(err, 0.8);
411 EXPECT_LT(err, 0.9);
412
413 for (int i = 0; i < kSrcPlaneSize; ++i)
414 src_a[i] = i;
415
416 err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
417 src_b + kSrcStride * b + b, kSrcStride,
418 kSrcWidth, kSrcHeight);
419
420 EXPECT_GT(err, 0.008);
421 EXPECT_LT(err, 0.009);
422
423 srandom(time(NULL));
424 for (int i = b; i < (kSrcHeight + b); ++i) {
425 for (int j = b; j < (kSrcWidth + b); ++j) {
426 src_a[(i * kSrcStride) + j] = (random() & 0xff);
427 src_b[(i * kSrcStride) + j] = (random() & 0xff);
428 }
429 }
430
431 MaskCpuFlags(kCpuInitialized);
432 double c_err, opt_err;
433
434 c_err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
435 src_b + kSrcStride * b + b, kSrcStride,
436 kSrcWidth, kSrcHeight);
437
438 MaskCpuFlags(-1);
439
440 opt_err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
441 src_b + kSrcStride * b + b, kSrcStride,
442 kSrcWidth, kSrcHeight);
443
444 EXPECT_EQ(opt_err, c_err);
445
446 free_aligned_buffer_16(src_a)
447 free_aligned_buffer_16(src_b)
448 }
449
450 } // namespace libyuv
451