diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/base/yuv_convert_unittest.cc | 70 | ||||
-rw-r--r-- | media/base/yuv_row_linux.cc | 25 | ||||
-rw-r--r-- | media/base/yuv_row_mac.cc | 25 |
3 files changed, 88 insertions, 32 deletions
diff --git a/media/base/yuv_convert_unittest.cc b/media/base/yuv_convert_unittest.cc index a5b31d7..d647136 100644 --- a/media/base/yuv_convert_unittest.cc +++ b/media/base/yuv_convert_unittest.cc @@ -40,6 +40,10 @@ unsigned int hash(unsigned char *s, size_t len, unsigned int hash = 5381) { } } +// Set to 100 to time ConvertYUVToRGB32. +// This will take approximately 40 to 200 ms. +static const int kTestTimes = 1; + TEST(YUVConvertTest, YV12) { // Allocate all surfaces. scoped_array<uint8> yuv_bytes(new uint8[kYUV12Size]); @@ -58,16 +62,18 @@ TEST(YUVConvertTest, YV12) { reinterpret_cast<char*>(yuv_bytes.get()), static_cast<int>(kYUV12Size))); - // Convert a frame of YUV to 32 bit ARGB. - media::ConvertYUVToRGB32(yuv_bytes.get(), // Y - yuv_bytes.get() + kWidth * kHeight, // U - yuv_bytes.get() + kWidth * kHeight * 5 / 4, // V - rgb_converted_bytes.get(), // RGB output - kWidth, kHeight, // Dimensions - kWidth, // YStride - kWidth / 2, // UVStride - kWidth * kBpp, // RGBStride - media::YV12); + for (int i = 0; i < kTestTimes; ++i) { + // Convert a frame of YUV to 32 bit ARGB. + media::ConvertYUVToRGB32(yuv_bytes.get(), // Y + yuv_bytes.get() + kWidth * kHeight, // U + yuv_bytes.get() + kWidth * kHeight * 5 / 4, // V + rgb_converted_bytes.get(), // RGB output + kWidth, kHeight, // Dimensions + kWidth, // YStride + kWidth / 2, // UVStride + kWidth * kBpp, // RGBStride + media::YV12); + } unsigned int rgb_hash = hash(rgb_converted_bytes.get(), kRGBSizeConverted); @@ -80,7 +86,6 @@ TEST(YUVConvertTest, YV12) { #else EXPECT_EQ(2936300063u, rgb_hash); #endif - return; // This is here to allow you to put a break point on this line } TEST(YUVConvertTest, YV16) { @@ -123,10 +128,9 @@ TEST(YUVConvertTest, YV16) { #else EXPECT_EQ(106869773u, rgb_hash); #endif - return; // This is here to allow you to put a break point on this line } -TEST(YuvScaleTest, Basic) { +TEST(YuvScaleTest, YV12) { // Read YUV reference data from file. FilePath yuv_url; EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &yuv_url)); @@ -168,10 +172,9 @@ TEST(YuvScaleTest, Basic) { #else EXPECT_EQ(197274901u, rgb_hash); #endif - return; // This is here to allow you to put a break point on this line } -TEST(YV16ScaleTest, Basic) { +TEST(YuvScaleTest, YV16) { // Read YV16 reference data from file. FilePath yuv_url; EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &yuv_url)); @@ -213,6 +216,41 @@ TEST(YV16ScaleTest, Basic) { #else EXPECT_EQ(2946450771u, rgb_hash); #endif - return; +} + +// This tests a known worst case YUV value, and for overflow. +TEST(YUVConvertTest, Clamp) { + // Allocate all surfaces. + scoped_array<uint8> yuv_bytes(new uint8[1]); + scoped_array<uint8> rgb_bytes(new uint8[1]); + scoped_array<uint8> rgb_converted_bytes(new uint8[1]); + + // Values that failed previously in bug report. + unsigned char y = 255u; + unsigned char u = 255u; + unsigned char v = 19u; + + // Prefill extra large destination buffer to test for overflow. + unsigned char rgb[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + // TODO(fbarchard): Make reference code mimic MMX exactly + // The code is fixed point and has slight rounding differences. +#if USE_MMX + unsigned char expected[8] = { 255, 255, 104, 255, 4, 5, 6, 7 }; +#else + unsigned char expected[8] = { 255, 255, 105, 255, 4, 5, 6, 7 }; +#endif + // Convert a frame of YUV to 32 bit ARGB. + media::ConvertYUVToRGB32(&y, // Y + &u, // U + &v, // V + &rgb[0], // RGB output + 1, 1, // Dimensions + 0, // YStride + 0, // UVStride + 0, // RGBStride + media::YV12); + + int expected_test = memcmp(rgb, expected, sizeof(expected)); + EXPECT_EQ(0, expected_test); } diff --git a/media/base/yuv_row_linux.cc b/media/base/yuv_row_linux.cc index db7c753..eb3d07e 100644 --- a/media/base/yuv_row_linux.cc +++ b/media/base/yuv_row_linux.cc @@ -17,12 +17,12 @@ namespace media { // Reference version of YUV converter. static const int kClipTableSize = 256; -static const int kClipOverflow = 256; +static const int kClipOverflow = 288; // Cb max is 535. static uint8 g_rgb_clip_table[kClipOverflow + kClipTableSize + kClipOverflow] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 256 underflow values + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 288 underflow values 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // clipped to 0. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -54,6 +54,10 @@ static uint8 g_rgb_clip_table[kClipOverflow + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // Unclipped values. 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, @@ -86,7 +90,7 @@ static uint8 g_rgb_clip_table[kClipOverflow + 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 256 overflow values + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 288 overflow values 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // clipped to 255. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, @@ -118,6 +122,10 @@ static uint8 g_rgb_clip_table[kClipOverflow + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; // Clip an rgb channel value to 0..255 range. @@ -155,14 +163,15 @@ void FastConvertYUVToRGB32Row(const uint8* y_buf, const uint8* v_buf, uint8* rgb_buf, int width) { - for (int32 x = 0; x < static_cast<int32>(width); x += 2) { + for (int x = 0; x < width; x += 2) { uint8 u = u_buf[x >> 1]; uint8 v = v_buf[x >> 1]; uint8 y0 = y_buf[x]; - uint8 y1 = y_buf[x + 1]; YuvPixel(y0, u, v, rgb_buf); - YuvPixel(y1, u, v, rgb_buf + 4); - + if ((x + 1) < width) { + uint8 y1 = y_buf[x + 1]; + YuvPixel(y1, u, v, rgb_buf + 4); + } rgb_buf += 8; // Advance 2 pixels. } } @@ -178,7 +187,7 @@ void ScaleYUVToRGB32Row(const uint8* y_buf, int width, int scaled_dx) { int scaled_x = 0; - for (int32 x = 0; x < width; ++x) { + for (int x = 0; x < width; ++x) { uint8 u = u_buf[scaled_x >> 5]; uint8 v = v_buf[scaled_x >> 5]; uint8 y0 = y_buf[scaled_x >> 4]; diff --git a/media/base/yuv_row_mac.cc b/media/base/yuv_row_mac.cc index db7c753..eb3d07e 100644 --- a/media/base/yuv_row_mac.cc +++ b/media/base/yuv_row_mac.cc @@ -17,12 +17,12 @@ namespace media { // Reference version of YUV converter. static const int kClipTableSize = 256; -static const int kClipOverflow = 256; +static const int kClipOverflow = 288; // Cb max is 535. static uint8 g_rgb_clip_table[kClipOverflow + kClipTableSize + kClipOverflow] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 256 underflow values + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 288 underflow values 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // clipped to 0. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -54,6 +54,10 @@ static uint8 g_rgb_clip_table[kClipOverflow + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // Unclipped values. 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, @@ -86,7 +90,7 @@ static uint8 g_rgb_clip_table[kClipOverflow + 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 256 overflow values + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 288 overflow values 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // clipped to 255. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, @@ -118,6 +122,10 @@ static uint8 g_rgb_clip_table[kClipOverflow + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; // Clip an rgb channel value to 0..255 range. @@ -155,14 +163,15 @@ void FastConvertYUVToRGB32Row(const uint8* y_buf, const uint8* v_buf, uint8* rgb_buf, int width) { - for (int32 x = 0; x < static_cast<int32>(width); x += 2) { + for (int x = 0; x < width; x += 2) { uint8 u = u_buf[x >> 1]; uint8 v = v_buf[x >> 1]; uint8 y0 = y_buf[x]; - uint8 y1 = y_buf[x + 1]; YuvPixel(y0, u, v, rgb_buf); - YuvPixel(y1, u, v, rgb_buf + 4); - + if ((x + 1) < width) { + uint8 y1 = y_buf[x + 1]; + YuvPixel(y1, u, v, rgb_buf + 4); + } rgb_buf += 8; // Advance 2 pixels. } } @@ -178,7 +187,7 @@ void ScaleYUVToRGB32Row(const uint8* y_buf, int width, int scaled_dx) { int scaled_x = 0; - for (int32 x = 0; x < width; ++x) { + for (int x = 0; x < width; ++x) { uint8 u = u_buf[scaled_x >> 5]; uint8 v = v_buf[scaled_x >> 5]; uint8 y0 = y_buf[scaled_x >> 4]; |