1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.41 2003/11/27 22:44:50 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 ( 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 p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
410 /* Init this new stream */
411 p_stream->i_pid = AllocatePID( p_sys, p_input->p_fmt->i_cat );
412 p_stream->i_continuity_counter = 0;
413 p_stream->i_decoder_specific_info = 0;
414 p_stream->p_decoder_specific_info = NULL;
416 msg_Dbg( p_mux, "adding input codec=%4.4s pid=%d", (char*)&p_input->p_fmt->i_codec, p_stream->i_pid );
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;
541 msg_Dbg( p_mux, "new PCR PID is %d", p_sys->i_pcr_pid );
547 /*****************************************************************************
548 * DelStream: called before a stream deletion
549 *****************************************************************************/
550 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
552 sout_mux_sys_t *p_sys = p_mux->p_sys;
553 ts_stream_t *p_stream;
556 p_stream = (ts_stream_t*)p_input->p_sys;
557 msg_Dbg( p_mux, "removing input pid=%d", p_stream->i_pid );
559 if( p_sys->i_pcr_pid == p_stream->i_pid )
563 /* Find a new pcr stream (Prefer Video Stream) */
564 p_sys->i_pcr_pid = 0x1fff;
565 p_sys->p_pcr_input = NULL;
566 for( i = 0; i < p_mux->i_nb_inputs; i++ )
568 if( p_mux->pp_inputs[i] == p_input )
573 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
576 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
577 p_sys->p_pcr_input= p_mux->pp_inputs[i];
580 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
581 p_sys->i_pcr_pid == 0x1fff )
584 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
585 p_sys->p_pcr_input= p_mux->pp_inputs[i];
588 if( p_sys->p_pcr_input )
590 /* Empty TS buffer */
593 msg_Dbg( p_mux, "new PCR PID is %d", p_sys->i_pcr_pid );
596 /* Empty all data in chain_pes */
597 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
599 if( p_stream->p_decoder_specific_info )
601 free( p_stream->p_decoder_specific_info );
603 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
605 p_sys->i_mpeg4_streams--;
607 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) )
609 int i_pid_video = strtol( val, NULL, 0 );
610 if ( i_pid_video == p_stream->i_pid )
612 p_sys->i_pid_video = i_pid_video;
613 msg_Dbg( p_mux, "freeing video PID %d", i_pid_video );
616 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) )
618 int i_pid_audio = strtol( val, NULL, 0 );
619 if ( i_pid_audio == p_stream->i_pid )
621 p_sys->i_pid_audio = i_pid_audio;
622 msg_Dbg( p_mux, "freeing audio PID %d", i_pid_audio );
627 /* We only change PMT version (PAT isn't changed) */
628 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
633 /*****************************************************************************
634 * Mux: Call each time there is new data for at least one stream
635 *****************************************************************************
637 *****************************************************************************/
638 static int Mux( sout_mux_t *p_mux )
640 sout_mux_sys_t *p_sys = p_mux->p_sys;
641 ts_stream_t *p_pcr_stream;
643 if( p_sys->i_pcr_pid == 0x1fff )
645 msg_Dbg( p_mux, "waiting PCR streams" );
649 p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
653 sout_buffer_chain_t chain_ts;
657 mtime_t i_pcr_length;
660 /* 1: get enough PES packet for all input */
663 vlc_bool_t b_ok = VLC_TRUE;
664 sout_buffer_t *p_data;
666 /* Accumulate enough data in the pcr stream (>i_caching_delay) */
667 /* Accumulate enough data in all other stream ( >= length of pcr) */
668 for( i = 0; i < p_mux->i_nb_inputs; i++ )
670 sout_input_t *p_input = p_mux->pp_inputs[i];
671 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
673 if( ( p_stream == p_pcr_stream && p_stream->i_pes_length <= p_sys->i_caching_delay ) ||
674 p_stream->i_pes_dts + p_stream->i_pes_length < p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
677 if( p_input->p_fifo->i_depth <= 1 )
679 if( p_input->p_fmt->i_cat == AUDIO_ES ||
680 p_input->p_fmt->i_cat == VIDEO_ES )
682 /* We need more data */
685 else if( p_input->p_fifo->i_depth <= 0 )
687 /* spu, only one packet is needed */
693 p_data = sout_FifoGet( p_input->p_fifo );
694 if( p_input->p_fifo->i_depth > 0 )
696 sout_buffer_t *p_next = sout_FifoShow( p_input->p_fifo );
698 p_data->i_length = p_next->i_dts - p_data->i_dts;
701 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 ) ||
702 p_data->i_dts < p_stream->i_pes_dts ||
703 ( p_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > p_stream->i_pes_dts + p_stream->i_pes_length ) )
705 msg_Warn( p_mux, "packet with too strange dts (dts=%lld,old=%lld,pcr=%lld)",
708 p_pcr_stream->i_pes_dts );
709 sout_BufferDelete( p_mux->p_sout, p_data );
711 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
712 p_stream->i_pes_dts = 0;
713 p_stream->i_pes_used = 0;
714 p_stream->i_pes_length = 0;
716 BufferChainClean( p_mux->p_sout, &p_pcr_stream->chain_pes );
717 p_pcr_stream->i_pes_dts = 0;
718 p_pcr_stream->i_pes_used = 0;
719 p_pcr_stream->i_pes_length = 0;
724 p_stream->i_pes_length += p_data->i_length;
725 if( p_stream->i_pes_dts == 0 )
727 p_stream->i_pes_dts = p_data->i_dts;
731 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1 );
733 BufferChainAppend( &p_stream->chain_pes, p_data );
745 i_pcr_dts = p_pcr_stream->i_pes_dts;
746 i_pcr_length = p_pcr_stream->i_pes_length;
748 /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */
749 /* 2: calculate non accurate total size of muxed ts */
751 for( i = 0; i < p_mux->i_nb_inputs; i++ )
753 ts_stream_t *p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
754 sout_buffer_t *p_pes;
756 /* False for pcr stream but it will be eough to do PCR algo */
757 for( p_pes = p_stream->chain_pes.p_first; p_pes != NULL; p_pes = p_pes->p_next )
759 int i_size = p_pes->i_size;
760 if( p_pes->i_dts + p_pes->i_length > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
762 mtime_t i_frag = p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length - p_pes->i_dts;
768 i_size = p_pes->i_size * i_frag / p_pes->i_length;
770 i_packet_count += ( i_size + 183 ) / 184;
773 /* add overhead for PCR (not really exact) */
774 i_packet_count += ( 8 * i_pcr_length / p_sys->i_pcr_delay + 175 ) / 176;
777 /* 3: mux PES into TS */
778 BufferChainInit( &chain_ts );
779 /* append PAT/PMT -> FIXME with big pcr delay it won't have enough pat/pmt */
780 GetPAT( p_mux, &chain_ts);
781 GetPMT( p_mux, &chain_ts );
783 i_packet_count += chain_ts.i_depth;
784 /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */
790 ts_stream_t *p_stream;
794 /* Select stream (lowest dts)*/
795 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
797 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
799 if( p_stream->i_pes_dts == 0 )
804 if( i_stream == -1 ||
805 p_stream->i_pes_dts < i_dts )
808 i_dts = p_stream->i_pes_dts;
815 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
817 /* do we need to issue pcr */
819 if( p_stream == p_pcr_stream &&
820 i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count >= p_sys->i_pcr + p_sys->i_pcr_delay )
823 p_sys->i_pcr = i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count;
826 /* Build the TS packet */
827 p_ts = TSNew( p_mux, p_stream, b_pcr );
831 BufferChainAppend( &chain_ts, p_ts );
834 /* 4: date and send */
835 i_packet_count = chain_ts.i_depth;
836 /* msg_Dbg( p_mux, "real pck=%d", i_packet_count ); */
837 for( i = 0; i < i_packet_count; i++ )
839 sout_buffer_t *p_ts = BufferChainGet( &chain_ts );
841 p_ts->i_dts = i_pcr_dts + i_pcr_length * i / i_packet_count;
842 p_ts->i_length = i_pcr_length / i_packet_count;
844 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR )
846 /* msg_Dbg( p_mux, "pcr=%lld ms", p_ts->i_dts / 1000 ); */
847 TSSetPCR( p_ts, p_ts->i_dts - p_sys->i_dts_delay );
851 p_ts->i_dts += 3*p_sys->i_caching_delay/2;
853 sout_AccessOutWrite( p_mux->p_access, p_ts );
858 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr )
860 sout_buffer_t *p_pes = p_stream->chain_pes.p_first;
863 vlc_bool_t b_new_pes = VLC_FALSE;
864 vlc_bool_t b_adaptation_field = VLC_FALSE;
866 int i_payload_max = 184 - ( b_pcr ? 8 : 0 );
869 if( p_stream->i_pes_used <= 0 )
871 b_new_pes = VLC_TRUE;
873 i_payload = __MIN( (int)p_pes->i_size - p_stream->i_pes_used, i_payload_max );
875 if( b_pcr || i_payload < i_payload_max )
877 b_adaptation_field = VLC_TRUE;
880 p_ts = sout_BufferNew( p_mux->p_sout, 188 );
882 p_ts->p_buffer[0] = 0x47;
883 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|( ( p_stream->i_pid >> 8 )&0x1f );
884 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
885 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|p_stream->i_continuity_counter;
887 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
889 if( b_adaptation_field )
895 int i_stuffing = i_payload_max - i_payload;
897 p_ts->i_flags |= SOUT_BUFFER_FLAGS_PRIVATE_PCR;
899 p_ts->p_buffer[4] = 7 + i_stuffing;
900 p_ts->p_buffer[5] = 0x10; /* flags */
901 p_ts->p_buffer[6] = ( 0 )&0xff;
902 p_ts->p_buffer[7] = ( 0 )&0xff;
903 p_ts->p_buffer[8] = ( 0 )&0xff;
904 p_ts->p_buffer[9] = ( 0 )&0xff;
905 p_ts->p_buffer[10]= ( 0 )&0x80;
906 p_ts->p_buffer[11]= 0;
908 for( i = 12; i < 12 + i_stuffing; i++ )
910 p_ts->p_buffer[i] = 0xff;
915 int i_stuffing = i_payload_max - i_payload;
917 p_ts->p_buffer[4] = i_stuffing - 1;
920 p_ts->p_buffer[5] = 0x00;
921 for( i = 6; i < 6 + i_stuffing - 2; i++ )
923 p_ts->p_buffer[i] = 0xff;
930 memcpy( &p_ts->p_buffer[188 - i_payload], &p_pes->p_buffer[p_stream->i_pes_used], i_payload );
932 p_stream->i_pes_used += i_payload;
933 p_stream->i_pes_dts = p_pes->i_dts + p_pes->i_length * p_stream->i_pes_used / p_pes->i_size;
934 p_stream->i_pes_length -= p_pes->i_length * i_payload / p_pes->i_size;
936 if( p_stream->i_pes_used >= (int)p_pes->i_size )
938 p_pes = BufferChainGet( &p_stream->chain_pes );
939 sout_BufferDelete( p_mux->p_sout, p_pes );
941 p_pes = p_stream->chain_pes.p_first;
944 p_stream->i_pes_dts = p_pes->i_dts;
945 p_stream->i_pes_length = 0;
948 p_stream->i_pes_length += p_pes->i_length;
950 p_pes = p_pes->p_next;
955 p_stream->i_pes_dts = 0;
956 p_stream->i_pes_length = 0;
958 p_stream->i_pes_used = 0;
965 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts )
967 mtime_t i_pcr = 9 * i_dts / 100;
969 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
970 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
971 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
972 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
973 p_ts->p_buffer[10]|= ( i_pcr << 7 )&0x80;
977 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 )
979 sout_mux_sys_t *p_sys = p_mux->p_sys;
980 sout_buffer_chain_t s = *c;
983 int i_packets_min = 0;
984 int i_packets_max = 0;
991 i_packets = c->i_depth;
992 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
993 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
995 if( i_packets < i_packets_min && i_packets_min > 0 )
998 int i_div = ( i_packets_min - i_packets ) / i_packets;
999 int i_mod = ( i_packets_min - i_packets ) % i_packets;
1002 /* We need to pad with null packets (pid=0x1fff)
1003 * We try to melt null packets with true packets */
1005 "packets=%d but min=%d -> adding %d packets of padding",
1006 i_packets, i_packets_min, i_packets_min - i_packets );
1008 BufferChainInit( c );
1009 while( ( p_pk = BufferChainGet( &s ) ) )
1013 BufferChainAppend( c, p_pk );
1015 i_null = i_div + ( i_rest + i_mod ) / i_packets;
1017 for( i = 0; i < i_null; i++ )
1019 sout_buffer_t *p_null;
1021 p_null = sout_BufferNew( p_mux->p_sout, 188 );
1022 p_null->p_buffer[0] = 0x47;
1023 p_null->p_buffer[1] = 0x1f;
1024 p_null->p_buffer[2] = 0xff;
1025 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
1026 memset( &p_null->p_buffer[4], 0, 184 );
1027 p_sys->i_null_continuity_counter =
1028 ( p_sys->i_null_continuity_counter + 1 ) % 16;
1030 BufferChainAppend( c, p_null );
1033 i_rest = ( i_rest + i_mod ) % i_packets;
1036 else if( i_packets > i_packets_max && i_packets_max > 0 )
1038 sout_buffer_t *p_pk;
1041 /* Arg, we need to drop packets, I don't do something clever (like
1042 * dropping complete pid, b frames, ... ), I just get the right amount
1043 * of packets and discard the others */
1045 "packets=%d but max=%d -> removing %d packets -> stream broken",
1046 i_packets, i_packets_max, i_packets - i_packets_max );
1048 BufferChainInit( c );
1049 for( i = 0; i < i_packets_max; i++ )
1051 BufferChainAppend( c, BufferChainGet( &s ) );
1054 while( ( p_pk = BufferChainGet( &s ) ) )
1056 sout_BufferDelete( p_mux->p_sout, p_pk );
1062 static void PEStoTS( sout_instance_t *p_sout,
1063 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
1064 ts_stream_t *p_stream )
1070 /* get PES total size */
1071 i_size = p_pes->i_size;
1072 p_data = p_pes->p_buffer;
1074 b_new_pes = VLC_TRUE;
1078 int b_adaptation_field;
1080 sout_buffer_t *p_ts;
1082 p_ts = sout_BufferNew( p_sout, 188 );
1085 * 1b transport_error_indicator
1086 * 1b payload_unit_start
1087 * 1b transport_priority
1089 * 2b transport_scrambling_control
1090 * 2b if adaptation_field 0x03 else 0x01
1091 * 4b continuity_counter
1094 i_copy = __MIN( i_size, 184 );
1095 b_adaptation_field = i_size < 184 ? VLC_TRUE : VLC_FALSE;
1097 p_ts->p_buffer[0] = 0x47;
1098 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
1099 ( ( p_stream->i_pid >> 8 )&0x1f );
1100 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
1101 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
1102 p_stream->i_continuity_counter;
1104 b_new_pes = VLC_FALSE;
1105 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
1107 if( b_adaptation_field )
1109 int i_stuffing = 184 - i_copy;
1112 p_ts->p_buffer[4] = i_stuffing - 1;
1113 if( i_stuffing > 1 )
1115 p_ts->p_buffer[5] = 0x00;
1116 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1118 p_ts->p_buffer[i] = 0xff;
1123 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1127 BufferChainAppend( c, p_ts );
1131 sout_buffer_t *p_next = p_pes->p_next;
1133 p_pes->p_next = NULL;
1134 sout_BufferDelete( p_sout, p_pes );
1135 if( p_next == NULL )
1139 b_new_pes = VLC_TRUE;
1141 i_size = p_pes->i_size;
1142 p_data = p_pes->p_buffer;
1149 #if defined MODULE_NAME_IS_mux_ts
1150 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1152 static uint32_t CRC32[256] =
1154 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1155 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1156 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1157 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1158 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1159 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1160 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1161 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1162 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1163 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1164 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1165 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1166 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1167 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1168 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1169 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1170 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1171 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1172 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1173 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1174 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1175 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1176 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1177 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1178 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1179 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1180 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1181 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1182 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1183 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1184 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1185 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1186 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1187 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1188 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1189 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1190 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1191 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1192 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1193 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1194 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1195 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1196 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1197 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1198 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1199 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1200 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1201 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1202 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1203 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1204 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1205 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1206 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1207 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1208 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1209 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1210 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1211 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1212 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1213 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1214 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1215 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1216 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1217 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1220 uint32_t i_crc = 0xffffffff;
1222 /* Calculate the CRC */
1223 while( i_count > 0 )
1225 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1233 static void GetPAT( sout_mux_t *p_mux,
1234 sout_buffer_chain_t *c )
1236 sout_mux_sys_t *p_sys = p_mux->p_sys;
1237 sout_buffer_t *p_pat;
1240 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1244 p_pat->i_length = 0;
1246 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1248 bits_write( &bits, 8, 0 ); // pointer
1249 bits_write( &bits, 8, 0x00 ); // table id
1250 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1251 bits_write( &bits, 1, 0 ); // 0
1252 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1253 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1254 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1255 bits_write( &bits, 2, 0x03 ); // FIXME
1256 bits_write( &bits, 5, p_sys->i_pat_version_number );
1257 bits_write( &bits, 1, 1 ); // current_next_indicator
1258 bits_write( &bits, 8, 0 ); // section number
1259 bits_write( &bits, 8, 0 ); // last section number
1261 bits_write( &bits, 16, 1 ); // program number
1262 bits_write( &bits, 3, 0x07 ); // reserved
1263 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1265 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1267 p_pat->i_size = bits.i_data;
1269 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1272 static void GetPMT( sout_mux_t *p_mux,
1273 sout_buffer_chain_t *c )
1275 sout_mux_sys_t *p_sys = p_mux->p_sys;
1276 sout_buffer_t *p_pmt;
1280 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1284 p_pmt->i_length = 0;
1286 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1288 bits_write( &bits, 8, 0 ); // pointer
1289 bits_write( &bits, 8, 0x02 ); // table id
1290 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1291 bits_write( &bits, 1, 0 ); // 0
1292 bits_write( &bits, 2, 0 ); // reserved FIXME
1293 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1294 bits_write( &bits, 16, 1 ); // FIXME program number
1295 bits_write( &bits, 2, 0 ); // FIXME
1296 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1297 bits_write( &bits, 1, 1 ); // current_next_indicator
1298 bits_write( &bits, 8, 0 ); // section number
1299 bits_write( &bits, 8, 0 ); // last section number
1301 bits_write( &bits, 3, 0 ); // reserved
1303 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1304 bits_write( &bits, 4, 0 ); // reserved FIXME
1306 bits_write( &bits, 12, 0 ); // program info len FIXME
1308 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1310 ts_stream_t *p_stream;
1312 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1314 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1315 bits_write( &bits, 3, 0 ); // reserved
1316 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1317 bits_write( &bits, 4, 0 ); //reserved
1318 bits_write( &bits, 12, 0 ); // es info len FIXME
1321 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1323 p_pmt->i_size = bits.i_data;
1325 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1327 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1329 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1330 dvbpsi_psi_section_t* p_section )
1332 sout_buffer_t *p_psi, *p_first = NULL;
1339 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1340 ( p_section->b_syntax_indicator ? 4 : 0 );
1342 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1345 p_psi->i_length = 0;
1346 p_psi->i_size = i_size + 1;
1348 p_psi->p_buffer[0] = 0; // pointer
1349 memcpy( p_psi->p_buffer + 1,
1353 sout_BufferChain( &p_first, p_psi );
1355 p_section = p_section->p_next;
1361 static void GetPAT( sout_mux_t *p_mux,
1362 sout_buffer_chain_t *c )
1364 sout_mux_sys_t *p_sys = p_mux->p_sys;
1365 sout_buffer_t *p_pat;
1367 dvbpsi_psi_section_t *p_section;
1369 dvbpsi_InitPAT( &pat,
1371 p_sys->i_pat_version_number,
1372 1 ); // b_current_next
1373 /* add all program (only one) */
1374 dvbpsi_PATAddProgram( &pat,
1376 p_sys->pmt.i_pid ); // i_pid
1378 p_section = dvbpsi_GenPATSections( &pat,
1379 0 ); // max program per section
1381 p_pat = WritePSISection( p_mux->p_sout, p_section );
1383 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1385 dvbpsi_DeletePSISections( p_section );
1386 dvbpsi_EmptyPAT( &pat );
1389 static uint32_t GetDescriptorLength24b( int i_length )
1391 uint32_t i_l1, i_l2, i_l3;
1393 i_l1 = i_length&0x7f;
1394 i_l2 = ( i_length >> 7 )&0x7f;
1395 i_l3 = ( i_length >> 14 )&0x7f;
1397 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1400 static void GetPMT( sout_mux_t *p_mux,
1401 sout_buffer_chain_t *c )
1403 sout_mux_sys_t *p_sys = p_mux->p_sys;
1404 sout_buffer_t *p_pmt;
1407 dvbpsi_pmt_es_t *p_es;
1408 dvbpsi_psi_section_t *p_section;
1412 dvbpsi_InitPMT( &pmt,
1413 0x01, // program number
1414 p_sys->i_pmt_version_number,
1415 1, // b_current_next
1418 if( p_sys->i_mpeg4_streams > 0 )
1422 bits_buffer_t bits_fix_IOD;
1424 /* Make valgrind happy : it works at byte level not bit one so
1425 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
1426 * working (needed when fixing some bits) */
1427 memset( iod, 0, 4096 );
1429 bits_initwrite( &bits, 4096, iod );
1431 bits_write( &bits, 8, 0x01 );
1432 // InitialObjectDescriptor
1433 bits_align( &bits );
1434 bits_write( &bits, 8, 0x02 ); // tag
1435 bits_fix_IOD = bits; // save states to fix length later
1436 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1437 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1438 bits_write( &bits, 1, 0x00 ); // URL Flag
1439 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1440 bits_write( &bits, 4, 0x0f ); // reserved
1441 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1442 bits_write( &bits, 8, 0xff ); // sceneProfile
1443 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1444 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1445 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1446 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1448 ts_stream_t *p_stream;
1449 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1451 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1453 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1455 bits_align( &bits );
1456 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1457 bits_fix_ESDescr = bits;
1458 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1459 bits_write( &bits, 16, p_stream->i_es_id );
1460 bits_write( &bits, 1, 0x00 ); // streamDependency
1461 bits_write( &bits, 1, 0x00 ); // URL Flag
1462 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1463 bits_write( &bits, 5, 0x1f ); // streamPriority
1465 // DecoderConfigDesciptor
1466 bits_align( &bits );
1467 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1468 bits_fix_Decoder = bits;
1469 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1470 if( p_stream->i_stream_type == 0x10 )
1472 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1473 bits_write( &bits, 6, 0x04 ); // VisualStream
1475 else if( p_stream->i_stream_type == 0x11 )
1477 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1478 bits_write( &bits, 6, 0x05 ); // AudioStream
1482 bits_write( &bits, 8, 0x00 );
1483 bits_write( &bits, 6, 0x00 );
1485 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1487 bits_write( &bits, 1, 0x00 ); // UpStream
1488 bits_write( &bits, 1, 0x01 ); // reserved
1489 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1490 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1491 bits_write( &bits, 32, 0 ); // avgBitrate
1493 if( p_stream->i_decoder_specific_info > 0 )
1496 // DecoderSpecificInfo
1497 bits_align( &bits );
1498 bits_write( &bits, 8, 0x05 ); // tag
1499 bits_write( &bits, 24,
1500 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1501 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1503 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1506 /* fix Decoder length */
1507 bits_write( &bits_fix_Decoder, 24,
1508 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1510 /* SLConfigDescriptor : predifined (0x01) */
1511 bits_align( &bits );
1512 bits_write( &bits, 8, 0x06 ); // tag
1513 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1514 bits_write( &bits, 8, 0x01 ); // predefined
1515 bits_write( &bits, 1, 0 ); // durationFlag
1516 bits_write( &bits, 32, 0 ); // OCRResolution
1517 bits_write( &bits, 8, 0 ); // OCRLength
1518 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1519 bits_align( &bits );
1521 /* fix ESDescr length */
1522 bits_write( &bits_fix_ESDescr, 24,
1523 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1526 bits_align( &bits );
1527 /* fix IOD length */
1528 bits_write( &bits_fix_IOD, 24,
1529 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1530 dvbpsi_PMTAddDescriptor( &pmt,
1536 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1538 ts_stream_t *p_stream;
1540 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1542 p_es = dvbpsi_PMTAddES( &pmt,
1543 p_stream->i_stream_type,
1545 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1550 es_id[0] = (p_stream->i_es_id >> 8)&0xff;
1551 es_id[1] = (p_stream->i_es_id)&0xff;
1552 dvbpsi_PMTESAddDescriptor( p_es, 0x1f, 2, es_id );
1554 else if( p_stream->i_stream_type == 0xa0 )
1557 int i_extra = __MIN( p_stream->i_decoder_specific_info,
1560 /* private DIV3 descripor */
1561 memcpy( &data[0], &p_stream->i_bih_codec, 4 );
1562 data[4] = ( p_stream->i_bih_width >> 8 )&0xff;
1563 data[5] = ( p_stream->i_bih_width )&0xff;
1564 data[6] = ( p_stream->i_bih_height>> 8 )&0xff;
1565 data[7] = ( p_stream->i_bih_height )&0xff;
1566 data[8] = ( i_extra >> 8 )&0xff;
1567 data[9] = ( i_extra )&0xff;
1570 memcpy( &data[10], p_stream->p_decoder_specific_info, i_extra );
1573 /* 0xa0 is private */
1574 dvbpsi_PMTESAddDescriptor( p_es, 0xa0, i_extra + 10, data );
1576 else if( p_stream->i_stream_type == 0x81 )
1578 uint8_t format[4] = { 0x41, 0x43, 0x2d, 0x33 };
1580 /* "registration" descriptor : "AC-3" */
1581 dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
1585 p_section = dvbpsi_GenPMTSections( &pmt );
1587 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1589 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1591 dvbpsi_DeletePSISections( p_section );
1592 dvbpsi_EmptyPMT( &pmt );