1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.38 2003/11/22 16:48:49 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( 'm', 'p','4', 'a' ):
478 p_stream->i_stream_type = 0x11;
479 p_stream->i_stream_id = 0xfa;
480 p_sys->i_mpeg4_streams++;
481 p_stream->i_es_id = p_stream->i_pid;
487 p_sys->i_audio_bound++;
491 switch( p_input->p_fmt->i_codec )
493 case VLC_FOURCC( 's', 'p','u', ' ' ):
494 p_stream->i_stream_type = 0x82;
495 p_stream->i_stream_id = 0x82;
508 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
509 p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra;
510 if( p_stream->i_decoder_specific_info > 0 )
512 p_stream->p_decoder_specific_info =
513 malloc( p_stream->i_decoder_specific_info );
514 memcpy( p_stream->p_decoder_specific_info,
515 p_input->p_fmt->p_extra,
516 p_input->p_fmt->i_extra );
520 BufferChainInit( &p_stream->chain_pes );
521 p_stream->i_pes_dts = 0;
522 p_stream->i_pes_length = 0;
523 p_stream->i_pes_used = 0;
525 /* We only change PMT version (PAT isn't changed) */
526 p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
529 if( p_input->p_fmt->i_cat != SPU_ES &&
530 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
532 if( p_sys->p_pcr_input )
534 /* There was already a PCR stream, so clean context */
537 p_sys->i_pcr_pid = p_stream->i_pid;
538 p_sys->p_pcr_input = p_input;
544 /*****************************************************************************
545 * DelStream: called before a stream deletion
546 *****************************************************************************/
547 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
549 sout_mux_sys_t *p_sys = p_mux->p_sys;
550 ts_stream_t *p_stream;
553 msg_Dbg( p_mux, "removing input" );
554 p_stream = (ts_stream_t*)p_input->p_sys;
556 if( p_sys->i_pcr_pid == p_stream->i_pid )
560 /* Find a new pcr stream (Prefer Video Stream) */
561 p_sys->i_pcr_pid = 0x1fff;
562 p_sys->p_pcr_input = NULL;
563 for( i = 0; i < p_mux->i_nb_inputs; i++ )
565 if( p_mux->pp_inputs[i] == p_input )
570 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
573 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
574 p_sys->p_pcr_input= p_mux->pp_inputs[i];
577 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
578 p_sys->i_pcr_pid == 0x1fff )
581 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
582 p_sys->p_pcr_input= p_mux->pp_inputs[i];
585 if( p_sys->p_pcr_input )
587 /* Empty TS buffer */
592 /* Empty all data in chain_pes */
593 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
595 if( p_stream->p_decoder_specific_info )
597 free( p_stream->p_decoder_specific_info );
599 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
601 p_sys->i_mpeg4_streams--;
603 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) )
605 int i_pid_video = strtol( val, NULL, 0 );
606 if ( i_pid_video == p_stream->i_pid )
608 p_sys->i_pid_video = i_pid_video;
611 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) )
613 int i_pid_audio = strtol( val, NULL, 0 );
614 if ( i_pid_audio == p_stream->i_pid )
616 p_sys->i_pid_audio = i_pid_audio;
621 /* We only change PMT version (PAT isn't changed) */
622 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
627 /*****************************************************************************
628 * Mux: Call each time there is new data for at least one stream
629 *****************************************************************************
631 *****************************************************************************/
632 static int Mux( sout_mux_t *p_mux )
634 sout_mux_sys_t *p_sys = p_mux->p_sys;
635 ts_stream_t *p_pcr_stream;
637 if( p_sys->i_pcr_pid == 0x1fff )
639 msg_Dbg( p_mux, "waiting PCR streams" );
643 p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
647 sout_buffer_chain_t chain_ts;
651 mtime_t i_pcr_length;
654 /* 1: get enough PES packet for all input */
657 vlc_bool_t b_ok = VLC_TRUE;
658 sout_buffer_t *p_data;
660 /* Accumulate enough data in the pcr stream (>i_caching_delay) */
661 /* Accumulate enough data in all other stream ( >= length of pcr) */
662 for( i = 0; i < p_mux->i_nb_inputs; i++ )
664 sout_input_t *p_input = p_mux->pp_inputs[i];
665 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
667 if( ( p_stream == p_pcr_stream && p_stream->i_pes_length <= p_sys->i_caching_delay ) ||
668 p_stream->i_pes_dts + p_stream->i_pes_length < p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
671 if( p_input->p_fifo->i_depth <= 1 )
673 if( p_input->p_fmt->i_cat == AUDIO_ES ||
674 p_input->p_fmt->i_cat == VIDEO_ES )
676 /* We need more data */
679 else if( p_input->p_fifo->i_depth <= 0 )
681 /* spu, only one packet is needed */
687 p_data = sout_FifoGet( p_input->p_fifo );
688 if( p_input->p_fifo->i_depth > 0 )
690 sout_buffer_t *p_next = sout_FifoShow( p_input->p_fifo );
692 p_data->i_length = p_next->i_dts - p_data->i_dts;
695 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 ) ||
696 p_data->i_dts < p_stream->i_pes_dts ||
697 ( p_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > p_stream->i_pes_dts + p_stream->i_pes_length ) )
699 msg_Warn( p_mux, "packet with too strange dts (dts=%lld,old=%lld,pcr=%lld)",
702 p_pcr_stream->i_pes_dts );
703 sout_BufferDelete( p_mux->p_sout, p_data );
705 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
706 p_stream->i_pes_dts = 0;
707 p_stream->i_pes_used = 0;
708 p_stream->i_pes_length = 0;
710 BufferChainClean( p_mux->p_sout, &p_pcr_stream->chain_pes );
711 p_pcr_stream->i_pes_dts = 0;
712 p_pcr_stream->i_pes_used = 0;
713 p_pcr_stream->i_pes_length = 0;
718 p_stream->i_pes_length += p_data->i_length;
719 if( p_stream->i_pes_dts == 0 )
721 p_stream->i_pes_dts = p_data->i_dts;
725 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1 );
727 BufferChainAppend( &p_stream->chain_pes, p_data );
739 i_pcr_dts = p_pcr_stream->i_pes_dts;
740 i_pcr_length = p_pcr_stream->i_pes_length;
742 /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */
743 /* 2: calculate non accurate total size of muxed ts */
745 for( i = 0; i < p_mux->i_nb_inputs; i++ )
747 ts_stream_t *p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
748 sout_buffer_t *p_pes;
750 /* False for pcr stream but it will be eough to do PCR algo */
751 for( p_pes = p_stream->chain_pes.p_first; p_pes != NULL; p_pes = p_pes->p_next )
753 int i_size = p_pes->i_size;
754 if( p_pes->i_dts + p_pes->i_length > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
756 mtime_t i_frag = p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length - p_pes->i_dts;
762 i_size = p_pes->i_size * i_frag / p_pes->i_length;
764 i_packet_count += ( i_size + 183 ) / 184;
767 /* add overhead for PCR (not really exact) */
768 i_packet_count += ( 8 * i_pcr_length / p_sys->i_pcr_delay + 175 ) / 176;
771 /* 3: mux PES into TS */
772 BufferChainInit( &chain_ts );
773 /* append PAT/PMT -> FIXME with big pcr delay it won't have enough pat/pmt */
774 GetPAT( p_mux, &chain_ts);
775 GetPMT( p_mux, &chain_ts );
777 i_packet_count += chain_ts.i_depth;
778 /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */
784 ts_stream_t *p_stream;
788 /* Select stream (lowest dts)*/
789 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
791 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
793 if( p_stream->i_pes_dts == 0 )
798 if( i_stream == -1 ||
799 p_stream->i_pes_dts < i_dts )
802 i_dts = p_stream->i_pes_dts;
809 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
811 /* do we need to issue pcr */
813 if( p_stream == p_pcr_stream &&
814 i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count >= p_sys->i_pcr + p_sys->i_pcr_delay )
817 p_sys->i_pcr = i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count;
820 /* Build the TS packet */
821 p_ts = TSNew( p_mux, p_stream, b_pcr );
825 BufferChainAppend( &chain_ts, p_ts );
828 /* 4: date and send */
829 i_packet_count = chain_ts.i_depth;
830 /* msg_Dbg( p_mux, "real pck=%d", i_packet_count ); */
831 for( i = 0; i < i_packet_count; i++ )
833 sout_buffer_t *p_ts = BufferChainGet( &chain_ts );
835 p_ts->i_dts = i_pcr_dts + i_pcr_length * i / i_packet_count;
836 p_ts->i_length = i_pcr_length / i_packet_count;
838 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR )
840 /* msg_Dbg( p_mux, "pcr=%lld ms", p_ts->i_dts / 1000 ); */
841 TSSetPCR( p_ts, p_ts->i_dts - p_sys->i_dts_delay );
845 p_ts->i_dts += 3*p_sys->i_caching_delay/2;
847 sout_AccessOutWrite( p_mux->p_access, p_ts );
852 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr )
854 sout_buffer_t *p_pes = p_stream->chain_pes.p_first;
857 vlc_bool_t b_new_pes = VLC_FALSE;
858 vlc_bool_t b_adaptation_field = VLC_FALSE;
860 int i_payload_max = 184 - ( b_pcr ? 8 : 0 );
863 if( p_stream->i_pes_used <= 0 )
865 b_new_pes = VLC_TRUE;
867 i_payload = __MIN( (int)p_pes->i_size - p_stream->i_pes_used, i_payload_max );
869 if( b_pcr || i_payload < i_payload_max )
871 b_adaptation_field = VLC_TRUE;
874 p_ts = sout_BufferNew( p_mux->p_sout, 188 );
876 p_ts->p_buffer[0] = 0x47;
877 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|( ( p_stream->i_pid >> 8 )&0x1f );
878 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
879 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|p_stream->i_continuity_counter;
881 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
883 if( b_adaptation_field )
889 int i_stuffing = i_payload_max - i_payload;
891 p_ts->i_flags |= SOUT_BUFFER_FLAGS_PRIVATE_PCR;
893 p_ts->p_buffer[4] = 7 + i_stuffing;
894 p_ts->p_buffer[5] = 0x10; /* flags */
895 p_ts->p_buffer[6] = ( 0 )&0xff;
896 p_ts->p_buffer[7] = ( 0 )&0xff;
897 p_ts->p_buffer[8] = ( 0 )&0xff;
898 p_ts->p_buffer[9] = ( 0 )&0xff;
899 p_ts->p_buffer[10]= ( 0 )&0x80;
900 p_ts->p_buffer[11]= 0;
902 for( i = 12; i < 12 + i_stuffing; i++ )
904 p_ts->p_buffer[i] = 0xff;
909 int i_stuffing = i_payload_max - i_payload;
911 p_ts->p_buffer[4] = i_stuffing - 1;
914 p_ts->p_buffer[5] = 0x00;
915 for( i = 6; i < 6 + i_stuffing - 2; i++ )
917 p_ts->p_buffer[i] = 0xff;
924 memcpy( &p_ts->p_buffer[188 - i_payload], &p_pes->p_buffer[p_stream->i_pes_used], i_payload );
926 p_stream->i_pes_used += i_payload;
927 p_stream->i_pes_dts = p_pes->i_dts + p_pes->i_length * p_stream->i_pes_used / p_pes->i_size;
928 p_stream->i_pes_length -= p_pes->i_length * i_payload / p_pes->i_size;
930 if( p_stream->i_pes_used >= (int)p_pes->i_size )
932 p_pes = BufferChainGet( &p_stream->chain_pes );
933 sout_BufferDelete( p_mux->p_sout, p_pes );
935 p_pes = p_stream->chain_pes.p_first;
938 p_stream->i_pes_dts = p_pes->i_dts;
939 p_stream->i_pes_length = 0;
942 p_stream->i_pes_length += p_pes->i_length;
944 p_pes = p_pes->p_next;
949 p_stream->i_pes_dts = 0;
950 p_stream->i_pes_length = 0;
952 p_stream->i_pes_used = 0;
959 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts )
961 mtime_t i_pcr = 9 * i_dts / 100;
963 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
964 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
965 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
966 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
967 p_ts->p_buffer[10]|= ( i_pcr << 7 )&0x80;
971 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 )
973 sout_mux_sys_t *p_sys = p_mux->p_sys;
974 sout_buffer_chain_t s = *c;
977 int i_packets_min = 0;
978 int i_packets_max = 0;
985 i_packets = c->i_depth;
986 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
987 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
989 if( i_packets < i_packets_min && i_packets_min > 0 )
992 int i_div = ( i_packets_min - i_packets ) / i_packets;
993 int i_mod = ( i_packets_min - i_packets ) % i_packets;
996 /* We need to pad with null packets (pid=0x1fff)
997 * We try to melt null packets with true packets */
999 "packets=%d but min=%d -> adding %d packets of padding",
1000 i_packets, i_packets_min, i_packets_min - i_packets );
1002 BufferChainInit( c );
1003 while( ( p_pk = BufferChainGet( &s ) ) )
1007 BufferChainAppend( c, p_pk );
1009 i_null = i_div + ( i_rest + i_mod ) / i_packets;
1011 for( i = 0; i < i_null; i++ )
1013 sout_buffer_t *p_null;
1015 p_null = sout_BufferNew( p_mux->p_sout, 188 );
1016 p_null->p_buffer[0] = 0x47;
1017 p_null->p_buffer[1] = 0x1f;
1018 p_null->p_buffer[2] = 0xff;
1019 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
1020 memset( &p_null->p_buffer[4], 0, 184 );
1021 p_sys->i_null_continuity_counter =
1022 ( p_sys->i_null_continuity_counter + 1 ) % 16;
1024 BufferChainAppend( c, p_null );
1027 i_rest = ( i_rest + i_mod ) % i_packets;
1030 else if( i_packets > i_packets_max && i_packets_max > 0 )
1032 sout_buffer_t *p_pk;
1035 /* Arg, we need to drop packets, I don't do something clever (like
1036 * dropping complete pid, b frames, ... ), I just get the right amount
1037 * of packets and discard the others */
1039 "packets=%d but max=%d -> removing %d packets -> stream broken",
1040 i_packets, i_packets_max, i_packets - i_packets_max );
1042 BufferChainInit( c );
1043 for( i = 0; i < i_packets_max; i++ )
1045 BufferChainAppend( c, BufferChainGet( &s ) );
1048 while( ( p_pk = BufferChainGet( &s ) ) )
1050 sout_BufferDelete( p_mux->p_sout, p_pk );
1056 static void PEStoTS( sout_instance_t *p_sout,
1057 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
1058 ts_stream_t *p_stream )
1064 /* get PES total size */
1065 i_size = p_pes->i_size;
1066 p_data = p_pes->p_buffer;
1068 b_new_pes = VLC_TRUE;
1072 int b_adaptation_field;
1074 sout_buffer_t *p_ts;
1076 p_ts = sout_BufferNew( p_sout, 188 );
1079 * 1b transport_error_indicator
1080 * 1b payload_unit_start
1081 * 1b transport_priority
1083 * 2b transport_scrambling_control
1084 * 2b if adaptation_field 0x03 else 0x01
1085 * 4b continuity_counter
1088 i_copy = __MIN( i_size, 184 );
1089 b_adaptation_field = i_size < 184 ? VLC_TRUE : VLC_FALSE;
1091 p_ts->p_buffer[0] = 0x47;
1092 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
1093 ( ( p_stream->i_pid >> 8 )&0x1f );
1094 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
1095 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
1096 p_stream->i_continuity_counter;
1098 b_new_pes = VLC_FALSE;
1099 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
1101 if( b_adaptation_field )
1103 int i_stuffing = 184 - i_copy;
1106 p_ts->p_buffer[4] = i_stuffing - 1;
1107 if( i_stuffing > 1 )
1109 p_ts->p_buffer[5] = 0x00;
1110 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1112 p_ts->p_buffer[i] = 0xff;
1117 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1121 BufferChainAppend( c, p_ts );
1125 sout_buffer_t *p_next = p_pes->p_next;
1127 p_pes->p_next = NULL;
1128 sout_BufferDelete( p_sout, p_pes );
1129 if( p_next == NULL )
1133 b_new_pes = VLC_TRUE;
1135 i_size = p_pes->i_size;
1136 p_data = p_pes->p_buffer;
1143 #if defined MODULE_NAME_IS_mux_ts
1144 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1146 static uint32_t CRC32[256] =
1148 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1149 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1150 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1151 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1152 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1153 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1154 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1155 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1156 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1157 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1158 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1159 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1160 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1161 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1162 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1163 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1164 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1165 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1166 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1167 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1168 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1169 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1170 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1171 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1172 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1173 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1174 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1175 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1176 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1177 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1178 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1179 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1180 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1181 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1182 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1183 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1184 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1185 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1186 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1187 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1188 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1189 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1190 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1191 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1192 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1193 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1194 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1195 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1196 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1197 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1198 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1199 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1200 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1201 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1202 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1203 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1204 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1205 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1206 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1207 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1208 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1209 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1210 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1211 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1214 uint32_t i_crc = 0xffffffff;
1216 /* Calculate the CRC */
1217 while( i_count > 0 )
1219 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1227 static void GetPAT( sout_mux_t *p_mux,
1228 sout_buffer_chain_t *c )
1230 sout_mux_sys_t *p_sys = p_mux->p_sys;
1231 sout_buffer_t *p_pat;
1234 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1238 p_pat->i_length = 0;
1240 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1242 bits_write( &bits, 8, 0 ); // pointer
1243 bits_write( &bits, 8, 0x00 ); // table id
1244 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1245 bits_write( &bits, 1, 0 ); // 0
1246 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1247 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1248 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1249 bits_write( &bits, 2, 0x03 ); // FIXME
1250 bits_write( &bits, 5, p_sys->i_pat_version_number );
1251 bits_write( &bits, 1, 1 ); // current_next_indicator
1252 bits_write( &bits, 8, 0 ); // section number
1253 bits_write( &bits, 8, 0 ); // last section number
1255 bits_write( &bits, 16, 1 ); // program number
1256 bits_write( &bits, 3, 0x07 ); // reserved
1257 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1259 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1261 p_pat->i_size = bits.i_data;
1263 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1266 static void GetPMT( sout_mux_t *p_mux,
1267 sout_buffer_chain_t *c )
1269 sout_mux_sys_t *p_sys = p_mux->p_sys;
1270 sout_buffer_t *p_pmt;
1274 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1278 p_pmt->i_length = 0;
1280 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1282 bits_write( &bits, 8, 0 ); // pointer
1283 bits_write( &bits, 8, 0x02 ); // table id
1284 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1285 bits_write( &bits, 1, 0 ); // 0
1286 bits_write( &bits, 2, 0 ); // reserved FIXME
1287 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1288 bits_write( &bits, 16, 1 ); // FIXME program number
1289 bits_write( &bits, 2, 0 ); // FIXME
1290 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1291 bits_write( &bits, 1, 1 ); // current_next_indicator
1292 bits_write( &bits, 8, 0 ); // section number
1293 bits_write( &bits, 8, 0 ); // last section number
1295 bits_write( &bits, 3, 0 ); // reserved
1297 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1298 bits_write( &bits, 4, 0 ); // reserved FIXME
1300 bits_write( &bits, 12, 0 ); // program info len FIXME
1302 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1304 ts_stream_t *p_stream;
1306 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1308 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1309 bits_write( &bits, 3, 0 ); // reserved
1310 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1311 bits_write( &bits, 4, 0 ); //reserved
1312 bits_write( &bits, 12, 0 ); // es info len FIXME
1315 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1317 p_pmt->i_size = bits.i_data;
1319 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1321 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1323 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1324 dvbpsi_psi_section_t* p_section )
1326 sout_buffer_t *p_psi, *p_first = NULL;
1333 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1334 ( p_section->b_syntax_indicator ? 4 : 0 );
1336 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1339 p_psi->i_length = 0;
1340 p_psi->i_size = i_size + 1;
1342 p_psi->p_buffer[0] = 0; // pointer
1343 memcpy( p_psi->p_buffer + 1,
1347 sout_BufferChain( &p_first, p_psi );
1349 p_section = p_section->p_next;
1355 static void GetPAT( sout_mux_t *p_mux,
1356 sout_buffer_chain_t *c )
1358 sout_mux_sys_t *p_sys = p_mux->p_sys;
1359 sout_buffer_t *p_pat;
1361 dvbpsi_psi_section_t *p_section;
1363 dvbpsi_InitPAT( &pat,
1365 p_sys->i_pat_version_number,
1366 1 ); // b_current_next
1367 /* add all program (only one) */
1368 dvbpsi_PATAddProgram( &pat,
1370 p_sys->pmt.i_pid ); // i_pid
1372 p_section = dvbpsi_GenPATSections( &pat,
1373 0 ); // max program per section
1375 p_pat = WritePSISection( p_mux->p_sout, p_section );
1377 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1379 dvbpsi_DeletePSISections( p_section );
1380 dvbpsi_EmptyPAT( &pat );
1383 static uint32_t GetDescriptorLength24b( int i_length )
1385 uint32_t i_l1, i_l2, i_l3;
1387 i_l1 = i_length&0x7f;
1388 i_l2 = ( i_length >> 7 )&0x7f;
1389 i_l3 = ( i_length >> 14 )&0x7f;
1391 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1394 static void GetPMT( sout_mux_t *p_mux,
1395 sout_buffer_chain_t *c )
1397 sout_mux_sys_t *p_sys = p_mux->p_sys;
1398 sout_buffer_t *p_pmt;
1401 dvbpsi_pmt_es_t *p_es;
1402 dvbpsi_psi_section_t *p_section;
1406 dvbpsi_InitPMT( &pmt,
1407 0x01, // program number
1408 p_sys->i_pmt_version_number,
1409 1, // b_current_next
1412 if( p_sys->i_mpeg4_streams > 0 )
1416 bits_buffer_t bits_fix_IOD;
1418 /* Make valgrind happy : it works at byte level not bit one so
1419 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
1420 * working (needed when fixing some bits) */
1421 memset( iod, 0, 4096 );
1423 bits_initwrite( &bits, 4096, iod );
1425 bits_write( &bits, 8, 0x01 );
1426 // InitialObjectDescriptor
1427 bits_align( &bits );
1428 bits_write( &bits, 8, 0x02 ); // tag
1429 bits_fix_IOD = bits; // save states to fix length later
1430 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1431 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1432 bits_write( &bits, 1, 0x00 ); // URL Flag
1433 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1434 bits_write( &bits, 4, 0x0f ); // reserved
1435 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1436 bits_write( &bits, 8, 0xff ); // sceneProfile
1437 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1438 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1439 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1440 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1442 ts_stream_t *p_stream;
1443 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1445 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1447 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1449 bits_align( &bits );
1450 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1451 bits_fix_ESDescr = bits;
1452 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1453 bits_write( &bits, 16, p_stream->i_es_id );
1454 bits_write( &bits, 1, 0x00 ); // streamDependency
1455 bits_write( &bits, 1, 0x00 ); // URL Flag
1456 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1457 bits_write( &bits, 5, 0x1f ); // streamPriority
1459 // DecoderConfigDesciptor
1460 bits_align( &bits );
1461 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1462 bits_fix_Decoder = bits;
1463 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1464 if( p_stream->i_stream_type == 0x10 )
1466 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1467 bits_write( &bits, 6, 0x04 ); // VisualStream
1469 else if( p_stream->i_stream_type == 0x11 )
1471 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1472 bits_write( &bits, 6, 0x05 ); // AudioStream
1476 bits_write( &bits, 8, 0x00 );
1477 bits_write( &bits, 6, 0x00 );
1479 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1481 bits_write( &bits, 1, 0x00 ); // UpStream
1482 bits_write( &bits, 1, 0x01 ); // reserved
1483 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1484 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1485 bits_write( &bits, 32, 0 ); // avgBitrate
1487 if( p_stream->i_decoder_specific_info > 0 )
1490 // DecoderSpecificInfo
1491 bits_align( &bits );
1492 bits_write( &bits, 8, 0x05 ); // tag
1493 bits_write( &bits, 24,
1494 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1495 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1497 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1500 /* fix Decoder length */
1501 bits_write( &bits_fix_Decoder, 24,
1502 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1504 /* SLConfigDescriptor : predifined (0x01) */
1505 bits_align( &bits );
1506 bits_write( &bits, 8, 0x06 ); // tag
1507 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1508 bits_write( &bits, 8, 0x01 ); // predefined
1509 bits_write( &bits, 1, 0 ); // durationFlag
1510 bits_write( &bits, 32, 0 ); // OCRResolution
1511 bits_write( &bits, 8, 0 ); // OCRLength
1512 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1513 bits_align( &bits );
1515 /* fix ESDescr length */
1516 bits_write( &bits_fix_ESDescr, 24,
1517 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1520 bits_align( &bits );
1521 /* fix IOD length */
1522 bits_write( &bits_fix_IOD, 24,
1523 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1524 dvbpsi_PMTAddDescriptor( &pmt,
1530 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1532 ts_stream_t *p_stream;
1534 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1536 p_es = dvbpsi_PMTAddES( &pmt,
1537 p_stream->i_stream_type,
1539 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1544 es_id[0] = (p_stream->i_es_id >> 8)&0xff;
1545 es_id[1] = (p_stream->i_es_id)&0xff;
1546 dvbpsi_PMTESAddDescriptor( p_es, 0x1f, 2, es_id );
1548 else if( p_stream->i_stream_type == 0xa0 )
1551 int i_extra = __MIN( p_stream->i_decoder_specific_info,
1554 /* private DIV3 descripor */
1555 memcpy( &data[0], &p_stream->i_bih_codec, 4 );
1556 data[4] = ( p_stream->i_bih_width >> 8 )&0xff;
1557 data[5] = ( p_stream->i_bih_width )&0xff;
1558 data[6] = ( p_stream->i_bih_height>> 8 )&0xff;
1559 data[7] = ( p_stream->i_bih_height )&0xff;
1560 data[8] = ( i_extra >> 8 )&0xff;
1561 data[9] = ( i_extra )&0xff;
1564 memcpy( &data[10], p_stream->p_decoder_specific_info, i_extra );
1567 /* 0xa0 is private */
1568 dvbpsi_PMTESAddDescriptor( p_es, 0xa0, i_extra + 10, data );
1570 else if( p_stream->i_stream_type == 0x81 )
1572 uint8_t format[4] = { 0x41, 0x43, 0x2d, 0x33 };
1574 /* "registration" descriptor : "AC-3" */
1575 dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
1579 p_section = dvbpsi_GenPMTSections( &pmt );
1581 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1583 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1585 dvbpsi_DeletePSISections( p_section );
1586 dvbpsi_EmptyPMT( &pmt );