Coverage Report

Created: 2026-09-01 07:42

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