xref: /aosp_15_r20/external/libyuv/unit_test/rotate_test.cc (revision 4e366538070a3a6c5c163c31b791eab742e1657a)
1 /*
2  *  Copyright 2012 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 
13 #include "../unit_test/unit_test.h"
14 #include "libyuv/cpu_id.h"
15 #include "libyuv/rotate.h"
16 
17 #ifdef ENABLE_ROW_TESTS
18 #include "libyuv/rotate_row.h"
19 #endif
20 
21 namespace libyuv {
22 
23 #define SUBSAMPLE(v, a) ((((v) + (a)-1)) / (a))
24 
I420TestRotate(int src_width,int src_height,int dst_width,int dst_height,libyuv::RotationMode mode,int benchmark_iterations,int disable_cpu_flags,int benchmark_cpu_info)25 static void I420TestRotate(int src_width,
26                            int src_height,
27                            int dst_width,
28                            int dst_height,
29                            libyuv::RotationMode mode,
30                            int benchmark_iterations,
31                            int disable_cpu_flags,
32                            int benchmark_cpu_info) {
33   if (src_width < 1) {
34     src_width = 1;
35   }
36   if (src_height == 0) {
37     src_height = 1;
38   }
39   if (dst_width < 1) {
40     dst_width = 1;
41   }
42   if (dst_height < 1) {
43     dst_height = 1;
44   }
45   int src_i420_y_size = src_width * Abs(src_height);
46   int src_i420_uv_size = ((src_width + 1) / 2) * ((Abs(src_height) + 1) / 2);
47   int src_i420_size = src_i420_y_size + src_i420_uv_size * 2;
48   align_buffer_page_end(src_i420, src_i420_size);
49   for (int i = 0; i < src_i420_size; ++i) {
50     src_i420[i] = fastrand() & 0xff;
51   }
52 
53   int dst_i420_y_size = dst_width * dst_height;
54   int dst_i420_uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2);
55   int dst_i420_size = dst_i420_y_size + dst_i420_uv_size * 2;
56   align_buffer_page_end(dst_i420_c, dst_i420_size);
57   align_buffer_page_end(dst_i420_opt, dst_i420_size);
58   memset(dst_i420_c, 2, dst_i420_size);
59   memset(dst_i420_opt, 3, dst_i420_size);
60 
61   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
62   I420Rotate(src_i420, src_width, src_i420 + src_i420_y_size,
63              (src_width + 1) / 2, src_i420 + src_i420_y_size + src_i420_uv_size,
64              (src_width + 1) / 2, dst_i420_c, dst_width,
65              dst_i420_c + dst_i420_y_size, (dst_width + 1) / 2,
66              dst_i420_c + dst_i420_y_size + dst_i420_uv_size,
67              (dst_width + 1) / 2, src_width, src_height, mode);
68 
69   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
70   for (int i = 0; i < benchmark_iterations; ++i) {
71     I420Rotate(
72         src_i420, src_width, src_i420 + src_i420_y_size, (src_width + 1) / 2,
73         src_i420 + src_i420_y_size + src_i420_uv_size, (src_width + 1) / 2,
74         dst_i420_opt, dst_width, dst_i420_opt + dst_i420_y_size,
75         (dst_width + 1) / 2, dst_i420_opt + dst_i420_y_size + dst_i420_uv_size,
76         (dst_width + 1) / 2, src_width, src_height, mode);
77   }
78 
79   // Rotation should be exact.
80   for (int i = 0; i < dst_i420_size; ++i) {
81     EXPECT_EQ(dst_i420_c[i], dst_i420_opt[i]);
82   }
83 
84   free_aligned_buffer_page_end(dst_i420_c);
85   free_aligned_buffer_page_end(dst_i420_opt);
86   free_aligned_buffer_page_end(src_i420);
87 }
88 
TEST_F(LibYUVRotateTest,I420Rotate0_Opt)89 TEST_F(LibYUVRotateTest, I420Rotate0_Opt) {
90   I420TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
91                  benchmark_height_, kRotate0, benchmark_iterations_,
92                  disable_cpu_flags_, benchmark_cpu_info_);
93 }
94 
TEST_F(LibYUVRotateTest,I420Rotate90_Opt)95 TEST_F(LibYUVRotateTest, I420Rotate90_Opt) {
96   I420TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
97                  benchmark_width_, kRotate90, benchmark_iterations_,
98                  disable_cpu_flags_, benchmark_cpu_info_);
99 }
100 
TEST_F(LibYUVRotateTest,I420Rotate180_Opt)101 TEST_F(LibYUVRotateTest, I420Rotate180_Opt) {
102   I420TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
103                  benchmark_height_, kRotate180, benchmark_iterations_,
104                  disable_cpu_flags_, benchmark_cpu_info_);
105 }
106 
TEST_F(LibYUVRotateTest,I420Rotate270_Opt)107 TEST_F(LibYUVRotateTest, I420Rotate270_Opt) {
108   I420TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
109                  benchmark_width_, kRotate270, benchmark_iterations_,
110                  disable_cpu_flags_, benchmark_cpu_info_);
111 }
112 
113 // TODO(fbarchard): Remove odd width tests.
114 // Odd width tests work but disabled because they use C code and can be
115 // tested by passing an odd width command line or environment variable.
TEST_F(LibYUVRotateTest,DISABLED_I420Rotate0_Odd)116 TEST_F(LibYUVRotateTest, DISABLED_I420Rotate0_Odd) {
117   I420TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
118                  benchmark_width_ + 1, benchmark_height_ + 1, kRotate0,
119                  benchmark_iterations_, disable_cpu_flags_,
120                  benchmark_cpu_info_);
121 }
122 
TEST_F(LibYUVRotateTest,DISABLED_I420Rotate90_Odd)123 TEST_F(LibYUVRotateTest, DISABLED_I420Rotate90_Odd) {
124   I420TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
125                  benchmark_height_ + 1, benchmark_width_ + 1, kRotate90,
126                  benchmark_iterations_, disable_cpu_flags_,
127                  benchmark_cpu_info_);
128 }
129 
TEST_F(LibYUVRotateTest,DISABLED_I420Rotate180_Odd)130 TEST_F(LibYUVRotateTest, DISABLED_I420Rotate180_Odd) {
131   I420TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
132                  benchmark_width_ + 1, benchmark_height_ + 1, kRotate180,
133                  benchmark_iterations_, disable_cpu_flags_,
134                  benchmark_cpu_info_);
135 }
136 
TEST_F(LibYUVRotateTest,DISABLED_I420Rotate270_Odd)137 TEST_F(LibYUVRotateTest, DISABLED_I420Rotate270_Odd) {
138   I420TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
139                  benchmark_height_ + 1, benchmark_width_ + 1, kRotate270,
140                  benchmark_iterations_, disable_cpu_flags_,
141                  benchmark_cpu_info_);
142 }
143 
I422TestRotate(int src_width,int src_height,int dst_width,int dst_height,libyuv::RotationMode mode,int benchmark_iterations,int disable_cpu_flags,int benchmark_cpu_info)144 static void I422TestRotate(int src_width,
145                            int src_height,
146                            int dst_width,
147                            int dst_height,
148                            libyuv::RotationMode mode,
149                            int benchmark_iterations,
150                            int disable_cpu_flags,
151                            int benchmark_cpu_info) {
152   if (src_width < 1) {
153     src_width = 1;
154   }
155   if (src_height == 0) {
156     src_height = 1;
157   }
158   if (dst_width < 1) {
159     dst_width = 1;
160   }
161   if (dst_height < 1) {
162     dst_height = 1;
163   }
164   int src_i422_y_size = src_width * Abs(src_height);
165   int src_i422_uv_size = ((src_width + 1) / 2) * Abs(src_height);
166   int src_i422_size = src_i422_y_size + src_i422_uv_size * 2;
167   align_buffer_page_end(src_i422, src_i422_size);
168   for (int i = 0; i < src_i422_size; ++i) {
169     src_i422[i] = fastrand() & 0xff;
170   }
171 
172   int dst_i422_y_size = dst_width * dst_height;
173   int dst_i422_uv_size = ((dst_width + 1) / 2) * dst_height;
174   int dst_i422_size = dst_i422_y_size + dst_i422_uv_size * 2;
175   align_buffer_page_end(dst_i422_c, dst_i422_size);
176   align_buffer_page_end(dst_i422_opt, dst_i422_size);
177   memset(dst_i422_c, 2, dst_i422_size);
178   memset(dst_i422_opt, 3, dst_i422_size);
179 
180   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
181   I422Rotate(src_i422, src_width, src_i422 + src_i422_y_size,
182              (src_width + 1) / 2, src_i422 + src_i422_y_size + src_i422_uv_size,
183              (src_width + 1) / 2, dst_i422_c, dst_width,
184              dst_i422_c + dst_i422_y_size, (dst_width + 1) / 2,
185              dst_i422_c + dst_i422_y_size + dst_i422_uv_size,
186              (dst_width + 1) / 2, src_width, src_height, mode);
187 
188   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
189   for (int i = 0; i < benchmark_iterations; ++i) {
190     I422Rotate(
191         src_i422, src_width, src_i422 + src_i422_y_size, (src_width + 1) / 2,
192         src_i422 + src_i422_y_size + src_i422_uv_size, (src_width + 1) / 2,
193         dst_i422_opt, dst_width, dst_i422_opt + dst_i422_y_size,
194         (dst_width + 1) / 2, dst_i422_opt + dst_i422_y_size + dst_i422_uv_size,
195         (dst_width + 1) / 2, src_width, src_height, mode);
196   }
197 
198   // Rotation should be exact.
199   for (int i = 0; i < dst_i422_size; ++i) {
200     EXPECT_EQ(dst_i422_c[i], dst_i422_opt[i]);
201   }
202 
203   free_aligned_buffer_page_end(dst_i422_c);
204   free_aligned_buffer_page_end(dst_i422_opt);
205   free_aligned_buffer_page_end(src_i422);
206 }
207 
TEST_F(LibYUVRotateTest,I422Rotate0_Opt)208 TEST_F(LibYUVRotateTest, I422Rotate0_Opt) {
209   I422TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
210                  benchmark_height_, kRotate0, benchmark_iterations_,
211                  disable_cpu_flags_, benchmark_cpu_info_);
212 }
213 
TEST_F(LibYUVRotateTest,I422Rotate90_Opt)214 TEST_F(LibYUVRotateTest, I422Rotate90_Opt) {
215   I422TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
216                  benchmark_width_, kRotate90, benchmark_iterations_,
217                  disable_cpu_flags_, benchmark_cpu_info_);
218 }
219 
TEST_F(LibYUVRotateTest,I422Rotate180_Opt)220 TEST_F(LibYUVRotateTest, I422Rotate180_Opt) {
221   I422TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
222                  benchmark_height_, kRotate180, benchmark_iterations_,
223                  disable_cpu_flags_, benchmark_cpu_info_);
224 }
225 
TEST_F(LibYUVRotateTest,I422Rotate270_Opt)226 TEST_F(LibYUVRotateTest, I422Rotate270_Opt) {
227   I422TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
228                  benchmark_width_, kRotate270, benchmark_iterations_,
229                  disable_cpu_flags_, benchmark_cpu_info_);
230 }
231 
I444TestRotate(int src_width,int src_height,int dst_width,int dst_height,libyuv::RotationMode mode,int benchmark_iterations,int disable_cpu_flags,int benchmark_cpu_info)232 static void I444TestRotate(int src_width,
233                            int src_height,
234                            int dst_width,
235                            int dst_height,
236                            libyuv::RotationMode mode,
237                            int benchmark_iterations,
238                            int disable_cpu_flags,
239                            int benchmark_cpu_info) {
240   if (src_width < 1) {
241     src_width = 1;
242   }
243   if (src_height == 0) {
244     src_height = 1;
245   }
246   if (dst_width < 1) {
247     dst_width = 1;
248   }
249   if (dst_height < 1) {
250     dst_height = 1;
251   }
252   int src_i444_y_size = src_width * Abs(src_height);
253   int src_i444_uv_size = src_width * Abs(src_height);
254   int src_i444_size = src_i444_y_size + src_i444_uv_size * 2;
255   align_buffer_page_end(src_i444, src_i444_size);
256   for (int i = 0; i < src_i444_size; ++i) {
257     src_i444[i] = fastrand() & 0xff;
258   }
259 
260   int dst_i444_y_size = dst_width * dst_height;
261   int dst_i444_uv_size = dst_width * dst_height;
262   int dst_i444_size = dst_i444_y_size + dst_i444_uv_size * 2;
263   align_buffer_page_end(dst_i444_c, dst_i444_size);
264   align_buffer_page_end(dst_i444_opt, dst_i444_size);
265   memset(dst_i444_c, 2, dst_i444_size);
266   memset(dst_i444_opt, 3, dst_i444_size);
267 
268   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
269   I444Rotate(src_i444, src_width, src_i444 + src_i444_y_size, src_width,
270              src_i444 + src_i444_y_size + src_i444_uv_size, src_width,
271              dst_i444_c, dst_width, dst_i444_c + dst_i444_y_size, dst_width,
272              dst_i444_c + dst_i444_y_size + dst_i444_uv_size, dst_width,
273              src_width, src_height, mode);
274 
275   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
276   for (int i = 0; i < benchmark_iterations; ++i) {
277     I444Rotate(src_i444, src_width, src_i444 + src_i444_y_size, src_width,
278                src_i444 + src_i444_y_size + src_i444_uv_size, src_width,
279                dst_i444_opt, dst_width, dst_i444_opt + dst_i444_y_size,
280                dst_width, dst_i444_opt + dst_i444_y_size + dst_i444_uv_size,
281                dst_width, src_width, src_height, mode);
282   }
283 
284   // Rotation should be exact.
285   for (int i = 0; i < dst_i444_size; ++i) {
286     EXPECT_EQ(dst_i444_c[i], dst_i444_opt[i]);
287   }
288 
289   free_aligned_buffer_page_end(dst_i444_c);
290   free_aligned_buffer_page_end(dst_i444_opt);
291   free_aligned_buffer_page_end(src_i444);
292 }
293 
TEST_F(LibYUVRotateTest,I444Rotate0_Opt)294 TEST_F(LibYUVRotateTest, I444Rotate0_Opt) {
295   I444TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
296                  benchmark_height_, kRotate0, benchmark_iterations_,
297                  disable_cpu_flags_, benchmark_cpu_info_);
298 }
299 
TEST_F(LibYUVRotateTest,I444Rotate90_Opt)300 TEST_F(LibYUVRotateTest, I444Rotate90_Opt) {
301   I444TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
302                  benchmark_width_, kRotate90, benchmark_iterations_,
303                  disable_cpu_flags_, benchmark_cpu_info_);
304 }
305 
TEST_F(LibYUVRotateTest,I444Rotate180_Opt)306 TEST_F(LibYUVRotateTest, I444Rotate180_Opt) {
307   I444TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
308                  benchmark_height_, kRotate180, benchmark_iterations_,
309                  disable_cpu_flags_, benchmark_cpu_info_);
310 }
311 
TEST_F(LibYUVRotateTest,I444Rotate270_Opt)312 TEST_F(LibYUVRotateTest, I444Rotate270_Opt) {
313   I444TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
314                  benchmark_width_, kRotate270, benchmark_iterations_,
315                  disable_cpu_flags_, benchmark_cpu_info_);
316 }
317 
318 // TODO(fbarchard): Remove odd width tests.
319 // Odd width tests work but disabled because they use C code and can be
320 // tested by passing an odd width command line or environment variable.
TEST_F(LibYUVRotateTest,DISABLED_I444Rotate0_Odd)321 TEST_F(LibYUVRotateTest, DISABLED_I444Rotate0_Odd) {
322   I444TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
323                  benchmark_width_ + 1, benchmark_height_ + 1, kRotate0,
324                  benchmark_iterations_, disable_cpu_flags_,
325                  benchmark_cpu_info_);
326 }
327 
TEST_F(LibYUVRotateTest,DISABLED_I444Rotate90_Odd)328 TEST_F(LibYUVRotateTest, DISABLED_I444Rotate90_Odd) {
329   I444TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
330                  benchmark_height_ + 1, benchmark_width_ + 1, kRotate90,
331                  benchmark_iterations_, disable_cpu_flags_,
332                  benchmark_cpu_info_);
333 }
334 
TEST_F(LibYUVRotateTest,DISABLED_I444Rotate180_Odd)335 TEST_F(LibYUVRotateTest, DISABLED_I444Rotate180_Odd) {
336   I444TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
337                  benchmark_width_ + 1, benchmark_height_ + 1, kRotate180,
338                  benchmark_iterations_, disable_cpu_flags_,
339                  benchmark_cpu_info_);
340 }
341 
TEST_F(LibYUVRotateTest,DISABLED_I444Rotate270_Odd)342 TEST_F(LibYUVRotateTest, DISABLED_I444Rotate270_Odd) {
343   I444TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
344                  benchmark_height_ + 1, benchmark_width_ + 1, kRotate270,
345                  benchmark_iterations_, disable_cpu_flags_,
346                  benchmark_cpu_info_);
347 }
348 
NV12TestRotate(int src_width,int src_height,int dst_width,int dst_height,libyuv::RotationMode mode,int benchmark_iterations,int disable_cpu_flags,int benchmark_cpu_info)349 static void NV12TestRotate(int src_width,
350                            int src_height,
351                            int dst_width,
352                            int dst_height,
353                            libyuv::RotationMode mode,
354                            int benchmark_iterations,
355                            int disable_cpu_flags,
356                            int benchmark_cpu_info) {
357   if (src_width < 1) {
358     src_width = 1;
359   }
360   if (src_height == 0) {  // allow negative for inversion test.
361     src_height = 1;
362   }
363   if (dst_width < 1) {
364     dst_width = 1;
365   }
366   if (dst_height < 1) {
367     dst_height = 1;
368   }
369   int src_nv12_y_size = src_width * Abs(src_height);
370   int src_nv12_uv_size =
371       ((src_width + 1) / 2) * ((Abs(src_height) + 1) / 2) * 2;
372   int src_nv12_size = src_nv12_y_size + src_nv12_uv_size;
373   align_buffer_page_end(src_nv12, src_nv12_size);
374   for (int i = 0; i < src_nv12_size; ++i) {
375     src_nv12[i] = fastrand() & 0xff;
376   }
377 
378   int dst_i420_y_size = dst_width * dst_height;
379   int dst_i420_uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2);
380   int dst_i420_size = dst_i420_y_size + dst_i420_uv_size * 2;
381   align_buffer_page_end(dst_i420_c, dst_i420_size);
382   align_buffer_page_end(dst_i420_opt, dst_i420_size);
383   memset(dst_i420_c, 2, dst_i420_size);
384   memset(dst_i420_opt, 3, dst_i420_size);
385 
386   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
387   NV12ToI420Rotate(src_nv12, src_width, src_nv12 + src_nv12_y_size,
388                    (src_width + 1) & ~1, dst_i420_c, dst_width,
389                    dst_i420_c + dst_i420_y_size, (dst_width + 1) / 2,
390                    dst_i420_c + dst_i420_y_size + dst_i420_uv_size,
391                    (dst_width + 1) / 2, src_width, src_height, mode);
392 
393   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
394   for (int i = 0; i < benchmark_iterations; ++i) {
395     NV12ToI420Rotate(src_nv12, src_width, src_nv12 + src_nv12_y_size,
396                      (src_width + 1) & ~1, dst_i420_opt, dst_width,
397                      dst_i420_opt + dst_i420_y_size, (dst_width + 1) / 2,
398                      dst_i420_opt + dst_i420_y_size + dst_i420_uv_size,
399                      (dst_width + 1) / 2, src_width, src_height, mode);
400   }
401 
402   // Rotation should be exact.
403   for (int i = 0; i < dst_i420_size; ++i) {
404     EXPECT_EQ(dst_i420_c[i], dst_i420_opt[i]);
405   }
406 
407   free_aligned_buffer_page_end(dst_i420_c);
408   free_aligned_buffer_page_end(dst_i420_opt);
409   free_aligned_buffer_page_end(src_nv12);
410 }
411 
TEST_F(LibYUVRotateTest,NV12Rotate0_Opt)412 TEST_F(LibYUVRotateTest, NV12Rotate0_Opt) {
413   NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
414                  benchmark_height_, kRotate0, benchmark_iterations_,
415                  disable_cpu_flags_, benchmark_cpu_info_);
416 }
417 
TEST_F(LibYUVRotateTest,NV12Rotate90_Opt)418 TEST_F(LibYUVRotateTest, NV12Rotate90_Opt) {
419   NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
420                  benchmark_width_, kRotate90, benchmark_iterations_,
421                  disable_cpu_flags_, benchmark_cpu_info_);
422 }
423 
TEST_F(LibYUVRotateTest,NV12Rotate180_Opt)424 TEST_F(LibYUVRotateTest, NV12Rotate180_Opt) {
425   NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
426                  benchmark_height_, kRotate180, benchmark_iterations_,
427                  disable_cpu_flags_, benchmark_cpu_info_);
428 }
429 
TEST_F(LibYUVRotateTest,NV12Rotate270_Opt)430 TEST_F(LibYUVRotateTest, NV12Rotate270_Opt) {
431   NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
432                  benchmark_width_, kRotate270, benchmark_iterations_,
433                  disable_cpu_flags_, benchmark_cpu_info_);
434 }
435 
TEST_F(LibYUVRotateTest,DISABLED_NV12Rotate0_Odd)436 TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate0_Odd) {
437   NV12TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
438                  benchmark_width_ + 1, benchmark_height_ + 1, kRotate0,
439                  benchmark_iterations_, disable_cpu_flags_,
440                  benchmark_cpu_info_);
441 }
442 
TEST_F(LibYUVRotateTest,DISABLED_NV12Rotate90_Odd)443 TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate90_Odd) {
444   NV12TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
445                  benchmark_height_ + 1, benchmark_width_ + 1, kRotate90,
446                  benchmark_iterations_, disable_cpu_flags_,
447                  benchmark_cpu_info_);
448 }
449 
TEST_F(LibYUVRotateTest,DISABLED_NV12Rotate180_Odd)450 TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate180_Odd) {
451   NV12TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
452                  benchmark_width_ + 1, benchmark_height_ + 1, kRotate180,
453                  benchmark_iterations_, disable_cpu_flags_,
454                  benchmark_cpu_info_);
455 }
456 
TEST_F(LibYUVRotateTest,DISABLED_NV12Rotate270_Odd)457 TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate270_Odd) {
458   NV12TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
459                  benchmark_height_ + 1, benchmark_width_ + 1, kRotate270,
460                  benchmark_iterations_, disable_cpu_flags_,
461                  benchmark_cpu_info_);
462 }
463 
TEST_F(LibYUVRotateTest,NV12Rotate0_Invert)464 TEST_F(LibYUVRotateTest, NV12Rotate0_Invert) {
465   NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_width_,
466                  benchmark_height_, kRotate0, benchmark_iterations_,
467                  disable_cpu_flags_, benchmark_cpu_info_);
468 }
469 
TEST_F(LibYUVRotateTest,NV12Rotate90_Invert)470 TEST_F(LibYUVRotateTest, NV12Rotate90_Invert) {
471   NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_height_,
472                  benchmark_width_, kRotate90, benchmark_iterations_,
473                  disable_cpu_flags_, benchmark_cpu_info_);
474 }
475 
TEST_F(LibYUVRotateTest,NV12Rotate180_Invert)476 TEST_F(LibYUVRotateTest, NV12Rotate180_Invert) {
477   NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_width_,
478                  benchmark_height_, kRotate180, benchmark_iterations_,
479                  disable_cpu_flags_, benchmark_cpu_info_);
480 }
481 
TEST_F(LibYUVRotateTest,NV12Rotate270_Invert)482 TEST_F(LibYUVRotateTest, NV12Rotate270_Invert) {
483   NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_height_,
484                  benchmark_width_, kRotate270, benchmark_iterations_,
485                  disable_cpu_flags_, benchmark_cpu_info_);
486 }
487 
488 // Test Android 420 to I420 Rotate
489 #define TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X,          \
490                         SRC_SUBSAMP_Y, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,      \
491                         W1280, N, NEG, OFF, PN, OFF_U, OFF_V, ROT)            \
492   TEST_F(LibYUVRotateTest,                                                    \
493          SRC_FMT_PLANAR##To##FMT_PLANAR##Rotate##ROT##To##PN##N) {            \
494     const int kWidth = W1280;                                                 \
495     const int kHeight = benchmark_height_;                                    \
496     const int kSizeUV =                                                       \
497         SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); \
498     align_buffer_page_end(src_y, kWidth* kHeight + OFF);                      \
499     align_buffer_page_end(src_uv,                                             \
500                           kSizeUV*((PIXEL_STRIDE == 3) ? 3 : 2) + OFF);       \
501     align_buffer_page_end(dst_y_c, kWidth* kHeight);                          \
502     align_buffer_page_end(dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X) *             \
503                                        SUBSAMPLE(kHeight, SUBSAMP_Y));        \
504     align_buffer_page_end(dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X) *             \
505                                        SUBSAMPLE(kHeight, SUBSAMP_Y));        \
506     align_buffer_page_end(dst_y_opt, kWidth* kHeight);                        \
507     align_buffer_page_end(dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X) *           \
508                                          SUBSAMPLE(kHeight, SUBSAMP_Y));      \
509     align_buffer_page_end(dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X) *           \
510                                          SUBSAMPLE(kHeight, SUBSAMP_Y));      \
511     uint8_t* src_u = src_uv + OFF_U;                                          \
512     uint8_t* src_v = src_uv + (PIXEL_STRIDE == 1 ? kSizeUV : OFF_V);          \
513     int src_stride_uv = SUBSAMPLE(kWidth, SUBSAMP_X) * PIXEL_STRIDE;          \
514     for (int i = 0; i < kHeight; ++i)                                         \
515       for (int j = 0; j < kWidth; ++j)                                        \
516         src_y[i * kWidth + j + OFF] = (fastrand() & 0xff);                    \
517     for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) {             \
518       for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) {            \
519         src_u[(i * src_stride_uv) + j * PIXEL_STRIDE + OFF] =                 \
520             (fastrand() & 0xff);                                              \
521         src_v[(i * src_stride_uv) + j * PIXEL_STRIDE + OFF] =                 \
522             (fastrand() & 0xff);                                              \
523       }                                                                       \
524     }                                                                         \
525     memset(dst_y_c, 1, kWidth* kHeight);                                      \
526     memset(dst_u_c, 2,                                                        \
527            SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y));     \
528     memset(dst_v_c, 3,                                                        \
529            SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y));     \
530     memset(dst_y_opt, 101, kWidth* kHeight);                                  \
531     memset(dst_u_opt, 102,                                                    \
532            SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y));     \
533     memset(dst_v_opt, 103,                                                    \
534            SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y));     \
535     MaskCpuFlags(disable_cpu_flags_);                                         \
536     SRC_FMT_PLANAR##To##FMT_PLANAR##Rotate(                                   \
537         src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X),   \
538         src_v + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), PIXEL_STRIDE, dst_y_c, \
539         kWidth, dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X), dst_v_c,               \
540         SUBSAMPLE(kWidth, SUBSAMP_X), kWidth, NEG kHeight,                    \
541         (libyuv::RotationMode)ROT);                                           \
542     MaskCpuFlags(benchmark_cpu_info_);                                        \
543     for (int i = 0; i < benchmark_iterations_; ++i) {                         \
544       SRC_FMT_PLANAR##To##FMT_PLANAR##Rotate(                                 \
545           src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \
546           src_v + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), PIXEL_STRIDE,        \
547           dst_y_opt, kWidth, dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X),         \
548           dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X), kWidth, NEG kHeight,       \
549           (libyuv::RotationMode)ROT);                                         \
550     }                                                                         \
551     for (int i = 0; i < kHeight; ++i) {                                       \
552       for (int j = 0; j < kWidth; ++j) {                                      \
553         EXPECT_EQ(dst_y_c[i * kWidth + j], dst_y_opt[i * kWidth + j]);        \
554       }                                                                       \
555     }                                                                         \
556     for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                 \
557       for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                \
558         EXPECT_EQ(dst_u_c[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j],              \
559                   dst_u_opt[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j]);           \
560       }                                                                       \
561     }                                                                         \
562     for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                 \
563       for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                \
564         EXPECT_EQ(dst_v_c[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j],              \
565                   dst_v_opt[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j]);           \
566       }                                                                       \
567     }                                                                         \
568     free_aligned_buffer_page_end(dst_y_c);                                    \
569     free_aligned_buffer_page_end(dst_u_c);                                    \
570     free_aligned_buffer_page_end(dst_v_c);                                    \
571     free_aligned_buffer_page_end(dst_y_opt);                                  \
572     free_aligned_buffer_page_end(dst_u_opt);                                  \
573     free_aligned_buffer_page_end(dst_v_opt);                                  \
574     free_aligned_buffer_page_end(src_y);                                      \
575     free_aligned_buffer_page_end(src_uv);                                     \
576   }
577 
578 #define TESTAPLANARTOP(SRC_FMT_PLANAR, PN, PIXEL_STRIDE, OFF_U, OFF_V,         \
579                        SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, SUBSAMP_X,    \
580                        SUBSAMP_Y)                                              \
581   TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,  \
582                   FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_ + 1,      \
583                   _Any, +, 0, PN, OFF_U, OFF_V, 0)                             \
584   TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,  \
585                   FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_,          \
586                   _Unaligned, +, 2, PN, OFF_U, OFF_V, 0)                       \
587   TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,  \
588                   FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Invert, \
589                   -, 0, PN, OFF_U, OFF_V, 0)                                   \
590   TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,  \
591                   FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Opt, +, \
592                   0, PN, OFF_U, OFF_V, 0)                                      \
593   TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,  \
594                   FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Opt, +, \
595                   0, PN, OFF_U, OFF_V, 180)
596 
597 TESTAPLANARTOP(Android420, I420, 1, 0, 0, 2, 2, I420, 2, 2)
598 TESTAPLANARTOP(Android420, NV12, 2, 0, 1, 2, 2, I420, 2, 2)
599 TESTAPLANARTOP(Android420, NV21, 2, 1, 0, 2, 2, I420, 2, 2)
600 #undef TESTAPLANARTOP
601 #undef TESTAPLANARTOPI
602 
I010TestRotate(int src_width,int src_height,int dst_width,int dst_height,libyuv::RotationMode mode,int benchmark_iterations,int disable_cpu_flags,int benchmark_cpu_info)603 static void I010TestRotate(int src_width,
604                            int src_height,
605                            int dst_width,
606                            int dst_height,
607                            libyuv::RotationMode mode,
608                            int benchmark_iterations,
609                            int disable_cpu_flags,
610                            int benchmark_cpu_info) {
611   if (src_width < 1) {
612     src_width = 1;
613   }
614   if (src_height == 0) {
615     src_height = 1;
616   }
617   if (dst_width < 1) {
618     dst_width = 1;
619   }
620   if (dst_height < 1) {
621     dst_height = 1;
622   }
623   int src_i010_y_size = src_width * Abs(src_height);
624   int src_i010_uv_size = ((src_width + 1) / 2) * ((Abs(src_height) + 1) / 2);
625   int src_i010_size = src_i010_y_size + src_i010_uv_size * 2;
626   align_buffer_page_end_16(src_i010, src_i010_size);
627   for (int i = 0; i < src_i010_size; ++i) {
628     src_i010[i] = fastrand() & 0x3ff;
629   }
630 
631   int dst_i010_y_size = dst_width * dst_height;
632   int dst_i010_uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2);
633   int dst_i010_size = dst_i010_y_size + dst_i010_uv_size * 2;
634   align_buffer_page_end_16(dst_i010_c, dst_i010_size);
635   align_buffer_page_end_16(dst_i010_opt, dst_i010_size);
636   memset(dst_i010_c, 2, dst_i010_size * 2);
637   memset(dst_i010_opt, 3, dst_i010_size * 2);
638 
639   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
640   I010Rotate(src_i010, src_width, src_i010 + src_i010_y_size,
641              (src_width + 1) / 2, src_i010 + src_i010_y_size + src_i010_uv_size,
642              (src_width + 1) / 2, dst_i010_c, dst_width,
643              dst_i010_c + dst_i010_y_size, (dst_width + 1) / 2,
644              dst_i010_c + dst_i010_y_size + dst_i010_uv_size,
645              (dst_width + 1) / 2, src_width, src_height, mode);
646 
647   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
648   for (int i = 0; i < benchmark_iterations; ++i) {
649     I010Rotate(
650         src_i010, src_width, src_i010 + src_i010_y_size, (src_width + 1) / 2,
651         src_i010 + src_i010_y_size + src_i010_uv_size, (src_width + 1) / 2,
652         dst_i010_opt, dst_width, dst_i010_opt + dst_i010_y_size,
653         (dst_width + 1) / 2, dst_i010_opt + dst_i010_y_size + dst_i010_uv_size,
654         (dst_width + 1) / 2, src_width, src_height, mode);
655   }
656 
657   // Rotation should be exact.
658   for (int i = 0; i < dst_i010_size; ++i) {
659     EXPECT_EQ(dst_i010_c[i], dst_i010_opt[i]);
660   }
661 
662   free_aligned_buffer_page_end_16(dst_i010_c);
663   free_aligned_buffer_page_end_16(dst_i010_opt);
664   free_aligned_buffer_page_end_16(src_i010);
665 }
666 
TEST_F(LibYUVRotateTest,I010Rotate0_Opt)667 TEST_F(LibYUVRotateTest, I010Rotate0_Opt) {
668   I010TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
669                  benchmark_height_, kRotate0, benchmark_iterations_,
670                  disable_cpu_flags_, benchmark_cpu_info_);
671 }
672 
TEST_F(LibYUVRotateTest,I010Rotate90_Opt)673 TEST_F(LibYUVRotateTest, I010Rotate90_Opt) {
674   I010TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
675                  benchmark_width_, kRotate90, benchmark_iterations_,
676                  disable_cpu_flags_, benchmark_cpu_info_);
677 }
678 
TEST_F(LibYUVRotateTest,I010Rotate180_Opt)679 TEST_F(LibYUVRotateTest, I010Rotate180_Opt) {
680   I010TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
681                  benchmark_height_, kRotate180, benchmark_iterations_,
682                  disable_cpu_flags_, benchmark_cpu_info_);
683 }
684 
TEST_F(LibYUVRotateTest,I010Rotate270_Opt)685 TEST_F(LibYUVRotateTest, I010Rotate270_Opt) {
686   I010TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
687                  benchmark_width_, kRotate270, benchmark_iterations_,
688                  disable_cpu_flags_, benchmark_cpu_info_);
689 }
690 
I210TestRotate(int src_width,int src_height,int dst_width,int dst_height,libyuv::RotationMode mode,int benchmark_iterations,int disable_cpu_flags,int benchmark_cpu_info)691 static void I210TestRotate(int src_width,
692                            int src_height,
693                            int dst_width,
694                            int dst_height,
695                            libyuv::RotationMode mode,
696                            int benchmark_iterations,
697                            int disable_cpu_flags,
698                            int benchmark_cpu_info) {
699   if (src_width < 1) {
700     src_width = 1;
701   }
702   if (src_height == 0) {
703     src_height = 1;
704   }
705   if (dst_width < 1) {
706     dst_width = 1;
707   }
708   if (dst_height < 1) {
709     dst_height = 1;
710   }
711   int src_i210_y_size = src_width * Abs(src_height);
712   int src_i210_uv_size = ((src_width + 1) / 2) * Abs(src_height);
713   int src_i210_size = src_i210_y_size + src_i210_uv_size * 2;
714   align_buffer_page_end_16(src_i210, src_i210_size);
715   for (int i = 0; i < src_i210_size; ++i) {
716     src_i210[i] = fastrand() & 0x3ff;
717   }
718 
719   int dst_i210_y_size = dst_width * dst_height;
720   int dst_i210_uv_size = ((dst_width + 1) / 2) * dst_height;
721   int dst_i210_size = dst_i210_y_size + dst_i210_uv_size * 2;
722   align_buffer_page_end_16(dst_i210_c, dst_i210_size);
723   align_buffer_page_end_16(dst_i210_opt, dst_i210_size);
724   memset(dst_i210_c, 2, dst_i210_size * 2);
725   memset(dst_i210_opt, 3, dst_i210_size * 2);
726 
727   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
728   I210Rotate(src_i210, src_width, src_i210 + src_i210_y_size,
729              (src_width + 1) / 2, src_i210 + src_i210_y_size + src_i210_uv_size,
730              (src_width + 1) / 2, dst_i210_c, dst_width,
731              dst_i210_c + dst_i210_y_size, (dst_width + 1) / 2,
732              dst_i210_c + dst_i210_y_size + dst_i210_uv_size,
733              (dst_width + 1) / 2, src_width, src_height, mode);
734 
735   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
736   for (int i = 0; i < benchmark_iterations; ++i) {
737     I210Rotate(
738         src_i210, src_width, src_i210 + src_i210_y_size, (src_width + 1) / 2,
739         src_i210 + src_i210_y_size + src_i210_uv_size, (src_width + 1) / 2,
740         dst_i210_opt, dst_width, dst_i210_opt + dst_i210_y_size,
741         (dst_width + 1) / 2, dst_i210_opt + dst_i210_y_size + dst_i210_uv_size,
742         (dst_width + 1) / 2, src_width, src_height, mode);
743   }
744 
745   // Rotation should be exact.
746   for (int i = 0; i < dst_i210_size; ++i) {
747     EXPECT_EQ(dst_i210_c[i], dst_i210_opt[i]);
748   }
749 
750   free_aligned_buffer_page_end_16(dst_i210_c);
751   free_aligned_buffer_page_end_16(dst_i210_opt);
752   free_aligned_buffer_page_end_16(src_i210);
753 }
754 
TEST_F(LibYUVRotateTest,I210Rotate0_Opt)755 TEST_F(LibYUVRotateTest, I210Rotate0_Opt) {
756   I210TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
757                  benchmark_height_, kRotate0, benchmark_iterations_,
758                  disable_cpu_flags_, benchmark_cpu_info_);
759 }
760 
TEST_F(LibYUVRotateTest,I210Rotate90_Opt)761 TEST_F(LibYUVRotateTest, I210Rotate90_Opt) {
762   I210TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
763                  benchmark_width_, kRotate90, benchmark_iterations_,
764                  disable_cpu_flags_, benchmark_cpu_info_);
765 }
766 
TEST_F(LibYUVRotateTest,I210Rotate180_Opt)767 TEST_F(LibYUVRotateTest, I210Rotate180_Opt) {
768   I210TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
769                  benchmark_height_, kRotate180, benchmark_iterations_,
770                  disable_cpu_flags_, benchmark_cpu_info_);
771 }
772 
TEST_F(LibYUVRotateTest,I210Rotate270_Opt)773 TEST_F(LibYUVRotateTest, I210Rotate270_Opt) {
774   I210TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
775                  benchmark_width_, kRotate270, benchmark_iterations_,
776                  disable_cpu_flags_, benchmark_cpu_info_);
777 }
778 
I410TestRotate(int src_width,int src_height,int dst_width,int dst_height,libyuv::RotationMode mode,int benchmark_iterations,int disable_cpu_flags,int benchmark_cpu_info)779 static void I410TestRotate(int src_width,
780                            int src_height,
781                            int dst_width,
782                            int dst_height,
783                            libyuv::RotationMode mode,
784                            int benchmark_iterations,
785                            int disable_cpu_flags,
786                            int benchmark_cpu_info) {
787   if (src_width < 1) {
788     src_width = 1;
789   }
790   if (src_height == 0) {
791     src_height = 1;
792   }
793   if (dst_width < 1) {
794     dst_width = 1;
795   }
796   if (dst_height < 1) {
797     dst_height = 1;
798   }
799   int src_i410_y_size = src_width * Abs(src_height);
800   int src_i410_uv_size = src_width * Abs(src_height);
801   int src_i410_size = src_i410_y_size + src_i410_uv_size * 2;
802   align_buffer_page_end_16(src_i410, src_i410_size);
803   for (int i = 0; i < src_i410_size; ++i) {
804     src_i410[i] = fastrand() & 0x3ff;
805   }
806 
807   int dst_i410_y_size = dst_width * dst_height;
808   int dst_i410_uv_size = dst_width * dst_height;
809   int dst_i410_size = dst_i410_y_size + dst_i410_uv_size * 2;
810   align_buffer_page_end_16(dst_i410_c, dst_i410_size);
811   align_buffer_page_end_16(dst_i410_opt, dst_i410_size);
812   memset(dst_i410_c, 2, dst_i410_size * 2);
813   memset(dst_i410_opt, 3, dst_i410_size * 2);
814 
815   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
816   I410Rotate(src_i410, src_width, src_i410 + src_i410_y_size, src_width,
817              src_i410 + src_i410_y_size + src_i410_uv_size, src_width,
818              dst_i410_c, dst_width, dst_i410_c + dst_i410_y_size, dst_width,
819              dst_i410_c + dst_i410_y_size + dst_i410_uv_size, dst_width,
820              src_width, src_height, mode);
821 
822   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
823   for (int i = 0; i < benchmark_iterations; ++i) {
824     I410Rotate(src_i410, src_width, src_i410 + src_i410_y_size, src_width,
825                src_i410 + src_i410_y_size + src_i410_uv_size, src_width,
826                dst_i410_opt, dst_width, dst_i410_opt + dst_i410_y_size,
827                dst_width, dst_i410_opt + dst_i410_y_size + dst_i410_uv_size,
828                dst_width, src_width, src_height, mode);
829   }
830 
831   // Rotation should be exact.
832   for (int i = 0; i < dst_i410_size; ++i) {
833     EXPECT_EQ(dst_i410_c[i], dst_i410_opt[i]);
834   }
835 
836   free_aligned_buffer_page_end_16(dst_i410_c);
837   free_aligned_buffer_page_end_16(dst_i410_opt);
838   free_aligned_buffer_page_end_16(src_i410);
839 }
840 
TEST_F(LibYUVRotateTest,I410Rotate0_Opt)841 TEST_F(LibYUVRotateTest, I410Rotate0_Opt) {
842   I410TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
843                  benchmark_height_, kRotate0, benchmark_iterations_,
844                  disable_cpu_flags_, benchmark_cpu_info_);
845 }
846 
TEST_F(LibYUVRotateTest,I410Rotate90_Opt)847 TEST_F(LibYUVRotateTest, I410Rotate90_Opt) {
848   I410TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
849                  benchmark_width_, kRotate90, benchmark_iterations_,
850                  disable_cpu_flags_, benchmark_cpu_info_);
851 }
852 
TEST_F(LibYUVRotateTest,I410Rotate180_Opt)853 TEST_F(LibYUVRotateTest, I410Rotate180_Opt) {
854   I410TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
855                  benchmark_height_, kRotate180, benchmark_iterations_,
856                  disable_cpu_flags_, benchmark_cpu_info_);
857 }
858 
TEST_F(LibYUVRotateTest,I410Rotate270_Opt)859 TEST_F(LibYUVRotateTest, I410Rotate270_Opt) {
860   I410TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
861                  benchmark_width_, kRotate270, benchmark_iterations_,
862                  disable_cpu_flags_, benchmark_cpu_info_);
863 }
864 
865 #if defined(ENABLE_ROW_TESTS)
866 
TEST_F(LibYUVRotateTest,Transpose4x4_Test)867 TEST_F(LibYUVRotateTest, Transpose4x4_Test) {
868   // dst width and height
869   const int width = 4;
870   const int height = 4;
871   int src_pixels[4][4];
872   int dst_pixels_c[4][4];
873   int dst_pixels_opt[4][4];
874 
875   for (int i = 0; i < 4; ++i) {
876     for (int j = 0; j < 4; ++j) {
877       src_pixels[i][j] = i * 10 + j;
878     }
879   }
880   memset(dst_pixels_c, 1, width * height * 4);
881   memset(dst_pixels_opt, 2, width * height * 4);
882 
883   Transpose4x4_32_C((const uint8_t*)src_pixels, height * 4,
884                     (uint8_t*)dst_pixels_c, width * 4, width);
885 
886   const int benchmark_iterations =
887       (benchmark_iterations_ * benchmark_width_ * benchmark_height_ + 15) /
888       (4 * 4);
889   for (int i = 0; i < benchmark_iterations; ++i) {
890 #if defined(HAS_TRANSPOSE4X4_32_NEON)
891     if (TestCpuFlag(kCpuHasNEON)) {
892       Transpose4x4_32_NEON((const uint8_t*)src_pixels, height * 4,
893                            (uint8_t*)dst_pixels_opt, width * 4, width);
894     } else
895 #elif defined(HAS_TRANSPOSE4X4_32_SSE2)
896     if (TestCpuFlag(kCpuHasSSE2)) {
897       Transpose4x4_32_SSE2((const uint8_t*)src_pixels, height * 4,
898                            (uint8_t*)dst_pixels_opt, width * 4, width);
899     } else
900 #endif
901     {
902       Transpose4x4_32_C((const uint8_t*)src_pixels, height * 4,
903                         (uint8_t*)dst_pixels_opt, width * 4, width);
904     }
905   }
906 
907   for (int i = 0; i < 4; ++i) {
908     for (int j = 0; j < 4; ++j) {
909       EXPECT_EQ(dst_pixels_c[i][j], src_pixels[j][i]);
910       EXPECT_EQ(dst_pixels_c[i][j], dst_pixels_opt[i][j]);
911     }
912   }
913 }
914 
TEST_F(LibYUVRotateTest,Transpose4x4_Opt)915 TEST_F(LibYUVRotateTest, Transpose4x4_Opt) {
916   // dst width and height
917   const int width = ((benchmark_width_ * benchmark_height_ + 3) / 4 + 3) & ~3;
918   const int height = 4;
919   align_buffer_page_end(src_pixels, height * width * 4);
920   align_buffer_page_end(dst_pixels_c, width * height * 4);
921   align_buffer_page_end(dst_pixels_opt, width * height * 4);
922 
923   MemRandomize(src_pixels, height * width * 4);
924   memset(dst_pixels_c, 1, width * height * 4);
925   memset(dst_pixels_opt, 2, width * height * 4);
926 
927   Transpose4x4_32_C((const uint8_t*)src_pixels, height * 4,
928                     (uint8_t*)dst_pixels_c, width * 4, width);
929 
930   for (int i = 0; i < benchmark_iterations_; ++i) {
931 #if defined(HAS_TRANSPOSE4X4_32_NEON)
932     if (TestCpuFlag(kCpuHasNEON)) {
933       Transpose4x4_32_NEON((const uint8_t*)src_pixels, height * 4,
934                            (uint8_t*)dst_pixels_opt, width * 4, width);
935     } else
936 #elif defined(HAS_TRANSPOSE4X4_32_AVX2)
937     if (TestCpuFlag(kCpuHasAVX2)) {
938       Transpose4x4_32_AVX2((const uint8_t*)src_pixels, height * 4,
939                            (uint8_t*)dst_pixels_opt, width * 4, width);
940     } else if (TestCpuFlag(kCpuHasSSE2)) {
941       Transpose4x4_32_SSE2((const uint8_t*)src_pixels, height * 4,
942                            (uint8_t*)dst_pixels_opt, width * 4, width);
943     } else
944 #endif
945     {
946       Transpose4x4_32_C((const uint8_t*)src_pixels, height * 4,
947                         (uint8_t*)dst_pixels_opt, width * 4, width);
948     }
949   }
950 
951   for (int i = 0; i < width * height; ++i) {
952     EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]);
953   }
954 
955   free_aligned_buffer_page_end(src_pixels);
956   free_aligned_buffer_page_end(dst_pixels_c);
957   free_aligned_buffer_page_end(dst_pixels_opt);
958 }
959 
960 #endif  // ENABLE_ROW_TESTS
961 
962 }  // namespace libyuv
963