]> git.sesse.net Git - vlc/blob - src/stream_output/stream_output.c
httplive: downgrade most of the messages from Info to Debug
[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 void sout_MuxSendBuffer( sout_mux_t *p_mux, sout_input_t *p_input,
516                          block_t *p_buffer )
517 {
518     block_FifoPut( p_input->p_fifo, p_buffer );
519
520     if( p_mux->p_sout->i_out_pace_nocontrol )
521     {
522         mtime_t current_date = mdate();
523         if ( current_date > p_buffer->i_dts )
524             msg_Warn( p_mux, "late buffer for mux input (%"PRId64")",
525                       current_date - p_buffer->i_dts );
526     }
527
528     if( p_mux->b_waiting_stream )
529     {
530         const int64_t i_caching = var_GetInteger( p_mux->p_sout, "sout-mux-caching" ) * INT64_C(1000);
531
532         if( p_mux->i_add_stream_start < 0 )
533             p_mux->i_add_stream_start = p_buffer->i_dts;
534
535         /* Wait until we have enought data before muxing */
536         if( p_mux->i_add_stream_start < 0 ||
537             p_buffer->i_dts < p_mux->i_add_stream_start + i_caching )
538             return;
539         p_mux->b_waiting_stream = false;
540     }
541     p_mux->pf_mux( p_mux );
542 }
543
544
545 /*****************************************************************************
546  * sout_MuxGetStream: find stream to be muxed
547  *****************************************************************************/
548 int sout_MuxGetStream( sout_mux_t *p_mux, int i_blocks, mtime_t *pi_dts )
549 {
550     mtime_t i_dts = 0;
551     int     i_stream = -1;
552
553     for( int i = 0; i < p_mux->i_nb_inputs; i++ )
554     {
555         sout_input_t *p_input = p_mux->pp_inputs[i];
556         block_t *p_data;
557
558         if( block_FifoCount( p_input->p_fifo ) < i_blocks )
559         {
560             if( p_input->p_fmt->i_cat != SPU_ES )
561             {
562                 return -1;
563             }
564             /* FIXME: SPU muxing */
565             continue;
566         }
567
568         p_data = block_FifoShow( p_input->p_fifo );
569         if( i_stream < 0 || p_data->i_dts < i_dts )
570         {
571             i_stream = i;
572             i_dts    = p_data->i_dts;
573         }
574     }
575
576     if( pi_dts ) *pi_dts = i_dts;
577
578     return i_stream;
579 }
580
581
582 /*****************************************************************************
583  *
584  *****************************************************************************/
585 static int mrl_Parse( mrl_t *p_mrl, const char *psz_mrl )
586 {
587     char * psz_dup = strdup( psz_mrl );
588     char * psz_parser = psz_dup;
589     const char * psz_access;
590     const char * psz_way;
591     char * psz_name;
592
593     /* *** first parse psz_dest */
594     while( *psz_parser && *psz_parser != ':' )
595     {
596         if( *psz_parser == '{' )
597         {
598             while( *psz_parser && *psz_parser != '}' )
599             {
600                 psz_parser++;
601             }
602             if( *psz_parser )
603             {
604                 psz_parser++;
605             }
606         }
607         else
608         {
609             psz_parser++;
610         }
611     }
612 #if defined( _WIN32 ) || defined( __OS2__ )
613     if( psz_parser - psz_dup == 1 )
614     {
615         /* msg_Warn( p_sout, "drive letter %c: found in source string",
616                           *psz_dup ) ; */
617         psz_parser = "";
618     }
619 #endif
620
621     if( !*psz_parser )
622     {
623         psz_access = psz_way = "";
624         psz_name = psz_dup;
625     }
626     else
627     {
628         *psz_parser++ = '\0';
629
630         /* let's skip '//' */
631         if( psz_parser[0] == '/' && psz_parser[1] == '/' )
632         {
633             psz_parser += 2 ;
634         }
635
636         psz_name = psz_parser ;
637
638         /* Come back to parse the access and mux plug-ins */
639         psz_parser = psz_dup;
640
641         if( !*psz_parser )
642         {
643             /* No access */
644             psz_access = "";
645         }
646         else if( *psz_parser == '/' )
647         {
648             /* No access */
649             psz_access = "";
650             psz_parser++;
651         }
652         else
653         {
654             psz_access = psz_parser;
655
656             while( *psz_parser && *psz_parser != '/' )
657             {
658                 if( *psz_parser == '{' )
659                 {
660                     while( *psz_parser && *psz_parser != '}' )
661                     {
662                         psz_parser++;
663                     }
664                     if( *psz_parser )
665                     {
666                         psz_parser++;
667                     }
668                 }
669                 else
670                 {
671                     psz_parser++;
672                 }
673             }
674
675             if( *psz_parser == '/' )
676             {
677                 *psz_parser++ = '\0';
678             }
679         }
680
681         if( !*psz_parser )
682         {
683             /* No mux */
684             psz_way = "";
685         }
686         else
687         {
688             psz_way = psz_parser;
689         }
690     }
691
692     p_mrl->psz_access = strdup( psz_access );
693     p_mrl->psz_way    = strdup( psz_way );
694     p_mrl->psz_name   = strdup( psz_name );
695
696     free( psz_dup );
697     return( VLC_SUCCESS );
698 }
699
700
701 /* mrl_Clean: clean p_mrl  after a call to mrl_Parse */
702 static void mrl_Clean( mrl_t *p_mrl )
703 {
704     FREENULL( p_mrl->psz_access );
705     FREENULL( p_mrl->psz_way );
706     FREENULL( p_mrl->psz_name );
707 }
708
709
710 /****************************************************************************
711  ****************************************************************************
712  **
713  **
714  **
715  ****************************************************************************
716  ****************************************************************************/
717
718 /* Destroy a "stream_out" module */
719 static void sout_StreamDelete( sout_stream_t *p_stream )
720 {
721     sout_instance_t *p_sout = (sout_instance_t *)(p_stream->p_parent);
722
723     msg_Dbg( p_stream, "destroying chain... (name=%s)", p_stream->psz_name );
724
725     p_sout->i_out_pace_nocontrol -= p_stream->pace_nocontrol;
726
727     if( p_stream->p_module != NULL )
728         module_unneed( p_stream, p_stream->p_module );
729
730     FREENULL( p_stream->psz_name );
731
732     config_ChainDestroy( p_stream->p_cfg );
733
734     msg_Dbg( p_stream, "destroying chain done" );
735     vlc_object_release( p_stream );
736 }
737
738 /* Destroy a "stream_out" modules chain
739  *
740  * p_first is the first module to be destroyed in the chain
741  * p_last is the last module to be destroyed
742  *  if NULL, all modules are destroyed
743  *  if not NULL, modules following it must be destroyed separately
744  */
745 void sout_StreamChainDelete(sout_stream_t *p_first, sout_stream_t *p_last)
746 {
747     while(p_first != NULL)
748     {
749         sout_stream_t *p_next = p_first->p_next;
750
751         sout_StreamDelete(p_first);
752         if(p_first == p_last)
753            break;
754         p_first = p_next;
755     }
756 }
757
758 /* Create a "stream_out" module, which may forward its ES to p_next module */
759 /*
760  * XXX name and p_cfg are used (-> do NOT free them)
761  */
762 static sout_stream_t *sout_StreamNew( sout_instance_t *p_sout, char *psz_name,
763                                config_chain_t *p_cfg, sout_stream_t *p_next)
764 {
765     sout_stream_t *p_stream;
766
767     assert(psz_name);
768
769     p_stream = vlc_custom_create( p_sout, sizeof( *p_stream ), "stream out" );
770     if( !p_stream )
771         return NULL;
772
773     p_stream->p_sout   = p_sout;
774     p_stream->psz_name = psz_name;
775     p_stream->p_cfg    = p_cfg;
776     p_stream->p_next   = p_next;
777     p_stream->pace_nocontrol = false;
778     p_stream->p_sys = NULL;
779
780     msg_Dbg( p_sout, "stream=`%s'", p_stream->psz_name );
781
782     p_stream->p_module =
783         module_need( p_stream, "sout stream", p_stream->psz_name, true );
784
785     if( !p_stream->p_module )
786     {
787         /* those must be freed by the caller if creation failed */
788         p_stream->psz_name = NULL;
789         p_stream->p_cfg = NULL;
790
791         sout_StreamDelete( p_stream );
792         return NULL;
793     }
794
795     p_sout->i_out_pace_nocontrol += p_stream->pace_nocontrol;
796     return p_stream;
797 }
798
799 /* Creates a complete "stream_out" modules chain
800  *
801  *  chain format: module1{option=*:option=*}[:module2{option=*:...}]
802  *
803  *  The modules are created starting from the last one and linked together
804  *  A pointer to the last module created is stored if pp_last isn't NULL, to
805  *  make sure sout_StreamChainDelete doesn't delete modules created in another
806  *  place.
807  *
808  *  Returns a pointer to the first module.
809  */
810 sout_stream_t *sout_StreamChainNew(sout_instance_t *p_sout, char *psz_chain,
811                                 sout_stream_t *p_next, sout_stream_t **pp_last)
812 {
813     if(!psz_chain || !*psz_chain)
814     {
815         if(pp_last) *pp_last = NULL;
816         return p_next;
817     }
818
819     char *psz_parser = strdup(psz_chain);
820     if(!psz_parser)
821         return NULL;
822
823     vlc_array_t cfg, name;
824     vlc_array_init(&cfg);
825     vlc_array_init(&name);
826
827     /* parse chain */
828     while(psz_parser)
829     {
830         config_chain_t *p_cfg;
831         char *psz_name;
832         psz_chain = config_ChainCreate( &psz_name, &p_cfg, psz_parser );
833         free( psz_parser );
834         psz_parser = psz_chain;
835
836         vlc_array_append(&cfg, p_cfg);
837         vlc_array_append(&name, psz_name);
838     }
839
840     int i = vlc_array_count(&name);
841     vlc_array_t module;
842     vlc_array_init(&module);
843     while(i--)
844     {
845         p_next = sout_StreamNew( p_sout, vlc_array_item_at_index(&name, i),
846             vlc_array_item_at_index(&cfg, i), p_next);
847
848         if(!p_next)
849             goto error;
850
851         if(i == vlc_array_count(&name) - 1 && pp_last)
852             *pp_last = p_next;   /* last module created in the chain */
853
854         vlc_array_append(&module, p_next);
855     }
856
857     vlc_array_clear(&name);
858     vlc_array_clear(&cfg);
859     vlc_array_clear(&module);
860
861     return p_next;
862
863 error:
864
865     i++;    /* last module couldn't be created */
866
867     /* destroy all modules created, starting with the last one */
868     int modules = vlc_array_count(&module);
869     while(modules--)
870         sout_StreamDelete(vlc_array_item_at_index(&module, modules));
871     vlc_array_clear(&module);
872
873     /* then destroy all names and config which weren't destroyed by
874      * sout_StreamDelete */
875     while(i--)
876     {
877         free(vlc_array_item_at_index(&name, i));
878         config_ChainDestroy(vlc_array_item_at_index(&cfg, i));
879     }
880     vlc_array_clear(&name);
881     vlc_array_clear(&cfg);
882
883     return NULL;
884 }
885
886 static char *sout_stream_url_to_chain( bool b_sout_display,
887                                        const char *psz_url )
888 {
889     mrl_t       mrl;
890     char        *psz_chain;
891
892     mrl_Parse( &mrl, psz_url );
893
894     /* Check if the URLs goes to #rtp - otherwise we'll use #standard */
895     static const char rtplist[] = "dccp\0sctp\0tcp\0udplite\0";
896     for (const char *a = rtplist; *a; a += strlen (a) + 1)
897         if (strcmp (a, mrl.psz_access) == 0)
898             goto rtp;
899
900     if (strcmp (mrl.psz_access, "rtp") == 0)
901     {
902         char *port;
903         /* For historical reasons, rtp:// means RTP over UDP */
904         strcpy (mrl.psz_access, "udp");
905 rtp:
906         if (mrl.psz_name[0] == '[')
907         {
908             port = strstr (mrl.psz_name, "]:");
909             if (port != NULL)
910                 port++;
911         }
912         else
913             port = strchr (mrl.psz_name, ':');
914         if (port != NULL)
915             *port++ = '\0'; /* erase ':' */
916
917         if (asprintf (&psz_chain,
918                       "rtp{mux=\"%s\",proto=\"%s\",dst=\"%s%s%s\"}",
919                       mrl.psz_way, mrl.psz_access, mrl.psz_name,
920                       port ? "\",port=\"" : "", port ? port : "") == -1)
921             psz_chain = NULL;
922     }
923     else
924     {
925         /* Convert the URL to a basic standard sout chain */
926         if (asprintf (&psz_chain,
927                       "standard{mux=\"%s\",access=\"%s\",dst=\"%s\"}",
928                       mrl.psz_way, mrl.psz_access, mrl.psz_name) == -1)
929             psz_chain = NULL;
930     }
931
932     /* Duplicate and wrap if sout-display is on */
933     if (psz_chain && b_sout_display)
934     {
935         char *tmp;
936         if (asprintf (&tmp, "duplicate{dst=display,dst=%s}", psz_chain) == -1)
937             tmp = NULL;
938         free (psz_chain);
939         psz_chain = tmp;
940     }
941
942     mrl_Clean( &mrl );
943     return psz_chain;
944 }
945
946 #undef sout_EncoderCreate
947 encoder_t *sout_EncoderCreate( vlc_object_t *p_this )
948 {
949     return vlc_custom_create( p_this, sizeof( encoder_t ), "encoder" );
950 }