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