]> git.sesse.net Git - vlc/blob - modules/mux/mpeg/ts.c
* modules/mux/mpeg/ts.c: compilation fix.
[vlc] / modules / mux / mpeg / ts.c
1 /*****************************************************************************
2  * ts.c: MPEG-II TS Muxer
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Eric Petit <titer@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>
29
30 #include <vlc/vlc.h>
31 #include <vlc/input.h>
32 #include <vlc/sout.h>
33
34 #include "iso_lang.h"
35
36 #include "bits.h"
37 #include "pes.h"
38 #include "csa.h"
39
40 #ifdef HAVE_DVBPSI_DR_H
41 #   include <dvbpsi/dvbpsi.h>
42 #   include <dvbpsi/descriptor.h>
43 #   include <dvbpsi/pat.h>
44 #   include <dvbpsi/pmt.h>
45 #   include <dvbpsi/dr.h>
46 #   include <dvbpsi/psi.h>
47 #else
48 #   include "dvbpsi.h"
49 #   include "descriptor.h"
50 #   include "tables/pat.h"
51 #   include "tables/pmt.h"
52 #   include "descriptors/dr.h"
53 #   include "psi.h"
54 #endif
55
56 /*
57  * TODO:
58  *  - check PCR frequency requirement
59  *  - check PAT/PMT  "        "
60  *  - check PCR/PCR "soft"
61  *  - check if "registration" descriptor : "AC-3" should be a program
62  *    descriptor or an es one. (xine want an es one)
63  *
64  *  - remove creation of PAT/PMT without dvbpsi
65  *  - ?
66  * FIXME:
67  *  - subtitle support is far from perfect. I expect some subtitles drop
68  *    if they arrive a bit late
69  *    (We cannot rely on the fact that the fifo should be full)
70  */
71 /*****************************************************************************
72  * Module descriptor
73  *****************************************************************************/
74 static int     Open   ( vlc_object_t * );
75 static void    Close  ( vlc_object_t * );
76
77 #define VPID_TEXT N_("Video PID")
78 #define VPID_LONGTEXT N_("Assigns a fixed PID to the video stream. The PCR " \
79   "PID will automatically be the video.")
80 #define APID_TEXT N_("Audio PID")
81 #define APID_LONGTEXT N_("Assigns a fixed PID to the audio stream.")
82
83 #define SHAPING_TEXT N_("Shaping delay (ms)")
84 #define SHAPING_LONGTEXT N_("If enabled, the TS muxer will cut the " \
85   "stream in slices of the given duration, and ensure a constant bitrate " \
86   "between the two boundaries. This avoids having huge bitrate peaks for " \
87   "reference frames, in particular.")
88 #define KEYF_TEXT N_("Use keyframes")
89 #define KEYF_LONGTEXT N_("If enabled, and shaping is specified, " \
90   "the TS muxer will place the boundaries at the end of I pictures. In " \
91   "that case, the shaping duration given by the user is a worse case " \
92   "used when no reference frame is available. This enhances the efficiency " \
93   "of the shaping algorithm, since I frames are usually the biggest " \
94   "frames in the stream.")
95
96 #define PCR_TEXT N_("PCR delay (ms)")
97 #define PCR_LONGTEXT N_("This option allows you to set at which interval " \
98   "PCRs (Program Clock Reference) will be sent. " \
99   "This value should be below 100ms. (default is 30)")
100
101 #define DTS_TEXT N_("DTS delay (ms)")
102 #define DTS_LONGTEXT N_("This option will delay the DTS (decoding time " \
103   "stamps) and PTS (presentation timestamps) of the data in the " \
104   "stream, compared to the PCRs. This allows for some buffering inside " \
105   "the client decoder.")
106
107 #define ACRYPT_TEXT N_("Crypt audio")
108 #define ACRYPT_LONGTEXT N_("Crypt audio using CSA")
109
110 #define CK_TEXT N_("CSA Key")
111 #define CK_LONGTEXT N_("Defines the CSA encryption key. This must be a " \
112   "16 char string (8 hexadecimal bytes).")
113
114 #define SOUT_CFG_PREFIX "sout-ts-"
115
116 vlc_module_begin();
117     set_description( _("TS muxer (libdvbpsi)") );
118     set_capability( "sout mux", 120 );
119     add_shortcut( "ts" );
120
121     add_integer( SOUT_CFG_PREFIX "pid-video", 0, NULL,VPID_TEXT, VPID_LONGTEXT,
122                                   VLC_TRUE );
123     add_integer( SOUT_CFG_PREFIX "pid-audio", 0, NULL, APID_TEXT,
124                  APID_LONGTEXT, VLC_TRUE );
125
126     add_integer( SOUT_CFG_PREFIX "shaping", 200, NULL,SHAPING_TEXT,
127                  SHAPING_LONGTEXT, VLC_TRUE );
128     add_bool( SOUT_CFG_PREFIX "use-key-frames", VLC_FALSE, NULL, KEYF_TEXT,
129               KEYF_LONGTEXT, VLC_TRUE );
130
131     add_integer( SOUT_CFG_PREFIX "pcr", 30, NULL, PCR_TEXT, PCR_LONGTEXT,
132                  VLC_TRUE );
133     add_integer( SOUT_CFG_PREFIX "dts-delay", 200, NULL, DTS_TEXT,
134                  DTS_LONGTEXT, VLC_TRUE );
135
136     add_bool( SOUT_CFG_PREFIX "crypt-audio", VLC_TRUE, NULL, ACRYPT_TEXT,
137               ACRYPT_LONGTEXT, VLC_TRUE );
138
139     add_string( SOUT_CFG_PREFIX "csa-ck", NULL, NULL, CK_TEXT, CK_LONGTEXT,
140                 VLC_TRUE );
141
142     set_callbacks( Open, Close );
143 vlc_module_end();
144
145 /*****************************************************************************
146  * Local data structures
147  *****************************************************************************/
148 static const char *ppsz_sout_options[] = {
149     "pid-video", "pid-audio", "shaping", "pcr",
150     "use-key-frames", "dts-delay", "csa-ck", "crypt-audio", NULL
151 };
152
153 #define SOUT_BUFFER_FLAGS_PRIVATE_PCR  ( 1 << BLOCK_FLAG_PRIVATE_SHIFT )
154 #define SOUT_BUFFER_FLAGS_PRIVATE_CSA  ( 2 << BLOCK_FLAG_PRIVATE_SHIFT )
155 typedef struct
156 {
157     int     i_depth;
158     block_t *p_first;
159     block_t **pp_last;
160 } sout_buffer_chain_t;
161
162 static inline void BufferChainInit  ( sout_buffer_chain_t *c )
163 {
164     c->i_depth = 0;
165     c->p_first = NULL;
166     c->pp_last = &c->p_first;
167 }
168 static inline void BufferChainAppend( sout_buffer_chain_t *c, block_t *b )
169 {
170     *c->pp_last = b;
171     c->i_depth++;
172
173     while( b->p_next )
174     {
175         b = b->p_next;
176         c->i_depth++;
177     }
178     c->pp_last = &b->p_next;
179 }
180 static inline block_t *BufferChainGet( sout_buffer_chain_t *c )
181 {
182     block_t *b = c->p_first;
183
184     if( b )
185     {
186         c->i_depth--;
187         c->p_first = b->p_next;
188
189         if( c->p_first == NULL )
190         {
191             c->pp_last = &c->p_first;
192         }
193
194         b->p_next = NULL;
195     }
196     return b;
197 }
198 static inline block_t *BufferChainPeek( sout_buffer_chain_t *c )
199 {
200     block_t *b = c->p_first;
201
202     return b;
203 }
204 static inline void BufferChainClean( sout_instance_t *p_sout,
205                                      sout_buffer_chain_t *c )
206 {
207     block_t *b;
208
209     while( ( b = BufferChainGet( c ) ) )
210     {
211         block_Release( b );
212     }
213     BufferChainInit( c );
214 }
215
216 typedef struct ts_stream_t
217 {
218     int             i_pid;
219     vlc_fourcc_t    i_codec;
220
221     int             i_stream_type;
222     int             i_stream_id;
223     int             i_continuity_counter;
224
225     /* to be used for carriege of DIV3 */
226     vlc_fourcc_t    i_bih_codec;
227     int             i_bih_width, i_bih_height;
228
229     /* Specific to mpeg4 in mpeg2ts */
230     int             i_es_id;
231
232     int             i_decoder_specific_info;
233     uint8_t         *p_decoder_specific_info;
234
235     /* language is iso639-2T */
236     uint8_t         lang[3];
237
238     sout_buffer_chain_t chain_pes;
239     mtime_t             i_pes_dts;
240     mtime_t             i_pes_length;
241     int                 i_pes_used;
242     vlc_bool_t          b_key_frame;
243
244 } ts_stream_t;
245
246 struct sout_mux_sys_t
247 {
248     int             i_pcr_pid;
249     sout_input_t    *p_pcr_input;
250
251     int             i_audio_bound;
252     int             i_video_bound;
253
254     int             i_pid_video;
255     int             i_pid_audio;
256     int             i_pid_free; // first usable pid
257
258     int             i_pat_version_number;
259     ts_stream_t     pat;
260
261     int             i_pmt_version_number;
262     ts_stream_t     pmt;        // Up to now only one program
263
264     int             i_mpeg4_streams;
265
266     int             i_null_continuity_counter;  /* Needed ? */
267
268     /* for TS building */
269     int64_t             i_bitrate_min;
270     int64_t             i_bitrate_max;
271
272     int64_t             i_shaping_delay;
273     int64_t             i_pcr_delay;
274
275     int64_t             i_dts_delay;
276
277     vlc_bool_t          b_use_key_frames;
278
279     mtime_t             i_pcr;  /* last PCR emited */
280
281     csa_t               *csa;
282     vlc_bool_t          b_crypt_audio;
283 };
284
285
286 /* Reserve a pid and return it */
287 static int  AllocatePID( sout_mux_sys_t *p_sys, int i_cat )
288 {
289     int i_pid;
290     if ( i_cat == VIDEO_ES && p_sys->i_pid_video )
291     {
292         i_pid = p_sys->i_pid_video;
293         p_sys->i_pid_video = 0;
294     }
295     else if ( i_cat == AUDIO_ES && p_sys->i_pid_audio )
296     {
297         i_pid = p_sys->i_pid_audio;
298         p_sys->i_pid_audio = 0;
299     }
300     else
301     {
302         i_pid = ++p_sys->i_pid_free;
303     }
304     return i_pid;
305 }
306
307 /*****************************************************************************
308  * Local prototypes
309  *****************************************************************************/
310 static int     Capability(sout_mux_t *, int, void *, void * );
311 static int     AddStream( sout_mux_t *, sout_input_t * );
312 static int     DelStream( sout_mux_t *, sout_input_t * );
313 static int     Mux      ( sout_mux_t * );
314
315 static void TSSchedule  ( sout_mux_t *p_mux, sout_buffer_chain_t *p_chain_ts,
316                           mtime_t i_pcr_length, mtime_t i_pcr_dts );
317 static void TSDate      ( sout_mux_t *p_mux, sout_buffer_chain_t *p_chain_ts,
318                           mtime_t i_pcr_length, mtime_t i_pcr_dts );
319 static void GetPAT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
320 static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
321
322 static block_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr );
323 static void TSSetPCR( block_t *p_ts, mtime_t i_dts );
324
325 static void PEStoTS  ( sout_instance_t *, sout_buffer_chain_t *, block_t *, ts_stream_t * );
326
327 /*****************************************************************************
328  * Open:
329  *****************************************************************************/
330 static int Open( vlc_object_t *p_this )
331 {
332     sout_mux_t          *p_mux =(sout_mux_t*)p_this;
333     sout_mux_sys_t      *p_sys;
334     vlc_value_t         val;
335
336     msg_Dbg( p_mux, "Open" );
337     sout_ParseCfg( p_mux, SOUT_CFG_PREFIX, ppsz_sout_options, p_mux->p_cfg );
338
339     p_sys = malloc( sizeof( sout_mux_sys_t ) );
340
341     p_mux->pf_capacity  = Capability;
342     p_mux->pf_addstream = AddStream;
343     p_mux->pf_delstream = DelStream;
344     p_mux->pf_mux       = Mux;
345     p_mux->p_sys        = p_sys;
346
347     srand( (uint32_t)mdate() );
348
349     p_sys->i_audio_bound = 0;
350     p_sys->i_video_bound = 0;
351
352     p_sys->i_pat_version_number = rand() % 32;
353     p_sys->pat.i_pid = 0;
354     p_sys->pat.i_continuity_counter = 0;
355
356     p_sys->i_pmt_version_number = rand() % 32;
357     p_sys->pmt.i_pid = 0x42;
358     p_sys->pmt.i_continuity_counter = 0;
359
360     p_sys->i_pid_free = 0x43;
361
362     var_Get( p_mux, SOUT_CFG_PREFIX "pid-video", &val );
363     p_sys->i_pid_video = val.i_int;
364     if ( p_sys->i_pid_video > p_sys->i_pid_free )
365     {
366         p_sys->i_pid_free = p_sys->i_pid_video + 1;
367     }
368
369     var_Get( p_mux, SOUT_CFG_PREFIX "pid-audio", &val );
370     p_sys->i_pid_audio = val.i_int;
371     if ( p_sys->i_pid_audio > p_sys->i_pid_free )
372     {
373         p_sys->i_pid_free = p_sys->i_pid_audio + 1;
374     }
375
376     p_sys->i_pcr_pid = 0x1fff;
377     p_sys->p_pcr_input = NULL;
378
379     p_sys->i_mpeg4_streams = 0;
380
381     p_sys->i_null_continuity_counter = 0;
382
383     /* Allow to create constrained stream */
384     var_Get( p_mux, SOUT_CFG_PREFIX "bmin", &val );
385     p_sys->i_bitrate_min = 0;/*val.i_int;*/
386
387     var_Get( p_mux, SOUT_CFG_PREFIX "bmax", &val );
388     p_sys->i_bitrate_max = 0;/*val.i_int;*/
389
390     if( p_sys->i_bitrate_min > 0 && p_sys->i_bitrate_max > 0 &&
391         p_sys->i_bitrate_min > p_sys->i_bitrate_max )
392     {
393         msg_Err( p_mux, "incompatible minimum and maximum bitrate, "
394                  "disabling bitrate control" );
395         p_sys->i_bitrate_min = 0;
396         p_sys->i_bitrate_max = 0;
397     }
398     if( p_sys->i_bitrate_min > 0 || p_sys->i_bitrate_max > 0 )
399     {
400         msg_Err( p_mux, "bmin and bmax no more supported "
401                  "(if you need them report it)" );
402     }
403
404     var_Get( p_mux, SOUT_CFG_PREFIX "shaping", &val );
405     p_sys->i_shaping_delay = (int64_t)val.i_int * 1000;
406     if( p_sys->i_shaping_delay <= 0 )
407     {
408         msg_Err( p_mux,
409                  "invalid shaping ("I64Fd"ms) resetting to 200ms",
410                  p_sys->i_shaping_delay / 1000 );
411         p_sys->i_shaping_delay = 200000;
412     }
413
414     var_Get( p_mux, SOUT_CFG_PREFIX "pcr", &val );
415     p_sys->i_pcr_delay = (int64_t)val.i_int * 1000;
416     if( p_sys->i_pcr_delay <= 0 ||
417         p_sys->i_pcr_delay >= p_sys->i_shaping_delay )
418     {
419         msg_Err( p_mux,
420                  "invalid pcr delay ("I64Fd"ms) resetting to 30ms",
421                  p_sys->i_pcr_delay / 1000 );
422         p_sys->i_pcr_delay = 30000;
423     }
424
425     var_Get( p_mux, SOUT_CFG_PREFIX "dts-delay", &val );
426     p_sys->i_dts_delay = (int64_t)val.i_int * 1000;
427
428     msg_Dbg( p_mux, "shaping="I64Fd" pcr="I64Fd" dts_delay="I64Fd,
429              p_sys->i_shaping_delay, p_sys->i_pcr_delay, p_sys->i_dts_delay );
430
431     var_Get( p_mux, SOUT_CFG_PREFIX "use-key-frames", &val );
432     p_sys->b_use_key_frames = val.b_bool;
433
434     /* for TS generation */
435     p_sys->i_pcr    = 0;
436
437     p_sys->csa      = NULL;
438     var_Get( p_mux, SOUT_CFG_PREFIX "csa-ck", &val );
439     if( val.psz_string )
440     {
441         char *psz = val.psz_string;
442
443         /* skip 0x */
444         if( psz[0] == '0' && ( psz[1] == 'x' || psz[1] == 'X' ) )
445         {
446             psz += 2;
447         }
448         if( strlen( psz ) != 16 )
449         {
450             msg_Dbg( p_mux, "invalid csa ck (it must be 16 chars long)" );
451         }
452         else
453         {
454             uint64_t i_ck = strtoll( psz, NULL, 16 );
455             uint8_t  ck[8];
456             int      i;
457
458             for( i = 0; i < 8; i++ )
459             {
460                 ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff;
461             }
462
463             msg_Dbg( p_mux, "using CSA scrambling with ck=%x:%x:%x:%x:%x:%x:%x:%x",
464                      ck[0], ck[1], ck[2], ck[3], ck[4], ck[5], ck[6], ck[7] );
465
466             p_sys->csa = csa_New();
467             csa_SetCW( p_sys->csa, ck, ck );
468         }
469     }
470     if( val.psz_string ) free( val.psz_string );
471
472     var_Get( p_mux, SOUT_CFG_PREFIX "crypt-audio", &val );
473     p_sys->b_crypt_audio = val.b_bool;
474
475     return VLC_SUCCESS;
476 }
477
478 /*****************************************************************************
479  * Close:
480  *****************************************************************************/
481 static void Close( vlc_object_t * p_this )
482 {
483     sout_mux_t          *p_mux = (sout_mux_t*)p_this;
484     sout_mux_sys_t      *p_sys = p_mux->p_sys;
485
486     msg_Dbg( p_mux, "Close" );
487     if( p_sys->csa )
488     {
489         csa_Delete( p_sys->csa );
490     }
491
492     free( p_sys );
493 }
494
495 /*****************************************************************************
496  * Capability:
497  *****************************************************************************/
498 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args,
499                        void *p_answer )
500 {
501    switch( i_query )
502    {
503         case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
504             *(vlc_bool_t*)p_answer = VLC_TRUE;
505             return( SOUT_MUX_CAP_ERR_OK );
506         default:
507             return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
508    }
509 }
510
511 /*****************************************************************************
512  * AddStream: called for each stream addition
513  *****************************************************************************/
514 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
515 {
516     sout_mux_sys_t      *p_sys = p_mux->p_sys;
517     ts_stream_t         *p_stream;
518
519     p_input->p_sys = p_stream = malloc( sizeof( ts_stream_t ) );
520
521     /* Init this new stream */
522     p_stream->i_pid = AllocatePID( p_sys, p_input->p_fmt->i_cat );
523     p_stream->i_codec = p_input->p_fmt->i_codec;
524     p_stream->i_continuity_counter    = 0;
525     p_stream->i_decoder_specific_info = 0;
526     p_stream->p_decoder_specific_info = NULL;
527
528     msg_Dbg( p_mux, "adding input codec=%4.4s pid=%d",
529              (char*)&p_input->p_fmt->i_codec, p_stream->i_pid );
530
531     /* All others fields depand on codec */
532     switch( p_input->p_fmt->i_cat )
533     {
534         case VIDEO_ES:
535             switch( p_input->p_fmt->i_codec )
536             {
537                 case VLC_FOURCC( 'm', 'p','g', 'v' ):
538                     /* TODO: do we need to check MPEG-I/II ? */
539                     p_stream->i_stream_type = 0x02;
540                     p_stream->i_stream_id = 0xe0;
541                     break;
542                 case VLC_FOURCC( 'm', 'p','4', 'v' ):
543                     p_stream->i_stream_type = 0x10;
544                     p_stream->i_stream_id = 0xfa;
545                     p_sys->i_mpeg4_streams++;
546                     p_stream->i_es_id = p_stream->i_pid;
547                     break;
548                 case VLC_FOURCC( 'h', '2','6', '4' ):
549                     p_stream->i_stream_type = 0x1b;
550                     p_stream->i_stream_id = 0xe0;
551                     break;
552                 /* XXX dirty dirty but somebody want that:
553                  *     using crapy MS-codec XXX */
554                 /* I didn't want to do that :P */
555                 case VLC_FOURCC( 'H', '2', '6', '3' ):
556                 case VLC_FOURCC( 'I', '2', '6', '3' ):
557                 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
558                 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
559                 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
560                 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
561                 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
562                 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
563                     p_stream->i_stream_type = 0xa0; // private
564                     p_stream->i_stream_id = 0xa0;   // beurk
565                     p_stream->i_bih_codec  = p_input->p_fmt->i_codec;
566                     p_stream->i_bih_width  = p_input->p_fmt->video.i_width;
567                     p_stream->i_bih_height = p_input->p_fmt->video.i_height;
568                     break;
569                 default:
570                     free( p_stream );
571                     return VLC_EGENERIC;
572             }
573             p_sys->i_video_bound++;
574             break;
575
576         case AUDIO_ES:
577             switch( p_input->p_fmt->i_codec )
578             {
579                 case VLC_FOURCC( 'm', 'p','g', 'a' ):
580                     p_stream->i_stream_type =
581                         p_input->p_fmt->audio.i_rate >= 32000 ? 0x03 : 0x04;
582                     p_stream->i_stream_id = 0xc0;
583                     break;
584                 case VLC_FOURCC( 'a', '5','2', ' ' ):
585                     p_stream->i_stream_type = 0x81;
586                     p_stream->i_stream_id = 0xbd;
587                     break;
588                 case VLC_FOURCC( 'l', 'p','c', 'm' ):
589                     p_stream->i_stream_type = 0x83;
590                     p_stream->i_stream_id = 0xbd;
591                     break;
592                 case VLC_FOURCC( 'd', 't','s', ' ' ):
593                     p_stream->i_stream_type = 0x06;
594                     p_stream->i_stream_id = 0xbd;
595                     break;
596
597                 case VLC_FOURCC( 'm', 'p','4', 'a' ):
598                     p_stream->i_stream_type = 0x11;
599                     p_stream->i_stream_id = 0xfa;
600                     p_sys->i_mpeg4_streams++;
601                     p_stream->i_es_id = p_stream->i_pid;
602                     break;
603                 default:
604                     free( p_stream );
605                     return VLC_EGENERIC;
606             }
607             p_sys->i_audio_bound++;
608             break;
609
610         case SPU_ES:
611             switch( p_input->p_fmt->i_codec )
612             {
613                 case VLC_FOURCC( 's', 'p','u', ' ' ):
614                     p_stream->i_stream_type = 0x82;
615                     p_stream->i_stream_id = 0xbd;
616                     break;
617                 case VLC_FOURCC( 's', 'u','b', 't' ):
618                     p_stream->i_stream_type = 0x12;
619                     p_stream->i_stream_id = 0xfa;
620                     p_sys->i_mpeg4_streams++;
621                     p_stream->i_es_id = p_stream->i_pid;
622                     break;
623                 case VLC_FOURCC('d','v','b','s'):
624                     p_stream->i_stream_type = 0x06;
625                     p_stream->i_es_id = p_input->p_fmt->subs.dvb.i_id;
626                     p_stream->i_stream_id = 0xa0;
627                     break;
628                 default:
629                     free( p_stream );
630                     return VLC_EGENERIC;
631             }
632             break;
633
634         default:
635             free( p_stream );
636             return VLC_EGENERIC;
637     }
638
639     p_stream->lang[0] =
640     p_stream->lang[1] =
641     p_stream->lang[2] = '\0';
642     if( p_input->p_fmt->psz_language )
643     {
644         char *psz = p_input->p_fmt->psz_language;
645         const iso639_lang_t *pl = NULL;
646
647         if( strlen( psz ) == 2 )
648         {
649             pl = GetLang_1( psz );
650         }
651         else if( strlen( psz ) == 3 )
652         {
653             pl = GetLang_2B( psz );
654             if( !strcmp( pl->psz_iso639_1, "??" ) )
655             {
656                 pl = GetLang_2T( psz );
657             }
658         }
659         if( pl && strcmp( pl->psz_iso639_1, "??" ) )
660         {
661             p_stream->lang[0] = pl->psz_iso639_2T[0];
662             p_stream->lang[1] = pl->psz_iso639_2T[1];
663             p_stream->lang[2] = pl->psz_iso639_2T[2];
664
665             msg_Dbg( p_mux, "    - lang=%c%c%c",
666                      p_stream->lang[0], p_stream->lang[1], p_stream->lang[2] );
667         }
668     }
669
670
671     /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
672     p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra;
673     if( p_stream->i_decoder_specific_info > 0 )
674     {
675         p_stream->p_decoder_specific_info =
676             malloc( p_stream->i_decoder_specific_info );
677         memcpy( p_stream->p_decoder_specific_info,
678                 p_input->p_fmt->p_extra,
679                 p_input->p_fmt->i_extra );
680     }
681
682     /* Create decoder specific info for subt */
683     if( p_stream->i_codec == VLC_FOURCC( 's', 'u','b', 't' ) )
684     {
685         uint8_t *p;
686
687         p_stream->i_decoder_specific_info = 55;
688         p_stream->p_decoder_specific_info = p =
689             malloc( p_stream->i_decoder_specific_info );
690
691         p[0] = 0x10;    /* textFormat, 0x10 for 3GPP TS 26.245 */
692         p[1] = 0x00;    /* flags: 1b: associated video info flag
693                                   3b: reserved
694                                   1b: duration flag
695                                   3b: reserved */
696         p[2] = 52;      /* remaining size */
697
698         p += 3;
699
700         p[0] = p[1] = p[2] = p[3] = 0; p+=4;    /* display flags */
701         *p++ = 0;  /* horizontal justification (-1: left, 0 center, 1 right) */
702         *p++ = 1;  /* vertical   justification (-1: top, 0 center, 1 bottom) */
703
704         p[0] = p[1] = p[2] = 0x00; p+=3;/* background rgb */
705         *p++ = 0xff;                    /* background a */
706
707         p[0] = p[1] = 0; p += 2;        /* text box top */
708         p[0] = p[1] = 0; p += 2;        /* text box left */
709         p[0] = p[1] = 0; p += 2;        /* text box bottom */
710         p[0] = p[1] = 0; p += 2;        /* text box right */
711
712         p[0] = p[1] = 0; p += 2;        /* start char */
713         p[0] = p[1] = 0; p += 2;        /* end char */
714         p[0] = p[1] = 0; p += 2;        /* default font id */
715
716         *p++ = 0;                       /* font style flags */
717         *p++ = 12;                      /* font size */
718
719         p[0] = p[1] = p[2] = 0x00; p+=3;/* foreground rgb */
720         *p++ = 0x00;                    /* foreground a */
721
722         p[0] = p[1] = p[2] = 0; p[3] = 22; p += 4;
723         memcpy( p, "ftab", 4 ); p += 4;
724         *p++ = 0; *p++ = 1;             /* entry count */
725         p[0] = p[1] = 0; p += 2;        /* font id */
726         *p++ = 9;                       /* font name length */
727         memcpy( p, "Helvetica", 9 );    /* font name */
728     }
729
730     /* Init pes chain */
731     BufferChainInit( &p_stream->chain_pes );
732     p_stream->i_pes_dts    = 0;
733     p_stream->i_pes_length = 0;
734     p_stream->i_pes_used   = 0;
735     p_stream->b_key_frame  = 0;
736
737     /* We only change PMT version (PAT isn't changed) */
738     p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
739
740     /* Update pcr_pid */
741     if( p_input->p_fmt->i_cat != SPU_ES &&
742         ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
743     {
744         if( p_sys->p_pcr_input )
745         {
746             /* There was already a PCR stream, so clean context */
747             /* FIXME */
748         }
749         p_sys->i_pcr_pid   = p_stream->i_pid;
750         p_sys->p_pcr_input = p_input;
751
752         msg_Dbg( p_mux, "new PCR PID is %d", p_sys->i_pcr_pid );
753     }
754
755     return VLC_SUCCESS;
756 }
757
758 /*****************************************************************************
759  * DelStream: called before a stream deletion
760  *****************************************************************************/
761 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
762 {
763     sout_mux_sys_t  *p_sys = p_mux->p_sys;
764     ts_stream_t     *p_stream;
765     vlc_value_t     val;
766
767     p_stream = (ts_stream_t*)p_input->p_sys;
768     msg_Dbg( p_mux, "removing input pid=%d", p_stream->i_pid );
769
770     if( p_sys->i_pcr_pid == p_stream->i_pid )
771     {
772         int i;
773
774         /* Find a new pcr stream (Prefer Video Stream) */
775         p_sys->i_pcr_pid = 0x1fff;
776         p_sys->p_pcr_input = NULL;
777         for( i = 0; i < p_mux->i_nb_inputs; i++ )
778         {
779             if( p_mux->pp_inputs[i] == p_input )
780             {
781                 continue;
782             }
783
784             if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
785             {
786                 p_sys->i_pcr_pid  =
787                     ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
788                 p_sys->p_pcr_input= p_mux->pp_inputs[i];
789                 break;
790             }
791             else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
792                      p_sys->i_pcr_pid == 0x1fff )
793             {
794                 p_sys->i_pcr_pid  =
795                     ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
796                 p_sys->p_pcr_input= p_mux->pp_inputs[i];
797             }
798         }
799         if( p_sys->p_pcr_input )
800         {
801             /* Empty TS buffer */
802             /* FIXME */
803         }
804         msg_Dbg( p_mux, "new PCR PID is %d", p_sys->i_pcr_pid );
805     }
806
807     /* Empty all data in chain_pes */
808     BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
809
810     if( p_stream->p_decoder_specific_info )
811     {
812         free( p_stream->p_decoder_specific_info );
813     }
814     if( p_stream->i_stream_id == 0xfa ||
815         p_stream->i_stream_id == 0xfb ||
816         p_stream->i_stream_id == 0xfe )
817     {
818         p_sys->i_mpeg4_streams--;
819     }
820
821     var_Get( p_mux, SOUT_CFG_PREFIX "pid-video", &val );
822     if( val.i_int > 0 )
823     {
824         int i_pid_video = val.i_int;
825         if ( i_pid_video == p_stream->i_pid )
826         {
827             p_sys->i_pid_video = i_pid_video;
828             msg_Dbg( p_mux, "freeing video PID %d", i_pid_video );
829         }
830     }
831     var_Get( p_mux, SOUT_CFG_PREFIX "pid-audio", &val );
832     if( val.i_int > 0 )
833     {
834         int i_pid_audio = val.i_int;
835         if ( i_pid_audio == p_stream->i_pid )
836         {
837             p_sys->i_pid_audio = i_pid_audio;
838             msg_Dbg( p_mux, "freeing audio PID %d", i_pid_audio );
839         }
840     }
841     free( p_stream );
842
843     /* We only change PMT version (PAT isn't changed) */
844     p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
845
846     return VLC_SUCCESS;
847 }
848
849 /*****************************************************************************
850  * Mux: Call each time there is new data for at least one stream
851  *****************************************************************************
852  *
853  *****************************************************************************/
854 static int Mux( sout_mux_t *p_mux )
855 {
856     sout_mux_sys_t  *p_sys = p_mux->p_sys;
857     ts_stream_t     *p_pcr_stream;
858
859     if( p_sys->i_pcr_pid == 0x1fff )
860     {
861         msg_Dbg( p_mux, "waiting for PCR streams" );
862         msleep( 1000 );
863         return VLC_SUCCESS;
864     }
865     p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
866
867     for( ;; )
868     {
869         sout_buffer_chain_t chain_ts;
870         int                 i_packet_count;
871         int                 i_packet_pos;
872         mtime_t             i_pcr_dts;
873         mtime_t             i_pcr_length;
874         mtime_t             i_shaping_delay;
875         int i;
876
877         if( p_pcr_stream->b_key_frame )
878         {
879             i_shaping_delay = p_pcr_stream->i_pes_length;
880         }
881         else
882         {
883             i_shaping_delay = p_sys->i_shaping_delay;
884         }
885
886         /* 1: get enough PES packet for all input */
887         for( ;; )
888         {
889             vlc_bool_t b_ok = VLC_TRUE;
890             block_t *p_data;
891
892             /* Accumulate enough data in the pcr stream (>i_shaping_delay) */
893             /* Accumulate enough data in all other stream ( >= length of pcr)*/
894             for( i = 0; i < p_mux->i_nb_inputs; i++ )
895             {
896                 sout_input_t *p_input = p_mux->pp_inputs[i];
897                 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
898                 int64_t i_spu_length = 0;
899                 int64_t i_spu_dts    = 0;
900
901
902                 if( ( p_stream == p_pcr_stream &&
903                       p_stream->i_pes_length < i_shaping_delay ) ||
904                     p_stream->i_pes_dts + p_stream->i_pes_length <
905                     p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
906                 {
907                     /* Need more data */
908                     if( p_input->p_fifo->i_depth <= 50 )
909                     {
910                         if( p_input->p_fmt->i_cat == AUDIO_ES ||
911                             p_input->p_fmt->i_cat == VIDEO_ES )
912                         {
913                             /* We need more data */
914                             return VLC_SUCCESS;
915                         }
916                         else if( p_input->p_fifo->i_depth <= 0 )
917                         {
918                             /* spu, only one packet is needed */
919                             continue;
920                         }
921                     }
922                     b_ok = VLC_FALSE;
923
924                     p_data = block_FifoGet( p_input->p_fifo );
925                     if( p_input->p_fmt->i_codec == VLC_FOURCC('s','u','b','t'))
926                     {
927                         i_spu_length = p_data->i_length;/* save info for SPU */
928                         i_spu_dts    = p_data->i_dts;
929                     }
930                     if( p_input->p_fifo->i_depth > 0 )
931                     {
932                         block_t *p_next = block_FifoShow( p_input->p_fifo );
933
934                         p_data->i_length = p_next->i_dts - p_data->i_dts;
935                     }
936
937                     if( ( p_pcr_stream->i_pes_dts > 0 &&
938                           p_data->i_dts - 2000000 > p_pcr_stream->i_pes_dts +
939                           p_pcr_stream->i_pes_length ) ||
940                         p_data->i_dts < p_stream->i_pes_dts ||
941                         ( p_stream->i_pes_dts > 0 &&
942                           p_input->p_fmt->i_cat != SPU_ES &&
943                           p_data->i_dts - 2000000 > p_stream->i_pes_dts +
944                           p_stream->i_pes_length ) )
945                     {
946                         msg_Warn( p_mux, "packet with too strange dts "
947                                   "(dts="I64Fd",old="I64Fd",pcr="I64Fd")",
948                                   p_data->i_dts, p_stream->i_pes_dts,
949                                   p_pcr_stream->i_pes_dts );
950                         block_Release( p_data );
951
952                         BufferChainClean( p_mux->p_sout,
953                                           &p_stream->chain_pes );
954                         p_stream->i_pes_dts = 0;
955                         p_stream->i_pes_used = 0;
956                         p_stream->i_pes_length = 0;
957
958                         BufferChainClean( p_mux->p_sout,
959                                           &p_pcr_stream->chain_pes );
960                         p_pcr_stream->i_pes_dts = 0;
961                         p_pcr_stream->i_pes_used = 0;
962                         p_pcr_stream->i_pes_length = 0;
963
964                     }
965                     else
966                     {
967                         if( p_input->p_fmt->i_cat == SPU_ES )
968                         {
969                             /* Arbitrary */
970                             p_data->i_length = 1000;
971                             if( p_input->p_fmt->i_codec ==
972                                 VLC_FOURCC('s','u','b','t') )
973                             {
974                                 /* Prepend header */
975                                 p_data = block_Realloc( p_data, 2,
976                                                         p_data->i_buffer );
977                                 p_data->p_buffer[0] =
978                                     ( (p_data->i_buffer - 2) >> 8) & 0xff;
979                                 p_data->p_buffer[1] =
980                                     ( (p_data->i_buffer - 2)     ) & 0xff;
981
982                                 /* remove trailling \0 if any */
983                                 if( p_data->i_buffer > 2 &&
984                                     p_data->p_buffer[p_data->i_buffer -1] ==
985                                     '\0' )
986                                     p_data->i_buffer--;
987                             }
988                         }
989                         else if( p_data->i_length < 0 ||
990                                  p_data->i_length > 2000000 )
991                         {
992                             /* FIXME choose a better value, but anyway we
993                              * should never have to do that */
994                             p_data->i_length = 1000;
995                         }
996
997                         p_stream->i_pes_length += p_data->i_length;
998                         if( p_stream->i_pes_dts == 0 )
999                         {
1000                             p_stream->i_pes_dts = p_data->i_dts;
1001                         }
1002
1003                         /* Convert to pes */
1004                         if( p_stream->i_stream_id == 0xa0 &&
1005                             p_data->i_pts <= 0 )
1006                         {
1007                             /* XXX yes I know, it's awfull, but it's needed,
1008                              * so don't remove it ... */
1009                             p_data->i_pts = p_data->i_dts;
1010                         }
1011                         E_( EStoPES )( p_mux->p_sout, &p_data, p_data,
1012                                        p_stream->i_stream_id, 1 );
1013
1014                         BufferChainAppend( &p_stream->chain_pes, p_data );
1015
1016                         if( p_sys->b_use_key_frames && p_stream == p_pcr_stream
1017                             && (p_data->i_flags & BLOCK_FLAG_TYPE_I )
1018                             && (p_stream->i_pes_length > 300000) )
1019                         {
1020                             i_shaping_delay = p_stream->i_pes_length;
1021                             p_stream->b_key_frame = 1;
1022                         }
1023
1024                         /* Append a empty sub (sub text only) */
1025                         if( i_spu_length > 0 )
1026                         {
1027                             block_t *p_spu = block_New( p_mux, 3 );
1028
1029                             p_spu->i_dts = p_spu->i_pts = i_spu_dts +
1030                                 i_spu_length;
1031                             p_spu->i_length = 1000;
1032
1033                             p_spu->p_buffer[0] = 0;
1034                             p_spu->p_buffer[1] = 1;
1035                             p_spu->p_buffer[2] = ' ';
1036
1037                             p_stream->i_pes_length += p_spu->i_length;
1038                             E_( EStoPES )( p_mux->p_sout, &p_spu, p_spu,
1039                                            p_stream->i_stream_id, 1 );
1040                             BufferChainAppend( &p_stream->chain_pes, p_spu );
1041                         }
1042                     }
1043                 }
1044             }
1045
1046             if( b_ok )
1047             {
1048                 break;
1049             }
1050         }
1051
1052         /* save */
1053         i_pcr_dts      = p_pcr_stream->i_pes_dts;
1054         i_pcr_length   = p_pcr_stream->i_pes_length;
1055         p_pcr_stream->b_key_frame = 0;
1056
1057         /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */
1058         /* 2: calculate non accurate total size of muxed ts */
1059         i_packet_count = 0;
1060         for( i = 0; i < p_mux->i_nb_inputs; i++ )
1061         {
1062             ts_stream_t *p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
1063             block_t *p_pes;
1064
1065             /* False for pcr stream but it will be enough to do PCR algo */
1066             for( p_pes = p_stream->chain_pes.p_first; p_pes != NULL;
1067                  p_pes = p_pes->p_next )
1068             {
1069                 int i_size = p_pes->i_buffer;
1070                 if( p_pes->i_dts + p_pes->i_length >
1071                     p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
1072                 {
1073                     mtime_t i_frag = p_pcr_stream->i_pes_dts +
1074                         p_pcr_stream->i_pes_length - p_pes->i_dts;
1075                     if( i_frag < 0 )
1076                     {
1077                         /* Next stream */
1078                         break;
1079                     }
1080                     i_size = p_pes->i_buffer * i_frag / p_pes->i_length;
1081                 }
1082                 i_packet_count += ( i_size + 183 ) / 184;
1083             }
1084         }
1085         /* add overhead for PCR (not really exact) */
1086         i_packet_count += (8 * i_pcr_length / p_sys->i_pcr_delay + 175) / 176;
1087
1088
1089         /* 3: mux PES into TS */
1090         BufferChainInit( &chain_ts );
1091         /* append PAT/PMT  -> FIXME with big pcr delay it won't have enough pat/pmt */
1092         GetPAT( p_mux, &chain_ts);
1093         GetPMT( p_mux, &chain_ts );
1094         i_packet_pos = 0;
1095         i_packet_count += chain_ts.i_depth;
1096         /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */
1097
1098         for( ;; )
1099         {
1100             int         i_stream;
1101             mtime_t     i_dts;
1102             ts_stream_t *p_stream;
1103             sout_input_t *p_input;
1104             block_t *p_ts;
1105             vlc_bool_t   b_pcr;
1106
1107             /* Select stream (lowest dts) */
1108             for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
1109             {
1110                 p_input = p_mux->pp_inputs[i];
1111                 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
1112
1113                 if( p_stream->i_pes_dts == 0 )
1114                 {
1115                     continue;
1116                 }
1117
1118                 if( i_stream == -1 ||
1119                     p_stream->i_pes_dts < i_dts )
1120                 {
1121                     i_stream = i;
1122                     i_dts = p_stream->i_pes_dts;
1123                 }
1124             }
1125             if( i_stream == -1 || i_dts > i_pcr_dts + i_pcr_length )
1126             {
1127                 break;
1128             }
1129             p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1130
1131             /* do we need to issue pcr */
1132             b_pcr = VLC_FALSE;
1133             if( p_stream == p_pcr_stream &&
1134                 i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count >=
1135                 p_sys->i_pcr + p_sys->i_pcr_delay )
1136             {
1137                 b_pcr = VLC_TRUE;
1138                 p_sys->i_pcr = i_pcr_dts + i_packet_pos *
1139                     i_pcr_length / i_packet_count;
1140             }
1141
1142             /* Build the TS packet */
1143             p_ts = TSNew( p_mux, p_stream, b_pcr );
1144             if( p_sys->csa != NULL &&
1145                  (p_input->p_fmt->i_cat != AUDIO_ES || p_sys->b_crypt_audio) )
1146             {
1147                 p_ts->i_flags |= SOUT_BUFFER_FLAGS_PRIVATE_CSA;
1148             }
1149             i_packet_pos++;
1150
1151             /* */
1152             BufferChainAppend( &chain_ts, p_ts );
1153         }
1154
1155         /* 4: date and send */
1156         TSSchedule( p_mux, &chain_ts, i_pcr_length, i_pcr_dts );
1157     }
1158 }
1159
1160 static void TSSchedule( sout_mux_t *p_mux, sout_buffer_chain_t *p_chain_ts,
1161                         mtime_t i_pcr_length, mtime_t i_pcr_dts )
1162 {
1163     sout_mux_sys_t  *p_sys = p_mux->p_sys;
1164     sout_buffer_chain_t new_chain;
1165     int i_packet_count = p_chain_ts->i_depth;
1166     int i;
1167
1168     BufferChainInit( &new_chain );
1169
1170     if ( i_pcr_length <= 0 )
1171     {
1172         i_pcr_length = i_packet_count;
1173     }
1174
1175     for( i = 0; i < i_packet_count; i++ )
1176     {
1177         block_t *p_ts = BufferChainGet( p_chain_ts );
1178         mtime_t i_new_dts = i_pcr_dts + i_pcr_length * i / i_packet_count;
1179
1180         BufferChainAppend( &new_chain, p_ts );
1181
1182         if( p_ts->i_dts &&
1183             p_ts->i_dts + p_sys->i_dts_delay * 2/3 < i_new_dts )
1184         {
1185             mtime_t i_max_diff = i_new_dts - p_ts->i_dts;
1186             mtime_t i_cut_dts = p_ts->i_dts;
1187
1188             p_ts = BufferChainPeek( p_chain_ts );
1189             i++;
1190             i_new_dts = i_pcr_dts + i_pcr_length * i / i_packet_count;
1191             while ( p_ts != NULL && i_new_dts - p_ts->i_dts >= i_max_diff )
1192             {
1193                 p_ts = BufferChainGet( p_chain_ts );
1194                 i_max_diff = i_new_dts - p_ts->i_dts;
1195                 i_cut_dts = p_ts->i_dts;
1196                 BufferChainAppend( &new_chain, p_ts );
1197
1198                 p_ts = BufferChainPeek( p_chain_ts );
1199                 i++;
1200                 i_new_dts = i_pcr_dts + i_pcr_length * i / i_packet_count;
1201             }
1202             msg_Dbg( p_mux, "adjusting rate at "I64Fd"/"I64Fd" (%d/%d)",
1203                      i_cut_dts - i_pcr_dts, i_pcr_length, new_chain.i_depth,
1204                      p_chain_ts->i_depth );
1205             if ( new_chain.i_depth )
1206                 TSDate( p_mux, &new_chain,
1207                         i_cut_dts - i_pcr_dts,
1208                         i_pcr_dts );
1209             if ( p_chain_ts->i_depth )
1210                 TSSchedule( p_mux,
1211                             p_chain_ts, i_pcr_dts + i_pcr_length - i_cut_dts,
1212                             i_cut_dts );
1213             return;
1214         }
1215     }
1216
1217     if ( new_chain.i_depth )
1218         TSDate( p_mux, &new_chain, i_pcr_length, i_pcr_dts );
1219 }
1220
1221 static void TSDate( sout_mux_t *p_mux, sout_buffer_chain_t *p_chain_ts,
1222                     mtime_t i_pcr_length, mtime_t i_pcr_dts )
1223 {
1224     sout_mux_sys_t  *p_sys = p_mux->p_sys;
1225     int i_packet_count = p_chain_ts->i_depth;
1226     int i;
1227
1228     if ( i_pcr_length / 1000 > 0 )
1229     {
1230         int i_bitrate = ((uint64_t)i_packet_count * 188 * 8000)
1231                           / (uint64_t)(i_pcr_length / 1000);
1232         if ( p_sys->i_bitrate_max && p_sys->i_bitrate_max < i_bitrate )
1233         {
1234             msg_Warn( p_mux, "max bitrate exceeded at "I64Fd
1235                       " (%d bi/s for %d pkt in "I64Fd" us)",
1236                       i_pcr_dts + p_sys->i_shaping_delay * 3 / 2 - mdate(),
1237                       i_bitrate, i_packet_count, i_pcr_length);
1238         }
1239 #if 0
1240         else
1241         {
1242             msg_Dbg( p_mux, "starting at "I64Fd
1243                      " (%d bi/s for %d packets in "I64Fd" us)",
1244                      i_pcr_dts + p_sys->i_shaping_delay * 3 / 2 - mdate(),
1245                      i_bitrate, i_packet_count, i_pcr_length);
1246         }
1247 #endif
1248     }
1249     else
1250     {
1251         /* This shouldn't happen, but happens in some rare heavy load
1252          * and packet losses conditions. */
1253         i_pcr_length = i_packet_count;
1254     }
1255
1256     /* msg_Dbg( p_mux, "real pck=%d", i_packet_count ); */
1257     for( i = 0; i < i_packet_count; i++ )
1258     {
1259         block_t *p_ts = BufferChainGet( p_chain_ts );
1260         mtime_t i_new_dts = i_pcr_dts + i_pcr_length * i / i_packet_count;
1261
1262         p_ts->i_dts    = i_new_dts;
1263         p_ts->i_length = i_pcr_length / i_packet_count;
1264
1265         if( p_ts->i_flags & SOUT_BUFFER_FLAGS_PRIVATE_PCR )
1266         {
1267             /* msg_Dbg( p_mux, "pcr=%lld ms", p_ts->i_dts / 1000 ); */
1268             TSSetPCR( p_ts, p_ts->i_dts - p_sys->i_dts_delay );
1269         }
1270         if( p_ts->i_flags & SOUT_BUFFER_FLAGS_PRIVATE_CSA )
1271         {
1272             csa_Encrypt( p_sys->csa, p_ts->p_buffer, 0 );
1273         }
1274
1275         /* latency */
1276         p_ts->i_dts += p_sys->i_shaping_delay * 3 / 2;
1277
1278         sout_AccessOutWrite( p_mux->p_access, p_ts );
1279     }
1280 }
1281
1282 static block_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream,
1283                        vlc_bool_t b_pcr )
1284 {
1285     block_t *p_pes = p_stream->chain_pes.p_first;
1286     block_t *p_ts;
1287
1288     vlc_bool_t b_new_pes = VLC_FALSE;
1289     vlc_bool_t b_adaptation_field = VLC_FALSE;
1290
1291     int        i_payload_max = 184 - ( b_pcr ? 8 : 0 );
1292     int        i_payload;
1293
1294     if( p_stream->i_pes_used <= 0 )
1295     {
1296         b_new_pes = VLC_TRUE;
1297     }
1298     i_payload = __MIN( (int)p_pes->i_buffer - p_stream->i_pes_used,
1299                        i_payload_max );
1300
1301     if( b_pcr || i_payload < i_payload_max )
1302     {
1303         b_adaptation_field = VLC_TRUE;
1304     }
1305
1306     p_ts = block_New( p_mux, 188 );
1307     p_ts->i_dts = p_pes->i_dts;
1308
1309     p_ts->p_buffer[0] = 0x47;
1310     p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 ) |
1311         ( ( p_stream->i_pid >> 8 )&0x1f );
1312     p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
1313     p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 ) |
1314         p_stream->i_continuity_counter;
1315
1316     p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
1317
1318     if( b_adaptation_field )
1319     {
1320         int i;
1321
1322         if( b_pcr )
1323         {
1324             int     i_stuffing = i_payload_max - i_payload;
1325
1326             p_ts->i_flags |= SOUT_BUFFER_FLAGS_PRIVATE_PCR;
1327
1328             p_ts->p_buffer[4] = 7 + i_stuffing;
1329             p_ts->p_buffer[5] = 0x10;   /* flags */
1330             p_ts->p_buffer[6] = ( 0 )&0xff;
1331             p_ts->p_buffer[7] = ( 0 )&0xff;
1332             p_ts->p_buffer[8] = ( 0 )&0xff;
1333             p_ts->p_buffer[9] = ( 0 )&0xff;
1334             p_ts->p_buffer[10]= ( 0 )&0x80;
1335             p_ts->p_buffer[11]= 0;
1336
1337             for( i = 12; i < 12 + i_stuffing; i++ )
1338             {
1339                 p_ts->p_buffer[i] = 0xff;
1340             }
1341         }
1342         else
1343         {
1344             int i_stuffing = i_payload_max - i_payload;
1345
1346             p_ts->p_buffer[4] = i_stuffing - 1;
1347             if( i_stuffing > 1 )
1348             {
1349                 p_ts->p_buffer[5] = 0x00;
1350                 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1351                 {
1352                     p_ts->p_buffer[i] = 0xff;
1353                 }
1354             }
1355         }
1356     }
1357
1358     /* copy payload */
1359     memcpy( &p_ts->p_buffer[188 - i_payload],
1360             &p_pes->p_buffer[p_stream->i_pes_used], i_payload );
1361
1362     p_stream->i_pes_used += i_payload;
1363     p_stream->i_pes_dts = p_pes->i_dts + p_pes->i_length *
1364         p_stream->i_pes_used / p_pes->i_buffer;
1365     p_stream->i_pes_length -= p_pes->i_length * i_payload / p_pes->i_buffer;
1366
1367     if( p_stream->i_pes_used >= (int)p_pes->i_buffer )
1368     {
1369         p_pes = BufferChainGet( &p_stream->chain_pes );
1370         block_Release( p_pes );
1371
1372         p_pes = p_stream->chain_pes.p_first;
1373         if( p_pes )
1374         {
1375             p_stream->i_pes_dts    = p_pes->i_dts;
1376             p_stream->i_pes_length = 0;
1377             while( p_pes )
1378             {
1379                 p_stream->i_pes_length += p_pes->i_length;
1380
1381                 p_pes = p_pes->p_next;
1382             }
1383         }
1384         else
1385         {
1386             p_stream->i_pes_dts = 0;
1387             p_stream->i_pes_length = 0;
1388         }
1389         p_stream->i_pes_used = 0;
1390     }
1391
1392     return p_ts;
1393 }
1394
1395
1396 static void TSSetPCR( block_t *p_ts, mtime_t i_dts )
1397 {
1398     mtime_t i_pcr = 9 * i_dts / 100;
1399
1400     p_ts->p_buffer[6]  = ( i_pcr >> 25 )&0xff;
1401     p_ts->p_buffer[7]  = ( i_pcr >> 17 )&0xff;
1402     p_ts->p_buffer[8]  = ( i_pcr >> 9  )&0xff;
1403     p_ts->p_buffer[9]  = ( i_pcr >> 1  )&0xff;
1404     p_ts->p_buffer[10]|= ( i_pcr << 7  )&0x80;
1405 }
1406
1407 #if 0
1408 static void TSSetConstraints( sout_mux_t *p_mux, sout_buffer_chain_t *c,
1409                               mtime_t i_length, int i_bitrate_min,
1410                               int i_bitrate_max )
1411 {
1412     sout_mux_sys_t  *p_sys = p_mux->p_sys;
1413     sout_buffer_chain_t s = *c;
1414
1415     int i_packets = 0;
1416     int i_packets_min = 0;
1417     int i_packets_max = 0;
1418
1419     if( i_length <= 0 )
1420     {
1421         return;
1422     }
1423
1424     i_packets     = c->i_depth;
1425     i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000  + 187 ) / 188;
1426     i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000  + 187 ) / 188;
1427
1428     if( i_packets < i_packets_min && i_packets_min > 0 )
1429     {
1430         block_t *p_pk;
1431         int i_div = ( i_packets_min - i_packets ) / i_packets;
1432         int i_mod = ( i_packets_min - i_packets ) % i_packets;
1433         int i_rest = 0;
1434
1435         /* We need to pad with null packets (pid=0x1fff)
1436          * We try to melt null packets with true packets */
1437         msg_Dbg( p_mux,
1438                  "packets=%d but min=%d -> adding %d packets of padding",
1439                  i_packets, i_packets_min, i_packets_min - i_packets );
1440
1441         BufferChainInit( c );
1442         while( ( p_pk = BufferChainGet( &s ) ) )
1443         {
1444             int i, i_null;
1445
1446             BufferChainAppend( c, p_pk );
1447
1448             i_null = i_div + ( i_rest + i_mod ) / i_packets;
1449
1450             for( i = 0; i < i_null; i++ )
1451             {
1452                 block_t *p_null;
1453
1454                 p_null = sout_BufferNew( p_mux->p_sout, 188 );
1455                 p_null->p_buffer[0] = 0x47;
1456                 p_null->p_buffer[1] = 0x1f;
1457                 p_null->p_buffer[2] = 0xff;
1458                 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
1459                 memset( &p_null->p_buffer[4], 0, 184 );
1460                 p_sys->i_null_continuity_counter =
1461                     ( p_sys->i_null_continuity_counter + 1 ) % 16;
1462
1463                 BufferChainAppend( c, p_null );
1464             }
1465
1466             i_rest = ( i_rest + i_mod ) % i_packets;
1467         }
1468     }
1469     else if( i_packets > i_packets_max && i_packets_max > 0 )
1470     {
1471         block_t *p_pk;
1472         int           i;
1473
1474         /* Arg, we need to drop packets, I don't do something clever (like
1475          * dropping complete pid, b frames, ... ), I just get the right amount
1476          * of packets and discard the others */
1477         msg_Warn( p_mux,
1478                   "packets=%d but max=%d -> removing %d packets -> stream broken",
1479                   i_packets, i_packets_max, i_packets - i_packets_max );
1480
1481         BufferChainInit( c );
1482         for( i = 0; i < i_packets_max; i++ )
1483         {
1484             BufferChainAppend( c, BufferChainGet( &s ) );
1485         }
1486
1487         while( ( p_pk = BufferChainGet( &s ) ) )
1488         {
1489             sout_BufferDelete( p_mux->p_sout, p_pk );
1490         }
1491     }
1492 }
1493 #endif
1494
1495 static void PEStoTS( sout_instance_t *p_sout,
1496                      sout_buffer_chain_t *c, block_t *p_pes,
1497                      ts_stream_t *p_stream )
1498 {
1499     uint8_t *p_data;
1500     int     i_size;
1501     int     b_new_pes;
1502
1503     /* get PES total size */
1504     i_size = p_pes->i_buffer;
1505     p_data = p_pes->p_buffer;
1506
1507     b_new_pes = VLC_TRUE;
1508
1509     for( ;; )
1510     {
1511         int           b_adaptation_field;
1512         int           i_copy;
1513         block_t *p_ts;
1514
1515         p_ts = block_New( p_sout, 188 );
1516         /* write header
1517          * 8b   0x47    sync byte
1518          * 1b           transport_error_indicator
1519          * 1b           payload_unit_start
1520          * 1b           transport_priority
1521          * 13b          pid
1522          * 2b           transport_scrambling_control
1523          * 2b           if adaptation_field 0x03 else 0x01
1524          * 4b           continuity_counter
1525          */
1526
1527         i_copy    = __MIN( i_size, 184 );
1528         b_adaptation_field = i_size < 184 ? VLC_TRUE : VLC_FALSE;
1529
1530         p_ts->p_buffer[0] = 0x47;
1531         p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
1532                             ( ( p_stream->i_pid >> 8 )&0x1f );
1533         p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
1534         p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
1535                             p_stream->i_continuity_counter;
1536
1537         b_new_pes = VLC_FALSE;
1538         p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
1539
1540         if( b_adaptation_field )
1541         {
1542             int i_stuffing = 184 - i_copy;
1543             int i;
1544
1545             p_ts->p_buffer[4] = i_stuffing - 1;
1546             if( i_stuffing > 1 )
1547             {
1548                 p_ts->p_buffer[5] = 0x00;
1549                 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1550                 {
1551                     p_ts->p_buffer[i] = 0xff;
1552                 }
1553             }
1554         }
1555         /* copy payload */
1556         memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1557         p_data += i_copy;
1558         i_size -= i_copy;
1559
1560         BufferChainAppend( c, p_ts );
1561
1562         if( i_size <= 0 )
1563         {
1564             block_t *p_next = p_pes->p_next;
1565
1566             p_pes->p_next = NULL;
1567             block_Release( p_pes );
1568             if( p_next == NULL )
1569             {
1570                 break;
1571             }
1572             b_new_pes = VLC_TRUE;
1573             p_pes = p_next;
1574             i_size = p_pes->i_buffer;
1575             p_data = p_pes->p_buffer;
1576         }
1577     }
1578
1579     return;
1580 }
1581
1582 static block_t *WritePSISection( sout_instance_t *p_sout,
1583                                        dvbpsi_psi_section_t* p_section )
1584 {
1585     block_t   *p_psi, *p_first = NULL;
1586
1587
1588     while( p_section )
1589     {
1590         int             i_size;
1591
1592         i_size =  (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1593                   ( p_section->b_syntax_indicator ? 4 : 0 );
1594
1595         p_psi = block_New( p_sout, i_size + 1 );
1596         p_psi->i_pts = 0;
1597         p_psi->i_dts = 0;
1598         p_psi->i_length = 0;
1599         p_psi->i_buffer = i_size + 1;
1600
1601         p_psi->p_buffer[0] = 0; // pointer
1602         memcpy( p_psi->p_buffer + 1,
1603                 p_section->p_data,
1604                 i_size );
1605
1606         block_ChainAppend( &p_first, p_psi );
1607
1608         p_section = p_section->p_next;
1609     }
1610
1611     return( p_first );
1612 }
1613
1614 static void GetPAT( sout_mux_t *p_mux,
1615                     sout_buffer_chain_t *c )
1616 {
1617     sout_mux_sys_t       *p_sys = p_mux->p_sys;
1618     block_t        *p_pat;
1619     dvbpsi_pat_t         pat;
1620     dvbpsi_psi_section_t *p_section;
1621
1622     dvbpsi_InitPAT( &pat,
1623                     0x01,    // i_ts_id
1624                     p_sys->i_pat_version_number,
1625                     1 );      // b_current_next
1626     /* add all program (only one) */
1627     dvbpsi_PATAddProgram( &pat,
1628                           1,                    // i_number
1629                           p_sys->pmt.i_pid );   // i_pid
1630
1631     p_section = dvbpsi_GenPATSections( &pat,
1632                                        0 );     // max program per section
1633
1634     p_pat = WritePSISection( p_mux->p_sout, p_section );
1635
1636     PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1637
1638     dvbpsi_DeletePSISections( p_section );
1639     dvbpsi_EmptyPAT( &pat );
1640 }
1641
1642 static uint32_t GetDescriptorLength24b( int i_length )
1643 {
1644     uint32_t i_l1, i_l2, i_l3;
1645
1646     i_l1 = i_length&0x7f;
1647     i_l2 = ( i_length >> 7 )&0x7f;
1648     i_l3 = ( i_length >> 14 )&0x7f;
1649
1650     return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1651 }
1652
1653 static void GetPMT( sout_mux_t *p_mux,
1654                     sout_buffer_chain_t *c )
1655 {
1656     sout_mux_sys_t  *p_sys = p_mux->p_sys;
1657     block_t   *p_pmt;
1658
1659     dvbpsi_pmt_t        pmt;
1660     dvbpsi_pmt_es_t     *p_es;
1661     dvbpsi_psi_section_t *p_section;
1662
1663     int                 i_stream;
1664
1665     dvbpsi_InitPMT( &pmt,
1666                     0x01,   // program number
1667                     p_sys->i_pmt_version_number,
1668                     1,      // b_current_next
1669                     p_sys->i_pcr_pid );
1670
1671     if( p_sys->i_mpeg4_streams > 0 )
1672     {
1673         uint8_t iod[4096];
1674         bits_buffer_t bits;
1675         bits_buffer_t bits_fix_IOD;
1676
1677         /* Make valgrind happy : it works at byte level not bit one so
1678          * bit_write confuse it (but DON'T CHANGE the way that bit_write is
1679          * working (needed when fixing some bits) */
1680         memset( iod, 0, 4096 );
1681
1682         bits_initwrite( &bits, 4096, iod );
1683         // IOD_label
1684         bits_write( &bits, 8,   0x01 );
1685         // InitialObjectDescriptor
1686         bits_align( &bits );
1687         bits_write( &bits, 8,   0x02 );     // tag
1688         bits_fix_IOD = bits;    // save states to fix length later
1689         bits_write( &bits, 24,
1690             GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1691         bits_write( &bits, 10,  0x01 );     // ObjectDescriptorID
1692         bits_write( &bits, 1,   0x00 );     // URL Flag
1693         bits_write( &bits, 1,   0x00 );     // includeInlineProfileLevelFlag
1694         bits_write( &bits, 4,   0x0f );     // reserved
1695         bits_write( &bits, 8,   0xff );     // ODProfile (no ODcapability )
1696         bits_write( &bits, 8,   0xff );     // sceneProfile
1697         bits_write( &bits, 8,   0xfe );     // audioProfile (unspecified)
1698         bits_write( &bits, 8,   0xfe );     // visualProfile( // )
1699         bits_write( &bits, 8,   0xff );     // graphicProfile (no )
1700         for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1701         {
1702             ts_stream_t *p_stream;
1703             p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1704
1705             if( p_stream->i_stream_id == 0xfa ||
1706                 p_stream->i_stream_id == 0xfb ||
1707                 p_stream->i_stream_id == 0xfe )
1708             {
1709                 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1710                 /* ES descriptor */
1711                 bits_align( &bits );
1712                 bits_write( &bits, 8,   0x03 );     // ES_DescrTag
1713                 bits_fix_ESDescr = bits;
1714                 bits_write( &bits, 24,
1715                             GetDescriptorLength24b( 0 ) ); // variable size
1716                 bits_write( &bits, 16,  p_stream->i_es_id );
1717                 bits_write( &bits, 1,   0x00 );     // streamDependency
1718                 bits_write( &bits, 1,   0x00 );     // URL Flag
1719                 bits_write( &bits, 1,   0x00 );     // OCRStreamFlag
1720                 bits_write( &bits, 5,   0x1f );     // streamPriority
1721
1722                 // DecoderConfigDesciptor
1723                 bits_align( &bits );
1724                 bits_write( &bits, 8,   0x04 ); // DecoderConfigDescrTag
1725                 bits_fix_Decoder = bits;
1726                 bits_write( &bits, 24,  GetDescriptorLength24b( 0 ) );
1727                 if( p_stream->i_stream_type == 0x10 )
1728                 {
1729                     bits_write( &bits, 8, 0x20 );   // Visual 14496-2
1730                     bits_write( &bits, 6, 0x04 );   // VisualStream
1731                 }
1732                 else if( p_stream->i_stream_type == 0x11 )
1733                 {
1734                     bits_write( &bits, 8, 0x40 );   // Audio 14496-3
1735                     bits_write( &bits, 6, 0x05 );   // AudioStream
1736                 }
1737                 else if( p_stream->i_stream_type == 0x12 &&
1738                          p_stream->i_codec == VLC_FOURCC('s','u','b','t') )
1739                 {
1740                     bits_write( &bits, 8, 0x0B );   // Text Stream
1741                     bits_write( &bits, 6, 0x04 );   // VisualStream
1742                 }
1743                 else
1744                 {
1745                     bits_write( &bits, 8, 0x00 );
1746                     bits_write( &bits, 6, 0x00 );
1747
1748                     msg_Err( p_mux->p_sout,"Unsupported stream_type => "
1749                              "broken IOD" );
1750                 }
1751                 bits_write( &bits, 1,   0x00 );     // UpStream
1752                 bits_write( &bits, 1,   0x01 );     // reserved
1753                 bits_write( &bits, 24,  1024 * 1024 );  // bufferSizeDB
1754                 bits_write( &bits, 32,  0x7fffffff );   // maxBitrate
1755                 bits_write( &bits, 32,  0 );            // avgBitrate
1756
1757                 if( p_stream->i_decoder_specific_info > 0 )
1758                 {
1759                     int i;
1760                     // DecoderSpecificInfo
1761                     bits_align( &bits );
1762                     bits_write( &bits, 8,   0x05 ); // tag
1763                     bits_write( &bits, 24, GetDescriptorLength24b(
1764                                 p_stream->i_decoder_specific_info ) );
1765                     for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1766                     {
1767                         bits_write( &bits, 8,
1768                             ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1769                     }
1770                 }
1771                 /* fix Decoder length */
1772                 bits_write( &bits_fix_Decoder, 24,
1773                             GetDescriptorLength24b( bits.i_data -
1774                             bits_fix_Decoder.i_data - 3 ) );
1775
1776                 /* SLConfigDescriptor : predifined (0x01) */
1777                 bits_align( &bits );
1778                 bits_write( &bits, 8,   0x06 ); // tag
1779                 bits_write( &bits, 24,  GetDescriptorLength24b( 8 ) );
1780                 bits_write( &bits, 8,   0x01 ); // predefined
1781                 bits_write( &bits, 1,   0 );   // durationFlag
1782                 bits_write( &bits, 32,  0 );   // OCRResolution
1783                 bits_write( &bits, 8,   0 );   // OCRLength
1784                 bits_write( &bits, 8,   0 );   // InstantBitrateLength
1785                 bits_align( &bits );
1786
1787                 /* fix ESDescr length */
1788                 bits_write( &bits_fix_ESDescr, 24,
1789                             GetDescriptorLength24b( bits.i_data -
1790                             bits_fix_ESDescr.i_data - 3 ) );
1791             }
1792         }
1793         bits_align( &bits );
1794         /* fix IOD length */
1795         bits_write( &bits_fix_IOD, 24,
1796                     GetDescriptorLength24b( bits.i_data -
1797                                             bits_fix_IOD.i_data - 3 ) );
1798         dvbpsi_PMTAddDescriptor( &pmt, 0x1d, bits.i_data, bits.p_data );
1799     }
1800
1801     for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1802     {
1803         ts_stream_t *p_stream;
1804
1805         p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1806
1807         p_es = dvbpsi_PMTAddES( &pmt, p_stream->i_stream_type,
1808                                 p_stream->i_pid );
1809         if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1810         {
1811             uint8_t     es_id[2];
1812
1813             /* SL descriptor */
1814             es_id[0] = (p_stream->i_es_id >> 8)&0xff;
1815             es_id[1] = (p_stream->i_es_id)&0xff;
1816             dvbpsi_PMTESAddDescriptor( p_es, 0x1f, 2, es_id );
1817         }
1818         else if( p_stream->i_stream_type == 0xa0 )
1819         {
1820             uint8_t data[512];
1821             int i_extra = __MIN( p_stream->i_decoder_specific_info, 502 );
1822
1823             /* private DIV3 descripor */
1824             memcpy( &data[0], &p_stream->i_bih_codec, 4 );
1825             data[4] = ( p_stream->i_bih_width >> 8 )&0xff;
1826             data[5] = ( p_stream->i_bih_width      )&0xff;
1827             data[6] = ( p_stream->i_bih_height>> 8 )&0xff;
1828             data[7] = ( p_stream->i_bih_height     )&0xff;
1829             data[8] = ( i_extra >> 8 )&0xff;
1830             data[9] = ( i_extra      )&0xff;
1831             if( i_extra > 0 )
1832             {
1833                 memcpy( &data[10], p_stream->p_decoder_specific_info, i_extra );
1834             }
1835
1836             /* 0xa0 is private */
1837             dvbpsi_PMTESAddDescriptor( p_es, 0xa0, i_extra + 10, data );
1838         }
1839         else if( p_stream->i_stream_type == 0x81 )
1840         {
1841             uint8_t format[4] = { 0x41, 0x43, 0x2d, 0x33 };
1842
1843             /* "registration" descriptor : "AC-3" */
1844             dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
1845         }
1846         else if( p_stream->i_codec == VLC_FOURCC('d','t','s',' ') )
1847         {
1848             /* DTS registration descriptor (ETSI TS 101 154 Annex F) */
1849
1850             /* DTS format identifier, frame size 1024 - FIXME */
1851             uint8_t data[4] = { 0x44, 0x54, 0x53, 0x32 };
1852             dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, data );
1853         }
1854 #ifdef _DVBPSI_DR_59_H_
1855         else if( p_stream->i_codec == VLC_FOURCC('d','v','b','s') )
1856         {
1857             /* DVB subtitles */
1858             dvbpsi_subtitling_dr_t descr;
1859             dvbpsi_subtitle_t sub;
1860             dvbpsi_descriptor_t *p_descr;
1861
1862             memcpy( sub.i_iso6392_language_code, p_stream->lang, 3 );
1863             sub.i_subtitling_type = 0;
1864             sub.i_composition_page_id = p_stream->i_es_id & 0xFF;
1865             sub.i_ancillary_page_id = p_stream->i_es_id >> 16;
1866
1867             descr.i_subtitles_number = 1;
1868             descr.p_subtitle[0] = sub;
1869
1870             p_descr = dvbpsi_GenSubtitlingDr( &descr, 0 );
1871             /* Work around bug in old libdvbpsi */ p_descr->i_length = 8;
1872             dvbpsi_PMTESAddDescriptor( p_es, p_descr->i_tag,
1873                                        p_descr->i_length, p_descr->p_data );
1874             continue;
1875         }
1876 #endif /* _DVBPSI_DR_59_H_ */
1877
1878         if( p_stream->lang[0] != 0 )
1879         {
1880             uint8_t data[4];
1881
1882             /* I construct the content myself, way faster than looking at
1883              * over complicated/mind broken libdvbpsi way */
1884             data[0] = p_stream->lang[0];
1885             data[1] = p_stream->lang[1];
1886             data[2] = p_stream->lang[2];
1887             data[3] = 0x00; /* audio type: 0x00 undefined */
1888
1889             dvbpsi_PMTESAddDescriptor( p_es, 0x0a, 4, data );
1890         }
1891     }
1892
1893     p_section = dvbpsi_GenPMTSections( &pmt );
1894
1895     p_pmt = WritePSISection( p_mux->p_sout, p_section );
1896
1897     PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1898
1899     dvbpsi_DeletePSISections( p_section );
1900     dvbpsi_EmptyPMT( &pmt );
1901 }