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