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