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