]> git.sesse.net Git - vlc/blobdiff - modules/demux/avi/avi.c
* Stringreview !!!
[vlc] / modules / demux / avi / avi.c
index c50ad775c8b6af74fdc92a9444a979ecb3378a0f..53d3e66f6896d44a7d7076409ff5c349a583030e 100644 (file)
@@ -1,15 +1,15 @@
 /*****************************************************************************
  * avi.c : AVI file Stream input module for vlc
  *****************************************************************************
- * Copyright (C) 2001 VideoLAN
- * $Id: avi.c,v 1.3 2002/08/08 22:28:22 sam Exp $
+ * Copyright (C) 2001-2004 VideoLAN
+ * $Id: avi.c,v 1.85 2004/01/25 20:05:28 hartman Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * Preamble
  *****************************************************************************/
 #include <stdlib.h>                                      /* malloc(), free() */
-#include <string.h>                                              /* strdup() */
-#include <errno.h>
-#include <sys/types.h>
 
 #include <vlc/vlc.h>
 #include <vlc/input.h>
+#include "vlc_playlist.h"
+#include "codecs.h"
 
-#include "video.h"
-
-#include "libioRIFF.h"
+#include "libavi.h"
 #include "avi.h"
 
 /*****************************************************************************
- * Local prototypes
+ * Module descriptor
  *****************************************************************************/
-static int    AVIInit   ( vlc_object_t * );
-static void __AVIEnd    ( vlc_object_t * );
-static int    AVIDemux  ( input_thread_t * );
 
-#define AVIEnd(a) __AVIEnd(VLC_OBJECT(a))
+#define INTERLEAVE_TEXT N_("Force interleaved method" )
+#define INTERLEAVE_LONGTEXT N_( "Force interleaved method" )
+
+#define INDEX_TEXT N_("Force index creation")
+#define INDEX_LONGTEXT N_( \
+    "Recreate a index for the AVI file so we can seek trough it more reliably." ) 
+
+static int  Open   ( vlc_object_t * );
+static void Close  ( vlc_object_t * );
 
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
 vlc_module_begin();
-    set_description( "RIFF-AVI demuxer" );
-    set_capability( "demux", 150 );
-    set_callbacks( AVIInit, __AVIEnd );
+    set_description( _("AVI demuxer") );
+    set_capability( "demux", 212 );
+    
+    add_bool( "avi-interleaved", 0, NULL,
+              INTERLEAVE_TEXT, INTERLEAVE_LONGTEXT, VLC_TRUE );
+    add_bool( "avi-index", 0, NULL,
+              INDEX_TEXT, INDEX_LONGTEXT, VLC_TRUE );
+
+    set_callbacks( Open, Close );
 vlc_module_end();
 
 /*****************************************************************************
- * Some usefull functions to manipulate memory 
+ * Local prototypes
  *****************************************************************************/
-static u16 GetWLE( byte_t *p_buff )
-{
-    u16 i;
-    i = (*p_buff) + ( *(p_buff + 1) <<8 );
-    return ( i );
-}
-static u32 GetDWLE( byte_t *p_buff )
-{
-    u32 i;
-    i = (*p_buff) + ( *(p_buff + 1) <<8 ) + 
-            ( *(p_buff + 2) <<16 ) + ( *(p_buff + 3) <<24 );
-    return ( i );
-}
-static u32 GetDWBE( byte_t *p_buff )
-{
-    u32 i;
-    i = ((*p_buff)<<24) + ( *(p_buff + 1) <<16 ) + 
-            ( *(p_buff + 2) <<8 ) + ( *(p_buff + 3) );
-    return ( i );
-}
+static int    Control         ( input_thread_t *, int, va_list );
+static int    Seek            ( input_thread_t *, mtime_t, int );
+static int    Demux_Seekable  ( input_thread_t * );
+static int    Demux_UnSeekable( input_thread_t *p_input );
+
+#define FREE( p ) if( p ) { free( p ); (p) = NULL; }
+#define __ABS( x ) ( (x) < 0 ? (-(x)) : (x) )
+
 static inline off_t __EVEN( off_t i )
 {
-    return( (i & 1) ? i+1 : i );
+    return (i & 1) ? i + 1 : i;
 }
 
+static mtime_t AVI_PTSToChunk( avi_track_t *, mtime_t i_pts );
+static mtime_t AVI_PTSToByte ( avi_track_t *, mtime_t i_pts );
+static mtime_t AVI_GetDPTS   ( avi_track_t *, int64_t i_count );
+static mtime_t AVI_GetPTS    ( avi_track_t * );
+
+
+static int AVI_StreamChunkFind( input_thread_t *, unsigned int i_stream );
+static int AVI_StreamChunkSet ( input_thread_t *,
+                                unsigned int i_stream, unsigned int i_ck );
+static int AVI_StreamBytesSet ( input_thread_t *,
+                                unsigned int i_stream, off_t   i_byte );
+
+vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t );
+static int   AVI_GetKeyFlag    ( vlc_fourcc_t , uint8_t * );
+
+static int AVI_PacketGetHeader( input_thread_t *, avi_packet_t *p_pk );
+static int AVI_PacketNext     ( input_thread_t * );
+static int AVI_PacketRead     ( input_thread_t *, avi_packet_t *, block_t **);
+static int AVI_PacketSearch   ( input_thread_t * );
+
+static void AVI_IndexLoad    ( input_thread_t * );
+static void AVI_IndexCreate  ( input_thread_t * );
+static void AVI_IndexAddEntry( demux_sys_t *, int, AVIIndexEntry_t * );
+
+static mtime_t  AVI_MovieGetLength( input_thread_t * );
 
 /*****************************************************************************
- * Functions for parsing the headers in an avi file
+ * Stream management
  *****************************************************************************/
-static void AVI_Parse_avih( MainAVIHeader_t *p_avih, byte_t *p_buff )
-{
-    p_avih->i_microsecperframe = GetDWLE( p_buff );
-    p_avih->i_maxbytespersec   = GetDWLE( p_buff + 4);
-    p_avih->i_reserved1        = GetDWLE( p_buff + 8);
-    p_avih->i_flags            = GetDWLE( p_buff + 12);
-    p_avih->i_totalframes      = GetDWLE( p_buff + 16);
-    p_avih->i_initialframes    = GetDWLE( p_buff + 20);
-    p_avih->i_streams          = GetDWLE( p_buff + 24);
-    p_avih->i_suggestedbuffersize = GetDWLE( p_buff + 28);
-    p_avih->i_width            = GetDWLE( p_buff + 32 );
-    p_avih->i_height           = GetDWLE( p_buff + 36 );
-    p_avih->i_scale            = GetDWLE( p_buff + 40 );
-    p_avih->i_rate             = GetDWLE( p_buff + 44 );
-    p_avih->i_start            = GetDWLE( p_buff + 48);
-    p_avih->i_length           = GetDWLE( p_buff + 52);
-}
-static void AVI_Parse_Header( AVIStreamHeader_t *p_strh, byte_t *p_buff )
-{
-    p_strh->i_type      = GetDWLE( p_buff );
-    p_strh->i_handler   = GetDWLE( p_buff + 4 );
-    p_strh->i_flags     = GetDWLE( p_buff + 8 );
-    p_strh->i_reserved1 = GetDWLE( p_buff + 12);
-    p_strh->i_initialframes = GetDWLE( p_buff + 16);
-    p_strh->i_scale     = GetDWLE( p_buff + 20);
-    p_strh->i_rate      = GetDWLE( p_buff + 24);
-    p_strh->i_start     = GetDWLE( p_buff + 28);
-    p_strh->i_length    = GetDWLE( p_buff + 32);
-    p_strh->i_suggestedbuffersize = GetDWLE( p_buff + 36);
-    p_strh->i_quality   = GetDWLE( p_buff + 40);
-    p_strh->i_samplesize = GetDWLE( p_buff + 44);
-}
-static void AVI_Parse_BitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
-{
-    h->i_size          = GetDWLE( p_data );
-    h->i_width         = GetDWLE( p_data + 4 );
-    h->i_height        = GetDWLE( p_data + 8 );
-    h->i_planes        = GetWLE( p_data + 12 );
-    h->i_bitcount      = GetWLE( p_data + 14 );
-    h->i_compression   = GetDWLE( p_data + 16 );
-    h->i_sizeimage     = GetDWLE( p_data + 20 );
-    h->i_xpelspermeter = GetDWLE( p_data + 24 );
-    h->i_ypelspermeter = GetDWLE( p_data + 28 );
-    h->i_clrused       = GetDWLE( p_data + 32 );
-    h->i_clrimportant  = GetDWLE( p_data + 36 );
-}
-static void AVI_Parse_WaveFormatEx( waveformatex_t *h, byte_t *p_data )
-{
-    h->i_formattag     = GetWLE( p_data );
-    h->i_channels      = GetWLE( p_data + 2 );
-    h->i_samplespersec = GetDWLE( p_data + 4 );
-    h->i_avgbytespersec= GetDWLE( p_data + 8 );
-    h->i_blockalign    = GetWLE( p_data + 12 );
-    h->i_bitspersample = GetWLE( p_data + 14 );
-    h->i_size          = GetWLE( p_data + 16 );
-}
+static int        AVI_TrackSeek  ( input_thread_t *, int, mtime_t );
+static int        AVI_TrackStopFinishedStreams( input_thread_t *);
+
+/* Remarks:
+ - For VBR mp3 stream:
+    count blocks by rounded-up chunksizes instead of chunks
+    we need full emulation of dshow avi demuxer bugs :(
+    fixes silly nandub-style a-v delaying in avi with vbr mp3...
+    (from mplayer 2002/08/02)
+ - to complete....
+ */
 
-static inline int AVI_GetESTypeFromTwoCC( u16 i_type )
+/*****************************************************************************
+ * Open: check file and initializes AVI structures
+ *****************************************************************************/
+static int Open( vlc_object_t * p_this )
 {
-    switch( i_type )
+    input_thread_t  *p_input = (input_thread_t *)p_this;
+    demux_sys_t     *p_sys;
+
+    avi_chunk_t         ck_riff;
+    avi_chunk_list_t    *p_riff = (avi_chunk_list_t*)&ck_riff;
+    avi_chunk_list_t    *p_hdrl, *p_movi;
+    avi_chunk_avih_t    *p_avih;
+
+    unsigned int i_track;
+    unsigned int i;
+
+    uint8_t  *p_peek;
+
+
+    /* Is it an avi file ? */
+    if( stream_Peek( p_input->s, &p_peek, 12 ) < 12 )
     {
-        case( TWOCC_wb ):
-            return( AUDIO_ES );
-         case( TWOCC_dc ):
-         case( TWOCC_db ):
-            return( VIDEO_ES );
-         default:
-            return( UNKNOWN_ES );
+        msg_Err( p_input, "cannot peek()" );
+        return VLC_EGENERIC;
+    }
+    if( strncmp( &p_peek[0], "RIFF", 4 ) || strncmp( &p_peek[8], "AVI ", 4 ) )
+    {
+        msg_Warn( p_input, "avi module discarded (invalid header)" );
+        return VLC_EGENERIC;
     }
-}
 
-static vlc_fourcc_t AVI_AudioGetType( u32 i_type )
-{
-    switch( i_type )
-    {
-/*        case( WAVE_FORMAT_PCM ):
-            return VLC_FOURCC('l','p','c','m'); */
-        case( WAVE_FORMAT_A52 ):
-            return VLC_FOURCC('a','5','2',' ');
-        case( WAVE_FORMAT_MPEG):
-        case( WAVE_FORMAT_MPEGLAYER3):
-            return VLC_FOURCC('m','p','g','a'); /* for mpeg2 layer 1 2 ou 3 */
-        default:
-            return 0;
+    /* Initialize input  structures. */
+    p_sys = p_input->p_demux_data = malloc( sizeof(demux_sys_t) );
+    memset( p_sys, 0, sizeof( demux_sys_t ) );
+    p_sys->i_time   = 0;
+    p_sys->i_length = 0;
+    p_sys->i_pcr    = 0;
+    p_sys->i_movi_lastchunk_pos = 0;
+    p_sys->b_odml   = VLC_FALSE;
+    p_sys->i_track  = 0;
+    p_sys->track    = NULL;
+
+    stream_Control( p_input->s, STREAM_CAN_FASTSEEK, &p_sys->b_seekable );
+
+    p_input->pf_demux_control = Control;
+    p_input->pf_demux = Demux_Seekable;
+    /* For unseekable stream, automaticaly use Demux_UnSeekable */
+    if( !p_sys->b_seekable || config_GetInt( p_input, "avi-interleaved" ) )
+    {
+        p_input->pf_demux = Demux_UnSeekable;
     }
-}
 
-/* Test if it seems that it's a key frame */
-static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, u8 *p_byte )
-{
-    switch( i_fourcc )
+    if( AVI_ChunkReadRoot( p_input->s, &p_sys->ck_root ) )
     {
-        case FOURCC_DIV1:
-        case FOURCC_div1:
-        case FOURCC_MPG4:
-        case FOURCC_mpg4:
-            if( GetDWBE( p_byte ) != 0x00000100 ) 
-            /* startcode perhaps swapped, I haven't tested */
-            {
-            /* it's seems it's not an msmpegv1 stream 
-               but perhaps I'm wrong so return yes */
-                return( AVIIF_KEYFRAME );
-            }
-            else
-            {
-                return( (*(p_byte+4))&0x06 ? 0 : AVIIF_KEYFRAME);
-            }
-        case FOURCC_DIV2:
-        case FOURCC_div2:
-        case FOURCC_MP42:
-        case FOURCC_mp42:
-        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( (*p_byte)&0xC0 ? 0 : AVIIF_KEYFRAME );
-        case FOURCC_DIVX:
-        case FOURCC_divx:
-        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:
-            if( GetDWBE( p_byte ) != 0x000001b6 )
-            {
-                /* not true , need to find the first VOP header
-                    but, I'm lazy */
-                return( AVIIF_KEYFRAME );
-            }
-            else
+        msg_Err( p_input, "avi module discarded (invalid file)" );
+        return VLC_EGENERIC;
+    }
+
+    if( AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF ) > 1 )
+    {
+        unsigned int i_count =
+            AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF );
+
+        msg_Warn( p_input, "multiple riff -> OpenDML ?" );
+        for( i = 1; i < i_count; i++ )
+        {
+            avi_chunk_list_t *p_sysx;
+
+            p_sysx = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, i );
+            if( p_sysx->i_type == AVIFOURCC_AVIX )
             {
-                return( (*(p_byte+4))&0xC0 ? 0 : AVIIF_KEYFRAME );
+                msg_Warn( p_input, "detected OpenDML file" );
+                p_sys->b_odml = VLC_TRUE;
+                break;
             }
-        default:
-            /* I can't do it, so said yes */
-            return( AVIIF_KEYFRAME );
+        }
     }
 
-}
-/*****************************************************************************
- * Data and functions to manipulate pes buffer
- *****************************************************************************/
-#define BUFFER_MAXTOTALSIZE   512*1024 /* 1/2 Mo */
-#define BUFFER_MAXSPESSIZE 1024*200
-static int  AVI_PESBuffer_IsFull( AVIStreamInfo_t *p_info )
-{
-    return( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE ? 1 : 0);
-}
-static void AVI_PESBuffer_Add( input_buffers_t *p_method_data,
-                               AVIStreamInfo_t *p_info,
-                               pes_packet_t *p_pes,
-                               int i_posc,
-                               int i_posb )
-{
-    AVIESBuffer_t   *p_buffer_pes;
+    p_riff  = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0 );
+    p_hdrl  = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
+    p_movi  = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0 );
 
-    if( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE )
+    if( !p_hdrl || !p_movi )
     {
-        input_DeletePES( p_method_data, p_pes );
-        return;
+        msg_Err( p_input, "avi module discarded (invalid file)" );
+        goto error;
     }
-    
-    if( !( p_buffer_pes = malloc( sizeof( AVIESBuffer_t ) ) ) )
+
+    if( !( p_avih = AVI_ChunkFind( p_hdrl, AVIFOURCC_avih, 0 ) ) )
     {
-        input_DeletePES( p_method_data, p_pes );
-        return;
+        msg_Err( p_input, "cannot find avih chunk" );
+        goto error;
     }
-    p_buffer_pes->p_next = NULL;
-    p_buffer_pes->p_pes = p_pes;
-    p_buffer_pes->i_posc = i_posc;
-    p_buffer_pes->i_posb = i_posb;
-
-    if( p_info->p_pes_last ) 
+    i_track = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl );
+    if( p_avih->i_streams != i_track )
     {
-        p_info->p_pes_last->p_next = p_buffer_pes;
+        msg_Warn( p_input,
+                  "found %d stream but %d are declared",
+                  i_track, p_avih->i_streams );
     }
-    p_info->p_pes_last = p_buffer_pes;
-    if( !p_info->p_pes_first )
+    if( i_track == 0 )
     {
-        p_info->p_pes_first = p_buffer_pes;
+        msg_Err( p_input, "no stream defined!" );
+        goto error;
     }
-    p_info->i_pes_count++;
-    p_info->i_pes_totalsize += p_pes->i_pes_size;
-}
-static pes_packet_t *AVI_PESBuffer_Get( AVIStreamInfo_t *p_info )
-{
-    AVIESBuffer_t   *p_buffer_pes;
-    pes_packet_t    *p_pes;
-    if( p_info->p_pes_first )
+
+    /*  create one program */
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    if( input_InitStream( p_input, 0 ) == -1)
+    {
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+        msg_Err( p_input, "cannot init stream" );
+        goto error;
+    }
+    p_input->stream.i_mux_rate = 0; /* Fixed later */
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+    /* print informations on streams */
+    msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ",
+             i_track,
+             p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
+             p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
+             p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
+             p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
+    {
+        playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_input,
+                        VLC_OBJECT_PLAYLIST,  FIND_PARENT);
+        input_info_category_t *p_cat = input_InfoCategory( p_input, _("Avi") );
+
+        input_AddInfo( p_cat, _("Number of streams"), "%d", i_track );
+        input_AddInfo( p_cat, _("Flags"), "%s%s%s%s",
+                       p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
+                       p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
+                       p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
+                       p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
+        if( p_playlist )
+        {
+            playlist_AddInfo( p_playlist, -1 , _("Avi"),
+                          _("Number of streams"), "%d", i_track );
+            playlist_AddInfo( p_playlist, -1 , _("Avi"),
+                       _("Flags"), "%s%s%s%s",
+                       p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
+                       p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
+                       p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
+                       p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
+            vlc_object_release( p_playlist );
+        }
+    }
+
+    /* now read info on each stream and create ES */
+    for( i = 0 ; i < i_track; i++ )
     {
-        p_buffer_pes = p_info->p_pes_first;
-        p_info->p_pes_first = p_buffer_pes->p_next;
-        if( !p_info->p_pes_first )
+        avi_track_t      *tk = malloc( sizeof( avi_track_t ) );
+        avi_chunk_list_t *p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
+        avi_chunk_strh_t *p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );
+        avi_chunk_strf_auds_t *p_auds;
+        avi_chunk_strf_vids_t *p_vids;
+        es_format_t fmt;
+
+        tk->b_activated = VLC_FALSE;
+        tk->p_index     = 0;
+        tk->i_idxnb     = 0;
+        tk->i_idxmax    = 0;
+        tk->i_idxposc   = 0;
+        tk->i_idxposb   = 0;
+
+        tk->i_blockno   = 0;
+        tk->i_blocksize = 0;
+
+        p_auds = (void*)p_vids = (void*)AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );
+
+        if( p_strl == NULL || p_strh == NULL || p_auds == NULL || p_vids == NULL )
         {
-            p_info->p_pes_last = NULL;
+            msg_Warn( p_input, "stream[%d] incomplete", i );
+            continue;
         }
-        p_pes = p_buffer_pes->p_pes;
 
-        free( p_buffer_pes );
-        p_info->i_pes_count--;
-        p_info->i_pes_totalsize -= p_pes->i_pes_size;
-        return( p_pes );
+        tk->i_rate  = p_strh->i_rate;
+        tk->i_scale = p_strh->i_scale;
+        tk->i_samplesize = p_strh->i_samplesize;
+        msg_Dbg( p_input, "stream[%d] rate:%d scale:%d samplesize:%d",
+                 i, tk->i_rate, tk->i_scale, tk->i_samplesize );
+
+        switch( p_strh->i_type )
+        {
+            case( AVIFOURCC_auds ):
+                tk->i_cat   = AUDIO_ES;
+                tk->i_codec = AVI_FourccGetCodec( AUDIO_ES,
+                                                  p_auds->p_wf->wFormatTag );
+                if( ( tk->i_blocksize = p_auds->p_wf->nBlockAlign ) == 0 )
+                {
+                    if( p_auds->p_wf->wFormatTag == 1 )
+                    {
+                        tk->i_blocksize = p_auds->p_wf->nChannels * (p_auds->p_wf->wBitsPerSample/8);
+                    }
+                    else
+                    {
+                        tk->i_blocksize = 1;
+                    }
+                }
+                es_format_Init( &fmt, AUDIO_ES, tk->i_codec );
+
+                fmt.audio.i_channels        = p_auds->p_wf->nChannels;
+                fmt.audio.i_rate            = p_auds->p_wf->nSamplesPerSec;
+                fmt.i_bitrate               = p_auds->p_wf->nAvgBytesPerSec*8;
+                fmt.audio.i_blockalign      = p_auds->p_wf->nBlockAlign;
+                fmt.audio.i_bitspersample   = p_auds->p_wf->wBitsPerSample;
+                fmt.i_extra = __MIN( p_auds->p_wf->cbSize,
+                    p_auds->i_chunk_size - sizeof(WAVEFORMATEX) );
+                fmt.p_extra = &p_auds->p_wf[1];
+                msg_Dbg( p_input, "stream[%d] audio(0x%x) %d channels %dHz %dbits",
+                         i, p_auds->p_wf->wFormatTag, p_auds->p_wf->nChannels,
+                         p_auds->p_wf->nSamplesPerSec, p_auds->p_wf->wBitsPerSample);
+                break;
+
+            case( AVIFOURCC_vids ):
+                tk->i_cat   = VIDEO_ES;
+                tk->i_codec = AVI_FourccGetCodec( VIDEO_ES,
+                                                  p_vids->p_bih->biCompression );
+                es_format_Init( &fmt, VIDEO_ES, p_vids->p_bih->biCompression );
+                tk->i_samplesize = 0;
+                fmt.video.i_width  = p_vids->p_bih->biWidth;
+                fmt.video.i_height = p_vids->p_bih->biHeight;
+                fmt.i_extra =
+                    __MIN( p_vids->p_bih->biSize - sizeof( BITMAPINFOHEADER ),
+                           p_vids->i_chunk_size - sizeof(BITMAPINFOHEADER) );
+                fmt.p_extra = &p_vids->p_bih[1];
+                msg_Dbg( p_input, "stream[%d] video(%4.4s) %dx%d %dbpp %ffps",
+                        i,
+                         (char*)&p_vids->p_bih->biCompression,
+                         p_vids->p_bih->biWidth,
+                         p_vids->p_bih->biHeight,
+                         p_vids->p_bih->biBitCount,
+                         (float)tk->i_rate/(float)tk->i_scale );
+                break;
+            default:
+                msg_Warn( p_input, "stream[%d] unknown type", i );
+                free( tk );
+                continue;
+        }
+        tk->p_es = es_out_Add( p_input->p_es_out, &fmt );
+        TAB_APPEND( p_sys->i_track, p_sys->track, tk );
     }
-    else
+
+    if( p_sys->i_track <= 0 )
     {
-        return( NULL );
+        msg_Err( p_input, "no valid track" );
+        goto error;
     }
-}
-static int AVI_PESBuffer_Drop( input_buffers_t *p_method_data,
-                                AVIStreamInfo_t *p_info )
-{
-    pes_packet_t *p_pes = AVI_PESBuffer_Get( p_info );
-    if( p_pes )
+
+    if( config_GetInt( p_input, "avi-index" ) )
     {
-        input_DeletePES( p_method_data, p_pes );
-        return( 1 );
+        if( p_sys->b_seekable )
+        {
+            AVI_IndexCreate( p_input );
+        }
+        else
+        {
+            msg_Warn( p_input, "cannot create index (unseekable stream)" );
+            AVI_IndexLoad( p_input );
+        }
     }
     else
     {
-        return( 0 );
+        AVI_IndexLoad( p_input );
     }
-}
-static void AVI_PESBuffer_Flush( input_buffers_t *p_method_data,
-                                 AVIStreamInfo_t *p_info )
-{
-    while( p_info->p_pes_first )
+
+    /* *** movie length in sec *** */
+    p_sys->i_length = AVI_MovieGetLength( p_input );
+    if( p_sys->i_length < (mtime_t)p_avih->i_totalframes *
+                          (mtime_t)p_avih->i_microsecperframe /
+                          (mtime_t)1000000 )
     {
-        AVI_PESBuffer_Drop( p_method_data, p_info );
+        msg_Warn( p_input, "broken or missing index, 'seek' will be axproximative or will have strange behavour" );
     }
-}
+    /* fix some BeOS MediaKit generated file */
+    for( i = 0 ; i < p_sys->i_track; i++ )
+    {
+        avi_track_t         *tk = p_sys->track[i];
+        avi_chunk_list_t    *p_strl;
+        avi_chunk_strh_t    *p_strh;
+        avi_chunk_strf_auds_t    *p_auds;
 
-static void AVI_ParseStreamHeader( u32 i_id, int *i_number, int *i_type )
-{
-    int c1,c2;
+        if( tk->i_cat != AUDIO_ES )
+        {
+            continue;
+        }
+        if( tk->i_idxnb < 1 ||
+            tk->i_scale != 1 ||
+            tk->i_samplesize != 0 )
+        {
+            continue;
+        }
+        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
+        p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );
+        p_auds = AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );
 
-    c1 = ( i_id ) & 0xFF;
-    c2 = ( i_id >>  8 ) & 0xFF;
+        if( p_auds->p_wf->wFormatTag != WAVE_FORMAT_PCM &&
+            (unsigned int)tk->i_rate == p_auds->p_wf->nSamplesPerSec )
+        {
+            int64_t i_track_length =
+                tk->p_index[tk->i_idxnb-1].i_length +
+                tk->p_index[tk->i_idxnb-1].i_lengthtotal;
+            mtime_t i_length = (mtime_t)p_avih->i_totalframes *
+                               (mtime_t)p_avih->i_microsecperframe;
 
-    if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
+            if( i_length == 0 )
+            {
+                msg_Warn( p_input, "track[%d] cannot be fixed (BeOS MediaKit generated)", i );
+                continue;
+            }
+            tk->i_samplesize = 1;
+            tk->i_rate       = i_track_length  * (int64_t)1000000/ i_length;
+            msg_Warn( p_input, "track[%d] fixed with rate=%d scale=%d (BeOS MediaKit generated)", i, tk->i_rate, tk->i_scale );
+        }
+    }
+
+    if( p_sys->i_length )
     {
-        *i_number = 100; /* > max stream number */
-        *i_type = 0;
+        p_input->stream.i_mux_rate =
+            stream_Size( p_input->s ) / 50 / p_sys->i_length;
     }
-    else
+
+    if( p_sys->b_seekable )
     {
-        *i_number = (c1 - '0') * 10 + (c2 - '0' );
-        *i_type = ( i_id >> 16 ) & 0xFFFF;
+        /* we have read all chunk so go back to movi */
+        stream_Seek( p_input->s, p_movi->i_chunk_pos );
     }
-}
+    /* Skip movi header */
+    stream_Read( p_input->s, NULL, 12 );
 
-/* Function to manipulate stream easily */
-static off_t AVI_TellAbsolute( input_thread_t *p_input )
-{
-    off_t i_pos;
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-    i_pos= p_input->stream.p_selected_area->i_tell -
-            ( p_input->p_last_data - p_input->p_current_data  );
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
+    p_sys->i_movi_begin = p_movi->i_chunk_pos;
+    return VLC_SUCCESS;
 
-    return( i_pos );
+error:
+    AVI_ChunkFreeRoot( p_input->s, &p_sys->ck_root );
+    free( p_sys );
+    return VLC_EGENERIC;
 }
-                            
-static int AVI_SeekAbsolute( input_thread_t *p_input,
-                             off_t i_pos)
+
+/*****************************************************************************
+ * Close: frees unused data
+ *****************************************************************************/
+static void Close ( vlc_object_t * p_this )
 {
-    off_t i_filepos;
-    /* FIXME add support for not seekable stream */
+    input_thread_t *    p_input = (input_thread_t *)p_this;
+    unsigned int i;
+    demux_sys_t *p_sys = p_input->p_demux_data  ;
 
-    i_filepos = AVI_TellAbsolute( p_input );
-    if( i_pos != i_filepos )
+    for( i = 0; i < p_sys->i_track; i++ )
     {
-/*        msg_Err( p_input, "Seek --> delta %d", i_pos - i_filepos );*/
-        p_input->pf_seek( p_input, i_pos );
-        input_AccessReinit( p_input );
+        if( p_sys->track[i] )
+        {
+            FREE( p_sys->track[i]->p_index );
+            free( p_sys->track[i] );
+        }
     }
-    return( 1 );
+    FREE( p_sys->track );
+    AVI_ChunkFreeRoot( p_input->s, &p_sys->ck_root );
+
+    free( p_sys );
 }
 
+/*****************************************************************************
+ * Demux_Seekable: reads and demuxes data packets for stream seekable
+ *****************************************************************************
+ * AVIDemux: reads and demuxes data packets
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ *****************************************************************************/
+typedef struct
+{
+    vlc_bool_t b_ok;
+
+    int i_toread;
+
+    off_t i_posf; /* where we will read :
+                   if i_idxposb == 0 : begining of chunk (+8 to acces data)
+                   else : point on data directly */
+} avi_track_toread_t;
 
-static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
-                                 AVIIndexEntry_t *p_index)
+static int Demux_Seekable( input_thread_t *p_input )
 {
-    AVIIndexEntry_t *p_tmp;
-    if( p_info->p_index == NULL )
-    {
-        p_info->i_idxmax = 16384;
-        p_info->i_idxnb = 0;
-        p_info->p_index = calloc( p_info->i_idxmax, 
-                                  sizeof( AVIIndexEntry_t ) );
-        if( p_info->p_index == NULL ) {return;}
-    }
-    if( p_info->i_idxnb >= p_info->i_idxmax )
+    demux_sys_t *p_sys = p_input->p_demux_data;
+
+    unsigned int i_track_count = 0;
+    unsigned int i_track;
+    vlc_bool_t b_stream;
+    /* cannot be more than 100 stream (dcXX or wbXX) */
+    avi_track_toread_t toread[100];
+
+
+    /* detect new selected/unselected streams */
+    for( i_track = 0; i_track < p_sys->i_track; i_track++ )
     {
-        p_info->i_idxmax += 16384;
-        p_tmp = realloc( (void*)p_info->p_index,
-                           p_info->i_idxmax * 
-                           sizeof( AVIIndexEntry_t ) );
-        if( !p_tmp ) 
-        { 
-            p_info->i_idxmax -= 16384;
-            return; 
+        avi_track_t *tk = p_sys->track[i_track];
+        vlc_bool_t  b;
+
+        es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
+        if( b && !tk->b_activated )
+        {
+            if( p_sys->b_seekable)
+            {
+                AVI_TrackSeek( p_input, i_track, p_sys->i_time );
+            }
+            tk->b_activated = VLC_TRUE;
+        }
+        else if( !b && tk->b_activated )
+        {
+            tk->b_activated = VLC_FALSE;
+        }
+        if( b )
+        {
+            i_track_count++;
         }
-        p_info->p_index = p_tmp;
-    }
-    /* calculate cumulate length */
-    if( p_info->i_idxnb > 0 )
-    {
-        p_index->i_lengthtotal = p_info->p_index[p_info->i_idxnb-1].i_length +
-                p_info->p_index[p_info->i_idxnb-1].i_lengthtotal;
     }
-    else
+
+    if( i_track_count <= 0 )
     {
-        p_index->i_lengthtotal = 0;
+        msg_Warn( p_input, "no track selected, exiting..." );
+        return( 0 );
     }
 
-    p_info->p_index[p_info->i_idxnb] = *p_index;
-    p_info->i_idxnb++;
-}
+    /* wait for the good time */
+    p_sys->i_pcr = p_sys->i_time * 9 / 100;
 
-static void __AVI_GetIndex( input_thread_t *p_input )
-{
-    AVIIndexEntry_t index;
-    byte_t          *p_buff;
-    riffchunk_t     *p_idx1;
-    int             i_read;
-    int             i;
-    int             i_number;
-    int             i_type;
-    int             i_totalentry = 0;
-    demux_sys_t *p_avi = p_input->p_demux_data;
-
-    if( RIFF_FindAndGotoDataChunk( p_input,
-                                   p_avi->p_riff, 
-                                   &p_idx1, 
-                                   FOURCC_idx1)!=0 )
-    {
-        msg_Warn( p_input, "cannot find index" );
-        RIFF_GoToChunk( p_input, p_avi->p_hdrl );        
-        return;
-    }
-    p_avi->p_idx1 = p_idx1;
-    msg_Dbg( p_input, "loading index" ); 
-    for(;;)
+    input_ClockManageRef( p_input,
+                          p_input->stream.p_selected_program,
+                          p_sys->i_pcr );
+
+
+    p_sys->i_time += 25*1000;  /* read 25ms */
+
+    /* init toread */
+    for( i_track = 0; i_track < p_sys->i_track; i_track++ )
     {
-        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 ) )
+        avi_track_t *tk = p_sys->track[i_track];
+        mtime_t i_dpts;
+
+        toread[i_track].b_ok = tk->b_activated;
+        if( tk->i_idxposc < tk->i_idxnb )
         {
-            msg_Dbg( p_input, "read %d idx entries", i_totalentry );
-            return;
+            toread[i_track].i_posf = tk->p_index[tk->i_idxposc].i_pos;
+           if( tk->i_idxposb > 0 )
+           {
+                toread[i_track].i_posf += 8 + tk->i_idxposb;
+           }
         }
-        i_read /= 16 ;
-        for( i = 0; i < i_read; i++ )
-        {
-            byte_t  *p_peek = p_buff + i * 16;
-            i_totalentry++;
-            index.i_id      = GetDWLE( p_peek );
-            index.i_flags   = GetDWLE( p_peek+4)&(~AVIIF_FIXKEYFRAME);
-            index.i_pos     = GetDWLE( p_peek+8);
-            index.i_length  = GetDWLE(p_peek+12);
-            AVI_ParseStreamHeader( index.i_id, &i_number, &i_type );
-            
-            if( ( i_number <  p_avi->i_streams )
-               &&(p_avi->pp_info[i_number]->i_cat == 
-                     AVI_GetESTypeFromTwoCC( i_type ))) 
-            {
-                __AVI_AddEntryIndex( p_avi->pp_info[i_number],
-                                     &index );
-            }
+        else
+        {
+            toread[i_track].i_posf = -1;
         }
-        __RIFF_SkipBytes( p_input, 16 * i_read );
-    }
 
-}
+        i_dpts = p_sys->i_time - AVI_GetPTS( tk  );
 
-/* XXX call after get p_movi */
-static void __AVI_UpdateIndexOffset( input_thread_t *p_input )
-{
-    int i_stream;
-    int b_start = 1;/* if index pos is based on start of file or not (p_movi) */
-    demux_sys_t *p_avi = p_input->p_demux_data;
+        if( tk->i_samplesize )
+        {
+            toread[i_track].i_toread = AVI_PTSToByte( tk, __ABS( i_dpts ) );
+        }
+        else
+        {
+            toread[i_track].i_toread = AVI_PTSToChunk( tk, __ABS( i_dpts ) );
+        }
 
-/* FIXME some work to do :
-        * test in the file if it's true, if not do a RIFF_Find...
-*/
-#define p_info p_avi->pp_info[i_stream]
-    for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
-    {
-        if( ( p_info->p_index )
-           && ( p_info->p_index[0].i_pos < p_avi->p_movi->i_pos + 8 ))
+        if( i_dpts < 0 )
         {
-            b_start = 0;
-            break;
+            toread[i_track].i_toread *= -1;
         }
     }
-    if( !b_start )
+
+    b_stream = VLC_FALSE;
+
+    for( ;; )
     {
-        for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
+        avi_track_t     *tk;
+        vlc_bool_t       b_done;
+        block_t         *p_frame;
+        off_t i_pos;
+        unsigned int i;
+        size_t i_size;
+
+        /* search for first chunk to be read */
+        for( i = 0, b_done = VLC_TRUE, i_pos = -1; i < p_sys->i_track; i++ )
         {
-            int i;
-            if( p_info->p_index )
+            if( !toread[i].b_ok ||
+                AVI_GetDPTS( p_sys->track[i],
+                             toread[i].i_toread ) <= -25 * 1000 )
+            {
+                continue;
+            }
+
+            if( toread[i].i_toread > 0 )
+            {
+                b_done = VLC_FALSE; /* not yet finished */
+            }
+            if( toread[i].i_posf > 0 )
             {
-                for( i = 0; i < p_info->i_idxnb; i++ )
+                if( i_pos == -1 || i_pos > toread[i_track].i_posf )
                 {
-                    p_info->p_index[i].i_pos += p_avi->p_movi->i_pos + 8;
+                    i_track = i;
+                    i_pos = toread[i].i_posf;
                 }
             }
         }
-    }
-#undef p_info
-}
 
-/*****************************************************************************
- * AVIEnd: frees unused data
- *****************************************************************************/
-static void __AVIEnd ( vlc_object_t * p_this )
-{   
-    input_thread_t *    p_input = (input_thread_t *)p_this;
-    int i;
-    demux_sys_t *p_avi = p_input->p_demux_data  ; 
-    
-    if( p_avi->p_riff ) 
-            RIFF_DeleteChunk( p_input, p_avi->p_riff );
-    if( p_avi->p_hdrl ) 
-            RIFF_DeleteChunk( p_input, p_avi->p_hdrl );
-    if( p_avi->p_movi ) 
-            RIFF_DeleteChunk( p_input, p_avi->p_movi );
-    if( p_avi->p_idx1 ) 
-            RIFF_DeleteChunk( p_input, p_avi->p_idx1 );
-    if( p_avi->pp_info )
-    {
-        for( i = 0; i < p_avi->i_streams; i++ )
-        {
-            if( p_avi->pp_info[i] ) 
+        if( b_done )
+        {
+            return( 1 );
+        }
+
+        if( i_pos == -1 )
+        {
+            /* no valid index, we will parse directly the stream
+             * in case we fail we will disable all finished stream */
+            if( p_sys->i_movi_lastchunk_pos >= p_sys->i_movi_begin + 12 )
             {
-                if( p_avi->pp_info[i]->p_index )
+                stream_Seek( p_input->s, p_sys->i_movi_lastchunk_pos );
+                if( AVI_PacketNext( p_input ) )
                 {
-                      free( p_avi->pp_info[i]->p_index );
-                      AVI_PESBuffer_Flush( p_input->p_method_data, 
-                                           p_avi->pp_info[i] );
+                    return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );
                 }
-                free( p_avi->pp_info[i] ); 
             }
-        }
-         free( p_avi->pp_info );
-    }
-}
-
-/*****************************************************************************
- * AVIInit: check file and initializes AVI structures
- *****************************************************************************/
-static int AVIInit( vlc_object_t * p_this )
-{   
-    input_thread_t *    p_input = (input_thread_t *)p_this;
-    riffchunk_t *p_riff,*p_hdrl,*p_movi;
-    riffchunk_t *p_avih;
-    riffchunk_t *p_strl,*p_strh,*p_strf;
-    demux_sys_t *p_avi;
-    es_descriptor_t *p_es = NULL; /* for not warning */
-    int i;
+            else
+            {
+                stream_Seek( p_input->s, p_sys->i_movi_begin + 12 );
+            }
 
-    p_input->pf_demux = AVIDemux;
+            for( ;; )
+            {
+                avi_packet_t avi_pk;
 
-    if( !( p_input->p_demux_data = 
-                    p_avi = malloc( sizeof(demux_sys_t) ) ) )
-    {
-        msg_Err( p_input, "out of memory" );
-        return( -1 );
-    }
-    memset( p_avi, 0, sizeof( demux_sys_t ) );
-    p_avi->i_rate = DEFAULT_RATE;
-    p_avi->b_seekable = ( ( p_input->stream.b_seekable )
-                        &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
+                if( AVI_PacketGetHeader( p_input, &avi_pk ) )
+                {
+                    msg_Warn( p_input,
+                             "cannot get packet header, track disabled" );
+                    return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );
+                }
+                if( avi_pk.i_stream >= p_sys->i_track ||
+                    ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
+                {
+                    if( AVI_PacketNext( p_input ) )
+                    {
+                        msg_Warn( p_input,
+                                  "cannot skip packet, track disabled" );
+                        return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );
+                    }
+                    continue;
+                }
+                else
+                {
+                    /* add this chunk to the index */
+                    AVIIndexEntry_t index;
+
+                    index.i_id = avi_pk.i_fourcc;
+                    index.i_flags =
+                       AVI_GetKeyFlag(p_sys->track[avi_pk.i_stream]->i_codec,
+                                      avi_pk.i_peek);
+                    index.i_pos = avi_pk.i_pos;
+                    index.i_length = avi_pk.i_size;
+                    AVI_IndexAddEntry( p_sys, avi_pk.i_stream, &index );
+
+                    i_track = avi_pk.i_stream;
+                    tk = p_sys->track[i_track];
+                    /* do we will read this data ? */
+                    if( AVI_GetDPTS( tk, toread[i_track].i_toread ) > -25*1000 )
+                    {
+                        break;
+                    }
+                    else
+                    {
+                        if( AVI_PacketNext( p_input ) )
+                        {
+                            msg_Warn( p_input,
+                                      "cannot skip packet, track disabled" );
+                            return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );
+                        }
+                    }
+                }
+            }
 
-    /* Initialize access plug-in structures. */
-    if( p_input->i_mtu == 0 )
-    {
-        /* Improve speed. */
-        p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
-    }
+        }
+        else
+        {
+            stream_Seek( p_input->s, i_pos );
+        }
 
-    if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 )    
-    {
-        AVIEnd( p_input );
-        msg_Warn( p_input, "RIFF-AVI module discarded" );
-        return( -1 );
-    }
-    p_avi->p_riff = p_riff;
+        /* Set the track to use */
+        tk = p_sys->track[i_track];
 
-    if ( RIFF_DescendChunk(p_input) != 0 )
-    {
-        AVIEnd( p_input );
-        msg_Err( p_input, "cannot look for subchunk" );
-        return ( -1 );
-    }
+        /* read thoses data */
+        if( tk->i_samplesize )
+        {
+            unsigned int i_toread;
 
-    /* it's a riff-avi file, so search for LIST-hdrl */
-    if( RIFF_FindListChunk(p_input ,&p_hdrl,p_riff, FOURCC_hdrl) != 0 )
-    {
-        AVIEnd( p_input );
-        msg_Err( p_input, "cannot find \"LIST-hdrl\"" );
-        return( -1 );
-    }
-    p_avi->p_hdrl = p_hdrl;
+            if( ( i_toread = toread[i_track].i_toread ) <= 0 )
+            {
+                if( tk->i_samplesize > 1 )
+                {
+                    i_toread = tk->i_samplesize;
+                }
+                else
+                {
+                    i_toread = __MAX( AVI_PTSToByte( tk, 20 * 1000 ), 100 );
+                }
+            }
+            i_size = __MIN( tk->p_index[tk->i_idxposc].i_length -
+                                tk->i_idxposb,
+                            i_toread );
+        }
+        else
+        {
+            i_size = tk->p_index[tk->i_idxposc].i_length;
+        }
 
-    if( RIFF_DescendChunk(p_input) != 0 )
-    {
-        AVIEnd( p_input );
-        msg_Err( p_input, "cannot look for subchunk" );
-        return ( -1 );
-    }
-    /* in  LIST-hdrl search avih */
-    if( RIFF_FindAndLoadChunk( p_input, p_hdrl, 
-                                    &p_avih, FOURCC_avih ) != 0 )
-    {
-        AVIEnd( p_input );
-        msg_Err( p_input, "cannot find \"avih\" chunk" );
-        return( -1 );
-    }
-    AVI_Parse_avih( &p_avi->avih, p_avih->p_data->p_payload_start );
-    RIFF_DeleteChunk( p_input, p_avih );
-    
-    if( p_avi->avih.i_streams == 0 )  
-    /* no stream found, perhaps it would be cool to find it */
-    {
-        AVIEnd( p_input );
-        msg_Err( p_input, "no stream defined!" );
-        return( -1 );
-    }
+        if( tk->i_idxposb == 0 )
+        {
+            i_size += 8; /* need to read and skip header */
+        }
 
-    /*  create one program */
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-    if( input_InitStream( p_input, 0 ) == -1)
-    {
-        vlc_mutex_unlock( &p_input->stream.stream_lock );
-        AVIEnd( p_input );
-        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 );
-        AVIEnd( p_input );
-        msg_Err( p_input, "cannot add program" );
-        return( -1 );
-    }
-    p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
-    p_input->stream.i_mux_rate = p_avi->avih.i_maxbytespersec / 50;
-    vlc_mutex_unlock( &p_input->stream.stream_lock ); 
+        if( ( p_frame = stream_Block( p_input->s, __EVEN( i_size ) ) )==NULL )
+        {
+            msg_Warn( p_input, "failled reading data" );
+            tk->b_activated = VLC_FALSE;
+            toread[i_track].b_ok = VLC_FALSE;
+            continue;
+        }
+        if( i_size % 2 )    /* read was padded on word boundary */
+        {
+            p_frame->i_buffer--;
+        }
+        /* skip header */
+        if( tk->i_idxposb == 0 )
+        {
+            p_frame->p_buffer += 8;
+            p_frame->i_buffer -= 8;
+        }
+        p_frame->i_pts = AVI_GetPTS( tk );
 
-    /* now read info on each stream and create ES */
-    p_avi->i_streams = p_avi->avih.i_streams;
-    
-    p_avi->pp_info = calloc( p_avi->i_streams, 
-                                    sizeof( AVIStreamInfo_t* ) );
-    memset( p_avi->pp_info, 
-            0, 
-            sizeof( AVIStreamInfo_t* ) * p_avi->i_streams );
-
-    for( i = 0 ; i < p_avi->i_streams; i++ )
-    {
-#define p_info  p_avi->pp_info[i]
-        p_info = malloc( sizeof(AVIStreamInfo_t ) );
-        memset( p_info, 0, sizeof( AVIStreamInfo_t ) );        
-
-        if( ( RIFF_FindListChunk(p_input,
-                                &p_strl,p_hdrl, FOURCC_strl) != 0 )
-                ||( RIFF_DescendChunk(p_input) != 0 ))
-        {
-            AVIEnd( p_input );
-            msg_Err( p_input, "cannot find \"LIST-strl\"" );
-            return( -1 );
-        }
-        
-        /* in  LIST-strl search strh */
-        if( RIFF_FindAndLoadChunk( p_input, p_hdrl, 
-                                &p_strh, FOURCC_strh ) != 0 )
-        {
-            RIFF_DeleteChunk( p_input, p_strl );
-            AVIEnd( p_input );
-            msg_Err( p_input, "cannot find \"strh\"" );
-            return( -1 );
-        }
-        AVI_Parse_Header( &p_info->header,
-                            p_strh->p_data->p_payload_start);
-        RIFF_DeleteChunk( p_input, p_strh );      
-
-        /* in  LIST-strl search strf */
-        if( RIFF_FindAndLoadChunk( p_input, p_hdrl, 
-                                &p_strf, FOURCC_strf ) != 0 )
-        {
-            RIFF_DeleteChunk( p_input, p_strl );
-            AVIEnd( p_input );
-            msg_Err( p_input, "cannot find \"strf\"" );
-            return( -1 );
-        }
-        /* we don't get strd, it's useless for divx,opendivx,mepgaudio */ 
-        if( RIFF_AscendChunk(p_input, p_strl) != 0 )
-        {
-            RIFF_DeleteChunk( p_input, p_strf );
-            RIFF_DeleteChunk( p_input, p_strl );
-            AVIEnd( p_input );
-            msg_Err( p_input, "cannot go out (\"strl\")" );
-            return( -1 );
-        }
-
-        /* add one ES */
-        vlc_mutex_lock( &p_input->stream.stream_lock );
-        p_es = input_AddES( p_input,
-                            p_input->stream.p_selected_program, 1+i,
-                            p_strf->i_size );
-        vlc_mutex_unlock( &p_input->stream.stream_lock );
-        p_es->i_stream_id =i; /* XXX: i don't use it */ 
-       
-        switch( p_info->header.i_type )
-        {
-            case( FOURCC_auds ):
-                p_es->i_cat = AUDIO_ES;
-                AVI_Parse_WaveFormatEx( &p_info->audio_format,
-                                   p_strf->p_data->p_payload_start ); 
-                p_es->i_fourcc = AVI_AudioGetType(
-                                     p_info->audio_format.i_formattag );
-                break;
-                
-            case( FOURCC_vids ):
-                p_es->i_cat = VIDEO_ES;
-                AVI_Parse_BitMapInfoHeader( &p_info->video_format,
-                                   p_strf->p_data->p_payload_start ); 
-
-                /* XXX quick hack for playing ffmpeg video, I don't know 
-                    who is doing something wrong */
-                p_info->header.i_samplesize = 0;
-                p_es->i_fourcc = p_info->video_format.i_compression;
-                break;
-            default:
-                msg_Err( p_input, "unknown stream(%d) type", i );
-                p_es->i_cat = UNKNOWN_ES;
-                break;
+        /* read data */
+        if( tk->i_samplesize )
+        {
+            if( tk->i_idxposb == 0 )
+            {
+                i_size -= 8;
+            }
+            toread[i_track].i_toread -= i_size;
+            tk->i_idxposb += i_size;
+            if( tk->i_idxposb >=
+                    tk->p_index[tk->i_idxposc].i_length )
+            {
+                tk->i_idxposb = 0;
+                tk->i_idxposc++;
+            }
         }
-        p_info->p_es = p_es;
-        p_info->i_cat = p_es->i_cat;
-        /* We copy strf for decoder in p_es->p_demux_data */
-        memcpy( p_es->p_demux_data, 
-                p_strf->p_data->p_payload_start,
-                p_strf->i_size );
-        RIFF_DeleteChunk( p_input, p_strf );
-        RIFF_DeleteChunk( p_input, p_strl );
-#undef p_info           
-    }
+        else
+        {
+            int i_length = tk->p_index[tk->i_idxposc].i_length;
+
+            tk->i_idxposc++;
+            if( tk->i_cat == AUDIO_ES )
+            {
+                tk->i_blockno += tk->i_blocksize > 0 ? ( i_length + tk->i_blocksize - 1 ) / tk->i_blocksize : 1;
+            }
+            toread[i_track].i_toread--;
+        }
+
+        if( tk->i_idxposc < tk->i_idxnb)
+        {
+            toread[i_track].i_posf =
+                tk->p_index[tk->i_idxposc].i_pos;
+            if( tk->i_idxposb > 0 )
+            {
+                toread[i_track].i_posf += 8 + tk->i_idxposb;
+            }
 
+        }
+        else
+        {
+            toread[i_track].i_posf = -1;
+        }
 
+        b_stream = VLC_TRUE; /* at least one read succeed */
 
-    /* go out of p_hdrl */
-    if( RIFF_AscendChunk(p_input, p_hdrl) != 0)
-    {
-        AVIEnd( p_input );
-        msg_Err( p_input, "cannot go out (\"hdrl\")" );
-        return( -1 );
-    }
+        p_frame->i_pts =
+            input_ClockGetTS( p_input,
+                              p_input->stream.p_selected_program,
+                              p_frame->i_pts * 9/100);
 
-    /* go to movi chunk to get it*/
-    if( RIFF_FindListChunk(p_input ,&p_movi,p_riff, FOURCC_movi) != 0 )
-    {
-        msg_Err( p_input, "cannot find \"LIST-movi\"" );
-        AVIEnd( p_input );
-        return( -1 );
+        if( tk->i_cat != VIDEO_ES )
+            p_frame->i_dts = p_frame->i_pts;
+        else
+        {
+            p_frame->i_dts = p_frame->i_pts;
+            p_frame->i_pts = 0;
+        }
+
+        //p_pes->i_rate = p_input->stream.control.i_rate;
+        es_out_Send( p_input->p_es_out, tk->p_es, p_frame );
     }
-    p_avi->p_movi = p_movi;
-    
-    /* get index  XXX need to have p_movi */
-    if( p_avi->b_seekable )
+}
+
+
+/*****************************************************************************
+ * Demux_UnSeekable: reads and demuxes data packets for unseekable file
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ *****************************************************************************/
+static int Demux_UnSeekable( input_thread_t *p_input )
+{
+    demux_sys_t     *p_sys = p_input->p_demux_data;
+    avi_track_t *p_stream_master = NULL;
+    vlc_bool_t b_audio;
+    unsigned int i_stream;
+    unsigned int i_packet;
+
+    /* Check if we need to send the audio data to decoder */
+    b_audio = !p_input->stream.control.b_mute;
+
+    input_ClockManageRef( p_input,
+                          p_input->stream.p_selected_program,
+                          p_sys->i_pcr );
+
+    /* *** find master stream for data packet skipping algo *** */
+    /* *** -> first video, if any, or first audio ES *** */
+    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
     {
-        /* get index */
-        __AVI_GetIndex( p_input ); 
-        /* try to get i_idxoffset for each stream  */
-        __AVI_UpdateIndexOffset( p_input );
-        /* to make sure to go the begining unless demux will see a seek */
-        RIFF_GoToChunk( p_input, p_avi->p_movi );
+        avi_track_t *tk = p_sys->track[i_stream];
+        vlc_bool_t  b;
+
+        es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
 
+        if( b && tk->i_cat == VIDEO_ES )
+        {
+            p_stream_master = tk;
+        }
+        else if( b )
+        {
+            p_stream_master = tk;
+        }
     }
-    else
+
+    if( !p_stream_master )
     {
-        msg_Warn( p_input, "no index!" );
+        msg_Warn( p_input, "no more stream selected" );
+        return( 0 );
     }
 
-    if( RIFF_DescendChunk( p_input ) != 0 )
+    p_sys->i_pcr = AVI_GetPTS( p_stream_master ) * 9 / 100;
+
+    for( i_packet = 0; i_packet < 10; i_packet++)
     {
-        AVIEnd( p_input );
-        msg_Err( p_input, "cannot go in (\"movi\")" );
-        return( -1 );
-    }
+#define p_stream    p_sys->track[avi_pk.i_stream]
 
-    /* print informations on streams */
-    msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ", 
-             p_avi->i_streams,
-             p_avi->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
-             p_avi->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
-             p_avi->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
-             p_avi->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
-
-    for( i = 0; i < p_avi->i_streams; i++ )
-    {
-#define p_info  p_avi->pp_info[i]
-        switch( p_info->p_es->i_cat )
-        {
-            case( VIDEO_ES ):
-
-                msg_Dbg( p_input, "video(%4.4s) %dx%d %dbpp %ffps",
-                         (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 );
-                if( (p_avi->p_info_video == NULL) ) 
+        avi_packet_t    avi_pk;
+
+        if( AVI_PacketGetHeader( p_input, &avi_pk ) )
+        {
+            return( 0 );
+        }
+
+        if( avi_pk.i_stream >= p_sys->i_track ||
+            ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
+        {
+            /* we haven't found an audio or video packet:
+             *  - we have seek, found first next packet
+             *  - others packets could be found, skip them
+             */
+            switch( avi_pk.i_fourcc )
+            {
+                case AVIFOURCC_JUNK:
+                case AVIFOURCC_LIST:
+                case AVIFOURCC_RIFF:
+                    return( !AVI_PacketNext( p_input ) ? 1 : 0 );
+                case AVIFOURCC_idx1:
+                    if( p_sys->b_odml )
+                    {
+                        return( !AVI_PacketNext( p_input ) ? 1 : 0 );
+                    }
+                    return( 0 );    /* eof */
+                default:
+                    msg_Warn( p_input,
+                              "seems to have lost position, resync" );
+                    if( AVI_PacketSearch( p_input ) )
+                    {
+                        msg_Err( p_input, "resync failed" );
+                        return( -1 );
+                    }
+            }
+        }
+        else
+        {
+            /* do will send this packet to decoder ? */
+            if( !b_audio && avi_pk.i_cat == AUDIO_ES )
+            {
+                if( AVI_PacketNext( p_input ) )
                 {
-                    p_avi->p_info_video = p_info;
-                    /* TODO add test to see if a decoder has been found */
-                    vlc_mutex_lock( &p_input->stream.stream_lock );
-                    input_SelectES( p_input, p_info->p_es );
-                    vlc_mutex_unlock( &p_input->stream.stream_lock );
+                    return( 0 );
                 }
-                break;
+            }
+            else
+            {
+                /* it's a selected stream, check for time */
+                if( __ABS( AVI_GetPTS( p_stream ) -
+                            AVI_GetPTS( p_stream_master ) )< 600*1000 )
+                {
+                    /* load it and send to decoder */
+                    block_t *p_frame;
+                    if( AVI_PacketRead( p_input, &avi_pk, &p_frame ) || p_frame == NULL )
+                    {
+                        return( -1 );
+                    }
+                    p_frame->i_pts =
+                        input_ClockGetTS( p_input,
+                                          p_input->stream.p_selected_program,
+                                          AVI_GetPTS( p_stream ) * 9/100);
 
-            case( AUDIO_ES ):
-                msg_Dbg( p_input, "audio(0x%x) %d channels %dHz %dbits",
-                         p_info->audio_format.i_formattag,
-                         p_info->audio_format.i_channels,
-                         p_info->audio_format.i_samplespersec,
-                         p_info->audio_format.i_bitspersample );
-                if( (p_avi->p_info_audio == NULL) ) 
+                    if( avi_pk.i_cat != VIDEO_ES )
+                        p_frame->i_dts = p_frame->i_pts;
+                    else
+                    {
+                        p_frame->i_dts = p_frame->i_pts;
+                        p_frame->i_pts = 0;
+                    }
+
+                    //p_pes->i_rate = p_input->stream.control.i_rate;
+                    es_out_Send( p_input->p_es_out, p_stream->p_es, p_frame );
+                }
+                else
                 {
-                    p_avi->p_info_audio = p_info;
-                    vlc_mutex_lock( &p_input->stream.stream_lock );
-                    input_SelectES( p_input, p_info->p_es );
-                    vlc_mutex_unlock( &p_input->stream.stream_lock );
+                    if( AVI_PacketNext( p_input ) )
+                    {
+                        return( 0 );
+                    }
                 }
-                break;
-            default:
-                break;
-        }
-#undef p_info    
-    }
+            }
 
+            /* *** update stream time position *** */
+            if( p_stream->i_samplesize )
+            {
+                p_stream->i_idxposb += avi_pk.i_size;
+            }
+            else
+            {
+                if( p_stream->i_cat == AUDIO_ES )
+                {
+                    p_stream->i_blockno += p_stream->i_blocksize > 0 ? ( avi_pk.i_size + p_stream->i_blocksize - 1 ) / p_stream->i_blocksize : 1;
+                }
+                p_stream->i_idxposc++;
+            }
 
-    /* we select the first audio and video ES */
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-    if( !p_avi->p_info_video ) 
-    {
-        msg_Warn( p_input, "no video stream found" );
-    }
-    if( !p_avi->p_info_audio )
-    {
-        msg_Warn( p_input, "no audio stream found!" );
+        }
+#undef p_stream
     }
-    p_input->stream.p_selected_program->b_is_ok = 1;
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
 
-    return( 0 );
+    return( 1 );
 }
 
-
-
-
-
-
 /*****************************************************************************
- * Function to convert pts to chunk or byte
+ * Seek: goto to i_date or i_percent
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
  *****************************************************************************/
-
-static inline mtime_t AVI_PTSToChunk( AVIStreamInfo_t *p_info, 
-                                        mtime_t i_pts )
+static int Seek( input_thread_t *p_input, mtime_t i_date, int i_percent )
 {
-    return( (mtime_t)((s64)i_pts *
-                      (s64)p_info->header.i_rate /
-                      (s64)p_info->header.i_scale /
-                      (s64)1000000 ) );
-}
-static inline mtime_t AVI_PTSToByte( AVIStreamInfo_t *p_info,
-                                       mtime_t i_pts )
-{
-    return( (mtime_t)((s64)i_pts * 
-                      (s64)p_info->header.i_samplesize *
-                      (s64)p_info->header.i_rate /
-                      (s64)p_info->header.i_scale /
-                      (s64)1000000 ) );
 
-}
-static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
-{
-    
-    if( p_info->header.i_samplesize )
+    demux_sys_t *p_sys = p_input->p_demux_data;
+    unsigned int i_stream;
+    msg_Dbg( p_input,
+             "seek requested: "I64Fd" secondes %d%%",
+             i_date / 1000000,
+             i_percent );
+
+    if( p_sys->b_seekable )
     {
-        /* we need a valid entry we will emulate one */
-        int i_len;
-        if( p_info->i_idxposc == p_info->i_idxnb )
+        if( !p_sys->i_length )
         {
-            if( p_info->i_idxposc )
+            avi_track_t *p_stream;
+            int64_t i_pos;
+
+            /* use i_percent to create a true i_date */
+            msg_Warn( p_input,
+                      "mmh, seeking without index at %d%%"
+                      " work only for interleaved file", i_percent );
+            if( i_percent >= 100 )
             {
-                /* use the last entry */
-                i_len = p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal
-                            + p_info->p_index[p_info->i_idxnb - 1].i_length
-                            + p_info->i_idxposb; /* should be 0 */
+                msg_Warn( p_input, "cannot seek so far !" );
+                return( -1 );
             }
-            else
+            i_percent = __MAX( i_percent, 0 );
+
+            /* try to find chunk that is at i_percent or the file */
+            i_pos = __MAX( i_percent *
+                           stream_Size( p_input->s ) / 100,
+                           p_sys->i_movi_begin );
+            /* search first selected stream */
+            for( i_stream = 0, p_stream = NULL;
+                        i_stream < p_sys->i_track; i_stream++ )
+            {
+                p_stream = p_sys->track[i_stream];
+                if( p_stream->b_activated )
+                {
+                    break;
+                }
+            }
+            if( !p_stream || !p_stream->b_activated )
+            {
+                msg_Warn( p_input, "cannot find any selected stream" );
+                return( -1 );
+            }
+
+            /* be sure that the index exist */
+            if( AVI_StreamChunkSet( p_input,
+                                    i_stream,
+                                    0 ) )
+            {
+                msg_Warn( p_input, "cannot seek" );
+                return( -1 );
+            }
+
+            while( i_pos >= p_stream->p_index[p_stream->i_idxposc].i_pos +
+               p_stream->p_index[p_stream->i_idxposc].i_length + 8 )
             {
-                i_len = p_info->i_idxposb; 
-                /* no valid entry use only offset*/
+                /* search after i_idxposc */
+                if( AVI_StreamChunkSet( p_input,
+                                        i_stream, p_stream->i_idxposc + 1 ) )
+                {
+                    msg_Warn( p_input, "cannot seek" );
+                    return( -1 );
+                }
             }
+            i_date = AVI_GetPTS( p_stream );
+            /* TODO better support for i_samplesize != 0 */
+            msg_Dbg( p_input, "estimate date "I64Fd, i_date );
         }
-        else
+
+#define p_stream    p_sys->track[i_stream]
+        p_sys->i_time = 0;
+        /* seek for chunk based streams */
+        for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
         {
-            i_len = p_info->p_index[p_info->i_idxposc].i_lengthtotal
-                                + p_info->i_idxposb;
+            if( p_stream->b_activated && !p_stream->i_samplesize )
+/*            if( p_stream->b_activated ) */
+            {
+                AVI_TrackSeek( p_input, i_stream, i_date );
+                p_sys->i_time = __MAX( AVI_GetPTS( p_stream ),
+                                        p_sys->i_time );
+            }
+        }
+#if 1
+        if( p_sys->i_time )
+        {
+            i_date = p_sys->i_time;
+        }
+        /* seek for bytes based streams */
+        for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
+        {
+            if( p_stream->b_activated && p_stream->i_samplesize )
+            {
+                AVI_TrackSeek( p_input, i_stream, i_date );
+/*                p_sys->i_time = __MAX( AVI_GetPTS( p_stream ), p_sys->i_time );*/
+            }
         }
-        return( (mtime_t)( (s64)1000000 *
-                   (s64)i_len *
-                    (s64)p_info->header.i_scale /
-                    (s64)p_info->header.i_rate /
-                    (s64)p_info->header.i_samplesize ) );
+        msg_Dbg( p_input, "seek: "I64Fd" seconds", p_sys->i_time /1000000 );
+        /* set true movie time */
+#endif
+        if( !p_sys->i_time )
+        {
+            p_sys->i_time = i_date;
+        }
+#undef p_stream
+        return( 1 );
     }
     else
     {
-        /* even if p_info->i_idxposc isn't valid, there isn't any probllem */
-        return( (mtime_t)( (s64)1000000 *
-                    (s64)(p_info->i_idxposc ) *
-                    (s64)p_info->header.i_scale /
-                    (s64)p_info->header.i_rate) );
+        msg_Err( p_input, "shouldn't yet be executed" );
+        return( -1 );
     }
 }
 
-
 /*****************************************************************************
- * Functions to acces streams data 
- * Uses it, because i plane to read unseekable stream
- * Don't work for the moment for unseekable stream 
- * XXX NEVER set directly i_idxposc and i_idxposb unless you know what you do 
+ * Control:
+ *****************************************************************************
+ *
  *****************************************************************************/
-
-/* FIXME FIXME change b_pad to number of bytes to skipp after reading */
-static int __AVI_GetDataInPES( input_thread_t *p_input,
-                               pes_packet_t   **pp_pes,
-                               int i_size,
-                               int b_pad )
+static double ControlGetPosition( input_thread_t *p_input )
 {
+    demux_sys_t *p_sys = p_input->p_demux_data;
 
-    int i_read;
-    data_packet_t *p_data;
-
-    
-    if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
-    {
-        return( 0 );
-    }
-
-    
-    if( !i_size )
+    if( p_sys->i_length > 0 )
     {
-        p_data = input_NewPacket( p_input->p_method_data, 0 );
-        (*pp_pes)->p_first = (*pp_pes)->p_last  = p_data;
-        (*pp_pes)->i_nb_data = 1;
-        (*pp_pes)->i_pes_size = 0;
-        return( 0 );
-    }
-    
-    if( ( i_size&1 )&&( b_pad ) )
-    {
-        b_pad = 1;
-        i_size++;
+        return (double)p_sys->i_time / (double)( p_sys->i_length * (mtime_t)1000000 );
     }
-    else
+    else if( stream_Size( p_input->s ) > 0 )
     {
-        b_pad = 0;
-    }
+        unsigned int i;
+        int64_t i_tmp;
+        int64_t i64 = 0;
 
-    do
-    {
-        i_read = input_SplitBuffer(p_input, &p_data, __MIN( i_size - 
-                                                              (*pp_pes)->i_pes_size, 1024 ) );
-        if( i_read < 0 )
-        {
-            return( (*pp_pes)->i_pes_size );
-        }
-        if( !(*pp_pes)->p_first )
-        {
-            (*pp_pes)->p_first = 
-                    (*pp_pes)->p_last  = p_data;
-            (*pp_pes)->i_nb_data = 1;
-            (*pp_pes)->i_pes_size = i_read;
-        }
-        else
+        /* search the more advanced selected es */
+        for( i = 0; i < p_sys->i_track; i++ )
         {
-            (*pp_pes)->p_last->p_next = 
-                    (*pp_pes)->p_last = p_data;
-            (*pp_pes)->i_nb_data++;
-            (*pp_pes)->i_pes_size += i_read;
+            avi_track_t *tk = p_sys->track[i];
+            if( tk->b_activated && tk->i_idxposc < tk->i_idxnb )
+            {
+                i_tmp = tk->p_index[tk->i_idxposc].i_pos +
+                        tk->p_index[tk->i_idxposc].i_length + 8;
+                if( i_tmp > i64 )
+                {
+                    i64 = i_tmp;
+                }
+            }
         }
-    } while( ((*pp_pes)->i_pes_size < i_size)&&( i_read ) );
-
-    if( b_pad )
-    {
-        (*pp_pes)->i_pes_size--;
-        (*pp_pes)->p_last->p_payload_end--;
-        i_size--;
+        return (double)i64 / (double)stream_Size( p_input->s );
     }
-
-       return( i_size );
+    return 0.0;
 }
 
-static int __AVI_SeekAndGetChunk( input_thread_t  *p_input,
-                                  AVIStreamInfo_t *p_info )
+static int    Control( input_thread_t *p_input, int i_query, va_list args )
 {
-    pes_packet_t *p_pes;
-    int i_length, i_ret;
-    
-    i_length = __MIN( p_info->p_index[p_info->i_idxposc].i_length 
-                        - p_info->i_idxposb,
-                            BUFFER_MAXSPESSIZE );
-
-    AVI_SeekAbsolute( p_input, 
-                      (off_t)p_info->p_index[p_info->i_idxposc].i_pos + 
-                            p_info->i_idxposb + 8);
-
-    i_ret = __AVI_GetDataInPES( p_input, &p_pes, i_length , 0);
+    demux_sys_t *p_sys = p_input->p_demux_data;
+    int i;
+    double   f, *pf;
+    int64_t i64, *pi64;
 
-    if( i_ret != i_length )
+    switch( i_query )
     {
-        return( 0 );
-    }
-    /*  TODO test key frame if i_idxposb == 0*/
-    AVI_PESBuffer_Add( p_input->p_method_data,
-                       p_info,
-                       p_pes,
-                       p_info->i_idxposc,
-                       p_info->i_idxposb );
-    return( 1 );
-}
-/* TODO check if it's correct (humm...) and optimisation ... */
-/* return 0 if we choose to get only the ck we want 
- *        1 if index is invalid
- *        2 if there is a ck_other before ck_info and the last proced ck_info*/
-/* XXX XXX XXX avi file is some BIG shit, and sometime index give 
- * a refenrence to the same chunk BUT with a different size ( usually 0 )
- */
+        case DEMUX_GET_POSITION:
+            pf = (double*)va_arg( args, double * );
+            *pf = ControlGetPosition( p_input );
+            return VLC_SUCCESS;
+        case DEMUX_SET_POSITION:
+            if( p_sys->b_seekable )
+            {
+                f = (double)va_arg( args, double );
+                i64 = (mtime_t)(1000000.0 * p_sys->i_length * f );
+                return Seek( p_input, i64, (int)(f * 100) ) < 0 ? VLC_EGENERIC : VLC_SUCCESS;
+            }
+            return demux_vaControlDefault( p_input, i_query, args );
 
-static inline int __AVI_GetChunkMethod( input_thread_t  *p_input,
-                                 AVIStreamInfo_t *p_info,
-                                 AVIStreamInfo_t *p_other )
-{
-    int i_info_pos;
-    int i_other_pos;
-    
-    int i_info_pos_last;
-    int i_other_pos_last;
+        case DEMUX_GET_TIME:
+            pi64 = (int64_t*)va_arg( args, int64_t * );
+            *pi64 = p_sys->i_time;
+            return VLC_SUCCESS;
 
-    /*If we don't have a valid entry we need to parse from last 
-        defined chunk and it's the only way that we return 1*/
-    if( p_info->i_idxposc >= p_info->i_idxnb )
-    {
-        return( 1 );
-    }
+        case DEMUX_SET_TIME:
+        {
+            int i_percent = 0;
 
-    /* KNOW we have a valid entry for p_info */
-    /* we return 0 if we haven't an valid entry for p_other */ 
-    if( ( !p_other )||( p_other->i_idxposc >= p_other->i_idxnb ) )
-    {
-        return( 0 );
-    }
+            i64 = (int64_t)va_arg( args, int64_t );
+            if( p_sys->i_length > 0 )
+            {
+                i_percent = 100 * i64 / (p_sys->i_length*1000000);
+            }
+            else if( p_sys->i_time > 0 )
+            {
+                i_percent = (int)( 100.0 * ControlGetPosition( p_input ) *
+                                   (double)i64 / (double)p_sys->i_time );
+            }
+            return Seek( p_input, i64, i_percent );
+        }
+        case DEMUX_GET_LENGTH:
+            pi64 = (int64_t*)va_arg( args, int64_t * );
+            *pi64 = p_sys->i_length * (mtime_t)1000000;
+            return VLC_SUCCESS;
+
+        case DEMUX_GET_FPS:
+            pf = (double*)va_arg( args, double * );
+            *pf = 0.0;
+            for( i = 0; i < (int)p_sys->i_track; i++ )
+            {
+                avi_track_t *tk = p_sys->track[i];
+                if( tk->i_cat == VIDEO_ES && tk->i_scale > 0)
+                {
+                    *pf = (float)tk->i_rate / (float)tk->i_scale;
+                    break;
+                }
+            }
+            return VLC_SUCCESS;
 
-    /* KNOW there are 2 streams with valid entry */
-   
-    /* we return 0 if for one of the two streams we will not read 
-       chunk-aligned */
-    if( ( p_info->i_idxposb )||( p_other->i_idxposb ) )
-    { 
-        return( 0 );
-    }
-    
-    /* KNOW we have a valid entry for the 2 streams
-         and for the 2 we want an aligned chunk (given by i_idxposc )*/
-        /* if in stream, the next chunk is back than the one we 
-           have just read, it's useless to parse */
-    i_info_pos  = p_info->p_index[p_info->i_idxposc].i_pos;
-    i_other_pos = p_other->p_index[p_other->i_idxposc].i_pos ;
-
-    i_info_pos_last  = p_info->i_idxposc ? 
-                            p_info->p_index[p_info->i_idxposc - 1].i_pos : 0;
-    i_other_pos_last = p_other->i_idxposc ?
-                            p_other->p_index[p_other->i_idxposc - 1].i_pos : 0 ;
-   
-    
-    if( ( ( p_info->i_idxposc )&&( i_info_pos <= i_info_pos_last ) ) ||
-        ( ( p_other->i_idxposc )&&( i_other_pos <= i_other_pos_last ) ) )
-    {
-        return( 0 );
+        default:
+            return demux_vaControlDefault( p_input, i_query, args );
     }
+    return VLC_EGENERIC;
+}
 
-    /* KNOW for the 2 streams, the ck we want are after the last read 
-           or it's the first */
+/*****************************************************************************
+ * Function to convert pts to chunk or byte
+ *****************************************************************************/
 
-    /* if the first ck_other we want isn't between ck_info_last 
-       and ck_info, don't parse */
-    /* TODO fix this, use also number in buffered PES */
-    if( ( i_other_pos > i_info_pos) /* ck_other too far */
-        ||( i_other_pos < i_info_pos_last ) ) /* it's too late for ck_other */
-    {
-        return( 0 );
-    } 
-   
-    /* we Know we will find ck_other, and before ck_info 
-        "if ck_info is too far" will be handle after */
-    return( 2 );
+static mtime_t AVI_PTSToChunk( avi_track_t *tk, mtime_t i_pts )
+{
+    return (mtime_t)((int64_t)i_pts *
+                     (int64_t)tk->i_rate /
+                     (int64_t)tk->i_scale /
+                     (int64_t)1000000 );
 }
-
-                         
-static inline int __AVI_ChooseSize( int l1, int l2 )
+static mtime_t AVI_PTSToByte( avi_track_t *tk, mtime_t i_pts )
 {
-    /* XXX l2 is prefered if 0 otherwise min not equal to 0 */
-    if( !l2 )
-    { 
-        return( 0 );
-    }
-    return( !l1 ? l2 : __MIN( l1,l2 ) );
+    return (mtime_t)((int64_t)i_pts *
+                     (int64_t)tk->i_rate /
+                     (int64_t)tk->i_scale /
+                     (int64_t)1000000 *
+                     (int64_t)tk->i_samplesize );
 }
 
-/* We know we will read chunk align */
-static int __AVI_GetAndPutChunkInBuffer( input_thread_t  *p_input,
-                                  AVIStreamInfo_t *p_info,
-                                  int i_size,
-                                  int i_ck )
+static mtime_t AVI_GetDPTS( avi_track_t *tk, int64_t i_count )
 {
+    mtime_t i_dpts;
 
-    pes_packet_t    *p_pes;
-    int i_length; 
-
-    i_length = __MIN( i_size, BUFFER_MAXSPESSIZE );
-
-    /* Skip chunk header */
-
-    if( __AVI_GetDataInPES( p_input, &p_pes, i_length + 8,1 ) != i_length +8 )
-    {
-        return( 0 );
-    }
-    p_pes->p_first->p_payload_start += 8;
-    p_pes->i_pes_size -= 8;
-
-    i_size = GetDWLE( p_pes->p_first->p_demux_start + 4);
+    i_dpts = (mtime_t)( (int64_t)1000000 *
+                        (int64_t)i_count *
+                        (int64_t)tk->i_scale /
+                        (int64_t)tk->i_rate );
 
-    AVI_PESBuffer_Add( p_input->p_method_data,
-                       p_info,
-                       p_pes,
-                       i_ck,
-                       0 );
-    /* skip unwanted bytes */
-    if( i_length != i_size)
+    if( tk->i_samplesize )
     {
-        msg_Err( p_input, "Chunk Size mismatch" );
-        AVI_SeekAbsolute( p_input,
-                          __EVEN( AVI_TellAbsolute( p_input ) + 
-                                  i_size - i_length ) );
+        return i_dpts / tk->i_samplesize;
     }
-    return( 1 );
+    return i_dpts;
 }
 
-/* XXX Don't use this function directly ! XXX */
-static int __AVI_GetChunk( input_thread_t  *p_input,
-                           AVIStreamInfo_t *p_info,
-                           int b_load )
+static mtime_t AVI_GetPTS( avi_track_t *tk )
 {
-    demux_sys_t *p_avi = p_input->p_demux_data;
-    AVIStreamInfo_t *p_other;
-    int i_method;
-    off_t i_posmax;
-    int i;
-   
-#define p_info_i p_avi->pp_info[i]
-    while( p_info->p_pes_first )
+    if( tk->i_samplesize )
     {
-        if( ( p_info->p_pes_first->i_posc == p_info->i_idxposc ) 
-             &&( p_info->i_idxposb >= p_info->p_pes_first->i_posb )
-             &&( p_info->i_idxposb < p_info->p_pes_first->i_posb + 
-                     p_info->p_pes_first->p_pes->i_pes_size ) )
-  
+        int64_t i_count = 0;
+
+        /* we need a valid entry we will emulate one */
+        if( tk->i_idxposc == tk->i_idxnb )
         {
-            return( 1 ); /* we have it in buffer */
+            if( tk->i_idxposc )
+            {
+                /* use the last entry */
+                i_count = tk->p_index[tk->i_idxnb - 1].i_lengthtotal
+                            + tk->p_index[tk->i_idxnb - 1].i_length;
+            }
         }
         else
         {
-            AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
+            i_count = tk->p_index[tk->i_idxposc].i_lengthtotal;
         }
+        return AVI_GetDPTS( tk, i_count + tk->i_idxposb );
     }
-    /* up to now we handle only one audio and video streams at the same time */
-    p_other = (p_info == p_avi->p_info_video ) ?
-                     p_avi->p_info_audio : p_avi->p_info_video ;
-
-    i_method = __AVI_GetChunkMethod( p_input, p_info, p_other );
-
-    if( !i_method )
-    {
-        /* get directly the good chunk */
-        return( b_load ? __AVI_SeekAndGetChunk( p_input, p_info ) : 1 );
-    }
-    /* We will parse
-        * because invalid index
-        * or will find ck_other before ck_info 
-    */
-/*    msg_Warn( p_input, "method %d", i_method ); */
-    /* we will calculate the better position we have to reach */
-    if( i_method == 1 )
+    else
     {
-        /* invalid index */
-    /*  the position max we have already reached */
-        /* FIXME this isn't the better because sometime will fail to
-            put in buffer p_other since it could be too far */
-        AVIStreamInfo_t *p_info_max = p_info;
-        
-        for( i = 0; i < p_avi->i_streams; i++ )
-        {
-            if( p_info_i->i_idxnb )
-            {
-                if( p_info_max->i_idxnb )
-                {
-                    if( p_info_i->p_index[p_info_i->i_idxnb -1 ].i_pos >
-                            p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos )
-                    {
-                        p_info_max = p_info_i;
-                    }
-                }
-                else
-                {
-                    p_info_max = p_info_i;
-                }
-            }
-        }
-        if( p_info_max->i_idxnb )
+        if( tk->i_cat == AUDIO_ES )
         {
-            /* be carefull that size between index and ck can sometime be 
-              different without any error (and other time it's an error) */
-           i_posmax = p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos; 
-           /* so choose this, and I know that we have already reach it */
+            return AVI_GetDPTS( tk, tk->i_blockno );
         }
         else
         {
-            i_posmax = p_avi->p_movi->i_pos + 12;
+            return AVI_GetDPTS( tk, tk->i_idxposc );
         }
     }
-    else
+}
+
+static int AVI_StreamChunkFind( input_thread_t *p_input,
+                                unsigned int i_stream )
+{
+    demux_sys_t *p_sys = p_input->p_demux_data;
+    avi_packet_t avi_pk;
+
+    /* find first chunk of i_stream that isn't in index */
+
+    if( p_sys->i_movi_lastchunk_pos >= p_sys->i_movi_begin + 12 )
     {
-        if( !b_load )
+        stream_Seek( p_input->s, p_sys->i_movi_lastchunk_pos );
+        if( AVI_PacketNext( p_input ) )
         {
-            return( 1 ); /* all is ok */
+            return VLC_EGENERIC;
         }
-        /* valid index */
-        /* we know that the entry and the last one are valid for the 2 stream */
-        /* and ck_other will come *before* index so go directly to it*/
-        i_posmax = p_other->p_index[p_other->i_idxposc].i_pos;
+    }
+    else
+    {
+        stream_Seek( p_input->s, p_sys->i_movi_begin + 12 );
     }
 
-    AVI_SeekAbsolute( p_input, i_posmax );
-    /* the first chunk we will see is :
-            * the last chunk that we have already seen for broken index 
-            * the first ck for other with good index */ 
-    for( ; ; ) /* infinite parsing until the ck we want */
+    for( ;; )
     {
-        riffchunk_t  *p_ck;
-        int i_type;
-        
-        /* Get the actual chunk in the stream */
-        if( !(p_ck = RIFF_ReadChunk( p_input )) )
+        if( p_input->b_die )
         {
-            return( 0 );
+            return VLC_EGENERIC;
         }
-/*        msg_Dbg( p_input, "ck: %4.4s len %d", &p_ck->i_id, p_ck->i_size ); */
-        /* special case for LIST-rec chunk */
-        if( ( p_ck->i_id == FOURCC_LIST )&&( p_ck->i_type == FOURCC_rec ) )
+
+        if( AVI_PacketGetHeader( p_input, &avi_pk ) )
         {
-            RIFF_DescendChunk( p_input );
-            RIFF_DeleteChunk( p_input, p_ck );
-            continue;
+            msg_Warn( p_input, "cannot get packet header" );
+            return VLC_EGENERIC;
         }
-        AVI_ParseStreamHeader( p_ck->i_id, &i, &i_type );
-        /* littles checks but not too much if you want to read all file */ 
-        if( i >= p_avi->i_streams )
-        /* (AVI_GetESTypeFromTwoCC(i_type) != p_info_i->i_cat) perhaps add it*/
-            
+        if( avi_pk.i_stream >= p_sys->i_track ||
+            ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
         {
-            RIFF_DeleteChunk( p_input, p_ck );
-            if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
+            if( AVI_PacketNext( p_input ) )
             {
-                return( 0 );
+                return VLC_EGENERIC;
             }
         }
         else
         {
-            int i_size;
-
-            /* have we found a new entry (not present in index)? */
-            if( ( !p_info_i->i_idxnb )
-                ||(p_info_i->p_index[p_info_i->i_idxnb-1].i_pos < p_ck->i_pos))
+            /* add this chunk to the index */
+            AVIIndexEntry_t index;
+
+            index.i_id = avi_pk.i_fourcc;
+            index.i_flags =
+               AVI_GetKeyFlag(p_sys->track[avi_pk.i_stream]->i_codec,
+                              avi_pk.i_peek);
+            index.i_pos = avi_pk.i_pos;
+            index.i_length = avi_pk.i_size;
+            AVI_IndexAddEntry( p_sys, avi_pk.i_stream, &index );
+
+            if( avi_pk.i_stream == i_stream  )
             {
-                AVIIndexEntry_t index;
-
-                index.i_id = p_ck->i_id;
-                index.i_flags = AVI_GetKeyFlag( p_info_i->p_es->i_fourcc,
-                                                (u8*)&p_ck->i_8bytes);
-                index.i_pos = p_ck->i_pos;
-                index.i_length = p_ck->i_size;
-                __AVI_AddEntryIndex( p_info_i, &index );   
+                return VLC_SUCCESS;
             }
 
-
-            /* TODO check if p_other is full and then if is possible 
-                go directly to the good chunk */
-            if( ( p_info_i == p_other )
-                &&( !AVI_PESBuffer_IsFull( p_other ) )
-                &&( ( !p_other->p_pes_last )||
-                    ( p_other->p_pes_last->p_pes->i_pes_size != 
-                                                    BUFFER_MAXSPESSIZE ) ) )
-            {
-                int i_ck = p_other->p_pes_last ? 
-                        p_other->p_pes_last->i_posc + 1 : p_other->i_idxposc;
-                i_size = __AVI_ChooseSize( p_ck->i_size,
-                                           p_other->p_index[i_ck].i_length);
-               
-                if( p_other->p_index[i_ck].i_pos == p_ck->i_pos )
-                {
-                    if( !__AVI_GetAndPutChunkInBuffer( p_input, p_other, 
-                                                       i_size, i_ck ) )
-                    {
-                        RIFF_DeleteChunk( p_input, p_ck );
-                        return( 0 );
-                    }
-                }
-                else
-                {
-                    if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
-                    {
-                        RIFF_DeleteChunk( p_input, p_ck );
-
-                        return( 0 );
-                    }
-
-                }
-                        
-                RIFF_DeleteChunk( p_input, p_ck );
-            }
-            else
-            if( ( p_info_i == p_info)
-                &&( p_info->i_idxposc < p_info->i_idxnb ) )
-            {
-                /* the first ck_info is ok otherwise it should be 
-                        loaded without parsing */
-                i_size = __AVI_ChooseSize( p_ck->i_size,
-                                 p_info->p_index[p_info->i_idxposc].i_length);
-
-
-                RIFF_DeleteChunk( p_input, p_ck );
-                
-                return( b_load ? __AVI_GetAndPutChunkInBuffer( p_input,
-                                                               p_info,
-                                                               i_size,
-                                                     p_info->i_idxposc ) : 1 );
-            }
-            else
+            if( AVI_PacketNext( p_input ) )
             {
-                /* skip it */
-                RIFF_DeleteChunk( p_input, p_ck );
-                if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
-                {
-                    return( 0 );
-                }
+                return VLC_EGENERIC;
             }
         }
-
-    
     }
-    
-#undef p_info_i
 }
 
+
 /* be sure that i_ck will be a valid index entry */
-static int AVI_SetStreamChunk( input_thread_t    *p_input,
-                               AVIStreamInfo_t   *p_info,
-                               int   i_ck )
+static int AVI_StreamChunkSet( input_thread_t    *p_input,
+                               unsigned int i_stream,
+                               unsigned int i_ck )
 {
+    demux_sys_t *p_sys = p_input->p_demux_data;
+    avi_track_t *p_stream = p_sys->track[i_stream];
 
-    p_info->i_idxposc = i_ck;
-    p_info->i_idxposb = 0;
+    p_stream->i_idxposc = i_ck;
+    p_stream->i_idxposb = 0;
 
-    if(  i_ck < p_info->i_idxnb )
-    {
-        return( 1 );
-    }
-    else
+    if(  i_ck >= p_stream->i_idxnb )
     {
-        p_info->i_idxposc = p_info->i_idxnb - 1;
+        p_stream->i_idxposc = p_stream->i_idxnb - 1;
         do
         {
-            p_info->i_idxposc++;
-            if( !__AVI_GetChunk( p_input, p_info, 0 ) )
+            p_stream->i_idxposc++;
+            if( AVI_StreamChunkFind( p_input, i_stream ) )
             {
-                return( 0 );
+                return VLC_EGENERIC;
             }
-        } while( p_info->i_idxposc < i_ck );
 
-        return( 1 );
+        } while( p_stream->i_idxposc < i_ck );
     }
+
+    return VLC_SUCCESS;
 }
 
 
 /* XXX FIXME up to now, we assume that all chunk are one after one */
-static int AVI_SetStreamBytes( input_thread_t    *p_input, 
-                               AVIStreamInfo_t   *p_info,
+static int AVI_StreamBytesSet( input_thread_t    *p_input,
+                               unsigned int i_stream,
                                off_t   i_byte )
 {
-    if( ( p_info->i_idxnb > 0 )
-        &&( i_byte < p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal + 
-                p_info->p_index[p_info->i_idxnb - 1].i_length ) )
+    demux_sys_t *p_sys = p_input->p_demux_data;
+    avi_track_t *p_stream = p_sys->track[i_stream];
+
+    if( ( p_stream->i_idxnb > 0 )
+        &&( i_byte < p_stream->p_index[p_stream->i_idxnb - 1].i_lengthtotal +
+                p_stream->p_index[p_stream->i_idxnb - 1].i_length ) )
     {
         /* index is valid to find the ck */
         /* uses dichototmie to be fast enougth */
-        int i_idxposc = __MIN( p_info->i_idxposc, p_info->i_idxnb - 1 );
-        int i_idxmax  = p_info->i_idxnb;
+        int i_idxposc = __MIN( p_stream->i_idxposc, p_stream->i_idxnb - 1 );
+        int i_idxmax  = p_stream->i_idxnb;
         int i_idxmin  = 0;
         for( ;; )
         {
-            if( p_info->p_index[i_idxposc].i_lengthtotal > i_byte )
+            if( p_stream->p_index[i_idxposc].i_lengthtotal > i_byte )
             {
                 i_idxmax  = i_idxposc ;
                 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
             }
             else
             {
-                if( p_info->p_index[i_idxposc].i_lengthtotal + 
-                        p_info->p_index[i_idxposc].i_length <= i_byte)
+                if( p_stream->p_index[i_idxposc].i_lengthtotal +
+                        p_stream->p_index[i_idxposc].i_length <= i_byte)
                 {
                     i_idxmin  = i_idxposc ;
                     i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
                 }
                 else
                 {
-                    p_info->i_idxposc = i_idxposc;
-                    p_info->i_idxposb = i_byte - 
-                            p_info->p_index[i_idxposc].i_lengthtotal;
-                    return( 1 );
+                    p_stream->i_idxposc = i_idxposc;
+                    p_stream->i_idxposb = i_byte -
+                            p_stream->p_index[i_idxposc].i_lengthtotal;
+                    return VLC_SUCCESS;
                 }
             }
         }
-        
+
     }
     else
     {
-        p_info->i_idxposc = p_info->i_idxnb - 1;
-        p_info->i_idxposb = 0;
+        p_stream->i_idxposc = p_stream->i_idxnb - 1;
+        p_stream->i_idxposb = 0;
         do
         {
-            p_info->i_idxposc++;
-            if( !__AVI_GetChunk( p_input, p_info, 0 ) )
+            p_stream->i_idxposc++;
+            if( AVI_StreamChunkFind( p_input, i_stream ) )
             {
-                return( 0 );
+                return VLC_EGENERIC;
             }
-        } while( p_info->p_index[p_info->i_idxposc].i_lengthtotal +
-                    p_info->p_index[p_info->i_idxposc].i_length <= i_byte );
 
-        p_info->i_idxposb = i_byte -
-                       p_info->p_index[p_info->i_idxposc].i_lengthtotal;
-        return( 1 );
+        } while( p_stream->p_index[p_stream->i_idxposc].i_lengthtotal +
+                    p_stream->p_index[p_stream->i_idxposc].i_length <= i_byte );
+
+        p_stream->i_idxposb = i_byte -
+                       p_stream->p_index[p_stream->i_idxposc].i_lengthtotal;
+        return VLC_SUCCESS;
     }
 }
 
-static pes_packet_t *AVI_ReadStreamChunkInPES(  input_thread_t  *p_input,
-                                                AVIStreamInfo_t *p_info )
+static int AVI_TrackSeek( input_thread_t *p_input,
+                           int i_stream,
+                           mtime_t i_date )
+{
+    demux_sys_t  *p_sys = p_input->p_demux_data;
+    avi_track_t  *tk = p_sys->track[i_stream];
+
+#define p_stream    p_sys->track[i_stream]
+    mtime_t i_oldpts;
+
+    i_oldpts = AVI_GetPTS( p_stream );
+
+    if( !p_stream->i_samplesize )
+    {
+        if( AVI_StreamChunkSet( p_input,
+                                i_stream,
+                                AVI_PTSToChunk( p_stream, i_date ) ) )
+        {
+            return VLC_EGENERIC;
+        }
+
+        if( p_stream->i_cat == AUDIO_ES )
+        {
+            unsigned int i;
+            tk->i_blockno = 0;
+            for( i = 0; i < tk->i_idxposc; i++ )
+            {
+                if( tk->i_blocksize > 0 )
+                {
+                    tk->i_blockno += ( tk->p_index[i].i_length + tk->i_blocksize - 1 ) / tk->i_blocksize;
+                }
+                else
+                {
+                    tk->i_blockno++;
+                }
+            }
+        }
+
+        msg_Dbg( p_input,
+                 "old:"I64Fd" %s new "I64Fd,
+                 i_oldpts,
+                 i_oldpts > i_date ? ">" : "<",
+                 i_date );
+
+        if( p_stream->i_cat == VIDEO_ES )
+        {
+            /* search key frame */
+            if( i_date < i_oldpts )
+            {
+                while( p_stream->i_idxposc > 0 &&
+                   !( p_stream->p_index[p_stream->i_idxposc].i_flags &
+                                                                AVIIF_KEYFRAME ) )
+                {
+                    if( AVI_StreamChunkSet( p_input,
+                                            i_stream,
+                                            p_stream->i_idxposc - 1 ) )
+                    {
+                        return VLC_EGENERIC;
+                    }
+                }
+            }
+            else
+            {
+                while( p_stream->i_idxposc < p_stream->i_idxnb &&
+                        !( p_stream->p_index[p_stream->i_idxposc].i_flags &
+                                                                AVIIF_KEYFRAME ) )
+                {
+                    if( AVI_StreamChunkSet( p_input,
+                                            i_stream,
+                                            p_stream->i_idxposc + 1 ) )
+                    {
+                        return VLC_EGENERIC;
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        if( AVI_StreamBytesSet( p_input,
+                                i_stream,
+                                AVI_PTSToByte( p_stream, i_date ) ) )
+        {
+            return VLC_EGENERIC;
+        }
+    }
+    return VLC_SUCCESS;
+#undef p_stream
+}
 
+/****************************************************************************
+ * Return VLC_TRUE if it's a key frame
+ ****************************************************************************/
+static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, uint8_t *p_byte )
 {
-    if( p_info->i_idxposc > p_info->i_idxnb )
+    switch( i_fourcc )
     {
-        return( NULL );
+        case FOURCC_DIV1:
+            /* we have:
+             *  startcode:      0x00000100   32bits
+             *  framenumber     ?             5bits
+             *  piture type     0(I),1(P)     2bits
+             */
+            if( GetDWBE( p_byte ) != 0x00000100 )
+            {
+                /* it's not an msmpegv1 stream, strange...*/
+                return AVIIF_KEYFRAME;
+            }
+            else
+            {
+                return p_byte[4] & 0x06 ? 0 : AVIIF_KEYFRAME;
+            }
+        case FOURCC_DIV2:
+        case FOURCC_DIV3:   /* wmv1 also */
+            /* we have
+             *  picture type    0(I),1(P)     2bits
+             */
+            return p_byte[0] & 0xC0 ? 0 : AVIIF_KEYFRAME;
+        case FOURCC_mp4v:
+            /* we should find first occurence of 0x000001b6 (32bits)
+             *  startcode:      0x000001b6   32bits
+             *  piture type     0(I),1(P)     2bits
+             */
+            if( GetDWBE( p_byte ) != 0x000001b6 )
+            {
+                /* not true , need to find the first VOP header */
+                return AVIIF_KEYFRAME;
+            }
+            else
+            {
+                return p_byte[4] & 0xC0 ? 0 : AVIIF_KEYFRAME;
+            }
+        default:
+            /* I can't do it, so say yes */
+            return AVIIF_KEYFRAME;
     }
+}
 
-    /* we want chunk (p_info->i_idxposc,0) */
-    p_info->i_idxposb = 0;
-    if( !__AVI_GetChunk( p_input, p_info, 1) )
+vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t i_codec )
+{
+    switch( i_cat )
     {
-        msg_Err( p_input, "Got one chunk : failed" );
-        return( NULL );
+        case AUDIO_ES:
+            wf_tag_to_fourcc( i_codec, &i_codec, NULL );
+            return i_codec;
+
+        case VIDEO_ES:
+            /* XXX DIV1 <- msmpeg4v1, DIV2 <- msmpeg4v2, DIV3 <- msmpeg4v3, mp4v for mpeg4 */
+            switch( i_codec )
+            {
+                case FOURCC_DIV1:
+                case FOURCC_div1:
+                case FOURCC_MPG4:
+                case FOURCC_mpg4:
+                    return FOURCC_DIV1;
+                case FOURCC_DIV2:
+                case FOURCC_div2:
+                case FOURCC_MP42:
+                case FOURCC_mp42:
+                case FOURCC_MPG3:
+                case FOURCC_mpg3:
+                    return FOURCC_DIV2;
+                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:
+                case FOURCC_3iv1:
+                case FOURCC_3IVD:
+                case FOURCC_3ivd:
+                case FOURCC_3VID:
+                case FOURCC_3vid:
+                    return FOURCC_DIV3;
+                case FOURCC_DIVX:
+                case FOURCC_divx:
+                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_dx50:
+                case FOURCC_mp4v:
+                case FOURCC_4:
+                case FOURCC_3IV2:
+                case FOURCC_3iv2:
+                    return FOURCC_mp4v;
+            }
+        default:
+            return VLC_FOURCC( 'u', 'n', 'd', 'f' );
     }
-    p_info->i_idxposc++;
-    return( AVI_PESBuffer_Get( p_info ) );
 }
 
-static pes_packet_t *AVI_ReadStreamBytesInPES(  input_thread_t  *p_input,
-                                                AVIStreamInfo_t *p_info,
-                                                int i_byte )
+/****************************************************************************
+ *
+ ****************************************************************************/
+static void AVI_ParseStreamHeader( vlc_fourcc_t i_id,
+                                   int *pi_number, int *pi_type )
 {
-    pes_packet_t    *p_pes;
-    data_packet_t   *p_data;
-    int             i_count = 0;
-    int             i_read;
+#define SET_PTR( p, v ) if( p ) *(p) = (v);
+    int c1, c2;
+
+    c1 = ((uint8_t *)&i_id)[0];
+    c2 = ((uint8_t *)&i_id)[1];
 
-        
-    if( !( p_pes = input_NewPES( p_input->p_method_data ) ) )
+    if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
     {
-        return( NULL );
+        SET_PTR( pi_number, 100 ); /* > max stream number */
+        SET_PTR( pi_type, UNKNOWN_ES );
     }
-    if( !( p_data = input_NewPacket( p_input->p_method_data, i_byte ) ) )
+    else
     {
-        input_DeletePES( p_input->p_method_data, p_pes );
-        return( NULL );
+        SET_PTR( pi_number, (c1 - '0') * 10 + (c2 - '0' ) );
+        switch( VLC_TWOCC( ((uint8_t *)&i_id)[2], ((uint8_t *)&i_id)[3] ) )
+        {
+            case AVITWOCC_wb:
+                SET_PTR( pi_type, AUDIO_ES );
+                break;
+            case AVITWOCC_dc:
+            case AVITWOCC_db:
+                SET_PTR( pi_type, VIDEO_ES );
+                break;
+            default:
+                SET_PTR( pi_type, UNKNOWN_ES );
+                break;
+        }
     }
+#undef SET_PTR
+}
 
-    p_pes->p_first =
-            p_pes->p_last = p_data;
-    p_pes->i_nb_data = 1;
-    p_pes->i_pes_size = i_byte;
+/****************************************************************************
+ *
+ ****************************************************************************/
+static int AVI_PacketGetHeader( input_thread_t *p_input, avi_packet_t *p_pk )
+{
+    uint8_t  *p_peek;
 
-    while( i_byte > 0 )
+    if( stream_Peek( p_input->s, &p_peek, 16 ) < 16 )
     {
-        if( !__AVI_GetChunk( p_input, p_info, 1) )
-        {
-         msg_Err( p_input, "Got one chunk : failed" );
-           
-            input_DeletePES( p_input->p_method_data, p_pes );
-            return( NULL );
-        }
+        return VLC_EGENERIC;
+    }
+    p_pk->i_fourcc  = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] );
+    p_pk->i_size    = GetDWLE( p_peek + 4 );
+    p_pk->i_pos     = stream_Tell( p_input->s );
+    if( p_pk->i_fourcc == AVIFOURCC_LIST || p_pk->i_fourcc == AVIFOURCC_RIFF )
+    {
+        p_pk->i_type = VLC_FOURCC( p_peek[8],  p_peek[9],
+                                   p_peek[10], p_peek[11] );
+    }
+    else
+    {
+        p_pk->i_type = 0;
+    }
 
-        i_read = __MIN( p_info->p_pes_first->p_pes->i_pes_size - 
-                            ( p_info->i_idxposb - p_info->p_pes_first->i_posb ),
-                        i_byte);
-        /* FIXME FIXME FIXME follow all data packet */
-        memcpy( p_data->p_payload_start + i_count, 
-                p_info->p_pes_first->p_pes->p_first->p_payload_start + 
-                    p_info->i_idxposb - p_info->p_pes_first->i_posb,
-                i_read );
+    memcpy( p_pk->i_peek, p_peek + 8, 8 );
 
-        AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
-        i_byte  -= i_read;
-        i_count += i_read;
+    AVI_ParseStreamHeader( p_pk->i_fourcc, &p_pk->i_stream, &p_pk->i_cat );
+    return VLC_SUCCESS;
+}
 
-        p_info->i_idxposb += i_read;
-        if( p_info->p_index[p_info->i_idxposc].i_length <= p_info->i_idxposb )
-        {
-            p_info->i_idxposb -= p_info->p_index[p_info->i_idxposc].i_length;
-            p_info->i_idxposc++;
-        }
+static int AVI_PacketNext( input_thread_t *p_input )
+{
+    avi_packet_t    avi_ck;
+    int             i_skip = 0;
+
+    if( AVI_PacketGetHeader( p_input, &avi_ck ) )
+    {
+        return VLC_EGENERIC;
     }
-   return( p_pes );
-}
-        
 
+    if( avi_ck.i_fourcc == AVIFOURCC_LIST &&
+        ( avi_ck.i_type == AVIFOURCC_rec || avi_ck.i_type == AVIFOURCC_movi ) )
+    {
+        i_skip = 12;
+    }
+    else if( avi_ck.i_fourcc == AVIFOURCC_RIFF &&
+             avi_ck.i_type == AVIFOURCC_AVIX )
+    {
+        i_skip = 24;
+    }
+    else
+    {
+        i_skip = __EVEN( avi_ck.i_size ) + 8;
+    }
 
-/* try to realign after a seek */
-static int AVI_ReAlign( input_thread_t *p_input,
-                        AVIStreamInfo_t *p_info )
+    if( stream_Read( p_input->s, NULL, i_skip ) != i_skip )
+    {
+        return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
+}
+static int AVI_PacketRead( input_thread_t   *p_input,
+                           avi_packet_t     *p_pk,
+                           block_t          **pp_frame )
 {
-    int i;
-    off_t   i_pos;
-    int     b_after = 0;
-    demux_sys_t *p_avi = p_input->p_demux_data;
+    size_t i_size;
 
+    i_size = __EVEN( p_pk->i_size + 8 );
 
-    for( i = 0; i < p_avi->i_streams; i++ )
+    if( ( *pp_frame = stream_Block( p_input->s, i_size ) ) == NULL )
     {
-        AVI_PESBuffer_Flush( p_input->p_method_data, p_avi->pp_info[i] );
+        return VLC_EGENERIC;
     }
-    /* Reinit clock
-       TODO use input_ClockInit instead but need to be exported 
-    p_input->stream.p_selected_program->last_cr = 0;
-    p_input->stream.p_selected_program->last_syscr = 0;
-    p_input->stream.p_selected_program->cr_ref = 0;
-    p_input->stream.p_selected_program->sysdate_ref = 0;
-    p_input->stream.p_selected_program->delta_cr = 0;
-    p_input->stream.p_selected_program->c_average_count = 0; */
-       
-    i_pos = AVI_TellAbsolute( p_input );
-
-    p_info->i_idxposc--; /* in fact  p_info->i_idxposc is for ck to be read */
-    
+    (*pp_frame)->p_buffer += 8;
+    (*pp_frame)->i_buffer -= 8;
 
-    if( ( p_info->i_idxposc <= 0)
-        ||( i_pos <= p_info->p_index[0].i_pos ) )
+    if( i_size != p_pk->i_size + 8 )
     {
-        /*  before beginning of stream  */
-        return( p_info->header.i_samplesize ?
-                    AVI_SetStreamBytes( p_input, p_info, 0 ) :
-                        AVI_SetStreamChunk( p_input, p_info, 0 ) );
+        (*pp_frame)->i_buffer--;
     }
-    
-    b_after = ( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos );
-    /* now find in what chunk we are */
-    while( ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
-           &&( p_info->i_idxposc > 0 ) )
-    {
-        /* search before i_idxposc */
 
-        if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc - 1 ) )
+    return VLC_SUCCESS;
+}
+
+static int AVI_PacketSearch( input_thread_t *p_input )
+{
+    demux_sys_t     *p_sys = p_input->p_demux_data;
+    avi_packet_t    avi_pk;
+    int             i_count = 0;
+
+    for( ;; )
+    {
+        if( stream_Read( p_input->s, NULL, 1 ) != 1 )
         {
-            return( 0 );   
+            return VLC_EGENERIC;
         }
-    }
-    
-    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_SetStreamChunk( p_input, p_info, p_info->i_idxposc + 1 ) )
+        AVI_PacketGetHeader( p_input, &avi_pk );
+        if( avi_pk.i_stream < p_sys->i_track &&
+            ( avi_pk.i_cat == AUDIO_ES || avi_pk.i_cat == VIDEO_ES ) )
         {
-            return( 0 );
+            return VLC_SUCCESS;
         }
-    }
-
-    /* search nearest key frame, only for video */
-    if( p_info->i_cat == VIDEO_ES )
-    {
-        if( b_after )
+        switch( avi_pk.i_fourcc )
         {
-            while(!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME) )
-            {
-                if( !AVI_SetStreamChunk( p_input, p_info, 
-                                         p_info->i_idxposc + 1 ) )
-                {
-                    return( 0 );
-                }
-            }
+            case AVIFOURCC_JUNK:
+            case AVIFOURCC_LIST:
+            case AVIFOURCC_RIFF:
+            case AVIFOURCC_idx1:
+                return VLC_SUCCESS;
         }
-        else
-        { 
-            while( ( p_info->i_idxposc > 0 ) &&
-              (!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME)) )
-            {
 
-                if( !AVI_SetStreamChunk( p_input, p_info, 
-                                        p_info->i_idxposc - 1 ) )
-                {
+        /* Prevents from eating all the CPU with broken files.
+         * This value should be low enough so that it doesn't affect the
+         * reading speed too much (not that we care much anyway because
+         * this code is called only on broken files). */
+        if( !(++i_count % 1024) )
+        {
+            if( p_input->b_die ) return VLC_EGENERIC;
 
-                    return( 0 );
-                }
-            }
+            msleep( 10000 );
+            if( !(i_count % (1024 * 10)) )
+                msg_Warn( p_input, "trying to resync..." );
         }
-    } 
-    return( 1 );
+    }
 }
 
-/* make difference between audio and video pts as little as possible */
-static void AVI_SynchroReInit( input_thread_t *p_input )
+/****************************************************************************
+ * Index stuff.
+ ****************************************************************************/
+static void AVI_IndexAddEntry( demux_sys_t *p_sys,
+                               int i_stream,
+                               AVIIndexEntry_t *p_index)
 {
-    demux_sys_t *p_avi = p_input->p_demux_data;
-    
-#define p_info_video p_avi->p_info_video
-#define p_info_audio p_avi->p_info_audio
-    if( ( !p_info_audio )||( !p_info_video ) )
+    avi_track_t *tk = p_sys->track[i_stream];
+
+    /* Update i_movi_lastchunk_pos */
+    if( p_sys->i_movi_lastchunk_pos < p_index->i_pos )
     {
-        return;
+        p_sys->i_movi_lastchunk_pos = p_index->i_pos;
+    }
+
+    /* add the entry */
+    if( tk->i_idxnb >= tk->i_idxmax )
+    {
+        tk->i_idxmax += 16384;
+        tk->p_index = realloc( tk->p_index,
+                               tk->i_idxmax * sizeof( AVIIndexEntry_t ) );
+        if( tk->p_index == NULL )
+        {
+            return;
+        }
     }
-    /* now resynch audio video video */
-    /*don't care of AVIF_KEYFRAME */
-    if( !p_info_audio->header.i_samplesize )
+    /* calculate cumulate length */
+    if( tk->i_idxnb > 0 )
     {
-        AVI_SetStreamChunk( p_input, 
-                            p_info_audio, 
-                            AVI_PTSToChunk( p_info_audio,
-                                            AVI_GetPTS( p_info_video ) ) );
+        p_index->i_lengthtotal =
+            tk->p_index[tk->i_idxnb - 1].i_length +
+                tk->p_index[tk->i_idxnb - 1].i_lengthtotal;
     }
     else
     {
-        AVI_SetStreamBytes( p_input,
-                            p_info_audio,
-                            AVI_PTSToByte( p_info_audio,
-                                            AVI_GetPTS( p_info_video ) ) ); 
+        p_index->i_lengthtotal = 0;
     }
-#undef p_info_video
-#undef p_info_audio
-} 
 
-/*****************************************************************************
- * 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)
+    tk->p_index[tk->i_idxnb++] = *p_index;
+}
+
+static int AVI_IndexLoad_idx1( input_thread_t *p_input )
 {
-    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_sys_t *p_sys = p_input->p_demux_data;
+
+    avi_chunk_list_t    *p_riff;
+    avi_chunk_list_t    *p_movi;
+    avi_chunk_idx1_t    *p_idx1;
+
+    unsigned int i_stream;
+    unsigned int i_index;
+    off_t        i_offset;
+    unsigned int i;
 
-    if( i_dpts < 1000 ) 
-    { 
-        return( NULL ) ; 
+    p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
+    p_idx1 = AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0);
+    p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
+
+    if( !p_idx1 )
+    {
+        msg_Warn( p_input, "cannot find idx1 chunk, no index defined" );
+        return VLC_EGENERIC;
     }
 
-    if( !p_info->header.i_samplesize )
+    /* *** calculate offset *** */
+    /* Well, avi is __SHIT__ so test more than one entry
+     * (needed for some avi files) */
+    i_offset = 0;
+    for( i = 0; i < __MIN( p_idx1->i_entry_count, 10 ); i++ )
     {
-        int i_chunk = __MAX( AVI_PTSToChunk( p_info, i_dpts), 1 );
-        p_pes_first = NULL;
-        for( i = 0; i < i_chunk; i++ )
+        if( p_idx1->entry[i].i_pos < p_movi->i_chunk_pos )
         {
-            /* get pts while is valid */
-            i_pts = AVI_GetPTS( p_info ); 
-            p_pes_tmp = AVI_ReadStreamChunkInPES( p_input, p_info );
-
-            if( !p_pes_tmp )
-            {
-                return( p_pes_first );
-            }
-            p_pes_tmp->i_pts = i_pts;
-            if( !p_pes_first )
-            {
-                p_pes_first = p_pes_tmp;
-            }
-            else
-            {
-                p_pes->p_next = p_pes_tmp;
-            }
-            p_pes = p_pes_tmp;
+            i_offset = p_movi->i_chunk_pos + 8;
+            break;
         }
-        return( p_pes_first );
     }
-    else
+
+    for( i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )
     {
-        /* stream is byte based */
-        int i_byte = AVI_PTSToByte( p_info, i_dpts);
-        if( i_byte < 50 ) /* to avoid some problem with audio */
-        {
-            return( NULL );
-        }
-        i_pts = AVI_GetPTS( p_info );  /* ok even with broken index */
-        p_pes = AVI_ReadStreamBytesInPES( p_input, p_info, i_byte);
+        unsigned int i_cat;
 
-        if( p_pes )
+        AVI_ParseStreamHeader( p_idx1->entry[i_index].i_fourcc,
+                               &i_stream,
+                               &i_cat );
+        if( i_stream < p_sys->i_track &&
+            i_cat == p_sys->track[i_stream]->i_cat )
         {
-            p_pes->i_pts = i_pts;
+            AVIIndexEntry_t index;
+            index.i_id      = p_idx1->entry[i_index].i_fourcc;
+            index.i_flags   =
+                p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME);
+            index.i_pos     = p_idx1->entry[i_index].i_pos + i_offset;
+            index.i_length  = p_idx1->entry[i_index].i_length;
+            AVI_IndexAddEntry( p_sys, i_stream, &index );
         }
-        return( p_pes );
     }
-}
-/*****************************************************************************
- * AVI_DecodePES : send a pes to decoder 
- *****************************************************************************
- * Handle multiple pes, and update 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;
-    /* input_decode want only one pes, but AVI_GetFrameInPES give
-          multiple pes so send one by one */
-    while( p_pes )
-    {
-        p_pes_next = p_pes->p_next;
-        p_pes->p_next = NULL;
-        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;
-    }
-  
+    return VLC_SUCCESS;
 }
 
-/*****************************************************************************
- * AVIDemux_Seekable: reads and demuxes data packets for stream seekable
- *****************************************************************************
- * Called by AVIDemux, that make common work
- * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
- *****************************************************************************/
-static int AVIDemux_Seekable( input_thread_t *p_input,
-                              AVIStreamInfo_t *p_info_master,
-                              AVIStreamInfo_t *p_info_slave )
+static void __Parse_indx( input_thread_t    *p_input,
+                          int               i_stream,
+                          avi_chunk_indx_t  *p_indx )
 {
-    demux_sys_t *p_avi = p_input->p_demux_data;
+    demux_sys_t         *p_sys    = p_input->p_demux_data;
+    AVIIndexEntry_t     index;
+    int32_t             i;
 
-    pes_packet_t *p_pes_master;
-    pes_packet_t *p_pes_slave;
-
-    /* check for signal from interface */
-    if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
-    { 
-        /* 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, p_info_master ) )
+    msg_Dbg( p_input, "loading subindex(0x%x) %d entries", p_indx->i_indextype, p_indx->i_entriesinuse );
+    if( p_indx->i_indexsubtype == 0 )
+    {
+        for( i = 0; i < p_indx->i_entriesinuse; i++ )
         {
-            return( 0 ); /* assume EOF */
-        }
-        AVI_SynchroReInit( p_input ); 
-    }
+            index.i_id      = p_indx->i_id;
+            index.i_flags   = p_indx->idx.std[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
+            index.i_pos     = p_indx->i_baseoffset + p_indx->idx.std[i].i_offset - 8;
+            index.i_length  = p_indx->idx.std[i].i_size&0x7fffffff;
 
-    /* take care of newly selected audio ES */
-    if( p_info_master->b_selected )
-    {
-        p_info_master->b_selected = 0;
-        AVI_SynchroReInit( p_input ); 
+            AVI_IndexAddEntry( p_sys, i_stream, &index );
+        }
     }
-    if( ( p_info_slave )&&( p_info_slave->b_selected ) )
+    else if( p_indx->i_indexsubtype == AVI_INDEX_2FIELD )
     {
-        p_info_slave->b_selected = 0;
-        AVI_SynchroReInit( p_input );
-    }
+        for( i = 0; i < p_indx->i_entriesinuse; i++ )
+        {
+            index.i_id      = p_indx->i_id;
+            index.i_flags   = p_indx->idx.field[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
+            index.i_pos     = p_indx->i_baseoffset + p_indx->idx.field[i].i_offset - 8;
+            index.i_length  = p_indx->idx.field[i].i_size;
 
-    /* wait for the good time */
-    input_ClockManageRef( p_input,
-                          p_input->stream.p_selected_program,
-                          p_avi->i_pcr /*- DEFAULT_PTS_DELAY / 2 */); 
-    /* 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->i_pcr =  __MIN( AVI_GetPTS( p_info_master ),
-                                     AVI_GetPTS( p_info_slave ) ) * 9/100;
+            AVI_IndexAddEntry( p_sys, i_stream, &index );
+        }
     }
     else
     {
-        p_avi->i_pcr =  AVI_GetPTS( p_info_master ) * 9/100;
+        msg_Warn( p_input, "unknow subtype index(0x%x)", p_indx->i_indexsubtype );
     }
+}
+
+static void AVI_IndexLoad_indx( input_thread_t *p_input )
+{
+    demux_sys_t         *p_sys = p_input->p_demux_data;
+    unsigned int        i_stream;
+    int32_t             i;
 
-    /* get video and audio frames */
-    p_pes_master = AVI_GetFrameInPES( p_input,
-                                      p_info_master,
-                                      100000 ); /* 100 ms */
-    AVI_DecodePES( p_input,
-                   p_info_master,
-                   p_pes_master);
+    avi_chunk_list_t    *p_riff;
+    avi_chunk_list_t    *p_hdrl;
 
+    p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
+    p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
 
-    if( p_info_slave )
+    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
     {
-        p_pes_slave = 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_slave );
-    }
+        avi_chunk_list_t    *p_strl;
+        avi_chunk_indx_t    *p_indx;
 
+#define p_stream  p_sys->track[i_stream]
+        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream );
+        p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0 );
 
-    /* at the end ? */
-    return( p_pes_master ? 1 : 0 );
+        if( !p_indx )
+        {
+            msg_Warn( p_input, "cannot find indx (misdetect/broken OpenDML file?)" );
+            continue;
+        }
 
+        if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS )
+        {
+            __Parse_indx( p_input, i_stream, p_indx );
+        }
+        else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )
+        {
+            avi_chunk_indx_t    ck_sub;
+            for( i = 0; i < p_indx->i_entriesinuse; i++ )
+            {
+                if( stream_Seek( p_input->s, p_indx->idx.super[i].i_offset )||
+                    AVI_ChunkRead( p_input->s, &ck_sub, NULL  ) )
+                {
+                    break;
+                }
+                __Parse_indx( p_input, i_stream, &ck_sub );
+            }
+        }
+        else
+        {
+            msg_Warn( p_input, "unknow type index(0x%x)", p_indx->i_indextype );
+        }
+#undef p_stream
+    }
 }
 
-/*****************************************************************************
- * AVIDemux_NotSeekable: reads and demuxes data packets for stream seekable
- *****************************************************************************
- * Called by AVIDemux, that makes common work
- * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
- *****************************************************************************/
-
-/* 0 if can be load/updated, 1 if skip, 2 if descend into, 3 if exit, 4 if error and need recover */
-static int __AVIDemux_ChunkAction( int i_streams_max,
-                                   riffchunk_t *p_ck )
+static void AVI_IndexLoad( input_thread_t *p_input )
 {
-    int i_stream;
-    int i_type;
+    demux_sys_t *p_sys = p_input->p_demux_data;
+    unsigned int i_stream;
 
-    AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
-    if( i_stream < i_streams_max )
+    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
     {
-        return( 0 ); /* read and/or update stream info */
+        p_sys->track[i_stream]->i_idxnb  = 0;
+        p_sys->track[i_stream]->i_idxmax = 0;
+        p_sys->track[i_stream]->p_index  = NULL;
     }
 
-    if( i_stream <= 99 )
+    if( p_sys->b_odml )
     {
-        /* should not happen but ... */
-        return( 1 );
+        AVI_IndexLoad_indx( p_input );
     }
-
-    /* now we know that it's not a stream */
-
-    switch( p_ck->i_id )
+    else  if( AVI_IndexLoad_idx1( p_input ) )
     {
-        case( FOURCC_JUNK ):
-            return( 1 );
-        case( FOURCC_idx1 ):
-            return( 3 );
-        case( FOURCC_LIST ):
-            if( p_ck->i_type == FOURCC_rec )
-            {
-                return( 2 );
-            }
-            else
-            {
-                return( 1 );
-            }
-        default:
-            break;
-    } 
-    /* test for ix?? */
+        /* try indx if idx1 failed as some "normal" file have indx too */
+        AVI_IndexLoad_indx( p_input );
+    }
 
-    if( ( p_ck->i_id & 0xFFFF ) == VLC_TWOCC( 'i','x' ) )
+    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
     {
-        return( 1 );
+        msg_Dbg( p_input, "stream[%d] created %d index entries",
+                i_stream, p_sys->track[i_stream]->i_idxnb );
     }
-
-    return( 4 );
 }
 
-static int AVI_NotSeekableRecover( input_thread_t *p_input )
+static void AVI_IndexCreate( input_thread_t *p_input )
 {
-    byte_t *p_id;
-    u32 i_id;
-    int i_number, i_type;
-    data_packet_t *p_pack;
+    demux_sys_t *p_sys = p_input->p_demux_data;
 
-    for( ; ; )
-    {
-        if( input_Peek( p_input, &p_id, 4 ) < 4 )
-        {
-            return( 0 ); /* Failed */
-        }
-        i_id = GetDWLE( p_id );
-        switch( i_id )
-        {
-            case( FOURCC_idx1 ):
-            case( FOURCC_JUNK ):
-            case( FOURCC_LIST ):
-                return( 1 );
-            default:
-                AVI_ParseStreamHeader( i_id, &i_number, &i_type );
-                if( i_number <= 99 )
-                {
-                    switch( i_type )
-                    {
-                        case( TWOCC_wb ):
-                        case( TWOCC_db ):
-                        case( TWOCC_dc ):
-                        case( TWOCC_pc ):
-                            return( 1 );
-                    }
-                }
-                else
-                {
-
-                }
-        }
-        /* Read 1 byte VERY unoptimised */
-        if( input_SplitBuffer( p_input, &p_pack, 1) < 1 )
-        {
-            return( 0 );
-        }
-        input_DeletePacket( p_input->p_method_data, p_pack);
-    }
+    avi_chunk_list_t    *p_riff;
+    avi_chunk_list_t    *p_movi;
 
-}
+    unsigned int i_stream;
+    off_t i_movi_end;
 
-static int AVIDemux_NotSeekable( input_thread_t *p_input,
-                                 AVIStreamInfo_t *p_info_master,
-                                 AVIStreamInfo_t *p_info_slave )
-{
-    demux_sys_t *p_avi = p_input->p_demux_data;
-    int i_loop;
-    int i_stream;
-    int i_type;
-    
-    riffchunk_t *p_ck;
-    pes_packet_t *p_pes;
-   
-/*
-    i_filepos = AVI_TellAbsolute( p_input );
-    p_input->pf_seek( p_input, i_filepos ); 
-    input_AccessReinit( p_input );
-*/
-    
-#define p_info p_avi->pp_info[i_stream]
+    p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
+    p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
 
-    /* The managment is very basic, we will read packets, caclulate pts 
-    and send it to decoder, synchro made on video, and audio is very less
-    important */
-    
-    /* wait the good time */
-    input_ClockManageRef( p_input,
-                          p_input->stream.p_selected_program,
-                          p_avi->i_pcr /*- DEFAULT_PTS_DELAY / 2 */); 
-    /* TODO be smart, seeing if we can wait for min( audio, video )
-        or there is a too big deep */
-    if( !p_info_slave )
+    if( !p_movi )
     {
-        p_avi->i_pcr =  AVI_GetPTS( p_info_master ) * 9/100;
+        msg_Err( p_input, "cannot find p_movi" );
+        return;
     }
-    else
+
+    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
     {
-        p_avi->i_pcr =  __MIN( AVI_GetPTS( p_info_master ),
-                                 AVI_GetPTS( p_info_slave ) ) * 9/100;
-        p_avi->i_pcr =  AVI_GetPTS( p_info_master ) * 9/100;
+        p_sys->track[i_stream]->i_idxnb  = 0;
+        p_sys->track[i_stream]->i_idxmax = 0;
+        p_sys->track[i_stream]->p_index  = NULL;
     }
-    
-    for( i_loop = 0; i_loop < 10; i_loop++ )
+    i_movi_end = __MIN( (off_t)(p_movi->i_chunk_pos + p_movi->i_chunk_size),
+                        stream_Size( p_input->s ) );
+
+    stream_Seek( p_input->s, p_movi->i_chunk_pos + 12 );
+    msg_Warn( p_input, "creating index from LIST-movi, will take time !" );
+    for( ;; )
     {
-        int b_load =0;
-        
-        /* first find a ck for master or slave */
-        do
-        {
+        avi_packet_t pk;
 
-            if( !(p_ck = RIFF_ReadChunk( p_input ) ) )
-            {
-                msg_Err( p_input, "Badd" );
-                return( 0 ); /* assume EOF */
-            }
-            /*msg_Err( p_input,"Looking ck: %4.4s %d",&p_ck->i_id, p_ck->i_size );*/
+        if( p_input->b_die )
+        {
+            return;
+        }
 
-            switch( __AVIDemux_ChunkAction( p_avi->i_streams, p_ck ) )
+        if( AVI_PacketGetHeader( p_input, &pk ) )
+        {
+            break;
+        }
+        if( pk.i_stream < p_sys->i_track &&
+            pk.i_cat == p_sys->track[pk.i_stream]->i_cat )
+        {
+            AVIIndexEntry_t index;
+            index.i_id      = pk.i_fourcc;
+            index.i_flags   =
+               AVI_GetKeyFlag(p_sys->track[pk.i_stream]->i_codec, pk.i_peek);
+            index.i_pos     = pk.i_pos;
+            index.i_length  = pk.i_size;
+            AVI_IndexAddEntry( p_sys, pk.i_stream, &index );
+        }
+        else
+        {
+            switch( pk.i_fourcc )
             {
-                case( 0 ): /* load it if possible */
-                    b_load = 1;
-                    break;
-                case( 1 ): /* skip it */
-                    RIFF_DeleteChunk( p_input, p_ck );
-                    if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
+                case AVIFOURCC_idx1:
+                    if( p_sys->b_odml )
                     {
-                        return( 0 );
+                        avi_chunk_list_t *p_sysx;
+                        p_sysx = AVI_ChunkFind( &p_sys->ck_root,
+                                                AVIFOURCC_RIFF, 1 );
+
+                        msg_Dbg( p_input, "looking for new RIFF chunk" );
+                        if( stream_Seek( p_input->s, p_sysx->i_chunk_pos + 24))
+                        {
+                            goto print_stat;
+                        }
+                        break;
                     }
-                    b_load = 0;
+                    goto print_stat;
+                case AVIFOURCC_RIFF:
+                        msg_Dbg( p_input, "new RIFF chunk found" );
+                case AVIFOURCC_rec:
+                case AVIFOURCC_JUNK:
                     break;
-                case( 2 ): /* descend into */
-                    RIFF_DeleteChunk( p_input, p_ck );
-                    RIFF_DescendChunk( p_input );
-                    b_load = 0;
-                    break;
-                case( 3 ): /* exit */
-                    RIFF_DeleteChunk( p_input, p_ck );
-                    return( 0 );
-                case( 4 ): /* Error */
-                    RIFF_DeleteChunk( p_input, p_ck );
-                    msg_Warn( p_input, "unknown chunk id 0x%8.8x, trying to recover", p_ck->i_id );
-                    if( !AVI_NotSeekableRecover( p_input ) )
+                default:
+                    msg_Warn( p_input, "need resync, probably broken avi" );
+                    if( AVI_PacketSearch( p_input ) )
                     {
-                        msg_Err( p_input, "cannot recover, dying" );
-                        return( -1 );
-                    }
-                    else
-                    {
-                        msg_Warn( p_input, "recovered sucessfully" );
+                        msg_Warn( p_input, "lost sync, abord index creation" );
+                        goto print_stat;
                     }
-                    b_load = 0;
-                    break;
             }
-
-        } while( !b_load );
-
-        AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
-        /* now check if we really have to load it */
-        if( ( p_info != p_info_master )&&( p_info != p_info_slave ) )
-        {
-            b_load = 0;
         }
-        else
-        {
-            if( p_info == p_info_master )
-            {
-                b_load = 1;
-            }
-            else
-            {
-                mtime_t i_dpts;
-                i_dpts = AVI_GetPTS( p_info_slave ) - 
-                            AVI_GetPTS( p_info_master );
-                if( i_dpts < 0 ) {i_dpts = - i_dpts; }
-                if( i_dpts < 600000 )
-                {
-                    b_load = 1;
-                } 
-                else
-                {
-                    b_load = 0;
-                }
-            }
 
+        if( ( !p_sys->b_odml && pk.i_pos + pk.i_size >= i_movi_end ) ||
+            AVI_PacketNext( p_input ) )
+        {
+            break;
         }
+    }
 
-        /* now do we can load this chunk ? */ 
-        if( b_load )
-        {
+print_stat:
+    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
+    {
+        msg_Dbg( p_input,
+                "stream[%d] creating %d index entries",
+                i_stream,
+                p_sys->track[i_stream]->i_idxnb );
+    }
+}
 
-            if( __AVI_GetDataInPES( p_input, &p_pes, p_ck->i_size + 8, 1) != p_ck->i_size + 8)
-            {
-                return( 0 );
-            }
-            p_pes->p_first->p_payload_start += 8;
-            p_pes->i_pes_size -= 8;
-            /* get PTS */
-            p_pes->i_pts = AVI_GetPTS( p_info );
-            AVI_DecodePES( p_input, p_info, p_pes );
-        }
-        else
-        {
+/*****************************************************************************
+ * Stream management
+ *****************************************************************************/
+static int AVI_TrackStopFinishedStreams( input_thread_t *p_input )
+{
+    demux_sys_t *p_sys = p_input->p_demux_data;
+    unsigned int i;
+    int b_end = VLC_TRUE;
 
-            if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
-            {
-                RIFF_DeleteChunk( p_input, p_ck );
-                return( 0 );
-            }
-        } 
-        
-        /* finaly update stream information */
-        if( p_info->header.i_samplesize )
+    for( i = 0; i < p_sys->i_track; i++ )
+    {
+        avi_track_t *tk = p_sys->track[i];
+        if( tk->i_idxposc >= tk->i_idxnb )
         {
-            p_info->i_idxposb += p_ck->i_size;
+            tk->b_activated = VLC_FALSE;
+            es_out_Control( p_input->p_es_out, ES_OUT_SET_ES_STATE, tk->p_es, VLC_FALSE );
         }
         else
         {
-            p_info->i_idxposc++;
+            b_end = VLC_FALSE;
         }
-        
-        RIFF_DeleteChunk( p_input, p_ck );
     }
-
-    return( 1 );
-#undef p_info
+    return( b_end );
 }
-/*****************************************************************************
- * AVIDemux: reads and demuxes data packets
- *****************************************************************************
- * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
- * TODO add support for unstreable file, just read a chunk and send it 
- *      to the right decoder, very easy
- *****************************************************************************/
 
-static int AVIDemux( input_thread_t *p_input )
+/****************************************************************************
+ * AVI_MovieGetLength give max streams length in second
+ ****************************************************************************/
+static mtime_t  AVI_MovieGetLength( input_thread_t *p_input )
 {
-    int i;
-    AVIStreamInfo_t *p_info_master;
-    AVIStreamInfo_t *p_info_slave;    
-
-    demux_sys_t *p_avi = p_input->p_demux_data;
+    demux_sys_t  *p_sys = p_input->p_demux_data;
+    mtime_t      i_maxlength = 0;
+    unsigned int i;
 
-    /* search new video and audio stream selected 
-          if current have been unselected*/
-    if( ( !p_avi->p_info_video )
-            || ( !p_avi->p_info_video->p_es->p_decoder_fifo ) )
+    for( i = 0; i < p_sys->i_track; i++ )
     {
-        p_avi->p_info_video = NULL;
-        for( i = 0; i < p_avi->i_streams; i++ )
+        avi_track_t *tk = p_sys->track[i];
+        mtime_t i_length;
+
+        /* fix length for each stream */
+        if( tk->i_idxnb < 1 || !tk->p_index )
         {
-            if( ( p_avi->pp_info[i]->i_cat == VIDEO_ES )
-                  &&( p_avi->pp_info[i]->p_es->p_decoder_fifo ) )
-            {
-                p_avi->p_info_video = p_avi->pp_info[i];
-                p_avi->p_info_video->b_selected = 1;
-                break;
-            }
+            continue;
         }
-    }
-    if( ( !p_avi->p_info_audio )
-            ||( !p_avi->p_info_audio->p_es->p_decoder_fifo ) )
-    {
-        p_avi->p_info_audio = NULL;
-        for( i = 0; i < p_avi->i_streams; i++ )
+
+        if( tk->i_samplesize )
         {
-            if( ( p_avi->pp_info[i]->i_cat == AUDIO_ES )
-                  &&( p_avi->pp_info[i]->p_es->p_decoder_fifo ) )
-            {
-                p_avi->p_info_audio = p_avi->pp_info[i];
-                p_avi->p_info_audio->b_selected = 1;
-                break;
-            }
+            i_length = AVI_GetDPTS( tk,
+                                    tk->p_index[tk->i_idxnb-1].i_lengthtotal +
+                                        tk->p_index[tk->i_idxnb-1].i_length );
         }
-    }
-    /* by default video is master for resync audio (after a seek .. ) */
-    if( p_avi->p_info_video )
-    {
-        p_info_master = p_avi->p_info_video;
-        p_info_slave  = p_avi->p_info_audio;
-    }
-    else
-    {
-        p_info_master = p_avi->p_info_audio;
-        p_info_slave  = NULL;
-    }
-    
-    if( !p_info_master ) 
-    {
-        msg_Err( p_input, "no stream selected" );
-        return( -1 );
-    }
-
-    /* manage rate, if not default: skeep audio */
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-    if( p_input->stream.control.i_rate != p_avi->i_rate )
-    {
-        if( p_avi->p_info_audio)
+        else
         {
-             p_avi->p_info_audio->b_selected = 1;
+            i_length = AVI_GetDPTS( tk, tk->i_idxnb );
         }
-        p_avi->i_rate = p_input->stream.control.i_rate;
-    }
-    vlc_mutex_unlock( &p_input->stream.stream_lock );    
-    p_avi->i_rate = DEFAULT_RATE;
-    if( p_avi->i_rate != DEFAULT_RATE )
-    {
-        p_info_slave = NULL;
-    }
+        i_length /= (mtime_t)1000000;    /* in seconds */
 
-    if( p_avi->b_seekable )
-    {
-        return( AVIDemux_Seekable( p_input,
-                                   p_info_master,
-                                   p_info_slave) );
-    }
-    else
-    {
-        return( AVIDemux_NotSeekable( p_input,
-                                      p_info_master,
-                                      p_info_slave ) );
+        msg_Dbg( p_input,
+                 "stream[%d] length:"I64Fd" (based on index)",
+                 i,
+                 i_length );
+        i_maxlength = __MAX( i_maxlength, i_length );
     }
-}
 
+    return i_maxlength;
+}