Home | History | Annotate | Download | only in unit_test
      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.
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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