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