1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.43 2004/01/30 17:53:05 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>
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 uint64_t i_ck = strtoll( val, NULL, 16 );
395 for( i = 0; i < 8; i++ )
397 ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff;
400 msg_Dbg( p_mux, "using CSA scrambling with ck=%x:%x:%x:%x:%x:%x:%x:%x",
401 ck[0], ck[1], ck[2], ck[3], ck[4], ck[5], ck[6], ck[7] );
403 p_sys->csa = csa_New();
404 csa_SetCW( p_sys->csa, ck, ck );
410 /*****************************************************************************
412 *****************************************************************************/
413 static void Close( vlc_object_t * p_this )
415 sout_mux_t *p_mux = (sout_mux_t*)p_this;
416 sout_mux_sys_t *p_sys = p_mux->p_sys;
418 msg_Dbg( p_mux, "Close" );
421 csa_Delete( p_sys->csa );
427 /*****************************************************************************
429 *****************************************************************************/
430 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
434 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
435 *(vlc_bool_t*)p_answer = VLC_TRUE;
436 return( SOUT_MUX_CAP_ERR_OK );
438 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
442 /*****************************************************************************
443 * AddStream: called for each stream addition
444 *****************************************************************************/
445 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
447 sout_mux_sys_t *p_sys = p_mux->p_sys;
448 ts_stream_t *p_stream;
450 p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
452 /* Init this new stream */
453 p_stream->i_pid = AllocatePID( p_sys, p_input->p_fmt->i_cat );
454 p_stream->i_continuity_counter = 0;
455 p_stream->i_decoder_specific_info = 0;
456 p_stream->p_decoder_specific_info = NULL;
458 msg_Dbg( p_mux, "adding input codec=%4.4s pid=%d", (char*)&p_input->p_fmt->i_codec, p_stream->i_pid );
460 /* All others fields depand on codec */
461 switch( p_input->p_fmt->i_cat )
464 switch( p_input->p_fmt->i_codec )
466 case VLC_FOURCC( 'm', 'p','g', 'v' ):
467 /* TODO: do we need to check MPEG-I/II ? */
468 p_stream->i_stream_type = 0x02;
469 p_stream->i_stream_id = 0xe0;
471 case VLC_FOURCC( 'm', 'p','4', 'v' ):
472 p_stream->i_stream_type = 0x10;
473 p_stream->i_stream_id = 0xfa;
474 p_sys->i_mpeg4_streams++;
475 p_stream->i_es_id = p_stream->i_pid;
477 /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
478 /* I didn't want to do that :P */
479 case VLC_FOURCC( 'H', '2', '6', '3' ):
480 case VLC_FOURCC( 'I', '2', '6', '3' ):
481 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
482 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
483 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
484 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
485 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
486 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
487 p_stream->i_stream_type = 0xa0; // private
488 p_stream->i_stream_id = 0xa0; // beurk
489 p_stream->i_bih_codec = p_input->p_fmt->i_codec;
490 p_stream->i_bih_width = p_input->p_fmt->video.i_width;
491 p_stream->i_bih_height = p_input->p_fmt->video.i_height;
497 p_sys->i_video_bound++;
501 switch( p_input->p_fmt->i_codec )
503 case VLC_FOURCC( 'm', 'p','g', 'a' ):
504 p_stream->i_stream_type = p_input->p_fmt->audio.i_rate >= 32000 ? 0x03 : 0x04;
505 p_stream->i_stream_id = 0xc0;
507 case VLC_FOURCC( 'a', '5','2', ' ' ):
508 p_stream->i_stream_type = 0x81;
509 p_stream->i_stream_id = 0xbd;
511 case VLC_FOURCC( 'l', 'p','c', 'm' ):
512 p_stream->i_stream_type = 0x83;
513 p_stream->i_stream_id = 0xbd;
515 case VLC_FOURCC( 'd', 't','s', ' ' ):
516 p_stream->i_stream_type = 0x85;
517 p_stream->i_stream_id = 0xbd;
520 case VLC_FOURCC( 'm', 'p','4', 'a' ):
521 p_stream->i_stream_type = 0x11;
522 p_stream->i_stream_id = 0xfa;
523 p_sys->i_mpeg4_streams++;
524 p_stream->i_es_id = p_stream->i_pid;
530 p_sys->i_audio_bound++;
534 switch( p_input->p_fmt->i_codec )
536 case VLC_FOURCC( 's', 'p','u', ' ' ):
537 p_stream->i_stream_type = 0x82;
538 p_stream->i_stream_id = 0xbd;
553 p_stream->lang[2] = '\0';
554 if( p_input->p_fmt->psz_language )
556 char *psz = p_input->p_fmt->psz_language;
557 const iso639_lang_t *pl = NULL;
559 if( strlen( psz ) == 2 )
561 pl = GetLang_1( psz );
563 else if( strlen( psz ) == 3 )
565 pl = GetLang_2B( psz );
566 if( !strcmp( pl->psz_iso639_1, "??" ) )
568 pl = GetLang_2T( psz );
571 if( pl && strcmp( pl->psz_iso639_1, "??" ) )
573 p_stream->lang[0] = pl->psz_iso639_2T[0];
574 p_stream->lang[1] = pl->psz_iso639_2T[1];
575 p_stream->lang[2] = pl->psz_iso639_2T[2];
577 msg_Dbg( p_mux, " - lang=%c%c%c",
585 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
586 p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra;
587 if( p_stream->i_decoder_specific_info > 0 )
589 p_stream->p_decoder_specific_info =
590 malloc( p_stream->i_decoder_specific_info );
591 memcpy( p_stream->p_decoder_specific_info,
592 p_input->p_fmt->p_extra,
593 p_input->p_fmt->i_extra );
597 BufferChainInit( &p_stream->chain_pes );
598 p_stream->i_pes_dts = 0;
599 p_stream->i_pes_length = 0;
600 p_stream->i_pes_used = 0;
602 /* We only change PMT version (PAT isn't changed) */
603 p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
606 if( p_input->p_fmt->i_cat != SPU_ES &&
607 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
609 if( p_sys->p_pcr_input )
611 /* There was already a PCR stream, so clean context */
614 p_sys->i_pcr_pid = p_stream->i_pid;
615 p_sys->p_pcr_input = p_input;
617 msg_Dbg( p_mux, "new PCR PID is %d", p_sys->i_pcr_pid );
623 /*****************************************************************************
624 * DelStream: called before a stream deletion
625 *****************************************************************************/
626 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
628 sout_mux_sys_t *p_sys = p_mux->p_sys;
629 ts_stream_t *p_stream;
632 p_stream = (ts_stream_t*)p_input->p_sys;
633 msg_Dbg( p_mux, "removing input pid=%d", p_stream->i_pid );
635 if( p_sys->i_pcr_pid == p_stream->i_pid )
639 /* Find a new pcr stream (Prefer Video Stream) */
640 p_sys->i_pcr_pid = 0x1fff;
641 p_sys->p_pcr_input = NULL;
642 for( i = 0; i < p_mux->i_nb_inputs; i++ )
644 if( p_mux->pp_inputs[i] == p_input )
649 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
652 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
653 p_sys->p_pcr_input= p_mux->pp_inputs[i];
656 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
657 p_sys->i_pcr_pid == 0x1fff )
660 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
661 p_sys->p_pcr_input= p_mux->pp_inputs[i];
664 if( p_sys->p_pcr_input )
666 /* Empty TS buffer */
669 msg_Dbg( p_mux, "new PCR PID is %d", p_sys->i_pcr_pid );
672 /* Empty all data in chain_pes */
673 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
675 if( p_stream->p_decoder_specific_info )
677 free( p_stream->p_decoder_specific_info );
679 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
681 p_sys->i_mpeg4_streams--;
683 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) )
685 int i_pid_video = strtol( val, NULL, 0 );
686 if ( i_pid_video == p_stream->i_pid )
688 p_sys->i_pid_video = i_pid_video;
689 msg_Dbg( p_mux, "freeing video PID %d", i_pid_video );
692 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) )
694 int i_pid_audio = strtol( val, NULL, 0 );
695 if ( i_pid_audio == p_stream->i_pid )
697 p_sys->i_pid_audio = i_pid_audio;
698 msg_Dbg( p_mux, "freeing audio PID %d", i_pid_audio );
703 /* We only change PMT version (PAT isn't changed) */
704 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
709 /*****************************************************************************
710 * Mux: Call each time there is new data for at least one stream
711 *****************************************************************************
713 *****************************************************************************/
714 static int Mux( sout_mux_t *p_mux )
716 sout_mux_sys_t *p_sys = p_mux->p_sys;
717 ts_stream_t *p_pcr_stream;
719 if( p_sys->i_pcr_pid == 0x1fff )
721 msg_Dbg( p_mux, "waiting PCR streams" );
725 p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
729 sout_buffer_chain_t chain_ts;
733 mtime_t i_pcr_length;
736 /* 1: get enough PES packet for all input */
739 vlc_bool_t b_ok = VLC_TRUE;
740 sout_buffer_t *p_data;
742 /* Accumulate enough data in the pcr stream (>i_caching_delay) */
743 /* Accumulate enough data in all other stream ( >= length of pcr) */
744 for( i = 0; i < p_mux->i_nb_inputs; i++ )
746 sout_input_t *p_input = p_mux->pp_inputs[i];
747 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
749 if( ( p_stream == p_pcr_stream && p_stream->i_pes_length <= p_sys->i_caching_delay ) ||
750 p_stream->i_pes_dts + p_stream->i_pes_length < p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
753 if( p_input->p_fifo->i_depth <= 1 )
755 if( p_input->p_fmt->i_cat == AUDIO_ES ||
756 p_input->p_fmt->i_cat == VIDEO_ES )
758 /* We need more data */
761 else if( p_input->p_fifo->i_depth <= 0 )
763 /* spu, only one packet is needed */
769 p_data = sout_FifoGet( p_input->p_fifo );
770 if( p_input->p_fifo->i_depth > 0 )
772 sout_buffer_t *p_next = sout_FifoShow( p_input->p_fifo );
774 p_data->i_length = p_next->i_dts - p_data->i_dts;
777 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 ) ||
778 p_data->i_dts < p_stream->i_pes_dts ||
779 ( p_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > p_stream->i_pes_dts + p_stream->i_pes_length ) )
781 msg_Warn( p_mux, "packet with too strange dts (dts=%lld,old=%lld,pcr=%lld)",
784 p_pcr_stream->i_pes_dts );
785 sout_BufferDelete( p_mux->p_sout, p_data );
787 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
788 p_stream->i_pes_dts = 0;
789 p_stream->i_pes_used = 0;
790 p_stream->i_pes_length = 0;
792 BufferChainClean( p_mux->p_sout, &p_pcr_stream->chain_pes );
793 p_pcr_stream->i_pes_dts = 0;
794 p_pcr_stream->i_pes_used = 0;
795 p_pcr_stream->i_pes_length = 0;
800 if( p_data->i_length < 0 || p_data->i_length > 2000000 )
802 /* FIXME choose a better value, but anyway we should never
804 p_data->i_length = 1000;
806 p_stream->i_pes_length += p_data->i_length;
807 if( p_stream->i_pes_dts == 0 )
809 p_stream->i_pes_dts = p_data->i_dts;
813 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1 );
815 BufferChainAppend( &p_stream->chain_pes, p_data );
827 i_pcr_dts = p_pcr_stream->i_pes_dts;
828 i_pcr_length = p_pcr_stream->i_pes_length;
830 /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */
831 /* 2: calculate non accurate total size of muxed ts */
833 for( i = 0; i < p_mux->i_nb_inputs; i++ )
835 ts_stream_t *p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
836 sout_buffer_t *p_pes;
838 /* False for pcr stream but it will be eough to do PCR algo */
839 for( p_pes = p_stream->chain_pes.p_first; p_pes != NULL; p_pes = p_pes->p_next )
841 int i_size = p_pes->i_size;
842 if( p_pes->i_dts + p_pes->i_length > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
844 mtime_t i_frag = p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length - p_pes->i_dts;
850 i_size = p_pes->i_size * i_frag / p_pes->i_length;
852 i_packet_count += ( i_size + 183 ) / 184;
855 /* add overhead for PCR (not really exact) */
856 i_packet_count += ( 8 * i_pcr_length / p_sys->i_pcr_delay + 175 ) / 176;
859 /* 3: mux PES into TS */
860 BufferChainInit( &chain_ts );
861 /* append PAT/PMT -> FIXME with big pcr delay it won't have enough pat/pmt */
862 GetPAT( p_mux, &chain_ts);
863 GetPMT( p_mux, &chain_ts );
865 i_packet_count += chain_ts.i_depth;
866 /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */
872 ts_stream_t *p_stream;
876 /* Select stream (lowest dts)*/
877 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
879 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
881 if( p_stream->i_pes_dts == 0 )
886 if( i_stream == -1 ||
887 p_stream->i_pes_dts < i_dts )
890 i_dts = p_stream->i_pes_dts;
897 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
899 /* do we need to issue pcr */
901 if( p_stream == p_pcr_stream &&
902 i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count >= p_sys->i_pcr + p_sys->i_pcr_delay )
905 p_sys->i_pcr = i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count;
908 /* Build the TS packet */
909 p_ts = TSNew( p_mux, p_stream, b_pcr );
912 p_ts->i_flags |= SOUT_BUFFER_FLAGS_PRIVATE_CSA;
917 BufferChainAppend( &chain_ts, p_ts );
920 /* 4: date and send */
921 i_packet_count = chain_ts.i_depth;
922 /* msg_Dbg( p_mux, "real pck=%d", i_packet_count ); */
923 for( i = 0; i < i_packet_count; i++ )
925 sout_buffer_t *p_ts = BufferChainGet( &chain_ts );
927 p_ts->i_dts = i_pcr_dts + i_pcr_length * i / i_packet_count;
928 p_ts->i_length = i_pcr_length / i_packet_count;
930 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR )
932 /* msg_Dbg( p_mux, "pcr=%lld ms", p_ts->i_dts / 1000 ); */
933 TSSetPCR( p_ts, p_ts->i_dts - p_sys->i_dts_delay );
935 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_CSA )
937 csa_Encrypt( p_sys->csa, p_ts->p_buffer, 0 );
941 p_ts->i_dts += 3*p_sys->i_caching_delay/2;
943 sout_AccessOutWrite( p_mux->p_access, p_ts );
948 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr )
950 sout_buffer_t *p_pes = p_stream->chain_pes.p_first;
953 vlc_bool_t b_new_pes = VLC_FALSE;
954 vlc_bool_t b_adaptation_field = VLC_FALSE;
956 int i_payload_max = 184 - ( b_pcr ? 8 : 0 );
959 if( p_stream->i_pes_used <= 0 )
961 b_new_pes = VLC_TRUE;
963 i_payload = __MIN( (int)p_pes->i_size - p_stream->i_pes_used, i_payload_max );
965 if( b_pcr || i_payload < i_payload_max )
967 b_adaptation_field = VLC_TRUE;
970 p_ts = sout_BufferNew( p_mux->p_sout, 188 );
972 p_ts->p_buffer[0] = 0x47;
973 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|( ( p_stream->i_pid >> 8 )&0x1f );
974 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
975 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|p_stream->i_continuity_counter;
977 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
979 if( b_adaptation_field )
985 int i_stuffing = i_payload_max - i_payload;
987 p_ts->i_flags |= SOUT_BUFFER_FLAGS_PRIVATE_PCR;
989 p_ts->p_buffer[4] = 7 + i_stuffing;
990 p_ts->p_buffer[5] = 0x10; /* flags */
991 p_ts->p_buffer[6] = ( 0 )&0xff;
992 p_ts->p_buffer[7] = ( 0 )&0xff;
993 p_ts->p_buffer[8] = ( 0 )&0xff;
994 p_ts->p_buffer[9] = ( 0 )&0xff;
995 p_ts->p_buffer[10]= ( 0 )&0x80;
996 p_ts->p_buffer[11]= 0;
998 for( i = 12; i < 12 + i_stuffing; i++ )
1000 p_ts->p_buffer[i] = 0xff;
1005 int i_stuffing = i_payload_max - i_payload;
1007 p_ts->p_buffer[4] = i_stuffing - 1;
1008 if( i_stuffing > 1 )
1010 p_ts->p_buffer[5] = 0x00;
1011 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1013 p_ts->p_buffer[i] = 0xff;
1020 memcpy( &p_ts->p_buffer[188 - i_payload], &p_pes->p_buffer[p_stream->i_pes_used], i_payload );
1022 p_stream->i_pes_used += i_payload;
1023 p_stream->i_pes_dts = p_pes->i_dts + p_pes->i_length * p_stream->i_pes_used / p_pes->i_size;
1024 p_stream->i_pes_length -= p_pes->i_length * i_payload / p_pes->i_size;
1026 if( p_stream->i_pes_used >= (int)p_pes->i_size )
1028 p_pes = BufferChainGet( &p_stream->chain_pes );
1029 sout_BufferDelete( p_mux->p_sout, p_pes );
1031 p_pes = p_stream->chain_pes.p_first;
1034 p_stream->i_pes_dts = p_pes->i_dts;
1035 p_stream->i_pes_length = 0;
1038 p_stream->i_pes_length += p_pes->i_length;
1040 p_pes = p_pes->p_next;
1045 p_stream->i_pes_dts = 0;
1046 p_stream->i_pes_length = 0;
1048 p_stream->i_pes_used = 0;
1055 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts )
1057 mtime_t i_pcr = 9 * i_dts / 100;
1059 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
1060 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
1061 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
1062 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
1063 p_ts->p_buffer[10]|= ( i_pcr << 7 )&0x80;
1067 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 )
1069 sout_mux_sys_t *p_sys = p_mux->p_sys;
1070 sout_buffer_chain_t s = *c;
1073 int i_packets_min = 0;
1074 int i_packets_max = 0;
1081 i_packets = c->i_depth;
1082 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
1083 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
1085 if( i_packets < i_packets_min && i_packets_min > 0 )
1087 sout_buffer_t *p_pk;
1088 int i_div = ( i_packets_min - i_packets ) / i_packets;
1089 int i_mod = ( i_packets_min - i_packets ) % i_packets;
1092 /* We need to pad with null packets (pid=0x1fff)
1093 * We try to melt null packets with true packets */
1095 "packets=%d but min=%d -> adding %d packets of padding",
1096 i_packets, i_packets_min, i_packets_min - i_packets );
1098 BufferChainInit( c );
1099 while( ( p_pk = BufferChainGet( &s ) ) )
1103 BufferChainAppend( c, p_pk );
1105 i_null = i_div + ( i_rest + i_mod ) / i_packets;
1107 for( i = 0; i < i_null; i++ )
1109 sout_buffer_t *p_null;
1111 p_null = sout_BufferNew( p_mux->p_sout, 188 );
1112 p_null->p_buffer[0] = 0x47;
1113 p_null->p_buffer[1] = 0x1f;
1114 p_null->p_buffer[2] = 0xff;
1115 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
1116 memset( &p_null->p_buffer[4], 0, 184 );
1117 p_sys->i_null_continuity_counter =
1118 ( p_sys->i_null_continuity_counter + 1 ) % 16;
1120 BufferChainAppend( c, p_null );
1123 i_rest = ( i_rest + i_mod ) % i_packets;
1126 else if( i_packets > i_packets_max && i_packets_max > 0 )
1128 sout_buffer_t *p_pk;
1131 /* Arg, we need to drop packets, I don't do something clever (like
1132 * dropping complete pid, b frames, ... ), I just get the right amount
1133 * of packets and discard the others */
1135 "packets=%d but max=%d -> removing %d packets -> stream broken",
1136 i_packets, i_packets_max, i_packets - i_packets_max );
1138 BufferChainInit( c );
1139 for( i = 0; i < i_packets_max; i++ )
1141 BufferChainAppend( c, BufferChainGet( &s ) );
1144 while( ( p_pk = BufferChainGet( &s ) ) )
1146 sout_BufferDelete( p_mux->p_sout, p_pk );
1152 static void PEStoTS( sout_instance_t *p_sout,
1153 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
1154 ts_stream_t *p_stream )
1160 /* get PES total size */
1161 i_size = p_pes->i_size;
1162 p_data = p_pes->p_buffer;
1164 b_new_pes = VLC_TRUE;
1168 int b_adaptation_field;
1170 sout_buffer_t *p_ts;
1172 p_ts = sout_BufferNew( p_sout, 188 );
1175 * 1b transport_error_indicator
1176 * 1b payload_unit_start
1177 * 1b transport_priority
1179 * 2b transport_scrambling_control
1180 * 2b if adaptation_field 0x03 else 0x01
1181 * 4b continuity_counter
1184 i_copy = __MIN( i_size, 184 );
1185 b_adaptation_field = i_size < 184 ? VLC_TRUE : VLC_FALSE;
1187 p_ts->p_buffer[0] = 0x47;
1188 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
1189 ( ( p_stream->i_pid >> 8 )&0x1f );
1190 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
1191 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
1192 p_stream->i_continuity_counter;
1194 b_new_pes = VLC_FALSE;
1195 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
1197 if( b_adaptation_field )
1199 int i_stuffing = 184 - i_copy;
1202 p_ts->p_buffer[4] = i_stuffing - 1;
1203 if( i_stuffing > 1 )
1205 p_ts->p_buffer[5] = 0x00;
1206 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1208 p_ts->p_buffer[i] = 0xff;
1213 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1217 BufferChainAppend( c, p_ts );
1221 sout_buffer_t *p_next = p_pes->p_next;
1223 p_pes->p_next = NULL;
1224 sout_BufferDelete( p_sout, p_pes );
1225 if( p_next == NULL )
1229 b_new_pes = VLC_TRUE;
1231 i_size = p_pes->i_size;
1232 p_data = p_pes->p_buffer;
1239 #if defined MODULE_NAME_IS_mux_ts
1240 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1242 static uint32_t CRC32[256] =
1244 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1245 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1246 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1247 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1248 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1249 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1250 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1251 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1252 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1253 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1254 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1255 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1256 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1257 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1258 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1259 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1260 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1261 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1262 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1263 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1264 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1265 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1266 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1267 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1268 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1269 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1270 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1271 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1272 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1273 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1274 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1275 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1276 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1277 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1278 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1279 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1280 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1281 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1282 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1283 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1284 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1285 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1286 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1287 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1288 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1289 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1290 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1291 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1292 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1293 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1294 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1295 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1296 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1297 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1298 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1299 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1300 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1301 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1302 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1303 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1304 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1305 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1306 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1307 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1310 uint32_t i_crc = 0xffffffff;
1312 /* Calculate the CRC */
1313 while( i_count > 0 )
1315 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1323 static void GetPAT( sout_mux_t *p_mux,
1324 sout_buffer_chain_t *c )
1326 sout_mux_sys_t *p_sys = p_mux->p_sys;
1327 sout_buffer_t *p_pat;
1330 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1334 p_pat->i_length = 0;
1336 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1338 bits_write( &bits, 8, 0 ); // pointer
1339 bits_write( &bits, 8, 0x00 ); // table id
1340 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1341 bits_write( &bits, 1, 0 ); // 0
1342 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1343 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1344 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1345 bits_write( &bits, 2, 0x03 ); // FIXME
1346 bits_write( &bits, 5, p_sys->i_pat_version_number );
1347 bits_write( &bits, 1, 1 ); // current_next_indicator
1348 bits_write( &bits, 8, 0 ); // section number
1349 bits_write( &bits, 8, 0 ); // last section number
1351 bits_write( &bits, 16, 1 ); // program number
1352 bits_write( &bits, 3, 0x07 ); // reserved
1353 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1355 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1357 p_pat->i_size = bits.i_data;
1359 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1362 static void GetPMT( sout_mux_t *p_mux,
1363 sout_buffer_chain_t *c )
1365 sout_mux_sys_t *p_sys = p_mux->p_sys;
1366 sout_buffer_t *p_pmt;
1370 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1374 p_pmt->i_length = 0;
1376 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1378 bits_write( &bits, 8, 0 ); // pointer
1379 bits_write( &bits, 8, 0x02 ); // table id
1380 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1381 bits_write( &bits, 1, 0 ); // 0
1382 bits_write( &bits, 2, 0 ); // reserved FIXME
1383 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1384 bits_write( &bits, 16, 1 ); // FIXME program number
1385 bits_write( &bits, 2, 0 ); // FIXME
1386 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1387 bits_write( &bits, 1, 1 ); // current_next_indicator
1388 bits_write( &bits, 8, 0 ); // section number
1389 bits_write( &bits, 8, 0 ); // last section number
1391 bits_write( &bits, 3, 0 ); // reserved
1393 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1394 bits_write( &bits, 4, 0 ); // reserved FIXME
1396 bits_write( &bits, 12, 0 ); // program info len FIXME
1398 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1400 ts_stream_t *p_stream;
1402 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1404 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1405 bits_write( &bits, 3, 0 ); // reserved
1406 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1407 bits_write( &bits, 4, 0 ); //reserved
1408 bits_write( &bits, 12, 0 ); // es info len FIXME
1411 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1413 p_pmt->i_size = bits.i_data;
1415 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1417 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1419 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1420 dvbpsi_psi_section_t* p_section )
1422 sout_buffer_t *p_psi, *p_first = NULL;
1429 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1430 ( p_section->b_syntax_indicator ? 4 : 0 );
1432 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1435 p_psi->i_length = 0;
1436 p_psi->i_size = i_size + 1;
1438 p_psi->p_buffer[0] = 0; // pointer
1439 memcpy( p_psi->p_buffer + 1,
1443 sout_BufferChain( &p_first, p_psi );
1445 p_section = p_section->p_next;
1451 static void GetPAT( sout_mux_t *p_mux,
1452 sout_buffer_chain_t *c )
1454 sout_mux_sys_t *p_sys = p_mux->p_sys;
1455 sout_buffer_t *p_pat;
1457 dvbpsi_psi_section_t *p_section;
1459 dvbpsi_InitPAT( &pat,
1461 p_sys->i_pat_version_number,
1462 1 ); // b_current_next
1463 /* add all program (only one) */
1464 dvbpsi_PATAddProgram( &pat,
1466 p_sys->pmt.i_pid ); // i_pid
1468 p_section = dvbpsi_GenPATSections( &pat,
1469 0 ); // max program per section
1471 p_pat = WritePSISection( p_mux->p_sout, p_section );
1473 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1475 dvbpsi_DeletePSISections( p_section );
1476 dvbpsi_EmptyPAT( &pat );
1479 static uint32_t GetDescriptorLength24b( int i_length )
1481 uint32_t i_l1, i_l2, i_l3;
1483 i_l1 = i_length&0x7f;
1484 i_l2 = ( i_length >> 7 )&0x7f;
1485 i_l3 = ( i_length >> 14 )&0x7f;
1487 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1490 static void GetPMT( sout_mux_t *p_mux,
1491 sout_buffer_chain_t *c )
1493 sout_mux_sys_t *p_sys = p_mux->p_sys;
1494 sout_buffer_t *p_pmt;
1497 dvbpsi_pmt_es_t *p_es;
1498 dvbpsi_psi_section_t *p_section;
1502 dvbpsi_InitPMT( &pmt,
1503 0x01, // program number
1504 p_sys->i_pmt_version_number,
1505 1, // b_current_next
1508 if( p_sys->i_mpeg4_streams > 0 )
1512 bits_buffer_t bits_fix_IOD;
1514 /* Make valgrind happy : it works at byte level not bit one so
1515 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
1516 * working (needed when fixing some bits) */
1517 memset( iod, 0, 4096 );
1519 bits_initwrite( &bits, 4096, iod );
1521 bits_write( &bits, 8, 0x01 );
1522 // InitialObjectDescriptor
1523 bits_align( &bits );
1524 bits_write( &bits, 8, 0x02 ); // tag
1525 bits_fix_IOD = bits; // save states to fix length later
1526 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1527 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1528 bits_write( &bits, 1, 0x00 ); // URL Flag
1529 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1530 bits_write( &bits, 4, 0x0f ); // reserved
1531 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1532 bits_write( &bits, 8, 0xff ); // sceneProfile
1533 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1534 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1535 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1536 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1538 ts_stream_t *p_stream;
1539 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1541 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1543 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1545 bits_align( &bits );
1546 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1547 bits_fix_ESDescr = bits;
1548 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1549 bits_write( &bits, 16, p_stream->i_es_id );
1550 bits_write( &bits, 1, 0x00 ); // streamDependency
1551 bits_write( &bits, 1, 0x00 ); // URL Flag
1552 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1553 bits_write( &bits, 5, 0x1f ); // streamPriority
1555 // DecoderConfigDesciptor
1556 bits_align( &bits );
1557 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1558 bits_fix_Decoder = bits;
1559 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1560 if( p_stream->i_stream_type == 0x10 )
1562 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1563 bits_write( &bits, 6, 0x04 ); // VisualStream
1565 else if( p_stream->i_stream_type == 0x11 )
1567 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1568 bits_write( &bits, 6, 0x05 ); // AudioStream
1572 bits_write( &bits, 8, 0x00 );
1573 bits_write( &bits, 6, 0x00 );
1575 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1577 bits_write( &bits, 1, 0x00 ); // UpStream
1578 bits_write( &bits, 1, 0x01 ); // reserved
1579 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1580 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1581 bits_write( &bits, 32, 0 ); // avgBitrate
1583 if( p_stream->i_decoder_specific_info > 0 )
1586 // DecoderSpecificInfo
1587 bits_align( &bits );
1588 bits_write( &bits, 8, 0x05 ); // tag
1589 bits_write( &bits, 24,
1590 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1591 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1593 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1596 /* fix Decoder length */
1597 bits_write( &bits_fix_Decoder, 24,
1598 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1600 /* SLConfigDescriptor : predifined (0x01) */
1601 bits_align( &bits );
1602 bits_write( &bits, 8, 0x06 ); // tag
1603 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1604 bits_write( &bits, 8, 0x01 ); // predefined
1605 bits_write( &bits, 1, 0 ); // durationFlag
1606 bits_write( &bits, 32, 0 ); // OCRResolution
1607 bits_write( &bits, 8, 0 ); // OCRLength
1608 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1609 bits_align( &bits );
1611 /* fix ESDescr length */
1612 bits_write( &bits_fix_ESDescr, 24,
1613 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1616 bits_align( &bits );
1617 /* fix IOD length */
1618 bits_write( &bits_fix_IOD, 24,
1619 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1620 dvbpsi_PMTAddDescriptor( &pmt,
1626 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1628 ts_stream_t *p_stream;
1630 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1632 p_es = dvbpsi_PMTAddES( &pmt,
1633 p_stream->i_stream_type,
1635 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1640 es_id[0] = (p_stream->i_es_id >> 8)&0xff;
1641 es_id[1] = (p_stream->i_es_id)&0xff;
1642 dvbpsi_PMTESAddDescriptor( p_es, 0x1f, 2, es_id );
1644 else if( p_stream->i_stream_type == 0xa0 )
1647 int i_extra = __MIN( p_stream->i_decoder_specific_info,
1650 /* private DIV3 descripor */
1651 memcpy( &data[0], &p_stream->i_bih_codec, 4 );
1652 data[4] = ( p_stream->i_bih_width >> 8 )&0xff;
1653 data[5] = ( p_stream->i_bih_width )&0xff;
1654 data[6] = ( p_stream->i_bih_height>> 8 )&0xff;
1655 data[7] = ( p_stream->i_bih_height )&0xff;
1656 data[8] = ( i_extra >> 8 )&0xff;
1657 data[9] = ( i_extra )&0xff;
1660 memcpy( &data[10], p_stream->p_decoder_specific_info, i_extra );
1663 /* 0xa0 is private */
1664 dvbpsi_PMTESAddDescriptor( p_es, 0xa0, i_extra + 10, data );
1666 else if( p_stream->i_stream_type == 0x81 )
1668 uint8_t format[4] = { 0x41, 0x43, 0x2d, 0x33 };
1670 /* "registration" descriptor : "AC-3" */
1671 dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
1674 if( p_stream->lang[0] != 0 )
1678 /* I construct the content myself, way faster than looking at
1679 * over complicated/mind broken libdvbpsi way */
1680 data[0] = p_stream->lang[0];
1681 data[1] = p_stream->lang[1];
1682 data[2] = p_stream->lang[2];
1683 data[3] = 0x00; /* audio type: 0x00 undefined */
1685 dvbpsi_PMTESAddDescriptor( p_es, 0x0a, 4, data );
1689 p_section = dvbpsi_GenPMTSections( &pmt );
1691 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1693 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1695 dvbpsi_DeletePSISections( p_section );
1696 dvbpsi_EmptyPMT( &pmt );