/*****************************************************************************
* input.c: input thread
*****************************************************************************
- * Copyright (C) 1998-2004 the VideoLAN team
+ * Copyright (C) 1998-2007 the VideoLAN team
* $Id$
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Local prototypes
*****************************************************************************/
static int Run ( input_thread_t *p_input );
-static int RunAndClean ( input_thread_t *p_input );
+static int RunAndDestroy ( input_thread_t *p_input );
static input_thread_t * Create ( vlc_object_t *, input_item_t *,
- const char *, vlc_bool_t );
+ const char *, vlc_bool_t, sout_instance_t * );
static int Init ( input_thread_t *p_input );
static void Error ( input_thread_t *p_input );
static void End ( input_thread_t *p_input );
static void MainLoop( input_thread_t *p_input );
+static void Destroy( input_thread_t *p_input, sout_instance_t **pp_sout );
static inline int ControlPopNoLock( input_thread_t *, int *, vlc_value_t * );
static void ControlReduce( input_thread_t * );
static input_source_t *InputSourceNew( input_thread_t *);
static int InputSourceInit( input_thread_t *, input_source_t *,
const char *, const char *psz_forced_demux );
-static void InputSourceClean( input_thread_t *, input_source_t * );
+static void InputSourceClean( input_source_t * );
static void SlaveDemux( input_thread_t *p_input );
static void SlaveSeek( input_thread_t *p_input );
static void InputMetaUser( input_thread_t *p_input );
+static sout_instance_t *SoutFind( vlc_object_t *p_parent, input_item_t *p_item, vlc_bool_t * );
+static void SoutKeep( sout_instance_t * );
+
/*****************************************************************************
* This function creates a new input, and returns a pointer
* to its description. On error, it returns NULL.
* TODO complete this list (?)
*****************************************************************************/
static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
- const char *psz_header, vlc_bool_t b_quick )
+ const char *psz_header, vlc_bool_t b_quick, sout_instance_t *p_sout )
{
input_thread_t *p_input = NULL; /* thread descriptor */
vlc_value_t val;
p_input->p->p_meta = NULL;
p_input->p->p_es_out = NULL;
p_input->p->p_sout = NULL;
+ p_input->p->b_sout_keep = VLC_FALSE;
p_input->p->b_out_pace_control = VLC_FALSE;
p_input->i_pts_delay = 0;
/* Parse input options */
vlc_mutex_lock( &p_item->lock );
for( i = 0; i < p_item->i_options; i++ )
- {
var_OptionParse( p_input, p_item->ppsz_options[i] );
- }
vlc_mutex_unlock( &p_item->lock );
/* Create Object Variables for private use only */
input_ConfigVarInit( p_input );
/* Create Objects variables for public Get and Set */
- if( !p_input->b_preparsing )
- input_ControlVarInit( p_input );
+ input_ControlVarInit( p_input );
p_input->p->input.i_cr_average = var_GetInteger( p_input, "cr-average" );
}
/* Remove 'Now playing' info as it is probably outdated */
- input_Control( p_input, INPUT_DEL_INFO, _(VLC_META_INFO_CAT),
- VLC_META_NOW_PLAYING ); /* ? Don't translate as it might has been copied ? */
+ input_Control( p_input, INPUT_DEL_INFO, _(VLC_META_INFO_CAT), VLC_META_NOW_PLAYING );
+ vlc_meta_SetNowPlaying( p_item->p_meta, NULL );
+
+ /* */
+ if( p_input->b_preparsing )
+ p_input->i_flags |= OBJECT_FLAGS_QUIET | OBJECT_FLAGS_NOINTERACT;
+
+ /* */
+ if( p_sout )
+ p_input->p->p_sout = p_sout;
+
+ /* Attach only once we are ready */
+ vlc_object_attach( p_input, p_parent );
return p_input;
}
+static void Destroy( input_thread_t *p_input, sout_instance_t **pp_sout )
+{
+ vlc_object_detach( p_input );
+
+ if( pp_sout )
+ *pp_sout = NULL;
+ if( p_input->p->p_sout )
+ {
+ if( pp_sout )
+ *pp_sout = p_input->p->p_sout;
+ else if( p_input->p->b_sout_keep )
+ SoutKeep( p_input->p->p_sout );
+ else
+ sout_DeleteInstance( p_input->p->p_sout );
+ }
+
+ vlc_mutex_destroy( &p_input->p->lock_control );
+ free( p_input->p );
+
+ vlc_object_destroy( p_input );
+}
+
/**
* Initialize an input thread and run it. You will need to monitor the
* thread to clean up after it is done
input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
input_item_t *p_item )
{
- return __input_CreateThread2( p_parent, p_item, NULL );
+ vlc_bool_t b_sout_keep;
+ sout_instance_t *p_sout = SoutFind( p_parent, p_item, &b_sout_keep );
+ input_thread_t *p_input = __input_CreateThreadExtended( p_parent, p_item, NULL, p_sout );
+
+ if( !p_input && p_sout )
+ SoutKeep( p_sout );
+
+ p_input->p->b_sout_keep = b_sout_keep;
+ return p_input;
}
-/* Gruik ! */
-input_thread_t *__input_CreateThread2( vlc_object_t *p_parent,
- input_item_t *p_item,
- const char *psz_header )
+/* */
+input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent,
+ input_item_t *p_item,
+ const char *psz_log, sout_instance_t *p_sout )
{
- input_thread_t *p_input = NULL; /* thread descriptor */
+ input_thread_t *p_input;
- p_input = Create( p_parent, p_item, psz_header, VLC_FALSE );
+ p_input = Create( p_parent, p_item, psz_log, VLC_FALSE, p_sout );
if( !p_input )
return NULL;
- /* Now we can attach our new input */
- vlc_object_attach( p_input, p_parent );
-
/* Create thread and wait for its readiness. */
if( vlc_thread_create( p_input, "input", Run,
- VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
+ VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
{
input_ChangeState( p_input, ERROR_S );
msg_Err( p_input, "cannot create input thread" );
- vlc_object_detach( p_input );
- free( p_input->p );
- vlc_object_destroy( p_input );
+ Destroy( p_input, &p_sout );
return NULL;
}
int __input_Read( vlc_object_t *p_parent, input_item_t *p_item,
vlc_bool_t b_block )
{
- input_thread_t *p_input = NULL; /* thread descriptor */
+ vlc_bool_t b_sout_keep;
+ sout_instance_t *p_sout = SoutFind( p_parent, p_item, &b_sout_keep );
+ input_thread_t *p_input;
- p_input = Create( p_parent, p_item, NULL, VLC_FALSE );
- if( !p_input )
+ p_input = Create( p_parent, p_item, NULL, VLC_FALSE, p_sout );
+ if( !p_input && p_sout )
+ {
+ SoutKeep( p_sout );
return VLC_EGENERIC;
-
- /* Now we can attach our new input */
- vlc_object_attach( p_input, p_parent );
+ }
+ p_input->p->b_sout_keep = b_sout_keep;
if( b_block )
{
- RunAndClean( p_input );
+ RunAndDestroy( p_input );
return VLC_SUCCESS;
}
else
{
- if( vlc_thread_create( p_input, "input", RunAndClean,
+ if( vlc_thread_create( p_input, "input", RunAndDestroy,
VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
{
input_ChangeState( p_input, ERROR_S );
msg_Err( p_input, "cannot create input thread" );
- vlc_object_detach( p_input );
- free( p_input->p );
- vlc_object_destroy( p_input );
+ Destroy( p_input, NULL );
return VLC_EGENERIC;
}
}
*/
int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item )
{
- input_thread_t *p_input = NULL; /* thread descriptor */
+ input_thread_t *p_input;
/* Allocate descriptor */
- p_input = Create( p_parent, p_item, NULL, VLC_TRUE );
+ p_input = Create( p_parent, p_item, NULL, VLC_TRUE, NULL );
if( !p_input )
return VLC_EGENERIC;
- p_input->i_flags |= OBJECT_FLAGS_QUIET;
- p_input->i_flags |= OBJECT_FLAGS_NOINTERACT;
-
- /* Now we can attach our new input */
- vlc_object_attach( p_input, p_parent );
-
- Init( p_input );
-
- /* Clean up master */
- InputSourceClean( p_input, &p_input->p->input );
-
- /* Unload all modules */
- if( p_input->p->p_es_out ) input_EsOutDelete( p_input->p->p_es_out );
+ if( !Init( p_input ) )
+ End( p_input );
- vlc_object_detach( p_input );
- free( p_input->p );
- vlc_object_destroy( p_input );
+ Destroy( p_input, NULL );
return VLC_SUCCESS;
}
int i;
/* Set die for input */
- p_input->b_die = VLC_TRUE;
+ vlc_object_kill( p_input );
+ /* FIXME: seems to be duplicated in ControlPush(INPUT_CONTROL_SET_DIE) */
/* We cannot touch p_input fields directly (we come from another thread),
* so use the vlc_object_find way, it's perfectly safe */
p_list = vlc_list_find( p_input, VLC_OBJECT_ACCESS, FIND_CHILD );
for( i = 0; i < p_list->i_count; i++ )
{
- p_list->p_values[i].p_object->b_die = VLC_TRUE;
+ vlc_object_kill( p_list->p_values[i].p_object );
}
vlc_list_release( p_list );
p_list = vlc_list_find( p_input, VLC_OBJECT_STREAM, FIND_CHILD );
for( i = 0; i < p_list->i_count; i++ )
{
- p_list->p_values[i].p_object->b_die = VLC_TRUE;
+ vlc_object_kill( p_list->p_values[i].p_object );
}
vlc_list_release( p_list );
p_list = vlc_list_find( p_input, VLC_OBJECT_DEMUX, FIND_CHILD );
for( i = 0; i < p_list->i_count; i++ )
{
- p_list->p_values[i].p_object->b_die = VLC_TRUE;
+ vlc_object_kill( p_list->p_values[i].p_object );
}
vlc_list_release( p_list );
* \param the input thread to kill
*/
void input_DestroyThread( input_thread_t *p_input )
+{
+ input_DestroyThreadExtended( p_input, NULL );
+}
+
+void input_DestroyThreadExtended( input_thread_t *p_input, sout_instance_t **pp_sout )
{
/* Join the thread */
vlc_thread_join( p_input );
- /* Delete input lock (only after thread joined) */
- vlc_mutex_destroy( &p_input->p->lock_control );
-
- /* TODO: maybe input_DestroyThread should also delete p_input instead
- * of the playlist but I'm not sure if it's possible */
+ /* */
+ Destroy( p_input, pp_sout );
}
/*****************************************************************************
}
/*****************************************************************************
- * RunAndClean: main thread loop
+ * RunAndDestroy: main thread loop
* This is the "just forget me" thread that spawns the input processing chain,
* reads the stream, cleans up and releases memory
*****************************************************************************/
-static int RunAndClean( input_thread_t *p_input )
+static int RunAndDestroy( input_thread_t *p_input )
{
/* Signal that the thread is launched */
vlc_thread_ready( p_input );
if( Init( p_input ) )
- {
- /* If we failed, just exit */
- return 0;
- }
+ goto exit;
MainLoop( p_input );
/* Clean up */
End( p_input );
+exit:
/* Release memory */
- vlc_object_detach( p_input );
- free( p_input->p );
- vlc_object_destroy( p_input );
-
+ Destroy( p_input, NULL );
return 0;
}
{
int64_t i_intf_update = 0;
int i_updates = 0;
+
while( !p_input->b_die && !p_input->b_error && !p_input->p->input.b_eof )
{
vlc_bool_t b_force_update = VLC_FALSE;
p_input->p->counters.p_input_bitrate->update_interval = 1000000;
}
- /* handle sout */
+ /* Find a usable sout and attach it to p_input */
psz = var_GetString( p_input, "sout" );
if( *psz && strncasecmp( p_input->p->input.p_item->psz_uri, "vlc:", 4 ) )
{
- p_input->p->p_sout = sout_NewInstance( p_input, psz );
- if( p_input->p->p_sout == NULL )
+ /* Check the validity of the provided sout */
+ if( p_input->p->p_sout )
{
- input_ChangeState( p_input, ERROR_S );
- msg_Err( p_input, "cannot start stream output instance, " \
- "aborting" );
- free( psz );
- return VLC_EGENERIC;
+ if( strcmp( p_input->p->p_sout->psz_sout, psz ) )
+ {
+ msg_Dbg( p_input, "destroying unusable sout" );
+
+ sout_DeleteInstance( p_input->p->p_sout );
+ p_input->p->p_sout = NULL;
+ }
}
+
+ if( p_input->p->p_sout )
+ {
+ /* Reuse it */
+ msg_Dbg( p_input, "sout keep: reusing sout" );
+ msg_Dbg( p_input, "sout keep: you probably want to use "
+ "gather stream_out" );
+ vlc_object_attach( p_input->p->p_sout, p_input );
+ }
+ else
+ {
+ /* Create a new one */
+ p_input->p->p_sout = sout_NewInstance( p_input, psz );
+
+ if( !p_input->p->p_sout )
+ {
+ input_ChangeState( p_input, ERROR_S );
+ msg_Err( p_input, "cannot start stream output instance, " \
+ "aborting" );
+ free( psz );
+ return VLC_EGENERIC;
+ }
+ }
+
if( p_input->p_libvlc->b_stats )
{
INIT_COUNTER( sout_sent_packets, INTEGER, COUNTER );
1000000;
}
}
+ else if( p_input->p->p_sout )
+ {
+ msg_Dbg( p_input, "destroying useless sout" );
+
+ sout_DeleteInstance( p_input->p->p_sout );
+ p_input->p->p_sout = NULL;
+ }
free( psz );
}
input_EsOutDelete( p_input->p->p_es_out );
if( p_input->p->p_sout )
+ {
+ vlc_object_detach( p_input->p->p_sout );
sout_DeleteInstance( p_input->p->p_sout );
+ }
+
+
+ if( !p_input->b_preparsing && p_input->p_libvlc->b_stats )
+ {
+#define EXIT_COUNTER( c ) do { if( p_input->p->counters.p_##c ) \
+ stats_CounterClean( p_input->p->counters.p_##c );\
+ p_input->p->counters.p_##c = NULL; } while(0)
+ EXIT_COUNTER( read_bytes );
+ EXIT_COUNTER( read_packets );
+ EXIT_COUNTER( demux_read );
+ EXIT_COUNTER( input_bitrate );
+ EXIT_COUNTER( demux_bitrate );
+ EXIT_COUNTER( played_abuffers );
+ EXIT_COUNTER( lost_abuffers );
+ EXIT_COUNTER( displayed_pictures );
+ EXIT_COUNTER( lost_pictures );
+ EXIT_COUNTER( decoded_audio );
+ EXIT_COUNTER( decoded_video );
+ EXIT_COUNTER( decoded_sub );
+
+ if( p_input->p->p_sout )
+ {
+ EXIT_COUNTER( sout_sent_packets );
+ EXIT_COUNTER (sout_sent_bytes );
+ EXIT_COUNTER( sout_send_bitrate );
+ }
+#undef EXIT_COUNTER
+ }
/* Mark them deleted */
p_input->p->input.p_demux = NULL;
{
int i;
- msg_Dbg( p_input, "closing input" );
-
/* We are at the end */
input_ChangeState( p_input, END_S );
/* Clean control variables */
- if( !p_input->b_preparsing )
- input_ControlVarClean( p_input );
+ input_ControlVarClean( p_input );
/* Clean up master */
- InputSourceClean( p_input, &p_input->p->input );
+ InputSourceClean( &p_input->p->input );
/* Delete slave */
for( i = 0; i < p_input->p->i_slave; i++ )
{
- InputSourceClean( p_input, p_input->p->slave[i] );
+ InputSourceClean( p_input->p->slave[i] );
free( p_input->p->slave[i] );
}
if( p_input->p->slave ) free( p_input->p->slave );
if( p_input->p->p_es_out )
input_EsOutDelete( p_input->p->p_es_out );
-#define CL_CO( c ) stats_CounterClean( p_input->p->counters.p_##c ); p_input->p->counters.p_##c = NULL;
- if( p_input->p_libvlc->b_stats )
- {
- /* make sure we are up to date */
- stats_ComputeInputStats( p_input, p_input->p->input.p_item->p_stats );
- if( p_input->p_libvlc->p_playlist->p_stats_computer == p_input )
- {
- stats_ComputeGlobalStats( p_input->p_libvlc->p_playlist,
- p_input->p_libvlc->p_playlist->p_stats );
- p_input->p_libvlc->p_playlist->p_stats_computer = NULL;
- }
- CL_CO( read_bytes );
- CL_CO( read_packets );
- CL_CO( demux_read );
- CL_CO( input_bitrate );
- CL_CO( demux_bitrate );
- CL_CO( played_abuffers );
- CL_CO( lost_abuffers );
- CL_CO( displayed_pictures );
- CL_CO( lost_pictures );
- CL_CO( decoded_audio) ;
- CL_CO( decoded_video );
- CL_CO( decoded_sub) ;
- }
-
- /* Close optional stream output instance */
- if( p_input->p->p_sout )
+ if( !p_input->b_preparsing )
{
- vlc_value_t keep;
-
- CL_CO( sout_sent_packets );
- CL_CO( sout_sent_bytes );
- CL_CO( sout_send_bitrate );
-
- if( var_Get( p_input, "sout-keep", &keep ) >= 0 && keep.b_bool )
+#define CL_CO( c ) stats_CounterClean( p_input->p->counters.p_##c ); p_input->p->counters.p_##c = NULL;
+ if( p_input->p_libvlc->b_stats )
{
- /* attach sout to the playlist */
- msg_Dbg( p_input, "keeping sout" );
- vlc_object_detach( p_input->p->p_sout );
- vlc_object_attach( p_input->p->p_sout, p_input->p_libvlc->p_playlist );
+ /* make sure we are up to date */
+ stats_ComputeInputStats( p_input, p_input->p->input.p_item->p_stats );
+ if( p_input->p_libvlc->p_playlist->p_stats_computer == p_input )
+ {
+ stats_ComputeGlobalStats( p_input->p_libvlc->p_playlist,
+ p_input->p_libvlc->p_playlist->p_stats );
+ p_input->p_libvlc->p_playlist->p_stats_computer = NULL;
+ }
+ CL_CO( read_bytes );
+ CL_CO( read_packets );
+ CL_CO( demux_read );
+ CL_CO( input_bitrate );
+ CL_CO( demux_bitrate );
+ CL_CO( played_abuffers );
+ CL_CO( lost_abuffers );
+ CL_CO( displayed_pictures );
+ CL_CO( lost_pictures );
+ CL_CO( decoded_audio) ;
+ CL_CO( decoded_video );
+ CL_CO( decoded_sub) ;
}
- else
+
+ /* Close optional stream output instance */
+ if( p_input->p->p_sout )
{
- msg_Dbg( p_input, "destroying sout" );
- sout_DeleteInstance( p_input->p->p_sout );
+ CL_CO( sout_sent_packets );
+ CL_CO( sout_sent_bytes );
+ CL_CO( sout_send_bitrate );
+
+ vlc_object_detach( p_input->p->p_sout );
}
- }
#undef CL_CO
+ }
vlc_mutex_destroy( &p_input->p->counters.counters_lock );
p_input->b_dead = VLC_TRUE;
}
+static sout_instance_t *SoutFind( vlc_object_t *p_parent, input_item_t *p_item, vlc_bool_t *pb_sout_keep )
+{
+ vlc_bool_t b_keep_sout = var_CreateGetBool( p_parent, "sout-keep" );
+ sout_instance_t *p_sout = NULL;
+ int i;
+
+ /* Search sout-keep options
+ * XXX it has to be done here, but it is duplicated work :( */
+ vlc_mutex_lock( &p_item->lock );
+ for( i = 0; i < p_item->i_options; i++ )
+ {
+ const char *psz_option = p_item->ppsz_options[i];
+ if( !psz_option )
+ continue;
+ if( *psz_option == ':' )
+ psz_option++;
+
+ if( !strcmp( psz_option, "sout-keep" ) )
+ b_keep_sout = VLC_TRUE;
+ else if( !strcmp( psz_option, "no-sout-keep" ) || !strcmp( psz_option, "nosout-keep" ) )
+ b_keep_sout = VLC_FALSE;
+ }
+ vlc_mutex_unlock( &p_item->lock );
+
+ /* Find a potential sout to reuse
+ * XXX it might be unusable but this will be checked later */
+ if( b_keep_sout )
+ {
+ /* Remove the sout from the playlist garbage collector */
+ playlist_t *p_playlist = pl_Yield( p_parent );
+
+ vlc_mutex_lock( &p_playlist->gc_lock );
+ p_sout = vlc_object_find( p_playlist, VLC_OBJECT_SOUT, FIND_CHILD );
+ if( p_sout )
+ {
+ if( p_sout->p_parent != VLC_OBJECT(p_playlist) )
+ {
+ vlc_object_release( p_sout );
+ p_sout = NULL;
+ }
+ else
+ {
+ vlc_object_detach( p_sout ); /* Remove it from the GC */
+
+ vlc_object_release( p_sout );
+ }
+ }
+ vlc_mutex_unlock( &p_playlist->gc_lock );
+
+ pl_Release( p_parent );
+ }
+
+ if( pb_sout_keep )
+ *pb_sout_keep = b_keep_sout;
+
+ return p_sout;
+}
+static void SoutKeep( sout_instance_t *p_sout )
+{
+ /* attach sout to the playlist */
+ playlist_t *p_playlist = pl_Yield( p_sout );
+
+ msg_Dbg( p_sout, "sout has been kept" );
+ vlc_object_attach( p_sout, p_playlist );
+
+ pl_Release( p_sout );
+}
+
/*****************************************************************************
* Control
*****************************************************************************/
msg_Dbg( p_input, "control: stopping input" );
/* Mark all submodules to die */
if( p_input->p->input.p_access )
- p_input->p->input.p_access->b_die = VLC_TRUE;
+ vlc_object_kill( p_input->p->input.p_access );
if( p_input->p->input.p_stream )
- p_input->p->input.p_stream->b_die = VLC_TRUE;
- p_input->p->input.p_demux->b_die = VLC_TRUE;
+ vlc_object_kill( p_input->p->input.p_stream );
+ vlc_object_kill( p_input->p->input.p_demux );
- p_input->b_die = VLC_TRUE;
+ vlc_object_kill( p_input );
break;
case INPUT_CONTROL_SET_POSITION:
/* Reset clock */
es_out_Control( p_input->p->p_es_out, ES_OUT_RESET_PCR );
- input_EsOutDiscontinuity( p_input->p->p_es_out, VLC_FALSE );
}
else if( val.i_int == PAUSE_S && p_input->i_state == PLAYING_S &&
p_input->p->b_can_pause )
/* Switch to new state */
p_input->i_state = val.i_int;
var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
+
+ /* Send discontinuity to decoders (it will allow them to flush
+ * if implemented */
+ input_EsOutDiscontinuity( p_input->p->p_es_out, VLC_FALSE );
}
else if( val.i_int == PAUSE_S && !p_input->p->b_can_pause )
{
}
if( i_rate != p_input->p->i_rate )
{
- p_input->p->i_rate = i_rate;
val.i_int = i_rate;
var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL );
- /* We haven't send data to decoder when rate != default */
- if( i_rate == INPUT_RATE_DEFAULT )
+ /* We will not send audio data if new rate != default */
+ if( i_rate != INPUT_RATE_DEFAULT && p_input->p->i_rate == INPUT_RATE_DEFAULT )
input_EsOutDiscontinuity( p_input->p->p_es_out, VLC_TRUE );
+ p_input->p->i_rate = i_rate;
+
/* Reset clock */
es_out_Control( p_input->p->p_es_out, ES_OUT_RESET_PCR );
DEMUX_GET_TIME, &i_time ) )
{
msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
- InputSourceClean( p_input, slave );
+ InputSourceClean( slave );
free( slave );
break;
}
DEMUX_SET_TIME, i_time ) )
{
msg_Err( p_input, "seek failed for new slave" );
- InputSourceClean( p_input, slave );
+ InputSourceClean( slave );
free( slave );
break;
}
char *psz;
vlc_value_t val;
- strcpy (psz_dup, psz_mrl);
+ strcpy( psz_dup, psz_mrl );
if( !in ) return VLC_EGENERIC;
if( !p_input ) return VLC_EGENERIC;
{
psz_demux = in->p_access->psz_demux;
}
- in->p_demux = demux2_New( p_input, psz_access, psz_demux, psz_path,
- in->p_stream, p_input->p->p_es_out,
- p_input->b_preparsing );
+
+ {
+ /* Take access redirections into account */
+ char *psz_real_path;
+ char *psz_buf = NULL;
+ if( in->p_access->psz_path )
+ {
+ psz_buf = strdup( in->p_access->psz_path );
+ char *psz_a, *psz_d;
+ MRLSplit( p_input, psz_buf, &psz_a, &psz_d, &psz_real_path );
+ }
+ else
+ {
+ psz_real_path = psz_path;
+ }
+ in->p_demux = demux2_New( p_input, psz_access, psz_demux,
+ psz_real_path,
+ in->p_stream, p_input->p->p_es_out,
+ p_input->b_preparsing );
+ free( psz_buf );
+ }
+
if( in->p_demux == NULL )
{
msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
psz_access, psz_demux, psz_path );
- intf_UserFatal( VLC_OBJECT( p_input), VLC_FALSE,
+ intf_UserFatal( VLC_OBJECT( p_input ), VLC_FALSE,
_("Can't recognize the input's format"),
_("The format of '%s' can't be detected. "
"Have a look the log for details."), psz_mrl );
/*****************************************************************************
* InputSourceClean:
*****************************************************************************/
-static void InputSourceClean( input_thread_t *p_input, input_source_t *in )
+static void InputSourceClean( input_source_t *in )
{
if( in->p_demux )
demux2_Delete( in->p_demux );
psz_path = psz_dup;
}
else
+#else
+ (void)p_input;
#endif
if( psz )