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_argb.h" 16 #include "../unit_test/unit_test.h" 17 18 namespace libyuv { 19 20 static int ARGBTestRotate(int src_width, int src_height, 21 int dst_width, int dst_height, 22 libyuv::RotationMode mode, int runs) { 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 ARGBRotate(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb, 50 dst_argb_c + (dst_stride_argb * b) + b * 4, dst_stride_argb, 51 src_width, src_height, mode); 52 MaskCpuFlags(-1); // Enable all CPU optimization. 53 ARGBRotate(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb, 54 dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb, 55 src_width, src_height, mode); 56 57 MaskCpuFlags(0); // Disable all CPU optimization. 58 double c_time = get_time(); 59 for (i = 0; i < runs; ++i) { 60 ARGBRotate(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb, 61 dst_argb_c + (dst_stride_argb * b) + b * 4, dst_stride_argb, 62 src_width, src_height, mode); 63 } 64 c_time = (get_time() - c_time) / runs; 65 66 MaskCpuFlags(-1); // Enable all CPU optimization. 67 double opt_time = get_time(); 68 for (i = 0; i < runs; ++i) { 69 ARGBRotate(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb, 70 dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb, 71 src_width, src_height, mode); 72 } 73 opt_time = (get_time() - opt_time) / runs; 74 75 // Report performance of C vs OPT 76 printf("filter %d - %8d us C - %8d us OPT\n", 77 mode, static_cast<int>(c_time*1e6), static_cast<int>(opt_time*1e6)); 78 79 // C version may be a little off from the optimized. Order of 80 // operations may introduce rounding somewhere. So do a difference 81 // of the buffers and look to see that the max difference isn't 82 // over 2. 83 int max_diff = 0; 84 for (i = b; i < (dst_height + b); ++i) { 85 for (j = b * 4; j < (dst_width + b) * 4; ++j) { 86 int abs_diff = abs(dst_argb_c[(i * dst_stride_argb) + j] - 87 dst_argb_opt[(i * dst_stride_argb) + j]); 88 if (abs_diff > max_diff) 89 max_diff = abs_diff; 90 } 91 } 92 93 free_aligned_buffer_16(dst_argb_c) 94 free_aligned_buffer_16(dst_argb_opt) 95 free_aligned_buffer_16(src_argb) 96 return max_diff; 97 } 98 99 TEST_F(libyuvTest, ARGBRotate0) { 100 const int src_width = 1280; 101 const int src_height = 720; 102 const int dst_width = 1280; 103 const int dst_height = 720; 104 105 int err = ARGBTestRotate(src_width, src_height, 106 dst_width, dst_height, kRotate0, 107 benchmark_iterations_); 108 EXPECT_GE(1, err); 109 } 110 111 TEST_F(libyuvTest, ARGBRotate90) { 112 const int src_width = 1280; 113 const int src_height = 720; 114 const int dst_width = 720; 115 const int dst_height = 1280; 116 117 int err = ARGBTestRotate(src_width, src_height, 118 dst_width, dst_height, kRotate90, 119 benchmark_iterations_); 120 EXPECT_GE(1, err); 121 } 122 123 TEST_F(libyuvTest, ARGBRotate180) { 124 const int src_width = 1280; 125 const int src_height = 720; 126 const int dst_width = 1280; 127 const int dst_height = 720; 128 129 int err = ARGBTestRotate(src_width, src_height, 130 dst_width, dst_height, kRotate180, 131 benchmark_iterations_); 132 EXPECT_GE(1, err); 133 } 134 135 TEST_F(libyuvTest, ARGBRotate270) { 136 const int src_width = 1280; 137 const int src_height = 720; 138 const int dst_width = 720; 139 const int dst_height = 1280; 140 141 int err = ARGBTestRotate(src_width, src_height, 142 dst_width, dst_height, kRotate270, 143 benchmark_iterations_); 144 EXPECT_GE(1, err); 145 } 146 147 TEST_F(libyuvTest, ARGBRotate0_Odd) { 148 const int src_width = 1277; 149 const int src_height = 719; 150 const int dst_width = 1277; 151 const int dst_height = 719; 152 153 int err = ARGBTestRotate(src_width, src_height, 154 dst_width, dst_height, kRotate0, 155 benchmark_iterations_); 156 EXPECT_GE(1, err); 157 } 158 159 TEST_F(libyuvTest, ARGBRotate90_Odd) { 160 const int src_width = 1277; 161 const int src_height = 719; 162 const int dst_width = 719; 163 const int dst_height = 1277; 164 165 int err = ARGBTestRotate(src_width, src_height, 166 dst_width, dst_height, kRotate90, 167 benchmark_iterations_); 168 EXPECT_GE(1, err); 169 } 170 171 TEST_F(libyuvTest, ARGBRotate180_Odd) { 172 const int src_width = 1277; 173 const int src_height = 719; 174 const int dst_width = 1277; 175 const int dst_height = 719; 176 177 int err = ARGBTestRotate(src_width, src_height, 178 dst_width, dst_height, kRotate180, 179 benchmark_iterations_); 180 EXPECT_GE(1, err); 181 } 182 183 TEST_F(libyuvTest, ARGBRotate270_Odd) { 184 const int src_width = 1277; 185 const int src_height = 719; 186 const int dst_width = 719; 187 const int dst_height = 1277; 188 189 int err = ARGBTestRotate(src_width, src_height, 190 dst_width, dst_height, kRotate270, 191 benchmark_iterations_); 192 EXPECT_GE(1, err); 193 } 194 195 } // namespace libyuv 196