|
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 #include <time.h> |
|
13 |
|
14 #include "libyuv/cpu_id.h" |
|
15 #include "libyuv/rotate.h" |
|
16 #include "libyuv/row.h" |
|
17 #include "../unit_test/unit_test.h" |
|
18 |
|
19 namespace libyuv { |
|
20 |
|
21 static void I420TestRotate(int src_width, int src_height, |
|
22 int dst_width, int dst_height, |
|
23 libyuv::RotationMode mode, |
|
24 int benchmark_iterations) { |
|
25 if (src_width < 1) { |
|
26 src_width = 1; |
|
27 } |
|
28 if (src_height < 1) { |
|
29 src_height = 1; |
|
30 } |
|
31 if (dst_width < 1) { |
|
32 dst_width = 1; |
|
33 } |
|
34 if (dst_height < 1) { |
|
35 dst_height = 1; |
|
36 } |
|
37 int src_i420_y_size = src_width * src_height; |
|
38 int src_i420_uv_size = ((src_width + 1) / 2) * ((src_height + 1) / 2); |
|
39 int src_i420_size = src_i420_y_size + src_i420_uv_size * 2; |
|
40 align_buffer_64(src_i420, src_i420_size); |
|
41 for (int i = 0; i < src_i420_size; ++i) { |
|
42 src_i420[i] = random() & 0xff; |
|
43 } |
|
44 |
|
45 int dst_i420_y_size = dst_width * dst_height; |
|
46 int dst_i420_uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2); |
|
47 int dst_i420_size = dst_i420_y_size + dst_i420_uv_size * 2; |
|
48 align_buffer_64(dst_i420_c, dst_i420_size); |
|
49 align_buffer_64(dst_i420_opt, dst_i420_size); |
|
50 memset(dst_i420_c, 2, dst_i420_size); |
|
51 memset(dst_i420_opt, 3, dst_i420_size); |
|
52 |
|
53 MaskCpuFlags(0); // Disable all CPU optimization. |
|
54 I420Rotate(src_i420, src_width, |
|
55 src_i420 + src_i420_y_size, (src_width + 1) / 2, |
|
56 src_i420 + src_i420_y_size + src_i420_uv_size, (src_width + 1) / 2, |
|
57 dst_i420_c, dst_width, |
|
58 dst_i420_c + dst_i420_y_size, (dst_width + 1) / 2, |
|
59 dst_i420_c + dst_i420_y_size + dst_i420_uv_size, |
|
60 (dst_width + 1) / 2, |
|
61 src_width, src_height, mode); |
|
62 |
|
63 MaskCpuFlags(-1); // Enable all CPU optimization. |
|
64 for (int i = 0; i < benchmark_iterations; ++i) { |
|
65 I420Rotate(src_i420, src_width, |
|
66 src_i420 + src_i420_y_size, (src_width + 1) / 2, |
|
67 src_i420 + src_i420_y_size + src_i420_uv_size, |
|
68 (src_width + 1) / 2, |
|
69 dst_i420_opt, dst_width, |
|
70 dst_i420_opt + dst_i420_y_size, (dst_width + 1) / 2, |
|
71 dst_i420_opt + dst_i420_y_size + dst_i420_uv_size, |
|
72 (dst_width + 1) / 2, |
|
73 src_width, src_height, mode); |
|
74 } |
|
75 |
|
76 // Rotation should be exact. |
|
77 for (int i = 0; i < dst_i420_size; ++i) { |
|
78 EXPECT_EQ(dst_i420_c[i], dst_i420_opt[i]); |
|
79 } |
|
80 |
|
81 free_aligned_buffer_64(dst_i420_c); |
|
82 free_aligned_buffer_64(dst_i420_opt); |
|
83 free_aligned_buffer_64(src_i420); |
|
84 } |
|
85 |
|
86 TEST_F(libyuvTest, I420Rotate0) { |
|
87 I420TestRotate(benchmark_width_, benchmark_height_, |
|
88 benchmark_width_, benchmark_height_, |
|
89 kRotate0, benchmark_iterations_); |
|
90 } |
|
91 |
|
92 TEST_F(libyuvTest, I420Rotate90) { |
|
93 I420TestRotate(benchmark_width_, benchmark_height_, |
|
94 benchmark_height_, benchmark_width_, |
|
95 kRotate90, benchmark_iterations_); |
|
96 } |
|
97 |
|
98 TEST_F(libyuvTest, I420Rotate180) { |
|
99 I420TestRotate(benchmark_width_, benchmark_height_, |
|
100 benchmark_width_, benchmark_height_, |
|
101 kRotate180, benchmark_iterations_); |
|
102 } |
|
103 |
|
104 TEST_F(libyuvTest, I420Rotate270) { |
|
105 I420TestRotate(benchmark_width_, benchmark_height_, |
|
106 benchmark_height_, benchmark_width_, |
|
107 kRotate270, benchmark_iterations_); |
|
108 } |
|
109 |
|
110 TEST_F(libyuvTest, I420Rotate0_Odd) { |
|
111 I420TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, |
|
112 benchmark_width_ - 3, benchmark_height_ - 1, |
|
113 kRotate0, benchmark_iterations_); |
|
114 } |
|
115 |
|
116 TEST_F(libyuvTest, I420Rotate90_Odd) { |
|
117 I420TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, |
|
118 benchmark_height_ - 1, benchmark_width_ - 3, |
|
119 kRotate90, benchmark_iterations_); |
|
120 } |
|
121 |
|
122 TEST_F(libyuvTest, I420Rotate180_Odd) { |
|
123 I420TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, |
|
124 benchmark_width_ - 3, benchmark_height_ - 1, |
|
125 kRotate180, benchmark_iterations_); |
|
126 } |
|
127 |
|
128 TEST_F(libyuvTest, I420Rotate270_Odd) { |
|
129 I420TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, |
|
130 benchmark_height_ - 1, benchmark_width_ - 3, |
|
131 kRotate270, benchmark_iterations_); |
|
132 } |
|
133 |
|
134 static void NV12TestRotate(int src_width, int src_height, |
|
135 int dst_width, int dst_height, |
|
136 libyuv::RotationMode mode, |
|
137 int benchmark_iterations) { |
|
138 if (src_width < 1) { |
|
139 src_width = 1; |
|
140 } |
|
141 if (src_height < 1) { |
|
142 src_height = 1; |
|
143 } |
|
144 if (dst_width < 1) { |
|
145 dst_width = 1; |
|
146 } |
|
147 if (dst_height < 1) { |
|
148 dst_height = 1; |
|
149 } |
|
150 int src_nv12_y_size = src_width * src_height; |
|
151 int src_nv12_uv_size = ((src_width + 1) / 2) * ((src_height + 1) / 2) * 2; |
|
152 int src_nv12_size = src_nv12_y_size + src_nv12_uv_size; |
|
153 align_buffer_64(src_nv12, src_nv12_size); |
|
154 for (int i = 0; i < src_nv12_size; ++i) { |
|
155 src_nv12[i] = random() & 0xff; |
|
156 } |
|
157 |
|
158 int dst_i420_y_size = dst_width * dst_height; |
|
159 int dst_i420_uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2); |
|
160 int dst_i420_size = dst_i420_y_size + dst_i420_uv_size * 2; |
|
161 align_buffer_64(dst_i420_c, dst_i420_size); |
|
162 align_buffer_64(dst_i420_opt, dst_i420_size); |
|
163 memset(dst_i420_c, 2, dst_i420_size); |
|
164 memset(dst_i420_opt, 3, dst_i420_size); |
|
165 |
|
166 MaskCpuFlags(0); // Disable all CPU optimization. |
|
167 NV12ToI420Rotate(src_nv12, src_width, |
|
168 src_nv12 + src_nv12_y_size, (src_width + 1) & ~1, |
|
169 dst_i420_c, dst_width, |
|
170 dst_i420_c + dst_i420_y_size, (dst_width + 1) / 2, |
|
171 dst_i420_c + dst_i420_y_size + dst_i420_uv_size, |
|
172 (dst_width + 1) / 2, |
|
173 src_width, src_height, mode); |
|
174 |
|
175 MaskCpuFlags(-1); // Enable all CPU optimization. |
|
176 for (int i = 0; i < benchmark_iterations; ++i) { |
|
177 NV12ToI420Rotate(src_nv12, src_width, |
|
178 src_nv12 + src_nv12_y_size, (src_width + 1) & ~1, |
|
179 dst_i420_opt, dst_width, |
|
180 dst_i420_opt + dst_i420_y_size, (dst_width + 1) / 2, |
|
181 dst_i420_opt + dst_i420_y_size + dst_i420_uv_size, |
|
182 (dst_width + 1) / 2, |
|
183 src_width, src_height, mode); |
|
184 } |
|
185 |
|
186 // Rotation should be exact. |
|
187 for (int i = 0; i < dst_i420_size; ++i) { |
|
188 EXPECT_EQ(dst_i420_c[i], dst_i420_opt[i]); |
|
189 } |
|
190 |
|
191 free_aligned_buffer_64(dst_i420_c); |
|
192 free_aligned_buffer_64(dst_i420_opt); |
|
193 free_aligned_buffer_64(src_nv12); |
|
194 } |
|
195 |
|
196 TEST_F(libyuvTest, NV12Rotate0) { |
|
197 NV12TestRotate(benchmark_width_, benchmark_height_, |
|
198 benchmark_width_, benchmark_height_, |
|
199 kRotate0, benchmark_iterations_); |
|
200 } |
|
201 |
|
202 TEST_F(libyuvTest, NV12Rotate90) { |
|
203 NV12TestRotate(benchmark_width_, benchmark_height_, |
|
204 benchmark_height_, benchmark_width_, |
|
205 kRotate90, benchmark_iterations_); |
|
206 } |
|
207 |
|
208 TEST_F(libyuvTest, NV12Rotate180) { |
|
209 NV12TestRotate(benchmark_width_, benchmark_height_, |
|
210 benchmark_width_, benchmark_height_, |
|
211 kRotate180, benchmark_iterations_); |
|
212 } |
|
213 |
|
214 TEST_F(libyuvTest, NV12Rotate270) { |
|
215 NV12TestRotate(benchmark_width_, benchmark_height_, |
|
216 benchmark_height_, benchmark_width_, |
|
217 kRotate270, benchmark_iterations_); |
|
218 } |
|
219 |
|
220 TEST_F(libyuvTest, NV12Rotate0_Odd) { |
|
221 NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, |
|
222 benchmark_width_ - 3, benchmark_height_ - 1, |
|
223 kRotate0, benchmark_iterations_); |
|
224 } |
|
225 |
|
226 TEST_F(libyuvTest, NV12Rotate90_Odd) { |
|
227 NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, |
|
228 benchmark_height_ - 1, benchmark_width_ - 3, |
|
229 kRotate90, benchmark_iterations_); |
|
230 } |
|
231 |
|
232 TEST_F(libyuvTest, NV12Rotate180_Odd) { |
|
233 NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, |
|
234 benchmark_width_ - 3, benchmark_height_ - 1, |
|
235 kRotate180, benchmark_iterations_); |
|
236 } |
|
237 |
|
238 TEST_F(libyuvTest, NV12Rotate270_Odd) { |
|
239 NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, |
|
240 benchmark_height_ - 1, benchmark_width_ - 3, |
|
241 kRotate270, benchmark_iterations_); |
|
242 } |
|
243 |
|
244 } // namespace libyuv |