compare_test.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  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. #include <stdlib.h>
  11. #include <string.h>
  12. #include <time.h>
  13. #include "../unit_test/unit_test.h"
  14. #include "libyuv/basic_types.h"
  15. #include "libyuv/compare.h"
  16. #include "libyuv/cpu_id.h"
  17. #include "libyuv/video_common.h"
  18. #ifdef ENABLE_ROW_TESTS
  19. #include "libyuv/compare_row.h" /* For HammingDistance_C */
  20. #endif
  21. namespace libyuv {
  22. // hash seed of 5381 recommended.
  23. static uint32_t ReferenceHashDjb2(const uint8_t* src,
  24. uint64_t count,
  25. uint32_t seed) {
  26. uint32_t hash = seed;
  27. if (count > 0) {
  28. do {
  29. hash = hash * 33 + *src++;
  30. } while (--count);
  31. }
  32. return hash;
  33. }
  34. TEST_F(LibYUVCompareTest, Djb2_Test) {
  35. const int kMaxTest = benchmark_width_ * benchmark_height_;
  36. align_buffer_page_end(src_a, kMaxTest);
  37. align_buffer_page_end(src_b, kMaxTest);
  38. const char* fox =
  39. "The quick brown fox jumps over the lazy dog"
  40. " and feels as if he were in the seventh heaven of typography"
  41. " together with Hermann Zapf";
  42. uint32_t foxhash = HashDjb2(reinterpret_cast<const uint8_t*>(fox), 131, 5381);
  43. const uint32_t kExpectedFoxHash = 2611006483u;
  44. EXPECT_EQ(kExpectedFoxHash, foxhash);
  45. for (int i = 0; i < kMaxTest; ++i) {
  46. src_a[i] = (fastrand() & 0xff);
  47. src_b[i] = (fastrand() & 0xff);
  48. }
  49. // Compare different buffers. Expect hash is different.
  50. uint32_t h1 = HashDjb2(src_a, kMaxTest, 5381);
  51. uint32_t h2 = HashDjb2(src_b, kMaxTest, 5381);
  52. EXPECT_NE(h1, h2);
  53. // Make last half same. Expect hash is different.
  54. memcpy(src_a + kMaxTest / 2, src_b + kMaxTest / 2, kMaxTest / 2);
  55. h1 = HashDjb2(src_a, kMaxTest, 5381);
  56. h2 = HashDjb2(src_b, kMaxTest, 5381);
  57. EXPECT_NE(h1, h2);
  58. // Make first half same. Expect hash is different.
  59. memcpy(src_a + kMaxTest / 2, src_a, kMaxTest / 2);
  60. memcpy(src_b + kMaxTest / 2, src_b, kMaxTest / 2);
  61. memcpy(src_a, src_b, kMaxTest / 2);
  62. h1 = HashDjb2(src_a, kMaxTest, 5381);
  63. h2 = HashDjb2(src_b, kMaxTest, 5381);
  64. EXPECT_NE(h1, h2);
  65. // Make same. Expect hash is same.
  66. memcpy(src_a, src_b, kMaxTest);
  67. h1 = HashDjb2(src_a, kMaxTest, 5381);
  68. h2 = HashDjb2(src_b, kMaxTest, 5381);
  69. EXPECT_EQ(h1, h2);
  70. // Mask seed different. Expect hash is different.
  71. memcpy(src_a, src_b, kMaxTest);
  72. h1 = HashDjb2(src_a, kMaxTest, 5381);
  73. h2 = HashDjb2(src_b, kMaxTest, 1234);
  74. EXPECT_NE(h1, h2);
  75. // Make one byte different in middle. Expect hash is different.
  76. memcpy(src_a, src_b, kMaxTest);
  77. ++src_b[kMaxTest / 2];
  78. h1 = HashDjb2(src_a, kMaxTest, 5381);
  79. h2 = HashDjb2(src_b, kMaxTest, 5381);
  80. EXPECT_NE(h1, h2);
  81. // Make first byte different. Expect hash is different.
  82. memcpy(src_a, src_b, kMaxTest);
  83. ++src_b[0];
  84. h1 = HashDjb2(src_a, kMaxTest, 5381);
  85. h2 = HashDjb2(src_b, kMaxTest, 5381);
  86. EXPECT_NE(h1, h2);
  87. // Make last byte different. Expect hash is different.
  88. memcpy(src_a, src_b, kMaxTest);
  89. ++src_b[kMaxTest - 1];
  90. h1 = HashDjb2(src_a, kMaxTest, 5381);
  91. h2 = HashDjb2(src_b, kMaxTest, 5381);
  92. EXPECT_NE(h1, h2);
  93. // Make a zeros. Test different lengths. Expect hash is different.
  94. memset(src_a, 0, kMaxTest);
  95. h1 = HashDjb2(src_a, kMaxTest, 5381);
  96. h2 = HashDjb2(src_a, kMaxTest / 2, 5381);
  97. EXPECT_NE(h1, h2);
  98. // Make a zeros and seed of zero. Test different lengths. Expect hash is same.
  99. memset(src_a, 0, kMaxTest);
  100. h1 = HashDjb2(src_a, kMaxTest, 0);
  101. h2 = HashDjb2(src_a, kMaxTest / 2, 0);
  102. EXPECT_EQ(h1, h2);
  103. free_aligned_buffer_page_end(src_a);
  104. free_aligned_buffer_page_end(src_b);
  105. }
  106. TEST_F(LibYUVCompareTest, BenchmarkDjb2_Opt) {
  107. const int kMaxTest = benchmark_width_ * benchmark_height_;
  108. align_buffer_page_end(src_a, kMaxTest);
  109. for (int i = 0; i < kMaxTest; ++i) {
  110. src_a[i] = i;
  111. }
  112. uint32_t h2 = ReferenceHashDjb2(src_a, kMaxTest, 5381);
  113. uint32_t h1;
  114. for (int i = 0; i < benchmark_iterations_; ++i) {
  115. h1 = HashDjb2(src_a, kMaxTest, 5381);
  116. }
  117. EXPECT_EQ(h1, h2);
  118. free_aligned_buffer_page_end(src_a);
  119. }
  120. TEST_F(LibYUVCompareTest, BenchmarkDjb2_Unaligned) {
  121. const int kMaxTest = benchmark_width_ * benchmark_height_;
  122. align_buffer_page_end(src_a, kMaxTest + 1);
  123. for (int i = 0; i < kMaxTest; ++i) {
  124. src_a[i + 1] = i;
  125. }
  126. uint32_t h2 = ReferenceHashDjb2(src_a + 1, kMaxTest, 5381);
  127. uint32_t h1;
  128. for (int i = 0; i < benchmark_iterations_; ++i) {
  129. h1 = HashDjb2(src_a + 1, kMaxTest, 5381);
  130. }
  131. EXPECT_EQ(h1, h2);
  132. free_aligned_buffer_page_end(src_a);
  133. }
  134. TEST_F(LibYUVCompareTest, BenchmarkARGBDetect_Opt) {
  135. uint32_t fourcc;
  136. const int kMaxTest = benchmark_width_ * benchmark_height_ * 4;
  137. align_buffer_page_end(src_a, kMaxTest);
  138. for (int i = 0; i < kMaxTest; ++i) {
  139. src_a[i] = 255;
  140. }
  141. src_a[0] = 0;
  142. fourcc = ARGBDetect(src_a, benchmark_width_ * 4, benchmark_width_,
  143. benchmark_height_);
  144. EXPECT_EQ(static_cast<uint32_t>(libyuv::FOURCC_BGRA), fourcc);
  145. src_a[0] = 255;
  146. src_a[3] = 0;
  147. fourcc = ARGBDetect(src_a, benchmark_width_ * 4, benchmark_width_,
  148. benchmark_height_);
  149. EXPECT_EQ(static_cast<uint32_t>(libyuv::FOURCC_ARGB), fourcc);
  150. src_a[3] = 255;
  151. for (int i = 0; i < benchmark_iterations_; ++i) {
  152. fourcc = ARGBDetect(src_a, benchmark_width_ * 4, benchmark_width_,
  153. benchmark_height_);
  154. }
  155. EXPECT_EQ(0u, fourcc);
  156. free_aligned_buffer_page_end(src_a);
  157. }
  158. TEST_F(LibYUVCompareTest, BenchmarkARGBDetect_Unaligned) {
  159. uint32_t fourcc;
  160. const int kMaxTest = benchmark_width_ * benchmark_height_ * 4 + 1;
  161. align_buffer_page_end(src_a, kMaxTest);
  162. for (int i = 1; i < kMaxTest; ++i) {
  163. src_a[i] = 255;
  164. }
  165. src_a[0 + 1] = 0;
  166. fourcc = ARGBDetect(src_a + 1, benchmark_width_ * 4, benchmark_width_,
  167. benchmark_height_);
  168. EXPECT_EQ(static_cast<uint32_t>(libyuv::FOURCC_BGRA), fourcc);
  169. src_a[0 + 1] = 255;
  170. src_a[3 + 1] = 0;
  171. fourcc = ARGBDetect(src_a + 1, benchmark_width_ * 4, benchmark_width_,
  172. benchmark_height_);
  173. EXPECT_EQ(static_cast<uint32_t>(libyuv::FOURCC_ARGB), fourcc);
  174. src_a[3 + 1] = 255;
  175. for (int i = 0; i < benchmark_iterations_; ++i) {
  176. fourcc = ARGBDetect(src_a + 1, benchmark_width_ * 4, benchmark_width_,
  177. benchmark_height_);
  178. }
  179. EXPECT_EQ(0u, fourcc);
  180. free_aligned_buffer_page_end(src_a);
  181. }
  182. #ifdef ENABLE_ROW_TESTS
  183. TEST_F(LibYUVCompareTest, BenchmarkHammingDistance_Opt) {
  184. const int kMaxWidth = 4096 * 3;
  185. align_buffer_page_end(src_a, kMaxWidth);
  186. align_buffer_page_end(src_b, kMaxWidth);
  187. memset(src_a, 0, kMaxWidth);
  188. memset(src_b, 0, kMaxWidth);
  189. // Test known value
  190. memcpy(src_a, "test0123test4567", 16);
  191. memcpy(src_b, "tick0123tock4567", 16);
  192. uint32_t h1 = HammingDistance_C(src_a, src_b, 16);
  193. EXPECT_EQ(16u, h1);
  194. // Test C vs OPT on random buffer
  195. MemRandomize(src_a, kMaxWidth);
  196. MemRandomize(src_b, kMaxWidth);
  197. uint32_t h0 = HammingDistance_C(src_a, src_b, kMaxWidth);
  198. int count =
  199. benchmark_iterations_ *
  200. ((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth);
  201. for (int i = 0; i < count; ++i) {
  202. #if defined(HAS_HAMMINGDISTANCE_NEON)
  203. h1 = HammingDistance_NEON(src_a, src_b, kMaxWidth);
  204. #elif defined(HAS_HAMMINGDISTANCE_AVX2)
  205. int has_avx2 = TestCpuFlag(kCpuHasAVX2);
  206. if (has_avx2) {
  207. h1 = HammingDistance_AVX2(src_a, src_b, kMaxWidth);
  208. } else {
  209. int has_sse42 = TestCpuFlag(kCpuHasSSE42);
  210. if (has_sse42) {
  211. h1 = HammingDistance_SSE42(src_a, src_b, kMaxWidth);
  212. } else {
  213. int has_ssse3 = TestCpuFlag(kCpuHasSSSE3);
  214. if (has_ssse3) {
  215. h1 = HammingDistance_SSSE3(src_a, src_b, kMaxWidth);
  216. } else {
  217. h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
  218. }
  219. }
  220. }
  221. #elif defined(HAS_HAMMINGDISTANCE_SSE42)
  222. int has_sse42 = TestCpuFlag(kCpuHasSSE42);
  223. if (has_sse42) {
  224. h1 = HammingDistance_SSE42(src_a, src_b, kMaxWidth);
  225. } else {
  226. h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
  227. }
  228. #else
  229. h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
  230. #endif
  231. }
  232. EXPECT_EQ(h0, h1);
  233. free_aligned_buffer_page_end(src_a);
  234. free_aligned_buffer_page_end(src_b);
  235. }
  236. TEST_F(LibYUVCompareTest, BenchmarkHammingDistance_C) {
  237. const int kMaxWidth = 4096 * 3;
  238. align_buffer_page_end(src_a, kMaxWidth);
  239. align_buffer_page_end(src_b, kMaxWidth);
  240. memset(src_a, 0, kMaxWidth);
  241. memset(src_b, 0, kMaxWidth);
  242. // Test known value
  243. memcpy(src_a, "test0123test4567", 16);
  244. memcpy(src_b, "tick0123tock4567", 16);
  245. uint32_t h1 = HammingDistance_C(src_a, src_b, 16);
  246. EXPECT_EQ(16u, h1);
  247. // Test C vs OPT on random buffer
  248. MemRandomize(src_a, kMaxWidth);
  249. MemRandomize(src_b, kMaxWidth);
  250. uint32_t h0 = HammingDistance_C(src_a, src_b, kMaxWidth);
  251. int count =
  252. benchmark_iterations_ *
  253. ((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth);
  254. for (int i = 0; i < count; ++i) {
  255. h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
  256. }
  257. EXPECT_EQ(h0, h1);
  258. free_aligned_buffer_page_end(src_a);
  259. free_aligned_buffer_page_end(src_b);
  260. }
  261. TEST_F(LibYUVCompareTest, BenchmarkHammingDistance) {
  262. const int kMaxWidth = 4096 * 3;
  263. align_buffer_page_end(src_a, kMaxWidth);
  264. align_buffer_page_end(src_b, kMaxWidth);
  265. memset(src_a, 0, kMaxWidth);
  266. memset(src_b, 0, kMaxWidth);
  267. memcpy(src_a, "test0123test4567", 16);
  268. memcpy(src_b, "tick0123tock4567", 16);
  269. uint64_t h1 = ComputeHammingDistance(src_a, src_b, 16);
  270. EXPECT_EQ(16u, h1);
  271. // Test C vs OPT on random buffer
  272. MemRandomize(src_a, kMaxWidth);
  273. MemRandomize(src_b, kMaxWidth);
  274. uint32_t h0 = HammingDistance_C(src_a, src_b, kMaxWidth);
  275. int count =
  276. benchmark_iterations_ *
  277. ((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth);
  278. for (int i = 0; i < count; ++i) {
  279. h1 = ComputeHammingDistance(src_a, src_b, kMaxWidth);
  280. }
  281. EXPECT_EQ(h0, h1);
  282. free_aligned_buffer_page_end(src_a);
  283. free_aligned_buffer_page_end(src_b);
  284. }
  285. // Tests low levels match reference C for specified size.
  286. // The opt implementations have size limitations
  287. // For NEON the counters are 16 bit so the shorts overflow after 65536 bytes.
  288. // So doing one less iteration of the loop is the maximum.
  289. #if defined(HAS_HAMMINGDISTANCE_NEON)
  290. static const int kMaxOptCount = 65536 - 32; // 65504
  291. #else
  292. static const int kMaxOptCount = (1 << (32 - 3)) - 64; // 536870848
  293. #endif
  294. TEST_F(LibYUVCompareTest, TestHammingDistance_Opt) {
  295. uint32_t h1 = 0;
  296. const int kMaxWidth = (benchmark_width_ * benchmark_height_ + 31) & ~31;
  297. align_buffer_page_end(src_a, kMaxWidth);
  298. align_buffer_page_end(src_b, kMaxWidth);
  299. memset(src_a, 255u, kMaxWidth);
  300. memset(src_b, 0u, kMaxWidth);
  301. uint64_t h0 = ComputeHammingDistance(src_a, src_b, kMaxWidth);
  302. EXPECT_EQ(kMaxWidth * 8ULL, h0);
  303. for (int i = 0; i < benchmark_iterations_; ++i) {
  304. #if defined(HAS_HAMMINGDISTANCE_NEON)
  305. h1 = HammingDistance_NEON(src_a, src_b, kMaxWidth);
  306. #elif defined(HAS_HAMMINGDISTANCE_AVX2)
  307. int has_avx2 = TestCpuFlag(kCpuHasAVX2);
  308. if (has_avx2) {
  309. h1 = HammingDistance_AVX2(src_a, src_b, kMaxWidth);
  310. } else {
  311. int has_sse42 = TestCpuFlag(kCpuHasSSE42);
  312. if (has_sse42) {
  313. h1 = HammingDistance_SSE42(src_a, src_b, kMaxWidth);
  314. } else {
  315. int has_ssse3 = TestCpuFlag(kCpuHasSSSE3);
  316. if (has_ssse3) {
  317. h1 = HammingDistance_SSSE3(src_a, src_b, kMaxWidth);
  318. } else {
  319. h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
  320. }
  321. }
  322. }
  323. #elif defined(HAS_HAMMINGDISTANCE_SSE42)
  324. int has_sse42 = TestCpuFlag(kCpuHasSSE42);
  325. if (has_sse42) {
  326. h1 = HammingDistance_SSE42(src_a, src_b, kMaxWidth);
  327. } else {
  328. h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
  329. }
  330. #else
  331. h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
  332. #endif
  333. }
  334. // A large count will cause the low level to potentially overflow so the
  335. // result can not be expected to be correct.
  336. // TODO(fbarchard): Consider expecting the low 16 bits to match.
  337. if (kMaxWidth <= kMaxOptCount) {
  338. EXPECT_EQ(kMaxWidth * 8U, h1);
  339. } else {
  340. if (kMaxWidth * 8ULL != static_cast<uint64_t>(h1)) {
  341. printf(
  342. "warning - HammingDistance_Opt %u does not match %llu "
  343. "but length of %u is longer than guaranteed.\n",
  344. h1, kMaxWidth * 8ULL, kMaxWidth);
  345. } else {
  346. printf(
  347. "warning - HammingDistance_Opt %u matches but length of %u "
  348. "is longer than guaranteed.\n",
  349. h1, kMaxWidth);
  350. }
  351. }
  352. free_aligned_buffer_page_end(src_a);
  353. free_aligned_buffer_page_end(src_b);
  354. }
  355. #endif // ENABLE_ROW_TESTS
  356. TEST_F(LibYUVCompareTest, TestHammingDistance) {
  357. align_buffer_page_end(src_a, benchmark_width_ * benchmark_height_);
  358. align_buffer_page_end(src_b, benchmark_width_ * benchmark_height_);
  359. memset(src_a, 255u, benchmark_width_ * benchmark_height_);
  360. memset(src_b, 0, benchmark_width_ * benchmark_height_);
  361. uint64_t h1 = 0;
  362. for (int i = 0; i < benchmark_iterations_; ++i) {
  363. h1 = ComputeHammingDistance(src_a, src_b,
  364. benchmark_width_ * benchmark_height_);
  365. }
  366. EXPECT_EQ(benchmark_width_ * benchmark_height_ * 8ULL, h1);
  367. free_aligned_buffer_page_end(src_a);
  368. free_aligned_buffer_page_end(src_b);
  369. }
  370. TEST_F(LibYUVCompareTest, BenchmarkSumSquareError_Opt) {
  371. const int kMaxWidth = 4096 * 3;
  372. align_buffer_page_end(src_a, kMaxWidth);
  373. align_buffer_page_end(src_b, kMaxWidth);
  374. memset(src_a, 0, kMaxWidth);
  375. memset(src_b, 0, kMaxWidth);
  376. memcpy(src_a, "test0123test4567", 16);
  377. memcpy(src_b, "tick0123tock4567", 16);
  378. uint64_t h1 = ComputeSumSquareError(src_a, src_b, 16);
  379. EXPECT_EQ(790u, h1);
  380. for (int i = 0; i < kMaxWidth; ++i) {
  381. src_a[i] = i;
  382. src_b[i] = i;
  383. }
  384. memset(src_a, 0, kMaxWidth);
  385. memset(src_b, 0, kMaxWidth);
  386. int count =
  387. benchmark_iterations_ *
  388. ((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth);
  389. for (int i = 0; i < count; ++i) {
  390. h1 = ComputeSumSquareError(src_a, src_b, kMaxWidth);
  391. }
  392. EXPECT_EQ(0u, h1);
  393. free_aligned_buffer_page_end(src_a);
  394. free_aligned_buffer_page_end(src_b);
  395. }
  396. TEST_F(LibYUVCompareTest, SumSquareError) {
  397. const int kMaxWidth = 4096 * 3;
  398. align_buffer_page_end(src_a, kMaxWidth);
  399. align_buffer_page_end(src_b, kMaxWidth);
  400. memset(src_a, 0, kMaxWidth);
  401. memset(src_b, 0, kMaxWidth);
  402. uint64_t err;
  403. err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
  404. EXPECT_EQ(0u, err);
  405. memset(src_a, 1, kMaxWidth);
  406. err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
  407. EXPECT_EQ(static_cast<int>(err), kMaxWidth);
  408. memset(src_a, 190, kMaxWidth);
  409. memset(src_b, 193, kMaxWidth);
  410. err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
  411. EXPECT_EQ(static_cast<int>(err), kMaxWidth * 3 * 3);
  412. for (int i = 0; i < kMaxWidth; ++i) {
  413. src_a[i] = (fastrand() & 0xff);
  414. src_b[i] = (fastrand() & 0xff);
  415. }
  416. MaskCpuFlags(disable_cpu_flags_);
  417. uint64_t c_err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
  418. MaskCpuFlags(benchmark_cpu_info_);
  419. uint64_t opt_err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
  420. EXPECT_EQ(c_err, opt_err);
  421. free_aligned_buffer_page_end(src_a);
  422. free_aligned_buffer_page_end(src_b);
  423. }
  424. TEST_F(LibYUVCompareTest, BenchmarkPsnr_Opt) {
  425. align_buffer_page_end(src_a, benchmark_width_ * benchmark_height_);
  426. align_buffer_page_end(src_b, benchmark_width_ * benchmark_height_);
  427. for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
  428. src_a[i] = i;
  429. src_b[i] = i;
  430. }
  431. MaskCpuFlags(benchmark_cpu_info_);
  432. double opt_time = get_time();
  433. for (int i = 0; i < benchmark_iterations_; ++i) {
  434. CalcFramePsnr(src_a, benchmark_width_, src_b, benchmark_width_,
  435. benchmark_width_, benchmark_height_);
  436. }
  437. opt_time = (get_time() - opt_time) / benchmark_iterations_;
  438. printf("BenchmarkPsnr_Opt - %8.2f us opt\n", opt_time * 1e6);
  439. EXPECT_EQ(0, 0);
  440. free_aligned_buffer_page_end(src_a);
  441. free_aligned_buffer_page_end(src_b);
  442. }
  443. TEST_F(LibYUVCompareTest, BenchmarkPsnr_Unaligned) {
  444. align_buffer_page_end(src_a, benchmark_width_ * benchmark_height_ + 1);
  445. align_buffer_page_end(src_b, benchmark_width_ * benchmark_height_);
  446. for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
  447. src_a[i + 1] = i;
  448. src_b[i] = i;
  449. }
  450. MaskCpuFlags(benchmark_cpu_info_);
  451. double opt_time = get_time();
  452. for (int i = 0; i < benchmark_iterations_; ++i) {
  453. CalcFramePsnr(src_a + 1, benchmark_width_, src_b, benchmark_width_,
  454. benchmark_width_, benchmark_height_);
  455. }
  456. opt_time = (get_time() - opt_time) / benchmark_iterations_;
  457. printf("BenchmarkPsnr_Opt - %8.2f us opt\n", opt_time * 1e6);
  458. EXPECT_EQ(0, 0);
  459. free_aligned_buffer_page_end(src_a);
  460. free_aligned_buffer_page_end(src_b);
  461. }
  462. TEST_F(LibYUVCompareTest, Psnr) {
  463. const int kSrcWidth = benchmark_width_;
  464. const int kSrcHeight = benchmark_height_;
  465. const int b = 128;
  466. const int kSrcPlaneSize = (kSrcWidth + b * 2) * (kSrcHeight + b * 2);
  467. const int kSrcStride = 2 * b + kSrcWidth;
  468. align_buffer_page_end(src_a, kSrcPlaneSize);
  469. align_buffer_page_end(src_b, kSrcPlaneSize);
  470. memset(src_a, 0, kSrcPlaneSize);
  471. memset(src_b, 0, kSrcPlaneSize);
  472. double err;
  473. err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
  474. src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
  475. kSrcHeight);
  476. EXPECT_EQ(err, kMaxPsnr);
  477. memset(src_a, 255, kSrcPlaneSize);
  478. err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
  479. src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
  480. kSrcHeight);
  481. EXPECT_EQ(err, 0.0);
  482. memset(src_a, 1, kSrcPlaneSize);
  483. err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
  484. src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
  485. kSrcHeight);
  486. EXPECT_GT(err, 48.0);
  487. EXPECT_LT(err, 49.0);
  488. for (int i = 0; i < kSrcPlaneSize; ++i) {
  489. src_a[i] = i;
  490. }
  491. err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
  492. src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
  493. kSrcHeight);
  494. EXPECT_GT(err, 2.0);
  495. if (kSrcWidth * kSrcHeight >= 256) {
  496. EXPECT_LT(err, 6.0);
  497. }
  498. memset(src_a, 0, kSrcPlaneSize);
  499. memset(src_b, 0, kSrcPlaneSize);
  500. for (int i = b; i < (kSrcHeight + b); ++i) {
  501. for (int j = b; j < (kSrcWidth + b); ++j) {
  502. src_a[(i * kSrcStride) + j] = (fastrand() & 0xff);
  503. src_b[(i * kSrcStride) + j] = (fastrand() & 0xff);
  504. }
  505. }
  506. MaskCpuFlags(disable_cpu_flags_);
  507. double c_err, opt_err;
  508. c_err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
  509. src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
  510. kSrcHeight);
  511. MaskCpuFlags(benchmark_cpu_info_);
  512. opt_err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
  513. src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
  514. kSrcHeight);
  515. EXPECT_EQ(opt_err, c_err);
  516. free_aligned_buffer_page_end(src_a);
  517. free_aligned_buffer_page_end(src_b);
  518. }
  519. TEST_F(LibYUVCompareTest, DISABLED_BenchmarkSsim_Opt) {
  520. align_buffer_page_end(src_a, benchmark_width_ * benchmark_height_);
  521. align_buffer_page_end(src_b, benchmark_width_ * benchmark_height_);
  522. for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
  523. src_a[i] = i;
  524. src_b[i] = i;
  525. }
  526. MaskCpuFlags(benchmark_cpu_info_);
  527. double opt_time = get_time();
  528. for (int i = 0; i < benchmark_iterations_; ++i) {
  529. CalcFrameSsim(src_a, benchmark_width_, src_b, benchmark_width_,
  530. benchmark_width_, benchmark_height_);
  531. }
  532. opt_time = (get_time() - opt_time) / benchmark_iterations_;
  533. printf("BenchmarkSsim_Opt - %8.2f us opt\n", opt_time * 1e6);
  534. EXPECT_EQ(0, 0); // Pass if we get this far.
  535. free_aligned_buffer_page_end(src_a);
  536. free_aligned_buffer_page_end(src_b);
  537. }
  538. TEST_F(LibYUVCompareTest, Ssim) {
  539. const int kSrcWidth = benchmark_width_;
  540. const int kSrcHeight = benchmark_height_;
  541. const int b = 128;
  542. const int kSrcPlaneSize = (kSrcWidth + b * 2) * (kSrcHeight + b * 2);
  543. const int kSrcStride = 2 * b + kSrcWidth;
  544. align_buffer_page_end(src_a, kSrcPlaneSize);
  545. align_buffer_page_end(src_b, kSrcPlaneSize);
  546. memset(src_a, 0, kSrcPlaneSize);
  547. memset(src_b, 0, kSrcPlaneSize);
  548. if (kSrcWidth <= 8 || kSrcHeight <= 8) {
  549. printf("warning - Ssim size too small. Testing function executes.\n");
  550. }
  551. double err;
  552. err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
  553. src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
  554. kSrcHeight);
  555. if (kSrcWidth > 8 && kSrcHeight > 8) {
  556. EXPECT_EQ(err, 1.0);
  557. }
  558. memset(src_a, 255, kSrcPlaneSize);
  559. err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
  560. src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
  561. kSrcHeight);
  562. if (kSrcWidth > 8 && kSrcHeight > 8) {
  563. EXPECT_LT(err, 0.0001);
  564. }
  565. memset(src_a, 1, kSrcPlaneSize);
  566. err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
  567. src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
  568. kSrcHeight);
  569. if (kSrcWidth > 8 && kSrcHeight > 8) {
  570. EXPECT_GT(err, 0.0001);
  571. EXPECT_LT(err, 0.9);
  572. }
  573. for (int i = 0; i < kSrcPlaneSize; ++i) {
  574. src_a[i] = i;
  575. }
  576. err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
  577. src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
  578. kSrcHeight);
  579. if (kSrcWidth > 8 && kSrcHeight > 8) {
  580. EXPECT_GT(err, 0.0);
  581. EXPECT_LT(err, 0.01);
  582. }
  583. for (int i = b; i < (kSrcHeight + b); ++i) {
  584. for (int j = b; j < (kSrcWidth + b); ++j) {
  585. src_a[(i * kSrcStride) + j] = (fastrand() & 0xff);
  586. src_b[(i * kSrcStride) + j] = (fastrand() & 0xff);
  587. }
  588. }
  589. MaskCpuFlags(disable_cpu_flags_);
  590. double c_err, opt_err;
  591. c_err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
  592. src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
  593. kSrcHeight);
  594. MaskCpuFlags(benchmark_cpu_info_);
  595. opt_err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
  596. src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
  597. kSrcHeight);
  598. if (kSrcWidth > 8 && kSrcHeight > 8) {
  599. EXPECT_EQ(opt_err, c_err);
  600. }
  601. free_aligned_buffer_page_end(src_a);
  602. free_aligned_buffer_page_end(src_b);
  603. }
  604. } // namespace libyuv