1 /*****************************************************************************
2 * ts.c: MPEG-II TS Muxer
3 *****************************************************************************
4 * Copyright (C) 2001-2005 the VideoLAN team
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Eric Petit <titer@videolan.org>
9 * Jean-Paul Saman <jpsaman #_at_# m2x.nl>
10 * Wallace Wadge <wwadge #_at_# gmail.com>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
37 #include <vlc_common.h>
38 #include <vlc_plugin.h>
40 #include <vlc_block.h>
43 #include <vlc_iso_lang.h>
49 # include <dvbpsi/dvbpsi.h>
50 # include <dvbpsi/demux.h>
51 # include <dvbpsi/descriptor.h>
52 # include <dvbpsi/pat.h>
53 # include <dvbpsi/pmt.h>
54 # include <dvbpsi/sdt.h>
55 # include <dvbpsi/dr.h>
56 # include <dvbpsi/psi.h>
60 * - check PCR frequency requirement
62 * - check PCR/PCR "soft"
63 * - check if "registration" descriptor : "AC-3" should be a program
64 * descriptor or an es one. (xine want an es one)
66 * - remove creation of PAT/PMT without dvbpsi
69 * - subtitle support is far from perfect. I expect some subtitles drop
70 * if they arrive a bit late
71 * (We cannot rely on the fact that the fifo should be full)
74 /*****************************************************************************
76 *****************************************************************************/
77 static int ChangeKeyCallback ( vlc_object_t
*, char const *, vlc_value_t
, vlc_value_t
, void * );
78 static int ActiveKeyCallback ( vlc_object_t
*, char const *, vlc_value_t
, vlc_value_t
, void * );
80 /*****************************************************************************
82 *****************************************************************************/
83 static int Open ( vlc_object_t
* );
84 static void Close ( vlc_object_t
* );
86 #define VPID_TEXT N_("Video PID")
87 #define VPID_LONGTEXT N_("Assign a fixed PID to the video stream. The PCR " \
88 "PID will automatically be the video.")
89 #define APID_TEXT N_("Audio PID")
90 #define APID_LONGTEXT N_("Assign a fixed PID to the audio stream.")
91 #define SPUPID_TEXT N_("SPU PID")
92 #define SPUPID_LONGTEXT N_("Assign a fixed PID to the SPU.")
93 #define PMTPID_TEXT N_("PMT PID")
94 #define PMTPID_LONGTEXT N_("Assign a fixed PID to the PMT")
95 #define TSID_TEXT N_("TS ID")
96 #define TSID_LONGTEXT N_("Assign a fixed Transport Stream ID.")
97 #define NETID_TEXT N_("NET ID")
98 #define NETID_LONGTEXT N_("Assign a fixed Network ID (for SDT table)")
100 #define PMTPROG_TEXT N_("PMT Program numbers")
101 #define PMTPROG_LONGTEXT N_("Assign a program number to each PMT. This " \
102 "requires \"Set PID to ID of ES\" to be enabled." )
104 #define MUXPMT_TEXT N_("Mux PMT (requires --sout-ts-es-id-pid)")
105 #define MUXPMT_LONGTEXT N_("Define the pids to add to each pmt. This " \
106 "requires \"Set PID to ID of ES\" to be enabled." )
108 #define SDTDESC_TEXT N_("SDT Descriptors (requires --sout-ts-es-id-pid)")
109 #define SDTDESC_LONGTEXT N_("Defines the descriptors of each SDT. This" \
110 "requires \"Set PID to ID of ES\" to be enabled." )
112 #define PID_TEXT N_("Set PID to ID of ES")
113 #define PID_LONGTEXT N_("Sets PID to the ID if the incoming ES. This is for " \
114 "use with --ts-es-id-pid, and allows having the same PIDs in the input " \
115 "and output streams.")
117 #define ALIGNMENT_TEXT N_("Data alignment")
118 #define ALIGNMENT_LONGTEXT N_("Enforces alignment of all access units on " \
119 "PES boundaries. Disabling this might save some bandwidth but introduce incompatibilities.")
121 #define SHAPING_TEXT N_("Shaping delay (ms)")
122 #define SHAPING_LONGTEXT N_("Cut the " \
123 "stream in slices of the given duration, and ensure a constant bitrate " \
124 "between the two boundaries. This avoids having huge bitrate peaks, " \
125 "especially for reference frames." )
127 #define KEYF_TEXT N_("Use keyframes")
128 #define KEYF_LONGTEXT N_("If enabled, and shaping is specified, " \
129 "the TS muxer will place the boundaries at the end of I pictures. In " \
130 "that case, the shaping duration given by the user is a worse case " \
131 "used when no reference frame is available. This enhances the efficiency " \
132 "of the shaping algorithm, since I frames are usually the biggest " \
133 "frames in the stream.")
135 #define PCR_TEXT N_("PCR interval (ms)")
136 #define PCR_LONGTEXT N_("Set at which interval " \
137 "PCRs (Program Clock Reference) will be sent (in milliseconds). " \
138 "This value should be below 100ms. (default is 70ms).")
140 #define BMIN_TEXT N_( "Minimum B (deprecated)")
141 #define BMIN_LONGTEXT N_( "This setting is deprecated and not used anymore" )
143 #define BMAX_TEXT N_( "Maximum B (deprecated)")
144 #define BMAX_LONGTEXT N_( "This setting is deprecated and not used anymore")
146 #define DTS_TEXT N_("DTS delay (ms)")
147 #define DTS_LONGTEXT N_("Delay the DTS (decoding time " \
148 "stamps) and PTS (presentation timestamps) of the data in the " \
149 "stream, compared to the PCRs. This allows for some buffering inside " \
150 "the client decoder.")
152 #define ACRYPT_TEXT N_("Crypt audio")
153 #define ACRYPT_LONGTEXT N_("Crypt audio using CSA")
154 #define VCRYPT_TEXT N_("Crypt video")
155 #define VCRYPT_LONGTEXT N_("Crypt video using CSA")
157 #define CK_TEXT N_("CSA Key")
158 #define CK_LONGTEXT N_("CSA encryption key. This must be a " \
159 "16 char string (8 hexadecimal bytes).")
161 #define CK2_TEXT N_("Second CSA Key")
162 #define CK2_LONGTEXT N_("The even CSA encryption key. This must be a " \
163 "16 char string (8 hexadecimal bytes).")
165 #define CU_TEXT N_("CSA Key in use")
166 #define CU_LONGTEXT N_("CSA encryption key used. It can be the odd/first/1 " \
167 "(default) or the even/second/2 one.")
169 #define CPKT_TEXT N_("Packet size in bytes to encrypt")
170 #define CPKT_LONGTEXT N_("Size of the TS packet to encrypt. " \
171 "The encryption routines subtract the TS-header from the value before " \
174 #define SOUT_CFG_PREFIX "sout-ts-"
175 #define MAX_PMT 64 /* Maximum number of programs. FIXME: I just chose an arbitrary number. Where is the maximum in the spec? */
176 #define MAX_PMT_PID 64 /* Maximum pids in each pmt. FIXME: I just chose an arbitrary number. Where is the maximum in the spec? */
179 set_description( N_("TS muxer (libdvbpsi)") )
180 set_shortname( "MPEG-TS")
181 set_category( CAT_SOUT
)
182 set_subcategory( SUBCAT_SOUT_MUX
)
183 set_capability( "sout mux", 120 )
186 add_integer( SOUT_CFG_PREFIX
"pid-video", 0,VPID_TEXT
, VPID_LONGTEXT
,
188 add_integer( SOUT_CFG_PREFIX
"pid-audio", 0, APID_TEXT
,
189 APID_LONGTEXT
, true )
190 add_integer( SOUT_CFG_PREFIX
"pid-spu", 0, SPUPID_TEXT
,
191 SPUPID_LONGTEXT
, true )
192 add_integer( SOUT_CFG_PREFIX
"pid-pmt", 0, PMTPID_TEXT
,
193 PMTPID_LONGTEXT
, true )
194 add_integer( SOUT_CFG_PREFIX
"tsid", 0, TSID_TEXT
,
195 TSID_LONGTEXT
, true )
196 #ifdef HAVE_DVBPSI_SDT
197 add_integer( SOUT_CFG_PREFIX
"netid", 0, NETID_TEXT
,
198 NETID_LONGTEXT
, true )
200 add_string( SOUT_CFG_PREFIX
"program-pmt", NULL
, PMTPROG_TEXT
,
201 PMTPROG_LONGTEXT
, true )
202 add_bool( SOUT_CFG_PREFIX
"es-id-pid", false, PID_TEXT
, PID_LONGTEXT
,
204 add_string( SOUT_CFG_PREFIX
"muxpmt", NULL
, MUXPMT_TEXT
, MUXPMT_LONGTEXT
, true )
205 #ifdef HAVE_DVBPSI_SDT
206 add_string( SOUT_CFG_PREFIX
"sdtdesc", NULL
, SDTDESC_TEXT
, SDTDESC_LONGTEXT
, true )
208 add_bool( SOUT_CFG_PREFIX
"alignment", true, ALIGNMENT_TEXT
,
209 ALIGNMENT_LONGTEXT
, true )
211 add_integer( SOUT_CFG_PREFIX
"shaping", 200, SHAPING_TEXT
,
212 SHAPING_LONGTEXT
, true )
213 add_bool( SOUT_CFG_PREFIX
"use-key-frames", false, KEYF_TEXT
,
214 KEYF_LONGTEXT
, true )
216 add_integer( SOUT_CFG_PREFIX
"pcr", 70, PCR_TEXT
, PCR_LONGTEXT
,
218 add_integer( SOUT_CFG_PREFIX
"bmin", 0, BMIN_TEXT
, BMIN_LONGTEXT
,
220 add_integer( SOUT_CFG_PREFIX
"bmax", 0, BMAX_TEXT
, BMAX_LONGTEXT
,
222 add_integer( SOUT_CFG_PREFIX
"dts-delay", 400, DTS_TEXT
,
225 add_bool( SOUT_CFG_PREFIX
"crypt-audio", true, ACRYPT_TEXT
,
226 ACRYPT_LONGTEXT
, true )
227 add_bool( SOUT_CFG_PREFIX
"crypt-video", true, VCRYPT_TEXT
,
228 VCRYPT_LONGTEXT
, true )
230 add_string( SOUT_CFG_PREFIX
"csa-ck", NULL
, CK_TEXT
, CK_LONGTEXT
,
232 add_string( SOUT_CFG_PREFIX
"csa2-ck", NULL
, CK2_TEXT
, CK2_LONGTEXT
,
234 add_string( SOUT_CFG_PREFIX
"csa-use", "1", CU_TEXT
, CU_LONGTEXT
,
236 add_integer( SOUT_CFG_PREFIX
"csa-pkt", 188, CPKT_TEXT
, CPKT_LONGTEXT
, true )
238 set_callbacks( Open
, Close
)
241 /*****************************************************************************
242 * Local data structures
243 *****************************************************************************/
244 static const char *const ppsz_sout_options
[] = {
245 "pid-video", "pid-audio", "pid-spu", "pid-pmt", "tsid",
246 #ifdef HAVE_DVBPSI_SDT
249 "es-id-pid", "shaping", "pcr", "bmin", "bmax", "use-key-frames",
250 "dts-delay", "csa-ck", "csa2-ck", "csa-use", "csa-pkt", "crypt-audio", "crypt-video",
251 "muxpmt", "program-pmt", "alignment",
255 typedef struct pmt_map_t
/* Holds the mapping between the pmt-pid/pmt table */
258 unsigned long i_prog
;
261 typedef struct sdt_desc_t
264 char *psz_service_name
; /* name of program */
272 } sout_buffer_chain_t
;
274 static inline void BufferChainInit ( sout_buffer_chain_t
*c
)
278 c
->pp_last
= &c
->p_first
;
281 static inline void BufferChainAppend( sout_buffer_chain_t
*c
, block_t
*b
)
291 c
->pp_last
= &b
->p_next
;
294 static inline block_t
*BufferChainGet( sout_buffer_chain_t
*c
)
296 block_t
*b
= c
->p_first
;
301 c
->p_first
= b
->p_next
;
303 if( c
->p_first
== NULL
)
305 c
->pp_last
= &c
->p_first
;
313 static inline block_t
*BufferChainPeek( sout_buffer_chain_t
*c
)
315 block_t
*b
= c
->p_first
;
320 static inline void BufferChainClean( sout_buffer_chain_t
*c
)
324 while( ( b
= BufferChainGet( c
) ) )
328 BufferChainInit( c
);
331 typedef struct ts_stream_t
334 vlc_fourcc_t i_codec
;
338 int i_continuity_counter
;
339 bool b_discontinuity
;
341 /* to be used for carriege of DIV3 */
342 vlc_fourcc_t i_bih_codec
;
343 int i_bih_width
, i_bih_height
;
345 /* Specific to mpeg4 in mpeg2ts */
348 int i_decoder_specific_info
;
349 uint8_t *p_decoder_specific_info
;
351 /* language is iso639-2T */
355 sout_buffer_chain_t chain_pes
;
357 mtime_t i_pes_length
;
363 struct sout_mux_sys_t
366 sout_input_t
*p_pcr_input
;
368 vlc_mutex_t csa_lock
;
378 int i_pid_free
; /* first usable pid */
384 int i_pat_version_number
;
387 int i_pmt_version_number
;
388 ts_stream_t pmt
[MAX_PMT
];
389 pmt_map_t pmtmap
[MAX_PMT_PID
];
390 int i_pmt_program_number
[MAX_PMT
];
391 sdt_desc_t sdt_descriptors
[MAX_PMT
];
392 bool b_data_alignment
;
396 int i_null_continuity_counter
; /* Needed ? */
398 dvbpsi_pmt_t
*dvbpmt
;
400 /* for TS building */
401 int64_t i_bitrate_min
;
402 int64_t i_bitrate_max
;
404 int64_t i_shaping_delay
;
409 bool b_use_key_frames
;
411 mtime_t i_pcr
; /* last PCR emited */
419 /* Reserve a pid and return it */
420 static int AllocatePID( sout_mux_sys_t
*p_sys
, int i_cat
)
423 if ( i_cat
== VIDEO_ES
&& p_sys
->i_pid_video
)
425 i_pid
= p_sys
->i_pid_video
;
426 p_sys
->i_pid_video
= 0;
428 else if ( i_cat
== AUDIO_ES
&& p_sys
->i_pid_audio
)
430 i_pid
= p_sys
->i_pid_audio
;
431 p_sys
->i_pid_audio
= 0;
433 else if ( i_cat
== SPU_ES
&& p_sys
->i_pid_spu
)
435 i_pid
= p_sys
->i_pid_spu
;
436 p_sys
->i_pid_spu
= 0;
440 i_pid
= ++p_sys
->i_pid_free
;
445 static int pmtcompare( const void *pa
, const void *pb
)
447 if ( ((pmt_map_t
*)pa
)->i_pid
< ((pmt_map_t
*)pb
)->i_pid
)
449 else if ( ((pmt_map_t
*)pa
)->i_pid
> ((pmt_map_t
*)pb
)->i_pid
)
455 static int intcompare( const void *pa
, const void *pb
)
457 if ( *(int *)pa
< *(int *)pb
)
459 else if ( *(int *)pa
> *(int *)pb
)
465 /*****************************************************************************
467 *****************************************************************************/
468 static int Control ( sout_mux_t
*, int, va_list );
469 static int AddStream( sout_mux_t
*, sout_input_t
* );
470 static int DelStream( sout_mux_t
*, sout_input_t
* );
471 static int Mux ( sout_mux_t
* );
473 static block_t
*FixPES( sout_mux_t
*p_mux
, block_fifo_t
*p_fifo
);
474 static block_t
*Add_ADTS( block_t
*, es_format_t
* );
475 static void TSSchedule ( sout_mux_t
*p_mux
, sout_buffer_chain_t
*p_chain_ts
,
476 mtime_t i_pcr_length
, mtime_t i_pcr_dts
);
477 static void TSDate ( sout_mux_t
*p_mux
, sout_buffer_chain_t
*p_chain_ts
,
478 mtime_t i_pcr_length
, mtime_t i_pcr_dts
);
479 static void GetPAT( sout_mux_t
*p_mux
, sout_buffer_chain_t
*c
);
480 static void GetPMT( sout_mux_t
*p_mux
, sout_buffer_chain_t
*c
);
482 static block_t
*TSNew( sout_mux_t
*p_mux
, ts_stream_t
*p_stream
, bool b_pcr
);
483 static void TSSetPCR( block_t
*p_ts
, mtime_t i_dts
);
485 static void PEStoTS ( sout_instance_t
*, sout_buffer_chain_t
*, block_t
*, ts_stream_t
* );
487 /*****************************************************************************
489 *****************************************************************************/
490 static int Open( vlc_object_t
*p_this
)
492 sout_mux_t
*p_mux
=(sout_mux_t
*)p_this
;
493 sout_mux_sys_t
*p_sys
= NULL
;
497 config_ChainParse( p_mux
, SOUT_CFG_PREFIX
, ppsz_sout_options
, p_mux
->p_cfg
);
499 p_sys
= malloc( sizeof( sout_mux_sys_t
) );
502 p_sys
->i_pmtslots
= p_sys
->b_sdt
= 0;
503 p_sys
->i_num_pmt
= 1;
504 p_sys
->dvbpmt
= NULL
;
505 memset( &p_sys
->pmtmap
, 0, sizeof(p_sys
->pmtmap
) );
507 vlc_mutex_init( &p_sys
->csa_lock
);
509 p_mux
->pf_control
= Control
;
510 p_mux
->pf_addstream
= AddStream
;
511 p_mux
->pf_delstream
= DelStream
;
513 p_mux
->p_sys
= p_sys
;
515 for ( i
= 0; i
< MAX_PMT
; i
++ )
516 p_sys
->sdt_descriptors
[i
].psz_service_name
517 = p_sys
->sdt_descriptors
[i
].psz_provider
= NULL
;
518 memset( p_sys
->sdt_descriptors
, 0, sizeof(sdt_desc_t
) );
520 p_sys
->i_audio_bound
= 0;
521 p_sys
->i_video_bound
= 0;
523 p_sys
->b_es_id_pid
= var_GetBool( p_mux
, SOUT_CFG_PREFIX
"es-id-pid" );
525 var_Get( p_mux
, SOUT_CFG_PREFIX
"muxpmt", &val
);
527 fetch string of pmts. Here's a sample: --sout-ts-muxpmt="0x451,0x200,0x28a,0x240,,0x450,0x201,0x28b,0x241,,0x452,0x202,0x28c,0x242"
528 This would mean 0x451, 0x200, 0x28a, 0x240 would fall under one pmt (program), 0x450,0x201,0x28b,0x241 would fall under another
530 if( val
.psz_string
!= NULL
&& *val
.psz_string
)
533 char *psz
= val
.psz_string
;
539 i_pid
= strtoul( psz
, &psz_next
, 0 );
541 if ( psz_next
[0] != '\0' )
546 if ( p_sys
->i_num_pmt
> MAX_PMT
)
549 "Number of PMTs greater than compiled maximum (%d)", MAX_PMT
);
550 p_sys
->i_num_pmt
= MAX_PMT
;
555 p_sys
->pmtmap
[p_sys
->i_pmtslots
].i_pid
= i_pid
;
556 p_sys
->pmtmap
[p_sys
->i_pmtslots
].i_prog
= p_sys
->i_num_pmt
- 1;
558 if ( p_sys
->i_pmtslots
> MAX_PMT_PID
)
561 "Number of pids in PMT greater than compiled maximum (%d)",
563 p_sys
->i_pmtslots
= MAX_PMT_PID
;
567 /* Now sort according to pids for fast search later on */
568 qsort( (void *)p_sys
->pmtmap
, p_sys
->i_pmtslots
,
569 sizeof(pmt_map_t
), &pmtcompare
);
574 free( val
.psz_string
);
576 unsigned short subi
[3];
577 vlc_rand_bytes(subi
, sizeof(subi
));
578 p_sys
->i_pat_version_number
= nrand48(subi
) & 0x1f;
579 p_sys
->pat
.i_pid
= 0;
580 p_sys
->pat
.i_continuity_counter
= 0;
581 p_sys
->pat
.b_discontinuity
= false;
583 var_Get( p_mux
, SOUT_CFG_PREFIX
"tsid", &val
);
585 p_sys
->i_tsid
= val
.i_int
;
587 p_sys
->i_tsid
= nrand48(subi
) & 0xffff;
589 p_sys
->i_netid
= nrand48(subi
) & 0xffff;
590 #ifdef HAVE_DVBPSI_SDT
591 var_Get( p_mux
, SOUT_CFG_PREFIX
"netid", &val
);
593 p_sys
->i_netid
= val
.i_int
;
596 p_sys
->i_pmt_version_number
= nrand48(subi
) & 0x1f;
597 for( i
= 0; i
< p_sys
->i_num_pmt
; i
++ )
599 p_sys
->pmt
[i
].i_continuity_counter
= 0;
600 p_sys
->pmt
[i
].b_discontinuity
= false;
603 p_sys
->sdt
.i_pid
= 0x11;
604 p_sys
->sdt
.i_continuity_counter
= 0;
605 p_sys
->sdt
.b_discontinuity
= false;
607 #ifdef HAVE_DVBPSI_SDT
608 var_Get( p_mux
, SOUT_CFG_PREFIX
"sdtdesc", &val
);
609 p_sys
->b_sdt
= val
.psz_string
&& *val
.psz_string
? true : false;
611 /* Syntax is provider_sdt1,service_name_sdt1,provider_sdt2,service_name_sdt2... */
615 char *psz
= val
.psz_string
;
616 char *psz_sdttoken
= psz
;
619 while ( psz_sdttoken
!= NULL
)
621 char *psz_end
= strchr( psz_sdttoken
, ',' );
622 if( psz_end
!= NULL
)
628 p_sys
->sdt_descriptors
[i
/2].psz_provider
629 = strdup(psz_sdttoken
);
633 p_sys
->sdt_descriptors
[i
/2].psz_service_name
634 = strdup(psz_sdttoken
);
638 psz_sdttoken
= psz_end
;
641 free( val
.psz_string
);
643 p_sys
->b_sdt
= false;
646 p_sys
->b_data_alignment
= var_GetBool( p_mux
, SOUT_CFG_PREFIX
"alignment" );
648 var_Get( p_mux
, SOUT_CFG_PREFIX
"program-pmt", &val
);
649 if( val
.psz_string
&& *val
.psz_string
)
652 char *psz
= val
.psz_string
;
657 while ( psz
!= NULL
)
659 i_pid
= strtoul( psz
, &psz_next
, 0 );
660 if( psz_next
[0] != '\0' )
668 msg_Err( p_mux
, "Number of PMTs > maximum (%d)",
673 p_sys
->i_pmt_program_number
[i
] = i_pid
;
680 /* Option not specified, use 1, 2, 3... */
681 for( i
= 0; i
< p_sys
->i_num_pmt
; i
++ )
682 p_sys
->i_pmt_program_number
[i
] = i
+ 1;
684 free( val
.psz_string
);
686 var_Get( p_mux
, SOUT_CFG_PREFIX
"pid-pmt", &val
);
689 for( i
= 0; i
< p_sys
->i_num_pmt
; i
++ )
690 p_sys
->pmt
[i
].i_pid
= val
.i_int
+ i
; /* Does this make any sense? */
694 for( i
= 0; i
< p_sys
->i_num_pmt
; i
++ )
695 p_sys
->pmt
[i
].i_pid
= 0x42 + i
;
698 p_sys
->i_pid_free
= p_sys
->pmt
[p_sys
->i_num_pmt
- 1].i_pid
+ 1;
700 p_sys
->i_pid_video
= var_GetInteger( p_mux
, SOUT_CFG_PREFIX
"pid-video" );
701 if ( p_sys
->i_pid_video
> p_sys
->i_pid_free
)
703 p_sys
->i_pid_free
= p_sys
->i_pid_video
+ 1;
706 p_sys
->i_pid_audio
= var_GetInteger( p_mux
, SOUT_CFG_PREFIX
"pid-audio" );
707 if ( p_sys
->i_pid_audio
> p_sys
->i_pid_free
)
709 p_sys
->i_pid_free
= p_sys
->i_pid_audio
+ 1;
712 p_sys
->i_pid_spu
= var_GetInteger( p_mux
, SOUT_CFG_PREFIX
"pid-spu" );
713 if ( p_sys
->i_pid_spu
> p_sys
->i_pid_free
)
715 p_sys
->i_pid_free
= p_sys
->i_pid_spu
+ 1;
718 p_sys
->i_pcr_pid
= 0x1fff;
719 p_sys
->p_pcr_input
= NULL
;
721 p_sys
->i_mpeg4_streams
= 0;
723 p_sys
->i_null_continuity_counter
= 0;
725 /* Allow to create constrained stream */
726 p_sys
->i_bitrate_min
= var_GetInteger( p_mux
, SOUT_CFG_PREFIX
"bmin" );
728 p_sys
->i_bitrate_max
= var_GetInteger( p_mux
, SOUT_CFG_PREFIX
"bmax" );
730 if( p_sys
->i_bitrate_min
> 0 && p_sys
->i_bitrate_max
> 0 &&
731 p_sys
->i_bitrate_min
> p_sys
->i_bitrate_max
)
733 msg_Err( p_mux
, "incompatible minimum and maximum bitrate, "
734 "disabling bitrate control" );
735 p_sys
->i_bitrate_min
= 0;
736 p_sys
->i_bitrate_max
= 0;
738 if( p_sys
->i_bitrate_min
> 0 || p_sys
->i_bitrate_max
> 0 )
740 msg_Err( p_mux
, "bmin and bmax no more supported "
741 "(if you need them report it)" );
744 var_Get( p_mux
, SOUT_CFG_PREFIX
"shaping", &val
);
745 p_sys
->i_shaping_delay
= (int64_t)val
.i_int
* 1000;
746 if( p_sys
->i_shaping_delay
<= 0 )
749 "invalid shaping (%"PRId64
"ms) resetting to 200ms",
750 p_sys
->i_shaping_delay
/ 1000 );
751 p_sys
->i_shaping_delay
= 200000;
754 var_Get( p_mux
, SOUT_CFG_PREFIX
"pcr", &val
);
755 p_sys
->i_pcr_delay
= (int64_t)val
.i_int
* 1000;
756 if( p_sys
->i_pcr_delay
<= 0 ||
757 p_sys
->i_pcr_delay
>= p_sys
->i_shaping_delay
)
760 "invalid pcr delay (%"PRId64
"ms) resetting to 70ms",
761 p_sys
->i_pcr_delay
/ 1000 );
762 p_sys
->i_pcr_delay
= 70000;
765 var_Get( p_mux
, SOUT_CFG_PREFIX
"dts-delay", &val
);
766 p_sys
->i_dts_delay
= (int64_t)val
.i_int
* 1000;
768 msg_Dbg( p_mux
, "shaping=%"PRId64
" pcr=%"PRId64
" dts_delay=%"PRId64
,
769 p_sys
->i_shaping_delay
, p_sys
->i_pcr_delay
, p_sys
->i_dts_delay
);
771 p_sys
->b_use_key_frames
= var_GetBool( p_mux
, SOUT_CFG_PREFIX
"use-key-frames" );
773 /* for TS generation */
777 var_Create( p_mux
, SOUT_CFG_PREFIX
"csa-ck", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
| VLC_VAR_ISCOMMAND
);
778 var_Get( p_mux
, SOUT_CFG_PREFIX
"csa-ck", &val
);
779 if( val
.psz_string
&& *val
.psz_string
)
784 p_sys
->csa
= csa_New();
786 var_Create( p_mux
, SOUT_CFG_PREFIX
"csa2-ck", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
| VLC_VAR_ISCOMMAND
);
787 var_Get( p_mux
, SOUT_CFG_PREFIX
"csa2-ck", &csa2
);
788 i_res
= csa_SetCW( (vlc_object_t
*)p_mux
, p_sys
->csa
, val
.psz_string
, true );
789 if( i_res
== VLC_SUCCESS
&& csa2
.psz_string
&& *csa2
.psz_string
)
791 if( csa_SetCW( (vlc_object_t
*)p_mux
, p_sys
->csa
, csa2
.psz_string
, false ) != VLC_SUCCESS
)
793 csa_SetCW( (vlc_object_t
*)p_mux
, p_sys
->csa
, val
.psz_string
, false );
796 else if( i_res
== VLC_SUCCESS
)
798 csa_SetCW( (vlc_object_t
*)p_mux
, p_sys
->csa
, val
.psz_string
, false );
802 csa_Delete( p_sys
->csa
);
808 vlc_value_t use_val
, pkt_val
;
810 var_Create( p_mux
, SOUT_CFG_PREFIX
"csa-use", VLC_VAR_STRING
| VLC_VAR_DOINHERIT
| VLC_VAR_ISCOMMAND
);
811 var_Get( p_mux
, SOUT_CFG_PREFIX
"csa-use", &use_val
);
812 var_AddCallback( p_mux
, SOUT_CFG_PREFIX
"csa-use", ActiveKeyCallback
, NULL
);
813 var_AddCallback( p_mux
, SOUT_CFG_PREFIX
"csa-ck", ChangeKeyCallback
, (void *)1 );
814 var_AddCallback( p_mux
, SOUT_CFG_PREFIX
"csa2-ck", ChangeKeyCallback
, NULL
);
816 if ( var_Set( p_mux
, SOUT_CFG_PREFIX
"csa-use", use_val
) != VLC_SUCCESS
)
818 var_SetString( p_mux
, SOUT_CFG_PREFIX
"csa-use", "odd" );
820 free( use_val
.psz_string
);
822 var_Get( p_mux
, SOUT_CFG_PREFIX
"csa-pkt", &pkt_val
);
823 if( pkt_val
.i_int
< 12 || pkt_val
.i_int
> 188 )
825 msg_Err( p_mux
, "wrong packet size %"PRId64
" specified.",
827 msg_Warn( p_mux
, "using default packet size of 188 bytes" );
828 p_sys
->i_csa_pkt_size
= 188;
830 else p_sys
->i_csa_pkt_size
= pkt_val
.i_int
;
831 msg_Dbg( p_mux
, "encrypting %d bytes of packet", p_sys
->i_csa_pkt_size
);
833 free( csa2
.psz_string
);
835 free( val
.psz_string
);
837 p_sys
->b_crypt_audio
= var_GetBool( p_mux
, SOUT_CFG_PREFIX
"crypt-audio" );
839 p_sys
->b_crypt_video
= var_GetBool( p_mux
, SOUT_CFG_PREFIX
"crypt-video" );
844 /*****************************************************************************
846 *****************************************************************************/
847 static void Close( vlc_object_t
* p_this
)
849 sout_mux_t
*p_mux
= (sout_mux_t
*)p_this
;
850 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
855 var_DelCallback( p_mux
, SOUT_CFG_PREFIX
"csa-ck", ChangeKeyCallback
, NULL
);
856 var_DelCallback( p_mux
, SOUT_CFG_PREFIX
"csa2-ck", ChangeKeyCallback
, NULL
);
857 var_DelCallback( p_mux
, SOUT_CFG_PREFIX
"csa-use", ActiveKeyCallback
, NULL
);
858 csa_Delete( p_sys
->csa
);
861 for( i
= 0; i
< MAX_PMT
; i
++ )
863 free( p_sys
->sdt_descriptors
[i
].psz_service_name
);
864 free( p_sys
->sdt_descriptors
[i
].psz_provider
);
867 vlc_mutex_destroy( &p_sys
->csa_lock
);
868 free( p_sys
->dvbpmt
);
872 /*****************************************************************************
873 * ChangeKeyCallback: called when changing the odd encryption key on the fly.
874 *****************************************************************************/
875 static int ChangeKeyCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
876 vlc_value_t oldval
, vlc_value_t newval
,
879 VLC_UNUSED(psz_cmd
); VLC_UNUSED(oldval
);
880 sout_mux_t
*p_mux
= (sout_mux_t
*)p_this
;
881 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
884 vlc_mutex_lock( &p_sys
->csa_lock
);
885 ret
= csa_SetCW( p_this
, p_sys
->csa
, newval
.psz_string
,
886 !!(intptr_t)p_data
);
887 vlc_mutex_unlock( &p_sys
->csa_lock
);
892 /*****************************************************************************
893 * ActiveKeyCallback: called when changing the active (in use) encryption key on the fly.
894 *****************************************************************************/
895 static int ActiveKeyCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
896 vlc_value_t oldval
, vlc_value_t newval
,
899 VLC_UNUSED(psz_cmd
); VLC_UNUSED(oldval
); VLC_UNUSED(p_data
);
900 sout_mux_t
*p_mux
= (sout_mux_t
*)p_this
;
901 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
902 int i_res
= VLC_EBADVAR
;
904 vlc_mutex_lock( &p_sys
->csa_lock
);
905 if( !strcmp(newval
.psz_string
, "odd" ) || !strcmp(newval
.psz_string
, "first" ) || !strcmp(newval
.psz_string
, "1" ) )
907 i_res
= csa_UseKey( (vlc_object_t
*)p_mux
, p_sys
->csa
, 1 );
909 else if( !strcmp(newval
.psz_string
, "even" ) || !strcmp(newval
.psz_string
, "second" ) || !strcmp(newval
.psz_string
, "2" ) )
911 i_res
= csa_UseKey( (vlc_object_t
*)p_mux
, p_sys
->csa
, 0 );
913 vlc_mutex_unlock( &p_sys
->csa_lock
);
918 /*****************************************************************************
920 *****************************************************************************/
921 static int Control( sout_mux_t
*p_mux
, int i_query
, va_list args
)
929 case MUX_CAN_ADD_STREAM_WHILE_MUXING
:
930 pb_bool
= (bool*)va_arg( args
, bool * );
934 case MUX_GET_ADD_STREAM_WAIT
:
935 pb_bool
= (bool*)va_arg( args
, bool * );
940 ppsz
= (char**)va_arg( args
, char ** );
941 *ppsz
= strdup( "video/mpeg" ); /* FIXME not sure */
949 /*****************************************************************************
950 * AddStream: called for each stream addition
951 *****************************************************************************/
952 static int AddStream( sout_mux_t
*p_mux
, sout_input_t
*p_input
)
954 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
955 ts_stream_t
*p_stream
;
958 p_input
->p_sys
= p_stream
= malloc( sizeof( ts_stream_t
) );
959 if( !p_input
->p_sys
)
962 /* Init this new stream */
963 if ( p_sys
->b_es_id_pid
)
964 p_stream
->i_pid
= p_input
->p_fmt
->i_id
& 0x1fff;
966 p_stream
->i_pid
= AllocatePID( p_sys
, p_input
->p_fmt
->i_cat
);
967 p_stream
->i_codec
= p_input
->p_fmt
->i_codec
;
968 p_stream
->i_continuity_counter
= 0;
969 p_stream
->b_discontinuity
= false;
970 p_stream
->i_decoder_specific_info
= 0;
971 p_stream
->p_decoder_specific_info
= NULL
;
973 msg_Dbg( p_mux
, "adding input codec=%4.4s pid=%d",
974 (char*)&p_input
->p_fmt
->i_codec
, p_stream
->i_pid
);
976 /* All others fields depand on codec */
977 switch( p_input
->p_fmt
->i_cat
)
980 switch( p_input
->p_fmt
->i_codec
)
983 /* TODO: do we need to check MPEG-I/II ? */
984 p_stream
->i_stream_type
= 0x02;
985 p_stream
->i_stream_id
= 0xe0;
988 p_stream
->i_stream_type
= 0x10;
989 p_stream
->i_stream_id
= 0xe0;
990 p_stream
->i_es_id
= p_stream
->i_pid
;
993 p_stream
->i_stream_type
= 0x1b;
994 p_stream
->i_stream_id
= 0xe0;
996 /* XXX dirty dirty but somebody want that:
997 * using crapy MS-codec XXX */
998 /* I didn't want to do that :P */
999 case VLC_CODEC_H263I
:
1000 case VLC_CODEC_H263
:
1001 case VLC_CODEC_WMV3
:
1002 case VLC_CODEC_WMV2
:
1003 case VLC_CODEC_WMV1
:
1004 case VLC_CODEC_DIV3
:
1005 case VLC_CODEC_DIV2
:
1006 case VLC_CODEC_DIV1
:
1007 case VLC_CODEC_MJPG
:
1008 p_stream
->i_stream_type
= 0xa0; /* private */
1009 p_stream
->i_stream_id
= 0xa0; /* beurk */
1010 p_stream
->i_bih_codec
= p_input
->p_fmt
->i_codec
;
1011 p_stream
->i_bih_width
= p_input
->p_fmt
->video
.i_width
;
1012 p_stream
->i_bih_height
= p_input
->p_fmt
->video
.i_height
;
1014 case VLC_CODEC_DIRAC
:
1015 /* stream_id makes use of stream_id_extension */
1016 p_stream
->i_stream_id
= (PES_EXTENDED_STREAM_ID
<< 8) | 0x60;
1017 p_stream
->i_stream_type
= 0xd1;
1021 return VLC_EGENERIC
;
1023 p_sys
->i_video_bound
++;
1027 switch( p_input
->p_fmt
->i_codec
)
1029 case VLC_CODEC_MPGA
:
1030 p_stream
->i_stream_type
=
1031 p_input
->p_fmt
->audio
.i_rate
>= 32000 ? 0x03 : 0x04;
1032 p_stream
->i_stream_id
= 0xc0;
1035 p_stream
->i_stream_type
= 0x81;
1036 p_stream
->i_stream_id
= 0xbd;
1038 case VLC_CODEC_EAC3
:
1039 p_stream
->i_stream_type
= 0x06;
1040 p_stream
->i_stream_id
= 0xbd;
1042 case VLC_CODEC_DVD_LPCM
:
1043 p_stream
->i_stream_type
= 0x83;
1044 p_stream
->i_stream_id
= 0xbd;
1047 p_stream
->i_stream_type
= 0x06;
1048 p_stream
->i_stream_id
= 0xbd;
1050 case VLC_CODEC_MP4A
:
1051 /* XXX: make that configurable in some way when LOAS
1052 * is implemented for AAC in TS */
1053 //p_stream->i_stream_type = 0x11; /* LOAS/LATM */
1054 p_stream
->i_stream_type
= 0x0f; /* ADTS */
1055 p_stream
->i_stream_id
= 0xc0;
1056 p_sys
->i_mpeg4_streams
++;
1057 p_stream
->i_es_id
= p_stream
->i_pid
;
1061 return VLC_EGENERIC
;
1063 p_sys
->i_audio_bound
++;
1067 switch( p_input
->p_fmt
->i_codec
)
1070 p_stream
->i_stream_type
= 0x82;
1071 p_stream
->i_stream_id
= 0xbd;
1073 case VLC_CODEC_SUBT
:
1074 p_stream
->i_stream_type
= 0x12;
1075 p_stream
->i_stream_id
= 0xfa;
1076 p_sys
->i_mpeg4_streams
++;
1077 p_stream
->i_es_id
= p_stream
->i_pid
;
1079 case VLC_CODEC_DVBS
:
1080 p_stream
->i_stream_type
= 0x06;
1081 p_stream
->i_es_id
= p_input
->p_fmt
->subs
.dvb
.i_id
;
1082 p_stream
->i_stream_id
= 0xbd;
1084 case VLC_CODEC_TELETEXT
:
1085 p_stream
->i_stream_type
= 0x06;
1086 p_stream
->i_stream_id
= 0xbd; /* FIXME */
1090 return VLC_EGENERIC
;
1096 return VLC_EGENERIC
;
1099 p_stream
->i_langs
= 1+p_input
->p_fmt
->i_extra_languages
;
1100 p_stream
->lang
= malloc(p_stream
->i_langs
*3);
1101 if( !p_stream
->lang
)
1103 p_stream
->i_langs
= 0;
1110 p_stream
->lang
[2] = '\0';
1111 if( p_input
->p_fmt
->psz_language
)
1113 char *psz
= p_input
->p_fmt
->psz_language
;
1114 const iso639_lang_t
*pl
= NULL
;
1116 if( strlen( psz
) == 2 )
1118 pl
= GetLang_1( psz
);
1120 else if( strlen( psz
) == 3 )
1122 pl
= GetLang_2B( psz
);
1123 if( !strcmp( pl
->psz_iso639_1
, "??" ) )
1125 pl
= GetLang_2T( psz
);
1128 if( pl
&& strcmp( pl
->psz_iso639_1
, "??" ) )
1130 p_stream
->lang
[0] = pl
->psz_iso639_2T
[0];
1131 p_stream
->lang
[1] = pl
->psz_iso639_2T
[1];
1132 p_stream
->lang
[2] = pl
->psz_iso639_2T
[2];
1134 msg_Dbg( p_mux
, " - lang=%c%c%c",
1135 p_stream
->lang
[0], p_stream
->lang
[1],
1136 p_stream
->lang
[2] );
1139 while( i
< p_stream
->i_langs
) {
1140 if( p_input
->p_fmt
->p_extra_languages
[i
-1].psz_language
)
1142 char *psz
= p_input
->p_fmt
->p_extra_languages
[i
-1].psz_language
;
1143 const iso639_lang_t
*pl
= NULL
;
1145 if( strlen( psz
) == 2 )
1147 pl
= GetLang_1( psz
);
1149 else if( strlen( psz
) == 3 )
1151 pl
= GetLang_2B( psz
);
1152 if( !strcmp( pl
->psz_iso639_1
, "??" ) )
1154 pl
= GetLang_2T( psz
);
1157 if( pl
&& strcmp( pl
->psz_iso639_1
, "??" ) )
1159 p_stream
->lang
[i
*3+0] = pl
->psz_iso639_2T
[0];
1160 p_stream
->lang
[i
*3+1] = pl
->psz_iso639_2T
[1];
1161 p_stream
->lang
[i
*3+2] = pl
->psz_iso639_2T
[2];
1163 msg_Dbg( p_mux
, " - lang=%c%c%c",
1164 p_stream
->lang
[i
*3+0], p_stream
->lang
[i
*3+1],
1165 p_stream
->lang
[i
*3+2] );
1171 /* Create decoder specific info for subt */
1172 if( p_stream
->i_codec
== VLC_CODEC_SUBT
)
1176 p_stream
->i_decoder_specific_info
= 55;
1177 p_stream
->p_decoder_specific_info
= p
=
1178 malloc( p_stream
->i_decoder_specific_info
);
1181 p
[0] = 0x10; /* textFormat, 0x10 for 3GPP TS 26.245 */
1182 p
[1] = 0x00; /* flags: 1b: associated video info flag
1186 p
[2] = 52; /* remaining size */
1190 p
[0] = p
[1] = p
[2] = p
[3] = 0; p
+=4; /* display flags */
1191 *p
++ = 0; /* horizontal justification (-1: left, 0 center, 1 right) */
1192 *p
++ = 1; /* vertical justification (-1: top, 0 center, 1 bottom) */
1194 p
[0] = p
[1] = p
[2] = 0x00; p
+=3;/* background rgb */
1195 *p
++ = 0xff; /* background a */
1197 p
[0] = p
[1] = 0; p
+= 2; /* text box top */
1198 p
[0] = p
[1] = 0; p
+= 2; /* text box left */
1199 p
[0] = p
[1] = 0; p
+= 2; /* text box bottom */
1200 p
[0] = p
[1] = 0; p
+= 2; /* text box right */
1202 p
[0] = p
[1] = 0; p
+= 2; /* start char */
1203 p
[0] = p
[1] = 0; p
+= 2; /* end char */
1204 p
[0] = p
[1] = 0; p
+= 2; /* default font id */
1206 *p
++ = 0; /* font style flags */
1207 *p
++ = 12; /* font size */
1209 p
[0] = p
[1] = p
[2] = 0x00; p
+=3;/* foreground rgb */
1210 *p
++ = 0x00; /* foreground a */
1212 p
[0] = p
[1] = p
[2] = 0; p
[3] = 22; p
+= 4;
1213 memcpy( p
, "ftab", 4 ); p
+= 4;
1214 *p
++ = 0; *p
++ = 1; /* entry count */
1215 p
[0] = p
[1] = 0; p
+= 2; /* font id */
1216 *p
++ = 9; /* font name length */
1217 memcpy( p
, "Helvetica", 9 ); /* font name */
1219 else p_stream
->i_decoder_specific_info
= 0;
1223 /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
1224 p_stream
->i_decoder_specific_info
= p_input
->p_fmt
->i_extra
;
1225 if( p_stream
->i_decoder_specific_info
> 0 )
1227 p_stream
->p_decoder_specific_info
=
1228 malloc( p_stream
->i_decoder_specific_info
);
1229 if( p_stream
->p_decoder_specific_info
)
1231 memcpy( p_stream
->p_decoder_specific_info
,
1232 p_input
->p_fmt
->p_extra
,
1233 p_input
->p_fmt
->i_extra
);
1235 else p_stream
->i_decoder_specific_info
= 0;
1239 /* Init pes chain */
1240 BufferChainInit( &p_stream
->chain_pes
);
1241 p_stream
->i_pes_dts
= 0;
1242 p_stream
->i_pes_length
= 0;
1243 p_stream
->i_pes_used
= 0;
1244 p_stream
->b_key_frame
= 0;
1246 /* We only change PMT version (PAT isn't changed) */
1247 p_sys
->i_pmt_version_number
= ( p_sys
->i_pmt_version_number
+ 1 )%32;
1249 /* Update pcr_pid */
1250 if( p_input
->p_fmt
->i_cat
!= SPU_ES
&&
1251 ( p_sys
->i_pcr_pid
== 0x1fff || p_input
->p_fmt
->i_cat
== VIDEO_ES
) )
1253 if( p_sys
->p_pcr_input
)
1255 /* There was already a PCR stream, so clean context */
1258 p_sys
->i_pcr_pid
= p_stream
->i_pid
;
1259 p_sys
->p_pcr_input
= p_input
;
1261 msg_Dbg( p_mux
, "new PCR PID is %d", p_sys
->i_pcr_pid
);
1267 /*****************************************************************************
1268 * DelStream: called before a stream deletion
1269 *****************************************************************************/
1270 static int DelStream( sout_mux_t
*p_mux
, sout_input_t
*p_input
)
1272 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
1273 ts_stream_t
*p_stream
;
1276 p_stream
= (ts_stream_t
*)p_input
->p_sys
;
1277 msg_Dbg( p_mux
, "removing input pid=%d", p_stream
->i_pid
);
1279 if( p_sys
->i_pcr_pid
== p_stream
->i_pid
)
1283 /* Find a new pcr stream (Prefer Video Stream) */
1284 p_sys
->i_pcr_pid
= 0x1fff;
1285 p_sys
->p_pcr_input
= NULL
;
1286 for( i
= 0; i
< p_mux
->i_nb_inputs
; i
++ )
1288 if( p_mux
->pp_inputs
[i
] == p_input
)
1293 if( p_mux
->pp_inputs
[i
]->p_fmt
->i_cat
== VIDEO_ES
)
1296 ((ts_stream_t
*)p_mux
->pp_inputs
[i
]->p_sys
)->i_pid
;
1297 p_sys
->p_pcr_input
= p_mux
->pp_inputs
[i
];
1300 else if( p_mux
->pp_inputs
[i
]->p_fmt
->i_cat
!= SPU_ES
&&
1301 p_sys
->i_pcr_pid
== 0x1fff )
1304 ((ts_stream_t
*)p_mux
->pp_inputs
[i
]->p_sys
)->i_pid
;
1305 p_sys
->p_pcr_input
= p_mux
->pp_inputs
[i
];
1308 if( p_sys
->p_pcr_input
)
1310 /* Empty TS buffer */
1313 msg_Dbg( p_mux
, "new PCR PID is %d", p_sys
->i_pcr_pid
);
1316 /* Empty all data in chain_pes */
1317 BufferChainClean( &p_stream
->chain_pes
);
1319 free(p_stream
->lang
);
1320 free( p_stream
->p_decoder_specific_info
);
1321 if( p_stream
->i_stream_id
== 0xfa ||
1322 p_stream
->i_stream_id
== 0xfb ||
1323 p_stream
->i_stream_id
== 0xfe )
1325 p_sys
->i_mpeg4_streams
--;
1328 var_Get( p_mux
, SOUT_CFG_PREFIX
"pid-video", &val
);
1331 int i_pid_video
= val
.i_int
;
1332 if ( i_pid_video
== p_stream
->i_pid
)
1334 p_sys
->i_pid_video
= i_pid_video
;
1335 msg_Dbg( p_mux
, "freeing video PID %d", i_pid_video
);
1338 var_Get( p_mux
, SOUT_CFG_PREFIX
"pid-audio", &val
);
1341 int i_pid_audio
= val
.i_int
;
1342 if ( i_pid_audio
== p_stream
->i_pid
)
1344 p_sys
->i_pid_audio
= i_pid_audio
;
1345 msg_Dbg( p_mux
, "freeing audio PID %d", i_pid_audio
);
1348 var_Get( p_mux
, SOUT_CFG_PREFIX
"pid-spu", &val
);
1351 int i_pid_spu
= val
.i_int
;
1352 if ( i_pid_spu
== p_stream
->i_pid
)
1354 p_sys
->i_pid_spu
= i_pid_spu
;
1355 msg_Dbg( p_mux
, "freeing spu PID %d", i_pid_spu
);
1360 /* We only change PMT version (PAT isn't changed) */
1361 p_sys
->i_pmt_version_number
++; p_sys
->i_pmt_version_number
%= 32;
1366 /*****************************************************************************
1367 * Mux: Call each time there is new data for at least one stream
1368 *****************************************************************************
1370 *****************************************************************************/
1371 static int Mux( sout_mux_t
*p_mux
)
1373 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
1374 ts_stream_t
*p_pcr_stream
;
1376 if( p_sys
->i_pcr_pid
== 0x1fff )
1379 for( i
= 0; i
< p_mux
->i_nb_inputs
; i
++ )
1381 block_FifoEmpty( p_mux
->pp_inputs
[i
]->p_fifo
);
1383 msg_Dbg( p_mux
, "waiting for PCR streams" );
1386 p_pcr_stream
= (ts_stream_t
*)p_sys
->p_pcr_input
->p_sys
;
1390 sout_buffer_chain_t chain_ts
;
1394 mtime_t i_pcr_length
;
1395 mtime_t i_shaping_delay
;
1398 if( p_pcr_stream
->b_key_frame
)
1400 i_shaping_delay
= p_pcr_stream
->i_pes_length
;
1404 i_shaping_delay
= p_sys
->i_shaping_delay
;
1407 /* 1: get enough PES packet for all input */
1413 /* Accumulate enough data in the pcr stream (>i_shaping_delay) */
1414 /* Accumulate enough data in all other stream ( >= length of pcr)*/
1415 for( i
= -1; i
< p_mux
->i_nb_inputs
; i
++ )
1417 sout_input_t
*p_input
;
1418 ts_stream_t
*p_stream
;
1419 int64_t i_spu_delay
= 0;
1422 p_input
= p_sys
->p_pcr_input
;
1423 else if( p_mux
->pp_inputs
[i
]->p_sys
== p_pcr_stream
)
1426 p_input
= p_mux
->pp_inputs
[i
];
1427 p_stream
= (ts_stream_t
*)p_input
->p_sys
;
1429 if( ( ( p_stream
== p_pcr_stream
) &&
1430 ( p_stream
->i_pes_length
< i_shaping_delay
) ) ||
1431 ( p_stream
->i_pes_dts
+ p_stream
->i_pes_length
<
1432 p_pcr_stream
->i_pes_dts
+ p_pcr_stream
->i_pes_length
) )
1434 /* Need more data */
1435 if( block_FifoCount( p_input
->p_fifo
) <= 1 )
1437 if( ( p_input
->p_fmt
->i_cat
== AUDIO_ES
) ||
1438 ( p_input
->p_fmt
->i_cat
== VIDEO_ES
) )
1440 /* We need more data */
1443 else if( block_FifoCount( p_input
->p_fifo
) <= 0 )
1445 /* spu, only one packet is needed */
1448 else if( p_input
->p_fmt
->i_cat
== SPU_ES
)
1450 /* Don't mux the SPU yet if it is too early */
1451 block_t
*p_spu
= block_FifoShow( p_input
->p_fifo
);
1454 p_spu
->i_dts
- p_pcr_stream
->i_pes_dts
;
1456 if( ( i_spu_delay
> i_shaping_delay
) &&
1457 ( i_spu_delay
< INT64_C(100000000) ) )
1460 if ( ( i_spu_delay
>= INT64_C(100000000) ) ||
1461 ( i_spu_delay
< INT64_C(10000) ) )
1463 BufferChainClean( &p_stream
->chain_pes
);
1464 p_stream
->i_pes_dts
= 0;
1465 p_stream
->i_pes_used
= 0;
1466 p_stream
->i_pes_length
= 0;
1473 if( p_stream
== p_pcr_stream
|| p_sys
->b_data_alignment
1474 || p_input
->p_fmt
->i_codec
!=
1477 p_data
= block_FifoGet( p_input
->p_fifo
);
1479 if( p_input
->p_fmt
->i_codec
==
1481 p_data
= Add_ADTS( p_data
, p_input
->p_fmt
);
1484 p_data
= FixPES( p_mux
, p_input
->p_fifo
);
1486 if( block_FifoCount( p_input
->p_fifo
) > 0 &&
1487 p_input
->p_fmt
->i_cat
!= SPU_ES
)
1489 block_t
*p_next
= block_FifoShow( p_input
->p_fifo
);
1490 p_data
->i_length
= p_next
->i_dts
- p_data
->i_dts
;
1492 else if( p_input
->p_fmt
->i_codec
!=
1494 p_data
->i_length
= 1000;
1496 if( ( p_pcr_stream
->i_pes_dts
> 0 &&
1497 p_data
->i_dts
- 10000000 > p_pcr_stream
->i_pes_dts
+
1498 p_pcr_stream
->i_pes_length
) ||
1499 p_data
->i_dts
< p_stream
->i_pes_dts
||
1500 ( p_stream
->i_pes_dts
> 0 &&
1501 p_input
->p_fmt
->i_cat
!= SPU_ES
&&
1502 p_data
->i_dts
- 10000000 > p_stream
->i_pes_dts
+
1503 p_stream
->i_pes_length
) )
1505 msg_Warn( p_mux
, "packet with too strange dts "
1506 "(dts=%"PRId64
",old=%"PRId64
",pcr=%"PRId64
")",
1507 p_data
->i_dts
, p_stream
->i_pes_dts
,
1508 p_pcr_stream
->i_pes_dts
);
1509 block_Release( p_data
);
1511 BufferChainClean( &p_stream
->chain_pes
);
1512 p_stream
->i_pes_dts
= 0;
1513 p_stream
->i_pes_used
= 0;
1514 p_stream
->i_pes_length
= 0;
1516 if( p_input
->p_fmt
->i_cat
!= SPU_ES
)
1518 BufferChainClean( &p_pcr_stream
->chain_pes
);
1519 p_pcr_stream
->i_pes_dts
= 0;
1520 p_pcr_stream
->i_pes_used
= 0;
1521 p_pcr_stream
->i_pes_length
= 0;
1526 int i_header_size
= 0;
1527 int i_max_pes_size
= 0;
1528 int b_data_alignment
= 0;
1529 if( p_input
->p_fmt
->i_cat
== SPU_ES
)
1531 if( p_input
->p_fmt
->i_codec
==
1534 /* Prepend header */
1535 p_data
= block_Realloc( p_data
, 2,
1537 p_data
->p_buffer
[0] =
1538 ( (p_data
->i_buffer
- 2) >> 8) & 0xff;
1539 p_data
->p_buffer
[1] =
1540 ( (p_data
->i_buffer
- 2) ) & 0xff;
1542 /* remove trailling \0 if any */
1543 if( p_data
->i_buffer
> 2 &&
1544 p_data
->p_buffer
[p_data
->i_buffer
-1] ==
1548 /* Append a empty sub (sub text only) */
1549 if( p_data
->i_length
> 0 &&
1550 !( p_data
->i_buffer
== 1 &&
1551 *p_data
->p_buffer
== ' ' ) )
1553 block_t
*p_spu
= block_New( p_mux
, 3 );
1555 p_spu
->i_dts
= p_spu
->i_pts
=
1556 p_data
->i_dts
+ p_data
->i_length
;
1557 p_spu
->i_length
= 1000;
1559 p_spu
->p_buffer
[0] = 0;
1560 p_spu
->p_buffer
[1] = 1;
1561 p_spu
->p_buffer
[2] = ' ';
1563 EStoPES( p_mux
->p_sout
, &p_spu
, p_spu
,
1565 p_stream
->i_stream_id
, 1,
1567 p_data
->p_next
= p_spu
;
1570 else if( p_input
->p_fmt
->i_codec
==
1571 VLC_CODEC_TELETEXT
)
1574 i_header_size
= 0x24;
1575 b_data_alignment
= 1;
1577 else if( p_input
->p_fmt
->i_codec
==
1581 b_data_alignment
= 1;
1584 else if( p_data
->i_length
< 0 ||
1585 p_data
->i_length
> 2000000 )
1587 /* FIXME choose a better value, but anyway we
1588 * should never have to do that */
1589 p_data
->i_length
= 1000;
1592 p_stream
->i_pes_length
+= p_data
->i_length
;
1593 if( p_stream
->i_pes_dts
== 0 )
1595 p_stream
->i_pes_dts
= p_data
->i_dts
;
1598 /* Convert to pes */
1599 if( p_stream
->i_stream_id
== 0xa0 &&
1600 p_data
->i_pts
<= 0 )
1602 /* XXX yes I know, it's awful, but it's needed,
1603 * so don't remove it ... */
1604 p_data
->i_pts
= p_data
->i_dts
;
1607 if( p_input
->p_fmt
->i_codec
==
1610 b_data_alignment
= 1;
1611 /* dirac pes packets should be unbounded in
1612 * length, specify a suitibly large max size */
1613 i_max_pes_size
= INT_MAX
;
1616 EStoPES ( p_mux
->p_sout
, &p_data
, p_data
,
1617 p_input
->p_fmt
, p_stream
->i_stream_id
,
1618 1, b_data_alignment
, i_header_size
,
1621 BufferChainAppend( &p_stream
->chain_pes
, p_data
);
1623 if( p_sys
->b_use_key_frames
&& p_stream
== p_pcr_stream
1624 && (p_data
->i_flags
& BLOCK_FLAG_TYPE_I
)
1625 && !(p_data
->i_flags
& BLOCK_FLAG_NO_KEYFRAME
)
1626 && (p_stream
->i_pes_length
> 400000) )
1628 i_shaping_delay
= p_stream
->i_pes_length
;
1629 p_stream
->b_key_frame
= 1;
1642 i_pcr_dts
= p_pcr_stream
->i_pes_dts
;
1643 i_pcr_length
= p_pcr_stream
->i_pes_length
;
1644 p_pcr_stream
->b_key_frame
= 0;
1646 /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */
1647 /* 2: calculate non accurate total size of muxed ts */
1649 for( i
= 0; i
< p_mux
->i_nb_inputs
; i
++ )
1651 ts_stream_t
*p_stream
= (ts_stream_t
*)p_mux
->pp_inputs
[i
]->p_sys
;
1654 /* False for pcr stream but it will be enough to do PCR algo */
1655 for( p_pes
= p_stream
->chain_pes
.p_first
; p_pes
!= NULL
;
1656 p_pes
= p_pes
->p_next
)
1658 int i_size
= p_pes
->i_buffer
;
1659 if( p_pes
->i_dts
+ p_pes
->i_length
>
1660 p_pcr_stream
->i_pes_dts
+ p_pcr_stream
->i_pes_length
)
1662 mtime_t i_frag
= p_pcr_stream
->i_pes_dts
+
1663 p_pcr_stream
->i_pes_length
- p_pes
->i_dts
;
1669 i_size
= p_pes
->i_buffer
* i_frag
/ p_pes
->i_length
;
1671 i_packet_count
+= ( i_size
+ 183 ) / 184;
1674 /* add overhead for PCR (not really exact) */
1675 i_packet_count
+= (8 * i_pcr_length
/ p_sys
->i_pcr_delay
+ 175) / 176;
1677 /* 3: mux PES into TS */
1678 BufferChainInit( &chain_ts
);
1679 /* append PAT/PMT -> FIXME with big pcr delay it won't have enough pat/pmt */
1680 GetPAT( p_mux
, &chain_ts
);
1681 GetPMT( p_mux
, &chain_ts
);
1683 i_packet_count
+= chain_ts
.i_depth
;
1684 /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */
1690 ts_stream_t
*p_stream
;
1691 sout_input_t
*p_input
;
1695 /* Select stream (lowest dts) */
1696 for( i
= 0, i_stream
= -1, i_dts
= 0; i
< p_mux
->i_nb_inputs
; i
++ )
1698 p_stream
= (ts_stream_t
*)p_mux
->pp_inputs
[i
]->p_sys
;
1700 if( p_stream
->i_pes_dts
== 0 )
1705 if( i_stream
== -1 ||
1706 p_stream
->i_pes_dts
< i_dts
)
1709 i_dts
= p_stream
->i_pes_dts
;
1712 if( i_stream
== -1 || i_dts
> i_pcr_dts
+ i_pcr_length
)
1716 p_stream
= (ts_stream_t
*)p_mux
->pp_inputs
[i_stream
]->p_sys
;
1717 p_input
= p_mux
->pp_inputs
[i_stream
];
1719 /* do we need to issue pcr */
1721 if( p_stream
== p_pcr_stream
&&
1722 i_pcr_dts
+ i_packet_pos
* i_pcr_length
/ i_packet_count
>=
1723 p_sys
->i_pcr
+ p_sys
->i_pcr_delay
)
1726 p_sys
->i_pcr
= i_pcr_dts
+ i_packet_pos
*
1727 i_pcr_length
/ i_packet_count
;
1730 /* Build the TS packet */
1731 p_ts
= TSNew( p_mux
, p_stream
, b_pcr
);
1732 if( p_sys
->csa
!= NULL
&&
1733 (p_input
->p_fmt
->i_cat
!= AUDIO_ES
|| p_sys
->b_crypt_audio
) &&
1734 (p_input
->p_fmt
->i_cat
!= VIDEO_ES
|| p_sys
->b_crypt_video
) )
1736 p_ts
->i_flags
|= BLOCK_FLAG_SCRAMBLED
;
1741 BufferChainAppend( &chain_ts
, p_ts
);
1744 /* 4: date and send */
1745 TSSchedule( p_mux
, &chain_ts
, i_pcr_length
, i_pcr_dts
);
1749 #define STD_PES_PAYLOAD 170
1750 static block_t
*FixPES( sout_mux_t
*p_mux
, block_fifo_t
*p_fifo
)
1756 p_data
= block_FifoShow( p_fifo
);
1757 i_size
= p_data
->i_buffer
;
1759 if( i_size
== STD_PES_PAYLOAD
)
1761 return block_FifoGet( p_fifo
);
1763 else if( i_size
> STD_PES_PAYLOAD
)
1765 block_t
*p_new
= block_New( p_mux
, STD_PES_PAYLOAD
);
1766 vlc_memcpy( p_new
->p_buffer
, p_data
->p_buffer
, STD_PES_PAYLOAD
);
1767 p_new
->i_pts
= p_data
->i_pts
;
1768 p_new
->i_dts
= p_data
->i_dts
;
1769 p_new
->i_length
= p_data
->i_length
* STD_PES_PAYLOAD
1771 p_data
->i_buffer
-= STD_PES_PAYLOAD
;
1772 p_data
->p_buffer
+= STD_PES_PAYLOAD
;
1773 p_data
->i_pts
+= p_new
->i_length
;
1774 p_data
->i_dts
+= p_new
->i_length
;
1775 p_data
->i_length
-= p_new
->i_length
;
1776 p_data
->i_flags
|= BLOCK_FLAG_NO_KEYFRAME
;
1784 p_data
= block_FifoGet( p_fifo
);
1785 p_data
= block_Realloc( p_data
, 0, STD_PES_PAYLOAD
);
1786 p_next
= block_FifoShow( p_fifo
);
1787 if ( p_data
->i_flags
& BLOCK_FLAG_NO_KEYFRAME
)
1789 p_data
->i_flags
&= ~BLOCK_FLAG_NO_KEYFRAME
;
1790 p_data
->i_pts
= p_next
->i_pts
;
1791 p_data
->i_dts
= p_next
->i_dts
;
1793 i_copy
= __MIN( STD_PES_PAYLOAD
- i_size
, p_next
->i_buffer
);
1795 vlc_memcpy( &p_data
->p_buffer
[i_size
], p_next
->p_buffer
, i_copy
);
1796 p_next
->i_pts
+= p_next
->i_length
* i_copy
/ p_next
->i_buffer
;
1797 p_next
->i_dts
+= p_next
->i_length
* i_copy
/ p_next
->i_buffer
;
1798 p_next
->i_length
-= p_next
->i_length
* i_copy
/ p_next
->i_buffer
;
1799 p_next
->i_buffer
-= i_copy
;
1800 p_next
->p_buffer
+= i_copy
;
1801 p_next
->i_flags
|= BLOCK_FLAG_NO_KEYFRAME
;
1803 if( !p_next
->i_buffer
)
1805 p_next
= block_FifoGet( p_fifo
);
1806 block_Release( p_next
);
1812 static block_t
*Add_ADTS( block_t
*p_data
, es_format_t
*p_fmt
)
1814 uint8_t *p_extra
= p_fmt
->p_extra
;
1816 if( !p_data
|| p_fmt
->i_extra
< 2 || !p_extra
)
1817 return p_data
; /* no data to construct the headers */
1819 int i_index
= ( (p_extra
[0] << 1) | (p_extra
[1] >> 7) ) & 0x0f;
1820 int i_profile
= (p_extra
[0] >> 3) - 1; /* i_profile < 4 */
1822 if( i_index
== 0x0f && p_fmt
->i_extra
< 5 )
1823 return p_data
; /* not enough data */
1825 int i_channels
= (p_extra
[i_index
== 0x0f ? 4 : 1] >> 3) & 0x0f;
1827 #define ADTS_HEADER_SIZE 7 /* CRC needs 2 more bytes */
1830 /* keep a copy in case block_Realloc() fails */
1831 block_t
*p_bak_block
= block_Duplicate( p_data
);
1832 if( !p_bak_block
) /* OOM, block_Realloc() is likely to lose our block */
1833 return p_data
; /* the frame isn't correct but that's the best we have */
1835 block_t
*p_new_block
= block_Realloc( p_data
, ADTS_HEADER_SIZE
,
1838 return p_bak_block
; /* OOM, send the (incorrect) original frame */
1840 block_Release( p_bak_block
); /* we don't need the copy anymore */
1843 uint8_t *p_buffer
= p_new_block
->p_buffer
;
1847 p_buffer
[1] = 0xf1; /* 0xf0 | 0x00 | 0x00 | 0x01 */
1848 p_buffer
[2] = (i_profile
<< 6) | ((i_index
& 0x0f) << 2) | ((i_channels
>> 2) & 0x01) ;
1849 p_buffer
[3] = (i_channels
<< 6) | ((p_data
->i_buffer
>> 11) & 0x03);
1851 /* variable header (starts at last 2 bits of 4th byte) */
1853 int i_fullness
= 0x7ff; /* 0x7ff means VBR */
1854 /* XXX: We should check if it's CBR or VBR, but no known implementation
1855 * do that, and it's a pain to calculate this field */
1857 p_buffer
[4] = p_data
->i_buffer
>> 3;
1858 p_buffer
[5] = ((p_data
->i_buffer
& 0x07) << 5) | ((i_fullness
>> 6) & 0x1f);
1859 p_buffer
[6] = ((i_fullness
& 0x3f) << 2) /* | 0xfc */;
1864 static void TSSchedule( sout_mux_t
*p_mux
, sout_buffer_chain_t
*p_chain_ts
,
1865 mtime_t i_pcr_length
, mtime_t i_pcr_dts
)
1867 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
1868 sout_buffer_chain_t new_chain
;
1869 int i_packet_count
= p_chain_ts
->i_depth
;
1872 BufferChainInit( &new_chain
);
1874 if ( i_pcr_length
<= 0 )
1876 i_pcr_length
= i_packet_count
;
1879 for( i
= 0; i
< i_packet_count
; i
++ )
1881 block_t
*p_ts
= BufferChainGet( p_chain_ts
);
1882 mtime_t i_new_dts
= i_pcr_dts
+ i_pcr_length
* i
/ i_packet_count
;
1884 BufferChainAppend( &new_chain
, p_ts
);
1887 p_ts
->i_dts
+ p_sys
->i_dts_delay
* 2/3 < i_new_dts
)
1889 mtime_t i_max_diff
= i_new_dts
- p_ts
->i_dts
;
1890 mtime_t i_cut_dts
= p_ts
->i_dts
;
1892 p_ts
= BufferChainPeek( p_chain_ts
);
1894 i_new_dts
= i_pcr_dts
+ i_pcr_length
* i
/ i_packet_count
;
1895 while ( p_ts
!= NULL
&& i_new_dts
- p_ts
->i_dts
>= i_max_diff
)
1897 p_ts
= BufferChainGet( p_chain_ts
);
1898 i_max_diff
= i_new_dts
- p_ts
->i_dts
;
1899 i_cut_dts
= p_ts
->i_dts
;
1900 BufferChainAppend( &new_chain
, p_ts
);
1902 p_ts
= BufferChainPeek( p_chain_ts
);
1904 i_new_dts
= i_pcr_dts
+ i_pcr_length
* i
/ i_packet_count
;
1906 msg_Dbg( p_mux
, "adjusting rate at %"PRId64
"/%"PRId64
" (%d/%d)",
1907 i_cut_dts
- i_pcr_dts
, i_pcr_length
, new_chain
.i_depth
,
1908 p_chain_ts
->i_depth
);
1909 if ( new_chain
.i_depth
)
1910 TSDate( p_mux
, &new_chain
,
1911 i_cut_dts
- i_pcr_dts
,
1913 if ( p_chain_ts
->i_depth
)
1915 p_chain_ts
, i_pcr_dts
+ i_pcr_length
- i_cut_dts
,
1921 if ( new_chain
.i_depth
)
1922 TSDate( p_mux
, &new_chain
, i_pcr_length
, i_pcr_dts
);
1925 static void TSDate( sout_mux_t
*p_mux
, sout_buffer_chain_t
*p_chain_ts
,
1926 mtime_t i_pcr_length
, mtime_t i_pcr_dts
)
1928 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
1929 int i_packet_count
= p_chain_ts
->i_depth
;
1932 if ( i_pcr_length
/ 1000 > 0 )
1934 int i_bitrate
= ((uint64_t)i_packet_count
* 188 * 8000)
1935 / (uint64_t)(i_pcr_length
/ 1000);
1936 if ( p_sys
->i_bitrate_max
&& p_sys
->i_bitrate_max
< i_bitrate
)
1938 msg_Warn( p_mux
, "max bitrate exceeded at %"PRId64
1939 " (%d bi/s for %d pkt in %"PRId64
" us)",
1940 i_pcr_dts
+ p_sys
->i_shaping_delay
* 3 / 2 - mdate(),
1941 i_bitrate
, i_packet_count
, i_pcr_length
);
1946 msg_Dbg( p_mux
, "starting at %"PRId64
1947 " (%d bi/s for %d packets in %"PRId64
" us)",
1948 i_pcr_dts
+ p_sys
->i_shaping_delay
* 3 / 2 - mdate(),
1949 i_bitrate
, i_packet_count
, i_pcr_length
);
1955 /* This shouldn't happen, but happens in some rare heavy load
1956 * and packet losses conditions. */
1957 i_pcr_length
= i_packet_count
;
1960 /* msg_Dbg( p_mux, "real pck=%d", i_packet_count ); */
1961 for( i
= 0; i
< i_packet_count
; i
++ )
1963 block_t
*p_ts
= BufferChainGet( p_chain_ts
);
1964 mtime_t i_new_dts
= i_pcr_dts
+ i_pcr_length
* i
/ i_packet_count
;
1966 p_ts
->i_dts
= i_new_dts
;
1967 p_ts
->i_length
= i_pcr_length
/ i_packet_count
;
1969 if( p_ts
->i_flags
& BLOCK_FLAG_CLOCK
)
1971 /* msg_Dbg( p_mux, "pcr=%lld ms", p_ts->i_dts / 1000 ); */
1972 TSSetPCR( p_ts
, p_ts
->i_dts
- p_sys
->i_dts_delay
);
1974 if( p_ts
->i_flags
& BLOCK_FLAG_SCRAMBLED
)
1976 vlc_mutex_lock( &p_sys
->csa_lock
);
1977 csa_Encrypt( p_sys
->csa
, p_ts
->p_buffer
, p_sys
->i_csa_pkt_size
);
1978 vlc_mutex_unlock( &p_sys
->csa_lock
);
1982 p_ts
->i_dts
+= p_sys
->i_shaping_delay
* 3 / 2;
1984 sout_AccessOutWrite( p_mux
->p_access
, p_ts
);
1988 static block_t
*TSNew( sout_mux_t
*p_mux
, ts_stream_t
*p_stream
,
1992 block_t
*p_pes
= p_stream
->chain_pes
.p_first
;
1995 bool b_new_pes
= false;
1996 bool b_adaptation_field
= false;
1998 int i_payload_max
= 184 - ( b_pcr
? 8 : 0 );
2001 if( p_stream
->i_pes_used
<= 0 )
2005 i_payload
= __MIN( (int)p_pes
->i_buffer
- p_stream
->i_pes_used
,
2008 if( b_pcr
|| i_payload
< i_payload_max
)
2010 b_adaptation_field
= true;
2013 p_ts
= block_New( p_mux
, 188 );
2015 if (b_new_pes
&& !(p_pes
->i_flags
& BLOCK_FLAG_NO_KEYFRAME
) && p_pes
->i_flags
& BLOCK_FLAG_TYPE_I
)
2017 p_ts
->i_flags
|= BLOCK_FLAG_TYPE_I
;
2020 p_ts
->i_dts
= p_pes
->i_dts
;
2022 p_ts
->p_buffer
[0] = 0x47;
2023 p_ts
->p_buffer
[1] = ( b_new_pes
? 0x40 : 0x00 ) |
2024 ( ( p_stream
->i_pid
>> 8 )&0x1f );
2025 p_ts
->p_buffer
[2] = p_stream
->i_pid
& 0xff;
2026 p_ts
->p_buffer
[3] = ( b_adaptation_field
? 0x30 : 0x10 ) |
2027 p_stream
->i_continuity_counter
;
2029 p_stream
->i_continuity_counter
= (p_stream
->i_continuity_counter
+1)%16;
2030 p_stream
->b_discontinuity
= (p_pes
->i_flags
& BLOCK_FLAG_DISCONTINUITY
);
2032 if( b_adaptation_field
)
2038 int i_stuffing
= i_payload_max
- i_payload
;
2040 p_ts
->i_flags
|= BLOCK_FLAG_CLOCK
;
2042 p_ts
->p_buffer
[4] = 7 + i_stuffing
;
2043 p_ts
->p_buffer
[5] = 0x10; /* flags */
2044 if( p_stream
->b_discontinuity
)
2046 p_ts
->p_buffer
[5] |= 0x80; /* flag TS dicontinuity */
2047 p_stream
->b_discontinuity
= false;
2049 p_ts
->p_buffer
[6] = ( 0 )&0xff;
2050 p_ts
->p_buffer
[7] = ( 0 )&0xff;
2051 p_ts
->p_buffer
[8] = ( 0 )&0xff;
2052 p_ts
->p_buffer
[9] = ( 0 )&0xff;
2053 p_ts
->p_buffer
[10]= ( ( 0 )&0x80 ) | 0x7e;
2054 p_ts
->p_buffer
[11]= 0;
2056 for( i
= 12; i
< 12 + i_stuffing
; i
++ )
2058 p_ts
->p_buffer
[i
] = 0xff;
2063 int i_stuffing
= i_payload_max
- i_payload
;
2065 p_ts
->p_buffer
[4] = i_stuffing
- 1;
2066 if( i_stuffing
> 1 )
2068 p_ts
->p_buffer
[5] = 0x00;
2069 for( i
= 6; i
< 6 + i_stuffing
- 2; i
++ )
2071 p_ts
->p_buffer
[i
] = 0xff;
2078 memcpy( &p_ts
->p_buffer
[188 - i_payload
],
2079 &p_pes
->p_buffer
[p_stream
->i_pes_used
], i_payload
);
2081 p_stream
->i_pes_used
+= i_payload
;
2082 p_stream
->i_pes_dts
= p_pes
->i_dts
+ p_pes
->i_length
*
2083 p_stream
->i_pes_used
/ p_pes
->i_buffer
;
2084 p_stream
->i_pes_length
-= p_pes
->i_length
* i_payload
/ p_pes
->i_buffer
;
2086 if( p_stream
->i_pes_used
>= (int)p_pes
->i_buffer
)
2088 p_pes
= BufferChainGet( &p_stream
->chain_pes
);
2089 block_Release( p_pes
);
2091 p_pes
= p_stream
->chain_pes
.p_first
;
2094 p_stream
->i_pes_dts
= p_pes
->i_dts
;
2095 p_stream
->i_pes_length
= 0;
2098 p_stream
->i_pes_length
+= p_pes
->i_length
;
2100 p_pes
= p_pes
->p_next
;
2105 p_stream
->i_pes_dts
= 0;
2106 p_stream
->i_pes_length
= 0;
2108 p_stream
->i_pes_used
= 0;
2114 static void TSSetPCR( block_t
*p_ts
, mtime_t i_dts
)
2116 mtime_t i_pcr
= 9 * i_dts
/ 100;
2118 p_ts
->p_buffer
[6] = ( i_pcr
>> 25 )&0xff;
2119 p_ts
->p_buffer
[7] = ( i_pcr
>> 17 )&0xff;
2120 p_ts
->p_buffer
[8] = ( i_pcr
>> 9 )&0xff;
2121 p_ts
->p_buffer
[9] = ( i_pcr
>> 1 )&0xff;
2122 p_ts
->p_buffer
[10]|= ( i_pcr
<< 7 )&0x80;
2126 static void TSSetConstraints( sout_mux_t
*p_mux
, sout_buffer_chain_t
*c
,
2127 mtime_t i_length
, int i_bitrate_min
,
2130 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
2131 sout_buffer_chain_t s
= *c
;
2134 int i_packets_min
= 0;
2135 int i_packets_max
= 0;
2142 i_packets
= c
->i_depth
;
2143 i_packets_min
= ( (int64_t)i_bitrate_min
* i_length
/ 8 / 1000000 + 187 ) / 188;
2144 i_packets_max
= ( (int64_t)i_bitrate_max
* i_length
/ 8 / 1000000 + 187 ) / 188;
2146 if( i_packets
< i_packets_min
&& i_packets_min
> 0 )
2149 int i_div
= ( i_packets_min
- i_packets
) / i_packets
;
2150 int i_mod
= ( i_packets_min
- i_packets
) % i_packets
;
2153 /* We need to pad with null packets (pid=0x1fff)
2154 * We try to melt null packets with true packets */
2156 "packets=%d but min=%d -> adding %d packets of padding",
2157 i_packets
, i_packets_min
, i_packets_min
- i_packets
);
2159 BufferChainInit( c
);
2160 while( ( p_pk
= BufferChainGet( &s
) ) )
2164 BufferChainAppend( c
, p_pk
);
2166 i_null
= i_div
+ ( i_rest
+ i_mod
) / i_packets
;
2168 for( i
= 0; i
< i_null
; i
++ )
2172 p_null
= sout_BufferNew( p_mux
->p_sout
, 188 );
2173 p_null
->p_buffer
[0] = 0x47;
2174 p_null
->p_buffer
[1] = 0x1f;
2175 p_null
->p_buffer
[2] = 0xff;
2176 p_null
->p_buffer
[3] = 0x10 | p_sys
->i_null_continuity_counter
;
2177 memset( &p_null
->p_buffer
[4], 0, 184 );
2178 p_sys
->i_null_continuity_counter
=
2179 ( p_sys
->i_null_continuity_counter
+ 1 ) % 16;
2181 BufferChainAppend( c
, p_null
);
2184 i_rest
= ( i_rest
+ i_mod
) % i_packets
;
2187 else if( i_packets
> i_packets_max
&& i_packets_max
> 0 )
2192 /* Arg, we need to drop packets, I don't do something clever (like
2193 * dropping complete pid, b frames, ... ), I just get the right amount
2194 * of packets and discard the others */
2196 "packets=%d but max=%d -> removing %d packets -> stream broken",
2197 i_packets
, i_packets_max
, i_packets
- i_packets_max
);
2199 BufferChainInit( c
);
2200 for( i
= 0; i
< i_packets_max
; i
++ )
2202 BufferChainAppend( c
, BufferChainGet( &s
) );
2205 while( ( p_pk
= BufferChainGet( &s
) ) )
2207 sout_BufferDelete( p_mux
->p_sout
, p_pk
);
2213 static void PEStoTS( sout_instance_t
*p_sout
,
2214 sout_buffer_chain_t
*c
, block_t
*p_pes
,
2215 ts_stream_t
*p_stream
)
2222 /* get PES total size */
2223 i_size
= p_pes
->i_buffer
;
2224 p_data
= p_pes
->p_buffer
;
2230 int b_adaptation_field
;
2234 p_ts
= block_New( p_sout
, 188 );
2237 * 1b transport_error_indicator
2238 * 1b payload_unit_start
2239 * 1b transport_priority
2241 * 2b transport_scrambling_control
2242 * 2b if adaptation_field 0x03 else 0x01
2243 * 4b continuity_counter
2246 i_copy
= __MIN( i_size
, 184 );
2247 b_adaptation_field
= i_size
< 184 ? true : false;
2249 p_ts
->p_buffer
[0] = 0x47;
2250 p_ts
->p_buffer
[1] = ( b_new_pes
? 0x40 : 0x00 )|
2251 ( ( p_stream
->i_pid
>> 8 )&0x1f );
2252 p_ts
->p_buffer
[2] = p_stream
->i_pid
& 0xff;
2253 p_ts
->p_buffer
[3] = ( b_adaptation_field
? 0x30 : 0x10 )|
2254 p_stream
->i_continuity_counter
;
2257 p_stream
->i_continuity_counter
= (p_stream
->i_continuity_counter
+1)%16;
2259 if( b_adaptation_field
)
2261 int i_stuffing
= 184 - i_copy
;
2264 p_ts
->p_buffer
[4] = i_stuffing
- 1;
2265 if( i_stuffing
> 1 )
2267 p_ts
->p_buffer
[5] = 0x00;
2268 if( p_stream
->b_discontinuity
)
2270 p_ts
->p_buffer
[5] |= 0x80;
2271 p_stream
->b_discontinuity
= false;
2273 for( i
= 6; i
< 6 + i_stuffing
- 2; i
++ )
2275 p_ts
->p_buffer
[i
] = 0xff;
2280 memcpy( &p_ts
->p_buffer
[188 - i_copy
], p_data
, i_copy
);
2284 BufferChainAppend( c
, p_ts
);
2288 block_t
*p_next
= p_pes
->p_next
;
2290 p_pes
->p_next
= NULL
;
2291 block_Release( p_pes
);
2292 if( p_next
== NULL
)
2298 i_size
= p_pes
->i_buffer
;
2299 p_data
= p_pes
->p_buffer
;
2306 static block_t
*WritePSISection( sout_instance_t
*p_sout
,
2307 dvbpsi_psi_section_t
* p_section
)
2310 block_t
*p_psi
, *p_first
= NULL
;
2316 i_size
= (uint32_t)( p_section
->p_payload_end
- p_section
->p_data
)+
2317 ( p_section
->b_syntax_indicator
? 4 : 0 );
2319 p_psi
= block_New( p_sout
, i_size
+ 1 );
2322 p_psi
->i_length
= 0;
2323 p_psi
->i_buffer
= i_size
+ 1;
2325 p_psi
->p_buffer
[0] = 0; /* pointer */
2326 memcpy( p_psi
->p_buffer
+ 1,
2330 block_ChainAppend( &p_first
, p_psi
);
2332 p_section
= p_section
->p_next
;
2338 static void GetPAT( sout_mux_t
*p_mux
,
2339 sout_buffer_chain_t
*c
)
2341 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
2344 dvbpsi_psi_section_t
*p_section
;
2347 dvbpsi_InitPAT( &pat
, p_sys
->i_tsid
, p_sys
->i_pat_version_number
,
2348 1 ); /* b_current_next */
2349 /* add all programs */
2350 for ( i
= 0; i
< p_sys
->i_num_pmt
; i
++ )
2351 dvbpsi_PATAddProgram( &pat
,
2352 p_sys
->i_pmt_program_number
[i
],
2353 p_sys
->pmt
[i
].i_pid
);
2355 p_section
= dvbpsi_GenPATSections( &pat
,
2356 0 ); /* max program per section */
2358 p_pat
= WritePSISection( p_mux
->p_sout
, p_section
);
2360 PEStoTS( p_mux
->p_sout
, c
, p_pat
, &p_sys
->pat
);
2362 dvbpsi_DeletePSISections( p_section
);
2363 dvbpsi_EmptyPAT( &pat
);
2366 static uint32_t GetDescriptorLength24b( int i_length
)
2368 uint32_t i_l1
, i_l2
, i_l3
;
2370 i_l1
= i_length
&0x7f;
2371 i_l2
= ( i_length
>> 7 )&0x7f;
2372 i_l3
= ( i_length
>> 14 )&0x7f;
2374 return( 0x808000 | ( i_l3
<< 16 ) | ( i_l2
<< 8 ) | i_l1
);
2377 static void GetPMT( sout_mux_t
*p_mux
, sout_buffer_chain_t
*c
)
2379 sout_mux_sys_t
*p_sys
= p_mux
->p_sys
;
2380 block_t
*p_pmt
[MAX_PMT
];
2382 dvbpsi_pmt_es_t
*p_es
;
2383 dvbpsi_psi_section_t
*p_section
[MAX_PMT
];
2388 int *p_usepid
= NULL
;
2390 #ifdef HAVE_DVBPSI_SDT
2394 dvbpsi_psi_section_t
* p_section2
;
2395 dvbpsi_sdt_service_t
*p_service
;
2397 uint8_t *psz_sdt_desc
;
2400 if( p_sys
->dvbpmt
== NULL
)
2402 p_sys
->dvbpmt
= malloc( p_sys
->i_num_pmt
* sizeof(dvbpsi_pmt_t
) );
2403 if( !p_sys
->dvbpmt
)
2408 #ifdef HAVE_DVBPSI_SDT
2410 dvbpsi_InitSDT( &sdt
, p_sys
->i_tsid
, 1, 1, p_sys
->i_netid
);
2413 for( i
= 0; i
< p_sys
->i_num_pmt
; i
++ )
2415 dvbpsi_InitPMT( &p_sys
->dvbpmt
[i
],
2416 p_sys
->i_pmt_program_number
[i
], /* program number */
2417 p_sys
->i_pmt_version_number
,
2418 1, /* b_current_next */
2421 #ifdef HAVE_DVBPSI_SDT
2424 p_service
= dvbpsi_SDTAddService( &sdt
,
2425 p_sys
->i_pmt_program_number
[i
], /* service id */
2426 0, /* eit schedule */
2427 0, /* eit present */
2428 4, /* running status ("4=RUNNING") */
2431 #define psz_sdtprov p_sys->sdt_descriptors[i].psz_provider
2432 #define psz_sdtserv p_sys->sdt_descriptors[i].psz_service_name
2434 /* FIXME: Ineffecient malloc's & ugly code...... */
2435 if( ( psz_sdtprov
!= NULL
) && ( psz_sdtserv
!= NULL
) )
2437 psz_sdt_desc
= malloc( 3 + strlen(psz_sdtprov
)
2438 + strlen(psz_sdtserv
) );
2441 psz_sdt_desc
[0] = 0x01; /* digital television service */
2443 /* service provider name length */
2444 psz_sdt_desc
[1] = (char)strlen(psz_sdtprov
);
2445 memcpy( &psz_sdt_desc
[2], psz_sdtprov
, strlen(psz_sdtprov
) );
2447 /* service name length */
2448 psz_sdt_desc
[ 2 + strlen(psz_sdtprov
) ]
2449 = (char)strlen(psz_sdtserv
);
2450 memcpy( &psz_sdt_desc
[3+strlen(psz_sdtprov
)], psz_sdtserv
,
2451 strlen(psz_sdtserv
) );
2453 dvbpsi_SDTServiceAddDescriptor( p_service
, 0x48,
2454 3 + strlen(psz_sdtprov
) + strlen(psz_sdtserv
),
2455 (uint8_t *)psz_sdt_desc
);
2456 free( psz_sdt_desc
);
2457 psz_sdt_desc
= NULL
;
2466 if( p_sys
->i_mpeg4_streams
> 0 )
2470 bits_buffer_t bits_fix_IOD
;
2472 /* Make valgrind happy : it works at byte level not bit one so
2473 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
2474 * working (needed when fixing some bits) */
2475 memset( iod
, 0, 4096 );
2477 bits_initwrite( &bits
, 4096, iod
);
2478 /* IOD_label_scope */
2479 bits_write( &bits
, 8, 0x11 );
2481 bits_write( &bits
, 8, 0x01 );
2482 /* InitialObjectDescriptor */
2483 bits_align( &bits
);
2484 bits_write( &bits
, 8, 0x02 ); /* tag */
2485 bits_fix_IOD
= bits
; /* save states to fix length later */
2486 bits_write( &bits
, 24,
2487 GetDescriptorLength24b( 0 ) ); /* variable length (fixed later) */
2488 bits_write( &bits
, 10, 0x01 ); /* ObjectDescriptorID */
2489 bits_write( &bits
, 1, 0x00 ); /* URL Flag */
2490 bits_write( &bits
, 1, 0x00 ); /* includeInlineProfileLevelFlag */
2491 bits_write( &bits
, 4, 0x0f ); /* reserved */
2492 bits_write( &bits
, 8, 0xff ); /* ODProfile (no ODcapability ) */
2493 bits_write( &bits
, 8, 0xff ); /* sceneProfile */
2494 bits_write( &bits
, 8, 0xfe ); /* audioProfile (unspecified) */
2495 bits_write( &bits
, 8, 0xfe ); /* visualProfile( // ) */
2496 bits_write( &bits
, 8, 0xff ); /* graphicProfile (no ) */
2497 for( i_stream
= 0; i_stream
< p_mux
->i_nb_inputs
; i_stream
++ )
2499 ts_stream_t
*p_stream
;
2500 p_stream
= (ts_stream_t
*)p_mux
->pp_inputs
[i_stream
]->p_sys
;
2502 if( p_stream
->i_stream_id
== 0xfa ||
2503 p_stream
->i_stream_id
== 0xfb ||
2504 p_stream
->i_stream_id
== 0xfe )
2506 bits_buffer_t bits_fix_ESDescr
, bits_fix_Decoder
;
2508 bits_align( &bits
);
2509 bits_write( &bits
, 8, 0x03 ); /* ES_DescrTag */
2510 bits_fix_ESDescr
= bits
;
2511 bits_write( &bits
, 24,
2512 GetDescriptorLength24b( 0 ) ); /* variable size */
2513 bits_write( &bits
, 16, p_stream
->i_es_id
);
2514 bits_write( &bits
, 1, 0x00 ); /* streamDependency */
2515 bits_write( &bits
, 1, 0x00 ); /* URL Flag */
2516 bits_write( &bits
, 1, 0x00 ); /* OCRStreamFlag */
2517 bits_write( &bits
, 5, 0x1f ); /* streamPriority */
2519 /* DecoderConfigDesciptor */
2520 bits_align( &bits
);
2521 bits_write( &bits
, 8, 0x04 ); /* DecoderConfigDescrTag */
2522 bits_fix_Decoder
= bits
;
2523 bits_write( &bits
, 24, GetDescriptorLength24b( 0 ) );
2524 if( p_stream
->i_stream_type
== 0x10 )
2526 bits_write( &bits
, 8, 0x20 ); /* Visual 14496-2 */
2527 bits_write( &bits
, 6, 0x04 ); /* VisualStream */
2529 else if( p_stream
->i_stream_type
== 0x1b )
2531 bits_write( &bits
, 8, 0x21 ); /* Visual 14496-2 */
2532 bits_write( &bits
, 6, 0x04 ); /* VisualStream */
2534 else if( p_stream
->i_stream_type
== 0x11 ||
2535 p_stream
->i_stream_type
== 0x0f )
2537 bits_write( &bits
, 8, 0x40 ); /* Audio 14496-3 */
2538 bits_write( &bits
, 6, 0x05 ); /* AudioStream */
2540 else if( p_stream
->i_stream_type
== 0x12 &&
2541 p_stream
->i_codec
== VLC_CODEC_SUBT
)
2543 bits_write( &bits
, 8, 0x0B ); /* Text Stream */
2544 bits_write( &bits
, 6, 0x04 ); /* VisualStream */
2548 bits_write( &bits
, 8, 0x00 );
2549 bits_write( &bits
, 6, 0x00 );
2551 msg_Err( p_mux
->p_sout
,"Unsupported stream_type => "
2554 bits_write( &bits
, 1, 0x00 ); /* UpStream */
2555 bits_write( &bits
, 1, 0x01 ); /* reserved */
2556 bits_write( &bits
, 24, 1024 * 1024 ); /* bufferSizeDB */
2557 bits_write( &bits
, 32, 0x7fffffff ); /* maxBitrate */
2558 bits_write( &bits
, 32, 0 ); /* avgBitrate */
2560 if( p_stream
->i_decoder_specific_info
> 0 )
2563 /* DecoderSpecificInfo */
2564 bits_align( &bits
);
2565 bits_write( &bits
, 8, 0x05 ); /* tag */
2566 bits_write( &bits
, 24, GetDescriptorLength24b(
2567 p_stream
->i_decoder_specific_info
) );
2568 for( i
= 0; i
< p_stream
->i_decoder_specific_info
; i
++ )
2570 bits_write( &bits
, 8,
2571 ((uint8_t*)p_stream
->p_decoder_specific_info
)[i
] );
2574 /* fix Decoder length */
2575 bits_write( &bits_fix_Decoder
, 24,
2576 GetDescriptorLength24b( bits
.i_data
-
2577 bits_fix_Decoder
.i_data
- 3 ) );
2579 /* SLConfigDescriptor : predefined (0x01) */
2580 bits_align( &bits
);
2581 bits_write( &bits
, 8, 0x06 ); /* tag */
2582 bits_write( &bits
, 24, GetDescriptorLength24b( 8 ) );
2583 bits_write( &bits
, 8, 0x01 );/* predefined */
2584 bits_write( &bits
, 1, 0 ); /* durationFlag */
2585 bits_write( &bits
, 32, 0 ); /* OCRResolution */
2586 bits_write( &bits
, 8, 0 ); /* OCRLength */
2587 bits_write( &bits
, 8, 0 ); /* InstantBitrateLength */
2588 bits_align( &bits
);
2590 /* fix ESDescr length */
2591 bits_write( &bits_fix_ESDescr
, 24,
2592 GetDescriptorLength24b( bits
.i_data
-
2593 bits_fix_ESDescr
.i_data
- 3 ) );
2596 bits_align( &bits
);
2597 /* fix IOD length */
2598 bits_write( &bits_fix_IOD
, 24,
2599 GetDescriptorLength24b( bits
.i_data
-
2600 bits_fix_IOD
.i_data
- 3 ) );
2602 #if 0 /* FIXME!!! This can't possibly work */
2603 i_pidinput
= p_mux
->pp_inputs
[i
]->p_fmt
->i_id
;
2604 p_usepid
= bsearch( &i_pidinput
, p_sys
->pmtmap
, p_sys
->i_pmtslots
,
2605 sizeof(pmt_map_t
), intcompare
);
2606 p_usepid
= bsearch( &p_usepid
, p_sys
->pmtmap
, p_sys
->i_num_pmt
,
2607 sizeof(pmt_map_t
), pmtcompare
);
2608 if( p_usepid
!= NULL
)
2609 dvbpsi_PMTAddDescriptor(
2610 &p_sys
->dvbpmt
[((pmt_map_t
*)p_usepid
)->i_prog
], 0x1d,
2611 bits
.i_data
, bits
.p_data
);
2613 msg_Err( p_mux
, "Received an unmapped PID" );
2615 dvbpsi_PMTAddDescriptor( &p_sys
->dvbpmt
[0], 0x1d, bits
.i_data
,
2620 for( i_stream
= 0; i_stream
< p_mux
->i_nb_inputs
; i_stream
++ )
2622 ts_stream_t
*p_stream
;
2624 p_stream
= (ts_stream_t
*)p_mux
->pp_inputs
[i_stream
]->p_sys
;
2626 i_pidinput
= p_mux
->pp_inputs
[i_stream
]->p_fmt
->i_id
;
2627 p_usepid
= bsearch( &i_pidinput
, p_sys
->pmtmap
, p_sys
->i_pmtslots
,
2628 sizeof(pmt_map_t
), intcompare
);
2630 if( p_usepid
!= NULL
)
2631 p_es
= dvbpsi_PMTAddES(
2632 &p_sys
->dvbpmt
[((pmt_map_t
*)p_usepid
)->i_prog
],
2633 p_stream
->i_stream_type
, p_stream
->i_pid
);
2635 /* If there's an error somewhere, dump it to the first pmt */
2636 p_es
= dvbpsi_PMTAddES( &p_sys
->dvbpmt
[0], p_stream
->i_stream_type
,
2639 if( p_stream
->i_stream_id
== 0xfa || p_stream
->i_stream_id
== 0xfb )
2644 es_id
[0] = (p_stream
->i_es_id
>> 8)&0xff;
2645 es_id
[1] = (p_stream
->i_es_id
)&0xff;
2646 dvbpsi_PMTESAddDescriptor( p_es
, 0x1f, 2, es_id
);
2648 else if( p_stream
->i_stream_type
== 0xa0 )
2651 int i_extra
= __MIN( p_stream
->i_decoder_specific_info
, 502 );
2653 /* private DIV3 descripor */
2654 memcpy( &data
[0], &p_stream
->i_bih_codec
, 4 );
2655 data
[4] = ( p_stream
->i_bih_width
>> 8 )&0xff;
2656 data
[5] = ( p_stream
->i_bih_width
)&0xff;
2657 data
[6] = ( p_stream
->i_bih_height
>> 8 )&0xff;
2658 data
[7] = ( p_stream
->i_bih_height
)&0xff;
2659 data
[8] = ( i_extra
>> 8 )&0xff;
2660 data
[9] = ( i_extra
)&0xff;
2663 memcpy( &data
[10], p_stream
->p_decoder_specific_info
, i_extra
);
2666 /* 0xa0 is private */
2667 dvbpsi_PMTESAddDescriptor( p_es
, 0xa0, i_extra
+ 10, data
);
2669 else if( p_stream
->i_stream_type
== 0x81 )
2671 uint8_t format
[4] = { 0x41, 0x43, 0x2d, 0x33 };
2673 /* "registration" descriptor : "AC-3" */
2674 dvbpsi_PMTESAddDescriptor( p_es
, 0x05, 4, format
);
2676 else if( p_stream
->i_codec
== VLC_CODEC_DIRAC
)
2678 /* Dirac registration descriptor */
2680 uint8_t data
[4] = { 'd', 'r', 'a', 'c' };
2681 dvbpsi_PMTESAddDescriptor( p_es
, 0x05, 4, data
);
2683 else if( p_stream
->i_codec
== VLC_CODEC_DTS
)
2685 /* DTS registration descriptor (ETSI TS 101 154 Annex F) */
2687 /* DTS format identifier, frame size 1024 - FIXME */
2688 uint8_t data
[4] = { 0x44, 0x54, 0x53, 0x32 };
2689 dvbpsi_PMTESAddDescriptor( p_es
, 0x05, 4, data
);
2691 else if( p_stream
->i_codec
== VLC_CODEC_EAC3
)
2693 uint8_t data
[1] = { 0x00 };
2694 dvbpsi_PMTESAddDescriptor( p_es
, 0x7a, 1, data
);
2696 else if( p_stream
->i_codec
== VLC_CODEC_TELETEXT
)
2698 if( p_stream
->i_decoder_specific_info
)
2700 dvbpsi_PMTESAddDescriptor( p_es
, 0x56,
2701 p_stream
->i_decoder_specific_info
,
2702 p_stream
->p_decoder_specific_info
);
2706 else if( p_stream
->i_codec
== VLC_CODEC_DVBS
)
2709 if( p_stream
->i_decoder_specific_info
)
2711 /* pass-through from the TS demux */
2712 dvbpsi_PMTESAddDescriptor( p_es
, 0x59,
2713 p_stream
->i_decoder_specific_info
,
2714 p_stream
->p_decoder_specific_info
);
2718 /* from the dvbsub transcoder */
2719 dvbpsi_subtitling_dr_t descr
;
2720 dvbpsi_subtitle_t sub
;
2721 dvbpsi_descriptor_t
*p_descr
;
2723 memcpy( sub
.i_iso6392_language_code
, p_stream
->lang
, 3 );
2724 sub
.i_subtitling_type
= 0x10; /* no aspect-ratio criticality */
2725 sub
.i_composition_page_id
= p_stream
->i_es_id
& 0xFF;
2726 sub
.i_ancillary_page_id
= p_stream
->i_es_id
>> 16;
2728 descr
.i_subtitles_number
= 1;
2729 descr
.p_subtitle
[0] = sub
;
2731 p_descr
= dvbpsi_GenSubtitlingDr( &descr
, 0 );
2732 /* Work around bug in old libdvbpsi */ p_descr
->i_length
= 8;
2733 dvbpsi_PMTESAddDescriptor( p_es
, p_descr
->i_tag
,
2734 p_descr
->i_length
, p_descr
->p_data
);
2739 if( p_stream
->lang
[0] != 0 )
2741 uint8_t data
[4*p_stream
->i_langs
];
2743 /* I construct the content myself, way faster than looking at
2744 * over complicated/mind broken libdvbpsi way */
2745 for(i
= 0; i
< p_stream
->i_langs
; i
++ )
2747 data
[i
*4+0] = p_stream
->lang
[i
*3+0];
2748 data
[i
*4+1] = p_stream
->lang
[i
*3+1];
2749 data
[i
*4+2] = p_stream
->lang
[i
*3+2];
2750 data
[i
*4+3] = 0x00; /* audio type: 0x00 undefined */
2752 dvbpsi_PMTESAddDescriptor( p_es
, 0x0a, 4*p_stream
->i_langs
, data
);
2756 for( i
= 0; i
< p_sys
->i_num_pmt
; i
++ )
2758 p_section
[i
] = dvbpsi_GenPMTSections( &p_sys
->dvbpmt
[i
] );
2759 p_pmt
[i
] = WritePSISection( p_mux
->p_sout
, p_section
[i
] );
2760 PEStoTS( p_mux
->p_sout
, c
, p_pmt
[i
], &p_sys
->pmt
[i
] );
2761 dvbpsi_DeletePSISections( p_section
[i
] );
2762 dvbpsi_EmptyPMT( &p_sys
->dvbpmt
[i
] );
2765 #ifdef HAVE_DVBPSI_SDT
2768 p_section2
= dvbpsi_GenSDTSections( &sdt
);
2769 p_sdt
= WritePSISection( p_mux
->p_sout
, p_section2
);
2770 PEStoTS( p_mux
->p_sout
, c
, p_sdt
, &p_sys
->sdt
);
2771 dvbpsi_DeletePSISections( p_section2
);
2772 dvbpsi_EmptySDT( &sdt
);