summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/base/yuv_convert_unittest.cc70
-rw-r--r--media/base/yuv_row_linux.cc25
-rw-r--r--media/base/yuv_row_mac.cc25
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];