1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.40 2003/11/27 19:39:53 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 ( 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;
148 static inline void BufferChainClean( sout_instance_t *p_sout, sout_buffer_chain_t *c )
152 while( ( b = BufferChainGet( c ) ) )
154 sout_BufferDelete( p_sout, b );
156 BufferChainInit( c );
159 typedef struct ts_stream_s
164 int i_continuity_counter;
166 /* to be used for carriege of DIV3 */
167 vlc_fourcc_t i_bih_codec;
168 int i_bih_width, i_bih_height;
170 /* Specific to mpeg4 in mpeg2ts */
173 int i_decoder_specific_info;
174 uint8_t *p_decoder_specific_info;
176 sout_buffer_chain_t chain_pes;
178 mtime_t i_pes_length;
183 struct sout_mux_sys_t
186 sout_input_t *p_pcr_input;
193 int i_pid_free; // first usable pid
195 int i_pat_version_number;
198 int i_pmt_version_number;
199 ts_stream_t pmt; // Up to now only one program
203 int i_null_continuity_counter; /* Needed ? */
205 /* for TS building */
206 int64_t i_bitrate_min;
207 int64_t i_bitrate_max;
209 int64_t i_caching_delay;
214 mtime_t i_pcr; /* last PCR emited */
218 /* Reserve a pid and return it */
219 static int AllocatePID( sout_mux_sys_t *p_sys, int i_cat )
222 if ( i_cat == VIDEO_ES && p_sys->i_pid_video )
224 i_pid = p_sys->i_pid_video;
225 p_sys->i_pid_video = 0;
227 else if ( i_cat == AUDIO_ES && p_sys->i_pid_audio )
229 i_pid = p_sys->i_pid_audio;
230 p_sys->i_pid_audio = 0;
234 i_pid = ++p_sys->i_pid_free;
239 static void GetPAT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
240 static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
242 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr );
243 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts );
245 static void PEStoTS ( sout_instance_t *, sout_buffer_chain_t *, sout_buffer_t *, ts_stream_t * );
247 /*****************************************************************************
249 *****************************************************************************/
250 static int Open( vlc_object_t *p_this )
252 sout_mux_t *p_mux =(sout_mux_t*)p_this;
253 sout_mux_sys_t *p_sys;
256 msg_Dbg( p_mux, "Open" );
258 p_sys = malloc( sizeof( sout_mux_sys_t ) );
260 p_mux->pf_capacity = Capability;
261 p_mux->pf_addstream = AddStream;
262 p_mux->pf_delstream = DelStream;
264 p_mux->p_sys = p_sys;
265 p_mux->i_preheader = 30; // really enough for a pes header
267 srand( (uint32_t)mdate() );
269 p_sys->i_audio_bound = 0;
270 p_sys->i_video_bound = 0;
272 p_sys->i_pat_version_number = rand() % 32;
273 p_sys->pat.i_pid = 0;
274 p_sys->pat.i_continuity_counter = 0;
276 p_sys->i_pmt_version_number = rand() % 32;
277 p_sys->pmt.i_pid = 0x42;
278 p_sys->pmt.i_continuity_counter = 0;
280 p_sys->i_pid_free = 0x43;
282 p_sys->i_pid_video = 0;
283 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) )
285 p_sys->i_pid_video = strtol( val, NULL, 0 );
286 if ( p_sys->i_pid_video > p_sys->i_pid_free )
288 p_sys->i_pid_free = p_sys->i_pid_video + 1;
291 p_sys->i_pid_audio = 0;
292 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) )
294 p_sys->i_pid_audio = strtol( val, NULL, 0 );
295 if ( p_sys->i_pid_audio > p_sys->i_pid_free )
297 p_sys->i_pid_free = p_sys->i_pid_audio + 1;
301 p_sys->i_pcr_pid = 0x1fff;
302 p_sys->p_pcr_input = NULL;
304 p_sys->i_mpeg4_streams = 0;
306 p_sys->i_null_continuity_counter = 0;
308 /* Allow to create constrained stream */
309 p_sys->i_bitrate_min = 0;
310 p_sys->i_bitrate_max = 0;
311 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmin" ) ) )
313 p_sys->i_bitrate_min = atoll( val );
315 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmax" ) ) )
317 p_sys->i_bitrate_max = atoll( val );
319 if( p_sys->i_bitrate_min > 0 && p_sys->i_bitrate_max > 0 &&
320 p_sys->i_bitrate_min > p_sys->i_bitrate_max )
322 msg_Err( p_mux, "incompatible minimum and maximum bitrate, "
323 "disabling bitrate control" );
324 p_sys->i_bitrate_min = 0;
325 p_sys->i_bitrate_max = 0;
327 if( p_sys->i_bitrate_min > 0 || p_sys->i_bitrate_max > 0 )
329 msg_Err( p_mux, "bmin and bmax no more supported (if you need them report it)" );
332 p_sys->i_caching_delay = 200000;
333 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "caching" ) ) )
335 p_sys->i_caching_delay = (int64_t)atoi( val ) * 1000;
336 if( p_sys->i_caching_delay <= 0 )
339 "invalid caching ("I64Fd"ms) reseting to 200ms",
340 p_sys->i_caching_delay / 1000 );
341 p_sys->i_caching_delay = 200000;
344 p_sys->i_pcr_delay = 30000;
345 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr" ) ) )
347 p_sys->i_pcr_delay = (int64_t)atoi( val ) * 1000;
348 if( p_sys->i_pcr_delay <= 0 ||
349 p_sys->i_pcr_delay >= p_sys->i_caching_delay )
352 "invalid pcr delay ("I64Fd"ms) reseting to 30ms",
353 p_sys->i_pcr_delay / 1000 );
354 p_sys->i_pcr_delay = 30000;
358 msg_Dbg( p_mux, "caching="I64Fd" pcr="I64Fd,
359 p_sys->i_caching_delay, p_sys->i_pcr_delay );
361 p_sys->i_dts_delay = 200000;
362 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "dts-delay" ) ) )
364 p_sys->i_dts_delay = (int64_t)atoi( val ) * 1000;
367 /* for TS generation */
372 /*****************************************************************************
374 *****************************************************************************/
375 static void Close( vlc_object_t * p_this )
377 sout_mux_t *p_mux = (sout_mux_t*)p_this;
378 sout_mux_sys_t *p_sys = p_mux->p_sys;
380 msg_Dbg( p_mux, "Close" );
385 /*****************************************************************************
387 *****************************************************************************/
388 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
392 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
393 *(vlc_bool_t*)p_answer = VLC_TRUE;
394 return( SOUT_MUX_CAP_ERR_OK );
396 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
400 /*****************************************************************************
401 * AddStream: called for each stream addition
402 *****************************************************************************/
403 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
405 sout_mux_sys_t *p_sys = p_mux->p_sys;
406 ts_stream_t *p_stream;
408 msg_Dbg( p_mux, "adding input codec=%4.4s", (char*)&p_input->p_fmt->i_codec );
410 p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
412 /* Init this new stream */
413 p_stream->i_pid = AllocatePID( p_sys, p_input->p_fmt->i_cat );
414 p_stream->i_continuity_counter = 0;
415 p_stream->i_decoder_specific_info = 0;
416 p_stream->p_decoder_specific_info = NULL;
418 /* All others fields depand on codec */
419 switch( p_input->p_fmt->i_cat )
422 switch( p_input->p_fmt->i_codec )
424 case VLC_FOURCC( 'm', 'p','g', 'v' ):
425 /* TODO: do we need to check MPEG-I/II ? */
426 p_stream->i_stream_type = 0x02;
427 p_stream->i_stream_id = 0xe0;
429 case VLC_FOURCC( 'm', 'p','4', 'v' ):
430 p_stream->i_stream_type = 0x10;
431 p_stream->i_stream_id = 0xfa;
432 p_sys->i_mpeg4_streams++;
433 p_stream->i_es_id = p_stream->i_pid;
435 /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
436 /* I didn't want to do that :P */
437 case VLC_FOURCC( 'H', '2', '6', '3' ):
438 case VLC_FOURCC( 'I', '2', '6', '3' ):
439 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
440 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
441 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
442 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
443 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
444 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
445 p_stream->i_stream_type = 0xa0; // private
446 p_stream->i_stream_id = 0xa0; // beurk
447 p_stream->i_bih_codec = p_input->p_fmt->i_codec;
448 p_stream->i_bih_width = p_input->p_fmt->video.i_width;
449 p_stream->i_bih_height = p_input->p_fmt->video.i_height;
455 p_sys->i_video_bound++;
459 switch( p_input->p_fmt->i_codec )
461 case VLC_FOURCC( 'm', 'p','g', 'a' ):
462 p_stream->i_stream_type = p_input->p_fmt->audio.i_rate >= 32000 ? 0x03 : 0x04;
463 p_stream->i_stream_id = 0xc0;
465 case VLC_FOURCC( 'a', '5','2', ' ' ):
466 p_stream->i_stream_type = 0x81;
467 p_stream->i_stream_id = 0xbd;
469 case VLC_FOURCC( 'l', 'p','c', 'm' ):
470 p_stream->i_stream_type = 0x83;
471 p_stream->i_stream_id = 0xbd;
473 case VLC_FOURCC( 'd', 't','s', ' ' ):
474 p_stream->i_stream_type = 0x85;
475 p_stream->i_stream_id = 0xbd;
478 case VLC_FOURCC( 'm', 'p','4', 'a' ):
479 p_stream->i_stream_type = 0x11;
480 p_stream->i_stream_id = 0xfa;
481 p_sys->i_mpeg4_streams++;
482 p_stream->i_es_id = p_stream->i_pid;
488 p_sys->i_audio_bound++;
492 switch( p_input->p_fmt->i_codec )
494 case VLC_FOURCC( 's', 'p','u', ' ' ):
495 p_stream->i_stream_type = 0x82;
496 p_stream->i_stream_id = 0xbd;
509 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
510 p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra;
511 if( p_stream->i_decoder_specific_info > 0 )
513 p_stream->p_decoder_specific_info =
514 malloc( p_stream->i_decoder_specific_info );
515 memcpy( p_stream->p_decoder_specific_info,
516 p_input->p_fmt->p_extra,
517 p_input->p_fmt->i_extra );
521 BufferChainInit( &p_stream->chain_pes );
522 p_stream->i_pes_dts = 0;
523 p_stream->i_pes_length = 0;
524 p_stream->i_pes_used = 0;
526 /* We only change PMT version (PAT isn't changed) */
527 p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
530 if( p_input->p_fmt->i_cat != SPU_ES &&
531 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
533 if( p_sys->p_pcr_input )
535 /* There was already a PCR stream, so clean context */
538 p_sys->i_pcr_pid = p_stream->i_pid;
539 p_sys->p_pcr_input = p_input;
545 /*****************************************************************************
546 * DelStream: called before a stream deletion
547 *****************************************************************************/
548 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
550 sout_mux_sys_t *p_sys = p_mux->p_sys;
551 ts_stream_t *p_stream;
554 msg_Dbg( p_mux, "removing input" );
555 p_stream = (ts_stream_t*)p_input->p_sys;
557 if( p_sys->i_pcr_pid == p_stream->i_pid )
561 /* Find a new pcr stream (Prefer Video Stream) */
562 p_sys->i_pcr_pid = 0x1fff;
563 p_sys->p_pcr_input = NULL;
564 for( i = 0; i < p_mux->i_nb_inputs; i++ )
566 if( p_mux->pp_inputs[i] == p_input )
571 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
574 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
575 p_sys->p_pcr_input= p_mux->pp_inputs[i];
578 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
579 p_sys->i_pcr_pid == 0x1fff )
582 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
583 p_sys->p_pcr_input= p_mux->pp_inputs[i];
586 if( p_sys->p_pcr_input )
588 /* Empty TS buffer */
593 /* Empty all data in chain_pes */
594 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
596 if( p_stream->p_decoder_specific_info )
598 free( p_stream->p_decoder_specific_info );
600 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
602 p_sys->i_mpeg4_streams--;
604 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) )
606 int i_pid_video = strtol( val, NULL, 0 );
607 if ( i_pid_video == p_stream->i_pid )
609 p_sys->i_pid_video = i_pid_video;
612 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) )
614 int i_pid_audio = strtol( val, NULL, 0 );
615 if ( i_pid_audio == p_stream->i_pid )
617 p_sys->i_pid_audio = i_pid_audio;
622 /* We only change PMT version (PAT isn't changed) */
623 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
628 /*****************************************************************************
629 * Mux: Call each time there is new data for at least one stream
630 *****************************************************************************
632 *****************************************************************************/
633 static int Mux( sout_mux_t *p_mux )
635 sout_mux_sys_t *p_sys = p_mux->p_sys;
636 ts_stream_t *p_pcr_stream;
638 if( p_sys->i_pcr_pid == 0x1fff )
640 msg_Dbg( p_mux, "waiting PCR streams" );
644 p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
648 sout_buffer_chain_t chain_ts;
652 mtime_t i_pcr_length;
655 /* 1: get enough PES packet for all input */
658 vlc_bool_t b_ok = VLC_TRUE;
659 sout_buffer_t *p_data;
661 /* Accumulate enough data in the pcr stream (>i_caching_delay) */
662 /* Accumulate enough data in all other stream ( >= length of pcr) */
663 for( i = 0; i < p_mux->i_nb_inputs; i++ )
665 sout_input_t *p_input = p_mux->pp_inputs[i];
666 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
668 if( ( p_stream == p_pcr_stream && p_stream->i_pes_length <= p_sys->i_caching_delay ) ||
669 p_stream->i_pes_dts + p_stream->i_pes_length < p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
672 if( p_input->p_fifo->i_depth <= 1 )
674 if( p_input->p_fmt->i_cat == AUDIO_ES ||
675 p_input->p_fmt->i_cat == VIDEO_ES )
677 /* We need more data */
680 else if( p_input->p_fifo->i_depth <= 0 )
682 /* spu, only one packet is needed */
688 p_data = sout_FifoGet( p_input->p_fifo );
689 if( p_input->p_fifo->i_depth > 0 )
691 sout_buffer_t *p_next = sout_FifoShow( p_input->p_fifo );
693 p_data->i_length = p_next->i_dts - p_data->i_dts;
696 if( ( p_pcr_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length ) ||
697 p_data->i_dts < p_stream->i_pes_dts ||
698 ( p_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > p_stream->i_pes_dts + p_stream->i_pes_length ) )
700 msg_Warn( p_mux, "packet with too strange dts (dts=%lld,old=%lld,pcr=%lld)",
703 p_pcr_stream->i_pes_dts );
704 sout_BufferDelete( p_mux->p_sout, p_data );
706 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
707 p_stream->i_pes_dts = 0;
708 p_stream->i_pes_used = 0;
709 p_stream->i_pes_length = 0;
711 BufferChainClean( p_mux->p_sout, &p_pcr_stream->chain_pes );
712 p_pcr_stream->i_pes_dts = 0;
713 p_pcr_stream->i_pes_used = 0;
714 p_pcr_stream->i_pes_length = 0;
719 p_stream->i_pes_length += p_data->i_length;
720 if( p_stream->i_pes_dts == 0 )
722 p_stream->i_pes_dts = p_data->i_dts;
726 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1 );
728 BufferChainAppend( &p_stream->chain_pes, p_data );
740 i_pcr_dts = p_pcr_stream->i_pes_dts;
741 i_pcr_length = p_pcr_stream->i_pes_length;
743 /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */
744 /* 2: calculate non accurate total size of muxed ts */
746 for( i = 0; i < p_mux->i_nb_inputs; i++ )
748 ts_stream_t *p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
749 sout_buffer_t *p_pes;
751 /* False for pcr stream but it will be eough to do PCR algo */
752 for( p_pes = p_stream->chain_pes.p_first; p_pes != NULL; p_pes = p_pes->p_next )
754 int i_size = p_pes->i_size;
755 if( p_pes->i_dts + p_pes->i_length > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
757 mtime_t i_frag = p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length - p_pes->i_dts;
763 i_size = p_pes->i_size * i_frag / p_pes->i_length;
765 i_packet_count += ( i_size + 183 ) / 184;
768 /* add overhead for PCR (not really exact) */
769 i_packet_count += ( 8 * i_pcr_length / p_sys->i_pcr_delay + 175 ) / 176;
772 /* 3: mux PES into TS */
773 BufferChainInit( &chain_ts );
774 /* append PAT/PMT -> FIXME with big pcr delay it won't have enough pat/pmt */
775 GetPAT( p_mux, &chain_ts);
776 GetPMT( p_mux, &chain_ts );
778 i_packet_count += chain_ts.i_depth;
779 /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */
785 ts_stream_t *p_stream;
789 /* Select stream (lowest dts)*/
790 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
792 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
794 if( p_stream->i_pes_dts == 0 )
799 if( i_stream == -1 ||
800 p_stream->i_pes_dts < i_dts )
803 i_dts = p_stream->i_pes_dts;
810 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
812 /* do we need to issue pcr */
814 if( p_stream == p_pcr_stream &&
815 i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count >= p_sys->i_pcr + p_sys->i_pcr_delay )
818 p_sys->i_pcr = i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count;
821 /* Build the TS packet */
822 p_ts = TSNew( p_mux, p_stream, b_pcr );
826 BufferChainAppend( &chain_ts, p_ts );
829 /* 4: date and send */
830 i_packet_count = chain_ts.i_depth;
831 /* msg_Dbg( p_mux, "real pck=%d", i_packet_count ); */
832 for( i = 0; i < i_packet_count; i++ )
834 sout_buffer_t *p_ts = BufferChainGet( &chain_ts );
836 p_ts->i_dts = i_pcr_dts + i_pcr_length * i / i_packet_count;
837 p_ts->i_length = i_pcr_length / i_packet_count;
839 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR )
841 /* msg_Dbg( p_mux, "pcr=%lld ms", p_ts->i_dts / 1000 ); */
842 TSSetPCR( p_ts, p_ts->i_dts - p_sys->i_dts_delay );
846 p_ts->i_dts += 3*p_sys->i_caching_delay/2;
848 sout_AccessOutWrite( p_mux->p_access, p_ts );
853 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr )
855 sout_buffer_t *p_pes = p_stream->chain_pes.p_first;
858 vlc_bool_t b_new_pes = VLC_FALSE;
859 vlc_bool_t b_adaptation_field = VLC_FALSE;
861 int i_payload_max = 184 - ( b_pcr ? 8 : 0 );
864 if( p_stream->i_pes_used <= 0 )
866 b_new_pes = VLC_TRUE;
868 i_payload = __MIN( (int)p_pes->i_size - p_stream->i_pes_used, i_payload_max );
870 if( b_pcr || i_payload < i_payload_max )
872 b_adaptation_field = VLC_TRUE;
875 p_ts = sout_BufferNew( p_mux->p_sout, 188 );
877 p_ts->p_buffer[0] = 0x47;
878 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|( ( p_stream->i_pid >> 8 )&0x1f );
879 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
880 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|p_stream->i_continuity_counter;
882 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
884 if( b_adaptation_field )
890 int i_stuffing = i_payload_max - i_payload;
892 p_ts->i_flags |= SOUT_BUFFER_FLAGS_PRIVATE_PCR;
894 p_ts->p_buffer[4] = 7 + i_stuffing;
895 p_ts->p_buffer[5] = 0x10; /* flags */
896 p_ts->p_buffer[6] = ( 0 )&0xff;
897 p_ts->p_buffer[7] = ( 0 )&0xff;
898 p_ts->p_buffer[8] = ( 0 )&0xff;
899 p_ts->p_buffer[9] = ( 0 )&0xff;
900 p_ts->p_buffer[10]= ( 0 )&0x80;
901 p_ts->p_buffer[11]= 0;
903 for( i = 12; i < 12 + i_stuffing; i++ )
905 p_ts->p_buffer[i] = 0xff;
910 int i_stuffing = i_payload_max - i_payload;
912 p_ts->p_buffer[4] = i_stuffing - 1;
915 p_ts->p_buffer[5] = 0x00;
916 for( i = 6; i < 6 + i_stuffing - 2; i++ )
918 p_ts->p_buffer[i] = 0xff;
925 memcpy( &p_ts->p_buffer[188 - i_payload], &p_pes->p_buffer[p_stream->i_pes_used], i_payload );
927 p_stream->i_pes_used += i_payload;
928 p_stream->i_pes_dts = p_pes->i_dts + p_pes->i_length * p_stream->i_pes_used / p_pes->i_size;
929 p_stream->i_pes_length -= p_pes->i_length * i_payload / p_pes->i_size;
931 if( p_stream->i_pes_used >= (int)p_pes->i_size )
933 p_pes = BufferChainGet( &p_stream->chain_pes );
934 sout_BufferDelete( p_mux->p_sout, p_pes );
936 p_pes = p_stream->chain_pes.p_first;
939 p_stream->i_pes_dts = p_pes->i_dts;
940 p_stream->i_pes_length = 0;
943 p_stream->i_pes_length += p_pes->i_length;
945 p_pes = p_pes->p_next;
950 p_stream->i_pes_dts = 0;
951 p_stream->i_pes_length = 0;
953 p_stream->i_pes_used = 0;
960 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts )
962 mtime_t i_pcr = 9 * i_dts / 100;
964 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
965 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
966 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
967 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
968 p_ts->p_buffer[10]|= ( i_pcr << 7 )&0x80;
972 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 )
974 sout_mux_sys_t *p_sys = p_mux->p_sys;
975 sout_buffer_chain_t s = *c;
978 int i_packets_min = 0;
979 int i_packets_max = 0;
986 i_packets = c->i_depth;
987 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
988 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
990 if( i_packets < i_packets_min && i_packets_min > 0 )
993 int i_div = ( i_packets_min - i_packets ) / i_packets;
994 int i_mod = ( i_packets_min - i_packets ) % i_packets;
997 /* We need to pad with null packets (pid=0x1fff)
998 * We try to melt null packets with true packets */
1000 "packets=%d but min=%d -> adding %d packets of padding",
1001 i_packets, i_packets_min, i_packets_min - i_packets );
1003 BufferChainInit( c );
1004 while( ( p_pk = BufferChainGet( &s ) ) )
1008 BufferChainAppend( c, p_pk );
1010 i_null = i_div + ( i_rest + i_mod ) / i_packets;
1012 for( i = 0; i < i_null; i++ )
1014 sout_buffer_t *p_null;
1016 p_null = sout_BufferNew( p_mux->p_sout, 188 );
1017 p_null->p_buffer[0] = 0x47;
1018 p_null->p_buffer[1] = 0x1f;
1019 p_null->p_buffer[2] = 0xff;
1020 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
1021 memset( &p_null->p_buffer[4], 0, 184 );
1022 p_sys->i_null_continuity_counter =
1023 ( p_sys->i_null_continuity_counter + 1 ) % 16;
1025 BufferChainAppend( c, p_null );
1028 i_rest = ( i_rest + i_mod ) % i_packets;
1031 else if( i_packets > i_packets_max && i_packets_max > 0 )
1033 sout_buffer_t *p_pk;
1036 /* Arg, we need to drop packets, I don't do something clever (like
1037 * dropping complete pid, b frames, ... ), I just get the right amount
1038 * of packets and discard the others */
1040 "packets=%d but max=%d -> removing %d packets -> stream broken",
1041 i_packets, i_packets_max, i_packets - i_packets_max );
1043 BufferChainInit( c );
1044 for( i = 0; i < i_packets_max; i++ )
1046 BufferChainAppend( c, BufferChainGet( &s ) );
1049 while( ( p_pk = BufferChainGet( &s ) ) )
1051 sout_BufferDelete( p_mux->p_sout, p_pk );
1057 static void PEStoTS( sout_instance_t *p_sout,
1058 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
1059 ts_stream_t *p_stream )
1065 /* get PES total size */
1066 i_size = p_pes->i_size;
1067 p_data = p_pes->p_buffer;
1069 b_new_pes = VLC_TRUE;
1073 int b_adaptation_field;
1075 sout_buffer_t *p_ts;
1077 p_ts = sout_BufferNew( p_sout, 188 );
1080 * 1b transport_error_indicator
1081 * 1b payload_unit_start
1082 * 1b transport_priority
1084 * 2b transport_scrambling_control
1085 * 2b if adaptation_field 0x03 else 0x01
1086 * 4b continuity_counter
1089 i_copy = __MIN( i_size, 184 );
1090 b_adaptation_field = i_size < 184 ? VLC_TRUE : VLC_FALSE;
1092 p_ts->p_buffer[0] = 0x47;
1093 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
1094 ( ( p_stream->i_pid >> 8 )&0x1f );
1095 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
1096 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
1097 p_stream->i_continuity_counter;
1099 b_new_pes = VLC_FALSE;
1100 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
1102 if( b_adaptation_field )
1104 int i_stuffing = 184 - i_copy;
1107 p_ts->p_buffer[4] = i_stuffing - 1;
1108 if( i_stuffing > 1 )
1110 p_ts->p_buffer[5] = 0x00;
1111 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1113 p_ts->p_buffer[i] = 0xff;
1118 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1122 BufferChainAppend( c, p_ts );
1126 sout_buffer_t *p_next = p_pes->p_next;
1128 p_pes->p_next = NULL;
1129 sout_BufferDelete( p_sout, p_pes );
1130 if( p_next == NULL )
1134 b_new_pes = VLC_TRUE;
1136 i_size = p_pes->i_size;
1137 p_data = p_pes->p_buffer;
1144 #if defined MODULE_NAME_IS_mux_ts
1145 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1147 static uint32_t CRC32[256] =
1149 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1150 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1151 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1152 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1153 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1154 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1155 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1156 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1157 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1158 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1159 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1160 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1161 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1162 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1163 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1164 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1165 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1166 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1167 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1168 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1169 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1170 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1171 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1172 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1173 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1174 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1175 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1176 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1177 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1178 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1179 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1180 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1181 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1182 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1183 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1184 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1185 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1186 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1187 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1188 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1189 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1190 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1191 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1192 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1193 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1194 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1195 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1196 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1197 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1198 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1199 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1200 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1201 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1202 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1203 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1204 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1205 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1206 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1207 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1208 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1209 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1210 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1211 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1212 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1215 uint32_t i_crc = 0xffffffff;
1217 /* Calculate the CRC */
1218 while( i_count > 0 )
1220 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1228 static void GetPAT( sout_mux_t *p_mux,
1229 sout_buffer_chain_t *c )
1231 sout_mux_sys_t *p_sys = p_mux->p_sys;
1232 sout_buffer_t *p_pat;
1235 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1239 p_pat->i_length = 0;
1241 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1243 bits_write( &bits, 8, 0 ); // pointer
1244 bits_write( &bits, 8, 0x00 ); // table id
1245 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1246 bits_write( &bits, 1, 0 ); // 0
1247 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1248 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1249 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1250 bits_write( &bits, 2, 0x03 ); // FIXME
1251 bits_write( &bits, 5, p_sys->i_pat_version_number );
1252 bits_write( &bits, 1, 1 ); // current_next_indicator
1253 bits_write( &bits, 8, 0 ); // section number
1254 bits_write( &bits, 8, 0 ); // last section number
1256 bits_write( &bits, 16, 1 ); // program number
1257 bits_write( &bits, 3, 0x07 ); // reserved
1258 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1260 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1262 p_pat->i_size = bits.i_data;
1264 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1267 static void GetPMT( sout_mux_t *p_mux,
1268 sout_buffer_chain_t *c )
1270 sout_mux_sys_t *p_sys = p_mux->p_sys;
1271 sout_buffer_t *p_pmt;
1275 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1279 p_pmt->i_length = 0;
1281 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1283 bits_write( &bits, 8, 0 ); // pointer
1284 bits_write( &bits, 8, 0x02 ); // table id
1285 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1286 bits_write( &bits, 1, 0 ); // 0
1287 bits_write( &bits, 2, 0 ); // reserved FIXME
1288 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1289 bits_write( &bits, 16, 1 ); // FIXME program number
1290 bits_write( &bits, 2, 0 ); // FIXME
1291 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1292 bits_write( &bits, 1, 1 ); // current_next_indicator
1293 bits_write( &bits, 8, 0 ); // section number
1294 bits_write( &bits, 8, 0 ); // last section number
1296 bits_write( &bits, 3, 0 ); // reserved
1298 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1299 bits_write( &bits, 4, 0 ); // reserved FIXME
1301 bits_write( &bits, 12, 0 ); // program info len FIXME
1303 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1305 ts_stream_t *p_stream;
1307 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1309 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1310 bits_write( &bits, 3, 0 ); // reserved
1311 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1312 bits_write( &bits, 4, 0 ); //reserved
1313 bits_write( &bits, 12, 0 ); // es info len FIXME
1316 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1318 p_pmt->i_size = bits.i_data;
1320 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1322 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1324 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1325 dvbpsi_psi_section_t* p_section )
1327 sout_buffer_t *p_psi, *p_first = NULL;
1334 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1335 ( p_section->b_syntax_indicator ? 4 : 0 );
1337 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1340 p_psi->i_length = 0;
1341 p_psi->i_size = i_size + 1;
1343 p_psi->p_buffer[0] = 0; // pointer
1344 memcpy( p_psi->p_buffer + 1,
1348 sout_BufferChain( &p_first, p_psi );
1350 p_section = p_section->p_next;
1356 static void GetPAT( sout_mux_t *p_mux,
1357 sout_buffer_chain_t *c )
1359 sout_mux_sys_t *p_sys = p_mux->p_sys;
1360 sout_buffer_t *p_pat;
1362 dvbpsi_psi_section_t *p_section;
1364 dvbpsi_InitPAT( &pat,
1366 p_sys->i_pat_version_number,
1367 1 ); // b_current_next
1368 /* add all program (only one) */
1369 dvbpsi_PATAddProgram( &pat,
1371 p_sys->pmt.i_pid ); // i_pid
1373 p_section = dvbpsi_GenPATSections( &pat,
1374 0 ); // max program per section
1376 p_pat = WritePSISection( p_mux->p_sout, p_section );
1378 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1380 dvbpsi_DeletePSISections( p_section );
1381 dvbpsi_EmptyPAT( &pat );
1384 static uint32_t GetDescriptorLength24b( int i_length )
1386 uint32_t i_l1, i_l2, i_l3;
1388 i_l1 = i_length&0x7f;
1389 i_l2 = ( i_length >> 7 )&0x7f;
1390 i_l3 = ( i_length >> 14 )&0x7f;
1392 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1395 static void GetPMT( sout_mux_t *p_mux,
1396 sout_buffer_chain_t *c )
1398 sout_mux_sys_t *p_sys = p_mux->p_sys;
1399 sout_buffer_t *p_pmt;
1402 dvbpsi_pmt_es_t *p_es;
1403 dvbpsi_psi_section_t *p_section;
1407 dvbpsi_InitPMT( &pmt,
1408 0x01, // program number
1409 p_sys->i_pmt_version_number,
1410 1, // b_current_next
1413 if( p_sys->i_mpeg4_streams > 0 )
1417 bits_buffer_t bits_fix_IOD;
1419 /* Make valgrind happy : it works at byte level not bit one so
1420 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
1421 * working (needed when fixing some bits) */
1422 memset( iod, 0, 4096 );
1424 bits_initwrite( &bits, 4096, iod );
1426 bits_write( &bits, 8, 0x01 );
1427 // InitialObjectDescriptor
1428 bits_align( &bits );
1429 bits_write( &bits, 8, 0x02 ); // tag
1430 bits_fix_IOD = bits; // save states to fix length later
1431 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1432 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1433 bits_write( &bits, 1, 0x00 ); // URL Flag
1434 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1435 bits_write( &bits, 4, 0x0f ); // reserved
1436 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1437 bits_write( &bits, 8, 0xff ); // sceneProfile
1438 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1439 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1440 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1441 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1443 ts_stream_t *p_stream;
1444 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1446 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1448 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1450 bits_align( &bits );
1451 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1452 bits_fix_ESDescr = bits;
1453 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1454 bits_write( &bits, 16, p_stream->i_es_id );
1455 bits_write( &bits, 1, 0x00 ); // streamDependency
1456 bits_write( &bits, 1, 0x00 ); // URL Flag
1457 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1458 bits_write( &bits, 5, 0x1f ); // streamPriority
1460 // DecoderConfigDesciptor
1461 bits_align( &bits );
1462 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1463 bits_fix_Decoder = bits;
1464 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1465 if( p_stream->i_stream_type == 0x10 )
1467 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1468 bits_write( &bits, 6, 0x04 ); // VisualStream
1470 else if( p_stream->i_stream_type == 0x11 )
1472 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1473 bits_write( &bits, 6, 0x05 ); // AudioStream
1477 bits_write( &bits, 8, 0x00 );
1478 bits_write( &bits, 6, 0x00 );
1480 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1482 bits_write( &bits, 1, 0x00 ); // UpStream
1483 bits_write( &bits, 1, 0x01 ); // reserved
1484 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1485 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1486 bits_write( &bits, 32, 0 ); // avgBitrate
1488 if( p_stream->i_decoder_specific_info > 0 )
1491 // DecoderSpecificInfo
1492 bits_align( &bits );
1493 bits_write( &bits, 8, 0x05 ); // tag
1494 bits_write( &bits, 24,
1495 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1496 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1498 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1501 /* fix Decoder length */
1502 bits_write( &bits_fix_Decoder, 24,
1503 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1505 /* SLConfigDescriptor : predifined (0x01) */
1506 bits_align( &bits );
1507 bits_write( &bits, 8, 0x06 ); // tag
1508 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1509 bits_write( &bits, 8, 0x01 ); // predefined
1510 bits_write( &bits, 1, 0 ); // durationFlag
1511 bits_write( &bits, 32, 0 ); // OCRResolution
1512 bits_write( &bits, 8, 0 ); // OCRLength
1513 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1514 bits_align( &bits );
1516 /* fix ESDescr length */
1517 bits_write( &bits_fix_ESDescr, 24,
1518 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1521 bits_align( &bits );
1522 /* fix IOD length */
1523 bits_write( &bits_fix_IOD, 24,
1524 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1525 dvbpsi_PMTAddDescriptor( &pmt,
1531 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1533 ts_stream_t *p_stream;
1535 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1537 p_es = dvbpsi_PMTAddES( &pmt,
1538 p_stream->i_stream_type,
1540 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1545 es_id[0] = (p_stream->i_es_id >> 8)&0xff;
1546 es_id[1] = (p_stream->i_es_id)&0xff;
1547 dvbpsi_PMTESAddDescriptor( p_es, 0x1f, 2, es_id );
1549 else if( p_stream->i_stream_type == 0xa0 )
1552 int i_extra = __MIN( p_stream->i_decoder_specific_info,
1555 /* private DIV3 descripor */
1556 memcpy( &data[0], &p_stream->i_bih_codec, 4 );
1557 data[4] = ( p_stream->i_bih_width >> 8 )&0xff;
1558 data[5] = ( p_stream->i_bih_width )&0xff;
1559 data[6] = ( p_stream->i_bih_height>> 8 )&0xff;
1560 data[7] = ( p_stream->i_bih_height )&0xff;
1561 data[8] = ( i_extra >> 8 )&0xff;
1562 data[9] = ( i_extra )&0xff;
1565 memcpy( &data[10], p_stream->p_decoder_specific_info, i_extra );
1568 /* 0xa0 is private */
1569 dvbpsi_PMTESAddDescriptor( p_es, 0xa0, i_extra + 10, data );
1571 else if( p_stream->i_stream_type == 0x81 )
1573 uint8_t format[4] = { 0x41, 0x43, 0x2d, 0x33 };
1575 /* "registration" descriptor : "AC-3" */
1576 dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
1580 p_section = dvbpsi_GenPMTSections( &pmt );
1582 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1584 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1586 dvbpsi_DeletePSISections( p_section );
1587 dvbpsi_EmptyPMT( &pmt );