1 /*****************************************************************************
2 * vout_xvideo.c: Xvideo video output display method
3 *****************************************************************************
4 * Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
5 * $Id: vout_xvideo.c,v 1.6 2001/04/13 06:20:23 sam Exp $
7 * Authors: Shane Harper <shanegh@optusnet.com.au>
8 * Vincent Seguin <seguin@via.ecp.fr>
9 * Samuel Hocevar <sam@zoy.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 #define MODULE_NAME xvideo
27 #include "modules_inner.h"
29 /*****************************************************************************
31 *****************************************************************************/
34 #include <errno.h> /* ENOMEM */
35 #include <stdlib.h> /* free() */
36 #include <string.h> /* strerror() */
38 #ifdef HAVE_MACHINE_PARAM_H
40 #include <machine/param.h>
41 #include <sys/types.h> /* typedef ushort */
45 #include <sys/shm.h> /* shmget(), shmctl() */
47 #include <X11/Xutil.h>
48 #include <X11/keysym.h>
49 #include <X11/extensions/XShm.h>
50 #include <X11/extensions/Xv.h>
51 #include <X11/extensions/Xvlib.h>
61 #include "video_output.h"
63 #include "interface.h"
66 #include "netutils.h" /* network_ChannelJoin */
70 /*****************************************************************************
71 * vout_sys_t: video output X11 method descriptor
72 *****************************************************************************
73 * This structure is part of the video output thread descriptor.
74 * It describes the XVideo specific properties of an output thread.
75 *****************************************************************************/
76 typedef struct vout_sys_s
80 /* this plugin (currently) requires the SHM Ext... */
81 boolean_t b_shm; /* shared memory extension flag */
84 /* Internal settings and properties */
85 Display * p_display; /* display pointer */
86 int i_screen; /* screen number */
87 Window window; /* root window */
88 GC gc; /* graphic context instance handler */
91 /* Display buffers and shared memory information */
92 /* Note: only 1 buffer... Xv ext does double buffering. */
96 /* i_image_width & i_image_height reflect the
97 * size of the XvImage. They are used by
98 * vout_Display() to check if the image to be
99 * displayed can use the current XvImage. */
100 XShmSegmentInfo shm_info; /* shared memory zone information */
102 /* X11 generic properties */
104 Atom wm_delete_window;
106 int i_window_width; /* width of main window */
107 int i_window_height; /* height of main window */
110 /* Screen saver properties */
111 int i_ss_timeout; /* timeout */
112 int i_ss_interval; /* interval between changes */
113 int i_ss_blanking; /* blanking mode */
114 int i_ss_exposure; /* exposure mode */
116 /* Auto-hide cursor */
119 /* Mouse pointer properties */
120 boolean_t b_mouse; /* is the mouse pointer displayed ? */
124 /*****************************************************************************
126 *****************************************************************************/
127 static int vout_Probe ( probedata_t * );
128 static int vout_Create ( vout_thread_t * );
129 static int vout_Init ( vout_thread_t * );
130 static void vout_End ( vout_thread_t * );
131 static void vout_Destroy ( vout_thread_t * );
132 static int vout_Manage ( vout_thread_t * );
133 static void vout_Display ( vout_thread_t * );
134 static void vout_SetPalette( vout_thread_t *, u16 *, u16 *, u16 *, u16 * );
136 static int XVideoCreateWindow ( vout_thread_t * );
137 static int XVideoUpdateImgSizeIfRequired( vout_thread_t *p_vout );
138 static int XVideoCreateShmImage ( Display* dpy, int xv_port,
139 XvImage **pp_xvimage,
140 XShmSegmentInfo *p_shm_info,
141 int i_width, int i_height );
142 static void XVideoDestroyShmImage ( vout_thread_t *, XvImage *,
144 static void XVideoTogglePointer ( vout_thread_t * );
145 static void XVideoEnableScreenSaver ( vout_thread_t * );
146 static void XVideoDisableScreenSaver ( vout_thread_t * );
147 /*static void XVideoSetAttribute ( vout_thread_t *, char *, float );*/
149 static int XVideoCheckForXv ( Display * );
150 static int XVideoGetPort ( Display * );
151 static void XVideoOutputCoords ( const picture_t *, const boolean_t,
152 const int, const int,
153 int *, int *, int *, int * );
155 /*****************************************************************************
156 * Functions exported as capabilities. They are declared as static so that
157 * we don't pollute the namespace too much.
158 *****************************************************************************/
159 void _M( vout_getfunctions )( function_list_t * p_function_list )
161 p_function_list->pf_probe = vout_Probe;
162 p_function_list->functions.vout.pf_create = vout_Create;
163 p_function_list->functions.vout.pf_init = vout_Init;
164 p_function_list->functions.vout.pf_end = vout_End;
165 p_function_list->functions.vout.pf_destroy = vout_Destroy;
166 p_function_list->functions.vout.pf_manage = vout_Manage;
167 p_function_list->functions.vout.pf_display = vout_Display;
168 p_function_list->functions.vout.pf_setpalette = vout_SetPalette;
171 /*****************************************************************************
172 * vout_Probe: probe the video driver and return a score
173 *****************************************************************************
174 * This returns a score to the plugin manager so that it can select the best
176 *****************************************************************************/
177 static int vout_Probe( probedata_t *p_data )
179 if( TestMethod( VOUT_METHOD_VAR, "xvideo" ) )
187 /*****************************************************************************
188 * vout_Create: allocate XVideo video thread output method
189 *****************************************************************************
190 * This function allocate and initialize a XVideo vout method. It uses some of
191 * the vout properties to choose the window size, and change them according to
192 * the actual properties of the display.
193 *****************************************************************************/
194 static int vout_Create( vout_thread_t *p_vout )
198 /* Allocate structure */
199 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
200 if( p_vout->p_sys == NULL )
202 intf_ErrMsg( "vout error: %s", strerror(ENOMEM) );
206 /* Open display, unsing 'vlc_display' or DISPLAY environment variable */
207 psz_display = XDisplayName( main_GetPszVariable( VOUT_DISPLAY_VAR, NULL ) );
208 p_vout->p_sys->p_display = XOpenDisplay( psz_display );
210 if( p_vout->p_sys->p_display == NULL ) /* error */
212 intf_ErrMsg( "vout error: cannot open display %s", psz_display );
213 free( p_vout->p_sys );
216 p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
218 if( !XVideoCheckForXv( p_vout->p_sys->p_display ) )
220 intf_ErrMsg( "vout error: no XVideo extension" );
221 XCloseDisplay( p_vout->p_sys->p_display );
222 free( p_vout->p_sys );
226 /* Spawn base window - this window will include the video output window,
227 * but also command buttons, subtitles and other indicators */
228 if( XVideoCreateWindow( p_vout ) )
230 intf_ErrMsg( "vout error: cannot create XVideo window" );
231 XCloseDisplay( p_vout->p_sys->p_display );
232 free( p_vout->p_sys );
236 if( (p_vout->p_sys->xv_port = XVideoGetPort( p_vout->p_sys->p_display ))<0 )
240 /* XXX The brightness and contrast values should be read from environment
241 * XXX variables... */
242 XVideoSetAttribute( p_vout, "XV_BRIGHTNESS", 0.5 );
243 XVideoSetAttribute( p_vout, "XV_CONTRAST", 0.5 );
246 p_vout->p_sys->b_mouse = 1;
248 /* Disable screen saver and return */
249 XVideoDisableScreenSaver( p_vout );
254 /*****************************************************************************
255 * vout_Init: initialize XVideo video thread output method
256 *****************************************************************************/
257 static int vout_Init( vout_thread_t *p_vout )
260 /* FIXME : As of 2001-03-16, XFree4 for MacOS X does not support Xshm. */
261 p_vout->p_sys->b_shm = 0;
263 p_vout->b_need_render = 0;
264 p_vout->p_sys->i_image_width = p_vout->p_sys->i_image_height = 0;
269 /*****************************************************************************
270 * vout_End: terminate XVideo video thread output method
271 *****************************************************************************
272 * Destroy the XvImage. It is called at the end of the thread, but also each
273 * time the image is resized.
274 *****************************************************************************/
275 static void vout_End( vout_thread_t *p_vout )
277 XVideoDestroyShmImage( p_vout, p_vout->p_sys->p_xvimage,
278 &p_vout->p_sys->shm_info );
281 /*****************************************************************************
282 * vout_Destroy: destroy XVideo video thread output method
283 *****************************************************************************
284 * Terminate an output method created by vout_CreateOutputMethod
285 *****************************************************************************/
286 static void vout_Destroy( vout_thread_t *p_vout )
288 /* Enable screen saver */
289 XVideoEnableScreenSaver( p_vout );
292 XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
293 XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->gc );
294 XDestroyWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
296 XCloseDisplay( p_vout->p_sys->p_display );
298 /* Destroy structure */
299 free( p_vout->p_sys );
302 /*****************************************************************************
303 * vout_Manage: handle X11 events
304 *****************************************************************************
305 * This function should be called regularly by video output thread. It manages
306 * X11 events and allows window resizing. It returns a non null value on
309 * XXX Should "factor-out" common code in this and the "same" fn in the x11
311 *****************************************************************************/
312 static int vout_Manage( vout_thread_t *p_vout )
314 XEvent xevent; /* X11 event */
315 char i_key; /* ISO Latin-1 key */
318 /* Handle X11 events: ConfigureNotify events are parsed to know if the
319 * output window's size changed, MapNotify and UnmapNotify to know if the
320 * window is mapped (and if the display is useful), and ClientMessages
321 * to intercept window destruction requests */
322 while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
323 StructureNotifyMask | KeyPressMask |
324 ButtonPressMask | ButtonReleaseMask |
325 PointerMotionMask, &xevent )
328 /* ConfigureNotify event: prepare */
329 if( (xevent.type == ConfigureNotify)
330 /*&& ((xevent.xconfigure.width != p_vout->p_sys->i_window_width)
331 || (xevent.xconfigure.height != p_vout->p_sys->i_window_height))*/ )
333 /* Update dimensions */
334 p_vout->p_sys->i_window_width = xevent.xconfigure.width;
335 p_vout->p_sys->i_window_height = xevent.xconfigure.height;
337 /* MapNotify event: change window status and disable screen saver */
338 else if( xevent.type == MapNotify)
340 if( (p_vout != NULL) && !p_vout->b_active )
342 XVideoDisableScreenSaver( p_vout );
343 p_vout->b_active = 1;
346 /* UnmapNotify event: change window status and enable screen saver */
347 else if( xevent.type == UnmapNotify )
349 if( (p_vout != NULL) && p_vout->b_active )
351 XVideoEnableScreenSaver( p_vout );
352 p_vout->b_active = 0;
356 else if( xevent.type == KeyPress )
358 /* We may have keys like F1 trough F12, ESC ... */
359 x_key_symbol = XKeycodeToKeysym( p_vout->p_sys->p_display,
360 xevent.xkey.keycode, 0 );
361 switch( x_key_symbol )
364 p_main->p_intf->b_die = 1;
367 p_main->p_intf->b_menu_change = 1;
371 * The reason why I use this instead of XK_0 is that
372 * with XLookupString, we don't have to care about
375 if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) )
381 p_main->p_intf->b_die = 1;
384 network_ChannelJoin( 0 );
387 network_ChannelJoin( 1 );
390 network_ChannelJoin( 2 );
393 network_ChannelJoin( 3 );
396 network_ChannelJoin( 4 );
399 network_ChannelJoin( 5 );
402 network_ChannelJoin( 6 );
405 network_ChannelJoin( 7 );
408 network_ChannelJoin( 8 );
411 network_ChannelJoin( 9 );
414 if( intf_ProcessKey( p_main->p_intf,
417 intf_DbgMsg( "unhandled key '%c' (%i)",
418 (char)i_key, i_key );
427 else if( xevent.type == ButtonPress )
429 switch( ((XButtonEvent *)&xevent)->button )
432 /* in this part we will eventually manage
433 * clicks for DVD navigation for instance */
438 else if( xevent.type == ButtonRelease )
440 switch( ((XButtonEvent *)&xevent)->button )
443 /* FIXME: need locking ! */
444 p_main->p_intf->b_menu_change = 1;
449 else if( xevent.type == MotionNotify )
451 p_vout->p_sys->i_lastmoved = mdate();
452 if( ! p_vout->p_sys->b_mouse )
454 XVideoTogglePointer( p_vout );
462 intf_DbgMsg( "%p -> unhandled event type %d received",
463 p_vout, xevent.type );
468 /* ClientMessage event - only WM_PROTOCOLS with WM_DELETE_WINDOW data
469 * are handled - according to the man pages, the format is always 32
471 while( XCheckTypedEvent( p_vout->p_sys->p_display,
472 ClientMessage, &xevent ) )
474 if( (xevent.xclient.message_type == p_vout->p_sys->wm_protocols)
475 && (xevent.xclient.data.l[0] == p_vout->p_sys->wm_delete_window ) )
477 p_main->p_intf->b_die = 1;
481 intf_DbgMsg( "%p -> unhandled ClientMessage received", p_vout );
485 if( (p_vout->i_changes & VOUT_GRAYSCALE_CHANGE))
487 /* FIXME: clear flags ?? */
493 if( p_vout->i_changes & VOUT_SIZE_CHANGE )
495 intf_DbgMsg( "vout: resizing window" );
496 p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
497 /* Noting to do here...
498 * vout_Display() detects size changes of the image to be displayed and
499 * re-creates the XvImage.*/
500 intf_Msg( "vout: video display resized (%dx%d)",
501 p_vout->i_width, p_vout->i_height );
504 /* Autohide Cursor */
505 if( p_vout->p_sys->b_mouse &&
506 mdate() - p_vout->p_sys->i_lastmoved > 2000000 )
507 XVideoTogglePointer( p_vout );
512 /*****************************************************************************
513 * XVideoUpdateImgSizeIfRequired
514 *****************************************************************************
515 * This function checks to see if the image to be displayed is of a different
516 * size to the last image displayed. If so, the old shm block must be
517 * destroyed and a new one created.
518 * Note: the "image size" is the size of the image to be passed to the Xv
519 * extension (which is probably different to the size of the output window).
520 *****************************************************************************/
521 static int XVideoUpdateImgSizeIfRequired( vout_thread_t *p_vout )
523 int i_img_width = p_vout->p_rendered_pic->i_width;
524 int i_img_height = p_vout->p_rendered_pic->i_height;
526 if( p_vout->p_sys->i_image_width != i_img_width
527 || p_vout->p_sys->i_image_height != i_img_height )
529 p_vout->p_sys->i_image_width = i_img_width;
530 p_vout->p_sys->i_image_height = i_img_height;
532 /* Destroy XvImage to change its size */
534 /* Note: vout_End does nothing if no XvImage to destroy. */
536 /* Create XvImage using XShm extension */
537 if( XVideoCreateShmImage( p_vout->p_sys->p_display,
538 p_vout->p_sys->xv_port,
539 &p_vout->p_sys->p_xvimage,
540 &p_vout->p_sys->shm_info,
541 i_img_width, i_img_height ) )
543 intf_Msg( "vout: failed to create xvimage." );
544 p_vout->p_sys->i_image_width = 0;
548 /* Set bytes per line and initialize buffers */
549 p_vout->i_bytes_per_line =
550 (p_vout->p_sys->p_xvimage->data_size) /
551 (p_vout->p_sys->p_xvimage->height);
553 /* vout_SetBuffers( p_vout, p_vout->p_sys->p_xvimage->data ); */
558 /*****************************************************************************
559 * vout_Display: displays previously rendered output
560 *****************************************************************************
561 * This function sends the currently rendered image to X11 server.
562 * (The Xv extension takes care of "double-buffering".)
563 *****************************************************************************/
564 static void vout_Display( vout_thread_t *p_vout )
566 boolean_t b_draw = 1;
567 int i_size = p_vout->p_rendered_pic->i_width *
568 p_vout->p_rendered_pic->i_height;
570 if( XVideoUpdateImgSizeIfRequired( p_vout ) )
573 switch( p_vout->p_rendered_pic->i_type )
575 case YUV_422_PICTURE:
576 intf_ErrMsg( "vout error: YUV_422_PICTURE not (yet) supported" );
580 case YUV_444_PICTURE:
581 intf_ErrMsg( "vout error: YUV_444_PICTURE not (yet) supported" );
585 case YUV_420_PICTURE:
586 memcpy( p_vout->p_sys->p_xvimage->data,
587 p_vout->p_rendered_pic->p_y, i_size );
588 memcpy( p_vout->p_sys->p_xvimage->data + ( i_size ),
589 p_vout->p_rendered_pic->p_v, i_size / 4 );
590 memcpy( p_vout->p_sys->p_xvimage->data + ( i_size ) + ( i_size / 4 ),
591 p_vout->p_rendered_pic->p_u, i_size / 4 );
598 i_window_width = p_vout->p_sys->i_window_width,
599 i_window_height = p_vout->p_sys->i_window_height,
600 i_dest_width, i_dest_height, i_dest_x, i_dest_y;
604 /* If I change the line above to "#if 0" I find on resizing the window
605 * that blue rectangles (used to specify where part of the YUV overlay
606 * used to be drawn) may remain around the edge of the video output. */
607 XGetGeometry( p_vout->p_sys->p_display, p_vout->p_sys->window,
608 &window, &i_dummy, &i_dummy,
609 &i_window_width, &i_window_height, &i_dummy, &i_dummy );
612 XVideoOutputCoords( p_vout->p_rendered_pic, p_vout->b_scale,
613 i_window_width, i_window_height,
614 &i_dest_x, &i_dest_y,
615 &i_dest_width, &i_dest_height);
617 XvShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->xv_port,
618 p_vout->p_sys->window, p_vout->p_sys->gc,
619 p_vout->p_sys->p_xvimage,
620 0 /*src_x*/, 0 /*src_y*/,
621 p_vout->p_rendered_pic->i_width,
622 p_vout->p_rendered_pic->i_height,
623 i_dest_x, i_dest_y, i_dest_width, i_dest_height,
628 static void vout_SetPalette( p_vout_thread_t p_vout,
629 u16 *red, u16 *green, u16 *blue, u16 *transp )
634 /* following functions are local */
636 /*****************************************************************************
637 * XVideoCheckForXv: check for the XVideo extension
638 *****************************************************************************/
639 static int XVideoCheckForXv( Display *dpy )
643 switch( XvQueryExtension( dpy, &i, &i, &i, &i, &i ) )
649 intf_ErrMsg( "vout error: XvBadExtension" );
653 intf_ErrMsg( "vout error: XvBadAlloc" );
657 intf_ErrMsg( "vout error: XvQueryExtension failed" );
662 /*****************************************************************************
663 * XVideoCreateWindow: open and set-up XVideo main window
664 *****************************************************************************/
665 static int XVideoCreateWindow( vout_thread_t *p_vout )
667 XSizeHints xsize_hints;
668 XSetWindowAttributes xwindow_attributes;
672 boolean_t b_configure_notify;
673 boolean_t b_map_notify;
675 /* Set main window's size */
676 p_vout->p_sys->i_window_width = main_GetIntVariable( VOUT_WIDTH_VAR,
677 VOUT_WIDTH_DEFAULT );
678 p_vout->p_sys->i_window_height = main_GetIntVariable( VOUT_HEIGHT_VAR,
679 VOUT_HEIGHT_DEFAULT );
681 /* Prepare window manager hints and properties */
682 xsize_hints.base_width = p_vout->p_sys->i_window_width;
683 xsize_hints.base_height = p_vout->p_sys->i_window_height;
684 xsize_hints.flags = PSize;
685 p_vout->p_sys->wm_protocols = XInternAtom( p_vout->p_sys->p_display,
686 "WM_PROTOCOLS", True );
687 p_vout->p_sys->wm_delete_window = XInternAtom( p_vout->p_sys->p_display,
688 "WM_DELETE_WINDOW", True );
690 /* Prepare window attributes */
691 xwindow_attributes.backing_store = Always; /* save the hidden part */
692 xwindow_attributes.background_pixel = BlackPixel( p_vout->p_sys->p_display,
693 p_vout->p_sys->i_screen );
695 xwindow_attributes.event_mask = ExposureMask | StructureNotifyMask;
697 /* Create the window and set hints - the window must receive ConfigureNotify
698 * events, and, until it is displayed, Expose and MapNotify events. */
699 p_vout->p_sys->window =
700 XCreateWindow( p_vout->p_sys->p_display,
701 DefaultRootWindow( p_vout->p_sys->p_display ),
703 p_vout->p_sys->i_window_width,
704 p_vout->p_sys->i_window_height, 1,
706 CWBackingStore | CWBackPixel | CWEventMask,
707 &xwindow_attributes );
709 /* Set window manager hints and properties: size hints, command,
710 * window's name, and accepted protocols */
711 XSetWMNormalHints( p_vout->p_sys->p_display, p_vout->p_sys->window,
713 XSetCommand( p_vout->p_sys->p_display, p_vout->p_sys->window,
714 p_main->ppsz_argv, p_main->i_argc );
715 XStoreName( p_vout->p_sys->p_display, p_vout->p_sys->window,
716 VOUT_TITLE " (XVideo output)" );
718 if( (p_vout->p_sys->wm_protocols == None) /* use WM_DELETE_WINDOW */
719 || (p_vout->p_sys->wm_delete_window == None)
720 || !XSetWMProtocols( p_vout->p_sys->p_display, p_vout->p_sys->window,
721 &p_vout->p_sys->wm_delete_window, 1 ) )
723 /* WM_DELETE_WINDOW is not supported by window manager */
724 intf_Msg( "vout error: missing or bad window manager" );
727 /* Creation of a graphic context that doesn't generate a GraphicsExpose
728 * event when using functions like XCopyArea */
729 xgcvalues.graphics_exposures = False;
730 p_vout->p_sys->gc = XCreateGC( p_vout->p_sys->p_display,
731 p_vout->p_sys->window,
732 GCGraphicsExposures, &xgcvalues);
734 /* Send orders to server, and wait until window is displayed - three
735 * events must be received: a MapNotify event, an Expose event allowing
736 * drawing in the window, and a ConfigureNotify to get the window
737 * dimensions. Once those events have been received, only ConfigureNotify
738 * events need to be received. */
740 b_configure_notify = 0;
742 XMapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
745 XNextEvent( p_vout->p_sys->p_display, &xevent);
746 if( (xevent.type == Expose)
747 && (xevent.xexpose.window == p_vout->p_sys->window) )
751 else if( (xevent.type == MapNotify)
752 && (xevent.xmap.window == p_vout->p_sys->window) )
756 else if( (xevent.type == ConfigureNotify)
757 && (xevent.xconfigure.window == p_vout->p_sys->window) )
759 b_configure_notify = 1;
760 p_vout->p_sys->i_window_width = xevent.xconfigure.width;
761 p_vout->p_sys->i_window_height = xevent.xconfigure.height;
763 } while( !( b_expose && b_configure_notify && b_map_notify ) );
765 XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window,
766 StructureNotifyMask | KeyPressMask |
767 ButtonPressMask | ButtonReleaseMask |
770 /* At this stage, the window is open, displayed, and ready to
775 /*****************************************************************************
776 * XVideoCreateShmImage: create an XvImage using shared memory extension
777 *****************************************************************************
778 * Prepare an XvImage for display function.
779 * The order of the operations respects the recommandations of the mit-shm
780 * document by J.Corbet and K.Packard. Most of the parameters were copied from
782 *****************************************************************************/
783 static int XVideoCreateShmImage( Display* dpy, int xv_port,
784 XvImage **pp_xvimage,
785 XShmSegmentInfo *p_shm_info,
786 int i_width, int i_height )
788 #define GUID_YUV12_PLANAR 0x32315659
790 *pp_xvimage = XvShmCreateImage( dpy, xv_port,
791 GUID_YUV12_PLANAR, 0,
795 p_shm_info->shmid = shmget( IPC_PRIVATE, (*pp_xvimage)->data_size,
797 p_shm_info->shmaddr = (*pp_xvimage)->data = shmat( p_shm_info->shmid,
799 p_shm_info->readOnly = False;
801 shmctl( p_shm_info->shmid, IPC_RMID, 0 ); /* XXX */
803 if( !XShmAttach( dpy, p_shm_info ) )
805 intf_ErrMsg( "vout error: XShmAttach failed" );
809 /* Send image to X server. This instruction is required, since having
810 * built a Shm XImage and not using it causes an error on XCloseDisplay */
816 /*****************************************************************************
817 * XVideoDestroyShmImage
818 *****************************************************************************
819 * Destroy XImage AND associated data. Detach shared memory segment from
820 * server and process, then free it. If pointer is NULL, the image won't be
821 * destroyed (see vout_ManageOutputMethod())
822 *****************************************************************************/
823 static void XVideoDestroyShmImage( vout_thread_t *p_vout, XvImage *p_xvimage,
824 XShmSegmentInfo *p_shm_info )
826 /* If pointer is NULL, do nothing */
827 if( p_xvimage == NULL )
832 XShmDetach( p_vout->p_sys->p_display, p_shm_info );/* detach from server */
834 XDestroyImage( p_ximage ); /* XXX */
837 if( shmdt( p_shm_info->shmaddr ) ) /* detach shared memory from process */
838 { /* also automatic freeing... */
839 intf_ErrMsg( "vout error: cannot detach shared memory (%s)",
844 /*****************************************************************************
845 * XVideoEnableScreenSaver: enable screen saver
846 *****************************************************************************
847 * This function enable the screen saver on a display after it had been
848 * disabled by XDisableScreenSaver. Both functions use a counter mechanism to
849 * know wether the screen saver can be activated or not: if n successive calls
850 * are made to XDisableScreenSaver, n successive calls to XEnableScreenSaver
851 * will be required before the screen saver could effectively be activated.
852 *****************************************************************************/
853 void XVideoEnableScreenSaver( vout_thread_t *p_vout )
855 intf_DbgMsg( "intf: enabling screen saver" );
856 XSetScreenSaver( p_vout->p_sys->p_display, p_vout->p_sys->i_ss_timeout,
857 p_vout->p_sys->i_ss_interval,
858 p_vout->p_sys->i_ss_blanking,
859 p_vout->p_sys->i_ss_exposure );
862 /*****************************************************************************
863 * XVideoDisableScreenSaver: disable screen saver
864 *****************************************************************************
865 * See XEnableScreenSaver
866 *****************************************************************************/
867 void XVideoDisableScreenSaver( vout_thread_t *p_vout )
869 /* Save screen saver informations */
870 XGetScreenSaver( p_vout->p_sys->p_display, &p_vout->p_sys->i_ss_timeout,
871 &p_vout->p_sys->i_ss_interval,
872 &p_vout->p_sys->i_ss_blanking,
873 &p_vout->p_sys->i_ss_exposure );
875 /* Disable screen saver */
876 intf_DbgMsg( "intf: disabling screen saver" );
877 XSetScreenSaver( p_vout->p_sys->p_display, 0,
878 p_vout->p_sys->i_ss_interval,
879 p_vout->p_sys->i_ss_blanking,
880 p_vout->p_sys->i_ss_exposure );
883 /*****************************************************************************
884 * XVideoTogglePointer: hide or show the mouse pointer
885 *****************************************************************************
886 * This function hides the X pointer if it is visible by putting it at
887 * coordinates (32,32) and setting the pointer sprite to a blank one. To
888 * show it again, we disable the sprite and restore the original coordinates.
889 *****************************************************************************/
890 void XVideoTogglePointer( vout_thread_t *p_vout )
892 static Cursor cursor;
893 static boolean_t b_cursor = 0;
895 if( p_vout->p_sys->b_mouse )
897 p_vout->p_sys->b_mouse = 0;
902 Pixmap blank = XCreatePixmap( p_vout->p_sys->p_display,
903 DefaultRootWindow(p_vout->p_sys->p_display),
906 XParseColor( p_vout->p_sys->p_display,
907 XCreateColormap( p_vout->p_sys->p_display,
909 p_vout->p_sys->p_display ),
911 p_vout->p_sys->p_display,
912 p_vout->p_sys->i_screen ),
916 cursor = XCreatePixmapCursor( p_vout->p_sys->p_display,
917 blank, blank, &color, &color, 1, 1 );
921 XDefineCursor( p_vout->p_sys->p_display,
922 p_vout->p_sys->window, cursor );
926 p_vout->p_sys->b_mouse = 1;
928 XUndefineCursor( p_vout->p_sys->p_display, p_vout->p_sys->window );
932 /* This based on some code in SetBufferPicture... At the moment it's only
933 * used by the xvideo plugin, but others may want to use it. */
934 static void XVideoOutputCoords( const picture_t *p_pic, const boolean_t scale,
935 const int win_w, const int win_h,
936 int *dx, int *dy, int *w, int *h)
940 *w = p_pic->i_width; *h = p_pic->i_height;
945 switch( p_pic->i_aspect_ratio )
947 case AR_3_4_PICTURE: *h = win_w * 3 / 4; break;
948 case AR_16_9_PICTURE: *h = win_w * 9 / 16; break;
949 case AR_221_1_PICTURE: *h = win_w * 100 / 221; break;
950 case AR_SQUARE_PICTURE:
951 default: *h = win_w; break;
957 switch( p_pic->i_aspect_ratio )
959 case AR_3_4_PICTURE: *w = win_h * 4 / 3; break;
960 case AR_16_9_PICTURE: *w = win_h * 16 / 9; break;
961 case AR_221_1_PICTURE: *w = win_h * 221 / 100; break;
962 case AR_SQUARE_PICTURE:
963 default: *w = win_h; break;
968 /* Set picture position */
969 *dx = (win_w - *w) / 2;
970 *dy = (win_h - *h) / 2;
974 static int XVideoGetPort( Display *dpy )
977 XvAdaptorInfo *adaptor_info;
979 switch( XvQueryAdaptors( dpy, DefaultRootWindow( dpy ),
980 &i_adaptors, &adaptor_info ) )
986 intf_ErrMsg( "vout error: XvBadExtension for XvQueryAdaptors" );
990 intf_ErrMsg( "vout error: XvBadAlloc for XvQueryAdaptors" );
994 intf_ErrMsg( "vout error: XvQueryAdaptors failed" );
998 for( i=0; i < i_adaptors; ++i )
999 if( ( adaptor_info[ i ].type & XvInputMask ) &&
1000 ( adaptor_info[ i ].type & XvImageMask ) )
1002 return adaptor_info[ i ].base_id;
1005 intf_ErrMsg( "vout error: didn't find an Xvideo image input port." );
1011 /*****************************************************************************
1012 * XVideoSetAttribute
1013 *****************************************************************************
1014 * This function can be used to set attributes, e.g. XV_BRIGHTNESS and
1015 * XV_CONTRAST. "value" should be in the range of 0 to 1.
1016 *****************************************************************************/
1017 static void XVideoSetAttribute( vout_thread_t *p_vout,
1018 char *attr_name, float f_value )
1021 XvAttribute *p_attrib;
1022 Display *p_dpy = p_vout->p_sys->p_display;
1023 int xv_port = p_vout->p_sys->xv_port;
1025 p_attrib = XvQueryPortAttributes( p_dpy, xv_port, &i_attrib );
1031 if( i_attrib >= 0 && !strcmp( p_attrib[ i_attrib ].name, attr_name ) )
1033 int i_sv = f_value * ( p_attrib[ i_attrib ].max_value
1034 - p_attrib[ i_attrib ].min_value + 1 )
1035 + p_attrib[ i_attrib ].min_value;
1037 XvSetPortAttribute( p_dpy, xv_port,
1038 XInternAtom( p_dpy, attr_name, False ), i_sv );
1042 } while( i_attrib > 0 );