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