diff options
author | hkuang@chromium.org <hkuang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-20 17:24:19 +0000 |
---|---|---|
committer | hkuang@chromium.org <hkuang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-20 17:24:19 +0000 |
commit | 7750e1756760e0c63eaee6713063567b0ddc8e24 (patch) | |
tree | 744cd9ef7093f6bc3a8f2f4e0977a1ca156c0a48 /media | |
parent | 97f8a48ec3d16c16bc966063f745b1fc1b45dac7 (diff) | |
download | chromium_src-7750e1756760e0c63eaee6713063567b0ddc8e24.zip chromium_src-7750e1756760e0c63eaee6713063567b0ddc8e24.tar.gz chromium_src-7750e1756760e0c63eaee6713063567b0ddc8e24.tar.bz2 |
Fix the WebRTC color bug.
On Android, pixel layout is RGBA. However, other Chrome platforms use BGRA.
BUG=239276
TEST= Visit inear.se/bgra on nexus 7. Color is right.
Review URL: https://chromiumcodereview.appspot.com/17043007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207472 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/base/simd/convert_rgb_to_yuv_c.cc | 23 | ||||
-rw-r--r-- | media/base/simd/convert_yuv_to_rgb_c.cc | 29 | ||||
-rw-r--r-- | media/base/yuv_convert_unittest.cc | 25 |
3 files changed, 65 insertions, 12 deletions
diff --git a/media/base/simd/convert_rgb_to_yuv_c.cc b/media/base/simd/convert_rgb_to_yuv_c.cc index ae4c731..4917d37 100644 --- a/media/base/simd/convert_rgb_to_yuv_c.cc +++ b/media/base/simd/convert_rgb_to_yuv_c.cc @@ -24,20 +24,29 @@ void ConvertRGB32ToYUV_C(const uint8* rgbframe, int rgbstride, int ystride, int uvstride) { +#if defined(OS_ANDROID) + const int r = 0; + const int g = 1; + const int b = 2; +#else + const int r = 2; + const int g = 1; + const int b = 0; +#endif + for (int i = 0; i < height; ++i) { for (int j = 0; j < width; ++j) { // Since the input pixel format is RGB32, there are 4 bytes per pixel. const uint8* pixel = rgbframe + 4 * j; - yplane[j] = clip_byte(((pixel[2] * 66 + pixel[1] * 129 + - pixel[0] * 25 + 128) >> 8) + 16); + yplane[j] = clip_byte(((pixel[r] * 66 + pixel[g] * 129 + + pixel[b] * 25 + 128) >> 8) + 16); if (i % 2 == 0 && j % 2 == 0) { - uplane[j / 2] = clip_byte(((pixel[2] * -38 + pixel[1] * -74 + - pixel[0] * 112 + 128) >> 8) + 128); - vplane[j / 2] = clip_byte(((pixel[2] * 112 + pixel[1] * -94 + - pixel[0] * -18 + 128) >> 8) + 128); + uplane[j / 2] = clip_byte(((pixel[r] * -38 + pixel[g] * -74 + + pixel[b] * 112 + 128) >> 8) + 128); + vplane[j / 2] = clip_byte(((pixel[r] * 112 + pixel[g] * -94 + + pixel[b] * -18 + 128) >> 8) + 128); } } - rgbframe += rgbstride; yplane += ystride; if (i % 2 == 0) { diff --git a/media/base/simd/convert_yuv_to_rgb_c.cc b/media/base/simd/convert_yuv_to_rgb_c.cc index f04a89d..b8ebd1e 100644 --- a/media/base/simd/convert_yuv_to_rgb_c.cc +++ b/media/base/simd/convert_yuv_to_rgb_c.cc @@ -11,6 +11,22 @@ namespace media { #define paddsw(x, y) (((x) + (y)) < -32768 ? -32768 : \ (((x) + (y)) > 32767 ? 32767 : ((x) + (y)))) +// On Android, pixel layout is RGBA (see skia/include/core/SkColorPriv.h); +// however, other Chrome platforms use BGRA (see skia/config/SkUserConfig.h). +// Ideally, android should not use the functions here due to performance issue +// (http://crbug.com/249980). +#if defined(OS_ANDROID) +#define SK_R32_SHIFT 0 +#define SK_G32_SHIFT 8 +#define SK_B32_SHIFT 16 +#define SK_A32_SHIFT 24 +#else +#define SK_B32_SHIFT 0 +#define SK_G32_SHIFT 8 +#define SK_R32_SHIFT 16 +#define SK_A32_SHIFT 24 +#endif + static inline void ConvertYUVToRGB32_C(uint8 y, uint8 u, uint8 v, @@ -35,10 +51,10 @@ static inline void ConvertYUVToRGB32_C(uint8 y, r >>= 6; a >>= 6; - *reinterpret_cast<uint32*>(rgb_buf) = (packuswb(b)) | - (packuswb(g) << 8) | - (packuswb(r) << 16) | - (packuswb(a) << 24); + *reinterpret_cast<uint32*>(rgb_buf) = (packuswb(b) << SK_B32_SHIFT) | + (packuswb(g) << SK_G32_SHIFT) | + (packuswb(r) << SK_R32_SHIFT) | + (packuswb(a) << SK_A32_SHIFT); } static inline void ConvertYUVAToARGB_C(uint8 y, @@ -66,7 +82,10 @@ static inline void ConvertYUVAToARGB_C(uint8 y, g = packuswb(g) * a >> 8; r = packuswb(r) * a >> 8; - *reinterpret_cast<uint32*>(rgb_buf) = b | (g << 8) | (r << 16) | (a << 24); + *reinterpret_cast<uint32*>(rgb_buf) = (b << SK_B32_SHIFT) | + (g << SK_G32_SHIFT) | + (r << SK_R32_SHIFT) | + (a << SK_A32_SHIFT); } void ConvertYUVToRGB32Row_C(const uint8* y_buf, diff --git a/media/base/yuv_convert_unittest.cc b/media/base/yuv_convert_unittest.cc index 1ac2a2d..21a82f1 100644 --- a/media/base/yuv_convert_unittest.cc +++ b/media/base/yuv_convert_unittest.cc @@ -76,6 +76,15 @@ static void ReadYUY2Data(scoped_ptr<uint8[]>* data) { ReadData(FILE_PATH_LITERAL("bali_640x360_YUY2.yuv"), kYUY2Size, data); } +#if defined(OS_ANDROID) +// Helper for swapping red and blue channels of RGBA or BGRA. +static void SwapRedAndBlueChannels(unsigned char* pixels, size_t buffer_size) { + for (size_t i = 0; i < buffer_size; i += 4) { + std::swap(pixels[i], pixels[i + 2]); + } +} +#endif + namespace media { TEST(YUVConvertTest, YV12) { @@ -98,6 +107,10 @@ TEST(YUVConvertTest, YV12) { kSourceWidth * kBpp, // RGBStride media::YV12); +#if defined(OS_ANDROID) + SwapRedAndBlueChannels(rgb_converted_bytes.get(), kRGBSizeConverted); +#endif + uint32 rgb_hash = DJB2Hash(rgb_converted_bytes.get(), kRGBSizeConverted, kDJB2HashSeed); EXPECT_EQ(2413171226u, rgb_hash); @@ -123,6 +136,10 @@ TEST(YUVConvertTest, YV16) { kSourceWidth * kBpp, // RGBStride media::YV16); +#if defined(OS_ANDROID) + SwapRedAndBlueChannels(rgb_converted_bytes.get(), kRGBSizeConverted); +#endif + uint32 rgb_hash = DJB2Hash(rgb_converted_bytes.get(), kRGBSizeConverted, kDJB2HashSeed); EXPECT_EQ(4222342047u, rgb_hash); @@ -217,6 +234,10 @@ TEST_P(YUVScaleTest, Normal) { media::ROTATE_0, GetParam().scale_filter); +#if defined(OS_ANDROID) + SwapRedAndBlueChannels(rgb_bytes_.get(), kRGBSizeScaled); +#endif + uint32 rgb_hash = DJB2Hash(rgb_bytes_.get(), kRGBSizeScaled, kDJB2HashSeed); EXPECT_EQ(GetParam().rgb_hash, rgb_hash); } @@ -304,6 +325,10 @@ TEST(YUVConvertTest, Clamp) { 0, // RGBStride media::YV12); +#if defined(OS_ANDROID) + SwapRedAndBlueChannels(rgb, kBpp); +#endif + int expected_test = memcmp(rgb, expected, sizeof(expected)); EXPECT_EQ(0, expected_test); } |