1 /* 2 * Copyright 2011 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/compare.h" 15 #include "libyuv/convert.h" 16 #include "libyuv/convert_argb.h" 17 #include "libyuv/convert_from.h" 18 #include "libyuv/convert_from_argb.h" 19 #include "libyuv/cpu_id.h" 20 #include "libyuv/format_conversion.h" 21 #ifdef HAVE_JPEG 22 #include "libyuv/mjpeg_decoder.h" 23 #endif 24 #include "libyuv/planar_functions.h" 25 #include "libyuv/rotate.h" 26 #include "libyuv/row.h" 27 #include "libyuv/video_common.h" 28 #include "../unit_test/unit_test.h" 29 30 #if defined(_MSC_VER) 31 #define SIMD_ALIGNED(var) __declspec(align(16)) var 32 #else // __GNUC__ 33 #define SIMD_ALIGNED(var) var __attribute__((aligned(16))) 34 #endif 35 36 namespace libyuv { 37 38 #define SUBSAMPLE(v, a) ((((v) + (a) - 1)) / (a)) 39 40 #define TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 41 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF) \ 42 TEST_F(libyuvTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) { \ 43 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \ 44 const int kHeight = benchmark_height_; \ 45 align_buffer_64(src_y, kWidth * kHeight + OFF); \ 46 align_buffer_64(src_u, \ 47 SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * \ 48 SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF); \ 49 align_buffer_64(src_v, \ 50 SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * \ 51 SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF); \ 52 align_buffer_64(dst_y_c, kWidth * kHeight); \ 53 align_buffer_64(dst_u_c, \ 54 SUBSAMPLE(kWidth, SUBSAMP_X) * \ 55 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 56 align_buffer_64(dst_v_c, \ 57 SUBSAMPLE(kWidth, SUBSAMP_X) * \ 58 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 59 align_buffer_64(dst_y_opt, kWidth * kHeight); \ 60 align_buffer_64(dst_u_opt, \ 61 SUBSAMPLE(kWidth, SUBSAMP_X) * \ 62 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 63 align_buffer_64(dst_v_opt, \ 64 SUBSAMPLE(kWidth, SUBSAMP_X) * \ 65 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 66 srandom(time(NULL)); \ 67 for (int i = 0; i < kHeight; ++i) \ 68 for (int j = 0; j < kWidth; ++j) \ 69 src_y[(i * kWidth) + j + OFF] = (random() & 0xff); \ 70 for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) { \ 71 for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) { \ 72 src_u[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] = \ 73 (random() & 0xff); \ 74 src_v[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] = \ 75 (random() & 0xff); \ 76 } \ 77 } \ 78 memset(dst_y_c, 1, kWidth * kHeight); \ 79 memset(dst_u_c, 2, SUBSAMPLE(kWidth, SUBSAMP_X) * \ 80 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 81 memset(dst_v_c, 3, SUBSAMPLE(kWidth, SUBSAMP_X) * \ 82 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 83 memset(dst_y_opt, 101, kWidth * kHeight); \ 84 memset(dst_u_opt, 102, SUBSAMPLE(kWidth, SUBSAMP_X) * \ 85 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 86 memset(dst_v_opt, 103, SUBSAMPLE(kWidth, SUBSAMP_X) * \ 87 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 88 MaskCpuFlags(0); \ 89 SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth, \ 90 src_u + OFF, \ 91 SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \ 92 src_v + OFF, \ 93 SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \ 94 dst_y_c, kWidth, \ 95 dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X), \ 96 dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X), \ 97 kWidth, NEG kHeight); \ 98 MaskCpuFlags(-1); \ 99 for (int i = 0; i < benchmark_iterations_; ++i) { \ 100 SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth, \ 101 src_u + OFF, \ 102 SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \ 103 src_v + OFF, \ 104 SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \ 105 dst_y_opt, kWidth, \ 106 dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X), \ 107 dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X), \ 108 kWidth, NEG kHeight); \ 109 } \ 110 int max_diff = 0; \ 111 for (int i = 0; i < kHeight; ++i) { \ 112 for (int j = 0; j < kWidth; ++j) { \ 113 int abs_diff = \ 114 abs(static_cast<int>(dst_y_c[i * kWidth + j]) - \ 115 static_cast<int>(dst_y_opt[i * kWidth + j])); \ 116 if (abs_diff > max_diff) { \ 117 max_diff = abs_diff; \ 118 } \ 119 } \ 120 } \ 121 EXPECT_EQ(0, max_diff); \ 122 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \ 123 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \ 124 int abs_diff = \ 125 abs(static_cast<int>(dst_u_c[i * \ 126 SUBSAMPLE(kWidth, SUBSAMP_X) + j]) - \ 127 static_cast<int>(dst_u_opt[i * \ 128 SUBSAMPLE(kWidth, SUBSAMP_X) + j])); \ 129 if (abs_diff > max_diff) { \ 130 max_diff = abs_diff; \ 131 } \ 132 } \ 133 } \ 134 EXPECT_LE(max_diff, 3); \ 135 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \ 136 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \ 137 int abs_diff = \ 138 abs(static_cast<int>(dst_v_c[i * \ 139 SUBSAMPLE(kWidth, SUBSAMP_X) + j]) - \ 140 static_cast<int>(dst_v_opt[i * \ 141 SUBSAMPLE(kWidth, SUBSAMP_X) + j])); \ 142 if (abs_diff > max_diff) { \ 143 max_diff = abs_diff; \ 144 } \ 145 } \ 146 } \ 147 EXPECT_LE(max_diff, 3); \ 148 free_aligned_buffer_64(dst_y_c); \ 149 free_aligned_buffer_64(dst_u_c); \ 150 free_aligned_buffer_64(dst_v_c); \ 151 free_aligned_buffer_64(dst_y_opt); \ 152 free_aligned_buffer_64(dst_u_opt); \ 153 free_aligned_buffer_64(dst_v_opt); \ 154 free_aligned_buffer_64(src_y); \ 155 free_aligned_buffer_64(src_u); \ 156 free_aligned_buffer_64(src_v); \ 157 } 158 159 #define TESTPLANARTOP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 160 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \ 161 TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 162 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 163 benchmark_width_ - 4, _Any, +, 0) \ 164 TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 165 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 166 benchmark_width_, _Unaligned, +, 1) \ 167 TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 168 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 169 benchmark_width_, _Invert, -, 0) \ 170 TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 171 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 172 benchmark_width_, _Opt, +, 0) 173 174 TESTPLANARTOP(I420, 2, 2, I420, 2, 2) 175 TESTPLANARTOP(I422, 2, 1, I420, 2, 2) 176 TESTPLANARTOP(I444, 1, 1, I420, 2, 2) 177 TESTPLANARTOP(I411, 4, 1, I420, 2, 2) 178 TESTPLANARTOP(I420, 2, 2, I422, 2, 1) 179 TESTPLANARTOP(I420, 2, 2, I444, 1, 1) 180 TESTPLANARTOP(I420, 2, 2, I411, 4, 1) 181 TESTPLANARTOP(I420, 2, 2, I420Mirror, 2, 2) 182 TESTPLANARTOP(I422, 2, 1, I422, 2, 1) 183 TESTPLANARTOP(I444, 1, 1, I444, 1, 1) 184 185 #define TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 186 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF) \ 187 TEST_F(libyuvTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) { \ 188 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \ 189 const int kHeight = benchmark_height_; \ 190 align_buffer_64(src_y, kWidth * kHeight + OFF); \ 191 align_buffer_64(src_u, \ 192 SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * \ 193 SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF); \ 194 align_buffer_64(src_v, \ 195 SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * \ 196 SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF); \ 197 align_buffer_64(dst_y_c, kWidth * kHeight); \ 198 align_buffer_64(dst_uv_c, SUBSAMPLE(kWidth * 2, SUBSAMP_X) * \ 199 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 200 align_buffer_64(dst_y_opt, kWidth * kHeight); \ 201 align_buffer_64(dst_uv_opt, SUBSAMPLE(kWidth * 2, SUBSAMP_X) * \ 202 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 203 srandom(time(NULL)); \ 204 for (int i = 0; i < kHeight; ++i) \ 205 for (int j = 0; j < kWidth; ++j) \ 206 src_y[(i * kWidth) + j + OFF] = (random() & 0xff); \ 207 for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) { \ 208 for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) { \ 209 src_u[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] = \ 210 (random() & 0xff); \ 211 src_v[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] = \ 212 (random() & 0xff); \ 213 } \ 214 } \ 215 memset(dst_y_c, 1, kWidth * kHeight); \ 216 memset(dst_uv_c, 2, SUBSAMPLE(kWidth * 2, SUBSAMP_X) * \ 217 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 218 memset(dst_y_opt, 101, kWidth * kHeight); \ 219 memset(dst_uv_opt, 102, SUBSAMPLE(kWidth * 2, SUBSAMP_X) * \ 220 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 221 MaskCpuFlags(0); \ 222 SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth, \ 223 src_u + OFF, \ 224 SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \ 225 src_v + OFF, \ 226 SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \ 227 dst_y_c, kWidth, \ 228 dst_uv_c, SUBSAMPLE(kWidth * 2, SUBSAMP_X), \ 229 kWidth, NEG kHeight); \ 230 MaskCpuFlags(-1); \ 231 for (int i = 0; i < benchmark_iterations_; ++i) { \ 232 SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth, \ 233 src_u + OFF, \ 234 SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \ 235 src_v + OFF, \ 236 SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \ 237 dst_y_opt, kWidth, \ 238 dst_uv_opt, \ 239 SUBSAMPLE(kWidth * 2, SUBSAMP_X), \ 240 kWidth, NEG kHeight); \ 241 } \ 242 int max_diff = 0; \ 243 for (int i = 0; i < kHeight; ++i) { \ 244 for (int j = 0; j < kWidth; ++j) { \ 245 int abs_diff = \ 246 abs(static_cast<int>(dst_y_c[i * kWidth + j]) - \ 247 static_cast<int>(dst_y_opt[i * kWidth + j])); \ 248 if (abs_diff > max_diff) { \ 249 max_diff = abs_diff; \ 250 } \ 251 } \ 252 } \ 253 EXPECT_LE(max_diff, 1); \ 254 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \ 255 for (int j = 0; j < SUBSAMPLE(kWidth * 2, SUBSAMP_X); ++j) { \ 256 int abs_diff = \ 257 abs(static_cast<int>(dst_uv_c[i * \ 258 SUBSAMPLE(kWidth * 2, SUBSAMP_X) + j]) - \ 259 static_cast<int>(dst_uv_opt[i * \ 260 SUBSAMPLE(kWidth * 2, SUBSAMP_X) + j])); \ 261 if (abs_diff > max_diff) { \ 262 max_diff = abs_diff; \ 263 } \ 264 } \ 265 } \ 266 EXPECT_LE(max_diff, 1); \ 267 free_aligned_buffer_64(dst_y_c); \ 268 free_aligned_buffer_64(dst_uv_c); \ 269 free_aligned_buffer_64(dst_y_opt); \ 270 free_aligned_buffer_64(dst_uv_opt); \ 271 free_aligned_buffer_64(src_y); \ 272 free_aligned_buffer_64(src_u); \ 273 free_aligned_buffer_64(src_v); \ 274 } 275 276 #define TESTPLANARTOBP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 277 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \ 278 TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 279 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 280 benchmark_width_ - 4, _Any, +, 0) \ 281 TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 282 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 283 benchmark_width_, _Unaligned, +, 1) \ 284 TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 285 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 286 benchmark_width_, _Invert, -, 0) \ 287 TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 288 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 289 benchmark_width_, _Opt, +, 0) 290 291 TESTPLANARTOBP(I420, 2, 2, NV12, 2, 2) 292 TESTPLANARTOBP(I420, 2, 2, NV21, 2, 2) 293 294 #define TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 295 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF) \ 296 TEST_F(libyuvTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) { \ 297 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \ 298 const int kHeight = benchmark_height_; \ 299 align_buffer_64(src_y, kWidth * kHeight + OFF); \ 300 align_buffer_64(src_uv, 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * \ 301 SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF); \ 302 align_buffer_64(dst_y_c, kWidth * kHeight); \ 303 align_buffer_64(dst_u_c, \ 304 SUBSAMPLE(kWidth, SUBSAMP_X) * \ 305 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 306 align_buffer_64(dst_v_c, \ 307 SUBSAMPLE(kWidth, SUBSAMP_X) * \ 308 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 309 align_buffer_64(dst_y_opt, kWidth * kHeight); \ 310 align_buffer_64(dst_u_opt, \ 311 SUBSAMPLE(kWidth, SUBSAMP_X) * \ 312 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 313 align_buffer_64(dst_v_opt, \ 314 SUBSAMPLE(kWidth, SUBSAMP_X) * \ 315 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 316 srandom(time(NULL)); \ 317 for (int i = 0; i < kHeight; ++i) \ 318 for (int j = 0; j < kWidth; ++j) \ 319 src_y[(i * kWidth) + j + OFF] = (random() & 0xff); \ 320 for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) { \ 321 for (int j = 0; j < 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) { \ 322 src_uv[(i * 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] = \ 323 (random() & 0xff); \ 324 } \ 325 } \ 326 memset(dst_y_c, 1, kWidth * kHeight); \ 327 memset(dst_u_c, 2, SUBSAMPLE(kWidth, SUBSAMP_X) * \ 328 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 329 memset(dst_v_c, 3, SUBSAMPLE(kWidth, SUBSAMP_X) * \ 330 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 331 memset(dst_y_opt, 101, kWidth * kHeight); \ 332 memset(dst_u_opt, 102, SUBSAMPLE(kWidth, SUBSAMP_X) * \ 333 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 334 memset(dst_v_opt, 103, SUBSAMPLE(kWidth, SUBSAMP_X) * \ 335 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 336 MaskCpuFlags(0); \ 337 SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth, \ 338 src_uv + OFF, \ 339 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \ 340 dst_y_c, kWidth, \ 341 dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X), \ 342 dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X), \ 343 kWidth, NEG kHeight); \ 344 MaskCpuFlags(-1); \ 345 for (int i = 0; i < benchmark_iterations_; ++i) { \ 346 SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth, \ 347 src_uv + OFF, \ 348 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \ 349 dst_y_opt, kWidth, \ 350 dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X), \ 351 dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X), \ 352 kWidth, NEG kHeight); \ 353 } \ 354 int max_diff = 0; \ 355 for (int i = 0; i < kHeight; ++i) { \ 356 for (int j = 0; j < kWidth; ++j) { \ 357 int abs_diff = \ 358 abs(static_cast<int>(dst_y_c[i * kWidth + j]) - \ 359 static_cast<int>(dst_y_opt[i * kWidth + j])); \ 360 if (abs_diff > max_diff) { \ 361 max_diff = abs_diff; \ 362 } \ 363 } \ 364 } \ 365 EXPECT_LE(max_diff, 1); \ 366 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \ 367 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \ 368 int abs_diff = \ 369 abs(static_cast<int>(dst_u_c[i * \ 370 SUBSAMPLE(kWidth, SUBSAMP_X) + j]) - \ 371 static_cast<int>(dst_u_opt[i * \ 372 SUBSAMPLE(kWidth, SUBSAMP_X) + j])); \ 373 if (abs_diff > max_diff) { \ 374 max_diff = abs_diff; \ 375 } \ 376 } \ 377 } \ 378 EXPECT_LE(max_diff, 1); \ 379 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \ 380 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \ 381 int abs_diff = \ 382 abs(static_cast<int>(dst_v_c[i * \ 383 SUBSAMPLE(kWidth, SUBSAMP_X) + j]) - \ 384 static_cast<int>(dst_v_opt[i * \ 385 SUBSAMPLE(kWidth, SUBSAMP_X) + j])); \ 386 if (abs_diff > max_diff) { \ 387 max_diff = abs_diff; \ 388 } \ 389 } \ 390 } \ 391 EXPECT_LE(max_diff, 1); \ 392 free_aligned_buffer_64(dst_y_c); \ 393 free_aligned_buffer_64(dst_u_c); \ 394 free_aligned_buffer_64(dst_v_c); \ 395 free_aligned_buffer_64(dst_y_opt); \ 396 free_aligned_buffer_64(dst_u_opt); \ 397 free_aligned_buffer_64(dst_v_opt); \ 398 free_aligned_buffer_64(src_y); \ 399 free_aligned_buffer_64(src_uv); \ 400 } 401 402 #define TESTBIPLANARTOP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 403 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \ 404 TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 405 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 406 benchmark_width_ - 4, _Any, +, 0) \ 407 TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 408 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 409 benchmark_width_, _Unaligned, +, 1) \ 410 TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 411 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 412 benchmark_width_, _Invert, -, 0) \ 413 TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \ 414 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 415 benchmark_width_, _Opt, +, 0) 416 417 TESTBIPLANARTOP(NV12, 2, 2, I420, 2, 2) 418 TESTBIPLANARTOP(NV21, 2, 2, I420, 2, 2) 419 420 #define ALIGNINT(V, ALIGN) (((V) + (ALIGN) - 1) / (ALIGN) * (ALIGN)) 421 422 #define TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \ 423 YALIGN, W1280, DIFF, N, NEG, OFF, FMT_C, BPP_C) \ 424 TEST_F(libyuvTest, FMT_PLANAR##To##FMT_B##N) { \ 425 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \ 426 const int kHeight = ALIGNINT(benchmark_height_, YALIGN); \ 427 const int kStrideB = ALIGNINT(kWidth * BPP_B, ALIGN); \ 428 const int kSizeUV = \ 429 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y); \ 430 align_buffer_64(src_y, kWidth * kHeight + OFF); \ 431 align_buffer_64(src_u, kSizeUV + OFF); \ 432 align_buffer_64(src_v, kSizeUV + OFF); \ 433 align_buffer_64(dst_argb_c, kStrideB * kHeight); \ 434 align_buffer_64(dst_argb_opt, kStrideB * kHeight); \ 435 srandom(time(NULL)); \ 436 for (int i = 0; i < kWidth * kHeight; ++i) { \ 437 src_y[i + OFF] = (random() & 0xff); \ 438 } \ 439 for (int i = 0; i < kSizeUV; ++i) { \ 440 src_u[i + OFF] = (random() & 0xff); \ 441 src_v[i + OFF] = (random() & 0xff); \ 442 } \ 443 memset(dst_argb_c, 1, kStrideB * kHeight); \ 444 memset(dst_argb_opt, 101, kStrideB * kHeight); \ 445 MaskCpuFlags(0); \ 446 FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth, \ 447 src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), \ 448 src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), \ 449 dst_argb_c, kStrideB, \ 450 kWidth, NEG kHeight); \ 451 MaskCpuFlags(-1); \ 452 for (int i = 0; i < benchmark_iterations_; ++i) { \ 453 FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth, \ 454 src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), \ 455 src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), \ 456 dst_argb_opt, kStrideB, \ 457 kWidth, NEG kHeight); \ 458 } \ 459 int max_diff = 0; \ 460 /* Convert to ARGB so 565 is expanded to bytes that can be compared. */ \ 461 align_buffer_64(dst_argb32_c, kWidth * BPP_C * kHeight); \ 462 align_buffer_64(dst_argb32_opt, kWidth * BPP_C * kHeight); \ 463 memset(dst_argb32_c, 2, kWidth * BPP_C * kHeight); \ 464 memset(dst_argb32_opt, 102, kWidth * BPP_C * kHeight); \ 465 FMT_B##To##FMT_C(dst_argb_c, kStrideB, \ 466 dst_argb32_c, kWidth * BPP_C , \ 467 kWidth, kHeight); \ 468 FMT_B##To##FMT_C(dst_argb_opt, kStrideB, \ 469 dst_argb32_opt, kWidth * BPP_C , \ 470 kWidth, kHeight); \ 471 for (int i = 0; i < kWidth * BPP_C * kHeight; ++i) { \ 472 int abs_diff = \ 473 abs(static_cast<int>(dst_argb32_c[i]) - \ 474 static_cast<int>(dst_argb32_opt[i])); \ 475 if (abs_diff > max_diff) { \ 476 max_diff = abs_diff; \ 477 } \ 478 } \ 479 EXPECT_LE(max_diff, DIFF); \ 480 free_aligned_buffer_64(src_y); \ 481 free_aligned_buffer_64(src_u); \ 482 free_aligned_buffer_64(src_v); \ 483 free_aligned_buffer_64(dst_argb_c); \ 484 free_aligned_buffer_64(dst_argb_opt); \ 485 free_aligned_buffer_64(dst_argb32_c); \ 486 free_aligned_buffer_64(dst_argb32_opt); \ 487 } 488 489 #define TESTPLANARTOB(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \ 490 YALIGN, DIFF, FMT_C, BPP_C) \ 491 TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \ 492 YALIGN, benchmark_width_ - 4, DIFF, _Any, +, 0, FMT_C, BPP_C) \ 493 TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \ 494 YALIGN, benchmark_width_, DIFF, _Unaligned, +, 1, FMT_C, BPP_C) \ 495 TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \ 496 YALIGN, benchmark_width_, DIFF, _Invert, -, 0, FMT_C, BPP_C) \ 497 TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \ 498 YALIGN, benchmark_width_, DIFF, _Opt, +, 0, FMT_C, BPP_C) 499 500 // TODO(fbarchard): Make vertical alignment unnecessary on bayer. 501 TESTPLANARTOB(I420, 2, 2, ARGB, 4, 4, 1, 2, ARGB, 4) 502 TESTPLANARTOB(I420, 2, 2, BGRA, 4, 4, 1, 2, ARGB, 4) 503 TESTPLANARTOB(I420, 2, 2, ABGR, 4, 4, 1, 2, ARGB, 4) 504 TESTPLANARTOB(I420, 2, 2, RGBA, 4, 4, 1, 2, ARGB, 4) 505 TESTPLANARTOB(I420, 2, 2, RAW, 3, 3, 1, 2, ARGB, 4) 506 TESTPLANARTOB(I420, 2, 2, RGB24, 3, 3, 1, 2, ARGB, 4) 507 TESTPLANARTOB(I420, 2, 2, RGB565, 2, 2, 1, 9, ARGB, 4) 508 TESTPLANARTOB(I420, 2, 2, ARGB1555, 2, 2, 1, 9, ARGB, 4) 509 TESTPLANARTOB(I420, 2, 2, ARGB4444, 2, 2, 1, 17, ARGB, 4) 510 TESTPLANARTOB(I422, 2, 1, ARGB, 4, 4, 1, 2, ARGB, 4) 511 TESTPLANARTOB(I422, 2, 1, BGRA, 4, 4, 1, 2, ARGB, 4) 512 TESTPLANARTOB(I422, 2, 1, ABGR, 4, 4, 1, 2, ARGB, 4) 513 TESTPLANARTOB(I422, 2, 1, RGBA, 4, 4, 1, 2, ARGB, 4) 514 TESTPLANARTOB(I411, 4, 1, ARGB, 4, 4, 1, 2, ARGB, 4) 515 TESTPLANARTOB(I444, 1, 1, ARGB, 4, 4, 1, 2, ARGB, 4) 516 TESTPLANARTOB(I420, 2, 2, YUY2, 2, 4, 1, 1, ARGB, 4) 517 TESTPLANARTOB(I420, 2, 2, UYVY, 2, 4, 1, 1, ARGB, 4) 518 TESTPLANARTOB(I422, 2, 1, YUY2, 2, 4, 1, 0, ARGB, 4) 519 TESTPLANARTOB(I422, 2, 1, UYVY, 2, 4, 1, 0, ARGB, 4) 520 TESTPLANARTOB(I420, 2, 2, I400, 1, 1, 1, 0, ARGB, 4) 521 TESTPLANARTOB(I420, 2, 2, BayerBGGR, 1, 2, 2, 2, ARGB, 4) 522 TESTPLANARTOB(I420, 2, 2, BayerRGGB, 1, 2, 2, 2, ARGB, 4) 523 TESTPLANARTOB(I420, 2, 2, BayerGBRG, 1, 2, 2, 2, ARGB, 4) 524 TESTPLANARTOB(I420, 2, 2, BayerGRBG, 1, 2, 2, 2, ARGB, 4) 525 526 #define TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, \ 527 W1280, DIFF, N, NEG, OFF) \ 528 TEST_F(libyuvTest, FMT_PLANAR##To##FMT_B##N) { \ 529 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \ 530 const int kHeight = benchmark_height_; \ 531 const int kStrideB = kWidth * BPP_B; \ 532 align_buffer_64(src_y, kWidth * kHeight + OFF); \ 533 align_buffer_64(src_uv, \ 534 SUBSAMPLE(kWidth, SUBSAMP_X) * \ 535 SUBSAMPLE(kHeight, SUBSAMP_Y) * 2 + OFF); \ 536 align_buffer_64(dst_argb_c, kStrideB * kHeight); \ 537 align_buffer_64(dst_argb_opt, kStrideB * kHeight); \ 538 srandom(time(NULL)); \ 539 for (int i = 0; i < kHeight; ++i) \ 540 for (int j = 0; j < kWidth; ++j) \ 541 src_y[(i * kWidth) + j + OFF] = (random() & 0xff); \ 542 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \ 543 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X) * 2; ++j) { \ 544 src_uv[(i * SUBSAMPLE(kWidth, SUBSAMP_X)) * 2 + j + OFF] = \ 545 (random() & 0xff); \ 546 } \ 547 } \ 548 memset(dst_argb_c, 1, kStrideB * kHeight); \ 549 memset(dst_argb_opt, 101, kStrideB * kHeight); \ 550 MaskCpuFlags(0); \ 551 FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth, \ 552 src_uv + OFF, SUBSAMPLE(kWidth, SUBSAMP_X) * 2, \ 553 dst_argb_c, kWidth * BPP_B, \ 554 kWidth, NEG kHeight); \ 555 MaskCpuFlags(-1); \ 556 for (int i = 0; i < benchmark_iterations_; ++i) { \ 557 FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth, \ 558 src_uv + OFF, SUBSAMPLE(kWidth, SUBSAMP_X) * 2, \ 559 dst_argb_opt, kWidth * BPP_B, \ 560 kWidth, NEG kHeight); \ 561 } \ 562 /* Convert to ARGB so 565 is expanded to bytes that can be compared. */ \ 563 align_buffer_64(dst_argb32_c, kWidth * 4 * kHeight); \ 564 align_buffer_64(dst_argb32_opt, kWidth * 4 * kHeight); \ 565 memset(dst_argb32_c, 2, kWidth * 4 * kHeight); \ 566 memset(dst_argb32_opt, 102, kWidth * 4 * kHeight); \ 567 FMT_B##ToARGB(dst_argb_c, kStrideB, \ 568 dst_argb32_c, kWidth * 4, \ 569 kWidth, kHeight); \ 570 FMT_B##ToARGB(dst_argb_opt, kStrideB, \ 571 dst_argb32_opt, kWidth * 4, \ 572 kWidth, kHeight); \ 573 int max_diff = 0; \ 574 for (int i = 0; i < kHeight; ++i) { \ 575 for (int j = 0; j < kWidth * 4; ++j) { \ 576 int abs_diff = \ 577 abs(static_cast<int>(dst_argb32_c[i * kWidth * 4 + j]) - \ 578 static_cast<int>(dst_argb32_opt[i * kWidth * 4 + j])); \ 579 if (abs_diff > max_diff) { \ 580 max_diff = abs_diff; \ 581 } \ 582 } \ 583 } \ 584 EXPECT_LE(max_diff, DIFF); \ 585 free_aligned_buffer_64(src_y); \ 586 free_aligned_buffer_64(src_uv); \ 587 free_aligned_buffer_64(dst_argb_c); \ 588 free_aligned_buffer_64(dst_argb_opt); \ 589 free_aligned_buffer_64(dst_argb32_c); \ 590 free_aligned_buffer_64(dst_argb32_opt); \ 591 } 592 593 #define TESTBIPLANARTOB(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, DIFF) \ 594 TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, \ 595 benchmark_width_ - 4, DIFF, _Any, +, 0) \ 596 TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, \ 597 benchmark_width_, DIFF, _Unaligned, +, 1) \ 598 TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, \ 599 benchmark_width_, DIFF, _Invert, -, 0) \ 600 TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, \ 601 benchmark_width_, DIFF, _Opt, +, 0) 602 603 TESTBIPLANARTOB(NV12, 2, 2, ARGB, 4, 2) 604 TESTBIPLANARTOB(NV21, 2, 2, ARGB, 4, 2) 605 TESTBIPLANARTOB(NV12, 2, 2, RGB565, 2, 9) 606 TESTBIPLANARTOB(NV21, 2, 2, RGB565, 2, 9) 607 608 #define TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 609 W1280, DIFF, N, NEG, OFF) \ 610 TEST_F(libyuvTest, FMT_A##To##FMT_PLANAR##N) { \ 611 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \ 612 const int kHeight = ALIGNINT(benchmark_height_, YALIGN); \ 613 const int kStride = \ 614 (SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMP_X * 8 * BPP_A + 7) / 8; \ 615 align_buffer_64(src_argb, kStride * kHeight + OFF); \ 616 align_buffer_64(dst_y_c, kWidth * kHeight); \ 617 align_buffer_64(dst_u_c, \ 618 SUBSAMPLE(kWidth, SUBSAMP_X) * \ 619 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 620 align_buffer_64(dst_v_c, \ 621 SUBSAMPLE(kWidth, SUBSAMP_X) * \ 622 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 623 align_buffer_64(dst_y_opt, kWidth * kHeight); \ 624 align_buffer_64(dst_u_opt, \ 625 SUBSAMPLE(kWidth, SUBSAMP_X) * \ 626 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 627 align_buffer_64(dst_v_opt, \ 628 SUBSAMPLE(kWidth, SUBSAMP_X) * \ 629 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 630 memset(dst_y_c, 1, kWidth * kHeight); \ 631 memset(dst_u_c, 2, \ 632 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 633 memset(dst_v_c, 3, \ 634 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 635 memset(dst_y_opt, 101, kWidth * kHeight); \ 636 memset(dst_u_opt, 102, \ 637 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 638 memset(dst_v_opt, 103, \ 639 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 640 srandom(time(NULL)); \ 641 for (int i = 0; i < kHeight; ++i) \ 642 for (int j = 0; j < kStride; ++j) \ 643 src_argb[(i * kStride) + j + OFF] = (random() & 0xff); \ 644 MaskCpuFlags(0); \ 645 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, \ 646 dst_y_c, kWidth, \ 647 dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X), \ 648 dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X), \ 649 kWidth, NEG kHeight); \ 650 MaskCpuFlags(-1); \ 651 for (int i = 0; i < benchmark_iterations_; ++i) { \ 652 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, \ 653 dst_y_opt, kWidth, \ 654 dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X), \ 655 dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X), \ 656 kWidth, NEG kHeight); \ 657 } \ 658 int max_diff = 0; \ 659 for (int i = 0; i < kHeight; ++i) { \ 660 for (int j = 0; j < kWidth; ++j) { \ 661 int abs_diff = \ 662 abs(static_cast<int>(dst_y_c[i * kWidth + j]) - \ 663 static_cast<int>(dst_y_opt[i * kWidth + j])); \ 664 if (abs_diff > max_diff) { \ 665 max_diff = abs_diff; \ 666 } \ 667 } \ 668 } \ 669 EXPECT_LE(max_diff, DIFF); \ 670 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \ 671 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \ 672 int abs_diff = \ 673 abs(static_cast<int>(dst_u_c[i * \ 674 SUBSAMPLE(kWidth, SUBSAMP_X) + j]) - \ 675 static_cast<int>(dst_u_opt[i * \ 676 SUBSAMPLE(kWidth, SUBSAMP_X) + j])); \ 677 if (abs_diff > max_diff) { \ 678 max_diff = abs_diff; \ 679 } \ 680 } \ 681 } \ 682 EXPECT_LE(max_diff, DIFF); \ 683 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \ 684 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \ 685 int abs_diff = \ 686 abs(static_cast<int>(dst_v_c[i * \ 687 SUBSAMPLE(kWidth, SUBSAMP_X) + j]) - \ 688 static_cast<int>(dst_v_opt[i * \ 689 SUBSAMPLE(kWidth, SUBSAMP_X) + j])); \ 690 if (abs_diff > max_diff) { \ 691 max_diff = abs_diff; \ 692 } \ 693 } \ 694 } \ 695 EXPECT_LE(max_diff, DIFF); \ 696 free_aligned_buffer_64(dst_y_c); \ 697 free_aligned_buffer_64(dst_u_c); \ 698 free_aligned_buffer_64(dst_v_c); \ 699 free_aligned_buffer_64(dst_y_opt); \ 700 free_aligned_buffer_64(dst_u_opt); \ 701 free_aligned_buffer_64(dst_v_opt); \ 702 free_aligned_buffer_64(src_argb); \ 703 } 704 705 #define TESTATOPLANAR(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 706 DIFF) \ 707 TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 708 benchmark_width_ - 4, DIFF, _Any, +, 0) \ 709 TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 710 benchmark_width_, DIFF, _Unaligned, +, 1) \ 711 TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 712 benchmark_width_, DIFF, _Invert, -, 0) \ 713 TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 714 benchmark_width_, DIFF, _Opt, +, 0) 715 716 TESTATOPLANAR(ARGB, 4, 1, I420, 2, 2, 4) 717 #ifdef __arm__ 718 TESTATOPLANAR(ARGB, 4, 1, J420, 2, 2, 4) 719 #else 720 TESTATOPLANAR(ARGB, 4, 1, J420, 2, 2, 0) 721 #endif 722 TESTATOPLANAR(BGRA, 4, 1, I420, 2, 2, 4) 723 TESTATOPLANAR(ABGR, 4, 1, I420, 2, 2, 4) 724 TESTATOPLANAR(RGBA, 4, 1, I420, 2, 2, 4) 725 TESTATOPLANAR(RAW, 3, 1, I420, 2, 2, 4) 726 TESTATOPLANAR(RGB24, 3, 1, I420, 2, 2, 4) 727 TESTATOPLANAR(RGB565, 2, 1, I420, 2, 2, 5) 728 // TODO(fbarchard): Make 1555 neon work same as C code, reduce to diff 9. 729 TESTATOPLANAR(ARGB1555, 2, 1, I420, 2, 2, 15) 730 TESTATOPLANAR(ARGB4444, 2, 1, I420, 2, 2, 17) 731 TESTATOPLANAR(ARGB, 4, 1, I411, 4, 1, 4) 732 TESTATOPLANAR(ARGB, 4, 1, I422, 2, 1, 2) 733 TESTATOPLANAR(ARGB, 4, 1, I444, 1, 1, 2) 734 TESTATOPLANAR(YUY2, 2, 1, I420, 2, 2, 2) 735 TESTATOPLANAR(UYVY, 2, 1, I420, 2, 2, 2) 736 TESTATOPLANAR(YUY2, 2, 1, I422, 2, 1, 2) 737 TESTATOPLANAR(UYVY, 2, 1, I422, 2, 1, 2) 738 TESTATOPLANAR(I400, 1, 1, I420, 2, 2, 2) 739 TESTATOPLANAR(BayerBGGR, 1, 2, I420, 2, 2, 4) 740 TESTATOPLANAR(BayerRGGB, 1, 2, I420, 2, 2, 4) 741 TESTATOPLANAR(BayerGBRG, 1, 2, I420, 2, 2, 4) 742 TESTATOPLANAR(BayerGRBG, 1, 2, I420, 2, 2, 4) 743 744 #define TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 745 W1280, N, NEG, OFF) \ 746 TEST_F(libyuvTest, FMT_A##To##FMT_PLANAR##N) { \ 747 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \ 748 const int kHeight = benchmark_height_; \ 749 const int kStride = (kWidth * 8 * BPP_A + 7) / 8; \ 750 align_buffer_64(src_argb, kStride * kHeight + OFF); \ 751 align_buffer_64(dst_y_c, kWidth * kHeight); \ 752 align_buffer_64(dst_uv_c, \ 753 SUBSAMPLE(kWidth, SUBSAMP_X) * 2 * \ 754 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 755 align_buffer_64(dst_y_opt, kWidth * kHeight); \ 756 align_buffer_64(dst_uv_opt, \ 757 SUBSAMPLE(kWidth, SUBSAMP_X) * 2 * \ 758 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 759 srandom(time(NULL)); \ 760 for (int i = 0; i < kHeight; ++i) \ 761 for (int j = 0; j < kStride; ++j) \ 762 src_argb[(i * kStride) + j + OFF] = (random() & 0xff); \ 763 memset(dst_y_c, 1, kWidth * kHeight); \ 764 memset(dst_uv_c, 2, SUBSAMPLE(kWidth, SUBSAMP_X) * 2 * \ 765 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 766 memset(dst_y_opt, 101, kWidth * kHeight); \ 767 memset(dst_uv_opt, 102, SUBSAMPLE(kWidth, SUBSAMP_X) * 2 * \ 768 SUBSAMPLE(kHeight, SUBSAMP_Y)); \ 769 MaskCpuFlags(0); \ 770 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, \ 771 dst_y_c, kWidth, \ 772 dst_uv_c, SUBSAMPLE(kWidth, SUBSAMP_X) * 2, \ 773 kWidth, NEG kHeight); \ 774 MaskCpuFlags(-1); \ 775 for (int i = 0; i < benchmark_iterations_; ++i) { \ 776 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, \ 777 dst_y_opt, kWidth, \ 778 dst_uv_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * 2, \ 779 kWidth, NEG kHeight); \ 780 } \ 781 int max_diff = 0; \ 782 for (int i = 0; i < kHeight; ++i) { \ 783 for (int j = 0; j < kWidth; ++j) { \ 784 int abs_diff = \ 785 abs(static_cast<int>(dst_y_c[i * kWidth + j]) - \ 786 static_cast<int>(dst_y_opt[i * kWidth + j])); \ 787 if (abs_diff > max_diff) { \ 788 max_diff = abs_diff; \ 789 } \ 790 } \ 791 } \ 792 EXPECT_LE(max_diff, 4); \ 793 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \ 794 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X) * 2; ++j) { \ 795 int abs_diff = \ 796 abs(static_cast<int>(dst_uv_c[i * \ 797 SUBSAMPLE(kWidth, SUBSAMP_X) * 2 + j]) - \ 798 static_cast<int>(dst_uv_opt[i * \ 799 SUBSAMPLE(kWidth, SUBSAMP_X) * 2 + j])); \ 800 if (abs_diff > max_diff) { \ 801 max_diff = abs_diff; \ 802 } \ 803 } \ 804 } \ 805 EXPECT_LE(max_diff, 4); \ 806 free_aligned_buffer_64(dst_y_c); \ 807 free_aligned_buffer_64(dst_uv_c); \ 808 free_aligned_buffer_64(dst_y_opt); \ 809 free_aligned_buffer_64(dst_uv_opt); \ 810 free_aligned_buffer_64(src_argb); \ 811 } 812 813 #define TESTATOBIPLANAR(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \ 814 TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 815 benchmark_width_ - 4, _Any, +, 0) \ 816 TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 817 benchmark_width_, _Unaligned, +, 1) \ 818 TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 819 benchmark_width_, _Invert, -, 0) \ 820 TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \ 821 benchmark_width_, _Opt, +, 0) 822 823 TESTATOBIPLANAR(ARGB, 4, NV12, 2, 2) 824 TESTATOBIPLANAR(ARGB, 4, NV21, 2, 2) 825 826 #define TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, \ 827 FMT_B, BPP_B, STRIDE_B, HEIGHT_B, \ 828 W1280, DIFF, N, NEG, OFF) \ 829 TEST_F(libyuvTest, FMT_A##To##FMT_B##N) { \ 830 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \ 831 const int kHeight = benchmark_height_; \ 832 const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A; \ 833 const int kHeightB = (kHeight + HEIGHT_B - 1) / HEIGHT_B * HEIGHT_B; \ 834 const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A; \ 835 const int kStrideB = (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B; \ 836 align_buffer_64(src_argb, kStrideA * kHeightA + OFF); \ 837 align_buffer_64(dst_argb_c, kStrideB * kHeightB); \ 838 align_buffer_64(dst_argb_opt, kStrideB * kHeightB); \ 839 srandom(time(NULL)); \ 840 for (int i = 0; i < kStrideA * kHeightA; ++i) { \ 841 src_argb[i + OFF] = (random() & 0xff); \ 842 } \ 843 memset(dst_argb_c, 1, kStrideB * kHeightB); \ 844 memset(dst_argb_opt, 101, kStrideB * kHeightB); \ 845 MaskCpuFlags(0); \ 846 FMT_A##To##FMT_B(src_argb + OFF, kStrideA, \ 847 dst_argb_c, kStrideB, \ 848 kWidth, NEG kHeight); \ 849 MaskCpuFlags(-1); \ 850 for (int i = 0; i < benchmark_iterations_; ++i) { \ 851 FMT_A##To##FMT_B(src_argb + OFF, kStrideA, \ 852 dst_argb_opt, kStrideB, \ 853 kWidth, NEG kHeight); \ 854 } \ 855 int max_diff = 0; \ 856 for (int i = 0; i < kStrideB * kHeightB; ++i) { \ 857 int abs_diff = \ 858 abs(static_cast<int>(dst_argb_c[i]) - \ 859 static_cast<int>(dst_argb_opt[i])); \ 860 if (abs_diff > max_diff) { \ 861 max_diff = abs_diff; \ 862 } \ 863 } \ 864 EXPECT_LE(max_diff, DIFF); \ 865 free_aligned_buffer_64(src_argb); \ 866 free_aligned_buffer_64(dst_argb_c); \ 867 free_aligned_buffer_64(dst_argb_opt); \ 868 } 869 870 #define TESTATOBRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, \ 871 FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF) \ 872 TEST_F(libyuvTest, FMT_A##To##FMT_B##_Random) { \ 873 srandom(time(NULL)); \ 874 for (int times = 0; times < benchmark_iterations_; ++times) { \ 875 const int kWidth = (random() & 63) + 1; \ 876 const int kHeight = (random() & 31) + 1; \ 877 const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A; \ 878 const int kHeightB = (kHeight + HEIGHT_B - 1) / HEIGHT_B * HEIGHT_B; \ 879 const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A;\ 880 const int kStrideB = (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B;\ 881 align_buffer_page_end(src_argb, kStrideA * kHeightA); \ 882 align_buffer_page_end(dst_argb_c, kStrideB * kHeightB); \ 883 align_buffer_page_end(dst_argb_opt, kStrideB * kHeightB); \ 884 for (int i = 0; i < kStrideA * kHeightA; ++i) { \ 885 src_argb[i] = (random() & 0xff); \ 886 } \ 887 memset(dst_argb_c, 123, kStrideB * kHeightB); \ 888 memset(dst_argb_opt, 123, kStrideB * kHeightB); \ 889 MaskCpuFlags(0); \ 890 FMT_A##To##FMT_B(src_argb, kStrideA, \ 891 dst_argb_c, kStrideB, \ 892 kWidth, kHeight); \ 893 MaskCpuFlags(-1); \ 894 FMT_A##To##FMT_B(src_argb, kStrideA, \ 895 dst_argb_opt, kStrideB, \ 896 kWidth, kHeight); \ 897 int max_diff = 0; \ 898 for (int i = 0; i < kStrideB * kHeightB; ++i) { \ 899 int abs_diff = \ 900 abs(static_cast<int>(dst_argb_c[i]) - \ 901 static_cast<int>(dst_argb_opt[i])); \ 902 if (abs_diff > max_diff) { \ 903 max_diff = abs_diff; \ 904 } \ 905 } \ 906 EXPECT_LE(max_diff, DIFF); \ 907 free_aligned_buffer_page_end(src_argb); \ 908 free_aligned_buffer_page_end(dst_argb_c); \ 909 free_aligned_buffer_page_end(dst_argb_opt); \ 910 } \ 911 } 912 913 #define TESTATOB(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, \ 914 FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF) \ 915 TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, \ 916 FMT_B, BPP_B, STRIDE_B, HEIGHT_B, \ 917 benchmark_width_ - 4, DIFF, _Any, +, 0) \ 918 TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, \ 919 FMT_B, BPP_B, STRIDE_B, HEIGHT_B, \ 920 benchmark_width_, DIFF, _Unaligned, +, 1) \ 921 TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, \ 922 FMT_B, BPP_B, STRIDE_B, HEIGHT_B, \ 923 benchmark_width_, DIFF, _Invert, -, 0) \ 924 TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, \ 925 FMT_B, BPP_B, STRIDE_B, HEIGHT_B, \ 926 benchmark_width_, DIFF, _Opt, +, 0) \ 927 TESTATOBRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, \ 928 FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF) 929 930 TESTATOB(ARGB, 4, 4, 1, ARGB, 4, 4, 1, 0) 931 TESTATOB(ARGB, 4, 4, 1, BGRA, 4, 4, 1, 0) 932 TESTATOB(ARGB, 4, 4, 1, ABGR, 4, 4, 1, 0) 933 TESTATOB(ARGB, 4, 4, 1, RGBA, 4, 4, 1, 0) 934 TESTATOB(ARGB, 4, 4, 1, RAW, 3, 3, 1, 0) 935 TESTATOB(ARGB, 4, 4, 1, RGB24, 3, 3, 1, 0) 936 TESTATOB(ARGB, 4, 4, 1, RGB565, 2, 2, 1, 0) 937 TESTATOB(ARGB, 4, 4, 1, ARGB1555, 2, 2, 1, 0) 938 TESTATOB(ARGB, 4, 4, 1, ARGB4444, 2, 2, 1, 0) 939 TESTATOB(ARGB, 4, 4, 1, BayerBGGR, 1, 1, 1, 0) 940 TESTATOB(ARGB, 4, 4, 1, BayerRGGB, 1, 1, 1, 0) 941 TESTATOB(ARGB, 4, 4, 1, BayerGBRG, 1, 1, 1, 0) 942 TESTATOB(ARGB, 4, 4, 1, BayerGRBG, 1, 1, 1, 0) 943 TESTATOB(ARGB, 4, 4, 1, YUY2, 2, 4, 1, 4) 944 TESTATOB(ARGB, 4, 4, 1, UYVY, 2, 4, 1, 4) 945 TESTATOB(ARGB, 4, 4, 1, I400, 1, 1, 1, 2) 946 TESTATOB(ARGB, 4, 4, 1, J400, 1, 1, 1, 2) 947 TESTATOB(BGRA, 4, 4, 1, ARGB, 4, 4, 1, 0) 948 TESTATOB(ABGR, 4, 4, 1, ARGB, 4, 4, 1, 0) 949 TESTATOB(RGBA, 4, 4, 1, ARGB, 4, 4, 1, 0) 950 TESTATOB(RAW, 3, 3, 1, ARGB, 4, 4, 1, 0) 951 TESTATOB(RGB24, 3, 3, 1, ARGB, 4, 4, 1, 0) 952 TESTATOB(RGB565, 2, 2, 1, ARGB, 4, 4, 1, 0) 953 TESTATOB(ARGB1555, 2, 2, 1, ARGB, 4, 4, 1, 0) 954 TESTATOB(ARGB4444, 2, 2, 1, ARGB, 4, 4, 1, 0) 955 TESTATOB(YUY2, 2, 4, 1, ARGB, 4, 4, 1, 4) 956 TESTATOB(UYVY, 2, 4, 1, ARGB, 4, 4, 1, 4) 957 TESTATOB(BayerBGGR, 1, 2, 2, ARGB, 4, 4, 1, 0) 958 TESTATOB(BayerRGGB, 1, 2, 2, ARGB, 4, 4, 1, 0) 959 TESTATOB(BayerGBRG, 1, 2, 2, ARGB, 4, 4, 1, 0) 960 TESTATOB(BayerGRBG, 1, 2, 2, ARGB, 4, 4, 1, 0) 961 TESTATOB(I400, 1, 1, 1, ARGB, 4, 4, 1, 0) 962 TESTATOB(I400, 1, 1, 1, I400, 1, 1, 1, 0) 963 TESTATOB(I400, 1, 1, 1, I400Mirror, 1, 1, 1, 0) 964 TESTATOB(Y, 1, 1, 1, ARGB, 4, 4, 1, 0) 965 TESTATOB(ARGB, 4, 4, 1, ARGBMirror, 4, 4, 1, 0) 966 967 #define TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A, \ 968 W1280, N, NEG, OFF) \ 969 TEST_F(libyuvTest, FMT_ATOB##_Symetric##N) { \ 970 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \ 971 const int kHeight = benchmark_height_; \ 972 const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A; \ 973 const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A; \ 974 align_buffer_64(src_argb, kStrideA * kHeightA + OFF); \ 975 align_buffer_64(dst_argb_c, kStrideA * kHeightA); \ 976 align_buffer_64(dst_argb_opt, kStrideA * kHeightA); \ 977 srandom(time(NULL)); \ 978 for (int i = 0; i < kStrideA * kHeightA; ++i) { \ 979 src_argb[i + OFF] = (random() & 0xff); \ 980 } \ 981 memset(dst_argb_c, 1, kStrideA * kHeightA); \ 982 memset(dst_argb_opt, 101, kStrideA * kHeightA); \ 983 MaskCpuFlags(0); \ 984 FMT_ATOB(src_argb + OFF, kStrideA, \ 985 dst_argb_c, kStrideA, \ 986 kWidth, NEG kHeight); \ 987 MaskCpuFlags(-1); \ 988 for (int i = 0; i < benchmark_iterations_; ++i) { \ 989 FMT_ATOB(src_argb + OFF, kStrideA, \ 990 dst_argb_opt, kStrideA, \ 991 kWidth, NEG kHeight); \ 992 } \ 993 MaskCpuFlags(0); \ 994 FMT_ATOB(dst_argb_c, kStrideA, \ 995 dst_argb_c, kStrideA, \ 996 kWidth, NEG kHeight); \ 997 MaskCpuFlags(-1); \ 998 FMT_ATOB(dst_argb_opt, kStrideA, \ 999 dst_argb_opt, kStrideA, \ 1000 kWidth, NEG kHeight); \ 1001 for (int i = 0; i < kStrideA * kHeightA; ++i) { \ 1002 EXPECT_EQ(src_argb[i + OFF], dst_argb_opt[i]); \ 1003 EXPECT_EQ(dst_argb_c[i], dst_argb_opt[i]); \ 1004 } \ 1005 free_aligned_buffer_64(src_argb); \ 1006 free_aligned_buffer_64(dst_argb_c); \ 1007 free_aligned_buffer_64(dst_argb_opt); \ 1008 } 1009 1010 #define TESTSYM(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A) \ 1011 TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A, \ 1012 benchmark_width_ - 4, _Any, +, 0) \ 1013 TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A, \ 1014 benchmark_width_, _Unaligned, +, 1) \ 1015 TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A, \ 1016 benchmark_width_, _Opt, +, 0) 1017 1018 TESTSYM(ARGBToARGB, 4, 4, 1) 1019 TESTSYM(ARGBToBGRA, 4, 4, 1) 1020 TESTSYM(ARGBToABGR, 4, 4, 1) 1021 TESTSYM(BGRAToARGB, 4, 4, 1) 1022 TESTSYM(ABGRToARGB, 4, 4, 1) 1023 1024 TEST_F(libyuvTest, Test565) { 1025 SIMD_ALIGNED(uint8 orig_pixels[256][4]); 1026 SIMD_ALIGNED(uint8 pixels565[256][2]); 1027 1028 for (int i = 0; i < 256; ++i) { 1029 for (int j = 0; j < 4; ++j) { 1030 orig_pixels[i][j] = i; 1031 } 1032 } 1033 ARGBToRGB565(&orig_pixels[0][0], 0, &pixels565[0][0], 0, 256, 1); 1034 uint32 checksum = HashDjb2(&pixels565[0][0], sizeof(pixels565), 5381); 1035 EXPECT_EQ(610919429u, checksum); 1036 } 1037 1038 #ifdef HAVE_JPEG 1039 TEST_F(libyuvTest, ValidateJpeg) { 1040 const int kOff = 10; 1041 const int kMinJpeg = 64; 1042 const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ? 1043 benchmark_width_ * benchmark_height_ : kMinJpeg; 1044 const int kSize = kImageSize + kOff; 1045 align_buffer_64(orig_pixels, kSize); 1046 1047 // No SOI or EOI. Expect fail. 1048 memset(orig_pixels, 0, kSize); 1049 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize)); 1050 1051 // EOI, SOI. Expect pass. 1052 orig_pixels[0] = 0xff; 1053 orig_pixels[1] = 0xd8; // SOI. 1054 orig_pixels[kSize - kOff + 0] = 0xff; 1055 orig_pixels[kSize - kOff + 1] = 0xd9; // EOI. 1056 for (int times = 0; times < benchmark_iterations_; ++times) { 1057 EXPECT_TRUE(ValidateJpeg(orig_pixels, kSize)); 1058 } 1059 free_aligned_buffer_page_end(orig_pixels); 1060 } 1061 1062 TEST_F(libyuvTest, InvalidateJpeg) { 1063 const int kOff = 10; 1064 const int kMinJpeg = 64; 1065 const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ? 1066 benchmark_width_ * benchmark_height_ : kMinJpeg; 1067 const int kSize = kImageSize + kOff; 1068 align_buffer_64(orig_pixels, kSize); 1069 1070 // No SOI or EOI. Expect fail. 1071 memset(orig_pixels, 0, kSize); 1072 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize)); 1073 1074 // SOI but no EOI. Expect fail. 1075 orig_pixels[0] = 0xff; 1076 orig_pixels[1] = 0xd8; // SOI. 1077 for (int times = 0; times < benchmark_iterations_; ++times) { 1078 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize)); 1079 } 1080 // EOI but no SOI. Expect fail. 1081 orig_pixels[0] = 0; 1082 orig_pixels[1] = 0; 1083 orig_pixels[kSize - kOff + 0] = 0xff; 1084 orig_pixels[kSize - kOff + 1] = 0xd9; // EOI. 1085 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize)); 1086 1087 free_aligned_buffer_page_end(orig_pixels); 1088 } 1089 1090 TEST_F(libyuvTest, MJPGToI420) { 1091 const int kOff = 10; 1092 const int kMinJpeg = 64; 1093 const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ? 1094 benchmark_width_ * benchmark_height_ : kMinJpeg; 1095 const int kSize = kImageSize + kOff; 1096 align_buffer_64(orig_pixels, kSize); 1097 align_buffer_64(dst_y_opt, benchmark_width_ * benchmark_height_); 1098 align_buffer_64(dst_u_opt, 1099 SUBSAMPLE(benchmark_width_, 2) * 1100 SUBSAMPLE(benchmark_height_, 2)); 1101 align_buffer_64(dst_v_opt, 1102 SUBSAMPLE(benchmark_width_, 2) * 1103 SUBSAMPLE(benchmark_height_, 2)); 1104 1105 // EOI, SOI to make MJPG appear valid. 1106 memset(orig_pixels, 0, kSize); 1107 orig_pixels[0] = 0xff; 1108 orig_pixels[1] = 0xd8; // SOI. 1109 orig_pixels[kSize - kOff + 0] = 0xff; 1110 orig_pixels[kSize - kOff + 1] = 0xd9; // EOI. 1111 1112 for (int times = 0; times < benchmark_iterations_; ++times) { 1113 int ret = MJPGToI420(orig_pixels, kSize, 1114 dst_y_opt, benchmark_width_, 1115 dst_u_opt, SUBSAMPLE(benchmark_width_, 2), 1116 dst_v_opt, SUBSAMPLE(benchmark_width_, 2), 1117 benchmark_width_, benchmark_height_, 1118 benchmark_width_, benchmark_height_); 1119 // Expect failure because image is not really valid. 1120 EXPECT_EQ(1, ret); 1121 } 1122 1123 free_aligned_buffer_page_end(dst_y_opt); 1124 free_aligned_buffer_page_end(dst_u_opt); 1125 free_aligned_buffer_page_end(dst_v_opt); 1126 free_aligned_buffer_page_end(orig_pixels); 1127 } 1128 1129 TEST_F(libyuvTest, MJPGToARGB) { 1130 const int kOff = 10; 1131 const int kMinJpeg = 64; 1132 const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ? 1133 benchmark_width_ * benchmark_height_ : kMinJpeg; 1134 const int kSize = kImageSize + kOff; 1135 align_buffer_64(orig_pixels, kSize); 1136 align_buffer_64(dst_argb_opt, benchmark_width_ * benchmark_height_ * 4); 1137 1138 // EOI, SOI to make MJPG appear valid. 1139 memset(orig_pixels, 0, kSize); 1140 orig_pixels[0] = 0xff; 1141 orig_pixels[1] = 0xd8; // SOI. 1142 orig_pixels[kSize - kOff + 0] = 0xff; 1143 orig_pixels[kSize - kOff + 1] = 0xd9; // EOI. 1144 1145 for (int times = 0; times < benchmark_iterations_; ++times) { 1146 int ret = MJPGToARGB(orig_pixels, kSize, 1147 dst_argb_opt, benchmark_width_ * 4, 1148 benchmark_width_, benchmark_height_, 1149 benchmark_width_, benchmark_height_); 1150 // Expect failure because image is not really valid. 1151 EXPECT_EQ(1, ret); 1152 } 1153 1154 free_aligned_buffer_page_end(dst_argb_opt); 1155 free_aligned_buffer_page_end(orig_pixels); 1156 } 1157 1158 #endif // HAVE_JPEG 1159 1160 TEST_F(libyuvTest, CropNV12) { 1161 const int SUBSAMP_X = 2; 1162 const int SUBSAMP_Y = 2; 1163 const int kWidth = benchmark_width_; 1164 const int kHeight = benchmark_height_; 1165 const int crop_y = 1166 (benchmark_height_ - (benchmark_height_ * 360 / 480)) / 2; 1167 const int kDestWidth = benchmark_width_; 1168 const int kDestHeight = benchmark_height_ - crop_y * 2;; 1169 const int sample_size = kWidth * kHeight + 1170 SUBSAMPLE(kWidth, SUBSAMP_X) * 1171 SUBSAMPLE(kHeight, SUBSAMP_Y) * 2; 1172 align_buffer_64(src_y, sample_size); 1173 uint8* src_uv = src_y + kWidth * kHeight; 1174 1175 align_buffer_64(dst_y, kDestWidth * kDestHeight); 1176 align_buffer_64(dst_u, 1177 SUBSAMPLE(kDestWidth, SUBSAMP_X) * 1178 SUBSAMPLE(kDestHeight, SUBSAMP_Y)); 1179 align_buffer_64(dst_v, 1180 SUBSAMPLE(kDestWidth, SUBSAMP_X) * 1181 SUBSAMPLE(kDestHeight, SUBSAMP_Y)); 1182 1183 align_buffer_64(dst_y_2, kDestWidth * kDestHeight); 1184 align_buffer_64(dst_u_2, 1185 SUBSAMPLE(kDestWidth, SUBSAMP_X) * 1186 SUBSAMPLE(kDestHeight, SUBSAMP_Y)); 1187 align_buffer_64(dst_v_2, 1188 SUBSAMPLE(kDestWidth, SUBSAMP_X) * 1189 SUBSAMPLE(kDestHeight, SUBSAMP_Y)); 1190 1191 srandom(time(NULL)); 1192 for (int i = 0; i < kHeight; ++i) 1193 for (int j = 0; j < kWidth; ++j) 1194 src_y[(i * kWidth) + j] = (random() & 0xff); 1195 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { 1196 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { 1197 src_uv[(i * SUBSAMPLE(kWidth, SUBSAMP_X)) + j * 2 + 0] = 1198 (random() & 0xff); 1199 src_uv[(i * SUBSAMPLE(kWidth, SUBSAMP_X)) + j * 2 + 1] = 1200 (random() & 0xff); 1201 } 1202 } 1203 memset(dst_y, 1, kDestWidth * kDestHeight); 1204 memset(dst_u, 2, SUBSAMPLE(kDestWidth, SUBSAMP_X) * 1205 SUBSAMPLE(kDestHeight, SUBSAMP_Y)); 1206 memset(dst_v, 3, SUBSAMPLE(kDestWidth, SUBSAMP_X) * 1207 SUBSAMPLE(kDestHeight, SUBSAMP_Y)); 1208 memset(dst_y_2, 1, kDestWidth * kDestHeight); 1209 memset(dst_u_2, 2, SUBSAMPLE(kDestWidth, SUBSAMP_X) * 1210 SUBSAMPLE(kDestHeight, SUBSAMP_Y)); 1211 memset(dst_v_2, 3, SUBSAMPLE(kDestWidth, SUBSAMP_X) * 1212 SUBSAMPLE(kDestHeight, SUBSAMP_Y)); 1213 1214 NV12ToI420(src_y + crop_y * kWidth, kWidth, 1215 src_uv + (crop_y / 2) * kWidth, kWidth, 1216 dst_y, kDestWidth, 1217 dst_u, SUBSAMPLE(kDestWidth, SUBSAMP_X), 1218 dst_v, SUBSAMPLE(kDestWidth, SUBSAMP_X), 1219 kDestWidth, kDestHeight); 1220 1221 ConvertToI420(src_y, sample_size, 1222 dst_y_2, kDestWidth, 1223 dst_u_2, SUBSAMPLE(kDestWidth, SUBSAMP_X), 1224 dst_v_2, SUBSAMPLE(kDestWidth, SUBSAMP_X), 1225 0, crop_y, 1226 kWidth, kHeight, 1227 kDestWidth, kDestHeight, 1228 libyuv::kRotate0, libyuv::FOURCC_NV12); 1229 1230 for (int i = 0; i < kDestHeight; ++i) { 1231 for (int j = 0; j < kDestWidth; ++j) { 1232 EXPECT_EQ(dst_y[i * kWidth + j], dst_y_2[i * kWidth + j]); 1233 } 1234 } 1235 for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) { 1236 for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) { 1237 EXPECT_EQ(dst_u[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j], 1238 dst_u_2[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]); 1239 } 1240 } 1241 for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) { 1242 for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) { 1243 EXPECT_EQ(dst_v[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j], 1244 dst_v_2[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]); 1245 } 1246 } 1247 free_aligned_buffer_64(dst_y); 1248 free_aligned_buffer_64(dst_u); 1249 free_aligned_buffer_64(dst_v); 1250 free_aligned_buffer_64(dst_y_2); 1251 free_aligned_buffer_64(dst_u_2); 1252 free_aligned_buffer_64(dst_v_2); 1253 free_aligned_buffer_64(src_y); 1254 } 1255 1256 TEST_F(libyuvTest, HaveJPEG) { 1257 #ifdef HAVE_JPEG 1258 printf("JPEG enabled\n."); 1259 #else 1260 printf("JPEG disabled\n."); 1261 #endif 1262 } 1263 1264 } // namespace libyuv 1265