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