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 19namespace libyuv { 20 21static 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 86TEST_F(libyuvTest, I420Rotate0) { 87 I420TestRotate(benchmark_width_, benchmark_height_, 88 benchmark_width_, benchmark_height_, 89 kRotate0, benchmark_iterations_); 90} 91 92TEST_F(libyuvTest, I420Rotate90) { 93 I420TestRotate(benchmark_width_, benchmark_height_, 94 benchmark_height_, benchmark_width_, 95 kRotate90, benchmark_iterations_); 96} 97 98TEST_F(libyuvTest, I420Rotate180) { 99 I420TestRotate(benchmark_width_, benchmark_height_, 100 benchmark_width_, benchmark_height_, 101 kRotate180, benchmark_iterations_); 102} 103 104TEST_F(libyuvTest, I420Rotate270) { 105 I420TestRotate(benchmark_width_, benchmark_height_, 106 benchmark_height_, benchmark_width_, 107 kRotate270, benchmark_iterations_); 108} 109 110TEST_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 116TEST_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 122TEST_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 128TEST_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 134static 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 196TEST_F(libyuvTest, NV12Rotate0) { 197 NV12TestRotate(benchmark_width_, benchmark_height_, 198 benchmark_width_, benchmark_height_, 199 kRotate0, benchmark_iterations_); 200} 201 202TEST_F(libyuvTest, NV12Rotate90) { 203 NV12TestRotate(benchmark_width_, benchmark_height_, 204 benchmark_height_, benchmark_width_, 205 kRotate90, benchmark_iterations_); 206} 207 208TEST_F(libyuvTest, NV12Rotate180) { 209 NV12TestRotate(benchmark_width_, benchmark_height_, 210 benchmark_width_, benchmark_height_, 211 kRotate180, benchmark_iterations_); 212} 213 214TEST_F(libyuvTest, NV12Rotate270) { 215 NV12TestRotate(benchmark_width_, benchmark_height_, 216 benchmark_height_, benchmark_width_, 217 kRotate270, benchmark_iterations_); 218} 219 220TEST_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 226TEST_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 232TEST_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 238TEST_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