xref: /aosp_15_r20/external/libyuv/unit_test/scale_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/cpu_id.h"
16 #include "libyuv/scale.h"
17 
18 #ifdef ENABLE_ROW_TESTS
19 #include "libyuv/scale_row.h"  // For ScaleRowDown2Box_Odd_C
20 #endif
21 
22 #define STRINGIZE(line) #line
23 #define FILELINESTR(file, line) file ":" STRINGIZE(line)
24 
25 #if defined(__riscv) && !defined(__clang__)
26 #define DISABLE_SLOW_TESTS
27 #undef ENABLE_FULL_TESTS
28 #endif
29 
30 #if !defined(DISABLE_SLOW_TESTS) || defined(__x86_64__) || defined(__i386__)
31 // SLOW TESTS are those that are unoptimized C code.
32 // FULL TESTS are optimized but test many variations of the same code.
33 #define ENABLE_FULL_TESTS
34 #endif
35 
36 namespace libyuv {
37 
38 // Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
I420TestFilter(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)39 static int I420TestFilter(int src_width,
40                           int src_height,
41                           int dst_width,
42                           int dst_height,
43                           FilterMode f,
44                           int benchmark_iterations,
45                           int disable_cpu_flags,
46                           int benchmark_cpu_info) {
47   if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
48     return 0;
49   }
50 
51   int i, j;
52   int src_width_uv = (Abs(src_width) + 1) >> 1;
53   int src_height_uv = (Abs(src_height) + 1) >> 1;
54 
55   int64_t src_y_plane_size = (Abs(src_width)) * (Abs(src_height));
56   int64_t src_uv_plane_size = (src_width_uv) * (src_height_uv);
57 
58   int src_stride_y = Abs(src_width);
59   int src_stride_uv = src_width_uv;
60 
61   align_buffer_page_end(src_y, src_y_plane_size);
62   align_buffer_page_end(src_u, src_uv_plane_size);
63   align_buffer_page_end(src_v, src_uv_plane_size);
64   if (!src_y || !src_u || !src_v) {
65     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
66     return 0;
67   }
68   MemRandomize(src_y, src_y_plane_size);
69   MemRandomize(src_u, src_uv_plane_size);
70   MemRandomize(src_v, src_uv_plane_size);
71 
72   int dst_width_uv = (dst_width + 1) >> 1;
73   int dst_height_uv = (dst_height + 1) >> 1;
74 
75   int64_t dst_y_plane_size = (dst_width) * (dst_height);
76   int64_t dst_uv_plane_size = (dst_width_uv) * (dst_height_uv);
77 
78   int dst_stride_y = dst_width;
79   int dst_stride_uv = dst_width_uv;
80 
81   align_buffer_page_end(dst_y_c, dst_y_plane_size);
82   align_buffer_page_end(dst_u_c, dst_uv_plane_size);
83   align_buffer_page_end(dst_v_c, dst_uv_plane_size);
84   align_buffer_page_end(dst_y_opt, dst_y_plane_size);
85   align_buffer_page_end(dst_u_opt, dst_uv_plane_size);
86   align_buffer_page_end(dst_v_opt, dst_uv_plane_size);
87   if (!dst_y_c || !dst_u_c || !dst_v_c || !dst_y_opt || !dst_u_opt ||
88       !dst_v_opt) {
89     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
90     return 0;
91   }
92 
93   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
94   double c_time = get_time();
95   I420Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
96             src_width, src_height, dst_y_c, dst_stride_y, dst_u_c,
97             dst_stride_uv, dst_v_c, dst_stride_uv, dst_width, dst_height, f);
98   c_time = (get_time() - c_time);
99 
100   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
101   double opt_time = get_time();
102   for (i = 0; i < benchmark_iterations; ++i) {
103     I420Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
104               src_width, src_height, dst_y_opt, dst_stride_y, dst_u_opt,
105               dst_stride_uv, dst_v_opt, dst_stride_uv, dst_width, dst_height,
106               f);
107   }
108   opt_time = (get_time() - opt_time) / benchmark_iterations;
109   // Report performance of C vs OPT.
110   printf("filter %d - %8d us C - %8d us OPT\n", f,
111          static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));
112 
113   // C version may be a little off from the optimized. Order of
114   //  operations may introduce rounding somewhere. So do a difference
115   //  of the buffers and look to see that the max difference is not
116   //  over 3.
117   int max_diff = 0;
118   for (i = 0; i < (dst_height); ++i) {
119     for (j = 0; j < (dst_width); ++j) {
120       int abs_diff = Abs(dst_y_c[(i * dst_stride_y) + j] -
121                          dst_y_opt[(i * dst_stride_y) + j]);
122       if (abs_diff > max_diff) {
123         max_diff = abs_diff;
124       }
125     }
126   }
127 
128   for (i = 0; i < (dst_height_uv); ++i) {
129     for (j = 0; j < (dst_width_uv); ++j) {
130       int abs_diff = Abs(dst_u_c[(i * dst_stride_uv) + j] -
131                          dst_u_opt[(i * dst_stride_uv) + j]);
132       if (abs_diff > max_diff) {
133         max_diff = abs_diff;
134       }
135       abs_diff = Abs(dst_v_c[(i * dst_stride_uv) + j] -
136                      dst_v_opt[(i * dst_stride_uv) + j]);
137       if (abs_diff > max_diff) {
138         max_diff = abs_diff;
139       }
140     }
141   }
142 
143   free_aligned_buffer_page_end(dst_y_c);
144   free_aligned_buffer_page_end(dst_u_c);
145   free_aligned_buffer_page_end(dst_v_c);
146   free_aligned_buffer_page_end(dst_y_opt);
147   free_aligned_buffer_page_end(dst_u_opt);
148   free_aligned_buffer_page_end(dst_v_opt);
149   free_aligned_buffer_page_end(src_y);
150   free_aligned_buffer_page_end(src_u);
151   free_aligned_buffer_page_end(src_v);
152 
153   return max_diff;
154 }
155 
156 // Test scaling with 8 bit C vs 12 bit C and return maximum pixel difference.
157 // 0 = exact.
I420TestFilter_12(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)158 static int I420TestFilter_12(int src_width,
159                              int src_height,
160                              int dst_width,
161                              int dst_height,
162                              FilterMode f,
163                              int benchmark_iterations,
164                              int disable_cpu_flags,
165                              int benchmark_cpu_info) {
166   if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
167     return 0;
168   }
169 
170   int i;
171   int src_width_uv = (Abs(src_width) + 1) >> 1;
172   int src_height_uv = (Abs(src_height) + 1) >> 1;
173 
174   int64_t src_y_plane_size = (Abs(src_width)) * (Abs(src_height));
175   int64_t src_uv_plane_size = (src_width_uv) * (src_height_uv);
176 
177   int src_stride_y = Abs(src_width);
178   int src_stride_uv = src_width_uv;
179 
180   align_buffer_page_end(src_y, src_y_plane_size);
181   align_buffer_page_end(src_u, src_uv_plane_size);
182   align_buffer_page_end(src_v, src_uv_plane_size);
183   align_buffer_page_end(src_y_12, src_y_plane_size * 2);
184   align_buffer_page_end(src_u_12, src_uv_plane_size * 2);
185   align_buffer_page_end(src_v_12, src_uv_plane_size * 2);
186   if (!src_y || !src_u || !src_v || !src_y_12 || !src_u_12 || !src_v_12) {
187     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
188     return 0;
189   }
190   uint16_t* p_src_y_12 = reinterpret_cast<uint16_t*>(src_y_12);
191   uint16_t* p_src_u_12 = reinterpret_cast<uint16_t*>(src_u_12);
192   uint16_t* p_src_v_12 = reinterpret_cast<uint16_t*>(src_v_12);
193 
194   MemRandomize(src_y, src_y_plane_size);
195   MemRandomize(src_u, src_uv_plane_size);
196   MemRandomize(src_v, src_uv_plane_size);
197 
198   for (i = 0; i < src_y_plane_size; ++i) {
199     p_src_y_12[i] = src_y[i];
200   }
201   for (i = 0; i < src_uv_plane_size; ++i) {
202     p_src_u_12[i] = src_u[i];
203     p_src_v_12[i] = src_v[i];
204   }
205 
206   int dst_width_uv = (dst_width + 1) >> 1;
207   int dst_height_uv = (dst_height + 1) >> 1;
208 
209   int dst_y_plane_size = (dst_width) * (dst_height);
210   int dst_uv_plane_size = (dst_width_uv) * (dst_height_uv);
211 
212   int dst_stride_y = dst_width;
213   int dst_stride_uv = dst_width_uv;
214 
215   align_buffer_page_end(dst_y_8, dst_y_plane_size);
216   align_buffer_page_end(dst_u_8, dst_uv_plane_size);
217   align_buffer_page_end(dst_v_8, dst_uv_plane_size);
218   align_buffer_page_end(dst_y_12, dst_y_plane_size * 2);
219   align_buffer_page_end(dst_u_12, dst_uv_plane_size * 2);
220   align_buffer_page_end(dst_v_12, dst_uv_plane_size * 2);
221 
222   uint16_t* p_dst_y_12 = reinterpret_cast<uint16_t*>(dst_y_12);
223   uint16_t* p_dst_u_12 = reinterpret_cast<uint16_t*>(dst_u_12);
224   uint16_t* p_dst_v_12 = reinterpret_cast<uint16_t*>(dst_v_12);
225 
226   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
227   I420Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
228             src_width, src_height, dst_y_8, dst_stride_y, dst_u_8,
229             dst_stride_uv, dst_v_8, dst_stride_uv, dst_width, dst_height, f);
230   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
231   for (i = 0; i < benchmark_iterations; ++i) {
232     I420Scale_12(p_src_y_12, src_stride_y, p_src_u_12, src_stride_uv,
233                  p_src_v_12, src_stride_uv, src_width, src_height, p_dst_y_12,
234                  dst_stride_y, p_dst_u_12, dst_stride_uv, p_dst_v_12,
235                  dst_stride_uv, dst_width, dst_height, f);
236   }
237 
238   // Expect an exact match.
239   int max_diff = 0;
240   for (i = 0; i < dst_y_plane_size; ++i) {
241     int abs_diff = Abs(dst_y_8[i] - p_dst_y_12[i]);
242     if (abs_diff > max_diff) {
243       max_diff = abs_diff;
244     }
245   }
246   for (i = 0; i < dst_uv_plane_size; ++i) {
247     int abs_diff = Abs(dst_u_8[i] - p_dst_u_12[i]);
248     if (abs_diff > max_diff) {
249       max_diff = abs_diff;
250     }
251     abs_diff = Abs(dst_v_8[i] - p_dst_v_12[i]);
252     if (abs_diff > max_diff) {
253       max_diff = abs_diff;
254     }
255   }
256 
257   free_aligned_buffer_page_end(dst_y_8);
258   free_aligned_buffer_page_end(dst_u_8);
259   free_aligned_buffer_page_end(dst_v_8);
260   free_aligned_buffer_page_end(dst_y_12);
261   free_aligned_buffer_page_end(dst_u_12);
262   free_aligned_buffer_page_end(dst_v_12);
263   free_aligned_buffer_page_end(src_y);
264   free_aligned_buffer_page_end(src_u);
265   free_aligned_buffer_page_end(src_v);
266   free_aligned_buffer_page_end(src_y_12);
267   free_aligned_buffer_page_end(src_u_12);
268   free_aligned_buffer_page_end(src_v_12);
269 
270   return max_diff;
271 }
272 
273 // Test scaling with 8 bit C vs 16 bit C and return maximum pixel difference.
274 // 0 = exact.
I420TestFilter_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)275 static int I420TestFilter_16(int src_width,
276                              int src_height,
277                              int dst_width,
278                              int dst_height,
279                              FilterMode f,
280                              int benchmark_iterations,
281                              int disable_cpu_flags,
282                              int benchmark_cpu_info) {
283   if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
284     return 0;
285   }
286 
287   int i;
288   int src_width_uv = (Abs(src_width) + 1) >> 1;
289   int src_height_uv = (Abs(src_height) + 1) >> 1;
290 
291   int64_t src_y_plane_size = (Abs(src_width)) * (Abs(src_height));
292   int64_t src_uv_plane_size = (src_width_uv) * (src_height_uv);
293 
294   int src_stride_y = Abs(src_width);
295   int src_stride_uv = src_width_uv;
296 
297   align_buffer_page_end(src_y, src_y_plane_size);
298   align_buffer_page_end(src_u, src_uv_plane_size);
299   align_buffer_page_end(src_v, src_uv_plane_size);
300   align_buffer_page_end(src_y_16, src_y_plane_size * 2);
301   align_buffer_page_end(src_u_16, src_uv_plane_size * 2);
302   align_buffer_page_end(src_v_16, src_uv_plane_size * 2);
303   if (!src_y || !src_u || !src_v || !src_y_16 || !src_u_16 || !src_v_16) {
304     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
305     return 0;
306   }
307   uint16_t* p_src_y_16 = reinterpret_cast<uint16_t*>(src_y_16);
308   uint16_t* p_src_u_16 = reinterpret_cast<uint16_t*>(src_u_16);
309   uint16_t* p_src_v_16 = reinterpret_cast<uint16_t*>(src_v_16);
310 
311   MemRandomize(src_y, src_y_plane_size);
312   MemRandomize(src_u, src_uv_plane_size);
313   MemRandomize(src_v, src_uv_plane_size);
314 
315   for (i = 0; i < src_y_plane_size; ++i) {
316     p_src_y_16[i] = src_y[i];
317   }
318   for (i = 0; i < src_uv_plane_size; ++i) {
319     p_src_u_16[i] = src_u[i];
320     p_src_v_16[i] = src_v[i];
321   }
322 
323   int dst_width_uv = (dst_width + 1) >> 1;
324   int dst_height_uv = (dst_height + 1) >> 1;
325 
326   int dst_y_plane_size = (dst_width) * (dst_height);
327   int dst_uv_plane_size = (dst_width_uv) * (dst_height_uv);
328 
329   int dst_stride_y = dst_width;
330   int dst_stride_uv = dst_width_uv;
331 
332   align_buffer_page_end(dst_y_8, dst_y_plane_size);
333   align_buffer_page_end(dst_u_8, dst_uv_plane_size);
334   align_buffer_page_end(dst_v_8, dst_uv_plane_size);
335   align_buffer_page_end(dst_y_16, dst_y_plane_size * 2);
336   align_buffer_page_end(dst_u_16, dst_uv_plane_size * 2);
337   align_buffer_page_end(dst_v_16, dst_uv_plane_size * 2);
338 
339   uint16_t* p_dst_y_16 = reinterpret_cast<uint16_t*>(dst_y_16);
340   uint16_t* p_dst_u_16 = reinterpret_cast<uint16_t*>(dst_u_16);
341   uint16_t* p_dst_v_16 = reinterpret_cast<uint16_t*>(dst_v_16);
342 
343   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
344   I420Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
345             src_width, src_height, dst_y_8, dst_stride_y, dst_u_8,
346             dst_stride_uv, dst_v_8, dst_stride_uv, dst_width, dst_height, f);
347   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
348   for (i = 0; i < benchmark_iterations; ++i) {
349     I420Scale_16(p_src_y_16, src_stride_y, p_src_u_16, src_stride_uv,
350                  p_src_v_16, src_stride_uv, src_width, src_height, p_dst_y_16,
351                  dst_stride_y, p_dst_u_16, dst_stride_uv, p_dst_v_16,
352                  dst_stride_uv, dst_width, dst_height, f);
353   }
354 
355   // Expect an exact match.
356   int max_diff = 0;
357   for (i = 0; i < dst_y_plane_size; ++i) {
358     int abs_diff = Abs(dst_y_8[i] - p_dst_y_16[i]);
359     if (abs_diff > max_diff) {
360       max_diff = abs_diff;
361     }
362   }
363   for (i = 0; i < dst_uv_plane_size; ++i) {
364     int abs_diff = Abs(dst_u_8[i] - p_dst_u_16[i]);
365     if (abs_diff > max_diff) {
366       max_diff = abs_diff;
367     }
368     abs_diff = Abs(dst_v_8[i] - p_dst_v_16[i]);
369     if (abs_diff > max_diff) {
370       max_diff = abs_diff;
371     }
372   }
373 
374   free_aligned_buffer_page_end(dst_y_8);
375   free_aligned_buffer_page_end(dst_u_8);
376   free_aligned_buffer_page_end(dst_v_8);
377   free_aligned_buffer_page_end(dst_y_16);
378   free_aligned_buffer_page_end(dst_u_16);
379   free_aligned_buffer_page_end(dst_v_16);
380   free_aligned_buffer_page_end(src_y);
381   free_aligned_buffer_page_end(src_u);
382   free_aligned_buffer_page_end(src_v);
383   free_aligned_buffer_page_end(src_y_16);
384   free_aligned_buffer_page_end(src_u_16);
385   free_aligned_buffer_page_end(src_v_16);
386 
387   return max_diff;
388 }
389 
390 // Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
I444TestFilter(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)391 static int I444TestFilter(int src_width,
392                           int src_height,
393                           int dst_width,
394                           int dst_height,
395                           FilterMode f,
396                           int benchmark_iterations,
397                           int disable_cpu_flags,
398                           int benchmark_cpu_info) {
399   if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
400     return 0;
401   }
402 
403   int i, j;
404   int src_width_uv = Abs(src_width);
405   int src_height_uv = Abs(src_height);
406 
407   int64_t src_y_plane_size = (Abs(src_width)) * (Abs(src_height));
408   int64_t src_uv_plane_size = (src_width_uv) * (src_height_uv);
409 
410   int src_stride_y = Abs(src_width);
411   int src_stride_uv = src_width_uv;
412 
413   align_buffer_page_end(src_y, src_y_plane_size);
414   align_buffer_page_end(src_u, src_uv_plane_size);
415   align_buffer_page_end(src_v, src_uv_plane_size);
416   if (!src_y || !src_u || !src_v) {
417     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
418     return 0;
419   }
420   MemRandomize(src_y, src_y_plane_size);
421   MemRandomize(src_u, src_uv_plane_size);
422   MemRandomize(src_v, src_uv_plane_size);
423 
424   int dst_width_uv = dst_width;
425   int dst_height_uv = dst_height;
426 
427   int64_t dst_y_plane_size = (dst_width) * (dst_height);
428   int64_t dst_uv_plane_size = (dst_width_uv) * (dst_height_uv);
429 
430   int dst_stride_y = dst_width;
431   int dst_stride_uv = dst_width_uv;
432 
433   align_buffer_page_end(dst_y_c, dst_y_plane_size);
434   align_buffer_page_end(dst_u_c, dst_uv_plane_size);
435   align_buffer_page_end(dst_v_c, dst_uv_plane_size);
436   align_buffer_page_end(dst_y_opt, dst_y_plane_size);
437   align_buffer_page_end(dst_u_opt, dst_uv_plane_size);
438   align_buffer_page_end(dst_v_opt, dst_uv_plane_size);
439   if (!dst_y_c || !dst_u_c || !dst_v_c || !dst_y_opt || !dst_u_opt ||
440       !dst_v_opt) {
441     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
442     return 0;
443   }
444 
445   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
446   double c_time = get_time();
447   I444Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
448             src_width, src_height, dst_y_c, dst_stride_y, dst_u_c,
449             dst_stride_uv, dst_v_c, dst_stride_uv, dst_width, dst_height, f);
450   c_time = (get_time() - c_time);
451 
452   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
453   double opt_time = get_time();
454   for (i = 0; i < benchmark_iterations; ++i) {
455     I444Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
456               src_width, src_height, dst_y_opt, dst_stride_y, dst_u_opt,
457               dst_stride_uv, dst_v_opt, dst_stride_uv, dst_width, dst_height,
458               f);
459   }
460   opt_time = (get_time() - opt_time) / benchmark_iterations;
461   // Report performance of C vs OPT.
462   printf("filter %d - %8d us C - %8d us OPT\n", f,
463          static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));
464 
465   // C version may be a little off from the optimized. Order of
466   //  operations may introduce rounding somewhere. So do a difference
467   //  of the buffers and look to see that the max difference is not
468   //  over 3.
469   int max_diff = 0;
470   for (i = 0; i < (dst_height); ++i) {
471     for (j = 0; j < (dst_width); ++j) {
472       int abs_diff = Abs(dst_y_c[(i * dst_stride_y) + j] -
473                          dst_y_opt[(i * dst_stride_y) + j]);
474       if (abs_diff > max_diff) {
475         max_diff = abs_diff;
476       }
477     }
478   }
479 
480   for (i = 0; i < (dst_height_uv); ++i) {
481     for (j = 0; j < (dst_width_uv); ++j) {
482       int abs_diff = Abs(dst_u_c[(i * dst_stride_uv) + j] -
483                          dst_u_opt[(i * dst_stride_uv) + j]);
484       if (abs_diff > max_diff) {
485         max_diff = abs_diff;
486       }
487       abs_diff = Abs(dst_v_c[(i * dst_stride_uv) + j] -
488                      dst_v_opt[(i * dst_stride_uv) + j]);
489       if (abs_diff > max_diff) {
490         max_diff = abs_diff;
491       }
492     }
493   }
494 
495   free_aligned_buffer_page_end(dst_y_c);
496   free_aligned_buffer_page_end(dst_u_c);
497   free_aligned_buffer_page_end(dst_v_c);
498   free_aligned_buffer_page_end(dst_y_opt);
499   free_aligned_buffer_page_end(dst_u_opt);
500   free_aligned_buffer_page_end(dst_v_opt);
501   free_aligned_buffer_page_end(src_y);
502   free_aligned_buffer_page_end(src_u);
503   free_aligned_buffer_page_end(src_v);
504 
505   return max_diff;
506 }
507 
508 // Test scaling with 8 bit C vs 12 bit C and return maximum pixel difference.
509 // 0 = exact.
I444TestFilter_12(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)510 static int I444TestFilter_12(int src_width,
511                              int src_height,
512                              int dst_width,
513                              int dst_height,
514                              FilterMode f,
515                              int benchmark_iterations,
516                              int disable_cpu_flags,
517                              int benchmark_cpu_info) {
518   if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
519     return 0;
520   }
521 
522   int i;
523   int src_width_uv = Abs(src_width);
524   int src_height_uv = Abs(src_height);
525 
526   int64_t src_y_plane_size = (Abs(src_width)) * (Abs(src_height));
527   int64_t src_uv_plane_size = (src_width_uv) * (src_height_uv);
528 
529   int src_stride_y = Abs(src_width);
530   int src_stride_uv = src_width_uv;
531 
532   align_buffer_page_end(src_y, src_y_plane_size);
533   align_buffer_page_end(src_u, src_uv_plane_size);
534   align_buffer_page_end(src_v, src_uv_plane_size);
535   align_buffer_page_end(src_y_12, src_y_plane_size * 2);
536   align_buffer_page_end(src_u_12, src_uv_plane_size * 2);
537   align_buffer_page_end(src_v_12, src_uv_plane_size * 2);
538   if (!src_y || !src_u || !src_v || !src_y_12 || !src_u_12 || !src_v_12) {
539     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
540     return 0;
541   }
542   uint16_t* p_src_y_12 = reinterpret_cast<uint16_t*>(src_y_12);
543   uint16_t* p_src_u_12 = reinterpret_cast<uint16_t*>(src_u_12);
544   uint16_t* p_src_v_12 = reinterpret_cast<uint16_t*>(src_v_12);
545 
546   MemRandomize(src_y, src_y_plane_size);
547   MemRandomize(src_u, src_uv_plane_size);
548   MemRandomize(src_v, src_uv_plane_size);
549 
550   for (i = 0; i < src_y_plane_size; ++i) {
551     p_src_y_12[i] = src_y[i];
552   }
553   for (i = 0; i < src_uv_plane_size; ++i) {
554     p_src_u_12[i] = src_u[i];
555     p_src_v_12[i] = src_v[i];
556   }
557 
558   int dst_width_uv = dst_width;
559   int dst_height_uv = dst_height;
560 
561   int dst_y_plane_size = (dst_width) * (dst_height);
562   int dst_uv_plane_size = (dst_width_uv) * (dst_height_uv);
563 
564   int dst_stride_y = dst_width;
565   int dst_stride_uv = dst_width_uv;
566 
567   align_buffer_page_end(dst_y_8, dst_y_plane_size);
568   align_buffer_page_end(dst_u_8, dst_uv_plane_size);
569   align_buffer_page_end(dst_v_8, dst_uv_plane_size);
570   align_buffer_page_end(dst_y_12, dst_y_plane_size * 2);
571   align_buffer_page_end(dst_u_12, dst_uv_plane_size * 2);
572   align_buffer_page_end(dst_v_12, dst_uv_plane_size * 2);
573 
574   uint16_t* p_dst_y_12 = reinterpret_cast<uint16_t*>(dst_y_12);
575   uint16_t* p_dst_u_12 = reinterpret_cast<uint16_t*>(dst_u_12);
576   uint16_t* p_dst_v_12 = reinterpret_cast<uint16_t*>(dst_v_12);
577 
578   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
579   I444Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
580             src_width, src_height, dst_y_8, dst_stride_y, dst_u_8,
581             dst_stride_uv, dst_v_8, dst_stride_uv, dst_width, dst_height, f);
582   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
583   for (i = 0; i < benchmark_iterations; ++i) {
584     I444Scale_12(p_src_y_12, src_stride_y, p_src_u_12, src_stride_uv,
585                  p_src_v_12, src_stride_uv, src_width, src_height, p_dst_y_12,
586                  dst_stride_y, p_dst_u_12, dst_stride_uv, p_dst_v_12,
587                  dst_stride_uv, dst_width, dst_height, f);
588   }
589 
590   // Expect an exact match.
591   int max_diff = 0;
592   for (i = 0; i < dst_y_plane_size; ++i) {
593     int abs_diff = Abs(dst_y_8[i] - p_dst_y_12[i]);
594     if (abs_diff > max_diff) {
595       max_diff = abs_diff;
596     }
597   }
598   for (i = 0; i < dst_uv_plane_size; ++i) {
599     int abs_diff = Abs(dst_u_8[i] - p_dst_u_12[i]);
600     if (abs_diff > max_diff) {
601       max_diff = abs_diff;
602     }
603     abs_diff = Abs(dst_v_8[i] - p_dst_v_12[i]);
604     if (abs_diff > max_diff) {
605       max_diff = abs_diff;
606     }
607   }
608 
609   free_aligned_buffer_page_end(dst_y_8);
610   free_aligned_buffer_page_end(dst_u_8);
611   free_aligned_buffer_page_end(dst_v_8);
612   free_aligned_buffer_page_end(dst_y_12);
613   free_aligned_buffer_page_end(dst_u_12);
614   free_aligned_buffer_page_end(dst_v_12);
615   free_aligned_buffer_page_end(src_y);
616   free_aligned_buffer_page_end(src_u);
617   free_aligned_buffer_page_end(src_v);
618   free_aligned_buffer_page_end(src_y_12);
619   free_aligned_buffer_page_end(src_u_12);
620   free_aligned_buffer_page_end(src_v_12);
621 
622   return max_diff;
623 }
624 
625 // Test scaling with 8 bit C vs 16 bit C and return maximum pixel difference.
626 // 0 = exact.
I444TestFilter_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)627 static int I444TestFilter_16(int src_width,
628                              int src_height,
629                              int dst_width,
630                              int dst_height,
631                              FilterMode f,
632                              int benchmark_iterations,
633                              int disable_cpu_flags,
634                              int benchmark_cpu_info) {
635   if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
636     return 0;
637   }
638 
639   int i;
640   int src_width_uv = Abs(src_width);
641   int src_height_uv = Abs(src_height);
642 
643   int64_t src_y_plane_size = (Abs(src_width)) * (Abs(src_height));
644   int64_t src_uv_plane_size = (src_width_uv) * (src_height_uv);
645 
646   int src_stride_y = Abs(src_width);
647   int src_stride_uv = src_width_uv;
648 
649   align_buffer_page_end(src_y, src_y_plane_size);
650   align_buffer_page_end(src_u, src_uv_plane_size);
651   align_buffer_page_end(src_v, src_uv_plane_size);
652   align_buffer_page_end(src_y_16, src_y_plane_size * 2);
653   align_buffer_page_end(src_u_16, src_uv_plane_size * 2);
654   align_buffer_page_end(src_v_16, src_uv_plane_size * 2);
655   if (!src_y || !src_u || !src_v || !src_y_16 || !src_u_16 || !src_v_16) {
656     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
657     return 0;
658   }
659   uint16_t* p_src_y_16 = reinterpret_cast<uint16_t*>(src_y_16);
660   uint16_t* p_src_u_16 = reinterpret_cast<uint16_t*>(src_u_16);
661   uint16_t* p_src_v_16 = reinterpret_cast<uint16_t*>(src_v_16);
662 
663   MemRandomize(src_y, src_y_plane_size);
664   MemRandomize(src_u, src_uv_plane_size);
665   MemRandomize(src_v, src_uv_plane_size);
666 
667   for (i = 0; i < src_y_plane_size; ++i) {
668     p_src_y_16[i] = src_y[i];
669   }
670   for (i = 0; i < src_uv_plane_size; ++i) {
671     p_src_u_16[i] = src_u[i];
672     p_src_v_16[i] = src_v[i];
673   }
674 
675   int dst_width_uv = dst_width;
676   int dst_height_uv = dst_height;
677 
678   int dst_y_plane_size = (dst_width) * (dst_height);
679   int dst_uv_plane_size = (dst_width_uv) * (dst_height_uv);
680 
681   int dst_stride_y = dst_width;
682   int dst_stride_uv = dst_width_uv;
683 
684   align_buffer_page_end(dst_y_8, dst_y_plane_size);
685   align_buffer_page_end(dst_u_8, dst_uv_plane_size);
686   align_buffer_page_end(dst_v_8, dst_uv_plane_size);
687   align_buffer_page_end(dst_y_16, dst_y_plane_size * 2);
688   align_buffer_page_end(dst_u_16, dst_uv_plane_size * 2);
689   align_buffer_page_end(dst_v_16, dst_uv_plane_size * 2);
690 
691   uint16_t* p_dst_y_16 = reinterpret_cast<uint16_t*>(dst_y_16);
692   uint16_t* p_dst_u_16 = reinterpret_cast<uint16_t*>(dst_u_16);
693   uint16_t* p_dst_v_16 = reinterpret_cast<uint16_t*>(dst_v_16);
694 
695   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
696   I444Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
697             src_width, src_height, dst_y_8, dst_stride_y, dst_u_8,
698             dst_stride_uv, dst_v_8, dst_stride_uv, dst_width, dst_height, f);
699   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
700   for (i = 0; i < benchmark_iterations; ++i) {
701     I444Scale_16(p_src_y_16, src_stride_y, p_src_u_16, src_stride_uv,
702                  p_src_v_16, src_stride_uv, src_width, src_height, p_dst_y_16,
703                  dst_stride_y, p_dst_u_16, dst_stride_uv, p_dst_v_16,
704                  dst_stride_uv, dst_width, dst_height, f);
705   }
706 
707   // Expect an exact match.
708   int max_diff = 0;
709   for (i = 0; i < dst_y_plane_size; ++i) {
710     int abs_diff = Abs(dst_y_8[i] - p_dst_y_16[i]);
711     if (abs_diff > max_diff) {
712       max_diff = abs_diff;
713     }
714   }
715   for (i = 0; i < dst_uv_plane_size; ++i) {
716     int abs_diff = Abs(dst_u_8[i] - p_dst_u_16[i]);
717     if (abs_diff > max_diff) {
718       max_diff = abs_diff;
719     }
720     abs_diff = Abs(dst_v_8[i] - p_dst_v_16[i]);
721     if (abs_diff > max_diff) {
722       max_diff = abs_diff;
723     }
724   }
725 
726   free_aligned_buffer_page_end(dst_y_8);
727   free_aligned_buffer_page_end(dst_u_8);
728   free_aligned_buffer_page_end(dst_v_8);
729   free_aligned_buffer_page_end(dst_y_16);
730   free_aligned_buffer_page_end(dst_u_16);
731   free_aligned_buffer_page_end(dst_v_16);
732   free_aligned_buffer_page_end(src_y);
733   free_aligned_buffer_page_end(src_u);
734   free_aligned_buffer_page_end(src_v);
735   free_aligned_buffer_page_end(src_y_16);
736   free_aligned_buffer_page_end(src_u_16);
737   free_aligned_buffer_page_end(src_v_16);
738 
739   return max_diff;
740 }
741 
742 // Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
NV12TestFilter(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)743 static int NV12TestFilter(int src_width,
744                           int src_height,
745                           int dst_width,
746                           int dst_height,
747                           FilterMode f,
748                           int benchmark_iterations,
749                           int disable_cpu_flags,
750                           int benchmark_cpu_info) {
751   if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
752     return 0;
753   }
754 
755   int i, j;
756   int src_width_uv = (Abs(src_width) + 1) >> 1;
757   int src_height_uv = (Abs(src_height) + 1) >> 1;
758 
759   int64_t src_y_plane_size = (Abs(src_width)) * (Abs(src_height));
760   int64_t src_uv_plane_size = (src_width_uv) * (src_height_uv)*2;
761 
762   int src_stride_y = Abs(src_width);
763   int src_stride_uv = src_width_uv * 2;
764 
765   align_buffer_page_end(src_y, src_y_plane_size);
766   align_buffer_page_end(src_uv, src_uv_plane_size);
767   if (!src_y || !src_uv) {
768     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
769     return 0;
770   }
771   MemRandomize(src_y, src_y_plane_size);
772   MemRandomize(src_uv, src_uv_plane_size);
773 
774   int dst_width_uv = (dst_width + 1) >> 1;
775   int dst_height_uv = (dst_height + 1) >> 1;
776 
777   int64_t dst_y_plane_size = (dst_width) * (dst_height);
778   int64_t dst_uv_plane_size = (dst_width_uv) * (dst_height_uv)*2;
779 
780   int dst_stride_y = dst_width;
781   int dst_stride_uv = dst_width_uv * 2;
782 
783   align_buffer_page_end(dst_y_c, dst_y_plane_size);
784   align_buffer_page_end(dst_uv_c, dst_uv_plane_size);
785   align_buffer_page_end(dst_y_opt, dst_y_plane_size);
786   align_buffer_page_end(dst_uv_opt, dst_uv_plane_size);
787   if (!dst_y_c || !dst_uv_c || !dst_y_opt || !dst_uv_opt) {
788     printf("Skipped.  Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
789     return 0;
790   }
791 
792   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
793   double c_time = get_time();
794   NV12Scale(src_y, src_stride_y, src_uv, src_stride_uv, src_width, src_height,
795             dst_y_c, dst_stride_y, dst_uv_c, dst_stride_uv, dst_width,
796             dst_height, f);
797   c_time = (get_time() - c_time);
798 
799   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
800   double opt_time = get_time();
801   for (i = 0; i < benchmark_iterations; ++i) {
802     NV12Scale(src_y, src_stride_y, src_uv, src_stride_uv, src_width, src_height,
803               dst_y_opt, dst_stride_y, dst_uv_opt, dst_stride_uv, dst_width,
804               dst_height, f);
805   }
806   opt_time = (get_time() - opt_time) / benchmark_iterations;
807   // Report performance of C vs OPT.
808   printf("filter %d - %8d us C - %8d us OPT\n", f,
809          static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));
810 
811   // C version may be a little off from the optimized. Order of
812   //  operations may introduce rounding somewhere. So do a difference
813   //  of the buffers and look to see that the max difference is not
814   //  over 3.
815   int max_diff = 0;
816   for (i = 0; i < (dst_height); ++i) {
817     for (j = 0; j < (dst_width); ++j) {
818       int abs_diff = Abs(dst_y_c[(i * dst_stride_y) + j] -
819                          dst_y_opt[(i * dst_stride_y) + j]);
820       if (abs_diff > max_diff) {
821         max_diff = abs_diff;
822       }
823     }
824   }
825 
826   for (i = 0; i < (dst_height_uv); ++i) {
827     for (j = 0; j < (dst_width_uv * 2); ++j) {
828       int abs_diff = Abs(dst_uv_c[(i * dst_stride_uv) + j] -
829                          dst_uv_opt[(i * dst_stride_uv) + j]);
830       if (abs_diff > max_diff) {
831         max_diff = abs_diff;
832       }
833     }
834   }
835 
836   free_aligned_buffer_page_end(dst_y_c);
837   free_aligned_buffer_page_end(dst_uv_c);
838   free_aligned_buffer_page_end(dst_y_opt);
839   free_aligned_buffer_page_end(dst_uv_opt);
840   free_aligned_buffer_page_end(src_y);
841   free_aligned_buffer_page_end(src_uv);
842 
843   return max_diff;
844 }
845 
846 // The following adjustments in dimensions ensure the scale factor will be
847 // exactly achieved.
848 // 2 is chroma subsample.
849 #define DX(x, nom, denom) static_cast<int>(((Abs(x) / nom + 1) / 2) * nom * 2)
850 #define SX(x, nom, denom) static_cast<int>(((x / nom + 1) / 2) * denom * 2)
851 
852 #define TEST_FACTOR1(DISABLED_, name, filter, nom, denom, max_diff)           \
853   TEST_F(LibYUVScaleTest, I420ScaleDownBy##name##_##filter) {                 \
854     int diff = I420TestFilter(                                                \
855         SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom),  \
856         DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom),  \
857         kFilter##filter, benchmark_iterations_, disable_cpu_flags_,           \
858         benchmark_cpu_info_);                                                 \
859     EXPECT_LE(diff, max_diff);                                                \
860   }                                                                           \
861   TEST_F(LibYUVScaleTest, I444ScaleDownBy##name##_##filter) {                 \
862     int diff = I444TestFilter(                                                \
863         SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom),  \
864         DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom),  \
865         kFilter##filter, benchmark_iterations_, disable_cpu_flags_,           \
866         benchmark_cpu_info_);                                                 \
867     EXPECT_LE(diff, max_diff);                                                \
868   }                                                                           \
869   TEST_F(LibYUVScaleTest, DISABLED_##I420ScaleDownBy##name##_##filter##_12) { \
870     int diff = I420TestFilter_12(                                             \
871         SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom),  \
872         DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom),  \
873         kFilter##filter, benchmark_iterations_, disable_cpu_flags_,           \
874         benchmark_cpu_info_);                                                 \
875     EXPECT_LE(diff, max_diff);                                                \
876   }                                                                           \
877   TEST_F(LibYUVScaleTest, DISABLED_##I444ScaleDownBy##name##_##filter##_12) { \
878     int diff = I444TestFilter_12(                                             \
879         SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom),  \
880         DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom),  \
881         kFilter##filter, benchmark_iterations_, disable_cpu_flags_,           \
882         benchmark_cpu_info_);                                                 \
883     EXPECT_LE(diff, max_diff);                                                \
884   }                                                                           \
885   TEST_F(LibYUVScaleTest, NV12ScaleDownBy##name##_##filter) {                 \
886     int diff = NV12TestFilter(                                                \
887         SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom),  \
888         DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom),  \
889         kFilter##filter, benchmark_iterations_, disable_cpu_flags_,           \
890         benchmark_cpu_info_);                                                 \
891     EXPECT_LE(diff, max_diff);                                                \
892   }
893 
894 // Test a scale factor with all 4 filters.  Expect unfiltered to be exact, but
895 // filtering is different fixed point implementations for SSSE3, Neon and C.
896 #ifndef DISABLE_SLOW_TESTS
897 #define TEST_FACTOR(name, nom, denom, boxdiff)  \
898   TEST_FACTOR1(, name, None, nom, denom, 0)     \
899   TEST_FACTOR1(, name, Linear, nom, denom, 3)   \
900   TEST_FACTOR1(, name, Bilinear, nom, denom, 3) \
901   TEST_FACTOR1(, name, Box, nom, denom, boxdiff)
902 #else
903 #if defined(ENABLE_FULL_TESTS)
904 #define TEST_FACTOR(name, nom, denom, boxdiff)           \
905   TEST_FACTOR1(DISABLED_, name, None, nom, denom, 0)     \
906   TEST_FACTOR1(DISABLED_, name, Linear, nom, denom, 3)   \
907   TEST_FACTOR1(DISABLED_, name, Bilinear, nom, denom, 3) \
908   TEST_FACTOR1(DISABLED_, name, Box, nom, denom, boxdiff)
909 #else
910 #define TEST_FACTOR(name, nom, denom, boxdiff)           \
911   TEST_FACTOR1(DISABLED_, name, Bilinear, nom, denom, 3) \
912   TEST_FACTOR1(DISABLED_, name, Box, nom, denom, boxdiff)
913 #endif
914 #endif
915 
916 TEST_FACTOR(2, 1, 2, 0)
917 TEST_FACTOR(4, 1, 4, 0)
918 #ifndef DISABLE_SLOW_TESTS
919 TEST_FACTOR(8, 1, 8, 0)
920 #endif
921 TEST_FACTOR(3by4, 3, 4, 1)
922 TEST_FACTOR(3by8, 3, 8, 1)
923 TEST_FACTOR(3, 1, 3, 0)
924 #undef TEST_FACTOR1
925 #undef TEST_FACTOR
926 #undef SX
927 #undef DX
928 
929 #define TEST_SCALETO1(DISABLED_, name, width, height, filter, max_diff)       \
930   TEST_F(LibYUVScaleTest, I420##name##To##width##x##height##_##filter) {      \
931     int diff = I420TestFilter(benchmark_width_, benchmark_height_, width,     \
932                               height, kFilter##filter, benchmark_iterations_, \
933                               disable_cpu_flags_, benchmark_cpu_info_);       \
934     EXPECT_LE(diff, max_diff);                                                \
935   }                                                                           \
936   TEST_F(LibYUVScaleTest, I444##name##To##width##x##height##_##filter) {      \
937     int diff = I444TestFilter(benchmark_width_, benchmark_height_, width,     \
938                               height, kFilter##filter, benchmark_iterations_, \
939                               disable_cpu_flags_, benchmark_cpu_info_);       \
940     EXPECT_LE(diff, max_diff);                                                \
941   }                                                                           \
942   TEST_F(LibYUVScaleTest,                                                     \
943          DISABLED_##I420##name##To##width##x##height##_##filter##_12) {       \
944     int diff = I420TestFilter_12(                                             \
945         benchmark_width_, benchmark_height_, width, height, kFilter##filter,  \
946         benchmark_iterations_, disable_cpu_flags_, benchmark_cpu_info_);      \
947     EXPECT_LE(diff, max_diff);                                                \
948   }                                                                           \
949   TEST_F(LibYUVScaleTest,                                                     \
950          DISABLED_##I444##name##To##width##x##height##_##filter##_12) {       \
951     int diff = I444TestFilter_12(                                             \
952         benchmark_width_, benchmark_height_, width, height, kFilter##filter,  \
953         benchmark_iterations_, disable_cpu_flags_, benchmark_cpu_info_);      \
954     EXPECT_LE(diff, max_diff);                                                \
955   }                                                                           \
956   TEST_F(LibYUVScaleTest,                                                     \
957          DISABLED_##I420##name##To##width##x##height##_##filter##_16) {       \
958     int diff = I420TestFilter_16(                                             \
959         benchmark_width_, benchmark_height_, width, height, kFilter##filter,  \
960         benchmark_iterations_, disable_cpu_flags_, benchmark_cpu_info_);      \
961     EXPECT_LE(diff, max_diff);                                                \
962   }                                                                           \
963   TEST_F(LibYUVScaleTest,                                                     \
964          DISABLED_##I444##name##To##width##x##height##_##filter##_16) {       \
965     int diff = I444TestFilter_16(                                             \
966         benchmark_width_, benchmark_height_, width, height, kFilter##filter,  \
967         benchmark_iterations_, disable_cpu_flags_, benchmark_cpu_info_);      \
968     EXPECT_LE(diff, max_diff);                                                \
969   }                                                                           \
970   TEST_F(LibYUVScaleTest, NV12##name##To##width##x##height##_##filter) {      \
971     int diff = NV12TestFilter(benchmark_width_, benchmark_height_, width,     \
972                               height, kFilter##filter, benchmark_iterations_, \
973                               disable_cpu_flags_, benchmark_cpu_info_);       \
974     EXPECT_LE(diff, max_diff);                                                \
975   }                                                                           \
976   TEST_F(LibYUVScaleTest, I420##name##From##width##x##height##_##filter) {    \
977     int diff = I420TestFilter(width, height, Abs(benchmark_width_),           \
978                               Abs(benchmark_height_), kFilter##filter,        \
979                               benchmark_iterations_, disable_cpu_flags_,      \
980                               benchmark_cpu_info_);                           \
981     EXPECT_LE(diff, max_diff);                                                \
982   }                                                                           \
983   TEST_F(LibYUVScaleTest, I444##name##From##width##x##height##_##filter) {    \
984     int diff = I444TestFilter(width, height, Abs(benchmark_width_),           \
985                               Abs(benchmark_height_), kFilter##filter,        \
986                               benchmark_iterations_, disable_cpu_flags_,      \
987                               benchmark_cpu_info_);                           \
988     EXPECT_LE(diff, max_diff);                                                \
989   }                                                                           \
990   TEST_F(LibYUVScaleTest,                                                     \
991          DISABLED_##I420##name##From##width##x##height##_##filter##_12) {     \
992     int diff = I420TestFilter_12(width, height, Abs(benchmark_width_),        \
993                                  Abs(benchmark_height_), kFilter##filter,     \
994                                  benchmark_iterations_, disable_cpu_flags_,   \
995                                  benchmark_cpu_info_);                        \
996     EXPECT_LE(diff, max_diff);                                                \
997   }                                                                           \
998   TEST_F(LibYUVScaleTest,                                                     \
999          DISABLED_##I444##name##From##width##x##height##_##filter##_12) {     \
1000     int diff = I444TestFilter_12(width, height, Abs(benchmark_width_),        \
1001                                  Abs(benchmark_height_), kFilter##filter,     \
1002                                  benchmark_iterations_, disable_cpu_flags_,   \
1003                                  benchmark_cpu_info_);                        \
1004     EXPECT_LE(diff, max_diff);                                                \
1005   }                                                                           \
1006   TEST_F(LibYUVScaleTest,                                                     \
1007          DISABLED_##I420##name##From##width##x##height##_##filter##_16) {     \
1008     int diff = I420TestFilter_16(width, height, Abs(benchmark_width_),        \
1009                                  Abs(benchmark_height_), kFilter##filter,     \
1010                                  benchmark_iterations_, disable_cpu_flags_,   \
1011                                  benchmark_cpu_info_);                        \
1012     EXPECT_LE(diff, max_diff);                                                \
1013   }                                                                           \
1014   TEST_F(LibYUVScaleTest,                                                     \
1015          DISABLED_##I444##name##From##width##x##height##_##filter##_16) {     \
1016     int diff = I444TestFilter_16(width, height, Abs(benchmark_width_),        \
1017                                  Abs(benchmark_height_), kFilter##filter,     \
1018                                  benchmark_iterations_, disable_cpu_flags_,   \
1019                                  benchmark_cpu_info_);                        \
1020     EXPECT_LE(diff, max_diff);                                                \
1021   }                                                                           \
1022   TEST_F(LibYUVScaleTest, NV12##name##From##width##x##height##_##filter) {    \
1023     int diff = NV12TestFilter(width, height, Abs(benchmark_width_),           \
1024                               Abs(benchmark_height_), kFilter##filter,        \
1025                               benchmark_iterations_, disable_cpu_flags_,      \
1026                               benchmark_cpu_info_);                           \
1027     EXPECT_LE(diff, max_diff);                                                \
1028   }
1029 
1030 #ifndef DISABLE_SLOW_TESTS
1031 // Test scale to a specified size with all 4 filters.
1032 #define TEST_SCALETO(name, width, height)           \
1033   TEST_SCALETO1(, name, width, height, None, 0)     \
1034   TEST_SCALETO1(, name, width, height, Linear, 3)   \
1035   TEST_SCALETO1(, name, width, height, Bilinear, 3) \
1036   TEST_SCALETO1(, name, width, height, Box, 3)
1037 #else
1038 #if defined(ENABLE_FULL_TESTS)
1039 #define TEST_SCALETO(name, width, height)                    \
1040   TEST_SCALETO1(DISABLED_, name, width, height, None, 0)     \
1041   TEST_SCALETO1(DISABLED_, name, width, height, Linear, 3)   \
1042   TEST_SCALETO1(DISABLED_, name, width, height, Bilinear, 3) \
1043   TEST_SCALETO1(DISABLED_, name, width, height, Box, 3)
1044 #else
1045 #define TEST_SCALETO(name, width, height)                    \
1046   TEST_SCALETO1(DISABLED_, name, width, height, Bilinear, 3) \
1047   TEST_SCALETO1(DISABLED_, name, width, height, Box, 3)
1048 #endif
1049 #endif
1050 
1051 TEST_SCALETO(Scale, 1, 1)
1052 TEST_SCALETO(Scale, 569, 480)
1053 TEST_SCALETO(Scale, 640, 360)
1054 #ifndef DISABLE_SLOW_TESTS
1055 TEST_SCALETO(Scale, 256, 144) /* 128x72 * 2 */
1056 TEST_SCALETO(Scale, 320, 240)
1057 TEST_SCALETO(Scale, 1280, 720)
1058 TEST_SCALETO(Scale, 1920, 1080)
1059 #endif  // DISABLE_SLOW_TESTS
1060 #undef TEST_SCALETO1
1061 #undef TEST_SCALETO
1062 
1063 #define TEST_SCALESWAPXY1(DISABLED_, name, filter, max_diff)               \
1064   TEST_F(LibYUVScaleTest, I420##name##SwapXY_##filter) {                   \
1065     int diff = I420TestFilter(benchmark_width_, benchmark_height_,         \
1066                               benchmark_height_, benchmark_width_,         \
1067                               kFilter##filter, benchmark_iterations_,      \
1068                               disable_cpu_flags_, benchmark_cpu_info_);    \
1069     EXPECT_LE(diff, max_diff);                                             \
1070   }                                                                        \
1071   TEST_F(LibYUVScaleTest, I444##name##SwapXY_##filter) {                   \
1072     int diff = I444TestFilter(benchmark_width_, benchmark_height_,         \
1073                               benchmark_height_, benchmark_width_,         \
1074                               kFilter##filter, benchmark_iterations_,      \
1075                               disable_cpu_flags_, benchmark_cpu_info_);    \
1076     EXPECT_LE(diff, max_diff);                                             \
1077   }                                                                        \
1078   TEST_F(LibYUVScaleTest, DISABLED_##I420##name##SwapXY_##filter##_12) {   \
1079     int diff = I420TestFilter_12(benchmark_width_, benchmark_height_,      \
1080                                  benchmark_height_, benchmark_width_,      \
1081                                  kFilter##filter, benchmark_iterations_,   \
1082                                  disable_cpu_flags_, benchmark_cpu_info_); \
1083     EXPECT_LE(diff, max_diff);                                             \
1084   }                                                                        \
1085   TEST_F(LibYUVScaleTest, DISABLED_##I444##name##SwapXY_##filter##_12) {   \
1086     int diff = I444TestFilter_12(benchmark_width_, benchmark_height_,      \
1087                                  benchmark_height_, benchmark_width_,      \
1088                                  kFilter##filter, benchmark_iterations_,   \
1089                                  disable_cpu_flags_, benchmark_cpu_info_); \
1090     EXPECT_LE(diff, max_diff);                                             \
1091   }                                                                        \
1092   TEST_F(LibYUVScaleTest, DISABLED_##I420##name##SwapXY_##filter##_16) {   \
1093     int diff = I420TestFilter_16(benchmark_width_, benchmark_height_,      \
1094                                  benchmark_height_, benchmark_width_,      \
1095                                  kFilter##filter, benchmark_iterations_,   \
1096                                  disable_cpu_flags_, benchmark_cpu_info_); \
1097     EXPECT_LE(diff, max_diff);                                             \
1098   }                                                                        \
1099   TEST_F(LibYUVScaleTest, DISABLED_##I444##name##SwapXY_##filter##_16) {   \
1100     int diff = I444TestFilter_16(benchmark_width_, benchmark_height_,      \
1101                                  benchmark_height_, benchmark_width_,      \
1102                                  kFilter##filter, benchmark_iterations_,   \
1103                                  disable_cpu_flags_, benchmark_cpu_info_); \
1104     EXPECT_LE(diff, max_diff);                                             \
1105   }                                                                        \
1106   TEST_F(LibYUVScaleTest, NV12##name##SwapXY_##filter) {                   \
1107     int diff = NV12TestFilter(benchmark_width_, benchmark_height_,         \
1108                               benchmark_height_, benchmark_width_,         \
1109                               kFilter##filter, benchmark_iterations_,      \
1110                               disable_cpu_flags_, benchmark_cpu_info_);    \
1111     EXPECT_LE(diff, max_diff);                                             \
1112   }
1113 
1114 // Test scale to a specified size with all 4 filters.
1115 #ifndef DISABLE_SLOW_TESTS
1116 TEST_SCALESWAPXY1(, Scale, None, 0)
1117 TEST_SCALESWAPXY1(, Scale, Linear, 3)
1118 TEST_SCALESWAPXY1(, Scale, Bilinear, 3)
1119 TEST_SCALESWAPXY1(, Scale, Box, 3)
1120 #else
1121 #if defined(ENABLE_FULL_TESTS)
1122 TEST_SCALESWAPXY1(DISABLED_, Scale, None, 0)
1123 TEST_SCALESWAPXY1(DISABLED_, Scale, Linear, 3)
1124 TEST_SCALESWAPXY1(DISABLED_, Scale, Bilinear, 3)
1125 TEST_SCALESWAPXY1(DISABLED_, Scale, Box, 3)
1126 #else
1127 TEST_SCALESWAPXY1(DISABLED_, Scale, Bilinear, 3)
1128 TEST_SCALESWAPXY1(DISABLED_, Scale, Box, 3)
1129 #endif
1130 #endif
1131 #undef TEST_SCALESWAPXY1
1132 
1133 }  // namespace libyuv
1134