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 "libyuv/cpu_id.h" 14#include "libyuv/rotate.h" 15#include "../unit_test/unit_test.h" 16 17namespace libyuv { 18 19static void I420TestRotate(int src_width, int src_height, 20 int dst_width, int dst_height, 21 libyuv::RotationMode mode, 22 int benchmark_iterations, 23 int disable_cpu_flags, int benchmark_cpu_info) { 24 if (src_width < 1) { 25 src_width = 1; 26 } 27 if (src_height == 0) { 28 src_height = 1; 29 } 30 if (dst_width < 1) { 31 dst_width = 1; 32 } 33 if (dst_height < 1) { 34 dst_height = 1; 35 } 36 int src_i420_y_size = src_width * Abs(src_height); 37 int src_i420_uv_size = ((src_width + 1) / 2) * ((Abs(src_height) + 1) / 2); 38 int src_i420_size = src_i420_y_size + src_i420_uv_size * 2; 39 align_buffer_page_end(src_i420, src_i420_size); 40 for (int i = 0; i < src_i420_size; ++i) { 41 src_i420[i] = fastrand() & 0xff; 42 } 43 44 int dst_i420_y_size = dst_width * dst_height; 45 int dst_i420_uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2); 46 int dst_i420_size = dst_i420_y_size + dst_i420_uv_size * 2; 47 align_buffer_page_end(dst_i420_c, dst_i420_size); 48 align_buffer_page_end(dst_i420_opt, dst_i420_size); 49 memset(dst_i420_c, 2, dst_i420_size); 50 memset(dst_i420_opt, 3, dst_i420_size); 51 52 MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization. 53 I420Rotate(src_i420, src_width, 54 src_i420 + src_i420_y_size, (src_width + 1) / 2, 55 src_i420 + src_i420_y_size + src_i420_uv_size, (src_width + 1) / 2, 56 dst_i420_c, dst_width, 57 dst_i420_c + dst_i420_y_size, (dst_width + 1) / 2, 58 dst_i420_c + dst_i420_y_size + dst_i420_uv_size, 59 (dst_width + 1) / 2, 60 src_width, src_height, mode); 61 62 MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization. 63 for (int i = 0; i < benchmark_iterations; ++i) { 64 I420Rotate(src_i420, src_width, 65 src_i420 + src_i420_y_size, (src_width + 1) / 2, 66 src_i420 + src_i420_y_size + src_i420_uv_size, 67 (src_width + 1) / 2, 68 dst_i420_opt, dst_width, 69 dst_i420_opt + dst_i420_y_size, (dst_width + 1) / 2, 70 dst_i420_opt + dst_i420_y_size + dst_i420_uv_size, 71 (dst_width + 1) / 2, 72 src_width, src_height, mode); 73 } 74 75 // Rotation should be exact. 76 for (int i = 0; i < dst_i420_size; ++i) { 77 EXPECT_EQ(dst_i420_c[i], dst_i420_opt[i]); 78 } 79 80 free_aligned_buffer_page_end(dst_i420_c); 81 free_aligned_buffer_page_end(dst_i420_opt); 82 free_aligned_buffer_page_end(src_i420); 83} 84 85TEST_F(LibYUVRotateTest, I420Rotate0_Opt) { 86 I420TestRotate(benchmark_width_, benchmark_height_, 87 benchmark_width_, benchmark_height_, 88 kRotate0, benchmark_iterations_, 89 disable_cpu_flags_, benchmark_cpu_info_); 90} 91 92TEST_F(LibYUVRotateTest, I420Rotate90_Opt) { 93 I420TestRotate(benchmark_width_, benchmark_height_, 94 benchmark_height_, benchmark_width_, 95 kRotate90, benchmark_iterations_, 96 disable_cpu_flags_, benchmark_cpu_info_); 97} 98 99TEST_F(LibYUVRotateTest, I420Rotate180_Opt) { 100 I420TestRotate(benchmark_width_, benchmark_height_, 101 benchmark_width_, benchmark_height_, 102 kRotate180, benchmark_iterations_, 103 disable_cpu_flags_, benchmark_cpu_info_); 104} 105 106TEST_F(LibYUVRotateTest, I420Rotate270_Opt) { 107 I420TestRotate(benchmark_width_, benchmark_height_, 108 benchmark_height_, benchmark_width_, 109 kRotate270, benchmark_iterations_, 110 disable_cpu_flags_, benchmark_cpu_info_); 111} 112 113// TODO(fbarchard): Remove odd width tests. 114// Odd width tests work but disabled because they use C code and can be 115// tested by passing an odd width command line or environment variable. 116TEST_F(LibYUVRotateTest, DISABLED_I420Rotate0_Odd) { 117 I420TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, 118 benchmark_width_ - 3, benchmark_height_ - 1, 119 kRotate0, benchmark_iterations_, 120 disable_cpu_flags_, benchmark_cpu_info_); 121} 122 123TEST_F(LibYUVRotateTest, DISABLED_I420Rotate90_Odd) { 124 I420TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, 125 benchmark_height_ - 1, benchmark_width_ - 3, 126 kRotate90, benchmark_iterations_, 127 disable_cpu_flags_, benchmark_cpu_info_); 128} 129 130TEST_F(LibYUVRotateTest, DISABLED_I420Rotate180_Odd) { 131 I420TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, 132 benchmark_width_ - 3, benchmark_height_ - 1, 133 kRotate180, benchmark_iterations_, 134 disable_cpu_flags_, benchmark_cpu_info_); 135} 136 137TEST_F(LibYUVRotateTest, DISABLED_I420Rotate270_Odd) { 138 I420TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, 139 benchmark_height_ - 1, benchmark_width_ - 3, 140 kRotate270, benchmark_iterations_, 141 disable_cpu_flags_, benchmark_cpu_info_); 142} 143 144static void NV12TestRotate(int src_width, int src_height, 145 int dst_width, int dst_height, 146 libyuv::RotationMode mode, 147 int benchmark_iterations, 148 int disable_cpu_flags, int benchmark_cpu_info) { 149 if (src_width < 1) { 150 src_width = 1; 151 } 152 if (src_height == 0) { // allow negative for inversion test. 153 src_height = 1; 154 } 155 if (dst_width < 1) { 156 dst_width = 1; 157 } 158 if (dst_height < 1) { 159 dst_height = 1; 160 } 161 int src_nv12_y_size = src_width * Abs(src_height); 162 int src_nv12_uv_size = 163 ((src_width + 1) / 2) * ((Abs(src_height) + 1) / 2) * 2; 164 int src_nv12_size = src_nv12_y_size + src_nv12_uv_size; 165 align_buffer_page_end(src_nv12, src_nv12_size); 166 for (int i = 0; i < src_nv12_size; ++i) { 167 src_nv12[i] = fastrand() & 0xff; 168 } 169 170 int dst_i420_y_size = dst_width * dst_height; 171 int dst_i420_uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2); 172 int dst_i420_size = dst_i420_y_size + dst_i420_uv_size * 2; 173 align_buffer_page_end(dst_i420_c, dst_i420_size); 174 align_buffer_page_end(dst_i420_opt, dst_i420_size); 175 memset(dst_i420_c, 2, dst_i420_size); 176 memset(dst_i420_opt, 3, dst_i420_size); 177 178 MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization. 179 NV12ToI420Rotate(src_nv12, src_width, 180 src_nv12 + src_nv12_y_size, (src_width + 1) & ~1, 181 dst_i420_c, dst_width, 182 dst_i420_c + dst_i420_y_size, (dst_width + 1) / 2, 183 dst_i420_c + dst_i420_y_size + dst_i420_uv_size, 184 (dst_width + 1) / 2, 185 src_width, src_height, mode); 186 187 MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization. 188 for (int i = 0; i < benchmark_iterations; ++i) { 189 NV12ToI420Rotate(src_nv12, src_width, 190 src_nv12 + src_nv12_y_size, (src_width + 1) & ~1, 191 dst_i420_opt, dst_width, 192 dst_i420_opt + dst_i420_y_size, (dst_width + 1) / 2, 193 dst_i420_opt + dst_i420_y_size + dst_i420_uv_size, 194 (dst_width + 1) / 2, 195 src_width, src_height, mode); 196 } 197 198 // Rotation should be exact. 199 for (int i = 0; i < dst_i420_size; ++i) { 200 EXPECT_EQ(dst_i420_c[i], dst_i420_opt[i]); 201 } 202 203 free_aligned_buffer_page_end(dst_i420_c); 204 free_aligned_buffer_page_end(dst_i420_opt); 205 free_aligned_buffer_page_end(src_nv12); 206} 207 208TEST_F(LibYUVRotateTest, NV12Rotate0_Opt) { 209 NV12TestRotate(benchmark_width_, benchmark_height_, 210 benchmark_width_, benchmark_height_, 211 kRotate0, benchmark_iterations_, 212 disable_cpu_flags_, benchmark_cpu_info_); 213} 214 215TEST_F(LibYUVRotateTest, NV12Rotate90_Opt) { 216 NV12TestRotate(benchmark_width_, benchmark_height_, 217 benchmark_height_, benchmark_width_, 218 kRotate90, benchmark_iterations_, 219 disable_cpu_flags_, benchmark_cpu_info_); 220} 221 222TEST_F(LibYUVRotateTest, NV12Rotate180_Opt) { 223 NV12TestRotate(benchmark_width_, benchmark_height_, 224 benchmark_width_, benchmark_height_, 225 kRotate180, benchmark_iterations_, 226 disable_cpu_flags_, benchmark_cpu_info_); 227} 228 229TEST_F(LibYUVRotateTest, NV12Rotate270_Opt) { 230 NV12TestRotate(benchmark_width_, benchmark_height_, 231 benchmark_height_, benchmark_width_, 232 kRotate270, benchmark_iterations_, 233 disable_cpu_flags_, benchmark_cpu_info_); 234} 235 236TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate0_Odd) { 237 NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, 238 benchmark_width_ - 3, benchmark_height_ - 1, 239 kRotate0, benchmark_iterations_, 240 disable_cpu_flags_, benchmark_cpu_info_); 241} 242 243TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate90_Odd) { 244 NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, 245 benchmark_height_ - 1, benchmark_width_ - 3, 246 kRotate90, benchmark_iterations_, 247 disable_cpu_flags_, benchmark_cpu_info_); 248} 249 250TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate180_Odd) { 251 NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, 252 benchmark_width_ - 3, benchmark_height_ - 1, 253 kRotate180, benchmark_iterations_, 254 disable_cpu_flags_, benchmark_cpu_info_); 255} 256 257TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate270_Odd) { 258 NV12TestRotate(benchmark_width_ - 3, benchmark_height_ - 1, 259 benchmark_height_ - 1, benchmark_width_ - 3, 260 kRotate270, benchmark_iterations_, 261 disable_cpu_flags_, benchmark_cpu_info_); 262} 263 264TEST_F(LibYUVRotateTest, NV12Rotate0_Invert) { 265 NV12TestRotate(benchmark_width_, -benchmark_height_, 266 benchmark_width_, benchmark_height_, 267 kRotate0, benchmark_iterations_, 268 disable_cpu_flags_, benchmark_cpu_info_); 269} 270 271TEST_F(LibYUVRotateTest, NV12Rotate90_Invert) { 272 NV12TestRotate(benchmark_width_, -benchmark_height_, 273 benchmark_height_, benchmark_width_, 274 kRotate90, benchmark_iterations_, 275 disable_cpu_flags_, benchmark_cpu_info_); 276} 277 278TEST_F(LibYUVRotateTest, NV12Rotate180_Invert) { 279 NV12TestRotate(benchmark_width_, -benchmark_height_, 280 benchmark_width_, benchmark_height_, 281 kRotate180, benchmark_iterations_, 282 disable_cpu_flags_, benchmark_cpu_info_); 283} 284 285TEST_F(LibYUVRotateTest, NV12Rotate270_Invert) { 286 NV12TestRotate(benchmark_width_, -benchmark_height_, 287 benchmark_height_, benchmark_width_, 288 kRotate270, benchmark_iterations_, 289 disable_cpu_flags_, benchmark_cpu_info_); 290} 291 292 293 294 295 296} // namespace libyuv 297