diff options
-rw-r--r-- | src/video_out/video_out_xshm.c | 140 | ||||
-rw-r--r-- | src/video_out/yuv2rgb.c | 896 | ||||
-rw-r--r-- | src/video_out/yuv2rgb.h | 24 |
3 files changed, 972 insertions, 88 deletions
diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c index 709f6a452..447f658be 100644 --- a/src/video_out/video_out_xshm.c +++ b/src/video_out/video_out_xshm.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_xshm.c,v 1.36 2001/09/21 14:34:58 jkeil Exp $ + * $Id: video_out_xshm.c,v 1.37 2001/09/23 15:14:01 jkeil Exp $ * * video_out_xshm.c, X11 shared memory extension interface for xine * @@ -41,6 +41,7 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> +#include <X11/Xatom.h> #include <X11/cursorfont.h> #include <errno.h> @@ -95,8 +96,9 @@ typedef struct xshm_driver_s { int use_shm; int zoom_mpeg1; int scaling_disabled; - int depth, bpp, bytes_per_pixel, byte_order; + int depth, bpp, bytes_per_pixel, image_byte_order; int expecting_event; + uint8_t *fast_rgb; yuv2rgb_t *yuv2rgb; @@ -232,7 +234,7 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, this->bpp = myimage->bits_per_pixel; this->bytes_per_pixel = this->bpp / 8; - this->byte_order = myimage->byte_order; + this->image_byte_order = myimage->byte_order; shminfo->shmid=shmget(IPC_PRIVATE, myimage->bytes_per_line * myimage->height, @@ -304,7 +306,7 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, this->bpp = myimage->bits_per_pixel; this->bytes_per_pixel = this->bpp / 8; - this->byte_order = myimage->byte_order; + this->image_byte_order = myimage->byte_order; myimage->data = xmalloc (width * this->bytes_per_pixel * height); } @@ -992,6 +994,61 @@ static void xshm_exit (vo_driver_t *this_gen) { } +static int +ImlibPaletteLUTGet(xshm_driver_t *this) +{ + unsigned char *retval; + Atom type_ret; + unsigned long bytes_after, num_ret; + int format_ret; + long length; + Atom to_get; + + retval = NULL; + length = 0x7fffffff; + to_get = XInternAtom(this->display, "_IMLIB_COLORMAP", False); + XGetWindowProperty(this->display, RootWindow(this->display, this->screen), + to_get, 0, length, False, + XA_CARDINAL, &type_ret, &format_ret, &num_ret, + &bytes_after, &retval); + if (retval != 0 && num_ret > 0 && format_ret > 0) { + if (format_ret == 8) { + int j, i, num_colors; + + num_colors = retval[0]; + j = 1 + num_colors*4; + this->fast_rgb = malloc(sizeof(uint8_t) * 32 * 32 * 32); + for (i = 0; i < 32 * 32 * 32 && j < num_ret; i++) + this->fast_rgb[i] = retval[j++]; + XFree(retval); + return 1; + } else + XFree(retval); + } + return 0; +} + + +static char *visual_class_name(Visual *visual) +{ + switch (visual->class) { + case StaticGray: + return "StaticGray"; + case GrayScale: + return "GrayScale"; + case StaticColor: + return "StaticColor"; + case PseudoColor: + return "PseudoColor"; + case TrueColor: + return "TrueColor"; + case DirectColor: + return "DirectColor"; + default: + return "unknown visual class"; + } +} + vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { xshm_driver_t *this; @@ -1104,46 +1161,67 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { myimage = create_ximage (this, &myshminfo, 100, 100); dispose_ximage (this, &myshminfo, myimage); - mode = 0; + /* + * Is the same byte order in use on the X11 client and server? + */ cpu_byte_order = htonl(1) == 1 ? MSBFirst : LSBFirst; - swapped = cpu_byte_order != this->byte_order; + swapped = cpu_byte_order != this->image_byte_order; - printf ("video_out_xshm: video mode depth is %d (%d bpp), %sswapped,\n" + printf ("video_out_xshm: video mode depth is %d (%d bpp), %s, %sswapped,\n" "\tred: %08lx, green: %08lx, blue: %08lx\n", this->depth, this->bpp, + visual_class_name(this->visual), swapped ? "" : "not ", this->visual->red_mask, this->visual->green_mask, this->visual->blue_mask); - switch (this->depth) { - case 24: - if (this->bpp == 32) { - if (this->visual->red_mask == 0x00ff0000) - mode = MODE_32_RGB; + mode = 0; + + switch (this->visual->class) { + case TrueColor: + switch (this->depth) { + case 24: + if (this->bpp == 32) { + if (this->visual->red_mask == 0x00ff0000) + mode = MODE_32_RGB; + else + mode = MODE_32_BGR; + } else { + if (this->visual->red_mask == 0x00ff0000) + mode = MODE_24_RGB; + else + mode = MODE_24_BGR; + } + break; + case 16: + if (this->visual->red_mask == 0xf800) + mode = MODE_16_RGB; else - mode = MODE_32_BGR; + mode = MODE_16_BGR; break; - } else { - if (this->visual->red_mask == 0x00ff0000) - mode = MODE_24_RGB; + case 15: + if (this->visual->red_mask == 0x7C00) + mode = MODE_15_RGB; else - mode = MODE_24_BGR; + mode = MODE_15_BGR; + break; + case 8: + if (this->visual->red_mask == 0xE0) + mode = MODE_8_RGB; /* Solaris x86: RGB332 */ + else + mode = MODE_8_BGR; /* XFree86: BGR233 */ + break; } break; - case 16: - if (this->visual->red_mask == 0xf800) - mode = MODE_16_RGB; - else - mode = MODE_16_BGR; - break; - case 15: - if (this->visual->red_mask == 0x7C00) - mode = MODE_15_RGB; - else - mode = MODE_15_BGR; + + case StaticGray: + if (this->depth == 8) + mode = MODE_8_GRAY; break; - case 8: - mode = MODE_PALETTE; + + case PseudoColor: + if (this->depth <= 8 && ImlibPaletteLUTGet(this)) + mode = MODE_PALETTE; break; } @@ -1152,7 +1230,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { return NULL; } - this->yuv2rgb = yuv2rgb_init (mode, swapped); + this->yuv2rgb = yuv2rgb_init (mode, swapped, this->fast_rgb); return &this->vo_driver; } diff --git a/src/video_out/yuv2rgb.c b/src/video_out/yuv2rgb.c index 08a880d5f..436d7d98c 100644 --- a/src/video_out/yuv2rgb.c +++ b/src/video_out/yuv2rgb.c @@ -22,7 +22,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: yuv2rgb.c,v 1.17 2001/09/21 14:34:58 jkeil Exp $ + * $Id: yuv2rgb.c,v 1.18 2001/09/23 15:14:01 jkeil Exp $ */ #include "config.h" @@ -254,14 +254,19 @@ static void scale_line_5_7 (uint8_t *source, uint8_t *dest, p1 = p2; } - switch (width + 7) { - case 6: *dest++ = source[0]; - case 5: *dest++ = (1*source[0] + 3*source[1]) >> 2; - case 4: *dest++ = (5*source[1] + 3*source[2]) >> 3; - case 3: *dest++ = (7*source[2] + 1*source[3]) >> 3; - case 2: *dest++ = (1*source[2] + 7*source[3]) >> 3; - case 1: *dest++ = (3*source[3] + 5*source[4]) >> 3; - } + if ((width += 7) <= 0) goto done; + *dest++ = source[0]; + if (--width <= 0) goto done; + *dest++ = (1*source[0] + 3*source[1]) >> 2; + if (--width <= 0) goto done; + *dest++ = (5*source[1] + 3*source[2]) >> 3; + if (--width <= 0) goto done; + *dest++ = (7*source[2] + 1*source[3]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[2] + 7*source[3]) >> 3; + if (--width <= 0) goto done; + *dest++ = (3*source[3] + 5*source[4]) >> 3; +done: profiler_stop_count(prof_scale_line); } @@ -315,34 +320,384 @@ static void scale_line_15_16 (uint8_t *source, uint8_t *dest, dest += 16; } - switch (width + 16) { - case 15: *dest++ = source[0]; - case 14: *dest++ = (1*source[0] + 7*source[1]) >> 3; - case 13: *dest++ = (1*source[1] + 7*source[2]) >> 3; - case 12: *dest++ = (1*source[2] + 3*source[3]) >> 2; - case 11: *dest++ = (1*source[3] + 3*source[4]) >> 2; - case 10: *dest++ = (3*source[4] + 5*source[5]) >> 3; - case 9: *dest++ = (3*source[5] + 5*source[6]) >> 3; - case 8: *dest++ = (1*source[6] + 1*source[7]) >> 1; - case 7: *dest++ = (1*source[7] + 1*source[8]) >> 1; - case 6: *dest++ = (5*source[8] + 3*source[9]) >> 3; - case 5: *dest++ = (5*source[9] + 3*source[10]) >> 3; - case 4: *dest++ = (3*source[10] + 1*source[11]) >> 2; - case 3: *dest++ = (3*source[11] + 1*source[12]) >> 2; - case 2: *dest++ = (7*source[12] + 1*source[13]) >> 3; - case 1: *dest++ = (7*source[13] + 1*source[14]) >> 3; + if ((width += 16) <= 0) goto done; + *dest++ = source[0]; + if (--width <= 0) goto done; + *dest++ = (1*source[0] + 7*source[1]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[1] + 7*source[2]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[2] + 3*source[3]) >> 2; + if (--width <= 0) goto done; + *dest++ = (1*source[3] + 3*source[4]) >> 2; + if (--width <= 0) goto done; + *dest++ = (3*source[4] + 5*source[5]) >> 3; + if (--width <= 0) goto done; + *dest++ = (3*source[5] + 5*source[6]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[6] + 1*source[7]) >> 1; + if (--width <= 0) goto done; + *dest++ = (1*source[7] + 1*source[8]) >> 1; + if (--width <= 0) goto done; + *dest++ = (5*source[8] + 3*source[9]) >> 3; + if (--width <= 0) goto done; + *dest++ = (5*source[9] + 3*source[10]) >> 3; + if (--width <= 0) goto done; + *dest++ = (3*source[10] + 1*source[11]) >> 2; + if (--width <= 0) goto done; + *dest++ = (3*source[11] + 1*source[12]) >> 2; + if (--width <= 0) goto done; + *dest++ = (7*source[12] + 1*source[13]) >> 3; + if (--width <= 0) goto done; + *dest++ = (7*source[13] + 1*source[14]) >> 3; + done: + profiler_stop_count(prof_scale_line); +} + + +/* + * Interpolates 64 output pixels from 45 source pixels using shifts. + * Useful for scaling an mpeg2 dvd input source to 1024x768 fullscreen + * (720 x 576 ==> 1024 x XXX) + */ +static void scale_line_45_64 (uint8_t *source, uint8_t *dest, + int width, int step) { + + int p1, p2; + + profiler_start_count(prof_scale_line); + + while ((width -= 64) >= 0) { + p1 = source[0]; + p2 = source[1]; + dest[0] = p1; + dest[1] = (1*p1 + 3*p2) >> 2; + p1 = source[2]; + dest[2] = (5*p2 + 3*p1) >> 3; + p2 = source[3]; + dest[3] = (7*p1 + 1*p2) >> 3; + dest[4] = (1*p1 + 3*p2) >> 2; + p1 = source[4]; + dest[5] = (1*p2 + 1*p1) >> 1; + p2 = source[5]; + dest[6] = (3*p1 + 1*p2) >> 2; + dest[7] = (1*p1 + 7*p2) >> 3; + p1 = source[6]; + dest[8] = (3*p2 + 5*p1) >> 3; + p2 = source[7]; + dest[9] = (5*p1 + 3*p2) >> 3; + p1 = source[8]; + dest[10] = p2; + dest[11] = (1*p2 + 3*p1) >> 2; + p2 = source[9]; + dest[12] = (5*p1 + 3*p2) >> 3; + p1 = source[10]; + dest[13] = (7*p2 + 1*p1) >> 3; + dest[14] = (1*p2 + 7*p1) >> 3; + p2 = source[11]; + dest[15] = (1*p1 + 1*p2) >> 1; + p1 = source[12]; + dest[16] = (3*p2 + 1*p1) >> 2; + dest[17] = p1; + p2 = source[13]; + dest[18] = (3*p1 + 5*p2) >> 3; + p1 = source[14]; + dest[19] = (5*p2 + 3*p1) >> 3; + p2 = source[15]; + dest[20] = p1; + dest[21] = (1*p1 + 3*p2) >> 2; + p1 = source[16]; + dest[22] = (1*p2 + 1*p1) >> 1; + p2 = source[17]; + dest[23] = (7*p1 + 1*p2) >> 3; + dest[24] = (1*p1 + 7*p2) >> 3; + p1 = source[18]; + dest[25] = (3*p2 + 5*p1) >> 3; + p2 = source[19]; + dest[26] = (3*p1 + 1*p2) >> 2; + dest[27] = p2; + p1 = source[20]; + dest[28] = (3*p2 + 5*p1) >> 3; + p2 = source[21]; + dest[29] = (5*p1 + 3*p2) >> 3; + p1 = source[22]; + dest[30] = (7*p2 + 1*p1) >> 3; + dest[31] = (1*p2 + 3*p1) >> 2; + p2 = source[23]; + dest[32] = (1*p1 + 1*p2) >> 1; + p1 = source[24]; + dest[33] = (3*p2 + 1*p1) >> 2; + dest[34] = (1*p2 + 7*p1) >> 3; + p2 = source[25]; + dest[35] = (3*p1 + 5*p2) >> 3; + p1 = source[26]; + dest[36] = (3*p2 + 1*p1) >> 2; + p2 = source[27]; + dest[37] = p1; + dest[38] = (1*p1 + 3*p2) >> 2; + p1 = source[28]; + dest[39] = (5*p2 + 3*p1) >> 3; + p2 = source[29]; + dest[40] = (7*p1 + 1*p2) >> 3; + dest[41] = (1*p1 + 7*p2) >> 3; + p1 = source[30]; + dest[42] = (1*p2 + 1*p1) >> 1; + p2 = source[31]; + dest[43] = (3*p1 + 1*p2) >> 2; + dest[44] = (1*p1 + 7*p2) >> 3; + p1 = source[32]; + dest[45] = (3*p2 + 5*p1) >> 3; + p2 = source[33]; + dest[46] = (5*p1 + 3*p2) >> 3; + p1 = source[34]; + dest[47] = p2; + dest[48] = (1*p2 + 3*p1) >> 2; + p2 = source[35]; + dest[49] = (1*p1 + 1*p2) >> 1; + p1 = source[36]; + dest[50] = (7*p2 + 1*p1) >> 3; + dest[51] = (1*p2 + 7*p1) >> 3; + p2 = source[37]; + dest[52] = (1*p1 + 1*p2) >> 1; + p1 = source[38]; + dest[53] = (3*p2 + 1*p1) >> 2; + dest[54] = p1; + p2 = source[39]; + dest[55] = (3*p1 + 5*p2) >> 3; + p1 = source[40]; + dest[56] = (5*p2 + 3*p1) >> 3; + p2 = source[41]; + dest[57] = (7*p1 + 1*p2) >> 3; + dest[58] = (1*p1 + 3*p2) >> 2; + p1 = source[42]; + dest[59] = (1*p2 + 1*p1) >> 1; + p2 = source[43]; + dest[60] = (7*p1 + 1*p2) >> 3; + dest[61] = (1*p1 + 7*p2) >> 3; + p1 = source[44]; + dest[62] = (3*p2 + 5*p1) >> 3; + p2 = source[45]; + dest[63] = (3*p1 + 1*p2) >> 2; + source += 45; + dest += 64; } + if ((width += 64) <= 0) goto done; + *dest++ = source[0]; + if (--width <= 0) goto done; + *dest++ = (1*source[0] + 3*source[1]) >> 2; + if (--width <= 0) goto done; + *dest++ = (5*source[1] + 3*source[2]) >> 3; + if (--width <= 0) goto done; + *dest++ = (7*source[2] + 1*source[3]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[2] + 3*source[3]) >> 2; + if (--width <= 0) goto done; + *dest++ = (1*source[3] + 1*source[4]) >> 1; + if (--width <= 0) goto done; + *dest++ = (3*source[4] + 1*source[5]) >> 2; + if (--width <= 0) goto done; + *dest++ = (1*source[4] + 7*source[5]) >> 3; + if (--width <= 0) goto done; + *dest++ = (3*source[5] + 5*source[6]) >> 3; + if (--width <= 0) goto done; + *dest++ = (5*source[6] + 3*source[7]) >> 3; + if (--width <= 0) goto done; + *dest++ = source[7]; + if (--width <= 0) goto done; + *dest++ = (1*source[7] + 3*source[8]) >> 2; + if (--width <= 0) goto done; + *dest++ = (5*source[8] + 3*source[9]) >> 3; + if (--width <= 0) goto done; + *dest++ = (7*source[9] + 1*source[10]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[9] + 7*source[10]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[10] + 1*source[11]) >> 1; + if (--width <= 0) goto done; + *dest++ = (3*source[11] + 1*source[12]) >> 2; + if (--width <= 0) goto done; + *dest++ = source[12]; + if (--width <= 0) goto done; + *dest++ = (3*source[12] + 5*source[13]) >> 3; + if (--width <= 0) goto done; + *dest++ = (5*source[13] + 3*source[14]) >> 3; + if (--width <= 0) goto done; + *dest++ = source[14]; + if (--width <= 0) goto done; + *dest++ = (1*source[14] + 3*source[15]) >> 2; + if (--width <= 0) goto done; + *dest++ = (1*source[15] + 1*source[16]) >> 1; + if (--width <= 0) goto done; + *dest++ = (7*source[16] + 1*source[17]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[16] + 7*source[17]) >> 3; + if (--width <= 0) goto done; + *dest++ = (3*source[17] + 5*source[18]) >> 3; + if (--width <= 0) goto done; + *dest++ = (3*source[18] + 1*source[19]) >> 2; + if (--width <= 0) goto done; + *dest++ = source[19]; + if (--width <= 0) goto done; + *dest++ = (3*source[19] + 5*source[20]) >> 3; + if (--width <= 0) goto done; + *dest++ = (5*source[20] + 3*source[21]) >> 3; + if (--width <= 0) goto done; + *dest++ = (7*source[21] + 1*source[22]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[21] + 3*source[22]) >> 2; + if (--width <= 0) goto done; + *dest++ = (1*source[22] + 1*source[23]) >> 1; + if (--width <= 0) goto done; + *dest++ = (3*source[23] + 1*source[24]) >> 2; + if (--width <= 0) goto done; + *dest++ = (1*source[23] + 7*source[24]) >> 3; + if (--width <= 0) goto done; + *dest++ = (3*source[24] + 5*source[25]) >> 3; + if (--width <= 0) goto done; + *dest++ = (3*source[25] + 1*source[26]) >> 2; + if (--width <= 0) goto done; + *dest++ = source[26]; + if (--width <= 0) goto done; + *dest++ = (1*source[26] + 3*source[27]) >> 2; + if (--width <= 0) goto done; + *dest++ = (5*source[27] + 3*source[28]) >> 3; + if (--width <= 0) goto done; + *dest++ = (7*source[28] + 1*source[29]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[28] + 7*source[29]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[29] + 1*source[30]) >> 1; + if (--width <= 0) goto done; + *dest++ = (3*source[30] + 1*source[31]) >> 2; + if (--width <= 0) goto done; + *dest++ = (1*source[30] + 7*source[31]) >> 3; + if (--width <= 0) goto done; + *dest++ = (3*source[31] + 5*source[32]) >> 3; + if (--width <= 0) goto done; + *dest++ = (5*source[32] + 3*source[33]) >> 3; + if (--width <= 0) goto done; + *dest++ = source[33]; + if (--width <= 0) goto done; + *dest++ = (1*source[33] + 3*source[34]) >> 2; + if (--width <= 0) goto done; + *dest++ = (1*source[34] + 1*source[35]) >> 1; + if (--width <= 0) goto done; + *dest++ = (7*source[35] + 1*source[36]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[35] + 7*source[36]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[36] + 1*source[37]) >> 1; + if (--width <= 0) goto done; + *dest++ = (3*source[37] + 1*source[38]) >> 2; + if (--width <= 0) goto done; + *dest++ = source[38]; + if (--width <= 0) goto done; + *dest++ = (3*source[38] + 5*source[39]) >> 3; + if (--width <= 0) goto done; + *dest++ = (5*source[39] + 3*source[40]) >> 3; + if (--width <= 0) goto done; + *dest++ = (7*source[40] + 1*source[41]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[40] + 3*source[41]) >> 2; + if (--width <= 0) goto done; + *dest++ = (1*source[41] + 1*source[42]) >> 1; + if (--width <= 0) goto done; + *dest++ = (7*source[42] + 1*source[43]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[42] + 7*source[43]) >> 3; + if (--width <= 0) goto done; + *dest++ = (3*source[43] + 5*source[44]) >> 3; + done: + profiler_stop_count(prof_scale_line); } - + +/* + * Interpolates 16 output pixels from 9 source pixels using shifts. + * Useful for scaling an mpeg2 dvd input source to 1280x1024 fullscreen + * (720 x 576 ==> 1280 x XXX) + */ +static void scale_line_9_16 (uint8_t *source, uint8_t *dest, + int width, int step) { + + int p1, p2; + + profiler_start_count(prof_scale_line); + + while ((width -= 16) >= 0) { + p1 = source[0]; + p2 = source[1]; + dest[0] = p1; + dest[1] = (1*p1 + 1*p2) >> 1; + p1 = source[2]; + dest[2] = (7*p2 + 1*p1) >> 3; + dest[3] = (3*p2 + 5*p1) >> 3; + p2 = source[3]; + dest[4] = (3*p1 + 1*p2) >> 2; + dest[5] = (1*p1 + 3*p2) >> 2; + p1 = source[4]; + dest[6] = (5*p2 + 3*p1) >> 3; + dest[7] = (1*p2 + 7*p1) >> 3; + p2 = source[5]; + dest[8] = (1*p1 + 1*p2) >> 1; + p1 = source[6]; + dest[9] = p2; + dest[10] = (3*p2 + 5*p1) >> 3; + p2 = source[7]; + dest[11] = (7*p1 + 1*p2) >> 3; + dest[12] = (1*p1 + 3*p2) >> 2; + p1 = source[8]; + dest[13] = (3*p2 + 1*p1) >> 2; + dest[14] = (1*p2 + 7*p1) >> 3; + p2 = source[9]; + dest[15] = (5*p1 + 3*p2) >> 3; + source += 9; + dest += 16; + } + + if ((width += 16) <= 0) goto done; + *dest++ = source[0]; + if (--width <= 0) goto done; + *dest++ = (1*source[0] + 1*source[1]) >> 1; + if (--width <= 0) goto done; + *dest++ = (7*source[1] + 1*source[2]) >> 3; + if (--width <= 0) goto done; + *dest++ = (3*source[1] + 5*source[2]) >> 3; + if (--width <= 0) goto done; + *dest++ = (3*source[2] + 1*source[3]) >> 2; + if (--width <= 0) goto done; + *dest++ = (1*source[2] + 3*source[3]) >> 2; + if (--width <= 0) goto done; + *dest++ = (5*source[3] + 3*source[4]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[3] + 7*source[4]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[4] + 1*source[5]) >> 1; + if (--width <= 0) goto done; + *dest++ = source[5]; + if (--width <= 0) goto done; + *dest++ = (3*source[5] + 5*source[6]) >> 3; + if (--width <= 0) goto done; + *dest++ = (7*source[6] + 1*source[7]) >> 3; + if (--width <= 0) goto done; + *dest++ = (1*source[6] + 3*source[7]) >> 2; + if (--width <= 0) goto done; + *dest++ = (3*source[7] + 1*source[8]) >> 2; + if (--width <= 0) goto done; + *dest++ = (1*source[7] + 7*source[8]) >> 3; +done: + profiler_stop_count(prof_scale_line); +} + + +/* Interpolate 2 output pixels from one source pixel. */ + static void scale_line_1_2 (uint8_t *source, uint8_t *dest, int width, int step) { int p1, p2; - /* Interpolates 2 output pixels from one source pixels. */ - profiler_start_count(prof_scale_line); p1 = *source; @@ -355,11 +710,13 @@ static void scale_line_1_2 (uint8_t *source, uint8_t *dest, *dest++ = (p2 + p1) >> 1; } - switch (width + 4) { - case 3: *dest++ = source[0]; - case 2: *dest++ = (source[0] + source[1]) >> 1; - case 1: *dest++ = source[1]; - } + if ((width += 4) <= 0) goto done; + *dest++ = source[0]; + if (--width <= 0) goto done; + *dest++ = (source[0] + source[1]) >> 1; + if (--width <= 0) goto done; + *dest++ = source[1]; + done: profiler_stop_count(prof_scale_line); } @@ -375,6 +732,14 @@ static scale_line_func_t find_scale_line_func(int step) { printf("yuv2rgb: using dvd 4:3 optimized scale_line\n"); return scale_line_15_16; } + if (abs(step - 45*32768/64) < 10) { + printf("yuv2rgb: using dvd fullscreen(1024x768) optimized scale_line\n"); + return scale_line_45_64; + } + if (abs(step - 9*32768/16) < 10) { + printf("yuv2rgb: using dvd fullscreen(1280x1024) optimized scale_line\n"); + return scale_line_9_16; + } if (abs(step - 1*32768/2) < 10) { printf("yuv2rgb: using optimized 2*zoom scale_line\n"); return scale_line_1_2; @@ -486,6 +851,18 @@ static void scale_line_4 (uint8_t *source, uint8_t *dest, Y = py_2[2*i+1]; \ dst_2[6*i+3] = b[Y]; dst_2[6*i+4] = g[Y]; dst_2[6*i+5] = r[Y]; +#define DST1CMAP(i) \ + Y = py_1[2*i]; \ + dst_1[2*i] = this->fast_rgb[r[Y] + g[Y] + b[Y]]; \ + Y = py_1[2*i+1]; \ + dst_1[2*i+1] = this->fast_rgb[r[Y] + g[Y] + b[Y]]; + +#define DST2CMAP(i) \ + Y = py_2[2*i]; \ + dst_2[2*i] = this->fast_rgb[r[Y] + g[Y] + b[Y]]; \ + Y = py_2[2*i+1]; \ + dst_2[2*i+1] = this->fast_rgb[r[Y] + g[Y] + b[Y]]; + static void yuv2rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _py, uint8_t * _pu, uint8_t * _pv) { @@ -995,11 +1372,14 @@ static void yuv2rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, } } -/* now for something different: 256 color mode */ -static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, - uint8_t * _py, uint8_t * _pu, uint8_t * _pv) +/* This is exactly the same code as yuv2rgb_c_32 except for the types of */ +/* r, g, b, dst_1, dst_2 */ +static void yuv2rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, + uint8_t * _py, uint8_t * _pu, uint8_t * _pv) { - uint8_t * py_1, * py_2, * pu, * pv; + int U, V, Y; + uint8_t * py_1, * py_2, * pu, * pv; + uint8_t * r, * g, * b; uint8_t * dst_1, * dst_2; int width, height, dst_height; int dy; @@ -1018,7 +1398,7 @@ static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, dst_height = this->dest_height; for (height = 0;; height++) { - dst_1 = _dst; + dst_1 = (uint8_t*)_dst; py_1 = this->y_buffer; pu = this->u_buffer; pv = this->v_buffer; @@ -1026,7 +1406,6 @@ static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, width = this->dest_width >> 3; do { - /* FIXME RGB(0); DST1(0); @@ -1038,7 +1417,6 @@ static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, RGB(3); DST1(3); - */ pu += 4; pv += 4; @@ -1051,7 +1429,7 @@ static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, while (--dst_height > 0 && dy < 32768) { - memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2); + memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); dy += this->step_dy; _dst += this->rgb_stride; @@ -1080,15 +1458,15 @@ static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, } else { height = this->source_height >> 1; do { - dst_1 = _dst; - dst_2 = _dst + this->rgb_stride; + dst_1 = (uint8_t*)_dst; + dst_2 = (void*)( (uint8_t *)_dst + this->rgb_stride ); py_1 = _py; py_2 = _py + this->y_stride; pu = _pu; pv = _pv; + width = this->source_width >> 3; do { - /* RGB(0); DST1(0); DST2(0); @@ -1104,7 +1482,174 @@ static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, RGB(3); DST2(3); DST1(3); - */ + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 8; + dst_2 += 8; + } while (--width); + + _dst += 2 * this->rgb_stride; + _py += 2 * this->y_stride; + _pu += this->uv_stride; + _pv += this->uv_stride; + + } while (--height); + } +} + +/* now for something different: 256 grayscale mode */ +static void yuv2rgb_c_gray (yuv2rgb_t *this, uint8_t * _dst, + uint8_t * _py, uint8_t * _pu, uint8_t * _pv) +{ + int height, dst_height; + int dy; + + if (this->do_scale) { + scale_line_func_t scale_line = this->scale_line; + + dy = 0; + dst_height = this->dest_height; + + for (;;) { + scale_line (_py, _dst, this->dest_width, this->step_dx); + + dy += this->step_dy; + _dst += this->rgb_stride; + + while (--dst_height > 0 && dy < 32768) { + + memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); + + dy += this->step_dy; + _dst += this->rgb_stride; + } + + if (dst_height <= 0) + break; + + dy -= 32768; + _py += this->y_stride; + } + } else { + for (height = this->source_height; --height >= 0; ) { + memcpy(_dst, _py, this->dest_width); + _dst += this->rgb_stride; + _py += this->y_stride; + } + } +} + +/* now for something different: 256 color mode */ +static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, + uint8_t * _py, uint8_t * _pu, uint8_t * _pv) +{ + int U, V, Y; + uint8_t * py_1, * py_2, * pu, * pv; + uint16_t * r, * g, * b; + uint8_t * dst_1, * dst_2; + int width, height, dst_height; + int dy; + + if (this->do_scale) { + scale_line_func_t scale_line = this->scale_line; + + scale_line (_pu, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line (_pv, this->v_buffer, + this->dest_width >> 1, this->step_dx); + scale_line (_py, this->y_buffer, + this->dest_width, this->step_dx); + + dy = 0; + dst_height = this->dest_height; + + for (height = 0;; height++) { + dst_1 = _dst; + py_1 = this->y_buffer; + pu = this->u_buffer; + pv = this->v_buffer; + + width = this->dest_width >> 3; + + do { + RGB(0); + DST1CMAP(0); + + RGB(1); + DST1CMAP(1); + + RGB(2); + DST1CMAP(2); + + RGB(3); + DST1CMAP(3); + + pu += 4; + pv += 4; + py_1 += 8; + dst_1 += 8; + } while (--width); + + dy += this->step_dy; + _dst += this->rgb_stride; + + while (--dst_height > 0 && dy < 32768) { + + memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); + + dy += this->step_dy; + _dst += this->rgb_stride; + } + + if (dst_height <= 0) + break; + + dy -= 32768; + _py += this->y_stride; + + scale_line (_py, this->y_buffer, + this->dest_width, this->step_dx); + + if (height & 1) { + _pu += this->uv_stride; + _pv += this->uv_stride; + + scale_line (_pu, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line (_pv, this->v_buffer, + this->dest_width >> 1, this->step_dx); + + } + } + } else { + height = this->source_height >> 1; + do { + dst_1 = _dst; + dst_2 = _dst + this->rgb_stride; + py_1 = _py; + py_2 = _py + this->y_stride; + pu = _pu; + pv = _pv; + width = this->source_width >> 3; + do { + RGB(0); + DST1CMAP(0); + DST2CMAP(0); + + RGB(1); + DST2CMAP(1); + DST1CMAP(1); + + RGB(2); + DST1CMAP(2); + DST2CMAP(2); + + RGB(3); + DST2CMAP(3); + DST1CMAP(3); pu += 4; pv += 4; @@ -1238,12 +1783,55 @@ static void yuv2rgb_setup_tables (yuv2rgb_t *this, int mode, int swapped) break; + case MODE_8_RGB: + case MODE_8_BGR: + table_8 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint8_t)); + + entry_size = sizeof (uint8_t); + table_r = table_8 + 197; + table_b = table_8 + 197 + 685; + table_g = table_8 + 197 + 2*682; + + switch (mode) { + case MODE_8_RGB: shift_r = 5; shift_g = 2; shift_b = 0; break; + case MODE_8_BGR: shift_r = 0; shift_g = 3; shift_b = 6; break; + } + + for (i = -197; i < 256+197; i++) + ((uint8_t *) table_r)[i] = (table_Y[i+384] >> 5) << shift_r; + for (i = -132; i < 256+132; i++) + ((uint8_t *) table_g)[i] = (table_Y[i+384] >> 5) << shift_g; + for (i = -232; i < 256+232; i++) + ((uint8_t *) table_b)[i] = (table_Y[i+384] >> 6) << shift_b; + break; + + case MODE_8_GRAY: + return; + case MODE_PALETTE: + table_16 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint16_t)); + + entry_size = sizeof (uint16_t); + table_r = table_16 + 197; + table_b = table_16 + 197 + 685; + table_g = table_16 + 197 + 2*682; + + shift_r = 10; + shift_g = 5; + shift_b = 0; + + for (i = -197; i < 256+197; i++) + ((uint16_t *)table_r)[i] = (table_Y[i+384] >> 3) << 10; - /* FIXME: set up 256 color table */ + for (i = -132; i < 256+132; i++) + ((uint16_t *)table_g)[i] = (table_Y[i+384] >> 3) << 5; + + for (i = -232; i < 256+232; i++) + ((uint16_t *)table_b)[i] = (table_Y[i+384] >> 3) << 0; break; + default: fprintf (stderr, "mode %d not supported by yuv2rgb\n", mode); exit (1); @@ -1283,6 +1871,15 @@ static void yuv2rgb_c_init (yuv2rgb_t *this, int mode, int swapped) this->yuv2rgb_fun = yuv2rgb_c_16; break; + case MODE_8_RGB: + case MODE_8_BGR: + this->yuv2rgb_fun = yuv2rgb_c_8; + break; + + case MODE_8_GRAY: + this->yuv2rgb_fun = yuv2rgb_c_gray; + break; + case MODE_PALETTE: this->yuv2rgb_fun = yuv2rgb_c_palette; break; @@ -1596,6 +2193,197 @@ static void yuy22rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) } } +static void yuy22rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) +{ + int U, V, Y; + uint8_t * py_1, * pu, * pv; + uint8_t * r, * g, * b; + uint8_t * dst_1; + int width, height; + int dy; + + /* FIXME: implement unscaled version */ + + scale_line_4 (_p+1, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_4 (_p+3, this->v_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_2 (_p, this->y_buffer, + this->dest_width, this->step_dx); + + dy = 0; + height = this->dest_height; + + for (;;) { + dst_1 = _dst; + py_1 = this->y_buffer; + pu = this->u_buffer; + pv = this->v_buffer; + + width = this->dest_width >> 3; + + do { + RGB(0); + DST1(0); + + RGB(1); + DST1(1); + + RGB(2); + DST1(2); + + RGB(3); + DST1(3); + + pu += 4; + pv += 4; + py_1 += 8; + dst_1 += 8; + } while (--width); + + dy += this->step_dy; + _dst += this->rgb_stride; + + while (--height > 0 && dy < 32768) { + + memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); + + dy += this->step_dy; + _dst += this->rgb_stride; + } + + if (height <= 0) + break; + + dy -= 32768; + _p += this->y_stride*2; + + scale_line_4 (_p+1, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_4 (_p+3, this->v_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_2 (_p, this->y_buffer, + this->dest_width, this->step_dx); + } +} + +static void yuy22rgb_c_gray (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) +{ + int width, height; + int dy; + uint8_t * dst; + uint8_t * y; + + if (this->do_scale) { + dy = 0; + height = this->dest_height; + + for (;;) { + scale_line_2 (_p, _dst, this->dest_width, this->step_dx); + + dy += this->step_dy; + _dst += this->rgb_stride; + + while (--height > 0 && dy < 32768) { + + memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); + + dy += this->step_dy; + _dst += this->rgb_stride; + } + + if (height <= 0) + break; + + dy -= 32768; + _p += this->y_stride*2; + } + } else { + for (height = this->source_height; --height >= 0; ) { + dst = _dst; + y = _p; + for (width = this->source_width; --width >= 0; ) { + *dst++ = *y; + y += 2; + } + _dst += this->rgb_stride; + _p += this->y_stride*2; + } + } +} + +static void yuy22rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) +{ + int U, V, Y; + uint8_t * py_1, * pu, * pv; + uint16_t * r, * g, * b; + uint8_t * dst_1; + int width, height; + int dy; + + scale_line_4 (_p+1, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_4 (_p+3, this->v_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_2 (_p, this->y_buffer, + this->dest_width, this->step_dx); + + dy = 0; + height = this->dest_height; + + for (;;) { + dst_1 = _dst; + py_1 = this->y_buffer; + pu = this->u_buffer; + pv = this->v_buffer; + + width = this->dest_width >> 3; + + do { + RGB(0); + DST1CMAP(0); + + RGB(1); + DST1CMAP(1); + + RGB(2); + DST1CMAP(2); + + RGB(3); + DST1CMAP(3); + + pu += 4; + pv += 4; + py_1 += 8; + dst_1 += 8; + } while (--width); + + dy += this->step_dy; + _dst += this->rgb_stride; + + while (--height > 0 && dy < 32768) { + + memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); + + dy += this->step_dy; + _dst += this->rgb_stride; + } + + if (height <= 0) + break; + + dy -= 32768; + _p += this->y_stride*2; + + scale_line_4 (_p+1, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_4 (_p+3, this->v_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_2 (_p, this->y_buffer, + this->dest_width, this->step_dx); + } +} + static void yuy22rgb_c_init (yuv2rgb_t *this, int mode, int swapped) { switch (mode) { @@ -1618,12 +2406,25 @@ static void yuy22rgb_c_init (yuv2rgb_t *this, int mode, int swapped) this->yuy22rgb_fun = yuy22rgb_c_16; break; + case MODE_8_RGB: + case MODE_8_BGR: + this->yuy22rgb_fun = yuy22rgb_c_8; + break; + + case MODE_8_GRAY: + this->yuy22rgb_fun = yuy22rgb_c_gray; + break; + + case MODE_PALETTE: + this->yuy22rgb_fun = yuy22rgb_c_palette; + break; + default: printf ("yuv2rgb: mode %d not supported for yuy2\n", mode); } } -yuv2rgb_t *yuv2rgb_init (int mode, int swapped) { +yuv2rgb_t *yuv2rgb_init (int mode, int swapped, uint8_t *colormap) { #ifdef ARCH_X86 uint32_t mm = mm_accel(); @@ -1632,6 +2433,7 @@ yuv2rgb_t *yuv2rgb_init (int mode, int swapped) { this->matrix_coefficients = 6; + this->fast_rgb = colormap; this->y_chunk = this->y_buffer = NULL; this->u_chunk = this->u_buffer = NULL; diff --git a/src/video_out/yuv2rgb.h b/src/video_out/yuv2rgb.h index 5e9869a3b..fc662aaf3 100644 --- a/src/video_out/yuv2rgb.h +++ b/src/video_out/yuv2rgb.h @@ -14,15 +14,18 @@ typedef void (*scale_line_func_t) (uint8_t *source, uint8_t *dest, * modes supported - feel free to implement yours */ -#define MODE_15_RGB 1 -#define MODE_15_BGR 2 -#define MODE_16_RGB 3 -#define MODE_16_BGR 4 -#define MODE_24_RGB 5 -#define MODE_24_BGR 6 -#define MODE_32_RGB 7 -#define MODE_32_BGR 8 -#define MODE_PALETTE 9 +#define MODE_8_RGB 1 +#define MODE_8_BGR 2 +#define MODE_15_RGB 3 +#define MODE_15_BGR 4 +#define MODE_16_RGB 5 +#define MODE_16_BGR 6 +#define MODE_24_RGB 7 +#define MODE_24_BGR 8 +#define MODE_32_RGB 9 +#define MODE_32_BGR 10 +#define MODE_8_GRAY 11 +#define MODE_PALETTE 12 typedef struct yuv2rgb_s yuv2rgb_t; @@ -60,12 +63,13 @@ struct yuv2rgb_s { int table_gV[256]; void *table_bU[256]; + uint8_t *fast_rgb; scale_line_func_t scale_line; } ; /* call once on startup */ -yuv2rgb_t *yuv2rgb_init (int mode, int swapped); +yuv2rgb_t *yuv2rgb_init (int mode, int swapped, uint8_t *colormap); /* * set up yuv2rgb function, determine scaling parameters if necessary |