1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.23 2003/08/01 19:38:25 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"
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, disabling bitrate control" );
304 p_sys->i_bitrate_min = 0;
305 p_sys->i_bitrate_max = 0;
307 p_sys->i_pcr_delay = 100000;
308 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr" ) ) )
310 p_sys->i_pcr_delay = (int64_t)atoi( val ) * 1000;
311 if( p_sys->i_pcr_delay <= 0 )
314 "invalid pcr delay (%lldms) reseting to 100ms",
315 p_sys->i_pcr_delay / 1000 );
316 p_sys->i_pcr_delay = 100000;
319 p_sys->i_pcr_soft_delay = 0;
320 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr-soft" ) ) )
322 p_sys->i_pcr_soft_delay = (int64_t)atoi( val ) * 1000;
323 if( p_sys->i_pcr_soft_delay <= 0 ||
324 p_sys->i_pcr_soft_delay >= p_sys->i_pcr_delay )
327 "invalid pcr-soft delay (%lldms) disabled",
328 p_sys->i_pcr_soft_delay / 1000 );
329 p_sys->i_pcr_soft_delay = 0;
333 msg_Dbg( p_mux, "pcr_delay=%lld pcr_soft_delay=%lld", p_sys->i_pcr_delay, p_sys->i_pcr_soft_delay );
334 /* for TS génération */
338 BufferChainInit( &p_sys->chain_ts );
342 /*****************************************************************************
344 *****************************************************************************/
345 static void Close( vlc_object_t * p_this )
347 sout_mux_t *p_mux = (sout_mux_t*)p_this;
348 sout_mux_sys_t *p_sys = p_mux->p_sys;
349 sout_buffer_t *p_data;
351 msg_Dbg( p_mux, "Close" );
353 /* Empty TS buffer */
354 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
356 sout_BufferDelete( p_mux->p_sout, p_data );
362 /*****************************************************************************
364 *****************************************************************************/
365 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
369 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
370 *(vlc_bool_t*)p_answer = VLC_TRUE;
371 return( SOUT_MUX_CAP_ERR_OK );
373 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
377 /*****************************************************************************
378 * AddStream: called for each stream addition
379 *****************************************************************************/
380 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
382 sout_mux_sys_t *p_sys = p_mux->p_sys;
383 ts_stream_t *p_stream;
385 msg_Dbg( p_mux, "adding input codec=%4.4s", (char*)&p_input->p_fmt->i_fourcc );
387 p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
389 /* Init this new stream */
390 p_stream->i_pid = AllocatePID( p_sys );
391 p_stream->i_continuity_counter = 0;
392 p_stream->i_decoder_specific_info = 0;
393 p_stream->p_decoder_specific_info = NULL;
395 /* All others fields depand on codec */
396 switch( p_input->p_fmt->i_cat )
399 switch( p_input->p_fmt->i_fourcc )
401 case VLC_FOURCC( 'm', 'p','g', 'v' ):
402 /* TODO: do we need to check MPEG-I/II ? */
403 p_stream->i_stream_type = 0x02;
404 p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
405 p_sys->i_stream_id_mpgv++;
407 case VLC_FOURCC( 'm', 'p','4', 'v' ):
408 p_stream->i_stream_type = 0x10;
409 p_stream->i_stream_id = 0xfa;
410 p_sys->i_mpeg4_streams++;
411 p_stream->i_es_id = p_stream->i_pid;
413 /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
414 /* I didn't want to do that :P */
415 case VLC_FOURCC( 'H', '2', '6', '3' ):
416 case VLC_FOURCC( 'I', '2', '6', '3' ):
417 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
418 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
419 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
420 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
421 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
422 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
423 p_stream->i_stream_type = 0xa0; // private
424 p_stream->i_stream_id = 0xa0; // beurk
425 p_stream->i_bih_codec = p_input->p_fmt->i_fourcc;
426 p_stream->i_bih_width = p_input->p_fmt->i_width;
427 p_stream->i_bih_height = p_input->p_fmt->i_height;
433 p_sys->i_video_bound++;
437 switch( p_input->p_fmt->i_fourcc )
439 case VLC_FOURCC( 'm', 'p','g', 'a' ):
440 p_stream->i_stream_type = p_input->p_fmt->i_sample_rate >= 32000 ? 0x03 : 0x04;
441 p_stream->i_stream_id = p_sys->i_stream_id_mpga;
442 p_sys->i_stream_id_mpga++;
444 case VLC_FOURCC( 'a', '5','2', ' ' ):
445 p_stream->i_stream_type = 0x81;
446 p_stream->i_stream_id = p_sys->i_stream_id_a52;
447 p_sys->i_stream_id_a52++;
449 case VLC_FOURCC( 'm', 'p','4', 'a' ):
450 p_stream->i_stream_type = 0x11;
451 p_stream->i_stream_id = 0xfa;
452 p_sys->i_mpeg4_streams++;
453 p_stream->i_es_id = p_stream->i_pid;
459 p_sys->i_audio_bound++;
463 switch( p_input->p_fmt->i_fourcc )
465 case VLC_FOURCC( 's', 'p','u', ' ' ):
466 p_stream->i_stream_type = 0x82;
467 p_stream->i_stream_id = 0x82;
480 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
481 p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra_data;
482 if( p_stream->i_decoder_specific_info > 0 )
484 p_stream->p_decoder_specific_info =
485 malloc( p_stream->i_decoder_specific_info );
486 memcpy( p_stream->p_decoder_specific_info,
487 p_input->p_fmt->p_extra_data,
488 p_input->p_fmt->i_extra_data );
490 /* Init chain for TS building */
491 BufferChainInit( &p_stream->chain_ts );
493 /* We only change PMT version (PAT isn't changed) */
494 p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
497 if( p_input->p_fmt->i_cat != SPU_ES &&
498 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
500 sout_buffer_t *p_data;
502 if( p_sys->p_pcr_input )
504 /* There was already a PCR stream, so clean context */
505 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
507 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
509 sout_BufferDelete( p_mux->p_sout, p_data );
512 p_sys->i_pcr_pid = p_stream->i_pid;
513 p_sys->p_pcr_input = p_input;
515 /* Empty TS buffer (avoid broken data or problem with pcr stream changement ) */
516 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
518 sout_BufferDelete( p_mux->p_sout, p_data );
525 /*****************************************************************************
526 * DelStream: called before a stream deletion
527 *****************************************************************************/
528 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
530 sout_mux_sys_t *p_sys = p_mux->p_sys;
531 ts_stream_t *p_stream;
532 sout_buffer_t *p_data;
534 msg_Dbg( p_mux, "removing input" );
535 p_stream = (ts_stream_t*)p_input->p_sys;
537 if( p_sys->i_pcr_pid == p_stream->i_pid )
541 /* Find a new pcr stream (Prefer Video Stream) */
542 p_sys->i_pcr_pid = 0x1fff;
543 for( i = 0; i < p_mux->i_nb_inputs; i++ )
545 if( p_mux->pp_inputs[i] == p_input )
550 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
552 p_sys->i_pcr_pid = ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
553 p_sys->p_pcr_input= p_mux->pp_inputs[i];
556 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES && p_sys->i_pcr_pid == 0x1fff )
558 p_sys->i_pcr_pid = ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
559 p_sys->p_pcr_input= p_mux->pp_inputs[i];
562 if( p_sys->p_pcr_input )
564 /* Empty TS buffer */
565 while( ( p_data = BufferChainGet( &((ts_stream_t*)p_sys->p_pcr_input->p_sys)->chain_ts ) ) )
567 sout_BufferDelete( p_mux->p_sout, p_data );
572 /* Empty all data in chain_ts */
573 while( ( p_data = BufferChainGet( &p_stream->chain_ts ) ) )
575 sout_BufferDelete( p_mux->p_sout, p_data );
577 if( p_stream->p_decoder_specific_info )
579 free( p_stream->p_decoder_specific_info );
581 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
583 p_sys->i_mpeg4_streams--;
587 /* We only change PMT version (PAT isn't changed) */
588 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
590 /* Empty TS buffer (avoid broken data or problem with pcr stream changement ) */
591 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
593 sout_BufferDelete( p_mux->p_sout, p_data );
599 /*****************************************************************************
600 * Mux: Call each time there is new data for at least one stream
601 *****************************************************************************
603 *****************************************************************************/
604 static int Mux( sout_mux_t *p_mux )
606 sout_mux_sys_t *p_sys = p_mux->p_sys;
608 sout_input_t *p_pcr_input = p_sys->p_pcr_input;
609 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
611 if( p_sys->i_pcr_pid == 0x1fff )
613 msg_Dbg( p_mux, "waiting PCR streams" );
620 ts_stream_t *p_stream = NULL;
621 sout_buffer_t *p_data;
626 /* fill ts packets for pcr XXX before GetPAT/GetPMT */
627 if( p_pcr_stream->chain_ts.p_first == NULL && TSFill( p_mux, p_pcr_input ) )
629 /* We need more data */
633 if( p_sys->chain_ts.p_first == NULL )
635 /* Every pcr packet send PAT/PMT */
636 GetPAT( p_mux, &p_sys->chain_ts);
637 GetPMT( p_mux, &p_sys->chain_ts );
640 /* search stream with lowest dts */
641 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
643 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
645 if( p_stream->chain_ts.p_first == NULL )
647 if( TSFill( p_mux, p_mux->pp_inputs[i] ) )
649 /* We need more data */
652 if( p_stream->chain_ts.p_first == NULL )
654 continue; /* SPU_ES */
658 if( i_stream == -1 ||
659 p_stream->chain_ts.p_first->i_dts < i_dts )
662 i_dts = p_stream->chain_ts.p_first->i_dts;
666 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
668 p_data = BufferChainGet( &p_stream->chain_ts );
669 BufferChainAppend( &p_sys->chain_ts, p_data );
671 if( p_stream->i_pid == p_pcr_stream->i_pid && p_stream->chain_ts.p_first == NULL )
673 sout_buffer_t *p_ts = p_sys->chain_ts.p_first;
675 /* We have consume all TS packets from the PCR stream */
677 if( p_sys->i_length > p_sys->i_pcr_delay )
679 /* Send TS data if last PCR was i_pcr_delay ago */
681 if( p_sys->i_bitrate_min > 0 ||
682 p_sys->i_bitrate_max > 0 )
684 TSSetConstraints( p_mux, &p_sys->chain_ts, p_sys->i_length,
685 p_sys->i_bitrate_min, p_sys->i_bitrate_max );
689 TSSetDate( &p_sys->chain_ts,
690 p_sys->i_dts + 3 * p_sys->i_pcr_delay / 2, /* latency is equal to i_pcr_delay, 3/2 is for security */
692 sout_AccessOutWrite( p_mux->p_access, p_ts );
694 /* Reset the ts chain */
695 BufferChainInit( &p_sys->chain_ts );
707 /*****************************************************************************
710 *****************************************************************************/
711 static int TSFill( sout_mux_t *p_mux, sout_input_t *p_input )
713 sout_mux_sys_t *p_sys = p_mux->p_sys;
715 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
716 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
717 mtime_t i_dts, i_length;
718 sout_buffer_t *p_data;
719 vlc_bool_t b_pcr = VLC_FALSE;
720 vlc_bool_t b_pcr_soft = VLC_FALSE;
725 if( p_input->p_fifo->i_depth <= 0 )
727 if( p_input->p_fmt->i_cat == AUDIO_ES || p_input->p_fmt->i_cat == VIDEO_ES )
729 /* We need more data */
737 p_data = sout_FifoGet( p_input->p_fifo );
738 i_dts = p_data->i_dts;
739 i_length = p_data->i_length;
741 if( p_stream->i_pid == p_pcr_stream->i_pid &&
742 p_stream->chain_ts.p_first == NULL )
744 p_sys->i_length+= i_length;
745 if( p_sys->chain_ts.p_first == NULL )
747 p_sys->i_dts = i_dts;
748 p_sys->i_pcr = i_dts;
751 else if( p_sys->i_pcr_soft_delay > 0 &&
752 p_sys->i_pcr + p_sys->i_pcr_soft_delay < i_dts )
754 p_sys->i_pcr = i_dts;
756 b_pcr_soft = VLC_TRUE;
761 if( ( p_sys->i_dts +p_sys->i_length ) - i_dts > 2000000 ||
762 ( p_sys->i_dts + p_sys->i_length ) - i_dts < -2000000 )
764 msg_Err( p_mux, "| buffer_dts - pcr_pts | > 2s empting pcr TS buffers" );
766 sout_BufferDelete( p_mux->p_sout, p_data );
768 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
770 sout_BufferDelete( p_mux->p_sout, p_data );
772 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
774 sout_BufferDelete( p_mux->p_sout, p_data );
779 if( i_dts >= p_sys->i_dts )
785 "dropping buffer size=%d dts=%lld pcr_dts=%lld",
786 p_data->i_size, i_dts, p_sys->i_dts );
787 sout_BufferDelete( p_mux->p_sout, p_data );
790 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
792 BufferChainInit( &p_stream->chain_ts );
793 PEStoTS( p_mux->p_sout, &p_stream->chain_ts, p_data, p_stream, b_pcr );
795 TSSetDate( &p_stream->chain_ts, i_dts, i_length );
797 if( b_pcr_soft && p_stream->chain_ts.p_first )
799 p_stream->chain_ts.p_first->i_flags = SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT;
805 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 )
807 sout_mux_sys_t *p_sys = p_mux->p_sys;
808 sout_buffer_chain_t s = *c;
811 int i_packets_min = 0;
812 int i_packets_max = 0;
819 i_packets = c->i_depth;
820 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
821 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
823 if( i_packets < i_packets_min && i_packets_min > 0 )
826 int i_div = ( i_packets_min - i_packets ) / i_packets;
827 int i_mod = ( i_packets_min - i_packets ) % i_packets;
830 /* We need to pad with null packets (pid=0x1fff)
831 * We try to melt null packets with true packets */
833 "packets=%d but min=%d -> adding %d packets of padding",
834 i_packets, i_packets_min, i_packets_min - i_packets );
836 BufferChainInit( c );
837 while( ( p_pk = BufferChainGet( &s ) ) )
841 BufferChainAppend( c, p_pk );
843 i_null = i_div + ( i_rest + i_mod ) / i_packets;
845 for( i = 0; i < i_null; i++ )
847 sout_buffer_t *p_null;
849 p_null = sout_BufferNew( p_mux->p_sout, 188 );
850 p_null->p_buffer[0] = 0x47;
851 p_null->p_buffer[1] = 0x1f;
852 p_null->p_buffer[2] = 0xff;
853 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
854 memset( &p_null->p_buffer[4], 0, 184 );
855 p_sys->i_null_continuity_counter =
856 ( p_sys->i_null_continuity_counter + 1 ) % 16;
858 BufferChainAppend( c, p_null );
861 i_rest = ( i_rest + i_mod ) % i_packets;
864 else if( i_packets > i_packets_max && i_packets_max > 0 )
869 /* Arg, we need to drop packets, I don't do something clever (like
870 * dropping complete pid, b frames, ... ), I just get the right amount
871 * of packets and discard the others */
873 "packets=%d but max=%d -> removing %d packets -> stream broken",
874 i_packets, i_packets_max, i_packets - i_packets_max );
876 BufferChainInit( c );
877 for( i = 0; i < i_packets_max; i++ )
879 BufferChainAppend( c, BufferChainGet( &s ) );
882 while( ( p_pk = BufferChainGet( &s ) ) )
884 sout_BufferDelete( p_mux->p_sout, p_pk );
889 static void TSSetDate( sout_buffer_chain_t *c, mtime_t i_dts, mtime_t i_length )
892 mtime_t i_delta = i_length / c->i_depth;
895 for( p_ts = c->p_first; p_ts != NULL; p_ts = p_ts->p_next )
897 p_ts->i_dts = i_dts + i_packet * i_length / c->i_depth; /* avoid rounding error */
898 p_ts->i_length = i_delta;
900 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT )
902 mtime_t i_pcr = 9 * p_ts->i_dts / 100;
904 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
905 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
906 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
907 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
908 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
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 bits_initwrite( &bits, 4096, iod );
1312 bits_write( &bits, 8, 0x01 );
1313 // InitialObjectDescriptor
1314 bits_align( &bits );
1315 bits_write( &bits, 8, 0x02 ); // tag
1316 bits_fix_IOD = bits; // save states to fix length later
1317 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1318 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1319 bits_write( &bits, 1, 0x00 ); // URL Flag
1320 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1321 bits_write( &bits, 4, 0x0f ); // reserved
1322 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1323 bits_write( &bits, 8, 0xff ); // sceneProfile
1324 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1325 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1326 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1327 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1329 ts_stream_t *p_stream;
1330 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1332 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1334 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1336 bits_align( &bits );
1337 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1338 bits_fix_ESDescr = bits;
1339 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1340 bits_write( &bits, 16, p_stream->i_es_id );
1341 bits_write( &bits, 1, 0x00 ); // streamDependency
1342 bits_write( &bits, 1, 0x00 ); // URL Flag
1343 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1344 bits_write( &bits, 5, 0x1f ); // streamPriority
1346 // DecoderConfigDesciptor
1347 bits_align( &bits );
1348 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1349 bits_fix_Decoder = bits;
1350 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1351 if( p_stream->i_stream_type == 0x10 )
1353 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1354 bits_write( &bits, 6, 0x04 ); // VisualStream
1356 else if( p_stream->i_stream_type == 0x11 )
1358 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1359 bits_write( &bits, 6, 0x05 ); // AudioStream
1363 bits_write( &bits, 8, 0x00 );
1364 bits_write( &bits, 6, 0x00 );
1366 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1368 bits_write( &bits, 1, 0x00 ); // UpStream
1369 bits_write( &bits, 1, 0x01 ); // reserved
1370 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1371 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1372 bits_write( &bits, 32, 0 ); // avgBitrate
1374 if( p_stream->i_decoder_specific_info > 0 )
1377 // DecoderSpecificInfo
1378 bits_align( &bits );
1379 bits_write( &bits, 8, 0x05 ); // tag
1380 bits_write( &bits, 24,
1381 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1382 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1384 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1387 /* fix Decoder length */
1388 bits_write( &bits_fix_Decoder, 24,
1389 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1391 /* SLConfigDescriptor : predifined (0x01) */
1392 bits_align( &bits );
1393 bits_write( &bits, 8, 0x06 ); // tag
1394 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1395 bits_write( &bits, 8, 0x01 ); // predefined
1396 bits_write( &bits, 1, 0 ); // durationFlag
1397 bits_write( &bits, 32, 0 ); // OCRResolution
1398 bits_write( &bits, 8, 0 ); // OCRLength
1399 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1400 bits_align( &bits );
1402 /* fix ESDescr length */
1403 bits_write( &bits_fix_ESDescr, 24,
1404 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1407 bits_align( &bits );
1408 /* fix IOD length */
1409 bits_write( &bits_fix_IOD, 24,
1410 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1411 dvbpsi_PMTAddDescriptor( &pmt,
1417 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1419 ts_stream_t *p_stream;
1421 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1423 p_es = dvbpsi_PMTAddES( &pmt,
1424 p_stream->i_stream_type,
1426 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1432 bits_initwrite( &bits, 512, data );
1433 bits_write( &bits, 16, p_stream->i_es_id );
1435 dvbpsi_PMTESAddDescriptor( p_es,
1440 else if( p_stream->i_stream_id == 0xa0 )
1446 memcpy( fcc, &p_stream->i_bih_codec, 4 );
1448 /* private DIV3 descripor */
1449 bits_initwrite( &bits, 512, data );
1450 bits_write( &bits, 8, fcc[0]);
1451 bits_write( &bits, 8, fcc[1]);
1452 bits_write( &bits, 8, fcc[2]);
1453 bits_write( &bits, 8, fcc[3]);
1454 bits_write( &bits, 16, p_stream->i_bih_width );
1455 bits_write( &bits, 16, p_stream->i_bih_height );
1456 bits_write( &bits, 16, p_stream->i_decoder_specific_info );
1457 if( p_stream->i_decoder_specific_info > 0 )
1460 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1462 bits_write( &bits, 8, p_stream->p_decoder_specific_info[i] );
1465 dvbpsi_PMTESAddDescriptor( p_es,
1472 p_section = dvbpsi_GenPMTSections( &pmt );
1474 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1476 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1478 dvbpsi_DeletePSISections( p_section );
1479 dvbpsi_EmptyPMT( &pmt );