1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001-2005, 2015 VLC authors and VideoLAN
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
24 #include <vlc_common.h>
25 #include <vlc_block.h>
28 # include <dvbpsi/dvbpsi.h>
29 # include <dvbpsi/demux.h>
30 # include <dvbpsi/descriptor.h>
31 # include <dvbpsi/pat.h>
32 # include <dvbpsi/pmt.h>
33 # include <dvbpsi/sdt.h>
34 # include <dvbpsi/dr.h>
35 # include <dvbpsi/psi.h>
37 #include "dvbpsi_compat.h"
45 #include "../../codec/jpeg2000.h"
49 block_t
*WritePSISection( dvbpsi_psi_section_t
* p_section
)
51 block_t
*p_psi
, *p_first
= NULL
;
55 int i_size
= (uint32_t)(p_section
->p_payload_end
- p_section
->p_data
) +
56 (p_section
->b_syntax_indicator
? 4 : 0);
58 p_psi
= block_Alloc( i_size
+ 1 );
64 p_psi
->i_buffer
= i_size
+ 1;
66 p_psi
->p_buffer
[0] = 0; /* pointer */
67 memcpy( p_psi
->p_buffer
+ 1,
71 block_ChainAppend( &p_first
, p_psi
);
73 p_section
= p_section
->p_next
;
80 block_ChainRelease( p_first
);
84 void BuildPAT( dvbpsi_t
*p_dvbpsi
,
85 void *p_opaque
, PEStoTSCallback pf_callback
,
86 int i_tsid
, int i_pat_version_number
,
87 tsmux_stream_t
*p_pat
,
88 unsigned i_programs
, tsmux_stream_t
*p_pmt
, const int *pi_programs_number
)
91 dvbpsi_psi_section_t
*p_section
;
93 dvbpsi_pat_init( &patpsi
, i_tsid
, i_pat_version_number
, true /* b_current_next */ );
94 /* add all programs */
95 for (unsigned i
= 0; i
< i_programs
; i
++ )
96 dvbpsi_pat_program_add( &patpsi
, pi_programs_number
[i
], p_pmt
[i
].i_pid
);
98 p_section
= dvbpsi_pat_sections_generate( p_dvbpsi
, &patpsi
, 0 );
99 if( likely(p_section
) )
101 block_t
*p_block
= WritePSISection( p_section
);
102 if( likely(p_block
) )
104 PEStoTS( p_opaque
, pf_callback
, p_block
, p_pat
->i_pid
,
105 &p_pat
->b_discontinuity
, &p_pat
->i_continuity_counter
);
107 dvbpsi_DeletePSISections( p_section
);
109 dvbpsi_pat_empty( &patpsi
);
113 static uint32_t GetDescriptorLength24b( int i_length
)
115 uint32_t i_l1
, i_l2
, i_l3
;
117 i_l1
= i_length
&0x7f;
118 i_l2
= ( i_length
>> 7 )&0x7f;
119 i_l3
= ( i_length
>> 14 )&0x7f;
121 return( 0x808000 | ( i_l3
<< 16 ) | ( i_l2
<< 8 ) | i_l1
);
124 static void Mpeg4SUBTDecoderSpecific_55( bits_buffer_t
*b
)
126 bits_write( b
, 8, 0x10 ); /* textFormat, 0x10 for 3GPP TS 26.245 */
127 bits_write( b
, 8, 0x00 ); /* flags: 1b: associated video info flag
131 bits_write( b
, 8, 52 ); /* remaining size */
133 bits_write( b
, 32, 0x00 ); /* display flags */
135 bits_write( b
, 8, 0x00 ); /* horizontal justification (-1: left, 0 center, 1 right) */
136 bits_write( b
, 8, 0x01 ); /* vertical justification (-1: top, 0 center, 1 bottom) */
138 bits_write( b
, 24, 0x00 ); /* background rgb */
139 bits_write( b
, 8, 0xff ); /* background a */
141 bits_write( b
, 16, 0x00 ); /* text box top */
142 bits_write( b
, 16, 0x00 ); /* text box left */
143 bits_write( b
, 16, 0x00 ); /* text box bottom */
144 bits_write( b
, 16, 0x00 ); /* text box right */
146 bits_write( b
, 16, 0x00 ); /* start char */
147 bits_write( b
, 16, 0x00 ); /* end char */
148 bits_write( b
, 16, 0x00 ); /* default font id */
151 bits_write( b
, 8, 0x00 ); /* font style flags */
152 bits_write( b
, 8, 12 ); /* font size */
154 bits_write( b
, 24, 0x00 ); /* foreground rgb */
155 bits_write( b
, 8, 0x00 ); /* foreground a */
157 bits_write( b
, 24, 0x00 );
158 bits_write( b
, 8, 22 ); /* atom size */
160 bits_write( b
, 8, 'f' ); /* atom id */
161 bits_write( b
, 8, 't' );
162 bits_write( b
, 8, 'a' );
163 bits_write( b
, 8, 'b' );
165 bits_write( b
, 8, 0x00 );
166 bits_write( b
, 8, 0x01 ); /* entry count */
168 bits_write( b
, 16, 0x00 ); /* font id */
169 bits_write( b
, 8, 9 ); /* font name length */
170 const char fontname
[] = "Helvetica";
171 for(int i
=0; i
<9; i
++)
172 bits_write( b
, 8, fontname
[i
] ); /* font name */
175 static void GetPMTmpeg4( vlc_object_t
*p_object
, dvbpsi_pmt_t
*p_dvbpmt
,
176 unsigned i_mapped_streams
, const pes_mapped_stream_t
*p_mapped_streams
)
179 bits_buffer_t bits
, bits_fix_IOD
;
181 /* Make valgrind happy : it works at byte level not bit one so
182 * bit_write confuse it (but DON'T CHANGE the way that bit_write is
183 * working (needed when fixing some bits) */
184 memset( iod
, 0, 4096 );
186 bits_initwrite( &bits
, 4096, iod
);
187 /* IOD_label_scope */
188 bits_write( &bits
, 8, 0x11 );
190 bits_write( &bits
, 8, 0x01 );
191 /* InitialObjectDescriptor */
193 bits_write( &bits
, 8, 0x02 ); /* tag */
194 bits_fix_IOD
= bits
; /* save states to fix length later */
195 bits_write( &bits
, 24,
196 GetDescriptorLength24b( 0 ) ); /* variable length (fixed later) */
197 bits_write( &bits
, 10, 0x01 ); /* ObjectDescriptorID */
198 bits_write( &bits
, 1, 0x00 ); /* URL Flag */
199 bits_write( &bits
, 1, 0x00 ); /* includeInlineProfileLevelFlag */
200 bits_write( &bits
, 4, 0x0f ); /* reserved */
201 bits_write( &bits
, 8, 0xff ); /* ODProfile (no ODcapability ) */
202 bits_write( &bits
, 8, 0xff ); /* sceneProfile */
203 bits_write( &bits
, 8, 0xfe ); /* audioProfile (unspecified) */
204 bits_write( &bits
, 8, 0xfe ); /* visualProfile( // ) */
205 bits_write( &bits
, 8, 0xff ); /* graphicProfile (no ) */
206 for (unsigned i
= 0; i
< i_mapped_streams
; i
++ )
208 const pes_mapped_stream_t
*p_stream
= &p_mapped_streams
[i
];
210 if( p_stream
->pes
->i_stream_id
!= 0xfa && p_stream
->pes
->i_stream_id
!= 0xfb &&
211 p_stream
->pes
->i_stream_id
!= 0xfe )
214 bits_buffer_t bits_fix_ESDescr
, bits_fix_Decoder
;
217 bits_write( &bits
, 8, 0x03 ); /* ES_DescrTag */
218 bits_fix_ESDescr
= bits
;
219 bits_write( &bits
, 24,
220 GetDescriptorLength24b( 0 ) ); /* variable size */
221 bits_write( &bits
, 16, p_stream
->pes
->i_es_id
);
222 bits_write( &bits
, 1, 0x00 ); /* streamDependency */
223 bits_write( &bits
, 1, 0x00 ); /* URL Flag */
224 bits_write( &bits
, 1, 0x00 ); /* OCRStreamFlag */
225 bits_write( &bits
, 5, 0x1f ); /* streamPriority */
227 /* DecoderConfigDesciptor */
229 bits_write( &bits
, 8, 0x04 ); /* DecoderConfigDescrTag */
230 bits_fix_Decoder
= bits
;
231 bits_write( &bits
, 24, GetDescriptorLength24b( 0 ) );
232 if( p_stream
->ts
->i_stream_type
== 0x10 )
234 bits_write( &bits
, 8, 0x20 ); /* Visual 14496-2 */
235 bits_write( &bits
, 6, 0x04 ); /* VisualStream */
237 else if( p_stream
->ts
->i_stream_type
== 0x1b )
239 bits_write( &bits
, 8, 0x21 ); /* Visual 14496-2 */
240 bits_write( &bits
, 6, 0x04 ); /* VisualStream */
242 else if( p_stream
->ts
->i_stream_type
== 0x11 ||
243 p_stream
->ts
->i_stream_type
== 0x0f )
245 bits_write( &bits
, 8, 0x40 ); /* Audio 14496-3 */
246 bits_write( &bits
, 6, 0x05 ); /* AudioStream */
248 else if( p_stream
->ts
->i_stream_type
== 0x12 &&
249 p_stream
->fmt
->i_codec
== VLC_CODEC_SUBT
)
251 bits_write( &bits
, 8, 0x0B ); /* Text Stream */
252 bits_write( &bits
, 6, 0x04 ); /* VisualStream */
256 bits_write( &bits
, 8, 0x00 );
257 bits_write( &bits
, 6, 0x00 );
259 msg_Err( p_object
, "Unsupported stream_type => broken IOD" );
261 bits_write( &bits
, 1, 0x00 ); /* UpStream */
262 bits_write( &bits
, 1, 0x01 ); /* reserved */
263 bits_write( &bits
, 24, 1024 * 1024 ); /* bufferSizeDB */
264 bits_write( &bits
, 32, 0x7fffffff ); /* maxBitrate */
265 bits_write( &bits
, 32, 0 ); /* avgBitrate */
267 /* DecoderSpecificInfo */
268 if( p_stream
->fmt
->i_codec
== VLC_CODEC_SUBT
)
271 bits_write( &bits
, 8, 0x05 ); /* tag */
272 bits_write( &bits
, 24, 55 );
273 /* Create decoder specific info for subt */
274 Mpeg4SUBTDecoderSpecific_55( &bits
);
276 else if( p_stream
->fmt
->i_extra
> 0 )
278 /* DecoderSpecificInfo */
280 bits_write( &bits
, 8, 0x05 ); /* tag */
281 bits_write( &bits
, 24, GetDescriptorLength24b(
282 p_stream
->fmt
->i_extra
) );
283 for (int j
= 0; j
< p_stream
->fmt
->i_extra
; j
++ )
285 bits_write( &bits
, 8,
286 ((uint8_t*)p_stream
->fmt
->p_extra
)[j
] );
290 /* fix Decoder length */
291 bits_write( &bits_fix_Decoder
, 24,
292 GetDescriptorLength24b( bits
.i_data
-
293 bits_fix_Decoder
.i_data
- 3 ) );
295 /* SLConfigDescriptor : predefined (0x01) */
297 bits_write( &bits
, 8, 0x06 ); /* tag */
298 bits_write( &bits
, 24, GetDescriptorLength24b( 8 ) );
299 bits_write( &bits
, 8, 0x01 );/* predefined */
300 bits_write( &bits
, 1, 0 ); /* durationFlag */
301 bits_write( &bits
, 32, 0 ); /* OCRResolution */
302 bits_write( &bits
, 8, 0 ); /* OCRLength */
303 bits_write( &bits
, 8, 0 ); /* InstantBitrateLength */
306 /* fix ESDescr length */
307 bits_write( &bits_fix_ESDescr
, 24,
308 GetDescriptorLength24b( bits
.i_data
-
309 bits_fix_ESDescr
.i_data
- 3 ) );
313 bits_write( &bits_fix_IOD
, 24,
314 GetDescriptorLength24b(bits
.i_data
- bits_fix_IOD
.i_data
- 3 ));
316 dvbpsi_pmt_descriptor_add(&p_dvbpmt
[0], 0x1d, bits
.i_data
, bits
.p_data
);
319 static void UpdateServiceType( uint8_t *pi_service_cat
, uint8_t *pi_service_type
,
320 const tsmux_stream_t
*p_ts
, const es_format_t
*fmt
)
322 uint8_t i_type
= 0x00;
324 switch( p_ts
->i_stream_type
)
326 case 0x01: /* MPEG1 */
327 case 0x02: /* MPEG2 */
332 case 0x24: /* HEVC */
333 case 0x10: /* MPEG4 */
334 case 0x1b: /* H264 */
335 case 0xA0: /* private */
336 case 0xd1: /* dirac */
344 if( i_type
== 0x01 && fmt
->video
.i_visible_height
> 468 &&
345 fmt
->video
.i_visible_width
> 720 ) /* MPEG2 SD -> HD */
349 else if( i_type
== 0x16 && fmt
->video
.i_visible_height
> 468 &&
350 fmt
->video
.i_visible_width
> 720 ) /* Advanced codec SD -> HD */
357 if( *pi_service_cat
!= VIDEO_ES
|| i_type
> *pi_service_type
)
359 *pi_service_type
= i_type
;
360 *pi_service_cat
= VIDEO_ES
;
365 if( *pi_service_cat
!= VIDEO_ES
) /* Don't overwrite video */
367 /* Not video, try audio */
368 switch( p_ts
->i_stream_type
)
370 case 0x03: /* MPEG1 audio */
371 case 0x04: /* MPEG2 audio */
379 i_type
= 0x0A; /* Avanced codec digital radio */
386 if( i_type
> *pi_service_type
)
387 *pi_service_type
= i_type
;
391 static inline size_t Write_AnnexA_String( uint8_t *p_dest
, const char *p_src
)
394 if( p_src
== NULL
|| !(i_src
= strlen( p_src
)) )
400 bool b_latin
= (p_src
[0] > 0x20);
401 for ( size_t i
=0; i
< i_src
&& b_latin
; i
++ )
402 b_latin
&= !( p_src
[i
] & 0x80 );
406 i_src
= __MIN( i_src
, UINT8_MAX
);
407 p_dest
[0] = i_src
; /* Total size */
408 memcpy( &p_dest
[1], p_src
, i_src
);
413 i_src
= __MIN( i_src
, UINT8_MAX
- 1 );
414 p_dest
[0] = 1 + i_src
; /* Total size */
415 p_dest
[1] = 0x15; /* UTF8 Encoding */
416 memcpy( &p_dest
[2], p_src
, i_src
);
421 void BuildPMT( dvbpsi_t
*p_dvbpsi
, vlc_object_t
*p_object
,
422 ts_mux_standard standard
,
423 void *p_opaque
, PEStoTSCallback pf_callback
,
424 int i_tsid
, int i_pmt_version_number
,
427 unsigned i_programs
, tsmux_stream_t
*p_pmt
, const int *pi_programs_number
,
428 unsigned i_mapped_streams
, const pes_mapped_stream_t
*p_mapped_streams
)
430 dvbpsi_pmt_t
*dvbpmt
= malloc( i_programs
* sizeof(dvbpsi_pmt_t
) );
434 VLC_UNUSED(standard
);
436 uint8_t *pi_service_types
= NULL
;
437 uint8_t *pi_service_cats
= NULL
;
440 dvbpsi_sdt_init( &sdtpsi
, 0x42, i_tsid
, 1, true, p_sdt
->i_netid
);
441 pi_service_types
= calloc( i_programs
* 2, sizeof *pi_service_types
);
442 if( !pi_service_types
)
447 pi_service_cats
= &pi_service_types
[i_programs
];
450 for (unsigned i
= 0; i
< i_programs
; i
++ )
452 dvbpsi_pmt_init( &dvbpmt
[i
],
453 pi_programs_number
[i
], /* program number */
454 i_pmt_version_number
,
455 true, /* b_current_next */
459 for (unsigned i
= 0; i
< i_mapped_streams
; i
++ )
461 const pes_mapped_stream_t
*p_stream
= &p_mapped_streams
[i
];
462 if( p_stream
->pes
->i_stream_id
== 0xfa ||
463 p_stream
->pes
->i_stream_id
== 0xfb ||
464 p_stream
->pes
->i_stream_id
== 0xfe )
466 /* Has at least 1 MPEG4 stream */
467 GetPMTmpeg4( p_object
, dvbpmt
, i_mapped_streams
, p_mapped_streams
);
472 for (unsigned i
= 0; i
< i_mapped_streams
; i
++ )
474 const pes_mapped_stream_t
*p_stream
= &p_mapped_streams
[i
];
476 dvbpsi_pmt_es_t
*p_es
= dvbpsi_pmt_es_add( &dvbpmt
[p_stream
->i_mapped_prog
],
477 p_stream
->ts
->i_stream_type
, p_stream
->ts
->i_pid
);
479 if( p_stream
->pes
->i_stream_id
== 0xfa || p_stream
->pes
->i_stream_id
== 0xfb )
484 es_id
[0] = (p_stream
->pes
->i_es_id
>> 8)&0xff;
485 es_id
[1] = (p_stream
->pes
->i_es_id
)&0xff;
486 dvbpsi_pmt_es_descriptor_add( p_es
, 0x1f, 2, es_id
);
488 else if( p_stream
->ts
->i_stream_type
== 0xa0 )
491 size_t i_extra
= __MIN( p_stream
->fmt
->i_extra
, 502 );
493 /* private DIV3 descripor */
494 memcpy( &data
[0], &p_stream
->fmt
->i_codec
, 4 );
495 data
[4] = ( p_stream
->fmt
->video
.i_visible_width
>> 8 )&0xff;
496 data
[5] = ( p_stream
->fmt
->video
.i_visible_width
)&0xff;
497 data
[6] = ( p_stream
->fmt
->video
.i_visible_height
>> 8 )&0xff;
498 data
[7] = ( p_stream
->fmt
->video
.i_visible_height
)&0xff;
499 data
[8] = ( i_extra
>> 8 )&0xff;
500 data
[9] = ( i_extra
)&0xff;
503 memcpy( &data
[10], p_stream
->fmt
->p_extra
, i_extra
);
506 /* 0xa0 is private */
507 dvbpsi_pmt_es_descriptor_add( p_es
, 0xa0, i_extra
+ 10, data
);
509 else if( p_stream
->fmt
->i_codec
== VLC_CODEC_JPEG2000
)
511 uint8_t *p_data
= calloc( 1, 24 + p_stream
->fmt
->i_extra
);
514 const int profile
= j2k_get_profile( p_stream
->fmt
->video
.i_visible_width
,
515 p_stream
->fmt
->video
.i_visible_height
,
516 p_stream
->fmt
->video
.i_frame_rate
,
517 p_stream
->fmt
->video
.i_frame_rate_base
, true );
519 if( profile
< J2K_PROFILE_HD
)
520 p_data
[1] = 0x01; /* 0x0101 */
521 else if( profile
< J2K_PROFILE_3G
)
522 p_data
[1] = 0x02; /* 0x0102 */
524 p_data
[1] = 0x04; /* 0x0104 */
525 SetDWBE( &p_data
[2], p_stream
->fmt
->video
.i_visible_width
);
526 SetDWBE( &p_data
[6], p_stream
->fmt
->video
.i_visible_height
);
527 SetWBE( &p_data
[18], p_stream
->fmt
->video
.i_frame_rate_base
);
528 SetWBE( &p_data
[20], p_stream
->fmt
->video
.i_frame_rate
);
529 p_data
[21] = j2k_get_color_spec( p_stream
->fmt
->video
.primaries
,
530 p_stream
->fmt
->video
.transfer
,
531 p_stream
->fmt
->video
.space
);
532 memcpy( &p_data
[24], p_stream
->fmt
->p_extra
, p_stream
->fmt
->i_extra
);
533 dvbpsi_pmt_es_descriptor_add( p_es
, 0x32, 24 + p_stream
->fmt
->i_extra
, p_data
);
537 else if( p_stream
->fmt
->i_codec
== VLC_CODEC_DIRAC
)
539 /* Dirac registration descriptor */
541 uint8_t data
[4] = { 'd', 'r', 'a', 'c' };
542 dvbpsi_pmt_es_descriptor_add( p_es
, 0x05, 4, data
);
544 else if( p_stream
->fmt
->i_codec
== VLC_CODEC_DTS
)
546 /* DTS registration descriptor (ETSI TS 101 154 Annex F) */
547 if(popcount(p_stream
->fmt
->audio
.i_bytes_per_frame
) == 1)
549 uint8_t i_ver
= ctz( p_stream
->fmt
->audio
.i_bytes_per_frame
>> 8 );
550 if(i_ver
> 0 && i_ver
< 4)
552 uint8_t data
[4] = { 'D', 'T', 'S', '0' + i_ver
};
553 dvbpsi_pmt_es_descriptor_add( p_es
, 0x05, 4, data
);
557 else if( p_stream
->fmt
->i_codec
== VLC_CODEC_A52
)
559 uint8_t format
[4] = { 'A', 'C', '-', '3'};
561 /* "registration" descriptor : "AC-3" */
562 dvbpsi_pmt_es_descriptor_add( p_es
, 0x05, 4, format
);
564 if( standard
== TS_MUX_STANDARD_ATSC
)
566 assert(p_stream
->ts
->i_stream_type
== 0x81);
567 /* FIXME: ATSC AC-3 audio_stream_descriptor */
568 uint8_t data
[1] = { 0x00 };
569 dvbpsi_pmt_es_descriptor_add( p_es
, 0x81, 1, data
);
573 /* FIXME: DVB AC-3 descriptor */
574 uint8_t data
[1] = { 0x00 };
575 dvbpsi_pmt_es_descriptor_add( p_es
, 0x6a, 1, data
);
578 else if( p_stream
->fmt
->i_codec
== VLC_CODEC_EAC3
)
580 uint8_t format
[4] = { 'E', 'A', 'C', '3'};
582 /* "registration" descriptor : "EAC3" */
583 dvbpsi_pmt_es_descriptor_add( p_es
, 0x05, 4, format
);
585 if( standard
== TS_MUX_STANDARD_ATSC
)
587 assert( p_stream
->ts
->i_stream_type
== 0x87 );
588 /* FIXME: ATSC EAC3 audio_stream_descriptor */
589 uint8_t data
[1] = { 0x00 };
590 dvbpsi_pmt_es_descriptor_add( p_es
, 0xcc, 1, data
);
591 /* FIXME: ATSC A-71 stream_info_details */
595 uint8_t data
[1] = { 0x00 };
596 dvbpsi_pmt_es_descriptor_add( p_es
, 0x7a, 1, data
);
599 else if( p_stream
->fmt
->i_codec
== VLC_CODEC_OPUS
)
602 0x80, /* tag extension */
603 p_stream
->fmt
->audio
.i_channels
605 dvbpsi_pmt_es_descriptor_add( p_es
, 0x7f, 2, data
);
606 uint8_t format
[4] = { 'O', 'p', 'u', 's'};
607 /* "registration" descriptor : "Opus" */
608 dvbpsi_pmt_es_descriptor_add( p_es
, 0x05, 4, format
);
610 else if( p_stream
->fmt
->i_codec
== VLC_CODEC_TELETEXT
)
612 if( p_stream
->fmt
->i_extra
)
614 dvbpsi_pmt_es_descriptor_add( p_es
, 0x56,
615 p_stream
->fmt
->i_extra
,
616 p_stream
->fmt
->p_extra
);
620 else if( p_stream
->fmt
->i_codec
== VLC_CODEC_DVBS
)
623 if( p_stream
->fmt
->i_extra
)
625 /* pass-through from the TS demux */
626 dvbpsi_pmt_es_descriptor_add( p_es
, 0x59,
627 p_stream
->fmt
->i_extra
,
628 p_stream
->fmt
->p_extra
);
632 /* from the dvbsub transcoder */
633 dvbpsi_subtitling_dr_t descr
;
634 dvbpsi_subtitle_t sub
;
635 dvbpsi_descriptor_t
*p_descr
;
637 memcpy( sub
.i_iso6392_language_code
, p_stream
->pes
->lang
, 3 );
638 sub
.i_subtitling_type
= 0x10; /* no aspect-ratio criticality */
639 sub
.i_composition_page_id
= p_stream
->pes
->i_es_id
& 0xFF;
640 sub
.i_ancillary_page_id
= p_stream
->pes
->i_es_id
>> 16;
642 descr
.i_subtitles_number
= 1;
643 descr
.p_subtitle
[0] = sub
;
645 p_descr
= dvbpsi_GenSubtitlingDr( &descr
, 0 );
646 /* Work around bug in old libdvbpsi */ p_descr
->i_length
= 8;
647 dvbpsi_pmt_es_descriptor_add( p_es
, p_descr
->i_tag
,
648 p_descr
->i_length
, p_descr
->p_data
);
653 if( p_stream
->pes
->i_langs
)
655 dvbpsi_pmt_es_descriptor_add( p_es
, 0x0a, 4*p_stream
->pes
->i_langs
,
656 p_stream
->pes
->lang
);
661 UpdateServiceType( &pi_service_cats
[p_stream
->i_mapped_prog
],
662 &pi_service_types
[p_stream
->i_mapped_prog
],
663 p_stream
->ts
, p_stream
->fmt
);
667 for (unsigned i
= 0; i
< i_programs
; i
++ )
669 dvbpsi_psi_section_t
*sect
= dvbpsi_pmt_sections_generate( p_dvbpsi
, &dvbpmt
[i
] );
672 block_t
*pmt
= WritePSISection( sect
);
675 PEStoTS( p_opaque
, pf_callback
, pmt
, p_pmt
[i
].i_pid
,
676 &p_pmt
[i
].b_discontinuity
, &p_pmt
[i
].i_continuity_counter
);
678 dvbpsi_DeletePSISections(sect
);
680 dvbpsi_pmt_empty( &dvbpmt
[i
] );
686 for (unsigned i
= 0; i
< i_programs
; i
++ )
688 dvbpsi_sdt_service_t
*p_service
= dvbpsi_sdt_service_add( &sdtpsi
,
689 pi_programs_number
[i
], /* service id */
690 false, /* eit schedule */
691 false, /* eit present */
692 4, /* running status ("4=RUNNING") */
693 false ); /* free ca */
695 const char *psz_sdtprov
= p_sdt
->desc
[i
].psz_provider
;
696 const char *psz_sdtserv
= p_sdt
->desc
[i
].psz_service_name
;
698 uint8_t p_sdt_desc
[4 + 255 * 2];
699 size_t i_sdt_desc
= 0;
701 /* mapped service type according to es types */
702 p_sdt_desc
[i_sdt_desc
++] = pi_service_types
[i
];
704 /* service provider name length */
705 i_sdt_desc
+= Write_AnnexA_String( &p_sdt_desc
[i_sdt_desc
], psz_sdtprov
);
707 /* service name length */
708 i_sdt_desc
+= Write_AnnexA_String( &p_sdt_desc
[i_sdt_desc
], psz_sdtserv
);
710 dvbpsi_sdt_service_descriptor_add( p_service
, 0x48, i_sdt_desc
, p_sdt_desc
);
712 free( pi_service_types
);
714 dvbpsi_psi_section_t
*sect
= dvbpsi_sdt_sections_generate( p_dvbpsi
, &sdtpsi
);
717 block_t
*p_sdtblock
= WritePSISection( sect
);
718 if( likely(p_sdtblock
) )
720 PEStoTS( p_opaque
, pf_callback
, p_sdtblock
, p_sdt
->ts
.i_pid
,
721 &p_sdt
->ts
.b_discontinuity
, &p_sdt
->ts
.i_continuity_counter
);
723 dvbpsi_DeletePSISections( sect
);
725 dvbpsi_sdt_empty( &sdtpsi
);
729 int FillPMTESParams( ts_mux_standard standard
, const es_format_t
*fmt
,
730 tsmux_stream_t
*ts
, pesmux_stream_t
*pes
)
732 switch( fmt
->i_codec
)
739 /* TODO: do we need to check MPEG-I/II ? */
740 ts
->i_stream_type
= 0x02;
741 pes
->i_stream_id
= 0xe0;
744 ts
->i_stream_type
= 0x10;
745 pes
->i_stream_id
= 0xe0;
746 pes
->i_es_id
= ts
->i_pid
;
749 ts
->i_stream_type
= 0x24;
750 pes
->i_stream_id
= 0xe0;
753 ts
->i_stream_type
= 0x1b;
754 pes
->i_stream_id
= 0xe0;
756 /* XXX dirty dirty but somebody want crapy MS-codec XXX */
757 case VLC_CODEC_H263I
:
766 ts
->i_stream_type
= 0xa0; /* private */
767 pes
->i_stream_id
= 0xa0; /* beurk */
769 case VLC_CODEC_DIRAC
:
770 /* stream_id makes use of stream_id_extension */
771 pes
->i_stream_id
= (PES_EXTENDED_STREAM_ID
<< 8) | 0x60;
772 ts
->i_stream_type
= 0xd1;
774 case VLC_CODEC_JPEG2000
:
775 if( !j2k_is_valid_framerate( fmt
->video
.i_frame_rate
,
776 fmt
->video
.i_frame_rate_base
) )
778 ts
->i_stream_type
= 0x21;
779 pes
->i_stream_id
= 0xbd;
787 ts
->i_stream_type
= fmt
->audio
.i_rate
>= 32000 ? 0x03 : 0x04;
788 pes
->i_stream_id
= 0xc0;
791 pes
->i_stream_id
= 0xbd;
792 if( standard
== TS_MUX_STANDARD_ATSC
)
794 ts
->i_stream_type
= 0x81;
798 ts
->i_stream_type
= 0x06;
801 case VLC_CODEC_DVD_LPCM
:
802 ts
->i_stream_type
= 0x83;
803 pes
->i_stream_id
= 0xbd;
806 if (fmt
->audio
.i_channels
> 8)
808 pes
->i_stream_id
= 0xbd;
809 pes
->i_stream_id
= 0x06;
812 pes
->i_stream_id
= 0xbd;
813 if( standard
== TS_MUX_STANDARD_ATSC
)
815 /* FIXME: Mandatory EAC3 audio_descriptor */
816 ts
->i_stream_type
= 0x87;
820 ts
->i_stream_type
= 0x06;
824 if( standard
== TS_MUX_STANDARD_ATSC
)
830 ts
->i_stream_type
= 0x06;
831 pes
->i_stream_id
= 0xbd;
835 /* XXX: make that configurable in some way when LOAS
836 * is implemented for AAC in TS */
837 //ts->i_stream_type = 0x11; /* LOAS/LATM */
838 ts
->i_stream_type
= 0x0f; /* ADTS */
839 pes
->i_stream_id
= 0xc0;
840 pes
->i_es_id
= ts
->i_pid
;
846 ts
->i_stream_type
= 0x82;
847 pes
->i_stream_id
= 0xbd;
850 ts
->i_stream_type
= 0x12;
851 pes
->i_stream_id
= 0xfa;
852 pes
->i_es_id
= ts
->i_pid
;
855 ts
->i_stream_type
= 0x06;
856 pes
->i_es_id
= fmt
->subs
.dvb
.i_id
;
857 pes
->i_stream_id
= 0xbd;
859 case VLC_CODEC_TELETEXT
:
860 ts
->i_stream_type
= 0x06;
861 pes
->i_stream_id
= 0xbd; /* FIXME */