Commit f6015e93 authored by Gildas Bazin's avatar Gildas Bazin

* src/video_output/video_output.c, include/video_output.h: modified vout_Request() to take into account the
filter chain. If the filter chain has changed, a new vout will be respawned allowing to switch filters on
the fly. This is still a bit hacky but to do it nicely will require implementing inheritance in object
variables.
* modules/video_filter/deinterlace/deinterlace.c: added a "deinterlace-mode" object variable to allow
switching deinterlace modes on the fly.
* modules/gui/gtk/menu.c: updated the deinterlace menu.
* include/vlc_common.h: compilation fixes for gtk_main and gnome_main.
parent c83f667f
......@@ -5,7 +5,7 @@
* thread, and destroy a previously opened video output thread.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: video_output.h,v 1.90 2003/01/28 02:03:32 sam Exp $
* $Id: video_output.h,v 1.91 2003/01/28 12:30:44 gbazin Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr>
......@@ -116,6 +116,7 @@ struct vout_thread_t
/* Filter chain */
char *psz_filter_chain;
vlc_bool_t b_filter_change;
};
#define I_OUTPUTPICTURES p_vout->output.i_pictures
......
......@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vlc_common.h,v 1.50 2003/01/28 03:11:02 sam Exp $
* $Id: vlc_common.h,v 1.51 2003/01/28 12:30:44 gbazin Exp $
*
* Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr>
......@@ -649,7 +649,6 @@ VLC_EXPORT( char *, vlc_dgettext, ( const char *package, const char *msgid ) );
#if defined( ENABLE_NLS ) && \
(defined(MODULE_NAME_IS_gnome)||defined(MODULE_NAME_IS_gtk) \
||defined(MODULE_NAME_IS_gnome_main)||defined(MODULE_NAME_IS_gtk_main) \
||defined(MODULE_NAME_IS_familiar))
/* Declare nothing: gtk.h will do it for us */
#elif defined( ENABLE_NLS ) && defined( HAVE_INCLUDED_GETTEXT )
......
......@@ -2,7 +2,7 @@
* menu.c : functions to handle menu items.
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: menu.c,v 1.6 2003/01/23 15:52:04 sam Exp $
* $Id: menu.c,v 1.7 2003/01/28 12:30:44 gbazin Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Stphane Borel <stef@via.ecp.fr>
......@@ -364,8 +364,6 @@ static void GtkDeinterlaceUpdate( intf_thread_t *p_intf, char *psz_mode )
}
config_PutPsz( p_intf, "filter", psz_filter );
}
config_PutPsz( p_intf, "deinterlace-mode", psz_mode );
}
if( psz_filter )
......@@ -374,7 +372,18 @@ static void GtkDeinterlaceUpdate( intf_thread_t *p_intf, char *psz_mode )
/* now restart all video stream */
if( p_intf->p_sys->p_input )
{
vout_thread_t *p_vout;
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
/* Warn the vout we are about to change the filter chain */
p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
FIND_ANYWHERE );
if( p_vout )
{
p_vout->b_filter_change = VLC_TRUE;
vlc_object_release( p_vout );
}
#define ES p_intf->p_sys->p_input->stream.pp_es[i]
/* create a set of language buttons and append them to the container */
for( i = 0 ; i < p_intf->p_sys->p_input->stream.i_es_number ; i++ )
......@@ -389,6 +398,26 @@ static void GtkDeinterlaceUpdate( intf_thread_t *p_intf, char *psz_mode )
}
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
}
if( strcmp( psz_mode, "None" ) )
{
vout_thread_t *p_vout;
p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
FIND_ANYWHERE );
if( p_vout )
{
vlc_value_t val;
val.psz_string = psz_mode;
if( var_Set( p_vout, "deinterlace-mode", val ) != VLC_SUCCESS )
config_PutPsz( p_intf, "deinterlace-mode", psz_mode );
vlc_object_release( p_vout );
}
else
config_PutPsz( p_intf, "deinterlace-mode", psz_mode );
}
}
static void GtkMenubarDeinterlaceToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
......@@ -1175,10 +1204,23 @@ static gint GtkDeinterlaceMenus( gpointer p_data,
{
if( strstr ( psz_filter, "deinterlace" ) )
{
free( psz_deinterlace_option );
psz_deinterlace_option = config_GetPsz( p_intf, "deinterlace-mode" );
if( !psz_deinterlace_option )
psz_deinterlace_option = strdup( "None" );
vlc_value_t val;
vout_thread_t *p_vout;
p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
FIND_ANYWHERE );
if( p_vout &&
var_Get( p_vout, "deinterlace-mode", &val ) == VLC_SUCCESS )
{
if( val.psz_string && *val.psz_string )
{
free( psz_deinterlace_option );
psz_deinterlace_option = val.psz_string;
}
else if( val.psz_string ) free( val.psz_string );
}
if( p_vout ) vlc_object_release( p_vout );
}
}
if( psz_filter )
......
......@@ -2,7 +2,7 @@
* deinterlace.c : deinterlacer plugin for vlc
*****************************************************************************
* Copyright (C) 2000, 2001, 2002, 2003 VideoLAN
* $Id: deinterlace.c,v 1.6 2003/01/17 16:18:03 sam Exp $
* $Id: deinterlace.c,v 1.7 2003/01/28 12:30:44 gbazin Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -60,6 +60,15 @@ static void Merge ( void *, const void *, const void *, size_t );
static int SendEvents ( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static void SetFilterMethod( vout_thread_t *p_vout, char *psz_method );
static vout_thread_t *SpawnRealVout( vout_thread_t *p_vout );
/*****************************************************************************
* Callback prototypes
*****************************************************************************/
static int FilterCallback ( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
......@@ -93,6 +102,8 @@ struct vout_sys_t
mtime_t next_date;
vout_thread_t *p_vout;
vlc_mutex_t filter_lock;
};
/*****************************************************************************
......@@ -103,7 +114,7 @@ struct vout_sys_t
static int Create( vlc_object_t *p_this )
{
vout_thread_t *p_vout = (vout_thread_t *)p_this;
char *psz_method;
vlc_value_t val;
/* Allocate structure */
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
......@@ -122,55 +133,73 @@ static int Create( vlc_object_t *p_this )
p_vout->p_sys->i_mode = DEINTERLACE_DISCARD;
p_vout->p_sys->b_double_rate = 0;
p_vout->p_sys->last_date = 0;
vlc_mutex_init( p_vout, &p_vout->p_sys->filter_lock );
/* Look what method was requested */
psz_method = config_GetPsz( p_vout, "deinterlace-mode" );
val.psz_string = config_GetPsz( p_vout, "deinterlace-mode" );
if( psz_method == NULL )
var_Create( p_vout, "deinterlace-mode", VLC_VAR_STRING );
if( val.psz_string == NULL )
{
msg_Err( p_vout, "configuration variable %s empty",
"deinterlace-mode" );
msg_Err( p_vout, "no deinterlace mode provided, using \"discard\"" );
}
else
{
if( !strcmp( psz_method, "discard" ) )
{
p_vout->p_sys->i_mode = DEINTERLACE_DISCARD;
}
else if( !strcmp( psz_method, "mean" ) )
{
p_vout->p_sys->i_mode = DEINTERLACE_MEAN;
}
else if( !strcmp( psz_method, "blend" )
|| !strcmp( psz_method, "average" )
|| !strcmp( psz_method, "combine-fields" ) )
{
p_vout->p_sys->i_mode = DEINTERLACE_BLEND;
}
else if( !strcmp( psz_method, "bob" )
|| !strcmp( psz_method, "progressive-scan" ) )
{
p_vout->p_sys->i_mode = DEINTERLACE_BOB;
p_vout->p_sys->b_double_rate = 1;
}
else if( !strcmp( psz_method, "linear" ) )
{
p_vout->p_sys->i_mode = DEINTERLACE_LINEAR;
p_vout->p_sys->b_double_rate = 1;
}
else
{
msg_Err( p_vout, "no valid deinterlace mode provided, "
"using \"discard\"" );
}
free( psz_method );
val.psz_string = strdup( "discard" );
}
var_Set( p_vout, "deinterlace-mode", val );
SetFilterMethod( p_vout, val.psz_string );
free( val.psz_string );
var_AddCallback( p_vout, "deinterlace-mode", FilterCallback, NULL );
return VLC_SUCCESS;
}
/*****************************************************************************
* SetFilterMethod: setup the deinterlace method to use.
*****************************************************************************/
static void SetFilterMethod( vout_thread_t *p_vout, char *psz_method )
{
if( !strcmp( psz_method, "discard" ) )
{
p_vout->p_sys->i_mode = DEINTERLACE_DISCARD;
p_vout->p_sys->b_double_rate = 0;
}
else if( !strcmp( psz_method, "mean" ) )
{
p_vout->p_sys->i_mode = DEINTERLACE_MEAN;
p_vout->p_sys->b_double_rate = 0;
}
else if( !strcmp( psz_method, "blend" )
|| !strcmp( psz_method, "average" )
|| !strcmp( psz_method, "combine-fields" ) )
{
p_vout->p_sys->i_mode = DEINTERLACE_BLEND;
p_vout->p_sys->b_double_rate = 0;
}
else if( !strcmp( psz_method, "bob" )
|| !strcmp( psz_method, "progressive-scan" ) )
{
p_vout->p_sys->i_mode = DEINTERLACE_BOB;
p_vout->p_sys->b_double_rate = 1;
}
else if( !strcmp( psz_method, "linear" ) )
{
p_vout->p_sys->i_mode = DEINTERLACE_LINEAR;
p_vout->p_sys->b_double_rate = 1;
}
else
{
msg_Err( p_vout, "no valid deinterlace mode provided, "
"using \"discard\"" );
}
}
/*****************************************************************************
* Init: initialize Deinterlace video thread output method
*****************************************************************************/
......@@ -200,7 +229,31 @@ static int Init( vout_thread_t *p_vout )
break;
}
/* Try to open the real video output, with half the height our images */
/* Try to open the real video output */
p_vout->p_sys->p_vout = SpawnRealVout( p_vout );
if( p_vout->p_sys->p_vout == NULL )
{
/* Everything failed */
msg_Err( p_vout, "cannot open vout, aborting" );
return VLC_EGENERIC;
}
ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
return VLC_SUCCESS;
}
/*****************************************************************************
* SpawnRealVout: spawn the real video output.
*****************************************************************************/
static vout_thread_t *SpawnRealVout( vout_thread_t *p_vout )
{
vout_thread_t *p_real_vout = NULL;
msg_Dbg( p_vout, "spawning the real video output" );
switch( p_vout->render.i_chroma )
......@@ -212,7 +265,7 @@ static int Init( vout_thread_t *p_vout )
{
case DEINTERLACE_MEAN:
case DEINTERLACE_DISCARD:
p_vout->p_sys->p_vout =
p_real_vout =
vout_Create( p_vout,
p_vout->output.i_width, p_vout->output.i_height / 2,
p_vout->output.i_chroma, p_vout->output.i_aspect );
......@@ -221,7 +274,7 @@ static int Init( vout_thread_t *p_vout )
case DEINTERLACE_BOB:
case DEINTERLACE_BLEND:
case DEINTERLACE_LINEAR:
p_vout->p_sys->p_vout =
p_real_vout =
vout_Create( p_vout,
p_vout->output.i_width, p_vout->output.i_height,
p_vout->output.i_chroma, p_vout->output.i_aspect );
......@@ -230,7 +283,7 @@ static int Init( vout_thread_t *p_vout )
break;
case VLC_FOURCC('I','4','2','2'):
p_vout->p_sys->p_vout =
p_real_vout =
vout_Create( p_vout,
p_vout->output.i_width, p_vout->output.i_height,
VLC_FOURCC('I','4','2','0'), p_vout->output.i_aspect );
......@@ -240,19 +293,7 @@ static int Init( vout_thread_t *p_vout )
break;
}
/* Everything failed */
if( p_vout->p_sys->p_vout == NULL )
{
msg_Err( p_vout, "cannot open vout, aborting" );
return VLC_EGENERIC;
}
ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
return VLC_SUCCESS;
return p_real_vout;
}
/*****************************************************************************
......@@ -281,6 +322,7 @@ static void Destroy( vlc_object_t *p_this )
DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
vlc_object_detach( p_vout->p_sys->p_vout );
vout_Destroy( p_vout->p_sys->p_vout );
free( p_vout->p_sys );
......@@ -297,6 +339,8 @@ static void Render ( vout_thread_t *p_vout, picture_t *p_pic )
{
picture_t *pp_outpic[2];
vlc_mutex_lock( &p_vout->p_sys->filter_lock );
/* Get a new picture */
while( ( pp_outpic[0] = vout_CreatePicture( p_vout->p_sys->p_vout,
0, 0, 0 ) )
......@@ -304,10 +348,11 @@ static void Render ( vout_thread_t *p_vout, picture_t *p_pic )
{
if( p_vout->b_die || p_vout->b_error )
{
vlc_mutex_unlock( &p_vout->p_sys->filter_lock );
return;
}
msleep( VOUT_OUTMEM_SLEEP );
}
}
vout_DatePicture( p_vout->p_sys->p_vout, pp_outpic[0], p_pic->date );
......@@ -321,9 +366,10 @@ static void Render ( vout_thread_t *p_vout, picture_t *p_pic )
if( p_vout->b_die || p_vout->b_error )
{
vout_DestroyPicture( p_vout->p_sys->p_vout, pp_outpic[0] );
vlc_mutex_unlock( &p_vout->p_sys->filter_lock );
return;
}
msleep( VOUT_OUTMEM_SLEEP );
msleep( VOUT_OUTMEM_SLEEP );
}
/* 20ms is a bit arbitrary, but it's only for the first image we get */
......@@ -371,6 +417,8 @@ static void Render ( vout_thread_t *p_vout, picture_t *p_pic )
vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] );
break;
}
vlc_mutex_unlock( &p_vout->p_sys->filter_lock );
}
/*****************************************************************************
......@@ -668,3 +716,82 @@ static int SendEvents( vlc_object_t *p_this, char const *psz_var,
return VLC_SUCCESS;
}
/*****************************************************************************
* FilterCallback: called when changing the deinterlace method on the fly.
*****************************************************************************/
static int FilterCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval,
void *p_data )
{
vout_thread_t * p_vout = (vout_thread_t *)p_this;
int i_old_mode = p_vout->p_sys->i_mode;
vlc_mutex_lock( &p_vout->p_sys->filter_lock );
msg_Err( p_vout, "filter method: %s", newval.psz_string );
SetFilterMethod( p_vout, newval.psz_string );
switch( p_vout->render.i_chroma )
{
case VLC_FOURCC('I','4','2','2'):
vlc_mutex_unlock( &p_vout->p_sys->filter_lock );
return VLC_SUCCESS;
break;
case VLC_FOURCC('I','4','2','0'):
case VLC_FOURCC('I','Y','U','V'):
case VLC_FOURCC('Y','V','1','2'):
switch( p_vout->p_sys->i_mode )
{
case DEINTERLACE_MEAN:
case DEINTERLACE_DISCARD:
if( ( i_old_mode == DEINTERLACE_MEAN )
|| ( i_old_mode == DEINTERLACE_DISCARD ) )
{
vlc_mutex_unlock( &p_vout->p_sys->filter_lock );
return VLC_SUCCESS;
}
break;
case DEINTERLACE_BOB:
case DEINTERLACE_BLEND:
case DEINTERLACE_LINEAR:
if( ( i_old_mode == DEINTERLACE_BOB )
|| ( i_old_mode == DEINTERLACE_BLEND )
|| ( i_old_mode == DEINTERLACE_LINEAR ) )
{
vlc_mutex_unlock( &p_vout->p_sys->filter_lock );
return VLC_SUCCESS;
}
break;
}
break;
default:
break;
}
/* We need to kill the old vout */
DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
vlc_object_detach( p_vout->p_sys->p_vout );
vout_Destroy( p_vout->p_sys->p_vout );
/* Try to open a new video output */
p_vout->p_sys->p_vout = SpawnRealVout( p_vout );
if( p_vout->p_sys->p_vout == NULL )
{
/* Everything failed */
msg_Err( p_vout, "cannot open vout, aborting" );
vlc_mutex_unlock( &p_vout->p_sys->filter_lock );
return VLC_EGENERIC;
}
ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
vlc_mutex_unlock( &p_vout->p_sys->filter_lock );
return VLC_SUCCESS;
}
......@@ -5,7 +5,7 @@
* thread, and destroy a previously oppened video output thread.
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
* $Id: video_output.c,v 1.207 2003/01/22 10:44:50 fenrir Exp $
* $Id: video_output.c,v 1.208 2003/01/28 12:30:44 gbazin Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
......@@ -81,7 +81,7 @@ vout_thread_t * __vout_Request ( vlc_object_t *p_this, vout_thread_t *p_vout,
else
{
vlc_object_detach( p_vout );
// vlc_object_release( p_vout );
vlc_object_release( p_vout );
vout_Destroy( p_vout );
}
if( psz_sout ) free( psz_sout );
......@@ -108,10 +108,39 @@ vout_thread_t * __vout_Request ( vlc_object_t *p_this, vout_thread_t *p_vout,
/* If we now have a video output, check it has the right properties */
if( p_vout )
{
char *psz_filter_chain;
/* We don't directly check for the "filter" variable for obvious
* performance reasons. */
if( p_vout->b_filter_change )
{
psz_filter_chain = config_GetPsz( p_this, "filter" );
if( psz_filter_chain && !*psz_filter_chain )
{
free( psz_filter_chain );
psz_filter_chain = NULL;
}
if( p_vout->psz_filter_chain && !*p_vout->psz_filter_chain )
{
free( p_vout->psz_filter_chain );
p_vout->psz_filter_chain = NULL;
}
if( ( !psz_filter_chain && !p_vout->psz_filter_chain ) ||
( psz_filter_chain && p_vout->psz_filter_chain &&
!strcmp( psz_filter_chain, p_vout->psz_filter_chain ) ) )
{
p_vout->b_filter_change = VLC_FALSE;
}
}
if( ( p_vout->render.i_width != i_width ) ||
( p_vout->render.i_height != i_height ) ||
( p_vout->render.i_chroma != i_chroma ) ||
( p_vout->render.i_aspect != i_aspect ) )
( p_vout->render.i_aspect != i_aspect ) ||
p_vout->b_filter_change )
{
/* We are not interested in this format, close this vout */
vlc_object_detach( p_vout );
......@@ -126,6 +155,8 @@ vout_thread_t * __vout_Request ( vlc_object_t *p_this, vout_thread_t *p_vout,
vlc_object_attach( p_vout, p_this );
vlc_object_release( p_vout );
}
if( psz_filter_chain ) free( psz_filter_chain );
}
if( !p_vout )
......@@ -218,7 +249,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent,
}
/* Choose the video output module */
if( !p_vout->psz_filter_chain )
if( !p_vout->psz_filter_chain || !*p_vout->psz_filter_chain )
{
psz_plugin = config_GetPsz( p_parent, "vout" );
}
......@@ -287,6 +318,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent,
p_vout->b_fullscreen = 0;
p_vout->render_time = 10;
p_vout->c_fps_samples= 0;
p_vout->b_filter_change = 0;
/* Mouse coordinates */
var_Create( p_vout, "mouse-x", VLC_VAR_INTEGER );
......@@ -307,7 +339,8 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent,
p_vout->p_module = module_Need( p_vout,
( p_vout->psz_filter_chain ) ?
( p_vout->psz_filter_chain &&
*p_vout->psz_filter_chain ) ?
"video filter" : "video output",
psz_plugin );
......
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