]> git.sesse.net Git - vlc/blobdiff - modules/demux/mp4/libmp4.c
* fixed several format string inconsistencies and deprecated C constructions.
[vlc] / modules / demux / mp4 / libmp4.c
index bb297ce30d5f6b7e231337d6e579160161056286..7edb0ace14534ad889e8e038ddbe80a6f4f75646 100644 (file)
@@ -2,7 +2,7 @@
  * libmp4.c : LibMP4 library for mp4 module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: libmp4.c,v 1.4 2002/08/13 11:59:36 sam Exp $
+ * $Id: libmp4.c,v 1.11 2002/12/18 14:17:10 sam Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 #include <stdlib.h>                                      /* malloc(), free() */
+#include <stdarg.h>
 #include <string.h>                                              /* strdup() */
 #include <errno.h>
 #include <sys/types.h>
@@ -60,7 +61,8 @@
     dst = GetDWBE( p_peek ); p_peek += 4; i_read -= 4
     
 #define MP4_GETFOURCC( dst ) \
-    dst = GetDWLE( p_peek ); p_peek += 4; i_read -= 4
+    dst = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] ); \
+    p_peek += 4; i_read -= 4
 
 #define MP4_GET8BYTES( dst ) \
     dst = GetQWBE( p_peek ); p_peek += 8; i_read -= 8
@@ -85,8 +87,8 @@
     
 
 #define MP4_READBOX_ENTER( MP4_Box_data_TYPE_t ) \
-    s64 i_read = p_box->i_size; \
-    u8 *p_peek, *p_buff; \
+    int64_t  i_read = p_box->i_size; \
+    uint8_t *p_peek, *p_buff; \
     i_read = p_box->i_size; \
     if( !( p_peek = p_buff = malloc( i_read ) ) ) \
     { \
       return( 0 ); \
     } 
                 
-
 #define MP4_READBOX_EXIT( i_code ) \
-    if( !i_code ) \
     free( p_buff ); \
     if( i_read < 0 ) \
     { \
 */
 
 /* Some functions to manipulate memory */
-static u16 GetWLE( u8 *p_buff )
+static uint16_t GetWLE( uint8_t *p_buff )
 {
     return( (p_buff[0]) + ( p_buff[1] <<8 ) );
 }
 
-static u32 GetDWLE( u8 *p_buff )
+static uint32_t GetDWLE( uint8_t *p_buff )
 {
     return( p_buff[0] + ( p_buff[1] <<8 ) +
             ( p_buff[2] <<16 ) + ( p_buff[3] <<24 ) );
 }
 
-static u16 GetWBE( u8 *p_buff )
+static uint16_t GetWBE( uint8_t *p_buff )
 {
     return( (p_buff[0]<<8) + p_buff[1] );
 }
 
-static u32 Get24bBE( u8 *p_buff )
+static uint32_t Get24bBE( uint8_t *p_buff )
 {
     return( ( p_buff[0] <<16 ) + ( p_buff[1] <<8 ) + p_buff[2] );
 }
 
 
-static u32 GetDWBE( u8 *p_buff )
+static uint32_t GetDWBE( uint8_t *p_buff )
 {
     return( (p_buff[0] << 24) + ( p_buff[1] <<16 ) +
             ( p_buff[2] <<8 ) + p_buff[3] );
 }
 
-static u64 GetQWBE( u8 *p_buff )
+static uint64_t GetQWBE( uint8_t *p_buff )
 {
-    return( ( (u64)GetDWBE( p_buff ) << 32 )|( (u64)GetDWBE( p_buff + 4 ) ) );
+    return( ( (uint64_t)GetDWBE( p_buff ) << 32 )|( (uint64_t)GetDWBE( p_buff + 4 ) ) );
 }
 
 
-static void GetUUID( UUID_t *p_uuid, u8 *p_buff )
+static void GetUUID( UUID_t *p_uuid, uint8_t *p_buff )
 {
     memcpy( p_uuid, 
             p_buff,
             16 );
 }
 
-static void CreateUUID( UUID_t *p_uuid, u32 i_fourcc )
+static void CreateUUID( UUID_t *p_uuid, uint32_t i_fourcc )
 {
     /* made by 0xXXXXXXXX-0011-0010-8000-00aa00389b71 
             where XXXXXXXX is the fourcc */
@@ -176,7 +176,7 @@ static void CreateUUID( UUID_t *p_uuid, u32 i_fourcc )
 
 /* some functions for mp4 encoding of variables */
 
-void MP4_ConvertDate2Str( char *psz, u64 i_date )
+void MP4_ConvertDate2Str( char *psz, uint64_t i_date )
 {
     int i_day;
     int i_hour;
@@ -210,8 +210,8 @@ off_t MP4_TellAbsolute( input_thread_t *p_input )
     
     vlc_mutex_lock( &p_input->stream.stream_lock );
     
-    i_pos= p_input->stream.p_selected_area->i_tell -
-            ( p_input->p_last_data - p_input->p_current_data  );
+    i_pos= p_input->stream.p_selected_area->i_tell;
+//            ( p_input->p_last_data - p_input->p_current_data  );
 
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 
@@ -238,7 +238,7 @@ int MP4_SeekAbsolute( input_thread_t *p_input,
 }
 
 /* return 1 if success, 0 if fail */
-int MP4_ReadData( input_thread_t *p_input, u8 *p_buff, int i_size )
+int MP4_ReadData( input_thread_t *p_input, uint8_t *p_buff, int i_size )
 {
     data_packet_t *p_data;
 
@@ -304,7 +304,7 @@ MP4_Stream_t *MP4_InputStream( input_thread_t *p_input )
  *
  ****************************************************************************/
 MP4_Stream_t *MP4_MemoryStream( input_thread_t *p_input,
-                                int i_size, u8 *p_buffer )
+                                int i_size, uint8_t *p_buffer )
 {
     MP4_Stream_t *p_stream;
 
@@ -335,7 +335,7 @@ MP4_Stream_t *MP4_MemoryStream( input_thread_t *p_input,
  * MP4_ReadStream read from a MP4_Stream_t
  *
  ****************************************************************************/
-int MP4_ReadStream( MP4_Stream_t *p_stream, u8 *p_buff, int i_size )
+int MP4_ReadStream( MP4_Stream_t *p_stream, uint8_t *p_buff, int i_size )
 {
     if( p_stream->b_memory )
     {
@@ -359,7 +359,7 @@ int MP4_ReadStream( MP4_Stream_t *p_stream, u8 *p_buff, int i_size )
  * MP4_PeekStream peek from a MP4_Stream_t
  *
  ****************************************************************************/
-int MP4_PeekStream( MP4_Stream_t *p_stream, u8 **pp_peek, int i_size )
+int MP4_PeekStream( MP4_Stream_t *p_stream, uint8_t **pp_peek, int i_size )
 {
     if( p_stream->b_memory )
     {
@@ -426,7 +426,7 @@ int MP4_SeekStream( MP4_Stream_t *p_stream, off_t i_pos)
 int MP4_ReadBoxCommon( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
     int i_read;
-    u8  *p_peek;
+    uint8_t  *p_peek;
     
     if( ( ( i_read = MP4_PeekStream( p_stream, &p_peek, 32 ) ) < 8 ) )
     {
@@ -467,13 +467,13 @@ int MP4_ReadBoxCommon( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
         CreateUUID( &p_box->i_uuid, p_box->i_type );
     }
 #ifdef MP4_VERBOSE
-    /* FIXME how to write u64 ??? */
+    /* FIXME how to write uint64_t ??? */
     if( p_box->i_size )
     {
         msg_Dbg( p_stream->p_input, "Found Box: %c%c%c%c size %d",
                  (p_box->i_type)&0xff, (p_box->i_type>>8)&0xff, 
                      (p_box->i_type>>16)&0xff, (p_box->i_type>>24)&0xff,
-                 (u32)p_box->i_size );
+                 (uint32_t)p_box->i_size );
     }
 #endif
 
@@ -534,7 +534,7 @@ int MP4_ReadBoxContainerRaw( MP4_Stream_t *p_stream, MP4_Box_t *p_container )
     MP4_Box_t *p_box;
     
     if( MP4_TellStream( p_stream ) + 8 > 
-                        p_container->i_pos + p_container->i_size  )
+                 (off_t)(p_container->i_pos + p_container->i_size) )
     {
         /* there is no box to load */
         return( 0 );
@@ -573,7 +573,7 @@ int MP4_ReadBoxContainerRaw( MP4_Stream_t *p_stream, MP4_Box_t *p_container )
 int MP4_ReadBoxContainer( MP4_Stream_t *p_stream, MP4_Box_t *p_container )
 {
     
-    if( p_container->i_size <= MP4_BOX_HEADERSIZE(p_container ) + 8 )
+    if( p_container->i_size <= (size_t)MP4_BOX_HEADERSIZE(p_container ) + 8 )
     {
         /* container is empty, 8 stand for the first header in this box */
         return( 1 );
@@ -612,9 +612,9 @@ int MP4_ReadBox_ftyp( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     
     if( ( p_box->data.p_ftyp->i_compatible_brands_count = i_read / 4 ) )
     {
-        int i;
+        unsigned int i;
         p_box->data.p_ftyp->i_compatible_brands = 
-            calloc( p_box->data.p_ftyp->i_compatible_brands_count, sizeof(u32));
+            calloc( p_box->data.p_ftyp->i_compatible_brands_count, sizeof(uint32_t));
 
         for( i =0; i < p_box->data.p_ftyp->i_compatible_brands_count; i++ )
         {
@@ -637,7 +637,7 @@ void MP4_FreeBox_ftyp( input_thread_t *p_input, MP4_Box_t *p_box )
 
 int MP4_ReadBox_mvhd(  MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
+    unsigned int i;
 #ifdef MP4_VERBOSE
     char s_creation_time[128];
     char s_modification_time[128];
@@ -698,18 +698,18 @@ int MP4_ReadBox_mvhd(  MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     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",
                   s_creation_time,
                   s_modification_time,
-                  (u32)p_box->data.p_mvhd->i_timescale,
+                  (uint32_t)p_box->data.p_mvhd->i_timescale,
                   s_duration,
                   (float)p_box->data.p_mvhd->i_rate / (1<<16 ),
                   (float)p_box->data.p_mvhd->i_volume / 256 ,
-                  (u32)p_box->data.p_mvhd->i_next_track_id );
+                  (uint32_t)p_box->data.p_mvhd->i_next_track_id );
 #endif
     MP4_READBOX_EXIT( 1 );
 }
 
 int MP4_ReadBox_tkhd(  MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
+    unsigned int i;
 #ifdef MP4_VERBOSE
     char s_creation_time[128];
     char s_modification_time[128];
@@ -773,7 +773,7 @@ int MP4_ReadBox_tkhd(  MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 int MP4_ReadBox_tref( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
 
-    if( p_box->i_size < MP4_BOX_HEADERSIZE(p_box ) + 8 )
+    if( p_box->i_size < (size_t)MP4_BOX_HEADERSIZE(p_box ) + 8 )
     {
         /* container is empty, 8 stand for the first header in this box */
         return( 1 );
@@ -797,8 +797,8 @@ int MP4_ReadBox_tref( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 
 int MP4_ReadBox_mdhd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
-    u16 i_language;
+    unsigned int i;
+    uint16_t i_language;
 #ifdef MP4_VERBOSE
     char s_creation_time[128];
     char s_modification_time[128];
@@ -838,7 +838,7 @@ int MP4_ReadBox_mdhd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     msg_Dbg( p_stream->p_input, "Read Box: \"mdhd\" creation %s modification %s time scale %d duration %s language %c%c%c",
                   s_creation_time,
                   s_modification_time,
-                  (u32)p_box->data.p_mdhd->i_timescale,
+                  (uint32_t)p_box->data.p_mdhd->i_timescale,
                   s_duration,
                   p_box->data.p_mdhd->i_language[0],
                   p_box->data.p_mdhd->i_language[1],
@@ -879,7 +879,7 @@ void MP4_FreeBox_hdlr( input_thread_t *p_input, MP4_Box_t *p_box )
 
 int MP4_ReadBox_vmhd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
+    unsigned int i;
    
     MP4_READBOX_ENTER( MP4_Box_data_vmhd_t ); 
 
@@ -1014,16 +1014,16 @@ int MP4_ReadBox_dref( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 
 int MP4_ReadBox_stts( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
+    unsigned int i;
     MP4_READBOX_ENTER( MP4_Box_data_stts_t ); 
 
     MP4_GETVERSIONFLAGS( p_box->data.p_stts );
     MP4_GET4BYTES( p_box->data.p_stts->i_entry_count );
 
     p_box->data.p_stts->i_sample_count = 
-        calloc( sizeof( u32 ), p_box->data.p_stts->i_entry_count );
+        calloc( sizeof( uint32_t ), p_box->data.p_stts->i_entry_count );
     p_box->data.p_stts->i_sample_delta =
-        calloc( sizeof( u32 ), p_box->data.p_stts->i_entry_count );
+        calloc( sizeof( uint32_t ), p_box->data.p_stts->i_entry_count );
     
     for( i = 0; (i < p_box->data.p_stts->i_entry_count )&&( i_read >=8 ); i++ )
     {
@@ -1049,7 +1049,7 @@ void MP4_FreeBox_stts( input_thread_t *p_input, MP4_Box_t *p_box )
 
 int MP4_ReadBox_ctts( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
+    unsigned int i;
     MP4_READBOX_ENTER( MP4_Box_data_ctts_t );
     
     MP4_GETVERSIONFLAGS( p_box->data.p_ctts );
@@ -1057,9 +1057,9 @@ int MP4_ReadBox_ctts( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     MP4_GET4BYTES( p_box->data.p_ctts->i_entry_count );
 
     p_box->data.p_ctts->i_sample_count = 
-        calloc( sizeof( u32 ), p_box->data.p_ctts->i_entry_count );
+        calloc( sizeof( uint32_t ), p_box->data.p_ctts->i_entry_count );
     p_box->data.p_ctts->i_sample_offset =
-        calloc( sizeof( u32 ), p_box->data.p_ctts->i_entry_count );
+        calloc( sizeof( uint32_t ), p_box->data.p_ctts->i_entry_count );
     
     for( i = 0; (i < p_box->data.p_ctts->i_entry_count )&&( i_read >=8 ); i++ )
     {
@@ -1082,10 +1082,10 @@ void MP4_FreeBox_ctts( input_thread_t *p_input, MP4_Box_t *p_box )
     FREE( p_box->data.p_ctts->i_sample_offset );
 }
 
-static int MP4_ReadLengthDescriptor( u8 **pp_peek, s64 *i_read )
+static int MP4_ReadLengthDescriptor( uint8_t **pp_peek, int64_t  *i_read )
 {
-    int i_b;
-    int i_len = 0;
+    unsigned int i_b;
+    unsigned int i_len = 0;
     do
     {
         i_b = **pp_peek;
@@ -1100,9 +1100,9 @@ static int MP4_ReadLengthDescriptor( u8 **pp_peek, s64 *i_read )
 int MP4_ReadBox_esds( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
 #define es_descriptor p_box->data.p_esds->es_descriptor
-    int i_len;
-    int i_flags;
-    int i_type;
+    unsigned int i_len;
+    unsigned int i_flags;
+    unsigned int i_type;
 
     MP4_READBOX_ENTER( MP4_Box_data_esds_t );
 
@@ -1127,7 +1127,7 @@ int MP4_ReadBox_esds( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
         }
         if( es_descriptor.b_url )
         {
-            int i_len;
+            unsigned int i_len;
         
             MP4_GET1BYTE( i_len );
             es_descriptor.psz_URL = calloc( sizeof(char), i_len + 1 );
@@ -1188,7 +1188,7 @@ void MP4_FreeBox_esds( input_thread_t *p_input, MP4_Box_t *p_box )
 
 int MP4_ReadBox_sample_soun( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;    
+    unsigned int i;    
     
     MP4_READBOX_ENTER( MP4_Box_data_sample_soun_t );
 
@@ -1228,7 +1228,7 @@ int MP4_ReadBox_sample_soun( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 #if 0
 int MP4_ReadBox_sample_mp4a( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;    
+    unsigned int i;    
 
     MP4_READBOX_ENTER( MP4_Box_data_sample_mp4a_t );
     
@@ -1268,7 +1268,7 @@ int MP4_ReadBox_sample_mp4a( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 
 int MP4_ReadBox_sample_vide( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;    
+    unsigned int i;    
 
     MP4_READBOX_ENTER( MP4_Box_data_sample_vide_t );
 
@@ -1340,7 +1340,7 @@ int MP4_ReadBox_stsd( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 
 int MP4_ReadBox_stsz( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
+    unsigned int i;
 
     MP4_READBOX_ENTER( MP4_Box_data_stsz_t );
     
@@ -1351,7 +1351,7 @@ int MP4_ReadBox_stsz( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     MP4_GET4BYTES( p_box->data.p_stsz->i_sample_count );
 
     p_box->data.p_stsz->i_entry_size = 
-        calloc( sizeof( u32 ), p_box->data.p_stsz->i_sample_count );
+        calloc( sizeof( uint32_t ), p_box->data.p_stsz->i_sample_count );
     
     if( !p_box->data.p_stsz->i_sample_size )
     {
@@ -1378,7 +1378,7 @@ void MP4_FreeBox_stsz( input_thread_t *p_input, MP4_Box_t *p_box )
 
 int MP4_ReadBox_stsc( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
+    unsigned int i;
     
     MP4_READBOX_ENTER( MP4_Box_data_stsc_t );
 
@@ -1387,11 +1387,11 @@ int MP4_ReadBox_stsc( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     MP4_GET4BYTES( p_box->data.p_stsc->i_entry_count );
 
     p_box->data.p_stsc->i_first_chunk = 
-        calloc( sizeof( u32 ), p_box->data.p_stsc->i_entry_count );
+        calloc( sizeof( uint32_t ), p_box->data.p_stsc->i_entry_count );
     p_box->data.p_stsc->i_samples_per_chunk = 
-        calloc( sizeof( u32 ), p_box->data.p_stsc->i_entry_count );
+        calloc( sizeof( uint32_t ), p_box->data.p_stsc->i_entry_count );
     p_box->data.p_stsc->i_sample_description_index = 
-        calloc( sizeof( u32 ), p_box->data.p_stsc->i_entry_count );
+        calloc( sizeof( uint32_t ), p_box->data.p_stsc->i_entry_count );
 
     for( i = 0; (i < p_box->data.p_stsc->i_entry_count )&&( i_read >= 12 );i++ )
     {
@@ -1418,7 +1418,7 @@ void MP4_FreeBox_stsc( input_thread_t *p_input, MP4_Box_t *p_box )
 
 int MP4_ReadBox_stco_co64( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
+    unsigned int i;
     
     MP4_READBOX_ENTER( MP4_Box_data_co64_t );
 
@@ -1427,16 +1427,24 @@ int MP4_ReadBox_stco_co64( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     MP4_GET4BYTES( p_box->data.p_co64->i_entry_count );
 
     p_box->data.p_co64->i_chunk_offset = 
-        calloc( sizeof( u64 ), p_box->data.p_co64->i_entry_count );
+        calloc( sizeof( uint64_t ), p_box->data.p_co64->i_entry_count );
 
-    for( i = 0; (i < p_box->data.p_co64->i_entry_count )&&( i_read >= 8 ); i++ )
+    for( i = 0; i < p_box->data.p_co64->i_entry_count; i++ )
     {
         if( p_box->i_type == FOURCC_stco )
         {
+            if( i_read < 4 )
+            {
+                break;
+            }
             MP4_GET4BYTES( p_box->data.p_co64->i_chunk_offset[i] );
         }
         else
         {
+            if( i_read < 8 )
+            {
+                break;
+            }
             MP4_GET8BYTES( p_box->data.p_co64->i_chunk_offset[i] );
         }
     }
@@ -1457,7 +1465,7 @@ void MP4_FreeBox_stco_co64( input_thread_t *p_input, MP4_Box_t *p_box )
 
 int MP4_ReadBox_stss( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
+    unsigned int i;
     
     MP4_READBOX_ENTER( MP4_Box_data_stss_t ); 
 
@@ -1466,12 +1474,14 @@ int MP4_ReadBox_stss( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     MP4_GET4BYTES( p_box->data.p_stss->i_entry_count );
 
     p_box->data.p_stss->i_sample_number = 
-        calloc( sizeof( u32 ), p_box->data.p_stss->i_entry_count );
+        calloc( sizeof( uint32_t ), p_box->data.p_stss->i_entry_count );
 
     for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 4 ); i++ )
     {
 
         MP4_GET4BYTES( p_box->data.p_stss->i_sample_number[i] );
+        /* XXX in libmp4 sample begin at 0 */
+        p_box->data.p_stss->i_sample_number[i]--;
     }
     
     
@@ -1490,7 +1500,7 @@ void MP4_FreeBox_stss( input_thread_t *p_input, MP4_Box_t *p_box )
 
 int MP4_ReadBox_stsh( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
+    unsigned int i;
     
     MP4_READBOX_ENTER( MP4_Box_data_stsh_t );
 
@@ -1500,10 +1510,10 @@ int MP4_ReadBox_stsh( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     MP4_GET4BYTES( p_box->data.p_stsh->i_entry_count );
 
     p_box->data.p_stsh->i_shadowed_sample_number = 
-        calloc( sizeof( u32 ), p_box->data.p_stsh->i_entry_count );
+        calloc( sizeof( uint32_t ), p_box->data.p_stsh->i_entry_count );
 
     p_box->data.p_stsh->i_sync_sample_number = 
-        calloc( sizeof( u32 ), p_box->data.p_stsh->i_entry_count );
+        calloc( sizeof( uint32_t ), p_box->data.p_stsh->i_entry_count );
 
 
     for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 8 ); i++ )
@@ -1530,14 +1540,14 @@ void MP4_FreeBox_stsh( input_thread_t *p_input, MP4_Box_t *p_box )
 
 int MP4_ReadBox_stdp( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
+    unsigned int i;
    
     MP4_READBOX_ENTER( MP4_Box_data_stdp_t ); 
 
     MP4_GETVERSIONFLAGS( p_box->data.p_stdp );
 
     p_box->data.p_stdp->i_priority = 
-        calloc( sizeof( u16 ), i_read / 2 );
+        calloc( sizeof( uint16_t ), i_read / 2 );
 
     for( i = 0; i < i_read / 2 ; i++ )
     {
@@ -1547,7 +1557,7 @@ int MP4_ReadBox_stdp( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     
     
 #ifdef MP4_VERBOSE 
-    msg_Dbg( p_stream->p_input, "Read Box: \"stdp\" entry-count %d",
+    msg_Dbg( p_stream->p_input, "Read Box: \"stdp\" entry-count "I64Fd,
                       i_read / 2 );
 
 #endif
@@ -1561,7 +1571,7 @@ void MP4_FreeBox_stdp( input_thread_t *p_input, MP4_Box_t *p_box )
 
 int MP4_ReadBox_padb( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
+    unsigned int i;
     
     MP4_READBOX_ENTER( MP4_Box_data_padb_t );
 
@@ -1571,13 +1581,13 @@ int MP4_ReadBox_padb( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     MP4_GET4BYTES( p_box->data.p_padb->i_sample_count );
 
     p_box->data.p_padb->i_reserved1 = 
-        calloc( sizeof( u16 ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
+        calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
     p_box->data.p_padb->i_pad2 = 
-        calloc( sizeof( u16 ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
+        calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
     p_box->data.p_padb->i_reserved2 = 
-        calloc( sizeof( u16 ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
+        calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
     p_box->data.p_padb->i_pad1 = 
-        calloc( sizeof( u16 ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
+        calloc( sizeof( uint16_t ), ( p_box->data.p_padb->i_sample_count + 1 ) / 2 );
 
 
     for( i = 0; i < i_read / 2 ; i++ )
@@ -1592,7 +1602,7 @@ int MP4_ReadBox_padb( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     
     
 #ifdef MP4_VERBOSE 
-    msg_Dbg( p_stream->p_input, "Read Box: \"stdp\" entry-count %d",
+    msg_Dbg( p_stream->p_input, "Read Box: \"stdp\" entry-count "I64Fd,
                       i_read / 2 );
 
 #endif
@@ -1609,7 +1619,7 @@ void MP4_FreeBox_padb( input_thread_t *p_input, MP4_Box_t *p_box )
 
 int MP4_ReadBox_elst( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i;
+    unsigned int i;
     
     MP4_READBOX_ENTER( MP4_Box_data_padb_t );
 
@@ -1619,13 +1629,13 @@ int MP4_ReadBox_elst( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     MP4_GET4BYTES( p_box->data.p_elst->i_entry_count );
 
     p_box->data.p_elst->i_segment_duration =
-        calloc( sizeof( u64 ), p_box->data.p_elst->i_entry_count );
+        calloc( sizeof( uint64_t ), p_box->data.p_elst->i_entry_count );
     p_box->data.p_elst->i_media_time =
-        calloc( sizeof( u64 ), p_box->data.p_elst->i_entry_count );
+        calloc( sizeof( uint64_t ), p_box->data.p_elst->i_entry_count );
     p_box->data.p_elst->i_media_rate_integer =
-        calloc( sizeof( u16 ), p_box->data.p_elst->i_entry_count );
+        calloc( sizeof( uint16_t ), p_box->data.p_elst->i_entry_count );
     p_box->data.p_elst->i_media_rate_fraction= 
-        calloc( sizeof( u16 ), p_box->data.p_elst->i_entry_count );
+        calloc( sizeof( uint16_t ), p_box->data.p_elst->i_entry_count );
 
 
     for( i = 0; i < p_box->data.p_elst->i_entry_count; i++ )
@@ -1651,7 +1661,7 @@ int MP4_ReadBox_elst( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     
     
 #ifdef MP4_VERBOSE 
-    msg_Dbg( p_stream->p_input, "Read Box: \"elst\" entry-count %d",
+    msg_Dbg( p_stream->p_input, "Read Box: \"elst\" entry-count "I64Fd,
                       i_read / 2 );
 
 #endif
@@ -1668,8 +1678,8 @@ void MP4_FreeBox_elst( input_thread_t *p_input, MP4_Box_t *p_box )
 
 int MP4_ReadBox_cprt( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 {
-    int i_language;
-    int i;
+    unsigned int i_language;
+    unsigned int i;
     
     MP4_READBOX_ENTER( MP4_Box_data_cprt_t );
 
@@ -1763,7 +1773,7 @@ int MP4_ReadBox_cmov( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 #ifdef HAVE_ZLIB_H
     z_stream  z_data;
 #endif
-    u8 *p_data;
+    uint8_t *p_data;
     
     int i_result;
 
@@ -1896,7 +1906,7 @@ int MP4_ReadBox_cmov( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
 
 static struct 
 {
-    u32 i_type;
+    uint32_t i_type;
     int  (*MP4_ReadBox_function )( MP4_Stream_t *p_stream, MP4_Box_t *p_box ); 
     void (*MP4_FreeBox_function )( input_thread_t *p_input, MP4_Box_t *p_box );
 } MP4_Box_Function [] =
@@ -1999,7 +2009,7 @@ static struct
 int MP4_ReadBox( MP4_Stream_t *p_stream, MP4_Box_t *p_box, MP4_Box_t *p_father )
 {
     int i_result;
-    int i_index;
+    unsigned int i_index;
     
     if( !MP4_ReadBoxCommon( p_stream, p_box ) )
     {
@@ -2044,14 +2054,120 @@ int MP4_ReadBox( MP4_Stream_t *p_stream, MP4_Box_t *p_box, MP4_Box_t *p_father )
     }
     return( i_result );
 }
+#if 0
+/*****************************************************************************
+ * MP4_CountBox: given a box, count how many child have the requested type 
+ * FIXME : support GUUID 
+ *****************************************************************************/
+int MP4_CountBox( MP4_Box_t *p_box, uint32_t i_type )
+{
+    unsigned int i_count;
+    MP4_Box_t *p_child;
+    
+    if( !p_box )
+    {
+        return( 0 );
+    }
+
+    i_count = 0;
+    p_child = p_box->p_first;
+    while( p_child )
+    {
+        if( p_child->i_type == i_type )
+        {   
+            i_count++;
+        }
+        p_child = p_child->p_next;
+    }
+    
+    return( i_count );
+}
+#endif
+
+/*****************************************************************************
+ * MP4_FindBox:  find first box with i_type child of p_box
+ *      return NULL if not found
+ *****************************************************************************/
+
+MP4_Box_t *MP4_FindBox( MP4_Box_t *p_box, uint32_t i_type )
+{
+    MP4_Box_t *p_child;
+    
+    if( !p_box )
+    {
+        return( NULL );
+    }
+
+    p_child = p_box->p_first;
+    while( p_child )
+    {
+        if( p_child->i_type == i_type )
+        {   
+            return( p_child );
+        }
+        p_child = p_child->p_next;
+    }
+    
+    return( NULL );
+}
+
+
+#if 0
+/*****************************************************************************
+ * MP4_FindNextBox:  find next box with thesame type and at the same level 
+ *                  than p_box
+ *****************************************************************************/
+MP4_Box_t *MP4_FindNextBox( MP4_Box_t *p_box )
+{
+    MP4_Box_t *p_next;
+    
+    if( !p_box )
+    {
+        return( NULL );
+    }
+
+    p_next = p_box->p_next;
+    while( p_next )
+    {
+        if( p_next->i_type == p_box->i_type )
+        {
+            return( p_next );
+        }
+        p_next = p_next->p_next;
+    }
+    return( NULL );
+}
+/*****************************************************************************
+ * MP4_FindNbBox:  find the box i_number
+ *****************************************************************************/
+MP4_Box_t *MP4_FindNbBox( MP4_Box_t *p_box, uint32_t i_number )
+{
+    MP4_Box_t *p_child = p_box->p_first;
+    
+    if( !p_child )
+    {
+        return( NULL );
+    }
+
+    while( i_number )
+    {
+        if( !( p_child = p_child->p_next ) )
+        {
+            return( NULL );
+        }
+        i_number--;
+    }
+    return( p_child );
+}
+#endif
 
 /*****************************************************************************
  * MP4_FreeBox : free memory after read with MP4_ReadBox and all 
  * the children
  *****************************************************************************/
-void MP4_FreeBox( input_thread_t *p_input, MP4_Box_t *p_box )
+void MP4_BoxFree( input_thread_t *p_input, MP4_Box_t *p_box )
 {
-    int i_index;
+    unsigned int i_index;
 
     MP4_Box_t *p_child;
     MP4_Box_t *p_next;
@@ -2064,7 +2180,7 @@ void MP4_FreeBox( input_thread_t *p_input, MP4_Box_t *p_box )
     while( p_child )
     {
         p_next = p_child->p_next;
-        MP4_FreeBox( p_input, p_child );
+        MP4_BoxFree( p_input, p_child );
         /* MP4_FreeBoxChildren have free all data expect p_child itself */
         free( p_child );
         p_child = p_next; 
@@ -2106,12 +2222,12 @@ void MP4_FreeBox( input_thread_t *p_input, MP4_Box_t *p_box )
 }
 
 /*****************************************************************************
- * MP4_ReadRoot : Parse the entire file, and create all boxes in memory
+ * MP4_BoxGetRoot : Parse the entire file, and create all boxes in memory
  *****************************************************************************
  *  The first box is a virtual box "root" and is the father for all first 
  *  level boxes for the file, a sort of virtual contener
  *****************************************************************************/
-int MP4_ReadBoxRoot( input_thread_t *p_input, MP4_Box_t *p_root )
+int MP4_BoxGetRoot( input_thread_t *p_input, MP4_Box_t *p_root )
 {
     
     MP4_Stream_t *p_stream;
@@ -2166,8 +2282,8 @@ int MP4_ReadBoxRoot( input_thread_t *p_input, MP4_Box_t *p_root )
 }
 
 
-static void __MP4_DumpBoxStructure( input_thread_t *p_input,
-                                    MP4_Box_t *p_box, int i_level )
+static void __MP4_BoxDumpStructure( input_thread_t *p_input,
+                                    MP4_Box_t *p_box, unsigned int i_level )
 {
     MP4_Box_t *p_child;
 
@@ -2182,8 +2298,8 @@ static void __MP4_DumpBoxStructure( input_thread_t *p_input,
     else
     {
         char str[512];
-        int i;
-        memset( str, (u8)' ', 512 );
+        unsigned int i;
+        memset( str, (uint8_t)' ', 512 );
         for( i = 0; i < i_level; i++ )
         {
             str[i*5] = '|';
@@ -2193,127 +2309,278 @@ static void __MP4_DumpBoxStructure( input_thread_t *p_input,
                       (p_box->i_type>>8 ) &0xff,
                       (p_box->i_type>>16 ) &0xff,
                       (p_box->i_type>>24 ) &0xff,
-                      (u32)p_box->i_size );
+                      (uint32_t)p_box->i_size );
         
         msg_Dbg( p_input, "%s", str );
     }
     p_child = p_box->p_first;
     while( p_child )
     {
-        __MP4_DumpBoxStructure( p_input, p_child, i_level + 1 );
+        __MP4_BoxDumpStructure( p_input, p_child, i_level + 1 );
         p_child = p_child->p_next;
     }
     
 }
 
-void MP4_DumpBoxStructure( input_thread_t *p_input, MP4_Box_t *p_box )
+void MP4_BoxDumpStructure( input_thread_t *p_input, MP4_Box_t *p_box )
 {
-    __MP4_DumpBoxStructure( p_input, p_box, 0 );
+    __MP4_BoxDumpStructure( p_input, p_box, 0 );
 }
 
 
+
 /*****************************************************************************
- * MP4_CountBox: given a box, count how many child have the requested type 
- * FIXME : support GUUID 
+ *****************************************************************************
+ **
+ **  High level methods to acces an MP4 file
+ **
+ *****************************************************************************
  *****************************************************************************/
-int MP4_CountBox( MP4_Box_t *p_box, u32 i_type )
+static void __get_token( char **ppsz_path, char **ppsz_token, int *pi_number )
 {
-    int i_count;
-    MP4_Box_t *p_child;
-    
-    if( !p_box )
+    size_t i_len ;
+    if( !*ppsz_path[0] )
     {
-        return( 0 );
+        *ppsz_token = NULL;
+        *pi_number = 0;
+        return;
+    }
+    i_len = 0;
+    while(  (*ppsz_path)[i_len] && 
+            (*ppsz_path)[i_len] != '/' && (*ppsz_path)[i_len] != '[' )
+    {
+        i_len++;
+    }
+    if( !i_len && **ppsz_path == '/' )
+    {
+        i_len = 1;
     }
+    *ppsz_token = malloc( i_len + 1 );
+        
+    memcpy( *ppsz_token, *ppsz_path, i_len );
 
-    i_count = 0;
-    p_child = p_box->p_first;
-    while( p_child )
+    (*ppsz_token)[i_len] = '\0';
+
+    *ppsz_path += i_len;
+        
+    if( **ppsz_path == '[' )
     {
-        if( p_child->i_type == i_type )
-        {   
-            i_count++;
+        (*ppsz_path)++;
+        *pi_number = strtol( *ppsz_path, NULL, 10 );
+        while( **ppsz_path && **ppsz_path != ']' )
+        {
+            (*ppsz_path)++;
+        }
+        if( **ppsz_path == ']' )
+        {
+            (*ppsz_path)++;
         }
-        p_child = p_child->p_next;
     }
-    
-    return( i_count );
+    else
+    {
+        *pi_number = 0;
+    }
+    while( **ppsz_path == '/' )
+    {
+        (*ppsz_path)++;
+    }
 }
 
-
-/*****************************************************************************
- * MP4_FindBox:  find first box with i_type child of p_box
- *      return NULL if not found
- *****************************************************************************/
-
-MP4_Box_t *MP4_FindBox( MP4_Box_t *p_box, u32 i_type )
+static void __MP4_BoxGet( MP4_Box_t **pp_result,
+                          MP4_Box_t *p_box, char *psz_fmt, va_list args)
 {
-    MP4_Box_t *p_child;
+    char    *psz_path;
+#if !defined(HAVE_VASPRINTF) || defined(SYS_DARWIN)
+    size_t  i_size;
+#endif
+
     
     if( !p_box )
     {
-        return( NULL );
+        *pp_result = NULL;
+        return;
     }
 
-    p_child = p_box->p_first;
-    while( p_child )
+#if defined(HAVE_VASPRINTF) && !defined(SYS_DARWIN)
+    vasprintf( &psz_path, psz_fmt, args );
+#else
+    i_size = strlen( psz_fmt ) + 1024;
+    psz_path = calloc( i_size, sizeof( char ) );
+    vsnprintf( psz_path, i_size, psz_fmt, args );
+    psz_path[i_size - 1] = 0;
+#endif
+
+    if( !psz_path || !psz_path[0] )
     {
-        if( p_child->i_type == i_type )
-        {   
-            return( p_child );
+        FREE( psz_path );
+        *pp_result = NULL;
+        return;
+    }
+
+//    fprintf( stderr, "path:'%s'\n", psz_path );
+    psz_fmt = psz_path; /* keep this pointer, as it need to be unallocated */
+    for( ; ; )
+    {
+        char *psz_token;
+        int i_number;
+
+        __get_token( &psz_path, &psz_token, &i_number );
+//        fprintf( stderr, "path:'%s', token:'%s' n:%d\n", 
+//                 psz_path,psz_token,i_number );
+        if( !psz_token )
+        {
+            FREE( psz_token );
+            free( psz_fmt );
+            *pp_result = p_box;
+            return;
         }
-        p_child = p_child->p_next;
+        else
+        if( !strcmp( psz_token, "/" ) )
+        {
+            /* Find root box */
+            while( p_box && p_box->i_type != VLC_FOURCC( 'r', 'o', 'o', 't' ) )
+            {
+                p_box = p_box->p_father;
+            }
+            if( !p_box )
+            {
+                free( psz_token );
+                free( psz_fmt );
+                *pp_result = NULL;
+                return;
+            }
+        }
+        else
+        if( !strcmp( psz_token, "." ) )
+        {
+            /* Do nothing */
+        }
+        else
+        if( !strcmp( psz_token, ".." ) )
+        {
+            p_box = p_box->p_father;
+            if( !p_box )
+            {
+                free( psz_token );
+                free( psz_fmt );
+                *pp_result = NULL;
+                return;
+            }
+        }
+        else
+        if( strlen( psz_token ) == 4 )
+        {
+            uint32_t i_fourcc;
+            i_fourcc = VLC_FOURCC( psz_token[0], psz_token[1],
+                                   psz_token[2], psz_token[3] );
+            p_box = p_box->p_first;
+            for( ; ; )
+            {
+                if( !p_box )
+                {
+                    free( psz_token );
+                    free( psz_fmt );
+                    *pp_result = NULL;
+                    return;
+                }
+                if( p_box->i_type == i_fourcc )
+                {
+                    if( !i_number )
+                    {
+                        break;
+                    }
+                    i_number--;
+                }
+                p_box = p_box->p_next;
+            }
+        }
+        else
+        if( strlen( psz_token ) == 0 )
+        {
+            p_box = p_box->p_first;
+            for( ; ; )
+            {
+                if( !p_box )
+                {
+                    free( psz_token );
+                    free( psz_fmt );
+                    *pp_result = NULL;
+                    return;
+                }
+                if( !i_number )
+                {
+                    break;
+                }
+                i_number--;
+                p_box = p_box->p_next;
+            }
+        }
+        else
+        {
+//            fprintf( stderr, "Argg malformed token \"%s\"",psz_token );
+            FREE( psz_token );
+            free( psz_fmt );
+            *pp_result = NULL;
+            return;
+        }
+        
+        free( psz_token );
     }
     
-    return( NULL );
 }
 
-
 /*****************************************************************************
- * MP4_FindNextBox:  find next box with thesame type and at the same level 
- *                  than p_box
+ * MP4_BoxGet: find a box given a path relative to p_box
+ *****************************************************************************
+ * Path Format: . .. / as usual
+ *              [number] to specifie box number ex: trak[12]
+ *              
+ * ex: /moov/trak[12]
+ *     ../mdia
  *****************************************************************************/
-MP4_Box_t *MP4_FindNextBox( MP4_Box_t *p_box )
+MP4_Box_t *MP4_BoxGet( MP4_Box_t *p_box, char *psz_fmt, ... )
 {
-    MP4_Box_t *p_next;
-    
-    if( !p_box )
-    {
-        return( NULL );
-    }
+    va_list args;
+    MP4_Box_t *p_result;
 
-    p_next = p_box->p_next;
-    while( p_next )
-    {
-        if( p_next->i_type == p_box->i_type )
-        {
-            return( p_next );
-        }
-        p_next = p_next->p_next;
-    }
-    return( NULL );
+    va_start( args, psz_fmt ); 
+    __MP4_BoxGet( &p_result, p_box, psz_fmt, args );
+    va_end( args );
+
+    return( p_result );
 }
 
 /*****************************************************************************
- * MP4_FindNbBox:  find the box i_number
+ * MP4_BoxCount: count box given a path relative to p_box
+ *****************************************************************************
+ * Path Format: . .. / as usual
+ *              [number] to specifie box number ex: trak[12]
+ *              
+ * ex: /moov/trak[12]
+ *     ../mdia
  *****************************************************************************/
-MP4_Box_t *MP4_FindNbBox( MP4_Box_t *p_box, u32 i_number )
+int MP4_BoxCount( MP4_Box_t *p_box, char *psz_fmt, ... )
 {
-    MP4_Box_t *p_child = p_box->p_first;
-    
-    if( !p_child )
+    va_list args;
+    int     i_count;
+    MP4_Box_t *p_result, *p_next;
+
+    va_start( args, psz_fmt ); 
+    __MP4_BoxGet( &p_result, p_box, psz_fmt, args );
+    va_end( args );
+    if( !p_result )
     {
-        return( NULL );
+        return( 0 );
     }
-
-    while( i_number )
+    
+    i_count = 1;
+    for( p_next = p_result->p_next; p_next != NULL; p_next = p_next->p_next)
     {
-        if( !( p_child = p_child->p_next ) )
+        if( p_next->i_type == p_result->i_type)
         {
-            return( NULL );
+            i_count++;
         }
-        i_number--;
     }
-    return( p_child );
+    return( i_count );
 }