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
3 // found in the LICENSE file.
6 #include "base/memory/scoped_ptr.h"
7 #include "media/base/simd/convert_rgb_to_yuv.h"
8 #include "testing/gtest/include/gtest/gtest.h"
12 // Reference code that converts RGB pixels to YUV pixels.
13 int ConvertRGBToY(const uint8
* rgb
) {
14 int y
= 25 * rgb
[0] + 129 * rgb
[1] + 66 * rgb
[2];
15 y
= ((y
+ 128) >> 8) + 16;
16 return std::max(0, std::min(255, y
));
19 int ConvertRGBToU(const uint8
* rgb
, int size
) {
20 int u
= 112 * rgb
[0] - 74 * rgb
[1] - 38 * rgb
[2];
21 u
= ((u
+ 128) >> 8) + 128;
22 return std::max(0, std::min(255, u
));
25 int ConvertRGBToV(const uint8
* rgb
, int size
) {
26 int v
= -18 * rgb
[0] - 94 * rgb
[1] + 112 * rgb
[2];
27 v
= ((v
+ 128) >> 8) + 128;
28 return std::max(0, std::min(255, v
));
33 // Assembly code confuses MemorySanitizer. Do not run it in MSan builds.
34 #if defined(MEMORY_SANITIZER)
35 #define MAYBE_SideBySideRGB DISABLED_SideBySideRGB
37 #define MAYBE_SideBySideRGB SideBySideRGB
40 // A side-by-side test that verifies our ASM functions that convert RGB pixels
41 // to YUV pixels can output the expected results. This test converts RGB pixels
42 // to YUV pixels with our ASM functions (which use SSE, SSE2, SSE3, and SSSE3)
43 // and compare the output YUV pixels with the ones calculated with out reference
44 // functions implemented in C++.
45 TEST(YUVConvertTest
, MAYBE_SideBySideRGB
) {
46 // We skip this test on PCs which does not support SSE3 because this test
52 // This test checks a subset of all RGB values so this test does not take so
55 const int kWidth
= 256 / kStep
;
57 for (int size
= 3; size
<= 4; ++size
) {
58 // Create the output buffers.
59 scoped_ptr
<uint8
[]> rgb(new uint8
[kWidth
* size
]);
60 scoped_ptr
<uint8
[]> y(new uint8
[kWidth
]);
61 scoped_ptr
<uint8
[]> u(new uint8
[kWidth
/ 2]);
62 scoped_ptr
<uint8
[]> v(new uint8
[kWidth
/ 2]);
64 // Choose the function that converts from RGB pixels to YUV ones.
65 void (*convert
)(const uint8
*, uint8
*, uint8
*, uint8
*,
66 int, int, int, int, int) = NULL
;
68 convert
= media::ConvertRGB24ToYUV_SSSE3
;
70 convert
= media::ConvertRGB32ToYUV_SSSE3
;
73 for (int r
= 0; r
< kWidth
; ++r
) {
74 for (int g
= 0; g
< kWidth
; ++g
) {
76 // Fill the input pixels.
77 for (int b
= 0; b
< kWidth
; ++b
) {
78 rgb
[b
* size
+ 0] = b
* kStep
;
79 rgb
[b
* size
+ 1] = g
* kStep
;
80 rgb
[b
* size
+ 2] = r
* kStep
;
82 rgb
[b
* size
+ 3] = 255;
85 // Convert the input RGB pixels to YUV ones.
86 convert(rgb
.get(), y
.get(), u
.get(), v
.get(), kWidth
, 1, kWidth
* size
,
89 // Check the output Y pixels.
90 for (int i
= 0; i
< kWidth
; ++i
) {
91 const uint8
* p
= &rgb
[i
* size
];
92 int error
= ConvertRGBToY(p
) - y
[i
];
93 total_error
+= error
> 0 ? error
: -error
;
96 // Check the output U pixels.
97 for (int i
= 0; i
< kWidth
/ 2; ++i
) {
98 const uint8
* p
= &rgb
[i
* 2 * size
];
99 int error
= ConvertRGBToU(p
, size
) - u
[i
];
100 total_error
+= error
> 0 ? error
: -error
;
103 // Check the output V pixels.
104 for (int i
= 0; i
< kWidth
/ 2; ++i
) {
105 const uint8
* p
= &rgb
[i
* 2 * size
];
106 int error
= ConvertRGBToV(p
, size
) - v
[i
];
107 total_error
+= error
> 0 ? error
: -error
;
112 EXPECT_EQ(0, total_error
);