|
@@ -26,6 +26,17 @@
|
|
|
#include "SDL_RLEaccel_c.h"
|
|
|
#include "SDL_pixels_c.h"
|
|
|
|
|
|
+/* Private routines */
|
|
|
+static int
|
|
|
+SDL_ConvertPixels_YUV_to_ARGB8888(int width, int height,
|
|
|
+ Uint32 src_format, const void *src,
|
|
|
+ void *dst, int dst_pitch);
|
|
|
+
|
|
|
+static int
|
|
|
+SDL_ConvertPixels_ARGB8888_to_YUV(int width, int height,
|
|
|
+ const void *src, int src_pitch,
|
|
|
+ Uint32 dst_format, void *dst);
|
|
|
+
|
|
|
/* Public routines */
|
|
|
|
|
|
/*
|
|
@@ -1124,56 +1135,131 @@ int SDL_ConvertPixels(int width, int height,
|
|
|
|
|
|
/* Fast path for same format copy */
|
|
|
if (src_format == dst_format) {
|
|
|
- int bpp, i;
|
|
|
+ int i;
|
|
|
|
|
|
if (SDL_ISPIXELFORMAT_FOURCC(src_format)) {
|
|
|
switch (src_format) {
|
|
|
case SDL_PIXELFORMAT_YUY2:
|
|
|
case SDL_PIXELFORMAT_UYVY:
|
|
|
case SDL_PIXELFORMAT_YVYU:
|
|
|
- bpp = 2;
|
|
|
+ /* Packed planes */
|
|
|
+ width = 4 * ((width + 1) / 2);
|
|
|
+ for (i = height; i--;) {
|
|
|
+ SDL_memcpy(dst, src, width);
|
|
|
+ src = (const Uint8*)src + src_pitch;
|
|
|
+ dst = (Uint8*)dst + dst_pitch;
|
|
|
+ }
|
|
|
break;
|
|
|
case SDL_PIXELFORMAT_YV12:
|
|
|
case SDL_PIXELFORMAT_IYUV:
|
|
|
case SDL_PIXELFORMAT_NV12:
|
|
|
case SDL_PIXELFORMAT_NV21:
|
|
|
- bpp = 1;
|
|
|
+ {
|
|
|
+ /* Y plane */
|
|
|
+ for (i = height; i--;) {
|
|
|
+ SDL_memcpy(dst, src, width);
|
|
|
+ src = (const Uint8*)src + src_pitch;
|
|
|
+ dst = (Uint8*)dst + dst_pitch;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* not sure the pitch is relevant here.
|
|
|
+ this also works to add the size of two chroma planes */
|
|
|
+#if 0
|
|
|
+ SDL_memcpy(dst, src, 2 * ((width + 1)/2) * ((height+1)/2));
|
|
|
+#else
|
|
|
+
|
|
|
+ if (src_format == SDL_PIXELFORMAT_YV12 || src_format == SDL_PIXELFORMAT_IYUV) {
|
|
|
+ /* U and V planes are a quarter the size of the Y plane */
|
|
|
+ width = (width + 1) / 2;
|
|
|
+ height = (height + 1) / 2;
|
|
|
+ src_pitch = (src_pitch + 1) / 2;
|
|
|
+ dst_pitch = (dst_pitch + 1) / 2;
|
|
|
+ for (i = height * 2; i--;) {
|
|
|
+ SDL_memcpy(dst, src, width);
|
|
|
+ src = (Uint8*)src + src_pitch;
|
|
|
+ dst = (Uint8*)dst + dst_pitch;
|
|
|
+ }
|
|
|
+ } else if (src_format == SDL_PIXELFORMAT_NV12 || src_format == SDL_PIXELFORMAT_NV21) {
|
|
|
+ /* U/V plane is half the height of the Y plane */
|
|
|
+ height = (height + 1) / 2;
|
|
|
+ width = (width + 1) / 2;
|
|
|
+ src_pitch = (src_pitch + 1) / 2;
|
|
|
+ dst_pitch = (dst_pitch + 1) / 2;
|
|
|
+ for (i = height; i--;) {
|
|
|
+ SDL_memcpy(dst, src, 2 * width);
|
|
|
+ src = (Uint8*)src + 2 * src_pitch;
|
|
|
+ dst = (Uint8*)dst + 2 * dst_pitch;
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ }
|
|
|
break;
|
|
|
default:
|
|
|
return SDL_SetError("Unknown FOURCC pixel format");
|
|
|
}
|
|
|
} else {
|
|
|
- bpp = SDL_BYTESPERPIXEL(src_format);
|
|
|
+ const int bpp = SDL_BYTESPERPIXEL(src_format);
|
|
|
+ width *= bpp;
|
|
|
+ for (i = height; i--;) {
|
|
|
+ SDL_memcpy(dst, src, width);
|
|
|
+ src = (const Uint8*)src + src_pitch;
|
|
|
+ dst = (Uint8*)dst + dst_pitch;
|
|
|
+ }
|
|
|
}
|
|
|
- width *= bpp;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- for (i = height; i--;) {
|
|
|
- SDL_memcpy(dst, src, width);
|
|
|
- src = (Uint8*)src + src_pitch;
|
|
|
- dst = (Uint8*)dst + dst_pitch;
|
|
|
+ /* FOURCC to Any */
|
|
|
+ if (SDL_ISPIXELFORMAT_FOURCC(src_format)) {
|
|
|
+ /* FOURCC to ARGB8888 */
|
|
|
+ if (dst_format == SDL_PIXELFORMAT_ARGB8888) {
|
|
|
+ SDL_ConvertPixels_YUV_to_ARGB8888(width, height, src_format, src, dst, dst_pitch);
|
|
|
+ return 0;
|
|
|
}
|
|
|
+ else /* FOURCC to not(ARGB8888) : need an intermediate conversion */
|
|
|
+ {
|
|
|
+ int ret;
|
|
|
+ void *tmp = SDL_malloc(width * height * 4);
|
|
|
+ if (tmp == NULL) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
|
|
|
- if (src_format == SDL_PIXELFORMAT_YV12 || src_format == SDL_PIXELFORMAT_IYUV) {
|
|
|
- /* U and V planes are a quarter the size of the Y plane */
|
|
|
- width /= 2;
|
|
|
- height /= 2;
|
|
|
- src_pitch /= 2;
|
|
|
- dst_pitch /= 2;
|
|
|
- for (i = height * 2; i--;) {
|
|
|
- SDL_memcpy(dst, src, width);
|
|
|
- src = (Uint8*)src + src_pitch;
|
|
|
- dst = (Uint8*)dst + dst_pitch;
|
|
|
+ /* convert src/FOURCC to tmp/ARGB8888 */
|
|
|
+ SDL_ConvertPixels_YUV_to_ARGB8888(width, height, src_format, src, tmp, width * 4);
|
|
|
+
|
|
|
+ /* convert tmp/ARGB8888 to dst/dst_format */
|
|
|
+ ret = SDL_ConvertPixels(width, height, SDL_PIXELFORMAT_ARGB8888, tmp, width * 4, dst_format, dst, dst_pitch);
|
|
|
+ SDL_free(tmp);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Any to FOURCC */
|
|
|
+ if (SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
|
|
|
+ /* ARGB8888 to FOURCC */
|
|
|
+ if (src_format == SDL_PIXELFORMAT_ARGB8888) {
|
|
|
+ SDL_ConvertPixels_ARGB8888_to_YUV(width, height, src, src_pitch, dst_format, dst);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ else /* not(ARGB8888) to FOURCC : need an intermediate conversion */
|
|
|
+ {
|
|
|
+ int ret;
|
|
|
+ void *tmp = SDL_malloc(width * height * 4);
|
|
|
+ if (tmp == NULL) {
|
|
|
+ return -1;
|
|
|
}
|
|
|
- } else if (src_format == SDL_PIXELFORMAT_NV12 || src_format == SDL_PIXELFORMAT_NV21) {
|
|
|
- /* U/V plane is half the height of the Y plane */
|
|
|
- height /= 2;
|
|
|
- for (i = height; i--;) {
|
|
|
- SDL_memcpy(dst, src, width);
|
|
|
- src = (Uint8*)src + src_pitch;
|
|
|
- dst = (Uint8*)dst + dst_pitch;
|
|
|
+ /* convert src/src_format to tmp/ARGB8888 */
|
|
|
+ ret = SDL_ConvertPixels(width, height, src_format, src, src_pitch, SDL_PIXELFORMAT_ARGB8888, tmp, width * 4);
|
|
|
+ if (ret == -1) {
|
|
|
+ SDL_free(tmp);
|
|
|
+ return ret;
|
|
|
}
|
|
|
+ /* convert tmp/ARGB8888 to dst/FOURCC */
|
|
|
+ SDL_ConvertPixels_ARGB8888_to_YUV(width, height, tmp, width * 4, dst_format, dst);
|
|
|
+
|
|
|
+ SDL_free(tmp);
|
|
|
+ return 0;
|
|
|
}
|
|
|
- return 0;
|
|
|
}
|
|
|
|
|
|
if (!SDL_CreateSurfaceOnStack(width, height, src_format, nonconst_src,
|
|
@@ -1231,4 +1317,472 @@ SDL_FreeSurface(SDL_Surface * surface)
|
|
|
SDL_free(surface);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+/* YUV-RGB conversion */
|
|
|
+#define CLAMP(val) ((val) > 0 ? ((val) < 255 ? (val) : 255) : 0)
|
|
|
+
|
|
|
+#define MAKE_Y(r, g, b) ((( 66 * (r) + 129 * (g) + 25 * (b) + 128) >> 8) + 16)
|
|
|
+#define MAKE_U(r, g, b) ((( -38 * (r) - 74 * (g) + 112 * (b) + 128) >> 8) + 128)
|
|
|
+#define MAKE_V(r, g, b) ((( 112 * (r) - 94 * (g) - 18 * (b) + 128) >> 8) + 128)
|
|
|
+
|
|
|
+
|
|
|
+#define MAKE_R(y, u, v) CLAMP(( 298 * ((y) - 16) + 409 * ((v) - 128) + 128) >> 8)
|
|
|
+#define MAKE_G(y, u, v) CLAMP(( 298 * ((y) - 16) - 100 * ((u) - 128) - 208 * ((v) - 128) + 128) >> 8)
|
|
|
+#define MAKE_B(y, u, v) CLAMP(( 298 * ((y) - 16) + 516 * ((u) - 128) + 128) >> 8)
|
|
|
+
|
|
|
+static int
|
|
|
+SDL_ConvertPixels_YUV_to_ARGB8888(int width, int height,
|
|
|
+ Uint32 src_format, const void *src,
|
|
|
+ void *dst, int dst_pitch)
|
|
|
+{
|
|
|
+ const int sz_plane = width * height;
|
|
|
+ const int sz_plane_chroma = ((width + 1) / 2) * ((height + 1) / 2);
|
|
|
+ const int width_remainder = (width & 0x1);
|
|
|
+ const int width_half = width / 2;
|
|
|
+ const int curr_row_padding = dst_pitch - 4 * width;
|
|
|
+ int i, j;
|
|
|
+ Uint8 *curr_row = (Uint8*)dst;
|
|
|
+
|
|
|
+ // SDL_Log("SDL_ConvertPixels_YUV_to_ARGB8888 (from %s)", SDL_GetPixelFormatName(src_format));
|
|
|
+
|
|
|
+#define WRITE_RGB_PIXEL(y, u, v) \
|
|
|
+ *((Uint32*)curr_row) = \
|
|
|
+ (MAKE_B((y), (u), (v)) \
|
|
|
+ | (MAKE_G((y), (u), (v)) << 8) \
|
|
|
+ | (MAKE_R((y), (u), (v)) << 16) \
|
|
|
+ | 0xff000000); \
|
|
|
+ curr_row += 4; \
|
|
|
+
|
|
|
+ switch (src_format)
|
|
|
+ {
|
|
|
+ case SDL_PIXELFORMAT_YV12:
|
|
|
+ case SDL_PIXELFORMAT_IYUV:
|
|
|
+ case SDL_PIXELFORMAT_NV12:
|
|
|
+ case SDL_PIXELFORMAT_NV21:
|
|
|
+ {
|
|
|
+ const Uint8 *plane_y = (const Uint8*)src;
|
|
|
+
|
|
|
+ if (src_format == SDL_PIXELFORMAT_YV12 || src_format == SDL_PIXELFORMAT_IYUV)
|
|
|
+ {
|
|
|
+ const Uint8 *plane_u = (src_format == SDL_PIXELFORMAT_YV12 ? plane_y + sz_plane + sz_plane_chroma : plane_y + sz_plane);
|
|
|
+ const Uint8 *plane_v = (src_format == SDL_PIXELFORMAT_YV12 ? plane_y + sz_plane : plane_y + sz_plane + sz_plane_chroma);
|
|
|
+
|
|
|
+ for (j = 0; j < height; j++) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ const Uint8 u = *plane_u++;
|
|
|
+ const Uint8 v = *plane_v++;
|
|
|
+ const Uint8 y = *plane_y++;
|
|
|
+ const Uint8 y1 = *plane_y++;
|
|
|
+ WRITE_RGB_PIXEL(y, u, v);
|
|
|
+ WRITE_RGB_PIXEL(y1, u, v);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ const Uint8 u = *plane_u++;
|
|
|
+ const Uint8 v = *plane_v++;
|
|
|
+ const Uint8 y = *plane_y++;
|
|
|
+ WRITE_RGB_PIXEL(y, u, v);
|
|
|
+ }
|
|
|
+ /* Re-use the same line of chroma planes */
|
|
|
+ if ((j & 0x1) == 0x0) {
|
|
|
+ plane_u -= width_half + width_remainder;
|
|
|
+ plane_v -= width_half + width_remainder;
|
|
|
+ }
|
|
|
+ curr_row += curr_row_padding;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (src_format == SDL_PIXELFORMAT_NV12)
|
|
|
+ {
|
|
|
+ const Uint8 *plane_interleaved_uv = plane_y + sz_plane;
|
|
|
+ for (j = 0; j < height; j++) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ const Uint8 y = *plane_y++;
|
|
|
+ const Uint8 y1 = *plane_y++;
|
|
|
+ const Uint8 u = *plane_interleaved_uv++;
|
|
|
+ const Uint8 v = *plane_interleaved_uv++;
|
|
|
+ WRITE_RGB_PIXEL(y, u, v);
|
|
|
+ WRITE_RGB_PIXEL(y1, u, v);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ const Uint8 y = *plane_y++;
|
|
|
+ const Uint8 u = *plane_interleaved_uv++;
|
|
|
+ const Uint8 v = *plane_interleaved_uv++;
|
|
|
+ WRITE_RGB_PIXEL(y, u, v);
|
|
|
+ }
|
|
|
+ /* Re-use the same line of chroma planes */
|
|
|
+ if ((j & 0x1) == 0x0) {
|
|
|
+ plane_interleaved_uv -= 2 * (width_half + width_remainder);
|
|
|
+ }
|
|
|
+ curr_row += curr_row_padding;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else /* src_format == SDL_PIXELFORMAT_NV21 */
|
|
|
+ {
|
|
|
+ const Uint8 *plane_interleaved_uv = plane_y + sz_plane;
|
|
|
+ for (j = 0; j < height; j++) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ const Uint8 y = *plane_y++;
|
|
|
+ const Uint8 y1 = *plane_y++;
|
|
|
+ const Uint8 v = *plane_interleaved_uv++;
|
|
|
+ const Uint8 u = *plane_interleaved_uv++;
|
|
|
+ WRITE_RGB_PIXEL(y, u, v);
|
|
|
+ WRITE_RGB_PIXEL(y1, u, v);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ const Uint8 y = *plane_y++;
|
|
|
+ const Uint8 v = *plane_interleaved_uv++;
|
|
|
+ const Uint8 u = *plane_interleaved_uv++;
|
|
|
+ WRITE_RGB_PIXEL(y, u, v);
|
|
|
+ }
|
|
|
+ /* Re-use the same line of chroma planes */
|
|
|
+ if ((j & 0x1) == 0x0) {
|
|
|
+ plane_interleaved_uv -= 2 * (width_half + width_remainder);
|
|
|
+ }
|
|
|
+ curr_row += curr_row_padding;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SDL_PIXELFORMAT_YUY2:
|
|
|
+ case SDL_PIXELFORMAT_UYVY:
|
|
|
+ case SDL_PIXELFORMAT_YVYU:
|
|
|
+ {
|
|
|
+ const Uint8 *plane = (const Uint8 *)src;
|
|
|
+
|
|
|
+#define READ_PACKED_YUV(var1, var2, var3, var4) \
|
|
|
+ const Uint8 var1 = plane[0]; \
|
|
|
+ const Uint8 var2 = plane[1]; \
|
|
|
+ const Uint8 var3 = plane[2]; \
|
|
|
+ const Uint8 var4 = plane[3]; \
|
|
|
+ plane += 4; \
|
|
|
+
|
|
|
+ if (src_format == SDL_PIXELFORMAT_YUY2) /* Y U Y1 V */
|
|
|
+ {
|
|
|
+ for (j = 0; j < height; j++) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ READ_PACKED_YUV(y, u, y1, v);
|
|
|
+ WRITE_RGB_PIXEL(y, u, v);
|
|
|
+ WRITE_RGB_PIXEL(y1, u, v);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ READ_PACKED_YUV(y, u, y1, v); /* y1 unused */
|
|
|
+ WRITE_RGB_PIXEL(y, u, v);
|
|
|
+ }
|
|
|
+ curr_row += curr_row_padding;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (src_format == SDL_PIXELFORMAT_UYVY) /* U Y V Y1 */
|
|
|
+ {
|
|
|
+ for (j = 0; j < height; j++) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ READ_PACKED_YUV(u, y, v, y1);
|
|
|
+ WRITE_RGB_PIXEL(y, u, v);
|
|
|
+ WRITE_RGB_PIXEL(y1, u, v);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ READ_PACKED_YUV(u, y, v, y1); /* y1 unused */
|
|
|
+ WRITE_RGB_PIXEL(y, u, v);
|
|
|
+ }
|
|
|
+ curr_row += curr_row_padding;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (src_format == SDL_PIXELFORMAT_YVYU) /* Y V Y1 U */
|
|
|
+ {
|
|
|
+ for (j = 0; j < height; j++) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ READ_PACKED_YUV(y, v, y1, u);
|
|
|
+ WRITE_RGB_PIXEL(y, u, v);
|
|
|
+ WRITE_RGB_PIXEL(y1, u, v);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ READ_PACKED_YUV(y, v, y1, u); /* y1 unused */
|
|
|
+ WRITE_RGB_PIXEL(y, u, v);
|
|
|
+ }
|
|
|
+ curr_row += curr_row_padding;
|
|
|
+ }
|
|
|
+ }
|
|
|
+#undef READ_PACKED_YUV
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+#undef WRITE_RGB_PIXEL
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+SDL_ConvertPixels_ARGB8888_to_YUV(int width, int height, const void *src, int src_pitch, Uint32 dst_format, void *dst)
|
|
|
+{
|
|
|
+ const int src_pitch_x_2 = src_pitch * 2;
|
|
|
+ const int sz_plane = width * height;
|
|
|
+ const int sz_plane_chroma = ((width + 1) / 2) * ((height + 1) / 2);
|
|
|
+ const int height_half = height / 2;
|
|
|
+ const int height_remainder = (height & 0x1);
|
|
|
+ const int width_half = width / 2;
|
|
|
+ const int width_remainder = (width & 0x1);
|
|
|
+ int i, j;
|
|
|
+
|
|
|
+ // SDL_Log("SDL_ConvertPixels_ARGB8888_to_YUV (to %s)", SDL_GetPixelFormatName(dst_format));
|
|
|
+
|
|
|
+ switch (dst_format)
|
|
|
+ {
|
|
|
+ case SDL_PIXELFORMAT_YV12:
|
|
|
+ case SDL_PIXELFORMAT_IYUV:
|
|
|
+ case SDL_PIXELFORMAT_NV12:
|
|
|
+ case SDL_PIXELFORMAT_NV21:
|
|
|
+ {
|
|
|
+ const Uint8 *curr_row, *next_row;
|
|
|
+
|
|
|
+ Uint8 *plane_y = (Uint8*) dst;
|
|
|
+ Uint8 *plane_u = (dst_format == SDL_PIXELFORMAT_YV12 ? plane_y + sz_plane + sz_plane_chroma : plane_y + sz_plane);
|
|
|
+ Uint8 *plane_v = (dst_format == SDL_PIXELFORMAT_YV12 ? plane_y + sz_plane : plane_y + sz_plane + sz_plane_chroma);
|
|
|
+ Uint8 *plane_interleaved_uv = plane_y + sz_plane;
|
|
|
+
|
|
|
+ curr_row = (const Uint8*)src;
|
|
|
+
|
|
|
+ /* Write Y plane */
|
|
|
+ for (j = 0; j < height; j++) {
|
|
|
+ for (i = 0; i < width; i++) {
|
|
|
+ const Uint8 b = curr_row[4 * i + 0];
|
|
|
+ const Uint8 g = curr_row[4 * i + 1];
|
|
|
+ const Uint8 r = curr_row[4 * i + 2];
|
|
|
+ *plane_y++ = MAKE_Y(r, g, b);
|
|
|
+ }
|
|
|
+ curr_row += src_pitch;
|
|
|
+ }
|
|
|
+
|
|
|
+ curr_row = (const Uint8*)src;
|
|
|
+ next_row = (const Uint8*)src;
|
|
|
+ next_row += src_pitch;
|
|
|
+
|
|
|
+#if 1
|
|
|
+/* slightly faster */
|
|
|
+#define READ_2x2_PIXELS \
|
|
|
+ const Uint32 p1 = ((Uint32 *)curr_row)[2 * i]; \
|
|
|
+ const Uint32 p2 = ((Uint32 *)curr_row)[2 * i + 1]; \
|
|
|
+ const Uint32 p3 = ((Uint32 *)next_row)[2 * i]; \
|
|
|
+ const Uint32 p4 = ((Uint32 *)next_row)[2 * i + 1]; \
|
|
|
+ const Uint32 b = ((p1 & 0x000000ff) + (p2 & 0x000000ff) + (p3 & 0x000000ff) + (p4 & 0x000000ff)) >> 2; \
|
|
|
+ const Uint32 g = ((p1 & 0x0000ff00) + (p2 & 0x0000ff00) + (p3 & 0x0000ff00) + (p4 & 0x0000ff00)) >> 10; \
|
|
|
+ const Uint32 r = ((p1 & 0x00ff0000) + (p2 & 0x00ff0000) + (p3 & 0x00ff0000) + (p4 & 0x00ff0000)) >> 18; \
|
|
|
+
|
|
|
+#else
|
|
|
+
|
|
|
+#define READ_2x2_PIXELS \
|
|
|
+ const Uint8 b = (curr_row[8 * i + 0] + curr_row[8 * i + 4] \
|
|
|
+ + next_row[8 * i + 0] + next_row[8 * i + 4] ) >> 2; \
|
|
|
+ const Uint8 g = (curr_row[8 * i + 1] + curr_row[8 * i + 5] \
|
|
|
+ + next_row[8 * i + 1] + next_row[8 * i + 5] ) >> 2; \
|
|
|
+ const Uint8 r = (curr_row[8 * i + 2] + curr_row[8 * i + 6] \
|
|
|
+ + next_row[8 * i + 2] + next_row[8 * i + 6] ) >> 2; \
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+#define READ_2x1_PIXELS \
|
|
|
+ const Uint8 b = (curr_row[8 * i + 0] + next_row[8 * i + 0]) >> 1; \
|
|
|
+ const Uint8 g = (curr_row[8 * i + 1] + next_row[8 * i + 1]) >> 1; \
|
|
|
+ const Uint8 r = (curr_row[8 * i + 2] + next_row[8 * i + 2]) >> 1; \
|
|
|
+
|
|
|
+#define READ_1x2_PIXELS \
|
|
|
+ const Uint8 b = (curr_row[8 * i + 0] + curr_row[8 * i + 4]) >> 1; \
|
|
|
+ const Uint8 g = (curr_row[8 * i + 1] + curr_row[8 * i + 5]) >> 1; \
|
|
|
+ const Uint8 r = (curr_row[8 * i + 2] + curr_row[8 * i + 6]) >> 1; \
|
|
|
+
|
|
|
+#define READ_1x1_PIXEL \
|
|
|
+ const Uint8 b = curr_row[8 * i + 0]; \
|
|
|
+ const Uint8 g = curr_row[8 * i + 1]; \
|
|
|
+ const Uint8 r = curr_row[8 * i + 2]; \
|
|
|
+
|
|
|
+ if (dst_format == SDL_PIXELFORMAT_YV12 || dst_format == SDL_PIXELFORMAT_IYUV)
|
|
|
+ {
|
|
|
+ /* Write UV planes, not interleaved */
|
|
|
+ for (j = 0; j < height_half; j++) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ READ_2x2_PIXELS;
|
|
|
+ *plane_u++ = MAKE_U(r, g, b);
|
|
|
+ *plane_v++ = MAKE_V(r, g, b);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ READ_2x1_PIXELS;
|
|
|
+ *plane_u++ = MAKE_U(r, g, b);
|
|
|
+ *plane_v++ = MAKE_V(r, g, b);
|
|
|
+ }
|
|
|
+ curr_row += src_pitch_x_2;
|
|
|
+ next_row += src_pitch_x_2;
|
|
|
+ }
|
|
|
+ if (height_remainder) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ READ_1x2_PIXELS;
|
|
|
+ *plane_u++ = MAKE_U(r, g, b);
|
|
|
+ *plane_v++ = MAKE_V(r, g, b);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ READ_1x1_PIXEL;
|
|
|
+ *plane_u++ = MAKE_U(r, g, b);
|
|
|
+ *plane_v++ = MAKE_V(r, g, b);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (dst_format == SDL_PIXELFORMAT_NV12)
|
|
|
+ {
|
|
|
+ for (j = 0; j < height_half; j++) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ READ_2x2_PIXELS;
|
|
|
+ *plane_interleaved_uv++ = MAKE_U(r, g, b);
|
|
|
+ *plane_interleaved_uv++ = MAKE_V(r, g, b);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ READ_2x1_PIXELS;
|
|
|
+ *plane_interleaved_uv++ = MAKE_U(r, g, b);
|
|
|
+ *plane_interleaved_uv++ = MAKE_V(r, g, b);
|
|
|
+ }
|
|
|
+ curr_row += src_pitch_x_2;
|
|
|
+ next_row += src_pitch_x_2;
|
|
|
+ }
|
|
|
+ if (height_remainder) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ READ_1x2_PIXELS;
|
|
|
+ *plane_interleaved_uv++ = MAKE_U(r, g, b);
|
|
|
+ *plane_interleaved_uv++ = MAKE_V(r, g, b);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ READ_1x1_PIXEL;
|
|
|
+ *plane_interleaved_uv++ = MAKE_U(r, g, b);
|
|
|
+ *plane_interleaved_uv++ = MAKE_V(r, g, b);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else /* dst_format == SDL_PIXELFORMAT_NV21 */
|
|
|
+ {
|
|
|
+ for (j = 0; j < height_half; j++) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ READ_2x2_PIXELS;
|
|
|
+ *plane_interleaved_uv++ = MAKE_V(r, g, b);
|
|
|
+ *plane_interleaved_uv++ = MAKE_U(r, g, b);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ READ_2x1_PIXELS;
|
|
|
+ *plane_interleaved_uv++ = MAKE_V(r, g, b);
|
|
|
+ *plane_interleaved_uv++ = MAKE_U(r, g, b);
|
|
|
+ }
|
|
|
+ curr_row += src_pitch_x_2;
|
|
|
+ next_row += src_pitch_x_2;
|
|
|
+ }
|
|
|
+ if (height_remainder) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ READ_1x2_PIXELS;
|
|
|
+ *plane_interleaved_uv++ = MAKE_V(r, g, b);
|
|
|
+ *plane_interleaved_uv++ = MAKE_U(r, g, b);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ READ_1x1_PIXEL;
|
|
|
+ *plane_interleaved_uv++ = MAKE_V(r, g, b);
|
|
|
+ *plane_interleaved_uv++ = MAKE_U(r, g, b);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+#undef READ_2x2_PIXELS
|
|
|
+#undef READ_2x1_PIXELS
|
|
|
+#undef READ_1x2_PIXELS
|
|
|
+#undef READ_1x1_PIXEL
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SDL_PIXELFORMAT_YUY2:
|
|
|
+ case SDL_PIXELFORMAT_UYVY:
|
|
|
+ case SDL_PIXELFORMAT_YVYU:
|
|
|
+ {
|
|
|
+ const Uint8 *curr_row = (const Uint8*) src;
|
|
|
+ Uint8 *plane = (Uint8*) dst;
|
|
|
+
|
|
|
+#define READ_TWO_RGB_PIXELS \
|
|
|
+ const Uint8 b = curr_row[8 * i + 0]; \
|
|
|
+ const Uint8 g = curr_row[8 * i + 1]; \
|
|
|
+ const Uint8 r = curr_row[8 * i + 2]; \
|
|
|
+ const Uint8 b1 = curr_row[8 * i + 4]; \
|
|
|
+ const Uint8 g1 = curr_row[8 * i + 5]; \
|
|
|
+ const Uint8 r1 = curr_row[8 * i + 6]; \
|
|
|
+ const Uint8 B = (b + b1) >> 1; \
|
|
|
+ const Uint8 G = (g + g1) >> 1; \
|
|
|
+ const Uint8 R = (r + r1) >> 1; \
|
|
|
+
|
|
|
+#define READ_ONE_RGB_PIXEL \
|
|
|
+ const Uint8 b = curr_row[8 * i + 0]; \
|
|
|
+ const Uint8 g = curr_row[8 * i + 1]; \
|
|
|
+ const Uint8 r = curr_row[8 * i + 2]; \
|
|
|
+
|
|
|
+ /* Write YUV plane, packed */
|
|
|
+ if (dst_format == SDL_PIXELFORMAT_YUY2)
|
|
|
+ {
|
|
|
+ for (j = 0; j < height; j++) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ READ_TWO_RGB_PIXELS;
|
|
|
+ /* Y U Y1 V */
|
|
|
+ *plane++ = MAKE_Y(r, g, b);
|
|
|
+ *plane++ = MAKE_U(R, G, B);
|
|
|
+ *plane++ = MAKE_Y(r1, g1, b1);
|
|
|
+ *plane++ = MAKE_V(R, G, B);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ READ_ONE_RGB_PIXEL;
|
|
|
+ /* Y U Y V */
|
|
|
+ *plane++ = MAKE_Y(r, g, b);
|
|
|
+ *plane++ = MAKE_U(r, g, b);
|
|
|
+ *plane++ = MAKE_Y(r, g, b);
|
|
|
+ *plane++ = MAKE_V(r, g, b);
|
|
|
+ }
|
|
|
+ curr_row += src_pitch;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (dst_format == SDL_PIXELFORMAT_UYVY)
|
|
|
+ {
|
|
|
+ for (j = 0; j < height; j++) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ READ_TWO_RGB_PIXELS;
|
|
|
+ /* U Y V Y1 */
|
|
|
+ *plane++ = MAKE_U(R, G, B);
|
|
|
+ *plane++ = MAKE_Y(r, g, b);
|
|
|
+ *plane++ = MAKE_V(R, G, B);
|
|
|
+ *plane++ = MAKE_Y(r1, g1, b1);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ READ_ONE_RGB_PIXEL;
|
|
|
+ /* U Y V Y */
|
|
|
+ *plane++ = MAKE_U(r, g, b);
|
|
|
+ *plane++ = MAKE_Y(r, g, b);
|
|
|
+ *plane++ = MAKE_V(r, g, b);
|
|
|
+ *plane++ = MAKE_Y(r, g, b);
|
|
|
+ }
|
|
|
+ curr_row += src_pitch;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (dst_format == SDL_PIXELFORMAT_YVYU)
|
|
|
+ {
|
|
|
+ for (j = 0; j < height; j++) {
|
|
|
+ for (i = 0; i < width_half; i++) {
|
|
|
+ READ_TWO_RGB_PIXELS;
|
|
|
+ /* Y V Y1 U */
|
|
|
+ *plane++ = MAKE_Y(r, g, b);
|
|
|
+ *plane++ = MAKE_V(R, G, B);
|
|
|
+ *plane++ = MAKE_Y(r1, g1, b1);
|
|
|
+ *plane++ = MAKE_U(R, G, B);
|
|
|
+ }
|
|
|
+ if (width_remainder) {
|
|
|
+ READ_ONE_RGB_PIXEL;
|
|
|
+ /* Y V Y U */
|
|
|
+ *plane++ = MAKE_Y(r, g, b);
|
|
|
+ *plane++ = MAKE_V(r, g, b);
|
|
|
+ *plane++ = MAKE_Y(r, g, b);
|
|
|
+ *plane++ = MAKE_U(r, g, b);
|
|
|
+ }
|
|
|
+ curr_row += src_pitch;
|
|
|
+ }
|
|
|
+ }
|
|
|
+#undef READ_TWO_RGB_PIXELS
|
|
|
+#undef READ_ONE_RGB_PIXEL
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/* vi: set ts=4 sw=4 expandtab: */
|