]> git.sesse.net Git - vlc/blob - src/stream_output/stream_output.c
* modules/packetizer/mpegvideo.c: fixed major bug where the first frame could be...
[vlc] / src / stream_output / stream_output.c
1 /*****************************************************************************
2  * stream_output.c : stream output module
3  *****************************************************************************
4  * Copyright (C) 2002-2004 VideoLAN
5  * $Id: stream_output.c,v 1.39 2004/01/27 14:05:33 gbazin Exp $
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
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 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 General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdlib.h>                                                /* free() */
30 #include <stdio.h>                                              /* sprintf() */
31 #include <string.h>                                            /* strerror() */
32
33 #include <vlc/vlc.h>
34
35 #include <vlc/sout.h>
36 #undef DEBUG_BUFFER
37 /*****************************************************************************
38  * Local prototypes
39  *****************************************************************************/
40 static void sout_cfg_free( sout_cfg_t * );
41
42 #define sout_stream_url_to_chain( p, s ) _sout_stream_url_to_chain( VLC_OBJECT(p), s )
43 static char *_sout_stream_url_to_chain( vlc_object_t *, char * );
44
45 #define module_NeedStrict(a,b,c) __module_NeedStrict(VLC_OBJECT(a),b,c)
46 static module_t *__module_NeedStrict( vlc_object_t *, const char *, const char * );
47
48 /*
49  * Generic MRL parser
50  *
51  */
52
53 typedef struct
54 {
55     char            *psz_access;
56
57     char            *psz_way;
58
59     char *psz_name;
60 } mrl_t;
61
62 /* mrl_Parse: parse psz_mrl and fill p_mrl */
63 static int  mrl_Parse( mrl_t *p_mrl, char *psz_mrl );
64 /* mrl_Clean: clean p_mrl  after a call to mrl_Parse */
65 static void mrl_Clean( mrl_t *p_mrl );
66
67 #define FREE( p ) if( p ) { free( p ); (p) = NULL; }
68
69 /*****************************************************************************
70  * sout_NewInstance: creates a new stream output instance
71  *****************************************************************************/
72 sout_instance_t * __sout_NewInstance ( vlc_object_t *p_parent,
73                                        char * psz_dest )
74 {
75     sout_instance_t *p_sout;
76     vlc_value_t keep;
77
78     if( var_Get( p_parent, "sout-keep", &keep ) < 0 )
79     {
80         msg_Warn( p_parent, "cannot get sout-keep value" );
81         keep.b_bool = VLC_FALSE;
82     }
83     else if( keep.b_bool )
84     {
85         msg_Warn( p_parent, "sout-keep true" );
86         if( ( p_sout = vlc_object_find( p_parent, VLC_OBJECT_SOUT, FIND_ANYWHERE ) ) )
87         {
88             if( !strcmp( p_sout->psz_sout, psz_dest ) )
89             {
90                 msg_Warn( p_parent, "sout keep : reusing sout" );
91                 msg_Warn( p_parent, "sout keep : you probably want to use gather stream_out" );
92                 vlc_object_detach( p_sout );
93                 vlc_object_attach( p_sout, p_parent );
94                 vlc_object_release( p_sout );
95                 return p_sout;
96             }
97             else
98             {
99                 msg_Warn( p_parent, "sout keep : destroying unusable sout" );
100                 sout_DeleteInstance( p_sout );
101             }
102         }
103     }
104     else if( !keep.b_bool )
105     {
106         while( ( p_sout = vlc_object_find( p_parent, VLC_OBJECT_SOUT, FIND_PARENT ) ) )
107         {
108             msg_Warn( p_parent, "sout keep : destroying old sout" );
109             sout_DeleteInstance( p_sout );
110         }
111     }
112
113     /* *** Allocate descriptor *** */
114     p_sout = vlc_object_create( p_parent, VLC_OBJECT_SOUT );
115     if( p_sout == NULL )
116     {
117         msg_Err( p_parent, "out of memory" );
118         return NULL;
119     }
120
121     /* *** init descriptor *** */
122     p_sout->psz_sout    = strdup( psz_dest );
123     p_sout->i_preheader = 0;
124     p_sout->i_padding   = 0;
125     p_sout->p_sys       = NULL;
126
127     vlc_mutex_init( p_sout, &p_sout->lock );
128     if( psz_dest && psz_dest[0] == '#' )
129     {
130         p_sout->psz_chain = strdup( &psz_dest[1] );
131     }
132     else
133     {
134         p_sout->psz_chain = sout_stream_url_to_chain( p_sout, psz_dest );
135         msg_Dbg( p_sout, "using sout chain=`%s'", p_sout->psz_chain );
136     }
137
138     p_sout->p_stream = sout_stream_new( p_sout, p_sout->psz_chain );
139
140     if( p_sout->p_stream == NULL )
141     {
142         msg_Err( p_sout, "stream chained failed for `%s'", p_sout->psz_chain );
143
144         FREE( p_sout->psz_sout );
145         FREE( p_sout->psz_chain );
146
147         vlc_object_destroy( p_sout );
148         return( NULL );
149     }
150
151     vlc_object_attach( p_sout, p_parent );
152
153     return p_sout;
154 }
155 /*****************************************************************************
156  * sout_DeleteInstance: delete a previously allocated instance
157  *****************************************************************************/
158 void sout_DeleteInstance( sout_instance_t * p_sout )
159 {
160     /* Unlink object */
161     vlc_object_detach( p_sout );
162
163     /* *** free all string *** */
164     FREE( p_sout->psz_sout );
165     FREE( p_sout->psz_chain );
166
167     sout_stream_delete( p_sout->p_stream );
168     vlc_mutex_destroy( &p_sout->lock );
169
170     /* *** free structure *** */
171     vlc_object_destroy( p_sout );
172 }
173
174 /*****************************************************************************
175  * Packetizer/Input
176  *****************************************************************************/
177 sout_packetizer_input_t *__sout_InputNew( vlc_object_t  *p_this,
178                                           es_format_t *p_fmt )
179 {
180     sout_instance_t         *p_sout = NULL;
181     sout_packetizer_input_t *p_input;
182
183     /* search an stream output */
184     if( !( p_sout = vlc_object_find( p_this, VLC_OBJECT_SOUT, FIND_ANYWHERE ) ) )
185     {
186         /* can't happen ... */
187         msg_Err( p_this, "cannot find any stream ouput" );
188         return NULL;
189     }
190
191     msg_Dbg( p_sout, "adding a new input" );
192
193     /* *** create a packetizer input *** */
194     p_input         = malloc( sizeof( sout_packetizer_input_t ) );
195     p_input->p_sout = p_sout;
196     p_input->p_fmt  = p_fmt;
197
198     if( p_fmt->i_codec == VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
199     {
200         vlc_object_release( p_sout );
201         return p_input;
202     }
203
204     /* *** add it to the stream chain */
205     vlc_mutex_lock( &p_sout->lock );
206     p_input->id = p_sout->p_stream->pf_add( p_sout->p_stream,
207                                             p_fmt );
208     vlc_mutex_unlock( &p_sout->lock );
209
210     vlc_object_release( p_sout );
211
212     if( p_input->id == NULL )
213     {
214         free( p_input );
215         return( NULL );
216     }
217
218     return( p_input );
219 }
220
221
222 int sout_InputDelete( sout_packetizer_input_t *p_input )
223 {
224     sout_instance_t     *p_sout = p_input->p_sout;
225
226     msg_Dbg( p_sout, "removing an input" );
227
228     if( p_input->p_fmt->i_codec != VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
229     {
230         vlc_mutex_lock( &p_sout->lock );
231         p_sout->p_stream->pf_del( p_sout->p_stream, p_input->id );
232         vlc_mutex_unlock( &p_sout->lock );
233     }
234
235     free( p_input );
236
237     return( VLC_SUCCESS);
238 }
239
240 int sout_InputSendBuffer( sout_packetizer_input_t *p_input,
241                           sout_buffer_t *p_buffer )
242 {
243     sout_instance_t     *p_sout = p_input->p_sout;
244     int                 i_ret;
245
246     if( p_input->p_fmt->i_codec == VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
247     {
248         sout_BufferDelete( p_input->p_sout, p_buffer );
249         return VLC_SUCCESS;
250     }
251
252     if( !p_buffer->i_dts )
253     {
254         msg_Warn( p_sout, "trying to send non-dated packet to stream output!");
255         sout_BufferDelete( p_input->p_sout, p_buffer );
256         return VLC_SUCCESS;
257     }
258
259     vlc_mutex_lock( &p_sout->lock );
260     i_ret = p_sout->p_stream->pf_send( p_sout->p_stream,
261                                        p_input->id, p_buffer );
262     vlc_mutex_unlock( &p_sout->lock );
263
264     return i_ret;
265 }
266
267 /*****************************************************************************
268  * sout_AccessOutNew: allocate a new access out
269  *****************************************************************************/
270 sout_access_out_t *sout_AccessOutNew( sout_instance_t *p_sout,
271                                       char *psz_access, char *psz_name )
272 {
273     sout_access_out_t *p_access;
274     char              *psz_next;
275
276     if( !( p_access = vlc_object_create( p_sout,
277                                          sizeof( sout_access_out_t ) ) ) )
278     {
279         msg_Err( p_sout, "out of memory" );
280         return NULL;
281     }
282
283     psz_next = sout_cfg_parser( &p_access->psz_access, &p_access->p_cfg,
284                                 psz_access );
285     if( psz_next )
286     {
287         free( psz_next );
288     }
289     p_access->psz_name   = strdup( psz_name ? psz_name : "" );
290     p_access->p_sout     = p_sout;
291     p_access->p_sys = NULL;
292     p_access->pf_seek    = NULL;
293     p_access->pf_read    = NULL;
294     p_access->pf_write   = NULL;
295
296     p_access->p_module   =
297         module_NeedStrict( p_access, "sout access", p_access->psz_access );
298
299     if( !p_access->p_module )
300     {
301         free( p_access->psz_access );
302         free( p_access->psz_name );
303         vlc_object_destroy( p_access );
304         return( NULL );
305     }
306
307     return p_access;
308 }
309 /*****************************************************************************
310  * sout_AccessDelete: delete an access out
311  *****************************************************************************/
312 void sout_AccessOutDelete( sout_access_out_t *p_access )
313 {
314     if( p_access->p_module )
315     {
316         module_Unneed( p_access, p_access->p_module );
317     }
318     free( p_access->psz_access );
319
320     sout_cfg_free( p_access->p_cfg );
321
322     free( p_access->psz_name );
323
324     vlc_object_destroy( p_access );
325 }
326
327 /*****************************************************************************
328  * sout_AccessSeek:
329  *****************************************************************************/
330 int sout_AccessOutSeek( sout_access_out_t *p_access, off_t i_pos )
331 {
332     return p_access->pf_seek( p_access, i_pos );
333 }
334
335 /*****************************************************************************
336  * sout_AccessRead:
337  *****************************************************************************/
338 int sout_AccessOutRead( sout_access_out_t *p_access, sout_buffer_t *p_buffer )
339 {
340     return ( p_access->pf_read ?
341              p_access->pf_read( p_access, p_buffer ) : VLC_EGENERIC );
342 }
343
344 /*****************************************************************************
345  * sout_AccessWrite:
346  *****************************************************************************/
347 int sout_AccessOutWrite( sout_access_out_t *p_access, sout_buffer_t *p_buffer )
348 {
349     return p_access->pf_write( p_access, p_buffer );
350 }
351
352 /*****************************************************************************
353  * MuxNew: allocate a new mux
354  *****************************************************************************/
355 sout_mux_t * sout_MuxNew         ( sout_instance_t *p_sout,
356                                    char *psz_mux,
357                                    sout_access_out_t *p_access )
358 {
359     sout_mux_t *p_mux;
360     char       *psz_next;
361
362     p_mux = vlc_object_create( p_sout,
363                                sizeof( sout_mux_t ) );
364     if( p_mux == NULL )
365     {
366         msg_Err( p_sout, "out of memory" );
367         return NULL;
368     }
369
370     p_mux->p_sout       = p_sout;
371     psz_next = sout_cfg_parser( &p_mux->psz_mux, &p_mux->p_cfg, psz_mux );
372     if( psz_next )
373     {
374         free( psz_next );
375     }
376     p_mux->p_access     = p_access;
377     p_mux->i_preheader  = 0;
378     p_mux->pf_capacity  = NULL;
379     p_mux->pf_addstream = NULL;
380     p_mux->pf_delstream = NULL;
381     p_mux->pf_mux       = NULL;
382     p_mux->i_nb_inputs  = 0;
383     p_mux->pp_inputs    = NULL;
384
385     p_mux->p_sys        = NULL;
386
387     p_mux->p_module     =
388         module_NeedStrict( p_mux, "sout mux", p_mux->psz_mux );
389
390     if( p_mux->p_module == NULL )
391     {
392         FREE( p_mux->psz_mux );
393
394         vlc_object_destroy( p_mux );
395         return NULL;
396     }
397
398     /* *** probe mux capacity *** */
399     if( p_mux->pf_capacity )
400     {
401         int b_answer;
402         if( p_mux->pf_capacity( p_mux,
403                                 SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME, NULL,
404                                 (void*)&b_answer ) != SOUT_MUX_CAP_ERR_OK )
405         {
406             b_answer = VLC_FALSE;
407         }
408         if( b_answer )
409         {
410             msg_Dbg( p_sout, "muxer support adding stream at any time" );
411             p_mux->b_add_stream_any_time = VLC_TRUE;
412             p_mux->b_waiting_stream = VLC_FALSE;
413
414             if( p_mux->pf_capacity( p_mux,
415                                     SOUT_MUX_CAP_GET_ADD_STREAM_WAIT, NULL,
416                                     (void*)&b_answer ) != SOUT_MUX_CAP_ERR_OK )
417             {
418                 b_answer = VLC_FALSE;
419             }
420             if( b_answer )
421             {
422                 msg_Dbg( p_sout, "muxer prefers waiting for all ES before "
423                          "starting muxing" );
424                 p_mux->b_waiting_stream = VLC_TRUE;
425             }
426         }
427         else
428         {
429             p_mux->b_add_stream_any_time = VLC_FALSE;
430             p_mux->b_waiting_stream = VLC_TRUE;
431         }
432     }
433     else
434     {
435         p_mux->b_add_stream_any_time = VLC_FALSE;
436         p_mux->b_waiting_stream = VLC_TRUE;
437     }
438     p_mux->i_add_stream_start = -1;
439
440     return p_mux;
441 }
442
443 void sout_MuxDelete( sout_mux_t *p_mux )
444 {
445     if( p_mux->p_module )
446     {
447         module_Unneed( p_mux, p_mux->p_module );
448     }
449     free( p_mux->psz_mux );
450
451     sout_cfg_free( p_mux->p_cfg );
452
453     vlc_object_destroy( p_mux );
454 }
455
456 sout_input_t *sout_MuxAddStream( sout_mux_t *p_mux, es_format_t *p_fmt )
457 {
458     sout_input_t *p_input;
459
460     if( !p_mux->b_add_stream_any_time && !p_mux->b_waiting_stream )
461     {
462         msg_Err( p_mux, "cannot add a new stream (unsuported while muxing "
463                         "for this format)" );
464         return NULL;
465     }
466     if( p_mux->i_add_stream_start < 0 )
467     {
468         /* we wait for one second */
469         p_mux->i_add_stream_start = mdate();
470     }
471
472     msg_Dbg( p_mux, "adding a new input" );
473
474     /* create a new sout input */
475     p_input = malloc( sizeof( sout_input_t ) );
476     p_input->p_sout = p_mux->p_sout;
477     p_input->p_fmt  = p_fmt;
478     p_input->p_fifo = sout_FifoCreate( p_mux->p_sout );
479     p_input->p_sys  = NULL;
480
481     TAB_APPEND( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input );
482     if( p_mux->pf_addstream( p_mux, p_input ) < 0 )
483     {
484             msg_Err( p_mux, "cannot add this stream" );
485             TAB_REMOVE( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input );
486             sout_FifoDestroy( p_mux->p_sout, p_input->p_fifo );
487             free( p_input );
488             return( NULL );
489     }
490
491     return( p_input );
492 }
493
494 void sout_MuxDeleteStream     ( sout_mux_t *p_mux,
495                                 sout_input_t *p_input )
496 {
497     int i_index;
498
499     TAB_FIND( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input, i_index );
500     if( i_index >= 0 )
501     {
502         if( p_mux->pf_delstream( p_mux, p_input ) < 0 )
503         {
504             msg_Err( p_mux, "cannot del this stream from mux" );
505         }
506
507         /* remove the entry */
508         TAB_REMOVE( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input );
509
510         if( p_mux->i_nb_inputs == 0 )
511         {
512             msg_Warn( p_mux, "no more input stream for this mux" );
513         }
514
515         sout_FifoDestroy( p_mux->p_sout, p_input->p_fifo );
516         free( p_input );
517     }
518 }
519
520 void sout_MuxSendBuffer       ( sout_mux_t    *p_mux,
521                                 sout_input_t  *p_input,
522                                 sout_buffer_t *p_buffer )
523 {
524     sout_FifoPut( p_input->p_fifo, p_buffer );
525
526     if( p_mux->b_waiting_stream )
527     {
528         if( p_mux->i_add_stream_start > 0 &&
529             p_mux->i_add_stream_start + (mtime_t)1500000 < mdate() )
530         {
531             /* more than 1.5 second, start muxing */
532             p_mux->b_waiting_stream = VLC_FALSE;
533         }
534         else
535         {
536             return;
537         }
538     }
539     p_mux->pf_mux( p_mux );
540 }
541
542
543
544 sout_fifo_t *sout_FifoCreate( sout_instance_t *p_sout )
545 {
546     sout_fifo_t *p_fifo;
547
548     if( !( p_fifo = malloc( sizeof( sout_fifo_t ) ) ) )
549     {
550         return( NULL );
551     }
552
553     vlc_mutex_init( p_sout, &p_fifo->lock );
554     vlc_cond_init ( p_sout, &p_fifo->wait );
555     p_fifo->i_depth = 0;
556     p_fifo->p_first = NULL;
557     p_fifo->pp_last = &p_fifo->p_first;
558
559     return( p_fifo );
560 }
561
562 void sout_FifoFree( sout_instance_t *p_sout, sout_fifo_t *p_fifo )
563 {
564     sout_buffer_t *p_buffer;
565
566     vlc_mutex_lock( &p_fifo->lock );
567     p_buffer = p_fifo->p_first;
568     while( p_buffer )
569     {
570         sout_buffer_t *p_next;
571         p_next = p_buffer->p_next;
572         sout_BufferDelete( p_sout, p_buffer );
573         p_buffer = p_next;
574     }
575     vlc_mutex_unlock( &p_fifo->lock );
576
577     return;
578 }
579 void sout_FifoDestroy( sout_instance_t *p_sout, sout_fifo_t *p_fifo )
580 {
581     sout_FifoFree( p_sout, p_fifo );
582     vlc_mutex_destroy( &p_fifo->lock );
583     vlc_cond_destroy ( &p_fifo->wait );
584
585     free( p_fifo );
586 }
587
588 void sout_FifoPut( sout_fifo_t *p_fifo, sout_buffer_t *p_buffer )
589 {
590     vlc_mutex_lock( &p_fifo->lock );
591
592     do
593     {
594         *p_fifo->pp_last = p_buffer;
595         p_fifo->pp_last = &p_buffer->p_next;
596         p_fifo->i_depth++;
597
598         p_buffer = p_buffer->p_next;
599
600     } while( p_buffer );
601
602     /* warm there is data in this fifo */
603     vlc_cond_signal( &p_fifo->wait );
604     vlc_mutex_unlock( &p_fifo->lock );
605 }
606
607 sout_buffer_t *sout_FifoGet( sout_fifo_t *p_fifo )
608 {
609     sout_buffer_t *p_buffer;
610
611     vlc_mutex_lock( &p_fifo->lock );
612
613     if( p_fifo->p_first == NULL )
614     {
615         vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
616     }
617
618     p_buffer = p_fifo->p_first;
619
620     p_fifo->p_first = p_buffer->p_next;
621     p_fifo->i_depth--;
622
623     if( p_fifo->p_first == NULL )
624     {
625         p_fifo->pp_last = &p_fifo->p_first;
626     }
627
628     vlc_mutex_unlock( &p_fifo->lock );
629
630     p_buffer->p_next = NULL;
631     return( p_buffer );
632 }
633
634 sout_buffer_t *sout_FifoShow( sout_fifo_t *p_fifo )
635 {
636     sout_buffer_t *p_buffer;
637
638     vlc_mutex_lock( &p_fifo->lock );
639
640     if( p_fifo->p_first == NULL )
641     {
642         vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
643     }
644
645     p_buffer = p_fifo->p_first;
646
647     vlc_mutex_unlock( &p_fifo->lock );
648
649     return( p_buffer );
650 }
651
652 sout_buffer_t *sout_BufferNew( sout_instance_t *p_sout, size_t i_size )
653 {
654     sout_buffer_t *p_buffer;
655     size_t        i_preheader, i_padding;
656
657     p_buffer = malloc( sizeof( sout_buffer_t ) );
658     i_preheader = p_sout->i_preheader;
659     i_padding = p_sout->i_padding;
660
661 #ifdef DEBUG_BUFFER
662     msg_Dbg( p_sout, "allocating an new buffer, size:%d, preheader:%d, "
663              "padding:%d", (uint32_t)i_size, i_preheader, i_padding );
664 #endif
665
666     if( i_size > 0 )
667     {
668         p_buffer->p_allocated_buffer =
669             malloc( i_size + i_preheader + i_padding );
670         p_buffer->p_buffer = p_buffer->p_allocated_buffer + i_preheader;
671
672         if( p_buffer->p_allocated_buffer && i_padding )
673             memset( p_buffer->p_allocated_buffer + i_size + i_preheader, 0,
674                     i_padding );
675     }
676     else
677     {
678         p_buffer->p_allocated_buffer = NULL;
679         p_buffer->p_buffer = NULL;
680     }
681     p_buffer->i_allocated_size = i_size + i_preheader + i_padding;
682     p_buffer->i_buffer_size = i_size;
683
684     p_buffer->i_size    = i_size;
685     p_buffer->i_length  = 0;
686     p_buffer->i_dts     = 0;
687     p_buffer->i_pts     = 0;
688     p_buffer->i_bitrate = 0;
689     p_buffer->i_flags   = 0x0000;
690     p_buffer->p_next = NULL;
691
692     return( p_buffer );
693 }
694
695 int sout_BufferRealloc( sout_instance_t *p_sout, sout_buffer_t *p_buffer,
696                         size_t i_size )
697 {
698     size_t i_preheader, i_padding;
699
700     i_preheader = p_buffer->p_buffer - p_buffer->p_allocated_buffer;
701     i_padding =  p_buffer->i_allocated_size - p_buffer->i_buffer_size
702                  - i_preheader;
703
704 #ifdef DEBUG_BUFFER
705     msg_Dbg( p_sout, "realloc buffer old size:%d new size:%d, preheader:%d, "
706              "padding:%d", (uint32_t)p_buffer->i_allocated_size,
707              (uint32_t)i_size, i_preheader, i_padding );
708 #endif
709
710     if( !( p_buffer->p_allocated_buffer =
711            realloc( p_buffer->p_allocated_buffer,
712                     i_size + i_preheader + i_padding ) ) )
713     {
714         msg_Err( p_sout, "realloc failed" );
715         p_buffer->i_allocated_size = 0;
716         p_buffer->i_buffer_size = 0;
717         p_buffer->i_size = 0;
718         p_buffer->p_buffer = NULL;
719         return( -1 );
720     }
721     p_buffer->p_buffer = p_buffer->p_allocated_buffer + i_preheader;
722
723     p_buffer->i_allocated_size = i_size + i_preheader + i_padding;
724     p_buffer->i_buffer_size = i_size;
725
726     if( i_padding )
727         memset( p_buffer->p_allocated_buffer + i_size + i_preheader, 0,
728                 i_padding );
729
730     return( 0 );
731 }
732
733 int sout_BufferReallocFromPreHeader( sout_instance_t *p_sout,
734                                      sout_buffer_t *p_buffer, size_t i_size )
735 {
736     size_t i_preheader;
737
738     i_preheader = p_buffer->p_buffer - p_buffer->p_allocated_buffer;
739
740     if( i_preheader < i_size )
741     {
742         return( -1 );
743     }
744
745     p_buffer->p_buffer -= i_size;
746     p_buffer->i_size += i_size;
747     p_buffer->i_buffer_size += i_size;
748
749     return( 0 );
750 }
751
752 int sout_BufferDelete( sout_instance_t *p_sout, sout_buffer_t *p_buffer )
753 {
754 #ifdef DEBUG_BUFFER
755     msg_Dbg( p_sout, "freeing buffer, size:%d", p_buffer->i_size );
756 #endif
757     if( p_buffer->p_allocated_buffer )
758     {
759         free( p_buffer->p_allocated_buffer );
760     }
761     free( p_buffer );
762     return( 0 );
763 }
764
765 sout_buffer_t *sout_BufferDuplicate( sout_instance_t *p_sout,
766                                      sout_buffer_t *p_buffer )
767 {
768     sout_buffer_t *p_dup;
769
770     p_dup = sout_BufferNew( p_sout, p_buffer->i_size );
771
772     p_dup->i_bitrate= p_buffer->i_bitrate;
773     p_dup->i_dts    = p_buffer->i_dts;
774     p_dup->i_pts    = p_buffer->i_pts;
775     p_dup->i_length = p_buffer->i_length;
776     p_dup->i_flags  = p_buffer->i_flags;
777     p_sout->p_vlc->pf_memcpy( p_dup->p_buffer, p_buffer->p_buffer, p_buffer->i_size );
778
779     return( p_dup );
780 }
781
782 void sout_BufferChain( sout_buffer_t **pp_chain,
783                        sout_buffer_t *p_buffer )
784 {
785     if( *pp_chain == NULL )
786     {
787         *pp_chain = p_buffer;
788     }
789     else if( p_buffer != NULL )
790     {
791         sout_buffer_t *p = *pp_chain;
792
793         while( p->p_next )
794         {
795             p = p->p_next;
796         }
797
798         p->p_next = p_buffer;
799     }
800 }
801
802 static int  mrl_Parse( mrl_t *p_mrl, char *psz_mrl )
803 {
804     char * psz_dup = strdup( psz_mrl );
805     char * psz_parser = psz_dup;
806     char * psz_access = "";
807     char * psz_way = "";
808     char * psz_name = "";
809
810     /* *** first parse psz_dest */
811     while( *psz_parser && *psz_parser != ':' )
812     {
813         if( *psz_parser == '{' )
814         {
815             while( *psz_parser && *psz_parser != '}' )
816             {
817                 psz_parser++;
818             }
819             if( *psz_parser )
820             {
821                 psz_parser++;
822             }
823         }
824         else
825         {
826             psz_parser++;
827         }
828     }
829 #if defined( WIN32 ) || defined( UNDER_CE )
830     if( psz_parser - psz_dup == 1 )
831     {
832         /* msg_Warn( p_sout, "drive letter %c: found in source string",
833                           *psz_dup ) ; */
834         psz_parser = "";
835     }
836 #endif
837
838     if( !*psz_parser )
839     {
840         psz_access = psz_way = "";
841         psz_name = psz_dup;
842     }
843     else
844     {
845         *psz_parser++ = '\0';
846
847         /* let's skip '//' */
848         if( psz_parser[0] == '/' && psz_parser[1] == '/' )
849         {
850             psz_parser += 2 ;
851         }
852
853         psz_name = psz_parser ;
854
855         /* Come back to parse the access and mux plug-ins */
856         psz_parser = psz_dup;
857
858         if( !*psz_parser )
859         {
860             /* No access */
861             psz_access = "";
862         }
863         else if( *psz_parser == '/' )
864         {
865             /* No access */
866             psz_access = "";
867             psz_parser++;
868         }
869         else
870         {
871             psz_access = psz_parser;
872
873             while( *psz_parser && *psz_parser != '/' )
874             {
875                 if( *psz_parser == '{' )
876                 {
877                     while( *psz_parser && *psz_parser != '}' )
878                     {
879                         psz_parser++;
880                     }
881                     if( *psz_parser )
882                     {
883                         psz_parser++;
884                     }
885                 }
886                 else
887                 {
888                     psz_parser++;
889                 }
890             }
891
892             if( *psz_parser == '/' )
893             {
894                 *psz_parser++ = '\0';
895             }
896         }
897
898         if( !*psz_parser )
899         {
900             /* No mux */
901             psz_way = "";
902         }
903         else
904         {
905             psz_way = psz_parser;
906         }
907     }
908
909     p_mrl->psz_access = strdup( psz_access );
910     p_mrl->psz_way    = strdup( psz_way );
911     p_mrl->psz_name   = strdup( psz_name );
912
913     free( psz_dup );
914     return( VLC_SUCCESS );
915 }
916
917
918 /* mrl_Clean: clean p_mrl  after a call to mrl_Parse */
919 static void mrl_Clean( mrl_t *p_mrl )
920 {
921     FREE( p_mrl->psz_access );
922     FREE( p_mrl->psz_way );
923     FREE( p_mrl->psz_name );
924 }
925
926
927 /****************************************************************************
928  ****************************************************************************
929  **
930  **
931  **
932  ****************************************************************************
933  ****************************************************************************/
934
935 /* create a complete chain */
936 /* chain format:
937     module{option=*:option=*}[:module{option=*:...}]
938  */
939
940 static char *_strndup( char *str, int i_len )
941 {
942     char *p;
943
944     p = malloc( i_len + 1 );
945     strncpy( p, str, i_len );
946     p[i_len] = '\0';
947
948     return( p );
949 }
950
951 /*
952  * parse module{options=str, option="str "}:
953  *  return a pointer on the rest
954  *  XXX: psz_chain is modified
955  */
956 #define SKIPSPACE( p ) { while( *p && ( *p == ' ' || *p == '\t' ) ) p++; }
957 /* go accross " " and { } */
958 static char *_get_chain_end( char *str )
959 {
960     char *p = str;
961
962     SKIPSPACE( p );
963
964     for( ;; )
965     {
966         if( *p == '{' || *p == '"' || *p == '\'')
967         {
968             char c;
969
970             if( *p == '{' )
971             {
972                 c = '}';
973             }
974             else
975             {
976                 c = *p;
977             }
978             p++;
979
980             for( ;; )
981             {
982                 if( *p == '\0' )
983                 {
984                     return p;
985                 }
986
987                 if( *p == c )
988                 {
989                     p++;
990                     return p;
991                 }
992                 else if( *p == '{' && c == '}' )
993                 {
994                     p = _get_chain_end( p );
995                 }
996                 else
997                 {
998                     p++;
999                 }
1000             }
1001         }
1002         else if( *p == '\0' || *p == ',' || *p == '}' || *p == ' ' || *p == '\t' )
1003         {
1004             return p;
1005         }
1006         else
1007         {
1008             p++;
1009         }
1010     }
1011 }
1012
1013 char * sout_cfg_parser( char **ppsz_name, sout_cfg_t **pp_cfg, char *psz_chain )
1014 {
1015     sout_cfg_t *p_cfg = NULL;
1016     char       *p = psz_chain;
1017
1018     *ppsz_name = NULL;
1019     *pp_cfg    = NULL;
1020
1021     if( p == NULL )
1022     {
1023         return NULL;
1024     }
1025
1026     SKIPSPACE( p );
1027
1028     while( *p && *p != '{' && *p != ':' && *p != ' ' && *p != '\t' )
1029     {
1030         p++;
1031     }
1032
1033     if( p == psz_chain )
1034     {
1035         return NULL;
1036     }
1037
1038     *ppsz_name = _strndup( psz_chain, p - psz_chain );
1039
1040     /* fprintf( stderr, "name=%s - rest=%s\n", *ppsz_name, p ); */
1041
1042     SKIPSPACE( p );
1043
1044     if( *p == '{' )
1045     {
1046         char *psz_name;
1047
1048         p++;
1049
1050         for( ;; )
1051         {
1052             sout_cfg_t cfg;
1053
1054             SKIPSPACE( p );
1055
1056             psz_name = p;
1057
1058             while( *p && *p != '=' && *p != ',' && *p != '}' && *p != ' ' && *p != '\t' )
1059             {
1060                 p++;
1061             }
1062
1063             /* fprintf( stderr, "name=%s - rest=%s\n", psz_name, p ); */
1064             if( p == psz_name )
1065             {
1066                 fprintf( stderr, "invalid options (empty)" );
1067                 break;
1068             }
1069
1070             cfg.psz_name = _strndup( psz_name, p - psz_name );
1071
1072             SKIPSPACE( p );
1073
1074             if( *p == '=' )
1075             {
1076                 char *end;
1077
1078                 p++;
1079 #if 0
1080                 SKIPSPACE( p );
1081
1082                 if( *p == '"' )
1083                 {
1084                     char *end;
1085
1086                     p++;
1087                     end = strchr( p, '"' );
1088
1089                     if( end )
1090                     {
1091 /*                        fprintf( stderr, "##%s -- %s\n", p, end ); */
1092                         cfg.psz_value = _strndup( p, end - p );
1093                         p = end + 1;
1094                     }
1095                     else
1096                     {
1097                         cfg.psz_value = strdup( p );
1098                         p += strlen( p );
1099                     }
1100
1101                 }
1102                 else
1103                 {
1104                     psz_value = p;
1105                     while( *p && *p != ',' && *p != '}' && *p != ' ' && *p != '\t' )
1106                     {
1107                         p++;
1108                     }
1109                     cfg.psz_value = _strndup( psz_value, p - psz_value );
1110                 }
1111 #endif
1112                 end = _get_chain_end( p );
1113                 if( end <= p )
1114                 {
1115                     cfg.psz_value = NULL;
1116                 }
1117                 else
1118                 {
1119                     if( *p == '\'' || *p =='"' || *p == '{' )
1120                     {
1121                         p++;
1122                         end--;
1123                     }
1124                     if( end <= p )
1125                     {
1126                         cfg.psz_value = NULL;
1127                     }
1128                     else
1129                     {
1130                         cfg.psz_value = _strndup( p, end - p );
1131                     }
1132                 }
1133
1134                 p = end;
1135                 SKIPSPACE( p );
1136             }
1137             else
1138             {
1139                 cfg.psz_value = NULL;
1140             }
1141
1142             cfg.p_next = NULL;
1143             if( p_cfg )
1144             {
1145                 p_cfg->p_next = malloc( sizeof( sout_cfg_t ) );
1146                 memcpy( p_cfg->p_next, &cfg, sizeof( sout_cfg_t ) );
1147
1148                 p_cfg = p_cfg->p_next;
1149             }
1150             else
1151             {
1152                 p_cfg = malloc( sizeof( sout_cfg_t ) );
1153                 memcpy( p_cfg, &cfg, sizeof( sout_cfg_t ) );
1154
1155                 *pp_cfg = p_cfg;
1156             }
1157
1158             if( *p == ',' )
1159             {
1160                 p++;
1161             }
1162
1163             if( *p == '}' )
1164             {
1165                 p++;
1166
1167                 break;
1168             }
1169         }
1170     }
1171
1172     if( *p == ':' )
1173     {
1174         return( strdup( p + 1 ) );
1175     }
1176
1177     return( NULL );
1178 }
1179
1180 static void sout_cfg_free( sout_cfg_t *p_cfg )
1181 {
1182     while( p_cfg != NULL )
1183     {
1184         sout_cfg_t *p_next;
1185
1186         p_next = p_cfg->p_next;
1187
1188         FREE( p_cfg->psz_name );
1189         FREE( p_cfg->psz_value );
1190         free( p_cfg );
1191
1192         p_cfg = p_next;
1193     }
1194 }
1195
1196
1197 /*
1198  * XXX name and p_cfg are used (-> do NOT free them)
1199  */
1200 sout_stream_t *sout_stream_new( sout_instance_t *p_sout,
1201                                 char *psz_chain )
1202 {
1203     sout_stream_t *p_stream;
1204
1205     if( !psz_chain )
1206     {
1207         msg_Err( p_sout, "invalid chain" );
1208         return NULL;
1209     }
1210
1211     p_stream = vlc_object_create( p_sout, sizeof( sout_stream_t ) );
1212
1213     if( !p_stream )
1214     {
1215         msg_Err( p_sout, "out of memory" );
1216         return NULL;
1217     }
1218
1219     p_stream->p_sout   = p_sout;
1220     p_stream->p_sys    = NULL;
1221
1222     p_stream->psz_next =
1223         sout_cfg_parser( &p_stream->psz_name, &p_stream->p_cfg, psz_chain);
1224
1225     msg_Dbg( p_sout, "stream=`%s'", p_stream->psz_name );
1226
1227     p_stream->p_module =
1228         module_NeedStrict( p_stream, "sout stream", p_stream->psz_name );
1229
1230     if( !p_stream->p_module )
1231     {
1232         sout_stream_delete( p_stream );
1233         return NULL;
1234     }
1235
1236     return p_stream;
1237 }
1238
1239 void sout_stream_delete( sout_stream_t *p_stream )
1240 {
1241     msg_Dbg( p_stream, "destroying chain... (name=%s)", p_stream->psz_name );
1242     if( p_stream->p_module ) module_Unneed( p_stream, p_stream->p_module );
1243
1244     FREE( p_stream->psz_name );
1245     FREE( p_stream->psz_next );
1246
1247     sout_cfg_free( p_stream->p_cfg );
1248
1249     msg_Dbg( p_stream, "destroying chain done" );
1250     vlc_object_destroy( p_stream );
1251 }
1252
1253 static char *_sout_stream_url_to_chain( vlc_object_t *p_this, char *psz_url )
1254 {
1255     mrl_t       mrl;
1256     char        *psz_chain, *p;
1257
1258     mrl_Parse( &mrl, psz_url );
1259     p = psz_chain = malloc( 500 + strlen( mrl.psz_way ) +
1260                                   strlen( mrl.psz_access ) +
1261                                   strlen( mrl.psz_name ) );
1262
1263
1264     if( config_GetInt( p_this, "sout-display" ) )
1265     {
1266         p += sprintf( p, "duplicate{dst=display,dst=std{mux=\"%s\",access=\"%s\",url=\"%s\"}}",
1267                       mrl.psz_way, mrl.psz_access, mrl.psz_name );
1268     }
1269     else
1270     {
1271         p += sprintf( p, "std{mux=\"%s\",access=\"%s\",url=\"%s\"}",
1272                       mrl.psz_way, mrl.psz_access, mrl.psz_name );
1273     }
1274
1275     mrl_Clean( &mrl );
1276     return( psz_chain );
1277 }
1278
1279 /*****************************************************************************/
1280 static module_t *__module_NeedStrict( vlc_object_t *p_obj, const char *psz_capacity, const char *psz_name )
1281 {
1282     module_t *p_module;
1283
1284     if( !psz_name || !*psz_name )
1285     {
1286         p_module = module_Need( p_obj, psz_capacity, psz_name );
1287     }
1288     else
1289     {
1290         char *psz_name_strict = malloc( strlen( psz_name ) + 6 );
1291         strcpy( psz_name_strict, psz_name );
1292         strcat( psz_name_strict, ",none" );
1293
1294         p_module = module_Need( p_obj, psz_capacity, psz_name_strict );
1295
1296         free( psz_name_strict );
1297     }
1298
1299     return p_module;
1300 }
1301
1302