summaryrefslogtreecommitdiffstats
path: root/media/base/yuv_convert.cc
diff options
context:
space:
mode:
authorfbarchard@chromium.org <fbarchard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-18 22:17:38 +0000
committerfbarchard@chromium.org <fbarchard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-18 22:17:38 +0000
commitbe5a116b8a3465308174ccc4ab63351413d6dfe7 (patch)
tree2ba1202e427db0fda4d70037a5afda93e7f576fe /media/base/yuv_convert.cc
parent3090eeb5afd49e828739b492eb400d8fcf734784 (diff)
downloadchromium_src-be5a116b8a3465308174ccc4ab63351413d6dfe7.zip
chromium_src-be5a116b8a3465308174ccc4ab63351413d6dfe7.tar.gz
chromium_src-be5a116b8a3465308174ccc4ab63351413d6dfe7.tar.bz2
YUV with clipping.
All functions do 2 pixels at a time. 90 and 270 rotations implemented. YV16 refactored. YV12 code accepts a YuvType that allows the same code to support YV16 as well. Special case for half size removed. Special case for doubling added. 3.62 ms versus 8.62 for general purpose code. Review URL: http://codereview.chromium.org/113407 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16334 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base/yuv_convert.cc')
-rw-r--r--media/base/yuv_convert.cc168
1 files changed, 123 insertions, 45 deletions
diff --git a/media/base/yuv_convert.cc b/media/base/yuv_convert.cc
index 788fd99..72f89a1 100644
--- a/media/base/yuv_convert.cc
+++ b/media/base/yuv_convert.cc
@@ -73,72 +73,150 @@
#define DCHECK(a)
#endif
+// Header for low level row functions.
#include "media/base/yuv_row.h"
namespace media {
-
-// Convert a frame of YV12 (aka YUV420) to 32 bit ARGB.
-void ConvertYV12ToRGB32(const uint8* y_buf,
+// Convert a frame of YUV to 32 bit ARGB.
+void ConvertYUVToRGB32(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
- size_t width,
- size_t height,
+ int width,
+ int height,
int y_pitch,
int uv_pitch,
- int rgb_pitch) {
- // Image must be multiple of 2 in width.
- DCHECK((width & 1) == 0);
- // Check alignment. Use memalign to allocate the buffer if you hit this
- // check:
- DCHECK((reinterpret_cast<uintptr_t>(rgb_buf) & 7) == 0);
+ int rgb_pitch,
+ YUVType yuv_type) {
+ unsigned int y_shift = yuv_type;
#ifdef _OPENMP
#pragma omp parallel for
#endif
- for (int y = 0; y < static_cast<int>(height); ++y) {
- uint8* d1 = rgb_buf + y * rgb_pitch;
+ for (int y = 0; y < height; ++y) {
+ uint8* rgb_row = rgb_buf + y * rgb_pitch;
const uint8* y_ptr = y_buf + y * y_pitch;
- const uint8* u_ptr = u_buf + y/2 * uv_pitch;
- const uint8* v_ptr = v_buf + y/2 * uv_pitch;
+ const uint8* u_ptr = u_buf + (y >> y_shift) * uv_pitch;
+ const uint8* v_ptr = v_buf + (y >> y_shift) * uv_pitch;
- ConvertYV12ToRGB32Row(y_ptr,
- u_ptr,
- v_ptr,
- d1,
- width);
+ FastConvertYUVToRGB32Row(y_ptr,
+ u_ptr,
+ v_ptr,
+ rgb_row,
+ width);
}
EMMS();
}
-// Convert a frame of YV16 (aka YUV422) to 32 bit ARGB.
-void ConvertYV16ToRGB32(const uint8* y_buf,
- const uint8* u_buf,
- const uint8* v_buf,
- uint8* rgb_buf,
- size_t width,
- size_t height,
- int y_pitch,
- int uv_pitch,
- int rgb_pitch) {
- // Image must be multiple of 2 in width.
- DCHECK((width & 1) == 0);
- // Check alignment. Use memalign to allocate the buffer if you hit this
- // check:
- DCHECK((reinterpret_cast<uintptr_t>(rgb_buf) & 7) == 0);
+// Scale a frame of YUV to 32 bit ARGB.
+void ScaleYUVToRGB32(const uint8* y_buf,
+ const uint8* u_buf,
+ const uint8* v_buf,
+ uint8* rgb_buf,
+ int width,
+ int height,
+ int scaled_width,
+ int scaled_height,
+ int y_pitch,
+ int uv_pitch,
+ int rgb_pitch,
+ YUVType yuv_type,
+ Rotate view_rotate) {
+ unsigned int y_shift = yuv_type;
+ // Diagram showing origin and direction of source sampling.
+ // ->0 4<-
+ // 7 3
+ //
+ // 6 5
+ // ->1 2<-
+ // 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 >> y_shift) - 1) * uv_pitch;
+ v_buf += ((height >> y_shift) - 1) * uv_pitch;
+ height = -height;
+ }
+
+ // Handle zero sized destination.
+ if (scaled_width == 0 || scaled_height == 0)
+ return;
+ int scaled_dx = width * 16 / scaled_width;
+ int scaled_dy = height * 16 / scaled_height;
+
+ int scaled_dx_uv = scaled_dx;
+
+ if ((view_rotate == ROTATE_90) ||
+ (view_rotate == ROTATE_270)) {
+ int tmp = scaled_height;
+ scaled_height = scaled_width;
+ scaled_width = tmp;
+ tmp = height;
+ height = width;
+ width = tmp;
+ int original_dx = scaled_dx;
+ int original_dy = scaled_dy;
+ scaled_dx = ((original_dy >> 4) * y_pitch) << 4;
+ scaled_dx_uv = ((original_dy >> 4) * uv_pitch) << 4;
+ scaled_dy = original_dx;
+ if (view_rotate == ROTATE_90) {
+ y_pitch = -1;
+ uv_pitch = -1;
+ height = -height;
+ } else {
+ y_pitch = 1;
+ uv_pitch = 1;
+ }
+ }
+
#ifdef _OPENMP
#pragma omp parallel for
#endif
- for (int y = 0; y < static_cast<int>(height); ++y) {
- uint8* d1 = rgb_buf + y * rgb_pitch;
- const uint8* y_ptr = y_buf + y * y_pitch;
- const uint8* u_ptr = u_buf + y * uv_pitch;
- const uint8* v_ptr = v_buf + y * uv_pitch;
+ 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 >> y_shift) * uv_pitch;
+ const uint8* v_ptr = v_buf + (scaled_y >> y_shift) * uv_pitch;
- ConvertYV12ToRGB32Row(y_ptr,
- u_ptr,
- v_ptr,
- d1,
- width);
+#if USE_MMX
+ if (scaled_width == (width * 2)) {
+ DoubleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
+ dest_pixel, scaled_width);
+ } else if ((scaled_dx & 15) == 0) { // Scaling by integer scale factor.
+ if (scaled_dx_uv == scaled_dx) { // Not rotated.
+ if (scaled_dx == 16) { // Not scaled
+ FastConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
+ dest_pixel, scaled_width);
+ } else { // Simple scale down. ie half
+ ConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
+ dest_pixel, scaled_width, scaled_dx >> 4);
+ }
+ } else {
+ RotateConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
+ dest_pixel, scaled_width,
+ scaled_dx >> 4, scaled_dx_uv >> 4);
+ }
+#else
+ if (scaled_dx == 16) { // Not scaled
+ FastConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
+ dest_pixel, scaled_width);
+#endif
+ } else {
+ ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
+ dest_pixel, scaled_width, scaled_dx);
+ }
}
EMMS();
}