]> git.sesse.net Git - vlc/blob - modules/demux/mp4/libmp4.c
6c282ead393c51f0299c9742945181ead97f711e
[vlc] / modules / demux / mp4 / libmp4.c
1 /*****************************************************************************
2  * libmp4.c : LibMP4 library for mp4 module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001-2004 the VideoLAN team
5  * $Id$
6  *
7  * Author: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23 #include <vlc/vlc.h>
24
25 #include <stdio.h>
26 #include <stdlib.h>                                      /* malloc(), free() */
27
28 #include <vlc/input.h>
29
30 #ifdef HAVE_ZLIB_H
31 #   include <zlib.h>                                  /* for compressed moov */
32 #endif
33
34 #include "libmp4.h"
35 #include "drms.h"
36
37 /*****************************************************************************
38  * Here are defined some macro to make life simpler but before using it
39  *  *look* at the code.
40  *
41  *****************************************************************************/
42 #define MP4_BOX_HEADERSIZE( p_box ) \
43   ( 8 + ( p_box->i_shortsize == 1 ? 8 : 0 ) \
44       + ( p_box->i_type == FOURCC_uuid ? 16 : 0 ) )
45
46 #define MP4_GET1BYTE( dst ) \
47     dst = *p_peek; p_peek++; i_read--
48
49 #define MP4_GET2BYTES( dst ) \
50     dst = GetWBE( p_peek ); p_peek += 2; i_read -= 2
51
52 #define MP4_GET3BYTES( dst ) \
53     dst = Get24bBE( p_peek ); p_peek += 3; i_read -= 3
54
55 #define MP4_GET4BYTES( dst ) \
56     dst = GetDWBE( p_peek ); p_peek += 4; i_read -= 4
57
58 #define MP4_GETFOURCC( dst ) \
59     dst = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] ); \
60     p_peek += 4; i_read -= 4
61
62 #define MP4_GET8BYTES( dst ) \
63     dst = GetQWBE( p_peek ); p_peek += 8; i_read -= 8
64
65 #define MP4_GETVERSIONFLAGS( p_void ) \
66     MP4_GET1BYTE( p_void->i_version ); \
67     MP4_GET3BYTES( p_void->i_flags )
68
69 #define MP4_GETSTRINGZ( p_str ) \
70     if( ( i_read > 0 )&&(p_peek[0] ) ) \
71     { \
72         p_str = calloc( sizeof( char ), __MIN( strlen( (char*)p_peek ), i_read )+1);\
73         memcpy( p_str, p_peek, __MIN( strlen( (char*)p_peek ), i_read ) ); \
74         p_str[__MIN( strlen( (char*)p_peek ), i_read )] = 0; \
75         p_peek += strlen( p_str ) + 1; \
76         i_read -= strlen( p_str ) + 1; \
77     } \
78     else \
79     { \
80         p_str = NULL; \
81     }
82
83
84 #define MP4_READBOX_ENTER( MP4_Box_data_TYPE_t ) \
85     uint64_t  i_read = p_box->i_size; \
86     uint8_t *p_peek, *p_buff; \
87     int i_actually_read; \
88     if( !( p_peek = p_buff = malloc( i_read ) ) ) \
89     { \
90         return( 0 ); \
91     } \
92     i_actually_read = stream_Read( p_stream, p_peek, i_read ); \
93     if( i_actually_read < 0 || (uint64_t)i_actually_read < i_read )\
94     { \
95         free( p_buff ); \
96         return( 0 ); \
97     } \
98     p_peek += MP4_BOX_HEADERSIZE( p_box ); \
99     i_read -= MP4_BOX_HEADERSIZE( p_box ); \
100     if( !( p_box->data.p_data = malloc( sizeof( MP4_Box_data_TYPE_t ) ) ) ) \
101     { \
102       free( p_buff ); \
103       return( 0 ); \
104     }
105
106 #define MP4_READBOX_EXIT( i_code ) \
107     free( p_buff ); \
108     if( i_read < 0 ) \
109     { \
110         msg_Warn( p_stream, "Not enough data" ); \
111     } \
112     return( i_code )
113
114
115 /* Some assumptions:
116         * The input method HAVE to be seekable
117
118 */
119
120 static uint32_t Get24bBE( uint8_t *p )
121 {
122     return( ( p[0] <<16 ) + ( p[1] <<8 ) + p[2] );
123 }
124
125 static void GetUUID( UUID_t *p_uuid, uint8_t *p_buff )
126 {
127     memcpy( p_uuid, p_buff, 16 );
128 }
129
130 static void CreateUUID( UUID_t *p_uuid, uint32_t i_fourcc )
131 {
132     /* made by 0xXXXXXXXX-0011-0010-8000-00aa00389b71
133             where XXXXXXXX is the fourcc */
134     /* FIXME implement this */
135 }
136
137 /* some functions for mp4 encoding of variables */
138
139 static void MP4_ConvertDate2Str( char *psz, uint64_t i_date )
140 {
141     int i_day;
142     int i_hour;
143     int i_min;
144     int i_sec;
145
146     /* date begin at 1 jan 1904 */
147     i_date += ((I64C(1904) * 365) + 17) * 24 * 60 * 60;
148
149     i_day = i_date / ( 60*60*24);
150     i_hour = ( i_date /( 60*60 ) ) % 60;
151     i_min  = ( i_date / 60 ) % 60;
152     i_sec =  i_date % 60;
153     sprintf( psz, "%dd-%2.2dh:%2.2dm:%2.2ds", i_day, i_hour, i_min, i_sec );
154 }
155
156 /*****************************************************************************
157  * Some prototypes.
158  *****************************************************************************/
159 static MP4_Box_t *MP4_ReadBox( stream_t *p_stream, MP4_Box_t *p_father );
160
161
162 /*****************************************************************************
163  * MP4_ReadBoxCommon : Load only common parameters for all boxes
164  *****************************************************************************
165  * p_box need to be an already allocated MP4_Box_t, and all data
166  *  will only be peek not read
167  *
168  * RETURN : 0 if it fail, 1 otherwise
169  *****************************************************************************/
170 int MP4_ReadBoxCommon( stream_t *p_stream, MP4_Box_t *p_box )
171 {
172     int      i_read;
173     uint8_t  *p_peek;
174
175     if( ( ( i_read = stream_Peek( p_stream, &p_peek, 32 ) ) < 8 ) )
176     {
177         return 0;
178     }
179     p_box->i_pos = stream_Tell( p_stream );
180
181     p_box->data.p_data = NULL;
182     p_box->p_father = NULL;
183     p_box->p_first  = NULL;
184     p_box->p_last  = NULL;
185     p_box->p_next   = NULL;
186
187     MP4_GET4BYTES( p_box->i_shortsize );
188     MP4_GETFOURCC( p_box->i_type );
189
190     /* Now special case */
191
192     if( p_box->i_shortsize == 1 )
193     {
194         /* get the true size on 64 bits */
195         MP4_GET8BYTES( p_box->i_size );
196     }
197     else
198     {
199         p_box->i_size = p_box->i_shortsize;
200         /* XXX size of 0 means that the box extends to end of file */
201     }
202
203     if( p_box->i_type == FOURCC_uuid )
204     {
205         /* get extented type on 16 bytes */
206         GetUUID( &p_box->i_uuid, p_peek );
207         p_peek += 16; i_read -= 16;
208     }
209     else
210     {
211         CreateUUID( &p_box->i_uuid, p_box->i_type );
212     }
213 #ifdef MP4_VERBOSE
214     if( p_box->i_size )
215     {
216         msg_Dbg( p_stream, "found Box: %4.4s size "I64Fd,
217                  (char*)&p_box->i_type, p_box->i_size );
218     }
219 #endif
220
221     return 1;
222 }
223
224 /*****************************************************************************
225  * MP4_NextBox : Go to the next box
226  *****************************************************************************
227  * if p_box == NULL, go to the next box in which we are( at the begining ).
228  *****************************************************************************/
229 static int MP4_NextBox( stream_t *p_stream, MP4_Box_t *p_box )
230 {
231     MP4_Box_t box;
232
233     if( !p_box )
234     {
235         MP4_ReadBoxCommon( p_stream, &box );
236         p_box = &box;
237     }
238
239     if( !p_box->i_size )
240     {
241         return 2; /* Box with infinite size */
242     }
243
244     if( p_box->p_father )
245     {
246         /* check if it's within p-father */
247         if( p_box->i_size + p_box->i_pos >=
248             p_box->p_father->i_size + p_box->p_father->i_pos )
249         {
250             msg_Dbg( p_stream, "out of bound child" );
251             return 0; /* out of bound */
252         }
253     }
254     if( stream_Seek( p_stream, p_box->i_size + p_box->i_pos ) )
255     {
256         return 0;
257     }
258
259     return 1;
260 }
261
262 /*****************************************************************************
263  * For all known box a loader is given,
264  *  XXX: all common struct have to be already read by MP4_ReadBoxCommon
265  *       after called one of theses functions, file position is unknown
266  *       you need to call MP4_GotoBox to go where you want
267  *****************************************************************************/
268 static int MP4_ReadBoxContainerRaw( stream_t *p_stream, MP4_Box_t *p_container )
269 {
270     MP4_Box_t *p_box;
271
272     if( stream_Tell( p_stream ) + 8 >
273         (off_t)(p_container->i_pos + p_container->i_size) )
274     {
275         /* there is no box to load */
276         return 0;
277     }
278
279     do
280     {
281         if( ( p_box = MP4_ReadBox( p_stream, p_container ) ) == NULL ) break;
282
283         /* chain this box with the father and the other at same level */
284         if( !p_container->p_first ) p_container->p_first = p_box;
285         else p_container->p_last->p_next = p_box;
286         p_container->p_last = p_box;
287
288     } while( MP4_NextBox( p_stream, p_box ) == 1 );
289
290     return 1;
291 }
292
293 static int MP4_ReadBoxContainer( stream_t *p_stream, MP4_Box_t *p_container )
294 {
295     if( p_container->i_size <= (size_t)MP4_BOX_HEADERSIZE(p_container ) + 8 )
296     {
297         /* container is empty, 8 stand for the first header in this box */
298         return 1;
299     }
300
301     /* enter box */
302     stream_Seek( p_stream, p_container->i_pos +
303                  MP4_BOX_HEADERSIZE( p_container ) );
304
305     return MP4_ReadBoxContainerRaw( p_stream, p_container );
306 }
307
308 static void MP4_FreeBox_Common( MP4_Box_t *p_box )
309 {
310     /* Up to now do nothing */
311 }
312
313 static int MP4_ReadBoxSkip( stream_t *p_stream, MP4_Box_t *p_box )
314 {
315     /* XXX sometime moov is hiden in a free box */
316     if( p_box->p_father &&
317         p_box->p_father->i_type == VLC_FOURCC( 'r', 'o', 'o', 't' ) &&
318         p_box->i_type == FOURCC_free )
319     {
320         uint8_t *p_peek;
321         int     i_read;
322         vlc_fourcc_t i_fcc;
323
324         i_read  = stream_Peek( p_stream, &p_peek, 44 );
325
326         p_peek += MP4_BOX_HEADERSIZE( p_box ) + 4;
327         i_read -= MP4_BOX_HEADERSIZE( p_box ) + 4;
328
329         if( i_read >= 8 )
330         {
331             i_fcc = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] );
332
333             if( i_fcc == FOURCC_cmov || i_fcc == FOURCC_mvhd )
334             {
335                 msg_Warn( p_stream, "detected moov hidden in a free box ..." );
336
337                 p_box->i_type = FOURCC_foov;
338                 return MP4_ReadBoxContainer( p_stream, p_box );
339             }
340         }
341     }
342
343     /* Nothing to do */
344 #ifdef MP4_VERBOSE
345     msg_Dbg( p_stream, "skip box: \"%4.4s\"", (char*)&p_box->i_type );
346 #endif
347     return 1;
348 }
349
350 static int MP4_ReadBox_ftyp( stream_t *p_stream, MP4_Box_t *p_box )
351 {
352     MP4_READBOX_ENTER( MP4_Box_data_ftyp_t );
353
354     MP4_GETFOURCC( p_box->data.p_ftyp->i_major_brand );
355     MP4_GET4BYTES( p_box->data.p_ftyp->i_minor_version );
356
357     if( ( p_box->data.p_ftyp->i_compatible_brands_count = i_read / 4 ) )
358     {
359         unsigned int i;
360         p_box->data.p_ftyp->i_compatible_brands =
361             calloc( p_box->data.p_ftyp->i_compatible_brands_count, sizeof(uint32_t));
362
363         for( i =0; i < p_box->data.p_ftyp->i_compatible_brands_count; i++ )
364         {
365             MP4_GETFOURCC( p_box->data.p_ftyp->i_compatible_brands[i] );
366         }
367     }
368     else
369     {
370         p_box->data.p_ftyp->i_compatible_brands = NULL;
371     }
372
373     MP4_READBOX_EXIT( 1 );
374 }
375
376 static void MP4_FreeBox_ftyp( MP4_Box_t *p_box )
377 {
378     FREENULL( p_box->data.p_ftyp->i_compatible_brands );
379 }
380
381
382 static int MP4_ReadBox_mvhd(  stream_t *p_stream, MP4_Box_t *p_box )
383 {
384     unsigned int i;
385 #ifdef MP4_VERBOSE
386     char s_creation_time[128];
387     char s_modification_time[128];
388     char s_duration[128];
389 #endif
390     MP4_READBOX_ENTER( MP4_Box_data_mvhd_t );
391
392     MP4_GETVERSIONFLAGS( p_box->data.p_mvhd );
393
394     if( p_box->data.p_mvhd->i_version )
395     {
396         MP4_GET8BYTES( p_box->data.p_mvhd->i_creation_time );
397         MP4_GET8BYTES( p_box->data.p_mvhd->i_modification_time );
398         MP4_GET4BYTES( p_box->data.p_mvhd->i_timescale );
399         MP4_GET8BYTES( p_box->data.p_mvhd->i_duration );
400     }
401     else
402     {
403         MP4_GET4BYTES( p_box->data.p_mvhd->i_creation_time );
404         MP4_GET4BYTES( p_box->data.p_mvhd->i_modification_time );
405         MP4_GET4BYTES( p_box->data.p_mvhd->i_timescale );
406         MP4_GET4BYTES( p_box->data.p_mvhd->i_duration );
407     }
408     MP4_GET4BYTES( p_box->data.p_mvhd->i_rate );
409     MP4_GET2BYTES( p_box->data.p_mvhd->i_volume );
410     MP4_GET2BYTES( p_box->data.p_mvhd->i_reserved1 );
411
412
413     for( i = 0; i < 2; i++ )
414     {
415         MP4_GET4BYTES( p_box->data.p_mvhd->i_reserved2[i] );
416     }
417     for( i = 0; i < 9; i++ )
418     {
419         MP4_GET4BYTES( p_box->data.p_mvhd->i_matrix[i] );
420     }
421     for( i = 0; i < 6; i++ )
422     {
423         MP4_GET4BYTES( p_box->data.p_mvhd->i_predefined[i] );
424     }
425
426     MP4_GET4BYTES( p_box->data.p_mvhd->i_next_track_id );
427
428
429 #ifdef MP4_VERBOSE
430     MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mvhd->i_creation_time );
431     MP4_ConvertDate2Str( s_modification_time,
432                          p_box->data.p_mvhd->i_modification_time );
433     if( p_box->data.p_mvhd->i_rate )
434     {
435         MP4_ConvertDate2Str( s_duration,
436                  p_box->data.p_mvhd->i_duration / p_box->data.p_mvhd->i_rate );
437     }
438     else
439     {
440         s_duration[0] = 0;
441     }
442     msg_Dbg( p_stream, "read box: \"mvhd\" creation %s modification %s time scale %d duration %s rate %f volume %f next track id %d",
443                   s_creation_time,
444                   s_modification_time,
445                   (uint32_t)p_box->data.p_mvhd->i_timescale,
446                   s_duration,
447                   (float)p_box->data.p_mvhd->i_rate / (1<<16 ),
448                   (float)p_box->data.p_mvhd->i_volume / 256 ,
449                   (uint32_t)p_box->data.p_mvhd->i_next_track_id );
450 #endif
451     MP4_READBOX_EXIT( 1 );
452 }
453
454 static int MP4_ReadBox_tkhd(  stream_t *p_stream, MP4_Box_t *p_box )
455 {
456     unsigned int i;
457 #ifdef MP4_VERBOSE
458     char s_creation_time[128];
459     char s_modification_time[128];
460     char s_duration[128];
461 #endif
462     MP4_READBOX_ENTER( MP4_Box_data_tkhd_t );
463
464     MP4_GETVERSIONFLAGS( p_box->data.p_tkhd );
465
466     if( p_box->data.p_tkhd->i_version )
467     {
468         MP4_GET8BYTES( p_box->data.p_tkhd->i_creation_time );
469         MP4_GET8BYTES( p_box->data.p_tkhd->i_modification_time );
470         MP4_GET4BYTES( p_box->data.p_tkhd->i_track_ID );
471         MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved );
472         MP4_GET8BYTES( p_box->data.p_tkhd->i_duration );
473     }
474     else
475     {
476         MP4_GET4BYTES( p_box->data.p_tkhd->i_creation_time );
477         MP4_GET4BYTES( p_box->data.p_tkhd->i_modification_time );
478         MP4_GET4BYTES( p_box->data.p_tkhd->i_track_ID );
479         MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved );
480         MP4_GET4BYTES( p_box->data.p_tkhd->i_duration );
481     }
482
483     for( i = 0; i < 2; i++ )
484     {
485         MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved2[i] );
486     }
487     MP4_GET2BYTES( p_box->data.p_tkhd->i_layer );
488     MP4_GET2BYTES( p_box->data.p_tkhd->i_predefined );
489     MP4_GET2BYTES( p_box->data.p_tkhd->i_volume );
490     MP4_GET2BYTES( p_box->data.p_tkhd->i_reserved3 );
491
492     for( i = 0; i < 9; i++ )
493     {
494         MP4_GET4BYTES( p_box->data.p_tkhd->i_matrix[i] );
495     }
496     MP4_GET4BYTES( p_box->data.p_tkhd->i_width );
497     MP4_GET4BYTES( p_box->data.p_tkhd->i_height );
498
499 #ifdef MP4_VERBOSE
500     MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mvhd->i_creation_time );
501     MP4_ConvertDate2Str( s_modification_time, p_box->data.p_mvhd->i_modification_time );
502     MP4_ConvertDate2Str( s_duration, p_box->data.p_mvhd->i_duration );
503
504     msg_Dbg( p_stream, "read box: \"tkhd\" creation %s modification %s duration %s track ID %d layer %d volume %f width %f height %f",
505                   s_creation_time,
506                   s_modification_time,
507                   s_duration,
508                   p_box->data.p_tkhd->i_track_ID,
509                   p_box->data.p_tkhd->i_layer,
510                   (float)p_box->data.p_tkhd->i_volume / 256 ,
511                   (float)p_box->data.p_tkhd->i_width / 65536,
512                   (float)p_box->data.p_tkhd->i_height / 65536 );
513 #endif
514     MP4_READBOX_EXIT( 1 );
515 }
516
517
518 static int MP4_ReadBox_mdhd( stream_t *p_stream, MP4_Box_t *p_box )
519 {
520     unsigned int i;
521     uint16_t i_language;
522 #ifdef MP4_VERBOSE
523     char s_creation_time[128];
524     char s_modification_time[128];
525     char s_duration[128];
526 #endif
527     MP4_READBOX_ENTER( MP4_Box_data_mdhd_t );
528
529     MP4_GETVERSIONFLAGS( p_box->data.p_mdhd );
530
531     if( p_box->data.p_mdhd->i_version )
532     {
533         MP4_GET8BYTES( p_box->data.p_mdhd->i_creation_time );
534         MP4_GET8BYTES( p_box->data.p_mdhd->i_modification_time );
535         MP4_GET4BYTES( p_box->data.p_mdhd->i_timescale );
536         MP4_GET8BYTES( p_box->data.p_mdhd->i_duration );
537     }
538     else
539     {
540         MP4_GET4BYTES( p_box->data.p_mdhd->i_creation_time );
541         MP4_GET4BYTES( p_box->data.p_mdhd->i_modification_time );
542         MP4_GET4BYTES( p_box->data.p_mdhd->i_timescale );
543         MP4_GET4BYTES( p_box->data.p_mdhd->i_duration );
544     }
545     i_language = GetWBE( p_peek );
546     for( i = 0; i < 3; i++ )
547     {
548         p_box->data.p_mdhd->i_language[i] =
549                     ( ( i_language >> ( (2-i)*5 ) )&0x1f ) + 0x60;
550     }
551
552     MP4_GET2BYTES( p_box->data.p_mdhd->i_predefined );
553
554 #ifdef MP4_VERBOSE
555     MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mdhd->i_creation_time );
556     MP4_ConvertDate2Str( s_modification_time, p_box->data.p_mdhd->i_modification_time );
557     MP4_ConvertDate2Str( s_duration, p_box->data.p_mdhd->i_duration );
558     msg_Dbg( p_stream, "read box: \"mdhd\" creation %s modification %s time scale %d duration %s language %c%c%c",
559                   s_creation_time,
560                   s_modification_time,
561                   (uint32_t)p_box->data.p_mdhd->i_timescale,
562                   s_duration,
563                   p_box->data.p_mdhd->i_language[0],
564                   p_box->data.p_mdhd->i_language[1],
565                   p_box->data.p_mdhd->i_language[2] );
566 #endif
567     MP4_READBOX_EXIT( 1 );
568 }
569
570
571 static int MP4_ReadBox_hdlr( stream_t *p_stream, MP4_Box_t *p_box )
572 {
573     int32_t i_reserved;
574
575     MP4_READBOX_ENTER( MP4_Box_data_hdlr_t );
576
577     MP4_GETVERSIONFLAGS( p_box->data.p_hdlr );
578
579     MP4_GETFOURCC( p_box->data.p_hdlr->i_predefined );
580     MP4_GETFOURCC( p_box->data.p_hdlr->i_handler_type );
581
582     MP4_GET4BYTES( i_reserved );
583     MP4_GET4BYTES( i_reserved );
584     MP4_GET4BYTES( i_reserved );
585     p_box->data.p_hdlr->psz_name = NULL;
586
587     if( i_read > 0 )
588     {
589         p_box->data.p_hdlr->psz_name = calloc( sizeof( char ), i_read + 1 );
590
591         /* Yes, I love .mp4 :( */
592         if( p_box->data.p_hdlr->i_predefined == VLC_FOURCC( 'm', 'h', 'l', 'r' ) )
593         {
594             uint8_t i_len;
595             int i_copy;
596
597             MP4_GET1BYTE( i_len );
598             i_copy = __MIN( i_read, i_len );
599
600             memcpy( p_box->data.p_hdlr->psz_name, p_peek, i_copy );
601             p_box->data.p_hdlr->psz_name[i_copy] = '\0';
602         }
603         else
604         {
605             memcpy( p_box->data.p_hdlr->psz_name, p_peek, i_read );
606             p_box->data.p_hdlr->psz_name[i_read] = '\0';
607         }
608     }
609
610 #ifdef MP4_VERBOSE
611     msg_Dbg( p_stream, "read box: \"hdlr\" handler type %4.4s name %s",
612                        (char*)&p_box->data.p_hdlr->i_handler_type,
613                        p_box->data.p_hdlr->psz_name );
614
615 #endif
616     MP4_READBOX_EXIT( 1 );
617 }
618
619 static void MP4_FreeBox_hdlr( MP4_Box_t *p_box )
620 {
621     FREENULL( p_box->data.p_hdlr->psz_name );
622 }
623
624 static int MP4_ReadBox_vmhd( stream_t *p_stream, MP4_Box_t *p_box )
625 {
626     unsigned int i;
627
628     MP4_READBOX_ENTER( MP4_Box_data_vmhd_t );
629
630     MP4_GETVERSIONFLAGS( p_box->data.p_vmhd );
631
632     MP4_GET2BYTES( p_box->data.p_vmhd->i_graphics_mode );
633     for( i = 0; i < 3; i++ )
634     {
635         MP4_GET2BYTES( p_box->data.p_vmhd->i_opcolor[i] );
636     }
637
638 #ifdef MP4_VERBOSE
639     msg_Dbg( p_stream, "read box: \"vmhd\" graphics-mode %d opcolor (%d, %d, %d)",
640                       p_box->data.p_vmhd->i_graphics_mode,
641                       p_box->data.p_vmhd->i_opcolor[0],
642                       p_box->data.p_vmhd->i_opcolor[1],
643                       p_box->data.p_vmhd->i_opcolor[2] );
644 #endif
645     MP4_READBOX_EXIT( 1 );
646 }
647
648 static int MP4_ReadBox_smhd( stream_t *p_stream, MP4_Box_t *p_box )
649 {
650     MP4_READBOX_ENTER( MP4_Box_data_smhd_t );
651
652     MP4_GETVERSIONFLAGS( p_box->data.p_smhd );
653
654
655
656     MP4_GET2BYTES( p_box->data.p_smhd->i_balance );
657
658     MP4_GET2BYTES( p_box->data.p_smhd->i_reserved );
659
660 #ifdef MP4_VERBOSE
661     msg_Dbg( p_stream, "read box: \"smhd\" balance %f",
662                       (float)p_box->data.p_smhd->i_balance / 256 );
663 #endif
664     MP4_READBOX_EXIT( 1 );
665 }
666
667
668 static int MP4_ReadBox_hmhd( stream_t *p_stream, MP4_Box_t *p_box )
669 {
670     MP4_READBOX_ENTER( MP4_Box_data_hmhd_t );
671
672     MP4_GETVERSIONFLAGS( p_box->data.p_hmhd );
673
674     MP4_GET2BYTES( p_box->data.p_hmhd->i_max_PDU_size );
675     MP4_GET2BYTES( p_box->data.p_hmhd->i_avg_PDU_size );
676
677     MP4_GET4BYTES( p_box->data.p_hmhd->i_max_bitrate );
678     MP4_GET4BYTES( p_box->data.p_hmhd->i_avg_bitrate );
679
680     MP4_GET4BYTES( p_box->data.p_hmhd->i_reserved );
681
682 #ifdef MP4_VERBOSE
683     msg_Dbg( p_stream, "read box: \"hmhd\" maxPDU-size %d avgPDU-size %d max-bitrate %d avg-bitrate %d",
684                       p_box->data.p_hmhd->i_max_PDU_size,
685                       p_box->data.p_hmhd->i_avg_PDU_size,
686                       p_box->data.p_hmhd->i_max_bitrate,
687                       p_box->data.p_hmhd->i_avg_bitrate );
688 #endif
689     MP4_READBOX_EXIT( 1 );
690 }
691
692 static int MP4_ReadBox_url( stream_t *p_stream, MP4_Box_t *p_box )
693 {
694     MP4_READBOX_ENTER( MP4_Box_data_url_t );
695
696     MP4_GETVERSIONFLAGS( p_box->data.p_url );
697     MP4_GETSTRINGZ( p_box->data.p_url->psz_location );
698
699 #ifdef MP4_VERBOSE
700     msg_Dbg( p_stream, "read box: \"url\" url: %s",
701                        p_box->data.p_url->psz_location );
702
703 #endif
704     MP4_READBOX_EXIT( 1 );
705 }
706
707
708 static void MP4_FreeBox_url( MP4_Box_t *p_box )
709 {
710     FREENULL( p_box->data.p_url->psz_location )
711 }
712
713 static int MP4_ReadBox_urn( stream_t *p_stream, MP4_Box_t *p_box )
714 {
715     MP4_READBOX_ENTER( MP4_Box_data_urn_t );
716
717     MP4_GETVERSIONFLAGS( p_box->data.p_urn );
718
719     MP4_GETSTRINGZ( p_box->data.p_urn->psz_name );
720     MP4_GETSTRINGZ( p_box->data.p_urn->psz_location );
721
722 #ifdef MP4_VERBOSE
723     msg_Dbg( p_stream, "read box: \"urn\" name %s location %s",
724                       p_box->data.p_urn->psz_name,
725                       p_box->data.p_urn->psz_location );
726 #endif
727     MP4_READBOX_EXIT( 1 );
728 }
729 static void MP4_FreeBox_urn( MP4_Box_t *p_box )
730 {
731     FREENULL( p_box->data.p_urn->psz_name );
732     FREENULL( p_box->data.p_urn->psz_location );
733 }
734
735
736 static int MP4_ReadBox_dref( stream_t *p_stream, MP4_Box_t *p_box )
737 {
738     MP4_READBOX_ENTER( MP4_Box_data_dref_t );
739
740     MP4_GETVERSIONFLAGS( p_box->data.p_dref );
741
742     MP4_GET4BYTES( p_box->data.p_dref->i_entry_count );
743
744     stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 8 );
745     MP4_ReadBoxContainerRaw( p_stream, p_box );
746
747 #ifdef MP4_VERBOSE
748     msg_Dbg( p_stream, "read box: \"dref\" entry-count %d",
749                       p_box->data.p_dref->i_entry_count );
750
751 #endif
752     MP4_READBOX_EXIT( 1 );
753 }
754
755
756 static int MP4_ReadBox_stts( stream_t *p_stream, MP4_Box_t *p_box )
757 {
758     unsigned int i;
759     MP4_READBOX_ENTER( MP4_Box_data_stts_t );
760
761     MP4_GETVERSIONFLAGS( p_box->data.p_stts );
762     MP4_GET4BYTES( p_box->data.p_stts->i_entry_count );
763
764     p_box->data.p_stts->i_sample_count =
765         calloc( sizeof( uint32_t ), p_box->data.p_stts->i_entry_count );
766     p_box->data.p_stts->i_sample_delta =
767         calloc( sizeof( uint32_t ), p_box->data.p_stts->i_entry_count );
768
769     for( i = 0; (i < p_box->data.p_stts->i_entry_count )&&( i_read >=8 ); i++ )
770     {
771         MP4_GET4BYTES( p_box->data.p_stts->i_sample_count[i] );
772         MP4_GET4BYTES( p_box->data.p_stts->i_sample_delta[i] );
773     }
774
775 #ifdef MP4_VERBOSE
776     msg_Dbg( p_stream, "read box: \"stts\" entry-count %d",
777                       p_box->data.p_stts->i_entry_count );
778
779 #endif
780     MP4_READBOX_EXIT( 1 );
781 }
782
783 static void MP4_FreeBox_stts( MP4_Box_t *p_box )
784 {
785     FREENULL( p_box->data.p_stts->i_sample_count );
786     FREENULL( p_box->data.p_stts->i_sample_delta );
787 }
788
789 static int MP4_ReadBox_ctts( stream_t *p_stream, MP4_Box_t *p_box )
790 {
791     unsigned int i;
792     MP4_READBOX_ENTER( MP4_Box_data_ctts_t );
793
794     MP4_GETVERSIONFLAGS( p_box->data.p_ctts );
795
796     MP4_GET4BYTES( p_box->data.p_ctts->i_entry_count );
797
798     p_box->data.p_ctts->i_sample_count =
799         calloc( sizeof( uint32_t ), p_box->data.p_ctts->i_entry_count );
800     p_box->data.p_ctts->i_sample_offset =
801         calloc( sizeof( uint32_t ), p_box->data.p_ctts->i_entry_count );
802
803     for( i = 0; (i < p_box->data.p_ctts->i_entry_count )&&( i_read >=8 ); i++ )
804     {
805         MP4_GET4BYTES( p_box->data.p_ctts->i_sample_count[i] );
806         MP4_GET4BYTES( p_box->data.p_ctts->i_sample_offset[i] );
807     }
808
809 #ifdef MP4_VERBOSE
810     msg_Dbg( p_stream, "read box: \"ctts\" entry-count %d",
811                       p_box->data.p_ctts->i_entry_count );
812
813 #endif
814     MP4_READBOX_EXIT( 1 );
815 }
816
817 static void MP4_FreeBox_ctts( MP4_Box_t *p_box )
818 {
819     FREENULL( p_box->data.p_ctts->i_sample_count );
820     FREENULL( p_box->data.p_ctts->i_sample_offset );
821 }
822
823 static int MP4_ReadLengthDescriptor( uint8_t **pp_peek, uint64_t  *i_read )
824 {
825     unsigned int i_b;
826     unsigned int i_len = 0;
827     do
828     {
829         i_b = **pp_peek;
830
831         (*pp_peek)++;
832         (*i_read)--;
833         i_len = ( i_len << 7 ) + ( i_b&0x7f );
834     } while( i_b&0x80 );
835     return( i_len );
836 }
837
838 static int MP4_ReadBox_esds( stream_t *p_stream, MP4_Box_t *p_box )
839 {
840 #define es_descriptor p_box->data.p_esds->es_descriptor
841     unsigned int i_len;
842     unsigned int i_flags;
843     unsigned int i_type;
844
845     MP4_READBOX_ENTER( MP4_Box_data_esds_t );
846
847     MP4_GETVERSIONFLAGS( p_box->data.p_esds );
848
849
850     MP4_GET1BYTE( i_type );
851     if( i_type == 0x03 ) /* MP4ESDescrTag */
852     {
853         i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
854
855 #ifdef MP4_VERBOSE
856         msg_Dbg( p_stream, "found esds MPEG4ESDescr (%dBytes)",
857                  i_len );
858 #endif
859
860         MP4_GET2BYTES( es_descriptor.i_ES_ID );
861         MP4_GET1BYTE( i_flags );
862         es_descriptor.b_stream_dependence = ( (i_flags&0x80) != 0);
863         es_descriptor.b_url = ( (i_flags&0x40) != 0);
864         es_descriptor.b_OCRstream = ( (i_flags&0x20) != 0);
865
866         es_descriptor.i_stream_priority = i_flags&0x1f;
867         if( es_descriptor.b_stream_dependence )
868         {
869             MP4_GET2BYTES( es_descriptor.i_depend_on_ES_ID );
870         }
871         if( es_descriptor.b_url )
872         {
873             unsigned int i_len;
874
875             MP4_GET1BYTE( i_len );
876             es_descriptor.psz_URL = calloc( sizeof(char), i_len + 1 );
877             memcpy( es_descriptor.psz_URL, p_peek, i_len );
878             es_descriptor.psz_URL[i_len] = 0;
879             p_peek += i_len;
880             i_read -= i_len;
881         }
882         else
883         {
884             es_descriptor.psz_URL = NULL;
885         }
886         if( es_descriptor.b_OCRstream )
887         {
888             MP4_GET2BYTES( es_descriptor.i_OCR_ES_ID );
889         }
890         MP4_GET1BYTE( i_type ); /* get next type */
891     }
892
893     if( i_type != 0x04)/* MP4DecConfigDescrTag */
894     {
895          es_descriptor.p_decConfigDescr = NULL;
896          MP4_READBOX_EXIT( 1 ); /* rest isn't interesting up to now */
897     }
898
899     i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
900
901 #ifdef MP4_VERBOSE
902         msg_Dbg( p_stream, "found esds MP4DecConfigDescr (%dBytes)",
903                  i_len );
904 #endif
905
906     es_descriptor.p_decConfigDescr =
907             malloc( sizeof( MP4_descriptor_decoder_config_t ));
908
909     MP4_GET1BYTE( es_descriptor.p_decConfigDescr->i_objectTypeIndication );
910     MP4_GET1BYTE( i_flags );
911     es_descriptor.p_decConfigDescr->i_streamType = i_flags >> 2;
912     es_descriptor.p_decConfigDescr->b_upStream = ( i_flags >> 1 )&0x01;
913     MP4_GET3BYTES( es_descriptor.p_decConfigDescr->i_buffer_sizeDB );
914     MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_max_bitrate );
915     MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_avg_bitrate );
916     MP4_GET1BYTE( i_type );
917     if( i_type !=  0x05 )/* MP4DecSpecificDescrTag */
918     {
919         es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = 0;
920         es_descriptor.p_decConfigDescr->p_decoder_specific_info  = NULL;
921         MP4_READBOX_EXIT( 1 );
922     }
923
924     i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
925
926 #ifdef MP4_VERBOSE
927         msg_Dbg( p_stream, "found esds MP4DecSpecificDescr (%dBytes)",
928                  i_len );
929 #endif
930
931     es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = i_len;
932     es_descriptor.p_decConfigDescr->p_decoder_specific_info = malloc( i_len );
933     memcpy( es_descriptor.p_decConfigDescr->p_decoder_specific_info,
934             p_peek, i_len );
935
936     MP4_READBOX_EXIT( 1 );
937
938 #undef es_descriptor
939 }
940
941 static void MP4_FreeBox_esds( MP4_Box_t *p_box )
942 {
943     FREENULL( p_box->data.p_esds->es_descriptor.psz_URL );
944     if( p_box->data.p_esds->es_descriptor.p_decConfigDescr )
945     {
946         FREENULL( p_box->data.p_esds->es_descriptor.p_decConfigDescr->p_decoder_specific_info );
947     }
948     FREENULL( p_box->data.p_esds->es_descriptor.p_decConfigDescr );
949 }
950
951 static int MP4_ReadBox_avcC( stream_t *p_stream, MP4_Box_t *p_box )
952 {
953     MP4_Box_data_avcC_t *p_avcC;
954     int i;
955
956     MP4_READBOX_ENTER( MP4_Box_data_avcC_t );
957     p_avcC = p_box->data.p_avcC;
958
959     p_avcC->i_avcC = i_read;
960     p_avcC->p_avcC = malloc( p_avcC->i_avcC );
961     memcpy( p_avcC->p_avcC, p_peek, i_read );
962
963     MP4_GET1BYTE( p_avcC->i_version );
964     MP4_GET1BYTE( p_avcC->i_profile );
965     MP4_GET1BYTE( p_avcC->i_profile_compatibility );
966     MP4_GET1BYTE( p_avcC->i_level );
967     MP4_GET1BYTE( p_avcC->i_reserved1 );
968     p_avcC->i_length_size = (p_avcC->i_reserved1&0x03) + 1;
969     p_avcC->i_reserved1 >>= 2;
970
971     MP4_GET1BYTE( p_avcC->i_reserved2 );
972     p_avcC->i_sps = p_avcC->i_reserved2&0x1f;
973     p_avcC->i_reserved2 >>= 5;
974
975     if( p_avcC->i_sps > 0 )
976     {
977         p_avcC->i_sps_length = malloc( p_avcC->i_sps * sizeof( uint16_t ) );
978         p_avcC->sps = malloc( p_avcC->i_sps * sizeof( uint8_t* ) );
979
980         for( i = 0; i < p_avcC->i_sps; i++ )
981         {
982             MP4_GET2BYTES( p_avcC->i_sps_length[i] );
983             p_avcC->sps[i] = malloc( p_avcC->i_sps_length[i] );
984             memcpy( p_avcC->sps[i], p_peek, p_avcC->i_sps_length[i] );
985
986             p_peek += p_avcC->i_sps_length[i];
987             i_read -= p_avcC->i_sps_length[i];
988         }
989     }
990
991     MP4_GET1BYTE( p_avcC->i_pps );
992     if( p_avcC->i_pps > 0 )
993     {
994         p_avcC->i_pps_length = malloc( p_avcC->i_pps * sizeof( uint16_t ) );
995         p_avcC->pps = malloc( p_avcC->i_pps * sizeof( uint8_t* ) );
996
997         for( i = 0; i < p_avcC->i_pps; i++ )
998         {
999             MP4_GET2BYTES( p_avcC->i_pps_length[i] );
1000             p_avcC->pps[i] = malloc( p_avcC->i_pps_length[i] );
1001             memcpy( p_avcC->pps[i], p_peek, p_avcC->i_pps_length[i] );
1002
1003             p_peek += p_avcC->i_pps_length[i];
1004             i_read -= p_avcC->i_pps_length[i];
1005         }
1006     }
1007 #ifdef MP4_VERBOSE
1008     msg_Dbg( p_stream,
1009              "read box: \"avcC\" version=%d profile=0x%x level=0x%x length size=%d sps=%d pps=%d",
1010              p_avcC->i_version, p_avcC->i_profile, p_avcC->i_level,
1011              p_avcC->i_length_size,
1012              p_avcC->i_sps, p_avcC->i_pps );
1013     for( i = 0; i < p_avcC->i_sps; i++ )
1014     {
1015         msg_Dbg( p_stream, "         - sps[%d] length=%d",
1016                  i, p_avcC->i_sps_length[i] );
1017     }
1018     for( i = 0; i < p_avcC->i_pps; i++ )
1019     {
1020         msg_Dbg( p_stream, "         - pps[%d] length=%d",
1021                  i, p_avcC->i_pps_length[i] );
1022     }
1023
1024 #endif
1025     MP4_READBOX_EXIT( 1 );
1026 }
1027
1028 static void MP4_FreeBox_avcC( MP4_Box_t *p_box )
1029 {
1030     MP4_Box_data_avcC_t *p_avcC = p_box->data.p_avcC;
1031     int i;
1032
1033     for( i = 0; i < p_avcC->i_sps; i++ )
1034     {
1035         FREENULL( p_avcC->sps[i] );
1036     }
1037     for( i = 0; i < p_avcC->i_pps; i++ )
1038     {
1039         FREENULL( p_avcC->pps[i] );
1040     }
1041     if( p_avcC->i_sps > 0 ) FREENULL( p_avcC->sps );
1042     if( p_avcC->i_pps > 0 ) FREENULL( p_avcC->pps );
1043 }
1044
1045 static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box )
1046 {
1047     unsigned int i;
1048
1049     MP4_READBOX_ENTER( MP4_Box_data_sample_soun_t );
1050     p_box->data.p_sample_soun->p_qt_description = NULL;
1051
1052     /* Sanity check needed because the "wave" box does also contain an
1053      * "mp4a" box that we don't understand. */
1054     if( i_read < 28 )
1055     {
1056         i_read -= 30;
1057         MP4_READBOX_EXIT( 1 );
1058     }
1059
1060     for( i = 0; i < 6 ; i++ )
1061     {
1062         MP4_GET1BYTE( p_box->data.p_sample_soun->i_reserved1[i] );
1063     }
1064
1065     MP4_GET2BYTES( p_box->data.p_sample_soun->i_data_reference_index );
1066
1067     /*
1068      * XXX hack -> produce a copy of the nearly complete chunk
1069      */
1070     if( i_read > 0 )
1071     {
1072         p_box->data.p_sample_soun->i_qt_description = i_read;
1073         p_box->data.p_sample_soun->p_qt_description = malloc( i_read );
1074         memcpy( p_box->data.p_sample_soun->p_qt_description, p_peek, i_read );
1075     }
1076     else
1077     {
1078         p_box->data.p_sample_soun->i_qt_description = 0;
1079         p_box->data.p_sample_soun->p_qt_description = NULL;
1080     }
1081
1082     MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_version );
1083     MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_revision_level );
1084     MP4_GET4BYTES( p_box->data.p_sample_soun->i_qt_vendor );
1085
1086     MP4_GET2BYTES( p_box->data.p_sample_soun->i_channelcount );
1087     MP4_GET2BYTES( p_box->data.p_sample_soun->i_samplesize );
1088     MP4_GET2BYTES( p_box->data.p_sample_soun->i_predefined );
1089     MP4_GET2BYTES( p_box->data.p_sample_soun->i_reserved3 );
1090     MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratehi );
1091     MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratelo );
1092
1093     if( p_box->data.p_sample_soun->i_qt_version == 1 && i_read >= 16 )
1094     {
1095         /* SoundDescriptionV1 */
1096         MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet );
1097         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_packet );
1098         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_frame );
1099         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_sample );
1100
1101 #ifdef MP4_VERBOSE
1102         msg_Dbg( p_stream,
1103                  "read box: \"soun\" qt3+ sample/packet=%d bytes/packet=%d "
1104                  "bytes/frame=%d bytes/sample=%d",
1105                  p_box->data.p_sample_soun->i_sample_per_packet,
1106                  p_box->data.p_sample_soun->i_bytes_per_packet,
1107                  p_box->data.p_sample_soun->i_bytes_per_frame,
1108                  p_box->data.p_sample_soun->i_bytes_per_sample );
1109 #endif
1110         stream_Seek( p_stream, p_box->i_pos +
1111                         MP4_BOX_HEADERSIZE( p_box ) + 44 );
1112     }
1113     else if( p_box->data.p_sample_soun->i_qt_version == 2 && i_read >= 36 )
1114     {
1115         /* SoundDescriptionV2 */
1116         double f_sample_rate;
1117         int64_t dummy;
1118         uint32_t i_channel;
1119
1120         MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet );
1121         MP4_GET8BYTES( dummy );
1122         memcpy( &f_sample_rate, &dummy, 8 );
1123
1124         msg_Dbg( p_stream, "read box: %f Hz", f_sample_rate );
1125         p_box->data.p_sample_soun->i_sampleratehi = (int)f_sample_rate % 65536;
1126         p_box->data.p_sample_soun->i_sampleratelo = f_sample_rate / 65536;
1127
1128         MP4_GET4BYTES( i_channel );
1129         p_box->data.p_sample_soun->i_channelcount = i_channel;
1130
1131 #ifdef MP4_VERBOSE
1132         msg_Dbg( p_stream, "read box: \"soun\" V2" );
1133 #endif
1134         stream_Seek( p_stream, p_box->i_pos +
1135                         MP4_BOX_HEADERSIZE( p_box ) + 28 + 36 );
1136     }
1137     else
1138     {
1139         p_box->data.p_sample_soun->i_sample_per_packet = 0;
1140         p_box->data.p_sample_soun->i_bytes_per_packet = 0;
1141         p_box->data.p_sample_soun->i_bytes_per_frame = 0;
1142         p_box->data.p_sample_soun->i_bytes_per_sample = 0;
1143
1144         msg_Dbg( p_stream, "read box: \"soun\" mp4 or qt1/2 (rest="I64Fd")",
1145                  i_read );
1146         stream_Seek( p_stream, p_box->i_pos +
1147                         MP4_BOX_HEADERSIZE( p_box ) + 28 );
1148     }
1149
1150     if( p_box->i_type == FOURCC_drms )
1151     {
1152         p_box->data.p_sample_soun->p_drms =
1153             drms_alloc( p_stream->p_libvlc->psz_homedir );
1154
1155         if( p_box->data.p_sample_soun->p_drms == NULL )
1156         {
1157             msg_Err( p_stream, "drms_alloc() failed" );
1158         }
1159     }
1160
1161     if( p_box->i_type == FOURCC_samr || p_box->i_type == FOURCC_sawb )
1162     {
1163         /* Ignore channelcount for AMR (3gpp AMRSpecificBox) */
1164         p_box->data.p_sample_soun->i_channelcount = 1;
1165     }
1166
1167     if( p_box->i_type == FOURCC_alac )
1168     {
1169         if( p_box->data.p_sample_soun->p_qt_description )
1170             free( p_box->data.p_sample_soun->p_qt_description );
1171
1172         p_box->data.p_sample_soun->p_qt_description = malloc( i_read );
1173         p_box->data.p_sample_soun->i_qt_description = i_read;
1174         memcpy( p_box->data.p_sample_soun->p_qt_description, p_peek, i_read );
1175     }
1176     else
1177     {
1178         MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds */
1179     }
1180
1181 #ifdef MP4_VERBOSE
1182     msg_Dbg( p_stream, "read box: \"soun\" in stsd channel %d "
1183              "sample size %d sample rate %f",
1184              p_box->data.p_sample_soun->i_channelcount,
1185              p_box->data.p_sample_soun->i_samplesize,
1186              (float)p_box->data.p_sample_soun->i_sampleratehi +
1187              (float)p_box->data.p_sample_soun->i_sampleratelo / 65536 );
1188
1189 #endif
1190     MP4_READBOX_EXIT( 1 );
1191 }
1192
1193
1194 static void MP4_FreeBox_sample_soun( MP4_Box_t *p_box )
1195 {
1196     FREENULL( p_box->data.p_sample_soun->p_qt_description );
1197
1198     if( p_box->i_type == FOURCC_drms )
1199     {
1200         if( p_box->data.p_sample_soun->p_drms )
1201         {
1202             drms_free( p_box->data.p_sample_soun->p_drms );
1203         }
1204     }
1205 }
1206
1207
1208 int MP4_ReadBox_sample_vide( stream_t *p_stream, MP4_Box_t *p_box )
1209 {
1210     unsigned int i;
1211
1212     MP4_READBOX_ENTER( MP4_Box_data_sample_vide_t );
1213
1214     for( i = 0; i < 6 ; i++ )
1215     {
1216         MP4_GET1BYTE( p_box->data.p_sample_vide->i_reserved1[i] );
1217     }
1218
1219     MP4_GET2BYTES( p_box->data.p_sample_vide->i_data_reference_index );
1220
1221     /*
1222      * XXX hack -> produce a copy of the nearly complete chunk
1223      */
1224     if( i_read > 0 )
1225     {
1226         p_box->data.p_sample_vide->i_qt_image_description = i_read;
1227         p_box->data.p_sample_vide->p_qt_image_description = malloc( i_read );
1228         memcpy( p_box->data.p_sample_vide->p_qt_image_description,
1229                 p_peek, i_read );
1230     }
1231     else
1232     {
1233         p_box->data.p_sample_vide->i_qt_image_description = 0;
1234         p_box->data.p_sample_vide->p_qt_image_description = NULL;
1235     }
1236
1237     MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_version );
1238     MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_revision_level );
1239     MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_vendor );
1240
1241     MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_temporal_quality );
1242     MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_spatial_quality );
1243
1244     MP4_GET2BYTES( p_box->data.p_sample_vide->i_width );
1245     MP4_GET2BYTES( p_box->data.p_sample_vide->i_height );
1246
1247     MP4_GET4BYTES( p_box->data.p_sample_vide->i_horizresolution );
1248     MP4_GET4BYTES( p_box->data.p_sample_vide->i_vertresolution );
1249
1250     MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_data_size );
1251     MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_frame_count );
1252
1253     memcpy( &p_box->data.p_sample_vide->i_compressorname, p_peek, 32 );
1254     p_peek += 32; i_read -= 32;
1255
1256     MP4_GET2BYTES( p_box->data.p_sample_vide->i_depth );
1257     MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_color_table );
1258
1259     stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 78);
1260     MP4_ReadBoxContainerRaw( p_stream, p_box );
1261
1262 #ifdef MP4_VERBOSE
1263     msg_Dbg( p_stream, "read box: \"vide\" in stsd %dx%d depth %d",
1264                       p_box->data.p_sample_vide->i_width,
1265                       p_box->data.p_sample_vide->i_height,
1266                       p_box->data.p_sample_vide->i_depth );
1267
1268 #endif
1269     MP4_READBOX_EXIT( 1 );
1270 }
1271
1272
1273 void MP4_FreeBox_sample_vide( MP4_Box_t *p_box )
1274 {
1275     FREENULL( p_box->data.p_sample_vide->p_qt_image_description );
1276 }
1277
1278 static int MP4_ReadBox_sample_mp4s( stream_t *p_stream, MP4_Box_t *p_box )
1279 {
1280     stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 8 );
1281     MP4_ReadBoxContainerRaw( p_stream, p_box );
1282     return 1;
1283 }
1284
1285 static int MP4_ReadBox_sample_text( stream_t *p_stream, MP4_Box_t *p_box )
1286 {
1287     int32_t t;
1288
1289     MP4_READBOX_ENTER( MP4_Box_data_sample_text_t );
1290
1291     MP4_GET4BYTES( p_box->data.p_sample_text->i_reserved1 );
1292     MP4_GET2BYTES( p_box->data.p_sample_text->i_reserved2 );
1293
1294     MP4_GET2BYTES( p_box->data.p_sample_text->i_data_reference_index );
1295
1296     MP4_GET4BYTES( p_box->data.p_sample_text->i_display_flags );
1297
1298     MP4_GET4BYTES( t );
1299     switch( t )
1300     {
1301         /* FIXME search right signification */
1302         case 1: // Center
1303             p_box->data.p_sample_text->i_justification_horizontal = 1;
1304             p_box->data.p_sample_text->i_justification_vertical = 1;
1305             break;
1306         case -1:    // Flush Right
1307             p_box->data.p_sample_text->i_justification_horizontal = -1;
1308             p_box->data.p_sample_text->i_justification_vertical = -1;
1309             break;
1310         case -2:    // Flush Left
1311             p_box->data.p_sample_text->i_justification_horizontal = 0;
1312             p_box->data.p_sample_text->i_justification_vertical = 0;
1313             break;
1314         case 0: // Flush Default
1315         default:
1316             p_box->data.p_sample_text->i_justification_horizontal = 1;
1317             p_box->data.p_sample_text->i_justification_vertical = -1;
1318             break;
1319     }
1320
1321     MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[0] );
1322     MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[1] );
1323     MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[2] );
1324     p_box->data.p_sample_text->i_background_color[3] = 0;
1325
1326     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_top );
1327     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_left );
1328     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_bottom );
1329     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_right );
1330
1331 #ifdef MP4_VERBOSE
1332     msg_Dbg( p_stream, "read box: \"text\" in stsd text" );
1333 #endif
1334     MP4_READBOX_EXIT( 1 );
1335 }
1336
1337 static int MP4_ReadBox_sample_tx3g( stream_t *p_stream, MP4_Box_t *p_box )
1338 {
1339     MP4_READBOX_ENTER( MP4_Box_data_sample_text_t );
1340
1341     MP4_GET4BYTES( p_box->data.p_sample_text->i_reserved1 );
1342     MP4_GET2BYTES( p_box->data.p_sample_text->i_reserved2 );
1343
1344     MP4_GET2BYTES( p_box->data.p_sample_text->i_data_reference_index );
1345
1346     MP4_GET4BYTES( p_box->data.p_sample_text->i_display_flags );
1347
1348     MP4_GET1BYTE ( p_box->data.p_sample_text->i_justification_horizontal );
1349     MP4_GET1BYTE ( p_box->data.p_sample_text->i_justification_vertical );
1350
1351     MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[0] );
1352     MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[1] );
1353     MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[2] );
1354     MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[3] );
1355
1356     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_top );
1357     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_left );
1358     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_bottom );
1359     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_right );
1360
1361 #ifdef MP4_VERBOSE
1362     msg_Dbg( p_stream, "read box: \"text\" in stsd text" );
1363 #endif
1364     MP4_READBOX_EXIT( 1 );
1365 }
1366
1367
1368 #if 0
1369 /* We can't easily call it, and anyway ~ 20 bytes lost isn't a real problem */
1370 static void MP4_FreeBox_sample_text( MP4_Box_t *p_box )
1371 {
1372     FREENULL( p_box->data.p_sample_text->psz_text_name );
1373 }
1374 #endif
1375
1376
1377 static int MP4_ReadBox_stsd( stream_t *p_stream, MP4_Box_t *p_box )
1378 {
1379
1380     MP4_READBOX_ENTER( MP4_Box_data_stsd_t );
1381
1382     MP4_GETVERSIONFLAGS( p_box->data.p_stsd );
1383
1384     MP4_GET4BYTES( p_box->data.p_stsd->i_entry_count );
1385
1386     stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 8 );
1387
1388     MP4_ReadBoxContainerRaw( p_stream, p_box );
1389
1390 #ifdef MP4_VERBOSE
1391     msg_Dbg( p_stream, "read box: \"stsd\" entry-count %d",
1392                       p_box->data.p_stsd->i_entry_count );
1393
1394 #endif
1395     MP4_READBOX_EXIT( 1 );
1396 }
1397
1398
1399 static int MP4_ReadBox_stsz( stream_t *p_stream, MP4_Box_t *p_box )
1400 {
1401     unsigned int i;
1402
1403     MP4_READBOX_ENTER( MP4_Box_data_stsz_t );
1404
1405     MP4_GETVERSIONFLAGS( p_box->data.p_stsz );
1406
1407     MP4_GET4BYTES( p_box->data.p_stsz->i_sample_size );
1408
1409     MP4_GET4BYTES( p_box->data.p_stsz->i_sample_count );
1410
1411     p_box->data.p_stsz->i_entry_size =
1412         calloc( sizeof( uint32_t ), p_box->data.p_stsz->i_sample_count );
1413
1414     if( !p_box->data.p_stsz->i_sample_size )
1415     {
1416         for( i=0; (i<p_box->data.p_stsz->i_sample_count)&&(i_read >= 4 ); i++ )
1417         {
1418             MP4_GET4BYTES( p_box->data.p_stsz->i_entry_size[i] );
1419         }
1420     }
1421
1422 #ifdef MP4_VERBOSE
1423     msg_Dbg( p_stream, "read box: \"stsz\" sample-size %d sample-count %d",
1424                       p_box->data.p_stsz->i_sample_size,
1425                       p_box->data.p_stsz->i_sample_count );
1426
1427 #endif
1428     MP4_READBOX_EXIT( 1 );
1429 }
1430
1431 static void MP4_FreeBox_stsz( MP4_Box_t *p_box )
1432 {
1433     FREENULL( p_box->data.p_stsz->i_entry_size );
1434 }
1435
1436 static int MP4_ReadBox_stsc( stream_t *p_stream, MP4_Box_t *p_box )
1437 {
1438     unsigned int i;
1439
1440     MP4_READBOX_ENTER( MP4_Box_data_stsc_t );
1441
1442     MP4_GETVERSIONFLAGS( p_box->data.p_stsc );
1443
1444     MP4_GET4BYTES( p_box->data.p_stsc->i_entry_count );
1445
1446     p_box->data.p_stsc->i_first_chunk =
1447         calloc( sizeof( uint32_t ), p_box->data.p_stsc->i_entry_count );
1448     p_box->data.p_stsc->i_samples_per_chunk =
1449         calloc( sizeof( uint32_t ), p_box->data.p_stsc->i_entry_count );
1450     p_box->data.p_stsc->i_sample_description_index =
1451         calloc( sizeof( uint32_t ), p_box->data.p_stsc->i_entry_count );
1452
1453     for( i = 0; (i < p_box->data.p_stsc->i_entry_count )&&( i_read >= 12 );i++ )
1454     {
1455         MP4_GET4BYTES( p_box->data.p_stsc->i_first_chunk[i] );
1456         MP4_GET4BYTES( p_box->data.p_stsc->i_samples_per_chunk[i] );
1457         MP4_GET4BYTES( p_box->data.p_stsc->i_sample_description_index[i] );
1458     }
1459
1460 #ifdef MP4_VERBOSE
1461     msg_Dbg( p_stream, "read box: \"stsc\" entry-count %d",
1462                       p_box->data.p_stsc->i_entry_count );
1463
1464 #endif
1465     MP4_READBOX_EXIT( 1 );
1466 }
1467
1468 static void MP4_FreeBox_stsc( MP4_Box_t *p_box )
1469 {
1470     FREENULL( p_box->data.p_stsc->i_first_chunk );
1471     FREENULL( p_box->data.p_stsc->i_samples_per_chunk );
1472     FREENULL( p_box->data.p_stsc->i_sample_description_index );
1473 }
1474
1475 static int MP4_ReadBox_stco_co64( stream_t *p_stream, MP4_Box_t *p_box )
1476 {
1477     unsigned int i;
1478
1479     MP4_READBOX_ENTER( MP4_Box_data_co64_t );
1480
1481     MP4_GETVERSIONFLAGS( p_box->data.p_co64 );
1482
1483     MP4_GET4BYTES( p_box->data.p_co64->i_entry_count );
1484
1485     p_box->data.p_co64->i_chunk_offset =
1486         calloc( sizeof( uint64_t ), p_box->data.p_co64->i_entry_count );
1487
1488     for( i = 0; i < p_box->data.p_co64->i_entry_count; i++ )
1489     {
1490         if( p_box->i_type == FOURCC_stco )
1491         {
1492             if( i_read < 4 )
1493             {
1494                 break;
1495             }
1496             MP4_GET4BYTES( p_box->data.p_co64->i_chunk_offset[i] );
1497         }
1498         else
1499         {
1500             if( i_read < 8 )
1501             {
1502                 break;
1503             }
1504             MP4_GET8BYTES( p_box->data.p_co64->i_chunk_offset[i] );
1505         }
1506     }
1507
1508 #ifdef MP4_VERBOSE
1509     msg_Dbg( p_stream, "read box: \"co64\" entry-count %d",
1510                       p_box->data.p_co64->i_entry_count );
1511
1512 #endif
1513     MP4_READBOX_EXIT( 1 );
1514 }
1515
1516 static void MP4_FreeBox_stco_co64( MP4_Box_t *p_box )
1517 {
1518     FREENULL( p_box->data.p_co64->i_chunk_offset );
1519 }
1520
1521 static int MP4_ReadBox_stss( stream_t *p_stream, MP4_Box_t *p_box )
1522 {
1523     unsigned int i;
1524
1525     MP4_READBOX_ENTER( MP4_Box_data_stss_t );
1526
1527     MP4_GETVERSIONFLAGS( p_box->data.p_stss );
1528
1529     MP4_GET4BYTES( p_box->data.p_stss->i_entry_count );
1530
1531     p_box->data.p_stss->i_sample_number =
1532         calloc( sizeof( uint32_t ), p_box->data.p_stss->i_entry_count );
1533
1534     for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 4 ); i++ )
1535     {
1536
1537         MP4_GET4BYTES( p_box->data.p_stss->i_sample_number[i] );
1538         /* XXX in libmp4 sample begin at 0 */
1539         p_box->data.p_stss->i_sample_number[i]--;
1540     }
1541
1542 #ifdef MP4_VERBOSE
1543     msg_Dbg( p_stream, "read box: \"stss\" entry-count %d",
1544                       p_box->data.p_stss->i_entry_count );
1545
1546 #endif
1547     MP4_READBOX_EXIT( 1 );
1548 }
1549
1550 static void MP4_FreeBox_stss( MP4_Box_t *p_box )
1551 {
1552     FREENULL( p_box->data.p_stss->i_sample_number )
1553 }
1554
1555 static int MP4_ReadBox_stsh( stream_t *p_stream, MP4_Box_t *p_box )
1556 {
1557     unsigned int i;
1558
1559     MP4_READBOX_ENTER( MP4_Box_data_stsh_t );
1560
1561     MP4_GETVERSIONFLAGS( p_box->data.p_stsh );
1562
1563
1564     MP4_GET4BYTES( p_box->data.p_stsh->i_entry_count );
1565
1566     p_box->data.p_stsh->i_shadowed_sample_number =
1567         calloc( sizeof( uint32_t ), p_box->data.p_stsh->i_entry_count );
1568
1569     p_box->data.p_stsh->i_sync_sample_number =
1570         calloc( sizeof( uint32_t ), p_box->data.p_stsh->i_entry_count );
1571
1572
1573     for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 8 ); i++ )
1574     {
1575
1576         MP4_GET4BYTES( p_box->data.p_stsh->i_shadowed_sample_number[i] );
1577         MP4_GET4BYTES( p_box->data.p_stsh->i_sync_sample_number[i] );
1578     }
1579
1580 #ifdef MP4_VERBOSE
1581     msg_Dbg( p_stream, "read box: \"stsh\" entry-count %d",
1582                       p_box->data.p_stsh->i_entry_count );
1583 #endif
1584     MP4_READBOX_EXIT( 1 );
1585 }
1586
1587 static void MP4_FreeBox_stsh( MP4_Box_t *p_box )
1588 {
1589     FREENULL( p_box->data.p_stsh->i_shadowed_sample_number )
1590     FREENULL( p_box->data.p_stsh->i_sync_sample_number )
1591 }
1592
1593
1594 static int MP4_ReadBox_stdp( stream_t *p_stream, MP4_Box_t *p_box )
1595 {
1596     unsigned int i;
1597
1598     MP4_READBOX_ENTER( MP4_Box_data_stdp_t );
1599
1600     MP4_GETVERSIONFLAGS( p_box->data.p_stdp );
1601
1602     p_box->data.p_stdp->i_priority =
1603         calloc( sizeof( uint16_t ), i_read / 2 );
1604
1605     for( i = 0; i < i_read / 2 ; i++ )
1606     {
1607
1608         MP4_GET2BYTES( p_box->data.p_stdp->i_priority[i] );
1609     }
1610
1611 #ifdef MP4_VERBOSE
1612     msg_Dbg( p_stream, "read box: \"stdp\" entry-count "I64Fd,
1613                       i_read / 2 );
1614
1615 #endif
1616     MP4_READBOX_EXIT( 1 );
1617 }
1618
1619 static void MP4_FreeBox_stdp( MP4_Box_t *p_box )
1620 {
1621     FREENULL( p_box->data.p_stdp->i_priority )
1622 }
1623
1624 static int MP4_ReadBox_padb( stream_t *p_stream, MP4_Box_t *p_box )
1625 {
1626     unsigned int i;
1627
1628     MP4_READBOX_ENTER( MP4_Box_data_padb_t );
1629
1630     MP4_GETVERSIONFLAGS( p_box->data.p_padb );
1631
1632
1633     MP4_GET4BYTES( p_box->data.p_padb->i_sample_count );
1634
1635     p_box->data.p_padb->i_reserved1 =
1636         calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
1637     p_box->data.p_padb->i_pad2 =
1638         calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
1639     p_box->data.p_padb->i_reserved2 =
1640         calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
1641     p_box->data.p_padb->i_pad1 =
1642         calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
1643
1644
1645     for( i = 0; i < i_read / 2 ; i++ )
1646     {
1647         p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 7 )&0x01;
1648         p_box->data.p_padb->i_pad2[i] = ( (*p_peek) >> 4 )&0x07;
1649         p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 3 )&0x01;
1650         p_box->data.p_padb->i_pad1[i] = ( (*p_peek) )&0x07;
1651
1652         p_peek += 1; i_read -= 1;
1653     }
1654
1655 #ifdef MP4_VERBOSE
1656     msg_Dbg( p_stream, "read box: \"stdp\" entry-count "I64Fd,
1657                       i_read / 2 );
1658
1659 #endif
1660     MP4_READBOX_EXIT( 1 );
1661 }
1662
1663 static void MP4_FreeBox_padb( MP4_Box_t *p_box )
1664 {
1665     FREENULL( p_box->data.p_padb->i_reserved1 );
1666     FREENULL( p_box->data.p_padb->i_pad2 );
1667     FREENULL( p_box->data.p_padb->i_reserved2 );
1668     FREENULL( p_box->data.p_padb->i_pad1 );
1669 }
1670
1671 static int MP4_ReadBox_elst( stream_t *p_stream, MP4_Box_t *p_box )
1672 {
1673     unsigned int i;
1674
1675     MP4_READBOX_ENTER( MP4_Box_data_padb_t );
1676
1677     MP4_GETVERSIONFLAGS( p_box->data.p_elst );
1678
1679
1680     MP4_GET4BYTES( p_box->data.p_elst->i_entry_count );
1681
1682     p_box->data.p_elst->i_segment_duration =
1683         calloc( sizeof( uint64_t ), p_box->data.p_elst->i_entry_count );
1684     p_box->data.p_elst->i_media_time =
1685         calloc( sizeof( int64_t ),  p_box->data.p_elst->i_entry_count );
1686     p_box->data.p_elst->i_media_rate_integer =
1687         calloc( sizeof( uint16_t ), p_box->data.p_elst->i_entry_count );
1688     p_box->data.p_elst->i_media_rate_fraction=
1689         calloc( sizeof( uint16_t ), p_box->data.p_elst->i_entry_count );
1690
1691
1692     for( i = 0; i < p_box->data.p_elst->i_entry_count; i++ )
1693     {
1694         if( p_box->data.p_elst->i_version == 1 )
1695         {
1696
1697             MP4_GET8BYTES( p_box->data.p_elst->i_segment_duration[i] );
1698
1699             MP4_GET8BYTES( p_box->data.p_elst->i_media_time[i] );
1700         }
1701         else
1702         {
1703
1704             MP4_GET4BYTES( p_box->data.p_elst->i_segment_duration[i] );
1705
1706             MP4_GET4BYTES( p_box->data.p_elst->i_media_time[i] );
1707             p_box->data.p_elst->i_media_time[i] = (int32_t)p_box->data.p_elst->i_media_time[i];
1708         }
1709
1710         MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_integer[i] );
1711         MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_fraction[i] );
1712     }
1713
1714 #ifdef MP4_VERBOSE
1715     msg_Dbg( p_stream, "read box: \"elst\" entry-count "I64Fd,
1716                       i_read / 2 );
1717
1718 #endif
1719     MP4_READBOX_EXIT( 1 );
1720 }
1721
1722 static void MP4_FreeBox_elst( MP4_Box_t *p_box )
1723 {
1724     FREENULL( p_box->data.p_elst->i_segment_duration );
1725     FREENULL( p_box->data.p_elst->i_media_time );
1726     FREENULL( p_box->data.p_elst->i_media_rate_integer );
1727     FREENULL( p_box->data.p_elst->i_media_rate_fraction );
1728 }
1729
1730 static int MP4_ReadBox_cprt( stream_t *p_stream, MP4_Box_t *p_box )
1731 {
1732     unsigned int i_language;
1733     unsigned int i;
1734
1735     MP4_READBOX_ENTER( MP4_Box_data_cprt_t );
1736
1737     MP4_GETVERSIONFLAGS( p_box->data.p_cprt );
1738
1739     i_language = GetWBE( p_peek );
1740     for( i = 0; i < 3; i++ )
1741     {
1742         p_box->data.p_cprt->i_language[i] =
1743             ( ( i_language >> ( (2-i)*5 ) )&0x1f ) + 0x60;
1744     }
1745     p_peek += 2; i_read -= 2;
1746     MP4_GETSTRINGZ( p_box->data.p_cprt->psz_notice );
1747
1748 #ifdef MP4_VERBOSE
1749     msg_Dbg( p_stream, "read box: \"cprt\" language %c%c%c notice %s",
1750                       p_box->data.p_cprt->i_language[0],
1751                       p_box->data.p_cprt->i_language[1],
1752                       p_box->data.p_cprt->i_language[2],
1753                       p_box->data.p_cprt->psz_notice );
1754
1755 #endif
1756     MP4_READBOX_EXIT( 1 );
1757 }
1758
1759 static void MP4_FreeBox_cprt( MP4_Box_t *p_box )
1760 {
1761     FREENULL( p_box->data.p_cprt->psz_notice );
1762 }
1763
1764
1765 static int MP4_ReadBox_dcom( stream_t *p_stream, MP4_Box_t *p_box )
1766 {
1767     MP4_READBOX_ENTER( MP4_Box_data_dcom_t );
1768
1769     MP4_GETFOURCC( p_box->data.p_dcom->i_algorithm );
1770 #ifdef MP4_VERBOSE
1771     msg_Dbg( p_stream,
1772              "read box: \"dcom\" compression algorithm : %4.4s",
1773                       (char*)&p_box->data.p_dcom->i_algorithm );
1774 #endif
1775     MP4_READBOX_EXIT( 1 );
1776 }
1777
1778 static int MP4_ReadBox_cmvd( stream_t *p_stream, MP4_Box_t *p_box )
1779 {
1780     MP4_READBOX_ENTER( MP4_Box_data_cmvd_t );
1781
1782     MP4_GET4BYTES( p_box->data.p_cmvd->i_uncompressed_size );
1783
1784     p_box->data.p_cmvd->i_compressed_size = i_read;
1785
1786     if( !( p_box->data.p_cmvd->p_data = malloc( i_read ) ) )
1787     {
1788         msg_Dbg( p_stream, "read box: \"cmvd\" not enough memory to load data" );
1789         return( 1 );
1790     }
1791
1792     /* now copy compressed data */
1793     memcpy( p_box->data.p_cmvd->p_data,
1794             p_peek,
1795             i_read);
1796
1797     p_box->data.p_cmvd->b_compressed = 1;
1798
1799 #ifdef MP4_VERBOSE
1800     msg_Dbg( p_stream, "read box: \"cmvd\" compressed data size %d",
1801                       p_box->data.p_cmvd->i_compressed_size );
1802 #endif
1803
1804     MP4_READBOX_EXIT( 1 );
1805 }
1806 static void MP4_FreeBox_cmvd( MP4_Box_t *p_box )
1807 {
1808     FREENULL( p_box->data.p_cmvd->p_data );
1809 }
1810
1811
1812 static int MP4_ReadBox_cmov( stream_t *p_stream, MP4_Box_t *p_box )
1813 {
1814     MP4_Box_t *p_dcom;
1815     MP4_Box_t *p_cmvd;
1816
1817 #ifdef HAVE_ZLIB_H
1818     stream_t *p_stream_memory;
1819     z_stream z_data;
1820     uint8_t *p_data;
1821     int i_result;
1822 #endif
1823
1824     if( !( p_box->data.p_cmov = malloc( sizeof( MP4_Box_data_cmov_t ) ) ) )
1825     {
1826         msg_Err( p_stream, "out of memory" );
1827         return 0;
1828     }
1829     memset( p_box->data.p_cmov, 0, sizeof( MP4_Box_data_cmov_t ) );
1830
1831     if( !p_box->p_father ||
1832         ( p_box->p_father->i_type != FOURCC_moov &&
1833           p_box->p_father->i_type != FOURCC_foov ) )
1834     {
1835         msg_Warn( p_stream, "Read box: \"cmov\" box alone" );
1836         return 1;
1837     }
1838
1839     if( !MP4_ReadBoxContainer( p_stream, p_box ) )
1840     {
1841         return 0;
1842     }
1843
1844     if( ( p_dcom = MP4_BoxGet( p_box, "dcom" ) ) == NULL ||
1845         ( p_cmvd = MP4_BoxGet( p_box, "cmvd" ) ) == NULL ||
1846         p_cmvd->data.p_cmvd->p_data == NULL )
1847     {
1848         msg_Warn( p_stream, "read box: \"cmov\" incomplete" );
1849         return 1;
1850     }
1851
1852     if( p_dcom->data.p_dcom->i_algorithm != FOURCC_zlib )
1853     {
1854         msg_Dbg( p_stream, "read box: \"cmov\" compression algorithm : %4.4s "
1855                  "not supported", (char*)&p_dcom->data.p_dcom->i_algorithm );
1856         return 1;
1857     }
1858
1859 #ifndef HAVE_ZLIB_H
1860     msg_Dbg( p_stream, "read box: \"cmov\" zlib unsupported" );
1861     return 1;
1862
1863 #else
1864     /* decompress data */
1865     /* allocate a new buffer */
1866     if( !( p_data = malloc( p_cmvd->data.p_cmvd->i_uncompressed_size ) ) )
1867     {
1868         msg_Err( p_stream, "read box: \"cmov\" not enough memory to "
1869                  "uncompress data" );
1870         return 1;
1871     }
1872     /* init default structures */
1873     z_data.next_in   = p_cmvd->data.p_cmvd->p_data;
1874     z_data.avail_in  = p_cmvd->data.p_cmvd->i_compressed_size;
1875     z_data.next_out  = p_data;
1876     z_data.avail_out = p_cmvd->data.p_cmvd->i_uncompressed_size;
1877     z_data.zalloc    = (alloc_func)Z_NULL;
1878     z_data.zfree     = (free_func)Z_NULL;
1879     z_data.opaque    = (voidpf)Z_NULL;
1880
1881     /* init zlib */
1882     if( inflateInit( &z_data ) != Z_OK )
1883     {
1884         msg_Err( p_stream, "read box: \"cmov\" error while uncompressing" );
1885         free( p_data );
1886         return 1;
1887     }
1888
1889     /* uncompress */
1890     i_result = inflate( &z_data, Z_NO_FLUSH );
1891     if( i_result != Z_OK && i_result != Z_STREAM_END )
1892     {
1893         msg_Err( p_stream, "read box: \"cmov\" error while uncompressing" );
1894         free( p_data );
1895         return 1;
1896     }
1897
1898     if( p_cmvd->data.p_cmvd->i_uncompressed_size != z_data.total_out )
1899     {
1900         msg_Warn( p_stream, "read box: \"cmov\" uncompressing data size "
1901                   "mismatch" );
1902     }
1903     p_cmvd->data.p_cmvd->i_uncompressed_size = z_data.total_out;
1904
1905     /* close zlib */
1906     if( inflateEnd( &z_data ) != Z_OK )
1907     {
1908         msg_Warn( p_stream, "read box: \"cmov\" error while uncompressing "
1909                   "data (ignored)" );
1910     }
1911
1912     free( p_cmvd->data.p_cmvd->p_data );
1913     p_cmvd->data.p_cmvd->p_data = p_data;
1914     p_cmvd->data.p_cmvd->b_compressed = 0;
1915
1916     msg_Dbg( p_stream, "read box: \"cmov\" box succesfully uncompressed" );
1917
1918     /* now create a memory stream */
1919     p_stream_memory =
1920         stream_MemoryNew( VLC_OBJECT(p_stream), p_cmvd->data.p_cmvd->p_data,
1921                           p_cmvd->data.p_cmvd->i_uncompressed_size, VLC_TRUE );
1922
1923     /* and read uncompressd moov */
1924     p_box->data.p_cmov->p_moov = MP4_ReadBox( p_stream_memory, NULL );
1925
1926     stream_Delete( p_stream_memory );
1927
1928 #ifdef MP4_VERBOSE
1929     msg_Dbg( p_stream, "read box: \"cmov\" compressed movie header completed");
1930 #endif
1931
1932     return p_box->data.p_cmov->p_moov ? 1 : 0;
1933 #endif /* HAVE_ZLIB_H */
1934 }
1935
1936 static int MP4_ReadBox_rdrf( stream_t *p_stream, MP4_Box_t *p_box )
1937 {
1938     uint32_t i_len;
1939     MP4_READBOX_ENTER( MP4_Box_data_rdrf_t );
1940
1941     MP4_GETVERSIONFLAGS( p_box->data.p_rdrf );
1942     MP4_GETFOURCC( p_box->data.p_rdrf->i_ref_type );
1943     MP4_GET4BYTES( i_len );
1944     if( i_len > 0 )
1945     {
1946         uint32_t i;
1947         p_box->data.p_rdrf->psz_ref = malloc( i_len  + 1);
1948         for( i = 0; i < i_len; i++ )
1949         {
1950             MP4_GET1BYTE( p_box->data.p_rdrf->psz_ref[i] );
1951         }
1952         p_box->data.p_rdrf->psz_ref[i_len] = '\0';
1953     }
1954     else
1955     {
1956         p_box->data.p_rdrf->psz_ref = NULL;
1957     }
1958
1959 #ifdef MP4_VERBOSE
1960     msg_Dbg( p_stream,
1961              "read box: \"rdrf\" type:%4.4s ref %s",
1962              (char*)&p_box->data.p_rdrf->i_ref_type,
1963              p_box->data.p_rdrf->psz_ref );
1964
1965 #endif
1966     MP4_READBOX_EXIT( 1 );
1967 }
1968
1969 static void MP4_FreeBox_rdrf( MP4_Box_t *p_box )
1970 {
1971     FREENULL( p_box->data.p_rdrf->psz_ref )
1972 }
1973
1974
1975 static int MP4_ReadBox_rmdr( stream_t *p_stream, MP4_Box_t *p_box )
1976 {
1977     MP4_READBOX_ENTER( MP4_Box_data_rmdr_t );
1978
1979     MP4_GETVERSIONFLAGS( p_box->data.p_rmdr );
1980
1981     MP4_GET4BYTES( p_box->data.p_rmdr->i_rate );
1982
1983 #ifdef MP4_VERBOSE
1984     msg_Dbg( p_stream,
1985              "read box: \"rmdr\" rate:%d",
1986              p_box->data.p_rmdr->i_rate );
1987 #endif
1988     MP4_READBOX_EXIT( 1 );
1989 }
1990
1991 static int MP4_ReadBox_rmqu( stream_t *p_stream, MP4_Box_t *p_box )
1992 {
1993     MP4_READBOX_ENTER( MP4_Box_data_rmqu_t );
1994
1995     MP4_GET4BYTES( p_box->data.p_rmqu->i_quality );
1996
1997 #ifdef MP4_VERBOSE
1998     msg_Dbg( p_stream,
1999              "read box: \"rmqu\" quality:%d",
2000              p_box->data.p_rmqu->i_quality );
2001 #endif
2002     MP4_READBOX_EXIT( 1 );
2003 }
2004
2005 static int MP4_ReadBox_rmvc( stream_t *p_stream, MP4_Box_t *p_box )
2006 {
2007     MP4_READBOX_ENTER( MP4_Box_data_rmvc_t );
2008     MP4_GETVERSIONFLAGS( p_box->data.p_rmvc );
2009
2010     MP4_GETFOURCC( p_box->data.p_rmvc->i_gestaltType );
2011     MP4_GET4BYTES( p_box->data.p_rmvc->i_val1 );
2012     MP4_GET4BYTES( p_box->data.p_rmvc->i_val2 );
2013     MP4_GET2BYTES( p_box->data.p_rmvc->i_checkType );
2014
2015 #ifdef MP4_VERBOSE
2016     msg_Dbg( p_stream,
2017              "read box: \"rmvc\" gestaltType:%4.4s val1:0x%x val2:0x%x checkType:0x%x",
2018              (char*)&p_box->data.p_rmvc->i_gestaltType,
2019              p_box->data.p_rmvc->i_val1,p_box->data.p_rmvc->i_val2,
2020              p_box->data.p_rmvc->i_checkType );
2021 #endif
2022
2023     MP4_READBOX_EXIT( 1 );
2024 }
2025
2026 static int MP4_ReadBox_drms( stream_t *p_stream, MP4_Box_t *p_box )
2027 {
2028     MP4_Box_t *p_drms_box = p_box;
2029
2030     MP4_READBOX_ENTER( uint8_t );
2031
2032     do
2033     {
2034         p_drms_box = p_drms_box->p_father;
2035     } while( p_drms_box && p_drms_box->i_type != FOURCC_drms );
2036
2037     if( p_drms_box && p_drms_box->data.p_sample_soun->p_drms )
2038     {
2039         int i_ret;
2040         if( config_GetInt( p_stream, "france" ) )
2041         {
2042             i_ret = -7;
2043         }
2044         else
2045         {
2046             i_ret= drms_init( p_drms_box->data.p_sample_soun->p_drms,
2047                                p_box->i_type, p_peek, i_read );
2048         }
2049         if( i_ret )
2050         {
2051             char *psz_error;
2052
2053             switch( i_ret )
2054             {
2055                 case -1: psz_error = "unimplemented"; break;
2056                 case -2: psz_error = "invalid argument"; break;
2057                 case -3: psz_error = "could not get system key"; break;
2058                 case -4: psz_error = "could not get SCI data"; break;
2059                 case -5: psz_error = "no user key found in SCI data"; break;
2060                 case -6: psz_error = "invalid user key"; break;
2061                 case -7: psz_error = "you live in France"; break;
2062                 default: psz_error = "unknown error"; break;
2063             }
2064
2065             msg_Err( p_stream, "drms_init(%4.4s) failed (%s)",
2066                      (char *)&p_box->i_type, psz_error );
2067
2068             drms_free( p_drms_box->data.p_sample_soun->p_drms );
2069             p_drms_box->data.p_sample_soun->p_drms = NULL;
2070         }
2071     }
2072
2073     MP4_READBOX_EXIT( 1 );
2074 }
2075
2076 static int MP4_ReadBox_0xa9xxx( stream_t *p_stream, MP4_Box_t *p_box )
2077 {
2078     uint16_t i_length, i_dummy;
2079
2080     MP4_READBOX_ENTER( MP4_Box_data_0xa9xxx_t );
2081
2082     p_box->data.p_0xa9xxx->psz_text = NULL;
2083
2084     MP4_GET2BYTES( i_length );
2085     MP4_GET2BYTES( i_dummy );
2086
2087     if( i_length > 0 )
2088     {
2089         if( i_length > i_read ) i_length = i_read;
2090
2091         p_box->data.p_0xa9xxx->psz_text = malloc( i_length + 1 );
2092
2093         memcpy( p_box->data.p_0xa9xxx->psz_text,
2094                 p_peek, i_length );
2095         p_box->data.p_0xa9xxx->psz_text[i_length] = '\0';
2096
2097 #ifdef MP4_VERBOSE
2098         msg_Dbg( p_stream,
2099                  "read box: \"%4.4s\" text=`%s'",
2100                  (char*)&p_box->i_type,
2101                  p_box->data.p_0xa9xxx->psz_text );
2102 #endif
2103     }
2104
2105     MP4_READBOX_EXIT( 1 );
2106 }
2107 static void MP4_FreeBox_0xa9xxx( MP4_Box_t *p_box )
2108 {
2109     FREENULL( p_box->data.p_0xa9xxx->psz_text );
2110 }
2111
2112 /* For generic */
2113 static int MP4_ReadBox_default( stream_t *p_stream, MP4_Box_t *p_box )
2114 {
2115     if( !p_box->p_father )
2116     {
2117         goto unknown;
2118     }
2119     if( p_box->p_father->i_type == FOURCC_stsd )
2120     {
2121         MP4_Box_t *p_mdia = MP4_BoxGet( p_box, "../../../.." );
2122         MP4_Box_t *p_hdlr;
2123
2124         if( p_mdia == NULL || p_mdia->i_type != FOURCC_mdia ||
2125             (p_hdlr = MP4_BoxGet( p_mdia, "hdlr" )) == NULL )
2126         {
2127             goto unknown;
2128         }
2129         switch( p_hdlr->data.p_hdlr->i_handler_type )
2130         {
2131             case FOURCC_soun:
2132                 return MP4_ReadBox_sample_soun( p_stream, p_box );
2133             case FOURCC_vide:
2134                 return MP4_ReadBox_sample_vide( p_stream, p_box );
2135             case FOURCC_text:
2136                 return MP4_ReadBox_sample_text( p_stream, p_box );
2137             case FOURCC_tx3g:
2138                 return MP4_ReadBox_sample_tx3g( p_stream, p_box );
2139             default:
2140                 msg_Warn( p_stream,
2141                           "unknown handler type in stsd (uncompletetly loaded)" );
2142                 return 1;
2143         }
2144     }
2145
2146 unknown:
2147     msg_Warn( p_stream,
2148               "unknown box type %4.4s (uncompletetly loaded)",
2149               (char*)&p_box->i_type );
2150
2151     return 1;
2152 }
2153
2154 /**** ------------------------------------------------------------------- ****/
2155 /****                   "Higher level" Functions                          ****/
2156 /**** ------------------------------------------------------------------- ****/
2157
2158 static struct
2159 {
2160     uint32_t i_type;
2161     int  (*MP4_ReadBox_function )( stream_t *p_stream, MP4_Box_t *p_box );
2162     void (*MP4_FreeBox_function )( MP4_Box_t *p_box );
2163 } MP4_Box_Function [] =
2164 {
2165     /* Containers */
2166     { FOURCC_moov,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2167     { FOURCC_trak,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2168     { FOURCC_mdia,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2169     { FOURCC_moof,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2170     { FOURCC_minf,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2171     { FOURCC_stbl,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2172     { FOURCC_dinf,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2173     { FOURCC_edts,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2174     { FOURCC_udta,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2175     { FOURCC_nmhd,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2176     { FOURCC_hnti,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2177     { FOURCC_rmra,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2178     { FOURCC_rmda,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2179     { FOURCC_tref,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2180     { FOURCC_gmhd,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2181     { FOURCC_wave,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2182
2183     /* specific box */
2184     { FOURCC_ftyp,  MP4_ReadBox_ftyp,       MP4_FreeBox_ftyp },
2185     { FOURCC_cmov,  MP4_ReadBox_cmov,       MP4_FreeBox_Common },
2186     { FOURCC_mvhd,  MP4_ReadBox_mvhd,       MP4_FreeBox_Common },
2187     { FOURCC_tkhd,  MP4_ReadBox_tkhd,       MP4_FreeBox_Common },
2188     { FOURCC_mdhd,  MP4_ReadBox_mdhd,       MP4_FreeBox_Common },
2189     { FOURCC_hdlr,  MP4_ReadBox_hdlr,       MP4_FreeBox_hdlr },
2190     { FOURCC_vmhd,  MP4_ReadBox_vmhd,       MP4_FreeBox_Common },
2191     { FOURCC_smhd,  MP4_ReadBox_smhd,       MP4_FreeBox_Common },
2192     { FOURCC_hmhd,  MP4_ReadBox_hmhd,       MP4_FreeBox_Common },
2193     { FOURCC_url,   MP4_ReadBox_url,        MP4_FreeBox_url },
2194     { FOURCC_urn,   MP4_ReadBox_urn,        MP4_FreeBox_urn },
2195     { FOURCC_dref,  MP4_ReadBox_dref,       MP4_FreeBox_Common },
2196     { FOURCC_stts,  MP4_ReadBox_stts,       MP4_FreeBox_stts },
2197     { FOURCC_ctts,  MP4_ReadBox_ctts,       MP4_FreeBox_ctts },
2198     { FOURCC_stsd,  MP4_ReadBox_stsd,       MP4_FreeBox_Common },
2199     { FOURCC_stsz,  MP4_ReadBox_stsz,       MP4_FreeBox_stsz },
2200     { FOURCC_stsc,  MP4_ReadBox_stsc,       MP4_FreeBox_stsc },
2201     { FOURCC_stco,  MP4_ReadBox_stco_co64,  MP4_FreeBox_stco_co64 },
2202     { FOURCC_co64,  MP4_ReadBox_stco_co64,  MP4_FreeBox_stco_co64 },
2203     { FOURCC_stss,  MP4_ReadBox_stss,       MP4_FreeBox_stss },
2204     { FOURCC_stsh,  MP4_ReadBox_stsh,       MP4_FreeBox_stsh },
2205     { FOURCC_stdp,  MP4_ReadBox_stdp,       MP4_FreeBox_stdp },
2206     { FOURCC_padb,  MP4_ReadBox_padb,       MP4_FreeBox_padb },
2207     { FOURCC_elst,  MP4_ReadBox_elst,       MP4_FreeBox_elst },
2208     { FOURCC_cprt,  MP4_ReadBox_cprt,       MP4_FreeBox_cprt },
2209     { FOURCC_esds,  MP4_ReadBox_esds,       MP4_FreeBox_esds },
2210     { FOURCC_dcom,  MP4_ReadBox_dcom,       MP4_FreeBox_Common },
2211     { FOURCC_cmvd,  MP4_ReadBox_cmvd,       MP4_FreeBox_cmvd },
2212     { FOURCC_avcC,  MP4_ReadBox_avcC,       MP4_FreeBox_avcC },
2213
2214     /* Nothing to do with this box */
2215     { FOURCC_mdat,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
2216     { FOURCC_skip,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
2217     { FOURCC_free,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
2218     { FOURCC_wide,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
2219
2220     /* for codecs */
2221     { FOURCC_soun,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2222     { FOURCC_ms02,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2223     { FOURCC_ms11,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2224     { FOURCC_ms55,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2225     { FOURCC__mp3,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2226     { FOURCC_mp4a,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2227     { FOURCC_twos,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2228     { FOURCC_sowt,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2229     { FOURCC_QDMC,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2230     { FOURCC_QDM2,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2231     { FOURCC_ima4,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2232     { FOURCC_IMA4,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2233     { FOURCC_dvi,   MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2234     { FOURCC_alaw,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2235     { FOURCC_ulaw,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2236     { FOURCC_raw,   MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2237     { FOURCC_MAC3,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2238     { FOURCC_MAC6,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2239     { FOURCC_Qclp,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2240     { FOURCC_samr,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2241     { FOURCC_sawb,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2242     { FOURCC_OggS,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2243     { FOURCC_alac,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2244
2245     { FOURCC_vide,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2246     { FOURCC_mp4v,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2247     { FOURCC_SVQ1,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2248     { FOURCC_SVQ3,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2249     { FOURCC_ZyGo,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2250     { FOURCC_DIVX,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2251     { FOURCC_XVID,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2252     { FOURCC_h263,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2253     { FOURCC_s263,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2254     { FOURCC_cvid,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2255     { FOURCC_3IV1,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2256     { FOURCC_3iv1,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2257     { FOURCC_3IV2,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2258     { FOURCC_3iv2,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2259     { FOURCC_3IVD,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2260     { FOURCC_3ivd,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2261     { FOURCC_3VID,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2262     { FOURCC_3vid,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2263     { FOURCC_mjpa,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2264     { FOURCC_mjpb,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2265     { FOURCC_qdrw,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2266     { FOURCC_mp2v,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2267     { FOURCC_hdv2,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2268
2269     { FOURCC_mjqt,  MP4_ReadBox_default,        NULL }, /* found in mjpa/b */
2270     { FOURCC_mjht,  MP4_ReadBox_default,        NULL },
2271
2272     { FOURCC_dvc,   MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2273     { FOURCC_dvp,   MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2274     { FOURCC_VP31,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2275     { FOURCC_vp31,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2276     { FOURCC_h264,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2277
2278     { FOURCC_jpeg,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2279     { FOURCC_avc1,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2280
2281     { FOURCC_mp4s,  MP4_ReadBox_sample_mp4s,    MP4_FreeBox_Common },
2282
2283     /* XXX there is 2 box where we could find this entry stbl and tref*/
2284     { FOURCC_hint,  MP4_ReadBox_default,        MP4_FreeBox_Common },
2285
2286     /* found in tref box */
2287     { FOURCC_dpnd,  MP4_ReadBox_default,   NULL },
2288     { FOURCC_ipir,  MP4_ReadBox_default,   NULL },
2289     { FOURCC_mpod,  MP4_ReadBox_default,   NULL },
2290
2291     /* found in hnti */
2292     { FOURCC_rtp,   MP4_ReadBox_default,   NULL },
2293
2294     /* found in rmra */
2295     { FOURCC_rdrf,  MP4_ReadBox_rdrf,           MP4_FreeBox_rdrf   },
2296     { FOURCC_rmdr,  MP4_ReadBox_rmdr,           MP4_FreeBox_Common },
2297     { FOURCC_rmqu,  MP4_ReadBox_rmqu,           MP4_FreeBox_Common },
2298     { FOURCC_rmvc,  MP4_ReadBox_rmvc,           MP4_FreeBox_Common },
2299
2300     { FOURCC_drms,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
2301     { FOURCC_sinf,  MP4_ReadBoxContainer,       MP4_FreeBox_Common },
2302     { FOURCC_schi,  MP4_ReadBoxContainer,       MP4_FreeBox_Common },
2303     { FOURCC_user,  MP4_ReadBox_drms,           MP4_FreeBox_Common },
2304     { FOURCC_key,   MP4_ReadBox_drms,           MP4_FreeBox_Common },
2305     { FOURCC_iviv,  MP4_ReadBox_drms,           MP4_FreeBox_Common },
2306     { FOURCC_name,  MP4_ReadBox_drms,           MP4_FreeBox_Common },
2307     { FOURCC_priv,  MP4_ReadBox_drms,           MP4_FreeBox_Common },
2308
2309     /* found in udta */
2310     { FOURCC_0xa9nam,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2311     { FOURCC_0xa9aut,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2312     { FOURCC_0xa9cpy,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2313     { FOURCC_0xa9swr,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2314     { FOURCC_0xa9inf,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2315     { FOURCC_0xa9ART,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2316     { FOURCC_0xa9dir,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2317     { FOURCC_0xa9cmt,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2318     { FOURCC_0xa9req,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2319     { FOURCC_0xa9day,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2320     { FOURCC_0xa9des,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2321     { FOURCC_0xa9fmt,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2322     { FOURCC_0xa9prd,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2323     { FOURCC_0xa9prf,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2324     { FOURCC_0xa9src,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2325     { FOURCC_0xa9alb,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2326     { FOURCC_0xa9dis,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2327     { FOURCC_0xa9enc,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2328     { FOURCC_0xa9gen,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2329     { FOURCC_0xa9trk,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2330     { FOURCC_0xa9dsa,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2331     { FOURCC_0xa9hst,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2332     { FOURCC_0xa9url,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2333     { FOURCC_0xa9ope,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2334     { FOURCC_0xa9com,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2335
2336     /* Last entry */
2337     { 0,             MP4_ReadBox_default,       NULL }
2338 };
2339
2340
2341
2342 /*****************************************************************************
2343  * MP4_ReadBox : parse the actual box and the children
2344  *  XXX : Do not go to the next box
2345  *****************************************************************************/
2346 static MP4_Box_t *MP4_ReadBox( stream_t *p_stream, MP4_Box_t *p_father )
2347 {
2348     MP4_Box_t    *p_box = malloc( sizeof( MP4_Box_t ) );
2349     unsigned int i_index;
2350
2351     if( !MP4_ReadBoxCommon( p_stream, p_box ) )
2352     {
2353         msg_Warn( p_stream, "cannot read one box" );
2354         free( p_box );
2355         return NULL;
2356     }
2357     if( !p_box->i_size )
2358     {
2359         msg_Dbg( p_stream, "found an empty box (null size)" );
2360         free( p_box );
2361         return NULL;
2362     }
2363     p_box->p_father = p_father;
2364
2365     /* Now search function to call */
2366     for( i_index = 0; ; i_index++ )
2367     {
2368         if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
2369             ( MP4_Box_Function[i_index].i_type == 0 ) )
2370         {
2371             break;
2372         }
2373     }
2374
2375     if( !(MP4_Box_Function[i_index].MP4_ReadBox_function)( p_stream, p_box ) )
2376     {
2377         free( p_box );
2378         return NULL;
2379     }
2380
2381     return p_box;
2382 }
2383
2384 /*****************************************************************************
2385  * MP4_FreeBox : free memory after read with MP4_ReadBox and all
2386  * the children
2387  *****************************************************************************/
2388 void MP4_BoxFree( stream_t *s, MP4_Box_t *p_box )
2389 {
2390     unsigned int i_index;
2391     MP4_Box_t    *p_child;
2392
2393     if( !p_box )
2394     {
2395         return; /* hehe */
2396     }
2397
2398     for( p_child = p_box->p_first; p_child != NULL; )
2399     {
2400         MP4_Box_t *p_next;
2401
2402         p_next = p_child->p_next;
2403         MP4_BoxFree( s, p_child );
2404         p_child = p_next;
2405     }
2406
2407     /* Now search function to call */
2408     if( p_box->data.p_data )
2409     {
2410         for( i_index = 0; ; i_index++ )
2411         {
2412             if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
2413                 ( MP4_Box_Function[i_index].i_type == 0 ) )
2414             {
2415                 break;
2416             }
2417         }
2418         if( MP4_Box_Function[i_index].MP4_FreeBox_function == NULL )
2419         {
2420             /* Should not happen */
2421             msg_Warn( s,
2422                       "cannot free box %4.4s, type unknown",
2423                       (char*)&p_box->i_type );
2424         }
2425         else
2426         {
2427             MP4_Box_Function[i_index].MP4_FreeBox_function( p_box );
2428         }
2429
2430         free( p_box->data.p_data );
2431     }
2432
2433     free( p_box );
2434 }
2435
2436 /*****************************************************************************
2437  * MP4_BoxGetRoot : Parse the entire file, and create all boxes in memory
2438  *****************************************************************************
2439  *  The first box is a virtual box "root" and is the father for all first
2440  *  level boxes for the file, a sort of virtual contener
2441  *****************************************************************************/
2442 MP4_Box_t *MP4_BoxGetRoot( stream_t *s )
2443 {
2444     MP4_Box_t *p_root;
2445     stream_t *p_stream;
2446     int i_result;
2447
2448     p_root = malloc( sizeof( MP4_Box_t ) );
2449     p_root->i_pos = 0;
2450     p_root->i_type = VLC_FOURCC( 'r', 'o', 'o', 't' );
2451     p_root->i_shortsize = 1;
2452     p_root->i_size = stream_Size( s );
2453     CreateUUID( &p_root->i_uuid, p_root->i_type );
2454
2455     p_root->data.p_data = NULL;
2456     p_root->p_father = NULL;
2457     p_root->p_first  = NULL;
2458     p_root->p_last  = NULL;
2459     p_root->p_next   = NULL;
2460
2461     p_stream = s;
2462
2463     i_result = MP4_ReadBoxContainerRaw( p_stream, p_root );
2464
2465     if( i_result )
2466     {
2467         MP4_Box_t *p_child;
2468         MP4_Box_t *p_moov;
2469         MP4_Box_t *p_cmov;
2470
2471         /* check if there is a cmov, if so replace
2472           compressed moov by  uncompressed one */
2473         if( ( ( p_moov = MP4_BoxGet( p_root, "moov" ) ) &&
2474               ( p_cmov = MP4_BoxGet( p_root, "moov/cmov" ) ) ) ||
2475             ( ( p_moov = MP4_BoxGet( p_root, "foov" ) ) &&
2476               ( p_cmov = MP4_BoxGet( p_root, "foov/cmov" ) ) ) )
2477         {
2478             /* rename the compressed moov as a box to skip */
2479             p_moov->i_type = FOURCC_skip;
2480
2481             /* get uncompressed p_moov */
2482             p_moov = p_cmov->data.p_cmov->p_moov;
2483             p_cmov->data.p_cmov->p_moov = NULL;
2484
2485             /* make p_root father of this new moov */
2486             p_moov->p_father = p_root;
2487
2488             /* insert this new moov box as first child of p_root */
2489             p_moov->p_next = p_child = p_root->p_first;
2490             p_root->p_first = p_moov;
2491         }
2492     }
2493
2494     return p_root;
2495 }
2496
2497
2498 static void __MP4_BoxDumpStructure( stream_t *s,
2499                                     MP4_Box_t *p_box, unsigned int i_level )
2500 {
2501     MP4_Box_t *p_child;
2502
2503     if( !i_level )
2504     {
2505         msg_Dbg( s, "dumping root Box \"%4.4s\"",
2506                           (char*)&p_box->i_type );
2507     }
2508     else
2509     {
2510         char str[512];
2511         unsigned int i;
2512         memset( str, (uint8_t)' ', 512 );
2513         for( i = 0; i < i_level; i++ )
2514         {
2515             str[i*5] = '|';
2516         }
2517         sprintf( str + i_level * 5, "+ %4.4s size %d",
2518                       (char*)&p_box->i_type,
2519                       (uint32_t)p_box->i_size );
2520
2521         msg_Dbg( s, "%s", str );
2522     }
2523     p_child = p_box->p_first;
2524     while( p_child )
2525     {
2526         __MP4_BoxDumpStructure( s, p_child, i_level + 1 );
2527         p_child = p_child->p_next;
2528     }
2529 }
2530
2531 void MP4_BoxDumpStructure( stream_t *s, MP4_Box_t *p_box )
2532 {
2533     __MP4_BoxDumpStructure( s, p_box, 0 );
2534 }
2535
2536
2537
2538 /*****************************************************************************
2539  *****************************************************************************
2540  **
2541  **  High level methods to acces an MP4 file
2542  **
2543  *****************************************************************************
2544  *****************************************************************************/
2545 static void __get_token( char **ppsz_path, char **ppsz_token, int *pi_number )
2546 {
2547     size_t i_len ;
2548     if( !*ppsz_path[0] )
2549     {
2550         *ppsz_token = NULL;
2551         *pi_number = 0;
2552         return;
2553     }
2554     i_len = 0;
2555     while(  (*ppsz_path)[i_len] &&
2556             (*ppsz_path)[i_len] != '/' && (*ppsz_path)[i_len] != '[' )
2557     {
2558         i_len++;
2559     }
2560     if( !i_len && **ppsz_path == '/' )
2561     {
2562         i_len = 1;
2563     }
2564     *ppsz_token = malloc( i_len + 1 );
2565
2566     memcpy( *ppsz_token, *ppsz_path, i_len );
2567
2568     (*ppsz_token)[i_len] = '\0';
2569
2570     *ppsz_path += i_len;
2571
2572     if( **ppsz_path == '[' )
2573     {
2574         (*ppsz_path)++;
2575         *pi_number = strtol( *ppsz_path, NULL, 10 );
2576         while( **ppsz_path && **ppsz_path != ']' )
2577         {
2578             (*ppsz_path)++;
2579         }
2580         if( **ppsz_path == ']' )
2581         {
2582             (*ppsz_path)++;
2583         }
2584     }
2585     else
2586     {
2587         *pi_number = 0;
2588     }
2589     while( **ppsz_path == '/' )
2590     {
2591         (*ppsz_path)++;
2592     }
2593 }
2594
2595 static void __MP4_BoxGet( MP4_Box_t **pp_result,
2596                           MP4_Box_t *p_box, char *psz_fmt, va_list args)
2597 {
2598     char    *psz_path;
2599
2600     if( !p_box )
2601     {
2602         *pp_result = NULL;
2603         return;
2604     }
2605
2606     vasprintf( &psz_path, psz_fmt, args );
2607
2608     if( !psz_path || !psz_path[0] )
2609     {
2610         FREENULL( psz_path );
2611         *pp_result = NULL;
2612         return;
2613     }
2614
2615 //    fprintf( stderr, "path:'%s'\n", psz_path );
2616     psz_fmt = psz_path; /* keep this pointer, as it need to be unallocated */
2617     for( ; ; )
2618     {
2619         char *psz_token;
2620         int i_number;
2621
2622         __get_token( &psz_path, &psz_token, &i_number );
2623 //        fprintf( stderr, "path:'%s', token:'%s' n:%d\n",
2624 //                 psz_path,psz_token,i_number );
2625         if( !psz_token )
2626         {
2627             FREENULL( psz_token );
2628             free( psz_fmt );
2629             *pp_result = p_box;
2630             return;
2631         }
2632         else
2633         if( !strcmp( psz_token, "/" ) )
2634         {
2635             /* Find root box */
2636             while( p_box && p_box->i_type != VLC_FOURCC( 'r', 'o', 'o', 't' ) )
2637             {
2638                 p_box = p_box->p_father;
2639             }
2640             if( !p_box )
2641             {
2642                 free( psz_token );
2643                 free( psz_fmt );
2644                 *pp_result = NULL;
2645                 return;
2646             }
2647         }
2648         else
2649         if( !strcmp( psz_token, "." ) )
2650         {
2651             /* Do nothing */
2652         }
2653         else
2654         if( !strcmp( psz_token, ".." ) )
2655         {
2656             p_box = p_box->p_father;
2657             if( !p_box )
2658             {
2659                 free( psz_token );
2660                 free( psz_fmt );
2661                 *pp_result = NULL;
2662                 return;
2663             }
2664         }
2665         else
2666         if( strlen( psz_token ) == 4 )
2667         {
2668             uint32_t i_fourcc;
2669             i_fourcc = VLC_FOURCC( psz_token[0], psz_token[1],
2670                                    psz_token[2], psz_token[3] );
2671             p_box = p_box->p_first;
2672             for( ; ; )
2673             {
2674                 if( !p_box )
2675                 {
2676                     free( psz_token );
2677                     free( psz_fmt );
2678                     *pp_result = NULL;
2679                     return;
2680                 }
2681                 if( p_box->i_type == i_fourcc )
2682                 {
2683                     if( !i_number )
2684                     {
2685                         break;
2686                     }
2687                     i_number--;
2688                 }
2689                 p_box = p_box->p_next;
2690             }
2691         }
2692         else
2693         if( strlen( psz_token ) == 0 )
2694         {
2695             p_box = p_box->p_first;
2696             for( ; ; )
2697             {
2698                 if( !p_box )
2699                 {
2700                     free( psz_token );
2701                     free( psz_fmt );
2702                     *pp_result = NULL;
2703                     return;
2704                 }
2705                 if( !i_number )
2706                 {
2707                     break;
2708                 }
2709                 i_number--;
2710                 p_box = p_box->p_next;
2711             }
2712         }
2713         else
2714         {
2715 //            fprintf( stderr, "Argg malformed token \"%s\"",psz_token );
2716             FREENULL( psz_token );
2717             free( psz_fmt );
2718             *pp_result = NULL;
2719             return;
2720         }
2721
2722         free( psz_token );
2723     }
2724 }
2725
2726 /*****************************************************************************
2727  * MP4_BoxGet: find a box given a path relative to p_box
2728  *****************************************************************************
2729  * Path Format: . .. / as usual
2730  *              [number] to specifie box number ex: trak[12]
2731  *
2732  * ex: /moov/trak[12]
2733  *     ../mdia
2734  *****************************************************************************/
2735 MP4_Box_t *MP4_BoxGet( MP4_Box_t *p_box, char *psz_fmt, ... )
2736 {
2737     va_list args;
2738     MP4_Box_t *p_result;
2739
2740     va_start( args, psz_fmt );
2741     __MP4_BoxGet( &p_result, p_box, psz_fmt, args );
2742     va_end( args );
2743
2744     return( p_result );
2745 }
2746
2747 /*****************************************************************************
2748  * MP4_BoxCount: count box given a path relative to p_box
2749  *****************************************************************************
2750  * Path Format: . .. / as usual
2751  *              [number] to specifie box number ex: trak[12]
2752  *
2753  * ex: /moov/trak[12]
2754  *     ../mdia
2755  *****************************************************************************/
2756 int MP4_BoxCount( MP4_Box_t *p_box, char *psz_fmt, ... )
2757 {
2758     va_list args;
2759     int     i_count;
2760     MP4_Box_t *p_result, *p_next;
2761
2762     va_start( args, psz_fmt );
2763     __MP4_BoxGet( &p_result, p_box, psz_fmt, args );
2764     va_end( args );
2765     if( !p_result )
2766     {
2767         return( 0 );
2768     }
2769
2770     i_count = 1;
2771     for( p_next = p_result->p_next; p_next != NULL; p_next = p_next->p_next)
2772     {
2773         if( p_next->i_type == p_result->i_type)
2774         {
2775             i_count++;
2776         }
2777     }
2778     return( i_count );
2779 }