• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 namespace libyuv {
18 
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)19 static void I420TestRotate(int src_width,
20                            int src_height,
21                            int dst_width,
22                            int dst_height,
23                            libyuv::RotationMode mode,
24                            int benchmark_iterations,
25                            int disable_cpu_flags,
26                            int benchmark_cpu_info) {
27   if (src_width < 1) {
28     src_width = 1;
29   }
30   if (src_height == 0) {
31     src_height = 1;
32   }
33   if (dst_width < 1) {
34     dst_width = 1;
35   }
36   if (dst_height < 1) {
37     dst_height = 1;
38   }
39   int src_i420_y_size = src_width * Abs(src_height);
40   int src_i420_uv_size = ((src_width + 1) / 2) * ((Abs(src_height) + 1) / 2);
41   int src_i420_size = src_i420_y_size + src_i420_uv_size * 2;
42   align_buffer_page_end(src_i420, src_i420_size);
43   for (int i = 0; i < src_i420_size; ++i) {
44     src_i420[i] = fastrand() & 0xff;
45   }
46 
47   int dst_i420_y_size = dst_width * dst_height;
48   int dst_i420_uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2);
49   int dst_i420_size = dst_i420_y_size + dst_i420_uv_size * 2;
50   align_buffer_page_end(dst_i420_c, dst_i420_size);
51   align_buffer_page_end(dst_i420_opt, dst_i420_size);
52   memset(dst_i420_c, 2, dst_i420_size);
53   memset(dst_i420_opt, 3, dst_i420_size);
54 
55   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
56   I420Rotate(src_i420, src_width, src_i420 + src_i420_y_size,
57              (src_width + 1) / 2, src_i420 + src_i420_y_size + src_i420_uv_size,
58              (src_width + 1) / 2, dst_i420_c, dst_width,
59              dst_i420_c + dst_i420_y_size, (dst_width + 1) / 2,
60              dst_i420_c + dst_i420_y_size + dst_i420_uv_size,
61              (dst_width + 1) / 2, src_width, src_height, mode);
62 
63   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
64   for (int i = 0; i < benchmark_iterations; ++i) {
65     I420Rotate(
66         src_i420, src_width, src_i420 + src_i420_y_size, (src_width + 1) / 2,
67         src_i420 + src_i420_y_size + src_i420_uv_size, (src_width + 1) / 2,
68         dst_i420_opt, dst_width, dst_i420_opt + dst_i420_y_size,
69         (dst_width + 1) / 2, dst_i420_opt + dst_i420_y_size + dst_i420_uv_size,
70         (dst_width + 1) / 2, src_width, src_height, mode);
71   }
72 
73   // Rotation should be exact.
74   for (int i = 0; i < dst_i420_size; ++i) {
75     EXPECT_EQ(dst_i420_c[i], dst_i420_opt[i]);
76   }
77 
78   free_aligned_buffer_page_end(dst_i420_c);
79   free_aligned_buffer_page_end(dst_i420_opt);
80   free_aligned_buffer_page_end(src_i420);
81 }
82 
TEST_F(LibYUVRotateTest,I420Rotate0_Opt)83 TEST_F(LibYUVRotateTest, I420Rotate0_Opt) {
84   I420TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
85                  benchmark_height_, kRotate0, benchmark_iterations_,
86                  disable_cpu_flags_, benchmark_cpu_info_);
87 }
88 
TEST_F(LibYUVRotateTest,I420Rotate90_Opt)89 TEST_F(LibYUVRotateTest, I420Rotate90_Opt) {
90   I420TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
91                  benchmark_width_, kRotate90, benchmark_iterations_,
92                  disable_cpu_flags_, benchmark_cpu_info_);
93 }
94 
TEST_F(LibYUVRotateTest,I420Rotate180_Opt)95 TEST_F(LibYUVRotateTest, I420Rotate180_Opt) {
96   I420TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
97                  benchmark_height_, kRotate180, benchmark_iterations_,
98                  disable_cpu_flags_, benchmark_cpu_info_);
99 }
100 
TEST_F(LibYUVRotateTest,I420Rotate270_Opt)101 TEST_F(LibYUVRotateTest, I420Rotate270_Opt) {
102   I420TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
103                  benchmark_width_, kRotate270, benchmark_iterations_,
104                  disable_cpu_flags_, benchmark_cpu_info_);
105 }
106 
107 // TODO(fbarchard): Remove odd width tests.
108 // Odd width tests work but disabled because they use C code and can be
109 // tested by passing an odd width command line or environment variable.
TEST_F(LibYUVRotateTest,DISABLED_I420Rotate0_Odd)110 TEST_F(LibYUVRotateTest, DISABLED_I420Rotate0_Odd) {
111   I420TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
112                  benchmark_width_ - 3, benchmark_height_ - 1, kRotate0,
113                  benchmark_iterations_, disable_cpu_flags_,
114                  benchmark_cpu_info_);
115 }
116 
TEST_F(LibYUVRotateTest,DISABLED_I420Rotate90_Odd)117 TEST_F(LibYUVRotateTest, DISABLED_I420Rotate90_Odd) {
118   I420TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
119                  benchmark_height_ - 1, benchmark_width_ - 3, kRotate90,
120                  benchmark_iterations_, disable_cpu_flags_,
121                  benchmark_cpu_info_);
122 }
123 
TEST_F(LibYUVRotateTest,DISABLED_I420Rotate180_Odd)124 TEST_F(LibYUVRotateTest, DISABLED_I420Rotate180_Odd) {
125   I420TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
126                  benchmark_width_ - 3, benchmark_height_ - 1, kRotate180,
127                  benchmark_iterations_, disable_cpu_flags_,
128                  benchmark_cpu_info_);
129 }
130 
TEST_F(LibYUVRotateTest,DISABLED_I420Rotate270_Odd)131 TEST_F(LibYUVRotateTest, DISABLED_I420Rotate270_Odd) {
132   I420TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
133                  benchmark_height_ - 1, benchmark_width_ - 3, kRotate270,
134                  benchmark_iterations_, disable_cpu_flags_,
135                  benchmark_cpu_info_);
136 }
137 
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)138 static void I444TestRotate(int src_width,
139                            int src_height,
140                            int dst_width,
141                            int dst_height,
142                            libyuv::RotationMode mode,
143                            int benchmark_iterations,
144                            int disable_cpu_flags,
145                            int benchmark_cpu_info) {
146   if (src_width < 1) {
147     src_width = 1;
148   }
149   if (src_height == 0) {
150     src_height = 1;
151   }
152   if (dst_width < 1) {
153     dst_width = 1;
154   }
155   if (dst_height < 1) {
156     dst_height = 1;
157   }
158   int src_i444_y_size = src_width * Abs(src_height);
159   int src_i444_uv_size = src_width * Abs(src_height);
160   int src_i444_size = src_i444_y_size + src_i444_uv_size * 2;
161   align_buffer_page_end(src_i444, src_i444_size);
162   for (int i = 0; i < src_i444_size; ++i) {
163     src_i444[i] = fastrand() & 0xff;
164   }
165 
166   int dst_i444_y_size = dst_width * dst_height;
167   int dst_i444_uv_size = dst_width * dst_height;
168   int dst_i444_size = dst_i444_y_size + dst_i444_uv_size * 2;
169   align_buffer_page_end(dst_i444_c, dst_i444_size);
170   align_buffer_page_end(dst_i444_opt, dst_i444_size);
171   memset(dst_i444_c, 2, dst_i444_size);
172   memset(dst_i444_opt, 3, dst_i444_size);
173 
174   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
175   I444Rotate(src_i444, src_width, src_i444 + src_i444_y_size, src_width,
176              src_i444 + src_i444_y_size + src_i444_uv_size, src_width,
177              dst_i444_c, dst_width, dst_i444_c + dst_i444_y_size, dst_width,
178              dst_i444_c + dst_i444_y_size + dst_i444_uv_size, dst_width,
179              src_width, src_height, mode);
180 
181   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
182   for (int i = 0; i < benchmark_iterations; ++i) {
183     I444Rotate(src_i444, src_width, src_i444 + src_i444_y_size, src_width,
184                src_i444 + src_i444_y_size + src_i444_uv_size, src_width,
185                dst_i444_opt, dst_width, dst_i444_opt + dst_i444_y_size,
186                dst_width, dst_i444_opt + dst_i444_y_size + dst_i444_uv_size,
187                dst_width, src_width, src_height, mode);
188   }
189 
190   // Rotation should be exact.
191   for (int i = 0; i < dst_i444_size; ++i) {
192     EXPECT_EQ(dst_i444_c[i], dst_i444_opt[i]);
193   }
194 
195   free_aligned_buffer_page_end(dst_i444_c);
196   free_aligned_buffer_page_end(dst_i444_opt);
197   free_aligned_buffer_page_end(src_i444);
198 }
199 
TEST_F(LibYUVRotateTest,I444Rotate0_Opt)200 TEST_F(LibYUVRotateTest, I444Rotate0_Opt) {
201   I444TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
202                  benchmark_height_, kRotate0, benchmark_iterations_,
203                  disable_cpu_flags_, benchmark_cpu_info_);
204 }
205 
TEST_F(LibYUVRotateTest,I444Rotate90_Opt)206 TEST_F(LibYUVRotateTest, I444Rotate90_Opt) {
207   I444TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
208                  benchmark_width_, kRotate90, benchmark_iterations_,
209                  disable_cpu_flags_, benchmark_cpu_info_);
210 }
211 
TEST_F(LibYUVRotateTest,I444Rotate180_Opt)212 TEST_F(LibYUVRotateTest, I444Rotate180_Opt) {
213   I444TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
214                  benchmark_height_, kRotate180, benchmark_iterations_,
215                  disable_cpu_flags_, benchmark_cpu_info_);
216 }
217 
TEST_F(LibYUVRotateTest,I444Rotate270_Opt)218 TEST_F(LibYUVRotateTest, I444Rotate270_Opt) {
219   I444TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
220                  benchmark_width_, kRotate270, benchmark_iterations_,
221                  disable_cpu_flags_, benchmark_cpu_info_);
222 }
223 
224 // TODO(fbarchard): Remove odd width tests.
225 // Odd width tests work but disabled because they use C code and can be
226 // tested by passing an odd width command line or environment variable.
TEST_F(LibYUVRotateTest,DISABLED_I444Rotate0_Odd)227 TEST_F(LibYUVRotateTest, DISABLED_I444Rotate0_Odd) {
228   I444TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
229                  benchmark_width_ - 3, benchmark_height_ - 1, kRotate0,
230                  benchmark_iterations_, disable_cpu_flags_,
231                  benchmark_cpu_info_);
232 }
233 
TEST_F(LibYUVRotateTest,DISABLED_I444Rotate90_Odd)234 TEST_F(LibYUVRotateTest, DISABLED_I444Rotate90_Odd) {
235   I444TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
236                  benchmark_height_ - 1, benchmark_width_ - 3, kRotate90,
237                  benchmark_iterations_, disable_cpu_flags_,
238                  benchmark_cpu_info_);
239 }
240 
TEST_F(LibYUVRotateTest,DISABLED_I444Rotate180_Odd)241 TEST_F(LibYUVRotateTest, DISABLED_I444Rotate180_Odd) {
242   I444TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
243                  benchmark_width_ - 3, benchmark_height_ - 1, kRotate180,
244                  benchmark_iterations_, disable_cpu_flags_,
245                  benchmark_cpu_info_);
246 }
247 
TEST_F(LibYUVRotateTest,DISABLED_I444Rotate270_Odd)248 TEST_F(LibYUVRotateTest, DISABLED_I444Rotate270_Odd) {
249   I444TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
250                  benchmark_height_ - 1, benchmark_width_ - 3, kRotate270,
251                  benchmark_iterations_, disable_cpu_flags_,
252                  benchmark_cpu_info_);
253 }
254 
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)255 static void NV12TestRotate(int src_width,
256                            int src_height,
257                            int dst_width,
258                            int dst_height,
259                            libyuv::RotationMode mode,
260                            int benchmark_iterations,
261                            int disable_cpu_flags,
262                            int benchmark_cpu_info) {
263   if (src_width < 1) {
264     src_width = 1;
265   }
266   if (src_height == 0) {  // allow negative for inversion test.
267     src_height = 1;
268   }
269   if (dst_width < 1) {
270     dst_width = 1;
271   }
272   if (dst_height < 1) {
273     dst_height = 1;
274   }
275   int src_nv12_y_size = src_width * Abs(src_height);
276   int src_nv12_uv_size =
277       ((src_width + 1) / 2) * ((Abs(src_height) + 1) / 2) * 2;
278   int src_nv12_size = src_nv12_y_size + src_nv12_uv_size;
279   align_buffer_page_end(src_nv12, src_nv12_size);
280   for (int i = 0; i < src_nv12_size; ++i) {
281     src_nv12[i] = fastrand() & 0xff;
282   }
283 
284   int dst_i420_y_size = dst_width * dst_height;
285   int dst_i420_uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2);
286   int dst_i420_size = dst_i420_y_size + dst_i420_uv_size * 2;
287   align_buffer_page_end(dst_i420_c, dst_i420_size);
288   align_buffer_page_end(dst_i420_opt, dst_i420_size);
289   memset(dst_i420_c, 2, dst_i420_size);
290   memset(dst_i420_opt, 3, dst_i420_size);
291 
292   MaskCpuFlags(disable_cpu_flags);  // Disable all CPU optimization.
293   NV12ToI420Rotate(src_nv12, src_width, src_nv12 + src_nv12_y_size,
294                    (src_width + 1) & ~1, dst_i420_c, dst_width,
295                    dst_i420_c + dst_i420_y_size, (dst_width + 1) / 2,
296                    dst_i420_c + dst_i420_y_size + dst_i420_uv_size,
297                    (dst_width + 1) / 2, src_width, src_height, mode);
298 
299   MaskCpuFlags(benchmark_cpu_info);  // Enable all CPU optimization.
300   for (int i = 0; i < benchmark_iterations; ++i) {
301     NV12ToI420Rotate(src_nv12, src_width, src_nv12 + src_nv12_y_size,
302                      (src_width + 1) & ~1, dst_i420_opt, dst_width,
303                      dst_i420_opt + dst_i420_y_size, (dst_width + 1) / 2,
304                      dst_i420_opt + dst_i420_y_size + dst_i420_uv_size,
305                      (dst_width + 1) / 2, src_width, src_height, mode);
306   }
307 
308   // Rotation should be exact.
309   for (int i = 0; i < dst_i420_size; ++i) {
310     EXPECT_EQ(dst_i420_c[i], dst_i420_opt[i]);
311   }
312 
313   free_aligned_buffer_page_end(dst_i420_c);
314   free_aligned_buffer_page_end(dst_i420_opt);
315   free_aligned_buffer_page_end(src_nv12);
316 }
317 
TEST_F(LibYUVRotateTest,NV12Rotate0_Opt)318 TEST_F(LibYUVRotateTest, NV12Rotate0_Opt) {
319   NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
320                  benchmark_height_, kRotate0, benchmark_iterations_,
321                  disable_cpu_flags_, benchmark_cpu_info_);
322 }
323 
TEST_F(LibYUVRotateTest,NV12Rotate90_Opt)324 TEST_F(LibYUVRotateTest, NV12Rotate90_Opt) {
325   NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
326                  benchmark_width_, kRotate90, benchmark_iterations_,
327                  disable_cpu_flags_, benchmark_cpu_info_);
328 }
329 
TEST_F(LibYUVRotateTest,NV12Rotate180_Opt)330 TEST_F(LibYUVRotateTest, NV12Rotate180_Opt) {
331   NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
332                  benchmark_height_, kRotate180, benchmark_iterations_,
333                  disable_cpu_flags_, benchmark_cpu_info_);
334 }
335 
TEST_F(LibYUVRotateTest,NV12Rotate270_Opt)336 TEST_F(LibYUVRotateTest, NV12Rotate270_Opt) {
337   NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
338                  benchmark_width_, kRotate270, benchmark_iterations_,
339                  disable_cpu_flags_, benchmark_cpu_info_);
340 }
341 
TEST_F(LibYUVRotateTest,DISABLED_NV12Rotate0_Odd)342 TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate0_Odd) {
343   NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
344                  benchmark_width_ - 3, benchmark_height_ - 1, kRotate0,
345                  benchmark_iterations_, disable_cpu_flags_,
346                  benchmark_cpu_info_);
347 }
348 
TEST_F(LibYUVRotateTest,DISABLED_NV12Rotate90_Odd)349 TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate90_Odd) {
350   NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
351                  benchmark_height_ - 1, benchmark_width_ - 3, kRotate90,
352                  benchmark_iterations_, disable_cpu_flags_,
353                  benchmark_cpu_info_);
354 }
355 
TEST_F(LibYUVRotateTest,DISABLED_NV12Rotate180_Odd)356 TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate180_Odd) {
357   NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
358                  benchmark_width_ - 3, benchmark_height_ - 1, kRotate180,
359                  benchmark_iterations_, disable_cpu_flags_,
360                  benchmark_cpu_info_);
361 }
362 
TEST_F(LibYUVRotateTest,DISABLED_NV12Rotate270_Odd)363 TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate270_Odd) {
364   NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
365                  benchmark_height_ - 1, benchmark_width_ - 3, kRotate270,
366                  benchmark_iterations_, disable_cpu_flags_,
367                  benchmark_cpu_info_);
368 }
369 
TEST_F(LibYUVRotateTest,NV12Rotate0_Invert)370 TEST_F(LibYUVRotateTest, NV12Rotate0_Invert) {
371   NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_width_,
372                  benchmark_height_, kRotate0, benchmark_iterations_,
373                  disable_cpu_flags_, benchmark_cpu_info_);
374 }
375 
TEST_F(LibYUVRotateTest,NV12Rotate90_Invert)376 TEST_F(LibYUVRotateTest, NV12Rotate90_Invert) {
377   NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_height_,
378                  benchmark_width_, kRotate90, benchmark_iterations_,
379                  disable_cpu_flags_, benchmark_cpu_info_);
380 }
381 
TEST_F(LibYUVRotateTest,NV12Rotate180_Invert)382 TEST_F(LibYUVRotateTest, NV12Rotate180_Invert) {
383   NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_width_,
384                  benchmark_height_, kRotate180, benchmark_iterations_,
385                  disable_cpu_flags_, benchmark_cpu_info_);
386 }
387 
TEST_F(LibYUVRotateTest,NV12Rotate270_Invert)388 TEST_F(LibYUVRotateTest, NV12Rotate270_Invert) {
389   NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_height_,
390                  benchmark_width_, kRotate270, benchmark_iterations_,
391                  disable_cpu_flags_, benchmark_cpu_info_);
392 }
393 
394 }  // namespace libyuv
395