1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libyuv/unit_test/compare_test.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,438 @@ 1.4 +/* 1.5 + * Copyright 2011 The LibYuv Project Authors. All rights reserved. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license 1.8 + * that can be found in the LICENSE file in the root of the source 1.9 + * tree. An additional intellectual property rights grant can be found 1.10 + * in the file PATENTS. All contributing project authors may 1.11 + * be found in the AUTHORS file in the root of the source tree. 1.12 + */ 1.13 + 1.14 +#include <stdlib.h> 1.15 +#include <string.h> 1.16 +#include <time.h> 1.17 + 1.18 +#include "../unit_test/unit_test.h" 1.19 +#include "libyuv/basic_types.h" 1.20 +#include "libyuv/compare.h" 1.21 +#include "libyuv/cpu_id.h" 1.22 +#include "libyuv/row.h" 1.23 + 1.24 +namespace libyuv { 1.25 + 1.26 +// hash seed of 5381 recommended. 1.27 +static uint32 ReferenceHashDjb2(const uint8* src, uint64 count, uint32 seed) { 1.28 + uint32 hash = seed; 1.29 + if (count > 0) { 1.30 + do { 1.31 + hash = hash * 33 + *src++; 1.32 + } while (--count); 1.33 + } 1.34 + return hash; 1.35 +} 1.36 + 1.37 +TEST_F(libyuvTest, Djb2_Test) { 1.38 + const int kMaxTest = benchmark_width_ * benchmark_height_; 1.39 + align_buffer_64(src_a, kMaxTest); 1.40 + align_buffer_64(src_b, kMaxTest); 1.41 + 1.42 + const char* fox = "The quick brown fox jumps over the lazy dog" 1.43 + " and feels as if he were in the seventh heaven of typography" 1.44 + " together with Hermann Zapf"; 1.45 + uint32 foxhash = HashDjb2(reinterpret_cast<const uint8*>(fox), 131, 5381); 1.46 + const uint32 kExpectedFoxHash = 2611006483u; 1.47 + EXPECT_EQ(kExpectedFoxHash, foxhash); 1.48 + 1.49 + for (int i = 0; i < kMaxTest; ++i) { 1.50 + src_a[i] = (random() & 0xff); 1.51 + src_b[i] = (random() & 0xff); 1.52 + } 1.53 + // Compare different buffers. Expect hash is different. 1.54 + uint32 h1 = HashDjb2(src_a, kMaxTest, 5381); 1.55 + uint32 h2 = HashDjb2(src_b, kMaxTest, 5381); 1.56 + EXPECT_NE(h1, h2); 1.57 + 1.58 + // Make last half same. Expect hash is different. 1.59 + memcpy(src_a + kMaxTest / 2, src_b + kMaxTest / 2, kMaxTest / 2); 1.60 + h1 = HashDjb2(src_a, kMaxTest, 5381); 1.61 + h2 = HashDjb2(src_b, kMaxTest, 5381); 1.62 + EXPECT_NE(h1, h2); 1.63 + 1.64 + // Make first half same. Expect hash is different. 1.65 + memcpy(src_a + kMaxTest / 2, src_a, kMaxTest / 2); 1.66 + memcpy(src_b + kMaxTest / 2, src_b, kMaxTest / 2); 1.67 + memcpy(src_a, src_b, kMaxTest / 2); 1.68 + h1 = HashDjb2(src_a, kMaxTest, 5381); 1.69 + h2 = HashDjb2(src_b, kMaxTest, 5381); 1.70 + EXPECT_NE(h1, h2); 1.71 + 1.72 + // Make same. Expect hash is same. 1.73 + memcpy(src_a, src_b, kMaxTest); 1.74 + h1 = HashDjb2(src_a, kMaxTest, 5381); 1.75 + h2 = HashDjb2(src_b, kMaxTest, 5381); 1.76 + EXPECT_EQ(h1, h2); 1.77 + 1.78 + // Mask seed different. Expect hash is different. 1.79 + memcpy(src_a, src_b, kMaxTest); 1.80 + h1 = HashDjb2(src_a, kMaxTest, 5381); 1.81 + h2 = HashDjb2(src_b, kMaxTest, 1234); 1.82 + EXPECT_NE(h1, h2); 1.83 + 1.84 + // Make one byte different in middle. Expect hash is different. 1.85 + memcpy(src_a, src_b, kMaxTest); 1.86 + ++src_b[kMaxTest / 2]; 1.87 + h1 = HashDjb2(src_a, kMaxTest, 5381); 1.88 + h2 = HashDjb2(src_b, kMaxTest, 5381); 1.89 + EXPECT_NE(h1, h2); 1.90 + 1.91 + // Make first byte different. Expect hash is different. 1.92 + memcpy(src_a, src_b, kMaxTest); 1.93 + ++src_b[0]; 1.94 + h1 = HashDjb2(src_a, kMaxTest, 5381); 1.95 + h2 = HashDjb2(src_b, kMaxTest, 5381); 1.96 + EXPECT_NE(h1, h2); 1.97 + 1.98 + // Make last byte different. Expect hash is different. 1.99 + memcpy(src_a, src_b, kMaxTest); 1.100 + ++src_b[kMaxTest - 1]; 1.101 + h1 = HashDjb2(src_a, kMaxTest, 5381); 1.102 + h2 = HashDjb2(src_b, kMaxTest, 5381); 1.103 + EXPECT_NE(h1, h2); 1.104 + 1.105 + // Make a zeros. Test different lengths. Expect hash is different. 1.106 + memset(src_a, 0, kMaxTest); 1.107 + h1 = HashDjb2(src_a, kMaxTest, 5381); 1.108 + h2 = HashDjb2(src_a, kMaxTest / 2, 5381); 1.109 + EXPECT_NE(h1, h2); 1.110 + 1.111 + // Make a zeros and seed of zero. Test different lengths. Expect hash is same. 1.112 + memset(src_a, 0, kMaxTest); 1.113 + h1 = HashDjb2(src_a, kMaxTest, 0); 1.114 + h2 = HashDjb2(src_a, kMaxTest / 2, 0); 1.115 + EXPECT_EQ(h1, h2); 1.116 + 1.117 + free_aligned_buffer_64(src_a); 1.118 + free_aligned_buffer_64(src_b); 1.119 +} 1.120 + 1.121 +TEST_F(libyuvTest, BenchmarkDjb2_Opt) { 1.122 + const int kMaxTest = benchmark_width_ * benchmark_height_; 1.123 + align_buffer_64(src_a, kMaxTest); 1.124 + 1.125 + for (int i = 0; i < kMaxTest; ++i) { 1.126 + src_a[i] = i; 1.127 + } 1.128 + uint32 h2 = ReferenceHashDjb2(src_a, kMaxTest, 5381); 1.129 + uint32 h1; 1.130 + for (int i = 0; i < benchmark_iterations_; ++i) { 1.131 + h1 = HashDjb2(src_a, kMaxTest, 5381); 1.132 + } 1.133 + EXPECT_EQ(h1, h2); 1.134 + free_aligned_buffer_64(src_a); 1.135 +} 1.136 + 1.137 +TEST_F(libyuvTest, BenchmarkDjb2_Unaligned) { 1.138 + const int kMaxTest = benchmark_width_ * benchmark_height_; 1.139 + align_buffer_64(src_a, kMaxTest + 1); 1.140 + for (int i = 0; i < kMaxTest; ++i) { 1.141 + src_a[i + 1] = i; 1.142 + } 1.143 + uint32 h2 = ReferenceHashDjb2(src_a + 1, kMaxTest, 5381); 1.144 + uint32 h1; 1.145 + for (int i = 0; i < benchmark_iterations_; ++i) { 1.146 + h1 = HashDjb2(src_a + 1, kMaxTest, 5381); 1.147 + } 1.148 + EXPECT_EQ(h1, h2); 1.149 + free_aligned_buffer_64(src_a); 1.150 +} 1.151 + 1.152 +TEST_F(libyuvTest, BenchmarkSumSquareError_Opt) { 1.153 + const int kMaxWidth = 4096 * 3; 1.154 + align_buffer_64(src_a, kMaxWidth); 1.155 + align_buffer_64(src_b, kMaxWidth); 1.156 + memset(src_a, 0, kMaxWidth); 1.157 + memset(src_b, 0, kMaxWidth); 1.158 + 1.159 + memcpy(src_a, "test0123test4567", 16); 1.160 + memcpy(src_b, "tick0123tock4567", 16); 1.161 + uint64 h1 = ComputeSumSquareError(src_a, src_b, 16); 1.162 + EXPECT_EQ(790u, h1); 1.163 + 1.164 + for (int i = 0; i < kMaxWidth; ++i) { 1.165 + src_a[i] = i; 1.166 + src_b[i] = i; 1.167 + } 1.168 + memset(src_a, 0, kMaxWidth); 1.169 + memset(src_b, 0, kMaxWidth); 1.170 + 1.171 + int count = benchmark_iterations_ * 1.172 + ((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth); 1.173 + for (int i = 0; i < count; ++i) { 1.174 + h1 = ComputeSumSquareError(src_a, src_b, kMaxWidth); 1.175 + } 1.176 + 1.177 + EXPECT_EQ(0, h1); 1.178 + 1.179 + free_aligned_buffer_64(src_a); 1.180 + free_aligned_buffer_64(src_b); 1.181 +} 1.182 + 1.183 +TEST_F(libyuvTest, SumSquareError) { 1.184 + const int kMaxWidth = 4096 * 3; 1.185 + align_buffer_64(src_a, kMaxWidth); 1.186 + align_buffer_64(src_b, kMaxWidth); 1.187 + memset(src_a, 0, kMaxWidth); 1.188 + memset(src_b, 0, kMaxWidth); 1.189 + 1.190 + uint64 err; 1.191 + err = ComputeSumSquareError(src_a, src_b, kMaxWidth); 1.192 + 1.193 + EXPECT_EQ(0, err); 1.194 + 1.195 + memset(src_a, 1, kMaxWidth); 1.196 + err = ComputeSumSquareError(src_a, src_b, kMaxWidth); 1.197 + 1.198 + EXPECT_EQ(err, kMaxWidth); 1.199 + 1.200 + memset(src_a, 190, kMaxWidth); 1.201 + memset(src_b, 193, kMaxWidth); 1.202 + err = ComputeSumSquareError(src_a, src_b, kMaxWidth); 1.203 + 1.204 + EXPECT_EQ(kMaxWidth * 3 * 3, err); 1.205 + 1.206 + srandom(time(NULL)); 1.207 + 1.208 + for (int i = 0; i < kMaxWidth; ++i) { 1.209 + src_a[i] = (random() & 0xff); 1.210 + src_b[i] = (random() & 0xff); 1.211 + } 1.212 + 1.213 + MaskCpuFlags(0); 1.214 + uint64 c_err = ComputeSumSquareError(src_a, src_b, kMaxWidth); 1.215 + 1.216 + MaskCpuFlags(-1); 1.217 + uint64 opt_err = ComputeSumSquareError(src_a, src_b, kMaxWidth); 1.218 + 1.219 + EXPECT_EQ(c_err, opt_err); 1.220 + 1.221 + free_aligned_buffer_64(src_a); 1.222 + free_aligned_buffer_64(src_b); 1.223 +} 1.224 + 1.225 +TEST_F(libyuvTest, BenchmarkPsnr_Opt) { 1.226 + align_buffer_64(src_a, benchmark_width_ * benchmark_height_); 1.227 + align_buffer_64(src_b, benchmark_width_ * benchmark_height_); 1.228 + for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) { 1.229 + src_a[i] = i; 1.230 + src_b[i] = i; 1.231 + } 1.232 + 1.233 + MaskCpuFlags(-1); 1.234 + 1.235 + double opt_time = get_time(); 1.236 + for (int i = 0; i < benchmark_iterations_; ++i) 1.237 + CalcFramePsnr(src_a, benchmark_width_, 1.238 + src_b, benchmark_width_, 1.239 + benchmark_width_, benchmark_height_); 1.240 + 1.241 + opt_time = (get_time() - opt_time) / benchmark_iterations_; 1.242 + printf("BenchmarkPsnr_Opt - %8.2f us opt\n", opt_time * 1e6); 1.243 + 1.244 + EXPECT_EQ(0, 0); 1.245 + 1.246 + free_aligned_buffer_64(src_a); 1.247 + free_aligned_buffer_64(src_b); 1.248 +} 1.249 + 1.250 +TEST_F(libyuvTest, Psnr) { 1.251 + const int kSrcWidth = benchmark_width_; 1.252 + const int kSrcHeight = benchmark_height_; 1.253 + const int b = 128; 1.254 + const int kSrcPlaneSize = (kSrcWidth + b * 2) * (kSrcHeight + b * 2); 1.255 + const int kSrcStride = 2 * b + kSrcWidth; 1.256 + align_buffer_64(src_a, kSrcPlaneSize); 1.257 + align_buffer_64(src_b, kSrcPlaneSize); 1.258 + memset(src_a, 0, kSrcPlaneSize); 1.259 + memset(src_b, 0, kSrcPlaneSize); 1.260 + 1.261 + double err; 1.262 + err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride, 1.263 + src_b + kSrcStride * b + b, kSrcStride, 1.264 + kSrcWidth, kSrcHeight); 1.265 + 1.266 + EXPECT_EQ(err, kMaxPsnr); 1.267 + 1.268 + memset(src_a, 255, kSrcPlaneSize); 1.269 + 1.270 + err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride, 1.271 + src_b + kSrcStride * b + b, kSrcStride, 1.272 + kSrcWidth, kSrcHeight); 1.273 + 1.274 + EXPECT_EQ(err, 0.0); 1.275 + 1.276 + memset(src_a, 1, kSrcPlaneSize); 1.277 + 1.278 + err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride, 1.279 + src_b + kSrcStride * b + b, kSrcStride, 1.280 + kSrcWidth, kSrcHeight); 1.281 + 1.282 + EXPECT_GT(err, 48.0); 1.283 + EXPECT_LT(err, 49.0); 1.284 + 1.285 + for (int i = 0; i < kSrcPlaneSize; ++i) { 1.286 + src_a[i] = i; 1.287 + } 1.288 + 1.289 + err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride, 1.290 + src_b + kSrcStride * b + b, kSrcStride, 1.291 + kSrcWidth, kSrcHeight); 1.292 + 1.293 + EXPECT_GT(err, 2.0); 1.294 + if (kSrcWidth * kSrcHeight >= 256) { 1.295 + EXPECT_LT(err, 6.0); 1.296 + } 1.297 + 1.298 + srandom(time(NULL)); 1.299 + 1.300 + memset(src_a, 0, kSrcPlaneSize); 1.301 + memset(src_b, 0, kSrcPlaneSize); 1.302 + 1.303 + for (int i = b; i < (kSrcHeight + b); ++i) { 1.304 + for (int j = b; j < (kSrcWidth + b); ++j) { 1.305 + src_a[(i * kSrcStride) + j] = (random() & 0xff); 1.306 + src_b[(i * kSrcStride) + j] = (random() & 0xff); 1.307 + } 1.308 + } 1.309 + 1.310 + MaskCpuFlags(0); 1.311 + double c_err, opt_err; 1.312 + 1.313 + c_err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride, 1.314 + src_b + kSrcStride * b + b, kSrcStride, 1.315 + kSrcWidth, kSrcHeight); 1.316 + 1.317 + MaskCpuFlags(-1); 1.318 + 1.319 + opt_err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride, 1.320 + src_b + kSrcStride * b + b, kSrcStride, 1.321 + kSrcWidth, kSrcHeight); 1.322 + 1.323 + EXPECT_EQ(opt_err, c_err); 1.324 + 1.325 + free_aligned_buffer_64(src_a); 1.326 + free_aligned_buffer_64(src_b); 1.327 +} 1.328 + 1.329 +TEST_F(libyuvTest, DISABLED_BenchmarkSsim_Opt) { 1.330 + align_buffer_64(src_a, benchmark_width_ * benchmark_height_); 1.331 + align_buffer_64(src_b, benchmark_width_ * benchmark_height_); 1.332 + for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) { 1.333 + src_a[i] = i; 1.334 + src_b[i] = i; 1.335 + } 1.336 + 1.337 + MaskCpuFlags(-1); 1.338 + 1.339 + double opt_time = get_time(); 1.340 + for (int i = 0; i < benchmark_iterations_; ++i) 1.341 + CalcFrameSsim(src_a, benchmark_width_, 1.342 + src_b, benchmark_width_, 1.343 + benchmark_width_, benchmark_height_); 1.344 + 1.345 + opt_time = (get_time() - opt_time) / benchmark_iterations_; 1.346 + printf("BenchmarkSsim_Opt - %8.2f us opt\n", opt_time * 1e6); 1.347 + 1.348 + EXPECT_EQ(0, 0); // Pass if we get this far. 1.349 + 1.350 + free_aligned_buffer_64(src_a); 1.351 + free_aligned_buffer_64(src_b); 1.352 +} 1.353 + 1.354 +TEST_F(libyuvTest, Ssim) { 1.355 + const int kSrcWidth = benchmark_width_; 1.356 + const int kSrcHeight = benchmark_height_; 1.357 + const int b = 128; 1.358 + const int kSrcPlaneSize = (kSrcWidth + b * 2) * (kSrcHeight + b * 2); 1.359 + const int kSrcStride = 2 * b + kSrcWidth; 1.360 + align_buffer_64(src_a, kSrcPlaneSize); 1.361 + align_buffer_64(src_b, kSrcPlaneSize); 1.362 + memset(src_a, 0, kSrcPlaneSize); 1.363 + memset(src_b, 0, kSrcPlaneSize); 1.364 + 1.365 + if (kSrcWidth <=8 || kSrcHeight <= 8) { 1.366 + printf("warning - Ssim size too small. Testing function executes.\n"); 1.367 + } 1.368 + 1.369 + double err; 1.370 + err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride, 1.371 + src_b + kSrcStride * b + b, kSrcStride, 1.372 + kSrcWidth, kSrcHeight); 1.373 + 1.374 + if (kSrcWidth > 8 && kSrcHeight > 8) { 1.375 + EXPECT_EQ(err, 1.0); 1.376 + } 1.377 + 1.378 + memset(src_a, 255, kSrcPlaneSize); 1.379 + 1.380 + err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride, 1.381 + src_b + kSrcStride * b + b, kSrcStride, 1.382 + kSrcWidth, kSrcHeight); 1.383 + 1.384 + if (kSrcWidth > 8 && kSrcHeight > 8) { 1.385 + EXPECT_LT(err, 0.0001); 1.386 + } 1.387 + 1.388 + memset(src_a, 1, kSrcPlaneSize); 1.389 + 1.390 + err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride, 1.391 + src_b + kSrcStride * b + b, kSrcStride, 1.392 + kSrcWidth, kSrcHeight); 1.393 + 1.394 + if (kSrcWidth > 8 && kSrcHeight > 8) { 1.395 + EXPECT_GT(err, 0.0001); 1.396 + EXPECT_LT(err, 0.9); 1.397 + } 1.398 + 1.399 + for (int i = 0; i < kSrcPlaneSize; ++i) { 1.400 + src_a[i] = i; 1.401 + } 1.402 + 1.403 + err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride, 1.404 + src_b + kSrcStride * b + b, kSrcStride, 1.405 + kSrcWidth, kSrcHeight); 1.406 + 1.407 + if (kSrcWidth > 8 && kSrcHeight > 8) { 1.408 + EXPECT_GT(err, 0.0); 1.409 + EXPECT_LT(err, 0.01); 1.410 + } 1.411 + 1.412 + srandom(time(NULL)); 1.413 + for (int i = b; i < (kSrcHeight + b); ++i) { 1.414 + for (int j = b; j < (kSrcWidth + b); ++j) { 1.415 + src_a[(i * kSrcStride) + j] = (random() & 0xff); 1.416 + src_b[(i * kSrcStride) + j] = (random() & 0xff); 1.417 + } 1.418 + } 1.419 + 1.420 + MaskCpuFlags(0); 1.421 + double c_err, opt_err; 1.422 + 1.423 + c_err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride, 1.424 + src_b + kSrcStride * b + b, kSrcStride, 1.425 + kSrcWidth, kSrcHeight); 1.426 + 1.427 + MaskCpuFlags(-1); 1.428 + 1.429 + opt_err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride, 1.430 + src_b + kSrcStride * b + b, kSrcStride, 1.431 + kSrcWidth, kSrcHeight); 1.432 + 1.433 + if (kSrcWidth > 8 && kSrcHeight > 8) { 1.434 + EXPECT_EQ(opt_err, c_err); 1.435 + } 1.436 + 1.437 + free_aligned_buffer_64(src_a); 1.438 + free_aligned_buffer_64(src_b); 1.439 +} 1.440 + 1.441 +} // namespace libyuv