]> git.sesse.net Git - vlc/blob - modules/demux/mp4/libmp4.c
* fixed a really stupid bug with compressed header, improved parsing
[vlc] / modules / demux / mp4 / libmp4.c
1 /*****************************************************************************
2  * libmp4.c : LibMP4 library for mp4 module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: libmp4.c,v 1.16 2003/03/09 16:22:35 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         MP4_READBOX_EXIT( 1 ); /* rest isn't interesting up to now */
1156     }
1157
1158     i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
1159     es_descriptor.p_decConfigDescr =
1160             malloc( sizeof( MP4_descriptor_decoder_config_t ));
1161
1162     MP4_GET1BYTE( es_descriptor.p_decConfigDescr->i_objectTypeIndication );
1163     MP4_GET1BYTE( i_flags );
1164     es_descriptor.p_decConfigDescr->i_streamType = i_flags >> 2;
1165     es_descriptor.p_decConfigDescr->b_upStream = ( i_flags >> 1 )&0x01;
1166     MP4_GET3BYTES( es_descriptor.p_decConfigDescr->i_buffer_sizeDB );
1167     MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_max_bitrate );
1168     MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_avg_bitrate );
1169     MP4_GET1BYTE( i_type );
1170     if( i_type !=  0x05 )/* MP4DecSpecificDescrTag */
1171     {
1172         MP4_READBOX_EXIT( 1 );
1173     }
1174
1175     i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
1176     es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = i_len;
1177     es_descriptor.p_decConfigDescr->p_decoder_specific_info = malloc( i_len );
1178     memcpy( es_descriptor.p_decConfigDescr->p_decoder_specific_info,
1179             p_peek, i_len );
1180
1181     MP4_READBOX_EXIT( 1 );
1182
1183 #undef es_descriptor
1184 }
1185
1186 void MP4_FreeBox_esds( input_thread_t *p_input, MP4_Box_t *p_box )
1187 {
1188     FREE( p_box->data.p_esds->es_descriptor.psz_URL );
1189     if( p_box->data.p_esds->es_descriptor.p_decConfigDescr )
1190     {
1191         FREE( p_box->data.p_esds->es_descriptor.p_decConfigDescr->p_decoder_specific_info );
1192     }
1193     FREE( p_box->data.p_esds->es_descriptor.p_decConfigDescr );
1194 }
1195
1196 int MP4_ReadBox_sample_soun( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1197 {
1198     unsigned int i;
1199
1200     MP4_READBOX_ENTER( MP4_Box_data_sample_soun_t );
1201
1202     for( i = 0; i < 6 ; i++ )
1203     {
1204         MP4_GET1BYTE( p_box->data.p_sample_soun->i_reserved1[i] );
1205     }
1206
1207     MP4_GET2BYTES( p_box->data.p_sample_soun->i_data_reference_index );
1208
1209     MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_version );
1210     MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_revision_level );
1211     MP4_GET4BYTES( p_box->data.p_sample_soun->i_qt_vendor );
1212
1213 #if 0
1214     for( i = 0; i < 2 ; i++ )
1215     {
1216         MP4_GET4BYTES( p_box->data.p_sample_soun->i_reserved2[i] );
1217     }
1218 #endif
1219
1220     MP4_GET2BYTES( p_box->data.p_sample_soun->i_channelcount );
1221     MP4_GET2BYTES( p_box->data.p_sample_soun->i_samplesize );
1222     MP4_GET2BYTES( p_box->data.p_sample_soun->i_predefined );
1223     MP4_GET2BYTES( p_box->data.p_sample_soun->i_reserved3 );
1224     MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratehi );
1225     MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratelo );
1226
1227     if( p_box->data.p_sample_soun->i_qt_version == 1 &&
1228         i_read >= 16 )
1229     {
1230         /* qt3+ */
1231         MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet );
1232         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_packet );
1233         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_frame );
1234         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_sample );
1235
1236 #ifdef MP4_VERBOSE
1237         msg_Dbg( p_stream->p_input, "" );
1238         msg_Dbg( p_stream->p_input,
1239                  "Read Box: \"soun\" qt3+ sample/packet=%d bytes/packet=%d bytes/frame=%d bytes/sample=%d",
1240                  p_box->data.p_sample_soun->i_sample_per_packet, p_box->data.p_sample_soun->i_bytes_per_packet,
1241                  p_box->data.p_sample_soun->i_bytes_per_frame, p_box->data.p_sample_soun->i_bytes_per_sample );
1242         msg_Dbg( p_stream->p_input, "" );
1243 #endif
1244         MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 44 );
1245     }
1246     else
1247     {
1248         p_box->data.p_sample_soun->i_sample_per_packet = 0;
1249         p_box->data.p_sample_soun->i_bytes_per_packet = 0;
1250         p_box->data.p_sample_soun->i_bytes_per_frame = 0;
1251         p_box->data.p_sample_soun->i_bytes_per_sample = 0;
1252
1253         msg_Dbg( p_stream->p_input, "" );
1254         msg_Dbg( p_stream->p_input, "Read Box: \"soun\" mp4 or qt1/2 (rest=%d)", i_read );
1255         msg_Dbg( p_stream->p_input, "" );
1256         MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 28 );
1257     }
1258     MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds */
1259
1260 #ifdef MP4_VERBOSE
1261     msg_Dbg( p_stream->p_input, "Read Box: \"soun\" in stsd channel %d sample size %d sampl rate %f",
1262                       p_box->data.p_sample_soun->i_channelcount,
1263                       p_box->data.p_sample_soun->i_samplesize,
1264                       (float)p_box->data.p_sample_soun->i_sampleratehi +
1265                     (float)p_box->data.p_sample_soun->i_sampleratelo / 65536 );
1266
1267 #endif
1268     MP4_READBOX_EXIT( 1 );
1269 }
1270
1271 #if 0
1272 int MP4_ReadBox_sample_mp4a( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1273 {
1274     unsigned int i;
1275
1276     MP4_READBOX_ENTER( MP4_Box_data_sample_mp4a_t );
1277
1278     for( i = 0; i < 6 ; i++ )
1279     {
1280         MP4_GET1BYTE( p_box->data.p_sample_mp4a->i_reserved1[i] );
1281     }
1282
1283     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_data_reference_index );
1284
1285     for( i = 0; i < 2 ; i++ )
1286     {
1287         MP4_GET4BYTES( p_box->data.p_sample_mp4a->i_reserved2[i] );
1288     }
1289
1290     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_channelcount );
1291     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_samplesize );
1292     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_predefined );
1293     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_reserved3 );
1294     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_sampleratehi );
1295     MP4_GET2BYTES( p_box->data.p_sample_mp4a->i_sampleratelo );
1296
1297     MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 28 );
1298     MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds */
1299
1300 #ifdef MP4_VERBOSE
1301     msg_Dbg( p_stream->p_input, "Read Box: \"mp4a\" in stsd channel %d sample size %d sampl rate %f",
1302                       p_box->data.p_sample_mp4a->i_channelcount,
1303                       p_box->data.p_sample_mp4a->i_samplesize,
1304                       (float)p_box->data.p_sample_mp4a->i_sampleratehi +
1305                         (float)p_box->data.p_sample_mp4a->i_sampleratelo / 65536 );
1306
1307 #endif
1308     MP4_READBOX_EXIT( 1 );
1309 }
1310 #endif
1311
1312 int MP4_ReadBox_sample_vide( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1313 {
1314     unsigned int i;
1315
1316     MP4_READBOX_ENTER( MP4_Box_data_sample_vide_t );
1317
1318     for( i = 0; i < 6 ; i++ )
1319     {
1320         MP4_GET1BYTE( p_box->data.p_sample_vide->i_reserved1[i] );
1321     }
1322
1323     MP4_GET2BYTES( p_box->data.p_sample_vide->i_data_reference_index );
1324
1325     MP4_GET2BYTES( p_box->data.p_sample_vide->i_predefined1 );
1326     MP4_GET2BYTES( p_box->data.p_sample_vide->i_reserved2 );
1327
1328     for( i = 0; i < 3 ; i++ )
1329     {
1330         MP4_GET4BYTES( p_box->data.p_sample_vide->i_predefined2[i] );
1331     }
1332
1333     MP4_GET2BYTES( p_box->data.p_sample_vide->i_width );
1334     MP4_GET2BYTES( p_box->data.p_sample_vide->i_height );
1335
1336     MP4_GET4BYTES( p_box->data.p_sample_vide->i_horizresolution );
1337     MP4_GET4BYTES( p_box->data.p_sample_vide->i_vertresolution );
1338
1339     MP4_GET4BYTES( p_box->data.p_sample_vide->i_reserved3 );
1340     MP4_GET2BYTES( p_box->data.p_sample_vide->i_predefined3 );
1341
1342     memcpy( &p_box->data.p_sample_vide->i_compressorname, p_peek, 32 );
1343     p_peek += 32; i_read -= 32;
1344
1345     MP4_GET2BYTES( p_box->data.p_sample_vide->i_depth );
1346     MP4_GET2BYTES( p_box->data.p_sample_vide->i_predefined4 );
1347
1348     MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 78);
1349     MP4_ReadBoxContainerRaw( p_stream, p_box );
1350
1351 #ifdef MP4_VERBOSE
1352     msg_Dbg( p_stream->p_input, "Read Box: \"vide\" in stsd %dx%d depth %d",
1353                       p_box->data.p_sample_vide->i_width,
1354                       p_box->data.p_sample_vide->i_height,
1355                       p_box->data.p_sample_vide->i_depth );
1356
1357 #endif
1358     MP4_READBOX_EXIT( 1 );
1359 }
1360
1361
1362 int MP4_ReadBox_stsd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1363 {
1364
1365     MP4_READBOX_ENTER( MP4_Box_data_stsd_t );
1366
1367     MP4_GETVERSIONFLAGS( p_box->data.p_stsd );
1368
1369     MP4_GET4BYTES( p_box->data.p_stsd->i_entry_count );
1370
1371     MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 8 );
1372
1373     MP4_ReadBoxContainerRaw( p_stream, p_box );
1374
1375 #ifdef MP4_VERBOSE
1376     msg_Dbg( p_stream->p_input, "Read Box: \"stsd\" entry-count %d",
1377                       p_box->data.p_stsd->i_entry_count );
1378
1379 #endif
1380     MP4_READBOX_EXIT( 1 );
1381 }
1382
1383
1384 int MP4_ReadBox_stsz( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1385 {
1386     unsigned int i;
1387
1388     MP4_READBOX_ENTER( MP4_Box_data_stsz_t );
1389
1390     MP4_GETVERSIONFLAGS( p_box->data.p_stsz );
1391
1392     MP4_GET4BYTES( p_box->data.p_stsz->i_sample_size );
1393
1394     MP4_GET4BYTES( p_box->data.p_stsz->i_sample_count );
1395
1396     p_box->data.p_stsz->i_entry_size =
1397         calloc( sizeof( uint32_t ), p_box->data.p_stsz->i_sample_count );
1398
1399     if( !p_box->data.p_stsz->i_sample_size )
1400     {
1401         for( i=0; (i<p_box->data.p_stsz->i_sample_count)&&(i_read >= 4 ); i++ )
1402         {
1403             MP4_GET4BYTES( p_box->data.p_stsz->i_entry_size[i] );
1404         }
1405     }
1406
1407 #ifdef MP4_VERBOSE
1408     msg_Dbg( p_stream->p_input, "Read Box: \"stsz\" sample-size %d sample-count %d",
1409                       p_box->data.p_stsz->i_sample_size,
1410                       p_box->data.p_stsz->i_sample_count );
1411
1412 #endif
1413     MP4_READBOX_EXIT( 1 );
1414 }
1415
1416 void MP4_FreeBox_stsz( input_thread_t *p_input, MP4_Box_t *p_box )
1417 {
1418     FREE( p_box->data.p_stsz->i_entry_size );
1419 }
1420
1421 int MP4_ReadBox_stsc( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1422 {
1423     unsigned int i;
1424
1425     MP4_READBOX_ENTER( MP4_Box_data_stsc_t );
1426
1427     MP4_GETVERSIONFLAGS( p_box->data.p_stsc );
1428
1429     MP4_GET4BYTES( p_box->data.p_stsc->i_entry_count );
1430
1431     p_box->data.p_stsc->i_first_chunk =
1432         calloc( sizeof( uint32_t ), p_box->data.p_stsc->i_entry_count );
1433     p_box->data.p_stsc->i_samples_per_chunk =
1434         calloc( sizeof( uint32_t ), p_box->data.p_stsc->i_entry_count );
1435     p_box->data.p_stsc->i_sample_description_index =
1436         calloc( sizeof( uint32_t ), p_box->data.p_stsc->i_entry_count );
1437
1438     for( i = 0; (i < p_box->data.p_stsc->i_entry_count )&&( i_read >= 12 );i++ )
1439     {
1440         MP4_GET4BYTES( p_box->data.p_stsc->i_first_chunk[i] );
1441         MP4_GET4BYTES( p_box->data.p_stsc->i_samples_per_chunk[i] );
1442         MP4_GET4BYTES( p_box->data.p_stsc->i_sample_description_index[i] );
1443     }
1444
1445 #ifdef MP4_VERBOSE
1446     msg_Dbg( p_stream->p_input, "Read Box: \"stsc\" entry-count %d",
1447                       p_box->data.p_stsc->i_entry_count );
1448
1449 #endif
1450     MP4_READBOX_EXIT( 1 );
1451 }
1452
1453 void MP4_FreeBox_stsc( input_thread_t *p_input, MP4_Box_t *p_box )
1454 {
1455     FREE( p_box->data.p_stsc->i_first_chunk );
1456     FREE( p_box->data.p_stsc->i_samples_per_chunk );
1457     FREE( p_box->data.p_stsc->i_sample_description_index );
1458 }
1459
1460 int MP4_ReadBox_stco_co64( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1461 {
1462     unsigned int i;
1463
1464     MP4_READBOX_ENTER( MP4_Box_data_co64_t );
1465
1466     MP4_GETVERSIONFLAGS( p_box->data.p_co64 );
1467
1468     MP4_GET4BYTES( p_box->data.p_co64->i_entry_count );
1469
1470     p_box->data.p_co64->i_chunk_offset =
1471         calloc( sizeof( uint64_t ), p_box->data.p_co64->i_entry_count );
1472
1473     for( i = 0; i < p_box->data.p_co64->i_entry_count; i++ )
1474     {
1475         if( p_box->i_type == FOURCC_stco )
1476         {
1477             if( i_read < 4 )
1478             {
1479                 break;
1480             }
1481             MP4_GET4BYTES( p_box->data.p_co64->i_chunk_offset[i] );
1482         }
1483         else
1484         {
1485             if( i_read < 8 )
1486             {
1487                 break;
1488             }
1489             MP4_GET8BYTES( p_box->data.p_co64->i_chunk_offset[i] );
1490         }
1491     }
1492
1493 #ifdef MP4_VERBOSE
1494     msg_Dbg( p_stream->p_input, "Read Box: \"co64\" entry-count %d",
1495                       p_box->data.p_co64->i_entry_count );
1496
1497 #endif
1498     MP4_READBOX_EXIT( 1 );
1499 }
1500
1501 void MP4_FreeBox_stco_co64( input_thread_t *p_input, MP4_Box_t *p_box )
1502 {
1503     FREE( p_box->data.p_co64->i_chunk_offset );
1504 }
1505
1506 int MP4_ReadBox_stss( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1507 {
1508     unsigned int i;
1509
1510     MP4_READBOX_ENTER( MP4_Box_data_stss_t );
1511
1512     MP4_GETVERSIONFLAGS( p_box->data.p_stss );
1513
1514     MP4_GET4BYTES( p_box->data.p_stss->i_entry_count );
1515
1516     p_box->data.p_stss->i_sample_number =
1517         calloc( sizeof( uint32_t ), p_box->data.p_stss->i_entry_count );
1518
1519     for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 4 ); i++ )
1520     {
1521
1522         MP4_GET4BYTES( p_box->data.p_stss->i_sample_number[i] );
1523         /* XXX in libmp4 sample begin at 0 */
1524         p_box->data.p_stss->i_sample_number[i]--;
1525     }
1526
1527 #ifdef MP4_VERBOSE
1528     msg_Dbg( p_stream->p_input, "Read Box: \"stss\" entry-count %d",
1529                       p_box->data.p_stss->i_entry_count );
1530
1531 #endif
1532     MP4_READBOX_EXIT( 1 );
1533 }
1534
1535 void MP4_FreeBox_stss( input_thread_t *p_input, MP4_Box_t *p_box )
1536 {
1537     FREE( p_box->data.p_stss->i_sample_number )
1538 }
1539
1540 int MP4_ReadBox_stsh( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1541 {
1542     unsigned int i;
1543
1544     MP4_READBOX_ENTER( MP4_Box_data_stsh_t );
1545
1546     MP4_GETVERSIONFLAGS( p_box->data.p_stsh );
1547
1548
1549     MP4_GET4BYTES( p_box->data.p_stsh->i_entry_count );
1550
1551     p_box->data.p_stsh->i_shadowed_sample_number =
1552         calloc( sizeof( uint32_t ), p_box->data.p_stsh->i_entry_count );
1553
1554     p_box->data.p_stsh->i_sync_sample_number =
1555         calloc( sizeof( uint32_t ), p_box->data.p_stsh->i_entry_count );
1556
1557
1558     for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 8 ); i++ )
1559     {
1560
1561         MP4_GET4BYTES( p_box->data.p_stsh->i_shadowed_sample_number[i] );
1562         MP4_GET4BYTES( p_box->data.p_stsh->i_sync_sample_number[i] );
1563     }
1564
1565 #ifdef MP4_VERBOSE
1566     msg_Dbg( p_stream->p_input, "Read Box: \"stsh\" entry-count %d",
1567                       p_box->data.p_stsh->i_entry_count );
1568 #endif
1569     MP4_READBOX_EXIT( 1 );
1570 }
1571
1572 void MP4_FreeBox_stsh( input_thread_t *p_input, MP4_Box_t *p_box )
1573 {
1574     FREE( p_box->data.p_stsh->i_shadowed_sample_number )
1575     FREE( p_box->data.p_stsh->i_sync_sample_number )
1576 }
1577
1578
1579 int MP4_ReadBox_stdp( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1580 {
1581     unsigned int i;
1582
1583     MP4_READBOX_ENTER( MP4_Box_data_stdp_t );
1584
1585     MP4_GETVERSIONFLAGS( p_box->data.p_stdp );
1586
1587     p_box->data.p_stdp->i_priority =
1588         calloc( sizeof( uint16_t ), i_read / 2 );
1589
1590     for( i = 0; i < i_read / 2 ; i++ )
1591     {
1592
1593         MP4_GET2BYTES( p_box->data.p_stdp->i_priority[i] );
1594     }
1595
1596 #ifdef MP4_VERBOSE
1597     msg_Dbg( p_stream->p_input, "Read Box: \"stdp\" entry-count "I64Fd,
1598                       i_read / 2 );
1599
1600 #endif
1601     MP4_READBOX_EXIT( 1 );
1602 }
1603
1604 void MP4_FreeBox_stdp( input_thread_t *p_input, MP4_Box_t *p_box )
1605 {
1606     FREE( p_box->data.p_stdp->i_priority )
1607 }
1608
1609 int MP4_ReadBox_padb( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1610 {
1611     unsigned int i;
1612
1613     MP4_READBOX_ENTER( MP4_Box_data_padb_t );
1614
1615     MP4_GETVERSIONFLAGS( p_box->data.p_padb );
1616
1617
1618     MP4_GET4BYTES( p_box->data.p_padb->i_sample_count );
1619
1620     p_box->data.p_padb->i_reserved1 =
1621         calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
1622     p_box->data.p_padb->i_pad2 =
1623         calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
1624     p_box->data.p_padb->i_reserved2 =
1625         calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
1626     p_box->data.p_padb->i_pad1 =
1627         calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
1628
1629
1630     for( i = 0; i < i_read / 2 ; i++ )
1631     {
1632         p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 7 )&0x01;
1633         p_box->data.p_padb->i_pad2[i] = ( (*p_peek) >> 4 )&0x07;
1634         p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 3 )&0x01;
1635         p_box->data.p_padb->i_pad1[i] = ( (*p_peek) )&0x07;
1636
1637         p_peek += 1; i_read -= 1;
1638     }
1639
1640 #ifdef MP4_VERBOSE
1641     msg_Dbg( p_stream->p_input, "Read Box: \"stdp\" entry-count "I64Fd,
1642                       i_read / 2 );
1643
1644 #endif
1645     MP4_READBOX_EXIT( 1 );
1646 }
1647
1648 void MP4_FreeBox_padb( input_thread_t *p_input, MP4_Box_t *p_box )
1649 {
1650     FREE( p_box->data.p_padb->i_reserved1 );
1651     FREE( p_box->data.p_padb->i_pad2 );
1652     FREE( p_box->data.p_padb->i_reserved2 );
1653     FREE( p_box->data.p_padb->i_pad1 );
1654 }
1655
1656 int MP4_ReadBox_elst( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1657 {
1658     unsigned int i;
1659
1660     MP4_READBOX_ENTER( MP4_Box_data_padb_t );
1661
1662     MP4_GETVERSIONFLAGS( p_box->data.p_elst );
1663
1664
1665     MP4_GET4BYTES( p_box->data.p_elst->i_entry_count );
1666
1667     p_box->data.p_elst->i_segment_duration =
1668         calloc( sizeof( uint64_t ), p_box->data.p_elst->i_entry_count );
1669     p_box->data.p_elst->i_media_time =
1670         calloc( sizeof( uint64_t ), p_box->data.p_elst->i_entry_count );
1671     p_box->data.p_elst->i_media_rate_integer =
1672         calloc( sizeof( uint16_t ), p_box->data.p_elst->i_entry_count );
1673     p_box->data.p_elst->i_media_rate_fraction=
1674         calloc( sizeof( uint16_t ), p_box->data.p_elst->i_entry_count );
1675
1676
1677     for( i = 0; i < p_box->data.p_elst->i_entry_count; i++ )
1678     {
1679         if( p_box->data.p_elst->i_version == 1 )
1680         {
1681
1682             MP4_GET8BYTES( p_box->data.p_elst->i_segment_duration[i] );
1683
1684             MP4_GET8BYTES( p_box->data.p_elst->i_media_time[i] );
1685         }
1686         else
1687         {
1688
1689             MP4_GET4BYTES( p_box->data.p_elst->i_segment_duration[i] );
1690
1691             MP4_GET4BYTES( p_box->data.p_elst->i_media_time[i] );
1692         }
1693
1694         MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_integer[i] );
1695         MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_fraction[i] );
1696     }
1697
1698 #ifdef MP4_VERBOSE
1699     msg_Dbg( p_stream->p_input, "Read Box: \"elst\" entry-count "I64Fd,
1700                       i_read / 2 );
1701
1702 #endif
1703     MP4_READBOX_EXIT( 1 );
1704 }
1705
1706 void MP4_FreeBox_elst( input_thread_t *p_input, MP4_Box_t *p_box )
1707 {
1708     FREE( p_box->data.p_elst->i_segment_duration );
1709     FREE( p_box->data.p_elst->i_media_time );
1710     FREE( p_box->data.p_elst->i_media_rate_integer );
1711     FREE( p_box->data.p_elst->i_media_rate_fraction );
1712 }
1713
1714 int MP4_ReadBox_cprt( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1715 {
1716     unsigned int i_language;
1717     unsigned int i;
1718
1719     MP4_READBOX_ENTER( MP4_Box_data_cprt_t );
1720
1721     MP4_GETVERSIONFLAGS( p_box->data.p_cprt );
1722
1723     i_language = GetWBE( p_peek );
1724     for( i = 0; i < 3; i++ )
1725     {
1726         p_box->data.p_cprt->i_language[i] =
1727             ( ( i_language >> ( (2-i)*5 ) )&0x1f ) + 0x60;
1728     }
1729     p_peek += 2; i_read -= 2;
1730     MP4_GETSTRINGZ( p_box->data.p_cprt->psz_notice );
1731
1732 #ifdef MP4_VERBOSE
1733     msg_Dbg( p_stream->p_input, "Read Box: \"cprt\" language %c%c%c notice %s",
1734                       p_box->data.p_cprt->i_language[0],
1735                       p_box->data.p_cprt->i_language[1],
1736                       p_box->data.p_cprt->i_language[2],
1737                       p_box->data.p_cprt->psz_notice );
1738
1739 #endif
1740     MP4_READBOX_EXIT( 1 );
1741 }
1742
1743 void MP4_FreeBox_cprt( input_thread_t *p_input, MP4_Box_t *p_box )
1744 {
1745     FREE( p_box->data.p_cprt->psz_notice );
1746 }
1747
1748
1749 int MP4_ReadBox_dcom( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1750 {
1751     MP4_READBOX_ENTER( MP4_Box_data_dcom_t );
1752
1753     MP4_GETFOURCC( p_box->data.p_dcom->i_algorithm );
1754 #ifdef MP4_VERBOSE
1755     msg_Dbg( p_stream->p_input,
1756              "Read Box: \"dcom\" compression algorithm : %4.4s",
1757                       (char*)&p_box->data.p_dcom->i_algorithm );
1758 #endif
1759     MP4_READBOX_EXIT( 1 );
1760 }
1761
1762 int MP4_ReadBox_cmvd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1763 {
1764     MP4_READBOX_ENTER( MP4_Box_data_cmvd_t );
1765
1766     MP4_GET4BYTES( p_box->data.p_cmvd->i_uncompressed_size );
1767
1768     p_box->data.p_cmvd->i_compressed_size = i_read;
1769
1770     if( !( p_box->data.p_cmvd->p_data = malloc( i_read ) ) )
1771     {
1772         msg_Dbg( p_stream->p_input, "Read Box: \"cmvd\" not enough memory to load data" );
1773         return( 1 );
1774     }
1775
1776     /* now copy compressed data */
1777     memcpy( p_box->data.p_cmvd->p_data,
1778             p_peek,
1779             i_read);
1780
1781     p_box->data.p_cmvd->b_compressed = 1;
1782
1783 #ifdef MP4_VERBOSE
1784     msg_Dbg( p_stream->p_input, "Read Box: \"cmvd\" compressed data size %d",
1785                       p_box->data.p_cmvd->i_compressed_size );
1786 #endif
1787
1788     MP4_READBOX_EXIT( 1 );
1789 }
1790 void MP4_FreeBox_cmvd( input_thread_t *p_input, MP4_Box_t *p_box )
1791 {
1792     FREE( p_box->data.p_cmvd->p_data );
1793 }
1794
1795
1796 int MP4_ReadBox_cmov( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1797 {
1798     MP4_Stream_t *p_stream_memory;
1799     MP4_Box_t *p_umov;
1800
1801     MP4_Box_t *p_dcom;
1802     MP4_Box_t *p_cmvd;
1803 #ifdef HAVE_ZLIB_H
1804     z_stream  z_data;
1805 #endif
1806     uint8_t *p_data;
1807
1808     int i_result;
1809
1810     if( !( p_box->data.p_cmov = malloc( sizeof( MP4_Box_data_cmov_t ) ) ) )
1811     {
1812         msg_Err( p_stream->p_input, "out of memory" );
1813         return( 0 );
1814     }
1815     memset( p_box->data.p_cmov, 0, sizeof( MP4_Box_data_cmov_t ) );
1816
1817     if( !( p_box->p_father )||
1818         ( p_box->p_father->i_type != FOURCC_moov ) )
1819     {
1820         msg_Warn( p_stream->p_input, "Read box: \"cmov\" box alone" );
1821         return( 1 );
1822     }
1823
1824     if( !(i_result = MP4_ReadBoxContainer( p_stream, p_box ) ) )
1825     {
1826         return( 0 );
1827     }
1828
1829     if( !( p_dcom = MP4_FindBox( p_box, FOURCC_dcom ) )||
1830         !( p_cmvd = MP4_FindBox( p_box, FOURCC_cmvd ) )||
1831         !( p_cmvd->data.p_cmvd->p_data ) )
1832     {
1833         msg_Warn( p_stream->p_input, "Read Box: \"cmov\" incomplete" );
1834         return( 1 );
1835     }
1836
1837     if( p_dcom->data.p_dcom->i_algorithm != FOURCC_zlib )
1838     {
1839         msg_Dbg( p_stream->p_input, "Read Box: \"cmov\" compression algorithm : %4.4s not supported",
1840                     (char*)&p_dcom->data.p_dcom->i_algorithm );
1841         return( 1 );
1842     }
1843
1844 #ifndef HAVE_ZLIB_H
1845     msg_Dbg( p_stream->p_input,
1846              "Read Box: \"cmov\" zlib unsupported" );
1847     return( 1 );
1848 #else
1849     /* decompress data */
1850     /* allocate a new buffer */
1851     if( !( p_data = malloc( p_cmvd->data.p_cmvd->i_uncompressed_size ) ) )
1852     {
1853         msg_Err( p_stream->p_input,
1854                  "Read Box: \"cmov\" not enough memory to uncompress data" );
1855         return( 1 );
1856     }
1857     /* init default structures */
1858     z_data.next_in   = p_cmvd->data.p_cmvd->p_data;
1859     z_data.avail_in  = p_cmvd->data.p_cmvd->i_compressed_size;
1860     z_data.next_out  = p_data;
1861     z_data.avail_out = p_cmvd->data.p_cmvd->i_uncompressed_size;
1862     z_data.zalloc    = (alloc_func)Z_NULL;
1863     z_data.zfree     = (free_func)Z_NULL;
1864     z_data.opaque    = (voidpf)Z_NULL;
1865
1866     /* init zlib */
1867     if( ( i_result = inflateInit( &z_data ) ) != Z_OK )
1868     {
1869         msg_Err( p_stream->p_input,
1870                  "Read Box: \"cmov\" error while uncompressing data" );
1871         free( p_data );
1872         return( 1 );
1873     }
1874
1875     /* uncompress */
1876     i_result = inflate( &z_data, Z_NO_FLUSH );
1877     if( ( i_result != Z_OK )&&( i_result != Z_STREAM_END ) )
1878     {
1879         msg_Err( p_stream->p_input,
1880                  "Read Box: \"cmov\" error while uncompressing data" );
1881         free( p_data );
1882         return( 1 );
1883     }
1884
1885     if( p_cmvd->data.p_cmvd->i_uncompressed_size != z_data.total_out )
1886     {
1887         msg_Warn( p_stream->p_input,
1888                   "Read Box: \"cmov\" uncompressing data size mismatch" );
1889     }
1890     p_cmvd->data.p_cmvd->i_uncompressed_size = z_data.total_out;
1891
1892     /* close zlib */
1893     i_result = inflateEnd( &z_data );
1894     if( i_result != Z_OK )
1895     {
1896         msg_Warn( p_stream->p_input,
1897            "Read Box: \"cmov\" error while uncompressing data (ignored)" );
1898     }
1899
1900
1901     free( p_cmvd->data.p_cmvd->p_data );
1902     p_cmvd->data.p_cmvd->p_data = p_data;
1903     p_cmvd->data.p_cmvd->b_compressed = 0;
1904
1905     msg_Dbg( p_stream->p_input,
1906              "Read Box: \"cmov\" box succesfully uncompressed" );
1907
1908     //DataDump( p_data, p_cmvd->data.p_cmvd->i_uncompressed_size );
1909     /* now create a memory stream */
1910     p_stream_memory = MP4_MemoryStream( p_stream->p_input,
1911                                         p_cmvd->data.p_cmvd->i_uncompressed_size,
1912                                         p_cmvd->data.p_cmvd->p_data );
1913
1914     //DataDump( p_stream_memory->p_buffer, p_stream_memory->i_stop );
1915
1916     /* and read uncompressd moov */
1917     p_umov = malloc( sizeof( MP4_Box_t ) );
1918
1919     i_result = MP4_ReadBox( p_stream_memory, p_umov, NULL );
1920
1921     p_box->data.p_cmov->p_moov = p_umov;
1922     free( p_stream_memory );
1923
1924 #ifdef MP4_VERBOSE
1925     msg_Dbg( p_stream->p_input,
1926              "Read Box: \"cmov\" compressed movie header completed" );
1927 #endif
1928     return( i_result );
1929 #endif /* HAVE_ZLIB_H */
1930 }
1931
1932 int MP4_ReadBox_rdrf( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1933 {
1934     uint32_t i_len;
1935     MP4_READBOX_ENTER( MP4_Box_data_rdrf_t );
1936
1937     MP4_GETVERSIONFLAGS( p_box->data.p_rdrf );
1938     MP4_GETFOURCC( p_box->data.p_rdrf->i_ref_type );
1939     MP4_GET4BYTES( i_len );
1940     if( i_len > 0 )
1941     {
1942         uint32_t i;
1943         p_box->data.p_rdrf->psz_ref = malloc( i_len );
1944         for( i = 0; i < i_len; i++ )
1945         {
1946             MP4_GET1BYTE( p_box->data.p_rdrf->psz_ref[i] );
1947         }
1948         p_box->data.p_rdrf->psz_ref[i_len] = '\0';
1949     }
1950     else
1951     {
1952         p_box->data.p_rdrf->psz_ref = NULL;
1953     }
1954
1955 #ifdef MP4_VERBOSE
1956     msg_Dbg( p_stream->p_input,
1957              "Read Box: \"rdrf\" type:%4.4s ref %s",
1958              (char*)&p_box->data.p_rdrf->i_ref_type,
1959              p_box->data.p_rdrf->psz_ref );
1960
1961 #endif
1962     MP4_READBOX_EXIT( 1 );
1963 }
1964 void MP4_FreeBox_rdrf( input_thread_t *p_input, MP4_Box_t *p_box )
1965 {
1966     FREE( p_box->data.p_rdrf->psz_ref )
1967 }
1968
1969
1970 int MP4_ReadBox_rmdr( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1971 {
1972     MP4_READBOX_ENTER( MP4_Box_data_rmdr_t );
1973
1974     MP4_GETVERSIONFLAGS( p_box->data.p_rmdr );
1975
1976     MP4_GET4BYTES( p_box->data.p_rmdr->i_rate );
1977
1978 #ifdef MP4_VERBOSE
1979     msg_Dbg( p_stream->p_input,
1980              "Read Box: \"rmdr\" rate:%d",
1981              p_box->data.p_rmdr->i_rate );
1982 #endif
1983     MP4_READBOX_EXIT( 1 );
1984 }
1985
1986 int MP4_ReadBox_rmqu( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
1987 {
1988     MP4_READBOX_ENTER( MP4_Box_data_rmqu_t );
1989
1990     MP4_GET4BYTES( p_box->data.p_rmqu->i_quality );
1991
1992 #ifdef MP4_VERBOSE
1993     msg_Dbg( p_stream->p_input,
1994              "Read Box: \"rmqu\" quality:%d",
1995              p_box->data.p_rmqu->i_quality );
1996 #endif
1997     MP4_READBOX_EXIT( 1 );
1998 }
1999
2000 int MP4_ReadBox_rmvc( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
2001 {
2002     MP4_READBOX_ENTER( MP4_Box_data_rmvc_t );
2003     MP4_GETVERSIONFLAGS( p_box->data.p_rmvc );
2004
2005     MP4_GETFOURCC( p_box->data.p_rmvc->i_gestaltType );
2006     MP4_GET4BYTES( p_box->data.p_rmvc->i_val1 );
2007     MP4_GET4BYTES( p_box->data.p_rmvc->i_val2 );
2008     MP4_GET2BYTES( p_box->data.p_rmvc->i_checkType );
2009
2010 #ifdef MP4_VERBOSE
2011     msg_Dbg( p_stream->p_input,
2012              "Read Box: \"rmvc\" gestaltType:%4.4s val1:0x%x val2:0x%x checkType:0x%x",
2013              (char*)&p_box->data.p_rmvc->i_gestaltType,
2014              p_box->data.p_rmvc->i_val1,p_box->data.p_rmvc->i_val2,
2015              p_box->data.p_rmvc->i_checkType );
2016 #endif
2017
2018     MP4_READBOX_EXIT( 1 );
2019 }
2020
2021 /**** ------------------------------------------------------------------- ****/
2022 /****                   "Higher level" Functions                          ****/
2023 /**** ------------------------------------------------------------------- ****/
2024
2025 static struct
2026 {
2027     uint32_t i_type;
2028     int  (*MP4_ReadBox_function )( MP4_Stream_t *p_stream, MP4_Box_t *p_box );
2029     void (*MP4_FreeBox_function )( input_thread_t *p_input, MP4_Box_t *p_box );
2030 } MP4_Box_Function [] =
2031 {
2032     /* Containers */
2033     { FOURCC_moov,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2034     { FOURCC_trak,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2035     { FOURCC_mdia,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2036     { FOURCC_moof,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2037     { FOURCC_minf,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2038     { FOURCC_stbl,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2039     { FOURCC_dinf,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2040     { FOURCC_edts,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2041     { FOURCC_udta,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2042     { FOURCC_nmhd,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2043     { FOURCC_hnti,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2044     { FOURCC_rmra,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2045     { FOURCC_rmda,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2046
2047     /* specific box */
2048     { FOURCC_ftyp,  MP4_ReadBox_ftyp,       MP4_FreeBox_ftyp },
2049     { FOURCC_cmov,  MP4_ReadBox_cmov,       MP4_FreeBox_Common },
2050     { FOURCC_mvhd,  MP4_ReadBox_mvhd,       MP4_FreeBox_Common },
2051     { FOURCC_tkhd,  MP4_ReadBox_tkhd,       MP4_FreeBox_Common },
2052     { FOURCC_tref,  MP4_ReadBox_tref,       MP4_FreeBox_Common },
2053     { FOURCC_mdhd,  MP4_ReadBox_mdhd,       MP4_FreeBox_Common },
2054     { FOURCC_hdlr,  MP4_ReadBox_hdlr,       MP4_FreeBox_hdlr },
2055     { FOURCC_vmhd,  MP4_ReadBox_vmhd,       MP4_FreeBox_Common },
2056     { FOURCC_smhd,  MP4_ReadBox_smhd,       MP4_FreeBox_Common },
2057     { FOURCC_hmhd,  MP4_ReadBox_hmhd,       MP4_FreeBox_Common },
2058     { FOURCC_url,   MP4_ReadBox_url,        MP4_FreeBox_url },
2059     { FOURCC_urn,   MP4_ReadBox_urn,        MP4_FreeBox_urn },
2060     { FOURCC_dref,  MP4_ReadBox_dref,       MP4_FreeBox_Common },
2061     { FOURCC_stts,  MP4_ReadBox_stts,       MP4_FreeBox_stts },
2062     { FOURCC_ctts,  MP4_ReadBox_ctts,       MP4_FreeBox_ctts },
2063     { FOURCC_stsd,  MP4_ReadBox_stsd,       MP4_FreeBox_Common },
2064     { FOURCC_stsz,  MP4_ReadBox_stsz,       MP4_FreeBox_stsz },
2065     { FOURCC_stsc,  MP4_ReadBox_stsc,       MP4_FreeBox_stsc },
2066     { FOURCC_stco,  MP4_ReadBox_stco_co64,  MP4_FreeBox_stco_co64 },
2067     { FOURCC_co64,  MP4_ReadBox_stco_co64,  MP4_FreeBox_stco_co64 },
2068     { FOURCC_stss,  MP4_ReadBox_stss,       MP4_FreeBox_stss },
2069     { FOURCC_stsh,  MP4_ReadBox_stsh,       MP4_FreeBox_stsh },
2070     { FOURCC_stdp,  MP4_ReadBox_stdp,       MP4_FreeBox_stdp },
2071     { FOURCC_padb,  MP4_ReadBox_padb,       MP4_FreeBox_padb },
2072     { FOURCC_elst,  MP4_ReadBox_elst,       MP4_FreeBox_elst },
2073     { FOURCC_cprt,  MP4_ReadBox_cprt,       MP4_FreeBox_cprt },
2074     { FOURCC_esds,  MP4_ReadBox_esds,       MP4_FreeBox_esds },
2075     { FOURCC_dcom,  MP4_ReadBox_dcom,       MP4_FreeBox_Common },
2076     { FOURCC_cmvd,  MP4_ReadBox_cmvd,       MP4_FreeBox_cmvd },
2077
2078     /* Nothing to do with this box */
2079     { FOURCC_mdat,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
2080     { FOURCC_skip,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
2081     { FOURCC_free,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
2082     { FOURCC_wide,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
2083
2084     /* for codecs */
2085     { FOURCC_soun,  MP4_ReadBox_sample_soun,    MP4_FreeBox_Common },
2086     { FOURCC__mp3,  MP4_ReadBox_sample_soun,    MP4_FreeBox_Common },
2087     { FOURCC_ms55,  MP4_ReadBox_sample_soun,    MP4_FreeBox_Common },
2088     { FOURCC_mp4a,  MP4_ReadBox_sample_soun,    MP4_FreeBox_Common },
2089     { FOURCC_twos,  MP4_ReadBox_sample_soun,    MP4_FreeBox_Common },
2090     { FOURCC_QDMC,  MP4_ReadBox_sample_soun,    MP4_FreeBox_Common },
2091     { FOURCC_raw,   MP4_ReadBox_sample_soun,    MP4_FreeBox_Common },
2092
2093     { FOURCC_vide,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2094     { FOURCC_mp4v,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2095     { FOURCC_SVQ1,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2096     { FOURCC_DIVX,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2097     { FOURCC_h263,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2098     { FOURCC_cvid,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2099     { FOURCC_3IV1,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2100     { FOURCC_3IV2,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2101     { FOURCC_mjpa,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2102     { FOURCC_mjpb,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2103     { FOURCC_mjqt,  NULL,                       NULL }, /* found in mjpa/b */
2104     { FOURCC_mjht,  NULL,                       NULL },
2105     { FOURCC_dvc,   MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2106     { FOURCC_dvp,   MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2107
2108     { FOURCC_jpeg,  MP4_ReadBox_sample_vide,    MP4_FreeBox_Common },
2109
2110     { FOURCC_mp4s,  NULL,                       MP4_FreeBox_Common },
2111
2112     /* XXX there is 2 box where we could find this entry stbl and tref*/
2113     { FOURCC_hint,  NULL,                       MP4_FreeBox_Common },
2114
2115     /* found in tref box */
2116     { FOURCC_dpnd,  NULL,   NULL },
2117     { FOURCC_ipir,  NULL,   NULL },
2118     { FOURCC_mpod,  NULL,   NULL },
2119
2120     /* found in hnti */
2121     { FOURCC_rtp,   NULL,   NULL },
2122
2123     /* found in rmra */
2124     { FOURCC_rdrf,  MP4_ReadBox_rdrf,           MP4_FreeBox_rdrf   },
2125     { FOURCC_rmdr,  MP4_ReadBox_rmdr,           MP4_FreeBox_Common },
2126     { FOURCC_rmqu,  MP4_ReadBox_rmqu,           MP4_FreeBox_Common },
2127     { FOURCC_rmvc,  MP4_ReadBox_rmvc,           MP4_FreeBox_Common },
2128
2129     /* Last entry */
2130     { 0,            NULL,                   NULL }
2131 };
2132
2133
2134
2135 /*****************************************************************************
2136  * MP4_ReadBox : parse the actual box and the children
2137  *  XXX : Do not go to the next box
2138  *****************************************************************************/
2139 int MP4_ReadBox( MP4_Stream_t *p_stream, MP4_Box_t *p_box, MP4_Box_t *p_father )
2140 {
2141     int i_result;
2142     unsigned int i_index;
2143
2144     if( !MP4_ReadBoxCommon( p_stream, p_box ) )
2145     {
2146         msg_Warn( p_stream->p_input, "Cannot read one box" );
2147         return( 0 );
2148     }
2149     if( !p_box->i_size )
2150     {
2151         msg_Dbg( p_stream->p_input, "Found an empty box (null size)" );
2152         return( 0 );
2153     }
2154     p_box->p_father = p_father;
2155
2156     /* Now search function to call */
2157     for( i_index = 0; ; i_index++ )
2158     {
2159         if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
2160             ( MP4_Box_Function[i_index].i_type == 0 ) )
2161         {
2162             break;
2163         }
2164     }
2165     if( MP4_Box_Function[i_index].MP4_ReadBox_function == NULL )
2166     {
2167         msg_Warn( p_stream->p_input,
2168                   "Unknown box type %4.4s (uncompletetly loaded)",
2169                   (char*)&p_box->i_type );
2170         return( 1 );
2171     }
2172     else
2173     {
2174         i_result =
2175            (MP4_Box_Function[i_index].MP4_ReadBox_function)( p_stream, p_box );
2176     }
2177
2178     if( !MP4_GotoBox( p_stream, p_box ) )
2179     {
2180         return( 0 );
2181     }
2182     return( i_result );
2183 }
2184 #if 0
2185 /*****************************************************************************
2186  * MP4_CountBox: given a box, count how many child have the requested type
2187  * FIXME : support GUUID
2188  *****************************************************************************/
2189 int MP4_CountBox( MP4_Box_t *p_box, uint32_t i_type )
2190 {
2191     unsigned int i_count;
2192     MP4_Box_t *p_child;
2193
2194     if( !p_box )
2195     {
2196         return( 0 );
2197     }
2198
2199     i_count = 0;
2200     p_child = p_box->p_first;
2201     while( p_child )
2202     {
2203         if( p_child->i_type == i_type )
2204         {
2205             i_count++;
2206         }
2207         p_child = p_child->p_next;
2208     }
2209
2210     return( i_count );
2211 }
2212 #endif
2213
2214 /*****************************************************************************
2215  * MP4_FindBox:  find first box with i_type child of p_box
2216  *      return NULL if not found
2217  *****************************************************************************/
2218
2219 MP4_Box_t *MP4_FindBox( MP4_Box_t *p_box, uint32_t i_type )
2220 {
2221     MP4_Box_t *p_child;
2222
2223     if( !p_box )
2224     {
2225         return( NULL );
2226     }
2227
2228     p_child = p_box->p_first;
2229     while( p_child )
2230     {
2231         if( p_child->i_type == i_type )
2232         {
2233             return( p_child );
2234         }
2235         p_child = p_child->p_next;
2236     }
2237
2238     return( NULL );
2239 }
2240
2241
2242 #if 0
2243 /*****************************************************************************
2244  * MP4_FindNextBox:  find next box with thesame type and at the same level
2245  *                  than p_box
2246  *****************************************************************************/
2247 MP4_Box_t *MP4_FindNextBox( MP4_Box_t *p_box )
2248 {
2249     MP4_Box_t *p_next;
2250
2251     if( !p_box )
2252     {
2253         return( NULL );
2254     }
2255
2256     p_next = p_box->p_next;
2257     while( p_next )
2258     {
2259         if( p_next->i_type == p_box->i_type )
2260         {
2261             return( p_next );
2262         }
2263         p_next = p_next->p_next;
2264     }
2265     return( NULL );
2266 }
2267 /*****************************************************************************
2268  * MP4_FindNbBox:  find the box i_number
2269  *****************************************************************************/
2270 MP4_Box_t *MP4_FindNbBox( MP4_Box_t *p_box, uint32_t i_number )
2271 {
2272     MP4_Box_t *p_child = p_box->p_first;
2273
2274     if( !p_child )
2275     {
2276         return( NULL );
2277     }
2278
2279     while( i_number )
2280     {
2281         if( !( p_child = p_child->p_next ) )
2282         {
2283             return( NULL );
2284         }
2285         i_number--;
2286     }
2287     return( p_child );
2288 }
2289 #endif
2290
2291 /*****************************************************************************
2292  * MP4_FreeBox : free memory after read with MP4_ReadBox and all
2293  * the children
2294  *****************************************************************************/
2295 void MP4_BoxFree( input_thread_t *p_input, MP4_Box_t *p_box )
2296 {
2297     unsigned int i_index;
2298
2299     MP4_Box_t *p_child;
2300     MP4_Box_t *p_next;
2301
2302     if( !p_box )
2303     {
2304         return; /* hehe */
2305     }
2306     p_child = p_box->p_first;
2307     while( p_child )
2308     {
2309         p_next = p_child->p_next;
2310         MP4_BoxFree( p_input, p_child );
2311         /* MP4_FreeBoxChildren have free all data expect p_child itself */
2312         free( p_child );
2313         p_child = p_next;
2314     }
2315
2316     /* Now search function to call */
2317     if( p_box->data.p_data )
2318     {
2319         for( i_index = 0; ; i_index++ )
2320         {
2321             if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
2322                 ( MP4_Box_Function[i_index].i_type == 0 ) )
2323             {
2324                 break;
2325             }
2326         }
2327         if( MP4_Box_Function[i_index].MP4_FreeBox_function == NULL )
2328         {
2329             /* Should not happen */
2330             msg_Warn( p_input,
2331                       "cannot free box %4.4s, type unknown",
2332                       (char*)&p_box->i_type );
2333         }
2334         else
2335         {
2336             MP4_Box_Function[i_index].MP4_FreeBox_function( p_input, p_box );
2337         }
2338
2339         free( p_box->data.p_data );
2340         p_box->data.p_data = NULL;
2341     }
2342
2343     p_box->p_first = NULL;
2344     p_box->p_last = NULL;
2345
2346 }
2347
2348 /*****************************************************************************
2349  * MP4_BoxGetRoot : Parse the entire file, and create all boxes in memory
2350  *****************************************************************************
2351  *  The first box is a virtual box "root" and is the father for all first
2352  *  level boxes for the file, a sort of virtual contener
2353  *****************************************************************************/
2354 int MP4_BoxGetRoot( input_thread_t *p_input, MP4_Box_t *p_root )
2355 {
2356     MP4_Stream_t *p_stream;
2357     int i_result;
2358
2359     MP4_SeekAbsolute( p_input, 0 );     /* Go to the begining */
2360     p_root->i_pos = 0;
2361     p_root->i_type = VLC_FOURCC( 'r', 'o', 'o', 't' );
2362     p_root->i_shortsize = 1;
2363     p_root->i_size = p_input->stream.p_selected_area->i_size;
2364     CreateUUID( &p_root->i_uuid, p_root->i_type );
2365
2366     p_root->data.p_data = NULL;
2367     p_root->p_father = NULL;
2368     p_root->p_first  = NULL;
2369     p_root->p_last  = NULL;
2370     p_root->p_next   = NULL;
2371
2372     p_stream = MP4_InputStream( p_input );
2373
2374     i_result = MP4_ReadBoxContainerRaw( p_stream, p_root );
2375
2376     free( p_stream );
2377
2378     if( i_result )
2379     {
2380         MP4_Box_t *p_child;
2381         MP4_Box_t *p_moov;
2382         MP4_Box_t *p_cmov;
2383
2384         /* check if there is a cmov, if so replace
2385           compressed moov by  uncompressed one */
2386         if( ( p_moov = MP4_FindBox( p_root, FOURCC_moov ) )&&
2387             ( p_cmov = MP4_FindBox( p_moov, FOURCC_cmov ) ) )
2388         {
2389             /* rename the compressed moov as a box to skip */
2390             p_moov->i_type = FOURCC_skip;
2391
2392             /* get uncompressed p_moov */
2393             p_moov = p_cmov->data.p_cmov->p_moov;
2394             p_cmov->data.p_cmov->p_moov = NULL;
2395
2396             /* make p_root father of this new moov */
2397             p_moov->p_father = p_root;
2398
2399             /* insert this new moov box as first child of p_root */
2400             p_moov->p_next = p_child = p_root->p_first;
2401             p_root->p_first = p_moov;
2402         }
2403     }
2404     return( i_result );
2405 }
2406
2407
2408 static void __MP4_BoxDumpStructure( input_thread_t *p_input,
2409                                     MP4_Box_t *p_box, unsigned int i_level )
2410 {
2411     MP4_Box_t *p_child;
2412
2413     if( !i_level )
2414     {
2415         msg_Dbg( p_input, "Dumping root Box \"%4.4s\"",
2416                           (char*)&p_box->i_type );
2417     }
2418     else
2419     {
2420         char str[512];
2421         unsigned int i;
2422         memset( str, (uint8_t)' ', 512 );
2423         for( i = 0; i < i_level; i++ )
2424         {
2425             str[i*5] = '|';
2426         }
2427         sprintf( str + i_level * 5, "+ %4.4s size %d",
2428                       (char*)&p_box->i_type,
2429                       (uint32_t)p_box->i_size );
2430
2431         msg_Dbg( p_input, "%s", str );
2432     }
2433     p_child = p_box->p_first;
2434     while( p_child )
2435     {
2436         __MP4_BoxDumpStructure( p_input, p_child, i_level + 1 );
2437         p_child = p_child->p_next;
2438     }
2439 }
2440
2441 void MP4_BoxDumpStructure( input_thread_t *p_input, MP4_Box_t *p_box )
2442 {
2443     __MP4_BoxDumpStructure( p_input, p_box, 0 );
2444 }
2445
2446
2447
2448 /*****************************************************************************
2449  *****************************************************************************
2450  **
2451  **  High level methods to acces an MP4 file
2452  **
2453  *****************************************************************************
2454  *****************************************************************************/
2455 static void __get_token( char **ppsz_path, char **ppsz_token, int *pi_number )
2456 {
2457     size_t i_len ;
2458     if( !*ppsz_path[0] )
2459     {
2460         *ppsz_token = NULL;
2461         *pi_number = 0;
2462         return;
2463     }
2464     i_len = 0;
2465     while(  (*ppsz_path)[i_len] &&
2466             (*ppsz_path)[i_len] != '/' && (*ppsz_path)[i_len] != '[' )
2467     {
2468         i_len++;
2469     }
2470     if( !i_len && **ppsz_path == '/' )
2471     {
2472         i_len = 1;
2473     }
2474     *ppsz_token = malloc( i_len + 1 );
2475
2476     memcpy( *ppsz_token, *ppsz_path, i_len );
2477
2478     (*ppsz_token)[i_len] = '\0';
2479
2480     *ppsz_path += i_len;
2481
2482     if( **ppsz_path == '[' )
2483     {
2484         (*ppsz_path)++;
2485         *pi_number = strtol( *ppsz_path, NULL, 10 );
2486         while( **ppsz_path && **ppsz_path != ']' )
2487         {
2488             (*ppsz_path)++;
2489         }
2490         if( **ppsz_path == ']' )
2491         {
2492             (*ppsz_path)++;
2493         }
2494     }
2495     else
2496     {
2497         *pi_number = 0;
2498     }
2499     while( **ppsz_path == '/' )
2500     {
2501         (*ppsz_path)++;
2502     }
2503 }
2504
2505 static void __MP4_BoxGet( MP4_Box_t **pp_result,
2506                           MP4_Box_t *p_box, char *psz_fmt, va_list args)
2507 {
2508     char    *psz_path;
2509 #if !defined(HAVE_VASPRINTF) || defined(SYS_DARWIN)
2510     size_t  i_size;
2511 #endif
2512
2513     if( !p_box )
2514     {
2515         *pp_result = NULL;
2516         return;
2517     }
2518
2519 #if defined(HAVE_VASPRINTF) && !defined(SYS_DARWIN)
2520     vasprintf( &psz_path, psz_fmt, args );
2521 #else
2522     i_size = strlen( psz_fmt ) + 1024;
2523     psz_path = calloc( i_size, sizeof( char ) );
2524     vsnprintf( psz_path, i_size, psz_fmt, args );
2525     psz_path[i_size - 1] = 0;
2526 #endif
2527
2528     if( !psz_path || !psz_path[0] )
2529     {
2530         FREE( psz_path );
2531         *pp_result = NULL;
2532         return;
2533     }
2534
2535 //    fprintf( stderr, "path:'%s'\n", psz_path );
2536     psz_fmt = psz_path; /* keep this pointer, as it need to be unallocated */
2537     for( ; ; )
2538     {
2539         char *psz_token;
2540         int i_number;
2541
2542         __get_token( &psz_path, &psz_token, &i_number );
2543 //        fprintf( stderr, "path:'%s', token:'%s' n:%d\n",
2544 //                 psz_path,psz_token,i_number );
2545         if( !psz_token )
2546         {
2547             FREE( psz_token );
2548             free( psz_fmt );
2549             *pp_result = p_box;
2550             return;
2551         }
2552         else
2553         if( !strcmp( psz_token, "/" ) )
2554         {
2555             /* Find root box */
2556             while( p_box && p_box->i_type != VLC_FOURCC( 'r', 'o', 'o', 't' ) )
2557             {
2558                 p_box = p_box->p_father;
2559             }
2560             if( !p_box )
2561             {
2562                 free( psz_token );
2563                 free( psz_fmt );
2564                 *pp_result = NULL;
2565                 return;
2566             }
2567         }
2568         else
2569         if( !strcmp( psz_token, "." ) )
2570         {
2571             /* Do nothing */
2572         }
2573         else
2574         if( !strcmp( psz_token, ".." ) )
2575         {
2576             p_box = p_box->p_father;
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( strlen( psz_token ) == 4 )
2587         {
2588             uint32_t i_fourcc;
2589             i_fourcc = VLC_FOURCC( psz_token[0], psz_token[1],
2590                                    psz_token[2], psz_token[3] );
2591             p_box = p_box->p_first;
2592             for( ; ; )
2593             {
2594                 if( !p_box )
2595                 {
2596                     free( psz_token );
2597                     free( psz_fmt );
2598                     *pp_result = NULL;
2599                     return;
2600                 }
2601                 if( p_box->i_type == i_fourcc )
2602                 {
2603                     if( !i_number )
2604                     {
2605                         break;
2606                     }
2607                     i_number--;
2608                 }
2609                 p_box = p_box->p_next;
2610             }
2611         }
2612         else
2613         if( strlen( psz_token ) == 0 )
2614         {
2615             p_box = p_box->p_first;
2616             for( ; ; )
2617             {
2618                 if( !p_box )
2619                 {
2620                     free( psz_token );
2621                     free( psz_fmt );
2622                     *pp_result = NULL;
2623                     return;
2624                 }
2625                 if( !i_number )
2626                 {
2627                     break;
2628                 }
2629                 i_number--;
2630                 p_box = p_box->p_next;
2631             }
2632         }
2633         else
2634         {
2635 //            fprintf( stderr, "Argg malformed token \"%s\"",psz_token );
2636             FREE( psz_token );
2637             free( psz_fmt );
2638             *pp_result = NULL;
2639             return;
2640         }
2641
2642         free( psz_token );
2643     }
2644 }
2645
2646 /*****************************************************************************
2647  * MP4_BoxGet: find a box given a path relative to p_box
2648  *****************************************************************************
2649  * Path Format: . .. / as usual
2650  *              [number] to specifie box number ex: trak[12]
2651  *
2652  * ex: /moov/trak[12]
2653  *     ../mdia
2654  *****************************************************************************/
2655 MP4_Box_t *MP4_BoxGet( MP4_Box_t *p_box, char *psz_fmt, ... )
2656 {
2657     va_list args;
2658     MP4_Box_t *p_result;
2659
2660     va_start( args, psz_fmt );
2661     __MP4_BoxGet( &p_result, p_box, psz_fmt, args );
2662     va_end( args );
2663
2664     return( p_result );
2665 }
2666
2667 /*****************************************************************************
2668  * MP4_BoxCount: count box given a path relative to p_box
2669  *****************************************************************************
2670  * Path Format: . .. / as usual
2671  *              [number] to specifie box number ex: trak[12]
2672  *
2673  * ex: /moov/trak[12]
2674  *     ../mdia
2675  *****************************************************************************/
2676 int MP4_BoxCount( MP4_Box_t *p_box, char *psz_fmt, ... )
2677 {
2678     va_list args;
2679     int     i_count;
2680     MP4_Box_t *p_result, *p_next;
2681
2682     va_start( args, psz_fmt );
2683     __MP4_BoxGet( &p_result, p_box, psz_fmt, args );
2684     va_end( args );
2685     if( !p_result )
2686     {
2687         return( 0 );
2688     }
2689
2690     i_count = 1;
2691     for( p_next = p_result->p_next; p_next != NULL; p_next = p_next->p_next)
2692     {
2693         if( p_next->i_type == p_result->i_type)
2694         {
2695             i_count++;
2696         }
2697     }
2698     return( i_count );
2699 }
2700