]> git.sesse.net Git - vlc/commitdiff
* all: - fix a memory leak while parsing.
authorLaurent Aimar <fenrir@videolan.org>
Tue, 17 Sep 2002 11:57:38 +0000 (11:57 +0000)
committerLaurent Aimar <fenrir@videolan.org>
Tue, 17 Sep 2002 11:57:38 +0000 (11:57 +0000)
        - fix a bug while playing last frames (in last chunk).
        - add seek support, not complete but usable.

modules/demux/mp4/libmp4.c
modules/demux/mp4/libmp4.h
modules/demux/mp4/mp4.c
modules/demux/mp4/mp4.h

index bb297ce30d5f6b7e231337d6e579160161056286..0f77df7d3569b6b10671335bf1c938b6347241c0 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.5 2002/09/17 11:57:38 fenrir 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>
       return( 0 ); \
     } 
                 
-
 #define MP4_READBOX_EXIT( i_code ) \
-    if( !i_code ) \
     free( p_buff ); \
     if( i_read < 0 ) \
     { \
@@ -1429,14 +1428,22 @@ int MP4_ReadBox_stco_co64( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     p_box->data.p_co64->i_chunk_offset = 
         calloc( sizeof( u64 ), 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] );
         }
     }
@@ -1472,6 +1479,8 @@ int MP4_ReadBox_stss( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
     {
 
         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]--;
     }
     
     
@@ -2044,12 +2053,118 @@ 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, u32 i_type )
+{
+    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, u32 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, u32 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;
 
@@ -2064,7 +2179,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 +2221,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,7 +2281,7 @@ int MP4_ReadBoxRoot( input_thread_t *p_input, MP4_Box_t *p_root )
 }
 
 
-static void __MP4_DumpBoxStructure( input_thread_t *p_input,
+static void __MP4_BoxDumpStructure( input_thread_t *p_input,
                                     MP4_Box_t *p_box, int i_level )
 {
     MP4_Box_t *p_child;
@@ -2200,120 +2315,271 @@ static void __MP4_DumpBoxStructure( input_thread_t *p_input,
     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 )
+    int 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;
+#ifndef HAVE_VASPRINTF
+    int     i_size;
+#endif
+
     
     if( !p_box )
     {
-        return( NULL );
+        *pp_result = NULL;
+        return;
     }
 
-    p_child = p_box->p_first;
-    while( p_child )
+#ifdef HAVE_VASPRINTF
+    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 )
+        {
+            u32 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 );
 }
 
index 7c5921ad5fa654618f28899dd8556b6435c1c22d..5f25e1837e5da3922c5cb966d7fb47b4ed6570d9 100644 (file)
@@ -2,7 +2,7 @@
  * libmp4.h : LibMP4 library for mp4 module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: libmp4.h,v 1.2 2002/08/08 22:28:22 sam Exp $
+ * $Id: libmp4.h,v 1.3 2002/09/17 11:57:38 fenrir Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -647,7 +647,8 @@ typedef struct MP4_Box_s
     
     u64     i_size; /* always set so use it */
 
-    MP4_Box_data_t   data;   /* union of pointers on extended data depending on i_type (or i_usertype) */
+    MP4_Box_data_t   data;   /* union of pointers on extended data depending    
+                                on i_type (or i_usertype) */
 
     struct MP4_Box_s *p_father; /* pointer on the father Box */
 
@@ -659,7 +660,9 @@ typedef struct MP4_Box_s
 } MP4_Box_t;
 
 /*---------------------------------------------------------------------------*/
+/*                                                                           */
 /****----------------------- High level functions ------------------------****/
+/*                                                                           */
 /*---------------------------------------------------------------------------*/
 
 /*****************************************************************************
@@ -671,40 +674,76 @@ int   MP4_SeekAbsolute( input_thread_t *p_input, off_t i_pos);
 int   MP4_ReadData( input_thread_t *p_input, u8 *p_buff, int i_size );
 
 /*****************************************************************************
- * 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 
  *
  *  RETURN : 1 if succes and 0 if it failed
  *****************************************************************************/
-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_FreeBox : free memory allocated after read with MP4_ReadBox
- *               this, means also children boxes
+ *               or MP4_BoxGetRoot, this means also children boxes
  * XXX : all children have to be allocated by a malloc !! and 
  *         p_box isn't freeing  
  *****************************************************************************/
-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 );
 
 /*****************************************************************************
  * MP4_DumpBoxStructure: print the structure of the p_box
+ *****************************************************************************
+ * Usefull while debugging
+ *****************************************************************************/
+void MP4_BoxDumpStructure( input_thread_t *p_input, MP4_Box_t *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_BoxGet( MP4_Box_t *p_box, char *psz_fmt, ... );
+    
+/*****************************************************************************
+ * MP4_BoxCount: find number of box given a path relative to p_box
+ *****************************************************************************
+ * Path Format: . .. / as usual
+ *              [number] to specifie box number ex: trak[12]
+ *              
+ * ex: /moov/trak
+ *     ../mdia 
  *****************************************************************************/
-void MP4_DumpBoxStructure( input_thread_t *p_input, MP4_Box_t *p_box );
+int MP4_BoxCount( MP4_Box_t *p_box, char *psz_fmt, ... );
+
+
 
+/*---------------------------------------------------------------------------*/
+/*                                                                           */
+/****---------------------- Medium level functions -----------------------****/
+/*                                                                           */
+/*---------------------------------------------------------------------------*/
+
+#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, u32 i_type );
-    
+#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, u32 i_type );
 
+#if 0
 /*****************************************************************************
  * MP4_FindNextBox:  find next box with thesame type and at the same level 
  *                  than p_box
@@ -715,12 +754,12 @@ MP4_Box_t *MP4_FindNextBox( MP4_Box_t *p_box );
  * MP4_FindNbBox:  find the box i_number 
  *****************************************************************************/
 MP4_Box_t *MP4_FindNbBox( MP4_Box_t *p_box, u32 i_number );
-   
+#endif
 
 /*---------------------------------------------------------------------------*/
 /****----------------------- Lower level functions -----------------------****/
 /****                                                                     ****/
-/****------Use them only when you known what they really do and need------****/  
+/****------Use them only when you known what they really do and need------****/
 /****                                                                     ****/
 /****---------------------------------------------------------------------****/
 /*---------------------------------------------------------------------------*/
index b0c1dabe2d361ec6f1b49e6f784df9e1d368b4ab..d0eaec0690b7827a1993ab5a1f2b5a6e2e71f7d5 100644 (file)
@@ -2,7 +2,7 @@
  * mp4.c : MP4 file input module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: mp4.c,v 1.3 2002/08/08 22:28:22 sam Exp $
+ * $Id: mp4.c,v 1.4 2002/09/17 11:57:38 fenrir Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -41,6 +41,9 @@ static int    MP4Init    ( vlc_object_t * );
 static void __MP4End     ( vlc_object_t * );
 static int    MP4Demux   ( input_thread_t * );
 
+/* New input could have something like that... */
+static int   MP4Seek     ( input_thread_t *, mtime_t );
+
 #define MP4End(a) __MP4End(VLC_OBJECT(a))
 
 /*****************************************************************************
@@ -55,6 +58,9 @@ vlc_module_end();
 /*****************************************************************************
  * Declaration of local function 
  *****************************************************************************/
+
+static int MP4_TrackSynchro( input_thread_t *p_input, track_data_mp4_t *p_track );
+
 static void MP4_ParseTrack();
 
 static int MP4_CreateChunksIndex();
@@ -88,7 +94,6 @@ static int MP4Init( vlc_object_t * p_this )
     
     demux_sys_t *p_demux;
     
-    MP4_Box_t *p_moov;    
     MP4_Box_t *p_ftyp;
 
 
@@ -126,10 +131,10 @@ static int MP4Init( vlc_object_t * p_this )
         case( FOURCC_moov ):
         case( FOURCC_moof ):
         case( FOURCC_mdat ):
-        case( FOURCC_udta ): /* should never match but ... */
+        case( FOURCC_udta ): 
         case( FOURCC_free ):
         case( FOURCC_skip ):
-        case( FOURCC_wide ): /* not mp4 compliant but ... */
+        case( FOURCC_wide ): 
             break;
          default:
             msg_Warn( p_input, "MP4 plugin discarded (not a valid file)" );
@@ -148,15 +153,15 @@ static int MP4Init( vlc_object_t * p_this )
        
 
     /* Now load all boxes ( except raw data ) */
-    if( !MP4_ReadBoxRoot( p_input, &p_demux->box_root ) )
+    if( !MP4_BoxGetRoot( p_input, &p_demux->box_root ) )
     {
         msg_Warn( p_input, "MP4 plugin discarded (not a valid file)" );
         return( -1 );
     }
 
-    MP4_DumpBoxStructure( p_input, &p_demux->box_root );
+    MP4_BoxDumpStructure( p_input, &p_demux->box_root );
 
-    if( ( p_ftyp = MP4_FindBox( &p_demux->box_root, FOURCC_ftyp ) ) )
+    if( ( p_ftyp = MP4_BoxGet( &p_demux->box_root, "/ftyp" ) ) )
     {
         switch( p_ftyp->data.p_ftyp->i_major_brand )
         {
@@ -181,40 +186,37 @@ static int MP4Init( vlc_object_t * p_this )
     }
 
     /* the file need to have one moov box */
-    if( !( p_moov = MP4_FindBox( &p_demux->box_root, FOURCC_moov ) ) )
+    if( MP4_BoxCount( &p_demux->box_root, "/moov" ) != 1 )
     {
-        msg_Warn( p_input, "MP4 plugin discarded (missing moov box)" );
+        msg_Err( p_input, 
+                 "MP4 plugin discarded (%d moov box)",
+                 MP4_BoxCount( &p_demux->box_root, "/moov" ) );
         MP4End( p_input );
         return( -1 );
     }
 
-    if( MP4_CountBox( &p_demux->box_root, FOURCC_moov ) != 1 )
-    {
-        msg_Warn( p_input, "more than one \"moov\" box (continuying anyway)" );
-    }
-
-    if( !(p_mvhd = MP4_FindBox( p_moov, FOURCC_mvhd ) ) )
+    if( !(p_mvhd = MP4_BoxGet( &p_demux->box_root, "/moov/mvhd" ) ) )
     {
-        msg_Err( p_input, "cannot find \"mvhd\" box" );
+        msg_Err( p_input, "cannot find /moov/mvhd !" );
         MP4End( p_input );
         return( -1 );
     }
     else
     {
         p_demux->i_timescale = p_mvhd->data.p_mvhd->i_timescale;
+        p_demux->i_duration = p_mvhd->data.p_mvhd->i_duration;
     }
     
-    p_demux->i_tracks = MP4_CountBox( p_moov, FOURCC_trak );
-    msg_Dbg( p_input, "find %d track%c",
-                        p_demux->i_tracks,
-                        p_demux->i_tracks ? 's':' ' );
-
-    if( !( p_trak = MP4_FindBox( p_moov, FOURCC_trak ) ) )
+    if( !( p_demux->i_tracks = 
+                MP4_BoxCount( &p_demux->box_root, "/moov/trak" ) ) )
     {
-        msg_Err( p_input, "cannot find /moov/trak !" );
+        msg_Err( p_input, "cannot find any /moov/trak !" );
         MP4End( p_input );
         return( -1 );
     }
+    msg_Dbg( p_input, "find %d track%c",
+                        p_demux->i_tracks,
+                        p_demux->i_tracks ? 's':' ' );
 
     /* allocate memory */
     p_demux->track = calloc( p_demux->i_tracks, sizeof( track_data_mp4_t ) );
@@ -222,6 +224,7 @@ static int MP4Init( vlc_object_t * p_this )
     /* now process each track and extract all usefull informations */
     for( i = 0; i < p_demux->i_tracks; i++ )
     {
+        p_trak = MP4_BoxGet( &p_demux->box_root, "/moov/trak[%d]", i );
         MP4_ParseTrack( p_input, &p_demux->track[i], p_trak );
 
         if( p_demux->track[i].b_ok )
@@ -236,12 +239,12 @@ static int MP4Init( vlc_object_t * p_this )
                     psz_cat = "audio";
                     break;
                 default:
-                    psz_cat = "";
+                    psz_cat = "unknown";
                     break;
             }
             
-            msg_Dbg( p_input, "adding track(%d) %s (%s) language %c%c%c",
-                            i,
+            msg_Dbg( p_input, "adding track[Id 0x%x] %s (%s) language %c%c%c",
+                            p_demux->track[i].i_track_ID,
                             psz_cat,
                             p_demux->track[i].b_enable ? "enable":"disable",
                             p_demux->track[i].i_language[0],
@@ -250,10 +253,9 @@ static int MP4Init( vlc_object_t * p_this )
         }
         else
         {
-            msg_Dbg( p_input, "ignoring track(%d)", i );
+            msg_Dbg( p_input, "ignoring track[Id 0x%x]", p_demux->track[i].i_track_ID );
         }
 
-        p_trak = MP4_FindNextBox( p_trak );
     }
   
     /*  create one program */
@@ -273,7 +275,10 @@ static int MP4Init( vlc_object_t * p_this )
         return( -1 );
     }
     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
-    p_input->stream.i_mux_rate = 0 ; /* FIXME */
+    /* XXX beurk and beurk, see MP4Demux and MP4Seek */
+    p_input->stream.i_mux_rate =  
+        p_input->stream.p_selected_area->i_size / 50 / 
+        ( p_demux->i_duration / p_demux->i_timescale );
     vlc_mutex_unlock( &p_input->stream.stream_lock );
    
     
@@ -296,14 +301,33 @@ static int MP4Init( vlc_object_t * p_this )
 
 /*****************************************************************************
  * MP4Demux: read packet and send them to decoders 
+ *****************************************************************************
+ * TODO check for newly selected track (ie audio upt to now )
  *****************************************************************************/
 static int MP4Demux( input_thread_t *p_input )
 {
     demux_sys_t *p_demux = p_input->p_demux_data;
     int i_track;
 
+    /* XXX beurk, beuRK and BEURK, 
+       but only way I've found to detect seek from interface */
+    if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
+    {
+        mtime_t i_date;
+        
+        /* first wait for empty buffer, arbitrary time FIXME */
+        msleep( DEFAULT_PTS_DELAY );
+        /* *** calculate new date *** */
+
+        i_date = (mtime_t)1000000 * 
+                 (mtime_t)p_demux->i_duration /
+                 (mtime_t)p_demux->i_timescale * 
+                 (mtime_t)MP4_TellAbsolute( p_input ) /
+                 (mtime_t)p_input->stream.p_selected_area->i_size;
+        MP4Seek( p_input, i_date );
+    }
+    
     /* first wait for the good time to read a packet */
-
     input_ClockManageRef( p_input,
                           p_input->stream.p_selected_program,
                           p_demux->i_pcr );
@@ -366,6 +390,26 @@ static int MP4Demux( input_thread_t *p_input )
 
     return( 0 ); /* EOF */
 }
+/*****************************************************************************
+ * MP4Seek: Got to i_date
+ ******************************************************************************/
+static int   MP4Seek     ( input_thread_t *p_input, mtime_t i_date )
+{
+    demux_sys_t *p_demux = p_input->p_demux_data;
+    int i_track;
+
+    /* First update update global time */
+    p_demux->i_time = i_date * p_demux->i_timescale / 1000000;
+    p_demux->i_pcr = __MAX( MP4_GetMoviePTS( p_demux ) - DEFAULT_PTS_DELAY,
+                            0 ) * 9 / 100; 
+    
+    /* Now for each stream try to go to this time */
+    for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
+    {
+        MP4_TrackSynchro( p_input, &p_demux->track[i_track] );
+    }
+    return( 1 );
+}
 
 /*****************************************************************************
  * MP4End: frees unused data
@@ -379,7 +423,7 @@ static void __MP4End ( vlc_object_t * p_this )
     demux_sys_t *p_demux = p_input->p_demux_data;
     
     msg_Dbg( p_input, "Freeing all memory" );
-    MP4_FreeBox( p_input, &p_demux->box_root );
+    MP4_BoxFree( p_input, &p_demux->box_root );
     for( i_track = 0; i_track < p_demux->i_tracks; i_track++ )
     {
         int i_chunk;
@@ -407,6 +451,116 @@ static void __MP4End ( vlc_object_t * p_this )
  * Local functions, specific to vlc
  ****************************************************************************/
 
+/****************************************************************************
+ * MP4_TrackSynchro : synchronize a track with movie time after seek or 
+ *                    for newly selected track
+ *****************************************************************************
+ * TODO add support of Edit List (edts/elts) and Shadow Sync Sample(stsh)
+ ****************************************************************************/
+static int MP4_TrackSynchro( input_thread_t *p_input, track_data_mp4_t *p_track )
+{
+    demux_sys_t *p_demux = p_input->p_demux_data;
+    int i_chunk_last;
+    MP4_Box_t   *p_stss;
+
+    if( !p_track->b_ok ||
+        !p_track->p_es ||
+        !p_track->p_es->p_decoder_fifo )
+    {
+        return( 0 );
+    }
+    p_track->i_sample = 0;
+    i_chunk_last = p_track->i_chunk;
+    p_track->i_chunk = 0;
+    for( ;; )
+    {
+        if( p_track->i_sample >= p_track->i_sample_count )
+        {
+            msg_Warn( p_input, 
+                        "track[Id 0x%x] will be disabled (seeking too far)",
+                        p_track->i_track_ID );
+            MP4_StopDecoder( p_input, p_track );
+            break;
+        }
+        if( MP4_GetTrackPTS( p_track ) >= MP4_GetMoviePTS( p_demux ) )
+        {
+            break;
+        }
+        /* go one sample after */
+        p_track->i_sample++;
+        if( p_track->i_sample >= p_track->chunk[p_track->i_chunk].i_sample_first +
+                p_track->chunk[p_track->i_chunk].i_sample_count )
+        {
+            p_track->i_chunk++;
+        }
+        
+    }
+    if( p_track->i_sample >= p_track->i_sample_count )
+    {
+        return( 0 );
+    }
+
+    /* *** Try to find nearest sync points *** */
+    if( ( p_stss = MP4_BoxGet( p_track->p_stbl, "stss" ) ) )
+    {
+        int i_index;
+        msg_Dbg( p_input, 
+                    "track[Id 0x%x] using Sync Sample Box (stss)", 
+                    p_track->i_track_ID );
+        for( i_index = 0; i_index < p_stss->data.p_stss->i_entry_count; i_index++ )
+        {
+            if( p_stss->data.p_stss->i_sample_number[i_index] >= p_track->i_sample )
+            {
+                if( i_index > 0 )
+                {
+                    msg_Dbg( p_input, "stts gives %d --> %d (sample number)", 
+                            p_track->i_sample, 
+                            p_stss->data.p_stss->i_sample_number[i_index-1] );
+                    p_track->i_sample = p_stss->data.p_stss->i_sample_number[i_index-1];
+                    /* new track.i_sample is less than old so i_chunk can only decreased */
+                    while( p_track->i_chunk > 0 && 
+                            p_track->i_sample < p_track->chunk[p_track->i_chunk].i_sample_first )
+                    {
+                        p_track->i_chunk--;
+                    }
+                }
+                else
+                {
+                    msg_Dbg( p_input, "stts gives %d --> %d (sample number)", 
+                            p_track->i_sample, 
+                            p_stss->data.p_stss->i_sample_number[i_index-1] );
+                    p_track->i_sample = p_stss->data.p_stss->i_sample_number[i_index];
+                    /* new track.i_sample is more than old so i_chunk can only increased */
+                    while( p_track->i_chunk < p_track->i_chunk_count - 1 &&
+                           p_track->i_sample >= p_track->chunk[p_track->i_chunk].i_sample_first +
+                                                p_track->chunk[p_track->i_chunk].i_sample_count )
+                    {
+                        p_track->i_chunk++;
+                    }
+                }
+                break;
+            }
+        }
+    }
+    else
+    {
+        msg_Dbg( p_input, 
+                    "track[Id 0x%x] doesn't provided Sync Sample Box (stss)", 
+                    p_track->i_track_ID );
+    }
+
+    /* *** If i_sample_description_index has changed restart decoder *** */
+    if( p_track->chunk[i_chunk_last].i_sample_description_index !=
+            p_track->chunk[p_track->i_chunk].i_sample_description_index )
+    {
+        msg_Warn( p_input,
+                "SampleEntry has changed, restarting decoder" );
+        MP4_StopDecoder( p_input, p_track );
+        MP4_StartDecoder( p_input, p_track );
+    }
+    return( 1 );
+}
+
 /****************************************************************************
  * Parse track information and create all needed data to run a track
  * If it succeed b_ok is set to 1 else to 0
@@ -417,14 +571,12 @@ static void MP4_ParseTrack( input_thread_t *p_input,
 {
     int i;
 
-    MP4_Box_t *p_tkhd = MP4_FindBox( p_trak, FOURCC_tkhd );
-    MP4_Box_t *p_tref = MP4_FindBox( p_trak, FOURCC_tref );
-    MP4_Box_t *p_edts = MP4_FindBox( p_trak, FOURCC_edts );
-    MP4_Box_t *p_mdia = MP4_FindBox( p_trak, FOURCC_mdia );
+    MP4_Box_t *p_tkhd = MP4_BoxGet( p_trak, "tkhd" );
+    MP4_Box_t *p_tref = MP4_BoxGet( p_trak, "tref" );
+    MP4_Box_t *p_elst;
 
     MP4_Box_t *p_mdhd;
     MP4_Box_t *p_hdlr;
-    MP4_Box_t *p_minf;
 
     MP4_Box_t *p_vmhd;
     MP4_Box_t *p_smhd; 
@@ -437,33 +589,33 @@ static void MP4_ParseTrack( input_thread_t *p_input,
     /* by default, we don't known the categorie */
     p_demux_track->i_cat = UNKNOWN_ES;
     
-    if( ( !p_tkhd )||( !p_mdia ) )
+    if( !p_tkhd )
     {
         return;
     }
 
     /* do we launch this track by default ? */
-    p_demux_track->b_enable = ( ( p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED ) != 0 );
+    p_demux_track->b_enable = 
+        ( ( p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED ) != 0 );
 
     p_demux_track->i_track_ID = p_tkhd->data.p_tkhd->i_track_ID;
     p_demux_track->i_width = p_tkhd->data.p_tkhd->i_width / 65536;
     p_demux_track->i_height = p_tkhd->data.p_tkhd->i_height / 65536;
     
-    if( !p_edts )
+    if( ( p_elst = MP4_BoxGet( p_trak, "edts/elst" ) ) )
     {
 /*        msg_Warn( p_input, "Unhandled box: edts --> FIXME" ); */
     }
 
-    if( !p_tref )
+    if( p_tref )
     {
 /*        msg_Warn( p_input, "Unhandled box: tref --> FIXME" ); */
     } 
 
-    p_mdhd = MP4_FindBox( p_mdia, FOURCC_mdhd );
-    p_hdlr = MP4_FindBox( p_mdia, FOURCC_hdlr );
-    p_minf = MP4_FindBox( p_mdia, FOURCC_minf );
+    p_mdhd = MP4_BoxGet( p_trak, "mdia/mdhd" );
+    p_hdlr = MP4_BoxGet( p_trak, "mdia/hdlr" );
     
-    if( ( !p_mdhd )||( !p_hdlr )||( !p_minf ) )
+    if( ( !p_mdhd )||( !p_hdlr ) )
     {
         return;
     }
@@ -474,11 +626,12 @@ static void MP4_ParseTrack( input_thread_t *p_input,
     {
         p_demux_track->i_language[i] = p_mdhd->data.p_mdhd->i_language[i];
     }
+    p_mdhd->data.p_mdhd->i_language[3] = 0;
     
     switch( p_hdlr->data.p_hdlr->i_handler_type )
     {
         case( FOURCC_soun ):
-            if( !( p_smhd = MP4_FindBox( p_minf, FOURCC_smhd ) ) )
+            if( !( p_smhd = MP4_BoxGet( p_trak, "mdia/minf/smhd" ) ) )
             {
                 return;
             }
@@ -486,7 +639,7 @@ static void MP4_ParseTrack( input_thread_t *p_input,
             break;
 
         case( FOURCC_vide ):
-            if( !( p_vmhd = MP4_FindBox( p_minf, FOURCC_vmhd ) ) )
+            if( !( p_vmhd = MP4_BoxGet( p_trak, "mdia/minf/vmhd" ) ) )
             {
                 return;
             }
@@ -496,16 +649,16 @@ static void MP4_ParseTrack( input_thread_t *p_input,
         default:
             return;
     }
-/*  FIXME
-    add support to:
-    p_dinf = MP4_FindBox( p_minf, FOURCC_dinf );
+/*  TODO
+    add support for:
+    p_dinf = MP4_BoxGet( p_minf, "dinf" );
 */
-    if( !( p_demux_track->p_stbl = MP4_FindBox( p_minf, FOURCC_stbl ) ) )
+    if( !( p_demux_track->p_stbl = MP4_BoxGet( p_trak,"mdia/minf/stbl" ) ) )
     {
         return;
     }
     
-    if( !( p_demux_track->p_stsd = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stsd ) ) )
+    if( !( p_demux_track->p_stsd = MP4_BoxGet( p_trak,"mdia/minf/stbl/stsd") ) )
     {
         return;
     }
@@ -538,9 +691,9 @@ static int MP4_CreateChunksIndex( input_thread_t *p_input,
     int i_index, i_last;
    
 
-    if( ( !(p_co64 = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stco ) )&&
-                 !(p_co64 = MP4_FindBox( p_demux_track->p_stbl, FOURCC_co64 ) ) )|| 
-        ( !(p_stsc = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stsc ) ) ))
+    if( ( !(p_co64 = MP4_BoxGet( p_demux_track->p_stbl, "stco" ) )&&
+          !(p_co64 = MP4_BoxGet( p_demux_track->p_stbl, "co64" ) ) )|| 
+        ( !(p_stsc = MP4_BoxGet( p_demux_track->p_stbl, "stsc" ) ) ))
     {
         return( 0 );
     }
@@ -595,7 +748,10 @@ static int MP4_CreateChunksIndex( input_thread_t *p_input,
         
     }
     
-    msg_Dbg( p_input, "read %d chunk", p_demux_track->i_chunk_count );
+    msg_Dbg( p_input, 
+             "track[Id 0x%x] read %d chunk",
+             p_demux_track->i_track_ID,
+            p_demux_track->i_chunk_count );
     return( 1 );
 
 }
@@ -621,8 +777,8 @@ static int MP4_CreateSamplesIndex( input_thread_t *p_input,
 
     u64 i_last_dts; 
     
-    p_stts = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stts );
-    p_stsz = MP4_FindBox( p_demux_track->p_stbl, FOURCC_stsz ); /* FIXME and stz2 */
+    p_stts = MP4_BoxGet( p_demux_track->p_stbl, "stts" );
+    p_stsz = MP4_BoxGet( p_demux_track->p_stbl, "stsz" ); /* FIXME and stz2 */
 
     
     if( ( !p_stts )||( !p_stsz ) )
@@ -722,7 +878,10 @@ static int MP4_CreateSamplesIndex( input_thread_t *p_input,
         
     }
 
-    msg_Dbg( p_input, "read %d samples", p_demux_track->i_sample_count );
+    msg_Dbg( p_input, 
+             "track[Id 0x%x] read %d samples", 
+             p_demux_track->i_track_ID,
+             p_demux_track->i_sample_count );
 
     return( 1 );
 }
@@ -747,7 +906,7 @@ static void MP4_StartDecoder( input_thread_t *p_input,
         return;
     }
     
-    msg_Dbg( p_input, "Starting decoder (track ID 0x%x)",
+    msg_Dbg( p_input, "Starting decoder for track[Id 0x%x]",
                       p_demux_track->i_track_ID );
 
     /* launch decoder according in chunk we are */
@@ -756,18 +915,18 @@ static void MP4_StartDecoder( input_thread_t *p_input,
     if( !p_demux_track->chunk[i_chunk].i_sample_description_index )
     {
         msg_Warn( p_input, 
-                  "invalid SampleEntry index (track ID 0x%x)",
+                  "invalid SampleEntry index (track[Id 0x%x])",
                   p_demux_track->i_track_ID );
         return;
     } 
-    
-    p_sample = MP4_FindNbBox( p_demux_track->p_stsd,
-                 p_demux_track->chunk[i_chunk].i_sample_description_index - 1);
+    p_sample = MP4_BoxGet(  p_demux_track->p_stsd, 
+                            "[%d]", 
+                p_demux_track->chunk[i_chunk].i_sample_description_index - 1 );
 
     if( ( !p_sample )||( !p_sample->data.p_data ) )
     {
         msg_Warn( p_input, 
-                  "cannot find SampleEntry (track ID 0x%x)",
+                  "cannot find SampleEntry (track[Id 0x%x])",
                   p_demux_track->i_track_ID );
         return;
     }
@@ -783,7 +942,7 @@ static void MP4_StartDecoder( input_thread_t *p_input,
     {
         p_demux_track->p_es->psz_desc[i] = p_demux_track->i_language[i];
     }
-    p_demux_track->p_es->psz_desc[4] = 0;
+    p_demux_track->p_es->psz_desc[3] = '\0';
     
     p_demux_track->p_es->i_stream_id = p_demux_track->i_track_ID;
 
@@ -807,7 +966,7 @@ static void MP4_StartDecoder( input_thread_t *p_input,
     /* now see if esds is present and if so create a data packet 
         with decoder_specific_info  */
 #define p_decconfig p_esds->data.p_esds->es_descriptor.p_decConfigDescr
-    if( ( p_esds = MP4_FindBox( p_sample, FOURCC_esds ) )&&
+    if( ( p_esds = MP4_BoxGet( p_sample, "esds" ) )&&
         ( p_esds->data.p_esds )&&
         ( p_decconfig ) )
     {
@@ -828,7 +987,7 @@ static void MP4_StartDecoder( input_thread_t *p_input,
             case( 0x65): /* MPEG2 video */
                 p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','v' );
                 break;
-            /* Theses are MPEG2-AAC (what is this codec ?) */
+            /* Theses are MPEG2-AAC */
             case( 0x66): /* main profile */
             case( 0x67): /* Low complexity profile */
             case( 0x68): /* Scaleable Sampling rate profile */
@@ -850,7 +1009,7 @@ static void MP4_StartDecoder( input_thread_t *p_input,
             default:
                 /* Unknown entry, but don't touch i_fourcc */
                 msg_Warn( p_input, 
-                          "objectTypeIndication(0x%x) unknow (Track ID 0x%x)",
+                          "objectTypeIndication(0x%x) unknow (Track[ID 0x%x])",
                           p_decconfig->i_objectTypeIndication,
                           p_demux_track->i_track_ID );
                 break;
@@ -948,16 +1107,19 @@ static void MP4_StartDecoder( input_thread_t *p_input,
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 
     p_demux_track->b_ok = 1;
+    p_demux_track->b_selected = 1;
 }
 
 static void MP4_StopDecoder( input_thread_t *p_input,
                              track_data_mp4_t *p_demux_track )
 {
-    msg_Dbg( p_input, "Stopping decoder (track ID 0x%x)",
+    msg_Dbg( p_input, "Stopping decoder (track[Id 0x%x])",
                       p_demux_track->i_track_ID );
 
     input_UnselectES( p_input, p_demux_track->p_es );
     p_demux_track->p_es = NULL;
+
+    p_demux_track->b_selected = 0;
 }
 
 static int  MP4_ReadSample( input_thread_t *p_input,
@@ -980,7 +1142,7 @@ static int  MP4_ReadSample( input_thread_t *p_input,
     i_size = p_demux_track->i_sample_size ? 
                     p_demux_track->i_sample_size : 
                     p_demux_track->p_sample_size[p_demux_track->i_sample];
-    /* TODO */
+
     i_pos  = MP4_GetTrackPos( p_demux_track );
 
     /* go,go go ! */
@@ -1062,7 +1224,7 @@ static int  MP4_DecodeSample( input_thread_t *p_input,
     {
         /* we haven't reached the end of the track, so see if we 
            have to change the decoder for the next frame because 
-           i_sample_description_index have changed */
+           i_sample_description_index has changed */
 
         p_demux_track->i_chunk++;
         if( p_demux_track->chunk[p_demux_track->i_chunk-1].i_sample_description_index 
@@ -1070,7 +1232,7 @@ static int  MP4_DecodeSample( input_thread_t *p_input,
         {
             /* FIXME */
             msg_Warn( p_input, 
-                      "SampleEntry have changed, starting a new decoder" );
+                      "SampleEntry has changed, starting a new decoder" );
             MP4_StopDecoder( p_input, p_demux_track );
             MP4_StartDecoder( p_input, p_demux_track );
         }
index 98011cd5a939fece8778af2aeb9521268863b9a0..176c95c3c16a355acfb4016a73ba7b65a41e2a17 100644 (file)
@@ -2,7 +2,7 @@
  * mp4.h : MP4 file input module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: mp4.h,v 1.2 2002/08/07 00:29:36 sam Exp $
+ * $Id: mp4.h,v 1.3 2002/09/17 11:57:38 fenrir Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -84,7 +84,7 @@ typedef struct track_data_mp4_s
     int b_ok;           /* The track is usable */
     int i_track_ID;     /* this should be unique */
     int b_enable;       /* is the trak enable by default */
-
+    int b_selected;     /* is the trak being played */
     int i_cat;          /* Type of the track, VIDEO_ES, AUDIO_ES, UNKNOWN_ES  ... */
     char        i_language[3];
 
@@ -132,7 +132,7 @@ struct demux_sys_t
     
     u64         i_time;         /* time position of the presentation in movie timescale */
     u64         i_timescale;    /* movie time scale */
-    
+    u64         i_duration;     /* movie duration */
     int i_tracks;               /* number of track */  
     track_data_mp4_t *track; /* array of track */