📄 xcommon.c
字号:
*****************************************************************************/static int InitVideo( vout_thread_t *p_vout ){ int i_index; picture_t *p_pic; I_OUTPUTPICTURES = 0;#ifdef MODULE_NAME_IS_xvideo /* Initialize the output structure; we already found an XVideo port, * and the corresponding chroma we will be using. Since we can * arbitrary scale, stick to the coordinates and aspect. */ 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; switch( p_vout->output.i_chroma ) { case VLC_FOURCC('R','V','1','5'): p_vout->output.i_rmask = 0x001f; p_vout->output.i_gmask = 0x07e0; p_vout->output.i_bmask = 0xf800; break; case VLC_FOURCC('R','V','1','6'): p_vout->output.i_rmask = 0x001f; p_vout->output.i_gmask = 0x03e0; p_vout->output.i_bmask = 0x7c00; break; }#elif defined(MODULE_NAME_IS_x11) /* Initialize the output structure: RGB with square pixels, whatever * the input format is, since it's the only format we know */ switch( p_vout->p_sys->i_screen_depth ) { case 8: /* FIXME: set the palette */ p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); break; case 15: p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); break; case 16: p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6'); break; case 24: case 32: p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2'); break; default: msg_Err( p_vout, "unknown screen depth %i", p_vout->p_sys->i_screen_depth ); return VLC_SUCCESS; } vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width, p_vout->p_sys->p_win->i_height, &i_index, &i_index, &p_vout->output.i_width, &p_vout->output.i_height ); /* Assume we have square pixels */ p_vout->output.i_aspect = p_vout->output.i_width * VOUT_ASPECT_FACTOR / p_vout->output.i_height;#endif /* Try to initialize up to MAX_DIRECTBUFFERS direct buffers */ while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS ) { p_pic = NULL; /* Find an empty picture slot */ for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ ) { if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE ) { p_pic = p_vout->p_picture + i_index; break; } } /* Allocate the picture */ if( p_pic == NULL || NewPicture( p_vout, p_pic ) ) { break; } p_pic->i_status = DESTROYED_PICTURE; p_pic->i_type = DIRECT_PICTURE; PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; I_OUTPUTPICTURES++; } if( p_vout->output.i_chroma == VLC_FOURCC('Y','V','1','2') ) { /* U and V inverted compared to I420 * Fixme: this should be handled by the vout core */ p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0'); } return VLC_SUCCESS;}/***************************************************************************** * DisplayVideo: displays previously rendered output ***************************************************************************** * This function sends the currently rendered image to X11 server. * (The Xv extension takes care of "double-buffering".) *****************************************************************************/static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic ){ int i_width, i_height, i_x, i_y; vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width, p_vout->p_sys->p_win->i_height, &i_x, &i_y, &i_width, &i_height ); vlc_mutex_lock( &p_vout->p_sys->lock );#ifdef HAVE_SYS_SHM_H if( p_vout->p_sys->b_shm ) { /* Display rendered image using shared memory extension */# ifdef MODULE_NAME_IS_xvideo XvShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->i_xvport, p_vout->p_sys->p_win->video_window, p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image, 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, False /* Don't put True here or you'll waste your CPU */ );# else XShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->p_win->video_window, p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image, 0 /*src_x*/, 0 /*src_y*/, 0 /*dest_x*/, 0 /*dest_y*/, p_vout->output.i_width, p_vout->output.i_height, False /* Don't put True here ! */ );# endif } else#endif /* HAVE_SYS_SHM_H */ { /* Use standard XPutImage -- this is gonna be slow ! */#ifdef MODULE_NAME_IS_xvideo XvPutImage( p_vout->p_sys->p_display, p_vout->p_sys->i_xvport, p_vout->p_sys->p_win->video_window, p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image, 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 );#else XPutImage( p_vout->p_sys->p_display, p_vout->p_sys->p_win->video_window, p_vout->p_sys->p_win->gc, p_pic->p_sys->p_image, 0 /*src_x*/, 0 /*src_y*/, 0 /*dest_x*/, 0 /*dest_y*/, p_vout->output.i_width, p_vout->output.i_height );#endif } /* Make sure the command is sent now - do NOT use XFlush !*/ XSync( p_vout->p_sys->p_display, False ); vlc_mutex_unlock( &p_vout->p_sys->lock );}/***************************************************************************** * ManageVideo: 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. *****************************************************************************/static int ManageVideo( vout_thread_t *p_vout ){ XEvent xevent; /* X11 event */ vlc_value_t val; vlc_mutex_lock( &p_vout->p_sys->lock ); /* Handle events from the owner window */ if( p_vout->p_sys->p_win->owner_window ) { while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->p_win->owner_window, StructureNotifyMask, &xevent ) == True ) { /* ConfigureNotify event: prepare */ if( xevent.type == ConfigureNotify ) { /* Update dimensions */ XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->p_win->base_window, xevent.xconfigure.width, xevent.xconfigure.height ); } } } /* 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->p_win->base_window, StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | Button1MotionMask , &xevent ) == True ) { /* ConfigureNotify event: prepare */ if( xevent.type == ConfigureNotify ) { if( (unsigned int)xevent.xconfigure.width != p_vout->p_sys->p_win->i_width || (unsigned int)xevent.xconfigure.height != p_vout->p_sys->p_win->i_height ) { /* Update dimensions */ p_vout->i_changes |= VOUT_SIZE_CHANGE; p_vout->p_sys->p_win->i_width = xevent.xconfigure.width; p_vout->p_sys->p_win->i_height = xevent.xconfigure.height; } } /* Keyboard event */ else if( xevent.type == KeyPress ) { unsigned int state = xevent.xkey.state; KeySym x_key_symbol; char i_key; /* ISO Latin-1 key */ /* We may have keys like F1 trough F12, ESC ... */ x_key_symbol = XKeycodeToKeysym( p_vout->p_sys->p_display, xevent.xkey.keycode, 0 ); val.i_int = ConvertKey( (int)x_key_symbol ); xevent.xkey.state &= ~ShiftMask; xevent.xkey.state &= ~ControlMask; xevent.xkey.state &= ~Mod1Mask; if( !val.i_int && XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) ) { /* "Normal Keys" * The reason why I use this instead of XK_0 is that * with XLookupString, we don't have to care about * keymaps. */ val.i_int = i_key; } if( val.i_int ) { if( state & ShiftMask ) { val.i_int |= KEY_MODIFIER_SHIFT; } if( state & ControlMask ) { val.i_int |= KEY_MODIFIER_CTRL; } if( state & Mod1Mask ) { val.i_int |= KEY_MODIFIER_ALT; } var_Set( p_vout->p_vlc, "key-pressed", val ); } } /* Mouse click */ else if( xevent.type == ButtonPress ) { switch( ((XButtonEvent *)&xevent)->button ) { case Button1: var_Get( p_vout, "mouse-button-down", &val ); val.i_int |= 1; var_Set( p_vout, "mouse-button-down", val ); /* detect double-clicks */ if( ( ((XButtonEvent *)&xevent)->time - p_vout->p_sys->i_time_button_last_pressed ) < 300 ) { p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE; } p_vout->p_sys->i_time_button_last_pressed = ((XButtonEvent *)&xevent)->time; break; case Button2: var_Get( p_vout, "mouse-button-down", &val ); val.i_int |= 2; var_Set( p_vout, "mouse-button-down", val ); break; case Button3: var_Get( p_vout, "mouse-button-down", &val ); val.i_int |= 4; var_Set( p_vout, "mouse-button-down", val ); break; case Button4: var_Get( p_vout, "mouse-button-down", &val ); val.i_int |= 8; var_Set( p_vout, "mouse-button-down", val ); break; case Button5: var_Get( p_vout, "mouse-button-down", &val ); val.i_int |= 16; var_Set( p_vout, "mouse-button-down", val ); break; } } /* Mouse release */ else if( xevent.type == ButtonRelease ) { switch( ((XButtonEvent *)&xevent)->button ) { case Button1: var_Get( p_vout, "mouse-button-down", &val ); val.i_int &= ~1; var_Set( p_vout, "mouse-button-down", val ); val.b_bool = VLC_TRUE; var_Set( p_vout, "mouse-clicked", val ); break; case Button2: { playlist_t *p_playlist; var_Get( p_vout, "mouse-button-down", &val ); val.i_int &= ~2; var_Set( p_vout, "mouse-button-down", val ); p_playlist = vlc_object_find( p_vout, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist != NULL ) { vlc_value_t val; var_Get( p_playlist, "intf-show", &val ); val.b_bool = !val.b_bool; var_Set( p_playlist, "intf-show", val ); vlc_object_release( p_playlist ); } } break; case Button3: { intf_thread_t *p_intf; playlist_t *p_playlist;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -