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