Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 ? 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