]> git.sesse.net Git - vlc/blobdiff - plugins/avi/avi.c
* ALL: the first libvlc commit.
[vlc] / plugins / avi / avi.c
index 7aa29e5f3742ff8bee7a6638fb87c7c7dec3db21..db1063f03b4290e6ab839ca7654d16ec64011d6f 100644 (file)
@@ -2,7 +2,7 @@
  * avi.c : AVI file Stream input module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: avi.c,v 1.9 2002/04/30 16:42:14 fenrir Exp $
+ * $Id: avi.c,v 1.21 2002/06/01 12:31:58 sam Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
 #include <errno.h>
 #include <sys/types.h>
 
-#include <videolan/vlc.h>
-
-#include "stream_control.h"
-#include "input_ext-intf.h"
-#include "input_ext-dec.h"
-#include "input_ext-plugins.h"
+#include <vlc/vlc.h>
+#include <vlc/input.h>
 
 #include "video.h"
 
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static void input_getfunctions( function_list_t * p_function_list );
-static int  AVIDemux         ( struct input_thread_s * );
-static int  AVIInit          ( struct input_thread_s * );
-static void AVIEnd           ( struct input_thread_s * );
+static void input_getfunctions( function_list_t * );
+static int  AVIDemux         ( input_thread_t * );
+static int  AVIInit          ( input_thread_t * );
+static void AVIEnd           ( input_thread_t * );
 
 /*****************************************************************************
  * Build configuration tree.
@@ -58,7 +54,6 @@ MODULE_CONFIG_STOP
 MODULE_INIT_START
     SET_DESCRIPTION( "RIFF-AVI Stream input" )
     ADD_CAPABILITY( DEMUX, 150 )
-    ADD_SHORTCUT( "avi" )
 MODULE_INIT_STOP
 
 MODULE_ACTIVATE_START
@@ -112,14 +107,11 @@ static void __AVIFreeDemuxData( input_thread_t *p_input )
         {
             if( p_avi_demux->pp_info[i] != NULL ) 
             {
-#define p_info p_avi_demux->pp_info[i]
-                
-                if( p_info->p_index != NULL )
+                if( p_avi_demux->pp_info[i]->p_index != NULL )
                 {
-                      free( p_info->p_index );
+                      free( p_avi_demux->pp_info[i]->p_index );
                 }
-                free( p_info ); 
-#undef  p_info
+                free( p_avi_demux->pp_info[i] ); 
             }
         }
          free( p_avi_demux->pp_info );
@@ -190,7 +182,7 @@ int avi_ParseWaveFormatEx( waveformatex_t *h, byte_t *p_data )
     return( 0 );
 }
 
-static __inline__ int __AVIGetESTypeFromTwoCC( u16 i_type )
+static inline int __AVIGetESTypeFromTwoCC( u16 i_type )
 {
     switch( i_type )
     {
@@ -264,7 +256,6 @@ static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
 
 static void __AVI_GetIndex( input_thread_t *p_input )
 {
-    demux_data_avi_file_t *p_avi_demux;
     AVIIndexEntry_t index;
     byte_t          *p_buff;
     riffchunk_t     *p_idx1;
@@ -273,46 +264,47 @@ static void __AVI_GetIndex( input_thread_t *p_input )
     int             i_number;
     u16             i_type;
     int             i_totalentry = 0;
-    
-    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data  ;    
+    demux_data_avi_file_t *p_avi_demux =
+                        (demux_data_avi_file_t*)p_input->p_demux_data  ;    
 
     if( RIFF_FindAndGotoDataChunk( p_input,
                                    p_avi_demux->p_riff, 
                                    &p_idx1, 
                                    FOURCC_idx1)!=0 )
     {
-        intf_WarnMsg( 1, "input init: cannot find index" );
+        msg_Warn( p_input, "cannot find index" );
         RIFF_GoToChunk( p_input, p_avi_demux->p_hdrl );        
         return;
     }
     p_avi_demux->p_idx1 = p_idx1;
-    intf_WarnMsg( 1, "input init: loading index" ); 
+    msg_Dbg( p_input, "loading index" ); 
     for(;;)
     {
-        if( ((i_read = input_Peek( p_input, &p_buff, 16*1024 )) < 16 )
+        i_read = __MIN( 16*1024, p_idx1->i_size - i_totalentry *16);
+        if( ((i_read = input_Peek( p_input, &p_buff, i_read )) < 16 )
               ||( i_totalentry *16 >= p_idx1->i_size ) )
         {
-            intf_WarnMsg( 1,"input info: read %d idx chunk", i_totalentry );
+            msg_Dbg( p_input, "read %d idx entries", i_totalentry );
             return;
         }
         i_read /= 16 ;
-        /* TODO try to verify if we are beyond end of p_idx1 */
         for( i = 0; i < i_read; i++ )
         {
             byte_t  *p_peek = p_buff + i * 16;
             i_totalentry++;
             index.i_id = __GetDoubleWordLittleEndianFromBuff( p_peek );
             index.i_flags = __GetDoubleWordLittleEndianFromBuff( p_peek+4);
-            index.i_offset = __GetDoubleWordLittleEndianFromBuff( p_peek+8);
+            index.i_pos = __GetDoubleWordLittleEndianFromBuff( p_peek+8);
             index.i_length = __GetDoubleWordLittleEndianFromBuff(p_peek+12);
             
-            if( (__AVI_ParseStreamHeader( index.i_id, &i_number, &i_type ) != 0)
-             ||(i_number > p_avi_demux->i_streams)) 
+            if( (__AVI_ParseStreamHeader( index.i_id, &i_number, &i_type ) == 0)
+             &&(i_number <  p_avi_demux->i_streams )
+             &&(p_avi_demux->pp_info[i_number]->i_cat == 
+                     __AVIGetESTypeFromTwoCC( i_type ))) 
             {
-                continue;
+                __AVI_AddEntryIndex( p_avi_demux->pp_info[i_number],
+                                     &index );
             }
-            __AVI_AddEntryIndex( p_avi_demux->pp_info[i_number],
-                                 &index );
         }
         __RIFF_SkipBytes( p_input, 16 * i_read );
     }
@@ -320,59 +312,55 @@ static void __AVI_GetIndex( input_thread_t *p_input )
 }
 static int __AVI_SeekToChunk( input_thread_t *p_input, AVIStreamInfo_t *p_info )
 {
-    demux_data_avi_file_t *p_avi_demux;
-    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
-    
-    if( (p_info->p_index != NULL)&&(p_info->i_idxposc < p_info->i_idxnb) )
+    if( (p_info->p_index )&&(p_info->i_idxposc < p_info->i_idxnb) )
     {
-        off_t i_pos;
-        i_pos = (off_t)p_info->p_index[p_info->i_idxposc].i_offset +
-                    p_info->i_idxoffset;
-
-        p_input->pf_seek( p_input, i_pos );
+        p_input->pf_seek( p_input, 
+                          (off_t)p_info->p_index[p_info->i_idxposc].i_pos);
         input_AccessReinit( p_input );
         return( 0 );
     }
     /* no index can't arrive but ...*/
-    intf_WarnMsg( 1, "input error: can't seek");
+    msg_Warn( p_input, "cannot seek");
     return( -1 );
 }
 
 
 /* XXX call after get p_movi */
-static void __AVI_GetIndexOffset( input_thread_t *p_input )
+static void __AVI_UpdateIndexOffset( input_thread_t *p_input )
 {
-    riffchunk_t *p_chunk;
-    demux_data_avi_file_t *p_avi_demux;
-    int i;
-
-    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
-    for( i = 0; i < p_avi_demux->i_streams; i++ )
-    {
-#define p_info p_avi_demux->pp_info[i]
-        if( p_info->p_index == NULL ) 
+    int i_stream;
+    int b_start = 1;/* if index pos is based on start of file or not (p_movi) */
+    demux_data_avi_file_t *p_avi_demux =
+                        (demux_data_avi_file_t*)p_input->p_demux_data;
+
+/* FIXME some work to do :
+        * test in the ile if it's true, if not do a RIFF_Find...
+*/
+#define p_info p_avi_demux->pp_info[i_stream]
+    for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
+    {
+        if( ( p_info->p_index )
+           && ( p_info->p_index[0].i_pos < p_avi_demux->p_movi->i_pos + 8 ))
         {
-            intf_WarnMsg( 1, "input demux: can't find offset for stream %d",i);
-            continue;
+            b_start = 0;
+            break;
         }
-        p_info->i_idxoffset = 0;
-        __AVI_SeekToChunk( p_input, p_info );
-        p_chunk = RIFF_ReadChunk( p_input );
-        if( (p_chunk == NULL)||(p_chunk->i_id != p_info->p_index[0].i_id) )
+    }
+    if( !b_start )
+    {
+        for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
         {
-            p_info->i_idxoffset = p_avi_demux->p_movi->i_pos + 8;
-            __AVI_SeekToChunk( p_input, p_info );
-            p_chunk = RIFF_ReadChunk( p_input );
-            if( (p_chunk == NULL)||(p_chunk->i_id != p_info->p_index[0].i_id) )
+            int i;
+            if( p_info->p_index )
             {
-                intf_WarnMsg( 1, "input demux: can't find offset for stream %d",
-                                i);
-                continue; /* TODO: search manually from p_movi */
+                for( i = 0; i < p_info->i_idxnb; i++ )
+                {
+                    p_info->p_index[i].i_pos += p_avi_demux->p_movi->i_pos + 8;
+                }
             }
         }
-#undef p_info
     }
-    return;
+#undef p_info
 }
 
 static int __AVI_AudioGetType( u32 i_type )
@@ -395,27 +383,46 @@ static int __AVI_VideoGetType( u32 i_type )
 {
     switch( i_type )
     {
-        case( FOURCC_DIV3 ):
-        case( FOURCC_div3 ):
-        case( FOURCC_DIV4 ):
-        case( FOURCC_div4 ):
-        case( FOURCC_DIV5 ):
-        case( FOURCC_div5 ):
-        case( FOURCC_DIV6 ):
-        case( FOURCC_div6 ):
-        case( FOURCC_3IV1 ):
-        case( FOURCC_AP41 ):
-        case( FOURCC_MP43 ):
-        case( FOURCC_mp43 ):
-            return( MSMPEG4_VIDEO_ES );
-
-        case( FOURCC_DIVX ):
-        case( FOURCC_divx ):
-        case( FOURCC_DX50 ):
-        case( FOURCC_MP4S ):
-        case( FOURCC_MPG4 ):
-        case( FOURCC_mpg4 ):
-        case( FOURCC_mp4v ):
+/* FIXME FIXME :  what are the correct tag for msmpeg4 v1 */
+        case(  FOURCC_MPG4  ):
+        case(  FOURCC_mpg4  ):
+        case(  FOURCC_DIV2  ):
+        case(  FOURCC_div2  ):
+        case(  FOURCC_MP42  ):
+        case(  FOURCC_mp42  ):
+             return( MSMPEG4v2_VIDEO_ES );
+           
+        case(  FOURCC_MPG3  ):
+        case(  FOURCC_mpg3  ):
+        case(  FOURCC_div3  ):
+        case(  FOURCC_MP43  ):
+        case(  FOURCC_mp43  ):
+        case(  FOURCC_DIV3  ):
+        case(  FOURCC_DIV4  ):
+        case(  FOURCC_div4  ):
+        case(  FOURCC_DIV5  ):
+        case(  FOURCC_div5  ):
+        case(  FOURCC_DIV6  ):
+        case(  FOURCC_div6  ):
+        case(  FOURCC_AP41  ):
+        case(  FOURCC_3IV1  ):
+            return( MSMPEG4v3_VIDEO_ES );
+
+
+        case(  FOURCC_DIVX  ):
+        case(  FOURCC_divx  ):
+        case(  FOURCC_DIV1  ):
+        case(  FOURCC_div1  ):
+        case(  FOURCC_MP4S  ):
+        case(  FOURCC_mp4s  ):
+        case(  FOURCC_M4S2  ):
+        case(  FOURCC_m4s2  ):
+        case(  FOURCC_xvid  ):
+        case(  FOURCC_XVID  ):
+        case(  FOURCC_XviD  ):
+        case(  FOURCC_DX50  ):
+        case(  FOURCC_mp4v  ):
+        case(  FOURCC_4     ):
             return( MPEG4_VIDEO_ES );
 
         default:
@@ -439,19 +446,18 @@ static int AVIInit( input_thread_t *p_input )
     /* we need to seek to be able to readcorrectly */
     if( !p_input->stream.b_seekable ) 
     {
-        intf_ErrMsg( "input error: need the ability to seek in stream" );
+        msg_Warn( p_input, "RIFF-AVI module discarded (not seekable)" );
         return( -1 );
     }
-
     p_input->p_demux_data = 
                 p_avi_demux = malloc( sizeof(demux_data_avi_file_t) );
     if( p_avi_demux == NULL )
     {
-        intf_ErrMsg( "input error: not enough memory" );
+        msg_Err( p_input, "out of memory" );
         return( -1 );
     }
     memset( p_avi_demux, 0, sizeof( demux_data_avi_file_t ) );
-
+    p_avi_demux->i_rate = DEFAULT_RATE;
     /* FIXME I don't know what it's do, copied from ESInit */
     /* Initialize access plug-in structures. */
     if( p_input->i_mtu == 0 )
@@ -463,7 +469,7 @@ static int AVIInit( input_thread_t *p_input )
     if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 )    
     {
         __AVIFreeDemuxData( p_input );
-        intf_ErrMsg( "input: RIFF-AVI plug-in discarded (avi_file)" );
+        msg_Warn( p_input, "RIFF-AVI module discarded" );
         return( -1 );
     }
     p_avi_demux->p_riff = p_riff;
@@ -471,7 +477,7 @@ static int AVIInit( input_thread_t *p_input )
     if ( RIFF_DescendChunk(p_input) != 0 )
     {
         __AVIFreeDemuxData( p_input );
-        intf_ErrMsg( "input error: cannot look for subchunk (avi_file)" );
+        msg_Err( p_input, "cannot look for subchunk" );
         return ( -1 );
     }
 
@@ -479,7 +485,7 @@ static int AVIInit( input_thread_t *p_input )
     if( RIFF_FindListChunk(p_input ,&p_hdrl,p_riff, FOURCC_hdrl) != 0 )
     {
         __AVIFreeDemuxData( p_input );
-        intf_ErrMsg( "input error: cannot find \"LIST-hdrl\" (avi_file)" );
+        msg_Err( p_input, "cannot find \"LIST-hdrl\"" );
         return( -1 );
     }
     p_avi_demux->p_hdrl = p_hdrl;
@@ -487,7 +493,7 @@ static int AVIInit( input_thread_t *p_input )
     if( RIFF_DescendChunk(p_input) != 0 )
     {
         __AVIFreeDemuxData( p_input );
-        intf_ErrMsg( "input error: cannot look for subchunk (avi_file)" );
+        msg_Err( p_input, "cannot look for subchunk" );
         return ( -1 );
     }
     /* in  LIST-hdrl search avih */
@@ -495,7 +501,7 @@ static int AVIInit( input_thread_t *p_input )
                                     &p_avih, FOURCC_avih ) != 0 )
     {
         __AVIFreeDemuxData( p_input );
-        intf_ErrMsg( "input error: cannot find \"avih\" chunk (avi_file)" );
+        msg_Err( p_input, "cannot find \"avih\" chunk" );
         return( -1 );
     }
     __AVI_Parse_avih( &p_avi_demux->avih, p_avih->p_data->p_payload_start );
@@ -505,24 +511,24 @@ static int AVIInit( input_thread_t *p_input )
     /* no stream found, perhaps it would be cool to find it */
     {
         __AVIFreeDemuxData( p_input );
-        intf_ErrMsg( "input error: no defined stream !" );
+        msg_Err( p_input, "no stream defined!" );
         return( -1 );
     }
 
     /*  create one program */
-    vlc_mutex_lock( &p_input->stream.stream_lock ); 
+    vlc_mutex_lock( &p_input->stream.stream_lock );
     if( input_InitStream( p_input, 0 ) == -1)
     {
         vlc_mutex_unlock( &p_input->stream.stream_lock );
         __AVIFreeDemuxData( p_input );
-        intf_ErrMsg( "input error: cannot init stream" );
+        msg_Err( p_input, "cannot init stream" );
         return( -1 );
     }
     if( input_AddProgram( p_input, 0, 0) == NULL )
     {
         vlc_mutex_unlock( &p_input->stream.stream_lock );
         __AVIFreeDemuxData( p_input );
-        intf_ErrMsg( "input error: cannot add program" );
+        msg_Err( p_input, "cannot add program" );
         return( -1 );
     }
     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
@@ -549,7 +555,7 @@ static int AVIInit( input_thread_t *p_input )
                 ||( RIFF_DescendChunk(p_input) != 0 ))
         {
             __AVIFreeDemuxData( p_input );
-            intf_ErrMsg( "input error: cannot find \"LIST-strl\" (avi_file)" );
+            msg_Err( p_input, "cannot find \"LIST-strl\"" );
             return( -1 );
         }
         
@@ -559,11 +565,11 @@ static int AVIInit( input_thread_t *p_input )
         {
             RIFF_DeleteChunk( p_input, p_strl );
             __AVIFreeDemuxData( p_input );
-            intf_ErrMsg( "input error: cannot find \"strh\" (avi_file)" );
+            msg_Err( p_input, "cannot find \"strh\"" );
             return( -1 );
         }
         __AVI_Parse_Header( &p_info->header,
-                        p_strh->p_data->p_payload_start);
+                            p_strh->p_data->p_payload_start);
         RIFF_DeleteChunk( p_input, p_strh );      
 
         /* in  LIST-strl search strf */
@@ -572,7 +578,7 @@ static int AVIInit( input_thread_t *p_input )
         {
             RIFF_DeleteChunk( p_input, p_strl );
             __AVIFreeDemuxData( p_input );
-            intf_ErrMsg( "input error: cannot find \"strf\" (avi_file)" );
+            msg_Err( p_input, "cannot find \"strf\"" );
             return( -1 );
         }
         /* we don't get strd, it's useless for divx,opendivx,mepgaudio */ 
@@ -581,7 +587,7 @@ static int AVIInit( input_thread_t *p_input )
             RIFF_DeleteChunk( p_input, p_strf );
             RIFF_DeleteChunk( p_input, p_strl );
             __AVIFreeDemuxData( p_input );
-            intf_ErrMsg( "input error: cannot go out (\"strl\") (avi_file)" );
+            msg_Err( p_input, "cannot go out (\"strl\")" );
             return( -1 );
         }
 
@@ -604,9 +610,8 @@ static int AVIInit( input_thread_t *p_input )
                     __AVI_AudioGetType( p_info->audio_format.i_formattag );
                 if( p_es->i_type == 0 )
                 {
-                    intf_ErrMsg( "input error: stream(%d,0x%x) not supported",
-                                    i,
-                                    p_info->audio_format.i_formattag );
+                    msg_Err( p_input, "stream(%d,0x%x) not supported", i,
+                                       p_info->audio_format.i_formattag );
                     p_es->i_cat = UNKNOWN_ES;
                 }
                 break;
@@ -620,15 +625,13 @@ static int AVIInit( input_thread_t *p_input )
                     __AVI_VideoGetType( p_info->video_format.i_compression );
                 if( p_es->i_type == 0 )
                 {
-                    intf_ErrMsg( "input error: stream(%d,%4.4s) not supported",
-                               i,
-                               (char*)&p_info->video_format.i_compression);
+                    msg_Err( p_input, "stream(%d,%4.4s) not supported", i,
+                              (char*)&p_info->video_format.i_compression);
                     p_es->i_cat = UNKNOWN_ES;
                 }
                 break;
             default:
-                intf_ErrMsg( "input error: unknown stream(%d) type",
-                            i );
+                msg_Err( p_input, "unknown stream(%d) type", i );
                 p_es->i_cat = UNKNOWN_ES;
                 break;
         }
@@ -649,14 +652,14 @@ static int AVIInit( input_thread_t *p_input )
     if( RIFF_AscendChunk(p_input, p_hdrl) != 0)
     {
         __AVIFreeDemuxData( p_input );
-        intf_ErrMsg( "input error: cannot go out (\"hdrl\") (avi_file)" );
+        msg_Err( p_input, "cannot go out (\"hdrl\")" );
         return( -1 );
     }
 
     /* go to movi chunk to get it*/
     if( RIFF_FindListChunk(p_input ,&p_movi,p_riff, FOURCC_movi) != 0 )
     {
-        intf_ErrMsg( "input error: cannot find \"LIST-movi\" (avi_file)" );
+        msg_Err( p_input, "cannot find \"LIST-movi\"" );
         __AVIFreeDemuxData( p_input );
         return( -1 );
     }
@@ -668,11 +671,11 @@ static int AVIInit( input_thread_t *p_input )
         /* get index */
         __AVI_GetIndex( p_input ); 
         /* try to get i_idxoffset for each stream  */
-        __AVI_GetIndexOffset( p_input );
+        __AVI_UpdateIndexOffset( p_input );
     }
     else
     {
-        intf_WarnMsg( 1, "input init: no index !" );
+        msg_Warn( p_input, "no index!" );
     }
 
     
@@ -684,16 +687,14 @@ static int AVIInit( input_thread_t *p_input )
 #define p_info  p_avi_demux->pp_info[i]
         if( p_info->p_index == NULL )
         {
-            intf_WarnMsg( 3, "input init: add index entry for stream %d", i ); 
             RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
             if( RIFF_DescendChunk(p_input) != 0 ) { continue; }
             p_chunk = NULL;
             switch( p_info->i_cat ) 
             {
                 case( AUDIO_ES ):
-                    p_info->i_idxoffset = 0;  /* ref: begining of file */
                     if( RIFF_FindChunk( p_input, 
-                               MAKEFOURCC('0'+i/10, '0'+i%10,'w','b' ), 
+                               VLC_FOURCC('0'+i/10, '0'+i%10,'w','b' ), 
                                              p_movi ) == 0)
                     {
                        p_chunk = RIFF_ReadChunk( p_input );
@@ -701,9 +702,8 @@ static int AVIInit( input_thread_t *p_input )
                     break;
                     
                 case( VIDEO_ES ):
-                    p_info->i_idxoffset = 0;
                     if( (RIFF_FindChunk( p_input, 
-                                    MAKEFOURCC('0'+i/10, '0'+i%10,'d','c' ),
+                                    VLC_FOURCC('0'+i/10, '0'+i%10,'d','c' ),
                                             p_movi ) == 0) )
                     {
                         p_chunk = RIFF_ReadChunk( p_input ); 
@@ -713,7 +713,7 @@ static int AVIInit( input_thread_t *p_input )
                         RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
                         if( RIFF_DescendChunk(p_input) != 0 ) { continue; }
                         if( (RIFF_FindChunk( p_input,
-                                        MAKEFOURCC('0'+i/10, '0'+i%10,'d','b' ),
+                                        VLC_FOURCC('0'+i/10, '0'+i%10,'d','b' ),
                                             p_movi ) == 0) )
                         {
                             p_chunk = RIFF_ReadChunk( p_input );
@@ -725,9 +725,12 @@ static int AVIInit( input_thread_t *p_input )
             {
                 index.i_id = p_chunk->i_id;
                 index.i_flags = AVIIF_KEYFRAME;
-                index.i_offset = p_chunk->i_pos;
+                index.i_pos = p_chunk->i_pos;
                 index.i_length = p_chunk->i_size;
                 __AVI_AddEntryIndex( p_info, &index );
+                msg_Dbg( p_input, "add index entry (%4.4s) (%d)", 
+                                  (char*)&p_chunk->i_id, i ); 
+               
             }
         }
 #undef p_info
@@ -738,19 +741,19 @@ static int AVIInit( input_thread_t *p_input )
     if( RIFF_DescendChunk( p_input ) != 0 )
     {
         __AVIFreeDemuxData( p_input );
-        intf_ErrMsg( "input error: cannot go in (\"movi\") (avi_file)" );
+        msg_Err( p_input, "cannot go in (\"movi\")" );
         return( -1 );
     }
 
     /* print informations on streams */
-    intf_Msg( "input init: AVIH: %d stream, flags %s%s%s%s%s%s ", 
-            p_avi_demux->i_streams,
-            p_avi_demux->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
-            p_avi_demux->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
-            p_avi_demux->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
-            p_avi_demux->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"",
-            p_avi_demux->avih.i_flags&AVIF_WASCAPTUREFILE?" CAPTUREFILE":"",
-            p_avi_demux->avih.i_flags&AVIF_COPYRIGHTED?" COPYRIGHTED":"" );
+    msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s%s%s ", 
+             p_avi_demux->i_streams,
+             p_avi_demux->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
+             p_avi_demux->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
+             p_avi_demux->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
+             p_avi_demux->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"",
+             p_avi_demux->avih.i_flags&AVIF_WASCAPTUREFILE?" CAPTUREFILE":"",
+             p_avi_demux->avih.i_flags&AVIF_COPYRIGHTED?" COPYRIGHTED":"" );
 
     for( i = 0; i < p_avi_demux->i_streams; i++ )
     {
@@ -758,36 +761,36 @@ static int AVIInit( input_thread_t *p_input )
         switch( p_info->p_es->i_cat )
         {
             case( VIDEO_ES ):
-                intf_Msg("input init: video(%4.4s) %dx%d %dbpp %ffps (size %d)",
-                        (char*)&p_info->video_format.i_compression,
-                        p_info->video_format.i_width,
-                        p_info->video_format.i_height,
-                        p_info->video_format.i_bitcount,
-                        (float)p_info->header.i_rate /
-                            (float)p_info->header.i_scale,
-                        p_info->header.i_samplesize );
+                msg_Dbg( p_input, "video(%4.4s) %dx%d %dbpp %ffps (size %d)",
+                         (char*)&p_info->video_format.i_compression,
+                         p_info->video_format.i_width,
+                         p_info->video_format.i_height,
+                         p_info->video_format.i_bitcount,
+                         (float)p_info->header.i_rate /
+                             (float)p_info->header.i_scale,
+                         p_info->header.i_samplesize );
                 if( (p_avi_demux->p_info_video == NULL) ) 
                 {
                     p_avi_demux->p_info_video = p_info;
-               }
+                }
                 break;
 
             case( AUDIO_ES ):
-                intf_Msg( "input init: audio(0x%x) %d channels %dHz %dbits %ffps (size %d)",
-                        p_info->audio_format.i_formattag,
-                        p_info->audio_format.i_channels,
-                        p_info->audio_format.i_samplespersec,
-                        p_info->audio_format.i_bitspersample,
-                        (float)p_info->header.i_rate /
-                            (float)p_info->header.i_scale,
-                        p_info->header.i_samplesize );
+                msg_Dbg( p_input, "audio(0x%x) %d channels %dHz %dbits %ffps (size %d)",
+                         p_info->audio_format.i_formattag,
+                         p_info->audio_format.i_channels,
+                         p_info->audio_format.i_samplespersec,
+                         p_info->audio_format.i_bitspersample,
+                         (float)p_info->header.i_rate /
+                             (float)p_info->header.i_scale,
+                         p_info->header.i_samplesize );
                 if( (p_avi_demux->p_info_audio == NULL) ) 
                 {
                     p_avi_demux->p_info_audio = p_info;
                 }
                 break;
             case( UNKNOWN_ES ):
-                intf_Msg( "input init: unhanled stream %d", i );
+                msg_Warn( p_input, "unhandled stream %d", i );
         }
 #undef p_info    
     }
@@ -802,23 +805,20 @@ static int AVIInit( input_thread_t *p_input )
     }
     else
     {
-        /* TODO: if there is more than 1 video stream */
-        vlc_mutex_unlock( &p_input->stream.stream_lock );
-        intf_ErrMsg( "input error: no video stream found !" );
-        return( -1 );
+        msg_Err( p_input, "no video stream found" );
     }
+
     if( p_avi_demux->p_info_audio != NULL ) 
     {
         input_SelectES( p_input, p_avi_demux->p_info_audio->p_es );
     }
     else
     {
-        intf_Msg( "input init: no audio stream found !" );
+        msg_Warn( p_input, "no audio stream found!" );
     }
     p_input->stream.p_selected_program->b_is_ok = 1;
     vlc_mutex_unlock( &p_input->stream.stream_lock );
-
-
+    
     return( 0 );
 }
 
@@ -833,30 +833,26 @@ static void AVIEnd( input_thread_t *p_input )
 }
 
 
-static mtime_t __AVI_GetPTS( AVIStreamInfo_t *p_info )
+static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
 {
-    /* XXX you need to add p_info->i_date to have correct pts */
     /* p_info->p_index[p_info->i_idxposc] need to be valid !! */
-    mtime_t i_pts;
-
     /* be careful to  *1000000 before round  ! */
     if( p_info->header.i_samplesize != 0 )
     {
-        i_pts = (mtime_t)( (double)1000000.0 *
-                   ((double)p_info->p_index[p_info->i_idxposc].i_lengthtotal +
-                    (double)p_info->i_idxposb ) *
+        return( (mtime_t)( (double)1000000.0 *
+                   (double)(p_info->p_index[p_info->i_idxposc].i_lengthtotal +
+                             p_info->i_idxposb )*
                     (double)p_info->header.i_scale /
                     (double)p_info->header.i_rate /
-                    (double)p_info->header.i_samplesize );
+                    (double)p_info->header.i_samplesize ) );
     }
     else
     {
-        i_pts = (mtime_t)( (double)1000000.0 *
-                    (double)p_info->i_idxposc *
+        return( (mtime_t)( (double)1000000.0 *
+                    (double)(p_info->i_idxposc ) *
                     (double)p_info->header.i_scale /
-                    (double)p_info->header.i_rate);
+                    (double)p_info->header.i_rate) );
     }
-    return( i_pts );
 }
 
 
@@ -866,12 +862,12 @@ static int __AVI_NextIndexEntry( input_thread_t *p_input,
 {
     AVIIndexEntry_t index;
     riffchunk_t     *p_chunk;
-    demux_data_avi_file_t *p_avi_demux;
     AVIStreamInfo_t *p_info_tmp;
     int             i;
     int             i_idxposc;
     int             b_inc = 0;
-    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
+    demux_data_avi_file_t *p_avi_demux =
+                        (demux_data_avi_file_t*)p_input->p_demux_data;
 
     p_info->i_idxposc++;
 
@@ -879,25 +875,27 @@ static int __AVI_NextIndexEntry( input_thread_t *p_input,
     {
         return( 0 );
     }
+    if( p_info->i_idxposc > p_info->i_idxnb )
+    {
+        return( -1 );
+    }
     p_info->i_idxposc--;
+    
     /* create entry on the fly */
-    /* TODO: when parsing for a stream take care of the other to not do 
-       the same things two time */
-    /* search for the less advance stream and parse from it for all streams*/
+    /* search for the more advance stream and parse from it for all streams*/
     p_info_tmp = p_info;
-    
     for( i = 0; i < p_avi_demux->i_streams; i++ )
     {
 #define p_info_i p_avi_demux->pp_info[i]
-        if( p_info_i->p_index[p_info_i->i_idxnb - 1].i_offset + 
-                        p_info_i->i_idxoffset < 
-            p_info_tmp->p_index[p_info_tmp->i_idxnb - 1].i_offset +
-                        p_info_tmp->i_idxoffset )
+        if( ( p_info_i->p_index )
+            && ( p_info_i->p_index[p_info_i->i_idxnb - 1].i_pos >
+            p_info_tmp->p_index[p_info_tmp->i_idxnb - 1].i_pos ) )
         {
             p_info_tmp = p_info_i;
         }
 #undef  p_info_i
     }
+       
     /* go to last defined entry */
     i_idxposc = p_info_tmp->i_idxposc; /* save p_info_tmp->i_idxposc */
     p_info_tmp->i_idxposc = p_info_tmp->i_idxnb - 1;
@@ -906,9 +904,10 @@ static int __AVI_NextIndexEntry( input_thread_t *p_input,
 
     if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
     {
-        __AVI_SeekToChunk( p_input, p_info );
+        p_info->i_idxposc++;
         return( -1 );
     }
+
     /* save idxpos of p_info */
     /* now parse for all stream and stop when reach next chunk for p_info */
     for( i = 0; (i < 15)||(!b_inc); i++)
@@ -917,49 +916,40 @@ static int __AVI_NextIndexEntry( input_thread_t *p_input,
         u16 i_type;
         if( (p_chunk = RIFF_ReadChunk( p_input )) == NULL )
         {
-            if( b_inc )
-            {
-                return( 0 );
-            }
-            else
-            {
-                return( -1 );
-            }
+            p_info->i_idxposc++;
+            return( b_inc == 1 ? 0 : -1 );
         }
 
         index.i_id = p_chunk->i_id;
         index.i_flags = AVIIF_KEYFRAME;
-        index.i_offset = p_chunk->i_pos;
+        index.i_pos = p_chunk->i_pos;
         index.i_length = p_chunk->i_size;
         RIFF_DeleteChunk( p_input, p_chunk );
 #define p_info_i    p_avi_demux->pp_info[i_number]
        if( (__AVI_ParseStreamHeader( index.i_id, &i_number, &i_type ) == 0)
              &&( i_number < p_avi_demux->i_streams )
-             &&( p_info_i->p_index[p_info_i->i_idxnb - 1].i_offset + 
+             &&( p_info_i->p_index )
+             &&( p_info_i->p_index[p_info_i->i_idxnb - 1].i_pos + 
                      p_info_i->p_index[p_info_i->i_idxnb - 1].i_length + 8<= 
-                        index.i_offset ) 
+                        index.i_pos ) 
              &&( __AVIGetESTypeFromTwoCC( i_type ) == p_info_i->i_cat ) )
         {
             __AVI_AddEntryIndex( p_info_i, &index );
             if( (p_info_i == p_info)&&(!b_inc) )
             {
-                p_info->i_idxposc++;
                 b_inc = 1;
             }
         }
 #undef  p_info_i
         if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
         {
-            if( b_inc )
-            {
-                return( 0 );
-            }
-            else
-            {
-                return( -1 );
-            }
+            p_info->i_idxposc++;
+            return( b_inc == 1 ? 0 : -1 );
         }
+
     } 
+
+    p_info->i_idxposc++;
     return( 0 );
 }
 
@@ -980,15 +970,12 @@ static int __AVI_GoToStreamChunk( input_thread_t    *p_input,
                                   AVIStreamInfo_t   *p_info,
                                   int   i_chunk )
 {
-    demux_data_avi_file_t *p_avi_demux;
     u32   u32_pos;
     off_t i_pos;
-
-    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
     
     if( !p_input->stream.b_seekable )
     {
-        intf_ErrMsg( "input error: need the ability to seek in stream" );
+        msg_Err( p_input, "need the ability to seek in stream" );
         return( -1 );
     }
 
@@ -1013,8 +1000,7 @@ static int __AVI_GoToStreamChunk( input_thread_t    *p_input,
         /* now do we have valid index for the chunk */
         __RIFF_TellPos( p_input, &u32_pos );
 
-        i_pos = (off_t)p_info->p_index[i_chunk].i_offset +
-                     p_info->i_idxoffset;
+        i_pos = (off_t)p_info->p_index[i_chunk].i_pos;
         if( i_pos != u32_pos )
         {
             p_input->pf_seek( p_input, i_pos );
@@ -1033,14 +1019,12 @@ static int __AVI_GoToStreamBytes( input_thread_t    *p_input,
                                   AVIStreamInfo_t   *p_info,
                                   int   i_byte )
 {
-    demux_data_avi_file_t *p_avi_demux;
     u32   u32_pos;
     off_t i_pos;
-    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
-    
+
     if( !p_input->stream.b_seekable )
     {
-        intf_ErrMsg( "input error: need the ability to seek in stream" );
+        msg_Err( p_input, "need the ability to seek in stream" );
         return( -1 );
     }
 
@@ -1093,8 +1077,8 @@ static int __AVI_GoToStreamBytes( input_thread_t    *p_input,
         p_info->i_idxposb = i_byte - 
                        p_info->p_index[p_info->i_idxposc].i_lengthtotal;
         
-        i_pos = (off_t)p_info->p_index[p_info->i_idxposc].i_offset +
-                     p_info->i_idxoffset + p_info->i_idxposb + 8;
+        i_pos = (off_t)p_info->p_index[p_info->i_idxposc].i_pos +
+                      p_info->i_idxposb + 8;
         __RIFF_TellPos( p_input, &u32_pos );
         if( u32_pos != i_pos )
         {
@@ -1110,11 +1094,20 @@ static int __AVI_GoToStreamBytes( input_thread_t    *p_input,
 }
 
 static pes_packet_t *__AVI_ReadStreamChunkInPES(  input_thread_t    *p_input,
-                                                AVIStreamInfo_t   *p_info )
+                                                  AVIStreamInfo_t   *p_info )
 {
     pes_packet_t    *p_pes;
+    if( p_info->i_idxposc >= p_info->i_idxnb )
+    {
+        return( NULL );
+    }
+    /*- XXX avio is sh*t sometime chunk size is broken, and 
+      we must choose index sie */
+    
     if( ( __AVI_GoToStreamChunk( p_input, p_info, p_info->i_idxposc ) != 0 )
-         ||( RIFF_LoadChunkDataInPES( p_input, &p_pes) != 0 ) )
+         ||( RIFF_LoadChunkDataInPES( p_input, 
+                                      &p_pes,
+                            p_info->p_index[p_info->i_idxposc].i_length ) != 0 ) )
     {
         return( NULL );
     }
@@ -1130,60 +1123,64 @@ static pes_packet_t *__AVI_ReadStreamBytesInPES(  input_thread_t    *p_input,
                                                   AVIStreamInfo_t   *p_info,
                                                   int i_byte )
 {
-    pes_packet_t    *p_pes;
+    pes_packet_t    *p_pes = NULL;
     data_packet_t   *p_data;
     int             i_read;
-    /* make one pes with one data_packet with all the data */
+
     if( ( p_pes = input_NewPES( p_input->p_method_data ) ) == NULL )
     {
         return( NULL );
     }
-    p_pes->i_nb_data = 1;
-    if( (p_pes->p_first =
-            p_pes->p_last = 
-                input_NewPacket( p_input->p_method_data, i_byte ) ) ==NULL )
-    {
-        input_DeletePES( p_input->p_method_data, p_pes );
-        return( NULL );
-    }
     
-    do
+    while( i_byte > 0 )
     {
+        if( p_info->i_idxposc >= p_info->i_idxnb )
+        {
+            input_DeletePES( p_input->p_method_data, p_pes );
+            return( NULL );
+        }
         if( __AVI_GoToStreamBytes( p_input, p_info, 
                        p_info->p_index[p_info->i_idxposc].i_lengthtotal + 
                         p_info->i_idxposb ) != 0 )
         {
-            input_DeletePacket( p_input->p_method_data, p_pes->p_first );
             input_DeletePES( p_input->p_method_data, p_pes );
             return( NULL );
         }
+
         i_read = input_SplitBuffer(p_input, &p_data,
                                  __MIN( i_byte, 
                                  p_info->p_index[p_info->i_idxposc].i_length 
                                     - p_info->i_idxposb ) );
         if( i_read <= 0 )
         {
-           p_pes->p_first->p_demux_start = p_pes->p_first->p_payload_start;
-           p_pes->i_pes_size = p_pes->p_first->p_payload_end
-                                - p_pes->p_first->p_payload_start;
-           return( p_pes );
+            input_DeletePES( p_input->p_method_data, p_pes );
+            return( NULL );
+        }
+        p_pes->i_nb_data++;
+        if( !p_pes->p_first )
+        {
+            p_pes->p_first = p_data;
+        }
+        else
+        {
+            p_pes->p_last->p_next = p_data;
         }
-        FAST_MEMCPY( p_pes->p_first->p_demux_start, 
-                     p_data->p_demux_start,
-                     i_read );
+        p_pes->p_last = p_data;
+        p_pes->i_pes_size += i_read;
+
         i_byte -= i_read;
         p_info->i_idxposb += i_read;
-        p_pes->p_first->p_demux_start += i_read;
+
         if( p_info->i_idxposb >= p_info->p_index[p_info->i_idxposc].i_length )
         {
             p_info->i_idxposb = 0;
-            __AVI_NextIndexEntry( p_input, p_info);
+            if( __AVI_NextIndexEntry( p_input, p_info) != 0 )
+            {
+                input_DeletePES( p_input->p_method_data, p_pes );
+                return( NULL );
+            }
         }
-        input_DeletePacket( p_input->p_method_data, p_data );
-    } while( i_byte > 0 );
-   p_pes->p_first->p_demux_start = p_pes->p_first->p_payload_start;
-   p_pes->i_pes_size = p_pes->p_first->p_payload_end
-                        - p_pes->p_first->p_payload_start;
+    };
    return( p_pes );
 }
         
@@ -1191,75 +1188,89 @@ static pes_packet_t *__AVI_ReadStreamBytesInPES(  input_thread_t    *p_input,
  * Function to convert pts to chunk or byte
  *****************************************************************************/
 
-static __inline__ mtime_t __AVI_PTSToChunk( AVIStreamInfo_t *p_info, 
-                                            mtime_t i_pts )
+static inline mtime_t __AVI_PTSToChunk( AVIStreamInfo_t *p_info, 
+                                        mtime_t i_pts )
 {
-    return( (mtime_t)((mtime_t)i_pts *
-                      (mtime_t)p_info->header.i_rate /
-                      (mtime_t)p_info->header.i_scale /
-                      (mtime_t)1000000.0 ) );
+    return( (mtime_t)((double)i_pts *
+                      (double)p_info->header.i_rate /
+                      (double)p_info->header.i_scale /
+                      (double)1000000.0 ) );
 }
 
-static __inline__ mtime_t __AVI_PTSToByte( AVIStreamInfo_t *p_info,
-                                   mtime_t i_pts )
+static inline mtime_t __AVI_PTSToByte( AVIStreamInfo_t *p_info,
+                                       mtime_t i_pts )
 {
-    return( (mtime_t)((mtime_t)i_pts * 
-                      (mtime_t)p_info->header.i_samplesize *
-                      (mtime_t)p_info->header.i_rate /
-                      (mtime_t)p_info->header.i_scale /
-                      (mtime_t)1000000.0 ) );
+    return( (mtime_t)((double)i_pts * 
+                      (double)p_info->header.i_samplesize *
+                      (double)p_info->header.i_rate /
+                      (double)p_info->header.i_scale /
+                      (double)1000000.0 ) );
 
 }
 
 /* try to realign after a seek */
-static int __AVI_ReAlign( input_thread_t *p_input )
+static int AVI_ReAlign( input_thread_t *p_input )
 {
     u32     u32_pos;
     off_t   i_pos;
-    demux_data_avi_file_t *p_avi_demux;
+    int     b_after = 0;
     AVIStreamInfo_t *p_info;
+    demux_data_avi_file_t *p_avi_demux =
+                        (demux_data_avi_file_t*)p_input->p_demux_data;
 
-    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
     p_info = (p_avi_demux->p_info_video != NULL ) ? 
                     p_avi_demux->p_info_video :
                     p_avi_demux->p_info_audio;
     
     __RIFF_TellPos( p_input, &u32_pos );
     
-    i_pos = (off_t)u32_pos - (off_t)p_info->i_idxoffset;
+    i_pos = (off_t)u32_pos;
     
-    if( i_pos <= p_info->p_index[0].i_offset )
+    if( i_pos <= p_info->p_index[0].i_pos )
     {
         /*  before beginning of stream  */
         if( !p_info->header.i_samplesize )
         {
-            __AVI_GoToStreamChunk( p_input, p_info, 0 );
-        }
+            __AVI_GoToStreamChunk( p_input, 
+                                   p_info,
+                                   0 );
+        } 
         else
         {
-            __AVI_GoToStreamBytes( p_input, p_info, 0 );
+            __AVI_GoToStreamBytes( p_input, 
+                                   p_info, 
+                                   0);
         }
         return( 0 );
     }
 
-    if( (p_info->p_index[p_info->i_idxposc].i_offset <= i_pos)
-        && ( i_pos < p_info->p_index[p_info->i_idxposc].i_offset +
+    if( (p_info->p_index[p_info->i_idxposc].i_pos <= i_pos)
+        && ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos +
                 p_info->p_index[p_info->i_idxposc].i_length ) )
     {
+        /* FIXME if master == audio and samplesize != 0 */
+        /* don't work with big chunk */
         /* don't do anything we are in the current chunk  */
         return( 0 );
     }
-
+    if( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
+    {
+        b_after = 0;
+    }
+    else
+    {
+        b_after = 1;
+    }
     /* now find in what chunk we are */
-    while( ( i_pos < p_info->p_index[p_info->i_idxposc].i_offset )
+    while( ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
            &&( p_info->i_idxposc > 0 ) )
     {
         /* search before i_idxposc */
         p_info->i_idxposc--;
     }
     
-    while( i_pos >= p_info->p_index[p_info->i_idxposc].i_offset +
-               p_info->p_index[p_info->i_idxposc].i_length )
+    while( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos +
+               p_info->p_index[p_info->i_idxposc].i_length + 8 )
     {
         /* search after i_idxposc */
         if( __AVI_NextIndexEntry( p_input, p_info ) != 0 )
@@ -1271,121 +1282,96 @@ static int __AVI_ReAlign( input_thread_t *p_input )
     if( ( !p_info->header.i_samplesize ) && ( p_info->i_cat == VIDEO_ES ) )
     {
         /* only for chunk stream */
-        int     i_idxposc   = p_info->i_idxposc;
-        int     i_idxposc_b = p_info->i_idxposc; /* before */
-        int     i_idxposc_a ;                    /* after */
-        
-        while( ( i_idxposc_b > 0 )
-                &&((p_info->p_index[i_idxposc_b].i_flags&AVIIF_KEYFRAME) == 0) )
+        if( b_after )
         {
-            i_idxposc_b--;
+            while(!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME) )
+            {
+                if( __AVI_NextIndexEntry( p_input, p_info ) != 0 )
+                {
+                    break;
+                }
+            }
         }
-
-        while((p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME) == 0 )
-        {
-            if( __AVI_NextIndexEntry( p_input, p_info ) != 0 )
+        else
+        { 
+            while( ( p_info->i_idxposc > 0 ) &&
+              (!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME)) )
             {
-                break;
+                p_info->i_idxposc--;
             }
         }
-        i_idxposc_a = p_info->i_idxposc;
-       
-        i_idxposc = (i_idxposc_a - i_idxposc <
-                        i_idxposc - i_idxposc_b ) ? i_idxposc_a : i_idxposc_b; 
-        __AVI_GoToStreamChunk( p_input, p_info, i_idxposc );
     } 
-    
+    __AVI_GoToStreamChunk( p_input, p_info, p_info->i_idxposc );
+   
     return( 0 );
 }
 
-/* update i_date and */
 /* make difference between audio and video pts as little as possible */
-static void __AVI_SynchroReInit( input_thread_t *p_input )
+static void AVI_SynchroReInit( input_thread_t *p_input )
 {
-    demux_data_avi_file_t *p_avi_demux;
-
-    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
-    p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_OK;
-
-    if( p_avi_demux->p_info_video == NULL )
+    demux_data_avi_file_t *p_avi_demux =
+                        (demux_data_avi_file_t*)p_input->p_demux_data;
+#define p_info_video p_avi_demux->p_info_video
+#define p_info_audio p_avi_demux->p_info_audio
+    if( ( p_info_video )&&( p_info_audio ) )
     {
-        p_avi_demux->i_date = mdate() + DEFAULT_PTS_DELAY
-                - __AVI_GetPTS( p_avi_demux->p_info_audio );
-        return;
-    }
-    else
-    {
-        p_avi_demux->i_date = mdate() + DEFAULT_PTS_DELAY
-                - __AVI_GetPTS( p_avi_demux->p_info_video );
         /* now resynch audio video video */
         /*don't care of AVIF_KEYFRAME */
-        if( p_avi_demux->p_info_audio != NULL )
+        if( !p_info_audio->header.i_samplesize )
         {
-            if( p_avi_demux->p_info_audio->header.i_samplesize == 0 )
-            {
-                int i_chunk = __AVI_PTSToChunk( p_avi_demux->p_info_audio, 
-                                    __AVI_GetPTS( p_avi_demux->p_info_video ));
-                if( i_chunk < 0 )
-                {
-                    i_chunk = 0;
-                }
-                __AVI_GoToStreamChunk( p_input, 
-                                       p_avi_demux->p_info_audio, 
-                                       i_chunk );            
-            }
-            else
-            {
-                int i_byte = __AVI_PTSToByte( p_avi_demux->p_info_audio, 
-                                    __AVI_GetPTS( p_avi_demux->p_info_video ) );
-                if( i_byte < 0 )
-                {
-                    i_byte = 0;
-                }
-                __AVI_GoToStreamBytes( p_input, 
-                                       p_avi_demux->p_info_audio,
-                                       i_byte );
-            }
+            int i_chunk = __AVI_PTSToChunk( p_info_audio, 
+                                            AVI_GetPTS( p_info_video ));
+            __AVI_GoToStreamChunk( p_input, 
+                                   p_info_audio, 
+                                   i_chunk );
+        }
+        else
+        {
+            int i_byte = __AVI_PTSToByte( p_info_audio, 
+                                          AVI_GetPTS( p_info_video ) ) ;
+            __AVI_GoToStreamBytes( p_input,
+                                   p_info_audio,
+                                   i_byte );
         }
    }
-            
+#undef p_info_video
+#undef p_info_audio
 } 
 
-static pes_packet_t *__AVI_GetFrameInPES( input_thread_t *p_input,
-                                          AVIStreamInfo_t *p_info,
-                                          mtime_t i_dpts)
+/*****************************************************************************
+ * AVI_GetFrameInPES : get dpts length(µs) in pes from stream
+ *****************************************************************************
+ * Handle multiple pes, and set pts to the good value 
+ *****************************************************************************/
+static pes_packet_t *AVI_GetFrameInPES( input_thread_t *p_input,
+                                        AVIStreamInfo_t *p_info,
+                                        mtime_t i_dpts)
 {
     int i;
     pes_packet_t *p_pes = NULL;
     pes_packet_t *p_pes_tmp = NULL;
     pes_packet_t *p_pes_first = NULL;
     mtime_t i_pts;
-    demux_data_avi_file_t *p_avi_demux;
-    
-    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
-    
-    if( ( !p_info)||(i_dpts < 0 ) ) 
+
+    /* we now that p_info != NULL */
+    if( i_dpts < 1000 ) 
     { 
         return( NULL ) ; 
     }
-    /* if i_pts is too small use 100 ms */
-    if( i_dpts <= 100000)
-    {
-        i_dpts = 100000; /* 100 ms by default */
-    }
 
     if( !p_info->header.i_samplesize )
     {
         /* stream is chunk based , easy */
-        int i_chunk = __MAX( __AVI_PTSToChunk( p_info, i_dpts) , 1 );
+        int i_chunk = __MAX( __AVI_PTSToChunk( p_info, i_dpts), 1 );
         /* at least one frame */
-        i_chunk = __MIN( 20, i_chunk ); /* but no more than 20 */
         /* read them */
         p_pes_first = NULL;
         for( i = 0; i < i_chunk; i++ )
         {
             /* get pts while is valid */
-            i_pts = __AVI_GetPTS( p_info );
+            i_pts = AVI_GetPTS( p_info );
             p_pes_tmp = __AVI_ReadStreamChunkInPES( p_input, p_info );
+
             if( !p_pes_tmp )
             {
                 return( p_pes_first );
@@ -1406,12 +1392,17 @@ static pes_packet_t *__AVI_GetFrameInPES( input_thread_t *p_input,
     else
     {
         /* stream is byte based */
-        int i_byte = __MAX( __AVI_PTSToByte( p_info, i_dpts), 1024 );
-         /* at least one Kbyte */
-        i_byte = __MIN( 1024*1000, i_byte ); /* but no more than 1000ko */
-        i_pts = __AVI_GetPTS( p_info );
+        int i_byte = __AVI_PTSToByte( p_info, i_dpts);
+        if( !i_byte )
+        {
+            return( NULL );
+        }
+        /* at least one Kbyte */
+        /*i_byte = __MIN( 1024*1000, i_byte ); *//* but no more than 1000ko */
+        i_pts = AVI_GetPTS( p_info );
 
         p_pes = __AVI_ReadStreamBytesInPES( p_input, p_info, i_byte);
+        
         if( p_pes != NULL )
         {
             p_pes->i_pts = i_pts;
@@ -1419,33 +1410,29 @@ static pes_packet_t *__AVI_GetFrameInPES( input_thread_t *p_input,
         return( p_pes );
     }
 }
-
-static void __AVI_DecodePES( AVIStreamInfo_t *p_info,
-                             pes_packet_t *p_pes,
-                             mtime_t    i_date )
+/*****************************************************************************
+ * AVI_DecodePES : send a pes to decoder 
+ *****************************************************************************
+ * Handle multiple pes, and set pts to the good value 
+ *****************************************************************************/
+static inline void AVI_DecodePES( input_thread_t *p_input,
+                                  AVIStreamInfo_t *p_info,
+                                  pes_packet_t *p_pes )
 {
-     pes_packet_t    *p_pes_next;
-    if( ( !p_info )||( !p_pes ) )
-    {
-        return;
-    }
-    vlc_mutex_lock( &p_info->p_es->p_decoder_fifo->data_lock );
-    if( p_info->p_es->p_decoder_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
-    {
-        vlc_cond_wait( &p_info->p_es->p_decoder_fifo->data_wait,
-                       &p_info->p_es->p_decoder_fifo->data_lock );
-    }
-    vlc_mutex_unlock( &p_info->p_es->p_decoder_fifo->data_lock );
+    pes_packet_t    *p_pes_next;
     /* input_decode want only one pes, but AVI_GetFrameInPES give
           multiple pes so send one by one */
-    do
+    /* we now that p_info != NULL */
+    while( p_pes )
     {
         p_pes_next = p_pes->p_next;
         p_pes->p_next = NULL;
-        p_pes->i_pts += i_date;
+        p_pes->i_pts = input_ClockGetTS( p_input, 
+                                         p_input->stream.p_selected_program, 
+                                         p_pes->i_pts * 9/100);
         input_DecodePES( p_info->p_es->p_decoder_fifo, p_pes );
         p_pes = p_pes_next;
-    } while( p_pes != NULL );
+    };
   
 }
 
@@ -1457,15 +1444,12 @@ static void __AVI_DecodePES( AVIStreamInfo_t *p_info,
 static int AVIDemux( input_thread_t *p_input )
 {
     int i;
-    pes_packet_t *p_pes_audio;
-    pes_packet_t *p_pes_video;
-    demux_data_avi_file_t *p_avi_demux;
+    pes_packet_t *p_pes;
+    AVIStreamInfo_t *p_info_master;
+    AVIStreamInfo_t *p_info_slave;    
 
-/*     try to use this to read data packet at the good time
- *     input_ClockManageRef( p_input,
-                            p_input->stream.p_selected_program,
-                            (mtime_t)pcr );  ??? what is supposed to do */
-    p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data;
+    demux_data_avi_file_t *p_avi_demux = 
+                (demux_data_avi_file_t*)p_input->p_demux_data;
 
     /* search new video and audio stream selected 
           if current have been unselected*/
@@ -1499,75 +1483,100 @@ static int AVIDemux( input_thread_t *p_input )
             }
         }
     }
-    /* for now, we need at least one video stream */
-    if( !p_avi_demux->p_info_video ) 
+    /* by default video is master for resync audio (after a seek .. ) */
+    if( p_avi_demux->p_info_video )
     {
-        intf_ErrMsg( "input error: no video ouput selected" );
-        return( -1 );
+        p_info_master = p_avi_demux->p_info_video;
+        p_info_slave  = p_avi_demux->p_info_audio;
+    }
+    else
+    {
+        p_info_master = p_avi_demux->p_info_audio;
+        p_info_slave  = NULL;
     }
 
-    /* check for signal from interface */
-    if( (input_ClockManageControl( p_input, p_input->stream.p_selected_program,
-                            (mtime_t)0) == PAUSE_S) )
-    {   
-        __AVI_SynchroReInit( p_input ); /* resynchro, and make pts audio 
-                                            and video egual */
+    if( !p_info_master ) 
+    {
+        msg_Err( p_input, "no stream selected" );
+        return( -1 );
     }
 
+    /* check for signal from interface */
     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
     { 
-       /*realign audio and video stream to the good pts*/
-        if( __AVI_ReAlign( p_input ) != 0 )
+        /* we can supposed that is a seek */
+        /* first wait for empty buffer, arbitrary time */
+        msleep( DEFAULT_PTS_DELAY );
+        /* then try to realign in stream */
+        if( AVI_ReAlign( p_input ) != 0 )
         {
             return( 0 ); /* assume EOF */
         }
-        __AVI_SynchroReInit( p_input ); /* resynchro, and make pts audio 
-                                            and video egual */
+        AVI_SynchroReInit( p_input ); 
     }
-
+    /* manage rate, if not default: skeep audio */
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    if( p_input->stream.control.i_rate != p_avi_demux->i_rate )
+    {
+        if( p_avi_demux->p_info_audio)
+        {
+             p_avi_demux->p_info_audio->b_selected = 1;
+        }
+        p_avi_demux->i_rate = p_input->stream.control.i_rate;
+    }
+    vlc_mutex_unlock( &p_input->stream.stream_lock );    
+    if( p_avi_demux->i_rate != DEFAULT_RATE )
+    {
+        p_info_slave = NULL;
+    }
     /* take care of newly selected audio ES */
-    if( (p_avi_demux->p_info_audio != NULL)
-                    &&(p_avi_demux->p_info_audio->b_selected ))
+    if( p_info_master->b_selected )
     {
-        p_avi_demux->p_info_audio->b_selected = 0 ;
-        __AVI_SynchroReInit( p_input ); /* resynchro, and make pts audio
-                                            and video egual */
+        p_info_master->b_selected = 0;
+        AVI_SynchroReInit( p_input ); 
     }
-    /* get audio and video frame */
-    if( p_avi_demux->p_info_video != NULL )
+    if( ( p_info_slave )&&( p_info_slave->b_selected ) )
     {
-       p_pes_video = __AVI_GetFrameInPES( p_input,
-                                           p_avi_demux->p_info_video,
-                                           100000 ); /* 100 ms */
-        if( p_avi_demux->p_info_audio != NULL )
-        {
-           p_pes_audio = __AVI_GetFrameInPES( p_input,
-                                               p_avi_demux->p_info_audio,
-                                   __AVI_GetPTS( p_avi_demux->p_info_video) -
-                                   __AVI_GetPTS( p_avi_demux->p_info_audio) );
-        }
-        else
-        {
-           p_pes_audio = NULL;
-        }
+        p_info_slave->b_selected = 0;
+        AVI_SynchroReInit( p_input );
+    }
+
+    /* wait for the good time */
+    input_ClockManageRef( p_input,
+                          p_input->stream.p_selected_program,
+                          p_avi_demux->i_pcr ); 
+    /* calculate pcr, time when we must read the next data */
+    /* 9/100 kludge ->need to convert to 1/1000000 clock unit to 1/90000 */
+    if( p_info_slave )
+    {
+        p_avi_demux->i_pcr =  __MIN( AVI_GetPTS( p_info_master ),
+                                     AVI_GetPTS( p_info_slave ) ) * 9/100;
     }
     else
     {
-        p_pes_video = NULL;
-        p_pes_audio = __AVI_GetFrameInPES( p_input,
-                                           p_avi_demux->p_info_audio,
-                                           100000 ); /* 100 ms */
+        p_avi_demux->i_pcr =  AVI_GetPTS( p_info_master ) * 9/100;
     }
-    /* send them to decoder */
-    __AVI_DecodePES( p_avi_demux->p_info_audio, p_pes_audio,
-                     p_avi_demux->i_date );
-    __AVI_DecodePES( p_avi_demux->p_info_video, p_pes_video,
-                     p_avi_demux->i_date );
-   
-    if( !p_pes_video )  /* no more video */
-    {                          /* currently i need a video stream */
-       return( 0 );
+
+    /* get video and audio frames */
+    p_pes = AVI_GetFrameInPES( p_input,
+                               p_info_master,
+                               100000 ); /* 100 ms */
+
+    AVI_DecodePES( p_input,
+                   p_info_master,
+                   p_pes);
+
+    if( p_info_slave )
+    {
+        p_pes = AVI_GetFrameInPES( p_input,
+                                   p_info_slave,
+                                   AVI_GetPTS( p_info_master ) -
+                                       AVI_GetPTS( p_info_slave));
+        AVI_DecodePES( p_input,
+                       p_info_slave,
+                       p_pes );
     }
-    
-    return( 1 );
+    /* at the end ? */
+    return( p_info_master->i_idxposc >= p_info_master->i_idxnb ? 0 : 1 );
 }