* mp4 : use same endian for fourcc than one used in vlc (video.h if I'm
[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.3 2002/07/21 18:47:22 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_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 #ifdef MP4_VERBOSE
1212     msg_Dbg( p_stream->p_input, "Read Box: \"soun\" in stsd channel %d sample size %d sampl rate %f",
1213                       p_box->data.p_sample_soun->i_channelcount,
1214                       p_box->data.p_sample_soun->i_samplesize,
1215                       (float)p_box->data.p_sample_soun->i_sampleratehi + 
1216                     (float)p_box->data.p_sample_soun->i_sampleratelo / 65536 );
1217
1218 #endif
1219     MP4_READBOX_EXIT( 1 );
1220 }
1221
1222 int MP4_ReadBox_sample_mp4a( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1223 {
1224     int i;    
1225
1226     MP4_READBOX_ENTER( MP4_Box_data_sample_mp4a_t );
1227     
1228     for( i = 0; i < 6 ; i++ )
1229     {
1230         MP4_GET1BYTE( p_box->data.p_sample_mp4a->i_reserved1[i] );
1231     }
1232
1233     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_data_reference_index );
1234     
1235     for( i = 0; i < 2 ; i++ )
1236     {
1237         MP4_GET4BYTES( p_box->data.p_sample_mp4a->i_reserved2[i] );
1238     }
1239    
1240     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_channelcount );
1241     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_samplesize );
1242     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_predefined );
1243     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_reserved3 );
1244     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_sampleratehi );
1245     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_sampleratelo );
1246     
1247     MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 28 );
1248     MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds */
1249
1250 #ifdef MP4_VERBOSE
1251     msg_Dbg( p_stream->p_input, "Read Box: \"mp4a\" in stsd channel %d sample size %d sampl rate %f",
1252                       p_box->data.p_sample_mp4a->i_channelcount,
1253                       p_box->data.p_sample_mp4a->i_samplesize,
1254                       (float)p_box->data.p_sample_mp4a->i_sampleratehi + 
1255                         (float)p_box->data.p_sample_mp4a->i_sampleratelo / 65536 );
1256
1257 #endif
1258     MP4_READBOX_EXIT( 1 );
1259 }
1260
1261 int MP4_ReadBox_sample_vide( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1262 {
1263     int i;    
1264
1265     MP4_READBOX_ENTER( MP4_Box_data_sample_vide_t );
1266
1267     for( i = 0; i < 6 ; i++ )
1268     {
1269         MP4_GET1BYTE( p_box->data.p_sample_vide->i_reserved1[i] );
1270     }
1271
1272     MP4_GET2BYTES( p_box->data.p_sample_vide->i_data_reference_index );
1273
1274     MP4_GET2BYTES( p_box->data.p_sample_vide->i_predefined1 );
1275     MP4_GET2BYTES( p_box->data.p_sample_vide->i_reserved2 );
1276
1277     for( i = 0; i < 3 ; i++ )
1278     {
1279         MP4_GET4BYTES( p_box->data.p_sample_vide->i_predefined2[i] );
1280     }
1281
1282     MP4_GET2BYTES( p_box->data.p_sample_vide->i_width );
1283     MP4_GET2BYTES( p_box->data.p_sample_vide->i_height );
1284     
1285     MP4_GET4BYTES( p_box->data.p_sample_vide->i_horizresolution );
1286     MP4_GET4BYTES( p_box->data.p_sample_vide->i_vertresolution );
1287
1288     MP4_GET4BYTES( p_box->data.p_sample_vide->i_reserved3 );
1289     MP4_GET2BYTES( p_box->data.p_sample_vide->i_predefined3 );
1290
1291     memcpy( &p_box->data.p_sample_vide->i_compressorname, p_peek, 32 );
1292     p_peek += 32; i_read -= 32;
1293
1294     MP4_GET2BYTES( p_box->data.p_sample_vide->i_depth );
1295     MP4_GET2BYTES( p_box->data.p_sample_vide->i_predefined4 );
1296     
1297     MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 78);
1298     MP4_ReadBoxContainerRaw( p_stream, p_box );
1299    
1300 #ifdef MP4_VERBOSE
1301     msg_Dbg( p_stream->p_input, "Read Box: \"vide\" in stsd %dx%d depth %d",
1302                       p_box->data.p_sample_vide->i_width,
1303                       p_box->data.p_sample_vide->i_height,
1304                       p_box->data.p_sample_vide->i_depth );
1305
1306 #endif
1307     MP4_READBOX_EXIT( 1 );
1308 }
1309
1310 #if 0
1311 int MP4_ReadBox_sample_mp4v( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1312 {
1313     int i;    
1314
1315     MP4_READBOX_ENTER( MP4_Box_data_sample_mp4v_t );
1316     
1317     for( i = 0; i < 6 ; i++ )
1318     {
1319         MP4_GET1BYTE( p_box->data.p_sample_mp4v->i_reserved1[i] );
1320     }
1321
1322     MP4_GET2BYTES( p_box->data.p_sample_mp4v->i_data_reference_index );
1323
1324     MP4_GET2BYTES( p_box->data.p_sample_mp4v->i_predefined1 );
1325     MP4_GET2BYTES( p_box->data.p_sample_mp4v->i_reserved2 );
1326
1327     for( i = 0; i < 3 ; i++ )
1328     {
1329         MP4_GET4BYTES( p_box->data.p_sample_mp4v->i_predefined2[i] );
1330     }
1331
1332     MP4_GET2BYTES( p_box->data.p_sample_mp4v->i_width );
1333     MP4_GET2BYTES( p_box->data.p_sample_mp4v->i_height );
1334     
1335     MP4_GET4BYTES( p_box->data.p_sample_mp4v->i_horizresolution );
1336     MP4_GET4BYTES( p_box->data.p_sample_mp4v->i_vertresolution );
1337
1338     MP4_GET4BYTES( p_box->data.p_sample_mp4v->i_reserved3 );
1339     MP4_GET2BYTES( p_box->data.p_sample_mp4v->i_predefined3 );
1340
1341     /* This is a pascal string, padded to 32 bytes */
1342     memcpy( &p_box->data.p_sample_mp4v->i_compressorname, p_peek+1, 31 );
1343     p_box->data.p_sample_mp4v->i_compressorname[*p_peek] = 0;
1344     p_peek += 32; i_read -= 32;
1345
1346     MP4_GET2BYTES( p_box->data.p_sample_mp4v->i_depth );
1347     MP4_GET2BYTES( p_box->data.p_sample_mp4v->i_predefined4 );
1348
1349
1350     MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 78);
1351     MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds */
1352     
1353 #ifdef MP4_VERBOSE
1354     msg_Dbg( p_stream->p_input, "Read Box: \"mp4v\" in stsd %dx%d depth %d compressor %s",
1355                       p_box->data.p_sample_mp4v->i_width,
1356                       p_box->data.p_sample_mp4v->i_height,
1357                       p_box->data.p_sample_mp4v->i_depth,
1358                       p_box->data.p_sample_mp4v->i_compressorname );
1359 #endif
1360     MP4_READBOX_EXIT( 1 );
1361 }
1362 #endif 
1363
1364
1365 int MP4_ReadBox_stsd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1366 {
1367
1368     MP4_READBOX_ENTER( MP4_Box_data_stsd_t );
1369
1370     MP4_GETVERSIONFLAGS( p_box->data.p_stsd );
1371
1372     MP4_GET4BYTES( p_box->data.p_stsd->i_entry_count );
1373
1374     MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 8 ); 
1375
1376     MP4_ReadBoxContainerRaw( p_stream, p_box );
1377
1378 #ifdef MP4_VERBOSE
1379     msg_Dbg( p_stream->p_input, "Read Box: \"stsd\" entry-count %d",
1380                       p_box->data.p_stsd->i_entry_count );
1381
1382 #endif
1383     MP4_READBOX_EXIT( 1 );
1384 }
1385
1386
1387 int MP4_ReadBox_stsz( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1388 {
1389     int i;
1390
1391     MP4_READBOX_ENTER( MP4_Box_data_stsz_t );
1392     
1393     MP4_GETVERSIONFLAGS( p_box->data.p_stsz );
1394     
1395     MP4_GET4BYTES( p_box->data.p_stsz->i_sample_size );
1396
1397     MP4_GET4BYTES( p_box->data.p_stsz->i_sample_count );
1398
1399     p_box->data.p_stsz->i_entry_size = 
1400         calloc( sizeof( u32 ), p_box->data.p_stsz->i_sample_count );
1401     
1402     if( !p_box->data.p_stsz->i_sample_size )
1403     {
1404         for( i=0; (i<p_box->data.p_stsz->i_sample_count)&&(i_read >= 4 ); i++ )
1405         {
1406             MP4_GET4BYTES( p_box->data.p_stsz->i_entry_size[i] );
1407         }
1408     }
1409     
1410     
1411 #ifdef MP4_VERBOSE 
1412     msg_Dbg( p_stream->p_input, "Read Box: \"stsz\" sample-size %d sample-count %d",
1413                       p_box->data.p_stsz->i_sample_size,
1414                       p_box->data.p_stsz->i_sample_count );
1415
1416 #endif
1417     MP4_READBOX_EXIT( 1 );
1418 }
1419
1420 void MP4_FreeBox_stsz( input_thread_t *p_input, MP4_Box_t *p_box )
1421 {
1422     FREE( p_box->data.p_stsz->i_entry_size );
1423 }
1424
1425 int MP4_ReadBox_stsc( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1426 {
1427     int i;
1428     
1429     MP4_READBOX_ENTER( MP4_Box_data_stsc_t );
1430
1431     MP4_GETVERSIONFLAGS( p_box->data.p_stsc );
1432     
1433     MP4_GET4BYTES( p_box->data.p_stsc->i_entry_count );
1434
1435     p_box->data.p_stsc->i_first_chunk = 
1436         calloc( sizeof( u32 ), p_box->data.p_stsc->i_entry_count );
1437     p_box->data.p_stsc->i_samples_per_chunk = 
1438         calloc( sizeof( u32 ), p_box->data.p_stsc->i_entry_count );
1439     p_box->data.p_stsc->i_sample_description_index = 
1440         calloc( sizeof( u32 ), p_box->data.p_stsc->i_entry_count );
1441
1442     for( i = 0; (i < p_box->data.p_stsc->i_entry_count )&&( i_read >= 12 );i++ )
1443     {
1444         MP4_GET4BYTES( p_box->data.p_stsc->i_first_chunk[i] );
1445         MP4_GET4BYTES( p_box->data.p_stsc->i_samples_per_chunk[i] );
1446         MP4_GET4BYTES( p_box->data.p_stsc->i_sample_description_index[i] );
1447     }
1448     
1449     
1450 #ifdef MP4_VERBOSE 
1451     msg_Dbg( p_stream->p_input, "Read Box: \"stsc\" entry-count %d",
1452                       p_box->data.p_stsc->i_entry_count );
1453
1454 #endif
1455     MP4_READBOX_EXIT( 1 );
1456 }
1457
1458 void MP4_FreeBox_stsc( input_thread_t *p_input, MP4_Box_t *p_box )
1459 {
1460     FREE( p_box->data.p_stsc->i_first_chunk );
1461     FREE( p_box->data.p_stsc->i_samples_per_chunk );
1462     FREE( p_box->data.p_stsc->i_sample_description_index );
1463 }
1464
1465 int MP4_ReadBox_stco_co64( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1466 {
1467     int i;
1468     
1469     MP4_READBOX_ENTER( MP4_Box_data_co64_t );
1470
1471     MP4_GETVERSIONFLAGS( p_box->data.p_co64 );
1472
1473     MP4_GET4BYTES( p_box->data.p_co64->i_entry_count );
1474
1475     p_box->data.p_co64->i_chunk_offset = 
1476         calloc( sizeof( u64 ), p_box->data.p_co64->i_entry_count );
1477
1478     for( i = 0; (i < p_box->data.p_co64->i_entry_count )&&( i_read >= 8 ); i++ )
1479     {
1480         if( p_box->i_type == FOURCC_stco )
1481         {
1482             MP4_GET4BYTES( p_box->data.p_co64->i_chunk_offset[i] );
1483         }
1484         else
1485         {
1486             MP4_GET8BYTES( p_box->data.p_co64->i_chunk_offset[i] );
1487         }
1488     }
1489     
1490     
1491 #ifdef MP4_VERBOSE 
1492     msg_Dbg( p_stream->p_input, "Read Box: \"co64\" entry-count %d",
1493                       p_box->data.p_co64->i_entry_count );
1494
1495 #endif
1496     MP4_READBOX_EXIT( 1 );
1497 }
1498
1499 void MP4_FreeBox_stco_co64( input_thread_t *p_input, MP4_Box_t *p_box )
1500 {
1501     FREE( p_box->data.p_co64->i_chunk_offset );
1502 }
1503
1504 int MP4_ReadBox_stss( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1505 {
1506     int i;
1507     
1508     MP4_READBOX_ENTER( MP4_Box_data_stss_t ); 
1509
1510     MP4_GETVERSIONFLAGS( p_box->data.p_stss );
1511
1512     MP4_GET4BYTES( p_box->data.p_stss->i_entry_count );
1513
1514     p_box->data.p_stss->i_sample_number = 
1515         calloc( sizeof( u32 ), p_box->data.p_stss->i_entry_count );
1516
1517     for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 4 ); i++ )
1518     {
1519
1520         MP4_GET4BYTES( p_box->data.p_stss->i_sample_number[i] );
1521     }
1522     
1523     
1524 #ifdef MP4_VERBOSE 
1525     msg_Dbg( p_stream->p_input, "Read Box: \"stss\" entry-count %d",
1526                       p_box->data.p_stss->i_entry_count );
1527
1528 #endif
1529     MP4_READBOX_EXIT( 1 );
1530 }
1531
1532 void MP4_FreeBox_stss( input_thread_t *p_input, MP4_Box_t *p_box )
1533 {
1534     FREE( p_box->data.p_stss->i_sample_number )
1535 }
1536
1537 int MP4_ReadBox_stsh( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1538 {
1539     int i;
1540     
1541     MP4_READBOX_ENTER( MP4_Box_data_stsh_t );
1542
1543     MP4_GETVERSIONFLAGS( p_box->data.p_stsh );
1544
1545
1546     MP4_GET4BYTES( p_box->data.p_stsh->i_entry_count );
1547
1548     p_box->data.p_stsh->i_shadowed_sample_number = 
1549         calloc( sizeof( u32 ), p_box->data.p_stsh->i_entry_count );
1550
1551     p_box->data.p_stsh->i_sync_sample_number = 
1552         calloc( sizeof( u32 ), p_box->data.p_stsh->i_entry_count );
1553
1554
1555     for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 8 ); i++ )
1556     {
1557
1558         MP4_GET4BYTES( p_box->data.p_stsh->i_shadowed_sample_number[i] );
1559         MP4_GET4BYTES( p_box->data.p_stsh->i_sync_sample_number[i] );
1560     }
1561     
1562     
1563 #ifdef MP4_VERBOSE 
1564     msg_Dbg( p_stream->p_input, "Read Box: \"stsh\" entry-count %d",
1565                       p_box->data.p_stsh->i_entry_count );
1566 #endif
1567     MP4_READBOX_EXIT( 1 );
1568 }
1569
1570 void MP4_FreeBox_stsh( input_thread_t *p_input, MP4_Box_t *p_box )
1571 {
1572     FREE( p_box->data.p_stsh->i_shadowed_sample_number )
1573     FREE( p_box->data.p_stsh->i_sync_sample_number )
1574 }
1575
1576
1577 int MP4_ReadBox_stdp( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1578 {
1579     int i;
1580    
1581     MP4_READBOX_ENTER( MP4_Box_data_stdp_t ); 
1582
1583     MP4_GETVERSIONFLAGS( p_box->data.p_stdp );
1584
1585     p_box->data.p_stdp->i_priority = 
1586         calloc( sizeof( u16 ), i_read / 2 );
1587
1588     for( i = 0; i < i_read / 2 ; i++ )
1589     {
1590
1591         MP4_GET2BYTES( p_box->data.p_stdp->i_priority[i] );
1592     }
1593     
1594     
1595 #ifdef MP4_VERBOSE 
1596     msg_Dbg( p_stream->p_input, "Read Box: \"stdp\" entry-count %d",
1597                       i_read / 2 );
1598
1599 #endif
1600     MP4_READBOX_EXIT( 1 );
1601 }
1602
1603 void MP4_FreeBox_stdp( input_thread_t *p_input, MP4_Box_t *p_box )
1604 {
1605     FREE( p_box->data.p_stdp->i_priority )
1606 }
1607
1608 int MP4_ReadBox_padb( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1609 {
1610     int i;
1611     
1612     MP4_READBOX_ENTER( MP4_Box_data_padb_t );
1613
1614     MP4_GETVERSIONFLAGS( p_box->data.p_padb );
1615
1616
1617     MP4_GET4BYTES( p_box->data.p_padb->i_sample_count );
1618
1619     p_box->data.p_padb->i_reserved1 = 
1620         calloc( sizeof( u16 ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
1621     p_box->data.p_padb->i_pad2 = 
1622         calloc( sizeof( u16 ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
1623     p_box->data.p_padb->i_reserved2 = 
1624         calloc( sizeof( u16 ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
1625     p_box->data.p_padb->i_pad1 = 
1626         calloc( sizeof( u16 ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
1627
1628
1629     for( i = 0; i < i_read / 2 ; i++ )
1630     {
1631         p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 7 )&0x01;
1632         p_box->data.p_padb->i_pad2[i] = ( (*p_peek) >> 4 )&0x07;
1633         p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 3 )&0x01;
1634         p_box->data.p_padb->i_pad1[i] = ( (*p_peek) )&0x07;
1635
1636         p_peek += 1; i_read -= 1;
1637     }
1638     
1639     
1640 #ifdef MP4_VERBOSE 
1641     msg_Dbg( p_stream->p_input, "Read Box: \"stdp\" entry-count %d",
1642                       i_read / 2 );
1643
1644 #endif
1645     MP4_READBOX_EXIT( 1 );
1646 }
1647
1648 void MP4_FreeBox_padb( input_thread_t *p_input, MP4_Box_t *p_box )
1649 {
1650     FREE( p_box->data.p_padb->i_reserved1 );
1651     FREE( p_box->data.p_padb->i_pad2 );
1652     FREE( p_box->data.p_padb->i_reserved2 );
1653     FREE( p_box->data.p_padb->i_pad1 );
1654 }
1655
1656 int MP4_ReadBox_elst( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1657 {
1658     int i;
1659     
1660     MP4_READBOX_ENTER( MP4_Box_data_padb_t );
1661
1662     MP4_GETVERSIONFLAGS( p_box->data.p_elst );
1663
1664
1665     MP4_GET4BYTES( p_box->data.p_elst->i_entry_count );
1666
1667     p_box->data.p_elst->i_segment_duration =
1668         calloc( sizeof( u64 ), p_box->data.p_elst->i_entry_count );
1669     p_box->data.p_elst->i_media_time =
1670         calloc( sizeof( u64 ), p_box->data.p_elst->i_entry_count );
1671     p_box->data.p_elst->i_media_rate_integer =
1672         calloc( sizeof( u16 ), p_box->data.p_elst->i_entry_count );
1673     p_box->data.p_elst->i_media_rate_fraction= 
1674         calloc( sizeof( u16 ), p_box->data.p_elst->i_entry_count );
1675
1676
1677     for( i = 0; i < p_box->data.p_elst->i_entry_count; i++ )
1678     {
1679         if( p_box->data.p_elst->i_version == 1 )
1680         {
1681
1682             MP4_GET8BYTES( p_box->data.p_elst->i_segment_duration[i] );
1683
1684             MP4_GET8BYTES( p_box->data.p_elst->i_media_time[i] );
1685         }
1686         else
1687         {
1688
1689             MP4_GET4BYTES( p_box->data.p_elst->i_segment_duration[i] );
1690
1691             MP4_GET4BYTES( p_box->data.p_elst->i_media_time[i] );
1692         }
1693
1694         MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_integer[i] );
1695         MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_fraction[i] );
1696     }
1697     
1698     
1699 #ifdef MP4_VERBOSE 
1700     msg_Dbg( p_stream->p_input, "Read Box: \"elst\" entry-count %d",
1701                       i_read / 2 );
1702
1703 #endif
1704     MP4_READBOX_EXIT( 1 );
1705 }
1706
1707 void MP4_FreeBox_elst( input_thread_t *p_input, MP4_Box_t *p_box )
1708 {
1709     FREE( p_box->data.p_elst->i_segment_duration );
1710     FREE( p_box->data.p_elst->i_media_time );
1711     FREE( p_box->data.p_elst->i_media_rate_integer );
1712     FREE( p_box->data.p_elst->i_media_rate_fraction );
1713 }
1714
1715 int MP4_ReadBox_cprt( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1716 {
1717     int i_language;
1718     int i;
1719     
1720     MP4_READBOX_ENTER( MP4_Box_data_cprt_t );
1721
1722     MP4_GETVERSIONFLAGS( p_box->data.p_cprt );
1723
1724     i_language = GetWBE( p_peek ); 
1725     for( i = 0; i < 3; i++ )
1726     {
1727         p_box->data.p_cprt->i_language[i] = 
1728             ( ( i_language >> ( (2-i)*5 ) )&0x1f ) + 0x60;
1729     }
1730     p_peek += 2; i_read -= 2;  
1731     MP4_GETSTRINGZ( p_box->data.p_cprt->psz_notice );
1732
1733 #ifdef MP4_VERBOSE
1734     msg_Dbg( p_stream->p_input, "Read Box: \"cprt\" language %c%c%c notice %s",
1735                       p_box->data.p_cprt->i_language[0],
1736                       p_box->data.p_cprt->i_language[1],
1737                       p_box->data.p_cprt->i_language[2],
1738                       p_box->data.p_cprt->psz_notice );
1739
1740 #endif
1741     MP4_READBOX_EXIT( 1 );
1742 }
1743
1744 void MP4_FreeBox_cprt( input_thread_t *p_input, MP4_Box_t *p_box )
1745 {
1746     FREE( p_box->data.p_cprt->psz_notice );
1747 }
1748
1749
1750 int MP4_ReadBox_dcom( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1751 {
1752     MP4_READBOX_ENTER( MP4_Box_data_dcom_t );
1753     
1754     MP4_GETFOURCC( p_box->data.p_dcom->i_algorithm );
1755 #ifdef MP4_VERBOSE
1756     msg_Dbg( p_stream->p_input, 
1757              "Read Box: \"dcom\" compression algorithm : %c%c%c%c",
1758                       ( p_box->data.p_dcom->i_algorithm )&0xff,
1759                       ( p_box->data.p_dcom->i_algorithm >> 8 )&0xff,
1760                       ( p_box->data.p_dcom->i_algorithm >> 16 )&0xff,
1761                       ( p_box->data.p_dcom->i_algorithm >> 24 )&0xff );
1762 #endif 
1763     
1764     MP4_READBOX_EXIT( 1 );
1765 }
1766
1767 int MP4_ReadBox_cmvd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1768 {
1769     MP4_READBOX_ENTER( MP4_Box_data_cmvd_t );
1770
1771     
1772     MP4_GET4BYTES( p_box->data.p_cmvd->i_uncompressed_size );
1773
1774     p_box->data.p_cmvd->i_compressed_size = i_read;
1775     
1776     if( !( p_box->data.p_cmvd->p_data = malloc( i_read ) ) )
1777     {
1778         msg_Dbg( p_stream->p_input, "Read Box: \"cmvd\" not enough memory to load data" );
1779         return( 1 );
1780     }
1781     
1782     /* now copy compressed data */
1783     memcpy( p_box->data.p_cmvd->p_data,
1784             p_peek,
1785             i_read);
1786     
1787     p_box->data.p_cmvd->b_compressed = 1;
1788      
1789 #ifdef MP4_VERBOSE
1790     msg_Dbg( p_stream->p_input, "Read Box: \"cmvd\" compressed data size %d",
1791                       p_box->data.p_cmvd->i_compressed_size );
1792 #endif 
1793     
1794     MP4_READBOX_EXIT( 1 );
1795 }
1796 void MP4_FreeBox_cmvd( input_thread_t *p_input, MP4_Box_t *p_box )
1797 {
1798     FREE( p_box->data.p_cmvd->p_data );
1799 }
1800
1801 int MP4_ReadBox_cmov( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1802 {
1803     MP4_Stream_t *p_stream_memory;
1804     MP4_Box_t *p_umov;
1805     
1806     MP4_Box_t *p_dcom;
1807     MP4_Box_t *p_cmvd;
1808     z_stream  z_data;
1809     u8 *p_data;
1810     
1811     int i_result;
1812
1813     if( !( p_box->data.p_cmov = malloc( sizeof( MP4_Box_data_cmov_t ) ) ) )
1814     {
1815         msg_Err( p_stream->p_input, "out of memory" );
1816         return( 0 );
1817     }
1818     memset( p_box->data.p_cmov, 0, sizeof( MP4_Box_data_cmov_t ) );
1819     
1820     if( !( p_box->p_father )||
1821         ( p_box->p_father->i_type != FOURCC_moov ) )
1822     {
1823         msg_Warn( p_stream->p_input, "Read box: \"cmov\" box alone" );
1824         return( 1 );
1825     }
1826
1827     if( !(i_result = MP4_ReadBoxContainer( p_stream, p_box ) ) )
1828     {
1829         return( 0 );
1830     }
1831     
1832     if( !( p_dcom = MP4_FindBox( p_box, FOURCC_dcom ) )||
1833         !( p_cmvd = MP4_FindBox( p_box, FOURCC_cmvd ) )||
1834         !( p_cmvd->data.p_cmvd->p_data ) )
1835     {
1836         msg_Warn( p_stream->p_input, "Read Box: \"cmov\" incomplete" );
1837         return( 1 );
1838     }
1839
1840     if( p_dcom->data.p_dcom->i_algorithm != FOURCC_zlib )
1841     {
1842         msg_Dbg( p_stream->p_input, "Read Box: \"cmov\" compression algorithm : %c%c%c%c not supported",
1843                     ( p_dcom->data.p_dcom->i_algorithm )&0xff,
1844                     ( p_dcom->data.p_dcom->i_algorithm >> 8 )&0xff,
1845                     ( p_dcom->data.p_dcom->i_algorithm >> 16 )&0xff,
1846                     ( p_dcom->data.p_dcom->i_algorithm >> 24 )&0xff );
1847         return( 1 );
1848     }
1849     
1850     /* decompress data */
1851     /* allocate a new buffer */
1852     if( !( p_data = malloc( p_cmvd->data.p_cmvd->i_uncompressed_size ) ) )
1853     {
1854         msg_Err( p_stream->p_input, 
1855                  "Read Box: \"cmov\" not enough memory to uncompress data" );
1856         return( 1 );
1857     }
1858     /* init default structures */
1859     z_data.next_in   = p_cmvd->data.p_cmvd->p_data;
1860     z_data.avail_in  = p_cmvd->data.p_cmvd->i_compressed_size;
1861     z_data.next_out  = p_data;
1862     z_data.avail_out = p_cmvd->data.p_cmvd->i_uncompressed_size;
1863     z_data.zalloc    = (alloc_func)Z_NULL;
1864     z_data.zfree     = (free_func)Z_NULL;
1865     z_data.opaque    = (voidpf)Z_NULL;
1866
1867     /* init zlib */
1868     if( ( i_result = inflateInit( &z_data ) ) != Z_OK )
1869     {
1870         msg_Err( p_stream->p_input, 
1871                  "Read Box: \"cmov\" error while uncompressing data" );
1872         free( p_data );
1873         return( 1 );
1874     }
1875
1876     /* uncompress */
1877     i_result = inflate( &z_data, Z_NO_FLUSH );
1878     if( ( i_result != Z_OK )&&( i_result != Z_STREAM_END ) )
1879     {
1880         msg_Err( p_stream->p_input, 
1881                  "Read Box: \"cmov\" error while uncompressing data" );
1882         free( p_data );
1883         return( 1 );
1884     }
1885
1886     if( p_cmvd->data.p_cmvd->i_uncompressed_size != z_data.total_out )
1887     {
1888         msg_Warn( p_stream->p_input, 
1889                   "Read Box: \"cmov\" uncompressing data size mismatch" );
1890     }
1891     p_cmvd->data.p_cmvd->i_uncompressed_size = z_data.total_out;
1892
1893     /* close zlib */ 
1894     i_result = inflateEnd( &z_data );
1895     if( i_result != Z_OK )
1896     {
1897         msg_Warn( p_stream->p_input, 
1898            "Read Box: \"cmov\" error while uncompressing data (ignored)" );
1899     }
1900
1901
1902     free( p_cmvd->data.p_cmvd->p_data );
1903     p_cmvd->data.p_cmvd->p_data = p_data;
1904     p_cmvd->data.p_cmvd->b_compressed = 0;
1905
1906     msg_Dbg( p_stream->p_input, 
1907              "Read Box: \"cmov\" box succesfully uncompressed" );
1908
1909     /* now create a memory stream */
1910     p_stream_memory = MP4_MemoryStream( p_stream->p_input, 
1911                                         p_cmvd->data.p_cmvd->i_uncompressed_size,
1912                                         p_cmvd->data.p_cmvd->p_data );
1913
1914     /* and read uncompressd moov */
1915     p_umov = malloc( sizeof( MP4_Box_t ) );
1916     
1917     i_result = MP4_ReadBox( p_stream_memory, p_umov, NULL );
1918   
1919     p_box->data.p_cmov->p_moov = p_umov;
1920     free( p_stream_memory );
1921
1922 #ifdef MP4_VERBOSE
1923     msg_Dbg( p_stream->p_input, 
1924              "Read Box: \"cmov\" compressed movie header completed" );
1925 #endif
1926     return( i_result );
1927 }
1928
1929
1930 /**** ------------------------------------------------------------------- ****/
1931 /****                   "Higher level" Functions                          ****/
1932 /**** ------------------------------------------------------------------- ****/
1933
1934 static struct 
1935 {
1936     u32 i_type;
1937     int  (*MP4_ReadBox_function )( MP4_Stream_t *p_stream, MP4_Box_t *p_box ); 
1938     void (*MP4_FreeBox_function )( input_thread_t *p_input, MP4_Box_t *p_box );
1939 } MP4_Box_Function [] =
1940 {
1941     /* Containers */
1942     { FOURCC_moov,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
1943     { FOURCC_trak,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
1944     { FOURCC_mdia,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
1945     { FOURCC_moof,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
1946     { FOURCC_minf,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
1947     { FOURCC_stbl,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
1948     { FOURCC_dinf,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
1949     { FOURCC_edts,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
1950     { FOURCC_udta,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
1951     { FOURCC_nmhd,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
1952     { FOURCC_hnti,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
1953
1954     /* specific box */
1955     { FOURCC_ftyp,  MP4_ReadBox_ftyp,       MP4_FreeBox_ftyp },
1956     { FOURCC_cmov,  MP4_ReadBox_cmov,       MP4_FreeBox_Common },
1957     { FOURCC_mvhd,  MP4_ReadBox_mvhd,       MP4_FreeBox_Common },
1958     { FOURCC_tkhd,  MP4_ReadBox_tkhd,       MP4_FreeBox_Common },
1959     { FOURCC_tref,  MP4_ReadBox_tref,       MP4_FreeBox_Common },
1960     { FOURCC_mdhd,  MP4_ReadBox_mdhd,       MP4_FreeBox_Common },
1961     { FOURCC_hdlr,  MP4_ReadBox_hdlr,       MP4_FreeBox_hdlr },
1962     { FOURCC_vmhd,  MP4_ReadBox_vmhd,       MP4_FreeBox_Common },
1963     { FOURCC_smhd,  MP4_ReadBox_smhd,       MP4_FreeBox_Common },
1964     { FOURCC_hmhd,  MP4_ReadBox_hmhd,       MP4_FreeBox_Common },
1965     { FOURCC_url,   MP4_ReadBox_url,        MP4_FreeBox_url },
1966     { FOURCC_urn,   MP4_ReadBox_urn,        MP4_FreeBox_urn },
1967     { FOURCC_dref,  MP4_ReadBox_dref,       MP4_FreeBox_Common },
1968     { FOURCC_stts,  MP4_ReadBox_stts,       MP4_FreeBox_stts },
1969     { FOURCC_ctts,  MP4_ReadBox_ctts,       MP4_FreeBox_ctts },
1970     { FOURCC_stsd,  MP4_ReadBox_stsd,       MP4_FreeBox_Common },
1971     { FOURCC_stsz,  MP4_ReadBox_stsz,       MP4_FreeBox_stsz },
1972     { FOURCC_stsc,  MP4_ReadBox_stsc,       MP4_FreeBox_stsc },
1973     { FOURCC_stco,  MP4_ReadBox_stco_co64,  MP4_FreeBox_stco_co64 },
1974     { FOURCC_co64,  MP4_ReadBox_stco_co64,  MP4_FreeBox_stco_co64 },
1975     { FOURCC_stss,  MP4_ReadBox_stss,       MP4_FreeBox_stss },
1976     { FOURCC_stsh,  MP4_ReadBox_stsh,       MP4_FreeBox_stsh },
1977     { FOURCC_stdp,  MP4_ReadBox_stdp,       MP4_FreeBox_stdp },
1978     { FOURCC_padb,  MP4_ReadBox_padb,       MP4_FreeBox_padb },
1979     { FOURCC_elst,  MP4_ReadBox_elst,       MP4_FreeBox_elst },
1980     { FOURCC_cprt,  MP4_ReadBox_cprt,       MP4_FreeBox_cprt },
1981     { FOURCC_esds,  MP4_ReadBox_esds,       MP4_FreeBox_esds },
1982     { FOURCC_dcom,  MP4_ReadBox_dcom,       MP4_FreeBox_Common },
1983     { FOURCC_cmvd,  MP4_ReadBox_cmvd,       MP4_FreeBox_cmvd },
1984
1985     /* Nothing to do with this box */
1986     { FOURCC_mdat,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
1987     { FOURCC_skip,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
1988     { FOURCC_free,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
1989     { FOURCC_wide,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
1990
1991     /* for codecs */
1992     { FOURCC_soun,  MP4_ReadBox_sample_soun,    MP4_FreeBox_Common },
1993     { FOURCC__mp3,  MP4_ReadBox_sample_soun,    MP4_FreeBox_Common },
1994     { FOURCC_mp4a,  MP4_ReadBox_sample_mp4a,    MP4_FreeBox_Common },
1995
1996     { FOURCC_vide,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
1997     { FOURCC_mp4v,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
1998     { FOURCC_SVQ1,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
1999     { FOURCC_DIVX,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2000     { FOURCC_h263,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2001     { FOURCC_cvid,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2002     { FOURCC_3IV1,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2003     { FOURCC_mjpa,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2004     { FOURCC_mjpb,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2005     { FOURCC_mjqt,  NULL,                       NULL }, /* found in mjpa/b */
2006     { FOURCC_mjht,  NULL,                       NULL },
2007  
2008     { FOURCC_jpeg,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2009
2010     { FOURCC_mp4s,  NULL,                       MP4_FreeBox_Common },
2011
2012     /* XXX there is 2 box where we could find this entry stbl and tref*/
2013     { FOURCC_hint,  NULL,                       MP4_FreeBox_Common },
2014
2015     /* found in tref box */
2016     { FOURCC_dpnd,  NULL,   NULL },
2017     { FOURCC_ipir,  NULL,   NULL },
2018     { FOURCC_mpod,  NULL,   NULL },
2019     
2020     /* found in hnti */
2021     { FOURCC_rtp,   NULL,   NULL },
2022     
2023     /* Last entry */
2024     
2025     { 0,            NULL,                   NULL }
2026 };
2027
2028
2029
2030 /*****************************************************************************
2031  * MP4_ReadBox : parse the actual box and the children 
2032  *  XXX : Do not go to the next box
2033  *****************************************************************************/
2034 int MP4_ReadBox( MP4_Stream_t *p_stream, MP4_Box_t *p_box, MP4_Box_t *p_father )
2035 {
2036     int i_result;
2037     int i_index;
2038     
2039     if( !MP4_ReadBoxCommon( p_stream, p_box ) )
2040     {
2041         msg_Warn( p_stream->p_input, "Cannot read one box" );
2042         return( 0 );
2043     }
2044     if( !p_box->i_size )
2045     {
2046         msg_Dbg( p_stream->p_input, "Found an empty box (null size)" );
2047         return( 0 );
2048     }
2049     p_box->p_father = p_father;
2050
2051     /* Now search function to call */
2052     for( i_index = 0; ; i_index++ )
2053     {
2054         if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
2055             ( MP4_Box_Function[i_index].i_type == 0 ) )
2056         {
2057             break;
2058         }
2059     }
2060     if( MP4_Box_Function[i_index].MP4_ReadBox_function == NULL )
2061     {
2062         msg_Warn( p_stream->p_input,
2063                   "Unknown box type %c%c%c%c (uncompletetly loaded)",
2064                   (p_box->i_type)&0xff, 
2065                   (p_box->i_type>>8)&0xff,
2066                   (p_box->i_type>>16)&0xff,
2067                   (p_box->i_type>>24)&0xff );
2068         return( 1 );
2069     }
2070     else
2071     {
2072         i_result = 
2073            (MP4_Box_Function[i_index].MP4_ReadBox_function)( p_stream, p_box );
2074     }
2075
2076     if( !MP4_GotoBox( p_stream, p_box ) )
2077     {
2078         return( 0 );
2079     }
2080     return( i_result );
2081 }
2082
2083 /*****************************************************************************
2084  * MP4_FreeBox : free memory after read with MP4_ReadBox and all 
2085  * the children
2086  *****************************************************************************/
2087 void MP4_FreeBox( input_thread_t *p_input, MP4_Box_t *p_box )
2088 {
2089     int i_index;
2090
2091     MP4_Box_t *p_child;
2092     MP4_Box_t *p_next;
2093
2094     if( !p_box )
2095     {
2096         return; /* hehe */
2097     }
2098     p_child = p_box->p_first;
2099     while( p_child )
2100     {
2101         p_next = p_child->p_next;
2102         MP4_FreeBox( p_input, p_child );
2103         /* MP4_FreeBoxChildren have free all data expect p_child itself */
2104         free( p_child );
2105         p_child = p_next; 
2106     }
2107
2108     /* Now search function to call */
2109     if( p_box->data.p_data )
2110     {
2111         for( i_index = 0; ; i_index++ )
2112         {
2113             if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
2114                 ( MP4_Box_Function[i_index].i_type == 0 ) )
2115             {
2116                 break;
2117             }
2118         }
2119         if( MP4_Box_Function[i_index].MP4_FreeBox_function == NULL )
2120         {
2121             /* Should not happen */
2122             msg_Warn( p_input, 
2123                       "cannot free box %c%c%c%c, type unknown",
2124                       (p_box->i_type)&0xff,
2125                       (p_box->i_type >> 8)&0xff, 
2126                       (p_box->i_type >> 16)&0xff, 
2127                       (p_box->i_type >> 24)&0xff );
2128         }
2129         else
2130         {
2131             MP4_Box_Function[i_index].MP4_FreeBox_function( p_input, p_box );
2132         }
2133
2134         free( p_box->data.p_data );
2135         p_box->data.p_data = NULL;
2136     }
2137
2138     p_box->p_first = NULL;
2139     p_box->p_last = NULL;
2140     
2141 }
2142
2143 /*****************************************************************************
2144  * MP4_ReadRoot : Parse the entire file, and create all boxes in memory
2145  *****************************************************************************
2146  *  The first box is a virtual box "root" and is the father for all first 
2147  *  level boxes for the file, a sort of virtual contener
2148  *****************************************************************************/
2149 int MP4_ReadBoxRoot( input_thread_t *p_input, MP4_Box_t *p_root )
2150 {
2151     
2152     MP4_Stream_t *p_stream;
2153     int i_result;
2154     
2155     MP4_SeekAbsolute( p_input, 0 );     /* Go to the begining */
2156     p_root->i_pos = 0;
2157     p_root->i_type = MP4_FOURCC( 'r', 'o', 'o', 't' );
2158     p_root->i_shortsize = 1;
2159     p_root->i_size = p_input->stream.p_selected_area->i_size;
2160     CreateUUID( &p_root->i_uuid, p_root->i_type );
2161
2162     p_root->data.p_data = NULL;
2163     p_root->p_father = NULL;
2164     p_root->p_first  = NULL;
2165     p_root->p_last  = NULL;
2166     p_root->p_next   = NULL;
2167     
2168     p_stream = MP4_InputStream( p_input );
2169     
2170     i_result = MP4_ReadBoxContainerRaw( p_stream, p_root );
2171
2172     free( p_stream );
2173     
2174     if( i_result )
2175     {
2176         MP4_Box_t *p_child; 
2177         MP4_Box_t *p_moov;
2178         MP4_Box_t *p_cmov;
2179
2180         /* check if there is a cmov, if so replace 
2181           compressed moov by  uncompressed one */
2182         if( ( p_moov = MP4_FindBox( p_root, FOURCC_moov ) )&&
2183             ( p_cmov = MP4_FindBox( p_moov, FOURCC_cmov ) ) )
2184         {
2185             /* rename the compressed moov as a box to skip */
2186             p_moov->i_type = FOURCC_skip;
2187                 
2188             /* get uncompressed p_moov */
2189             p_moov = p_cmov->data.p_cmov->p_moov;
2190             p_cmov->data.p_cmov->p_moov = NULL;
2191
2192             /* make p_root father of this new moov */
2193             p_moov->p_father = p_root;
2194
2195             /* insert this new moov box as first child of p_root */
2196             p_moov->p_next = p_child = p_root->p_first;
2197             p_root->p_first = p_moov;
2198         }
2199     }
2200     return( i_result );
2201 }
2202
2203
2204 static void __MP4_DumpBoxStructure( input_thread_t *p_input,
2205                                     MP4_Box_t *p_box, int i_level )
2206 {
2207     MP4_Box_t *p_child;
2208
2209     if( !i_level )
2210     {
2211         msg_Dbg( p_input, "Dumping root Box \"%c%c%c%c \"",
2212                           (p_box->i_type ) &0xff,
2213                           (p_box->i_type >>8 ) &0xff,
2214                           (p_box->i_type >>16 ) &0xff,
2215                           (p_box->i_type >>24) &0xff );
2216     }
2217     else
2218     {
2219         char str[512];
2220         int i;
2221         memset( str, (u8)' ', 512 );
2222         for( i = 0; i < i_level; i++ )
2223         {
2224             str[i*5] = '|';
2225         }
2226         sprintf( str + i_level * 5, "+ %c%c%c%c size %d",
2227                       (p_box->i_type ) &0xff,
2228                       (p_box->i_type>>8 ) &0xff,
2229                       (p_box->i_type>>16 ) &0xff,
2230                       (p_box->i_type>>24 ) &0xff,
2231                       (u32)p_box->i_size );
2232         
2233         msg_Dbg( p_input, "%s", str );
2234     }
2235     p_child = p_box->p_first;
2236     while( p_child )
2237     {
2238         __MP4_DumpBoxStructure( p_input, p_child, i_level + 1 );
2239         p_child = p_child->p_next;
2240     }
2241     
2242 }
2243
2244 void MP4_DumpBoxStructure( input_thread_t *p_input, MP4_Box_t *p_box )
2245 {
2246     __MP4_DumpBoxStructure( p_input, p_box, 0 );
2247 }
2248
2249
2250 /*****************************************************************************
2251  * MP4_CountBox: given a box, count how many child have the requested type 
2252  * FIXME : support GUUID 
2253  *****************************************************************************/
2254 int MP4_CountBox( MP4_Box_t *p_box, u32 i_type )
2255 {
2256     int i_count;
2257     MP4_Box_t *p_child;
2258     
2259     if( !p_box )
2260     {
2261         return( 0 );
2262     }
2263
2264     i_count = 0;
2265     p_child = p_box->p_first;
2266     while( p_child )
2267     {
2268         if( p_child->i_type == i_type )
2269         {   
2270             i_count++;
2271         }
2272         p_child = p_child->p_next;
2273     }
2274     
2275     return( i_count );
2276 }
2277
2278
2279 /*****************************************************************************
2280  * MP4_FindBox:  find first box with i_type child of p_box
2281  *      return NULL if not found
2282  *****************************************************************************/
2283
2284 MP4_Box_t *MP4_FindBox( MP4_Box_t *p_box, u32 i_type )
2285 {
2286     MP4_Box_t *p_child;
2287     
2288     if( !p_box )
2289     {
2290         return( NULL );
2291     }
2292
2293     p_child = p_box->p_first;
2294     while( p_child )
2295     {
2296         if( p_child->i_type == i_type )
2297         {   
2298             return( p_child );
2299         }
2300         p_child = p_child->p_next;
2301     }
2302     
2303     return( NULL );
2304 }
2305
2306
2307 /*****************************************************************************
2308  * MP4_FindNextBox:  find next box with thesame type and at the same level 
2309  *                  than p_box
2310  *****************************************************************************/
2311 MP4_Box_t *MP4_FindNextBox( MP4_Box_t *p_box )
2312 {
2313     MP4_Box_t *p_next;
2314     
2315     if( !p_box )
2316     {
2317         return( NULL );
2318     }
2319
2320     p_next = p_box->p_next;
2321     while( p_next )
2322     {
2323         if( p_next->i_type == p_box->i_type )
2324         {
2325             return( p_next );
2326         }
2327         p_next = p_next->p_next;
2328     }
2329     return( NULL );
2330 }
2331
2332 /*****************************************************************************
2333  * MP4_FindNbBox:  find the box i_number
2334  *****************************************************************************/
2335 MP4_Box_t *MP4_FindNbBox( MP4_Box_t *p_box, u32 i_number )
2336 {
2337     MP4_Box_t *p_child = p_box->p_first;
2338     
2339     if( !p_child )
2340     {
2341         return( NULL );
2342     }
2343
2344     while( i_number )
2345     {
2346         if( !( p_child = p_child->p_next ) )
2347         {
2348             return( NULL );
2349         }
2350         i_number--;
2351     }
2352     return( p_child );
2353 }
2354