Coverage Report

Created: 2026-05-30 08:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/demux/mp4/libmp4.c
Line
Count
Source
1
/*****************************************************************************
2
 * libmp4.c : LibMP4 library for mp4 module for vlc
3
 *****************************************************************************
4
 * Copyright (C) 2001-2004, 2010 VLC authors and VideoLAN
5
 *
6
 * Author: Laurent Aimar <fenrir@via.ecp.fr>
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation; either version 2.1 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 * GNU Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program; if not, write to the Free Software Foundation,
20
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21
 *****************************************************************************/
22
23
#ifdef HAVE_CONFIG_H
24
# include "config.h"
25
#endif
26
27
#include <vlc_common.h>
28
#include <vlc_stream.h>                               /* vlc_stream_Peek*/
29
#include <vlc_strings.h>                              /* vlc_ascii_tolower */
30
31
#ifdef HAVE_ZLIB_H
32
#   include <zlib.h>                                  /* for compressed moov */
33
#endif
34
35
#include "libmp4.h"
36
#include "languages.h"
37
#include <math.h>
38
#include <assert.h>
39
#include <limits.h>
40
#include <stdckdint.h>
41
42
13.2k
#define MP4_DEPTH_MAX 32
43
44
/* Some assumptions:
45
 * The input method HAS to be seekable
46
 */
47
48
/* convert 16.16 fixed point to floating point */
49
16.3k
static double conv_fx( int32_t fx ) {
50
16.3k
    double fp = fx;
51
16.3k
    fp /= 65536.;
52
16.3k
    return fp;
53
16.3k
}
54
55
/* some functions for mp4 encoding of variables */
56
#ifdef MP4_VERBOSE
57
static char * MP4_Time2Str( stime_t i_duration, uint32_t i_scale )
58
2.38k
{
59
2.38k
    uint64_t i_time = (i_scale) ? i_duration / i_scale : 0;
60
2.38k
    unsigned h = ( i_time /( 60*60 ) ) % 60;
61
2.38k
    unsigned m = ( i_time / 60 ) % 60;
62
2.38k
    unsigned s = i_time % 60;
63
2.38k
    uint64_t ms;
64
2.38k
    if ( i_scale == 0 || ckd_mul( &ms, 1000, i_duration ) )
65
22
        ms = 0;
66
2.36k
    else
67
2.36k
        ms = (ms / i_scale) % 1000;
68
69
2.38k
    char *out;
70
2.38k
    if( asprintf( &out, "%u:%.2u:%.2u:%.3" PRIu64, h, m, s, ms ) < 0 )
71
0
        return NULL;
72
2.38k
    return out;
73
2.38k
}
74
#endif
75
76
#define MP4_GETX_PRIVATE(dst, code, size) \
77
1.75M
    do \
78
1.75M
    { \
79
1.75M
        if( (i_read) >= (size) ) \
80
1.75M
        { \
81
1.74M
            dst = (code); \
82
1.74M
            p_peek += (size); \
83
1.74M
            i_read -= (size); \
84
1.74M
        } \
85
1.75M
        else \
86
1.75M
        { \
87
4.24k
            dst = 0; \
88
4.24k
            i_read = 0; \
89
4.24k
        } \
90
1.75M
    } while(0)
91
92
#define MP4_COPY_BYTES( dst, size ) \
93
0
    do \
94
0
    { \
95
0
        if( (i_read) >= (size) ) \
96
0
        { \
97
0
            memcpy( &dst, p_peek, size ); \
98
0
            p_peek += (size); \
99
0
            i_read -= (size); \
100
0
        } \
101
0
        else \
102
0
        { \
103
0
            dst = 0; \
104
0
            i_read = 0; \
105
0
        } \
106
0
    } while(0)
107
108
#define MP4_SKIPBYTES(size) \
109
3.91k
    do \
110
3.91k
    { \
111
3.91k
        if( (i_read) >= (size) ) \
112
3.91k
        { \
113
3.89k
            p_peek += (size); \
114
3.89k
            i_read -= (size); \
115
3.89k
        } \
116
3.91k
        else \
117
3.91k
        { \
118
17
            i_read = 0; \
119
17
        } \
120
3.91k
    } while(0)
121
122
350k
#define MP4_GET1BYTE( dst )  MP4_GETX_PRIVATE( dst, *p_peek, 1 )
123
27.1k
#define MP4_GET2BYTES( dst ) MP4_GETX_PRIVATE( dst, GetWBE(p_peek), 2 )
124
17.8k
#define MP4_GET3BYTES( dst ) MP4_GETX_PRIVATE( dst, Get24bBE(p_peek), 3 )
125
1.30M
#define MP4_GET4BYTES( dst ) MP4_GETX_PRIVATE( dst, GetDWBE(p_peek), 4 )
126
3.36k
#define MP4_GET8BYTES( dst ) MP4_GETX_PRIVATE( dst, GetQWBE(p_peek), 8 )
127
128
130
#define MP4_GET2BYTESLE( dst ) MP4_GETX_PRIVATE( dst, GetWLE(p_peek), 2 )
129
53.0k
#define MP4_GET4BYTESLE( dst ) MP4_GETX_PRIVATE( dst, GetDWLE(p_peek), 4 )
130
#define MP4_GET8BYTESLE( dst ) MP4_GETX_PRIVATE( dst, GetQWLE(p_peek), 8 )
131
52.9k
#define MP4_GETFOURCC( dst )   MP4_GET4BYTESLE( dst )
132
133
#define MP4_GETVERSIONFLAGS( p_void ) \
134
17.5k
    MP4_GET1BYTE( p_void->i_version ); \
135
17.5k
    MP4_GET3BYTES( p_void->i_flags )
136
137
#define READ_SAMPLE_DESC_COMMON_8BYTES_HEADER \
138
1.37k
    do\
139
1.37k
    {\
140
1.37k
        if( i_read < 8 )\
141
1.37k
            MP4_READBOX_EXIT( 0 );\
142
9.56k
        for( unsigned i = 0; i < 6 ; i++ )\
143
1.36k
            MP4_GET1BYTE( p_box->data.p_sample_gen->i_reserved1[i] );\
144
1.36k
        MP4_GET2BYTES( p_box->data.p_sample_gen->i_data_reference_index );\
145
1.36k
    } while(0)
146
147
148
static char *mp4_getstringz( uint8_t **restrict in, uint64_t *restrict size )
149
373
{
150
373
    assert( *size <= SSIZE_MAX );
151
152
373
    if( *size == 0 )
153
307
        return NULL;
154
155
66
    if( *in == 0 ) /* Null string stored */
156
0
    {
157
0
        *in += 1;
158
0
        *size -= 1;
159
0
        return NULL;
160
0
    }
161
162
66
    size_t len = strnlen( (const char *)*in, *size );
163
66
    if( len == 0 || len >= *size )
164
44
        return NULL;
165
166
22
    len++;
167
168
22
    char *ret = malloc( len );
169
22
    if( likely(ret != NULL) )
170
22
        memcpy( ret, *in, len );
171
22
    *in += len;
172
22
    *size -= len;
173
22
    return ret;
174
66
}
175
176
#define MP4_GETSTRINGZ( p_str ) \
177
348
    do \
178
348
        (p_str) = mp4_getstringz( &p_peek, &i_read ); \
179
348
    while(0)
180
181
/* This macro is used when we want to printf the box type
182
 * APPLE annotation box is :
183
 *  either 0xA9 + 24-bit ASCII text string (and 0xA9 isn't printable)
184
 *  either 32-bit ASCII text string
185
 */
186
41.1k
#define MP4_BOX_TYPE_ASCII() ( ((unsigned char*)&p_box->i_type)[0] != 0xA9 )
187
188
static inline uint32_t Get24bBE( const uint8_t *p )
189
17.7k
{
190
17.7k
    return( ( p[0] <<16 ) + ( p[1] <<8 ) + p[2] );
191
17.7k
}
192
193
static inline void GetUUID( UUID_t *p_uuid, const uint8_t *p_buff )
194
7
{
195
7
    memcpy( p_uuid, p_buff, 16 );
196
7
}
197
198
static unsigned GetDepth( const MP4_Box_t *box )
199
13.2k
{
200
13.2k
    unsigned i = 0;
201
69.4k
    for( ; box ; box = box->p_father )
202
56.1k
        i++;
203
13.2k
    return i;
204
13.2k
}
205
206
static video_palette_t * ReadQuicktimePalette( uint8_t **pp_peek, uint64_t *pi_read )
207
0
{
208
0
    uint8_t *p_peek = *pp_peek;
209
0
    uint64_t i_read = *pi_read;
210
0
    uint32_t v;
211
0
    MP4_GET4BYTES(v);
212
0
    if( v != 0 )
213
0
        return NULL;
214
0
    MP4_GET2BYTES(v); // should be == 0x8000, but does not in the wild
215
0
    uint16_t i_colors_count;
216
0
    MP4_GET2BYTES(i_colors_count);
217
0
    if( i_colors_count == UINT16_MAX ||
218
0
        ++i_colors_count > VIDEO_PALETTE_COLORS_MAX ||
219
0
        i_read < i_colors_count * 8U)
220
0
        return NULL;
221
0
    video_palette_t *p_palette = malloc( sizeof(video_palette_t) );
222
0
    if( p_palette == NULL )
223
0
        return NULL;
224
0
    for( uint16_t i=0; i<i_colors_count; i++ )
225
0
    {
226
0
        MP4_SKIPBYTES(2);
227
0
        MP4_GET2BYTES(p_palette->palette[i][0]);
228
0
        MP4_GET2BYTES(p_palette->palette[i][1]);
229
0
        MP4_GET2BYTES(p_palette->palette[i][2]);
230
0
        p_palette->palette[i][3] = 0xFF;
231
0
    }
232
0
    p_palette->i_entries = i_colors_count;
233
0
    *pp_peek = p_peek;
234
0
    *pi_read = i_read;
235
0
    return p_palette;
236
0
}
237
238
static uint8_t *mp4_readbox_enter_common( stream_t *s, MP4_Box_t *box,
239
                                          size_t typesize,
240
                                          void (*release)( MP4_Box_t * ),
241
                                          uint64_t readsize )
242
23.0k
{
243
23.0k
    const size_t headersize = mp4_box_headersize( box );
244
245
23.0k
    if( unlikely(readsize < headersize) || unlikely(readsize > SSIZE_MAX) )
246
14
        return NULL;
247
248
23.0k
    uint8_t *buf = malloc( readsize );
249
23.0k
    if( unlikely(buf == NULL) )
250
0
        return NULL;
251
252
23.0k
    ssize_t val = vlc_stream_Read( s, buf, readsize );
253
23.0k
    if( (size_t)val != readsize )
254
4
    {
255
4
        msg_Warn( s, "mp4: wanted %"PRIu64" bytes, got %zd", readsize, val );
256
4
        goto error;
257
4
    }
258
259
23.0k
    box->data.p_payload = calloc( 1, typesize );
260
23.0k
    if( unlikely(box->data.p_payload == NULL) )
261
0
        goto error;
262
263
23.0k
    box->pf_free = release;
264
23.0k
    return buf;
265
4
error:
266
4
    free( buf );
267
4
    return NULL;
268
23.0k
}
269
270
static uint8_t *mp4_readbox_enter_partial( stream_t *s, MP4_Box_t *box,
271
                                           size_t typesize,
272
                                           void (*release)( MP4_Box_t * ),
273
                                           uint64_t *restrict readsize )
274
2.68k
{
275
2.68k
    if( (uint64_t)*readsize > box->i_size )
276
6
        *readsize = box->i_size;
277
278
2.68k
    return mp4_readbox_enter_common( s, box, typesize, release, *readsize );
279
2.68k
}
280
281
static uint8_t *mp4_readbox_enter( stream_t *s, MP4_Box_t *box,
282
                                   size_t typesize,
283
                                   void (*release)( MP4_Box_t * ) )
284
20.3k
{
285
20.3k
    uint64_t readsize = box->i_size;
286
20.3k
    return mp4_readbox_enter_common( s, box, typesize, release, readsize );
287
20.3k
}
288
289
290
#define MP4_READBOX_ENTER_PARTIAL( MP4_Box_data_TYPE_t, maxread, release ) \
291
2.68k
    uint64_t i_read = (maxread); \
292
2.68k
    uint8_t *p_buff = mp4_readbox_enter_partial( p_stream, p_box, \
293
2.68k
        sizeof( MP4_Box_data_TYPE_t ), release, &i_read ); \
294
2.68k
    if( unlikely(p_buff == NULL) ) \
295
2.68k
        return 0; \
296
2.68k
    const size_t header_size = mp4_box_headersize( p_box ); \
297
2.68k
    uint8_t *p_peek = p_buff + header_size; \
298
2.68k
    i_read -= header_size
299
300
#define MP4_READBOX_ENTER( MP4_Box_data_TYPE_t, release ) \
301
20.3k
    uint8_t *p_buff = mp4_readbox_enter( p_stream, p_box, \
302
20.3k
        sizeof(MP4_Box_data_TYPE_t), release ); \
303
20.3k
    if( unlikely(p_buff == NULL) ) \
304
20.3k
        return 0; \
305
20.3k
    uint64_t i_read = p_box->i_size; \
306
20.3k
    const size_t header_size = mp4_box_headersize( p_box ); \
307
20.3k
    uint8_t *p_peek = p_buff + header_size; \
308
20.3k
    i_read -= header_size
309
310
#define MP4_READBOX_EXIT( i_code ) \
311
23.0k
    do \
312
23.0k
    { \
313
23.0k
        free( p_buff ); \
314
23.0k
        return( i_code ); \
315
23.0k
    } while (0)
316
317
/*****************************************************************************
318
 * Some prototypes.
319
 *****************************************************************************/
320
static MP4_Box_t *MP4_ReadBox( stream_t *p_stream, MP4_Box_t *p_father );
321
static MP4_Box_t *MP4_ReadBoxUsing( stream_t *p_stream, MP4_Box_t *p_father,
322
                                    int(*MP4_ReadBox_function)(stream_t *, MP4_Box_t *) );
323
static int MP4_Box_Read_Specific( stream_t *p_stream, MP4_Box_t *p_box, MP4_Box_t *p_father );
324
static int MP4_PeekBoxHeader( stream_t *p_stream, MP4_Box_t *p_box );
325
326
int MP4_Seek( stream_t *p_stream, uint64_t i_pos )
327
54.1k
{
328
54.1k
    bool b_canseek = false;
329
54.1k
    if ( vlc_stream_Control( p_stream, STREAM_CAN_SEEK, &b_canseek ) != VLC_SUCCESS ||
330
54.1k
         b_canseek )
331
54.1k
    {
332
        /* can seek or don't know */
333
54.1k
        return vlc_stream_Seek( p_stream, i_pos );
334
54.1k
    }
335
    /* obviously can't seek then */
336
337
0
    int64_t i_current_pos = vlc_stream_Tell( p_stream );
338
0
    if ( i_current_pos < 0 || i_pos < (uint64_t)i_current_pos )
339
0
        return VLC_EGENERIC;
340
341
0
    uint64_t i_toread = i_pos - i_current_pos;
342
0
    if( i_toread == 0 )
343
0
        return VLC_SUCCESS;
344
0
    if( i_toread > SSIZE_MAX ) // we can't read more than that
345
0
        return VLC_EGENERIC;
346
347
0
    if( vlc_stream_Read( p_stream, NULL, i_toread ) != (ssize_t) i_toread )
348
0
        return VLC_EGENERIC;
349
0
    return VLC_SUCCESS;
350
0
}
351
352
static void MP4_BoxAddChild( MP4_Box_t *p_parent, MP4_Box_t *p_childbox )
353
39.8k
{
354
39.8k
    if( !p_parent->p_first )
355
14.3k
            p_parent->p_first = p_childbox;
356
25.4k
    else
357
25.4k
            p_parent->p_last->p_next = p_childbox;
358
39.8k
    p_parent->p_last = p_childbox;
359
39.8k
    p_childbox->p_father = p_parent;
360
39.8k
}
361
362
MP4_Box_t * MP4_BoxExtract( MP4_Box_t **pp_chain, uint32_t i_type )
363
114
{
364
114
    MP4_Box_t *p_box = *pp_chain;
365
114
    while( p_box )
366
114
    {
367
114
        if( p_box->i_type == i_type )
368
114
        {
369
114
            *pp_chain = p_box->p_next;
370
114
            p_box->p_next = NULL;
371
114
            p_box->p_father = NULL;
372
114
            return p_box;
373
114
        }
374
0
        pp_chain = &p_box->p_next;
375
0
        p_box = p_box->p_next;
376
0
    }
377
0
    return NULL;
378
114
}
379
380
/* Don't use vlc_stream_Seek directly */
381
#undef vlc_stream_Seek
382
#define vlc_stream_Seek(a,b) __NO__
383
384
/*****************************************************************************
385
 * MP4_PeekBoxHeader : Load only common parameters for all boxes
386
 *****************************************************************************
387
 * p_box need to be an already allocated MP4_Box_t, and all data
388
 *  will only be peek not read
389
 *
390
 * RETURN : 0 if it fail, 1 otherwise
391
 *****************************************************************************/
392
static int MP4_PeekBoxHeader( stream_t *p_stream, MP4_Box_t *p_box )
393
45.8k
{
394
45.8k
    ssize_t i_read;
395
45.8k
    const uint8_t  *p_peek;
396
397
45.8k
    if( ( ( i_read = vlc_stream_Peek( p_stream, &p_peek, 32 ) ) < 8 ) )
398
1.77k
    {
399
1.77k
        return 0;
400
1.77k
    }
401
44.0k
    p_box->i_pos = vlc_stream_Tell( p_stream );
402
403
44.0k
    p_box->data.p_payload = NULL;
404
44.0k
    p_box->p_father = NULL;
405
44.0k
    p_box->p_first  = NULL;
406
44.0k
    p_box->p_last  = NULL;
407
44.0k
    p_box->p_next   = NULL;
408
409
44.0k
    MP4_GET4BYTES( p_box->i_shortsize );
410
44.0k
    MP4_GETFOURCC( p_box->i_type );
411
412
    /* Now special case */
413
414
44.0k
    if( p_box->i_shortsize == 1 )
415
138
    {
416
138
        if( i_read < 8 )
417
41
            return 0;
418
        /* get the true size on 64 bits */
419
97
        MP4_GET8BYTES( p_box->i_size );
420
97
    }
421
43.9k
    else
422
43.9k
    {
423
43.9k
        p_box->i_size = p_box->i_shortsize;
424
        /* XXX size of 0 means that the box extends to end of file */
425
43.9k
    }
426
427
43.9k
    if( UINT64_MAX - p_box->i_size < p_box->i_pos )
428
0
        return 0;
429
430
43.9k
    if( p_box->i_type == ATOM_uuid )
431
7
    {
432
7
        if( i_read < 16 )
433
0
            return 0;
434
        /* get extended type on 16 bytes */
435
7
        GetUUID( &p_box->i_uuid, p_peek );
436
7
    }
437
438
#ifdef MP4_ULTRA_VERBOSE
439
    if( p_box->i_size )
440
    {
441
        if MP4_BOX_TYPE_ASCII()
442
            msg_Dbg( p_stream, "found Box: %4.4s size %"PRId64" %"PRId64,
443
                    (char*)&p_box->i_type, p_box->i_size, p_box->i_pos );
444
        else
445
            msg_Dbg( p_stream, "found Box: c%3.3s size %"PRId64,
446
                    (char*)&p_box->i_type+1, p_box->i_size );
447
    }
448
#endif
449
450
43.9k
    return 1;
451
43.9k
}
452
453
/*****************************************************************************
454
 * MP4_ReadBoxRestricted : Reads box from current position
455
 *****************************************************************************
456
 * if p_box == NULL, box is invalid or failed, position undefined
457
 * on success, position is past read box or EOF
458
 *****************************************************************************/
459
static MP4_Box_t *MP4_ReadBoxRestricted( stream_t *p_stream, MP4_Box_t *p_father,
460
                                         const uint32_t stopbefore[], bool *pb_restrictionhit )
461
43.0k
{
462
43.0k
    MP4_Box_t peekbox = { 0 };
463
43.0k
    if ( !MP4_PeekBoxHeader( p_stream, &peekbox ) )
464
1.81k
        return NULL;
465
466
41.2k
    if( peekbox.i_size < 8 )
467
284
    {
468
284
        msg_Warn( p_stream, "found an invalid sized %"PRIu64" box %4.4s @%"PRIu64 ,
469
284
                  peekbox.i_size, (char *) &peekbox.i_type, vlc_stream_Tell(p_stream) );
470
284
        return NULL;
471
284
    }
472
473
41.2k
    for( size_t i=0; stopbefore && stopbefore[i]; i++ )
474
358
    {
475
358
        if( stopbefore[i] == peekbox.i_type )
476
46
        {
477
46
            *pb_restrictionhit = true;
478
46
            return NULL;
479
46
        }
480
358
    }
481
482
    /* if father's size == 0, it means unknown or infinite size,
483
     * and we skip the followong check */
484
40.9k
    if( p_father && p_father->i_size > 0 )
485
40.5k
    {
486
40.5k
        const uint64_t i_box_next = peekbox.i_size + peekbox.i_pos;
487
40.5k
        const uint64_t i_father_next = p_father->i_size + p_father->i_pos;
488
        /* check if it's within p-father */
489
40.5k
        if( i_box_next > i_father_next )
490
3.14k
        {
491
3.14k
            msg_Warn( p_stream, "out of bound child %4.4s", (char*) &peekbox.i_type );
492
3.14k
            return NULL; /* out of bound */
493
3.14k
        }
494
40.5k
    }
495
496
    /* Everything seems OK */
497
37.7k
    MP4_Box_t *p_box = (MP4_Box_t *) malloc( sizeof(MP4_Box_t) );
498
37.7k
    if( !p_box )
499
0
        return NULL;
500
37.7k
    *p_box = peekbox;
501
502
37.7k
    const uint64_t i_next = p_box->i_pos + p_box->i_size;
503
37.7k
    p_box->p_father = p_father;
504
37.7k
    if( MP4_Box_Read_Specific( p_stream, p_box, p_father ) != VLC_SUCCESS )
505
127
    {
506
127
        msg_Warn( p_stream, "Failed reading box %4.4s", (char*) &peekbox.i_type );
507
127
        MP4_BoxFree( p_box );
508
127
        p_box = NULL;
509
127
    }
510
511
    /* Check is we consumed all data */
512
37.7k
    if( vlc_stream_Tell( p_stream ) < i_next )
513
6.41k
    {
514
6.41k
        MP4_Seek( p_stream, i_next - 1 ); /*  since past seek can fail when hitting EOF */
515
6.41k
        MP4_Seek( p_stream, i_next );
516
6.41k
        if( vlc_stream_Tell( p_stream ) < i_next - 1 ) /* Truncated box */
517
0
        {
518
0
            msg_Warn( p_stream, "truncated box %4.4s discarded", (char*) &peekbox.i_type );
519
0
            MP4_BoxFree( p_box );
520
0
            p_box = NULL;
521
0
        }
522
6.41k
    }
523
524
37.7k
    if ( p_box )
525
37.6k
        MP4_BoxAddChild( p_father, p_box );
526
527
37.7k
    return p_box;
528
37.7k
}
529
530
/*****************************************************************************
531
 * For all known box a loader is given,
532
 * you have to be already read container header
533
 * without container size, file position on exit is unknown
534
 *****************************************************************************/
535
static int MP4_ReadBoxContainerChildrenIndexed( stream_t *p_stream,
536
               MP4_Box_t *p_container, const uint32_t stoplist[],
537
               const uint32_t excludelist[], bool b_indexed )
538
13.3k
{
539
    /* Size of root container is set to 0 when unknown, for example
540
     * with a DASH stream. In that case, we skip the following check */
541
13.3k
    if( (p_container->i_size || p_container->p_father)
542
13.1k
            && ( vlc_stream_Tell( p_stream ) + ((b_indexed)?16:8) >
543
13.1k
        (uint64_t)(p_container->i_pos + p_container->i_size) )
544
13.3k
      )
545
26
    {
546
        /* there is no box to load */
547
26
        return 0;
548
26
    }
549
550
13.2k
    if( GetDepth( p_container ) > MP4_DEPTH_MAX ) /* Prevent unbounded recursions */
551
0
        return 1;
552
553
13.2k
    uint64_t i_last_pos = 0; /* used to detect read failure loops */
554
13.2k
    const uint64_t i_end = p_container->i_pos + p_container->i_size;
555
13.2k
    MP4_Box_t *p_box = NULL;
556
13.2k
    bool b_onexclude = false;
557
13.2k
    bool b_continue;
558
13.2k
    do
559
43.4k
    {
560
43.4k
        b_continue = false;
561
43.4k
        if ( p_container->i_size )
562
42.9k
        {
563
42.9k
            const uint64_t i_tell = vlc_stream_Tell( p_stream );
564
42.9k
            if( i_tell + ((b_indexed)?16:8) >= i_end )
565
365
                break;
566
42.9k
        }
567
568
43.0k
        uint32_t i_index = 0;
569
43.0k
        if ( b_indexed )
570
10
        {
571
10
            uint8_t read[8];
572
10
            if ( vlc_stream_Read( p_stream, read, 8 ) < 8 )
573
0
                break;
574
10
            i_index = GetDWBE(&read[4]);
575
10
        }
576
43.0k
        b_onexclude = false; /* If stopped due exclude list */
577
43.0k
        if( (p_box = MP4_ReadBoxRestricted( p_stream, p_container, excludelist, &b_onexclude )) )
578
37.6k
        {
579
37.6k
            b_continue = true;
580
37.6k
            p_box->i_index = i_index;
581
42.2k
            for(size_t i=0; stoplist && stoplist[i]; i++)
582
6.08k
            {
583
6.08k
                if( p_box->i_type == stoplist[i] )
584
1.42k
                    return 1;
585
6.08k
            }
586
37.6k
        }
587
588
41.6k
        const uint64_t i_tell = vlc_stream_Tell( p_stream );
589
41.6k
        if ( p_container->i_size && i_tell >= i_end )
590
8.72k
        {
591
8.72k
            assert( i_tell == i_end );
592
8.72k
            break;
593
8.72k
        }
594
595
32.9k
        if ( !p_box )
596
5.37k
        {
597
            /* Continue with next if box fails to load */
598
5.37k
            if( i_last_pos == i_tell )
599
2.76k
                break;
600
2.61k
            i_last_pos = i_tell;
601
2.61k
            b_continue = true;
602
2.61k
        }
603
604
32.9k
    } while( b_continue );
605
606
    /* Always move to end of container */
607
11.8k
    if ( !b_onexclude &&  p_container->i_size )
608
11.8k
    {
609
11.8k
        const uint64_t i_tell = vlc_stream_Tell( p_stream );
610
11.8k
        if ( i_tell != i_end )
611
3.07k
            MP4_Seek( p_stream, i_end );
612
11.8k
    }
613
614
11.8k
    return 1;
615
13.2k
}
616
617
int MP4_ReadBoxContainerRestricted( stream_t *p_stream, MP4_Box_t *p_container,
618
                                    const uint32_t stoplist[], const uint32_t excludelist[] )
619
0
{
620
0
    return MP4_ReadBoxContainerChildrenIndexed( p_stream, p_container,
621
0
                                                stoplist, excludelist, false );
622
0
}
623
624
int MP4_ReadBoxContainerChildren( stream_t *p_stream, MP4_Box_t *p_container,
625
                                  const uint32_t stoplist[] )
626
13.2k
{
627
13.2k
    return MP4_ReadBoxContainerChildrenIndexed( p_stream, p_container,
628
13.2k
                                                stoplist, NULL, false );
629
13.2k
}
630
631
static void MP4_BoxOffsetUp( MP4_Box_t *p_box, uint64_t i_offset )
632
2.99k
{
633
4.95k
    while(p_box)
634
1.96k
    {
635
1.96k
        p_box->i_pos += i_offset;
636
1.96k
        MP4_BoxOffsetUp( p_box->p_first, i_offset );
637
1.96k
        p_box = p_box->p_next;
638
1.96k
    }
639
2.99k
}
640
641
/* Reads within an already read/in memory box (containers without having to seek) */
642
static int MP4_ReadBoxContainerRawInBox( stream_t *p_stream, MP4_Box_t *p_container,
643
                                         uint8_t *p_buffer, uint64_t i_size, uint64_t i_offset )
644
1.03k
{
645
1.03k
    if(!p_container)
646
0
        return 0;
647
1.03k
    stream_t *p_substream = vlc_stream_MemoryNew( p_stream, p_buffer, i_size,
648
1.03k
                                                  true );
649
1.03k
    if( !p_substream )
650
0
        return 0;
651
1.03k
    MP4_Box_t *p_last = p_container->p_last;
652
1.03k
    MP4_ReadBoxContainerChildren( p_substream, p_container, NULL );
653
1.03k
    vlc_stream_Delete( p_substream );
654
    /* do pos fixup */
655
1.03k
    if( p_container )
656
1.03k
    {
657
1.03k
        MP4_Box_t *p_box = p_last ? p_last : p_container->p_first;
658
1.03k
        MP4_BoxOffsetUp(p_box, i_offset);
659
1.03k
    }
660
661
1.03k
    return 1;
662
1.03k
}
663
664
static int MP4_ReadBoxContainer( stream_t *p_stream, MP4_Box_t *p_container )
665
8.80k
{
666
8.80k
    if( p_container->i_size &&
667
8.80k
        ( p_container->i_size <= (size_t)mp4_box_headersize(p_container ) + 8 ) )
668
124
    {
669
        /* container is empty, 8 stand for the first header in this box */
670
124
        return 1;
671
124
    }
672
673
    /* enter box */
674
8.67k
    if ( MP4_Seek( p_stream, p_container->i_pos +
675
8.67k
                      mp4_box_headersize( p_container ) ) )
676
0
        return 0;
677
8.67k
    return MP4_ReadBoxContainerChildren( p_stream, p_container, NULL );
678
8.67k
}
679
680
static int MP4_ReadBoxSkip( stream_t *p_stream, MP4_Box_t *p_box )
681
654
{
682
    /* XXX sometime moov is hidden in a free box */
683
654
    if( p_box->p_father &&
684
654
        p_box->p_father->i_type == ATOM_root &&
685
304
        p_box->i_type == ATOM_free )
686
104
    {
687
104
        const uint8_t *p_peek;
688
104
        size_t header_size = mp4_box_headersize( p_box ) + 4;
689
104
        vlc_fourcc_t i_fcc;
690
691
104
        ssize_t i_read = vlc_stream_Peek( p_stream, &p_peek, 44 );
692
104
        if( unlikely(i_read < (ssize_t)header_size) )
693
0
            return 0;
694
695
104
        p_peek += header_size;
696
104
        i_read -= header_size;
697
698
104
        if( i_read >= 8 )
699
104
        {
700
104
            i_fcc = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] );
701
702
104
            if( i_fcc == ATOM_cmov || i_fcc == ATOM_mvhd )
703
2
            {
704
2
                msg_Warn( p_stream, "detected moov hidden in a free box ..." );
705
706
2
                p_box->i_type = ATOM_foov;
707
2
                return MP4_ReadBoxContainer( p_stream, p_box );
708
2
            }
709
104
        }
710
104
    }
711
712
    /* Nothing to do */
713
#ifdef MP4_ULTRA_VERBOSE
714
    if MP4_BOX_TYPE_ASCII()
715
        msg_Dbg( p_stream, "skip box: \"%4.4s\"", (char*)&p_box->i_type );
716
    else
717
        msg_Dbg( p_stream, "skip box: \"c%3.3s\"", (char*)&p_box->i_type+1 );
718
#endif
719
652
    return 1;
720
654
}
721
722
static int MP4_ReadBox_mdia( stream_t *p_stream, MP4_Box_t *p_container )
723
1.33k
{
724
1.33k
    if( p_container->i_size &&
725
1.33k
        ( p_container->i_size <= (size_t)mp4_box_headersize(p_container ) + 8 ) )
726
0
    {
727
        /* container is empty, 8 stand for the first header in this box */
728
0
        return 1;
729
0
    }
730
731
    /* enter box */
732
1.33k
    if ( MP4_Seek( p_stream, p_container->i_pos +
733
1.33k
                               mp4_box_headersize( p_container ) ) )
734
0
        return 0;
735
1.33k
    int ret = MP4_ReadBoxContainerChildren( p_stream, p_container, NULL );
736
1.33k
    MP4_Box_t *stsd = MP4_BoxGet( p_container, "minf/stbl/stsd" );
737
1.33k
    if( stsd && stsd->i_handler == 0 )
738
90
    {
739
        /* Delayed parsing due to missing hdlr */
740
90
        if( MP4_Seek( p_stream, stsd->i_pos ) ||
741
90
            MP4_Box_Read_Specific( p_stream, stsd, stsd->p_father ) ||
742
90
            stsd->i_handler == 0 )
743
90
            msg_Warn( p_stream, "Failed to re-parse stsd" );
744
90
    }
745
746
1.33k
    return ret;
747
1.33k
}
748
749
static int MP4_ReadBox_ilst( stream_t *p_stream, MP4_Box_t *p_box )
750
42
{
751
42
    if( p_box->i_size < 8 || vlc_stream_Read( p_stream, NULL, 8 ) != 8 )
752
0
        return 0;
753
754
    /* Find our handler */
755
42
    if ( !p_box->i_handler && p_box->p_father )
756
42
    {
757
42
        const MP4_Box_t *p_sibling = p_box->p_father->p_first;
758
43
        while( p_sibling )
759
42
        {
760
42
            if ( p_sibling->i_type == ATOM_hdlr && p_sibling->data.p_hdlr )
761
41
            {
762
41
                p_box->i_handler = p_sibling->data.p_hdlr->i_handler_type;
763
41
                break;
764
41
            }
765
1
            p_sibling = p_sibling->p_next;
766
1
        }
767
42
    }
768
769
42
    switch( p_box->i_handler )
770
42
    {
771
1
    case 0:
772
1
        msg_Warn( p_stream, "no handler for ilst atom" );
773
1
        return 0;
774
3
    case HANDLER_mdta:
775
3
        return MP4_ReadBoxContainerChildrenIndexed( p_stream, p_box, NULL, NULL, true );
776
38
    case HANDLER_mdir:
777
38
        return MP4_ReadBoxContainerChildren( p_stream, p_box, NULL );
778
0
    default:
779
0
        msg_Warn( p_stream, "Unknown ilst handler type '%4.4s'", (char*)&p_box->i_handler );
780
0
        return 0;
781
42
    }
782
42
}
783
784
static void MP4_FreeBox_ftyp( MP4_Box_t *p_box )
785
711
{
786
711
    free( p_box->data.p_ftyp->i_compatible_brands );
787
711
}
788
789
static int MP4_ReadBox_ftyp( stream_t *p_stream, MP4_Box_t *p_box )
790
711
{
791
711
    MP4_READBOX_ENTER( MP4_Box_data_ftyp_t, MP4_FreeBox_ftyp );
792
793
711
    MP4_GETFOURCC( p_box->data.p_ftyp->i_major_brand );
794
711
    MP4_GET4BYTES( p_box->data.p_ftyp->i_minor_version );
795
796
711
    p_box->data.p_ftyp->i_compatible_brands_count = i_read / 4;
797
711
    if( p_box->data.p_ftyp->i_compatible_brands_count > 0 )
798
690
    {
799
690
        uint32_t *tab = p_box->data.p_ftyp->i_compatible_brands =
800
690
            vlc_alloc( p_box->data.p_ftyp->i_compatible_brands_count,
801
690
                       sizeof(uint32_t) );
802
803
690
        if( unlikely( tab == NULL ) )
804
0
            MP4_READBOX_EXIT( 0 );
805
806
3.60k
        for( unsigned i = 0; i < p_box->data.p_ftyp->i_compatible_brands_count; i++ )
807
2.91k
        {
808
2.91k
            MP4_GETFOURCC( tab[i] );
809
2.91k
        }
810
690
    }
811
21
    else
812
21
    {
813
21
        p_box->data.p_ftyp->i_compatible_brands = NULL;
814
21
    }
815
816
711
    MP4_READBOX_EXIT( 1 );
817
711
}
818
819
820
static int MP4_ReadBox_mvhd(  stream_t *p_stream, MP4_Box_t *p_box )
821
1.04k
{
822
1.04k
    MP4_READBOX_ENTER( MP4_Box_data_mvhd_t, NULL );
823
824
1.04k
    MP4_GETVERSIONFLAGS( p_box->data.p_mvhd );
825
826
1.04k
    if( p_box->data.p_mvhd->i_version )
827
61
    {
828
61
        MP4_GET8BYTES( p_box->data.p_mvhd->i_creation_time );
829
61
        MP4_GET8BYTES( p_box->data.p_mvhd->i_modification_time );
830
61
        MP4_GET4BYTES( p_box->data.p_mvhd->i_timescale );
831
61
        MP4_GET8BYTES( p_box->data.p_mvhd->i_duration );
832
61
    }
833
987
    else
834
987
    {
835
987
        MP4_GET4BYTES( p_box->data.p_mvhd->i_creation_time );
836
987
        MP4_GET4BYTES( p_box->data.p_mvhd->i_modification_time );
837
987
        MP4_GET4BYTES( p_box->data.p_mvhd->i_timescale );
838
987
        MP4_GET4BYTES( p_box->data.p_mvhd->i_duration );
839
987
    }
840
1.04k
    MP4_GET4BYTES( p_box->data.p_mvhd->i_rate );
841
1.04k
    MP4_GET2BYTES( p_box->data.p_mvhd->i_volume );
842
1.04k
    MP4_GET2BYTES( p_box->data.p_mvhd->i_reserved1 );
843
844
845
3.14k
    for( unsigned i = 0; i < 2; i++ )
846
2.09k
    {
847
2.09k
        MP4_GET4BYTES( p_box->data.p_mvhd->i_reserved2[i] );
848
2.09k
    }
849
10.4k
    for( unsigned i = 0; i < 9; i++ )
850
9.43k
    {
851
9.43k
        MP4_GET4BYTES( p_box->data.p_mvhd->i_matrix[i] );
852
9.43k
    }
853
7.33k
    for( unsigned i = 0; i < 6; i++ )
854
6.28k
    {
855
6.28k
        MP4_GET4BYTES( p_box->data.p_mvhd->i_predefined[i] );
856
6.28k
    }
857
858
1.04k
    MP4_GET4BYTES( p_box->data.p_mvhd->i_next_track_id );
859
860
861
1.04k
#ifdef MP4_VERBOSE
862
1.04k
    char *psz_duration = MP4_Time2Str( p_box->data.p_mvhd->i_duration, p_box->data.p_mvhd->i_timescale );
863
1.04k
    msg_Dbg( p_stream, "read box: \"mvhd\" timescale %"PRIu32" duration %"PRIu64" (%s) rate %.2f volume %.2f",
864
1.04k
                  p_box->data.p_mvhd->i_timescale,
865
1.04k
                  p_box->data.p_mvhd->i_duration,
866
1.04k
                  psz_duration,
867
1.04k
                  (float)p_box->data.p_mvhd->i_rate / (1<<16 ),
868
1.04k
                  (float)p_box->data.p_mvhd->i_volume / 256 );
869
1.04k
    free( psz_duration );
870
1.04k
#endif
871
1.04k
    MP4_READBOX_EXIT( 1 );
872
1.04k
}
873
874
static int MP4_ReadBox_mfhd(  stream_t *p_stream, MP4_Box_t *p_box )
875
258
{
876
258
    MP4_READBOX_ENTER( MP4_Box_data_mfhd_t, NULL );
877
878
258
    MP4_GETVERSIONFLAGS( p_box->data.p_mvhd );
879
880
258
    MP4_GET4BYTES( p_box->data.p_mfhd->i_sequence_number );
881
882
258
#ifdef MP4_VERBOSE
883
258
    msg_Dbg( p_stream, "read box: \"mfhd\" sequence number %d",
884
258
                  p_box->data.p_mfhd->i_sequence_number );
885
258
#endif
886
258
    MP4_READBOX_EXIT( 1 );
887
258
}
888
889
static int MP4_ReadBox_tfxd(  stream_t *p_stream, MP4_Box_t *p_box )
890
6
{
891
6
    MP4_READBOX_ENTER( MP4_Box_data_tfxd_t, NULL );
892
893
6
    MP4_Box_data_tfxd_t *p_tfxd_data = p_box->data.p_tfxd;
894
6
    MP4_GETVERSIONFLAGS( p_tfxd_data );
895
896
6
    if( p_tfxd_data->i_version == 0 )
897
6
    {
898
6
        MP4_GET4BYTES( p_tfxd_data->i_fragment_abs_time );
899
6
        MP4_GET4BYTES( p_tfxd_data->i_fragment_duration );
900
6
    }
901
0
    else
902
0
    {
903
0
        MP4_GET8BYTES( p_tfxd_data->i_fragment_abs_time );
904
0
        MP4_GET8BYTES( p_tfxd_data->i_fragment_duration );
905
0
    }
906
907
6
#ifdef MP4_VERBOSE
908
6
    msg_Dbg( p_stream, "read box: \"tfxd\" version %d, flags 0x%x, "\
909
6
            "fragment duration %"PRIu64", fragment abs time %"PRIu64,
910
6
                p_tfxd_data->i_version,
911
6
                p_tfxd_data->i_flags,
912
6
                p_tfxd_data->i_fragment_duration,
913
6
                p_tfxd_data->i_fragment_abs_time
914
6
           );
915
6
#endif
916
917
6
    MP4_READBOX_EXIT( 1 );
918
6
}
919
920
static void MP4_FreeBox_tfrf( MP4_Box_t *p_box )
921
0
{
922
0
    free( p_box->data.p_tfrf->p_tfrf_data_fields );
923
0
}
924
925
static int MP4_ReadBox_tfrf(  stream_t *p_stream, MP4_Box_t *p_box )
926
0
{
927
0
    MP4_READBOX_ENTER( MP4_Box_data_tfxd_t, MP4_FreeBox_tfrf );
928
929
0
    MP4_Box_data_tfrf_t *p_tfrf_data = p_box->data.p_tfrf;
930
0
    MP4_GETVERSIONFLAGS( p_tfrf_data );
931
932
0
    MP4_GET1BYTE( p_tfrf_data->i_fragment_count );
933
934
0
    p_tfrf_data->p_tfrf_data_fields = calloc( p_tfrf_data->i_fragment_count,
935
0
                                              sizeof( TfrfBoxDataFields_t ) );
936
0
    if( !p_tfrf_data->p_tfrf_data_fields )
937
0
        MP4_READBOX_EXIT( 0 );
938
939
0
    for( uint8_t i = 0; i < p_tfrf_data->i_fragment_count; i++ )
940
0
    {
941
0
        TfrfBoxDataFields_t *TfrfBoxDataField = &p_tfrf_data->p_tfrf_data_fields[i];
942
0
        if( p_tfrf_data->i_version == 0 )
943
0
        {
944
0
            MP4_GET4BYTES( TfrfBoxDataField->i_fragment_abs_time );
945
0
            MP4_GET4BYTES( TfrfBoxDataField->i_fragment_duration );
946
0
        }
947
0
        else
948
0
        {
949
0
            MP4_GET8BYTES( TfrfBoxDataField->i_fragment_abs_time );
950
0
            MP4_GET8BYTES( TfrfBoxDataField->i_fragment_duration );
951
0
        }
952
0
    }
953
954
0
#ifdef MP4_VERBOSE
955
0
    msg_Dbg( p_stream, "read box: \"tfrf\" version %d, flags 0x%x, "\
956
0
            "fragment count %"PRIu8, p_tfrf_data->i_version,
957
0
                p_tfrf_data->i_flags, p_tfrf_data->i_fragment_count );
958
959
0
    for( uint8_t i = 0; i < p_tfrf_data->i_fragment_count; i++ )
960
0
    {
961
0
        TfrfBoxDataFields_t *TfrfBoxDataField = &p_tfrf_data->p_tfrf_data_fields[i];
962
0
        msg_Dbg( p_stream, "\"tfrf\" fragment duration %"PRIu64", "\
963
0
                                    "fragment abs time %"PRIu64,
964
0
                    TfrfBoxDataField->i_fragment_duration,
965
0
                    TfrfBoxDataField->i_fragment_abs_time );
966
0
    }
967
968
0
#endif
969
970
0
    MP4_READBOX_EXIT( 1 );
971
0
}
972
973
static int MP4_ReadBox_XML360( stream_t *p_stream, MP4_Box_t *p_box )
974
0
{
975
0
    MP4_READBOX_ENTER( MP4_Box_data_360_t, NULL );
976
977
0
    MP4_Box_data_360_t *p_360_data = p_box->data.p_360;
978
979
    /* Copy the string for pattern matching as it does not end
980
    with a '\0' in the stream. */
981
0
    char *psz_rdf = strndup((char *)p_peek, i_read);
982
983
0
    if ( unlikely( !psz_rdf ) )
984
0
        MP4_READBOX_EXIT( 0 );
985
986
    /* Try to find the string "GSpherical:Spherical" because the v1
987
    spherical video spec says the tag must be there. */
988
989
0
    if ( strcasestr( psz_rdf, "Gspherical:Spherical" ) )
990
0
        p_360_data->i_projection_mode = PROJECTION_MODE_EQUIRECTANGULAR;
991
992
    /* Try to find the stero mode. */
993
0
    if ( strcasestr( psz_rdf, "left-right" ) )
994
0
    {
995
0
        msg_Dbg( p_stream, "Left-right stereo mode" );
996
0
        p_360_data->e_stereo_mode = XML360_STEREOSCOPIC_LEFT_RIGHT;
997
0
    }
998
999
0
    if ( strcasestr( psz_rdf, "top-bottom" ) )
1000
0
    {
1001
0
        msg_Dbg( p_stream, "Top-bottom stereo mode" );
1002
0
        p_360_data->e_stereo_mode = XML360_STEREOSCOPIC_TOP_BOTTOM;
1003
0
    }
1004
1005
0
    free( psz_rdf );
1006
1007
0
    MP4_READBOX_EXIT( 1 );
1008
0
}
1009
1010
static int MP4_ReadBox_st3d( stream_t *p_stream, MP4_Box_t *p_box )
1011
0
{
1012
0
    MP4_READBOX_ENTER( MP4_Box_data_st3d_t, NULL );
1013
1014
0
    uint8_t i_version;
1015
0
    MP4_GET1BYTE( i_version );
1016
0
    if ( i_version != 0 )
1017
0
        MP4_READBOX_EXIT( 0 );
1018
1019
0
    MP4_SKIPBYTES( 3 ); // flags
1020
1021
0
    MP4_Box_data_st3d_t *p_data = p_box->data.p_st3d;
1022
0
    MP4_GET1BYTE( p_data->i_stereo_mode );
1023
1024
0
    MP4_READBOX_EXIT( 1 );
1025
0
}
1026
1027
static int MP4_ReadBox_prhd( stream_t *p_stream, MP4_Box_t *p_box )
1028
0
{
1029
0
    MP4_READBOX_ENTER( MP4_Box_data_prhd_t, NULL );
1030
1031
0
    uint8_t i_version;
1032
0
    MP4_GET1BYTE( i_version );
1033
0
    if (i_version != 0)
1034
0
        MP4_READBOX_EXIT( 0 );
1035
1036
0
    MP4_SKIPBYTES( 3 ); // flags
1037
1038
0
    MP4_Box_data_prhd_t *p_data = p_box->data.p_prhd;
1039
0
    int32_t fixed16_16;
1040
0
    MP4_GET4BYTES( fixed16_16 );
1041
0
    p_data->f_pose_yaw_degrees   = (float) fixed16_16 / 65536.0f;
1042
1043
0
    MP4_GET4BYTES( fixed16_16 );
1044
0
    p_data->f_pose_pitch_degrees = (float) fixed16_16 / 65536.0f;
1045
1046
0
    MP4_GET4BYTES( fixed16_16 );
1047
0
    p_data->f_pose_roll_degrees  = (float) fixed16_16 / 65536.0f;
1048
1049
0
    MP4_READBOX_EXIT( 1 );
1050
0
}
1051
1052
static int MP4_ReadBox_equi( stream_t *p_stream, MP4_Box_t *p_box )
1053
0
{
1054
0
    MP4_READBOX_ENTER( MP4_Box_data_equi_t, NULL );
1055
1056
0
    uint8_t i_version;
1057
0
    MP4_GET1BYTE( i_version );
1058
0
    if (i_version != 0)
1059
0
        MP4_READBOX_EXIT( 0 );
1060
1061
0
    MP4_SKIPBYTES( 3 ); // flags
1062
1063
0
    MP4_Box_data_equi_t *p_data = p_box->data.p_equi;
1064
0
    MP4_GET4BYTES( p_data->i_projection_bounds_top );
1065
0
    MP4_GET4BYTES( p_data->i_projection_bounds_bottom );
1066
0
    MP4_GET4BYTES( p_data->i_projection_bounds_left );
1067
0
    MP4_GET4BYTES( p_data->i_projection_bounds_right );
1068
1069
0
    MP4_READBOX_EXIT( 1 );
1070
0
}
1071
1072
static int MP4_ReadBox_cbmp( stream_t *p_stream, MP4_Box_t *p_box )
1073
0
{
1074
0
    MP4_READBOX_ENTER( MP4_Box_data_cbmp_t, NULL );
1075
1076
0
    uint8_t i_version;
1077
0
    MP4_GET1BYTE( i_version );
1078
0
    if (i_version != 0)
1079
0
        MP4_READBOX_EXIT( 0 );
1080
1081
0
    MP4_SKIPBYTES( 3 ); // flags
1082
1083
0
    MP4_Box_data_cbmp_t *p_data = p_box->data.p_cbmp;
1084
0
    MP4_GET4BYTES( p_data->i_layout );
1085
0
    MP4_GET4BYTES( p_data->i_padding );
1086
1087
0
    MP4_READBOX_EXIT( 1 );
1088
0
}
1089
1090
static void MP4_FreeBox_sidx( MP4_Box_t *p_box )
1091
9
{
1092
9
    free( p_box->data.p_sidx->p_items );
1093
9
}
1094
1095
static int MP4_ReadBox_sidx(  stream_t *p_stream, MP4_Box_t *p_box )
1096
9
{
1097
9
    MP4_READBOX_ENTER( MP4_Box_data_sidx_t, MP4_FreeBox_sidx );
1098
1099
9
    MP4_Box_data_sidx_t *p_sidx_data = p_box->data.p_sidx;
1100
9
    MP4_GETVERSIONFLAGS( p_sidx_data );
1101
1102
9
    MP4_GET4BYTES( p_sidx_data->i_reference_ID );
1103
9
    MP4_GET4BYTES( p_sidx_data->i_timescale );
1104
1105
9
    if( p_sidx_data->i_version == 0 )
1106
9
    {
1107
9
        MP4_GET4BYTES( p_sidx_data->i_earliest_presentation_time );
1108
9
        MP4_GET4BYTES( p_sidx_data->i_first_offset );
1109
9
    }
1110
0
    else
1111
0
    {
1112
0
        MP4_GET8BYTES( p_sidx_data->i_earliest_presentation_time );
1113
0
        MP4_GET8BYTES( p_sidx_data->i_first_offset );
1114
0
    }
1115
1116
9
    uint16_t i_count;
1117
1118
9
    MP4_SKIPBYTES( 2 ); // reserved
1119
9
    MP4_GET2BYTES( i_count );
1120
9
    if( i_count == 0 )
1121
0
        MP4_READBOX_EXIT( 1 );
1122
1123
9
    p_sidx_data->i_reference_count = i_count;
1124
9
    p_sidx_data->p_items = vlc_alloc( i_count, sizeof( MP4_Box_sidx_item_t ) );
1125
9
    if( unlikely(p_sidx_data->p_items == NULL) )
1126
0
        MP4_READBOX_EXIT( 0 );
1127
1128
575
    for( unsigned i = 0; i < i_count; i++ )
1129
566
    {
1130
566
        MP4_Box_sidx_item_t *item = p_sidx_data->p_items + i;
1131
566
        uint32_t tmp;
1132
1133
566
        MP4_GET4BYTES( tmp );
1134
566
        item->b_reference_type = tmp >> 31;
1135
566
        item->i_referenced_size = tmp & 0x7fffffff;
1136
566
        MP4_GET4BYTES( item->i_subsegment_duration );
1137
1138
566
        MP4_GET4BYTES( tmp );
1139
566
        item->b_starts_with_SAP = tmp >> 31;
1140
566
        item->i_SAP_type = (tmp >> 24) & 0x70;
1141
566
        item->i_SAP_delta_time = tmp & 0xfffffff;
1142
566
    }
1143
1144
9
#ifdef MP4_VERBOSE
1145
9
    msg_Dbg( p_stream, "read box: \"sidx\" version %d, flags 0x%x, "\
1146
9
            "ref_ID %"PRIu32", timescale %"PRIu32", ref_count %"PRIu16", "\
1147
9
            "first subsegmt duration %"PRIu32,
1148
9
                p_sidx_data->i_version,
1149
9
                p_sidx_data->i_flags,
1150
9
                p_sidx_data->i_reference_ID,
1151
9
                p_sidx_data->i_timescale,
1152
9
                p_sidx_data->i_reference_count,
1153
9
                p_sidx_data->p_items[0].i_subsegment_duration
1154
9
           );
1155
9
#endif
1156
1157
9
    MP4_READBOX_EXIT( 1 );
1158
9
}
1159
1160
static int MP4_ReadBox_tfhd(  stream_t *p_stream, MP4_Box_t *p_box )
1161
266
{
1162
266
    MP4_READBOX_ENTER( MP4_Box_data_tfhd_t, NULL );
1163
1164
264
    MP4_GETVERSIONFLAGS( p_box->data.p_tfhd );
1165
1166
264
    if( p_box->data.p_tfhd->i_version != 0 )
1167
0
    {
1168
0
        msg_Warn( p_stream, "'tfhd' box with version != 0. "\
1169
0
                " Don't know what to do with that, please patch" );
1170
0
        MP4_READBOX_EXIT( 0 );
1171
0
    }
1172
1173
264
    MP4_GET4BYTES( p_box->data.p_tfhd->i_track_ID );
1174
1175
264
    if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DURATION_IS_EMPTY )
1176
4
    {
1177
4
        msg_Dbg( p_stream, "'duration-is-empty' flag is present "\
1178
4
                "=> no samples for this time interval." );
1179
4
        p_box->data.p_tfhd->b_empty = true;
1180
4
    }
1181
260
    else
1182
260
        p_box->data.p_tfhd->b_empty = false;
1183
1184
264
    if( p_box->data.p_tfhd->i_flags & MP4_TFHD_BASE_DATA_OFFSET )
1185
264
        MP4_GET8BYTES( p_box->data.p_tfhd->i_base_data_offset );
1186
264
    if( p_box->data.p_tfhd->i_flags & MP4_TFHD_SAMPLE_DESC_INDEX )
1187
264
        MP4_GET4BYTES( p_box->data.p_tfhd->i_sample_description_index );
1188
264
    if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_DURATION )
1189
264
        MP4_GET4BYTES( p_box->data.p_tfhd->i_default_sample_duration );
1190
264
    if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_SIZE )
1191
264
        MP4_GET4BYTES( p_box->data.p_tfhd->i_default_sample_size );
1192
264
    if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_FLAGS )
1193
264
        MP4_GET4BYTES( p_box->data.p_tfhd->i_default_sample_flags );
1194
1195
264
#ifdef MP4_VERBOSE
1196
264
    char psz_base[128] = "\0";
1197
264
    char psz_desc[128] = "\0";
1198
264
    char psz_dura[128] = "\0";
1199
264
    char psz_size[128] = "\0";
1200
264
    char psz_flag[128] = "\0";
1201
264
    if( p_box->data.p_tfhd->i_flags & MP4_TFHD_BASE_DATA_OFFSET )
1202
264
        snprintf(psz_base, sizeof(psz_base), "base offset %"PRId64, p_box->data.p_tfhd->i_base_data_offset);
1203
264
    if( p_box->data.p_tfhd->i_flags & MP4_TFHD_SAMPLE_DESC_INDEX )
1204
264
        snprintf(psz_desc, sizeof(psz_desc), "sample description index %d", p_box->data.p_tfhd->i_sample_description_index);
1205
264
    if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_DURATION )
1206
264
        snprintf(psz_dura, sizeof(psz_dura), "sample duration %d", p_box->data.p_tfhd->i_default_sample_duration);
1207
264
    if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_SIZE )
1208
264
        snprintf(psz_size, sizeof(psz_size), "sample size %d", p_box->data.p_tfhd->i_default_sample_size);
1209
264
    if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_FLAGS )
1210
264
        snprintf(psz_flag, sizeof(psz_flag), "sample flags 0x%x", p_box->data.p_tfhd->i_default_sample_flags);
1211
1212
264
    msg_Dbg( p_stream, "read box: \"tfhd\" version %d flags 0x%x track ID %d %s %s %s %s %s",
1213
264
                p_box->data.p_tfhd->i_version,
1214
264
                p_box->data.p_tfhd->i_flags,
1215
264
                p_box->data.p_tfhd->i_track_ID,
1216
264
                psz_base, psz_desc, psz_dura, psz_size, psz_flag );
1217
264
#endif
1218
1219
264
    MP4_READBOX_EXIT( 1 );
1220
264
}
1221
1222
static void MP4_FreeBox_trun( MP4_Box_t *p_box )
1223
264
{
1224
264
    free( p_box->data.p_trun->p_samples );
1225
264
}
1226
1227
static int MP4_ReadBox_trun(  stream_t *p_stream, MP4_Box_t *p_box )
1228
264
{
1229
264
    uint32_t count;
1230
1231
264
    MP4_READBOX_ENTER( MP4_Box_data_trun_t, MP4_FreeBox_trun );
1232
264
    MP4_Box_data_trun_t *p_trun = p_box->data.p_trun;
1233
264
    MP4_GETVERSIONFLAGS( p_trun );
1234
264
    MP4_GET4BYTES( count );
1235
1236
264
    if( p_trun->i_flags & MP4_TRUN_DATA_OFFSET )
1237
264
        MP4_GET4BYTES( p_trun->i_data_offset );
1238
264
    if( p_trun->i_flags & MP4_TRUN_FIRST_FLAGS )
1239
264
        MP4_GET4BYTES( p_trun->i_first_sample_flags );
1240
1241
264
    uint64_t i_entry_size =
1242
264
        !!(p_trun->i_flags & MP4_TRUN_SAMPLE_DURATION) +
1243
264
        !!(p_trun->i_flags & MP4_TRUN_SAMPLE_SIZE) +
1244
264
        !!(p_trun->i_flags & MP4_TRUN_SAMPLE_FLAGS) +
1245
264
        !!(p_trun->i_flags & MP4_TRUN_SAMPLE_TIME_OFFSET);
1246
1247
264
    if( i_entry_size * 4 * count > i_read )
1248
7
        MP4_READBOX_EXIT( 0 );
1249
1250
257
    p_trun->p_samples = vlc_alloc( count, sizeof(MP4_descriptor_trun_sample_t) );
1251
257
    if ( p_trun->p_samples == NULL )
1252
0
        MP4_READBOX_EXIT( 0 );
1253
257
    p_trun->i_sample_count = count;
1254
1255
4.26k
    for( unsigned int i = 0; i < count; i++ )
1256
4.00k
    {
1257
4.00k
        MP4_descriptor_trun_sample_t *p_sample = &p_trun->p_samples[i];
1258
4.00k
        if( p_trun->i_flags & MP4_TRUN_SAMPLE_DURATION )
1259
4.00k
            MP4_GET4BYTES( p_sample->i_duration );
1260
4.00k
        if( p_trun->i_flags & MP4_TRUN_SAMPLE_SIZE )
1261
4.00k
            MP4_GET4BYTES( p_sample->i_size );
1262
4.00k
        if( p_trun->i_flags & MP4_TRUN_SAMPLE_FLAGS )
1263
4.00k
            MP4_GET4BYTES( p_sample->i_flags );
1264
4.00k
        if( p_trun->i_flags & MP4_TRUN_SAMPLE_TIME_OFFSET )
1265
4.00k
            MP4_GET4BYTES( p_sample->i_composition_time_offset.v0 );
1266
4.00k
    }
1267
1268
#ifdef MP4_ULTRA_VERBOSE
1269
    msg_Dbg( p_stream, "read box: \"trun\" version %u flags 0x%x sample count %"PRIu32,
1270
                  p_trun->i_version,
1271
                  p_trun->i_flags,
1272
                  p_trun->i_sample_count );
1273
1274
    for( unsigned int i = 0; i < count; i++ )
1275
    {
1276
        MP4_descriptor_trun_sample_t *p_sample = &p_trun->p_samples[i];
1277
        msg_Dbg( p_stream, "read box: \"trun\" sample %4.4u flags 0x%x "\
1278
            "duration %"PRIu32" size %"PRIu32" composition time offset %"PRIu32,
1279
                        i, p_sample->i_flags, p_sample->i_duration,
1280
                        p_sample->i_size, p_sample->i_composition_time_offset );
1281
    }
1282
#endif
1283
1284
257
    MP4_READBOX_EXIT( 1 );
1285
257
}
1286
1287
static int MP4_ReadBox_tfdt( stream_t *p_stream, MP4_Box_t *p_box )
1288
55
{
1289
55
    MP4_READBOX_ENTER( MP4_Box_data_tfdt_t, NULL );
1290
55
    if( i_read < 8 )
1291
0
        MP4_READBOX_EXIT( 0 );
1292
1293
55
    MP4_GETVERSIONFLAGS( p_box->data.p_tfdt );
1294
1295
55
    if( p_box->data.p_tfdt->i_version == 0 )
1296
55
        MP4_GET4BYTES( p_box->data.p_tfdt->i_base_media_decode_time );
1297
4
    else if( p_box->data.p_tfdt->i_version == 1 )
1298
4
        MP4_GET8BYTES( p_box->data.p_tfdt->i_base_media_decode_time );
1299
4
    else
1300
4
        MP4_READBOX_EXIT( 0 );
1301
1302
51
    MP4_READBOX_EXIT( 1 );
1303
51
}
1304
1305
static int MP4_ReadBox_tkhd(  stream_t *p_stream, MP4_Box_t *p_box )
1306
1.36k
{
1307
1.36k
    MP4_READBOX_ENTER( MP4_Box_data_tkhd_t, NULL );
1308
1309
1.36k
    MP4_GETVERSIONFLAGS( p_box->data.p_tkhd );
1310
1311
1.36k
    if( p_box->data.p_tkhd->i_version )
1312
100
    {
1313
100
        MP4_GET8BYTES( p_box->data.p_tkhd->i_creation_time );
1314
100
        MP4_GET8BYTES( p_box->data.p_tkhd->i_modification_time );
1315
100
        MP4_GET4BYTES( p_box->data.p_tkhd->i_track_ID );
1316
100
        MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved );
1317
100
        MP4_GET8BYTES( p_box->data.p_tkhd->i_duration );
1318
100
    }
1319
1.26k
    else
1320
1.26k
    {
1321
1.26k
        MP4_GET4BYTES( p_box->data.p_tkhd->i_creation_time );
1322
1.26k
        MP4_GET4BYTES( p_box->data.p_tkhd->i_modification_time );
1323
1.26k
        MP4_GET4BYTES( p_box->data.p_tkhd->i_track_ID );
1324
1.26k
        MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved );
1325
1.26k
        MP4_GET4BYTES( p_box->data.p_tkhd->i_duration );
1326
1.26k
    }
1327
1328
4.10k
    for( unsigned i = 0; i < 2; i++ )
1329
2.73k
    {
1330
2.73k
        MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved2[i] );
1331
2.73k
    }
1332
1.36k
    MP4_GET2BYTES( p_box->data.p_tkhd->i_layer );
1333
1.36k
    MP4_GET2BYTES( p_box->data.p_tkhd->i_alternate_group );
1334
1.36k
    MP4_GET2BYTES( p_box->data.p_tkhd->i_volume );
1335
1.36k
    MP4_GET2BYTES( p_box->data.p_tkhd->i_reserved3 );
1336
1337
13.6k
    for( unsigned i = 0; i < 9; i++ )
1338
12.3k
    {
1339
12.3k
        MP4_GET4BYTES( p_box->data.p_tkhd->i_matrix[i] );
1340
12.3k
    }
1341
1.36k
    MP4_GET4BYTES( p_box->data.p_tkhd->i_width );
1342
1.36k
    MP4_GET4BYTES( p_box->data.p_tkhd->i_height );
1343
1344
1.36k
    double rotation = 0;//angle in degrees to be rotated clockwise
1345
1.36k
    double scale[2];    // scale factor; sx = scale[0] , sy = scale[1]
1346
1.36k
    int32_t *matrix = p_box->data.p_tkhd->i_matrix;
1347
1348
1.36k
    int64_t det = (int64_t)matrix[0] * matrix[4] - (int64_t)matrix[1] * matrix[3];
1349
1.36k
    if (det < 0) {
1350
        /* If determinant is negative copy the matrix and flip it horizontally. */
1351
552
        const int flip[] = { -1, 1, 1 };
1352
5.52k
        for (int j = 0; j < 9; j++)
1353
4.96k
            matrix[j] *= flip[j % 3];
1354
552
        p_box->data.p_tkhd->i_flip = 1;
1355
552
    }
1356
1357
1.36k
    scale[0] = sqrt(conv_fx(matrix[0]) * conv_fx(matrix[0]) +
1358
1.36k
                    conv_fx(matrix[3]) * conv_fx(matrix[3]));
1359
1.36k
    scale[1] = sqrt(conv_fx(matrix[1]) * conv_fx(matrix[1]) +
1360
1.36k
                    conv_fx(matrix[4]) * conv_fx(matrix[4]));
1361
1362
1.36k
    if( likely(scale[0] > 0 && scale[1] > 0) )
1363
1.30k
    {
1364
1.30k
        rotation = atan2(conv_fx(matrix[1]) / scale[1],
1365
1.30k
                         conv_fx(matrix[0]) / scale[0]) * 180 / M_PI;
1366
1.30k
        if (rotation < 0)
1367
16
            rotation += 360.;
1368
1.30k
    }
1369
1370
1.36k
    p_box->data.p_tkhd->f_rotation = rotation;
1371
1372
1.36k
#ifdef MP4_VERBOSE
1373
1.36k
    double translate[2];// amount to translate; tx = translate[0] , ty = translate[1]
1374
1375
1.36k
    translate[0] = conv_fx(matrix[6]);
1376
1.36k
    translate[1] = conv_fx(matrix[7]);
1377
1378
1.36k
    msg_Dbg( p_stream, "read box: \"tkhd\" track #%"PRIu32" duration %"PRIu64" layer %d "
1379
1.36k
                       "volume %3.1f rotation %3.1f scale %.2fx%.2f translate +%.2f+%.2f size %ux%u. "
1380
1.36k
                       "Matrix: %i %i %i %i %i %i %i %i %i",
1381
1.36k
                  p_box->data.p_tkhd->i_track_ID,
1382
1.36k
                  p_box->data.p_tkhd->i_duration,
1383
1.36k
                  p_box->data.p_tkhd->i_layer,
1384
1.36k
                  (float)p_box->data.p_tkhd->i_volume / 256 ,
1385
1.36k
                  rotation,
1386
1.36k
                  scale[0],
1387
1.36k
                  scale[1],
1388
1.36k
                  translate[0],
1389
1.36k
                  translate[1],
1390
1.36k
                  (unsigned)p_box->data.p_tkhd->i_width / BLOCK16x16,
1391
1.36k
                  (unsigned)p_box->data.p_tkhd->i_height / BLOCK16x16,
1392
1.36k
                  p_box->data.p_tkhd->i_matrix[0],
1393
1.36k
                  p_box->data.p_tkhd->i_matrix[1],
1394
1.36k
                  p_box->data.p_tkhd->i_matrix[2],
1395
1.36k
                  p_box->data.p_tkhd->i_matrix[3],
1396
1.36k
                  p_box->data.p_tkhd->i_matrix[4],
1397
1.36k
                  p_box->data.p_tkhd->i_matrix[5],
1398
1.36k
                  p_box->data.p_tkhd->i_matrix[6],
1399
1.36k
                  p_box->data.p_tkhd->i_matrix[7],
1400
1.36k
                  p_box->data.p_tkhd->i_matrix[8] );
1401
1.36k
#endif
1402
1.36k
    MP4_READBOX_EXIT( 1 );
1403
1.36k
}
1404
1405
static int MP4_ReadBox_load( stream_t *p_stream, MP4_Box_t *p_box )
1406
8
{
1407
8
    if ( p_box->i_size != 24 )
1408
0
        return 0;
1409
16
    MP4_READBOX_ENTER( MP4_Box_data_load_t, NULL );
1410
16
    MP4_GET4BYTES( p_box->data.p_load->i_start_time );
1411
16
    MP4_GET4BYTES( p_box->data.p_load->i_duration );
1412
16
    MP4_GET4BYTES( p_box->data.p_load->i_flags );
1413
16
    MP4_GET4BYTES( p_box->data.p_load->i_hints );
1414
16
    MP4_READBOX_EXIT( 1 );
1415
16
}
1416
1417
static int MP4_ReadBox_mdhd( stream_t *p_stream, MP4_Box_t *p_box )
1418
1.33k
{
1419
1.33k
    uint16_t i_language;
1420
1.33k
    MP4_READBOX_ENTER( MP4_Box_data_mdhd_t, NULL );
1421
1422
1.33k
    MP4_GETVERSIONFLAGS( p_box->data.p_mdhd );
1423
1424
1.33k
    if( p_box->data.p_mdhd->i_version )
1425
87
    {
1426
87
        MP4_GET8BYTES( p_box->data.p_mdhd->i_creation_time );
1427
87
        MP4_GET8BYTES( p_box->data.p_mdhd->i_modification_time );
1428
87
        MP4_GET4BYTES( p_box->data.p_mdhd->i_timescale );
1429
87
        MP4_GET8BYTES( p_box->data.p_mdhd->i_duration );
1430
87
    }
1431
1.24k
    else
1432
1.24k
    {
1433
1.24k
        MP4_GET4BYTES( p_box->data.p_mdhd->i_creation_time );
1434
1.24k
        MP4_GET4BYTES( p_box->data.p_mdhd->i_modification_time );
1435
1.24k
        MP4_GET4BYTES( p_box->data.p_mdhd->i_timescale );
1436
1.24k
        MP4_GET4BYTES( p_box->data.p_mdhd->i_duration );
1437
1.24k
    }
1438
1439
1.33k
    MP4_GET2BYTES( i_language );
1440
1.33k
    decodeQtLanguageCode( i_language, p_box->data.p_mdhd->rgs_language,
1441
1.33k
                          &p_box->data.p_mdhd->b_mac_encoding );
1442
1443
1.33k
    MP4_GET2BYTES( p_box->data.p_mdhd->i_quality );
1444
1445
1.33k
#ifdef MP4_VERBOSE
1446
1.33k
    char *psz_duration = MP4_Time2Str( p_box->data.p_mdhd->i_duration, p_box->data.p_mdhd->i_timescale );
1447
1.33k
    msg_Dbg( p_stream, "read box: \"mdhd\" timescale %"PRIu32" duration %"PRIu64" (%s) language %3.3s",
1448
1.33k
                  p_box->data.p_mdhd->i_timescale,
1449
1.33k
                  p_box->data.p_mdhd->i_duration,
1450
1.33k
                  psz_duration,
1451
1.33k
                  (char*) &p_box->data.p_mdhd->rgs_language );
1452
1.33k
    free( psz_duration );
1453
1.33k
#endif
1454
1.33k
    MP4_READBOX_EXIT( 1 );
1455
1.33k
}
1456
1457
static void MP4_FreeBox_hdlr( MP4_Box_t *p_box )
1458
2.31k
{
1459
2.31k
    free( p_box->data.p_hdlr->psz_name );
1460
2.31k
}
1461
1462
static int MP4_ReadBox_hdlr( stream_t *p_stream, MP4_Box_t *p_box )
1463
2.31k
{
1464
2.31k
    MP4_READBOX_ENTER( MP4_Box_data_hdlr_t, MP4_FreeBox_hdlr );
1465
1466
2.31k
    MP4_GETVERSIONFLAGS( p_box->data.p_hdlr );
1467
1468
2.31k
    MP4_GETFOURCC( p_box->data.p_hdlr->i_predefined );
1469
2.31k
    MP4_GETFOURCC( p_box->data.p_hdlr->i_handler_type );
1470
1471
2.31k
    MP4_SKIPBYTES( 3*4 ); // reserved[3]
1472
2.31k
    p_box->data.p_hdlr->psz_name = NULL;
1473
1474
2.31k
    if( i_read >= SSIZE_MAX )
1475
0
        MP4_READBOX_EXIT( 0 );
1476
1477
2.31k
    if( i_read > 0 )
1478
2.19k
    {
1479
2.19k
        size_t i_copy;
1480
1481
        /* Yes, I love .mp4 :( */
1482
2.19k
        if( p_box->data.p_hdlr->i_predefined == VLC_FOURCC( 'm', 'h', 'l', 'r' ) )
1483
936
        {
1484
936
            uint8_t i_len;
1485
1486
936
            MP4_GET1BYTE( i_len );
1487
936
            i_copy = (i_len <= i_read) ? i_len : i_read;
1488
936
        }
1489
1.25k
        else
1490
1.25k
            i_copy = i_read;
1491
1492
2.19k
        uint8_t *psz = p_box->data.p_hdlr->psz_name = malloc( i_copy + 1 );
1493
2.19k
        if( unlikely( psz == NULL ) )
1494
0
            MP4_READBOX_EXIT( 0 );
1495
1496
2.19k
        memcpy( psz, p_peek, i_copy );
1497
2.19k
        p_box->data.p_hdlr->psz_name[i_copy] = '\0';
1498
2.19k
    }
1499
1500
2.31k
#ifdef MP4_VERBOSE
1501
2.31k
        msg_Dbg( p_stream, "read box: \"hdlr\" handler type: \"%4.4s\" name: \"%s\"",
1502
2.31k
                   (char*)&p_box->data.p_hdlr->i_handler_type,
1503
2.31k
                   p_box->data.p_hdlr->psz_name );
1504
1505
2.31k
#endif
1506
2.31k
    MP4_READBOX_EXIT( 1 );
1507
2.31k
}
1508
1509
static int MP4_ReadBox_vmhd( stream_t *p_stream, MP4_Box_t *p_box )
1510
801
{
1511
801
    MP4_READBOX_ENTER( MP4_Box_data_vmhd_t, NULL );
1512
1513
801
    MP4_GETVERSIONFLAGS( p_box->data.p_vmhd );
1514
1515
801
    MP4_GET2BYTES( p_box->data.p_vmhd->i_graphics_mode );
1516
3.20k
    for( unsigned i = 0; i < 3; i++ )
1517
2.40k
    {
1518
2.40k
        MP4_GET2BYTES( p_box->data.p_vmhd->i_opcolor[i] );
1519
2.40k
    }
1520
1521
801
#ifdef MP4_VERBOSE
1522
801
    msg_Dbg( p_stream, "read box: \"vmhd\" graphics-mode %" PRIu16 " opcolor (%" PRIu16 ", %" PRIu16 ", %" PRIu16 ")",
1523
801
                      p_box->data.p_vmhd->i_graphics_mode,
1524
801
                      p_box->data.p_vmhd->i_opcolor[0],
1525
801
                      p_box->data.p_vmhd->i_opcolor[1],
1526
801
                      p_box->data.p_vmhd->i_opcolor[2] );
1527
801
#endif
1528
801
    MP4_READBOX_EXIT( 1 );
1529
801
}
1530
1531
static int MP4_ReadBox_smhd( stream_t *p_stream, MP4_Box_t *p_box )
1532
245
{
1533
245
    MP4_READBOX_ENTER( MP4_Box_data_smhd_t, NULL );
1534
1535
245
    MP4_GETVERSIONFLAGS( p_box->data.p_smhd );
1536
1537
1538
1539
245
    MP4_GET2BYTES( p_box->data.p_smhd->i_balance );
1540
1541
245
    MP4_GET2BYTES( p_box->data.p_smhd->i_reserved );
1542
1543
245
#ifdef MP4_VERBOSE
1544
245
    msg_Dbg( p_stream, "read box: \"smhd\" balance %f",
1545
245
                      (float)p_box->data.p_smhd->i_balance / 256 );
1546
245
#endif
1547
245
    MP4_READBOX_EXIT( 1 );
1548
245
}
1549
1550
1551
static int MP4_ReadBox_hmhd( stream_t *p_stream, MP4_Box_t *p_box )
1552
95
{
1553
95
    MP4_READBOX_ENTER( MP4_Box_data_hmhd_t, NULL );
1554
1555
95
    MP4_GETVERSIONFLAGS( p_box->data.p_hmhd );
1556
1557
95
    MP4_GET2BYTES( p_box->data.p_hmhd->i_max_PDU_size );
1558
95
    MP4_GET2BYTES( p_box->data.p_hmhd->i_avg_PDU_size );
1559
1560
95
    MP4_GET4BYTES( p_box->data.p_hmhd->i_max_bitrate );
1561
95
    MP4_GET4BYTES( p_box->data.p_hmhd->i_avg_bitrate );
1562
1563
95
    MP4_GET4BYTES( p_box->data.p_hmhd->i_reserved );
1564
1565
95
#ifdef MP4_VERBOSE
1566
95
    msg_Dbg( p_stream, "read box: \"hmhd\" maxPDU-size %d avgPDU-size %d max-bitrate %d avg-bitrate %d",
1567
95
                      p_box->data.p_hmhd->i_max_PDU_size,
1568
95
                      p_box->data.p_hmhd->i_avg_PDU_size,
1569
95
                      p_box->data.p_hmhd->i_max_bitrate,
1570
95
                      p_box->data.p_hmhd->i_avg_bitrate );
1571
95
#endif
1572
95
    MP4_READBOX_EXIT( 1 );
1573
95
}
1574
1575
static void MP4_FreeBox_url( MP4_Box_t *p_box )
1576
323
{
1577
323
    free( p_box->data.p_url->psz_location );
1578
323
}
1579
1580
static int MP4_ReadBox_url( stream_t *p_stream, MP4_Box_t *p_box )
1581
323
{
1582
323
    MP4_READBOX_ENTER( MP4_Box_data_url_t, MP4_FreeBox_url );
1583
1584
323
    MP4_GETVERSIONFLAGS( p_box->data.p_url );
1585
323
    MP4_GETSTRINGZ( p_box->data.p_url->psz_location );
1586
1587
323
#ifdef MP4_VERBOSE
1588
323
    msg_Dbg( p_stream, "read box: \"url\" url: %s",
1589
323
                       p_box->data.p_url->psz_location );
1590
1591
323
#endif
1592
323
    MP4_READBOX_EXIT( 1 );
1593
323
}
1594
1595
static void MP4_FreeBox_urn( MP4_Box_t *p_box )
1596
0
{
1597
0
    free( p_box->data.p_urn->psz_name );
1598
0
    free( p_box->data.p_urn->psz_location );
1599
0
}
1600
1601
static int MP4_ReadBox_urn( stream_t *p_stream, MP4_Box_t *p_box )
1602
0
{
1603
0
    MP4_READBOX_ENTER( MP4_Box_data_urn_t, MP4_FreeBox_urn );
1604
1605
0
    MP4_GETVERSIONFLAGS( p_box->data.p_urn );
1606
1607
0
    MP4_GETSTRINGZ( p_box->data.p_urn->psz_name );
1608
0
    MP4_GETSTRINGZ( p_box->data.p_urn->psz_location );
1609
1610
0
#ifdef MP4_VERBOSE
1611
0
    msg_Dbg( p_stream, "read box: \"urn\" name %s location %s",
1612
0
                      p_box->data.p_urn->psz_name,
1613
0
                      p_box->data.p_urn->psz_location );
1614
0
#endif
1615
0
    MP4_READBOX_EXIT( 1 );
1616
0
}
1617
1618
static int MP4_ReadBox_LtdContainer( stream_t *p_stream, MP4_Box_t *p_box )
1619
1.14k
{
1620
1.14k
    MP4_READBOX_ENTER_PARTIAL( MP4_Box_data_lcont_t, 16, NULL );
1621
1.14k
    if( i_read < 8 )
1622
0
        MP4_READBOX_EXIT( 0 );
1623
1624
1.14k
    MP4_GETVERSIONFLAGS( p_box->data.p_lcont );
1625
1.14k
    if( p_box->data.p_lcont->i_version != 0 )
1626
38
        MP4_READBOX_EXIT( 0 );
1627
1.10k
    MP4_GET4BYTES( p_box->data.p_lcont->i_entry_count );
1628
1629
1.10k
    uint32_t i_entry = 0;
1630
1.10k
    i_read = p_box->i_size - 16;
1631
1.72k
    while (i_read > 8 && i_entry < p_box->data.p_lcont->i_entry_count )
1632
1.08k
    {
1633
1.08k
        MP4_Box_t *p_childbox = MP4_ReadBox( p_stream, p_box );
1634
1.08k
        if( !p_childbox )
1635
464
            break;
1636
617
        MP4_BoxAddChild( p_box, p_childbox );
1637
617
        i_entry++;
1638
1639
617
        if( i_read < p_childbox->i_size )
1640
0
            MP4_READBOX_EXIT( 0 );
1641
1642
617
        i_read -= p_childbox->i_size;
1643
617
    }
1644
1645
1.10k
    if (i_entry != p_box->data.p_lcont->i_entry_count)
1646
481
        p_box->data.p_lcont->i_entry_count = i_entry;
1647
1648
1.10k
#ifdef MP4_VERBOSE
1649
1.10k
    msg_Dbg( p_stream, "read box: \"%4.4s\" entry-count %d", (char *)&p_box->i_type,
1650
1.10k
                        p_box->data.p_lcont->i_entry_count );
1651
1652
1.10k
#endif
1653
1654
1.10k
    if ( MP4_Seek( p_stream, p_box->i_pos + p_box->i_size ) )
1655
0
        MP4_READBOX_EXIT( 0 );
1656
1657
1.10k
    MP4_READBOX_EXIT( 1 );
1658
1.10k
}
1659
1660
static void MP4_FreeBox_stts( MP4_Box_t *p_box )
1661
1.20k
{
1662
1.20k
    free( p_box->data.p_stts->pi_sample_count );
1663
1.20k
    free( p_box->data.p_stts->pi_sample_delta );
1664
1.20k
}
1665
1666
static int MP4_ReadBox_stts( stream_t *p_stream, MP4_Box_t *p_box )
1667
1.20k
{
1668
1.20k
    uint32_t count;
1669
1670
1.20k
    MP4_READBOX_ENTER( MP4_Box_data_stts_t, MP4_FreeBox_stts );
1671
1672
1.20k
    MP4_GETVERSIONFLAGS( p_box->data.p_stts );
1673
1.20k
    MP4_GET4BYTES( count );
1674
1675
1.20k
    if( UINT64_C(8) * count > i_read )
1676
0
    {
1677
        /*count = i_read / 8;*/
1678
0
        MP4_READBOX_EXIT( 0 );
1679
0
    }
1680
1681
1.20k
    p_box->data.p_stts->pi_sample_count = vlc_alloc( count, sizeof(uint32_t) );
1682
1.20k
    p_box->data.p_stts->pi_sample_delta = vlc_alloc( count, sizeof(uint32_t) );
1683
1.20k
    p_box->data.p_stts->i_entry_count = count;
1684
1685
1.20k
    if( p_box->data.p_stts->pi_sample_count == NULL
1686
1.20k
     || p_box->data.p_stts->pi_sample_delta == NULL )
1687
0
    {
1688
0
        MP4_FreeBox_stts( p_box );
1689
0
        MP4_READBOX_EXIT( 0 );
1690
0
    }
1691
1692
7.81k
    for( uint32_t i = 0; i < count; i++ )
1693
6.60k
    {
1694
6.60k
        MP4_GET4BYTES( p_box->data.p_stts->pi_sample_count[i] );
1695
6.60k
        MP4_GET4BYTES( p_box->data.p_stts->pi_sample_delta[i] );
1696
        /* Patch bogus durations, including negative stored values */
1697
6.60k
        if( p_box->data.p_stts->pi_sample_delta[i] == 0 ||
1698
6.51k
            p_box->data.p_stts->pi_sample_delta[i] >= 0xF0000000 )
1699
132
            p_box->data.p_stts->pi_sample_delta[i] = 1;
1700
6.60k
    }
1701
1702
1.20k
#ifdef MP4_VERBOSE
1703
1.20k
    msg_Dbg( p_stream, "read box: \"stts\" entry-count %d",
1704
1.20k
                      p_box->data.p_stts->i_entry_count );
1705
1706
1.20k
#endif
1707
1.20k
    MP4_READBOX_EXIT( 1 );
1708
1.20k
}
1709
1710
1711
static void MP4_FreeBox_ctts( MP4_Box_t *p_box )
1712
547
{
1713
547
    free( p_box->data.p_ctts->pi_sample_count );
1714
547
    free( p_box->data.p_ctts->pi_sample_offset );
1715
547
}
1716
1717
static int MP4_ReadBox_ctts( stream_t *p_stream, MP4_Box_t *p_box )
1718
547
{
1719
547
    uint32_t count;
1720
1721
547
    MP4_READBOX_ENTER( MP4_Box_data_ctts_t, MP4_FreeBox_ctts );
1722
1723
547
    MP4_GETVERSIONFLAGS( p_box->data.p_ctts );
1724
547
    MP4_GET4BYTES( count );
1725
1726
547
    if( UINT64_C(8) * count > i_read )
1727
0
        MP4_READBOX_EXIT( 0 );
1728
1729
547
    p_box->data.p_ctts->pi_sample_count = vlc_alloc( count, sizeof(uint32_t) );
1730
547
    p_box->data.p_ctts->pi_sample_offset = vlc_alloc( count, sizeof(int32_t) );
1731
547
    if( unlikely(p_box->data.p_ctts->pi_sample_count == NULL
1732
547
              || p_box->data.p_ctts->pi_sample_offset == NULL) )
1733
0
    {
1734
0
        MP4_FreeBox_ctts( p_box );
1735
0
        MP4_READBOX_EXIT( 0 );
1736
0
    }
1737
547
    p_box->data.p_ctts->i_entry_count = count;
1738
1739
348k
    for( uint32_t i = 0; i < count; i++ )
1740
348k
    {
1741
348k
        MP4_GET4BYTES( p_box->data.p_ctts->pi_sample_count[i] );
1742
348k
        MP4_GET4BYTES( p_box->data.p_ctts->pi_sample_offset[i] );
1743
348k
    }
1744
1745
547
#ifdef MP4_VERBOSE
1746
547
    msg_Dbg( p_stream, "read box: \"ctts\" entry-count %"PRIu32, count );
1747
1748
547
#endif
1749
547
    MP4_READBOX_EXIT( 1 );
1750
547
}
1751
1752
static int MP4_ReadBox_cslg( stream_t *p_stream, MP4_Box_t *p_box )
1753
457
{
1754
457
    MP4_READBOX_ENTER( MP4_Box_data_cslg_t, NULL );
1755
1756
457
    uint8_t i_version;
1757
457
    MP4_GET1BYTE( i_version );
1758
457
    MP4_SKIPBYTES( 3 ); // flags
1759
1760
457
    if( i_version > 1 )
1761
2
        MP4_READBOX_EXIT( 0 );
1762
1763
455
    union { int32_t s; uint32_t u; } u32;
1764
455
    union { int64_t s; uint64_t u; } u64;
1765
455
#define DOREAD_CSLG( readbytes, temp, member ) \
1766
2.27k
        { readbytes( temp.u ); member = temp.s; }
1767
1768
455
#define READ_CSLG( readbytes, temp ) {\
1769
455
    DOREAD_CSLG( readbytes, temp, p_box->data.p_cslg->ct_to_dts_shift );\
1770
455
    DOREAD_CSLG( readbytes, temp, p_box->data.p_cslg->i_least_delta );\
1771
455
    DOREAD_CSLG( readbytes, temp, p_box->data.p_cslg->i_max_delta );\
1772
455
    DOREAD_CSLG( readbytes, temp, p_box->data.p_cslg->i_composition_starttime );\
1773
455
    DOREAD_CSLG( readbytes, temp, p_box->data.p_cslg->i_composition_endtime ); }
1774
1775
455
    if( i_version == 0 )
1776
70
        READ_CSLG( MP4_GET4BYTES, u32 )
1777
441
    else
1778
2.20k
        READ_CSLG( MP4_GET8BYTES, u64 )
1779
1780
455
    MP4_READBOX_EXIT( 1 );
1781
455
}
1782
1783
static uint64_t MP4_ReadLengthDescriptor( uint8_t **restrict bufp,
1784
                                          uint64_t *restrict lenp )
1785
211
{
1786
211
    unsigned char *buf = *bufp;
1787
211
    uint64_t len = *lenp;
1788
211
    unsigned char b;
1789
211
    uint64_t value = 0;
1790
1791
211
    do
1792
812
    {
1793
812
        if (unlikely(len == 0))
1794
0
            return UINT64_C(-1); /* end of bit stream */
1795
812
        if (unlikely(value > (UINT64_MAX >> 7)))
1796
0
            return UINT64_C(-1); /* integer overflow */
1797
1798
812
        b = *(buf++);
1799
812
        len--;
1800
812
        value = (value << 7) + (b & 0x7f);
1801
812
    }
1802
812
    while (b & 0x80);
1803
1804
211
    *bufp = buf;
1805
211
    *lenp = len;
1806
211
    return value;
1807
211
}
1808
1809
1810
static void MP4_FreeBox_esds( MP4_Box_t *p_box )
1811
85
{
1812
85
    free( p_box->data.p_esds->es_descriptor.psz_URL );
1813
85
    if( p_box->data.p_esds->es_descriptor.p_decConfigDescr )
1814
85
    {
1815
85
        free( p_box->data.p_esds->es_descriptor.p_decConfigDescr->p_decoder_specific_info );
1816
85
        free( p_box->data.p_esds->es_descriptor.p_decConfigDescr );
1817
85
    }
1818
85
}
1819
1820
static int MP4_ReadBox_esds( stream_t *p_stream, MP4_Box_t *p_box )
1821
85
{
1822
1.14k
#define es_descriptor p_box->data.p_esds->es_descriptor
1823
85
    uint64_t i_len;
1824
85
    unsigned int i_flags;
1825
85
    unsigned int i_type;
1826
1827
85
    MP4_READBOX_ENTER( MP4_Box_data_esds_t, MP4_FreeBox_esds );
1828
1829
85
    MP4_GETVERSIONFLAGS( p_box->data.p_esds );
1830
1831
1832
85
    MP4_GET1BYTE( i_type );
1833
85
    if( i_type == 0x03 ) /* MP4ESDescrTag ISO/IEC 14496-1 */
1834
85
    {
1835
85
        i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
1836
85
        if( unlikely(i_len == UINT64_C(-1)) )
1837
0
            MP4_READBOX_EXIT( 0 );
1838
1839
85
#ifdef MP4_VERBOSE
1840
85
        msg_Dbg( p_stream, "found esds MPEG4ESDescr (%"PRIu64" bytes)",
1841
85
                 i_len );
1842
85
#endif
1843
1844
85
        MP4_GET2BYTES( es_descriptor.i_ES_ID );
1845
85
        MP4_GET1BYTE( i_flags );
1846
85
        es_descriptor.b_stream_dependence = ( (i_flags&0x80) != 0);
1847
85
        es_descriptor.b_url = ( (i_flags&0x40) != 0);
1848
85
        es_descriptor.b_OCRstream = ( (i_flags&0x20) != 0);
1849
1850
85
        es_descriptor.i_stream_priority = i_flags&0x1f;
1851
85
        if( es_descriptor.b_stream_dependence )
1852
0
        {
1853
0
            MP4_GET2BYTES( es_descriptor.i_depend_on_ES_ID );
1854
0
        }
1855
85
        if( es_descriptor.b_url && i_read > 0 )
1856
0
        {
1857
0
            uint8_t i_url;
1858
1859
0
            MP4_GET1BYTE( i_url );
1860
0
            if( i_url > i_read )
1861
0
                MP4_READBOX_EXIT( 1 );
1862
0
            es_descriptor.psz_URL = malloc( (unsigned) i_url + 1 );
1863
0
            if( es_descriptor.psz_URL )
1864
0
            {
1865
0
                memcpy( es_descriptor.psz_URL, p_peek, i_url );
1866
0
                es_descriptor.psz_URL[i_url] = 0;
1867
0
            }
1868
0
            p_peek += i_url;
1869
0
            i_read -= i_url;
1870
0
        }
1871
85
        else
1872
85
        {
1873
85
            es_descriptor.psz_URL = NULL;
1874
85
        }
1875
85
        if( es_descriptor.b_OCRstream )
1876
0
        {
1877
0
            MP4_GET2BYTES( es_descriptor.i_OCR_ES_ID );
1878
0
        }
1879
85
        MP4_GET1BYTE( i_type ); /* get next type */
1880
85
    }
1881
1882
85
    if( i_type != 0x04)/* MP4DecConfigDescrTag ISO/IEC 14496-1 8.3.4 */
1883
0
    {
1884
0
         es_descriptor.p_decConfigDescr = NULL;
1885
0
         MP4_READBOX_EXIT( 1 ); /* rest isn't interesting up to now */
1886
0
    }
1887
1888
85
    i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
1889
85
    if( unlikely(i_len == UINT64_C(-1)) )
1890
0
        MP4_READBOX_EXIT( 0 );
1891
85
#ifdef MP4_VERBOSE
1892
85
    msg_Dbg( p_stream, "found esds MP4DecConfigDescr (%"PRIu64" bytes)",
1893
85
             i_len );
1894
85
#endif
1895
1896
85
    es_descriptor.p_decConfigDescr =
1897
85
            calloc( 1, sizeof( MP4_descriptor_decoder_config_t ));
1898
85
    if( unlikely( es_descriptor.p_decConfigDescr == NULL ) )
1899
0
        MP4_READBOX_EXIT( 0 );
1900
1901
85
    MP4_GET1BYTE( es_descriptor.p_decConfigDescr->i_objectProfileIndication );
1902
85
    MP4_GET1BYTE( i_flags );
1903
85
    es_descriptor.p_decConfigDescr->i_streamType = i_flags >> 2;
1904
85
    es_descriptor.p_decConfigDescr->b_upStream = ( i_flags >> 1 )&0x01;
1905
85
    MP4_GET3BYTES( es_descriptor.p_decConfigDescr->i_buffer_sizeDB );
1906
85
    MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_max_bitrate );
1907
85
    MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_avg_bitrate );
1908
85
    MP4_GET1BYTE( i_type );
1909
85
    if( i_type !=  0x05 )/* MP4DecSpecificDescrTag ISO/IEC 14496-1 8.3.5 */
1910
44
    {
1911
44
        es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = 0;
1912
44
        es_descriptor.p_decConfigDescr->p_decoder_specific_info  = NULL;
1913
44
        MP4_READBOX_EXIT( 1 );
1914
44
    }
1915
1916
41
    i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
1917
41
    if( unlikely(i_len == UINT64_C(-1)) )
1918
0
        MP4_READBOX_EXIT( 0 );
1919
41
#ifdef MP4_VERBOSE
1920
41
    msg_Dbg( p_stream, "found esds MP4DecSpecificDescr (%"PRIu64" bytes)",
1921
41
             i_len );
1922
41
#endif
1923
41
    if( i_len > i_read )
1924
0
        MP4_READBOX_EXIT( 0 );
1925
1926
41
    es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = i_len;
1927
41
    es_descriptor.p_decConfigDescr->p_decoder_specific_info = malloc( i_len );
1928
41
    if( unlikely( es_descriptor.p_decConfigDescr->p_decoder_specific_info == NULL ) )
1929
0
        MP4_READBOX_EXIT( 0 );
1930
1931
41
    memcpy( es_descriptor.p_decConfigDescr->p_decoder_specific_info,
1932
41
            p_peek, i_len );
1933
1934
41
    MP4_READBOX_EXIT( 1 );
1935
41
#undef es_descriptor
1936
41
}
1937
1938
static void MP4_FreeBox_av1C( MP4_Box_t *p_box )
1939
25
{
1940
25
    MP4_Box_data_av1C_t *p_av1C = p_box->data.p_av1C;
1941
25
    free( p_av1C->p_av1C );
1942
25
}
1943
1944
static int MP4_ReadBox_av1C( stream_t *p_stream, MP4_Box_t *p_box )
1945
25
{
1946
25
    MP4_Box_data_av1C_t *p_av1C;
1947
1948
25
    MP4_READBOX_ENTER( MP4_Box_data_av1C_t, MP4_FreeBox_av1C );
1949
25
    p_av1C = p_box->data.p_av1C;
1950
1951
25
    if( i_read < 4 ||
1952
25
       p_peek[0] != 0x81 ) /* marker / version */
1953
0
        MP4_READBOX_EXIT( 0 );
1954
1955
25
    p_av1C->p_av1C = malloc( i_read );
1956
25
    if( p_av1C->p_av1C )
1957
25
    {
1958
25
        memcpy( p_av1C->p_av1C, p_peek, i_read );
1959
25
        p_av1C->i_av1C = i_read;
1960
25
    }
1961
1962
25
    uint8_t i_8b;
1963
25
    MP4_GET1BYTE( i_8b ); /* marker / version */
1964
1965
25
    MP4_GET1BYTE( i_8b );
1966
25
    p_av1C->i_profile = i_8b >> 5;
1967
25
    p_av1C->i_level = i_8b & 0x1F;
1968
1969
25
    MP4_GET1BYTE( i_8b );
1970
25
    MP4_GET1BYTE( i_8b );
1971
1972
25
    if( i_8b & 0x10 ) /* delay flag */
1973
0
        p_av1C->i_presentation_delay = 1 + (i_8b & 0x0F);
1974
25
    else
1975
25
        p_av1C->i_presentation_delay = 0;
1976
1977
25
    MP4_READBOX_EXIT( 1 );
1978
25
}
1979
1980
static void MP4_FreeBox_avcC( MP4_Box_t *p_box )
1981
76
{
1982
76
    MP4_Box_data_avcC_t *p_avcC = p_box->data.p_avcC;
1983
76
    free( p_avcC->p_avcC );
1984
76
}
1985
1986
static int MP4_ReadBox_avcC( stream_t *p_stream, MP4_Box_t *p_box )
1987
76
{
1988
76
    MP4_Box_data_avcC_t *p_avcC;
1989
1990
76
    MP4_READBOX_ENTER( MP4_Box_data_avcC_t, MP4_FreeBox_avcC );
1991
76
    p_avcC = p_box->data.p_avcC;
1992
1993
76
    if( i_read > 0 )
1994
76
    {
1995
76
        p_avcC->p_avcC = malloc( i_read );
1996
76
        if( p_avcC->p_avcC )
1997
76
        {
1998
76
            memcpy( p_avcC->p_avcC, p_peek, i_read );
1999
76
            p_avcC->i_avcC = i_read;
2000
76
        }
2001
76
    }
2002
2003
76
    MP4_GET1BYTE( p_avcC->i_version );
2004
76
    MP4_GET1BYTE( p_avcC->i_profile );
2005
76
    MP4_GET1BYTE( p_avcC->i_profile_compatibility );
2006
76
    MP4_GET1BYTE( p_avcC->i_level );
2007
76
#ifdef MP4_VERBOSE
2008
76
    msg_Dbg( p_stream,
2009
76
             "read box: \"avcC\" version=%d profile=0x%x level=0x%x",
2010
76
             p_avcC->i_version, p_avcC->i_profile, p_avcC->i_level );
2011
76
#endif
2012
76
    MP4_READBOX_EXIT( 1 );
2013
76
}
2014
2015
static void MP4_FreeBox_vpcC( MP4_Box_t *p_box )
2016
0
{
2017
0
    free( p_box->data.p_vpcC->p_codec_init_data );
2018
0
}
2019
2020
static int MP4_ReadBox_vpcC( stream_t *p_stream, MP4_Box_t *p_box )
2021
0
{
2022
0
    MP4_READBOX_ENTER( MP4_Box_data_vpcC_t, MP4_FreeBox_vpcC );
2023
0
    MP4_Box_data_vpcC_t *p_vpcC = p_box->data.p_vpcC;
2024
2025
0
    if( p_box->i_size < 9 )
2026
0
        MP4_READBOX_EXIT( 0 );
2027
2028
0
    MP4_GET1BYTE( p_vpcC->i_version );
2029
0
    if( p_vpcC->i_version > 1 )
2030
0
        MP4_READBOX_EXIT( 0 );
2031
2032
    /* Skip flags */
2033
0
    MP4_SKIPBYTES( 3 ); // flags
2034
2035
0
    MP4_GET1BYTE( p_vpcC->i_profile );
2036
0
    MP4_GET1BYTE( p_vpcC->i_level );
2037
0
    MP4_GET1BYTE( p_vpcC->i_bit_depth );
2038
2039
    /* Deprecated one
2040
       https://github.com/webmproject/vp9-dash/blob/master/archive/VPCodecISOMediaFileFormatBinding-v0.docx */
2041
0
    if( p_vpcC->i_version == 0 )
2042
0
    {
2043
0
        p_vpcC->i_color_primaries = p_vpcC->i_bit_depth & 0x0F;
2044
0
        p_vpcC->i_bit_depth >>= 4;
2045
0
        MP4_GET1BYTE( p_vpcC->i_chroma_subsampling );
2046
0
        p_vpcC->i_xfer_function = ( p_vpcC->i_chroma_subsampling & 0x0F ) >> 1;
2047
0
        p_vpcC->i_fullrange = p_vpcC->i_chroma_subsampling & 0x01;
2048
0
        p_vpcC->i_chroma_subsampling >>= 4;
2049
0
    }
2050
0
    else
2051
0
    {
2052
0
        p_vpcC->i_chroma_subsampling = ( p_vpcC->i_bit_depth & 0x0F ) >> 1;
2053
0
        p_vpcC->i_fullrange = p_vpcC->i_bit_depth & 0x01;
2054
0
        p_vpcC->i_bit_depth >>= 4;
2055
0
        MP4_GET1BYTE( p_vpcC->i_color_primaries );
2056
0
        MP4_GET1BYTE( p_vpcC->i_xfer_function );
2057
0
        MP4_GET1BYTE( p_vpcC->i_matrix_coeffs );
2058
0
    }
2059
2060
0
    MP4_GET2BYTES( p_vpcC->i_codec_init_datasize );
2061
0
    if( p_vpcC->i_codec_init_datasize > i_read )
2062
0
        p_vpcC->i_codec_init_datasize = i_read;
2063
2064
0
    if( p_vpcC->i_codec_init_datasize )
2065
0
    {
2066
0
        p_vpcC->p_codec_init_data = malloc( i_read );
2067
0
        if( !p_vpcC->p_codec_init_data )
2068
0
            MP4_READBOX_EXIT( 0 );
2069
0
        memcpy( p_vpcC->p_codec_init_data, p_peek, i_read );
2070
0
    }
2071
2072
0
    MP4_READBOX_EXIT( 1 );
2073
0
}
2074
2075
static int MP4_ReadBox_SmDm( stream_t *p_stream, MP4_Box_t *p_box )
2076
0
{
2077
0
    MP4_READBOX_ENTER( MP4_Box_data_SmDm_t, NULL );
2078
0
    MP4_Box_data_SmDm_t *p_SmDm = p_box->data.p_SmDm;
2079
2080
    /* SmDm: version/flags RGB */
2081
    /* mdcv: version/flags GBR or not */
2082
0
    if( p_box->i_type != ATOM_mdcv )
2083
0
    {
2084
0
        uint8_t i_version;
2085
0
        MP4_GET1BYTE( i_version );
2086
0
        MP4_SKIPBYTES( 3 ); // flags
2087
0
        if( i_version != 0 )
2088
0
            MP4_READBOX_EXIT( 0 );
2089
0
    }
2090
2091
0
    const uint8_t RGB2GBR[3] = {2,0,1};
2092
0
    for(int i=0; i<6; i++)
2093
0
    {
2094
0
        int index = (p_box->i_type != ATOM_mdcv) ? RGB2GBR[i/2] + i%2 : i;
2095
0
        MP4_GET2BYTES( p_SmDm->primaries[index] );
2096
2097
        /* convert from fixed point to 0.00002 resolution */
2098
0
        if(p_box->i_type != ATOM_mdcv)
2099
0
            p_SmDm->primaries[index] = 50000 *
2100
0
                    (double)p_SmDm->primaries[index] / (double)(1<<16);
2101
0
    }
2102
0
    for(int i=0; i<2; i++)
2103
0
    {
2104
0
        MP4_GET2BYTES( p_SmDm->white_point[i] );
2105
0
        if(p_box->i_type != ATOM_mdcv)
2106
0
            p_SmDm->white_point[i] = 50000 *
2107
0
                    (double)p_SmDm->white_point[i] / (double)(1<<16);
2108
0
    }
2109
2110
0
    MP4_GET4BYTES( p_SmDm->i_luminanceMax );
2111
0
    MP4_GET4BYTES( p_SmDm->i_luminanceMin );
2112
0
    if(p_box->i_type != ATOM_mdcv)
2113
0
    {
2114
0
        p_SmDm->i_luminanceMax = 10000 *
2115
0
                (double)p_SmDm->i_luminanceMax / (double) (1<<8);
2116
0
        p_SmDm->i_luminanceMin = 10000 *
2117
0
                (double)p_SmDm->i_luminanceMin / (double) (1<<14);
2118
0
    }
2119
2120
0
    MP4_READBOX_EXIT( 1 );
2121
0
}
2122
2123
static int MP4_ReadBox_CoLL( stream_t *p_stream, MP4_Box_t *p_box )
2124
0
{
2125
0
    MP4_READBOX_ENTER( MP4_Box_data_CoLL_t, NULL );
2126
0
    MP4_Box_data_CoLL_t *p_CoLL = p_box->data.p_CoLL;
2127
2128
0
    if( p_box->i_type != ATOM_clli )
2129
0
    {
2130
0
        uint8_t i_version;
2131
0
        MP4_GET1BYTE( i_version );
2132
0
        MP4_SKIPBYTES( 3 ); // flags
2133
0
        if( i_version != 0 )
2134
0
            MP4_READBOX_EXIT( 0 );
2135
0
    }
2136
2137
0
    MP4_GET2BYTES( p_CoLL->i_maxCLL );
2138
0
    MP4_GET2BYTES( p_CoLL->i_maxFALL );
2139
0
    MP4_READBOX_EXIT( 1 );
2140
0
}
2141
2142
static void MP4_FreeBox_WMA2( MP4_Box_t *p_box )
2143
26
{
2144
26
    free( p_box->data.p_WMA2->p_extra );
2145
26
}
2146
2147
static int MP4_ReadBox_WMA2( stream_t *p_stream, MP4_Box_t *p_box )
2148
26
{
2149
26
    MP4_READBOX_ENTER( MP4_Box_data_WMA2_t, MP4_FreeBox_WMA2 );
2150
2151
26
    MP4_Box_data_WMA2_t *p_WMA2 = p_box->data.p_WMA2;
2152
2153
26
    MP4_GET2BYTESLE( p_WMA2->Format.wFormatTag );
2154
26
    MP4_GET2BYTESLE( p_WMA2->Format.nChannels );
2155
26
    MP4_GET4BYTESLE( p_WMA2->Format.nSamplesPerSec );
2156
26
    MP4_GET4BYTESLE( p_WMA2->Format.nAvgBytesPerSec );
2157
26
    MP4_GET2BYTESLE( p_WMA2->Format.nBlockAlign );
2158
26
    MP4_GET2BYTESLE( p_WMA2->Format.wBitsPerSample );
2159
2160
26
    uint16_t i_cbSize;
2161
26
    MP4_GET2BYTESLE( i_cbSize );
2162
2163
26
    if( i_cbSize > i_read )
2164
0
        goto error;
2165
2166
26
    p_WMA2->i_extra = i_cbSize;
2167
26
    if ( p_WMA2->i_extra )
2168
26
    {
2169
26
        p_WMA2->p_extra = malloc( p_WMA2->i_extra );
2170
26
        if ( ! p_WMA2->p_extra )
2171
0
            goto error;
2172
26
        memcpy( p_WMA2->p_extra, p_peek, p_WMA2->i_extra );
2173
26
    }
2174
2175
26
    MP4_READBOX_EXIT( 1 );
2176
2177
0
error:
2178
0
    MP4_READBOX_EXIT( 0 );
2179
0
}
2180
2181
static void MP4_FreeBox_strf( MP4_Box_t *p_box )
2182
0
{
2183
0
    free( p_box->data.p_strf->p_extra );
2184
0
}
2185
2186
static int MP4_ReadBox_strf( stream_t *p_stream, MP4_Box_t *p_box )
2187
0
{
2188
0
    MP4_READBOX_ENTER( MP4_Box_data_strf_t, MP4_FreeBox_strf );
2189
2190
0
    MP4_Box_data_strf_t *p_strf = p_box->data.p_strf;
2191
2192
0
    if( i_read < 40 )
2193
0
        goto error;
2194
2195
0
    MP4_GET4BYTESLE( p_strf->bmiHeader.biSize );
2196
0
    MP4_GET4BYTESLE( p_strf->bmiHeader.biWidth );
2197
0
    MP4_GET4BYTESLE( p_strf->bmiHeader.biHeight );
2198
0
    MP4_GET2BYTESLE( p_strf->bmiHeader.biPlanes );
2199
0
    MP4_GET2BYTESLE( p_strf->bmiHeader.biBitCount );
2200
0
    MP4_GETFOURCC( p_strf->bmiHeader.biCompression );
2201
0
    MP4_GET4BYTESLE( p_strf->bmiHeader.biSizeImage );
2202
0
    MP4_GET4BYTESLE( p_strf->bmiHeader.biXPelsPerMeter );
2203
0
    MP4_GET4BYTESLE( p_strf->bmiHeader.biYPelsPerMeter );
2204
0
    MP4_GET4BYTESLE( p_strf->bmiHeader.biClrUsed );
2205
0
    MP4_GET4BYTESLE( p_strf->bmiHeader.biClrImportant );
2206
2207
0
    p_strf->i_extra = i_read;
2208
0
    if ( p_strf->i_extra )
2209
0
    {
2210
0
        p_strf->p_extra = malloc( p_strf->i_extra );
2211
0
        if ( ! p_strf->p_extra )
2212
0
            goto error;
2213
0
        memcpy( p_strf->p_extra, p_peek, i_read );
2214
0
    }
2215
2216
0
    MP4_READBOX_EXIT( 1 );
2217
2218
0
error:
2219
0
    MP4_READBOX_EXIT( 0 );
2220
0
}
2221
2222
static int MP4_ReadBox_ASF( stream_t *p_stream, MP4_Box_t *p_box )
2223
0
{
2224
0
    MP4_READBOX_ENTER( MP4_Box_data_ASF_t, NULL );
2225
2226
0
    MP4_Box_data_ASF_t *p_asf = p_box->data.p_asf;
2227
2228
0
    if (i_read != 8)
2229
0
        MP4_READBOX_EXIT( 0 );
2230
2231
0
    MP4_GET1BYTE( p_asf->i_stream_number );
2232
    /* remaining is unknown */
2233
2234
0
    MP4_READBOX_EXIT( 1 );
2235
0
}
2236
2237
static void MP4_FreeBox_sbgp( MP4_Box_t *p_box )
2238
6
{
2239
6
    MP4_Box_data_sbgp_t *p_sbgp = p_box->data.p_sbgp;
2240
6
    free( p_sbgp->p_entries );
2241
6
}
2242
2243
static int MP4_ReadBox_sbgp( stream_t *p_stream, MP4_Box_t *p_box )
2244
6
{
2245
6
    MP4_READBOX_ENTER( MP4_Box_data_sbgp_t, MP4_FreeBox_sbgp );
2246
6
    MP4_Box_data_sbgp_t *p_sbgp = p_box->data.p_sbgp;
2247
6
    uint32_t i_flags;
2248
2249
6
    if ( i_read < 12 )
2250
0
        MP4_READBOX_EXIT( 0 );
2251
2252
6
    MP4_GET1BYTE( p_sbgp->i_version );
2253
6
    MP4_GET3BYTES( i_flags );
2254
6
    if( i_flags != 0 )
2255
1
        MP4_READBOX_EXIT( 0 );
2256
2257
5
    MP4_GETFOURCC( p_sbgp->i_grouping_type );
2258
2259
5
    if( p_sbgp->i_version == 1 )
2260
0
    {
2261
0
        if( i_read < 8 )
2262
0
            MP4_READBOX_EXIT( 0 );
2263
0
        MP4_GET4BYTES( p_sbgp->i_grouping_type_parameter );
2264
0
    }
2265
2266
5
    MP4_GET4BYTES( p_sbgp->i_entry_count );
2267
5
    if( p_sbgp->i_entry_count > i_read / (4 + 4) )
2268
0
        p_sbgp->i_entry_count = i_read / (4 + 4);
2269
2270
5
    p_sbgp->p_entries = vlc_alloc( p_sbgp->i_entry_count, sizeof(*p_sbgp->p_entries) );
2271
5
    if( !p_sbgp->p_entries )
2272
0
    {
2273
0
        MP4_FreeBox_sbgp( p_box );
2274
0
        MP4_READBOX_EXIT( 0 );
2275
0
    }
2276
2277
52
    for( uint32_t i=0; i<p_sbgp->i_entry_count; i++ )
2278
47
    {
2279
47
        MP4_GET4BYTES( p_sbgp->p_entries[i].i_sample_count );
2280
47
        MP4_GET4BYTES( p_sbgp->p_entries[i].i_group_description_index );
2281
47
    }
2282
2283
5
#ifdef MP4_VERBOSE
2284
5
    msg_Dbg( p_stream,
2285
5
        "read box: \"sbgp\" grouping type %4.4s", (char*) &p_sbgp->i_grouping_type );
2286
 #ifdef MP4_ULTRA_VERBOSE
2287
    for (uint32_t i = 0; i < p_sbgp->i_entry_count; i++)
2288
        msg_Dbg( p_stream, "\t samples %" PRIu32 " group %" PRIu32,
2289
                 p_sbgp->entries[i].i_sample_count,
2290
                 p_sbgp->entries[i].i_group_description_index );
2291
 #endif
2292
5
#endif
2293
2294
5
    MP4_READBOX_EXIT( 1 );
2295
5
}
2296
2297
static void MP4_FreeBox_sgpd( MP4_Box_t *p_box )
2298
6
{
2299
6
    MP4_Box_data_sgpd_t *p_sgpd = p_box->data.p_sgpd;
2300
6
    free( p_sgpd->p_entries );
2301
6
}
2302
2303
static int MP4_ReadBox_sgpd( stream_t *p_stream, MP4_Box_t *p_box )
2304
6
{
2305
6
    MP4_READBOX_ENTER( MP4_Box_data_sgpd_t, MP4_FreeBox_sgpd );
2306
6
    MP4_Box_data_sgpd_t *p_sgpd = p_box->data.p_sgpd;
2307
6
    uint32_t i_flags;
2308
6
    uint32_t i_default_length = 0;
2309
2310
6
    if ( i_read < 8 )
2311
0
        MP4_READBOX_EXIT( 0 );
2312
2313
6
    MP4_GET1BYTE( p_sgpd->i_version );
2314
6
    MP4_GET3BYTES( i_flags );
2315
6
    if( i_flags != 0 )
2316
0
        MP4_READBOX_EXIT( 0 );
2317
2318
6
    MP4_GETFOURCC( p_sgpd->i_grouping_type );
2319
2320
6
    switch( p_sgpd->i_grouping_type )
2321
6
    {
2322
1
        case SAMPLEGROUP_rap:
2323
2
        case SAMPLEGROUP_roll:
2324
2
            break;
2325
2326
4
        default:
2327
4
#ifdef MP4_VERBOSE
2328
4
    msg_Dbg( p_stream,
2329
4
        "read box: \"sgpd\" grouping type %4.4s (unimplemented)", (char*) &p_sgpd->i_grouping_type );
2330
4
#endif
2331
4
            MP4_READBOX_EXIT( 1 );
2332
6
    }
2333
2334
2
    if( p_sgpd->i_version == 1 )
2335
2
    {
2336
2
        if( i_read < 8 )
2337
0
            MP4_READBOX_EXIT( 0 );
2338
2
        MP4_GET4BYTES( i_default_length );
2339
2
    }
2340
0
    else if( p_sgpd->i_version >= 2 )
2341
0
    {
2342
0
        if( i_read < 8 )
2343
0
            MP4_READBOX_EXIT( 0 );
2344
0
        MP4_GET4BYTES( p_sgpd->i_default_sample_description_index );
2345
0
    }
2346
2347
2
    MP4_GET4BYTES( p_sgpd->i_entry_count );
2348
2349
2
    p_sgpd->p_entries = vlc_alloc( p_sgpd->i_entry_count, sizeof(*p_sgpd->p_entries) );
2350
2
    if( !p_sgpd->p_entries )
2351
0
        MP4_READBOX_EXIT( 0 );
2352
2353
2
    uint32_t i = 0;
2354
3
    for( ; i<p_sgpd->i_entry_count; i++ )
2355
1
    {
2356
1
        uint32_t i_description_length = i_default_length;
2357
1
        if( p_sgpd->i_version == 1 && i_default_length == 0 )
2358
0
        {
2359
0
            if( i_read < 4 )
2360
0
                break;
2361
0
            MP4_GET4BYTES( i_description_length );
2362
0
        }
2363
2364
1
        if( p_sgpd->i_version == 1 && i_read < i_description_length )
2365
0
            break;
2366
2367
1
        switch( p_sgpd->i_grouping_type )
2368
1
        {
2369
1
            case SAMPLEGROUP_rap:
2370
1
                {
2371
1
                    if( i_read < 1 )
2372
0
                    {
2373
0
                        free( p_sgpd->p_entries );
2374
0
                        p_sgpd->i_entry_count = 0;
2375
0
                        p_sgpd->p_entries = NULL;
2376
0
                        MP4_READBOX_EXIT( 0 );
2377
0
                    }
2378
1
                    uint8_t i_data;
2379
1
                    MP4_GET1BYTE( i_data );
2380
1
                    p_sgpd->p_entries[i].rap.i_num_leading_samples_known = i_data & 0x80;
2381
1
                    p_sgpd->p_entries[i].rap.i_num_leading_samples = i_data & 0x7F;
2382
1
                }
2383
0
                break;
2384
2385
0
            case SAMPLEGROUP_roll:
2386
0
                {
2387
0
                    if( i_read < 2 )
2388
0
                    {
2389
0
                        free( p_sgpd->p_entries );
2390
0
                        p_sgpd->i_entry_count = 0;
2391
0
                        p_sgpd->p_entries = NULL;
2392
0
                        MP4_READBOX_EXIT( 0 );
2393
0
                    }
2394
0
                    union
2395
0
                    {
2396
0
                        uint16_t u;
2397
0
                        int16_t  s;
2398
0
                    } readsigned;
2399
0
                    MP4_GET2BYTES( readsigned.u );
2400
0
                    p_sgpd->p_entries[i].roll.i_roll_distance = readsigned.s;
2401
0
                }
2402
0
                break;
2403
2404
0
            default:
2405
0
                vlc_assert_unreachable();
2406
0
                free( p_sgpd->p_entries );
2407
0
                p_sgpd->i_entry_count = 0;
2408
0
                p_sgpd->p_entries = NULL;
2409
0
                MP4_READBOX_EXIT( 0 );
2410
1
        }
2411
1
    }
2412
2413
2
    if( i != p_sgpd->i_entry_count )
2414
0
        p_sgpd->i_entry_count = i;
2415
2416
2
#ifdef MP4_VERBOSE
2417
2
    msg_Dbg( p_stream,
2418
2
        "read box: \"sgpd\" grouping type %4.4s", (char*) &p_sgpd->i_grouping_type );
2419
2
#endif
2420
2421
2
    MP4_READBOX_EXIT( 1 );
2422
2
}
2423
2424
static void MP4_FreeBox_stsdext_chan( MP4_Box_t *p_box )
2425
2
{
2426
2
    MP4_Box_data_chan_t *p_chan = p_box->data.p_chan;
2427
2
    CoreAudio_Layout_Clean( &p_chan->layout );
2428
2
}
2429
2430
static int MP4_ReadBox_stsdext_chan( stream_t *p_stream, MP4_Box_t *p_box )
2431
2
{
2432
2
    MP4_READBOX_ENTER( MP4_Box_data_chan_t, MP4_FreeBox_stsdext_chan );
2433
2
    MP4_Box_data_chan_t *p_chan = p_box->data.p_chan;
2434
2435
2
    if ( i_read < 16 )
2436
0
        MP4_READBOX_EXIT( 0 );
2437
2438
2
    MP4_GET1BYTE( p_chan->i_version );
2439
2
    MP4_GET3BYTES( p_chan->i_channels_flags );
2440
2
    MP4_GET4BYTES( p_chan->layout.i_channels_layout_tag );
2441
2
    MP4_GET4BYTES( p_chan->layout.i_channels_bitmap );
2442
2
    MP4_GET4BYTES( p_chan->layout.i_channels_description_count );
2443
2444
2
    size_t i_descsize = 8 + 3 * sizeof(float);
2445
2
    if ( i_read < p_chan->layout.i_channels_description_count * i_descsize )
2446
0
        MP4_READBOX_EXIT( 0 );
2447
2448
2
    p_chan->layout.p_descriptions =
2449
2
        vlc_alloc( p_chan->layout.i_channels_description_count, i_descsize );
2450
2451
2
    if ( !p_chan->layout.p_descriptions )
2452
0
        MP4_READBOX_EXIT( 0 );
2453
2454
2
    uint32_t i;
2455
2
    for( i=0; i<p_chan->layout.i_channels_description_count; i++ )
2456
0
    {
2457
0
        if ( i_read < 20 )
2458
0
            break;
2459
0
        MP4_GET4BYTES( p_chan->layout.p_descriptions[i].i_channel_label );
2460
0
        MP4_GET4BYTES( p_chan->layout.p_descriptions[i].i_channel_flags );
2461
0
        MP4_GET4BYTES( p_chan->layout.p_descriptions[i].f_coordinates[0] );
2462
0
        MP4_GET4BYTES( p_chan->layout.p_descriptions[i].f_coordinates[1] );
2463
0
        MP4_GET4BYTES( p_chan->layout.p_descriptions[i].f_coordinates[2] );
2464
0
    }
2465
2
    if ( i<p_chan->layout.i_channels_description_count )
2466
0
        p_chan->layout.i_channels_description_count = i;
2467
2468
2
#ifdef MP4_VERBOSE
2469
2
    msg_Dbg( p_stream,
2470
2
             "read box: \"chan\" flags=0x%x tag=0x%x bitmap=0x%x descriptions=%u",
2471
2
             p_chan->i_channels_flags, p_chan->layout.i_channels_layout_tag,
2472
2
             p_chan->layout.i_channels_bitmap, p_chan->layout.i_channels_description_count );
2473
2
#endif
2474
2
    MP4_READBOX_EXIT( 1 );
2475
2
}
2476
2477
static int MP4_ReadBox_stsdext_srat( stream_t *p_stream, MP4_Box_t *p_box )
2478
0
{
2479
0
    MP4_READBOX_ENTER( MP4_Box_data_srat_t, NULL );
2480
0
    MP4_Box_data_srat_t *p_srat = p_box->data.p_srat;
2481
0
    if ( i_read != 8 )
2482
0
        MP4_READBOX_EXIT( 0 );
2483
2484
0
    MP4_SKIPBYTES( 4 ); /* version flags */
2485
0
    MP4_GET4BYTES( p_srat->i_sample_rate );
2486
2487
0
    MP4_READBOX_EXIT( 1 );
2488
0
}
2489
2490
static int MP4_ReadBox_dec3( stream_t *p_stream, MP4_Box_t *p_box )
2491
0
{
2492
0
    MP4_READBOX_ENTER( MP4_Box_data_dec3_t, NULL );
2493
2494
0
    MP4_Box_data_dec3_t *p_dec3 = p_box->data.p_dec3;
2495
2496
0
    unsigned i_header;
2497
0
    MP4_GET2BYTES( i_header );
2498
2499
0
    p_dec3->i_data_rate = i_header >> 3;
2500
0
    p_dec3->i_num_ind_sub = (i_header & 0x7) + 1;
2501
0
    for (uint8_t i = 0; i < p_dec3->i_num_ind_sub; i++) {
2502
0
        MP4_GET3BYTES( i_header );
2503
0
        p_dec3->stream[i].i_fscod = ( i_header >> 22 ) & 0x03;
2504
0
        p_dec3->stream[i].i_bsid  = ( i_header >> 17 ) & 0x01f;
2505
0
        p_dec3->stream[i].i_bsmod = ( i_header >> 12 ) & 0x01f;
2506
0
        p_dec3->stream[i].i_acmod = ( i_header >> 9 ) & 0x07;
2507
0
        p_dec3->stream[i].i_lfeon = ( i_header >> 8 ) & 0x01;
2508
0
        p_dec3->stream[i].i_num_dep_sub = (i_header >> 1) & 0x0f;
2509
0
        if (p_dec3->stream[i].i_num_dep_sub) {
2510
0
            MP4_GET1BYTE( p_dec3->stream[i].i_chan_loc );
2511
0
            p_dec3->stream[i].i_chan_loc |= (i_header & 1) << 8;
2512
0
        } else
2513
0
            p_dec3->stream[i].i_chan_loc = 0;
2514
0
    }
2515
2516
0
#ifdef MP4_VERBOSE
2517
0
    msg_Dbg( p_stream,
2518
0
        "read box: \"dec3\" bitrate %dkbps %d independent substreams",
2519
0
            p_dec3->i_data_rate, p_dec3->i_num_ind_sub);
2520
2521
0
    for (uint8_t i = 0; i < p_dec3->i_num_ind_sub; i++)
2522
0
        msg_Dbg( p_stream,
2523
0
                "\tstream %d: bsid=0x%x bsmod=0x%x acmod=0x%x lfeon=0x%x "
2524
0
                "num dependent subs=%d chan_loc=0x%x",
2525
0
                i, p_dec3->stream[i].i_bsid, p_dec3->stream[i].i_bsmod, p_dec3->stream[i].i_acmod,
2526
0
                p_dec3->stream[i].i_lfeon, p_dec3->stream[i].i_num_dep_sub, p_dec3->stream[i].i_chan_loc );
2527
0
#endif
2528
0
    MP4_READBOX_EXIT( 1 );
2529
0
}
2530
2531
static int MP4_ReadBox_dac3( stream_t *p_stream, MP4_Box_t *p_box )
2532
0
{
2533
0
    MP4_Box_data_dac3_t *p_dac3;
2534
0
    MP4_READBOX_ENTER( MP4_Box_data_dac3_t, NULL );
2535
2536
0
    p_dac3 = p_box->data.p_dac3;
2537
2538
0
    unsigned i_header;
2539
0
    MP4_GET3BYTES( i_header );
2540
2541
0
    p_dac3->i_fscod = ( i_header >> 22 ) & 0x03;
2542
0
    p_dac3->i_bsid  = ( i_header >> 17 ) & 0x01f;
2543
0
    p_dac3->i_bsmod = ( i_header >> 14 ) & 0x07;
2544
0
    p_dac3->i_acmod = ( i_header >> 11 ) & 0x07;
2545
0
    p_dac3->i_lfeon = ( i_header >> 10 ) & 0x01;
2546
0
    p_dac3->i_bitrate_code = ( i_header >> 5) & 0x1f;
2547
2548
0
#ifdef MP4_VERBOSE
2549
0
    msg_Dbg( p_stream,
2550
0
             "read box: \"dac3\" fscod=0x%x bsid=0x%x bsmod=0x%x acmod=0x%x lfeon=0x%x bitrate_code=0x%x",
2551
0
             p_dac3->i_fscod, p_dac3->i_bsid, p_dac3->i_bsmod, p_dac3->i_acmod, p_dac3->i_lfeon, p_dac3->i_bitrate_code );
2552
0
#endif
2553
0
    MP4_READBOX_EXIT( 1 );
2554
0
}
2555
2556
static void MP4_FreeBox_dvc1( MP4_Box_t *p_box )
2557
36
{
2558
36
    free( p_box->data.p_dvc1->p_vc1 );
2559
36
}
2560
2561
static int MP4_ReadBox_dvc1( stream_t *p_stream, MP4_Box_t *p_box )
2562
36
{
2563
36
    MP4_READBOX_ENTER( MP4_Box_data_dvc1_t, MP4_FreeBox_dvc1 );
2564
36
    if( i_read < 7 )
2565
0
        MP4_READBOX_EXIT( 0 );
2566
2567
36
    MP4_Box_data_dvc1_t *p_dvc1 = p_box->data.p_dvc1;
2568
36
    MP4_GET1BYTE( p_dvc1->i_profile_level );
2569
36
    p_dvc1->i_vc1 = i_read; /* Header + profile_level */
2570
36
    if( p_dvc1->i_vc1 > 0 && (p_dvc1->p_vc1 = malloc( p_dvc1->i_vc1 )) )
2571
36
        memcpy( p_dvc1->p_vc1, p_peek, i_read );
2572
2573
36
#ifdef MP4_VERBOSE
2574
36
    uint8_t i_profile = (p_dvc1->i_profile_level & 0xf0) >> 4;
2575
36
    msg_Dbg( p_stream, "read box: \"dvc1\" profile=%"PRIu8, i_profile );
2576
36
#endif
2577
2578
36
    MP4_READBOX_EXIT( 1 );
2579
36
}
2580
2581
static int MP4_ReadBox_fiel( stream_t *p_stream, MP4_Box_t *p_box )
2582
16
{
2583
16
    MP4_Box_data_fiel_t *p_fiel;
2584
16
    MP4_READBOX_ENTER( MP4_Box_data_fiel_t, NULL );
2585
16
    p_fiel = p_box->data.p_fiel;
2586
16
    if(i_read < 2)
2587
0
        MP4_READBOX_EXIT( 0 );
2588
16
    if(p_peek[0] == 2) /* Interlaced */
2589
13
    {
2590
        /*
2591
         * 0 – There is only one field.
2592
         * 1 – T is displayed earliest, T is stored first in the file.
2593
         * 6 – B is displayed earliest, B is stored first in the file.
2594
         * 9 – B is displayed earliest, T is stored first in the file.
2595
         * 14 – T is displayed earliest, B is stored first in the file.
2596
        */
2597
13
        if(p_peek[1] == 0)
2598
0
            p_fiel->i_flags = BLOCK_FLAG_SINGLE_FIELD;
2599
13
        else if(p_peek[1] == 1 || p_peek[1] == 9)
2600
0
            p_fiel->i_flags = BLOCK_FLAG_TOP_FIELD_FIRST;
2601
13
        else if(p_peek[1] == 6 || p_peek[1] == 14)
2602
13
            p_fiel->i_flags = BLOCK_FLAG_BOTTOM_FIELD_FIRST;
2603
13
    }
2604
16
    MP4_READBOX_EXIT( 1 );
2605
16
}
2606
2607
static int MP4_ReadBox_enda( stream_t *p_stream, MP4_Box_t *p_box )
2608
0
{
2609
0
    MP4_Box_data_enda_t *p_enda;
2610
0
    MP4_READBOX_ENTER( MP4_Box_data_enda_t, NULL );
2611
2612
0
    p_enda = p_box->data.p_enda;
2613
2614
0
    MP4_GET2BYTES( p_enda->i_little_endian );
2615
2616
0
#ifdef MP4_VERBOSE
2617
0
    msg_Dbg( p_stream,
2618
0
             "read box: \"enda\" little_endian=%d", p_enda->i_little_endian );
2619
0
#endif
2620
0
    MP4_READBOX_EXIT( 1 );
2621
0
}
2622
2623
static int MP4_ReadBox_pcmC( stream_t *p_stream, MP4_Box_t *p_box )
2624
0
{
2625
0
    MP4_READBOX_ENTER( MP4_Box_data_pcmC_t, NULL );
2626
0
    if(i_read != 6)
2627
0
        MP4_READBOX_EXIT( 0 );
2628
0
    uint32_t temp;
2629
0
    MP4_GET4BYTES(temp);
2630
0
    if(temp != 0) /* support only v0 */
2631
0
        MP4_READBOX_EXIT( 0 );
2632
0
    MP4_GET1BYTE(p_box->data.p_pcmC->i_format_flags);
2633
0
    MP4_GET1BYTE(p_box->data.p_pcmC->i_sample_size);
2634
0
    MP4_READBOX_EXIT( 1 );
2635
0
}
2636
2637
static void MP4_FreeBox_sample_soun( MP4_Box_t *p_box )
2638
238
{
2639
238
    free( p_box->data.p_sample_soun->p_qt_description );
2640
238
}
2641
2642
static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box )
2643
238
{
2644
238
    p_box->i_handler = ATOM_soun;
2645
238
    MP4_READBOX_ENTER( MP4_Box_data_sample_soun_t, MP4_FreeBox_sample_soun );
2646
238
    p_box->data.p_sample_soun->p_qt_description = NULL;
2647
2648
238
    size_t i_actually_read = i_read + header_size;
2649
2650
    /* Sanity check needed because the "wave" box does also contain an
2651
     * "mp4a" box that we don't understand. */
2652
238
    if( i_read < 28 )
2653
8
    {
2654
8
        MP4_READBOX_EXIT( 1 );
2655
8
    }
2656
2657
230
    READ_SAMPLE_DESC_COMMON_8BYTES_HEADER;
2658
2659
    /*
2660
     * XXX hack -> produce a copy of the nearly complete chunk
2661
     */
2662
230
    p_box->data.p_sample_soun->i_qt_description = 0;
2663
230
    p_box->data.p_sample_soun->p_qt_description = NULL;
2664
230
    if( i_read > 0 )
2665
230
    {
2666
230
        p_box->data.p_sample_soun->p_qt_description = malloc( i_read );
2667
230
        if( p_box->data.p_sample_soun->p_qt_description )
2668
230
        {
2669
230
            p_box->data.p_sample_soun->i_qt_description = i_read;
2670
230
            memcpy( p_box->data.p_sample_soun->p_qt_description, p_peek, i_read );
2671
230
        }
2672
230
    }
2673
2674
230
    MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_version );
2675
230
    MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_revision_level );
2676
230
    MP4_GET4BYTES( p_box->data.p_sample_soun->i_qt_vendor );
2677
2678
230
    MP4_GET2BYTES( p_box->data.p_sample_soun->i_channelcount );
2679
230
    MP4_GET2BYTES( p_box->data.p_sample_soun->i_samplesize );
2680
230
    MP4_GET2BYTES( p_box->data.p_sample_soun->i_compressionid );
2681
230
    MP4_GET2BYTES( p_box->data.p_sample_soun->i_reserved3 );
2682
230
    MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratehi );
2683
230
    MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratelo );
2684
2685
230
#ifdef MP4_VERBOSE
2686
230
    msg_Dbg( p_stream,
2687
230
             "read box: \"soun\" stsd qt_version %"PRIu16" compid=%"PRIx16,
2688
230
             p_box->data.p_sample_soun->i_qt_version,
2689
230
             p_box->data.p_sample_soun->i_compressionid );
2690
230
#endif
2691
    /* @36 bytes */
2692
230
    if( p_box->data.p_sample_soun->i_qt_version == 1 && i_read >= 16 )
2693
9
    {
2694
        /* SoundDescriptionV1 */
2695
9
        MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet );
2696
9
        MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_packet );
2697
9
        MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_frame );
2698
9
        MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_sample );
2699
2700
9
#ifdef MP4_VERBOSE
2701
9
        msg_Dbg( p_stream,
2702
9
                 "read box: \"soun\" V1 sample/packet=%d bytes/packet=%d "
2703
9
                 "bytes/frame=%d bytes/sample=%d",
2704
9
                 p_box->data.p_sample_soun->i_sample_per_packet,
2705
9
                 p_box->data.p_sample_soun->i_bytes_per_packet,
2706
9
                 p_box->data.p_sample_soun->i_bytes_per_frame,
2707
9
                 p_box->data.p_sample_soun->i_bytes_per_sample );
2708
9
#endif
2709
        /* @52 bytes */
2710
9
    }
2711
221
    else if( p_box->data.p_sample_soun->i_qt_version == 2 && i_read >= 36 )
2712
15
    {
2713
        /* SoundDescriptionV2 */
2714
15
        double f_sample_rate;
2715
15
        int64_t i_dummy64;
2716
15
        uint32_t i_channel, i_extoffset, i_dummy32;
2717
2718
        /* Checks */
2719
15
        if ( p_box->data.p_sample_soun->i_channelcount != 0x3  ||
2720
1
             p_box->data.p_sample_soun->i_samplesize != 0x0010 ||
2721
1
             p_box->data.p_sample_soun->i_compressionid != 0xFFFE ||
2722
0
             p_box->data.p_sample_soun->i_reserved3 != 0x0     ||
2723
0
             p_box->data.p_sample_soun->i_sampleratehi != 0x1  ||//65536
2724
0
             p_box->data.p_sample_soun->i_sampleratelo != 0x0 )  //remainder
2725
15
        {
2726
15
            msg_Err( p_stream, "invalid stsd V2 box defaults" );
2727
15
            MP4_READBOX_EXIT( 0 );
2728
15
        }
2729
        /* !Checks */
2730
2731
0
        MP4_GET4BYTES( i_extoffset ); /* offset to stsd extensions */
2732
0
        MP4_GET8BYTES( i_dummy64 );
2733
0
        memcpy( &f_sample_rate, &i_dummy64, 8 );
2734
0
        msg_Dbg( p_stream, "read box: %f Hz", f_sample_rate );
2735
        /* Rounding error with lo, but we don't care since we do not support fractional audio rate */
2736
0
        p_box->data.p_sample_soun->i_sampleratehi = (uint16_t)f_sample_rate;
2737
0
        p_box->data.p_sample_soun->i_sampleratelo = (f_sample_rate - p_box->data.p_sample_soun->i_sampleratehi);
2738
2739
0
        MP4_GET4BYTES( i_channel );
2740
0
        p_box->data.p_sample_soun->i_channelcount = i_channel;
2741
2742
0
        MP4_GET4BYTES( i_dummy32 );
2743
0
        if ( i_dummy32 != 0x7F000000 )
2744
0
        {
2745
0
            msg_Err( p_stream, "invalid stsd V2 box" );
2746
0
            MP4_READBOX_EXIT( 0 );
2747
0
        }
2748
2749
0
        MP4_GET4BYTES( p_box->data.p_sample_soun->i_constbitsperchannel );
2750
0
        MP4_GET4BYTES( p_box->data.p_sample_soun->i_formatflags );
2751
0
        MP4_GET4BYTES( p_box->data.p_sample_soun->i_constbytesperaudiopacket );
2752
0
        MP4_GET4BYTES( p_box->data.p_sample_soun->i_constLPCMframesperaudiopacket );
2753
2754
0
#ifdef MP4_VERBOSE
2755
0
        msg_Dbg( p_stream, "read box: \"soun\" V2 rate=%f bitsperchannel=%u "
2756
0
                           "flags=%u bytesperpacket=%u lpcmframesperpacket=%u",
2757
0
                 f_sample_rate,
2758
0
                 p_box->data.p_sample_soun->i_constbitsperchannel,
2759
0
                 p_box->data.p_sample_soun->i_formatflags,
2760
0
                 p_box->data.p_sample_soun->i_constbytesperaudiopacket,
2761
0
                 p_box->data.p_sample_soun->i_constLPCMframesperaudiopacket );
2762
0
#endif
2763
        /* @72 bytes + */
2764
0
        if( i_extoffset > i_actually_read )
2765
0
            i_extoffset = i_actually_read;
2766
0
        p_peek = &p_buff[i_extoffset];
2767
0
        i_read = i_actually_read - i_extoffset;
2768
0
    }
2769
206
    else
2770
206
    {
2771
206
        p_box->data.p_sample_soun->i_sample_per_packet = 0;
2772
206
        p_box->data.p_sample_soun->i_bytes_per_packet = 0;
2773
206
        p_box->data.p_sample_soun->i_bytes_per_frame = 0;
2774
206
        p_box->data.p_sample_soun->i_bytes_per_sample = 0;
2775
2776
206
#ifdef MP4_VERBOSE
2777
206
        msg_Dbg( p_stream, "read box: \"soun\" V0 or qt1/2 (rest=%"PRIu64")",
2778
206
                 i_read );
2779
206
#endif
2780
        /* @36 bytes */
2781
206
    }
2782
2783
215
    if( p_box->i_type == ATOM_drms )
2784
0
    {
2785
0
        msg_Warn( p_stream, "DRM protected streams are not supported." );
2786
0
        MP4_READBOX_EXIT( 0 );
2787
0
    }
2788
2789
215
    if( p_box->i_type == ATOM_samr || p_box->i_type == ATOM_sawb )
2790
0
    {
2791
        /* Ignore channelcount for AMR (3gpp AMRSpecificBox) */
2792
0
        p_box->data.p_sample_soun->i_channelcount = 1;
2793
0
    }
2794
2795
    /* Loads extensions */
2796
215
    MP4_ReadBoxContainerRawInBox( p_stream, p_box, p_peek, i_read,
2797
215
                                  p_box->i_pos + p_peek - p_buff ); /* esds/wave/... */
2798
2799
215
#ifdef MP4_VERBOSE
2800
215
    msg_Dbg( p_stream, "read box: \"soun\" in stsd channel %d "
2801
215
             "sample size %d sample rate %f",
2802
215
             p_box->data.p_sample_soun->i_channelcount,
2803
215
             p_box->data.p_sample_soun->i_samplesize,
2804
215
             (float)p_box->data.p_sample_soun->i_sampleratehi +
2805
215
             (float)p_box->data.p_sample_soun->i_sampleratelo / BLOCK16x16 );
2806
2807
215
#endif
2808
215
    MP4_READBOX_EXIT( 1 );
2809
215
}
2810
2811
static void MP4_FreeBox_sample_vide( MP4_Box_t *p_box )
2812
820
{
2813
820
    free( p_box->data.p_sample_vide->p_qt_image_description );
2814
820
    free( p_box->data.p_sample_vide->p_palette );
2815
820
}
2816
2817
int MP4_ReadBox_sample_vide( stream_t *p_stream, MP4_Box_t *p_box )
2818
820
{
2819
820
    p_box->i_handler = ATOM_vide;
2820
820
    MP4_READBOX_ENTER( MP4_Box_data_sample_vide_t, MP4_FreeBox_sample_vide );
2821
2822
820
    size_t i_actually_read = i_read + header_size;
2823
2824
820
    READ_SAMPLE_DESC_COMMON_8BYTES_HEADER;
2825
2826
    /*
2827
     * XXX hack -> produce a copy of the nearly complete chunk
2828
     */
2829
820
    if( i_read > 0 )
2830
818
    {
2831
818
        p_box->data.p_sample_vide->p_qt_image_description = malloc( i_read );
2832
818
        if( unlikely( p_box->data.p_sample_vide->p_qt_image_description == NULL ) )
2833
0
            MP4_READBOX_EXIT( 0 );
2834
818
        p_box->data.p_sample_vide->i_qt_image_description = i_read;
2835
818
        memcpy( p_box->data.p_sample_vide->p_qt_image_description,
2836
818
                p_peek, i_read );
2837
818
    }
2838
2
    else
2839
2
    {
2840
2
        p_box->data.p_sample_vide->i_qt_image_description = 0;
2841
2
        p_box->data.p_sample_vide->p_qt_image_description = NULL;
2842
2
    }
2843
2844
820
    MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_version );
2845
820
    MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_revision_level );
2846
820
    MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_vendor );
2847
2848
820
    MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_temporal_quality );
2849
820
    MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_spatial_quality );
2850
2851
820
    MP4_GET2BYTES( p_box->data.p_sample_vide->i_width );
2852
820
    MP4_GET2BYTES( p_box->data.p_sample_vide->i_height );
2853
2854
820
    MP4_GET4BYTES( p_box->data.p_sample_vide->i_horizresolution );
2855
820
    MP4_GET4BYTES( p_box->data.p_sample_vide->i_vertresolution );
2856
2857
820
    MP4_GET4BYTES( p_box->data.p_sample_vide->reserved );
2858
820
    MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_frame_count );
2859
2860
820
    if ( i_read < 32 )
2861
2
        MP4_READBOX_EXIT( 0 );
2862
818
    if( p_peek[0] <= 31 ) // Must be Pascal String
2863
749
    {
2864
749
        memcpy( &p_box->data.p_sample_vide->sz_compressorname, &p_peek[1], p_peek[0] );
2865
749
        p_box->data.p_sample_vide->sz_compressorname[p_peek[0]] = 0;
2866
749
    }
2867
818
    p_peek += 32; i_read -= 32;
2868
2869
818
    MP4_GET2BYTES( p_box->data.p_sample_vide->i_depth );
2870
818
    MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_color_table );
2871
2872
818
    if( p_box->data.p_sample_vide->i_depth == 8 &&
2873
5
        p_box->data.p_sample_vide->i_qt_color_table == 0 )
2874
0
    {
2875
0
        p_box->data.p_sample_vide->p_palette = ReadQuicktimePalette( &p_peek, &i_read );
2876
0
        if( p_box->data.p_sample_vide->p_palette == NULL )
2877
0
            MP4_READBOX_EXIT( 0 );
2878
0
    }
2879
2880
818
    if( p_box->i_type == ATOM_drmi )
2881
0
    {
2882
0
        msg_Warn( p_stream, "DRM protected streams are not supported." );
2883
0
        MP4_READBOX_EXIT( 0 );
2884
0
    }
2885
2886
818
    if( i_actually_read > 78 && p_peek - p_buff > 78 )
2887
818
    {
2888
818
        MP4_ReadBoxContainerRawInBox( p_stream, p_box, p_peek, i_read,
2889
818
                                      p_box->i_pos + p_peek - p_buff );
2890
818
    }
2891
2892
818
#ifdef MP4_VERBOSE
2893
818
    msg_Dbg( p_stream, "read box: \"vide\" in stsd %dx%d depth %d (%s)",
2894
818
                      p_box->data.p_sample_vide->i_width,
2895
818
                      p_box->data.p_sample_vide->i_height,
2896
818
                      p_box->data.p_sample_vide->i_depth,
2897
818
                      p_box->data.p_sample_vide->sz_compressorname );
2898
2899
818
#endif
2900
818
    MP4_READBOX_EXIT( 1 );
2901
818
}
2902
2903
static void MP4_FreeBox_sample_generic( MP4_Box_t *p_box )
2904
321
{
2905
321
    free( p_box->data.p_sample_gen->p_data );
2906
321
}
2907
2908
static int MP4_ReadBox_sample_generic( stream_t *p_stream, MP4_Box_t *p_box )
2909
0
{
2910
0
    MP4_READBOX_ENTER_PARTIAL( MP4_Box_data_sample_generic_t, 16, NULL );
2911
2912
0
    READ_SAMPLE_DESC_COMMON_8BYTES_HEADER;
2913
2914
0
    switch( p_box->i_type )
2915
0
    {
2916
0
        case ATOM_mp4s:
2917
0
            p_box->i_handler = ATOM_text;
2918
0
            break;
2919
0
        default:
2920
0
            msg_Warn( p_stream, "Unknown mapping for %4.4s with generic handler",
2921
0
                      (const char *)&p_box->i_type );
2922
0
            break;
2923
0
    }
2924
2925
0
    MP4_ReadBoxContainerChildren( p_stream, p_box, NULL );
2926
2927
0
    if ( MP4_Seek( p_stream, p_box->i_pos + p_box->i_size ) )
2928
0
        MP4_READBOX_EXIT( 0 );
2929
2930
0
    MP4_READBOX_EXIT( 1 );
2931
0
}
2932
2933
static int MP4_ReadBox_sample_hint8( stream_t *p_stream, MP4_Box_t *p_box )
2934
184
{
2935
184
    MP4_READBOX_ENTER_PARTIAL( MP4_Box_data_sample_generic_t, 24, MP4_FreeBox_sample_generic );
2936
2937
183
    READ_SAMPLE_DESC_COMMON_8BYTES_HEADER;
2938
2939
180
    if( !(p_box->data.p_sample_gen->p_data = malloc(8)) )
2940
0
        MP4_READBOX_EXIT( 0 );
2941
2942
180
    MP4_GET8BYTES( *(p_box->data.p_sample_gen->p_data) );
2943
180
    p_box->data.p_sample_gen->i_data = 8;
2944
2945
180
    MP4_ReadBoxContainerChildren(p_stream, p_box, NULL);
2946
2947
180
    if ( MP4_Seek( p_stream, p_box->i_pos + p_box->i_size ) )
2948
0
        MP4_READBOX_EXIT( 0 );
2949
2950
180
    MP4_READBOX_EXIT( 1 );
2951
180
}
2952
2953
static int MP4_ReadBox_sample_text( stream_t *p_stream, MP4_Box_t *p_box )
2954
149
{
2955
149
    p_box->i_handler = ATOM_text;
2956
149
    MP4_READBOX_ENTER( MP4_Box_data_sample_generic_t, MP4_FreeBox_sample_generic );
2957
2958
138
    READ_SAMPLE_DESC_COMMON_8BYTES_HEADER;
2959
2960
137
    if( i_read )
2961
133
    {
2962
133
        p_box->data.p_sample_gen->p_data = malloc( i_read );
2963
133
        if( !p_box->data.p_sample_gen->p_data )
2964
0
            MP4_READBOX_EXIT( 0 );
2965
133
        memcpy( p_box->data.p_sample_gen->p_data, p_peek, i_read );
2966
133
    }
2967
137
    p_box->data.p_sample_gen->i_data = i_read;
2968
2969
137
#ifdef MP4_VERBOSE
2970
137
    msg_Dbg( p_stream, "read box: \"%4.4s\" in stsd", (const char*) &p_box->i_type );
2971
137
#endif
2972
137
    MP4_READBOX_EXIT( 1 );
2973
137
}
2974
2975
static int MP4_ReadBox_stsd( stream_t *p_stream, MP4_Box_t *p_box )
2976
1.32k
{
2977
1.32k
    MP4_READBOX_ENTER_PARTIAL( MP4_Box_data_lcont_t, 16, NULL );
2978
1.32k
    if( i_read < 8 )
2979
0
        MP4_READBOX_EXIT( 0 );
2980
2981
1.32k
    MP4_GETVERSIONFLAGS( p_box->data.p_lcont );
2982
1.32k
    if( p_box->data.p_lcont->i_version > 1 )
2983
0
        MP4_READBOX_EXIT( 0 );
2984
1.32k
    MP4_GET4BYTES( p_box->data.p_lcont->i_entry_count );
2985
2986
1.32k
    const MP4_Box_t *p_mdia = MP4_BoxGet( p_box, "../../../" );
2987
1.32k
    const MP4_Box_t *p_hdlr;
2988
1.32k
    if( p_mdia == NULL || p_mdia->i_type != ATOM_mdia ||
2989
1.32k
        (p_hdlr = MP4_BoxGet( p_mdia, "hdlr" )) == NULL )
2990
0
    {
2991
0
        if ( MP4_Seek( p_stream, p_box->i_pos + p_box->i_size ) == VLC_SUCCESS )
2992
0
        {
2993
0
            msg_Warn( p_stream, "missing hdlr for stsd, delaying" );
2994
0
            MP4_READBOX_EXIT( 1 );
2995
0
        }
2996
0
        MP4_READBOX_EXIT( 0 );
2997
0
    }
2998
2999
    /* Tag stsd with handler type that children can just read from */
3000
1.32k
    p_box->i_handler = BOXDATA(p_hdlr)->i_handler_type;
3001
3002
1.32k
    uint32_t i_entry = 0;
3003
1.32k
    i_read = p_box->i_size - 16;
3004
2.68k
    while (i_read > 8 && i_entry < p_box->data.p_lcont->i_entry_count )
3005
1.45k
    {
3006
1.45k
        int(*pf_read)(stream_t *, MP4_Box_t *);
3007
1.45k
        switch( BOXDATA(p_hdlr)->i_handler_type )
3008
1.45k
        {
3009
239
            case ATOM_soun:
3010
239
                pf_read = MP4_ReadBox_sample_soun;
3011
239
                break;
3012
827
            case ATOM_vide:
3013
827
            case ATOM_pict: /* heif */
3014
827
                pf_read = MP4_ReadBox_sample_vide;
3015
827
                break;
3016
184
            case ATOM_hint:
3017
184
                pf_read = MP4_ReadBox_sample_hint8;
3018
184
                break;
3019
0
            case ATOM_clcp:
3020
199
            case ATOM_text:
3021
199
            case ATOM_subt:
3022
200
            case ATOM_tx3g:
3023
200
            case ATOM_sbtl:
3024
200
                pf_read = MP4_ReadBox_sample_text;
3025
200
                break;
3026
0
            case ATOM_subp: /* see #13464 */
3027
0
                pf_read = MP4_ReadBox_sample_generic;
3028
0
                break;
3029
4
            default:
3030
4
                pf_read = NULL;
3031
4
                msg_Warn( p_stream, "unknown handler type %4.4s in stsd",
3032
4
                          (const char *)& BOXDATA(p_hdlr)->i_handler_type );
3033
4
                break;
3034
1.45k
        }
3035
3036
1.45k
        if( !pf_read )
3037
4
            break;
3038
3039
1.45k
        MP4_Box_t *p_sample = MP4_ReadBoxUsing( p_stream, p_box, pf_read );
3040
1.45k
        if( !p_sample )
3041
92
            break;
3042
3043
        /* write back stsd handler in case of final handler set by child */
3044
1.35k
        p_box->i_handler = p_sample->i_handler;
3045
3046
1.35k
        MP4_BoxAddChild( p_box, p_sample );
3047
1.35k
        i_entry++;
3048
3049
1.35k
        if( i_read < p_sample->i_size )
3050
0
            MP4_READBOX_EXIT( 0 );
3051
3052
1.35k
        i_read -= p_sample->i_size;
3053
1.35k
    }
3054
3055
1.32k
    if (i_entry != p_box->data.p_lcont->i_entry_count)
3056
166
        p_box->data.p_lcont->i_entry_count = i_entry;
3057
3058
1.32k
#ifdef MP4_VERBOSE
3059
1.32k
    msg_Dbg( p_stream, "read box: \"%4.4s\" entry-count %d", (char *)&p_box->i_type,
3060
1.32k
                        p_box->data.p_lcont->i_entry_count );
3061
3062
1.32k
#endif
3063
3064
1.32k
    if ( MP4_Seek( p_stream, p_box->i_pos + p_box->i_size ) )
3065
0
        MP4_READBOX_EXIT( 0 );
3066
3067
1.32k
    MP4_READBOX_EXIT( 1 );
3068
1.32k
}
3069
3070
static void MP4_FreeBox_stsz( MP4_Box_t *p_box )
3071
1.18k
{
3072
1.18k
    free( p_box->data.p_stsz->i_entry_size );
3073
1.18k
}
3074
3075
static int MP4_ReadBox_stsz( stream_t *p_stream, MP4_Box_t *p_box )
3076
1.18k
{
3077
1.18k
    uint32_t count;
3078
3079
1.18k
    MP4_READBOX_ENTER( MP4_Box_data_stsz_t, MP4_FreeBox_stsz );
3080
3081
1.18k
    MP4_GETVERSIONFLAGS( p_box->data.p_stsz );
3082
3083
1.18k
    MP4_GET4BYTES( p_box->data.p_stsz->i_sample_size );
3084
1.18k
    MP4_GET4BYTES( count );
3085
1.18k
    p_box->data.p_stsz->i_sample_count = count;
3086
3087
1.18k
    if( p_box->data.p_stsz->i_sample_size == 0 )
3088
514
    {
3089
514
        if( UINT64_C(4) * count > i_read )
3090
0
            MP4_READBOX_EXIT( 0 );
3091
3092
514
        p_box->data.p_stsz->i_entry_size =
3093
514
            vlc_alloc( count, sizeof(uint32_t) );
3094
514
        if( unlikely( !p_box->data.p_stsz->i_entry_size ) )
3095
0
            MP4_READBOX_EXIT( 0 );
3096
3097
229k
        for( uint32_t i = 0; i < count; i++ )
3098
228k
        {
3099
228k
            MP4_GET4BYTES( p_box->data.p_stsz->i_entry_size[i] );
3100
228k
        }
3101
514
    }
3102
667
    else
3103
667
        p_box->data.p_stsz->i_entry_size = NULL;
3104
3105
1.18k
#ifdef MP4_VERBOSE
3106
1.18k
    msg_Dbg( p_stream, "read box: \"stsz\" sample-size %d sample-count %d",
3107
1.18k
                      p_box->data.p_stsz->i_sample_size,
3108
1.18k
                      p_box->data.p_stsz->i_sample_count );
3109
3110
1.18k
#endif
3111
1.18k
    MP4_READBOX_EXIT( 1 );
3112
1.18k
}
3113
3114
static int MP4_ReadBox_stz2( stream_t *p_stream, MP4_Box_t *p_box )
3115
0
{
3116
0
    uint32_t count;
3117
0
    uint8_t field_size;
3118
3119
0
    MP4_READBOX_ENTER( MP4_Box_data_stsz_t, MP4_FreeBox_stsz );
3120
3121
0
    MP4_GETVERSIONFLAGS( p_box->data.p_stsz );
3122
3123
0
    uint32_t reserved;
3124
0
    MP4_GET3BYTES( reserved );
3125
0
    (void) reserved;
3126
3127
0
    MP4_GET1BYTE(field_size);
3128
3129
0
    MP4_GET4BYTES( count );
3130
0
    p_box->data.p_stsz->i_sample_count = count;
3131
3132
0
    if( field_size != 4 && field_size != 8 && field_size != 16 )
3133
0
        MP4_READBOX_EXIT( 0 );
3134
0
    if( ( (uint64_t)field_size * count + 7 ) / 8 > i_read )
3135
0
        MP4_READBOX_EXIT( 0 );
3136
3137
0
    p_box->data.p_stsz->i_entry_size =
3138
0
            vlc_alloc( count, sizeof(uint32_t) );
3139
0
    if( unlikely( p_box->data.p_stsz->i_entry_size == NULL ) )
3140
0
        MP4_READBOX_EXIT( 0 );
3141
3142
0
    if( field_size == 16 )
3143
0
    {
3144
0
        for( uint32_t i = 0; i < count; i++ )
3145
0
            MP4_GET2BYTES( p_box->data.p_stsz->i_entry_size[i] );
3146
0
    }
3147
0
    else if( field_size == 8 )
3148
0
    {
3149
0
        for( uint32_t i = 0; i < count; i++ )
3150
0
            MP4_GET1BYTE( p_box->data.p_stsz->i_entry_size[i] );
3151
0
    }
3152
0
    else
3153
0
    {
3154
0
        vlc_assert( field_size == 4 );
3155
0
        count &= ~1;
3156
0
        for( uint32_t i = 0; i < count; i += 2 )
3157
0
        {
3158
0
            uint8_t entry;
3159
0
            MP4_GET1BYTE( entry );
3160
0
            p_box->data.p_stsz->i_entry_size[i] = entry >> 4;
3161
0
            p_box->data.p_stsz->i_entry_size[i + 1] = entry & 0x0F;
3162
0
        }
3163
0
        if( count < p_box->data.p_stsz->i_sample_count )
3164
0
        {
3165
0
            uint8_t entry;
3166
            /* ISO-14496-12: if the sizes do not fill an integral number of
3167
             * bytes, the last byte is padded with zeros.
3168
             */
3169
0
            MP4_GET1BYTE( entry );
3170
0
            p_box->data.p_stsz->i_entry_size[count] = entry >> 4;
3171
0
        }
3172
0
    }
3173
3174
0
#ifdef MP4_VERBOSE
3175
0
    msg_Dbg( p_stream, "read box: \"stz2\" field-size %d sample-count %d",
3176
0
             field_size,
3177
0
             p_box->data.p_stsz->i_sample_count );
3178
3179
0
#endif
3180
0
    MP4_READBOX_EXIT( 1 );
3181
0
}
3182
3183
static void MP4_FreeBox_stsc( MP4_Box_t *p_box )
3184
1.08k
{
3185
1.08k
    free( p_box->data.p_stsc->i_first_chunk );
3186
1.08k
    free( p_box->data.p_stsc->i_samples_per_chunk );
3187
1.08k
    free( p_box->data.p_stsc->i_sample_description_index );
3188
1.08k
}
3189
3190
static int MP4_ReadBox_stsc( stream_t *p_stream, MP4_Box_t *p_box )
3191
1.08k
{
3192
1.08k
    uint32_t count;
3193
3194
1.08k
    MP4_READBOX_ENTER( MP4_Box_data_stsc_t, MP4_FreeBox_stsc );
3195
3196
1.08k
    MP4_GETVERSIONFLAGS( p_box->data.p_stsc );
3197
1.08k
    MP4_GET4BYTES( count );
3198
3199
1.08k
    if( UINT64_C(12) * count > i_read )
3200
1
        MP4_READBOX_EXIT( 0 );
3201
3202
1.08k
    p_box->data.p_stsc->i_first_chunk = vlc_alloc( count, sizeof(uint32_t) );
3203
1.08k
    p_box->data.p_stsc->i_samples_per_chunk = vlc_alloc( count,
3204
1.08k
                                                         sizeof(uint32_t) );
3205
1.08k
    p_box->data.p_stsc->i_sample_description_index = vlc_alloc( count,
3206
1.08k
                                                            sizeof(uint32_t) );
3207
1.08k
    if( unlikely( p_box->data.p_stsc->i_first_chunk == NULL
3208
1.08k
     || p_box->data.p_stsc->i_samples_per_chunk == NULL
3209
1.08k
     || p_box->data.p_stsc->i_sample_description_index == NULL ) )
3210
0
    {
3211
0
        MP4_READBOX_EXIT( 0 );
3212
0
    }
3213
1.08k
    p_box->data.p_stsc->i_entry_count = count;
3214
3215
32.9k
    for( uint32_t i = 0; i < count;i++ )
3216
31.8k
    {
3217
31.8k
        MP4_GET4BYTES( p_box->data.p_stsc->i_first_chunk[i] );
3218
31.8k
        MP4_GET4BYTES( p_box->data.p_stsc->i_samples_per_chunk[i] );
3219
31.8k
        MP4_GET4BYTES( p_box->data.p_stsc->i_sample_description_index[i] );
3220
31.8k
    }
3221
3222
1.08k
#ifdef MP4_VERBOSE
3223
1.08k
    msg_Dbg( p_stream, "read box: \"stsc\" entry-count %d",
3224
1.08k
                      p_box->data.p_stsc->i_entry_count );
3225
3226
1.08k
#endif
3227
1.08k
    MP4_READBOX_EXIT( 1 );
3228
1.08k
}
3229
3230
static void MP4_FreeBox_sdp( MP4_Box_t *p_box )
3231
24
{
3232
24
    free( p_box->data.p_sdp->psz_text );
3233
24
}
3234
3235
static int MP4_ReadBox_sdp( stream_t *p_stream, MP4_Box_t *p_box )
3236
24
{
3237
24
   MP4_READBOX_ENTER( MP4_Box_data_sdp_t, MP4_FreeBox_sdp );
3238
3239
24
   MP4_GETSTRINGZ( p_box->data.p_sdp->psz_text );
3240
3241
24
   MP4_READBOX_EXIT( 1 );
3242
24
}
3243
3244
static void MP4_FreeBox_rtp( MP4_Box_t *p_box )
3245
0
{
3246
0
    free( p_box->data.p_moviehintinformation_rtp->psz_text );
3247
0
}
3248
3249
static int MP4_ReadBox_rtp( stream_t *p_stream, MP4_Box_t *p_box )
3250
0
{
3251
0
    MP4_READBOX_ENTER( MP4_Box_data_moviehintinformation_rtp_t, MP4_FreeBox_rtp );
3252
3253
0
    MP4_GET4BYTES( p_box->data.p_moviehintinformation_rtp->i_description_format );
3254
3255
0
    MP4_GETSTRINGZ( p_box->data.p_moviehintinformation_rtp->psz_text );
3256
3257
0
    MP4_READBOX_EXIT( 1 );
3258
0
}
3259
3260
static int MP4_ReadBox_tims( stream_t *p_stream, MP4_Box_t *p_box )
3261
164
{
3262
164
    MP4_READBOX_ENTER( MP4_Box_data_tims_t, NULL );
3263
3264
164
    MP4_GET4BYTES( p_box->data.p_tims->i_timescale );
3265
3266
164
    MP4_READBOX_EXIT( 1 );
3267
164
}
3268
3269
static int MP4_ReadBox_tsro( stream_t *p_stream, MP4_Box_t *p_box )
3270
0
{
3271
0
    MP4_READBOX_ENTER( MP4_Box_data_tsro_t, NULL );
3272
3273
0
    MP4_GET4BYTES( p_box->data.p_tsro->i_offset );
3274
3275
0
    MP4_READBOX_EXIT( 1 );
3276
0
}
3277
3278
static int MP4_ReadBox_tssy( stream_t *p_stream, MP4_Box_t *p_box )
3279
0
{
3280
0
    MP4_READBOX_ENTER( MP4_Box_data_tssy_t,  NULL );
3281
3282
0
    MP4_GET1BYTE( p_box->data.p_tssy->i_reserved_timestamp_sync );
3283
3284
0
    MP4_READBOX_EXIT( 1 );
3285
0
}
3286
3287
static void MP4_FreeBox_stco_co64( MP4_Box_t *p_box )
3288
1.18k
{
3289
1.18k
    free( p_box->data.p_co64->i_chunk_offset );
3290
1.18k
}
3291
3292
static int MP4_ReadBox_stco_co64( stream_t *p_stream, MP4_Box_t *p_box )
3293
1.18k
{
3294
1.18k
    const bool sixtyfour = p_box->i_type != ATOM_stco;
3295
1.18k
    uint32_t count;
3296
3297
1.18k
    MP4_READBOX_ENTER( MP4_Box_data_co64_t, MP4_FreeBox_stco_co64 );
3298
3299
1.18k
    MP4_GETVERSIONFLAGS( p_box->data.p_co64 );
3300
1.18k
    MP4_GET4BYTES( count );
3301
3302
1.18k
    if( (sixtyfour ? UINT64_C(8) : UINT64_C(4)) * count > i_read )
3303
1
        MP4_READBOX_EXIT( 0 );
3304
3305
1.17k
    p_box->data.p_co64->i_chunk_offset = vlc_alloc( count, sizeof(uint64_t) );
3306
1.17k
    if( unlikely(p_box->data.p_co64->i_chunk_offset == NULL) )
3307
0
        MP4_READBOX_EXIT( 0 );
3308
1.17k
    p_box->data.p_co64->i_entry_count = count;
3309
3310
121k
    for( uint32_t i = 0; i < count; i++ )
3311
120k
    {
3312
120k
        if( sixtyfour )
3313
120k
            MP4_GET8BYTES( p_box->data.p_co64->i_chunk_offset[i] );
3314
120k
        else
3315
120k
            MP4_GET4BYTES( p_box->data.p_co64->i_chunk_offset[i] );
3316
120k
    }
3317
3318
1.17k
#ifdef MP4_VERBOSE
3319
1.17k
    msg_Dbg( p_stream, "read box: \"co64\" entry-count %d",
3320
1.17k
                      p_box->data.p_co64->i_entry_count );
3321
3322
1.17k
#endif
3323
1.17k
    MP4_READBOX_EXIT( 1 );
3324
1.17k
}
3325
3326
static void MP4_FreeBox_stss( MP4_Box_t *p_box )
3327
501
{
3328
501
    free( p_box->data.p_stss->i_sample_number );
3329
501
}
3330
3331
static int MP4_ReadBox_stss( stream_t *p_stream, MP4_Box_t *p_box )
3332
501
{
3333
501
    uint32_t count;
3334
3335
501
    MP4_READBOX_ENTER( MP4_Box_data_stss_t, MP4_FreeBox_stss );
3336
3337
501
    MP4_GETVERSIONFLAGS( p_box->data.p_stss );
3338
501
    MP4_GET4BYTES( count );
3339
3340
501
    if( UINT64_C(4) * count > i_read )
3341
12
        MP4_READBOX_EXIT( 0 );
3342
3343
489
    p_box->data.p_stss->i_sample_number = vlc_alloc( count, sizeof(uint32_t) );
3344
489
    if( unlikely( p_box->data.p_stss->i_sample_number == NULL ) )
3345
0
        MP4_READBOX_EXIT( 0 );
3346
489
    p_box->data.p_stss->i_entry_count = count;
3347
3348
15.1k
    for( uint32_t i = 0; i < count; i++ )
3349
14.6k
    {
3350
14.6k
        MP4_GET4BYTES( p_box->data.p_stss->i_sample_number[i] );
3351
14.6k
    }
3352
3353
489
#ifdef MP4_VERBOSE
3354
489
    msg_Dbg( p_stream, "read box: \"stss\" entry-count %d",
3355
489
                      p_box->data.p_stss->i_entry_count );
3356
3357
489
#endif
3358
489
    MP4_READBOX_EXIT( 1 );
3359
489
}
3360
3361
static void MP4_FreeBox_stsh( MP4_Box_t *p_box )
3362
1
{
3363
1
    free( p_box->data.p_stsh->i_shadowed_sample_number );
3364
1
    free( p_box->data.p_stsh->i_sync_sample_number );
3365
1
}
3366
3367
static int MP4_ReadBox_stsh( stream_t *p_stream, MP4_Box_t *p_box )
3368
1
{
3369
1
    uint32_t count;
3370
3371
1
    MP4_READBOX_ENTER( MP4_Box_data_stsh_t, MP4_FreeBox_stsh );
3372
3373
1
    MP4_GETVERSIONFLAGS( p_box->data.p_stsh );
3374
1
    MP4_GET4BYTES( count );
3375
3376
1
    if( UINT64_C(8) * count > i_read )
3377
0
        MP4_READBOX_EXIT( 0 );
3378
3379
1
    p_box->data.p_stsh->i_shadowed_sample_number = vlc_alloc( count,
3380
1
                                                            sizeof(uint32_t) );
3381
1
    p_box->data.p_stsh->i_sync_sample_number = vlc_alloc( count,
3382
1
                                                          sizeof(uint32_t) );
3383
1
    if( p_box->data.p_stsh->i_shadowed_sample_number == NULL
3384
1
     || p_box->data.p_stsh->i_sync_sample_number == NULL )
3385
0
        MP4_READBOX_EXIT( 0 );
3386
1
    p_box->data.p_stsh->i_entry_count = count;
3387
3388
70
    for( uint32_t i = 0; i < p_box->data.p_stss->i_entry_count; i++ )
3389
69
    {
3390
69
        MP4_GET4BYTES( p_box->data.p_stsh->i_shadowed_sample_number[i] );
3391
69
        MP4_GET4BYTES( p_box->data.p_stsh->i_sync_sample_number[i] );
3392
69
    }
3393
3394
1
#ifdef MP4_VERBOSE
3395
1
    msg_Dbg( p_stream, "read box: \"stsh\" entry-count %d",
3396
1
                      p_box->data.p_stsh->i_entry_count );
3397
1
#endif
3398
1
    MP4_READBOX_EXIT( 1 );
3399
1
}
3400
3401
static void MP4_FreeBox_stdp( MP4_Box_t *p_box )
3402
0
{
3403
0
    free( p_box->data.p_stdp->i_priority );
3404
0
}
3405
3406
static int MP4_ReadBox_stdp( stream_t *p_stream, MP4_Box_t *p_box )
3407
0
{
3408
0
    MP4_READBOX_ENTER( MP4_Box_data_stdp_t, MP4_FreeBox_stdp );
3409
3410
0
    MP4_GETVERSIONFLAGS( p_box->data.p_stdp );
3411
3412
0
    p_box->data.p_stdp->i_priority =
3413
0
        calloc( i_read / 2, sizeof(*p_box->data.p_stdp->i_priority) );
3414
3415
0
    if( unlikely( !p_box->data.p_stdp->i_priority ) )
3416
0
        MP4_READBOX_EXIT( 0 );
3417
3418
0
    for( unsigned i = 0; i < i_read / 2 ; i++ )
3419
0
    {
3420
0
        MP4_GET2BYTES( p_box->data.p_stdp->i_priority[i] );
3421
0
    }
3422
3423
0
#ifdef MP4_VERBOSE
3424
0
    msg_Dbg( p_stream, "read box: \"stdp\" entry-count %"PRId64,
3425
0
                      i_read / 2 );
3426
3427
0
#endif
3428
0
    MP4_READBOX_EXIT( 1 );
3429
0
}
3430
3431
static void MP4_FreeBox_elst( MP4_Box_t *p_box )
3432
962
{
3433
962
    free( p_box->data.p_elst->entries );
3434
962
}
3435
3436
static int MP4_ReadBox_elst( stream_t *p_stream, MP4_Box_t *p_box )
3437
962
{
3438
962
    uint32_t count;
3439
3440
962
    MP4_READBOX_ENTER( MP4_Box_data_elst_t, MP4_FreeBox_elst );
3441
962
    MP4_Box_data_elst_t *p_elst = p_box->data.p_elst;
3442
3443
962
    uint8_t i_version;
3444
962
    MP4_GET1BYTE( i_version );
3445
962
    MP4_SKIPBYTES( 3 );  // flags
3446
3447
962
    if( i_version > 1 )
3448
3
        MP4_READBOX_EXIT( 0 );
3449
3450
959
    MP4_GET4BYTES( count );
3451
959
    if( count == 0 )
3452
55
        MP4_READBOX_EXIT( 1 );
3453
3454
904
    uint32_t i_entries_max = i_read / ((i_version == 1) ? 20 : 12);
3455
904
    if( count > i_entries_max )
3456
53
        count = i_entries_max;
3457
3458
904
    p_elst->entries = vlc_alloc( count, sizeof(*p_elst->entries) );
3459
904
    if( !p_elst->entries )
3460
0
        MP4_READBOX_EXIT( 0 );
3461
3462
904
    p_elst->i_entry_count = count;
3463
3464
1.86k
    for( uint32_t i = 0; i < count; i++ )
3465
958
    {
3466
958
        uint64_t segment_duration;
3467
958
        int64_t media_time;
3468
3469
958
        if( i_version == 1 )
3470
9
        {
3471
9
            union { int64_t s; uint64_t u; } u;
3472
3473
9
            MP4_GET8BYTES( segment_duration );
3474
9
            MP4_GET8BYTES( u.u );
3475
9
            media_time = u.s;
3476
9
        }
3477
949
        else
3478
949
        {
3479
949
            union { int32_t s; uint32_t u; } u;
3480
3481
949
            MP4_GET4BYTES( segment_duration );
3482
949
            MP4_GET4BYTES( u.u );
3483
949
            media_time = u.s;
3484
949
        }
3485
3486
958
        p_elst->entries[i].i_segment_duration = segment_duration;
3487
958
        p_elst->entries[i].i_media_time = media_time;
3488
958
        MP4_GET2BYTES( p_elst->entries[i].i_media_rate_integer );
3489
958
        MP4_GET2BYTES( p_elst->entries[i].i_media_rate_fraction );
3490
958
    }
3491
3492
904
#ifdef MP4_VERBOSE
3493
904
    msg_Dbg( p_stream, "read box: \"elst\" entry-count %" PRIu32,
3494
904
             p_elst->i_entry_count );
3495
904
#endif
3496
904
    MP4_READBOX_EXIT( 1 );
3497
904
}
3498
3499
static void MP4_FreeBox_cprt( MP4_Box_t *p_box )
3500
1
{
3501
1
    free( p_box->data.p_cprt->psz_notice );
3502
1
}
3503
3504
static int MP4_ReadBox_cprt( stream_t *p_stream, MP4_Box_t *p_box )
3505
1
{
3506
1
    uint16_t i_language;
3507
1
    bool b_mac;
3508
3509
1
    MP4_READBOX_ENTER( MP4_Box_data_cprt_t, MP4_FreeBox_cprt );
3510
3511
1
    MP4_GETVERSIONFLAGS( p_box->data.p_cprt );
3512
3513
1
    MP4_GET2BYTES( i_language );
3514
1
    decodeQtLanguageCode( i_language, p_box->data.p_cprt->rgs_language, &b_mac );
3515
3516
1
    MP4_GETSTRINGZ( p_box->data.p_cprt->psz_notice );
3517
3518
1
#ifdef MP4_VERBOSE
3519
1
    msg_Dbg( p_stream, "read box: \"cprt\" language %3.3s notice %s",
3520
1
                      p_box->data.p_cprt->rgs_language,
3521
1
                      p_box->data.p_cprt->psz_notice );
3522
3523
1
#endif
3524
1
    MP4_READBOX_EXIT( 1 );
3525
1
}
3526
3527
static int MP4_ReadBox_dcom( stream_t *p_stream, MP4_Box_t *p_box )
3528
0
{
3529
0
    MP4_READBOX_ENTER( MP4_Box_data_dcom_t, NULL );
3530
3531
0
    MP4_GETFOURCC( p_box->data.p_dcom->i_algorithm );
3532
0
#ifdef MP4_VERBOSE
3533
0
    msg_Dbg( p_stream,
3534
0
             "read box: \"dcom\" compression algorithm : %4.4s",
3535
0
                      (char*)&p_box->data.p_dcom->i_algorithm );
3536
0
#endif
3537
0
    MP4_READBOX_EXIT( 1 );
3538
0
}
3539
3540
static void MP4_FreeBox_cmvd( MP4_Box_t *p_box )
3541
0
{
3542
0
    free( p_box->data.p_cmvd->p_data );
3543
0
}
3544
3545
static int MP4_ReadBox_cmvd( stream_t *p_stream, MP4_Box_t *p_box )
3546
0
{
3547
0
    MP4_READBOX_ENTER( MP4_Box_data_cmvd_t, MP4_FreeBox_cmvd );
3548
3549
0
    MP4_GET4BYTES( p_box->data.p_cmvd->i_uncompressed_size );
3550
3551
0
    p_box->data.p_cmvd->i_compressed_size = i_read;
3552
3553
0
    if( !( p_box->data.p_cmvd->p_data = malloc( i_read ) ) )
3554
0
        MP4_READBOX_EXIT( 0 );
3555
3556
    /* now copy compressed data */
3557
0
    memcpy( p_box->data.p_cmvd->p_data, p_peek,i_read);
3558
3559
0
#ifdef MP4_VERBOSE
3560
0
    msg_Dbg( p_stream, "read box: \"cmvd\" compressed data size %d",
3561
0
                      p_box->data.p_cmvd->i_compressed_size );
3562
0
#endif
3563
3564
0
    MP4_READBOX_EXIT( 1 );
3565
0
}
3566
3567
static int MP4_ReadBox_cmov( stream_t *p_stream, MP4_Box_t *p_box )
3568
0
{
3569
#ifndef HAVE_ZLIB
3570
    (void)p_box;
3571
    msg_Dbg( p_stream, "read box: \"cmov\" zlib unsupported" );
3572
    return 0;
3573
#else
3574
3575
0
    MP4_Box_t *p_dcom;
3576
0
    MP4_Box_t *p_cmvd;
3577
3578
0
    stream_t *p_stream_memory;
3579
0
    z_stream z_data;
3580
0
    uint8_t *p_data;
3581
3582
0
    if( !MP4_ReadBoxContainer( p_stream, p_box ) )
3583
0
    {
3584
0
        return 0;
3585
0
    }
3586
3587
0
    if( ( p_dcom = MP4_BoxGet( p_box, "dcom" ) ) == NULL ||
3588
0
        ( p_cmvd = MP4_BoxGet( p_box, "cmvd" ) ) == NULL ||
3589
0
        p_cmvd->data.p_cmvd->p_data == NULL )
3590
0
    {
3591
0
        msg_Warn( p_stream, "read box: \"cmov\" incomplete" );
3592
0
        return 0;
3593
0
    }
3594
3595
0
    if( p_dcom->data.p_dcom->i_algorithm != ATOM_zlib )
3596
0
    {
3597
0
        msg_Dbg( p_stream, "read box: \"cmov\" compression algorithm : %4.4s "
3598
0
                 "not supported", (char*)&p_dcom->data.p_dcom->i_algorithm );
3599
0
        return 0;
3600
0
    }
3601
3602
    /* decompress data */
3603
    /* allocate a new buffer */
3604
0
    if( !( p_data = malloc( p_cmvd->data.p_cmvd->i_uncompressed_size ) ) )
3605
0
        return 0;
3606
    /* init default structures */
3607
0
    z_data.next_in   = p_cmvd->data.p_cmvd->p_data;
3608
0
    z_data.avail_in  = p_cmvd->data.p_cmvd->i_compressed_size;
3609
0
    z_data.next_out  = p_data;
3610
0
    z_data.avail_out = p_cmvd->data.p_cmvd->i_uncompressed_size;
3611
0
    z_data.zalloc    = (alloc_func)Z_NULL;
3612
0
    z_data.zfree     = (free_func)Z_NULL;
3613
0
    z_data.opaque    = (voidpf)Z_NULL;
3614
3615
    /* init zlib */
3616
0
    if( inflateInit( &z_data ) != Z_OK )
3617
0
    {
3618
0
        msg_Err( p_stream, "read box: \"cmov\" error while uncompressing" );
3619
0
        free( p_data );
3620
0
        return 0;
3621
0
    }
3622
3623
    /* uncompress */
3624
0
    if( inflate( &z_data, Z_FINISH ) != Z_STREAM_END )
3625
0
    {
3626
0
        msg_Err( p_stream, "read box: \"cmov\" error while uncompressing" );
3627
0
        inflateEnd( &z_data );
3628
0
        free( p_data );
3629
0
        return 0;
3630
0
    }
3631
3632
0
    if( p_cmvd->data.p_cmvd->i_uncompressed_size != z_data.total_out )
3633
0
    {
3634
0
        msg_Warn( p_stream, "read box: \"cmov\" uncompressing data size "
3635
0
                  "mismatch" );
3636
0
    }
3637
3638
    /* close zlib */
3639
0
    if( inflateEnd( &z_data ) != Z_OK )
3640
0
    {
3641
0
        msg_Warn( p_stream, "read box: \"cmov\" error while uncompressing "
3642
0
                  "data (ignored)" );
3643
0
    }
3644
3645
0
    msg_Dbg( p_stream, "read box: \"cmov\" box successfully uncompressed" );
3646
3647
    /* now create a memory stream */
3648
0
    p_stream_memory = vlc_stream_MemoryNew( VLC_OBJECT(p_stream),
3649
0
                                            p_data, z_data.total_out, false );
3650
0
    if( !p_stream_memory )
3651
0
    {
3652
0
        free( p_data );
3653
0
        return 0;
3654
0
    }
3655
3656
    /* and read uncompressd moov */
3657
0
    MP4_Box_t *p_moov =  MP4_ReadBox( p_stream_memory, NULL );
3658
3659
0
    vlc_stream_Delete( p_stream_memory );
3660
3661
0
    if( p_moov )
3662
0
        MP4_BoxAddChild( p_box, p_moov );
3663
3664
0
#ifdef MP4_VERBOSE
3665
0
    msg_Dbg( p_stream, "read box: \"cmov\" compressed movie header completed");
3666
0
#endif
3667
3668
0
    return p_moov ? 1 : 0;
3669
0
#endif /* HAVE_ZLIB */
3670
0
}
3671
3672
static void MP4_FreeBox_rdrf( MP4_Box_t *p_box )
3673
0
{
3674
0
    free( p_box->data.p_rdrf->psz_ref );
3675
0
}
3676
3677
static int MP4_ReadBox_rdrf( stream_t *p_stream, MP4_Box_t *p_box )
3678
0
{
3679
0
    uint32_t i_len;
3680
0
    MP4_READBOX_ENTER( MP4_Box_data_rdrf_t, MP4_FreeBox_rdrf );
3681
3682
0
    MP4_GETVERSIONFLAGS( p_box->data.p_rdrf );
3683
0
    MP4_GETFOURCC( p_box->data.p_rdrf->i_ref_type );
3684
0
    MP4_GET4BYTES( i_len );
3685
3686
0
    if( i_len != 0 )
3687
0
    {
3688
0
        p_box->data.p_rdrf->psz_ref = malloc( i_len + 1 );
3689
0
        if( p_box->data.p_rdrf->psz_ref == NULL )
3690
0
            MP4_READBOX_EXIT( 0 );
3691
3692
0
        MP4_COPY_BYTES( p_box->data.p_rdrf->psz_ref, i_len );
3693
0
        p_box->data.p_rdrf->psz_ref[i_len] = '\0';
3694
0
    }
3695
0
    else
3696
0
    {
3697
0
        p_box->data.p_rdrf->psz_ref = NULL;
3698
0
    }
3699
3700
0
#ifdef MP4_VERBOSE
3701
0
    msg_Dbg( p_stream,
3702
0
            "read box: \"rdrf\" type:%4.4s ref %s",
3703
0
            (char*)&p_box->data.p_rdrf->i_ref_type,
3704
0
            p_box->data.p_rdrf->psz_ref );
3705
0
#endif
3706
0
    MP4_READBOX_EXIT( 1 );
3707
0
}
3708
3709
3710
3711
static int MP4_ReadBox_rmdr( stream_t *p_stream, MP4_Box_t *p_box )
3712
0
{
3713
0
    MP4_READBOX_ENTER( MP4_Box_data_rmdr_t, NULL );
3714
3715
0
    MP4_GETVERSIONFLAGS( p_box->data.p_rmdr );
3716
3717
0
    MP4_GET4BYTES( p_box->data.p_rmdr->i_rate );
3718
3719
0
#ifdef MP4_VERBOSE
3720
0
    msg_Dbg( p_stream,
3721
0
             "read box: \"rmdr\" rate:%d",
3722
0
             p_box->data.p_rmdr->i_rate );
3723
0
#endif
3724
0
    MP4_READBOX_EXIT( 1 );
3725
0
}
3726
3727
static int MP4_ReadBox_rmqu( stream_t *p_stream, MP4_Box_t *p_box )
3728
0
{
3729
0
    MP4_READBOX_ENTER( MP4_Box_data_rmqu_t, NULL );
3730
3731
0
    MP4_GET4BYTES( p_box->data.p_rmqu->i_quality );
3732
3733
0
#ifdef MP4_VERBOSE
3734
0
    msg_Dbg( p_stream,
3735
0
             "read box: \"rmqu\" quality:%d",
3736
0
             p_box->data.p_rmqu->i_quality );
3737
0
#endif
3738
0
    MP4_READBOX_EXIT( 1 );
3739
0
}
3740
3741
static int MP4_ReadBox_rmvc( stream_t *p_stream, MP4_Box_t *p_box )
3742
0
{
3743
0
    MP4_READBOX_ENTER( MP4_Box_data_rmvc_t, NULL );
3744
0
    MP4_GETVERSIONFLAGS( p_box->data.p_rmvc );
3745
3746
0
    MP4_GETFOURCC( p_box->data.p_rmvc->i_gestaltType );
3747
0
    MP4_GET4BYTES( p_box->data.p_rmvc->i_val1 );
3748
0
    MP4_GET4BYTES( p_box->data.p_rmvc->i_val2 );
3749
0
    MP4_GET2BYTES( p_box->data.p_rmvc->i_checkType );
3750
3751
0
#ifdef MP4_VERBOSE
3752
0
    msg_Dbg( p_stream,
3753
0
             "read box: \"rmvc\" gestaltType:%4.4s val1:0x%x val2:0x%x checkType:0x%x",
3754
0
             (char*)&p_box->data.p_rmvc->i_gestaltType,
3755
0
             p_box->data.p_rmvc->i_val1,p_box->data.p_rmvc->i_val2,
3756
0
             p_box->data.p_rmvc->i_checkType );
3757
0
#endif
3758
3759
0
    MP4_READBOX_EXIT( 1 );
3760
0
}
3761
3762
static int MP4_ReadBox_frma( stream_t *p_stream, MP4_Box_t *p_box )
3763
8
{
3764
8
    MP4_READBOX_ENTER( MP4_Box_data_frma_t, NULL );
3765
3766
8
    MP4_GETFOURCC( p_box->data.p_frma->i_type );
3767
3768
8
#ifdef MP4_VERBOSE
3769
8
    msg_Dbg( p_stream, "read box: \"frma\" i_type:%4.4s",
3770
8
             (char *)&p_box->data.p_frma->i_type );
3771
8
#endif
3772
3773
8
    MP4_READBOX_EXIT( 1 );
3774
8
}
3775
3776
static int MP4_ReadBox_skcr( stream_t *p_stream, MP4_Box_t *p_box )
3777
0
{
3778
0
    MP4_READBOX_ENTER( MP4_Box_data_skcr_t, NULL );
3779
3780
0
    MP4_GET4BYTES( p_box->data.p_skcr->i_init );
3781
0
    MP4_GET4BYTES( p_box->data.p_skcr->i_encr );
3782
0
    MP4_GET4BYTES( p_box->data.p_skcr->i_decr );
3783
3784
0
#ifdef MP4_VERBOSE
3785
0
    msg_Dbg( p_stream, "read box: \"skcr\" i_init:%d i_encr:%d i_decr:%d",
3786
0
             p_box->data.p_skcr->i_init,
3787
0
             p_box->data.p_skcr->i_encr,
3788
0
             p_box->data.p_skcr->i_decr );
3789
0
#endif
3790
3791
0
    MP4_READBOX_EXIT( 1 );
3792
0
}
3793
3794
static int MP4_ReadBox_drms( stream_t *p_stream, MP4_Box_t *p_box )
3795
0
{
3796
0
    VLC_UNUSED(p_box);
3797
    /* ATOMs 'user', 'key', 'iviv', and 'priv' will be skipped,
3798
     * so unless data decrypt itself by magic, there will be no playback,
3799
     * but we never know... */
3800
0
    msg_Warn( p_stream, "DRM protected streams are not supported." );
3801
0
    return 1;
3802
0
}
3803
3804
static void MP4_FreeBox_Binary( MP4_Box_t *p_box )
3805
286
{
3806
286
    free( p_box->data.p_binary->p_blob );
3807
286
}
3808
3809
static int MP4_ReadBox_Binary( stream_t *p_stream, MP4_Box_t *p_box )
3810
286
{
3811
286
    MP4_READBOX_ENTER( MP4_Box_data_binary_t, MP4_FreeBox_Binary );
3812
286
    i_read = __MIN( i_read, UINT32_MAX );
3813
286
    if ( i_read > 0 )
3814
286
    {
3815
286
        p_box->data.p_binary->p_blob = malloc( i_read );
3816
286
        if ( p_box->data.p_binary->p_blob )
3817
286
        {
3818
286
            memcpy( p_box->data.p_binary->p_blob, p_peek, i_read );
3819
286
            p_box->data.p_binary->i_blob = i_read;
3820
286
        }
3821
286
    }
3822
286
    MP4_READBOX_EXIT( 1 );
3823
286
}
3824
3825
static void MP4_FreeBox_data( MP4_Box_t *p_box )
3826
133
{
3827
133
    free( p_box->data.p_data->p_blob );
3828
133
}
3829
3830
static int MP4_ReadBox_data( stream_t *p_stream, MP4_Box_t *p_box )
3831
133
{
3832
133
    MP4_READBOX_ENTER( MP4_Box_data_data_t, MP4_FreeBox_data );
3833
133
    MP4_Box_data_data_t *p_data = p_box->data.p_data;
3834
3835
133
    if ( i_read < 8 || i_read - 8 > UINT32_MAX )
3836
0
        MP4_READBOX_EXIT( 0 );
3837
3838
133
    uint8_t i_type;
3839
133
    MP4_GET1BYTE( i_type );
3840
133
    if ( i_type != 0 )
3841
1
    {
3842
1
#ifdef MP4_VERBOSE
3843
1
        msg_Dbg( p_stream, "skipping unknown 'data' atom with type %"PRIu8, i_type );
3844
1
#endif
3845
1
        MP4_READBOX_EXIT( 0 );
3846
1
    }
3847
3848
132
    MP4_GET3BYTES( p_data->e_wellknowntype );
3849
132
    MP4_GET2BYTES( p_data->locale.i_country );
3850
132
    MP4_GET2BYTES( p_data->locale.i_language );
3851
132
#ifdef MP4_VERBOSE
3852
132
        msg_Dbg( p_stream, "read 'data' atom: knowntype=%"PRIu32", country=%"PRIu16" lang=%"PRIu16
3853
132
                 ", size %"PRIu64" bytes", p_data->e_wellknowntype,
3854
132
                 p_data->locale.i_country, p_data->locale.i_language, i_read );
3855
132
#endif
3856
132
    p_box->data.p_data->p_blob = malloc( i_read );
3857
132
    if ( !p_box->data.p_data->p_blob )
3858
0
        MP4_READBOX_EXIT( 0 );
3859
3860
132
    p_box->data.p_data->i_blob = i_read;
3861
132
    memcpy( p_box->data.p_data->p_blob, p_peek, i_read);
3862
3863
132
    MP4_READBOX_EXIT( 1 );
3864
132
}
3865
3866
static int MP4_ReadBox_Metadata( stream_t *p_stream, MP4_Box_t *p_box )
3867
123
{
3868
123
    const uint8_t *p_peek;
3869
123
    if ( vlc_stream_Peek( p_stream, &p_peek, 16 ) < 16 )
3870
0
        return 0;
3871
123
    if ( vlc_stream_Read( p_stream, NULL, 8 ) != 8 )
3872
0
        return 0;
3873
123
    const uint32_t stoplist[] = { ATOM_data, 0 };
3874
123
    return MP4_ReadBoxContainerChildren( p_stream, p_box, stoplist );
3875
123
}
3876
3877
/* Chapter support */
3878
static void MP4_FreeBox_chpl( MP4_Box_t *p_box )
3879
0
{
3880
0
    MP4_Box_data_chpl_t *p_chpl = p_box->data.p_chpl;
3881
0
    for( unsigned i = 0; i < p_chpl->i_chapter; i++ )
3882
0
        free( p_chpl->chapter[i].psz_name );
3883
0
}
3884
3885
static int MP4_ReadBox_chpl( stream_t *p_stream, MP4_Box_t *p_box )
3886
0
{
3887
0
    MP4_Box_data_chpl_t *p_chpl;
3888
0
    int i;
3889
0
    MP4_READBOX_ENTER( MP4_Box_data_chpl_t, MP4_FreeBox_chpl );
3890
3891
0
    p_chpl = p_box->data.p_chpl;
3892
3893
0
    MP4_GETVERSIONFLAGS( p_chpl );
3894
3895
0
    if ( i_read < 5 || p_chpl->i_version != 0x1 )
3896
0
        MP4_READBOX_EXIT( 0 );
3897
3898
0
    MP4_SKIPBYTES( 4 );
3899
3900
0
    MP4_GET1BYTE( p_chpl->i_chapter );
3901
3902
0
    for( i = 0; i < p_chpl->i_chapter; i++ )
3903
0
    {
3904
0
        uint64_t i_start;
3905
0
        uint8_t i_len;
3906
0
        int i_copy;
3907
0
        if ( i_read < 9 )
3908
0
            break;
3909
0
        MP4_GET8BYTES( i_start );
3910
0
        MP4_GET1BYTE( i_len );
3911
3912
0
        p_chpl->chapter[i].psz_name = malloc( i_len + 1 );
3913
0
        if( !p_chpl->chapter[i].psz_name )
3914
0
            MP4_READBOX_EXIT( 0 );
3915
3916
0
        i_copy = __MIN( i_len, i_read );
3917
0
        if( i_copy > 0 )
3918
0
            memcpy( p_chpl->chapter[i].psz_name, p_peek, i_copy );
3919
0
        p_chpl->chapter[i].psz_name[i_copy] = '\0';
3920
0
        p_chpl->chapter[i].i_start = i_start;
3921
3922
0
        p_peek += i_copy;
3923
0
        i_read -= i_copy;
3924
0
    }
3925
3926
0
    if ( i != p_chpl->i_chapter )
3927
0
        p_chpl->i_chapter = i;
3928
3929
    /* Bubble sort by increasing start date */
3930
0
    do
3931
0
    {
3932
0
        for( i = 0; i < p_chpl->i_chapter - 1; i++ )
3933
0
        {
3934
0
            if( p_chpl->chapter[i].i_start > p_chpl->chapter[i+1].i_start )
3935
0
            {
3936
0
                char *psz = p_chpl->chapter[i+1].psz_name;
3937
0
                int64_t i64 = p_chpl->chapter[i+1].i_start;
3938
3939
0
                p_chpl->chapter[i+1].psz_name = p_chpl->chapter[i].psz_name;
3940
0
                p_chpl->chapter[i+1].i_start = p_chpl->chapter[i].i_start;
3941
3942
0
                p_chpl->chapter[i].psz_name = psz;
3943
0
                p_chpl->chapter[i].i_start = i64;
3944
3945
0
                i = -1;
3946
0
                break;
3947
0
            }
3948
0
        }
3949
0
    } while( i == -1 );
3950
3951
0
#ifdef MP4_VERBOSE
3952
0
    msg_Dbg( p_stream, "read box: \"chpl\" %d chapters",
3953
0
                       p_chpl->i_chapter );
3954
0
#endif
3955
0
    MP4_READBOX_EXIT( 1 );
3956
0
}
3957
3958
/* GoPro HiLight tags support */
3959
static void MP4_FreeBox_HMMT( MP4_Box_t *p_box )
3960
0
{
3961
0
    free( p_box->data.p_hmmt->pi_chapter_start );
3962
0
}
3963
3964
static int MP4_ReadBox_HMMT( stream_t *p_stream, MP4_Box_t *p_box )
3965
0
{
3966
0
#define MAX_CHAPTER_COUNT 100
3967
3968
0
    MP4_Box_data_HMMT_t *p_hmmt;
3969
0
    MP4_READBOX_ENTER( MP4_Box_data_HMMT_t, MP4_FreeBox_HMMT );
3970
3971
0
    if( i_read < 4 )
3972
0
        MP4_READBOX_EXIT( 0 );
3973
3974
0
    p_hmmt = p_box->data.p_hmmt;
3975
3976
0
    MP4_GET4BYTES( p_hmmt->i_chapter_count );
3977
3978
0
    if( p_hmmt->i_chapter_count <= 0 )
3979
0
    {
3980
0
        p_hmmt->pi_chapter_start = NULL;
3981
0
        MP4_READBOX_EXIT( 1 );
3982
0
    }
3983
3984
0
    if( ( i_read / sizeof(uint32_t) ) < p_hmmt->i_chapter_count )
3985
0
        MP4_READBOX_EXIT( 0 );
3986
3987
    /* Cameras are allowing a maximum of 100 tags */
3988
0
    if( p_hmmt->i_chapter_count > MAX_CHAPTER_COUNT )
3989
0
        p_hmmt->i_chapter_count = MAX_CHAPTER_COUNT;
3990
3991
0
    p_hmmt->pi_chapter_start = vlc_alloc( p_hmmt->i_chapter_count, sizeof(uint32_t) );
3992
0
    if( p_hmmt->pi_chapter_start == NULL )
3993
0
        MP4_READBOX_EXIT( 0 );
3994
3995
0
    for( uint32_t i = 0; i < p_hmmt->i_chapter_count; i++ )
3996
0
    {
3997
0
        MP4_GET4BYTES( p_hmmt->pi_chapter_start[i] );
3998
0
    }
3999
4000
0
#ifdef MP4_VERBOSE
4001
0
    msg_Dbg( p_stream, "read box: \"HMMT\" %d HiLight tags", p_hmmt->i_chapter_count );
4002
0
#endif
4003
4004
0
    MP4_READBOX_EXIT( 1 );
4005
0
}
4006
4007
static void MP4_FreeBox_TrackReference( MP4_Box_t *p_box )
4008
188
{
4009
188
    free( p_box->data.p_track_reference->i_track_ID );
4010
188
}
4011
4012
static int MP4_ReadBox_TrackReference( stream_t *p_stream, MP4_Box_t *p_box )
4013
190
{
4014
190
    uint32_t count;
4015
4016
190
    MP4_READBOX_ENTER( MP4_Box_data_trak_reference_t, MP4_FreeBox_TrackReference );
4017
4018
188
    p_box->data.p_track_reference->i_track_ID = NULL;
4019
188
    count = i_read / sizeof(uint32_t);
4020
188
    p_box->data.p_track_reference->i_entry_count = count;
4021
188
    p_box->data.p_track_reference->i_track_ID = vlc_alloc( count,
4022
188
                                                        sizeof(uint32_t) );
4023
188
    if( p_box->data.p_track_reference->i_track_ID == NULL )
4024
0
        MP4_READBOX_EXIT( 0 );
4025
4026
3.92k
    for( unsigned i = 0; i < count; i++ )
4027
3.73k
    {
4028
3.73k
        MP4_GET4BYTES( p_box->data.p_track_reference->i_track_ID[i] );
4029
3.73k
    }
4030
188
#ifdef MP4_VERBOSE
4031
188
        msg_Dbg( p_stream, "read box: \"chap\" %d references",
4032
188
                 p_box->data.p_track_reference->i_entry_count );
4033
188
#endif
4034
4035
188
    MP4_READBOX_EXIT( 1 );
4036
188
}
4037
4038
static int MP4_ReadBox_tref( stream_t *p_stream, MP4_Box_t *p_box )
4039
181
{
4040
    /* skip header */
4041
181
    size_t i_header = mp4_box_headersize( p_box );
4042
181
    if( vlc_stream_Read( p_stream, NULL, i_header ) != (ssize_t) i_header )
4043
0
        return 0;
4044
    /* read each reference atom with forced handler */
4045
181
    uint64_t i_remain = p_box->i_size - 8;
4046
369
    while ( i_remain > 8 )
4047
194
    {
4048
194
        MP4_Box_t *p_childbox = MP4_ReadBoxUsing( p_stream, p_box,
4049
194
                                                  MP4_ReadBox_TrackReference );
4050
194
        if( !p_childbox || i_remain < p_childbox->i_size )
4051
6
        {
4052
6
            MP4_BoxFree( p_childbox );
4053
6
            break;
4054
6
        }
4055
4056
188
        MP4_BoxAddChild( p_box, p_childbox );
4057
188
        i_remain -= p_childbox->i_size;
4058
188
    }
4059
4060
181
    return MP4_Seek( p_stream, p_box->i_pos + p_box->i_size ) ? 0 : 1;
4061
181
}
4062
4063
static void MP4_FreeBox_keys( MP4_Box_t *p_box )
4064
4
{
4065
15
    for( uint32_t i=0; i<p_box->data.p_keys->i_entry_count; i++ )
4066
11
        free( p_box->data.p_keys->p_entries[i].psz_value );
4067
4
    free( p_box->data.p_keys->p_entries );
4068
4
}
4069
4070
static int MP4_ReadBox_keys( stream_t *p_stream, MP4_Box_t *p_box )
4071
4
{
4072
4
    MP4_READBOX_ENTER( MP4_Box_data_keys_t, MP4_FreeBox_keys );
4073
4074
4
    if ( i_read < 8 )
4075
0
        MP4_READBOX_EXIT( 0 );
4076
4077
4
    uint32_t i_count;
4078
4
    MP4_GET4BYTES( i_count ); /* reserved + flags */
4079
4
    if ( i_count != 0 )
4080
0
        MP4_READBOX_EXIT( 0 );
4081
4082
4
    MP4_GET4BYTES( i_count );
4083
4
    p_box->data.p_keys->p_entries = calloc( i_count, sizeof(*p_box->data.p_keys->p_entries) );
4084
4
    if ( !p_box->data.p_keys->p_entries )
4085
0
        MP4_READBOX_EXIT( 0 );
4086
4
    p_box->data.p_keys->i_entry_count = i_count;
4087
4088
4
    uint32_t i=0;
4089
15
    for( ; i < i_count; i++ )
4090
12
    {
4091
12
        if ( i_read < 8 )
4092
0
            break;
4093
12
        uint32_t i_keysize;
4094
12
        MP4_GET4BYTES( i_keysize );
4095
12
        if ( (i_keysize < 8) || (i_keysize - 4 > i_read) )
4096
1
            break;
4097
11
        MP4_GETFOURCC( p_box->data.p_keys->p_entries[i].i_namespace );
4098
11
        i_keysize -= 8;
4099
11
        p_box->data.p_keys->p_entries[i].psz_value = malloc( i_keysize + 1 );
4100
11
        if ( !p_box->data.p_keys->p_entries[i].psz_value )
4101
0
            break;
4102
11
        memcpy( p_box->data.p_keys->p_entries[i].psz_value, p_peek, i_keysize );
4103
11
        p_box->data.p_keys->p_entries[i].psz_value[i_keysize] = 0;
4104
11
        p_peek += i_keysize;
4105
11
        i_read -= i_keysize;
4106
#ifdef MP4_ULTRA_VERBOSE
4107
        msg_Dbg( p_stream, "read box: \"keys\": %u '%s'", i + 1,
4108
                 p_box->data.p_keys->p_entries[i].psz_value );
4109
#endif
4110
11
    }
4111
4
    if ( i < i_count )
4112
1
        p_box->data.p_keys->i_entry_count = i;
4113
4114
4
    MP4_READBOX_EXIT( 1 );
4115
4
}
4116
4117
static int MP4_ReadBox_colr( stream_t *p_stream, MP4_Box_t *p_box )
4118
633
{
4119
633
    MP4_READBOX_ENTER( MP4_Box_data_colr_t, NULL );
4120
632
    MP4_GETFOURCC( p_box->data.p_colr->i_type );
4121
632
    if ( p_box->data.p_colr->i_type == VLC_FOURCC( 'n', 'c', 'l', 'c' ) ||
4122
220
         p_box->data.p_colr->i_type == VLC_FOURCC( 'n', 'c', 'l', 'x' ) )
4123
517
    {
4124
517
        MP4_GET2BYTES( p_box->data.p_colr->nclc.i_primary_idx );
4125
517
        MP4_GET2BYTES( p_box->data.p_colr->nclc.i_transfer_function_idx );
4126
517
        MP4_GET2BYTES( p_box->data.p_colr->nclc.i_matrix_idx );
4127
517
        if ( p_box->data.p_colr->i_type == VLC_FOURCC( 'n', 'c', 'l', 'x' ) )
4128
517
            MP4_GET1BYTE( p_box->data.p_colr->nclc.i_full_range );
4129
517
    }
4130
115
    else
4131
115
    {
4132
115
#ifdef MP4_VERBOSE
4133
115
        msg_Warn( p_stream, "Unhandled colr type: %4.4s", (char*)&p_box->data.p_colr->i_type );
4134
115
#endif
4135
115
    }
4136
632
    MP4_READBOX_EXIT( 1 );
4137
632
}
4138
4139
static int MP4_ReadBox_irot( stream_t *p_stream, MP4_Box_t *p_box )
4140
35
{
4141
35
    MP4_READBOX_ENTER( MP4_Box_data_irot_t, NULL );
4142
35
    MP4_GET1BYTE( p_box->data.p_irot->i_ccw_degrees );
4143
35
    p_box->data.p_irot->i_ccw_degrees &= 0x03;
4144
35
    p_box->data.p_irot->i_ccw_degrees *= 90;
4145
35
    MP4_READBOX_EXIT( 1 );
4146
35
}
4147
4148
static int MP4_ReadBox_dvcC( stream_t *p_stream, MP4_Box_t *p_box )
4149
0
{
4150
0
    MP4_Box_data_dvcC_t *p_dvcC;
4151
0
    uint16_t flags;
4152
0
    MP4_READBOX_ENTER( MP4_Box_data_dvcC_t, NULL );
4153
0
    p_dvcC = p_box->data.p_dvcC;
4154
0
    MP4_GET1BYTE( p_dvcC->i_version_major );
4155
0
    MP4_GET1BYTE( p_dvcC->i_version_minor );
4156
0
    MP4_GET2BYTES( flags );
4157
0
    p_dvcC->i_profile       = (flags >> 9) & 0x7f;  // 7 bits
4158
0
    p_dvcC->i_level         = (flags >> 3) & 0x3f;  // 6 bits
4159
0
    p_dvcC->i_rpu_present   = (flags >> 2) & 0x01;  // 1 bit
4160
0
    p_dvcC->i_el_present    = (flags >> 1) & 0x01;  // 1 bit
4161
0
    p_dvcC->i_bl_present    =  flags       & 0x01;  // 1 bit
4162
    /* TODO: remainder of box, if needed */
4163
0
    MP4_READBOX_EXIT( 1 );
4164
0
}
4165
4166
static int MP4_ReadBox_meta( stream_t *p_stream, MP4_Box_t *p_box )
4167
211
{
4168
211
    const uint8_t *p_peek;
4169
211
    const size_t i_headersize = mp4_box_headersize( p_box );
4170
4171
211
    if( p_box->i_size < 16 || p_box->i_size - i_headersize < 8 )
4172
0
        return 0;
4173
4174
    /* skip over box header */
4175
211
    if( vlc_stream_Read( p_stream, NULL, i_headersize ) != (ssize_t) i_headersize )
4176
0
        return 0;
4177
4178
    /* meta content starts with a 4 byte version/flags value (should be 0) */
4179
211
    if( vlc_stream_Peek( p_stream, &p_peek, 8 ) < 8 )
4180
0
        return 0;
4181
4182
211
    if( !memcmp( p_peek, "\0\0\0", 4 ) ) /* correct header case */
4183
203
    {
4184
203
        if( vlc_stream_Read( p_stream, NULL, 4 ) != 4 )
4185
0
            return 0;
4186
203
    }
4187
8
    else if( memcmp( &p_peek[4], "hdlr", 4 ) ) /* Broken, headerless ones */
4188
4
    {
4189
4
       return 0;
4190
4
    }
4191
4192
    /* load child atoms up to the handler (which should be next anyway) */
4193
207
    const uint32_t stoplist[] = { ATOM_hdlr, 0 };
4194
207
    if ( !MP4_ReadBoxContainerChildren( p_stream, p_box, stoplist ) )
4195
0
        return 0;
4196
4197
    /* Mandatory */
4198
207
    const MP4_Box_t *p_hdlr = MP4_BoxGet( p_box, "hdlr" );
4199
207
    if ( p_hdlr && BOXDATA(p_hdlr) && BOXDATA(p_hdlr)->i_version == 0 )
4200
59
    {
4201
59
        p_box->i_handler = BOXDATA(p_hdlr)->i_handler_type;
4202
59
        switch( p_box->i_handler )
4203
59
        {
4204
0
            case HANDLER_pict:
4205
4
            case HANDLER_mdta:
4206
42
            case HANDLER_mdir:
4207
                /* then it behaves like a container */
4208
42
                return MP4_ReadBoxContainerChildren( p_stream, p_box, NULL );
4209
17
            default:
4210
                /* skip parsing, will be seen as empty container */
4211
17
                break;
4212
59
        }
4213
59
    }
4214
4215
165
    return 1;
4216
207
}
4217
4218
static int MP4_ReadBox_iods( stream_t *p_stream, MP4_Box_t *p_box )
4219
34
{
4220
34
    MP4_READBOX_ENTER( MP4_Box_data_iods_t, NULL );
4221
34
    MP4_GETVERSIONFLAGS( p_box->data.p_iods );
4222
4223
34
    MP4_SKIPBYTES( 1 ); /* tag */
4224
34
    MP4_SKIPBYTES( 1 ); /* length */
4225
4226
34
    MP4_GET2BYTES( p_box->data.p_iods->i_object_descriptor ); /* 10bits, 6 other bits
4227
                                                              are used for other flags */
4228
34
    MP4_GET1BYTE( p_box->data.p_iods->i_OD_profile_level );
4229
34
    MP4_GET1BYTE( p_box->data.p_iods->i_scene_profile_level );
4230
34
    MP4_GET1BYTE( p_box->data.p_iods->i_audio_profile_level );
4231
34
    MP4_GET1BYTE( p_box->data.p_iods->i_visual_profile_level );
4232
34
    MP4_GET1BYTE( p_box->data.p_iods->i_graphics_profile_level );
4233
4234
34
#ifdef MP4_VERBOSE
4235
34
    msg_Dbg( p_stream,
4236
34
             "read box: \"iods\" objectDescriptorId: %i, OD: %i, scene: %i, audio: %i, "
4237
34
             "visual: %i, graphics: %i",
4238
34
             p_box->data.p_iods->i_object_descriptor >> 6,
4239
34
             p_box->data.p_iods->i_OD_profile_level,
4240
34
             p_box->data.p_iods->i_scene_profile_level,
4241
34
             p_box->data.p_iods->i_audio_profile_level,
4242
34
             p_box->data.p_iods->i_visual_profile_level,
4243
34
             p_box->data.p_iods->i_graphics_profile_level );
4244
34
#endif
4245
4246
34
    MP4_READBOX_EXIT( 1 );
4247
34
}
4248
4249
static int MP4_ReadBox_btrt( stream_t *p_stream, MP4_Box_t *p_box )
4250
1
{
4251
1
    MP4_READBOX_ENTER( MP4_Box_data_btrt_t, NULL );
4252
4253
1
    if(i_read != 12)
4254
0
        MP4_READBOX_EXIT( 0 );
4255
4256
1
    MP4_GET4BYTES( p_box->data.p_btrt->i_buffer_size );
4257
1
    MP4_GET4BYTES( p_box->data.p_btrt->i_max_bitrate );
4258
1
    MP4_GET4BYTES( p_box->data.p_btrt->i_avg_bitrate );
4259
4260
1
    MP4_READBOX_EXIT( 1 );
4261
1
}
4262
4263
static int MP4_ReadBox_pasp( stream_t *p_stream, MP4_Box_t *p_box )
4264
87
{
4265
87
    MP4_READBOX_ENTER( MP4_Box_data_pasp_t, NULL );
4266
4267
87
    MP4_GET4BYTES( p_box->data.p_pasp->i_horizontal_spacing );
4268
87
    MP4_GET4BYTES( p_box->data.p_pasp->i_vertical_spacing );
4269
4270
87
#ifdef MP4_VERBOSE
4271
87
    msg_Dbg( p_stream,
4272
87
             "read box: \"paps\" %dx%d",
4273
87
             p_box->data.p_pasp->i_horizontal_spacing,
4274
87
             p_box->data.p_pasp->i_vertical_spacing);
4275
87
#endif
4276
4277
87
    MP4_READBOX_EXIT( 1 );
4278
87
}
4279
4280
static int MP4_ReadBox_clap( stream_t *p_stream, MP4_Box_t *p_box )
4281
65
{
4282
65
    MP4_READBOX_ENTER( MP4_Box_data_clap_t, NULL );
4283
4284
65
    if ( i_read != 32 )
4285
48
        MP4_READBOX_EXIT( 0 );
4286
4287
17
    MP4_Box_data_clap_t *p_clap = p_box->data.p_clap;
4288
17
    uint32_t num, den;
4289
4290
17
    MP4_GET4BYTES( num ); MP4_GET4BYTES( den );
4291
17
    p_clap->i_width = num / (den ? den : 1);
4292
17
    MP4_GET4BYTES( num ); MP4_GET4BYTES( den );
4293
17
    p_clap->i_height = num / (den ? den : 1);
4294
17
    MP4_GET4BYTES( num ); MP4_GET4BYTES( den );
4295
17
    p_clap->i_x_offset = num / (den ? den : 1);
4296
17
    MP4_GET4BYTES( num ); MP4_GET4BYTES( den );
4297
17
    p_clap->i_y_offset = num / (den ? den : 1);
4298
4299
17
    if( UINT32_MAX - p_clap->i_width < p_clap->i_x_offset ||
4300
17
        UINT32_MAX - p_clap->i_height < p_clap->i_y_offset )
4301
0
        MP4_READBOX_EXIT( 0 );
4302
4303
17
#ifdef MP4_VERBOSE
4304
17
    msg_Dbg( p_stream,
4305
17
             "read box: \"clap\" %"PRIu32"x%"PRIu32"+%"PRIu32"+%"PRIu32,
4306
17
             p_box->data.p_clap->i_width, p_box->data.p_clap->i_height,
4307
17
             p_box->data.p_clap->i_x_offset, p_box->data.p_clap->i_y_offset );
4308
17
#endif
4309
4310
17
    MP4_READBOX_EXIT( 1 );
4311
17
}
4312
4313
static int MP4_ReadBox_mehd( stream_t *p_stream, MP4_Box_t *p_box )
4314
60
{
4315
60
    MP4_READBOX_ENTER( MP4_Box_data_mehd_t, NULL );
4316
4317
60
    MP4_GETVERSIONFLAGS( p_box->data.p_mehd );
4318
60
    if( p_box->data.p_mehd->i_version == 1 )
4319
60
        MP4_GET8BYTES( p_box->data.p_mehd->i_fragment_duration );
4320
25
    else /* version == 0 */
4321
60
        MP4_GET4BYTES( p_box->data.p_mehd->i_fragment_duration );
4322
4323
60
#ifdef MP4_VERBOSE
4324
60
    msg_Dbg( p_stream,
4325
60
             "read box: \"mehd\" frag dur. %"PRIu64"",
4326
60
             p_box->data.p_mehd->i_fragment_duration );
4327
60
#endif
4328
4329
60
    MP4_READBOX_EXIT( 1 );
4330
60
}
4331
4332
static int MP4_ReadBox_trex( stream_t *p_stream, MP4_Box_t *p_box )
4333
171
{
4334
171
    MP4_READBOX_ENTER( MP4_Box_data_trex_t, NULL );
4335
171
    MP4_GETVERSIONFLAGS( p_box->data.p_trex );
4336
4337
171
    MP4_GET4BYTES( p_box->data.p_trex->i_track_ID );
4338
171
    MP4_GET4BYTES( p_box->data.p_trex->i_default_sample_description_index );
4339
171
    MP4_GET4BYTES( p_box->data.p_trex->i_default_sample_duration );
4340
171
    MP4_GET4BYTES( p_box->data.p_trex->i_default_sample_size );
4341
171
    MP4_GET4BYTES( p_box->data.p_trex->i_default_sample_flags );
4342
4343
171
#ifdef MP4_VERBOSE
4344
171
    msg_Dbg( p_stream,
4345
171
             "read box: \"trex\" trackID: %"PRIu32"",
4346
171
             p_box->data.p_trex->i_track_ID );
4347
171
#endif
4348
4349
171
    MP4_READBOX_EXIT( 1 );
4350
171
}
4351
4352
static void MP4_FreeBox_sdtp( MP4_Box_t *p_box )
4353
606
{
4354
606
    free( p_box->data.p_sdtp->p_sample_table );
4355
606
}
4356
4357
static int MP4_ReadBox_sdtp( stream_t *p_stream, MP4_Box_t *p_box )
4358
606
{
4359
606
    uint32_t i_sample_count;
4360
606
    MP4_READBOX_ENTER( MP4_Box_data_sdtp_t, MP4_FreeBox_sdtp );
4361
606
    MP4_Box_data_sdtp_t *p_sdtp = p_box->data.p_sdtp;
4362
606
    MP4_GETVERSIONFLAGS( p_box->data.p_sdtp );
4363
606
    i_sample_count = i_read;
4364
4365
606
    p_sdtp->p_sample_table = malloc( i_sample_count );
4366
606
    if( unlikely(p_sdtp->p_sample_table == NULL) )
4367
0
        MP4_READBOX_EXIT( 0 );
4368
4369
321k
    for( uint32_t i = 0; i < i_sample_count; i++ )
4370
321k
        MP4_GET1BYTE( p_sdtp->p_sample_table[i] );
4371
4372
606
#ifdef MP4_VERBOSE
4373
606
    msg_Dbg( p_stream, "i_sample_count is %"PRIu32"", i_sample_count );
4374
606
    if ( i_sample_count > 3 )
4375
606
        msg_Dbg( p_stream,
4376
606
             "read box: \"sdtp\" head: %"PRIx8" %"PRIx8" %"PRIx8" %"PRIx8"",
4377
606
                 p_sdtp->p_sample_table[0],
4378
606
                 p_sdtp->p_sample_table[1],
4379
606
                 p_sdtp->p_sample_table[2],
4380
606
                 p_sdtp->p_sample_table[3] );
4381
606
#endif
4382
4383
606
    MP4_READBOX_EXIT( 1 );
4384
606
}
4385
4386
static int MP4_ReadBox_tsel( stream_t *p_stream, MP4_Box_t *p_box )
4387
0
{
4388
0
    MP4_READBOX_ENTER( MP4_Box_data_tsel_t, NULL );
4389
0
    uint32_t i_version;
4390
0
    MP4_GET4BYTES( i_version );
4391
0
    if ( i_version != 0 || i_read < 4 )
4392
0
        MP4_READBOX_EXIT( 0 );
4393
0
    MP4_GET4BYTES( p_box->data.p_tsel->i_switch_group );
4394
    /* ignore list of attributes as es are present before switch */
4395
0
    MP4_READBOX_EXIT( 1 );
4396
0
}
4397
4398
static int MP4_ReadBox_mfro( stream_t *p_stream, MP4_Box_t *p_box )
4399
4
{
4400
4
    MP4_READBOX_ENTER( MP4_Box_data_mfro_t, NULL );
4401
4402
3
    MP4_GETVERSIONFLAGS( p_box->data.p_mfro );
4403
3
    MP4_GET4BYTES( p_box->data.p_mfro->i_size );
4404
4405
3
#ifdef MP4_VERBOSE
4406
3
    msg_Dbg( p_stream,
4407
3
             "read box: \"mfro\" size: %"PRIu32"",
4408
3
             p_box->data.p_mfro->i_size);
4409
3
#endif
4410
4411
3
    MP4_READBOX_EXIT( 1 );
4412
3
}
4413
4414
static void MP4_FreeBox_tfra( MP4_Box_t *p_box )
4415
8
{
4416
8
    free( p_box->data.p_tfra->p_time );
4417
8
    free( p_box->data.p_tfra->p_moof_offset );
4418
8
    free( p_box->data.p_tfra->p_traf_number );
4419
8
    free( p_box->data.p_tfra->p_trun_number );
4420
8
    free( p_box->data.p_tfra->p_sample_number );
4421
8
}
4422
4423
static int MP4_ReadBox_tfra( stream_t *p_stream, MP4_Box_t *p_box )
4424
8
{
4425
60
#define READ_VARIABLE_LENGTH(lengthvar, p_array) switch (lengthvar)\
4426
0
{\
4427
60
    case 0:\
4428
60
        MP4_GET1BYTE( p_array[i] );\
4429
60
        break;\
4430
0
    case 1:\
4431
0
        MP4_GET2BYTES( *((uint16_t *)&p_array[i*2]) );\
4432
0
        break;\
4433
0
    case 2:\
4434
0
        MP4_GET3BYTES( *((uint32_t *)&p_array[i*4]) );\
4435
0
        break;\
4436
0
    case 3:\
4437
0
        MP4_GET4BYTES( *((uint32_t *)&p_array[i*4]) );\
4438
0
        break;\
4439
0
    default:\
4440
0
        goto error;\
4441
60
}
4442
24
#define FIX_VARIABLE_LENGTH(lengthvar) if ( lengthvar == 3 ) lengthvar = 4
4443
4444
8
    uint32_t i_number_of_entries;
4445
8
    MP4_READBOX_ENTER( MP4_Box_data_tfra_t, MP4_FreeBox_tfra );
4446
8
    MP4_Box_data_tfra_t *p_tfra = p_box->data.p_tfra;
4447
8
    MP4_GETVERSIONFLAGS( p_box->data.p_tfra );
4448
8
    if ( p_tfra->i_version > 1 )
4449
0
        MP4_READBOX_EXIT( 0 );
4450
8
    MP4_GET4BYTES( p_tfra->i_track_ID );
4451
8
    uint32_t i_lengths = 0;
4452
8
    MP4_GET4BYTES( i_lengths );
4453
8
    MP4_GET4BYTES( p_tfra->i_number_of_entries );
4454
8
    i_number_of_entries = p_tfra->i_number_of_entries;
4455
8
    p_tfra->i_length_size_of_traf_num = i_lengths >> 4;
4456
8
    p_tfra->i_length_size_of_trun_num = ( i_lengths & 0x0c ) >> 2;
4457
8
    p_tfra->i_length_size_of_sample_num = i_lengths & 0x03;
4458
4459
8
    size_t size;
4460
8
    p_tfra->p_time = calloc( i_number_of_entries, sizeof(*p_tfra->p_time) );
4461
8
    p_tfra->p_moof_offset = calloc( i_number_of_entries, sizeof(*p_tfra->p_moof_offset) );
4462
4463
8
    size = 1 + p_tfra->i_length_size_of_traf_num; /* size in [|1, 4|] */
4464
8
    if ( size == 3 ) size++;
4465
8
    p_tfra->p_traf_number = calloc( i_number_of_entries, size );
4466
8
    size = 1 + p_tfra->i_length_size_of_trun_num;
4467
8
    if ( size == 3 ) size++;
4468
8
    p_tfra->p_trun_number = calloc( i_number_of_entries, size );
4469
8
    size = 1 + p_tfra->i_length_size_of_sample_num;
4470
8
    if ( size == 3 ) size++;
4471
8
    p_tfra->p_sample_number = calloc( i_number_of_entries, size );
4472
4473
8
    if( !p_tfra->p_time || !p_tfra->p_moof_offset || !p_tfra->p_traf_number
4474
8
                        || !p_tfra->p_trun_number || !p_tfra->p_sample_number )
4475
0
        goto error;
4476
4477
8
    unsigned i_fields_length = 3 + p_tfra->i_length_size_of_traf_num
4478
8
            + p_tfra->i_length_size_of_trun_num
4479
8
            + p_tfra->i_length_size_of_sample_num;
4480
4481
8
    uint32_t i;
4482
28
    for( i = 0; i < i_number_of_entries; i++ )
4483
20
    {
4484
4485
20
        if( p_tfra->i_version == 1 )
4486
20
        {
4487
20
            if ( i_read < i_fields_length + 16 )
4488
0
                break;
4489
20
            MP4_GET8BYTES( p_tfra->p_time[i] );
4490
20
            MP4_GET8BYTES( p_tfra->p_moof_offset[i] );
4491
20
        }
4492
0
        else
4493
0
        {
4494
0
            if ( i_read < i_fields_length + 8 )
4495
0
                break;
4496
0
            MP4_GET4BYTES( p_tfra->p_time[i] );
4497
0
            MP4_GET4BYTES( p_tfra->p_moof_offset[i] );
4498
0
        }
4499
4500
20
        READ_VARIABLE_LENGTH(p_tfra->i_length_size_of_traf_num, p_tfra->p_traf_number);
4501
20
        READ_VARIABLE_LENGTH(p_tfra->i_length_size_of_trun_num, p_tfra->p_trun_number);
4502
20
        READ_VARIABLE_LENGTH(p_tfra->i_length_size_of_sample_num, p_tfra->p_sample_number);
4503
20
    }
4504
8
    if ( i < i_number_of_entries )
4505
0
        i_number_of_entries = i;
4506
4507
8
    FIX_VARIABLE_LENGTH(p_tfra->i_length_size_of_traf_num);
4508
8
    FIX_VARIABLE_LENGTH(p_tfra->i_length_size_of_trun_num);
4509
8
    FIX_VARIABLE_LENGTH(p_tfra->i_length_size_of_sample_num);
4510
4511
#ifdef MP4_ULTRA_VERBOSE
4512
    for( i = 0; i < i_number_of_entries; i++ )
4513
    {
4514
        msg_Dbg( p_stream, "tfra[%"PRIu32"] time[%"PRIu32"]: %"PRIu64", "
4515
                            "moof_offset[%"PRIu32"]: %"PRIu64"",
4516
                    p_tfra->i_track_ID,
4517
                    i, p_tfra->p_time[i],
4518
                    i, p_tfra->p_moof_offset[i] );
4519
    }
4520
#endif
4521
8
#ifdef MP4_VERBOSE
4522
8
    msg_Dbg( p_stream, "tfra[%"PRIu32"] %"PRIu32" entries",
4523
8
             p_tfra->i_track_ID, i_number_of_entries );
4524
8
#endif
4525
4526
8
    MP4_READBOX_EXIT( 1 );
4527
0
error:
4528
0
    MP4_READBOX_EXIT( 0 );
4529
4530
0
#undef READ_VARIABLE_LENGTH
4531
0
#undef FIX_VARIABLE_LENGTH
4532
0
}
4533
4534
static int MP4_ReadBox_pnot( stream_t *p_stream, MP4_Box_t *p_box )
4535
0
{
4536
0
    if ( p_box->i_size != 20 )
4537
0
        return 0;
4538
0
    MP4_READBOX_ENTER( MP4_Box_data_pnot_t, NULL );
4539
0
    MP4_GET4BYTES( p_box->data.p_pnot->i_date );
4540
0
    uint16_t i_version;
4541
0
    MP4_GET2BYTES( i_version );
4542
0
    if ( i_version != 0 )
4543
0
        MP4_READBOX_EXIT( 0 );
4544
0
    MP4_GETFOURCC( p_box->data.p_pnot->i_type );
4545
0
    MP4_GET2BYTES( p_box->data.p_pnot->i_index );
4546
0
    MP4_READBOX_EXIT( 1 );
4547
0
}
4548
4549
static int MP4_ReadBox_SA3D( stream_t *p_stream, MP4_Box_t *p_box )
4550
0
{
4551
0
    MP4_READBOX_ENTER( MP4_Box_data_SA3D_t, NULL );
4552
4553
0
    uint8_t i_version;
4554
0
    MP4_GET1BYTE( i_version );
4555
0
    if ( i_version != 0 )
4556
0
        MP4_READBOX_EXIT( 0 );
4557
4558
0
    MP4_GET1BYTE( p_box->data.p_SA3D->i_ambisonic_type );
4559
0
    MP4_GET4BYTES( p_box->data.p_SA3D->i_ambisonic_order );
4560
0
    MP4_GET1BYTE( p_box->data.p_SA3D->i_ambisonic_channel_ordering );
4561
0
    MP4_GET1BYTE( p_box->data.p_SA3D->i_ambisonic_normalization );
4562
0
    MP4_GET4BYTES( p_box->data.p_SA3D->i_num_channels );
4563
0
    MP4_READBOX_EXIT( 1 );
4564
0
}
4565
4566
static void MP4_FreeBox_Reference( MP4_Box_t *p_box )
4567
0
{
4568
0
    MP4_Box_data_refbox_t *p_data = p_box->data.p_refbox;
4569
0
    free( p_data->p_references );
4570
0
}
4571
4572
static int MP4_ReadBox_Reference( stream_t *p_stream, MP4_Box_t *p_box )
4573
0
{
4574
0
    MP4_READBOX_ENTER( MP4_Box_data_refbox_t, MP4_FreeBox_Reference );
4575
0
    MP4_Box_data_refbox_t *p_data = p_box->data.p_refbox;
4576
4577
0
    if( p_box->p_father->data.p_iref->i_flags == 0 )
4578
0
        MP4_GET2BYTES( p_data->i_from_item_id );
4579
0
    else
4580
0
        MP4_GET4BYTES( p_data->i_from_item_id );
4581
0
    MP4_GET2BYTES( p_data->i_reference_count );
4582
0
    if( i_read / ((p_box->p_father->data.p_iref->i_flags == 0 ) ? 2 : 4) <
4583
0
            p_data->i_reference_count )
4584
0
        MP4_READBOX_EXIT( 0 );
4585
4586
0
    p_data->p_references = vlc_alloc( p_data->i_reference_count, sizeof(*p_data->p_references) );
4587
0
    if( !p_data->p_references )
4588
0
        MP4_READBOX_EXIT( 0 );
4589
0
    for( uint16_t i=0; i<p_data->i_reference_count; i++ )
4590
0
    {
4591
0
        if( p_box->p_father->data.p_iref->i_flags == 0 )
4592
0
            MP4_GET2BYTES( p_data->p_references[i].i_to_item_id );
4593
0
        else
4594
0
            MP4_GET4BYTES( p_data->p_references[i].i_to_item_id );
4595
0
    }
4596
4597
0
    MP4_READBOX_EXIT( 1 );
4598
0
}
4599
4600
static int MP4_ReadBox_iref( stream_t *p_stream, MP4_Box_t *p_box )
4601
0
{
4602
0
    MP4_READBOX_ENTER_PARTIAL( MP4_Box_data_iref_t, 12, NULL );
4603
0
    MP4_Box_data_iref_t *p_data = p_box->data.p_iref;
4604
0
    if( i_read < 4 )
4605
0
        MP4_READBOX_EXIT( 0 );
4606
4607
0
    MP4_GET1BYTE( p_data->i_version );
4608
0
    MP4_GET3BYTES( p_data->i_flags );
4609
0
    if( p_data->i_version > 0 )
4610
0
        MP4_READBOX_EXIT( 0 );
4611
4612
0
    assert( i_read == 0 );
4613
4614
0
    uint64_t i_remain = p_box->i_size - 12;
4615
0
    while ( i_remain > 8 )
4616
0
    {
4617
0
        MP4_Box_t *p_childbox = MP4_ReadBoxUsing( p_stream, p_box,
4618
0
                                                  MP4_ReadBox_Reference );
4619
0
        if( !p_childbox || i_remain < p_childbox->i_size )
4620
0
        {
4621
0
            MP4_BoxFree( p_childbox );
4622
0
            break;
4623
0
        }
4624
4625
0
        MP4_BoxAddChild( p_box, p_childbox );
4626
0
        i_remain -= p_childbox->i_size;
4627
0
    }
4628
4629
0
    if ( MP4_Seek( p_stream, p_box->i_pos + p_box->i_size ) )
4630
0
        MP4_READBOX_EXIT( 0 );
4631
4632
0
    MP4_READBOX_EXIT( 1 );
4633
0
}
4634
4635
static void MP4_FreeBox_iloc( MP4_Box_t *p_box )
4636
31
{
4637
31
    MP4_Box_data_iloc_t *p_data = p_box->data.p_iloc;
4638
31
    if( p_data->p_items )
4639
31
    {
4640
62
        for( uint32_t i=0; i<p_data->i_item_count; i++ )
4641
31
            free( p_data->p_items[i].p_extents );
4642
31
        free( p_data->p_items );
4643
31
    }
4644
31
}
4645
4646
static int MP4_ReadBox_iloc( stream_t *p_stream, MP4_Box_t *p_box )
4647
31
{
4648
31
    MP4_READBOX_ENTER( MP4_Box_data_iloc_t, MP4_FreeBox_iloc );
4649
31
    MP4_Box_data_iloc_t *p_data = p_box->data.p_iloc;
4650
4651
31
    uint16_t i_foo;
4652
4653
31
    uint8_t i_version;
4654
31
    MP4_GET1BYTE( i_version );
4655
31
    MP4_SKIPBYTES( 3 ); // flags
4656
4657
31
    MP4_GET1BYTE( p_data->i_offset_size );
4658
31
    p_data->i_length_size = p_data->i_offset_size & 0x0F;
4659
31
    p_data->i_offset_size >>= 4;
4660
31
    MP4_GET1BYTE( p_data->i_base_offset_size );
4661
31
    if( i_version == 0 )
4662
31
        p_data->i_index_size = 0;
4663
0
    else
4664
0
        p_data->i_index_size = p_data->i_base_offset_size & 0x0F;
4665
31
    p_data->i_base_offset_size >>= 4;
4666
4667
    /* Only accept 0,4,8 */
4668
31
    if( (p_data->i_offset_size & 0xF3) || p_data->i_offset_size > 8 ||
4669
31
        (p_data->i_length_size & 0xF3) || p_data->i_length_size > 8 ||
4670
31
        (p_data->i_base_offset_size & 0xF3) || p_data->i_base_offset_size > 8 ||
4671
31
        (p_data->i_index_size & 0xF3) || p_data->i_index_size > 8 )
4672
0
        MP4_READBOX_EXIT( 0 );
4673
4674
31
    if( i_version < 2 )
4675
31
        MP4_GET2BYTES( p_data->i_item_count );
4676
0
    else if( i_version == 2 )
4677
0
        MP4_GET4BYTES( p_data->i_item_count );
4678
0
    else
4679
0
        MP4_READBOX_EXIT( 0 );
4680
4681
31
    if( i_read / 6 < p_data->i_item_count )
4682
0
        MP4_READBOX_EXIT( 0 );
4683
4684
31
    p_data->p_items = vlc_alloc( p_data->i_item_count, sizeof(p_data->p_items[0]) );
4685
31
    if( !p_data->p_items )
4686
0
        MP4_READBOX_EXIT( 0 );
4687
4688
62
    for( uint32_t i=0; i<p_data->i_item_count; i++ )
4689
31
    {
4690
31
        if( i_version < 2 )
4691
31
            MP4_GET2BYTES( p_data->p_items[i].i_item_id );
4692
0
        else
4693
31
            MP4_GET4BYTES( p_data->p_items[i].i_item_id );
4694
4695
31
        if( i_version > 0 )
4696
0
        {
4697
0
            MP4_GET2BYTES( i_foo );
4698
0
            p_data->p_items[i].i_construction_method = i_foo & 0x0F;
4699
0
        }
4700
31
        else p_data->p_items[i].i_construction_method = 0;
4701
4702
31
        MP4_GET2BYTES( p_data->p_items[i].i_data_reference_index );
4703
4704
31
        switch( p_data->i_base_offset_size )
4705
31
        {
4706
31
            case 4: MP4_GET4BYTES( p_data->p_items[i].i_base_offset ); break;
4707
0
            case 8: MP4_GET8BYTES( p_data->p_items[i].i_base_offset ); break;
4708
0
            default: p_data->p_items[i].i_base_offset = 0; break;
4709
31
        }
4710
4711
31
        MP4_GET2BYTES( p_data->p_items[i].i_extent_count );
4712
31
        if( p_data->p_items[i].i_extent_count == 0 ) // can not happen
4713
0
        {
4714
0
            p_data->i_item_count = i;
4715
0
            MP4_READBOX_EXIT( 0 );
4716
0
        }
4717
4718
31
        uint64_t i_entrysize = (( i_version > 0 ) ? p_data->i_index_size : 0) +
4719
31
                               p_data->i_offset_size + p_data->i_length_size;
4720
31
        if( i_entrysize > 0 &&
4721
31
            i_read / i_entrysize < p_data->p_items[i].i_extent_count )
4722
0
        {
4723
0
            p_data->i_item_count = i;
4724
0
            MP4_READBOX_EXIT( 0 );
4725
0
        }
4726
4727
31
        p_data->p_items[i].p_extents = vlc_alloc( p_data->p_items[i].i_extent_count,
4728
31
                                               sizeof(p_data->p_items[i].p_extents[0]) );
4729
31
        if(!p_data->p_items[i].p_extents)
4730
0
        {
4731
0
            p_data->i_item_count = i;
4732
0
            MP4_READBOX_EXIT( 0 );
4733
0
        }
4734
62
        for( uint16_t j=0; j<p_data->p_items[i].i_extent_count; j++ )
4735
31
        {
4736
31
            if( i_version > 0 )
4737
0
            {
4738
0
                switch( p_data->i_index_size )
4739
0
                {
4740
0
                    case 4: MP4_GET4BYTES( p_data->p_items[i].p_extents[j].i_extent_index ); break;
4741
0
                    case 8: MP4_GET8BYTES( p_data->p_items[i].p_extents[j].i_extent_index ); break;
4742
0
                    default: p_data->p_items[i].p_extents[j].i_extent_index = 0 ; break;
4743
0
                }
4744
0
            }
4745
31
            switch( p_data->i_offset_size )
4746
31
            {
4747
31
                case 4: MP4_GET4BYTES( p_data->p_items[i].p_extents[j].i_extent_offset ); break;
4748
0
                case 8: MP4_GET8BYTES( p_data->p_items[i].p_extents[j].i_extent_offset ); break;
4749
0
                default: p_data->p_items[i].p_extents[j].i_extent_offset = 0; break;
4750
31
            }
4751
31
            switch( p_data->i_length_size )
4752
31
            {
4753
31
                case 4: MP4_GET4BYTES( p_data->p_items[i].p_extents[j].i_extent_length ); break;
4754
0
                case 8: MP4_GET8BYTES( p_data->p_items[i].p_extents[j].i_extent_length ); break;
4755
0
                default: p_data->p_items[i].p_extents[j].i_extent_length = 0; break;
4756
31
            }
4757
31
        }
4758
31
    }
4759
4760
31
    MP4_READBOX_EXIT( 1 );
4761
31
}
4762
4763
static int MP4_ReadBox_iinf( stream_t *p_stream, MP4_Box_t *p_box )
4764
30
{
4765
30
    const uint8_t *p_versionpeek;
4766
30
    if( vlc_stream_Peek( p_stream, &p_versionpeek, 9 ) < 9 )
4767
0
        return 0;
4768
4769
30
    size_t i_header = 12 + (( p_versionpeek[8] == 0 ) ? 2 : 4);
4770
30
    MP4_READBOX_ENTER_PARTIAL( MP4_Box_data_iinf_t, i_header, NULL );
4771
30
    if( i_read + 8 < i_header )
4772
0
        MP4_READBOX_EXIT( 0 );
4773
4774
30
    uint8_t i_version;
4775
30
    MP4_GET1BYTE( i_version );
4776
30
    MP4_SKIPBYTES( 3 ); // flags
4777
30
    if( i_version > 2 )
4778
0
        MP4_READBOX_EXIT( 0 );
4779
4780
30
    if( i_version == 0 )
4781
30
        MP4_GET2BYTES( p_box->data.p_iinf->i_entry_count );
4782
0
    else
4783
30
        MP4_GET4BYTES( p_box->data.p_iinf->i_entry_count );
4784
4785
30
    assert( i_read == 0 );
4786
4787
30
    uint32_t i = 0;
4788
30
    uint64_t i_remain = p_box->i_size - i_header;
4789
53
    while ( i_remain > 8 && i < p_box->data.p_iinf->i_entry_count )
4790
30
    {
4791
30
        MP4_Box_t *p_childbox = MP4_ReadBox( p_stream, p_box );
4792
30
        if( !p_childbox || i_remain < p_childbox->i_size )
4793
7
        {
4794
7
            MP4_BoxFree( p_childbox );
4795
7
            p_box->data.p_iinf->i_entry_count = i;
4796
7
            break;
4797
7
        }
4798
4799
23
        MP4_BoxAddChild( p_box, p_childbox );
4800
23
        i_remain -= p_childbox->i_size;
4801
23
        i++;
4802
23
    }
4803
4804
30
    if ( MP4_Seek( p_stream, p_box->i_pos + p_box->i_size ) )
4805
0
        MP4_READBOX_EXIT( 0 );
4806
4807
30
    MP4_READBOX_EXIT( 1 );
4808
30
}
4809
4810
static void MP4_FreeBox_infe( MP4_Box_t *p_box )
4811
23
{
4812
23
    MP4_Box_data_infe_t *p_data = p_box->data.p_infe;
4813
23
    free( p_data->psz_content_encoding );
4814
23
    free( p_data->psz_content_type );
4815
23
    free( p_data->psz_item_name );
4816
23
    free( p_data->psz_item_uri_type );
4817
23
}
4818
4819
static int MP4_ReadBox_infe( stream_t *p_stream, MP4_Box_t *p_box )
4820
23
{
4821
23
    MP4_READBOX_ENTER( MP4_Box_data_infe_t, MP4_FreeBox_infe );
4822
23
    MP4_Box_data_infe_t *p_data = p_box->data.p_infe;
4823
4824
23
    uint8_t i_version;
4825
23
    MP4_GET1BYTE( i_version );
4826
23
    MP4_GET3BYTES( p_data->i_flags );
4827
23
    if( i_version > 3 )
4828
0
        MP4_READBOX_EXIT( 0 );
4829
4830
23
    if( i_version < 2 )
4831
1
    {
4832
1
        MP4_GET2BYTES( p_data->i_item_id );
4833
1
        MP4_GET2BYTES( p_data->i_item_protection_index );
4834
1
        p_data->psz_item_name = mp4_getstringz( &p_peek, &i_read );
4835
1
        if( i_read > 0 )
4836
1
        {
4837
1
            p_data->psz_content_type = mp4_getstringz( &p_peek, &i_read );
4838
1
            if( i_read > 0 )
4839
1
                p_data->psz_content_encoding = mp4_getstringz( &p_peek, &i_read );
4840
1
        }
4841
4842
        //if( i_version == 1 )
4843
1
        {
4844
            /* extensions, we do not care */
4845
1
        }
4846
1
    }
4847
22
    else
4848
22
    {
4849
22
        if( i_version == 2 )
4850
22
            MP4_GET2BYTES( p_data->i_item_id );
4851
0
        else
4852
22
            MP4_GET4BYTES( p_data->i_item_id );
4853
22
        MP4_GET2BYTES( p_data->i_item_protection_index );
4854
22
        MP4_GETFOURCC( p_data->item_type );
4855
22
        p_data->psz_item_name = mp4_getstringz( &p_peek, &i_read );
4856
22
        if( p_data->item_type == VLC_FOURCC('m','i','m','e') )
4857
0
        {
4858
0
            p_data->psz_content_type = mp4_getstringz( &p_peek, &i_read );
4859
0
            if( i_read > 0 )
4860
0
                p_data->psz_content_encoding = mp4_getstringz( &p_peek, &i_read );
4861
0
        }
4862
22
        else if( p_data->item_type == VLC_FOURCC('u','r','i',' ') )
4863
0
        {
4864
0
            p_data->psz_item_uri_type = mp4_getstringz( &p_peek, &i_read );
4865
0
        }
4866
22
    }
4867
4868
23
    MP4_READBOX_EXIT( 1 );
4869
23
}
4870
4871
static int MP4_ReadBox_pitm( stream_t *p_stream, MP4_Box_t *p_box )
4872
32
{
4873
32
    MP4_READBOX_ENTER( MP4_Box_data_pitm_t, NULL );
4874
32
    MP4_Box_data_pitm_t *p_data = p_box->data.p_pitm;
4875
4876
32
    uint8_t i_version;
4877
32
    MP4_GET1BYTE( i_version );
4878
32
    MP4_SKIPBYTES( 3 ); // flags
4879
4880
32
    if( i_version == 0 )
4881
32
        MP4_GET2BYTES( p_data->i_item_id );
4882
0
    else
4883
32
        MP4_GET4BYTES( p_data->i_item_id );
4884
4885
32
    MP4_READBOX_EXIT( 1 );
4886
32
}
4887
4888
static int MP4_ReadBox_ispe( stream_t *p_stream, MP4_Box_t *p_box )
4889
12
{
4890
12
    MP4_READBOX_ENTER( MP4_Box_data_ispe_t, NULL );
4891
12
    MP4_Box_data_ispe_t *p_data = p_box->data.p_ispe;
4892
4893
12
    uint8_t i_version;
4894
12
    MP4_GET1BYTE( i_version );
4895
12
    MP4_SKIPBYTES( 3 ); // flags
4896
12
    if( i_version > 0 )
4897
0
        MP4_READBOX_EXIT( 0 );
4898
4899
12
    MP4_GET4BYTES( p_data->i_width );
4900
12
    MP4_GET4BYTES( p_data->i_height );
4901
4902
12
    MP4_READBOX_EXIT( 1 );
4903
12
}
4904
4905
static void MP4_FreeBox_ipma( MP4_Box_t *p_box )
4906
29
{
4907
29
    MP4_Box_data_ipma_t *p_data = p_box->data.p_ipma;
4908
58
    for( uint32_t i=0; i<p_data->i_entry_count; i++ )
4909
29
        free( p_data->p_entries[i].p_assocs );
4910
29
    free( p_data->p_entries );
4911
29
}
4912
4913
static int MP4_ReadBox_ipma( stream_t *p_stream, MP4_Box_t *p_box )
4914
29
{
4915
29
    MP4_READBOX_ENTER( MP4_Box_data_ipma_t, MP4_FreeBox_ipma );
4916
29
    MP4_Box_data_ipma_t *p_data = p_box->data.p_ipma;
4917
4918
29
    uint8_t i_version;
4919
29
    uint32_t i_flags;
4920
29
    MP4_GET1BYTE( i_version );
4921
29
    MP4_GET3BYTES( i_flags );
4922
4923
29
    MP4_GET4BYTES( p_data->i_entry_count );
4924
29
    if( (i_read / ((i_version < 1) ? 3 : 5) <  p_data->i_entry_count) )
4925
0
    {
4926
0
        p_data->i_entry_count = 0;
4927
0
        MP4_READBOX_EXIT( 0 );
4928
0
    }
4929
4930
29
    p_data->p_entries = vlc_alloc( p_data->i_entry_count, sizeof(p_data->p_entries[0]) );
4931
29
    if( !p_data->p_entries )
4932
0
    {
4933
0
        p_data->i_entry_count = 0;
4934
0
        MP4_READBOX_EXIT( 0 );
4935
0
    }
4936
4937
58
    for( uint32_t i=0; i<p_data->i_entry_count; i++ )
4938
29
    {
4939
29
        if( i_read < ((i_version < 1) ? 3 : 5) )
4940
0
        {
4941
0
            p_data->i_entry_count = i;
4942
0
            MP4_READBOX_EXIT( 0 );
4943
0
        }
4944
29
        if( i_version < 1 )
4945
29
            MP4_GET2BYTES( p_data->p_entries[i].i_item_id );
4946
0
        else
4947
29
            MP4_GET4BYTES( p_data->p_entries[i].i_item_id );
4948
29
        MP4_GET1BYTE( p_data->p_entries[i].i_association_count );
4949
4950
29
        if( i_read / ((i_flags & 0x01) ? 2 : 1) <
4951
29
               p_data->p_entries[i].i_association_count )
4952
0
        {
4953
0
            p_data->i_entry_count = i;
4954
0
            MP4_READBOX_EXIT( 0 );
4955
0
        }
4956
4957
29
        p_data->p_entries[i].p_assocs =
4958
29
                vlc_alloc( p_data->p_entries[i].i_association_count,
4959
29
                           sizeof(p_data->p_entries[i].p_assocs[0]) );
4960
29
        if( !p_data->p_entries[i].p_assocs )
4961
0
        {
4962
0
            p_data->p_entries[i].i_association_count = 0;
4963
0
            p_data->i_entry_count = i;
4964
0
            MP4_READBOX_EXIT( 0 );
4965
0
        }
4966
4967
145
        for( uint8_t j=0; j<p_data->p_entries[i].i_association_count; j++ )
4968
116
        {
4969
116
            MP4_GET1BYTE( p_data->p_entries[i].p_assocs[j].i_property_index );
4970
116
            p_data->p_entries[i].p_assocs[j].b_essential =
4971
116
                    p_data->p_entries[i].p_assocs[j].i_property_index & 0x80;
4972
116
            p_data->p_entries[i].p_assocs[j].i_property_index &= 0x7F;
4973
116
            if( i_flags & 0x01 )
4974
0
            {
4975
0
                p_data->p_entries[i].p_assocs[j].i_property_index <<= 8;
4976
0
                uint8_t i_low;
4977
0
                MP4_GET1BYTE( i_low );
4978
0
                p_data->p_entries[i].p_assocs[j].i_property_index |= i_low;
4979
0
            }
4980
116
        }
4981
29
    }
4982
4983
29
    MP4_READBOX_EXIT( 1 );
4984
29
}
4985
4986
/* For generic */
4987
static int MP4_ReadBox_default( stream_t *p_stream, MP4_Box_t *p_box )
4988
5.69k
{
4989
5.69k
    if( !p_box->p_father )
4990
0
    {
4991
0
        goto unknown;
4992
0
    }
4993
4994
5.69k
unknown:
4995
5.69k
    if MP4_BOX_TYPE_ASCII()
4996
5.69k
        msg_Warn( p_stream,
4997
2
                "unknown box type %4.4s (incompletely loaded)",
4998
2
                (char*)&p_box->i_type );
4999
2
    else
5000
5.69k
        msg_Warn( p_stream,
5001
5.69k
                "unknown box type c%3.3s (incompletely loaded)",
5002
5.69k
                (char*)&p_box->i_type+1 );
5003
5.69k
    p_box->e_flags |= BOX_FLAG_INCOMPLETE;
5004
5005
5.69k
    return 1;
5006
5.69k
}
5007
5008
/**** ------------------------------------------------------------------- ****/
5009
5010
static int MP4_ReadBox_uuid( stream_t *p_stream, MP4_Box_t *p_box )
5011
7
{
5012
7
    if( !CmpUUID( &p_box->i_uuid, &TfrfBoxUUID ) )
5013
0
        return MP4_ReadBox_tfrf( p_stream, p_box );
5014
7
    if( !CmpUUID( &p_box->i_uuid, &TfxdBoxUUID ) )
5015
6
        return MP4_ReadBox_tfxd( p_stream, p_box );
5016
1
    if( !CmpUUID( &p_box->i_uuid, &XML360BoxUUID ) )
5017
0
        return MP4_ReadBox_XML360( p_stream, p_box );
5018
1
    if( !CmpUUID( &p_box->i_uuid, &PS3DDSBoxUUID ) && p_box->i_size == 28 )
5019
0
        return MP4_ReadBox_Binary( p_stream, p_box );
5020
5021
1
#ifdef MP4_VERBOSE
5022
1
    msg_Warn( p_stream, "Unknown uuid type box: "
5023
1
    "%2.2x%2.2x%2.2x%2.2x-%2.2x%2.2x-%2.2x%2.2x-"
5024
1
    "%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
5025
1
    p_box->i_uuid.b[0],  p_box->i_uuid.b[1],  p_box->i_uuid.b[2],  p_box->i_uuid.b[3],
5026
1
    p_box->i_uuid.b[4],  p_box->i_uuid.b[5],  p_box->i_uuid.b[6],  p_box->i_uuid.b[7],
5027
1
    p_box->i_uuid.b[8],  p_box->i_uuid.b[9],  p_box->i_uuid.b[10], p_box->i_uuid.b[11],
5028
1
    p_box->i_uuid.b[12], p_box->i_uuid.b[13], p_box->i_uuid.b[14], p_box->i_uuid.b[15] );
5029
#else
5030
    msg_Warn( p_stream, "Unknown uuid type box" );
5031
#endif
5032
1
    return 1;
5033
1
}
5034
5035
/**** ------------------------------------------------------------------- ****/
5036
/****                   "Higher level" Functions                          ****/
5037
/**** ------------------------------------------------------------------- ****/
5038
5039
static const struct
5040
{
5041
    uint32_t i_type;
5042
    int  (*MP4_ReadBox_function )( stream_t *p_stream, MP4_Box_t *p_box );
5043
    uint32_t i_parent; /* set parent to restrict, duplicating if needed; 0 for any */
5044
} MP4_Box_Function [] =
5045
{
5046
    /* Containers */
5047
    { ATOM_moov,    MP4_ReadBoxContainer,     0 },
5048
    { ATOM_trak,    MP4_ReadBoxContainer,     ATOM_moov },
5049
    { ATOM_trak,    MP4_ReadBoxContainer,     ATOM_foov },
5050
    { ATOM_mdia,    MP4_ReadBox_mdia,         ATOM_trak },
5051
    { ATOM_moof,    MP4_ReadBoxContainer,     0 },
5052
    { ATOM_minf,    MP4_ReadBoxContainer,     ATOM_mdia },
5053
    { ATOM_stbl,    MP4_ReadBoxContainer,     ATOM_minf },
5054
    { ATOM_dinf,    MP4_ReadBoxContainer,     ATOM_minf },
5055
    { ATOM_dinf,    MP4_ReadBoxContainer,     ATOM_meta },
5056
    { ATOM_edts,    MP4_ReadBoxContainer,     ATOM_trak },
5057
    { ATOM_udta,    MP4_ReadBoxContainer,     0 },
5058
    { ATOM_nmhd,    MP4_ReadBoxContainer,     ATOM_minf },
5059
    { ATOM_hnti,    MP4_ReadBoxContainer,     ATOM_udta },
5060
    { ATOM_rmra,    MP4_ReadBoxContainer,     ATOM_moov },
5061
    { ATOM_rmda,    MP4_ReadBoxContainer,     ATOM_rmra },
5062
    { ATOM_tref,    MP4_ReadBox_tref,         ATOM_trak },
5063
    { ATOM_gmhd,    MP4_ReadBoxContainer,     ATOM_minf },
5064
    { ATOM_wave,    MP4_ReadBoxContainer,     ATOM_stsd },
5065
    { ATOM_wave,    MP4_ReadBoxContainer,     ATOM_mp4a }, /* some quicktime mp4a/wave/mp4a.. */
5066
    { ATOM_wave,    MP4_ReadBoxContainer,     ATOM_WMA2 }, /* flip4mac */
5067
    { ATOM_wave,    MP4_ReadBoxContainer,     ATOM_in24 },
5068
    { ATOM_wave,    MP4_ReadBoxContainer,     ATOM_in32 },
5069
    { ATOM_wave,    MP4_ReadBoxContainer,     ATOM_fl32 },
5070
    { ATOM_wave,    MP4_ReadBoxContainer,     ATOM_fl64 },
5071
    { ATOM_wave,    MP4_ReadBoxContainer,     ATOM_QDMC },
5072
    { ATOM_wave,    MP4_ReadBoxContainer,     ATOM_QDM2 },
5073
    { ATOM_wave,    MP4_ReadBoxContainer,     ATOM_XiFL }, /* XiphQT */
5074
    { ATOM_wave,    MP4_ReadBoxContainer,     ATOM_XiVs }, /* XiphQT */
5075
    { ATOM_ilst,    MP4_ReadBox_ilst,         ATOM_meta },
5076
    { ATOM_mvex,    MP4_ReadBoxContainer,     ATOM_moov },
5077
    { ATOM_mvex,    MP4_ReadBoxContainer,     ATOM_ftyp },
5078
5079
    /* Quicktime compression */
5080
    { ATOM_foov,    MP4_ReadBoxContainer,     0 },
5081
    { ATOM_cmov,    MP4_ReadBox_cmov,         ATOM_foov },
5082
    { ATOM_cmov,    MP4_ReadBox_cmov,         ATOM_moov },
5083
    { ATOM_dcom,    MP4_ReadBox_dcom,         ATOM_cmov },
5084
    { ATOM_cmvd,    MP4_ReadBox_cmvd,         ATOM_cmov },
5085
5086
    /* specific box */
5087
    { ATOM_ftyp,    MP4_ReadBox_ftyp,         0 },
5088
    { ATOM_styp,    MP4_ReadBox_ftyp,         0 },
5089
    { ATOM_mvhd,    MP4_ReadBox_mvhd,         ATOM_moov },
5090
    { ATOM_mvhd,    MP4_ReadBox_mvhd,         ATOM_foov },
5091
    { ATOM_tkhd,    MP4_ReadBox_tkhd,         ATOM_trak },
5092
    { ATOM_load,    MP4_ReadBox_load,         ATOM_trak },
5093
    { ATOM_mdhd,    MP4_ReadBox_mdhd,         ATOM_mdia },
5094
    { ATOM_hdlr,    MP4_ReadBox_hdlr,         ATOM_mdia },
5095
    { ATOM_hdlr,    MP4_ReadBox_hdlr,         ATOM_meta },
5096
    { ATOM_hdlr,    MP4_ReadBox_hdlr,         ATOM_minf },
5097
    { ATOM_vmhd,    MP4_ReadBox_vmhd,         ATOM_minf },
5098
    { ATOM_smhd,    MP4_ReadBox_smhd,         ATOM_minf },
5099
    { ATOM_hmhd,    MP4_ReadBox_hmhd,         ATOM_minf },
5100
    { ATOM_alis,    MP4_ReadBoxSkip,          ATOM_dref },
5101
    { ATOM_url,     MP4_ReadBox_url,          0 },
5102
    { ATOM_urn,     MP4_ReadBox_urn,          0 },
5103
    { ATOM_dref,    MP4_ReadBox_LtdContainer, 0 },
5104
    { ATOM_stts,    MP4_ReadBox_stts,         ATOM_stbl },
5105
    { ATOM_ctts,    MP4_ReadBox_ctts,         ATOM_stbl },
5106
    { ATOM_cslg,    MP4_ReadBox_cslg,         ATOM_stbl },
5107
    { ATOM_stsd,    MP4_ReadBox_stsd,         ATOM_stbl },
5108
    { ATOM_stsz,    MP4_ReadBox_stsz,         ATOM_stbl },
5109
    { ATOM_stz2,    MP4_ReadBox_stz2,         ATOM_stbl },
5110
    { ATOM_stsc,    MP4_ReadBox_stsc,         ATOM_stbl },
5111
    { ATOM_stco,    MP4_ReadBox_stco_co64,    ATOM_stbl },
5112
    { ATOM_co64,    MP4_ReadBox_stco_co64,    ATOM_stbl },
5113
    { ATOM_stss,    MP4_ReadBox_stss,         ATOM_stbl },
5114
    { ATOM_stsh,    MP4_ReadBox_stsh,         ATOM_stbl },
5115
    { ATOM_stdp,    MP4_ReadBox_stdp,         0 },
5116
    { ATOM_elst,    MP4_ReadBox_elst,         ATOM_edts },
5117
    { ATOM_cprt,    MP4_ReadBox_cprt,         0 },
5118
    { ATOM_esds,    MP4_ReadBox_esds,         ATOM_wave }, /* mp4a in wave chunk */
5119
    { ATOM_esds,    MP4_ReadBox_esds,         ATOM_mp4a },
5120
    { ATOM_esds,    MP4_ReadBox_esds,         ATOM_mp4v },
5121
    { ATOM_esds,    MP4_ReadBox_esds,         ATOM_mp4s },
5122
    { ATOM_dfLa,    MP4_ReadBox_Binary,       ATOM_fLaC },
5123
    { ATOM_av1C,    MP4_ReadBox_av1C,         ATOM_av01 },
5124
    { ATOM_avcC,    MP4_ReadBox_avcC,         ATOM_avc1 },
5125
    { ATOM_avcC,    MP4_ReadBox_avcC,         ATOM_avc3 },
5126
    { ATOM_vvcC,    MP4_ReadBox_Binary,       ATOM_vvc1 },
5127
    { ATOM_apvC,    MP4_ReadBox_Binary,       ATOM_apv1 },
5128
    { ATOM_hvcC,    MP4_ReadBox_Binary,       0 },
5129
    { ATOM_jpeC,    MP4_ReadBox_Binary,       0 }, /* heif */
5130
    { ATOM_av1C,    MP4_ReadBox_av1C,         ATOM_ipco }, /* heif */
5131
    { ATOM_vpcC,    MP4_ReadBox_vpcC,         ATOM_vp08 },
5132
    { ATOM_vpcC,    MP4_ReadBox_vpcC,         ATOM_vp09 },
5133
    { ATOM_vpcC,    MP4_ReadBox_vpcC,         ATOM_vp10 },
5134
    { ATOM_SmDm,    MP4_ReadBox_SmDm,         ATOM_vpcC }, /* SMPTE2086 mastering display */
5135
    { ATOM_mdcv,    MP4_ReadBox_SmDm,         0 }, /* */
5136
    { ATOM_CoLL,    MP4_ReadBox_CoLL,         ATOM_vpcC }, /* CEA861-3 light level */
5137
    { ATOM_clli,    MP4_ReadBox_CoLL,         0 }, /* */
5138
    { ATOM_dac3,    MP4_ReadBox_dac3,         0 },
5139
    { ATOM_dec3,    MP4_ReadBox_dec3,         0 },
5140
    { ATOM_dvc1,    MP4_ReadBox_dvc1,         ATOM_vc1  },
5141
    { ATOM_fiel,    MP4_ReadBox_fiel,         0 },
5142
    { ATOM_glbl,    MP4_ReadBox_Binary,       0 },
5143
    { ATOM_enda,    MP4_ReadBox_enda,         0 },
5144
    { ATOM_pcmC,    MP4_ReadBox_pcmC,         0 }, /* ISO-IEC 23003-5 */
5145
    { ATOM_iods,    MP4_ReadBox_iods,         0 },
5146
    { ATOM_pasp,    MP4_ReadBox_pasp,         0 },
5147
    { ATOM_clap,    MP4_ReadBox_clap,         0 },
5148
    { ATOM_btrt,    MP4_ReadBox_btrt,         0 }, /* codecs bitrate stsd/????/btrt */
5149
    { ATOM_keys,    MP4_ReadBox_keys,         ATOM_meta },
5150
    { ATOM_colr,    MP4_ReadBox_colr,         0 },
5151
    { ATOM_irot,    MP4_ReadBox_irot,         0 }, /* heif */
5152
    { ATOM_dvcC,    MP4_ReadBox_dvcC,         0 }, /* dolby vision config record */
5153
    { ATOM_dvvC,    MP4_ReadBox_dvcC,         0 },
5154
    { ATOM_dvwC,    MP4_ReadBox_dvcC,         0 },
5155
5156
    /* XiphQT */
5157
    { ATOM_vCtH,    MP4_ReadBox_Binary,       ATOM_wave },
5158
    { ATOM_vCtC,    MP4_ReadBox_Binary,       ATOM_wave },
5159
    { ATOM_vCtd,    MP4_ReadBox_Binary,       ATOM_wave },
5160
    { ATOM_fCtS,    MP4_ReadBox_Binary,       ATOM_wave },
5161
5162
    /* Samples groups specific information */
5163
    { ATOM_sbgp,    MP4_ReadBox_sbgp,         ATOM_stbl },
5164
    { ATOM_sbgp,    MP4_ReadBox_sbgp,         ATOM_traf },
5165
    { ATOM_sgpd,    MP4_ReadBox_sgpd,         ATOM_stbl },
5166
    { ATOM_sgpd,    MP4_ReadBox_sgpd,         ATOM_traf },
5167
5168
    /* Quicktime preview atoms, all at root */
5169
    { ATOM_pnot,    MP4_ReadBox_pnot,         0 },
5170
    { ATOM_pict,    MP4_ReadBox_Binary,       0 },
5171
    { ATOM_PICT,    MP4_ReadBox_Binary,       0 },
5172
    /* Other preview atoms */
5173
    { ATOM_thum,    MP4_ReadBox_Binary,       0 },
5174
5175
    /* Nothing to do with this box */
5176
    { ATOM_mdat,    MP4_ReadBoxSkip,          0 },
5177
    { ATOM_skip,    MP4_ReadBoxSkip,          0 },
5178
    { ATOM_free,    MP4_ReadBoxSkip,          0 },
5179
    { ATOM_wide,    MP4_ReadBoxSkip,          0 },
5180
    { ATOM_binm,    MP4_ReadBoxSkip,          0 },
5181
5182
    /* In sample WebVTT subtitle atoms. No ATOM_wvtt in normal parsing */
5183
    { ATOM_vttc,    MP4_ReadBoxContainer,         ATOM_wvtt },
5184
    { ATOM_payl,    MP4_ReadBox_Binary,           ATOM_vttc },
5185
5186
    /* Sound extensions */
5187
    { ATOM_chan,    MP4_ReadBox_stsdext_chan, 0 },
5188
    { ATOM_srat,    MP4_ReadBox_stsdext_srat, 0 },
5189
    { ATOM_WMA2,    MP4_ReadBox_WMA2,         ATOM_wave }, /* flip4mac */
5190
    { ATOM_dOps,    MP4_ReadBox_Binary,       ATOM_Opus },
5191
    { ATOM_wfex,    MP4_ReadBox_WMA2,         ATOM_wma  }, /* ismv formatex */
5192
5193
    { ATOM_mjqt,    MP4_ReadBox_default,      0 }, /* found in mjpa/b */
5194
    { ATOM_mjht,    MP4_ReadBox_default,      0 },
5195
5196
    { ATOM_strf,    MP4_ReadBox_strf,         ATOM_WVC1 }, /* MS smooth */
5197
    { ATOM_strf,    MP4_ReadBox_strf,         ATOM_H264 }, /* MS smooth */
5198
5199
    { ATOM_strf,    MP4_ReadBox_strf,         ATOM_WMV3 }, /* flip4mac */
5200
    { ATOM_ASF ,    MP4_ReadBox_ASF,          ATOM_WMV3 }, /* flip4mac */
5201
    { ATOM_ASF ,    MP4_ReadBox_ASF,          ATOM_wave }, /* flip4mac */
5202
5203
    { ATOM_hint,    MP4_ReadBox_default,      ATOM_stbl },
5204
5205
    /* found in hnti */
5206
    { ATOM_rtp,     MP4_ReadBox_rtp,          ATOM_hnti },
5207
    { ATOM_sdp,     MP4_ReadBox_sdp,          ATOM_hnti },
5208
5209
    /* found in rrtp sample description */
5210
    { ATOM_tims,     MP4_ReadBox_tims,        0 },
5211
    { ATOM_tsro,     MP4_ReadBox_tsro,        0 },
5212
    { ATOM_tssy,     MP4_ReadBox_tssy,        0 },
5213
5214
    /* found in rmra/rmda */
5215
    { ATOM_rdrf,    MP4_ReadBox_rdrf,         ATOM_rmda },
5216
    { ATOM_rmdr,    MP4_ReadBox_rmdr,         ATOM_rmda },
5217
    { ATOM_rmqu,    MP4_ReadBox_rmqu,         ATOM_rmda },
5218
    { ATOM_rmvc,    MP4_ReadBox_rmvc,         ATOM_rmda },
5219
5220
    { ATOM_sinf,    MP4_ReadBoxContainer,     0 },
5221
    { ATOM_schi,    MP4_ReadBoxContainer,     0 },
5222
    { ATOM_user,    MP4_ReadBox_drms,         0 },
5223
    { ATOM_key,     MP4_ReadBox_drms,         0 },
5224
    { ATOM_iviv,    MP4_ReadBox_drms,         0 },
5225
    { ATOM_priv,    MP4_ReadBox_drms,         0 },
5226
    { ATOM_frma,    MP4_ReadBox_frma,         ATOM_sinf }, /* and rinf */
5227
    { ATOM_frma,    MP4_ReadBox_frma,         ATOM_wave }, /* flip4mac */
5228
    { ATOM_skcr,    MP4_ReadBox_skcr,         0 },
5229
5230
    /* ilst meta tags */
5231
    { ATOM_0xa9ART, MP4_ReadBox_Metadata,    ATOM_ilst },
5232
    { ATOM_0xa9alb, MP4_ReadBox_Metadata,    ATOM_ilst },
5233
    { ATOM_0xa9cmt, MP4_ReadBox_Metadata,    ATOM_ilst },
5234
    { ATOM_0xa9com, MP4_ReadBox_Metadata,    ATOM_ilst },
5235
    { ATOM_0xa9cpy, MP4_ReadBox_Metadata,    ATOM_ilst },
5236
    { ATOM_0xa9day, MP4_ReadBox_Metadata,    ATOM_ilst },
5237
    { ATOM_0xa9des, MP4_ReadBox_Metadata,    ATOM_ilst },
5238
    { ATOM_0xa9enc, MP4_ReadBox_Metadata,    ATOM_ilst },
5239
    { ATOM_0xa9gen, MP4_ReadBox_Metadata,    ATOM_ilst },
5240
    { ATOM_0xa9grp, MP4_ReadBox_Metadata,    ATOM_ilst },
5241
    { ATOM_0xa9lyr, MP4_ReadBox_Metadata,    ATOM_ilst },
5242
    { ATOM_0xa9nam, MP4_ReadBox_Metadata,    ATOM_ilst },
5243
    { ATOM_0xa9too, MP4_ReadBox_Metadata,    ATOM_ilst },
5244
    { ATOM_0xa9trk, MP4_ReadBox_Metadata,    ATOM_ilst },
5245
    { ATOM_0xa9wrt, MP4_ReadBox_Metadata,    ATOM_ilst },
5246
    { ATOM_aART,    MP4_ReadBox_Metadata,    ATOM_ilst },
5247
    { ATOM_atID,    MP4_ReadBox_Metadata,    ATOM_ilst }, /* iTunes */
5248
    { ATOM_cnID,    MP4_ReadBox_Metadata,    ATOM_ilst }, /* iTunes */
5249
    { ATOM_covr,    MP4_ReadBoxContainer,    ATOM_ilst },
5250
    { ATOM_desc,    MP4_ReadBox_Metadata,    ATOM_ilst },
5251
    { ATOM_disk,    MP4_ReadBox_Metadata,    ATOM_ilst },
5252
    { ATOM_flvr,    MP4_ReadBox_Metadata,    ATOM_ilst },
5253
    { ATOM_gnre,    MP4_ReadBox_Metadata,    ATOM_ilst },
5254
    { ATOM_rtng,    MP4_ReadBox_Metadata,    ATOM_ilst },
5255
    { ATOM_trkn,    MP4_ReadBox_Metadata,    ATOM_ilst },
5256
    { ATOM_xid_,    MP4_ReadBox_Metadata,    ATOM_ilst },
5257
    { ATOM_gshh,    MP4_ReadBox_Metadata,    ATOM_ilst }, /* YouTube gs?? */
5258
    { ATOM_gspm,    MP4_ReadBox_Metadata,    ATOM_ilst },
5259
    { ATOM_gspu,    MP4_ReadBox_Metadata,    ATOM_ilst },
5260
    { ATOM_gssd,    MP4_ReadBox_Metadata,    ATOM_ilst },
5261
    { ATOM_gsst,    MP4_ReadBox_Metadata,    ATOM_ilst },
5262
    { ATOM_gstd,    MP4_ReadBox_Metadata,    ATOM_ilst },
5263
    { ATOM_ITUN,    MP4_ReadBox_Metadata,    ATOM_ilst }, /* iTunesInfo */
5264
    { ATOM_purl,    MP4_ReadBox_Metadata,    ATOM_ilst },
5265
5266
    /* udta */
5267
    { ATOM_0x40PRM, MP4_ReadBox_Binary,    ATOM_udta },
5268
    { ATOM_0x40PRQ, MP4_ReadBox_Binary,    ATOM_udta },
5269
    { ATOM_0xa9ART, MP4_ReadBox_Binary,    ATOM_udta },
5270
    { ATOM_0xa9alb, MP4_ReadBox_Binary,    ATOM_udta },
5271
    { ATOM_0xa9ard, MP4_ReadBox_Binary,    ATOM_udta },
5272
    { ATOM_0xa9arg, MP4_ReadBox_Binary,    ATOM_udta },
5273
    { ATOM_0xa9aut, MP4_ReadBox_Binary,    ATOM_udta },
5274
    { ATOM_0xa9cak, MP4_ReadBox_Binary,    ATOM_udta },
5275
    { ATOM_0xa9cmt, MP4_ReadBox_Binary,    ATOM_udta },
5276
    { ATOM_0xa9con, MP4_ReadBox_Binary,    ATOM_udta },
5277
    { ATOM_0xa9com, MP4_ReadBox_Binary,    ATOM_udta },
5278
    { ATOM_0xa9cpy, MP4_ReadBox_Binary,    ATOM_udta },
5279
    { ATOM_0xa9day, MP4_ReadBox_Binary,    ATOM_udta },
5280
    { ATOM_0xa9des, MP4_ReadBox_Binary,    ATOM_udta },
5281
    { ATOM_0xa9dir, MP4_ReadBox_Binary,    ATOM_udta },
5282
    { ATOM_0xa9dis, MP4_ReadBox_Binary,    ATOM_udta },
5283
    { ATOM_0xa9dsa, MP4_ReadBox_Binary,    ATOM_udta },
5284
    { ATOM_0xa9fmt, MP4_ReadBox_Binary,    ATOM_udta },
5285
    { ATOM_0xa9gen, MP4_ReadBox_Binary,    ATOM_udta },
5286
    { ATOM_0xa9grp, MP4_ReadBox_Binary,    ATOM_udta },
5287
    { ATOM_0xa9hst, MP4_ReadBox_Binary,    ATOM_udta },
5288
    { ATOM_0xa9inf, MP4_ReadBox_Binary,    ATOM_udta },
5289
    { ATOM_0xa9isr, MP4_ReadBox_Binary,    ATOM_udta },
5290
    { ATOM_0xa9lab, MP4_ReadBox_Binary,    ATOM_udta },
5291
    { ATOM_0xa9lal, MP4_ReadBox_Binary,    ATOM_udta },
5292
    { ATOM_0xa9lnt, MP4_ReadBox_Binary,    ATOM_udta },
5293
    { ATOM_0xa9lyr, MP4_ReadBox_Binary,    ATOM_udta },
5294
    { ATOM_0xa9mak, MP4_ReadBox_Binary,    ATOM_udta },
5295
    { ATOM_0xa9mal, MP4_ReadBox_Binary,    ATOM_udta },
5296
    { ATOM_0xa9mod, MP4_ReadBox_Binary,    ATOM_udta },
5297
    { ATOM_0xa9nam, MP4_ReadBox_Binary,    ATOM_udta },
5298
    { ATOM_0xa9ope, MP4_ReadBox_Binary,    ATOM_udta },
5299
    { ATOM_0xa9phg, MP4_ReadBox_Binary,    ATOM_udta },
5300
    { ATOM_0xa9PRD, MP4_ReadBox_Binary,    ATOM_udta },
5301
    { ATOM_0xa9prd, MP4_ReadBox_Binary,    ATOM_udta },
5302
    { ATOM_0xa9prf, MP4_ReadBox_Binary,    ATOM_udta },
5303
    { ATOM_0xa9pub, MP4_ReadBox_Binary,    ATOM_udta },
5304
    { ATOM_0xa9req, MP4_ReadBox_Binary,    ATOM_udta },
5305
    { ATOM_0xa9sne, MP4_ReadBox_Binary,    ATOM_udta },
5306
    { ATOM_0xa9snm, MP4_ReadBox_Binary,    ATOM_udta },
5307
    { ATOM_0xa9sol, MP4_ReadBox_Binary,    ATOM_udta },
5308
    { ATOM_0xa9src, MP4_ReadBox_Binary,    ATOM_udta },
5309
    { ATOM_0xa9st3, MP4_ReadBox_Binary,    ATOM_udta },
5310
    { ATOM_0xa9swr, MP4_ReadBox_Binary,    ATOM_udta },
5311
    { ATOM_0xa9thx, MP4_ReadBox_Binary,    ATOM_udta },
5312
    { ATOM_0xa9too, MP4_ReadBox_Binary,    ATOM_udta },
5313
    { ATOM_0xa9trk, MP4_ReadBox_Binary,    ATOM_udta },
5314
    { ATOM_0xa9url, MP4_ReadBox_Binary,    ATOM_udta },
5315
    { ATOM_0xa9wrn, MP4_ReadBox_Binary,    ATOM_udta },
5316
    { ATOM_0xa9xpd, MP4_ReadBox_Binary,    ATOM_udta },
5317
    { ATOM_0xa9xyz, MP4_ReadBox_Binary,    ATOM_udta },
5318
    { ATOM_chpl,    MP4_ReadBox_chpl,      ATOM_udta }, /* nero unlabeled chapters list */
5319
    { ATOM_MCPS,    MP4_ReadBox_Binary,    ATOM_udta },
5320
    { ATOM_name,    MP4_ReadBox_Binary,    ATOM_udta },
5321
    { ATOM_vndr,    MP4_ReadBox_Binary,    ATOM_udta },
5322
    { ATOM_SDLN,    MP4_ReadBox_Binary,    ATOM_udta },
5323
    { ATOM_HMMT,    MP4_ReadBox_HMMT,      ATOM_udta }, /* GoPro HiLight tags */
5324
5325
    /* udta, non meta */
5326
    { ATOM_tsel,    MP4_ReadBox_tsel,    ATOM_udta },
5327
5328
    /* iTunes/Quicktime meta info */
5329
    { ATOM_meta,    MP4_ReadBox_meta,    0 },
5330
    { ATOM_ID32,    MP4_ReadBox_Binary,  ATOM_meta }, /* ID3v2 in 3GPP / ETSI TS 126 244 8.3 */
5331
    { ATOM_data,    MP4_ReadBox_data,    0 }, /* ilst/@too and others, ITUN/data */
5332
    { ATOM_mean,    MP4_ReadBox_Binary,  ATOM_ITUN },
5333
    { ATOM_name,    MP4_ReadBox_Binary,  ATOM_ITUN },
5334
5335
    /* found in smoothstreaming */
5336
    { ATOM_traf,    MP4_ReadBoxContainer,    ATOM_moof },
5337
    { ATOM_mfra,    MP4_ReadBoxContainer,    0 },
5338
    { ATOM_mfhd,    MP4_ReadBox_mfhd,        ATOM_moof },
5339
    { ATOM_sidx,    MP4_ReadBox_sidx,        0 },
5340
    { ATOM_tfhd,    MP4_ReadBox_tfhd,        ATOM_traf },
5341
    { ATOM_trun,    MP4_ReadBox_trun,        ATOM_traf },
5342
    { ATOM_tfdt,    MP4_ReadBox_tfdt,        ATOM_traf },
5343
    { ATOM_trex,    MP4_ReadBox_trex,        ATOM_mvex },
5344
    { ATOM_mehd,    MP4_ReadBox_mehd,        ATOM_mvex },
5345
    { ATOM_sdtp,    MP4_ReadBox_sdtp,        0 },
5346
    { ATOM_tfra,    MP4_ReadBox_tfra,        ATOM_mfra },
5347
    { ATOM_mfro,    MP4_ReadBox_mfro,        ATOM_mfra },
5348
    { ATOM_uuid,    MP4_ReadBox_uuid,        0 },
5349
5350
    /* spatial/360°/VR */
5351
    { ATOM_st3d,    MP4_ReadBox_st3d,        0 },
5352
    { ATOM_sv3d,    MP4_ReadBoxContainer,    0 },
5353
    { ATOM_proj,    MP4_ReadBoxContainer,    ATOM_sv3d },
5354
    { ATOM_prhd,    MP4_ReadBox_prhd,        ATOM_proj },
5355
    { ATOM_equi,    MP4_ReadBox_equi,        ATOM_proj },
5356
    { ATOM_cbmp,    MP4_ReadBox_cbmp,        ATOM_proj },
5357
5358
    /* Ambisonics */
5359
    { ATOM_SA3D,    MP4_ReadBox_SA3D,        0 },
5360
5361
    /* iso4 brand meta references */
5362
    { ATOM_idat,    MP4_ReadBoxSkip,         ATOM_meta },
5363
    { ATOM_iloc,    MP4_ReadBox_iloc,        ATOM_meta },
5364
    { ATOM_iinf,    MP4_ReadBox_iinf,        ATOM_meta },
5365
    { ATOM_infe,    MP4_ReadBox_infe,        ATOM_iinf },
5366
    { ATOM_iref,    MP4_ReadBox_iref,        ATOM_meta },
5367
    { ATOM_pitm,    MP4_ReadBox_pitm,        ATOM_meta },
5368
5369
    /* HEIF specific meta references */
5370
    { ATOM_iprp,    MP4_ReadBoxContainer,    ATOM_meta },
5371
    { ATOM_ipco,    MP4_ReadBoxContainer,    ATOM_iprp },
5372
    { ATOM_ispe,    MP4_ReadBox_ispe,        ATOM_ipco },
5373
    { ATOM_ipma,    MP4_ReadBox_ipma,        ATOM_iprp },
5374
5375
    /* Last entry */
5376
    { 0,              MP4_ReadBox_default,   0 }
5377
};
5378
5379
static int MP4_Box_Read_Specific( stream_t *p_stream, MP4_Box_t *p_box, MP4_Box_t *p_father )
5380
38.4k
{
5381
38.4k
    int i_index;
5382
5383
3.51M
    for( i_index = 0; ; i_index++ )
5384
3.55M
    {
5385
3.55M
        if ( MP4_Box_Function[i_index].i_parent &&
5386
2.81M
             p_father && p_father->i_type != MP4_Box_Function[i_index].i_parent )
5387
2.68M
            continue;
5388
5389
870k
        if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
5390
837k
            ( MP4_Box_Function[i_index].i_type == 0 ) )
5391
38.4k
        {
5392
38.4k
            break;
5393
38.4k
        }
5394
870k
    }
5395
5396
38.4k
    if( !(MP4_Box_Function[i_index].MP4_ReadBox_function)( p_stream, p_box ) )
5397
127
    {
5398
127
        return VLC_EGENERIC;
5399
127
    }
5400
5401
38.3k
    return VLC_SUCCESS;
5402
38.4k
}
5403
5404
static MP4_Box_t *MP4_ReadBoxAllocateCheck( stream_t *p_stream, MP4_Box_t *p_father )
5405
2.75k
{
5406
2.75k
    MP4_Box_t *p_box = calloc( 1, sizeof( MP4_Box_t ) ); /* Needed to ensure simple on error handler */
5407
2.75k
    if( p_box == NULL )
5408
0
        return NULL;
5409
5410
2.75k
    if( !MP4_PeekBoxHeader( p_stream, p_box ) )
5411
0
    {
5412
0
        msg_Warn( p_stream, "cannot read one box" );
5413
0
        free( p_box );
5414
0
        return NULL;
5415
0
    }
5416
5417
2.75k
    if( p_father && p_father->i_size > 0 &&
5418
2.75k
        p_father->i_pos + p_father->i_size < p_box->i_pos + p_box->i_size )
5419
532
    {
5420
532
        msg_Dbg( p_stream, "out of bound child" );
5421
532
        free( p_box );
5422
532
        return NULL;
5423
532
    }
5424
5425
2.22k
    if( !p_box->i_size )
5426
2
    {
5427
2
        msg_Dbg( p_stream, "found an empty box (null size)" );
5428
2
        free( p_box );
5429
2
        return NULL;
5430
2
    }
5431
2.22k
    p_box->p_father = p_father;
5432
5433
2.22k
    return p_box;
5434
2.22k
}
5435
5436
/*****************************************************************************
5437
 * MP4_ReadBoxUsing : parse the actual box and the children using handler
5438
 *****************************************************************************/
5439
static MP4_Box_t *MP4_ReadBoxUsing( stream_t *p_stream, MP4_Box_t *p_father,
5440
                                    int(*MP4_ReadBox_function)(stream_t *, MP4_Box_t *) )
5441
1.64k
{
5442
1.64k
    MP4_Box_t *p_box = MP4_ReadBoxAllocateCheck( p_stream, p_father );
5443
1.64k
    if( !p_box )
5444
63
        return NULL;
5445
5446
1.58k
    if( MP4_ReadBox_function( p_stream, p_box ) != 1 )
5447
35
    {
5448
35
        uint64_t i_end = p_box->i_pos + p_box->i_size;
5449
35
        MP4_BoxFree( p_box );
5450
35
        MP4_Seek( p_stream, i_end ); /* Skip the failed box */
5451
35
        return NULL;
5452
35
    }
5453
1.54k
    return p_box;
5454
1.58k
}
5455
5456
/*****************************************************************************
5457
 * MP4_ReadBox : parse the actual box and the children
5458
 *  XXX : Do not go to the next box
5459
 *****************************************************************************/
5460
static MP4_Box_t *MP4_ReadBox( stream_t *p_stream, MP4_Box_t *p_father )
5461
1.11k
{
5462
1.11k
    MP4_Box_t *p_box = MP4_ReadBoxAllocateCheck( p_stream, p_father );
5463
1.11k
    if( !p_box )
5464
471
        return NULL;
5465
5466
640
    if( MP4_Box_Read_Specific( p_stream, p_box, p_father ) != VLC_SUCCESS )
5467
0
    {
5468
0
        uint64_t i_end = p_box->i_pos + p_box->i_size;
5469
0
        MP4_BoxFree( p_box );
5470
0
        MP4_Seek( p_stream, i_end ); /* Skip the failed box */
5471
0
        return NULL;
5472
0
    }
5473
640
    return p_box;
5474
640
}
5475
5476
/*****************************************************************************
5477
 * MP4_BoxNew : creates and initializes an arbitrary box
5478
 *****************************************************************************/
5479
MP4_Box_t * MP4_BoxNew( uint32_t i_type )
5480
1.09k
{
5481
1.09k
    MP4_Box_t *p_box = calloc( 1, sizeof( MP4_Box_t ) );
5482
1.09k
    if( likely( p_box != NULL ) )
5483
1.09k
    {
5484
1.09k
        p_box->i_type = i_type;
5485
1.09k
    }
5486
1.09k
    return p_box;
5487
1.09k
}
5488
5489
/*****************************************************************************
5490
 * MP4_FreeBox : free memory after read with MP4_ReadBox and all
5491
 * the children
5492
 *****************************************************************************/
5493
void MP4_BoxFree( MP4_Box_t *p_box )
5494
41.1k
{
5495
41.1k
    MP4_Box_t    *p_child;
5496
5497
41.1k
    if( !p_box )
5498
37
        return; /* hehe */
5499
5500
80.7k
    for( p_child = p_box->p_first; p_child != NULL; )
5501
39.7k
    {
5502
39.7k
        MP4_Box_t *p_next;
5503
5504
39.7k
        p_next = p_child->p_next;
5505
39.7k
        MP4_BoxFree( p_child );
5506
39.7k
        p_child = p_next;
5507
39.7k
    }
5508
5509
41.0k
    if( p_box->pf_free )
5510
13.2k
        p_box->pf_free( p_box );
5511
5512
41.0k
    free( p_box->data.p_payload );
5513
41.0k
    free( p_box );
5514
41.0k
}
5515
5516
MP4_Box_t *MP4_BoxGetNextChunk( stream_t *s )
5517
143
{
5518
    /* p_chunk is a virtual root container for the moof and mdat boxes */
5519
143
    MP4_Box_t *p_fakeroot;
5520
143
    MP4_Box_t *p_tmp_box;
5521
5522
143
    p_fakeroot = MP4_BoxNew( ATOM_root );
5523
143
    if( unlikely( p_fakeroot == NULL ) )
5524
0
        return NULL;
5525
143
    p_fakeroot->i_shortsize = 1;
5526
5527
143
    const uint32_t stoplist[] = { ATOM_moov, ATOM_moof, 0 };
5528
143
    MP4_ReadBoxContainerChildren( s, p_fakeroot, stoplist );
5529
5530
143
    p_tmp_box = p_fakeroot->p_first;
5531
143
    if( p_tmp_box == NULL )
5532
0
    {
5533
0
        MP4_BoxFree( p_fakeroot );
5534
0
        return NULL;
5535
0
    }
5536
286
    else while( p_tmp_box )
5537
143
    {
5538
143
        p_fakeroot->i_size += p_tmp_box->i_size;
5539
143
        p_tmp_box = p_tmp_box->p_next;
5540
143
    }
5541
5542
143
    return p_fakeroot;
5543
143
}
5544
5545
/*****************************************************************************
5546
 * MP4_BoxGetRoot : Parse the entire file, and create all boxes in memory
5547
 *****************************************************************************
5548
 *  The first box is a virtual box "root" and is the father for all first
5549
 *  level boxes for the file, a sort of virtual container
5550
 *****************************************************************************/
5551
MP4_Box_t *MP4_BoxGetRoot( stream_t *p_stream )
5552
928
{
5553
928
    int i_result;
5554
5555
928
    MP4_Box_t *p_vroot = MP4_BoxNew( ATOM_root );
5556
928
    if( p_vroot == NULL )
5557
0
        return NULL;
5558
5559
928
    p_vroot->i_shortsize = 1;
5560
928
    uint64_t i_size;
5561
928
    if( vlc_stream_GetSize( p_stream, &i_size ) == 0 )
5562
928
        p_vroot->i_size = i_size;
5563
5564
    /* First get the moov */
5565
928
    {
5566
928
        const uint32_t stoplist[] = { ATOM_moov, ATOM_mdat, 0 };
5567
928
        i_result = MP4_ReadBoxContainerChildren( p_stream, p_vroot, stoplist );
5568
928
    }
5569
5570
    /* mdat appeared first */
5571
928
    if( i_result && !MP4_BoxGet( p_vroot, "moov" ) )
5572
129
    {
5573
129
        bool b_seekable;
5574
129
        if( vlc_stream_Control( p_stream, STREAM_CAN_SEEK, &b_seekable ) != VLC_SUCCESS || !b_seekable )
5575
0
        {
5576
0
            msg_Err( p_stream, "no moov before mdat and the stream is not seekable" );
5577
0
            goto error;
5578
0
        }
5579
5580
        /* continue loading up to moov */
5581
129
        const uint32_t stoplist[] = { ATOM_moov, 0 };
5582
129
        i_result = MP4_ReadBoxContainerChildren( p_stream, p_vroot, stoplist );
5583
129
    }
5584
5585
928
    if( !i_result )
5586
22
        return p_vroot;
5587
5588
    /* If there is a mvex box, it means fragmented MP4, and we're done */
5589
906
    if( MP4_BoxCount( p_vroot, "moov/mvex" ) > 0 )
5590
37
    {
5591
        /* Read a bit more atoms as we might have an index between moov and moof */
5592
37
        const uint32_t stoplist[] = { ATOM_sidx, 0 };
5593
37
        const uint32_t excludelist[] = { ATOM_moof, ATOM_mdat, 0 };
5594
37
        MP4_ReadBoxContainerChildrenIndexed( p_stream, p_vroot, stoplist, excludelist, false );
5595
37
        return p_vroot;
5596
37
    }
5597
5598
869
    if( vlc_stream_Tell( p_stream ) + 8 < i_size )
5599
399
    {
5600
        /* Get the rest of the file */
5601
399
        i_result = MP4_ReadBoxContainerChildren( p_stream, p_vroot, NULL );
5602
5603
399
        if( !i_result )
5604
0
            goto error;
5605
399
    }
5606
5607
869
    MP4_Box_t *p_cmov;
5608
    /* check if there is a cmov, if so replace
5609
      compressed moov by  uncompressed one */
5610
869
    if( ( p_cmov = MP4_BoxGet( p_vroot, "moov/cmov" ) ) ||
5611
869
        ( p_cmov = MP4_BoxGet( p_vroot, "foov/cmov" ) ) )
5612
0
    {
5613
0
        MP4_Box_t *p_moov = MP4_BoxExtract( &p_vroot->p_first, p_cmov->p_father->i_type );
5614
        /* get uncompressed p_moov */
5615
0
        MP4_Box_t *p_umoov = MP4_BoxExtract( &p_cmov->p_first, ATOM_moov );
5616
        /* make p_root father of this new moov */
5617
0
        MP4_BoxAddChild( p_vroot, p_umoov );
5618
        /* Release old moov and compressed info */
5619
0
        MP4_BoxFree( p_moov );
5620
0
    }
5621
5622
869
    return p_vroot;
5623
5624
0
error:
5625
0
    MP4_BoxFree( p_vroot );
5626
0
    MP4_Seek( p_stream, 0 );
5627
0
    return NULL;
5628
869
}
5629
5630
5631
static void MP4_BoxDumpStructure_Internal( vlc_object_t *obj, const MP4_Box_t *p_box,
5632
                                           unsigned int i_level )
5633
35.5k
{
5634
35.5k
    const MP4_Box_t *p_child;
5635
35.5k
    uint32_t i_displayedtype = p_box->i_type;
5636
35.5k
    if( ! MP4_BOX_TYPE_ASCII() ) ((char*)&i_displayedtype)[0] = 'c';
5637
5638
35.5k
    if( !i_level )
5639
904
    {
5640
904
        msg_Dbg( obj, "dumping root Box \"%4.4s\"",
5641
904
                          (char*)&i_displayedtype );
5642
904
    }
5643
34.5k
    else
5644
34.5k
    {
5645
34.5k
        char str[512];
5646
34.5k
        if( i_level >= (sizeof(str) - 1)/4 )
5647
0
            return;
5648
5649
34.5k
        memset( str, ' ', sizeof(str) );
5650
191k
        for( unsigned i = 0; i < i_level; i++ )
5651
157k
        {
5652
157k
            str[i*4] = '|';
5653
157k
        }
5654
5655
34.5k
        snprintf( &str[i_level * 4], sizeof(str) - 4*i_level,
5656
34.5k
                  "+ %4.4s size %"PRIu64" offset %"PRIu64"%s",
5657
34.5k
                  (char *)&i_displayedtype, p_box->i_size, p_box->i_pos,
5658
34.5k
                  p_box->e_flags & BOX_FLAG_INCOMPLETE ? " (\?\?\?\?)" : "" );
5659
34.5k
        msg_Dbg( obj, "%s", str );
5660
34.5k
    }
5661
35.5k
    p_child = p_box->p_first;
5662
70.0k
    while( p_child )
5663
34.5k
    {
5664
34.5k
        MP4_BoxDumpStructure_Internal( obj, p_child, i_level + 1 );
5665
34.5k
        p_child = p_child->p_next;
5666
34.5k
    }
5667
35.5k
}
5668
5669
void MP4_BoxDumpStructure( vlc_object_t *obj, const MP4_Box_t *p_box )
5670
904
{
5671
904
    MP4_BoxDumpStructure_Internal( obj, p_box, 0 );
5672
904
}
5673
5674
5675
/*****************************************************************************
5676
 *****************************************************************************
5677
 **
5678
 **  High level methods to access an MP4 file
5679
 **
5680
 *****************************************************************************
5681
 *****************************************************************************/
5682
static bool get_token( const char **ppsz_path, char **ppsz_token, unsigned *pi_number )
5683
345M
{
5684
345M
    size_t i_len ;
5685
345M
    if( !*ppsz_path[0] )
5686
40.0k
    {
5687
40.0k
        *ppsz_token = NULL;
5688
40.0k
        *pi_number = 0;
5689
40.0k
        return true;
5690
40.0k
    }
5691
345M
    i_len = strcspn( *ppsz_path, "/[" );
5692
345M
    if( !i_len && **ppsz_path == '/' )
5693
17.6k
    {
5694
17.6k
        i_len = 1;
5695
17.6k
    }
5696
345M
    *ppsz_token = strndup( *ppsz_path, i_len );
5697
345M
    if( unlikely(!*ppsz_token) )
5698
0
        return false;
5699
5700
345M
    *ppsz_path += i_len;
5701
5702
    /* Parse the token number token[n] */
5703
345M
    if( **ppsz_path == '[' )
5704
5.15k
    {
5705
5.15k
        (*ppsz_path)++;
5706
5.15k
        char *endptr = NULL;
5707
5.15k
        *pi_number = strtoul( *ppsz_path, &endptr, 10 );
5708
5.15k
        if( endptr == *ppsz_path || *endptr != ']' )
5709
0
        {
5710
0
            free(*ppsz_token);
5711
0
            return false;
5712
0
        }
5713
5.15k
        *ppsz_path = endptr + 1;
5714
5.15k
    }
5715
345M
    else
5716
345M
    {
5717
345M
        *pi_number = 0;
5718
345M
    }
5719
5720
    /* Forward to start of next token */
5721
345M
    while( **ppsz_path == '/' )
5722
47.5k
    {
5723
47.5k
        (*ppsz_path)++;
5724
47.5k
    }
5725
5726
345M
    return true;
5727
345M
}
5728
5729
static const MP4_Box_t * MP4_BoxGet_Path( const MP4_Box_t *p_box, const char *psz_path)
5730
345M
{
5731
345M
    assert( psz_path && psz_path[0] );
5732
5733
//    fprintf( stderr, "path:'%s'\n", psz_path );
5734
690M
    for( ; p_box ; )
5735
345M
    {
5736
345M
        unsigned i_number;
5737
345M
        char *psz_token = NULL;
5738
5739
345M
        if( !get_token( &psz_path, &psz_token, &i_number ) )
5740
0
        {
5741
0
            p_box = NULL;
5742
0
            break;
5743
0
        }
5744
//        fprintf( stderr, "path:'%s', token:'%s' n:%d\n",
5745
//                 psz_path,psz_token,i_number );
5746
345M
        if( !psz_token )
5747
40.0k
            break;
5748
5749
345M
        if( !strcmp( psz_token, "/" ) )
5750
17.6k
        {
5751
            /* Find root box */
5752
17.6k
            while( p_box && p_box->i_type != ATOM_root )
5753
0
                p_box = p_box->p_father;
5754
17.6k
        }
5755
345M
        else
5756
345M
        if( !strcmp( psz_token, "." ) )
5757
0
        {
5758
            /* Do nothing */
5759
0
        }
5760
345M
        else
5761
345M
        if( !strcmp( psz_token, ".." ) )
5762
3.97k
        {
5763
3.97k
            p_box = p_box->p_father;
5764
3.97k
        }
5765
345M
        else
5766
345M
        {
5767
345M
            size_t len = strlen( psz_token );
5768
345M
            if( len != 0 && len != 4 )
5769
0
            {
5770
//            fprintf( stderr, "Argg malformed token \"%s\"",psz_token );
5771
0
              free( psz_token );
5772
0
              p_box = NULL;
5773
0
              break;
5774
0
            }
5775
5776
345M
            uint32_t i_fourcc = 0 ;
5777
345M
            if( len == 4 )
5778
345M
                i_fourcc = VLC_FOURCC( psz_token[0], psz_token[1],
5779
345M
                                       psz_token[2], psz_token[3] );
5780
5781
2.07G
            for( p_box = p_box->p_first; p_box; p_box = p_box->p_next )
5782
1.72G
            {
5783
1.72G
                if( i_fourcc && p_box->i_type != i_fourcc )
5784
1.72G
                    continue;
5785
72.4k
                if( i_number == 0 )
5786
70.4k
                    break;
5787
1.92k
                i_number--;
5788
1.92k
            }
5789
345M
        }
5790
5791
345M
        free( psz_token );
5792
345M
    }
5793
5794
345M
    return p_box;
5795
345M
}
5796
5797
static const MP4_Box_t * MP4_BoxGet_Internal( const MP4_Box_t *p_box,
5798
                                 const char *psz_fmt, va_list args)
5799
5.15k
{
5800
5.15k
    char *psz_path;
5801
5802
5.15k
    if( !p_box )
5803
0
        return NULL;
5804
5805
5.15k
    if( vasprintf( &psz_path, psz_fmt, args ) == -1 )
5806
0
        psz_path = NULL;
5807
5808
5.15k
    if( !psz_path || !psz_path[0] )
5809
0
    {
5810
0
        free( psz_path );
5811
0
        return NULL;
5812
0
    }
5813
5814
5.15k
    const MP4_Box_t *p_result = MP4_BoxGet_Path( p_box, psz_path );
5815
5.15k
    free( psz_path );
5816
5.15k
    return p_result;
5817
5.15k
}
5818
5819
/*****************************************************************************
5820
 * MP4_BoxGet: find a box given a path relative to p_box
5821
 *****************************************************************************
5822
 * Path Format: . .. / as usual
5823
 *              [number] to specifie box number ex: trak[12]
5824
 *
5825
 * ex: /moov/trak[12]
5826
 *     ../mdia
5827
 *****************************************************************************/
5828
MP4_Box_t *MP4_BoxGetVa( const MP4_Box_t *p_box, const char *psz_fmt, ... )
5829
5.15k
{
5830
5.15k
    va_list args;
5831
5.15k
    const MP4_Box_t *p_result;
5832
5833
5.15k
    va_start( args, psz_fmt );
5834
5.15k
    p_result = MP4_BoxGet_Internal( p_box, psz_fmt, args );
5835
5.15k
    va_end( args );
5836
5837
5.15k
    return( (MP4_Box_t *) p_result );
5838
5.15k
}
5839
5840
MP4_Box_t *MP4_BoxGet( const MP4_Box_t *p_box, const char *psz_fmt )
5841
345M
{
5842
345M
    return (MP4_Box_t *) MP4_BoxGet_Path( p_box, psz_fmt );
5843
345M
}
5844
5845
/*****************************************************************************
5846
 * MP4_BoxCount: count box given a path relative to p_box
5847
 *****************************************************************************
5848
 * Path Format: . .. / as usual
5849
 *              [number] to specifie box number ex: trak[12]
5850
 *
5851
 * ex: /moov/trak[12]
5852
 *     ../mdia
5853
 *****************************************************************************/
5854
unsigned MP4_BoxCountVa( const MP4_Box_t *p_box, const char *psz_fmt, ... )
5855
0
{
5856
0
    va_list args;
5857
0
    unsigned i_count;
5858
0
    const MP4_Box_t *p_result, *p_next;
5859
5860
0
    va_start( args, psz_fmt );
5861
0
    p_result = MP4_BoxGet_Internal( p_box, psz_fmt, args );
5862
0
    va_end( args );
5863
0
    if( !p_result )
5864
0
    {
5865
0
        return( 0 );
5866
0
    }
5867
5868
0
    i_count = 1;
5869
0
    for( p_next = p_result->p_next; p_next != NULL; p_next = p_next->p_next)
5870
0
    {
5871
0
        if( p_next->i_type == p_result->i_type)
5872
0
        {
5873
0
            i_count++;
5874
0
        }
5875
0
    }
5876
0
    return( i_count );
5877
0
}
5878
5879
unsigned MP4_BoxCount( const MP4_Box_t *p_box, const char *psz_fmt )
5880
1.95k
{
5881
1.95k
    unsigned i_count;
5882
1.95k
    const MP4_Box_t *p_result, *p_next;
5883
5884
1.95k
    p_result = MP4_BoxGet_Path( p_box, psz_fmt );
5885
1.95k
    if( !p_result )
5886
875
    {
5887
875
        return( 0 );
5888
875
    }
5889
5890
1.07k
    i_count = 1;
5891
2.47k
    for( p_next = p_result->p_next; p_next != NULL; p_next = p_next->p_next)
5892
1.39k
    {
5893
1.39k
        if( p_next->i_type == p_result->i_type)
5894
421
        {
5895
421
            i_count++;
5896
421
        }
5897
1.39k
    }
5898
1.07k
    return( i_count );
5899
1.95k
}