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