1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.36 2003/11/20 18:26:44 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_fourcc );
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_fourcc )
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_fourcc;
455 p_stream->i_bih_width = p_input->p_fmt->i_width;
456 p_stream->i_bih_height = p_input->p_fmt->i_height;
462 p_sys->i_video_bound++;
466 switch( p_input->p_fmt->i_fourcc )
468 case VLC_FOURCC( 'm', 'p','g', 'a' ):
469 p_stream->i_stream_type = p_input->p_fmt->i_sample_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_fourcc )
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_data;
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_data,
516 p_input->p_fmt->i_extra_data );
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->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 );
689 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 ) ||
690 p_data->i_dts < p_stream->i_pes_dts ||
691 ( p_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > p_stream->i_pes_dts + p_stream->i_pes_length ) )
693 msg_Warn( p_mux, "packet with too strange dts (dts=%lld,old=%lld,pcr=%lld)",
696 p_pcr_stream->i_pes_dts );
697 sout_BufferDelete( p_mux->p_sout, p_data );
699 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
700 p_stream->i_pes_dts = 0;
701 p_stream->i_pes_used = 0;
702 p_stream->i_pes_length = 0;
704 BufferChainClean( p_mux->p_sout, &p_pcr_stream->chain_pes );
705 p_pcr_stream->i_pes_dts = 0;
706 p_pcr_stream->i_pes_used = 0;
707 p_pcr_stream->i_pes_length = 0;
712 p_stream->i_pes_length += p_data->i_length;
713 if( p_stream->i_pes_dts == 0 )
715 p_stream->i_pes_dts = p_data->i_dts;
719 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1 );
721 BufferChainAppend( &p_stream->chain_pes, p_data );
733 i_pcr_dts = p_pcr_stream->i_pes_dts;
734 i_pcr_length = p_pcr_stream->i_pes_length;
736 /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */
737 /* 2: calculate non accurate total size of muxed ts */
739 for( i = 0; i < p_mux->i_nb_inputs; i++ )
741 ts_stream_t *p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
742 sout_buffer_t *p_pes;
744 /* False for pcr stream but it will be eough to do PCR algo */
745 for( p_pes = p_stream->chain_pes.p_first; p_pes != NULL; p_pes = p_pes->p_next )
747 int i_size = p_pes->i_size;
748 if( p_pes->i_dts + p_pes->i_length > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
750 mtime_t i_frag = p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length - p_pes->i_dts;
756 i_size = p_pes->i_size * i_frag / p_pes->i_length;
758 i_packet_count += ( i_size + 183 ) / 184;
761 /* add overhead for PCR (not really exact) */
762 i_packet_count += ( 8 * i_pcr_length / p_sys->i_pcr_delay + 175 ) / 176;
765 /* 3: mux PES into TS */
766 BufferChainInit( &chain_ts );
767 /* append PAT/PMT -> FIXME with big pcr delay it won't have enough pat/pmt */
768 GetPAT( p_mux, &chain_ts);
769 GetPMT( p_mux, &chain_ts );
771 i_packet_count += chain_ts.i_depth;
772 /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */
778 ts_stream_t *p_stream;
782 /* Select stream (lowest dts)*/
783 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
785 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
787 if( p_stream->i_pes_dts == 0 )
792 if( i_stream == -1 ||
793 p_stream->i_pes_dts < i_dts )
796 i_dts = p_stream->i_pes_dts;
803 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
805 /* do we need to issue pcr */
807 if( p_stream == p_pcr_stream &&
808 i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count >= p_sys->i_pcr + p_sys->i_pcr_delay )
811 p_sys->i_pcr = i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count;
814 /* Build the TS packet */
815 p_ts = TSNew( p_mux, p_stream, b_pcr );
819 BufferChainAppend( &chain_ts, p_ts );
822 /* 4: date and send */
823 i_packet_count = chain_ts.i_depth;
824 /* msg_Dbg( p_mux, "real pck=%d", i_packet_count ); */
825 for( i = 0; i < i_packet_count; i++ )
827 sout_buffer_t *p_ts = BufferChainGet( &chain_ts );
829 p_ts->i_dts = i_pcr_dts + i_pcr_length * i / i_packet_count;
830 p_ts->i_length = i_pcr_length / i_packet_count;
832 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR )
834 /* msg_Dbg( p_mux, "pcr=%lld ms", p_ts->i_dts / 1000 ); */
835 TSSetPCR( p_ts, p_ts->i_dts - p_sys->i_dts_delay );
839 p_ts->i_dts += 3*p_sys->i_caching_delay/2;
841 sout_AccessOutWrite( p_mux->p_access, p_ts );
846 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr )
848 sout_buffer_t *p_pes = p_stream->chain_pes.p_first;
851 vlc_bool_t b_new_pes = VLC_FALSE;
852 vlc_bool_t b_adaptation_field = VLC_FALSE;
854 int i_payload_max = 184 - ( b_pcr ? 8 : 0 );
857 if( p_stream->i_pes_used <= 0 )
859 b_new_pes = VLC_TRUE;
861 i_payload = __MIN( (int)p_pes->i_size - p_stream->i_pes_used, i_payload_max );
863 if( b_pcr || i_payload < i_payload_max )
865 b_adaptation_field = VLC_TRUE;
868 p_ts = sout_BufferNew( p_mux->p_sout, 188 );
870 p_ts->p_buffer[0] = 0x47;
871 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|( ( p_stream->i_pid >> 8 )&0x1f );
872 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
873 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|p_stream->i_continuity_counter;
875 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
877 if( b_adaptation_field )
883 int i_stuffing = i_payload_max - i_payload;
885 p_ts->i_flags |= SOUT_BUFFER_FLAGS_PRIVATE_PCR;
887 p_ts->p_buffer[4] = 7 + i_stuffing;
888 p_ts->p_buffer[5] = 0x10; /* flags */
889 p_ts->p_buffer[6] = ( 0 )&0xff;
890 p_ts->p_buffer[7] = ( 0 )&0xff;
891 p_ts->p_buffer[8] = ( 0 )&0xff;
892 p_ts->p_buffer[9] = ( 0 )&0xff;
893 p_ts->p_buffer[10]= ( 0 )&0x80;
894 p_ts->p_buffer[11]= 0;
896 for( i = 12; i < 12 + i_stuffing; i++ )
898 p_ts->p_buffer[i] = 0xff;
903 int i_stuffing = i_payload_max - i_payload;
905 p_ts->p_buffer[4] = i_stuffing - 1;
908 p_ts->p_buffer[5] = 0x00;
909 for( i = 6; i < 6 + i_stuffing - 2; i++ )
911 p_ts->p_buffer[i] = 0xff;
918 memcpy( &p_ts->p_buffer[188 - i_payload], &p_pes->p_buffer[p_stream->i_pes_used], i_payload );
920 p_stream->i_pes_used += i_payload;
921 p_stream->i_pes_dts = p_pes->i_dts + p_pes->i_length * p_stream->i_pes_used / p_pes->i_size;
922 p_stream->i_pes_length -= p_pes->i_length * i_payload / p_pes->i_size;
924 if( p_stream->i_pes_used >= (int)p_pes->i_size )
926 p_pes = BufferChainGet( &p_stream->chain_pes );
927 sout_BufferDelete( p_mux->p_sout, p_pes );
929 p_pes = p_stream->chain_pes.p_first;
932 p_stream->i_pes_dts = p_pes->i_dts;
933 p_stream->i_pes_length = 0;
936 p_stream->i_pes_length += p_pes->i_length;
938 p_pes = p_pes->p_next;
943 p_stream->i_pes_dts = 0;
944 p_stream->i_pes_length = 0;
946 p_stream->i_pes_used = 0;
953 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts )
955 mtime_t i_pcr = 9 * i_dts / 100;
957 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
958 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
959 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
960 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
961 p_ts->p_buffer[10]|= ( i_pcr << 7 )&0x80;
965 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 )
967 sout_mux_sys_t *p_sys = p_mux->p_sys;
968 sout_buffer_chain_t s = *c;
971 int i_packets_min = 0;
972 int i_packets_max = 0;
979 i_packets = c->i_depth;
980 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
981 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
983 if( i_packets < i_packets_min && i_packets_min > 0 )
986 int i_div = ( i_packets_min - i_packets ) / i_packets;
987 int i_mod = ( i_packets_min - i_packets ) % i_packets;
990 /* We need to pad with null packets (pid=0x1fff)
991 * We try to melt null packets with true packets */
993 "packets=%d but min=%d -> adding %d packets of padding",
994 i_packets, i_packets_min, i_packets_min - i_packets );
996 BufferChainInit( c );
997 while( ( p_pk = BufferChainGet( &s ) ) )
1001 BufferChainAppend( c, p_pk );
1003 i_null = i_div + ( i_rest + i_mod ) / i_packets;
1005 for( i = 0; i < i_null; i++ )
1007 sout_buffer_t *p_null;
1009 p_null = sout_BufferNew( p_mux->p_sout, 188 );
1010 p_null->p_buffer[0] = 0x47;
1011 p_null->p_buffer[1] = 0x1f;
1012 p_null->p_buffer[2] = 0xff;
1013 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
1014 memset( &p_null->p_buffer[4], 0, 184 );
1015 p_sys->i_null_continuity_counter =
1016 ( p_sys->i_null_continuity_counter + 1 ) % 16;
1018 BufferChainAppend( c, p_null );
1021 i_rest = ( i_rest + i_mod ) % i_packets;
1024 else if( i_packets > i_packets_max && i_packets_max > 0 )
1026 sout_buffer_t *p_pk;
1029 /* Arg, we need to drop packets, I don't do something clever (like
1030 * dropping complete pid, b frames, ... ), I just get the right amount
1031 * of packets and discard the others */
1033 "packets=%d but max=%d -> removing %d packets -> stream broken",
1034 i_packets, i_packets_max, i_packets - i_packets_max );
1036 BufferChainInit( c );
1037 for( i = 0; i < i_packets_max; i++ )
1039 BufferChainAppend( c, BufferChainGet( &s ) );
1042 while( ( p_pk = BufferChainGet( &s ) ) )
1044 sout_BufferDelete( p_mux->p_sout, p_pk );
1050 static void PEStoTS( sout_instance_t *p_sout,
1051 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
1052 ts_stream_t *p_stream )
1058 /* get PES total size */
1059 i_size = p_pes->i_size;
1060 p_data = p_pes->p_buffer;
1062 b_new_pes = VLC_TRUE;
1066 int b_adaptation_field;
1068 sout_buffer_t *p_ts;
1070 p_ts = sout_BufferNew( p_sout, 188 );
1073 * 1b transport_error_indicator
1074 * 1b payload_unit_start
1075 * 1b transport_priority
1077 * 2b transport_scrambling_control
1078 * 2b if adaptation_field 0x03 else 0x01
1079 * 4b continuity_counter
1082 i_copy = __MIN( i_size, 184 );
1083 b_adaptation_field = i_size < 184 ? VLC_TRUE : VLC_FALSE;
1085 p_ts->p_buffer[0] = 0x47;
1086 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
1087 ( ( p_stream->i_pid >> 8 )&0x1f );
1088 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
1089 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
1090 p_stream->i_continuity_counter;
1092 b_new_pes = VLC_FALSE;
1093 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
1095 if( b_adaptation_field )
1097 int i_stuffing = 184 - i_copy;
1100 p_ts->p_buffer[4] = i_stuffing - 1;
1101 if( i_stuffing > 1 )
1103 p_ts->p_buffer[5] = 0x00;
1104 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1106 p_ts->p_buffer[i] = 0xff;
1111 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1115 BufferChainAppend( c, p_ts );
1119 sout_buffer_t *p_next = p_pes->p_next;
1121 p_pes->p_next = NULL;
1122 sout_BufferDelete( p_sout, p_pes );
1123 if( p_next == NULL )
1127 b_new_pes = VLC_TRUE;
1129 i_size = p_pes->i_size;
1130 p_data = p_pes->p_buffer;
1137 #if defined MODULE_NAME_IS_mux_ts
1138 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1140 static uint32_t CRC32[256] =
1142 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1143 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1144 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1145 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1146 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1147 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1148 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1149 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1150 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1151 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1152 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1153 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1154 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1155 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1156 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1157 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1158 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1159 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1160 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1161 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1162 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1163 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1164 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1165 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1166 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1167 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1168 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1169 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1170 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1171 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1172 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1173 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1174 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1175 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1176 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1177 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1178 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1179 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1180 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1181 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1182 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1183 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1184 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1185 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1186 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1187 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1188 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1189 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1190 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1191 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1192 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1193 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1194 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1195 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1196 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1197 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1198 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1199 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1200 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1201 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1202 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1203 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1204 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1205 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1208 uint32_t i_crc = 0xffffffff;
1210 /* Calculate the CRC */
1211 while( i_count > 0 )
1213 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1221 static void GetPAT( sout_mux_t *p_mux,
1222 sout_buffer_chain_t *c )
1224 sout_mux_sys_t *p_sys = p_mux->p_sys;
1225 sout_buffer_t *p_pat;
1228 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1232 p_pat->i_length = 0;
1234 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1236 bits_write( &bits, 8, 0 ); // pointer
1237 bits_write( &bits, 8, 0x00 ); // table id
1238 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1239 bits_write( &bits, 1, 0 ); // 0
1240 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1241 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1242 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1243 bits_write( &bits, 2, 0x03 ); // FIXME
1244 bits_write( &bits, 5, p_sys->i_pat_version_number );
1245 bits_write( &bits, 1, 1 ); // current_next_indicator
1246 bits_write( &bits, 8, 0 ); // section number
1247 bits_write( &bits, 8, 0 ); // last section number
1249 bits_write( &bits, 16, 1 ); // program number
1250 bits_write( &bits, 3, 0x07 ); // reserved
1251 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1253 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1255 p_pat->i_size = bits.i_data;
1257 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1260 static void GetPMT( sout_mux_t *p_mux,
1261 sout_buffer_chain_t *c )
1263 sout_mux_sys_t *p_sys = p_mux->p_sys;
1264 sout_buffer_t *p_pmt;
1268 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1272 p_pmt->i_length = 0;
1274 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1276 bits_write( &bits, 8, 0 ); // pointer
1277 bits_write( &bits, 8, 0x02 ); // table id
1278 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1279 bits_write( &bits, 1, 0 ); // 0
1280 bits_write( &bits, 2, 0 ); // reserved FIXME
1281 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1282 bits_write( &bits, 16, 1 ); // FIXME program number
1283 bits_write( &bits, 2, 0 ); // FIXME
1284 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1285 bits_write( &bits, 1, 1 ); // current_next_indicator
1286 bits_write( &bits, 8, 0 ); // section number
1287 bits_write( &bits, 8, 0 ); // last section number
1289 bits_write( &bits, 3, 0 ); // reserved
1291 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1292 bits_write( &bits, 4, 0 ); // reserved FIXME
1294 bits_write( &bits, 12, 0 ); // program info len FIXME
1296 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1298 ts_stream_t *p_stream;
1300 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1302 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1303 bits_write( &bits, 3, 0 ); // reserved
1304 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1305 bits_write( &bits, 4, 0 ); //reserved
1306 bits_write( &bits, 12, 0 ); // es info len FIXME
1309 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1311 p_pmt->i_size = bits.i_data;
1313 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1315 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1317 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1318 dvbpsi_psi_section_t* p_section )
1320 sout_buffer_t *p_psi, *p_first = NULL;
1327 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1328 ( p_section->b_syntax_indicator ? 4 : 0 );
1330 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1333 p_psi->i_length = 0;
1334 p_psi->i_size = i_size + 1;
1336 p_psi->p_buffer[0] = 0; // pointer
1337 memcpy( p_psi->p_buffer + 1,
1341 sout_BufferChain( &p_first, p_psi );
1343 p_section = p_section->p_next;
1349 static void GetPAT( sout_mux_t *p_mux,
1350 sout_buffer_chain_t *c )
1352 sout_mux_sys_t *p_sys = p_mux->p_sys;
1353 sout_buffer_t *p_pat;
1355 dvbpsi_psi_section_t *p_section;
1357 dvbpsi_InitPAT( &pat,
1359 p_sys->i_pat_version_number,
1360 1 ); // b_current_next
1361 /* add all program (only one) */
1362 dvbpsi_PATAddProgram( &pat,
1364 p_sys->pmt.i_pid ); // i_pid
1366 p_section = dvbpsi_GenPATSections( &pat,
1367 0 ); // max program per section
1369 p_pat = WritePSISection( p_mux->p_sout, p_section );
1371 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1373 dvbpsi_DeletePSISections( p_section );
1374 dvbpsi_EmptyPAT( &pat );
1377 static uint32_t GetDescriptorLength24b( int i_length )
1379 uint32_t i_l1, i_l2, i_l3;
1381 i_l1 = i_length&0x7f;
1382 i_l2 = ( i_length >> 7 )&0x7f;
1383 i_l3 = ( i_length >> 14 )&0x7f;
1385 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1388 static void GetPMT( sout_mux_t *p_mux,
1389 sout_buffer_chain_t *c )
1391 sout_mux_sys_t *p_sys = p_mux->p_sys;
1392 sout_buffer_t *p_pmt;
1395 dvbpsi_pmt_es_t *p_es;
1396 dvbpsi_psi_section_t *p_section;
1400 dvbpsi_InitPMT( &pmt,
1401 0x01, // program number
1402 p_sys->i_pmt_version_number,
1403 1, // b_current_next
1406 if( p_sys->i_mpeg4_streams > 0 )
1410 bits_buffer_t bits_fix_IOD;
1412 /* Make valgrind happy : it works at byte level not bit one so
1413 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
1414 * working (needed when fixing some bits) */
1415 memset( iod, 0, 4096 );
1417 bits_initwrite( &bits, 4096, iod );
1419 bits_write( &bits, 8, 0x01 );
1420 // InitialObjectDescriptor
1421 bits_align( &bits );
1422 bits_write( &bits, 8, 0x02 ); // tag
1423 bits_fix_IOD = bits; // save states to fix length later
1424 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1425 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1426 bits_write( &bits, 1, 0x00 ); // URL Flag
1427 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1428 bits_write( &bits, 4, 0x0f ); // reserved
1429 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1430 bits_write( &bits, 8, 0xff ); // sceneProfile
1431 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1432 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1433 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1434 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1436 ts_stream_t *p_stream;
1437 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1439 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1441 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1443 bits_align( &bits );
1444 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1445 bits_fix_ESDescr = bits;
1446 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1447 bits_write( &bits, 16, p_stream->i_es_id );
1448 bits_write( &bits, 1, 0x00 ); // streamDependency
1449 bits_write( &bits, 1, 0x00 ); // URL Flag
1450 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1451 bits_write( &bits, 5, 0x1f ); // streamPriority
1453 // DecoderConfigDesciptor
1454 bits_align( &bits );
1455 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1456 bits_fix_Decoder = bits;
1457 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1458 if( p_stream->i_stream_type == 0x10 )
1460 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1461 bits_write( &bits, 6, 0x04 ); // VisualStream
1463 else if( p_stream->i_stream_type == 0x11 )
1465 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1466 bits_write( &bits, 6, 0x05 ); // AudioStream
1470 bits_write( &bits, 8, 0x00 );
1471 bits_write( &bits, 6, 0x00 );
1473 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1475 bits_write( &bits, 1, 0x00 ); // UpStream
1476 bits_write( &bits, 1, 0x01 ); // reserved
1477 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1478 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1479 bits_write( &bits, 32, 0 ); // avgBitrate
1481 if( p_stream->i_decoder_specific_info > 0 )
1484 // DecoderSpecificInfo
1485 bits_align( &bits );
1486 bits_write( &bits, 8, 0x05 ); // tag
1487 bits_write( &bits, 24,
1488 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1489 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1491 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1494 /* fix Decoder length */
1495 bits_write( &bits_fix_Decoder, 24,
1496 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1498 /* SLConfigDescriptor : predifined (0x01) */
1499 bits_align( &bits );
1500 bits_write( &bits, 8, 0x06 ); // tag
1501 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1502 bits_write( &bits, 8, 0x01 ); // predefined
1503 bits_write( &bits, 1, 0 ); // durationFlag
1504 bits_write( &bits, 32, 0 ); // OCRResolution
1505 bits_write( &bits, 8, 0 ); // OCRLength
1506 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1507 bits_align( &bits );
1509 /* fix ESDescr length */
1510 bits_write( &bits_fix_ESDescr, 24,
1511 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1514 bits_align( &bits );
1515 /* fix IOD length */
1516 bits_write( &bits_fix_IOD, 24,
1517 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1518 dvbpsi_PMTAddDescriptor( &pmt,
1524 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1526 ts_stream_t *p_stream;
1528 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1530 p_es = dvbpsi_PMTAddES( &pmt,
1531 p_stream->i_stream_type,
1533 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1538 es_id[0] = (p_stream->i_es_id >> 8)&0xff;
1539 es_id[1] = (p_stream->i_es_id)&0xff;
1540 dvbpsi_PMTESAddDescriptor( p_es, 0x1f, 2, es_id );
1542 else if( p_stream->i_stream_type == 0xa0 )
1545 int i_extra = __MIN( p_stream->i_decoder_specific_info,
1548 /* private DIV3 descripor */
1549 memcpy( &data[0], &p_stream->i_bih_codec, 4 );
1550 data[4] = ( p_stream->i_bih_width >> 8 )&0xff;
1551 data[5] = ( p_stream->i_bih_width )&0xff;
1552 data[6] = ( p_stream->i_bih_height>> 8 )&0xff;
1553 data[7] = ( p_stream->i_bih_height )&0xff;
1554 data[8] = ( i_extra >> 8 )&0xff;
1555 data[9] = ( i_extra )&0xff;
1558 memcpy( &data[10], p_stream->p_decoder_specific_info, i_extra );
1561 /* 0xa0 is private */
1562 dvbpsi_PMTESAddDescriptor( p_es, 0xa0, i_extra + 10, data );
1564 else if( p_stream->i_stream_type == 0x81 )
1566 uint8_t format[4] = { 0x41, 0x43, 0x2d, 0x33 };
1568 /* "registration" descriptor : "AC-3" */
1569 dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
1573 p_section = dvbpsi_GenPMTSections( &pmt );
1575 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1577 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1579 dvbpsi_DeletePSISections( p_section );
1580 dvbpsi_EmptyPMT( &pmt );