Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(931)

Unified Diff: media/base/yuv_convert_unittest.cc

Issue 7003082: Implements RGB to YV12 conversion in YASM. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/base/yuv_convert_unittest.cc
===================================================================
--- media/base/yuv_convert_unittest.cc (revision 99154)
+++ media/base/yuv_convert_unittest.cc (working copy)
@@ -6,11 +6,68 @@
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
+#include "base/stringprintf.h"
#include "media/base/djb2.h"
#include "media/base/yuv_convert.h"
#include "media/base/yuv_row.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace {
+
+// Reference code that converts RGB pixels to YUV pixels.
+int ConvertRGBToY(const uint8* rgb) {
+ int y = 25 * rgb[0] + 129 * rgb[1] + 66 * rgb[2];
+ y = ((y + 128) >> 8) + 16;
+ return std::max(0, std::min(255, y));
+}
+
+int ConvertRGBToU(const uint8* rgb, int size, bool subsampling) {
+ int u = 0;
+ if (!subsampling) {
+ u = 112 * rgb[0] - 74 * rgb[1] - 38 * rgb[2];
+ } else {
+ int u0 = 112 * rgb[0] - 74 * rgb[1] - 38 * rgb[2];
+ int u1 = 112 * rgb[size] - 74 * rgb[size + 1] - 38 * rgb[size + 2];
+ u = (u0 + u1 + 1) / 2;
+ }
+ u = ((u + 128) >> 8) + 128;
+ return std::max(0, std::min(255, u));
+}
+
+int ConvertRGBToV(const uint8* rgb, int size, bool subsampling) {
+ int v = 0;
+ if (!subsampling) {
+ v = -18 * rgb[0] - 94 * rgb[1] + 112 * rgb[2];
+ } else {
+ int v0 = -18 * rgb[0] - 94 * rgb[1] + 112 * rgb[2];
+ int v1 = -18 * rgb[size] - 94 * rgb[size + 1] + 112 * rgb[size + 2];
+ v = (v0 + v1 + 1) / 2;
+ }
+ v = ((v + 128) >> 8) + 128;
+ return std::max(0, std::min(255, v));
+}
+
+// Reference code that converts YUV pixels to RGB pixels.
+int ConvertYUVToR(uint8 y, uint8 u, uint8 v) {
+ int r = 298 * (y - 16) + 409 * (v - 128);
+ r = (r + 128) >> 8;
+ return std::max(0, std::min(255, r));
+}
+
+int ConvertYUVToG(uint8 y, uint8 u, uint8 v) {
+ int g = 298 * (y - 16) - 100 * (u - 128) - 208 * (v - 128);
+ g = (g + 128) >> 8;
+ return std::max(0, std::min(255, g));
+}
+
+int ConvertYUVToB(uint8 y, uint8 u, uint8 v) {
+ int b = 298 * (y - 16) + 516 * (u - 128);
+ b = (b + 128) >> 8;
+ return std::max(0, std::min(255, b));
+}
+
+} // namespace
+
// Size of raw image.
static const int kSourceWidth = 640;
static const int kSourceHeight = 360;
@@ -294,3 +351,115 @@
kDJB2HashSeed);
EXPECT_EQ(666823187u, yuy_hash);
}
+
+// A side-by-side test that verifies our ASM functions that convert RGB pixels
+// to YUV pixels can output the expected results. This test converts RGB pixels
+// to YUV pixels with our ASM functions (which use SSE, SSE2, SSE3, and SSSE3)
+// and compare the output YUV pixels with the ones calculated with out reference
+// functions implemented in C++.
+TEST(YUVConvertTest, SideBySideRGB) {
Alpha Left Google 2011/09/01 13:26:41 One more comment on these tests, since they test C
+ // This test checks a subset of all RGB values so this test does not take so
+ // long time.
+ const int kStep = 8;
+ const int kWidth = 256 / kStep;
+
+#ifdef ENABLE_SUBSAMPLING
+ const bool kSubsampling = true;
+#else
+ const bool kSubsampling = false;
+#endif
+
+ for (int size = 3; size <= 4; ++size) {
+ // Create the output buffers.
+ scoped_array<uint8> rgb(new uint8[kWidth * size]);
+ scoped_array<uint8> y(new uint8[kWidth]);
+ scoped_array<uint8> u(new uint8[kWidth / 2]);
+ scoped_array<uint8> v(new uint8[kWidth / 2]);
+
+ // Choose the function that converts from RGB pixels to YUV ones.
+ void (*convert)(const uint8*, uint8*, uint8*, uint8*,
+ int, int, int, int, int) = NULL;
+ if (size == 3)
+ convert = media::ConvertRGB24ToYUV;
+ else
+ convert = media::ConvertRGB32ToYUV;
+
+ for (int r = 0; r < kWidth; ++r) {
+ for (int g = 0; g < kWidth; ++g) {
+
+ // Fill the input pixels.
+ for (int b = 0; b < kWidth; ++b) {
+ rgb[b * size + 0] = b * kStep;
+ rgb[b * size + 1] = g * kStep;
+ rgb[b * size + 2] = r * kStep;
+ if (size == 4)
+ rgb[b * size + 3] = 255;
+ }
+
+ // Convert the input RGB pixels to YUV ones.
+ convert(rgb.get(), y.get(), u.get(), v.get(), kWidth, 1, kWidth * size,
+ kWidth, kWidth / 2);
+
+ // Check the output Y pixels.
+ for (int i = 0; i < kWidth; ++i) {
+ const uint8* p = &rgb[i * size];
+ SCOPED_TRACE(base::StringPrintf("r=%d,g=%d,b=%d", p[2], p[1], p[0]));
+ EXPECT_EQ(ConvertRGBToY(p), y[i]);
+ }
+
+ // Check the output U pixels.
+ for (int i = 0; i < kWidth / 2; ++i) {
+ const uint8* p = &rgb[i * 2 * size];
+ SCOPED_TRACE(base::StringPrintf("r=%d,g=%d,b=%d", p[2], p[1], p[0]));
+ EXPECT_EQ(ConvertRGBToU(p, size, kSubsampling), u[i]);
+ }
+
+ // Check the output V pixels.
+ for (int i = 0; i < kWidth / 2; ++i) {
+ const uint8* p = &rgb[i * 2 * size];
+ SCOPED_TRACE(base::StringPrintf("r=%d,g=%d,b=%d", p[2], p[1], p[0]));
+ EXPECT_EQ(ConvertRGBToV(p, size, kSubsampling), v[i]);
+ }
+ }
+ }
+ }
+}
+
+// Another side-by-side test for our ASM functions that convert YUV pixels
+// to RGB pixels.
+TEST(YUVConvertTest, SideBySideYUV) {
+ const int kStep = 4;
+ const int kWidth = 256 / kStep;
+
+ // Create the output buffers.
+ scoped_array<uint8> rgb(new uint8[kWidth * 4]);
+ scoped_array<uint8> y(new uint8[kWidth]);
+ scoped_array<uint8> u(new uint8[kWidth / 2]);
+ scoped_array<uint8> v(new uint8[kWidth / 2]);
+
+ for (int y0 = 0; y0 < kWidth; ++y0) {
+ for (int i = 0; i < kWidth; ++i)
+ y[i] = y0 * kStep;
+
+ for (int u0 = 0; u0 < kWidth / 2; ++u0) {
+ for (int i = 0; i < kWidth / 2; ++i)
+ u[i] = u0 * kStep * 2;
+
+ for (int v0 = 0; v0 < kWidth / 2; ++v0)
+ v[v0] = v0 * kStep * 2;
+
+ // Convert the input YUV pixels to RGB ones.
+ media::ConvertYUVToRGB32(y.get(), u.get(), v.get(), rgb.get(), kWidth, 1,
+ kWidth, kWidth / 2, kWidth * 4, media::YV12);
+
+ for (int i = 0; i < kWidth; ++i) {
+ SCOPED_TRACE(
+ base::StringPrintf("y=%d,u=%d,v=%d", y[i], u[i / 2], v[i / 2]));
+ EXPECT_EQ(255, rgb[i * 4 + 3]);
+ EXPECT_EQ(ConvertYUVToR(y[i], u[i / 2], v[i / 2]), rgb[i * 4 + 2]);
+ EXPECT_EQ(ConvertYUVToG(y[i], u[i / 2], v[i / 2]), rgb[i * 4 + 1]);
+ EXPECT_EQ(ConvertYUVToB(y[i], u[i / 2], v[i / 2]), rgb[i * 4 + 0]);
+ }
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698