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