xref: /aosp_15_r20/external/libyuv/unit_test/scale_plane_test.cc (revision 4e366538070a3a6c5c163c31b791eab742e1657a)
1*4e366538SXin Li /*
2*4e366538SXin Li  *  Copyright 2023 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 <time.h>
13*4e366538SXin Li 
14*4e366538SXin Li #include "../unit_test/unit_test.h"
15*4e366538SXin Li #include "libyuv/cpu_id.h"
16*4e366538SXin Li #include "libyuv/scale.h"
17*4e366538SXin Li 
18*4e366538SXin Li #ifdef ENABLE_ROW_TESTS
19*4e366538SXin Li #include "libyuv/scale_row.h"  // For ScaleRowDown2Box_Odd_C
20*4e366538SXin Li #endif
21*4e366538SXin Li 
22*4e366538SXin Li #define STRINGIZE(line) #line
23*4e366538SXin Li #define FILELINESTR(file, line) file ":" STRINGIZE(line)
24*4e366538SXin Li 
25*4e366538SXin Li #if defined(__riscv) && !defined(__clang__)
26*4e366538SXin Li #define DISABLE_SLOW_TESTS
27*4e366538SXin Li #undef ENABLE_FULL_TESTS
28*4e366538SXin Li #undef ENABLE_ROW_TESTS
29*4e366538SXin Li #define LEAN_TESTS
30*4e366538SXin Li #endif
31*4e366538SXin Li 
32*4e366538SXin Li #if !defined(DISABLE_SLOW_TESTS) || defined(__x86_64__) || defined(__i386__)
33*4e366538SXin Li // SLOW TESTS are those that are unoptimized C code.
34*4e366538SXin Li // FULL TESTS are optimized but test many variations of the same code.
35*4e366538SXin Li #define ENABLE_FULL_TESTS
36*4e366538SXin Li #endif
37*4e366538SXin Li 
38*4e366538SXin Li namespace libyuv {
39*4e366538SXin Li 
40*4e366538SXin Li #ifdef ENABLE_ROW_TESTS
41*4e366538SXin Li #ifdef HAS_SCALEROWDOWN2_SSSE3
TEST_F(LibYUVScaleTest,TestScaleRowDown2Box_Odd_SSSE3)42*4e366538SXin Li TEST_F(LibYUVScaleTest, TestScaleRowDown2Box_Odd_SSSE3) {
43*4e366538SXin Li   SIMD_ALIGNED(uint8_t orig_pixels[128 * 2]);
44*4e366538SXin Li   SIMD_ALIGNED(uint8_t dst_pixels_opt[64]);
45*4e366538SXin Li   SIMD_ALIGNED(uint8_t dst_pixels_c[64]);
46*4e366538SXin Li   memset(orig_pixels, 0, sizeof(orig_pixels));
47*4e366538SXin Li   memset(dst_pixels_opt, 0, sizeof(dst_pixels_opt));
48*4e366538SXin Li   memset(dst_pixels_c, 0, sizeof(dst_pixels_c));
49*4e366538SXin Li 
50*4e366538SXin Li   int has_ssse3 = TestCpuFlag(kCpuHasSSSE3);
51*4e366538SXin Li   if (!has_ssse3) {
52*4e366538SXin Li     printf("Warning SSSE3 not detected; Skipping test.\n");
53*4e366538SXin Li   } else {
54*4e366538SXin Li     // TL.
55*4e366538SXin Li     orig_pixels[0] = 255u;
56*4e366538SXin Li     orig_pixels[1] = 0u;
57*4e366538SXin Li     orig_pixels[128 + 0] = 0u;
58*4e366538SXin Li     orig_pixels[128 + 1] = 0u;
59*4e366538SXin Li     // TR.
60*4e366538SXin Li     orig_pixels[2] = 0u;
61*4e366538SXin Li     orig_pixels[3] = 100u;
62*4e366538SXin Li     orig_pixels[128 + 2] = 0u;
63*4e366538SXin Li     orig_pixels[128 + 3] = 0u;
64*4e366538SXin Li     // BL.
65*4e366538SXin Li     orig_pixels[4] = 0u;
66*4e366538SXin Li     orig_pixels[5] = 0u;
67*4e366538SXin Li     orig_pixels[128 + 4] = 50u;
68*4e366538SXin Li     orig_pixels[128 + 5] = 0u;
69*4e366538SXin Li     // BR.
70*4e366538SXin Li     orig_pixels[6] = 0u;
71*4e366538SXin Li     orig_pixels[7] = 0u;
72*4e366538SXin Li     orig_pixels[128 + 6] = 0u;
73*4e366538SXin Li     orig_pixels[128 + 7] = 20u;
74*4e366538SXin Li     // Odd.
75*4e366538SXin Li     orig_pixels[126] = 4u;
76*4e366538SXin Li     orig_pixels[127] = 255u;
77*4e366538SXin Li     orig_pixels[128 + 126] = 16u;
78*4e366538SXin Li     orig_pixels[128 + 127] = 255u;
79*4e366538SXin Li 
80*4e366538SXin Li     // Test regular half size.
81*4e366538SXin Li     ScaleRowDown2Box_C(orig_pixels, 128, dst_pixels_c, 64);
82*4e366538SXin Li 
83*4e366538SXin Li     EXPECT_EQ(64u, dst_pixels_c[0]);
84*4e366538SXin Li     EXPECT_EQ(25u, dst_pixels_c[1]);
85*4e366538SXin Li     EXPECT_EQ(13u, dst_pixels_c[2]);
86*4e366538SXin Li     EXPECT_EQ(5u, dst_pixels_c[3]);
87*4e366538SXin Li     EXPECT_EQ(0u, dst_pixels_c[4]);
88*4e366538SXin Li     EXPECT_EQ(133u, dst_pixels_c[63]);
89*4e366538SXin Li 
90*4e366538SXin Li     // Test Odd width version - Last pixel is just 1 horizontal pixel.
91*4e366538SXin Li     ScaleRowDown2Box_Odd_C(orig_pixels, 128, dst_pixels_c, 64);
92*4e366538SXin Li 
93*4e366538SXin Li     EXPECT_EQ(64u, dst_pixels_c[0]);
94*4e366538SXin Li     EXPECT_EQ(25u, dst_pixels_c[1]);
95*4e366538SXin Li     EXPECT_EQ(13u, dst_pixels_c[2]);
96*4e366538SXin Li     EXPECT_EQ(5u, dst_pixels_c[3]);
97*4e366538SXin Li     EXPECT_EQ(0u, dst_pixels_c[4]);
98*4e366538SXin Li     EXPECT_EQ(10u, dst_pixels_c[63]);
99*4e366538SXin Li 
100*4e366538SXin Li     // Test one pixel less, should skip the last pixel.
101*4e366538SXin Li     memset(dst_pixels_c, 0, sizeof(dst_pixels_c));
102*4e366538SXin Li     ScaleRowDown2Box_Odd_C(orig_pixels, 128, dst_pixels_c, 63);
103*4e366538SXin Li 
104*4e366538SXin Li     EXPECT_EQ(64u, dst_pixels_c[0]);
105*4e366538SXin Li     EXPECT_EQ(25u, dst_pixels_c[1]);
106*4e366538SXin Li     EXPECT_EQ(13u, dst_pixels_c[2]);
107*4e366538SXin Li     EXPECT_EQ(5u, dst_pixels_c[3]);
108*4e366538SXin Li     EXPECT_EQ(0u, dst_pixels_c[4]);
109*4e366538SXin Li     EXPECT_EQ(0u, dst_pixels_c[63]);
110*4e366538SXin Li 
111*4e366538SXin Li     // Test regular half size SSSE3.
112*4e366538SXin Li     ScaleRowDown2Box_SSSE3(orig_pixels, 128, dst_pixels_opt, 64);
113*4e366538SXin Li 
114*4e366538SXin Li     EXPECT_EQ(64u, dst_pixels_opt[0]);
115*4e366538SXin Li     EXPECT_EQ(25u, dst_pixels_opt[1]);
116*4e366538SXin Li     EXPECT_EQ(13u, dst_pixels_opt[2]);
117*4e366538SXin Li     EXPECT_EQ(5u, dst_pixels_opt[3]);
118*4e366538SXin Li     EXPECT_EQ(0u, dst_pixels_opt[4]);
119*4e366538SXin Li     EXPECT_EQ(133u, dst_pixels_opt[63]);
120*4e366538SXin Li 
121*4e366538SXin Li     // Compare C and SSSE3 match.
122*4e366538SXin Li     ScaleRowDown2Box_Odd_C(orig_pixels, 128, dst_pixels_c, 64);
123*4e366538SXin Li     ScaleRowDown2Box_Odd_SSSE3(orig_pixels, 128, dst_pixels_opt, 64);
124*4e366538SXin Li     for (int i = 0; i < 64; ++i) {
125*4e366538SXin Li       EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]);
126*4e366538SXin Li     }
127*4e366538SXin Li   }
128*4e366538SXin Li }
129*4e366538SXin Li #endif  // HAS_SCALEROWDOWN2_SSSE3
130*4e366538SXin Li 
131*4e366538SXin Li extern "C" void ScaleRowDown2Box_16_NEON(const uint16_t* src_ptr,
132*4e366538SXin Li                                          ptrdiff_t src_stride,
133*4e366538SXin Li                                          uint16_t* dst,
134*4e366538SXin Li                                          int dst_width);
135*4e366538SXin Li 
TEST_F(LibYUVScaleTest,TestScaleRowDown2Box_16)136*4e366538SXin Li TEST_F(LibYUVScaleTest, TestScaleRowDown2Box_16) {
137*4e366538SXin Li   SIMD_ALIGNED(uint16_t orig_pixels[2560 * 2]);
138*4e366538SXin Li   SIMD_ALIGNED(uint16_t dst_pixels_c[1280]);
139*4e366538SXin Li   SIMD_ALIGNED(uint16_t dst_pixels_opt[1280]);
140*4e366538SXin Li 
141*4e366538SXin Li   memset(orig_pixels, 0, sizeof(orig_pixels));
142*4e366538SXin Li   memset(dst_pixels_c, 1, sizeof(dst_pixels_c));
143*4e366538SXin Li   memset(dst_pixels_opt, 2, sizeof(dst_pixels_opt));
144*4e366538SXin Li 
145*4e366538SXin Li   for (int i = 0; i < 2560 * 2; ++i) {
146*4e366538SXin Li     orig_pixels[i] = i;
147*4e366538SXin Li   }
148*4e366538SXin Li   ScaleRowDown2Box_16_C(&orig_pixels[0], 2560, &dst_pixels_c[0], 1280);
149*4e366538SXin Li   for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
150*4e366538SXin Li #if !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__)
151*4e366538SXin Li     int has_neon = TestCpuFlag(kCpuHasNEON);
152*4e366538SXin Li     if (has_neon) {
153*4e366538SXin Li       ScaleRowDown2Box_16_NEON(&orig_pixels[0], 2560, &dst_pixels_opt[0], 1280);
154*4e366538SXin Li     } else {
155*4e366538SXin Li       ScaleRowDown2Box_16_C(&orig_pixels[0], 2560, &dst_pixels_opt[0], 1280);
156*4e366538SXin Li     }
157*4e366538SXin Li #else
158*4e366538SXin Li     ScaleRowDown2Box_16_C(&orig_pixels[0], 2560, &dst_pixels_opt[0], 1280);
159*4e366538SXin Li #endif
160*4e366538SXin Li   }
161*4e366538SXin Li 
162*4e366538SXin Li   for (int i = 0; i < 1280; ++i) {
163*4e366538SXin Li     EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]);
164*4e366538SXin Li   }
165*4e366538SXin Li 
166*4e366538SXin Li   EXPECT_EQ(dst_pixels_c[0], (0 + 1 + 2560 + 2561 + 2) / 4);
167*4e366538SXin Li   EXPECT_EQ(dst_pixels_c[1279], 3839);
168*4e366538SXin Li }
169*4e366538SXin Li #endif  // ENABLE_ROW_TESTS
170*4e366538SXin Li 
171*4e366538SXin Li // Test scaling plane with 8 bit C vs 12 bit C and return maximum pixel
172*4e366538SXin Li // difference.
173*4e366538SXin Li // 0 = exact.
TestPlaneFilter_16(int src_width,int src_height,int dst_width,int dst_height,FilterMode f,int benchmark_iterations,int disable_cpu_flags,int benchmark_cpu_info)174*4e366538SXin Li static int TestPlaneFilter_16(int src_width,
175*4e366538SXin Li                               int src_height,
176*4e366538SXin Li                               int dst_width,
177*4e366538SXin Li                               int dst_height,
178*4e366538SXin Li                               FilterMode f,
179*4e366538SXin Li                               int benchmark_iterations,
180*4e366538SXin Li                               int disable_cpu_flags,
181*4e366538SXin Li                               int benchmark_cpu_info) {
182*4e366538SXin Li   if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
183*4e366538SXin Li     return 0;
184*4e366538SXin Li   }
185*4e366538SXin Li 
186*4e366538SXin Li   int i;
187*4e366538SXin Li   int64_t src_y_plane_size = (Abs(src_width)) * (Abs(src_height));
188*4e366538SXin Li   int src_stride_y = Abs(src_width);
189*4e366538SXin Li   int dst_y_plane_size = dst_width * dst_height;
190*4e366538SXin Li   int dst_stride_y = dst_width;
191*4e366538SXin Li 
192*4e366538SXin Li   align_buffer_page_end(src_y, src_y_plane_size);
193*4e366538SXin Li   align_buffer_page_end(src_y_16, src_y_plane_size * 2);
194*4e366538SXin Li   align_buffer_page_end(dst_y_8, dst_y_plane_size);
195*4e366538SXin Li   align_buffer_page_end(dst_y_16, dst_y_plane_size * 2);
196*4e366538SXin Li   uint16_t* p_src_y_16 = reinterpret_cast<uint16_t*>(src_y_16);
197*4e366538SXin Li   uint16_t* p_dst_y_16 = reinterpret_cast<uint16_t*>(dst_y_16);
198*4e366538SXin Li 
199*4e366538SXin Li   MemRandomize(src_y, src_y_plane_size);
200*4e366538SXin Li   memset(dst_y_8, 0, dst_y_plane_size);
201*4e366538SXin Li   memset(dst_y_16, 1, dst_y_plane_size * 2);
202*4e366538SXin Li 
203*4e366538SXin Li   for (i = 0; i < src_y_plane_size; ++i) {
204*4e366538SXin Li     p_src_y_16[i] = src_y[i] & 255;
205*4e366538SXin Li   }
206*4e366538SXin Li 
207*4e366538SXin Li   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
208*4e366538SXin Li   ScalePlane(src_y, src_stride_y, src_width, src_height, dst_y_8, dst_stride_y,
209*4e366538SXin Li              dst_width, dst_height, f);
210*4e366538SXin Li   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
211*4e366538SXin Li 
212*4e366538SXin Li   for (i = 0; i < benchmark_iterations; ++i) {
213*4e366538SXin Li     ScalePlane_16(p_src_y_16, src_stride_y, src_width, src_height, p_dst_y_16,
214*4e366538SXin Li                   dst_stride_y, dst_width, dst_height, f);
215*4e366538SXin Li   }
216*4e366538SXin Li 
217*4e366538SXin Li   // Expect an exact match.
218*4e366538SXin Li   int max_diff = 0;
219*4e366538SXin Li   for (i = 0; i < dst_y_plane_size; ++i) {
220*4e366538SXin Li     int abs_diff = Abs(dst_y_8[i] - p_dst_y_16[i]);
221*4e366538SXin Li     if (abs_diff > max_diff) {
222*4e366538SXin Li       max_diff = abs_diff;
223*4e366538SXin Li     }
224*4e366538SXin Li   }
225*4e366538SXin Li 
226*4e366538SXin Li   free_aligned_buffer_page_end(dst_y_8);
227*4e366538SXin Li   free_aligned_buffer_page_end(dst_y_16);
228*4e366538SXin Li   free_aligned_buffer_page_end(src_y);
229*4e366538SXin Li   free_aligned_buffer_page_end(src_y_16);
230*4e366538SXin Li 
231*4e366538SXin Li   return max_diff;
232*4e366538SXin Li }
233*4e366538SXin Li 
234*4e366538SXin Li // The following adjustments in dimensions ensure the scale factor will be
235*4e366538SXin Li // exactly achieved.
236*4e366538SXin Li // 2 is chroma subsample.
237*4e366538SXin Li #define DX(x, nom, denom) static_cast<int>(((Abs(x) / nom + 1) / 2) * nom * 2)
238*4e366538SXin Li #define SX(x, nom, denom) static_cast<int>(((x / nom + 1) / 2) * denom * 2)
239*4e366538SXin Li 
240*4e366538SXin Li #define TEST_FACTOR1(name, filter, nom, denom, max_diff)                       \
241*4e366538SXin Li   TEST_F(LibYUVScaleTest, DISABLED_##ScalePlaneDownBy##name##_##filter##_16) { \
242*4e366538SXin Li     int diff = TestPlaneFilter_16(                                             \
243*4e366538SXin Li         SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom),   \
244*4e366538SXin Li         DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom),   \
245*4e366538SXin Li         kFilter##filter, benchmark_iterations_, disable_cpu_flags_,            \
246*4e366538SXin Li         benchmark_cpu_info_);                                                  \
247*4e366538SXin Li     EXPECT_LE(diff, max_diff);                                                 \
248*4e366538SXin Li   }
249*4e366538SXin Li 
250*4e366538SXin Li // Test a scale factor with all 4 filters.  Expect unfiltered to be exact, but
251*4e366538SXin Li // filtering is different fixed point implementations for SSSE3, Neon and C.
252*4e366538SXin Li #define TEST_FACTOR(name, nom, denom, boxdiff)      \
253*4e366538SXin Li   TEST_FACTOR1(name, None, nom, denom, 0)           \
254*4e366538SXin Li   TEST_FACTOR1(name, Linear, nom, denom, boxdiff)   \
255*4e366538SXin Li   TEST_FACTOR1(name, Bilinear, nom, denom, boxdiff) \
256*4e366538SXin Li   TEST_FACTOR1(name, Box, nom, denom, boxdiff)
257*4e366538SXin Li 
258*4e366538SXin Li TEST_FACTOR(2, 1, 2, 0)
259*4e366538SXin Li TEST_FACTOR(4, 1, 4, 0)
260*4e366538SXin Li // TEST_FACTOR(8, 1, 8, 0) Disable for benchmark performance.  Takes 90 seconds.
261*4e366538SXin Li TEST_FACTOR(3by4, 3, 4, 1)
262*4e366538SXin Li TEST_FACTOR(3by8, 3, 8, 1)
263*4e366538SXin Li TEST_FACTOR(3, 1, 3, 0)
264*4e366538SXin Li #undef TEST_FACTOR1
265*4e366538SXin Li #undef TEST_FACTOR
266*4e366538SXin Li #undef SX
267*4e366538SXin Li #undef DX
268*4e366538SXin Li 
TEST_F(LibYUVScaleTest,PlaneTest3x)269*4e366538SXin Li TEST_F(LibYUVScaleTest, PlaneTest3x) {
270*4e366538SXin Li   const int kSrcStride = 480;
271*4e366538SXin Li   const int kDstStride = 160;
272*4e366538SXin Li   const int kSize = kSrcStride * 3;
273*4e366538SXin Li   align_buffer_page_end(orig_pixels, kSize);
274*4e366538SXin Li   for (int i = 0; i < 480 * 3; ++i) {
275*4e366538SXin Li     orig_pixels[i] = i;
276*4e366538SXin Li   }
277*4e366538SXin Li   align_buffer_page_end(dest_pixels, kDstStride);
278*4e366538SXin Li 
279*4e366538SXin Li   int iterations160 = (benchmark_width_ * benchmark_height_ + (160 - 1)) / 160 *
280*4e366538SXin Li                       benchmark_iterations_;
281*4e366538SXin Li   for (int i = 0; i < iterations160; ++i) {
282*4e366538SXin Li     ScalePlane(orig_pixels, kSrcStride, 480, 3, dest_pixels, kDstStride, 160, 1,
283*4e366538SXin Li                kFilterBilinear);
284*4e366538SXin Li   }
285*4e366538SXin Li 
286*4e366538SXin Li   EXPECT_EQ(225, dest_pixels[0]);
287*4e366538SXin Li 
288*4e366538SXin Li   ScalePlane(orig_pixels, kSrcStride, 480, 3, dest_pixels, kDstStride, 160, 1,
289*4e366538SXin Li              kFilterNone);
290*4e366538SXin Li 
291*4e366538SXin Li   EXPECT_EQ(225, dest_pixels[0]);
292*4e366538SXin Li 
293*4e366538SXin Li   free_aligned_buffer_page_end(dest_pixels);
294*4e366538SXin Li   free_aligned_buffer_page_end(orig_pixels);
295*4e366538SXin Li }
296*4e366538SXin Li 
TEST_F(LibYUVScaleTest,PlaneTest4x)297*4e366538SXin Li TEST_F(LibYUVScaleTest, PlaneTest4x) {
298*4e366538SXin Li   const int kSrcStride = 640;
299*4e366538SXin Li   const int kDstStride = 160;
300*4e366538SXin Li   const int kSize = kSrcStride * 4;
301*4e366538SXin Li   align_buffer_page_end(orig_pixels, kSize);
302*4e366538SXin Li   for (int i = 0; i < 640 * 4; ++i) {
303*4e366538SXin Li     orig_pixels[i] = i;
304*4e366538SXin Li   }
305*4e366538SXin Li   align_buffer_page_end(dest_pixels, kDstStride);
306*4e366538SXin Li 
307*4e366538SXin Li   int iterations160 = (benchmark_width_ * benchmark_height_ + (160 - 1)) / 160 *
308*4e366538SXin Li                       benchmark_iterations_;
309*4e366538SXin Li   for (int i = 0; i < iterations160; ++i) {
310*4e366538SXin Li     ScalePlane(orig_pixels, kSrcStride, 640, 4, dest_pixels, kDstStride, 160, 1,
311*4e366538SXin Li                kFilterBilinear);
312*4e366538SXin Li   }
313*4e366538SXin Li 
314*4e366538SXin Li   EXPECT_EQ(66, dest_pixels[0]);
315*4e366538SXin Li 
316*4e366538SXin Li   ScalePlane(orig_pixels, kSrcStride, 640, 4, dest_pixels, kDstStride, 160, 1,
317*4e366538SXin Li              kFilterNone);
318*4e366538SXin Li 
319*4e366538SXin Li   EXPECT_EQ(2, dest_pixels[0]);  // expect the 3rd pixel of the 3rd row
320*4e366538SXin Li 
321*4e366538SXin Li   free_aligned_buffer_page_end(dest_pixels);
322*4e366538SXin Li   free_aligned_buffer_page_end(orig_pixels);
323*4e366538SXin Li }
324*4e366538SXin Li 
325*4e366538SXin Li // Intent is to test 200x50 to 50x200 but width and height can be parameters.
TEST_F(LibYUVScaleTest,PlaneTestRotate_None)326*4e366538SXin Li TEST_F(LibYUVScaleTest, PlaneTestRotate_None) {
327*4e366538SXin Li   const int kSize = benchmark_width_ * benchmark_height_;
328*4e366538SXin Li   align_buffer_page_end(orig_pixels, kSize);
329*4e366538SXin Li   for (int i = 0; i < kSize; ++i) {
330*4e366538SXin Li     orig_pixels[i] = i;
331*4e366538SXin Li   }
332*4e366538SXin Li   align_buffer_page_end(dest_opt_pixels, kSize);
333*4e366538SXin Li   align_buffer_page_end(dest_c_pixels, kSize);
334*4e366538SXin Li 
335*4e366538SXin Li   MaskCpuFlags(disable_cpu_flags_);  // Disable all CPU optimization.
336*4e366538SXin Li   ScalePlane(orig_pixels, benchmark_width_, benchmark_width_, benchmark_height_,
337*4e366538SXin Li              dest_c_pixels, benchmark_height_, benchmark_height_,
338*4e366538SXin Li              benchmark_width_, kFilterNone);
339*4e366538SXin Li   MaskCpuFlags(benchmark_cpu_info_);  // Enable all CPU optimization.
340*4e366538SXin Li 
341*4e366538SXin Li   for (int i = 0; i < benchmark_iterations_; ++i) {
342*4e366538SXin Li     ScalePlane(orig_pixels, benchmark_width_, benchmark_width_,
343*4e366538SXin Li                benchmark_height_, dest_opt_pixels, benchmark_height_,
344*4e366538SXin Li                benchmark_height_, benchmark_width_, kFilterNone);
345*4e366538SXin Li   }
346*4e366538SXin Li 
347*4e366538SXin Li   for (int i = 0; i < kSize; ++i) {
348*4e366538SXin Li     EXPECT_EQ(dest_c_pixels[i], dest_opt_pixels[i]);
349*4e366538SXin Li   }
350*4e366538SXin Li 
351*4e366538SXin Li   free_aligned_buffer_page_end(dest_c_pixels);
352*4e366538SXin Li   free_aligned_buffer_page_end(dest_opt_pixels);
353*4e366538SXin Li   free_aligned_buffer_page_end(orig_pixels);
354*4e366538SXin Li }
355*4e366538SXin Li 
TEST_F(LibYUVScaleTest,PlaneTestRotate_Bilinear)356*4e366538SXin Li TEST_F(LibYUVScaleTest, PlaneTestRotate_Bilinear) {
357*4e366538SXin Li   const int kSize = benchmark_width_ * benchmark_height_;
358*4e366538SXin Li   align_buffer_page_end(orig_pixels, kSize);
359*4e366538SXin Li   for (int i = 0; i < kSize; ++i) {
360*4e366538SXin Li     orig_pixels[i] = i;
361*4e366538SXin Li   }
362*4e366538SXin Li   align_buffer_page_end(dest_opt_pixels, kSize);
363*4e366538SXin Li   align_buffer_page_end(dest_c_pixels, kSize);
364*4e366538SXin Li 
365*4e366538SXin Li   MaskCpuFlags(disable_cpu_flags_);  // Disable all CPU optimization.
366*4e366538SXin Li   ScalePlane(orig_pixels, benchmark_width_, benchmark_width_, benchmark_height_,
367*4e366538SXin Li              dest_c_pixels, benchmark_height_, benchmark_height_,
368*4e366538SXin Li              benchmark_width_, kFilterBilinear);
369*4e366538SXin Li   MaskCpuFlags(benchmark_cpu_info_);  // Enable all CPU optimization.
370*4e366538SXin Li 
371*4e366538SXin Li   for (int i = 0; i < benchmark_iterations_; ++i) {
372*4e366538SXin Li     ScalePlane(orig_pixels, benchmark_width_, benchmark_width_,
373*4e366538SXin Li                benchmark_height_, dest_opt_pixels, benchmark_height_,
374*4e366538SXin Li                benchmark_height_, benchmark_width_, kFilterBilinear);
375*4e366538SXin Li   }
376*4e366538SXin Li 
377*4e366538SXin Li   for (int i = 0; i < kSize; ++i) {
378*4e366538SXin Li     EXPECT_EQ(dest_c_pixels[i], dest_opt_pixels[i]);
379*4e366538SXin Li   }
380*4e366538SXin Li 
381*4e366538SXin Li   free_aligned_buffer_page_end(dest_c_pixels);
382*4e366538SXin Li   free_aligned_buffer_page_end(dest_opt_pixels);
383*4e366538SXin Li   free_aligned_buffer_page_end(orig_pixels);
384*4e366538SXin Li }
385*4e366538SXin Li 
386*4e366538SXin Li // Intent is to test 200x50 to 50x200 but width and height can be parameters.
TEST_F(LibYUVScaleTest,PlaneTestRotate_Box)387*4e366538SXin Li TEST_F(LibYUVScaleTest, PlaneTestRotate_Box) {
388*4e366538SXin Li   const int kSize = benchmark_width_ * benchmark_height_;
389*4e366538SXin Li   align_buffer_page_end(orig_pixels, kSize);
390*4e366538SXin Li   for (int i = 0; i < kSize; ++i) {
391*4e366538SXin Li     orig_pixels[i] = i;
392*4e366538SXin Li   }
393*4e366538SXin Li   align_buffer_page_end(dest_opt_pixels, kSize);
394*4e366538SXin Li   align_buffer_page_end(dest_c_pixels, kSize);
395*4e366538SXin Li 
396*4e366538SXin Li   MaskCpuFlags(disable_cpu_flags_);  // Disable all CPU optimization.
397*4e366538SXin Li   ScalePlane(orig_pixels, benchmark_width_, benchmark_width_, benchmark_height_,
398*4e366538SXin Li              dest_c_pixels, benchmark_height_, benchmark_height_,
399*4e366538SXin Li              benchmark_width_, kFilterBox);
400*4e366538SXin Li   MaskCpuFlags(benchmark_cpu_info_);  // Enable all CPU optimization.
401*4e366538SXin Li 
402*4e366538SXin Li   for (int i = 0; i < benchmark_iterations_; ++i) {
403*4e366538SXin Li     ScalePlane(orig_pixels, benchmark_width_, benchmark_width_,
404*4e366538SXin Li                benchmark_height_, dest_opt_pixels, benchmark_height_,
405*4e366538SXin Li                benchmark_height_, benchmark_width_, kFilterBox);
406*4e366538SXin Li   }
407*4e366538SXin Li 
408*4e366538SXin Li   for (int i = 0; i < kSize; ++i) {
409*4e366538SXin Li     EXPECT_EQ(dest_c_pixels[i], dest_opt_pixels[i]);
410*4e366538SXin Li   }
411*4e366538SXin Li 
412*4e366538SXin Li   free_aligned_buffer_page_end(dest_c_pixels);
413*4e366538SXin Li   free_aligned_buffer_page_end(dest_opt_pixels);
414*4e366538SXin Li   free_aligned_buffer_page_end(orig_pixels);
415*4e366538SXin Li }
416*4e366538SXin Li 
TEST_F(LibYUVScaleTest,PlaneTest1_Box)417*4e366538SXin Li TEST_F(LibYUVScaleTest, PlaneTest1_Box) {
418*4e366538SXin Li   align_buffer_page_end(orig_pixels, 3);
419*4e366538SXin Li   align_buffer_page_end(dst_pixels, 3);
420*4e366538SXin Li 
421*4e366538SXin Li   // Pad the 1x1 byte image with invalid values before and after in case libyuv
422*4e366538SXin Li   // reads outside the memory boundaries.
423*4e366538SXin Li   orig_pixels[0] = 0;
424*4e366538SXin Li   orig_pixels[1] = 1;  // scale this pixel
425*4e366538SXin Li   orig_pixels[2] = 2;
426*4e366538SXin Li   dst_pixels[0] = 3;
427*4e366538SXin Li   dst_pixels[1] = 3;
428*4e366538SXin Li   dst_pixels[2] = 3;
429*4e366538SXin Li 
430*4e366538SXin Li   libyuv::ScalePlane(orig_pixels + 1, /* src_stride= */ 1, /* src_width= */ 1,
431*4e366538SXin Li                      /* src_height= */ 1, dst_pixels, /* dst_stride= */ 1,
432*4e366538SXin Li                      /* dst_width= */ 1, /* dst_height= */ 2,
433*4e366538SXin Li                      libyuv::kFilterBox);
434*4e366538SXin Li 
435*4e366538SXin Li   EXPECT_EQ(dst_pixels[0], 1);
436*4e366538SXin Li   EXPECT_EQ(dst_pixels[1], 1);
437*4e366538SXin Li   EXPECT_EQ(dst_pixels[2], 3);
438*4e366538SXin Li 
439*4e366538SXin Li   free_aligned_buffer_page_end(dst_pixels);
440*4e366538SXin Li   free_aligned_buffer_page_end(orig_pixels);
441*4e366538SXin Li }
442*4e366538SXin Li 
TEST_F(LibYUVScaleTest,PlaneTest1_16_Box)443*4e366538SXin Li TEST_F(LibYUVScaleTest, PlaneTest1_16_Box) {
444*4e366538SXin Li   align_buffer_page_end(orig_pixels_alloc, 3 * 2);
445*4e366538SXin Li   align_buffer_page_end(dst_pixels_alloc, 3 * 2);
446*4e366538SXin Li   uint16_t* orig_pixels = (uint16_t*)orig_pixels_alloc;
447*4e366538SXin Li   uint16_t* dst_pixels = (uint16_t*)dst_pixels_alloc;
448*4e366538SXin Li 
449*4e366538SXin Li   // Pad the 1x1 byte image with invalid values before and after in case libyuv
450*4e366538SXin Li   // reads outside the memory boundaries.
451*4e366538SXin Li   orig_pixels[0] = 0;
452*4e366538SXin Li   orig_pixels[1] = 1;  // scale this pixel
453*4e366538SXin Li   orig_pixels[2] = 2;
454*4e366538SXin Li   dst_pixels[0] = 3;
455*4e366538SXin Li   dst_pixels[1] = 3;
456*4e366538SXin Li   dst_pixels[2] = 3;
457*4e366538SXin Li 
458*4e366538SXin Li   libyuv::ScalePlane_16(
459*4e366538SXin Li       orig_pixels + 1, /* src_stride= */ 1, /* src_width= */ 1,
460*4e366538SXin Li       /* src_height= */ 1, dst_pixels, /* dst_stride= */ 1,
461*4e366538SXin Li       /* dst_width= */ 1, /* dst_height= */ 2, libyuv::kFilterNone);
462*4e366538SXin Li 
463*4e366538SXin Li   EXPECT_EQ(dst_pixels[0], 1);
464*4e366538SXin Li   EXPECT_EQ(dst_pixels[1], 1);
465*4e366538SXin Li   EXPECT_EQ(dst_pixels[2], 3);
466*4e366538SXin Li 
467*4e366538SXin Li   free_aligned_buffer_page_end(dst_pixels_alloc);
468*4e366538SXin Li   free_aligned_buffer_page_end(orig_pixels_alloc);
469*4e366538SXin Li }
470*4e366538SXin Li }  // namespace libyuv
471