Coverage Report

Created: 2025-07-23 07:11

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