Magellan Linux

Annotation of /trunk/xine-lib/patches/xine-lib-1.1.4-xcb.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 153 - (hide annotations) (download)
Tue May 8 20:52:56 2007 UTC (17 years, 1 month ago) by niro
File size: 124995 byte(s)
-import

1 niro 153 ? 32bit
2     ? default
3     ? enterprise
4     ? prakesh
5     Index: configure.ac
6     ===================================================================
7     RCS file: /cvsroot/xine/xine-lib/configure.ac,v
8     retrieving revision 1.459
9     diff -u -B -r1.459 configure.ac
10     --- configure.ac 28 Jan 2007 23:48:29 -0000 1.459
11     +++ configure.ac 7 Feb 2007 02:41:31 -0000
12     @@ -894,6 +894,46 @@
13    
14    
15     dnl ---------------------------------------------
16     +dnl Check for xcb
17     +dnl ---------------------------------------------
18     +AC_ARG_WITH([xcb], AC_HELP_STRING([--without-xcb], [Doesn't build XCB video out plugins]))
19     +
20     +if test "x$with_xcb" != "xno"; then
21     + PKG_CHECK_MODULES([XCB], [xcb-shape >= 1.0], [have_xcb="yes"], [have_xcb="no"])
22     +fi
23     +
24     +AC_SUBST(XCB_CFLAGS)
25     +AC_SUBST(XCB_LIBS)
26     +AM_CONDITIONAL(HAVE_XCB, test "x$have_xcb" = "xyes" )
27     +
28     +
29     +dnl ---------------------------------------------
30     +dnl Check for xcb-shm
31     +dnl ---------------------------------------------
32     +
33     +if test "x$have_xcb" = "xyes"; then
34     + PKG_CHECK_MODULES([XCBSHM], [xcb-shm], [have_xcbshm="yes"], [have_xcbshm="no"])
35     +fi
36     +
37     +AC_SUBST(XCBSHM_CFLAGS)
38     +AC_SUBST(XCBSHM_LIBS)
39     +AM_CONDITIONAL(HAVE_XCBSHM, test "x$have_xcbshm" = "xyes" )
40     +
41     +
42     +dnl ---------------------------------------------
43     +dnl Check for xcb-xv
44     +dnl ---------------------------------------------
45     +
46     +if test "x$have_xcb" = "xyes"; then
47     + PKG_CHECK_MODULES([XCBXV], [xcb-xv], [have_xcbxv="yes"], [have_xcbxv="no"])
48     +fi
49     +
50     +AC_SUBST(XCBXV_CFLAGS)
51     +AC_SUBST(XCBXV_LIBS)
52     +AM_CONDITIONAL(HAVE_XCBXV, test "x$have_xcbxv" = "xyes" )
53     +
54     +
55     +dnl ---------------------------------------------
56     dnl Checks for Xinerama extension
57     dnl ---------------------------------------------
58    
59     @@ -2959,6 +2999,16 @@
60     fi
61     fi
62     fi
63     +if test "x$have_xcb" = "xyes"; then
64     + dnl xcb-shm
65     + if test "x$have_xcbshm" = "xyes"; then
66     + echo " - xcb-shm (X shared memory using XCB)"
67     + fi
68     + dnl xcb-xv
69     + if test "x$have_xcbxv" = "xyes"; then
70     + echo " - xcb-xv (XVideo using XCB)"
71     + fi
72     +fi
73     if test "x$no_aalib" != "xyes"; then
74     echo " - aa (Ascii ART)"
75     fi
76     Index: include/xine.h.in
77     ===================================================================
78     RCS file: /cvsroot/xine/xine-lib/include/xine.h.in,v
79     retrieving revision 1.162
80     diff -u -B -r1.162 xine.h.in
81     --- include/xine.h.in 21 Dec 2006 00:09:18 -0000 1.162
82     +++ include/xine.h.in 7 Feb 2007 02:41:33 -0000
83     @@ -176,6 +176,7 @@
84     #define XINE_VISUAL_TYPE_DIRECTX 7 /* used by the win32/msvc port */
85     #define XINE_VISUAL_TYPE_CACA 8
86     #define XINE_VISUAL_TYPE_MACOSX 9
87     +#define XINE_VISUAL_TYPE_XCB 11
88    
89     /*
90     * free all resources, close all plugins, close engine.
91     @@ -1192,6 +1193,82 @@
92     } x11_visual_t;
93    
94     /*
95     + * this is the visual data struct any xcb gui
96     + * must supply to the xine_open_video_driver call
97     + * ("data" parameter)
98     + */
99     +typedef struct {
100     +
101     + /* some information about the display */
102     + void *connection; /* xcb_connection_t */
103     + void *screen; /* xcb_screen_t */
104     +
105     + /* window to display the video in / on */
106     + unsigned int window; /* xcb_window_t */
107     +
108     + void *user_data;
109     +
110     + /*
111     + * dest size callback
112     + *
113     + * this will be called by the video driver to find out
114     + * how big the video output area size will be for a
115     + * given video size. The ui should _not_ adjust it's
116     + * video out area, just do some calculations and return
117     + * the size. This will be called for every frame, ui
118     + * implementation should be fast.
119     + * dest_pixel_aspect should be set to the used display pixel aspect.
120     + * NOTE: Semantics has changed: video_width and video_height
121     + * are no longer pixel aspect corrected. Get the old semantics
122     + * in the UI with
123     + * *dest_pixel_aspect = display_pixel_aspect;
124     + * if (video_pixel_aspect >= display_pixel_aspect)
125     + * video_width = video_width * video_pixel_aspect / display_pixel_aspect + .5;
126     + * else
127     + * video_height = video_height * display_pixel_aspect / video_pixel_aspect + .5;
128     + */
129     + void (*dest_size_cb) (void *user_data,
130     + int video_width, int video_height,
131     + double video_pixel_aspect,
132     + int *dest_width, int *dest_height,
133     + double *dest_pixel_aspect);
134     +
135     + /*
136     + * frame output callback
137     + *
138     + * this will be called by the video driver for every frame
139     + * it's about to draw. ui can adapt it's size if necessary
140     + * here.
141     + * note: the ui doesn't have to adjust itself to this
142     + * size, this is just to be taken as a hint.
143     + * ui must return the actual size of the video output
144     + * area and the video output driver will do it's best
145     + * to adjust the video frames to that size (while
146     + * preserving aspect ratio and stuff).
147     + * dest_x, dest_y: offset inside window
148     + * dest_width, dest_height: available drawing space
149     + * dest_pixel_aspect: display pixel aspect
150     + * win_x, win_y: window absolute screen position
151     + * NOTE: Semantics has changed: video_width and video_height
152     + * are no longer pixel aspect corrected. Get the old semantics
153     + * in the UI with
154     + * *dest_pixel_aspect = display_pixel_aspect;
155     + * if (video_pixel_aspect >= display_pixel_aspect)
156     + * video_width = video_width * video_pixel_aspect / display_pixel_aspect + .5;
157     + * else
158     + * video_height = video_height * display_pixel_aspect / video_pixel_aspect + .5;
159     + */
160     + void (*frame_output_cb) (void *user_data,
161     + int video_width, int video_height,
162     + double video_pixel_aspect,
163     + int *dest_x, int *dest_y,
164     + int *dest_width, int *dest_height,
165     + double *dest_pixel_aspect,
166     + int *win_x, int *win_y);
167     +
168     +} xcb_visual_t;
169     +
170     +/*
171     * this is the visual data struct any fb gui
172     * may supply to the xine_open_video_driver call
173     * ("data" parameter) to get frame_output_cd calls
174     Index: src/video_out/Makefile.am
175     ===================================================================
176     RCS file: /cvsroot/xine/xine-lib/src/video_out/Makefile.am,v
177     retrieving revision 1.128
178     diff -u -B -r1.128 Makefile.am
179     --- src/video_out/Makefile.am 28 Jan 2007 17:35:01 -0000 1.128
180     +++ src/video_out/Makefile.am 7 Feb 2007 02:41:36 -0000
181     @@ -37,6 +37,16 @@
182     endif
183     endif
184    
185     +if HAVE_XCB
186     +XCBOSD = xcbosd.c
187     +if HAVE_XCBSHM
188     +xcbshm_module = xineplug_vo_out_xcbshm.la
189     +endif
190     +if HAVE_XCBXV
191     +xcbxv_module = xineplug_vo_out_xcbxv.la
192     +endif
193     +endif
194     +
195     if HAVE_VIDIX
196     vidix_module = xineplug_vo_out_vidix.la
197     endif
198     @@ -86,8 +96,20 @@
199     $(caca_module) \
200     $(macosx_module) \
201     $(xxmc_module) \
202     + $(xcbshm_module) \
203     + $(xcbxv_module) \
204     xineplug_vo_out_none.la
205    
206     +xineplug_vo_out_xcbshm_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_xcbshm.c $(XCBOSD)
207     +xineplug_vo_out_xcbshm_la_LIBADD = $(MLIB_LIBS) $(XINE_LIB) $(THREAD_LIBS) $(XCB_LIBS) $(XCBSHM_LIBS)
208     +xineplug_vo_out_xcbshm_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) $(XCB_CFLAGS) $(XCBSHM_CFLAGS)
209     +xineplug_vo_out_xcbshm_la_LDFLAGS = -avoid-version -module
210     +
211     +xineplug_vo_out_xcbxv_la_SOURCES = deinterlace.c video_out_xcbxv.c $(XCBOSD)
212     +xineplug_vo_out_xcbxv_la_LIBADD = $(XINE_LIB) $(THREAD_LIBS) $(XCBXV_LIBS) $(XCB_LIBS)
213     +xineplug_vo_out_xcbxv_la_CFLAGS = $(VISIBILITY_FLAG) $(XCB_CFLAGS) $(XCBXV_CFLAGS)
214     +xineplug_vo_out_xcbxv_la_LDFLAGS = -avoid-version -module
215     +
216     xineplug_vo_out_xshm_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \
217     video_out_xshm.c $(X11OSD)
218     xineplug_vo_out_xshm_la_LIBADD = $(MLIB_LIBS) $(X_LIBS) -lXext $(X_PRE_LIBS) -lX11 $(XINE_LIB) $(THREAD_LIBS)
219     @@ -192,4 +214,4 @@
220     -Wl,-framework -Wl,Cocoa -framework Cocoa -framework OpenGL
221    
222     noinst_HEADERS = deinterlace.h video_out_syncfb.h \
223     - yuv2rgb.h x11osd.h
224     + yuv2rgb.h x11osd.h xcbosd.h
225     Index: src/video_out/video_out_xcbshm.c
226     ===================================================================
227     RCS file: src/video_out/video_out_xcbshm.c
228     diff -N src/video_out/video_out_xcbshm.c
229     --- /dev/null 1 Jan 1970 00:00:00 -0000
230     +++ src/video_out/video_out_xcbshm.c 7 Feb 2007 02:41:40 -0000
231     @@ -0,0 +1,1274 @@
232     +/*
233     + * Copyright (C) 2000-2003, 2007 the xine project
234     + *
235     + * This file is part of xine, a free video player.
236     + *
237     + * xine is free software; you can redistribute it and/or modify
238     + * it under the terms of the GNU General Public License as published by
239     + * the Free Software Foundation; either version 2 of the License, or
240     + * (at your option) any later version.
241     + *
242     + * xine is distributed in the hope that it will be useful,
243     + * but WITHOUT ANY WARRANTY; without even the implied warranty of
244     + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
245     + * GNU General Public License for more details.
246     + *
247     + * You should have received a copy of the GNU General Public License
248     + * along with this program; if not, write to the Free Software
249     + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
250     + *
251     + * $Id: xine-lib-1.1.4-xcb.patch,v 1.1 2007-05-08 20:43:46 niro Exp $
252     + *
253     + * video_out_xcbshm.c, X11 shared memory extension interface for xine
254     + *
255     + * based on mpeg2dec code from
256     + * Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
257     + *
258     + * xine-specific code by Guenter Bartsch <bartscgr@studbox.uni-stuttgart.de>
259     + *
260     + * ported to xcb by Christoph Pfister - Feb 2007
261     + */
262     +
263     +#ifdef HAVE_CONFIG_H
264     +#include "config.h"
265     +#endif
266     +
267     +#include <stdio.h>
268     +#include <stdlib.h>
269     +#include <string.h>
270     +#include <math.h>
271     +
272     +#include "xine.h"
273     +#include "video_out.h"
274     +
275     +#include <errno.h>
276     +
277     +#include <xcb/shm.h>
278     +
279     +#include <sys/ipc.h>
280     +#include <sys/shm.h>
281     +#include <sys/time.h>
282     +
283     +#include <pthread.h>
284     +#include <netinet/in.h>
285     +
286     +#define LOG_MODULE "video_out_xcbshm"
287     +#define LOG_VERBOSE
288     +/*
289     +#define LOG
290     +*/
291     +
292     +#include "xine_internal.h"
293     +#include "yuv2rgb.h"
294     +#include "xineutils.h"
295     +#include "vo_scale.h"
296     +#include "xcbosd.h"
297     +
298     +typedef struct {
299     + vo_frame_t vo_frame;
300     +
301     + /* frame properties as delivered by the decoder: */
302     + /* obs: for width/height use vo_scale_t struct */
303     + int format;
304     + int flags;
305     +
306     + vo_scale_t sc;
307     +
308     + uint8_t *image;
309     + int bytes_per_line;
310     + xcb_shm_seg_t shmseg;
311     +
312     + uint8_t *chunk[3]; /* mem alloc by xmalloc_aligned */
313     +
314     + yuv2rgb_t *yuv2rgb; /* yuv2rgb converter set up for this frame */
315     + uint8_t *rgb_dst;
316     +
317     +} xshm_frame_t;
318     +
319     +typedef struct {
320     +
321     + vo_driver_t vo_driver;
322     +
323     + /* xcb / shm related stuff */
324     + xcb_connection_t *connection;
325     + xcb_screen_t *screen;
326     + xcb_window_t window;
327     + xcb_gcontext_t gc;
328     + int depth;
329     + int bpp;
330     + int scanline_pad;
331     + int use_shm;
332     +
333     + int yuv2rgb_brightness;
334     + int yuv2rgb_contrast;
335     + int yuv2rgb_saturation;
336     + uint8_t *yuv2rgb_cmap;
337     + yuv2rgb_factory_t *yuv2rgb_factory;
338     +
339     + vo_scale_t sc;
340     +
341     + xshm_frame_t *cur_frame;
342     + xcbosd *xoverlay;
343     + int ovl_changed;
344     +
345     + xine_t *xine;
346     +
347     + alphablend_t alphablend_extra_data;
348     +
349     + pthread_mutex_t main_mutex;
350     +
351     +} xshm_driver_t;
352     +
353     +typedef struct {
354     + video_driver_class_t driver_class;
355     +
356     + config_values_t *config;
357     + xine_t *xine;
358     +} xshm_class_t;
359     +
360     +
361     +/*
362     + * allocate an XImage, try XShm first but fall back to
363     + * plain X11 if XShm should fail
364     + */
365     +static void create_ximage(xshm_driver_t *this, xshm_frame_t *frame, int width, int height)
366     +{
367     + frame->bytes_per_line = ((this->bpp * width + this->scanline_pad - 1) &
368     + (~(this->scanline_pad - 1))) >> 3;
369     +
370     + if (this->use_shm) {
371     + int shmid;
372     + xcb_void_cookie_t shm_attach_cookie;
373     + xcb_generic_error_t *generic_error;
374     +
375     + /*
376     + * try shm
377     + */
378     +
379     + shmid = shmget(IPC_PRIVATE, frame->bytes_per_line * height, IPC_CREAT | 0777);
380     +
381     + if (shmid < 0) {
382     + xprintf(this->xine, XINE_VERBOSITY_LOG,
383     + _("video_out_xshm: %s: allocating image\n"
384     + "video_out_xshm: => not using MIT Shared Memory extension.\n"), strerror(errno));
385     + goto shm_fail1;
386     + }
387     +
388     + frame->image = shmat(shmid, 0, 0);
389     +
390     + if (frame->image == ((void *) -1)) {
391     + xprintf(this->xine, XINE_VERBOSITY_LOG,
392     + _("video_out_xshm: shared memory error (address error) when allocating image \n"
393     + "video_out_xshm: => not using MIT Shared Memory extension.\n"));
394     + goto shm_fail2;
395     + }
396     +
397     + frame->shmseg = xcb_generate_id(this->connection);
398     + shm_attach_cookie = xcb_shm_attach_checked(this->connection, frame->shmseg, shmid, 0);
399     + generic_error = xcb_request_check(this->connection, shm_attach_cookie);
400     +
401     + if (generic_error != NULL) {
402     + xprintf(this->xine, XINE_VERBOSITY_LOG,
403     + _("video_out_xshm: x11 error during shared memory XImage creation\n"
404     + "video_out_xshm: => not using MIT Shared Memory extension.\n"));
405     + free(generic_error);
406     + goto shm_fail3;
407     + }
408     +
409     + /*
410     + * Now that the Xserver has learned about and attached to the
411     + * shared memory segment, delete it. It's actually deleted by
412     + * the kernel when all users of that segment have detached from
413     + * it. Gives an automatic shared memory cleanup in case we crash.
414     + */
415     +
416     + shmctl(shmid, IPC_RMID, 0);
417     +
418     + return;
419     +
420     + shm_fail3:
421     + frame->shmseg = 0;
422     + shmdt(frame->image);
423     + shm_fail2:
424     + shmctl(shmid, IPC_RMID, 0);
425     + shm_fail1:
426     + this->use_shm = 0;
427     + }
428     +
429     + /*
430     + * fall back to plain X11 if necessary
431     + */
432     +
433     + frame->image = malloc(frame->bytes_per_line * height);
434     +}
435     +
436     +static void dispose_ximage(xshm_driver_t *this, xshm_frame_t *frame)
437     +{
438     + if (frame->shmseg) {
439     + xcb_shm_detach(this->connection, frame->shmseg);
440     + frame->shmseg = 0;
441     + shmdt(frame->image);
442     + } else
443     + free(frame->image);
444     + frame->image = NULL;
445     +}
446     +
447     +
448     +/*
449     + * and now, the driver functions
450     + */
451     +
452     +static uint32_t xshm_get_capabilities (vo_driver_t *this_gen) {
453     + xshm_driver_t *this = (xshm_driver_t *) this_gen;
454     + uint32_t capabilities = VO_CAP_YV12 | VO_CAP_YUY2;
455     +
456     + if( this->xoverlay )
457     + capabilities |= VO_CAP_UNSCALED_OVERLAY;
458     +
459     + return capabilities;
460     +}
461     +
462     +static void xshm_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) {
463     + xshm_frame_t *frame = (xshm_frame_t *) vo_img ;
464     + /*xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; */
465     +
466     + vo_img->proc_called = 1;
467     +
468     + if( frame->vo_frame.crop_left || frame->vo_frame.crop_top ||
469     + frame->vo_frame.crop_right || frame->vo_frame.crop_bottom )
470     + {
471     + /* we don't support crop, so don't even waste cpu cycles.
472     + * cropping will be performed by video_out.c
473     + */
474     + return;
475     + }
476     +
477     + lprintf ("copy... (format %d)\n", frame->format);
478     +
479     + if (frame->format == XINE_IMGFMT_YV12)
480     + frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst,
481     + src[0], src[1], src[2]);
482     + else
483     + frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst,
484     + src[0]);
485     +
486     + lprintf ("copy...done\n");
487     +}
488     +
489     +static void xshm_frame_field (vo_frame_t *vo_img, int which_field) {
490     + xshm_frame_t *frame = (xshm_frame_t *) vo_img ;
491     + /* xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; */
492     +
493     + switch (which_field) {
494     + case VO_TOP_FIELD:
495     + frame->rgb_dst = frame->image;
496     + break;
497     + case VO_BOTTOM_FIELD:
498     + frame->rgb_dst = frame->image + frame->bytes_per_line;
499     + break;
500     + case VO_BOTH_FIELDS:
501     + frame->rgb_dst = frame->image;
502     + break;
503     + }
504     +
505     + frame->yuv2rgb->next_slice (frame->yuv2rgb, NULL);
506     +}
507     +
508     +static void xshm_frame_dispose (vo_frame_t *vo_img) {
509     + xshm_frame_t *frame = (xshm_frame_t *) vo_img ;
510     + xshm_driver_t *this = (xshm_driver_t *) vo_img->driver;
511     +
512     + if (frame->image) {
513     + pthread_mutex_lock(&this->main_mutex);
514     + dispose_ximage(this, frame);
515     + pthread_mutex_unlock(&this->main_mutex);
516     + }
517     +
518     + frame->yuv2rgb->dispose (frame->yuv2rgb);
519     +
520     + free (frame->chunk[0]);
521     + free (frame->chunk[1]);
522     + free (frame->chunk[2]);
523     + free (frame);
524     +}
525     +
526     +
527     +static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) {
528     + xshm_frame_t *frame;
529     + xshm_driver_t *this = (xshm_driver_t *) this_gen;
530     +
531     + frame = (xshm_frame_t *) xine_xmalloc (sizeof (xshm_frame_t));
532     + if (!frame)
533     + return NULL;
534     +
535     + memcpy (&frame->sc, &this->sc, sizeof(vo_scale_t));
536     +
537     + pthread_mutex_init (&frame->vo_frame.mutex, NULL);
538     +
539     + /*
540     + * supply required functions/fields
541     + */
542     +
543     + frame->vo_frame.proc_slice = xshm_frame_proc_slice;
544     + frame->vo_frame.proc_frame = NULL;
545     + frame->vo_frame.field = xshm_frame_field;
546     + frame->vo_frame.dispose = xshm_frame_dispose;
547     + frame->vo_frame.driver = this_gen;
548     +
549     + /*
550     + * colorspace converter for this frame
551     + */
552     +
553     + frame->yuv2rgb = this->yuv2rgb_factory->create_converter (this->yuv2rgb_factory);
554     +
555     + return (vo_frame_t *) frame;
556     +}
557     +
558     +static void xshm_compute_ideal_size (xshm_driver_t *this, xshm_frame_t *frame) {
559     + _x_vo_scale_compute_ideal_size( &frame->sc );
560     +}
561     +
562     +static void xshm_compute_rgb_size (xshm_driver_t *this, xshm_frame_t *frame) {
563     + _x_vo_scale_compute_output_size( &frame->sc );
564     +
565     + /* avoid problems in yuv2rgb */
566     + if (frame->sc.output_height < 1)
567     + frame->sc.output_height = 1;
568     + if (frame->sc.output_width < 8)
569     + frame->sc.output_width = 8;
570     + if (frame->sc.output_width & 1) /* yuv2rgb_mlib needs an even YUV2 width */
571     + frame->sc.output_width++;
572     +
573     + lprintf("frame source (%d) %d x %d => screen output %d x %d%s\n",
574     + frame->vo_frame.id,
575     + frame->sc.delivered_width, frame->sc.delivered_height,
576     + frame->sc.output_width, frame->sc.output_height,
577     + ( frame->sc.delivered_width != frame->sc.output_width
578     + || frame->sc.delivered_height != frame->sc.output_height
579     + ? ", software scaling"
580     + : "" )
581     + );
582     +}
583     +
584     +static void xshm_update_frame_format (vo_driver_t *this_gen,
585     + vo_frame_t *frame_gen,
586     + uint32_t width, uint32_t height,
587     + double ratio, int format, int flags) {
588     + xshm_driver_t *this = (xshm_driver_t *) this_gen;
589     + xshm_frame_t *frame = (xshm_frame_t *) frame_gen;
590     + int do_adapt;
591     + int gui_width;
592     + int gui_height;
593     + double gui_pixel_aspect;
594     +
595     + flags &= VO_BOTH_FIELDS;
596     +
597     + /* ask gui what output size we'll have for this frame */
598     + /* get the gui_pixel_aspect before calling xshm_compute_ideal_size() */
599     + /* note: gui_width and gui_height may be bogus because we may have not yet*/
600     + /* updated video_pixel_aspect (see _x_vo_scale_compute_ideal_size). */
601     + frame->sc.dest_size_cb (frame->sc.user_data, width, height,
602     + frame->sc.video_pixel_aspect,
603     + &gui_width, &gui_height,
604     + &gui_pixel_aspect);
605     +
606     + /* find out if we need to adapt this frame */
607     + do_adapt = 0;
608     +
609     + if ((width != frame->sc.delivered_width)
610     + || (height != frame->sc.delivered_height)
611     + || (ratio != frame->sc.delivered_ratio)
612     + || (flags != frame->flags)
613     + || (format != frame->format)
614     + || (gui_pixel_aspect != frame->sc.gui_pixel_aspect)
615     + || (this->sc.user_ratio != frame->sc.user_ratio)) {
616     +
617     + do_adapt = 1;
618     +
619     + lprintf ("frame format (from decoder) has changed => adapt\n");
620     +
621     + frame->sc.delivered_width = width;
622     + frame->sc.delivered_height = height;
623     + frame->sc.delivered_ratio = ratio;
624     + frame->sc.gui_pixel_aspect = gui_pixel_aspect;
625     + frame->flags = flags;
626     + frame->format = format;
627     + frame->sc.user_ratio = this->sc.user_ratio;
628     +
629     + xshm_compute_ideal_size (this, frame);
630     +
631     + /* now we have updated video_aspect_pixel we use the callback */
632     + /* again to obtain the correct gui_width and gui_height values. */
633     + frame->sc.dest_size_cb (frame->sc.user_data, width, height,
634     + frame->sc.video_pixel_aspect,
635     + &gui_width, &gui_height,
636     + &gui_pixel_aspect);
637     + }
638     +
639     + if ((frame->sc.gui_width != gui_width) ||
640     + (frame->sc.gui_height != gui_height) ||
641     + do_adapt) {
642     +
643     + do_adapt = 1;
644     + frame->sc.gui_width = gui_width;
645     + frame->sc.gui_height = gui_height;
646     +
647     + xshm_compute_rgb_size (this, frame);
648     +
649     + lprintf ("gui_size has changed => adapt\n");
650     + }
651     +
652     +
653     + /* ok, now do what we have to do */
654     +
655     + if (do_adapt) {
656     +
657     + lprintf ("updating frame to %d x %d\n",
658     + frame->sc.output_width, frame->sc.output_height);
659     +
660     + pthread_mutex_lock(&this->main_mutex);
661     +
662     + /*
663     + * (re-) allocate XImage
664     + */
665     +
666     + if (frame->image) {
667     +
668     + dispose_ximage(this, frame);
669     +
670     + if (frame->chunk[0]){
671     + free (frame->chunk[0]);
672     + frame->chunk[0] = NULL;
673     + }
674     + if (frame->chunk[1]) {
675     + free (frame->chunk[1]);
676     + frame->chunk[1] = NULL;
677     + }
678     + if (frame->chunk[2]) {
679     + free (frame->chunk[2]);
680     + frame->chunk[2] = NULL;
681     + }
682     + }
683     +
684     + create_ximage(this, frame, frame->sc.output_width, frame->sc.output_height);
685     +
686     + pthread_mutex_unlock(&this->main_mutex);
687     +
688     + if (format == XINE_IMGFMT_YV12) {
689     + frame->vo_frame.pitches[0] = 8*((width + 7) / 8);
690     + frame->vo_frame.pitches[1] = 8*((width + 15) / 16);
691     + frame->vo_frame.pitches[2] = 8*((width + 15) / 16);
692     + frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]);
693     + frame->vo_frame.base[1] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[1] * ((height+1)/2), (void **) &frame->chunk[1]);
694     + frame->vo_frame.base[2] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[2] * ((height+1)/2), (void **) &frame->chunk[2]);
695     + } else {
696     + frame->vo_frame.pitches[0] = 8*((width + 3) / 4);
697     + frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]);
698     + frame->chunk[1] = NULL;
699     + frame->chunk[2] = NULL;
700     + }
701     +
702     + lprintf ("stripe out_ht=%i, deliv_ht=%i\n",
703     + frame->sc.output_height, frame->sc.delivered_height);
704     +
705     + /*
706     + * set up colorspace converter
707     + */
708     +
709     + switch (flags) {
710     + case VO_TOP_FIELD:
711     + case VO_BOTTOM_FIELD:
712     + frame->yuv2rgb->configure (frame->yuv2rgb,
713     + frame->sc.delivered_width,
714     + frame->sc.delivered_height,
715     + 2*frame->vo_frame.pitches[0],
716     + 2*frame->vo_frame.pitches[1],
717     + frame->sc.output_width,
718     + frame->sc.output_height,
719     + frame->bytes_per_line*2);
720     + break;
721     + case VO_BOTH_FIELDS:
722     + frame->yuv2rgb->configure (frame->yuv2rgb,
723     + frame->sc.delivered_width,
724     + frame->sc.delivered_height,
725     + frame->vo_frame.pitches[0],
726     + frame->vo_frame.pitches[1],
727     + frame->sc.output_width,
728     + frame->sc.output_height,
729     + frame->bytes_per_line);
730     + break;
731     + }
732     + }
733     +
734     + xshm_frame_field ((vo_frame_t *)frame, flags);
735     +}
736     +
737     +static void xshm_overlay_clut_yuv2rgb(xshm_driver_t *this, vo_overlay_t *overlay,
738     + xshm_frame_t *frame) {
739     + size_t i;
740     + clut_t* clut = (clut_t*) overlay->color;
741     +
742     + if (!overlay->rgb_clut) {
743     + for (i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) {
744     + *((uint32_t *)&clut[i]) =
745     + frame->yuv2rgb->yuv2rgb_single_pixel_fun (frame->yuv2rgb,
746     + clut[i].y, clut[i].cb, clut[i].cr);
747     + }
748     + overlay->rgb_clut++;
749     + }
750     + if (!overlay->hili_rgb_clut) {
751     + clut = (clut_t*) overlay->hili_color;
752     + for (i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) {
753     + *((uint32_t *)&clut[i]) =
754     + frame->yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb,
755     + clut[i].y, clut[i].cb, clut[i].cr);
756     + }
757     + overlay->hili_rgb_clut++;
758     + }
759     +}
760     +
761     +static void xshm_overlay_begin (vo_driver_t *this_gen,
762     + vo_frame_t *frame_gen, int changed) {
763     + xshm_driver_t *this = (xshm_driver_t *) this_gen;
764     +
765     + this->ovl_changed += changed;
766     +
767     + if( this->ovl_changed && this->xoverlay ) {
768     + pthread_mutex_lock(&this->main_mutex);
769     + xcbosd_clear(this->xoverlay);
770     + pthread_mutex_unlock(&this->main_mutex);
771     + }
772     +
773     + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x;
774     + this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y;
775     +}
776     +
777     +static void xshm_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) {
778     + xshm_driver_t *this = (xshm_driver_t *) this_gen;
779     +
780     + if( this->ovl_changed && this->xoverlay ) {
781     + pthread_mutex_lock(&this->main_mutex);
782     + xcbosd_expose(this->xoverlay);
783     + pthread_mutex_unlock(&this->main_mutex);
784     + }
785     +
786     + this->ovl_changed = 0;
787     +}
788     +
789     +static void xshm_overlay_blend (vo_driver_t *this_gen,
790     + vo_frame_t *frame_gen, vo_overlay_t *overlay) {
791     + xshm_driver_t *this = (xshm_driver_t *) this_gen;
792     + xshm_frame_t *frame = (xshm_frame_t *) frame_gen;
793     +
794     + /* Alpha Blend here */
795     + if (overlay->rle) {
796     + if( overlay->unscaled ) {
797     + if( this->ovl_changed && this->xoverlay ) {
798     + pthread_mutex_lock(&this->main_mutex);
799     + xcbosd_blend(this->xoverlay, overlay);
800     + pthread_mutex_unlock(&this->main_mutex);
801     + }
802     + } else {
803     + if (!overlay->rgb_clut || !overlay->hili_rgb_clut)
804     + xshm_overlay_clut_yuv2rgb (this, overlay, frame);
805     +
806     + switch (this->bpp) {
807     + case 16:
808     + _x_blend_rgb16(frame->image, overlay,
809     + frame->sc.output_width, frame->sc.output_height,
810     + frame->sc.delivered_width, frame->sc.delivered_height,
811     + &this->alphablend_extra_data);
812     + break;
813     + case 24:
814     + _x_blend_rgb24(frame->image, overlay,
815     + frame->sc.output_width, frame->sc.output_height,
816     + frame->sc.delivered_width, frame->sc.delivered_height,
817     + &this->alphablend_extra_data);
818     + break;
819     + case 32:
820     + _x_blend_rgb32(frame->image, overlay,
821     + frame->sc.output_width, frame->sc.output_height,
822     + frame->sc.delivered_width, frame->sc.delivered_height,
823     + &this->alphablend_extra_data);
824     + break;
825     + default:
826     + xprintf(this->xine, XINE_VERBOSITY_DEBUG,
827     + "xine-lib:video_out_xshm:xshm_overlay_blend: Cannot blend bpp:%i\n", this->bpp);
828     + /* it should never get here, unless a user tries to play in bpp:8 */
829     + break;
830     + }
831     + }
832     + }
833     +}
834     +
835     +static void clean_output_area (xshm_driver_t *this, xshm_frame_t *frame) {
836     + int i;
837     + xcb_rectangle_t rects[4];
838     + int rects_count = 0;
839     +
840     + memcpy( this->sc.border, frame->sc.border, sizeof(this->sc.border) );
841     +
842     + pthread_mutex_lock(&this->main_mutex);
843     +
844     + for( i = 0; i < 4; i++ ) {
845     + if( this->sc.border[i].w && this->sc.border[i].h )
846     + rects[rects_count].x = this->sc.border[i].x;
847     + rects[rects_count].y = this->sc.border[i].y;
848     + rects[rects_count].width = this->sc.border[i].w;
849     + rects[rects_count].height = this->sc.border[i].h;
850     + rects_count++;
851     + }
852     +
853     + if (rects_count > 0)
854     + xcb_poly_fill_rectangle(this->connection, this->window, this->gc, rects_count, rects);
855     +
856     + if (this->xoverlay) {
857     + xcbosd_resize(this->xoverlay, this->sc.gui_width, this->sc.gui_height);
858     + this->ovl_changed = 1;
859     + }
860     +
861     + pthread_mutex_unlock(&this->main_mutex);
862     +}
863     +
864     +static int xshm_redraw_needed (vo_driver_t *this_gen) {
865     + xshm_driver_t *this = (xshm_driver_t *) this_gen;
866     + int ret = 0;
867     +
868     + if( this->cur_frame ) {
869     + this->sc.delivered_height = this->cur_frame->sc.delivered_height;
870     + this->sc.delivered_width = this->cur_frame->sc.delivered_width;
871     + this->sc.video_pixel_aspect = this->cur_frame->sc.video_pixel_aspect;
872     + if( _x_vo_scale_redraw_needed( &this->sc ) ) {
873     +
874     + clean_output_area (this, this->cur_frame);
875     + ret = 1;
876     + }
877     + }
878     + else
879     + ret = 1;
880     +
881     + return ret;
882     +}
883     +
884     +static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
885     + xshm_driver_t *this = (xshm_driver_t *) this_gen;
886     + xshm_frame_t *frame = (xshm_frame_t *) frame_gen;
887     +
888     + lprintf ("display frame...\n");
889     + lprintf ("about to draw frame (%d) %d x %d...\n",
890     + frame->vo_frame.id,
891     + frame->sc.output_width, frame->sc.output_height);
892     +
893     + /*
894     + * tell gui that we are about to display a frame,
895     + * ask for offset
896     + */
897     +
898     + this->sc.delivered_height = frame->sc.delivered_height;
899     + this->sc.delivered_width = frame->sc.delivered_width;
900     + this->sc.video_pixel_aspect = frame->sc.video_pixel_aspect;
901     + if( _x_vo_scale_redraw_needed( &this->sc ) ) {
902     +
903     + clean_output_area (this, frame);
904     + }
905     +
906     + if (this->cur_frame) {
907     +
908     + if ( (this->cur_frame->sc.output_width != frame->sc.output_width)
909     + || (this->cur_frame->sc.output_height != frame->sc.output_height)
910     + || (this->cur_frame->sc.output_xoffset != frame->sc.output_xoffset)
911     + || (this->cur_frame->sc.output_yoffset != frame->sc.output_yoffset) )
912     + clean_output_area (this, frame);
913     +
914     + this->cur_frame->vo_frame.free (&this->cur_frame->vo_frame);
915     + }
916     +
917     + this->cur_frame = frame;
918     +
919     + pthread_mutex_lock(&this->main_mutex);
920     + lprintf ("display locked...\n");
921     +
922     + if (frame->shmseg) {
923     +
924     + lprintf ("put image (shm)\n");
925     + xcb_shm_put_image(this->connection, this->window, this->gc, this->cur_frame->sc.output_width,
926     + this->cur_frame->sc.output_height, 0, 0, this->cur_frame->sc.output_width,
927     + this->cur_frame->sc.output_height, this->cur_frame->sc.output_xoffset,
928     + this->cur_frame->sc.output_yoffset, this->depth, XCB_IMAGE_FORMAT_Z_PIXMAP,
929     + 0, this->cur_frame->shmseg, 0);
930     +
931     + } else {
932     +
933     + lprintf ("put image (plain/remote)\n");
934     + xcb_put_image(this->connection, XCB_IMAGE_FORMAT_Z_PIXMAP, this->window, this->gc,
935     + frame->sc.output_width, frame->sc.output_height, frame->sc.output_xoffset, frame->sc.output_yoffset,
936     + 0, this->depth, frame->bytes_per_line * frame->sc.output_height, frame->image);
937     +
938     + }
939     + xcb_flush(this->connection);
940     + pthread_mutex_unlock(&this->main_mutex);
941     +
942     + lprintf ("display frame done\n");
943     +}
944     +
945     +static int xshm_get_property (vo_driver_t *this_gen, int property) {
946     + xshm_driver_t *this = (xshm_driver_t *) this_gen;
947     +
948     + switch (property) {
949     + case VO_PROP_ASPECT_RATIO:
950     + return this->sc.user_ratio;
951     + case VO_PROP_MAX_NUM_FRAMES:
952     + return 15;
953     + case VO_PROP_BRIGHTNESS:
954     + return this->yuv2rgb_brightness;
955     + case VO_PROP_CONTRAST:
956     + return this->yuv2rgb_contrast;
957     + case VO_PROP_SATURATION:
958     + return this->yuv2rgb_saturation;
959     + case VO_PROP_WINDOW_WIDTH:
960     + return this->sc.gui_width;
961     + case VO_PROP_WINDOW_HEIGHT:
962     + return this->sc.gui_height;
963     + default:
964     + xprintf(this->xine, XINE_VERBOSITY_DEBUG,
965     + "video_out_xshm: tried to get unsupported property %d\n", property);
966     + }
967     +
968     + return 0;
969     +}
970     +
971     +static int xshm_set_property (vo_driver_t *this_gen,
972     + int property, int value) {
973     + xshm_driver_t *this = (xshm_driver_t *) this_gen;
974     +
975     + if ( property == VO_PROP_ASPECT_RATIO) {
976     +
977     + if (value>=XINE_VO_ASPECT_NUM_RATIOS)
978     + value = XINE_VO_ASPECT_AUTO;
979     + this->sc.user_ratio = value;
980     + xprintf(this->xine, XINE_VERBOSITY_DEBUG,
981     + "video_out_xshm: aspect ratio changed to %s\n", _x_vo_scale_aspect_ratio_name(value));
982     +
983     + } else if (property == VO_PROP_BRIGHTNESS) {
984     +
985     + this->yuv2rgb_brightness = value;
986     + this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory,
987     + this->yuv2rgb_brightness,
988     + this->yuv2rgb_contrast,
989     + this->yuv2rgb_saturation);
990     +
991     + this->sc.force_redraw = 1;
992     +
993     + } else if (property == VO_PROP_CONTRAST) {
994     +
995     + this->yuv2rgb_contrast = value;
996     + this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory,
997     + this->yuv2rgb_brightness,
998     + this->yuv2rgb_contrast,
999     + this->yuv2rgb_saturation);
1000     +
1001     + this->sc.force_redraw = 1;
1002     +
1003     + } else if (property == VO_PROP_SATURATION) {
1004     +
1005     + this->yuv2rgb_saturation = value;
1006     + this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory,
1007     + this->yuv2rgb_brightness,
1008     + this->yuv2rgb_contrast,
1009     + this->yuv2rgb_saturation);
1010     +
1011     + this->sc.force_redraw = 1;
1012     +
1013     + } else {
1014     + xprintf (this->xine, XINE_VERBOSITY_DEBUG,
1015     + "video_out_xshm: tried to set unsupported property %d\n", property);
1016     + }
1017     +
1018     + return value;
1019     +}
1020     +
1021     +static void xshm_get_property_min_max (vo_driver_t *this_gen,
1022     + int property, int *min, int *max) {
1023     + /* xshm_driver_t *this = (xshm_driver_t *) this_gen; */
1024     +
1025     + if (property == VO_PROP_BRIGHTNESS) {
1026     + *min = -128;
1027     + *max = +127;
1028     + } else if (property == VO_PROP_CONTRAST) {
1029     + *min = 0;
1030     + *max = 255;
1031     + } else if (property == VO_PROP_SATURATION) {
1032     + *min = 0;
1033     + *max = 255;
1034     + } else {
1035     + *min = 0;
1036     + *max = 0;
1037     + }
1038     +}
1039     +
1040     +static int xshm_gui_data_exchange (vo_driver_t *this_gen,
1041     + int data_type, void *data) {
1042     + xshm_driver_t *this = (xshm_driver_t *) this_gen;
1043     +
1044     + switch (data_type) {
1045     +#ifndef XINE_DISABLE_DEPRECATED_FEATURES
1046     + case XINE_GUI_SEND_COMPLETION_EVENT:
1047     + break;
1048     +#endif
1049     +
1050     + case XINE_GUI_SEND_EXPOSE_EVENT:
1051     +
1052     + lprintf ("expose event\n");
1053     +
1054     + if (this->cur_frame) {
1055     + xcb_expose_event_t *xev = (xcb_expose_event_t *) data;
1056     +
1057     + if (xev && xev->count == 0) {
1058     + int i;
1059     + xcb_rectangle_t rects[4];
1060     + int rects_count = 0;
1061     +
1062     + pthread_mutex_lock(&this->main_mutex);
1063     + if (this->cur_frame->shmseg)
1064     + xcb_shm_put_image(this->connection, this->window, this->gc, this->cur_frame->sc.output_width,
1065     + this->cur_frame->sc.output_height, 0, 0, this->cur_frame->sc.output_width,
1066     + this->cur_frame->sc.output_height, this->cur_frame->sc.output_xoffset,
1067     + this->cur_frame->sc.output_yoffset, this->depth, XCB_IMAGE_FORMAT_Z_PIXMAP,
1068     + 0, this->cur_frame->shmseg, 0);
1069     + else
1070     + xcb_put_image(this->connection, XCB_IMAGE_FORMAT_Z_PIXMAP, this->window, this->gc,
1071     + this->cur_frame->sc.output_width, this->cur_frame->sc.output_height,
1072     + this->cur_frame->sc.output_xoffset, this->cur_frame->sc.output_yoffset,
1073     + 0, this->depth, this->cur_frame->bytes_per_line * this->cur_frame->sc.output_height,
1074     + this->cur_frame->image);
1075     +
1076     + for( i = 0; i < 4; i++ ) {
1077     + if( this->sc.border[i].w && this->sc.border[i].h )
1078     + rects[rects_count].x = this->sc.border[i].x;
1079     + rects[rects_count].y = this->sc.border[i].y;
1080     + rects[rects_count].width = this->sc.border[i].w;
1081     + rects[rects_count].height = this->sc.border[i].h;
1082     + rects_count++;
1083     + }
1084     +
1085     + if (rects_count > 0)
1086     + xcb_poly_fill_rectangle(this->connection, this->window, this->gc, rects_count, rects);
1087     +
1088     + if(this->xoverlay)
1089     + xcbosd_expose(this->xoverlay);
1090     +
1091     + xcb_flush(this->connection);
1092     + pthread_mutex_unlock(&this->main_mutex);
1093     + }
1094     + }
1095     + break;
1096     +
1097     + case XINE_GUI_SEND_DRAWABLE_CHANGED:
1098     + this->window = (xcb_window_t) data;
1099     +
1100     + pthread_mutex_lock(&this->main_mutex);
1101     + xcb_free_gc(this->connection, this->gc);
1102     + this->gc = xcb_generate_id(this->connection);
1103     + xcb_create_gc(this->connection, this->gc, this->window, XCB_GC_FOREGROUND, &this->screen->black_pixel);
1104     + if(this->xoverlay)
1105     + xcbosd_drawable_changed(this->xoverlay, this->window);
1106     + this->ovl_changed = 1;
1107     + pthread_mutex_unlock(&this->main_mutex);
1108     + break;
1109     +
1110     + case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO:
1111     +
1112     + if (this->cur_frame) {
1113     + x11_rectangle_t *rect = data;
1114     + int x1, y1, x2, y2;
1115     +
1116     + _x_vo_scale_translate_gui2video(&this->cur_frame->sc,
1117     + rect->x, rect->y,
1118     + &x1, &y1);
1119     + _x_vo_scale_translate_gui2video(&this->cur_frame->sc,
1120     + rect->x + rect->w, rect->y + rect->h,
1121     + &x2, &y2);
1122     + rect->x = x1;
1123     + rect->y = y1;
1124     + rect->w = x2-x1;
1125     + rect->h = y2-y1;
1126     + }
1127     + break;
1128     +
1129     + default:
1130     + return -1;
1131     + }
1132     +
1133     + return 0;
1134     +}
1135     +
1136     +static void xshm_dispose (vo_driver_t *this_gen) {
1137     + xshm_driver_t *this = (xshm_driver_t *) this_gen;
1138     +
1139     + if (this->cur_frame)
1140     + this->cur_frame->vo_frame.dispose (&this->cur_frame->vo_frame);
1141     +
1142     + this->yuv2rgb_factory->dispose (this->yuv2rgb_factory);
1143     +
1144     + pthread_mutex_lock(&this->main_mutex);
1145     + xcb_free_gc(this->connection, this->gc);
1146     + pthread_mutex_unlock(&this->main_mutex);
1147     +
1148     + if( this->xoverlay ) {
1149     + pthread_mutex_lock(&this->main_mutex);
1150     + xcbosd_destroy(this->xoverlay);
1151     + pthread_mutex_unlock(&this->main_mutex);
1152     + }
1153     +
1154     + pthread_mutex_destroy(&this->main_mutex);
1155     +
1156     + _x_alphablend_free(&this->alphablend_extra_data);
1157     +
1158     + free (this);
1159     +}
1160     +
1161     +static int ImlibPaletteLUTGet(xshm_driver_t *this) {
1162     + static const xcb_atom_t CARDINAL = 6;
1163     +
1164     + xcb_intern_atom_cookie_t atom_cookie;
1165     + xcb_intern_atom_reply_t *atom_reply;
1166     +
1167     + xcb_get_property_cookie_t prop_cookie;
1168     + xcb_get_property_reply_t *prop_reply;
1169     +
1170     + atom_cookie = xcb_intern_atom(this->connection, 0, sizeof("_IMLIB_COLORMAP"), "_IMLIB_COLORMAP");
1171     + atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL);
1172     +
1173     + if (atom_reply == NULL)
1174     + return 0;
1175     +
1176     + prop_cookie = xcb_get_property(this->connection, 0, this->window, atom_reply->atom, CARDINAL, 0, 0x7fffffff);
1177     + prop_reply = xcb_get_property_reply(this->connection, prop_cookie, NULL);
1178     +
1179     + free(atom_reply);
1180     +
1181     + if (prop_reply == NULL)
1182     + return 0;
1183     +
1184     + if (prop_reply->format == 8) {
1185     + unsigned int i;
1186     + unsigned long j;
1187     + int num_ret = xcb_get_property_value_length(prop_reply);
1188     + char *retval = xcb_get_property_value(prop_reply);
1189     +
1190     + j = 1 + retval[0]*4;
1191     + this->yuv2rgb_cmap = malloc(sizeof(uint8_t) * 32 * 32 * 32);
1192     + for (i = 0; i < 32 * 32 * 32 && j < num_ret; i++)
1193     + this->yuv2rgb_cmap[i] = retval[1+4*retval[j++]+3];
1194     +
1195     + free(prop_reply);
1196     + return 1;
1197     + }
1198     +
1199     + free(prop_reply);
1200     + return 0;
1201     +}
1202     +
1203     +
1204     +static char *visual_class_name(xcb_visualtype_t *visual) {
1205     +
1206     + switch (visual->_class) {
1207     + case XCB_VISUAL_CLASS_STATIC_GRAY:
1208     + return "StaticGray";
1209     + case XCB_VISUAL_CLASS_GRAY_SCALE:
1210     + return "GrayScale";
1211     + case XCB_VISUAL_CLASS_STATIC_COLOR:
1212     + return "StaticColor";
1213     + case XCB_VISUAL_CLASS_PSEUDO_COLOR:
1214     + return "PseudoColor";
1215     + case XCB_VISUAL_CLASS_TRUE_COLOR:
1216     + return "TrueColor";
1217     + case XCB_VISUAL_CLASS_DIRECT_COLOR:
1218     + return "DirectColor";
1219     + default:
1220     + return "unknown visual class";
1221     + }
1222     +}
1223     +
1224     +static vo_driver_t *xshm_open_plugin(video_driver_class_t *class_gen, const void *visual_gen) {
1225     + xshm_class_t *class = (xshm_class_t *) class_gen;
1226     + config_values_t *config = class->config;
1227     + xcb_visual_t *visual = (xcb_visual_t *) visual_gen;
1228     + xshm_driver_t *this;
1229     + xcb_visualtype_t *visualtype;
1230     + int mode;
1231     + int swapped;
1232     + int cpu_byte_order;
1233     + int image_byte_order;
1234     +
1235     + xcb_get_window_attributes_cookie_t window_attrs_cookie;
1236     + xcb_get_window_attributes_reply_t *window_attrs_reply;
1237     +
1238     + xcb_get_geometry_cookie_t geometry_cookie;
1239     + xcb_get_geometry_reply_t *geometry_reply;
1240     +
1241     + const xcb_query_extension_reply_t *query_extension_reply;
1242     +
1243     + this = (xshm_driver_t *) xine_xmalloc (sizeof (xshm_driver_t));
1244     +
1245     + if (!this)
1246     + return NULL;
1247     +
1248     + pthread_mutex_init(&this->main_mutex, NULL);
1249     +
1250     + _x_alphablend_init(&this->alphablend_extra_data, class->xine);
1251     +
1252     + this->connection = visual->connection;
1253     + this->screen = visual->screen;
1254     + this->window = visual->window;
1255     +
1256     + _x_vo_scale_init( &this->sc, 0, 0, config );
1257     + this->sc.frame_output_cb = visual->frame_output_cb;
1258     + this->sc.dest_size_cb = visual->dest_size_cb;
1259     + this->sc.user_data = visual->user_data;
1260     +
1261     + this->sc.user_ratio = XINE_VO_ASPECT_AUTO;
1262     +
1263     + this->cur_frame = NULL;
1264     + this->gc = xcb_generate_id(this->connection);
1265     + xcb_create_gc(this->connection, this->gc, this->window, XCB_GC_FOREGROUND, &this->screen->black_pixel);
1266     + this->xoverlay = NULL;
1267     + this->ovl_changed = 0;
1268     +
1269     + this->xine = class->xine;
1270     +
1271     + this->vo_driver.get_capabilities = xshm_get_capabilities;
1272     + this->vo_driver.alloc_frame = xshm_alloc_frame;
1273     + this->vo_driver.update_frame_format = xshm_update_frame_format;
1274     + this->vo_driver.overlay_begin = xshm_overlay_begin;
1275     + this->vo_driver.overlay_blend = xshm_overlay_blend;
1276     + this->vo_driver.overlay_end = xshm_overlay_end;
1277     + this->vo_driver.display_frame = xshm_display_frame;
1278     + this->vo_driver.get_property = xshm_get_property;
1279     + this->vo_driver.set_property = xshm_set_property;
1280     + this->vo_driver.get_property_min_max = xshm_get_property_min_max;
1281     + this->vo_driver.gui_data_exchange = xshm_gui_data_exchange;
1282     + this->vo_driver.dispose = xshm_dispose;
1283     + this->vo_driver.redraw_needed = xshm_redraw_needed;
1284     +
1285     + /*
1286     + *
1287     + * depth in X11 terminology land is the number of bits used to
1288     + * actually represent the colour.
1289     + *
1290     + * bpp in X11 land means how many bits in the frame buffer per
1291     + * pixel.
1292     + *
1293     + * ex. 15 bit color is 15 bit depth and 16 bpp. Also 24 bit
1294     + * color is 24 bit depth, but can be 24 bpp or 32 bpp.
1295     + */
1296     +
1297     + window_attrs_cookie = xcb_get_window_attributes(this->connection, this->window);
1298     + geometry_cookie = xcb_get_geometry(this->connection, this->window);
1299     + xcb_prefetch_extension_data(this->connection, &xcb_shm_id);
1300     +
1301     + window_attrs_reply = xcb_get_window_attributes_reply(this->connection, window_attrs_cookie, NULL);
1302     +
1303     + visualtype = NULL;
1304     + {
1305     + xcb_depth_t *depth = xcb_screen_allowed_depths_iterator(this->screen).data;
1306     + xcb_visualtype_t *vis = xcb_depth_visuals(depth);
1307     + xcb_visualtype_t *vis_end = vis + xcb_depth_visuals_length(depth);
1308     +
1309     + for (; vis != vis_end; ++vis)
1310     + if (window_attrs_reply->visual == vis->visual_id) {
1311     + visualtype = vis;
1312     + break;
1313     + }
1314     + }
1315     +
1316     + free(window_attrs_reply);
1317     +
1318     + geometry_reply = xcb_get_geometry_reply(this->connection, geometry_cookie, NULL);
1319     +
1320     + this->depth = geometry_reply->depth;
1321     +
1322     + free(geometry_reply);
1323     +
1324     + if (this->depth>16)
1325     + xprintf(this->xine, XINE_VERBOSITY_LOG,
1326     + _("\n\nWARNING: current display depth is %d. For better performance\n"
1327     + "a depth of 16 bpp is recommended!\n\n"), this->depth);
1328     +
1329     + /*
1330     + * check for X shared memory support
1331     + */
1332     +
1333     + query_extension_reply = xcb_get_extension_data(this->connection, &xcb_shm_id);
1334     + if (query_extension_reply && query_extension_reply->present) {
1335     + this->use_shm = 1;
1336     + }
1337     + else {
1338     + xprintf(this->xine, XINE_VERBOSITY_LOG,
1339     + _("video_out_xshm: MIT shared memory extension not present on display.\n"));
1340     + this->use_shm = 0;
1341     + }
1342     +
1343     + {
1344     + const xcb_setup_t *setup = xcb_get_setup(this->connection);
1345     + xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
1346     + xcb_format_t *fmt_end = fmt + xcb_setup_pixmap_formats_length(setup);
1347     +
1348     + for (; fmt != fmt_end; ++fmt)
1349     + if(fmt->depth == this->depth) {
1350     + this->bpp = fmt->bits_per_pixel;
1351     + this->scanline_pad = fmt->scanline_pad;
1352     + break;
1353     + }
1354     +
1355     + if (fmt == fmt_end) {
1356     + if (this->depth <= 4)
1357     + this->bpp = 4;
1358     + else if (this->depth <= 8)
1359     + this->bpp = 8;
1360     + else if (this->depth <= 16)
1361     + this->bpp = 16;
1362     + else
1363     + this->bpp = 32;
1364     + this->scanline_pad = setup->bitmap_format_scanline_pad;
1365     + }
1366     +
1367     + image_byte_order = setup->image_byte_order;
1368     + }
1369     +
1370     + /*
1371     + * Is the same byte order in use on the X11 client and server?
1372     + */
1373     + cpu_byte_order = htonl(1) == 1 ? XCB_IMAGE_ORDER_MSB_FIRST : XCB_IMAGE_ORDER_LSB_FIRST;
1374     + swapped = cpu_byte_order != image_byte_order;
1375     +
1376     + xprintf(this->xine, XINE_VERBOSITY_DEBUG,
1377     + "video_out_xshm: video mode depth is %d (%d bpp), %s, %sswapped,\n"
1378     + "\tred: %08x, green: %08x, blue: %08x\n",
1379     + this->depth, this->bpp,
1380     + visual_class_name(visualtype),
1381     + swapped ? "" : "not ",
1382     + visualtype->red_mask, visualtype->green_mask, visualtype->blue_mask);
1383     +
1384     + mode = 0;
1385     +
1386     + switch (visualtype->_class) {
1387     + case XCB_VISUAL_CLASS_TRUE_COLOR:
1388     + switch (this->depth) {
1389     + case 24:
1390     + case 32:
1391     + if (this->bpp == 32) {
1392     + if (visualtype->red_mask == 0x00ff0000)
1393     + mode = MODE_32_RGB;
1394     + else
1395     + mode = MODE_32_BGR;
1396     + } else {
1397     + if (visualtype->red_mask == 0x00ff0000)
1398     + mode = MODE_24_RGB;
1399     + else
1400     + mode = MODE_24_BGR;
1401     + }
1402     + break;
1403     + case 16:
1404     + if (visualtype->red_mask == 0xf800)
1405     + mode = MODE_16_RGB;
1406     + else
1407     + mode = MODE_16_BGR;
1408     + break;
1409     + case 15:
1410     + if (visualtype->red_mask == 0x7C00)
1411     + mode = MODE_15_RGB;
1412     + else
1413     + mode = MODE_15_BGR;
1414     + break;
1415     + case 8:
1416     + if (visualtype->red_mask == 0xE0)
1417     + mode = MODE_8_RGB; /* Solaris x86: RGB332 */
1418     + else
1419     + mode = MODE_8_BGR; /* XFree86: BGR233 */
1420     + break;
1421     + }
1422     + break;
1423     +
1424     + case XCB_VISUAL_CLASS_STATIC_GRAY:
1425     + if (this->depth == 8)
1426     + mode = MODE_8_GRAY;
1427     + break;
1428     +
1429     + case XCB_VISUAL_CLASS_PSEUDO_COLOR:
1430     + case XCB_VISUAL_CLASS_GRAY_SCALE:
1431     + if (this->depth <= 8 && ImlibPaletteLUTGet(this))
1432     + mode = MODE_PALETTE;
1433     + break;
1434     + }
1435     +
1436     + if (!mode) {
1437     + xprintf (this->xine, XINE_VERBOSITY_LOG,
1438     + _("video_out_xshm: your video mode was not recognized, sorry :-(\n"));
1439     + return NULL;
1440     + }
1441     +
1442     + this->yuv2rgb_brightness = 0;
1443     + this->yuv2rgb_contrast = 128;
1444     + this->yuv2rgb_saturation = 128;
1445     +
1446     + this->yuv2rgb_factory = yuv2rgb_factory_init (mode, swapped,
1447     + this->yuv2rgb_cmap);
1448     + this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory,
1449     + this->yuv2rgb_brightness,
1450     + this->yuv2rgb_contrast,
1451     + this->yuv2rgb_saturation);
1452     +
1453     + this->xoverlay = xcbosd_create(this->xine, this->connection, this->screen,
1454     + this->window, XCBOSD_SHAPED);
1455     +
1456     + return &this->vo_driver;
1457     +}
1458     +
1459     +/*
1460     + * class functions
1461     + */
1462     +
1463     +static char* xshm_get_identifier (video_driver_class_t *this_gen) {
1464     + return "XShm";
1465     +}
1466     +
1467     +static char* xshm_get_description (video_driver_class_t *this_gen) {
1468     + return _("xine video output plugin using the MIT X shared memory extension");
1469     +}
1470     +
1471     +static void xshm_dispose_class (video_driver_class_t *this_gen) {
1472     + xshm_class_t *this = (xshm_class_t *) this_gen;
1473     +
1474     + free (this);
1475     +}
1476     +
1477     +static void *xshm_init_class (xine_t *xine, void *visual_gen) {
1478     + xshm_class_t *this = (xshm_class_t *) xine_xmalloc (sizeof (xshm_class_t));
1479     +
1480     + this->driver_class.open_plugin = xshm_open_plugin;
1481     + this->driver_class.get_identifier = xshm_get_identifier;
1482     + this->driver_class.get_description = xshm_get_description;
1483     + this->driver_class.dispose = xshm_dispose_class;
1484     + this->config = xine->config;
1485     + this->xine = xine;
1486     +
1487     + return this;
1488     +}
1489     +
1490     +
1491     +static const vo_info_t vo_info_xshm = {
1492     + 6, /* priority */
1493     + XINE_VISUAL_TYPE_XCB /* visual type */
1494     +};
1495     +
1496     +
1497     +/*
1498     + * exported plugin catalog entry
1499     + */
1500     +
1501     +const plugin_info_t xine_plugin_info[] EXPORTED = {
1502     + /* type, API, "name", version, special_info, init_function */
1503     + { PLUGIN_VIDEO_OUT, 21, "xshm", XINE_VERSION_CODE, &vo_info_xshm, xshm_init_class },
1504     + { PLUGIN_NONE, 0, "", 0, NULL, NULL }
1505     +};
1506     Index: src/video_out/video_out_xcbxv.c
1507     ===================================================================
1508     RCS file: src/video_out/video_out_xcbxv.c
1509     diff -N src/video_out/video_out_xcbxv.c
1510     --- /dev/null 1 Jan 1970 00:00:00 -0000
1511     +++ src/video_out/video_out_xcbxv.c 7 Feb 2007 02:41:40 -0000
1512     @@ -0,0 +1,1598 @@
1513     +/*
1514     + * Copyright (C) 2000-2004, 2007 the xine project
1515     + *
1516     + * This file is part of xine, a free video player.
1517     + *
1518     + * xine is free software; you can redistribute it and/or modify
1519     + * it under the terms of the GNU General Public License as published by
1520     + * the Free Software Foundation; either version 2 of the License, or
1521     + * (at your option) any later version.
1522     + *
1523     + * xine is distributed in the hope that it will be useful,
1524     + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1525     + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1526     + * GNU General Public License for more details.
1527     + *
1528     + * You should have received a copy of the GNU General Public License
1529     + * along with this program; if not, write to the Free Software
1530     + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
1531     + *
1532     + * $Id: xine-lib-1.1.4-xcb.patch,v 1.1 2007-05-08 20:43:46 niro Exp $
1533     + *
1534     + * video_out_xcbxv.c, X11 video extension interface for xine
1535     + *
1536     + * based on mpeg2dec code from
1537     + * Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
1538     + *
1539     + * Xv image support by Gerd Knorr <kraxel@goldbach.in-berlin.de>
1540     + *
1541     + * xine-specific code by Guenter Bartsch <bartscgr@studbox.uni-stuttgart.de>
1542     + *
1543     + * overlay support by James Courtier-Dutton <James@superbug.demon.co.uk> - July 2001
1544     + * X11 unscaled overlay support by Miguel Freitas - Nov 2003
1545     + * ported to xcb by Christoph Pfister - Feb 2007
1546     + */
1547     +
1548     +#ifdef HAVE_CONFIG_H
1549     +#include "config.h"
1550     +#endif
1551     +
1552     +#ifdef HAVE_XV
1553     +
1554     +#include <stdio.h>
1555     +#include <stdlib.h>
1556     +#include <string.h>
1557     +#include <errno.h>
1558     +#include <math.h>
1559     +
1560     +#include <sys/types.h>
1561     +#if defined(__FreeBSD__)
1562     +#include <machine/param.h>
1563     +#endif
1564     +#include <sys/ipc.h>
1565     +#include <sys/shm.h>
1566     +#include <sys/time.h>
1567     +
1568     +#include <xcb/xv.h>
1569     +
1570     +#define LOG_MODULE "video_out_xcbxv"
1571     +#define LOG_VERBOSE
1572     +/*
1573     +#define LOG
1574     +*/
1575     +
1576     +#include "xine.h"
1577     +#include "video_out.h"
1578     +#include "xine_internal.h"
1579     +/* #include "overlay.h" */
1580     +#include "deinterlace.h"
1581     +#include "xineutils.h"
1582     +#include "vo_scale.h"
1583     +#include "xcbosd.h"
1584     +
1585     +typedef struct xv_driver_s xv_driver_t;
1586     +
1587     +typedef struct {
1588     + int value;
1589     + int min;
1590     + int max;
1591     + xcb_atom_t atom;
1592     +
1593     + cfg_entry_t *entry;
1594     +
1595     + xv_driver_t *this;
1596     +} xv_property_t;
1597     +
1598     +typedef struct {
1599     + char *name;
1600     + int value;
1601     +} xv_portattribute_t;
1602     +
1603     +typedef struct {
1604     + vo_frame_t vo_frame;
1605     +
1606     + int width, height, format;
1607     + double ratio;
1608     +
1609     + uint8_t *image;
1610     + xcb_shm_seg_t shmseg;
1611     + unsigned int xv_format;
1612     + unsigned int xv_data_size;
1613     + unsigned int xv_width;
1614     + unsigned int xv_height;
1615     + unsigned int xv_pitches[3];
1616     + unsigned int xv_offsets[3];
1617     +
1618     +} xv_frame_t;
1619     +
1620     +
1621     +struct xv_driver_s {
1622     +
1623     + vo_driver_t vo_driver;
1624     +
1625     + config_values_t *config;
1626     +
1627     + /* xcb / xv related stuff */
1628     + xcb_connection_t *connection;
1629     + xcb_screen_t *screen;
1630     + xcb_window_t window;
1631     + unsigned int xv_format_yv12;
1632     + unsigned int xv_format_yuy2;
1633     + xcb_gc_t gc;
1634     + xcb_xv_port_t xv_port;
1635     +
1636     + int use_shm;
1637     + int use_pitch_alignment;
1638     + xv_property_t props[VO_NUM_PROPERTIES];
1639     + uint32_t capabilities;
1640     +
1641     + xv_frame_t *recent_frames[VO_NUM_RECENT_FRAMES];
1642     + xv_frame_t *cur_frame;
1643     + xcbosd *xoverlay;
1644     + int ovl_changed;
1645     +
1646     + /* all scaling information goes here */
1647     + vo_scale_t sc;
1648     +
1649     + xv_frame_t deinterlace_frame;
1650     + int deinterlace_method;
1651     + int deinterlace_enabled;
1652     +
1653     + int use_colorkey;
1654     + uint32_t colorkey;
1655     +
1656     + /* hold initial port attributes values to restore on exit */
1657     + xine_list_t *port_attributes;
1658     +
1659     + xine_t *xine;
1660     +
1661     + alphablend_t alphablend_extra_data;
1662     +
1663     + pthread_mutex_t main_mutex;
1664     +
1665     +};
1666     +
1667     +typedef struct {
1668     + video_driver_class_t driver_class;
1669     +
1670     + config_values_t *config;
1671     + xine_t *xine;
1672     +} xv_class_t;
1673     +
1674     +static uint32_t xv_get_capabilities (vo_driver_t *this_gen) {
1675     + xv_driver_t *this = (xv_driver_t *) this_gen;
1676     +
1677     + return this->capabilities;
1678     +}
1679     +
1680     +static void xv_frame_field (vo_frame_t *vo_img, int which_field) {
1681     + /* not needed for Xv */
1682     +}
1683     +
1684     +static void xv_frame_dispose (vo_frame_t *vo_img) {
1685     + xv_frame_t *frame = (xv_frame_t *) vo_img ;
1686     + xv_driver_t *this = (xv_driver_t *) vo_img->driver;
1687     +
1688     + if (frame->shmseg) {
1689     + pthread_mutex_lock(&this->main_mutex);
1690     + xcb_shm_detach(this->connection, frame->shmseg);
1691     + frame->shmseg = 0;
1692     + pthread_mutex_unlock(&this->main_mutex);
1693     + shmdt(frame->image);
1694     + }
1695     + else
1696     + free(frame->image);
1697     +
1698     + free (frame);
1699     +}
1700     +
1701     +static vo_frame_t *xv_alloc_frame (vo_driver_t *this_gen) {
1702     + /* xv_driver_t *this = (xv_driver_t *) this_gen; */
1703     + xv_frame_t *frame ;
1704     +
1705     + frame = (xv_frame_t *) xine_xmalloc (sizeof (xv_frame_t));
1706     + if (!frame)
1707     + return NULL;
1708     +
1709     + pthread_mutex_init (&frame->vo_frame.mutex, NULL);
1710     +
1711     + /*
1712     + * supply required functions
1713     + */
1714     + frame->vo_frame.proc_slice = NULL;
1715     + frame->vo_frame.proc_frame = NULL;
1716     + frame->vo_frame.field = xv_frame_field;
1717     + frame->vo_frame.dispose = xv_frame_dispose;
1718     + frame->vo_frame.driver = this_gen;
1719     +
1720     + return (vo_frame_t *) frame;
1721     +}
1722     +
1723     +static void create_ximage(xv_driver_t *this, xv_frame_t *frame, int width, int height, int format)
1724     +{
1725     + xcb_xv_query_image_attributes_cookie_t query_attributes_cookie;
1726     + xcb_xv_query_image_attributes_reply_t *query_attributes_reply;
1727     +
1728     + unsigned int length;
1729     +
1730     + if (this->use_pitch_alignment) {
1731     + width = (width + 7) & ~0x7;
1732     + }
1733     +
1734     + switch (format) {
1735     + case XINE_IMGFMT_YV12:
1736     + frame->xv_format = this->xv_format_yv12;
1737     + break;
1738     + case XINE_IMGFMT_YUY2:
1739     + frame->xv_format = this->xv_format_yuy2;
1740     + break;
1741     + default:
1742     + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "create_ximage: unknown format %08x\n",format);
1743     + _x_abort();
1744     + }
1745     +
1746     + query_attributes_cookie = xcb_xv_query_image_attributes(this->connection, this->xv_port, frame->xv_format, width, height);
1747     + query_attributes_reply = xcb_xv_query_image_attributes_reply(this->connection, query_attributes_cookie, NULL);
1748     +
1749     + if (query_attributes_reply == NULL)
1750     + return;
1751     +
1752     + frame->xv_data_size = query_attributes_reply->data_size;
1753     + frame->xv_width = query_attributes_reply->width;
1754     + frame->xv_height = query_attributes_reply->height;
1755     +
1756     + length = xcb_xv_query_image_attributes_pitches_length(query_attributes_reply);
1757     + if (length > 3)
1758     + length = 3;
1759     + memcpy(frame->xv_pitches, xcb_xv_query_image_attributes_pitches(query_attributes_reply), length * sizeof(frame->xv_pitches[0]));
1760     +
1761     + length = xcb_xv_query_image_attributes_offsets_length(query_attributes_reply);
1762     + if (length > 3)
1763     + length = 3;
1764     + memcpy(frame->xv_offsets, xcb_xv_query_image_attributes_offsets(query_attributes_reply), length * sizeof(frame->xv_offsets[0]));
1765     +
1766     + free(query_attributes_reply);
1767     +
1768     + if (this->use_shm) {
1769     + int shmid;
1770     + xcb_void_cookie_t shm_attach_cookie;
1771     + xcb_generic_error_t *generic_error;
1772     +
1773     + /*
1774     + * try shm
1775     + */
1776     +
1777     + if (frame->xv_data_size == 0) {
1778     + xprintf(this->xine, XINE_VERBOSITY_LOG,
1779     + _("video_out_xv: XvShmCreateImage returned a zero size\n"
1780     + "video_out_xv: => not using MIT Shared Memory extension.\n"));
1781     + goto shm_fail1;
1782     + }
1783     +
1784     + shmid = shmget(IPC_PRIVATE, frame->xv_data_size, IPC_CREAT | 0777);
1785     +
1786     + if (shmid < 0 ) {
1787     + xprintf(this->xine, XINE_VERBOSITY_LOG,
1788     + _("video_out_xv: shared memory error in shmget: %s\n"
1789     + "video_out_xv: => not using MIT Shared Memory extension.\n"), strerror(errno));
1790     + goto shm_fail1;
1791     + }
1792     +
1793     + frame->image = shmat(shmid, 0, 0);
1794     +
1795     + if (frame->image == ((void *) -1)) {
1796     + xprintf(this->xine, XINE_VERBOSITY_DEBUG,
1797     + "video_out_xv: shared memory error (address error)\n");
1798     + goto shm_fail2;
1799     + }
1800     +
1801     + frame->shmseg = xcb_generate_id(this->connection);
1802     + shm_attach_cookie = xcb_shm_attach_checked(this->connection, frame->shmseg, shmid, 0);
1803     + generic_error = xcb_request_check(this->connection, shm_attach_cookie);
1804     +
1805     + if (generic_error != NULL) {
1806     + xprintf(this->xine, XINE_VERBOSITY_LOG,
1807     + _("video_out_xv: x11 error during shared memory XImage creation\n"
1808     + "video_out_xv: => not using MIT Shared Memory extension.\n"));
1809     + free(generic_error);
1810     + goto shm_fail3;
1811     + }
1812     +
1813     + /*
1814     + * Now that the Xserver has learned about and attached to the
1815     + * shared memory segment, delete it. It's actually deleted by
1816     + * the kernel when all users of that segment have detached from
1817     + * it. Gives an automatic shared memory cleanup in case we crash.
1818     + */
1819     +
1820     + shmctl(shmid, IPC_RMID, 0);
1821     +
1822     + return;
1823     +
1824     + shm_fail3:
1825     + frame->shmseg = 0;
1826     + shmdt(frame->image);
1827     + shm_fail2:
1828     + shmctl(shmid, IPC_RMID, 0);
1829     + shm_fail1:
1830     + this->use_shm = 0;
1831     + }
1832     +
1833     + /*
1834     + * fall back to plain Xv if necessary
1835     + */
1836     +
1837     + switch (format) {
1838     + case XINE_IMGFMT_YV12:
1839     + frame->image = malloc(width * height * 3/2);
1840     + break;
1841     + case XINE_IMGFMT_YUY2:
1842     + frame->image = malloc(width * height * 2);
1843     + break;
1844     + default:
1845     + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "create_ximage: unknown format %08x\n",format);
1846     + _x_abort();
1847     + }
1848     +}
1849     +
1850     +static void dispose_ximage(xv_driver_t *this, xv_frame_t *frame)
1851     +{
1852     + if (frame->shmseg) {
1853     + xcb_shm_detach(this->connection, frame->shmseg);
1854     + frame->shmseg = 0;
1855     + shmdt(frame->image);
1856     + } else
1857     + free(frame->image);
1858     + frame->image = NULL;
1859     +}
1860     +
1861     +static void xv_update_frame_format (vo_driver_t *this_gen,
1862     + vo_frame_t *frame_gen,
1863     + uint32_t width, uint32_t height,
1864     + double ratio, int format, int flags) {
1865     + xv_driver_t *this = (xv_driver_t *) this_gen;
1866     + xv_frame_t *frame = (xv_frame_t *) frame_gen;
1867     +
1868     + if (this->use_pitch_alignment) {
1869     + width = (width + 7) & ~0x7;
1870     + }
1871     +
1872     + if ((frame->width != width)
1873     + || (frame->height != height)
1874     + || (frame->format != format)) {
1875     +
1876     + /* printf ("video_out_xv: updating frame to %d x %d (ratio=%d, format=%08x)\n",width,height,ratio_code,format); */
1877     +
1878     + pthread_mutex_lock(&this->main_mutex);
1879     +
1880     + /*
1881     + * (re-) allocate xvimage
1882     + */
1883     +
1884     + if (frame->image)
1885     + dispose_ximage(this, frame);
1886     +
1887     + create_ximage(this, frame, width, height, format);
1888     +
1889     + if(format == XINE_IMGFMT_YUY2) {
1890     + frame->vo_frame.pitches[0] = frame->xv_pitches[0];
1891     + frame->vo_frame.base[0] = frame->image + frame->xv_offsets[0];
1892     + }
1893     + else {
1894     + frame->vo_frame.pitches[0] = frame->xv_pitches[0];
1895     + frame->vo_frame.pitches[1] = frame->xv_pitches[2];
1896     + frame->vo_frame.pitches[2] = frame->xv_pitches[1];
1897     + frame->vo_frame.base[0] = frame->image + frame->xv_offsets[0];
1898     + frame->vo_frame.base[1] = frame->image + frame->xv_offsets[2];
1899     + frame->vo_frame.base[2] = frame->image + frame->xv_offsets[1];
1900     + }
1901     +
1902     + frame->width = width;
1903     + frame->height = height;
1904     + frame->format = format;
1905     +
1906     + pthread_mutex_unlock(&this->main_mutex);
1907     + }
1908     +
1909     + frame->ratio = ratio;
1910     +}
1911     +
1912     +#define DEINTERLACE_CROMA
1913     +static void xv_deinterlace_frame (xv_driver_t *this) {
1914     + uint8_t *recent_bitmaps[VO_NUM_RECENT_FRAMES];
1915     + xv_frame_t *frame = this->recent_frames[0];
1916     + int i;
1917     + int xvscaling;
1918     +
1919     + xvscaling = (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) ? 2 : 1;
1920     +
1921     + if (!this->deinterlace_frame.image
1922     + || (frame->width != this->deinterlace_frame.width)
1923     + || (frame->height != this->deinterlace_frame.height )
1924     + || (frame->format != this->deinterlace_frame.format)
1925     + || (frame->ratio != this->deinterlace_frame.ratio)) {
1926     + pthread_mutex_lock(&this->main_mutex);
1927     +
1928     + if(this->deinterlace_frame.image)
1929     + dispose_ximage(this, &this->deinterlace_frame);
1930     +
1931     + create_ximage(this, &this->deinterlace_frame, frame->width, frame->height / xvscaling, frame->format);
1932     + this->deinterlace_frame.width = frame->width;
1933     + this->deinterlace_frame.height = frame->height;
1934     + this->deinterlace_frame.format = frame->format;
1935     + this->deinterlace_frame.ratio = frame->ratio;
1936     +
1937     + pthread_mutex_unlock(&this->main_mutex);
1938     + }
1939     +
1940     +
1941     + if ( this->deinterlace_method != DEINTERLACE_ONEFIELDXV ) {
1942     +#ifdef DEINTERLACE_CROMA
1943     +
1944     + /* I don't think this is the right way to do it (deinterlacing croma by croma info).
1945     + DScaler deinterlaces croma together with luma, but it's easier for them because
1946     + they have that components 1:1 at the same table.
1947     + */
1948     + for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ )
1949     + if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width &&
1950     + this->recent_frames[i]->height == frame->height )
1951     + recent_bitmaps[i] = this->recent_frames[i]->image + frame->width*frame->height;
1952     + else
1953     + recent_bitmaps[i] = NULL;
1954     +
1955     + deinterlace_yuv( this->deinterlace_frame.image+frame->width*frame->height,
1956     + recent_bitmaps, frame->width/2, frame->height/2, this->deinterlace_method );
1957     + for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ )
1958     + if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width &&
1959     + this->recent_frames[i]->height == frame->height )
1960     + recent_bitmaps[i] = this->recent_frames[i]->image + frame->width*frame->height*5/4;
1961     + else
1962     + recent_bitmaps[i] = NULL;
1963     +
1964     + deinterlace_yuv( this->deinterlace_frame.image+frame->width*frame->height*5/4,
1965     + recent_bitmaps, frame->width/2, frame->height/2, this->deinterlace_method );
1966     +
1967     +#else
1968     +
1969     + /* know bug: we are not deinterlacing Cb and Cr */
1970     + xine_fast_memcpy(this->deinterlace_frame.image + frame->width*frame->height,
1971     + frame->image + frame->width*frame->height,
1972     + frame->width*frame->height*1/2);
1973     +
1974     +#endif
1975     +
1976     + for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ )
1977     + if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width &&
1978     + this->recent_frames[i]->height == frame->height )
1979     + recent_bitmaps[i] = this->recent_frames[i]->image;
1980     + else
1981     + recent_bitmaps[i] = NULL;
1982     +
1983     + deinterlace_yuv( this->deinterlace_frame.image, recent_bitmaps,
1984     + frame->width, frame->height, this->deinterlace_method );
1985     + }
1986     + else {
1987     + /*
1988     + dirty and cheap deinterlace method: we give half of the lines to xv
1989     + driver and let it scale for us.
1990     + note that memcpy's below don't seem to impact much on performance,
1991     + specially when fast memcpys are available.
1992     + */
1993     + uint8_t *dst, *src;
1994     +
1995     + dst = this->deinterlace_frame.image;
1996     + src = this->recent_frames[0]->image;
1997     + for( i = 0; i < frame->height; i+=2 ) {
1998     + xine_fast_memcpy(dst,src,frame->width);
1999     + dst += frame->width;
2000     + src += 2 * frame->width;
2001     + }
2002     +
2003     + dst = this->deinterlace_frame.image + frame->width * frame->height / 2;
2004     + src = this->recent_frames[0]->image + frame->width * frame->height;
2005     + for( i = 0; i < frame->height; i+=4 ) {
2006     + xine_fast_memcpy(dst,src,frame->width / 2);
2007     + dst += frame->width / 2;
2008     + src += frame->width;
2009     + }
2010     +
2011     + dst = this->deinterlace_frame.image + frame->width * frame->height * 5 / 8;
2012     + src = this->recent_frames[0]->image + frame->width * frame->height * 5 / 4;
2013     + for( i = 0; i < frame->height; i+=4 ) {
2014     + xine_fast_memcpy(dst,src,frame->width / 2);
2015     + dst += frame->width / 2;
2016     + src += frame->width;
2017     + }
2018     + }
2019     +
2020     + this->cur_frame = &this->deinterlace_frame;
2021     +}
2022     +
2023     +static void xv_clean_output_area (xv_driver_t *this) {
2024     + int i;
2025     + xcb_rectangle_t rects[4];
2026     + int rects_count = 0;
2027     +
2028     + pthread_mutex_lock(&this->main_mutex);
2029     +
2030     + xcb_change_gc(this->connection, this->gc, XCB_GC_FOREGROUND, &this->screen->black_pixel);
2031     +
2032     + for( i = 0; i < 4; i++ ) {
2033     + if( this->sc.border[i].w && this->sc.border[i].h ) {
2034     + rects[rects_count].x = this->sc.border[i].x;
2035     + rects[rects_count].y = this->sc.border[i].y;
2036     + rects[rects_count].width = this->sc.border[i].w;
2037     + rects[rects_count].height = this->sc.border[i].h;
2038     + rects_count++;
2039     + }
2040     + }
2041     +
2042     + if (rects_count > 0)
2043     + xcb_poly_fill_rectangle(this->connection, this->window, this->gc, rects_count, rects);
2044     +
2045     + if (this->use_colorkey) {
2046     + xcb_change_gc(this->connection, this->gc, XCB_GC_FOREGROUND, &this->colorkey);
2047     + xcb_rectangle_t rectangle = { this->sc.output_xoffset, this->sc.output_yoffset,
2048     + this->sc.output_width, this->sc.output_height };
2049     + xcb_poly_fill_rectangle(this->connection, this->window, this->gc, 1, &rectangle);
2050     + }
2051     +
2052     + if (this->xoverlay) {
2053     + xcbosd_resize(this->xoverlay, this->sc.gui_width, this->sc.gui_height);
2054     + this->ovl_changed = 1;
2055     + }
2056     +
2057     + pthread_mutex_unlock(&this->main_mutex);
2058     +}
2059     +
2060     +/*
2061     + * convert delivered height/width to ideal width/height
2062     + * taking into account aspect ratio and zoom factor
2063     + */
2064     +
2065     +static void xv_compute_ideal_size (xv_driver_t *this) {
2066     + _x_vo_scale_compute_ideal_size( &this->sc );
2067     +}
2068     +
2069     +
2070     +/*
2071     + * make ideal width/height "fit" into the gui
2072     + */
2073     +
2074     +static void xv_compute_output_size (xv_driver_t *this) {
2075     +
2076     + _x_vo_scale_compute_output_size( &this->sc );
2077     +
2078     + /* onefield_xv divide by 2 the number of lines */
2079     + if (this->deinterlace_enabled
2080     + && (this->deinterlace_method == DEINTERLACE_ONEFIELDXV)
2081     + && this->cur_frame && (this->cur_frame->format == XINE_IMGFMT_YV12)) {
2082     + this->sc.displayed_height = this->sc.displayed_height / 2 - 1;
2083     + this->sc.displayed_yoffset = this->sc.displayed_yoffset / 2;
2084     + }
2085     +}
2086     +
2087     +static void xv_overlay_begin (vo_driver_t *this_gen,
2088     + vo_frame_t *frame_gen, int changed) {
2089     + xv_driver_t *this = (xv_driver_t *) this_gen;
2090     +
2091     + this->ovl_changed += changed;
2092     +
2093     + if( this->ovl_changed && this->xoverlay ) {
2094     + pthread_mutex_lock(&this->main_mutex);
2095     + xcbosd_clear(this->xoverlay);
2096     + pthread_mutex_unlock(&this->main_mutex);
2097     + }
2098     +
2099     + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x;
2100     + this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y;
2101     +}
2102     +
2103     +static void xv_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) {
2104     + xv_driver_t *this = (xv_driver_t *) this_gen;
2105     +
2106     + if( this->ovl_changed && this->xoverlay ) {
2107     + pthread_mutex_lock(&this->main_mutex);
2108     + xcbosd_expose(this->xoverlay);
2109     + pthread_mutex_unlock(&this->main_mutex);
2110     + }
2111     +
2112     + this->ovl_changed = 0;
2113     +}
2114     +
2115     +static void xv_overlay_blend (vo_driver_t *this_gen,
2116     + vo_frame_t *frame_gen, vo_overlay_t *overlay) {
2117     + xv_driver_t *this = (xv_driver_t *) this_gen;
2118     + xv_frame_t *frame = (xv_frame_t *) frame_gen;
2119     +
2120     + if (overlay->rle) {
2121     + if( overlay->unscaled ) {
2122     + if( this->ovl_changed && this->xoverlay ) {
2123     + pthread_mutex_lock(&this->main_mutex);
2124     + xcbosd_blend(this->xoverlay, overlay);
2125     + pthread_mutex_unlock(&this->main_mutex);
2126     + }
2127     + } else {
2128     + if (frame->format == XINE_IMGFMT_YV12)
2129     + _x_blend_yuv(frame->vo_frame.base, overlay,
2130     + frame->width, frame->height, frame->vo_frame.pitches,
2131     + &this->alphablend_extra_data);
2132     + else
2133     + _x_blend_yuy2(frame->vo_frame.base[0], overlay,
2134     + frame->width, frame->height, frame->vo_frame.pitches[0],
2135     + &this->alphablend_extra_data);
2136     + }
2137     + }
2138     +}
2139     +
2140     +static void xv_add_recent_frame (xv_driver_t *this, xv_frame_t *frame) {
2141     + int i;
2142     +
2143     + i = VO_NUM_RECENT_FRAMES-1;
2144     + if( this->recent_frames[i] )
2145     + this->recent_frames[i]->vo_frame.free
2146     + (&this->recent_frames[i]->vo_frame);
2147     +
2148     + for( ; i ; i-- )
2149     + this->recent_frames[i] = this->recent_frames[i-1];
2150     +
2151     + this->recent_frames[0] = frame;
2152     +}
2153     +
2154     +/* currently not used - we could have a method to call this from video loop */
2155     +#if 0
2156     +static void xv_flush_recent_frames (xv_driver_t *this) {
2157     + int i;
2158     +
2159     + for( i=0; i < VO_NUM_RECENT_FRAMES; i++ ) {
2160     + if( this->recent_frames[i] )
2161     + this->recent_frames[i]->vo_frame.free
2162     + (&this->recent_frames[i]->vo_frame);
2163     + this->recent_frames[i] = NULL;
2164     + }
2165     +}
2166     +#endif
2167     +
2168     +static int xv_redraw_needed (vo_driver_t *this_gen) {
2169     + xv_driver_t *this = (xv_driver_t *) this_gen;
2170     + int ret = 0;
2171     +
2172     + if( this->cur_frame ) {
2173     +
2174     + this->sc.delivered_height = this->cur_frame->height;
2175     + this->sc.delivered_width = this->cur_frame->width;
2176     + this->sc.delivered_ratio = this->cur_frame->ratio;
2177     +
2178     + this->sc.crop_left = this->cur_frame->vo_frame.crop_left;
2179     + this->sc.crop_right = this->cur_frame->vo_frame.crop_right;
2180     + this->sc.crop_top = this->cur_frame->vo_frame.crop_top;
2181     + this->sc.crop_bottom = this->cur_frame->vo_frame.crop_bottom;
2182     +
2183     + xv_compute_ideal_size(this);
2184     +
2185     + if( _x_vo_scale_redraw_needed( &this->sc ) ) {
2186     +
2187     + xv_compute_output_size (this);
2188     +
2189     + xv_clean_output_area (this);
2190     +
2191     + ret = 1;
2192     + }
2193     + }
2194     + else
2195     + ret = 1;
2196     +
2197     + return ret;
2198     +}
2199     +
2200     +static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
2201     + xv_driver_t *this = (xv_driver_t *) this_gen;
2202     + xv_frame_t *frame = (xv_frame_t *) frame_gen;
2203     + /*
2204     + printf ("video_out_xv: xv_display_frame...\n");
2205     + */
2206     +
2207     + /*
2208     + * queue frames (deinterlacing)
2209     + * free old frames
2210     + */
2211     +
2212     + xv_add_recent_frame (this, frame); /* deinterlacing */
2213     +
2214     + this->cur_frame = frame;
2215     +
2216     + /*
2217     + * let's see if this frame is different in size / aspect
2218     + * ratio from the previous one
2219     + */
2220     + if ( (frame->width != this->sc.delivered_width)
2221     + || (frame->height != this->sc.delivered_height)
2222     + || (frame->ratio != this->sc.delivered_ratio) ) {
2223     + lprintf("frame format changed\n");
2224     + this->sc.force_redraw = 1; /* trigger re-calc of output size */
2225     + }
2226     +
2227     + /*
2228     + * deinterlace frame if necessary
2229     + * (currently only working for YUV images)
2230     + */
2231     +
2232     + if (this->deinterlace_enabled && this->deinterlace_method
2233     + && frame->format == XINE_IMGFMT_YV12
2234     + && (deinterlace_yuv_supported( this->deinterlace_method ) == 1
2235     + || this->deinterlace_method == DEINTERLACE_ONEFIELDXV))
2236     + xv_deinterlace_frame (this);
2237     +
2238     + /*
2239     + * tell gui that we are about to display a frame,
2240     + * ask for offset and output size
2241     + */
2242     + xv_redraw_needed (this_gen);
2243     +
2244     + pthread_mutex_lock(&this->main_mutex);
2245     +
2246     + if (this->cur_frame->shmseg) {
2247     + xcb_xv_shm_put_image(this->connection, this->xv_port, this->window, this->gc,
2248     + this->cur_frame->shmseg, this->cur_frame->xv_format, 0,
2249     + this->sc.displayed_xoffset, this->sc.displayed_yoffset,
2250     + this->sc.displayed_width, this->sc.displayed_height,
2251     + this->sc.output_xoffset, this->sc.output_yoffset,
2252     + this->sc.output_width, this->sc.output_height,
2253     + this->cur_frame->xv_width, this->cur_frame->xv_height, 0);
2254     +
2255     + } else {
2256     + xcb_xv_put_image(this->connection, this->xv_port, this->window, this->gc,
2257     + this->cur_frame->xv_format,
2258     + this->sc.displayed_xoffset, this->sc.displayed_yoffset,
2259     + this->sc.displayed_width, this->sc.displayed_height,
2260     + this->sc.output_xoffset, this->sc.output_yoffset,
2261     + this->sc.output_width, this->sc.output_height,
2262     + this->cur_frame->xv_width, this->cur_frame->xv_height,
2263     + this->cur_frame->xv_data_size, this->cur_frame->image);
2264     + }
2265     +
2266     + xcb_flush(this->connection);
2267     +
2268     + pthread_mutex_unlock(&this->main_mutex);
2269     +
2270     + /*
2271     + printf ("video_out_xv: xv_display_frame... done\n");
2272     + */
2273     +}
2274     +
2275     +static int xv_get_property (vo_driver_t *this_gen, int property) {
2276     + xv_driver_t *this = (xv_driver_t *) this_gen;
2277     +
2278     + switch (property) {
2279     + case VO_PROP_WINDOW_WIDTH:
2280     + this->props[property].value = this->sc.gui_width;
2281     + break;
2282     + case VO_PROP_WINDOW_HEIGHT:
2283     + this->props[property].value = this->sc.gui_height;
2284     + break;
2285     + }
2286     +
2287     + lprintf("video_out_xv: property #%d = %d\n", property, this->props[property].value);
2288     +
2289     + return this->props[property].value;
2290     +}
2291     +
2292     +static void xv_property_callback (void *property_gen, xine_cfg_entry_t *entry) {
2293     + xv_property_t *property = (xv_property_t *) property_gen;
2294     + xv_driver_t *this = property->this;
2295     +
2296     + pthread_mutex_lock(&this->main_mutex);
2297     + xcb_xv_set_port_attribute(this->connection, this->xv_port,
2298     + property->atom, entry->num_value);
2299     + pthread_mutex_unlock(&this->main_mutex);
2300     +}
2301     +
2302     +static int xv_set_property (vo_driver_t *this_gen,
2303     + int property, int value) {
2304     + xv_driver_t *this = (xv_driver_t *) this_gen;
2305     +
2306     + if (this->props[property].atom != XCB_NONE) {
2307     + xcb_xv_get_port_attribute_cookie_t get_attribute_cookie;
2308     + xcb_xv_get_port_attribute_reply_t *get_attribute_reply;
2309     +
2310     + /* value is out of bound */
2311     + if((value < this->props[property].min) || (value > this->props[property].max))
2312     + value = (this->props[property].min + this->props[property].max) >> 1;
2313     +
2314     + pthread_mutex_lock(&this->main_mutex);
2315     + xcb_xv_set_port_attribute(this->connection, this->xv_port,
2316     + this->props[property].atom, value);
2317     +
2318     + get_attribute_cookie = xcb_xv_get_port_attribute(this->connection, this->xv_port, this->props[property].atom);
2319     + get_attribute_reply = xcb_xv_get_port_attribute_reply(this->connection, get_attribute_cookie, NULL);
2320     + this->props[property].value = get_attribute_reply->value;
2321     + free(get_attribute_reply);
2322     +
2323     + pthread_mutex_unlock(&this->main_mutex);
2324     +
2325     + if (this->props[property].entry)
2326     + this->props[property].entry->num_value = this->props[property].value;
2327     +
2328     + return this->props[property].value;
2329     + }
2330     + else {
2331     + switch (property) {
2332     +
2333     + case VO_PROP_INTERLACED:
2334     + this->props[property].value = value;
2335     + xprintf(this->xine, XINE_VERBOSITY_LOG,
2336     + "video_out_xv: VO_PROP_INTERLACED(%d)\n", this->props[property].value);
2337     + this->deinterlace_enabled = value;
2338     + if (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) {
2339     + xv_compute_ideal_size (this);
2340     + xv_compute_output_size (this);
2341     + }
2342     + break;
2343     +
2344     + case VO_PROP_ASPECT_RATIO:
2345     + if (value>=XINE_VO_ASPECT_NUM_RATIOS)
2346     + value = XINE_VO_ASPECT_AUTO;
2347     +
2348     + this->props[property].value = value;
2349     + xprintf(this->xine, XINE_VERBOSITY_LOG,
2350     + "video_out_xv: VO_PROP_ASPECT_RATIO(%d)\n", this->props[property].value);
2351     + this->sc.user_ratio = value;
2352     +
2353     + xv_compute_ideal_size (this);
2354     +
2355     + this->sc.force_redraw = 1; /* trigger re-calc of output size */
2356     + break;
2357     +
2358     + case VO_PROP_ZOOM_X:
2359     + if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) {
2360     + this->props[property].value = value;
2361     + xprintf(this->xine, XINE_VERBOSITY_LOG,
2362     + "video_out_xv: VO_PROP_ZOOM_X = %d\n", this->props[property].value);
2363     +
2364     + this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP;
2365     +
2366     + xv_compute_ideal_size (this);
2367     +
2368     + this->sc.force_redraw = 1; /* trigger re-calc of output size */
2369     + }
2370     + break;
2371     +
2372     + case VO_PROP_ZOOM_Y:
2373     + if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) {
2374     + this->props[property].value = value;
2375     + xprintf(this->xine, XINE_VERBOSITY_LOG,
2376     + "video_out_xv: VO_PROP_ZOOM_Y = %d\n", this->props[property].value);
2377     +
2378     + this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP;
2379     +
2380     + xv_compute_ideal_size (this);
2381     +
2382     + this->sc.force_redraw = 1; /* trigger re-calc of output size */
2383     + }
2384     + break;
2385     + }
2386     + }
2387     +
2388     + return value;
2389     +}
2390     +
2391     +static void xv_get_property_min_max (vo_driver_t *this_gen,
2392     + int property, int *min, int *max) {
2393     + xv_driver_t *this = (xv_driver_t *) this_gen;
2394     +
2395     + *min = this->props[property].min;
2396     + *max = this->props[property].max;
2397     +}
2398     +
2399     +static int xv_gui_data_exchange (vo_driver_t *this_gen,
2400     + int data_type, void *data) {
2401     + xv_driver_t *this = (xv_driver_t *) this_gen;
2402     +
2403     + switch (data_type) {
2404     +#ifndef XINE_DISABLE_DEPRECATED_FEATURES
2405     + case XINE_GUI_SEND_COMPLETION_EVENT:
2406     + break;
2407     +#endif
2408     +
2409     + case XINE_GUI_SEND_EXPOSE_EVENT: {
2410     + /* XExposeEvent * xev = (XExposeEvent *) data; */
2411     +
2412     + if (this->cur_frame) {
2413     +
2414     + pthread_mutex_lock(&this->main_mutex);
2415     +
2416     + if (this->cur_frame->shmseg) {
2417     + xcb_xv_shm_put_image(this->connection, this->xv_port, this->window, this->gc,
2418     + this->cur_frame->shmseg, this->cur_frame->xv_format, 0,
2419     + this->sc.displayed_xoffset, this->sc.displayed_yoffset,
2420     + this->sc.displayed_width, this->sc.displayed_height,
2421     + this->sc.output_xoffset, this->sc.output_yoffset,
2422     + this->sc.output_width, this->sc.output_height,
2423     + this->cur_frame->xv_width, this->cur_frame->xv_height, 0);
2424     + } else {
2425     + xcb_xv_put_image(this->connection, this->xv_port, this->window, this->gc,
2426     + this->cur_frame->xv_format,
2427     + this->sc.displayed_xoffset, this->sc.displayed_yoffset,
2428     + this->sc.displayed_width, this->sc.displayed_height,
2429     + this->sc.output_xoffset, this->sc.output_yoffset,
2430     + this->sc.output_width, this->sc.output_height,
2431     + this->cur_frame->xv_width, this->cur_frame->xv_height,
2432     + this->cur_frame->xv_data_size, this->cur_frame->image);
2433     + }
2434     +
2435     + if(this->xoverlay)
2436     + xcbosd_expose(this->xoverlay);
2437     +
2438     + xcb_flush(this->connection);
2439     + pthread_mutex_unlock(&this->main_mutex);
2440     + }
2441     + }
2442     + break;
2443     +
2444     + case XINE_GUI_SEND_DRAWABLE_CHANGED:
2445     + pthread_mutex_lock(&this->main_mutex);
2446     + this->window = (xcb_window_t) data;
2447     + xcb_free_gc(this->connection, this->gc);
2448     + this->gc = xcb_generate_id(this->connection);
2449     + xcb_create_gc(this->connection, this->gc, this->window, 0, NULL);
2450     + if(this->xoverlay)
2451     + xcbosd_drawable_changed(this->xoverlay, this->window);
2452     + this->ovl_changed = 1;
2453     + pthread_mutex_unlock(&this->main_mutex);
2454     + this->sc.force_redraw = 1;
2455     + break;
2456     +
2457     + case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO:
2458     + {
2459     + int x1, y1, x2, y2;
2460     + x11_rectangle_t *rect = data;
2461     +
2462     + _x_vo_scale_translate_gui2video(&this->sc, rect->x, rect->y,
2463     + &x1, &y1);
2464     + _x_vo_scale_translate_gui2video(&this->sc, rect->x + rect->w, rect->y + rect->h,
2465     + &x2, &y2);
2466     + rect->x = x1;
2467     + rect->y = y1;
2468     + rect->w = x2-x1;
2469     + rect->h = y2-y1;
2470     +
2471     + /* onefield_xv divide by 2 the number of lines */
2472     + if (this->deinterlace_enabled
2473     + && (this->deinterlace_method == DEINTERLACE_ONEFIELDXV)
2474     + && (this->cur_frame->format == XINE_IMGFMT_YV12)) {
2475     + rect->y = rect->y * 2;
2476     + rect->h = rect->h * 2;
2477     + }
2478     +
2479     + }
2480     + break;
2481     +
2482     + default:
2483     + return -1;
2484     + }
2485     +
2486     + return 0;
2487     +}
2488     +
2489     +static void xv_store_port_attribute(xv_driver_t *this, char *name) {
2490     + xv_portattribute_t *attr;
2491     +
2492     + xcb_intern_atom_cookie_t atom_cookie;
2493     + xcb_intern_atom_reply_t *atom_reply;
2494     +
2495     + xcb_xv_get_port_attribute_cookie_t get_attribute_cookie;
2496     + xcb_xv_get_port_attribute_reply_t *get_attribute_reply;
2497     +
2498     + attr = (xv_portattribute_t *)malloc( sizeof(xv_portattribute_t) );
2499     + attr->name = strdup(name);
2500     +
2501     + pthread_mutex_lock(&this->main_mutex);
2502     + atom_cookie = xcb_intern_atom(this->connection, 0, strlen(attr->name), attr->name);
2503     + atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL);
2504     + get_attribute_cookie = xcb_xv_get_port_attribute(this->connection, this->xv_port, atom_reply->atom);
2505     + get_attribute_reply = xcb_xv_get_port_attribute_reply(this->connection, get_attribute_cookie, NULL);
2506     + attr->value = get_attribute_reply->value;
2507     + free(atom_reply);
2508     + free(get_attribute_reply);
2509     + pthread_mutex_unlock(&this->main_mutex);
2510     +
2511     + xine_list_push_back (this->port_attributes, attr);
2512     +}
2513     +
2514     +static void xv_restore_port_attributes(xv_driver_t *this) {
2515     + xine_list_iterator_t ite;
2516     +
2517     + xcb_intern_atom_cookie_t atom_cookie;
2518     + xcb_intern_atom_reply_t *atom_reply;
2519     +
2520     + while ((ite = xine_list_front(this->port_attributes)) != NULL) {
2521     + xv_portattribute_t *attr = xine_list_get_value(this->port_attributes, ite);
2522     + xine_list_remove (this->port_attributes, ite);
2523     +
2524     + pthread_mutex_lock(&this->main_mutex);
2525     + atom_cookie = xcb_intern_atom(this->connection, 0, strlen(attr->name), attr->name);
2526     + atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL);
2527     + xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, attr->value);
2528     + free(atom_reply);
2529     + pthread_mutex_unlock(&this->main_mutex);
2530     +
2531     + free( attr->name );
2532     + free( attr );
2533     + }
2534     +
2535     + pthread_mutex_lock(&this->main_mutex);
2536     + xcb_flush(this->connection);
2537     + pthread_mutex_unlock(&this->main_mutex);
2538     +
2539     + xine_list_delete( this->port_attributes );
2540     +}
2541     +
2542     +static void xv_dispose (vo_driver_t *this_gen) {
2543     + xv_driver_t *this = (xv_driver_t *) this_gen;
2544     + int i;
2545     +
2546     + /* restore port attributes to their initial values */
2547     + xv_restore_port_attributes(this);
2548     +
2549     + if (this->deinterlace_frame.image) {
2550     + pthread_mutex_lock(&this->main_mutex);
2551     + dispose_ximage(this, &this->deinterlace_frame);
2552     + pthread_mutex_unlock(&this->main_mutex);
2553     + }
2554     +
2555     + pthread_mutex_lock(&this->main_mutex);
2556     + xcb_xv_ungrab_port(this->connection, this->xv_port, XCB_CURRENT_TIME);
2557     + xcb_free_gc(this->connection, this->gc);
2558     + pthread_mutex_unlock(&this->main_mutex);
2559     +
2560     + for( i=0; i < VO_NUM_RECENT_FRAMES; i++ ) {
2561     + if( this->recent_frames[i] )
2562     + this->recent_frames[i]->vo_frame.dispose
2563     + (&this->recent_frames[i]->vo_frame);
2564     + this->recent_frames[i] = NULL;
2565     + }
2566     +
2567     + if( this->xoverlay ) {
2568     + pthread_mutex_lock(&this->main_mutex);
2569     + xcbosd_destroy(this->xoverlay);
2570     + pthread_mutex_unlock(&this->main_mutex);
2571     + }
2572     +
2573     + pthread_mutex_destroy(&this->main_mutex);
2574     +
2575     + _x_alphablend_free(&this->alphablend_extra_data);
2576     +
2577     + free (this);
2578     +}
2579     +
2580     +static int xv_check_yv12(xcb_connection_t *connection, xcb_xv_port_t port) {
2581     + xcb_xv_list_image_formats_cookie_t list_formats_cookie;
2582     + xcb_xv_list_image_formats_reply_t *list_formats_reply;
2583     +
2584     + xcb_xv_image_format_info_iterator_t format_it;
2585     +
2586     + list_formats_cookie = xcb_xv_list_image_formats(connection, port);
2587     + list_formats_reply = xcb_xv_list_image_formats_reply(connection, list_formats_cookie, NULL);
2588     + format_it = xcb_xv_list_image_formats_format_iterator(list_formats_reply);
2589     +
2590     + for (; format_it.rem; xcb_xv_image_format_info_next(&format_it))
2591     + if ((format_it.data->id == XINE_IMGFMT_YV12) &&
2592     + (! (strcmp ((char *) format_it.data->guid, "YV12")))) {
2593     + free(list_formats_reply);
2594     + return 0;
2595     + }
2596     +
2597     + free(list_formats_reply);
2598     + return 1;
2599     +}
2600     +
2601     +static void xv_check_capability (xv_driver_t *this,
2602     + int property, xcb_xv_attribute_info_t *attr,
2603     + int base_id,
2604     + char *config_name,
2605     + char *config_desc,
2606     + char *config_help) {
2607     + int int_default;
2608     + cfg_entry_t *entry;
2609     + char *str_prop = xcb_xv_attribute_info_name(attr);
2610     +
2611     + xcb_xv_get_port_attribute_cookie_t get_attribute_cookie;
2612     + xcb_xv_get_port_attribute_reply_t *get_attribute_reply;
2613     +
2614     + xcb_intern_atom_cookie_t atom_cookie;
2615     + xcb_intern_atom_reply_t *atom_reply;
2616     +
2617     + /*
2618     + * some Xv drivers (Gatos ATI) report some ~0 as max values, this is confusing.
2619     + */
2620     + if (VO_PROP_COLORKEY && (attr->max == ~0))
2621     + attr->max = 2147483615;
2622     +
2623     + atom_cookie = xcb_intern_atom(this->connection, 0, strlen(str_prop), str_prop);
2624     + atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL);
2625     +
2626     + this->props[property].min = attr->min;
2627     + this->props[property].max = attr->max;
2628     + this->props[property].atom = atom_reply->atom;
2629     +
2630     + free(atom_reply);
2631     +
2632     + get_attribute_cookie = xcb_xv_get_port_attribute(this->connection, this->xv_port, this->props[property].atom);
2633     + get_attribute_reply = xcb_xv_get_port_attribute_reply(this->connection, get_attribute_cookie, NULL);
2634     +
2635     + int_default = get_attribute_reply->value;
2636     +
2637     + free(get_attribute_reply);
2638     +
2639     + xprintf(this->xine, XINE_VERBOSITY_DEBUG,
2640     + "video_out_xv: port attribute %s (%d) value is %d\n", str_prop, property, int_default);
2641     +
2642     + /* disable autopaint colorkey by default */
2643     + /* might be overridden using config entry */
2644     + if(strcmp(str_prop, "XV_AUTOPAINT_COLORKEY") == 0)
2645     + int_default = 0;
2646     +
2647     + if (config_name) {
2648     + /* is this a boolean property ? */
2649     + if ((attr->min == 0) && (attr->max == 1)) {
2650     + this->config->register_bool (this->config, config_name, int_default,
2651     + config_desc,
2652     + config_help, 20, xv_property_callback, &this->props[property]);
2653     +
2654     + } else {
2655     + this->config->register_range (this->config, config_name, int_default,
2656     + this->props[property].min, this->props[property].max,
2657     + config_desc,
2658     + config_help, 20, xv_property_callback, &this->props[property]);
2659     + }
2660     +
2661     + entry = this->config->lookup_entry (this->config, config_name);
2662     +
2663     + if((entry->num_value < this->props[property].min) ||
2664     + (entry->num_value > this->props[property].max)) {
2665     +
2666     + this->config->update_num(this->config, config_name,
2667     + ((this->props[property].min + this->props[property].max) >> 1));
2668     +
2669     + entry = this->config->lookup_entry (this->config, config_name);
2670     + }
2671     +
2672     + this->props[property].entry = entry;
2673     +
2674     + xv_set_property (&this->vo_driver, property, entry->num_value);
2675     +
2676     + if (strcmp(str_prop, "XV_COLORKEY") == 0) {
2677     + this->use_colorkey |= 1;
2678     + this->colorkey = entry->num_value;
2679     + } else if(strcmp(str_prop, "XV_AUTOPAINT_COLORKEY") == 0) {
2680     + if(entry->num_value==1)
2681     + this->use_colorkey |= 2; /* colorkey is autopainted */
2682     + }
2683     + } else
2684     + this->props[property].value = int_default;
2685     +
2686     +}
2687     +
2688     +static void xv_update_deinterlace(void *this_gen, xine_cfg_entry_t *entry) {
2689     + xv_driver_t *this = (xv_driver_t *) this_gen;
2690     +
2691     + this->deinterlace_method = entry->num_value;
2692     +}
2693     +
2694     +static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) {
2695     + xv_driver_t *this = (xv_driver_t *) this_gen;
2696     + int xv_filter;
2697     +
2698     + xcb_intern_atom_cookie_t atom_cookie;
2699     + xcb_intern_atom_reply_t *atom_reply;
2700     +
2701     + xv_filter = entry->num_value;
2702     +
2703     + pthread_mutex_lock(&this->main_mutex);
2704     + atom_cookie = xcb_intern_atom(this->connection, 0, sizeof("XV_FILTER"), "XV_FILTER");
2705     + atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL);
2706     + xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, xv_filter);
2707     + free(atom_reply);
2708     + pthread_mutex_unlock(&this->main_mutex);
2709     +
2710     + xprintf(this->xine, XINE_VERBOSITY_DEBUG,
2711     + "video_out_xv: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter);
2712     +}
2713     +
2714     +static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) {
2715     + xv_driver_t *this = (xv_driver_t *) this_gen;
2716     + int xv_double_buffer;
2717     +
2718     + xcb_intern_atom_cookie_t atom_cookie;
2719     + xcb_intern_atom_reply_t *atom_reply;
2720     +
2721     + xv_double_buffer = entry->num_value;
2722     +
2723     + pthread_mutex_lock(&this->main_mutex);
2724     + atom_cookie = xcb_intern_atom(this->connection, 0, sizeof("XV_DOUBLE_BUFFER"), "XV_DOUBLE_BUFFER");
2725     + atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL);
2726     + xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, xv_double_buffer);
2727     + free(atom_reply);
2728     + pthread_mutex_unlock(&this->main_mutex);
2729     +
2730     + xprintf(this->xine, XINE_VERBOSITY_DEBUG,
2731     + "video_out_xv: double buffering mode = %d\n", xv_double_buffer);
2732     +}
2733     +
2734     +static void xv_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) {
2735     + xv_driver_t *this = (xv_driver_t *) this_gen;
2736     +
2737     + this->use_pitch_alignment = entry->num_value;
2738     +}
2739     +
2740     +static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *visual_gen) {
2741     + xv_class_t *class = (xv_class_t *) class_gen;
2742     + config_values_t *config = class->config;
2743     + xv_driver_t *this;
2744     + int i;
2745     + xcb_visual_t *visual = (xcb_visual_t *) visual_gen;
2746     + unsigned int j;
2747     + xcb_xv_port_t xv_port;
2748     +
2749     + const xcb_query_extension_reply_t *query_extension_reply;
2750     +
2751     + xcb_xv_query_adaptors_cookie_t query_adaptors_cookie;
2752     + xcb_xv_query_adaptors_reply_t *query_adaptors_reply;
2753     + xcb_xv_query_port_attributes_cookie_t query_attributes_cookie;
2754     + xcb_xv_query_port_attributes_reply_t *query_attributes_reply;
2755     + xcb_xv_list_image_formats_cookie_t list_formats_cookie;
2756     + xcb_xv_list_image_formats_reply_t *list_formats_reply;
2757     +
2758     + xcb_xv_adaptor_info_iterator_t adaptor_it;
2759     + xcb_xv_image_format_info_iterator_t format_it;
2760     +
2761     + this = (xv_driver_t *) xine_xmalloc (sizeof (xv_driver_t));
2762     + if (!this)
2763     + return NULL;
2764     +
2765     + pthread_mutex_init(&this->main_mutex, NULL);
2766     +
2767     + _x_alphablend_init(&this->alphablend_extra_data, class->xine);
2768     +
2769     + this->connection = visual->connection;
2770     + this->screen = visual->screen;
2771     + this->window = visual->window;
2772     + this->config = config;
2773     +
2774     + /*
2775     + * check for Xvideo support
2776     + */
2777     +
2778     + query_extension_reply = xcb_get_extension_data(this->connection, &xcb_xv_id);
2779     + if (!query_extension_reply || !query_extension_reply->present) {
2780     + xprintf (class->xine, XINE_VERBOSITY_LOG, _("video_out_xv: Xv extension not present.\n"));
2781     + return NULL;
2782     + }
2783     +
2784     + /*
2785     + * check adaptors, search for one that supports (at least) yuv12
2786     + */
2787     +
2788     + query_adaptors_cookie = xcb_xv_query_adaptors(this->connection, this->window);
2789     + query_adaptors_reply = xcb_xv_query_adaptors_reply(this->connection, query_adaptors_cookie, NULL);
2790     +
2791     + if (!query_adaptors_reply) {
2792     + xprintf(class->xine, XINE_VERBOSITY_DEBUG, "video_out_xv: XvQueryAdaptors failed.\n");
2793     + return NULL;
2794     + }
2795     +
2796     + adaptor_it = xcb_xv_query_adaptors_info_iterator(query_adaptors_reply);
2797     +
2798     + xv_port = 0;
2799     +
2800     + for (; adaptor_it.rem && !xv_port; xcb_xv_adaptor_info_next(&adaptor_it)) {
2801     +
2802     + if (adaptor_it.data->type & XCB_XV_TYPE_IMAGE_MASK) {
2803     +
2804     + for (j = 0; j < adaptor_it.data->num_ports; j++)
2805     + if (!xv_check_yv12(this->connection, adaptor_it.data->base_id + j)) {
2806     + xcb_xv_grab_port_cookie_t grab_port_cookie;
2807     + xcb_xv_grab_port_reply_t *grab_port_reply;
2808     + grab_port_cookie = xcb_xv_grab_port(this->connection, adaptor_it.data->base_id + j, XCB_CURRENT_TIME);
2809     + grab_port_reply = xcb_xv_grab_port_reply(this->connection, grab_port_cookie, NULL);
2810     + if (grab_port_reply && (grab_port_reply->result == XCB_GRAB_STATUS_SUCCESS)) {
2811     + free(grab_port_reply);
2812     + xv_port = adaptor_it.data->base_id + j;
2813     + break;
2814     + }
2815     + free(grab_port_reply);
2816     + }
2817     + }
2818     + }
2819     +
2820     + if (!xv_port) {
2821     + xprintf(class->xine, XINE_VERBOSITY_LOG,
2822     + _("video_out_xv: Xv extension is present but I couldn't find a usable yuv12 port.\n"
2823     + " Looks like your graphics hardware driver doesn't support Xv?!\n"));
2824     +
2825     + /* XvFreeAdaptorInfo (adaptor_info); this crashed on me (gb)*/
2826     + return NULL;
2827     + }
2828     + else
2829     + xprintf(class->xine, XINE_VERBOSITY_LOG,
2830     + _("video_out_xv: using Xv port %d from adaptor %s for hardware "
2831     + "colorspace conversion and scaling.\n"), xv_port,
2832     + xcb_xv_adaptor_info_name(adaptor_it.data));
2833     +
2834     + this->xv_port = xv_port;
2835     +
2836     + _x_vo_scale_init (&this->sc, 1, 0, config );
2837     + this->sc.frame_output_cb = visual->frame_output_cb;
2838     + this->sc.user_data = visual->user_data;
2839     +
2840     + this->gc = xcb_generate_id(this->connection);
2841     + xcb_create_gc(this->connection, this->gc, this->window, 0, NULL);
2842     + this->capabilities = VO_CAP_CROP;
2843     + this->use_shm = 1;
2844     + this->deinterlace_method = 0;
2845     + this->deinterlace_frame.image = NULL;
2846     + this->use_colorkey = 0;
2847     + this->colorkey = 0;
2848     + this->xoverlay = NULL;
2849     + this->ovl_changed = 0;
2850     + this->xine = class->xine;
2851     +
2852     + this->vo_driver.get_capabilities = xv_get_capabilities;
2853     + this->vo_driver.alloc_frame = xv_alloc_frame;
2854     + this->vo_driver.update_frame_format = xv_update_frame_format;
2855     + this->vo_driver.overlay_begin = xv_overlay_begin;
2856     + this->vo_driver.overlay_blend = xv_overlay_blend;
2857     + this->vo_driver.overlay_end = xv_overlay_end;
2858     + this->vo_driver.display_frame = xv_display_frame;
2859     + this->vo_driver.get_property = xv_get_property;
2860     + this->vo_driver.set_property = xv_set_property;
2861     + this->vo_driver.get_property_min_max = xv_get_property_min_max;
2862     + this->vo_driver.gui_data_exchange = xv_gui_data_exchange;
2863     + this->vo_driver.dispose = xv_dispose;
2864     + this->vo_driver.redraw_needed = xv_redraw_needed;
2865     +
2866     + /*
2867     + * init properties
2868     + */
2869     +
2870     + for (i = 0; i < VO_NUM_PROPERTIES; i++) {
2871     + this->props[i].value = 0;
2872     + this->props[i].min = 0;
2873     + this->props[i].max = 0;
2874     + this->props[i].atom = XCB_NONE;
2875     + this->props[i].entry = NULL;
2876     + this->props[i].this = this;
2877     + }
2878     +
2879     + this->props[VO_PROP_INTERLACED].value = 0;
2880     + this->sc.user_ratio =
2881     + this->props[VO_PROP_ASPECT_RATIO].value = XINE_VO_ASPECT_AUTO;
2882     + this->props[VO_PROP_ZOOM_X].value = 100;
2883     + this->props[VO_PROP_ZOOM_Y].value = 100;
2884     +
2885     + /*
2886     + * check this adaptor's capabilities
2887     + */
2888     + this->port_attributes = xine_list_new();
2889     +
2890     + query_attributes_cookie = xcb_xv_query_port_attributes(this->connection, xv_port);
2891     + query_attributes_reply = xcb_xv_query_port_attributes_reply(this->connection, query_attributes_cookie, NULL);
2892     + if(query_attributes_reply) {
2893     + xcb_xv_attribute_info_iterator_t attribute_it;
2894     + attribute_it = xcb_xv_query_port_attributes_attributes_iterator(query_attributes_reply);
2895     +
2896     + for (; attribute_it.rem; xcb_xv_attribute_info_next(&attribute_it)) {
2897     + if ((attribute_it.data->flags & XCB_XV_ATTRIBUTE_FLAG_SETTABLE) && (attribute_it.data->flags & XCB_XV_ATTRIBUTE_FLAG_GETTABLE)) {
2898     + /* store initial port attribute value */
2899     + xv_store_port_attribute(this, xcb_xv_attribute_info_name(attribute_it.data));
2900     +
2901     + if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_HUE")) {
2902     + if (!strncmp(xcb_xv_adaptor_info_name(adaptor_it.data), "NV", 2)) {
2903     + xprintf (this->xine, XINE_VERBOSITY_NONE, "video_out_xv: ignoring broken XV_HUE settings on NVidia cards");
2904     + } else {
2905     + xv_check_capability (this, VO_PROP_HUE, attribute_it.data,
2906     + adaptor_it.data->base_id,
2907     + NULL, NULL, NULL);
2908     + }
2909     + } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_SATURATION")) {
2910     + xv_check_capability (this, VO_PROP_SATURATION, attribute_it.data,
2911     + adaptor_it.data->base_id,
2912     + NULL, NULL, NULL);
2913     +
2914     + } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_BRIGHTNESS")) {
2915     + xv_check_capability (this, VO_PROP_BRIGHTNESS, attribute_it.data,
2916     + adaptor_it.data->base_id,
2917     + NULL, NULL, NULL);
2918     +
2919     + } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_CONTRAST")) {
2920     + xv_check_capability (this, VO_PROP_CONTRAST, attribute_it.data,
2921     + adaptor_it.data->base_id,
2922     + NULL, NULL, NULL);
2923     +
2924     + } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_COLORKEY")) {
2925     + xv_check_capability (this, VO_PROP_COLORKEY, attribute_it.data,
2926     + adaptor_it.data->base_id,
2927     + "video.device.xv_colorkey",
2928     + _("video overlay colour key"),
2929     + _("The colour key is used to tell the graphics card where to "
2930     + "overlay the video image. Try different values, if you experience "
2931     + "windows becoming transparent."));
2932     +
2933     + } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_AUTOPAINT_COLORKEY")) {
2934     + xv_check_capability (this, VO_PROP_AUTOPAINT_COLORKEY, attribute_it.data,
2935     + adaptor_it.data->base_id,
2936     + "video.device.xv_autopaint_colorkey",
2937     + _("autopaint colour key"),
2938     + _("Make Xv autopaint its colorkey."));
2939     +
2940     + } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_FILTER")) {
2941     + int xv_filter;
2942     + /* This setting is specific to Permedia 2/3 cards. */
2943     + xv_filter = config->register_range (config, "video.device.xv_filter", 0,
2944     + attribute_it.data->min, attribute_it.data->max,
2945     + _("bilinear scaling mode"),
2946     + _("Selects the bilinear scaling mode for Permedia cards. "
2947     + "The individual values are:\n\n"
2948     + "Permedia 2\n"
2949     + "0 - disable bilinear filtering\n"
2950     + "1 - enable bilinear filtering\n\n"
2951     + "Permedia 3\n"
2952     + "0 - disable bilinear filtering\n"
2953     + "1 - horizontal linear filtering\n"
2954     + "2 - enable full bilinear filtering"),
2955     + 20, xv_update_XV_FILTER, this);
2956     + config->update_num(config,"video.device.xv_filter",xv_filter);
2957     + } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_DOUBLE_BUFFER")) {
2958     + int xv_double_buffer;
2959     + xv_double_buffer =
2960     + config->register_bool (config, "video.device.xv_double_buffer", 1,
2961     + _("enable double buffering"),
2962     + _("Double buffering will synchronize the update of the video image to the "
2963     + "repainting of the entire screen (\"vertical retrace\"). This eliminates "
2964     + "flickering and tearing artifacts, but will use more graphics memory."),
2965     + 20, xv_update_XV_DOUBLE_BUFFER, this);
2966     + config->update_num(config,"video.device.xv_double_buffer",xv_double_buffer);
2967     + }
2968     + }
2969     + }
2970     + free(query_attributes_reply);
2971     + }
2972     + else
2973     + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_xv: no port attributes defined.\n");
2974     + free(query_adaptors_reply);
2975     +
2976     + /*
2977     + * check supported image formats
2978     + */
2979     +
2980     + list_formats_cookie = xcb_xv_list_image_formats(this->connection, xv_port);
2981     + list_formats_reply = xcb_xv_list_image_formats_reply(this->connection, list_formats_cookie, NULL);
2982     +
2983     + format_it = xcb_xv_list_image_formats_format_iterator(list_formats_reply);
2984     +
2985     + this->xv_format_yv12 = 0;
2986     + this->xv_format_yuy2 = 0;
2987     +
2988     + for (; format_it.rem; xcb_xv_image_format_info_next(&format_it)) {
2989     + lprintf ("Xv image format: 0x%x (%4.4s) %s\n",
2990     + format_it.data->id, (char*)&format_it.data->id,
2991     + (format_it.data->format == XvPacked) ? "packed" : "planar");
2992     +
2993     + if (format_it.data->id == XINE_IMGFMT_YV12) {
2994     + this->xv_format_yv12 = format_it.data->id;
2995     + this->capabilities |= VO_CAP_YV12;
2996     + xprintf(this->xine, XINE_VERBOSITY_LOG,
2997     + _("video_out_xv: this adaptor supports the yv12 format.\n"));
2998     + } else if (format_it.data->id == XINE_IMGFMT_YUY2) {
2999     + this->xv_format_yuy2 = format_it.data->id;
3000     + this->capabilities |= VO_CAP_YUY2;
3001     + xprintf(this->xine, XINE_VERBOSITY_LOG,
3002     + _("video_out_xv: this adaptor supports the yuy2 format.\n"));
3003     + }
3004     + }
3005     +
3006     + free(list_formats_reply);
3007     +
3008     + this->use_pitch_alignment =
3009     + config->register_bool (config, "video.device.xv_pitch_alignment", 0,
3010     + _("pitch alignment workaround"),
3011     + _("Some buggy video drivers need a workaround to function properly."),
3012     + 10, xv_update_xv_pitch_alignment, this);
3013     +
3014     + this->deinterlace_method =
3015     + config->register_enum (config, "video.output.xv_deinterlace_method", 4,
3016     + deinterlace_methods,
3017     + _("deinterlace method (deprecated)"),
3018     + _("This config setting is deprecated. You should use the new deinterlacing "
3019     + "post processing settings instead.\n\n"
3020     + "From the old days of analog television, where the even and odd numbered "
3021     + "lines of a video frame would be displayed at different times comes the "
3022     + "idea to increase motion smoothness by also recording the lines at "
3023     + "different times. This is called \"interlacing\". But unfortunately, "
3024     + "todays displays show the even and odd numbered lines as one complete frame "
3025     + "all at the same time (called \"progressive display\"), which results in "
3026     + "ugly frame errors known as comb artifacts. Software deinterlacing is an "
3027     + "approach to reduce these artifacts. The individual values are:\n\n"
3028     + "none\n"
3029     + "Disables software deinterlacing.\n\n"
3030     + "bob\n"
3031     + "Interpolates between the lines for moving parts of the image.\n\n"
3032     + "weave\n"
3033     + "Similar to bob, but with a tendency to preserve the full resolution, "
3034     + "better for high detail in low movement scenes.\n\n"
3035     + "greedy\n"
3036     + "Very good adaptive deinterlacer, but needs a lot of CPU power.\n\n"
3037     + "onefield\n"
3038     + "Always interpolates and reduces vertical resolution.\n\n"
3039     + "onefieldxv\n"
3040     + "Same as onefield, but does the interpolation in hardware.\n\n"
3041     + "linearblend\n"
3042     + "Applies a slight vertical blur to remove the comb artifacts. Good results "
3043     + "with medium CPU usage."),
3044     + 10, xv_update_deinterlace, this);
3045     + this->deinterlace_enabled = 0;
3046     +
3047     + if(this->use_colorkey==1) {
3048     + this->xoverlay = xcbosd_create(this->xine, this->connection, this->screen,
3049     + this->window, XCBOSD_COLORKEY);
3050     + if(this->xoverlay)
3051     + xcbosd_colorkey(this->xoverlay, this->colorkey, &this->sc);
3052     + } else {
3053     + this->xoverlay = xcbosd_create(this->xine, this->connection, this->screen,
3054     + this->window, XCBOSD_SHAPED);
3055     + }
3056     +
3057     + if( this->xoverlay )
3058     + this->capabilities |= VO_CAP_UNSCALED_OVERLAY;
3059     +
3060     + return &this->vo_driver;
3061     +}
3062     +
3063     +/*
3064     + * class functions
3065     + */
3066     +
3067     +static char* get_identifier (video_driver_class_t *this_gen) {
3068     + return "Xv";
3069     +}
3070     +
3071     +static char* get_description (video_driver_class_t *this_gen) {
3072     + return _("xine video output plugin using the MIT X video extension");
3073     +}
3074     +
3075     +static void dispose_class (video_driver_class_t *this_gen) {
3076     + xv_class_t *this = (xv_class_t *) this_gen;
3077     +
3078     + free (this);
3079     +}
3080     +
3081     +static void *init_class (xine_t *xine, void *visual_gen) {
3082     + xv_class_t *this = (xv_class_t *) xine_xmalloc (sizeof (xv_class_t));
3083     +
3084     + this->driver_class.open_plugin = open_plugin;
3085     + this->driver_class.get_identifier = get_identifier;
3086     + this->driver_class.get_description = get_description;
3087     + this->driver_class.dispose = dispose_class;
3088     +
3089     + this->config = xine->config;
3090     + this->xine = xine;
3091     +
3092     + return this;
3093     +}
3094     +
3095     +static const vo_info_t vo_info_xv = {
3096     + 9, /* priority */
3097     + XINE_VISUAL_TYPE_XCB /* visual type */
3098     +};
3099     +
3100     +/*
3101     + * exported plugin catalog entry
3102     + */
3103     +
3104     +const plugin_info_t xine_plugin_info[] EXPORTED = {
3105     + /* type, API, "name", version, special_info, init_function */
3106     + { PLUGIN_VIDEO_OUT, 21, "xv", XINE_VERSION_CODE, &vo_info_xv, init_class },
3107     + { PLUGIN_NONE, 0, "", 0, NULL, NULL }
3108     +};
3109     +
3110     +#endif
3111     Index: src/video_out/video_out_xshm.c
3112     ===================================================================
3113     RCS file: /cvsroot/xine/xine-lib/src/video_out/video_out_xshm.c,v
3114     retrieving revision 1.148
3115     diff -u -B -r1.148 video_out_xshm.c
3116     --- src/video_out/video_out_xshm.c 28 Oct 2006 18:51:08 -0000 1.148
3117     +++ src/video_out/video_out_xshm.c 7 Feb 2007 02:41:42 -0000
3118     @@ -87,7 +87,6 @@
3119    
3120     yuv2rgb_t *yuv2rgb; /* yuv2rgb converter set up for this frame */
3121     uint8_t *rgb_dst;
3122     - int yuv_stride;
3123    
3124     } xshm_frame_t;
3125    
3126     @@ -105,8 +104,6 @@
3127     int use_shm;
3128     XColor black;
3129    
3130     - int yuv2rgb_mode;
3131     - int yuv2rgb_swap;
3132     int yuv2rgb_brightness;
3133     int yuv2rgb_contrast;
3134     int yuv2rgb_saturation;
3135     @@ -585,7 +582,6 @@
3136     frame->sc.output_width,
3137     frame->sc.output_height,
3138     frame->image->bytes_per_line*2);
3139     - frame->yuv_stride = frame->image->bytes_per_line*2;
3140     break;
3141     case VO_BOTH_FIELDS:
3142     frame->yuv2rgb->configure (frame->yuv2rgb,
3143     @@ -596,7 +592,6 @@
3144     frame->sc.output_width,
3145     frame->sc.output_height,
3146     frame->image->bytes_per_line);
3147     - frame->yuv_stride = frame->image->bytes_per_line;
3148     break;
3149     }
3150     }
3151     @@ -1255,8 +1250,6 @@
3152     return NULL;
3153     }
3154    
3155     - this->yuv2rgb_mode = mode;
3156     - this->yuv2rgb_swap = swapped;
3157     this->yuv2rgb_brightness = 0;
3158     this->yuv2rgb_contrast = 128;
3159     this->yuv2rgb_saturation = 128;
3160     Index: src/video_out/xcbosd.c
3161     ===================================================================
3162     RCS file: src/video_out/xcbosd.c
3163     diff -N src/video_out/xcbosd.c
3164     --- /dev/null 1 Jan 1970 00:00:00 -0000
3165     +++ src/video_out/xcbosd.c 7 Feb 2007 02:41:42 -0000
3166     @@ -0,0 +1,546 @@
3167     +/*
3168     + * Copyright (C) 2003, 2007 the xine project
3169     + *
3170     + * This file is part of xine, a free video player.
3171     + *
3172     + * xine is free software; you can redistribute it and/or modify
3173     + * it under the terms of the GNU General Public License as published by
3174     + * the Free Software Foundation; either version 2 of the License, or
3175     + * (at your option) any later version.
3176     + *
3177     + * xine is distributed in the hope that it will be useful,
3178     + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3179     + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3180     + * GNU General Public License for more details.
3181     + *
3182     + * You should have received a copy of the GNU General Public License
3183     + * along with this program; if not, write to the Free Software
3184     + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
3185     + *
3186     + * $Id: xine-lib-1.1.4-xcb.patch,v 1.1 2007-05-08 20:43:46 niro Exp $
3187     + *
3188     + * xcbosd.c, use X11 Nonrectangular Window Shape Extension to draw xine OSD
3189     + *
3190     + * Nov 2003 - Miguel Freitas
3191     + * Feb 2007 - ported to xcb by Christoph Pfister
3192     + *
3193     + * based on ideas and code of
3194     + * xosd Copyright (c) 2000 Andre Renaud (andre@ignavus.net)
3195     + *
3196     + * colorkey support by Yann Vernier
3197     + */
3198     +
3199     +#include <stdarg.h>
3200     +#include <stdio.h>
3201     +#include <stdlib.h>
3202     +#include <string.h>
3203     +#include <unistd.h>
3204     +#include <signal.h>
3205     +#include <time.h>
3206     +
3207     +#include <assert.h>
3208     +
3209     +#include <netinet/in.h>
3210     +
3211     +#include <xcb/shape.h>
3212     +
3213     +#define LOG_MODULE "xcbosd"
3214     +#define LOG_VERBOSE
3215     +
3216     +/*
3217     +#define LOG
3218     +*/
3219     +
3220     +#include "xine_internal.h"
3221     +#include "xcbosd.h"
3222     +
3223     +struct xcbosd
3224     +{
3225     + xcb_connection_t *connection;
3226     + xcb_screen_t *screen;
3227     + enum xcbosd_mode mode;
3228     +
3229     + union {
3230     + struct {
3231     + xcb_window_t window;
3232     + xcb_pixmap_t mask_bitmap;
3233     + xcb_gc_t mask_gc;
3234     + xcb_gc_t mask_gc_back;
3235     + int mapped;
3236     + } shaped;
3237     + struct {
3238     + uint32_t colorkey;
3239     + vo_scale_t *sc;
3240     + } colorkey;
3241     + } u;
3242     + xcb_window_t window;
3243     + unsigned int depth;
3244     + xcb_pixmap_t bitmap;
3245     + xcb_visualid_t visual;
3246     + xcb_colormap_t cmap;
3247     +
3248     + xcb_gc_t gc;
3249     +
3250     + int width;
3251     + int height;
3252     + int x;
3253     + int y;
3254     + enum {DRAWN, WIPED, UNDEFINED} clean;
3255     + xine_t *xine;
3256     +};
3257     +
3258     +
3259     +void xcbosd_expose(xcbosd *osd)
3260     +{
3261     + assert (osd);
3262     +
3263     + lprintf("expose (state:%d)\n", osd->clean );
3264     +
3265     + switch (osd->mode) {
3266     + case XCBOSD_SHAPED:
3267     + xcb_shape_mask(osd->connection, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING,
3268     + osd->u.shaped.window, 0, 0, osd->u.shaped.mask_bitmap);
3269     + if( osd->clean==DRAWN ) {
3270     +
3271     + if( !osd->u.shaped.mapped ) {
3272     + unsigned int stack_mode = XCB_STACK_MODE_ABOVE;
3273     + xcb_configure_window(osd->connection, osd->u.shaped.window, XCB_CONFIG_WINDOW_STACK_MODE, &stack_mode);
3274     + xcb_map_window(osd->connection, osd->u.shaped.window);
3275     + }
3276     + osd->u.shaped.mapped = 1;
3277     +
3278     + xcb_copy_area(osd->connection, osd->bitmap, osd->u.shaped.window,
3279     + osd->gc, 0, 0, 0, 0, osd->width, osd->height);
3280     + } else {
3281     + if( osd->u.shaped.mapped )
3282     + xcb_unmap_window(osd->connection, osd->u.shaped.window);
3283     + osd->u.shaped.mapped = 0;
3284     + }
3285     + break;
3286     + case XCBOSD_COLORKEY:
3287     + if( osd->clean!=UNDEFINED )
3288     + xcb_copy_area(osd->connection, osd->bitmap, osd->window, osd->gc, 0, 0,
3289     + 0, 0, osd->width, osd->height);
3290     + }
3291     +}
3292     +
3293     +
3294     +void xcbosd_resize(xcbosd *osd, int width, int height)
3295     +{
3296     + assert (osd);
3297     + assert (width);
3298     + assert (height);
3299     +
3300     + lprintf("resize old:%dx%d new:%dx%d\n", osd->width, osd->height, width, height );
3301     +
3302     + osd->width = width;
3303     + osd->height = height;
3304     +
3305     + xcb_free_pixmap(osd->connection, osd->bitmap);
3306     + switch(osd->mode) {
3307     + case XCBOSD_SHAPED: {
3308     + unsigned int window_config[] = { osd->width, osd->height };
3309     + xcb_configure_window(osd->connection, osd->u.shaped.window, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, window_config);
3310     + xcb_free_pixmap(osd->connection, osd->u.shaped.mask_bitmap);
3311     + osd->u.shaped.mask_bitmap = xcb_generate_id(osd->connection);
3312     + xcb_create_pixmap(osd->connection, 1, osd->u.shaped.mask_bitmap, osd->u.shaped.window, osd->width, osd->height);
3313     + osd->bitmap = xcb_generate_id(osd->connection);
3314     + xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->u.shaped.window, osd->width, osd->height);
3315     + break;
3316     + }
3317     + case XCBOSD_COLORKEY:
3318     + osd->bitmap = xcb_generate_id(osd->connection);
3319     + xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->window, osd->width, osd->height);
3320     + break;
3321     + }
3322     +
3323     + osd->clean = UNDEFINED;
3324     + xcbosd_clear(osd);
3325     +}
3326     +
3327     +void xcbosd_drawable_changed(xcbosd *osd, xcb_window_t window)
3328     +{
3329     + xcb_get_geometry_cookie_t get_geometry_cookie;
3330     + xcb_get_geometry_reply_t *get_geometry_reply;
3331     +
3332     + assert (osd);
3333     +
3334     + lprintf("drawable changed\n");
3335     +
3336     +/*
3337     + Do I need to recreate the GC's??
3338     +
3339     + XFreeGC (osd->display, osd->gc);
3340     + XFreeGC (osd->display, osd->mask_gc);
3341     + XFreeGC (osd->display, osd->mask_gc_back);
3342     +*/
3343     + xcb_free_pixmap(osd->connection, osd->bitmap);
3344     + xcb_free_colormap(osd->connection, osd->cmap);
3345     +
3346     + /* we need to call XSync(), because otherwise, calling XDestroyWindow()
3347     + on the parent window could destroy our OSD window twice !! */
3348     + /* XSync (osd->display, False); FIXME don't think that we need that --pfister */
3349     +
3350     + osd->window = window;
3351     +
3352     + get_geometry_cookie = xcb_get_geometry(osd->connection, osd->window);
3353     + get_geometry_reply = xcb_get_geometry_reply(osd->connection, get_geometry_cookie, NULL);
3354     + osd->depth = get_geometry_reply->depth;
3355     + osd->width = get_geometry_reply->width;
3356     + osd->height = get_geometry_reply->height;
3357     + free(get_geometry_reply);
3358     +
3359     + assert(osd->width);
3360     + assert(osd->height);
3361     +
3362     + switch(osd->mode) {
3363     + case XCBOSD_SHAPED: {
3364     + xcb_free_pixmap(osd->connection, osd->u.shaped.mask_bitmap);
3365     + xcb_destroy_window(osd->connection, osd->u.shaped.window);
3366     +
3367     + unsigned int window_params[] = { osd->screen->black_pixel, 1, XCB_EVENT_MASK_EXPOSURE };
3368     + osd->u.shaped.window = xcb_generate_id(osd->connection);
3369     + xcb_create_window(osd->connection, XCB_COPY_FROM_PARENT, osd->u.shaped.window,
3370     + osd->window, 0, 0, osd->width, osd->height, 0, XCB_COPY_FROM_PARENT,
3371     + XCB_COPY_FROM_PARENT, XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
3372     + window_params);
3373     +
3374     + osd->u.shaped.mapped = 0;
3375     +
3376     + osd->u.shaped.mask_bitmap = xcb_generate_id(osd->connection);
3377     + xcb_create_pixmap(osd->connection, 1, osd->u.shaped.mask_bitmap, osd->u.shaped.window, osd->width, osd->height);
3378     +
3379     + osd->bitmap = xcb_generate_id(osd->connection);
3380     + xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->u.shaped.window, osd->width, osd->height);
3381     +
3382     + osd->cmap = xcb_generate_id(osd->connection);
3383     + xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->u.shaped.window, osd->visual);
3384     + break;
3385     + }
3386     + case XCBOSD_COLORKEY:
3387     + osd->bitmap = xcb_generate_id(osd->connection);
3388     + xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->window, osd->width, osd->height);
3389     + osd->cmap = xcb_generate_id(osd->connection);
3390     + xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->window, osd->visual);
3391     +
3392     + break;
3393     + }
3394     +
3395     + osd->clean = UNDEFINED;
3396     + /* do not xcbosd_clear() here: osd->u.colorkey.sc has not being updated yet */
3397     +}
3398     +
3399     +xcbosd *xcbosd_create(xine_t *xine, xcb_connection_t *connection, xcb_screen_t *screen, xcb_window_t window, enum xcbosd_mode mode)
3400     +{
3401     + xcbosd *osd;
3402     +
3403     + xcb_get_geometry_cookie_t get_geometry_cookie;
3404     + xcb_get_geometry_reply_t *get_geometry_reply;
3405     +
3406     + xcb_void_cookie_t generic_cookie;
3407     + xcb_generic_error_t *generic_error;
3408     +
3409     + osd = xine_xmalloc (sizeof (xcbosd));
3410     + if (!osd)
3411     + return NULL;
3412     +
3413     + osd->mode = mode;
3414     + osd->xine = xine;
3415     + osd->connection = connection;
3416     + osd->screen = screen;
3417     + osd->window = window;
3418     +
3419     + osd->visual = osd->screen->root_visual;
3420     +
3421     + get_geometry_cookie = xcb_get_geometry(osd->connection, osd->window);
3422     + get_geometry_reply = xcb_get_geometry_reply(osd->connection, get_geometry_cookie, NULL);
3423     + osd->depth = get_geometry_reply->depth;
3424     + osd->width = get_geometry_reply->width;
3425     + osd->height = get_geometry_reply->height;
3426     + free(get_geometry_reply);
3427     +
3428     + assert(osd->width);
3429     + assert(osd->height);
3430     +
3431     + switch (mode) {
3432     + case XCBOSD_SHAPED: {
3433     + const xcb_query_extension_reply_t *query_extension_reply = xcb_get_extension_data(osd->connection, &xcb_shape_id);
3434     +
3435     + if (!query_extension_reply || !query_extension_reply->present) {
3436     + xprintf(osd->xine, XINE_VERBOSITY_LOG, _("x11osd: XShape extension not available. unscaled overlay disabled.\n"));
3437     + goto error2;
3438     + }
3439     +
3440     + unsigned int window_params[] = { osd->screen->black_pixel, 1, XCB_EVENT_MASK_EXPOSURE };
3441     + osd->u.shaped.window = xcb_generate_id(osd->connection);
3442     + generic_cookie = xcb_create_window_checked(osd->connection, XCB_COPY_FROM_PARENT, osd->u.shaped.window,
3443     + osd->window, 0, 0, osd->width, osd->height, 0, XCB_COPY_FROM_PARENT,
3444     + XCB_COPY_FROM_PARENT, XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
3445     + window_params);
3446     + generic_error = xcb_request_check(osd->connection, generic_cookie);
3447     +
3448     + if (generic_error != NULL) {
3449     + xprintf(osd->xine, XINE_VERBOSITY_LOG, _("x11osd: error creating window. unscaled overlay disabled.\n"));
3450     + free(generic_error);
3451     + goto error_window;
3452     + }
3453     +
3454     + osd->u.shaped.mask_bitmap = xcb_generate_id(osd->connection);
3455     + generic_cookie = xcb_create_pixmap_checked(osd->connection, 1, osd->u.shaped.mask_bitmap, osd->u.shaped.window, osd->width, osd->height);
3456     + generic_error = xcb_request_check(osd->connection, generic_cookie);
3457     +
3458     + if (generic_error != NULL) {
3459     + xprintf(osd->xine, XINE_VERBOSITY_LOG, _("x11osd: error creating pixmap. unscaled overlay disabled.\n"));
3460     + free(generic_error);
3461     + goto error_aftermaskbitmap;
3462     + }
3463     +
3464     + osd->bitmap = xcb_generate_id(osd->connection);
3465     + xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->u.shaped.window, osd->width, osd->height);
3466     + osd->gc = xcb_generate_id(osd->connection);
3467     + xcb_create_gc(osd->connection, osd->gc, osd->u.shaped.window, 0, NULL);
3468     +
3469     + osd->u.shaped.mask_gc = xcb_generate_id(osd->connection);
3470     + xcb_create_gc(osd->connection, osd->u.shaped.mask_gc, osd->u.shaped.mask_bitmap, XCB_GC_FOREGROUND, &osd->screen->white_pixel);
3471     +
3472     + osd->u.shaped.mask_gc_back = xcb_generate_id(osd->connection);
3473     + xcb_create_gc(osd->connection, osd->u.shaped.mask_gc_back, osd->u.shaped.mask_bitmap, XCB_GC_FOREGROUND, &osd->screen->black_pixel);
3474     +
3475     + osd->u.shaped.mapped = 0;
3476     + osd->cmap = xcb_generate_id(osd->connection);
3477     + xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->u.shaped.window, osd->visual);
3478     + break;
3479     + }
3480     + case XCBOSD_COLORKEY:
3481     + osd->bitmap = xcb_generate_id(osd->connection);
3482     + xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->window, osd->width, osd->height);
3483     + osd->gc = xcb_generate_id(osd->connection);
3484     + xcb_create_gc(osd->connection, osd->gc, osd->window, 0, NULL);
3485     + osd->cmap = xcb_generate_id(osd->connection);
3486     + xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->window, osd->visual);
3487     + /* FIXME: the expose event doesn't seem to happen? */
3488     + /*XSelectInput (osd->display, osd->window, ExposureMask);*/
3489     + break;
3490     + default:
3491     + goto error2;
3492     + }
3493     +
3494     + osd->clean = UNDEFINED;
3495     + xcbosd_expose(osd);
3496     +
3497     + xprintf(osd->xine, XINE_VERBOSITY_DEBUG,
3498     + _("x11osd: unscaled overlay created (%s mode).\n"),
3499     + (mode==XCBOSD_SHAPED) ? "XShape" : "Colorkey" );
3500     +
3501     + return osd;
3502     +
3503     +/*
3504     + XFreeGC (osd->display, osd->gc);
3505     + XFreeGC (osd->display, osd->mask_gc);
3506     + XFreeGC (osd->display, osd->mask_gc_back);
3507     +*/
3508     +
3509     +error_aftermaskbitmap:
3510     + if(mode==XCBOSD_SHAPED)
3511     + xcb_free_pixmap(osd->connection, osd->u.shaped.mask_bitmap);
3512     +error_window:
3513     + if(mode==XCBOSD_SHAPED)
3514     + xcb_destroy_window(osd->connection, osd->u.shaped.window);
3515     +error2:
3516     + free (osd);
3517     + return NULL;
3518     +}
3519     +
3520     +void xcbosd_colorkey(xcbosd *osd, uint32_t colorkey, vo_scale_t *scaling)
3521     +{
3522     + assert (osd);
3523     + assert (osd->mode==XCBOSD_COLORKEY);
3524     +
3525     + osd->u.colorkey.colorkey=colorkey;
3526     + osd->u.colorkey.sc=scaling;
3527     + osd->clean = UNDEFINED;
3528     + xcbosd_clear(osd);
3529     + xcbosd_expose(osd);
3530     +}
3531     +
3532     +void xcbosd_destroy(xcbosd *osd)
3533     +{
3534     +
3535     + assert (osd);
3536     +
3537     + xcb_free_gc(osd->connection, osd->gc);
3538     + xcb_free_pixmap(osd->connection, osd->bitmap);
3539     + xcb_free_colormap(osd->connection, osd->cmap);
3540     + if(osd->mode==XCBOSD_SHAPED) {
3541     + xcb_free_gc(osd->connection, osd->u.shaped.mask_gc);
3542     + xcb_free_gc(osd->connection, osd->u.shaped.mask_gc_back);
3543     + xcb_free_pixmap(osd->connection, osd->u.shaped.mask_bitmap);
3544     + xcb_destroy_window(osd->connection, osd->u.shaped.window);
3545     + }
3546     +
3547     + free (osd);
3548     +}
3549     +
3550     +void xcbosd_clear(xcbosd *osd)
3551     +{
3552     + int i;
3553     +
3554     + lprintf("clear (state:%d)\n", osd->clean );
3555     +
3556     + if( osd->clean != WIPED )
3557     + switch (osd->mode) {
3558     + case XCBOSD_SHAPED: {
3559     + xcb_rectangle_t rectangle = { 0, 0, osd->width, osd->height };
3560     + xcb_poly_fill_rectangle(osd->connection, osd->u.shaped.mask_bitmap, osd->u.shaped.mask_gc_back, 1, &rectangle);
3561     + break;
3562     + }
3563     + case XCBOSD_COLORKEY:
3564     + xcb_change_gc(osd->connection, osd->gc, XCB_GC_FOREGROUND, &osd->u.colorkey.colorkey);
3565     + if(osd->u.colorkey.sc) {
3566     + xcb_rectangle_t rectangle = { osd->u.colorkey.sc->output_xoffset, osd->u.colorkey.sc->output_yoffset,
3567     + osd->u.colorkey.sc->output_width, osd->u.colorkey.sc->output_height };
3568     + xcb_poly_fill_rectangle(osd->connection, osd->bitmap, osd->gc, 1, &rectangle);
3569     + xcb_change_gc(osd->connection, osd->gc, XCB_GC_FOREGROUND, &osd->screen->black_pixel);
3570     +
3571     + xcb_rectangle_t rects[4];
3572     + int rects_count = 0;
3573     +
3574     + for( i = 0; i < 4; i++ ) {
3575     + if( osd->u.colorkey.sc->border[i].w && osd->u.colorkey.sc->border[i].h ) {
3576     + rects[rects_count].x = osd->u.colorkey.sc->border[i].x;
3577     + rects[rects_count].y = osd->u.colorkey.sc->border[i].y;
3578     + rects[rects_count].width = osd->u.colorkey.sc->border[i].w;
3579     + rects[rects_count].height = osd->u.colorkey.sc->border[i].h;
3580     + rects_count++;
3581     + }
3582     +
3583     + if (rects_count > 0)
3584     + xcb_poly_fill_rectangle(osd->connection, osd->bitmap, osd->gc, rects_count, rects);
3585     + }
3586     + } else {
3587     + xcb_rectangle_t rectangle = { 0, 0, osd->width, osd->height };
3588     + xcb_poly_fill_rectangle(osd->connection, osd->bitmap, osd->gc, 1, &rectangle);
3589     + }
3590     + break;
3591     + }
3592     + osd->clean = WIPED;
3593     +}
3594     +
3595     +#define TRANSPARENT 0xffffffff
3596     +
3597     +#define saturate(n, l, u) ((n) < (l) ? (l) : ((n) > (u) ? (u) : (n)))
3598     +
3599     +void xcbosd_blend(xcbosd *osd, vo_overlay_t *overlay)
3600     +{
3601     + xcb_alloc_color_cookie_t alloc_color_cookie;
3602     + xcb_alloc_color_reply_t *alloc_color_reply;
3603     +
3604     + if (osd->clean==UNDEFINED)
3605     + xcbosd_clear(osd); /* Workaround. Colorkey mode needs sc data before the clear. */
3606     +
3607     + if (overlay->rle) {
3608     + int i, x, y, len, width;
3609     + int use_clip_palette, max_palette_colour[2];
3610     + uint32_t palette[2][OVL_PALETTE_SIZE];
3611     +
3612     + max_palette_colour[0] = -1;
3613     + max_palette_colour[1] = -1;
3614     +
3615     + for (i=0, x=0, y=0; i<overlay->num_rle; i++) {
3616     + len = overlay->rle[i].len;
3617     +
3618     + while (len > 0) {
3619     + use_clip_palette = 0;
3620     + if (len > overlay->width) {
3621     + width = overlay->width;
3622     + len -= overlay->width;
3623     + }
3624     + else {
3625     + width = len;
3626     + len = 0;
3627     + }
3628     + if ((y >= overlay->hili_top) && (y <= overlay->hili_bottom) && (x <= overlay->hili_right)) {
3629     + if ((x < overlay->hili_left) && (x + width - 1 >= overlay->hili_left)) {
3630     + width -= overlay->hili_left - x;
3631     + len += overlay->hili_left - x;
3632     + }
3633     + else if (x > overlay->hili_left) {
3634     + use_clip_palette = 1;
3635     + if (x + width - 1 > overlay->hili_right) {
3636     + width -= overlay->hili_right - x;
3637     + len += overlay->hili_right - x;
3638     + }
3639     + }
3640     + }
3641     +
3642     + if (overlay->rle[i].color > max_palette_colour[use_clip_palette]) {
3643     + int j;
3644     + clut_t *src_clut;
3645     + uint8_t *src_trans;
3646     +
3647     + if (use_clip_palette) {
3648     + src_clut = (clut_t *)&overlay->hili_color;
3649     + src_trans = (uint8_t *)&overlay->hili_trans;
3650     + }
3651     + else {
3652     + src_clut = (clut_t *)&overlay->color;
3653     + src_trans = (uint8_t *)&overlay->trans;
3654     + }
3655     + for (j=max_palette_colour[use_clip_palette]+1; j<=overlay->rle[i].color; j++) {
3656     + if (src_trans[j]) {
3657     + if (1) {
3658     + int red, green, blue;
3659     + int y, u, v, r, g, b;
3660     +
3661     + y = saturate(src_clut[j].y, 16, 235);
3662     + u = saturate(src_clut[j].cb, 16, 240);
3663     + v = saturate(src_clut[j].cr, 16, 240);
3664     + y = (9 * y) / 8;
3665     + r = y + (25 * v) / 16 - 218;
3666     + red = (65536 * saturate(r, 0, 255)) / 256;
3667     + g = y + (-13 * v) / 16 + (-25 * u) / 64 + 136;
3668     + green = (65536 * saturate(g, 0, 255)) / 256;
3669     + b = y + 2 * u - 274;
3670     + blue = (65536 * saturate(b, 0, 255)) / 256;
3671     +
3672     + alloc_color_cookie = xcb_alloc_color(osd->connection, osd->cmap, red, green, blue);
3673     + alloc_color_reply = xcb_alloc_color_reply(osd->connection, alloc_color_cookie, NULL);
3674     +
3675     + palette[use_clip_palette][j] = alloc_color_reply->pixel;
3676     + free(alloc_color_reply);
3677     + }
3678     + else {
3679     + if (src_clut[j].y > 127) {
3680     + palette[use_clip_palette][j] = osd->screen->white_pixel;
3681     + }
3682     + else {
3683     + palette[use_clip_palette][j] = osd->screen->black_pixel;
3684     + }
3685     + }
3686     + }
3687     + else {
3688     + palette[use_clip_palette][j] = TRANSPARENT;
3689     + }
3690     + }
3691     + max_palette_colour[use_clip_palette] = overlay->rle[i].color;
3692     + }
3693     +
3694     + if(palette[use_clip_palette][overlay->rle[i].color] != TRANSPARENT) {
3695     + xcb_change_gc(osd->connection, osd->gc, XCB_GC_FOREGROUND, &palette[use_clip_palette][overlay->rle[i].color]);
3696     + xcb_rectangle_t rectangle = { overlay->x + x, overlay->y + y, width, 1 };
3697     + xcb_poly_fill_rectangle(osd->connection, osd->bitmap, osd->gc, 1, &rectangle);
3698     + if(osd->mode==XCBOSD_SHAPED)
3699     + xcb_poly_fill_rectangle(osd->connection, osd->u.shaped.mask_bitmap, osd->u.shaped.mask_gc, 1, &rectangle);
3700     + }
3701     +
3702     + x += width;
3703     + if (x == overlay->width) {
3704     + x = 0;
3705     + y++;
3706     + }
3707     + }
3708     + }
3709     + osd->clean = DRAWN;
3710     + }
3711     +}
3712     +
3713     Index: src/video_out/xcbosd.h
3714     ===================================================================
3715     RCS file: src/video_out/xcbosd.h
3716     diff -N src/video_out/xcbosd.h
3717     --- /dev/null 1 Jan 1970 00:00:00 -0000
3718     +++ src/video_out/xcbosd.h 7 Feb 2007 02:41:42 -0000
3719     @@ -0,0 +1,55 @@
3720     +/*
3721     + * Copyright (C) 2003, 2007 the xine project
3722     + *
3723     + * This file is part of xine, a free video player.
3724     + *
3725     + * xine is free software; you can redistribute it and/or modify
3726     + * it under the terms of the GNU General Public License as published by
3727     + * the Free Software Foundation; either version 2 of the License, or
3728     + * (at your option) any later version.
3729     + *
3730     + * xine is distributed in the hope that it will be useful,
3731     + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3732     + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3733     + * GNU General Public License for more details.
3734     + *
3735     + * You should have received a copy of the GNU General Public License
3736     + * along with this program; if not, write to the Free Software
3737     + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
3738     + *
3739     + * $Id: xine-lib-1.1.4-xcb.patch,v 1.1 2007-05-08 20:43:46 niro Exp $
3740     + *
3741     + * xcbosd.h, use X11 Nonrectangular Window Shape Extension to draw xine OSD
3742     + *
3743     + * Nov 2003 - Miguel Freitas
3744     + * Feb 2007 - ported to xcb by Christoph Pfister
3745     + *
3746     + * based on ideas and code of
3747     + * xosd Copyright (c) 2000 Andre Renaud (andre@ignavus.net)
3748     + */
3749     +
3750     +#ifndef XCBOSD_H
3751     +#define XCBOSD_H
3752     +
3753     +#include "vo_scale.h"
3754     +
3755     +typedef struct xcbosd xcbosd;
3756     +enum xcbosd_mode {XCBOSD_SHAPED, XCBOSD_COLORKEY};
3757     +
3758     +xcbosd *xcbosd_create(xine_t *xine, xcb_connection_t *connection, xcb_screen_t *screen, xcb_window_t window, enum xcbosd_mode mode);
3759     +
3760     +void xcbosd_colorkey(xcbosd *osd, uint32_t colorkey, vo_scale_t *scaling);
3761     +
3762     +void xcbosd_destroy(xcbosd *osd);
3763     +
3764     +void xcbosd_expose(xcbosd *osd);
3765     +
3766     +void xcbosd_resize(xcbosd *osd, int width, int height);
3767     +
3768     +void xcbosd_drawable_changed(xcbosd *osd, xcb_window_t window);
3769     +
3770     +void xcbosd_clear(xcbosd *osd);
3771     +
3772     +void xcbosd_blend(xcbosd *osd, vo_overlay_t *overlay);
3773     +
3774     +#endif