/*****************************************************************************
* vout_xvideo.c: Xvideo video output display method
*****************************************************************************
- * Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
- * $Id: vout_xvideo.c,v 1.10 2001/04/25 09:31:14 sam Exp $
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: vout_xvideo.c,v 1.40 2001/12/17 03:38:21 sam Exp $
*
* Authors: Shane Harper <shanegh@optusnet.com.au>
* Vincent Seguin <seguin@via.ecp.fr>
#include <sys/ipc.h>
#endif
+#ifndef WIN32
+#include <netinet/in.h> /* BSD: struct in_addr */
+#endif
+
#include <sys/shm.h> /* shmget(), shmctl() */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XShm.h>
#include <X11/extensions/Xv.h>
#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/dpms.h>
-#include "config.h"
#include "common.h"
+#include "intf_msg.h"
#include "threads.h"
#include "mtime.h"
#include "tests.h"
-#include "modules.h"
#include "video.h"
#include "video_output.h"
+#include "vout_common.h"
#include "interface.h"
-#include "intf_msg.h"
-
#include "netutils.h" /* network_ChannelJoin */
-#include "main.h"
+#include "stream_control.h" /* needed by input_ext-intf.h... */
+#include "input_ext-intf.h"
+#include "modules.h"
+#include "modules_export.h"
+#define XVIDEO_MAX_DIRECTBUFFERS 5
#define GUID_YUV12_PLANAR 0x32315659
-
-/*****************************************************************************
- * vout_sys_t: video output X11 method descriptor
- *****************************************************************************
- * This structure is part of the video output thread descriptor.
- * It describes the XVideo specific properties of an output thread.
- *****************************************************************************/
-typedef struct vout_sys_s
-{
- /* User settings */
-#if 0
- /* this plugin (currently) requires the SHM Ext... */
- boolean_t b_shm; /* shared memory extension flag */
-#endif
-
- /* Internal settings and properties */
- Display * p_display; /* display pointer */
- int i_screen; /* screen number */
- Window window; /* root window */
- GC gc; /* graphic context instance handler */
- int xv_port;
-
- /* Display buffers and shared memory information */
- /* Note: only 1 buffer... Xv ext does double buffering. */
- XvImage * p_xvimage;
- int i_image_width;
- int i_image_height;
- /* i_image_width & i_image_height reflect the
- * size of the XvImage. They are used by
- * vout_Display() to check if the image to be
- * displayed can use the current XvImage. */
- XShmSegmentInfo shm_info; /* shared memory zone information */
-
- /* X11 generic properties */
- Atom wm_protocols;
- Atom wm_delete_window;
-
- int i_window_width; /* width of main window */
- int i_window_height; /* height of main window */
-
-
- /* Screen saver properties */
- int i_ss_timeout; /* timeout */
- int i_ss_interval; /* interval between changes */
- int i_ss_blanking; /* blanking mode */
- int i_ss_exposure; /* exposure mode */
-
- /* Auto-hide cursor */
- mtime_t i_lastmoved;
-
- /* Mouse pointer properties */
- boolean_t b_mouse; /* is the mouse pointer displayed ? */
-
- /* Displaying fullscreen */
- boolean_t b_fullscreen;
-
-} vout_sys_t;
-
-/* Fullscreen needs to be able to hide the wm decorations */
-#define MWM_HINTS_DECORATIONS (1L << 1)
-#define PROP_MWM_HINTS_ELEMENTS 5
-typedef struct mwmhints_s
-{
- u32 flags;
- u32 functions;
- u32 decorations;
- s32 input_mode;
- u32 status;
-} mwmhints_t;
-
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int vout_Init ( vout_thread_t * );
static void vout_End ( vout_thread_t * );
static void vout_Destroy ( vout_thread_t * );
-static int vout_Manage ( vout_thread_t * );
-static void vout_Display ( vout_thread_t * );
-static void vout_SetPalette( vout_thread_t *, u16 *, u16 *, u16 *, u16 * );
-
-static int XVideoCreateWindow ( vout_thread_t * );
-static int XVideoUpdateImgSizeIfRequired( vout_thread_t *p_vout );
-static int XVideoCreateShmImage ( Display* dpy, int xv_port,
- XvImage **pp_xvimage,
- XShmSegmentInfo *p_shm_info,
- int i_width, int i_height );
-static void XVideoDestroyShmImage ( vout_thread_t *, XvImage *,
- XShmSegmentInfo * );
-static void XVideoTogglePointer ( vout_thread_t * );
-static void XVideoEnableScreenSaver ( vout_thread_t * );
-static void XVideoDisableScreenSaver ( vout_thread_t * );
-/*static void XVideoSetAttribute ( vout_thread_t *, char *, float );*/
+static void vout_Display ( vout_thread_t *, picture_t * );
-static int XVideoCheckForXv ( Display * );
-static int XVideoGetPort ( Display * );
-static void XVideoOutputCoords ( const picture_t *, const boolean_t,
- const int, const int,
- int *, int *, int *, int * );
+static int XVideoNewPicture ( vout_thread_t *, picture_t * );
+
+static XvImage *CreateShmImage ( Display *, int, XShmSegmentInfo *, int, int );
+static void DestroyShmImage( Display *, XvImage *, XShmSegmentInfo * );
+
+static int CheckForXVideo ( Display * );
+static int GetXVideoPort ( Display * );
+
+/*static void XVideoSetAttribute ( vout_thread_t *, char *, float );*/
/*****************************************************************************
* Functions exported as capabilities. They are declared as static so that
p_function_list->functions.vout.pf_init = vout_Init;
p_function_list->functions.vout.pf_end = vout_End;
p_function_list->functions.vout.pf_destroy = vout_Destroy;
- p_function_list->functions.vout.pf_manage = vout_Manage;
+ p_function_list->functions.vout.pf_manage = _M( vout_Manage );
p_function_list->functions.vout.pf_display = vout_Display;
- p_function_list->functions.vout.pf_setpalette = vout_SetPalette;
+ p_function_list->functions.vout.pf_setpalette = NULL;
}
/*****************************************************************************
*****************************************************************************/
static int vout_Probe( probedata_t *p_data )
{
+ Display *p_display; /* display pointer */
+ char *psz_display;
+
+ /* Open display, unsing 'vlc_display' or DISPLAY environment variable */
+ psz_display = XDisplayName( main_GetPszVariable(VOUT_DISPLAY_VAR, NULL) );
+ p_display = XOpenDisplay( psz_display );
+ if( p_display == NULL ) /* error */
+ {
+ intf_WarnMsg( 3, "vout: Xvideo cannot open display %s", psz_display );
+ intf_WarnMsg( 3, "vout: Xvideo not supported" );
+ return( 0 );
+ }
+
+ if( !CheckForXVideo( p_display ) )
+ {
+ intf_WarnMsg( 3, "vout: Xvideo not supported" );
+ XCloseDisplay( p_display );
+ return( 0 );
+ }
+
+ if( GetXVideoPort( p_display ) < 0 )
+ {
+ intf_WarnMsg( 3, "vout: Xvideo not supported" );
+ XCloseDisplay( p_display );
+ return( 0 );
+ }
+
+ /* Clean-up everyting */
+ XCloseDisplay( p_display );
+
if( TestMethod( VOUT_METHOD_VAR, "xvideo" ) )
{
return( 999 );
}
- return( 110 );
+ return( 150 );
}
/*****************************************************************************
* vout_Create: allocate XVideo video thread output method
*****************************************************************************
- * This function allocate and initialize a XVideo vout method. It uses some of
+ * This function allocates and initialize a XVideo vout method. It uses some of
* the vout properties to choose the window size, and change them according to
* the actual properties of the display.
*****************************************************************************/
static int vout_Create( vout_thread_t *p_vout )
{
char *psz_display;
+ XColor cursor_color;
/* Allocate structure */
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
}
p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
- p_vout->p_sys->b_fullscreen
- = main_GetIntVariable( VOUT_FULLSCREEN_VAR, VOUT_FULLSCREEN_DEFAULT );
-
- if( !XVideoCheckForXv( p_vout->p_sys->p_display ) )
+ if( !CheckForXVideo( p_vout->p_sys->p_display ) )
{
intf_ErrMsg( "vout error: no XVideo extension" );
XCloseDisplay( p_vout->p_sys->p_display );
return( 1 );
}
+ /* Check we have access to a video port */
+ if( (p_vout->p_sys->i_xvport = GetXVideoPort(p_vout->p_sys->p_display)) <0 )
+ {
+ intf_ErrMsg( "vout error: cannot get XVideo port" );
+ XCloseDisplay( p_vout->p_sys->p_display );
+ free( p_vout->p_sys );
+ return 1;
+ }
+ intf_DbgMsg( "Using xv port %d" , p_vout->p_sys->xv_port );
+
+ /* Create blank cursor (for mouse cursor autohiding) */
+ p_vout->p_sys->b_mouse_pointer_visible = 1;
+ p_vout->p_sys->cursor_pixmap = XCreatePixmap( p_vout->p_sys->p_display,
+ DefaultRootWindow(
+ p_vout->p_sys->p_display),
+ 1, 1, 1 );
+
+ XParseColor( p_vout->p_sys->p_display,
+ XCreateColormap( p_vout->p_sys->p_display,
+ DefaultRootWindow(
+ p_vout->p_sys->p_display ),
+ DefaultVisual(
+ p_vout->p_sys->p_display,
+ p_vout->p_sys->i_screen ),
+ AllocNone ),
+ "black", &cursor_color );
+
+ p_vout->p_sys->blank_cursor = XCreatePixmapCursor(
+ p_vout->p_sys->p_display,
+ p_vout->p_sys->cursor_pixmap,
+ p_vout->p_sys->cursor_pixmap,
+ &cursor_color,
+ &cursor_color, 1, 1 );
+
/* Spawn base window - this window will include the video output window,
* but also command buttons, subtitles and other indicators */
- if( XVideoCreateWindow( p_vout ) )
+ if( _M( XCommonCreateWindow ) ( p_vout ) )
{
- intf_ErrMsg( "vout error: cannot create XVideo window" );
+ intf_ErrMsg( "vout error: no suitable Xvideo image input port" );
+ _M( XCommonDestroyWindow ) ( p_vout );
XCloseDisplay( p_vout->p_sys->p_display );
free( p_vout->p_sys );
return( 1 );
}
- if( (p_vout->p_sys->xv_port = XVideoGetPort( p_vout->p_sys->p_display ))<0 )
- return 1;
- intf_DbgMsg( "Using xv port %d" , p_vout->p_sys->xv_port );
-
#if 0
/* XXX The brightness and contrast values should be read from environment
* XXX variables... */
XVideoSetAttribute( p_vout, "XV_CONTRAST", 0.5 );
#endif
- p_vout->p_sys->b_mouse = 1;
-
/* Disable screen saver and return */
- XVideoDisableScreenSaver( p_vout );
+ _M( XCommonDisableScreenSaver ) ( p_vout );
return( 0 );
}
*****************************************************************************/
static int vout_Init( vout_thread_t *p_vout )
{
-#ifdef SYS_DARWIN1_3
- /* FIXME : As of 2001-03-16, XFree4 for MacOS X does not support Xshm. */
- p_vout->p_sys->b_shm = 0;
-#endif
- p_vout->b_need_render = 0;
- p_vout->p_sys->i_image_width = p_vout->p_sys->i_image_height = 0;
+ int i_index;
+ picture_t *p_pic;
- return( 0 );
-}
+ I_OUTPUTPICTURES = 0;
-/*****************************************************************************
- * vout_End: terminate XVideo video thread output method
- *****************************************************************************
- * Destroy the XvImage. It is called at the end of the thread, but also each
- * time the image is resized.
- *****************************************************************************/
-static void vout_End( vout_thread_t *p_vout )
-{
- XVideoDestroyShmImage( p_vout, p_vout->p_sys->p_xvimage,
- &p_vout->p_sys->shm_info );
-}
-
-/*****************************************************************************
- * vout_Destroy: destroy XVideo video thread output method
- *****************************************************************************
- * Terminate an output method created by vout_CreateOutputMethod
- *****************************************************************************/
-static void vout_Destroy( vout_thread_t *p_vout )
-{
- /* Enable screen saver */
- XVideoEnableScreenSaver( p_vout );
-
- /* Destroy window */
- XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
- XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->gc );
- XDestroyWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
-
- XCloseDisplay( p_vout->p_sys->p_display );
+ /* Initialize the output structure */
+ switch( p_vout->render.i_chroma )
+ {
+ case YUV_420_PICTURE:
+ p_vout->output.i_chroma = p_vout->render.i_chroma;
+ p_vout->output.i_width = p_vout->render.i_width;
+ p_vout->output.i_height = p_vout->render.i_height;
+ p_vout->output.i_aspect = p_vout->render.i_aspect;
+ break;
- /* Destroy structure */
- free( p_vout->p_sys );
-}
+ default:
+ return( 0 );
+ }
-/*****************************************************************************
- * vout_Manage: handle X11 events
- *****************************************************************************
- * This function should be called regularly by video output thread. It manages
- * X11 events and allows window resizing. It returns a non null value on
- * error.
- *
- * XXX Should "factor-out" common code in this and the "same" fn in the x11
- * XXX plugin!
- *****************************************************************************/
-static int vout_Manage( vout_thread_t *p_vout )
-{
- XEvent xevent; /* X11 event */
- boolean_t b_gofullscreen; /* user wants full-screen */
- char i_key; /* ISO Latin-1 key */
- KeySym x_key_symbol;
-
- b_gofullscreen = 0;
-
- /* Handle X11 events: ConfigureNotify events are parsed to know if the
- * output window's size changed, MapNotify and UnmapNotify to know if the
- * window is mapped (and if the display is useful), and ClientMessages
- * to intercept window destruction requests */
- while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
- StructureNotifyMask | KeyPressMask |
- ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask, &xevent )
- == True )
+ /* Try to initialize up to XVIDEO_MAX_DIRECTBUFFERS direct buffers */
+ while( I_OUTPUTPICTURES < XVIDEO_MAX_DIRECTBUFFERS )
{
- /* ConfigureNotify event: prepare */
- if( (xevent.type == ConfigureNotify)
- /*&& ((xevent.xconfigure.width != p_vout->p_sys->i_window_width)
- || (xevent.xconfigure.height != p_vout->p_sys->i_window_height))*/ )
- {
- /* Update dimensions */
- p_vout->p_sys->i_window_width = xevent.xconfigure.width;
- p_vout->p_sys->i_window_height = xevent.xconfigure.height;
- }
- /* MapNotify event: change window status and disable screen saver */
- else if( xevent.type == MapNotify)
- {
- if( (p_vout != NULL) && !p_vout->b_active )
- {
- XVideoDisableScreenSaver( p_vout );
- p_vout->b_active = 1;
- }
- }
- /* UnmapNotify event: change window status and enable screen saver */
- else if( xevent.type == UnmapNotify )
- {
- if( (p_vout != NULL) && p_vout->b_active )
- {
- XVideoEnableScreenSaver( p_vout );
- p_vout->b_active = 0;
- }
- }
- /* Keyboard event */
- else if( xevent.type == KeyPress )
+ p_pic = NULL;
+
+ /* Find an empty picture slot */
+ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
{
- /* We may have keys like F1 trough F12, ESC ... */
- x_key_symbol = XKeycodeToKeysym( p_vout->p_sys->p_display,
- xevent.xkey.keycode, 0 );
- switch( x_key_symbol )
+ if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
{
- case XK_Escape:
- p_main->p_intf->b_die = 1;
- break;
- case XK_Menu:
- p_main->p_intf->b_menu_change = 1;
- break;
- default:
- /* "Normal Keys"
- * The reason why I use this instead of XK_0 is that
- * with XLookupString, we don't have to care about
- * keymaps. */
-
- if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) )
- {
- switch( i_key )
- {
- case 'q':
- case 'Q':
- p_main->p_intf->b_die = 1;
- break;
- case 'f':
- case 'F':
- b_gofullscreen = 1;
- break;
- case '0':
- network_ChannelJoin( 0 );
- break;
- case '1':
- network_ChannelJoin( 1 );
- break;
- case '2':
- network_ChannelJoin( 2 );
- break;
- case '3':
- network_ChannelJoin( 3 );
- break;
- case '4':
- network_ChannelJoin( 4 );
- break;
- case '5':
- network_ChannelJoin( 5 );
- break;
- case '6':
- network_ChannelJoin( 6 );
- break;
- case '7':
- network_ChannelJoin( 7 );
- break;
- case '8':
- network_ChannelJoin( 8 );
- break;
- case '9':
- network_ChannelJoin( 9 );
- break;
- default:
- if( intf_ProcessKey( p_main->p_intf,
- (char )i_key ) )
- {
- intf_DbgMsg( "unhandled key '%c' (%i)",
- (char)i_key, i_key );
- }
- break;
- }
- }
+ p_pic = p_vout->p_picture + i_index;
break;
}
}
- /* Mouse click */
- else if( xevent.type == ButtonPress )
- {
- switch( ((XButtonEvent *)&xevent)->button )
- {
- case Button1:
- /* in this part we will eventually manage
- * clicks for DVD navigation for instance */
- break;
- }
- }
- /* Mouse release */
- else if( xevent.type == ButtonRelease )
- {
- switch( ((XButtonEvent *)&xevent)->button )
- {
- case Button3:
- /* FIXME: need locking ! */
- p_main->p_intf->b_menu_change = 1;
- break;
- }
- }
- /* Mouse move */
- else if( xevent.type == MotionNotify )
- {
- p_vout->p_sys->i_lastmoved = mdate();
- if( ! p_vout->p_sys->b_mouse )
- {
- XVideoTogglePointer( p_vout );
- }
- }
-
-#ifdef DEBUG
- /* Other event */
- else
- {
- intf_DbgMsg( "%p -> unhandled event type %d received",
- p_vout, xevent.type );
- }
-#endif
- }
- /* ClientMessage event - only WM_PROTOCOLS with WM_DELETE_WINDOW data
- * are handled - according to the man pages, the format is always 32
- * in this case */
- while( XCheckTypedEvent( p_vout->p_sys->p_display,
- ClientMessage, &xevent ) )
- {
- if( (xevent.xclient.message_type == p_vout->p_sys->wm_protocols)
- && (xevent.xclient.data.l[0] == p_vout->p_sys->wm_delete_window ) )
+ /* Allocate the picture */
+ if( XVideoNewPicture( p_vout, p_pic ) )
{
- p_main->p_intf->b_die = 1;
- }
- else
- {
- intf_DbgMsg( "%p -> unhandled ClientMessage received", p_vout );
+ break;
}
- }
-
- if ( b_gofullscreen )
- {
- char *psz_display;
- /* Open display, unsing 'vlc_display' or DISPLAY environment variable */
- psz_display = XDisplayName( main_GetPszVariable( VOUT_DISPLAY_VAR, NULL ) );
-
- intf_DbgMsg( "vout: changing full-screen status" );
- p_vout->p_sys->b_fullscreen = !p_vout->p_sys->b_fullscreen;
+ p_pic->i_status = DESTROYED_PICTURE;
+ p_pic->i_type = DIRECT_PICTURE;
- /* Get rid of the old window */
- XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
- XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->gc );
+ p_pic->i_left_margin =
+ p_pic->i_right_margin =
+ p_pic->i_top_margin =
+ p_pic->i_bottom_margin = 0;
- /* And create a new one */
- if( XVideoCreateWindow( p_vout ) )
- {
- intf_ErrMsg( "vout error: cannot create X11 window" );
- XCloseDisplay( p_vout->p_sys->p_display );
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
- free( p_vout->p_sys );
- return( 1 );
- }
-
- /* We've changed the size, update it */
- p_vout->i_changes |= VOUT_SIZE_CHANGE;
+ I_OUTPUTPICTURES++;
}
-
- if( (p_vout->i_changes & VOUT_GRAYSCALE_CHANGE))
- {
- /* FIXME: clear flags ?? */
- }
+ return( 0 );
+}
- /*
- * Size change
- */
- if( p_vout->i_changes & VOUT_SIZE_CHANGE )
+/*****************************************************************************
+ * vout_End: terminate XVideo video thread output method
+ *****************************************************************************
+ * Destroy the XvImage. It is called at the end of the thread, but also each
+ * time the image is resized.
+ *****************************************************************************/
+static void vout_End( vout_thread_t *p_vout )
+{
+ int i_index;
+
+ /* Free the direct buffers we allocated */
+ for( i_index = I_OUTPUTPICTURES ; i_index ; )
{
- intf_DbgMsg( "vout: resizing window" );
- p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
- /* Noting to do here...
- * vout_Display() detects size changes of the image to be displayed and
- * re-creates the XvImage.*/
- intf_Msg( "vout: video display resized (%dx%d)",
- p_vout->i_width, p_vout->i_height );
+ i_index--;
+ DestroyShmImage( p_vout->p_sys->p_display,
+ PP_OUTPUTPICTURE[ i_index ]->p_sys->p_xvimage,
+ &PP_OUTPUTPICTURE[ i_index ]->p_sys->shminfo );
+ free( PP_OUTPUTPICTURE[ i_index ]->p_sys );
}
-
- /* Autohide Cursor */
- if( p_vout->p_sys->b_mouse &&
- mdate() - p_vout->p_sys->i_lastmoved > 2000000 )
- XVideoTogglePointer( p_vout );
-
- return 0;
}
/*****************************************************************************
- * XVideoUpdateImgSizeIfRequired
+ * vout_Destroy: destroy XVideo video thread output method
*****************************************************************************
- * This function checks to see if the image to be displayed is of a different
- * size to the last image displayed. If so, the old shm block must be
- * destroyed and a new one created.
- * Note: the "image size" is the size of the image to be passed to the Xv
- * extension (which is probably different to the size of the output window).
+ * Terminate an output method created by vout_Create
*****************************************************************************/
-static int XVideoUpdateImgSizeIfRequired( vout_thread_t *p_vout )
+static void vout_Destroy( vout_thread_t *p_vout )
{
- int i_img_width = p_vout->p_rendered_pic->i_width;
- int i_img_height = p_vout->p_rendered_pic->i_height;
-
- if( p_vout->p_sys->i_image_width != i_img_width
- || p_vout->p_sys->i_image_height != i_img_height )
+ /* Restore cursor if it was blanked */
+ if( !p_vout->p_sys->b_mouse_pointer_visible )
{
- p_vout->p_sys->i_image_width = i_img_width;
- p_vout->p_sys->i_image_height = i_img_height;
-
- /* Destroy XvImage to change its size */
- vout_End( p_vout );
- /* Note: vout_End does nothing if no XvImage to destroy. */
-
- /* Create XvImage using XShm extension */
- if( XVideoCreateShmImage( p_vout->p_sys->p_display,
- p_vout->p_sys->xv_port,
- &p_vout->p_sys->p_xvimage,
- &p_vout->p_sys->shm_info,
- i_img_width, i_img_height ) )
- {
- intf_ErrMsg( "vout: failed to create xvimage." );
- p_vout->p_sys->i_image_width = 0;
- return( 1 );
- }
+ _M( XCommonToggleMousePointer ) ( p_vout );
+ }
- /* Set bytes per line and initialize buffers */
- p_vout->i_bytes_per_line =
- (p_vout->p_sys->p_xvimage->data_size) /
- (p_vout->p_sys->p_xvimage->height);
+ /* Destroy blank cursor pixmap */
+ XFreePixmap( p_vout->p_sys->p_display, p_vout->p_sys->cursor_pixmap );
- /* vout_SetBuffers( p_vout, p_vout->p_sys->p_xvimage->data ); */
- }
- return( 0 );
+ _M( XCommonEnableScreenSaver ) ( p_vout );
+ _M( XCommonDestroyWindow ) ( p_vout );
+ XCloseDisplay( p_vout->p_sys->p_display );
+
+ /* Destroy structure */
+ free( p_vout->p_sys );
}
/*****************************************************************************
* This function sends the currently rendered image to X11 server.
* (The Xv extension takes care of "double-buffering".)
*****************************************************************************/
-static void vout_Display( vout_thread_t *p_vout )
+static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
{
- boolean_t b_draw = 1;
- int i_size = p_vout->p_rendered_pic->i_width *
- p_vout->p_rendered_pic->i_height;
-
- if( XVideoUpdateImgSizeIfRequired( p_vout ) )
- return;
-
- switch( p_vout->p_rendered_pic->i_type )
- {
- case YUV_422_PICTURE:
- intf_ErrMsg( "vout error: YUV_422_PICTURE not (yet) supported" );
- b_draw = 0;
- break;
-
- case YUV_444_PICTURE:
- intf_ErrMsg( "vout error: YUV_444_PICTURE not (yet) supported" );
- b_draw = 0;
- break;
-
- case YUV_420_PICTURE:
- memcpy( p_vout->p_sys->p_xvimage->data,
- p_vout->p_rendered_pic->p_y, i_size );
- memcpy( p_vout->p_sys->p_xvimage->data + ( i_size ),
- p_vout->p_rendered_pic->p_v, i_size / 4 );
- memcpy( p_vout->p_sys->p_xvimage->data + ( i_size ) + ( i_size / 4 ),
- p_vout->p_rendered_pic->p_u, i_size / 4 );
- break;
- }
+ int i_width, i_height, i_x, i_y;
- if( b_draw )
- {
- int i_dummy,
- i_window_width = p_vout->p_sys->i_window_width,
- i_window_height = p_vout->p_sys->i_window_height,
- i_dest_width, i_dest_height, i_dest_x, i_dest_y;
- Window window;
+ vout_PlacePicture( p_vout, p_vout->p_sys->i_width, p_vout->p_sys->i_height,
+ &i_x, &i_y, &i_width, &i_height );
-#if 1
- /* If I change the line above to "#if 0" I find on resizing the window
- * that blue rectangles (used to specify where part of the YUV overlay
- * used to be drawn) may remain around the edge of the video output. */
- XGetGeometry( p_vout->p_sys->p_display, p_vout->p_sys->window,
- &window, &i_dummy, &i_dummy,
- &i_window_width, &i_window_height, &i_dummy, &i_dummy );
-#endif
+ XvShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->i_xvport,
+ p_vout->p_sys->yuv_window, p_vout->p_sys->gc,
+ p_pic->p_sys->p_xvimage, 0 /*src_x*/, 0 /*src_y*/,
+ p_vout->output.i_width, p_vout->output.i_height,
+ 0 /*dest_x*/, 0 /*dest_y*/, i_width, i_height,
+ True );
- XVideoOutputCoords( p_vout->p_rendered_pic, p_vout->b_scale,
- i_window_width, i_window_height,
- &i_dest_x, &i_dest_y,
- &i_dest_width, &i_dest_height);
-
- XvShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->xv_port,
- p_vout->p_sys->window, p_vout->p_sys->gc,
- p_vout->p_sys->p_xvimage,
- 0 /*src_x*/, 0 /*src_y*/,
- p_vout->p_rendered_pic->i_width,
- p_vout->p_rendered_pic->i_height,
- i_dest_x, i_dest_y, i_dest_width, i_dest_height,
- True );
- }
-}
+ XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->yuv_window,
+ i_width, i_height );
-static void vout_SetPalette( p_vout_thread_t p_vout,
- u16 *red, u16 *green, u16 *blue, u16 *transp )
-{
- return;
+ XMoveWindow( p_vout->p_sys->p_display, p_vout->p_sys->yuv_window,
+ i_x, i_y );
}
/* following functions are local */
/*****************************************************************************
- * XVideoCheckForXv: check for the XVideo extension
+ * CheckForXVideo: check for the XVideo extension
*****************************************************************************/
-static int XVideoCheckForXv( Display *dpy )
+static int CheckForXVideo( Display *p_display )
{
unsigned int i;
- switch( XvQueryExtension( dpy, &i, &i, &i, &i, &i ) )
+ switch( XvQueryExtension( p_display, &i, &i, &i, &i, &i ) )
{
case Success:
return( 1 );
case XvBadExtension:
- intf_ErrMsg( "vout error: XvBadExtension" );
+ intf_WarnMsg( 3, "vout error: XvBadExtension" );
return( 0 );
case XvBadAlloc:
- intf_ErrMsg( "vout error: XvBadAlloc" );
+ intf_WarnMsg( 3, "vout error: XvBadAlloc" );
return( 0 );
default:
- intf_ErrMsg( "vout error: XvQueryExtension failed" );
+ intf_WarnMsg( 3, "vout error: XvQueryExtension failed" );
return( 0 );
}
}
/*****************************************************************************
- * XVideoCreateWindow: open and set-up XVideo main window
+ * XVideoNewPicture: allocate a picture
+ *****************************************************************************
+ * Returns 0 on success, -1 otherwise
*****************************************************************************/
-static int XVideoCreateWindow( vout_thread_t *p_vout )
+static int XVideoNewPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
- XSizeHints xsize_hints;
- XSetWindowAttributes xwindow_attributes;
- XGCValues xgcvalues;
- XEvent xevent;
- Atom prop;
- mwmhints_t mwmhints;
-
- boolean_t b_expose;
- boolean_t b_configure_notify;
- boolean_t b_map_notify;
-
-
- /* If we're full screen, we're full screen! */
- if( p_vout->p_sys->b_fullscreen )
- {
- p_vout->p_sys->i_window_width = DisplayWidth( p_vout->p_sys->p_display,
- p_vout->p_sys->i_screen );
- p_vout->p_sys->i_window_height = DisplayHeight( p_vout->p_sys->p_display,
- p_vout->p_sys->i_screen );
- p_vout->i_width = p_vout->p_sys->i_window_width;
- p_vout->i_height = p_vout->p_sys->i_window_height;
- }
- else
- {
- /* Set main window's size */
- p_vout->p_sys->i_window_width = main_GetIntVariable( VOUT_WIDTH_VAR,
- VOUT_WIDTH_DEFAULT );
- p_vout->p_sys->i_window_height = main_GetIntVariable( VOUT_HEIGHT_VAR,
- VOUT_HEIGHT_DEFAULT );
- }
+ int i_width = p_vout->output.i_width;
+ int i_height = p_vout->output.i_height;
- /* Prepare window manager hints and properties */
- xsize_hints.base_width = p_vout->p_sys->i_window_width;
- xsize_hints.base_height = p_vout->p_sys->i_window_height;
- xsize_hints.flags = PSize;
- p_vout->p_sys->wm_protocols = XInternAtom( p_vout->p_sys->p_display,
- "WM_PROTOCOLS", True );
- p_vout->p_sys->wm_delete_window = XInternAtom( p_vout->p_sys->p_display,
- "WM_DELETE_WINDOW", True );
-
- /* Prepare window attributes */
- xwindow_attributes.backing_store = Always; /* save the hidden part */
- xwindow_attributes.background_pixel = BlackPixel( p_vout->p_sys->p_display,
- p_vout->p_sys->i_screen );
-
- xwindow_attributes.event_mask = ExposureMask | StructureNotifyMask;
-
- /* Create the window and set hints - the window must receive ConfigureNotify
- * events, and, until it is displayed, Expose and MapNotify events. */
- p_vout->p_sys->window =
- XCreateWindow( p_vout->p_sys->p_display,
- DefaultRootWindow( p_vout->p_sys->p_display ),
- 0, 0,
- p_vout->p_sys->i_window_width,
- p_vout->p_sys->i_window_height, 1,
- 0, InputOutput, 0,
- CWBackingStore | CWBackPixel | CWEventMask,
- &xwindow_attributes );
-
- if ( p_vout->p_sys->b_fullscreen )
+ switch( p_vout->output.i_chroma )
{
- prop = XInternAtom(p_vout->p_sys->p_display, "_MOTIF_WM_HINTS", False);
- mwmhints.flags = MWM_HINTS_DECORATIONS;
- mwmhints.decorations = 0;
- XChangeProperty( p_vout->p_sys->p_display, p_vout->p_sys->window,
- prop, prop, 32, PropModeReplace,
- (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS );
-
- XSetTransientForHint( p_vout->p_sys->p_display,
- p_vout->p_sys->window, None );
- XRaiseWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
- }
+ case YUV_420_PICTURE:
+ /* We know this chroma, allocate a buffer which will be used
+ * directly by the decoder */
+ p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
-
- /* Set window manager hints and properties: size hints, command,
- * window's name, and accepted protocols */
- XSetWMNormalHints( p_vout->p_sys->p_display, p_vout->p_sys->window,
- &xsize_hints );
- XSetCommand( p_vout->p_sys->p_display, p_vout->p_sys->window,
- p_main->ppsz_argv, p_main->i_argc );
- XStoreName( p_vout->p_sys->p_display, p_vout->p_sys->window,
- VOUT_TITLE " (XVideo output)" );
-
- if( (p_vout->p_sys->wm_protocols == None) /* use WM_DELETE_WINDOW */
- || (p_vout->p_sys->wm_delete_window == None)
- || !XSetWMProtocols( p_vout->p_sys->p_display, p_vout->p_sys->window,
- &p_vout->p_sys->wm_delete_window, 1 ) )
- {
- /* WM_DELETE_WINDOW is not supported by window manager */
- intf_Msg( "vout error: missing or bad window manager" );
- }
+ if( p_pic->p_sys == NULL )
+ {
+ return -1;
+ }
- /* Creation of a graphic context that doesn't generate a GraphicsExpose
- * event when using functions like XCopyArea */
- xgcvalues.graphics_exposures = False;
- p_vout->p_sys->gc = XCreateGC( p_vout->p_sys->p_display,
- p_vout->p_sys->window,
- GCGraphicsExposures, &xgcvalues);
-
- /* Send orders to server, and wait until window is displayed - three
- * events must be received: a MapNotify event, an Expose event allowing
- * drawing in the window, and a ConfigureNotify to get the window
- * dimensions. Once those events have been received, only ConfigureNotify
- * events need to be received. */
- b_expose = 0;
- b_configure_notify = 0;
- b_map_notify = 0;
- XMapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
- do
- {
- XNextEvent( p_vout->p_sys->p_display, &xevent);
- if( (xevent.type == Expose)
- && (xevent.xexpose.window == p_vout->p_sys->window) )
- {
- b_expose = 1;
- }
- else if( (xevent.type == MapNotify)
- && (xevent.xmap.window == p_vout->p_sys->window) )
- {
- b_map_notify = 1;
- }
- else if( (xevent.type == ConfigureNotify)
- && (xevent.xconfigure.window == p_vout->p_sys->window) )
- {
- b_configure_notify = 1;
- p_vout->p_sys->i_window_width = xevent.xconfigure.width;
- p_vout->p_sys->i_window_height = xevent.xconfigure.height;
- }
- } while( !( b_expose && b_configure_notify && b_map_notify ) );
+ /* Create XvImage using XShm extension */
+ p_pic->p_sys->p_xvimage =
+ CreateShmImage( p_vout->p_sys->p_display,
+ p_vout->p_sys->i_xvport,
+ &p_pic->p_sys->shminfo,
+ p_vout->output.i_width,
+ p_vout->output.i_height );
+ if( p_pic->p_sys->p_xvimage == NULL )
+ {
+ free( p_pic->p_sys );
+ return -1;
+ }
- XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window,
- StructureNotifyMask | KeyPressMask |
- ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask );
- if( p_vout->p_sys->b_fullscreen )
- {
- XSetInputFocus( p_vout->p_sys->p_display, p_vout->p_sys->window,
- RevertToNone, CurrentTime );
- XMoveWindow( p_vout->p_sys->p_display, p_vout->p_sys->window, 0, 0 );
- }
+ /* Precalculate some values */
+ p_pic->i_size = i_width * i_height;
+ p_pic->i_chroma_width = i_width / 2;
+ p_pic->i_chroma_size = i_height * ( i_width / 2 );
- /* At this stage, the window is open, displayed, and ready to
- * receive data */
- return( 0 );
+ /* FIXME: try to get the right i_bytes value from p_xvimage */
+ p_pic->planes[Y_PLANE].p_data = p_pic->p_sys->p_xvimage->data;
+ p_pic->planes[Y_PLANE].i_bytes = p_pic->i_size * sizeof(u8);
+ p_pic->planes[Y_PLANE].i_line_bytes = i_width * sizeof(u8);
+
+ p_pic->planes[U_PLANE].p_data = (u8*)p_pic->p_sys->p_xvimage->data
+ + p_pic->i_size * 5 / 4;
+ p_pic->planes[U_PLANE].i_bytes = p_pic->i_size * sizeof(u8) / 4;
+ p_pic->planes[U_PLANE].i_line_bytes = p_pic->i_chroma_width
+ * sizeof(u8);
+
+ p_pic->planes[V_PLANE].p_data = (u8*)p_pic->p_sys->p_xvimage->data
+ + p_pic->i_size;
+ p_pic->planes[V_PLANE].i_bytes = p_pic->i_size * sizeof(u8) / 4;
+ p_pic->planes[V_PLANE].i_line_bytes = p_pic->i_chroma_width
+ * sizeof(u8);
+
+ p_pic->i_planes = 3;
+
+ return 0;
+
+ default:
+ /* Unknown chroma, tell the guy to get lost */
+ p_pic->i_planes = 0;
+
+ return -1;
+ }
}
/*****************************************************************************
- * XVideoCreateShmImage: create an XvImage using shared memory extension
+ * CreateShmImage: create an XvImage using shared memory extension
*****************************************************************************
* Prepare an XvImage for display function.
* The order of the operations respects the recommandations of the mit-shm
* document by J.Corbet and K.Packard. Most of the parameters were copied from
* there.
*****************************************************************************/
-static int XVideoCreateShmImage( Display* dpy, int xv_port,
- XvImage **pp_xvimage,
- XShmSegmentInfo *p_shm_info,
- int i_width, int i_height )
+static XvImage *CreateShmImage( Display* p_display, int i_xvport,
+ XShmSegmentInfo *p_shminfo,
+ int i_width, int i_height )
{
- *pp_xvimage = XvShmCreateImage( dpy, xv_port,
- GUID_YUV12_PLANAR, 0,
- i_width, i_height,
- p_shm_info );
- if( !(*pp_xvimage) )
+ XvImage *p_xvimage;
+
+ p_xvimage = XvShmCreateImage( p_display, i_xvport,
+ GUID_YUV12_PLANAR, 0,
+ i_width, i_height,
+ p_shminfo );
+ if( p_xvimage == NULL )
{
intf_ErrMsg( "vout error: XvShmCreateImage failed." );
- return( -1 );
+ return( NULL );
}
- p_shm_info->shmid = shmget( IPC_PRIVATE, (*pp_xvimage)->data_size,
- IPC_CREAT | 0777 );
- if( p_shm_info->shmid < 0) /* error */
+ p_shminfo->shmid = shmget( IPC_PRIVATE, p_xvimage->data_size,
+ IPC_CREAT | 0776 );
+ if( p_shminfo->shmid < 0 ) /* error */
{
intf_ErrMsg( "vout error: cannot allocate shared image data (%s)",
- strerror(errno));
- return( 1 );
+ strerror( errno ) );
+ return( NULL );
}
- p_shm_info->shmaddr = (*pp_xvimage)->data = shmat( p_shm_info->shmid,
- 0, 0 );
- p_shm_info->readOnly = False;
+ p_shminfo->shmaddr = p_xvimage->data = shmat( p_shminfo->shmid, 0, 0 );
+ p_shminfo->readOnly = False;
- /* Mark the shm segment to be removed when there will be no more
- * attachements, so it is automatic on process exit or after shmdt */
- shmctl( p_shm_info->shmid, IPC_RMID, 0 );
-
- if( !XShmAttach( dpy, p_shm_info ) )
+ if( !XShmAttach( p_display, p_shminfo ) )
{
intf_ErrMsg( "vout error: XShmAttach failed" );
- shmdt( p_shm_info->shmaddr );
- return( -1 );
+ shmctl( p_shminfo->shmid, IPC_RMID, 0 );
+ shmdt( p_shminfo->shmaddr );
+ return( NULL );
}
/* Send image to X server. This instruction is required, since having
* built a Shm XImage and not using it causes an error on XCloseDisplay */
- XFlush( dpy );
+ XSync( p_display, False );
- return( 0 );
+#if 1
+ /* Mark the shm segment to be removed when there are no more
+ * attachements, so it is automatic on process exit or after shmdt */
+ shmctl( p_shminfo->shmid, IPC_RMID, 0 );
+#endif
+
+ return( p_xvimage );
}
/*****************************************************************************
- * XVideoDestroyShmImage
+ * DestroyShmImage
*****************************************************************************
* Destroy XImage AND associated data. Detach shared memory segment from
* server and process, then free it. If pointer is NULL, the image won't be
- * destroyed (see vout_ManageOutputMethod())
+ * destroyed (see vout_Manage())
*****************************************************************************/
-static void XVideoDestroyShmImage( vout_thread_t *p_vout, XvImage *p_xvimage,
- XShmSegmentInfo *p_shm_info )
+static void DestroyShmImage( Display *p_display, XvImage *p_xvimage,
+ XShmSegmentInfo *p_shminfo )
{
- /* If pointer is NULL, do nothing */
- if( p_xvimage == NULL )
- {
- return;
- }
+ /* Detach from server */
+ XShmDetach( p_display, p_shminfo );
+ XSync( p_display, False );
- XShmDetach( p_vout->p_sys->p_display, p_shm_info );/* detach from server */
#if 0
- XDestroyImage( p_ximage ); /* XXX */
+ XDestroyImage( p_xvimage ); /* XXX */
#endif
- if( shmdt( p_shm_info->shmaddr ) ) /* detach shared memory from process */
- { /* also automatic freeing... */
+ XFree( p_xvimage );
+
+ if( shmdt( p_shminfo->shmaddr ) ) /* detach shared memory from process */
+ {
intf_ErrMsg( "vout error: cannot detach shared memory (%s)",
strerror(errno) );
}
}
/*****************************************************************************
- * XVideoEnableScreenSaver: enable screen saver
+ * GetXVideoPort: get YUV12 port
*****************************************************************************
- * This function enable the screen saver on a display after it had been
- * disabled by XDisableScreenSaver. Both functions use a counter mechanism to
- * know wether the screen saver can be activated or not: if n successive calls
- * are made to XDisableScreenSaver, n successive calls to XEnableScreenSaver
- * will be required before the screen saver could effectively be activated.
+ *
*****************************************************************************/
-void XVideoEnableScreenSaver( vout_thread_t *p_vout )
+static int GetXVideoPort( Display *dpy )
{
- intf_DbgMsg( "intf: enabling screen saver" );
- XSetScreenSaver( p_vout->p_sys->p_display, p_vout->p_sys->i_ss_timeout,
- p_vout->p_sys->i_ss_interval,
- p_vout->p_sys->i_ss_blanking,
- p_vout->p_sys->i_ss_exposure );
-}
+ XvAdaptorInfo *p_adaptor;
+ int i_adaptor, i_num_adaptors, i_requested_adaptor;
+ int i_selected_port;
-/*****************************************************************************
- * XVideoDisableScreenSaver: disable screen saver
- *****************************************************************************
- * See XEnableScreenSaver
- *****************************************************************************/
-void XVideoDisableScreenSaver( vout_thread_t *p_vout )
-{
- /* Save screen saver informations */
- XGetScreenSaver( p_vout->p_sys->p_display, &p_vout->p_sys->i_ss_timeout,
- &p_vout->p_sys->i_ss_interval,
- &p_vout->p_sys->i_ss_blanking,
- &p_vout->p_sys->i_ss_exposure );
-
- /* Disable screen saver */
- intf_DbgMsg( "intf: disabling screen saver" );
- XSetScreenSaver( p_vout->p_sys->p_display, 0,
- p_vout->p_sys->i_ss_interval,
- p_vout->p_sys->i_ss_blanking,
- p_vout->p_sys->i_ss_exposure );
-}
+ switch( XvQueryAdaptors( dpy, DefaultRootWindow( dpy ),
+ &i_num_adaptors, &p_adaptor ) )
+ {
+ case Success:
+ break;
-/*****************************************************************************
- * XVideoTogglePointer: hide or show the mouse pointer
- *****************************************************************************
- * This function hides the X pointer if it is visible by putting it at
- * coordinates (32,32) and setting the pointer sprite to a blank one. To
- * show it again, we disable the sprite and restore the original coordinates.
- *****************************************************************************/
-void XVideoTogglePointer( vout_thread_t *p_vout )
-{
- static Cursor cursor;
- static boolean_t b_cursor = 0;
+ case XvBadExtension:
+ intf_WarnMsg( 3, "vout error: XvBadExtension for XvQueryAdaptors" );
+ return( -1 );
- if( p_vout->p_sys->b_mouse )
- {
- p_vout->p_sys->b_mouse = 0;
+ case XvBadAlloc:
+ intf_WarnMsg( 3, "vout error: XvBadAlloc for XvQueryAdaptors" );
+ return( -1 );
- if( !b_cursor )
- {
- XColor color;
- Pixmap blank = XCreatePixmap( p_vout->p_sys->p_display,
- DefaultRootWindow(p_vout->p_sys->p_display),
- 1, 1, 1 );
-
- XParseColor( p_vout->p_sys->p_display,
- XCreateColormap( p_vout->p_sys->p_display,
- DefaultRootWindow(
- p_vout->p_sys->p_display ),
- DefaultVisual(
- p_vout->p_sys->p_display,
- p_vout->p_sys->i_screen ),
- AllocNone ),
- "black", &color );
-
- cursor = XCreatePixmapCursor( p_vout->p_sys->p_display,
- blank, blank, &color, &color, 1, 1 );
-
- b_cursor = 1;
- }
- XDefineCursor( p_vout->p_sys->p_display,
- p_vout->p_sys->window, cursor );
+ default:
+ intf_WarnMsg( 3, "vout error: XvQueryAdaptors failed" );
+ return( -1 );
}
- else
- {
- p_vout->p_sys->b_mouse = 1;
- XUndefineCursor( p_vout->p_sys->p_display, p_vout->p_sys->window );
- }
-}
+ i_selected_port = -1;
+ i_requested_adaptor = main_GetIntVariable( VOUT_XVADAPTOR_VAR, -1 );
-/* This based on some code in SetBufferPicture... At the moment it's only
- * used by the xvideo plugin, but others may want to use it. */
-static void XVideoOutputCoords( const picture_t *p_pic, const boolean_t scale,
- const int win_w, const int win_h,
- int *dx, int *dy, int *w, int *h)
-{
- if( !scale )
+ /* No special xv port has been requested so try all of them */
+ for( i_adaptor = 0; i_adaptor < i_num_adaptors; ++i_adaptor )
{
- *w = p_pic->i_width; *h = p_pic->i_height;
- }
- else
- {
- *w = win_w;
- switch( p_pic->i_aspect_ratio )
+ XvImageFormatValues *p_formats;
+ int i_format, i_num_formats;
+ int i_port;
+
+ /* If we requested an adaptor and it's not this one, we aren't
+ * interested */
+ if( i_requested_adaptor != -1 && i_adaptor != i_requested_adaptor )
+ {
+ continue;
+ }
+
+ /* If the adaptor doesn't have the required properties, skip it */
+ if( !( p_adaptor[ i_adaptor ].type & XvInputMask ) ||
+ !( p_adaptor[ i_adaptor ].type & XvImageMask ) )
{
- case AR_3_4_PICTURE: *h = win_w * 3 / 4; break;
- case AR_16_9_PICTURE: *h = win_w * 9 / 16; break;
- case AR_221_1_PICTURE: *h = win_w * 100 / 221; break;
- case AR_SQUARE_PICTURE:
- default: *h = win_w; break;
- }
+ continue;
+ }
- if( *h > win_h )
+ /* Check that port supports YUV12 planar format... */
+ p_formats = XvListImageFormats( dpy, p_adaptor[i_adaptor].base_id,
+ &i_num_formats );
+
+ for( i_format = 0; i_format < i_num_formats; i_format++ )
{
- *h = win_h;
- switch( p_pic->i_aspect_ratio )
+ XvEncodingInfo *p_enc;
+ int i_enc, i_num_encodings;
+ XvAttribute *p_attr;
+ int i_attr, i_num_attributes;
+
+ /* If this is not the format we want, forget it */
+ if( p_formats[ i_format ].id != GUID_YUV12_PLANAR )
{
- case AR_3_4_PICTURE: *w = win_h * 4 / 3; break;
- case AR_16_9_PICTURE: *w = win_h * 16 / 9; break;
- case AR_221_1_PICTURE: *w = win_h * 221 / 100; break;
- case AR_SQUARE_PICTURE:
- default: *w = win_h; break;
+ continue;
}
- }
- }
-
- /* Set picture position */
- *dx = (win_w - *w) / 2;
- *dy = (win_h - *h) / 2;
-}
+ /* Look for the first available port supporting this format */
+ for( i_port = p_adaptor[i_adaptor].base_id;
+ ( i_port < p_adaptor[i_adaptor].base_id
+ + p_adaptor[i_adaptor].num_ports )
+ && ( i_selected_port == -1 );
+ i_port++ )
+ {
+ if( XvGrabPort( dpy, i_port, CurrentTime ) == Success )
+ {
+ i_selected_port = i_port;
+ }
+ }
-static int XVideoGetPort( Display *dpy )
-{
- int i, i_adaptors;
- int xv_port = -1;
- XvAdaptorInfo *adaptor_info;
-
- switch( XvQueryAdaptors( dpy, DefaultRootWindow( dpy ),
- &i_adaptors, &adaptor_info ) )
- {
- case Success:
- break;
+ /* If no free port was found, forget it */
+ if( i_selected_port == -1 )
+ {
+ continue;
+ }
- case XvBadExtension:
- intf_ErrMsg( "vout error: XvBadExtension for XvQueryAdaptors" );
- return( -1 );
+ /* If we found a port, print information about it */
+ intf_WarnMsg( 3, "vout: GetXVideoPort found adaptor %i, port %i",
+ i_adaptor, i_selected_port );
+ intf_WarnMsg( 3, " image format 0x%x (%4.4s) %s supported",
+ p_formats[ i_format ].id,
+ (char *)&p_formats[ i_format ].id,
+ ( p_formats[ i_format ].format
+ == XvPacked ) ? "packed" : "planar" );
- case XvBadAlloc:
- intf_ErrMsg( "vout error: XvBadAlloc for XvQueryAdaptors" );
- return( -1 );
+ intf_WarnMsg( 4, " encoding list:" );
- default:
- intf_ErrMsg( "vout error: XvQueryAdaptors failed" );
- return( -1 );
- }
+ if( XvQueryEncodings( dpy, i_selected_port,
+ &i_num_encodings, &p_enc )
+ != Success )
+ {
+ intf_WarnMsg( 4, " XvQueryEncodings failed" );
+ continue;
+ }
- for( i=0; i < i_adaptors && xv_port == -1; ++i )
- if( ( adaptor_info[ i ].type & XvInputMask ) &&
- ( adaptor_info[ i ].type & XvImageMask ) )
- {
- /* check that port supports YUV12 planar format... */
- int port = adaptor_info[ i ].base_id;
- int i_num_formats, i;
- XvImageFormatValues *imageFormats;
+ for( i_enc = 0; i_enc < i_num_encodings; i_enc++ )
+ {
+ intf_WarnMsg( 4, " id=%ld, name=%s, size=%ldx%ld,"
+ " numerator=%d, denominator=%d",
+ p_enc[i_enc].encoding_id, p_enc[i_enc].name,
+ p_enc[i_enc].width, p_enc[i_enc].height,
+ p_enc[i_enc].rate.numerator,
+ p_enc[i_enc].rate.denominator );
+ }
- imageFormats = XvListImageFormats( dpy, port, &i_num_formats );
+ if( p_enc != NULL )
+ {
+ XvFreeEncodingInfo( p_enc );
+ }
- for( i=0; i < i_num_formats && xv_port == -1; ++i )
- if( imageFormats[ i ].id == GUID_YUV12_PLANAR )
- xv_port = port;
+ intf_WarnMsg( 4, " attribute list:" );
+ p_attr = XvQueryPortAttributes( dpy, i_selected_port,
+ &i_num_attributes );
+ for( i_attr = 0; i_attr < i_num_attributes; i_attr++ )
+ {
+ intf_WarnMsg( 4,
+ " name=%s, flags=[%s%s ], min=%i, max=%i",
+ p_attr[i_attr].name,
+ (p_attr[i_attr].flags & XvGettable) ? " get" : "",
+ (p_attr[i_attr].flags & XvSettable) ? " set" : "",
+ p_attr[i_attr].min_value, p_attr[i_attr].max_value );
+ }
- if( xv_port == -1 )
- intf_WarnMsg( 3, "vout: XVideo image input port %d "
- "does not support the YUV12 planar format which is "
- "currently required by the xvideo output plugin.",
- port );
+ if( p_attr != NULL )
+ {
+ XFree( p_attr );
+ }
+ }
- if( imageFormats )
- XFree( imageFormats );
+ if( p_formats != NULL )
+ {
+ XFree( p_formats );
}
- if( i_adaptors > 0 )
- XvFreeAdaptorInfo(adaptor_info);
+ }
- if( xv_port == -1 )
- intf_ErrMsg( "vout error: didn't find a suitable Xvideo image input port." );
+ if( i_num_adaptors > 0 )
+ {
+ XvFreeAdaptorInfo( p_adaptor );
+ }
- return( xv_port );
-}
+ if( i_selected_port == -1 )
+ {
+ if( i_requested_adaptor == -1 )
+ {
+ intf_WarnMsg( 3, "vout: no free XVideo port found for YV12" );
+ }
+ else
+ {
+ intf_WarnMsg( 3, "vout: XVideo adaptor %i does not have a free "
+ "XVideo port for YV12", i_requested_adaptor );
+ }
+ }
+ return( i_selected_port );
+}
#if 0
/*****************************************************************************
{
int i_attrib;
XvAttribute *p_attrib;
- Display *p_dpy = p_vout->p_sys->p_display;
- int xv_port = p_vout->p_sys->xv_port;
+ Display *p_display = p_vout->p_sys->p_display;
+ int i_xvport = p_vout->p_sys->i_xvport;
- p_attrib = XvQueryPortAttributes( p_dpy, xv_port, &i_attrib );
+ p_attrib = XvQueryPortAttributes( p_display, i_xvport, &i_attrib );
do
{
- p_attrib[ i_attrib ].min_value + 1 )
+ p_attrib[ i_attrib ].min_value;
- XvSetPortAttribute( p_dpy, xv_port,
- XInternAtom( p_dpy, attr_name, False ), i_sv );
+ XvSetPortAttribute( p_display, i_xvport,
+ XInternAtom( p_display, attr_name, False ), i_sv );
break;
}
XFree( p_attrib );
}
#endif
+