• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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