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
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)138 static void NV12TestRotate(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) { // allow negative for inversion test.
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_nv12_y_size = src_width * Abs(src_height);
159 int src_nv12_uv_size =
160 ((src_width + 1) / 2) * ((Abs(src_height) + 1) / 2) * 2;
161 int src_nv12_size = src_nv12_y_size + src_nv12_uv_size;
162 align_buffer_page_end(src_nv12, src_nv12_size);
163 for (int i = 0; i < src_nv12_size; ++i) {
164 src_nv12[i] = fastrand() & 0xff;
165 }
166
167 int dst_i420_y_size = dst_width * dst_height;
168 int dst_i420_uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2);
169 int dst_i420_size = dst_i420_y_size + dst_i420_uv_size * 2;
170 align_buffer_page_end(dst_i420_c, dst_i420_size);
171 align_buffer_page_end(dst_i420_opt, dst_i420_size);
172 memset(dst_i420_c, 2, dst_i420_size);
173 memset(dst_i420_opt, 3, dst_i420_size);
174
175 MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
176 NV12ToI420Rotate(src_nv12, src_width, src_nv12 + src_nv12_y_size,
177 (src_width + 1) & ~1, dst_i420_c, dst_width,
178 dst_i420_c + dst_i420_y_size, (dst_width + 1) / 2,
179 dst_i420_c + dst_i420_y_size + dst_i420_uv_size,
180 (dst_width + 1) / 2, src_width, src_height, mode);
181
182 MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
183 for (int i = 0; i < benchmark_iterations; ++i) {
184 NV12ToI420Rotate(src_nv12, src_width, src_nv12 + src_nv12_y_size,
185 (src_width + 1) & ~1, dst_i420_opt, dst_width,
186 dst_i420_opt + dst_i420_y_size, (dst_width + 1) / 2,
187 dst_i420_opt + dst_i420_y_size + dst_i420_uv_size,
188 (dst_width + 1) / 2, src_width, src_height, mode);
189 }
190
191 // Rotation should be exact.
192 for (int i = 0; i < dst_i420_size; ++i) {
193 EXPECT_EQ(dst_i420_c[i], dst_i420_opt[i]);
194 }
195
196 free_aligned_buffer_page_end(dst_i420_c);
197 free_aligned_buffer_page_end(dst_i420_opt);
198 free_aligned_buffer_page_end(src_nv12);
199 }
200
TEST_F(LibYUVRotateTest,NV12Rotate0_Opt)201 TEST_F(LibYUVRotateTest, NV12Rotate0_Opt) {
202 NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
203 benchmark_height_, kRotate0, benchmark_iterations_,
204 disable_cpu_flags_, benchmark_cpu_info_);
205 }
206
TEST_F(LibYUVRotateTest,NV12Rotate90_Opt)207 TEST_F(LibYUVRotateTest, NV12Rotate90_Opt) {
208 NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
209 benchmark_width_, kRotate90, benchmark_iterations_,
210 disable_cpu_flags_, benchmark_cpu_info_);
211 }
212
TEST_F(LibYUVRotateTest,NV12Rotate180_Opt)213 TEST_F(LibYUVRotateTest, NV12Rotate180_Opt) {
214 NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
215 benchmark_height_, kRotate180, benchmark_iterations_,
216 disable_cpu_flags_, benchmark_cpu_info_);
217 }
218
TEST_F(LibYUVRotateTest,NV12Rotate270_Opt)219 TEST_F(LibYUVRotateTest, NV12Rotate270_Opt) {
220 NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
221 benchmark_width_, kRotate270, benchmark_iterations_,
222 disable_cpu_flags_, benchmark_cpu_info_);
223 }
224
TEST_F(LibYUVRotateTest,DISABLED_NV12Rotate0_Odd)225 TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate0_Odd) {
226 NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
227 benchmark_width_ - 3, benchmark_height_ - 1, kRotate0,
228 benchmark_iterations_, disable_cpu_flags_,
229 benchmark_cpu_info_);
230 }
231
TEST_F(LibYUVRotateTest,DISABLED_NV12Rotate90_Odd)232 TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate90_Odd) {
233 NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
234 benchmark_height_ - 1, benchmark_width_ - 3, kRotate90,
235 benchmark_iterations_, disable_cpu_flags_,
236 benchmark_cpu_info_);
237 }
238
TEST_F(LibYUVRotateTest,DISABLED_NV12Rotate180_Odd)239 TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate180_Odd) {
240 NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
241 benchmark_width_ - 3, benchmark_height_ - 1, kRotate180,
242 benchmark_iterations_, disable_cpu_flags_,
243 benchmark_cpu_info_);
244 }
245
TEST_F(LibYUVRotateTest,DISABLED_NV12Rotate270_Odd)246 TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate270_Odd) {
247 NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1,
248 benchmark_height_ - 1, benchmark_width_ - 3, kRotate270,
249 benchmark_iterations_, disable_cpu_flags_,
250 benchmark_cpu_info_);
251 }
252
TEST_F(LibYUVRotateTest,NV12Rotate0_Invert)253 TEST_F(LibYUVRotateTest, NV12Rotate0_Invert) {
254 NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_width_,
255 benchmark_height_, kRotate0, benchmark_iterations_,
256 disable_cpu_flags_, benchmark_cpu_info_);
257 }
258
TEST_F(LibYUVRotateTest,NV12Rotate90_Invert)259 TEST_F(LibYUVRotateTest, NV12Rotate90_Invert) {
260 NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_height_,
261 benchmark_width_, kRotate90, benchmark_iterations_,
262 disable_cpu_flags_, benchmark_cpu_info_);
263 }
264
TEST_F(LibYUVRotateTest,NV12Rotate180_Invert)265 TEST_F(LibYUVRotateTest, NV12Rotate180_Invert) {
266 NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_width_,
267 benchmark_height_, kRotate180, benchmark_iterations_,
268 disable_cpu_flags_, benchmark_cpu_info_);
269 }
270
TEST_F(LibYUVRotateTest,NV12Rotate270_Invert)271 TEST_F(LibYUVRotateTest, NV12Rotate270_Invert) {
272 NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_height_,
273 benchmark_width_, kRotate270, benchmark_iterations_,
274 disable_cpu_flags_, benchmark_cpu_info_);
275 }
276
277 } // namespace libyuv
278