1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.31 2003/08/26 01:04:29 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 <= 1 )
713 if( p_input->p_fmt->i_cat == AUDIO_ES ||
714 p_input->p_fmt->i_cat == VIDEO_ES )
716 /* We need more data */
719 else if( p_input->p_fifo->i_depth <= 0 )
721 /* spu, only one packet is needed */
725 p_data = sout_FifoGet( p_input->p_fifo );
726 i_dts = p_data->i_dts;
727 i_length = p_data->i_length;
729 if( p_stream->i_pid == p_pcr_stream->i_pid &&
730 p_stream->chain_ts.p_first == NULL )
732 /* I need that length == dts_next - dts, but be carefull if
733 * some dts are broken length >= 0.5s are suspicious */
734 sout_buffer_t *p_next;
737 p_next = sout_FifoShow( p_input->p_fifo );
738 i_dts_next = p_next->i_dts;
740 if( i_dts_next > i_dts &&
741 i_dts_next - i_dts < (mtime_t)500000 )
743 i_length = i_dts_next - i_dts;
745 p_sys->i_length+= i_length;
746 if( p_sys->chain_ts.p_first == NULL )
748 p_sys->i_dts = i_dts;
749 p_sys->i_pcr = i_dts;
752 else if( p_sys->i_pcr_soft_delay > 0 &&
753 p_sys->i_pcr + p_sys->i_pcr_soft_delay < i_dts )
755 p_sys->i_pcr = i_dts;
757 b_pcr_soft = VLC_TRUE;
762 if( ( p_sys->i_dts + p_sys->i_length ) - i_dts > 2000000 ||
763 ( p_sys->i_dts + p_sys->i_length ) - i_dts < -2000000 )
765 msg_Err( p_mux, "| buffer_dts - pcr_pts | > 2s ("I64Fd") empting "
766 "pcr TS buffers", p_sys->i_dts + p_sys->i_length - i_dts);
768 sout_BufferDelete( p_mux->p_sout, p_data );
770 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
772 sout_BufferDelete( p_mux->p_sout, p_data );
774 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
776 sout_BufferDelete( p_mux->p_sout, p_data );
781 if( i_dts >= p_sys->i_dts )
786 msg_Dbg( p_mux, "dropping buffer size=%d dts="I64Fd" pcr_dts="I64Fd
787 " diff="I64Fd, p_data->i_size, i_dts, p_sys->i_dts,
788 p_sys->i_dts + p_sys->i_length - i_dts );
789 sout_BufferDelete( p_mux->p_sout, p_data );
792 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
794 BufferChainInit( &p_stream->chain_ts );
795 PEStoTS( p_mux->p_sout, &p_stream->chain_ts, p_data, p_stream, b_pcr );
797 TSSetDate( &p_stream->chain_ts, i_dts, i_length, 0 );
799 if( b_pcr_soft && p_stream->chain_ts.p_first )
801 p_stream->chain_ts.p_first->i_flags=SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT;
807 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 )
809 sout_mux_sys_t *p_sys = p_mux->p_sys;
810 sout_buffer_chain_t s = *c;
813 int i_packets_min = 0;
814 int i_packets_max = 0;
821 i_packets = c->i_depth;
822 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
823 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
825 if( i_packets < i_packets_min && i_packets_min > 0 )
828 int i_div = ( i_packets_min - i_packets ) / i_packets;
829 int i_mod = ( i_packets_min - i_packets ) % i_packets;
832 /* We need to pad with null packets (pid=0x1fff)
833 * We try to melt null packets with true packets */
835 "packets=%d but min=%d -> adding %d packets of padding",
836 i_packets, i_packets_min, i_packets_min - i_packets );
838 BufferChainInit( c );
839 while( ( p_pk = BufferChainGet( &s ) ) )
843 BufferChainAppend( c, p_pk );
845 i_null = i_div + ( i_rest + i_mod ) / i_packets;
847 for( i = 0; i < i_null; i++ )
849 sout_buffer_t *p_null;
851 p_null = sout_BufferNew( p_mux->p_sout, 188 );
852 p_null->p_buffer[0] = 0x47;
853 p_null->p_buffer[1] = 0x1f;
854 p_null->p_buffer[2] = 0xff;
855 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
856 memset( &p_null->p_buffer[4], 0, 184 );
857 p_sys->i_null_continuity_counter =
858 ( p_sys->i_null_continuity_counter + 1 ) % 16;
860 BufferChainAppend( c, p_null );
863 i_rest = ( i_rest + i_mod ) % i_packets;
866 else if( i_packets > i_packets_max && i_packets_max > 0 )
871 /* Arg, we need to drop packets, I don't do something clever (like
872 * dropping complete pid, b frames, ... ), I just get the right amount
873 * of packets and discard the others */
875 "packets=%d but max=%d -> removing %d packets -> stream broken",
876 i_packets, i_packets_max, i_packets - i_packets_max );
878 BufferChainInit( c );
879 for( i = 0; i < i_packets_max; i++ )
881 BufferChainAppend( c, BufferChainGet( &s ) );
884 while( ( p_pk = BufferChainGet( &s ) ) )
886 sout_BufferDelete( p_mux->p_sout, p_pk );
891 static void TSSetDate( sout_buffer_chain_t *c,
892 mtime_t i_dts, mtime_t i_length, mtime_t i_send_offset )
895 mtime_t i_delta = i_length / c->i_depth;
898 for( p_ts = c->p_first; p_ts != NULL; p_ts = p_ts->p_next )
900 p_ts->i_dts = i_dts + i_packet * i_length / c->i_depth; /* avoid rounding error */
901 p_ts->i_length = i_delta;
903 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT )
905 mtime_t i_pcr = 9 * p_ts->i_dts / 100;
907 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
908 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
909 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
910 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
911 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
913 p_ts->i_dts += i_send_offset;
919 static void PEStoTS( sout_instance_t *p_sout,
920 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
921 ts_stream_t *p_stream,
928 /* get PES total size */
929 i_size = p_pes->i_size;
930 p_data = p_pes->p_buffer;
932 /* Set pcr only with valid DTS */
933 if( p_pes->i_dts <= 0 )
938 b_new_pes = VLC_TRUE;
942 int b_adaptation_field;
947 p_ts = sout_BufferNew( p_sout, 188 );
950 * 1b transport_error_indicator
951 * 1b payload_unit_start
952 * 1b transport_priority
954 * 2b transport_scrambling_control
955 * 2b if adaptation_field 0x03 else 0x01
956 * 4b continuity_counter
959 i_payload = 184 - ( b_pcr ? 8 : 0 );
960 i_copy = __MIN( i_size, i_payload );
961 b_adaptation_field = (b_pcr||i_size<i_payload) ? VLC_TRUE : VLC_FALSE;
963 p_ts->p_buffer[0] = 0x47;
964 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
965 ( ( p_stream->i_pid >> 8 )&0x1f );
966 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
967 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
968 p_stream->i_continuity_counter;
970 b_new_pes = VLC_FALSE;
971 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
973 if( b_adaptation_field )
979 mtime_t i_pcr = p_pes->i_dts * 9 / 100;
980 int i_stuffing = i_payload - i_copy;
982 p_ts->p_buffer[4] = 7 + i_stuffing;
983 p_ts->p_buffer[5] = 0x10; /* flags */
984 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
985 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
986 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
987 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
988 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
989 p_ts->p_buffer[11]= 0;
992 for( i = 12; i < 12 + i_stuffing; i++ )
994 p_ts->p_buffer[i] = 0xff;
999 int i_stuffing = i_payload - i_copy;
1001 p_ts->p_buffer[4] = i_stuffing - 1;
1002 if( i_stuffing > 1 )
1004 p_ts->p_buffer[5] = 0x00;
1005 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1007 p_ts->p_buffer[i] = 0xff;
1013 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1017 BufferChainAppend( c, p_ts );
1021 sout_buffer_t *p_next = p_pes->p_next;
1023 p_pes->p_next = NULL;
1024 sout_BufferDelete( p_sout, p_pes );
1025 if( p_next == NULL )
1029 b_new_pes = VLC_TRUE;
1031 i_size = p_pes->i_size;
1032 p_data = p_pes->p_buffer;
1039 #if defined MODULE_NAME_IS_mux_ts
1040 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1042 static uint32_t CRC32[256] =
1044 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1045 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1046 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1047 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1048 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1049 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1050 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1051 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1052 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1053 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1054 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1055 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1056 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1057 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1058 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1059 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1060 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1061 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1062 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1063 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1064 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1065 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1066 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1067 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1068 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1069 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1070 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1071 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1072 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1073 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1074 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1075 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1076 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1077 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1078 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1079 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1080 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1081 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1082 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1083 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1084 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1085 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1086 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1087 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1088 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1089 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1090 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1091 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1092 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1093 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1094 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1095 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1096 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1097 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1098 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1099 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1100 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1101 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1102 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1103 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1104 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1105 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1106 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1107 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1110 uint32_t i_crc = 0xffffffff;
1112 /* Calculate the CRC */
1113 while( i_count > 0 )
1115 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1123 static void GetPAT( sout_mux_t *p_mux,
1124 sout_buffer_chain_t *c )
1126 sout_mux_sys_t *p_sys = p_mux->p_sys;
1127 sout_buffer_t *p_pat;
1130 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1134 p_pat->i_length = 0;
1136 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1138 bits_write( &bits, 8, 0 ); // pointer
1139 bits_write( &bits, 8, 0x00 ); // table id
1140 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1141 bits_write( &bits, 1, 0 ); // 0
1142 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1143 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1144 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1145 bits_write( &bits, 2, 0x03 ); // FIXME
1146 bits_write( &bits, 5, p_sys->i_pat_version_number );
1147 bits_write( &bits, 1, 1 ); // current_next_indicator
1148 bits_write( &bits, 8, 0 ); // section number
1149 bits_write( &bits, 8, 0 ); // last section number
1151 bits_write( &bits, 16, 1 ); // program number
1152 bits_write( &bits, 3, 0x07 ); // reserved
1153 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1155 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1157 p_pat->i_size = bits.i_data;
1159 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1162 static void GetPMT( sout_mux_t *p_mux,
1163 sout_buffer_chain_t *c )
1165 sout_mux_sys_t *p_sys = p_mux->p_sys;
1166 sout_buffer_t *p_pmt;
1170 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1174 p_pmt->i_length = 0;
1176 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1178 bits_write( &bits, 8, 0 ); // pointer
1179 bits_write( &bits, 8, 0x02 ); // table id
1180 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1181 bits_write( &bits, 1, 0 ); // 0
1182 bits_write( &bits, 2, 0 ); // reserved FIXME
1183 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1184 bits_write( &bits, 16, 1 ); // FIXME program number
1185 bits_write( &bits, 2, 0 ); // FIXME
1186 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1187 bits_write( &bits, 1, 1 ); // current_next_indicator
1188 bits_write( &bits, 8, 0 ); // section number
1189 bits_write( &bits, 8, 0 ); // last section number
1191 bits_write( &bits, 3, 0 ); // reserved
1193 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1194 bits_write( &bits, 4, 0 ); // reserved FIXME
1196 bits_write( &bits, 12, 0 ); // program info len FIXME
1198 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1200 ts_stream_t *p_stream;
1202 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1204 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1205 bits_write( &bits, 3, 0 ); // reserved
1206 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1207 bits_write( &bits, 4, 0 ); //reserved
1208 bits_write( &bits, 12, 0 ); // es info len FIXME
1211 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1213 p_pmt->i_size = bits.i_data;
1215 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1217 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1219 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1220 dvbpsi_psi_section_t* p_section )
1222 sout_buffer_t *p_psi, *p_first = NULL;
1229 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1230 ( p_section->b_syntax_indicator ? 4 : 0 );
1232 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1235 p_psi->i_length = 0;
1236 p_psi->i_size = i_size + 1;
1238 p_psi->p_buffer[0] = 0; // pointer
1239 memcpy( p_psi->p_buffer + 1,
1243 sout_BufferChain( &p_first, p_psi );
1245 p_section = p_section->p_next;
1251 static void GetPAT( sout_mux_t *p_mux,
1252 sout_buffer_chain_t *c )
1254 sout_mux_sys_t *p_sys = p_mux->p_sys;
1255 sout_buffer_t *p_pat;
1257 dvbpsi_psi_section_t *p_section;
1259 dvbpsi_InitPAT( &pat,
1261 p_sys->i_pat_version_number,
1262 1 ); // b_current_next
1263 /* add all program (only one) */
1264 dvbpsi_PATAddProgram( &pat,
1266 p_sys->pmt.i_pid ); // i_pid
1268 p_section = dvbpsi_GenPATSections( &pat,
1269 0 ); // max program per section
1271 p_pat = WritePSISection( p_mux->p_sout, p_section );
1273 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1275 dvbpsi_DeletePSISections( p_section );
1276 dvbpsi_EmptyPAT( &pat );
1279 static uint32_t GetDescriptorLength24b( int i_length )
1281 uint32_t i_l1, i_l2, i_l3;
1283 i_l1 = i_length&0x7f;
1284 i_l2 = ( i_length >> 7 )&0x7f;
1285 i_l3 = ( i_length >> 14 )&0x7f;
1287 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1290 static void GetPMT( sout_mux_t *p_mux,
1291 sout_buffer_chain_t *c )
1293 sout_mux_sys_t *p_sys = p_mux->p_sys;
1294 sout_buffer_t *p_pmt;
1297 dvbpsi_pmt_es_t *p_es;
1298 dvbpsi_psi_section_t *p_section;
1302 dvbpsi_InitPMT( &pmt,
1303 0x01, // program number
1304 p_sys->i_pmt_version_number,
1305 1, // b_current_next
1308 if( p_sys->i_mpeg4_streams > 0 )
1312 bits_buffer_t bits_fix_IOD;
1314 /* Make valgrind happy : it works at byte level not bit one so
1315 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
1316 * working (needed when fixing some bits) */
1317 memset( iod, 0, 4096 );
1319 bits_initwrite( &bits, 4096, iod );
1321 bits_write( &bits, 8, 0x01 );
1322 // InitialObjectDescriptor
1323 bits_align( &bits );
1324 bits_write( &bits, 8, 0x02 ); // tag
1325 bits_fix_IOD = bits; // save states to fix length later
1326 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1327 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1328 bits_write( &bits, 1, 0x00 ); // URL Flag
1329 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1330 bits_write( &bits, 4, 0x0f ); // reserved
1331 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1332 bits_write( &bits, 8, 0xff ); // sceneProfile
1333 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1334 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1335 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1336 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1338 ts_stream_t *p_stream;
1339 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1341 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1343 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1345 bits_align( &bits );
1346 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1347 bits_fix_ESDescr = bits;
1348 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1349 bits_write( &bits, 16, p_stream->i_es_id );
1350 bits_write( &bits, 1, 0x00 ); // streamDependency
1351 bits_write( &bits, 1, 0x00 ); // URL Flag
1352 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1353 bits_write( &bits, 5, 0x1f ); // streamPriority
1355 // DecoderConfigDesciptor
1356 bits_align( &bits );
1357 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1358 bits_fix_Decoder = bits;
1359 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1360 if( p_stream->i_stream_type == 0x10 )
1362 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1363 bits_write( &bits, 6, 0x04 ); // VisualStream
1365 else if( p_stream->i_stream_type == 0x11 )
1367 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1368 bits_write( &bits, 6, 0x05 ); // AudioStream
1372 bits_write( &bits, 8, 0x00 );
1373 bits_write( &bits, 6, 0x00 );
1375 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1377 bits_write( &bits, 1, 0x00 ); // UpStream
1378 bits_write( &bits, 1, 0x01 ); // reserved
1379 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1380 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1381 bits_write( &bits, 32, 0 ); // avgBitrate
1383 if( p_stream->i_decoder_specific_info > 0 )
1386 // DecoderSpecificInfo
1387 bits_align( &bits );
1388 bits_write( &bits, 8, 0x05 ); // tag
1389 bits_write( &bits, 24,
1390 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1391 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1393 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1396 /* fix Decoder length */
1397 bits_write( &bits_fix_Decoder, 24,
1398 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1400 /* SLConfigDescriptor : predifined (0x01) */
1401 bits_align( &bits );
1402 bits_write( &bits, 8, 0x06 ); // tag
1403 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1404 bits_write( &bits, 8, 0x01 ); // predefined
1405 bits_write( &bits, 1, 0 ); // durationFlag
1406 bits_write( &bits, 32, 0 ); // OCRResolution
1407 bits_write( &bits, 8, 0 ); // OCRLength
1408 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1409 bits_align( &bits );
1411 /* fix ESDescr length */
1412 bits_write( &bits_fix_ESDescr, 24,
1413 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1416 bits_align( &bits );
1417 /* fix IOD length */
1418 bits_write( &bits_fix_IOD, 24,
1419 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1420 dvbpsi_PMTAddDescriptor( &pmt,
1426 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1428 ts_stream_t *p_stream;
1430 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1432 p_es = dvbpsi_PMTAddES( &pmt,
1433 p_stream->i_stream_type,
1435 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1440 es_id[0] = (p_stream->i_es_id >> 8)&0xff;
1441 es_id[1] = (p_stream->i_es_id)&0xff;
1442 dvbpsi_PMTESAddDescriptor( p_es, 0x1f, 2, es_id );
1444 else if( p_stream->i_stream_type == 0xa0 )
1447 int i_extra = __MIN( p_stream->i_decoder_specific_info,
1450 /* private DIV3 descripor */
1451 memcpy( &data[0], &p_stream->i_bih_codec, 4 );
1452 data[4] = ( p_stream->i_bih_width >> 8 )&&0xff;
1453 data[5] = ( p_stream->i_bih_width )&&0xff;
1454 data[6] = ( p_stream->i_bih_height>> 8 )&&0xff;
1455 data[7] = ( p_stream->i_bih_height )&&0xff;
1456 data[8] = ( i_extra >> 8 )&&0xff;
1457 data[9] = ( i_extra )&&0xff;
1460 memcpy( &data[10], p_stream->p_decoder_specific_info, i_extra );
1463 /* 0xa0 is private */
1464 dvbpsi_PMTESAddDescriptor( p_es, 0xa0, i_extra + 10, data );
1466 else if( p_stream->i_stream_type == 0x81 )
1468 uint8_t format[4] = { 0x41, 0x43, 0x2d, 0x33 };
1470 /* "registration" descriptor : "AC-3" */
1471 dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
1475 p_section = dvbpsi_GenPMTSections( &pmt );
1477 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1479 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1481 dvbpsi_DeletePSISections( p_section );
1482 dvbpsi_EmptyPMT( &pmt );