1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.39 2003/11/22 20:25:01 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;
188 int i_stream_id_mpga;
189 int i_stream_id_mpgv;
196 int i_pid_free; // first usable pid
198 int i_pat_version_number;
201 int i_pmt_version_number;
202 ts_stream_t pmt; // Up to now only one program
206 int i_null_continuity_counter; /* Needed ? */
208 /* for TS building */
209 int64_t i_bitrate_min;
210 int64_t i_bitrate_max;
212 int64_t i_caching_delay;
217 mtime_t i_pcr; /* last PCR emited */
221 /* Reserve a pid and return it */
222 static int AllocatePID( sout_mux_sys_t *p_sys, int i_cat )
225 if ( i_cat == VIDEO_ES && p_sys->i_pid_video )
227 i_pid = p_sys->i_pid_video;
228 p_sys->i_pid_video = 0;
230 else if ( i_cat == AUDIO_ES && p_sys->i_pid_audio )
232 i_pid = p_sys->i_pid_audio;
233 p_sys->i_pid_audio = 0;
237 i_pid = ++p_sys->i_pid_free;
242 static void GetPAT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
243 static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
245 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr );
246 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts );
248 static void PEStoTS ( sout_instance_t *, sout_buffer_chain_t *, sout_buffer_t *, ts_stream_t * );
250 /*****************************************************************************
252 *****************************************************************************/
253 static int Open( vlc_object_t *p_this )
255 sout_mux_t *p_mux =(sout_mux_t*)p_this;
256 sout_mux_sys_t *p_sys;
259 msg_Dbg( p_mux, "Open" );
261 p_sys = malloc( sizeof( sout_mux_sys_t ) );
263 p_mux->pf_capacity = Capability;
264 p_mux->pf_addstream = AddStream;
265 p_mux->pf_delstream = DelStream;
267 p_mux->p_sys = p_sys;
268 p_mux->i_preheader = 30; // really enough for a pes header
270 srand( (uint32_t)mdate() );
272 p_sys->i_stream_id_mpga = 0xc0;
273 p_sys->i_stream_id_mpgv = 0xe0;
275 p_sys->i_audio_bound = 0;
276 p_sys->i_video_bound = 0;
278 p_sys->i_pat_version_number = rand() % 32;
279 p_sys->pat.i_pid = 0;
280 p_sys->pat.i_continuity_counter = 0;
282 p_sys->i_pmt_version_number = rand() % 32;
283 p_sys->pmt.i_pid = 0x42;
284 p_sys->pmt.i_continuity_counter = 0;
286 p_sys->i_pid_free = 0x43;
288 p_sys->i_pid_video = 0;
289 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) )
291 p_sys->i_pid_video = strtol( val, NULL, 0 );
292 if ( p_sys->i_pid_video > p_sys->i_pid_free )
294 p_sys->i_pid_free = p_sys->i_pid_video + 1;
297 p_sys->i_pid_audio = 0;
298 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) )
300 p_sys->i_pid_audio = strtol( val, NULL, 0 );
301 if ( p_sys->i_pid_audio > p_sys->i_pid_free )
303 p_sys->i_pid_free = p_sys->i_pid_audio + 1;
307 p_sys->i_pcr_pid = 0x1fff;
308 p_sys->p_pcr_input = NULL;
310 p_sys->i_mpeg4_streams = 0;
312 p_sys->i_null_continuity_counter = 0;
314 /* Allow to create constrained stream */
315 p_sys->i_bitrate_min = 0;
316 p_sys->i_bitrate_max = 0;
317 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmin" ) ) )
319 p_sys->i_bitrate_min = atoll( val );
321 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmax" ) ) )
323 p_sys->i_bitrate_max = atoll( val );
325 if( p_sys->i_bitrate_min > 0 && p_sys->i_bitrate_max > 0 &&
326 p_sys->i_bitrate_min > p_sys->i_bitrate_max )
328 msg_Err( p_mux, "incompatible minimum and maximum bitrate, "
329 "disabling bitrate control" );
330 p_sys->i_bitrate_min = 0;
331 p_sys->i_bitrate_max = 0;
333 if( p_sys->i_bitrate_min > 0 || p_sys->i_bitrate_max > 0 )
335 msg_Err( p_mux, "bmin and bmax no more supported (if you need them report it)" );
338 p_sys->i_caching_delay = 200000;
339 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "caching" ) ) )
341 p_sys->i_caching_delay = (int64_t)atoi( val ) * 1000;
342 if( p_sys->i_caching_delay <= 0 )
345 "invalid caching ("I64Fd"ms) reseting to 200ms",
346 p_sys->i_caching_delay / 1000 );
347 p_sys->i_caching_delay = 200000;
350 p_sys->i_pcr_delay = 30000;
351 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr" ) ) )
353 p_sys->i_pcr_delay = (int64_t)atoi( val ) * 1000;
354 if( p_sys->i_pcr_delay <= 0 ||
355 p_sys->i_pcr_delay >= p_sys->i_caching_delay )
358 "invalid pcr delay ("I64Fd"ms) reseting to 30ms",
359 p_sys->i_pcr_delay / 1000 );
360 p_sys->i_pcr_delay = 30000;
364 msg_Dbg( p_mux, "caching="I64Fd" pcr="I64Fd,
365 p_sys->i_caching_delay, p_sys->i_pcr_delay );
367 p_sys->i_dts_delay = 200000;
368 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "dts-delay" ) ) )
370 p_sys->i_dts_delay = (int64_t)atoi( val ) * 1000;
373 /* for TS generation */
378 /*****************************************************************************
380 *****************************************************************************/
381 static void Close( vlc_object_t * p_this )
383 sout_mux_t *p_mux = (sout_mux_t*)p_this;
384 sout_mux_sys_t *p_sys = p_mux->p_sys;
386 msg_Dbg( p_mux, "Close" );
391 /*****************************************************************************
393 *****************************************************************************/
394 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
398 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
399 *(vlc_bool_t*)p_answer = VLC_TRUE;
400 return( SOUT_MUX_CAP_ERR_OK );
402 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
406 /*****************************************************************************
407 * AddStream: called for each stream addition
408 *****************************************************************************/
409 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
411 sout_mux_sys_t *p_sys = p_mux->p_sys;
412 ts_stream_t *p_stream;
414 msg_Dbg( p_mux, "adding input codec=%4.4s", (char*)&p_input->p_fmt->i_codec );
416 p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
418 /* Init this new stream */
419 p_stream->i_pid = AllocatePID( p_sys, p_input->p_fmt->i_cat );
420 p_stream->i_continuity_counter = 0;
421 p_stream->i_decoder_specific_info = 0;
422 p_stream->p_decoder_specific_info = NULL;
424 /* All others fields depand on codec */
425 switch( p_input->p_fmt->i_cat )
428 switch( p_input->p_fmt->i_codec )
430 case VLC_FOURCC( 'm', 'p','g', 'v' ):
431 /* TODO: do we need to check MPEG-I/II ? */
432 p_stream->i_stream_type = 0x02;
433 p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
434 p_sys->i_stream_id_mpgv++;
436 case VLC_FOURCC( 'm', 'p','4', 'v' ):
437 p_stream->i_stream_type = 0x10;
438 p_stream->i_stream_id = 0xfa;
439 p_sys->i_mpeg4_streams++;
440 p_stream->i_es_id = p_stream->i_pid;
442 /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
443 /* I didn't want to do that :P */
444 case VLC_FOURCC( 'H', '2', '6', '3' ):
445 case VLC_FOURCC( 'I', '2', '6', '3' ):
446 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
447 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
448 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
449 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
450 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
451 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
452 p_stream->i_stream_type = 0xa0; // private
453 p_stream->i_stream_id = 0xa0; // beurk
454 p_stream->i_bih_codec = p_input->p_fmt->i_codec;
455 p_stream->i_bih_width = p_input->p_fmt->video.i_width;
456 p_stream->i_bih_height = p_input->p_fmt->video.i_height;
462 p_sys->i_video_bound++;
466 switch( p_input->p_fmt->i_codec )
468 case VLC_FOURCC( 'm', 'p','g', 'a' ):
469 p_stream->i_stream_type = p_input->p_fmt->audio.i_rate >= 32000 ? 0x03 : 0x04;
470 p_stream->i_stream_id = p_sys->i_stream_id_mpga;
471 p_sys->i_stream_id_mpga++;
473 case VLC_FOURCC( 'a', '5','2', ' ' ):
474 p_stream->i_stream_type = 0x81;
475 p_stream->i_stream_id = 0xbd;
477 case VLC_FOURCC( 'l', 'p','c', 'm' ):
478 p_stream->i_stream_type = 0x83;
479 p_stream->i_stream_id = 0xbd;
481 case VLC_FOURCC( 'd', 't','s', ' ' ):
482 p_stream->i_stream_type = 0x85;
483 p_stream->i_stream_id = 0xbd;
486 case VLC_FOURCC( 'm', 'p','4', 'a' ):
487 p_stream->i_stream_type = 0x11;
488 p_stream->i_stream_id = 0xfa;
489 p_sys->i_mpeg4_streams++;
490 p_stream->i_es_id = p_stream->i_pid;
496 p_sys->i_audio_bound++;
500 switch( p_input->p_fmt->i_codec )
502 case VLC_FOURCC( 's', 'p','u', ' ' ):
503 p_stream->i_stream_type = 0x82;
504 p_stream->i_stream_id = 0xbd;
517 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
518 p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra;
519 if( p_stream->i_decoder_specific_info > 0 )
521 p_stream->p_decoder_specific_info =
522 malloc( p_stream->i_decoder_specific_info );
523 memcpy( p_stream->p_decoder_specific_info,
524 p_input->p_fmt->p_extra,
525 p_input->p_fmt->i_extra );
529 BufferChainInit( &p_stream->chain_pes );
530 p_stream->i_pes_dts = 0;
531 p_stream->i_pes_length = 0;
532 p_stream->i_pes_used = 0;
534 /* We only change PMT version (PAT isn't changed) */
535 p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
538 if( p_input->p_fmt->i_cat != SPU_ES &&
539 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
541 if( p_sys->p_pcr_input )
543 /* There was already a PCR stream, so clean context */
546 p_sys->i_pcr_pid = p_stream->i_pid;
547 p_sys->p_pcr_input = p_input;
553 /*****************************************************************************
554 * DelStream: called before a stream deletion
555 *****************************************************************************/
556 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
558 sout_mux_sys_t *p_sys = p_mux->p_sys;
559 ts_stream_t *p_stream;
562 msg_Dbg( p_mux, "removing input" );
563 p_stream = (ts_stream_t*)p_input->p_sys;
565 if( p_sys->i_pcr_pid == p_stream->i_pid )
569 /* Find a new pcr stream (Prefer Video Stream) */
570 p_sys->i_pcr_pid = 0x1fff;
571 p_sys->p_pcr_input = NULL;
572 for( i = 0; i < p_mux->i_nb_inputs; i++ )
574 if( p_mux->pp_inputs[i] == p_input )
579 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
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 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
587 p_sys->i_pcr_pid == 0x1fff )
590 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
591 p_sys->p_pcr_input= p_mux->pp_inputs[i];
594 if( p_sys->p_pcr_input )
596 /* Empty TS buffer */
601 /* Empty all data in chain_pes */
602 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
604 if( p_stream->p_decoder_specific_info )
606 free( p_stream->p_decoder_specific_info );
608 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
610 p_sys->i_mpeg4_streams--;
612 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) )
614 int i_pid_video = strtol( val, NULL, 0 );
615 if ( i_pid_video == p_stream->i_pid )
617 p_sys->i_pid_video = i_pid_video;
620 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) )
622 int i_pid_audio = strtol( val, NULL, 0 );
623 if ( i_pid_audio == p_stream->i_pid )
625 p_sys->i_pid_audio = i_pid_audio;
630 /* We only change PMT version (PAT isn't changed) */
631 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
636 /*****************************************************************************
637 * Mux: Call each time there is new data for at least one stream
638 *****************************************************************************
640 *****************************************************************************/
641 static int Mux( sout_mux_t *p_mux )
643 sout_mux_sys_t *p_sys = p_mux->p_sys;
644 ts_stream_t *p_pcr_stream;
646 if( p_sys->i_pcr_pid == 0x1fff )
648 msg_Dbg( p_mux, "waiting PCR streams" );
652 p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
656 sout_buffer_chain_t chain_ts;
660 mtime_t i_pcr_length;
663 /* 1: get enough PES packet for all input */
666 vlc_bool_t b_ok = VLC_TRUE;
667 sout_buffer_t *p_data;
669 /* Accumulate enough data in the pcr stream (>i_caching_delay) */
670 /* Accumulate enough data in all other stream ( >= length of pcr) */
671 for( i = 0; i < p_mux->i_nb_inputs; i++ )
673 sout_input_t *p_input = p_mux->pp_inputs[i];
674 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
676 if( ( p_stream == p_pcr_stream && p_stream->i_pes_length <= p_sys->i_caching_delay ) ||
677 p_stream->i_pes_dts + p_stream->i_pes_length < p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
680 if( p_input->p_fifo->i_depth <= 1 )
682 if( p_input->p_fmt->i_cat == AUDIO_ES ||
683 p_input->p_fmt->i_cat == VIDEO_ES )
685 /* We need more data */
688 else if( p_input->p_fifo->i_depth <= 0 )
690 /* spu, only one packet is needed */
696 p_data = sout_FifoGet( p_input->p_fifo );
697 if( p_input->p_fifo->i_depth > 0 )
699 sout_buffer_t *p_next = sout_FifoShow( p_input->p_fifo );
701 p_data->i_length = p_next->i_dts - p_data->i_dts;
704 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 ) ||
705 p_data->i_dts < p_stream->i_pes_dts ||
706 ( p_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > p_stream->i_pes_dts + p_stream->i_pes_length ) )
708 msg_Warn( p_mux, "packet with too strange dts (dts=%lld,old=%lld,pcr=%lld)",
711 p_pcr_stream->i_pes_dts );
712 sout_BufferDelete( p_mux->p_sout, p_data );
714 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
715 p_stream->i_pes_dts = 0;
716 p_stream->i_pes_used = 0;
717 p_stream->i_pes_length = 0;
719 BufferChainClean( p_mux->p_sout, &p_pcr_stream->chain_pes );
720 p_pcr_stream->i_pes_dts = 0;
721 p_pcr_stream->i_pes_used = 0;
722 p_pcr_stream->i_pes_length = 0;
727 p_stream->i_pes_length += p_data->i_length;
728 if( p_stream->i_pes_dts == 0 )
730 p_stream->i_pes_dts = p_data->i_dts;
734 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1 );
736 BufferChainAppend( &p_stream->chain_pes, p_data );
748 i_pcr_dts = p_pcr_stream->i_pes_dts;
749 i_pcr_length = p_pcr_stream->i_pes_length;
751 /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */
752 /* 2: calculate non accurate total size of muxed ts */
754 for( i = 0; i < p_mux->i_nb_inputs; i++ )
756 ts_stream_t *p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
757 sout_buffer_t *p_pes;
759 /* False for pcr stream but it will be eough to do PCR algo */
760 for( p_pes = p_stream->chain_pes.p_first; p_pes != NULL; p_pes = p_pes->p_next )
762 int i_size = p_pes->i_size;
763 if( p_pes->i_dts + p_pes->i_length > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
765 mtime_t i_frag = p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length - p_pes->i_dts;
771 i_size = p_pes->i_size * i_frag / p_pes->i_length;
773 i_packet_count += ( i_size + 183 ) / 184;
776 /* add overhead for PCR (not really exact) */
777 i_packet_count += ( 8 * i_pcr_length / p_sys->i_pcr_delay + 175 ) / 176;
780 /* 3: mux PES into TS */
781 BufferChainInit( &chain_ts );
782 /* append PAT/PMT -> FIXME with big pcr delay it won't have enough pat/pmt */
783 GetPAT( p_mux, &chain_ts);
784 GetPMT( p_mux, &chain_ts );
786 i_packet_count += chain_ts.i_depth;
787 /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */
793 ts_stream_t *p_stream;
797 /* Select stream (lowest dts)*/
798 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
800 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
802 if( p_stream->i_pes_dts == 0 )
807 if( i_stream == -1 ||
808 p_stream->i_pes_dts < i_dts )
811 i_dts = p_stream->i_pes_dts;
818 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
820 /* do we need to issue pcr */
822 if( p_stream == p_pcr_stream &&
823 i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count >= p_sys->i_pcr + p_sys->i_pcr_delay )
826 p_sys->i_pcr = i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count;
829 /* Build the TS packet */
830 p_ts = TSNew( p_mux, p_stream, b_pcr );
834 BufferChainAppend( &chain_ts, p_ts );
837 /* 4: date and send */
838 i_packet_count = chain_ts.i_depth;
839 /* msg_Dbg( p_mux, "real pck=%d", i_packet_count ); */
840 for( i = 0; i < i_packet_count; i++ )
842 sout_buffer_t *p_ts = BufferChainGet( &chain_ts );
844 p_ts->i_dts = i_pcr_dts + i_pcr_length * i / i_packet_count;
845 p_ts->i_length = i_pcr_length / i_packet_count;
847 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR )
849 /* msg_Dbg( p_mux, "pcr=%lld ms", p_ts->i_dts / 1000 ); */
850 TSSetPCR( p_ts, p_ts->i_dts - p_sys->i_dts_delay );
854 p_ts->i_dts += 3*p_sys->i_caching_delay/2;
856 sout_AccessOutWrite( p_mux->p_access, p_ts );
861 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr )
863 sout_buffer_t *p_pes = p_stream->chain_pes.p_first;
866 vlc_bool_t b_new_pes = VLC_FALSE;
867 vlc_bool_t b_adaptation_field = VLC_FALSE;
869 int i_payload_max = 184 - ( b_pcr ? 8 : 0 );
872 if( p_stream->i_pes_used <= 0 )
874 b_new_pes = VLC_TRUE;
876 i_payload = __MIN( (int)p_pes->i_size - p_stream->i_pes_used, i_payload_max );
878 if( b_pcr || i_payload < i_payload_max )
880 b_adaptation_field = VLC_TRUE;
883 p_ts = sout_BufferNew( p_mux->p_sout, 188 );
885 p_ts->p_buffer[0] = 0x47;
886 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|( ( p_stream->i_pid >> 8 )&0x1f );
887 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
888 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|p_stream->i_continuity_counter;
890 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
892 if( b_adaptation_field )
898 int i_stuffing = i_payload_max - i_payload;
900 p_ts->i_flags |= SOUT_BUFFER_FLAGS_PRIVATE_PCR;
902 p_ts->p_buffer[4] = 7 + i_stuffing;
903 p_ts->p_buffer[5] = 0x10; /* flags */
904 p_ts->p_buffer[6] = ( 0 )&0xff;
905 p_ts->p_buffer[7] = ( 0 )&0xff;
906 p_ts->p_buffer[8] = ( 0 )&0xff;
907 p_ts->p_buffer[9] = ( 0 )&0xff;
908 p_ts->p_buffer[10]= ( 0 )&0x80;
909 p_ts->p_buffer[11]= 0;
911 for( i = 12; i < 12 + i_stuffing; i++ )
913 p_ts->p_buffer[i] = 0xff;
918 int i_stuffing = i_payload_max - i_payload;
920 p_ts->p_buffer[4] = i_stuffing - 1;
923 p_ts->p_buffer[5] = 0x00;
924 for( i = 6; i < 6 + i_stuffing - 2; i++ )
926 p_ts->p_buffer[i] = 0xff;
933 memcpy( &p_ts->p_buffer[188 - i_payload], &p_pes->p_buffer[p_stream->i_pes_used], i_payload );
935 p_stream->i_pes_used += i_payload;
936 p_stream->i_pes_dts = p_pes->i_dts + p_pes->i_length * p_stream->i_pes_used / p_pes->i_size;
937 p_stream->i_pes_length -= p_pes->i_length * i_payload / p_pes->i_size;
939 if( p_stream->i_pes_used >= (int)p_pes->i_size )
941 p_pes = BufferChainGet( &p_stream->chain_pes );
942 sout_BufferDelete( p_mux->p_sout, p_pes );
944 p_pes = p_stream->chain_pes.p_first;
947 p_stream->i_pes_dts = p_pes->i_dts;
948 p_stream->i_pes_length = 0;
951 p_stream->i_pes_length += p_pes->i_length;
953 p_pes = p_pes->p_next;
958 p_stream->i_pes_dts = 0;
959 p_stream->i_pes_length = 0;
961 p_stream->i_pes_used = 0;
968 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts )
970 mtime_t i_pcr = 9 * i_dts / 100;
972 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
973 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
974 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
975 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
976 p_ts->p_buffer[10]|= ( i_pcr << 7 )&0x80;
980 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 )
982 sout_mux_sys_t *p_sys = p_mux->p_sys;
983 sout_buffer_chain_t s = *c;
986 int i_packets_min = 0;
987 int i_packets_max = 0;
994 i_packets = c->i_depth;
995 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
996 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
998 if( i_packets < i_packets_min && i_packets_min > 0 )
1000 sout_buffer_t *p_pk;
1001 int i_div = ( i_packets_min - i_packets ) / i_packets;
1002 int i_mod = ( i_packets_min - i_packets ) % i_packets;
1005 /* We need to pad with null packets (pid=0x1fff)
1006 * We try to melt null packets with true packets */
1008 "packets=%d but min=%d -> adding %d packets of padding",
1009 i_packets, i_packets_min, i_packets_min - i_packets );
1011 BufferChainInit( c );
1012 while( ( p_pk = BufferChainGet( &s ) ) )
1016 BufferChainAppend( c, p_pk );
1018 i_null = i_div + ( i_rest + i_mod ) / i_packets;
1020 for( i = 0; i < i_null; i++ )
1022 sout_buffer_t *p_null;
1024 p_null = sout_BufferNew( p_mux->p_sout, 188 );
1025 p_null->p_buffer[0] = 0x47;
1026 p_null->p_buffer[1] = 0x1f;
1027 p_null->p_buffer[2] = 0xff;
1028 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
1029 memset( &p_null->p_buffer[4], 0, 184 );
1030 p_sys->i_null_continuity_counter =
1031 ( p_sys->i_null_continuity_counter + 1 ) % 16;
1033 BufferChainAppend( c, p_null );
1036 i_rest = ( i_rest + i_mod ) % i_packets;
1039 else if( i_packets > i_packets_max && i_packets_max > 0 )
1041 sout_buffer_t *p_pk;
1044 /* Arg, we need to drop packets, I don't do something clever (like
1045 * dropping complete pid, b frames, ... ), I just get the right amount
1046 * of packets and discard the others */
1048 "packets=%d but max=%d -> removing %d packets -> stream broken",
1049 i_packets, i_packets_max, i_packets - i_packets_max );
1051 BufferChainInit( c );
1052 for( i = 0; i < i_packets_max; i++ )
1054 BufferChainAppend( c, BufferChainGet( &s ) );
1057 while( ( p_pk = BufferChainGet( &s ) ) )
1059 sout_BufferDelete( p_mux->p_sout, p_pk );
1065 static void PEStoTS( sout_instance_t *p_sout,
1066 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
1067 ts_stream_t *p_stream )
1073 /* get PES total size */
1074 i_size = p_pes->i_size;
1075 p_data = p_pes->p_buffer;
1077 b_new_pes = VLC_TRUE;
1081 int b_adaptation_field;
1083 sout_buffer_t *p_ts;
1085 p_ts = sout_BufferNew( p_sout, 188 );
1088 * 1b transport_error_indicator
1089 * 1b payload_unit_start
1090 * 1b transport_priority
1092 * 2b transport_scrambling_control
1093 * 2b if adaptation_field 0x03 else 0x01
1094 * 4b continuity_counter
1097 i_copy = __MIN( i_size, 184 );
1098 b_adaptation_field = i_size < 184 ? VLC_TRUE : VLC_FALSE;
1100 p_ts->p_buffer[0] = 0x47;
1101 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
1102 ( ( p_stream->i_pid >> 8 )&0x1f );
1103 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
1104 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
1105 p_stream->i_continuity_counter;
1107 b_new_pes = VLC_FALSE;
1108 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
1110 if( b_adaptation_field )
1112 int i_stuffing = 184 - i_copy;
1115 p_ts->p_buffer[4] = i_stuffing - 1;
1116 if( i_stuffing > 1 )
1118 p_ts->p_buffer[5] = 0x00;
1119 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1121 p_ts->p_buffer[i] = 0xff;
1126 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1130 BufferChainAppend( c, p_ts );
1134 sout_buffer_t *p_next = p_pes->p_next;
1136 p_pes->p_next = NULL;
1137 sout_BufferDelete( p_sout, p_pes );
1138 if( p_next == NULL )
1142 b_new_pes = VLC_TRUE;
1144 i_size = p_pes->i_size;
1145 p_data = p_pes->p_buffer;
1152 #if defined MODULE_NAME_IS_mux_ts
1153 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1155 static uint32_t CRC32[256] =
1157 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1158 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1159 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1160 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1161 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1162 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1163 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1164 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1165 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1166 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1167 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1168 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1169 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1170 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1171 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1172 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1173 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1174 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1175 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1176 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1177 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1178 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1179 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1180 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1181 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1182 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1183 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1184 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1185 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1186 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1187 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1188 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1189 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1190 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1191 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1192 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1193 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1194 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1195 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1196 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1197 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1198 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1199 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1200 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1201 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1202 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1203 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1204 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1205 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1206 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1207 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1208 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1209 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1210 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1211 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1212 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1213 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1214 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1215 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1216 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1217 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1218 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1219 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1220 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1223 uint32_t i_crc = 0xffffffff;
1225 /* Calculate the CRC */
1226 while( i_count > 0 )
1228 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1236 static void GetPAT( sout_mux_t *p_mux,
1237 sout_buffer_chain_t *c )
1239 sout_mux_sys_t *p_sys = p_mux->p_sys;
1240 sout_buffer_t *p_pat;
1243 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1247 p_pat->i_length = 0;
1249 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1251 bits_write( &bits, 8, 0 ); // pointer
1252 bits_write( &bits, 8, 0x00 ); // table id
1253 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1254 bits_write( &bits, 1, 0 ); // 0
1255 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1256 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1257 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1258 bits_write( &bits, 2, 0x03 ); // FIXME
1259 bits_write( &bits, 5, p_sys->i_pat_version_number );
1260 bits_write( &bits, 1, 1 ); // current_next_indicator
1261 bits_write( &bits, 8, 0 ); // section number
1262 bits_write( &bits, 8, 0 ); // last section number
1264 bits_write( &bits, 16, 1 ); // program number
1265 bits_write( &bits, 3, 0x07 ); // reserved
1266 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1268 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1270 p_pat->i_size = bits.i_data;
1272 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1275 static void GetPMT( sout_mux_t *p_mux,
1276 sout_buffer_chain_t *c )
1278 sout_mux_sys_t *p_sys = p_mux->p_sys;
1279 sout_buffer_t *p_pmt;
1283 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1287 p_pmt->i_length = 0;
1289 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1291 bits_write( &bits, 8, 0 ); // pointer
1292 bits_write( &bits, 8, 0x02 ); // table id
1293 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1294 bits_write( &bits, 1, 0 ); // 0
1295 bits_write( &bits, 2, 0 ); // reserved FIXME
1296 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1297 bits_write( &bits, 16, 1 ); // FIXME program number
1298 bits_write( &bits, 2, 0 ); // FIXME
1299 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1300 bits_write( &bits, 1, 1 ); // current_next_indicator
1301 bits_write( &bits, 8, 0 ); // section number
1302 bits_write( &bits, 8, 0 ); // last section number
1304 bits_write( &bits, 3, 0 ); // reserved
1306 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1307 bits_write( &bits, 4, 0 ); // reserved FIXME
1309 bits_write( &bits, 12, 0 ); // program info len FIXME
1311 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1313 ts_stream_t *p_stream;
1315 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1317 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1318 bits_write( &bits, 3, 0 ); // reserved
1319 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1320 bits_write( &bits, 4, 0 ); //reserved
1321 bits_write( &bits, 12, 0 ); // es info len FIXME
1324 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1326 p_pmt->i_size = bits.i_data;
1328 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1330 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1332 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1333 dvbpsi_psi_section_t* p_section )
1335 sout_buffer_t *p_psi, *p_first = NULL;
1342 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1343 ( p_section->b_syntax_indicator ? 4 : 0 );
1345 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1348 p_psi->i_length = 0;
1349 p_psi->i_size = i_size + 1;
1351 p_psi->p_buffer[0] = 0; // pointer
1352 memcpy( p_psi->p_buffer + 1,
1356 sout_BufferChain( &p_first, p_psi );
1358 p_section = p_section->p_next;
1364 static void GetPAT( sout_mux_t *p_mux,
1365 sout_buffer_chain_t *c )
1367 sout_mux_sys_t *p_sys = p_mux->p_sys;
1368 sout_buffer_t *p_pat;
1370 dvbpsi_psi_section_t *p_section;
1372 dvbpsi_InitPAT( &pat,
1374 p_sys->i_pat_version_number,
1375 1 ); // b_current_next
1376 /* add all program (only one) */
1377 dvbpsi_PATAddProgram( &pat,
1379 p_sys->pmt.i_pid ); // i_pid
1381 p_section = dvbpsi_GenPATSections( &pat,
1382 0 ); // max program per section
1384 p_pat = WritePSISection( p_mux->p_sout, p_section );
1386 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1388 dvbpsi_DeletePSISections( p_section );
1389 dvbpsi_EmptyPAT( &pat );
1392 static uint32_t GetDescriptorLength24b( int i_length )
1394 uint32_t i_l1, i_l2, i_l3;
1396 i_l1 = i_length&0x7f;
1397 i_l2 = ( i_length >> 7 )&0x7f;
1398 i_l3 = ( i_length >> 14 )&0x7f;
1400 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1403 static void GetPMT( sout_mux_t *p_mux,
1404 sout_buffer_chain_t *c )
1406 sout_mux_sys_t *p_sys = p_mux->p_sys;
1407 sout_buffer_t *p_pmt;
1410 dvbpsi_pmt_es_t *p_es;
1411 dvbpsi_psi_section_t *p_section;
1415 dvbpsi_InitPMT( &pmt,
1416 0x01, // program number
1417 p_sys->i_pmt_version_number,
1418 1, // b_current_next
1421 if( p_sys->i_mpeg4_streams > 0 )
1425 bits_buffer_t bits_fix_IOD;
1427 /* Make valgrind happy : it works at byte level not bit one so
1428 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
1429 * working (needed when fixing some bits) */
1430 memset( iod, 0, 4096 );
1432 bits_initwrite( &bits, 4096, iod );
1434 bits_write( &bits, 8, 0x01 );
1435 // InitialObjectDescriptor
1436 bits_align( &bits );
1437 bits_write( &bits, 8, 0x02 ); // tag
1438 bits_fix_IOD = bits; // save states to fix length later
1439 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1440 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1441 bits_write( &bits, 1, 0x00 ); // URL Flag
1442 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1443 bits_write( &bits, 4, 0x0f ); // reserved
1444 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1445 bits_write( &bits, 8, 0xff ); // sceneProfile
1446 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1447 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1448 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1449 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1451 ts_stream_t *p_stream;
1452 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1454 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1456 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1458 bits_align( &bits );
1459 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1460 bits_fix_ESDescr = bits;
1461 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1462 bits_write( &bits, 16, p_stream->i_es_id );
1463 bits_write( &bits, 1, 0x00 ); // streamDependency
1464 bits_write( &bits, 1, 0x00 ); // URL Flag
1465 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1466 bits_write( &bits, 5, 0x1f ); // streamPriority
1468 // DecoderConfigDesciptor
1469 bits_align( &bits );
1470 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1471 bits_fix_Decoder = bits;
1472 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1473 if( p_stream->i_stream_type == 0x10 )
1475 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1476 bits_write( &bits, 6, 0x04 ); // VisualStream
1478 else if( p_stream->i_stream_type == 0x11 )
1480 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1481 bits_write( &bits, 6, 0x05 ); // AudioStream
1485 bits_write( &bits, 8, 0x00 );
1486 bits_write( &bits, 6, 0x00 );
1488 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1490 bits_write( &bits, 1, 0x00 ); // UpStream
1491 bits_write( &bits, 1, 0x01 ); // reserved
1492 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1493 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1494 bits_write( &bits, 32, 0 ); // avgBitrate
1496 if( p_stream->i_decoder_specific_info > 0 )
1499 // DecoderSpecificInfo
1500 bits_align( &bits );
1501 bits_write( &bits, 8, 0x05 ); // tag
1502 bits_write( &bits, 24,
1503 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1504 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1506 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1509 /* fix Decoder length */
1510 bits_write( &bits_fix_Decoder, 24,
1511 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1513 /* SLConfigDescriptor : predifined (0x01) */
1514 bits_align( &bits );
1515 bits_write( &bits, 8, 0x06 ); // tag
1516 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1517 bits_write( &bits, 8, 0x01 ); // predefined
1518 bits_write( &bits, 1, 0 ); // durationFlag
1519 bits_write( &bits, 32, 0 ); // OCRResolution
1520 bits_write( &bits, 8, 0 ); // OCRLength
1521 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1522 bits_align( &bits );
1524 /* fix ESDescr length */
1525 bits_write( &bits_fix_ESDescr, 24,
1526 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1529 bits_align( &bits );
1530 /* fix IOD length */
1531 bits_write( &bits_fix_IOD, 24,
1532 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1533 dvbpsi_PMTAddDescriptor( &pmt,
1539 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1541 ts_stream_t *p_stream;
1543 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1545 p_es = dvbpsi_PMTAddES( &pmt,
1546 p_stream->i_stream_type,
1548 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1553 es_id[0] = (p_stream->i_es_id >> 8)&0xff;
1554 es_id[1] = (p_stream->i_es_id)&0xff;
1555 dvbpsi_PMTESAddDescriptor( p_es, 0x1f, 2, es_id );
1557 else if( p_stream->i_stream_type == 0xa0 )
1560 int i_extra = __MIN( p_stream->i_decoder_specific_info,
1563 /* private DIV3 descripor */
1564 memcpy( &data[0], &p_stream->i_bih_codec, 4 );
1565 data[4] = ( p_stream->i_bih_width >> 8 )&0xff;
1566 data[5] = ( p_stream->i_bih_width )&0xff;
1567 data[6] = ( p_stream->i_bih_height>> 8 )&0xff;
1568 data[7] = ( p_stream->i_bih_height )&0xff;
1569 data[8] = ( i_extra >> 8 )&0xff;
1570 data[9] = ( i_extra )&0xff;
1573 memcpy( &data[10], p_stream->p_decoder_specific_info, i_extra );
1576 /* 0xa0 is private */
1577 dvbpsi_PMTESAddDescriptor( p_es, 0xa0, i_extra + 10, data );
1579 else if( p_stream->i_stream_type == 0x81 )
1581 uint8_t format[4] = { 0x41, 0x43, 0x2d, 0x33 };
1583 /* "registration" descriptor : "AC-3" */
1584 dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
1588 p_section = dvbpsi_GenPMTSections( &pmt );
1590 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1592 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1594 dvbpsi_DeletePSISections( p_section );
1595 dvbpsi_EmptyPMT( &pmt );