OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include <stdint.h> | |
6 | |
7 #include <memory> | |
8 | |
9 #include "base/base_paths.h" | |
10 #include "base/cpu.h" | |
11 #include "base/files/file_util.h" | |
12 #include "base/logging.h" | |
13 #include "base/macros.h" | |
14 #include "base/path_service.h" | |
15 #include "base/time/time.h" | |
16 #include "build/build_config.h" | |
17 #include "media/base/simd/convert_yuv_to_rgb.h" | |
18 #include "media/base/yuv_convert.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | |
20 #include "testing/perf/perf_test.h" | |
21 #include "third_party/libyuv/include/libyuv/row.h" | |
22 | |
23 namespace media { | |
24 #if !defined(ARCH_CPU_ARM_FAMILY) && !defined(ARCH_CPU_MIPS_FAMILY) | |
25 // Size of raw image. | |
26 static const int kSourceWidth = 640; | |
27 static const int kSourceHeight = 360; | |
28 static const int kSourceYSize = kSourceWidth * kSourceHeight; | |
29 static const int kSourceUOffset = kSourceYSize; | |
30 static const int kSourceVOffset = kSourceYSize * 5 / 4; | |
31 static const int kBpp = 4; | |
32 | |
33 // Width of the row to convert. Odd so that we exercise the ending | |
34 // one-pixel-leftover case. | |
35 static const int kWidth = 639; | |
36 | |
37 // Surface sizes for various test files. | |
38 static const int kYUV12Size = kSourceYSize * 12 / 8; | |
39 static const int kRGBSize = kSourceYSize * kBpp; | |
40 | |
41 static const int kPerfTestIterations = 2000; | |
42 | |
43 class YUVConvertPerfTest : public testing::Test { | |
44 public: | |
45 YUVConvertPerfTest() | |
46 : yuv_bytes_(new uint8_t[kYUV12Size]), | |
47 rgb_bytes_converted_(new uint8_t[kRGBSize]) { | |
48 base::FilePath path; | |
49 CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &path)); | |
50 path = path.Append(FILE_PATH_LITERAL("media")) | |
51 .Append(FILE_PATH_LITERAL("test")) | |
52 .Append(FILE_PATH_LITERAL("data")) | |
53 .Append(FILE_PATH_LITERAL("bali_640x360_P420.yuv")); | |
54 | |
55 // Verify file size is correct. | |
56 int64_t actual_size = 0; | |
57 base::GetFileSize(path, &actual_size); | |
58 CHECK_EQ(actual_size, kYUV12Size); | |
59 | |
60 // Verify bytes read are correct. | |
61 int bytes_read = base::ReadFile( | |
62 path, reinterpret_cast<char*>(yuv_bytes_.get()), kYUV12Size); | |
63 | |
64 CHECK_EQ(bytes_read, kYUV12Size); | |
65 } | |
66 | |
67 std::unique_ptr<uint8_t[]> yuv_bytes_; | |
68 std::unique_ptr<uint8_t[]> rgb_bytes_converted_; | |
69 | |
70 private: | |
71 DISALLOW_COPY_AND_ASSIGN(YUVConvertPerfTest); | |
72 }; | |
73 | |
74 TEST_F(YUVConvertPerfTest, ConvertYUVToRGB32Row_SSE) { | |
75 ASSERT_TRUE(base::CPU().has_sse()); | |
76 | |
77 base::TimeTicks start = base::TimeTicks::Now(); | |
78 for (int i = 0; i < kPerfTestIterations; ++i) { | |
79 for (int row = 0; row < kSourceHeight; ++row) { | |
80 int chroma_row = row / 2; | |
81 ConvertYUVToRGB32Row_SSE( | |
82 yuv_bytes_.get() + row * kSourceWidth, | |
83 yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2), | |
84 yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2), | |
85 rgb_bytes_converted_.get(), | |
86 kWidth, | |
87 GetLookupTable(YV12)); | |
88 } | |
89 } | |
90 media::EmptyRegisterState(); | |
91 double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF(); | |
92 perf_test::PrintResult( | |
93 "yuv_convert_perftest", "", "ConvertYUVToRGB32Row_SSE", | |
94 kPerfTestIterations / total_time_seconds, "runs/s", true); | |
95 } | |
96 | |
97 #ifdef HAS_I422TOARGBROW_SSSE3 | |
98 TEST_F(YUVConvertPerfTest, I422ToARGBRow_SSSE3) { | |
99 ASSERT_TRUE(base::CPU().has_ssse3()); | |
100 | |
101 base::TimeTicks start = base::TimeTicks::Now(); | |
102 for (int i = 0; i < kPerfTestIterations; ++i) { | |
103 for (int row = 0; row < kSourceHeight; ++row) { | |
104 int chroma_row = row / 2; | |
105 libyuv::I422ToARGBRow_SSSE3( | |
106 yuv_bytes_.get() + row * kSourceWidth, | |
107 yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2), | |
108 yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2), | |
109 rgb_bytes_converted_.get(), &libyuv::kYuvI601Constants, kWidth); | |
110 } | |
111 } | |
112 double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF(); | |
113 perf_test::PrintResult("yuv_convert_perftest", "", "I422ToARGBRow_SSSE3", | |
114 kPerfTestIterations / total_time_seconds, "runs/s", | |
115 true); | |
116 } | |
117 #endif | |
118 | |
119 TEST_F(YUVConvertPerfTest, ConvertYUVAToARGBRow_MMX) { | |
120 ASSERT_TRUE(base::CPU().has_sse()); | |
121 | |
122 base::TimeTicks start = base::TimeTicks::Now(); | |
123 for (int i = 0; i < kPerfTestIterations; ++i) { | |
124 for (int row = 0; row < kSourceHeight; ++row) { | |
125 int chroma_row = row / 2; | |
126 ConvertYUVAToARGBRow_MMX( | |
127 yuv_bytes_.get() + row * kSourceWidth, | |
128 yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2), | |
129 yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2), | |
130 yuv_bytes_.get() + row * kSourceWidth, // hack: use luma for alpha | |
131 rgb_bytes_converted_.get(), kWidth, GetLookupTable(YV12)); | |
132 } | |
133 } | |
134 media::EmptyRegisterState(); | |
135 double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF(); | |
136 perf_test::PrintResult("yuv_convert_perftest", "", "ConvertYUVAToARGBRow_MMX", | |
137 kPerfTestIterations / total_time_seconds, "runs/s", | |
138 true); | |
139 } | |
140 | |
141 #ifdef HAS_I422ALPHATOARGBROW_SSSE3 | |
142 TEST_F(YUVConvertPerfTest, I422AlphaToARGBRow_SSSE3) { | |
143 ASSERT_TRUE(base::CPU().has_ssse3()); | |
144 | |
145 base::TimeTicks start = base::TimeTicks::Now(); | |
146 for (int i = 0; i < kPerfTestIterations; ++i) { | |
147 for (int row = 0; row < kSourceHeight; ++row) { | |
148 int chroma_row = row / 2; | |
149 libyuv::I422AlphaToARGBRow_SSSE3( | |
150 yuv_bytes_.get() + row * kSourceWidth, | |
151 yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2), | |
152 yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2), | |
153 yuv_bytes_.get() + row * kSourceWidth, // hack: use luma for alpha | |
154 rgb_bytes_converted_.get(), &libyuv::kYuvI601Constants, kWidth); | |
155 } | |
156 } | |
157 double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF(); | |
158 perf_test::PrintResult("yuv_convert_perftest", "", "I422AlphaToARGBRow_SSSE3", | |
159 kPerfTestIterations / total_time_seconds, "runs/s", | |
160 true); | |
161 } | |
162 #endif | |
163 | |
164 // 64-bit release + component builds on Windows are too smart and optimizes | |
165 // away the function being tested. | |
166 #if defined(OS_WIN) && (defined(ARCH_CPU_X86) || !defined(COMPONENT_BUILD)) | |
167 TEST_F(YUVConvertPerfTest, ScaleYUVToRGB32Row_SSE) { | |
168 ASSERT_TRUE(base::CPU().has_sse()); | |
169 | |
170 const int kSourceDx = 80000; // This value means a scale down. | |
171 | |
172 base::TimeTicks start = base::TimeTicks::Now(); | |
173 for (int i = 0; i < kPerfTestIterations; ++i) { | |
174 for (int row = 0; row < kSourceHeight; ++row) { | |
175 int chroma_row = row / 2; | |
176 ScaleYUVToRGB32Row_SSE( | |
177 yuv_bytes_.get() + row * kSourceWidth, | |
178 yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2), | |
179 yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2), | |
180 rgb_bytes_converted_.get(), | |
181 kWidth, | |
182 kSourceDx, | |
183 GetLookupTable(YV12)); | |
184 } | |
185 } | |
186 media::EmptyRegisterState(); | |
187 double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF(); | |
188 perf_test::PrintResult( | |
189 "yuv_convert_perftest", "", "ScaleYUVToRGB32Row_SSE", | |
190 kPerfTestIterations / total_time_seconds, "runs/s", true); | |
191 } | |
192 | |
193 TEST_F(YUVConvertPerfTest, LinearScaleYUVToRGB32Row_SSE) { | |
194 ASSERT_TRUE(base::CPU().has_sse()); | |
195 | |
196 const int kSourceDx = 80000; // This value means a scale down. | |
197 | |
198 base::TimeTicks start = base::TimeTicks::Now(); | |
199 for (int i = 0; i < kPerfTestIterations; ++i) { | |
200 for (int row = 0; row < kSourceHeight; ++row) { | |
201 int chroma_row = row / 2; | |
202 LinearScaleYUVToRGB32Row_SSE( | |
203 yuv_bytes_.get() + row * kSourceWidth, | |
204 yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2), | |
205 yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2), | |
206 rgb_bytes_converted_.get(), | |
207 kWidth, | |
208 kSourceDx, | |
209 GetLookupTable(YV12)); | |
210 } | |
211 } | |
212 media::EmptyRegisterState(); | |
213 double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF(); | |
214 perf_test::PrintResult( | |
215 "yuv_convert_perftest", "", "LinearScaleYUVToRGB32Row_SSE", | |
216 kPerfTestIterations / total_time_seconds, "runs/s", true); | |
217 } | |
218 #endif // defined(OS_WIN) && (ARCH_CPU_X86 || COMPONENT_BUILD) | |
219 | |
220 #endif // !defined(ARCH_CPU_ARM_FAMILY) && !defined(ARCH_CPU_MIPS_FAMILY) | |
221 | |
222 } // namespace media | |
OLD | NEW |