Index: media/base/yuv_convert.cc |
=================================================================== |
--- media/base/yuv_convert.cc (revision 16299) |
+++ media/base/yuv_convert.cc (working copy) |
@@ -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(); |
} |