1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.24 2003/08/04 22:49:02 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",
334 p_sys->i_pcr_delay, p_sys->i_pcr_soft_delay );
335 /* for TS génération */
339 BufferChainInit( &p_sys->chain_ts );
343 /*****************************************************************************
345 *****************************************************************************/
346 static void Close( vlc_object_t * p_this )
348 sout_mux_t *p_mux = (sout_mux_t*)p_this;
349 sout_mux_sys_t *p_sys = p_mux->p_sys;
350 sout_buffer_t *p_data;
352 msg_Dbg( p_mux, "Close" );
354 /* Empty TS buffer */
355 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
357 sout_BufferDelete( p_mux->p_sout, p_data );
363 /*****************************************************************************
365 *****************************************************************************/
366 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
370 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
371 *(vlc_bool_t*)p_answer = VLC_TRUE;
372 return( SOUT_MUX_CAP_ERR_OK );
374 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
378 /*****************************************************************************
379 * AddStream: called for each stream addition
380 *****************************************************************************/
381 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
383 sout_mux_sys_t *p_sys = p_mux->p_sys;
384 ts_stream_t *p_stream;
386 msg_Dbg( p_mux, "adding input codec=%4.4s", (char*)&p_input->p_fmt->i_fourcc );
388 p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
390 /* Init this new stream */
391 p_stream->i_pid = AllocatePID( p_sys );
392 p_stream->i_continuity_counter = 0;
393 p_stream->i_decoder_specific_info = 0;
394 p_stream->p_decoder_specific_info = NULL;
396 /* All others fields depand on codec */
397 switch( p_input->p_fmt->i_cat )
400 switch( p_input->p_fmt->i_fourcc )
402 case VLC_FOURCC( 'm', 'p','g', 'v' ):
403 /* TODO: do we need to check MPEG-I/II ? */
404 p_stream->i_stream_type = 0x02;
405 p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
406 p_sys->i_stream_id_mpgv++;
408 case VLC_FOURCC( 'm', 'p','4', 'v' ):
409 p_stream->i_stream_type = 0x10;
410 p_stream->i_stream_id = 0xfa;
411 p_sys->i_mpeg4_streams++;
412 p_stream->i_es_id = p_stream->i_pid;
414 /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
415 /* I didn't want to do that :P */
416 case VLC_FOURCC( 'H', '2', '6', '3' ):
417 case VLC_FOURCC( 'I', '2', '6', '3' ):
418 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
419 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
420 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
421 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
422 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
423 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
424 p_stream->i_stream_type = 0xa0; // private
425 p_stream->i_stream_id = 0xa0; // beurk
426 p_stream->i_bih_codec = p_input->p_fmt->i_fourcc;
427 p_stream->i_bih_width = p_input->p_fmt->i_width;
428 p_stream->i_bih_height = p_input->p_fmt->i_height;
434 p_sys->i_video_bound++;
438 switch( p_input->p_fmt->i_fourcc )
440 case VLC_FOURCC( 'm', 'p','g', 'a' ):
441 p_stream->i_stream_type = p_input->p_fmt->i_sample_rate >= 32000 ? 0x03 : 0x04;
442 p_stream->i_stream_id = p_sys->i_stream_id_mpga;
443 p_sys->i_stream_id_mpga++;
445 case VLC_FOURCC( 'a', '5','2', ' ' ):
446 p_stream->i_stream_type = 0x81;
447 p_stream->i_stream_id = p_sys->i_stream_id_a52;
448 p_sys->i_stream_id_a52++;
450 case VLC_FOURCC( 'm', 'p','4', 'a' ):
451 p_stream->i_stream_type = 0x11;
452 p_stream->i_stream_id = 0xfa;
453 p_sys->i_mpeg4_streams++;
454 p_stream->i_es_id = p_stream->i_pid;
460 p_sys->i_audio_bound++;
464 switch( p_input->p_fmt->i_fourcc )
466 case VLC_FOURCC( 's', 'p','u', ' ' ):
467 p_stream->i_stream_type = 0x82;
468 p_stream->i_stream_id = 0x82;
481 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
482 p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra_data;
483 if( p_stream->i_decoder_specific_info > 0 )
485 p_stream->p_decoder_specific_info =
486 malloc( p_stream->i_decoder_specific_info );
487 memcpy( p_stream->p_decoder_specific_info,
488 p_input->p_fmt->p_extra_data,
489 p_input->p_fmt->i_extra_data );
491 /* Init chain for TS building */
492 BufferChainInit( &p_stream->chain_ts );
494 /* We only change PMT version (PAT isn't changed) */
495 p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
498 if( p_input->p_fmt->i_cat != SPU_ES &&
499 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
501 sout_buffer_t *p_data;
503 if( p_sys->p_pcr_input )
505 /* There was already a PCR stream, so clean context */
506 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
508 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
510 sout_BufferDelete( p_mux->p_sout, p_data );
513 p_sys->i_pcr_pid = p_stream->i_pid;
514 p_sys->p_pcr_input = p_input;
516 /* Empty TS buffer (avoid broken data/problems with pcr stream changement ) */
517 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
519 sout_BufferDelete( p_mux->p_sout, p_data );
526 /*****************************************************************************
527 * DelStream: called before a stream deletion
528 *****************************************************************************/
529 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
531 sout_mux_sys_t *p_sys = p_mux->p_sys;
532 ts_stream_t *p_stream;
533 sout_buffer_t *p_data;
535 msg_Dbg( p_mux, "removing input" );
536 p_stream = (ts_stream_t*)p_input->p_sys;
538 if( p_sys->i_pcr_pid == p_stream->i_pid )
542 /* Find a new pcr stream (Prefer Video Stream) */
543 p_sys->i_pcr_pid = 0x1fff;
544 p_sys->p_pcr_input = NULL;
545 for( i = 0; i < p_mux->i_nb_inputs; i++ )
547 if( p_mux->pp_inputs[i] == p_input )
552 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
555 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
556 p_sys->p_pcr_input= p_mux->pp_inputs[i];
559 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
560 p_sys->i_pcr_pid == 0x1fff )
563 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
564 p_sys->p_pcr_input= p_mux->pp_inputs[i];
567 if( p_sys->p_pcr_input )
569 /* Empty TS buffer */
570 while( ( p_data = BufferChainGet( &((ts_stream_t*)p_sys->p_pcr_input->p_sys)->chain_ts ) ) )
572 sout_BufferDelete( p_mux->p_sout, p_data );
577 /* Empty all data in chain_ts */
578 while( ( p_data = BufferChainGet( &p_stream->chain_ts ) ) )
580 sout_BufferDelete( p_mux->p_sout, p_data );
582 if( p_stream->p_decoder_specific_info )
584 free( p_stream->p_decoder_specific_info );
586 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
588 p_sys->i_mpeg4_streams--;
592 /* We only change PMT version (PAT isn't changed) */
593 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
595 /*Empty TS buffer (avoid broken data/problems with pcr stream changement) */
596 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
598 sout_BufferDelete( p_mux->p_sout, p_data );
604 /*****************************************************************************
605 * Mux: Call each time there is new data for at least one stream
606 *****************************************************************************
608 *****************************************************************************/
609 static int Mux( sout_mux_t *p_mux )
611 sout_mux_sys_t *p_sys = p_mux->p_sys;
613 sout_input_t *p_pcr_input = p_sys->p_pcr_input;
614 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
616 if( p_sys->i_pcr_pid == 0x1fff )
618 msg_Dbg( p_mux, "waiting PCR streams" );
625 ts_stream_t *p_stream = NULL;
626 sout_buffer_t *p_data;
631 /* fill ts packets for pcr XXX before GetPAT/GetPMT */
632 if( p_pcr_stream->chain_ts.p_first == NULL && TSFill( p_mux, p_pcr_input ) )
634 /* We need more data */
638 if( p_sys->chain_ts.p_first == NULL )
640 /* Every pcr packet send PAT/PMT */
641 GetPAT( p_mux, &p_sys->chain_ts);
642 GetPMT( p_mux, &p_sys->chain_ts );
645 /* search stream with lowest dts */
646 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
648 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
650 if( p_stream->chain_ts.p_first == NULL )
652 if( TSFill( p_mux, p_mux->pp_inputs[i] ) )
654 /* We need more data */
657 if( p_stream->chain_ts.p_first == NULL )
659 continue; /* SPU_ES */
663 if( i_stream == -1 ||
664 p_stream->chain_ts.p_first->i_dts < i_dts )
667 i_dts = p_stream->chain_ts.p_first->i_dts;
671 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
673 p_data = BufferChainGet( &p_stream->chain_ts );
674 BufferChainAppend( &p_sys->chain_ts, p_data );
676 if( p_stream->i_pid == p_pcr_stream->i_pid && p_stream->chain_ts.p_first == NULL )
678 sout_buffer_t *p_ts = p_sys->chain_ts.p_first;
680 /* We have consume all TS packets from the PCR stream */
682 if( p_sys->i_length > p_sys->i_pcr_delay )
684 /* Send TS data if last PCR was i_pcr_delay ago */
686 if( p_sys->i_bitrate_min > 0 ||
687 p_sys->i_bitrate_max > 0 )
689 TSSetConstraints( p_mux, &p_sys->chain_ts, p_sys->i_length,
690 p_sys->i_bitrate_min, p_sys->i_bitrate_max );
694 TSSetDate( &p_sys->chain_ts,
695 p_sys->i_dts + 3 * p_sys->i_pcr_delay / 2, /* latency is equal to i_pcr_delay, 3/2 is for security */
697 sout_AccessOutWrite( p_mux->p_access, p_ts );
699 /* Reset the ts chain */
700 BufferChainInit( &p_sys->chain_ts );
712 /*****************************************************************************
715 *****************************************************************************/
716 static int TSFill( sout_mux_t *p_mux, sout_input_t *p_input )
718 sout_mux_sys_t *p_sys = p_mux->p_sys;
720 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
721 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
722 mtime_t i_dts, i_length;
723 sout_buffer_t *p_data;
724 vlc_bool_t b_pcr = VLC_FALSE;
725 vlc_bool_t b_pcr_soft = VLC_FALSE;
730 if( p_input->p_fifo->i_depth <= 0 )
732 if( p_input->p_fmt->i_cat == AUDIO_ES ||
733 p_input->p_fmt->i_cat == VIDEO_ES )
735 /* We need more data */
743 p_data = sout_FifoGet( p_input->p_fifo );
744 i_dts = p_data->i_dts;
745 i_length = p_data->i_length;
747 if( p_stream->i_pid == p_pcr_stream->i_pid &&
748 p_stream->chain_ts.p_first == NULL )
750 p_sys->i_length+= i_length;
751 if( p_sys->chain_ts.p_first == NULL )
753 p_sys->i_dts = i_dts;
754 p_sys->i_pcr = i_dts;
757 else if( p_sys->i_pcr_soft_delay > 0 &&
758 p_sys->i_pcr + p_sys->i_pcr_soft_delay < i_dts )
760 p_sys->i_pcr = i_dts;
762 b_pcr_soft = VLC_TRUE;
767 if( ( p_sys->i_dts +p_sys->i_length ) - i_dts > 2000000 ||
768 ( p_sys->i_dts + p_sys->i_length ) - i_dts < -2000000 )
770 msg_Err( p_mux, "| buffer_dts - pcr_pts | > 2s empting pcr TS buffers" );
772 sout_BufferDelete( p_mux->p_sout, p_data );
774 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
776 sout_BufferDelete( p_mux->p_sout, p_data );
778 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
780 sout_BufferDelete( p_mux->p_sout, p_data );
785 if( i_dts >= p_sys->i_dts )
791 "dropping buffer size=%d dts=%lld pcr_dts=%lld",
792 p_data->i_size, i_dts, p_sys->i_dts );
793 sout_BufferDelete( p_mux->p_sout, p_data );
796 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
798 BufferChainInit( &p_stream->chain_ts );
799 PEStoTS( p_mux->p_sout, &p_stream->chain_ts, p_data, p_stream, b_pcr );
801 TSSetDate( &p_stream->chain_ts, i_dts, i_length );
803 if( b_pcr_soft && p_stream->chain_ts.p_first )
805 p_stream->chain_ts.p_first->i_flags=SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT;
811 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 )
813 sout_mux_sys_t *p_sys = p_mux->p_sys;
814 sout_buffer_chain_t s = *c;
817 int i_packets_min = 0;
818 int i_packets_max = 0;
825 i_packets = c->i_depth;
826 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
827 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
829 if( i_packets < i_packets_min && i_packets_min > 0 )
832 int i_div = ( i_packets_min - i_packets ) / i_packets;
833 int i_mod = ( i_packets_min - i_packets ) % i_packets;
836 /* We need to pad with null packets (pid=0x1fff)
837 * We try to melt null packets with true packets */
839 "packets=%d but min=%d -> adding %d packets of padding",
840 i_packets, i_packets_min, i_packets_min - i_packets );
842 BufferChainInit( c );
843 while( ( p_pk = BufferChainGet( &s ) ) )
847 BufferChainAppend( c, p_pk );
849 i_null = i_div + ( i_rest + i_mod ) / i_packets;
851 for( i = 0; i < i_null; i++ )
853 sout_buffer_t *p_null;
855 p_null = sout_BufferNew( p_mux->p_sout, 188 );
856 p_null->p_buffer[0] = 0x47;
857 p_null->p_buffer[1] = 0x1f;
858 p_null->p_buffer[2] = 0xff;
859 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
860 memset( &p_null->p_buffer[4], 0, 184 );
861 p_sys->i_null_continuity_counter =
862 ( p_sys->i_null_continuity_counter + 1 ) % 16;
864 BufferChainAppend( c, p_null );
867 i_rest = ( i_rest + i_mod ) % i_packets;
870 else if( i_packets > i_packets_max && i_packets_max > 0 )
875 /* Arg, we need to drop packets, I don't do something clever (like
876 * dropping complete pid, b frames, ... ), I just get the right amount
877 * of packets and discard the others */
879 "packets=%d but max=%d -> removing %d packets -> stream broken",
880 i_packets, i_packets_max, i_packets - i_packets_max );
882 BufferChainInit( c );
883 for( i = 0; i < i_packets_max; i++ )
885 BufferChainAppend( c, BufferChainGet( &s ) );
888 while( ( p_pk = BufferChainGet( &s ) ) )
890 sout_BufferDelete( p_mux->p_sout, p_pk );
895 static void TSSetDate( sout_buffer_chain_t *c, mtime_t i_dts, mtime_t i_length )
898 mtime_t i_delta = i_length / c->i_depth;
901 for( p_ts = c->p_first; p_ts != NULL; p_ts = p_ts->p_next )
903 p_ts->i_dts = i_dts + i_packet * i_length / c->i_depth; /* avoid rounding error */
904 p_ts->i_length = i_delta;
906 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT )
908 mtime_t i_pcr = 9 * p_ts->i_dts / 100;
910 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
911 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
912 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
913 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
914 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
921 static void PEStoTS( sout_instance_t *p_sout,
922 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
923 ts_stream_t *p_stream,
930 /* get PES total size */
931 i_size = p_pes->i_size;
932 p_data = p_pes->p_buffer;
934 /* Set pcr only with valid DTS */
935 if( p_pes->i_dts <= 0 )
940 b_new_pes = VLC_TRUE;
944 int b_adaptation_field;
949 p_ts = sout_BufferNew( p_sout, 188 );
952 * 1b transport_error_indicator
953 * 1b payload_unit_start
954 * 1b transport_priority
956 * 2b transport_scrambling_control
957 * 2b if adaptation_field 0x03 else 0x01
958 * 4b continuity_counter
961 i_payload = 184 - ( b_pcr ? 8 : 0 );
962 i_copy = __MIN( i_size, i_payload );
963 b_adaptation_field = (b_pcr||i_size<i_payload) ? VLC_TRUE : VLC_FALSE;
965 p_ts->p_buffer[0] = 0x47;
966 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
967 ( ( p_stream->i_pid >> 8 )&0x1f );
968 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
969 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
970 p_stream->i_continuity_counter;
972 b_new_pes = VLC_FALSE;
973 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
975 if( b_adaptation_field )
981 mtime_t i_pcr = p_pes->i_dts * 9 / 100;
982 int i_stuffing = i_payload - i_copy;
984 p_ts->p_buffer[4] = 7 + i_stuffing;
985 p_ts->p_buffer[5] = 0x10; /* flags */
986 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
987 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
988 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
989 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
990 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
991 p_ts->p_buffer[11]= 0;
994 for( i = 12; i < 12 + i_stuffing; i++ )
996 p_ts->p_buffer[i] = 0xff;
1001 int i_stuffing = i_payload - i_copy;
1003 p_ts->p_buffer[4] = i_stuffing - 1;
1004 if( i_stuffing > 1 )
1006 p_ts->p_buffer[5] = 0x00;
1007 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1009 p_ts->p_buffer[i] = 0xff;
1015 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1019 BufferChainAppend( c, p_ts );
1023 sout_buffer_t *p_next = p_pes->p_next;
1025 p_pes->p_next = NULL;
1026 sout_BufferDelete( p_sout, p_pes );
1027 if( p_next == NULL )
1031 b_new_pes = VLC_TRUE;
1033 i_size = p_pes->i_size;
1034 p_data = p_pes->p_buffer;
1041 #if defined MODULE_NAME_IS_mux_ts
1042 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1044 static uint32_t CRC32[256] =
1046 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1047 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1048 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1049 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1050 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1051 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1052 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1053 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1054 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1055 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1056 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1057 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1058 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1059 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1060 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1061 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1062 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1063 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1064 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1065 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1066 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1067 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1068 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1069 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1070 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1071 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1072 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1073 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1074 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1075 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1076 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1077 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1078 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1079 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1080 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1081 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1082 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1083 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1084 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1085 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1086 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1087 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1088 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1089 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1090 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1091 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1092 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1093 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1094 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1095 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1096 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1097 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1098 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1099 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1100 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1101 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1102 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1103 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1104 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1105 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1106 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1107 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1108 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1109 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1112 uint32_t i_crc = 0xffffffff;
1114 /* Calculate the CRC */
1115 while( i_count > 0 )
1117 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1125 static void GetPAT( sout_mux_t *p_mux,
1126 sout_buffer_chain_t *c )
1128 sout_mux_sys_t *p_sys = p_mux->p_sys;
1129 sout_buffer_t *p_pat;
1132 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1136 p_pat->i_length = 0;
1138 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1140 bits_write( &bits, 8, 0 ); // pointer
1141 bits_write( &bits, 8, 0x00 ); // table id
1142 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1143 bits_write( &bits, 1, 0 ); // 0
1144 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1145 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1146 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1147 bits_write( &bits, 2, 0x03 ); // FIXME
1148 bits_write( &bits, 5, p_sys->i_pat_version_number );
1149 bits_write( &bits, 1, 1 ); // current_next_indicator
1150 bits_write( &bits, 8, 0 ); // section number
1151 bits_write( &bits, 8, 0 ); // last section number
1153 bits_write( &bits, 16, 1 ); // program number
1154 bits_write( &bits, 3, 0x07 ); // reserved
1155 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1157 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1159 p_pat->i_size = bits.i_data;
1161 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1164 static void GetPMT( sout_mux_t *p_mux,
1165 sout_buffer_chain_t *c )
1167 sout_mux_sys_t *p_sys = p_mux->p_sys;
1168 sout_buffer_t *p_pmt;
1172 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1176 p_pmt->i_length = 0;
1178 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1180 bits_write( &bits, 8, 0 ); // pointer
1181 bits_write( &bits, 8, 0x02 ); // table id
1182 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1183 bits_write( &bits, 1, 0 ); // 0
1184 bits_write( &bits, 2, 0 ); // reserved FIXME
1185 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1186 bits_write( &bits, 16, 1 ); // FIXME program number
1187 bits_write( &bits, 2, 0 ); // FIXME
1188 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1189 bits_write( &bits, 1, 1 ); // current_next_indicator
1190 bits_write( &bits, 8, 0 ); // section number
1191 bits_write( &bits, 8, 0 ); // last section number
1193 bits_write( &bits, 3, 0 ); // reserved
1195 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1196 bits_write( &bits, 4, 0 ); // reserved FIXME
1198 bits_write( &bits, 12, 0 ); // program info len FIXME
1200 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1202 ts_stream_t *p_stream;
1204 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1206 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1207 bits_write( &bits, 3, 0 ); // reserved
1208 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1209 bits_write( &bits, 4, 0 ); //reserved
1210 bits_write( &bits, 12, 0 ); // es info len FIXME
1213 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1215 p_pmt->i_size = bits.i_data;
1217 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1219 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1221 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1222 dvbpsi_psi_section_t* p_section )
1224 sout_buffer_t *p_psi, *p_first = NULL;
1231 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1232 ( p_section->b_syntax_indicator ? 4 : 0 );
1234 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1237 p_psi->i_length = 0;
1238 p_psi->i_size = i_size + 1;
1240 p_psi->p_buffer[0] = 0; // pointer
1241 memcpy( p_psi->p_buffer + 1,
1245 sout_BufferChain( &p_first, p_psi );
1247 p_section = p_section->p_next;
1253 static void GetPAT( sout_mux_t *p_mux,
1254 sout_buffer_chain_t *c )
1256 sout_mux_sys_t *p_sys = p_mux->p_sys;
1257 sout_buffer_t *p_pat;
1259 dvbpsi_psi_section_t *p_section;
1261 dvbpsi_InitPAT( &pat,
1263 p_sys->i_pat_version_number,
1264 1 ); // b_current_next
1265 /* add all program (only one) */
1266 dvbpsi_PATAddProgram( &pat,
1268 p_sys->pmt.i_pid ); // i_pid
1270 p_section = dvbpsi_GenPATSections( &pat,
1271 0 ); // max program per section
1273 p_pat = WritePSISection( p_mux->p_sout, p_section );
1275 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1277 dvbpsi_DeletePSISections( p_section );
1278 dvbpsi_EmptyPAT( &pat );
1281 static uint32_t GetDescriptorLength24b( int i_length )
1283 uint32_t i_l1, i_l2, i_l3;
1285 i_l1 = i_length&0x7f;
1286 i_l2 = ( i_length >> 7 )&0x7f;
1287 i_l3 = ( i_length >> 14 )&0x7f;
1289 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1292 static void GetPMT( sout_mux_t *p_mux,
1293 sout_buffer_chain_t *c )
1295 sout_mux_sys_t *p_sys = p_mux->p_sys;
1296 sout_buffer_t *p_pmt;
1299 dvbpsi_pmt_es_t *p_es;
1300 dvbpsi_psi_section_t *p_section;
1304 dvbpsi_InitPMT( &pmt,
1305 0x01, // program number
1306 p_sys->i_pmt_version_number,
1307 1, // b_current_next
1310 if( p_sys->i_mpeg4_streams > 0 )
1314 bits_buffer_t bits_fix_IOD;
1316 bits_initwrite( &bits, 4096, iod );
1318 bits_write( &bits, 8, 0x01 );
1319 // InitialObjectDescriptor
1320 bits_align( &bits );
1321 bits_write( &bits, 8, 0x02 ); // tag
1322 bits_fix_IOD = bits; // save states to fix length later
1323 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1324 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1325 bits_write( &bits, 1, 0x00 ); // URL Flag
1326 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1327 bits_write( &bits, 4, 0x0f ); // reserved
1328 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1329 bits_write( &bits, 8, 0xff ); // sceneProfile
1330 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1331 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1332 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1333 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1335 ts_stream_t *p_stream;
1336 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1338 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1340 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1342 bits_align( &bits );
1343 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1344 bits_fix_ESDescr = bits;
1345 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1346 bits_write( &bits, 16, p_stream->i_es_id );
1347 bits_write( &bits, 1, 0x00 ); // streamDependency
1348 bits_write( &bits, 1, 0x00 ); // URL Flag
1349 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1350 bits_write( &bits, 5, 0x1f ); // streamPriority
1352 // DecoderConfigDesciptor
1353 bits_align( &bits );
1354 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1355 bits_fix_Decoder = bits;
1356 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1357 if( p_stream->i_stream_type == 0x10 )
1359 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1360 bits_write( &bits, 6, 0x04 ); // VisualStream
1362 else if( p_stream->i_stream_type == 0x11 )
1364 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1365 bits_write( &bits, 6, 0x05 ); // AudioStream
1369 bits_write( &bits, 8, 0x00 );
1370 bits_write( &bits, 6, 0x00 );
1372 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1374 bits_write( &bits, 1, 0x00 ); // UpStream
1375 bits_write( &bits, 1, 0x01 ); // reserved
1376 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1377 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1378 bits_write( &bits, 32, 0 ); // avgBitrate
1380 if( p_stream->i_decoder_specific_info > 0 )
1383 // DecoderSpecificInfo
1384 bits_align( &bits );
1385 bits_write( &bits, 8, 0x05 ); // tag
1386 bits_write( &bits, 24,
1387 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1388 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1390 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1393 /* fix Decoder length */
1394 bits_write( &bits_fix_Decoder, 24,
1395 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1397 /* SLConfigDescriptor : predifined (0x01) */
1398 bits_align( &bits );
1399 bits_write( &bits, 8, 0x06 ); // tag
1400 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1401 bits_write( &bits, 8, 0x01 ); // predefined
1402 bits_write( &bits, 1, 0 ); // durationFlag
1403 bits_write( &bits, 32, 0 ); // OCRResolution
1404 bits_write( &bits, 8, 0 ); // OCRLength
1405 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1406 bits_align( &bits );
1408 /* fix ESDescr length */
1409 bits_write( &bits_fix_ESDescr, 24,
1410 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1413 bits_align( &bits );
1414 /* fix IOD length */
1415 bits_write( &bits_fix_IOD, 24,
1416 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1417 dvbpsi_PMTAddDescriptor( &pmt,
1423 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1425 ts_stream_t *p_stream;
1427 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1429 p_es = dvbpsi_PMTAddES( &pmt,
1430 p_stream->i_stream_type,
1432 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1438 bits_initwrite( &bits, 512, data );
1439 bits_write( &bits, 16, p_stream->i_es_id );
1441 dvbpsi_PMTESAddDescriptor( p_es,
1446 else if( p_stream->i_stream_id == 0xa0 )
1452 memcpy( fcc, &p_stream->i_bih_codec, 4 );
1454 /* private DIV3 descripor */
1455 bits_initwrite( &bits, 512, data );
1456 bits_write( &bits, 8, fcc[0]);
1457 bits_write( &bits, 8, fcc[1]);
1458 bits_write( &bits, 8, fcc[2]);
1459 bits_write( &bits, 8, fcc[3]);
1460 bits_write( &bits, 16, p_stream->i_bih_width );
1461 bits_write( &bits, 16, p_stream->i_bih_height );
1462 bits_write( &bits, 16, p_stream->i_decoder_specific_info );
1463 if( p_stream->i_decoder_specific_info > 0 )
1466 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1468 bits_write( &bits, 8, p_stream->p_decoder_specific_info[i] );
1471 dvbpsi_PMTESAddDescriptor( p_es,
1478 p_section = dvbpsi_GenPMTSections( &pmt );
1480 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1482 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1484 dvbpsi_DeletePSISections( p_section );
1485 dvbpsi_EmptyPMT( &pmt );