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
I420TestRotate(int src_width,int src_height,int dst_width,int dst_height,libyuv::RotationMode mode,int benchmark_iterations)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
TEST_F(libyuvTest,I420Rotate0)86 TEST_F(libyuvTest, I420Rotate0) {
87 I420TestRotate(benchmark_width_, benchmark_height_,
88 benchmark_width_, benchmark_height_,
89 kRotate0, benchmark_iterations_);
90 }
91
TEST_F(libyuvTest,I420Rotate90)92 TEST_F(libyuvTest, I420Rotate90) {
93 I420TestRotate(benchmark_width_, benchmark_height_,
94 benchmark_height_, benchmark_width_,
95 kRotate90, benchmark_iterations_);
96 }
97
TEST_F(libyuvTest,I420Rotate180)98 TEST_F(libyuvTest, I420Rotate180) {
99 I420TestRotate(benchmark_width_, benchmark_height_,
100 benchmark_width_, benchmark_height_,
101 kRotate180, benchmark_iterations_);
102 }
103
TEST_F(libyuvTest,I420Rotate270)104 TEST_F(libyuvTest, I420Rotate270) {
105 I420TestRotate(benchmark_width_, benchmark_height_,
106 benchmark_height_, benchmark_width_,
107 kRotate270, benchmark_iterations_);
108 }
109
TEST_F(libyuvTest,I420Rotate0_Odd)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
TEST_F(libyuvTest,I420Rotate90_Odd)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
TEST_F(libyuvTest,I420Rotate180_Odd)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
TEST_F(libyuvTest,I420Rotate270_Odd)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
NV12TestRotate(int src_width,int src_height,int dst_width,int dst_height,libyuv::RotationMode mode,int benchmark_iterations)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
TEST_F(libyuvTest,NV12Rotate0)196 TEST_F(libyuvTest, NV12Rotate0) {
197 NV12TestRotate(benchmark_width_, benchmark_height_,
198 benchmark_width_, benchmark_height_,
199 kRotate0, benchmark_iterations_);
200 }
201
TEST_F(libyuvTest,NV12Rotate90)202 TEST_F(libyuvTest, NV12Rotate90) {
203 NV12TestRotate(benchmark_width_, benchmark_height_,
204 benchmark_height_, benchmark_width_,
205 kRotate90, benchmark_iterations_);
206 }
207
TEST_F(libyuvTest,NV12Rotate180)208 TEST_F(libyuvTest, NV12Rotate180) {
209 NV12TestRotate(benchmark_width_, benchmark_height_,
210 benchmark_width_, benchmark_height_,
211 kRotate180, benchmark_iterations_);
212 }
213
TEST_F(libyuvTest,NV12Rotate270)214 TEST_F(libyuvTest, NV12Rotate270) {
215 NV12TestRotate(benchmark_width_, benchmark_height_,
216 benchmark_height_, benchmark_width_,
217 kRotate270, benchmark_iterations_);
218 }
219
TEST_F(libyuvTest,NV12Rotate0_Odd)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
TEST_F(libyuvTest,NV12Rotate90_Odd)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
TEST_F(libyuvTest,NV12Rotate180_Odd)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
TEST_F(libyuvTest,NV12Rotate270_Odd)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
245