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