* modules/mux/mpeg/ps.c: save pack and system headers for http streaming.
[vlc.git] / modules / mux / mpeg / ps.c
1 /*****************************************************************************
2  * ps.c: MPEG PS (ISO/IEC 13818-1) / MPEG SYSTEM (ISO/IEC 1172-1)
3  *       multiplexer module for vlc
4  *****************************************************************************
5  * Copyright (C) 2001, 2002 VideoLAN
6  * $Id: ps.c,v 1.14 2003/07/15 16:07:33 gbazin Exp $
7  *
8  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9  *          Eric Petit <titer@videolan.org>
10  *          Gildas Bazin <gbazin@netcourrier.com>
11  *
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
26  *****************************************************************************/
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <fcntl.h>
37
38 #include <vlc/vlc.h>
39 #include <vlc/input.h>
40 #include <vlc/sout.h>
41
42 #ifdef HAVE_UNISTD_H
43 #   include <unistd.h>
44 #endif
45
46 #include "codecs.h"
47 #include "bits.h"
48 #include "pes.h"
49
50 /*****************************************************************************
51  * Exported prototypes
52  *****************************************************************************/
53 static int     Open   ( vlc_object_t * );
54 static void    Close  ( vlc_object_t * );
55
56 static int Capability(sout_mux_t *, int, void *, void * );
57 static int AddStream( sout_mux_t *, sout_input_t * );
58 static int DelStream( sout_mux_t *, sout_input_t * );
59 static int Mux      ( sout_mux_t * );
60
61 static void SetWBE ( uint8_t *p, uint16_t v )
62 {
63     p[0] = ( v >> 8 )&0xff;
64     p[1] = v&0xff;
65 }
66 static void SetDWBE( uint8_t *p, uint32_t v )
67 {
68     SetWBE( p,    ( v >> 16 )&0xffff );
69     SetWBE( p + 2,  v & 0xffff );
70 }
71 #define ADD_DWBE( p_buff, v ) \
72     SetDWBE( (p_buff)->p_buffer + i_buffer, (v) ); \
73     i_buffer +=4;
74
75 /*****************************************************************************
76  * Module descriptor
77  *****************************************************************************/
78 vlc_module_begin();
79     set_description( _("PS muxer") );
80     set_capability( "sout mux", 50 );
81     add_shortcut( "ps" );
82     add_shortcut( "mpeg1" );
83     set_callbacks( Open, Close );
84 vlc_module_end();
85
86 typedef struct ps_stream_s
87 {
88     int             i_ok;
89
90     int             i_stream_id;
91
92 } ps_stream_t;
93
94 struct sout_mux_sys_t
95 {
96     int         i_stream_id_mpga;
97     int         i_stream_id_mpgv;
98     int         i_stream_id_a52;
99
100     int         i_audio_bound;
101     int         i_video_bound;
102
103     int         i_pes_count;
104
105     int         i_system_header;
106
107     vlc_bool_t  b_mpeg2;
108 };
109
110 /*****************************************************************************
111  * Open:
112  *****************************************************************************/
113 static int Open( vlc_object_t *p_this )
114 {
115     sout_mux_t      *p_mux = (sout_mux_t*)p_this;
116     sout_mux_sys_t  *p_sys;
117
118     msg_Info( p_mux, "Open" );
119
120     p_sys = malloc( sizeof( sout_mux_sys_t ) );
121
122     p_mux->pf_capacity  = Capability;
123     p_mux->pf_addstream = AddStream;
124     p_mux->pf_delstream = DelStream;
125     p_mux->pf_mux       = Mux;
126     p_mux->p_sys        = p_sys;
127     p_mux->i_preheader  = 30; // really enough for a pes header
128
129     p_sys->i_stream_id_mpga = 0xc0;
130     p_sys->i_stream_id_a52  = 0x80;
131     p_sys->i_stream_id_mpgv = 0xe0;
132     p_sys->i_audio_bound = 0;
133     p_sys->i_video_bound = 0;
134     p_sys->i_system_header = 0;
135     p_sys->i_pes_count = 0;
136
137     p_sys->b_mpeg2 = !(p_mux->psz_mux && !strcmp( p_mux->psz_mux, "mpeg1" ));
138
139     return VLC_SUCCESS;
140 }
141
142 /*****************************************************************************
143  * Close:
144  *****************************************************************************/
145
146 static void Close( vlc_object_t * p_this )
147 {
148     sout_mux_t      *p_mux = (sout_mux_t*)p_this;
149     sout_mux_sys_t  *p_sys = p_mux->p_sys;
150
151     sout_buffer_t   *p_end;
152
153     msg_Info( p_mux, "Close" );
154
155     p_end = sout_BufferNew( p_mux->p_sout, 4 );
156     SetDWBE( p_end->p_buffer, 0x01b9 );
157
158     sout_AccessOutWrite( p_mux->p_access, p_end );
159
160     free( p_sys );
161 }
162
163 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args,
164                        void *p_answer )
165 {
166    switch( i_query )
167    {
168         case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
169             *(vlc_bool_t*)p_answer = VLC_TRUE;
170             return( SOUT_MUX_CAP_ERR_OK );
171         default:
172             return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
173    }
174 }
175
176 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
177 {
178     sout_mux_sys_t  *p_sys = p_mux->p_sys;
179     ps_stream_t         *p_stream;
180
181     msg_Dbg( p_mux, "adding input" );
182     p_input->p_sys = (void*)p_stream = malloc( sizeof( ps_stream_t ) );
183     p_stream->i_ok = 0;
184     switch( p_input->p_fmt->i_cat )
185     {
186         case VIDEO_ES:
187             switch( p_input->p_fmt->i_fourcc )
188             {
189                 case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
190                     p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
191                     p_sys->i_stream_id_mpgv++;
192                     p_sys->i_video_bound++;
193                     break;
194                 default:
195                     return( -1 );
196             }
197             break;
198
199         case AUDIO_ES:
200             switch( p_input->p_fmt->i_fourcc )
201             {
202                 case VLC_FOURCC( 'a', '5', '2', ' ' ):
203                 case VLC_FOURCC( 'a', '5', '2', 'b' ):
204                     p_stream->i_stream_id = p_sys->i_stream_id_a52 |
205                                             ( 0xbd << 8 );
206                     p_sys->i_stream_id_a52++;
207                     p_sys->i_audio_bound++;
208                     break;
209                 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
210                     p_stream->i_stream_id = p_sys->i_stream_id_mpga;
211                     p_sys->i_stream_id_mpga++;
212                     p_sys->i_audio_bound++;
213                     break;
214                 default:
215                     return( -1 );
216             }
217             break;
218         default:
219             return( -1 );
220     }
221
222     p_stream->i_ok = 1;
223     msg_Dbg( p_mux, "adding input stream_id:0x%x [OK]",
224              p_stream->i_stream_id );
225
226     return( 0 );
227 }
228
229 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
230 {
231     ps_stream_t *p_stream =(ps_stream_t*)p_input->p_sys;
232
233     msg_Dbg( p_mux, "removing input" );
234     if( p_stream )
235     {
236         free( p_stream );
237     }
238     return( VLC_SUCCESS );
239 }
240
241 static int MuxWritePackHeader( sout_mux_t *p_mux, sout_buffer_t **p_buf,
242                                mtime_t i_dts )
243 {
244     sout_buffer_t   *p_hdr;
245     bits_buffer_t   bits;
246     mtime_t         i_src;
247
248     i_src = i_dts * 9 / 100;
249
250     p_hdr = sout_BufferNew( p_mux->p_sout, 18 );
251     bits_initwrite( &bits, 14, p_hdr->p_buffer );
252     bits_write( &bits, 32, 0x01ba );
253
254     if( p_mux->p_sys->b_mpeg2 )
255         bits_write( &bits, 2, 0x01 );
256     else
257         bits_write( &bits, 4, 0x02 );
258
259     bits_write( &bits, 3, ( i_src >> 30 )&0x07 );
260     bits_write( &bits, 1,  1 );
261     bits_write( &bits, 15, ( i_src >> 15 )&0x7fff );
262     bits_write( &bits, 1,  1 );
263     bits_write( &bits, 15, i_src&0x7fff );
264     bits_write( &bits, 1,  1 );
265
266     if( p_mux->p_sys->b_mpeg2 )
267     {
268         bits_write( &bits, 9,  0 ); // src extention
269     }
270     bits_write( &bits, 1,  1 );
271
272     bits_write( &bits, 22,  1000/8/50); // FIXME mux rate
273     bits_write( &bits, 1,  1 );
274
275     if( p_mux->p_sys->b_mpeg2 )
276     {
277         bits_write( &bits, 1,  1 );
278         bits_write( &bits, 5,  0x1f );  // FIXME reserved
279         bits_write( &bits, 3,  0 );     // stuffing bytes
280     }
281
282     if( p_mux->p_sys->b_mpeg2 )
283         p_hdr->i_size = 14;
284     else
285         p_hdr->i_size = 12;
286
287     sout_BufferChain( p_buf, p_hdr );
288
289     return( 0 );
290 }
291
292 static int MuxWriteSystemHeader( sout_mux_t *p_mux, sout_buffer_t **p_buf )
293 {
294     sout_mux_sys_t  *p_sys = p_mux->p_sys;
295     sout_buffer_t   *p_hdr;
296     bits_buffer_t   bits;
297     int i;
298
299     p_hdr = sout_BufferNew( p_mux->p_sout, 12 + p_mux->i_nb_inputs * 3 );
300
301     bits_initwrite( &bits, 12 + p_mux->i_nb_inputs * 3, p_hdr->p_buffer );
302     bits_write( &bits, 32, 0x01bb );
303     bits_write( &bits, 16, 12 - 6 + p_mux->i_nb_inputs * 3 );
304     bits_write( &bits, 1,  1 );
305     bits_write( &bits, 22, 0 ); // FIXME rate bound
306     bits_write( &bits, 1,  1 );
307
308     bits_write( &bits, 6,  p_sys->i_audio_bound );
309     bits_write( &bits, 1,  0 ); // fixed flag
310     bits_write( &bits, 1,  0 ); // CSPS flag
311     bits_write( &bits, 1,  0 ); // system audio lock flag
312     bits_write( &bits, 1,  0 ); // system video lock flag
313
314     bits_write( &bits, 1,  1 ); // marker bit
315
316     bits_write( &bits, 5,  p_sys->i_video_bound );
317     bits_write( &bits, 1,  1 ); // packet rate restriction flag (1 for mpeg1)
318     bits_write( &bits, 7,  0xff ); // reserved bits
319
320     /* stream_id table */
321     for( i = 0; i < p_mux->i_nb_inputs; i++ )
322     {
323         ps_stream_t *p_stream = (ps_stream_t *)p_mux->pp_inputs[i]->p_sys;
324
325         if( p_stream->i_stream_id < 0xc0 )
326         {
327             /* FIXME */
328         }
329         bits_write( &bits, 8, p_stream->i_stream_id ); // stream ID
330         bits_write( &bits, 2, 0x03 );
331         if( p_stream->i_stream_id < 0xe0 ) /* FIXME */
332         {
333             /* audio */
334             bits_write( &bits, 1, 0 );
335             bits_write( &bits, 13, /* stream->max_buffer_size */ 0 / 128 );
336         } else {
337             /* video */
338             bits_write( &bits, 1, 1 );
339             bits_write( &bits, 13, /* stream->max_buffer_size */ 0 / 1024 );
340         }
341     }
342
343     sout_BufferChain( p_buf, p_hdr );
344
345     return( 0 );
346 }
347
348 /* return stream number to be muxed */
349 static int MuxGetStream( sout_mux_t *p_mux, 
350                          int        *pi_stream, 
351                          mtime_t    *pi_dts )
352 {
353     mtime_t i_dts;
354     int     i_stream;
355     int     i;
356
357     for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ )
358     {
359         sout_fifo_t  *p_fifo;
360
361         p_fifo = p_mux->pp_inputs[i]->p_fifo;
362
363         if( p_fifo->i_depth > 1 )
364         {
365             sout_buffer_t *p_buf;
366
367             p_buf = sout_FifoShow( p_fifo );
368             if( i_stream < 0 || p_buf->i_dts < i_dts )
369             {
370                 i_dts = p_buf->i_dts;
371                 i_stream = i;
372             }
373         }
374         else
375         {
376             return( -1 ); // wait that all fifo have at least 2 packets
377         }
378     }
379
380     if( pi_stream )
381     {
382         *pi_stream = i_stream;
383     }
384     if( pi_dts )
385     {
386         *pi_dts = i_dts;
387     }
388
389     return( i_stream );
390 }
391
392 static int Mux( sout_mux_t *p_mux )
393 {
394     sout_mux_sys_t *p_sys = p_mux->p_sys;
395     mtime_t        i_dts;
396     int            i_stream;
397
398     for( ;; )
399     {
400         sout_input_t *p_input;
401         ps_stream_t *p_stream;
402         sout_fifo_t  *p_fifo;
403         sout_buffer_t *p_hdr = NULL, *p_data;
404
405         if( MuxGetStream( p_mux, &i_stream, &i_dts ) < 0 )
406         {
407             return( VLC_SUCCESS );
408         }
409
410         p_input = p_mux->pp_inputs[i_stream];
411         p_fifo = p_input->p_fifo;
412         p_stream = (ps_stream_t*)p_input->p_sys;
413
414         if( p_sys->i_pes_count % 30 == 0)
415         {
416             MuxWritePackHeader( p_mux, &p_hdr, i_dts );
417         }
418
419         if( p_sys->i_pes_count % 300 == 0 )
420         {
421             sout_buffer_t *p_buf;
422
423             MuxWriteSystemHeader( p_mux, &p_hdr );
424
425             /* For MPEG1 streaming, set HEADER flag */
426             for( p_buf = p_hdr; p_buf != NULL; p_buf = p_buf->p_next )
427             {
428                 p_buf->i_flags |= SOUT_BUFFER_FLAGS_HEADER;
429             }
430         }
431
432         p_data = sout_FifoGet( p_fifo );
433         E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id,
434                        p_mux->p_sys->b_mpeg2 );
435
436         sout_BufferChain( &p_hdr, p_data );
437         sout_AccessOutWrite( p_mux->p_access, p_hdr );
438
439         p_sys->i_pes_count++;
440
441     }
442     return( 0 );
443 }