1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.18 2003/05/14 11:15:50 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 *****************************************************************************/
30 #include <sys/types.h>
37 #include <vlc/input.h>
48 #if defined MODULE_NAME_IS_mux_ts_dvbpsi
49 # ifdef HAVE_DVBPSI_DR_H
50 # include <dvbpsi/dvbpsi.h>
51 # include <dvbpsi/descriptor.h>
52 # include <dvbpsi/pat.h>
53 # include <dvbpsi/pmt.h>
54 # include <dvbpsi/dr.h>
55 # include <dvbpsi/psi.h>
58 # include "descriptor.h"
59 # include "tables/pat.h"
60 # include "tables/pmt.h"
61 # include "descriptors/dr.h"
66 typedef struct ts_stream_s
71 int i_continuity_counter;
73 /* to be used for carriege of DIV3 */
74 vlc_fourcc_t i_bih_codec;
75 int i_bih_width, i_bih_height;
77 /* Specific to mpeg4 in mpeg2ts */
81 int i_decoder_specific_info_len;
82 uint8_t *p_decoder_specific_info;
95 int i_pid_free; // first usable pid
97 int i_pat_version_number;
100 int i_pmt_version_number;
101 ts_stream_t pmt; // Up to now only one program
103 int i_ts_packet;// To known when to put pat/mpt
110 /*****************************************************************************
111 * Exported prototypes
112 *****************************************************************************/
113 static int Open ( vlc_object_t * );
114 static void Close ( vlc_object_t * );
117 static int Capability(sout_mux_t *, int, void *, void * );
118 static int AddStream( sout_mux_t *, sout_input_t * );
119 static int DelStream( sout_mux_t *, sout_input_t * );
120 static int Mux ( sout_mux_t * );
124 /* Reserve a pid and return it */
125 static int AllocatePID( sout_mux_sys_t *p_sys )
127 return( ++p_sys->i_pid_free );
130 static int GetPAT( sout_mux_t *p_mux, sout_buffer_t **pp_ts );
131 static int GetPMT( sout_mux_t *p_mux, sout_buffer_t **pp_ts );
133 /*****************************************************************************
135 *****************************************************************************/
137 #if defined MODULE_NAME_IS_mux_ts
138 set_description( _("TS muxer") );
139 set_capability( "sout mux", 100 );
140 add_shortcut( "ts" );
141 add_shortcut( "ts_nodvbpsi" );
142 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
143 set_description( _("TS muxer (libdvbpsi)") );
144 set_capability( "sout mux", 120 );
145 add_shortcut( "ts" );
146 add_shortcut( "ts_dvbpsi" );
148 set_callbacks( Open, Close );
151 /*****************************************************************************
153 *****************************************************************************/
154 static int Open( vlc_object_t *p_this )
156 sout_mux_t *p_mux =(sout_mux_t*)p_this;
157 sout_mux_sys_t *p_sys;
159 msg_Info( p_mux, "Open" );
161 p_sys = malloc( sizeof( sout_mux_sys_t ) );
163 p_mux->pf_capacity = Capability;
164 p_mux->pf_addstream = AddStream;
165 p_mux->pf_delstream = DelStream;
167 p_mux->p_sys = p_sys;
168 p_mux->i_preheader = 30; // really enough for a pes header
170 srand( (uint32_t)mdate() );
172 p_sys->i_stream_id_mpga = 0xc0;
173 p_sys->i_stream_id_a52 = 0x80;
174 p_sys->i_stream_id_mpgv = 0xe0;
176 p_sys->i_audio_bound = 0;
177 p_sys->i_video_bound = 0;
179 p_sys->i_pat_version_number = rand() % 32;
180 p_sys->pat.i_pid = 0;
181 p_sys->pat.i_continuity_counter = 0;
183 p_sys->i_pmt_version_number = rand() % 32;
184 p_sys->pmt.i_pid = 0x42;
185 p_sys->pmt.i_continuity_counter = 0;
187 p_sys->i_pid_free = 0x43;
188 p_sys->i_pcr_pid = 0x1fff;
190 p_sys->i_mpeg4_streams = 0;
195 /*****************************************************************************
197 *****************************************************************************/
199 static void Close( vlc_object_t * p_this )
201 sout_mux_t *p_mux = (sout_mux_t*)p_this;
202 sout_mux_sys_t *p_sys = p_mux->p_sys;
204 msg_Info( p_mux, "Close" );
210 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
214 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
215 *(vlc_bool_t*)p_answer = VLC_TRUE;
216 return( SOUT_MUX_CAP_ERR_OK );
218 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
222 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
224 sout_mux_sys_t *p_sys = p_mux->p_sys;
225 ts_stream_t *p_stream;
227 msg_Dbg( p_mux, "adding input" );
228 p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
230 p_stream->i_pid = AllocatePID( p_sys );
231 if( p_sys->i_pcr_pid == 0x1fff )
233 p_sys->i_pcr_pid = p_stream->i_pid;
235 p_stream->i_continuity_counter = 0;
237 switch( p_input->p_fmt->i_cat )
240 switch( p_input->p_fmt->i_fourcc )
242 case VLC_FOURCC( 'm', 'p','g', 'v' ):
243 p_stream->i_stream_type = 0x02;
244 p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
245 p_sys->i_stream_id_mpgv++;
247 case VLC_FOURCC( 'm', 'p','4', 'v' ):
248 p_stream->i_stream_type = 0x10;
249 p_stream->i_stream_id = 0xfa;
250 p_sys->i_mpeg4_streams++;
251 p_stream->i_es_id = p_stream->i_pid;
252 p_stream->i_sl_predefined = 0x01; // NULL SL header
254 /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
255 /* I didn't want to do that :P */
256 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
257 case VLC_FOURCC( 'H', '2', '6', '3' ):
258 case VLC_FOURCC( 'I', '2', '6', '3' ):
259 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
260 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
261 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
262 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
263 p_stream->i_stream_type = 0xa0; // private
264 p_stream->i_stream_id = 0xa0; // beurk
269 p_sys->i_video_bound++;
271 p_stream->i_bih_codec = p_input->p_fmt->i_fourcc;
272 p_stream->i_bih_width = p_input->p_fmt->i_width;
273 p_stream->i_bih_height = p_input->p_fmt->i_height;
275 p_stream->i_decoder_specific_info_len = p_input->p_fmt->i_extra_data;
276 if( p_stream->i_decoder_specific_info_len > 0 )
278 p_stream->p_decoder_specific_info =
279 malloc( p_stream->i_decoder_specific_info_len );
280 memcpy( p_stream->p_decoder_specific_info,
281 p_input->p_fmt->p_extra_data,
282 p_input->p_fmt->i_extra_data );
286 p_stream->p_decoder_specific_info = NULL;
291 switch( p_input->p_fmt->i_fourcc )
293 case VLC_FOURCC( 'a', '5','2', ' ' ):
294 case VLC_FOURCC( 'a', '5','2', 'b' ):
295 p_stream->i_stream_type = 0x81;
296 p_stream->i_stream_id = p_sys->i_stream_id_a52;
297 p_sys->i_stream_id_a52++;
299 case VLC_FOURCC( 'm', 'p','4', 'a' ):
300 p_stream->i_stream_type = 0x11;
301 p_stream->i_stream_id = 0xfa;
302 p_sys->i_mpeg4_streams++;
303 p_stream->i_es_id = p_stream->i_pid;
304 p_stream->i_sl_predefined = 0x01; // NULL SL header
306 case VLC_FOURCC( 'm', 'p','g', 'a' ):
307 p_stream->i_stream_type = 0x04;
308 p_stream->i_stream_id = p_sys->i_stream_id_mpga;
309 p_sys->i_stream_id_mpga++;
314 p_sys->i_audio_bound++;
316 p_stream->i_decoder_specific_info_len = p_input->p_fmt->i_extra_data;
317 if( p_stream->i_decoder_specific_info_len > 0 )
319 p_stream->p_decoder_specific_info =
320 malloc( p_stream->i_decoder_specific_info_len );
321 memcpy( p_stream->p_decoder_specific_info,
322 p_input->p_fmt->p_extra_data,
323 p_input->p_fmt->i_extra_data );
327 p_stream->p_decoder_specific_info = NULL;
334 p_sys->i_ts_packet = 0; // force pat/pmt recreation
335 p_sys->i_pat_version_number++; p_sys->i_pat_version_number %= 32;
336 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
341 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
343 sout_mux_sys_t *p_sys = p_mux->p_sys;
344 ts_stream_t *p_stream;
346 msg_Dbg( p_mux, "removing input" );
347 p_stream = (ts_stream_t*)p_input->p_sys;
349 if( p_stream->p_decoder_specific_info )
351 free( p_stream->p_decoder_specific_info );
353 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
355 p_sys->i_mpeg4_streams--;
359 p_sys->i_ts_packet = 0; // force pat/pmt recreation
360 p_sys->i_pat_version_number++; p_sys->i_pat_version_number %= 32;
361 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
368 static int MuxGetStream( sout_mux_t *p_mux,
376 for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ )
380 p_fifo = p_mux->pp_inputs[i]->p_fifo;
382 if( p_fifo->i_depth > 1 )
384 sout_buffer_t *p_buf;
386 p_buf = sout_FifoShow( p_fifo );
387 if( i_stream < 0 || p_buf->i_dts < i_dts )
389 i_dts = p_buf->i_dts;
395 return( -1 ); // wait that all fifo have at least 2 packets
401 *pi_stream = i_stream;
411 static int PEStoTS( sout_instance_t *p_sout,
412 sout_buffer_t **pp_ts, sout_buffer_t *p_pes,
413 ts_stream_t *p_stream )
423 /* get PES total size */
424 i_size = p_pes->i_size;
425 p_data = p_pes->p_buffer;
427 if( p_pes->i_dts == 0 && p_pes->i_length > 0 )
429 i_dts = 1; // XXX <french> kludge immonde </french>
433 i_dts = p_pes->i_dts;
436 for( i_first = 1, b_new_pes = 1; p_pes != NULL; )
438 int i_adaptation_field;
444 p_ts = sout_BufferNew( p_sout, 188 );
450 i_payload = 184 - ( i_first && i_dts > 0 ? 8 : 0 );
451 i_copy = __MIN( i_size, i_payload );
453 i_adaptation_field = ( ( i_first && i_dts > 0 ) ||
454 i_size < i_payload ) ? 1 : 0;
457 bits_initwrite( &bits, 188, p_ts->p_buffer );
458 bits_write( &bits, 8, 0x47 ); /* sync byte */
459 bits_write( &bits, 1, 0 ); /* transport_error_indicator */
460 bits_write( &bits, 1, b_new_pes ? 1 : 0 ); /* payload_unit_start */
462 bits_write( &bits, 1, 0 ); /* transport_priority */
463 bits_write( &bits, 13, p_stream->i_pid );
464 bits_write( &bits, 2, 0 ); /* transport_scrambling_control */
465 bits_write( &bits, 2, ( i_adaptation_field ? 0x03 : 0x01 ) );
467 bits_write( &bits, 4, /* continuity_counter */
468 p_stream->i_continuity_counter );
469 p_stream->i_continuity_counter++;
470 p_stream->i_continuity_counter %= 16;
471 if( i_adaptation_field )
476 if( i_first && i_dts > 0 )
478 i_stuffing = i_payload - i_copy;
479 bits_write( &bits, 8, 7 + i_stuffing );
480 bits_write( &bits, 8, 0x10 ); /* various flags */
481 bits_write( &bits, 33, i_dts * 9 / 100);
482 bits_write( &bits, 6, 0 );
483 bits_write( &bits, 9, 0 );
484 i_dts = 0; /* XXX set dts only for first ts packet */
488 i_stuffing = i_payload - i_copy;
489 bits_write( &bits, 8, i_stuffing - 1);
490 if( i_stuffing - 1 > 0 )
492 bits_write( &bits, 8, 0 );
498 for( i = 0; i < i_stuffing; i++ )
500 bits_write( &bits, 8, 0xff );
504 memcpy( p_ts->p_buffer + bits.i_data,
510 sout_BufferChain( pp_ts, p_ts );
516 sout_buffer_t *p_next;
518 p_next = p_pes->p_next;
519 p_pes->p_next = NULL;
520 sout_BufferDelete( p_sout, p_pes );
525 i_size = p_pes->i_size;
526 p_data = p_pes->p_buffer;
538 static void SetTSDate( sout_buffer_t *p_ts, mtime_t i_dts, mtime_t i_length )
541 sout_buffer_t *p_tmp;
544 for( p_tmp = p_ts, i_count = 0; p_tmp != NULL; p_tmp = p_tmp->p_next )
548 i_delta = i_length / i_count;
550 for( p_tmp = p_ts; p_tmp != NULL; p_tmp = p_tmp->p_next )
552 p_tmp->i_dts = i_dts;
553 p_tmp->i_length = i_delta;
559 static int Mux( sout_mux_t *p_mux )
561 sout_mux_sys_t *p_sys = p_mux->p_sys;
564 sout_buffer_t *p_pat, *p_pmt, *p_ts;
568 mtime_t i_dts, i_length;
570 sout_input_t *p_input;
571 ts_stream_t *p_stream;
573 sout_buffer_t *p_data;
575 if( MuxGetStream( p_mux, &i_stream, &i_dts ) < 0 )
580 p_input = p_mux->pp_inputs[i_stream];
581 p_fifo = p_input->p_fifo;
582 p_stream = (ts_stream_t*)p_input->p_sys;
584 p_data = sout_FifoGet( p_fifo );
585 i_dts = p_data->i_dts;
586 i_length = p_data->i_length;
588 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
589 PEStoTS( p_mux->p_sout, &p_data, p_data, p_stream );
591 if( p_sys->i_ts_packet % 30 == 0 )
594 GetPAT( p_mux, &p_pat );
595 GetPMT( p_mux, &p_pmt );
598 sout_BufferChain( &p_ts, p_pmt );
599 sout_BufferChain( &p_ts, p_data );
606 p_sys->i_ts_packet++;
607 SetTSDate( p_ts, i_dts, i_length );
609 sout_AccessOutWrite( p_mux->p_access, p_ts );
616 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
618 static uint32_t CRC32[256] =
620 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
621 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
622 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
623 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
624 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
625 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
626 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
627 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
628 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
629 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
630 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
631 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
632 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
633 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
634 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
635 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
636 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
637 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
638 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
639 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
640 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
641 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
642 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
643 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
644 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
645 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
646 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
647 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
648 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
649 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
650 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
651 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
652 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
653 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
654 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
655 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
656 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
657 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
658 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
659 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
660 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
661 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
662 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
663 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
664 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
665 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
666 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
667 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
668 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
669 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
670 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
671 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
672 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
673 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
674 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
675 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
676 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
677 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
678 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
679 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
680 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
681 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
682 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
683 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
686 uint32_t i_crc = 0xffffffff;
688 /* Calculate the CRC */
691 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
699 #if defined MODULE_NAME_IS_mux_ts
700 static int GetPAT( sout_mux_t *p_mux,
701 sout_buffer_t **pp_ts )
703 sout_mux_sys_t *p_sys = p_mux->p_sys;
704 sout_buffer_t *p_pat;
707 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
713 bits_initwrite( &bits, 1024, p_pat->p_buffer );
715 bits_write( &bits, 8, 0 ); // pointer
716 bits_write( &bits, 8, 0x00 ); // table id
717 bits_write( &bits, 1, 1 ); // section_syntax_indicator
718 bits_write( &bits, 1, 0 ); // 0
719 bits_write( &bits, 2, 0x03 ); // reserved FIXME
720 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
721 bits_write( &bits, 16, 0x01 ); // FIXME stream id
722 bits_write( &bits, 2, 0x03 ); // FIXME
723 bits_write( &bits, 5, p_sys->i_pat_version_number );
724 bits_write( &bits, 1, 1 ); // current_next_indicator
725 bits_write( &bits, 8, 0 ); // section number
726 bits_write( &bits, 8, 0 ); // last section number
728 bits_write( &bits, 16, 1 ); // program number
729 bits_write( &bits, 3, 0x07 ); // reserved
730 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
732 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
734 p_pat->i_size = bits.i_data;
736 return( PEStoTS( p_mux->p_sout, pp_ts, p_pat, &p_sys->pat ) );
739 static int GetPMT( sout_mux_t *p_mux,
740 sout_buffer_t **pp_ts )
742 sout_mux_sys_t *p_sys = p_mux->p_sys;
743 sout_buffer_t *p_pmt;
747 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
753 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
755 bits_write( &bits, 8, 0 ); // pointer
756 bits_write( &bits, 8, 0x02 ); // table id
757 bits_write( &bits, 1, 1 ); // section_syntax_indicator
758 bits_write( &bits, 1, 0 ); // 0
759 bits_write( &bits, 2, 0 ); // reserved FIXME
760 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
761 bits_write( &bits, 16, 1 ); // FIXME program number
762 bits_write( &bits, 2, 0 ); // FIXME
763 bits_write( &bits, 5, p_sys->i_pmt_version_number );
764 bits_write( &bits, 1, 0 ); // current_next_indicator
765 bits_write( &bits, 8, 0 ); // section number
766 bits_write( &bits, 8, 0 ); // last section number
768 bits_write( &bits, 3, 0 ); // reserved
770 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
771 bits_write( &bits, 4, 0 ); // reserved FIXME
773 bits_write( &bits, 12, 0 ); // program info len FIXME
775 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
777 ts_stream_t *p_stream;
779 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
781 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
782 bits_write( &bits, 3, 0 ); // reserved
783 bits_write( &bits, 13, p_stream->i_pid ); // es pid
784 bits_write( &bits, 4, 0 ); //reserved
785 bits_write( &bits, 12, 0 ); // es info len FIXME
788 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
790 p_pmt->i_size = bits.i_data;
792 return( PEStoTS( p_mux->p_sout, pp_ts, p_pmt, &p_sys->pmt ) );
795 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
797 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
798 dvbpsi_psi_section_t* p_section )
800 sout_buffer_t *p_psi, *p_first = NULL;
807 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
808 ( p_section->b_syntax_indicator ? 4 : 0 );
810 p_psi = sout_BufferNew( p_sout, i_size + 1 );
814 p_psi->i_size = i_size + 1;
816 p_psi->p_buffer[0] = 0; // pointer
817 memcpy( p_psi->p_buffer + 1,
821 sout_BufferChain( &p_first, p_psi );
823 p_section = p_section->p_next;
829 static int GetPAT( sout_mux_t *p_mux,
830 sout_buffer_t **pp_ts )
832 sout_mux_sys_t *p_sys = p_mux->p_sys;
833 sout_buffer_t *p_pat;
835 dvbpsi_psi_section_t *p_section;
837 dvbpsi_InitPAT( &pat,
839 p_sys->i_pat_version_number,
840 0); // b_current_next
841 /* add all program (only one) */
842 dvbpsi_PATAddProgram( &pat,
844 p_sys->pmt.i_pid ); // i_pid
846 p_section = dvbpsi_GenPATSections( &pat,
847 0 ); // max program per section
849 p_pat = WritePSISection( p_mux->p_sout, p_section );
851 PEStoTS( p_mux->p_sout, pp_ts, p_pat, &p_sys->pat );
853 dvbpsi_DeletePSISections( p_section );
854 dvbpsi_EmptyPAT( &pat );
858 static uint32_t GetDescriptorLength24b( int i_length )
860 uint32_t i_l1, i_l2, i_l3;
862 i_l1 = i_length&0x7f;
863 i_l2 = ( i_length >> 7 )&0x7f;
864 i_l3 = ( i_length >> 14 )&0x7f;
866 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
869 static int GetPMT( sout_mux_t *p_mux,
870 sout_buffer_t **pp_ts )
872 sout_mux_sys_t *p_sys = p_mux->p_sys;
873 sout_buffer_t *p_pmt;
876 dvbpsi_pmt_es_t *p_es;
877 dvbpsi_psi_section_t *p_section;
881 dvbpsi_InitPMT( &pmt,
882 0x01, // program number
883 p_sys->i_pmt_version_number,
887 if( p_sys->i_mpeg4_streams > 0 )
891 bits_buffer_t bits_fix_IOD;
893 bits_initwrite( &bits, 4096, iod );
895 bits_write( &bits, 8, 0x01 );
896 // InitialObjectDescriptor
898 bits_write( &bits, 8, 0x02 ); // tag
899 bits_fix_IOD = bits; // save states to fix length later
900 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
901 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
902 bits_write( &bits, 1, 0x00 ); // URL Flag
903 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
904 bits_write( &bits, 4, 0x0f ); // reserved
905 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
906 bits_write( &bits, 8, 0xff ); // sceneProfile
907 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
908 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
909 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
910 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
912 ts_stream_t *p_stream;
913 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
915 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
917 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
920 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
921 bits_fix_ESDescr = bits;
922 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
923 bits_write( &bits, 16, p_stream->i_es_id );
924 bits_write( &bits, 1, 0x00 ); // streamDependency
925 bits_write( &bits, 1, 0x00 ); // URL Flag
926 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
927 bits_write( &bits, 5, 0x1f ); // streamPriority
929 // DecoderConfigDesciptor
931 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
932 bits_fix_Decoder = bits;
933 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
934 if( p_stream->i_stream_type == 0x10 )
936 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
937 bits_write( &bits, 6, 0x04 ); // VisualStream
939 else if( p_stream->i_stream_type == 0x11 )
941 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
942 bits_write( &bits, 6, 0x05 ); // AudioStream
946 bits_write( &bits, 8, 0x00 );
947 bits_write( &bits, 6, 0x00 );
949 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
951 bits_write( &bits, 1, 0x00 ); // UpStream
952 bits_write( &bits, 1, 0x01 ); // reserved
953 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
954 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
955 bits_write( &bits, 32, 0 ); // avgBitrate
957 if( p_stream->i_decoder_specific_info_len > 0 )
960 // DecoderSpecificInfo
962 bits_write( &bits, 8, 0x05 ); // tag
963 bits_write( &bits, 24,
964 GetDescriptorLength24b( p_stream->i_decoder_specific_info_len ) );
965 for( i = 0; i < p_stream->i_decoder_specific_info_len; i++ )
967 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
970 /* fix Decoder length */
971 bits_write( &bits_fix_Decoder, 24,
972 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
974 // SLConfigDescriptor
975 switch( p_stream->i_sl_predefined )
980 bits_write( &bits, 8, 0x06 ); // tag
981 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
982 bits_write( &bits, 8, 0x01 ); // predefined
983 bits_write( &bits, 1, 0 ); // durationFlag
984 bits_write( &bits, 32, 0 ); // OCRResolution
985 bits_write( &bits, 8, 0 ); // OCRLength
986 bits_write( &bits, 8, 0 ); // InstantBitrateLength
990 msg_Err( p_mux,"Unsupported SL profile => broken IOD");
993 /* fix ESDescr length */
994 bits_write( &bits_fix_ESDescr, 24,
995 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1000 bits_write( &bits_fix_IOD, 24,
1001 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1002 dvbpsi_PMTAddDescriptor( &pmt,
1008 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1010 ts_stream_t *p_stream;
1012 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1014 p_es = dvbpsi_PMTAddES( &pmt,
1015 p_stream->i_stream_type,
1017 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1023 bits_initwrite( &bits, 512, data );
1024 bits_write( &bits, 16, p_stream->i_es_id );
1026 dvbpsi_PMTESAddDescriptor( p_es,
1031 else if( p_stream->i_stream_id == 0xa0 )
1036 /* private DIV3 descripor */
1037 bits_initwrite( &bits, 512, data );
1038 bits_write( &bits, 32, p_stream->i_bih_codec );
1039 bits_write( &bits, 16, p_stream->i_bih_width );
1040 bits_write( &bits, 16, p_stream->i_bih_height );
1041 bits_write( &bits, 16, p_stream->i_decoder_specific_info_len );
1042 if( p_stream->i_decoder_specific_info_len > 0 )
1045 for( i = 0; i < p_stream->i_decoder_specific_info_len; i++ )
1047 bits_write( &bits, 8, p_stream->p_decoder_specific_info[i] );
1050 dvbpsi_PMTESAddDescriptor( p_es,
1057 p_section = dvbpsi_GenPMTSections( &pmt );
1059 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1061 PEStoTS( p_mux->p_sout, pp_ts, p_pmt, &p_sys->pmt );
1063 dvbpsi_DeletePSISections( p_section );
1064 dvbpsi_EmptyPMT( &pmt );