Coverage Report

Created: 2026-03-07 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/demux/mpeg/mpeg4_iod.c
Line
Count
Source
1
/*****************************************************************************
2
 * mpeg4_iod.c: ISO 14496-1 IOD and OD parsers
3
 *****************************************************************************
4
 * Copyright (C) 2004-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
21
/*****************************************************************************
22
 * Preamble
23
 *****************************************************************************/
24
25
#ifdef HAVE_CONFIG_H
26
# include "config.h"
27
#endif
28
29
#include <vlc_common.h>
30
#include <vlc_bits.h>
31
32
#include "mpeg4_iod.h"
33
34
#include <stdlib.h>
35
36
//#define OD_DEBUG 1
37
static void od_debug( vlc_object_t *p_object, const char *format, ... )
38
354k
{
39
#ifdef OD_DEBUG
40
    va_list ap;
41
    va_start(ap, format);
42
    msg_GenericVa( p_object, VLC_MSG_DBG, format, ap );
43
    va_end(ap);
44
#else
45
354k
    VLC_UNUSED(format);
46
354k
    VLC_UNUSED(p_object);
47
354k
#endif
48
354k
}
49
50
/*****************************************************************************
51
 * MP4 specific functions (OD parser)
52
 *****************************************************************************/
53
static unsigned ODDescriptorLength( unsigned *pi_data, const uint8_t **pp_data )
54
209k
{
55
209k
    unsigned int i_b;
56
209k
    unsigned int i_len = 0;
57
58
209k
    if(*pi_data == 0)
59
48
        return 0;
60
61
209k
    do
62
266k
    {
63
266k
        i_b = **pp_data;
64
266k
        (*pp_data)++;
65
266k
        (*pi_data)--;
66
266k
        i_len = ( i_len << 7 ) + ( i_b&0x7f );
67
68
266k
    } while( i_b&0x80 && *pi_data > 0 );
69
70
209k
    if (i_len > *pi_data)
71
15.7k
        i_len = *pi_data;
72
73
209k
    return i_len;
74
209k
}
75
76
static unsigned ODGetBytes( unsigned *pi_data, const uint8_t **pp_data, size_t bytes )
77
929k
{
78
929k
    unsigned res = 0;
79
2.48M
    while( *pi_data > 0 && bytes-- )
80
1.55M
    {
81
1.55M
        res <<= 8;
82
1.55M
        res |= **pp_data;
83
1.55M
        (*pp_data)++;
84
1.55M
        (*pi_data)--;
85
1.55M
    }
86
87
929k
    return res;
88
929k
}
89
90
static char* ODGetURL( unsigned *pi_data, const uint8_t **pp_data )
91
74
{
92
74
    unsigned len = ODGetBytes( pi_data, pp_data, 1 );
93
74
    if (len > *pi_data)
94
38
        len = *pi_data;
95
74
    char *url = strndup( (char*)*pp_data, len );
96
74
    *pp_data += len;
97
74
    *pi_data -= len;
98
74
    return url;
99
74
}
100
101
46.2k
#define ODTag_ObjectDescr           0x01
102
9.89k
#define ODTag_InitialObjectDescr    0x02
103
72.4k
#define ODTag_ESDescr               0x03
104
76.2k
#define ODTag_DecConfigDescr        0x04
105
63.1k
#define ODTag_DecSpecificDescr      0x05
106
72.8k
#define ODTag_SLDescr               0x06
107
108
/* Unified pointer for read helper */
109
typedef union
110
{
111
    od_descriptor_t *p_od;
112
    od_descriptor_t **pp_ods;
113
    es_mpeg4_descriptor_t *es_descr;
114
    decoder_config_descriptor_t *p_dec_config;
115
    sl_config_descriptor_t *sl_descr;
116
} od_read_params_t;
117
118
static uint8_t OD_Desc_Read( vlc_object_t *, unsigned *, const uint8_t **, uint8_t, uint8_t, od_read_params_t params );
119
120
34.7k
#define SL_Predefined_Custom 0x00
121
1
#define SL_Predefined_NULL   0x01
122
1
#define SL_Predefined_MP4    0x02
123
static bool OD_SLDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
124
                             od_read_params_t params )
125
34.7k
{
126
34.7k
    sl_config_descriptor_t *sl_descr = params.sl_descr;
127
128
34.7k
    uint8_t i_predefined = ODGetBytes( &i_data, &p_data, 1 );
129
34.7k
    switch( i_predefined )
130
34.7k
    {
131
34.7k
    case SL_Predefined_Custom:
132
34.7k
        if( i_data < 15 )
133
2
            return false;
134
34.6k
        sl_descr->i_flags = ODGetBytes( &i_data, &p_data, 1 );
135
34.6k
        sl_descr->i_timestamp_resolution = ODGetBytes( &i_data, &p_data, 4 );
136
34.6k
        sl_descr->i_OCR_resolution = ODGetBytes( &i_data, &p_data, 4 );
137
34.6k
        sl_descr->i_timestamp_length = ODGetBytes( &i_data, &p_data, 1 );
138
34.6k
        sl_descr->i_OCR_length = ODGetBytes( &i_data, &p_data, 1 );
139
34.6k
        sl_descr->i_AU_length = ODGetBytes( &i_data, &p_data, 1 );
140
34.6k
        sl_descr->i_instant_bitrate_length = ODGetBytes( &i_data, &p_data, 1 );
141
34.6k
        uint16_t i16 = ODGetBytes( &i_data, &p_data, 2 );
142
34.6k
        sl_descr->i_degradation_priority_length = i16 >> 12;
143
34.6k
        sl_descr->i_AU_seqnum_length = (i16 >> 7) & 0x1f;
144
34.6k
        sl_descr->i_packet_seqnum_length = (i16 >> 2) & 0x1f;
145
34.6k
        break;
146
1
    case SL_Predefined_NULL:
147
1
        memset( sl_descr, 0, sizeof(*sl_descr) );
148
1
        sl_descr->i_timestamp_resolution = 1000;
149
1
        sl_descr->i_timestamp_length = 32;
150
1
        break;
151
1
    case SL_Predefined_MP4:
152
1
        memset( sl_descr, 0, sizeof(*sl_descr) );
153
1
        sl_descr->i_flags = USE_TIMESTAMPS_FLAG;
154
1
        break;
155
70
    default:
156
        /* reserved */
157
70
        return false;
158
34.7k
    }
159
160
34.7k
    if( sl_descr->i_flags & USE_DURATION_FLAG )
161
138
    {
162
138
        if( i_data < 8 )
163
138
            return false;
164
0
        sl_descr->i_timescale = ODGetBytes( &i_data, &p_data, 4 );
165
0
        sl_descr->i_accessunit_duration = ODGetBytes( &i_data, &p_data, 2 );
166
0
        sl_descr->i_compositionunit_duration = ODGetBytes( &i_data, &p_data, 2 );
167
0
    }
168
169
34.5k
    if( (sl_descr->i_flags & USE_TIMESTAMPS_FLAG) == 0 )
170
55
    {
171
55
        bs_t s;
172
55
        bs_init( &s, p_data, i_data );
173
55
        sl_descr->i_startdecoding_timestamp = bs_read( &s, sl_descr->i_timestamp_length );
174
55
        sl_descr->i_startcomposition_timestamp = bs_read( &s, sl_descr->i_timestamp_length );
175
55
    }
176
177
34.5k
    od_debug( p_object, "   * read sl desc predefined: 0x%x", i_predefined );
178
34.5k
    return true;
179
34.7k
}
180
181
static bool OD_DecSpecificDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
182
                                      od_read_params_t params )
183
25.1k
{
184
25.1k
    VLC_UNUSED(p_object);
185
25.1k
    decoder_config_descriptor_t *p_dec_config = params.p_dec_config;
186
187
25.1k
    p_dec_config->p_extra = malloc( i_data );
188
25.1k
    if( p_dec_config->p_extra )
189
25.1k
    {
190
25.1k
        p_dec_config->i_extra = i_data;
191
25.1k
        memcpy( p_dec_config->p_extra, p_data, p_dec_config->i_extra );
192
25.1k
    }
193
194
25.1k
    return !!p_dec_config->i_extra;
195
25.1k
}
196
197
static bool OD_DecConfigDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
198
                                    od_read_params_t params )
199
38.0k
{
200
38.0k
    decoder_config_descriptor_t *p_dec_config = params.p_dec_config;
201
202
38.0k
    if( i_data < 13 )
203
87
        return false;
204
205
37.9k
    p_dec_config->i_objectTypeIndication = ODGetBytes( &i_data, &p_data, 1 );
206
37.9k
    uint8_t i_flags = ODGetBytes( &i_data, &p_data, 1 );
207
37.9k
    p_dec_config->i_streamType = i_flags >> 2;
208
209
37.9k
    ODGetBytes( &i_data, &p_data, 3 ); /* bufferSizeDB */
210
37.9k
    ODGetBytes( &i_data, &p_data, 4 ); /* maxBitrate */
211
37.9k
    ODGetBytes( &i_data, &p_data, 4 ); /* avgBitrate */
212
213
    /* DecoderSpecificDescr */
214
37.9k
    OD_Desc_Read( p_object, &i_data, &p_data,
215
37.9k
                   ODTag_DecSpecificDescr, 1, params );
216
217
37.9k
    od_debug( p_object, "   * read decoder objecttype: %x streamtype:%x extra: %u",
218
37.9k
               p_dec_config->i_objectTypeIndication, p_dec_config->i_streamType, p_dec_config->i_extra );
219
    /* ProfileLevelIndicator [0..255] */
220
37.9k
    return true;
221
38.0k
}
222
223
static bool OD_ESDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
224
                             od_read_params_t params )
225
38.6k
{
226
38.6k
    es_mpeg4_descriptor_t *es_descr = params.es_descr;
227
228
38.6k
    if ( i_data < 3 )
229
1
        return false;
230
38.6k
    es_descr->i_es_id = ODGetBytes( &i_data, &p_data, 2 );
231
38.6k
    uint8_t i_flags = ODGetBytes( &i_data, &p_data, 1 );
232
233
38.6k
    if( ( i_flags >> 7 )&0x01 )
234
81
    {
235
81
        if ( i_data < 2 )
236
64
            return false;
237
17
        ODGetBytes( &i_data, &p_data, 2 ); /* dependOn_es_id */
238
17
    }
239
240
38.5k
    if( (i_flags >> 6) & 0x01 )
241
27
        es_descr->psz_url = ODGetURL( &i_data, &p_data );
242
243
38.5k
    if( ( i_flags >> 5 )&0x01 )
244
38.4k
    {
245
38.4k
        if ( i_data < 2 )
246
394
            return false;
247
38.0k
        ODGetBytes( &i_data, &p_data, 2 ); /* OCR_es_id */
248
38.0k
    }
249
250
38.1k
    od_debug( p_object, "   * read ES Descriptor for es id %"PRIx16, es_descr->i_es_id );
251
252
    /* DecoderConfigDescr */
253
38.1k
    params.p_dec_config = &es_descr->dec_descr;
254
38.1k
    if ( 1 != OD_Desc_Read( p_object, &i_data, &p_data,
255
38.1k
                             ODTag_DecConfigDescr, 1, params ) )
256
145
        return false;
257
258
    /* SLDescr */
259
38.0k
    params.sl_descr = &es_descr->sl_descr;
260
38.0k
    OD_Desc_Read( p_object, &i_data, &p_data, ODTag_SLDescr, 1, params );
261
262
    /* IPI / IP / IPMP ... */
263
264
38.0k
    es_descr->b_ok = true;
265
266
38.0k
    return true;
267
38.1k
}
268
269
static bool OD_InitialObjectDesc_Read( vlc_object_t *p_object, unsigned i_data,
270
                                        const uint8_t *p_data, od_read_params_t params )
271
4.94k
{
272
4.94k
    od_descriptor_t *p_iod = params.p_od;
273
4.94k
    if( i_data < 3 + 5 + 2 )
274
0
        return false;
275
276
4.94k
    p_iod->i_ID = ( ODGetBytes( &i_data, &p_data, 1 ) << 2 );
277
4.94k
    uint8_t i_flags = ODGetBytes( &i_data, &p_data, 1 );
278
4.94k
    p_iod->i_ID |= i_flags >> 6;
279
280
4.94k
    od_debug( p_object, "  * ObjectDescriptorID: %"PRIu16, p_iod->i_ID );
281
4.94k
    od_debug( p_object, "  * includeInlineProfileLevel flag: 0x%"PRIx8, ( i_flags >> 4 )&0x01 );
282
4.94k
    if ( (i_flags >> 5) & 0x01 )
283
0
    {
284
0
        p_iod->psz_url = ODGetURL( &i_data, &p_data );
285
0
        od_debug( p_object, "  * URL: %s", p_iod->psz_url );
286
0
        return true; /* leaves out unparsed remaining extdescr */
287
0
    }
288
289
4.94k
    if( i_data < 5 + 2 ) /* at least one ES desc */
290
0
        return false;
291
292
    /* Profile Level Indication */
293
4.94k
    ODGetBytes( &i_data, &p_data, 1 ); /* OD */
294
4.94k
    ODGetBytes( &i_data, &p_data, 1 ); /* scene */
295
4.94k
    ODGetBytes( &i_data, &p_data, 1 ); /* audio */
296
4.94k
    ODGetBytes( &i_data, &p_data, 1 ); /* visual */
297
4.94k
    ODGetBytes( &i_data, &p_data, 1 ); /* graphics */
298
299
    /* Now read */
300
    /* 1..255 ESdescr */
301
4.94k
    uint8_t i_desc_count = OD_Desc_Read( p_object, &i_data, &p_data,
302
4.94k
                                          ODTag_ESDescr, ES_DESCRIPTOR_COUNT, params );
303
4.94k
    if( i_desc_count == 0 )
304
0
    {
305
0
        od_debug( p_object, "   * missing ES Descriptor" );
306
0
        return false;
307
0
    }
308
309
    /* 0..255 OCIdescr */
310
    /* 0..255 IPMPdescpointer */
311
    /* 0..255 IPMPdesc */
312
    /* 0..1   IPMPtoollistdesc */
313
    /* 0..255 Extensiondescr */
314
315
4.94k
    return true;
316
4.94k
}
317
318
static bool ODObjectDescriptorRead( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
319
                                  od_read_params_t params )
320
28.9k
{
321
28.9k
    od_descriptor_t *p_iod = params.p_od;
322
28.9k
    if( i_data < 3 + 2 )
323
73
        return false;
324
325
28.8k
    p_iod->i_ID = ( ODGetBytes( &i_data, &p_data, 1 ) << 2 );
326
28.8k
    uint8_t i_flags = ODGetBytes( &i_data, &p_data, 1 );
327
28.8k
    p_iod->i_ID |= i_flags >> 6;
328
329
28.8k
    od_debug( p_object, "  * ObjectDescriptorID: %"PRIu16, p_iod->i_ID );
330
28.8k
    if ( (i_flags >> 5) & 0x01 )
331
47
    {
332
47
        p_iod->psz_url = ODGetURL( &i_data, &p_data );
333
47
        od_debug( p_object, "  * URL: %s", p_iod->psz_url );
334
47
        return true;
335
47
    }
336
337
28.8k
    if( i_data < 2 ) /* at least one ES desc */
338
0
        return false;
339
340
    /* 1..255 ESdescr */
341
28.8k
    uint8_t i_desc_count = OD_Desc_Read( p_object, &i_data, &p_data,
342
28.8k
                                          ODTag_ESDescr, ES_DESCRIPTOR_COUNT, params );
343
28.8k
    if( i_desc_count == 0 )
344
96
    {
345
96
        od_debug( p_object, "   * missing ES Descriptor" );
346
96
        return false;
347
96
    }
348
349
    /* 0..255 OCIdescr */
350
    /* 0..255 IPMPdescpointer */
351
    /* 0..255 IPMPdesc */
352
    /* 0..1   IPMPtoollistdesc */
353
    /* 0..255 Extensiondescr */
354
355
28.7k
    return true;
356
28.8k
}
357
358
static uint8_t OD_Desc_Read( vlc_object_t *p_object, unsigned *pi_data, const uint8_t **pp_data,
359
                              uint8_t i_target_tag, uint8_t i_max_desc, od_read_params_t params )
360
170k
{
361
170k
    uint8_t i_read_count = 0;
362
363
340k
    for (unsigned i = 0; *pi_data > 2 && i < i_max_desc; i++)
364
180k
    {
365
180k
        const uint8_t i_tag = ODGetBytes( pi_data, pp_data, 1 );
366
180k
        const unsigned i_length = ODDescriptorLength( pi_data, pp_data );
367
180k
        if( i_target_tag != i_tag || i_length > *pi_data )
368
9.83k
            break;
369
370
170k
        unsigned i_descriptor_data = i_length;
371
170k
        const uint8_t *p_descriptor_data = *pp_data;
372
373
170k
        od_debug( p_object, "  Reading descriptor 0x%"PRIx8": found tag 0x%"PRIx8" left %d",
374
170k
                   i_target_tag, i_tag, *pi_data );
375
170k
        switch( i_tag )
376
170k
        {
377
28.9k
            case ODTag_ObjectDescr:
378
28.9k
            {
379
28.9k
                od_descriptor_t *p_od = calloc( 1, sizeof( od_descriptor_t ) );
380
28.9k
                if( !p_od )
381
0
                    break;
382
28.9k
                od_read_params_t childparams;
383
28.9k
                childparams.p_od = params.pp_ods[i_read_count] = p_od;
384
                /* od_descriptor_t *p_iod = (od_descriptor_t *) param; */
385
28.9k
                if ( !ODObjectDescriptorRead( p_object, i_descriptor_data,
386
28.9k
                                               p_descriptor_data, childparams ) )
387
169
                {};
388
28.9k
                break;
389
28.9k
            }
390
391
4.94k
            case ODTag_InitialObjectDescr:
392
4.94k
            {
393
4.94k
                od_descriptor_t *p_iod = calloc( 1, sizeof( od_descriptor_t ) );
394
4.94k
                if( !p_iod )
395
0
                    break;
396
4.94k
                od_read_params_t childparams;
397
4.94k
                childparams.p_od = params.pp_ods[i_read_count] = p_iod;
398
                /* od_descriptor_t *p_iod = (od_descriptor_t *) param; */
399
4.94k
                if ( !OD_InitialObjectDesc_Read( p_object, i_descriptor_data,
400
4.94k
                                                  p_descriptor_data, childparams ) )
401
0
                {};
402
4.94k
                break;
403
4.94k
            }
404
405
38.6k
            case ODTag_ESDescr: /**/
406
38.6k
            {
407
38.6k
                od_descriptor_t *p_iod = params.p_od;
408
38.6k
                od_read_params_t childparams;
409
38.6k
                childparams.es_descr = &p_iod->es_descr[i_read_count];
410
38.6k
                if ( !OD_ESDesc_Read( p_object, i_descriptor_data,
411
38.6k
                                       p_descriptor_data, childparams ) )
412
604
                {};
413
38.6k
                break;
414
4.94k
            }
415
416
38.0k
            case ODTag_DecConfigDescr:
417
38.0k
            {
418
38.0k
                if ( !OD_DecConfigDesc_Read( p_object, i_descriptor_data,
419
38.0k
                                              p_descriptor_data, params ) )
420
87
                {};
421
38.0k
                break;
422
4.94k
            }
423
424
25.1k
            case ODTag_DecSpecificDescr:
425
25.1k
            {
426
25.1k
                if ( !OD_DecSpecificDesc_Read( p_object, i_descriptor_data,
427
25.1k
                                                p_descriptor_data, params ) )
428
0
                {};
429
25.1k
                break;
430
4.94k
            }
431
432
34.7k
            case ODTag_SLDescr:
433
34.7k
            {
434
34.7k
                if ( !OD_SLDesc_Read( p_object, i_descriptor_data,
435
34.7k
                                       p_descriptor_data, params ) )
436
210
                {};
437
34.7k
                break;
438
4.94k
            }
439
440
0
            default:
441
0
                od_debug( p_object, "trying to read unsupported descriptor" );
442
0
                break;
443
170k
        }
444
445
170k
        *pp_data += i_length;
446
170k
        *pi_data -= i_length;
447
448
170k
        i_read_count++;
449
170k
    }
450
451
170k
    return i_read_count;
452
170k
}
453
454
static uint8_t ODInit( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
455
                       uint8_t i_start_tag, uint8_t i_min, uint8_t i_max, od_descriptor_t **pp_ods )
456
22.2k
{
457
22.2k
    od_read_params_t params;
458
22.2k
    params.pp_ods = pp_ods;
459
22.2k
    uint8_t i_read = OD_Desc_Read( p_object, &i_data, &p_data, i_start_tag, i_max, params );
460
22.2k
    if ( i_read < i_min )
461
1.06k
    {
462
1.06k
        od_debug( p_object, "   cannot read first tag 0x%"PRIx8, i_start_tag );
463
1.06k
        return 0;
464
1.06k
    }
465
466
21.2k
    return i_read;
467
22.2k
}
468
469
od_descriptor_t *IODNew( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data )
470
4.94k
{
471
4.94k
    if( i_data < 4 )
472
0
        return NULL;
473
474
4.94k
    uint8_t i_iod_scope = ODGetBytes( &i_data, &p_data, 1 ); /* scope */
475
4.94k
    uint8_t i_iod_label = ODGetBytes( &i_data, &p_data, 1 );
476
4.94k
    if( i_iod_label == 0x02 ) /* old vlc's buggy implementation of the OD_descriptor */
477
0
    {
478
0
        i_iod_label = i_iod_scope;
479
0
        i_iod_scope = 0x10; /* Add the missing front iod scope byte */
480
0
        i_data++; p_data--; /* next byte must be tag */
481
0
    }
482
483
4.94k
    od_debug( p_object, "  * iod label:0x%"PRIx8" scope:0x%"PRIx8,
484
4.94k
               i_iod_label, i_iod_scope );
485
486
4.94k
    if( i_iod_scope != 0x10 && i_iod_scope != 0x11 ) /* Uniqueness in program or transport */
487
0
    {
488
0
        od_debug( p_object, "  * can't handle reserved scope 0x%"PRIx8, i_iod_scope );
489
0
        return NULL;
490
0
    }
491
492
4.94k
    od_descriptor_t * ods[1];
493
4.94k
    uint8_t i_count = ODInit( p_object, i_data, p_data, ODTag_InitialObjectDescr, 1, 1, ods );
494
4.94k
    if( !i_count )
495
0
    {
496
0
        ODFree( ods[0] );
497
0
        return NULL;
498
0
    }
499
4.94k
    return ods[0];
500
4.94k
}
501
502
void ODFree( od_descriptor_t *p_iod )
503
33.8k
{
504
33.8k
    if( p_iod->psz_url )
505
47
    {
506
47
        free( p_iod->psz_url );
507
47
        free( p_iod );
508
47
        return;
509
47
    }
510
511
8.65M
    for( int i = 0; i < 255; i++ )
512
8.61M
    {
513
8.69M
#define es_descr p_iod->es_descr[i]
514
8.61M
        if( es_descr.b_ok )
515
38.0k
        {
516
38.0k
            if( es_descr.psz_url )
517
4
                free( es_descr.psz_url );
518
38.0k
            else
519
38.0k
                free( es_descr.dec_descr.p_extra );
520
38.0k
        }
521
8.61M
#undef  es_descr
522
8.61M
    }
523
33.8k
    free( p_iod );
524
33.8k
}
525
526
/*****************************************************************************
527
 * SL Packet Parser
528
 *****************************************************************************/
529
sl_header_data DecodeSLHeader( unsigned i_data, const uint8_t *p_data,
530
                               const sl_config_descriptor_t *sl )
531
458k
{
532
458k
    sl_header_data ret = { 0 };
533
534
458k
    bs_t s;
535
458k
    bs_init( &s, p_data, i_data );
536
537
458k
    bool b_has_ocr = false;
538
458k
    bool b_is_idle = false;
539
458k
    bool b_has_padding = false;
540
458k
    uint8_t i_padding = 0;
541
542
458k
    if( sl->i_flags & USE_ACCESS_UNIT_START_FLAG )
543
396k
        ret.b_au_start = bs_read1( &s );
544
458k
    if( sl->i_flags & USE_ACCESS_UNIT_END_FLAG )
545
395k
        ret.b_au_end = bs_read1( &s );
546
458k
    if( sl->i_OCR_length > 0 )
547
202k
        b_has_ocr = bs_read1( &s );
548
458k
    if( sl->i_flags & USE_IDLE_FLAG )
549
397k
        b_is_idle = bs_read1( &s );
550
458k
    if( sl->i_flags & USE_PADDING_FLAG )
551
4.18k
        b_has_padding = bs_read1( &s );
552
553
458k
    if( ret.b_au_end == ret.b_au_start && ret.b_au_start == false )
554
127k
        ret.b_au_end = ret.b_au_start = true;
555
556
458k
    if( b_has_padding )
557
2.08k
        i_padding = bs_read( &s, 3 );
558
559
    /* Optional fields */
560
458k
    if( !b_is_idle && ( !b_has_padding || !i_padding ) ) /* When not idle and not only padding */
561
428k
    {
562
428k
        bool b_has_dts = false;
563
428k
        bool b_has_cts = false;
564
428k
        bool b_has_instant_bitrate = false;
565
428k
        struct
566
428k
        {
567
428k
            bool *p_b;
568
428k
            vlc_tick_t *p_t;
569
428k
        } const timestamps[2] = { { &b_has_dts, &ret.i_dts }, { &b_has_cts, &ret.i_pts } };
570
571
428k
        bs_read( &s, sl->i_packet_seqnum_length );
572
573
428k
        if( sl->i_degradation_priority_length && bs_read1( &s ) )
574
2.95k
            bs_read( &s, sl->i_degradation_priority_length );
575
576
428k
        if( b_has_ocr )
577
19.7k
            bs_read( &s, sl->i_OCR_length );
578
579
428k
        if ( ret.b_au_start )
580
425k
        {
581
425k
            if( sl->i_flags & USE_RANDOM_ACCESS_POINT_FLAG )
582
3.50k
                bs_read1( &s );
583
584
425k
            bs_read( &s, sl->i_AU_seqnum_length );
585
586
425k
            if ( sl->i_flags & USE_TIMESTAMPS_FLAG )
587
362k
            {
588
362k
                b_has_dts = bs_read1( &s );
589
362k
                b_has_cts = bs_read1( &s );
590
362k
            }
591
592
425k
            if( sl->i_instant_bitrate_length )
593
6.49k
                b_has_instant_bitrate = bs_read1( &s );
594
595
1.27M
            for( int i=0; i<2; i++ )
596
850k
            {
597
850k
                if( !*(timestamps[i].p_b) )
598
519k
                    continue;
599
331k
                uint64_t i_read = bs_read( &s, __MIN( 32, sl->i_timestamp_length ) );
600
331k
                if( sl->i_timestamp_length > 32 )
601
318k
                {
602
318k
                    uint8_t i_bits = __MAX( 1, sl->i_timestamp_length - 32 );
603
318k
                    i_read = i_read << i_bits;
604
318k
                    i_read |= bs_read( &s, i_bits );
605
318k
                }
606
331k
                if( sl->i_timestamp_resolution )
607
317k
                    *(timestamps[i].p_t) = VLC_TICK_0 +
608
317k
                        vlc_tick_from_samples(i_read, sl->i_timestamp_resolution);
609
331k
            }
610
611
425k
            bs_read( &s, sl->i_AU_length );
612
613
425k
            if( b_has_instant_bitrate )
614
1.89k
                bs_read( &s, sl->i_instant_bitrate_length );
615
425k
        }
616
617
        /* more to read if ExtSLConfigDescrTag */
618
428k
    }
619
620
458k
    if ( b_has_padding && !i_padding ) /* all padding */
621
1.74k
        ret.i_size =  i_data;
622
457k
    else
623
457k
        ret.i_size = (bs_pos( &s ) + 7) / 8;
624
625
458k
    return ret;
626
458k
}
627
628
/*****************************************************************************
629
 * OD Commands Parser
630
 *****************************************************************************/
631
17.3k
#define ODTag_ObjectDescrUpdate 0x01
632
455
#define ODTag_ObjectDescrRemove 0x02
633
634
struct bsearch_key
635
{
636
    uint16_t id;
637
    const od_descriptor_t ***ppp_lowerbest;
638
};
639
640
static int bsearch_cmp( const void *key_, const void *el_ )
641
38.0k
{
642
38.0k
    const struct bsearch_key *key = key_;
643
38.0k
    const od_descriptor_t *el = *((const od_descriptor_t **) el_);
644
38.0k
    if( key->id < el->i_ID )
645
11.1k
        return -1;
646
26.8k
    if( key->ppp_lowerbest )
647
24.6k
        *key->ppp_lowerbest = (const od_descriptor_t **) el_;
648
26.8k
    if( key->id > el->i_ID )
649
5.78k
        return 1;
650
21.1k
    return 0;
651
26.8k
}
652
653
static void ObjectDescrUpdateCommandRead( vlc_object_t *p_object, od_descriptors_t *p_ods,
654
                                          unsigned i_data, const uint8_t *p_data )
655
17.3k
{
656
17.3k
    od_descriptor_t *p_odsread[255];
657
17.3k
    uint8_t i_count = ODInit( p_object, i_data, p_data, ODTag_ObjectDescr, 1, 255, p_odsread );
658
46.2k
    for( int i=0; i<i_count; i++ )
659
28.9k
    {
660
28.9k
        od_descriptor_t *p_od = p_odsread[i];
661
28.9k
        const od_descriptor_t **pp_lowerbest = NULL;
662
28.9k
        struct bsearch_key key = { .id = p_od->i_ID, .ppp_lowerbest = &pp_lowerbest };
663
28.9k
        od_descriptor_t **pp_cur = bsearch( &key, p_ods->objects.p_elems,
664
28.9k
                                            p_ods->objects.i_size, sizeof(*pp_cur),
665
28.9k
                                            bsearch_cmp );
666
28.9k
        if ( pp_cur )
667
21.0k
        {
668
21.0k
            int i_pos = pp_cur - p_ods->objects.p_elems;
669
21.0k
            ODFree( *pp_cur );
670
21.0k
            p_ods->objects.p_elems[i_pos] = p_od;
671
21.0k
        }
672
7.85k
        else
673
7.85k
        {
674
7.85k
            int i_pos = pp_lowerbest ? pp_lowerbest - (const od_descriptor_t **) p_ods->objects.p_elems + 1 : 0;
675
7.85k
            ARRAY_INSERT( p_ods->objects, p_od, i_pos );
676
7.85k
        }
677
28.9k
    }
678
17.3k
}
679
680
static void ObjectDescrRemoveCommandRead( vlc_object_t *p_object, od_descriptors_t *p_ods,
681
                                          unsigned i_data, const uint8_t *p_data )
682
455
{
683
455
    VLC_UNUSED(p_object);
684
455
    bs_t s;
685
455
    bs_init( &s, p_data, i_data );
686
6.50k
    for( unsigned i=0; i< (i_data * 8 / 10); i++ )
687
6.04k
    {
688
6.04k
        struct bsearch_key key = { 0 };
689
6.04k
        key.id = bs_read( &s, 10 );
690
6.04k
        od_descriptor_t **pp_cur = bsearch( &key, p_ods->objects.p_elems,
691
6.04k
                                            p_ods->objects.i_size, sizeof(*pp_cur),
692
6.04k
                                            bsearch_cmp );
693
6.04k
        if( pp_cur )
694
27
            ARRAY_REMOVE( p_ods->objects, pp_cur - p_ods->objects.p_elems );
695
6.04k
    }
696
455
}
697
698
void DecodeODCommand( vlc_object_t *p_object, od_descriptors_t *p_ods,
699
                      unsigned i_data, const uint8_t *p_data )
700
18.1k
{
701
46.9k
    while( i_data )
702
28.9k
    {
703
28.9k
        const uint8_t i_tag = ODGetBytes( &i_data, &p_data, 1 );
704
28.9k
        const unsigned i_length = ODDescriptorLength( &i_data, &p_data );
705
28.9k
        if( !i_length || i_length > i_data )
706
162
            break;
707
28.8k
        od_debug( p_object, "Decode tag 0x%x length %d", i_tag, i_length );
708
28.8k
        switch( i_tag )
709
28.8k
        {
710
17.3k
            case ODTag_ObjectDescrUpdate:
711
17.3k
                ObjectDescrUpdateCommandRead( p_object, p_ods, i_length, p_data );
712
17.3k
                break;
713
455
            case ODTag_ObjectDescrRemove:
714
455
                ObjectDescrRemoveCommandRead( p_object, p_ods, i_length, p_data );
715
455
                break;
716
11.0k
            default:
717
11.0k
                break;
718
28.8k
        }
719
28.8k
        p_data += i_length;
720
28.8k
        i_data -= i_length;
721
28.8k
    }
722
18.1k
}