- add sources.
[platform/framework/web/crosswalk.git] / src / media / base / simd / convert_rgb_to_yuv_unittest.cc
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.
4
5 #include "base/cpu.h"
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"
9
10 namespace {
11
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));
17 }
18
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));
23 }
24
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));
29 }
30
31 }  // namespace
32
33 // A side-by-side test that verifies our ASM functions that convert RGB pixels
34 // to YUV pixels can output the expected results. This test converts RGB pixels
35 // to YUV pixels with our ASM functions (which use SSE, SSE2, SSE3, and SSSE3)
36 // and compare the output YUV pixels with the ones calculated with out reference
37 // functions implemented in C++.
38 TEST(YUVConvertTest, SideBySideRGB) {
39   // We skip this test on PCs which does not support SSE3 because this test
40   // needs it.
41   base::CPU cpu;
42   if (!cpu.has_ssse3())
43     return;
44
45   // This test checks a subset of all RGB values so this test does not take so
46   // long time.
47   const int kStep = 8;
48   const int kWidth = 256 / kStep;
49
50   for (int size = 3; size <= 4; ++size) {
51     // Create the output buffers.
52     scoped_ptr<uint8[]> rgb(new uint8[kWidth * size]);
53     scoped_ptr<uint8[]> y(new uint8[kWidth]);
54     scoped_ptr<uint8[]> u(new uint8[kWidth / 2]);
55     scoped_ptr<uint8[]> v(new uint8[kWidth / 2]);
56
57     // Choose the function that converts from RGB pixels to YUV ones.
58     void (*convert)(const uint8*, uint8*, uint8*, uint8*,
59                     int, int, int, int, int) = NULL;
60     if (size == 3)
61       convert = media::ConvertRGB24ToYUV_SSSE3;
62     else
63       convert = media::ConvertRGB32ToYUV_SSSE3;
64
65     int total_error = 0;
66     for (int r = 0; r < kWidth; ++r) {
67       for (int g = 0; g < kWidth; ++g) {
68
69         // Fill the input pixels.
70         for (int b = 0; b < kWidth; ++b) {
71           rgb[b * size + 0] = b * kStep;
72           rgb[b * size + 1] = g * kStep;
73           rgb[b * size + 2] = r * kStep;
74           if (size == 4)
75             rgb[b * size + 3] = 255;
76         }
77
78         // Convert the input RGB pixels to YUV ones.
79         convert(rgb.get(), y.get(), u.get(), v.get(), kWidth, 1, kWidth * size,
80                 kWidth, kWidth / 2);
81
82         // Check the output Y pixels.
83         for (int i = 0; i < kWidth; ++i) {
84           const uint8* p = &rgb[i * size];
85           int error = ConvertRGBToY(p) - y[i];
86           total_error += error > 0 ? error : -error;
87         }
88
89         // Check the output U pixels.
90         for (int i = 0; i < kWidth / 2; ++i) {
91           const uint8* p = &rgb[i * 2 * size];
92           int error = ConvertRGBToU(p, size) - u[i];
93           total_error += error > 0 ? error : -error;
94         }
95
96         // Check the output V pixels.
97         for (int i = 0; i < kWidth / 2; ++i) {
98           const uint8* p = &rgb[i * 2 * size];
99           int error = ConvertRGBToV(p, size) - v[i];
100           total_error += error > 0 ? error : -error;
101         }
102       }
103     }
104
105     EXPECT_EQ(0, total_error);
106   }
107 }