? 32bit
? default
? enterprise
? prakesh
Index: configure.ac
===================================================================
RCS file: /cvsroot/xine/xine-lib/configure.ac,v
retrieving revision 1.459
diff -u -B -r1.459 configure.ac
--- configure.ac	28 Jan 2007 23:48:29 -0000	1.459
+++ configure.ac	7 Feb 2007 02:41:31 -0000
@@ -894,6 +894,46 @@
 
 
 dnl ---------------------------------------------
+dnl Check for xcb
+dnl ---------------------------------------------
+AC_ARG_WITH([xcb], AC_HELP_STRING([--without-xcb], [Doesn't build XCB video out plugins]))
+
+if test "x$with_xcb" != "xno"; then
+  PKG_CHECK_MODULES([XCB], [xcb-shape >= 1.0], [have_xcb="yes"], [have_xcb="no"])
+fi
+
+AC_SUBST(XCB_CFLAGS)
+AC_SUBST(XCB_LIBS)
+AM_CONDITIONAL(HAVE_XCB, test "x$have_xcb" = "xyes" )
+
+
+dnl ---------------------------------------------
+dnl Check for xcb-shm
+dnl ---------------------------------------------
+
+if test "x$have_xcb" = "xyes"; then
+  PKG_CHECK_MODULES([XCBSHM], [xcb-shm], [have_xcbshm="yes"], [have_xcbshm="no"])
+fi
+
+AC_SUBST(XCBSHM_CFLAGS)
+AC_SUBST(XCBSHM_LIBS)
+AM_CONDITIONAL(HAVE_XCBSHM, test "x$have_xcbshm" = "xyes" )
+
+
+dnl ---------------------------------------------
+dnl Check for xcb-xv
+dnl ---------------------------------------------
+
+if test "x$have_xcb" = "xyes"; then
+  PKG_CHECK_MODULES([XCBXV], [xcb-xv], [have_xcbxv="yes"], [have_xcbxv="no"])
+fi
+
+AC_SUBST(XCBXV_CFLAGS)
+AC_SUBST(XCBXV_LIBS)
+AM_CONDITIONAL(HAVE_XCBXV, test "x$have_xcbxv" = "xyes" )
+
+
+dnl ---------------------------------------------
 dnl Checks for Xinerama extension
 dnl ---------------------------------------------
 
@@ -2959,6 +2999,16 @@
     fi
   fi
 fi
+if test "x$have_xcb" = "xyes"; then
+  dnl xcb-shm
+  if test "x$have_xcbshm" = "xyes"; then
+    echo "   - xcb-shm (X shared memory using XCB)"
+  fi
+  dnl xcb-xv
+  if test "x$have_xcbxv" = "xyes"; then
+    echo "   - xcb-xv (XVideo using XCB)"
+  fi
+fi
 if test "x$no_aalib" != "xyes"; then
   echo "   - aa (Ascii ART)"
 fi
Index: include/xine.h.in
===================================================================
RCS file: /cvsroot/xine/xine-lib/include/xine.h.in,v
retrieving revision 1.162
diff -u -B -r1.162 xine.h.in
--- include/xine.h.in	21 Dec 2006 00:09:18 -0000	1.162
+++ include/xine.h.in	7 Feb 2007 02:41:33 -0000
@@ -176,6 +176,7 @@
 #define XINE_VISUAL_TYPE_DIRECTX           7 /* used by the win32/msvc port */
 #define XINE_VISUAL_TYPE_CACA              8
 #define XINE_VISUAL_TYPE_MACOSX            9
+#define XINE_VISUAL_TYPE_XCB              11
 
 /*
  * free all resources, close all plugins, close engine.
@@ -1192,6 +1193,82 @@
 } x11_visual_t;
 
 /*
+ * this is the visual data struct any xcb gui
+ * must supply to the xine_open_video_driver call
+ * ("data" parameter)
+ */
+typedef struct {
+
+  /* some information about the display */
+  void        *connection; /* xcb_connection_t */
+  void        *screen;     /* xcb_screen_t     */
+
+  /* window to display the video in / on */
+  unsigned int window; /* xcb_window_t */
+
+  void        *user_data;
+
+  /*
+   * dest size callback
+   *
+   * this will be called by the video driver to find out
+   * how big the video output area size will be for a
+   * given video size. The ui should _not_ adjust it's
+   * video out area, just do some calculations and return
+   * the size. This will be called for every frame, ui
+   * implementation should be fast.
+   * dest_pixel_aspect should be set to the used display pixel aspect.
+   * NOTE: Semantics has changed: video_width and video_height
+   * are no longer pixel aspect corrected. Get the old semantics
+   * in the UI with
+   *   *dest_pixel_aspect = display_pixel_aspect;
+   *   if (video_pixel_aspect >= display_pixel_aspect)
+   *     video_width  = video_width * video_pixel_aspect / display_pixel_aspect + .5;
+   *   else
+   *     video_height = video_height * display_pixel_aspect / video_pixel_aspect + .5;
+   */
+  void (*dest_size_cb) (void *user_data,
+			int video_width, int video_height,
+			double video_pixel_aspect,
+			int *dest_width, int *dest_height,
+			double *dest_pixel_aspect);
+
+  /*
+   * frame output callback
+   *
+   * this will be called by the video driver for every frame
+   * it's about to draw. ui can adapt it's size if necessary
+   * here.
+   * note: the ui doesn't have to adjust itself to this
+   * size, this is just to be taken as a hint.
+   * ui must return the actual size of the video output
+   * area and the video output driver will do it's best
+   * to adjust the video frames to that size (while
+   * preserving aspect ratio and stuff).
+   *    dest_x, dest_y: offset inside window
+   *    dest_width, dest_height: available drawing space
+   *    dest_pixel_aspect: display pixel aspect
+   *    win_x, win_y: window absolute screen position
+   * NOTE: Semantics has changed: video_width and video_height
+   * are no longer pixel aspect corrected. Get the old semantics
+   * in the UI with
+   *   *dest_pixel_aspect = display_pixel_aspect;
+   *   if (video_pixel_aspect >= display_pixel_aspect)
+   *     video_width  = video_width * video_pixel_aspect / display_pixel_aspect + .5;
+   *   else
+   *     video_height = video_height * display_pixel_aspect / video_pixel_aspect + .5;
+   */
+  void (*frame_output_cb) (void *user_data,
+			   int video_width, int video_height,
+			   double video_pixel_aspect,
+			   int *dest_x, int *dest_y,
+			   int *dest_width, int *dest_height,
+			   double *dest_pixel_aspect,
+			   int *win_x, int *win_y);
+
+} xcb_visual_t;
+
+/*
  * this is the visual data struct any fb gui
  * may supply to the xine_open_video_driver call
  * ("data" parameter) to get frame_output_cd calls
Index: src/video_out/Makefile.am
===================================================================
RCS file: /cvsroot/xine/xine-lib/src/video_out/Makefile.am,v
retrieving revision 1.128
diff -u -B -r1.128 Makefile.am
--- src/video_out/Makefile.am	28 Jan 2007 17:35:01 -0000	1.128
+++ src/video_out/Makefile.am	7 Feb 2007 02:41:36 -0000
@@ -37,6 +37,16 @@
 endif
 endif
 
+if HAVE_XCB
+XCBOSD = xcbosd.c
+if HAVE_XCBSHM
+xcbshm_module = xineplug_vo_out_xcbshm.la
+endif
+if HAVE_XCBXV
+xcbxv_module = xineplug_vo_out_xcbxv.la
+endif
+endif
+
 if HAVE_VIDIX
 vidix_module = xineplug_vo_out_vidix.la
 endif
@@ -86,8 +96,20 @@
                   $(caca_module) \
 		  $(macosx_module) \
 		  $(xxmc_module) \
+		  $(xcbshm_module) \
+		  $(xcbxv_module) \
                   xineplug_vo_out_none.la
 
+xineplug_vo_out_xcbshm_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_xcbshm.c $(XCBOSD)
+xineplug_vo_out_xcbshm_la_LIBADD = $(MLIB_LIBS) $(XINE_LIB) $(THREAD_LIBS) $(XCB_LIBS) $(XCBSHM_LIBS)
+xineplug_vo_out_xcbshm_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) $(XCB_CFLAGS) $(XCBSHM_CFLAGS)
+xineplug_vo_out_xcbshm_la_LDFLAGS = -avoid-version -module
+
+xineplug_vo_out_xcbxv_la_SOURCES = deinterlace.c video_out_xcbxv.c $(XCBOSD)
+xineplug_vo_out_xcbxv_la_LIBADD = $(XINE_LIB) $(THREAD_LIBS) $(XCBXV_LIBS) $(XCB_LIBS)
+xineplug_vo_out_xcbxv_la_CFLAGS = $(VISIBILITY_FLAG) $(XCB_CFLAGS) $(XCBXV_CFLAGS)
+xineplug_vo_out_xcbxv_la_LDFLAGS = -avoid-version -module
+
 xineplug_vo_out_xshm_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \
 	video_out_xshm.c $(X11OSD)
 xineplug_vo_out_xshm_la_LIBADD = $(MLIB_LIBS) $(X_LIBS) -lXext $(X_PRE_LIBS) -lX11 $(XINE_LIB) $(THREAD_LIBS)
@@ -192,4 +214,4 @@
 	-Wl,-framework -Wl,Cocoa -framework Cocoa -framework OpenGL
 
 noinst_HEADERS = deinterlace.h video_out_syncfb.h \
-	yuv2rgb.h x11osd.h
+	yuv2rgb.h x11osd.h xcbosd.h
Index: src/video_out/video_out_xcbshm.c
===================================================================
RCS file: src/video_out/video_out_xcbshm.c
diff -N src/video_out/video_out_xcbshm.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/video_out/video_out_xcbshm.c	7 Feb 2007 02:41:40 -0000
@@ -0,0 +1,1274 @@
+/*
+ * Copyright (C) 2000-2003, 2007 the xine project
+ * 
+ * This file is part of xine, a free video player.
+ * 
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * 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_xcbshm.c,v 1.148 2006/10/28 18:51:08 miguelfreitas Exp $
+ * 
+ * video_out_xcbshm.c, X11 shared memory extension interface for xine
+ *
+ * based on mpeg2dec code from
+ * Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * xine-specific code by Guenter Bartsch <bartscgr@studbox.uni-stuttgart.de>
+ * 
+ * ported to xcb by Christoph Pfister - Feb 2007
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "xine.h"
+#include "video_out.h"
+
+#include <errno.h>
+
+#include <xcb/shm.h>
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/time.h>
+
+#include <pthread.h>
+#include <netinet/in.h>
+
+#define LOG_MODULE "video_out_xcbshm"
+#define LOG_VERBOSE
+/*
+#define LOG
+*/
+
+#include "xine_internal.h"
+#include "yuv2rgb.h"
+#include "xineutils.h"
+#include "vo_scale.h"
+#include "xcbosd.h"
+
+typedef struct {
+  vo_frame_t         vo_frame;
+
+  /* frame properties as delivered by the decoder: */
+  /* obs: for width/height use vo_scale_t struct */
+  int                format;
+  int                flags;
+
+  vo_scale_t         sc;
+    
+  uint8_t           *image;
+  int                bytes_per_line;
+  xcb_shm_seg_t      shmseg;
+
+  uint8_t           *chunk[3]; /* mem alloc by xmalloc_aligned           */
+
+  yuv2rgb_t         *yuv2rgb; /* yuv2rgb converter set up for this frame */
+  uint8_t           *rgb_dst;
+
+} xshm_frame_t;
+
+typedef struct {
+
+  vo_driver_t        vo_driver;
+
+  /* xcb / shm related stuff */
+  xcb_connection_t  *connection;
+  xcb_screen_t      *screen;
+  xcb_window_t       window;
+  xcb_gcontext_t     gc;
+  int                depth;
+  int                bpp;
+  int                scanline_pad;
+  int                use_shm;
+  
+  int                yuv2rgb_brightness;
+  int                yuv2rgb_contrast;
+  int                yuv2rgb_saturation;
+  uint8_t           *yuv2rgb_cmap;
+  yuv2rgb_factory_t *yuv2rgb_factory;
+
+  vo_scale_t         sc;
+  
+  xshm_frame_t      *cur_frame;
+  xcbosd            *xoverlay;
+  int                ovl_changed;
+
+  xine_t            *xine;
+
+  alphablend_t       alphablend_extra_data;
+
+  pthread_mutex_t    main_mutex;
+
+} xshm_driver_t;
+
+typedef struct {
+  video_driver_class_t driver_class;
+
+  config_values_t     *config;
+  xine_t              *xine;
+} xshm_class_t;
+
+
+/*
+ * allocate an XImage, try XShm first but fall back to 
+ * plain X11 if XShm should fail
+ */
+static void create_ximage(xshm_driver_t *this, xshm_frame_t *frame, int width, int height)
+{
+  frame->bytes_per_line = ((this->bpp * width + this->scanline_pad - 1) &
+			   (~(this->scanline_pad - 1))) >> 3;
+
+  if (this->use_shm) {
+    int shmid;
+    xcb_void_cookie_t shm_attach_cookie;
+    xcb_generic_error_t *generic_error;
+
+    /*
+     * try shm
+     */
+
+    shmid = shmget(IPC_PRIVATE, frame->bytes_per_line * height, IPC_CREAT | 0777);
+
+    if (shmid < 0) {
+      xprintf(this->xine, XINE_VERBOSITY_LOG,
+	      _("video_out_xshm: %s: allocating image\n"
+		"video_out_xshm: => not using MIT Shared Memory extension.\n"), strerror(errno));
+      goto shm_fail1;
+    }
+  
+    frame->image = shmat(shmid, 0, 0);
+  
+    if (frame->image == ((void *) -1)) {
+      xprintf(this->xine, XINE_VERBOSITY_LOG,
+	      _("video_out_xshm: shared memory error (address error) when allocating image \n"
+		"video_out_xshm: => not using MIT Shared Memory extension.\n"));
+      goto shm_fail2;
+    }
+
+    frame->shmseg = xcb_generate_id(this->connection);
+    shm_attach_cookie = xcb_shm_attach_checked(this->connection, frame->shmseg, shmid, 0);
+    generic_error = xcb_request_check(this->connection, shm_attach_cookie);
+
+    if (generic_error != NULL) {
+      xprintf(this->xine, XINE_VERBOSITY_LOG,
+	      _("video_out_xshm: x11 error during shared memory XImage creation\n"
+		"video_out_xshm: => not using MIT Shared Memory extension.\n"));
+      free(generic_error);
+      goto shm_fail3;
+    }
+
+    /* 
+     * Now that the Xserver has learned about and attached to the
+     * shared memory segment,  delete it.  It's actually deleted by
+     * the kernel when all users of that segment have detached from 
+     * it.  Gives an automatic shared memory cleanup in case we crash.
+     */
+
+    shmctl(shmid, IPC_RMID, 0);
+
+    return;
+
+  shm_fail3:
+    frame->shmseg = 0;
+    shmdt(frame->image);
+  shm_fail2:
+    shmctl(shmid, IPC_RMID, 0);
+  shm_fail1:
+    this->use_shm = 0;
+  }
+
+  /*
+   * fall back to plain X11 if necessary
+   */
+
+  frame->image = malloc(frame->bytes_per_line * height);
+}
+
+static void dispose_ximage(xshm_driver_t *this, xshm_frame_t *frame)
+{
+  if (frame->shmseg) {
+    xcb_shm_detach(this->connection, frame->shmseg);
+    frame->shmseg = 0;
+    shmdt(frame->image);
+  } else
+    free(frame->image);
+  frame->image = NULL;
+}
+
+
+/*
+ * and now, the driver functions
+ */
+
+static uint32_t xshm_get_capabilities (vo_driver_t *this_gen) {
+  xshm_driver_t *this = (xshm_driver_t *) this_gen;
+  uint32_t capabilities = VO_CAP_YV12 | VO_CAP_YUY2;
+
+  if( this->xoverlay )
+    capabilities |= VO_CAP_UNSCALED_OVERLAY;
+
+  return capabilities;
+}
+
+static void xshm_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) {
+  xshm_frame_t  *frame = (xshm_frame_t *) vo_img ;
+  /*xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; */
+  
+  vo_img->proc_called = 1;                                    
+  
+  if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || 
+      frame->vo_frame.crop_right || frame->vo_frame.crop_bottom )
+  {
+    /* we don't support crop, so don't even waste cpu cycles.
+     * cropping will be performed by video_out.c
+     */
+    return;
+  }
+  
+  lprintf ("copy... (format %d)\n", frame->format);
+
+  if (frame->format == XINE_IMGFMT_YV12)
+    frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst,
+				 src[0], src[1], src[2]);
+  else
+    frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst,
+				  src[0]);
+  
+  lprintf ("copy...done\n");
+}
+
+static void xshm_frame_field (vo_frame_t *vo_img, int which_field) {
+  xshm_frame_t  *frame = (xshm_frame_t *) vo_img ;
+  /* xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; */
+
+  switch (which_field) {
+  case VO_TOP_FIELD:
+    frame->rgb_dst = frame->image;
+    break;
+  case VO_BOTTOM_FIELD:
+    frame->rgb_dst = frame->image + frame->bytes_per_line;
+    break;
+  case VO_BOTH_FIELDS:
+    frame->rgb_dst = frame->image;
+    break;
+  }
+
+  frame->yuv2rgb->next_slice (frame->yuv2rgb, NULL);
+}
+
+static void xshm_frame_dispose (vo_frame_t *vo_img) {
+  xshm_frame_t  *frame = (xshm_frame_t *) vo_img ;
+  xshm_driver_t *this  = (xshm_driver_t *) vo_img->driver;
+
+  if (frame->image) {
+    pthread_mutex_lock(&this->main_mutex);
+    dispose_ximage(this, frame);
+    pthread_mutex_unlock(&this->main_mutex);
+  }
+
+  frame->yuv2rgb->dispose (frame->yuv2rgb);
+
+  free (frame->chunk[0]);
+  free (frame->chunk[1]);
+  free (frame->chunk[2]);
+  free (frame);
+}
+
+
+static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) {
+  xshm_frame_t  *frame;
+  xshm_driver_t *this = (xshm_driver_t *) this_gen;
+
+  frame = (xshm_frame_t *) xine_xmalloc (sizeof (xshm_frame_t));
+  if (!frame)
+    return NULL;
+
+  memcpy (&frame->sc, &this->sc, sizeof(vo_scale_t));
+
+  pthread_mutex_init (&frame->vo_frame.mutex, NULL);
+
+  /*
+   * supply required functions/fields
+   */
+  
+  frame->vo_frame.proc_slice = xshm_frame_proc_slice;
+  frame->vo_frame.proc_frame = NULL;
+  frame->vo_frame.field      = xshm_frame_field; 
+  frame->vo_frame.dispose    = xshm_frame_dispose;
+  frame->vo_frame.driver     = this_gen;
+
+  /*
+   * colorspace converter for this frame
+   */
+
+  frame->yuv2rgb = this->yuv2rgb_factory->create_converter (this->yuv2rgb_factory);
+
+  return (vo_frame_t *) frame;
+}
+
+static void xshm_compute_ideal_size (xshm_driver_t *this, xshm_frame_t *frame) {
+  _x_vo_scale_compute_ideal_size( &frame->sc );
+}
+
+static void xshm_compute_rgb_size (xshm_driver_t *this, xshm_frame_t *frame) {
+  _x_vo_scale_compute_output_size( &frame->sc );
+
+  /* avoid problems in yuv2rgb */
+  if (frame->sc.output_height < 1)
+    frame->sc.output_height = 1;
+  if (frame->sc.output_width < 8)
+    frame->sc.output_width = 8;
+  if (frame->sc.output_width & 1) /* yuv2rgb_mlib needs an even YUV2 width */
+    frame->sc.output_width++;
+
+  lprintf("frame source (%d) %d x %d => screen output %d x %d%s\n",
+	  frame->vo_frame.id,
+	  frame->sc.delivered_width, frame->sc.delivered_height,
+	  frame->sc.output_width, frame->sc.output_height,
+	  ( frame->sc.delivered_width != frame->sc.output_width
+	    || frame->sc.delivered_height != frame->sc.output_height
+	    ? ", software scaling"
+	   : "" )
+	  );
+}
+
+static void xshm_update_frame_format (vo_driver_t *this_gen,
+				      vo_frame_t *frame_gen,
+				      uint32_t width, uint32_t height,
+				      double ratio, int format, int flags) {
+  xshm_driver_t  *this = (xshm_driver_t *) this_gen;
+  xshm_frame_t   *frame = (xshm_frame_t *) frame_gen;
+  int             do_adapt;
+  int             gui_width;
+  int             gui_height;
+  double          gui_pixel_aspect;
+
+  flags &= VO_BOTH_FIELDS;
+
+  /* ask gui what output size we'll have for this frame */
+  /* get the gui_pixel_aspect before calling xshm_compute_ideal_size() */
+  /* note: gui_width and gui_height may be bogus because we may have not yet*/
+  /*       updated video_pixel_aspect (see _x_vo_scale_compute_ideal_size). */
+  frame->sc.dest_size_cb (frame->sc.user_data, width, height,
+                          frame->sc.video_pixel_aspect,
+                          &gui_width, &gui_height,
+                          &gui_pixel_aspect);
+                          
+  /* find out if we need to adapt this frame */
+  do_adapt = 0;
+
+  if ((width != frame->sc.delivered_width)
+      || (height != frame->sc.delivered_height)
+      || (ratio != frame->sc.delivered_ratio)
+      || (flags != frame->flags)
+      || (format != frame->format)
+      || (gui_pixel_aspect != frame->sc.gui_pixel_aspect)
+      || (this->sc.user_ratio != frame->sc.user_ratio)) {
+
+    do_adapt = 1;
+
+    lprintf ("frame format (from decoder) has changed => adapt\n");
+
+    frame->sc.delivered_width    = width;
+    frame->sc.delivered_height   = height;
+    frame->sc.delivered_ratio    = ratio;
+    frame->sc.gui_pixel_aspect   = gui_pixel_aspect;
+    frame->flags                 = flags;
+    frame->format                = format;
+    frame->sc.user_ratio         = this->sc.user_ratio;
+
+    xshm_compute_ideal_size (this, frame);
+  
+    /* now we have updated video_aspect_pixel we use the callback   */
+    /* again to obtain the correct gui_width and gui_height values. */
+    frame->sc.dest_size_cb (frame->sc.user_data, width, height,
+                            frame->sc.video_pixel_aspect,
+                            &gui_width, &gui_height,
+                            &gui_pixel_aspect);
+  }
+  
+  if ((frame->sc.gui_width != gui_width) ||
+      (frame->sc.gui_height != gui_height) ||
+      do_adapt) {
+    
+    do_adapt = 1;
+    frame->sc.gui_width  = gui_width;
+    frame->sc.gui_height = gui_height;
+    
+    xshm_compute_rgb_size (this, frame);
+    
+    lprintf ("gui_size has changed => adapt\n");
+  }
+  
+
+  /* ok, now do what we have to do */
+
+  if (do_adapt) {
+
+    lprintf ("updating frame to %d x %d\n",
+	     frame->sc.output_width, frame->sc.output_height);
+
+    pthread_mutex_lock(&this->main_mutex);
+
+    /*
+     * (re-) allocate XImage
+     */
+
+    if (frame->image) {
+
+      dispose_ximage(this, frame);
+
+      if (frame->chunk[0]){
+	free (frame->chunk[0]);
+	frame->chunk[0] = NULL;
+      }
+      if (frame->chunk[1]) {
+	free (frame->chunk[1]);
+	frame->chunk[1] = NULL;
+      }
+      if (frame->chunk[2]) {
+	free (frame->chunk[2]);
+	frame->chunk[2] = NULL;
+      }
+    }
+
+    create_ximage(this, frame, frame->sc.output_width, frame->sc.output_height);
+
+    pthread_mutex_unlock(&this->main_mutex);
+
+    if (format == XINE_IMGFMT_YV12) {
+      frame->vo_frame.pitches[0] = 8*((width + 7) / 8);
+      frame->vo_frame.pitches[1] = 8*((width + 15) / 16);
+      frame->vo_frame.pitches[2] = 8*((width + 15) / 16);
+      frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height,  (void **) &frame->chunk[0]);
+      frame->vo_frame.base[1] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[1] * ((height+1)/2), (void **) &frame->chunk[1]);
+      frame->vo_frame.base[2] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[2] * ((height+1)/2), (void **) &frame->chunk[2]);
+    } else {
+      frame->vo_frame.pitches[0] = 8*((width + 3) / 4);
+      frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]);
+      frame->chunk[1] = NULL;
+      frame->chunk[2] = NULL;
+    }
+
+    lprintf ("stripe out_ht=%i, deliv_ht=%i\n",
+	    frame->sc.output_height, frame->sc.delivered_height);
+
+    /* 
+     * set up colorspace converter
+     */
+
+    switch (flags) {
+    case VO_TOP_FIELD:
+    case VO_BOTTOM_FIELD:
+      frame->yuv2rgb->configure (frame->yuv2rgb,
+				 frame->sc.delivered_width,
+				 frame->sc.delivered_height,
+				 2*frame->vo_frame.pitches[0],
+				 2*frame->vo_frame.pitches[1],
+				 frame->sc.output_width,
+				 frame->sc.output_height,
+				 frame->bytes_per_line*2);
+      break;
+    case VO_BOTH_FIELDS:
+      frame->yuv2rgb->configure (frame->yuv2rgb,
+				 frame->sc.delivered_width,
+				 frame->sc.delivered_height,
+				 frame->vo_frame.pitches[0],
+				 frame->vo_frame.pitches[1],
+				 frame->sc.output_width,
+				 frame->sc.output_height,
+				 frame->bytes_per_line);
+      break;
+    }
+  }
+
+  xshm_frame_field ((vo_frame_t *)frame, flags);
+}
+
+static void xshm_overlay_clut_yuv2rgb(xshm_driver_t  *this, vo_overlay_t *overlay,
+				      xshm_frame_t *frame) {
+  size_t  i;
+  clut_t* clut = (clut_t*) overlay->color;
+
+  if (!overlay->rgb_clut) {
+    for (i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) {
+      *((uint32_t *)&clut[i]) =
+	frame->yuv2rgb->yuv2rgb_single_pixel_fun (frame->yuv2rgb,
+						  clut[i].y, clut[i].cb, clut[i].cr);
+    }
+    overlay->rgb_clut++;
+  }
+  if (!overlay->hili_rgb_clut) {
+    clut = (clut_t*) overlay->hili_color;
+    for (i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) {
+      *((uint32_t *)&clut[i]) =
+	frame->yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb,
+						 clut[i].y, clut[i].cb, clut[i].cr);
+    }
+    overlay->hili_rgb_clut++;
+  }
+}
+
+static void xshm_overlay_begin (vo_driver_t *this_gen, 
+			      vo_frame_t *frame_gen, int changed) {
+  xshm_driver_t  *this  = (xshm_driver_t *) this_gen;
+
+  this->ovl_changed += changed;
+
+  if( this->ovl_changed && this->xoverlay ) {
+    pthread_mutex_lock(&this->main_mutex);
+    xcbosd_clear(this->xoverlay);
+    pthread_mutex_unlock(&this->main_mutex);
+  }
+  
+  this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x;
+  this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y;
+}
+
+static void xshm_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) {
+  xshm_driver_t  *this  = (xshm_driver_t *) this_gen;
+
+  if( this->ovl_changed && this->xoverlay ) {
+    pthread_mutex_lock(&this->main_mutex);
+    xcbosd_expose(this->xoverlay);
+    pthread_mutex_unlock(&this->main_mutex);
+  }
+
+  this->ovl_changed = 0;
+}
+
+static void xshm_overlay_blend (vo_driver_t *this_gen, 
+				vo_frame_t *frame_gen, vo_overlay_t *overlay) {
+  xshm_driver_t  *this  = (xshm_driver_t *) this_gen;
+  xshm_frame_t   *frame = (xshm_frame_t *) frame_gen;
+
+  /* Alpha Blend here */
+  if (overlay->rle) {
+    if( overlay->unscaled ) {
+      if( this->ovl_changed && this->xoverlay ) {
+        pthread_mutex_lock(&this->main_mutex);
+        xcbosd_blend(this->xoverlay, overlay);
+        pthread_mutex_unlock(&this->main_mutex);
+      }
+    } else {
+      if (!overlay->rgb_clut || !overlay->hili_rgb_clut)
+        xshm_overlay_clut_yuv2rgb (this, overlay, frame);
+ 
+      switch (this->bpp) {
+        case 16:
+         _x_blend_rgb16(frame->image, overlay,
+		      frame->sc.output_width, frame->sc.output_height,
+		      frame->sc.delivered_width, frame->sc.delivered_height,
+                      &this->alphablend_extra_data);
+         break;
+        case 24:
+         _x_blend_rgb24(frame->image, overlay,
+		      frame->sc.output_width, frame->sc.output_height,
+		      frame->sc.delivered_width, frame->sc.delivered_height,
+                      &this->alphablend_extra_data);
+         break;
+        case 32:
+         _x_blend_rgb32(frame->image, overlay,
+		      frame->sc.output_width, frame->sc.output_height,
+		      frame->sc.delivered_width, frame->sc.delivered_height,
+                      &this->alphablend_extra_data);
+         break;
+        default:
+	  xprintf(this->xine, XINE_VERBOSITY_DEBUG, 
+		  "xine-lib:video_out_xshm:xshm_overlay_blend: Cannot blend bpp:%i\n", this->bpp);
+	/* it should never get here, unless a user tries to play in bpp:8 */
+	break;
+      }
+    }
+  }
+}
+
+static void clean_output_area (xshm_driver_t *this, xshm_frame_t *frame) {
+  int i;
+  xcb_rectangle_t rects[4];
+  int rects_count = 0;
+  
+  memcpy( this->sc.border, frame->sc.border, sizeof(this->sc.border) );
+  
+  pthread_mutex_lock(&this->main_mutex);
+  
+  for( i = 0; i < 4; i++ ) {
+    if( this->sc.border[i].w && this->sc.border[i].h )
+      rects[rects_count].x = this->sc.border[i].x;
+      rects[rects_count].y = this->sc.border[i].y;
+      rects[rects_count].width = this->sc.border[i].w;
+      rects[rects_count].height = this->sc.border[i].h;
+      rects_count++;
+  }
+
+  if (rects_count > 0)
+    xcb_poly_fill_rectangle(this->connection, this->window, this->gc, rects_count, rects);
+
+  if (this->xoverlay) {
+    xcbosd_resize(this->xoverlay, this->sc.gui_width, this->sc.gui_height);
+    this->ovl_changed = 1;
+  }
+  
+  pthread_mutex_unlock(&this->main_mutex);
+}
+
+static int xshm_redraw_needed (vo_driver_t *this_gen) {
+  xshm_driver_t  *this = (xshm_driver_t *) this_gen;
+  int             ret = 0;
+
+  if( this->cur_frame ) {
+    this->sc.delivered_height   = this->cur_frame->sc.delivered_height;
+    this->sc.delivered_width    = this->cur_frame->sc.delivered_width;
+    this->sc.video_pixel_aspect = this->cur_frame->sc.video_pixel_aspect;
+    if( _x_vo_scale_redraw_needed( &this->sc ) ) {  
+
+      clean_output_area (this, this->cur_frame);
+      ret = 1;
+    }
+  } 
+  else
+    ret = 1;
+      
+  return ret;
+}
+
+static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
+  xshm_driver_t  *this  = (xshm_driver_t *) this_gen;
+  xshm_frame_t   *frame = (xshm_frame_t *) frame_gen;
+
+  lprintf ("display frame...\n");
+  lprintf ("about to draw frame (%d) %d x %d...\n",
+	   frame->vo_frame.id,
+	   frame->sc.output_width, frame->sc.output_height);
+
+  /* 
+   * tell gui that we are about to display a frame,
+   * ask for offset
+   */
+    
+  this->sc.delivered_height   = frame->sc.delivered_height;
+  this->sc.delivered_width    = frame->sc.delivered_width;
+  this->sc.video_pixel_aspect = frame->sc.video_pixel_aspect;
+  if( _x_vo_scale_redraw_needed( &this->sc ) ) {  
+
+    clean_output_area (this, frame);
+  }
+    
+  if (this->cur_frame) {
+
+    if ( (this->cur_frame->sc.output_width != frame->sc.output_width) 
+         || (this->cur_frame->sc.output_height != frame->sc.output_height)
+         || (this->cur_frame->sc.output_xoffset != frame->sc.output_xoffset)
+         || (this->cur_frame->sc.output_yoffset != frame->sc.output_yoffset) )
+      clean_output_area (this, frame);
+
+    this->cur_frame->vo_frame.free (&this->cur_frame->vo_frame);
+  }
+
+  this->cur_frame = frame;
+    
+  pthread_mutex_lock(&this->main_mutex);
+  lprintf ("display locked...\n");
+  
+  if (frame->shmseg) {
+
+    lprintf ("put image (shm)\n");
+    xcb_shm_put_image(this->connection, this->window, this->gc, this->cur_frame->sc.output_width,
+                      this->cur_frame->sc.output_height, 0, 0, this->cur_frame->sc.output_width,
+                      this->cur_frame->sc.output_height, this->cur_frame->sc.output_xoffset,
+                      this->cur_frame->sc.output_yoffset, this->depth, XCB_IMAGE_FORMAT_Z_PIXMAP,
+                      0, this->cur_frame->shmseg, 0);
+
+  } else {
+
+    lprintf ("put image (plain/remote)\n");
+    xcb_put_image(this->connection, XCB_IMAGE_FORMAT_Z_PIXMAP, this->window, this->gc,
+                  frame->sc.output_width, frame->sc.output_height, frame->sc.output_xoffset, frame->sc.output_yoffset,
+                  0, this->depth, frame->bytes_per_line * frame->sc.output_height, frame->image);
+
+  }
+  xcb_flush(this->connection);
+  pthread_mutex_unlock(&this->main_mutex);
+
+  lprintf ("display frame done\n");
+}
+
+static int xshm_get_property (vo_driver_t *this_gen, int property) {
+  xshm_driver_t *this = (xshm_driver_t *) this_gen;
+
+  switch (property) {
+  case VO_PROP_ASPECT_RATIO:
+    return this->sc.user_ratio;
+  case VO_PROP_MAX_NUM_FRAMES:
+    return 15;
+  case VO_PROP_BRIGHTNESS:
+    return this->yuv2rgb_brightness;
+  case VO_PROP_CONTRAST:
+    return this->yuv2rgb_contrast;
+  case VO_PROP_SATURATION:
+    return this->yuv2rgb_saturation;
+  case VO_PROP_WINDOW_WIDTH:
+    return this->sc.gui_width;
+  case VO_PROP_WINDOW_HEIGHT:
+    return this->sc.gui_height;
+  default:
+    xprintf(this->xine, XINE_VERBOSITY_DEBUG, 
+	    "video_out_xshm: tried to get unsupported property %d\n", property);
+  }
+
+  return 0;
+}
+
+static int xshm_set_property (vo_driver_t *this_gen, 
+			      int property, int value) {
+  xshm_driver_t *this = (xshm_driver_t *) this_gen;
+
+  if ( property == VO_PROP_ASPECT_RATIO) {
+
+    if (value>=XINE_VO_ASPECT_NUM_RATIOS)
+      value = XINE_VO_ASPECT_AUTO;
+    this->sc.user_ratio = value;
+    xprintf(this->xine, XINE_VERBOSITY_DEBUG, 
+	    "video_out_xshm: aspect ratio changed to %s\n", _x_vo_scale_aspect_ratio_name(value));
+
+  } else if (property == VO_PROP_BRIGHTNESS) {
+
+    this->yuv2rgb_brightness = value;
+    this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory,
+					   this->yuv2rgb_brightness,
+					   this->yuv2rgb_contrast,
+					   this->yuv2rgb_saturation);
+
+    this->sc.force_redraw = 1;
+
+  } else if (property == VO_PROP_CONTRAST) {
+
+    this->yuv2rgb_contrast = value;
+    this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory,
+					   this->yuv2rgb_brightness,
+					   this->yuv2rgb_contrast,
+					   this->yuv2rgb_saturation);
+
+    this->sc.force_redraw = 1;
+
+  } else if (property == VO_PROP_SATURATION) {
+
+    this->yuv2rgb_saturation = value;
+    this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory,
+					   this->yuv2rgb_brightness,
+					   this->yuv2rgb_contrast,
+					   this->yuv2rgb_saturation);
+
+    this->sc.force_redraw = 1;
+
+  } else {
+    xprintf (this->xine, XINE_VERBOSITY_DEBUG, 
+	     "video_out_xshm: tried to set unsupported property %d\n", property);
+  }
+
+  return value;
+}
+
+static void xshm_get_property_min_max (vo_driver_t *this_gen,
+				     int property, int *min, int *max) {
+  /* xshm_driver_t *this = (xshm_driver_t *) this_gen;  */
+
+  if (property == VO_PROP_BRIGHTNESS) {
+    *min = -128;
+    *max = +127;
+  } else if (property == VO_PROP_CONTRAST) {
+    *min = 0;
+    *max = 255;
+  } else if (property == VO_PROP_SATURATION) {
+    *min = 0;
+    *max = 255;
+  } else {
+    *min = 0;
+    *max = 0;
+  }
+}
+
+static int xshm_gui_data_exchange (vo_driver_t *this_gen, 
+				   int data_type, void *data) {
+  xshm_driver_t   *this = (xshm_driver_t *) this_gen;
+
+  switch (data_type) {
+#ifndef XINE_DISABLE_DEPRECATED_FEATURES
+  case XINE_GUI_SEND_COMPLETION_EVENT:
+    break;
+#endif
+
+  case XINE_GUI_SEND_EXPOSE_EVENT:
+    
+    lprintf ("expose event\n");
+
+    if (this->cur_frame) {
+      xcb_expose_event_t *xev = (xcb_expose_event_t *) data;
+      
+      if (xev && xev->count == 0) {
+	int i;
+	xcb_rectangle_t rects[4];
+	int rects_count = 0;
+	
+	pthread_mutex_lock(&this->main_mutex);
+	if (this->cur_frame->shmseg)
+	  xcb_shm_put_image(this->connection, this->window, this->gc, this->cur_frame->sc.output_width,
+			    this->cur_frame->sc.output_height, 0, 0, this->cur_frame->sc.output_width,
+			    this->cur_frame->sc.output_height, this->cur_frame->sc.output_xoffset,
+			    this->cur_frame->sc.output_yoffset, this->depth, XCB_IMAGE_FORMAT_Z_PIXMAP,
+			    0, this->cur_frame->shmseg, 0);
+	else
+	  xcb_put_image(this->connection, XCB_IMAGE_FORMAT_Z_PIXMAP, this->window, this->gc,
+			this->cur_frame->sc.output_width, this->cur_frame->sc.output_height,
+			this->cur_frame->sc.output_xoffset, this->cur_frame->sc.output_yoffset,
+			0, this->depth, this->cur_frame->bytes_per_line * this->cur_frame->sc.output_height,
+			this->cur_frame->image);
+
+	for( i = 0; i < 4; i++ ) {
+	  if( this->sc.border[i].w && this->sc.border[i].h )
+	    rects[rects_count].x = this->sc.border[i].x;
+	    rects[rects_count].y = this->sc.border[i].y;
+	    rects[rects_count].width = this->sc.border[i].w;
+	    rects[rects_count].height = this->sc.border[i].h;
+	    rects_count++;
+	}
+
+	if (rects_count > 0)
+	  xcb_poly_fill_rectangle(this->connection, this->window, this->gc, rects_count, rects);
+
+        if(this->xoverlay)
+          xcbosd_expose(this->xoverlay);
+
+	xcb_flush(this->connection);
+	pthread_mutex_unlock(&this->main_mutex);
+      }
+    }
+  break;
+  
+  case XINE_GUI_SEND_DRAWABLE_CHANGED:
+    this->window = (xcb_window_t) data;
+
+    pthread_mutex_lock(&this->main_mutex);
+    xcb_free_gc(this->connection, this->gc);
+    this->gc = xcb_generate_id(this->connection);
+    xcb_create_gc(this->connection, this->gc, this->window, XCB_GC_FOREGROUND, &this->screen->black_pixel);
+    if(this->xoverlay)
+      xcbosd_drawable_changed(this->xoverlay, this->window);
+    this->ovl_changed = 1;
+    pthread_mutex_unlock(&this->main_mutex);
+  break;
+
+  case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO:
+
+    if (this->cur_frame) {
+      x11_rectangle_t *rect = data;
+      int              x1, y1, x2, y2;
+      
+      _x_vo_scale_translate_gui2video(&this->cur_frame->sc,
+			       rect->x, rect->y,
+			       &x1, &y1);
+      _x_vo_scale_translate_gui2video(&this->cur_frame->sc,
+			       rect->x + rect->w, rect->y + rect->h,
+			       &x2, &y2);
+      rect->x = x1;
+      rect->y = y1;
+      rect->w = x2-x1;
+      rect->h = y2-y1;
+    }
+  break;
+
+  default:
+    return -1;
+  }
+
+  return 0;
+}
+
+static void xshm_dispose (vo_driver_t *this_gen) {
+  xshm_driver_t *this = (xshm_driver_t *) this_gen;
+  
+  if (this->cur_frame)
+    this->cur_frame->vo_frame.dispose (&this->cur_frame->vo_frame);
+
+  this->yuv2rgb_factory->dispose (this->yuv2rgb_factory);
+  
+  pthread_mutex_lock(&this->main_mutex);
+  xcb_free_gc(this->connection, this->gc);
+  pthread_mutex_unlock(&this->main_mutex);
+  
+  if( this->xoverlay ) {
+    pthread_mutex_lock(&this->main_mutex);
+    xcbosd_destroy(this->xoverlay);
+    pthread_mutex_unlock(&this->main_mutex);
+  }
+
+  pthread_mutex_destroy(&this->main_mutex);
+
+  _x_alphablend_free(&this->alphablend_extra_data);
+  
+  free (this);
+}
+
+static int ImlibPaletteLUTGet(xshm_driver_t *this) {
+  static const xcb_atom_t CARDINAL = 6;
+
+  xcb_intern_atom_cookie_t atom_cookie;
+  xcb_intern_atom_reply_t *atom_reply;
+
+  xcb_get_property_cookie_t prop_cookie;
+  xcb_get_property_reply_t *prop_reply;
+
+  atom_cookie = xcb_intern_atom(this->connection, 0, sizeof("_IMLIB_COLORMAP"), "_IMLIB_COLORMAP");
+  atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL);
+
+  if (atom_reply == NULL)
+    return 0;
+
+  prop_cookie = xcb_get_property(this->connection, 0, this->window, atom_reply->atom, CARDINAL, 0, 0x7fffffff);
+  prop_reply = xcb_get_property_reply(this->connection, prop_cookie, NULL);
+
+  free(atom_reply);
+
+  if (prop_reply == NULL)
+    return 0;
+
+  if (prop_reply->format == 8) {
+    unsigned int i;
+    unsigned long j;
+    int num_ret = xcb_get_property_value_length(prop_reply);
+    char *retval = xcb_get_property_value(prop_reply);
+
+    j = 1 + retval[0]*4;
+    this->yuv2rgb_cmap = malloc(sizeof(uint8_t) * 32 * 32 * 32);
+    for (i = 0; i < 32 * 32 * 32 && j < num_ret; i++)
+      this->yuv2rgb_cmap[i] = retval[1+4*retval[j++]+3];
+
+    free(prop_reply);
+    return 1;
+  }
+
+  free(prop_reply);
+  return 0;
+}
+
+
+static char *visual_class_name(xcb_visualtype_t *visual) {
+
+  switch (visual->_class) {
+  case XCB_VISUAL_CLASS_STATIC_GRAY:
+    return "StaticGray";
+  case XCB_VISUAL_CLASS_GRAY_SCALE:
+    return "GrayScale";
+  case XCB_VISUAL_CLASS_STATIC_COLOR:
+    return "StaticColor";
+  case XCB_VISUAL_CLASS_PSEUDO_COLOR:
+    return "PseudoColor";
+  case XCB_VISUAL_CLASS_TRUE_COLOR:
+    return "TrueColor";
+  case XCB_VISUAL_CLASS_DIRECT_COLOR:
+    return "DirectColor";
+  default:
+    return "unknown visual class";
+  }
+}
+
+static vo_driver_t *xshm_open_plugin(video_driver_class_t *class_gen, const void *visual_gen) {
+  xshm_class_t         *class   = (xshm_class_t *) class_gen;
+  config_values_t      *config  = class->config;
+  xcb_visual_t         *visual  = (xcb_visual_t *) visual_gen;
+  xshm_driver_t        *this;
+  xcb_visualtype_t     *visualtype;
+  int                   mode;
+  int			swapped;
+  int			cpu_byte_order;
+  int			image_byte_order;
+
+  xcb_get_window_attributes_cookie_t window_attrs_cookie;
+  xcb_get_window_attributes_reply_t *window_attrs_reply;
+
+  xcb_get_geometry_cookie_t geometry_cookie;
+  xcb_get_geometry_reply_t *geometry_reply;
+
+  const xcb_query_extension_reply_t *query_extension_reply;
+  
+  this = (xshm_driver_t *) xine_xmalloc (sizeof (xshm_driver_t));
+
+  if (!this)
+    return NULL;
+
+  pthread_mutex_init(&this->main_mutex, NULL);
+
+  _x_alphablend_init(&this->alphablend_extra_data, class->xine);
+  
+  this->connection          = visual->connection;
+  this->screen              = visual->screen;
+  this->window              = visual->window;
+
+  _x_vo_scale_init( &this->sc, 0, 0, config );
+  this->sc.frame_output_cb  = visual->frame_output_cb;
+  this->sc.dest_size_cb     = visual->dest_size_cb;
+  this->sc.user_data        = visual->user_data;
+  
+  this->sc.user_ratio       = XINE_VO_ASPECT_AUTO;
+  
+  this->cur_frame           = NULL;
+  this->gc                  = xcb_generate_id(this->connection);
+  xcb_create_gc(this->connection, this->gc, this->window, XCB_GC_FOREGROUND, &this->screen->black_pixel);
+  this->xoverlay            = NULL;
+  this->ovl_changed         = 0;
+ 
+  this->xine                = class->xine;
+
+  this->vo_driver.get_capabilities     = xshm_get_capabilities;
+  this->vo_driver.alloc_frame          = xshm_alloc_frame;
+  this->vo_driver.update_frame_format  = xshm_update_frame_format;
+  this->vo_driver.overlay_begin        = xshm_overlay_begin;
+  this->vo_driver.overlay_blend        = xshm_overlay_blend;
+  this->vo_driver.overlay_end          = xshm_overlay_end;
+  this->vo_driver.display_frame        = xshm_display_frame;
+  this->vo_driver.get_property         = xshm_get_property;
+  this->vo_driver.set_property         = xshm_set_property;
+  this->vo_driver.get_property_min_max = xshm_get_property_min_max;
+  this->vo_driver.gui_data_exchange    = xshm_gui_data_exchange;
+  this->vo_driver.dispose              = xshm_dispose;
+  this->vo_driver.redraw_needed        = xshm_redraw_needed;
+
+  /*
+   *
+   * depth in X11 terminology land is the number of bits used to
+   * actually represent the colour.
+   *
+   * bpp in X11 land means how many bits in the frame buffer per
+   * pixel.
+   *
+   * ex. 15 bit color is 15 bit depth and 16 bpp. Also 24 bit
+   *     color is 24 bit depth, but can be 24 bpp or 32 bpp.
+   */
+
+  window_attrs_cookie = xcb_get_window_attributes(this->connection, this->window);
+  geometry_cookie = xcb_get_geometry(this->connection, this->window);
+  xcb_prefetch_extension_data(this->connection, &xcb_shm_id);
+
+  window_attrs_reply = xcb_get_window_attributes_reply(this->connection, window_attrs_cookie, NULL);
+
+  visualtype = NULL;
+  {
+    xcb_depth_t *depth = xcb_screen_allowed_depths_iterator(this->screen).data;
+    xcb_visualtype_t *vis = xcb_depth_visuals(depth);
+    xcb_visualtype_t *vis_end = vis + xcb_depth_visuals_length(depth);
+
+    for (; vis != vis_end; ++vis)
+      if (window_attrs_reply->visual == vis->visual_id) {
+        visualtype = vis;
+        break;
+      }
+  }
+
+  free(window_attrs_reply);
+
+  geometry_reply = xcb_get_geometry_reply(this->connection, geometry_cookie, NULL);
+
+  this->depth = geometry_reply->depth;
+
+  free(geometry_reply);
+
+  if (this->depth>16)
+    xprintf(this->xine, XINE_VERBOSITY_LOG,
+	    _("\n\nWARNING: current display depth is %d. For better performance\n"
+	      "a depth of 16 bpp is recommended!\n\n"), this->depth);
+
+  /*
+   * check for X shared memory support
+   */
+
+  query_extension_reply = xcb_get_extension_data(this->connection, &xcb_shm_id);
+  if (query_extension_reply && query_extension_reply->present) {
+    this->use_shm = 1;
+  } 
+  else {
+    xprintf(this->xine, XINE_VERBOSITY_LOG,
+	    _("video_out_xshm: MIT shared memory extension not present on display.\n"));
+    this->use_shm = 0;
+  }
+
+  {
+    const xcb_setup_t *setup = xcb_get_setup(this->connection);
+    xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
+    xcb_format_t *fmt_end = fmt + xcb_setup_pixmap_formats_length(setup);
+
+    for (; fmt != fmt_end; ++fmt)
+      if(fmt->depth == this->depth) {
+        this->bpp = fmt->bits_per_pixel;
+        this->scanline_pad = fmt->scanline_pad;
+        break;
+    }
+
+    if (fmt == fmt_end) {
+      if (this->depth <= 4)
+        this->bpp = 4;
+      else if (this->depth <= 8)
+        this->bpp = 8;
+      else if (this->depth <= 16)
+        this->bpp = 16;
+      else
+        this->bpp = 32;
+      this->scanline_pad = setup->bitmap_format_scanline_pad;
+    }
+
+    image_byte_order = setup->image_byte_order;
+  }
+
+  /*
+   * Is the same byte order in use on the X11 client and server?
+   */
+  cpu_byte_order = htonl(1) == 1 ? XCB_IMAGE_ORDER_MSB_FIRST : XCB_IMAGE_ORDER_LSB_FIRST;
+  swapped = cpu_byte_order != image_byte_order;
+  
+  xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+	  "video_out_xshm: video mode depth is %d (%d bpp), %s, %sswapped,\n"
+	  "\tred: %08x, green: %08x, blue: %08x\n",
+	  this->depth, this->bpp,
+	  visual_class_name(visualtype),
+	  swapped ? "" : "not ",
+	  visualtype->red_mask, visualtype->green_mask, visualtype->blue_mask);
+
+  mode = 0;
+
+  switch (visualtype->_class) {
+  case XCB_VISUAL_CLASS_TRUE_COLOR:
+    switch (this->depth) {
+    case 24:
+    case 32:
+      if (this->bpp == 32) {
+	if (visualtype->red_mask == 0x00ff0000)
+	  mode = MODE_32_RGB;
+	else
+	  mode = MODE_32_BGR;
+      } else {
+	if (visualtype->red_mask == 0x00ff0000)
+	  mode = MODE_24_RGB;
+	else
+	  mode = MODE_24_BGR;
+      }
+      break;
+    case 16:
+	if (visualtype->red_mask == 0xf800)
+	mode = MODE_16_RGB;
+      else
+	mode = MODE_16_BGR;
+      break;
+    case 15:
+	if (visualtype->red_mask == 0x7C00)
+	mode = MODE_15_RGB;
+      else
+	mode = MODE_15_BGR;
+      break;
+    case 8:
+	if (visualtype->red_mask == 0xE0)
+	mode = MODE_8_RGB; /* Solaris x86: RGB332 */
+      else
+	mode = MODE_8_BGR; /* XFree86: BGR233 */
+      break;
+    }
+    break;
+
+  case XCB_VISUAL_CLASS_STATIC_GRAY:
+    if (this->depth == 8)
+      mode = MODE_8_GRAY;
+    break;
+
+  case XCB_VISUAL_CLASS_PSEUDO_COLOR:
+  case XCB_VISUAL_CLASS_GRAY_SCALE:
+    if (this->depth <= 8 && ImlibPaletteLUTGet(this))
+      mode = MODE_PALETTE;
+    break;
+  }
+
+  if (!mode) {
+    xprintf (this->xine, XINE_VERBOSITY_LOG, 
+	     _("video_out_xshm: your video mode was not recognized, sorry :-(\n"));
+    return NULL;
+  }
+  
+  this->yuv2rgb_brightness = 0;
+  this->yuv2rgb_contrast   = 128;
+  this->yuv2rgb_saturation = 128;
+  
+  this->yuv2rgb_factory = yuv2rgb_factory_init (mode, swapped, 
+						this->yuv2rgb_cmap);
+  this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory,
+					 this->yuv2rgb_brightness,
+					 this->yuv2rgb_contrast,
+					 this->yuv2rgb_saturation);
+
+  this->xoverlay = xcbosd_create(this->xine, this->connection, this->screen,
+                                 this->window, XCBOSD_SHAPED);
+
+  return &this->vo_driver;
+}
+
+/*
+ * class functions
+ */
+
+static char* xshm_get_identifier (video_driver_class_t *this_gen) {
+  return "XShm";
+}
+
+static char* xshm_get_description (video_driver_class_t *this_gen) {
+  return _("xine video output plugin using the MIT X shared memory extension");
+}
+
+static void xshm_dispose_class (video_driver_class_t *this_gen) {
+  xshm_class_t         *this = (xshm_class_t *) this_gen;
+
+  free (this);
+}
+
+static void *xshm_init_class (xine_t *xine, void *visual_gen) {
+  xshm_class_t	       *this = (xshm_class_t *) xine_xmalloc (sizeof (xshm_class_t));
+
+  this->driver_class.open_plugin     = xshm_open_plugin;
+  this->driver_class.get_identifier  = xshm_get_identifier;
+  this->driver_class.get_description = xshm_get_description;
+  this->driver_class.dispose         = xshm_dispose_class;
+  this->config                       = xine->config;
+  this->xine                         = xine;
+
+  return this;
+}
+
+
+static const vo_info_t vo_info_xshm = {
+  6,                      /* priority    */
+  XINE_VISUAL_TYPE_XCB    /* visual type */
+};
+
+
+/*
+ * exported plugin catalog entry
+ */
+
+const plugin_info_t xine_plugin_info[] EXPORTED = {
+  /* type, API, "name", version, special_info, init_function */  
+  { PLUGIN_VIDEO_OUT, 21, "xshm", XINE_VERSION_CODE, &vo_info_xshm, xshm_init_class },
+  { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};
Index: src/video_out/video_out_xcbxv.c
===================================================================
RCS file: src/video_out/video_out_xcbxv.c
diff -N src/video_out/video_out_xcbxv.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/video_out/video_out_xcbxv.c	7 Feb 2007 02:41:40 -0000
@@ -0,0 +1,1598 @@
+/*
+ * Copyright (C) 2000-2004, 2007 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * 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_xcbxv.c,v 1.221 2006/12/25 15:19:51 dgp85 Exp $
+ *
+ * video_out_xcbxv.c, X11 video extension interface for xine
+ *
+ * based on mpeg2dec code from
+ * Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ *
+ * Xv image support by Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ * xine-specific code by Guenter Bartsch <bartscgr@studbox.uni-stuttgart.de>
+ *
+ * overlay support by James Courtier-Dutton <James@superbug.demon.co.uk> - July 2001
+ * X11 unscaled overlay support by Miguel Freitas - Nov 2003
+ * ported to xcb by Christoph Pfister - Feb 2007
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_XV
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+
+#include <sys/types.h>
+#if defined(__FreeBSD__)
+#include <machine/param.h>
+#endif
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/time.h>
+
+#include <xcb/xv.h>
+
+#define LOG_MODULE "video_out_xcbxv"
+#define LOG_VERBOSE
+/*
+#define LOG
+*/
+
+#include "xine.h"
+#include "video_out.h"
+#include "xine_internal.h"
+/* #include "overlay.h" */
+#include "deinterlace.h"
+#include "xineutils.h"
+#include "vo_scale.h"
+#include "xcbosd.h"
+
+typedef struct xv_driver_s xv_driver_t;
+
+typedef struct {
+  int                value;
+  int                min;
+  int                max;
+  xcb_atom_t         atom;
+
+  cfg_entry_t       *entry;
+
+  xv_driver_t       *this;
+} xv_property_t;
+
+typedef struct {
+  char              *name;
+  int                value;
+} xv_portattribute_t;
+
+typedef struct {
+  vo_frame_t         vo_frame;
+
+  int                width, height, format;
+  double             ratio;
+
+  uint8_t           *image;
+  xcb_shm_seg_t      shmseg;
+  unsigned int       xv_format;
+  unsigned int       xv_data_size;
+  unsigned int       xv_width;
+  unsigned int       xv_height;
+  unsigned int       xv_pitches[3];
+  unsigned int       xv_offsets[3];
+
+} xv_frame_t;
+
+
+struct xv_driver_s {
+
+  vo_driver_t        vo_driver;
+
+  config_values_t   *config;
+
+  /* xcb / xv related stuff */
+  xcb_connection_t  *connection;
+  xcb_screen_t      *screen;
+  xcb_window_t       window;
+  unsigned int       xv_format_yv12;
+  unsigned int       xv_format_yuy2;
+  xcb_gc_t           gc;
+  xcb_xv_port_t      xv_port;
+
+  int                use_shm;
+  int                use_pitch_alignment;
+  xv_property_t      props[VO_NUM_PROPERTIES];
+  uint32_t           capabilities;
+
+  xv_frame_t        *recent_frames[VO_NUM_RECENT_FRAMES];
+  xv_frame_t        *cur_frame;
+  xcbosd            *xoverlay;
+  int                ovl_changed;
+
+  /* all scaling information goes here */
+  vo_scale_t         sc;
+
+  xv_frame_t         deinterlace_frame;
+  int                deinterlace_method;
+  int                deinterlace_enabled;
+
+  int                use_colorkey;
+  uint32_t           colorkey;
+
+  /* hold initial port attributes values to restore on exit */
+  xine_list_t       *port_attributes;
+
+  xine_t            *xine;
+
+  alphablend_t       alphablend_extra_data;
+
+  pthread_mutex_t    main_mutex;
+
+};
+
+typedef struct {
+  video_driver_class_t driver_class;
+
+  config_values_t     *config;
+  xine_t              *xine;
+} xv_class_t;
+
+static uint32_t xv_get_capabilities (vo_driver_t *this_gen) {
+  xv_driver_t *this = (xv_driver_t *) this_gen;
+
+  return this->capabilities;
+}
+
+static void xv_frame_field (vo_frame_t *vo_img, int which_field) {
+  /* not needed for Xv */
+}
+
+static void xv_frame_dispose (vo_frame_t *vo_img) {
+  xv_frame_t  *frame = (xv_frame_t *) vo_img ;
+  xv_driver_t *this  = (xv_driver_t *) vo_img->driver;
+
+  if (frame->shmseg) {
+    pthread_mutex_lock(&this->main_mutex);
+    xcb_shm_detach(this->connection, frame->shmseg);
+    frame->shmseg = 0;
+    pthread_mutex_unlock(&this->main_mutex);
+    shmdt(frame->image);
+  }
+  else
+    free(frame->image);
+
+  free (frame);
+}
+
+static vo_frame_t *xv_alloc_frame (vo_driver_t *this_gen) {
+  /* xv_driver_t  *this = (xv_driver_t *) this_gen; */
+  xv_frame_t   *frame ;
+
+  frame = (xv_frame_t *) xine_xmalloc (sizeof (xv_frame_t));
+  if (!frame)
+    return NULL;
+  
+  pthread_mutex_init (&frame->vo_frame.mutex, NULL);
+
+  /*
+   * supply required functions
+   */
+  frame->vo_frame.proc_slice = NULL;
+  frame->vo_frame.proc_frame = NULL;
+  frame->vo_frame.field      = xv_frame_field;
+  frame->vo_frame.dispose    = xv_frame_dispose;
+  frame->vo_frame.driver     = this_gen;
+
+  return (vo_frame_t *) frame;
+}
+
+static void create_ximage(xv_driver_t *this, xv_frame_t *frame, int width, int height, int format)
+{
+  xcb_xv_query_image_attributes_cookie_t query_attributes_cookie;
+  xcb_xv_query_image_attributes_reply_t *query_attributes_reply;
+
+  unsigned int length;
+
+  if (this->use_pitch_alignment) {
+    width = (width + 7) & ~0x7;
+  }
+
+  switch (format) {
+  case XINE_IMGFMT_YV12:
+    frame->xv_format = this->xv_format_yv12;
+    break;
+  case XINE_IMGFMT_YUY2:
+    frame->xv_format = this->xv_format_yuy2;
+    break;
+  default:
+    xprintf (this->xine, XINE_VERBOSITY_DEBUG, "create_ximage: unknown format %08x\n",format);
+    _x_abort();
+  }
+
+  query_attributes_cookie = xcb_xv_query_image_attributes(this->connection, this->xv_port, frame->xv_format, width, height);
+  query_attributes_reply = xcb_xv_query_image_attributes_reply(this->connection, query_attributes_cookie, NULL);
+
+  if (query_attributes_reply == NULL)
+    return;
+
+  frame->xv_data_size = query_attributes_reply->data_size;
+  frame->xv_width = query_attributes_reply->width;
+  frame->xv_height = query_attributes_reply->height;
+
+  length = xcb_xv_query_image_attributes_pitches_length(query_attributes_reply);
+  if (length > 3)
+    length = 3;
+  memcpy(frame->xv_pitches, xcb_xv_query_image_attributes_pitches(query_attributes_reply), length * sizeof(frame->xv_pitches[0]));
+
+  length = xcb_xv_query_image_attributes_offsets_length(query_attributes_reply);
+  if (length > 3)
+    length = 3;
+  memcpy(frame->xv_offsets, xcb_xv_query_image_attributes_offsets(query_attributes_reply), length * sizeof(frame->xv_offsets[0]));
+
+  free(query_attributes_reply);
+
+  if (this->use_shm) {
+    int shmid;
+    xcb_void_cookie_t shm_attach_cookie;
+    xcb_generic_error_t *generic_error;
+
+    /*
+     * try shm
+     */
+
+    if (frame->xv_data_size == 0) {
+      xprintf(this->xine, XINE_VERBOSITY_LOG,
+	      _("video_out_xv: XvShmCreateImage returned a zero size\n"
+		"video_out_xv: => not using MIT Shared Memory extension.\n"));
+      goto shm_fail1;
+    }
+
+    shmid = shmget(IPC_PRIVATE, frame->xv_data_size, IPC_CREAT | 0777);
+
+    if (shmid < 0 ) {
+      xprintf(this->xine, XINE_VERBOSITY_LOG,
+	      _("video_out_xv: shared memory error in shmget: %s\n"
+		"video_out_xv: => not using MIT Shared Memory extension.\n"), strerror(errno));
+      goto shm_fail1;
+    }
+
+    frame->image = shmat(shmid, 0, 0);
+
+    if (frame->image == ((void *) -1)) {
+      xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+	      "video_out_xv: shared memory error (address error)\n");
+      goto shm_fail2;
+    }
+
+    frame->shmseg = xcb_generate_id(this->connection);
+    shm_attach_cookie = xcb_shm_attach_checked(this->connection, frame->shmseg, shmid, 0);
+    generic_error = xcb_request_check(this->connection, shm_attach_cookie);
+
+    if (generic_error != NULL) {
+      xprintf(this->xine, XINE_VERBOSITY_LOG,
+	      _("video_out_xv: x11 error during shared memory XImage creation\n"
+		"video_out_xv: => not using MIT Shared Memory extension.\n"));
+      free(generic_error);
+      goto shm_fail3;
+    }
+
+    /*
+     * Now that the Xserver has learned about and attached to the
+     * shared memory segment,  delete it.  It's actually deleted by
+     * the kernel when all users of that segment have detached from
+     * it.  Gives an automatic shared memory cleanup in case we crash.
+     */
+
+    shmctl(shmid, IPC_RMID, 0);
+
+    return;
+
+  shm_fail3:
+    frame->shmseg = 0;
+    shmdt(frame->image);
+  shm_fail2:
+    shmctl(shmid, IPC_RMID, 0);
+  shm_fail1:
+    this->use_shm = 0;
+  }
+
+  /*
+   * fall back to plain Xv if necessary
+   */
+
+  switch (format) {
+  case XINE_IMGFMT_YV12:
+    frame->image = malloc(width * height * 3/2);
+    break;
+  case XINE_IMGFMT_YUY2:
+    frame->image = malloc(width * height * 2);
+    break;
+  default:
+    xprintf (this->xine, XINE_VERBOSITY_DEBUG, "create_ximage: unknown format %08x\n",format);
+    _x_abort();
+  }
+}
+
+static void dispose_ximage(xv_driver_t *this, xv_frame_t *frame)
+{
+  if (frame->shmseg) {
+    xcb_shm_detach(this->connection, frame->shmseg);
+    frame->shmseg = 0;
+    shmdt(frame->image);
+  } else
+    free(frame->image);
+  frame->image = NULL;
+}
+
+static void xv_update_frame_format (vo_driver_t *this_gen,
+				    vo_frame_t *frame_gen,
+				    uint32_t width, uint32_t height,
+				    double ratio, int format, int flags) {
+  xv_driver_t  *this  = (xv_driver_t *) this_gen;
+  xv_frame_t   *frame = (xv_frame_t *) frame_gen;
+
+  if (this->use_pitch_alignment) {
+    width = (width + 7) & ~0x7;
+  }
+
+  if ((frame->width != width)
+      || (frame->height != height)
+      || (frame->format != format)) {
+
+    /* printf ("video_out_xv: updating frame to %d x %d (ratio=%d, format=%08x)\n",width,height,ratio_code,format); */
+
+    pthread_mutex_lock(&this->main_mutex);
+
+    /*
+     * (re-) allocate xvimage
+     */
+
+    if (frame->image)
+      dispose_ximage(this, frame);
+
+    create_ximage(this, frame, width, height, format);
+
+    if(format == XINE_IMGFMT_YUY2) {
+      frame->vo_frame.pitches[0] = frame->xv_pitches[0];
+      frame->vo_frame.base[0] = frame->image + frame->xv_offsets[0];
+    } 
+    else {
+      frame->vo_frame.pitches[0] = frame->xv_pitches[0];
+      frame->vo_frame.pitches[1] = frame->xv_pitches[2];
+      frame->vo_frame.pitches[2] = frame->xv_pitches[1];
+      frame->vo_frame.base[0] = frame->image + frame->xv_offsets[0];
+      frame->vo_frame.base[1] = frame->image + frame->xv_offsets[2];
+      frame->vo_frame.base[2] = frame->image + frame->xv_offsets[1];
+    }
+
+    frame->width  = width;
+    frame->height = height;
+    frame->format = format;
+
+    pthread_mutex_unlock(&this->main_mutex);
+  }
+
+  frame->ratio = ratio;
+}
+
+#define DEINTERLACE_CROMA
+static void xv_deinterlace_frame (xv_driver_t *this) {
+  uint8_t    *recent_bitmaps[VO_NUM_RECENT_FRAMES];
+  xv_frame_t *frame = this->recent_frames[0];
+  int         i;
+  int         xvscaling;
+
+  xvscaling = (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) ? 2 : 1;
+
+  if (!this->deinterlace_frame.image
+      || (frame->width != this->deinterlace_frame.width)
+      || (frame->height != this->deinterlace_frame.height )
+      || (frame->format != this->deinterlace_frame.format)
+      || (frame->ratio != this->deinterlace_frame.ratio)) {
+    pthread_mutex_lock(&this->main_mutex);
+
+    if(this->deinterlace_frame.image)
+      dispose_ximage(this, &this->deinterlace_frame);
+    
+    create_ximage(this, &this->deinterlace_frame, frame->width, frame->height / xvscaling, frame->format);
+    this->deinterlace_frame.width  = frame->width;
+    this->deinterlace_frame.height = frame->height;
+    this->deinterlace_frame.format = frame->format;
+    this->deinterlace_frame.ratio  = frame->ratio;
+
+    pthread_mutex_unlock(&this->main_mutex);
+  }
+
+
+  if ( this->deinterlace_method != DEINTERLACE_ONEFIELDXV ) {
+#ifdef DEINTERLACE_CROMA
+
+    /* I don't think this is the right way to do it (deinterlacing croma by croma info).
+       DScaler deinterlaces croma together with luma, but it's easier for them because
+       they have that components 1:1 at the same table.
+    */
+    for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ )
+      if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width &&
+          this->recent_frames[i]->height == frame->height )
+        recent_bitmaps[i] = this->recent_frames[i]->image + frame->width*frame->height;
+      else
+        recent_bitmaps[i] = NULL;
+
+    deinterlace_yuv( this->deinterlace_frame.image+frame->width*frame->height,
+		     recent_bitmaps, frame->width/2, frame->height/2, this->deinterlace_method );
+    for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ )
+      if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width &&
+          this->recent_frames[i]->height == frame->height )
+        recent_bitmaps[i] = this->recent_frames[i]->image + frame->width*frame->height*5/4;
+      else
+        recent_bitmaps[i] = NULL;
+
+    deinterlace_yuv( this->deinterlace_frame.image+frame->width*frame->height*5/4,
+		     recent_bitmaps, frame->width/2, frame->height/2, this->deinterlace_method );
+
+#else
+
+    /* know bug: we are not deinterlacing Cb and Cr */
+    xine_fast_memcpy(this->deinterlace_frame.image + frame->width*frame->height,
+		     frame->image + frame->width*frame->height,
+		     frame->width*frame->height*1/2);
+
+#endif
+
+    for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ )
+      if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width &&
+          this->recent_frames[i]->height == frame->height )
+        recent_bitmaps[i] = this->recent_frames[i]->image;
+      else
+        recent_bitmaps[i] = NULL;
+
+    deinterlace_yuv( this->deinterlace_frame.image, recent_bitmaps,
+                     frame->width, frame->height, this->deinterlace_method );
+  }
+  else {
+    /*
+      dirty and cheap deinterlace method: we give half of the lines to xv
+      driver and let it scale for us.
+      note that memcpy's below don't seem to impact much on performance,
+      specially when fast memcpys are available.
+    */
+    uint8_t *dst, *src;
+
+    dst = this->deinterlace_frame.image;
+    src = this->recent_frames[0]->image;
+    for( i = 0; i < frame->height; i+=2 ) {
+      xine_fast_memcpy(dst,src,frame->width);
+      dst += frame->width;
+      src += 2 * frame->width;
+    }
+
+    dst = this->deinterlace_frame.image + frame->width * frame->height / 2;
+    src = this->recent_frames[0]->image + frame->width * frame->height;
+    for( i = 0; i < frame->height; i+=4 ) {
+      xine_fast_memcpy(dst,src,frame->width / 2);
+      dst += frame->width / 2;
+      src += frame->width;
+    }
+
+    dst = this->deinterlace_frame.image + frame->width * frame->height * 5 / 8;
+    src = this->recent_frames[0]->image + frame->width * frame->height * 5 / 4;
+    for( i = 0; i < frame->height; i+=4 ) {
+      xine_fast_memcpy(dst,src,frame->width / 2);
+      dst += frame->width / 2;
+      src += frame->width;
+    }
+  }
+
+  this->cur_frame = &this->deinterlace_frame;
+}
+
+static void xv_clean_output_area (xv_driver_t *this) {
+  int i;
+  xcb_rectangle_t rects[4];
+  int rects_count = 0;
+
+  pthread_mutex_lock(&this->main_mutex);
+
+  xcb_change_gc(this->connection, this->gc, XCB_GC_FOREGROUND, &this->screen->black_pixel);
+
+  for( i = 0; i < 4; i++ ) {
+    if( this->sc.border[i].w && this->sc.border[i].h ) {
+      rects[rects_count].x = this->sc.border[i].x;
+      rects[rects_count].y = this->sc.border[i].y;
+      rects[rects_count].width = this->sc.border[i].w;
+      rects[rects_count].height = this->sc.border[i].h;
+      rects_count++;
+    }
+  }
+
+  if (rects_count > 0)
+    xcb_poly_fill_rectangle(this->connection, this->window, this->gc, rects_count, rects);
+
+  if (this->use_colorkey) {
+    xcb_change_gc(this->connection, this->gc, XCB_GC_FOREGROUND, &this->colorkey);
+    xcb_rectangle_t rectangle = { this->sc.output_xoffset, this->sc.output_yoffset,
+				  this->sc.output_width, this->sc.output_height };
+    xcb_poly_fill_rectangle(this->connection, this->window, this->gc, 1, &rectangle);
+  }
+  
+  if (this->xoverlay) {
+    xcbosd_resize(this->xoverlay, this->sc.gui_width, this->sc.gui_height);
+    this->ovl_changed = 1;
+  }
+  
+  pthread_mutex_unlock(&this->main_mutex);
+}
+
+/*
+ * convert delivered height/width to ideal width/height
+ * taking into account aspect ratio and zoom factor
+ */
+
+static void xv_compute_ideal_size (xv_driver_t *this) {
+  _x_vo_scale_compute_ideal_size( &this->sc );
+}
+
+
+/*
+ * make ideal width/height "fit" into the gui
+ */
+
+static void xv_compute_output_size (xv_driver_t *this) {
+
+  _x_vo_scale_compute_output_size( &this->sc );
+
+  /* onefield_xv divide by 2 the number of lines */
+  if (this->deinterlace_enabled
+      && (this->deinterlace_method == DEINTERLACE_ONEFIELDXV)
+      && this->cur_frame && (this->cur_frame->format == XINE_IMGFMT_YV12)) {
+    this->sc.displayed_height  = this->sc.displayed_height / 2 - 1;
+    this->sc.displayed_yoffset = this->sc.displayed_yoffset / 2;
+  }
+}
+
+static void xv_overlay_begin (vo_driver_t *this_gen, 
+			      vo_frame_t *frame_gen, int changed) {
+  xv_driver_t  *this = (xv_driver_t *) this_gen;
+
+  this->ovl_changed += changed;
+
+  if( this->ovl_changed && this->xoverlay ) {
+    pthread_mutex_lock(&this->main_mutex);
+    xcbosd_clear(this->xoverlay);
+    pthread_mutex_unlock(&this->main_mutex);
+  }
+  
+  this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x;
+  this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y;
+}
+
+static void xv_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) {
+  xv_driver_t  *this = (xv_driver_t *) this_gen;
+
+  if( this->ovl_changed && this->xoverlay ) {
+    pthread_mutex_lock(&this->main_mutex);
+    xcbosd_expose(this->xoverlay);
+    pthread_mutex_unlock(&this->main_mutex);
+  }
+
+  this->ovl_changed = 0;
+}
+
+static void xv_overlay_blend (vo_driver_t *this_gen, 
+			      vo_frame_t *frame_gen, vo_overlay_t *overlay) {
+  xv_driver_t  *this = (xv_driver_t *) this_gen;
+  xv_frame_t   *frame = (xv_frame_t *) frame_gen;
+
+  if (overlay->rle) {
+    if( overlay->unscaled ) {
+      if( this->ovl_changed && this->xoverlay ) {
+        pthread_mutex_lock(&this->main_mutex);
+        xcbosd_blend(this->xoverlay, overlay);
+        pthread_mutex_unlock(&this->main_mutex);
+      }
+    } else {
+      if (frame->format == XINE_IMGFMT_YV12)
+        _x_blend_yuv(frame->vo_frame.base, overlay, 
+		  frame->width, frame->height, frame->vo_frame.pitches,
+                  &this->alphablend_extra_data);
+      else
+        _x_blend_yuy2(frame->vo_frame.base[0], overlay, 
+		   frame->width, frame->height, frame->vo_frame.pitches[0],
+                   &this->alphablend_extra_data);
+    }
+  }
+}
+
+static void xv_add_recent_frame (xv_driver_t *this, xv_frame_t *frame) {
+  int i;
+
+  i = VO_NUM_RECENT_FRAMES-1;
+  if( this->recent_frames[i] )
+    this->recent_frames[i]->vo_frame.free
+       (&this->recent_frames[i]->vo_frame);
+
+  for( ; i ; i-- )
+    this->recent_frames[i] = this->recent_frames[i-1];
+
+  this->recent_frames[0] = frame;
+}
+
+/* currently not used - we could have a method to call this from video loop */
+#if 0
+static void xv_flush_recent_frames (xv_driver_t *this) {
+  int i;
+
+  for( i=0; i < VO_NUM_RECENT_FRAMES; i++ ) {
+    if( this->recent_frames[i] )
+      this->recent_frames[i]->vo_frame.free
+         (&this->recent_frames[i]->vo_frame);
+    this->recent_frames[i] = NULL;
+  }
+}
+#endif
+
+static int xv_redraw_needed (vo_driver_t *this_gen) {
+  xv_driver_t  *this = (xv_driver_t *) this_gen;
+  int           ret  = 0;
+
+  if( this->cur_frame ) {
+
+    this->sc.delivered_height = this->cur_frame->height;
+    this->sc.delivered_width  = this->cur_frame->width;
+    this->sc.delivered_ratio  = this->cur_frame->ratio;
+    
+    this->sc.crop_left        = this->cur_frame->vo_frame.crop_left;
+    this->sc.crop_right       = this->cur_frame->vo_frame.crop_right;
+    this->sc.crop_top         = this->cur_frame->vo_frame.crop_top;
+    this->sc.crop_bottom      = this->cur_frame->vo_frame.crop_bottom;
+
+    xv_compute_ideal_size(this);
+
+    if( _x_vo_scale_redraw_needed( &this->sc ) ) {
+
+      xv_compute_output_size (this);
+
+      xv_clean_output_area (this);
+
+      ret = 1;
+    }
+  }
+  else
+    ret = 1;
+
+  return ret;
+}
+
+static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
+  xv_driver_t  *this  = (xv_driver_t *) this_gen;
+  xv_frame_t   *frame = (xv_frame_t *) frame_gen;
+  /*
+  printf ("video_out_xv: xv_display_frame...\n");
+  */
+  
+  /*
+   * queue frames (deinterlacing)
+   * free old frames
+   */
+
+  xv_add_recent_frame (this, frame); /* deinterlacing */
+
+  this->cur_frame = frame;
+
+  /*
+   * let's see if this frame is different in size / aspect
+   * ratio from the previous one
+   */
+  if ( (frame->width != this->sc.delivered_width)
+       || (frame->height != this->sc.delivered_height)
+       || (frame->ratio != this->sc.delivered_ratio) ) {
+    lprintf("frame format changed\n");
+    this->sc.force_redraw = 1;    /* trigger re-calc of output size */
+  }
+
+  /*
+   * deinterlace frame if necessary
+   * (currently only working for YUV images)
+   */
+
+  if (this->deinterlace_enabled && this->deinterlace_method
+      && frame->format == XINE_IMGFMT_YV12
+      && (deinterlace_yuv_supported( this->deinterlace_method ) == 1
+	  || this->deinterlace_method ==  DEINTERLACE_ONEFIELDXV))
+    xv_deinterlace_frame (this);
+
+  /*
+   * tell gui that we are about to display a frame,
+   * ask for offset and output size
+   */
+  xv_redraw_needed (this_gen);
+
+  pthread_mutex_lock(&this->main_mutex);
+
+  if (this->cur_frame->shmseg) {
+    xcb_xv_shm_put_image(this->connection, this->xv_port, this->window, this->gc,
+                         this->cur_frame->shmseg, this->cur_frame->xv_format, 0,
+                         this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+                         this->sc.displayed_width, this->sc.displayed_height,
+                         this->sc.output_xoffset, this->sc.output_yoffset,
+                         this->sc.output_width, this->sc.output_height,
+                         this->cur_frame->xv_width, this->cur_frame->xv_height, 0);
+
+  } else {
+    xcb_xv_put_image(this->connection, this->xv_port, this->window, this->gc,
+                     this->cur_frame->xv_format,
+                     this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+                     this->sc.displayed_width, this->sc.displayed_height,
+                     this->sc.output_xoffset, this->sc.output_yoffset,
+                     this->sc.output_width, this->sc.output_height,
+                     this->cur_frame->xv_width, this->cur_frame->xv_height,
+                     this->cur_frame->xv_data_size, this->cur_frame->image);
+  }
+
+  xcb_flush(this->connection);
+
+  pthread_mutex_unlock(&this->main_mutex);
+
+  /*
+  printf ("video_out_xv: xv_display_frame... done\n");
+  */
+}
+
+static int xv_get_property (vo_driver_t *this_gen, int property) {
+  xv_driver_t *this = (xv_driver_t *) this_gen;
+
+  switch (property) {
+    case VO_PROP_WINDOW_WIDTH:
+      this->props[property].value = this->sc.gui_width;
+      break;
+    case VO_PROP_WINDOW_HEIGHT:
+      this->props[property].value = this->sc.gui_height;
+      break;
+  }
+
+  lprintf("video_out_xv: property #%d = %d\n", property, this->props[property].value);
+
+  return this->props[property].value;
+}
+
+static void xv_property_callback (void *property_gen, xine_cfg_entry_t *entry) {
+  xv_property_t *property = (xv_property_t *) property_gen;
+  xv_driver_t   *this = property->this;
+  
+  pthread_mutex_lock(&this->main_mutex);
+  xcb_xv_set_port_attribute(this->connection, this->xv_port,
+			    property->atom, entry->num_value);
+  pthread_mutex_unlock(&this->main_mutex);
+}
+
+static int xv_set_property (vo_driver_t *this_gen,
+			    int property, int value) {
+  xv_driver_t *this = (xv_driver_t *) this_gen;
+
+  if (this->props[property].atom != XCB_NONE) {
+    xcb_xv_get_port_attribute_cookie_t get_attribute_cookie;
+    xcb_xv_get_port_attribute_reply_t *get_attribute_reply;
+
+    /* value is out of bound */
+    if((value < this->props[property].min) || (value > this->props[property].max))
+      value = (this->props[property].min + this->props[property].max) >> 1;
+
+    pthread_mutex_lock(&this->main_mutex);
+    xcb_xv_set_port_attribute(this->connection, this->xv_port,
+			      this->props[property].atom, value);
+
+    get_attribute_cookie = xcb_xv_get_port_attribute(this->connection, this->xv_port, this->props[property].atom);
+    get_attribute_reply = xcb_xv_get_port_attribute_reply(this->connection, get_attribute_cookie, NULL);
+    this->props[property].value = get_attribute_reply->value;
+    free(get_attribute_reply);
+
+    pthread_mutex_unlock(&this->main_mutex);
+
+    if (this->props[property].entry)
+      this->props[property].entry->num_value = this->props[property].value;
+
+    return this->props[property].value;
+  } 
+  else {
+    switch (property) {
+
+    case VO_PROP_INTERLACED:
+      this->props[property].value = value;
+      xprintf(this->xine, XINE_VERBOSITY_LOG,
+	      "video_out_xv: VO_PROP_INTERLACED(%d)\n", this->props[property].value);
+      this->deinterlace_enabled = value;
+      if (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) {
+         xv_compute_ideal_size (this);
+         xv_compute_output_size (this);
+      }
+      break;
+  
+    case VO_PROP_ASPECT_RATIO:
+      if (value>=XINE_VO_ASPECT_NUM_RATIOS)
+	value = XINE_VO_ASPECT_AUTO;
+
+      this->props[property].value = value;
+      xprintf(this->xine, XINE_VERBOSITY_LOG, 
+	      "video_out_xv: VO_PROP_ASPECT_RATIO(%d)\n", this->props[property].value);
+      this->sc.user_ratio = value;
+
+      xv_compute_ideal_size (this);
+
+      this->sc.force_redraw = 1;    /* trigger re-calc of output size */
+      break;
+
+    case VO_PROP_ZOOM_X:
+      if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) {
+        this->props[property].value = value;
+	xprintf(this->xine, XINE_VERBOSITY_LOG,
+		"video_out_xv: VO_PROP_ZOOM_X = %d\n", this->props[property].value);
+	
+	this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP;
+
+	xv_compute_ideal_size (this);
+
+	this->sc.force_redraw = 1;    /* trigger re-calc of output size */
+      }
+      break;
+
+    case VO_PROP_ZOOM_Y:
+      if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) {
+        this->props[property].value = value;
+	xprintf(this->xine, XINE_VERBOSITY_LOG,
+		"video_out_xv: VO_PROP_ZOOM_Y = %d\n", this->props[property].value);
+
+	this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP;
+
+	xv_compute_ideal_size (this);
+
+	this->sc.force_redraw = 1;    /* trigger re-calc of output size */
+      }
+      break;
+    }
+  }
+
+  return value;
+}
+
+static void xv_get_property_min_max (vo_driver_t *this_gen,
+				     int property, int *min, int *max) {
+  xv_driver_t *this = (xv_driver_t *) this_gen;
+
+  *min = this->props[property].min;
+  *max = this->props[property].max;
+}
+
+static int xv_gui_data_exchange (vo_driver_t *this_gen,
+				 int data_type, void *data) {
+  xv_driver_t     *this = (xv_driver_t *) this_gen;
+
+  switch (data_type) {
+#ifndef XINE_DISABLE_DEPRECATED_FEATURES
+  case XINE_GUI_SEND_COMPLETION_EVENT:
+    break;
+#endif
+
+  case XINE_GUI_SEND_EXPOSE_EVENT: {
+    /* XExposeEvent * xev = (XExposeEvent *) data; */
+
+    if (this->cur_frame) {
+
+      pthread_mutex_lock(&this->main_mutex);
+
+      if (this->cur_frame->shmseg) {
+	xcb_xv_shm_put_image(this->connection, this->xv_port, this->window, this->gc,
+			     this->cur_frame->shmseg, this->cur_frame->xv_format, 0,
+			     this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+			     this->sc.displayed_width, this->sc.displayed_height,
+			     this->sc.output_xoffset, this->sc.output_yoffset,
+			     this->sc.output_width, this->sc.output_height,
+			     this->cur_frame->xv_width, this->cur_frame->xv_height, 0);
+      } else {
+	xcb_xv_put_image(this->connection, this->xv_port, this->window, this->gc,
+			 this->cur_frame->xv_format,
+			 this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+			 this->sc.displayed_width, this->sc.displayed_height,
+			 this->sc.output_xoffset, this->sc.output_yoffset,
+			 this->sc.output_width, this->sc.output_height,
+			 this->cur_frame->xv_width, this->cur_frame->xv_height,
+			 this->cur_frame->xv_data_size, this->cur_frame->image);
+      }
+
+      if(this->xoverlay)
+	xcbosd_expose(this->xoverlay);
+      
+      xcb_flush(this->connection);
+      pthread_mutex_unlock(&this->main_mutex);
+    }
+  }
+  break;
+
+  case XINE_GUI_SEND_DRAWABLE_CHANGED:
+    pthread_mutex_lock(&this->main_mutex);
+    this->window = (xcb_window_t) data;
+    xcb_free_gc(this->connection, this->gc);
+    this->gc = xcb_generate_id(this->connection);
+    xcb_create_gc(this->connection, this->gc, this->window, 0, NULL);
+    if(this->xoverlay)
+      xcbosd_drawable_changed(this->xoverlay, this->window);
+    this->ovl_changed = 1;
+    pthread_mutex_unlock(&this->main_mutex);
+    this->sc.force_redraw = 1;
+    break;
+
+  case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO:
+    {
+      int x1, y1, x2, y2;
+      x11_rectangle_t *rect = data;
+
+      _x_vo_scale_translate_gui2video(&this->sc, rect->x, rect->y,
+				   &x1, &y1);
+      _x_vo_scale_translate_gui2video(&this->sc, rect->x + rect->w, rect->y + rect->h,
+				   &x2, &y2);
+      rect->x = x1;
+      rect->y = y1;
+      rect->w = x2-x1;
+      rect->h = y2-y1;
+
+      /* onefield_xv divide by 2 the number of lines */
+      if (this->deinterlace_enabled
+          && (this->deinterlace_method == DEINTERLACE_ONEFIELDXV)
+          && (this->cur_frame->format == XINE_IMGFMT_YV12)) {
+        rect->y = rect->y * 2;
+        rect->h = rect->h * 2;
+      }
+
+    }
+    break;
+
+  default:
+    return -1;
+  }
+
+  return 0;
+}
+
+static void xv_store_port_attribute(xv_driver_t *this, char *name) {
+  xv_portattribute_t  *attr;
+
+  xcb_intern_atom_cookie_t atom_cookie;
+  xcb_intern_atom_reply_t *atom_reply;
+
+  xcb_xv_get_port_attribute_cookie_t get_attribute_cookie;
+  xcb_xv_get_port_attribute_reply_t *get_attribute_reply;
+  
+  attr = (xv_portattribute_t *)malloc( sizeof(xv_portattribute_t) );
+  attr->name = strdup(name);
+  
+  pthread_mutex_lock(&this->main_mutex);
+  atom_cookie = xcb_intern_atom(this->connection, 0, strlen(attr->name), attr->name);
+  atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL);
+  get_attribute_cookie = xcb_xv_get_port_attribute(this->connection, this->xv_port, atom_reply->atom);
+  get_attribute_reply = xcb_xv_get_port_attribute_reply(this->connection, get_attribute_cookie, NULL);
+  attr->value = get_attribute_reply->value;
+  free(atom_reply);
+  free(get_attribute_reply);
+  pthread_mutex_unlock(&this->main_mutex);
+  
+  xine_list_push_back (this->port_attributes, attr);
+}
+
+static void xv_restore_port_attributes(xv_driver_t *this) {
+  xine_list_iterator_t ite;
+
+  xcb_intern_atom_cookie_t atom_cookie;
+  xcb_intern_atom_reply_t *atom_reply;
+  
+  while ((ite = xine_list_front(this->port_attributes)) != NULL) {
+    xv_portattribute_t *attr = xine_list_get_value(this->port_attributes, ite);
+    xine_list_remove (this->port_attributes, ite);
+  
+    pthread_mutex_lock(&this->main_mutex);
+    atom_cookie = xcb_intern_atom(this->connection, 0, strlen(attr->name), attr->name);
+    atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL);
+    xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, attr->value);
+    free(atom_reply);
+    pthread_mutex_unlock(&this->main_mutex);
+        
+    free( attr->name );
+    free( attr );
+  }
+  
+  pthread_mutex_lock(&this->main_mutex);
+  xcb_flush(this->connection);
+  pthread_mutex_unlock(&this->main_mutex);
+ 
+  xine_list_delete( this->port_attributes );
+}
+
+static void xv_dispose (vo_driver_t *this_gen) {
+  xv_driver_t *this = (xv_driver_t *) this_gen;
+  int          i;
+
+  /* restore port attributes to their initial values */
+  xv_restore_port_attributes(this);
+  
+  if (this->deinterlace_frame.image) {
+    pthread_mutex_lock(&this->main_mutex);
+    dispose_ximage(this, &this->deinterlace_frame);
+    pthread_mutex_unlock(&this->main_mutex);
+  }
+
+  pthread_mutex_lock(&this->main_mutex);
+  xcb_xv_ungrab_port(this->connection, this->xv_port, XCB_CURRENT_TIME);
+  xcb_free_gc(this->connection, this->gc);
+  pthread_mutex_unlock(&this->main_mutex);
+
+  for( i=0; i < VO_NUM_RECENT_FRAMES; i++ ) {
+    if( this->recent_frames[i] )
+      this->recent_frames[i]->vo_frame.dispose
+         (&this->recent_frames[i]->vo_frame);
+    this->recent_frames[i] = NULL;
+  }
+
+  if( this->xoverlay ) {
+    pthread_mutex_lock(&this->main_mutex);
+    xcbosd_destroy(this->xoverlay);
+    pthread_mutex_unlock(&this->main_mutex);
+  }
+
+  pthread_mutex_destroy(&this->main_mutex);
+
+  _x_alphablend_free(&this->alphablend_extra_data);
+  
+  free (this);
+}
+
+static int xv_check_yv12(xcb_connection_t *connection, xcb_xv_port_t port) {
+  xcb_xv_list_image_formats_cookie_t list_formats_cookie;
+  xcb_xv_list_image_formats_reply_t *list_formats_reply;
+
+  xcb_xv_image_format_info_iterator_t format_it;
+
+  list_formats_cookie = xcb_xv_list_image_formats(connection, port);
+  list_formats_reply = xcb_xv_list_image_formats_reply(connection, list_formats_cookie, NULL);
+  format_it = xcb_xv_list_image_formats_format_iterator(list_formats_reply);
+  
+  for (; format_it.rem; xcb_xv_image_format_info_next(&format_it))
+    if ((format_it.data->id == XINE_IMGFMT_YV12) &&
+	(! (strcmp ((char *) format_it.data->guid, "YV12")))) {
+      free(list_formats_reply);
+      return 0;
+    }
+
+  free(list_formats_reply);
+  return 1;
+}
+
+static void xv_check_capability (xv_driver_t *this,
+				 int property, xcb_xv_attribute_info_t *attr,
+				 int base_id,
+				 char *config_name,
+				 char *config_desc,
+				 char *config_help) {
+  int          int_default;
+  cfg_entry_t *entry;
+  char        *str_prop = xcb_xv_attribute_info_name(attr);
+
+  xcb_xv_get_port_attribute_cookie_t get_attribute_cookie;
+  xcb_xv_get_port_attribute_reply_t *get_attribute_reply;
+
+  xcb_intern_atom_cookie_t atom_cookie;
+  xcb_intern_atom_reply_t *atom_reply;
+   
+  /*
+   * some Xv drivers (Gatos ATI) report some ~0 as max values, this is confusing.
+   */
+  if (VO_PROP_COLORKEY && (attr->max == ~0))
+    attr->max = 2147483615;
+
+  atom_cookie = xcb_intern_atom(this->connection, 0, strlen(str_prop), str_prop);
+  atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL);
+
+  this->props[property].min  = attr->min;
+  this->props[property].max  = attr->max;
+  this->props[property].atom = atom_reply->atom;
+
+  free(atom_reply);
+
+  get_attribute_cookie = xcb_xv_get_port_attribute(this->connection, this->xv_port, this->props[property].atom);
+  get_attribute_reply = xcb_xv_get_port_attribute_reply(this->connection, get_attribute_cookie, NULL);
+
+  int_default = get_attribute_reply->value;
+
+  free(get_attribute_reply);
+
+  xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+	  "video_out_xv: port attribute %s (%d) value is %d\n", str_prop, property, int_default);
+
+  /* disable autopaint colorkey by default */
+  /* might be overridden using config entry */
+  if(strcmp(str_prop, "XV_AUTOPAINT_COLORKEY") == 0)
+    int_default = 0;
+    
+  if (config_name) {
+    /* is this a boolean property ? */
+    if ((attr->min == 0) && (attr->max == 1)) {
+      this->config->register_bool (this->config, config_name, int_default,
+				   config_desc,
+				   config_help, 20, xv_property_callback, &this->props[property]);
+
+    } else {
+      this->config->register_range (this->config, config_name, int_default,
+				    this->props[property].min, this->props[property].max,
+				    config_desc,
+				    config_help, 20, xv_property_callback, &this->props[property]);
+    }
+
+    entry = this->config->lookup_entry (this->config, config_name);
+
+    if((entry->num_value < this->props[property].min) || 
+       (entry->num_value > this->props[property].max)) {
+
+      this->config->update_num(this->config, config_name, 
+			       ((this->props[property].min + this->props[property].max) >> 1));
+      
+      entry = this->config->lookup_entry (this->config, config_name);
+    }
+
+    this->props[property].entry = entry;
+
+    xv_set_property (&this->vo_driver, property, entry->num_value);
+
+    if (strcmp(str_prop, "XV_COLORKEY") == 0) {
+      this->use_colorkey |= 1;
+      this->colorkey = entry->num_value;
+    } else if(strcmp(str_prop, "XV_AUTOPAINT_COLORKEY") == 0) {
+      if(entry->num_value==1)
+        this->use_colorkey |= 2;	/* colorkey is autopainted */
+    }
+  } else
+    this->props[property].value  = int_default;
+
+}
+
+static void xv_update_deinterlace(void *this_gen, xine_cfg_entry_t *entry) {
+  xv_driver_t *this = (xv_driver_t *) this_gen;
+
+  this->deinterlace_method = entry->num_value;
+}
+
+static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) {
+  xv_driver_t *this = (xv_driver_t *) this_gen;
+  int xv_filter;
+
+  xcb_intern_atom_cookie_t atom_cookie;
+  xcb_intern_atom_reply_t *atom_reply;
+
+  xv_filter = entry->num_value;
+
+  pthread_mutex_lock(&this->main_mutex);
+  atom_cookie = xcb_intern_atom(this->connection, 0, sizeof("XV_FILTER"), "XV_FILTER");
+  atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL);
+  xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, xv_filter);
+  free(atom_reply);
+  pthread_mutex_unlock(&this->main_mutex);
+
+  xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+	  "video_out_xv: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter);
+}
+
+static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) {
+  xv_driver_t *this = (xv_driver_t *) this_gen;
+  int          xv_double_buffer;
+
+  xcb_intern_atom_cookie_t atom_cookie;
+  xcb_intern_atom_reply_t *atom_reply;
+
+  xv_double_buffer = entry->num_value;
+
+  pthread_mutex_lock(&this->main_mutex);
+  atom_cookie = xcb_intern_atom(this->connection, 0, sizeof("XV_DOUBLE_BUFFER"), "XV_DOUBLE_BUFFER");
+  atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL);
+  xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, xv_double_buffer);
+  free(atom_reply);
+  pthread_mutex_unlock(&this->main_mutex);
+
+  xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+	  "video_out_xv: double buffering mode = %d\n", xv_double_buffer);
+}
+
+static void xv_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) {
+  xv_driver_t *this = (xv_driver_t *) this_gen;
+
+  this->use_pitch_alignment = entry->num_value;
+}
+
+static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *visual_gen) {
+  xv_class_t           *class = (xv_class_t *) class_gen;
+  config_values_t      *config = class->config;
+  xv_driver_t          *this;
+  int                   i;
+  xcb_visual_t         *visual = (xcb_visual_t *) visual_gen;
+  unsigned int          j;
+  xcb_xv_port_t         xv_port;
+
+  const xcb_query_extension_reply_t *query_extension_reply;
+
+  xcb_xv_query_adaptors_cookie_t query_adaptors_cookie;
+  xcb_xv_query_adaptors_reply_t *query_adaptors_reply;
+  xcb_xv_query_port_attributes_cookie_t query_attributes_cookie;
+  xcb_xv_query_port_attributes_reply_t *query_attributes_reply;
+  xcb_xv_list_image_formats_cookie_t list_formats_cookie;
+  xcb_xv_list_image_formats_reply_t *list_formats_reply;
+
+  xcb_xv_adaptor_info_iterator_t adaptor_it;
+  xcb_xv_image_format_info_iterator_t format_it;
+
+  this = (xv_driver_t *) xine_xmalloc (sizeof (xv_driver_t));
+  if (!this)
+    return NULL;
+
+  pthread_mutex_init(&this->main_mutex, NULL);
+
+  _x_alphablend_init(&this->alphablend_extra_data, class->xine);
+  
+  this->connection        = visual->connection;
+  this->screen            = visual->screen;
+  this->window            = visual->window;
+  this->config            = config;
+
+  /*
+   * check for Xvideo support
+   */
+
+  query_extension_reply = xcb_get_extension_data(this->connection, &xcb_xv_id);
+  if (!query_extension_reply || !query_extension_reply->present) {
+    xprintf (class->xine, XINE_VERBOSITY_LOG, _("video_out_xv: Xv extension not present.\n"));
+    return NULL;
+  }
+
+  /*
+   * check adaptors, search for one that supports (at least) yuv12
+   */
+
+  query_adaptors_cookie = xcb_xv_query_adaptors(this->connection, this->window);
+  query_adaptors_reply = xcb_xv_query_adaptors_reply(this->connection, query_adaptors_cookie, NULL);
+
+  if (!query_adaptors_reply) {
+    xprintf(class->xine, XINE_VERBOSITY_DEBUG, "video_out_xv: XvQueryAdaptors failed.\n");
+    return NULL;
+  }
+
+  adaptor_it = xcb_xv_query_adaptors_info_iterator(query_adaptors_reply);
+
+  xv_port = 0;
+
+  for (; adaptor_it.rem && !xv_port; xcb_xv_adaptor_info_next(&adaptor_it)) {
+
+    if (adaptor_it.data->type & XCB_XV_TYPE_IMAGE_MASK) {
+
+      for (j = 0; j < adaptor_it.data->num_ports; j++)
+        if (!xv_check_yv12(this->connection, adaptor_it.data->base_id + j)) {
+          xcb_xv_grab_port_cookie_t grab_port_cookie;
+          xcb_xv_grab_port_reply_t *grab_port_reply;
+          grab_port_cookie = xcb_xv_grab_port(this->connection, adaptor_it.data->base_id + j, XCB_CURRENT_TIME);
+          grab_port_reply = xcb_xv_grab_port_reply(this->connection, grab_port_cookie, NULL);
+          if (grab_port_reply && (grab_port_reply->result == XCB_GRAB_STATUS_SUCCESS)) {
+            free(grab_port_reply);
+            xv_port = adaptor_it.data->base_id + j;
+            break;
+          }
+          free(grab_port_reply);
+        }
+    }
+  }
+
+  if (!xv_port) {
+    xprintf(class->xine, XINE_VERBOSITY_LOG,
+	    _("video_out_xv: Xv extension is present but I couldn't find a usable yuv12 port.\n"
+	      "              Looks like your graphics hardware driver doesn't support Xv?!\n"));
+    
+    /* XvFreeAdaptorInfo (adaptor_info); this crashed on me (gb)*/
+    return NULL;
+  } 
+  else
+    xprintf(class->xine, XINE_VERBOSITY_LOG,
+	    _("video_out_xv: using Xv port %d from adaptor %s for hardware "
+	      "colorspace conversion and scaling.\n"), xv_port,
+            xcb_xv_adaptor_info_name(adaptor_it.data));
+  
+  this->xv_port           = xv_port;
+
+  _x_vo_scale_init (&this->sc, 1, 0, config );
+  this->sc.frame_output_cb   = visual->frame_output_cb;
+  this->sc.user_data         = visual->user_data;
+
+  this->gc                      = xcb_generate_id(this->connection);
+  xcb_create_gc(this->connection, this->gc, this->window, 0, NULL);
+  this->capabilities            = VO_CAP_CROP;
+  this->use_shm                 = 1;
+  this->deinterlace_method      = 0;
+  this->deinterlace_frame.image = NULL;
+  this->use_colorkey            = 0;
+  this->colorkey                = 0;
+  this->xoverlay                = NULL;
+  this->ovl_changed             = 0;
+  this->xine                    = class->xine;
+
+  this->vo_driver.get_capabilities     = xv_get_capabilities;
+  this->vo_driver.alloc_frame          = xv_alloc_frame;
+  this->vo_driver.update_frame_format  = xv_update_frame_format;
+  this->vo_driver.overlay_begin        = xv_overlay_begin;
+  this->vo_driver.overlay_blend        = xv_overlay_blend;
+  this->vo_driver.overlay_end          = xv_overlay_end;
+  this->vo_driver.display_frame        = xv_display_frame;
+  this->vo_driver.get_property         = xv_get_property;
+  this->vo_driver.set_property         = xv_set_property;
+  this->vo_driver.get_property_min_max = xv_get_property_min_max;
+  this->vo_driver.gui_data_exchange    = xv_gui_data_exchange;
+  this->vo_driver.dispose              = xv_dispose;
+  this->vo_driver.redraw_needed        = xv_redraw_needed;
+
+  /*
+   * init properties
+   */
+
+  for (i = 0; i < VO_NUM_PROPERTIES; i++) {
+    this->props[i].value = 0;
+    this->props[i].min   = 0;
+    this->props[i].max   = 0;
+    this->props[i].atom  = XCB_NONE;
+    this->props[i].entry = NULL;
+    this->props[i].this  = this;
+  }
+
+  this->props[VO_PROP_INTERLACED].value      = 0;
+  this->sc.user_ratio                        =
+    this->props[VO_PROP_ASPECT_RATIO].value  = XINE_VO_ASPECT_AUTO;
+  this->props[VO_PROP_ZOOM_X].value          = 100;
+  this->props[VO_PROP_ZOOM_Y].value          = 100;
+
+  /*
+   * check this adaptor's capabilities
+   */
+  this->port_attributes = xine_list_new();
+
+  query_attributes_cookie = xcb_xv_query_port_attributes(this->connection, xv_port);
+  query_attributes_reply = xcb_xv_query_port_attributes_reply(this->connection, query_attributes_cookie, NULL);
+  if(query_attributes_reply) {
+    xcb_xv_attribute_info_iterator_t attribute_it;
+    attribute_it = xcb_xv_query_port_attributes_attributes_iterator(query_attributes_reply);
+
+    for (; attribute_it.rem; xcb_xv_attribute_info_next(&attribute_it)) {
+      if ((attribute_it.data->flags & XCB_XV_ATTRIBUTE_FLAG_SETTABLE) && (attribute_it.data->flags & XCB_XV_ATTRIBUTE_FLAG_GETTABLE)) {
+	/* store initial port attribute value */
+	xv_store_port_attribute(this, xcb_xv_attribute_info_name(attribute_it.data));
+	
+	if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_HUE")) {
+	  if (!strncmp(xcb_xv_adaptor_info_name(adaptor_it.data), "NV", 2)) {
+            xprintf (this->xine, XINE_VERBOSITY_NONE, "video_out_xv: ignoring broken XV_HUE settings on NVidia cards");
+	  } else {
+	    xv_check_capability (this, VO_PROP_HUE, attribute_it.data,
+			         adaptor_it.data->base_id,
+			         NULL, NULL, NULL);
+	  }
+	} else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_SATURATION")) {
+	  xv_check_capability (this, VO_PROP_SATURATION, attribute_it.data,
+			       adaptor_it.data->base_id,
+			       NULL, NULL, NULL);
+
+	} else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_BRIGHTNESS")) {
+	  xv_check_capability (this, VO_PROP_BRIGHTNESS, attribute_it.data,
+			       adaptor_it.data->base_id,
+			       NULL, NULL, NULL);
+
+	} else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_CONTRAST")) {
+	  xv_check_capability (this, VO_PROP_CONTRAST, attribute_it.data,
+			       adaptor_it.data->base_id,
+			       NULL, NULL, NULL);
+
+	} else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_COLORKEY")) {
+	  xv_check_capability (this, VO_PROP_COLORKEY, attribute_it.data,
+			       adaptor_it.data->base_id,
+			       "video.device.xv_colorkey",
+			       _("video overlay colour key"),
+			       _("The colour key is used to tell the graphics card where to "
+				 "overlay the video image. Try different values, if you experience "
+				 "windows becoming transparent."));
+
+	} else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_AUTOPAINT_COLORKEY")) {
+	  xv_check_capability (this, VO_PROP_AUTOPAINT_COLORKEY, attribute_it.data,
+			       adaptor_it.data->base_id,
+			       "video.device.xv_autopaint_colorkey",
+			       _("autopaint colour key"),
+			       _("Make Xv autopaint its colorkey."));
+
+	} else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_FILTER")) {
+	  int xv_filter;
+	  /* This setting is specific to Permedia 2/3 cards. */
+	  xv_filter = config->register_range (config, "video.device.xv_filter", 0,
+					      attribute_it.data->min, attribute_it.data->max,
+					      _("bilinear scaling mode"),
+					      _("Selects the bilinear scaling mode for Permedia cards. "
+						"The individual values are:\n\n"
+						"Permedia 2\n"
+						"0 - disable bilinear filtering\n"
+						"1 - enable bilinear filtering\n\n"
+						"Permedia 3\n"
+						"0 - disable bilinear filtering\n"
+						"1 - horizontal linear filtering\n"
+						"2 - enable full bilinear filtering"),
+					      20, xv_update_XV_FILTER, this);
+	  config->update_num(config,"video.device.xv_filter",xv_filter);
+	} else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_DOUBLE_BUFFER")) {
+	  int xv_double_buffer;
+	  xv_double_buffer = 
+	    config->register_bool (config, "video.device.xv_double_buffer", 1,
+	      _("enable double buffering"),
+	      _("Double buffering will synchronize the update of the video image to the "
+		"repainting of the entire screen (\"vertical retrace\"). This eliminates "
+		"flickering and tearing artifacts, but will use more graphics memory."),
+	      20, xv_update_XV_DOUBLE_BUFFER, this);
+	  config->update_num(config,"video.device.xv_double_buffer",xv_double_buffer);
+	}
+      }
+    }
+    free(query_attributes_reply);
+  }
+  else
+    xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_xv: no port attributes defined.\n");
+  free(query_adaptors_reply);
+
+  /*
+   * check supported image formats
+   */
+
+  list_formats_cookie = xcb_xv_list_image_formats(this->connection, xv_port);
+  list_formats_reply = xcb_xv_list_image_formats_reply(this->connection, list_formats_cookie, NULL);
+
+  format_it = xcb_xv_list_image_formats_format_iterator(list_formats_reply);
+  
+  this->xv_format_yv12 = 0;
+  this->xv_format_yuy2 = 0;
+  
+  for (; format_it.rem; xcb_xv_image_format_info_next(&format_it)) {
+    lprintf ("Xv image format: 0x%x (%4.4s) %s\n",
+	     format_it.data->id, (char*)&format_it.data->id,
+	     (format_it.data->format == XvPacked) ? "packed" : "planar");
+
+    if (format_it.data->id == XINE_IMGFMT_YV12)  {
+      this->xv_format_yv12 = format_it.data->id;
+      this->capabilities |= VO_CAP_YV12;
+      xprintf(this->xine, XINE_VERBOSITY_LOG,
+	      _("video_out_xv: this adaptor supports the yv12 format.\n"));
+    } else if (format_it.data->id == XINE_IMGFMT_YUY2) {
+      this->xv_format_yuy2 = format_it.data->id;
+      this->capabilities |= VO_CAP_YUY2;
+      xprintf(this->xine, XINE_VERBOSITY_LOG, 
+	      _("video_out_xv: this adaptor supports the yuy2 format.\n"));
+    }
+  }
+
+  free(list_formats_reply);
+
+  this->use_pitch_alignment = 
+    config->register_bool (config, "video.device.xv_pitch_alignment", 0,
+			   _("pitch alignment workaround"),
+			   _("Some buggy video drivers need a workaround to function properly."),
+			   10, xv_update_xv_pitch_alignment, this);
+
+  this->deinterlace_method = 
+    config->register_enum (config, "video.output.xv_deinterlace_method", 4,
+			   deinterlace_methods,
+			   _("deinterlace method (deprecated)"),
+			   _("This config setting is deprecated. You should use the new deinterlacing "
+			     "post processing settings instead.\n\n"
+			     "From the old days of analog television, where the even and odd numbered "
+			     "lines of a video frame would be displayed at different times comes the "
+			     "idea to increase motion smoothness by also recording the lines at "
+			     "different times. This is called \"interlacing\". But unfortunately, "
+			     "todays displays show the even and odd numbered lines as one complete frame "
+			     "all at the same time (called \"progressive display\"), which results in "
+			     "ugly frame errors known as comb artifacts. Software deinterlacing is an "
+			     "approach to reduce these artifacts. The individual values are:\n\n"
+			     "none\n"
+			     "Disables software deinterlacing.\n\n"
+			     "bob\n"
+			     "Interpolates between the lines for moving parts of the image.\n\n"
+			     "weave\n"
+			     "Similar to bob, but with a tendency to preserve the full resolution, "
+			     "better for high detail in low movement scenes.\n\n"
+			     "greedy\n"
+			     "Very good adaptive deinterlacer, but needs a lot of CPU power.\n\n"
+			     "onefield\n"
+			     "Always interpolates and reduces vertical resolution.\n\n"
+			     "onefieldxv\n"
+			     "Same as onefield, but does the interpolation in hardware.\n\n"
+			     "linearblend\n"
+			     "Applies a slight vertical blur to remove the comb artifacts. Good results "
+			     "with medium CPU usage."),
+			   10, xv_update_deinterlace, this);
+  this->deinterlace_enabled = 0;
+
+  if(this->use_colorkey==1) {
+    this->xoverlay = xcbosd_create(this->xine, this->connection, this->screen,
+                                   this->window, XCBOSD_COLORKEY);
+    if(this->xoverlay)
+      xcbosd_colorkey(this->xoverlay, this->colorkey, &this->sc);
+  } else {
+    this->xoverlay = xcbosd_create(this->xine, this->connection, this->screen,
+                                   this->window, XCBOSD_SHAPED);
+  }
+
+  if( this->xoverlay )
+    this->capabilities |= VO_CAP_UNSCALED_OVERLAY;
+
+  return &this->vo_driver;
+}
+
+/*
+ * class functions
+ */
+
+static char* get_identifier (video_driver_class_t *this_gen) {
+  return "Xv";
+}
+
+static char* get_description (video_driver_class_t *this_gen) {
+  return _("xine video output plugin using the MIT X video extension");
+}
+
+static void dispose_class (video_driver_class_t *this_gen) {
+  xv_class_t        *this = (xv_class_t *) this_gen;
+  
+  free (this);
+}
+
+static void *init_class (xine_t *xine, void *visual_gen) {
+  xv_class_t        *this = (xv_class_t *) xine_xmalloc (sizeof (xv_class_t));
+
+  this->driver_class.open_plugin     = open_plugin;
+  this->driver_class.get_identifier  = get_identifier;
+  this->driver_class.get_description = get_description;
+  this->driver_class.dispose         = dispose_class;
+
+  this->config                       = xine->config;
+  this->xine                         = xine;
+
+  return this;
+}
+
+static const vo_info_t vo_info_xv = {
+  9,                      /* priority    */
+  XINE_VISUAL_TYPE_XCB    /* visual type */
+};
+
+/*
+ * exported plugin catalog entry
+ */
+
+const plugin_info_t xine_plugin_info[] EXPORTED = {
+  /* type, API, "name", version, special_info, init_function */
+  { PLUGIN_VIDEO_OUT, 21, "xv", XINE_VERSION_CODE, &vo_info_xv, init_class },
+  { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};
+
+#endif
Index: src/video_out/video_out_xshm.c
===================================================================
RCS file: /cvsroot/xine/xine-lib/src/video_out/video_out_xshm.c,v
retrieving revision 1.148
diff -u -B -r1.148 video_out_xshm.c
--- src/video_out/video_out_xshm.c	28 Oct 2006 18:51:08 -0000	1.148
+++ src/video_out/video_out_xshm.c	7 Feb 2007 02:41:42 -0000
@@ -87,7 +87,6 @@
 
   yuv2rgb_t         *yuv2rgb; /* yuv2rgb converter set up for this frame */
   uint8_t           *rgb_dst;
-  int                yuv_stride;
 
 } xshm_frame_t;
 
@@ -105,8 +104,6 @@
   int                use_shm;
   XColor             black;
   
-  int                yuv2rgb_mode;
-  int                yuv2rgb_swap;
   int                yuv2rgb_brightness;
   int                yuv2rgb_contrast;
   int                yuv2rgb_saturation;
@@ -585,7 +582,6 @@
 				 frame->sc.output_width,
 				 frame->sc.output_height,
 				 frame->image->bytes_per_line*2);
-      frame->yuv_stride = frame->image->bytes_per_line*2;
       break;
     case VO_BOTH_FIELDS:
       frame->yuv2rgb->configure (frame->yuv2rgb,
@@ -596,7 +592,6 @@
 				 frame->sc.output_width,
 				 frame->sc.output_height,
 				 frame->image->bytes_per_line);
-      frame->yuv_stride = frame->image->bytes_per_line;
       break;
     }
   }
@@ -1255,8 +1250,6 @@
     return NULL;
   }
   
-  this->yuv2rgb_mode  = mode;
-  this->yuv2rgb_swap  = swapped;
   this->yuv2rgb_brightness = 0;
   this->yuv2rgb_contrast   = 128;
   this->yuv2rgb_saturation = 128;
Index: src/video_out/xcbosd.c
===================================================================
RCS file: src/video_out/xcbosd.c
diff -N src/video_out/xcbosd.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/video_out/xcbosd.c	7 Feb 2007 02:41:42 -0000
@@ -0,0 +1,546 @@
+/* 
+ * Copyright (C) 2003, 2007 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+ *
+ * $Id: xcbosd.c,v 1.15 2005/09/25 00:44:04 miguelfreitas Exp $
+ *
+ * xcbosd.c, use X11 Nonrectangular Window Shape Extension to draw xine OSD
+ *
+ * Nov 2003 - Miguel Freitas
+ * Feb 2007 - ported to xcb by Christoph Pfister
+ *
+ * based on ideas and code of
+ * xosd Copyright (c) 2000 Andre Renaud (andre@ignavus.net)
+ *
+ * colorkey support by Yann Vernier
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+
+#include <assert.h>
+
+#include <netinet/in.h>
+
+#include <xcb/shape.h>
+
+#define LOG_MODULE "xcbosd"
+#define LOG_VERBOSE
+
+/*
+#define LOG
+*/
+
+#include "xine_internal.h"
+#include "xcbosd.h"
+
+struct xcbosd
+{
+  xcb_connection_t *connection;
+  xcb_screen_t *screen;
+  enum xcbosd_mode mode;
+
+  union {
+    struct {
+      xcb_window_t window;
+      xcb_pixmap_t mask_bitmap;
+      xcb_gc_t mask_gc;
+      xcb_gc_t mask_gc_back;
+      int mapped;
+    } shaped;
+    struct {
+      uint32_t colorkey;
+      vo_scale_t *sc;
+    } colorkey;
+  } u;
+  xcb_window_t window;
+  unsigned int depth;
+  xcb_pixmap_t bitmap;
+  xcb_visualid_t visual;
+  xcb_colormap_t cmap;
+
+  xcb_gc_t gc;
+
+  int width;
+  int height;
+  int x;
+  int y;
+  enum {DRAWN, WIPED, UNDEFINED} clean;
+  xine_t *xine;
+};
+
+
+void xcbosd_expose(xcbosd *osd)
+{
+  assert (osd);
+
+  lprintf("expose (state:%d)\n", osd->clean );
+  
+  switch (osd->mode) {
+    case XCBOSD_SHAPED:
+      xcb_shape_mask(osd->connection, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING,
+		     osd->u.shaped.window, 0, 0, osd->u.shaped.mask_bitmap);
+      if( osd->clean==DRAWN ) {
+
+	if( !osd->u.shaped.mapped ) {
+	  unsigned int stack_mode = XCB_STACK_MODE_ABOVE;
+	  xcb_configure_window(osd->connection, osd->u.shaped.window, XCB_CONFIG_WINDOW_STACK_MODE, &stack_mode);
+	  xcb_map_window(osd->connection, osd->u.shaped.window);
+	}
+	osd->u.shaped.mapped = 1;
+    
+	xcb_copy_area(osd->connection, osd->bitmap, osd->u.shaped.window,
+		      osd->gc, 0, 0, 0, 0, osd->width, osd->height);
+      } else {
+	if( osd->u.shaped.mapped )
+	  xcb_unmap_window(osd->connection, osd->u.shaped.window);
+	osd->u.shaped.mapped = 0;
+      }
+      break;
+    case XCBOSD_COLORKEY:
+      if( osd->clean!=UNDEFINED )
+	xcb_copy_area(osd->connection, osd->bitmap, osd->window, osd->gc, 0, 0,
+		      0, 0, osd->width, osd->height);
+  }
+}
+
+
+void xcbosd_resize(xcbosd *osd, int width, int height)
+{
+  assert (osd);
+  assert (width);
+  assert (height);
+  
+  lprintf("resize old:%dx%d new:%dx%d\n", osd->width, osd->height, width, height );
+
+  osd->width = width;
+  osd->height = height;
+
+  xcb_free_pixmap(osd->connection, osd->bitmap);
+  switch(osd->mode) {
+    case XCBOSD_SHAPED: {
+      unsigned int window_config[] = { osd->width, osd->height };
+      xcb_configure_window(osd->connection, osd->u.shaped.window, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, window_config);
+      xcb_free_pixmap(osd->connection, osd->u.shaped.mask_bitmap);
+      osd->u.shaped.mask_bitmap = xcb_generate_id(osd->connection);
+      xcb_create_pixmap(osd->connection, 1, osd->u.shaped.mask_bitmap, osd->u.shaped.window, osd->width, osd->height);
+      osd->bitmap = xcb_generate_id(osd->connection);
+      xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->u.shaped.window, osd->width, osd->height);
+      break;
+      }
+    case XCBOSD_COLORKEY:
+      osd->bitmap = xcb_generate_id(osd->connection);
+      xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->window, osd->width, osd->height);
+      break;
+  }
+  
+  osd->clean = UNDEFINED;
+  xcbosd_clear(osd);
+}
+
+void xcbosd_drawable_changed(xcbosd *osd, xcb_window_t window)
+{
+  xcb_get_geometry_cookie_t get_geometry_cookie;
+  xcb_get_geometry_reply_t *get_geometry_reply;
+
+  assert (osd);
+  
+  lprintf("drawable changed\n");
+
+/*
+  Do I need to recreate the GC's??
+
+  XFreeGC (osd->display, osd->gc);
+  XFreeGC (osd->display, osd->mask_gc);
+  XFreeGC (osd->display, osd->mask_gc_back);
+*/
+  xcb_free_pixmap(osd->connection, osd->bitmap);
+  xcb_free_colormap(osd->connection, osd->cmap);
+
+  /* we need to call XSync(), because otherwise, calling XDestroyWindow()
+     on the parent window could destroy our OSD window twice !! */
+  /* XSync (osd->display, False); FIXME don't think that we need that --pfister */
+
+  osd->window = window;
+  
+  get_geometry_cookie = xcb_get_geometry(osd->connection, osd->window);
+  get_geometry_reply = xcb_get_geometry_reply(osd->connection, get_geometry_cookie, NULL);
+  osd->depth = get_geometry_reply->depth;
+  osd->width = get_geometry_reply->width;
+  osd->height = get_geometry_reply->height;
+  free(get_geometry_reply);
+  
+  assert(osd->width);
+  assert(osd->height);
+  
+  switch(osd->mode) {
+    case XCBOSD_SHAPED: {
+      xcb_free_pixmap(osd->connection, osd->u.shaped.mask_bitmap);
+      xcb_destroy_window(osd->connection, osd->u.shaped.window);
+
+      unsigned int window_params[] = { osd->screen->black_pixel, 1, XCB_EVENT_MASK_EXPOSURE };
+      osd->u.shaped.window = xcb_generate_id(osd->connection);
+      xcb_create_window(osd->connection, XCB_COPY_FROM_PARENT, osd->u.shaped.window,
+			osd->window, 0, 0, osd->width, osd->height, 0, XCB_COPY_FROM_PARENT,
+			XCB_COPY_FROM_PARENT, XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
+			window_params);
+
+      osd->u.shaped.mapped = 0;
+
+      osd->u.shaped.mask_bitmap = xcb_generate_id(osd->connection);
+      xcb_create_pixmap(osd->connection, 1, osd->u.shaped.mask_bitmap, osd->u.shaped.window, osd->width, osd->height);
+
+      osd->bitmap = xcb_generate_id(osd->connection);
+      xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->u.shaped.window, osd->width, osd->height);
+
+      osd->cmap = xcb_generate_id(osd->connection);
+      xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->u.shaped.window, osd->visual);
+      break;
+      }
+    case XCBOSD_COLORKEY:
+      osd->bitmap = xcb_generate_id(osd->connection);
+      xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->window, osd->width, osd->height);
+      osd->cmap = xcb_generate_id(osd->connection);
+      xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->window, osd->visual);
+
+      break;
+  }
+  
+  osd->clean = UNDEFINED;
+  /* do not xcbosd_clear() here: osd->u.colorkey.sc has not being updated yet */
+}
+
+xcbosd *xcbosd_create(xine_t *xine, xcb_connection_t *connection, xcb_screen_t *screen, xcb_window_t window, enum xcbosd_mode mode)
+{
+  xcbosd *osd;
+
+  xcb_get_geometry_cookie_t get_geometry_cookie;
+  xcb_get_geometry_reply_t *get_geometry_reply;
+
+  xcb_void_cookie_t generic_cookie;
+  xcb_generic_error_t *generic_error;
+
+  osd = xine_xmalloc (sizeof (xcbosd));
+  if (!osd)
+    return NULL;
+
+  osd->mode = mode;
+  osd->xine = xine;
+  osd->connection = connection;
+  osd->screen = screen;
+  osd->window = window;
+
+  osd->visual = osd->screen->root_visual;
+  
+  get_geometry_cookie = xcb_get_geometry(osd->connection, osd->window);
+  get_geometry_reply = xcb_get_geometry_reply(osd->connection, get_geometry_cookie, NULL);
+  osd->depth = get_geometry_reply->depth;
+  osd->width = get_geometry_reply->width;
+  osd->height = get_geometry_reply->height;
+  free(get_geometry_reply);
+  
+  assert(osd->width);
+  assert(osd->height);
+
+  switch (mode) {
+    case XCBOSD_SHAPED: {
+      const xcb_query_extension_reply_t *query_extension_reply = xcb_get_extension_data(osd->connection, &xcb_shape_id);
+
+      if (!query_extension_reply || !query_extension_reply->present) {
+	xprintf(osd->xine, XINE_VERBOSITY_LOG, _("x11osd: XShape extension not available. unscaled overlay disabled.\n"));
+	goto error2;
+      }
+
+      unsigned int window_params[] = { osd->screen->black_pixel, 1, XCB_EVENT_MASK_EXPOSURE };
+      osd->u.shaped.window = xcb_generate_id(osd->connection);
+      generic_cookie = xcb_create_window_checked(osd->connection, XCB_COPY_FROM_PARENT, osd->u.shaped.window,
+			osd->window, 0, 0, osd->width, osd->height, 0, XCB_COPY_FROM_PARENT,
+			XCB_COPY_FROM_PARENT, XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
+			window_params);
+      generic_error = xcb_request_check(osd->connection, generic_cookie);
+
+      if (generic_error != NULL) {
+	xprintf(osd->xine, XINE_VERBOSITY_LOG, _("x11osd: error creating window. unscaled overlay disabled.\n"));
+	free(generic_error);
+	goto error_window;
+      }
+
+      osd->u.shaped.mask_bitmap = xcb_generate_id(osd->connection);
+      generic_cookie = xcb_create_pixmap_checked(osd->connection, 1, osd->u.shaped.mask_bitmap, osd->u.shaped.window, osd->width, osd->height);
+      generic_error = xcb_request_check(osd->connection, generic_cookie);
+
+      if (generic_error != NULL) {
+	xprintf(osd->xine, XINE_VERBOSITY_LOG, _("x11osd: error creating pixmap. unscaled overlay disabled.\n"));
+	free(generic_error);
+	goto error_aftermaskbitmap;
+      }
+
+      osd->bitmap = xcb_generate_id(osd->connection);
+      xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->u.shaped.window, osd->width, osd->height);
+      osd->gc = xcb_generate_id(osd->connection);
+      xcb_create_gc(osd->connection, osd->gc, osd->u.shaped.window, 0, NULL);
+
+      osd->u.shaped.mask_gc = xcb_generate_id(osd->connection);
+      xcb_create_gc(osd->connection, osd->u.shaped.mask_gc, osd->u.shaped.mask_bitmap, XCB_GC_FOREGROUND, &osd->screen->white_pixel);
+
+      osd->u.shaped.mask_gc_back = xcb_generate_id(osd->connection);
+      xcb_create_gc(osd->connection, osd->u.shaped.mask_gc_back, osd->u.shaped.mask_bitmap, XCB_GC_FOREGROUND, &osd->screen->black_pixel);
+
+      osd->u.shaped.mapped = 0;
+      osd->cmap = xcb_generate_id(osd->connection);
+      xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->u.shaped.window, osd->visual);
+      break;
+      }
+    case XCBOSD_COLORKEY:
+      osd->bitmap = xcb_generate_id(osd->connection);
+      xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->window, osd->width, osd->height);
+      osd->gc = xcb_generate_id(osd->connection);
+      xcb_create_gc(osd->connection, osd->gc, osd->window, 0, NULL);
+      osd->cmap = xcb_generate_id(osd->connection);
+      xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->window, osd->visual);
+      /* FIXME: the expose event doesn't seem to happen? */
+      /*XSelectInput (osd->display, osd->window, ExposureMask);*/
+      break;
+    default:
+      goto error2;
+  }
+
+  osd->clean = UNDEFINED;
+  xcbosd_expose(osd);
+
+  xprintf(osd->xine, XINE_VERBOSITY_DEBUG, 
+    _("x11osd: unscaled overlay created (%s mode).\n"), 
+    (mode==XCBOSD_SHAPED) ? "XShape" : "Colorkey" );
+
+  return osd;
+
+/*
+  XFreeGC (osd->display, osd->gc);
+  XFreeGC (osd->display, osd->mask_gc);
+  XFreeGC (osd->display, osd->mask_gc_back);
+*/
+
+error_aftermaskbitmap:
+  if(mode==XCBOSD_SHAPED)
+    xcb_free_pixmap(osd->connection, osd->u.shaped.mask_bitmap);
+error_window:
+  if(mode==XCBOSD_SHAPED)
+    xcb_destroy_window(osd->connection, osd->u.shaped.window);
+error2:
+  free (osd);
+  return NULL;
+}
+
+void xcbosd_colorkey(xcbosd *osd, uint32_t colorkey, vo_scale_t *scaling)
+{
+  assert (osd);
+  assert (osd->mode==XCBOSD_COLORKEY);
+
+  osd->u.colorkey.colorkey=colorkey;
+  osd->u.colorkey.sc=scaling;
+  osd->clean = UNDEFINED;
+  xcbosd_clear(osd);
+  xcbosd_expose(osd);
+}
+
+void xcbosd_destroy(xcbosd *osd)
+{
+
+  assert (osd);
+
+  xcb_free_gc(osd->connection, osd->gc);
+  xcb_free_pixmap(osd->connection, osd->bitmap);
+  xcb_free_colormap(osd->connection, osd->cmap);
+  if(osd->mode==XCBOSD_SHAPED) {
+    xcb_free_gc(osd->connection, osd->u.shaped.mask_gc);
+    xcb_free_gc(osd->connection, osd->u.shaped.mask_gc_back);
+    xcb_free_pixmap(osd->connection, osd->u.shaped.mask_bitmap);
+    xcb_destroy_window(osd->connection, osd->u.shaped.window);
+  }
+
+  free (osd);
+}
+
+void xcbosd_clear(xcbosd *osd)
+{
+  int i;
+  
+  lprintf("clear (state:%d)\n", osd->clean );
+  
+  if( osd->clean != WIPED )
+    switch (osd->mode) {
+      case XCBOSD_SHAPED: {
+	xcb_rectangle_t rectangle = { 0, 0, osd->width, osd->height };
+	xcb_poly_fill_rectangle(osd->connection, osd->u.shaped.mask_bitmap, osd->u.shaped.mask_gc_back, 1, &rectangle);
+	break;
+	}
+      case XCBOSD_COLORKEY:
+	xcb_change_gc(osd->connection, osd->gc, XCB_GC_FOREGROUND, &osd->u.colorkey.colorkey);
+	if(osd->u.colorkey.sc) {
+	  xcb_rectangle_t rectangle = { osd->u.colorkey.sc->output_xoffset, osd->u.colorkey.sc->output_yoffset,
+					osd->u.colorkey.sc->output_width, osd->u.colorkey.sc->output_height };
+	  xcb_poly_fill_rectangle(osd->connection, osd->bitmap, osd->gc, 1, &rectangle);
+	  xcb_change_gc(osd->connection, osd->gc, XCB_GC_FOREGROUND, &osd->screen->black_pixel);
+
+	  xcb_rectangle_t rects[4];
+	  int rects_count = 0;
+
+          for( i = 0; i < 4; i++ ) {
+            if( osd->u.colorkey.sc->border[i].w && osd->u.colorkey.sc->border[i].h ) {
+	      rects[rects_count].x = osd->u.colorkey.sc->border[i].x;
+	      rects[rects_count].y = osd->u.colorkey.sc->border[i].y;
+	      rects[rects_count].width = osd->u.colorkey.sc->border[i].w;
+	      rects[rects_count].height = osd->u.colorkey.sc->border[i].h;
+	      rects_count++;
+            }
+
+          if (rects_count > 0)
+	    xcb_poly_fill_rectangle(osd->connection, osd->bitmap, osd->gc, rects_count, rects);
+          }
+	} else {
+	  xcb_rectangle_t rectangle = { 0, 0, osd->width, osd->height };
+	  xcb_poly_fill_rectangle(osd->connection, osd->bitmap, osd->gc, 1, &rectangle);
+	}
+	break;
+    }
+  osd->clean = WIPED;
+}
+
+#define TRANSPARENT 0xffffffff
+
+#define saturate(n, l, u) ((n) < (l) ? (l) : ((n) > (u) ? (u) : (n)))
+
+void xcbosd_blend(xcbosd *osd, vo_overlay_t *overlay)
+{
+  xcb_alloc_color_cookie_t alloc_color_cookie;
+  xcb_alloc_color_reply_t *alloc_color_reply;
+
+  if (osd->clean==UNDEFINED)
+    xcbosd_clear(osd);	/* Workaround. Colorkey mode needs sc data before the clear. */
+  
+  if (overlay->rle) {
+    int i, x, y, len, width;
+    int use_clip_palette, max_palette_colour[2];
+    uint32_t palette[2][OVL_PALETTE_SIZE];
+
+    max_palette_colour[0] = -1;
+    max_palette_colour[1] = -1;
+
+    for (i=0, x=0, y=0; i<overlay->num_rle; i++) {
+      len = overlay->rle[i].len;
+
+      while (len > 0) {
+        use_clip_palette = 0;
+        if (len > overlay->width) {
+          width = overlay->width;
+          len -= overlay->width;
+        }
+        else {
+          width = len;
+          len = 0;
+        }
+        if ((y >= overlay->hili_top) && (y <= overlay->hili_bottom) && (x <= overlay->hili_right)) {
+          if ((x < overlay->hili_left) && (x + width - 1 >= overlay->hili_left)) {
+            width -= overlay->hili_left - x;
+            len += overlay->hili_left - x;
+          }
+          else if (x > overlay->hili_left)  {
+            use_clip_palette = 1;
+            if (x + width - 1 > overlay->hili_right) {
+              width -= overlay->hili_right - x;
+              len += overlay->hili_right - x;
+            } 
+          }
+        }
+
+        if (overlay->rle[i].color > max_palette_colour[use_clip_palette]) {
+          int j;
+          clut_t *src_clut;
+          uint8_t *src_trans;
+          
+          if (use_clip_palette) {
+            src_clut = (clut_t *)&overlay->hili_color;
+            src_trans = (uint8_t *)&overlay->hili_trans;
+          }
+          else {
+            src_clut = (clut_t *)&overlay->color;
+            src_trans = (uint8_t *)&overlay->trans;
+          }
+          for (j=max_palette_colour[use_clip_palette]+1; j<=overlay->rle[i].color; j++) {
+            if (src_trans[j]) {
+              if (1) {
+                int red, green, blue;
+                int y, u, v, r, g, b;
+
+                y = saturate(src_clut[j].y, 16, 235);
+                u = saturate(src_clut[j].cb, 16, 240);
+                v = saturate(src_clut[j].cr, 16, 240);
+                y = (9 * y) / 8;
+                r = y + (25 * v) / 16 - 218;
+                red = (65536 * saturate(r, 0, 255)) / 256;
+                g = y + (-13 * v) / 16 + (-25 * u) / 64 + 136;
+                green = (65536 * saturate(g, 0, 255)) / 256;
+                b = y + 2 * u - 274;
+                blue = (65536 * saturate(b, 0, 255)) / 256;
+
+                alloc_color_cookie = xcb_alloc_color(osd->connection, osd->cmap, red, green, blue);
+                alloc_color_reply = xcb_alloc_color_reply(osd->connection, alloc_color_cookie, NULL);
+
+                palette[use_clip_palette][j] = alloc_color_reply->pixel;
+                free(alloc_color_reply);
+              }
+              else {
+                if (src_clut[j].y > 127) {
+                  palette[use_clip_palette][j] = osd->screen->white_pixel;
+                }
+                else {
+                  palette[use_clip_palette][j] = osd->screen->black_pixel;
+                }
+              }
+            }
+            else {
+              palette[use_clip_palette][j] = TRANSPARENT;
+            }
+          }
+          max_palette_colour[use_clip_palette] = overlay->rle[i].color;
+        }
+
+        if(palette[use_clip_palette][overlay->rle[i].color] != TRANSPARENT) {
+          xcb_change_gc(osd->connection, osd->gc, XCB_GC_FOREGROUND, &palette[use_clip_palette][overlay->rle[i].color]);
+          xcb_rectangle_t rectangle = { overlay->x + x, overlay->y + y, width, 1 };
+          xcb_poly_fill_rectangle(osd->connection, osd->bitmap, osd->gc, 1, &rectangle);
+	  if(osd->mode==XCBOSD_SHAPED)
+            xcb_poly_fill_rectangle(osd->connection, osd->u.shaped.mask_bitmap, osd->u.shaped.mask_gc, 1, &rectangle);
+        }
+
+        x += width;
+        if (x == overlay->width) {
+          x = 0;
+          y++;
+        }
+      }
+    }
+    osd->clean = DRAWN;
+  }
+}
+
Index: src/video_out/xcbosd.h
===================================================================
RCS file: src/video_out/xcbosd.h
diff -N src/video_out/xcbosd.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/video_out/xcbosd.h	7 Feb 2007 02:41:42 -0000
@@ -0,0 +1,55 @@
+/* 
+ * Copyright (C) 2003, 2007 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+ *
+ * $Id: xcbosd.h,v 1.4 2004/04/10 15:31:10 miguelfreitas Exp $
+ *
+ * xcbosd.h, use X11 Nonrectangular Window Shape Extension to draw xine OSD
+ *
+ * Nov 2003 - Miguel Freitas
+ * Feb 2007 - ported to xcb by Christoph Pfister
+ *
+ * based on ideas and code of
+ * xosd Copyright (c) 2000 Andre Renaud (andre@ignavus.net)
+ */
+
+#ifndef XCBOSD_H
+#define XCBOSD_H
+
+#include "vo_scale.h"
+
+typedef struct xcbosd xcbosd;
+enum xcbosd_mode {XCBOSD_SHAPED, XCBOSD_COLORKEY};
+
+xcbosd *xcbosd_create(xine_t *xine, xcb_connection_t *connection, xcb_screen_t *screen, xcb_window_t window, enum xcbosd_mode mode);
+
+void xcbosd_colorkey(xcbosd *osd, uint32_t colorkey, vo_scale_t *scaling);
+
+void xcbosd_destroy(xcbosd *osd);
+
+void xcbosd_expose(xcbosd *osd);
+
+void xcbosd_resize(xcbosd *osd, int width, int height);
+
+void xcbosd_drawable_changed(xcbosd *osd, xcb_window_t window);
+
+void xcbosd_clear(xcbosd *osd);
+
+void xcbosd_blend(xcbosd *osd, vo_overlay_t *overlay);
+
+#endif
