1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.29 2003/08/18 17:25:51 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"
62 * - check if "registration" descriptor : "AC-3" should be a program
63 * descriptor or an es one. (xine want an es one)
65 * - remove creation of PAT/PMT without dvbpsi
68 * - subtitle support is far from perfect. I expect some subtitles drop
69 * if they arrive a bit late
70 * (We cannot rely on the fact that the fifo should be full)
72 /*****************************************************************************
74 *****************************************************************************/
75 static int Open ( vlc_object_t * );
76 static void Close ( vlc_object_t * );
79 #if defined MODULE_NAME_IS_mux_ts
80 set_description( _("TS muxer") );
81 set_capability( "sout mux", 100 );
83 add_shortcut( "ts_nodvbpsi" );
84 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
85 set_description( _("TS muxer (libdvbpsi)") );
86 set_capability( "sout mux", 120 );
88 add_shortcut( "ts_dvbpsi" );
90 set_callbacks( Open, Close );
93 /*****************************************************************************
95 *****************************************************************************/
96 static int Capability(sout_mux_t *, int, void *, void * );
97 static int AddStream( sout_mux_t *, sout_input_t * );
98 static int DelStream( sout_mux_t *, sout_input_t * );
99 static int Mux ( sout_mux_t * );
101 /*****************************************************************************
103 *****************************************************************************/
104 #define SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT ( 1 << SOUT_BUFFER_FLAGS_PRIVATE_SHIFT )
108 sout_buffer_t *p_first;
109 sout_buffer_t **pp_last;
110 } sout_buffer_chain_t;
112 static inline void BufferChainInit ( sout_buffer_chain_t *c )
116 c->pp_last = &c->p_first;
118 static inline void BufferChainAppend( sout_buffer_chain_t *c, sout_buffer_t *b )
128 c->pp_last = &b->p_next;
130 static inline sout_buffer_t *BufferChainGet( sout_buffer_chain_t *c )
132 sout_buffer_t *b = c->p_first;
137 c->p_first = b->p_next;
139 if( c->p_first == NULL )
141 c->pp_last = &c->p_first;
149 typedef struct ts_stream_s
154 int i_continuity_counter;
156 /* to be used for carriege of DIV3 */
157 vlc_fourcc_t i_bih_codec;
158 int i_bih_width, i_bih_height;
160 /* Specific to mpeg4 in mpeg2ts */
163 int i_decoder_specific_info;
164 uint8_t *p_decoder_specific_info;
166 /* for TS building */
167 sout_buffer_chain_t chain_ts;
171 struct sout_mux_sys_t
174 sout_input_t *p_pcr_input;
176 int i_stream_id_mpga;
177 int i_stream_id_mpgv;
182 int i_pid_free; // first usable pid
184 int i_pat_version_number;
187 int i_pmt_version_number;
188 ts_stream_t pmt; // Up to now only one program
192 int i_null_continuity_counter; /* Needed ? */
194 /* for TS building */
195 int64_t i_bitrate_min;
196 int64_t i_bitrate_max;
198 int64_t i_pcr_soft_delay;
200 mtime_t i_pcr; /* last PCR emited (for pcr-soft) */
203 sout_buffer_chain_t chain_ts;
207 /* Reserve a pid and return it */
208 static int AllocatePID( sout_mux_sys_t *p_sys )
210 return( ++p_sys->i_pid_free );
213 static void GetPAT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
214 static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
216 static int TSFill ( sout_mux_t *, sout_input_t * );
217 static void PEStoTS ( sout_instance_t *, sout_buffer_chain_t *, sout_buffer_t *, ts_stream_t *, vlc_bool_t );
218 static void TSSetDate( sout_buffer_chain_t *, mtime_t, mtime_t, mtime_t );
219 static void TSSetConstraints( sout_mux_t*, sout_buffer_chain_t *,
220 mtime_t i_length, int i_bitrate_min, int i_bitrate_max );
222 /*****************************************************************************
224 *****************************************************************************/
225 static int Open( vlc_object_t *p_this )
227 sout_mux_t *p_mux =(sout_mux_t*)p_this;
228 sout_mux_sys_t *p_sys;
231 msg_Dbg( p_mux, "Open" );
233 p_sys = malloc( sizeof( sout_mux_sys_t ) );
235 p_mux->pf_capacity = Capability;
236 p_mux->pf_addstream = AddStream;
237 p_mux->pf_delstream = DelStream;
239 p_mux->p_sys = p_sys;
240 p_mux->i_preheader = 30; // really enough for a pes header
242 srand( (uint32_t)mdate() );
244 p_sys->i_stream_id_mpga = 0xc0;
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 = 0xbd;
429 case VLC_FOURCC( 'm', 'p','4', 'a' ):
430 p_stream->i_stream_type = 0x11;
431 p_stream->i_stream_id = 0xfa;
432 p_sys->i_mpeg4_streams++;
433 p_stream->i_es_id = p_stream->i_pid;
439 p_sys->i_audio_bound++;
443 switch( p_input->p_fmt->i_fourcc )
445 case VLC_FOURCC( 's', 'p','u', ' ' ):
446 p_stream->i_stream_type = 0x82;
447 p_stream->i_stream_id = 0x82;
460 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
461 p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra_data;
462 if( p_stream->i_decoder_specific_info > 0 )
464 p_stream->p_decoder_specific_info =
465 malloc( p_stream->i_decoder_specific_info );
466 memcpy( p_stream->p_decoder_specific_info,
467 p_input->p_fmt->p_extra_data,
468 p_input->p_fmt->i_extra_data );
470 /* Init chain for TS building */
471 BufferChainInit( &p_stream->chain_ts );
473 /* We only change PMT version (PAT isn't changed) */
474 p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
477 if( p_input->p_fmt->i_cat != SPU_ES &&
478 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
480 sout_buffer_t *p_data;
482 if( p_sys->p_pcr_input )
484 /* There was already a PCR stream, so clean context */
485 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
487 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
489 sout_BufferDelete( p_mux->p_sout, p_data );
492 p_sys->i_pcr_pid = p_stream->i_pid;
493 p_sys->p_pcr_input = p_input;
495 /* Empty TS buffer (avoid broken data/problems with pcr stream changement ) */
496 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
498 sout_BufferDelete( p_mux->p_sout, p_data );
505 /*****************************************************************************
506 * DelStream: called before a stream deletion
507 *****************************************************************************/
508 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
510 sout_mux_sys_t *p_sys = p_mux->p_sys;
511 ts_stream_t *p_stream;
512 sout_buffer_t *p_data;
514 msg_Dbg( p_mux, "removing input" );
515 p_stream = (ts_stream_t*)p_input->p_sys;
517 if( p_sys->i_pcr_pid == p_stream->i_pid )
521 /* Find a new pcr stream (Prefer Video Stream) */
522 p_sys->i_pcr_pid = 0x1fff;
523 p_sys->p_pcr_input = NULL;
524 for( i = 0; i < p_mux->i_nb_inputs; i++ )
526 if( p_mux->pp_inputs[i] == p_input )
531 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
534 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
535 p_sys->p_pcr_input= p_mux->pp_inputs[i];
538 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
539 p_sys->i_pcr_pid == 0x1fff )
542 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
543 p_sys->p_pcr_input= p_mux->pp_inputs[i];
546 if( p_sys->p_pcr_input )
548 /* Empty TS buffer */
549 while( ( p_data = BufferChainGet( &((ts_stream_t*)p_sys->p_pcr_input->p_sys)->chain_ts ) ) )
551 sout_BufferDelete( p_mux->p_sout, p_data );
556 /* Empty all data in chain_ts */
557 while( ( p_data = BufferChainGet( &p_stream->chain_ts ) ) )
559 sout_BufferDelete( p_mux->p_sout, p_data );
561 if( p_stream->p_decoder_specific_info )
563 free( p_stream->p_decoder_specific_info );
565 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
567 p_sys->i_mpeg4_streams--;
571 /* We only change PMT version (PAT isn't changed) */
572 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
574 /*Empty TS buffer (avoid broken data/problems with pcr stream changement) */
575 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
577 sout_BufferDelete( p_mux->p_sout, p_data );
583 /*****************************************************************************
584 * Mux: Call each time there is new data for at least one stream
585 *****************************************************************************
587 *****************************************************************************/
588 static int Mux( sout_mux_t *p_mux )
590 sout_mux_sys_t *p_sys = p_mux->p_sys;
592 sout_input_t *p_pcr_input = p_sys->p_pcr_input;
593 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
595 if( p_sys->i_pcr_pid == 0x1fff )
597 msg_Dbg( p_mux, "waiting PCR streams" );
604 ts_stream_t *p_stream = NULL;
605 sout_buffer_t *p_data;
610 /* fill ts packets for pcr XXX before GetPAT/GetPMT */
611 if( p_pcr_stream->chain_ts.p_first == NULL && TSFill( p_mux, p_pcr_input ) )
613 /* We need more data */
617 if( p_sys->chain_ts.p_first == NULL )
619 /* Every pcr packet send PAT/PMT */
620 GetPAT( p_mux, &p_sys->chain_ts);
621 GetPMT( p_mux, &p_sys->chain_ts );
624 /* search stream with lowest dts */
625 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
627 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
629 if( p_stream->chain_ts.p_first == NULL )
631 if( TSFill( p_mux, p_mux->pp_inputs[i] ) )
633 /* We need more data */
636 if( p_stream->chain_ts.p_first == NULL )
638 continue; /* SPU_ES */
642 if( i_stream == -1 ||
643 p_stream->chain_ts.p_first->i_dts < i_dts )
646 i_dts = p_stream->chain_ts.p_first->i_dts;
650 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
652 p_data = BufferChainGet( &p_stream->chain_ts );
653 BufferChainAppend( &p_sys->chain_ts, p_data );
655 if( p_stream->i_pid == p_pcr_stream->i_pid && p_stream->chain_ts.p_first == NULL )
657 sout_buffer_t *p_ts = p_sys->chain_ts.p_first;
659 /* We have consume all TS packets from the PCR stream */
661 if( p_sys->i_length > p_sys->i_pcr_delay )
663 /* Send TS data if last PCR was i_pcr_delay ago */
665 if( p_sys->i_bitrate_min > 0 ||
666 p_sys->i_bitrate_max > 0 )
668 TSSetConstraints( p_mux, &p_sys->chain_ts, p_sys->i_length,
669 p_sys->i_bitrate_min, p_sys->i_bitrate_max );
673 TSSetDate( &p_sys->chain_ts,
676 3 * p_sys->i_pcr_delay/2 ); /* latency is equal to i_pcr_delay
677 3/2 is for security */
678 sout_AccessOutWrite( p_mux->p_access, p_ts );
680 /* Reset the ts chain */
681 BufferChainInit( &p_sys->chain_ts );
693 /*****************************************************************************
696 *****************************************************************************/
697 static int TSFill( sout_mux_t *p_mux, sout_input_t *p_input )
699 sout_mux_sys_t *p_sys = p_mux->p_sys;
701 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
702 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
703 mtime_t i_dts, i_length;
704 sout_buffer_t *p_data;
705 vlc_bool_t b_pcr = VLC_FALSE;
706 vlc_bool_t b_pcr_soft = VLC_FALSE;
711 if( p_input->p_fifo->i_depth <= 0 )
713 if( p_input->p_fmt->i_cat == AUDIO_ES ||
714 p_input->p_fmt->i_cat == VIDEO_ES )
716 /* We need more data */
724 p_data = sout_FifoGet( p_input->p_fifo );
725 i_dts = p_data->i_dts;
726 i_length = p_data->i_length;
728 if( p_stream->i_pid == p_pcr_stream->i_pid &&
729 p_stream->chain_ts.p_first == NULL )
731 p_sys->i_length+= i_length;
732 if( p_sys->chain_ts.p_first == NULL )
734 p_sys->i_dts = i_dts;
735 p_sys->i_pcr = i_dts;
738 else if( p_sys->i_pcr_soft_delay > 0 &&
739 p_sys->i_pcr + p_sys->i_pcr_soft_delay < i_dts )
741 p_sys->i_pcr = i_dts;
743 b_pcr_soft = VLC_TRUE;
748 if( ( p_sys->i_dts + p_sys->i_length ) - i_dts > 2000000 ||
749 ( p_sys->i_dts + p_sys->i_length ) - i_dts < -2000000 )
751 msg_Err( p_mux, "| buffer_dts - pcr_pts | > 2s ("I64Fd") empting "
752 "pcr TS buffers", p_sys->i_dts + p_sys->i_length - i_dts);
754 sout_BufferDelete( p_mux->p_sout, p_data );
756 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
758 sout_BufferDelete( p_mux->p_sout, p_data );
760 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
762 sout_BufferDelete( p_mux->p_sout, p_data );
767 if( i_dts >= p_sys->i_dts )
772 msg_Dbg( p_mux, "dropping buffer size=%d dts="I64Fd" pcr_dts="I64Fd
773 " diff="I64Fd, p_data->i_size, i_dts, p_sys->i_dts,
774 p_sys->i_dts + p_sys->i_length - i_dts );
775 sout_BufferDelete( p_mux->p_sout, p_data );
778 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
780 BufferChainInit( &p_stream->chain_ts );
781 PEStoTS( p_mux->p_sout, &p_stream->chain_ts, p_data, p_stream, b_pcr );
783 TSSetDate( &p_stream->chain_ts, i_dts, i_length, 0 );
785 if( b_pcr_soft && p_stream->chain_ts.p_first )
787 p_stream->chain_ts.p_first->i_flags=SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT;
793 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 )
795 sout_mux_sys_t *p_sys = p_mux->p_sys;
796 sout_buffer_chain_t s = *c;
799 int i_packets_min = 0;
800 int i_packets_max = 0;
807 i_packets = c->i_depth;
808 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
809 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
811 if( i_packets < i_packets_min && i_packets_min > 0 )
814 int i_div = ( i_packets_min - i_packets ) / i_packets;
815 int i_mod = ( i_packets_min - i_packets ) % i_packets;
818 /* We need to pad with null packets (pid=0x1fff)
819 * We try to melt null packets with true packets */
821 "packets=%d but min=%d -> adding %d packets of padding",
822 i_packets, i_packets_min, i_packets_min - i_packets );
824 BufferChainInit( c );
825 while( ( p_pk = BufferChainGet( &s ) ) )
829 BufferChainAppend( c, p_pk );
831 i_null = i_div + ( i_rest + i_mod ) / i_packets;
833 for( i = 0; i < i_null; i++ )
835 sout_buffer_t *p_null;
837 p_null = sout_BufferNew( p_mux->p_sout, 188 );
838 p_null->p_buffer[0] = 0x47;
839 p_null->p_buffer[1] = 0x1f;
840 p_null->p_buffer[2] = 0xff;
841 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
842 memset( &p_null->p_buffer[4], 0, 184 );
843 p_sys->i_null_continuity_counter =
844 ( p_sys->i_null_continuity_counter + 1 ) % 16;
846 BufferChainAppend( c, p_null );
849 i_rest = ( i_rest + i_mod ) % i_packets;
852 else if( i_packets > i_packets_max && i_packets_max > 0 )
857 /* Arg, we need to drop packets, I don't do something clever (like
858 * dropping complete pid, b frames, ... ), I just get the right amount
859 * of packets and discard the others */
861 "packets=%d but max=%d -> removing %d packets -> stream broken",
862 i_packets, i_packets_max, i_packets - i_packets_max );
864 BufferChainInit( c );
865 for( i = 0; i < i_packets_max; i++ )
867 BufferChainAppend( c, BufferChainGet( &s ) );
870 while( ( p_pk = BufferChainGet( &s ) ) )
872 sout_BufferDelete( p_mux->p_sout, p_pk );
877 static void TSSetDate( sout_buffer_chain_t *c,
878 mtime_t i_dts, mtime_t i_length, mtime_t i_send_offset )
881 mtime_t i_delta = i_length / c->i_depth;
884 for( p_ts = c->p_first; p_ts != NULL; p_ts = p_ts->p_next )
886 p_ts->i_dts = i_dts + i_packet * i_length / c->i_depth; /* avoid rounding error */
887 p_ts->i_length = i_delta;
889 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT )
891 mtime_t i_pcr = 9 * p_ts->i_dts / 100;
893 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
894 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
895 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
896 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
897 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
899 p_ts->i_dts += i_send_offset;
905 static void PEStoTS( sout_instance_t *p_sout,
906 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
907 ts_stream_t *p_stream,
914 /* get PES total size */
915 i_size = p_pes->i_size;
916 p_data = p_pes->p_buffer;
918 /* Set pcr only with valid DTS */
919 if( p_pes->i_dts <= 0 )
924 b_new_pes = VLC_TRUE;
928 int b_adaptation_field;
933 p_ts = sout_BufferNew( p_sout, 188 );
936 * 1b transport_error_indicator
937 * 1b payload_unit_start
938 * 1b transport_priority
940 * 2b transport_scrambling_control
941 * 2b if adaptation_field 0x03 else 0x01
942 * 4b continuity_counter
945 i_payload = 184 - ( b_pcr ? 8 : 0 );
946 i_copy = __MIN( i_size, i_payload );
947 b_adaptation_field = (b_pcr||i_size<i_payload) ? VLC_TRUE : VLC_FALSE;
949 p_ts->p_buffer[0] = 0x47;
950 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
951 ( ( p_stream->i_pid >> 8 )&0x1f );
952 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
953 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
954 p_stream->i_continuity_counter;
956 b_new_pes = VLC_FALSE;
957 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
959 if( b_adaptation_field )
965 mtime_t i_pcr = p_pes->i_dts * 9 / 100;
966 int i_stuffing = i_payload - i_copy;
968 p_ts->p_buffer[4] = 7 + i_stuffing;
969 p_ts->p_buffer[5] = 0x10; /* flags */
970 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
971 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
972 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
973 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
974 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
975 p_ts->p_buffer[11]= 0;
978 for( i = 12; i < 12 + i_stuffing; i++ )
980 p_ts->p_buffer[i] = 0xff;
985 int i_stuffing = i_payload - i_copy;
987 p_ts->p_buffer[4] = i_stuffing - 1;
990 p_ts->p_buffer[5] = 0x00;
991 for( i = 6; i < 6 + i_stuffing - 2; i++ )
993 p_ts->p_buffer[i] = 0xff;
999 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1003 BufferChainAppend( c, p_ts );
1007 sout_buffer_t *p_next = p_pes->p_next;
1009 p_pes->p_next = NULL;
1010 sout_BufferDelete( p_sout, p_pes );
1011 if( p_next == NULL )
1015 b_new_pes = VLC_TRUE;
1017 i_size = p_pes->i_size;
1018 p_data = p_pes->p_buffer;
1025 #if defined MODULE_NAME_IS_mux_ts
1026 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1028 static uint32_t CRC32[256] =
1030 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1031 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1032 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1033 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1034 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1035 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1036 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1037 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1038 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1039 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1040 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1041 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1042 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1043 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1044 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1045 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1046 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1047 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1048 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1049 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1050 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1051 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1052 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1053 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1054 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1055 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1056 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1057 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1058 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1059 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1060 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1061 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1062 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1063 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1064 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1065 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1066 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1067 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1068 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1069 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1070 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1071 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1072 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1073 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1074 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1075 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1076 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1077 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1078 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1079 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1080 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1081 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1082 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1083 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1084 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1085 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1086 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1087 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1088 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1089 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1090 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1091 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1092 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1093 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1096 uint32_t i_crc = 0xffffffff;
1098 /* Calculate the CRC */
1099 while( i_count > 0 )
1101 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1109 static void GetPAT( sout_mux_t *p_mux,
1110 sout_buffer_chain_t *c )
1112 sout_mux_sys_t *p_sys = p_mux->p_sys;
1113 sout_buffer_t *p_pat;
1116 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1120 p_pat->i_length = 0;
1122 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1124 bits_write( &bits, 8, 0 ); // pointer
1125 bits_write( &bits, 8, 0x00 ); // table id
1126 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1127 bits_write( &bits, 1, 0 ); // 0
1128 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1129 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1130 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1131 bits_write( &bits, 2, 0x03 ); // FIXME
1132 bits_write( &bits, 5, p_sys->i_pat_version_number );
1133 bits_write( &bits, 1, 1 ); // current_next_indicator
1134 bits_write( &bits, 8, 0 ); // section number
1135 bits_write( &bits, 8, 0 ); // last section number
1137 bits_write( &bits, 16, 1 ); // program number
1138 bits_write( &bits, 3, 0x07 ); // reserved
1139 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1141 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1143 p_pat->i_size = bits.i_data;
1145 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1148 static void GetPMT( sout_mux_t *p_mux,
1149 sout_buffer_chain_t *c )
1151 sout_mux_sys_t *p_sys = p_mux->p_sys;
1152 sout_buffer_t *p_pmt;
1156 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1160 p_pmt->i_length = 0;
1162 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1164 bits_write( &bits, 8, 0 ); // pointer
1165 bits_write( &bits, 8, 0x02 ); // table id
1166 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1167 bits_write( &bits, 1, 0 ); // 0
1168 bits_write( &bits, 2, 0 ); // reserved FIXME
1169 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1170 bits_write( &bits, 16, 1 ); // FIXME program number
1171 bits_write( &bits, 2, 0 ); // FIXME
1172 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1173 bits_write( &bits, 1, 1 ); // current_next_indicator
1174 bits_write( &bits, 8, 0 ); // section number
1175 bits_write( &bits, 8, 0 ); // last section number
1177 bits_write( &bits, 3, 0 ); // reserved
1179 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1180 bits_write( &bits, 4, 0 ); // reserved FIXME
1182 bits_write( &bits, 12, 0 ); // program info len FIXME
1184 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1186 ts_stream_t *p_stream;
1188 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1190 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1191 bits_write( &bits, 3, 0 ); // reserved
1192 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1193 bits_write( &bits, 4, 0 ); //reserved
1194 bits_write( &bits, 12, 0 ); // es info len FIXME
1197 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1199 p_pmt->i_size = bits.i_data;
1201 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1203 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1205 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1206 dvbpsi_psi_section_t* p_section )
1208 sout_buffer_t *p_psi, *p_first = NULL;
1215 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1216 ( p_section->b_syntax_indicator ? 4 : 0 );
1218 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1221 p_psi->i_length = 0;
1222 p_psi->i_size = i_size + 1;
1224 p_psi->p_buffer[0] = 0; // pointer
1225 memcpy( p_psi->p_buffer + 1,
1229 sout_BufferChain( &p_first, p_psi );
1231 p_section = p_section->p_next;
1237 static void GetPAT( sout_mux_t *p_mux,
1238 sout_buffer_chain_t *c )
1240 sout_mux_sys_t *p_sys = p_mux->p_sys;
1241 sout_buffer_t *p_pat;
1243 dvbpsi_psi_section_t *p_section;
1245 dvbpsi_InitPAT( &pat,
1247 p_sys->i_pat_version_number,
1248 1 ); // b_current_next
1249 /* add all program (only one) */
1250 dvbpsi_PATAddProgram( &pat,
1252 p_sys->pmt.i_pid ); // i_pid
1254 p_section = dvbpsi_GenPATSections( &pat,
1255 0 ); // max program per section
1257 p_pat = WritePSISection( p_mux->p_sout, p_section );
1259 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1261 dvbpsi_DeletePSISections( p_section );
1262 dvbpsi_EmptyPAT( &pat );
1265 static uint32_t GetDescriptorLength24b( int i_length )
1267 uint32_t i_l1, i_l2, i_l3;
1269 i_l1 = i_length&0x7f;
1270 i_l2 = ( i_length >> 7 )&0x7f;
1271 i_l3 = ( i_length >> 14 )&0x7f;
1273 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1276 static void GetPMT( sout_mux_t *p_mux,
1277 sout_buffer_chain_t *c )
1279 sout_mux_sys_t *p_sys = p_mux->p_sys;
1280 sout_buffer_t *p_pmt;
1283 dvbpsi_pmt_es_t *p_es;
1284 dvbpsi_psi_section_t *p_section;
1288 dvbpsi_InitPMT( &pmt,
1289 0x01, // program number
1290 p_sys->i_pmt_version_number,
1291 1, // b_current_next
1294 if( p_sys->i_mpeg4_streams > 0 )
1298 bits_buffer_t bits_fix_IOD;
1300 /* Make valgrind happy : it works at byte level not bit one so
1301 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
1302 * working (needed when fixing some bits) */
1303 memset( iod, 0, 4096 );
1305 bits_initwrite( &bits, 4096, iod );
1307 bits_write( &bits, 8, 0x01 );
1308 // InitialObjectDescriptor
1309 bits_align( &bits );
1310 bits_write( &bits, 8, 0x02 ); // tag
1311 bits_fix_IOD = bits; // save states to fix length later
1312 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1313 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1314 bits_write( &bits, 1, 0x00 ); // URL Flag
1315 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1316 bits_write( &bits, 4, 0x0f ); // reserved
1317 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1318 bits_write( &bits, 8, 0xff ); // sceneProfile
1319 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1320 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1321 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1322 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1324 ts_stream_t *p_stream;
1325 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1327 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1329 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1331 bits_align( &bits );
1332 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1333 bits_fix_ESDescr = bits;
1334 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1335 bits_write( &bits, 16, p_stream->i_es_id );
1336 bits_write( &bits, 1, 0x00 ); // streamDependency
1337 bits_write( &bits, 1, 0x00 ); // URL Flag
1338 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1339 bits_write( &bits, 5, 0x1f ); // streamPriority
1341 // DecoderConfigDesciptor
1342 bits_align( &bits );
1343 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1344 bits_fix_Decoder = bits;
1345 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1346 if( p_stream->i_stream_type == 0x10 )
1348 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1349 bits_write( &bits, 6, 0x04 ); // VisualStream
1351 else if( p_stream->i_stream_type == 0x11 )
1353 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1354 bits_write( &bits, 6, 0x05 ); // AudioStream
1358 bits_write( &bits, 8, 0x00 );
1359 bits_write( &bits, 6, 0x00 );
1361 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1363 bits_write( &bits, 1, 0x00 ); // UpStream
1364 bits_write( &bits, 1, 0x01 ); // reserved
1365 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1366 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1367 bits_write( &bits, 32, 0 ); // avgBitrate
1369 if( p_stream->i_decoder_specific_info > 0 )
1372 // DecoderSpecificInfo
1373 bits_align( &bits );
1374 bits_write( &bits, 8, 0x05 ); // tag
1375 bits_write( &bits, 24,
1376 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1377 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1379 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1382 /* fix Decoder length */
1383 bits_write( &bits_fix_Decoder, 24,
1384 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1386 /* SLConfigDescriptor : predifined (0x01) */
1387 bits_align( &bits );
1388 bits_write( &bits, 8, 0x06 ); // tag
1389 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1390 bits_write( &bits, 8, 0x01 ); // predefined
1391 bits_write( &bits, 1, 0 ); // durationFlag
1392 bits_write( &bits, 32, 0 ); // OCRResolution
1393 bits_write( &bits, 8, 0 ); // OCRLength
1394 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1395 bits_align( &bits );
1397 /* fix ESDescr length */
1398 bits_write( &bits_fix_ESDescr, 24,
1399 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1402 bits_align( &bits );
1403 /* fix IOD length */
1404 bits_write( &bits_fix_IOD, 24,
1405 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1406 dvbpsi_PMTAddDescriptor( &pmt,
1412 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1414 ts_stream_t *p_stream;
1416 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1418 p_es = dvbpsi_PMTAddES( &pmt,
1419 p_stream->i_stream_type,
1421 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1426 es_id[0] = (p_stream->i_es_id >> 8)&0xff;
1427 es_id[1] = (p_stream->i_es_id)&0xff;
1428 dvbpsi_PMTESAddDescriptor( p_es, 0x1f, 2, es_id );
1430 else if( p_stream->i_stream_type == 0xa0 )
1433 int i_extra = __MIN( p_stream->i_decoder_specific_info,
1436 /* private DIV3 descripor */
1437 memcpy( &data[0], &p_stream->i_bih_codec, 4 );
1438 data[4] = ( p_stream->i_bih_width >> 8 )&&0xff;
1439 data[5] = ( p_stream->i_bih_width )&&0xff;
1440 data[6] = ( p_stream->i_bih_height>> 8 )&&0xff;
1441 data[7] = ( p_stream->i_bih_height )&&0xff;
1442 data[8] = ( i_extra >> 8 )&&0xff;
1443 data[9] = ( i_extra )&&0xff;
1446 memcpy( &data[10], p_stream->p_decoder_specific_info, i_extra );
1449 /* 0xa0 is private */
1450 dvbpsi_PMTESAddDescriptor( p_es, 0xa0, i_extra + 10, data );
1452 else if( p_stream->i_stream_type == 0x81 )
1454 uint8_t format[4] = { 0x41, 0x43, 0x2d, 0x33 };
1456 /* "registration" descriptor : "AC-3" */
1457 dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
1461 p_section = dvbpsi_GenPMTSections( &pmt );
1463 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1465 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1467 dvbpsi_DeletePSISections( p_section );
1468 dvbpsi_EmptyPMT( &pmt );