* 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>
* Stéphane Borel <stef@via.ecp.fr>
}
config_PutPsz( p_intf, "filter", psz_filter );
}
-
- config_PutPsz( p_intf, "deinterlace-mode", psz_mode );
}
if( psz_filter )
/* 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++ )
}
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 )
{
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 )
* 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>
*
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
*****************************************************************************/
mtime_t next_date;
vout_thread_t *p_vout;
+
+ vlc_mutex_t filter_lock;
};
/*****************************************************************************
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 ) );
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
*****************************************************************************/
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 )
{
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 );
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 );
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 );
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;
}
/*****************************************************************************
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 );
{
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 ) )
{
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 );
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 */
vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] );
break;
}
+
+ vlc_mutex_unlock( &p_vout->p_sys->filter_lock );
}
/*****************************************************************************
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;
+}
* 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>
*
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 );
/* 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 );
vlc_object_attach( p_vout, p_this );
vlc_object_release( p_vout );
}
+
+ if( psz_filter_chain ) free( psz_filter_chain );
}
if( !p_vout )
}
/* 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" );
}
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 );
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 );