1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.20 2003/05/31 21:49:12 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 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
264 p_stream->i_stream_type = 0xa0; // private
265 p_stream->i_stream_id = 0xa0; // beurk
270 p_sys->i_video_bound++;
272 p_stream->i_bih_codec = p_input->p_fmt->i_fourcc;
273 p_stream->i_bih_width = p_input->p_fmt->i_width;
274 p_stream->i_bih_height = p_input->p_fmt->i_height;
276 p_stream->i_decoder_specific_info_len = p_input->p_fmt->i_extra_data;
277 if( p_stream->i_decoder_specific_info_len > 0 )
279 p_stream->p_decoder_specific_info =
280 malloc( p_stream->i_decoder_specific_info_len );
281 memcpy( p_stream->p_decoder_specific_info,
282 p_input->p_fmt->p_extra_data,
283 p_input->p_fmt->i_extra_data );
287 p_stream->p_decoder_specific_info = NULL;
292 switch( p_input->p_fmt->i_fourcc )
294 case VLC_FOURCC( 'a', '5','2', ' ' ):
295 case VLC_FOURCC( 'a', '5','2', 'b' ):
296 p_stream->i_stream_type = 0x81;
297 p_stream->i_stream_id = p_sys->i_stream_id_a52;
298 p_sys->i_stream_id_a52++;
300 case VLC_FOURCC( 'm', 'p','4', 'a' ):
301 p_stream->i_stream_type = 0x11;
302 p_stream->i_stream_id = 0xfa;
303 p_sys->i_mpeg4_streams++;
304 p_stream->i_es_id = p_stream->i_pid;
305 p_stream->i_sl_predefined = 0x01; // NULL SL header
307 case VLC_FOURCC( 'm', 'p','g', 'a' ):
308 p_stream->i_stream_type = 0x04;
309 p_stream->i_stream_id = p_sys->i_stream_id_mpga;
310 p_sys->i_stream_id_mpga++;
315 p_sys->i_audio_bound++;
317 p_stream->i_decoder_specific_info_len = p_input->p_fmt->i_extra_data;
318 if( p_stream->i_decoder_specific_info_len > 0 )
320 p_stream->p_decoder_specific_info =
321 malloc( p_stream->i_decoder_specific_info_len );
322 memcpy( p_stream->p_decoder_specific_info,
323 p_input->p_fmt->p_extra_data,
324 p_input->p_fmt->i_extra_data );
328 p_stream->p_decoder_specific_info = NULL;
335 p_sys->i_ts_packet = 0; // force pat/pmt recreation
336 p_sys->i_pat_version_number++; p_sys->i_pat_version_number %= 32;
337 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
342 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
344 sout_mux_sys_t *p_sys = p_mux->p_sys;
345 ts_stream_t *p_stream;
347 msg_Dbg( p_mux, "removing input" );
348 p_stream = (ts_stream_t*)p_input->p_sys;
350 if( p_stream->p_decoder_specific_info )
352 free( p_stream->p_decoder_specific_info );
354 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
356 p_sys->i_mpeg4_streams--;
360 p_sys->i_ts_packet = 0; // force pat/pmt recreation
361 p_sys->i_pat_version_number++; p_sys->i_pat_version_number %= 32;
362 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
369 static int MuxGetStream( sout_mux_t *p_mux,
377 for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ )
381 p_fifo = p_mux->pp_inputs[i]->p_fifo;
383 if( p_fifo->i_depth > 1 )
385 sout_buffer_t *p_buf;
387 p_buf = sout_FifoShow( p_fifo );
388 if( i_stream < 0 || p_buf->i_dts < i_dts )
390 i_dts = p_buf->i_dts;
396 return( -1 ); // wait that all fifo have at least 2 packets
402 *pi_stream = i_stream;
412 static int PEStoTS( sout_instance_t *p_sout,
413 sout_buffer_t **pp_ts, sout_buffer_t *p_pes,
414 ts_stream_t *p_stream )
424 /* get PES total size */
425 i_size = p_pes->i_size;
426 p_data = p_pes->p_buffer;
428 if( p_pes->i_dts == 0 && p_pes->i_length > 0 )
430 i_dts = 1; // XXX <french> kludge immonde </french>
434 i_dts = p_pes->i_dts;
437 for( i_first = 1, b_new_pes = 1; p_pes != NULL; )
439 int i_adaptation_field;
445 p_ts = sout_BufferNew( p_sout, 188 );
451 i_payload = 184 - ( i_first && i_dts > 0 ? 8 : 0 );
452 i_copy = __MIN( i_size, i_payload );
454 i_adaptation_field = ( ( i_first && i_dts > 0 ) ||
455 i_size < i_payload ) ? 1 : 0;
458 bits_initwrite( &bits, 188, p_ts->p_buffer );
459 bits_write( &bits, 8, 0x47 ); /* sync byte */
460 bits_write( &bits, 1, 0 ); /* transport_error_indicator */
461 bits_write( &bits, 1, b_new_pes ? 1 : 0 ); /* payload_unit_start */
463 bits_write( &bits, 1, 0 ); /* transport_priority */
464 bits_write( &bits, 13, p_stream->i_pid );
465 bits_write( &bits, 2, 0 ); /* transport_scrambling_control */
466 bits_write( &bits, 2, ( i_adaptation_field ? 0x03 : 0x01 ) );
468 bits_write( &bits, 4, /* continuity_counter */
469 p_stream->i_continuity_counter );
470 p_stream->i_continuity_counter++;
471 p_stream->i_continuity_counter %= 16;
472 if( i_adaptation_field )
477 if( i_first && i_dts > 0 )
479 i_stuffing = i_payload - i_copy;
480 bits_write( &bits, 8, 7 + i_stuffing );
481 bits_write( &bits, 8, 0x10 ); /* various flags */
482 bits_write( &bits, 33, i_dts * 9 / 100);
483 bits_write( &bits, 6, 0 );
484 bits_write( &bits, 9, 0 );
485 i_dts = 0; /* XXX set dts only for first ts packet */
489 i_stuffing = i_payload - i_copy;
490 bits_write( &bits, 8, i_stuffing - 1);
491 if( i_stuffing - 1 > 0 )
493 bits_write( &bits, 8, 0 );
499 for( i = 0; i < i_stuffing; i++ )
501 bits_write( &bits, 8, 0xff );
505 memcpy( p_ts->p_buffer + bits.i_data,
511 sout_BufferChain( pp_ts, p_ts );
517 sout_buffer_t *p_next;
519 p_next = p_pes->p_next;
520 p_pes->p_next = NULL;
521 sout_BufferDelete( p_sout, p_pes );
526 i_size = p_pes->i_size;
527 p_data = p_pes->p_buffer;
539 static void SetTSDate( sout_buffer_t *p_ts, mtime_t i_dts, mtime_t i_length )
542 sout_buffer_t *p_tmp;
545 for( p_tmp = p_ts, i_count = 0; p_tmp != NULL; p_tmp = p_tmp->p_next )
549 i_delta = i_length / i_count;
551 for( p_tmp = p_ts; p_tmp != NULL; p_tmp = p_tmp->p_next )
553 p_tmp->i_dts = i_dts;
554 p_tmp->i_length = i_delta;
560 static int Mux( sout_mux_t *p_mux )
562 sout_mux_sys_t *p_sys = p_mux->p_sys;
565 sout_buffer_t *p_pat, *p_pmt, *p_ts;
569 mtime_t i_dts, i_length;
571 sout_input_t *p_input;
572 ts_stream_t *p_stream;
574 sout_buffer_t *p_data;
576 if( MuxGetStream( p_mux, &i_stream, &i_dts ) < 0 )
581 p_input = p_mux->pp_inputs[i_stream];
582 p_fifo = p_input->p_fifo;
583 p_stream = (ts_stream_t*)p_input->p_sys;
585 p_data = sout_FifoGet( p_fifo );
586 i_dts = p_data->i_dts;
587 i_length = p_data->i_length;
589 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
590 PEStoTS( p_mux->p_sout, &p_data, p_data, p_stream );
592 if( p_sys->i_ts_packet % 30 == 0 )
595 GetPAT( p_mux, &p_pat );
596 GetPMT( p_mux, &p_pmt );
599 sout_BufferChain( &p_ts, p_pmt );
600 sout_BufferChain( &p_ts, p_data );
607 p_sys->i_ts_packet++;
608 SetTSDate( p_ts, i_dts, i_length );
610 sout_AccessOutWrite( p_mux->p_access, p_ts );
617 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
619 static uint32_t CRC32[256] =
621 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
622 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
623 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
624 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
625 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
626 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
627 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
628 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
629 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
630 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
631 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
632 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
633 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
634 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
635 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
636 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
637 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
638 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
639 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
640 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
641 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
642 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
643 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
644 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
645 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
646 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
647 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
648 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
649 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
650 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
651 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
652 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
653 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
654 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
655 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
656 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
657 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
658 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
659 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
660 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
661 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
662 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
663 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
664 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
665 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
666 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
667 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
668 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
669 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
670 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
671 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
672 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
673 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
674 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
675 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
676 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
677 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
678 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
679 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
680 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
681 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
682 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
683 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
684 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
687 uint32_t i_crc = 0xffffffff;
689 /* Calculate the CRC */
692 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
700 #if defined MODULE_NAME_IS_mux_ts
701 static int GetPAT( sout_mux_t *p_mux,
702 sout_buffer_t **pp_ts )
704 sout_mux_sys_t *p_sys = p_mux->p_sys;
705 sout_buffer_t *p_pat;
708 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
714 bits_initwrite( &bits, 1024, p_pat->p_buffer );
716 bits_write( &bits, 8, 0 ); // pointer
717 bits_write( &bits, 8, 0x00 ); // table id
718 bits_write( &bits, 1, 1 ); // section_syntax_indicator
719 bits_write( &bits, 1, 0 ); // 0
720 bits_write( &bits, 2, 0x03 ); // reserved FIXME
721 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
722 bits_write( &bits, 16, 0x01 ); // FIXME stream id
723 bits_write( &bits, 2, 0x03 ); // FIXME
724 bits_write( &bits, 5, p_sys->i_pat_version_number );
725 bits_write( &bits, 1, 1 ); // current_next_indicator
726 bits_write( &bits, 8, 0 ); // section number
727 bits_write( &bits, 8, 0 ); // last section number
729 bits_write( &bits, 16, 1 ); // program number
730 bits_write( &bits, 3, 0x07 ); // reserved
731 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
733 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
735 p_pat->i_size = bits.i_data;
737 return( PEStoTS( p_mux->p_sout, pp_ts, p_pat, &p_sys->pat ) );
740 static int GetPMT( sout_mux_t *p_mux,
741 sout_buffer_t **pp_ts )
743 sout_mux_sys_t *p_sys = p_mux->p_sys;
744 sout_buffer_t *p_pmt;
748 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
754 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
756 bits_write( &bits, 8, 0 ); // pointer
757 bits_write( &bits, 8, 0x02 ); // table id
758 bits_write( &bits, 1, 1 ); // section_syntax_indicator
759 bits_write( &bits, 1, 0 ); // 0
760 bits_write( &bits, 2, 0 ); // reserved FIXME
761 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
762 bits_write( &bits, 16, 1 ); // FIXME program number
763 bits_write( &bits, 2, 0 ); // FIXME
764 bits_write( &bits, 5, p_sys->i_pmt_version_number );
765 bits_write( &bits, 1, 0 ); // current_next_indicator
766 bits_write( &bits, 8, 0 ); // section number
767 bits_write( &bits, 8, 0 ); // last section number
769 bits_write( &bits, 3, 0 ); // reserved
771 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
772 bits_write( &bits, 4, 0 ); // reserved FIXME
774 bits_write( &bits, 12, 0 ); // program info len FIXME
776 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
778 ts_stream_t *p_stream;
780 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
782 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
783 bits_write( &bits, 3, 0 ); // reserved
784 bits_write( &bits, 13, p_stream->i_pid ); // es pid
785 bits_write( &bits, 4, 0 ); //reserved
786 bits_write( &bits, 12, 0 ); // es info len FIXME
789 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
791 p_pmt->i_size = bits.i_data;
793 return( PEStoTS( p_mux->p_sout, pp_ts, p_pmt, &p_sys->pmt ) );
796 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
798 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
799 dvbpsi_psi_section_t* p_section )
801 sout_buffer_t *p_psi, *p_first = NULL;
808 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
809 ( p_section->b_syntax_indicator ? 4 : 0 );
811 p_psi = sout_BufferNew( p_sout, i_size + 1 );
815 p_psi->i_size = i_size + 1;
817 p_psi->p_buffer[0] = 0; // pointer
818 memcpy( p_psi->p_buffer + 1,
822 sout_BufferChain( &p_first, p_psi );
824 p_section = p_section->p_next;
830 static int GetPAT( sout_mux_t *p_mux,
831 sout_buffer_t **pp_ts )
833 sout_mux_sys_t *p_sys = p_mux->p_sys;
834 sout_buffer_t *p_pat;
836 dvbpsi_psi_section_t *p_section;
838 dvbpsi_InitPAT( &pat,
840 p_sys->i_pat_version_number,
841 0); // b_current_next
842 /* add all program (only one) */
843 dvbpsi_PATAddProgram( &pat,
845 p_sys->pmt.i_pid ); // i_pid
847 p_section = dvbpsi_GenPATSections( &pat,
848 0 ); // max program per section
850 p_pat = WritePSISection( p_mux->p_sout, p_section );
852 PEStoTS( p_mux->p_sout, pp_ts, p_pat, &p_sys->pat );
854 dvbpsi_DeletePSISections( p_section );
855 dvbpsi_EmptyPAT( &pat );
859 static uint32_t GetDescriptorLength24b( int i_length )
861 uint32_t i_l1, i_l2, i_l3;
863 i_l1 = i_length&0x7f;
864 i_l2 = ( i_length >> 7 )&0x7f;
865 i_l3 = ( i_length >> 14 )&0x7f;
867 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
870 static int GetPMT( sout_mux_t *p_mux,
871 sout_buffer_t **pp_ts )
873 sout_mux_sys_t *p_sys = p_mux->p_sys;
874 sout_buffer_t *p_pmt;
877 dvbpsi_pmt_es_t *p_es;
878 dvbpsi_psi_section_t *p_section;
882 dvbpsi_InitPMT( &pmt,
883 0x01, // program number
884 p_sys->i_pmt_version_number,
888 if( p_sys->i_mpeg4_streams > 0 )
892 bits_buffer_t bits_fix_IOD;
894 bits_initwrite( &bits, 4096, iod );
896 bits_write( &bits, 8, 0x01 );
897 // InitialObjectDescriptor
899 bits_write( &bits, 8, 0x02 ); // tag
900 bits_fix_IOD = bits; // save states to fix length later
901 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
902 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
903 bits_write( &bits, 1, 0x00 ); // URL Flag
904 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
905 bits_write( &bits, 4, 0x0f ); // reserved
906 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
907 bits_write( &bits, 8, 0xff ); // sceneProfile
908 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
909 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
910 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
911 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
913 ts_stream_t *p_stream;
914 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
916 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
918 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
921 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
922 bits_fix_ESDescr = bits;
923 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
924 bits_write( &bits, 16, p_stream->i_es_id );
925 bits_write( &bits, 1, 0x00 ); // streamDependency
926 bits_write( &bits, 1, 0x00 ); // URL Flag
927 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
928 bits_write( &bits, 5, 0x1f ); // streamPriority
930 // DecoderConfigDesciptor
932 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
933 bits_fix_Decoder = bits;
934 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
935 if( p_stream->i_stream_type == 0x10 )
937 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
938 bits_write( &bits, 6, 0x04 ); // VisualStream
940 else if( p_stream->i_stream_type == 0x11 )
942 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
943 bits_write( &bits, 6, 0x05 ); // AudioStream
947 bits_write( &bits, 8, 0x00 );
948 bits_write( &bits, 6, 0x00 );
950 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
952 bits_write( &bits, 1, 0x00 ); // UpStream
953 bits_write( &bits, 1, 0x01 ); // reserved
954 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
955 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
956 bits_write( &bits, 32, 0 ); // avgBitrate
958 if( p_stream->i_decoder_specific_info_len > 0 )
961 // DecoderSpecificInfo
963 bits_write( &bits, 8, 0x05 ); // tag
964 bits_write( &bits, 24,
965 GetDescriptorLength24b( p_stream->i_decoder_specific_info_len ) );
966 for( i = 0; i < p_stream->i_decoder_specific_info_len; i++ )
968 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
971 /* fix Decoder length */
972 bits_write( &bits_fix_Decoder, 24,
973 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
975 // SLConfigDescriptor
976 switch( p_stream->i_sl_predefined )
981 bits_write( &bits, 8, 0x06 ); // tag
982 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
983 bits_write( &bits, 8, 0x01 ); // predefined
984 bits_write( &bits, 1, 0 ); // durationFlag
985 bits_write( &bits, 32, 0 ); // OCRResolution
986 bits_write( &bits, 8, 0 ); // OCRLength
987 bits_write( &bits, 8, 0 ); // InstantBitrateLength
991 msg_Err( p_mux,"Unsupported SL profile => broken IOD");
994 /* fix ESDescr length */
995 bits_write( &bits_fix_ESDescr, 24,
996 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1000 /* fix IOD length */
1001 bits_write( &bits_fix_IOD, 24,
1002 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1003 dvbpsi_PMTAddDescriptor( &pmt,
1009 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1011 ts_stream_t *p_stream;
1013 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1015 p_es = dvbpsi_PMTAddES( &pmt,
1016 p_stream->i_stream_type,
1018 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1024 bits_initwrite( &bits, 512, data );
1025 bits_write( &bits, 16, p_stream->i_es_id );
1027 dvbpsi_PMTESAddDescriptor( p_es,
1032 else if( p_stream->i_stream_id == 0xa0 )
1038 memcpy( fcc, &p_stream->i_bih_codec, 4 );
1040 /* private DIV3 descripor */
1041 bits_initwrite( &bits, 512, data );
1042 bits_write( &bits, 8, fcc[0]);
1043 bits_write( &bits, 8, fcc[1]);
1044 bits_write( &bits, 8, fcc[2]);
1045 bits_write( &bits, 8, fcc[3]);
1046 bits_write( &bits, 16, p_stream->i_bih_width );
1047 bits_write( &bits, 16, p_stream->i_bih_height );
1048 bits_write( &bits, 16, p_stream->i_decoder_specific_info_len );
1049 if( p_stream->i_decoder_specific_info_len > 0 )
1052 for( i = 0; i < p_stream->i_decoder_specific_info_len; i++ )
1054 bits_write( &bits, 8, p_stream->p_decoder_specific_info[i] );
1057 dvbpsi_PMTESAddDescriptor( p_es,
1064 p_section = dvbpsi_GenPMTSections( &pmt );
1066 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1068 PEStoTS( p_mux->p_sout, pp_ts, p_pmt, &p_sys->pmt );
1070 dvbpsi_DeletePSISections( p_section );
1071 dvbpsi_EmptyPMT( &pmt );