1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.25 2003/08/10 14:21:16 gbazin 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"
63 * - remove creation of PAT/PMT without dvbpsi
66 * - subtitle support is far from perfect. I expect some subtitles drop
67 * if they arrive a bit late
68 * (We cannot rely on the fact that the fifo should be full)
70 /*****************************************************************************
72 *****************************************************************************/
73 static int Open ( vlc_object_t * );
74 static void Close ( vlc_object_t * );
77 #if defined MODULE_NAME_IS_mux_ts
78 set_description( _("TS muxer") );
79 set_capability( "sout mux", 100 );
81 add_shortcut( "ts_nodvbpsi" );
82 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
83 set_description( _("TS muxer (libdvbpsi)") );
84 set_capability( "sout mux", 120 );
86 add_shortcut( "ts_dvbpsi" );
88 set_callbacks( Open, Close );
91 /*****************************************************************************
93 *****************************************************************************/
94 static int Capability(sout_mux_t *, int, void *, void * );
95 static int AddStream( sout_mux_t *, sout_input_t * );
96 static int DelStream( sout_mux_t *, sout_input_t * );
97 static int Mux ( sout_mux_t * );
99 /*****************************************************************************
101 *****************************************************************************/
102 #define SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT ( 1 << SOUT_BUFFER_FLAGS_PRIVATE_SHIFT )
106 sout_buffer_t *p_first;
107 sout_buffer_t **pp_last;
108 } sout_buffer_chain_t;
110 static inline void BufferChainInit ( sout_buffer_chain_t *c )
114 c->pp_last = &c->p_first;
116 static inline void BufferChainAppend( sout_buffer_chain_t *c, sout_buffer_t *b )
126 c->pp_last = &b->p_next;
128 static inline sout_buffer_t *BufferChainGet( sout_buffer_chain_t *c )
130 sout_buffer_t *b = c->p_first;
135 c->p_first = b->p_next;
137 if( c->p_first == NULL )
139 c->pp_last = &c->p_first;
147 typedef struct ts_stream_s
152 int i_continuity_counter;
154 /* to be used for carriege of DIV3 */
155 vlc_fourcc_t i_bih_codec;
156 int i_bih_width, i_bih_height;
158 /* Specific to mpeg4 in mpeg2ts */
161 int i_decoder_specific_info;
162 uint8_t *p_decoder_specific_info;
164 /* for TS building */
165 sout_buffer_chain_t chain_ts;
169 struct sout_mux_sys_t
172 sout_input_t *p_pcr_input;
174 int i_stream_id_mpga;
175 int i_stream_id_mpgv;
181 int i_pid_free; // first usable pid
183 int i_pat_version_number;
186 int i_pmt_version_number;
187 ts_stream_t pmt; // Up to now only one program
191 int i_null_continuity_counter; /* Needed ? */
193 /* for TS building */
194 int64_t i_bitrate_min;
195 int64_t i_bitrate_max;
197 int64_t i_pcr_soft_delay;
199 mtime_t i_pcr; /* last PCR emited (for pcr-soft) */
202 sout_buffer_chain_t chain_ts;
206 /* Reserve a pid and return it */
207 static int AllocatePID( sout_mux_sys_t *p_sys )
209 return( ++p_sys->i_pid_free );
212 static void GetPAT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
213 static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
215 static int TSFill ( sout_mux_t *, sout_input_t * );
216 static void PEStoTS ( sout_instance_t *, sout_buffer_chain_t *, sout_buffer_t *, ts_stream_t *, vlc_bool_t );
217 static void TSSetDate( sout_buffer_chain_t *, mtime_t, mtime_t );
218 static void TSSetConstraints( sout_mux_t*, sout_buffer_chain_t *,
219 mtime_t i_length, int i_bitrate_min, int i_bitrate_max );
221 #if !defined( HAVE_ATOLL )
222 /* Et oui y'a des systemes de MERDE (ex: OS X, Solaris) qui ne l'ont pas :((( */
223 static long long atoll(const char *str)
225 long long i_value = 0;
233 while( *str >= '0' && *str <= '9' )
235 i_value = i_value * 10 + ( *str - '0' );
238 return i_value * sign;
243 /*****************************************************************************
245 *****************************************************************************/
246 static int Open( vlc_object_t *p_this )
248 sout_mux_t *p_mux =(sout_mux_t*)p_this;
249 sout_mux_sys_t *p_sys;
252 msg_Dbg( p_mux, "Open" );
254 p_sys = malloc( sizeof( sout_mux_sys_t ) );
256 p_mux->pf_capacity = Capability;
257 p_mux->pf_addstream = AddStream;
258 p_mux->pf_delstream = DelStream;
260 p_mux->p_sys = p_sys;
261 p_mux->i_preheader = 30; // really enough for a pes header
263 srand( (uint32_t)mdate() );
265 p_sys->i_stream_id_mpga = 0xc0;
266 p_sys->i_stream_id_a52 = 0x80;
267 p_sys->i_stream_id_mpgv = 0xe0;
269 p_sys->i_audio_bound = 0;
270 p_sys->i_video_bound = 0;
272 p_sys->i_pat_version_number = rand() % 32;
273 p_sys->pat.i_pid = 0;
274 p_sys->pat.i_continuity_counter = 0;
276 p_sys->i_pmt_version_number = rand() % 32;
277 p_sys->pmt.i_pid = 0x42;
278 p_sys->pmt.i_continuity_counter = 0;
280 p_sys->i_pid_free = 0x43;
282 p_sys->i_pcr_pid = 0x1fff;
283 p_sys->p_pcr_input = NULL;
285 p_sys->i_mpeg4_streams = 0;
287 p_sys->i_null_continuity_counter = 0;
289 /* Allow to create constrained stream */
290 p_sys->i_bitrate_min = 0;
291 p_sys->i_bitrate_max = 0;
292 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmin" ) ) )
294 p_sys->i_bitrate_min = atoll( val );
296 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmax" ) ) )
298 p_sys->i_bitrate_max = atoll( val );
300 if( p_sys->i_bitrate_min > 0 && p_sys->i_bitrate_max > 0 &&
301 p_sys->i_bitrate_min > p_sys->i_bitrate_max )
303 msg_Err( p_mux, "incompatible minimum and maximum bitrate, "
304 "disabling bitrate control" );
305 p_sys->i_bitrate_min = 0;
306 p_sys->i_bitrate_max = 0;
308 p_sys->i_pcr_delay = 100000;
309 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr" ) ) )
311 p_sys->i_pcr_delay = (int64_t)atoi( val ) * 1000;
312 if( p_sys->i_pcr_delay <= 0 )
315 "invalid pcr delay ("I64Fd"ms) reseting to 100ms",
316 p_sys->i_pcr_delay / 1000 );
317 p_sys->i_pcr_delay = 100000;
320 p_sys->i_pcr_soft_delay = 0;
321 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr-soft" ) ) )
323 p_sys->i_pcr_soft_delay = (int64_t)atoi( val ) * 1000;
324 if( p_sys->i_pcr_soft_delay <= 0 ||
325 p_sys->i_pcr_soft_delay >= p_sys->i_pcr_delay )
328 "invalid pcr-soft delay ("I64Fd"ms) disabled",
329 p_sys->i_pcr_soft_delay / 1000 );
330 p_sys->i_pcr_soft_delay = 0;
334 msg_Dbg( p_mux, "pcr_delay="I64d" pcr_soft_delay="I64Fd,
335 p_sys->i_pcr_delay, p_sys->i_pcr_soft_delay );
337 /* for TS génération */
341 BufferChainInit( &p_sys->chain_ts );
345 /*****************************************************************************
347 *****************************************************************************/
348 static void Close( vlc_object_t * p_this )
350 sout_mux_t *p_mux = (sout_mux_t*)p_this;
351 sout_mux_sys_t *p_sys = p_mux->p_sys;
352 sout_buffer_t *p_data;
354 msg_Dbg( p_mux, "Close" );
356 /* Empty TS buffer */
357 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
359 sout_BufferDelete( p_mux->p_sout, p_data );
365 /*****************************************************************************
367 *****************************************************************************/
368 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
372 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
373 *(vlc_bool_t*)p_answer = VLC_TRUE;
374 return( SOUT_MUX_CAP_ERR_OK );
376 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
380 /*****************************************************************************
381 * AddStream: called for each stream addition
382 *****************************************************************************/
383 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
385 sout_mux_sys_t *p_sys = p_mux->p_sys;
386 ts_stream_t *p_stream;
388 msg_Dbg( p_mux, "adding input codec=%4.4s", (char*)&p_input->p_fmt->i_fourcc );
390 p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
392 /* Init this new stream */
393 p_stream->i_pid = AllocatePID( p_sys );
394 p_stream->i_continuity_counter = 0;
395 p_stream->i_decoder_specific_info = 0;
396 p_stream->p_decoder_specific_info = NULL;
398 /* All others fields depand on codec */
399 switch( p_input->p_fmt->i_cat )
402 switch( p_input->p_fmt->i_fourcc )
404 case VLC_FOURCC( 'm', 'p','g', 'v' ):
405 /* TODO: do we need to check MPEG-I/II ? */
406 p_stream->i_stream_type = 0x02;
407 p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
408 p_sys->i_stream_id_mpgv++;
410 case VLC_FOURCC( 'm', 'p','4', 'v' ):
411 p_stream->i_stream_type = 0x10;
412 p_stream->i_stream_id = 0xfa;
413 p_sys->i_mpeg4_streams++;
414 p_stream->i_es_id = p_stream->i_pid;
416 /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
417 /* I didn't want to do that :P */
418 case VLC_FOURCC( 'H', '2', '6', '3' ):
419 case VLC_FOURCC( 'I', '2', '6', '3' ):
420 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
421 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
422 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
423 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
424 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
425 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
426 p_stream->i_stream_type = 0xa0; // private
427 p_stream->i_stream_id = 0xa0; // beurk
428 p_stream->i_bih_codec = p_input->p_fmt->i_fourcc;
429 p_stream->i_bih_width = p_input->p_fmt->i_width;
430 p_stream->i_bih_height = p_input->p_fmt->i_height;
436 p_sys->i_video_bound++;
440 switch( p_input->p_fmt->i_fourcc )
442 case VLC_FOURCC( 'm', 'p','g', 'a' ):
443 p_stream->i_stream_type = p_input->p_fmt->i_sample_rate >= 32000 ? 0x03 : 0x04;
444 p_stream->i_stream_id = p_sys->i_stream_id_mpga;
445 p_sys->i_stream_id_mpga++;
447 case VLC_FOURCC( 'a', '5','2', ' ' ):
448 p_stream->i_stream_type = 0x81;
449 p_stream->i_stream_id = p_sys->i_stream_id_a52;
450 p_sys->i_stream_id_a52++;
452 case VLC_FOURCC( 'm', 'p','4', 'a' ):
453 p_stream->i_stream_type = 0x11;
454 p_stream->i_stream_id = 0xfa;
455 p_sys->i_mpeg4_streams++;
456 p_stream->i_es_id = p_stream->i_pid;
462 p_sys->i_audio_bound++;
466 switch( p_input->p_fmt->i_fourcc )
468 case VLC_FOURCC( 's', 'p','u', ' ' ):
469 p_stream->i_stream_type = 0x82;
470 p_stream->i_stream_id = 0x82;
483 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
484 p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra_data;
485 if( p_stream->i_decoder_specific_info > 0 )
487 p_stream->p_decoder_specific_info =
488 malloc( p_stream->i_decoder_specific_info );
489 memcpy( p_stream->p_decoder_specific_info,
490 p_input->p_fmt->p_extra_data,
491 p_input->p_fmt->i_extra_data );
493 /* Init chain for TS building */
494 BufferChainInit( &p_stream->chain_ts );
496 /* We only change PMT version (PAT isn't changed) */
497 p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
500 if( p_input->p_fmt->i_cat != SPU_ES &&
501 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
503 sout_buffer_t *p_data;
505 if( p_sys->p_pcr_input )
507 /* There was already a PCR stream, so clean context */
508 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
510 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
512 sout_BufferDelete( p_mux->p_sout, p_data );
515 p_sys->i_pcr_pid = p_stream->i_pid;
516 p_sys->p_pcr_input = p_input;
518 /* Empty TS buffer (avoid broken data/problems with pcr stream changement ) */
519 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
521 sout_BufferDelete( p_mux->p_sout, p_data );
528 /*****************************************************************************
529 * DelStream: called before a stream deletion
530 *****************************************************************************/
531 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
533 sout_mux_sys_t *p_sys = p_mux->p_sys;
534 ts_stream_t *p_stream;
535 sout_buffer_t *p_data;
537 msg_Dbg( p_mux, "removing input" );
538 p_stream = (ts_stream_t*)p_input->p_sys;
540 if( p_sys->i_pcr_pid == p_stream->i_pid )
544 /* Find a new pcr stream (Prefer Video Stream) */
545 p_sys->i_pcr_pid = 0x1fff;
546 p_sys->p_pcr_input = NULL;
547 for( i = 0; i < p_mux->i_nb_inputs; i++ )
549 if( p_mux->pp_inputs[i] == p_input )
554 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
557 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
558 p_sys->p_pcr_input= p_mux->pp_inputs[i];
561 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
562 p_sys->i_pcr_pid == 0x1fff )
565 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
566 p_sys->p_pcr_input= p_mux->pp_inputs[i];
569 if( p_sys->p_pcr_input )
571 /* Empty TS buffer */
572 while( ( p_data = BufferChainGet( &((ts_stream_t*)p_sys->p_pcr_input->p_sys)->chain_ts ) ) )
574 sout_BufferDelete( p_mux->p_sout, p_data );
579 /* Empty all data in chain_ts */
580 while( ( p_data = BufferChainGet( &p_stream->chain_ts ) ) )
582 sout_BufferDelete( p_mux->p_sout, p_data );
584 if( p_stream->p_decoder_specific_info )
586 free( p_stream->p_decoder_specific_info );
588 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
590 p_sys->i_mpeg4_streams--;
594 /* We only change PMT version (PAT isn't changed) */
595 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
597 /*Empty TS buffer (avoid broken data/problems with pcr stream changement) */
598 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
600 sout_BufferDelete( p_mux->p_sout, p_data );
606 /*****************************************************************************
607 * Mux: Call each time there is new data for at least one stream
608 *****************************************************************************
610 *****************************************************************************/
611 static int Mux( sout_mux_t *p_mux )
613 sout_mux_sys_t *p_sys = p_mux->p_sys;
615 sout_input_t *p_pcr_input = p_sys->p_pcr_input;
616 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
618 if( p_sys->i_pcr_pid == 0x1fff )
620 msg_Dbg( p_mux, "waiting PCR streams" );
627 ts_stream_t *p_stream = NULL;
628 sout_buffer_t *p_data;
633 /* fill ts packets for pcr XXX before GetPAT/GetPMT */
634 if( p_pcr_stream->chain_ts.p_first == NULL && TSFill( p_mux, p_pcr_input ) )
636 /* We need more data */
640 if( p_sys->chain_ts.p_first == NULL )
642 /* Every pcr packet send PAT/PMT */
643 GetPAT( p_mux, &p_sys->chain_ts);
644 GetPMT( p_mux, &p_sys->chain_ts );
647 /* search stream with lowest dts */
648 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
650 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
652 if( p_stream->chain_ts.p_first == NULL )
654 if( TSFill( p_mux, p_mux->pp_inputs[i] ) )
656 /* We need more data */
659 if( p_stream->chain_ts.p_first == NULL )
661 continue; /* SPU_ES */
665 if( i_stream == -1 ||
666 p_stream->chain_ts.p_first->i_dts < i_dts )
669 i_dts = p_stream->chain_ts.p_first->i_dts;
673 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
675 p_data = BufferChainGet( &p_stream->chain_ts );
676 BufferChainAppend( &p_sys->chain_ts, p_data );
678 if( p_stream->i_pid == p_pcr_stream->i_pid && p_stream->chain_ts.p_first == NULL )
680 sout_buffer_t *p_ts = p_sys->chain_ts.p_first;
682 /* We have consume all TS packets from the PCR stream */
684 if( p_sys->i_length > p_sys->i_pcr_delay )
686 /* Send TS data if last PCR was i_pcr_delay ago */
688 if( p_sys->i_bitrate_min > 0 ||
689 p_sys->i_bitrate_max > 0 )
691 TSSetConstraints( p_mux, &p_sys->chain_ts, p_sys->i_length,
692 p_sys->i_bitrate_min, p_sys->i_bitrate_max );
696 TSSetDate( &p_sys->chain_ts,
697 p_sys->i_dts + 3 * p_sys->i_pcr_delay / 2, /* latency is equal to i_pcr_delay, 3/2 is for security */
699 sout_AccessOutWrite( p_mux->p_access, p_ts );
701 /* Reset the ts chain */
702 BufferChainInit( &p_sys->chain_ts );
714 /*****************************************************************************
717 *****************************************************************************/
718 static int TSFill( sout_mux_t *p_mux, sout_input_t *p_input )
720 sout_mux_sys_t *p_sys = p_mux->p_sys;
722 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
723 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
724 mtime_t i_dts, i_length;
725 sout_buffer_t *p_data;
726 vlc_bool_t b_pcr = VLC_FALSE;
727 vlc_bool_t b_pcr_soft = VLC_FALSE;
732 if( p_input->p_fifo->i_depth <= 0 )
734 if( p_input->p_fmt->i_cat == AUDIO_ES ||
735 p_input->p_fmt->i_cat == VIDEO_ES )
737 /* We need more data */
745 p_data = sout_FifoGet( p_input->p_fifo );
746 i_dts = p_data->i_dts;
747 i_length = p_data->i_length;
749 if( p_stream->i_pid == p_pcr_stream->i_pid &&
750 p_stream->chain_ts.p_first == NULL )
752 p_sys->i_length+= i_length;
753 if( p_sys->chain_ts.p_first == NULL )
755 p_sys->i_dts = i_dts;
756 p_sys->i_pcr = i_dts;
759 else if( p_sys->i_pcr_soft_delay > 0 &&
760 p_sys->i_pcr + p_sys->i_pcr_soft_delay < i_dts )
762 p_sys->i_pcr = i_dts;
764 b_pcr_soft = VLC_TRUE;
769 if( ( p_sys->i_dts + p_sys->i_length ) - i_dts > 2000000 ||
770 ( p_sys->i_dts + p_sys->i_length ) - i_dts < -2000000 )
772 msg_Err( p_mux, "| buffer_dts - pcr_pts | > 2s ("I64Fd") empting "
773 "pcr TS buffers", p_sys->i_dts + p_sys->i_length - i_dts);
775 sout_BufferDelete( p_mux->p_sout, p_data );
777 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
779 sout_BufferDelete( p_mux->p_sout, p_data );
781 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
783 sout_BufferDelete( p_mux->p_sout, p_data );
788 if( i_dts >= p_sys->i_dts )
793 msg_Dbg( p_mux, "dropping buffer size=%d dts="I64Fd" pcr_dts="I64Fd
794 " diff="I64Fd, p_data->i_size, i_dts, p_sys->i_dts );
795 sout_BufferDelete( p_mux->p_sout, p_data );
798 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
800 BufferChainInit( &p_stream->chain_ts );
801 PEStoTS( p_mux->p_sout, &p_stream->chain_ts, p_data, p_stream, b_pcr );
803 TSSetDate( &p_stream->chain_ts, i_dts, i_length );
805 if( b_pcr_soft && p_stream->chain_ts.p_first )
807 p_stream->chain_ts.p_first->i_flags=SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT;
813 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 )
815 sout_mux_sys_t *p_sys = p_mux->p_sys;
816 sout_buffer_chain_t s = *c;
819 int i_packets_min = 0;
820 int i_packets_max = 0;
827 i_packets = c->i_depth;
828 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
829 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
831 if( i_packets < i_packets_min && i_packets_min > 0 )
834 int i_div = ( i_packets_min - i_packets ) / i_packets;
835 int i_mod = ( i_packets_min - i_packets ) % i_packets;
838 /* We need to pad with null packets (pid=0x1fff)
839 * We try to melt null packets with true packets */
841 "packets=%d but min=%d -> adding %d packets of padding",
842 i_packets, i_packets_min, i_packets_min - i_packets );
844 BufferChainInit( c );
845 while( ( p_pk = BufferChainGet( &s ) ) )
849 BufferChainAppend( c, p_pk );
851 i_null = i_div + ( i_rest + i_mod ) / i_packets;
853 for( i = 0; i < i_null; i++ )
855 sout_buffer_t *p_null;
857 p_null = sout_BufferNew( p_mux->p_sout, 188 );
858 p_null->p_buffer[0] = 0x47;
859 p_null->p_buffer[1] = 0x1f;
860 p_null->p_buffer[2] = 0xff;
861 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
862 memset( &p_null->p_buffer[4], 0, 184 );
863 p_sys->i_null_continuity_counter =
864 ( p_sys->i_null_continuity_counter + 1 ) % 16;
866 BufferChainAppend( c, p_null );
869 i_rest = ( i_rest + i_mod ) % i_packets;
872 else if( i_packets > i_packets_max && i_packets_max > 0 )
877 /* Arg, we need to drop packets, I don't do something clever (like
878 * dropping complete pid, b frames, ... ), I just get the right amount
879 * of packets and discard the others */
881 "packets=%d but max=%d -> removing %d packets -> stream broken",
882 i_packets, i_packets_max, i_packets - i_packets_max );
884 BufferChainInit( c );
885 for( i = 0; i < i_packets_max; i++ )
887 BufferChainAppend( c, BufferChainGet( &s ) );
890 while( ( p_pk = BufferChainGet( &s ) ) )
892 sout_BufferDelete( p_mux->p_sout, p_pk );
897 static void TSSetDate( sout_buffer_chain_t *c, mtime_t i_dts, mtime_t i_length )
900 mtime_t i_delta = i_length / c->i_depth;
903 for( p_ts = c->p_first; p_ts != NULL; p_ts = p_ts->p_next )
905 p_ts->i_dts = i_dts + i_packet * i_length / c->i_depth; /* avoid rounding error */
906 p_ts->i_length = i_delta;
908 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT )
910 mtime_t i_pcr = 9 * p_ts->i_dts / 100;
912 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
913 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
914 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
915 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
916 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
923 static void PEStoTS( sout_instance_t *p_sout,
924 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
925 ts_stream_t *p_stream,
932 /* get PES total size */
933 i_size = p_pes->i_size;
934 p_data = p_pes->p_buffer;
936 /* Set pcr only with valid DTS */
937 if( p_pes->i_dts <= 0 )
942 b_new_pes = VLC_TRUE;
946 int b_adaptation_field;
951 p_ts = sout_BufferNew( p_sout, 188 );
954 * 1b transport_error_indicator
955 * 1b payload_unit_start
956 * 1b transport_priority
958 * 2b transport_scrambling_control
959 * 2b if adaptation_field 0x03 else 0x01
960 * 4b continuity_counter
963 i_payload = 184 - ( b_pcr ? 8 : 0 );
964 i_copy = __MIN( i_size, i_payload );
965 b_adaptation_field = (b_pcr||i_size<i_payload) ? VLC_TRUE : VLC_FALSE;
967 p_ts->p_buffer[0] = 0x47;
968 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
969 ( ( p_stream->i_pid >> 8 )&0x1f );
970 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
971 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
972 p_stream->i_continuity_counter;
974 b_new_pes = VLC_FALSE;
975 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
977 if( b_adaptation_field )
983 mtime_t i_pcr = p_pes->i_dts * 9 / 100;
984 int i_stuffing = i_payload - i_copy;
986 p_ts->p_buffer[4] = 7 + i_stuffing;
987 p_ts->p_buffer[5] = 0x10; /* flags */
988 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
989 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
990 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
991 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
992 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
993 p_ts->p_buffer[11]= 0;
996 for( i = 12; i < 12 + i_stuffing; i++ )
998 p_ts->p_buffer[i] = 0xff;
1003 int i_stuffing = i_payload - i_copy;
1005 p_ts->p_buffer[4] = i_stuffing - 1;
1006 if( i_stuffing > 1 )
1008 p_ts->p_buffer[5] = 0x00;
1009 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1011 p_ts->p_buffer[i] = 0xff;
1017 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1021 BufferChainAppend( c, p_ts );
1025 sout_buffer_t *p_next = p_pes->p_next;
1027 p_pes->p_next = NULL;
1028 sout_BufferDelete( p_sout, p_pes );
1029 if( p_next == NULL )
1033 b_new_pes = VLC_TRUE;
1035 i_size = p_pes->i_size;
1036 p_data = p_pes->p_buffer;
1043 #if defined MODULE_NAME_IS_mux_ts
1044 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1046 static uint32_t CRC32[256] =
1048 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1049 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1050 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1051 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1052 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1053 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1054 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1055 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1056 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1057 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1058 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1059 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1060 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1061 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1062 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1063 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1064 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1065 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1066 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1067 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1068 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1069 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1070 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1071 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1072 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1073 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1074 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1075 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1076 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1077 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1078 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1079 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1080 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1081 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1082 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1083 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1084 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1085 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1086 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1087 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1088 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1089 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1090 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1091 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1092 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1093 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1094 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1095 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1096 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1097 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1098 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1099 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1100 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1101 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1102 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1103 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1104 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1105 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1106 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1107 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1108 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1109 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1110 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1111 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1114 uint32_t i_crc = 0xffffffff;
1116 /* Calculate the CRC */
1117 while( i_count > 0 )
1119 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1127 static void GetPAT( sout_mux_t *p_mux,
1128 sout_buffer_chain_t *c )
1130 sout_mux_sys_t *p_sys = p_mux->p_sys;
1131 sout_buffer_t *p_pat;
1134 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1138 p_pat->i_length = 0;
1140 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1142 bits_write( &bits, 8, 0 ); // pointer
1143 bits_write( &bits, 8, 0x00 ); // table id
1144 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1145 bits_write( &bits, 1, 0 ); // 0
1146 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1147 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1148 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1149 bits_write( &bits, 2, 0x03 ); // FIXME
1150 bits_write( &bits, 5, p_sys->i_pat_version_number );
1151 bits_write( &bits, 1, 1 ); // current_next_indicator
1152 bits_write( &bits, 8, 0 ); // section number
1153 bits_write( &bits, 8, 0 ); // last section number
1155 bits_write( &bits, 16, 1 ); // program number
1156 bits_write( &bits, 3, 0x07 ); // reserved
1157 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1159 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1161 p_pat->i_size = bits.i_data;
1163 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1166 static void GetPMT( sout_mux_t *p_mux,
1167 sout_buffer_chain_t *c )
1169 sout_mux_sys_t *p_sys = p_mux->p_sys;
1170 sout_buffer_t *p_pmt;
1174 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1178 p_pmt->i_length = 0;
1180 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1182 bits_write( &bits, 8, 0 ); // pointer
1183 bits_write( &bits, 8, 0x02 ); // table id
1184 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1185 bits_write( &bits, 1, 0 ); // 0
1186 bits_write( &bits, 2, 0 ); // reserved FIXME
1187 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1188 bits_write( &bits, 16, 1 ); // FIXME program number
1189 bits_write( &bits, 2, 0 ); // FIXME
1190 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1191 bits_write( &bits, 1, 1 ); // current_next_indicator
1192 bits_write( &bits, 8, 0 ); // section number
1193 bits_write( &bits, 8, 0 ); // last section number
1195 bits_write( &bits, 3, 0 ); // reserved
1197 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1198 bits_write( &bits, 4, 0 ); // reserved FIXME
1200 bits_write( &bits, 12, 0 ); // program info len FIXME
1202 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1204 ts_stream_t *p_stream;
1206 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1208 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1209 bits_write( &bits, 3, 0 ); // reserved
1210 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1211 bits_write( &bits, 4, 0 ); //reserved
1212 bits_write( &bits, 12, 0 ); // es info len FIXME
1215 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1217 p_pmt->i_size = bits.i_data;
1219 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1221 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1223 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1224 dvbpsi_psi_section_t* p_section )
1226 sout_buffer_t *p_psi, *p_first = NULL;
1233 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1234 ( p_section->b_syntax_indicator ? 4 : 0 );
1236 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1239 p_psi->i_length = 0;
1240 p_psi->i_size = i_size + 1;
1242 p_psi->p_buffer[0] = 0; // pointer
1243 memcpy( p_psi->p_buffer + 1,
1247 sout_BufferChain( &p_first, p_psi );
1249 p_section = p_section->p_next;
1255 static void GetPAT( sout_mux_t *p_mux,
1256 sout_buffer_chain_t *c )
1258 sout_mux_sys_t *p_sys = p_mux->p_sys;
1259 sout_buffer_t *p_pat;
1261 dvbpsi_psi_section_t *p_section;
1263 dvbpsi_InitPAT( &pat,
1265 p_sys->i_pat_version_number,
1266 1 ); // b_current_next
1267 /* add all program (only one) */
1268 dvbpsi_PATAddProgram( &pat,
1270 p_sys->pmt.i_pid ); // i_pid
1272 p_section = dvbpsi_GenPATSections( &pat,
1273 0 ); // max program per section
1275 p_pat = WritePSISection( p_mux->p_sout, p_section );
1277 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1279 dvbpsi_DeletePSISections( p_section );
1280 dvbpsi_EmptyPAT( &pat );
1283 static uint32_t GetDescriptorLength24b( int i_length )
1285 uint32_t i_l1, i_l2, i_l3;
1287 i_l1 = i_length&0x7f;
1288 i_l2 = ( i_length >> 7 )&0x7f;
1289 i_l3 = ( i_length >> 14 )&0x7f;
1291 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1294 static void GetPMT( sout_mux_t *p_mux,
1295 sout_buffer_chain_t *c )
1297 sout_mux_sys_t *p_sys = p_mux->p_sys;
1298 sout_buffer_t *p_pmt;
1301 dvbpsi_pmt_es_t *p_es;
1302 dvbpsi_psi_section_t *p_section;
1306 dvbpsi_InitPMT( &pmt,
1307 0x01, // program number
1308 p_sys->i_pmt_version_number,
1309 1, // b_current_next
1312 if( p_sys->i_mpeg4_streams > 0 )
1316 bits_buffer_t bits_fix_IOD;
1318 bits_initwrite( &bits, 4096, iod );
1320 bits_write( &bits, 8, 0x01 );
1321 // InitialObjectDescriptor
1322 bits_align( &bits );
1323 bits_write( &bits, 8, 0x02 ); // tag
1324 bits_fix_IOD = bits; // save states to fix length later
1325 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1326 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1327 bits_write( &bits, 1, 0x00 ); // URL Flag
1328 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1329 bits_write( &bits, 4, 0x0f ); // reserved
1330 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1331 bits_write( &bits, 8, 0xff ); // sceneProfile
1332 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1333 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1334 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1335 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1337 ts_stream_t *p_stream;
1338 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1340 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1342 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1344 bits_align( &bits );
1345 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1346 bits_fix_ESDescr = bits;
1347 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1348 bits_write( &bits, 16, p_stream->i_es_id );
1349 bits_write( &bits, 1, 0x00 ); // streamDependency
1350 bits_write( &bits, 1, 0x00 ); // URL Flag
1351 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1352 bits_write( &bits, 5, 0x1f ); // streamPriority
1354 // DecoderConfigDesciptor
1355 bits_align( &bits );
1356 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1357 bits_fix_Decoder = bits;
1358 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1359 if( p_stream->i_stream_type == 0x10 )
1361 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1362 bits_write( &bits, 6, 0x04 ); // VisualStream
1364 else if( p_stream->i_stream_type == 0x11 )
1366 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1367 bits_write( &bits, 6, 0x05 ); // AudioStream
1371 bits_write( &bits, 8, 0x00 );
1372 bits_write( &bits, 6, 0x00 );
1374 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1376 bits_write( &bits, 1, 0x00 ); // UpStream
1377 bits_write( &bits, 1, 0x01 ); // reserved
1378 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1379 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1380 bits_write( &bits, 32, 0 ); // avgBitrate
1382 if( p_stream->i_decoder_specific_info > 0 )
1385 // DecoderSpecificInfo
1386 bits_align( &bits );
1387 bits_write( &bits, 8, 0x05 ); // tag
1388 bits_write( &bits, 24,
1389 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1390 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1392 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1395 /* fix Decoder length */
1396 bits_write( &bits_fix_Decoder, 24,
1397 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1399 /* SLConfigDescriptor : predifined (0x01) */
1400 bits_align( &bits );
1401 bits_write( &bits, 8, 0x06 ); // tag
1402 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1403 bits_write( &bits, 8, 0x01 ); // predefined
1404 bits_write( &bits, 1, 0 ); // durationFlag
1405 bits_write( &bits, 32, 0 ); // OCRResolution
1406 bits_write( &bits, 8, 0 ); // OCRLength
1407 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1408 bits_align( &bits );
1410 /* fix ESDescr length */
1411 bits_write( &bits_fix_ESDescr, 24,
1412 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1415 bits_align( &bits );
1416 /* fix IOD length */
1417 bits_write( &bits_fix_IOD, 24,
1418 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1419 dvbpsi_PMTAddDescriptor( &pmt,
1425 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1427 ts_stream_t *p_stream;
1429 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1431 p_es = dvbpsi_PMTAddES( &pmt,
1432 p_stream->i_stream_type,
1434 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1440 bits_initwrite( &bits, 512, data );
1441 bits_write( &bits, 16, p_stream->i_es_id );
1443 dvbpsi_PMTESAddDescriptor( p_es,
1448 else if( p_stream->i_stream_id == 0xa0 )
1454 memcpy( fcc, &p_stream->i_bih_codec, 4 );
1456 /* private DIV3 descripor */
1457 bits_initwrite( &bits, 512, data );
1458 bits_write( &bits, 8, fcc[0]);
1459 bits_write( &bits, 8, fcc[1]);
1460 bits_write( &bits, 8, fcc[2]);
1461 bits_write( &bits, 8, fcc[3]);
1462 bits_write( &bits, 16, p_stream->i_bih_width );
1463 bits_write( &bits, 16, p_stream->i_bih_height );
1464 bits_write( &bits, 16, p_stream->i_decoder_specific_info );
1465 if( p_stream->i_decoder_specific_info > 0 )
1468 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1470 bits_write( &bits, 8, p_stream->p_decoder_specific_info[i] );
1473 dvbpsi_PMTESAddDescriptor( p_es,
1480 p_section = dvbpsi_GenPMTSections( &pmt );
1482 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1484 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1486 dvbpsi_DeletePSISections( p_section );
1487 dvbpsi_EmptyPMT( &pmt );