1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.13 2003/02/26 12:38:17 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>
42 #elif defined( _MSC_VER ) && defined( _WIN32 ) && !defined( UNDER_CE )
50 #if defined MODULE_NAME_IS_mux_ts_dvbpsi
51 # ifdef HAVE_DVBPSI_DR_H
52 # include <dvbpsi/dvbpsi.h>
53 # include <dvbpsi/descriptor.h>
54 # include <dvbpsi/pat.h>
55 # include <dvbpsi/pmt.h>
56 # include <dvbpsi/dr.h>
57 # include <dvbpsi/psi.h>
60 # include "descriptor.h"
61 # include "tables/pat.h"
62 # include "tables/pmt.h"
63 # include "descriptors/dr.h"
68 typedef struct ts_stream_s
73 int i_continuity_counter;
75 /* to be used for carriege of DIV3 */
76 vlc_fourcc_t i_bih_codec;
77 int i_bih_width, i_bih_height;
79 /* Specific to mpeg4 in mpeg2ts */
83 int i_decoder_specific_info_len;
84 uint8_t *p_decoder_specific_info;
87 typedef struct sout_mux_s
97 int i_pid_free; // first usable pid
99 int i_pat_version_number;
102 int i_pmt_version_number;
103 ts_stream_t pmt; // Up to now only one program
105 int i_ts_packet;// To known when to put pat/mpt
112 /*****************************************************************************
113 * Exported prototypes
114 *****************************************************************************/
115 static int Open ( vlc_object_t * );
116 static void Close ( vlc_object_t * );
119 static int Capability(sout_instance_t *, int, void *, void * );
120 static int AddStream( sout_instance_t *, sout_input_t * );
121 static int DelStream( sout_instance_t *, sout_input_t * );
122 static int Mux ( sout_instance_t * );
126 /* Reserve a pid and return it */
127 static int AllocatePID( sout_mux_t *p_mux )
129 return( ++p_mux->i_pid_free );
132 static int GetPAT( sout_instance_t *p_sout, sout_buffer_t **pp_ts );
133 static int GetPMT( sout_instance_t *p_sout, sout_buffer_t **pp_ts );
135 /*****************************************************************************
137 *****************************************************************************/
139 #if defined MODULE_NAME_IS_mux_ts
140 set_description( _("TS muxer") );
141 set_capability( "sout mux", 100 );
142 add_shortcut( "ts" );
143 add_shortcut( "ts_nodvbpsi" );
144 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
145 set_description( _("TS muxer (libdvbpsi)") );
146 set_capability( "sout mux", 120 );
147 add_shortcut( "ts" );
148 add_shortcut( "ts_dvbpsi" );
150 set_callbacks( Open, Close );
153 /*****************************************************************************
155 *****************************************************************************/
156 static int Open( vlc_object_t *p_this )
158 sout_instance_t *p_sout = (sout_instance_t*)p_this;
161 msg_Info( p_sout, "Open" );
163 p_mux = malloc( sizeof( sout_mux_t ) );
165 p_sout->pf_mux_capacity = Capability;
166 p_sout->pf_mux_addstream = AddStream;
167 p_sout->pf_mux_delstream = DelStream;
168 p_sout->pf_mux = Mux;
169 p_sout->p_mux_data = (void*)p_mux;
170 p_sout->i_mux_preheader = 30; // really enough for a pes header
172 srand( (uint32_t)mdate() );
174 p_mux->i_stream_id_mpga = 0xc0;
175 p_mux->i_stream_id_a52 = 0x80;
176 p_mux->i_stream_id_mpgv = 0xe0;
178 p_mux->i_audio_bound = 0;
179 p_mux->i_video_bound = 0;
181 p_mux->i_pat_version_number = rand() % 32;
182 p_mux->pat.i_pid = 0;
183 p_mux->pat.i_continuity_counter = 0;
185 p_mux->i_pmt_version_number = rand() % 32;
186 p_mux->pmt.i_pid = 0x10;
187 p_mux->pmt.i_continuity_counter = 0;
189 p_mux->i_pid_free = 0x11;
190 p_mux->i_pcr_pid = 0x1fff;
192 p_mux->i_mpeg4_streams = 0;
197 /*****************************************************************************
199 *****************************************************************************/
201 static void Close( vlc_object_t * p_this )
203 sout_instance_t *p_sout = (sout_instance_t*)p_this;
204 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
206 msg_Info( p_sout, "Close" );
209 p_sout->p_mux_data = NULL;
212 static int Capability( sout_instance_t *p_sout, int i_query, void *p_args, void *p_answer )
216 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
217 *(vlc_bool_t*)p_answer = VLC_TRUE;
218 return( SOUT_MUX_CAP_ERR_OK );
220 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
224 static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
226 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
227 ts_stream_t *p_stream;
228 BITMAPINFOHEADER *p_bih;
231 msg_Dbg( p_sout, "adding input" );
232 p_input->p_mux_data = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
234 p_stream->i_pid = AllocatePID( p_mux );
235 if( p_mux->i_pcr_pid == 0x1fff )
237 p_mux->i_pcr_pid = p_stream->i_pid;
239 p_stream->i_continuity_counter = 0;
241 switch( p_input->input_format.i_cat )
244 switch( p_input->input_format.i_fourcc )
246 case VLC_FOURCC( 'm', 'p','g', 'v' ):
247 p_stream->i_stream_type = 0x02;
248 p_stream->i_stream_id = p_mux->i_stream_id_mpgv;
249 p_mux->i_stream_id_mpgv++;
251 case VLC_FOURCC( 'm', 'p','4', 'v' ):
252 p_stream->i_stream_type = 0x10;
253 p_stream->i_stream_id = 0xfa;
254 p_mux->i_mpeg4_streams++;
255 p_stream->i_es_id = p_stream->i_pid;
256 p_stream->i_sl_predefined = 0x01; // NULL SL header
258 /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
259 /* I didn't want to do that :P */
260 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
261 case VLC_FOURCC( 'H', '2', '6', '3' ):
262 case VLC_FOURCC( 'I', '2', '6', '3' ):
263 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
264 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
265 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
266 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
267 p_stream->i_stream_type = 0xa0; // private
268 p_stream->i_stream_id = 0xa0; // beurk
273 p_mux->i_video_bound++;
274 p_bih = (BITMAPINFOHEADER*)p_input->input_format.p_format;
277 p_stream->i_bih_codec = p_input->input_format.i_fourcc;
278 p_stream->i_bih_width = p_bih->biWidth;
279 p_stream->i_bih_height = p_bih->biHeight;
283 p_stream->i_bih_codec = 0x0;
284 p_stream->i_bih_width = 0;
285 p_stream->i_bih_height = 0;
288 if( p_bih && p_bih->biSize > sizeof( BITMAPINFOHEADER ) )
290 p_stream->i_decoder_specific_info_len =
291 p_bih->biSize - sizeof( BITMAPINFOHEADER );
292 p_stream->p_decoder_specific_info =
293 malloc( p_stream->i_decoder_specific_info_len );
294 memcpy( p_stream->p_decoder_specific_info,
296 p_stream->i_decoder_specific_info_len );
300 p_stream->p_decoder_specific_info = NULL;
301 p_stream->i_decoder_specific_info_len = 0;
305 switch( p_input->input_format.i_fourcc )
307 case VLC_FOURCC( 'a', '5','2', ' ' ):
308 case VLC_FOURCC( 'a', '5','2', 'b' ):
309 p_stream->i_stream_type = 0x81;
310 p_stream->i_stream_id = p_mux->i_stream_id_a52;
311 p_mux->i_stream_id_a52++;
313 case VLC_FOURCC( 'm', 'p','4', 'a' ):
314 p_stream->i_stream_type = 0x11;
315 p_stream->i_stream_id = 0xfa;
316 p_mux->i_mpeg4_streams++;
317 p_stream->i_es_id = p_stream->i_pid;
318 p_stream->i_sl_predefined = 0x01; // NULL SL header
320 case VLC_FOURCC( 'm', 'p','g', 'a' ):
321 p_stream->i_stream_type = 0x04;
322 p_stream->i_stream_id = p_mux->i_stream_id_mpga;
323 p_mux->i_stream_id_mpga++;
328 p_mux->i_audio_bound++;
329 p_wf = (WAVEFORMATEX*)p_input->input_format.p_format;
330 if( p_wf && p_wf->cbSize > 0 )
332 p_stream->i_decoder_specific_info_len = p_wf->cbSize;
333 p_stream->p_decoder_specific_info =
334 malloc( p_stream->i_decoder_specific_info_len );
335 memcpy( p_stream->p_decoder_specific_info,
337 p_stream->i_decoder_specific_info_len );
341 p_stream->p_decoder_specific_info = NULL;
342 p_stream->i_decoder_specific_info_len = 0;
349 p_mux->i_ts_packet = 0; // force pat/pmt recreation
350 p_mux->i_pat_version_number++; p_mux->i_pat_version_number %= 32;
351 p_mux->i_pmt_version_number++; p_mux->i_pmt_version_number %= 32;
356 static int DelStream( sout_instance_t *p_sout, sout_input_t *p_input )
358 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
359 ts_stream_t *p_stream;
361 msg_Dbg( p_sout, "removing input" );
362 p_stream = (ts_stream_t*)p_input->p_mux_data;
364 if( p_stream->p_decoder_specific_info )
366 free( p_stream->p_decoder_specific_info );
368 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
370 p_mux->i_mpeg4_streams--;
372 p_mux->i_ts_packet = 0; // force pat/pmt recreation
373 p_mux->i_pat_version_number++; p_mux->i_pat_version_number %= 32;
374 p_mux->i_pmt_version_number++; p_mux->i_pmt_version_number %= 32;
381 static int MuxGetStream( sout_instance_t *p_sout,
389 for( i = 0, i_dts = 0, i_stream = -1; i < p_sout->i_nb_inputs; i++ )
393 p_fifo = p_sout->pp_inputs[i]->p_fifo;
395 if( p_fifo->i_depth > 1 )
397 sout_buffer_t *p_buf;
399 p_buf = sout_FifoShow( p_fifo );
400 if( i_stream < 0 || p_buf->i_dts < i_dts )
402 i_dts = p_buf->i_dts;
408 return( -1 ); // wait that all fifo have at least 2 packets
414 *pi_stream = i_stream;
424 static int PEStoTS( sout_instance_t *p_sout,
425 sout_buffer_t **pp_ts, sout_buffer_t *p_pes,
426 ts_stream_t *p_stream )
436 /* get PES total size */
437 i_size = p_pes->i_size;
438 p_data = p_pes->p_buffer;
440 if( p_pes->i_dts == 0 && p_pes->i_length > 0 )
442 i_dts = 1; // XXX <french> kludge immonde </french>
446 i_dts = p_pes->i_dts;
449 for( i_first = 1, b_new_pes = 1; p_pes != NULL; )
451 int i_adaptation_field;
457 p_ts = sout_BufferNew( p_sout, 188 );
463 i_payload = 184 - ( i_first && i_dts > 0 ? 8 : 0 );
464 i_copy = __MIN( i_size, i_payload );
466 i_adaptation_field = ( ( i_first && i_dts > 0 ) ||
467 i_size < i_payload ) ? 1 : 0;
470 bits_initwrite( &bits, 188, p_ts->p_buffer );
471 bits_write( &bits, 8, 0x47 ); /* sync byte */
472 bits_write( &bits, 1, 0 ); /* transport_error_indicator */
473 bits_write( &bits, 1, b_new_pes ? 1 : 0 ); /* payload_unit_start */
475 bits_write( &bits, 1, 0 ); /* transport_priority */
476 bits_write( &bits, 13, p_stream->i_pid );
477 bits_write( &bits, 2, 0 ); /* transport_scrambling_control */
478 bits_write( &bits, 2, ( i_adaptation_field ? 0x03 : 0x01 ) );
480 bits_write( &bits, 4, /* continuity_counter */
481 p_stream->i_continuity_counter );
482 p_stream->i_continuity_counter++;
483 p_stream->i_continuity_counter %= 16;
484 if( i_adaptation_field )
489 if( i_first && i_dts > 0 )
491 i_stuffing = i_payload - i_copy;
492 bits_write( &bits, 8, 7 + i_stuffing );
493 bits_write( &bits, 8, 0x10 ); /* various flags */
494 bits_write( &bits, 33, i_dts * 9 / 100);
495 bits_write( &bits, 6, 0 );
496 bits_write( &bits, 9, 0 );
497 i_dts = 0; /* XXX set dts only for first ts packet */
501 i_stuffing = i_payload - i_copy;
502 bits_write( &bits, 8, i_stuffing - 1);
503 if( i_stuffing - 1 > 0 )
505 bits_write( &bits, 8, 0 );
511 for( i = 0; i < i_stuffing; i++ )
513 bits_write( &bits, 8, 0xff );
517 memcpy( p_ts->p_buffer + bits.i_data,
523 sout_BufferChain( pp_ts, p_ts );
529 sout_buffer_t *p_next;
531 p_next = p_pes->p_next;
532 p_pes->p_next = NULL;
533 sout_BufferDelete( p_sout, p_pes );
538 i_size = p_pes->i_size;
539 p_data = p_pes->p_buffer;
551 static void SetTSDate( sout_buffer_t *p_ts, mtime_t i_dts, mtime_t i_length )
554 sout_buffer_t *p_tmp;
557 for( p_tmp = p_ts, i_count = 0; p_tmp != NULL; p_tmp = p_tmp->p_next )
561 i_delta = i_length / i_count;
563 for( p_tmp = p_ts; p_tmp != NULL; p_tmp = p_tmp->p_next )
565 p_tmp->i_dts = i_dts;
566 p_tmp->i_length = i_delta;
572 static int Mux( sout_instance_t *p_sout )
574 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
577 sout_buffer_t *p_pat, *p_pmt, *p_ts;
581 mtime_t i_dts, i_length;
583 sout_input_t *p_input;
584 ts_stream_t *p_stream;
586 sout_buffer_t *p_data;
588 if( MuxGetStream( p_sout, &i_stream, &i_dts ) < 0 )
593 p_input = p_sout->pp_inputs[i_stream];
594 p_fifo = p_input->p_fifo;
595 p_stream = (ts_stream_t*)p_input->p_mux_data;
597 p_data = sout_FifoGet( p_fifo );
598 i_dts = p_data->i_dts;
599 i_length = p_data->i_length;
601 E_( EStoPES )( p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
602 PEStoTS( p_sout, &p_data, p_data, p_stream );
604 if( p_mux->i_ts_packet % 30 == 0 )
607 GetPAT( p_sout, &p_pat );
608 GetPMT( p_sout, &p_pmt );
611 sout_BufferChain( &p_ts, p_pmt );
612 sout_BufferChain( &p_ts, p_data );
619 p_mux->i_ts_packet++;
620 SetTSDate( p_ts, i_dts, i_length );
622 sout_AccessOutWrite( p_sout->p_access, p_ts );
629 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
631 static uint32_t CRC32[256] =
633 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
634 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
635 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
636 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
637 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
638 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
639 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
640 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
641 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
642 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
643 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
644 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
645 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
646 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
647 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
648 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
649 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
650 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
651 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
652 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
653 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
654 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
655 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
656 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
657 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
658 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
659 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
660 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
661 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
662 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
663 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
664 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
665 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
666 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
667 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
668 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
669 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
670 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
671 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
672 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
673 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
674 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
675 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
676 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
677 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
678 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
679 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
680 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
681 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
682 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
683 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
684 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
685 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
686 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
687 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
688 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
689 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
690 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
691 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
692 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
693 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
694 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
695 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
696 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
699 uint32_t i_crc = 0xffffffff;
701 /* Calculate the CRC */
704 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
712 #if defined MODULE_NAME_IS_mux_ts
713 static int GetPAT( sout_instance_t *p_sout,
714 sout_buffer_t **pp_ts )
716 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
717 sout_buffer_t *p_pat;
720 p_pat = sout_BufferNew( p_sout, 1024 );
726 bits_initwrite( &bits, 1024, p_pat->p_buffer );
728 bits_write( &bits, 8, 0 ); // pointer
729 bits_write( &bits, 8, 0x00 ); // table id
730 bits_write( &bits, 1, 1 ); // section_syntax_indicator
731 bits_write( &bits, 1, 0 ); // 0
732 bits_write( &bits, 2, 0x03 ); // reserved FIXME
733 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
734 bits_write( &bits, 16, 0x01 ); // FIXME stream id
735 bits_write( &bits, 2, 0x03 ); // FIXME
736 bits_write( &bits, 5, p_mux->i_pat_version_number );
737 bits_write( &bits, 1, 1 ); // current_next_indicator
738 bits_write( &bits, 8, 0 ); // section number
739 bits_write( &bits, 8, 0 ); // last section number
741 bits_write( &bits, 16, 1 ); // program number
742 bits_write( &bits, 3, 0x07 ); // reserved
743 bits_write( &bits, 13, p_mux->pmt.i_pid ); // program map pid
745 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
747 p_pat->i_size = bits.i_data;
749 return( PEStoTS( p_sout, pp_ts, p_pat, &p_mux->pat ) );
752 static int GetPMT( sout_instance_t *p_sout,
753 sout_buffer_t **pp_ts )
755 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
756 sout_buffer_t *p_pmt;
760 p_pmt = sout_BufferNew( p_sout, 1024 );
766 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
768 bits_write( &bits, 8, 0 ); // pointer
769 bits_write( &bits, 8, 0x02 ); // table id
770 bits_write( &bits, 1, 1 ); // section_syntax_indicator
771 bits_write( &bits, 1, 0 ); // 0
772 bits_write( &bits, 2, 0 ); // reserved FIXME
773 bits_write( &bits, 12, 13 + 5 * p_sout->i_nb_inputs );
774 bits_write( &bits, 16, 1 ); // FIXME program number
775 bits_write( &bits, 2, 0 ); // FIXME
776 bits_write( &bits, 5, p_mux->i_pmt_version_number );
777 bits_write( &bits, 1, 0 ); // current_next_indicator
778 bits_write( &bits, 8, 0 ); // section number
779 bits_write( &bits, 8, 0 ); // last section number
781 bits_write( &bits, 3, 0 ); // reserved
783 bits_write( &bits, 13, p_mux->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
784 bits_write( &bits, 4, 0 ); // reserved FIXME
786 bits_write( &bits, 12, 0 ); // program info len FIXME
788 for( i_stream = 0; i_stream < p_sout->i_nb_inputs; i_stream++ )
790 ts_stream_t *p_stream;
792 p_stream = (ts_stream_t*)p_sout->pp_inputs[i_stream]->p_mux_data;
794 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
795 bits_write( &bits, 3, 0 ); // reserved
796 bits_write( &bits, 13, p_stream->i_pid ); // es pid
797 bits_write( &bits, 4, 0 ); //reserved
798 bits_write( &bits, 12, 0 ); // es info len FIXME
801 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
803 p_pmt->i_size = bits.i_data;
805 return( PEStoTS( p_sout, pp_ts, p_pmt, &p_mux->pmt ) );
808 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
810 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
811 dvbpsi_psi_section_t* p_section )
813 sout_buffer_t *p_psi, *p_first = NULL;
820 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
821 ( p_section->b_syntax_indicator ? 4 : 0 );
823 p_psi = sout_BufferNew( p_sout, i_size + 1 );
827 p_psi->i_size = i_size + 1;
829 p_psi->p_buffer[0] = 0; // pointer
830 memcpy( p_psi->p_buffer + 1,
834 sout_BufferChain( &p_first, p_psi );
836 p_section = p_section->p_next;
842 static int GetPAT( sout_instance_t *p_sout,
843 sout_buffer_t **pp_ts )
845 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
846 sout_buffer_t *p_pat;
848 dvbpsi_psi_section_t *p_section;
850 dvbpsi_InitPAT( &pat,
852 p_mux->i_pat_version_number,
853 0); // b_current_next
854 /* add all program (only one) */
855 dvbpsi_PATAddProgram( &pat,
857 p_mux->pmt.i_pid ); // i_pid
859 p_section = dvbpsi_GenPATSections( &pat,
860 0 ); // max program per section
862 p_pat = WritePSISection( p_sout, p_section );
864 PEStoTS( p_sout, pp_ts, p_pat, &p_mux->pat );
866 dvbpsi_DeletePSISections( p_section );
867 dvbpsi_EmptyPAT( &pat );
871 static uint32_t GetDescriptorLength24b( int i_length )
873 uint32_t i_l1, i_l2, i_l3;
875 i_l1 = i_length&0x7f;
876 i_l2 = ( i_length >> 7 )&0x7f;
877 i_l3 = ( i_length >> 14 )&0x7f;
879 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
882 static int GetPMT( sout_instance_t *p_sout,
883 sout_buffer_t **pp_ts )
885 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
886 sout_buffer_t *p_pmt;
889 dvbpsi_pmt_es_t* p_es;
890 dvbpsi_psi_section_t *p_section;
894 dvbpsi_InitPMT( &pmt,
895 0x01, // program number
896 p_mux->i_pmt_version_number,
900 if( p_mux->i_mpeg4_streams > 0 )
904 bits_buffer_t bits_fix_IOD;
906 bits_initwrite( &bits, 4096, iod );
908 bits_write( &bits, 8, 0x01 );
909 // InitialObjectDescriptor
911 bits_write( &bits, 8, 0x02 ); // tag
912 bits_fix_IOD = bits; // save states to fix length later
913 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
914 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
915 bits_write( &bits, 1, 0x00 ); // URL Flag
916 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
917 bits_write( &bits, 4, 0x0f ); // reserved
918 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
919 bits_write( &bits, 8, 0xff ); // sceneProfile
920 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
921 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
922 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
923 for( i_stream = 0; i_stream < p_sout->i_nb_inputs; i_stream++ )
925 ts_stream_t *p_stream;
926 p_stream = (ts_stream_t*)p_sout->pp_inputs[i_stream]->p_mux_data;
928 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
930 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
933 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
934 bits_fix_ESDescr = bits;
935 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
936 bits_write( &bits, 16, p_stream->i_es_id );
937 bits_write( &bits, 1, 0x00 ); // streamDependency
938 bits_write( &bits, 1, 0x00 ); // URL Flag
939 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
940 bits_write( &bits, 5, 0x1f ); // streamPriority
942 // DecoderConfigDesciptor
944 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
945 bits_fix_Decoder = bits;
946 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
947 if( p_stream->i_stream_type == 0x10 )
949 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
950 bits_write( &bits, 6, 0x04 ); // VisualStream
952 else if( p_stream->i_stream_type == 0x11 )
954 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
955 bits_write( &bits, 6, 0x05 ); // AudioStream
959 bits_write( &bits, 8, 0x00 );
960 bits_write( &bits, 6, 0x00 );
962 msg_Err( p_sout,"Unsupported stream_type => broken IOD");
964 bits_write( &bits, 1, 0x00 ); // UpStream
965 bits_write( &bits, 1, 0x01 ); // reserved
966 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
967 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
968 bits_write( &bits, 32, 0 ); // avgBitrate
970 if( p_stream->i_decoder_specific_info_len > 0 )
973 // DecoderSpecificInfo
975 bits_write( &bits, 8, 0x05 ); // tag
976 bits_write( &bits, 24,
977 GetDescriptorLength24b( p_stream->i_decoder_specific_info_len ) );
978 for( i = 0; i < p_stream->i_decoder_specific_info_len; i++ )
980 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
983 /* fix Decoder length */
984 bits_write( &bits_fix_Decoder, 24,
985 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
987 // SLConfigDescriptor
988 switch( p_stream->i_sl_predefined )
993 bits_write( &bits, 8, 0x06 ); // tag
994 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
995 bits_write( &bits, 8, 0x01 ); // predefined
996 bits_write( &bits, 1, 0 ); // durationFlag
997 bits_write( &bits, 32, 0 ); // OCRResolution
998 bits_write( &bits, 8, 0 ); // OCRLength
999 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1000 bits_align( &bits );
1003 msg_Err( p_sout,"Unsupported SL profile => broken IOD");
1006 /* fix ESDescr length */
1007 bits_write( &bits_fix_ESDescr, 24,
1008 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1011 bits_align( &bits );
1012 /* fix IOD length */
1013 bits_write( &bits_fix_IOD, 24,
1014 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1015 dvbpsi_PMTAddDescriptor( &pmt,
1021 for( i_stream = 0; i_stream < p_sout->i_nb_inputs; i_stream++ )
1023 ts_stream_t *p_stream;
1025 p_stream = (ts_stream_t*)p_sout->pp_inputs[i_stream]->p_mux_data;
1027 p_es = dvbpsi_PMTAddES( &pmt,
1028 p_stream->i_stream_type,
1030 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1036 bits_initwrite( &bits, 512, data );
1037 bits_write( &bits, 16, p_stream->i_es_id );
1039 dvbpsi_PMTESAddDescriptor( p_es,
1044 else if( p_stream->i_stream_id == 0xa0 )
1049 /* private DIV3 descripor */
1050 bits_initwrite( &bits, 512, data );
1051 bits_write( &bits, 32, p_stream->i_bih_codec );
1052 bits_write( &bits, 16, p_stream->i_bih_width );
1053 bits_write( &bits, 16, p_stream->i_bih_height );
1054 bits_write( &bits, 16, p_stream->i_decoder_specific_info_len );
1055 if( p_stream->i_decoder_specific_info_len > 0 )
1058 for( i = 0; i < p_stream->i_decoder_specific_info_len; i++ )
1060 bits_write( &bits, 8, p_stream->p_decoder_specific_info[i] );
1063 dvbpsi_PMTESAddDescriptor( p_es,
1070 p_section = dvbpsi_GenPMTSections( &pmt );
1072 p_pmt = WritePSISection( p_sout, p_section );
1074 PEStoTS( p_sout, pp_ts, p_pmt, &p_mux->pmt );
1076 dvbpsi_DeletePSISections( p_section );
1077 dvbpsi_EmptyPMT( &pmt );