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