Commit 4416b2cb authored by Gildas Bazin's avatar Gildas Bazin

* major rewrite of the directx video plugin to adapt it to the new vout4
    architecture. This plugin has also been through a major clean-up
    and it is now much more robust and optimized.

* Fixed a few problems with the win32 build.

* Replaced the "overlay" command line option with "nooverlay". The
    former was confusing and useless because overlays were used by
    default anyway.
parent 338b73f4
...@@ -354,8 +354,8 @@ ...@@ -354,8 +354,8 @@
#define VOUT_FULLSCREEN_DEFAULT 0 #define VOUT_FULLSCREEN_DEFAULT 0
/* Environment variable for overlay mode, and default value */ /* Environment variable for overlay mode, and default value */
#define VOUT_OVERLAY_VAR "vlc_overlay" #define VOUT_NOOVERLAY_VAR "vlc_nooverlay"
#define VOUT_OVERLAY_DEFAULT 0 #define VOUT_NOOVERLAY_DEFAULT 0
/* Default gamma */ /* Default gamma */
#define VOUT_GAMMA_VAR "vlc_gamma" #define VOUT_GAMMA_VAR "vlc_gamma"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* aout_directx.c: Windows DirectX audio output method * aout_directx.c: Windows DirectX audio output method
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: aout_directx.c,v 1.14 2001/12/30 07:09:54 sam Exp $ * $Id: aout_directx.c,v 1.15 2002/01/17 23:02:45 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -41,6 +41,14 @@ ...@@ -41,6 +41,14 @@
#include "audio_output.h" /* aout_thread_t */ #include "audio_output.h" /* aout_thread_t */
/*****************************************************************************
* DirectSound GUIDs.
* Defining them here allows us to get rid of the dxguid library during
* the linking stage.
*****************************************************************************/
#include <initguid.h>
DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);
/***************************************************************************** /*****************************************************************************
* aout_sys_t: directx audio output method descriptor * aout_sys_t: directx audio output method descriptor
***************************************************************************** *****************************************************************************
...@@ -120,10 +128,6 @@ void _M( aout_getfunctions )( function_list_t * p_function_list ) ...@@ -120,10 +128,6 @@ void _M( aout_getfunctions )( function_list_t * p_function_list )
static int aout_Probe( probedata_t *p_data ) static int aout_Probe( probedata_t *p_data )
{ {
/* For now just assume the computer has a sound device */ /* For now just assume the computer has a sound device */
if( TestMethod( AOUT_METHOD_VAR, "directx" ) )
{
return( 999 );
}
return( 1 ); return( 1 );
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* directx.c : Windows DirectX plugin for vlc * directx.c : Windows DirectX plugin for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: directx.c,v 1.4 2001/12/30 07:09:54 sam Exp $ * $Id: directx.c,v 1.5 2002/01/17 23:02:45 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -44,15 +44,15 @@ void _M( vout_getfunctions )( function_list_t * p_function_list ); ...@@ -44,15 +44,15 @@ void _M( vout_getfunctions )( function_list_t * p_function_list );
* Building configuration tree * Building configuration tree
*****************************************************************************/ *****************************************************************************/
MODULE_CONFIG_START MODULE_CONFIG_START
ADD_WINDOW( "Configuration for Windows DirectX module" ) ADD_WINDOW( "Configuration for Windows DirectX module" )
ADD_COMMENT( "For now, the Windows DirectX module cannot be configured" ) ADD_COMMENT( "For now, the Windows DirectX module cannot be configured" )
MODULE_CONFIG_STOP MODULE_CONFIG_STOP
MODULE_INIT_START MODULE_INIT_START
p_module->i_capabilities = MODULE_CAPABILITY_NULL SET_DESCRIPTION( "DirectX extension module" )
| MODULE_CAPABILITY_VOUT ADD_CAPABILITY( AOUT, 150 )
| MODULE_CAPABILITY_AOUT; ADD_CAPABILITY( VOUT, 150 )
p_module->psz_longname = "DirectX module"; ADD_SHORTCUT( "directx" )
MODULE_INIT_STOP MODULE_INIT_STOP
MODULE_ACTIVATE_START MODULE_ACTIVATE_START
...@@ -62,4 +62,3 @@ MODULE_ACTIVATE_STOP ...@@ -62,4 +62,3 @@ MODULE_ACTIVATE_STOP
MODULE_DEACTIVATE_START MODULE_DEACTIVATE_START
MODULE_DEACTIVATE_STOP MODULE_DEACTIVATE_STOP
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vout_directx.c: Windows DirectX video output display method * vout_directx.c: Windows DirectX video output display method
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: vout_directx.c,v 1.18 2002/01/04 14:01:34 sam Exp $ * $Id: vout_directx.c,v 1.19 2002/01/17 23:02:45 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -21,13 +21,6 @@ ...@@ -21,13 +21,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
/* ToDo:
*
* Double buffering
*
* Port this plugin to Video Output IV
*/
/***************************************************************************** /*****************************************************************************
* Preamble: * Preamble:
* *
...@@ -35,14 +28,15 @@ ...@@ -35,14 +28,15 @@
* the best video quality (hardware interpolation when rescaling the picture) * the best video quality (hardware interpolation when rescaling the picture)
* and the fastest display as it requires less processing. * and the fastest display as it requires less processing.
* *
* If YUV overlay is not supported the plugin will use an RGB offscreen video * If YUV overlay is not supported this plugin will use RGB offscreen video
* surface that will be blitted onto the primary surface (display) to * surfaces that will be blitted onto the primary surface (display) to
* effectively display the picture. this fallback method enables us to display * effectively display the pictures. this fallback method enables us to display
* video in window mode. * video in window mode.
* Another fallback method (which isn't implemented yet) would be to use the * Another fallback method (which isn't implemented) would be take the
* primary surface as the video buffer. This would allow for better * exclusive control of the screen so we could spare the blitting process and
* performance but this is restricted to fullscreen video. In short, * decode directly to video memory. This should theoretically allow for better
* implementing this is not considered high priority. * performance (although on my system it is actually slower) but this is
* restricted to fullscreen video.
* *
*****************************************************************************/ *****************************************************************************/
#include <errno.h> /* ENOMEM */ #include <errno.h> /* ENOMEM */
...@@ -54,11 +48,7 @@ ...@@ -54,11 +48,7 @@
#include <windows.h> #include <windows.h>
#include <windowsx.h> #include <windowsx.h>
#if defined( _MSC_VER ) #include <ddraw.h>
# include <ddraw.h>
#else
# include <directx.h>
#endif
#include "netutils.h" #include "netutils.h"
...@@ -69,28 +59,42 @@ ...@@ -69,28 +59,42 @@
#include "vout_directx.h" #include "vout_directx.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_IDirectDrawSurface3, 0xDA044E00,0x69B2,0x11D0,0xA1,0xD5,0x00,0xAA,0x00,0xB8,0xDF,0xBB );
/***************************************************************************** /*****************************************************************************
* Local prototypes. * Local prototypes.
*****************************************************************************/ *****************************************************************************/
static int vout_Probe ( probedata_t *p_data ); static int vout_Probe ( probedata_t *p_data );
static int vout_Create ( struct vout_thread_s * ); static int vout_Create ( vout_thread_t * );
static int vout_Init ( struct vout_thread_s * ); static void vout_Destroy ( vout_thread_t * );
static void vout_End ( struct vout_thread_s * ); static int vout_Init ( vout_thread_t * );
static void vout_Destroy ( struct vout_thread_s * ); static void vout_End ( vout_thread_t * );
static int vout_Manage ( struct vout_thread_s * ); static int vout_Manage ( vout_thread_t * );
static void vout_Display ( struct vout_thread_s * ); static void vout_Render ( vout_thread_t *, picture_t * );
static void vout_SetPalette( p_vout_thread_t p_vout, u16 *red, u16 *green, static void vout_Display ( vout_thread_t *, picture_t * );
u16 *blue, u16 *transp );
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 int DirectXInitDDraw ( vout_thread_t *p_vout );
static int DirectXCreateDisplay ( vout_thread_t *p_vout );
static int DirectXCreateSurface ( vout_thread_t *p_vout );
static int DirectXCreateClipper ( vout_thread_t *p_vout );
static int DirectXUpdateOverlay ( vout_thread_t *p_vout );
static void DirectXCloseDDraw ( 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 void DirectXCloseDisplay ( vout_thread_t *p_vout );
static void DirectXCloseSurface ( vout_thread_t *p_vout ); static int DirectXCreateSurface ( vout_thread_t *p_vout,
static void DirectXKeepAspectRatio( vout_thread_t *p_vout, RECT *coordinates ); LPDIRECTDRAWSURFACE3 *, int, int );
static void DirectXCloseSurface ( vout_thread_t *p_vout,
LPDIRECTDRAWSURFACE3 );
static int DirectXCreateClipper ( vout_thread_t *p_vout );
static void DirectXGetDDrawCaps ( vout_thread_t *p_vout );
static int DirectXGetSurfaceDesc ( picture_t *p_pic );
/***************************************************************************** /*****************************************************************************
* Functions exported as capabilities. They are declared as static so that * Functions exported as capabilities. They are declared as static so that
...@@ -104,8 +108,8 @@ void _M( vout_getfunctions )( function_list_t * p_function_list ) ...@@ -104,8 +108,8 @@ void _M( vout_getfunctions )( function_list_t * p_function_list )
p_function_list->functions.vout.pf_end = vout_End; p_function_list->functions.vout.pf_end = vout_End;
p_function_list->functions.vout.pf_destroy = vout_Destroy; 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 = vout_Manage;
p_function_list->functions.vout.pf_render = vout_Render;
p_function_list->functions.vout.pf_display = vout_Display; p_function_list->functions.vout.pf_display = vout_Display;
p_function_list->functions.vout.pf_setpalette = vout_SetPalette;
} }
/***************************************************************************** /*****************************************************************************
...@@ -117,11 +121,6 @@ void _M( vout_getfunctions )( function_list_t * p_function_list ) ...@@ -117,11 +121,6 @@ void _M( vout_getfunctions )( function_list_t * p_function_list )
static int vout_Probe( probedata_t *p_data ) static int vout_Probe( probedata_t *p_data )
{ {
if( TestMethod( VOUT_METHOD_VAR, "directx" ) )
{
return( 999 );
}
/* Check that at least DirectX5 is installed on the computer */ /* Check that at least DirectX5 is installed on the computer */
/* Fixme */ /* Fixme */
...@@ -146,37 +145,44 @@ static int vout_Create( vout_thread_t *p_vout ) ...@@ -146,37 +145,44 @@ static int vout_Create( vout_thread_t *p_vout )
/* Initialisations */ /* Initialisations */
p_vout->p_sys->p_ddobject = NULL; p_vout->p_sys->p_ddobject = NULL;
p_vout->p_sys->p_display = NULL; p_vout->p_sys->p_display = NULL;
p_vout->p_sys->p_surface = NULL; p_vout->p_sys->p_current_surface = NULL;
p_vout->p_sys->p_clipper = NULL; p_vout->p_sys->p_clipper = NULL;
p_vout->p_sys->hbrush = NULL; p_vout->p_sys->hbrush = NULL;
p_vout->p_sys->hwnd = NULL; p_vout->p_sys->hwnd = NULL;
p_vout->p_sys->i_changes = 0; p_vout->p_sys->i_changes = 0;
p_vout->p_sys->b_event_thread_die = 0; p_vout->p_sys->b_event_thread_die = 0;
p_vout->p_sys->b_display_enabled = 0; p_vout->p_sys->b_caps_overlay_clipping = 0;
SetRectEmpty( &p_vout->p_sys->rect_display );
p_vout->p_sys->b_using_overlay =
!main_GetIntVariable( VOUT_NOOVERLAY_VAR, VOUT_NOOVERLAY_DEFAULT );
p_vout->p_sys->b_cursor = 1; /* TODO should be done with a main_GetInt.. */ p_vout->p_sys->b_cursor = 1;
p_vout->p_sys->b_cursor_autohidden = 0; p_vout->p_sys->b_cursor_autohidden = 0;
p_vout->p_sys->i_lastmoved = mdate(); p_vout->p_sys->i_lastmoved = mdate();
p_vout->b_fullscreen = main_GetIntVariable( VOUT_FULLSCREEN_VAR, /* Set main window's size */
VOUT_FULLSCREEN_DEFAULT ); if( p_vout->render.i_height * p_vout->render.i_aspect
>= p_vout->render.i_width * VOUT_ASPECT_FACTOR )
{
p_vout->p_sys->i_window_width = p_vout->render.i_height
* p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
p_vout->p_sys->i_window_height = p_vout->render.i_height;
}
else
{
p_vout->p_sys->i_window_width = p_vout->render.i_width;
p_vout->p_sys->i_window_height = p_vout->render.i_width
* VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
}
#if 0 #if 0
p_vout->b_need_render = !main_GetIntVariable( VOUT_OVERLAY_VAR,
VOUT_OVERLAY_DEFAULT );
#else
p_vout->b_need_render = 0; /* default = overlay */
#endif
p_vout->p_sys->i_window_width = main_GetIntVariable( VOUT_WIDTH_VAR, p_vout->p_sys->i_window_width = main_GetIntVariable( VOUT_WIDTH_VAR,
VOUT_WIDTH_DEFAULT ); VOUT_WIDTH_DEFAULT );
p_vout->p_sys->i_window_height = main_GetIntVariable( VOUT_HEIGHT_VAR, p_vout->p_sys->i_window_height = main_GetIntVariable( VOUT_HEIGHT_VAR,
VOUT_HEIGHT_DEFAULT ); VOUT_HEIGHT_DEFAULT );
/* We don't know yet the dimensions of the video so the best guess is to #endif
* pick the same as the window */
p_vout->p_sys->i_image_width = p_vout->p_sys->i_window_width;
p_vout->p_sys->i_image_height = p_vout->p_sys->i_window_height;
/* Set locks and condition variables */ /* Set locks and condition variables */
vlc_mutex_init( &p_vout->p_sys->event_thread_lock ); vlc_mutex_init( &p_vout->p_sys->event_thread_lock );
vlc_cond_init( &p_vout->p_sys->event_thread_wait ); vlc_cond_init( &p_vout->p_sys->event_thread_wait );
...@@ -215,8 +221,8 @@ static int vout_Create( vout_thread_t *p_vout ) ...@@ -215,8 +221,8 @@ static int vout_Create( vout_thread_t *p_vout )
return( 1 ); return( 1 );
} }
intf_WarnMsg( 3, "vout: vout_Create DirectXEventThread running" );
intf_WarnMsg( 3, "vout : vout_Create DirectXEventThread running" );
/* Initialise DirectDraw */ /* Initialise DirectDraw */
if( DirectXInitDDraw( p_vout ) ) if( DirectXInitDDraw( p_vout ) )
...@@ -249,16 +255,36 @@ static int vout_Create( vout_thread_t *p_vout ) ...@@ -249,16 +255,36 @@ static int vout_Create( vout_thread_t *p_vout )
return ( 1 ); return ( 1 );
} }
/* Attach the current thread input queue to the events thread qeue.
* This allows us to hide or show the cursor in vout_Manage() */
ShowCursor( TRUE ); ShowCursor( FALSE ); /* create input queue */
AttachThreadInput( GetCurrentThreadId(),
GetWindowThreadProcessId( p_vout->p_sys->hwnd, NULL ),
1 );
return( 0 ); return( 0 );
} }
/***************************************************************************** /*****************************************************************************
* vout_Init: initialize DirectX video thread output method * vout_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 vout_Init( vout_thread_t *p_vout ) static int vout_Init( vout_thread_t *p_vout )
{ {
/* Initialize the output structure.
* Since DirectDraw can do rescaling for us, stick to the default
* 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;
#define MAX_DIRECTBUFFERS 1
NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
return( 0 ); return( 0 );
} }
...@@ -270,6 +296,7 @@ static int vout_Init( vout_thread_t *p_vout ) ...@@ -270,6 +296,7 @@ static int vout_Init( vout_thread_t *p_vout )
*****************************************************************************/ *****************************************************************************/
static void vout_End( vout_thread_t *p_vout ) static void vout_End( vout_thread_t *p_vout )
{ {
FreePictureVec( p_vout, p_vout->p_picture, I_OUTPUTPICTURES );
return; return;
} }
...@@ -304,13 +331,12 @@ static void vout_Destroy( vout_thread_t *p_vout ) ...@@ -304,13 +331,12 @@ static void vout_Destroy( vout_thread_t *p_vout )
/***************************************************************************** /*****************************************************************************
* vout_Manage: handle Sys events * vout_Manage: handle Sys events
***************************************************************************** *****************************************************************************
* This function should be called regularly by video output thread. It returns * This function should be called regularly by the video output thread.
* a non null value if an error occured. * It returns a non null value if an error occured.
*****************************************************************************/ *****************************************************************************/
static int vout_Manage( vout_thread_t *p_vout ) static int vout_Manage( vout_thread_t *p_vout )
{ {
WINDOWPLACEMENT window_placement; WINDOWPLACEMENT window_placement;
extern int b_directx_update_overlay;
/* We used to call the Win32 PeekMessage function here to read the window /* We used to call the Win32 PeekMessage function here to read the window
* messages. But since window can stay blocked into this function for a * messages. But since window can stay blocked into this function for a
...@@ -324,11 +350,10 @@ static int vout_Manage( vout_thread_t *p_vout ) ...@@ -324,11 +350,10 @@ static int vout_Manage( vout_thread_t *p_vout )
|| p_vout->p_sys->i_changes & VOUT_SCALE_CHANGE) || p_vout->p_sys->i_changes & VOUT_SCALE_CHANGE)
{ {
intf_WarnMsg( 3, "vout: vout_Manage Scale Change" ); intf_WarnMsg( 3, "vout: vout_Manage Scale Change" );
if( p_vout->b_need_render ) if( !p_vout->p_sys->b_using_overlay )
InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE ); InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE );
if( DirectXUpdateOverlay( p_vout ) ) else
/* failed so try again next time */ DirectXUpdateOverlay( p_vout );
PostMessage( p_vout->p_sys->hwnd, WM_CHAR, (WPARAM)'S', 0);
p_vout->i_changes &= ~VOUT_SCALE_CHANGE; p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
p_vout->p_sys->i_changes &= ~VOUT_SCALE_CHANGE; p_vout->p_sys->i_changes &= ~VOUT_SCALE_CHANGE;
} }
...@@ -337,45 +362,15 @@ static int vout_Manage( vout_thread_t *p_vout ) ...@@ -337,45 +362,15 @@ static int vout_Manage( vout_thread_t *p_vout )
* Size Change * Size Change
*/ */
if( p_vout->i_changes & VOUT_SIZE_CHANGE if( p_vout->i_changes & VOUT_SIZE_CHANGE
|| p_vout->p_sys->i_changes & VOUT_SIZE_CHANGE || p_vout->p_sys->i_changes & VOUT_SIZE_CHANGE )
|| b_directx_update_overlay )
{ {
intf_WarnMsg( 3, "vout: vout_Manage Size Change" ); intf_WarnMsg( 3, "vout: vout_Manage Size Change" );
if( DirectXUpdateOverlay( p_vout ) ) if( !p_vout->p_sys->b_using_overlay )
/* failed so try again next time */ InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE );
PostMessage( p_vout->p_sys->hwnd, WM_APP, 0, 0); else
DirectXUpdateOverlay( p_vout );
p_vout->i_changes &= ~VOUT_SIZE_CHANGE; p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
p_vout->p_sys->i_changes &= ~VOUT_SIZE_CHANGE; p_vout->p_sys->i_changes &= ~VOUT_SIZE_CHANGE;
b_directx_update_overlay = 0;
}
/*
* YUV Change
*/
if( p_vout->i_changes & VOUT_YUV_CHANGE
|| p_vout->p_sys->i_changes & VOUT_YUV_CHANGE )
{
p_vout->b_need_render = ! p_vout->b_need_render;
/* Need to reopen display */
DirectXCloseSurface( p_vout );
if( DirectXCreateSurface( p_vout ) )
{
intf_ErrMsg( "error: can't reopen display after YUV change" );
return( 1 );
}
/* Repaint the window background (needed by the overlay surface) */
if( !p_vout->b_need_render )
{
InvalidateRect( p_vout->p_sys->hwnd, NULL, TRUE );
p_vout->p_sys->b_display_enabled = 1;
if( DirectXUpdateOverlay( p_vout ) )
/* failed so try again next time */
PostMessage( p_vout->p_sys->hwnd, WM_APP, 0, 0);
}
p_vout->i_changes &= ~VOUT_YUV_CHANGE;
p_vout->p_sys->i_changes &= ~VOUT_YUV_CHANGE;
} }
/* /*
...@@ -423,6 +418,7 @@ static int vout_Manage( vout_thread_t *p_vout ) ...@@ -423,6 +418,7 @@ static int vout_Manage( vout_thread_t *p_vout )
ShowCursor( FALSE ); ShowCursor( FALSE );
} }
#if 0
if( p_vout->i_changes & VOUT_CURSOR_CHANGE if( p_vout->i_changes & VOUT_CURSOR_CHANGE
|| p_vout->p_sys->i_changes & VOUT_CURSOR_CHANGE ) || p_vout->p_sys->i_changes & VOUT_CURSOR_CHANGE )
{ {
...@@ -434,38 +430,34 @@ static int vout_Manage( vout_thread_t *p_vout ) ...@@ -434,38 +430,34 @@ static int vout_Manage( vout_thread_t *p_vout )
p_vout->i_changes &= ~VOUT_CURSOR_CHANGE; p_vout->i_changes &= ~VOUT_CURSOR_CHANGE;
p_vout->p_sys->i_changes &= ~VOUT_CURSOR_CHANGE; p_vout->p_sys->i_changes &= ~VOUT_CURSOR_CHANGE;
} }
#endif
/* Check if the event thread is still running */
if( p_vout->p_sys->b_event_thread_die )
return 1; /* exit */
return( 0 ); return( 0 );
} }
/***************************************************************************** /*****************************************************************************
* vout_SetPalette: sets an 8 bpp palette * vout_Render: render previously calculated output
*****************************************************************************
* This function sets the palette given as an argument. It does not return
* anything, but could later send information on which colors it was unable
* to set.
*****************************************************************************/ *****************************************************************************/
static void vout_SetPalette( p_vout_thread_t p_vout, u16 *red, u16 *green, static void vout_Render( vout_thread_t *p_vout, picture_t *p_pic )
u16 *blue, u16 *transp)
{ {
/* Nothing yet */ ;
return;
} }
/***************************************************************************** /*****************************************************************************
* vout_Display: displays previously rendered output * vout_Display: displays previously rendered output
***************************************************************************** *****************************************************************************
* This function send the currently rendered image to the display, wait until * This function sends the currently rendered image to the display, wait until
* it is displayed and switch the two rendering buffer, preparing next frame. * it is displayed and switch the two rendering buffers, preparing next frame.
*****************************************************************************/ *****************************************************************************/
static void vout_Display( vout_thread_t *p_vout ) static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
{ {
DDSURFACEDESC ddsd; HRESULT dxresult;
HRESULT dxresult;
int i; intf_WarnMsg( 8, "vout: vout_Display" );
int i_image_width;
int i_image_height;
if( (p_vout->p_sys->p_display == NULL) ) if( (p_vout->p_sys->p_display == NULL) )
{ {
...@@ -473,77 +465,19 @@ static void vout_Display( vout_thread_t *p_vout ) ...@@ -473,77 +465,19 @@ static void vout_Display( vout_thread_t *p_vout )
return; return;
} }
/* if the size of the decoded pictures has changed then we close the if( !p_vout->p_sys->b_using_overlay )
* video surface (which doesn't have the right size anymore). */
i_image_width = ( p_vout->p_rendered_pic ) ?
p_vout->p_rendered_pic->i_width : p_vout->p_sys->i_image_width;
i_image_height = ( p_vout->p_rendered_pic ) ?
p_vout->p_rendered_pic->i_height : p_vout->p_sys->i_image_height;
if( p_vout->p_sys->i_image_width != i_image_width
|| p_vout->p_sys->i_image_height != i_image_height )
{
intf_WarnMsg( 3, "vout: video surface size changed" );
p_vout->p_sys->i_image_width = i_image_width;
p_vout->p_sys->i_image_height = i_image_height;
DirectXCloseSurface( p_vout );
}
if( p_vout->b_need_render )
{ {
RECT rect_window;
POINT point_window;
DDBLTFX ddbltfx; DDBLTFX ddbltfx;
/* Nothing yet */
if( p_vout->p_sys->p_surface == NULL )
{
intf_WarnMsg( 3, "vout: no video surface, open one..." );
if( DirectXCreateSurface( p_vout ) )
{
intf_WarnMsg( 3, "vout: cannot open a new video surface !!" );
return;
}
/* Display the surface */
p_vout->p_sys->b_display_enabled = 1;
}
/* Now get the coordinates of the window. We don't actually want the
* window coordinates but these of the usable surface inside the window
* By specification GetClientRect will always set rect_window.left and
* rect_window.top to 0 because the Client area is always relative to
* the container window */
GetClientRect(p_vout->p_sys->hwnd, &rect_window);
point_window.x = 0;
point_window.y = 0;
ClientToScreen(p_vout->p_sys->hwnd, &point_window);
rect_window.left = point_window.x;
rect_window.top = point_window.y;
point_window.x = rect_window.right;
point_window.y = rect_window.bottom;
ClientToScreen(p_vout->p_sys->hwnd, &point_window);
rect_window.right = point_window.x;
rect_window.bottom = point_window.y;
/* We want to keep the aspect ratio of the video */
#if 0
if( p_vout->b_scale )
{
DirectXKeepAspectRatio( p_vout, &rect_window );
}
#endif
/* We ask for the "NOTEARING" option */ /* We ask for the "NOTEARING" option */
memset( &ddbltfx, 0, sizeof(DDBLTFX) ); memset( &ddbltfx, 0, sizeof(DDBLTFX) );
ddbltfx.dwSize = sizeof(DDBLTFX); ddbltfx.dwSize = sizeof(DDBLTFX);
ddbltfx.dwDDFX = DDBLTFX_NOTEARING; ddbltfx.dwDDFX = DDBLTFX_NOTEARING | DDBLT_ASYNC;
/* Blit video surface to display */ /* Blit video surface to display */
dxresult = IDirectDrawSurface3_Blt(p_vout->p_sys->p_display, dxresult = IDirectDrawSurface3_Blt(p_vout->p_sys->p_display,
&rect_window, &p_vout->p_sys->rect_dest,
p_vout->p_sys->p_surface, p_pic->p_sys->p_surface,
NULL, NULL,
0, &ddbltfx ); 0, &ddbltfx );
if( dxresult != DD_OK ) if( dxresult != DD_OK )
...@@ -553,107 +487,31 @@ static void vout_Display( vout_thread_t *p_vout ) ...@@ -553,107 +487,31 @@ static void vout_Display( vout_thread_t *p_vout )
} }
} }
else else /* using overlay */
{ {
/*
* p_vout->p_rendered_pic->p_y/u/v contains the YUV buffers to
* render
*/
/* TODO: support for streams other than 4:2:0 */
if( p_vout->p_sys->p_surface == NULL ) /* Flip the overlay buffers */
{ //dxresult = IDirectDrawSurface3_Flip(p_pic->p_sys->p_surface, NULL, 0 );
intf_WarnMsg( 3, "vout: no video surface, open one..." );
if( DirectXCreateSurface( p_vout ) )
{
intf_WarnMsg( 3, "vout: cannot open a new video surface !!" );
return;
}
}
/* Lock the overlay surface */ if( !DirectXGetSurfaceDesc( p_pic ) )
memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
ddsd.dwSize = sizeof(DDSURFACEDESC);
dxresult = IDirectDrawSurface3_Lock(p_vout->p_sys->p_surface, NULL,
&ddsd, DDLOCK_NOSYSLOCK, NULL);
if ( dxresult == DDERR_SURFACELOST )
{ {
/* Your surface can be lost (thanks to windows) so be sure /* AAARRGG */
* to check this and restore it if needed */ intf_ErrMsg( "vout error: vout_Display cannot get surface desc" );
dxresult = IDirectDrawSurface3_Restore( p_vout->p_sys->p_surface );
dxresult = IDirectDrawSurface3_Lock( p_vout->p_sys->p_surface,
NULL, &ddsd, DDLOCK_NOSYSLOCK
| DDLOCK_WAIT, NULL);
}
if( dxresult != DD_OK )
{
intf_WarnMsg( 3, "vout: could not lock the surface" );
return; return;
} }
/* Now we can do the actual image copy. if( !UpdatePictureStruct( p_vout, p_pic, p_vout->output.i_chroma ) )
* The copy has to be done line by line because of the special case
* when the Pitch does not equal the width of the picture */
for( i=0; i < ddsd.dwHeight/2; i++)
{
#ifdef NONAMELESSUNION
/* copy Y, we copy two lines at once */
memcpy(ddsd.lpSurface + i*2*ddsd.u1.lPitch,
p_vout->p_rendered_pic->p_y + i*2*i_image_width,
i_image_width);
memcpy(ddsd.lpSurface + (i*2+1)*ddsd.u1.lPitch,
p_vout->p_rendered_pic->p_y + (i*2+1)*i_image_width,
i_image_width);
/* then V */
memcpy((ddsd.lpSurface + ddsd.dwHeight * ddsd.u1.lPitch)
+ i * ddsd.u1.lPitch/2,
p_vout->p_rendered_pic->p_v + i*i_image_width/2,
i_image_width/2);
/* and U */
memcpy((ddsd.lpSurface + ddsd.dwHeight * ddsd.u1.lPitch)
+ (ddsd.dwHeight * ddsd.u1.lPitch/4)
+ i * ddsd.u1.lPitch/2,
p_vout->p_rendered_pic->p_u + i*i_image_width/2,
i_image_width/2);
#else
/* copy Y, we copy two lines at once */
memcpy((u8*)ddsd.lpSurface + i*2*ddsd.lPitch,
p_vout->p_rendered_pic->p_y + i*2*i_image_width,
i_image_width);
memcpy((u8*)ddsd.lpSurface + (i*2+1)*ddsd.lPitch,
p_vout->p_rendered_pic->p_y + (i*2+1)*i_image_width,
i_image_width);
/* then V */
memcpy(((u8*)ddsd.lpSurface + ddsd.dwHeight * ddsd.lPitch)
+ i * ddsd.lPitch/2,
p_vout->p_rendered_pic->p_v + i*i_image_width/2,
i_image_width/2);
/* and U */
memcpy(((u8*)ddsd.lpSurface + ddsd.dwHeight * ddsd.lPitch)
+ (ddsd.dwHeight * ddsd.lPitch/4)
+ i * ddsd.lPitch/2,
p_vout->p_rendered_pic->p_u + i*i_image_width/2,
i_image_width/2);
#endif /* NONAMELESSUNION */
}
/* Unlock the Surface */
dxresult = IDirectDrawSurface3_Unlock(p_vout->p_sys->p_surface,
ddsd.lpSurface );
/* If display not enabled yet then enable */
if( !p_vout->p_sys->b_display_enabled )
{ {
p_vout->p_sys->b_display_enabled = 1; /* AAARRGG */
DirectXUpdateOverlay( p_vout ); intf_ErrMsg( "vout error: vout_Display unvalid pic chroma" );
return;
} }
/* set currently displayed pic !!! faux*/
p_vout->p_sys->p_current_surface = p_pic->p_sys->p_surface;
} }
/* The first time this function is called it enables the display */ intf_WarnMsg( 8, "vout: vout_Display End" );
p_vout->p_sys->b_display_enabled = 1;
} }
...@@ -733,6 +591,9 @@ static int DirectXInitDDraw( vout_thread_t *p_vout ) ...@@ -733,6 +591,9 @@ static int DirectXInitDDraw( vout_thread_t *p_vout )
IDirectDraw_Release( p_ddobject ); IDirectDraw_Release( p_ddobject );
} }
/* Probe the capabilities of the hardware */
DirectXGetDDrawCaps( p_vout );
intf_WarnMsg( 3, "vout: End DirectXInitDDraw" ); intf_WarnMsg( 3, "vout: End DirectXInitDDraw" );
return( 0 ); return( 0 );
} }
...@@ -748,11 +609,11 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout ) ...@@ -748,11 +609,11 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
HRESULT dxresult; HRESULT dxresult;
DDSURFACEDESC ddsd; DDSURFACEDESC ddsd;
LPDIRECTDRAWSURFACE p_display; LPDIRECTDRAWSURFACE p_display;
DDPIXELFORMAT ddpfPixelFormat; DDPIXELFORMAT pixel_format;
intf_WarnMsg( 3, "vout: DirectXCreateDisplay" ); intf_WarnMsg( 3, "vout: DirectXCreateDisplay" );
/* Now create the primary surface. This surface is what you actually see /* Now get the primary surface. This surface is what you actually see
* on your screen */ * on your screen */
memset( &ddsd, 0, sizeof( DDSURFACEDESC )); memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwSize = sizeof(DDSURFACEDESC);
...@@ -764,7 +625,7 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout ) ...@@ -764,7 +625,7 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
&p_display, NULL ); &p_display, NULL );
if( dxresult != DD_OK ) if( dxresult != DD_OK )
{ {
intf_ErrMsg( "vout error: can't create direct draw primary surface." ); intf_ErrMsg( "vout error: can't get direct draw primary surface." );
p_vout->p_sys->p_display = NULL; p_vout->p_sys->p_display = NULL;
return( 1 ); return( 1 );
} }
...@@ -786,39 +647,75 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout ) ...@@ -786,39 +647,75 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
} }
/* We need to fill in some information for the video output thread. /* The clipper will be used only in non-overlay mode */
* We do this here because it must be done before the video_output DirectXCreateClipper( p_vout );
* thread enters its main loop - and DirectXCreateSurface can be called
* after that ! */
ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); #if 1
IDirectDrawSurface3_GetPixelFormat( p_vout->p_sys->p_display, /* compute the colorkey pixel value from the RGB value we've got */
&ddpfPixelFormat ); memset( &pixel_format, 0, sizeof( DDPIXELFORMAT ));
#ifdef NONAMELESSUNION pixel_format.dwSize = sizeof( DDPIXELFORMAT );
p_vout->i_screen_depth = ddpfPixelFormat.u1.dwRGBBitCount; dxresult = IDirectDrawSurface3_GetPixelFormat( p_vout->p_sys->p_display,
p_vout->i_bytes_per_pixel = ddpfPixelFormat.u1.dwRGBBitCount/8; &pixel_format );
if( dxresult != DD_OK )
p_vout->i_red_mask = ddpfPixelFormat.u2.dwRBitMask; intf_WarnMsg( 3, "vout: DirectXUpdateOverlay GetPixelFormat failed" );
p_vout->i_green_mask = ddpfPixelFormat.u3.dwGBitMask; p_vout->p_sys->i_colorkey = (DWORD)((( p_vout->p_sys->i_rgb_colorkey
p_vout->i_blue_mask = ddpfPixelFormat.u4.dwBBitMask; * pixel_format.dwRBitMask) / 255)
#else & pixel_format.dwRBitMask);
p_vout->i_screen_depth = ddpfPixelFormat.dwRGBBitCount; #endif
p_vout->i_bytes_per_pixel = ddpfPixelFormat.dwRGBBitCount/8;
return( 0 );
p_vout->i_red_mask = ddpfPixelFormat.dwRBitMask; }
p_vout->i_green_mask = ddpfPixelFormat.dwGBitMask;
p_vout->i_blue_mask = ddpfPixelFormat.dwBBitMask;
#endif /* NONAMELESSUNION */ /*****************************************************************************
* DirectXCreateClipper: Create a clipper that will be used when blitting the
/* Create a video surface. This function will try to create an * RGB surface to the main display.
* YUV overlay first and if it can't it will create a simple RGB surface */ *****************************************************************************
if( DirectXCreateSurface( p_vout ) ) * This clipper prevents us to modify by mistake anything on the screen
* which doesn't belong to our window. For example when a part of our video
* window is hidden by another window.
*****************************************************************************/
static int DirectXCreateClipper( vout_thread_t *p_vout )
{
HRESULT dxresult;
intf_WarnMsg( 3, "vout: DirectXCreateClipper" );
/* Create the clipper */
dxresult = IDirectDraw2_CreateClipper( p_vout->p_sys->p_ddobject, 0,
&p_vout->p_sys->p_clipper, NULL );
if( dxresult != DD_OK )
{ {
intf_ErrMsg( "vout error: can't create a video surface." ); intf_WarnMsg( 3, "vout: DirectXCreateClipper can't create clipper." );
IDirectDrawSurface3_Release( p_vout->p_sys->p_display ); p_vout->p_sys->p_clipper = NULL;
p_vout->p_sys->p_display = NULL;
return( 1 ); return( 1 );
} }
/* associate the clipper to the window */
dxresult = IDirectDrawClipper_SetHWnd(p_vout->p_sys->p_clipper, 0,
p_vout->p_sys->hwnd);
if( dxresult != DD_OK )
{
intf_WarnMsg( 3,
"vout: DirectXCreateClipper can't attach clipper to window." );
IDirectDrawSurface_Release( p_vout->p_sys->p_clipper );
p_vout->p_sys->p_clipper = NULL;
return( 1 );
}
/* associate the clipper with the surface */
dxresult = IDirectDrawSurface_SetClipper(p_vout->p_sys->p_display,
p_vout->p_sys->p_clipper);
if( dxresult != DD_OK )
{
intf_WarnMsg( 3,
"vout: DirectXCreateClipper can't attach clipper to surface." );
IDirectDrawSurface_Release( p_vout->p_sys->p_clipper );
p_vout->p_sys->p_clipper = NULL;
return( 1 );
}
return( 0 ); return( 0 );
} }
...@@ -826,61 +723,24 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout ) ...@@ -826,61 +723,24 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout )
* DirectXCreateSurface: create an YUV overlay or RGB surface for the video. * DirectXCreateSurface: create an YUV overlay or RGB surface for the video.
***************************************************************************** *****************************************************************************
* The best method of display is with an YUV overlay because the YUV->RGB * The best method of display is with an YUV overlay because the YUV->RGB
* conversion is done in hardware, so we'll try to create this surface first. * conversion is done in hardware.
* If we fail, we'll try to create a plain RGB surface. * You can also create a plain RGB surface.
* ( Maybe we could also try an RGB overlay surface, which could have hardware * ( Maybe we could also try an RGB overlay surface, which could have hardware
* scaling and which would also be faster in window mode because you don't * scaling and which would also be faster in window mode because you don't
* need to do any blitting to the main display...) * need to do any blitting to the main display...)
*****************************************************************************/ *****************************************************************************/
static int DirectXCreateSurface( vout_thread_t *p_vout ) static int DirectXCreateSurface( vout_thread_t *p_vout,
LPDIRECTDRAWSURFACE3 *pp_surface_final,
int i_chroma, int b_overlay )
{ {
HRESULT dxresult; HRESULT dxresult;
DDSURFACEDESC ddsd;
LPDIRECTDRAWSURFACE p_surface; LPDIRECTDRAWSURFACE p_surface;
DDCAPS ddcaps; DDSURFACEDESC ddsd;
intf_WarnMsg( 3, "vout: DirectXCreateSurface" ); intf_WarnMsg( 3, "vout: DirectXCreateSurface" );
/* Disable display */
p_vout->p_sys->b_display_enabled = 0;
#if 1
/* Probe the capabilities of the hardware */
/* This is just an indication of whether or not we'll support overlay,
* but with this test we don't know if we support YUV overlay */
memset( &ddcaps, 0, sizeof( DDCAPS ));
ddcaps.dwSize = sizeof(DDCAPS);
dxresult = IDirectDraw2_GetCaps( p_vout->p_sys->p_ddobject,
&ddcaps, NULL );
if(dxresult != DD_OK )
{
intf_WarnMsg( 3,"vout error: can't get caps." );
}
else
{
BOOL bHasOverlay, bHasColorKey, bCanStretch;
/* Determine if the hardware supports overlay surfaces */
bHasOverlay = ((ddcaps.dwCaps & DDCAPS_OVERLAY) ==
DDCAPS_OVERLAY) ? TRUE : FALSE;
/* Determine if the hardware supports colorkeying */
bHasColorKey = ((ddcaps.dwCaps & DDCAPS_COLORKEY) ==
DDCAPS_COLORKEY) ? TRUE : FALSE;
/* Determine if the hardware supports scaling of the overlay surface */
bCanStretch = ((ddcaps.dwCaps & DDCAPS_OVERLAYSTRETCH) ==
DDCAPS_OVERLAYSTRETCH) ? TRUE : FALSE;
intf_WarnMsg( 3, "vout: Dx Caps: overlay=%i colorkey=%i stretch=%i",
bHasOverlay, bHasColorKey, bCanStretch );
#if 0
if( !bHasOverlay ) p_vout->b_need_render = 1;
#endif
}
#endif
/* Create the video surface */ /* Create the video surface */
if( !p_vout->b_need_render ) if( b_overlay )
{ {
/* Now try to create the YUV overlay surface. /* Now try to create the YUV overlay surface.
* This overlay will be displayed on top of the primary surface. * This overlay will be displayed on top of the primary surface.
...@@ -894,23 +754,23 @@ static int DirectXCreateSurface( vout_thread_t *p_vout ) ...@@ -894,23 +754,23 @@ static int DirectXCreateSurface( vout_thread_t *p_vout )
ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
ddsd.ddpfPixelFormat.dwFourCC = mmioFOURCC('Y','V','1','2'); ddsd.ddpfPixelFormat.dwFourCC = i_chroma;
#ifdef NONAMELESSUNION
ddsd.ddpfPixelFormat.u1.dwYUVBitCount = 16;
#else
ddsd.ddpfPixelFormat.dwYUVBitCount = 16;
#endif
ddsd.dwFlags = DDSD_CAPS | ddsd.dwFlags = DDSD_CAPS |
DDSD_HEIGHT | DDSD_HEIGHT |
DDSD_WIDTH | DDSD_WIDTH |
//DDSD_BACKBUFFERCOUNT |
DDSD_PIXELFORMAT; DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY; ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY |
ddsd.dwHeight = p_vout->p_sys->i_image_height; // DDSCAPS_COMPLEX |
ddsd.dwWidth = p_vout->p_sys->i_image_width; //DDSCAPS_FLIP |
ddsd.dwBackBufferCount = 1; /* One back buffer */ DDSCAPS_VIDEOMEMORY;
ddsd.dwHeight = p_vout->render.i_height;
ddsd.dwWidth = p_vout->render.i_width;
ddsd.dwBackBufferCount = 0; /* One back buffer */
dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject, dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
&ddsd, &p_surface, NULL ); &ddsd,
&p_surface, NULL );
if( dxresult == DD_OK ) if( dxresult == DD_OK )
{ {
intf_WarnMsg( 3,"vout: DirectX YUV overlay created successfully" ); intf_WarnMsg( 3,"vout: DirectX YUV overlay created successfully" );
...@@ -918,24 +778,27 @@ static int DirectXCreateSurface( vout_thread_t *p_vout ) ...@@ -918,24 +778,27 @@ static int DirectXCreateSurface( vout_thread_t *p_vout )
else else
{ {
intf_ErrMsg( "vout error: can't create YUV overlay surface." ); intf_ErrMsg( "vout error: can't create YUV overlay surface." );
p_vout->b_need_render = 1; *pp_surface_final = NULL;
return 0;
} }
} }
if( p_vout->b_need_render ) if( !b_overlay )
{ {
/* Now try to create a plain RGB surface. */ /* Now try to create a plain RGB surface. */
memset( &ddsd, 0, sizeof( DDSURFACEDESC )); memset( &ddsd, 0, sizeof( DDSURFACEDESC ) );
ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_HEIGHT | ddsd.dwFlags = DDSD_HEIGHT |
DDSD_WIDTH | DDSD_WIDTH |
DDSD_CAPS; DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
ddsd.dwHeight = p_vout->p_sys->i_image_height; DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = p_vout->p_sys->i_image_width; ddsd.dwHeight = p_vout->render.i_height;
ddsd.dwWidth = p_vout->render.i_width;
dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject, dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject,
&ddsd, &p_surface, NULL ); &ddsd,
&p_surface, NULL );
if( dxresult == DD_OK ) if( dxresult == DD_OK )
{ {
intf_WarnMsg( 3,"vout: DirectX RGB surface created successfully" ); intf_WarnMsg( 3,"vout: DirectX RGB surface created successfully" );
...@@ -943,167 +806,24 @@ static int DirectXCreateSurface( vout_thread_t *p_vout ) ...@@ -943,167 +806,24 @@ static int DirectXCreateSurface( vout_thread_t *p_vout )
else else
{ {
intf_ErrMsg( "vout error: can't create RGB surface." ); intf_ErrMsg( "vout error: can't create RGB surface." );
p_vout->p_sys->p_surface = NULL; *pp_surface_final = NULL;
return( 1 ); return 0;
} }
} }
/* Now that the surface is created, try to get a newer DirectX interface */ /* Now that the surface is created, try to get a newer DirectX interface */
dxresult = IDirectDrawSurface_QueryInterface( p_surface, dxresult = IDirectDrawSurface_QueryInterface( p_surface,
&IID_IDirectDrawSurface3, &IID_IDirectDrawSurface3,
(LPVOID *)&p_vout->p_sys->p_surface ); (LPVOID *)pp_surface_final );
IDirectDrawSurface_Release( p_surface ); /* Release the old interface */
if ( dxresult != DD_OK ) if ( dxresult != DD_OK )
{ {
intf_ErrMsg( "vout error: can't get IDirectDrawSurface3 interface." ); intf_ErrMsg( "vout error: can't get IDirectDrawSurface3 interface." );
IDirectDrawSurface_Release( p_surface ); *pp_surface_final = NULL;
p_vout->p_sys->p_surface = NULL; return 0;
return( 1 );
}
else
{
/* Release the old interface */
IDirectDrawSurface_Release( p_surface );
}
if( !p_vout->b_need_render )
{
/* Hide the overlay for now */
IDirectDrawSurface3_UpdateOverlay(p_vout->p_sys->p_surface,
NULL,
p_vout->p_sys->p_display,
NULL,
DDOVER_HIDE,
NULL);
} }
else
{
DirectXCreateClipper( p_vout );
}
/* From now on, do some initialisation for video_output */
/* if we want a valid pointer to the surface memory, we must lock
* the surface */
memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
ddsd.dwSize = sizeof(DDSURFACEDESC);
dxresult = IDirectDrawSurface3_Lock( p_vout->p_sys->p_surface, NULL, &ddsd,
DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL);
if ( dxresult == DDERR_SURFACELOST )
{
/* Your surface can be lost so be sure
* to check this and restore it if needed */
dxresult = IDirectDrawSurface3_Restore( p_vout->p_sys->p_surface );
dxresult = IDirectDrawSurface3_Lock( p_vout->p_sys->p_surface,
NULL, &ddsd, DDLOCK_NOSYSLOCK
| DDLOCK_WAIT, NULL);
}
if( dxresult != DD_OK )
{
intf_ErrMsg( "vout: DirectXCreateDisplay could not lock the surface" );
return( 1 );
}
/* Set the pointer to the surface memory */
p_vout->p_sys->p_directx_buf[ 0 ] = ddsd.lpSurface;
/* back buffer, none for now */
p_vout->p_sys->p_directx_buf[ 1 ] = ddsd.lpSurface;
/* Set thread information */
p_vout->i_width = ddsd.dwWidth;
p_vout->i_height = ddsd.dwHeight;
#ifdef NONAMELESSUNION
p_vout->i_bytes_per_line = ddsd.u1.lPitch;
#else
p_vout->i_bytes_per_line = ddsd.lPitch;
#endif /* NONAMELESSUNION */
if( p_vout->b_need_render )
{
/* For an RGB surface we need to fill in some more info */
#ifdef NONAMELESSUNION
p_vout->i_screen_depth = ddsd.ddpfPixelFormat.u1.dwRGBBitCount;
p_vout->i_bytes_per_pixel = ddsd.ddpfPixelFormat.u1.dwRGBBitCount/8;
p_vout->i_red_mask = ddsd.ddpfPixelFormat.u2.dwRBitMask;
p_vout->i_green_mask = ddsd.ddpfPixelFormat.u3.dwGBitMask;
p_vout->i_blue_mask = ddsd.ddpfPixelFormat.u4.dwBBitMask;
#else
p_vout->i_screen_depth = ddsd.ddpfPixelFormat.dwRGBBitCount;
p_vout->i_bytes_per_pixel = ddsd.ddpfPixelFormat.dwRGBBitCount/8;
p_vout->i_red_mask = ddsd.ddpfPixelFormat.dwRBitMask;
p_vout->i_green_mask = ddsd.ddpfPixelFormat.dwGBitMask;
p_vout->i_blue_mask = ddsd.ddpfPixelFormat.dwBBitMask;
#endif /* NONAMELESSUNION */
}
/* Unlock the Surface */
dxresult = IDirectDrawSurface3_Unlock(p_vout->p_sys->p_surface,
ddsd.lpSurface );
/* Set and initialize buffers */
p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_directx_buf[ 0 ],
p_vout->p_sys->p_directx_buf[ 1 ] );
return 1;
return ( 0 );
}
/*****************************************************************************
* DirectXCreateClipper: Create a clipper that will be used when blitting the
* RGB surface to the main display.
*****************************************************************************
* This clipper prevents us to modify by mistake anything on the screen
* which doesn't belong to our window. For example when a part of our video
* window is hidden by another window.
*****************************************************************************/
static int DirectXCreateClipper( vout_thread_t *p_vout )
{
HRESULT dxresult;
intf_WarnMsg( 3, "vout: DirectXCreateClipper" );
/* Create the clipper */
dxresult = IDirectDraw2_CreateClipper( p_vout->p_sys->p_ddobject, 0,
&p_vout->p_sys->p_clipper, NULL );
if( dxresult != DD_OK )
{
intf_WarnMsg( 3, "vout: DirectXCreateClipper can't create clipper." );
IDirectDrawSurface_Release( p_vout->p_sys->p_clipper );
p_vout->p_sys->p_clipper = NULL;
return( 1 );
}
/* associate the clipper to the window */
dxresult = IDirectDrawClipper_SetHWnd(p_vout->p_sys->p_clipper, 0,
p_vout->p_sys->hwnd);
if( dxresult != DD_OK )
{
intf_WarnMsg( 3,
"vout: DirectXCreateClipper can't attach clipper to window." );
IDirectDrawSurface_Release( p_vout->p_sys->p_clipper );
p_vout->p_sys->p_clipper = NULL;
return( 1 );
}
/* associate the clipper with the surface */
dxresult = IDirectDrawSurface_SetClipper(p_vout->p_sys->p_display,
p_vout->p_sys->p_clipper);
if( dxresult != DD_OK )
{
intf_WarnMsg( 3,
"vout: DirectXCreateClipper can't attach clipper to surface." );
IDirectDrawSurface_Release( p_vout->p_sys->p_clipper );
p_vout->p_sys->p_clipper = NULL;
return( 1 );
}
return( 0 );
} }
...@@ -1114,155 +834,45 @@ static int DirectXCreateClipper( vout_thread_t *p_vout ) ...@@ -1114,155 +834,45 @@ static int DirectXCreateClipper( vout_thread_t *p_vout )
* Ususally the overlay is moved by the user and thus, by a move or resize * Ususally the overlay is moved by the user and thus, by a move or resize
* event (in vout_Manage). * event (in vout_Manage).
*****************************************************************************/ *****************************************************************************/
static int DirectXUpdateOverlay( vout_thread_t *p_vout ) void DirectXUpdateOverlay( vout_thread_t *p_vout )
{ {
DDOVERLAYFX ddofx; DDOVERLAYFX ddofx;
RECT rect_window, rect_window_backup, rect_image;
POINT point_window;
DWORD dwFlags; DWORD dwFlags;
HRESULT dxresult; HRESULT dxresult;
DWORD dw_colorkey;
DDPIXELFORMAT pixel_format;
DDSURFACEDESC ddsd;
if( p_vout->p_sys->p_surface == NULL || p_vout->b_need_render )
{
intf_WarnMsg( 3, "vout: DirectXUpdateOverlay no overlay !!" );
return( 0 );
}
if( !p_vout->p_rendered_pic ) if( p_vout->p_sys->p_current_surface == NULL ||
!p_vout->p_sys->b_using_overlay )
{ {
intf_WarnMsg( 3, "vout: DirectXUpdateOverlay p_rendered_pic=NULL !" ); intf_WarnMsg( 5, "vout: DirectXUpdateOverlay no overlay !!" );
return( 1 ); return;
}
if( !p_vout->p_sys->b_display_enabled )
{
return( 0 );
}
/* Now get the coordinates of the window. We don't actually want the
* window coordinates but these of the usable surface inside the window.
* By specification GetClientRect will always set rect_window.left and
* rect_window.top to 0 because the Client area is always relative to the
* container window */
GetClientRect(p_vout->p_sys->hwnd, &rect_window);
point_window.x = 0;
point_window.y = 0;
ClientToScreen(p_vout->p_sys->hwnd, &point_window);
rect_window.left = point_window.x;
rect_window.top = point_window.y;
point_window.x = rect_window.right;
point_window.y = rect_window.bottom;
ClientToScreen(p_vout->p_sys->hwnd, &point_window);
rect_window.right = point_window.x;
rect_window.bottom = point_window.y;
/* We want to keep the aspect ratio of the video */
if( p_vout->b_scale )
{
DirectXKeepAspectRatio( p_vout, &rect_window );
} }
/* It seems we can't feed the UpdateOverlay directdraw function with /* The new window dimensions should already have been computed by the
* negative values so we have to clip the computed rectangles */ * caller of this function */
memset( &ddsd, 0, sizeof( DDSURFACEDESC ));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
IDirectDraw2_GetDisplayMode( p_vout->p_sys->p_ddobject, &ddsd );
rect_window_backup = rect_window;
/* Clip the destination window */
rect_window.left = (rect_window.left < 0) ? 0 : rect_window.left;
rect_window.right = (rect_window.right < 0) ? 0 : rect_window.right;
rect_window.top = (rect_window.top < 0) ? 0 : rect_window.top;
rect_window.bottom = (rect_window.bottom < 0) ? 0 : rect_window.bottom;
rect_window.left = (rect_window.left > ddsd.dwWidth) ? ddsd.dwWidth
: rect_window.left;
rect_window.right = (rect_window.right > ddsd.dwWidth) ? ddsd.dwWidth
: rect_window.right;
rect_window.top = (rect_window.top > ddsd.dwHeight) ? ddsd.dwHeight
: rect_window.top;
rect_window.bottom = (rect_window.bottom > ddsd.dwHeight) ? ddsd.dwHeight
: rect_window.bottom;
intf_WarnMsg( 3, "vout: DirectXUpdateOverlay window coords: %i,%i,%i,%i",
rect_window.left, rect_window.top,
rect_window.right, rect_window.bottom);
/* the 2 following lines are to fix a bug when click on Windows desktop */
if( (rect_window.right-rect_window.left)==0 ||
(rect_window.bottom-rect_window.top)==0 ) return 0;
/* Clip the source image */
rect_image.left = ( rect_window.left == rect_window_backup.left ) ? 0
: labs(rect_window_backup.left - rect_window.left) *
p_vout->p_rendered_pic->i_width /
(rect_window_backup.right - rect_window_backup.left);
rect_image.right = ( rect_window.right == rect_window_backup.right ) ?
p_vout->p_rendered_pic->i_width
: p_vout->p_rendered_pic->i_width -
labs(rect_window_backup.right - rect_window.right) *
p_vout->p_rendered_pic->i_width /
(rect_window_backup.right - rect_window_backup.left);
rect_image.top = ( rect_window.top == rect_window_backup.top ) ? 0
: labs(rect_window_backup.top - rect_window.top) *
p_vout->p_rendered_pic->i_height /
(rect_window_backup.bottom - rect_window_backup.top);
rect_image.bottom = ( rect_window.bottom == rect_window_backup.bottom ) ?
p_vout->p_rendered_pic->i_height
: p_vout->p_rendered_pic->i_height -
labs(rect_window_backup.bottom - rect_window.bottom) *
p_vout->p_rendered_pic->i_height /
(rect_window_backup.bottom - rect_window_backup.top);
intf_WarnMsg( 3, "vout: DirectXUpdateOverlay image coords: %i,%i,%i,%i",
rect_image.left, rect_image.top,
rect_image.right, rect_image.bottom);
/* compute the colorkey pixel value from the RGB value we've got */
memset( &pixel_format, 0, sizeof( DDPIXELFORMAT ));
pixel_format.dwSize = sizeof( DDPIXELFORMAT );
dxresult = IDirectDrawSurface3_GetPixelFormat( p_vout->p_sys->p_display,
&pixel_format );
if( dxresult != DD_OK )
intf_WarnMsg( 3, "vout: DirectXUpdateOverlay GetPixelFormat failed" );
dw_colorkey = (DWORD)p_vout->p_sys->i_colorkey;
#ifdef NONAMELESSUNION
dw_colorkey = (DWORD)((( dw_colorkey * pixel_format.u2.dwRBitMask) / 255)
& pixel_format.u2.dwRBitMask);
#else
dw_colorkey = (DWORD)((( dw_colorkey * pixel_format.dwRBitMask) / 255)
& pixel_format.dwRBitMask);
#endif
/* Position and show the overlay */ /* Position and show the overlay */
memset(&ddofx, 0, sizeof(DDOVERLAYFX)); memset(&ddofx, 0, sizeof(DDOVERLAYFX));
ddofx.dwSize = sizeof(DDOVERLAYFX); ddofx.dwSize = sizeof(DDOVERLAYFX);
ddofx.dckDestColorkey.dwColorSpaceLowValue = dw_colorkey; ddofx.dckDestColorkey.dwColorSpaceLowValue = p_vout->p_sys->i_colorkey;
ddofx.dckDestColorkey.dwColorSpaceHighValue = dw_colorkey; ddofx.dckDestColorkey.dwColorSpaceHighValue = p_vout->p_sys->i_colorkey;
dwFlags = DDOVER_KEYDESTOVERRIDE | DDOVER_SHOW; dwFlags = DDOVER_SHOW;
if( !p_vout->p_sys->b_caps_overlay_clipping )
dxresult = IDirectDrawSurface3_UpdateOverlay(p_vout->p_sys->p_surface, dwFlags |= DDOVER_KEYDESTOVERRIDE;
&rect_image,
p_vout->p_sys->p_display, dxresult = IDirectDrawSurface3_UpdateOverlay(
&rect_window, p_vout->p_sys->p_current_surface,
dwFlags, &p_vout->p_sys->rect_src_clipped,
&ddofx); p_vout->p_sys->p_display,
&p_vout->p_sys->rect_dest_clipped,
dwFlags,
&ddofx );
if(dxresult != DD_OK) if(dxresult != DD_OK)
{ {
intf_WarnMsg( 3, intf_WarnMsg( 3,
"vout: DirectXUpdateOverlay can't move or resize overlay" ); "vout: DirectXUpdateOverlay can't move or resize overlay" );
} }
return ( 0 );
} }
/***************************************************************************** /*****************************************************************************
...@@ -1294,10 +904,16 @@ static void DirectXCloseDDraw( vout_thread_t *p_vout ) ...@@ -1294,10 +904,16 @@ static void DirectXCloseDDraw( vout_thread_t *p_vout )
static void DirectXCloseDisplay( vout_thread_t *p_vout ) static void DirectXCloseDisplay( vout_thread_t *p_vout )
{ {
intf_WarnMsg( 3, "vout: DirectXCloseDisplay" ); intf_WarnMsg( 3, "vout: DirectXCloseDisplay" );
if( p_vout->p_sys->p_display != NULL )
if( p_vout->p_sys->p_clipper != NULL )
{ {
DirectXCloseSurface( p_vout ); intf_WarnMsg( 3, "vout: DirectXCloseDisplay clipper" );
IDirectDraw2_Release( p_vout->p_sys->p_clipper );
p_vout->p_sys->p_clipper = NULL;
}
if( p_vout->p_sys->p_display != NULL )
{
intf_WarnMsg( 3, "vout: DirectXCloseDisplay display" ); intf_WarnMsg( 3, "vout: DirectXCloseDisplay display" );
IDirectDraw2_Release( p_vout->p_sys->p_display ); IDirectDraw2_Release( p_vout->p_sys->p_display );
p_vout->p_sys->p_display = NULL; p_vout->p_sys->p_display = NULL;
...@@ -1307,126 +923,392 @@ static void DirectXCloseDisplay( vout_thread_t *p_vout ) ...@@ -1307,126 +923,392 @@ static void DirectXCloseDisplay( vout_thread_t *p_vout )
/***************************************************************************** /*****************************************************************************
* DirectXCloseSurface: close the YUV overlay or RGB surface. * DirectXCloseSurface: close the YUV overlay or RGB surface.
***************************************************************************** *****************************************************************************
* This function returns all resources allocated by the surface. * This function returns all resources allocated for the surface.
* We also call this function when the decoded picture change its dimensions
* (in that case we close the overlay surface and reopen another with the
* right dimensions).
*****************************************************************************/ *****************************************************************************/
static void DirectXCloseSurface( vout_thread_t *p_vout ) static void DirectXCloseSurface( vout_thread_t *p_vout,
LPDIRECTDRAWSURFACE3 p_surface )
{ {
intf_WarnMsg( 3, "vout: DirectXCloseSurface" ); intf_WarnMsg( 3, "vout: DirectXCloseSurface" );
if( p_vout->p_sys->p_surface != NULL ) if( p_surface != NULL )
{ {
intf_WarnMsg( 3, "vout: DirectXCloseSurface surface" ); IDirectDraw2_Release( p_surface );
IDirectDraw2_Release( p_vout->p_sys->p_surface );
p_vout->p_sys->p_surface = NULL;
} }
}
if( p_vout->p_sys->p_clipper != NULL ) /*****************************************************************************
* NewPictureVec: allocate a vector of identical pictures
*****************************************************************************
* Returns 0 on success, -1 otherwise
*****************************************************************************/
static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic,
int i_num_pics )
{
int i;
LPDIRECTDRAWSURFACE3 p_surface;
#if 0
/* We couldn't use an YUV overlay so we need to indicate to video_output
* which format we are falling back to */
switch( )
{ {
intf_WarnMsg( 3, "vout: DirectXCloseSurface clipper" ); case 8: /* FIXME: set the palette */
IDirectDraw2_Release( p_vout->p_sys->p_clipper ); p_vout->output.i_chroma = FOURCC_BI_RGB; break;
p_vout->p_sys->p_clipper = NULL; case 15:
p_vout->output.i_chroma = FOURCC_RV15; break;
case 16:
p_vout->output.i_chroma = FOURCC_RV16; break;
case 24:
p_vout->output.i_chroma = FOURCC_BI_BITFIELDS; break;
case 32:
p_vout->output.i_chroma = FOURCC_BI_BITFIELDS; break;
default:
intf_ErrMsg( "vout error: unknown screen depth" );
return( 0 );
}
#endif
intf_WarnMsg( 3, "vout: NewPictureVec" );
I_OUTPUTPICTURES = 0;
/* chroma asked for */
p_vout->output.i_chroma = p_vout->render.i_chroma;
/* hack */
if( p_vout->render.i_chroma == FOURCC_I420 )
p_vout->output.i_chroma = FOURCC_YV12;
/* First we try to create an overlay surface.
* It looks like with most hardware it's not possible to create several
* overlay surfaces, and even if it was I bet it would be slower anyway to
* use them as direct buffers because they usually reside in video memory
* which is quite slow.
* So the overlay surface (with a back-buffer) that we create won't be used
* to decode directly into it but instead picture buffers in system memory
* will be blitted to it. */
if( p_vout->p_sys->b_using_overlay )
{
if( DirectXCreateSurface( p_vout, &p_surface, p_vout->output.i_chroma,
p_vout->p_sys->b_using_overlay ) )
{
/* Allocate internal structure */
p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) );
if( p_pic[0].p_sys == NULL )
{
DirectXCloseSurface( p_vout, p_surface );
return -1;
}
p_pic[0].p_sys->p_surface = p_surface;
p_vout->p_sys->p_current_surface = p_surface;
DirectXUpdateOverlay( p_vout );
I_OUTPUTPICTURES = 1;
}
else p_vout->p_sys->b_using_overlay = 0;
}
/* As we can't have overlays, will try to create plain RBG surfaces in
* system memory. These surfaces will then be blitted onto the primary
* surface (display) so they can be displayed */
if( !p_vout->p_sys->b_using_overlay )
{
/* FixMe */
p_vout->output.i_chroma = FOURCC_RV16;
for( i = 0; i < i_num_pics; i++ )
{
if( DirectXCreateSurface( p_vout, &p_surface,
p_vout->output.i_chroma,
p_vout->p_sys->b_using_overlay ) )
{
/* Allocate internal structure */
p_pic[i].p_sys = malloc( sizeof( picture_sys_t ) );
if( p_pic[i].p_sys == NULL )
{
DirectXCloseSurface( p_vout, p_surface );
FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
I_OUTPUTPICTURES = 0;
return -1;
}
p_pic[i].p_sys->p_surface = p_surface;
I_OUTPUTPICTURES++;
}
else break;
}
}
/* Now that we've got all our direct-buffers, we can finish filling in the
* picture_t structures */
for( i = 0; i < I_OUTPUTPICTURES; i++ )
{
p_pic[i].i_status = DESTROYED_PICTURE;
p_pic[i].i_type = DIRECT_PICTURE;
PP_OUTPUTPICTURE[i] = &p_pic[i];
if( !DirectXGetSurfaceDesc( &p_pic[i] ) )
{
/* AAARRGG */
FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
I_OUTPUTPICTURES = 0;
return -1;
}
if( !UpdatePictureStruct(p_vout, &p_pic[i], p_vout->output.i_chroma) )
{
/* Unknown chroma, tell the guy to get lost */
intf_ErrMsg( "vout error: never heard of chroma 0x%.8x (%4.4s)",
p_vout->output.i_chroma,
(char*)&p_vout->output.i_chroma );
FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES );
I_OUTPUTPICTURES = 0;
return -1;
}
} }
/* Disable any display */ intf_WarnMsg( 3, "vout: End NewPictureVec");
p_vout->p_sys->b_display_enabled = 0; return 0;
} }
/***************************************************************************** /*****************************************************************************
* DirectXKeepAspectRatio: * FreePicture: destroy a picture vector allocated with NewPictureVec
***************************************************************************** *****************************************************************************
* This function adjusts the coordinates of the video rectangle to keep the *
* aspect/ratio of the video.
*****************************************************************************/ *****************************************************************************/
static void DirectXKeepAspectRatio( vout_thread_t *p_vout, RECT *rect_window ) static void FreePictureVec( vout_thread_t *p_vout, picture_t *p_pic,
int i_num_pics )
{ {
int i;
for( i = 0; i < i_num_pics; i++ )
{
DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_surface );
if( !p_vout->p_rendered_pic ) return; for( i = 0; i < i_num_pics; i++ )
switch( p_vout->p_rendered_pic->i_aspect )
{
case AR_16_9_PICTURE:
if( ((rect_window->right-rect_window->left)*9)
> ((rect_window->bottom-rect_window->top)*16) )
{
int temp;
temp = (rect_window->bottom-rect_window->top)*16/9;
temp = (rect_window->right-rect_window->left) - temp;
rect_window->left += (temp/2);
rect_window->right -= (temp/2);
}
else
{ {
int temp; free( p_pic[i].p_sys );
temp = (rect_window->right-rect_window->left)*9/16;
temp = (rect_window->bottom-rect_window->top) - temp;
rect_window->top += (temp/2);
rect_window->bottom -= (temp/2);
} }
break; }
}
case AR_221_1_PICTURE:
if( ((rect_window->right-rect_window->left)*100) /*****************************************************************************
> ((rect_window->bottom-rect_window->top)*221) ) * UpdatePictureStruct: updates the internal data in the picture_t structure
{ *****************************************************************************
int temp; * This will setup stuff for use by the video_output thread
temp = (rect_window->bottom-rect_window->top)*221/100; *****************************************************************************/
temp = (rect_window->right-rect_window->left) - temp; static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic,
rect_window->left += (temp/2); int i_chroma )
rect_window->right -= (temp/2); {
}
else switch( p_vout->output.i_chroma )
{ {
int temp;
temp = (rect_window->right-rect_window->left)*100/221; case FOURCC_YV12:
temp = (rect_window->bottom-rect_window->top) - temp;
rect_window->top += (temp/2); p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
rect_window->bottom -= (temp/2); p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
} p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->ddsd.lPitch;
break; p_pic->p[Y_PLANE].i_pixel_bytes = 1;
p_pic->p[Y_PLANE].b_margin = 0;
case AR_3_4_PICTURE:
if( ((rect_window->right-rect_window->left)*3) p_pic->V_PIXELS = p_pic->Y_PIXELS
> ((rect_window->bottom-rect_window->top)*4) ) + p_pic->p[Y_PLANE].i_lines * p_pic->p[Y_PLANE].i_pitch;
{ p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
int temp; p_pic->p[V_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
temp = (rect_window->bottom-rect_window->top)*4/3; p_pic->p[V_PLANE].i_pixel_bytes = 1;
temp = (rect_window->right-rect_window->left) - temp; p_pic->p[V_PLANE].b_margin = 0;
rect_window->left += (temp/2);
rect_window->right -= (temp/2); p_pic->U_PIXELS = p_pic->V_PIXELS
} + p_pic->p[V_PLANE].i_lines * p_pic->p[V_PLANE].i_pitch;
else p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
{ p_pic->p[U_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
int temp; p_pic->p[U_PLANE].i_pixel_bytes = 1;
temp = (rect_window->right-rect_window->left)*3/4; p_pic->p[U_PLANE].b_margin = 0;
temp = (rect_window->bottom-rect_window->top) - temp;
rect_window->top += (temp/2); p_pic->i_planes = 3;
rect_window->bottom -= (temp/2); break;
}
break; case FOURCC_RV16:
case AR_SQUARE_PICTURE: p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
default: p_pic->p->i_lines = p_vout->output.i_height;
if( (rect_window->right-rect_window->left) p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
> (rect_window->bottom-rect_window->top) ) p_pic->p->i_pixel_bytes = 2;
{ p_pic->p->b_margin = 0;
int temp;
temp = (rect_window->bottom-rect_window->top); p_pic->p->i_red_mask = 0x001f;
temp = (rect_window->right-rect_window->left) - temp; p_pic->p->i_green_mask = 0x03e0;
rect_window->left += (temp/2); p_pic->p->i_blue_mask = 0x7c00;
rect_window->right -= (temp/2);
} p_pic->i_planes = 1;
break;
case FOURCC_RV15:
p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
p_pic->p->i_lines = p_vout->output.i_height;
p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch;
p_pic->p->i_pixel_bytes = 2;
p_pic->p->b_margin = 0;
p_pic->p->i_red_mask = 0x001f;
p_pic->p->i_green_mask = 0x07e0;
p_pic->p->i_blue_mask = 0xf800;
p_pic->i_planes = 1;
break;
#if 0
case FOURCC_I420:
p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->ddsd.lPitch;
p_pic->p[Y_PLANE].i_pixel_bytes = 1;
p_pic->p[Y_PLANE].b_margin = 0;
p_pic->U_PIXELS = p_pic->Y_PIXELS
+ p_pic->p[Y_PLANE].i_lines * p_pic->p[Y_PLANE].i_pitch;
p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
p_pic->p[U_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
p_pic->p[U_PLANE].i_pixel_bytes = 1;
p_pic->p[U_PLANE].b_margin = 0;
p_pic->V_PIXELS = p_pic->U_PIXELS
+ p_pic->p[U_PLANE].i_lines * p_pic->p[U_PLANE].i_pitch;
p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
p_pic->p[V_PLANE].i_pitch = p_pic->p[U_PLANE].i_pitch;
p_pic->p[V_PLANE].i_pixel_bytes = 1;
p_pic->p[V_PLANE].b_margin = 0;
p_pic->i_planes = 3;
break;
case FOURCC_Y211:
p_pic->p->p_pixels = p_pic->p_sys->p_image->data
+ p_pic->p_sys->p_image->offsets[0];
p_pic->p->i_lines = p_vout->output.i_height;
/* XXX: this just looks so plain wrong... check it out ! */
p_pic->p->i_pitch = p_pic->p_sys->p_image->pitches[0] / 4;
p_pic->p->i_pixel_bytes = 4;
p_pic->p->b_margin = 0;
p_pic->i_planes = 1;
break;
case FOURCC_YUY2:
case FOURCC_UYVY:
p_pic->p->p_pixels = p_pic->p_sys->p_image->data
+ p_pic->p_sys->p_image->offsets[0];
p_pic->p->i_lines = p_vout->output.i_height;
p_pic->p->i_pitch = p_pic->p_sys->p_image->pitches[0];
p_pic->p->i_pixel_bytes = 4;
p_pic->p->b_margin = 0;
p_pic->i_planes = 1;
break;
#endif
default:
/* Not supported */
return 0;
}
return 1;
}
/*****************************************************************************
* DirectXGetDDrawCaps: Probe the capabilities of the hardware
*****************************************************************************
* It is nice to know which features are supported by the hardware so we can
* find ways to optimize our rendering.
*****************************************************************************/
static void DirectXGetDDrawCaps( vout_thread_t *p_vout )
{
DDCAPS ddcaps;
HRESULT dxresult;
/* This is just an indication of whether or not we'll support overlay,
* but with this test we don't know if we support YUV overlay */
memset( &ddcaps, 0, sizeof( DDCAPS ));
ddcaps.dwSize = sizeof(DDCAPS);
dxresult = IDirectDraw2_GetCaps( p_vout->p_sys->p_ddobject,
&ddcaps, NULL );
if(dxresult != DD_OK )
{
intf_WarnMsg( 3,"vout error: can't get caps." );
}
else else
{ {
int temp; BOOL bHasOverlay, bHasOverlayFourCC, bCanClipOverlay,
temp = (rect_window->right-rect_window->left); bHasColorKey, bCanStretch;
temp = (rect_window->bottom-rect_window->top) - temp;
rect_window->top += (temp/2); /* Determine if the hardware supports overlay surfaces */
rect_window->bottom -= (temp/2); bHasOverlay = ((ddcaps.dwCaps & DDCAPS_OVERLAY) ==
} DDCAPS_OVERLAY) ? TRUE : FALSE;
break; /* Determine if the hardware supports overlay surfaces */
bHasOverlayFourCC = ((ddcaps.dwCaps & DDCAPS_OVERLAYFOURCC) ==
} DDCAPS_OVERLAYFOURCC) ? TRUE : FALSE;
/* Determine if the hardware supports overlay surfaces */
bCanClipOverlay = ((ddcaps.dwCaps & DDCAPS_OVERLAYCANTCLIP) ==
0 ) ? TRUE : FALSE;
/* Determine if the hardware supports colorkeying */
bHasColorKey = ((ddcaps.dwCaps & DDCAPS_COLORKEY) ==
DDCAPS_COLORKEY) ? TRUE : FALSE;
/* Determine if the hardware supports scaling of the overlay surface */
bCanStretch = ((ddcaps.dwCaps & DDCAPS_OVERLAYSTRETCH) ==
DDCAPS_OVERLAYSTRETCH) ? TRUE : FALSE;
intf_WarnMsg( 3, "vout: DirectDraw Capabilities:" );
intf_WarnMsg( 3, " overlay=%i yuvoverlay=%i can_clip_overlay=%i "
"colorkey=%i stretch=%i",
bHasOverlay, bHasOverlayFourCC, bCanClipOverlay,
bHasColorKey, bCanStretch );
/* Overlay clipping support is interesting for us as it means we can
* get rid of the colorkey alltogether */
p_vout->p_sys->b_caps_overlay_clipping = bCanClipOverlay;
}
}
/*****************************************************************************
* DirectXGetSurfaceDesc: Get some more information about the surface
*****************************************************************************
* This function get and stores the surface descriptor which among things
* has the pointer to the picture data.
*****************************************************************************/
static int DirectXGetSurfaceDesc( picture_t *p_pic )
{
HRESULT dxresult;
/* Lock the surface to get a valid pointer to the picture buffer */
memset( &p_pic->p_sys->ddsd, 0, sizeof( DDSURFACEDESC ));
p_pic->p_sys->ddsd.dwSize = sizeof(DDSURFACEDESC);
dxresult = IDirectDrawSurface3_Lock( p_pic->p_sys->p_surface,
NULL, &p_pic->p_sys->ddsd,
DDLOCK_NOSYSLOCK | DDLOCK_WAIT,
NULL );
if ( dxresult == DDERR_SURFACELOST )
{
/* Your surface can be lost so be sure
* to check this and restore it if needed */
dxresult = IDirectDrawSurface3_Restore( p_pic->p_sys->p_surface );
dxresult = IDirectDrawSurface3_Lock( p_pic->p_sys->p_surface, NULL,
&p_pic->p_sys->ddsd,
DDLOCK_NOSYSLOCK | DDLOCK_WAIT,
NULL);
}
if( dxresult != DD_OK )
{
intf_ErrMsg( "vout: DirectXGetSurfaceDesc can't lock surface" );
return 0;
}
/* Unlock the Surface */
dxresult = IDirectDrawSurface3_Unlock( p_pic->p_sys->p_surface, NULL );
return 1;
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vout_directx.h: Windows DirectX video output header file * vout_directx.h: Windows DirectX video output header file
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vout_directx.h,v 1.1 2001/07/11 14:26:19 gbazin Exp $ * $Id: vout_directx.h,v 1.2 2002/01/17 23:02:45 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -32,28 +32,42 @@ typedef struct vout_sys_s ...@@ -32,28 +32,42 @@ typedef struct vout_sys_s
LPDIRECTDRAW2 p_ddobject; /* DirectDraw object */ LPDIRECTDRAW2 p_ddobject; /* DirectDraw object */
LPDIRECTDRAWSURFACE3 p_display; /* Display device */ LPDIRECTDRAWSURFACE3 p_display; /* Display device */
LPDIRECTDRAWSURFACE3 p_surface; /* surface where we display the video */ LPDIRECTDRAWSURFACE3 p_current_surface; /* surface currently displayed */
LPDIRECTDRAWCLIPPER p_clipper; /* clipper used for blitting */ LPDIRECTDRAWCLIPPER p_clipper; /* clipper used for blitting */
HINSTANCE hddraw_dll; /* handle of the opened ddraw dll */ HINSTANCE hddraw_dll; /* handle of the opened ddraw dll */
HBRUSH hbrush; /* window backgound brush (color) */ HBRUSH hbrush; /* window backgound brush (color) */
HWND hwnd; /* Handle of the main window */ HWND hwnd; /* Handle of the main window */
int i_image_width; /* size of the decoded image */ boolean_t b_using_overlay; /* Are we using an overlay surface */
int i_image_height;
int i_window_width; /* size of the displayed image */
int i_window_height;
int i_colorkey; /* colorkey used to display the overlay */ /* size of the display */
RECT rect_display;
boolean_t b_display_enabled; int i_display_depth;
boolean_t b_cursor;
/* Window position and size */
int i_window_x;
int i_window_y;
int i_window_width;
int i_window_height;
/* Coordinates of src and dest images (used when blitting to display) */
RECT rect_src;
RECT rect_src_clipped;
RECT rect_dest;
RECT rect_dest_clipped;
u16 i_changes; /* changes made to the video display */ /* DDraw capabilities */
int b_caps_overlay_clipping;
boolean_t b_cursor_autohidden; int i_rgb_colorkey; /* colorkey in RGB used by the overlay */
mtime_t i_lastmoved; int i_colorkey; /* colorkey used by the overlay */
boolean_t b_cursor;
u16 i_changes; /* changes made to the video display */
char *p_directx_buf[2]; /* Buffer information */ boolean_t b_cursor_autohidden;
mtime_t i_lastmoved;
vlc_thread_t event_thread_id; /* event thread */ vlc_thread_t event_thread_id; /* event thread */
vlc_mutex_t event_thread_lock; /* lock for the event thread */ vlc_mutex_t event_thread_lock; /* lock for the event thread */
...@@ -64,6 +78,19 @@ typedef struct vout_sys_s ...@@ -64,6 +78,19 @@ typedef struct vout_sys_s
} vout_sys_t; } vout_sys_t;
/*****************************************************************************
* 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.
*****************************************************************************/
typedef struct picture_sys_s
{
LPDIRECTDRAWSURFACE3 p_surface;
DDSURFACEDESC ddsd;
} picture_sys_t;
/***************************************************************************** /*****************************************************************************
* Prototypes from vout_directx.c * Prototypes from vout_directx.c
*****************************************************************************/ *****************************************************************************/
...@@ -72,3 +99,4 @@ typedef struct vout_sys_s ...@@ -72,3 +99,4 @@ typedef struct vout_sys_s
* Prototypes from vout_events.c * Prototypes from vout_events.c
*****************************************************************************/ *****************************************************************************/
void DirectXEventThread ( vout_thread_t *p_vout ); void DirectXEventThread ( vout_thread_t *p_vout );
void DirectXUpdateOverlay( vout_thread_t *p_vout );
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vout_events.c: Windows DirectX video output events handler * vout_events.c: Windows DirectX video output events handler
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: vout_events.c,v 1.7 2001/12/30 07:09:54 sam Exp $ * $Id: vout_events.c,v 1.8 2002/01/17 23:02:45 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -39,12 +39,9 @@ ...@@ -39,12 +39,9 @@
#include <windows.h> #include <windows.h>
#include <windowsx.h> #include <windowsx.h>
#include <shellapi.h>
#if defined( _MSC_VER ) #include <ddraw.h>
# include <ddraw.h>
#else
# include <directx.h>
#endif
#include "interface.h" #include "interface.h"
...@@ -55,19 +52,10 @@ ...@@ -55,19 +52,10 @@
*****************************************************************************/ *****************************************************************************/
static int DirectXCreateWindow( vout_thread_t *p_vout ); static int DirectXCreateWindow( vout_thread_t *p_vout );
static void DirectXCloseWindow ( vout_thread_t *p_vout ); static void DirectXCloseWindow ( vout_thread_t *p_vout );
static void DirectXUpdateRects( vout_thread_t *p_vout );
static long FAR PASCAL DirectXEventProc ( HWND hwnd, UINT message, static long FAR PASCAL DirectXEventProc ( HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam ); WPARAM wParam, LPARAM lParam );
/*****************************************************************************
* Global variables.
* I really hate them, but here I don't have any choice. And anyway, this
* shouldn't really affect reentrancy.
* This variable is used to know if we have to update the overlay position
* and size. This is to fix the bug we've got when the Windows option, to show
* the content of a window when you drag it, is enabled.
*****************************************************************************/
int b_directx_update_overlay = 0;
/***************************************************************************** /*****************************************************************************
* DirectXEventThread: Create video window & handle its messages * DirectXEventThread: Create video window & handle its messages
***************************************************************************** *****************************************************************************
...@@ -79,7 +67,6 @@ int b_directx_update_overlay = 0; ...@@ -79,7 +67,6 @@ int b_directx_update_overlay = 0;
void DirectXEventThread( vout_thread_t *p_vout ) void DirectXEventThread( vout_thread_t *p_vout )
{ {
MSG msg; MSG msg;
boolean_t b_dispatch_msg = TRUE;
/* Initialisation */ /* Initialisation */
...@@ -104,191 +91,147 @@ void DirectXEventThread( vout_thread_t *p_vout ) ...@@ -104,191 +91,147 @@ void DirectXEventThread( vout_thread_t *p_vout )
vlc_mutex_unlock( &p_vout->p_sys->event_thread_lock ); vlc_mutex_unlock( &p_vout->p_sys->event_thread_lock );
/* Main loop */ /* Main loop */
while( !p_vout->b_die && !p_vout->p_sys->b_event_thread_die ) /* GetMessage will sleep if there's no message in the queue */
while( GetMessage( &msg, p_vout->p_sys->hwnd, 0, 0 ) )
{ {
/* GetMessage will sleep if there's no message in the queue */ /* Check if we are asked to exit */
if( GetMessage( &msg, NULL, 0, 0 ) >= 0 ) if( p_vout->b_die || p_vout->p_sys->b_event_thread_die )
break;
switch( msg.message )
{ {
switch( msg.message )
#if 0
case WM_PAINT:
intf_WarnMsg( 4, "vout: vout_Manage WM_PAINT" );
break;
case WM_ERASEBKGND:
intf_WarnMsg( 4, "vout: vout_Manage WM_ERASEBKGND" );
break;
#endif
case WM_MOUSEMOVE:
if( p_vout->p_sys->b_cursor )
{ {
if( p_vout->p_sys->b_cursor_autohidden )
case WM_CLOSE:
intf_WarnMsg( 3, "vout: vout_Manage WM_CLOSE" );
break;
case WM_QUIT:
intf_WarnMsg( 3, "vout: vout_Manage WM_QUIT" );
p_vout->p_sys->b_event_thread_die = 1;
p_main->p_intf->b_die = 1;
break;
case WM_MOVE:
intf_WarnMsg( 3, "vout: vout_Manage WM_MOVE" );
if( !p_vout->b_need_render )
{ {
p_vout->p_sys->i_changes |= VOUT_SIZE_CHANGE; p_vout->p_sys->b_cursor_autohidden = 0;
p_vout->p_sys->i_lastmoved = mdate();
ShowCursor( TRUE );
} }
/* don't create a never ending loop */ else
b_dispatch_msg = FALSE;
break;
case WM_APP:
intf_WarnMsg( 3, "vout: vout_Manage WM_APP" );
if( !p_vout->b_need_render )
{ {
p_vout->p_sys->i_changes |= VOUT_SIZE_CHANGE; p_vout->p_sys->i_lastmoved = mdate();
} }
/* size change has been handled (to fix a bug)*/ }
b_directx_update_overlay = 0; break;
/* don't create a never ending loop */
b_dispatch_msg = FALSE; case WM_RBUTTONUP:
intf_WarnMsg( 4, "vout: vout_Manage WM_RBUTTONUP" );
p_main->p_intf->b_menu_change = 1;
break;
case WM_KEYDOWN:
/* the key events are first processed here. The next
* message processed by this main message loop will be the
* char translation of the key event */
intf_WarnMsg( 3, "vout: vout_Manage WM_KEYDOWN" );
switch( msg.wParam )
{
case VK_ESCAPE:
case VK_F12:
PostQuitMessage( 0 );
break; break;
}
#if 0 TranslateMessage(&msg);
case WM_PAINT: break;
intf_WarnMsg( 4, "vout: vout_Manage WM_PAINT" );
case WM_CHAR:
intf_WarnMsg( 3, "vout: vout_Manage WM_CHAR" );
switch( msg.wParam )
{
case 'q':
case 'Q':
PostQuitMessage( 0 );
break; break;
case WM_ERASEBKGND: case 'f': /* switch to fullscreen */
intf_WarnMsg( 4, "vout: vout_Manage WM_ERASEBKGND" ); case 'F':
p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
break; break;
#endif
case 'c': /* toggle grayscale */
case WM_MOUSEMOVE: case 'C':
intf_WarnMsg( 4, "vout: vout_Manage WM_MOUSEMOVE" ); p_vout->b_grayscale = ! p_vout->b_grayscale;
if( p_vout->p_sys->b_cursor ) p_vout->p_sys->i_changes |= VOUT_GRAYSCALE_CHANGE;
{
if( p_vout->p_sys->b_cursor_autohidden )
{
p_vout->p_sys->b_cursor_autohidden = 0;
p_vout->p_sys->i_lastmoved = mdate();
ShowCursor( TRUE );
}
else
{
p_vout->p_sys->i_lastmoved = mdate();
}
}
break; break;
case WM_RBUTTONUP: case 'i': /* toggle info */
intf_WarnMsg( 4, "vout: vout_Manage WM_RBUTTONUP" ); case 'I':
p_main->p_intf->b_menu_change = 1; p_vout->b_info = ! p_vout->b_info;
p_vout->p_sys->i_changes |= VOUT_INFO_CHANGE;
break; break;
case WM_KEYDOWN: case 's': /* toggle scaling */
/* the key events are first processed here. The next case 'S':
* message processed by this main message loop will be the p_vout->b_scale = ! p_vout->b_scale;
* char translation of the key event */ p_vout->p_sys->i_changes |= VOUT_SCALE_CHANGE;
intf_WarnMsg( 3, "vout: vout_Manage WM_KEYDOWN" );
switch( msg.wParam )
{
case VK_ESCAPE:
case VK_F12:
PostQuitMessage( 0 );
break;
}
TranslateMessage(&msg);
b_dispatch_msg = FALSE;
break; break;
case WM_CHAR: case ' ': /* toggle interface */
intf_WarnMsg( 3, "vout: vout_Manage WM_CHAR" ); p_vout->b_interface = ! p_vout->b_interface;
switch( msg.wParam ) p_vout->p_sys->i_changes |= VOUT_INTF_CHANGE;
{
case 'q':
case 'Q':
PostQuitMessage( 0 );
break;
case 'f': /* switch to fullscreen */
case 'F':
p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
break;
case 'y': /* switch to hard YUV */
case 'Y':
p_vout->p_sys->i_changes |= VOUT_YUV_CHANGE;
break;
case 'c': /* toggle grayscale */
case 'C':
p_vout->b_grayscale = ! p_vout->b_grayscale;
p_vout->p_sys->i_changes |= VOUT_GRAYSCALE_CHANGE;
break;
case 'i': /* toggle info */
case 'I':
p_vout->b_info = ! p_vout->b_info;
p_vout->p_sys->i_changes |= VOUT_INFO_CHANGE;
break;
case 's': /* toggle scaling */
case 'S':
p_vout->b_scale = ! p_vout->b_scale;
p_vout->p_sys->i_changes |= VOUT_SCALE_CHANGE;
break;
case ' ': /* toggle interface */
p_vout->b_interface = ! p_vout->b_interface;
p_vout->p_sys->i_changes |= VOUT_INTF_CHANGE;
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 )msg.wParam ) )
{
intf_DbgMsg( "unhandled key '%c' (%i)",
(char)msg.wParam, msg.wParam );
}
break;
}
#if 0
default:
intf_WarnMsg( 4, "vout: vout_Manage WM Default %i",
msg.message );
break; break;
#endif
} /* End Switch */ 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;
/* don't create a never ending loop */ default:
if( b_dispatch_msg ) intf_DbgMsg( "unhandled key '%c' (%i)",
{ (char)msg.wParam, msg.wParam );
TranslateMessage(&msg); break;
DispatchMessage(&msg);
} }
b_dispatch_msg = TRUE;
} /* if( GetMessage() ) */ default:
else /* Messages we don't handle directly are dispatched to the
{ * window procedure */
intf_ErrMsg("vout error: GetMessage failed in DirectXEventThread"); #if 0
p_vout->p_sys->b_event_thread_die = 1; intf_WarnMsg( 5, "vout: vout_Manage unhandled message",
} /* End if( GetMessage() ) */ msg.message );
#endif
TranslateMessage(&msg);
DispatchMessage(&msg);
break;
} /* End Switch */
} /* End Main loop */ } /* End Main loop */
/* Destroy the window */ if( msg.message == WM_QUIT )
DirectXCloseWindow( p_vout ); {
intf_WarnMsg( 3, "vout: DirectXEventThread WM_QUIT" );
p_vout->p_sys->hwnd = NULL; /* Window already destroyed */
/* exit application */
p_main->p_intf->b_die = 1;
}
intf_WarnMsg( 3, "vout: DirectXEventThread Terminating" );
/* Set thread Status */ /* clear the changes formerly signaled */
p_vout->p_sys->i_event_thread_status = THREAD_OVER; p_vout->p_sys->i_changes = 0;
DirectXCloseWindow( p_vout );
} }
...@@ -308,6 +251,8 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -308,6 +251,8 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
RECT rect_window; RECT rect_window;
COLORREF colorkey; COLORREF colorkey;
HDC hdc; HDC hdc;
HICON vlc_icon = NULL;
char vlc_path[_MAX_PATH+1];
intf_WarnMsg( 3, "vout: DirectXCreateWindow" ); intf_WarnMsg( 3, "vout: DirectXCreateWindow" );
...@@ -326,18 +271,37 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -326,18 +271,37 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
/* the first step is to find the colorkey we want to use. The difficulty /* the first step is to find the colorkey we want to use. The difficulty
* comes from the potential dithering (depends on the display depth) * comes from the potential dithering (depends on the display depth)
* because we need to know the real RGB value of the chosen colorkey */ * because we need to know the real RGB value of the chosen colorkey */
hdc = GetDC( GetDesktopWindow() ); hdc = GetDC( NULL );
for( colorkey = 5; colorkey < 0xFF /*all shades of red*/; colorkey++ ) for( colorkey = 5; colorkey < 0xFF /*all shades of red*/; colorkey++ )
{ {
if( colorkey == GetNearestColor( hdc, colorkey ) ) if( colorkey == GetNearestColor( hdc, colorkey ) )
break; break;
} }
intf_WarnMsg(3,"vout: DirectXCreateWindow background color:%i", colorkey); intf_WarnMsg(3,"vout: DirectXCreateWindow background color:%i", colorkey);
ReleaseDC( p_vout->p_sys->hwnd, hdc );
/* create the actual brush */ /* create the actual brush */
p_vout->p_sys->hbrush = CreateSolidBrush(colorkey); p_vout->p_sys->hbrush = CreateSolidBrush(colorkey);
p_vout->p_sys->i_colorkey = (int)colorkey; p_vout->p_sys->i_rgb_colorkey = (int)colorkey;
/* Get the current size of the display and its colour depth */
p_vout->p_sys->rect_display.right = GetDeviceCaps( hdc, HORZRES );
p_vout->p_sys->rect_display.bottom = GetDeviceCaps( hdc, VERTRES );
p_vout->p_sys->i_display_depth = GetDeviceCaps( hdc, BITSPIXEL );
intf_WarnMsg( 3, "vout: Screen dimensions %ix%i colour depth %i",
p_vout->p_sys->rect_display.right,
p_vout->p_sys->rect_display.bottom,
p_vout->p_sys->i_display_depth );
ReleaseDC( p_vout->p_sys->hwnd, hdc );
/* Get the Icon from the main app */
if( GetModuleFileName( NULL, vlc_path, _MAX_PATH ) )
{
vlc_icon = ExtractIcon( hInstance, vlc_path, 0 );
}
if( !vlc_icon )
vlc_icon = LoadIcon( NULL, IDI_APPLICATION );
/* fill in the window class structure */ /* fill in the window class structure */
wc.cbSize = sizeof(WNDCLASSEX); wc.cbSize = sizeof(WNDCLASSEX);
...@@ -346,12 +310,12 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -346,12 +310,12 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
wc.cbClsExtra = 0; /* no extra class data */ wc.cbClsExtra = 0; /* no extra class data */
wc.cbWndExtra = 0; /* no extra window data */ wc.cbWndExtra = 0; /* no extra window data */
wc.hInstance = hInstance; /* instance */ wc.hInstance = hInstance; /* instance */
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); /* load the vlc icon */ wc.hIcon = CopyIcon( vlc_icon ); /* load the vlc icon */
wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* load a default cursor */ wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* load a default cursor */
wc.hbrBackground = p_vout->p_sys->hbrush; /* background color */ wc.hbrBackground = p_vout->p_sys->hbrush; /* background color */
wc.lpszMenuName = NULL; /* no menu */ wc.lpszMenuName = NULL; /* no menu */
wc.lpszClassName = "VLC DirectX"; /* use a special class */ wc.lpszClassName = "VLC DirectX"; /* use a special class */
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); /* load the vlc icon */ wc.hIconSm = CopyIcon( vlc_icon ); /* load the vlc icon */
/* register the window class */ /* register the window class */
if (!RegisterClassEx(&wc)) if (!RegisterClassEx(&wc))
...@@ -374,7 +338,7 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -374,7 +338,7 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
p_vout->p_sys->hwnd = CreateWindow("VLC DirectX",/* name of window class */ p_vout->p_sys->hwnd = CreateWindow("VLC DirectX",/* name of window class */
"VLC DirectX", /* window title bar text */ "VLC DirectX", /* window title bar text */
WS_OVERLAPPEDWINDOW WS_OVERLAPPEDWINDOW
| WS_SIZEBOX | WS_VISIBLE, /* window style */ | WS_SIZEBOX, /* window style */
10, /* default X coordinate */ 10, /* default X coordinate */
10, /* default Y coordinate */ 10, /* default Y coordinate */
rect_window.right - rect_window.left, /* window width */ rect_window.right - rect_window.left, /* window width */
...@@ -389,6 +353,11 @@ static int DirectXCreateWindow( vout_thread_t *p_vout ) ...@@ -389,6 +353,11 @@ static int DirectXCreateWindow( vout_thread_t *p_vout )
return (1); return (1);
} }
/* store a p_vout pointer into the window local storage (for later use
* in DirectXEventProc).
* We need to use SetWindowLongPtr when it is available in mingw */
SetWindowLong( p_vout->p_sys->hwnd, GWL_USERDATA, (LONG)p_vout );
/* now display the window */ /* now display the window */
ShowWindow(p_vout->p_sys->hwnd, SW_SHOW); ShowWindow(p_vout->p_sys->hwnd, SW_SHOW);
...@@ -423,6 +392,83 @@ static void DirectXCloseWindow( vout_thread_t *p_vout ) ...@@ -423,6 +392,83 @@ static void DirectXCloseWindow( vout_thread_t *p_vout )
} }
} }
/*****************************************************************************
* DirectXUpdateRects:
*****************************************************************************
* This function is called when the window position and size is changed, and
* its job is to update the source and destination RECTs used to display the
* picture.
*****************************************************************************/
static void DirectXUpdateRects( vout_thread_t *p_vout )
{
int i_width, i_height, i_x, i_y;
#define rect_src p_vout->p_sys->rect_src
#define rect_src_clipped p_vout->p_sys->rect_src_clipped
#define rect_dest p_vout->p_sys->rect_dest
#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
#define rect_display p_vout->p_sys->rect_display
vout_PlacePicture( p_vout, p_vout->p_sys->i_window_width,
p_vout->p_sys->i_window_height,
&i_x, &i_y, &i_width, &i_height );
/* Destination image position and dimensions */
rect_dest.left = i_x + p_vout->p_sys->i_window_x;
rect_dest.top = i_y + p_vout->p_sys->i_window_y;
rect_dest.right = rect_dest.left + i_width;
rect_dest.bottom = rect_dest.top + i_height;
/* UpdateOverlay directdraw function doesn't automatically clip to the
* display size so we need to do it otherwise it will fails */
/* Clip the destination window */
IntersectRect( &rect_dest_clipped, &rect_dest, &rect_display );
intf_WarnMsg( 3, "vout: DirectXUpdateRects image_dst_clipped coords:"
" %i,%i,%i,%i",
rect_dest_clipped.left, rect_dest_clipped.top,
rect_dest_clipped.right, rect_dest_clipped.bottom);
/* the 2 following lines are to fix a bug when clicking on the desktop */
if( (rect_dest_clipped.right - rect_dest_clipped.left)==0 ||
(rect_dest_clipped.bottom - rect_dest_clipped.top)==0 )
{
SetRectEmpty( &rect_src_clipped );
return;
}
/* src image dimensions */
rect_src.left = 0;
rect_src.top = 0;
rect_src.right = p_vout->render.i_width;
rect_src.bottom = p_vout->render.i_height;
/* Clip the source image */
rect_src_clipped.left = (rect_dest_clipped.left - rect_dest.left) *
p_vout->render.i_width / (rect_dest.right - rect_dest.left);
rect_src_clipped.right = p_vout->render.i_width -
(rect_dest.right - rect_dest_clipped.right) * p_vout->render.i_width /
(rect_dest.right - rect_dest.left);
rect_src_clipped.top = (rect_dest_clipped.top - rect_dest.top) *
p_vout->render.i_height / (rect_dest.bottom - rect_dest.top);
rect_src_clipped.bottom = p_vout->render.i_height -
(rect_dest.bottom - rect_dest_clipped.bottom) * p_vout->render.i_height /
(rect_dest.bottom - rect_dest.top);
intf_WarnMsg( 3, "vout: DirectXUpdateRects image_src_clipped"
" coords: %i,%i,%i,%i",
rect_src_clipped.left, rect_src_clipped.top,
rect_src_clipped.right, rect_src_clipped.bottom);
#undef rect_src
#undef rect_src_clipped
#undef rect_dest
#undef rect_dest_clipped
#undef rect_display
}
/***************************************************************************** /*****************************************************************************
* DirectXEventProc: This is the window event processing function. * DirectXEventProc: This is the window event processing function.
***************************************************************************** *****************************************************************************
...@@ -430,23 +476,54 @@ static void DirectXCloseWindow( vout_thread_t *p_vout ) ...@@ -430,23 +476,54 @@ static void DirectXCloseWindow( vout_thread_t *p_vout )
* function to it. The aim of this function is to manage "Queued Messages" and * function to it. The aim of this function is to manage "Queued Messages" and
* "Nonqueued Messages". * "Nonqueued Messages".
* Queued Messages are those picked up and retransmitted by vout_Manage * Queued Messages are those picked up and retransmitted by vout_Manage
* (using the GetMessage function). * (using the GetMessage and DispatchMessage functions).
* Nonqueued Messages are those that Windows will send directly to this * Nonqueued Messages are those that Windows will send directly to this
* function (like WM_DESTROY, WM_WINDOWPOSCHANGED...) * procedure (like WM_DESTROY, WM_WINDOWPOSCHANGED...)
*****************************************************************************/ *****************************************************************************/
static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam ) WPARAM wParam, LPARAM lParam )
{ {
vout_thread_t *p_vout;
switch( message ) switch( message )
{ {
#if 0 case WM_WINDOWPOSCHANGED:
case WM_APP: {
intf_WarnMsg( 3, "vout: WinProc WM_APP" ); RECT rect_window;
POINT point_window;
p_vout = (vout_thread_t *)GetWindowLong( hwnd, GWL_USERDATA );
/* update the window position */
point_window.x = 0;
point_window.y = 0;
ClientToScreen( hwnd, &point_window );
p_vout->p_sys->i_window_x = point_window.x;
p_vout->p_sys->i_window_y = point_window.y;
/* update the window size */
GetClientRect( hwnd, &rect_window );
p_vout->p_sys->i_window_width = rect_window.right;
p_vout->p_sys->i_window_height = rect_window.bottom;
intf_WarnMsg( 3, "vout: WinProc WM_WINDOWPOSCHANGED %i,%i,%i,%i",
p_vout->p_sys->i_window_x, p_vout->p_sys->i_window_y,
p_vout->p_sys->i_window_width,
p_vout->p_sys->i_window_height );
DirectXUpdateRects( p_vout );
if( p_vout->p_sys->b_using_overlay )
DirectXUpdateOverlay( p_vout );
/* signal the size change */
p_vout->p_sys->i_changes |= VOUT_SIZE_CHANGE;
return 0;
}
break; break;
case WM_ACTIVATE: case WM_ACTIVATE:
intf_WarnMsg( 4, "vout: WinProc WM_ACTIVED" ); intf_WarnMsg( 4, "vout: WinProc WM_ACTIVE" );
break; break;
case WM_CREATE: case WM_CREATE:
...@@ -457,7 +534,6 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, ...@@ -457,7 +534,6 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
case WM_CLOSE: case WM_CLOSE:
intf_WarnMsg( 4, "vout: WinProc WM_CLOSE" ); intf_WarnMsg( 4, "vout: WinProc WM_CLOSE" );
break; break;
#endif
/* the window has been closed so shut down everything now */ /* the window has been closed so shut down everything now */
case WM_DESTROY: case WM_DESTROY:
...@@ -476,46 +552,6 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, ...@@ -476,46 +552,6 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message,
break; break;
#if 0 #if 0
case WM_MOVE:
intf_WarnMsg( 4, "vout: WinProc WM_MOVE" );
break;
case WM_SIZE:
intf_WarnMsg( 4, "vout: WinProc WM_SIZE" );
break;
case WM_MOVING:
intf_WarnMsg( 4, "vout: WinProc WM_MOVING" );
break;
case WM_ENTERSIZEMOVE:
intf_WarnMsg( 4, "vout: WinProc WM_ENTERSIZEMOVE" );
break;
case WM_SIZING:
intf_WarnMsg( 4, "vout: WinProc WM_SIZING" );
break;
#endif
case WM_WINDOWPOSCHANGED:
intf_WarnMsg( 3, "vout: WinProc WM_WINDOWPOSCHANGED" );
b_directx_update_overlay = 1;
PostMessage( hwnd, WM_APP, 0, 0);
break;
#if 0
case WM_WINDOWPOSCHANGING:
intf_WarnMsg( 3, "vout: WinProc WM_WINDOWPOSCHANGING" );
break;
case WM_PAINT:
intf_WarnMsg( 4, "vout: WinProc WM_PAINT" );
break;
case WM_ERASEBKGND:
intf_WarnMsg( 4, "vout: WinProc WM_ERASEBKGND" );
break;
default: default:
intf_WarnMsg( 4, "vout: WinProc WM Default %i", message ); intf_WarnMsg( 4, "vout: WinProc WM Default %i", message );
break; break;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* gtk_playlist.c : Interface for the playlist dialog * gtk_playlist.c : Interface for the playlist dialog
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: gtk_playlist.c,v 1.26 2002/01/07 02:12:29 sam Exp $ * $Id: gtk_playlist.c,v 1.27 2002/01/17 23:02:45 gbazin Exp $
* *
* Authors: Pierre Baillet <oct@zoy.org> * Authors: Pierre Baillet <oct@zoy.org>
* Stphane Borel <stef@via.ecp.fr> * Stphane Borel <stef@via.ecp.fr>
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include <sys/types.h> /* for readdir and stat stuff */ #include <sys/types.h> /* for readdir and stat stuff */
#ifndef WIN32 #if !defined( _MSC_VER )
# include <dirent.h> # include <dirent.h>
#endif #endif
......
...@@ -162,8 +162,8 @@ static int vout_Create( vout_thread_t *p_vout ) ...@@ -162,8 +162,8 @@ static int vout_Create( vout_thread_t *p_vout )
p_vout->b_fullscreen = p_vout->b_fullscreen =
main_GetIntVariable( VOUT_FULLSCREEN_VAR, VOUT_FULLSCREEN_DEFAULT ); main_GetIntVariable( VOUT_FULLSCREEN_VAR, VOUT_FULLSCREEN_DEFAULT );
p_vout->p_sys->i_mode = p_vout->p_sys->i_mode =
main_GetIntVariable( VOUT_OVERLAY_VAR, VOUT_OVERLAY_DEFAULT ) ? main_GetIntVariable( VOUT_NOOVERLAY_VAR, VOUT_NOOVERLAY_DEFAULT ) ?
MODE_VIDEO_OVERLAY : MODE_NORMAL_MEM; MODE_NORMAL_MEM : MODE_VIDEO_OVERLAY;
p_vout->p_sys->dim.w = p_vout->p_sys->dim.w =
main_GetIntVariable( VOUT_WIDTH_VAR, VOUT_WIDTH_DEFAULT ); main_GetIntVariable( VOUT_WIDTH_VAR, VOUT_WIDTH_DEFAULT );
p_vout->p_sys->dim.h = p_vout->p_sys->dim.h =
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* and spawn threads. * and spawn threads.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: main.c,v 1.144 2002/01/09 10:22:37 sam Exp $ * $Id: main.c,v 1.145 2002/01/17 23:02:45 gbazin Exp $
* *
* Authors: Vincent Seguin <seguin@via.ecp.fr> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
...@@ -103,7 +103,7 @@ ...@@ -103,7 +103,7 @@
#define OPT_HEIGHT 163 #define OPT_HEIGHT 163
#define OPT_COLOR 164 #define OPT_COLOR 164
#define OPT_FULLSCREEN 165 #define OPT_FULLSCREEN 165
#define OPT_OVERLAY 166 #define OPT_NOOVERLAY 166
#define OPT_XVADAPTOR 167 #define OPT_XVADAPTOR 167
#define OPT_SMP 168 #define OPT_SMP 168
#define OPT_FILTER 169 #define OPT_FILTER 169
...@@ -182,7 +182,7 @@ static const struct option longopts[] = ...@@ -182,7 +182,7 @@ static const struct option longopts[] =
{ "idct", 1, 0, OPT_IDCT }, { "idct", 1, 0, OPT_IDCT },
{ "yuv", 1, 0, OPT_YUV }, { "yuv", 1, 0, OPT_YUV },
{ "fullscreen", 0, 0, OPT_FULLSCREEN }, { "fullscreen", 0, 0, OPT_FULLSCREEN },
{ "overlay", 0, 0, OPT_OVERLAY }, { "nooverlay", 0, 0, OPT_NOOVERLAY },
{ "xvadaptor", 1, 0, OPT_XVADAPTOR }, { "xvadaptor", 1, 0, OPT_XVADAPTOR },
{ "smp", 1, 0, OPT_SMP }, { "smp", 1, 0, OPT_SMP },
{ "filter", 1, 0, OPT_FILTER }, { "filter", 1, 0, OPT_FILTER },
...@@ -777,8 +777,8 @@ static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] ) ...@@ -777,8 +777,8 @@ static int GetConfiguration( int *pi_argc, char *ppsz_argv[], char *ppsz_env[] )
case OPT_FULLSCREEN: /* --fullscreen */ case OPT_FULLSCREEN: /* --fullscreen */
main_PutIntVariable( VOUT_FULLSCREEN_VAR, 1 ); main_PutIntVariable( VOUT_FULLSCREEN_VAR, 1 );
break; break;
case OPT_OVERLAY: /* --overlay */ case OPT_NOOVERLAY: /* --nooverlay */
main_PutIntVariable( VOUT_OVERLAY_VAR, 1 ); main_PutIntVariable( VOUT_NOOVERLAY_VAR, 1 );
break; break;
case OPT_XVADAPTOR: /* --xvadaptor */ case OPT_XVADAPTOR: /* --xvadaptor */
main_PutIntVariable( VOUT_XVADAPTOR_VAR, atoi(optarg) ); main_PutIntVariable( VOUT_XVADAPTOR_VAR, atoi(optarg) );
...@@ -966,7 +966,7 @@ static void Usage( int i_fashion ) ...@@ -966,7 +966,7 @@ static void Usage( int i_fashion )
"\n --width <w>, --height <h> \tdisplay dimensions" "\n --width <w>, --height <h> \tdisplay dimensions"
"\n -g, --grayscale \tgrayscale output" "\n -g, --grayscale \tgrayscale output"
"\n --fullscreen \tfullscreen output" "\n --fullscreen \tfullscreen output"
"\n --overlay \taccelerated display" "\n --nooverlay \tdisable accelerated display"
"\n --xvadaptor <adaptor> \tXVideo adaptor" "\n --xvadaptor <adaptor> \tXVideo adaptor"
"\n --color \tcolor output" "\n --color \tcolor output"
"\n --motion <module> \tmotion compensation method" "\n --motion <module> \tmotion compensation method"
...@@ -1041,7 +1041,7 @@ static void Usage( int i_fashion ) ...@@ -1041,7 +1041,7 @@ static void Usage( int i_fashion )
"\n " VOUT_FB_DEV_VAR "=<filename> \tframebuffer device path" "\n " VOUT_FB_DEV_VAR "=<filename> \tframebuffer device path"
"\n " VOUT_GRAYSCALE_VAR "={1|0} \tgrayscale or color output" "\n " VOUT_GRAYSCALE_VAR "={1|0} \tgrayscale or color output"
"\n " VOUT_FULLSCREEN_VAR "={1|0} \tfullscreen" "\n " VOUT_FULLSCREEN_VAR "={1|0} \tfullscreen"
"\n " VOUT_OVERLAY_VAR "={1|0} \toverlay" "\n " VOUT_NOOVERLAY_VAR "={1|0} \tnooverlay"
"\n " VOUT_XVADAPTOR_VAR "=<adaptor> \tXVideo adaptor" "\n " VOUT_XVADAPTOR_VAR "=<adaptor> \tXVideo adaptor"
"\n " MOTION_METHOD_VAR "=<method name> \tmotion compensation method" "\n " MOTION_METHOD_VAR "=<method name> \tmotion compensation method"
"\n " IDCT_METHOD_VAR "=<method name> \tIDCT method" "\n " IDCT_METHOD_VAR "=<method name> \tIDCT method"
...@@ -1445,4 +1445,3 @@ static void ShowConsole( void ) ...@@ -1445,4 +1445,3 @@ static void ShowConsole( void )
#endif #endif
return; return;
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vout_pictures.c : picture management functions * vout_pictures.c : picture management functions
***************************************************************************** *****************************************************************************
* Copyright (C) 2000 VideoLAN * Copyright (C) 2000 VideoLAN
* $Id: vout_pictures.c,v 1.10 2002/01/12 01:25:57 sam Exp $ * $Id: vout_pictures.c,v 1.11 2002/01/17 23:02:45 gbazin Exp $
* *
* Authors: Vincent Seguin <seguin@via.ecp.fr> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
...@@ -394,6 +394,9 @@ picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, ...@@ -394,6 +394,9 @@ picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
void vout_PlacePicture( vout_thread_t *p_vout, int i_width, int i_height, void vout_PlacePicture( vout_thread_t *p_vout, int i_width, int i_height,
int *pi_x, int *pi_y, int *pi_width, int *pi_height ) int *pi_x, int *pi_y, int *pi_width, int *pi_height )
{ {
if( (i_width <= 0) || (i_height <=0) )
return;
if( p_vout->b_scale ) if( p_vout->b_scale )
{ {
*pi_width = i_width; *pi_width = i_width;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment