Coverage Report

Created: 2026-03-31 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/mux/mpeg/tables.c
Line
Count
Source
1
/*****************************************************************************
2
 * tables.c
3
 *****************************************************************************
4
 * Copyright (C) 2001-2005, 2015 VLC authors and VideoLAN
5
 *
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.
10
 *
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.
15
 *
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
 *****************************************************************************/
20
#ifdef HAVE_CONFIG_H
21
# include "config.h"
22
#endif
23
24
#include <stdbit.h>
25
26
#include <vlc_common.h>
27
#include <vlc_block.h>
28
#include <vlc_es.h>
29
30
# include <dvbpsi/dvbpsi.h>
31
# include <dvbpsi/demux.h>
32
# include <dvbpsi/descriptor.h>
33
# include <dvbpsi/pat.h>
34
# include <dvbpsi/pmt.h>
35
# include <dvbpsi/sdt.h>
36
# include <dvbpsi/dr.h>
37
# include <dvbpsi/psi.h>
38
39
#include "streams.h"
40
#include "tsutil.h"
41
#include "tables.h"
42
#include "bits.h"
43
#include "pes.h"
44
45
#include "../../codec/jpeg2000.h"
46
#include "../../packetizer/dts_header.h"
47
48
#include <assert.h>
49
50
block_t *WritePSISection( dvbpsi_psi_section_t* p_section )
51
1.57k
{
52
1.57k
    block_t   *p_psi, *p_first = NULL;
53
54
3.14k
    while( p_section )
55
1.57k
    {
56
1.57k
        int i_size = (uint32_t)(p_section->p_payload_end - p_section->p_data) +
57
1.57k
                  (p_section->b_syntax_indicator ? 4 : 0);
58
59
1.57k
        p_psi = block_Alloc( i_size + 1 );
60
1.57k
        if( !p_psi )
61
0
            goto error;
62
1.57k
        p_psi->i_pts = 0;
63
1.57k
        p_psi->i_dts = 0;
64
1.57k
        p_psi->i_length = 0;
65
1.57k
        p_psi->i_buffer = i_size + 1;
66
67
1.57k
        p_psi->p_buffer[0] = 0; /* pointer */
68
1.57k
        memcpy( p_psi->p_buffer + 1,
69
1.57k
                p_section->p_data,
70
1.57k
                i_size );
71
72
1.57k
        block_ChainAppend( &p_first, p_psi );
73
74
1.57k
        p_section = p_section->p_next;
75
1.57k
    }
76
77
1.57k
    return( p_first );
78
79
0
error:
80
0
    if( p_first )
81
0
        block_ChainRelease( p_first );
82
0
    return NULL;
83
1.57k
}
84
85
void BuildPAT( dvbpsi_t *p_dvbpsi,
86
               void *p_opaque, PEStoTSCallback pf_callback,
87
               int i_tsid, int i_pat_version_number,
88
               tsmux_stream_t *p_pat,
89
               unsigned i_programs, tsmux_stream_t *p_pmt, const int *pi_programs_number )
90
786
{
91
786
    dvbpsi_pat_t         patpsi;
92
786
    dvbpsi_psi_section_t *p_section;
93
94
786
    dvbpsi_pat_init( &patpsi, i_tsid, i_pat_version_number, true /* b_current_next */ );
95
    /* add all programs */
96
1.57k
    for (unsigned i = 0; i < i_programs; i++ )
97
786
        dvbpsi_pat_program_add( &patpsi, pi_programs_number[i], p_pmt[i].i_pid );
98
99
786
    p_section = dvbpsi_pat_sections_generate( p_dvbpsi, &patpsi, 0 );
100
786
    if( likely(p_section) )
101
786
    {
102
786
        block_t *p_block = WritePSISection( p_section );
103
786
        if( likely(p_block) )
104
786
        {
105
786
            PEStoTS( p_opaque, pf_callback, p_block, p_pat->i_pid,
106
786
                     &p_pat->b_discontinuity, &p_pat->i_continuity_counter );
107
786
        }
108
786
        dvbpsi_DeletePSISections( p_section );
109
786
    }
110
786
    dvbpsi_pat_empty( &patpsi );
111
786
}
112
#if 1
113
114
static uint32_t GetDescriptorLength24b( int i_length )
115
0
{
116
0
    uint32_t i_l1, i_l2, i_l3;
117
118
0
    i_l1 = i_length&0x7f;
119
0
    i_l2 = ( i_length >> 7 )&0x7f;
120
0
    i_l3 = ( i_length >> 14 )&0x7f;
121
122
0
    return( 0x808000 | ( i_l3 << 16 ) | ( i_l2 << 8 ) | i_l1 );
123
0
}
124
125
static void Mpeg4SUBTDecoderSpecific_55( bits_buffer_t *b )
126
0
{
127
0
    bits_write( b, 8, 0x10 ); /* textFormat, 0x10 for 3GPP TS 26.245 */
128
0
    bits_write( b, 8, 0x00 ); /* flags: 1b: associated video info flag
129
                                        3b: reserved
130
                                        1b: duration flag
131
                                        3b: reserved */
132
0
    bits_write( b, 8, 52 );   /* remaining size */
133
134
0
    bits_write( b, 32, 0x00 ); /* display flags */
135
136
0
    bits_write( b, 8, 0x00 ); /* horizontal justification (-1: left, 0 center, 1 right) */
137
0
    bits_write( b, 8, 0x01 );  /* vertical   justification (-1: top, 0 center, 1 bottom) */
138
139
0
    bits_write( b, 24, 0x00 ); /* background rgb */
140
0
    bits_write( b, 8,  0xff ); /* background a */
141
142
0
    bits_write( b, 16,  0x00 ); /* text box top */
143
0
    bits_write( b, 16,  0x00 ); /* text box left */
144
0
    bits_write( b, 16,  0x00 ); /* text box bottom */
145
0
    bits_write( b, 16,  0x00 ); /* text box right */
146
147
0
    bits_write( b, 16,  0x00 ); /* start char */
148
0
    bits_write( b, 16,  0x00 ); /* end char */
149
0
    bits_write( b, 16,  0x00 ); /* default font id */
150
151
152
0
    bits_write( b, 8, 0x00 );   /* font style flags */
153
0
    bits_write( b, 8,   12 );   /* font size */
154
155
0
    bits_write( b, 24, 0x00 );  /* foreground rgb */
156
0
    bits_write( b,  8, 0x00 );  /* foreground a */
157
158
0
    bits_write( b, 24, 0x00 );
159
0
    bits_write( b,  8,   22 );  /* atom size */
160
161
0
    bits_write( b,  8,   'f' ); /* atom id */
162
0
    bits_write( b,  8,   't' );
163
0
    bits_write( b,  8,   'a' );
164
0
    bits_write( b,  8,   'b' );
165
166
0
    bits_write( b,  8,  0x00 );
167
0
    bits_write( b,  8,  0x01 ); /* entry count */
168
169
0
    bits_write( b, 16,  0x00 ); /* font id */
170
0
    bits_write( b,  8,     9 ); /* font name length */
171
0
    const char fontname[] = "Helvetica";
172
0
    for(int i=0; i<9; i++)
173
0
        bits_write( b,  8, fontname[i] ); /* font name */
174
0
}
175
176
static void GetPMTmpeg4( vlc_object_t *p_object, dvbpsi_pmt_t *p_dvbpmt,
177
                         unsigned i_mapped_streams, const pes_mapped_stream_t *p_mapped_streams )
178
0
{
179
0
    uint8_t iod[4096];
180
0
    bits_buffer_t bits, bits_fix_IOD;
181
182
    /* Make valgrind happy : it works at byte level not bit one so
183
     * bit_write confuse it (but DON'T CHANGE the way that bit_write is
184
     * working (needed when fixing some bits) */
185
0
    memset( iod, 0, 4096 );
186
187
0
    bits_initwrite( &bits, 4096, iod );
188
    /* IOD_label_scope */
189
0
    bits_write( &bits, 8,   0x11 );
190
    /* IOD_label */
191
0
    bits_write( &bits, 8,   0x01 );
192
    /* InitialObjectDescriptor */
193
0
    bits_align( &bits );
194
0
    bits_write( &bits, 8,   0x02 );     /* tag */
195
0
    bits_fix_IOD = bits;    /* save states to fix length later */
196
0
    bits_write( &bits, 24,
197
0
        GetDescriptorLength24b( 0 ) );  /* variable length (fixed later) */
198
0
    bits_write( &bits, 10,  0x01 );     /* ObjectDescriptorID */
199
0
    bits_write( &bits, 1,   0x00 );     /* URL Flag */
200
0
    bits_write( &bits, 1,   0x00 );     /* includeInlineProfileLevelFlag */
201
0
    bits_write( &bits, 4,   0x0f );     /* reserved */
202
0
    bits_write( &bits, 8,   0xff );     /* ODProfile (no ODcapability ) */
203
0
    bits_write( &bits, 8,   0xff );     /* sceneProfile */
204
0
    bits_write( &bits, 8,   0xfe );     /* audioProfile (unspecified) */
205
0
    bits_write( &bits, 8,   0xfe );     /* visualProfile( // ) */
206
0
    bits_write( &bits, 8,   0xff );     /* graphicProfile (no ) */
207
0
    for (unsigned i = 0; i < i_mapped_streams; i++ )
208
0
    {
209
0
        const pes_mapped_stream_t *p_stream = &p_mapped_streams[i];
210
211
0
        if( p_stream->pes->i_stream_id != 0xfa && p_stream->pes->i_stream_id != 0xfb &&
212
0
            p_stream->pes->i_stream_id != 0xfe )
213
0
            continue;
214
215
0
        bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
216
        /* ES descriptor */
217
0
        bits_align( &bits );
218
0
        bits_write( &bits, 8,   0x03 );     /* ES_DescrTag */
219
0
        bits_fix_ESDescr = bits;
220
0
        bits_write( &bits, 24,
221
0
                    GetDescriptorLength24b( 0 ) ); /* variable size */
222
0
        bits_write( &bits, 16,  p_stream->pes->i_es_id );
223
0
        bits_write( &bits, 1,   0x00 );     /* streamDependency */
224
0
        bits_write( &bits, 1,   0x00 );     /* URL Flag */
225
0
        bits_write( &bits, 1,   0x00 );     /* OCRStreamFlag */
226
0
        bits_write( &bits, 5,   0x1f );     /* streamPriority */
227
228
        /* DecoderConfigDesciptor */
229
0
        bits_align( &bits );
230
0
        bits_write( &bits, 8,   0x04 ); /* DecoderConfigDescrTag */
231
0
        bits_fix_Decoder = bits;
232
0
        bits_write( &bits, 24,  GetDescriptorLength24b( 0 ) );
233
0
        if( p_stream->ts->i_stream_type == 0x10 )
234
0
        {
235
0
            bits_write( &bits, 8, 0x20 );   /* Visual 14496-2 */
236
0
            bits_write( &bits, 6, 0x04 );   /* VisualStream */
237
0
        }
238
0
        else if( p_stream->ts->i_stream_type == 0x1b )
239
0
        {
240
0
            bits_write( &bits, 8, 0x21 );   /* Visual 14496-2 */
241
0
            bits_write( &bits, 6, 0x04 );   /* VisualStream */
242
0
        }
243
0
        else if( p_stream->ts->i_stream_type == 0x11 ||
244
0
                 p_stream->ts->i_stream_type == 0x0f )
245
0
        {
246
0
            bits_write( &bits, 8, 0x40 );   /* Audio 14496-3 */
247
0
            bits_write( &bits, 6, 0x05 );   /* AudioStream */
248
0
        }
249
0
        else if( p_stream->ts->i_stream_type == 0x12 &&
250
0
                 p_stream->fmt->i_codec == VLC_CODEC_SUBT )
251
0
        {
252
0
            bits_write( &bits, 8, 0x0B );   /* Text Stream */
253
0
            bits_write( &bits, 6, 0x04 );   /* VisualStream */
254
0
        }
255
0
        else
256
0
        {
257
0
            bits_write( &bits, 8, 0x00 );
258
0
            bits_write( &bits, 6, 0x00 );
259
260
0
            msg_Err( p_object, "Unsupported stream_type => broken IOD" );
261
0
        }
262
0
        bits_write( &bits, 1,   0x00 );         /* UpStream */
263
0
        bits_write( &bits, 1,   0x01 );         /* reserved */
264
0
        bits_write( &bits, 24,  1024 * 1024 );  /* bufferSizeDB */
265
0
        bits_write( &bits, 32,  0x7fffffff );   /* maxBitrate */
266
0
        bits_write( &bits, 32,  0 );            /* avgBitrate */
267
268
        /* DecoderSpecificInfo */
269
0
        if( p_stream->fmt->i_codec == VLC_CODEC_SUBT )
270
0
        {
271
0
            bits_align( &bits );
272
0
            bits_write( &bits, 8,   0x05 ); /* tag */
273
0
            bits_write( &bits, 24,  55 );
274
            /* Create decoder specific info for subt */
275
0
            Mpeg4SUBTDecoderSpecific_55( &bits );
276
0
        }
277
0
        else if( p_stream->fmt->i_extra > 0 )
278
0
        {
279
            /* DecoderSpecificInfo */
280
0
            bits_align( &bits );
281
0
            bits_write( &bits, 8,   0x05 ); /* tag */
282
0
            bits_write( &bits, 24, GetDescriptorLength24b(
283
0
                        p_stream->fmt->i_extra ) );
284
0
            for (size_t j = 0; j < p_stream->fmt->i_extra; j++ )
285
0
            {
286
            // TODO checks
287
0
                bits_write( &bits, 8,
288
0
                    ((uint8_t*)p_stream->fmt->p_extra)[j] );
289
0
            }
290
0
        }
291
292
        /* fix Decoder length */
293
0
        bits_write( &bits_fix_Decoder, 24,
294
0
                    GetDescriptorLength24b( bits.i_data -
295
0
                    bits_fix_Decoder.i_data - 3 ) );
296
297
        /* SLConfigDescriptor : predefined (0x01) */
298
0
        bits_align( &bits );
299
0
        bits_write( &bits, 8,   0x06 ); /* tag */
300
0
        bits_write( &bits, 24,  GetDescriptorLength24b( 8 ) );
301
0
        bits_write( &bits, 8,   0x01 );/* predefined */
302
0
        bits_write( &bits, 1,   0 );   /* durationFlag */
303
0
        bits_write( &bits, 32,  0 );   /* OCRResolution */
304
0
        bits_write( &bits, 8,   0 );   /* OCRLength */
305
0
        bits_write( &bits, 8,   0 );   /* InstantBitrateLength */
306
0
        bits_align( &bits );
307
308
        /* fix ESDescr length */
309
0
        bits_write( &bits_fix_ESDescr, 24,
310
0
                    GetDescriptorLength24b( bits.i_data -
311
0
                    bits_fix_ESDescr.i_data - 3 ) );
312
0
    }
313
0
    bits_align( &bits );
314
    /* fix IOD length */
315
0
    bits_write( &bits_fix_IOD, 24,
316
0
                GetDescriptorLength24b(bits.i_data - bits_fix_IOD.i_data - 3 ));
317
318
0
    dvbpsi_pmt_descriptor_add(&p_dvbpmt[0], 0x1d, bits.i_data, bits.p_data);
319
0
}
320
321
struct service_info
322
{
323
    uint8_t cat;
324
    uint8_t type;
325
    bool b_scrambled;
326
};
327
328
static void UpdateServiceType( struct service_info *info,
329
                               const tsmux_stream_t *p_ts, const es_format_t *fmt )
330
0
{
331
0
    uint8_t i_type = 0x00;
332
333
0
    info->b_scrambled |= p_ts->b_scramble;
334
335
0
    switch( p_ts->i_stream_type )
336
0
    {
337
0
        case 0x01: /* MPEG1 */
338
0
        case 0x02: /* MPEG2 */
339
0
        case 0x80:
340
0
            i_type = 0x01;
341
0
            break;
342
343
0
        case 0x24: /* HEVC */
344
0
        case 0x10: /* MPEG4 */
345
0
        case 0x1b: /* H264 */
346
0
        case 0xA0: /* private */
347
0
        case 0xd1: /* dirac */
348
0
            i_type = 0x16;
349
0
            break;
350
351
0
        default:
352
0
            break;
353
0
    }
354
355
0
    if( i_type == 0x01 && fmt->video.i_visible_height > 468 &&
356
0
                          fmt->video.i_visible_width > 720 ) /* MPEG2 SD -> HD */
357
0
    {
358
0
         i_type = 0x11;
359
0
    }
360
0
    else if( i_type == 0x16 && fmt->video.i_visible_height > 468 &&
361
0
                               fmt->video.i_visible_width > 720 ) /* Advanced codec SD -> HD */
362
0
    {
363
0
         i_type = 0x19;
364
0
    }
365
366
0
    if( i_type != 0x00 )
367
0
    {
368
0
        if( info->cat != VIDEO_ES || i_type > info->type )
369
0
        {
370
0
            info->type = i_type;
371
0
            info->cat = VIDEO_ES;
372
0
        }
373
0
        return;
374
0
    }
375
376
0
    if( info->cat != VIDEO_ES ) /* Don't overwrite video */
377
0
    {
378
        /* Not video, try audio */
379
0
        switch( p_ts->i_stream_type )
380
0
        {
381
0
            case 0x03: /* MPEG1 audio */
382
0
            case 0x04: /* MPEG2 audio */
383
0
                i_type = 0x02;
384
0
                break;
385
386
0
            case 0x06:
387
0
            case 0x0f:
388
0
            case 0x81:
389
0
            case 0x83:
390
0
                i_type = 0x0A; /* Advanced codec digital radio */
391
0
                break;
392
393
0
            default:
394
0
                break;
395
0
        }
396
397
0
        if( i_type > info->type )
398
0
            info->type = i_type;
399
0
    }
400
0
}
401
402
static inline size_t Write_AnnexA_String( uint8_t *p_dest, const char *p_src )
403
0
{
404
0
    size_t i_src;
405
0
    if( p_src == NULL || !(i_src = strlen( p_src )) )
406
0
    {
407
0
        p_dest[0] = 0;
408
0
        return 1;
409
0
    }
410
411
0
    bool b_latin = (p_src[0] > 0x20);
412
0
    for ( size_t i=0; i< i_src && b_latin; i++ )
413
0
        b_latin &= !( p_src[i] & 0x80 );
414
415
0
    if( b_latin )
416
0
    {
417
0
        i_src = __MIN( i_src, UINT8_MAX );
418
0
        p_dest[0] = i_src; /* Total size */
419
0
        memcpy( &p_dest[1], p_src, i_src );
420
0
        return 1 + i_src;
421
0
    }
422
0
    else
423
0
    {
424
0
        i_src = __MIN( i_src, UINT8_MAX - 1 );
425
0
        p_dest[0] = 1 + i_src; /* Total size */
426
0
        p_dest[1] = 0x15; /* UTF8 Encoding */
427
0
        memcpy( &p_dest[2], p_src, i_src );
428
0
        return 2 + i_src;
429
0
    }
430
0
}
431
432
void BuildPMT( dvbpsi_t *p_dvbpsi, vlc_object_t *p_object,
433
               ts_mux_standard standard,
434
               void *p_opaque, PEStoTSCallback pf_callback,
435
               int i_tsid, int i_pmt_version_number,
436
               int i_pcr_pid,
437
               sdt_psi_t *p_sdt,
438
               unsigned i_programs, tsmux_stream_t *p_pmt, const int *pi_programs_number,
439
               unsigned i_mapped_streams, const pes_mapped_stream_t *p_mapped_streams )
440
784
{
441
784
    dvbpsi_pmt_t *dvbpmt = vlc_alloc( i_programs, sizeof(dvbpsi_pmt_t) );
442
784
    if( !dvbpmt )
443
0
            return;
444
445
784
    VLC_UNUSED(standard);
446
784
    dvbpsi_sdt_t sdtpsi;
447
784
    struct service_info *p_service_infos = NULL;
448
784
    if( p_sdt )
449
0
    {
450
0
        dvbpsi_sdt_init( &sdtpsi, 0x42, i_tsid, 1, true, p_sdt->i_netid );
451
0
        p_service_infos = calloc( i_programs, sizeof(*p_service_infos) );
452
0
        if( !p_service_infos )
453
0
        {
454
0
            free( dvbpmt );
455
0
            return;
456
0
        }
457
0
    }
458
459
1.56k
    for (unsigned i = 0; i < i_programs; i++ )
460
784
    {
461
784
        dvbpsi_pmt_init( &dvbpmt[i],
462
784
                        pi_programs_number[i],   /* program number */
463
784
                        i_pmt_version_number,
464
784
                        true,      /* b_current_next */
465
784
                        i_pcr_pid );
466
784
    }
467
468
1.74k
    for (unsigned i = 0; i < i_mapped_streams; i++ )
469
958
    {
470
958
        const pes_mapped_stream_t *p_stream = &p_mapped_streams[i];
471
958
        if( p_stream->pes->i_stream_id == 0xfa ||
472
958
            p_stream->pes->i_stream_id == 0xfb ||
473
958
            p_stream->pes->i_stream_id == 0xfe )
474
0
        {
475
            /* Has at least 1 MPEG4 stream */
476
0
            GetPMTmpeg4( p_object, dvbpmt, i_mapped_streams, p_mapped_streams );
477
0
            break;
478
0
        }
479
958
    }
480
481
1.74k
    for (unsigned i = 0; i < i_mapped_streams; i++ )
482
958
    {
483
958
        const pes_mapped_stream_t *p_stream = &p_mapped_streams[i];
484
485
958
        dvbpsi_pmt_es_t *p_es = dvbpsi_pmt_es_add( &dvbpmt[p_stream->i_mapped_prog],
486
958
                    p_stream->ts->i_stream_type, p_stream->ts->i_pid );
487
488
958
        if( p_stream->pes->i_stream_id == 0xfa || p_stream->pes->i_stream_id == 0xfb )
489
0
        {
490
0
            uint8_t     es_id[2];
491
492
            /* SL descriptor */
493
0
            es_id[0] = (p_stream->pes->i_es_id >> 8)&0xff;
494
0
            es_id[1] = (p_stream->pes->i_es_id)&0xff;
495
0
            dvbpsi_pmt_es_descriptor_add( p_es, 0x1f, 2, es_id );
496
0
        }
497
958
        else if( p_stream->ts->i_stream_type == 0xa0 )
498
0
        {
499
0
            uint8_t data[512];
500
0
            size_t i_extra = __MIN( p_stream->fmt->i_extra, 502 );
501
502
            /* private DIV3 descriptor */
503
0
            memcpy( &data[0], &p_stream->fmt->i_codec, 4 );
504
0
            data[4] = ( p_stream->fmt->video.i_visible_width >> 8 )&0xff;
505
0
            data[5] = ( p_stream->fmt->video.i_visible_width      )&0xff;
506
0
            data[6] = ( p_stream->fmt->video.i_visible_height>> 8 )&0xff;
507
0
            data[7] = ( p_stream->fmt->video.i_visible_height     )&0xff;
508
0
            data[8] = ( i_extra >> 8 )&0xff;
509
0
            data[9] = ( i_extra      )&0xff;
510
0
            if( i_extra > 0 )
511
0
            {
512
0
                memcpy( &data[10], p_stream->fmt->p_extra, i_extra );
513
0
            }
514
515
            /* 0xa0 is private */
516
0
            dvbpsi_pmt_es_descriptor_add( p_es, 0xa0, i_extra + 10, data );
517
0
        }
518
958
        else if( p_stream->fmt->i_codec == VLC_CODEC_JPEG2000 )
519
0
        {
520
0
            uint8_t *p_data = calloc( 1, 24 + p_stream->fmt->i_extra );
521
0
            if( p_data )
522
0
            {
523
0
                const int profile = j2k_get_profile( p_stream->fmt->video.i_visible_width,
524
0
                                                     p_stream->fmt->video.i_visible_height,
525
0
                                                     p_stream->fmt->video.i_frame_rate,
526
0
                                                     p_stream->fmt->video.i_frame_rate_base, true );
527
0
                p_data[0] = 0x01;
528
0
                if( profile < J2K_PROFILE_HD )
529
0
                    p_data[1] = 0x01; /* 0x0101 */
530
0
                else if( profile < J2K_PROFILE_3G )
531
0
                    p_data[1] = 0x02; /* 0x0102 */
532
0
                else
533
0
                    p_data[1] = 0x04; /* 0x0104 */
534
0
                SetDWBE( &p_data[2], p_stream->fmt->video.i_visible_width );
535
0
                SetDWBE( &p_data[6], p_stream->fmt->video.i_visible_height );
536
0
                SetWBE( &p_data[18], p_stream->fmt->video.i_frame_rate_base );
537
0
                SetWBE( &p_data[20], p_stream->fmt->video.i_frame_rate );
538
0
                p_data[21] = j2k_get_color_spec( p_stream->fmt->video.primaries,
539
0
                                                 p_stream->fmt->video.transfer,
540
0
                                                 p_stream->fmt->video.space );
541
0
                memcpy( &p_data[24], p_stream->fmt->p_extra, p_stream->fmt->i_extra );
542
0
                dvbpsi_pmt_es_descriptor_add( p_es, 0x32, 24 + p_stream->fmt->i_extra, p_data );
543
0
                free(p_data);
544
0
            }
545
0
        }
546
958
        else if( p_stream->fmt->i_codec == VLC_CODEC_DIRAC )
547
0
        {
548
            /* Dirac registration descriptor */
549
550
0
            uint8_t data[4] = { 'd', 'r', 'a', 'c' };
551
0
            dvbpsi_pmt_es_descriptor_add( p_es, 0x05, 4, data );
552
0
        }
553
958
        else if( p_stream->fmt->i_codec == VLC_CODEC_DTS )
554
5
        {
555
5
            uint8_t i_ver;
556
            /* DTS registration descriptor (ETSI TS 101 154 Annex F) */
557
5
            if( p_stream->fmt->i_profile == PROFILE_DTS_HD )
558
0
            {
559
0
                i_ver = 'H';
560
0
            }
561
5
            else if (stdc_has_single_bit(p_stream->fmt->audio.i_frame_length))
562
0
            {
563
0
                i_ver = stdc_trailing_zeros( p_stream->fmt->audio.i_frame_length >> 8 );
564
0
                if(i_ver == 0 || i_ver > 3)
565
0
                   i_ver = 1;
566
0
                i_ver += '0';
567
0
            }
568
5
            else i_ver = '0';
569
5
            uint8_t data[4] = { 'D', 'T', 'S', i_ver };
570
5
            dvbpsi_pmt_es_descriptor_add( p_es, 0x05, 4, data );
571
5
        }
572
953
        else if( p_stream->fmt->i_codec == VLC_CODEC_A52 )
573
0
        {
574
0
            uint8_t format[4] = { 'A', 'C', '-', '3'};
575
576
            /* "registration" descriptor : "AC-3" */
577
0
            dvbpsi_pmt_es_descriptor_add( p_es, 0x05, 4, format );
578
579
0
            if( standard == TS_MUX_STANDARD_ATSC )
580
0
            {
581
0
                assert(p_stream->ts->i_stream_type == 0x81);
582
                /* FIXME: ATSC AC-3 audio_stream_descriptor */
583
0
                uint8_t data[1] = { 0x00 };
584
0
                dvbpsi_pmt_es_descriptor_add( p_es, 0x81, 1, data );
585
0
            }
586
0
            else
587
0
            {
588
                /* FIXME: DVB AC-3 descriptor */
589
0
                uint8_t data[1] = { 0x00 };
590
0
                dvbpsi_pmt_es_descriptor_add( p_es, 0x6a, 1, data );
591
0
            }
592
0
        }
593
953
        else if( p_stream->fmt->i_codec == VLC_CODEC_EAC3 )
594
106
        {
595
106
            uint8_t format[4] = { 'E', 'A', 'C', '3'};
596
597
            /* "registration" descriptor : "EAC3" */
598
106
            dvbpsi_pmt_es_descriptor_add( p_es, 0x05, 4, format );
599
600
106
            if( standard == TS_MUX_STANDARD_ATSC )
601
0
            {
602
0
                assert( p_stream->ts->i_stream_type == 0x87 );
603
                /* FIXME: ATSC EAC3 audio_stream_descriptor */
604
0
                uint8_t data[1] = { 0x00 };
605
0
                dvbpsi_pmt_es_descriptor_add( p_es, 0xcc, 1, data );
606
                /* FIXME: ATSC A-71 stream_info_details */
607
0
            }
608
106
            else
609
106
            {
610
106
                uint8_t data[1] = { 0x00 };
611
106
                dvbpsi_pmt_es_descriptor_add( p_es, 0x7a, 1, data );
612
106
            }
613
106
        }
614
847
        else if( p_stream->fmt->i_codec == VLC_CODEC_OPUS )
615
0
        {
616
0
            uint8_t data[2] = {
617
0
                0x80, /* tag extension */
618
0
                p_stream->fmt->audio.i_channels
619
0
            };
620
0
            dvbpsi_pmt_es_descriptor_add( p_es, 0x7f, 2, data );
621
0
            uint8_t format[4] = { 'O', 'p', 'u', 's'};
622
            /* "registration" descriptor : "Opus" */
623
0
            dvbpsi_pmt_es_descriptor_add( p_es, 0x05, 4, format );
624
0
        }
625
847
        else if( p_stream->fmt->i_codec == VLC_CODEC_TELETEXT )
626
0
        {
627
0
            if( p_stream->fmt->i_extra )
628
0
            {
629
0
                dvbpsi_pmt_es_descriptor_add( p_es, 0x56,
630
0
                                           p_stream->fmt->i_extra,
631
0
                                           p_stream->fmt->p_extra );
632
0
            }
633
0
            continue;
634
0
        }
635
847
        else if( p_stream->fmt->i_codec == VLC_CODEC_DVBS )
636
0
        {
637
            /* DVB subtitles */
638
0
            if( p_stream->fmt->i_extra )
639
0
            {
640
                /* pass-through from the TS demux */
641
0
                dvbpsi_pmt_es_descriptor_add( p_es, 0x59,
642
0
                                           p_stream->fmt->i_extra,
643
0
                                           p_stream->fmt->p_extra );
644
0
            }
645
0
            else
646
0
            {
647
                /* from the dvbsub transcoder */
648
0
                dvbpsi_subtitling_dr_t descr;
649
0
                dvbpsi_subtitle_t sub;
650
0
                dvbpsi_descriptor_t *p_descr;
651
652
0
                memcpy( sub.i_iso6392_language_code, p_stream->pes->lang, 3 );
653
0
                sub.i_subtitling_type = 0x10; /* no aspect-ratio criticality */
654
0
                sub.i_composition_page_id = p_stream->pes->i_es_id & 0xFF;
655
0
                sub.i_ancillary_page_id = p_stream->pes->i_es_id >> 16;
656
657
0
                descr.i_subtitles_number = 1;
658
0
                descr.p_subtitle[0] = sub;
659
660
0
                p_descr = dvbpsi_GenSubtitlingDr( &descr, 0 );
661
0
                /* Work around bug in old libdvbpsi */ p_descr->i_length = 8;
662
0
                dvbpsi_pmt_es_descriptor_add( p_es, p_descr->i_tag,
663
0
                                           p_descr->i_length, p_descr->p_data );
664
0
            }
665
0
            continue;
666
0
        }
667
668
958
        if( p_stream->pes->i_langs )
669
0
        {
670
0
            dvbpsi_pmt_es_descriptor_add( p_es, 0x0a, 4*p_stream->pes->i_langs,
671
0
                p_stream->pes->lang);
672
0
        }
673
674
958
        if( p_stream->ts->b_scramble )
675
0
        {
676
0
            if( standard == TS_MUX_STANDARD_DVB )
677
0
            {
678
                /* scrambling_descriptor() */
679
0
                uint8_t data[1] = { 0x01 /* CSA1 */ };
680
0
                dvbpsi_pmt_es_descriptor_add( p_es, 0x65, 1, data );
681
0
            }
682
0
        }
683
684
958
        if( p_sdt )
685
0
        {
686
0
            UpdateServiceType( &p_service_infos[p_stream->i_mapped_prog],
687
0
                               p_stream->ts, p_stream->fmt );
688
0
        }
689
958
    }
690
691
1.56k
    for (unsigned i = 0; i < i_programs; i++ )
692
784
    {
693
784
        dvbpsi_psi_section_t *sect = dvbpsi_pmt_sections_generate( p_dvbpsi, &dvbpmt[i] );
694
784
        if( likely(sect) )
695
784
        {
696
784
            block_t *pmt = WritePSISection( sect );
697
784
            if( likely(pmt) )
698
784
            {
699
784
                PEStoTS( p_opaque, pf_callback, pmt, p_pmt[i].i_pid,
700
784
                         &p_pmt[i].b_discontinuity, &p_pmt[i].i_continuity_counter );
701
784
            }
702
784
            dvbpsi_DeletePSISections(sect);
703
784
        }
704
784
        dvbpsi_pmt_empty( &dvbpmt[i] );
705
784
    }
706
784
    free( dvbpmt );
707
708
784
    if( p_sdt )
709
0
    {
710
0
        for (unsigned i = 0; i < i_programs; i++ )
711
0
        {
712
0
            dvbpsi_sdt_service_t *p_service = dvbpsi_sdt_service_add( &sdtpsi,
713
0
                                                                      pi_programs_number[i], /* service id */
714
0
                                                                      false,     /* eit schedule */
715
0
                                                                      false,     /* eit present */
716
0
                                                                      4,         /* running status ("4=RUNNING") */
717
0
                                                                      p_service_infos[i].b_scrambled ); /* free ca */
718
719
0
            const char *psz_sdtprov = p_sdt->desc[i].psz_provider;
720
0
            const char *psz_sdtserv = p_sdt->desc[i].psz_service_name;
721
722
0
            uint8_t p_sdt_desc[4 + 255 * 2];
723
0
            size_t i_sdt_desc = 0;
724
725
            /* mapped service type according to es types */
726
0
            p_sdt_desc[i_sdt_desc++] = p_service_infos[i].type;
727
728
            /* service provider name length */
729
0
            i_sdt_desc += Write_AnnexA_String( &p_sdt_desc[i_sdt_desc], psz_sdtprov );
730
731
            /* service name length */
732
0
            i_sdt_desc += Write_AnnexA_String( &p_sdt_desc[i_sdt_desc], psz_sdtserv );
733
734
0
            dvbpsi_sdt_service_descriptor_add( p_service, 0x48, i_sdt_desc, p_sdt_desc );
735
0
        }
736
0
        free( p_service_infos );
737
738
0
        dvbpsi_psi_section_t *sect = dvbpsi_sdt_sections_generate( p_dvbpsi, &sdtpsi );
739
0
        if( likely(sect) )
740
0
        {
741
0
            block_t *p_sdtblock = WritePSISection( sect );
742
0
            if( likely(p_sdtblock) )
743
0
            {
744
0
                PEStoTS( p_opaque, pf_callback, p_sdtblock, p_sdt->ts.i_pid,
745
0
                         &p_sdt->ts.b_discontinuity, &p_sdt->ts.i_continuity_counter );
746
0
            }
747
0
            dvbpsi_DeletePSISections( sect );
748
0
        }
749
0
        dvbpsi_sdt_empty( &sdtpsi );
750
0
    }
751
784
}
752
753
int FillPMTESParams( ts_mux_standard standard, const es_format_t *fmt,
754
                     tsmux_stream_t *ts, pesmux_stream_t *pes )
755
958
{
756
958
    switch( fmt->i_codec )
757
958
    {
758
    /* VIDEO */
759
760
11
    case VLC_CODEC_MPGV:
761
11
    case VLC_CODEC_MP2V:
762
11
    case VLC_CODEC_MP1V:
763
        /* TODO: do we need to check MPEG-I/II ? */
764
11
        ts->i_stream_type = 0x02;
765
11
        pes->i_stream_id = 0xe0;
766
11
        break;
767
0
    case VLC_CODEC_MP4V:
768
0
        ts->i_stream_type = 0x10;
769
0
        pes->i_stream_id = 0xe0;
770
0
        pes->i_es_id = ts->i_pid;
771
0
        break;
772
0
    case VLC_CODEC_HEVC:
773
0
        ts->i_stream_type = 0x24;
774
0
        pes->i_stream_id = 0xe0;
775
0
        break;
776
1
    case VLC_CODEC_H264:
777
1
        ts->i_stream_type = 0x1b;
778
1
        pes->i_stream_id = 0xe0;
779
1
        break;
780
    /* XXX dirty dirty but somebody want crapy MS-codec XXX */
781
0
    case VLC_CODEC_H263I:
782
0
    case VLC_CODEC_H263:
783
0
    case VLC_CODEC_WMV3:
784
0
    case VLC_CODEC_WMV2:
785
0
    case VLC_CODEC_WMV1:
786
0
    case VLC_CODEC_DIV3:
787
0
    case VLC_CODEC_DIV2:
788
0
    case VLC_CODEC_DIV1:
789
0
    case VLC_CODEC_MJPG:
790
0
        ts->i_stream_type = 0xa0; /* private */
791
0
        pes->i_stream_id = 0xa0;   /* beurk */
792
0
        break;
793
0
    case VLC_CODEC_DIRAC:
794
        /* stream_id makes use of stream_id_extension */
795
0
        pes->i_stream_id = (PES_EXTENDED_STREAM_ID << 8) | 0x60;
796
0
        ts->i_stream_type = 0xd1;
797
0
        break;
798
0
    case VLC_CODEC_JPEG2000:
799
0
        if( !j2k_is_valid_framerate( fmt->video.i_frame_rate,
800
0
                                     fmt->video.i_frame_rate_base ) )
801
0
            return VLC_EGENERIC;
802
0
        ts->i_stream_type = 0x21;
803
0
        pes->i_stream_id = 0xbd;
804
0
    break;
805
806
    /* AUDIO */
807
808
509
    case VLC_CODEC_MPGA:
809
509
    case VLC_CODEC_MP2:
810
509
    case VLC_CODEC_MP3:
811
509
        ts->i_stream_type = fmt->audio.i_rate >= 32000 ? 0x03 : 0x04;
812
509
        pes->i_stream_id = 0xc0;
813
509
        break;
814
0
    case VLC_CODEC_A52:
815
0
        pes->i_stream_id = 0xbd;
816
0
        if( standard == TS_MUX_STANDARD_ATSC )
817
0
        {
818
0
            ts->i_stream_type = 0x81;
819
0
        }
820
0
        else
821
0
        {
822
0
            ts->i_stream_type = 0x06;
823
0
        }
824
0
        break;
825
0
    case VLC_CODEC_DVD_LPCM:
826
0
        ts->i_stream_type = 0x83;
827
0
        pes->i_stream_id = 0xbd;
828
0
        break;
829
0
    case VLC_CODEC_OPUS:
830
0
        if (fmt->audio.i_channels > 8)
831
0
            return VLC_EGENERIC;
832
0
        ts->i_stream_type = 0x06;
833
0
        pes->i_stream_id = 0xbd;
834
0
        break;
835
106
    case VLC_CODEC_EAC3:
836
106
        pes->i_stream_id = 0xbd;
837
106
        if( standard == TS_MUX_STANDARD_ATSC )
838
0
        {
839
            /* FIXME: Mandatory EAC3 audio_descriptor */
840
0
            ts->i_stream_type = 0x87;
841
0
        }
842
106
        else
843
106
        {
844
106
            ts->i_stream_type = 0x06;
845
106
        }
846
106
        break;
847
5
    case VLC_CODEC_DTS:
848
5
        if( standard == TS_MUX_STANDARD_ATSC )
849
0
        {
850
0
            return VLC_EGENERIC;
851
0
        }
852
5
        else
853
5
        {
854
5
            ts->i_stream_type = 0x06;
855
5
            pes->i_stream_id = 0xbd;
856
5
        }
857
5
        break;
858
326
    case VLC_CODEC_MP4A:
859
        /* XXX: make that configurable in some way when LOAS
860
         * is implemented for AAC in TS */
861
        //ts->i_stream_type = 0x11; /* LOAS/LATM */
862
326
        ts->i_stream_type = 0x0f; /* ADTS */
863
326
        pes->i_stream_id = 0xc0;
864
326
        pes->i_es_id = ts->i_pid;
865
326
        break;
866
867
    /* TEXT */
868
869
0
    case VLC_CODEC_SPU:
870
0
        ts->i_stream_type = 0x82;
871
0
        pes->i_stream_id = 0xbd;
872
0
        break;
873
0
    case VLC_CODEC_SUBT:
874
0
        ts->i_stream_type = 0x12;
875
0
        pes->i_stream_id = 0xfa;
876
0
        pes->i_es_id = ts->i_pid;
877
0
        break;
878
0
    case VLC_CODEC_DVBS:
879
0
        ts->i_stream_type = 0x06;
880
0
        pes->i_es_id = fmt->subs.dvb.i_id;
881
0
        pes->i_stream_id = 0xbd;
882
0
        break;
883
0
    case VLC_CODEC_TELETEXT:
884
0
        ts->i_stream_type = 0x06;
885
0
        pes->i_stream_id = 0xbd; /* FIXME */
886
0
        break;
887
888
0
    default:
889
0
        return VLC_EGENERIC;
890
958
    }
891
892
958
    return VLC_SUCCESS;
893
958
}
894
895
#endif