1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ts.c,v 1.34 2003/11/17 11:25:54 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>
39 #if defined MODULE_NAME_IS_mux_ts_dvbpsi
40 # ifdef HAVE_DVBPSI_DR_H
41 # include <dvbpsi/dvbpsi.h>
42 # include <dvbpsi/descriptor.h>
43 # include <dvbpsi/pat.h>
44 # include <dvbpsi/pmt.h>
45 # include <dvbpsi/dr.h>
46 # include <dvbpsi/psi.h>
49 # include "descriptor.h"
50 # include "tables/pat.h"
51 # include "tables/pmt.h"
52 # include "descriptors/dr.h"
59 * - check PCR frequency requirement
61 * - check PCR/PCR "soft"
62 * - check if "registration" descriptor : "AC-3" should be a program
63 * descriptor or an es one. (xine want an es one)
65 * - remove creation of PAT/PMT without dvbpsi
68 * - subtitle support is far from perfect. I expect some subtitles drop
69 * if they arrive a bit late
70 * (We cannot rely on the fact that the fifo should be full)
72 /*****************************************************************************
74 *****************************************************************************/
75 static int Open ( vlc_object_t * );
76 static void Close ( vlc_object_t * );
79 #if defined MODULE_NAME_IS_mux_ts
80 set_description( _("TS muxer") );
81 set_capability( "sout mux", 100 );
83 add_shortcut( "ts_nodvbpsi" );
84 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
85 set_description( _("TS muxer (libdvbpsi)") );
86 set_capability( "sout mux", 120 );
88 add_shortcut( "ts_dvbpsi" );
90 set_callbacks( Open, Close );
93 /*****************************************************************************
95 *****************************************************************************/
96 static int Capability(sout_mux_t *, int, void *, void * );
97 static int AddStream( sout_mux_t *, sout_input_t * );
98 static int DelStream( sout_mux_t *, sout_input_t * );
99 static int Mux ( sout_mux_t * );
101 /*****************************************************************************
103 *****************************************************************************/
104 #define SOUT_BUFFER_FLAGS_PRIVATE_PCR ( 1 << SOUT_BUFFER_FLAGS_PRIVATE_SHIFT )
108 sout_buffer_t *p_first;
109 sout_buffer_t **pp_last;
110 } sout_buffer_chain_t;
112 static inline void BufferChainInit ( sout_buffer_chain_t *c )
116 c->pp_last = &c->p_first;
118 static inline void BufferChainAppend( sout_buffer_chain_t *c, sout_buffer_t *b )
128 c->pp_last = &b->p_next;
130 static inline sout_buffer_t *BufferChainGet( sout_buffer_chain_t *c )
132 sout_buffer_t *b = c->p_first;
137 c->p_first = b->p_next;
139 if( c->p_first == NULL )
141 c->pp_last = &c->p_first;
148 static inline void BufferChainClean( sout_instance_t *p_sout, sout_buffer_chain_t *c )
152 while( ( b = BufferChainGet( c ) ) )
154 sout_BufferDelete( p_sout, b );
156 BufferChainInit( c );
159 typedef struct ts_stream_s
164 int i_continuity_counter;
166 /* to be used for carriege of DIV3 */
167 vlc_fourcc_t i_bih_codec;
168 int i_bih_width, i_bih_height;
170 /* Specific to mpeg4 in mpeg2ts */
173 int i_decoder_specific_info;
174 uint8_t *p_decoder_specific_info;
176 sout_buffer_chain_t chain_pes;
178 mtime_t i_pes_length;
183 struct sout_mux_sys_t
186 sout_input_t *p_pcr_input;
188 int i_stream_id_mpga;
189 int i_stream_id_mpgv;
196 int i_pid_free; // first usable pid
198 int i_pat_version_number;
201 int i_pmt_version_number;
202 ts_stream_t pmt; // Up to now only one program
206 int i_null_continuity_counter; /* Needed ? */
208 /* for TS building */
209 int64_t i_bitrate_min;
210 int64_t i_bitrate_max;
212 int64_t i_caching_delay;
215 mtime_t i_pcr; /* last PCR emited */
219 /* Reserve a pid and return it */
220 static int AllocatePID( sout_mux_sys_t *p_sys, int i_cat )
223 if ( i_cat == VIDEO_ES && p_sys->i_pid_video )
225 i_pid = p_sys->i_pid_video;
226 p_sys->i_pid_video = 0;
228 else if ( i_cat == AUDIO_ES && p_sys->i_pid_audio )
230 i_pid = p_sys->i_pid_audio;
231 p_sys->i_pid_audio = 0;
235 i_pid = ++p_sys->i_pid_free;
240 static void GetPAT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
241 static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
243 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr );
244 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts );
246 static void PEStoTS ( sout_instance_t *, sout_buffer_chain_t *, sout_buffer_t *, ts_stream_t * );
248 /*****************************************************************************
250 *****************************************************************************/
251 static int Open( vlc_object_t *p_this )
253 sout_mux_t *p_mux =(sout_mux_t*)p_this;
254 sout_mux_sys_t *p_sys;
257 msg_Dbg( p_mux, "Open" );
259 p_sys = malloc( sizeof( sout_mux_sys_t ) );
261 p_mux->pf_capacity = Capability;
262 p_mux->pf_addstream = AddStream;
263 p_mux->pf_delstream = DelStream;
265 p_mux->p_sys = p_sys;
266 p_mux->i_preheader = 30; // really enough for a pes header
268 srand( (uint32_t)mdate() );
270 p_sys->i_stream_id_mpga = 0xc0;
271 p_sys->i_stream_id_mpgv = 0xe0;
273 p_sys->i_audio_bound = 0;
274 p_sys->i_video_bound = 0;
276 p_sys->i_pat_version_number = rand() % 32;
277 p_sys->pat.i_pid = 0;
278 p_sys->pat.i_continuity_counter = 0;
280 p_sys->i_pmt_version_number = rand() % 32;
281 p_sys->pmt.i_pid = 0x42;
282 p_sys->pmt.i_continuity_counter = 0;
284 p_sys->i_pid_free = 0x43;
286 p_sys->i_pid_video = 0;
287 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) )
289 p_sys->i_pid_video = strtol( val, NULL, 0 );
290 if ( p_sys->i_pid_video > p_sys->i_pid_free )
292 p_sys->i_pid_free = p_sys->i_pid_video + 1;
295 p_sys->i_pid_audio = 0;
296 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) )
298 p_sys->i_pid_audio = strtol( val, NULL, 0 );
299 if ( p_sys->i_pid_audio > p_sys->i_pid_free )
301 p_sys->i_pid_free = p_sys->i_pid_audio + 1;
305 p_sys->i_pcr_pid = 0x1fff;
306 p_sys->p_pcr_input = NULL;
308 p_sys->i_mpeg4_streams = 0;
310 p_sys->i_null_continuity_counter = 0;
312 /* Allow to create constrained stream */
313 p_sys->i_bitrate_min = 0;
314 p_sys->i_bitrate_max = 0;
315 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmin" ) ) )
317 p_sys->i_bitrate_min = atoll( val );
319 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmax" ) ) )
321 p_sys->i_bitrate_max = atoll( val );
323 if( p_sys->i_bitrate_min > 0 && p_sys->i_bitrate_max > 0 &&
324 p_sys->i_bitrate_min > p_sys->i_bitrate_max )
326 msg_Err( p_mux, "incompatible minimum and maximum bitrate, "
327 "disabling bitrate control" );
328 p_sys->i_bitrate_min = 0;
329 p_sys->i_bitrate_max = 0;
331 if( p_sys->i_bitrate_min > 0 || p_sys->i_bitrate_max > 0 )
333 msg_Err( p_mux, "bmin and bmax no more supported (if you need them report it)" );
336 p_sys->i_caching_delay = 200000;
337 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "caching" ) ) )
339 p_sys->i_caching_delay = (int64_t)atoi( val ) * 1000;
340 if( p_sys->i_caching_delay <= 0 )
343 "invalid caching ("I64Fd"ms) reseting to 200ms",
344 p_sys->i_caching_delay / 1000 );
345 p_sys->i_caching_delay = 200000;
348 p_sys->i_pcr_delay = 30000;
349 if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr" ) ) )
351 p_sys->i_pcr_delay = (int64_t)atoi( val ) * 1000;
352 if( p_sys->i_pcr_delay <= 0 ||
353 p_sys->i_pcr_delay >= p_sys->i_caching_delay )
356 "invalid pcr delay ("I64Fd"ms) reseting to 30ms",
357 p_sys->i_pcr_delay / 1000 );
358 p_sys->i_pcr_delay = 30000;
362 msg_Dbg( p_mux, "caching="I64Fd" pcr="I64Fd,
363 p_sys->i_caching_delay, p_sys->i_pcr_delay );
365 /* for TS generation */
370 /*****************************************************************************
372 *****************************************************************************/
373 static void Close( vlc_object_t * p_this )
375 sout_mux_t *p_mux = (sout_mux_t*)p_this;
376 sout_mux_sys_t *p_sys = p_mux->p_sys;
378 msg_Dbg( p_mux, "Close" );
383 /*****************************************************************************
385 *****************************************************************************/
386 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
390 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
391 *(vlc_bool_t*)p_answer = VLC_TRUE;
392 return( SOUT_MUX_CAP_ERR_OK );
394 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
398 /*****************************************************************************
399 * AddStream: called for each stream addition
400 *****************************************************************************/
401 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
403 sout_mux_sys_t *p_sys = p_mux->p_sys;
404 ts_stream_t *p_stream;
406 msg_Dbg( p_mux, "adding input codec=%4.4s", (char*)&p_input->p_fmt->i_fourcc );
408 p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
410 /* Init this new stream */
411 p_stream->i_pid = AllocatePID( p_sys, p_input->p_fmt->i_cat );
412 p_stream->i_continuity_counter = 0;
413 p_stream->i_decoder_specific_info = 0;
414 p_stream->p_decoder_specific_info = NULL;
416 /* All others fields depand on codec */
417 switch( p_input->p_fmt->i_cat )
420 switch( p_input->p_fmt->i_fourcc )
422 case VLC_FOURCC( 'm', 'p','g', 'v' ):
423 /* TODO: do we need to check MPEG-I/II ? */
424 p_stream->i_stream_type = 0x02;
425 p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
426 p_sys->i_stream_id_mpgv++;
428 case VLC_FOURCC( 'm', 'p','4', 'v' ):
429 p_stream->i_stream_type = 0x10;
430 p_stream->i_stream_id = 0xfa;
431 p_sys->i_mpeg4_streams++;
432 p_stream->i_es_id = p_stream->i_pid;
434 /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
435 /* I didn't want to do that :P */
436 case VLC_FOURCC( 'H', '2', '6', '3' ):
437 case VLC_FOURCC( 'I', '2', '6', '3' ):
438 case VLC_FOURCC( 'W', 'M', 'V', '2' ):
439 case VLC_FOURCC( 'W', 'M', 'V', '1' ):
440 case VLC_FOURCC( 'D', 'I', 'V', '3' ):
441 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
442 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
443 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
444 p_stream->i_stream_type = 0xa0; // private
445 p_stream->i_stream_id = 0xa0; // beurk
446 p_stream->i_bih_codec = p_input->p_fmt->i_fourcc;
447 p_stream->i_bih_width = p_input->p_fmt->i_width;
448 p_stream->i_bih_height = p_input->p_fmt->i_height;
454 p_sys->i_video_bound++;
458 switch( p_input->p_fmt->i_fourcc )
460 case VLC_FOURCC( 'm', 'p','g', 'a' ):
461 p_stream->i_stream_type = p_input->p_fmt->i_sample_rate >= 32000 ? 0x03 : 0x04;
462 p_stream->i_stream_id = p_sys->i_stream_id_mpga;
463 p_sys->i_stream_id_mpga++;
465 case VLC_FOURCC( 'a', '5','2', ' ' ):
466 p_stream->i_stream_type = 0x81;
467 p_stream->i_stream_id = 0xbd;
469 case VLC_FOURCC( 'm', 'p','4', 'a' ):
470 p_stream->i_stream_type = 0x11;
471 p_stream->i_stream_id = 0xfa;
472 p_sys->i_mpeg4_streams++;
473 p_stream->i_es_id = p_stream->i_pid;
479 p_sys->i_audio_bound++;
483 switch( p_input->p_fmt->i_fourcc )
485 case VLC_FOURCC( 's', 'p','u', ' ' ):
486 p_stream->i_stream_type = 0x82;
487 p_stream->i_stream_id = 0x82;
500 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
501 p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra_data;
502 if( p_stream->i_decoder_specific_info > 0 )
504 p_stream->p_decoder_specific_info =
505 malloc( p_stream->i_decoder_specific_info );
506 memcpy( p_stream->p_decoder_specific_info,
507 p_input->p_fmt->p_extra_data,
508 p_input->p_fmt->i_extra_data );
512 BufferChainInit( &p_stream->chain_pes );
513 p_stream->i_pes_dts = 0;
514 p_stream->i_pes_length = 0;
515 p_stream->i_pes_used = 0;
517 /* We only change PMT version (PAT isn't changed) */
518 p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;
521 if( p_input->p_fmt->i_cat != SPU_ES &&
522 ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
524 if( p_sys->p_pcr_input )
526 /* There was already a PCR stream, so clean context */
529 p_sys->i_pcr_pid = p_stream->i_pid;
530 p_sys->p_pcr_input = p_input;
536 /*****************************************************************************
537 * DelStream: called before a stream deletion
538 *****************************************************************************/
539 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
541 sout_mux_sys_t *p_sys = p_mux->p_sys;
542 ts_stream_t *p_stream;
544 msg_Dbg( p_mux, "removing input" );
545 p_stream = (ts_stream_t*)p_input->p_sys;
547 if( p_sys->i_pcr_pid == p_stream->i_pid )
551 /* Find a new pcr stream (Prefer Video Stream) */
552 p_sys->i_pcr_pid = 0x1fff;
553 p_sys->p_pcr_input = NULL;
554 for( i = 0; i < p_mux->i_nb_inputs; i++ )
556 if( p_mux->pp_inputs[i] == p_input )
561 if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
564 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
565 p_sys->p_pcr_input= p_mux->pp_inputs[i];
568 else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
569 p_sys->i_pcr_pid == 0x1fff )
572 ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
573 p_sys->p_pcr_input= p_mux->pp_inputs[i];
576 if( p_sys->p_pcr_input )
578 /* Empty TS buffer */
583 /* Empty all data in chain_pes */
584 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
586 if( p_stream->p_decoder_specific_info )
588 free( p_stream->p_decoder_specific_info );
590 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
592 p_sys->i_mpeg4_streams--;
596 /* We only change PMT version (PAT isn't changed) */
597 p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
602 /*****************************************************************************
603 * Mux: Call each time there is new data for at least one stream
604 *****************************************************************************
606 *****************************************************************************/
607 static int Mux( sout_mux_t *p_mux )
609 sout_mux_sys_t *p_sys = p_mux->p_sys;
610 ts_stream_t *p_pcr_stream;
612 if( p_sys->i_pcr_pid == 0x1fff )
614 msg_Dbg( p_mux, "waiting PCR streams" );
618 p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
622 sout_buffer_chain_t chain_ts;
626 mtime_t i_pcr_length;
629 /* 1: get enough PES packet for all input */
632 vlc_bool_t b_ok = VLC_TRUE;
633 sout_buffer_t *p_data;
635 /* Accumulate enough data in the pcr stream (>i_caching_delay) */
636 /* Accumulate enough data in all other stream ( >= length of pcr) */
637 for( i = 0; i < p_mux->i_nb_inputs; i++ )
639 sout_input_t *p_input = p_mux->pp_inputs[i];
640 ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;
642 if( p_stream->i_pes_length <= p_sys->i_caching_delay ||
643 p_stream->i_pes_dts + p_stream->i_pes_length < p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
646 if( p_input->p_fifo->i_depth <= 1 )
648 if( p_input->p_fmt->i_cat == AUDIO_ES ||
649 p_input->p_fmt->i_cat == VIDEO_ES )
651 /* We need more data */
654 else if( p_input->p_fifo->i_depth <= 0 )
656 /* spu, only one packet is needed */
662 p_data = sout_FifoGet( p_input->p_fifo );
664 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 ) ||
665 p_data->i_dts < p_stream->i_pes_dts ||
666 ( p_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > p_stream->i_pes_dts + p_stream->i_pes_length ) )
668 msg_Warn( p_mux, "packet with too strange dts (dts=%lld,old=%lld,pcr=%lld)",
671 p_pcr_stream->i_pes_dts );
672 sout_BufferDelete( p_mux->p_sout, p_data );
674 BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
675 p_stream->i_pes_dts = 0;
676 p_stream->i_pes_used = 0;
677 p_stream->i_pes_length = 0;
679 BufferChainClean( p_mux->p_sout, &p_pcr_stream->chain_pes );
680 p_pcr_stream->i_pes_dts = 0;
681 p_pcr_stream->i_pes_used = 0;
682 p_pcr_stream->i_pes_length = 0;
687 p_stream->i_pes_length += p_data->i_length;
688 if( p_stream->i_pes_dts == 0 )
690 p_stream->i_pes_dts = p_data->i_dts;
694 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1 );
696 BufferChainAppend( &p_stream->chain_pes, p_data );
708 i_pcr_dts = p_pcr_stream->i_pes_dts;
709 i_pcr_length = p_pcr_stream->i_pes_length;
711 /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */
712 /* 2: calculate non accurate total size of muxed ts */
714 for( i = 0; i < p_mux->i_nb_inputs; i++ )
716 ts_stream_t *p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
717 sout_buffer_t *p_pes;
719 /* False for pcr stream but it will be eough to do PCR algo */
720 for( p_pes = p_stream->chain_pes.p_first; p_pes != NULL; p_pes = p_pes->p_next )
722 int i_size = p_pes->i_size;
723 if( p_pes->i_dts + p_pes->i_length > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
725 mtime_t i_frag = p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length - p_pes->i_dts;
731 i_size = p_pes->i_size * i_frag / p_pes->i_length;
733 i_packet_count += ( i_size + 183 ) / 184;
736 /* add overhead for PCR (not really exact) */
737 i_packet_count += ( 8 * i_pcr_length / p_sys->i_pcr_delay + 175 ) / 176;
740 /* 3: mux PES into TS */
741 BufferChainInit( &chain_ts );
742 /* append PAT/PMT -> FIXME with big pcr delay it won't have enough pat/pmt */
743 GetPAT( p_mux, &chain_ts);
744 GetPMT( p_mux, &chain_ts );
746 i_packet_count += chain_ts.i_depth;
747 /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */
753 ts_stream_t *p_stream;
757 /* Select stream (lowest dts)*/
758 for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
760 p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
762 if( p_stream->i_pes_dts == 0 )
767 if( i_stream == -1 ||
768 p_stream->i_pes_dts < i_dts )
771 i_dts = p_stream->i_pes_dts;
778 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
780 /* do we need to issue pcr */
782 if( p_stream == p_pcr_stream &&
783 i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count >= p_sys->i_pcr + p_sys->i_pcr_delay )
786 p_sys->i_pcr = i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count;
789 /* Build the TS packet */
790 p_ts = TSNew( p_mux, p_stream, b_pcr );
794 BufferChainAppend( &chain_ts, p_ts );
797 /* 4: date and send */
798 i_packet_count = chain_ts.i_depth;
799 /* msg_Dbg( p_mux, "real pck=%d", i_packet_count ); */
800 for( i = 0; i < i_packet_count; i++ )
802 sout_buffer_t *p_ts = BufferChainGet( &chain_ts );
804 p_ts->i_dts = i_pcr_dts + i_pcr_length * i / i_packet_count;
805 p_ts->i_length = i_pcr_length / i_packet_count;
807 if( p_ts->i_flags&SOUT_BUFFER_FLAGS_PRIVATE_PCR )
809 /* msg_Dbg( p_mux, "pcr=%lld ms", p_ts->i_dts / 1000 ); */
810 TSSetPCR( p_ts, p_ts->i_dts );
814 p_ts->i_dts += 3*p_sys->i_caching_delay/2;
816 sout_AccessOutWrite( p_mux->p_access, p_ts );
821 static sout_buffer_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr )
823 sout_buffer_t *p_pes = p_stream->chain_pes.p_first;
826 vlc_bool_t b_new_pes = VLC_FALSE;
827 vlc_bool_t b_adaptation_field = VLC_FALSE;
829 int i_payload_max = 184 - ( b_pcr ? 8 : 0 );
832 if( p_stream->i_pes_used <= 0 )
834 b_new_pes = VLC_TRUE;
836 i_payload = __MIN( (int)p_pes->i_size - p_stream->i_pes_used, i_payload_max );
838 if( b_pcr || i_payload < i_payload_max )
840 b_adaptation_field = VLC_TRUE;
843 p_ts = sout_BufferNew( p_mux->p_sout, 188 );
845 p_ts->p_buffer[0] = 0x47;
846 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|( ( p_stream->i_pid >> 8 )&0x1f );
847 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
848 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|p_stream->i_continuity_counter;
850 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
852 if( b_adaptation_field )
858 int i_stuffing = i_payload_max - i_payload;
860 p_ts->i_flags |= SOUT_BUFFER_FLAGS_PRIVATE_PCR;
862 p_ts->p_buffer[4] = 7 + i_stuffing;
863 p_ts->p_buffer[5] = 0x10; /* flags */
864 p_ts->p_buffer[6] = ( 0 )&0xff;
865 p_ts->p_buffer[7] = ( 0 )&0xff;
866 p_ts->p_buffer[8] = ( 0 )&0xff;
867 p_ts->p_buffer[9] = ( 0 )&0xff;
868 p_ts->p_buffer[10]= ( 0 )&0x80;
869 p_ts->p_buffer[11]= 0;
871 for( i = 12; i < 12 + i_stuffing; i++ )
873 p_ts->p_buffer[i] = 0xff;
878 int i_stuffing = i_payload_max - i_payload;
880 p_ts->p_buffer[4] = i_stuffing - 1;
883 p_ts->p_buffer[5] = 0x00;
884 for( i = 6; i < 6 + i_stuffing - 2; i++ )
886 p_ts->p_buffer[i] = 0xff;
893 memcpy( &p_ts->p_buffer[188 - i_payload], &p_pes->p_buffer[p_stream->i_pes_used], i_payload );
895 p_stream->i_pes_used += i_payload;
896 p_stream->i_pes_dts = p_pes->i_dts + p_pes->i_length * p_stream->i_pes_used / p_pes->i_size;
897 p_stream->i_pes_length -= p_pes->i_length * i_payload / p_pes->i_size;
899 if( p_stream->i_pes_used >= (int)p_pes->i_size )
901 p_pes = BufferChainGet( &p_stream->chain_pes );
902 sout_BufferDelete( p_mux->p_sout, p_pes );
904 p_pes = p_stream->chain_pes.p_first;
907 p_stream->i_pes_dts = p_pes->i_dts;
908 p_stream->i_pes_length = 0;
911 p_stream->i_pes_length += p_pes->i_length;
913 p_pes = p_pes->p_next;
918 p_stream->i_pes_dts = 0;
919 p_stream->i_pes_length = 0;
921 p_stream->i_pes_used = 0;
928 static void TSSetPCR( sout_buffer_t *p_ts, mtime_t i_dts )
930 mtime_t i_pcr = 9 * p_ts->i_dts / 100;
932 p_ts->p_buffer[6] = ( i_pcr >> 25 )&0xff;
933 p_ts->p_buffer[7] = ( i_pcr >> 17 )&0xff;
934 p_ts->p_buffer[8] = ( i_pcr >> 9 )&0xff;
935 p_ts->p_buffer[9] = ( i_pcr >> 1 )&0xff;
936 p_ts->p_buffer[10]|= ( i_pcr << 7 )&0x80;
940 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 )
942 sout_mux_sys_t *p_sys = p_mux->p_sys;
943 sout_buffer_chain_t s = *c;
946 int i_packets_min = 0;
947 int i_packets_max = 0;
954 i_packets = c->i_depth;
955 i_packets_min = ( (int64_t)i_bitrate_min * i_length / 8 / 1000000 + 187 ) / 188;
956 i_packets_max = ( (int64_t)i_bitrate_max * i_length / 8 / 1000000 + 187 ) / 188;
958 if( i_packets < i_packets_min && i_packets_min > 0 )
961 int i_div = ( i_packets_min - i_packets ) / i_packets;
962 int i_mod = ( i_packets_min - i_packets ) % i_packets;
965 /* We need to pad with null packets (pid=0x1fff)
966 * We try to melt null packets with true packets */
968 "packets=%d but min=%d -> adding %d packets of padding",
969 i_packets, i_packets_min, i_packets_min - i_packets );
971 BufferChainInit( c );
972 while( ( p_pk = BufferChainGet( &s ) ) )
976 BufferChainAppend( c, p_pk );
978 i_null = i_div + ( i_rest + i_mod ) / i_packets;
980 for( i = 0; i < i_null; i++ )
982 sout_buffer_t *p_null;
984 p_null = sout_BufferNew( p_mux->p_sout, 188 );
985 p_null->p_buffer[0] = 0x47;
986 p_null->p_buffer[1] = 0x1f;
987 p_null->p_buffer[2] = 0xff;
988 p_null->p_buffer[3] = 0x10 | p_sys->i_null_continuity_counter;
989 memset( &p_null->p_buffer[4], 0, 184 );
990 p_sys->i_null_continuity_counter =
991 ( p_sys->i_null_continuity_counter + 1 ) % 16;
993 BufferChainAppend( c, p_null );
996 i_rest = ( i_rest + i_mod ) % i_packets;
999 else if( i_packets > i_packets_max && i_packets_max > 0 )
1001 sout_buffer_t *p_pk;
1004 /* Arg, we need to drop packets, I don't do something clever (like
1005 * dropping complete pid, b frames, ... ), I just get the right amount
1006 * of packets and discard the others */
1008 "packets=%d but max=%d -> removing %d packets -> stream broken",
1009 i_packets, i_packets_max, i_packets - i_packets_max );
1011 BufferChainInit( c );
1012 for( i = 0; i < i_packets_max; i++ )
1014 BufferChainAppend( c, BufferChainGet( &s ) );
1017 while( ( p_pk = BufferChainGet( &s ) ) )
1019 sout_BufferDelete( p_mux->p_sout, p_pk );
1025 static void PEStoTS( sout_instance_t *p_sout,
1026 sout_buffer_chain_t *c, sout_buffer_t *p_pes,
1027 ts_stream_t *p_stream )
1033 /* get PES total size */
1034 i_size = p_pes->i_size;
1035 p_data = p_pes->p_buffer;
1037 b_new_pes = VLC_TRUE;
1041 int b_adaptation_field;
1043 sout_buffer_t *p_ts;
1045 p_ts = sout_BufferNew( p_sout, 188 );
1048 * 1b transport_error_indicator
1049 * 1b payload_unit_start
1050 * 1b transport_priority
1052 * 2b transport_scrambling_control
1053 * 2b if adaptation_field 0x03 else 0x01
1054 * 4b continuity_counter
1057 i_copy = __MIN( i_size, 184 );
1058 b_adaptation_field = i_size < 184 ? VLC_TRUE : VLC_FALSE;
1060 p_ts->p_buffer[0] = 0x47;
1061 p_ts->p_buffer[1] = ( b_new_pes ? 0x40 : 0x00 )|
1062 ( ( p_stream->i_pid >> 8 )&0x1f );
1063 p_ts->p_buffer[2] = p_stream->i_pid & 0xff;
1064 p_ts->p_buffer[3] = ( b_adaptation_field ? 0x30 : 0x10 )|
1065 p_stream->i_continuity_counter;
1067 b_new_pes = VLC_FALSE;
1068 p_stream->i_continuity_counter = (p_stream->i_continuity_counter+1)%16;
1070 if( b_adaptation_field )
1072 int i_stuffing = 184 - i_copy;
1075 p_ts->p_buffer[4] = i_stuffing - 1;
1076 if( i_stuffing > 1 )
1078 p_ts->p_buffer[5] = 0x00;
1079 for( i = 6; i < 6 + i_stuffing - 2; i++ )
1081 p_ts->p_buffer[i] = 0xff;
1086 memcpy( &p_ts->p_buffer[188 - i_copy], p_data, i_copy );
1090 BufferChainAppend( c, p_ts );
1094 sout_buffer_t *p_next = p_pes->p_next;
1096 p_pes->p_next = NULL;
1097 sout_BufferDelete( p_sout, p_pes );
1098 if( p_next == NULL )
1102 b_new_pes = VLC_TRUE;
1104 i_size = p_pes->i_size;
1105 p_data = p_pes->p_buffer;
1112 #if defined MODULE_NAME_IS_mux_ts
1113 static uint32_t CalculateCRC( uint8_t *p_begin, int i_count )
1115 static uint32_t CRC32[256] =
1117 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
1118 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
1119 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1120 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
1121 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
1122 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1123 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
1124 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
1125 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1126 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
1127 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
1128 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1129 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
1130 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
1131 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1132 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
1133 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
1134 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1135 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
1136 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
1137 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1138 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
1139 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
1140 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1141 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
1142 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
1143 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1144 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
1145 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
1146 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1147 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
1148 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
1149 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1150 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
1151 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
1152 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1153 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
1154 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
1155 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1156 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
1157 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
1158 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1159 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
1160 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
1161 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1162 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
1163 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
1164 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1165 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
1166 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
1167 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1168 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
1169 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
1170 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1171 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
1172 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
1173 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1174 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
1175 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
1176 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1177 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
1178 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
1179 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1180 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1183 uint32_t i_crc = 0xffffffff;
1185 /* Calculate the CRC */
1186 while( i_count > 0 )
1188 i_crc = (i_crc<<8) ^ CRC32[ (i_crc>>24) ^ ((uint32_t)*p_begin) ];
1196 static void GetPAT( sout_mux_t *p_mux,
1197 sout_buffer_chain_t *c )
1199 sout_mux_sys_t *p_sys = p_mux->p_sys;
1200 sout_buffer_t *p_pat;
1203 p_pat = sout_BufferNew( p_mux->p_sout, 1024 );
1207 p_pat->i_length = 0;
1209 bits_initwrite( &bits, 1024, p_pat->p_buffer );
1211 bits_write( &bits, 8, 0 ); // pointer
1212 bits_write( &bits, 8, 0x00 ); // table id
1213 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1214 bits_write( &bits, 1, 0 ); // 0
1215 bits_write( &bits, 2, 0x03 ); // reserved FIXME
1216 bits_write( &bits, 12, 13 ); // XXX for one program only XXX
1217 bits_write( &bits, 16, 0x01 ); // FIXME stream id
1218 bits_write( &bits, 2, 0x03 ); // FIXME
1219 bits_write( &bits, 5, p_sys->i_pat_version_number );
1220 bits_write( &bits, 1, 1 ); // current_next_indicator
1221 bits_write( &bits, 8, 0 ); // section number
1222 bits_write( &bits, 8, 0 ); // last section number
1224 bits_write( &bits, 16, 1 ); // program number
1225 bits_write( &bits, 3, 0x07 ); // reserved
1226 bits_write( &bits, 13, p_sys->pmt.i_pid ); // program map pid
1228 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1230 p_pat->i_size = bits.i_data;
1232 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1235 static void GetPMT( sout_mux_t *p_mux,
1236 sout_buffer_chain_t *c )
1238 sout_mux_sys_t *p_sys = p_mux->p_sys;
1239 sout_buffer_t *p_pmt;
1243 p_pmt = sout_BufferNew( p_mux->p_sout, 1024 );
1247 p_pmt->i_length = 0;
1249 bits_initwrite( &bits, 1024, p_pmt->p_buffer );
1251 bits_write( &bits, 8, 0 ); // pointer
1252 bits_write( &bits, 8, 0x02 ); // table id
1253 bits_write( &bits, 1, 1 ); // section_syntax_indicator
1254 bits_write( &bits, 1, 0 ); // 0
1255 bits_write( &bits, 2, 0 ); // reserved FIXME
1256 bits_write( &bits, 12, 13 + 5 * p_mux->i_nb_inputs );
1257 bits_write( &bits, 16, 1 ); // FIXME program number
1258 bits_write( &bits, 2, 0 ); // FIXME
1259 bits_write( &bits, 5, p_sys->i_pmt_version_number );
1260 bits_write( &bits, 1, 1 ); // current_next_indicator
1261 bits_write( &bits, 8, 0 ); // section number
1262 bits_write( &bits, 8, 0 ); // last section number
1264 bits_write( &bits, 3, 0 ); // reserved
1266 bits_write( &bits, 13, p_sys->i_pcr_pid ); // FIXME FXIME PCR_PID FIXME
1267 bits_write( &bits, 4, 0 ); // reserved FIXME
1269 bits_write( &bits, 12, 0 ); // program info len FIXME
1271 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1273 ts_stream_t *p_stream;
1275 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1277 bits_write( &bits, 8, p_stream->i_stream_type ); // stream_type
1278 bits_write( &bits, 3, 0 ); // reserved
1279 bits_write( &bits, 13, p_stream->i_pid ); // es pid
1280 bits_write( &bits, 4, 0 ); //reserved
1281 bits_write( &bits, 12, 0 ); // es info len FIXME
1284 bits_write( &bits, 32, CalculateCRC( bits.p_data + 1, bits.i_data - 1) );
1286 p_pmt->i_size = bits.i_data;
1288 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1290 #elif defined MODULE_NAME_IS_mux_ts_dvbpsi
1292 static sout_buffer_t *WritePSISection( sout_instance_t *p_sout,
1293 dvbpsi_psi_section_t* p_section )
1295 sout_buffer_t *p_psi, *p_first = NULL;
1302 i_size = (uint32_t)( p_section->p_payload_end - p_section->p_data )+
1303 ( p_section->b_syntax_indicator ? 4 : 0 );
1305 p_psi = sout_BufferNew( p_sout, i_size + 1 );
1308 p_psi->i_length = 0;
1309 p_psi->i_size = i_size + 1;
1311 p_psi->p_buffer[0] = 0; // pointer
1312 memcpy( p_psi->p_buffer + 1,
1316 sout_BufferChain( &p_first, p_psi );
1318 p_section = p_section->p_next;
1324 static void GetPAT( sout_mux_t *p_mux,
1325 sout_buffer_chain_t *c )
1327 sout_mux_sys_t *p_sys = p_mux->p_sys;
1328 sout_buffer_t *p_pat;
1330 dvbpsi_psi_section_t *p_section;
1332 dvbpsi_InitPAT( &pat,
1334 p_sys->i_pat_version_number,
1335 1 ); // b_current_next
1336 /* add all program (only one) */
1337 dvbpsi_PATAddProgram( &pat,
1339 p_sys->pmt.i_pid ); // i_pid
1341 p_section = dvbpsi_GenPATSections( &pat,
1342 0 ); // max program per section
1344 p_pat = WritePSISection( p_mux->p_sout, p_section );
1346 PEStoTS( p_mux->p_sout, c, p_pat, &p_sys->pat );
1348 dvbpsi_DeletePSISections( p_section );
1349 dvbpsi_EmptyPAT( &pat );
1352 static uint32_t GetDescriptorLength24b( int i_length )
1354 uint32_t i_l1, i_l2, i_l3;
1356 i_l1 = i_length&0x7f;
1357 i_l2 = ( i_length >> 7 )&0x7f;
1358 i_l3 = ( i_length >> 14 )&0x7f;
1360 return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
1363 static void GetPMT( sout_mux_t *p_mux,
1364 sout_buffer_chain_t *c )
1366 sout_mux_sys_t *p_sys = p_mux->p_sys;
1367 sout_buffer_t *p_pmt;
1370 dvbpsi_pmt_es_t *p_es;
1371 dvbpsi_psi_section_t *p_section;
1375 dvbpsi_InitPMT( &pmt,
1376 0x01, // program number
1377 p_sys->i_pmt_version_number,
1378 1, // b_current_next
1381 if( p_sys->i_mpeg4_streams > 0 )
1385 bits_buffer_t bits_fix_IOD;
1387 /* Make valgrind happy : it works at byte level not bit one so
1388 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
1389 * working (needed when fixing some bits) */
1390 memset( iod, 0, 4096 );
1392 bits_initwrite( &bits, 4096, iod );
1394 bits_write( &bits, 8, 0x01 );
1395 // InitialObjectDescriptor
1396 bits_align( &bits );
1397 bits_write( &bits, 8, 0x02 ); // tag
1398 bits_fix_IOD = bits; // save states to fix length later
1399 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
1400 bits_write( &bits, 10, 0x01 ); // ObjectDescriptorID
1401 bits_write( &bits, 1, 0x00 ); // URL Flag
1402 bits_write( &bits, 1, 0x00 ); // includeInlineProfileLevelFlag
1403 bits_write( &bits, 4, 0x0f ); // reserved
1404 bits_write( &bits, 8, 0xff ); // ODProfile (no ODcapability )
1405 bits_write( &bits, 8, 0xff ); // sceneProfile
1406 bits_write( &bits, 8, 0xfe ); // audioProfile (unspecified)
1407 bits_write( &bits, 8, 0xfe ); // visualProfile( // )
1408 bits_write( &bits, 8, 0xff ); // graphicProfile (no )
1409 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1411 ts_stream_t *p_stream;
1412 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1414 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1416 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
1418 bits_align( &bits );
1419 bits_write( &bits, 8, 0x03 ); // ES_DescrTag
1420 bits_fix_ESDescr = bits;
1421 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) ); // variable size
1422 bits_write( &bits, 16, p_stream->i_es_id );
1423 bits_write( &bits, 1, 0x00 ); // streamDependency
1424 bits_write( &bits, 1, 0x00 ); // URL Flag
1425 bits_write( &bits, 1, 0x00 ); // OCRStreamFlag
1426 bits_write( &bits, 5, 0x1f ); // streamPriority
1428 // DecoderConfigDesciptor
1429 bits_align( &bits );
1430 bits_write( &bits, 8, 0x04 ); // DecoderConfigDescrTag
1431 bits_fix_Decoder = bits;
1432 bits_write( &bits, 24, GetDescriptorLength24b( 0 ) );
1433 if( p_stream->i_stream_type == 0x10 )
1435 bits_write( &bits, 8, 0x20 ); // Visual 14496-2
1436 bits_write( &bits, 6, 0x04 ); // VisualStream
1438 else if( p_stream->i_stream_type == 0x11 )
1440 bits_write( &bits, 8, 0x40 ); // Audio 14496-3
1441 bits_write( &bits, 6, 0x05 ); // AudioStream
1445 bits_write( &bits, 8, 0x00 );
1446 bits_write( &bits, 6, 0x00 );
1448 msg_Err( p_mux->p_sout,"Unsupported stream_type => broken IOD");
1450 bits_write( &bits, 1, 0x00 ); // UpStream
1451 bits_write( &bits, 1, 0x01 ); // reserved
1452 bits_write( &bits, 24, 1024 * 1024 ); // bufferSizeDB
1453 bits_write( &bits, 32, 0x7fffffff ); // maxBitrate
1454 bits_write( &bits, 32, 0 ); // avgBitrate
1456 if( p_stream->i_decoder_specific_info > 0 )
1459 // DecoderSpecificInfo
1460 bits_align( &bits );
1461 bits_write( &bits, 8, 0x05 ); // tag
1462 bits_write( &bits, 24,
1463 GetDescriptorLength24b( p_stream->i_decoder_specific_info ) );
1464 for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
1466 bits_write( &bits, 8, ((uint8_t*)p_stream->p_decoder_specific_info)[i] );
1469 /* fix Decoder length */
1470 bits_write( &bits_fix_Decoder, 24,
1471 GetDescriptorLength24b( bits.i_data - bits_fix_Decoder.i_data - 3 ) );
1473 /* SLConfigDescriptor : predifined (0x01) */
1474 bits_align( &bits );
1475 bits_write( &bits, 8, 0x06 ); // tag
1476 bits_write( &bits, 24, GetDescriptorLength24b( 8 ) );
1477 bits_write( &bits, 8, 0x01 ); // predefined
1478 bits_write( &bits, 1, 0 ); // durationFlag
1479 bits_write( &bits, 32, 0 ); // OCRResolution
1480 bits_write( &bits, 8, 0 ); // OCRLength
1481 bits_write( &bits, 8, 0 ); // InstantBitrateLength
1482 bits_align( &bits );
1484 /* fix ESDescr length */
1485 bits_write( &bits_fix_ESDescr, 24,
1486 GetDescriptorLength24b( bits.i_data - bits_fix_ESDescr.i_data - 3 ) );
1489 bits_align( &bits );
1490 /* fix IOD length */
1491 bits_write( &bits_fix_IOD, 24,
1492 GetDescriptorLength24b( bits.i_data - bits_fix_IOD.i_data - 3 ) );
1493 dvbpsi_PMTAddDescriptor( &pmt,
1499 for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
1501 ts_stream_t *p_stream;
1503 p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
1505 p_es = dvbpsi_PMTAddES( &pmt,
1506 p_stream->i_stream_type,
1508 if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
1513 es_id[0] = (p_stream->i_es_id >> 8)&0xff;
1514 es_id[1] = (p_stream->i_es_id)&0xff;
1515 dvbpsi_PMTESAddDescriptor( p_es, 0x1f, 2, es_id );
1517 else if( p_stream->i_stream_type == 0xa0 )
1520 int i_extra = __MIN( p_stream->i_decoder_specific_info,
1523 /* private DIV3 descripor */
1524 memcpy( &data[0], &p_stream->i_bih_codec, 4 );
1525 data[4] = ( p_stream->i_bih_width >> 8 )&&0xff;
1526 data[5] = ( p_stream->i_bih_width )&&0xff;
1527 data[6] = ( p_stream->i_bih_height>> 8 )&&0xff;
1528 data[7] = ( p_stream->i_bih_height )&&0xff;
1529 data[8] = ( i_extra >> 8 )&&0xff;
1530 data[9] = ( i_extra )&&0xff;
1533 memcpy( &data[10], p_stream->p_decoder_specific_info, i_extra );
1536 /* 0xa0 is private */
1537 dvbpsi_PMTESAddDescriptor( p_es, 0xa0, i_extra + 10, data );
1539 else if( p_stream->i_stream_type == 0x81 )
1541 uint8_t format[4] = { 0x41, 0x43, 0x2d, 0x33 };
1543 /* "registration" descriptor : "AC-3" */
1544 dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
1548 p_section = dvbpsi_GenPMTSections( &pmt );
1550 p_pmt = WritePSISection( p_mux->p_sout, p_section );
1552 PEStoTS( p_mux->p_sout, c, p_pmt, &p_sys->pmt );
1554 dvbpsi_DeletePSISections( p_section );
1555 dvbpsi_EmptyPMT( &pmt );