📄 vout_x11.c
字号:
/***************************************************************************** * vout_x11.c: X11 video output display method ***************************************************************************** * Copyright (C) 1998, 1999, 2000 VideoLAN * * Authors: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include "defs.h"#include <errno.h> /* ENOMEM */#include <stdlib.h> /* free() */#include <string.h> /* strerror() */#ifdef SYS_BSD#include <sys/types.h> /* typedef ushort */#endif#include <sys/shm.h> /* shmget(), shmctl() */#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/extensions/XShm.h>#include "config.h"#include "common.h"#include "threads.h"#include "mtime.h"#include "plugins.h"#include "video.h"#include "video_output.h"#include "intf_msg.h"/***************************************************************************** * vout_sys_t: video output X11 method descriptor ***************************************************************************** * This structure is part of the video output thread descriptor. * It describes the X11 specific properties of an output thread. X11 video * output is performed through regular resizable windows. Windows can be * dynamically resized to adapt to the size of the streams. *****************************************************************************/typedef struct vout_sys_s{ /* User settings */ boolean_t b_shm; /* shared memory extension flag */ /* Internal settings and properties */ Display * p_display; /* display pointer */ Visual * p_visual; /* visual pointer */ int i_screen; /* screen number */ Window root_window; /* root window */ Window window; /* window instance handler */ GC gc; /* graphic context instance handler */ Colormap colormap; /* colormap used (8bpp only) */ /* Display buffers and shared memory information */ XImage * p_ximage[2]; /* XImage pointer */ XShmSegmentInfo shm_info[2]; /* shared memory zone information */} vout_sys_t;/***************************************************************************** * Local prototypes *****************************************************************************/static int X11OpenDisplay ( vout_thread_t *p_vout, char *psz_display, Window root_window, void *p_data );static void X11CloseDisplay ( vout_thread_t *p_vout );static int X11CreateWindow ( vout_thread_t *p_vout );static void X11DestroyWindow ( vout_thread_t *p_vout );static int X11CreateImage ( vout_thread_t *p_vout, XImage **pp_ximage );static void X11DestroyImage ( XImage *p_ximage );static int X11CreateShmImage ( vout_thread_t *p_vout, XImage **pp_ximage, XShmSegmentInfo *p_shm_info );static void X11DestroyShmImage ( vout_thread_t *p_vout, XImage *p_ximage, XShmSegmentInfo *p_shm_info );static void X11SetPalette ( p_vout_thread_t p_vout, u16 *red, u16 *green, u16 *blue, u16 *transp );/***************************************************************************** * vout_SysCreate: allocate X11 video thread output method ***************************************************************************** * This function allocate and initialize a X11 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. *****************************************************************************/int vout_SysCreate( vout_thread_t *p_vout, char *psz_display, int i_root_window, void *p_data ){ /* Allocate structure */ p_vout->p_sys = malloc( sizeof( vout_sys_t ) ); if( p_vout->p_sys == NULL ) { intf_ErrMsg("error: %s\n", strerror(ENOMEM) ); return( 1 ); } /* Open and initialize device. This function issues its own error messages. * Since XLib is usually not thread-safe, we can't use the same display * pointer than the interface or another thread. However, the root window * id is still valid. */ if( X11OpenDisplay( p_vout, psz_display, i_root_window, p_data ) ) { intf_ErrMsg("error: can't initialize X11 display\n" ); free( p_vout->p_sys ); return( 1 ); } return( 0 );}/***************************************************************************** * vout_SysInit: initialize X11 video thread output method ***************************************************************************** * This function create the XImages needed by the output thread. It is called * at the beginning of the thread, but also each time the window is resized. *****************************************************************************/int vout_SysInit( vout_thread_t *p_vout ){ int i_err; /* Initialize palette changing procedure */ p_vout->p_set_palette = X11SetPalette; /* Create XImages using XShm extension - on failure, fall back to regular * way (and destroy the first image if it was created successfully) */ if( p_vout->p_sys->b_shm ) { /* Create first image */ i_err = X11CreateShmImage( p_vout, &p_vout->p_sys->p_ximage[0], &p_vout->p_sys->shm_info[0] ); if( !i_err ) /* first image has been created */ { /* Create second image */ if( X11CreateShmImage( p_vout, &p_vout->p_sys->p_ximage[1], &p_vout->p_sys->shm_info[1] ) ) { /* error creating the second image */ X11DestroyShmImage( p_vout, p_vout->p_sys->p_ximage[0], &p_vout->p_sys->shm_info[0] ); i_err = 1; } } if( i_err ) /* an error occured */ { intf_Msg("XShm video sextension desactivated\n" ); p_vout->p_sys->b_shm = 0; } } /* Create XImages without XShm extension */ if( !p_vout->p_sys->b_shm ) { if( X11CreateImage( p_vout, &p_vout->p_sys->p_ximage[0] ) ) { intf_ErrMsg("error: can't create images\n"); p_vout->p_sys->p_ximage[0] = NULL; p_vout->p_sys->p_ximage[1] = NULL; return( 1 ); } if( X11CreateImage( p_vout, &p_vout->p_sys->p_ximage[1] ) ) { intf_ErrMsg("error: can't create images\n"); X11DestroyImage( p_vout->p_sys->p_ximage[0] ); p_vout->p_sys->p_ximage[0] = NULL; p_vout->p_sys->p_ximage[1] = NULL; return( 1 ); } } /* Set bytes per line and initialize buffers */ p_vout->i_bytes_per_line = p_vout->p_sys->p_ximage[0]->bytes_per_line; vout_SetBuffers( p_vout, p_vout->p_sys->p_ximage[ 0 ]->data, p_vout->p_sys->p_ximage[ 1 ]->data ); return( 0 );}/***************************************************************************** * vout_SysEnd: terminate X11 video thread output method ***************************************************************************** * Destroy the X11 XImages created by vout_SysInit. It is called at the end of * the thread, but also each time the window is resized. *****************************************************************************/void vout_SysEnd( vout_thread_t *p_vout ){ if( p_vout->p_sys->b_shm ) /* Shm XImages... */ { X11DestroyShmImage( p_vout, p_vout->p_sys->p_ximage[0], &p_vout->p_sys->shm_info[0] ); X11DestroyShmImage( p_vout, p_vout->p_sys->p_ximage[1], &p_vout->p_sys->shm_info[1] ); } else /* ...or regular XImages */ { X11DestroyImage( p_vout->p_sys->p_ximage[0] ); X11DestroyImage( p_vout->p_sys->p_ximage[1] ); }}/***************************************************************************** * vout_SysDestroy: destroy X11 video thread output method ***************************************************************************** * Terminate an output method created by vout_CreateOutputMethod *****************************************************************************/void vout_SysDestroy( vout_thread_t *p_vout ){ X11CloseDisplay( p_vout ); free( p_vout->p_sys );}/***************************************************************************** * vout_SysManage: 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. *****************************************************************************/int vout_SysManage( vout_thread_t *p_vout ){ /* * Color/Grayscale or gamma change: in 8bpp, just change the colormap */ if( (p_vout->i_changes & VOUT_GRAYSCALE_CHANGE) && (p_vout->i_screen_depth == 8) ) { /* FIXME: clear flags ?? */ } /* * Size change */ if( p_vout->i_changes & VOUT_SIZE_CHANGE ) { intf_DbgMsg("resizing window\n"); p_vout->i_changes &= ~VOUT_SIZE_CHANGE; /* Resize window */ XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->i_width, p_vout->i_height ); /* Destroy XImages to change their size */ vout_SysEnd( p_vout ); /* Recreate XImages. If SysInit failed, the thread can't go on. */ if( vout_SysInit( p_vout ) ) { intf_ErrMsg("error: can't resize display\n"); return( 1 ); } /* Tell the video output thread that it will need to rebuild YUV * tables. This is needed since conversion buffer size may have changed */ p_vout->i_changes |= VOUT_YUV_CHANGE; intf_Msg("Video display resized (%dx%d)\n", p_vout->i_width, p_vout->i_height); } return 0;}/***************************************************************************** * vout_SysDisplay: displays previously rendered output ***************************************************************************** * This function send the currently rendered image to X11 server, wait until * it is displayed and switch the two rendering buffer, preparing next frame. *****************************************************************************/void vout_SysDisplay( vout_thread_t *p_vout ){ if( p_vout->p_sys->b_shm) /* XShm is used */ { /* Display rendered image using shared memory extension */ XShmPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc, p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ], 0, 0, 0, 0, p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ]->width, p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ]->height, True); /* Send the order to the X server */ XFlush(p_vout->p_sys->p_display); } else /* regular X11 capabilities are used */ { XPutImage(p_vout->p_sys->p_display, p_vout->p_sys->window, p_vout->p_sys->gc, p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ], 0, 0, 0, 0, p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ]->width, p_vout->p_sys->p_ximage[ p_vout->i_buffer_index ]->height); /* Send the order to the X server */ XFlush(p_vout->p_sys->p_display); }}/* following functions are local *//***************************************************************************** * X11OpenDisplay: open and initialize X11 device ***************************************************************************** * Create a window according to video output given size, and set other * properties according to the display properties. *****************************************************************************/static int X11OpenDisplay( vout_thread_t *p_vout, char *psz_display, Window root_window, void *p_data ){ XPixmapFormatValues * p_xpixmap_format; /* pixmap formats */ XVisualInfo * p_xvisual; /* visuals informations */ XVisualInfo xvisual_template; /* visual template */ int i_count; /* array size */ /* Open display */ p_vout->p_sys->p_display = XOpenDisplay( psz_display ); if( p_vout->p_sys->p_display == NULL ) { intf_ErrMsg("error: can't open display %s\n", psz_display ); return( 1 ); } /* Initialize structure */ p_vout->p_sys->root_window = root_window; p_vout->p_sys->b_shm = (XShmQueryExtension(p_vout->p_sys->p_display) == True); p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display ); if( !p_vout->p_sys->b_shm ) { intf_Msg("XShm video extension is not available\n"); } /* Get screen depth */ p_vout->i_screen_depth = XDefaultDepth( p_vout->p_sys->p_display, p_vout->p_sys->i_screen ); switch( p_vout->i_screen_depth ) { case 8: /* * Screen depth is 8bpp. Use PseudoColor visual with private colormap. */ xvisual_template.screen = p_vout->p_sys->i_screen; xvisual_template.class = DirectColor;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -