| OLD | NEW |
| (Empty) |
| 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 "media/base/simd/convert_rgb_to_yuv.h" | |
| 6 | |
| 7 #include <stdint.h> | |
| 8 | |
| 9 #include <memory> | |
| 10 | |
| 11 #include "base/cpu.h" | |
| 12 #include "testing/gtest/include/gtest/gtest.h" | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 // Reference code that converts RGB pixels to YUV pixels. | |
| 17 int ConvertRGBToY(const uint8_t* rgb) { | |
| 18 int y = 25 * rgb[0] + 129 * rgb[1] + 66 * rgb[2]; | |
| 19 y = ((y + 128) >> 8) + 16; | |
| 20 return std::max(0, std::min(255, y)); | |
| 21 } | |
| 22 | |
| 23 int ConvertRGBToU(const uint8_t* rgb, int size) { | |
| 24 int u = 112 * rgb[0] - 74 * rgb[1] - 38 * rgb[2]; | |
| 25 u = ((u + 128) >> 8) + 128; | |
| 26 return std::max(0, std::min(255, u)); | |
| 27 } | |
| 28 | |
| 29 int ConvertRGBToV(const uint8_t* rgb, int size) { | |
| 30 int v = -18 * rgb[0] - 94 * rgb[1] + 112 * rgb[2]; | |
| 31 v = ((v + 128) >> 8) + 128; | |
| 32 return std::max(0, std::min(255, v)); | |
| 33 } | |
| 34 | |
| 35 } // namespace | |
| 36 | |
| 37 // Assembly code confuses MemorySanitizer. Do not run it in MSan builds. | |
| 38 #if defined(MEMORY_SANITIZER) | |
| 39 #define MAYBE_SideBySideRGB DISABLED_SideBySideRGB | |
| 40 #else | |
| 41 #define MAYBE_SideBySideRGB SideBySideRGB | |
| 42 #endif | |
| 43 | |
| 44 // A side-by-side test that verifies our ASM functions that convert RGB pixels | |
| 45 // to YUV pixels can output the expected results. This test converts RGB pixels | |
| 46 // to YUV pixels with our ASM functions (which use SSE, SSE2, SSE3, and SSSE3) | |
| 47 // and compare the output YUV pixels with the ones calculated with out reference | |
| 48 // functions implemented in C++. | |
| 49 TEST(YUVConvertTest, MAYBE_SideBySideRGB) { | |
| 50 // We skip this test on PCs which does not support SSE3 because this test | |
| 51 // needs it. | |
| 52 base::CPU cpu; | |
| 53 if (!cpu.has_ssse3()) | |
| 54 return; | |
| 55 | |
| 56 // This test checks a subset of all RGB values so this test does not take so | |
| 57 // long time. | |
| 58 const int kStep = 8; | |
| 59 const int kWidth = 256 / kStep; | |
| 60 | |
| 61 for (int size = 3; size <= 4; ++size) { | |
| 62 // Create the output buffers. | |
| 63 std::unique_ptr<uint8_t[]> rgb(new uint8_t[kWidth * size]); | |
| 64 std::unique_ptr<uint8_t[]> y(new uint8_t[kWidth]); | |
| 65 std::unique_ptr<uint8_t[]> u(new uint8_t[kWidth / 2]); | |
| 66 std::unique_ptr<uint8_t[]> v(new uint8_t[kWidth / 2]); | |
| 67 | |
| 68 // Choose the function that converts from RGB pixels to YUV ones. | |
| 69 void (*convert)(const uint8_t*, uint8_t*, uint8_t*, uint8_t*, int, int, int, | |
| 70 int, int) = NULL; | |
| 71 if (size == 3) | |
| 72 convert = media::ConvertRGB24ToYUV_SSSE3; | |
| 73 else | |
| 74 convert = media::ConvertRGB32ToYUV_SSSE3; | |
| 75 | |
| 76 int total_error = 0; | |
| 77 for (int r = 0; r < kWidth; ++r) { | |
| 78 for (int g = 0; g < kWidth; ++g) { | |
| 79 | |
| 80 // Fill the input pixels. | |
| 81 for (int b = 0; b < kWidth; ++b) { | |
| 82 rgb[b * size + 0] = b * kStep; | |
| 83 rgb[b * size + 1] = g * kStep; | |
| 84 rgb[b * size + 2] = r * kStep; | |
| 85 if (size == 4) | |
| 86 rgb[b * size + 3] = 255; | |
| 87 } | |
| 88 | |
| 89 // Convert the input RGB pixels to YUV ones. | |
| 90 convert(rgb.get(), y.get(), u.get(), v.get(), kWidth, 1, kWidth * size, | |
| 91 kWidth, kWidth / 2); | |
| 92 | |
| 93 // Check the output Y pixels. | |
| 94 for (int i = 0; i < kWidth; ++i) { | |
| 95 const uint8_t* p = &rgb[i * size]; | |
| 96 int error = ConvertRGBToY(p) - y[i]; | |
| 97 total_error += error > 0 ? error : -error; | |
| 98 } | |
| 99 | |
| 100 // Check the output U pixels. | |
| 101 for (int i = 0; i < kWidth / 2; ++i) { | |
| 102 const uint8_t* p = &rgb[i * 2 * size]; | |
| 103 int error = ConvertRGBToU(p, size) - u[i]; | |
| 104 total_error += error > 0 ? error : -error; | |
| 105 } | |
| 106 | |
| 107 // Check the output V pixels. | |
| 108 for (int i = 0; i < kWidth / 2; ++i) { | |
| 109 const uint8_t* p = &rgb[i * 2 * size]; | |
| 110 int error = ConvertRGBToV(p, size) - v[i]; | |
| 111 total_error += error > 0 ? error : -error; | |
| 112 } | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 EXPECT_EQ(0, total_error); | |
| 117 } | |
| 118 } | |
| OLD | NEW |