summaryrefslogtreecommitdiffstats
path: root/media/base
diff options
context:
space:
mode:
authorfbarchard@chromium.org <fbarchard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-11 22:19:41 +0000
committerfbarchard@chromium.org <fbarchard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-11 22:19:41 +0000
commitce7a1c1b77b669d7c146a2459d731e7d0452671c (patch)
treecb8bd3a6acd91067fe4f2617ed9ff477b077d7aa /media/base
parent1d3aa17b318b5691cf5b292ba6336f25f9d25d3c (diff)
downloadchromium_src-ce7a1c1b77b669d7c146a2459d731e7d0452671c.zip
chromium_src-ce7a1c1b77b669d7c146a2459d731e7d0452671c.tar.gz
chromium_src-ce7a1c1b77b669d7c146a2459d731e7d0452671c.tar.bz2
Review URL: http://codereview.chromium.org/115197
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15800 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base')
-rw-r--r--media/base/yuv_scale.cc120
-rw-r--r--media/base/yuv_scale.h48
-rw-r--r--media/base/yuv_scale_unittest.cc6
3 files changed, 134 insertions, 40 deletions
diff --git a/media/base/yuv_scale.cc b/media/base/yuv_scale.cc
index 7f39861..96e905c 100644
--- a/media/base/yuv_scale.cc
+++ b/media/base/yuv_scale.cc
@@ -20,36 +20,78 @@ static void ScaleYV12ToRGB32Row(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
- size_t width,
- size_t scaled_width);
+ int width,
+ int scaled_width);
static void HalfYV12ToRGB32Row(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
- size_t width);
+ int width);
+
+// TODO(fbarchard): Refactor row functions into seperate module and test on Mac.
+#ifdef _MSC_VER
+extern "C" void ConvertYV12ToRGB32Row(const uint8* y_buf,
+ const uint8* u_buf,
+ const uint8* v_buf,
+ uint8* rgb_buf,
+ size_t width);
+#endif
// Scale a frame of YV12 (aka YUV420) to 32 bit ARGB.
void ScaleYV12ToRGB32(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
- size_t width,
- size_t height,
- size_t scaled_width,
- size_t scaled_height,
+ int width,
+ int height,
+ int scaled_width,
+ int scaled_height,
int y_pitch,
int uv_pitch,
- int rgb_pitch) {
+ int rgb_pitch,
+ Rotate view_rotate) {
+ // Rotations that start at right side of image.
+ if ((view_rotate == ROTATE_180) ||
+ (view_rotate == ROTATE_270) ||
+ (view_rotate == MIRROR_ROTATE_0) ||
+ (view_rotate == MIRROR_ROTATE_90)) {
+ y_buf += width - 1;
+ u_buf += width / 2 - 1;
+ v_buf += width / 2 - 1;
+ width = -width;
+ }
+ // Rotations that start at bottom of image.
+ if ((view_rotate == ROTATE_90) ||
+ (view_rotate == ROTATE_180) ||
+ (view_rotate == MIRROR_ROTATE_90) ||
+ (view_rotate == MIRROR_ROTATE_180)) {
+ y_buf += (height - 1) * y_pitch;
+ u_buf += (height / 2 - 1) * uv_pitch;
+ v_buf += (height / 2 - 1) * uv_pitch;
+ height = -height;
+ }
+ // Only these rotations are implemented.
+ DCHECK((view_rotate == ROTATE_0) ||
+ (view_rotate == ROTATE_180) ||
+ (view_rotate == MIRROR_ROTATE_0) ||
+ (view_rotate == MIRROR_ROTATE_180));
+
#ifdef _OPENMP
#pragma omp parallel for
#endif
- for (int y = 0; y < static_cast<int>(scaled_height); ++y) {
+ for (int y = 0; y < scaled_height; ++y) {
uint8* dest_pixel = rgb_buf + y * rgb_pitch;
int scaled_y = (y * height / scaled_height);
+
const uint8* y_ptr = y_buf + scaled_y * y_pitch;
const uint8* u_ptr = u_buf + scaled_y / 2 * uv_pitch;
const uint8* v_ptr = v_buf + scaled_y / 2 * uv_pitch;
-
+#ifdef _MSC_VER
+ if (scaled_width == width) {
+ ConvertYV12ToRGB32Row(y_ptr, u_ptr, v_ptr,
+ dest_pixel, scaled_width);
+ } else
+#endif
if (scaled_width == (width / 2)) {
HalfYV12ToRGB32Row(y_ptr, u_ptr, v_ptr,
dest_pixel, scaled_width);
@@ -65,17 +107,43 @@ void ScaleYV16ToRGB32(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
- size_t width,
- size_t height,
- size_t scaled_width,
- size_t scaled_height,
+ int width,
+ int height,
+ int scaled_width,
+ int scaled_height,
int y_pitch,
int uv_pitch,
- int rgb_pitch) {
+ int rgb_pitch,
+ Rotate view_rotate) {
+ // Rotations that start at right side of image.
+ if ((view_rotate == ROTATE_180) ||
+ (view_rotate == ROTATE_270) ||
+ (view_rotate == MIRROR_ROTATE_0) ||
+ (view_rotate == MIRROR_ROTATE_90)) {
+ y_buf += width - 1;
+ u_buf += width / 2 - 1;
+ v_buf += width / 2 - 1;
+ width = -width;
+ }
+ // Rotations that start at bottom of image.
+ if ((view_rotate == ROTATE_90) ||
+ (view_rotate == ROTATE_180) ||
+ (view_rotate == MIRROR_ROTATE_90) ||
+ (view_rotate == MIRROR_ROTATE_180)) {
+ y_buf += (height - 1) * y_pitch;
+ u_buf += (height - 1) * uv_pitch;
+ v_buf += (height - 1) * uv_pitch;
+ height = -height;
+ }
+ // Only these rotations are implemented.
+ DCHECK((view_rotate == ROTATE_0) ||
+ (view_rotate == ROTATE_180) ||
+ (view_rotate == MIRROR_ROTATE_0) ||
+ (view_rotate == MIRROR_ROTATE_180));
#ifdef _OPENMP
#pragma omp parallel for
#endif
- for (int y = 0; y < static_cast<int>(scaled_height); ++y) {
+ for (int y = 0; y < scaled_height; ++y) {
uint8* dest_pixel = rgb_buf + y * rgb_pitch;
int scaled_y = (y * height / scaled_height);
const uint8* y_ptr = y_buf + scaled_y * y_pitch;
@@ -100,7 +168,7 @@ static uint8 g_rgb_clip_table[kClipOverflow
+ kClipTableSize
+ kClipOverflow] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 128 underflow values
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // cliped to 0.
+ 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,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -148,7 +216,7 @@ static uint8 g_rgb_clip_table[kClipOverflow
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 128 overflow values
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // cliped to 255.
+ 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,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -171,9 +239,9 @@ static uint8 g_rgb_clip_table[kClipOverflow
// Therefore source range is -128 to 384.
// Output clips to unsigned 0 to 255.
static inline uint32 clip(int32 value) {
- DCHECK(((value >> 8) + kClipOverflow) >= 0);
- DCHECK(((value >> 8) + kClipOverflow) <
- (kClipOverflow + kClipTableSize + kClipOverflow));
+// DCHECK(((value >> 8) + kClipOverflow) >= 0);
+// DCHECK(((value >> 8) + kClipOverflow) <
+// (kClipOverflow + kClipTableSize + kClipOverflow));
return static_cast<uint32>(g_rgb_clip_table[((value) >> 8) + kClipOverflow]);
}
@@ -186,11 +254,11 @@ static void ScaleYV12ToRGB32Row(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
- size_t width,
- size_t scaled_width) {
+ int width,
+ int scaled_width) {
int scaled_dx = width * 16 / scaled_width;
int scaled_x = 0;
- for (int32 x = 0; x < static_cast<int32>(scaled_width); ++x) {
+ for (int32 x = 0; x < scaled_width; ++x) {
uint8 u = u_buf[scaled_x >> 5];
uint8 v = v_buf[scaled_x >> 5];
int32 d = static_cast<int32>(u) - 128;
@@ -233,8 +301,8 @@ static void HalfYV12ToRGB32Row(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
- size_t width) {
- for (int32 x = 0; x < static_cast<int32>(width); ++x) {
+ int width) {
+ for (int32 x = 0; x < width; ++x) {
uint8 u = u_buf[x];
uint8 v = v_buf[x];
int32 d = static_cast<int32>(u) - 128;
diff --git a/media/base/yuv_scale.h b/media/base/yuv_scale.h
index f354942..a029664 100644
--- a/media/base/yuv_scale.h
+++ b/media/base/yuv_scale.h
@@ -9,33 +9,57 @@
namespace media {
+// Mirror means flip the image horizontally, as in looking in a mirror.
+// Rotate happens after mirroring.
+
+enum Rotate {
+ ROTATE_0, // Rotation off.
+ ROTATE_90, // Rotate clockwise.
+ ROTATE_180, // Rotate upside down.
+ ROTATE_270, // Rotate counter clockwise.
+ MIRROR_ROTATE_0, // Mirror horizontally.
+ MIRROR_ROTATE_90, // Mirror then Rotate clockwise.
+ MIRROR_ROTATE_180, // Mirror vertically.
+ MIRROR_ROTATE_270, // Transpose.
+};
+
+// Diagram showing origin and direction of source sampling.
+// ->0 4<-
+// 7 3
+//
+// 6 5
+// ->1 2<-
+
+
// Scale a frame of YV12 (aka YUV420) to 32 bit ARGB.
void ScaleYV12ToRGB32(const uint8* yplane,
const uint8* uplane,
const uint8* vplane,
uint8* rgbframe,
- size_t frame_width,
- size_t frame_height,
- size_t scaled_width,
- size_t scaled_height,
+ int frame_width,
+ int frame_height,
+ int scaled_width,
+ int scaled_height,
int ystride,
int uvstride,
- int rgbstride);
+ int rgbstride,
+ Rotate view_rotate);
// Scale a frame of YV16 (aka YUV422) to 32 bit ARGB.
void ScaleYV16ToRGB32(const uint8* yplane,
const uint8* uplane,
const uint8* vplane,
uint8* rgbframe,
- size_t frame_width,
- size_t frame_height,
- size_t scaled_width,
- size_t scaled_height,
+ int frame_width,
+ int frame_height,
+ int scaled_width,
+ int scaled_height,
int ystride,
int uvstride,
- int rgbstride);
-
-#endif // MEDIA_BASE_YUV_SCALE_H_
+ int rgbstride,
+ Rotate view_rotate);
} // namespace media
+#endif // MEDIA_BASE_YUV_SCALE_H_
+
diff --git a/media/base/yuv_scale_unittest.cc b/media/base/yuv_scale_unittest.cc
index f5e2f0d..c81c74f 100644
--- a/media/base/yuv_scale_unittest.cc
+++ b/media/base/yuv_scale_unittest.cc
@@ -68,7 +68,8 @@ TEST(YuvScaleTest, Basic) {
kScaledWidth, kScaledHeight, // Dimensions
kWidth, // YStride
kWidth / 2, // UvStride
- kScaledWidth * kBpp); // RgbStride
+ kScaledWidth * kBpp, // RgbStride
+ media::ROTATE_0);
unsigned int rgb_hash = hash(rgb_scaled_bytes, size_of_rgb_scaled);
@@ -106,7 +107,8 @@ TEST(YV16ScaleTest, Basic) {
kScaledWidth, kScaledHeight, // Dimensions
kWidth, // YStride
kWidth / 2, // UvStride
- kScaledWidth * kBpp); // RgbStride
+ kScaledWidth * kBpp, // RgbStride
+ media::ROTATE_0);
unsigned int rgb_hash = hash(rgb_scaled_bytes, size_of_rgb_scaled);