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