📄 directx.c
字号:
/***************************************************************************** * vout.c: Windows DirectX video output display method ***************************************************************************** * Copyright (C) 2001-2004 the VideoLAN team * $Id$ * * Authors: Gildas Bazin <gbazin@videolan.org> * * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble: * * This plugin will use YUV overlay if supported, using overlay will result in * the best video quality (hardware interpolation when rescaling the picture) * and the fastest display as it requires less processing. * * If YUV overlay is not supported this plugin will use RGB offscreen video * surfaces that will be blitted onto the primary surface (display) to * effectively display the pictures. This fallback method also enables us to * display video in window mode. * *****************************************************************************/#include <errno.h> /* ENOMEM */#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_plugin.h>#include <vlc_interface.h>#include <vlc_playlist.h>#include <vlc_vout.h>#include <windows.h>#include <ddraw.h>#include <commctrl.h>#ifndef UNDER_CE# include <multimon.h>#endif#undef GetSystemMetrics#ifndef MONITOR_DEFAULTTONEAREST# define MONITOR_DEFAULTTONEAREST 2#endif#include "vout.h"/***************************************************************************** * picture_sys_t: direct buffer method descriptor ***************************************************************************** * This structure is part of the picture descriptor, it describes the * DirectX specific properties of a direct buffer. *****************************************************************************/struct picture_sys_t{ LPDIRECTDRAWSURFACE2 p_surface; LPDIRECTDRAWSURFACE2 p_front_surface; DDSURFACEDESC ddsd;};/***************************************************************************** * DirectDraw GUIDs. * Defining them here allows us to get rid of the dxguid library during * the linking stage. *****************************************************************************/#include <initguid.h>#undef GUID_EXT#define GUID_EXTDEFINE_GUID( IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );DEFINE_GUID( IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 );/***************************************************************************** * Local prototypes. *****************************************************************************/static int OpenVideo ( vlc_object_t * );static void CloseVideo ( vlc_object_t * );static int Init ( vout_thread_t * );static void End ( vout_thread_t * );static int Manage ( vout_thread_t * );static void Display ( vout_thread_t *, picture_t * );static void FirstDisplay( vout_thread_t *, picture_t * );static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );static int NewPictureVec ( vout_thread_t *, picture_t *, int );static void FreePictureVec ( vout_thread_t *, picture_t *, int );static int UpdatePictureStruct( vout_thread_t *, picture_t *, int );static int DirectXInitDDraw ( vout_thread_t *p_vout );static void DirectXCloseDDraw ( vout_thread_t *p_vout );static int DirectXCreateDisplay ( vout_thread_t *p_vout );static void DirectXCloseDisplay ( vout_thread_t *p_vout );static int DirectXCreateSurface ( vout_thread_t *p_vout, LPDIRECTDRAWSURFACE2 *, int, int, int );static void DirectXCloseSurface ( vout_thread_t *p_vout, LPDIRECTDRAWSURFACE2 );static int DirectXCreateClipper ( vout_thread_t *p_vout );static void DirectXGetDDrawCaps ( vout_thread_t *p_vout );static int DirectXLockSurface ( vout_thread_t *p_vout, picture_t *p_pic );static int DirectXUnlockSurface ( vout_thread_t *p_vout, picture_t *p_pic );static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t *i_color );void SwitchWallpaperMode( vout_thread_t *, bool );/* Object variables callbacks */static int FindDevicesCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );static int WallpaperCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );/***************************************************************************** * Module descriptor *****************************************************************************/#define HW_YUV_TEXT N_("Use hardware YUV->RGB conversions")#define HW_YUV_LONGTEXT N_( \ "Try to use hardware acceleration for YUV->RGB conversions. " \ "This option doesn't have any effect when using overlays." )#define SYSMEM_TEXT N_("Use video buffers in system memory")#define SYSMEM_LONGTEXT N_( \ "Create video buffers in system memory instead of video memory. This " \ "isn't recommended as usually using video memory allows to benefit from " \ "more hardware acceleration (like rescaling or YUV->RGB conversions). " \ "This option doesn't have any effect when using overlays." )#define TRIPLEBUF_TEXT N_("Use triple buffering for overlays")#define TRIPLEBUF_LONGTEXT N_( \ "Try to use triple buffering when using YUV overlays. That results in " \ "much better video quality (no flickering)." )#define DEVICE_TEXT N_("Name of desired display device")#define DEVICE_LONGTEXT N_("In a multiple monitor configuration, you can " \ "specify the Windows device name of the display that you want the video " \ "window to open on. For example, \"\\\\.\\DISPLAY1\" or " \ "\"\\\\.\\DISPLAY2\"." )#define WALLPAPER_TEXT N_("Enable wallpaper mode ")#define WALLPAPER_LONGTEXT N_( \ "The wallpaper mode allows you to display the video as the desktop " \ "background. Note that this feature only works in overlay mode and " \ "the desktop must not already have a wallpaper." )static const char *const ppsz_dev[] = { "" };static const char *const ppsz_dev_text[] = { N_("Default") };vlc_module_begin(); set_shortname( "DirectX" ); set_category( CAT_VIDEO ); set_subcategory( SUBCAT_VIDEO_VOUT ); add_bool( "directx-hw-yuv", 1, NULL, HW_YUV_TEXT, HW_YUV_LONGTEXT, true ); add_bool( "directx-use-sysmem", 0, NULL, SYSMEM_TEXT, SYSMEM_LONGTEXT, true ); add_bool( "directx-3buffering", 1, NULL, TRIPLEBUF_TEXT, TRIPLEBUF_LONGTEXT, true ); add_string( "directx-device", "", NULL, DEVICE_TEXT, DEVICE_LONGTEXT, true ); change_string_list( ppsz_dev, ppsz_dev_text, FindDevicesCallback ); change_action_add( FindDevicesCallback, N_("Refresh list") ); add_bool( "directx-wallpaper", 0, NULL, WALLPAPER_TEXT, WALLPAPER_LONGTEXT, true ); set_description( N_("DirectX video output") ); set_capability( "video output", 100 ); add_shortcut( "directx" ); set_callbacks( OpenVideo, CloseVideo ); /* FIXME: Hack to avoid unregistering our window class */ linked_with_a_crap_library_which_uses_atexit( );vlc_module_end();#if 0 /* FIXME */ /* check if we registered a window class because we need to * unregister it */ WNDCLASS wndclass; if( GetClassInfo( GetModuleHandle(NULL), "VLC DirectX", &wndclass ) ) UnregisterClass( "VLC DirectX", GetModuleHandle(NULL) );#endif/***************************************************************************** * OpenVideo: allocate DirectX video thread output method ***************************************************************************** * This function allocates and initialize the DirectX vout method. *****************************************************************************/static int OpenVideo( vlc_object_t *p_this ){ vout_thread_t * p_vout = (vout_thread_t *)p_this; vlc_value_t val; HMODULE huser32; /* Allocate structure */ p_vout->p_sys = malloc( sizeof( vout_sys_t ) ); if( p_vout->p_sys == NULL ) return VLC_ENOMEM; memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) ); /* Initialisations */ p_vout->pf_init = Init; p_vout->pf_end = End; p_vout->pf_manage = Manage; p_vout->pf_render = NULL; p_vout->pf_display = FirstDisplay; p_vout->p_sys->p_ddobject = NULL; p_vout->p_sys->p_display = NULL; p_vout->p_sys->p_current_surface = NULL; p_vout->p_sys->p_clipper = NULL; p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL; p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL; p_vout->p_sys->i_changes = 0; p_vout->p_sys->b_wallpaper = 0; vlc_mutex_init( &p_vout->p_sys->lock ); SetRectEmpty( &p_vout->p_sys->rect_display ); SetRectEmpty( &p_vout->p_sys->rect_parent ); /* Multimonitor stuff */ p_vout->p_sys->hmonitor = NULL; p_vout->p_sys->p_display_driver = NULL; p_vout->p_sys->MonitorFromWindow = NULL; p_vout->p_sys->GetMonitorInfo = NULL; if( (huser32 = GetModuleHandle( _T("USER32") ) ) ) { p_vout->p_sys->MonitorFromWindow = (HMONITOR (WINAPI *)( HWND, DWORD )) GetProcAddress( huser32, _T("MonitorFromWindow") ); p_vout->p_sys->GetMonitorInfo =#ifndef UNICODE GetProcAddress( huser32, "GetMonitorInfoA" );#else GetProcAddress( huser32, _T("GetMonitorInfoW") );#endif } var_Create( p_vout, "overlay", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_vout, "directx-use-sysmem", VLC_VAR_BOOL|VLC_VAR_DOINHERIT ); var_Create( p_vout, "directx-hw-yuv", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_vout, "directx-3buffering", VLC_VAR_BOOL|VLC_VAR_DOINHERIT ); var_Create( p_vout, "directx-device", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Create( p_vout, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); p_vout->p_sys->b_cursor_hidden = 0; p_vout->p_sys->i_lastmoved = mdate(); p_vout->p_sys->i_mouse_hide_timeout = var_GetInteger(p_vout, "mouse-hide-timeout") * 1000; /* Set main window's size */ p_vout->p_sys->i_window_width = p_vout->i_window_width; p_vout->p_sys->i_window_height = p_vout->i_window_height; /* Create the Vout EventThread, this thread is created by us to isolate * the Win32 PeekMessage function calls. We want to do this because * Windows can stay blocked inside this call for a long time, and when * this happens it thus blocks vlc's video_output thread. * DirectXEventThread will take care of the creation of the video * window (because PeekMessage has to be called from the same thread which * created the window). */ msg_Dbg( p_vout, "creating DirectXEventThread" ); p_vout->p_sys->p_event = vlc_object_create( p_vout, sizeof(event_thread_t) ); p_vout->p_sys->p_event->p_vout = p_vout; if( vlc_thread_create( p_vout->p_sys->p_event, "Vout Events Thread", EventThread, 0, 1 ) ) { msg_Err( p_vout, "cannot create Vout EventThread" ); vlc_object_release( p_vout->p_sys->p_event ); p_vout->p_sys->p_event = NULL; goto error; } if( p_vout->p_sys->p_event->b_error ) { msg_Err( p_vout, "Vout EventThread failed" ); goto error; } vlc_object_attach( p_vout->p_sys->p_event, p_vout ); msg_Dbg( p_vout, "Vout EventThread running" ); /* Initialise DirectDraw */ if( DirectXInitDDraw( p_vout ) ) { msg_Err( p_vout, "cannot initialize DirectX DirectDraw" ); goto error; } /* Create the directx display */ if( DirectXCreateDisplay( p_vout ) ) { msg_Err( p_vout, "cannot initialize DirectX DirectDraw" ); goto error; } /* Variable to indicate if the window should be on top of others */ /* Trigger a callback right now */ var_Get( p_vout, "video-on-top", &val ); var_Set( p_vout, "video-on-top", val ); /* Variable to indicate if the window should be on top of others */ /* Trigger a callback right now */ var_Create( p_vout, "directx-wallpaper", VLC_VAR_BOOL|VLC_VAR_DOINHERIT ); val.psz_string = _("Wallpaper"); var_Change( p_vout, "directx-wallpaper", VLC_VAR_SETTEXT, &val, NULL ); var_AddCallback( p_vout, "directx-wallpaper", WallpaperCallback, NULL ); var_Get( p_vout, "directx-wallpaper", &val ); var_Set( p_vout, "directx-wallpaper", val ); /* disable screensaver by temporarily changing system settings */ p_vout->p_sys->i_spi_lowpowertimeout = 0; p_vout->p_sys->i_spi_powerofftimeout = 0; p_vout->p_sys->i_spi_screensavetimeout = 0; var_Get( p_vout, "disable-screensaver", &val); if( val.b_bool ) { msg_Dbg(p_vout, "disabling screen saver"); SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT, 0, &(p_vout->p_sys->i_spi_lowpowertimeout), 0); if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) { SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, 0, NULL, 0); } SystemParametersInfo(SPI_GETPOWEROFFTIMEOUT, 0, &(p_vout->p_sys->i_spi_powerofftimeout), 0); if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -