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