1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.26 2003/08/10 14:23:15 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="I64Fd" 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 p_sys->i_dts + p_sys->i_length - i_dts );
796 sout_BufferDelete( p_mux->p_sout, p_data );
799 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
801 BufferChainInit( &p_stream->chain_ts );
802 PEStoTS( p_mux->p_sout, &p_stream->chain_ts, p_data, p_stream, b_pcr );
804 TSSetDate( &p_stream->chain_ts, i_dts, i_length );
806 if( b_pcr_soft && p_stream->chain_ts.p_first )
808 p_stream->chain_ts.p_first->i_flags=SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT;
814 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 )
816 sout_mux_sys_t *p_sys = p_mux->p_sys;
817 sout_buffer_chain_t s = *c;
820 int i_packets_min = 0;
821 int i_packets_max = 0;
828 i_packets = c->i_depth;
829 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
830 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
832 if( i_packets < i_packets_min && i_packets_min > 0 )
835 int i_div = ( i_packets_min - i_packets ) / i_packets;
836 int i_mod = ( i_packets_min - i_packets ) % i_packets;
839 /* We need to pad with null packets (pid=0x1fff)
840 * We try to melt null packets with true packets */
842 "packets=%d but min=%d -> adding %d packets of padding",
843 i_packets, i_packets_min, i_packets_min - i_packets );
845 BufferChainInit( c );
846 while( ( p_pk = BufferChainGet( &s ) ) )
850 BufferChainAppend( c, p_pk );
852 i_null = i_div + ( i_rest + i_mod ) / i_packets;
854 for( i = 0; i < i_null; i++ )
856 sout_buffer_t *p_null;
858 p_null = sout_BufferNew( p_mux->p_sout, 188 );
859 p_null->p_buffer[0] = 0x47;
860 p_null->p_buffer[1] = 0x1f;
861 p_null->p_buffer[2] = 0xff;
862 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
863 memset( &p_null->p_buffer[4], 0, 184 );
864 p_sys->i_null_continuity_counter =
865 ( p_sys->i_null_continuity_counter + 1 ) % 16;
867 BufferChainAppend( c, p_null );
870 i_rest = ( i_rest + i_mod ) % i_packets;
873 else if( i_packets > i_packets_max && i_packets_max > 0 )
878 /* Arg, we need to drop packets, I don't do something clever (like
879 * dropping complete pid, b frames, ... ), I just get the right amount
880 * of packets and discard the others */
882 "packets=%d but max=%d -> removing %d packets -> stream broken",
883 i_packets, i_packets_max, i_packets - i_packets_max );
885 BufferChainInit( c );
886 for( i = 0; i < i_packets_max; i++ )
888 BufferChainAppend( c, BufferChainGet( &s ) );
891 while( ( p_pk = BufferChainGet( &s ) ) )
893 sout_BufferDelete( p_mux->p_sout, p_pk );
898 static void TSSetDate( sout_buffer_chain_t *c, mtime_t i_dts, mtime_t i_length )
901 mtime_t i_delta = i_length / c->i_depth;
904 for( p_ts = c->p_first; p_ts != NULL; p_ts = p_ts->p_next )
906 p_ts->i_dts = i_dts + i_packet * i_length / c->i_depth; /* avoid rounding error */
907 p_ts->i_length = i_delta;
909 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT )
911 mtime_t i_pcr = 9 * p_ts->i_dts / 100;
913 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
914 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
915 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
916 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
917 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
924 static void PEStoTS( sout_instance_t *p_sout,
925 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
926 ts_stream_t *p_stream,
933 /* get PES total size */
934 i_size = p_pes->i_size;
935 p_data = p_pes->p_buffer;
937 /* Set pcr only with valid DTS */
938 if( p_pes->i_dts <= 0 )
943 b_new_pes = VLC_TRUE;
947 int b_adaptation_field;
952 p_ts = sout_BufferNew( p_sout, 188 );
955 * 1b transport_error_indicator
956 * 1b payload_unit_start
957 * 1b transport_priority
959 * 2b transport_scrambling_control
960 * 2b if adaptation_field 0x03 else 0x01
961 * 4b continuity_counter
964 i_payload = 184 - ( b_pcr ? 8 : 0 );
965 i_copy = __MIN( i_size, i_payload );
966 b_adaptation_field = (b_pcr||i_size<i_payload) ? VLC_TRUE : VLC_FALSE;
968 p_ts->p_buffer[0] = 0x47;
969 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
970 ( ( p_stream->i_pid >> 8 )&0x1f );
971 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
972 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
973 p_stream->i_continuity_counter;
975 b_new_pes = VLC_FALSE;
976 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
978 if( b_adaptation_field )
984 mtime_t i_pcr = p_pes->i_dts * 9 / 100;
985 int i_stuffing = i_payload - i_copy;
987 p_ts->p_buffer[4] = 7 + i_stuffing;
988 p_ts->p_buffer[5] = 0x10; /* flags */
989 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
990 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
991 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
992 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
993 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
994 p_ts->p_buffer[11]= 0;
997 for( i = 12; i < 12 + i_stuffing; i++ )
999 p_ts->p_buffer[i] = 0xff;
1004 int i_stuffing = i_payload - i_copy;
1006 p_ts->p_buffer[4] = i_stuffing - 1;
1007 if( i_stuffing > 1 )
1009 p_ts->p_buffer[5] = 0x00;
1010 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1012 p_ts->p_buffer[i] = 0xff;
1018 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1022 BufferChainAppend( c, p_ts );
1026 sout_buffer_t *p_next = p_pes->p_next;
1028 p_pes->p_next = NULL;
1029 sout_BufferDelete( p_sout, p_pes );
1030 if( p_next == NULL )
1034 b_new_pes = VLC_TRUE;
1036 i_size = p_pes->i_size;
1037 p_data = p_pes->p_buffer;
1044 #if defined MODULE_NAME_IS_mux_ts
1045 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1047 static uint32_t CRC32[256] =
1049 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1050 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1051 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1052 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1053 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1054 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1055 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1056 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1057 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1058 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1059 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1060 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1061 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1062 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1063 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1064 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1065 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1066 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1067 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1068 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1069 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1070 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1071 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1072 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1073 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1074 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1075 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1076 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1077 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1078 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1079 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1080 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1081 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1082 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1083 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1084 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1085 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1086 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1087 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1088 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1089 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1090 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1091 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1092 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1093 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1094 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1095 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1096 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1097 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1098 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1099 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1100 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1101 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1102 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1103 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1104 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1105 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1106 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1107 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1108 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1109 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1110 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1111 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1112 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1115 uint32_t i_crc = 0xffffffff;
1117 /* Calculate the CRC */
1118 while( i_count > 0 )
1120 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1128 static void GetPAT( sout_mux_t *p_mux,
1129 sout_buffer_chain_t *c )
1131 sout_mux_sys_t *p_sys = p_mux->p_sys;
1132 sout_buffer_t *p_pat;
1135 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1139 p_pat->i_length = 0;
1141 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1143 bits_write( &bits, 8, 0 ); // pointer
1144 bits_write( &bits, 8, 0x00 ); // table id
1145 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1146 bits_write( &bits, 1, 0 ); // 0
1147 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1148 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1149 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1150 bits_write( &bits, 2, 0x03 ); // FIXME
1151 bits_write( &bits, 5, p_sys->i_pat_version_number );
1152 bits_write( &bits, 1, 1 ); // current_next_indicator
1153 bits_write( &bits, 8, 0 ); // section number
1154 bits_write( &bits, 8, 0 ); // last section number
1156 bits_write( &bits, 16, 1 ); // program number
1157 bits_write( &bits, 3, 0x07 ); // reserved
1158 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1160 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1162 p_pat->i_size = bits.i_data;
1164 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1167 static void GetPMT( sout_mux_t *p_mux,
1168 sout_buffer_chain_t *c )
1170 sout_mux_sys_t *p_sys = p_mux->p_sys;
1171 sout_buffer_t *p_pmt;
1175 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1179 p_pmt->i_length = 0;
1181 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1183 bits_write( &bits, 8, 0 ); // pointer
1184 bits_write( &bits, 8, 0x02 ); // table id
1185 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1186 bits_write( &bits, 1, 0 ); // 0
1187 bits_write( &bits, 2, 0 ); // reserved FIXME
1188 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1189 bits_write( &bits, 16, 1 ); // FIXME program number
1190 bits_write( &bits, 2, 0 ); // FIXME
1191 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1192 bits_write( &bits, 1, 1 ); // current_next_indicator
1193 bits_write( &bits, 8, 0 ); // section number
1194 bits_write( &bits, 8, 0 ); // last section number
1196 bits_write( &bits, 3, 0 ); // reserved
1198 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1199 bits_write( &bits, 4, 0 ); // reserved FIXME
1201 bits_write( &bits, 12, 0 ); // program info len FIXME
1203 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1205 ts_stream_t *p_stream;
1207 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1209 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1210 bits_write( &bits, 3, 0 ); // reserved
1211 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1212 bits_write( &bits, 4, 0 ); //reserved
1213 bits_write( &bits, 12, 0 ); // es info len FIXME
1216 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1218 p_pmt->i_size = bits.i_data;
1220 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1222 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1224 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1225 dvbpsi_psi_section_t* p_section )
1227 sout_buffer_t *p_psi, *p_first = NULL;
1234 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1235 ( p_section->b_syntax_indicator ? 4 : 0 );
1237 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1240 p_psi->i_length = 0;
1241 p_psi->i_size = i_size + 1;
1243 p_psi->p_buffer[0] = 0; // pointer
1244 memcpy( p_psi->p_buffer + 1,
1248 sout_BufferChain( &p_first, p_psi );
1250 p_section = p_section->p_next;
1256 static void GetPAT( sout_mux_t *p_mux,
1257 sout_buffer_chain_t *c )
1259 sout_mux_sys_t *p_sys = p_mux->p_sys;
1260 sout_buffer_t *p_pat;
1262 dvbpsi_psi_section_t *p_section;
1264 dvbpsi_InitPAT( &pat,
1266 p_sys->i_pat_version_number,
1267 1 ); // b_current_next
1268 /* add all program (only one) */
1269 dvbpsi_PATAddProgram( &pat,
1271 p_sys->pmt.i_pid ); // i_pid
1273 p_section = dvbpsi_GenPATSections( &pat,
1274 0 ); // max program per section
1276 p_pat = WritePSISection( p_mux->p_sout, p_section );
1278 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1280 dvbpsi_DeletePSISections( p_section );
1281 dvbpsi_EmptyPAT( &pat );
1284 static uint32_t GetDescriptorLength24b( int i_length )
1286 uint32_t i_l1, i_l2, i_l3;
1288 i_l1 = i_length&0x7f;
1289 i_l2 = ( i_length >> 7 )&0x7f;
1290 i_l3 = ( i_length >> 14 )&0x7f;
1292 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1295 static void GetPMT( sout_mux_t *p_mux,
1296 sout_buffer_chain_t *c )
1298 sout_mux_sys_t *p_sys = p_mux->p_sys;
1299 sout_buffer_t *p_pmt;
1302 dvbpsi_pmt_es_t *p_es;
1303 dvbpsi_psi_section_t *p_section;
1307 dvbpsi_InitPMT( &pmt,
1308 0x01, // program number
1309 p_sys->i_pmt_version_number,
1310 1, // b_current_next
1313 if( p_sys->i_mpeg4_streams > 0 )
1317 bits_buffer_t bits_fix_IOD;
1319 bits_initwrite( &bits, 4096, iod );
1321 bits_write( &bits, 8, 0x01 );
1322 // InitialObjectDescriptor
1323 bits_align( &bits );
1324 bits_write( &bits, 8, 0x02 ); // tag
1325 bits_fix_IOD = bits; // save states to fix length later
1326 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1327 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1328 bits_write( &bits, 1, 0x00 ); // URL Flag
1329 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1330 bits_write( &bits, 4, 0x0f ); // reserved
1331 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1332 bits_write( &bits, 8, 0xff ); // sceneProfile
1333 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1334 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1335 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1336 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1338 ts_stream_t *p_stream;
1339 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1341 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1343 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1345 bits_align( &bits );
1346 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1347 bits_fix_ESDescr = bits;
1348 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1349 bits_write( &bits, 16, p_stream->i_es_id );
1350 bits_write( &bits, 1, 0x00 ); // streamDependency
1351 bits_write( &bits, 1, 0x00 ); // URL Flag
1352 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1353 bits_write( &bits, 5, 0x1f ); // streamPriority
1355 // DecoderConfigDesciptor
1356 bits_align( &bits );
1357 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1358 bits_fix_Decoder = bits;
1359 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1360 if( p_stream->i_stream_type == 0x10 )
1362 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1363 bits_write( &bits, 6, 0x04 ); // VisualStream
1365 else if( p_stream->i_stream_type == 0x11 )
1367 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1368 bits_write( &bits, 6, 0x05 ); // AudioStream
1372 bits_write( &bits, 8, 0x00 );
1373 bits_write( &bits, 6, 0x00 );
1375 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1377 bits_write( &bits, 1, 0x00 ); // UpStream
1378 bits_write( &bits, 1, 0x01 ); // reserved
1379 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1380 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1381 bits_write( &bits, 32, 0 ); // avgBitrate
1383 if( p_stream->i_decoder_specific_info > 0 )
1386 // DecoderSpecificInfo
1387 bits_align( &bits );
1388 bits_write( &bits, 8, 0x05 ); // tag
1389 bits_write( &bits, 24,
1390 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1391 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1393 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1396 /* fix Decoder length */
1397 bits_write( &bits_fix_Decoder, 24,
1398 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1400 /* SLConfigDescriptor : predifined (0x01) */
1401 bits_align( &bits );
1402 bits_write( &bits, 8, 0x06 ); // tag
1403 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1404 bits_write( &bits, 8, 0x01 ); // predefined
1405 bits_write( &bits, 1, 0 ); // durationFlag
1406 bits_write( &bits, 32, 0 ); // OCRResolution
1407 bits_write( &bits, 8, 0 ); // OCRLength
1408 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1409 bits_align( &bits );
1411 /* fix ESDescr length */
1412 bits_write( &bits_fix_ESDescr, 24,
1413 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1416 bits_align( &bits );
1417 /* fix IOD length */
1418 bits_write( &bits_fix_IOD, 24,
1419 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1420 dvbpsi_PMTAddDescriptor( &pmt,
1426 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1428 ts_stream_t *p_stream;
1430 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1432 p_es = dvbpsi_PMTAddES( &pmt,
1433 p_stream->i_stream_type,
1435 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1441 bits_initwrite( &bits, 512, data );
1442 bits_write( &bits, 16, p_stream->i_es_id );
1444 dvbpsi_PMTESAddDescriptor( p_es,
1449 else if( p_stream->i_stream_id == 0xa0 )
1455 memcpy( fcc, &p_stream->i_bih_codec, 4 );
1457 /* private DIV3 descripor */
1458 bits_initwrite( &bits, 512, data );
1459 bits_write( &bits, 8, fcc[0]);
1460 bits_write( &bits, 8, fcc[1]);
1461 bits_write( &bits, 8, fcc[2]);
1462 bits_write( &bits, 8, fcc[3]);
1463 bits_write( &bits, 16, p_stream->i_bih_width );
1464 bits_write( &bits, 16, p_stream->i_bih_height );
1465 bits_write( &bits, 16, p_stream->i_decoder_specific_info );
1466 if( p_stream->i_decoder_specific_info > 0 )
1469 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1471 bits_write( &bits, 8, p_stream->p_decoder_specific_info[i] );
1474 dvbpsi_PMTESAddDescriptor( p_es,
1481 p_section = dvbpsi_GenPMTSections( &pmt );
1483 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1485 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1487 dvbpsi_DeletePSISections( p_section );
1488 dvbpsi_EmptyPMT( &pmt );