#include <vlc_sout.h>
#include "../stream_output/stream_output.h"
-#include <vlc_playlist.h>
#include <vlc_interface.h>
#include <vlc_url.h>
-#include <vlc_demux.h>
#include <vlc_charset.h>
+#include <vlc_playlist.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
+static void Destructor( input_thread_t * p_input );
+
static int Run ( input_thread_t *p_input );
static int RunAndDestroy ( 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 * );
* * Get only:
* - length
* - bookmarks
- * - seekable (if you can seek, it doesn't say if 'bar display' has be shown or not, for that check position != 0.0)
+ * - seekable (if you can seek, it doesn't say if 'bar display' has be shown
+ * or not, for that check position != 0.0)
* - can-pause
* * For intf callback upon changes
* - intf-change
* 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, sout_instance_t *p_sout )
+ const char *psz_header, vlc_bool_t b_quick,
+ sout_instance_t *p_sout )
{
+ static const char input_name[] = "input";
input_thread_t *p_input = NULL; /* thread descriptor */
vlc_value_t val;
int i;
/* Allocate descriptor */
- p_input = vlc_object_create( p_parent, VLC_OBJECT_INPUT );
+ p_input = vlc_custom_create( p_parent, sizeof( *p_input ),
+ VLC_OBJECT_INPUT, input_name );
if( p_input == NULL )
{
msg_Err( p_parent, "out of memory" );
/* One "randomly" selected input thread is responsible for computing
* the global stats. Check if there is already someone doing this */
- if( p_input->p_libvlc->p_playlist->p_stats && !b_quick )
+ if( p_input->p_libvlc->p_stats && !b_quick )
{
- vlc_mutex_lock( &p_input->p_libvlc->p_playlist->p_stats->lock );
- if( p_input->p_libvlc->p_playlist->p_stats_computer == NULL )
+ vlc_mutex_lock( &p_input->p_libvlc->p_stats->lock );
+ if( p_input->p_libvlc->p_stats_computer == NULL )
{
- p_input->p_libvlc->p_playlist->p_stats_computer = p_input;
+ p_input->p_libvlc->p_stats_computer = p_input;
}
- vlc_mutex_unlock( &p_input->p_libvlc->p_playlist->p_stats->lock );
+ vlc_mutex_unlock( &p_input->p_libvlc->p_stats->lock );
}
p_input->b_preparsing = b_quick;
TAB_INIT( p_input->p->i_attachment, p_input->p->attachment );
p_input->p->p_es_out = NULL;
p_input->p->p_sout = NULL;
+ p_input->p->b_owns_its_sout = VLC_TRUE;
p_input->p->b_sout_keep = VLC_FALSE;
p_input->p->b_out_pace_control = VLC_FALSE;
p_input->i_pts_delay = 0;
/* Init Input fields */
+ vlc_gc_incref( p_item ); /* Released in Destructor() */
p_input->p->input.p_item = p_item;
p_input->p->input.p_access = NULL;
p_input->p->input.p_stream = NULL;
/* Parse input options */
vlc_mutex_lock( &p_item->lock );
+ assert( p_item->optflagc == p_item->i_options );
for( i = 0; i < p_item->i_options; i++ )
- var_OptionParse( VLC_OBJECT(p_input), p_item->ppsz_options[i] );
+ var_OptionParse( VLC_OBJECT(p_input), p_item->ppsz_options[i],
+ !!(p_item->optflagv[i] & VLC_INPUT_OPTION_TRUSTED) );
vlc_mutex_unlock( &p_item->lock );
/* Create Object Variables for private use only */
/* */
if( p_sout )
+ {
p_input->p->p_sout = p_sout;
+ p_input->p->b_owns_its_sout = VLC_FALSE;
+ }
+
+ memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) );
+ vlc_mutex_init( p_input, &p_input->p->counters.counters_lock );
/* Attach only once we are ready */
vlc_object_attach( p_input, p_parent );
+ /* Set the destructor when we are sure we are initialized */
+ vlc_object_set_destructor( p_input, (vlc_destructor_t)Destructor );
+
return p_input;
}
-static void Destroy( input_thread_t *p_input, sout_instance_t **pp_sout )
+/**
+ * Input destructor (called when the object's refcount reaches 0).
+ */
+static void Destructor( input_thread_t * p_input )
{
- vlc_object_detach( p_input );
input_thread_private_t *priv = p_input->p;
- if( pp_sout )
- *pp_sout = NULL;
- if( priv->p_sout )
+ if( priv->b_owns_its_sout && priv->p_sout )
{
- if( pp_sout )
- *pp_sout = priv->p_sout;
- else if( priv->b_sout_keep )
+ if( priv->b_sout_keep )
SoutKeep( priv->p_sout );
else
sout_DeleteInstance( priv->p_sout );
}
- vlc_object_release( p_input );
+ vlc_gc_decref( p_input->p->input.p_item );
+
+ vlc_mutex_destroy( &p_input->p->counters.counters_lock );
+
vlc_mutex_destroy( &priv->lock_control );
free( priv );
}
{
input_ChangeState( p_input, ERROR_S );
msg_Err( p_input, "cannot create input thread" );
- Destroy( p_input, &p_sout );
+ vlc_object_detach( p_input );
+ vlc_object_release( p_input );
return NULL;
}
{
input_ChangeState( p_input, ERROR_S );
msg_Err( p_input, "cannot create input thread" );
- Destroy( p_input, NULL );
+ vlc_object_release( p_input );
return VLC_EGENERIC;
}
}
if( !Init( p_input ) )
End( p_input );
- Destroy( p_input, NULL );
+ vlc_object_detach( p_input );
+ vlc_object_release( p_input );
return VLC_SUCCESS;
}
input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
}
-/**
- * Clean up a dead input thread
- * This function does not return until the thread is effectively cancelled.
- *
- * \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 )
+sout_instance_t * input_DetachSout( input_thread_t *p_input )
{
- /* Join the thread */
- vlc_thread_join( p_input );
-
- /* */
- Destroy( p_input, pp_sout );
+ p_input->p->b_owns_its_sout = VLC_FALSE;
+ return p_input->p->p_sout;
}
/*****************************************************************************
{
/* If we failed, wait before we are killed, and exit */
p_input->b_error = VLC_TRUE;
- playlist_Signal( pl_Get( p_input ) );
+
+ /* FIXME: we don't want to depend on the playlist */
+ playlist_t * p_playlist = vlc_object_find( p_input,
+ VLC_OBJECT_PLAYLIST, FIND_PARENT );
+ if( p_playlist )
+ {
+ playlist_Signal( p_playlist );
+ vlc_object_release( p_playlist );
+ }
Error( p_input );
exit:
/* Release memory */
- Destroy( p_input, NULL );
+ vlc_object_release( p_input );
return 0;
}
{
stats_ComputeInputStats( p_input, p_input->p->input.p_item->p_stats );
/* Are we the thread responsible for computing global stats ? */
- if( p_input->p_libvlc->p_playlist->p_stats_computer == p_input )
+ if( p_input->p_libvlc->p_stats_computer == p_input )
{
- stats_ComputeGlobalStats( p_input->p_libvlc->p_playlist,
- p_input->p_libvlc->p_playlist->p_stats );
+ stats_ComputeGlobalStats( p_input->p_libvlc,
+ p_input->p_libvlc->p_stats );
}
}
}
int i_es_out_mode;
int i, i_delay;
- /* Initialize optional stream output. (before access/demuxer)
- * XXX: we add a special case if the uri starts by vlc.
- * else 'vlc in.file --sout "" vlc:quit' cannot work (the output will
- * be destroyed in case of a file).
- * (this will break playing of file starting by 'vlc:' but I don't
- * want to add more logic, just force file by file:// or code it ;)
- */
- memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) );
- vlc_mutex_init( p_input, &p_input->p->counters.counters_lock );
-
for( i = 0; i < p_input->p->input.p_item->i_options; i++ )
{
if( !strncmp( p_input->p->input.p_item->ppsz_options[i], "meta-file", 9 ) )
}
free( subs[i] );
}
- if( subs ) free( subs );
- if( psz_autopath ) free( psz_autopath );
+ free( subs );
+ free( psz_autopath );
}
free( psz_subtitle );
InputSourceClean( p_input->p->slave[i] );
free( p_input->p->slave[i] );
}
- if( p_input->p->slave ) free( p_input->p->slave );
+ free( p_input->p->slave );
/* Unload all modules */
if( p_input->p->p_es_out )
{
/* 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 )
+ if( p_input->p_libvlc->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;
+ stats_ComputeGlobalStats( p_input->p_libvlc,
+ p_input->p_libvlc->p_stats );
+ p_input->p_libvlc->p_stats_computer = NULL;
}
CL_CO( read_bytes );
CL_CO( read_packets );
TAB_CLEAN( p_input->p->i_attachment, p_input->p->attachment );
}
- vlc_mutex_destroy( &p_input->p->counters.counters_lock );
-
/* Tell we're dead */
p_input->b_dead = VLC_TRUE;
}
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 )
+ /* FIXME: we don't want to depend on the playlist, sout
+ * should be attached to libvlc */
+ playlist_t * p_playlist = vlc_object_find( p_parent,
+ VLC_OBJECT_PLAYLIST, FIND_PARENT );
+ if( p_playlist )
{
- if( p_sout->p_parent != VLC_OBJECT(p_playlist) )
- {
- vlc_object_release( p_sout );
- p_sout = NULL;
- }
- else
+ vlc_mutex_lock( &p_playlist->gc_lock );
+ p_sout = vlc_object_find( p_playlist, VLC_OBJECT_SOUT, FIND_CHILD );
+ if( p_sout )
{
- vlc_object_detach( p_sout ); /* Remove it from the GC */
+ 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_object_release( p_sout );
+ }
}
- }
- vlc_mutex_unlock( &p_playlist->gc_lock );
+ vlc_mutex_unlock( &p_playlist->gc_lock );
- pl_Release( p_parent );
+ vlc_object_release( p_playlist );
+ }
}
if( pb_sout_keep )
return p_sout;
}
+
static void SoutKeep( sout_instance_t *p_sout )
{
- /* attach sout to the playlist */
- playlist_t *p_playlist = pl_Yield( p_sout );
+ /* FIXME: we don't want to depend on the playlist, sout
+ * should be attached to libvlc */
+ playlist_t * p_playlist = vlc_object_find( p_sout, VLC_OBJECT_PLAYLIST,
+ FIND_PARENT );
+ if( !p_playlist ) return;
msg_Dbg( p_sout, "sout has been kept" );
vlc_object_attach( p_sout, p_playlist );
{
psz_demux = psz_forced_demux;
}
- else if( !psz_demux || *psz_demux == '\0' )
+ else if( *psz_demux == '\0' )
{
/* special hack for forcing a demuxer with --demux=module
* (and do nothing with a list) */
else
{
/* Preparsing is only for file:// */
- if( psz_demux && *psz_demux )
+ if( *psz_demux )
goto error;
- if( !psz_access || !*psz_access ) /* path without scheme:// */
+ if( !*psz_access ) /* path without scheme:// */
psz_access = "file";
if( strcmp( psz_access, "file" ) )
goto error;
input_ChangeState( p_input, OPENING_S );
/* Now try a real access */
- in->p_access = access2_New( p_input, psz_access, psz_demux, psz_path,
- p_input->b_preparsing );
+ in->p_access = access2_New( p_input, psz_access, psz_demux, psz_path );
/* Access failed, URL encoded ? */
if( in->p_access == NULL && strchr( psz_path, '%' ) )
psz_access, psz_demux, psz_path );
in->p_access = access2_New( p_input,
- psz_access, psz_demux, psz_path,
- p_input->b_preparsing );
+ psz_access, psz_demux, psz_path );
}
if( in->p_access == NULL )
{
sizeof(input_attachment_t**) * ( i_attachment + i_new ) );
for( i = 0; i < i_new; i++ )
attachment[i_attachment++] = pp_new[i];
- if( pp_new )
- free( pp_new );
+ free( pp_new );
/* */
*pi_attachment = i_attachment;