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