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/cpu_id.h" 15#include "libyuv/scale_argb.h" 16#include "../unit_test/unit_test.h" 17 18namespace libyuv { 19 20static int ARGBTestFilter(int src_width, int src_height, 21 int dst_width, int dst_height, 22 FilterMode f, int benchmark_iterations) { 23 const int b = 128; 24 int src_argb_plane_size = (src_width + b * 2) * (src_height + b * 2) * 4; 25 int src_stride_argb = (b * 2 + src_width) * 4; 26 27 align_buffer_16(src_argb, src_argb_plane_size) 28 memset(src_argb, 1, src_argb_plane_size); 29 30 int dst_argb_plane_size = (dst_width + b * 2) * (dst_height + b * 2) * 4; 31 int dst_stride_argb = (b * 2 + dst_width) * 4; 32 33 srandom(time(NULL)); 34 35 int i, j; 36 for (i = b; i < (src_height + b); ++i) { 37 for (j = b; j < (src_width + b) * 4; ++j) { 38 src_argb[(i * src_stride_argb) + j] = (random() & 0xff); 39 } 40 } 41 42 align_buffer_16(dst_argb_c, dst_argb_plane_size) 43 align_buffer_16(dst_argb_opt, dst_argb_plane_size) 44 memset(dst_argb_c, 2, dst_argb_plane_size); 45 memset(dst_argb_opt, 3, dst_argb_plane_size); 46 47 // Warm up both versions for consistent benchmarks. 48 MaskCpuFlags(0); // Disable all CPU optimization. 49 ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb, 50 src_width, src_height, 51 dst_argb_c + (dst_stride_argb * b) + b * 4, dst_stride_argb, 52 dst_width, dst_height, f); 53 MaskCpuFlags(-1); // Enable all CPU optimization. 54 ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb, 55 src_width, src_height, 56 dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb, 57 dst_width, dst_height, f); 58 59 MaskCpuFlags(0); // Disable all CPU optimization. 60 double c_time = get_time(); 61 for (i = 0; i < benchmark_iterations; ++i) { 62 ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb, 63 src_width, src_height, 64 dst_argb_c + (dst_stride_argb * b) + b * 4, dst_stride_argb, 65 dst_width, dst_height, f); 66 } 67 c_time = (get_time() - c_time) / benchmark_iterations; 68 69 MaskCpuFlags(-1); // Enable all CPU optimization. 70 double opt_time = get_time(); 71 for (i = 0; i < benchmark_iterations; ++i) { 72 ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb, 73 src_width, src_height, 74 dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb, 75 dst_width, dst_height, f); 76 } 77 opt_time = (get_time() - opt_time) / benchmark_iterations; 78 79 // Report performance of C vs OPT 80 printf("filter %d - %8d us C - %8d us OPT\n", 81 f, static_cast<int>(c_time*1e6), static_cast<int>(opt_time*1e6)); 82 83 // C version may be a little off from the optimized. Order of 84 // operations may introduce rounding somewhere. So do a difference 85 // of the buffers and look to see that the max difference isn't 86 // over 2. 87 int max_diff = 0; 88 for (i = b; i < (dst_height + b); ++i) { 89 for (j = b * 4; j < (dst_width + b) * 4; ++j) { 90 int abs_diff = abs(dst_argb_c[(i * dst_stride_argb) + j] - 91 dst_argb_opt[(i * dst_stride_argb) + j]); 92 if (abs_diff > max_diff) { 93 max_diff = abs_diff; 94 } 95 } 96 } 97 98 free_aligned_buffer_16(dst_argb_c) 99 free_aligned_buffer_16(dst_argb_opt) 100 free_aligned_buffer_16(src_argb) 101 return max_diff; 102} 103 104TEST_F(libyuvTest, ARGBScaleDownBy2) { 105 const int src_width = 1280; 106 const int src_height = 720; 107 const int dst_width = src_width / 2; 108 const int dst_height = src_height / 2; 109 110 for (int f = 0; f < 2; ++f) { 111 int max_diff = ARGBTestFilter(src_width, src_height, 112 dst_width, dst_height, 113 static_cast<FilterMode>(f), 114 benchmark_iterations_); 115 EXPECT_LE(max_diff, 1); 116 } 117} 118 119TEST_F(libyuvTest, ARGBScaleDownBy4) { 120 const int src_width = 1280; 121 const int src_height = 720; 122 const int dst_width = src_width / 4; 123 const int dst_height = src_height / 4; 124 125 for (int f = 0; f < 2; ++f) { 126 int max_diff = ARGBTestFilter(src_width, src_height, 127 dst_width, dst_height, 128 static_cast<FilterMode>(f), 129 benchmark_iterations_); 130 EXPECT_LE(max_diff, 1); 131 } 132} 133 134TEST_F(libyuvTest, ARGBScaleDownBy5) { 135 const int src_width = 1280; 136 const int src_height = 720; 137 const int dst_width = src_width / 5; 138 const int dst_height = src_height / 5; 139 140 for (int f = 0; f < 2; ++f) { 141 int max_diff = ARGBTestFilter(src_width, src_height, 142 dst_width, dst_height, 143 static_cast<FilterMode>(f), 144 benchmark_iterations_); 145 EXPECT_LE(max_diff, 1); 146 } 147} 148 149TEST_F(libyuvTest, ARGBScaleDownBy8) { 150 const int src_width = 1280; 151 const int src_height = 720; 152 const int dst_width = src_width / 8; 153 const int dst_height = src_height / 8; 154 155 for (int f = 0; f < 2; ++f) { 156 int max_diff = ARGBTestFilter(src_width, src_height, 157 dst_width, dst_height, 158 static_cast<FilterMode>(f), 159 benchmark_iterations_); 160 EXPECT_LE(max_diff, 1); 161 } 162} 163 164TEST_F(libyuvTest, ARGBScaleDownBy16) { 165 const int src_width = 1280; 166 const int src_height = 720; 167 const int dst_width = src_width / 16; 168 const int dst_height = src_height / 16; 169 170 for (int f = 0; f < 2; ++f) { 171 int max_diff = ARGBTestFilter(src_width, src_height, 172 dst_width, dst_height, 173 static_cast<FilterMode>(f), 174 benchmark_iterations_); 175 EXPECT_LE(max_diff, 1); 176 } 177} 178 179TEST_F(libyuvTest, ARGBScaleDownBy34) { 180 const int src_width = 1280; 181 const int src_height = 720; 182 const int dst_width = src_width * 3 / 4; 183 const int dst_height = src_height * 3 / 4; 184 185 for (int f = 0; f < 2; ++f) { 186 int max_diff = ARGBTestFilter(src_width, src_height, 187 dst_width, dst_height, 188 static_cast<FilterMode>(f), 189 benchmark_iterations_); 190 EXPECT_LE(max_diff, 1); 191 } 192} 193 194TEST_F(libyuvTest, ARGBScaleDownBy38) { 195 int src_width = 1280; 196 int src_height = 720; 197 int dst_width = src_width * 3 / 8; 198 int dst_height = src_height * 3 / 8; 199 200 for (int f = 0; f < 2; ++f) { 201 int max_diff = ARGBTestFilter(src_width, src_height, 202 dst_width, dst_height, 203 static_cast<FilterMode>(f), 204 benchmark_iterations_); 205 EXPECT_LE(max_diff, 1); 206 } 207} 208 209TEST_F(libyuvTest, ARGBScaleTo1366) { 210 int src_width = 1280; 211 int src_height = 720; 212 int dst_width = 1366; 213 int dst_height = 768; 214 215 for (int f = 0; f < 2; ++f) { 216 int max_diff = ARGBTestFilter(src_width, src_height, 217 dst_width, dst_height, 218 static_cast<FilterMode>(f), 219 benchmark_iterations_); 220 EXPECT_LE(max_diff, 1); 221 } 222} 223 224TEST_F(libyuvTest, ARGBScaleTo4074) { 225 int src_width = 2880 * 2; 226 int src_height = 1800; 227 int dst_width = 4074; 228 int dst_height = 1272; 229 230 for (int f = 0; f < 2; ++f) { 231 int max_diff = ARGBTestFilter(src_width, src_height, 232 dst_width, dst_height, 233 static_cast<FilterMode>(f), 234 benchmark_iterations_); 235 EXPECT_LE(max_diff, 1); 236 } 237} 238 239 240TEST_F(libyuvTest, ARGBScaleTo853) { 241 int src_width = 1280; 242 int src_height = 720; 243 int dst_width = 853; 244 int dst_height = 480; 245 246 for (int f = 0; f < 2; ++f) { 247 int max_diff = ARGBTestFilter(src_width, src_height, 248 dst_width, dst_height, 249 static_cast<FilterMode>(f), 250 benchmark_iterations_); 251 EXPECT_LE(max_diff, 1); 252 } 253} 254 255} // namespace libyuv 256