xref: /aosp_15_r20/external/libyuv/unit_test/scale_argb_test.cc (revision 4e366538070a3a6c5c163c31b791eab742e1657a)
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 
11 #include <stdlib.h>
12 #include <time.h>
13 
14 #include "../unit_test/unit_test.h"
15 #include "libyuv/convert_argb.h"
16 #include "libyuv/cpu_id.h"
17 #include "libyuv/scale_argb.h"
18 #include "libyuv/video_common.h"
19 
20 namespace libyuv {
21 
22 #define STRINGIZE(line) #line
23 #define FILELINESTR(file, line) file ":" STRINGIZE(line)
24 
25 #if !defined(DISABLE_SLOW_TESTS) || defined(__x86_64__) || defined(__i386__)
26 // SLOW TESTS are those that are unoptimized C code.
27 // FULL TESTS are optimized but test many variations of the same code.
28 #define ENABLE_FULL_TESTS
29 #endif
30 
31 // Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
ARGBTestFilter(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)32 static int ARGBTestFilter(int src_width,
33                           int src_height,
34                           int dst_width,
35                           int dst_height,
36                           FilterMode f,
37                           int benchmark_iterations,
38                           int disable_cpu_flags,
39                           int benchmark_cpu_info) {
40   if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
41     return 0;
42   }
43 
44   int i, j;
45   const int b = 0;  // 128 to test for padding/stride.
46   int64_t src_argb_plane_size =
47       (Abs(src_width) + b * 2) * (Abs(src_height) + b * 2) * 4LL;
48   int src_stride_argb = (b * 2 + Abs(src_width)) * 4;
49 
50   align_buffer_page_end(src_argb, src_argb_plane_size);
51   if (!src_argb) {
52     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
53     return 0;
54   }
55   MemRandomize(src_argb, src_argb_plane_size);
56 
57   int64_t dst_argb_plane_size =
58       (dst_width + b * 2) * (dst_height + b * 2) * 4LL;
59   int dst_stride_argb = (b * 2 + dst_width) * 4;
60 
61   align_buffer_page_end(dst_argb_c, dst_argb_plane_size);
62   align_buffer_page_end(dst_argb_opt, dst_argb_plane_size);
63   if (!dst_argb_c || !dst_argb_opt) {
64     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
65     return 0;
66   }
67   memset(dst_argb_c, 2, dst_argb_plane_size);
68   memset(dst_argb_opt, 3, dst_argb_plane_size);
69 
70   // Warm up both versions for consistent benchmarks.
71   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
72   ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
73             src_width, src_height, dst_argb_c + (dst_stride_argb * b) + b * 4,
74             dst_stride_argb, dst_width, dst_height, f);
75   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
76   ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
77             src_width, src_height, dst_argb_opt + (dst_stride_argb * b) + b * 4,
78             dst_stride_argb, dst_width, dst_height, f);
79 
80   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
81   double c_time = get_time();
82   ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
83             src_width, src_height, dst_argb_c + (dst_stride_argb * b) + b * 4,
84             dst_stride_argb, dst_width, dst_height, f);
85 
86   c_time = (get_time() - c_time);
87 
88   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
89   double opt_time = get_time();
90   for (i = 0; i < benchmark_iterations; ++i) {
91     ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
92               src_width, src_height,
93               dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb,
94               dst_width, dst_height, f);
95   }
96   opt_time = (get_time() - opt_time) / benchmark_iterations;
97 
98   // Report performance of C vs OPT
99   printf("filter %d - %8d us C - %8d us OPT\n", f,
100          static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));
101 
102   // C version may be a little off from the optimized. Order of
103   //  operations may introduce rounding somewhere. So do a difference
104   //  of the buffers and look to see that the max difference isn't
105   //  over 2.
106   int max_diff = 0;
107   for (i = b; i < (dst_height + b); ++i) {
108     for (j = b * 4; j < (dst_width + b) * 4; ++j) {
109       int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
110                          dst_argb_opt[(i * dst_stride_argb) + j]);
111       if (abs_diff > max_diff) {
112         max_diff = abs_diff;
113       }
114     }
115   }
116 
117   free_aligned_buffer_page_end(dst_argb_c);
118   free_aligned_buffer_page_end(dst_argb_opt);
119   free_aligned_buffer_page_end(src_argb);
120   return max_diff;
121 }
122 
123 static const int kTileX = 64;
124 static const int kTileY = 64;
125 
TileARGBScale(const uint8_t * src_argb,int src_stride_argb,int src_width,int src_height,uint8_t * dst_argb,int dst_stride_argb,int dst_width,int dst_height,FilterMode filtering)126 static int TileARGBScale(const uint8_t* src_argb,
127                          int src_stride_argb,
128                          int src_width,
129                          int src_height,
130                          uint8_t* dst_argb,
131                          int dst_stride_argb,
132                          int dst_width,
133                          int dst_height,
134                          FilterMode filtering) {
135   for (int y = 0; y < dst_height; y += kTileY) {
136     for (int x = 0; x < dst_width; x += kTileX) {
137       int clip_width = kTileX;
138       if (x + clip_width > dst_width) {
139         clip_width = dst_width - x;
140       }
141       int clip_height = kTileY;
142       if (y + clip_height > dst_height) {
143         clip_height = dst_height - y;
144       }
145       int r = ARGBScaleClip(src_argb, src_stride_argb, src_width, src_height,
146                             dst_argb, dst_stride_argb, dst_width, dst_height, x,
147                             y, clip_width, clip_height, filtering);
148       if (r) {
149         return r;
150       }
151     }
152   }
153   return 0;
154 }
155 
ARGBClipTestFilter(int src_width,int src_height,int dst_width,int dst_height,FilterMode f,int benchmark_iterations)156 static int ARGBClipTestFilter(int src_width,
157                               int src_height,
158                               int dst_width,
159                               int dst_height,
160                               FilterMode f,
161                               int benchmark_iterations) {
162   if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
163     return 0;
164   }
165 
166   const int b = 128;
167   int64_t src_argb_plane_size =
168       (Abs(src_width) + b * 2) * (Abs(src_height) + b * 2) * 4;
169   int src_stride_argb = (b * 2 + Abs(src_width)) * 4;
170 
171   align_buffer_page_end(src_argb, src_argb_plane_size);
172   if (!src_argb) {
173     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
174     return 0;
175   }
176   memset(src_argb, 1, src_argb_plane_size);
177 
178   int64_t dst_argb_plane_size = (dst_width + b * 2) * (dst_height + b * 2) * 4;
179   int dst_stride_argb = (b * 2 + dst_width) * 4;
180 
181   int i, j;
182   for (i = b; i < (Abs(src_height) + b); ++i) {
183     for (j = b; j < (Abs(src_width) + b) * 4; ++j) {
184       src_argb[(i * src_stride_argb) + j] = (fastrand() & 0xff);
185     }
186   }
187 
188   align_buffer_page_end(dst_argb_c, dst_argb_plane_size);
189   align_buffer_page_end(dst_argb_opt, dst_argb_plane_size);
190   if (!dst_argb_c || !dst_argb_opt) {
191     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
192     return 0;
193   }
194   memset(dst_argb_c, 2, dst_argb_plane_size);
195   memset(dst_argb_opt, 3, dst_argb_plane_size);
196 
197   // Do full image, no clipping.
198   double c_time = get_time();
199   ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
200             src_width, src_height, dst_argb_c + (dst_stride_argb * b) + b * 4,
201             dst_stride_argb, dst_width, dst_height, f);
202   c_time = (get_time() - c_time);
203 
204   // Do tiled image, clipping scale to a tile at a time.
205   double opt_time = get_time();
206   for (i = 0; i < benchmark_iterations; ++i) {
207     TileARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
208                   src_width, src_height,
209                   dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb,
210                   dst_width, dst_height, f);
211   }
212   opt_time = (get_time() - opt_time) / benchmark_iterations;
213 
214   // Report performance of Full vs Tiled.
215   printf("filter %d - %8d us Full - %8d us Tiled\n", f,
216          static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));
217 
218   // Compare full scaled image vs tiled image.
219   int max_diff = 0;
220   for (i = b; i < (dst_height + b); ++i) {
221     for (j = b * 4; j < (dst_width + b) * 4; ++j) {
222       int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
223                          dst_argb_opt[(i * dst_stride_argb) + j]);
224       if (abs_diff > max_diff) {
225         max_diff = abs_diff;
226       }
227     }
228   }
229 
230   free_aligned_buffer_page_end(dst_argb_c);
231   free_aligned_buffer_page_end(dst_argb_opt);
232   free_aligned_buffer_page_end(src_argb);
233   return max_diff;
234 }
235 
236 // The following adjustments in dimensions ensure the scale factor will be
237 // exactly achieved.
238 #define DX(x, nom, denom) static_cast<int>((Abs(x) / nom) * nom)
239 #define SX(x, nom, denom) static_cast<int>((x / nom) * denom)
240 
241 #define TEST_FACTOR1(DISABLED_, name, filter, nom, denom, max_diff)          \
242   TEST_F(LibYUVScaleTest, ARGBScaleDownBy##name##_##filter) {                \
243     int diff = ARGBTestFilter(                                               \
244         SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
245         DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \
246         kFilter##filter, benchmark_iterations_, disable_cpu_flags_,          \
247         benchmark_cpu_info_);                                                \
248     EXPECT_LE(diff, max_diff);                                               \
249   }                                                                          \
250   TEST_F(LibYUVScaleTest, DISABLED_##ARGBScaleDownClipBy##name##_##filter) { \
251     int diff = ARGBClipTestFilter(                                           \
252         SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
253         DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \
254         kFilter##filter, benchmark_iterations_);                             \
255     EXPECT_LE(diff, max_diff);                                               \
256   }
257 
258 // Test a scale factor with all 4 filters.  Expect unfiltered to be exact, but
259 // filtering is different fixed point implementations for SSSE3, Neon and C.
260 #ifndef DISABLE_SLOW_TESTS
261 #define TEST_FACTOR(name, nom, denom)           \
262   TEST_FACTOR1(, name, None, nom, denom, 0)     \
263   TEST_FACTOR1(, name, Linear, nom, denom, 3)   \
264   TEST_FACTOR1(, name, Bilinear, nom, denom, 3) \
265   TEST_FACTOR1(, name, Box, nom, denom, 3)
266 #else
267 #if defined(ENABLE_FULL_TESTS)
268 #define TEST_FACTOR(name, nom, denom)                    \
269   TEST_FACTOR1(DISABLED_, name, None, nom, denom, 0)     \
270   TEST_FACTOR1(DISABLED_, name, Linear, nom, denom, 3)   \
271   TEST_FACTOR1(DISABLED_, name, Bilinear, nom, denom, 3) \
272   TEST_FACTOR1(DISABLED_, name, Box, nom, denom, 3)
273 #else
274 #define TEST_FACTOR(name, nom, denom) \
275   TEST_FACTOR1(DISABLED_, name, Bilinear, nom, denom, 3)
276 #endif
277 #endif
278 
279 TEST_FACTOR(2, 1, 2)
280 TEST_FACTOR(4, 1, 4)
281 #ifndef DISABLE_SLOW_TESTS
282 TEST_FACTOR(8, 1, 8)
283 #endif
284 TEST_FACTOR(3by4, 3, 4)
285 TEST_FACTOR(3by8, 3, 8)
286 TEST_FACTOR(3, 1, 3)
287 #undef TEST_FACTOR1
288 #undef TEST_FACTOR
289 #undef SX
290 #undef DX
291 
292 #define TEST_SCALETO1(DISABLED_, name, width, height, filter, max_diff)        \
293   TEST_F(LibYUVScaleTest, name##To##width##x##height##_##filter) {             \
294     int diff = ARGBTestFilter(benchmark_width_, benchmark_height_, width,      \
295                               height, kFilter##filter, benchmark_iterations_,  \
296                               disable_cpu_flags_, benchmark_cpu_info_);        \
297     EXPECT_LE(diff, max_diff);                                                 \
298   }                                                                            \
299   TEST_F(LibYUVScaleTest, name##From##width##x##height##_##filter) {           \
300     int diff = ARGBTestFilter(width, height, Abs(benchmark_width_),            \
301                               Abs(benchmark_height_), kFilter##filter,         \
302                               benchmark_iterations_, disable_cpu_flags_,       \
303                               benchmark_cpu_info_);                            \
304     EXPECT_LE(diff, max_diff);                                                 \
305   }                                                                            \
306   TEST_F(LibYUVScaleTest,                                                      \
307          DISABLED_##name##ClipTo##width##x##height##_##filter) {               \
308     int diff =                                                                 \
309         ARGBClipTestFilter(benchmark_width_, benchmark_height_, width, height, \
310                            kFilter##filter, benchmark_iterations_);            \
311     EXPECT_LE(diff, max_diff);                                                 \
312   }                                                                            \
313   TEST_F(LibYUVScaleTest,                                                      \
314          DISABLED_##name##ClipFrom##width##x##height##_##filter) {             \
315     int diff = ARGBClipTestFilter(width, height, Abs(benchmark_width_),        \
316                                   Abs(benchmark_height_), kFilter##filter,     \
317                                   benchmark_iterations_);                      \
318     EXPECT_LE(diff, max_diff);                                                 \
319   }
320 
321 #ifndef DISABLE_SLOW_TESTS
322 // Test scale to a specified size with all 4 filters.
323 #define TEST_SCALETO(name, width, height)         \
324   TEST_SCALETO1(, name, width, height, None, 0)   \
325   TEST_SCALETO1(, name, width, height, Linear, 3) \
326   TEST_SCALETO1(, name, width, height, Bilinear, 3)
327 #else
328 #if defined(ENABLE_FULL_TESTS)
329 #define TEST_SCALETO(name, width, height)                  \
330   TEST_SCALETO1(DISABLED_, name, width, height, None, 0)   \
331   TEST_SCALETO1(DISABLED_, name, width, height, Linear, 3) \
332   TEST_SCALETO1(DISABLED_, name, width, height, Bilinear, 3)
333 #else
334 #define TEST_SCALETO(name, width, height) \
335   TEST_SCALETO1(DISABLED_, name, width, height, Bilinear, 3)
336 #endif
337 #endif
338 
339 TEST_SCALETO(ARGBScale, 1, 1)
340 TEST_SCALETO(ARGBScale, 569, 480)
341 TEST_SCALETO(ARGBScale, 640, 360)
342 #ifndef DISABLE_SLOW_TESTS
343 TEST_SCALETO(ARGBScale, 256, 144) /* 128x72 * 2 */
344 TEST_SCALETO(ARGBScale, 320, 240)
345 TEST_SCALETO(ARGBScale, 1280, 720)
346 TEST_SCALETO(ARGBScale, 1920, 1080)
347 #endif  // DISABLE_SLOW_TESTS
348 #undef TEST_SCALETO1
349 #undef TEST_SCALETO
350 
351 #define TEST_SCALESWAPXY1(name, filter, max_diff)                       \
352   TEST_F(LibYUVScaleTest, name##SwapXY_##filter) {                      \
353     int diff = ARGBTestFilter(benchmark_width_, benchmark_height_,      \
354                               benchmark_height_, benchmark_width_,      \
355                               kFilter##filter, benchmark_iterations_,   \
356                               disable_cpu_flags_, benchmark_cpu_info_); \
357     EXPECT_LE(diff, max_diff);                                          \
358   }
359 
360 #if defined(ENABLE_FULL_TESTS)
361 // Test scale with swapped width and height with all 3 filters.
362 TEST_SCALESWAPXY1(ARGBScale, None, 0)
363 TEST_SCALESWAPXY1(ARGBScale, Linear, 0)
364 TEST_SCALESWAPXY1(ARGBScale, Bilinear, 0)
365 #else
366 TEST_SCALESWAPXY1(ARGBScale, Bilinear, 0)
367 #endif
368 #undef TEST_SCALESWAPXY1
369 
370 // Scale with YUV conversion to ARGB and clipping.
371 // TODO(fbarchard): Add fourcc support.  All 4 ARGB formats is easy to support.
372 LIBYUV_API
YUVToARGBScaleReference2(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint32_t,int src_width,int src_height,uint8_t * dst_argb,int dst_stride_argb,uint32_t,int dst_width,int dst_height,int clip_x,int clip_y,int clip_width,int clip_height,enum FilterMode filtering)373 int YUVToARGBScaleReference2(const uint8_t* src_y,
374                              int src_stride_y,
375                              const uint8_t* src_u,
376                              int src_stride_u,
377                              const uint8_t* src_v,
378                              int src_stride_v,
379                              uint32_t /* src_fourcc */,
380                              int src_width,
381                              int src_height,
382                              uint8_t* dst_argb,
383                              int dst_stride_argb,
384                              uint32_t /* dst_fourcc */,
385                              int dst_width,
386                              int dst_height,
387                              int clip_x,
388                              int clip_y,
389                              int clip_width,
390                              int clip_height,
391                              enum FilterMode filtering) {
392   uint8_t* argb_buffer =
393       static_cast<uint8_t*>(malloc(src_width * src_height * 4));
394   int r;
395   I420ToARGB(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
396              argb_buffer, src_width * 4, src_width, src_height);
397 
398   r = ARGBScaleClip(argb_buffer, src_width * 4, src_width, src_height, dst_argb,
399                     dst_stride_argb, dst_width, dst_height, clip_x, clip_y,
400                     clip_width, clip_height, filtering);
401   free(argb_buffer);
402   return r;
403 }
404 
FillRamp(uint8_t * buf,int width,int height,int v,int dx,int dy)405 static void FillRamp(uint8_t* buf,
406                      int width,
407                      int height,
408                      int v,
409                      int dx,
410                      int dy) {
411   int rv = v;
412   for (int y = 0; y < height; ++y) {
413     for (int x = 0; x < width; ++x) {
414       *buf++ = v;
415       v += dx;
416       if (v < 0 || v > 255) {
417         dx = -dx;
418         v += dx;
419       }
420     }
421     v = rv + dy;
422     if (v < 0 || v > 255) {
423       dy = -dy;
424       v += dy;
425     }
426     rv = v;
427   }
428 }
429 
430 // Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
YUVToARGBTestFilter(int src_width,int src_height,int dst_width,int dst_height,FilterMode f,int benchmark_iterations)431 static int YUVToARGBTestFilter(int src_width,
432                                int src_height,
433                                int dst_width,
434                                int dst_height,
435                                FilterMode f,
436                                int benchmark_iterations) {
437   int64_t src_y_plane_size = Abs(src_width) * Abs(src_height);
438   int64_t src_uv_plane_size =
439       ((Abs(src_width) + 1) / 2) * ((Abs(src_height) + 1) / 2);
440   int src_stride_y = Abs(src_width);
441   int src_stride_uv = (Abs(src_width) + 1) / 2;
442 
443   align_buffer_page_end(src_y, src_y_plane_size);
444   align_buffer_page_end(src_u, src_uv_plane_size);
445   align_buffer_page_end(src_v, src_uv_plane_size);
446 
447   int64_t dst_argb_plane_size = (dst_width) * (dst_height)*4LL;
448   int dst_stride_argb = (dst_width)*4;
449   align_buffer_page_end(dst_argb_c, dst_argb_plane_size);
450   align_buffer_page_end(dst_argb_opt, dst_argb_plane_size);
451   if (!dst_argb_c || !dst_argb_opt || !src_y || !src_u || !src_v) {
452     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
453     return 0;
454   }
455   // Fill YUV image with continuous ramp, which is less sensitive to
456   // subsampling and filtering differences for test purposes.
457   FillRamp(src_y, Abs(src_width), Abs(src_height), 128, 1, 1);
458   FillRamp(src_u, (Abs(src_width) + 1) / 2, (Abs(src_height) + 1) / 2, 3, 1, 1);
459   FillRamp(src_v, (Abs(src_width) + 1) / 2, (Abs(src_height) + 1) / 2, 4, 1, 1);
460   memset(dst_argb_c, 2, dst_argb_plane_size);
461   memset(dst_argb_opt, 3, dst_argb_plane_size);
462 
463   YUVToARGBScaleReference2(src_y, src_stride_y, src_u, src_stride_uv, src_v,
464                            src_stride_uv, libyuv::FOURCC_I420, src_width,
465                            src_height, dst_argb_c, dst_stride_argb,
466                            libyuv::FOURCC_I420, dst_width, dst_height, 0, 0,
467                            dst_width, dst_height, f);
468 
469   for (int i = 0; i < benchmark_iterations; ++i) {
470     YUVToARGBScaleClip(src_y, src_stride_y, src_u, src_stride_uv, src_v,
471                        src_stride_uv, libyuv::FOURCC_I420, src_width,
472                        src_height, dst_argb_opt, dst_stride_argb,
473                        libyuv::FOURCC_I420, dst_width, dst_height, 0, 0,
474                        dst_width, dst_height, f);
475   }
476   int max_diff = 0;
477   for (int i = 0; i < dst_height; ++i) {
478     for (int j = 0; j < dst_width * 4; ++j) {
479       int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
480                          dst_argb_opt[(i * dst_stride_argb) + j]);
481       if (abs_diff > max_diff) {
482         printf("error %d at %d,%d c %d opt %d", abs_diff, j, i,
483                dst_argb_c[(i * dst_stride_argb) + j],
484                dst_argb_opt[(i * dst_stride_argb) + j]);
485         EXPECT_LE(abs_diff, 40);
486         max_diff = abs_diff;
487       }
488     }
489   }
490 
491   free_aligned_buffer_page_end(dst_argb_c);
492   free_aligned_buffer_page_end(dst_argb_opt);
493   free_aligned_buffer_page_end(src_y);
494   free_aligned_buffer_page_end(src_u);
495   free_aligned_buffer_page_end(src_v);
496   return max_diff;
497 }
498 
TEST_F(LibYUVScaleTest,YUVToRGBScaleUp)499 TEST_F(LibYUVScaleTest, YUVToRGBScaleUp) {
500   int diff =
501       YUVToARGBTestFilter(benchmark_width_, benchmark_height_,
502                           benchmark_width_ * 3 / 2, benchmark_height_ * 3 / 2,
503                           libyuv::kFilterBilinear, benchmark_iterations_);
504   EXPECT_LE(diff, 10);
505 }
506 
TEST_F(LibYUVScaleTest,YUVToRGBScaleDown)507 TEST_F(LibYUVScaleTest, YUVToRGBScaleDown) {
508   int diff = YUVToARGBTestFilter(
509       benchmark_width_ * 3 / 2, benchmark_height_ * 3 / 2, benchmark_width_,
510       benchmark_height_, libyuv::kFilterBilinear, benchmark_iterations_);
511   EXPECT_LE(diff, 10);
512 }
513 
TEST_F(LibYUVScaleTest,ARGBTest3x)514 TEST_F(LibYUVScaleTest, ARGBTest3x) {
515   const int kSrcStride = 480 * 4;
516   const int kDstStride = 160 * 4;
517   const int kSize = kSrcStride * 3;
518   align_buffer_page_end(orig_pixels, kSize);
519   for (int i = 0; i < 480 * 3; ++i) {
520     orig_pixels[i * 4 + 0] = i;
521     orig_pixels[i * 4 + 1] = 255 - i;
522     orig_pixels[i * 4 + 2] = i + 1;
523     orig_pixels[i * 4 + 3] = i + 10;
524   }
525   align_buffer_page_end(dest_pixels, kDstStride);
526 
527   int iterations160 = (benchmark_width_ * benchmark_height_ + (160 - 1)) / 160 *
528                       benchmark_iterations_;
529   for (int i = 0; i < iterations160; ++i) {
530     ARGBScale(orig_pixels, kSrcStride, 480, 3, dest_pixels, kDstStride, 160, 1,
531               kFilterBilinear);
532   }
533 
534   EXPECT_EQ(225, dest_pixels[0]);
535   EXPECT_EQ(255 - 225, dest_pixels[1]);
536   EXPECT_EQ(226, dest_pixels[2]);
537   EXPECT_EQ(235, dest_pixels[3]);
538 
539   ARGBScale(orig_pixels, kSrcStride, 480, 3, dest_pixels, kDstStride, 160, 1,
540             kFilterNone);
541 
542   EXPECT_EQ(225, dest_pixels[0]);
543   EXPECT_EQ(255 - 225, dest_pixels[1]);
544   EXPECT_EQ(226, dest_pixels[2]);
545   EXPECT_EQ(235, dest_pixels[3]);
546 
547   free_aligned_buffer_page_end(dest_pixels);
548   free_aligned_buffer_page_end(orig_pixels);
549 }
550 
TEST_F(LibYUVScaleTest,ARGBTest4x)551 TEST_F(LibYUVScaleTest, ARGBTest4x) {
552   const int kSrcStride = 640 * 4;
553   const int kDstStride = 160 * 4;
554   const int kSize = kSrcStride * 4;
555   align_buffer_page_end(orig_pixels, kSize);
556   for (int i = 0; i < 640 * 4; ++i) {
557     orig_pixels[i * 4 + 0] = i;
558     orig_pixels[i * 4 + 1] = 255 - i;
559     orig_pixels[i * 4 + 2] = i + 1;
560     orig_pixels[i * 4 + 3] = i + 10;
561   }
562   align_buffer_page_end(dest_pixels, kDstStride);
563 
564   int iterations160 = (benchmark_width_ * benchmark_height_ + (160 - 1)) / 160 *
565                       benchmark_iterations_;
566   for (int i = 0; i < iterations160; ++i) {
567     ARGBScale(orig_pixels, kSrcStride, 640, 4, dest_pixels, kDstStride, 160, 1,
568               kFilterBilinear);
569   }
570 
571   EXPECT_NEAR(66, dest_pixels[0], 4);
572   EXPECT_NEAR(255 - 66, dest_pixels[1], 4);
573   EXPECT_NEAR(67, dest_pixels[2], 4);
574   EXPECT_NEAR(76, dest_pixels[3], 4);
575 
576   ARGBScale(orig_pixels, kSrcStride, 640, 4, dest_pixels, kDstStride, 160, 1,
577             kFilterNone);
578 
579   EXPECT_EQ(2, dest_pixels[0]);
580   EXPECT_EQ(255 - 2, dest_pixels[1]);
581   EXPECT_EQ(3, dest_pixels[2]);
582   EXPECT_EQ(12, dest_pixels[3]);
583 
584   free_aligned_buffer_page_end(dest_pixels);
585   free_aligned_buffer_page_end(orig_pixels);
586 }
587 
588 }  // namespace libyuv
589