OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/cpu.h" | 5 #include "base/cpu.h" |
6 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
7 #include "media/base/simd/convert_rgb_to_yuv.h" | 7 #include "media/base/simd/convert_rgb_to_yuv.h" |
8 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
9 | 9 |
10 namespace { | 10 namespace { |
11 | 11 |
12 // Reference code that converts RGB pixels to YUV pixels. | 12 // Reference code that converts RGB pixels to YUV pixels. |
13 int ConvertRGBToY(const uint8* rgb) { | 13 int ConvertRGBToY(const uint8* rgb) { |
14 int y = 25 * rgb[0] + 129 * rgb[1] + 66 * rgb[2]; | 14 int y = 25 * rgb[0] + 129 * rgb[1] + 66 * rgb[2]; |
15 y = ((y + 128) >> 8) + 16; | 15 y = ((y + 128) >> 8) + 16; |
16 return std::max(0, std::min(255, y)); | 16 return std::max(0, std::min(255, y)); |
17 } | 17 } |
18 | 18 |
19 int ConvertRGBToU(const uint8* rgb, int size, bool subsampling) { | 19 int ConvertRGBToU(const uint8* rgb, int size) { |
20 int u = 0; | 20 int u = 112 * rgb[0] - 74 * rgb[1] - 38 * rgb[2]; |
21 if (!subsampling) { | |
22 u = 112 * rgb[0] - 74 * rgb[1] - 38 * rgb[2]; | |
23 } else { | |
24 int u0 = 112 * rgb[0] - 74 * rgb[1] - 38 * rgb[2]; | |
25 int u1 = 112 * rgb[size] - 74 * rgb[size + 1] - 38 * rgb[size + 2]; | |
26 u = (u0 + u1 + 1) / 2; | |
27 } | |
28 u = ((u + 128) >> 8) + 128; | 21 u = ((u + 128) >> 8) + 128; |
29 return std::max(0, std::min(255, u)); | 22 return std::max(0, std::min(255, u)); |
30 } | 23 } |
31 | 24 |
32 int ConvertRGBToV(const uint8* rgb, int size, bool subsampling) { | 25 int ConvertRGBToV(const uint8* rgb, int size) { |
33 int v = 0; | 26 int v = -18 * rgb[0] - 94 * rgb[1] + 112 * rgb[2]; |
34 if (!subsampling) { | |
35 v = -18 * rgb[0] - 94 * rgb[1] + 112 * rgb[2]; | |
36 } else { | |
37 int v0 = -18 * rgb[0] - 94 * rgb[1] + 112 * rgb[2]; | |
38 int v1 = -18 * rgb[size] - 94 * rgb[size + 1] + 112 * rgb[size + 2]; | |
39 v = (v0 + v1 + 1) / 2; | |
40 } | |
41 v = ((v + 128) >> 8) + 128; | 27 v = ((v + 128) >> 8) + 128; |
42 return std::max(0, std::min(255, v)); | 28 return std::max(0, std::min(255, v)); |
43 } | 29 } |
44 | 30 |
45 } // namespace | 31 } // namespace |
46 | 32 |
47 // A side-by-side test that verifies our ASM functions that convert RGB pixels | 33 // A side-by-side test that verifies our ASM functions that convert RGB pixels |
48 // to YUV pixels can output the expected results. This test converts RGB pixels | 34 // to YUV pixels can output the expected results. This test converts RGB pixels |
49 // to YUV pixels with our ASM functions (which use SSE, SSE2, SSE3, and SSSE3) | 35 // to YUV pixels with our ASM functions (which use SSE, SSE2, SSE3, and SSSE3) |
50 // and compare the output YUV pixels with the ones calculated with out reference | 36 // and compare the output YUV pixels with the ones calculated with out reference |
51 // functions implemented in C++. | 37 // functions implemented in C++. |
52 TEST(YUVConvertTest, SideBySideRGB) { | 38 TEST(YUVConvertTest, SideBySideRGB) { |
53 // We skip this test on PCs which does not support SSE3 because this test | 39 // We skip this test on PCs which does not support SSE3 because this test |
54 // needs it. | 40 // needs it. |
55 base::CPU cpu; | 41 base::CPU cpu; |
56 if (!cpu.has_ssse3()) | 42 if (!cpu.has_ssse3()) |
57 return; | 43 return; |
58 | 44 |
59 // This test checks a subset of all RGB values so this test does not take so | 45 // This test checks a subset of all RGB values so this test does not take so |
60 // long time. | 46 // long time. |
61 const int kStep = 8; | 47 const int kStep = 8; |
62 const int kWidth = 256 / kStep; | 48 const int kWidth = 256 / kStep; |
63 | 49 |
64 #ifdef ENABLE_SUBSAMPLING | |
65 const bool kSubsampling = true; | |
66 #else | |
67 const bool kSubsampling = false; | |
68 #endif | |
69 | |
70 for (int size = 3; size <= 4; ++size) { | 50 for (int size = 3; size <= 4; ++size) { |
71 // Create the output buffers. | 51 // Create the output buffers. |
72 scoped_array<uint8> rgb(new uint8[kWidth * size]); | 52 scoped_array<uint8> rgb(new uint8[kWidth * size]); |
73 scoped_array<uint8> y(new uint8[kWidth]); | 53 scoped_array<uint8> y(new uint8[kWidth]); |
74 scoped_array<uint8> u(new uint8[kWidth / 2]); | 54 scoped_array<uint8> u(new uint8[kWidth / 2]); |
75 scoped_array<uint8> v(new uint8[kWidth / 2]); | 55 scoped_array<uint8> v(new uint8[kWidth / 2]); |
76 | 56 |
77 // Choose the function that converts from RGB pixels to YUV ones. | 57 // Choose the function that converts from RGB pixels to YUV ones. |
78 void (*convert)(const uint8*, uint8*, uint8*, uint8*, | 58 void (*convert)(const uint8*, uint8*, uint8*, uint8*, |
79 int, int, int, int, int) = NULL; | 59 int, int, int, int, int) = NULL; |
(...skipping 22 matching lines...) Expand all Loading... |
102 // Check the output Y pixels. | 82 // Check the output Y pixels. |
103 for (int i = 0; i < kWidth; ++i) { | 83 for (int i = 0; i < kWidth; ++i) { |
104 const uint8* p = &rgb[i * size]; | 84 const uint8* p = &rgb[i * size]; |
105 int error = ConvertRGBToY(p) - y[i]; | 85 int error = ConvertRGBToY(p) - y[i]; |
106 total_error += error > 0 ? error : -error; | 86 total_error += error > 0 ? error : -error; |
107 } | 87 } |
108 | 88 |
109 // Check the output U pixels. | 89 // Check the output U pixels. |
110 for (int i = 0; i < kWidth / 2; ++i) { | 90 for (int i = 0; i < kWidth / 2; ++i) { |
111 const uint8* p = &rgb[i * 2 * size]; | 91 const uint8* p = &rgb[i * 2 * size]; |
112 int error = ConvertRGBToU(p, size, kSubsampling) - u[i]; | 92 int error = ConvertRGBToU(p, size) - u[i]; |
113 total_error += error > 0 ? error : -error; | 93 total_error += error > 0 ? error : -error; |
114 } | 94 } |
115 | 95 |
116 // Check the output V pixels. | 96 // Check the output V pixels. |
117 for (int i = 0; i < kWidth / 2; ++i) { | 97 for (int i = 0; i < kWidth / 2; ++i) { |
118 const uint8* p = &rgb[i * 2 * size]; | 98 const uint8* p = &rgb[i * 2 * size]; |
119 int error = ConvertRGBToV(p, size, kSubsampling) - v[i]; | 99 int error = ConvertRGBToV(p, size) - v[i]; |
120 total_error += error > 0 ? error : -error; | 100 total_error += error > 0 ? error : -error; |
121 } | 101 } |
122 } | 102 } |
123 } | 103 } |
124 | 104 |
125 EXPECT_EQ(0, total_error); | 105 EXPECT_EQ(0, total_error); |
126 } | 106 } |
127 } | 107 } |
OLD | NEW |