📄 directx.c
字号:
/***************************************************************************** * vout.c: Windows DirectX video output display method ***************************************************************************** * Copyright (C) 2001-2004 VideoLAN * $Id: directx.c 11257 2005-06-02 17:06:00Z fkuehne $ * * 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., 59 Temple Place - Suite 330, Boston, MA 02111, 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 */#include <stdlib.h> /* free() */#include <string.h> /* strerror() */#include <vlc/vlc.h>#include <vlc/intf.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"/***************************************************************************** * DirectDraw GUIDs. * Defining them here allows us to get rid of the dxguid library during * the linking stage. *****************************************************************************/#include <initguid.h>DEFINE_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 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 *, vlc_bool_t );/* 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 char *ppsz_dev[] = { "" };static char *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, VLC_TRUE ); add_bool( "directx-use-sysmem", 0, NULL, SYSMEM_TEXT, SYSMEM_LONGTEXT, VLC_TRUE ); add_bool( "directx-3buffering", 1, NULL, TRIPLEBUF_TEXT, TRIPLEBUF_LONGTEXT, VLC_TRUE ); add_string( "directx-device", "", NULL, DEVICE_TEXT, DEVICE_LONGTEXT, VLC_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, VLC_TRUE ); set_description( _("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 ) { msg_Err( p_vout, "out of memory" ); 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 = Display; 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_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 ); p_vout->p_sys->b_cursor_hidden = 0; p_vout->p_sys->i_lastmoved = mdate(); /* 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 DirectXEventThread, 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, "DirectX Events Thread", E_(DirectXEventThread), 0, 1 ) ) { msg_Err( p_vout, "cannot create DirectXEventThread" ); vlc_object_destroy( 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, "DirectXEventThread failed" ); goto error; } vlc_object_attach( p_vout->p_sys->p_event, p_vout ); msg_Dbg( p_vout, "DirectXEventThread running" ); /* Initialise DirectDraw */ if( DirectXInitDDraw( p_vout ) ) { msg_Err( p_vout, "cannot initialize DirectDraw" ); goto error; } /* Create the directx display */ if( DirectXCreateDisplay( p_vout ) ) { msg_Err( p_vout, "cannot initialize 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 ); return VLC_SUCCESS; error: CloseVideo( VLC_OBJECT(p_vout) ); return VLC_EGENERIC;}/***************************************************************************** * Init: initialize DirectX video thread output method ***************************************************************************** * This function create the directx surfaces needed by the output thread. * It is called at the beginning of the thread. *****************************************************************************/static int Init( vout_thread_t *p_vout ){ int i_chroma_backup; vlc_value_t val; /* Get a few default parameters */ var_Get( p_vout, "overlay", &val ); p_vout->p_sys->b_using_overlay = val.b_bool; var_Get( p_vout, "directx-use-sysmem", &val ); p_vout->p_sys->b_use_sysmem = val.b_bool; var_Get( p_vout, "directx-hw-yuv", &val ); p_vout->p_sys->b_hw_yuv = val.b_bool; var_Get( p_vout, "directx-3buffering", &val ); p_vout->p_sys->b_3buf_overlay = val.b_bool; /* Initialise DirectDraw if not already done. * We do this here because on multi-monitor systems we may have to * re-create the directdraw surfaces. */ if( !p_vout->p_sys->p_ddobject && DirectXInitDDraw( p_vout ) != VLC_SUCCESS ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -