| 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();
|
| }
|
|
|