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