]> git.sesse.net Git - vlc/blob - modules/mux/mpeg/ps.c
d27fd8f4d69d18efccb330284a357b8d4b418c8b
[vlc] / 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$
7  *
8  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9  *          Eric Petit <titer@videolan.org>
10  *          Gildas Bazin <gbazin@videolan.org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include <stdlib.h>
31
32 #include <vlc/vlc.h>
33 #include <vlc/input.h>
34 #include <vlc/sout.h>
35
36 #include "codecs.h"
37 #include "bits.h"
38 #include "pes.h"
39
40 #include "iso_lang.h"
41
42 /*****************************************************************************
43  * Module descriptor
44  *****************************************************************************/
45 #define DTS_TEXT N_("DTS delay (ms)")
46 #define DTS_LONGTEXT N_("This option will delay the DTS (decoding time " \
47   "stamps) and PTS (presentation timestamps) of the data in the " \
48   "stream, compared to the SCRs. This allows for some buffering inside " \
49   "the client decoder.")
50
51 static int     Open   ( vlc_object_t * );
52 static void    Close  ( vlc_object_t * );
53
54 #define SOUT_CFG_PREFIX "sout-ps-"
55
56 vlc_module_begin();
57     set_description( _("PS muxer") );
58     set_shortname( "MPEG-PS" );
59     set_category( CAT_SOUT );
60     set_subcategory( SUBCAT_SOUT_MUX );
61     set_capability( "sout mux", 50 );
62     add_shortcut( "ps" );
63     add_shortcut( "mpeg1" );
64     add_shortcut( "dvd" );
65     set_callbacks( Open, Close );
66
67     add_integer( SOUT_CFG_PREFIX "dts-delay", 200, NULL, DTS_TEXT,
68                  DTS_LONGTEXT, VLC_TRUE );
69 vlc_module_end();
70
71 /*****************************************************************************
72  * Exported prototypes
73  *****************************************************************************/
74 static int Control  ( sout_mux_t *, int, va_list );
75 static int AddStream( sout_mux_t *, sout_input_t * );
76 static int DelStream( sout_mux_t *, sout_input_t * );
77 static int Mux      ( sout_mux_t * );
78
79 /*****************************************************************************
80  * Local prototypes
81  *****************************************************************************/
82 static int  MuxGetStream        ( sout_mux_t *, int *, mtime_t * );
83
84 static void MuxWritePackHeader  ( sout_mux_t *, block_t **, mtime_t );
85 static void MuxWriteSystemHeader( sout_mux_t *, block_t **, mtime_t );
86 static void MuxWritePSM         ( sout_mux_t *, block_t **, mtime_t );
87
88 static void StreamIdInit        ( vlc_bool_t *id, int i_range );
89 static int  StreamIdGet         ( vlc_bool_t *id, int i_id_min, int i_id_max );
90 static void StreamIdRelease     ( vlc_bool_t *id, int i_id_min, int i_id );
91
92 typedef struct ps_stream_s
93 {
94     int i_stream_id;
95     int i_stream_type;
96
97     /* Language is iso639-2T */
98     uint8_t lang[3];
99
100 } ps_stream_t;
101
102 struct sout_mux_sys_t
103 {
104     /* Which id are unused */
105     vlc_bool_t  stream_id_mpga[16]; /* 0xc0 -> 0xcf */
106     vlc_bool_t  stream_id_mpgv[16]; /* 0xe0 -> 0xef */
107     vlc_bool_t  stream_id_a52[8];   /* 0x80 -> 0x87 <- FIXME I'm not sure */
108     vlc_bool_t  stream_id_spu[32];  /* 0x20 -> 0x3f */
109     vlc_bool_t  stream_id_dts[8];   /* 0x88 -> 0x8f */
110     vlc_bool_t  stream_id_lpcm[16]; /* 0xa0 -> 0xaf */
111
112     int i_audio_bound;
113     int i_video_bound;
114     int i_pes_count;
115     int i_system_header;
116     int i_dts_delay;
117
118     int64_t i_instant_bitrate;
119     int64_t i_instant_size;
120     int64_t i_instant_dts;
121
122     vlc_bool_t b_mpeg2;
123
124     int i_psm_version;
125     uint32_t crc32_table[256];
126 };
127
128 static const char *ppsz_sout_options[] = {
129     "dts-delay", NULL
130 };
131
132 /*****************************************************************************
133  * Open:
134  *****************************************************************************/
135 static int Open( vlc_object_t *p_this )
136 {
137     sout_mux_t *p_mux = (sout_mux_t*)p_this;
138     sout_mux_sys_t *p_sys;
139     vlc_value_t val;
140
141     msg_Info( p_mux, "Open" );
142     sout_CfgParse( p_mux, SOUT_CFG_PREFIX, ppsz_sout_options, p_mux->p_cfg );
143
144     p_mux->pf_control   = Control;
145     p_mux->pf_addstream = AddStream;
146     p_mux->pf_delstream = DelStream;
147     p_mux->pf_mux       = Mux;
148     p_mux->p_sys        = p_sys = malloc( sizeof( sout_mux_sys_t ) );
149
150     /* Init free stream id */
151     StreamIdInit( p_sys->stream_id_a52,  8  );
152     StreamIdInit( p_sys->stream_id_dts,  8  );
153     StreamIdInit( p_sys->stream_id_mpga, 16 );
154     StreamIdInit( p_sys->stream_id_mpgv, 16 );
155     StreamIdInit( p_sys->stream_id_lpcm, 16 );
156     StreamIdInit( p_sys->stream_id_spu,  32 );
157
158     p_sys->i_audio_bound   = 0;
159     p_sys->i_video_bound   = 0;
160     p_sys->i_system_header = 0;
161     p_sys->i_pes_count     = 0;
162
163     p_sys->i_psm_version   = 0;
164
165     p_sys->i_instant_bitrate  = 0;
166     p_sys->i_instant_size     = 0;
167     p_sys->i_instant_dts      = 0;
168
169     p_sys->b_mpeg2 = !(p_mux->psz_mux && !strcmp( p_mux->psz_mux, "mpeg1" ));
170
171     var_Get( p_mux, SOUT_CFG_PREFIX "dts-delay", &val );
172     p_sys->i_dts_delay = (int64_t)val.i_int * 1000;
173
174     /* Initialise CRC32 table */
175     if( p_sys->b_mpeg2 )
176     {
177         uint32_t i, j, k;
178
179         for(i = 0; i < 256; i++)
180         {
181             k = 0;
182             for( j = (i << 24) | 0x800000; j != 0x80000000; j <<= 1 )
183                 k = (k << 1) ^ (((k ^ j) & 0x80000000) ? 0x04c11db7 : 0);
184
185             p_sys->crc32_table[i] = k;
186         }
187     }
188
189     return VLC_SUCCESS;
190 }
191
192 /*****************************************************************************
193  * Close:
194  *****************************************************************************/
195 static void Close( vlc_object_t * p_this )
196 {
197     sout_mux_t      *p_mux = (sout_mux_t*)p_this;
198     sout_mux_sys_t  *p_sys = p_mux->p_sys;
199
200     block_t   *p_end;
201
202     msg_Info( p_mux, "Close" );
203
204     p_end = block_New( p_mux, 4 );
205     p_end->p_buffer[0] = 0x00; p_end->p_buffer[1] = 0x00;
206     p_end->p_buffer[2] = 0x01; p_end->p_buffer[3] = 0xb9;
207
208     sout_AccessOutWrite( p_mux->p_access, p_end );
209
210     free( p_sys );
211 }
212
213 /*****************************************************************************
214  * Control:
215  *****************************************************************************/
216 static int Control( sout_mux_t *p_mux, int i_query, va_list args )
217 {
218     vlc_bool_t *pb_bool;
219     char **ppsz;
220
221    switch( i_query )
222    {
223        case MUX_CAN_ADD_STREAM_WHILE_MUXING:
224            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
225            *pb_bool = VLC_TRUE;
226            return VLC_SUCCESS;
227
228        case MUX_GET_ADD_STREAM_WAIT:
229            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
230            *pb_bool = VLC_FALSE;
231            return VLC_SUCCESS;
232
233        case MUX_GET_MIME:
234            ppsz = (char**)va_arg( args, char ** );
235            *ppsz = strdup( "video/mpeg" );
236            return VLC_SUCCESS;
237
238         default:
239             return VLC_EGENERIC;
240    }
241 }
242
243 /*****************************************************************************
244  * AddStream:
245  *****************************************************************************/
246 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
247 {
248     sout_mux_sys_t  *p_sys = p_mux->p_sys;
249     ps_stream_t *p_stream;
250
251     msg_Dbg( p_mux, "adding input codec=%4.4s",
252              (char*)&p_input->p_fmt->i_codec );
253
254     p_input->p_sys = p_stream = malloc( sizeof( ps_stream_t ) );
255     p_stream->i_stream_type = 0x81;
256
257     /* Init this new stream */
258     switch( p_input->p_fmt->i_codec )
259     {
260         case VLC_FOURCC( 'm', 'p', '1', 'v' ):
261             p_stream->i_stream_id =
262                 StreamIdGet( p_sys->stream_id_mpgv, 0xe0, 0xef );
263             p_stream->i_stream_type = 0x01; /* ISO/IEC 11172 Video */
264             break;
265         case VLC_FOURCC( 'm', 'p', '2', 'v' ):
266         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
267             p_stream->i_stream_id =
268                 StreamIdGet( p_sys->stream_id_mpgv, 0xe0, 0xef );
269             p_stream->i_stream_type = 0x02; /* ISO/IEC 13818 Video */
270             break;
271         case VLC_FOURCC( 'm', 'p', '4', 'v' ):
272             p_stream->i_stream_id =
273                 StreamIdGet( p_sys->stream_id_mpgv, 0xe0, 0xef );
274             p_stream->i_stream_type = 0x10;
275             break;
276         case VLC_FOURCC( 'h', '2', '6', '4' ):
277             p_stream->i_stream_id =
278                 StreamIdGet( p_sys->stream_id_mpgv, 0xe0, 0xef );
279             p_stream->i_stream_type = 0x1b;
280             break;
281         case VLC_FOURCC( 'l', 'p', 'c', 'm' ):
282             p_stream->i_stream_id =
283                 0xbd00 | StreamIdGet( p_sys->stream_id_lpcm, 0xa0, 0xaf );
284             break;
285         case VLC_FOURCC( 'd', 't', 's', ' ' ):
286             p_stream->i_stream_id =
287                 0xbd00 | StreamIdGet( p_sys->stream_id_dts, 0x88, 0x8f );
288             break;
289         case VLC_FOURCC( 'a', '5', '2', ' ' ):
290             p_stream->i_stream_id =
291                 0xbd00 | StreamIdGet( p_sys->stream_id_a52, 0x80, 0x87 );
292             break;
293         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
294             p_stream->i_stream_id =
295                 StreamIdGet( p_sys->stream_id_mpga, 0xc0, 0xcf );
296             p_stream->i_stream_type = 0x03; /* ISO/IEC 11172 Audio */
297             break;
298         case VLC_FOURCC( 'm', 'p', '4', 'a' ):
299             p_stream->i_stream_id =
300                 StreamIdGet( p_sys->stream_id_mpga, 0xc0, 0xcf );
301             p_stream->i_stream_type = 0x0f;
302             break;
303         case VLC_FOURCC( 's', 'p', 'u', ' ' ):
304             p_stream->i_stream_id =
305                 0xbd00 | StreamIdGet( p_sys->stream_id_spu, 0x20, 0x3f );
306             break;
307         default:
308             goto error;
309     }
310
311     if( p_stream->i_stream_id < 0 ) goto error;
312
313     if( p_input->p_fmt->i_cat == AUDIO_ES )
314     {
315         p_sys->i_audio_bound++;
316     }
317     else if( p_input->p_fmt->i_cat == VIDEO_ES )
318     {
319         p_sys->i_video_bound++;
320     }
321
322     /* Try to set a sensible default value for the instant bitrate */
323     p_sys->i_instant_bitrate += p_input->p_fmt->i_bitrate + 1000/* overhead */;
324
325     p_sys->i_psm_version++;
326
327     p_stream->lang[0] = p_stream->lang[1] = p_stream->lang[2] = 0;
328     if( p_input->p_fmt->psz_language )
329     {
330         char *psz = p_input->p_fmt->psz_language;
331         const iso639_lang_t *pl = NULL;
332
333         if( strlen( psz ) == 2 )
334         {
335             pl = GetLang_1( psz );
336         }
337         else if( strlen( psz ) == 3 )
338         {
339             pl = GetLang_2B( psz );
340             if( !strcmp( pl->psz_iso639_1, "??" ) )
341             {
342                 pl = GetLang_2T( psz );
343             }
344         }
345         if( pl && strcmp( pl->psz_iso639_1, "??" ) )
346         {
347             p_stream->lang[0] = pl->psz_iso639_2T[0];
348             p_stream->lang[1] = pl->psz_iso639_2T[1];
349             p_stream->lang[2] = pl->psz_iso639_2T[2];
350
351             msg_Dbg( p_mux, "    - lang=%c%c%c",
352                      p_stream->lang[0], p_stream->lang[1], p_stream->lang[2] );
353         }
354     }
355
356     return VLC_SUCCESS;
357
358 error:
359     free( p_stream );
360     return VLC_EGENERIC;
361 }
362
363 /*****************************************************************************
364  * DelStream:
365  *****************************************************************************/
366 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
367 {
368     sout_mux_sys_t *p_sys = p_mux->p_sys;
369     ps_stream_t *p_stream =(ps_stream_t*)p_input->p_sys;
370
371     msg_Dbg( p_mux, "removing input" );
372     switch( p_input->p_fmt->i_codec )
373     {
374         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
375             StreamIdRelease( p_sys->stream_id_mpgv, 0xe0,
376                              p_stream->i_stream_id );
377             break;
378         case VLC_FOURCC( 'l', 'p', 'c', 'm' ):
379             StreamIdRelease( p_sys->stream_id_lpcm, 0xa0,
380                              p_stream->i_stream_id&0xff );
381             break;
382         case VLC_FOURCC( 'd', 't', 's', ' ' ):
383             StreamIdRelease( p_sys->stream_id_dts, 0x88,
384                              p_stream->i_stream_id&0xff );
385             break;
386         case VLC_FOURCC( 'a', '5', '2', ' ' ):
387             StreamIdRelease( p_sys->stream_id_a52, 0x80,
388                              p_stream->i_stream_id&0xff );
389             break;
390         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
391             StreamIdRelease( p_sys->stream_id_mpga, 0xc0,
392                              p_stream->i_stream_id  );
393             break;
394         case VLC_FOURCC( 's', 'p', 'u', ' ' ):
395             StreamIdRelease( p_sys->stream_id_spu, 0x20,
396                              p_stream->i_stream_id&0xff );
397             break;
398         default:
399             /* Never reached */
400             break;
401     }
402
403     if( p_input->p_fmt->i_cat == AUDIO_ES )
404     {
405         p_sys->i_audio_bound--;
406     }
407     else if( p_input->p_fmt->i_cat == VIDEO_ES )
408     {
409         p_sys->i_video_bound--;
410     }
411
412     /* Try to set a sensible default value for the instant bitrate */
413     p_sys->i_instant_bitrate -= (p_input->p_fmt->i_bitrate + 1000);
414
415     p_sys->i_psm_version++;
416
417     free( p_stream );
418     return VLC_SUCCESS;
419 }
420
421 /*****************************************************************************
422  * Mux: Call each time there is new data for at least one stream
423  *****************************************************************************/
424 static int Mux( sout_mux_t *p_mux )
425 {
426     sout_mux_sys_t *p_sys = p_mux->p_sys;
427
428     for( ;; )
429     {
430         sout_input_t *p_input;
431         ps_stream_t *p_stream;
432
433         block_t *p_ps, *p_data;
434
435         mtime_t        i_dts;
436         int            i_stream;
437
438         /* Choose which stream to mux */
439         if( MuxGetStream( p_mux, &i_stream, &i_dts ) )
440         {
441             return VLC_SUCCESS;
442         }
443
444         p_input  = p_mux->pp_inputs[i_stream];
445         p_stream = (ps_stream_t*)p_input->p_sys;
446         p_ps     = NULL;
447
448         /* Write regulary PackHeader */
449         if( p_sys->i_pes_count % 30 == 0)
450         {
451             /* Update the instant bitrate every second or so */
452             if( p_sys->i_instant_size &&
453                 i_dts - p_sys->i_instant_dts > 1000000 )
454             {
455                 int64_t i_instant_bitrate = p_sys->i_instant_size * 8000000 /
456                     ( i_dts - p_sys->i_instant_dts );
457
458                 p_sys->i_instant_bitrate += i_instant_bitrate;
459                 p_sys->i_instant_bitrate /= 2;
460
461                 p_sys->i_instant_size = 0;
462                 p_sys->i_instant_dts = i_dts;
463             }
464             else if( !p_sys->i_instant_size )
465             {
466                 p_sys->i_instant_dts = i_dts;
467             }
468
469             MuxWritePackHeader( p_mux, &p_ps, i_dts );
470         }
471
472         /* Write regulary SystemHeader */
473         if( p_sys->i_pes_count % 300 == 0 )
474         {
475             block_t *p_pk;
476
477             MuxWriteSystemHeader( p_mux, &p_ps, i_dts );
478
479             /* For MPEG1 streaming, set HEADER flag */
480             for( p_pk = p_ps; p_pk != NULL; p_pk = p_pk->p_next )
481             {
482                 p_pk->i_flags |= BLOCK_FLAG_HEADER;
483             }
484         }
485
486         /* Write regulary ProgramStreamMap */
487         if( p_sys->b_mpeg2 && p_sys->i_pes_count % 300 == 0 )
488         {
489             MuxWritePSM( p_mux, &p_ps, i_dts );
490         }
491
492         /* Get and mux a packet */
493         p_data = block_FifoGet( p_input->p_fifo );
494         E_( EStoPES )( p_mux->p_sout, &p_data, p_data,
495                        p_input->p_fmt, p_stream->i_stream_id,
496                        p_sys->b_mpeg2, 0, 0 );
497
498         block_ChainAppend( &p_ps, p_data );
499
500         /* Get size of output data so we can calculate the instant bitrate */
501         for( p_data = p_ps; p_data; p_data = p_data->p_next )
502         {
503             p_sys->i_instant_size += p_data->i_buffer;
504         }
505
506         sout_AccessOutWrite( p_mux->p_access, p_ps );
507
508         /* Increase counter */
509         p_sys->i_pes_count++;
510     }
511
512     return VLC_SUCCESS;
513 }
514
515 /*****************************************************************************
516  *
517  *****************************************************************************/
518 static void StreamIdInit( vlc_bool_t *id, int i_range )
519 {
520     int i;
521
522     for( i = 0; i < i_range; i++ )
523     {
524         id[i] = VLC_TRUE;
525     }
526 }
527 static int StreamIdGet( vlc_bool_t *id, int i_id_min, int i_id_max )
528 {
529     int i;
530
531     for( i = 0; i <= i_id_max - i_id_min; i++ )
532     {
533         if( id[i] )
534         {
535             id[i] = VLC_FALSE;
536
537             return i_id_min + i;
538         }
539     }
540     return -1;
541 }
542 static void StreamIdRelease( vlc_bool_t *id, int i_id_min, int i_id )
543 {
544     id[i_id - i_id_min] = VLC_TRUE;
545 }
546
547 static void MuxWritePackHeader( sout_mux_t *p_mux, block_t **p_buf,
548                                 mtime_t i_dts )
549 {
550     sout_mux_sys_t *p_sys = p_mux->p_sys;
551     bits_buffer_t bits;
552     block_t *p_hdr;
553     mtime_t i_scr;
554     int i_mux_rate;
555
556     i_scr = (i_dts - p_sys->i_dts_delay) * 9 / 100;
557
558     p_hdr = block_New( p_mux, 18 );
559     p_hdr->i_pts = p_hdr->i_dts = i_dts;
560     bits_initwrite( &bits, 14, p_hdr->p_buffer );
561     bits_write( &bits, 32, 0x01ba );
562
563     /* The spec specifies that the mux rate must be rounded upwards */
564     i_mux_rate = (p_sys->i_instant_bitrate + 8 * 50 - 1 ) / (8 * 50);
565
566     if( p_sys->b_mpeg2 )
567     {
568         bits_write( &bits, 2, 0x01 );
569     }
570     else
571     {
572         bits_write( &bits, 4, 0x02 );
573     }
574
575     bits_write( &bits, 3, ( i_scr >> 30 )&0x07 );
576     bits_write( &bits, 1,  1 );
577     bits_write( &bits, 15, ( i_scr >> 15 )&0x7fff );
578     bits_write( &bits, 1,  1 );
579     bits_write( &bits, 15, i_scr&0x7fff );
580     bits_write( &bits, 1,  1 );
581
582     if( p_sys->b_mpeg2 )
583     {
584         bits_write( &bits, 9,  0 ); // src extention
585     }
586     bits_write( &bits, 1,  1 );
587
588     bits_write( &bits, 22,  i_mux_rate);  // FIXME mux rate
589     bits_write( &bits, 1,  1 );
590
591     if( p_sys->b_mpeg2 )
592     {
593         bits_write( &bits, 1,  1 );
594         bits_write( &bits, 5,  0x1f );  // FIXME reserved
595         bits_write( &bits, 3,  0 );     // stuffing bytes
596     }
597
598     p_hdr->i_buffer = p_sys->b_mpeg2 ? 14: 12;
599
600     block_ChainAppend( p_buf, p_hdr );
601 }
602
603 static void MuxWriteSystemHeader( sout_mux_t *p_mux, block_t **p_buf,
604                                   mtime_t i_dts )
605 {
606     sout_mux_sys_t  *p_sys = p_mux->p_sys;
607     block_t   *p_hdr;
608     bits_buffer_t   bits;
609     vlc_bool_t      b_private;
610     int i_mux_rate;
611
612     int             i_nb_private, i_nb_stream;
613     int i;
614
615     /* Count the number of private stream */
616     for( i = 0, i_nb_private = 0; i < p_mux->i_nb_inputs; i++ )
617     {
618         ps_stream_t *p_stream;
619
620         p_stream = (ps_stream_t*)p_mux->pp_inputs[i]->p_sys;
621
622         if( ( p_stream->i_stream_id&0xff00 ) == 0xbd00 )
623         {
624             i_nb_private++;
625         }
626     }
627
628     /* Private stream are declared only one time */
629     i_nb_stream = p_mux->i_nb_inputs -
630         ( i_nb_private > 0 ? i_nb_private - 1 : 0 );
631
632     p_hdr = block_New( p_mux, 12 + i_nb_stream * 3 );
633     p_hdr->i_dts = p_hdr->i_pts = i_dts;
634
635     /* The spec specifies that the mux rate must be rounded upwards */
636     i_mux_rate = (p_sys->i_instant_bitrate + 8 * 50 - 1 ) / (8 * 50);
637
638     bits_initwrite( &bits, 12 + i_nb_stream * 3, p_hdr->p_buffer );
639     bits_write( &bits, 32, 0x01bb );
640     bits_write( &bits, 16, 12 - 6 + i_nb_stream * 3 );
641     bits_write( &bits, 1,  1 );
642     bits_write( &bits, 22, i_mux_rate); // FIXME rate bound
643     bits_write( &bits, 1,  1 );
644
645     bits_write( &bits, 6,  p_sys->i_audio_bound );
646     bits_write( &bits, 1,  0 ); // fixed flag
647     bits_write( &bits, 1,  0 ); // CSPS flag
648     bits_write( &bits, 1,  0 ); // system audio lock flag
649     bits_write( &bits, 1,  0 ); // system video lock flag
650
651     bits_write( &bits, 1,  1 ); // marker bit
652
653     bits_write( &bits, 5,  p_sys->i_video_bound );
654     bits_write( &bits, 1,  1 ); // packet rate restriction flag (1 for mpeg1)
655     bits_write( &bits, 7,  0xff ); // reserved bits
656
657     /* stream_id table */
658     for( i = 0, b_private = VLC_FALSE; i < p_mux->i_nb_inputs; i++ )
659     {
660         sout_input_t *p_input;
661         ps_stream_t *p_stream;
662
663         p_input = p_mux->pp_inputs[i];
664         p_stream = (ps_stream_t *)p_input->p_sys;
665
666         if( ( p_stream->i_stream_id&0xff00 ) == 0xbd00 )
667         {
668             if( b_private )
669             {
670                 continue;
671             }
672             b_private = VLC_TRUE;
673             /* Write stream id */
674             bits_write( &bits, 8, 0xbd );
675         }
676         else
677         {
678             /* Write stream id */
679             bits_write( &bits, 8, p_stream->i_stream_id&0xff );
680         }
681         bits_write( &bits, 2, 0x03 );
682         if( p_input->p_fmt->i_cat == AUDIO_ES )
683         {
684             bits_write( &bits, 1, 0 );
685             bits_write( &bits, 13, /* stream->max_buffer_size */ 0 / 128 );
686         }
687         else if( p_input->p_fmt->i_cat == VIDEO_ES )
688         {
689             bits_write( &bits, 1, 1 );
690             bits_write( &bits, 13, /* stream->max_buffer_size */ 0 / 1024);
691         }
692         else
693         {
694             /* FIXME */
695             bits_write( &bits, 1, 0 );
696             bits_write( &bits, 13, /* stream->max_buffer_size */ 0 );
697         }
698     }
699
700     block_ChainAppend( p_buf, p_hdr );
701 }
702
703 static void MuxWritePSM( sout_mux_t *p_mux, block_t **p_buf, mtime_t i_dts )
704 {
705     sout_mux_sys_t *p_sys = p_mux->p_sys;
706     block_t *p_hdr;
707     bits_buffer_t bits;
708     int i, i_psm_size = 16, i_es_map_size = 0;
709
710     for( i = 0; i < p_mux->i_nb_inputs; i++ )
711     {
712         sout_input_t *p_input = p_mux->pp_inputs[i];
713         ps_stream_t *p_stream = p_input->p_sys;
714
715         i_es_map_size += 4;
716         if( p_stream->lang[0] != 0 ) i_es_map_size += 6;
717     }
718
719     i_psm_size += i_es_map_size;
720
721     p_hdr = block_New( p_mux, i_psm_size );
722     p_hdr->i_dts = p_hdr->i_pts = i_dts;
723
724     bits_initwrite( &bits, i_psm_size, p_hdr->p_buffer );
725     bits_write( &bits, 32, 0x01bc );
726     bits_write( &bits, 16, i_psm_size - 3 );
727     bits_write( &bits, 1, 1 ); /* current_next_indicator */
728     bits_write( &bits, 2, 0xF ); /* reserved */
729     bits_write( &bits, 5, p_sys->i_psm_version );
730     bits_write( &bits, 7, 0xFF ); /* reserved */
731     bits_write( &bits, 1, 1 ); /* marker */
732
733     bits_write( &bits, 16, 0 ); /* program_stream_info_length */
734     /* empty */
735
736     bits_write( &bits, 16, i_es_map_size ); /* elementary_stream_map_length */
737     for( i = 0; i < p_mux->i_nb_inputs; i++ )
738     {
739         sout_input_t *p_input = p_mux->pp_inputs[i];
740         ps_stream_t *p_stream = p_input->p_sys;
741
742         bits_write( &bits, 8, p_stream->i_stream_type ); /* stream_type */
743         bits_write( &bits, 8, p_stream->i_stream_id ); /* elementary_stream_id */
744
745         /* ISO639 language descriptor */
746         if( p_stream->lang[0] != 0 )
747         {
748             bits_write( &bits, 16, 6 ); /* elementary_stream_info_length */
749
750             bits_write( &bits, 8, 0x0a ); /* descriptor_tag */
751             bits_write( &bits, 8, 4 ); /* descriptor_length */
752
753             bits_write( &bits, 8, p_stream->lang[0] );
754             bits_write( &bits, 8, p_stream->lang[1] );
755             bits_write( &bits, 8, p_stream->lang[2] );
756             bits_write( &bits, 8, 0 ); /* audio type: 0x00 undefined */
757         }
758         else
759         {
760             bits_write( &bits, 16, 0 ); /* elementary_stream_info_length */
761         }
762     }
763
764     /* CRC32 */
765     {
766         uint32_t i_crc = 0xffffffff;
767         for( i = 0; i < p_hdr->i_buffer; i++ )
768         i_crc = (i_crc << 8) ^
769             p_sys->crc32_table[((i_crc >> 24) ^ p_hdr->p_buffer[i]) & 0xff];
770
771         bits_write( &bits, 32, i_crc );
772     }
773
774     block_ChainAppend( p_buf, p_hdr );
775 }
776
777 /*
778  * Find stream to be muxed.
779  */
780 static int MuxGetStream( sout_mux_t *p_mux, int *pi_stream, mtime_t *pi_dts )
781 {
782     mtime_t i_dts;
783     int     i_stream;
784     int     i;
785
786     for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ )
787     {
788         sout_input_t *p_input = p_mux->pp_inputs[i];
789         block_t *p_data;
790
791         if( p_input->p_fifo->i_depth <= 0 )
792         {
793             if( p_input->p_fmt->i_cat == AUDIO_ES ||
794                 p_input->p_fmt->i_cat == VIDEO_ES )
795             {
796                 /* We need that audio+video fifo contain at least 1 packet */
797                 return VLC_EGENERIC;
798             }
799
800             /* SPU */
801             continue;
802         }
803
804         p_data = block_FifoShow( p_input->p_fifo );
805         if( i_stream == -1 || p_data->i_dts < i_dts )
806         {
807             i_stream = i;
808             i_dts    = p_data->i_dts;
809         }
810     }
811
812     *pi_stream = i_stream;
813     *pi_dts = i_dts;
814
815     return VLC_SUCCESS;
816 }