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 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 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 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 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 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. 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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