Commit c884cebc authored by Laurent Aimar's avatar Laurent Aimar

Activated vout/aout recycling with playlist inputs.

parent 3b40c174
......@@ -662,6 +662,10 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
msg_Dbg( p_sys->p_input, "Decoder buffering done in %d ms",
(int)(mdate() - i_decoder_buffering_start)/1000 );
/* Here is a good place to destroy unused vout with every demuxer */
input_ressource_TerminateVout( p_sys->p_input->p->p_ressource );
/* */
const mtime_t i_wakeup_delay = 10*1000; /* FIXME CLEANUP thread wake up time*/
const mtime_t i_current_date = p_sys->b_paused ? p_sys->i_pause_date : mdate();
......@@ -2014,6 +2018,20 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
case ES_OUT_SET_ACTIVE:
{
b = (bool) va_arg( args, int );
if( b && !p_sys->b_active && p_sys->i_es > 0 )
{
/* XXX Terminate vout if there are tracks but no video one.
* This one is not mandatory but is he earliest place where it
* can be done */
for( i = 0; i < p_sys->i_es; i++ )
{
es_out_id_t *p_es = p_sys->es[i];
if( p_es->fmt.i_cat == VIDEO_ES )
break;
}
if( i >= p_sys->i_es )
input_ressource_TerminateVout( p_sys->p_input->p->p_ressource );
}
p_sys->b_active = b;
return VLC_SUCCESS;
}
......@@ -2295,7 +2313,13 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
assert(0);
}
/* TODO if the lock is made non recursive it should be changed */
return es_out_Control( out, i_new_query, p_es );
int i_ret = es_out_Control( out, i_new_query, p_es );
/* Clean up vout after user action (in active mode only).
* FIXME it does not work well with multiple video windows */
if( p_sys->b_active )
input_ressource_TerminateVout( p_sys->p_input->p->p_ressource );
return i_ret;
}
case ES_OUT_GET_BUFFERING:
......
......@@ -66,7 +66,7 @@ static void *Run ( vlc_object_t *p_this );
static void *RunAndDestroy ( vlc_object_t *p_this );
static input_thread_t * Create ( vlc_object_t *, input_item_t *,
const char *, bool, sout_instance_t * );
const char *, bool, input_ressource_t * );
static int Init ( input_thread_t *p_input );
static void WaitDie ( input_thread_t *p_input );
static void End ( input_thread_t *p_input );
......@@ -118,7 +118,7 @@ static void input_ChangeState( input_thread_t *p_input, int i_state ); /* TODO f
*****************************************************************************/
static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
const char *psz_header, bool b_quick,
sout_instance_t *p_sout )
input_ressource_t *p_ressource )
{
static const char input_name[] = "input";
input_thread_t *p_input = NULL; /* thread descriptor */
......@@ -214,7 +214,10 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
p_input->p->slave = NULL;
/* */
p_input->p->p_ressource = input_ressource_New();
if( p_ressource )
p_input->p->p_ressource = p_ressource;
else
p_input->p->p_ressource = input_ressource_New();
input_ressource_SetInput( p_input->p->p_ressource, p_input );
/* Init control buffer */
......@@ -298,9 +301,6 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
p_input->i_flags |= OBJECT_FLAGS_QUIET | OBJECT_FLAGS_NOINTERACT;
/* */
if( p_sout )
input_ressource_RequestSout( p_input->p->p_ressource, p_sout, NULL );
memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) );
vlc_mutex_init( &p_input->p->counters.counters_lock );
......@@ -356,11 +356,11 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
/* */
input_thread_t *__input_CreateThreadExtended( vlc_object_t *p_parent,
input_item_t *p_item,
const char *psz_log, sout_instance_t *p_sout )
const char *psz_log, input_ressource_t *p_ressource )
{
input_thread_t *p_input;
p_input = Create( p_parent, p_item, psz_log, false, p_sout );
p_input = Create( p_parent, p_item, psz_log, false, p_ressource );
if( !p_input )
return NULL;
......
......@@ -53,16 +53,23 @@ typedef struct input_ressource_t input_ressource_t;
void input_ressource_Delete( input_ressource_t * );
/**
* This function return the current sout (if any) from the ressource
* and stop tracking it.
* This function deletes the current sout in the ressources.
*
* You are then responsible of its release.
* It can only be called on detached ressources.
*/
sout_instance_t *input_ressource_ExtractSout( input_ressource_t *p_ressource );
void input_ressource_TerminateSout( input_ressource_t *p_ressource );
/**
* This function deletes the current vout in the ressources.
*
* It can only be called on detached ressources.
*/
void input_ressource_TerminateVout( input_ressource_t *p_ressource );
/* input.c */
#define input_CreateThreadExtended(a,b,c,d) __input_CreateThreadExtended(VLC_OBJECT(a),b,c,d)
input_thread_t *__input_CreateThreadExtended ( vlc_object_t *, input_item_t *, const char *, sout_instance_t * );
input_thread_t *__input_CreateThreadExtended ( vlc_object_t *, input_item_t *, const char *, input_ressource_t * );
/**
* This function detaches ressources from a dead input.
......
......@@ -60,28 +60,20 @@ static void DestroySout( input_ressource_t *p_ressource )
sout_DeleteInstance( p_ressource->p_sout );
p_ressource->p_sout = NULL;
}
static sout_instance_t *ExtractSout( input_ressource_t *p_ressource )
{
sout_instance_t *p_sout = p_ressource->p_sout;
p_ressource->p_sout = NULL;
return p_sout;
}
static sout_instance_t *RequestSout( input_ressource_t *p_ressource,
sout_instance_t *p_sout, const char *psz_sout )
{
assert( p_ressource->p_input );
assert( !p_sout || ( !p_ressource->p_sout && !psz_sout ) );
if( !p_sout && !psz_sout )
{
if( p_ressource->p_sout )
msg_Dbg( p_ressource->p_input, "destroying useless sout" );
msg_Dbg( p_ressource->p_sout, "destroying useless sout" );
DestroySout( p_ressource );
return NULL;
}
assert( p_ressource->p_input );
assert( !p_sout || ( !p_ressource->p_sout && !psz_sout ) );
/* Check the validity of the sout */
if( p_ressource->p_sout &&
strcmp( p_ressource->p_sout->psz_sout, psz_sout ) )
......@@ -104,7 +96,11 @@ static sout_instance_t *RequestSout( input_ressource_t *p_ressource,
/* Create a new one */
p_ressource->p_sout = sout_NewInstance( p_ressource->p_input, psz_sout );
}
return ExtractSout( p_ressource );
p_sout = p_ressource->p_sout;
p_ressource->p_sout = NULL;
return p_sout;
}
else
{
......@@ -128,25 +124,24 @@ static void DestroyVout( input_ressource_t *p_ressource )
static vout_thread_t *RequestVout( input_ressource_t *p_ressource,
vout_thread_t *p_vout, video_format_t *p_fmt )
{
assert( p_ressource->p_input );
if( !p_vout && !p_fmt )
{
if( p_ressource->p_vout_free )
{
msg_Err( p_ressource->p_input, "destroying useless vout" );
msg_Dbg( p_ressource->p_vout_free, "destroying useless vout" );
vout_CloseAndRelease( p_ressource->p_vout_free );
p_ressource->p_vout_free = NULL;
}
return NULL;
}
assert( p_ressource->p_input );
if( p_fmt )
{
/* */
if( !p_vout && p_ressource->p_vout_free )
{
msg_Err( p_ressource->p_input, "trying to reuse free vout" );
msg_Dbg( p_ressource->p_input, "trying to reuse free vout" );
p_vout = p_ressource->p_vout_free;
p_ressource->p_vout_free = NULL;
......@@ -171,12 +166,12 @@ static vout_thread_t *RequestVout( input_ressource_t *p_ressource,
TAB_REMOVE( p_ressource->i_vout, p_ressource->pp_vout, p_vout );
if( p_ressource->p_vout_free )
{
msg_Err( p_ressource->p_input, "detroying vout (already one saved)" );
msg_Dbg( p_ressource->p_input, "detroying vout (already one saved)" );
vout_CloseAndRelease( p_vout );
}
else
{
msg_Err( p_ressource->p_input, "saving a free vout" );
msg_Dbg( p_ressource->p_input, "saving a free vout" );
p_ressource->p_vout_free = p_vout;
}
return NULL;
......@@ -208,7 +203,7 @@ static aout_instance_t *RequestAout( input_ressource_t *p_ressource, aout_instan
if( p_aout )
{
msg_Err( p_ressource->p_input, "releasing aout" );
msg_Dbg( p_ressource->p_input, "releasing aout" );
vlc_object_release( p_aout );
return NULL;
}
......@@ -216,19 +211,19 @@ static aout_instance_t *RequestAout( input_ressource_t *p_ressource, aout_instan
{
if( !p_ressource->p_aout )
{
msg_Err( p_ressource->p_input, "creating aout" );
msg_Dbg( p_ressource->p_input, "creating aout" );
p_ressource->p_aout = aout_New( p_ressource->p_input );
}
else
{
msg_Err( p_ressource->p_input, "reusing aout" );
vlc_object_attach( p_ressource->p_aout, p_ressource->p_input );
msg_Dbg( p_ressource->p_input, "reusing aout" );
}
if( !p_ressource->p_aout )
return NULL;
vlc_object_detach( p_ressource->p_aout );
vlc_object_attach( p_ressource->p_aout, p_ressource->p_input );
vlc_object_hold( p_ressource->p_aout );
return p_ressource->p_aout;
}
......@@ -295,6 +290,10 @@ vout_thread_t *input_ressource_HoldVout( input_ressource_t *p_ressource )
return p_ret;
}
void input_ressource_TerminateVout( input_ressource_t *p_ressource )
{
input_ressource_RequestVout( p_ressource, NULL, NULL );
}
/* */
aout_instance_t *input_ressource_RequestAout( input_ressource_t *p_ressource, aout_instance_t *p_aout )
......@@ -315,13 +314,8 @@ sout_instance_t *input_ressource_RequestSout( input_ressource_t *p_ressource, so
return p_ret;
}
sout_instance_t *input_ressource_ExtractSout( input_ressource_t *p_ressource )
void input_ressource_TerminateSout( input_ressource_t *p_ressource )
{
vlc_mutex_lock( &p_ressource->lock );
sout_instance_t *p_ret = ExtractSout( p_ressource );
vlc_mutex_unlock( &p_ressource->lock );
return p_ret;
input_ressource_RequestSout( p_ressource, NULL, NULL );
}
......@@ -755,7 +755,7 @@ static vlm_media_instance_sys_t *vlm_MediaInstanceNew( vlm_t *p_vlm, const char
p_instance->i_index = 0;
p_instance->b_sout_keep = false;
p_instance->p_input = NULL;
p_instance->p_sout = NULL;
p_instance->p_input_ressource = NULL;
return p_instance;
}
......@@ -774,8 +774,8 @@ static void vlm_MediaInstanceDelete( vlm_media_instance_sys_t *p_instance )
vlc_object_release( p_input );
}
if( p_instance->p_sout )
sout_DeleteInstance( p_instance->p_sout );
if( p_instance->p_input_ressource )
input_ressource_Delete( p_instance->p_input_ressource );
vlc_gc_decref( p_instance->p_item );
free( p_instance->psz_name );
......@@ -839,8 +839,6 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char *
input_thread_t *p_input = p_instance->p_input;
if( p_input )
{
input_ressource_t *p_ressource;
if( p_instance->i_index == i_input_index &&
!p_input->b_eof && !p_input->b_error )
{
......@@ -852,13 +850,13 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char *
input_StopThread( p_input );
vlc_thread_join( p_input );
p_ressource = input_DetachRessource( p_input );
p_instance->p_input_ressource = input_DetachRessource( p_input );
vlc_object_release( p_input );
if( p_instance->b_sout_keep )
p_instance->p_sout = input_ressource_ExtractSout( p_ressource );
input_ressource_Delete( p_ressource );
if( !p_instance->b_sout_keep )
input_ressource_TerminateSout( p_instance->p_input_ressource );
input_ressource_TerminateVout( p_instance->p_input_ressource );
}
/* Start new one */
......@@ -867,16 +865,15 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char *
if( asprintf( &psz_log, _("Media: %s"), p_media->cfg.psz_name ) != -1 )
{
p_instance->p_input = input_CreateThreadExtended( p_vlm, p_instance->p_item, psz_log, p_instance->p_sout );
p_instance->p_input = input_CreateThreadExtended( p_vlm, p_instance->p_item,
psz_log, p_instance->p_input_ressource );
p_instance->p_input_ressource = NULL;
if( !p_instance->p_input )
{
TAB_REMOVE( p_media->i_instance, p_media->instance, p_instance );
vlm_MediaInstanceDelete( p_instance );
}
else
{
p_instance->p_sout = NULL;
}
free( psz_log );
}
......
......@@ -41,9 +41,9 @@ typedef struct
bool b_sout_keep;
input_item_t *p_item;
input_thread_t *p_input;
sout_instance_t *p_sout;
input_item_t *p_item;
input_thread_t *p_input;
input_ressource_t *p_input_ressource;
} vlm_media_instance_sys_t;
......
......@@ -175,7 +175,7 @@ static void playlist_Destructor( vlc_object_t * p_this )
playlist_private_t *p_sys = pl_priv(p_playlist);
assert( !p_sys->p_input );
assert( !p_sys->p_sout );
assert( !p_sys->p_input_ressource );
assert( !p_sys->p_preparser );
assert( !p_sys->p_fetcher );
......
......@@ -46,7 +46,6 @@ typedef struct playlist_private_t
playlist_t public_data;
playlist_preparser_t *p_preparser; /**< Preparser data */
playlist_fetcher_t *p_fetcher; /**< Meta and art fetcher data */
sout_instance_t *p_sout; /**< Kept sout instance */
playlist_item_array_t items_to_delete; /**< Array of items and nodes to
delete... At the very end. This sucks. */
......@@ -60,6 +59,7 @@ typedef struct playlist_private_t
int i_sds; /**< Number of service discovery modules */
input_thread_t * p_input; /**< the input thread associated
* with the current item */
input_ressource_t * p_input_ressource; /**< input ressources */
struct {
/* Current status. These fields are readonly, only the playlist
* main loop can touch it*/
......
......@@ -98,10 +98,10 @@ void playlist_Deactivate( playlist_t *p_playlist )
if( p_fetcher )
playlist_fetcher_Delete( p_fetcher );
/* close the remaining sout-keep */
if( p_sys->p_sout )
sout_DeleteInstance( p_sys->p_sout );
p_sys->p_sout = NULL;
/* release input ressources */
if( p_sys->p_input_ressource )
input_ressource_Delete( p_sys->p_input_ressource );
p_sys->p_input_ressource = NULL;
/* */
playlist_MLDump( p_playlist );
......@@ -263,7 +263,7 @@ static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item )
assert( p_sys->p_input == NULL );
input_thread_t *p_input_thread =
input_CreateThreadExtended( p_playlist, p_input, NULL, p_sys->p_sout );
input_CreateThreadExtended( p_playlist, p_input, NULL, p_sys->p_input_ressource );
if( p_input_thread )
{
......@@ -272,7 +272,7 @@ static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item )
var_AddCallback( p_input_thread, "intf-event", InputEvent, p_playlist );
}
p_sys->p_sout = NULL;
p_sys->p_input_ressource = NULL;
char *psz_uri = input_item_GetURI( p_item->p_input );
if( psz_uri && ( !strncmp( psz_uri, "directory:", 10 ) ||
......@@ -492,13 +492,11 @@ static int LoopInput( playlist_t *p_playlist )
{
PL_DEBUG( "dead input" );
assert( p_sys->p_sout == NULL );
assert( p_sys->p_input_ressource == NULL );
input_ressource_t *p_ressource = input_DetachRessource( p_input );
if( var_CreateGetBool( p_input, "sout-keep" ) )
p_sys->p_sout = input_ressource_ExtractSout( p_ressource );
input_ressource_Delete( p_ressource );
p_sys->p_input_ressource = input_DetachRessource( p_input );
if( !var_CreateGetBool( p_input, "sout-keep" ) )
input_ressource_TerminateSout( p_sys->p_input_ressource );
/* The DelCallback must be issued without playlist lock
* It is not a problem as we return VLC_EGENERIC */
......@@ -546,6 +544,9 @@ static void LoopRequest( playlist_t *p_playlist )
{
p_sys->status.i_status = PLAYLIST_STOPPED;
if( p_sys->p_input_ressource )
input_ressource_TerminateVout( p_sys->p_input_ressource );
if( vlc_object_alive( p_playlist ) )
vlc_object_wait( p_playlist );
return;
......
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