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