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