Commit e87abf62 authored by Laurent Aimar's avatar Laurent Aimar

Reworked/improved the way sout-keep works. (VLM sout-keep does not

work again yet )
parent 0bf39ed3
...@@ -52,11 +52,12 @@ static int Run ( input_thread_t *p_input ); ...@@ -52,11 +52,12 @@ static int Run ( input_thread_t *p_input );
static int RunAndDestroy ( input_thread_t *p_input ); static int RunAndDestroy ( input_thread_t *p_input );
static input_thread_t * Create ( vlc_object_t *, input_item_t *, 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 int Init ( input_thread_t *p_input );
static void Error ( input_thread_t *p_input ); static void Error ( input_thread_t *p_input );
static void End ( input_thread_t *p_input ); static void End ( input_thread_t *p_input );
static void MainLoop( 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 inline int ControlPopNoLock( input_thread_t *, int *, vlc_value_t * );
static void ControlReduce( input_thread_t * ); static void ControlReduce( input_thread_t * );
...@@ -80,6 +81,9 @@ static void SlaveSeek( input_thread_t *p_input ); ...@@ -80,6 +81,9 @@ static void SlaveSeek( input_thread_t *p_input );
static void InputMetaUser( 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 * This function creates a new input, and returns a pointer
* to its description. On error, it returns NULL. * to its description. On error, it returns NULL.
...@@ -105,7 +109,7 @@ static void InputMetaUser( input_thread_t *p_input ); ...@@ -105,7 +109,7 @@ static void InputMetaUser( input_thread_t *p_input );
* TODO complete this list (?) * TODO complete this list (?)
*****************************************************************************/ *****************************************************************************/
static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, 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 */ input_thread_t *p_input = NULL; /* thread descriptor */
vlc_value_t val; vlc_value_t val;
...@@ -151,6 +155,7 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, ...@@ -151,6 +155,7 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
p_input->p->p_meta = NULL; p_input->p->p_meta = NULL;
p_input->p->p_es_out = NULL; p_input->p->p_es_out = NULL;
p_input->p->p_sout = 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->p->b_out_pace_control = VLC_FALSE;
p_input->i_pts_delay = 0; p_input->i_pts_delay = 0;
...@@ -188,9 +193,7 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, ...@@ -188,9 +193,7 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
/* Parse input options */ /* Parse input options */
vlc_mutex_lock( &p_item->lock ); vlc_mutex_lock( &p_item->lock );
for( i = 0; i < p_item->i_options; i++ ) for( i = 0; i < p_item->i_options; i++ )
{
var_OptionParse( p_input, p_item->ppsz_options[i] ); var_OptionParse( p_input, p_item->ppsz_options[i] );
}
vlc_mutex_unlock( &p_item->lock ); vlc_mutex_unlock( &p_item->lock );
/* Create Object Variables for private use only */ /* Create Object Variables for private use only */
...@@ -257,21 +260,38 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, ...@@ -257,21 +260,38 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
if( p_input->b_preparsing ) if( p_input->b_preparsing )
p_input->i_flags |= OBJECT_FLAGS_QUIET | OBJECT_FLAGS_NOINTERACT; 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 */ /* Attach only once we are ready */
vlc_object_attach( p_input, p_parent ); vlc_object_attach( p_input, p_parent );
return p_input; return p_input;
} }
static void Destroy( input_thread_t *p_input ) static void Destroy( input_thread_t *p_input, sout_instance_t **pp_sout )
{ {
vlc_object_detach( p_input ); 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 ); vlc_mutex_destroy( &p_input->p->lock_control );
free( p_input->p ); free( p_input->p );
vlc_object_destroy( p_input ); vlc_object_destroy( p_input );
} }
/** /**
* Initialize an input thread and run it. You will need to monitor the * Initialize an input thread and run it. You will need to monitor the
* thread to clean up after it is done * thread to clean up after it is done
...@@ -283,27 +303,35 @@ static void Destroy( input_thread_t *p_input ) ...@@ -283,27 +303,35 @@ static void Destroy( input_thread_t *p_input )
input_thread_t *__input_CreateThread( vlc_object_t *p_parent, input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
input_item_t *p_item ) 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_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent,
input_item_t *p_item, input_item_t *p_item,
const char *psz_header ) 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 ) if( !p_input )
return NULL; return NULL;
/* Create thread and wait for its readiness. */ /* Create thread and wait for its readiness. */
if( vlc_thread_create( p_input, "input", Run, 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 ); input_ChangeState( p_input, ERROR_S );
msg_Err( p_input, "cannot create input thread" ); msg_Err( p_input, "cannot create input thread" );
Destroy( p_input ); Destroy( p_input, &p_sout );
return NULL; return NULL;
} }
...@@ -322,11 +350,17 @@ input_thread_t *__input_CreateThread2( vlc_object_t *p_parent, ...@@ -322,11 +350,17 @@ input_thread_t *__input_CreateThread2( vlc_object_t *p_parent,
int __input_Read( vlc_object_t *p_parent, input_item_t *p_item, int __input_Read( vlc_object_t *p_parent, input_item_t *p_item,
vlc_bool_t b_block ) 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 ); p_input = Create( p_parent, p_item, NULL, VLC_FALSE, p_sout );
if( !p_input ) if( !p_input && p_sout )
{
SoutKeep( p_sout );
return VLC_EGENERIC; return VLC_EGENERIC;
}
p_input->p->b_sout_keep = b_sout_keep;
if( b_block ) if( b_block )
{ {
...@@ -340,7 +374,7 @@ int __input_Read( vlc_object_t *p_parent, input_item_t *p_item, ...@@ -340,7 +374,7 @@ int __input_Read( vlc_object_t *p_parent, input_item_t *p_item,
{ {
input_ChangeState( p_input, ERROR_S ); input_ChangeState( p_input, ERROR_S );
msg_Err( p_input, "cannot create input thread" ); msg_Err( p_input, "cannot create input thread" );
Destroy( p_input ); Destroy( p_input, NULL );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
} }
...@@ -357,17 +391,17 @@ int __input_Read( vlc_object_t *p_parent, input_item_t *p_item, ...@@ -357,17 +391,17 @@ int __input_Read( vlc_object_t *p_parent, input_item_t *p_item,
*/ */
int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item ) 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 */ /* 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 ) if( !p_input )
return VLC_EGENERIC; return VLC_EGENERIC;
Init( p_input ); Init( p_input );
End( p_input ); End( p_input );
Destroy( p_input ); Destroy( p_input, NULL );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -422,12 +456,17 @@ void input_StopThread( input_thread_t *p_input ) ...@@ -422,12 +456,17 @@ void input_StopThread( input_thread_t *p_input )
* \param the input thread to kill * \param the input thread to kill
*/ */
void input_DestroyThread( input_thread_t *p_input ) 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 */ /* Join the thread */
vlc_thread_join( p_input ); vlc_thread_join( p_input );
/* */ /* */
Destroy( p_input ); Destroy( p_input, pp_sout );
} }
/***************************************************************************** /*****************************************************************************
...@@ -523,7 +562,7 @@ static int RunAndDestroy( input_thread_t *p_input ) ...@@ -523,7 +562,7 @@ static int RunAndDestroy( input_thread_t *p_input )
exit: exit:
/* Release memory */ /* Release memory */
Destroy( p_input ); Destroy( p_input, NULL );
return 0; return 0;
} }
...@@ -534,6 +573,7 @@ static void MainLoop( input_thread_t *p_input ) ...@@ -534,6 +573,7 @@ static void MainLoop( input_thread_t *p_input )
{ {
int64_t i_intf_update = 0; int64_t i_intf_update = 0;
int i_updates = 0; int i_updates = 0;
while( !p_input->b_die && !p_input->b_error && !p_input->p->input.b_eof ) while( !p_input->b_die && !p_input->b_error && !p_input->p->input.b_eof )
{ {
vlc_bool_t b_force_update = VLC_FALSE; vlc_bool_t b_force_update = VLC_FALSE;
...@@ -744,19 +784,45 @@ static int Init( input_thread_t * p_input ) ...@@ -744,19 +784,45 @@ static int Init( input_thread_t * p_input )
p_input->p->counters.p_input_bitrate->update_interval = 1000000; 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" ); psz = var_GetString( p_input, "sout" );
if( *psz && strncasecmp( p_input->p->input.p_item->psz_uri, "vlc:", 4 ) ) if( *psz && strncasecmp( p_input->p->input.p_item->psz_uri, "vlc:", 4 ) )
{ {
p_input->p->p_sout = sout_NewInstance( p_input, psz ); /* Check the validity of the provided sout */
if( p_input->p->p_sout == NULL ) if( p_input->p->p_sout )
{
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
{ {
input_ChangeState( p_input, ERROR_S ); /* Create a new one */
msg_Err( p_input, "cannot start stream output instance, " \ p_input->p->p_sout = sout_NewInstance( p_input, psz );
"aborting" );
free( psz ); if( !p_input->p->p_sout )
return VLC_EGENERIC; {
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 ) if( p_input->p_libvlc->b_stats )
{ {
INIT_COUNTER( sout_sent_packets, INTEGER, COUNTER ); INIT_COUNTER( sout_sent_packets, INTEGER, COUNTER );
...@@ -767,6 +833,13 @@ static int Init( input_thread_t * p_input ) ...@@ -767,6 +833,13 @@ static int Init( input_thread_t * p_input )
1000000; 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 ); free( psz );
} }
...@@ -1093,7 +1166,7 @@ error: ...@@ -1093,7 +1166,7 @@ error:
input_EsOutDelete( p_input->p->p_es_out ); input_EsOutDelete( p_input->p->p_es_out );
if( p_input->p->p_sout ) if( p_input->p->p_sout )
sout_DeleteInstance( p_input->p->p_sout ); vlc_object_detach( p_input->p->p_sout );
/* Mark them deleted */ /* Mark them deleted */
p_input->p->input.p_demux = NULL; p_input->p->input.p_demux = NULL;
...@@ -1178,35 +1251,87 @@ static void End( input_thread_t * p_input ) ...@@ -1178,35 +1251,87 @@ static void End( input_thread_t * p_input )
/* Close optional stream output instance */ /* Close optional stream output instance */
if( p_input->p->p_sout ) if( p_input->p->p_sout )
{ {
vlc_value_t keep;
CL_CO( sout_sent_packets ); CL_CO( sout_sent_packets );
CL_CO( sout_sent_bytes ); CL_CO( sout_sent_bytes );
CL_CO( sout_send_bitrate ); CL_CO( sout_send_bitrate );
if( var_Get( p_input, "sout-keep", &keep ) >= 0 && keep.b_bool ) vlc_object_detach( p_input->p->p_sout );
{ }
playlist_t *p_playlist = pl_Yield( p_input ); #undef CL_CO
}
vlc_mutex_destroy( &p_input->p->counters.counters_lock );
/* Tell we're dead */
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++;
/* attach sout to the playlist */ if( !strcmp( psz_option, "sout-keep" ) )
vlc_object_detach( p_input->p->p_sout ); b_keep_sout = VLC_TRUE;
vlc_object_attach( p_input->p->p_sout, p_playlist ); else if( !strcmp( psz_option, "no-sout-keep" ) || !strcmp( psz_option, "nosout-keep" ) )
pl_Release( p_input ); b_keep_sout = VLC_FALSE;
msg_Dbg( p_input, "kept sout" ); }
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 else
{ {
sout_DeleteInstance( p_input->p->p_sout ); vlc_object_detach( p_sout ); /* Remove it from the GC */
msg_Dbg( p_input, "destroyed sout" );
vlc_object_release( p_sout );
} }
} }
#undef CL_CO vlc_mutex_unlock( &p_playlist->gc_lock );
pl_Release( p_parent );
} }
vlc_mutex_destroy( &p_input->p->counters.counters_lock ); if( pb_sout_keep )
*pb_sout_keep = b_keep_sout;
/* Tell we're dead */ return p_sout;
p_input->b_dead = VLC_TRUE; }
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 );
} }
/***************************************************************************** /*****************************************************************************
......
...@@ -93,6 +93,7 @@ struct input_thread_private_t ...@@ -93,6 +93,7 @@ struct input_thread_private_t
/* Output */ /* Output */
es_out_t *p_es_out; es_out_t *p_es_out;
sout_instance_t *p_sout; /* XXX Move it to es_out ? */ sout_instance_t *p_sout; /* XXX Move it to es_out ? */
vlc_bool_t b_sout_keep;
vlc_bool_t b_out_pace_control; /* idem ? */ vlc_bool_t b_out_pace_control; /* idem ? */
/* Main input properties */ /* Main input properties */
...@@ -225,8 +226,10 @@ int input_DownloadAndCacheArt ( playlist_t *, input_item_t * ); ...@@ -225,8 +226,10 @@ int input_DownloadAndCacheArt ( playlist_t *, input_item_t * );
***************************************************************************/ ***************************************************************************/
/* input.c */ /* input.c */
#define input_CreateThread2(a,b,c) __input_CreateThread2(VLC_OBJECT(a),b,c) #define input_CreateThreadExtended(a,b,c,d) __input_CreateThreadExtended(VLC_OBJECT(a),b,c,d)
input_thread_t *__input_CreateThread2 ( vlc_object_t *, input_item_t *, const char * ); input_thread_t *__input_CreateThreadExtended ( vlc_object_t *, input_item_t *, const char *, sout_instance_t * );
void input_DestroyThreadExtended( input_thread_t *p_input, sout_instance_t ** );
/* var.c */ /* var.c */
void input_ControlVarInit ( input_thread_t * ); void input_ControlVarInit ( input_thread_t * );
......
...@@ -1140,14 +1140,13 @@ int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, const char *psz_cmd, ...@@ -1140,14 +1140,13 @@ int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, const char *psz_cmd,
asprintf( &psz_header, _("Media: %s"), media->psz_name ); asprintf( &psz_header, _("Media: %s"), media->psz_name );
if( (p_input = input_CreateThread2( vlm, &media->item, psz_header if( (p_input = input_CreateThreadExtended( vlm, &media->item, psz_header, NULL ) ) )
) ) )
{ {
while( !p_input->b_eof && !p_input->b_error ) while( !p_input->b_eof && !p_input->b_error )
msleep( 100000 ); msleep( 100000 );
input_StopThread( p_input ); input_StopThread( p_input );
input_DestroyThread( p_input ); input_DestroyThreadExtended( p_input, NULL );
} }
free( psz_output ); free( psz_output );
free( psz_header ); free( psz_header );
...@@ -1242,12 +1241,11 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id, ...@@ -1242,12 +1241,11 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id,
if( p_instance->p_input ) if( p_instance->p_input )
{ {
input_StopThread( p_instance->p_input ); input_StopThread( p_instance->p_input );
input_DestroyThread( p_instance->p_input ); input_DestroyThreadExtended( p_instance->p_input, NULL );
} }
asprintf( &psz_header, _("Media: %s"), media->psz_name ); asprintf( &psz_header, _("Media: %s"), media->psz_name );
p_instance->p_input = input_CreateThread2( vlm, &p_instance->item, p_instance->p_input = input_CreateThreadExtended( vlm, &p_instance->item, psz_header, NULL );
psz_header );
if( !p_instance->p_input ) if( !p_instance->p_input )
{ {
TAB_REMOVE( media->i_instance, media->instance, p_instance ); TAB_REMOVE( media->i_instance, media->instance, p_instance );
...@@ -1361,7 +1359,7 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id, ...@@ -1361,7 +1359,7 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id,
if( p_instance->p_input ) if( p_instance->p_input )
{ {
input_StopThread( p_instance->p_input ); input_StopThread( p_instance->p_input );
input_DestroyThread( p_instance->p_input ); input_DestroyThreadExtended( p_instance->p_input, NULL );
} }
input_ItemClean( &p_instance->item ); input_ItemClean( &p_instance->item );
...@@ -2502,7 +2500,7 @@ static int Manage( vlc_object_t* p_object ) ...@@ -2502,7 +2500,7 @@ static int Manage( vlc_object_t* p_object )
char buffer[12]; char buffer[12];
input_StopThread( p_instance->p_input ); input_StopThread( p_instance->p_input );
input_DestroyThread( p_instance->p_input ); input_DestroyThreadExtended( p_instance->p_input, NULL );
p_instance->p_input = NULL; p_instance->p_input = NULL;
/* FIXME, find a way to select the right instance */ /* FIXME, find a way to select the right instance */
......
...@@ -210,6 +210,8 @@ static void ObjectGarbageCollector( playlist_t *p_playlist ) ...@@ -210,6 +210,8 @@ static void ObjectGarbageCollector( playlist_t *p_playlist )
vlc_object_release( p_obj ); vlc_object_release( p_obj );
break; break;
} }
msg_Dbg( p_playlist, "garbage collector destroying 1 sout" );
vlc_object_detach( p_obj );
vlc_object_release( p_obj ); vlc_object_release( p_obj );
sout_DeleteInstance( (sout_instance_t*)p_obj ); sout_DeleteInstance( (sout_instance_t*)p_obj );
} }
...@@ -409,6 +411,7 @@ void playlist_LastLoop( playlist_t *p_playlist ) ...@@ -409,6 +411,7 @@ void playlist_LastLoop( playlist_t *p_playlist )
while( ( p_obj = vlc_object_find( p_playlist, while( ( p_obj = vlc_object_find( p_playlist,
VLC_OBJECT_SOUT, FIND_CHILD ) ) ) VLC_OBJECT_SOUT, FIND_CHILD ) ) )
{ {
vlc_object_detach( p_obj );
vlc_object_release( p_obj ); vlc_object_release( p_obj );
sout_DeleteInstance( (sout_instance_t*)p_obj ); sout_DeleteInstance( (sout_instance_t*)p_obj );
} }
......
...@@ -73,45 +73,6 @@ static void mrl_Clean( mrl_t *p_mrl ); ...@@ -73,45 +73,6 @@ static void mrl_Clean( mrl_t *p_mrl );
sout_instance_t *__sout_NewInstance( vlc_object_t *p_parent, char * psz_dest ) sout_instance_t *__sout_NewInstance( vlc_object_t *p_parent, char * psz_dest )
{ {
sout_instance_t *p_sout; sout_instance_t *p_sout;
vlc_value_t keep;
if( var_Get( p_parent, "sout-keep", &keep ) >= 0 && keep.b_bool )
{
/* 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 && p_sout->p_parent != (vlc_object_t *)p_playlist )
{
vlc_object_release( p_sout );
p_sout = NULL;
}
if( p_sout )
vlc_object_detach( p_sout ); /* Remove it from the GC */
vlc_mutex_unlock( &p_playlist->gc_lock );
pl_Release( p_parent );
/* */
if( p_sout )
{
if( !strcmp( p_sout->psz_sout, psz_dest ) )
{
msg_Dbg( p_parent, "sout keep: reusing sout" );
msg_Dbg( p_parent, "sout keep: you probably want to use "
"gather stream_out" );
vlc_object_attach( p_sout, p_parent );
vlc_object_release( p_sout );
return p_sout;
}
msg_Dbg( p_parent, "sout keep: destroying unusable sout" );
vlc_object_release( p_sout );
sout_DeleteInstance( p_sout );
}
}
/* *** Allocate descriptor *** */ /* *** Allocate descriptor *** */
p_sout = vlc_object_create( p_parent, VLC_OBJECT_SOUT ); p_sout = vlc_object_create( p_parent, VLC_OBJECT_SOUT );
...@@ -164,9 +125,6 @@ sout_instance_t *__sout_NewInstance( vlc_object_t *p_parent, char * psz_dest ) ...@@ -164,9 +125,6 @@ sout_instance_t *__sout_NewInstance( vlc_object_t *p_parent, char * psz_dest )
*****************************************************************************/ *****************************************************************************/
void sout_DeleteInstance( sout_instance_t * p_sout ) void sout_DeleteInstance( sout_instance_t * p_sout )
{ {
/* Unlink object */
vlc_object_detach( p_sout );
/* remove the stream out chain */ /* remove the stream out chain */
sout_StreamDelete( p_sout->p_stream ); sout_StreamDelete( p_sout->p_stream );
......
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