]> git.sesse.net Git - vlc/blob - src/stream_output/stream_output.c
* stream_output.c : fixed compilation.
[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.14 2003/02/24 12:34:29 fenrir Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *          Laurent Aimar <fenrir@via.ecp.fr>
9  *          Erioc 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      InitInstance      ( sout_instance_t * );
41
42 struct sout_instance_sys_t
43 {
44     /* if muxer doesn't support adding stream at any time then we first wait
45      *  for stream then we refuse all stream and start muxing */
46     vlc_bool_t  b_add_stream_any_time;
47     vlc_bool_t  b_waiting_stream;
48
49     /* we wait one second after first stream added */
50     mtime_t     i_add_stream_start;
51 };
52
53
54 /*****************************************************************************
55  * sout_NewInstance: creates a new stream output instance
56  *****************************************************************************/
57 sout_instance_t * __sout_NewInstance ( vlc_object_t *p_parent,
58                                        char * psz_dest )
59 {
60     sout_instance_t * p_sout;
61
62     /* Allocate descriptor */
63     p_sout = vlc_object_create( p_parent, VLC_OBJECT_SOUT );
64     if( p_sout == NULL )
65     {
66         msg_Err( p_parent, "out of memory" );
67         return NULL;
68     }
69
70     p_sout->psz_dest = strdup( psz_dest );
71
72     if ( InitInstance( p_sout ) == -1 )
73     {
74         vlc_object_destroy( p_sout );
75         return NULL;
76     }
77
78     vlc_object_attach( p_sout, p_parent );
79
80     return p_sout;
81 }
82
83 /*****************************************************************************
84  * InitInstance: opens appropriate modules
85  *****************************************************************************/
86 static int InitInstance( sout_instance_t * p_sout )
87 {
88     /* Parse dest string. Syntax : [[<access>][/<mux>]:][<dest>] */
89     /* This code is identical to input.c:InitThread. FIXME : factorize it ? */
90     char * psz_parser = p_sout->psz_dest;
91
92     p_sout->psz_access = "";
93     p_sout->psz_mux = "";
94     p_sout->psz_name = "";
95     p_sout->p_access = NULL;
96     p_sout->p_mux = NULL;
97     p_sout->i_mux_preheader = 0;
98     p_sout->i_nb_inputs = 0;
99     p_sout->pp_inputs = NULL;
100     vlc_mutex_init( p_sout, &p_sout->lock );
101     p_sout->p_sys = malloc( sizeof( sout_instance_sys_t ) );
102     /* fixed after opening muxer */
103     p_sout->p_sys->b_add_stream_any_time = VLC_FALSE;
104     p_sout->p_sys->b_waiting_stream = VLC_TRUE;
105     p_sout->p_sys->i_add_stream_start = -1;
106
107     /* Skip the plug-in names */
108     while( *psz_parser && *psz_parser != ':' )
109     {
110         psz_parser++;
111     }
112 #if defined( WIN32 ) || defined( UNDER_CE )
113     if( psz_parser - p_sout->psz_dest == 1 )
114     {
115         msg_Warn( p_sout, "drive letter %c: found in source string",
116                           *p_sout->psz_dest ) ;
117         psz_parser = "";
118     }
119 #endif
120
121     if( !*psz_parser )
122     {
123         p_sout->psz_access = p_sout->psz_mux = "";
124         p_sout->psz_name = p_sout->psz_dest;
125     }
126     else
127     {
128         *psz_parser++ = '\0';
129
130         /* let's skip '//' */
131         if( psz_parser[0] == '/' && psz_parser[1] == '/' )
132         {
133             psz_parser += 2 ;
134         } 
135
136         p_sout->psz_name = psz_parser ;
137
138         /* Come back to parse the access and mux plug-ins */
139         psz_parser = p_sout->psz_dest;
140
141         if( !*psz_parser )
142         {
143             /* No access */
144             p_sout->psz_access = "";
145         }
146         else if( *psz_parser == '/' )
147         {
148             /* No access */
149             p_sout->psz_access = "";
150             psz_parser++;
151         }
152         else
153         {
154             p_sout->psz_access = psz_parser;
155
156             while( *psz_parser && *psz_parser != '/' )
157             {
158                 psz_parser++;
159             }
160
161             if( *psz_parser == '/' )
162             {
163                 *psz_parser++ = '\0';
164             }
165         }
166
167         if( !*psz_parser )
168         {
169             /* No mux */
170             p_sout->psz_mux = "";
171         }
172         else
173         {
174             p_sout->psz_mux = psz_parser;
175         }
176     }
177
178     msg_Dbg( p_sout, "access `%s', mux `%s', name `%s'",
179              p_sout->psz_access, p_sout->psz_mux, p_sout->psz_name );
180
181
182     /* Find and open appropriate access module */
183     p_sout->p_access =
184         sout_AccessOutNew( p_sout, p_sout->psz_access, p_sout->psz_name );
185     if( p_sout->p_access == NULL )
186     {
187         msg_Err( p_sout, "no suitable sout access module for `%s/%s://%s'",
188                  p_sout->psz_access, p_sout->psz_mux, p_sout->psz_name );
189         return -1;
190     }
191
192
193     /* Find and open appropriate mux module */
194     p_sout->p_mux =
195         module_Need( p_sout, "sout mux", p_sout->psz_mux );
196
197     if( p_sout->p_mux == NULL )
198     {
199         msg_Err( p_sout, "no suitable mux module for `%s/%s://%s'",
200                  p_sout->psz_access, p_sout->psz_mux, p_sout->psz_name );
201
202         sout_AccessOutDelete( p_sout->p_access );
203         return -1;
204     }
205     if( p_sout->pf_mux_capacity )
206     {
207         int b_answer;
208         if( p_sout->pf_mux_capacity( p_sout,
209                                        SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME,
210                                        NULL, (void*)&b_answer ) != SOUT_MUX_CAP_ERR_OK )
211         {
212             b_answer = VLC_FALSE;
213         }
214         if( b_answer )
215         {
216             msg_Dbg( p_sout, "muxer support adding stream at any time" );
217             p_sout->p_sys->b_add_stream_any_time = VLC_TRUE;
218             p_sout->p_sys->b_waiting_stream = VLC_FALSE;
219         }
220         else
221         {
222             p_sout->p_sys->b_add_stream_any_time = VLC_FALSE;
223             p_sout->p_sys->b_waiting_stream = VLC_TRUE;
224         }
225     }
226     p_sout->i_nb_inputs = 0;
227     p_sout->pp_inputs = NULL;
228
229     return 0;
230 }
231
232
233 /*****************************************************************************
234  * sout_DeleteInstance: delete a previously allocated instance
235  *****************************************************************************/
236 void sout_DeleteInstance( sout_instance_t * p_sout )
237 {
238     /* Unlink object */
239     vlc_object_detach( p_sout );
240     if( p_sout->p_mux )
241     {
242         module_Unneed( p_sout, p_sout->p_mux );
243     }
244     if( p_sout->p_access )
245     {
246         sout_AccessOutDelete( p_sout->p_access );
247     }
248
249     vlc_mutex_destroy( &p_sout->lock );
250
251     /* Free structure */
252     vlc_object_destroy( p_sout );
253 }
254
255 /*****************************************************************************
256  * sout_AccessOutNew: allocate a new access out
257  *****************************************************************************/
258 sout_access_out_t *sout_AccessOutNew( sout_instance_t *p_sout,
259                                       char *psz_access, char *psz_name )
260 {
261     sout_access_out_t *p_access;
262
263     if( !( p_access = vlc_object_create( p_sout,
264                                          sizeof( sout_access_out_t ) ) ) )
265     {
266         msg_Err( p_sout, "out of memory" );
267         return NULL;
268     }
269     p_access->psz_access = strdup( psz_access ? psz_access : "" );
270     p_access->psz_name   = strdup( psz_name ? psz_name : "" );
271     p_access->p_sout     = p_sout;
272     p_access->p_sys = NULL;
273     p_access->pf_seek    = NULL;
274     p_access->pf_write   = NULL;
275
276     p_access->p_module   = module_Need( p_access,
277                                         "sout access",
278                                         p_access->psz_access );;
279
280     if( !p_access->p_module )
281     {
282         vlc_object_destroy( p_access );
283         p_access = NULL;
284     }
285
286     return p_access;
287 }
288 /*****************************************************************************
289  * sout_AccessDelete: delete an access out
290  *****************************************************************************/
291 void sout_AccessOutDelete( sout_access_out_t *p_access )
292 {
293     if( p_access->p_module )
294     {
295         module_Unneed( p_access, p_access->p_module );
296     }
297     free( p_access->psz_access );
298     free( p_access->psz_name );
299
300     vlc_object_destroy( p_access );
301 }
302
303 /*****************************************************************************
304  * sout_AccessSeek:
305  *****************************************************************************/
306 int  sout_AccessOutSeek( sout_access_out_t *p_access, off_t i_pos )
307 {
308     return( p_access->pf_seek( p_access, i_pos ) );
309 }
310
311 /*****************************************************************************
312  * sout_AccessWrite:
313  *****************************************************************************/
314 int  sout_AccessOutWrite( sout_access_out_t *p_access, sout_buffer_t *p_buffer )
315 {
316     return( p_access->pf_write( p_access, p_buffer ) );
317 }
318
319
320
321 /*****************************************************************************
322  *
323  *****************************************************************************/
324 sout_input_t *__sout_InputNew( vlc_object_t *p_this,
325                                 sout_packet_format_t *p_format )
326 {
327     sout_instance_t *p_sout = NULL;
328     sout_input_t    *p_input;
329     int             i_try;
330
331     /* search an stream output */
332     for( i_try = 0; i_try < 12; i_try++ )
333     {
334         p_sout = vlc_object_find( p_this, VLC_OBJECT_SOUT, FIND_ANYWHERE );
335         if( !p_sout )
336         {
337             msleep( 100*1000 );
338             msg_Dbg( p_this, "waiting for sout" );
339         }
340         else
341         {
342             break;
343         }
344     }
345
346     if( !p_sout )
347     {
348         msg_Err( p_this, "cannot find any stream ouput" );
349         return( NULL );
350     }
351     if( !p_sout->p_sys->b_add_stream_any_time && !p_sout->p_sys->b_waiting_stream)
352     {
353         msg_Err( p_sout, "cannot add a new stream (unsuported while muxing for this format)" );
354         return( NULL );
355     }
356
357     msg_Dbg( p_sout, "adding a new input" );
358     if( p_sout->p_sys->i_add_stream_start < 0 )
359     {
360         /* we wait for one second */
361         p_sout->p_sys->i_add_stream_start = mdate();
362     }
363
364     /* create a new sout input */
365     p_input = malloc( sizeof( sout_input_t ) );
366
367     p_input->p_sout = p_sout;
368     vlc_mutex_init( p_sout, &p_input->lock );
369     memcpy( &p_input->input_format,
370             p_format,
371             sizeof( sout_packet_format_t ) );
372     p_input->p_fifo = sout_FifoCreate( p_sout );
373     p_input->p_mux_data = NULL;
374
375     if( p_input->input_format.i_fourcc != VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
376     {
377         /* add this new one to p_sout */
378         vlc_mutex_lock( &p_sout->lock );
379         if( p_sout->i_nb_inputs == 0 )
380         {
381             p_sout->pp_inputs = malloc( sizeof( sout_input_t * ) );
382         }
383         else
384         {
385             p_sout->pp_inputs = realloc( p_sout->pp_inputs,
386                                         sizeof( sout_input_t * ) *
387                                                 ( p_sout->i_nb_inputs + 1 ) );
388         }
389         p_sout->pp_inputs[p_sout->i_nb_inputs] = p_input;
390         p_sout->i_nb_inputs++;
391
392         if( p_sout->pf_mux_addstream( p_sout, p_input ) < 0 )
393         {
394             msg_Err( p_sout, "cannot add this stream" );
395
396             vlc_mutex_unlock( &p_sout->lock );
397             sout_InputDelete( p_input );
398             vlc_mutex_lock( &p_sout->lock );
399
400             p_input = NULL;
401         }
402         vlc_mutex_unlock( &p_sout->lock );
403     }
404
405     vlc_object_release( p_sout );
406
407     return( p_input );
408 }
409
410
411 int sout_InputDelete( sout_input_t *p_input )
412 {
413     sout_instance_t     *p_sout = p_input->p_sout;
414     int                 i_input;
415
416
417     msg_Dbg( p_sout, "removing an input" );
418
419     vlc_mutex_lock( &p_sout->lock );
420
421     sout_FifoDestroy( p_sout, p_input->p_fifo );
422     vlc_mutex_destroy( &p_input->lock );
423
424     for( i_input = 0; i_input < p_sout->i_nb_inputs; i_input++ )
425     {
426         if( p_sout->pp_inputs[i_input] == p_input )
427         {
428             break;
429         }
430     }
431     if( i_input < p_sout->i_nb_inputs )
432     {
433         if( p_sout->pf_mux_delstream( p_sout, p_input ) < 0 )
434         {
435             msg_Err( p_sout, "cannot del this stream from mux" );
436         }
437
438         /* remove the entry */
439         if( p_sout->i_nb_inputs > 1 )
440         {
441             memmove( &p_sout->pp_inputs[i_input],
442                      &p_sout->pp_inputs[i_input+1],
443                      (p_sout->i_nb_inputs - i_input - 1) * sizeof( sout_input_t*) );
444         }
445         else
446         {
447             free( p_sout->pp_inputs );
448         }
449         p_sout->i_nb_inputs--;
450
451         if( p_sout->i_nb_inputs == 0 )
452         {
453             msg_Warn( p_sout, "no more input stream" );
454         }
455     }
456     else if( p_input->input_format.i_fourcc != VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
457     {
458         msg_Err( p_sout, "cannot find the input to be deleted" );
459     }
460
461     free( p_input );
462
463     vlc_mutex_unlock( &p_sout->lock );
464
465     return( 0 );
466 }
467
468
469 int sout_InputSendBuffer( sout_input_t *p_input, sout_buffer_t *p_buffer )
470 {
471     sout_instance_sys_t *p_sys = p_input->p_sout->p_sys;
472 /*    msg_Dbg( p_input->p_sout,
473              "send buffer, size:%d", p_buffer->i_size ); */
474
475     if( p_input->input_format.i_fourcc != VLC_FOURCC( 'n', 'u', 'l', 'l' ) )
476     {
477         sout_FifoPut( p_input->p_fifo, p_buffer );
478
479         if( p_sys->b_waiting_stream )
480         {
481             if( p_sys->i_add_stream_start > 0 &&
482                 p_sys->i_add_stream_start + (mtime_t)1000000 < mdate() )
483             {
484                 /* more than 1 second, start muxing */
485                 p_sys->b_waiting_stream = VLC_FALSE;
486             }
487             else
488             {
489                 return( 0 );
490             }
491         }
492         vlc_mutex_lock( &p_input->p_sout->lock );
493         p_input->p_sout->pf_mux( p_input->p_sout );
494         vlc_mutex_unlock( &p_input->p_sout->lock );
495     }
496     else
497     {
498         sout_BufferDelete( p_input->p_sout, p_buffer );
499     }
500
501     return( 0 );
502 }
503
504 sout_fifo_t *sout_FifoCreate( sout_instance_t *p_sout )
505 {
506     sout_fifo_t *p_fifo;
507
508     if( !( p_fifo = malloc( sizeof( sout_fifo_t ) ) ) )
509     {
510         return( NULL );
511     }
512
513     vlc_mutex_init( p_sout, &p_fifo->lock );
514     vlc_cond_init ( p_sout, &p_fifo->wait );
515     p_fifo->i_depth = 0;
516     p_fifo->p_first = NULL;
517     p_fifo->pp_last = &p_fifo->p_first;
518
519     return( p_fifo );
520 }
521
522 void       sout_FifoFree( sout_instance_t *p_sout, sout_fifo_t *p_fifo )
523 {
524     sout_buffer_t *p_buffer;
525
526     vlc_mutex_lock( &p_fifo->lock );
527     p_buffer = p_fifo->p_first;
528     while( p_buffer )
529     {
530         sout_buffer_t *p_next;
531         p_next = p_buffer->p_next;
532         sout_BufferDelete( p_sout, p_buffer );
533         p_buffer = p_next;
534     }
535     vlc_mutex_unlock( &p_fifo->lock );
536
537     return;
538 }
539 void       sout_FifoDestroy( sout_instance_t *p_sout, sout_fifo_t *p_fifo )
540 {
541     sout_FifoFree( p_sout, p_fifo );
542     vlc_mutex_destroy( &p_fifo->lock );
543     vlc_cond_destroy ( &p_fifo->wait );
544
545     free( p_fifo );
546 }
547
548 void        sout_FifoPut( sout_fifo_t *p_fifo, sout_buffer_t *p_buffer )
549 {
550     vlc_mutex_lock( &p_fifo->lock );
551
552     do
553     {
554         *p_fifo->pp_last = p_buffer;
555         p_fifo->pp_last = &p_buffer->p_next;
556         p_fifo->i_depth++;
557
558         p_buffer = p_buffer->p_next;
559
560     } while( p_buffer );
561
562     /* warm there is data in this fifo */
563     vlc_cond_signal( &p_fifo->wait );
564     vlc_mutex_unlock( &p_fifo->lock );
565 }
566
567 sout_buffer_t *sout_FifoGet( sout_fifo_t *p_fifo )
568 {
569     sout_buffer_t *p_buffer;
570
571     vlc_mutex_lock( &p_fifo->lock );
572
573     if( p_fifo->p_first == NULL )
574     {
575         vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
576     }
577
578     p_buffer = p_fifo->p_first;
579
580     p_fifo->p_first = p_buffer->p_next;
581     p_fifo->i_depth--;
582
583     if( p_fifo->p_first == NULL )
584     {
585         p_fifo->pp_last = &p_fifo->p_first;
586     }
587
588     vlc_mutex_unlock( &p_fifo->lock );
589
590     p_buffer->p_next = NULL;
591     return( p_buffer );
592 }
593
594 sout_buffer_t *sout_FifoShow( sout_fifo_t *p_fifo )
595 {
596     sout_buffer_t *p_buffer;
597
598     vlc_mutex_lock( &p_fifo->lock );
599
600     if( p_fifo->p_first == NULL )
601     {
602         vlc_cond_wait( &p_fifo->wait, &p_fifo->lock );
603     }
604
605     p_buffer = p_fifo->p_first;
606
607     vlc_mutex_unlock( &p_fifo->lock );
608
609     return( p_buffer );
610 }
611
612 sout_buffer_t *sout_BufferNew( sout_instance_t *p_sout, size_t i_size )
613 {
614     sout_buffer_t *p_buffer;
615     size_t        i_prehader;
616
617 #ifdef DEBUG_BUFFER
618     msg_Dbg( p_sout, "allocating an new buffer, size:%d", (uint32_t)i_size );
619 #endif
620
621     p_buffer = malloc( sizeof( sout_buffer_t ) );
622     i_prehader = p_sout->i_mux_preheader;
623
624     if( i_size > 0 )
625     {
626         p_buffer->p_allocated_buffer = malloc( i_size + i_prehader );
627         p_buffer->p_buffer = p_buffer->p_allocated_buffer + i_prehader;
628     }
629     else
630     {
631         p_buffer->p_allocated_buffer = NULL;
632         p_buffer->p_buffer = NULL;
633     }
634     p_buffer->i_allocated_size = i_size + i_prehader;
635     p_buffer->i_buffer_size = i_size;
636
637     p_buffer->i_size = i_size;
638     p_buffer->i_length = 0;
639     p_buffer->i_dts = 0;
640     p_buffer->i_pts = 0;
641     p_buffer->i_bitrate = 0;
642     p_buffer->p_next = NULL;
643
644     return( p_buffer );
645 }
646 int sout_BufferRealloc( sout_instance_t *p_sout, sout_buffer_t *p_buffer, size_t i_size )
647 {
648     size_t          i_prehader;
649
650 #ifdef DEBUG_BUFFER
651     msg_Dbg( p_sout,
652              "realloc buffer old size:%d new size:%d",
653              (uint32_t)p_buffer->i_allocated_size,
654              (uint32_t)i_size );
655 #endif
656
657     i_prehader = p_buffer->p_buffer - p_buffer->p_allocated_buffer;
658
659     if( !( p_buffer->p_allocated_buffer = realloc( p_buffer->p_allocated_buffer, i_size + i_prehader ) ) )
660     {
661         msg_Err( p_sout, "realloc failed" );
662         p_buffer->i_allocated_size = 0;
663         p_buffer->i_buffer_size = 0;
664         p_buffer->i_size = 0;
665         p_buffer->p_buffer = NULL;
666         return( -1 );
667     }
668     p_buffer->p_buffer = p_buffer->p_allocated_buffer + i_prehader;
669
670     p_buffer->i_allocated_size = i_size + i_prehader;
671     p_buffer->i_buffer_size = i_size;
672
673     return( 0 );
674 }
675
676 int sout_BufferReallocFromPreHeader( sout_instance_t *p_sout, sout_buffer_t *p_buffer, size_t i_size )
677 {
678     size_t  i_preheader;
679
680     i_preheader = p_buffer->p_buffer - p_buffer->p_allocated_buffer;
681
682     if( i_preheader < i_size )
683     {
684         return( -1 );
685     }
686
687     p_buffer->p_buffer -= i_size;
688     p_buffer->i_size += i_size;
689     p_buffer->i_buffer_size += i_size;
690
691     return( 0 );
692 }
693
694 int sout_BufferDelete( sout_instance_t *p_sout, sout_buffer_t *p_buffer )
695 {
696 #ifdef DEBUG_BUFFER
697     msg_Dbg( p_sout, "freeing buffer, size:%d", p_buffer->i_size );
698 #endif
699     if( p_buffer->p_allocated_buffer )
700     {
701         free( p_buffer->p_allocated_buffer );
702     }
703     free( p_buffer );
704     return( 0 );
705 }
706
707 sout_buffer_t *sout_BufferDuplicate( sout_instance_t *p_sout,
708                                      sout_buffer_t *p_buffer )
709 {
710     sout_buffer_t *p_dup;
711
712     p_dup = sout_BufferNew( p_sout, p_buffer->i_size );
713
714     p_dup->i_bitrate= p_buffer->i_bitrate;
715     p_dup->i_dts    = p_buffer->i_dts;
716     p_dup->i_pts    = p_buffer->i_pts;
717     p_dup->i_length = p_buffer->i_length;
718     p_sout->p_vlc->pf_memcpy( p_dup->p_buffer, p_buffer->p_buffer, p_buffer->i_size );
719
720     return( p_dup );
721 }
722
723 void sout_BufferChain( sout_buffer_t **pp_chain,
724                        sout_buffer_t *p_buffer )
725 {
726     if( *pp_chain == NULL )
727     {
728         *pp_chain = p_buffer;
729     }
730     else
731     {
732         sout_buffer_t *p = *pp_chain;
733
734         while( p->p_next )
735         {
736             p = p->p_next;
737         }
738
739         p->p_next = p_buffer;
740     }
741 }