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