d4492f32d91a0b72c79113dfc4d87dd0b05898b4
[vlc.git] / src / stream_output / stream_output.c
1 /*****************************************************************************
2  * stream_output.c : stream output module
3  *****************************************************************************
4  * Copyright (C) 2002-2007 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Laurent Aimar <fenrir@via.ecp.fr>
9  *          Eric Petit <titer@videolan.org>
10  *
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation; either version 2.1 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <assert.h>
35
36 #include <vlc_common.h>
37
38 #include <stdlib.h>                                                /* free() */
39 #include <stdio.h>                                              /* sprintf() */
40 #include <string.h>
41
42 #include <vlc_sout.h>
43
44 #include "stream_output.h"
45
46 #include <vlc_meta.h>
47 #include <vlc_block.h>
48 #include <vlc_codec.h>
49 #include <vlc_modules.h>
50
51 #include "input/input_interface.h"
52
53 #undef DEBUG_BUFFER
54 /*****************************************************************************
55  * Local prototypes
56  *****************************************************************************/
57 static char *sout_stream_url_to_chain( bool, const char * );
58
59 /*
60  * Generic MRL parser
61  *
62  */
63
64 typedef struct
65 {
66     char *psz_access;
67     char *psz_way;
68     char *psz_name;
69 } mrl_t;
70
71 /* mrl_Parse: parse psz_mrl and fill p_mrl */
72 static int  mrl_Parse( mrl_t *p_mrl, const char *psz_mrl );
73 /* mrl_Clean: clean p_mrl  after a call to mrl_Parse */
74 static void mrl_Clean( mrl_t *p_mrl );
75
76 #undef sout_NewInstance
77
78 /*****************************************************************************
79  * sout_NewInstance: creates a new stream output instance
80  *****************************************************************************/
81 sout_instance_t *sout_NewInstance( vlc_object_t *p_parent, const char *psz_dest )
82 {
83     sout_instance_t *p_sout;
84     char *psz_chain;
85
86     assert( psz_dest != NULL );
87
88     if( psz_dest[0] == '#' )
89     {
90         psz_chain = strdup( &psz_dest[1] );
91     }
92     else
93     {
94         psz_chain = sout_stream_url_to_chain(
95             var_InheritBool(p_parent, "sout-display"), psz_dest );
96     }
97     if(!psz_chain)
98         return NULL;
99
100     /* *** Allocate descriptor *** */
101     p_sout = vlc_custom_create( p_parent, sizeof( *p_sout ), "stream output" );
102     if( p_sout == NULL )
103     {
104         free( psz_chain );
105         return NULL;
106     }
107
108     msg_Dbg( p_sout, "using sout chain=`%s'", psz_chain );
109
110     /* *** init descriptor *** */
111     p_sout->psz_sout    = strdup( psz_dest );
112     p_sout->i_out_pace_nocontrol = 0;
113
114     vlc_mutex_init( &p_sout->lock );
115     p_sout->p_stream = NULL;
116
117     var_Create( p_sout, "sout-mux-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
118
119     p_sout->p_stream = sout_StreamChainNew( p_sout, psz_chain, NULL, NULL );
120     if( p_sout->p_stream )
121     {
122         free( psz_chain );
123         return p_sout;
124     }
125
126     msg_Err( p_sout, "stream chain failed for `%s'", psz_chain );
127     free( psz_chain );
128
129     FREENULL( p_sout->psz_sout );
130
131     vlc_mutex_destroy( &p_sout->lock );
132     vlc_object_release( p_sout );
133     return NULL;
134 }
135
136 /*****************************************************************************
137  * sout_DeleteInstance: delete a previously allocated instance
138  *****************************************************************************/
139 void sout_DeleteInstance( sout_instance_t * p_sout )
140 {
141     /* remove the stream out chain */
142     sout_StreamChainDelete( p_sout->p_stream, NULL );
143
144     /* *** free all string *** */
145     FREENULL( p_sout->psz_sout );
146
147     vlc_mutex_destroy( &p_sout->lock );
148
149     /* *** free structure *** */
150     vlc_object_release( p_sout );
151 }
152
153 /*****************************************************************************
154  * Packetizer/Input
155  *****************************************************************************/
156 sout_packetizer_input_t *sout_InputNew( sout_instance_t *p_sout,
157                                         const es_format_t *p_fmt )
158 {
159     sout_packetizer_input_t *p_input;
160
161     /* *** create a packetizer input *** */
162     if( !p_fmt->i_codec || !(p_input = malloc(sizeof(sout_packetizer_input_t))) )
163         return NULL;
164
165     p_input->p_sout = p_sout;
166
167     msg_Dbg( p_sout, "adding a new sout input for `%4.4s` (sout_input: %p)",
168              (char*) &p_fmt->i_codec, (void *)p_input );
169
170     /* *** add it to the stream chain */
171     vlc_mutex_lock( &p_sout->lock );
172     p_input->id = p_sout->p_stream->pf_add( p_sout->p_stream, p_fmt );
173     vlc_mutex_unlock( &p_sout->lock );
174
175     if( p_input->id == NULL )
176     {
177         msg_Warn( p_sout, "new sout input failed (sout_input: %p)",
178                  (void *)p_input );
179         free( p_input );
180         p_input = NULL;
181     }
182
183     return( p_input );
184 }
185
186 /*****************************************************************************
187  *
188  *****************************************************************************/
189 int sout_InputDelete( sout_packetizer_input_t *p_input )
190 {
191     sout_instance_t     *p_sout = p_input->p_sout;
192
193     msg_Dbg( p_sout, "removing a sout input (sout_input: %p)",
194              (void *)p_input );
195
196     vlc_mutex_lock( &p_sout->lock );
197     p_sout->p_stream->pf_del( p_sout->p_stream, p_input->id );
198     vlc_mutex_unlock( &p_sout->lock );
199
200     free( p_input );
201
202     return( VLC_SUCCESS);
203 }
204
205 bool sout_InputIsEmpty( sout_packetizer_input_t *p_input )
206 {
207     sout_instance_t *p_sout = p_input->p_sout;
208     bool b;
209
210     vlc_mutex_lock( &p_sout->lock );
211     if( sout_StreamControl( p_sout->p_stream, SOUT_STREAM_EMPTY, &b ) != VLC_SUCCESS )
212         b = true;
213     vlc_mutex_unlock( &p_sout->lock );
214     return b;
215 }
216
217 void sout_InputFlush( sout_packetizer_input_t *p_input )
218 {
219     sout_instance_t     *p_sout = p_input->p_sout;
220
221     vlc_mutex_lock( &p_sout->lock );
222     sout_StreamFlush( p_sout->p_stream, p_input->id );
223     vlc_mutex_unlock( &p_sout->lock );
224 }
225
226 /*****************************************************************************
227  *
228  *****************************************************************************/
229 int sout_InputSendBuffer( sout_packetizer_input_t *p_input,
230                           block_t *p_buffer )
231 {
232     sout_instance_t     *p_sout = p_input->p_sout;
233     int                 i_ret;
234
235     vlc_mutex_lock( &p_sout->lock );
236     i_ret = p_sout->p_stream->pf_send( p_sout->p_stream,
237                                        p_input->id, p_buffer );
238     vlc_mutex_unlock( &p_sout->lock );
239
240     return i_ret;
241 }
242
243 #undef sout_AccessOutNew
244 /*****************************************************************************
245  * sout_AccessOutNew: allocate a new access out
246  *****************************************************************************/
247 sout_access_out_t *sout_AccessOutNew( vlc_object_t *p_sout,
248                                       const char *psz_access, const char *psz_name )
249 {
250     sout_access_out_t *p_access;
251     char              *psz_next;
252
253     p_access = vlc_custom_create( p_sout, sizeof( *p_access ), "access out" );
254     if( !p_access )
255         return NULL;
256
257     psz_next = config_ChainCreate( &p_access->psz_access, &p_access->p_cfg,
258                                    psz_access );
259     free( psz_next );
260     p_access->psz_path   = strdup( psz_name ? psz_name : "" );
261     p_access->p_sys      = NULL;
262     p_access->pf_seek    = NULL;
263     p_access->pf_read    = NULL;
264     p_access->pf_write   = NULL;
265     p_access->pf_control = NULL;
266     p_access->p_module   = NULL;
267
268     p_access->p_module   =
269         module_need( p_access, "sout access", p_access->psz_access, true );
270
271     if( !p_access->p_module )
272     {
273         free( p_access->psz_access );
274         free( p_access->psz_path );
275         vlc_object_release( p_access );
276         return( NULL );
277     }
278
279     return p_access;
280 }
281 /*****************************************************************************
282  * sout_AccessDelete: delete an access out
283  *****************************************************************************/
284 void sout_AccessOutDelete( sout_access_out_t *p_access )
285 {
286     if( p_access->p_module )
287     {
288         module_unneed( p_access, p_access->p_module );
289     }
290     free( p_access->psz_access );
291
292     config_ChainDestroy( p_access->p_cfg );
293
294     free( p_access->psz_path );
295
296     vlc_object_release( p_access );
297 }
298
299 /*****************************************************************************
300  * sout_AccessSeek:
301  *****************************************************************************/
302 int sout_AccessOutSeek( sout_access_out_t *p_access, off_t i_pos )
303 {
304     return p_access->pf_seek( p_access, i_pos );
305 }
306
307 /*****************************************************************************
308  * sout_AccessRead:
309  *****************************************************************************/
310 ssize_t sout_AccessOutRead( sout_access_out_t *p_access, block_t *p_buffer )
311 {
312     return( p_access->pf_read ?
313             p_access->pf_read( p_access, p_buffer ) : VLC_EGENERIC );
314 }
315
316 /*****************************************************************************
317  * sout_AccessWrite:
318  *****************************************************************************/
319 ssize_t sout_AccessOutWrite( sout_access_out_t *p_access, block_t *p_buffer )
320 {
321     return p_access->pf_write( p_access, p_buffer );
322 }
323
324 /**
325  * sout_AccessOutControl
326  */
327 int sout_AccessOutControl (sout_access_out_t *access, int query, ...)
328 {
329     va_list ap;
330     int ret;
331
332     va_start (ap, query);
333     if (access->pf_control)
334         ret = access->pf_control (access, query, ap);
335     else
336         ret = VLC_EGENERIC;
337     va_end (ap);
338     return ret;
339 }
340
341 /*****************************************************************************
342  * sout_MuxNew: create a new mux
343  *****************************************************************************/
344 sout_mux_t * sout_MuxNew( sout_instance_t *p_sout, const char *psz_mux,
345                           sout_access_out_t *p_access )
346 {
347     sout_mux_t *p_mux;
348     char       *psz_next;
349
350     p_mux = vlc_custom_create( p_sout, sizeof( *p_mux ), "mux" );
351     if( p_mux == NULL )
352         return NULL;
353
354     p_mux->p_sout = p_sout;
355     psz_next = config_ChainCreate( &p_mux->psz_mux, &p_mux->p_cfg, psz_mux );
356     free( psz_next );
357
358     p_mux->p_access     = p_access;
359     p_mux->pf_control   = NULL;
360     p_mux->pf_addstream = NULL;
361     p_mux->pf_delstream = NULL;
362     p_mux->pf_mux       = NULL;
363     p_mux->i_nb_inputs  = 0;
364     p_mux->pp_inputs    = NULL;
365
366     p_mux->p_sys        = NULL;
367     p_mux->p_module     = NULL;
368
369     p_mux->b_add_stream_any_time = false;
370     p_mux->b_waiting_stream = true;
371     p_mux->i_add_stream_start = -1;
372
373     p_mux->p_module =
374         module_need( p_mux, "sout mux", p_mux->psz_mux, true );
375
376     if( p_mux->p_module == NULL )
377     {
378         FREENULL( p_mux->psz_mux );
379
380         vlc_object_release( p_mux );
381         return NULL;
382     }
383
384     /* *** probe mux capacity *** */
385     if( p_mux->pf_control )
386     {
387         int b_answer = false;
388
389         if( sout_MuxControl( p_mux, MUX_CAN_ADD_STREAM_WHILE_MUXING,
390                              &b_answer ) )
391         {
392             b_answer = false;
393         }
394
395         if( b_answer )
396         {
397             msg_Dbg( p_sout, "muxer support adding stream at any time" );
398             p_mux->b_add_stream_any_time = true;
399             p_mux->b_waiting_stream = false;
400
401             /* If we control the output pace then it's better to wait before
402              * starting muxing (generates better streams/files). */
403             if( !p_sout->i_out_pace_nocontrol )
404             {
405                 b_answer = true;
406             }
407             else if( sout_MuxControl( p_mux, MUX_GET_ADD_STREAM_WAIT,
408                                       &b_answer ) )
409             {
410                 b_answer = false;
411             }
412
413             if( b_answer )
414             {
415                 msg_Dbg( p_sout, "muxer prefers to wait for all ES before "
416                          "starting to mux" );
417                 p_mux->b_waiting_stream = true;
418             }
419         }
420     }
421
422     return p_mux;
423 }
424
425 /*****************************************************************************
426  * sout_MuxDelete:
427  *****************************************************************************/
428 void sout_MuxDelete( sout_mux_t *p_mux )
429 {
430     if( p_mux->p_module )
431     {
432         module_unneed( p_mux, p_mux->p_module );
433     }
434     free( p_mux->psz_mux );
435
436     config_ChainDestroy( p_mux->p_cfg );
437
438     vlc_object_release( p_mux );
439 }
440
441 /*****************************************************************************
442  * sout_MuxAddStream:
443  *****************************************************************************/
444 sout_input_t *sout_MuxAddStream( sout_mux_t *p_mux, const es_format_t *p_fmt )
445 {
446     sout_input_t *p_input;
447
448     if( !p_mux->b_add_stream_any_time && !p_mux->b_waiting_stream )
449     {
450         msg_Err( p_mux, "cannot add a new stream (unsupported while muxing "
451                         "to this format). You can try increasing sout-mux-caching value" );
452         return NULL;
453     }
454
455     msg_Dbg( p_mux, "adding a new input" );
456
457     /* create a new sout input */
458     p_input = malloc( sizeof( sout_input_t ) );
459     if( !p_input )
460         return NULL;
461
462     // FIXME: remove either fmt or p_fmt...
463     es_format_Copy( &p_input->fmt, p_fmt );
464     p_input->p_fmt = &p_input->fmt;
465
466     p_input->p_fifo = block_FifoNew();
467     p_input->p_sys  = NULL;
468
469     TAB_APPEND( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input );
470     if( p_mux->pf_addstream( p_mux, p_input ) < 0 )
471     {
472         msg_Err( p_mux, "cannot add this stream" );
473         TAB_REMOVE( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input );
474         block_FifoRelease( p_input->p_fifo );
475         es_format_Clean( &p_input->fmt );
476         free( p_input );
477         return NULL;
478     }
479
480     return p_input;
481 }
482
483 /*****************************************************************************
484  * sout_MuxDeleteStream:
485  *****************************************************************************/
486 void sout_MuxDeleteStream( sout_mux_t *p_mux, sout_input_t *p_input )
487 {
488     int i_index;
489
490     if( p_mux->b_waiting_stream
491      && block_FifoCount( p_input->p_fifo ) > 0 )
492     {
493         /* We stop waiting, and call the muxer for taking care of the data
494          * before we remove this es */
495         p_mux->b_waiting_stream = false;
496         p_mux->pf_mux( p_mux );
497     }
498
499     TAB_FIND( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input, i_index );
500     if( i_index >= 0 )
501     {
502         p_mux->pf_delstream( p_mux, p_input );
503
504         /* remove the entry */
505         TAB_REMOVE( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input );
506
507         if( p_mux->i_nb_inputs == 0 )
508         {
509             msg_Warn( p_mux, "no more input streams for this mux" );
510         }
511
512         block_FifoRelease( p_input->p_fifo );
513         es_format_Clean( &p_input->fmt );
514         free( p_input );
515     }
516 }
517
518 /*****************************************************************************
519  * sout_MuxSendBuffer:
520  *****************************************************************************/
521 int sout_MuxSendBuffer( sout_mux_t *p_mux, sout_input_t *p_input,
522                          block_t *p_buffer )
523 {
524     mtime_t i_dts = p_buffer->i_dts;
525     block_FifoPut( p_input->p_fifo, p_buffer );
526
527     if( p_mux->p_sout->i_out_pace_nocontrol )
528     {
529         mtime_t current_date = mdate();
530         if ( current_date > i_dts )
531             msg_Warn( p_mux, "late buffer for mux input (%"PRId64")",
532                       current_date - i_dts );
533     }
534
535     if( p_mux->b_waiting_stream )
536     {
537         const int64_t i_caching = var_GetInteger( p_mux->p_sout, "sout-mux-caching" ) * INT64_C(1000);
538
539         if( p_mux->i_add_stream_start < 0 )
540             p_mux->i_add_stream_start = i_dts;
541
542         /* Wait until we have enough data before muxing */
543         if( p_mux->i_add_stream_start < 0 ||
544             i_dts < p_mux->i_add_stream_start + i_caching )
545             return VLC_SUCCESS;
546         p_mux->b_waiting_stream = false;
547     }
548     return p_mux->pf_mux( p_mux );
549 }
550
551 void sout_MuxFlush( sout_mux_t *p_mux, sout_input_t *p_input )
552 {
553     VLC_UNUSED(p_mux);
554     block_FifoEmpty( p_input->p_fifo );
555 }
556
557 /*****************************************************************************
558  * sout_MuxGetStream: find stream to be muxed
559  *****************************************************************************/
560 int sout_MuxGetStream( sout_mux_t *p_mux, unsigned i_blocks, mtime_t *pi_dts )
561 {
562     mtime_t i_dts = 0;
563     int     i_stream = -1;
564
565     assert( i_blocks > 0 );
566
567     for( int i = 0; i < p_mux->i_nb_inputs; i++ )
568     {
569         sout_input_t *p_input = p_mux->pp_inputs[i];
570         block_t *p_data;
571
572         if( block_FifoCount( p_input->p_fifo ) < i_blocks )
573         {
574             if( (!p_mux->b_add_stream_any_time) &&
575                 (p_input->p_fmt->i_cat != SPU_ES ) )
576             {
577                 return -1;
578             }
579             /* FIXME: SPU muxing */
580             continue;
581         }
582
583         p_data = block_FifoShow( p_input->p_fifo );
584         if( i_stream < 0 || p_data->i_dts < i_dts )
585         {
586             i_stream = i;
587             i_dts    = p_data->i_dts;
588         }
589     }
590
591     if( pi_dts ) *pi_dts = i_dts;
592
593     return i_stream;
594 }
595
596
597 /*****************************************************************************
598  *
599  *****************************************************************************/
600 static int mrl_Parse( mrl_t *p_mrl, const char *psz_mrl )
601 {
602     char * psz_dup = strdup( psz_mrl );
603     char * psz_parser = psz_dup;
604     const char * psz_access;
605     const char * psz_way;
606     char * psz_name;
607
608     /* *** first parse psz_dest */
609     while( *psz_parser && *psz_parser != ':' )
610     {
611         if( *psz_parser == '{' )
612         {
613             while( *psz_parser && *psz_parser != '}' )
614             {
615                 psz_parser++;
616             }
617             if( *psz_parser )
618             {
619                 psz_parser++;
620             }
621         }
622         else
623         {
624             psz_parser++;
625         }
626     }
627 #if defined( _WIN32 ) || defined( __OS2__ )
628     if( psz_parser - psz_dup == 1 )
629     {
630         /* msg_Warn( p_sout, "drive letter %c: found in source string",
631                           *psz_dup ) ; */
632         *psz_parser = '\0';
633     }
634 #endif
635
636     if( !*psz_parser )
637     {
638         psz_access = psz_way = "";
639         psz_name = psz_dup;
640     }
641     else
642     {
643         *psz_parser++ = '\0';
644
645         /* let's skip '//' */
646         if( psz_parser[0] == '/' && psz_parser[1] == '/' )
647         {
648             psz_parser += 2 ;
649         }
650
651         psz_name = psz_parser ;
652
653         /* Come back to parse the access and mux plug-ins */
654         psz_parser = psz_dup;
655
656         if( !*psz_parser )
657         {
658             /* No access */
659             psz_access = "";
660         }
661         else if( *psz_parser == '/' )
662         {
663             /* No access */
664             psz_access = "";
665             psz_parser++;
666         }
667         else
668         {
669             psz_access = psz_parser;
670
671             while( *psz_parser && *psz_parser != '/' )
672             {
673                 if( *psz_parser == '{' )
674                 {
675                     while( *psz_parser && *psz_parser != '}' )
676                     {
677                         psz_parser++;
678                     }
679                     if( *psz_parser )
680                     {
681                         psz_parser++;
682                     }
683                 }
684                 else
685                 {
686                     psz_parser++;
687                 }
688             }
689
690             if( *psz_parser == '/' )
691             {
692                 *psz_parser++ = '\0';
693             }
694         }
695
696         if( !*psz_parser )
697         {
698             /* No mux */
699             psz_way = "";
700         }
701         else
702         {
703             psz_way = psz_parser;
704         }
705     }
706
707     p_mrl->psz_access = strdup( psz_access );
708     p_mrl->psz_way    = strdup( psz_way );
709     p_mrl->psz_name   = strdup( psz_name );
710
711     free( psz_dup );
712     return( VLC_SUCCESS );
713 }
714
715
716 /* mrl_Clean: clean p_mrl  after a call to mrl_Parse */
717 static void mrl_Clean( mrl_t *p_mrl )
718 {
719     FREENULL( p_mrl->psz_access );
720     FREENULL( p_mrl->psz_way );
721     FREENULL( p_mrl->psz_name );
722 }
723
724
725 /****************************************************************************
726  ****************************************************************************
727  **
728  **
729  **
730  ****************************************************************************
731  ****************************************************************************/
732
733 /* Destroy a "stream_out" module */
734 static void sout_StreamDelete( sout_stream_t *p_stream )
735 {
736     sout_instance_t *p_sout = (sout_instance_t *)(p_stream->obj.parent);
737
738     msg_Dbg( p_stream, "destroying chain... (name=%s)", p_stream->psz_name );
739
740     p_sout->i_out_pace_nocontrol -= p_stream->pace_nocontrol;
741
742     if( p_stream->p_module != NULL )
743         module_unneed( p_stream, p_stream->p_module );
744
745     FREENULL( p_stream->psz_name );
746
747     config_ChainDestroy( p_stream->p_cfg );
748
749     msg_Dbg( p_stream, "destroying chain done" );
750     vlc_object_release( p_stream );
751 }
752
753 /* Destroy a "stream_out" modules chain
754  *
755  * p_first is the first module to be destroyed in the chain
756  * p_last is the last module to be destroyed
757  *  if NULL, all modules are destroyed
758  *  if not NULL, modules following it must be destroyed separately
759  */
760 void sout_StreamChainDelete(sout_stream_t *p_first, sout_stream_t *p_last)
761 {
762     while(p_first != NULL)
763     {
764         sout_stream_t *p_next = p_first->p_next;
765
766         sout_StreamDelete(p_first);
767         if(p_first == p_last)
768            break;
769         p_first = p_next;
770     }
771 }
772
773 /* Create a "stream_out" module, which may forward its ES to p_next module */
774 /*
775  * XXX name and p_cfg are used (-> do NOT free them)
776  */
777 static sout_stream_t *sout_StreamNew( sout_instance_t *p_sout, char *psz_name,
778                                config_chain_t *p_cfg, sout_stream_t *p_next)
779 {
780     sout_stream_t *p_stream;
781
782     assert(psz_name);
783
784     p_stream = vlc_custom_create( p_sout, sizeof( *p_stream ), "stream out" );
785     if( !p_stream )
786         return NULL;
787
788     p_stream->p_sout   = p_sout;
789     p_stream->psz_name = psz_name;
790     p_stream->p_cfg    = p_cfg;
791     p_stream->p_next   = p_next;
792     p_stream->pf_flush = NULL;
793     p_stream->pf_control = NULL;
794     p_stream->pace_nocontrol = false;
795     p_stream->p_sys = NULL;
796
797     msg_Dbg( p_sout, "stream=`%s'", p_stream->psz_name );
798
799     p_stream->p_module =
800         module_need( p_stream, "sout stream", p_stream->psz_name, true );
801
802     if( !p_stream->p_module )
803     {
804         /* those must be freed by the caller if creation failed */
805         p_stream->psz_name = NULL;
806         p_stream->p_cfg = NULL;
807
808         sout_StreamDelete( p_stream );
809         return NULL;
810     }
811
812     p_sout->i_out_pace_nocontrol += p_stream->pace_nocontrol;
813     return p_stream;
814 }
815
816 /* Creates a complete "stream_out" modules chain
817  *
818  *  chain format: module1{option=*:option=*}[:module2{option=*:...}]
819  *
820  *  The modules are created starting from the last one and linked together
821  *  A pointer to the last module created is stored if pp_last isn't NULL, to
822  *  make sure sout_StreamChainDelete doesn't delete modules created in another
823  *  place.
824  *
825  *  Returns a pointer to the first module.
826  */
827 sout_stream_t *sout_StreamChainNew(sout_instance_t *p_sout, const char *psz_chain,
828                                 sout_stream_t *p_next, sout_stream_t **pp_last)
829 {
830     if(!psz_chain || !*psz_chain)
831     {
832         if(pp_last) *pp_last = NULL;
833         return p_next;
834     }
835
836     char *psz_parser = strdup(psz_chain);
837     if(!psz_parser)
838         return NULL;
839
840     vlc_array_t cfg, name;
841     vlc_array_init(&cfg);
842     vlc_array_init(&name);
843
844     /* parse chain */
845     while(psz_parser)
846     {
847         config_chain_t *p_cfg;
848         char *psz_name;
849         char *psz_rest_chain = config_ChainCreate( &psz_name, &p_cfg, psz_parser );
850         free( psz_parser );
851         psz_parser = psz_rest_chain;
852
853         vlc_array_append(&cfg, p_cfg);
854         vlc_array_append(&name, psz_name);
855     }
856
857     size_t i = vlc_array_count(&name);
858     vlc_array_t module;
859     vlc_array_init(&module);
860     while(i--)
861     {
862         p_next = sout_StreamNew( p_sout, vlc_array_item_at_index(&name, i),
863             vlc_array_item_at_index(&cfg, i), p_next);
864
865         if(!p_next)
866             goto error;
867
868         if(i == vlc_array_count(&name) - 1 && pp_last)
869             *pp_last = p_next;   /* last module created in the chain */
870
871         vlc_array_append(&module, p_next);
872     }
873
874     vlc_array_clear(&name);
875     vlc_array_clear(&cfg);
876     vlc_array_clear(&module);
877
878     return p_next;
879
880 error:
881
882     i++;    /* last module couldn't be created */
883
884     /* destroy all modules created, starting with the last one */
885     int modules = vlc_array_count(&module);
886     while(modules--)
887         sout_StreamDelete(vlc_array_item_at_index(&module, modules));
888     vlc_array_clear(&module);
889
890     /* then destroy all names and config which weren't destroyed by
891      * sout_StreamDelete */
892     while(i--)
893     {
894         free(vlc_array_item_at_index(&name, i));
895         config_ChainDestroy(vlc_array_item_at_index(&cfg, i));
896     }
897     vlc_array_clear(&name);
898     vlc_array_clear(&cfg);
899
900     return NULL;
901 }
902
903 static char *sout_stream_url_to_chain( bool b_sout_display,
904                                        const char *psz_url )
905 {
906     mrl_t       mrl;
907     char        *psz_chain;
908
909     mrl_Parse( &mrl, psz_url );
910
911     /* Check if the URLs goes to #rtp - otherwise we'll use #standard */
912     static const char rtplist[] = "dccp\0sctp\0tcp\0udplite\0";
913     for (const char *a = rtplist; *a; a += strlen (a) + 1)
914         if (strcmp (a, mrl.psz_access) == 0)
915             goto rtp;
916
917     if (strcmp (mrl.psz_access, "rtp") == 0)
918     {
919         char *port;
920         /* For historical reasons, rtp:// means RTP over UDP */
921         strcpy (mrl.psz_access, "udp");
922 rtp:
923         if (mrl.psz_name[0] == '[')
924         {
925             port = strstr (mrl.psz_name, "]:");
926             if (port != NULL)
927                 port++;
928         }
929         else
930             port = strchr (mrl.psz_name, ':');
931         if (port != NULL)
932             *port++ = '\0'; /* erase ':' */
933
934         if (asprintf (&psz_chain,
935                       "rtp{mux=\"%s\",proto=\"%s\",dst=\"%s%s%s\"}",
936                       mrl.psz_way, mrl.psz_access, mrl.psz_name,
937                       port ? "\",port=\"" : "", port ? port : "") == -1)
938             psz_chain = NULL;
939     }
940     else
941     {
942         /* Convert the URL to a basic standard sout chain */
943         if (asprintf (&psz_chain,
944                       "standard{mux=\"%s\",access=\"%s\",dst=\"%s\"}",
945                       mrl.psz_way, mrl.psz_access, mrl.psz_name) == -1)
946             psz_chain = NULL;
947     }
948
949     /* Duplicate and wrap if sout-display is on */
950     if (psz_chain && b_sout_display)
951     {
952         char *tmp;
953         if (asprintf (&tmp, "duplicate{dst=display,dst=%s}", psz_chain) == -1)
954             tmp = NULL;
955         free (psz_chain);
956         psz_chain = tmp;
957     }
958
959     mrl_Clean( &mrl );
960     return psz_chain;
961 }
962
963 #undef sout_EncoderCreate
964 encoder_t *sout_EncoderCreate( vlc_object_t *p_this )
965 {
966     return vlc_custom_create( p_this, sizeof( encoder_t ), "encoder" );
967 }