media/libyuv/unit_test/compare_test.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * Copyright 2011 The LibYuv Project Authors. All rights reserved.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license
michael@0 5 * that can be found in the LICENSE file in the root of the source
michael@0 6 * tree. An additional intellectual property rights grant can be found
michael@0 7 * in the file PATENTS. All contributing project authors may
michael@0 8 * be found in the AUTHORS file in the root of the source tree.
michael@0 9 */
michael@0 10
michael@0 11 #include <stdlib.h>
michael@0 12 #include <string.h>
michael@0 13 #include <time.h>
michael@0 14
michael@0 15 #include "../unit_test/unit_test.h"
michael@0 16 #include "libyuv/basic_types.h"
michael@0 17 #include "libyuv/compare.h"
michael@0 18 #include "libyuv/cpu_id.h"
michael@0 19 #include "libyuv/row.h"
michael@0 20
michael@0 21 namespace libyuv {
michael@0 22
michael@0 23 // hash seed of 5381 recommended.
michael@0 24 static uint32 ReferenceHashDjb2(const uint8* src, uint64 count, uint32 seed) {
michael@0 25 uint32 hash = seed;
michael@0 26 if (count > 0) {
michael@0 27 do {
michael@0 28 hash = hash * 33 + *src++;
michael@0 29 } while (--count);
michael@0 30 }
michael@0 31 return hash;
michael@0 32 }
michael@0 33
michael@0 34 TEST_F(libyuvTest, Djb2_Test) {
michael@0 35 const int kMaxTest = benchmark_width_ * benchmark_height_;
michael@0 36 align_buffer_64(src_a, kMaxTest);
michael@0 37 align_buffer_64(src_b, kMaxTest);
michael@0 38
michael@0 39 const char* fox = "The quick brown fox jumps over the lazy dog"
michael@0 40 " and feels as if he were in the seventh heaven of typography"
michael@0 41 " together with Hermann Zapf";
michael@0 42 uint32 foxhash = HashDjb2(reinterpret_cast<const uint8*>(fox), 131, 5381);
michael@0 43 const uint32 kExpectedFoxHash = 2611006483u;
michael@0 44 EXPECT_EQ(kExpectedFoxHash, foxhash);
michael@0 45
michael@0 46 for (int i = 0; i < kMaxTest; ++i) {
michael@0 47 src_a[i] = (random() & 0xff);
michael@0 48 src_b[i] = (random() & 0xff);
michael@0 49 }
michael@0 50 // Compare different buffers. Expect hash is different.
michael@0 51 uint32 h1 = HashDjb2(src_a, kMaxTest, 5381);
michael@0 52 uint32 h2 = HashDjb2(src_b, kMaxTest, 5381);
michael@0 53 EXPECT_NE(h1, h2);
michael@0 54
michael@0 55 // Make last half same. Expect hash is different.
michael@0 56 memcpy(src_a + kMaxTest / 2, src_b + kMaxTest / 2, kMaxTest / 2);
michael@0 57 h1 = HashDjb2(src_a, kMaxTest, 5381);
michael@0 58 h2 = HashDjb2(src_b, kMaxTest, 5381);
michael@0 59 EXPECT_NE(h1, h2);
michael@0 60
michael@0 61 // Make first half same. Expect hash is different.
michael@0 62 memcpy(src_a + kMaxTest / 2, src_a, kMaxTest / 2);
michael@0 63 memcpy(src_b + kMaxTest / 2, src_b, kMaxTest / 2);
michael@0 64 memcpy(src_a, src_b, kMaxTest / 2);
michael@0 65 h1 = HashDjb2(src_a, kMaxTest, 5381);
michael@0 66 h2 = HashDjb2(src_b, kMaxTest, 5381);
michael@0 67 EXPECT_NE(h1, h2);
michael@0 68
michael@0 69 // Make same. Expect hash is same.
michael@0 70 memcpy(src_a, src_b, kMaxTest);
michael@0 71 h1 = HashDjb2(src_a, kMaxTest, 5381);
michael@0 72 h2 = HashDjb2(src_b, kMaxTest, 5381);
michael@0 73 EXPECT_EQ(h1, h2);
michael@0 74
michael@0 75 // Mask seed different. Expect hash is different.
michael@0 76 memcpy(src_a, src_b, kMaxTest);
michael@0 77 h1 = HashDjb2(src_a, kMaxTest, 5381);
michael@0 78 h2 = HashDjb2(src_b, kMaxTest, 1234);
michael@0 79 EXPECT_NE(h1, h2);
michael@0 80
michael@0 81 // Make one byte different in middle. Expect hash is different.
michael@0 82 memcpy(src_a, src_b, kMaxTest);
michael@0 83 ++src_b[kMaxTest / 2];
michael@0 84 h1 = HashDjb2(src_a, kMaxTest, 5381);
michael@0 85 h2 = HashDjb2(src_b, kMaxTest, 5381);
michael@0 86 EXPECT_NE(h1, h2);
michael@0 87
michael@0 88 // Make first byte different. Expect hash is different.
michael@0 89 memcpy(src_a, src_b, kMaxTest);
michael@0 90 ++src_b[0];
michael@0 91 h1 = HashDjb2(src_a, kMaxTest, 5381);
michael@0 92 h2 = HashDjb2(src_b, kMaxTest, 5381);
michael@0 93 EXPECT_NE(h1, h2);
michael@0 94
michael@0 95 // Make last byte different. Expect hash is different.
michael@0 96 memcpy(src_a, src_b, kMaxTest);
michael@0 97 ++src_b[kMaxTest - 1];
michael@0 98 h1 = HashDjb2(src_a, kMaxTest, 5381);
michael@0 99 h2 = HashDjb2(src_b, kMaxTest, 5381);
michael@0 100 EXPECT_NE(h1, h2);
michael@0 101
michael@0 102 // Make a zeros. Test different lengths. Expect hash is different.
michael@0 103 memset(src_a, 0, kMaxTest);
michael@0 104 h1 = HashDjb2(src_a, kMaxTest, 5381);
michael@0 105 h2 = HashDjb2(src_a, kMaxTest / 2, 5381);
michael@0 106 EXPECT_NE(h1, h2);
michael@0 107
michael@0 108 // Make a zeros and seed of zero. Test different lengths. Expect hash is same.
michael@0 109 memset(src_a, 0, kMaxTest);
michael@0 110 h1 = HashDjb2(src_a, kMaxTest, 0);
michael@0 111 h2 = HashDjb2(src_a, kMaxTest / 2, 0);
michael@0 112 EXPECT_EQ(h1, h2);
michael@0 113
michael@0 114 free_aligned_buffer_64(src_a);
michael@0 115 free_aligned_buffer_64(src_b);
michael@0 116 }
michael@0 117
michael@0 118 TEST_F(libyuvTest, BenchmarkDjb2_Opt) {
michael@0 119 const int kMaxTest = benchmark_width_ * benchmark_height_;
michael@0 120 align_buffer_64(src_a, kMaxTest);
michael@0 121
michael@0 122 for (int i = 0; i < kMaxTest; ++i) {
michael@0 123 src_a[i] = i;
michael@0 124 }
michael@0 125 uint32 h2 = ReferenceHashDjb2(src_a, kMaxTest, 5381);
michael@0 126 uint32 h1;
michael@0 127 for (int i = 0; i < benchmark_iterations_; ++i) {
michael@0 128 h1 = HashDjb2(src_a, kMaxTest, 5381);
michael@0 129 }
michael@0 130 EXPECT_EQ(h1, h2);
michael@0 131 free_aligned_buffer_64(src_a);
michael@0 132 }
michael@0 133
michael@0 134 TEST_F(libyuvTest, BenchmarkDjb2_Unaligned) {
michael@0 135 const int kMaxTest = benchmark_width_ * benchmark_height_;
michael@0 136 align_buffer_64(src_a, kMaxTest + 1);
michael@0 137 for (int i = 0; i < kMaxTest; ++i) {
michael@0 138 src_a[i + 1] = i;
michael@0 139 }
michael@0 140 uint32 h2 = ReferenceHashDjb2(src_a + 1, kMaxTest, 5381);
michael@0 141 uint32 h1;
michael@0 142 for (int i = 0; i < benchmark_iterations_; ++i) {
michael@0 143 h1 = HashDjb2(src_a + 1, kMaxTest, 5381);
michael@0 144 }
michael@0 145 EXPECT_EQ(h1, h2);
michael@0 146 free_aligned_buffer_64(src_a);
michael@0 147 }
michael@0 148
michael@0 149 TEST_F(libyuvTest, BenchmarkSumSquareError_Opt) {
michael@0 150 const int kMaxWidth = 4096 * 3;
michael@0 151 align_buffer_64(src_a, kMaxWidth);
michael@0 152 align_buffer_64(src_b, kMaxWidth);
michael@0 153 memset(src_a, 0, kMaxWidth);
michael@0 154 memset(src_b, 0, kMaxWidth);
michael@0 155
michael@0 156 memcpy(src_a, "test0123test4567", 16);
michael@0 157 memcpy(src_b, "tick0123tock4567", 16);
michael@0 158 uint64 h1 = ComputeSumSquareError(src_a, src_b, 16);
michael@0 159 EXPECT_EQ(790u, h1);
michael@0 160
michael@0 161 for (int i = 0; i < kMaxWidth; ++i) {
michael@0 162 src_a[i] = i;
michael@0 163 src_b[i] = i;
michael@0 164 }
michael@0 165 memset(src_a, 0, kMaxWidth);
michael@0 166 memset(src_b, 0, kMaxWidth);
michael@0 167
michael@0 168 int count = benchmark_iterations_ *
michael@0 169 ((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth);
michael@0 170 for (int i = 0; i < count; ++i) {
michael@0 171 h1 = ComputeSumSquareError(src_a, src_b, kMaxWidth);
michael@0 172 }
michael@0 173
michael@0 174 EXPECT_EQ(0, h1);
michael@0 175
michael@0 176 free_aligned_buffer_64(src_a);
michael@0 177 free_aligned_buffer_64(src_b);
michael@0 178 }
michael@0 179
michael@0 180 TEST_F(libyuvTest, SumSquareError) {
michael@0 181 const int kMaxWidth = 4096 * 3;
michael@0 182 align_buffer_64(src_a, kMaxWidth);
michael@0 183 align_buffer_64(src_b, kMaxWidth);
michael@0 184 memset(src_a, 0, kMaxWidth);
michael@0 185 memset(src_b, 0, kMaxWidth);
michael@0 186
michael@0 187 uint64 err;
michael@0 188 err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
michael@0 189
michael@0 190 EXPECT_EQ(0, err);
michael@0 191
michael@0 192 memset(src_a, 1, kMaxWidth);
michael@0 193 err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
michael@0 194
michael@0 195 EXPECT_EQ(err, kMaxWidth);
michael@0 196
michael@0 197 memset(src_a, 190, kMaxWidth);
michael@0 198 memset(src_b, 193, kMaxWidth);
michael@0 199 err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
michael@0 200
michael@0 201 EXPECT_EQ(kMaxWidth * 3 * 3, err);
michael@0 202
michael@0 203 srandom(time(NULL));
michael@0 204
michael@0 205 for (int i = 0; i < kMaxWidth; ++i) {
michael@0 206 src_a[i] = (random() & 0xff);
michael@0 207 src_b[i] = (random() & 0xff);
michael@0 208 }
michael@0 209
michael@0 210 MaskCpuFlags(0);
michael@0 211 uint64 c_err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
michael@0 212
michael@0 213 MaskCpuFlags(-1);
michael@0 214 uint64 opt_err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
michael@0 215
michael@0 216 EXPECT_EQ(c_err, opt_err);
michael@0 217
michael@0 218 free_aligned_buffer_64(src_a);
michael@0 219 free_aligned_buffer_64(src_b);
michael@0 220 }
michael@0 221
michael@0 222 TEST_F(libyuvTest, BenchmarkPsnr_Opt) {
michael@0 223 align_buffer_64(src_a, benchmark_width_ * benchmark_height_);
michael@0 224 align_buffer_64(src_b, benchmark_width_ * benchmark_height_);
michael@0 225 for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
michael@0 226 src_a[i] = i;
michael@0 227 src_b[i] = i;
michael@0 228 }
michael@0 229
michael@0 230 MaskCpuFlags(-1);
michael@0 231
michael@0 232 double opt_time = get_time();
michael@0 233 for (int i = 0; i < benchmark_iterations_; ++i)
michael@0 234 CalcFramePsnr(src_a, benchmark_width_,
michael@0 235 src_b, benchmark_width_,
michael@0 236 benchmark_width_, benchmark_height_);
michael@0 237
michael@0 238 opt_time = (get_time() - opt_time) / benchmark_iterations_;
michael@0 239 printf("BenchmarkPsnr_Opt - %8.2f us opt\n", opt_time * 1e6);
michael@0 240
michael@0 241 EXPECT_EQ(0, 0);
michael@0 242
michael@0 243 free_aligned_buffer_64(src_a);
michael@0 244 free_aligned_buffer_64(src_b);
michael@0 245 }
michael@0 246
michael@0 247 TEST_F(libyuvTest, Psnr) {
michael@0 248 const int kSrcWidth = benchmark_width_;
michael@0 249 const int kSrcHeight = benchmark_height_;
michael@0 250 const int b = 128;
michael@0 251 const int kSrcPlaneSize = (kSrcWidth + b * 2) * (kSrcHeight + b * 2);
michael@0 252 const int kSrcStride = 2 * b + kSrcWidth;
michael@0 253 align_buffer_64(src_a, kSrcPlaneSize);
michael@0 254 align_buffer_64(src_b, kSrcPlaneSize);
michael@0 255 memset(src_a, 0, kSrcPlaneSize);
michael@0 256 memset(src_b, 0, kSrcPlaneSize);
michael@0 257
michael@0 258 double err;
michael@0 259 err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
michael@0 260 src_b + kSrcStride * b + b, kSrcStride,
michael@0 261 kSrcWidth, kSrcHeight);
michael@0 262
michael@0 263 EXPECT_EQ(err, kMaxPsnr);
michael@0 264
michael@0 265 memset(src_a, 255, kSrcPlaneSize);
michael@0 266
michael@0 267 err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
michael@0 268 src_b + kSrcStride * b + b, kSrcStride,
michael@0 269 kSrcWidth, kSrcHeight);
michael@0 270
michael@0 271 EXPECT_EQ(err, 0.0);
michael@0 272
michael@0 273 memset(src_a, 1, kSrcPlaneSize);
michael@0 274
michael@0 275 err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
michael@0 276 src_b + kSrcStride * b + b, kSrcStride,
michael@0 277 kSrcWidth, kSrcHeight);
michael@0 278
michael@0 279 EXPECT_GT(err, 48.0);
michael@0 280 EXPECT_LT(err, 49.0);
michael@0 281
michael@0 282 for (int i = 0; i < kSrcPlaneSize; ++i) {
michael@0 283 src_a[i] = i;
michael@0 284 }
michael@0 285
michael@0 286 err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
michael@0 287 src_b + kSrcStride * b + b, kSrcStride,
michael@0 288 kSrcWidth, kSrcHeight);
michael@0 289
michael@0 290 EXPECT_GT(err, 2.0);
michael@0 291 if (kSrcWidth * kSrcHeight >= 256) {
michael@0 292 EXPECT_LT(err, 6.0);
michael@0 293 }
michael@0 294
michael@0 295 srandom(time(NULL));
michael@0 296
michael@0 297 memset(src_a, 0, kSrcPlaneSize);
michael@0 298 memset(src_b, 0, kSrcPlaneSize);
michael@0 299
michael@0 300 for (int i = b; i < (kSrcHeight + b); ++i) {
michael@0 301 for (int j = b; j < (kSrcWidth + b); ++j) {
michael@0 302 src_a[(i * kSrcStride) + j] = (random() & 0xff);
michael@0 303 src_b[(i * kSrcStride) + j] = (random() & 0xff);
michael@0 304 }
michael@0 305 }
michael@0 306
michael@0 307 MaskCpuFlags(0);
michael@0 308 double c_err, opt_err;
michael@0 309
michael@0 310 c_err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
michael@0 311 src_b + kSrcStride * b + b, kSrcStride,
michael@0 312 kSrcWidth, kSrcHeight);
michael@0 313
michael@0 314 MaskCpuFlags(-1);
michael@0 315
michael@0 316 opt_err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
michael@0 317 src_b + kSrcStride * b + b, kSrcStride,
michael@0 318 kSrcWidth, kSrcHeight);
michael@0 319
michael@0 320 EXPECT_EQ(opt_err, c_err);
michael@0 321
michael@0 322 free_aligned_buffer_64(src_a);
michael@0 323 free_aligned_buffer_64(src_b);
michael@0 324 }
michael@0 325
michael@0 326 TEST_F(libyuvTest, DISABLED_BenchmarkSsim_Opt) {
michael@0 327 align_buffer_64(src_a, benchmark_width_ * benchmark_height_);
michael@0 328 align_buffer_64(src_b, benchmark_width_ * benchmark_height_);
michael@0 329 for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
michael@0 330 src_a[i] = i;
michael@0 331 src_b[i] = i;
michael@0 332 }
michael@0 333
michael@0 334 MaskCpuFlags(-1);
michael@0 335
michael@0 336 double opt_time = get_time();
michael@0 337 for (int i = 0; i < benchmark_iterations_; ++i)
michael@0 338 CalcFrameSsim(src_a, benchmark_width_,
michael@0 339 src_b, benchmark_width_,
michael@0 340 benchmark_width_, benchmark_height_);
michael@0 341
michael@0 342 opt_time = (get_time() - opt_time) / benchmark_iterations_;
michael@0 343 printf("BenchmarkSsim_Opt - %8.2f us opt\n", opt_time * 1e6);
michael@0 344
michael@0 345 EXPECT_EQ(0, 0); // Pass if we get this far.
michael@0 346
michael@0 347 free_aligned_buffer_64(src_a);
michael@0 348 free_aligned_buffer_64(src_b);
michael@0 349 }
michael@0 350
michael@0 351 TEST_F(libyuvTest, Ssim) {
michael@0 352 const int kSrcWidth = benchmark_width_;
michael@0 353 const int kSrcHeight = benchmark_height_;
michael@0 354 const int b = 128;
michael@0 355 const int kSrcPlaneSize = (kSrcWidth + b * 2) * (kSrcHeight + b * 2);
michael@0 356 const int kSrcStride = 2 * b + kSrcWidth;
michael@0 357 align_buffer_64(src_a, kSrcPlaneSize);
michael@0 358 align_buffer_64(src_b, kSrcPlaneSize);
michael@0 359 memset(src_a, 0, kSrcPlaneSize);
michael@0 360 memset(src_b, 0, kSrcPlaneSize);
michael@0 361
michael@0 362 if (kSrcWidth <=8 || kSrcHeight <= 8) {
michael@0 363 printf("warning - Ssim size too small. Testing function executes.\n");
michael@0 364 }
michael@0 365
michael@0 366 double err;
michael@0 367 err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
michael@0 368 src_b + kSrcStride * b + b, kSrcStride,
michael@0 369 kSrcWidth, kSrcHeight);
michael@0 370
michael@0 371 if (kSrcWidth > 8 && kSrcHeight > 8) {
michael@0 372 EXPECT_EQ(err, 1.0);
michael@0 373 }
michael@0 374
michael@0 375 memset(src_a, 255, kSrcPlaneSize);
michael@0 376
michael@0 377 err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
michael@0 378 src_b + kSrcStride * b + b, kSrcStride,
michael@0 379 kSrcWidth, kSrcHeight);
michael@0 380
michael@0 381 if (kSrcWidth > 8 && kSrcHeight > 8) {
michael@0 382 EXPECT_LT(err, 0.0001);
michael@0 383 }
michael@0 384
michael@0 385 memset(src_a, 1, kSrcPlaneSize);
michael@0 386
michael@0 387 err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
michael@0 388 src_b + kSrcStride * b + b, kSrcStride,
michael@0 389 kSrcWidth, kSrcHeight);
michael@0 390
michael@0 391 if (kSrcWidth > 8 && kSrcHeight > 8) {
michael@0 392 EXPECT_GT(err, 0.0001);
michael@0 393 EXPECT_LT(err, 0.9);
michael@0 394 }
michael@0 395
michael@0 396 for (int i = 0; i < kSrcPlaneSize; ++i) {
michael@0 397 src_a[i] = i;
michael@0 398 }
michael@0 399
michael@0 400 err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
michael@0 401 src_b + kSrcStride * b + b, kSrcStride,
michael@0 402 kSrcWidth, kSrcHeight);
michael@0 403
michael@0 404 if (kSrcWidth > 8 && kSrcHeight > 8) {
michael@0 405 EXPECT_GT(err, 0.0);
michael@0 406 EXPECT_LT(err, 0.01);
michael@0 407 }
michael@0 408
michael@0 409 srandom(time(NULL));
michael@0 410 for (int i = b; i < (kSrcHeight + b); ++i) {
michael@0 411 for (int j = b; j < (kSrcWidth + b); ++j) {
michael@0 412 src_a[(i * kSrcStride) + j] = (random() & 0xff);
michael@0 413 src_b[(i * kSrcStride) + j] = (random() & 0xff);
michael@0 414 }
michael@0 415 }
michael@0 416
michael@0 417 MaskCpuFlags(0);
michael@0 418 double c_err, opt_err;
michael@0 419
michael@0 420 c_err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
michael@0 421 src_b + kSrcStride * b + b, kSrcStride,
michael@0 422 kSrcWidth, kSrcHeight);
michael@0 423
michael@0 424 MaskCpuFlags(-1);
michael@0 425
michael@0 426 opt_err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
michael@0 427 src_b + kSrcStride * b + b, kSrcStride,
michael@0 428 kSrcWidth, kSrcHeight);
michael@0 429
michael@0 430 if (kSrcWidth > 8 && kSrcHeight > 8) {
michael@0 431 EXPECT_EQ(opt_err, c_err);
michael@0 432 }
michael@0 433
michael@0 434 free_aligned_buffer_64(src_a);
michael@0 435 free_aligned_buffer_64(src_b);
michael@0 436 }
michael@0 437
michael@0 438 } // namespace libyuv

mercurial