1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.30 2003/08/26 00:52:38 fenrir Exp $
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Eric Petit <titer@videolan.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
32 #include <vlc/input.h>
39 #if defined MODULE_NAME_IS_mux_ts_dvbpsi
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>
49 # include "descriptor.h"
50 # include "tables/pat.h"
51 # include "tables/pmt.h"
52 # include "descriptors/dr.h"
59 * - check PCR frequency requirement
61 * - check PCR/PCR "soft"
62 * - check if "registration" descriptor : "AC-3" should be a program
63 * descriptor or an es one. (xine want an es one)
65 * - remove creation of PAT/PMT without dvbpsi
68 * - subtitle support is far from perfect. I expect some subtitles drop
69 * if they arrive a bit late
70 * (We cannot rely on the fact that the fifo should be full)
72 /*****************************************************************************
74 *****************************************************************************/
75 static int Open ( vlc_object_t * );
76 static void Close ( vlc_object_t * );
79 #if defined MODULE_NAME_IS_mux_ts
80 set_description( _("TS muxer") );
81 set_capability( "sout mux", 100 );
83 add_shortcut( "ts_nodvbpsi" );
84 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
85 set_description( _("TS muxer (libdvbpsi)") );
86 set_capability( "sout mux", 120 );
88 add_shortcut( "ts_dvbpsi" );
90 set_callbacks( Open, Close );
93 /*****************************************************************************
95 *****************************************************************************/
96 static int Capability(sout_mux_t *, int, void *, void * );
97 static int AddStream( sout_mux_t *, sout_input_t * );
98 static int DelStream( sout_mux_t *, sout_input_t * );
99 static int Mux ( sout_mux_t * );
101 /*****************************************************************************
103 *****************************************************************************/
104 #define SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT ( 1 << SOUT_BUFFER_FLAGS_PRIVATE_SHIFT )
108 sout_buffer_t *p_first;
109 sout_buffer_t **pp_last;
110 } sout_buffer_chain_t;
112 static inline void BufferChainInit ( sout_buffer_chain_t *c )
116 c->pp_last = &c->p_first;
118 static inline void BufferChainAppend( sout_buffer_chain_t *c, sout_buffer_t *b )
128 c->pp_last = &b->p_next;
130 static inline sout_buffer_t *BufferChainGet( sout_buffer_chain_t *c )
132 sout_buffer_t *b = c->p_first;
137 c->p_first = b->p_next;
139 if( c->p_first == NULL )
141 c->pp_last = &c->p_first;
149 typedef struct ts_stream_s
154 int i_continuity_counter;
156 /* to be used for carriege of DIV3 */
157 vlc_fourcc_t i_bih_codec;
158 int i_bih_width, i_bih_height;
160 /* Specific to mpeg4 in mpeg2ts */
163 int i_decoder_specific_info;
164 uint8_t *p_decoder_specific_info;
166 /* for TS building */
167 sout_buffer_chain_t chain_ts;
171 struct sout_mux_sys_t
174 sout_input_t *p_pcr_input;
176 int i_stream_id_mpga;
177 int i_stream_id_mpgv;
182 int i_pid_free; // first usable pid
184 int i_pat_version_number;
187 int i_pmt_version_number;
188 ts_stream_t pmt; // Up to now only one program
192 int i_null_continuity_counter; /* Needed ? */
194 /* for TS building */
195 int64_t i_bitrate_min;
196 int64_t i_bitrate_max;
198 int64_t i_pcr_soft_delay;
200 mtime_t i_pcr; /* last PCR emited (for pcr-soft) */
203 sout_buffer_chain_t chain_ts;
207 /* Reserve a pid and return it */
208 static int AllocatePID( sout_mux_sys_t *p_sys )
210 return( ++p_sys->i_pid_free );
213 static void GetPAT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
214 static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
216 static int TSFill ( sout_mux_t *, sout_input_t * );
217 static void PEStoTS ( sout_instance_t *, sout_buffer_chain_t *, sout_buffer_t *, ts_stream_t *, vlc_bool_t );
218 static void TSSetDate( sout_buffer_chain_t *, mtime_t, mtime_t, mtime_t );
219 static void TSSetConstraints( sout_mux_t*, sout_buffer_chain_t *,
220 mtime_t i_length, int i_bitrate_min, int i_bitrate_max );
222 /*****************************************************************************
224 *****************************************************************************/
225 static int Open( vlc_object_t *p_this )
227 sout_mux_t *p_mux =(sout_mux_t*)p_this;
228 sout_mux_sys_t *p_sys;
231 msg_Dbg( p_mux, "Open" );
233 p_sys = malloc( sizeof( sout_mux_sys_t ) );
235 p_mux->pf_capacity = Capability;
236 p_mux->pf_addstream = AddStream;
237 p_mux->pf_delstream = DelStream;
239 p_mux->p_sys = p_sys;
240 p_mux->i_preheader = 30; // really enough for a pes header
242 srand( (uint32_t)mdate() );
244 p_sys->i_stream_id_mpga = 0xc0;
245 p_sys->i_stream_id_mpgv = 0xe0;
247 p_sys->i_audio_bound = 0;
248 p_sys->i_video_bound = 0;
250 p_sys->i_pat_version_number = rand() % 32;
251 p_sys->pat.i_pid = 0;
252 p_sys->pat.i_continuity_counter = 0;
254 p_sys->i_pmt_version_number = rand() % 32;
255 p_sys->pmt.i_pid = 0x42;
256 p_sys->pmt.i_continuity_counter = 0;
258 p_sys->i_pid_free = 0x43;
260 p_sys->i_pcr_pid = 0x1fff;
261 p_sys->p_pcr_input = NULL;
263 p_sys->i_mpeg4_streams = 0;
265 p_sys->i_null_continuity_counter = 0;
267 /* Allow to create constrained stream */
268 p_sys->i_bitrate_min = 0;
269 p_sys->i_bitrate_max = 0;
270 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmin" ) ) )
272 p_sys->i_bitrate_min = atoll( val );
274 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmax" ) ) )
276 p_sys->i_bitrate_max = atoll( val );
278 if( p_sys->i_bitrate_min > 0 && p_sys->i_bitrate_max > 0 &&
279 p_sys->i_bitrate_min > p_sys->i_bitrate_max )
281 msg_Err( p_mux, "incompatible minimum and maximum bitrate, "
282 "disabling bitrate control" );
283 p_sys->i_bitrate_min = 0;
284 p_sys->i_bitrate_max = 0;
286 p_sys->i_pcr_delay = 100000;
287 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr" ) ) )
289 p_sys->i_pcr_delay = (int64_t)atoi( val ) * 1000;
290 if( p_sys->i_pcr_delay <= 0 )
293 "invalid pcr delay ("I64Fd"ms) reseting to 100ms",
294 p_sys->i_pcr_delay / 1000 );
295 p_sys->i_pcr_delay = 100000;
298 p_sys->i_pcr_soft_delay = 0;
299 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr-soft" ) ) )
301 p_sys->i_pcr_soft_delay = (int64_t)atoi( val ) * 1000;
302 if( p_sys->i_pcr_soft_delay <= 0 ||
303 p_sys->i_pcr_soft_delay >= p_sys->i_pcr_delay )
306 "invalid pcr-soft delay ("I64Fd"ms) disabled",
307 p_sys->i_pcr_soft_delay / 1000 );
308 p_sys->i_pcr_soft_delay = 0;
312 msg_Dbg( p_mux, "pcr_delay="I64Fd" pcr_soft_delay="I64Fd,
313 p_sys->i_pcr_delay, p_sys->i_pcr_soft_delay );
315 /* for TS génération */
319 BufferChainInit( &p_sys->chain_ts );
323 /*****************************************************************************
325 *****************************************************************************/
326 static void Close( vlc_object_t * p_this )
328 sout_mux_t *p_mux = (sout_mux_t*)p_this;
329 sout_mux_sys_t *p_sys = p_mux->p_sys;
330 sout_buffer_t *p_data;
332 msg_Dbg( p_mux, "Close" );
334 /* Empty TS buffer */
335 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
337 sout_BufferDelete( p_mux->p_sout, p_data );
343 /*****************************************************************************
345 *****************************************************************************/
346 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
350 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
351 *(vlc_bool_t*)p_answer = VLC_TRUE;
352 return( SOUT_MUX_CAP_ERR_OK );
354 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
358 /*****************************************************************************
359 * AddStream: called for each stream addition
360 *****************************************************************************/
361 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
363 sout_mux_sys_t *p_sys = p_mux->p_sys;
364 ts_stream_t *p_stream;
366 msg_Dbg( p_mux, "adding input codec=%4.4s", (char*)&p_input->p_fmt->i_fourcc );
368 p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
370 /* Init this new stream */
371 p_stream->i_pid = AllocatePID( p_sys );
372 p_stream->i_continuity_counter = 0;
373 p_stream->i_decoder_specific_info = 0;
374 p_stream->p_decoder_specific_info = NULL;
376 /* All others fields depand on codec */
377 switch( p_input->p_fmt->i_cat )
380 switch( p_input->p_fmt->i_fourcc )
382 case VLC_FOURCC( 'm', 'p','g', 'v' ):
383 /* TODO: do we need to check MPEG-I/II ? */
384 p_stream->i_stream_type = 0x02;
385 p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
386 p_sys->i_stream_id_mpgv++;
388 case VLC_FOURCC( 'm', 'p','4', 'v' ):
389 p_stream->i_stream_type = 0x10;
390 p_stream->i_stream_id = 0xfa;
391 p_sys->i_mpeg4_streams++;
392 p_stream->i_es_id = p_stream->i_pid;
394 /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
395 /* I didn't want to do that :P */
396 case VLC_FOURCC( 'H', '2', '6', '3' ):
397 case VLC_FOURCC( 'I', '2', '6', '3' ):
398 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
399 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
400 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
401 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
402 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
403 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
404 p_stream->i_stream_type = 0xa0; // private
405 p_stream->i_stream_id = 0xa0; // beurk
406 p_stream->i_bih_codec = p_input->p_fmt->i_fourcc;
407 p_stream->i_bih_width = p_input->p_fmt->i_width;
408 p_stream->i_bih_height = p_input->p_fmt->i_height;
414 p_sys->i_video_bound++;
418 switch( p_input->p_fmt->i_fourcc )
420 case VLC_FOURCC( 'm', 'p','g', 'a' ):
421 p_stream->i_stream_type = p_input->p_fmt->i_sample_rate >= 32000 ? 0x03 : 0x04;
422 p_stream->i_stream_id = p_sys->i_stream_id_mpga;
423 p_sys->i_stream_id_mpga++;
425 case VLC_FOURCC( 'a', '5','2', ' ' ):
426 p_stream->i_stream_type = 0x81;
427 p_stream->i_stream_id = 0xbd;
429 case VLC_FOURCC( 'm', 'p','4', 'a' ):
430 p_stream->i_stream_type = 0x11;
431 p_stream->i_stream_id = 0xfa;
432 p_sys->i_mpeg4_streams++;
433 p_stream->i_es_id = p_stream->i_pid;
439 p_sys->i_audio_bound++;
443 switch( p_input->p_fmt->i_fourcc )
445 case VLC_FOURCC( 's', 'p','u', ' ' ):
446 p_stream->i_stream_type = 0x82;
447 p_stream->i_stream_id = 0x82;
460 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
461 p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra_data;
462 if( p_stream->i_decoder_specific_info > 0 )
464 p_stream->p_decoder_specific_info =
465 malloc( p_stream->i_decoder_specific_info );
466 memcpy( p_stream->p_decoder_specific_info,
467 p_input->p_fmt->p_extra_data,
468 p_input->p_fmt->i_extra_data );
470 /* Init chain for TS building */
471 BufferChainInit( &p_stream->chain_ts );
473 /* We only change PMT version (PAT isn't changed) */
474 p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
477 if( p_input->p_fmt->i_cat != SPU_ES &&
478 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
480 sout_buffer_t *p_data;
482 if( p_sys->p_pcr_input )
484 /* There was already a PCR stream, so clean context */
485 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
487 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
489 sout_BufferDelete( p_mux->p_sout, p_data );
492 p_sys->i_pcr_pid = p_stream->i_pid;
493 p_sys->p_pcr_input = p_input;
495 /* Empty TS buffer (avoid broken data/problems with pcr stream changement ) */
496 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
498 sout_BufferDelete( p_mux->p_sout, p_data );
505 /*****************************************************************************
506 * DelStream: called before a stream deletion
507 *****************************************************************************/
508 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
510 sout_mux_sys_t *p_sys = p_mux->p_sys;
511 ts_stream_t *p_stream;
512 sout_buffer_t *p_data;
514 msg_Dbg( p_mux, "removing input" );
515 p_stream = (ts_stream_t*)p_input->p_sys;
517 if( p_sys->i_pcr_pid == p_stream->i_pid )
521 /* Find a new pcr stream (Prefer Video Stream) */
522 p_sys->i_pcr_pid = 0x1fff;
523 p_sys->p_pcr_input = NULL;
524 for( i = 0; i < p_mux->i_nb_inputs; i++ )
526 if( p_mux->pp_inputs[i] == p_input )
531 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
534 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
535 p_sys->p_pcr_input= p_mux->pp_inputs[i];
538 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
539 p_sys->i_pcr_pid == 0x1fff )
542 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
543 p_sys->p_pcr_input= p_mux->pp_inputs[i];
546 if( p_sys->p_pcr_input )
548 /* Empty TS buffer */
549 while( ( p_data = BufferChainGet( &((ts_stream_t*)p_sys->p_pcr_input->p_sys)->chain_ts ) ) )
551 sout_BufferDelete( p_mux->p_sout, p_data );
556 /* Empty all data in chain_ts */
557 while( ( p_data = BufferChainGet( &p_stream->chain_ts ) ) )
559 sout_BufferDelete( p_mux->p_sout, p_data );
561 if( p_stream->p_decoder_specific_info )
563 free( p_stream->p_decoder_specific_info );
565 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
567 p_sys->i_mpeg4_streams--;
571 /* We only change PMT version (PAT isn't changed) */
572 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
574 /*Empty TS buffer (avoid broken data/problems with pcr stream changement) */
575 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
577 sout_BufferDelete( p_mux->p_sout, p_data );
583 /*****************************************************************************
584 * Mux: Call each time there is new data for at least one stream
585 *****************************************************************************
587 *****************************************************************************/
588 static int Mux( sout_mux_t *p_mux )
590 sout_mux_sys_t *p_sys = p_mux->p_sys;
592 sout_input_t *p_pcr_input = p_sys->p_pcr_input;
593 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
595 if( p_sys->i_pcr_pid == 0x1fff )
597 msg_Dbg( p_mux, "waiting PCR streams" );
604 ts_stream_t *p_stream = NULL;
605 sout_buffer_t *p_data;
610 /* fill ts packets for pcr XXX before GetPAT/GetPMT */
611 if( p_pcr_stream->chain_ts.p_first == NULL && TSFill( p_mux, p_pcr_input ) )
613 /* We need more data */
617 if( p_sys->chain_ts.p_first == NULL )
619 /* Every pcr packet send PAT/PMT */
620 GetPAT( p_mux, &p_sys->chain_ts);
621 GetPMT( p_mux, &p_sys->chain_ts );
624 /* search stream with lowest dts */
625 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
627 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
629 if( p_stream->chain_ts.p_first == NULL )
631 if( TSFill( p_mux, p_mux->pp_inputs[i] ) )
633 /* We need more data */
636 if( p_stream->chain_ts.p_first == NULL )
638 continue; /* SPU_ES */
642 if( i_stream == -1 ||
643 p_stream->chain_ts.p_first->i_dts < i_dts )
646 i_dts = p_stream->chain_ts.p_first->i_dts;
650 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
652 p_data = BufferChainGet( &p_stream->chain_ts );
653 BufferChainAppend( &p_sys->chain_ts, p_data );
655 if( p_stream->i_pid == p_pcr_stream->i_pid && p_stream->chain_ts.p_first == NULL )
657 sout_buffer_t *p_ts = p_sys->chain_ts.p_first;
659 /* We have consume all TS packets from the PCR stream */
661 if( p_sys->i_length > p_sys->i_pcr_delay )
663 /* Send TS data if last PCR was i_pcr_delay ago */
665 if( p_sys->i_bitrate_min > 0 ||
666 p_sys->i_bitrate_max > 0 )
668 TSSetConstraints( p_mux, &p_sys->chain_ts, p_sys->i_length,
669 p_sys->i_bitrate_min, p_sys->i_bitrate_max );
673 TSSetDate( &p_sys->chain_ts,
676 3 * p_sys->i_pcr_delay/2 ); /* latency is equal to i_pcr_delay
677 3/2 is for security */
678 sout_AccessOutWrite( p_mux->p_access, p_ts );
680 /* Reset the ts chain */
681 BufferChainInit( &p_sys->chain_ts );
693 /*****************************************************************************
696 *****************************************************************************/
697 static int TSFill( sout_mux_t *p_mux, sout_input_t *p_input )
699 sout_mux_sys_t *p_sys = p_mux->p_sys;
701 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
702 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
703 mtime_t i_dts, i_dts_next,i_length;
704 sout_buffer_t *p_data, *p_next;
705 vlc_bool_t b_pcr = VLC_FALSE;
706 vlc_bool_t b_pcr_soft = VLC_FALSE;
711 if( p_input->p_fifo->i_depth <= 1 )
713 if( p_input->p_fmt->i_cat == AUDIO_ES ||
714 p_input->p_fmt->i_cat == VIDEO_ES )
716 /* We need more data */
724 p_data = sout_FifoGet( p_input->p_fifo );
725 i_dts = p_data->i_dts;
726 i_length = p_data->i_length;
728 p_next = sout_FifoShow( p_input->p_fifo );
729 i_dts_next = p_next->i_dts;
731 if( p_stream->i_pid == p_pcr_stream->i_pid &&
732 p_stream->chain_ts.p_first == NULL )
734 /* I need that length == dts_next - dts, but be carefull if
735 * some dts are broken length >= 0.5s are suspicious */
736 if( i_dts_next > i_dts &&
737 i_dts_next - i_dts < (mtime_t)500000 )
739 i_length = i_dts_next - i_dts;
741 p_sys->i_length+= i_length;
742 if( p_sys->chain_ts.p_first == NULL )
744 p_sys->i_dts = i_dts;
745 p_sys->i_pcr = i_dts;
748 else if( p_sys->i_pcr_soft_delay > 0 &&
749 p_sys->i_pcr + p_sys->i_pcr_soft_delay < i_dts )
751 p_sys->i_pcr = i_dts;
753 b_pcr_soft = VLC_TRUE;
758 if( ( p_sys->i_dts + p_sys->i_length ) - i_dts > 2000000 ||
759 ( p_sys->i_dts + p_sys->i_length ) - i_dts < -2000000 )
761 msg_Err( p_mux, "| buffer_dts - pcr_pts | > 2s ("I64Fd") empting "
762 "pcr TS buffers", p_sys->i_dts + p_sys->i_length - i_dts);
764 sout_BufferDelete( p_mux->p_sout, p_data );
766 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
768 sout_BufferDelete( p_mux->p_sout, p_data );
770 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
772 sout_BufferDelete( p_mux->p_sout, p_data );
777 if( i_dts >= p_sys->i_dts )
782 msg_Dbg( p_mux, "dropping buffer size=%d dts="I64Fd" pcr_dts="I64Fd
783 " diff="I64Fd, p_data->i_size, i_dts, p_sys->i_dts,
784 p_sys->i_dts + p_sys->i_length - i_dts );
785 sout_BufferDelete( p_mux->p_sout, p_data );
788 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
790 BufferChainInit( &p_stream->chain_ts );
791 PEStoTS( p_mux->p_sout, &p_stream->chain_ts, p_data, p_stream, b_pcr );
793 TSSetDate( &p_stream->chain_ts, i_dts, i_length, 0 );
795 if( b_pcr_soft && p_stream->chain_ts.p_first )
797 p_stream->chain_ts.p_first->i_flags=SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT;
803 static void TSSetConstraints( sout_mux_t *p_mux, sout_buffer_chain_t *c, mtime_t i_length, int i_bitrate_min, int i_bitrate_max )
805 sout_mux_sys_t *p_sys = p_mux->p_sys;
806 sout_buffer_chain_t s = *c;
809 int i_packets_min = 0;
810 int i_packets_max = 0;
817 i_packets = c->i_depth;
818 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
819 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
821 if( i_packets < i_packets_min && i_packets_min > 0 )
824 int i_div = ( i_packets_min - i_packets ) / i_packets;
825 int i_mod = ( i_packets_min - i_packets ) % i_packets;
828 /* We need to pad with null packets (pid=0x1fff)
829 * We try to melt null packets with true packets */
831 "packets=%d but min=%d -> adding %d packets of padding",
832 i_packets, i_packets_min, i_packets_min - i_packets );
834 BufferChainInit( c );
835 while( ( p_pk = BufferChainGet( &s ) ) )
839 BufferChainAppend( c, p_pk );
841 i_null = i_div + ( i_rest + i_mod ) / i_packets;
843 for( i = 0; i < i_null; i++ )
845 sout_buffer_t *p_null;
847 p_null = sout_BufferNew( p_mux->p_sout, 188 );
848 p_null->p_buffer[0] = 0x47;
849 p_null->p_buffer[1] = 0x1f;
850 p_null->p_buffer[2] = 0xff;
851 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
852 memset( &p_null->p_buffer[4], 0, 184 );
853 p_sys->i_null_continuity_counter =
854 ( p_sys->i_null_continuity_counter + 1 ) % 16;
856 BufferChainAppend( c, p_null );
859 i_rest = ( i_rest + i_mod ) % i_packets;
862 else if( i_packets > i_packets_max && i_packets_max > 0 )
867 /* Arg, we need to drop packets, I don't do something clever (like
868 * dropping complete pid, b frames, ... ), I just get the right amount
869 * of packets and discard the others */
871 "packets=%d but max=%d -> removing %d packets -> stream broken",
872 i_packets, i_packets_max, i_packets - i_packets_max );
874 BufferChainInit( c );
875 for( i = 0; i < i_packets_max; i++ )
877 BufferChainAppend( c, BufferChainGet( &s ) );
880 while( ( p_pk = BufferChainGet( &s ) ) )
882 sout_BufferDelete( p_mux->p_sout, p_pk );
887 static void TSSetDate( sout_buffer_chain_t *c,
888 mtime_t i_dts, mtime_t i_length, mtime_t i_send_offset )
891 mtime_t i_delta = i_length / c->i_depth;
894 for( p_ts = c->p_first; p_ts != NULL; p_ts = p_ts->p_next )
896 p_ts->i_dts = i_dts + i_packet * i_length / c->i_depth; /* avoid rounding error */
897 p_ts->i_length = i_delta;
899 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT )
901 mtime_t i_pcr = 9 * p_ts->i_dts / 100;
903 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
904 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
905 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
906 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
907 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
909 p_ts->i_dts += i_send_offset;
915 static void PEStoTS( sout_instance_t *p_sout,
916 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
917 ts_stream_t *p_stream,
924 /* get PES total size */
925 i_size = p_pes->i_size;
926 p_data = p_pes->p_buffer;
928 /* Set pcr only with valid DTS */
929 if( p_pes->i_dts <= 0 )
934 b_new_pes = VLC_TRUE;
938 int b_adaptation_field;
943 p_ts = sout_BufferNew( p_sout, 188 );
946 * 1b transport_error_indicator
947 * 1b payload_unit_start
948 * 1b transport_priority
950 * 2b transport_scrambling_control
951 * 2b if adaptation_field 0x03 else 0x01
952 * 4b continuity_counter
955 i_payload = 184 - ( b_pcr ? 8 : 0 );
956 i_copy = __MIN( i_size, i_payload );
957 b_adaptation_field = (b_pcr||i_size<i_payload) ? VLC_TRUE : VLC_FALSE;
959 p_ts->p_buffer[0] = 0x47;
960 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
961 ( ( p_stream->i_pid >> 8 )&0x1f );
962 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
963 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
964 p_stream->i_continuity_counter;
966 b_new_pes = VLC_FALSE;
967 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
969 if( b_adaptation_field )
975 mtime_t i_pcr = p_pes->i_dts * 9 / 100;
976 int i_stuffing = i_payload - i_copy;
978 p_ts->p_buffer[4] = 7 + i_stuffing;
979 p_ts->p_buffer[5] = 0x10; /* flags */
980 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
981 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
982 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
983 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
984 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
985 p_ts->p_buffer[11]= 0;
988 for( i = 12; i < 12 + i_stuffing; i++ )
990 p_ts->p_buffer[i] = 0xff;
995 int i_stuffing = i_payload - i_copy;
997 p_ts->p_buffer[4] = i_stuffing - 1;
1000 p_ts->p_buffer[5] = 0x00;
1001 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1003 p_ts->p_buffer[i] = 0xff;
1009 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1013 BufferChainAppend( c, p_ts );
1017 sout_buffer_t *p_next = p_pes->p_next;
1019 p_pes->p_next = NULL;
1020 sout_BufferDelete( p_sout, p_pes );
1021 if( p_next == NULL )
1025 b_new_pes = VLC_TRUE;
1027 i_size = p_pes->i_size;
1028 p_data = p_pes->p_buffer;
1035 #if defined MODULE_NAME_IS_mux_ts
1036 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1038 static uint32_t CRC32[256] =
1040 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1041 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1042 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1043 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1044 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1045 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1046 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1047 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1048 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1049 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1050 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1051 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1052 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1053 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1054 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1055 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1056 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1057 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1058 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1059 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1060 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1061 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1062 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1063 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1064 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1065 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1066 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1067 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1068 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1069 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1070 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1071 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1072 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1073 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1074 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1075 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1076 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1077 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1078 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1079 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1080 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1081 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1082 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1083 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1084 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1085 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1086 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1087 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1088 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1089 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1090 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1091 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1092 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1093 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1094 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1095 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1096 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1097 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1098 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1099 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1100 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1101 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1102 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1103 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1106 uint32_t i_crc = 0xffffffff;
1108 /* Calculate the CRC */
1109 while( i_count > 0 )
1111 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1119 static void GetPAT( sout_mux_t *p_mux,
1120 sout_buffer_chain_t *c )
1122 sout_mux_sys_t *p_sys = p_mux->p_sys;
1123 sout_buffer_t *p_pat;
1126 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1130 p_pat->i_length = 0;
1132 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1134 bits_write( &bits, 8, 0 ); // pointer
1135 bits_write( &bits, 8, 0x00 ); // table id
1136 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1137 bits_write( &bits, 1, 0 ); // 0
1138 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1139 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1140 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1141 bits_write( &bits, 2, 0x03 ); // FIXME
1142 bits_write( &bits, 5, p_sys->i_pat_version_number );
1143 bits_write( &bits, 1, 1 ); // current_next_indicator
1144 bits_write( &bits, 8, 0 ); // section number
1145 bits_write( &bits, 8, 0 ); // last section number
1147 bits_write( &bits, 16, 1 ); // program number
1148 bits_write( &bits, 3, 0x07 ); // reserved
1149 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1151 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1153 p_pat->i_size = bits.i_data;
1155 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1158 static void GetPMT( sout_mux_t *p_mux,
1159 sout_buffer_chain_t *c )
1161 sout_mux_sys_t *p_sys = p_mux->p_sys;
1162 sout_buffer_t *p_pmt;
1166 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1170 p_pmt->i_length = 0;
1172 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1174 bits_write( &bits, 8, 0 ); // pointer
1175 bits_write( &bits, 8, 0x02 ); // table id
1176 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1177 bits_write( &bits, 1, 0 ); // 0
1178 bits_write( &bits, 2, 0 ); // reserved FIXME
1179 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1180 bits_write( &bits, 16, 1 ); // FIXME program number
1181 bits_write( &bits, 2, 0 ); // FIXME
1182 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1183 bits_write( &bits, 1, 1 ); // current_next_indicator
1184 bits_write( &bits, 8, 0 ); // section number
1185 bits_write( &bits, 8, 0 ); // last section number
1187 bits_write( &bits, 3, 0 ); // reserved
1189 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1190 bits_write( &bits, 4, 0 ); // reserved FIXME
1192 bits_write( &bits, 12, 0 ); // program info len FIXME
1194 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1196 ts_stream_t *p_stream;
1198 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1200 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1201 bits_write( &bits, 3, 0 ); // reserved
1202 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1203 bits_write( &bits, 4, 0 ); //reserved
1204 bits_write( &bits, 12, 0 ); // es info len FIXME
1207 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1209 p_pmt->i_size = bits.i_data;
1211 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1213 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1215 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1216 dvbpsi_psi_section_t* p_section )
1218 sout_buffer_t *p_psi, *p_first = NULL;
1225 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1226 ( p_section->b_syntax_indicator ? 4 : 0 );
1228 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1231 p_psi->i_length = 0;
1232 p_psi->i_size = i_size + 1;
1234 p_psi->p_buffer[0] = 0; // pointer
1235 memcpy( p_psi->p_buffer + 1,
1239 sout_BufferChain( &p_first, p_psi );
1241 p_section = p_section->p_next;
1247 static void GetPAT( sout_mux_t *p_mux,
1248 sout_buffer_chain_t *c )
1250 sout_mux_sys_t *p_sys = p_mux->p_sys;
1251 sout_buffer_t *p_pat;
1253 dvbpsi_psi_section_t *p_section;
1255 dvbpsi_InitPAT( &pat,
1257 p_sys->i_pat_version_number,
1258 1 ); // b_current_next
1259 /* add all program (only one) */
1260 dvbpsi_PATAddProgram( &pat,
1262 p_sys->pmt.i_pid ); // i_pid
1264 p_section = dvbpsi_GenPATSections( &pat,
1265 0 ); // max program per section
1267 p_pat = WritePSISection( p_mux->p_sout, p_section );
1269 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1271 dvbpsi_DeletePSISections( p_section );
1272 dvbpsi_EmptyPAT( &pat );
1275 static uint32_t GetDescriptorLength24b( int i_length )
1277 uint32_t i_l1, i_l2, i_l3;
1279 i_l1 = i_length&0x7f;
1280 i_l2 = ( i_length >> 7 )&0x7f;
1281 i_l3 = ( i_length >> 14 )&0x7f;
1283 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1286 static void GetPMT( sout_mux_t *p_mux,
1287 sout_buffer_chain_t *c )
1289 sout_mux_sys_t *p_sys = p_mux->p_sys;
1290 sout_buffer_t *p_pmt;
1293 dvbpsi_pmt_es_t *p_es;
1294 dvbpsi_psi_section_t *p_section;
1298 dvbpsi_InitPMT( &pmt,
1299 0x01, // program number
1300 p_sys->i_pmt_version_number,
1301 1, // b_current_next
1304 if( p_sys->i_mpeg4_streams > 0 )
1308 bits_buffer_t bits_fix_IOD;
1310 /* Make valgrind happy : it works at byte level not bit one so
1311 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
1312 * working (needed when fixing some bits) */
1313 memset( iod, 0, 4096 );
1315 bits_initwrite( &bits, 4096, iod );
1317 bits_write( &bits, 8, 0x01 );
1318 // InitialObjectDescriptor
1319 bits_align( &bits );
1320 bits_write( &bits, 8, 0x02 ); // tag
1321 bits_fix_IOD = bits; // save states to fix length later
1322 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1323 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1324 bits_write( &bits, 1, 0x00 ); // URL Flag
1325 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1326 bits_write( &bits, 4, 0x0f ); // reserved
1327 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1328 bits_write( &bits, 8, 0xff ); // sceneProfile
1329 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1330 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1331 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1332 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1334 ts_stream_t *p_stream;
1335 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1337 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1339 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1341 bits_align( &bits );
1342 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1343 bits_fix_ESDescr = bits;
1344 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1345 bits_write( &bits, 16, p_stream->i_es_id );
1346 bits_write( &bits, 1, 0x00 ); // streamDependency
1347 bits_write( &bits, 1, 0x00 ); // URL Flag
1348 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1349 bits_write( &bits, 5, 0x1f ); // streamPriority
1351 // DecoderConfigDesciptor
1352 bits_align( &bits );
1353 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1354 bits_fix_Decoder = bits;
1355 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1356 if( p_stream->i_stream_type == 0x10 )
1358 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1359 bits_write( &bits, 6, 0x04 ); // VisualStream
1361 else if( p_stream->i_stream_type == 0x11 )
1363 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1364 bits_write( &bits, 6, 0x05 ); // AudioStream
1368 bits_write( &bits, 8, 0x00 );
1369 bits_write( &bits, 6, 0x00 );
1371 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1373 bits_write( &bits, 1, 0x00 ); // UpStream
1374 bits_write( &bits, 1, 0x01 ); // reserved
1375 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1376 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1377 bits_write( &bits, 32, 0 ); // avgBitrate
1379 if( p_stream->i_decoder_specific_info > 0 )
1382 // DecoderSpecificInfo
1383 bits_align( &bits );
1384 bits_write( &bits, 8, 0x05 ); // tag
1385 bits_write( &bits, 24,
1386 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1387 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1389 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1392 /* fix Decoder length */
1393 bits_write( &bits_fix_Decoder, 24,
1394 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1396 /* SLConfigDescriptor : predifined (0x01) */
1397 bits_align( &bits );
1398 bits_write( &bits, 8, 0x06 ); // tag
1399 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1400 bits_write( &bits, 8, 0x01 ); // predefined
1401 bits_write( &bits, 1, 0 ); // durationFlag
1402 bits_write( &bits, 32, 0 ); // OCRResolution
1403 bits_write( &bits, 8, 0 ); // OCRLength
1404 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1405 bits_align( &bits );
1407 /* fix ESDescr length */
1408 bits_write( &bits_fix_ESDescr, 24,
1409 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1412 bits_align( &bits );
1413 /* fix IOD length */
1414 bits_write( &bits_fix_IOD, 24,
1415 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1416 dvbpsi_PMTAddDescriptor( &pmt,
1422 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1424 ts_stream_t *p_stream;
1426 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1428 p_es = dvbpsi_PMTAddES( &pmt,
1429 p_stream->i_stream_type,
1431 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1436 es_id[0] = (p_stream->i_es_id >> 8)&0xff;
1437 es_id[1] = (p_stream->i_es_id)&0xff;
1438 dvbpsi_PMTESAddDescriptor( p_es, 0x1f, 2, es_id );
1440 else if( p_stream->i_stream_type == 0xa0 )
1443 int i_extra = __MIN( p_stream->i_decoder_specific_info,
1446 /* private DIV3 descripor */
1447 memcpy( &data[0], &p_stream->i_bih_codec, 4 );
1448 data[4] = ( p_stream->i_bih_width >> 8 )&&0xff;
1449 data[5] = ( p_stream->i_bih_width )&&0xff;
1450 data[6] = ( p_stream->i_bih_height>> 8 )&&0xff;
1451 data[7] = ( p_stream->i_bih_height )&&0xff;
1452 data[8] = ( i_extra >> 8 )&&0xff;
1453 data[9] = ( i_extra )&&0xff;
1456 memcpy( &data[10], p_stream->p_decoder_specific_info, i_extra );
1459 /* 0xa0 is private */
1460 dvbpsi_PMTESAddDescriptor( p_es, 0xa0, i_extra + 10, data );
1462 else if( p_stream->i_stream_type == 0x81 )
1464 uint8_t format[4] = { 0x41, 0x43, 0x2d, 0x33 };
1466 /* "registration" descriptor : "AC-3" */
1467 dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
1471 p_section = dvbpsi_GenPMTSections( &pmt );
1473 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1475 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1477 dvbpsi_DeletePSISections( p_section );
1478 dvbpsi_EmptyPMT( &pmt );