Commit 1743aae3 authored by Rafaël Carré's avatar Rafaël Carré

sout: allow duplicate outputs to be merged

The stream_out_t chain creation is modified: all modules are created by
the core (or by stream_out_duplicate) instead of being created by the
previous module.

sout_StreamChain{New,Delete} replace sout_Stream{New,Delete} to handle
modules chains instead of individual modules

sout_Stream{New,Delete} are still used by those new functions but made
static inside stream_output.c

Remove now unneeded psz_chain from struct sout_instance_t
Replace pointer to chain of next module by pointer to next module in
struct sout_stream_t

Example use:

vlc --sout-all input.mp4 --sout
"#duplicate{dst=transcode{vcodec=mp2v},select=es=0,dst=transcode,select=es=1}:std{...}"

(dst=transcode without acodec/vcodec is a hack to pass the encoded stream to
stream_out_standard without transcoding)
parent d83a491d
...@@ -45,7 +45,6 @@ struct sout_instance_t ...@@ -45,7 +45,6 @@ struct sout_instance_t
VLC_COMMON_MEMBERS VLC_COMMON_MEMBERS
char *psz_sout; char *psz_sout;
char *psz_chain;
/* meta data (Read only) XXX it won't be set before the first packet received */ /* meta data (Read only) XXX it won't be set before the first packet received */
vlc_meta_t *p_meta; vlc_meta_t *p_meta;
...@@ -208,7 +207,7 @@ struct sout_stream_t ...@@ -208,7 +207,7 @@ struct sout_stream_t
char *psz_name; char *psz_name;
config_chain_t *p_cfg; config_chain_t *p_cfg;
char *psz_next; sout_stream_t *p_next;
/* Subpicture unit */ /* Subpicture unit */
spu_t *p_spu; spu_t *p_spu;
...@@ -223,8 +222,9 @@ struct sout_stream_t ...@@ -223,8 +222,9 @@ struct sout_stream_t
sout_stream_sys_t *p_sys; sout_stream_sys_t *p_sys;
}; };
VLC_EXPORT( sout_stream_t *, sout_StreamNew, ( sout_instance_t *, char *psz_chain ) ); VLC_EXPORT( void, sout_StreamChainDelete, (sout_stream_t *p_first, sout_stream_t *p_last ) );
VLC_EXPORT( void, sout_StreamDelete, ( sout_stream_t * ) ); VLC_EXPORT( sout_stream_t *, sout_StreamChainNew, (sout_instance_t *p_sout,
char *psz_chain, sout_stream_t *p_next, sout_stream_t **p_last) );
static inline sout_stream_id_t *sout_StreamIdAdd( sout_stream_t *s, es_format_t *fmt ) static inline sout_stream_id_t *sout_StreamIdAdd( sout_stream_t *s, es_format_t *fmt )
{ {
......
...@@ -68,7 +68,6 @@ struct sout_stream_id_t ...@@ -68,7 +68,6 @@ struct sout_stream_id_t
struct sout_stream_sys_t struct sout_stream_sys_t
{ {
sout_stream_t *p_out;
sout_stream_id_t **pp_es; sout_stream_id_t **pp_es;
int i_es_num; int i_es_num;
}; };
...@@ -83,8 +82,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -83,8 +82,7 @@ static int Open( vlc_object_t *p_this )
p_sys = malloc( sizeof( sout_stream_sys_t ) ); p_sys = malloc( sizeof( sout_stream_sys_t ) );
p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next ); if( !p_stream->p_next )
if( !p_sys->p_out )
{ {
msg_Err( p_stream, "cannot create chain" ); msg_Err( p_stream, "cannot create chain" );
free( p_sys ); free( p_sys );
...@@ -113,7 +111,6 @@ static void Close( vlc_object_t * p_this ) ...@@ -113,7 +111,6 @@ static void Close( vlc_object_t * p_this )
sout_stream_t *p_stream = (sout_stream_t*)p_this; sout_stream_t *p_stream = (sout_stream_t*)p_this;
sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys; sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys;
sout_StreamDelete( p_sys->p_out );
p_stream->p_sout->i_out_pace_nocontrol--; p_stream->p_sout->i_out_pace_nocontrol--;
free( p_sys ); free( p_sys );
...@@ -142,7 +139,7 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *p_es ) ...@@ -142,7 +139,7 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *p_es )
free( p_es ); free( p_es );
if ( id != NULL ) if ( id != NULL )
return p_sys->p_out->pf_del( p_sys->p_out, id ); return p_stream->p_next->pf_del( p_stream->p_next, id );
else else
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -157,7 +154,7 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *p_es, ...@@ -157,7 +154,7 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *p_es,
p_es->i_last = p_buffer->i_dts; p_es->i_last = p_buffer->i_dts;
if ( p_es->id == NULL && p_es->b_error != true ) if ( p_es->id == NULL && p_es->b_error != true )
{ {
p_es->id = p_sys->p_out->pf_add( p_sys->p_out, &p_es->fmt ); p_es->id = p_stream->p_next->pf_add( p_stream->p_next, &p_es->fmt );
if ( p_es->id == NULL ) if ( p_es->id == NULL )
{ {
p_es->b_error = true; p_es->b_error = true;
...@@ -167,7 +164,7 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *p_es, ...@@ -167,7 +164,7 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *p_es,
} }
if ( p_es->b_error != true ) if ( p_es->b_error != true )
p_sys->p_out->pf_send( p_sys->p_out, p_es->id, p_buffer ); p_stream->p_next->pf_send( p_stream->p_next, p_es->id, p_buffer );
else else
block_ChainRelease( p_buffer ); block_ChainRelease( p_buffer );
...@@ -178,7 +175,7 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *p_es, ...@@ -178,7 +175,7 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *p_es,
|| p_sys->pp_es[i]->fmt.i_cat == AUDIO_ES) || p_sys->pp_es[i]->fmt.i_cat == AUDIO_ES)
&& p_sys->pp_es[i]->i_last < i_current ) && p_sys->pp_es[i]->i_last < i_current )
{ {
p_sys->p_out->pf_del( p_sys->p_out, p_sys->pp_es[i]->id ); p_stream->p_next->pf_del( p_stream->p_next, p_sys->pp_es[i]->id );
p_sys->pp_es[i]->id = NULL; p_sys->pp_es[i]->id = NULL;
} }
} }
......
...@@ -363,7 +363,6 @@ static int SendOut( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -363,7 +363,6 @@ static int SendOut( sout_stream_t *p_stream, sout_stream_id_t *id,
typedef struct in_sout_stream_sys_t typedef struct in_sout_stream_sys_t
{ {
sout_stream_t *p_out;
vlc_mutex_t *p_lock; vlc_mutex_t *p_lock;
int i_id_offset; int i_id_offset;
mtime_t i_delay; mtime_t i_delay;
...@@ -395,8 +394,7 @@ static int OpenIn( vlc_object_t *p_this ) ...@@ -395,8 +394,7 @@ static int OpenIn( vlc_object_t *p_this )
if( unlikely( !p_sys ) ) if( unlikely( !p_sys ) )
return VLC_ENOMEM; return VLC_ENOMEM;
p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next ); if( !p_stream->p_next )
if( !p_sys->p_out )
{ {
msg_Err( p_stream, "cannot create chain" ); msg_Err( p_stream, "cannot create chain" );
free( p_sys ); free( p_sys );
...@@ -461,7 +459,6 @@ static void CloseIn( vlc_object_t * p_this ) ...@@ -461,7 +459,6 @@ static void CloseIn( vlc_object_t * p_this )
sout_stream_t *p_stream = (sout_stream_t*)p_this; sout_stream_t *p_stream = (sout_stream_t*)p_this;
in_sout_stream_sys_t *p_sys = (in_sout_stream_sys_t *)p_stream->p_sys; in_sout_stream_sys_t *p_sys = (in_sout_stream_sys_t *)p_stream->p_sys;
sout_StreamDelete( p_sys->p_out );
p_stream->p_sout->i_out_pace_nocontrol--; p_stream->p_sout->i_out_pace_nocontrol--;
free( p_sys->psz_name ); free( p_sys->psz_name );
...@@ -481,7 +478,7 @@ static sout_stream_id_t * AddIn( sout_stream_t *p_stream, es_format_t *p_fmt ) ...@@ -481,7 +478,7 @@ static sout_stream_id_t * AddIn( sout_stream_t *p_stream, es_format_t *p_fmt )
sout_stream_id_t *id = malloc( sizeof( sout_stream_id_t ) ); sout_stream_id_t *id = malloc( sizeof( sout_stream_id_t ) );
if( !id ) return NULL; if( !id ) return NULL;
id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt ); id->id = p_stream->p_next->pf_add( p_stream->p_next, p_fmt );
if( !id->id ) if( !id->id )
{ {
free( id ); free( id );
...@@ -516,7 +513,7 @@ static int DelIn( sout_stream_t *p_stream, sout_stream_id_t *id ) ...@@ -516,7 +513,7 @@ static int DelIn( sout_stream_t *p_stream, sout_stream_id_t *id )
if( id == p_sys->id_video ) p_sys->id_video = NULL; if( id == p_sys->id_video ) p_sys->id_video = NULL;
if( id == p_sys->id_audio ) p_sys->id_audio = NULL; if( id == p_sys->id_audio ) p_sys->id_audio = NULL;
int ret = p_sys->p_out->pf_del( p_sys->p_out, id->id ); int ret = p_stream->p_next->pf_del( p_stream->p_next, id->id );
free( id ); free( id );
return ret; return ret;
...@@ -533,7 +530,7 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -533,7 +530,7 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id,
/* First forward the packet for our own ES */ /* First forward the packet for our own ES */
if( !p_sys->b_placeholder ) if( !p_sys->b_placeholder )
p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer ); p_stream->p_next->pf_send( p_stream->p_next, id->id, p_buffer );
/* Then check all bridged streams */ /* Then check all bridged streams */
vlc_mutex_lock( p_sys->p_lock ); vlc_mutex_lock( p_sys->p_lock );
...@@ -570,7 +567,7 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -570,7 +567,7 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id,
{ {
if ( p_bridge->pp_es[i]->b_empty && p_bridge->pp_es[i]->id != NULL ) if ( p_bridge->pp_es[i]->b_empty && p_bridge->pp_es[i]->id != NULL )
{ {
p_sys->p_out->pf_del( p_sys->p_out, p_bridge->pp_es[i]->id ); p_stream->p_next->pf_del( p_stream->p_next, p_bridge->pp_es[i]->id );
} }
else else
{ {
...@@ -584,8 +581,8 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -584,8 +581,8 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id,
p_bridge->pp_es[i]->fmt.i_id += p_sys->i_id_offset; p_bridge->pp_es[i]->fmt.i_id += p_sys->i_id_offset;
if( !p_sys->b_placeholder ) if( !p_sys->b_placeholder )
{ {
p_bridge->pp_es[i]->id = p_sys->p_out->pf_add( p_bridge->pp_es[i]->id = p_stream->p_next->pf_add(
p_sys->p_out, &p_bridge->pp_es[i]->fmt ); p_stream->p_next, &p_bridge->pp_es[i]->fmt );
if ( p_bridge->pp_es[i]->id == NULL ) if ( p_bridge->pp_es[i]->id == NULL )
{ {
msg_Warn( p_stream, "couldn't create chain for id %d", msg_Warn( p_stream, "couldn't create chain for id %d",
...@@ -608,7 +605,7 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -608,7 +605,7 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id,
&& p_bridge->pp_es[i]->i_last < i_date ) && p_bridge->pp_es[i]->i_last < i_date )
{ {
if( !p_sys->b_placeholder ) if( !p_sys->b_placeholder )
p_sys->p_out->pf_del( p_sys->p_out, p_stream->p_next->pf_del( p_stream->p_next,
p_bridge->pp_es[i]->id ); p_bridge->pp_es[i]->id );
p_bridge->pp_es[i]->fmt.i_id -= p_sys->i_id_offset; p_bridge->pp_es[i]->fmt.i_id -= p_sys->i_id_offset;
p_bridge->pp_es[i]->b_changed = true; p_bridge->pp_es[i]->b_changed = true;
...@@ -642,7 +639,7 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -642,7 +639,7 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id,
( p_bridge->pp_es[i]->fmt.i_cat == VIDEO_ES && ( p_bridge->pp_es[i]->fmt.i_cat == VIDEO_ES &&
p_bridge->pp_es[i]->p_block->i_flags & BLOCK_FLAG_TYPE_I ) ) p_bridge->pp_es[i]->p_block->i_flags & BLOCK_FLAG_TYPE_I ) )
{ {
p_sys->p_out->pf_send( p_sys->p_out, p_stream->p_next->pf_send( p_stream->p_next,
newid, newid,
p_bridge->pp_es[i]->p_block ); p_bridge->pp_es[i]->p_block );
p_sys->i_state = placeholder_off; p_sys->i_state = placeholder_off;
...@@ -654,14 +651,14 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -654,14 +651,14 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id,
break; break;
p_sys->i_last_audio = i_date; p_sys->i_last_audio = i_date;
default: default:
p_sys->p_out->pf_send( p_sys->p_out, p_stream->p_next->pf_send( p_stream->p_next,
newid?newid:p_bridge->pp_es[i]->id, newid?newid:p_bridge->pp_es[i]->id,
p_bridge->pp_es[i]->p_block ); p_bridge->pp_es[i]->p_block );
break; break;
} }
} }
else /* !b_placeholder */ else /* !b_placeholder */
p_sys->p_out->pf_send( p_sys->p_out, p_stream->p_next->pf_send( p_stream->p_next,
p_bridge->pp_es[i]->id, p_bridge->pp_es[i]->id,
p_bridge->pp_es[i]->p_block ); p_bridge->pp_es[i]->p_block );
} }
...@@ -694,7 +691,7 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -694,7 +691,7 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id,
|| p_buffer->i_flags & BLOCK_FLAG_TYPE_I ) ) || p_buffer->i_flags & BLOCK_FLAG_TYPE_I ) )
|| p_sys->i_state == placeholder_on ) || p_sys->i_state == placeholder_on )
{ {
p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer ); p_stream->p_next->pf_send( p_stream->p_next, id->id, p_buffer );
p_sys->i_state = placeholder_on; p_sys->i_state = placeholder_on;
} }
else else
...@@ -703,7 +700,7 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -703,7 +700,7 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_t *id,
case AUDIO_ES: case AUDIO_ES:
if( p_sys->i_last_audio + p_sys->i_placeholder_delay < i_date ) if( p_sys->i_last_audio + p_sys->i_placeholder_delay < i_date )
p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer ); p_stream->p_next->pf_send( p_stream->p_next, id->id, p_buffer );
else else
block_Release( p_buffer ); block_Release( p_buffer );
break; break;
......
...@@ -64,6 +64,9 @@ struct sout_stream_sys_t ...@@ -64,6 +64,9 @@ struct sout_stream_sys_t
int i_nb_streams; int i_nb_streams;
sout_stream_t **pp_streams; sout_stream_t **pp_streams;
int i_nb_last_streams;
sout_stream_t **pp_last_streams;
int i_nb_select; int i_nb_select;
char **ppsz_select; char **ppsz_select;
}; };
...@@ -92,20 +95,24 @@ static int Open( vlc_object_t *p_this ) ...@@ -92,20 +95,24 @@ static int Open( vlc_object_t *p_this )
return VLC_ENOMEM; return VLC_ENOMEM;
TAB_INIT( p_sys->i_nb_streams, p_sys->pp_streams ); TAB_INIT( p_sys->i_nb_streams, p_sys->pp_streams );
TAB_INIT( p_sys->i_nb_last_streams, p_sys->pp_last_streams );
TAB_INIT( p_sys->i_nb_select, p_sys->ppsz_select ); TAB_INIT( p_sys->i_nb_select, p_sys->ppsz_select );
for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next ) for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
{ {
if( !strncmp( p_cfg->psz_name, "dst", strlen( "dst" ) ) ) if( !strncmp( p_cfg->psz_name, "dst", strlen( "dst" ) ) )
{ {
sout_stream_t *s; sout_stream_t *s, *p_last;
msg_Dbg( p_stream, " * adding `%s'", p_cfg->psz_value ); msg_Dbg( p_stream, " * adding `%s'", p_cfg->psz_value );
s = sout_StreamNew( p_stream->p_sout, p_cfg->psz_value ); s = sout_StreamChainNew( p_stream->p_sout, p_cfg->psz_value,
p_stream->p_next, &p_last );
if( s ) if( s )
{ {
TAB_APPEND( p_sys->i_nb_streams, p_sys->pp_streams, s ); TAB_APPEND( p_sys->i_nb_streams, p_sys->pp_streams, s );
TAB_APPEND( p_sys->i_nb_last_streams, p_sys->pp_last_streams,
p_last );
TAB_APPEND( p_sys->i_nb_select, p_sys->ppsz_select, NULL ); TAB_APPEND( p_sys->i_nb_select, p_sys->ppsz_select, NULL );
} }
} }
...@@ -164,10 +171,11 @@ static void Close( vlc_object_t * p_this ) ...@@ -164,10 +171,11 @@ static void Close( vlc_object_t * p_this )
msg_Dbg( p_stream, "closing a duplication" ); msg_Dbg( p_stream, "closing a duplication" );
for( i = 0; i < p_sys->i_nb_streams; i++ ) for( i = 0; i < p_sys->i_nb_streams; i++ )
{ {
sout_StreamDelete( p_sys->pp_streams[i] ); sout_StreamChainDelete(p_sys->pp_streams[i], p_sys->pp_last_streams[i]);
free( p_sys->ppsz_select[i] ); free( p_sys->ppsz_select[i] );
} }
free( p_sys->pp_streams ); free( p_sys->pp_streams );
free( p_sys->pp_last_streams );
free( p_sys->ppsz_select ); free( p_sys->ppsz_select );
free( p_sys ); free( p_sys );
......
...@@ -64,8 +64,6 @@ struct sout_stream_id_t ...@@ -64,8 +64,6 @@ struct sout_stream_id_t
struct sout_stream_sys_t struct sout_stream_sys_t
{ {
sout_stream_t *p_out;
int i_id; int i_id;
sout_stream_id_t **id; sout_stream_id_t **id;
}; };
...@@ -82,8 +80,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -82,8 +80,7 @@ static int Open( vlc_object_t *p_this )
if( p_sys == NULL ) if( p_sys == NULL )
return VLC_EGENERIC; return VLC_EGENERIC;
p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next ); if( !p_stream->p_next )
if( p_sys->p_out == NULL )
{ {
free( p_sys ); free( p_sys );
return VLC_EGENERIC; return VLC_EGENERIC;
...@@ -110,13 +107,12 @@ static void Close( vlc_object_t * p_this ) ...@@ -110,13 +107,12 @@ static void Close( vlc_object_t * p_this )
{ {
sout_stream_id_t *id = p_sys->id[i]; sout_stream_id_t *id = p_sys->id[i];
sout_StreamIdDel( p_sys->p_out, id->id ); sout_StreamIdDel( p_stream->p_next, id->id );
es_format_Clean( &id->fmt ); es_format_Clean( &id->fmt );
free( id ); free( id );
} }
TAB_CLEAN( p_sys->i_id, p_sys->id ); TAB_CLEAN( p_sys->i_id, p_sys->id );
sout_StreamDelete( p_sys->p_out );
free( p_sys ); free( p_sys );
} }
...@@ -168,7 +164,7 @@ static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt ) ...@@ -168,7 +164,7 @@ static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt )
if( !id->b_used && id->fmt.i_cat == p_fmt->i_cat ) if( !id->b_used && id->fmt.i_cat == p_fmt->i_cat )
{ {
TAB_REMOVE( p_sys->i_id, p_sys->id, id ); TAB_REMOVE( p_sys->i_id, p_sys->id, id );
sout_StreamIdDel( p_sys->p_out, id->id ); sout_StreamIdDel( p_stream->p_next, id->id );
es_format_Clean( &id->fmt ); es_format_Clean( &id->fmt );
free( id ); free( id );
...@@ -183,7 +179,7 @@ static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt ) ...@@ -183,7 +179,7 @@ static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt )
return NULL; return NULL;
es_format_Copy( &id->fmt, p_fmt ); es_format_Copy( &id->fmt, p_fmt );
id->b_used = true; id->b_used = true;
id->id = sout_StreamIdAdd( p_sys->p_out, &id->fmt ); id->id = sout_StreamIdAdd( p_stream->p_next, &id->fmt );
if( id->id == NULL ) if( id->id == NULL )
{ {
free( id ); free( id );
...@@ -210,7 +206,5 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *id ) ...@@ -210,7 +206,5 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
static int Send( sout_stream_t *p_stream, static int Send( sout_stream_t *p_stream,
sout_stream_id_t *id, block_t *p_buffer ) sout_stream_id_t *id, block_t *p_buffer )
{ {
sout_stream_sys_t *p_sys = p_stream->p_sys; return sout_StreamIdSend( p_stream->p_next, id->id, p_buffer );
return sout_StreamIdSend( p_sys->p_out, id->id, p_buffer );
} }
...@@ -170,7 +170,7 @@ static void Close( vlc_object_t * p_this ) ...@@ -170,7 +170,7 @@ static void Close( vlc_object_t * p_this )
sout_stream_sys_t *p_sys = p_stream->p_sys; sout_stream_sys_t *p_sys = p_stream->p_sys;
if( p_sys->p_out ) if( p_sys->p_out )
sout_StreamDelete( p_sys->p_out ); sout_StreamChainDelete( p_sys->p_out, p_sys->p_out );
TAB_CLEAN( p_sys->i_id, p_sys->id ); TAB_CLEAN( p_sys->i_id, p_sys->id );
free( p_sys->psz_prefix ); free( p_sys->psz_prefix );
...@@ -327,7 +327,7 @@ static int OutputNew( sout_stream_t *p_stream, ...@@ -327,7 +327,7 @@ static int OutputNew( sout_stream_t *p_stream,
/* Create the output */ /* Create the output */
msg_Dbg( p_stream, "Using record output `%s'", psz_output ); msg_Dbg( p_stream, "Using record output `%s'", psz_output );
p_sys->p_out = sout_StreamNew( p_stream->p_sout, psz_output ); p_sys->p_out = sout_StreamChainNew( p_stream->p_sout, psz_output, NULL, NULL );
if( !p_sys->p_out ) if( !p_sys->p_out )
goto error; goto error;
...@@ -460,7 +460,7 @@ static void OutputStart( sout_stream_t *p_stream ) ...@@ -460,7 +460,7 @@ static void OutputStart( sout_stream_t *p_stream )
id->id = NULL; id->id = NULL;
} }
if( p_sys->p_out ) if( p_sys->p_out )
sout_StreamDelete( p_sys->p_out ); sout_StreamChainDelete( p_sys->p_out, p_sys->p_out );
p_sys->p_out = NULL; p_sys->p_out = NULL;
if( i_es > i_best_es ) if( i_es > i_best_es )
......
...@@ -143,7 +143,6 @@ static const char *const ppsz_sout_options[] = { ...@@ -143,7 +143,6 @@ static const char *const ppsz_sout_options[] = {
struct sout_stream_sys_t struct sout_stream_sys_t
{ {
sout_stream_t *p_out;
int i_gop; int i_gop;
int i_qscale; int i_qscale;
int i_aspect; int i_aspect;
...@@ -191,8 +190,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -191,8 +190,7 @@ static int Open( vlc_object_t *p_this )
if( !p_sys ) if( !p_sys )
return VLC_ENOMEM; return VLC_ENOMEM;
p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next ); if( !p_stream->p_next )
if( !p_sys->p_out )
{ {
msg_Err( p_stream, "cannot create chain" ); msg_Err( p_stream, "cannot create chain" );
free( p_sys ); free( p_sys );
...@@ -306,8 +304,6 @@ static void Close( vlc_object_t * p_this ) ...@@ -306,8 +304,6 @@ static void Close( vlc_object_t * p_this )
sout_stream_t *p_stream = (sout_stream_t *)p_this; sout_stream_t *p_stream = (sout_stream_t *)p_this;
sout_stream_sys_t *p_sys = p_stream->p_sys; sout_stream_sys_t *p_sys = p_stream->p_sys;
sout_StreamDelete( p_sys->p_out );
free( p_sys ); free( p_sys );
} }
...@@ -427,7 +423,7 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) ...@@ -427,7 +423,7 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
memcpy( &id->f_src, p_fmt, sizeof( es_format_t ) ); memcpy( &id->f_src, p_fmt, sizeof( es_format_t ) );
/* open output stream */ /* open output stream */
id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt ); id->id = p_stream->p_next->pf_add( p_stream->p_next, p_fmt );
if( id->id != NULL ) if( id->id != NULL )
return id; return id;
...@@ -475,7 +471,7 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *id ) ...@@ -475,7 +471,7 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
if ( id->id ) if ( id->id )
{ {
p_sys->p_out->pf_del( p_sys->p_out, id->id ); p_stream->p_next->pf_del( p_stream->p_next, id->id );
} }
free( id ); free( id );
...@@ -498,7 +494,7 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -498,7 +494,7 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
if ( !id->b_switcher_video && !id->b_switcher_audio ) if ( !id->b_switcher_video && !id->b_switcher_audio )
{ {
return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer ); return p_stream->p_next->pf_send( p_stream->p_next, id->id, p_buffer );
} }
block_ChainAppend( &id->p_queued, p_buffer ); block_ChainAppend( &id->p_queued, p_buffer );
...@@ -557,7 +553,7 @@ static mtime_t Process( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -557,7 +553,7 @@ static mtime_t Process( sout_stream_t *p_stream, sout_stream_id_t *id,
{ {
/* Full forward */ /* Full forward */
if ( p_blocks != NULL ) if ( p_blocks != NULL )
p_sys->p_out->pf_send( p_sys->p_out, id->id, p_blocks ); p_stream->p_next->pf_send( p_stream->p_next, id->id, p_blocks );
return i_dts; return i_dts;
} }
...@@ -594,7 +590,7 @@ static mtime_t Process( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -594,7 +590,7 @@ static mtime_t Process( sout_stream_t *p_stream, sout_stream_id_t *id,
} }
if ( p_blocks_out != NULL ) if ( p_blocks_out != NULL )
p_sys->p_out->pf_send( p_sys->p_out, id->id, p_blocks_out ); p_stream->p_next->pf_send( p_stream->p_next, id->id, p_blocks_out );
return i_dts; return i_dts;
} }
......
...@@ -438,7 +438,7 @@ bool transcode_audio_add( sout_stream_t *p_stream, es_format_t *p_fmt, ...@@ -438,7 +438,7 @@ bool transcode_audio_add( sout_stream_t *p_stream, es_format_t *p_fmt,
} }
/* Open output stream */ /* Open output stream */
id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_encoder->fmt_out ); id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
id->b_transcode = true; id->b_transcode = true;
if( !id->id ) if( !id->id )
......
...@@ -68,7 +68,7 @@ int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id ) ...@@ -68,7 +68,7 @@ int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
} }
/* open output stream */ /* open output stream */
id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_encoder->fmt_out ); id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
id->b_transcode = true; id->b_transcode = true;
if( !id->id ) goto error; if( !id->id ) goto error;
...@@ -77,7 +77,7 @@ int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id ) ...@@ -77,7 +77,7 @@ int transcode_osd_new( sout_stream_t *p_stream, sout_stream_id_t *id )
{ {
msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')", msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
(char*)&id->p_decoder->fmt_out.i_codec ); (char*)&id->p_decoder->fmt_out.i_codec );
id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_decoder->fmt_out ); id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_decoder->fmt_out );
id->b_transcode = false; id->b_transcode = false;
if( !id->id ) goto error; if( !id->id ) goto error;
......
...@@ -173,7 +173,7 @@ bool transcode_spu_add( sout_stream_t *p_stream, es_format_t *p_fmt, ...@@ -173,7 +173,7 @@ bool transcode_spu_add( sout_stream_t *p_stream, es_format_t *p_fmt,
} }
/* open output stream */ /* open output stream */
id->id = sout_StreamIdAdd( p_sys->p_out, &id->p_encoder->fmt_out ); id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
id->b_transcode = true; id->b_transcode = true;
if( !id->id ) if( !id->id )
......
...@@ -258,8 +258,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -258,8 +258,7 @@ static int Open( vlc_object_t *p_this )
p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) ); p_sys = vlc_object_create( p_this, sizeof( sout_stream_sys_t ) );
p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next ); if( !p_stream->p_next )
if( !p_sys->p_out )
{ {
msg_Err( p_stream, "cannot create chain" ); msg_Err( p_stream, "cannot create chain" );
vlc_object_release( p_sys ); vlc_object_release( p_sys );
...@@ -515,8 +514,6 @@ static void Close( vlc_object_t * p_this ) ...@@ -515,8 +514,6 @@ static void Close( vlc_object_t * p_this )
sout_stream_t *p_stream = (sout_stream_t*)p_this; sout_stream_t *p_stream = (sout_stream_t*)p_this;
sout_stream_sys_t *p_sys = p_stream->p_sys; sout_stream_sys_t *p_sys = p_stream->p_sys;
sout_StreamDelete( p_sys->p_out );
free( p_sys->psz_af ); free( p_sys->psz_af );
config_ChainDestroy( p_sys->p_audio_cfg ); config_ChainDestroy( p_sys->p_audio_cfg );
...@@ -596,7 +593,7 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) ...@@ -596,7 +593,7 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
{ {
msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')", msg_Dbg( p_stream, "not transcoding a stream (fcc=`%4.4s')",
(char*)&p_fmt->i_codec ); (char*)&p_fmt->i_codec );
id->id = sout_StreamIdAdd( p_sys->p_out, p_fmt ); id->id = sout_StreamIdAdd( p_stream->p_next, p_fmt );
id->b_transcode = false; id->b_transcode = false;
success = id->id; success = id->id;
...@@ -653,7 +650,7 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *id ) ...@@ -653,7 +650,7 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
} }
} }
if( id->id ) sout_StreamIdDel( p_sys->p_out, id->id ); if( id->id ) sout_StreamIdDel( p_stream->p_next, id->id );
if( id->p_decoder ) if( id->p_decoder )
{ {
...@@ -683,7 +680,7 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -683,7 +680,7 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
if( !id->b_transcode ) if( !id->b_transcode )
{ {
if( id->id ) if( id->id )
return sout_StreamIdSend( p_sys->p_out, id->id, p_buffer ); return sout_StreamIdSend( p_stream->p_next, id->id, p_buffer );
block_Release( p_buffer ); block_Release( p_buffer );
return VLC_EGENERIC; return VLC_EGENERIC;
...@@ -727,6 +724,6 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id, ...@@ -727,6 +724,6 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
} }
if( p_out ) if( p_out )
return sout_StreamIdSend( p_sys->p_out, id->id, p_out ); return sout_StreamIdSend( p_stream->p_next, id->id, p_out );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -19,7 +19,6 @@ struct sout_stream_sys_t ...@@ -19,7 +19,6 @@ struct sout_stream_sys_t
{ {
VLC_COMMON_MEMBERS VLC_COMMON_MEMBERS
sout_stream_t *p_out;
sout_stream_id_t *id_video; sout_stream_id_t *id_video;
block_t *p_buffers; block_t *p_buffers;
vlc_mutex_t lock_out; vlc_mutex_t lock_out;
......
...@@ -482,8 +482,7 @@ static int transcode_video_encoder_open( sout_stream_t *p_stream, ...@@ -482,8 +482,7 @@ static int transcode_video_encoder_open( sout_stream_t *p_stream,
id->p_encoder->fmt_out.i_codec = id->p_encoder->fmt_out.i_codec =
vlc_fourcc_GetCodec( VIDEO_ES, id->p_encoder->fmt_out.i_codec ); vlc_fourcc_GetCodec( VIDEO_ES, id->p_encoder->fmt_out.i_codec );
id->id = sout_StreamIdAdd( p_stream->p_sys->p_out, id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
&id->p_encoder->fmt_out );
if( !id->id ) if( !id->id )
{ {
msg_Err( p_stream, "cannot add this stream" ); msg_Err( p_stream, "cannot add this stream" );
......
...@@ -367,8 +367,8 @@ sout_MuxGetStream ...@@ -367,8 +367,8 @@ sout_MuxGetStream
sout_MuxNew sout_MuxNew
sout_MuxSendBuffer sout_MuxSendBuffer
sout_SAPMethod sout_SAPMethod
sout_StreamDelete sout_StreamChainDelete
sout_StreamNew sout_StreamChainNew
sout_UpdateStatistic sout_UpdateStatistic
__spu_Create __spu_Create
spu_Destroy spu_Destroy
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
# include "config.h" # include "config.h"
#endif #endif
#include <assert.h>
#include <vlc_common.h> #include <vlc_common.h>
#include <stdlib.h> /* free() */ #include <stdlib.h> /* free() */
...@@ -53,9 +55,7 @@ ...@@ -53,9 +55,7 @@
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
#define sout_stream_url_to_chain( p, s ) \ static char *sout_stream_url_to_chain( bool, const char * );
_sout_stream_url_to_chain( VLC_OBJECT(p), s )
static char *_sout_stream_url_to_chain( vlc_object_t *, const char * );
/* /*
* Generic MRL parser * Generic MRL parser
...@@ -82,12 +82,27 @@ sout_instance_t *__sout_NewInstance( vlc_object_t *p_parent, const char *psz_des ...@@ -82,12 +82,27 @@ sout_instance_t *__sout_NewInstance( vlc_object_t *p_parent, const char *psz_des
static const char typename[] = "stream output"; static const char typename[] = "stream output";
sout_instance_t *p_sout; sout_instance_t *p_sout;
char *psz_chain;
if( psz_dest && psz_dest[0] == '#' )
{
psz_chain = strdup( &psz_dest[1] );
}
else
{
psz_chain = sout_stream_url_to_chain(
config_GetInt(p_parent, "sout-display") > 0, psz_dest );
}
if(!psz_chain)
return NULL;
/* *** Allocate descriptor *** */ /* *** Allocate descriptor *** */
p_sout = vlc_custom_create( p_parent, sizeof( *p_sout ), p_sout = vlc_custom_create( p_parent, sizeof( *p_sout ),
VLC_OBJECT_GENERIC, typename ); VLC_OBJECT_GENERIC, typename );
if( p_sout == NULL ) if( p_sout == NULL )
return NULL; return NULL;
msg_Dbg( p_sout, "using sout chain=`%s'", psz_chain );
/* *** init descriptor *** */ /* *** init descriptor *** */
p_sout->psz_sout = strdup( psz_dest ); p_sout->psz_sout = strdup( psz_dest );
p_sout->p_meta = NULL; p_sout->p_meta = NULL;
...@@ -95,38 +110,28 @@ sout_instance_t *__sout_NewInstance( vlc_object_t *p_parent, const char *psz_des ...@@ -95,38 +110,28 @@ sout_instance_t *__sout_NewInstance( vlc_object_t *p_parent, const char *psz_des
p_sout->p_sys = NULL; p_sout->p_sys = NULL;
vlc_mutex_init( &p_sout->lock ); vlc_mutex_init( &p_sout->lock );
if( psz_dest && psz_dest[0] == '#' )
{
p_sout->psz_chain = strdup( &psz_dest[1] );
}
else
{
p_sout->psz_chain = sout_stream_url_to_chain( p_sout, psz_dest );
msg_Dbg( p_sout, "using sout chain=`%s'", p_sout->psz_chain );
}
p_sout->p_stream = NULL; p_sout->p_stream = NULL;
/* attach it for inherit */ /* attach it for inherit */
vlc_object_attach( p_sout, p_parent ); vlc_object_attach( p_sout, p_parent );
/* */
var_Create( p_sout, "sout-mux-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_sout, "sout-mux-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
/* */ p_sout->p_stream = sout_StreamChainNew( p_sout, psz_chain, NULL, NULL );
p_sout->p_stream = sout_StreamNew( p_sout, p_sout->psz_chain ); if( p_sout->p_stream )
if( p_sout->p_stream == NULL )
{ {
msg_Err( p_sout, "stream chain failed for `%s'", p_sout->psz_chain ); free( psz_chain );
return p_sout;
}
FREENULL( p_sout->psz_sout ); free( psz_chain );
FREENULL( p_sout->psz_chain ); msg_Err( p_sout, "stream chain failed for `%s'", psz_chain );
vlc_object_detach( p_sout ); FREENULL( p_sout->psz_sout );
vlc_object_release( p_sout );
return NULL;
}
return p_sout; vlc_object_detach( p_sout );
vlc_object_release( p_sout );
return NULL;
} }
/***************************************************************************** /*****************************************************************************
...@@ -135,11 +140,10 @@ sout_instance_t *__sout_NewInstance( vlc_object_t *p_parent, const char *psz_des ...@@ -135,11 +140,10 @@ sout_instance_t *__sout_NewInstance( vlc_object_t *p_parent, const char *psz_des
void sout_DeleteInstance( sout_instance_t * p_sout ) void sout_DeleteInstance( sout_instance_t * p_sout )
{ {
/* remove the stream out chain */ /* remove the stream out chain */
sout_StreamDelete( p_sout->p_stream ); sout_StreamChainDelete( p_sout->p_stream, NULL );
/* *** free all string *** */ /* *** free all string *** */
FREENULL( p_sout->psz_sout ); FREENULL( p_sout->psz_sout );
FREENULL( p_sout->psz_chain );
/* delete meta */ /* delete meta */
if( p_sout->p_meta ) if( p_sout->p_meta )
...@@ -789,30 +793,51 @@ static void mrl_Clean( mrl_t *p_mrl ) ...@@ -789,30 +793,51 @@ static void mrl_Clean( mrl_t *p_mrl )
**************************************************************************** ****************************************************************************
****************************************************************************/ ****************************************************************************/
/* create a complete chain */ /* Destroy a "stream_out" module */
/* chain format: static void sout_StreamDelete( sout_stream_t *p_stream )
module{option=*:option=*}[:module{option=*:...}] {
*/ msg_Dbg( p_stream, "destroying chain... (name=%s)", p_stream->psz_name );
/* vlc_object_detach( p_stream );
* parse module{options=str, option="str "}: if( p_stream->p_module ) module_unneed( p_stream, p_stream->p_module );
* return a pointer on the rest
* XXX: psz_chain is modified FREENULL( p_stream->psz_name );
config_ChainDestroy( p_stream->p_cfg );
msg_Dbg( p_stream, "destroying chain done" );
vlc_object_release( p_stream );
}
/* Destroy a "stream_out" modules chain
*
* p_first is the first module to be destroyed in the chain
* p_last is the last module to be destroyed
* if NULL, all modules are destroyed
* if not NULL, modules following it must be destroyed separately
*/ */
void sout_StreamChainDelete(sout_stream_t *p_first, sout_stream_t *p_last)
{
if(!p_first)
return;
if(p_first != p_last)
sout_StreamChainDelete(p_first->p_next, p_last);
sout_StreamDelete(p_first);
}
/* Create a "stream_out" module, which may forward its ES to p_next module */
/* /*
* XXX name and p_cfg are used (-> do NOT free them) * XXX name and p_cfg are used (-> do NOT free them)
*/ */
sout_stream_t *sout_StreamNew( sout_instance_t *p_sout, char *psz_chain ) static sout_stream_t *sout_StreamNew( sout_instance_t *p_sout, char *psz_name,
config_chain_t *p_cfg, sout_stream_t *p_next)
{ {
static const char typename[] = "stream out"; static const char typename[] = "stream out";
sout_stream_t *p_stream; sout_stream_t *p_stream;
if( !psz_chain ) assert(psz_name);
{
msg_Err( p_sout, "invalid chain" );
return NULL;
}
p_stream = vlc_custom_create( p_sout, sizeof( *p_stream ), p_stream = vlc_custom_create( p_sout, sizeof( *p_stream ),
VLC_OBJECT_GENERIC, typename ); VLC_OBJECT_GENERIC, typename );
...@@ -821,9 +846,9 @@ sout_stream_t *sout_StreamNew( sout_instance_t *p_sout, char *psz_chain ) ...@@ -821,9 +846,9 @@ sout_stream_t *sout_StreamNew( sout_instance_t *p_sout, char *psz_chain )
p_stream->p_sout = p_sout; p_stream->p_sout = p_sout;
p_stream->p_sys = NULL; p_stream->p_sys = NULL;
p_stream->psz_name = psz_name;
p_stream->psz_next = p_stream->p_cfg = p_cfg;
config_ChainCreate( &p_stream->psz_name, &p_stream->p_cfg, psz_chain); p_stream->p_next = p_next;
msg_Dbg( p_sout, "stream=`%s'", p_stream->psz_name ); msg_Dbg( p_sout, "stream=`%s'", p_stream->psz_name );
...@@ -841,24 +866,95 @@ sout_stream_t *sout_StreamNew( sout_instance_t *p_sout, char *psz_chain ) ...@@ -841,24 +866,95 @@ sout_stream_t *sout_StreamNew( sout_instance_t *p_sout, char *psz_chain )
return p_stream; return p_stream;
} }
void sout_StreamDelete( sout_stream_t *p_stream ) /* Creates a complete "stream_out" modules chain
*
* chain format: module1{option=*:option=*}[:module2{option=*:...}]
*
* The modules are created starting from the last one and linked together
* A pointer to the last module created is stored if pp_last isn't NULL, to
* make sure sout_StreamChainDelete doesn't delete modules created in another
* place.
*
* Returns a pointer to the first module.
*/
sout_stream_t *sout_StreamChainNew(sout_instance_t *p_sout, char *psz_chain,
sout_stream_t *p_next, sout_stream_t **pp_last)
{ {
msg_Dbg( p_stream, "destroying chain... (name=%s)", p_stream->psz_name ); if(!psz_chain || !*psz_chain)
{
if(pp_last) *pp_last = NULL;
return p_next;
}
vlc_object_detach( p_stream ); char *psz_parser = strdup(psz_chain);
if( p_stream->p_module ) module_unneed( p_stream, p_stream->p_module ); if(!psz_parser)
return NULL;
FREENULL( p_stream->psz_name ); vlc_array_t cfg, name;
FREENULL( p_stream->psz_next ); vlc_array_init(&cfg);
vlc_array_init(&name);
config_ChainDestroy( p_stream->p_cfg ); /* parse chain */
while(psz_parser)
{
config_chain_t *p_cfg;
char *psz_name;
psz_chain = config_ChainCreate( &psz_name, &p_cfg, psz_parser );
free( psz_parser );
psz_parser = psz_chain;
msg_Dbg( p_stream, "destroying chain done" ); vlc_array_append(&cfg, p_cfg);
vlc_object_release( p_stream ); vlc_array_append(&name, psz_name);
}
int i = vlc_array_count(&name);
vlc_array_t module;
vlc_array_init(&module);
while(i--)
{
p_next = sout_StreamNew( p_sout, vlc_array_item_at_index(&name, i),
vlc_array_item_at_index(&cfg, i), p_next);
if(!p_next)
goto error;
if(i == vlc_array_count(&name) - 1 && pp_last)
*pp_last = p_next; /* last module created in the chain */
vlc_array_append(&module, p_next);
}
vlc_array_clear(&name);
vlc_array_clear(&cfg);
vlc_array_clear(&module);
return p_next;
error:
i++; /* last module couldn't be created */
/* destroy all modules created, starting with the last one */
int modules = vlc_array_count(&module);
while(modules--)
sout_StreamDelete(vlc_array_item_at_index(&module, modules));
vlc_array_clear(&module);
/* then destroy all names and config which weren't destroyed by
* sout_StreamDelete */
while(i--)
{
free(vlc_array_item_at_index(&name, i));
config_ChainDestroy(vlc_array_item_at_index(&cfg, i));
}
vlc_array_clear(&name);
vlc_array_clear(&cfg);
return NULL;
} }
static char *_sout_stream_url_to_chain( vlc_object_t *p_this, static char *sout_stream_url_to_chain( bool b_sout_display,
const char *psz_url ) const char *psz_url )
{ {
mrl_t mrl; mrl_t mrl;
char *psz_chain; char *psz_chain;
...@@ -904,7 +1000,7 @@ rtp: ...@@ -904,7 +1000,7 @@ rtp:
} }
/* Duplicate and wrap if sout-display is on */ /* Duplicate and wrap if sout-display is on */
if (psz_chain && (config_GetInt( p_this, "sout-display" ) > 0)) if (psz_chain && b_sout_display)
{ {
char *tmp; char *tmp;
if (asprintf (&tmp, "duplicate{dst=display,dst=%s}", tmp) == -1) if (asprintf (&tmp, "duplicate{dst=display,dst=%s}", tmp) == -1)
......
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