]> git.sesse.net Git - vlc/blob - modules/demux/mp4/libmp4.c
mp4: fix pointer type
[vlc] / modules / demux / mp4 / libmp4.c
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>                               /* stream_Peek*/
29
30 #ifdef HAVE_ZLIB_H
31 #   include <zlib.h>                                  /* for compressed moov */
32 #endif
33
34 #include "libmp4.h"
35 #include <math.h>
36
37 /* Some assumptions:
38  * The input method HAS to be seekable
39  */
40
41 /* convert 16.16 fixed point to floating point */
42 static double conv_fx( int32_t fx ) {
43     double fp = fx;
44     fp /= 65536.;
45     return fp;
46 }
47
48 /* some functions for mp4 encoding of variables */
49 #ifdef MP4_VERBOSE
50 static void MP4_ConvertDate2Str( char *psz, uint64_t i_date )
51 {
52     int i_day;
53     int i_hour;
54     int i_min;
55     int i_sec;
56
57     /* date begin at 1 jan 1904 */
58     i_date += ((INT64_C(1904) * 365) + 17) * 24 * 60 * 60;
59
60     i_day = i_date / ( 60*60*24);
61     i_hour = ( i_date /( 60*60 ) ) % 60;
62     i_min  = ( i_date / 60 ) % 60;
63     i_sec =  i_date % 60;
64     sprintf( psz, "%dd-%2.2dh:%2.2dm:%2.2ds", i_day, i_hour, i_min, i_sec );
65 }
66 #endif
67
68 /*****************************************************************************
69  * Some prototypes.
70  *****************************************************************************/
71 static MP4_Box_t *MP4_ReadBox( stream_t *p_stream, MP4_Box_t *p_father );
72
73
74 /*****************************************************************************
75  * MP4_ReadBoxCommon : Load only common parameters for all boxes
76  *****************************************************************************
77  * p_box need to be an already allocated MP4_Box_t, and all data
78  *  will only be peek not read
79  *
80  * RETURN : 0 if it fail, 1 otherwise
81  *****************************************************************************/
82 int MP4_ReadBoxCommon( stream_t *p_stream, MP4_Box_t *p_box )
83 {
84     int      i_read;
85     const uint8_t  *p_peek;
86
87     if( ( ( i_read = stream_Peek( p_stream, &p_peek, 32 ) ) < 8 ) )
88     {
89         return 0;
90     }
91     p_box->i_pos = stream_Tell( p_stream );
92
93     p_box->data.p_payload = NULL;
94     p_box->p_father = NULL;
95     p_box->p_first  = NULL;
96     p_box->p_last  = NULL;
97     p_box->p_next   = NULL;
98
99     MP4_GET4BYTES( p_box->i_shortsize );
100     MP4_GETFOURCC( p_box->i_type );
101
102     /* Now special case */
103
104     if( p_box->i_shortsize == 1 )
105     {
106         /* get the true size on 64 bits */
107         MP4_GET8BYTES( p_box->i_size );
108     }
109     else
110     {
111         p_box->i_size = p_box->i_shortsize;
112         /* XXX size of 0 means that the box extends to end of file */
113     }
114
115     if( p_box->i_type == ATOM_uuid )
116     {
117         /* get extented type on 16 bytes */
118         GetUUID( &p_box->i_uuid, p_peek );
119         p_peek += 16; i_read -= 16;
120     }
121     else
122     {
123         CreateUUID( &p_box->i_uuid, p_box->i_type );
124     }
125 #ifdef MP4_VERBOSE
126     if( p_box->i_size )
127     {
128         if MP4_BOX_TYPE_ASCII()
129             msg_Dbg( p_stream, "found Box: %4.4s size %"PRId64,
130                     (char*)&p_box->i_type, p_box->i_size );
131         else
132             msg_Dbg( p_stream, "found Box: c%3.3s size %"PRId64,
133                     (char*)&p_box->i_type+1, p_box->i_size );
134     }
135 #endif
136
137     return 1;
138 }
139
140 /*****************************************************************************
141  * MP4_NextBox : Go to the next box
142  *****************************************************************************
143  * if p_box == NULL, go to the next box in which we are( at the begining ).
144  *****************************************************************************/
145 static int MP4_NextBox( stream_t *p_stream, MP4_Box_t *p_box )
146 {
147     MP4_Box_t box;
148
149     if( !p_box )
150     {
151         MP4_ReadBoxCommon( p_stream, &box );
152         p_box = &box;
153     }
154
155     if( !p_box->i_size )
156     {
157         return 2; /* Box with infinite size */
158     }
159
160     if( p_box->p_father )
161     {
162         /* if father's size == 0, it means unknown or infinite size,
163          * and we skip the followong check */
164         if( p_box->p_father->i_size > 0 )
165         {
166             const off_t i_box_end = p_box->i_size + p_box->i_pos;
167             const off_t i_father_end = p_box->p_father->i_size + p_box->p_father->i_pos;
168
169             /* check if it's within p-father */
170             if( i_box_end >= i_father_end )
171             {
172                 if( i_box_end > i_father_end )
173                     msg_Dbg( p_stream, "out of bound child" );
174                 return 0; /* out of bound */
175             }
176         }
177     }
178     if( stream_Seek( p_stream, p_box->i_size + p_box->i_pos ) )
179     {
180         return 0;
181     }
182
183     return 1;
184 }
185
186 /*****************************************************************************
187  * For all known box a loader is given,
188  *  XXX: all common struct have to be already read by MP4_ReadBoxCommon
189  *       after called one of theses functions, file position is unknown
190  *       you need to call MP4_GotoBox to go where you want
191  *****************************************************************************/
192 static int MP4_ReadBoxContainerChildren( stream_t *p_stream,
193                                     MP4_Box_t *p_container, uint32_t i_last_child )
194 {
195     MP4_Box_t *p_box;
196
197     /* Size of root container is set to 0 when unknown, for exemple
198      * with a DASH stream. In that case, we skip the following check */
199     if( p_container->i_size
200             && ( stream_Tell( p_stream ) + 8 >
201         (off_t)(p_container->i_pos + p_container->i_size) )
202       )
203     {
204         /* there is no box to load */
205         return 0;
206     }
207
208     do
209     {
210         if( ( p_box = MP4_ReadBox( p_stream, p_container ) ) == NULL ) break;
211
212         /* chain this box with the father and the other at same level */
213         if( !p_container->p_first ) p_container->p_first = p_box;
214         else p_container->p_last->p_next = p_box;
215         p_container->p_last = p_box;
216
217         if( p_box->i_type == i_last_child )
218         {
219             MP4_NextBox( p_stream, p_box );
220             break;
221         }
222
223     } while( MP4_NextBox( p_stream, p_box ) == 1 );
224
225     return 1;
226 }
227
228 static int MP4_ReadBoxContainerRaw( stream_t *p_stream, MP4_Box_t *p_container )
229 {
230     return MP4_ReadBoxContainerChildren( p_stream, p_container, 0 );
231 }
232
233 static int MP4_ReadBoxContainer( stream_t *p_stream, MP4_Box_t *p_container )
234 {
235     if( p_container->i_size &&
236         ( p_container->i_size <= (size_t)mp4_box_headersize(p_container ) + 8 ) )
237     {
238         /* container is empty, 8 stand for the first header in this box */
239         return 1;
240     }
241
242     /* enter box */
243     stream_Seek( p_stream, p_container->i_pos +
244                  mp4_box_headersize( p_container ) );
245
246     return MP4_ReadBoxContainerRaw( p_stream, p_container );
247 }
248
249 static void MP4_FreeBox_Common( MP4_Box_t *p_box )
250 {
251     /* Up to now do nothing */
252     (void)p_box;
253 }
254
255 static int MP4_ReadBoxSkip( stream_t *p_stream, MP4_Box_t *p_box )
256 {
257     /* XXX sometime moov is hiden in a free box */
258     if( p_box->p_father &&
259         p_box->p_father->i_type == ATOM_root &&
260         p_box->i_type == ATOM_free )
261     {
262         const uint8_t *p_peek;
263         int     i_read;
264         vlc_fourcc_t i_fcc;
265
266         i_read  = stream_Peek( p_stream, &p_peek, 44 );
267
268         p_peek += mp4_box_headersize( p_box ) + 4;
269         i_read -= mp4_box_headersize( p_box ) + 4;
270
271         if( i_read >= 8 )
272         {
273             i_fcc = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] );
274
275             if( i_fcc == ATOM_cmov || i_fcc == ATOM_mvhd )
276             {
277                 msg_Warn( p_stream, "detected moov hidden in a free box ..." );
278
279                 p_box->i_type = ATOM_foov;
280                 return MP4_ReadBoxContainer( p_stream, p_box );
281             }
282         }
283     }
284
285     /* Nothing to do */
286 #ifdef MP4_VERBOSE
287     if MP4_BOX_TYPE_ASCII()
288         msg_Dbg( p_stream, "skip box: \"%4.4s\"", (char*)&p_box->i_type );
289     else
290         msg_Dbg( p_stream, "skip box: \"c%3.3s\"", (char*)&p_box->i_type+1 );
291 #endif
292     return 1;
293 }
294
295 static int MP4_ReadBox_ftyp( stream_t *p_stream, MP4_Box_t *p_box )
296 {
297     MP4_READBOX_ENTER( MP4_Box_data_ftyp_t );
298
299     MP4_GETFOURCC( p_box->data.p_ftyp->i_major_brand );
300     MP4_GET4BYTES( p_box->data.p_ftyp->i_minor_version );
301
302     if( ( p_box->data.p_ftyp->i_compatible_brands_count = i_read / 4 ) )
303     {
304         uint32_t *tab = p_box->data.p_ftyp->i_compatible_brands =
305             calloc( p_box->data.p_ftyp->i_compatible_brands_count,
306                     sizeof(uint32_t));
307
308         if( unlikely( tab == NULL ) )
309             MP4_READBOX_EXIT( 0 );
310
311         for( unsigned i = 0; i < p_box->data.p_ftyp->i_compatible_brands_count; i++ )
312         {
313             MP4_GETFOURCC( tab[i] );
314         }
315     }
316     else
317     {
318         p_box->data.p_ftyp->i_compatible_brands = NULL;
319     }
320
321     MP4_READBOX_EXIT( 1 );
322 }
323
324 static void MP4_FreeBox_ftyp( MP4_Box_t *p_box )
325 {
326     FREENULL( p_box->data.p_ftyp->i_compatible_brands );
327 }
328
329
330 static int MP4_ReadBox_mvhd(  stream_t *p_stream, MP4_Box_t *p_box )
331 {
332 #ifdef MP4_VERBOSE
333     char s_creation_time[128];
334     char s_modification_time[128];
335     char s_duration[128];
336 #endif
337     MP4_READBOX_ENTER( MP4_Box_data_mvhd_t );
338
339     MP4_GETVERSIONFLAGS( p_box->data.p_mvhd );
340
341     if( p_box->data.p_mvhd->i_version )
342     {
343         MP4_GET8BYTES( p_box->data.p_mvhd->i_creation_time );
344         MP4_GET8BYTES( p_box->data.p_mvhd->i_modification_time );
345         MP4_GET4BYTES( p_box->data.p_mvhd->i_timescale );
346         MP4_GET8BYTES( p_box->data.p_mvhd->i_duration );
347     }
348     else
349     {
350         MP4_GET4BYTES( p_box->data.p_mvhd->i_creation_time );
351         MP4_GET4BYTES( p_box->data.p_mvhd->i_modification_time );
352         MP4_GET4BYTES( p_box->data.p_mvhd->i_timescale );
353         MP4_GET4BYTES( p_box->data.p_mvhd->i_duration );
354     }
355     MP4_GET4BYTES( p_box->data.p_mvhd->i_rate );
356     MP4_GET2BYTES( p_box->data.p_mvhd->i_volume );
357     MP4_GET2BYTES( p_box->data.p_mvhd->i_reserved1 );
358
359
360     for( unsigned i = 0; i < 2; i++ )
361     {
362         MP4_GET4BYTES( p_box->data.p_mvhd->i_reserved2[i] );
363     }
364     for( unsigned i = 0; i < 9; i++ )
365     {
366         MP4_GET4BYTES( p_box->data.p_mvhd->i_matrix[i] );
367     }
368     for( unsigned i = 0; i < 6; i++ )
369     {
370         MP4_GET4BYTES( p_box->data.p_mvhd->i_predefined[i] );
371     }
372
373     MP4_GET4BYTES( p_box->data.p_mvhd->i_next_track_id );
374
375
376 #ifdef MP4_VERBOSE
377     MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mvhd->i_creation_time );
378     MP4_ConvertDate2Str( s_modification_time,
379                          p_box->data.p_mvhd->i_modification_time );
380     if( p_box->data.p_mvhd->i_rate )
381     {
382         MP4_ConvertDate2Str( s_duration,
383                  p_box->data.p_mvhd->i_duration / p_box->data.p_mvhd->i_rate );
384     }
385     else
386     {
387         s_duration[0] = 0;
388     }
389     msg_Dbg( p_stream, "read box: \"mvhd\" creation %s modification %s time scale %d duration %s rate %f volume %f next track id %d",
390                   s_creation_time,
391                   s_modification_time,
392                   (uint32_t)p_box->data.p_mvhd->i_timescale,
393                   s_duration,
394                   (float)p_box->data.p_mvhd->i_rate / (1<<16 ),
395                   (float)p_box->data.p_mvhd->i_volume / 256 ,
396                   (uint32_t)p_box->data.p_mvhd->i_next_track_id );
397 #endif
398     MP4_READBOX_EXIT( 1 );
399 }
400
401 static int MP4_ReadBox_mfhd(  stream_t *p_stream, MP4_Box_t *p_box )
402 {
403     MP4_READBOX_ENTER( MP4_Box_data_mfhd_t );
404
405     MP4_GETVERSIONFLAGS( p_box->data.p_mvhd );
406
407     MP4_GET4BYTES( p_box->data.p_mfhd->i_sequence_number );
408
409 #ifdef MP4_VERBOSE
410     msg_Dbg( p_stream, "read box: \"mfhd\" sequence number %d",
411                   p_box->data.p_mfhd->i_sequence_number );
412 #endif
413     MP4_READBOX_EXIT( 1 );
414 }
415
416 static int MP4_ReadBox_tfxd(  stream_t *p_stream, MP4_Box_t *p_box )
417 {
418     MP4_READBOX_ENTER( MP4_Box_data_tfxd_t );
419
420     MP4_Box_data_tfxd_t *p_tfxd_data = p_box->data.p_tfxd;
421     MP4_GETVERSIONFLAGS( p_tfxd_data );
422
423     if( p_tfxd_data->i_version == 0 )
424     {
425         MP4_GET4BYTES( p_tfxd_data->i_fragment_abs_time );
426         MP4_GET4BYTES( p_tfxd_data->i_fragment_duration );
427     }
428     else
429     {
430         MP4_GET8BYTES( p_tfxd_data->i_fragment_abs_time );
431         MP4_GET8BYTES( p_tfxd_data->i_fragment_duration );
432     }
433
434 #ifdef MP4_VERBOSE
435     msg_Dbg( p_stream, "read box: \"tfxd\" version %d, flags 0x%x, "\
436             "fragment duration %"PRIu64", fragment abs time %"PRIu64,
437                 p_tfxd_data->i_version,
438                 p_tfxd_data->i_flags,
439                 p_tfxd_data->i_fragment_duration,
440                 p_tfxd_data->i_fragment_abs_time
441            );
442 #endif
443
444     MP4_READBOX_EXIT( 1 );
445 }
446
447 static int MP4_ReadBox_tfrf(  stream_t *p_stream, MP4_Box_t *p_box )
448 {
449     MP4_READBOX_ENTER( MP4_Box_data_tfxd_t );
450
451     MP4_Box_data_tfrf_t *p_tfrf_data = p_box->data.p_tfrf;
452     MP4_GETVERSIONFLAGS( p_tfrf_data );
453
454     MP4_GET1BYTE( p_tfrf_data->i_fragment_count );
455
456     p_tfrf_data->p_tfrf_data_fields = calloc( p_tfrf_data->i_fragment_count,
457                                               sizeof( TfrfBoxDataFields_t ) );
458     if( !p_tfrf_data->p_tfrf_data_fields )
459         MP4_READBOX_EXIT( 0 );
460
461     for( uint8_t i = 0; i < p_tfrf_data->i_fragment_count; i++ )
462     {
463         TfrfBoxDataFields_t *TfrfBoxDataField = &p_tfrf_data->p_tfrf_data_fields[i];
464         if( p_tfrf_data->i_version == 0 )
465         {
466             MP4_GET4BYTES( TfrfBoxDataField->i_fragment_abs_time );
467             MP4_GET4BYTES( TfrfBoxDataField->i_fragment_duration );
468         }
469         else
470         {
471             MP4_GET8BYTES( TfrfBoxDataField->i_fragment_abs_time );
472             MP4_GET8BYTES( TfrfBoxDataField->i_fragment_duration );
473         }
474     }
475
476 #ifdef MP4_VERBOSE
477     msg_Dbg( p_stream, "read box: \"tfrf\" version %d, flags 0x%x, "\
478             "fragment count %"PRIu8, p_tfrf_data->i_version,
479                 p_tfrf_data->i_flags, p_tfrf_data->i_fragment_count );
480
481     for( uint8_t i = 0; i < p_tfrf_data->i_fragment_count; i++ )
482     {
483         TfrfBoxDataFields_t *TfrfBoxDataField = &p_tfrf_data->p_tfrf_data_fields[i];
484         msg_Dbg( p_stream, "\"tfrf\" fragment duration %"PRIu64", "\
485                                     "fragment abs time %"PRIu64,
486                     TfrfBoxDataField->i_fragment_duration,
487                     TfrfBoxDataField->i_fragment_abs_time );
488     }
489
490 #endif
491
492     MP4_READBOX_EXIT( 1 );
493 }
494
495 static void MP4_FreeBox_tfrf( MP4_Box_t *p_box )
496 {
497     FREENULL( p_box->data.p_tfrf->p_tfrf_data_fields );
498 }
499
500 static int MP4_ReadBox_stra( stream_t *p_stream, MP4_Box_t *p_box )
501 {
502     MP4_READBOX_ENTER( MP4_Box_data_stra_t );
503     MP4_Box_data_stra_t *p_stra = p_box->data.p_stra;
504
505     uint8_t i_reserved;
506     VLC_UNUSED(i_reserved);
507     MP4_GET1BYTE( p_stra->i_es_cat );
508     MP4_GET1BYTE( i_reserved );
509     MP4_GET2BYTES( p_stra->i_track_ID );
510
511     MP4_GET4BYTES( p_stra->i_timescale );
512     MP4_GET8BYTES( p_stra->i_duration );
513
514     MP4_GET4BYTES( p_stra->FourCC );
515     MP4_GET4BYTES( p_stra->Bitrate );
516     MP4_GET4BYTES( p_stra->MaxWidth );
517     MP4_GET4BYTES( p_stra->MaxHeight );
518     MP4_GET4BYTES( p_stra->SamplingRate );
519     MP4_GET4BYTES( p_stra->Channels );
520     MP4_GET4BYTES( p_stra->BitsPerSample );
521     MP4_GET4BYTES( p_stra->AudioTag );
522     MP4_GET2BYTES( p_stra->nBlockAlign );
523
524     MP4_GET1BYTE( i_reserved );
525     MP4_GET1BYTE( i_reserved );
526     MP4_GET1BYTE( i_reserved );
527     MP4_GET1BYTE( p_stra->cpd_len );
528     if( p_stra->cpd_len > i_read )
529         goto error;
530     p_stra->CodecPrivateData = malloc( p_stra->cpd_len );
531     if( unlikely( p_stra->CodecPrivateData == NULL ) )
532         goto error;
533     memcpy( p_stra->CodecPrivateData, p_peek, p_stra->cpd_len );
534
535 #ifdef MP4_VERBOSE
536     msg_Dbg( p_stream, "es_cat is %"PRIu8", birate is %"PRIu32,
537               p_stra->i_es_cat, p_stra->Bitrate );
538 #endif
539
540     MP4_READBOX_EXIT( 1 );
541 error:
542     MP4_READBOX_EXIT( 0 );
543 }
544
545 static void MP4_FreeBox_stra( MP4_Box_t *p_box )
546 {
547     FREENULL( p_box->data.p_stra->CodecPrivateData );
548 }
549
550 static int MP4_ReadBox_uuid( stream_t *p_stream, MP4_Box_t *p_box )
551 {
552     if( !CmpUUID( &p_box->i_uuid, &TfrfBoxUUID ) )
553         return MP4_ReadBox_tfrf( p_stream, p_box );
554     if( !CmpUUID( &p_box->i_uuid, &TfxdBoxUUID ) )
555         return MP4_ReadBox_tfxd( p_stream, p_box );
556     if( !CmpUUID( &p_box->i_uuid, &SmooBoxUUID ) )
557         return MP4_ReadBoxContainer( p_stream, p_box );
558     if( !CmpUUID( &p_box->i_uuid, &StraBoxUUID ) )
559         return MP4_ReadBox_stra( p_stream, p_box );
560
561     msg_Warn( p_stream, "Unknown uuid type box" );
562     return 1;
563 }
564
565 static void MP4_FreeBox_uuid( MP4_Box_t *p_box )
566 {
567     if( !CmpUUID( &p_box->i_uuid, &TfrfBoxUUID ) )
568         return MP4_FreeBox_tfrf( p_box );
569     if( !CmpUUID( &p_box->i_uuid, &TfxdBoxUUID ) )
570         return MP4_FreeBox_Common( p_box );
571     if( !CmpUUID( &p_box->i_uuid, &SmooBoxUUID ) )
572         return MP4_FreeBox_Common( p_box );
573     if( !CmpUUID( &p_box->i_uuid, &StraBoxUUID ) )
574         return MP4_FreeBox_stra( p_box );
575 }
576
577 static int MP4_ReadBox_sidx(  stream_t *p_stream, MP4_Box_t *p_box )
578 {
579     MP4_READBOX_ENTER( MP4_Box_data_sidx_t );
580
581     MP4_Box_data_sidx_t *p_sidx_data = p_box->data.p_sidx;
582     MP4_GETVERSIONFLAGS( p_sidx_data );
583
584     MP4_GET4BYTES( p_sidx_data->i_reference_ID );
585     MP4_GET4BYTES( p_sidx_data->i_timescale );
586
587     if( p_sidx_data->i_version == 0 )
588     {
589         MP4_GET4BYTES( p_sidx_data->i_earliest_presentation_time );
590         MP4_GET4BYTES( p_sidx_data->i_first_offset );
591     }
592     else
593     {
594         MP4_GET8BYTES( p_sidx_data->i_earliest_presentation_time );
595         MP4_GET8BYTES( p_sidx_data->i_first_offset );
596     }
597
598     uint16_t i_reserved;
599     VLC_UNUSED(i_reserved);
600     MP4_GET2BYTES( i_reserved );
601     MP4_GET2BYTES( p_sidx_data->i_reference_count );
602     uint16_t i_count = p_sidx_data->i_reference_count;
603
604     p_sidx_data->p_items = calloc( i_count, sizeof( MP4_Box_sidx_item_t ) );
605     uint32_t tmp;
606     for( unsigned i = 0; i < i_count; i++ )
607     {
608         MP4_GET4BYTES( tmp );
609         p_sidx_data->p_items[i].b_reference_type = (bool)((tmp & 0x80000000)>>24);
610         p_sidx_data->p_items[i].i_referenced_size = tmp & 0x7fffffff;
611         MP4_GET4BYTES( p_sidx_data->p_items[i].i_subsegment_duration );
612
613         MP4_GET4BYTES( tmp );
614         p_sidx_data->p_items[i].b_starts_with_SAP = (bool)((tmp & 0x80000000)>>24);
615         p_sidx_data->p_items[i].i_SAP_type = (tmp & 0x70000000)>>24;
616         p_sidx_data->p_items[i].i_SAP_delta_time = tmp & 0xfffffff;
617     }
618
619 #ifdef MP4_VERBOSE
620     msg_Dbg( p_stream, "read box: \"sidx\" version %d, flags 0x%x, "\
621             "ref_ID %"PRIu32", timescale %"PRIu32", ref_count %"PRIu16", "\
622             "first subsegmt duration %"PRIu32,
623                 p_sidx_data->i_version,
624                 p_sidx_data->i_flags,
625                 p_sidx_data->i_reference_ID,
626                 p_sidx_data->i_timescale,
627                 p_sidx_data->i_reference_count,
628                 p_sidx_data->p_items[0].i_subsegment_duration
629            );
630 #endif
631
632     MP4_READBOX_EXIT( 1 );
633 }
634
635 static void MP4_FreeBox_sidx( MP4_Box_t *p_box )
636 {
637     FREENULL( p_box->data.p_sidx->p_items );
638 }
639
640 static int MP4_ReadBox_tfhd(  stream_t *p_stream, MP4_Box_t *p_box )
641 {
642     MP4_READBOX_ENTER( MP4_Box_data_tfhd_t );
643
644     MP4_GETVERSIONFLAGS( p_box->data.p_tfhd );
645
646     if( p_box->data.p_tfhd->i_version != 0 )
647     {
648         msg_Warn( p_stream, "'tfhd' box with version != 0. "\
649                 " Don't know what to do with that, please patch" );
650         MP4_READBOX_EXIT( 0 );
651     }
652
653     MP4_GET4BYTES( p_box->data.p_tfhd->i_track_ID );
654
655     if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DURATION_IS_EMPTY )
656     {
657         msg_Dbg( p_stream, "'duration-is-empty' flag is present "\
658                 "=> no samples for this time interval." );
659         p_box->data.p_tfhd->b_empty = true;
660     }
661     else
662         p_box->data.p_tfhd->b_empty = false;
663
664     if( p_box->data.p_tfhd->i_flags & MP4_TFHD_BASE_DATA_OFFSET )
665         MP4_GET8BYTES( p_box->data.p_tfhd->i_base_data_offset );
666     if( p_box->data.p_tfhd->i_flags & MP4_TFHD_SAMPLE_DESC_INDEX )
667         MP4_GET4BYTES( p_box->data.p_tfhd->i_sample_description_index );
668     if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_DURATION )
669         MP4_GET4BYTES( p_box->data.p_tfhd->i_default_sample_duration );
670     if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_SIZE )
671         MP4_GET4BYTES( p_box->data.p_tfhd->i_default_sample_size );
672     if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_FLAGS )
673         MP4_GET4BYTES( p_box->data.p_tfhd->i_default_sample_flags );
674
675 #ifdef MP4_VERBOSE
676     char psz_base[128] = "\0";
677     char psz_desc[128] = "\0";
678     char psz_dura[128] = "\0";
679     char psz_size[128] = "\0";
680     char psz_flag[128] = "\0";
681     if( p_box->data.p_tfhd->i_flags & MP4_TFHD_BASE_DATA_OFFSET )
682         snprintf(psz_base, sizeof(psz_base), "base offset %"PRId64, p_box->data.p_tfhd->i_base_data_offset);
683     if( p_box->data.p_tfhd->i_flags & MP4_TFHD_SAMPLE_DESC_INDEX )
684         snprintf(psz_desc, sizeof(psz_desc), "sample description index %d", p_box->data.p_tfhd->i_sample_description_index);
685     if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_DURATION )
686         snprintf(psz_dura, sizeof(psz_dura), "sample duration %d", p_box->data.p_tfhd->i_default_sample_duration);
687     if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_SIZE )
688         snprintf(psz_size, sizeof(psz_size), "sample size %d", p_box->data.p_tfhd->i_default_sample_size);
689     if( p_box->data.p_tfhd->i_flags & MP4_TFHD_DFLT_SAMPLE_FLAGS )
690         snprintf(psz_flag, sizeof(psz_flag), "sample flags 0x%x", p_box->data.p_tfhd->i_default_sample_flags);
691
692     msg_Dbg( p_stream, "read box: \"tfhd\" version %d flags 0x%x track ID %d %s %s %s %s %s",
693                 p_box->data.p_tfhd->i_version,
694                 p_box->data.p_tfhd->i_flags,
695                 p_box->data.p_tfhd->i_track_ID,
696                 psz_base, psz_desc, psz_dura, psz_size, psz_flag );
697 #endif
698
699     MP4_READBOX_EXIT( 1 );
700 }
701
702 static int MP4_ReadBox_trun(  stream_t *p_stream, MP4_Box_t *p_box )
703 {
704     MP4_READBOX_ENTER( MP4_Box_data_trun_t );
705
706     MP4_GETVERSIONFLAGS( p_box->data.p_trun );
707
708     MP4_GET4BYTES( p_box->data.p_trun->i_sample_count );
709
710     if( p_box->data.p_trun->i_flags & MP4_TRUN_DATA_OFFSET )
711         MP4_GET4BYTES( p_box->data.p_trun->i_data_offset );
712     if( p_box->data.p_trun->i_flags & MP4_TRUN_FIRST_FLAGS )
713         MP4_GET4BYTES( p_box->data.p_trun->i_first_sample_flags );
714
715     p_box->data.p_trun->p_samples =
716       calloc( p_box->data.p_trun->i_sample_count, sizeof(MP4_descriptor_trun_sample_t) );
717     if ( p_box->data.p_trun->p_samples == NULL )
718         MP4_READBOX_EXIT( 0 );
719
720     for( unsigned int i = 0; i<p_box->data.p_trun->i_sample_count; i++ )
721     {
722         MP4_descriptor_trun_sample_t *p_sample = &p_box->data.p_trun->p_samples[i];
723         if( p_box->data.p_trun->i_flags & MP4_TRUN_SAMPLE_DURATION )
724             MP4_GET4BYTES( p_sample->i_duration );
725         if( p_box->data.p_trun->i_flags & MP4_TRUN_SAMPLE_SIZE )
726             MP4_GET4BYTES( p_sample->i_size );
727         if( p_box->data.p_trun->i_flags & MP4_TRUN_SAMPLE_FLAGS )
728             MP4_GET4BYTES( p_sample->i_flags );
729         if( p_box->data.p_trun->i_flags & MP4_TRUN_SAMPLE_TIME_OFFSET )
730             MP4_GET4BYTES( p_sample->i_composition_time_offset );
731     }
732
733 #ifdef MP4_VERBOSE
734     msg_Dbg( p_stream, "read box: \"trun\" version %u flags 0x%x sample count %u",
735                   p_box->data.p_trun->i_version,
736                   p_box->data.p_trun->i_flags,
737                   p_box->data.p_trun->i_sample_count );
738
739     for( unsigned int i = 0; i<p_box->data.p_trun->i_sample_count; i++ )
740     {
741         MP4_descriptor_trun_sample_t *p_sample = &p_box->data.p_trun->p_samples[i];
742         msg_Dbg( p_stream, "read box: \"trun\" sample %4.4u flags 0x%x "\
743             "duration %"PRIu32" size %"PRIu32" composition time offset %"PRIu32,
744                         i, p_sample->i_flags, p_sample->i_duration,
745                         p_sample->i_size, p_sample->i_composition_time_offset );
746     }
747 #endif
748
749     MP4_READBOX_EXIT( 1 );
750 }
751
752 static void MP4_FreeBox_trun( MP4_Box_t *p_box )
753 {
754     FREENULL( p_box->data.p_trun->p_samples );
755 }
756
757
758 static int MP4_ReadBox_tkhd(  stream_t *p_stream, MP4_Box_t *p_box )
759 {
760 #ifdef MP4_VERBOSE
761     char s_creation_time[128];
762     char s_modification_time[128];
763     char s_duration[128];
764 #endif
765     MP4_READBOX_ENTER( MP4_Box_data_tkhd_t );
766
767     MP4_GETVERSIONFLAGS( p_box->data.p_tkhd );
768
769     if( p_box->data.p_tkhd->i_version )
770     {
771         MP4_GET8BYTES( p_box->data.p_tkhd->i_creation_time );
772         MP4_GET8BYTES( p_box->data.p_tkhd->i_modification_time );
773         MP4_GET4BYTES( p_box->data.p_tkhd->i_track_ID );
774         MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved );
775         MP4_GET8BYTES( p_box->data.p_tkhd->i_duration );
776     }
777     else
778     {
779         MP4_GET4BYTES( p_box->data.p_tkhd->i_creation_time );
780         MP4_GET4BYTES( p_box->data.p_tkhd->i_modification_time );
781         MP4_GET4BYTES( p_box->data.p_tkhd->i_track_ID );
782         MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved );
783         MP4_GET4BYTES( p_box->data.p_tkhd->i_duration );
784     }
785
786     for( unsigned i = 0; i < 2; i++ )
787     {
788         MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved2[i] );
789     }
790     MP4_GET2BYTES( p_box->data.p_tkhd->i_layer );
791     MP4_GET2BYTES( p_box->data.p_tkhd->i_predefined );
792     MP4_GET2BYTES( p_box->data.p_tkhd->i_volume );
793     MP4_GET2BYTES( p_box->data.p_tkhd->i_reserved3 );
794
795     for( unsigned i = 0; i < 9; i++ )
796     {
797         MP4_GET4BYTES( p_box->data.p_tkhd->i_matrix[i] );
798     }
799     MP4_GET4BYTES( p_box->data.p_tkhd->i_width );
800     MP4_GET4BYTES( p_box->data.p_tkhd->i_height );
801
802     double rotation;    //angle in degrees to be rotated clockwise
803     double scale[2];    // scale factor; sx = scale[0] , sy = scale[1]
804     double translate[2];// amount to translate; tx = translate[0] , ty = translate[1]
805
806     int32_t *matrix = p_box->data.p_tkhd->i_matrix;
807
808     translate[0] = conv_fx(matrix[6]);
809     translate[1] = conv_fx(matrix[7]);
810
811     scale[0] = sqrt(conv_fx(matrix[0]) * conv_fx(matrix[0]) +
812                     conv_fx(matrix[3]) * conv_fx(matrix[3]));
813     scale[1] = sqrt(conv_fx(matrix[1]) * conv_fx(matrix[1]) +
814                     conv_fx(matrix[4]) * conv_fx(matrix[4]));
815
816     rotation = atan2(conv_fx(matrix[1]) / scale[1], conv_fx(matrix[0]) / scale[0]) * 180 / M_PI;
817
818     if (rotation < 0)
819         rotation += 360.;
820
821     p_box->data.p_tkhd->f_rotation = rotation;
822
823 #ifdef MP4_VERBOSE
824     MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mvhd->i_creation_time );
825     MP4_ConvertDate2Str( s_modification_time, p_box->data.p_mvhd->i_modification_time );
826     MP4_ConvertDate2Str( s_duration, p_box->data.p_mvhd->i_duration );
827
828     msg_Dbg( p_stream, "read box: \"tkhd\" creation %s modification %s duration %s track ID %d layer %d volume %f rotation %f scaleX %f scaleY %f translateX %f translateY %f width %f height %f. "
829             "Matrix: %i %i %i %i %i %i %i %i %i",
830                   s_creation_time,
831                   s_modification_time,
832                   s_duration,
833                   p_box->data.p_tkhd->i_track_ID,
834                   p_box->data.p_tkhd->i_layer,
835                   (float)p_box->data.p_tkhd->i_volume / 256 ,
836                   rotation,
837                   scale[0],
838                   scale[1],
839                   translate[0],
840                   translate[1],
841                   (float)p_box->data.p_tkhd->i_width / 65536,
842                   (float)p_box->data.p_tkhd->i_height / 65536,
843                   p_box->data.p_tkhd->i_matrix[0],
844                   p_box->data.p_tkhd->i_matrix[1],
845                   p_box->data.p_tkhd->i_matrix[2],
846                   p_box->data.p_tkhd->i_matrix[3],
847                   p_box->data.p_tkhd->i_matrix[4],
848                   p_box->data.p_tkhd->i_matrix[5],
849                   p_box->data.p_tkhd->i_matrix[6],
850                   p_box->data.p_tkhd->i_matrix[7],
851                   p_box->data.p_tkhd->i_matrix[8] );
852 #endif
853     MP4_READBOX_EXIT( 1 );
854 }
855
856
857 static int MP4_ReadBox_mdhd( stream_t *p_stream, MP4_Box_t *p_box )
858 {
859     uint16_t i_language;
860 #ifdef MP4_VERBOSE
861     char s_creation_time[128];
862     char s_modification_time[128];
863     char s_duration[128];
864 #endif
865     MP4_READBOX_ENTER( MP4_Box_data_mdhd_t );
866
867     MP4_GETVERSIONFLAGS( p_box->data.p_mdhd );
868
869     if( p_box->data.p_mdhd->i_version )
870     {
871         MP4_GET8BYTES( p_box->data.p_mdhd->i_creation_time );
872         MP4_GET8BYTES( p_box->data.p_mdhd->i_modification_time );
873         MP4_GET4BYTES( p_box->data.p_mdhd->i_timescale );
874         MP4_GET8BYTES( p_box->data.p_mdhd->i_duration );
875     }
876     else
877     {
878         MP4_GET4BYTES( p_box->data.p_mdhd->i_creation_time );
879         MP4_GET4BYTES( p_box->data.p_mdhd->i_modification_time );
880         MP4_GET4BYTES( p_box->data.p_mdhd->i_timescale );
881         MP4_GET4BYTES( p_box->data.p_mdhd->i_duration );
882     }
883     p_box->data.p_mdhd->i_language_code = i_language = GetWBE( p_peek );
884     for( unsigned i = 0; i < 3; i++ )
885     {
886         p_box->data.p_mdhd->i_language[i] =
887                     ( ( i_language >> ( (2-i)*5 ) )&0x1f ) + 0x60;
888     }
889
890     MP4_GET2BYTES( p_box->data.p_mdhd->i_predefined );
891
892 #ifdef MP4_VERBOSE
893     MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mdhd->i_creation_time );
894     MP4_ConvertDate2Str( s_modification_time, p_box->data.p_mdhd->i_modification_time );
895     MP4_ConvertDate2Str( s_duration, p_box->data.p_mdhd->i_duration );
896     msg_Dbg( p_stream, "read box: \"mdhd\" creation %s modification %s time scale %d duration %s language %c%c%c",
897                   s_creation_time,
898                   s_modification_time,
899                   (uint32_t)p_box->data.p_mdhd->i_timescale,
900                   s_duration,
901                   p_box->data.p_mdhd->i_language[0],
902                   p_box->data.p_mdhd->i_language[1],
903                   p_box->data.p_mdhd->i_language[2] );
904 #endif
905     MP4_READBOX_EXIT( 1 );
906 }
907
908
909 static int MP4_ReadBox_hdlr( stream_t *p_stream, MP4_Box_t *p_box )
910 {
911     int32_t i_reserved;
912     VLC_UNUSED(i_reserved);
913
914     MP4_READBOX_ENTER( MP4_Box_data_hdlr_t );
915
916     MP4_GETVERSIONFLAGS( p_box->data.p_hdlr );
917
918     MP4_GETFOURCC( p_box->data.p_hdlr->i_predefined );
919     MP4_GETFOURCC( p_box->data.p_hdlr->i_handler_type );
920
921     MP4_GET4BYTES( i_reserved );
922     MP4_GET4BYTES( i_reserved );
923     MP4_GET4BYTES( i_reserved );
924     p_box->data.p_hdlr->psz_name = NULL;
925
926     if( i_read > 0 )
927     {
928         uint8_t *psz = p_box->data.p_hdlr->psz_name = malloc( i_read + 1 );
929         if( unlikely( psz == NULL ) )
930             MP4_READBOX_EXIT( 0 );
931
932         /* Yes, I love .mp4 :( */
933         if( p_box->data.p_hdlr->i_predefined == VLC_FOURCC( 'm', 'h', 'l', 'r' ) )
934         {
935             uint8_t i_len;
936             int i_copy;
937
938             MP4_GET1BYTE( i_len );
939             i_copy = __MIN( i_read, i_len );
940
941             memcpy( psz, p_peek, i_copy );
942             p_box->data.p_hdlr->psz_name[i_copy] = '\0';
943         }
944         else
945         {
946             memcpy( psz, p_peek, i_read );
947             p_box->data.p_hdlr->psz_name[i_read] = '\0';
948         }
949     }
950
951 #ifdef MP4_VERBOSE
952         msg_Dbg( p_stream, "read box: \"hdlr\" handler type: \"%4.4s\" name: \"%s\"",
953                    (char*)&p_box->data.p_hdlr->i_handler_type,
954                    p_box->data.p_hdlr->psz_name );
955
956 #endif
957     MP4_READBOX_EXIT( 1 );
958 }
959
960 static void MP4_FreeBox_hdlr( MP4_Box_t *p_box )
961 {
962     FREENULL( p_box->data.p_hdlr->psz_name );
963 }
964
965 static int MP4_ReadBox_vmhd( stream_t *p_stream, MP4_Box_t *p_box )
966 {
967     MP4_READBOX_ENTER( MP4_Box_data_vmhd_t );
968
969     MP4_GETVERSIONFLAGS( p_box->data.p_vmhd );
970
971     MP4_GET2BYTES( p_box->data.p_vmhd->i_graphics_mode );
972     for( unsigned i = 0; i < 3; i++ )
973     {
974         MP4_GET2BYTES( p_box->data.p_vmhd->i_opcolor[i] );
975     }
976
977 #ifdef MP4_VERBOSE
978     msg_Dbg( p_stream, "read box: \"vmhd\" graphics-mode %d opcolor (%d, %d, %d)",
979                       p_box->data.p_vmhd->i_graphics_mode,
980                       p_box->data.p_vmhd->i_opcolor[0],
981                       p_box->data.p_vmhd->i_opcolor[1],
982                       p_box->data.p_vmhd->i_opcolor[2] );
983 #endif
984     MP4_READBOX_EXIT( 1 );
985 }
986
987 static int MP4_ReadBox_smhd( stream_t *p_stream, MP4_Box_t *p_box )
988 {
989     MP4_READBOX_ENTER( MP4_Box_data_smhd_t );
990
991     MP4_GETVERSIONFLAGS( p_box->data.p_smhd );
992
993
994
995     MP4_GET2BYTES( p_box->data.p_smhd->i_balance );
996
997     MP4_GET2BYTES( p_box->data.p_smhd->i_reserved );
998
999 #ifdef MP4_VERBOSE
1000     msg_Dbg( p_stream, "read box: \"smhd\" balance %f",
1001                       (float)p_box->data.p_smhd->i_balance / 256 );
1002 #endif
1003     MP4_READBOX_EXIT( 1 );
1004 }
1005
1006
1007 static int MP4_ReadBox_hmhd( stream_t *p_stream, MP4_Box_t *p_box )
1008 {
1009     MP4_READBOX_ENTER( MP4_Box_data_hmhd_t );
1010
1011     MP4_GETVERSIONFLAGS( p_box->data.p_hmhd );
1012
1013     MP4_GET2BYTES( p_box->data.p_hmhd->i_max_PDU_size );
1014     MP4_GET2BYTES( p_box->data.p_hmhd->i_avg_PDU_size );
1015
1016     MP4_GET4BYTES( p_box->data.p_hmhd->i_max_bitrate );
1017     MP4_GET4BYTES( p_box->data.p_hmhd->i_avg_bitrate );
1018
1019     MP4_GET4BYTES( p_box->data.p_hmhd->i_reserved );
1020
1021 #ifdef MP4_VERBOSE
1022     msg_Dbg( p_stream, "read box: \"hmhd\" maxPDU-size %d avgPDU-size %d max-bitrate %d avg-bitrate %d",
1023                       p_box->data.p_hmhd->i_max_PDU_size,
1024                       p_box->data.p_hmhd->i_avg_PDU_size,
1025                       p_box->data.p_hmhd->i_max_bitrate,
1026                       p_box->data.p_hmhd->i_avg_bitrate );
1027 #endif
1028     MP4_READBOX_EXIT( 1 );
1029 }
1030
1031 static int MP4_ReadBox_url( stream_t *p_stream, MP4_Box_t *p_box )
1032 {
1033     MP4_READBOX_ENTER( MP4_Box_data_url_t );
1034
1035     MP4_GETVERSIONFLAGS( p_box->data.p_url );
1036     MP4_GETSTRINGZ( p_box->data.p_url->psz_location );
1037
1038 #ifdef MP4_VERBOSE
1039     msg_Dbg( p_stream, "read box: \"url\" url: %s",
1040                        p_box->data.p_url->psz_location );
1041
1042 #endif
1043     MP4_READBOX_EXIT( 1 );
1044 }
1045
1046
1047 static void MP4_FreeBox_url( MP4_Box_t *p_box )
1048 {
1049     FREENULL( p_box->data.p_url->psz_location );
1050 }
1051
1052 static int MP4_ReadBox_urn( stream_t *p_stream, MP4_Box_t *p_box )
1053 {
1054     MP4_READBOX_ENTER( MP4_Box_data_urn_t );
1055
1056     MP4_GETVERSIONFLAGS( p_box->data.p_urn );
1057
1058     MP4_GETSTRINGZ( p_box->data.p_urn->psz_name );
1059     MP4_GETSTRINGZ( p_box->data.p_urn->psz_location );
1060
1061 #ifdef MP4_VERBOSE
1062     msg_Dbg( p_stream, "read box: \"urn\" name %s location %s",
1063                       p_box->data.p_urn->psz_name,
1064                       p_box->data.p_urn->psz_location );
1065 #endif
1066     MP4_READBOX_EXIT( 1 );
1067 }
1068 static void MP4_FreeBox_urn( MP4_Box_t *p_box )
1069 {
1070     FREENULL( p_box->data.p_urn->psz_name );
1071     FREENULL( p_box->data.p_urn->psz_location );
1072 }
1073
1074
1075 static int MP4_ReadBox_dref( stream_t *p_stream, MP4_Box_t *p_box )
1076 {
1077     MP4_READBOX_ENTER( MP4_Box_data_dref_t );
1078
1079     MP4_GETVERSIONFLAGS( p_box->data.p_dref );
1080
1081     MP4_GET4BYTES( p_box->data.p_dref->i_entry_count );
1082
1083     stream_Seek( p_stream, p_box->i_pos + mp4_box_headersize( p_box ) + 8 );
1084     MP4_ReadBoxContainerRaw( p_stream, p_box );
1085
1086 #ifdef MP4_VERBOSE
1087     msg_Dbg( p_stream, "read box: \"dref\" entry-count %d",
1088                       p_box->data.p_dref->i_entry_count );
1089
1090 #endif
1091     MP4_READBOX_EXIT( 1 );
1092 }
1093
1094 static void MP4_FreeBox_stts( MP4_Box_t *p_box )
1095 {
1096     FREENULL( p_box->data.p_stts->i_sample_count );
1097     FREENULL( p_box->data.p_stts->i_sample_delta );
1098 }
1099
1100 static int MP4_ReadBox_stts( stream_t *p_stream, MP4_Box_t *p_box )
1101 {
1102     MP4_READBOX_ENTER( MP4_Box_data_stts_t );
1103
1104     MP4_GETVERSIONFLAGS( p_box->data.p_stts );
1105     MP4_GET4BYTES( p_box->data.p_stts->i_entry_count );
1106
1107     p_box->data.p_stts->i_sample_count =
1108         calloc( p_box->data.p_stts->i_entry_count, sizeof(uint32_t) );
1109     p_box->data.p_stts->i_sample_delta =
1110         calloc( p_box->data.p_stts->i_entry_count, sizeof(int32_t) );
1111     if( p_box->data.p_stts->i_sample_count == NULL
1112      || p_box->data.p_stts->i_sample_delta == NULL )
1113     {
1114         MP4_READBOX_EXIT( 0 );
1115     }
1116
1117     for( unsigned int i = 0; (i < p_box->data.p_stts->i_entry_count )&&( i_read >=8 ); i++ )
1118     {
1119         MP4_GET4BYTES( p_box->data.p_stts->i_sample_count[i] );
1120         MP4_GET4BYTES( p_box->data.p_stts->i_sample_delta[i] );
1121     }
1122
1123 #ifdef MP4_VERBOSE
1124     msg_Dbg( p_stream, "read box: \"stts\" entry-count %d",
1125                       p_box->data.p_stts->i_entry_count );
1126
1127 #endif
1128     MP4_READBOX_EXIT( 1 );
1129 }
1130
1131
1132 static void MP4_FreeBox_ctts( MP4_Box_t *p_box )
1133 {
1134     FREENULL( p_box->data.p_ctts->i_sample_count );
1135     FREENULL( p_box->data.p_ctts->i_sample_offset );
1136 }
1137
1138 static int MP4_ReadBox_ctts( stream_t *p_stream, MP4_Box_t *p_box )
1139 {
1140     MP4_READBOX_ENTER( MP4_Box_data_ctts_t );
1141
1142     MP4_GETVERSIONFLAGS( p_box->data.p_ctts );
1143
1144     MP4_GET4BYTES( p_box->data.p_ctts->i_entry_count );
1145
1146     p_box->data.p_ctts->i_sample_count =
1147         calloc( p_box->data.p_ctts->i_entry_count, sizeof(uint32_t) );
1148     p_box->data.p_ctts->i_sample_offset =
1149         calloc( p_box->data.p_ctts->i_entry_count, sizeof(int32_t) );
1150     if( ( p_box->data.p_ctts->i_sample_count == NULL )
1151      || ( p_box->data.p_ctts->i_sample_offset == NULL ) )
1152     {
1153         MP4_READBOX_EXIT( 0 );
1154     }
1155
1156     for( unsigned int i = 0; (i < p_box->data.p_ctts->i_entry_count )&&( i_read >=8 ); i++ )
1157     {
1158         MP4_GET4BYTES( p_box->data.p_ctts->i_sample_count[i] );
1159         MP4_GET4BYTES( p_box->data.p_ctts->i_sample_offset[i] );
1160     }
1161
1162 #ifdef MP4_VERBOSE
1163     msg_Dbg( p_stream, "read box: \"ctts\" entry-count %d",
1164                       p_box->data.p_ctts->i_entry_count );
1165
1166 #endif
1167     MP4_READBOX_EXIT( 1 );
1168 }
1169
1170
1171 static int MP4_ReadLengthDescriptor( uint8_t **pp_peek, int64_t  *i_read )
1172 {
1173     unsigned int i_b;
1174     unsigned int i_len = 0;
1175     do
1176     {
1177         i_b = **pp_peek;
1178
1179         (*pp_peek)++;
1180         (*i_read)--;
1181         i_len = ( i_len << 7 ) + ( i_b&0x7f );
1182     } while( i_b&0x80 );
1183     return( i_len );
1184 }
1185
1186
1187 static void MP4_FreeBox_esds( MP4_Box_t *p_box )
1188 {
1189     FREENULL( p_box->data.p_esds->es_descriptor.psz_URL );
1190     if( p_box->data.p_esds->es_descriptor.p_decConfigDescr )
1191     {
1192         FREENULL( p_box->data.p_esds->es_descriptor.p_decConfigDescr->p_decoder_specific_info );
1193         FREENULL( p_box->data.p_esds->es_descriptor.p_decConfigDescr );
1194     }
1195 }
1196
1197 static int MP4_ReadBox_esds( stream_t *p_stream, MP4_Box_t *p_box )
1198 {
1199 #define es_descriptor p_box->data.p_esds->es_descriptor
1200     unsigned int i_len;
1201     unsigned int i_flags;
1202     unsigned int i_type;
1203
1204     MP4_READBOX_ENTER( MP4_Box_data_esds_t );
1205
1206     MP4_GETVERSIONFLAGS( p_box->data.p_esds );
1207
1208
1209     MP4_GET1BYTE( i_type );
1210     if( i_type == 0x03 ) /* MP4ESDescrTag */
1211     {
1212         i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
1213
1214 #ifdef MP4_VERBOSE
1215         msg_Dbg( p_stream, "found esds MPEG4ESDescr (%dBytes)",
1216                  i_len );
1217 #endif
1218
1219         MP4_GET2BYTES( es_descriptor.i_ES_ID );
1220         MP4_GET1BYTE( i_flags );
1221         es_descriptor.b_stream_dependence = ( (i_flags&0x80) != 0);
1222         es_descriptor.b_url = ( (i_flags&0x40) != 0);
1223         es_descriptor.b_OCRstream = ( (i_flags&0x20) != 0);
1224
1225         es_descriptor.i_stream_priority = i_flags&0x1f;
1226         if( es_descriptor.b_stream_dependence )
1227         {
1228             MP4_GET2BYTES( es_descriptor.i_depend_on_ES_ID );
1229         }
1230         if( es_descriptor.b_url )
1231         {
1232             unsigned int i_len;
1233
1234             MP4_GET1BYTE( i_len );
1235             es_descriptor.psz_URL = malloc( i_len + 1 );
1236             if( es_descriptor.psz_URL )
1237             {
1238                 memcpy( es_descriptor.psz_URL, p_peek, i_len );
1239                 es_descriptor.psz_URL[i_len] = 0;
1240             }
1241             p_peek += i_len;
1242             i_read -= i_len;
1243         }
1244         else
1245         {
1246             es_descriptor.psz_URL = NULL;
1247         }
1248         if( es_descriptor.b_OCRstream )
1249         {
1250             MP4_GET2BYTES( es_descriptor.i_OCR_ES_ID );
1251         }
1252         MP4_GET1BYTE( i_type ); /* get next type */
1253     }
1254
1255     if( i_type != 0x04)/* MP4DecConfigDescrTag */
1256     {
1257          es_descriptor.p_decConfigDescr = NULL;
1258          MP4_READBOX_EXIT( 1 ); /* rest isn't interesting up to now */
1259     }
1260
1261     i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
1262
1263 #ifdef MP4_VERBOSE
1264         msg_Dbg( p_stream, "found esds MP4DecConfigDescr (%dBytes)",
1265                  i_len );
1266 #endif
1267
1268     es_descriptor.p_decConfigDescr =
1269             calloc( 1, sizeof( MP4_descriptor_decoder_config_t ));
1270     if( unlikely( es_descriptor.p_decConfigDescr == NULL ) )
1271         MP4_READBOX_EXIT( 0 );
1272
1273     MP4_GET1BYTE( es_descriptor.p_decConfigDescr->i_objectTypeIndication );
1274     MP4_GET1BYTE( i_flags );
1275     es_descriptor.p_decConfigDescr->i_streamType = i_flags >> 2;
1276     es_descriptor.p_decConfigDescr->b_upStream = ( i_flags >> 1 )&0x01;
1277     MP4_GET3BYTES( es_descriptor.p_decConfigDescr->i_buffer_sizeDB );
1278     MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_max_bitrate );
1279     MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_avg_bitrate );
1280     MP4_GET1BYTE( i_type );
1281     if( i_type !=  0x05 )/* MP4DecSpecificDescrTag */
1282     {
1283         es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = 0;
1284         es_descriptor.p_decConfigDescr->p_decoder_specific_info  = NULL;
1285         MP4_READBOX_EXIT( 1 );
1286     }
1287
1288     i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
1289
1290 #ifdef MP4_VERBOSE
1291         msg_Dbg( p_stream, "found esds MP4DecSpecificDescr (%dBytes)",
1292                  i_len );
1293 #endif
1294     if( i_len > i_read )
1295         MP4_READBOX_EXIT( 0 );
1296
1297     es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = i_len;
1298     es_descriptor.p_decConfigDescr->p_decoder_specific_info = malloc( i_len );
1299     if( unlikely( es_descriptor.p_decConfigDescr->p_decoder_specific_info == NULL ) )
1300         MP4_READBOX_EXIT( 0 );
1301
1302     memcpy( es_descriptor.p_decConfigDescr->p_decoder_specific_info,
1303             p_peek, i_len );
1304
1305     MP4_READBOX_EXIT( 1 );
1306 #undef es_descriptor
1307 }
1308
1309 static void MP4_FreeBox_hvcC(MP4_Box_t *p_box )
1310 {
1311     MP4_Box_data_hvcC_t *p_hvcC =  p_box->data.p_hvcC;
1312     if( p_hvcC->i_hvcC > 0 ) FREENULL( p_hvcC->p_hvcC) ;
1313 }
1314
1315 static int MP4_ReadBox_hvcC( stream_t *p_stream, MP4_Box_t *p_box )
1316 {
1317     MP4_Box_data_hvcC_t *p_hvcC;
1318
1319     MP4_READBOX_ENTER( MP4_Box_data_hvcC_t );
1320     p_hvcC = p_box->data.p_hvcC;
1321
1322     p_hvcC->i_hvcC = i_read;
1323     if( p_hvcC->i_hvcC > 0 )
1324     {
1325         uint8_t * p = p_hvcC->p_hvcC = malloc( p_hvcC->i_hvcC );
1326         if( p )
1327             memcpy( p, p_peek, i_read );
1328     }
1329     MP4_READBOX_EXIT( 1 );
1330 }
1331
1332 static void MP4_FreeBox_avcC( MP4_Box_t *p_box )
1333 {
1334     MP4_Box_data_avcC_t *p_avcC = p_box->data.p_avcC;
1335     int i;
1336
1337     if( p_avcC->i_avcC > 0 ) FREENULL( p_avcC->p_avcC );
1338
1339     if( p_avcC->sps )
1340     {
1341         for( i = 0; i < p_avcC->i_sps; i++ )
1342             FREENULL( p_avcC->sps[i] );
1343     }
1344     if( p_avcC->pps )
1345     {
1346         for( i = 0; i < p_avcC->i_pps; i++ )
1347             FREENULL( p_avcC->pps[i] );
1348     }
1349     if( p_avcC->i_sps > 0 ) FREENULL( p_avcC->sps );
1350     if( p_avcC->i_sps > 0 ) FREENULL( p_avcC->i_sps_length );
1351     if( p_avcC->i_pps > 0 ) FREENULL( p_avcC->pps );
1352     if( p_avcC->i_pps > 0 ) FREENULL( p_avcC->i_pps_length );
1353 }
1354
1355 static int MP4_ReadBox_avcC( stream_t *p_stream, MP4_Box_t *p_box )
1356 {
1357     MP4_Box_data_avcC_t *p_avcC;
1358     int i;
1359
1360     MP4_READBOX_ENTER( MP4_Box_data_avcC_t );
1361     p_avcC = p_box->data.p_avcC;
1362
1363     p_avcC->i_avcC = i_read;
1364     if( p_avcC->i_avcC > 0 )
1365     {
1366         uint8_t * p = p_avcC->p_avcC = malloc( p_avcC->i_avcC );
1367         if( p )
1368             memcpy( p, p_peek, i_read );
1369     }
1370
1371     MP4_GET1BYTE( p_avcC->i_version );
1372     MP4_GET1BYTE( p_avcC->i_profile );
1373     MP4_GET1BYTE( p_avcC->i_profile_compatibility );
1374     MP4_GET1BYTE( p_avcC->i_level );
1375     MP4_GET1BYTE( p_avcC->i_reserved1 );
1376     p_avcC->i_length_size = (p_avcC->i_reserved1&0x03) + 1;
1377     p_avcC->i_reserved1 >>= 2;
1378
1379     MP4_GET1BYTE( p_avcC->i_reserved2 );
1380     p_avcC->i_sps = p_avcC->i_reserved2&0x1f;
1381     p_avcC->i_reserved2 >>= 5;
1382
1383     if( p_avcC->i_sps > 0 )
1384     {
1385         p_avcC->i_sps_length = calloc( p_avcC->i_sps, sizeof( uint16_t ) );
1386         p_avcC->sps = calloc( p_avcC->i_sps, sizeof( uint8_t* ) );
1387
1388         if( !p_avcC->i_sps_length || !p_avcC->sps )
1389             goto error;
1390
1391         for( i = 0; i < p_avcC->i_sps; i++ )
1392         {
1393             MP4_GET2BYTES( p_avcC->i_sps_length[i] );
1394             p_avcC->sps[i] = malloc( p_avcC->i_sps_length[i] );
1395             if( p_avcC->sps[i] )
1396                 memcpy( p_avcC->sps[i], p_peek, p_avcC->i_sps_length[i] );
1397
1398             p_peek += p_avcC->i_sps_length[i];
1399             i_read -= p_avcC->i_sps_length[i];
1400         }
1401     }
1402
1403     MP4_GET1BYTE( p_avcC->i_pps );
1404     if( p_avcC->i_pps > 0 )
1405     {
1406         p_avcC->i_pps_length = calloc( p_avcC->i_pps, sizeof( uint16_t ) );
1407         p_avcC->pps = calloc( p_avcC->i_pps, sizeof( uint8_t* ) );
1408
1409         if( !p_avcC->i_pps_length || !p_avcC->pps )
1410             goto error;
1411
1412         for( i = 0; i < p_avcC->i_pps; i++ )
1413         {
1414             MP4_GET2BYTES( p_avcC->i_pps_length[i] );
1415             p_avcC->pps[i] = malloc( p_avcC->i_pps_length[i] );
1416             if( p_avcC->pps[i] )
1417                 memcpy( p_avcC->pps[i], p_peek, p_avcC->i_pps_length[i] );
1418
1419             p_peek += p_avcC->i_pps_length[i];
1420             i_read -= p_avcC->i_pps_length[i];
1421         }
1422     }
1423 #ifdef MP4_VERBOSE
1424     msg_Dbg( p_stream,
1425              "read box: \"avcC\" version=%d profile=0x%x level=0x%x length size=%d sps=%d pps=%d",
1426              p_avcC->i_version, p_avcC->i_profile, p_avcC->i_level,
1427              p_avcC->i_length_size,
1428              p_avcC->i_sps, p_avcC->i_pps );
1429     for( i = 0; i < p_avcC->i_sps; i++ )
1430     {
1431         msg_Dbg( p_stream, "         - sps[%d] length=%d",
1432                  i, p_avcC->i_sps_length[i] );
1433     }
1434     for( i = 0; i < p_avcC->i_pps; i++ )
1435     {
1436         msg_Dbg( p_stream, "         - pps[%d] length=%d",
1437                  i, p_avcC->i_pps_length[i] );
1438     }
1439
1440 #endif
1441     MP4_READBOX_EXIT( 1 );
1442
1443 error:
1444     MP4_READBOX_EXIT( 0 );
1445 }
1446
1447 static int MP4_ReadBox_dac3( stream_t *p_stream, MP4_Box_t *p_box )
1448 {
1449     MP4_Box_data_dac3_t *p_dac3;
1450     MP4_READBOX_ENTER( MP4_Box_data_dac3_t );
1451
1452     p_dac3 = p_box->data.p_dac3;
1453
1454     unsigned i_header;
1455     MP4_GET3BYTES( i_header );
1456
1457     p_dac3->i_fscod = ( i_header >> 22 ) & 0x03;
1458     p_dac3->i_bsid  = ( i_header >> 17 ) & 0x01f;
1459     p_dac3->i_bsmod = ( i_header >> 14 ) & 0x07;
1460     p_dac3->i_acmod = ( i_header >> 11 ) & 0x07;
1461     p_dac3->i_lfeon = ( i_header >> 10 ) & 0x01;
1462     p_dac3->i_bitrate_code = ( i_header >> 5) & 0x1f;
1463
1464 #ifdef MP4_VERBOSE
1465     msg_Dbg( p_stream,
1466              "read box: \"dac3\" fscod=0x%x bsid=0x%x bsmod=0x%x acmod=0x%x lfeon=0x%x bitrate_code=0x%x",
1467              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 );
1468 #endif
1469     MP4_READBOX_EXIT( 1 );
1470 }
1471
1472 static int MP4_ReadBox_dvc1( stream_t *p_stream, MP4_Box_t *p_box )
1473 {
1474     MP4_Box_data_dvc1_t *p_dvc1;
1475
1476     MP4_READBOX_ENTER( MP4_Box_data_dvc1_t );
1477     p_dvc1 = p_box->data.p_dvc1;
1478
1479     MP4_GET1BYTE( p_dvc1->i_profile_level ); /* profile is on 4bits, level 3bits */
1480     uint8_t i_profile = (p_dvc1->i_profile_level & 0xf0) >> 4;
1481     if( i_profile != 0x06 && i_profile != 0x0c )
1482     {
1483         msg_Warn( p_stream, "unsupported VC-1 profile (%"PRIu8"), please report", i_profile );
1484         MP4_READBOX_EXIT( 0 );
1485     }
1486
1487
1488     p_dvc1->i_vc1 = p_box->i_size - 7; /* Header + profile_level */
1489
1490     if( p_dvc1->i_vc1 > 0 )
1491     {
1492         uint8_t *p = p_dvc1->p_vc1 = malloc( p_dvc1->i_vc1 );
1493         if( p )
1494             memcpy( p, p_peek, i_read );
1495     }
1496
1497 #ifdef MP4_VERBOSE
1498     msg_Dbg( p_stream,
1499              "read box: \"dvc1\" profile=%"PRIu8" level=%i",
1500              i_profile, p_dvc1->i_profile_level & 0x0e >> 1 );
1501 #endif
1502
1503     MP4_READBOX_EXIT( 1 );
1504 }
1505
1506 static int MP4_ReadBox_enda( stream_t *p_stream, MP4_Box_t *p_box )
1507 {
1508     MP4_Box_data_enda_t *p_enda;
1509     MP4_READBOX_ENTER( MP4_Box_data_enda_t );
1510
1511     p_enda = p_box->data.p_enda;
1512
1513     MP4_GET2BYTES( p_enda->i_little_endian );
1514
1515 #ifdef MP4_VERBOSE
1516     msg_Dbg( p_stream,
1517              "read box: \"enda\" little_endian=%d", p_enda->i_little_endian );
1518 #endif
1519     MP4_READBOX_EXIT( 1 );
1520 }
1521
1522 static int MP4_ReadBox_gnre( stream_t *p_stream, MP4_Box_t *p_box )
1523 {
1524     MP4_Box_data_gnre_t *p_gnre;
1525     MP4_READBOX_ENTER( MP4_Box_data_gnre_t );
1526
1527     p_gnre = p_box->data.p_gnre;
1528
1529     uint32_t i_data_len;
1530     uint32_t i_data_tag;
1531
1532     MP4_GET4BYTES( i_data_len );
1533     MP4_GETFOURCC( i_data_tag );
1534     if( i_data_len < 10 || i_data_tag != ATOM_data )
1535         MP4_READBOX_EXIT( 0 );
1536
1537     uint32_t i_version;
1538     VLC_UNUSED(i_version);
1539     uint32_t i_reserved;
1540     VLC_UNUSED(i_reserved);
1541     MP4_GET4BYTES( i_version );
1542     MP4_GET4BYTES( i_reserved );
1543     MP4_GET2BYTES( p_gnre->i_genre );
1544     if( p_gnre->i_genre == 0 )
1545         MP4_READBOX_EXIT( 0 );
1546 #ifdef MP4_VERBOSE
1547     msg_Dbg( p_stream, "read box: \"gnre\" genre=%i", p_gnre->i_genre );
1548 #endif
1549
1550     MP4_READBOX_EXIT( 1 );
1551 }
1552
1553 static int MP4_ReadBox_trkn( stream_t *p_stream, MP4_Box_t *p_box )
1554 {
1555     MP4_Box_data_trkn_t *p_trkn;
1556     MP4_READBOX_ENTER( MP4_Box_data_trkn_t );
1557
1558     p_trkn = p_box->data.p_trkn;
1559
1560     uint32_t i_data_len;
1561     uint32_t i_data_tag;
1562
1563     MP4_GET4BYTES( i_data_len );
1564     MP4_GETFOURCC( i_data_tag );
1565     if( i_data_len < 12 || i_data_tag != ATOM_data )
1566         MP4_READBOX_EXIT( 0 );
1567
1568     uint32_t i_version;
1569     VLC_UNUSED(i_version);
1570     uint32_t i_reserved;
1571     VLC_UNUSED(i_reserved);
1572     MP4_GET4BYTES( i_version );
1573     MP4_GET4BYTES( i_reserved );
1574     MP4_GET2BYTES( i_reserved );
1575     MP4_GET2BYTES( p_trkn->i_track_number );
1576 #ifdef MP4_VERBOSE
1577     msg_Dbg( p_stream, "read box: \"trkn\" number=%i", p_trkn->i_track_number );
1578 #endif
1579     if( i_data_len > 15 )
1580     {
1581        MP4_GET2BYTES( p_trkn->i_track_total );
1582 #ifdef MP4_VERBOSE
1583        msg_Dbg( p_stream, "read box: \"trkn\" total=%i", p_trkn->i_track_total );
1584 #endif
1585     }
1586
1587     MP4_READBOX_EXIT( 1 );
1588 }
1589
1590 static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box )
1591 {
1592     MP4_READBOX_ENTER( MP4_Box_data_sample_soun_t );
1593     p_box->data.p_sample_soun->p_qt_description = NULL;
1594
1595     /* Sanity check needed because the "wave" box does also contain an
1596      * "mp4a" box that we don't understand. */
1597     if( i_read < 28 )
1598     {
1599         i_read -= 30;
1600         MP4_READBOX_EXIT( 1 );
1601     }
1602
1603     for( unsigned i = 0; i < 6 ; i++ )
1604     {
1605         MP4_GET1BYTE( p_box->data.p_sample_soun->i_reserved1[i] );
1606     }
1607
1608     MP4_GET2BYTES( p_box->data.p_sample_soun->i_data_reference_index );
1609
1610     /*
1611      * XXX hack -> produce a copy of the nearly complete chunk
1612      */
1613     p_box->data.p_sample_soun->i_qt_description = 0;
1614     p_box->data.p_sample_soun->p_qt_description = NULL;
1615     if( i_read > 0 )
1616     {
1617         p_box->data.p_sample_soun->p_qt_description = malloc( i_read );
1618         if( p_box->data.p_sample_soun->p_qt_description )
1619         {
1620             p_box->data.p_sample_soun->i_qt_description = i_read;
1621             memcpy( p_box->data.p_sample_soun->p_qt_description, p_peek, i_read );
1622         }
1623     }
1624
1625     MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_version );
1626     MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_revision_level );
1627     MP4_GET4BYTES( p_box->data.p_sample_soun->i_qt_vendor );
1628
1629     MP4_GET2BYTES( p_box->data.p_sample_soun->i_channelcount );
1630     MP4_GET2BYTES( p_box->data.p_sample_soun->i_samplesize );
1631     MP4_GET2BYTES( p_box->data.p_sample_soun->i_predefined );
1632     MP4_GET2BYTES( p_box->data.p_sample_soun->i_reserved3 );
1633     MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratehi );
1634     MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratelo );
1635
1636     if( p_box->data.p_sample_soun->i_qt_version == 1 && i_read >= 16 )
1637     {
1638         /* SoundDescriptionV1 */
1639         MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet );
1640         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_packet );
1641         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_frame );
1642         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_sample );
1643
1644 #ifdef MP4_VERBOSE
1645         msg_Dbg( p_stream,
1646                  "read box: \"soun\" qt3+ sample/packet=%d bytes/packet=%d "
1647                  "bytes/frame=%d bytes/sample=%d",
1648                  p_box->data.p_sample_soun->i_sample_per_packet,
1649                  p_box->data.p_sample_soun->i_bytes_per_packet,
1650                  p_box->data.p_sample_soun->i_bytes_per_frame,
1651                  p_box->data.p_sample_soun->i_bytes_per_sample );
1652 #endif
1653         stream_Seek( p_stream, p_box->i_pos +
1654                         mp4_box_headersize( p_box ) + 44 );
1655     }
1656     else if( p_box->data.p_sample_soun->i_qt_version == 2 && i_read >= 36 )
1657     {
1658         /* SoundDescriptionV2 */
1659         double f_sample_rate;
1660         int64_t dummy;
1661         uint32_t i_channel;
1662
1663         MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet );
1664         MP4_GET8BYTES( dummy );
1665         memcpy( &f_sample_rate, &dummy, 8 );
1666
1667         msg_Dbg( p_stream, "read box: %f Hz", f_sample_rate );
1668         p_box->data.p_sample_soun->i_sampleratehi = (int)f_sample_rate % 65536;
1669         p_box->data.p_sample_soun->i_sampleratelo = f_sample_rate / 65536;
1670
1671         MP4_GET4BYTES( i_channel );
1672         p_box->data.p_sample_soun->i_channelcount = i_channel;
1673
1674 #ifdef MP4_VERBOSE
1675         msg_Dbg( p_stream, "read box: \"soun\" V2" );
1676 #endif
1677         stream_Seek( p_stream, p_box->i_pos +
1678                         mp4_box_headersize( p_box ) + 28 + 36 );
1679     }
1680     else
1681     {
1682         p_box->data.p_sample_soun->i_sample_per_packet = 0;
1683         p_box->data.p_sample_soun->i_bytes_per_packet = 0;
1684         p_box->data.p_sample_soun->i_bytes_per_frame = 0;
1685         p_box->data.p_sample_soun->i_bytes_per_sample = 0;
1686
1687 #ifdef MP4_VERBOSE
1688         msg_Dbg( p_stream, "read box: \"soun\" mp4 or qt1/2 (rest=%"PRId64")",
1689                  i_read );
1690 #endif
1691         stream_Seek( p_stream, p_box->i_pos +
1692                         mp4_box_headersize( p_box ) + 28 );
1693     }
1694
1695     if( p_box->i_type == ATOM_drms )
1696     {
1697         msg_Warn( p_stream, "DRM protected streams are not supported." );
1698         MP4_READBOX_EXIT( 0 );
1699     }
1700
1701     if( p_box->i_type == ATOM_samr || p_box->i_type == ATOM_sawb )
1702     {
1703         /* Ignore channelcount for AMR (3gpp AMRSpecificBox) */
1704         p_box->data.p_sample_soun->i_channelcount = 1;
1705     }
1706
1707     MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds/wave/... */
1708
1709 #ifdef MP4_VERBOSE
1710     msg_Dbg( p_stream, "read box: \"soun\" in stsd channel %d "
1711              "sample size %d sample rate %f",
1712              p_box->data.p_sample_soun->i_channelcount,
1713              p_box->data.p_sample_soun->i_samplesize,
1714              (float)p_box->data.p_sample_soun->i_sampleratehi +
1715              (float)p_box->data.p_sample_soun->i_sampleratelo / 65536 );
1716
1717 #endif
1718     MP4_READBOX_EXIT( 1 );
1719 }
1720
1721
1722 static void MP4_FreeBox_sample_soun( MP4_Box_t *p_box )
1723 {
1724     FREENULL( p_box->data.p_sample_soun->p_qt_description );
1725 }
1726
1727
1728 int MP4_ReadBox_sample_vide( stream_t *p_stream, MP4_Box_t *p_box )
1729 {
1730     MP4_READBOX_ENTER( MP4_Box_data_sample_vide_t );
1731
1732     for( unsigned i = 0; i < 6 ; i++ )
1733     {
1734         MP4_GET1BYTE( p_box->data.p_sample_vide->i_reserved1[i] );
1735     }
1736
1737     MP4_GET2BYTES( p_box->data.p_sample_vide->i_data_reference_index );
1738
1739     /*
1740      * XXX hack -> produce a copy of the nearly complete chunk
1741      */
1742     if( i_read > 0 )
1743     {
1744         p_box->data.p_sample_vide->p_qt_image_description = malloc( i_read );
1745         if( unlikely( p_box->data.p_sample_vide->p_qt_image_description == NULL ) )
1746             MP4_READBOX_EXIT( 0 );
1747         p_box->data.p_sample_vide->i_qt_image_description = i_read;
1748         memcpy( p_box->data.p_sample_vide->p_qt_image_description,
1749                 p_peek, i_read );
1750     }
1751     else
1752     {
1753         p_box->data.p_sample_vide->i_qt_image_description = 0;
1754         p_box->data.p_sample_vide->p_qt_image_description = NULL;
1755     }
1756
1757     MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_version );
1758     MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_revision_level );
1759     MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_vendor );
1760
1761     MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_temporal_quality );
1762     MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_spatial_quality );
1763
1764     MP4_GET2BYTES( p_box->data.p_sample_vide->i_width );
1765     MP4_GET2BYTES( p_box->data.p_sample_vide->i_height );
1766
1767     MP4_GET4BYTES( p_box->data.p_sample_vide->i_horizresolution );
1768     MP4_GET4BYTES( p_box->data.p_sample_vide->i_vertresolution );
1769
1770     MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_data_size );
1771     MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_frame_count );
1772
1773     memcpy( &p_box->data.p_sample_vide->i_compressorname, p_peek, 32 );
1774     p_peek += 32; i_read -= 32;
1775
1776     MP4_GET2BYTES( p_box->data.p_sample_vide->i_depth );
1777     MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_color_table );
1778
1779     stream_Seek( p_stream, p_box->i_pos + mp4_box_headersize( p_box ) + 78);
1780
1781     if( p_box->i_type == ATOM_drmi )
1782     {
1783         msg_Warn( p_stream, "DRM protected streams are not supported." );
1784         MP4_READBOX_EXIT( 0 );
1785     }
1786
1787     MP4_ReadBoxContainerRaw( p_stream, p_box );
1788
1789 #ifdef MP4_VERBOSE
1790     msg_Dbg( p_stream, "read box: \"vide\" in stsd %dx%d depth %d",
1791                       p_box->data.p_sample_vide->i_width,
1792                       p_box->data.p_sample_vide->i_height,
1793                       p_box->data.p_sample_vide->i_depth );
1794
1795 #endif
1796     MP4_READBOX_EXIT( 1 );
1797 }
1798
1799
1800 void MP4_FreeBox_sample_vide( MP4_Box_t *p_box )
1801 {
1802     FREENULL( p_box->data.p_sample_vide->p_qt_image_description );
1803 }
1804
1805 static int MP4_ReadBox_sample_mp4s( stream_t *p_stream, MP4_Box_t *p_box )
1806 {
1807     stream_Seek( p_stream, p_box->i_pos + mp4_box_headersize( p_box ) + 8 );
1808     MP4_ReadBoxContainerRaw( p_stream, p_box );
1809     return 1;
1810 }
1811
1812 static int MP4_ReadBox_sample_text( stream_t *p_stream, MP4_Box_t *p_box )
1813 {
1814     int32_t t;
1815
1816     MP4_READBOX_ENTER( MP4_Box_data_sample_text_t );
1817
1818     MP4_GET4BYTES( p_box->data.p_sample_text->i_reserved1 );
1819     MP4_GET2BYTES( p_box->data.p_sample_text->i_reserved2 );
1820
1821     MP4_GET2BYTES( p_box->data.p_sample_text->i_data_reference_index );
1822
1823     MP4_GET4BYTES( p_box->data.p_sample_text->i_display_flags );
1824
1825     MP4_GET4BYTES( t );
1826     switch( t )
1827     {
1828         /* FIXME search right signification */
1829         case 1: // Center
1830             p_box->data.p_sample_text->i_justification_horizontal = 1;
1831             p_box->data.p_sample_text->i_justification_vertical = 1;
1832             break;
1833         case -1:    // Flush Right
1834             p_box->data.p_sample_text->i_justification_horizontal = -1;
1835             p_box->data.p_sample_text->i_justification_vertical = -1;
1836             break;
1837         case -2:    // Flush Left
1838             p_box->data.p_sample_text->i_justification_horizontal = 0;
1839             p_box->data.p_sample_text->i_justification_vertical = 0;
1840             break;
1841         case 0: // Flush Default
1842         default:
1843             p_box->data.p_sample_text->i_justification_horizontal = 1;
1844             p_box->data.p_sample_text->i_justification_vertical = -1;
1845             break;
1846     }
1847
1848     MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[0] );
1849     MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[1] );
1850     MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[2] );
1851     p_box->data.p_sample_text->i_background_color[3] = 0xFF;
1852
1853     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_top );
1854     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_left );
1855     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_bottom );
1856     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_right );
1857
1858 #ifdef MP4_VERBOSE
1859     msg_Dbg( p_stream, "read box: \"text\" in stsd text" );
1860 #endif
1861     MP4_READBOX_EXIT( 1 );
1862 }
1863
1864 static int MP4_ReadBox_sample_tx3g( stream_t *p_stream, MP4_Box_t *p_box )
1865 {
1866     MP4_READBOX_ENTER( MP4_Box_data_sample_text_t );
1867
1868     MP4_GET4BYTES( p_box->data.p_sample_text->i_reserved1 );
1869     MP4_GET2BYTES( p_box->data.p_sample_text->i_reserved2 );
1870
1871     MP4_GET2BYTES( p_box->data.p_sample_text->i_data_reference_index );
1872
1873     MP4_GET4BYTES( p_box->data.p_sample_text->i_display_flags );
1874
1875     MP4_GET1BYTE ( p_box->data.p_sample_text->i_justification_horizontal );
1876     MP4_GET1BYTE ( p_box->data.p_sample_text->i_justification_vertical );
1877
1878     MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[0] );
1879     MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[1] );
1880     MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[2] );
1881     MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[3] );
1882
1883     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_top );
1884     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_left );
1885     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_bottom );
1886     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_right );
1887
1888     MP4_GET4BYTES( p_box->data.p_sample_text->i_reserved3 );
1889
1890     MP4_GET2BYTES( p_box->data.p_sample_text->i_font_id );
1891     MP4_GET1BYTE ( p_box->data.p_sample_text->i_font_face );
1892     MP4_GET1BYTE ( p_box->data.p_sample_text->i_font_size );
1893     MP4_GET4BYTES( p_box->data.p_sample_text->i_font_color );
1894
1895 #ifdef MP4_VERBOSE
1896     msg_Dbg( p_stream, "read box: \"tx3g\" in stsd text" );
1897 #endif
1898     MP4_READBOX_EXIT( 1 );
1899 }
1900
1901
1902 #if 0
1903 /* We can't easily call it, and anyway ~ 20 bytes lost isn't a real problem */
1904 static void MP4_FreeBox_sample_text( MP4_Box_t *p_box )
1905 {
1906     FREENULL( p_box->data.p_sample_text->psz_text_name );
1907 }
1908 #endif
1909
1910
1911 static int MP4_ReadBox_stsd( stream_t *p_stream, MP4_Box_t *p_box )
1912 {
1913
1914     MP4_READBOX_ENTER( MP4_Box_data_stsd_t );
1915
1916     MP4_GETVERSIONFLAGS( p_box->data.p_stsd );
1917
1918     MP4_GET4BYTES( p_box->data.p_stsd->i_entry_count );
1919
1920     stream_Seek( p_stream, p_box->i_pos + mp4_box_headersize( p_box ) + 8 );
1921
1922     MP4_ReadBoxContainerRaw( p_stream, p_box );
1923
1924 #ifdef MP4_VERBOSE
1925     msg_Dbg( p_stream, "read box: \"stsd\" entry-count %d",
1926                       p_box->data.p_stsd->i_entry_count );
1927
1928 #endif
1929     MP4_READBOX_EXIT( 1 );
1930 }
1931
1932
1933 static int MP4_ReadBox_stsz( stream_t *p_stream, MP4_Box_t *p_box )
1934 {
1935     MP4_READBOX_ENTER( MP4_Box_data_stsz_t );
1936
1937     MP4_GETVERSIONFLAGS( p_box->data.p_stsz );
1938
1939     MP4_GET4BYTES( p_box->data.p_stsz->i_sample_size );
1940     MP4_GET4BYTES( p_box->data.p_stsz->i_sample_count );
1941
1942     if( p_box->data.p_stsz->i_sample_size == 0 )
1943     {
1944         p_box->data.p_stsz->i_entry_size =
1945             calloc( p_box->data.p_stsz->i_sample_count, sizeof(uint32_t) );
1946         if( unlikely( !p_box->data.p_stsz->i_entry_size ) )
1947             MP4_READBOX_EXIT( 0 );
1948
1949         for( unsigned int i = 0; (i<p_box->data.p_stsz->i_sample_count)&&(i_read >= 4 ); i++ )
1950         {
1951             MP4_GET4BYTES( p_box->data.p_stsz->i_entry_size[i] );
1952         }
1953     }
1954     else
1955         p_box->data.p_stsz->i_entry_size = NULL;
1956
1957 #ifdef MP4_VERBOSE
1958     msg_Dbg( p_stream, "read box: \"stsz\" sample-size %d sample-count %d",
1959                       p_box->data.p_stsz->i_sample_size,
1960                       p_box->data.p_stsz->i_sample_count );
1961
1962 #endif
1963     MP4_READBOX_EXIT( 1 );
1964 }
1965
1966 static void MP4_FreeBox_stsz( MP4_Box_t *p_box )
1967 {
1968     FREENULL( p_box->data.p_stsz->i_entry_size );
1969 }
1970
1971 static void MP4_FreeBox_stsc( MP4_Box_t *p_box )
1972 {
1973     FREENULL( p_box->data.p_stsc->i_first_chunk );
1974     FREENULL( p_box->data.p_stsc->i_samples_per_chunk );
1975     FREENULL( p_box->data.p_stsc->i_sample_description_index );
1976 }
1977
1978 static int MP4_ReadBox_stsc( stream_t *p_stream, MP4_Box_t *p_box )
1979 {
1980     MP4_READBOX_ENTER( MP4_Box_data_stsc_t );
1981
1982     MP4_GETVERSIONFLAGS( p_box->data.p_stsc );
1983
1984     MP4_GET4BYTES( p_box->data.p_stsc->i_entry_count );
1985
1986     p_box->data.p_stsc->i_first_chunk =
1987         calloc( p_box->data.p_stsc->i_entry_count, sizeof(uint32_t) );
1988     p_box->data.p_stsc->i_samples_per_chunk =
1989         calloc( p_box->data.p_stsc->i_entry_count, sizeof(uint32_t) );
1990     p_box->data.p_stsc->i_sample_description_index =
1991         calloc( p_box->data.p_stsc->i_entry_count, sizeof(uint32_t) );
1992     if( unlikely( p_box->data.p_stsc->i_first_chunk == NULL
1993      || p_box->data.p_stsc->i_samples_per_chunk == NULL
1994      || p_box->data.p_stsc->i_sample_description_index == NULL ) )
1995     {
1996         MP4_READBOX_EXIT( 0 );
1997     }
1998
1999     for( unsigned int i = 0; (i < p_box->data.p_stsc->i_entry_count )&&( i_read >= 12 );i++ )
2000     {
2001         MP4_GET4BYTES( p_box->data.p_stsc->i_first_chunk[i] );
2002         MP4_GET4BYTES( p_box->data.p_stsc->i_samples_per_chunk[i] );
2003         MP4_GET4BYTES( p_box->data.p_stsc->i_sample_description_index[i] );
2004     }
2005
2006 #ifdef MP4_VERBOSE
2007     msg_Dbg( p_stream, "read box: \"stsc\" entry-count %d",
2008                       p_box->data.p_stsc->i_entry_count );
2009
2010 #endif
2011     MP4_READBOX_EXIT( 1 );
2012 }
2013
2014 static int MP4_ReadBox_stco_co64( stream_t *p_stream, MP4_Box_t *p_box )
2015 {
2016     MP4_READBOX_ENTER( MP4_Box_data_co64_t );
2017
2018     MP4_GETVERSIONFLAGS( p_box->data.p_co64 );
2019
2020     MP4_GET4BYTES( p_box->data.p_co64->i_entry_count );
2021
2022     p_box->data.p_co64->i_chunk_offset =
2023         calloc( p_box->data.p_co64->i_entry_count, sizeof(uint64_t) );
2024     if( p_box->data.p_co64->i_chunk_offset == NULL )
2025         MP4_READBOX_EXIT( 0 );
2026
2027     for( unsigned int i = 0; i < p_box->data.p_co64->i_entry_count; i++ )
2028     {
2029         if( p_box->i_type == ATOM_stco )
2030         {
2031             if( i_read < 4 )
2032             {
2033                 break;
2034             }
2035             MP4_GET4BYTES( p_box->data.p_co64->i_chunk_offset[i] );
2036         }
2037         else
2038         {
2039             if( i_read < 8 )
2040             {
2041                 break;
2042             }
2043             MP4_GET8BYTES( p_box->data.p_co64->i_chunk_offset[i] );
2044         }
2045     }
2046
2047 #ifdef MP4_VERBOSE
2048     msg_Dbg( p_stream, "read box: \"co64\" entry-count %d",
2049                       p_box->data.p_co64->i_entry_count );
2050
2051 #endif
2052     MP4_READBOX_EXIT( 1 );
2053 }
2054
2055 static void MP4_FreeBox_stco_co64( MP4_Box_t *p_box )
2056 {
2057     FREENULL( p_box->data.p_co64->i_chunk_offset );
2058 }
2059
2060 static int MP4_ReadBox_stss( stream_t *p_stream, MP4_Box_t *p_box )
2061 {
2062     MP4_READBOX_ENTER( MP4_Box_data_stss_t );
2063
2064     MP4_GETVERSIONFLAGS( p_box->data.p_stss );
2065
2066     MP4_GET4BYTES( p_box->data.p_stss->i_entry_count );
2067
2068     p_box->data.p_stss->i_sample_number =
2069         calloc( p_box->data.p_stss->i_entry_count, sizeof(uint32_t) );
2070     if( unlikely( p_box->data.p_stss->i_sample_number == NULL ) )
2071         MP4_READBOX_EXIT( 0 );
2072
2073     for( unsigned int i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 4 ); i++ )
2074     {
2075
2076         MP4_GET4BYTES( p_box->data.p_stss->i_sample_number[i] );
2077         /* XXX in libmp4 sample begin at 0 */
2078         p_box->data.p_stss->i_sample_number[i]--;
2079     }
2080
2081 #ifdef MP4_VERBOSE
2082     msg_Dbg( p_stream, "read box: \"stss\" entry-count %d",
2083                       p_box->data.p_stss->i_entry_count );
2084
2085 #endif
2086     MP4_READBOX_EXIT( 1 );
2087 }
2088
2089 static void MP4_FreeBox_stss( MP4_Box_t *p_box )
2090 {
2091     FREENULL( p_box->data.p_stss->i_sample_number );
2092 }
2093
2094 static void MP4_FreeBox_stsh( MP4_Box_t *p_box )
2095 {
2096     FREENULL( p_box->data.p_stsh->i_shadowed_sample_number );
2097     FREENULL( p_box->data.p_stsh->i_sync_sample_number );
2098 }
2099
2100 static int MP4_ReadBox_stsh( stream_t *p_stream, MP4_Box_t *p_box )
2101 {
2102     MP4_READBOX_ENTER( MP4_Box_data_stsh_t );
2103
2104     MP4_GETVERSIONFLAGS( p_box->data.p_stsh );
2105
2106
2107     MP4_GET4BYTES( p_box->data.p_stsh->i_entry_count );
2108
2109     p_box->data.p_stsh->i_shadowed_sample_number =
2110         calloc( p_box->data.p_stsh->i_entry_count, sizeof(uint32_t) );
2111     p_box->data.p_stsh->i_sync_sample_number =
2112         calloc( p_box->data.p_stsh->i_entry_count, sizeof(uint32_t) );
2113
2114     if( p_box->data.p_stsh->i_shadowed_sample_number == NULL
2115      || p_box->data.p_stsh->i_sync_sample_number == NULL )
2116     {
2117         MP4_READBOX_EXIT( 0 );
2118     }
2119
2120     for( unsigned i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 8 ); i++ )
2121     {
2122         MP4_GET4BYTES( p_box->data.p_stsh->i_shadowed_sample_number[i] );
2123         MP4_GET4BYTES( p_box->data.p_stsh->i_sync_sample_number[i] );
2124     }
2125
2126 #ifdef MP4_VERBOSE
2127     msg_Dbg( p_stream, "read box: \"stsh\" entry-count %d",
2128                       p_box->data.p_stsh->i_entry_count );
2129 #endif
2130     MP4_READBOX_EXIT( 1 );
2131 }
2132
2133
2134 static int MP4_ReadBox_stdp( stream_t *p_stream, MP4_Box_t *p_box )
2135 {
2136     MP4_READBOX_ENTER( MP4_Box_data_stdp_t );
2137
2138     MP4_GETVERSIONFLAGS( p_box->data.p_stdp );
2139
2140     p_box->data.p_stdp->i_priority =
2141         calloc( i_read / 2, sizeof(uint16_t) );
2142
2143     if( unlikely( !p_box->data.p_stdp->i_priority ) )
2144         MP4_READBOX_EXIT( 0 );
2145
2146     for( unsigned i = 0; i < i_read / 2 ; i++ )
2147     {
2148         MP4_GET2BYTES( p_box->data.p_stdp->i_priority[i] );
2149     }
2150
2151 #ifdef MP4_VERBOSE
2152     msg_Dbg( p_stream, "read box: \"stdp\" entry-count %"PRId64,
2153                       i_read / 2 );
2154
2155 #endif
2156     MP4_READBOX_EXIT( 1 );
2157 }
2158
2159 static void MP4_FreeBox_stdp( MP4_Box_t *p_box )
2160 {
2161     FREENULL( p_box->data.p_stdp->i_priority );
2162 }
2163
2164 static void MP4_FreeBox_padb( MP4_Box_t *p_box )
2165 {
2166     FREENULL( p_box->data.p_padb->i_reserved1 );
2167     FREENULL( p_box->data.p_padb->i_pad2 );
2168     FREENULL( p_box->data.p_padb->i_reserved2 );
2169     FREENULL( p_box->data.p_padb->i_pad1 );
2170 }
2171
2172 static int MP4_ReadBox_padb( stream_t *p_stream, MP4_Box_t *p_box )
2173 {
2174     uint32_t count;
2175
2176     MP4_READBOX_ENTER( MP4_Box_data_padb_t );
2177
2178     MP4_GETVERSIONFLAGS( p_box->data.p_padb );
2179
2180     MP4_GET4BYTES( p_box->data.p_padb->i_sample_count );
2181     count = (p_box->data.p_padb->i_sample_count + 1) / 2;
2182
2183     p_box->data.p_padb->i_reserved1 = calloc( count, sizeof(uint16_t) );
2184     p_box->data.p_padb->i_pad2 = calloc( count, sizeof(uint16_t) );
2185     p_box->data.p_padb->i_reserved2 = calloc( count, sizeof(uint16_t) );
2186     p_box->data.p_padb->i_pad1 = calloc( count, sizeof(uint16_t) );
2187     if( p_box->data.p_padb->i_reserved1 == NULL
2188      || p_box->data.p_padb->i_pad2 == NULL
2189      || p_box->data.p_padb->i_reserved2 == NULL
2190      || p_box->data.p_padb->i_pad1 == NULL )
2191     {
2192         MP4_READBOX_EXIT( 0 );
2193     }
2194
2195     for( unsigned int i = 0; i < i_read / 2 ; i++ )
2196     {
2197         if( i >= count )
2198         {
2199             MP4_READBOX_EXIT( 0 );
2200         }
2201         p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 7 )&0x01;
2202         p_box->data.p_padb->i_pad2[i] = ( (*p_peek) >> 4 )&0x07;
2203         p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 3 )&0x01;
2204         p_box->data.p_padb->i_pad1[i] = ( (*p_peek) )&0x07;
2205
2206         p_peek += 1; i_read -= 1;
2207     }
2208
2209 #ifdef MP4_VERBOSE
2210     msg_Dbg( p_stream, "read box: \"stdp\" entry-count %"PRId64,
2211                       i_read / 2 );
2212
2213 #endif
2214     MP4_READBOX_EXIT( 1 );
2215 }
2216
2217 static void MP4_FreeBox_elst( MP4_Box_t *p_box )
2218 {
2219     FREENULL( p_box->data.p_elst->i_segment_duration );
2220     FREENULL( p_box->data.p_elst->i_media_time );
2221     FREENULL( p_box->data.p_elst->i_media_rate_integer );
2222     FREENULL( p_box->data.p_elst->i_media_rate_fraction );
2223 }
2224
2225 static int MP4_ReadBox_elst( stream_t *p_stream, MP4_Box_t *p_box )
2226 {
2227     MP4_READBOX_ENTER( MP4_Box_data_elst_t );
2228
2229     MP4_GETVERSIONFLAGS( p_box->data.p_elst );
2230
2231
2232     MP4_GET4BYTES( p_box->data.p_elst->i_entry_count );
2233
2234     p_box->data.p_elst->i_segment_duration =
2235         calloc( p_box->data.p_elst->i_entry_count, sizeof(uint64_t) );
2236     p_box->data.p_elst->i_media_time =
2237         calloc( p_box->data.p_elst->i_entry_count, sizeof(int64_t) );
2238     p_box->data.p_elst->i_media_rate_integer =
2239         calloc( p_box->data.p_elst->i_entry_count, sizeof(uint16_t) );
2240     p_box->data.p_elst->i_media_rate_fraction =
2241         calloc( p_box->data.p_elst->i_entry_count, sizeof(uint16_t) );
2242     if( p_box->data.p_elst->i_segment_duration == NULL
2243      || p_box->data.p_elst->i_media_time == NULL
2244      || p_box->data.p_elst->i_media_rate_integer == NULL
2245      || p_box->data.p_elst->i_media_rate_fraction == NULL )
2246     {
2247         MP4_READBOX_EXIT( 0 );
2248     }
2249
2250
2251     for( unsigned i = 0; i < p_box->data.p_elst->i_entry_count; i++ )
2252     {
2253         if( p_box->data.p_elst->i_version == 1 )
2254         {
2255
2256             MP4_GET8BYTES( p_box->data.p_elst->i_segment_duration[i] );
2257
2258             MP4_GET8BYTES( p_box->data.p_elst->i_media_time[i] );
2259         }
2260         else
2261         {
2262
2263             MP4_GET4BYTES( p_box->data.p_elst->i_segment_duration[i] );
2264
2265             MP4_GET4BYTES( p_box->data.p_elst->i_media_time[i] );
2266             p_box->data.p_elst->i_media_time[i] = (int32_t)p_box->data.p_elst->i_media_time[i];
2267         }
2268
2269         MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_integer[i] );
2270         MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_fraction[i] );
2271     }
2272
2273 #ifdef MP4_VERBOSE
2274     msg_Dbg( p_stream, "read box: \"elst\" entry-count %lu",
2275              (unsigned long)p_box->data.p_elst->i_entry_count );
2276 #endif
2277     MP4_READBOX_EXIT( 1 );
2278 }
2279
2280 static int MP4_ReadBox_cprt( stream_t *p_stream, MP4_Box_t *p_box )
2281 {
2282     unsigned int i_language;
2283
2284     MP4_READBOX_ENTER( MP4_Box_data_cprt_t );
2285
2286     MP4_GETVERSIONFLAGS( p_box->data.p_cprt );
2287
2288     i_language = GetWBE( p_peek );
2289     for( unsigned i = 0; i < 3; i++ )
2290     {
2291         p_box->data.p_cprt->i_language[i] =
2292             ( ( i_language >> ( (2-i)*5 ) )&0x1f ) + 0x60;
2293     }
2294     p_peek += 2; i_read -= 2;
2295     MP4_GETSTRINGZ( p_box->data.p_cprt->psz_notice );
2296
2297 #ifdef MP4_VERBOSE
2298     msg_Dbg( p_stream, "read box: \"cprt\" language %c%c%c notice %s",
2299                       p_box->data.p_cprt->i_language[0],
2300                       p_box->data.p_cprt->i_language[1],
2301                       p_box->data.p_cprt->i_language[2],
2302                       p_box->data.p_cprt->psz_notice );
2303
2304 #endif
2305     MP4_READBOX_EXIT( 1 );
2306 }
2307
2308 static void MP4_FreeBox_cprt( MP4_Box_t *p_box )
2309 {
2310     FREENULL( p_box->data.p_cprt->psz_notice );
2311 }
2312
2313
2314 static int MP4_ReadBox_dcom( stream_t *p_stream, MP4_Box_t *p_box )
2315 {
2316     MP4_READBOX_ENTER( MP4_Box_data_dcom_t );
2317
2318     MP4_GETFOURCC( p_box->data.p_dcom->i_algorithm );
2319 #ifdef MP4_VERBOSE
2320     msg_Dbg( p_stream,
2321              "read box: \"dcom\" compression algorithm : %4.4s",
2322                       (char*)&p_box->data.p_dcom->i_algorithm );
2323 #endif
2324     MP4_READBOX_EXIT( 1 );
2325 }
2326
2327 static int MP4_ReadBox_cmvd( stream_t *p_stream, MP4_Box_t *p_box )
2328 {
2329     MP4_READBOX_ENTER( MP4_Box_data_cmvd_t );
2330
2331     MP4_GET4BYTES( p_box->data.p_cmvd->i_uncompressed_size );
2332
2333     p_box->data.p_cmvd->i_compressed_size = i_read;
2334
2335     if( !( p_box->data.p_cmvd->p_data = malloc( i_read ) ) )
2336         MP4_READBOX_EXIT( 0 );
2337
2338     /* now copy compressed data */
2339     memcpy( p_box->data.p_cmvd->p_data, p_peek,i_read);
2340
2341     p_box->data.p_cmvd->b_compressed = 1;
2342
2343 #ifdef MP4_VERBOSE
2344     msg_Dbg( p_stream, "read box: \"cmvd\" compressed data size %d",
2345                       p_box->data.p_cmvd->i_compressed_size );
2346 #endif
2347
2348     MP4_READBOX_EXIT( 1 );
2349 }
2350 static void MP4_FreeBox_cmvd( MP4_Box_t *p_box )
2351 {
2352     FREENULL( p_box->data.p_cmvd->p_data );
2353 }
2354
2355
2356 static int MP4_ReadBox_cmov( stream_t *p_stream, MP4_Box_t *p_box )
2357 {
2358     MP4_Box_t *p_dcom;
2359     MP4_Box_t *p_cmvd;
2360
2361 #ifdef HAVE_ZLIB_H
2362     stream_t *p_stream_memory;
2363     z_stream z_data;
2364     uint8_t *p_data;
2365     int i_result;
2366 #endif
2367
2368     if( !( p_box->data.p_cmov = calloc(1, sizeof( MP4_Box_data_cmov_t ) ) ) )
2369         return 0;
2370
2371     if( !p_box->p_father ||
2372         ( p_box->p_father->i_type != ATOM_moov &&
2373           p_box->p_father->i_type != ATOM_foov ) )
2374     {
2375         msg_Warn( p_stream, "Read box: \"cmov\" box alone" );
2376         return 1;
2377     }
2378
2379     if( !MP4_ReadBoxContainer( p_stream, p_box ) )
2380     {
2381         return 0;
2382     }
2383
2384     if( ( p_dcom = MP4_BoxGet( p_box, "dcom" ) ) == NULL ||
2385         ( p_cmvd = MP4_BoxGet( p_box, "cmvd" ) ) == NULL ||
2386         p_cmvd->data.p_cmvd->p_data == NULL )
2387     {
2388         msg_Warn( p_stream, "read box: \"cmov\" incomplete" );
2389         return 0;
2390     }
2391
2392     if( p_dcom->data.p_dcom->i_algorithm != ATOM_zlib )
2393     {
2394         msg_Dbg( p_stream, "read box: \"cmov\" compression algorithm : %4.4s "
2395                  "not supported", (char*)&p_dcom->data.p_dcom->i_algorithm );
2396         return 0;
2397     }
2398
2399 #ifndef HAVE_ZLIB_H
2400     msg_Dbg( p_stream, "read box: \"cmov\" zlib unsupported" );
2401     return 0;
2402
2403 #else
2404     /* decompress data */
2405     /* allocate a new buffer */
2406     if( !( p_data = malloc( p_cmvd->data.p_cmvd->i_uncompressed_size ) ) )
2407         return 0;
2408     /* init default structures */
2409     z_data.next_in   = p_cmvd->data.p_cmvd->p_data;
2410     z_data.avail_in  = p_cmvd->data.p_cmvd->i_compressed_size;
2411     z_data.next_out  = p_data;
2412     z_data.avail_out = p_cmvd->data.p_cmvd->i_uncompressed_size;
2413     z_data.zalloc    = (alloc_func)Z_NULL;
2414     z_data.zfree     = (free_func)Z_NULL;
2415     z_data.opaque    = (voidpf)Z_NULL;
2416
2417     /* init zlib */
2418     if( inflateInit( &z_data ) != Z_OK )
2419     {
2420         msg_Err( p_stream, "read box: \"cmov\" error while uncompressing" );
2421         free( p_data );
2422         return 0;
2423     }
2424
2425     /* uncompress */
2426     i_result = inflate( &z_data, Z_NO_FLUSH );
2427     if( i_result != Z_OK && i_result != Z_STREAM_END )
2428     {
2429         msg_Err( p_stream, "read box: \"cmov\" error while uncompressing" );
2430         free( p_data );
2431         return 0;
2432     }
2433
2434     if( p_cmvd->data.p_cmvd->i_uncompressed_size != z_data.total_out )
2435     {
2436         msg_Warn( p_stream, "read box: \"cmov\" uncompressing data size "
2437                   "mismatch" );
2438     }
2439     p_cmvd->data.p_cmvd->i_uncompressed_size = z_data.total_out;
2440
2441     /* close zlib */
2442     if( inflateEnd( &z_data ) != Z_OK )
2443     {
2444         msg_Warn( p_stream, "read box: \"cmov\" error while uncompressing "
2445                   "data (ignored)" );
2446     }
2447
2448     free( p_cmvd->data.p_cmvd->p_data );
2449     p_cmvd->data.p_cmvd->p_data = p_data;
2450     p_cmvd->data.p_cmvd->b_compressed = 0;
2451
2452     msg_Dbg( p_stream, "read box: \"cmov\" box successfully uncompressed" );
2453
2454     /* now create a memory stream */
2455     p_stream_memory =
2456         stream_MemoryNew( VLC_OBJECT(p_stream), p_cmvd->data.p_cmvd->p_data,
2457                           p_cmvd->data.p_cmvd->i_uncompressed_size, true );
2458
2459     /* and read uncompressd moov */
2460     p_box->data.p_cmov->p_moov = MP4_ReadBox( p_stream_memory, NULL );
2461
2462     stream_Delete( p_stream_memory );
2463
2464 #ifdef MP4_VERBOSE
2465     msg_Dbg( p_stream, "read box: \"cmov\" compressed movie header completed");
2466 #endif
2467
2468     return p_box->data.p_cmov->p_moov ? 1 : 0;
2469 #endif /* HAVE_ZLIB_H */
2470 }
2471
2472 static int MP4_ReadBox_rdrf( stream_t *p_stream, MP4_Box_t *p_box )
2473 {
2474     uint32_t i_len;
2475     MP4_READBOX_ENTER( MP4_Box_data_rdrf_t );
2476
2477     MP4_GETVERSIONFLAGS( p_box->data.p_rdrf );
2478     MP4_GETFOURCC( p_box->data.p_rdrf->i_ref_type );
2479     MP4_GET4BYTES( i_len );
2480     i_len++;
2481
2482     if( i_len > 0 )
2483     {
2484         p_box->data.p_rdrf->psz_ref = malloc( i_len );
2485         if( p_box->data.p_rdrf->psz_ref == NULL )
2486             MP4_READBOX_EXIT( 0 );
2487         i_len--;
2488
2489         for( unsigned i = 0; i < i_len; i++ )
2490         {
2491             MP4_GET1BYTE( p_box->data.p_rdrf->psz_ref[i] );
2492         }
2493         p_box->data.p_rdrf->psz_ref[i_len] = '\0';
2494     }
2495     else
2496     {
2497         p_box->data.p_rdrf->psz_ref = NULL;
2498     }
2499
2500 #ifdef MP4_VERBOSE
2501     msg_Dbg( p_stream,
2502             "read box: \"rdrf\" type:%4.4s ref %s",
2503             (char*)&p_box->data.p_rdrf->i_ref_type,
2504             p_box->data.p_rdrf->psz_ref );
2505 #endif
2506     MP4_READBOX_EXIT( 1 );
2507 }
2508
2509 static void MP4_FreeBox_rdrf( MP4_Box_t *p_box )
2510 {
2511     FREENULL( p_box->data.p_rdrf->psz_ref );
2512 }
2513
2514
2515 static int MP4_ReadBox_rmdr( stream_t *p_stream, MP4_Box_t *p_box )
2516 {
2517     MP4_READBOX_ENTER( MP4_Box_data_rmdr_t );
2518
2519     MP4_GETVERSIONFLAGS( p_box->data.p_rmdr );
2520
2521     MP4_GET4BYTES( p_box->data.p_rmdr->i_rate );
2522
2523 #ifdef MP4_VERBOSE
2524     msg_Dbg( p_stream,
2525              "read box: \"rmdr\" rate:%d",
2526              p_box->data.p_rmdr->i_rate );
2527 #endif
2528     MP4_READBOX_EXIT( 1 );
2529 }
2530
2531 static int MP4_ReadBox_rmqu( stream_t *p_stream, MP4_Box_t *p_box )
2532 {
2533     MP4_READBOX_ENTER( MP4_Box_data_rmqu_t );
2534
2535     MP4_GET4BYTES( p_box->data.p_rmqu->i_quality );
2536
2537 #ifdef MP4_VERBOSE
2538     msg_Dbg( p_stream,
2539              "read box: \"rmqu\" quality:%d",
2540              p_box->data.p_rmqu->i_quality );
2541 #endif
2542     MP4_READBOX_EXIT( 1 );
2543 }
2544
2545 static int MP4_ReadBox_rmvc( stream_t *p_stream, MP4_Box_t *p_box )
2546 {
2547     MP4_READBOX_ENTER( MP4_Box_data_rmvc_t );
2548     MP4_GETVERSIONFLAGS( p_box->data.p_rmvc );
2549
2550     MP4_GETFOURCC( p_box->data.p_rmvc->i_gestaltType );
2551     MP4_GET4BYTES( p_box->data.p_rmvc->i_val1 );
2552     MP4_GET4BYTES( p_box->data.p_rmvc->i_val2 );
2553     MP4_GET2BYTES( p_box->data.p_rmvc->i_checkType );
2554
2555 #ifdef MP4_VERBOSE
2556     msg_Dbg( p_stream,
2557              "read box: \"rmvc\" gestaltType:%4.4s val1:0x%x val2:0x%x checkType:0x%x",
2558              (char*)&p_box->data.p_rmvc->i_gestaltType,
2559              p_box->data.p_rmvc->i_val1,p_box->data.p_rmvc->i_val2,
2560              p_box->data.p_rmvc->i_checkType );
2561 #endif
2562
2563     MP4_READBOX_EXIT( 1 );
2564 }
2565
2566 static int MP4_ReadBox_frma( stream_t *p_stream, MP4_Box_t *p_box )
2567 {
2568     MP4_READBOX_ENTER( MP4_Box_data_frma_t );
2569
2570     MP4_GETFOURCC( p_box->data.p_frma->i_type );
2571
2572 #ifdef MP4_VERBOSE
2573     msg_Dbg( p_stream, "read box: \"frma\" i_type:%4.4s",
2574              (char *)&p_box->data.p_frma->i_type );
2575 #endif
2576
2577     MP4_READBOX_EXIT( 1 );
2578 }
2579
2580 static int MP4_ReadBox_skcr( stream_t *p_stream, MP4_Box_t *p_box )
2581 {
2582     MP4_READBOX_ENTER( MP4_Box_data_skcr_t );
2583
2584     MP4_GET4BYTES( p_box->data.p_skcr->i_init );
2585     MP4_GET4BYTES( p_box->data.p_skcr->i_encr );
2586     MP4_GET4BYTES( p_box->data.p_skcr->i_decr );
2587
2588 #ifdef MP4_VERBOSE
2589     msg_Dbg( p_stream, "read box: \"skcr\" i_init:%d i_encr:%d i_decr:%d",
2590              p_box->data.p_skcr->i_init,
2591              p_box->data.p_skcr->i_encr,
2592              p_box->data.p_skcr->i_decr );
2593 #endif
2594
2595     MP4_READBOX_EXIT( 1 );
2596 }
2597
2598 static int MP4_ReadBox_drms( stream_t *p_stream, MP4_Box_t *p_box )
2599 {
2600     VLC_UNUSED(p_box);
2601     /* ATOMs 'user', 'key', 'iviv', and 'priv' will be skipped,
2602      * so unless data decrypt itself by magic, there will be no playback,
2603      * but we never know... */
2604     msg_Warn( p_stream, "DRM protected streams are not supported." );
2605     return 1;
2606 }
2607
2608 static int MP4_ReadBox_name( stream_t *p_stream, MP4_Box_t *p_box )
2609 {
2610     MP4_READBOX_ENTER( MP4_Box_data_name_t );
2611
2612     p_box->data.p_name->psz_text = malloc( p_box->i_size + 1 - 8 ); /* +\0, -name, -size */
2613     if( p_box->data.p_name->psz_text == NULL )
2614         MP4_READBOX_EXIT( 0 );
2615
2616     memcpy( p_box->data.p_name->psz_text, p_peek, p_box->i_size - 8 );
2617     p_box->data.p_name->psz_text[p_box->i_size - 8] = '\0';
2618
2619 #ifdef MP4_VERBOSE
2620         msg_Dbg( p_stream, "read box: \"name\" text=`%s'",
2621                  p_box->data.p_name->psz_text );
2622 #endif
2623     MP4_READBOX_EXIT( 1 );
2624 }
2625
2626 static void MP4_FreeBox_name( MP4_Box_t *p_box )
2627 {
2628     FREENULL( p_box->data.p_name->psz_text );
2629 }
2630
2631 static int MP4_ReadBox_data( stream_t *p_stream, MP4_Box_t *p_box )
2632 {
2633     MP4_READBOX_ENTER( MP4_Box_data_data_t );
2634
2635     /* What's that header ?? */
2636     if ( i_read <= 8 )
2637         MP4_READBOX_EXIT( 0 );
2638
2639     p_box->data.p_data->p_blob = malloc( i_read - 8 );
2640     if ( !p_box->data.p_data->p_blob )
2641         MP4_READBOX_EXIT( 0 );
2642
2643     p_box->data.p_data->i_blob = i_read - 8;
2644     memcpy( p_box->data.p_data->p_blob, p_peek + 8, i_read - 8 );
2645
2646     MP4_READBOX_EXIT( 1 );
2647 }
2648
2649 static void MP4_FreeBox_data( MP4_Box_t *p_box )
2650 {
2651     free( p_box->data.p_data->p_blob );
2652 }
2653
2654 static int MP4_ReadBox_0xa9xxx( stream_t *p_stream, MP4_Box_t *p_box )
2655 {
2656     uint16_t i16;
2657
2658     MP4_READBOX_ENTER( MP4_Box_data_0xa9xxx_t );
2659
2660     p_box->data.p_0xa9xxx->psz_text = NULL;
2661
2662     MP4_GET2BYTES( i16 );
2663
2664     if( i16 > 0 )
2665     {
2666         int i_length = i16;
2667
2668         MP4_GET2BYTES( i16 );
2669         if( i_length >= i_read ) i_length = i_read + 1;
2670
2671         p_box->data.p_0xa9xxx->psz_text = malloc( i_length );
2672         if( p_box->data.p_0xa9xxx->psz_text == NULL )
2673             MP4_READBOX_EXIT( 0 );
2674
2675         i_length--;
2676         memcpy( p_box->data.p_0xa9xxx->psz_text,
2677                 p_peek, i_length );
2678         p_box->data.p_0xa9xxx->psz_text[i_length] = '\0';
2679
2680 #ifdef MP4_VERBOSE
2681         msg_Dbg( p_stream,
2682                  "read box: \"c%3.3s\" text=`%s'",
2683                  ((char*)&p_box->i_type + 1),
2684                  p_box->data.p_0xa9xxx->psz_text );
2685 #endif
2686     }
2687     else
2688     {
2689         /* try iTune/Quicktime format, rewind to start */
2690         p_peek -= 2; i_read += 2;
2691         // we are expecting a 'data' box
2692         uint32_t i_data_len;
2693         uint32_t i_data_tag;
2694
2695         MP4_GET4BYTES( i_data_len );
2696         if( i_data_len > i_read ) i_data_len = i_read;
2697         MP4_GETFOURCC( i_data_tag );
2698         if( (i_data_len > 0) && (i_data_tag == ATOM_data) )
2699         {
2700             /* data box contains a version/flags field */
2701             uint32_t i_version;
2702             uint32_t i_reserved;
2703             VLC_UNUSED(i_reserved);
2704             MP4_GET4BYTES( i_version );
2705             MP4_GET4BYTES( i_reserved );
2706             // version should be 0, flags should be 1 for text, 0 for data
2707             if( ( i_version == 0x00000001 ) && (i_data_len >= 12 ) )
2708             {
2709                 // the rest is the text
2710                 i_data_len -= 12;
2711                 p_box->data.p_0xa9xxx->psz_text = malloc( i_data_len + 1 );
2712                 if( p_box->data.p_0xa9xxx->psz_text == NULL )
2713                     MP4_READBOX_EXIT( 0 );
2714
2715                 memcpy( p_box->data.p_0xa9xxx->psz_text,
2716                         p_peek, i_data_len );
2717                 p_box->data.p_0xa9xxx->psz_text[i_data_len] = '\0';
2718 #ifdef MP4_VERBOSE
2719         msg_Dbg( p_stream,
2720                  "read box: \"c%3.3s\" text=`%s'",
2721                  ((char*)&p_box->i_type+1),
2722                  p_box->data.p_0xa9xxx->psz_text );
2723 #endif
2724             }
2725             else
2726             {
2727                 // TODO: handle data values for ID3 tag values, track num or cover art,etc...
2728             }
2729         }
2730     }
2731
2732     MP4_READBOX_EXIT( 1 );
2733 }
2734 static void MP4_FreeBox_0xa9xxx( MP4_Box_t *p_box )
2735 {
2736     FREENULL( p_box->data.p_0xa9xxx->psz_text );
2737 }
2738
2739 /* Chapter support */
2740 static void MP4_FreeBox_chpl( MP4_Box_t *p_box )
2741 {
2742     MP4_Box_data_chpl_t *p_chpl = p_box->data.p_chpl;
2743     for( unsigned i = 0; i < p_chpl->i_chapter; i++ )
2744         free( p_chpl->chapter[i].psz_name );
2745 }
2746
2747 static int MP4_ReadBox_chpl( stream_t *p_stream, MP4_Box_t *p_box )
2748 {
2749     MP4_Box_data_chpl_t *p_chpl;
2750     uint32_t i_dummy;
2751     VLC_UNUSED(i_dummy);
2752     int i;
2753     MP4_READBOX_ENTER( MP4_Box_data_chpl_t );
2754
2755     p_chpl = p_box->data.p_chpl;
2756
2757     MP4_GETVERSIONFLAGS( p_chpl );
2758
2759     MP4_GET4BYTES( i_dummy );
2760
2761     MP4_GET1BYTE( p_chpl->i_chapter );
2762
2763     for( i = 0; i < p_chpl->i_chapter; i++ )
2764     {
2765         uint64_t i_start;
2766         uint8_t i_len;
2767         int i_copy;
2768         MP4_GET8BYTES( i_start );
2769         MP4_GET1BYTE( i_len );
2770
2771         p_chpl->chapter[i].psz_name = malloc( i_len + 1 );
2772         if( !p_chpl->chapter[i].psz_name )
2773             MP4_READBOX_EXIT( 0 );
2774
2775         i_copy = __MIN( i_len, i_read );
2776         if( i_copy > 0 )
2777             memcpy( p_chpl->chapter[i].psz_name, p_peek, i_copy );
2778         p_chpl->chapter[i].psz_name[i_copy] = '\0';
2779         p_chpl->chapter[i].i_start = i_start;
2780
2781         p_peek += i_copy;
2782         i_read -= i_copy;
2783     }
2784     /* Bubble sort by increasing start date */
2785     do
2786     {
2787         for( i = 0; i < p_chpl->i_chapter - 1; i++ )
2788         {
2789             if( p_chpl->chapter[i].i_start > p_chpl->chapter[i+1].i_start )
2790             {
2791                 char *psz = p_chpl->chapter[i+1].psz_name;
2792                 int64_t i64 = p_chpl->chapter[i+1].i_start;
2793
2794                 p_chpl->chapter[i+1].psz_name = p_chpl->chapter[i].psz_name;
2795                 p_chpl->chapter[i+1].i_start = p_chpl->chapter[i].i_start;
2796
2797                 p_chpl->chapter[i].psz_name = psz;
2798                 p_chpl->chapter[i].i_start = i64;
2799
2800                 i = -1;
2801                 break;
2802             }
2803         }
2804     } while( i == -1 );
2805
2806 #ifdef MP4_VERBOSE
2807     msg_Dbg( p_stream, "read box: \"chpl\" %d chapters",
2808                        p_chpl->i_chapter );
2809 #endif
2810     MP4_READBOX_EXIT( 1 );
2811 }
2812
2813 static int MP4_ReadBox_tref_generic( stream_t *p_stream, MP4_Box_t *p_box )
2814 {
2815     MP4_READBOX_ENTER( MP4_Box_data_tref_generic_t );
2816
2817     p_box->data.p_tref_generic->i_track_ID = NULL;
2818     p_box->data.p_tref_generic->i_entry_count = i_read / sizeof(uint32_t);
2819     if( p_box->data.p_tref_generic->i_entry_count > 0 )
2820         p_box->data.p_tref_generic->i_track_ID = calloc( p_box->data.p_tref_generic->i_entry_count, sizeof(uint32_t) );
2821     if( p_box->data.p_tref_generic->i_track_ID == NULL )
2822         MP4_READBOX_EXIT( 0 );
2823
2824     for( unsigned i = 0; i < p_box->data.p_tref_generic->i_entry_count; i++ )
2825     {
2826         MP4_GET4BYTES( p_box->data.p_tref_generic->i_track_ID[i] );
2827     }
2828 #ifdef MP4_VERBOSE
2829         msg_Dbg( p_stream, "read box: \"chap\" %d references",
2830                  p_box->data.p_tref_generic->i_entry_count );
2831 #endif
2832
2833     MP4_READBOX_EXIT( 1 );
2834 }
2835 static void MP4_FreeBox_tref_generic( MP4_Box_t *p_box )
2836 {
2837     FREENULL( p_box->data.p_tref_generic->i_track_ID );
2838 }
2839
2840 static int MP4_ReadBox_meta( stream_t *p_stream, MP4_Box_t *p_box )
2841 {
2842     uint8_t meta_data[8];
2843     int i_actually_read;
2844
2845     // skip over box header
2846     i_actually_read = stream_Read( p_stream, meta_data, 8 );
2847     if( i_actually_read < 8 )
2848         return 0;
2849
2850     /* meta content starts with a 4 byte version/flags value (should be 0) */
2851     i_actually_read = stream_Read( p_stream, meta_data, 4 );
2852     if( i_actually_read < 4 )
2853         return 0;
2854
2855     /* then it behaves like a container */
2856     return MP4_ReadBoxContainerRaw( p_stream, p_box );
2857 }
2858
2859 static int MP4_ReadBox_iods( stream_t *p_stream, MP4_Box_t *p_box )
2860 {
2861     char i_unused;
2862     VLC_UNUSED(i_unused);
2863
2864     MP4_READBOX_ENTER( MP4_Box_data_iods_t );
2865     MP4_GETVERSIONFLAGS( p_box->data.p_iods );
2866
2867     MP4_GET1BYTE( i_unused ); /* tag */
2868     MP4_GET1BYTE( i_unused ); /* length */
2869
2870     MP4_GET2BYTES( p_box->data.p_iods->i_object_descriptor ); /* 10bits, 6 other bits
2871                                                               are used for other flags */
2872     MP4_GET1BYTE( p_box->data.p_iods->i_OD_profile_level );
2873     MP4_GET1BYTE( p_box->data.p_iods->i_scene_profile_level );
2874     MP4_GET1BYTE( p_box->data.p_iods->i_audio_profile_level );
2875     MP4_GET1BYTE( p_box->data.p_iods->i_visual_profile_level );
2876     MP4_GET1BYTE( p_box->data.p_iods->i_graphics_profile_level );
2877
2878 #ifdef MP4_VERBOSE
2879     msg_Dbg( p_stream,
2880              "read box: \"iods\" objectDescriptorId: %i, OD: %i, scene: %i, audio: %i, "
2881              "visual: %i, graphics: %i",
2882              p_box->data.p_iods->i_object_descriptor >> 6,
2883              p_box->data.p_iods->i_OD_profile_level,
2884              p_box->data.p_iods->i_scene_profile_level,
2885              p_box->data.p_iods->i_audio_profile_level,
2886              p_box->data.p_iods->i_visual_profile_level,
2887              p_box->data.p_iods->i_graphics_profile_level );
2888 #endif
2889
2890     MP4_READBOX_EXIT( 1 );
2891 }
2892
2893 static int MP4_ReadBox_pasp( stream_t *p_stream, MP4_Box_t *p_box )
2894 {
2895     MP4_READBOX_ENTER( MP4_Box_data_pasp_t );
2896
2897     MP4_GET4BYTES( p_box->data.p_pasp->i_horizontal_spacing );
2898     MP4_GET4BYTES( p_box->data.p_pasp->i_vertical_spacing );
2899
2900 #ifdef MP4_VERBOSE
2901     msg_Dbg( p_stream,
2902              "read box: \"paps\" %dx%d",
2903              p_box->data.p_pasp->i_horizontal_spacing,
2904              p_box->data.p_pasp->i_vertical_spacing);
2905 #endif
2906
2907     MP4_READBOX_EXIT( 1 );
2908 }
2909
2910 static int MP4_ReadBox_mehd( stream_t *p_stream, MP4_Box_t *p_box )
2911 {
2912     MP4_READBOX_ENTER( MP4_Box_data_mehd_t );
2913
2914     MP4_GETVERSIONFLAGS( p_box->data.p_mehd );
2915     if( p_box->data.p_mehd->i_version == 1 )
2916         MP4_GET8BYTES( p_box->data.p_mehd->i_fragment_duration );
2917     else /* version == 0 */
2918         MP4_GET4BYTES( p_box->data.p_mehd->i_fragment_duration );
2919
2920 #ifdef MP4_VERBOSE
2921     msg_Dbg( p_stream,
2922              "read box: \"mehd\" frag dur. %"PRIu64"",
2923              p_box->data.p_mehd->i_fragment_duration );
2924 #endif
2925
2926     MP4_READBOX_EXIT( 1 );
2927 }
2928
2929 static int MP4_ReadBox_trex( stream_t *p_stream, MP4_Box_t *p_box )
2930 {
2931     MP4_READBOX_ENTER( MP4_Box_data_trex_t );
2932     MP4_GETVERSIONFLAGS( p_box->data.p_trex );
2933
2934     MP4_GET4BYTES( p_box->data.p_trex->i_track_ID );
2935     MP4_GET4BYTES( p_box->data.p_trex->i_default_sample_description_index );
2936     MP4_GET4BYTES( p_box->data.p_trex->i_default_sample_duration );
2937     MP4_GET4BYTES( p_box->data.p_trex->i_default_sample_size );
2938     MP4_GET4BYTES( p_box->data.p_trex->i_default_sample_flags );
2939
2940 #ifdef MP4_VERBOSE
2941     msg_Dbg( p_stream,
2942              "read box: \"trex\" trackID: %"PRIu32"",
2943              p_box->data.p_trex->i_track_ID );
2944 #endif
2945
2946     MP4_READBOX_EXIT( 1 );
2947 }
2948
2949 static int MP4_ReadBox_sdtp( stream_t *p_stream, MP4_Box_t *p_box )
2950 {
2951     uint32_t i_sample_count;
2952     MP4_READBOX_ENTER( MP4_Box_data_sdtp_t );
2953     MP4_Box_data_sdtp_t *p_sdtp = p_box->data.p_sdtp;
2954     MP4_GETVERSIONFLAGS( p_box->data.p_sdtp );
2955     i_sample_count = i_read;
2956
2957     p_sdtp->p_sample_table = calloc( i_sample_count, 1 );
2958
2959     if( !p_sdtp->p_sample_table )
2960         MP4_READBOX_EXIT( 0 );
2961
2962     for( uint32_t i = 0; i < i_sample_count; i++ )
2963         MP4_GET1BYTE( p_sdtp->p_sample_table[i] );
2964
2965 #ifdef MP4_VERBOSE
2966     msg_Dbg( p_stream, "i_sample_count is %"PRIu32"", i_sample_count );
2967     msg_Dbg( p_stream,
2968              "read box: \"sdtp\" head: %"PRIx8" %"PRIx8" %"PRIx8" %"PRIx8"",
2969                  p_sdtp->p_sample_table[0],
2970                  p_sdtp->p_sample_table[1],
2971                  p_sdtp->p_sample_table[2],
2972                  p_sdtp->p_sample_table[3] );
2973 #endif
2974
2975     MP4_READBOX_EXIT( 1 );
2976 }
2977
2978 static void MP4_FreeBox_sdtp( MP4_Box_t *p_box )
2979 {
2980     FREENULL( p_box->data.p_sdtp->p_sample_table );
2981 }
2982
2983 static int MP4_ReadBox_mfro( stream_t *p_stream, MP4_Box_t *p_box )
2984 {
2985     MP4_READBOX_ENTER( MP4_Box_data_mfro_t );
2986
2987     MP4_GETVERSIONFLAGS( p_box->data.p_mfro );
2988     MP4_GET4BYTES( p_box->data.p_mfro->i_size );
2989
2990 #ifdef MP4_VERBOSE
2991     msg_Dbg( p_stream,
2992              "read box: \"mfro\" size: %"PRIu32"",
2993              p_box->data.p_mfro->i_size);
2994 #endif
2995
2996     MP4_READBOX_EXIT( 1 );
2997 }
2998
2999 static int MP4_ReadBox_tfra( stream_t *p_stream, MP4_Box_t *p_box )
3000 {
3001     uint32_t i_number_of_entries;
3002     MP4_READBOX_ENTER( MP4_Box_data_tfra_t );
3003     MP4_Box_data_tfra_t *p_tfra = p_box->data.p_tfra;
3004     MP4_GETVERSIONFLAGS( p_box->data.p_tfra );
3005
3006     MP4_GET4BYTES( p_tfra->i_track_ID );
3007     uint32_t i_lengths = 0;
3008     MP4_GET4BYTES( i_lengths );
3009     MP4_GET4BYTES( p_tfra->i_number_of_entries );
3010     i_number_of_entries = p_tfra->i_number_of_entries;
3011     p_tfra->i_length_size_of_traf_num = i_lengths >> 4;
3012     p_tfra->i_length_size_of_trun_num = ( i_lengths & 0x0c ) >> 2;
3013     p_tfra->i_length_size_of_sample_num = i_lengths & 0x03;
3014
3015     size_t size = 4 + 4*p_tfra->i_version; /* size in {4, 8} */
3016     p_tfra->p_time = calloc( i_number_of_entries, size );
3017     p_tfra->p_moof_offset = calloc( i_number_of_entries, size );
3018
3019     size = 1 + p_tfra->i_length_size_of_traf_num; /* size in [|1, 4|] */
3020     p_tfra->p_traf_number = calloc( i_number_of_entries, size );
3021     size = 1 + p_tfra->i_length_size_of_trun_num;
3022     p_tfra->p_trun_number = calloc( i_number_of_entries, size );
3023     size = 1 + p_tfra->i_length_size_of_sample_num;
3024     p_tfra->p_sample_number = calloc( i_number_of_entries, size );
3025
3026     if( !p_tfra->p_time || !p_tfra->p_moof_offset || !p_tfra->p_traf_number
3027                         || !p_tfra->p_trun_number || !p_tfra->p_sample_number )
3028         goto error;
3029
3030     for( uint32_t i = 0; i < i_number_of_entries; i++ )
3031     {
3032         if( p_tfra->i_version == 1 )
3033         {
3034             MP4_GET8BYTES( p_tfra->p_time[i*2] );
3035             MP4_GET8BYTES( p_tfra->p_moof_offset[i*2] );
3036         }
3037         else
3038         {
3039             MP4_GET4BYTES( p_tfra->p_time[i] );
3040             MP4_GET4BYTES( p_tfra->p_moof_offset[i] );
3041         }
3042         switch (p_tfra->i_length_size_of_traf_num)
3043         {
3044             case 0:
3045                 MP4_GET1BYTE( p_tfra->p_traf_number[i] );
3046                 break;
3047             case 1:
3048                 MP4_GET2BYTES( p_tfra->p_traf_number[i*2] );
3049                 break;
3050             case 2:
3051                 MP4_GET3BYTES( p_tfra->p_traf_number[i*3] );
3052                 break;
3053             case 3:
3054                 MP4_GET4BYTES( p_tfra->p_traf_number[i*4] );
3055                 break;
3056             default:
3057                 goto error;
3058         }
3059
3060         switch (p_tfra->i_length_size_of_trun_num)
3061         {
3062             case 0:
3063                 MP4_GET1BYTE( p_tfra->p_trun_number[i] );
3064                 break;
3065             case 1:
3066                 MP4_GET2BYTES( p_tfra->p_trun_number[i*2] );
3067                 break;
3068             case 2:
3069                 MP4_GET3BYTES( p_tfra->p_trun_number[i*3] );
3070                 break;
3071             case 3:
3072                 MP4_GET4BYTES( p_tfra->p_trun_number[i*4] );
3073                 break;
3074             default:
3075                 goto error;
3076         }
3077
3078         switch (p_tfra->i_length_size_of_sample_num)
3079         {
3080             case 0:
3081                 MP4_GET1BYTE( p_tfra->p_sample_number[i] );
3082                 break;
3083             case 1:
3084                 MP4_GET2BYTES( p_tfra->p_sample_number[i*2] );
3085                 break;
3086             case 2:
3087                 MP4_GET3BYTES( p_tfra->p_sample_number[i*3] );
3088                 break;
3089             case 3:
3090                 MP4_GET4BYTES( p_tfra->p_sample_number[i*4] );
3091                 break;
3092             default:
3093                 goto error;
3094         }
3095     }
3096
3097 #ifdef MP4_VERBOSE
3098     if( p_tfra->i_version == 0 )
3099     {
3100         msg_Dbg( p_stream, "time[0]: %"PRIu32", moof_offset[0]: %"PRIx32"",
3101                          p_tfra->p_time[0], p_tfra->p_moof_offset[0] );
3102
3103         msg_Dbg( p_stream, "time[1]: %"PRIu32", moof_offset[1]: %"PRIx32"",
3104                          p_tfra->p_time[1], p_tfra->p_moof_offset[1] );
3105     }
3106     else
3107     {
3108         msg_Dbg( p_stream, "time[0]: %"PRIu64", moof_offset[0]: %"PRIx64"",
3109                 ((uint64_t *)(p_tfra->p_time))[0],
3110                 ((uint64_t *)(p_tfra->p_moof_offset))[0] );
3111
3112         msg_Dbg( p_stream, "time[1]: %"PRIu64", moof_offset[1]: %"PRIx64"",
3113                 ((uint64_t *)(p_tfra->p_time))[1],
3114                 ((uint64_t *)(p_tfra->p_moof_offset))[1] );
3115     }
3116
3117     msg_Dbg( p_stream, "number_of_entries is %"PRIu32"", i_number_of_entries );
3118     msg_Dbg( p_stream, "track ID is: %"PRIu32"", p_tfra->i_track_ID );
3119 #endif
3120
3121     MP4_READBOX_EXIT( 1 );
3122 error:
3123     MP4_READBOX_EXIT( 0 );
3124 }
3125
3126 static void MP4_FreeBox_tfra( MP4_Box_t *p_box )
3127 {
3128     FREENULL( p_box->data.p_tfra->p_time );
3129     FREENULL( p_box->data.p_tfra->p_moof_offset );
3130     FREENULL( p_box->data.p_tfra->p_traf_number );
3131     FREENULL( p_box->data.p_tfra->p_trun_number );
3132     FREENULL( p_box->data.p_tfra->p_sample_number );
3133 }
3134
3135
3136 /* For generic */
3137 static int MP4_ReadBox_default( stream_t *p_stream, MP4_Box_t *p_box )
3138 {
3139     if( !p_box->p_father )
3140     {
3141         goto unknown;
3142     }
3143     if( p_box->p_father->i_type == ATOM_stsd )
3144     {
3145         MP4_Box_t *p_mdia = MP4_BoxGet( p_box, "../../../.." );
3146         MP4_Box_t *p_hdlr;
3147
3148         if( p_mdia == NULL || p_mdia->i_type != ATOM_mdia ||
3149             (p_hdlr = MP4_BoxGet( p_mdia, "hdlr" )) == NULL )
3150         {
3151             goto unknown;
3152         }
3153         switch( p_hdlr->data.p_hdlr->i_handler_type )
3154         {
3155             case ATOM_soun:
3156                 return MP4_ReadBox_sample_soun( p_stream, p_box );
3157             case ATOM_vide:
3158                 return MP4_ReadBox_sample_vide( p_stream, p_box );
3159             case ATOM_text:
3160                 return MP4_ReadBox_sample_text( p_stream, p_box );
3161             case ATOM_tx3g:
3162             case ATOM_sbtl:
3163                 return MP4_ReadBox_sample_tx3g( p_stream, p_box );
3164             default:
3165                 msg_Warn( p_stream,
3166                           "unknown handler type in stsd (incompletely loaded)" );
3167                 return 1;
3168         }
3169     }
3170
3171 unknown:
3172     if MP4_BOX_TYPE_ASCII()
3173         msg_Warn( p_stream,
3174                 "unknown box type %4.4s (incompletely loaded)",
3175                 (char*)&p_box->i_type );
3176     else
3177         msg_Warn( p_stream,
3178                 "unknown box type c%3.3s (incompletely loaded)",
3179                 (char*)&p_box->i_type+1 );
3180
3181     return 1;
3182 }
3183
3184 /**** ------------------------------------------------------------------- ****/
3185 /****                   "Higher level" Functions                          ****/
3186 /**** ------------------------------------------------------------------- ****/
3187
3188 static const struct
3189 {
3190     uint32_t i_type;
3191     int  (*MP4_ReadBox_function )( stream_t *p_stream, MP4_Box_t *p_box );
3192     void (*MP4_FreeBox_function )( MP4_Box_t *p_box );
3193 } MP4_Box_Function [] =
3194 {
3195     /* Containers */
3196     { ATOM_moov,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3197     { ATOM_trak,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3198     { ATOM_mdia,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3199     { ATOM_moof,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3200     { ATOM_minf,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3201     { ATOM_stbl,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3202     { ATOM_dinf,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3203     { ATOM_edts,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3204     { ATOM_udta,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3205     { ATOM_nmhd,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3206     { ATOM_hnti,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3207     { ATOM_rmra,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3208     { ATOM_rmda,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3209     { ATOM_tref,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3210     { ATOM_gmhd,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3211     { ATOM_wave,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3212     { ATOM_ilst,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3213     { ATOM_mvex,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3214
3215     /* specific box */
3216     { ATOM_ftyp,    MP4_ReadBox_ftyp,         MP4_FreeBox_ftyp },
3217     { ATOM_cmov,    MP4_ReadBox_cmov,         MP4_FreeBox_Common },
3218     { ATOM_mvhd,    MP4_ReadBox_mvhd,         MP4_FreeBox_Common },
3219     { ATOM_tkhd,    MP4_ReadBox_tkhd,         MP4_FreeBox_Common },
3220     { ATOM_mdhd,    MP4_ReadBox_mdhd,         MP4_FreeBox_Common },
3221     { ATOM_hdlr,    MP4_ReadBox_hdlr,         MP4_FreeBox_hdlr },
3222     { ATOM_vmhd,    MP4_ReadBox_vmhd,         MP4_FreeBox_Common },
3223     { ATOM_smhd,    MP4_ReadBox_smhd,         MP4_FreeBox_Common },
3224     { ATOM_hmhd,    MP4_ReadBox_hmhd,         MP4_FreeBox_Common },
3225     { ATOM_url,     MP4_ReadBox_url,          MP4_FreeBox_url },
3226     { ATOM_urn,     MP4_ReadBox_urn,          MP4_FreeBox_urn },
3227     { ATOM_dref,    MP4_ReadBox_dref,         MP4_FreeBox_Common },
3228     { ATOM_stts,    MP4_ReadBox_stts,         MP4_FreeBox_stts },
3229     { ATOM_ctts,    MP4_ReadBox_ctts,         MP4_FreeBox_ctts },
3230     { ATOM_stsd,    MP4_ReadBox_stsd,         MP4_FreeBox_Common },
3231     { ATOM_stsz,    MP4_ReadBox_stsz,         MP4_FreeBox_stsz },
3232     { ATOM_stsc,    MP4_ReadBox_stsc,         MP4_FreeBox_stsc },
3233     { ATOM_stco,    MP4_ReadBox_stco_co64,    MP4_FreeBox_stco_co64 },
3234     { ATOM_co64,    MP4_ReadBox_stco_co64,    MP4_FreeBox_stco_co64 },
3235     { ATOM_stss,    MP4_ReadBox_stss,         MP4_FreeBox_stss },
3236     { ATOM_stsh,    MP4_ReadBox_stsh,         MP4_FreeBox_stsh },
3237     { ATOM_stdp,    MP4_ReadBox_stdp,         MP4_FreeBox_stdp },
3238     { ATOM_padb,    MP4_ReadBox_padb,         MP4_FreeBox_padb },
3239     { ATOM_elst,    MP4_ReadBox_elst,         MP4_FreeBox_elst },
3240     { ATOM_cprt,    MP4_ReadBox_cprt,         MP4_FreeBox_cprt },
3241     { ATOM_esds,    MP4_ReadBox_esds,         MP4_FreeBox_esds },
3242     { ATOM_dcom,    MP4_ReadBox_dcom,         MP4_FreeBox_Common },
3243     { ATOM_cmvd,    MP4_ReadBox_cmvd,         MP4_FreeBox_cmvd },
3244     { ATOM_avcC,    MP4_ReadBox_avcC,         MP4_FreeBox_avcC },
3245     { ATOM_hvcC,    MP4_ReadBox_hvcC,         MP4_FreeBox_hvcC },
3246     { ATOM_dac3,    MP4_ReadBox_dac3,         MP4_FreeBox_Common },
3247     { ATOM_dvc1,    MP4_ReadBox_dvc1,         MP4_FreeBox_Common },
3248     { ATOM_enda,    MP4_ReadBox_enda,         MP4_FreeBox_Common },
3249     { ATOM_gnre,    MP4_ReadBox_gnre,         MP4_FreeBox_Common },
3250     { ATOM_trkn,    MP4_ReadBox_trkn,         MP4_FreeBox_Common },
3251     { ATOM_iods,    MP4_ReadBox_iods,         MP4_FreeBox_Common },
3252     { ATOM_pasp,    MP4_ReadBox_pasp,         MP4_FreeBox_Common },
3253
3254     /* Nothing to do with this box */
3255     { ATOM_mdat,    MP4_ReadBoxSkip,          MP4_FreeBox_Common },
3256     { ATOM_skip,    MP4_ReadBoxSkip,          MP4_FreeBox_Common },
3257     { ATOM_free,    MP4_ReadBoxSkip,          MP4_FreeBox_Common },
3258     { ATOM_wide,    MP4_ReadBoxSkip,          MP4_FreeBox_Common },
3259
3260     /* Subtitles */
3261     { ATOM_tx3g,    MP4_ReadBox_sample_tx3g,      MP4_FreeBox_Common },
3262     //{ ATOM_text,    MP4_ReadBox_sample_text,      MP4_FreeBox_Common },
3263
3264     /* for codecs */
3265     { ATOM_soun,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3266     { ATOM_ms02,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3267     { ATOM_ms11,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3268     { ATOM_ms55,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3269     { ATOM__mp3,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3270     { ATOM_mp4a,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3271     { ATOM_twos,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3272     { ATOM_sowt,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3273     { ATOM_QDMC,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3274     { ATOM_QDM2,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3275     { ATOM_ima4,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3276     { ATOM_IMA4,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3277     { ATOM_dvi,     MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3278     { ATOM_alaw,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3279     { ATOM_ulaw,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3280     { ATOM_raw,     MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3281     { ATOM_MAC3,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3282     { ATOM_MAC6,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3283     { ATOM_Qclp,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3284     { ATOM_samr,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3285     { ATOM_sawb,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3286     { ATOM_OggS,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3287     { ATOM_alac,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3288
3289     { ATOM_drmi,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3290     { ATOM_vide,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3291     { ATOM_mp4v,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3292     { ATOM_SVQ1,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3293     { ATOM_SVQ3,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3294     { ATOM_ZyGo,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3295     { ATOM_DIVX,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3296     { ATOM_XVID,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3297     { ATOM_h263,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3298     { ATOM_s263,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3299     { ATOM_cvid,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3300     { ATOM_3IV1,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3301     { ATOM_3iv1,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3302     { ATOM_3IV2,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3303     { ATOM_3iv2,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3304     { ATOM_3IVD,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3305     { ATOM_3ivd,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3306     { ATOM_3VID,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3307     { ATOM_3vid,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3308     { ATOM_mjpa,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3309     { ATOM_mjpb,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3310     { ATOM_qdrw,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3311     { ATOM_mp2v,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3312     { ATOM_hdv2,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3313
3314     { ATOM_mjqt,    MP4_ReadBox_default,      NULL }, /* found in mjpa/b */
3315     { ATOM_mjht,    MP4_ReadBox_default,      NULL },
3316
3317     { ATOM_dvc,     MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3318     { ATOM_dvp,     MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3319     { ATOM_dv5n,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3320     { ATOM_dv5p,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3321     { ATOM_VP31,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3322     { ATOM_vp31,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3323     { ATOM_h264,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3324
3325     { ATOM_jpeg,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3326     { ATOM_avc1,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3327
3328     { ATOM_yv12,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3329     { ATOM_yuv2,    MP4_ReadBox_sample_vide,  MP4_FreeBox_sample_vide },
3330
3331     { ATOM_mp4s,    MP4_ReadBox_sample_mp4s,  MP4_FreeBox_Common },
3332
3333     /* XXX there is 2 box where we could find this entry stbl and tref*/
3334     { ATOM_hint,    MP4_ReadBox_default,      MP4_FreeBox_Common },
3335
3336     /* found in tref box */
3337     { ATOM_dpnd,    MP4_ReadBox_default,      NULL },
3338     { ATOM_ipir,    MP4_ReadBox_default,      NULL },
3339     { ATOM_mpod,    MP4_ReadBox_default,      NULL },
3340     { ATOM_chap,    MP4_ReadBox_tref_generic, MP4_FreeBox_tref_generic },
3341
3342     /* found in hnti */
3343     { ATOM_rtp,     MP4_ReadBox_default,      NULL },
3344
3345     /* found in rmra */
3346     { ATOM_rdrf,    MP4_ReadBox_rdrf,         MP4_FreeBox_rdrf   },
3347     { ATOM_rmdr,    MP4_ReadBox_rmdr,         MP4_FreeBox_Common },
3348     { ATOM_rmqu,    MP4_ReadBox_rmqu,         MP4_FreeBox_Common },
3349     { ATOM_rmvc,    MP4_ReadBox_rmvc,         MP4_FreeBox_Common },
3350
3351     { ATOM_drms,    MP4_ReadBox_sample_soun,  MP4_FreeBox_sample_soun },
3352     { ATOM_sinf,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3353     { ATOM_schi,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3354     { ATOM_user,    MP4_ReadBox_drms,         MP4_FreeBox_Common },
3355     { ATOM_key,     MP4_ReadBox_drms,         MP4_FreeBox_Common },
3356     { ATOM_iviv,    MP4_ReadBox_drms,         MP4_FreeBox_Common },
3357     { ATOM_priv,    MP4_ReadBox_drms,         MP4_FreeBox_Common },
3358     { ATOM_frma,    MP4_ReadBox_frma,         MP4_FreeBox_Common },
3359     { ATOM_skcr,    MP4_ReadBox_skcr,         MP4_FreeBox_Common },
3360
3361     /* found in udta */
3362     { ATOM_0xa9nam, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3363     { ATOM_0xa9aut, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3364     { ATOM_0xa9cpy, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3365     { ATOM_0xa9swr, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3366     { ATOM_0xa9inf, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3367     { ATOM_0xa9ART, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3368     { ATOM_0xa9dir, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3369     { ATOM_0xa9cmt, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3370     { ATOM_0xa9req, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3371     { ATOM_0xa9day, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3372     { ATOM_0xa9des, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3373     { ATOM_0xa9fmt, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3374     { ATOM_0xa9prd, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3375     { ATOM_0xa9prf, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3376     { ATOM_0xa9src, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3377     { ATOM_0xa9alb, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3378     { ATOM_0xa9dis, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3379     { ATOM_0xa9enc, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3380     { ATOM_0xa9gen, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3381     { ATOM_0xa9trk, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3382     { ATOM_0xa9dsa, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3383     { ATOM_0xa9hst, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3384     { ATOM_0xa9url, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3385     { ATOM_0xa9ope, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3386     { ATOM_0xa9com, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3387     { ATOM_0xa9wrt, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3388     { ATOM_0xa9too, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3389     { ATOM_0xa9wrn, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3390     { ATOM_0xa9mak, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3391     { ATOM_0xa9mod, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3392     { ATOM_0xa9PRD, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3393     { ATOM_0xa9grp, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3394     { ATOM_0xa9lyr, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3395     { ATOM_0xa9gen, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3396     { ATOM_0xa9st3, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3397     { ATOM_0xa9ard, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3398     { ATOM_0xa9arg, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3399     { ATOM_0xa9cak, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3400     { ATOM_0xa9con, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3401     { ATOM_0xa9des, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3402     { ATOM_0xa9lnt, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3403     { ATOM_0xa9phg, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3404     { ATOM_0xa9pub, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3405     { ATOM_0xa9sne, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3406     { ATOM_0xa9sol, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3407     { ATOM_0xa9thx, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3408     { ATOM_0xa9xpd, MP4_ReadBox_0xa9xxx,      MP4_FreeBox_0xa9xxx },
3409
3410     { ATOM_chpl,    MP4_ReadBox_chpl,         MP4_FreeBox_chpl },
3411
3412     /* iTunes/Quicktime meta info */
3413     { ATOM_meta,    MP4_ReadBox_meta,         MP4_FreeBox_Common },
3414     { ATOM_name,    MP4_ReadBox_name,         MP4_FreeBox_name },
3415     { ATOM_covr,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3416     { ATOM_data,    MP4_ReadBox_data,         MP4_FreeBox_data },
3417
3418     /* found in smoothstreaming */
3419     { ATOM_traf,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3420     { ATOM_mfra,    MP4_ReadBoxContainer,     MP4_FreeBox_Common },
3421     { ATOM_mfhd,    MP4_ReadBox_mfhd,         MP4_FreeBox_Common },
3422     { ATOM_sidx,    MP4_ReadBox_sidx,         MP4_FreeBox_sidx },
3423     { ATOM_tfhd,    MP4_ReadBox_tfhd,         MP4_FreeBox_Common },
3424     { ATOM_trun,    MP4_ReadBox_trun,         MP4_FreeBox_trun },
3425     { ATOM_trex,    MP4_ReadBox_trex,         MP4_FreeBox_Common },
3426     { ATOM_mehd,    MP4_ReadBox_mehd,         MP4_FreeBox_Common },
3427     { ATOM_sdtp,    MP4_ReadBox_sdtp,         MP4_FreeBox_sdtp },
3428     { ATOM_tfra,    MP4_ReadBox_tfra,         MP4_FreeBox_tfra },
3429     { ATOM_mfro,    MP4_ReadBox_mfro,         MP4_FreeBox_Common },
3430     { ATOM_uuid,    MP4_ReadBox_uuid,         MP4_FreeBox_uuid },
3431
3432     /* Last entry */
3433     { 0,              MP4_ReadBox_default,      NULL }
3434 };
3435
3436
3437 /*****************************************************************************
3438  * MP4_ReadBox : parse the actual box and the children
3439  *  XXX : Do not go to the next box
3440  *****************************************************************************/
3441 static MP4_Box_t *MP4_ReadBox( stream_t *p_stream, MP4_Box_t *p_father )
3442 {
3443     MP4_Box_t *p_box = calloc( 1, sizeof( MP4_Box_t ) ); /* Needed to ensure simple on error handler */
3444     unsigned int i_index;
3445
3446     if( p_box == NULL )
3447         return NULL;
3448
3449     if( !MP4_ReadBoxCommon( p_stream, p_box ) )
3450     {
3451         msg_Warn( p_stream, "cannot read one box" );
3452         free( p_box );
3453         return NULL;
3454     }
3455     if( !p_box->i_size )
3456     {
3457         msg_Dbg( p_stream, "found an empty box (null size)" );
3458         free( p_box );
3459         return NULL;
3460     }
3461     p_box->p_father = p_father;
3462
3463     /* Now search function to call */
3464     for( i_index = 0; ; i_index++ )
3465     {
3466         if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
3467             ( MP4_Box_Function[i_index].i_type == 0 ) )
3468         {
3469             break;
3470         }
3471     }
3472
3473     if( !(MP4_Box_Function[i_index].MP4_ReadBox_function)( p_stream, p_box ) )
3474     {
3475         MP4_BoxFree( p_stream, p_box );
3476         return NULL;
3477     }
3478
3479     return p_box;
3480 }
3481
3482 /*****************************************************************************
3483  * MP4_FreeBox : free memory after read with MP4_ReadBox and all
3484  * the children
3485  *****************************************************************************/
3486 void MP4_BoxFree( stream_t *s, MP4_Box_t *p_box )
3487 {
3488     unsigned int i_index;
3489     MP4_Box_t    *p_child;
3490
3491     if( !p_box )
3492         return; /* hehe */
3493
3494     for( p_child = p_box->p_first; p_child != NULL; )
3495     {
3496         MP4_Box_t *p_next;
3497
3498         p_next = p_child->p_next;
3499         MP4_BoxFree( s, p_child );
3500         p_child = p_next;
3501     }
3502
3503     /* Now search function to call */
3504     if( p_box->data.p_payload )
3505     {
3506         for( i_index = 0; ; i_index++ )
3507         {
3508             if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
3509                 ( MP4_Box_Function[i_index].i_type == 0 ) )
3510             {
3511                 break;
3512             }
3513         }
3514         if( MP4_Box_Function[i_index].MP4_FreeBox_function == NULL )
3515         {
3516             /* Should not happen */
3517             if MP4_BOX_TYPE_ASCII()
3518                 msg_Warn( s,
3519                         "cannot free box %4.4s, type unknown",
3520                         (char*)&p_box->i_type );
3521             else
3522                 msg_Warn( s,
3523                         "cannot free box c%3.3s, type unknown",
3524                         (char*)&p_box->i_type+1 );
3525         }
3526         else
3527         {
3528             MP4_Box_Function[i_index].MP4_FreeBox_function( p_box );
3529         }
3530         free( p_box->data.p_payload );
3531     }
3532     free( p_box );
3533 }
3534
3535 /* SmooBox is a very simple MP4 box, VLC specific, used only for the stream_filter to
3536  * send information to the demux. SmooBox is actually a simplified moov box (we wanted
3537  * to avoid the hassle of building a moov box at the stream_filter level) */
3538 MP4_Box_t *MP4_BoxGetSmooBox( stream_t *s )
3539 {
3540     /* p_chunk is a virtual root container for the smoo box */
3541     MP4_Box_t *p_chunk;
3542     MP4_Box_t *p_smoo;
3543
3544     p_chunk = calloc( 1, sizeof( MP4_Box_t ) );
3545     if( unlikely( p_chunk == NULL ) )
3546         return NULL;
3547
3548     p_chunk->i_type = ATOM_root;
3549     p_chunk->i_shortsize = 1;
3550
3551     p_smoo = MP4_ReadBox( s, p_chunk );
3552     if( !p_smoo || p_smoo->i_type != ATOM_uuid || CmpUUID( &p_smoo->i_uuid, &SmooBoxUUID ) )
3553     {
3554         msg_Warn( s, "no smoo box found!");
3555         goto error;
3556     }
3557
3558     p_chunk->p_first = p_smoo;
3559     p_chunk->p_last = p_smoo;
3560
3561     return p_chunk;
3562
3563 error:
3564     free( p_chunk );
3565     return NULL;
3566 }
3567
3568 MP4_Box_t *MP4_BoxGetNextChunk( stream_t *s )
3569 {
3570     /* p_chunk is a virtual root container for the moof and mdat boxes */
3571     MP4_Box_t *p_chunk;
3572     MP4_Box_t *p_tmp_box = NULL;
3573
3574     p_tmp_box = calloc( 1, sizeof( MP4_Box_t ) );
3575     if( unlikely( p_tmp_box == NULL ) )
3576         return NULL;
3577
3578     /* We might get a ftyp box or a SmooBox */
3579     MP4_ReadBoxCommon( s, p_tmp_box );
3580
3581     if( (p_tmp_box->i_type == ATOM_uuid && !CmpUUID( &p_tmp_box->i_uuid, &SmooBoxUUID )) )
3582     {
3583         free( p_tmp_box );
3584         return MP4_BoxGetSmooBox( s );
3585     }
3586     else if( p_tmp_box->i_type == ATOM_ftyp )
3587     {
3588         free( p_tmp_box );
3589         return MP4_BoxGetRoot( s );
3590     }
3591     free( p_tmp_box );
3592
3593     p_chunk = calloc( 1, sizeof( MP4_Box_t ) );
3594     if( unlikely( p_chunk == NULL ) )
3595         return NULL;
3596
3597     p_chunk->i_type = ATOM_root;
3598     p_chunk->i_shortsize = 1;
3599
3600     MP4_ReadBoxContainerChildren( s, p_chunk, ATOM_moof );
3601
3602     return p_chunk;
3603 }
3604
3605 /*****************************************************************************
3606  * MP4_BoxGetRoot : Parse the entire file, and create all boxes in memory
3607  *****************************************************************************
3608  *  The first box is a virtual box "root" and is the father for all first
3609  *  level boxes for the file, a sort of virtual contener
3610  *****************************************************************************/
3611 MP4_Box_t *MP4_BoxGetRoot( stream_t *s )
3612 {
3613     MP4_Box_t *p_root;
3614     stream_t *p_stream;
3615     int i_result;
3616
3617     p_root = malloc( sizeof( MP4_Box_t ) );
3618     if( p_root == NULL )
3619         return NULL;
3620
3621     p_root->i_pos = 0;
3622     p_root->i_type = ATOM_root;
3623     p_root->i_shortsize = 1;
3624     /* could be a DASH stream for exemple, 0 means unknown or infinite size */
3625     p_root->i_size = 0;
3626     CreateUUID( &p_root->i_uuid, p_root->i_type );
3627
3628     p_root->data.p_payload = NULL;
3629     p_root->p_father    = NULL;
3630     p_root->p_first     = NULL;
3631     p_root->p_last      = NULL;
3632     p_root->p_next      = NULL;
3633
3634     p_stream = s;
3635
3636     /* First get the moov */
3637     i_result = MP4_ReadBoxContainerChildren( p_stream, p_root, ATOM_moov );
3638
3639     if( !i_result )
3640         goto error;
3641     /* If there is a mvex box, it means fragmented MP4, and we're done */
3642     else if( MP4_BoxCount( p_root, "moov/mvex" ) > 0 )
3643         return p_root;
3644
3645     p_root->i_size = stream_Size( s );
3646     if( stream_Tell( s ) + 8 < stream_Size( s ) )
3647     {
3648         /* Get the rest of the file */
3649         i_result = MP4_ReadBoxContainerRaw( p_stream, p_root );
3650
3651         if( !i_result )
3652             goto error;
3653     }
3654
3655     MP4_Box_t *p_moov;
3656     MP4_Box_t *p_cmov;
3657
3658     /* check if there is a cmov, if so replace
3659       compressed moov by  uncompressed one */
3660     if( ( ( p_moov = MP4_BoxGet( p_root, "moov" ) ) &&
3661           ( p_cmov = MP4_BoxGet( p_root, "moov/cmov" ) ) ) ||
3662         ( ( p_moov = MP4_BoxGet( p_root, "foov" ) ) &&
3663           ( p_cmov = MP4_BoxGet( p_root, "foov/cmov" ) ) ) )
3664     {
3665         /* rename the compressed moov as a box to skip */
3666         p_moov->i_type = ATOM_skip;
3667
3668         /* get uncompressed p_moov */
3669         p_moov = p_cmov->data.p_cmov->p_moov;
3670         p_cmov->data.p_cmov->p_moov = NULL;
3671
3672         /* make p_root father of this new moov */
3673         p_moov->p_father = p_root;
3674
3675         /* insert this new moov box as first child of p_root */
3676         p_moov->p_next = p_root->p_first;
3677         p_root->p_first = p_moov;
3678     }
3679
3680     return p_root;
3681
3682 error:
3683     free( p_root );
3684     stream_Seek( p_stream, 0 );
3685     return NULL;
3686 }
3687
3688
3689 static void MP4_BoxDumpStructure_Internal( stream_t *s,
3690                                     MP4_Box_t *p_box, unsigned int i_level )
3691 {
3692     MP4_Box_t *p_child;
3693
3694     if( !i_level )
3695     {
3696         if MP4_BOX_TYPE_ASCII()
3697             msg_Dbg( s, "dumping root Box \"%4.4s\"",
3698                               (char*)&p_box->i_type );
3699         else
3700             msg_Dbg( s, "dumping root Box \"c%3.3s\"",
3701                               (char*)&p_box->i_type+1 );
3702     }
3703     else
3704     {
3705         char str[512];
3706         if( i_level >= (sizeof(str) - 1)/4 )
3707             return;
3708
3709         memset( str, ' ', sizeof(str) );
3710         for( unsigned i = 0; i < i_level; i++ )
3711         {
3712             str[i*4] = '|';
3713         }
3714         if( MP4_BOX_TYPE_ASCII() )
3715             snprintf( &str[i_level * 4], sizeof(str) - 4*i_level,
3716                       "+ %4.4s size %"PRIu64" offset %ld",
3717                         (char*)&p_box->i_type, p_box->i_size, p_box->i_pos );
3718         else
3719             snprintf( &str[i_level * 4], sizeof(str) - 4*i_level,
3720                       "+ c%3.3s size %"PRIu64" offset %ld",
3721                         (char*)&p_box->i_type+1, p_box->i_size, p_box->i_pos );
3722         msg_Dbg( s, "%s", str );
3723     }
3724     p_child = p_box->p_first;
3725     while( p_child )
3726     {
3727         MP4_BoxDumpStructure_Internal( s, p_child, i_level + 1 );
3728         p_child = p_child->p_next;
3729     }
3730 }
3731
3732 void MP4_BoxDumpStructure( stream_t *s, MP4_Box_t *p_box )
3733 {
3734     MP4_BoxDumpStructure_Internal( s, p_box, 0 );
3735 }
3736
3737
3738 /*****************************************************************************
3739  *****************************************************************************
3740  **
3741  **  High level methods to acces an MP4 file
3742  **
3743  *****************************************************************************
3744  *****************************************************************************/
3745 static void get_token( char **ppsz_path, char **ppsz_token, int *pi_number )
3746 {
3747     size_t i_len ;
3748     if( !*ppsz_path[0] )
3749     {
3750         *ppsz_token = NULL;
3751         *pi_number = 0;
3752         return;
3753     }
3754     i_len = strcspn( *ppsz_path, "/[" );
3755     if( !i_len && **ppsz_path == '/' )
3756     {
3757         i_len = 1;
3758     }
3759     *ppsz_token = strndup( *ppsz_path, i_len );
3760     if( unlikely(!*ppsz_token) )
3761         abort();
3762
3763     *ppsz_path += i_len;
3764
3765     if( **ppsz_path == '[' )
3766     {
3767         (*ppsz_path)++;
3768         *pi_number = strtol( *ppsz_path, NULL, 10 );
3769         while( **ppsz_path && **ppsz_path != ']' )
3770         {
3771             (*ppsz_path)++;
3772         }
3773         if( **ppsz_path == ']' )
3774         {
3775             (*ppsz_path)++;
3776         }
3777     }
3778     else
3779     {
3780         *pi_number = 0;
3781     }
3782     while( **ppsz_path == '/' )
3783     {
3784         (*ppsz_path)++;
3785     }
3786 }
3787
3788 static void MP4_BoxGet_Internal( MP4_Box_t **pp_result,
3789                           MP4_Box_t *p_box, const char *psz_fmt, va_list args)
3790 {
3791     char *psz_dup;
3792     char *psz_path;
3793     char *psz_token;
3794
3795     if( !p_box )
3796     {
3797         *pp_result = NULL;
3798         return;
3799     }
3800
3801     if( vasprintf( &psz_path, psz_fmt, args ) == -1 )
3802         psz_path = NULL;
3803
3804     if( !psz_path || !psz_path[0] )
3805     {
3806         free( psz_path );
3807         *pp_result = NULL;
3808         return;
3809     }
3810
3811 //    fprintf( stderr, "path:'%s'\n", psz_path );
3812     psz_dup = psz_path; /* keep this pointer, as it need to be unallocated */
3813     for( ; ; )
3814     {
3815         int i_number;
3816
3817         get_token( &psz_path, &psz_token, &i_number );
3818 //        fprintf( stderr, "path:'%s', token:'%s' n:%d\n",
3819 //                 psz_path,psz_token,i_number );
3820         if( !psz_token )
3821         {
3822             free( psz_dup );
3823             *pp_result = p_box;
3824             return;
3825         }
3826         else
3827         if( !strcmp( psz_token, "/" ) )
3828         {
3829             /* Find root box */
3830             while( p_box && p_box->i_type != ATOM_root )
3831             {
3832                 p_box = p_box->p_father;
3833             }
3834             if( !p_box )
3835             {
3836                 goto error_box;
3837             }
3838         }
3839         else
3840         if( !strcmp( psz_token, "." ) )
3841         {
3842             /* Do nothing */
3843         }
3844         else
3845         if( !strcmp( psz_token, ".." ) )
3846         {
3847             p_box = p_box->p_father;
3848             if( !p_box )
3849             {
3850                 goto error_box;
3851             }
3852         }
3853         else
3854         if( strlen( psz_token ) == 4 )
3855         {
3856             uint32_t i_fourcc;
3857             i_fourcc = VLC_FOURCC( psz_token[0], psz_token[1],
3858                                    psz_token[2], psz_token[3] );
3859             p_box = p_box->p_first;
3860             for( ; ; )
3861             {
3862                 if( !p_box )
3863                 {
3864                     goto error_box;
3865                 }
3866                 if( p_box->i_type == i_fourcc )
3867                 {
3868                     if( !i_number )
3869                     {
3870                         break;
3871                     }
3872                     i_number--;
3873                 }
3874                 p_box = p_box->p_next;
3875             }
3876         }
3877         else
3878         if( *psz_token == '\0' )
3879         {
3880             p_box = p_box->p_first;
3881             for( ; ; )
3882             {
3883                 if( !p_box )
3884                 {
3885                     goto error_box;
3886                 }
3887                 if( !i_number )
3888                 {
3889                     break;
3890                 }
3891                 i_number--;
3892                 p_box = p_box->p_next;
3893             }
3894         }
3895         else
3896         {
3897 //            fprintf( stderr, "Argg malformed token \"%s\"",psz_token );
3898             goto error_box;
3899         }
3900
3901         FREENULL( psz_token );
3902     }
3903
3904     return;
3905
3906 error_box:
3907     free( psz_token );
3908     free( psz_dup );
3909     *pp_result = NULL;
3910     return;
3911 }
3912
3913 /*****************************************************************************
3914  * MP4_BoxGet: find a box given a path relative to p_box
3915  *****************************************************************************
3916  * Path Format: . .. / as usual
3917  *              [number] to specifie box number ex: trak[12]
3918  *
3919  * ex: /moov/trak[12]
3920  *     ../mdia
3921  *****************************************************************************/
3922 MP4_Box_t *MP4_BoxGet( MP4_Box_t *p_box, const char *psz_fmt, ... )
3923 {
3924     va_list args;
3925     MP4_Box_t *p_result;
3926
3927     va_start( args, psz_fmt );
3928     MP4_BoxGet_Internal( &p_result, p_box, psz_fmt, args );
3929     va_end( args );
3930
3931     return( p_result );
3932 }
3933
3934 /*****************************************************************************
3935  * MP4_BoxCount: count box given a path relative to p_box
3936  *****************************************************************************
3937  * Path Format: . .. / as usual
3938  *              [number] to specifie box number ex: trak[12]
3939  *
3940  * ex: /moov/trak[12]
3941  *     ../mdia
3942  *****************************************************************************/
3943 int MP4_BoxCount( MP4_Box_t *p_box, const char *psz_fmt, ... )
3944 {
3945     va_list args;
3946     int     i_count;
3947     MP4_Box_t *p_result, *p_next;
3948
3949     va_start( args, psz_fmt );
3950     MP4_BoxGet_Internal( &p_result, p_box, psz_fmt, args );
3951     va_end( args );
3952     if( !p_result )
3953     {
3954         return( 0 );
3955     }
3956
3957     i_count = 1;
3958     for( p_next = p_result->p_next; p_next != NULL; p_next = p_next->p_next)
3959     {
3960         if( p_next->i_type == p_result->i_type)
3961         {
3962             i_count++;
3963         }
3964     }
3965     return( i_count );
3966 }