1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.33 2003/11/07 18:41:09 massiot 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;
184 int i_pid_free; // first usable pid
186 int i_pat_version_number;
189 int i_pmt_version_number;
190 ts_stream_t pmt; // Up to now only one program
194 int i_null_continuity_counter; /* Needed ? */
196 /* for TS building */
197 int64_t i_bitrate_min;
198 int64_t i_bitrate_max;
200 int64_t i_pcr_soft_delay;
202 mtime_t i_pcr; /* last PCR emited (for pcr-soft) */
205 sout_buffer_chain_t chain_ts;
209 /* Reserve a pid and return it */
210 static int AllocatePID( sout_mux_sys_t *p_sys, int i_cat )
213 if ( i_cat == VIDEO_ES && p_sys->i_pid_video )
215 i_pid = p_sys->i_pid_video;
216 p_sys->i_pid_video = 0;
218 else if ( i_cat == AUDIO_ES && p_sys->i_pid_audio )
220 i_pid = p_sys->i_pid_audio;
221 p_sys->i_pid_audio = 0;
225 i_pid = ++p_sys->i_pid_free;
230 static void GetPAT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
231 static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
233 static int TSFill ( sout_mux_t *, sout_input_t * );
234 static void PEStoTS ( sout_instance_t *, sout_buffer_chain_t *, sout_buffer_t *, ts_stream_t *, vlc_bool_t );
235 static void TSSetDate( sout_buffer_chain_t *, mtime_t, mtime_t, mtime_t );
236 static void TSSetConstraints( sout_mux_t*, sout_buffer_chain_t *,
237 mtime_t i_length, int i_bitrate_min, int i_bitrate_max );
239 /*****************************************************************************
241 *****************************************************************************/
242 static int Open( vlc_object_t *p_this )
244 sout_mux_t *p_mux =(sout_mux_t*)p_this;
245 sout_mux_sys_t *p_sys;
248 msg_Dbg( p_mux, "Open" );
250 p_sys = malloc( sizeof( sout_mux_sys_t ) );
252 p_mux->pf_capacity = Capability;
253 p_mux->pf_addstream = AddStream;
254 p_mux->pf_delstream = DelStream;
256 p_mux->p_sys = p_sys;
257 p_mux->i_preheader = 30; // really enough for a pes header
259 srand( (uint32_t)mdate() );
261 p_sys->i_stream_id_mpga = 0xc0;
262 p_sys->i_stream_id_mpgv = 0xe0;
264 p_sys->i_audio_bound = 0;
265 p_sys->i_video_bound = 0;
267 p_sys->i_pat_version_number = rand() % 32;
268 p_sys->pat.i_pid = 0;
269 p_sys->pat.i_continuity_counter = 0;
271 p_sys->i_pmt_version_number = rand() % 32;
272 p_sys->pmt.i_pid = 0x42;
273 p_sys->pmt.i_continuity_counter = 0;
275 p_sys->i_pid_free = 0x43;
277 p_sys->i_pid_video = 0;
278 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) )
280 p_sys->i_pid_video = strtol( val, NULL, 0 );
281 if ( p_sys->i_pid_video > p_sys->i_pid_free )
283 p_sys->i_pid_free = p_sys->i_pid_video + 1;
286 p_sys->i_pid_audio = 0;
287 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) )
289 p_sys->i_pid_audio = strtol( val, NULL, 0 );
290 if ( p_sys->i_pid_audio > p_sys->i_pid_free )
292 p_sys->i_pid_free = p_sys->i_pid_audio + 1;
296 p_sys->i_pcr_pid = 0x1fff;
297 p_sys->p_pcr_input = NULL;
299 p_sys->i_mpeg4_streams = 0;
301 p_sys->i_null_continuity_counter = 0;
303 /* Allow to create constrained stream */
304 p_sys->i_bitrate_min = 0;
305 p_sys->i_bitrate_max = 0;
306 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmin" ) ) )
308 p_sys->i_bitrate_min = atoll( val );
310 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmax" ) ) )
312 p_sys->i_bitrate_max = atoll( val );
314 if( p_sys->i_bitrate_min > 0 && p_sys->i_bitrate_max > 0 &&
315 p_sys->i_bitrate_min > p_sys->i_bitrate_max )
317 msg_Err( p_mux, "incompatible minimum and maximum bitrate, "
318 "disabling bitrate control" );
319 p_sys->i_bitrate_min = 0;
320 p_sys->i_bitrate_max = 0;
322 p_sys->i_pcr_delay = 90000;
323 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr" ) ) )
325 p_sys->i_pcr_delay = (int64_t)atoi( val ) * 1000;
326 if( p_sys->i_pcr_delay <= 0 )
329 "invalid pcr delay ("I64Fd"ms) reseting to 90ms",
330 p_sys->i_pcr_delay / 1000 );
331 p_sys->i_pcr_delay = 90000;
334 p_sys->i_pcr_soft_delay = 0;
335 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr-soft" ) ) )
337 p_sys->i_pcr_soft_delay = (int64_t)atoi( val ) * 1000;
338 if( p_sys->i_pcr_soft_delay <= 0 ||
339 p_sys->i_pcr_soft_delay >= p_sys->i_pcr_delay )
342 "invalid pcr-soft delay ("I64Fd"ms) disabled",
343 p_sys->i_pcr_soft_delay / 1000 );
344 p_sys->i_pcr_soft_delay = 0;
348 msg_Dbg( p_mux, "pcr_delay="I64Fd" pcr_soft_delay="I64Fd,
349 p_sys->i_pcr_delay, p_sys->i_pcr_soft_delay );
351 /* for TS generation */
355 BufferChainInit( &p_sys->chain_ts );
359 /*****************************************************************************
361 *****************************************************************************/
362 static void Close( vlc_object_t * p_this )
364 sout_mux_t *p_mux = (sout_mux_t*)p_this;
365 sout_mux_sys_t *p_sys = p_mux->p_sys;
366 sout_buffer_t *p_data;
368 msg_Dbg( p_mux, "Close" );
370 /* Empty TS buffer */
371 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
373 sout_BufferDelete( p_mux->p_sout, p_data );
379 /*****************************************************************************
381 *****************************************************************************/
382 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
386 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
387 *(vlc_bool_t*)p_answer = VLC_TRUE;
388 return( SOUT_MUX_CAP_ERR_OK );
390 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
394 /*****************************************************************************
395 * AddStream: called for each stream addition
396 *****************************************************************************/
397 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
399 sout_mux_sys_t *p_sys = p_mux->p_sys;
400 ts_stream_t *p_stream;
402 msg_Dbg( p_mux, "adding input codec=%4.4s", (char*)&p_input->p_fmt->i_fourcc );
404 p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
406 /* Init this new stream */
407 p_stream->i_pid = AllocatePID( p_sys, p_input->p_fmt->i_cat );
408 p_stream->i_continuity_counter = 0;
409 p_stream->i_decoder_specific_info = 0;
410 p_stream->p_decoder_specific_info = NULL;
412 /* All others fields depand on codec */
413 switch( p_input->p_fmt->i_cat )
416 switch( p_input->p_fmt->i_fourcc )
418 case VLC_FOURCC( 'm', 'p','g', 'v' ):
419 /* TODO: do we need to check MPEG-I/II ? */
420 p_stream->i_stream_type = 0x02;
421 p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
422 p_sys->i_stream_id_mpgv++;
424 case VLC_FOURCC( 'm', 'p','4', 'v' ):
425 p_stream->i_stream_type = 0x10;
426 p_stream->i_stream_id = 0xfa;
427 p_sys->i_mpeg4_streams++;
428 p_stream->i_es_id = p_stream->i_pid;
430 /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
431 /* I didn't want to do that :P */
432 case VLC_FOURCC( 'H', '2', '6', '3' ):
433 case VLC_FOURCC( 'I', '2', '6', '3' ):
434 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
435 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
436 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
437 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
438 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
439 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
440 p_stream->i_stream_type = 0xa0; // private
441 p_stream->i_stream_id = 0xa0; // beurk
442 p_stream->i_bih_codec = p_input->p_fmt->i_fourcc;
443 p_stream->i_bih_width = p_input->p_fmt->i_width;
444 p_stream->i_bih_height = p_input->p_fmt->i_height;
450 p_sys->i_video_bound++;
454 switch( p_input->p_fmt->i_fourcc )
456 case VLC_FOURCC( 'm', 'p','g', 'a' ):
457 p_stream->i_stream_type = p_input->p_fmt->i_sample_rate >= 32000 ? 0x03 : 0x04;
458 p_stream->i_stream_id = p_sys->i_stream_id_mpga;
459 p_sys->i_stream_id_mpga++;
461 case VLC_FOURCC( 'a', '5','2', ' ' ):
462 p_stream->i_stream_type = 0x81;
463 p_stream->i_stream_id = 0xbd;
465 case VLC_FOURCC( 'm', 'p','4', 'a' ):
466 p_stream->i_stream_type = 0x11;
467 p_stream->i_stream_id = 0xfa;
468 p_sys->i_mpeg4_streams++;
469 p_stream->i_es_id = p_stream->i_pid;
475 p_sys->i_audio_bound++;
479 switch( p_input->p_fmt->i_fourcc )
481 case VLC_FOURCC( 's', 'p','u', ' ' ):
482 p_stream->i_stream_type = 0x82;
483 p_stream->i_stream_id = 0x82;
496 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
497 p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra_data;
498 if( p_stream->i_decoder_specific_info > 0 )
500 p_stream->p_decoder_specific_info =
501 malloc( p_stream->i_decoder_specific_info );
502 memcpy( p_stream->p_decoder_specific_info,
503 p_input->p_fmt->p_extra_data,
504 p_input->p_fmt->i_extra_data );
506 /* Init chain for TS building */
507 BufferChainInit( &p_stream->chain_ts );
509 /* We only change PMT version (PAT isn't changed) */
510 p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
513 if( p_input->p_fmt->i_cat != SPU_ES &&
514 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
516 sout_buffer_t *p_data;
518 if( p_sys->p_pcr_input )
520 /* There was already a PCR stream, so clean context */
521 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
523 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
525 sout_BufferDelete( p_mux->p_sout, p_data );
528 p_sys->i_pcr_pid = p_stream->i_pid;
529 p_sys->p_pcr_input = p_input;
531 /* Empty TS buffer (avoid broken data/problems with pcr stream changement ) */
532 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
534 sout_BufferDelete( p_mux->p_sout, p_data );
541 /*****************************************************************************
542 * DelStream: called before a stream deletion
543 *****************************************************************************/
544 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
546 sout_mux_sys_t *p_sys = p_mux->p_sys;
547 ts_stream_t *p_stream;
548 sout_buffer_t *p_data;
550 msg_Dbg( p_mux, "removing input" );
551 p_stream = (ts_stream_t*)p_input->p_sys;
553 if( p_sys->i_pcr_pid == p_stream->i_pid )
557 /* Find a new pcr stream (Prefer Video Stream) */
558 p_sys->i_pcr_pid = 0x1fff;
559 p_sys->p_pcr_input = NULL;
560 for( i = 0; i < p_mux->i_nb_inputs; i++ )
562 if( p_mux->pp_inputs[i] == p_input )
567 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
570 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
571 p_sys->p_pcr_input= p_mux->pp_inputs[i];
574 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
575 p_sys->i_pcr_pid == 0x1fff )
578 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
579 p_sys->p_pcr_input= p_mux->pp_inputs[i];
582 if( p_sys->p_pcr_input )
584 /* Empty TS buffer */
585 while( ( p_data = BufferChainGet( &((ts_stream_t*)p_sys->p_pcr_input->p_sys)->chain_ts ) ) )
587 sout_BufferDelete( p_mux->p_sout, p_data );
592 /* Empty all data in chain_ts */
593 while( ( p_data = BufferChainGet( &p_stream->chain_ts ) ) )
595 sout_BufferDelete( p_mux->p_sout, p_data );
597 if( p_stream->p_decoder_specific_info )
599 free( p_stream->p_decoder_specific_info );
601 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
603 p_sys->i_mpeg4_streams--;
607 /* We only change PMT version (PAT isn't changed) */
608 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
610 /*Empty TS buffer (avoid broken data/problems with pcr stream changement) */
611 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
613 sout_BufferDelete( p_mux->p_sout, p_data );
619 /*****************************************************************************
620 * Mux: Call each time there is new data for at least one stream
621 *****************************************************************************
623 *****************************************************************************/
624 static int Mux( sout_mux_t *p_mux )
626 sout_mux_sys_t *p_sys = p_mux->p_sys;
628 sout_input_t *p_pcr_input = p_sys->p_pcr_input;
629 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
631 if( p_sys->i_pcr_pid == 0x1fff )
633 msg_Dbg( p_mux, "waiting PCR streams" );
640 ts_stream_t *p_stream = NULL;
641 sout_buffer_t *p_data;
646 /* fill ts packets for pcr XXX before GetPAT/GetPMT */
647 if( p_pcr_stream->chain_ts.p_first == NULL && TSFill( p_mux, p_pcr_input ) )
649 /* We need more data */
653 if( p_sys->chain_ts.p_first == NULL )
655 /* Every pcr packet send PAT/PMT */
656 GetPAT( p_mux, &p_sys->chain_ts);
657 GetPMT( p_mux, &p_sys->chain_ts );
660 /* search stream with lowest dts */
661 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
663 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
665 if( p_stream->chain_ts.p_first == NULL )
667 if( TSFill( p_mux, p_mux->pp_inputs[i] ) )
669 /* We need more data */
672 if( p_stream->chain_ts.p_first == NULL )
674 continue; /* SPU_ES */
678 if( i_stream == -1 ||
679 p_stream->chain_ts.p_first->i_dts < i_dts )
682 i_dts = p_stream->chain_ts.p_first->i_dts;
686 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
688 p_data = BufferChainGet( &p_stream->chain_ts );
689 BufferChainAppend( &p_sys->chain_ts, p_data );
691 if( p_stream->i_pid == p_pcr_stream->i_pid && p_stream->chain_ts.p_first == NULL )
693 sout_buffer_t *p_ts = p_sys->chain_ts.p_first;
695 /* We have consume all TS packets from the PCR stream */
697 if( p_sys->i_length > p_sys->i_pcr_delay )
699 /* Send TS data if last PCR was i_pcr_delay ago */
701 if( p_sys->i_bitrate_min > 0 ||
702 p_sys->i_bitrate_max > 0 )
704 TSSetConstraints( p_mux, &p_sys->chain_ts, p_sys->i_length,
705 p_sys->i_bitrate_min, p_sys->i_bitrate_max );
709 TSSetDate( &p_sys->chain_ts,
712 3 * p_sys->i_pcr_delay/2 ); /* latency is equal to i_pcr_delay
713 3/2 is for security */
714 sout_AccessOutWrite( p_mux->p_access, p_ts );
716 /* Reset the ts chain */
717 BufferChainInit( &p_sys->chain_ts );
729 /*****************************************************************************
732 *****************************************************************************/
733 static int TSFill( sout_mux_t *p_mux, sout_input_t *p_input )
735 sout_mux_sys_t *p_sys = p_mux->p_sys;
737 ts_stream_t *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
738 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
739 mtime_t i_dts, i_length;
740 sout_buffer_t *p_data;
741 vlc_bool_t b_pcr = VLC_FALSE;
742 vlc_bool_t b_pcr_soft = VLC_FALSE;
747 if( p_input->p_fifo->i_depth <= 1 )
749 if( p_input->p_fmt->i_cat == AUDIO_ES ||
750 p_input->p_fmt->i_cat == VIDEO_ES )
752 /* We need more data */
755 else if( p_input->p_fifo->i_depth <= 0 )
757 /* spu, only one packet is needed */
761 p_data = sout_FifoGet( p_input->p_fifo );
762 i_dts = p_data->i_dts;
763 i_length = p_data->i_length;
765 if( p_stream->i_pid == p_pcr_stream->i_pid &&
766 p_stream->chain_ts.p_first == NULL )
768 /* I need that length == dts_next - dts, but be carefull if
769 * some dts are broken length >= 0.5s are suspicious */
770 sout_buffer_t *p_next;
773 p_next = sout_FifoShow( p_input->p_fifo );
774 i_dts_next = p_next->i_dts;
776 if( i_dts_next > i_dts &&
777 i_dts_next - i_dts < (mtime_t)500000 )
779 i_length = i_dts_next - i_dts;
781 p_sys->i_length+= i_length;
782 if( p_sys->chain_ts.p_first == NULL )
784 p_sys->i_dts = i_dts;
785 p_sys->i_pcr = i_dts;
788 else if( p_sys->i_pcr_soft_delay > 0 &&
789 p_sys->i_pcr + p_sys->i_pcr_soft_delay < i_dts )
791 p_sys->i_pcr = i_dts;
793 b_pcr_soft = VLC_TRUE;
798 if( ( p_sys->i_dts + p_sys->i_length ) - i_dts > 2000000 ||
799 ( p_sys->i_dts + p_sys->i_length ) - i_dts < -2000000 )
801 msg_Err( p_mux, "| buffer_dts - pcr_pts | > 2s ("I64Fd") empting "
802 "pcr TS buffers", p_sys->i_dts + p_sys->i_length - i_dts);
804 sout_BufferDelete( p_mux->p_sout, p_data );
806 while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )
808 sout_BufferDelete( p_mux->p_sout, p_data );
810 while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )
812 sout_BufferDelete( p_mux->p_sout, p_data );
817 if( i_dts >= p_sys->i_dts )
822 msg_Dbg( p_mux, "dropping buffer size=%d dts="I64Fd" pcr_dts="I64Fd
823 " diff="I64Fd, p_data->i_size, i_dts, p_sys->i_dts,
824 p_sys->i_dts + p_sys->i_length - i_dts );
825 sout_BufferDelete( p_mux->p_sout, p_data );
828 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
830 BufferChainInit( &p_stream->chain_ts );
831 PEStoTS( p_mux->p_sout, &p_stream->chain_ts, p_data, p_stream, b_pcr );
833 TSSetDate( &p_stream->chain_ts, i_dts, i_length, 0 );
835 if( b_pcr_soft && p_stream->chain_ts.p_first )
837 p_stream->chain_ts.p_first->i_flags=SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT;
843 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 )
845 sout_mux_sys_t *p_sys = p_mux->p_sys;
846 sout_buffer_chain_t s = *c;
849 int i_packets_min = 0;
850 int i_packets_max = 0;
857 i_packets = c->i_depth;
858 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
859 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
861 if( i_packets < i_packets_min && i_packets_min > 0 )
864 int i_div = ( i_packets_min - i_packets ) / i_packets;
865 int i_mod = ( i_packets_min - i_packets ) % i_packets;
868 /* We need to pad with null packets (pid=0x1fff)
869 * We try to melt null packets with true packets */
871 "packets=%d but min=%d -> adding %d packets of padding",
872 i_packets, i_packets_min, i_packets_min - i_packets );
874 BufferChainInit( c );
875 while( ( p_pk = BufferChainGet( &s ) ) )
879 BufferChainAppend( c, p_pk );
881 i_null = i_div + ( i_rest + i_mod ) / i_packets;
883 for( i = 0; i < i_null; i++ )
885 sout_buffer_t *p_null;
887 p_null = sout_BufferNew( p_mux->p_sout, 188 );
888 p_null->p_buffer[0] = 0x47;
889 p_null->p_buffer[1] = 0x1f;
890 p_null->p_buffer[2] = 0xff;
891 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
892 memset( &p_null->p_buffer[4], 0, 184 );
893 p_sys->i_null_continuity_counter =
894 ( p_sys->i_null_continuity_counter + 1 ) % 16;
896 BufferChainAppend( c, p_null );
899 i_rest = ( i_rest + i_mod ) % i_packets;
902 else if( i_packets > i_packets_max && i_packets_max > 0 )
907 /* Arg, we need to drop packets, I don't do something clever (like
908 * dropping complete pid, b frames, ... ), I just get the right amount
909 * of packets and discard the others */
911 "packets=%d but max=%d -> removing %d packets -> stream broken",
912 i_packets, i_packets_max, i_packets - i_packets_max );
914 BufferChainInit( c );
915 for( i = 0; i < i_packets_max; i++ )
917 BufferChainAppend( c, BufferChainGet( &s ) );
920 while( ( p_pk = BufferChainGet( &s ) ) )
922 sout_BufferDelete( p_mux->p_sout, p_pk );
927 static void TSSetDate( sout_buffer_chain_t *c,
928 mtime_t i_dts, mtime_t i_length, mtime_t i_send_offset )
931 mtime_t i_delta = i_length / c->i_depth;
934 for( p_ts = c->p_first; p_ts != NULL; p_ts = p_ts->p_next )
936 p_ts->i_dts = i_dts + i_packet * i_length / c->i_depth; /* avoid rounding error */
937 p_ts->i_length = i_delta;
939 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR_SOFT )
941 mtime_t i_pcr = 9 * p_ts->i_dts / 100;
943 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
944 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
945 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
946 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
947 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
949 p_ts->i_dts += i_send_offset;
955 static void PEStoTS( sout_instance_t *p_sout,
956 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
957 ts_stream_t *p_stream,
964 /* get PES total size */
965 i_size = p_pes->i_size;
966 p_data = p_pes->p_buffer;
968 /* Set pcr only with valid DTS */
969 if( p_pes->i_dts <= 0 )
974 b_new_pes = VLC_TRUE;
978 int b_adaptation_field;
983 p_ts = sout_BufferNew( p_sout, 188 );
986 * 1b transport_error_indicator
987 * 1b payload_unit_start
988 * 1b transport_priority
990 * 2b transport_scrambling_control
991 * 2b if adaptation_field 0x03 else 0x01
992 * 4b continuity_counter
995 i_payload = 184 - ( b_pcr ? 8 : 0 );
996 i_copy = __MIN( i_size, i_payload );
997 b_adaptation_field = (b_pcr||i_size<i_payload) ? VLC_TRUE : VLC_FALSE;
999 p_ts->p_buffer[0] = 0x47;
1000 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
1001 ( ( p_stream->i_pid >> 8 )&0x1f );
1002 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
1003 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
1004 p_stream->i_continuity_counter;
1006 b_new_pes = VLC_FALSE;
1007 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
1009 if( b_adaptation_field )
1015 mtime_t i_pcr = p_pes->i_dts * 9 / 100;
1016 int i_stuffing = i_payload - i_copy;
1018 p_ts->p_buffer[4] = 7 + i_stuffing;
1019 p_ts->p_buffer[5] = 0x10; /* flags */
1020 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
1021 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
1022 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
1023 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
1024 p_ts->p_buffer[10]= ( i_pcr << 7 )&0x80;
1025 p_ts->p_buffer[11]= 0;
1028 for( i = 12; i < 12 + i_stuffing; i++ )
1030 p_ts->p_buffer[i] = 0xff;
1035 int i_stuffing = i_payload - i_copy;
1037 p_ts->p_buffer[4] = i_stuffing - 1;
1038 if( i_stuffing > 1 )
1040 p_ts->p_buffer[5] = 0x00;
1041 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1043 p_ts->p_buffer[i] = 0xff;
1049 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1053 BufferChainAppend( c, p_ts );
1057 sout_buffer_t *p_next = p_pes->p_next;
1059 p_pes->p_next = NULL;
1060 sout_BufferDelete( p_sout, p_pes );
1061 if( p_next == NULL )
1065 b_new_pes = VLC_TRUE;
1067 i_size = p_pes->i_size;
1068 p_data = p_pes->p_buffer;
1075 #if defined MODULE_NAME_IS_mux_ts
1076 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1078 static uint32_t CRC32[256] =
1080 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1081 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1082 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1083 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1084 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1085 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1086 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1087 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1088 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1089 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1090 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1091 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1092 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1093 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1094 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1095 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1096 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1097 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1098 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1099 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1100 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1101 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1102 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1103 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1104 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1105 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1106 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1107 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1108 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1109 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1110 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1111 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1112 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1113 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1114 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1115 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1116 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1117 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1118 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1119 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1120 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1121 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1122 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1123 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1124 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1125 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1126 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1127 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1128 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1129 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1130 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1131 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1132 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1133 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1134 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1135 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1136 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1137 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1138 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1139 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1140 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1141 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1142 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1143 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1146 uint32_t i_crc = 0xffffffff;
1148 /* Calculate the CRC */
1149 while( i_count > 0 )
1151 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1159 static void GetPAT( sout_mux_t *p_mux,
1160 sout_buffer_chain_t *c )
1162 sout_mux_sys_t *p_sys = p_mux->p_sys;
1163 sout_buffer_t *p_pat;
1166 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1170 p_pat->i_length = 0;
1172 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1174 bits_write( &bits, 8, 0 ); // pointer
1175 bits_write( &bits, 8, 0x00 ); // table id
1176 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1177 bits_write( &bits, 1, 0 ); // 0
1178 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1179 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1180 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1181 bits_write( &bits, 2, 0x03 ); // FIXME
1182 bits_write( &bits, 5, p_sys->i_pat_version_number );
1183 bits_write( &bits, 1, 1 ); // current_next_indicator
1184 bits_write( &bits, 8, 0 ); // section number
1185 bits_write( &bits, 8, 0 ); // last section number
1187 bits_write( &bits, 16, 1 ); // program number
1188 bits_write( &bits, 3, 0x07 ); // reserved
1189 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1191 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1193 p_pat->i_size = bits.i_data;
1195 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1198 static void GetPMT( sout_mux_t *p_mux,
1199 sout_buffer_chain_t *c )
1201 sout_mux_sys_t *p_sys = p_mux->p_sys;
1202 sout_buffer_t *p_pmt;
1206 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1210 p_pmt->i_length = 0;
1212 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1214 bits_write( &bits, 8, 0 ); // pointer
1215 bits_write( &bits, 8, 0x02 ); // table id
1216 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1217 bits_write( &bits, 1, 0 ); // 0
1218 bits_write( &bits, 2, 0 ); // reserved FIXME
1219 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1220 bits_write( &bits, 16, 1 ); // FIXME program number
1221 bits_write( &bits, 2, 0 ); // FIXME
1222 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1223 bits_write( &bits, 1, 1 ); // current_next_indicator
1224 bits_write( &bits, 8, 0 ); // section number
1225 bits_write( &bits, 8, 0 ); // last section number
1227 bits_write( &bits, 3, 0 ); // reserved
1229 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1230 bits_write( &bits, 4, 0 ); // reserved FIXME
1232 bits_write( &bits, 12, 0 ); // program info len FIXME
1234 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1236 ts_stream_t *p_stream;
1238 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1240 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1241 bits_write( &bits, 3, 0 ); // reserved
1242 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1243 bits_write( &bits, 4, 0 ); //reserved
1244 bits_write( &bits, 12, 0 ); // es info len FIXME
1247 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1249 p_pmt->i_size = bits.i_data;
1251 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1253 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1255 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1256 dvbpsi_psi_section_t* p_section )
1258 sout_buffer_t *p_psi, *p_first = NULL;
1265 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1266 ( p_section->b_syntax_indicator ? 4 : 0 );
1268 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1271 p_psi->i_length = 0;
1272 p_psi->i_size = i_size + 1;
1274 p_psi->p_buffer[0] = 0; // pointer
1275 memcpy( p_psi->p_buffer + 1,
1279 sout_BufferChain( &p_first, p_psi );
1281 p_section = p_section->p_next;
1287 static void GetPAT( sout_mux_t *p_mux,
1288 sout_buffer_chain_t *c )
1290 sout_mux_sys_t *p_sys = p_mux->p_sys;
1291 sout_buffer_t *p_pat;
1293 dvbpsi_psi_section_t *p_section;
1295 dvbpsi_InitPAT( &pat,
1297 p_sys->i_pat_version_number,
1298 1 ); // b_current_next
1299 /* add all program (only one) */
1300 dvbpsi_PATAddProgram( &pat,
1302 p_sys->pmt.i_pid ); // i_pid
1304 p_section = dvbpsi_GenPATSections( &pat,
1305 0 ); // max program per section
1307 p_pat = WritePSISection( p_mux->p_sout, p_section );
1309 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat, VLC_FALSE );
1311 dvbpsi_DeletePSISections( p_section );
1312 dvbpsi_EmptyPAT( &pat );
1315 static uint32_t GetDescriptorLength24b( int i_length )
1317 uint32_t i_l1, i_l2, i_l3;
1319 i_l1 = i_length&0x7f;
1320 i_l2 = ( i_length >> 7 )&0x7f;
1321 i_l3 = ( i_length >> 14 )&0x7f;
1323 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1326 static void GetPMT( sout_mux_t *p_mux,
1327 sout_buffer_chain_t *c )
1329 sout_mux_sys_t *p_sys = p_mux->p_sys;
1330 sout_buffer_t *p_pmt;
1333 dvbpsi_pmt_es_t *p_es;
1334 dvbpsi_psi_section_t *p_section;
1338 dvbpsi_InitPMT( &pmt,
1339 0x01, // program number
1340 p_sys->i_pmt_version_number,
1341 1, // b_current_next
1344 if( p_sys->i_mpeg4_streams > 0 )
1348 bits_buffer_t bits_fix_IOD;
1350 /* Make valgrind happy : it works at byte level not bit one so
1351 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
1352 * working (needed when fixing some bits) */
1353 memset( iod, 0, 4096 );
1355 bits_initwrite( &bits, 4096, iod );
1357 bits_write( &bits, 8, 0x01 );
1358 // InitialObjectDescriptor
1359 bits_align( &bits );
1360 bits_write( &bits, 8, 0x02 ); // tag
1361 bits_fix_IOD = bits; // save states to fix length later
1362 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1363 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1364 bits_write( &bits, 1, 0x00 ); // URL Flag
1365 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1366 bits_write( &bits, 4, 0x0f ); // reserved
1367 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1368 bits_write( &bits, 8, 0xff ); // sceneProfile
1369 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1370 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1371 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1372 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1374 ts_stream_t *p_stream;
1375 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1377 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1379 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1381 bits_align( &bits );
1382 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1383 bits_fix_ESDescr = bits;
1384 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1385 bits_write( &bits, 16, p_stream->i_es_id );
1386 bits_write( &bits, 1, 0x00 ); // streamDependency
1387 bits_write( &bits, 1, 0x00 ); // URL Flag
1388 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1389 bits_write( &bits, 5, 0x1f ); // streamPriority
1391 // DecoderConfigDesciptor
1392 bits_align( &bits );
1393 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1394 bits_fix_Decoder = bits;
1395 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1396 if( p_stream->i_stream_type == 0x10 )
1398 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1399 bits_write( &bits, 6, 0x04 ); // VisualStream
1401 else if( p_stream->i_stream_type == 0x11 )
1403 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1404 bits_write( &bits, 6, 0x05 ); // AudioStream
1408 bits_write( &bits, 8, 0x00 );
1409 bits_write( &bits, 6, 0x00 );
1411 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1413 bits_write( &bits, 1, 0x00 ); // UpStream
1414 bits_write( &bits, 1, 0x01 ); // reserved
1415 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1416 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1417 bits_write( &bits, 32, 0 ); // avgBitrate
1419 if( p_stream->i_decoder_specific_info > 0 )
1422 // DecoderSpecificInfo
1423 bits_align( &bits );
1424 bits_write( &bits, 8, 0x05 ); // tag
1425 bits_write( &bits, 24,
1426 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1427 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1429 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1432 /* fix Decoder length */
1433 bits_write( &bits_fix_Decoder, 24,
1434 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1436 /* SLConfigDescriptor : predifined (0x01) */
1437 bits_align( &bits );
1438 bits_write( &bits, 8, 0x06 ); // tag
1439 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1440 bits_write( &bits, 8, 0x01 ); // predefined
1441 bits_write( &bits, 1, 0 ); // durationFlag
1442 bits_write( &bits, 32, 0 ); // OCRResolution
1443 bits_write( &bits, 8, 0 ); // OCRLength
1444 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1445 bits_align( &bits );
1447 /* fix ESDescr length */
1448 bits_write( &bits_fix_ESDescr, 24,
1449 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1452 bits_align( &bits );
1453 /* fix IOD length */
1454 bits_write( &bits_fix_IOD, 24,
1455 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1456 dvbpsi_PMTAddDescriptor( &pmt,
1462 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1464 ts_stream_t *p_stream;
1466 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1468 p_es = dvbpsi_PMTAddES( &pmt,
1469 p_stream->i_stream_type,
1471 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1476 es_id[0] = (p_stream->i_es_id >> 8)&0xff;
1477 es_id[1] = (p_stream->i_es_id)&0xff;
1478 dvbpsi_PMTESAddDescriptor( p_es, 0x1f, 2, es_id );
1480 else if( p_stream->i_stream_type == 0xa0 )
1483 int i_extra = __MIN( p_stream->i_decoder_specific_info,
1486 /* private DIV3 descripor */
1487 memcpy( &data[0], &p_stream->i_bih_codec, 4 );
1488 data[4] = ( p_stream->i_bih_width >> 8 )&&0xff;
1489 data[5] = ( p_stream->i_bih_width )&&0xff;
1490 data[6] = ( p_stream->i_bih_height>> 8 )&&0xff;
1491 data[7] = ( p_stream->i_bih_height )&&0xff;
1492 data[8] = ( i_extra >> 8 )&&0xff;
1493 data[9] = ( i_extra )&&0xff;
1496 memcpy( &data[10], p_stream->p_decoder_specific_info, i_extra );
1499 /* 0xa0 is private */
1500 dvbpsi_PMTESAddDescriptor( p_es, 0xa0, i_extra + 10, data );
1502 else if( p_stream->i_stream_type == 0x81 )
1504 uint8_t format[4] = { 0x41, 0x43, 0x2d, 0x33 };
1506 /* "registration" descriptor : "AC-3" */
1507 dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
1511 p_section = dvbpsi_GenPMTSections( &pmt );
1513 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1515 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt, VLC_FALSE );
1517 dvbpsi_DeletePSISections( p_section );
1518 dvbpsi_EmptyPMT( &pmt );