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