1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.27 2003/08/14 11:47:32 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 /*****************************************************************************
223 *****************************************************************************/
224 static int Open( vlc_object_t *p_this )
226 sout_mux_t *p_mux =(sout_mux_t*)p_this;
227 sout_mux_sys_t *p_sys;
230 msg_Dbg( p_mux, "Open" );
232 p_sys = malloc( sizeof( sout_mux_sys_t ) );
234 p_mux->pf_capacity = Capability;
235 p_mux->pf_addstream = AddStream;
236 p_mux->pf_delstream = DelStream;
238 p_mux->p_sys = p_sys;
239 p_mux->i_preheader = 30; // really enough for a pes header
241 srand( (uint32_t)mdate() );
243 p_sys->i_stream_id_mpga = 0xc0;
244 p_sys->i_stream_id_a52 = 0x80;
245 p_sys->i_stream_id_mpgv = 0xe0;
247 p_sys->i_audio_bound = 0;
248 p_sys->i_video_bound = 0;
250 p_sys->i_pat_version_number = rand() % 32;
251 p_sys->pat.i_pid = 0;
252 p_sys->pat.i_continuity_counter = 0;
254 p_sys->i_pmt_version_number = rand() % 32;
255 p_sys->pmt.i_pid = 0x42;
256 p_sys->pmt.i_continuity_counter = 0;
258 p_sys->i_pid_free = 0x43;
260 p_sys->i_pcr_pid = 0x1fff;
261 p_sys->p_pcr_input = NULL;
263 p_sys->i_mpeg4_streams = 0;
265 p_sys->i_null_continuity_counter = 0;
267 /* Allow to create constrained stream */
268 p_sys->i_bitrate_min = 0;
269 p_sys->i_bitrate_max = 0;
270 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmin" ) ) )
272 p_sys->i_bitrate_min = atoll( val );
274 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmax" ) ) )
276 p_sys->i_bitrate_max = atoll( val );
278 if( p_sys->i_bitrate_min > 0 && p_sys->i_bitrate_max > 0 &&
279 p_sys->i_bitrate_min > p_sys->i_bitrate_max )
281 msg_Err( p_mux, "incompatible minimum and maximum bitrate, "
282 "disabling bitrate control" );
283 p_sys->i_bitrate_min = 0;
284 p_sys->i_bitrate_max = 0;
286 p_sys->i_pcr_delay = 100000;
287 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr" ) ) )
289 p_sys->i_pcr_delay = (int64_t)atoi( val ) * 1000;
290 if( p_sys->i_pcr_delay <= 0 )
293 "invalid pcr delay ("I64Fd"ms) reseting to 100ms",
294 p_sys->i_pcr_delay / 1000 );
295 p_sys->i_pcr_delay = 100000;
298 p_sys->i_pcr_soft_delay = 0;
299 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr-soft" ) ) )
301 p_sys->i_pcr_soft_delay = (int64_t)atoi( val ) * 1000;
302 if( p_sys->i_pcr_soft_delay <= 0 ||
303 p_sys->i_pcr_soft_delay >= p_sys->i_pcr_delay )
306 "invalid pcr-soft delay ("I64Fd"ms) disabled",
307 p_sys->i_pcr_soft_delay / 1000 );
308 p_sys->i_pcr_soft_delay = 0;
312 msg_Dbg( p_mux, "pcr_delay="I64Fd" pcr_soft_delay="I64Fd,
313 p_sys->i_pcr_delay, p_sys->i_pcr_soft_delay );
315 /* for TS génération */
319 BufferChainInit( &p_sys->chain_ts );
323 /*****************************************************************************
325 *****************************************************************************/
326 static void Close( vlc_object_t * p_this )
328 sout_mux_t *p_mux = (sout_mux_t*)p_this;
329 sout_mux_sys_t *p_sys = p_mux->p_sys;
330 sout_buffer_t *p_data;
332 msg_Dbg( p_mux, "Close" );
334 /* Empty TS buffer */
335 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
337 sout_BufferDelete( p_mux->p_sout, p_data );
343 /*****************************************************************************
345 *****************************************************************************/
346 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
350 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
351 *(vlc_bool_t*)p_answer = VLC_TRUE;
352 return( SOUT_MUX_CAP_ERR_OK );
354 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
358 /*****************************************************************************
359 * AddStream: called for each stream addition
360 *****************************************************************************/
361 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
363 sout_mux_sys_t *p_sys = p_mux->p_sys;
364 ts_stream_t *p_stream;
366 msg_Dbg( p_mux, "adding input codec=%4.4s", (char*)&p_input->p_fmt->i_fourcc );
368 p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
370 /* Init this new stream */
371 p_stream->i_pid = AllocatePID( p_sys );
372 p_stream->i_continuity_counter = 0;
373 p_stream->i_decoder_specific_info = 0;
374 p_stream->p_decoder_specific_info = NULL;
376 /* All others fields depand on codec */
377 switch( p_input->p_fmt->i_cat )
380 switch( p_input->p_fmt->i_fourcc )
382 case VLC_FOURCC( 'm', 'p','g', 'v' ):
383 /* TODO: do we need to check MPEG-I/II ? */
384 p_stream->i_stream_type = 0x02;
385 p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
386 p_sys->i_stream_id_mpgv++;
388 case VLC_FOURCC( 'm', 'p','4', 'v' ):
389 p_stream->i_stream_type = 0x10;
390 p_stream->i_stream_id = 0xfa;
391 p_sys->i_mpeg4_streams++;
392 p_stream->i_es_id = p_stream->i_pid;
394 /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
395 /* I didn't want to do that :P */
396 case VLC_FOURCC( 'H', '2', '6', '3' ):
397 case VLC_FOURCC( 'I', '2', '6', '3' ):
398 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
399 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
400 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
401 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
402 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
403 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
404 p_stream->i_stream_type = 0xa0; // private
405 p_stream->i_stream_id = 0xa0; // beurk
406 p_stream->i_bih_codec = p_input->p_fmt->i_fourcc;
407 p_stream->i_bih_width = p_input->p_fmt->i_width;
408 p_stream->i_bih_height = p_input->p_fmt->i_height;
414 p_sys->i_video_bound++;
418 switch( p_input->p_fmt->i_fourcc )
420 case VLC_FOURCC( 'm', 'p','g', 'a' ):
421 p_stream->i_stream_type = p_input->p_fmt->i_sample_rate >= 32000 ? 0x03 : 0x04;
422 p_stream->i_stream_id = p_sys->i_stream_id_mpga;
423 p_sys->i_stream_id_mpga++;
425 case VLC_FOURCC( 'a', '5','2', ' ' ):
426 p_stream->i_stream_type = 0x81;
427 p_stream->i_stream_id = p_sys->i_stream_id_a52;
428 p_sys->i_stream_id_a52++;
430 case VLC_FOURCC( 'm', 'p','4', 'a' ):
431 p_stream->i_stream_type = 0x11;
432 p_stream->i_stream_id = 0xfa;
433 p_sys->i_mpeg4_streams++;
434 p_stream->i_es_id = p_stream->i_pid;
440 p_sys->i_audio_bound++;
444 switch( p_input->p_fmt->i_fourcc )
446 case VLC_FOURCC( 's', 'p','u', ' ' ):
447 p_stream->i_stream_type = 0x82;
448 p_stream->i_stream_id = 0x82;
461 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
462 p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra_data;
463 if( p_stream->i_decoder_specific_info > 0 )
465 p_stream->p_decoder_specific_info =
466 malloc( p_stream->i_decoder_specific_info );
467 memcpy( p_stream->p_decoder_specific_info,
468 p_input->p_fmt->p_extra_data,
469 p_input->p_fmt->i_extra_data );
471 /* Init chain for TS building */
472 BufferChainInit( &p_stream->chain_ts );
474 /* We only change PMT version (PAT isn't changed) */
475 p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
478 if( p_input->p_fmt->i_cat != SPU_ES &&
479 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
481 sout_buffer_t *p_data;
483 if( p_sys->p_pcr_input )
485 /* There was already a PCR stream, so clean context */
486 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
488 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
490 sout_BufferDelete( p_mux->p_sout, p_data );
493 p_sys->i_pcr_pid = p_stream->i_pid;
494 p_sys->p_pcr_input = p_input;
496 /* Empty TS buffer (avoid broken data/problems with pcr stream changement ) */
497 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
499 sout_BufferDelete( p_mux->p_sout, p_data );
506 /*****************************************************************************
507 * DelStream: called before a stream deletion
508 *****************************************************************************/
509 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
511 sout_mux_sys_t *p_sys = p_mux->p_sys;
512 ts_stream_t *p_stream;
513 sout_buffer_t *p_data;
515 msg_Dbg( p_mux, "removing input" );
516 p_stream = (ts_stream_t*)p_input->p_sys;
518 if( p_sys->i_pcr_pid == p_stream->i_pid )
522 /* Find a new pcr stream (Prefer Video Stream) */
523 p_sys->i_pcr_pid = 0x1fff;
524 p_sys->p_pcr_input = NULL;
525 for( i = 0; i < p_mux->i_nb_inputs; i++ )
527 if( p_mux->pp_inputs[i] == p_input )
532 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
535 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
536 p_sys->p_pcr_input= p_mux->pp_inputs[i];
539 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
540 p_sys->i_pcr_pid == 0x1fff )
543 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
544 p_sys->p_pcr_input= p_mux->pp_inputs[i];
547 if( p_sys->p_pcr_input )
549 /* Empty TS buffer */
550 while( ( p_data = BufferChainGet( &((ts_stream_t*)p_sys->p_pcr_input->p_sys)->chain_ts ) ) )
552 sout_BufferDelete( p_mux->p_sout, p_data );
557 /* Empty all data in chain_ts */
558 while( ( p_data = BufferChainGet( &p_stream->chain_ts ) ) )
560 sout_BufferDelete( p_mux->p_sout, p_data );
562 if( p_stream->p_decoder_specific_info )
564 free( p_stream->p_decoder_specific_info );
566 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
568 p_sys->i_mpeg4_streams--;
572 /* We only change PMT version (PAT isn't changed) */
573 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
575 /*Empty TS buffer (avoid broken data/problems with pcr stream changement) */
576 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
578 sout_BufferDelete( p_mux->p_sout, p_data );
584 /*****************************************************************************
585 * Mux: Call each time there is new data for at least one stream
586 *****************************************************************************
588 *****************************************************************************/
589 static int Mux( sout_mux_t *p_mux )
591 sout_mux_sys_t *p_sys = p_mux->p_sys;
593 sout_input_t *p_pcr_input = p_sys->p_pcr_input;
594 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
596 if( p_sys->i_pcr_pid == 0x1fff )
598 msg_Dbg( p_mux, "waiting PCR streams" );
605 ts_stream_t *p_stream = NULL;
606 sout_buffer_t *p_data;
611 /* fill ts packets for pcr XXX before GetPAT/GetPMT */
612 if( p_pcr_stream->chain_ts.p_first == NULL && TSFill( p_mux, p_pcr_input ) )
614 /* We need more data */
618 if( p_sys->chain_ts.p_first == NULL )
620 /* Every pcr packet send PAT/PMT */
621 GetPAT( p_mux, &p_sys->chain_ts);
622 GetPMT( p_mux, &p_sys->chain_ts );
625 /* search stream with lowest dts */
626 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
628 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
630 if( p_stream->chain_ts.p_first == NULL )
632 if( TSFill( p_mux, p_mux->pp_inputs[i] ) )
634 /* We need more data */
637 if( p_stream->chain_ts.p_first == NULL )
639 continue; /* SPU_ES */
643 if( i_stream == -1 ||
644 p_stream->chain_ts.p_first->i_dts < i_dts )
647 i_dts = p_stream->chain_ts.p_first->i_dts;
651 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
653 p_data = BufferChainGet( &p_stream->chain_ts );
654 BufferChainAppend( &p_sys->chain_ts, p_data );
656 if( p_stream->i_pid == p_pcr_stream->i_pid && p_stream->chain_ts.p_first == NULL )
658 sout_buffer_t *p_ts = p_sys->chain_ts.p_first;
660 /* We have consume all TS packets from the PCR stream */
662 if( p_sys->i_length > p_sys->i_pcr_delay )
664 /* Send TS data if last PCR was i_pcr_delay ago */
666 if( p_sys->i_bitrate_min > 0 ||
667 p_sys->i_bitrate_max > 0 )
669 TSSetConstraints( p_mux, &p_sys->chain_ts, p_sys->i_length,
670 p_sys->i_bitrate_min, p_sys->i_bitrate_max );
674 TSSetDate( &p_sys->chain_ts,
675 p_sys->i_dts + 3 * p_sys->i_pcr_delay / 2, /* latency is equal to i_pcr_delay, 3/2 is for security */
677 sout_AccessOutWrite( p_mux->p_access, p_ts );
679 /* Reset the ts chain */
680 BufferChainInit( &p_sys->chain_ts );
692 /*****************************************************************************
695 *****************************************************************************/
696 static int TSFill( sout_mux_t *p_mux, sout_input_t *p_input )
698 sout_mux_sys_t *p_sys = p_mux->p_sys;
700 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
701 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
702 mtime_t i_dts, i_length;
703 sout_buffer_t *p_data;
704 vlc_bool_t b_pcr = VLC_FALSE;
705 vlc_bool_t b_pcr_soft = VLC_FALSE;
710 if( p_input->p_fifo->i_depth <= 0 )
712 if( p_input->p_fmt->i_cat == AUDIO_ES ||
713 p_input->p_fmt->i_cat == VIDEO_ES )
715 /* We need more data */
723 p_data = sout_FifoGet( p_input->p_fifo );
724 i_dts = p_data->i_dts;
725 i_length = p_data->i_length;
727 if( p_stream->i_pid == p_pcr_stream->i_pid &&
728 p_stream->chain_ts.p_first == NULL )
730 p_sys->i_length+= i_length;
731 if( p_sys->chain_ts.p_first == NULL )
733 p_sys->i_dts = i_dts;
734 p_sys->i_pcr = i_dts;
737 else if( p_sys->i_pcr_soft_delay > 0 &&
738 p_sys->i_pcr + p_sys->i_pcr_soft_delay < i_dts )
740 p_sys->i_pcr = i_dts;
742 b_pcr_soft = VLC_TRUE;
747 if( ( p_sys->i_dts + p_sys->i_length ) - i_dts > 2000000 ||
748 ( p_sys->i_dts + p_sys->i_length ) - i_dts < -2000000 )
750 msg_Err( p_mux, "| buffer_dts - pcr_pts | > 2s ("I64Fd") empting "
751 "pcr TS buffers", p_sys->i_dts + p_sys->i_length - i_dts);
753 sout_BufferDelete( p_mux->p_sout, p_data );
755 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
757 sout_BufferDelete( p_mux->p_sout, p_data );
759 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
761 sout_BufferDelete( p_mux->p_sout, p_data );
766 if( i_dts >= p_sys->i_dts )
771 msg_Dbg( p_mux, "dropping buffer size=%d dts="I64Fd" pcr_dts="I64Fd
772 " diff="I64Fd, p_data->i_size, i_dts, p_sys->i_dts,
773 p_sys->i_dts + p_sys->i_length - i_dts );
774 sout_BufferDelete( p_mux->p_sout, p_data );
777 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
779 BufferChainInit( &p_stream->chain_ts );
780 PEStoTS( p_mux->p_sout, &p_stream->chain_ts, p_data, p_stream, b_pcr );
782 TSSetDate( &p_stream->chain_ts, i_dts, i_length );
784 if( b_pcr_soft && p_stream->chain_ts.p_first )
786 p_stream->chain_ts.p_first->i_flags=SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT;
792 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 )
794 sout_mux_sys_t *p_sys = p_mux->p_sys;
795 sout_buffer_chain_t s = *c;
798 int i_packets_min = 0;
799 int i_packets_max = 0;
806 i_packets = c->i_depth;
807 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
808 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
810 if( i_packets < i_packets_min && i_packets_min > 0 )
813 int i_div = ( i_packets_min - i_packets ) / i_packets;
814 int i_mod = ( i_packets_min - i_packets ) % i_packets;
817 /* We need to pad with null packets (pid=0x1fff)
818 * We try to melt null packets with true packets */
820 "packets=%d but min=%d -> adding %d packets of padding",
821 i_packets, i_packets_min, i_packets_min - i_packets );
823 BufferChainInit( c );
824 while( ( p_pk = BufferChainGet( &s ) ) )
828 BufferChainAppend( c, p_pk );
830 i_null = i_div + ( i_rest + i_mod ) / i_packets;
832 for( i = 0; i < i_null; i++ )
834 sout_buffer_t *p_null;
836 p_null = sout_BufferNew( p_mux->p_sout, 188 );
837 p_null->p_buffer[0] = 0x47;
838 p_null->p_buffer[1] = 0x1f;
839 p_null->p_buffer[2] = 0xff;
840 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
841 memset( &p_null->p_buffer[4], 0, 184 );
842 p_sys->i_null_continuity_counter =
843 ( p_sys->i_null_continuity_counter + 1 ) % 16;
845 BufferChainAppend( c, p_null );
848 i_rest = ( i_rest + i_mod ) % i_packets;
851 else if( i_packets > i_packets_max && i_packets_max > 0 )
856 /* Arg, we need to drop packets, I don't do something clever (like
857 * dropping complete pid, b frames, ... ), I just get the right amount
858 * of packets and discard the others */
860 "packets=%d but max=%d -> removing %d packets -> stream broken",
861 i_packets, i_packets_max, i_packets - i_packets_max );
863 BufferChainInit( c );
864 for( i = 0; i < i_packets_max; i++ )
866 BufferChainAppend( c, BufferChainGet( &s ) );
869 while( ( p_pk = BufferChainGet( &s ) ) )
871 sout_BufferDelete( p_mux->p_sout, p_pk );
876 static void TSSetDate( sout_buffer_chain_t *c, mtime_t i_dts, mtime_t i_length )
879 mtime_t i_delta = i_length / c->i_depth;
882 for( p_ts = c->p_first; p_ts != NULL; p_ts = p_ts->p_next )
884 p_ts->i_dts = i_dts + i_packet * i_length / c->i_depth; /* avoid rounding error */
885 p_ts->i_length = i_delta;
887 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT )
889 mtime_t i_pcr = 9 * p_ts->i_dts / 100;
891 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
892 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
893 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
894 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
895 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
902 static void PEStoTS( sout_instance_t *p_sout,
903 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
904 ts_stream_t *p_stream,
911 /* get PES total size */
912 i_size = p_pes->i_size;
913 p_data = p_pes->p_buffer;
915 /* Set pcr only with valid DTS */
916 if( p_pes->i_dts <= 0 )
921 b_new_pes = VLC_TRUE;
925 int b_adaptation_field;
930 p_ts = sout_BufferNew( p_sout, 188 );
933 * 1b transport_error_indicator
934 * 1b payload_unit_start
935 * 1b transport_priority
937 * 2b transport_scrambling_control
938 * 2b if adaptation_field 0x03 else 0x01
939 * 4b continuity_counter
942 i_payload = 184 - ( b_pcr ? 8 : 0 );
943 i_copy = __MIN( i_size, i_payload );
944 b_adaptation_field = (b_pcr||i_size<i_payload) ? VLC_TRUE : VLC_FALSE;
946 p_ts->p_buffer[0] = 0x47;
947 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
948 ( ( p_stream->i_pid >> 8 )&0x1f );
949 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
950 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
951 p_stream->i_continuity_counter;
953 b_new_pes = VLC_FALSE;
954 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
956 if( b_adaptation_field )
962 mtime_t i_pcr = p_pes->i_dts * 9 / 100;
963 int i_stuffing = i_payload - i_copy;
965 p_ts->p_buffer[4] = 7 + i_stuffing;
966 p_ts->p_buffer[5] = 0x10; /* flags */
967 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
968 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
969 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
970 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
971 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
972 p_ts->p_buffer[11]= 0;
975 for( i = 12; i < 12 + i_stuffing; i++ )
977 p_ts->p_buffer[i] = 0xff;
982 int i_stuffing = i_payload - i_copy;
984 p_ts->p_buffer[4] = i_stuffing - 1;
987 p_ts->p_buffer[5] = 0x00;
988 for( i = 6; i < 6 + i_stuffing - 2; i++ )
990 p_ts->p_buffer[i] = 0xff;
996 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1000 BufferChainAppend( c, p_ts );
1004 sout_buffer_t *p_next = p_pes->p_next;
1006 p_pes->p_next = NULL;
1007 sout_BufferDelete( p_sout, p_pes );
1008 if( p_next == NULL )
1012 b_new_pes = VLC_TRUE;
1014 i_size = p_pes->i_size;
1015 p_data = p_pes->p_buffer;
1022 #if defined MODULE_NAME_IS_mux_ts
1023 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1025 static uint32_t CRC32[256] =
1027 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1028 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1029 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1030 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1031 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1032 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1033 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1034 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1035 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1036 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1037 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1038 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1039 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1040 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1041 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1042 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1043 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1044 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1045 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1046 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1047 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1048 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1049 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1050 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1051 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1052 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1053 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1054 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1055 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1056 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1057 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1058 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1059 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1060 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1061 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1062 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1063 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1064 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1065 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1066 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1067 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1068 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1069 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1070 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1071 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1072 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1073 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1074 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1075 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1076 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1077 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1078 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1079 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1080 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1081 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1082 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1083 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1084 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1085 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1086 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1087 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1088 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1089 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1090 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1093 uint32_t i_crc = 0xffffffff;
1095 /* Calculate the CRC */
1096 while( i_count > 0 )
1098 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1106 static void GetPAT( sout_mux_t *p_mux,
1107 sout_buffer_chain_t *c )
1109 sout_mux_sys_t *p_sys = p_mux->p_sys;
1110 sout_buffer_t *p_pat;
1113 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1117 p_pat->i_length = 0;
1119 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1121 bits_write( &bits, 8, 0 ); // pointer
1122 bits_write( &bits, 8, 0x00 ); // table id
1123 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1124 bits_write( &bits, 1, 0 ); // 0
1125 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1126 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1127 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1128 bits_write( &bits, 2, 0x03 ); // FIXME
1129 bits_write( &bits, 5, p_sys->i_pat_version_number );
1130 bits_write( &bits, 1, 1 ); // current_next_indicator
1131 bits_write( &bits, 8, 0 ); // section number
1132 bits_write( &bits, 8, 0 ); // last section number
1134 bits_write( &bits, 16, 1 ); // program number
1135 bits_write( &bits, 3, 0x07 ); // reserved
1136 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1138 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1140 p_pat->i_size = bits.i_data;
1142 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1145 static void GetPMT( sout_mux_t *p_mux,
1146 sout_buffer_chain_t *c )
1148 sout_mux_sys_t *p_sys = p_mux->p_sys;
1149 sout_buffer_t *p_pmt;
1153 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1157 p_pmt->i_length = 0;
1159 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1161 bits_write( &bits, 8, 0 ); // pointer
1162 bits_write( &bits, 8, 0x02 ); // table id
1163 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1164 bits_write( &bits, 1, 0 ); // 0
1165 bits_write( &bits, 2, 0 ); // reserved FIXME
1166 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1167 bits_write( &bits, 16, 1 ); // FIXME program number
1168 bits_write( &bits, 2, 0 ); // FIXME
1169 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1170 bits_write( &bits, 1, 1 ); // current_next_indicator
1171 bits_write( &bits, 8, 0 ); // section number
1172 bits_write( &bits, 8, 0 ); // last section number
1174 bits_write( &bits, 3, 0 ); // reserved
1176 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1177 bits_write( &bits, 4, 0 ); // reserved FIXME
1179 bits_write( &bits, 12, 0 ); // program info len FIXME
1181 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1183 ts_stream_t *p_stream;
1185 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1187 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1188 bits_write( &bits, 3, 0 ); // reserved
1189 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1190 bits_write( &bits, 4, 0 ); //reserved
1191 bits_write( &bits, 12, 0 ); // es info len FIXME
1194 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1196 p_pmt->i_size = bits.i_data;
1198 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1200 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1202 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1203 dvbpsi_psi_section_t* p_section )
1205 sout_buffer_t *p_psi, *p_first = NULL;
1212 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1213 ( p_section->b_syntax_indicator ? 4 : 0 );
1215 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1218 p_psi->i_length = 0;
1219 p_psi->i_size = i_size + 1;
1221 p_psi->p_buffer[0] = 0; // pointer
1222 memcpy( p_psi->p_buffer + 1,
1226 sout_BufferChain( &p_first, p_psi );
1228 p_section = p_section->p_next;
1234 static void GetPAT( sout_mux_t *p_mux,
1235 sout_buffer_chain_t *c )
1237 sout_mux_sys_t *p_sys = p_mux->p_sys;
1238 sout_buffer_t *p_pat;
1240 dvbpsi_psi_section_t *p_section;
1242 dvbpsi_InitPAT( &pat,
1244 p_sys->i_pat_version_number,
1245 1 ); // b_current_next
1246 /* add all program (only one) */
1247 dvbpsi_PATAddProgram( &pat,
1249 p_sys->pmt.i_pid ); // i_pid
1251 p_section = dvbpsi_GenPATSections( &pat,
1252 0 ); // max program per section
1254 p_pat = WritePSISection( p_mux->p_sout, p_section );
1256 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1258 dvbpsi_DeletePSISections( p_section );
1259 dvbpsi_EmptyPAT( &pat );
1262 static uint32_t GetDescriptorLength24b( int i_length )
1264 uint32_t i_l1, i_l2, i_l3;
1266 i_l1 = i_length&0x7f;
1267 i_l2 = ( i_length >> 7 )&0x7f;
1268 i_l3 = ( i_length >> 14 )&0x7f;
1270 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1273 static void GetPMT( sout_mux_t *p_mux,
1274 sout_buffer_chain_t *c )
1276 sout_mux_sys_t *p_sys = p_mux->p_sys;
1277 sout_buffer_t *p_pmt;
1280 dvbpsi_pmt_es_t *p_es;
1281 dvbpsi_psi_section_t *p_section;
1285 dvbpsi_InitPMT( &pmt,
1286 0x01, // program number
1287 p_sys->i_pmt_version_number,
1288 1, // b_current_next
1291 if( p_sys->i_mpeg4_streams > 0 )
1295 bits_buffer_t bits_fix_IOD;
1297 bits_initwrite( &bits, 4096, iod );
1299 bits_write( &bits, 8, 0x01 );
1300 // InitialObjectDescriptor
1301 bits_align( &bits );
1302 bits_write( &bits, 8, 0x02 ); // tag
1303 bits_fix_IOD = bits; // save states to fix length later
1304 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1305 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1306 bits_write( &bits, 1, 0x00 ); // URL Flag
1307 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1308 bits_write( &bits, 4, 0x0f ); // reserved
1309 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1310 bits_write( &bits, 8, 0xff ); // sceneProfile
1311 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1312 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1313 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1314 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1316 ts_stream_t *p_stream;
1317 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1319 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1321 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1323 bits_align( &bits );
1324 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1325 bits_fix_ESDescr = bits;
1326 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1327 bits_write( &bits, 16, p_stream->i_es_id );
1328 bits_write( &bits, 1, 0x00 ); // streamDependency
1329 bits_write( &bits, 1, 0x00 ); // URL Flag
1330 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1331 bits_write( &bits, 5, 0x1f ); // streamPriority
1333 // DecoderConfigDesciptor
1334 bits_align( &bits );
1335 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1336 bits_fix_Decoder = bits;
1337 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1338 if( p_stream->i_stream_type == 0x10 )
1340 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1341 bits_write( &bits, 6, 0x04 ); // VisualStream
1343 else if( p_stream->i_stream_type == 0x11 )
1345 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1346 bits_write( &bits, 6, 0x05 ); // AudioStream
1350 bits_write( &bits, 8, 0x00 );
1351 bits_write( &bits, 6, 0x00 );
1353 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1355 bits_write( &bits, 1, 0x00 ); // UpStream
1356 bits_write( &bits, 1, 0x01 ); // reserved
1357 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1358 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1359 bits_write( &bits, 32, 0 ); // avgBitrate
1361 if( p_stream->i_decoder_specific_info > 0 )
1364 // DecoderSpecificInfo
1365 bits_align( &bits );
1366 bits_write( &bits, 8, 0x05 ); // tag
1367 bits_write( &bits, 24,
1368 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1369 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1371 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1374 /* fix Decoder length */
1375 bits_write( &bits_fix_Decoder, 24,
1376 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1378 /* SLConfigDescriptor : predifined (0x01) */
1379 bits_align( &bits );
1380 bits_write( &bits, 8, 0x06 ); // tag
1381 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1382 bits_write( &bits, 8, 0x01 ); // predefined
1383 bits_write( &bits, 1, 0 ); // durationFlag
1384 bits_write( &bits, 32, 0 ); // OCRResolution
1385 bits_write( &bits, 8, 0 ); // OCRLength
1386 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1387 bits_align( &bits );
1389 /* fix ESDescr length */
1390 bits_write( &bits_fix_ESDescr, 24,
1391 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1394 bits_align( &bits );
1395 /* fix IOD length */
1396 bits_write( &bits_fix_IOD, 24,
1397 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1398 dvbpsi_PMTAddDescriptor( &pmt,
1404 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1406 ts_stream_t *p_stream;
1408 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1410 p_es = dvbpsi_PMTAddES( &pmt,
1411 p_stream->i_stream_type,
1413 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1419 bits_initwrite( &bits, 512, data );
1420 bits_write( &bits, 16, p_stream->i_es_id );
1422 dvbpsi_PMTESAddDescriptor( p_es,
1427 else if( p_stream->i_stream_id == 0xa0 )
1433 memcpy( fcc, &p_stream->i_bih_codec, 4 );
1435 /* private DIV3 descripor */
1436 bits_initwrite( &bits, 512, data );
1437 bits_write( &bits, 8, fcc[0]);
1438 bits_write( &bits, 8, fcc[1]);
1439 bits_write( &bits, 8, fcc[2]);
1440 bits_write( &bits, 8, fcc[3]);
1441 bits_write( &bits, 16, p_stream->i_bih_width );
1442 bits_write( &bits, 16, p_stream->i_bih_height );
1443 bits_write( &bits, 16, p_stream->i_decoder_specific_info );
1444 if( p_stream->i_decoder_specific_info > 0 )
1447 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1449 bits_write( &bits, 8, p_stream->p_decoder_specific_info[i] );
1452 dvbpsi_PMTESAddDescriptor( p_es,
1459 p_section = dvbpsi_GenPMTSections( &pmt );
1461 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1463 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1465 dvbpsi_DeletePSISections( p_section );
1466 dvbpsi_EmptyPMT( &pmt );