1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.44 2004/02/17 13:13:31 gbazin 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>
41 #if defined MODULE_NAME_IS_mux_ts_dvbpsi
42 # ifdef HAVE_DVBPSI_DR_H
43 # include <dvbpsi/dvbpsi.h>
44 # include <dvbpsi/descriptor.h>
45 # include <dvbpsi/pat.h>
46 # include <dvbpsi/pmt.h>
47 # include <dvbpsi/dr.h>
48 # include <dvbpsi/psi.h>
51 # include "descriptor.h"
52 # include "tables/pat.h"
53 # include "tables/pmt.h"
54 # include "descriptors/dr.h"
61 * - check PCR frequency requirement
63 * - check PCR/PCR "soft"
64 * - check if "registration" descriptor : "AC-3" should be a program
65 * descriptor or an es one. (xine want an es one)
67 * - remove creation of PAT/PMT without dvbpsi
70 * - subtitle support is far from perfect. I expect some subtitles drop
71 * if they arrive a bit late
72 * (We cannot rely on the fact that the fifo should be full)
74 /*****************************************************************************
76 *****************************************************************************/
77 static int Open ( vlc_object_t * );
78 static void Close ( vlc_object_t * );
81 #if defined MODULE_NAME_IS_mux_ts
82 set_description( _("TS muxer") );
83 set_capability( "sout mux", 100 );
85 add_shortcut( "ts_nodvbpsi" );
86 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
87 set_description( _("TS muxer (libdvbpsi)") );
88 set_capability( "sout mux", 120 );
90 add_shortcut( "ts_dvbpsi" );
92 set_callbacks( Open, Close );
95 /*****************************************************************************
97 *****************************************************************************/
98 static int Capability(sout_mux_t *, int, void *, void * );
99 static int AddStream( sout_mux_t *, sout_input_t * );
100 static int DelStream( sout_mux_t *, sout_input_t * );
101 static int Mux ( sout_mux_t * );
103 /*****************************************************************************
105 *****************************************************************************/
106 #define SOUT_BUFFER_FLAGS_PRIVATE_PCR ( 1 << SOUT_BUFFER_FLAGS_PRIVATE_SHIFT )
107 #define SOUT_BUFFER_FLAGS_PRIVATE_CSA ( 2 << SOUT_BUFFER_FLAGS_PRIVATE_SHIFT )
111 sout_buffer_t *p_first;
112 sout_buffer_t **pp_last;
113 } sout_buffer_chain_t;
115 static inline void BufferChainInit ( sout_buffer_chain_t *c )
119 c->pp_last = &c->p_first;
121 static inline void BufferChainAppend( sout_buffer_chain_t *c, sout_buffer_t *b )
131 c->pp_last = &b->p_next;
133 static inline sout_buffer_t *BufferChainGet( sout_buffer_chain_t *c )
135 sout_buffer_t *b = c->p_first;
140 c->p_first = b->p_next;
142 if( c->p_first == NULL )
144 c->pp_last = &c->p_first;
151 static inline void BufferChainClean( sout_instance_t *p_sout, sout_buffer_chain_t *c )
155 while( ( b = BufferChainGet( c ) ) )
157 sout_BufferDelete( p_sout, b );
159 BufferChainInit( c );
162 typedef struct ts_stream_s
167 int i_continuity_counter;
169 /* to be used for carriege of DIV3 */
170 vlc_fourcc_t i_bih_codec;
171 int i_bih_width, i_bih_height;
173 /* Specific to mpeg4 in mpeg2ts */
176 int i_decoder_specific_info;
177 uint8_t *p_decoder_specific_info;
179 /* language is iso639-2T */
182 sout_buffer_chain_t chain_pes;
184 mtime_t i_pes_length;
189 struct sout_mux_sys_t
192 sout_input_t *p_pcr_input;
199 int i_pid_free; // first usable pid
201 int i_pat_version_number;
204 int i_pmt_version_number;
205 ts_stream_t pmt; // Up to now only one program
209 int i_null_continuity_counter; /* Needed ? */
211 /* for TS building */
212 int64_t i_bitrate_min;
213 int64_t i_bitrate_max;
215 int64_t i_caching_delay;
220 mtime_t i_pcr; /* last PCR emited */
226 /* Reserve a pid and return it */
227 static int AllocatePID( sout_mux_sys_t *p_sys, int i_cat )
230 if ( i_cat == VIDEO_ES && p_sys->i_pid_video )
232 i_pid = p_sys->i_pid_video;
233 p_sys->i_pid_video = 0;
235 else if ( i_cat == AUDIO_ES && p_sys->i_pid_audio )
237 i_pid = p_sys->i_pid_audio;
238 p_sys->i_pid_audio = 0;
242 i_pid = ++p_sys->i_pid_free;
247 static void GetPAT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
248 static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
250 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr );
251 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts );
253 static void PEStoTS ( sout_instance_t *, sout_buffer_chain_t *, sout_buffer_t *, ts_stream_t * );
255 /*****************************************************************************
257 *****************************************************************************/
258 static int Open( vlc_object_t *p_this )
260 sout_mux_t *p_mux =(sout_mux_t*)p_this;
261 sout_mux_sys_t *p_sys;
264 msg_Dbg( p_mux, "Open" );
266 p_sys = malloc( sizeof( sout_mux_sys_t ) );
268 p_mux->pf_capacity = Capability;
269 p_mux->pf_addstream = AddStream;
270 p_mux->pf_delstream = DelStream;
272 p_mux->p_sys = p_sys;
273 p_mux->i_preheader = 30; // really enough for a pes header
275 srand( (uint32_t)mdate() );
277 p_sys->i_audio_bound = 0;
278 p_sys->i_video_bound = 0;
280 p_sys->i_pat_version_number = rand() % 32;
281 p_sys->pat.i_pid = 0;
282 p_sys->pat.i_continuity_counter = 0;
284 p_sys->i_pmt_version_number = rand() % 32;
285 p_sys->pmt.i_pid = 0x42;
286 p_sys->pmt.i_continuity_counter = 0;
288 p_sys->i_pid_free = 0x43;
290 p_sys->i_pid_video = 0;
291 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) )
293 p_sys->i_pid_video = strtol( val, NULL, 0 );
294 if ( p_sys->i_pid_video > p_sys->i_pid_free )
296 p_sys->i_pid_free = p_sys->i_pid_video + 1;
299 p_sys->i_pid_audio = 0;
300 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) )
302 p_sys->i_pid_audio = strtol( val, NULL, 0 );
303 if ( p_sys->i_pid_audio > p_sys->i_pid_free )
305 p_sys->i_pid_free = p_sys->i_pid_audio + 1;
309 p_sys->i_pcr_pid = 0x1fff;
310 p_sys->p_pcr_input = NULL;
312 p_sys->i_mpeg4_streams = 0;
314 p_sys->i_null_continuity_counter = 0;
316 /* Allow to create constrained stream */
317 p_sys->i_bitrate_min = 0;
318 p_sys->i_bitrate_max = 0;
319 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmin" ) ) )
321 p_sys->i_bitrate_min = atoll( val );
323 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmax" ) ) )
325 p_sys->i_bitrate_max = atoll( val );
327 if( p_sys->i_bitrate_min > 0 && p_sys->i_bitrate_max > 0 &&
328 p_sys->i_bitrate_min > p_sys->i_bitrate_max )
330 msg_Err( p_mux, "incompatible minimum and maximum bitrate, "
331 "disabling bitrate control" );
332 p_sys->i_bitrate_min = 0;
333 p_sys->i_bitrate_max = 0;
335 if( p_sys->i_bitrate_min > 0 || p_sys->i_bitrate_max > 0 )
337 msg_Err( p_mux, "bmin and bmax no more supported (if you need them report it)" );
340 p_sys->i_caching_delay = 200000;
341 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "caching" ) ) )
343 p_sys->i_caching_delay = (int64_t)atoi( val ) * 1000;
344 if( p_sys->i_caching_delay <= 0 )
347 "invalid caching ("I64Fd"ms) reseting to 200ms",
348 p_sys->i_caching_delay / 1000 );
349 p_sys->i_caching_delay = 200000;
352 p_sys->i_pcr_delay = 30000;
353 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr" ) ) )
355 p_sys->i_pcr_delay = (int64_t)atoi( val ) * 1000;
356 if( p_sys->i_pcr_delay <= 0 ||
357 p_sys->i_pcr_delay >= p_sys->i_caching_delay )
360 "invalid pcr delay ("I64Fd"ms) reseting to 30ms",
361 p_sys->i_pcr_delay / 1000 );
362 p_sys->i_pcr_delay = 30000;
366 msg_Dbg( p_mux, "caching="I64Fd" pcr="I64Fd,
367 p_sys->i_caching_delay, p_sys->i_pcr_delay );
369 p_sys->i_dts_delay = 200000;
370 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "dts-delay" ) ) )
372 p_sys->i_dts_delay = (int64_t)atoi( val ) * 1000;
375 /* for TS generation */
379 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "csa-ck" ) ) )
382 if( val[0] == '0' && ( val[1] == 'x' || val[1] == 'X' ) )
386 if( strlen( val ) != 16 )
388 msg_Dbg( p_mux, "invalid csa ck (it must be 16 chars long)" );
392 /* Avoid using strtoll */
399 i_ck = strtol( val, NULL, 16 ) << 32;
401 i_ck += strtol( &val[8], NULL, 16 );
402 for( i = 0; i < 8; i++ )
404 ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff;
407 msg_Dbg( p_mux, "using CSA scrambling with ck=%x:%x:%x:%x:%x:%x:%x:%x",
408 ck[0], ck[1], ck[2], ck[3], ck[4], ck[5], ck[6], ck[7] );
410 p_sys->csa = csa_New();
411 csa_SetCW( p_sys->csa, ck, ck );
417 /*****************************************************************************
419 *****************************************************************************/
420 static void Close( vlc_object_t * p_this )
422 sout_mux_t *p_mux = (sout_mux_t*)p_this;
423 sout_mux_sys_t *p_sys = p_mux->p_sys;
425 msg_Dbg( p_mux, "Close" );
428 csa_Delete( p_sys->csa );
434 /*****************************************************************************
436 *****************************************************************************/
437 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
441 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
442 *(vlc_bool_t*)p_answer = VLC_TRUE;
443 return( SOUT_MUX_CAP_ERR_OK );
445 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
449 /*****************************************************************************
450 * AddStream: called for each stream addition
451 *****************************************************************************/
452 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
454 sout_mux_sys_t *p_sys = p_mux->p_sys;
455 ts_stream_t *p_stream;
457 p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
459 /* Init this new stream */
460 p_stream->i_pid = AllocatePID( p_sys, p_input->p_fmt->i_cat );
461 p_stream->i_continuity_counter = 0;
462 p_stream->i_decoder_specific_info = 0;
463 p_stream->p_decoder_specific_info = NULL;
465 msg_Dbg( p_mux, "adding input codec=%4.4s pid=%d", (char*)&p_input->p_fmt->i_codec, p_stream->i_pid );
467 /* All others fields depand on codec */
468 switch( p_input->p_fmt->i_cat )
471 switch( p_input->p_fmt->i_codec )
473 case VLC_FOURCC( 'm', 'p','g', 'v' ):
474 /* TODO: do we need to check MPEG-I/II ? */
475 p_stream->i_stream_type = 0x02;
476 p_stream->i_stream_id = 0xe0;
478 case VLC_FOURCC( 'm', 'p','4', 'v' ):
479 p_stream->i_stream_type = 0x10;
480 p_stream->i_stream_id = 0xfa;
481 p_sys->i_mpeg4_streams++;
482 p_stream->i_es_id = p_stream->i_pid;
484 /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
485 /* I didn't want to do that :P */
486 case VLC_FOURCC( 'H', '2', '6', '3' ):
487 case VLC_FOURCC( 'I', '2', '6', '3' ):
488 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
489 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
490 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
491 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
492 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
493 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
494 p_stream->i_stream_type = 0xa0; // private
495 p_stream->i_stream_id = 0xa0; // beurk
496 p_stream->i_bih_codec = p_input->p_fmt->i_codec;
497 p_stream->i_bih_width = p_input->p_fmt->video.i_width;
498 p_stream->i_bih_height = p_input->p_fmt->video.i_height;
504 p_sys->i_video_bound++;
508 switch( p_input->p_fmt->i_codec )
510 case VLC_FOURCC( 'm', 'p','g', 'a' ):
511 p_stream->i_stream_type = p_input->p_fmt->audio.i_rate >= 32000 ? 0x03 : 0x04;
512 p_stream->i_stream_id = 0xc0;
514 case VLC_FOURCC( 'a', '5','2', ' ' ):
515 p_stream->i_stream_type = 0x81;
516 p_stream->i_stream_id = 0xbd;
518 case VLC_FOURCC( 'l', 'p','c', 'm' ):
519 p_stream->i_stream_type = 0x83;
520 p_stream->i_stream_id = 0xbd;
522 case VLC_FOURCC( 'd', 't','s', ' ' ):
523 p_stream->i_stream_type = 0x85;
524 p_stream->i_stream_id = 0xbd;
527 case VLC_FOURCC( 'm', 'p','4', 'a' ):
528 p_stream->i_stream_type = 0x11;
529 p_stream->i_stream_id = 0xfa;
530 p_sys->i_mpeg4_streams++;
531 p_stream->i_es_id = p_stream->i_pid;
537 p_sys->i_audio_bound++;
541 switch( p_input->p_fmt->i_codec )
543 case VLC_FOURCC( 's', 'p','u', ' ' ):
544 p_stream->i_stream_type = 0x82;
545 p_stream->i_stream_id = 0xbd;
560 p_stream->lang[2] = '\0';
561 if( p_input->p_fmt->psz_language )
563 char *psz = p_input->p_fmt->psz_language;
564 const iso639_lang_t *pl = NULL;
566 if( strlen( psz ) == 2 )
568 pl = GetLang_1( psz );
570 else if( strlen( psz ) == 3 )
572 pl = GetLang_2B( psz );
573 if( !strcmp( pl->psz_iso639_1, "??" ) )
575 pl = GetLang_2T( psz );
578 if( pl && strcmp( pl->psz_iso639_1, "??" ) )
580 p_stream->lang[0] = pl->psz_iso639_2T[0];
581 p_stream->lang[1] = pl->psz_iso639_2T[1];
582 p_stream->lang[2] = pl->psz_iso639_2T[2];
584 msg_Dbg( p_mux, " - lang=%c%c%c",
592 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
593 p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra;
594 if( p_stream->i_decoder_specific_info > 0 )
596 p_stream->p_decoder_specific_info =
597 malloc( p_stream->i_decoder_specific_info );
598 memcpy( p_stream->p_decoder_specific_info,
599 p_input->p_fmt->p_extra,
600 p_input->p_fmt->i_extra );
604 BufferChainInit( &p_stream->chain_pes );
605 p_stream->i_pes_dts = 0;
606 p_stream->i_pes_length = 0;
607 p_stream->i_pes_used = 0;
609 /* We only change PMT version (PAT isn't changed) */
610 p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
613 if( p_input->p_fmt->i_cat != SPU_ES &&
614 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
616 if( p_sys->p_pcr_input )
618 /* There was already a PCR stream, so clean context */
621 p_sys->i_pcr_pid = p_stream->i_pid;
622 p_sys->p_pcr_input = p_input;
624 msg_Dbg( p_mux, "new PCR PID is %d", p_sys->i_pcr_pid );
630 /*****************************************************************************
631 * DelStream: called before a stream deletion
632 *****************************************************************************/
633 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
635 sout_mux_sys_t *p_sys = p_mux->p_sys;
636 ts_stream_t *p_stream;
639 p_stream = (ts_stream_t*)p_input->p_sys;
640 msg_Dbg( p_mux, "removing input pid=%d", p_stream->i_pid );
642 if( p_sys->i_pcr_pid == p_stream->i_pid )
646 /* Find a new pcr stream (Prefer Video Stream) */
647 p_sys->i_pcr_pid = 0x1fff;
648 p_sys->p_pcr_input = NULL;
649 for( i = 0; i < p_mux->i_nb_inputs; i++ )
651 if( p_mux->pp_inputs[i] == p_input )
656 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
659 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
660 p_sys->p_pcr_input= p_mux->pp_inputs[i];
663 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
664 p_sys->i_pcr_pid == 0x1fff )
667 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
668 p_sys->p_pcr_input= p_mux->pp_inputs[i];
671 if( p_sys->p_pcr_input )
673 /* Empty TS buffer */
676 msg_Dbg( p_mux, "new PCR PID is %d", p_sys->i_pcr_pid );
679 /* Empty all data in chain_pes */
680 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
682 if( p_stream->p_decoder_specific_info )
684 free( p_stream->p_decoder_specific_info );
686 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
688 p_sys->i_mpeg4_streams--;
690 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) )
692 int i_pid_video = strtol( val, NULL, 0 );
693 if ( i_pid_video == p_stream->i_pid )
695 p_sys->i_pid_video = i_pid_video;
696 msg_Dbg( p_mux, "freeing video PID %d", i_pid_video );
699 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) )
701 int i_pid_audio = strtol( val, NULL, 0 );
702 if ( i_pid_audio == p_stream->i_pid )
704 p_sys->i_pid_audio = i_pid_audio;
705 msg_Dbg( p_mux, "freeing audio PID %d", i_pid_audio );
710 /* We only change PMT version (PAT isn't changed) */
711 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
716 /*****************************************************************************
717 * Mux: Call each time there is new data for at least one stream
718 *****************************************************************************
720 *****************************************************************************/
721 static int Mux( sout_mux_t *p_mux )
723 sout_mux_sys_t *p_sys = p_mux->p_sys;
724 ts_stream_t *p_pcr_stream;
726 if( p_sys->i_pcr_pid == 0x1fff )
728 msg_Dbg( p_mux, "waiting PCR streams" );
732 p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
736 sout_buffer_chain_t chain_ts;
740 mtime_t i_pcr_length;
743 /* 1: get enough PES packet for all input */
746 vlc_bool_t b_ok = VLC_TRUE;
747 sout_buffer_t *p_data;
749 /* Accumulate enough data in the pcr stream (>i_caching_delay) */
750 /* Accumulate enough data in all other stream ( >= length of pcr) */
751 for( i = 0; i < p_mux->i_nb_inputs; i++ )
753 sout_input_t *p_input = p_mux->pp_inputs[i];
754 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
756 if( ( p_stream == p_pcr_stream && p_stream->i_pes_length <= p_sys->i_caching_delay ) ||
757 p_stream->i_pes_dts + p_stream->i_pes_length < p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
760 if( p_input->p_fifo->i_depth <= 1 )
762 if( p_input->p_fmt->i_cat == AUDIO_ES ||
763 p_input->p_fmt->i_cat == VIDEO_ES )
765 /* We need more data */
768 else if( p_input->p_fifo->i_depth <= 0 )
770 /* spu, only one packet is needed */
776 p_data = sout_FifoGet( p_input->p_fifo );
777 if( p_input->p_fifo->i_depth > 0 )
779 sout_buffer_t *p_next = sout_FifoShow( p_input->p_fifo );
781 p_data->i_length = p_next->i_dts - p_data->i_dts;
784 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 ) ||
785 p_data->i_dts < p_stream->i_pes_dts ||
786 ( p_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > p_stream->i_pes_dts + p_stream->i_pes_length ) )
788 msg_Warn( p_mux, "packet with too strange dts (dts=%lld,old=%lld,pcr=%lld)",
791 p_pcr_stream->i_pes_dts );
792 sout_BufferDelete( p_mux->p_sout, p_data );
794 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
795 p_stream->i_pes_dts = 0;
796 p_stream->i_pes_used = 0;
797 p_stream->i_pes_length = 0;
799 BufferChainClean( p_mux->p_sout, &p_pcr_stream->chain_pes );
800 p_pcr_stream->i_pes_dts = 0;
801 p_pcr_stream->i_pes_used = 0;
802 p_pcr_stream->i_pes_length = 0;
807 if( p_data->i_length < 0 || p_data->i_length > 2000000 )
809 /* FIXME choose a better value, but anyway we should never
811 p_data->i_length = 1000;
813 p_stream->i_pes_length += p_data->i_length;
814 if( p_stream->i_pes_dts == 0 )
816 p_stream->i_pes_dts = p_data->i_dts;
820 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1 );
822 BufferChainAppend( &p_stream->chain_pes, p_data );
834 i_pcr_dts = p_pcr_stream->i_pes_dts;
835 i_pcr_length = p_pcr_stream->i_pes_length;
837 /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */
838 /* 2: calculate non accurate total size of muxed ts */
840 for( i = 0; i < p_mux->i_nb_inputs; i++ )
842 ts_stream_t *p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
843 sout_buffer_t *p_pes;
845 /* False for pcr stream but it will be eough to do PCR algo */
846 for( p_pes = p_stream->chain_pes.p_first; p_pes != NULL; p_pes = p_pes->p_next )
848 int i_size = p_pes->i_size;
849 if( p_pes->i_dts + p_pes->i_length > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
851 mtime_t i_frag = p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length - p_pes->i_dts;
857 i_size = p_pes->i_size * i_frag / p_pes->i_length;
859 i_packet_count += ( i_size + 183 ) / 184;
862 /* add overhead for PCR (not really exact) */
863 i_packet_count += ( 8 * i_pcr_length / p_sys->i_pcr_delay + 175 ) / 176;
866 /* 3: mux PES into TS */
867 BufferChainInit( &chain_ts );
868 /* append PAT/PMT -> FIXME with big pcr delay it won't have enough pat/pmt */
869 GetPAT( p_mux, &chain_ts);
870 GetPMT( p_mux, &chain_ts );
872 i_packet_count += chain_ts.i_depth;
873 /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */
879 ts_stream_t *p_stream;
883 /* Select stream (lowest dts)*/
884 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
886 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
888 if( p_stream->i_pes_dts == 0 )
893 if( i_stream == -1 ||
894 p_stream->i_pes_dts < i_dts )
897 i_dts = p_stream->i_pes_dts;
904 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
906 /* do we need to issue pcr */
908 if( p_stream == p_pcr_stream &&
909 i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count >= p_sys->i_pcr + p_sys->i_pcr_delay )
912 p_sys->i_pcr = i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count;
915 /* Build the TS packet */
916 p_ts = TSNew( p_mux, p_stream, b_pcr );
919 p_ts->i_flags |= SOUT_BUFFER_FLAGS_PRIVATE_CSA;
924 BufferChainAppend( &chain_ts, p_ts );
927 /* 4: date and send */
928 i_packet_count = chain_ts.i_depth;
929 /* msg_Dbg( p_mux, "real pck=%d", i_packet_count ); */
930 for( i = 0; i < i_packet_count; i++ )
932 sout_buffer_t *p_ts = BufferChainGet( &chain_ts );
934 p_ts->i_dts = i_pcr_dts + i_pcr_length * i / i_packet_count;
935 p_ts->i_length = i_pcr_length / i_packet_count;
937 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR )
939 /* msg_Dbg( p_mux, "pcr=%lld ms", p_ts->i_dts / 1000 ); */
940 TSSetPCR( p_ts, p_ts->i_dts - p_sys->i_dts_delay );
942 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_CSA )
944 csa_Encrypt( p_sys->csa, p_ts->p_buffer, 0 );
948 p_ts->i_dts += 3*p_sys->i_caching_delay/2;
950 sout_AccessOutWrite( p_mux->p_access, p_ts );
955 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr )
957 sout_buffer_t *p_pes = p_stream->chain_pes.p_first;
960 vlc_bool_t b_new_pes = VLC_FALSE;
961 vlc_bool_t b_adaptation_field = VLC_FALSE;
963 int i_payload_max = 184 - ( b_pcr ? 8 : 0 );
966 if( p_stream->i_pes_used <= 0 )
968 b_new_pes = VLC_TRUE;
970 i_payload = __MIN( (int)p_pes->i_size - p_stream->i_pes_used, i_payload_max );
972 if( b_pcr || i_payload < i_payload_max )
974 b_adaptation_field = VLC_TRUE;
977 p_ts = sout_BufferNew( p_mux->p_sout, 188 );
979 p_ts->p_buffer[0] = 0x47;
980 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|( ( p_stream->i_pid >> 8 )&0x1f );
981 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
982 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|p_stream->i_continuity_counter;
984 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
986 if( b_adaptation_field )
992 int i_stuffing = i_payload_max - i_payload;
994 p_ts->i_flags |= SOUT_BUFFER_FLAGS_PRIVATE_PCR;
996 p_ts->p_buffer[4] = 7 + i_stuffing;
997 p_ts->p_buffer[5] = 0x10; /* flags */
998 p_ts->p_buffer[6] = ( 0 )&0xff;
999 p_ts->p_buffer[7] = ( 0 )&0xff;
1000 p_ts->p_buffer[8] = ( 0 )&0xff;
1001 p_ts->p_buffer[9] = ( 0 )&0xff;
1002 p_ts->p_buffer[10]= ( 0 )&0x80;
1003 p_ts->p_buffer[11]= 0;
1005 for( i = 12; i < 12 + i_stuffing; i++ )
1007 p_ts->p_buffer[i] = 0xff;
1012 int i_stuffing = i_payload_max - i_payload;
1014 p_ts->p_buffer[4] = i_stuffing - 1;
1015 if( i_stuffing > 1 )
1017 p_ts->p_buffer[5] = 0x00;
1018 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1020 p_ts->p_buffer[i] = 0xff;
1027 memcpy( &p_ts->p_buffer[188 - i_payload], &p_pes->p_buffer[p_stream->i_pes_used], i_payload );
1029 p_stream->i_pes_used += i_payload;
1030 p_stream->i_pes_dts = p_pes->i_dts + p_pes->i_length * p_stream->i_pes_used / p_pes->i_size;
1031 p_stream->i_pes_length -= p_pes->i_length * i_payload / p_pes->i_size;
1033 if( p_stream->i_pes_used >= (int)p_pes->i_size )
1035 p_pes = BufferChainGet( &p_stream->chain_pes );
1036 sout_BufferDelete( p_mux->p_sout, p_pes );
1038 p_pes = p_stream->chain_pes.p_first;
1041 p_stream->i_pes_dts = p_pes->i_dts;
1042 p_stream->i_pes_length = 0;
1045 p_stream->i_pes_length += p_pes->i_length;
1047 p_pes = p_pes->p_next;
1052 p_stream->i_pes_dts = 0;
1053 p_stream->i_pes_length = 0;
1055 p_stream->i_pes_used = 0;
1062 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts )
1064 mtime_t i_pcr = 9 * i_dts / 100;
1066 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
1067 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
1068 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
1069 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
1070 p_ts->p_buffer[10]|= ( i_pcr << 7 )&0x80;
1074 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 )
1076 sout_mux_sys_t *p_sys = p_mux->p_sys;
1077 sout_buffer_chain_t s = *c;
1080 int i_packets_min = 0;
1081 int i_packets_max = 0;
1088 i_packets = c->i_depth;
1089 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
1090 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
1092 if( i_packets < i_packets_min && i_packets_min > 0 )
1094 sout_buffer_t *p_pk;
1095 int i_div = ( i_packets_min - i_packets ) / i_packets;
1096 int i_mod = ( i_packets_min - i_packets ) % i_packets;
1099 /* We need to pad with null packets (pid=0x1fff)
1100 * We try to melt null packets with true packets */
1102 "packets=%d but min=%d -> adding %d packets of padding",
1103 i_packets, i_packets_min, i_packets_min - i_packets );
1105 BufferChainInit( c );
1106 while( ( p_pk = BufferChainGet( &s ) ) )
1110 BufferChainAppend( c, p_pk );
1112 i_null = i_div + ( i_rest + i_mod ) / i_packets;
1114 for( i = 0; i < i_null; i++ )
1116 sout_buffer_t *p_null;
1118 p_null = sout_BufferNew( p_mux->p_sout, 188 );
1119 p_null->p_buffer[0] = 0x47;
1120 p_null->p_buffer[1] = 0x1f;
1121 p_null->p_buffer[2] = 0xff;
1122 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
1123 memset( &p_null->p_buffer[4], 0, 184 );
1124 p_sys->i_null_continuity_counter =
1125 ( p_sys->i_null_continuity_counter + 1 ) % 16;
1127 BufferChainAppend( c, p_null );
1130 i_rest = ( i_rest + i_mod ) % i_packets;
1133 else if( i_packets > i_packets_max && i_packets_max > 0 )
1135 sout_buffer_t *p_pk;
1138 /* Arg, we need to drop packets, I don't do something clever (like
1139 * dropping complete pid, b frames, ... ), I just get the right amount
1140 * of packets and discard the others */
1142 "packets=%d but max=%d -> removing %d packets -> stream broken",
1143 i_packets, i_packets_max, i_packets - i_packets_max );
1145 BufferChainInit( c );
1146 for( i = 0; i < i_packets_max; i++ )
1148 BufferChainAppend( c, BufferChainGet( &s ) );
1151 while( ( p_pk = BufferChainGet( &s ) ) )
1153 sout_BufferDelete( p_mux->p_sout, p_pk );
1159 static void PEStoTS( sout_instance_t *p_sout,
1160 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
1161 ts_stream_t *p_stream )
1167 /* get PES total size */
1168 i_size = p_pes->i_size;
1169 p_data = p_pes->p_buffer;
1171 b_new_pes = VLC_TRUE;
1175 int b_adaptation_field;
1177 sout_buffer_t *p_ts;
1179 p_ts = sout_BufferNew( p_sout, 188 );
1182 * 1b transport_error_indicator
1183 * 1b payload_unit_start
1184 * 1b transport_priority
1186 * 2b transport_scrambling_control
1187 * 2b if adaptation_field 0x03 else 0x01
1188 * 4b continuity_counter
1191 i_copy = __MIN( i_size, 184 );
1192 b_adaptation_field = i_size < 184 ? VLC_TRUE : VLC_FALSE;
1194 p_ts->p_buffer[0] = 0x47;
1195 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
1196 ( ( p_stream->i_pid >> 8 )&0x1f );
1197 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
1198 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
1199 p_stream->i_continuity_counter;
1201 b_new_pes = VLC_FALSE;
1202 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
1204 if( b_adaptation_field )
1206 int i_stuffing = 184 - i_copy;
1209 p_ts->p_buffer[4] = i_stuffing - 1;
1210 if( i_stuffing > 1 )
1212 p_ts->p_buffer[5] = 0x00;
1213 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1215 p_ts->p_buffer[i] = 0xff;
1220 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1224 BufferChainAppend( c, p_ts );
1228 sout_buffer_t *p_next = p_pes->p_next;
1230 p_pes->p_next = NULL;
1231 sout_BufferDelete( p_sout, p_pes );
1232 if( p_next == NULL )
1236 b_new_pes = VLC_TRUE;
1238 i_size = p_pes->i_size;
1239 p_data = p_pes->p_buffer;
1246 #if defined MODULE_NAME_IS_mux_ts
1247 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1249 static uint32_t CRC32[256] =
1251 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1252 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1253 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1254 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1255 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1256 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1257 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1258 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1259 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1260 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1261 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1262 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1263 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1264 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1265 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1266 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1267 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1268 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1269 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1270 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1271 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1272 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1273 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1274 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1275 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1276 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1277 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1278 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1279 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1280 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1281 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1282 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1283 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1284 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1285 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1286 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1287 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1288 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1289 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1290 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1291 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1292 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1293 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1294 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1295 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1296 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1297 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1298 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1299 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1300 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1301 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1302 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1303 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1304 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1305 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1306 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1307 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1308 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1309 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1310 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1311 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1312 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1313 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1314 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1317 uint32_t i_crc = 0xffffffff;
1319 /* Calculate the CRC */
1320 while( i_count > 0 )
1322 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1330 static void GetPAT( sout_mux_t *p_mux,
1331 sout_buffer_chain_t *c )
1333 sout_mux_sys_t *p_sys = p_mux->p_sys;
1334 sout_buffer_t *p_pat;
1337 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1341 p_pat->i_length = 0;
1343 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1345 bits_write( &bits, 8, 0 ); // pointer
1346 bits_write( &bits, 8, 0x00 ); // table id
1347 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1348 bits_write( &bits, 1, 0 ); // 0
1349 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1350 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1351 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1352 bits_write( &bits, 2, 0x03 ); // FIXME
1353 bits_write( &bits, 5, p_sys->i_pat_version_number );
1354 bits_write( &bits, 1, 1 ); // current_next_indicator
1355 bits_write( &bits, 8, 0 ); // section number
1356 bits_write( &bits, 8, 0 ); // last section number
1358 bits_write( &bits, 16, 1 ); // program number
1359 bits_write( &bits, 3, 0x07 ); // reserved
1360 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1362 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1364 p_pat->i_size = bits.i_data;
1366 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1369 static void GetPMT( sout_mux_t *p_mux,
1370 sout_buffer_chain_t *c )
1372 sout_mux_sys_t *p_sys = p_mux->p_sys;
1373 sout_buffer_t *p_pmt;
1377 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1381 p_pmt->i_length = 0;
1383 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1385 bits_write( &bits, 8, 0 ); // pointer
1386 bits_write( &bits, 8, 0x02 ); // table id
1387 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1388 bits_write( &bits, 1, 0 ); // 0
1389 bits_write( &bits, 2, 0 ); // reserved FIXME
1390 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1391 bits_write( &bits, 16, 1 ); // FIXME program number
1392 bits_write( &bits, 2, 0 ); // FIXME
1393 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1394 bits_write( &bits, 1, 1 ); // current_next_indicator
1395 bits_write( &bits, 8, 0 ); // section number
1396 bits_write( &bits, 8, 0 ); // last section number
1398 bits_write( &bits, 3, 0 ); // reserved
1400 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1401 bits_write( &bits, 4, 0 ); // reserved FIXME
1403 bits_write( &bits, 12, 0 ); // program info len FIXME
1405 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1407 ts_stream_t *p_stream;
1409 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1411 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1412 bits_write( &bits, 3, 0 ); // reserved
1413 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1414 bits_write( &bits, 4, 0 ); //reserved
1415 bits_write( &bits, 12, 0 ); // es info len FIXME
1418 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1420 p_pmt->i_size = bits.i_data;
1422 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1424 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1426 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1427 dvbpsi_psi_section_t* p_section )
1429 sout_buffer_t *p_psi, *p_first = NULL;
1436 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1437 ( p_section->b_syntax_indicator ? 4 : 0 );
1439 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1442 p_psi->i_length = 0;
1443 p_psi->i_size = i_size + 1;
1445 p_psi->p_buffer[0] = 0; // pointer
1446 memcpy( p_psi->p_buffer + 1,
1450 sout_BufferChain( &p_first, p_psi );
1452 p_section = p_section->p_next;
1458 static void GetPAT( sout_mux_t *p_mux,
1459 sout_buffer_chain_t *c )
1461 sout_mux_sys_t *p_sys = p_mux->p_sys;
1462 sout_buffer_t *p_pat;
1464 dvbpsi_psi_section_t *p_section;
1466 dvbpsi_InitPAT( &pat,
1468 p_sys->i_pat_version_number,
1469 1 ); // b_current_next
1470 /* add all program (only one) */
1471 dvbpsi_PATAddProgram( &pat,
1473 p_sys->pmt.i_pid ); // i_pid
1475 p_section = dvbpsi_GenPATSections( &pat,
1476 0 ); // max program per section
1478 p_pat = WritePSISection( p_mux->p_sout, p_section );
1480 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1482 dvbpsi_DeletePSISections( p_section );
1483 dvbpsi_EmptyPAT( &pat );
1486 static uint32_t GetDescriptorLength24b( int i_length )
1488 uint32_t i_l1, i_l2, i_l3;
1490 i_l1 = i_length&0x7f;
1491 i_l2 = ( i_length >> 7 )&0x7f;
1492 i_l3 = ( i_length >> 14 )&0x7f;
1494 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1497 static void GetPMT( sout_mux_t *p_mux,
1498 sout_buffer_chain_t *c )
1500 sout_mux_sys_t *p_sys = p_mux->p_sys;
1501 sout_buffer_t *p_pmt;
1504 dvbpsi_pmt_es_t *p_es;
1505 dvbpsi_psi_section_t *p_section;
1509 dvbpsi_InitPMT( &pmt,
1510 0x01, // program number
1511 p_sys->i_pmt_version_number,
1512 1, // b_current_next
1515 if( p_sys->i_mpeg4_streams > 0 )
1519 bits_buffer_t bits_fix_IOD;
1521 /* Make valgrind happy : it works at byte level not bit one so
1522 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
1523 * working (needed when fixing some bits) */
1524 memset( iod, 0, 4096 );
1526 bits_initwrite( &bits, 4096, iod );
1528 bits_write( &bits, 8, 0x01 );
1529 // InitialObjectDescriptor
1530 bits_align( &bits );
1531 bits_write( &bits, 8, 0x02 ); // tag
1532 bits_fix_IOD = bits; // save states to fix length later
1533 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1534 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1535 bits_write( &bits, 1, 0x00 ); // URL Flag
1536 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1537 bits_write( &bits, 4, 0x0f ); // reserved
1538 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1539 bits_write( &bits, 8, 0xff ); // sceneProfile
1540 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1541 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1542 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1543 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1545 ts_stream_t *p_stream;
1546 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1548 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1550 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1552 bits_align( &bits );
1553 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1554 bits_fix_ESDescr = bits;
1555 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1556 bits_write( &bits, 16, p_stream->i_es_id );
1557 bits_write( &bits, 1, 0x00 ); // streamDependency
1558 bits_write( &bits, 1, 0x00 ); // URL Flag
1559 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1560 bits_write( &bits, 5, 0x1f ); // streamPriority
1562 // DecoderConfigDesciptor
1563 bits_align( &bits );
1564 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1565 bits_fix_Decoder = bits;
1566 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1567 if( p_stream->i_stream_type == 0x10 )
1569 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1570 bits_write( &bits, 6, 0x04 ); // VisualStream
1572 else if( p_stream->i_stream_type == 0x11 )
1574 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1575 bits_write( &bits, 6, 0x05 ); // AudioStream
1579 bits_write( &bits, 8, 0x00 );
1580 bits_write( &bits, 6, 0x00 );
1582 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1584 bits_write( &bits, 1, 0x00 ); // UpStream
1585 bits_write( &bits, 1, 0x01 ); // reserved
1586 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1587 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1588 bits_write( &bits, 32, 0 ); // avgBitrate
1590 if( p_stream->i_decoder_specific_info > 0 )
1593 // DecoderSpecificInfo
1594 bits_align( &bits );
1595 bits_write( &bits, 8, 0x05 ); // tag
1596 bits_write( &bits, 24,
1597 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1598 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1600 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1603 /* fix Decoder length */
1604 bits_write( &bits_fix_Decoder, 24,
1605 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1607 /* SLConfigDescriptor : predifined (0x01) */
1608 bits_align( &bits );
1609 bits_write( &bits, 8, 0x06 ); // tag
1610 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1611 bits_write( &bits, 8, 0x01 ); // predefined
1612 bits_write( &bits, 1, 0 ); // durationFlag
1613 bits_write( &bits, 32, 0 ); // OCRResolution
1614 bits_write( &bits, 8, 0 ); // OCRLength
1615 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1616 bits_align( &bits );
1618 /* fix ESDescr length */
1619 bits_write( &bits_fix_ESDescr, 24,
1620 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1623 bits_align( &bits );
1624 /* fix IOD length */
1625 bits_write( &bits_fix_IOD, 24,
1626 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1627 dvbpsi_PMTAddDescriptor( &pmt,
1633 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1635 ts_stream_t *p_stream;
1637 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1639 p_es = dvbpsi_PMTAddES( &pmt,
1640 p_stream->i_stream_type,
1642 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1647 es_id[0] = (p_stream->i_es_id >> 8)&0xff;
1648 es_id[1] = (p_stream->i_es_id)&0xff;
1649 dvbpsi_PMTESAddDescriptor( p_es, 0x1f, 2, es_id );
1651 else if( p_stream->i_stream_type == 0xa0 )
1654 int i_extra = __MIN( p_stream->i_decoder_specific_info,
1657 /* private DIV3 descripor */
1658 memcpy( &data[0], &p_stream->i_bih_codec, 4 );
1659 data[4] = ( p_stream->i_bih_width >> 8 )&0xff;
1660 data[5] = ( p_stream->i_bih_width )&0xff;
1661 data[6] = ( p_stream->i_bih_height>> 8 )&0xff;
1662 data[7] = ( p_stream->i_bih_height )&0xff;
1663 data[8] = ( i_extra >> 8 )&0xff;
1664 data[9] = ( i_extra )&0xff;
1667 memcpy( &data[10], p_stream->p_decoder_specific_info, i_extra );
1670 /* 0xa0 is private */
1671 dvbpsi_PMTESAddDescriptor( p_es, 0xa0, i_extra + 10, data );
1673 else if( p_stream->i_stream_type == 0x81 )
1675 uint8_t format[4] = { 0x41, 0x43, 0x2d, 0x33 };
1677 /* "registration" descriptor : "AC-3" */
1678 dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
1681 if( p_stream->lang[0] != 0 )
1685 /* I construct the content myself, way faster than looking at
1686 * over complicated/mind broken libdvbpsi way */
1687 data[0] = p_stream->lang[0];
1688 data[1] = p_stream->lang[1];
1689 data[2] = p_stream->lang[2];
1690 data[3] = 0x00; /* audio type: 0x00 undefined */
1692 dvbpsi_PMTESAddDescriptor( p_es, 0x0a, 4, data );
1696 p_section = dvbpsi_GenPMTSections( &pmt );
1698 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1700 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1702 dvbpsi_DeletePSISections( p_section );
1703 dvbpsi_EmptyPMT( &pmt );