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