]> git.sesse.net Git - vlc/commitdiff
* all : rewrite demux part (simpler and cleaner). Please, tell me if you see
authorLaurent Aimar <fenrir@videolan.org>
Sun, 27 Oct 2002 15:37:16 +0000 (15:37 +0000)
committerLaurent Aimar <fenrir@videolan.org>
Sun, 27 Oct 2002 15:37:16 +0000 (15:37 +0000)
some regression.

modules/demux/avi/Modules.am
modules/demux/avi/avi.c
modules/demux/avi/avi.h
modules/demux/avi/libavi.c

index 60e8f7d3416dacd2f5cbda74b3714311d1c889ec..743c15ce1528fef2794dbef70b8da5c33f8d3149 100644 (file)
@@ -1,10 +1,8 @@
 SOURCES_avi = \
        modules/demux/avi/avi.c \
-       modules/demux/avi/libioRIFF.c \
     modules/demux/avi/libavi.c
 
 
 noinst_HEADERS += \
        modules/demux/avi/avi.h \
-       modules/demux/avi/libioRIFF.h \
     modules/demux/avi/libavi.h
index 2ac4d85e9dc51071b160b8acdad3fb8ba20fb1ba..4d921af5435bd76f9977344f395b76b6f8833d1f 100644 (file)
@@ -2,7 +2,7 @@
  * avi.c : AVI file Stream input module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: avi.c,v 1.6 2002/10/15 00:55:07 fenrir Exp $
+ * $Id: avi.c,v 1.7 2002/10/27 15:37:16 fenrir Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -33,7 +33,6 @@
 
 #include "video.h"
 
-#include "libioRIFF.h"
 #include "libavi.h"
 #include "avi.h"
 
@@ -61,14 +60,13 @@ vlc_module_begin();
                   "force index creation" );
 
     set_description( "avi demuxer" );
-    set_capability( "demux", 160 );
+    set_capability( "demux", 212 );
     set_callbacks( AVIInit, __AVIEnd );
 vlc_module_end();
 
 /*****************************************************************************
  * Some usefull functions to manipulate memory 
  *****************************************************************************/
-static int __AVI_GetDataInPES( input_thread_t *, pes_packet_t **, int, int );
 
 static u16 GetWLE( byte_t *p_buff )
 {
@@ -96,6 +94,66 @@ static inline off_t __EVEN( off_t i )
 
 #define __ABS( x ) ( (x) < 0 ? (-(x)) : (x) )
 
+/* read data in a pes */
+static int input_ReadInPES( input_thread_t *p_input, 
+                            pes_packet_t **pp_pes, 
+                            int i_size )
+{
+    pes_packet_t *p_pes;
+    data_packet_t *p_data;
+
+    
+    if( !(p_pes = input_NewPES( p_input->p_method_data ) ) )
+    {
+        pp_pes = NULL;
+        return( -1 );
+    }
+
+    *pp_pes = p_pes;
+
+    if( !i_size )
+    {
+        p_pes->p_first = 
+            p_pes->p_last  = 
+                input_NewPacket( p_input->p_method_data, 0 );
+        p_pes->i_nb_data = 1;
+        p_pes->i_pes_size = 0;
+        return( 0 );
+    }
+    
+    p_pes->i_nb_data = 0;
+    p_pes->i_pes_size = 0;
+
+    while( p_pes->i_pes_size < i_size )
+    {
+        int i_read;
+
+        i_read = input_SplitBuffer(p_input, 
+                                   &p_data, 
+                                   __MIN( i_size - 
+                                          p_pes->i_pes_size, 1024 ) );
+        if( i_read <= 0 )
+        {
+            return( p_pes->i_pes_size );
+        }
+        
+        if( !p_pes->p_first )
+        {
+            p_pes->p_first = p_data;
+        }
+        else
+        {
+            p_pes->p_last->p_next = p_data;
+        }
+        p_pes->p_last = p_data;
+        p_pes->i_nb_data++;
+        p_pes->i_pes_size += i_read;
+    } 
+
+
+       return( p_pes->i_pes_size );
+}
+
 /* Test if it seems that it's a key frame */
 static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, u8 *p_byte )
 {
@@ -212,97 +270,6 @@ vlc_fourcc_t AVI_FourccGetCodec( int i_cat, vlc_fourcc_t i_codec )
             return( VLC_FOURCC( 'u', 'n', 'd', 'f' ) );
     }
 }
-/*****************************************************************************
- * Data and functions to manipulate pes buffer
- *****************************************************************************/
-#define BUFFER_MAXTOTALSIZE     500*1024 /* 1/2 Mo */
-#define BUFFER_MAXSPESSIZE      200*1024
-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;
-
-    if( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE )
-    {
-        input_DeletePES( p_method_data, p_pes );
-        return;
-    }
-    
-    if( !( p_buffer_pes = malloc( sizeof( AVIESBuffer_t ) ) ) )
-    {
-        input_DeletePES( p_method_data, p_pes );
-        return;
-    }
-    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 ) 
-    {
-        p_info->p_pes_last->p_next = p_buffer_pes;
-    }
-    p_info->p_pes_last = p_buffer_pes;
-    if( !p_info->p_pes_first )
-    {
-        p_info->p_pes_first = p_buffer_pes;
-    }
-    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 )
-    {
-        p_buffer_pes = p_info->p_pes_first;
-        p_info->p_pes_first = p_buffer_pes->p_next;
-        if( !p_info->p_pes_first )
-        {
-            p_info->p_pes_last = NULL;
-        }
-        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 );
-    }
-    else
-    {
-        return( NULL );
-    }
-}
-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 )
-    {
-        input_DeletePES( p_method_data, p_pes );
-        return( 1 );
-    }
-    else
-    {
-        return( 0 );
-    }
-}
-static void AVI_PESBuffer_Flush( input_buffers_t *p_method_data,
-                                 AVIStreamInfo_t *p_info )
-{
-    while( p_info->p_pes_first )
-    {
-        AVI_PESBuffer_Drop( p_method_data, p_info );
-    }
-}
 
 static void AVI_ParseStreamHeader( u32 i_id, int *pi_number, int *pi_type )
 {
@@ -337,18 +304,6 @@ static void AVI_ParseStreamHeader( u32 i_id, int *pi_number, int *pi_type )
 #undef SET_PTR
 }
 
-typedef struct avi_packet_s
-{
-    u32     i_fourcc;
-    off_t   i_pos;
-    u32     i_size;
-    u32     i_type;     // only for AVIFOURCC_LIST
-    u8      i_peek[8];  //first 8 bytes
-
-    int     i_stream;
-    int     i_cat;
-} avi_packet_t;
-
 static int AVI_PacketGetHeader( input_thread_t *p_input, avi_packet_t *p_pk )
 {
     u8  *p_peek;
@@ -396,14 +351,25 @@ static int AVI_PacketRead( input_thread_t   *p_input,
                            avi_packet_t     *p_pk,
                            pes_packet_t     **pp_pes )
 {
+    int i_size;
+    int b_pad;
 
-    if( __AVI_GetDataInPES( p_input, pp_pes, p_pk->i_size + 8, 1) 
-            != p_pk->i_size + 8)
+    i_size = __EVEN( p_pk->i_size + 8 );
+    b_pad  = ( i_size != p_pk->i_size + 8 );
+    
+    if( input_ReadInPES( p_input, pp_pes, i_size ) != i_size )
     {
         return( 0 );
     }
     (*pp_pes)->p_first->p_payload_start += 8;
     (*pp_pes)->i_pes_size -= 8;
+
+    if( b_pad )
+    {
+        (*pp_pes)->p_last->p_payload_end--;
+        (*pp_pes)->i_pes_size--;
+    }
+
     return( 1 );
 }
 
@@ -435,7 +401,7 @@ static int AVI_PacketSearch( input_thread_t *p_input )
 }
 
 
-static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
+static void __AVI_AddEntryIndex( avi_stream_t *p_info,
                                  AVIIndexEntry_t *p_index)
 {
     if( p_info->p_index == NULL )
@@ -472,6 +438,19 @@ static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
 
     p_info->p_index[p_info->i_idxnb] = *p_index;
     p_info->i_idxnb++;
+
+}
+
+static void AVI_IndexAddEntry( demux_sys_t *p_avi, 
+                               int i_stream, 
+                               AVIIndexEntry_t *p_index)
+{
+    __AVI_AddEntryIndex( p_avi->pp_info[i_stream],
+                         p_index );
+    if( p_avi->i_movi_lastchunk_pos < p_index->i_pos )
+    {
+        p_avi->i_movi_lastchunk_pos = p_index->i_pos;
+    }
 }
 
 static void AVI_IndexLoad( input_thread_t *p_input )
@@ -526,11 +505,11 @@ static void AVI_IndexLoad( input_thread_t *p_input )
         {
             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_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_AddEntryIndex( p_avi->pp_info[i_stream],
-                                 &index );
+            AVI_IndexAddEntry( p_avi, i_stream, &index );
         }
     }
     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
@@ -591,8 +570,7 @@ static void AVI_IndexCreate( input_thread_t *p_input )
                AVI_GetKeyFlag(p_avi->pp_info[pk.i_stream]->i_codec, pk.i_peek);
             index.i_pos     = pk.i_pos;
             index.i_length  = pk.i_size;
-            __AVI_AddEntryIndex( p_avi->pp_info[pk.i_stream],
-                                 &index );
+            AVI_IndexAddEntry( p_avi, pk.i_stream, &index );
         }
         else
         {
@@ -659,8 +637,10 @@ static int  AVI_StreamStart( input_thread_t *p_input,
         vlc_mutex_unlock( &p_input->stream.stream_lock );
     }
     p_stream->i_activated = p_stream->p_es->p_decoder_fifo ? 1 : 0;
-
-    AVI_StreamSeek( p_input, p_avi, i_stream, p_avi->i_time );
+    if( p_stream->i_activated )
+    {
+        AVI_StreamSeek( p_input, p_avi, i_stream, p_avi->i_time );
+    }
 
     return( p_stream->i_activated );
 #undef  p_stream
@@ -677,8 +657,6 @@ static void    AVI_StreamStop( input_thread_t *p_input,
         return;
     }
     
-//    AVI_PESBuffer_Flush( p_input->p_method_data, p_stream );
-
     if( p_stream->p_es->p_decoder_fifo )
     {
         vlc_mutex_lock( &p_input->stream.stream_lock );
@@ -747,8 +725,6 @@ static void __AVIEnd ( vlc_object_t * p_this )
     int i;
     demux_sys_t *p_avi = p_input->p_demux_data  ; 
     
-    if( p_avi->p_movi ) 
-            RIFF_DeleteChunk( p_input, p_avi->p_movi );
     if( p_avi->pp_info )
     {
         for( i = 0; i < p_avi->i_streams; i++ )
@@ -758,8 +734,6 @@ static void __AVIEnd ( vlc_object_t * p_this )
                 if( p_avi->pp_info[i]->p_index )
                 {
                       free( p_avi->pp_info[i]->p_index );
-                      AVI_PESBuffer_Flush( p_input->p_method_data, 
-                                           p_avi->pp_info[i] );
                 }
                 free( p_avi->pp_info[i] ); 
             }
@@ -787,6 +761,8 @@ static int AVIInit( vlc_object_t * p_this )
     es_descriptor_t *p_es = NULL; /* avoid warning */
     int i;
 
+    int b_stream_audio, b_stream_video; 
+
     p_input->pf_demux = AVIDemux_Seekable;
     if( !AVI_TestFile( p_input ) )
     {
@@ -810,7 +786,6 @@ static int AVIInit( vlc_object_t * p_this )
     memset( p_avi, 0, sizeof( demux_sys_t ) );
     p_avi->i_time = 0;
     p_avi->i_pcr  = 0;
-    p_avi->i_rate = DEFAULT_RATE;
     p_avi->b_seekable = ( ( p_input->stream.b_seekable )
                         &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
     /* *** for unseekable stream, automaticaly use AVIDemux_interleaved *** */
@@ -900,10 +875,10 @@ static int AVIInit( vlc_object_t * p_this )
 
     /* now read info on each stream and create ES */
     p_avi->pp_info = calloc( p_avi->i_streams, 
-                            sizeof( AVIStreamInfo_t* ) );
+                            sizeof( avi_stream_t* ) );
     memset( p_avi->pp_info, 
             0, 
-            sizeof( AVIStreamInfo_t* ) * p_avi->i_streams );
+            sizeof( avi_stream_t* ) * p_avi->i_streams );
 
     for( i = 0 ; i < p_avi->i_streams; i++ )
     {
@@ -914,15 +889,16 @@ static int AVIInit( vlc_object_t * p_this )
         int     i_init_size;
         void    *p_init_data;
 #define p_info  p_avi->pp_info[i]
-        p_info = malloc( sizeof(AVIStreamInfo_t ) );
-        memset( p_info, 0, sizeof( AVIStreamInfo_t ) );        
+        p_info = malloc( sizeof(avi_stream_t ) );
+        memset( p_info, 0, sizeof( avi_stream_t ) );        
     
         p_avi_strl = (avi_chunk_list_t*)AVI_ChunkFind( p_hdrl, 
                                                        AVIFOURCC_strl, i );
         p_avi_strh = (avi_chunk_strh_t*)AVI_ChunkFind( p_avi_strl, 
                                                        AVIFOURCC_strh, 0 );
-        p_avi_strf_auds = 
-            p_avi_strf_vids = AVI_ChunkFind( p_avi_strl, AVIFOURCC_strf, 0 );
+        p_avi_strf_auds = (avi_chunk_strf_auds_t*)
+            p_avi_strf_vids = (avi_chunk_strf_vids_t*)
+                AVI_ChunkFind( p_avi_strl, AVIFOURCC_strf, 0 );
 
         if( !p_avi_strl || !p_avi_strh || 
                 ( !p_avi_strf_auds && !p_avi_strf_vids ) )
@@ -1045,15 +1021,9 @@ static int AVIInit( vlc_object_t * p_this )
     }
     vlc_mutex_unlock( &p_input->stream.stream_lock ); 
 
-    /* create a pseudo p_movi */
-    p_avi->p_movi = malloc( sizeof( riffchunk_t ) );
-    p_avi->p_movi->i_id = AVIFOURCC_LIST;
-    p_avi->p_movi->i_type = AVIFOURCC_movi;
-    p_avi->p_movi->i_size = p_movi->i_chunk_size;
-    p_avi->p_movi->i_pos = p_movi->i_chunk_pos;
-    p_avi->p_movi->p_data = NULL;
-        
-
+    b_stream_audio = 0;
+    b_stream_video = 0;
+    
     for( i = 0; i < p_avi->i_streams; i++ )
     {
 #define p_info  p_avi->pp_info[i]
@@ -1061,19 +1031,16 @@ static int AVIInit( vlc_object_t * p_this )
         {
             case( VIDEO_ES ):
 
-                if( (p_avi->p_info_video == NULL) ) 
+                if( !b_stream_video ) 
                 {
-                    p_avi->p_info_video = p_info;
-                    /* TODO add test to see if a decoder has been found */
-                    AVI_StreamStart( p_input, p_avi, i );
+                    b_stream_video = AVI_StreamStart( p_input, p_avi, i );
                 }
                 break;
 
             case( AUDIO_ES ):
-                if( (p_avi->p_info_audio == NULL) ) 
+                if( !b_stream_audio ) 
                 {
-                    p_avi->p_info_audio = p_info;
-                    AVI_StreamStart( p_input, p_avi, i );
+                    b_stream_audio = AVI_StreamStart( p_input, p_avi, i );
                 }
                 break;
             default:
@@ -1082,16 +1049,16 @@ static int AVIInit( vlc_object_t * p_this )
 #undef p_info    
     }
 
-    /* we select the first audio and video ES */
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-    if( !p_avi->p_info_video ) 
+    if( !b_stream_video ) 
     {
         msg_Warn( p_input, "no video stream found" );
     }
-    if( !p_avi->p_info_audio )
+    if( !b_stream_audio )
     {
         msg_Warn( p_input, "no audio stream found!" );
     }
+
+    vlc_mutex_lock( &p_input->stream.stream_lock );
     p_input->stream.p_selected_program->b_is_ok = 1;
     vlc_mutex_unlock( &p_input->stream.stream_lock );
     
@@ -1104,6 +1071,9 @@ static int AVIInit( vlc_object_t * p_this )
         // already at begining of p_movi
     }
     AVI_SkipBytes( p_input, 12 ); // enter in p_movi
+
+    p_avi->i_movi_begin = p_movi->i_chunk_pos;
+    p_avi->i_movi_lastchunk_pos = 0;
     return( 0 );
 }
 
@@ -1114,7 +1084,7 @@ static int AVIInit( vlc_object_t * p_this )
  * Function to convert pts to chunk or byte
  *****************************************************************************/
 
-static inline mtime_t AVI_PTSToChunk( AVIStreamInfo_t *p_info, 
+static inline mtime_t AVI_PTSToChunk( avi_stream_t *p_info, 
                                         mtime_t i_pts )
 {
     return( (mtime_t)((s64)i_pts *
@@ -1122,7 +1092,7 @@ static inline mtime_t AVI_PTSToChunk( AVIStreamInfo_t *p_info,
                       (s64)p_info->i_scale /
                       (s64)1000000 ) );
 }
-static inline mtime_t AVI_PTSToByte( AVIStreamInfo_t *p_info,
+static inline mtime_t AVI_PTSToByte( avi_stream_t *p_info,
                                        mtime_t i_pts )
 {
     return( (mtime_t)((s64)i_pts * 
@@ -1132,7 +1102,28 @@ static inline mtime_t AVI_PTSToByte( AVIStreamInfo_t *p_info,
                       (s64)1000000 ) );
 
 }
-static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
+
+static mtime_t AVI_GetDPTS( avi_stream_t *p_stream, int i_count )
+{
+    if( p_stream->i_samplesize )
+    {
+        return( (mtime_t)( (s64)1000000 *
+                    (s64)i_count *
+                    (s64)p_stream->i_scale /
+                    (s64)p_stream->i_rate /
+                    (s64)p_stream->i_samplesize ) );
+    }
+    else
+    {
+        return( (mtime_t)( (s64)1000000 *
+                    (s64)i_count *
+                    (s64)p_stream->i_scale /
+                    (s64)p_stream->i_rate) );
+    }
+
+}
+
+static mtime_t AVI_GetPTS( avi_stream_t *p_info )
 {
     
     if( p_info->i_samplesize )
@@ -1175,712 +1166,175 @@ static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
     }
 }
 
-
-/*****************************************************************************
- * Functions to acces streams data 
- * Uses it, because i plane to read unseekable stream
- * XXX NEVER set directly i_idxposc and i_idxposb unless you know what you do 
- *****************************************************************************/
-
-/* 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 int AVI_StreamChunkFind( input_thread_t *p_input,
+                                int i_stream )
 {
+    demux_sys_t *p_avi = p_input->p_demux_data;
+    avi_packet_t avi_pk;
 
-    int i_read;
-    data_packet_t *p_data;
-
-    
-    if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
-    {
-        return( 0 );
-    }
+    /* find first chunk of i_stream that isn't in index */
 
-    
-    if( !i_size )
-    {
-        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 ) )
+    if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin )
     {
-        b_pad = 1;
-        i_size++;
+        AVI_SeekAbsolute( p_input, p_avi->i_movi_lastchunk_pos );
+        if( !AVI_PacketNext( p_input ) )
+        {
+            return( 0 );
+        }
     }
     else
     {
-        b_pad = 0;
+        AVI_SeekAbsolute( p_input, p_avi->i_movi_begin );
     }
 
-    do
+    for( ;; )
     {
-        i_read = input_SplitBuffer(p_input, &p_data, __MIN( i_size - 
-                                                              (*pp_pes)->i_pes_size, 1024 ) );
-        if( i_read < 0 )
+
+        if( !AVI_PacketGetHeader( p_input, &avi_pk ) )
         {
-            return( (*pp_pes)->i_pes_size );
+            msg_Err( p_input, "cannot get packet header" );
+            return( 0 );
         }
-        if( !(*pp_pes)->p_first )
+        if( avi_pk.i_stream >= p_avi->i_streams ||
+            ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
         {
-            (*pp_pes)->p_first = 
-                    (*pp_pes)->p_last  = p_data;
-            (*pp_pes)->i_nb_data = 1;
-            (*pp_pes)->i_pes_size = i_read;
+            switch( avi_pk.i_fourcc )
+            {
+                case AVIFOURCC_LIST:
+                    AVI_SkipBytes( p_input, 12 );
+                    break;
+                default:
+                    if( !AVI_PacketNext( p_input ) )
+                    {
+                        return( 0 );
+                    }
+                    break;
+            }
         }
         else
         {
-            (*pp_pes)->p_last->p_next = 
-                    (*pp_pes)->p_last = p_data;
-            (*pp_pes)->i_nb_data++;
-            (*pp_pes)->i_pes_size += i_read;
+            /* add this chunk to the index */
+            AVIIndexEntry_t index;
+            
+            index.i_id = avi_pk.i_fourcc;
+            index.i_flags = 
+               AVI_GetKeyFlag(p_avi->pp_info[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_avi, avi_pk.i_stream, &index );
+
+            if( avi_pk.i_stream == i_stream  )
+            {
+                return( 1 );
+            }
+            
+            if( !AVI_PacketNext( p_input ) )
+            {
+                return( 0 );
+            }
         }
-    } 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( i_size );
 }
 
-static int __AVI_SeekAndGetChunk( input_thread_t  *p_input,
-                                  AVIStreamInfo_t *p_info )
-{
-    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);
 
-    if( i_ret != i_length )
-    {
-        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 )
- */
-
-static inline int __AVI_GetChunkMethod( input_thread_t  *p_input,
-                                 AVIStreamInfo_t *p_info,
-                                 AVIStreamInfo_t *p_other )
+/* be sure that i_ck will be a valid index entry */
+static int AVI_SetStreamChunk( input_thread_t    *p_input,
+                               int i_stream,
+                               int i_ck )
 {
-    int i_info_pos;
-    int i_other_pos;
+    demux_sys_t *p_avi = p_input->p_demux_data;
+    avi_stream_t *p_stream = p_avi->pp_info[i_stream];
     
-    int i_info_pos_last;
-    int i_other_pos_last;
+    p_stream->i_idxposc = i_ck;
+    p_stream->i_idxposb = 0;
 
-    /*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 )
+    if(  i_ck < p_stream->i_idxnb )
     {
         return( 1 );
     }
-
-    /* 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 );
-    }
-
-    /* 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 ) ) )
+    else
     {
-        return( 0 );
-    }
-
-    /* KNOW for the 2 streams, the ck we want are after the last read 
-           or it's the first */
+        p_stream->i_idxposc = p_stream->i_idxnb - 1;
+        do
+        {
+            p_stream->i_idxposc++;
+            if( !AVI_StreamChunkFind( p_input, i_stream ) )
+            {
+                return( 0 );
+            }
 
-    /* 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 );
-}
+        } while( p_stream->i_idxposc < i_ck );
 
-                         
-static inline int __AVI_ChooseSize( int l1, int l2 )
-{
-    /* XXX l2 is prefered if 0 otherwise min not equal to 0 */
-    if( !l2 )
-    { 
-        return( 0 );
+        return( 1 );
     }
-    return( !l1 ? l2 : __MIN( l1,l2 ) );
 }
 
-/* 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 )
-{
-
-    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);
 
-    AVI_PESBuffer_Add( p_input->p_method_data,
-                       p_info,
-                       p_pes,
-                       i_ck,
-                       0 );
-    /* skip unwanted bytes */
-    if( i_length != i_size)
-    {
-        msg_Err( p_input, "Chunk Size mismatch" );
-        AVI_SeekAbsolute( p_input,
-                          __EVEN( AVI_TellAbsolute( p_input ) + 
-                                  i_size - i_length ) );
-    }
-    return( 1 );
-}
-
-/* XXX Don't use this function directly ! XXX */
-static int __AVI_GetChunk( input_thread_t  *p_input,
-                           AVIStreamInfo_t *p_info,
-                           int b_load )
+/* XXX FIXME up to now, we assume that all chunk are one after one */
+static int AVI_SetStreamBytes( input_thread_t    *p_input, 
+                               int i_stream,
+                               off_t   i_byte )
 {
     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( ( 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 ) )
-  
-        {
-            return( 1 ); /* we have it in buffer */
-        }
-        else
-        {
-            AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
-        }
-    }
-    /* 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 ;
+    avi_stream_t *p_stream = p_avi->pp_info[i_stream];
 
-    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 )
+    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 ) )
     {
-        /* 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++ )
+        /* index is valid to find the ck */
+        /* uses dichototmie to be fast enougth */
+        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_i->i_idxnb )
+            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_max->i_idxnb )
+                if( p_stream->p_index[i_idxposc].i_lengthtotal + 
+                        p_stream->p_index[i_idxposc].i_length <= i_byte)
                 {
-                    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;
-                    }
+                    i_idxmin  = i_idxposc ;
+                    i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
                 }
                 else
                 {
-                    p_info_max = p_info_i;
+                    p_stream->i_idxposc = i_idxposc;
+                    p_stream->i_idxposb = i_byte - 
+                            p_stream->p_index[i_idxposc].i_lengthtotal;
+                    return( 1 );
                 }
             }
         }
-        if( p_info_max->i_idxnb )
+        
+    }
+    else
+    {
+        p_stream->i_idxposc = p_stream->i_idxnb - 1;
+        p_stream->i_idxposb = 0;
+        do
         {
-            /* 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 */
-        }
-        else
-        {
-            i_posmax = p_avi->p_movi->i_pos + 12;
-        }
-    }
-    else
-    {
-        if( !b_load )
-        {
-            return( 1 ); /* all is ok */
-        }
-        /* 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;
-    }
-
-    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 */
-    {
-        riffchunk_t  *p_ck;
-        int i_type;
-        
-        /* Get the actual chunk in the stream */
-        if( !(p_ck = RIFF_ReadChunk( p_input )) )
-        {
-            return( 0 );
-        }
-/*        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 == AVIFOURCC_LIST )&&( p_ck->i_type == AVIFOURCC_rec ) )
-        {
-            AVI_SkipBytes( p_input, 12 );
-//            RIFF_DescendChunk( p_input );
-            RIFF_DeleteChunk( p_input, p_ck );
-            continue;
-        }
-        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 )
-        {
-            RIFF_DeleteChunk( p_input, p_ck );
-            if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
+            p_stream->i_idxposc++;
+            if( !AVI_StreamChunkFind( p_input, i_stream ) )
             {
                 return( 0 );
             }
-        }
-        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))
-            {
-                AVIIndexEntry_t index;
-
-                index.i_id = p_ck->i_id;
-                index.i_flags = AVI_GetKeyFlag( p_info_i->i_codec,
-                                                (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 );   
-            }
-
-
-            /* 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
-            {
-                /* skip it */
-                RIFF_DeleteChunk( p_input, p_ck );
-                if( RIFF_NextChunk( p_input, p_avi->p_movi ) != 0 )
-                {
-                    return( 0 );
-                }
-            }
-        }
-
-    
-    }
-    
-#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 )
-{
-
-    p_info->i_idxposc = i_ck;
-    p_info->i_idxposb = 0;
 
-    if(  i_ck < p_info->i_idxnb )
-    {
-        return( 1 );
-    }
-    else
-    {
-        p_info->i_idxposc = p_info->i_idxnb - 1;
-        do
-        {
-            p_info->i_idxposc++;
-            if( !__AVI_GetChunk( p_input, p_info, 0 ) )
-            {
-                return( 0 );
-            }
-        } while( p_info->i_idxposc < i_ck );
+        } 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( 1 );
     }
 }
 
-
-/* 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,
-                               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 ) )
-    {
-        /* 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_idxmin  = 0;
-        for( ;; )
-        {
-            if( p_info->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)
-                {
-                    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 );
-                }
-            }
-        }
-        
-    }
-    else
-    {
-        p_info->i_idxposc = p_info->i_idxnb - 1;
-        p_info->i_idxposb = 0;
-        do
-        {
-            p_info->i_idxposc++;
-            if( !__AVI_GetChunk( p_input, p_info, 0 ) )
-            {
-                return( 0 );
-            }
-        } 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 );
-    }
-}
-
-static pes_packet_t *AVI_ReadStreamChunkInPES(  input_thread_t  *p_input,
-                                                AVIStreamInfo_t *p_info )
-
-{
-    if( p_info->i_idxposc > p_info->i_idxnb )
-    {
-        return( NULL );
-    }
-
-    /* we want chunk (p_info->i_idxposc,0) */
-    p_info->i_idxposb = 0;
-    if( !__AVI_GetChunk( p_input, p_info, 1) )
-    {
-        msg_Err( p_input, "Got one chunk : failed" );
-        return( NULL );
-    }
-    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 )
-{
-    pes_packet_t    *p_pes;
-    data_packet_t   *p_data;
-    int             i_count = 0;
-    int             i_read;
-
-        
-    if( !( p_pes = input_NewPES( p_input->p_method_data ) ) )
-    {
-        return( NULL );
-    }
-    if( !( p_data = input_NewPacket( p_input->p_method_data, i_byte ) ) )
-    {
-        input_DeletePES( p_input->p_method_data, p_pes );
-        return( NULL );
-    }
-
-    p_pes->p_first =
-            p_pes->p_last = p_data;
-    p_pes->i_nb_data = 1;
-    p_pes->i_pes_size = i_byte;
-
-    while( i_byte > 0 )
-    {
-        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 );
-        }
-
-        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 );
-
-        AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
-        i_byte  -= i_read;
-        i_count += i_read;
-
-        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++;
-        }
-    }
-   return( p_pes );
-}
-
-/*****************************************************************************
- * AVI_GetFrameInPES : get dpts length(µs) in pes from stream
- *****************************************************************************
- * Handle multiple pes, and set pts to the good value 
- *****************************************************************************/
-static pes_packet_t *AVI_GetFrameInPES( input_thread_t *p_input,
-                                        AVIStreamInfo_t *p_info,
-                                        mtime_t i_dpts)
-{
-    int i;
-    pes_packet_t *p_pes = NULL;
-    pes_packet_t *p_pes_tmp = NULL;
-    pes_packet_t *p_pes_first = NULL;
-    mtime_t i_pts;
-
-    if( i_dpts < 1000 ) 
-    { 
-        return( NULL ) ; 
-    }
-
-    if( !p_info->i_samplesize )
-    {
-        int i_chunk = __MAX( AVI_PTSToChunk( p_info, i_dpts), 1 );
-        p_pes_first = NULL;
-        for( i = 0; i < i_chunk; i++ )
-        {
-            /* 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;
-        }
-        return( p_pes_first );
-    }
-    else
-    {
-        /* 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);
-
-        if( p_pes )
-        {
-            p_pes->i_pts = i_pts;
-        }
-        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;
-    }
-  
-}
-
 static int AVI_StreamSeek( input_thread_t *p_input,
                            demux_sys_t  *p_avi,
                            int i_stream, 
@@ -1889,14 +1343,17 @@ static int AVI_StreamSeek( input_thread_t *p_input,
 #define p_stream    p_avi->pp_info[i_stream]
     mtime_t i_oldpts;
     
-    AVI_PESBuffer_Flush( p_input->p_method_data, p_stream );
     i_oldpts = AVI_GetPTS( p_stream );
 
     if( !p_stream->i_samplesize )
     {
-        AVI_SetStreamChunk( p_input,
-                            p_stream, 
-                            AVI_PTSToChunk( p_stream, i_date ) );
+        if( !AVI_SetStreamChunk( p_input,
+                                 i_stream, 
+                                 AVI_PTSToChunk( p_stream, i_date ) ) )
+        {
+            return( 0 );
+        }
+                
         /* search key frame */
         msg_Dbg( p_input, 
                  "old:%lld %s new %lld",
@@ -1911,7 +1368,7 @@ static int AVI_StreamSeek( input_thread_t *p_input,
                                                             AVIIF_KEYFRAME ) )
             {
                 if( !AVI_SetStreamChunk( p_input,
-                                         p_stream,
+                                         i_stream,
                                          p_stream->i_idxposc - 1 ) )
                 {
                     return( 0 );
@@ -1920,11 +1377,12 @@ static int AVI_StreamSeek( input_thread_t *p_input,
         }
         else
         {
-            while( !( p_stream->p_index[p_stream->i_idxposc].i_flags &
+            while( p_stream->i_idxposc < p_stream->i_idxnb &&
+                    !( p_stream->p_index[p_stream->i_idxposc].i_flags &
                                                             AVIIF_KEYFRAME ) )
             {
                 if( !AVI_SetStreamChunk( p_input, 
-                                         p_stream, 
+                                         i_stream, 
                                          p_stream->i_idxposc + 1 ) )
                 {
                     return( 0 );
@@ -1934,9 +1392,12 @@ static int AVI_StreamSeek( input_thread_t *p_input,
     }
     else
     {
-        AVI_SetStreamBytes( p_input,
-                            p_stream,
-                            AVI_PTSToByte( p_stream, i_date ) );
+        if( !AVI_SetStreamBytes( p_input,
+                                 i_stream,
+                                 AVI_PTSToByte( p_stream, i_date ) ) )
+        {
+            return( 0 );
+        }
     }
     return( 1 );
 #undef p_stream
@@ -1962,8 +1423,7 @@ static int    AVISeek   ( input_thread_t *p_input,
     {
         if( !p_avi->i_length )
         {
-            int i_index;
-            AVIStreamInfo_t *p_stream;
+            avi_stream_t *p_stream;
             u64 i_pos;
 
             /* use i_percent to create a true i_date */
@@ -1981,41 +1441,38 @@ static int    AVISeek   ( input_thread_t *p_input,
             /* try to find chunk that is at i_percent or the file */
             i_pos = __MAX( i_percent * 
                            p_input->stream.p_selected_area->i_size / 100,
-                           p_avi->p_movi->i_pos );
+                           p_avi->i_movi_begin );
             /* search first selected stream */
-            for( i_index = 0,p_stream = NULL; 
-                 i_index < p_avi->i_streams; i_stream++ )
+            for( i_stream = 0, p_stream = NULL; 
+                        i_stream < p_avi->i_streams; i_stream++ )
             {
-                p_stream = p_avi->pp_info[i_index];
+                p_stream = p_avi->pp_info[i_stream];
                 if( p_stream->i_activated )
                 {
                     break;
                 }
             }
-            if( !p_stream || !p_stream->p_index )
+            if( !p_stream || !p_stream->i_activated )
             {
                 msg_Err( p_input, "cannot find any selected stream" );
                 return( -1 );
             }
-            /* search chunk */
-            p_stream->i_idxposc =  __MAX( p_stream->i_idxposc - 1, 0 );
-            while( ( i_pos < p_stream->p_index[p_stream->i_idxposc].i_pos )
-                   &&( p_stream->i_idxposc > 0 ) )
+            
+            /* be sure that the index exit */
+            if( !AVI_SetStreamChunk( p_input, 
+                                     i_stream,
+                                     0 ) )
             {
-                /* search before i_idxposc */
-                if( !AVI_SetStreamChunk( p_input, 
-                                         p_stream, p_stream->i_idxposc - 1 ) )
-                {
-                    msg_Err( p_input, "cannot seek" );
-                    return( -1 );
-                }
+                msg_Err( 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 )
             {
                 /* search after i_idxposc */
                 if( !AVI_SetStreamChunk( p_input, 
-                                         p_stream, p_stream->i_idxposc + 1 ) )
+                                         i_stream, p_stream->i_idxposc + 1 ) )
                 {
                     msg_Err( p_input, "cannot seek" );
                     return( -1 );
@@ -2076,16 +1533,26 @@ static int    AVISeek   ( input_thread_t *p_input,
  * 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
  *****************************************************************************/
+typedef struct avi_stream_toread_s
+{ 
+    int i_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_stream_toread_t;
 
 static int AVIDemux_Seekable( input_thread_t *p_input )
 {
-    int i;
     int i_stream;
     int b_stream;
 
+    // cannot be more than 100 stream (dcXX or wbXX)
+    avi_stream_toread_t toread[100]; 
+
     demux_sys_t *p_avi = p_input->p_demux_data;
 
     /* detect new selected/unselected streams */
@@ -2108,43 +1575,13 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
         }       
 #undef  p_stream
     }
-    /* 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 ) )
-    {
-        p_avi->p_info_video = NULL;
-        for( i = 0; i < p_avi->i_streams; i++ )
-        {
-            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];
-                break;
-            }
-        }
-    }
-    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( ( 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];
-                break;
-            }
-        }
-    }
 
     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
     {
         mtime_t i_date;
         int i_percent;
         /* first wait for empty buffer, arbitrary time FIXME */
-        msleep( DEFAULT_PTS_DELAY );
+//        msleep( DEFAULT_PTS_DELAY );
 
         i_date = (mtime_t)1000000 *
                  (mtime_t)p_avi->i_length *
@@ -2152,48 +1589,284 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
                  (mtime_t)p_input->stream.p_selected_area->i_size;
         i_percent = 100 * AVI_TellAbsolute( p_input ) / 
                         p_input->stream.p_selected_area->i_size;
-        AVISeek( p_input, i_date, i_percent);
+
 //        input_ClockInit( p_input->stream.p_selected_program );
+        AVISeek( p_input, i_date, i_percent);
     }
+
+    
     /* wait for the good time */
+
+    p_avi->i_pcr = p_avi->i_time * 9 / 100;
+
     input_ClockManageRef( p_input,
                           p_input->stream.p_selected_program,
                           p_avi->i_pcr ); 
 
-    p_avi->i_pcr = p_avi->i_time * 9 / 100;
+
     p_avi->i_time += 100*1000;  /* read 100ms */
+
+    /* init toread */
+    for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
+    {
+#define p_stream    p_avi->pp_info[i_stream]
+        mtime_t i_dpts;
+
+        toread[i_stream].i_ok = p_stream->i_activated;
+
+        if( p_stream->i_idxposc < p_stream->i_idxnb )
+        {
+            toread[i_stream].i_posf = 
+                p_stream->p_index[p_stream->i_idxposc].i_pos;
+           if( p_stream->i_idxposb > 0 )
+           {
+                toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
+           }
+        }
+        else
+        { 
+            toread[i_stream].i_posf = -1;
+        }
+
+        i_dpts = p_avi->i_time - AVI_GetPTS( p_stream  );
+
+        if( p_stream->i_samplesize )
+        {
+            toread[i_stream].i_toread = AVI_PTSToByte( p_stream, 
+                                                       __ABS( i_dpts ) );
+        }
+        else
+        {
+            toread[i_stream].i_toread = AVI_PTSToChunk( p_stream,
+                                                        __ABS( i_dpts ) );
+        }
+        
+        if( i_dpts < 0 )
+        {
+            toread[i_stream].i_toread *= -1;
+        }
+#undef  p_stream
+    }
+    
+    b_stream = 0;
     
-    for( i_stream = 0, b_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
+    for( ;; )
     {
 #define p_stream    p_avi->pp_info[i_stream]
+        int b_done;
         pes_packet_t    *p_pes;
+        off_t i_pos;
+        int i;
+        int i_size;
+        
+        /* search for first chunk to be read */
+        for( i = 0, b_done = 1, i_pos = -1; i < p_avi->i_streams; i++ )
+        {
+            if( !toread[i].i_ok ||
+                AVI_GetDPTS( p_avi->pp_info[i],
+                             toread[i].i_toread ) <= -25 * 1000 )
+            {
+                continue;
+            }
+
+            if( toread[i].i_toread > 0 )
+            {
+                b_done = 0; // not yet finished
+            }
+
+            if( toread[i].i_posf > 0 )
+            {
+                i_stream = i;
+                if( i_pos == -1 )
+                {
+                    i_pos = toread[i_stream].i_posf;
+                }
+                else
+                {
+                    i_pos = __MIN( i_pos, toread[i_stream].i_posf );
+                }
+            }
+        }
 
-        if( !p_stream->p_es ||
-            !p_stream->p_es->p_decoder_fifo )
+        if( b_done )
         {
+            return( b_stream ? 1 : 0 );
+        }
+        
+        if( i_pos == -1 )
+        {
+            /* no valid index, we will parse directly the stream */
+            if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin )
+            {
+                AVI_SeekAbsolute( p_input, p_avi->i_movi_lastchunk_pos );
+                if( !AVI_PacketNext( p_input ) )
+                {
+                    return( 0 );
+                }
+            }
+            else
+            {
+                AVI_SeekAbsolute( p_input, p_avi->i_movi_begin );
+            }
 
-            continue;
+            for( ;; )
+            {
+                avi_packet_t avi_pk;
+
+                if( !AVI_PacketGetHeader( p_input, &avi_pk ) )
+                {
+                    msg_Err( p_input, "cannot get packet header" );
+                    return( 0 );
+                }
+                if( avi_pk.i_stream >= p_avi->i_streams ||
+                    ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
+                {
+                    switch( avi_pk.i_fourcc )
+                    {
+                        case AVIFOURCC_LIST:
+                            AVI_SkipBytes( p_input, 12 );
+                            break;
+                        default:
+                            if( !AVI_PacketNext( p_input ) )
+                            {
+                                msg_Err( p_input, "cannot skip packet" );
+                                return( 0 );
+                            }
+                            break;
+                    }
+                    continue;
+                }
+                else
+                {
+                    /* add this chunk to the index */
+                    AVIIndexEntry_t index;
+                    
+                    index.i_id = avi_pk.i_fourcc;
+                    index.i_flags = 
+                       AVI_GetKeyFlag(p_avi->pp_info[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_avi, avi_pk.i_stream, &index );
+
+                    i_stream = avi_pk.i_stream;
+                    /* do we will read this data ? */
+                    if( AVI_GetDPTS( p_stream,
+                             toread[i_stream].i_toread ) > -25 * 1000 )
+                    {
+                        break;
+                    }
+                    else
+                    {
+                        if( !AVI_PacketNext( p_input ) )
+                        {
+                            msg_Err( p_input, "cannot skip packet" );
+                            return( 0 );
+                        }
+                    }
+                }
+            }
+            
         }
-        if( p_avi->i_time <= AVI_GetPTS( p_stream  ) )
+        else
         {
-            msg_Warn( p_input, "skeeping stream %d", i_stream );
-            b_stream = 1;
+            AVI_SeekAbsolute( p_input, i_pos );
+        }
+
+        /* read thoses data */
+        if( p_stream->i_samplesize )
+        {
+            i_size = __MIN( p_stream->p_index[p_stream->i_idxposc].i_length - 
+                                p_stream->i_idxposb,
+                                100 * 1024 ); // 10Ko max
+//                            toread[i_stream].i_toread );
+        }
+        else
+        {
+            i_size = p_stream->p_index[p_stream->i_idxposc].i_length;
+        }
+
+        if( p_stream->i_idxposb == 0 )
+        {
+            i_size += 8; // need to read and skip header
+        }
+
+        if( input_ReadInPES( p_input, &p_pes, __EVEN( i_size ) ) < 0 )
+        {
+            msg_Err( p_input, "failled reading data" );
+            toread[i_stream].i_ok = 0;
             continue;
         }
-        p_pes = AVI_GetFrameInPES( p_input,
-                                   p_stream,
-                                   p_avi->i_time - AVI_GetPTS( p_stream  ) ); 
-        if( p_pes )
+
+        if( i_size % 2 )    // read was padded on word boundary
         {
-            AVI_DecodePES( p_input, p_stream, p_pes );
-            b_stream = 1;
+            p_pes->p_last->p_payload_end--;
+            p_pes->i_pes_size--;
+        }
+        // skip header
+        if( p_stream->i_idxposb == 0 )
+        {
+            p_pes->p_first->p_payload_start += 8;
+            p_pes->i_pes_size -= 8;
         }
-#undef p_stream
-    }
 
-    /* at the end ? */
-    return( b_stream ? 1 : 0 );
+        p_pes->i_pts = AVI_GetPTS( p_stream );
+       
+        /* read data */
+        if( p_stream->i_samplesize )
+        {
+            if( p_stream->i_idxposb == 0 )
+            {
+                i_size -= 8;
+            }
+            toread[i_stream].i_toread -= i_size;
+            p_stream->i_idxposb += i_size;
+            if( p_stream->i_idxposb >= 
+                    p_stream->p_index[p_stream->i_idxposc].i_length )
+            {
+                p_stream->i_idxposb = 0;
+                p_stream->i_idxposc++;
+            }
+        }
+        else
+        {
+            toread[i_stream].i_toread--;
+            p_stream->i_idxposc++;
+        }
+
+        if( p_stream->i_idxposc < p_stream->i_idxnb)             
+        {
+            toread[i_stream].i_posf = 
+                p_stream->p_index[p_stream->i_idxposc].i_pos;
+            if( p_stream->i_idxposb > 0 )
+            {
+                toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
+            }
+            
+        }
+        else
+        {
+            toread[i_stream].i_posf = -1;
+        }
 
+        b_stream = 1; // at least one read succeed
+        
+        if( p_stream->p_es && p_stream->p_es->p_decoder_fifo )
+        {
+            p_pes->i_dts =
+                p_pes->i_pts = 
+                    input_ClockGetTS( p_input,
+                                      p_input->stream.p_selected_program,
+                                      p_pes->i_pts * 9/100);
+            
+            input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
+        }
+        else
+        {
+            input_DeletePES( p_input->p_method_data, p_pes );
+        }
+    }
+    
 }
 
 
@@ -2206,7 +1879,7 @@ static int AVIDemux_Seekable( input_thread_t *p_input )
 static int AVIDemux_UnSeekable( input_thread_t *p_input )
 {
     demux_sys_t     *p_avi = p_input->p_demux_data;
-    AVIStreamInfo_t *p_stream_master;
+    avi_stream_t *p_stream_master;
     int     i_stream;
     int     b_audio;
     int     i_packet;
@@ -2308,8 +1981,11 @@ static int AVIDemux_UnSeekable( input_thread_t *p_input )
                     {
                         return( -1 );
                     }
-                    p_pes->i_pts = AVI_GetPTS( p_stream );
-                    AVI_DecodePES( p_input, p_stream, p_pes );
+                    p_pes->i_pts = 
+                        input_ClockGetTS( p_input, 
+                                          p_input->stream.p_selected_program, 
+                                          AVI_GetPTS( p_stream ) * 9/100);
+                    input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
                 }
                 else
                 {
index 999f92161832f1da172b6331e5567b5f56897645..958c06463f0ed13e2bd608e3050de4fb251bd94e 100644 (file)
@@ -2,7 +2,7 @@
  * avi.h : AVI file Stream input module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: avi.h,v 1.4 2002/10/15 00:55:07 fenrir Exp $
+ * $Id: avi.h,v 1.5 2002/10/27 15:37:16 fenrir Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
-#define        MAX_PACKETS_IN_FIFO     2
+
+typedef struct avi_packet_s
+{
+    u32     i_fourcc;
+    off_t   i_pos;
+    u32     i_size;
+    u32     i_type;     // only for AVIFOURCC_LIST
+    
+    u8      i_peek[8];  //first 8 bytes
+
+    int     i_stream;
+    int     i_cat;
+} avi_packet_t;
+
 
 typedef struct AVIIndexEntry_s
 {
@@ -29,22 +42,14 @@ typedef struct AVIIndexEntry_s
     u32 i_pos;
     u32 i_length;
     u32 i_lengthtotal;
+
 } AVIIndexEntry_t;
 
-typedef struct AVIESBuffer_s
+typedef struct avi_stream_s
 {
-    struct AVIESBuffer_s *p_next;
-
-    pes_packet_t *p_pes;
-    int i_posc;
-    int i_posb;
-} AVIESBuffer_t;
-
+    int i_activated;
 
-typedef struct AVIStreamInfo_s
-{
     int i_cat;           /* AUDIO_ES, VIDEO_ES */
-    int i_activated;
     vlc_fourcc_t    i_fourcc;
     vlc_fourcc_t    i_codec;
 
@@ -52,8 +57,8 @@ typedef struct AVIStreamInfo_s
     int             i_scale;
     int             i_samplesize;
     
-    es_descriptor_t     *p_es;   
-    int                 b_selected; /* newly selected */
+    es_descriptor_t     *p_es;
+
     AVIIndexEntry_t     *p_index;
     int                 i_idxnb;
     int                 i_idxmax; 
@@ -61,32 +66,23 @@ typedef struct AVIStreamInfo_s
     int                 i_idxposc;  /* numero of chunk */
     int                 i_idxposb;  /* byte in the current chunk */
 
-    /* add some buffering */
-    AVIESBuffer_t       *p_pes_first;
-    AVIESBuffer_t       *p_pes_last;
-    int                 i_pes_count;
-    int                 i_pes_totalsize;
-} AVIStreamInfo_t;
+} avi_stream_t;
 
 struct demux_sys_t
 {
     mtime_t i_time;
     mtime_t i_length;
     mtime_t i_pcr; 
-    int     i_rate;
-    riffchunk_t *p_movi;
 
     int     b_seekable;
     avi_chunk_t ck_root;
     
-    /* Info extrated from avih */
-
+    off_t   i_movi_begin;
+    off_t   i_movi_lastchunk_pos; /* XXX position of last valid chunk */
+    
     /* number of stream and informations*/
     int i_streams;
-    AVIStreamInfo_t   **pp_info; 
+    avi_stream_t  **pp_info; 
 
-    /* current audio and video es */
-    AVIStreamInfo_t *p_info_video;
-    AVIStreamInfo_t *p_info_audio;
 };
 
index c2e7a86a0e72dbd128745a2d732ebee935079f31..b3eaa02d7eccb587df578086578f9cd7b86ea1f2 100644 (file)
@@ -2,7 +2,7 @@
  * libavi.c : 
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: libavi.c,v 1.2 2002/10/26 19:14:45 fenrir Exp $
+ * $Id: libavi.c,v 1.3 2002/10/27 15:37:16 fenrir Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -109,14 +109,33 @@ int AVI_SeekAbsolute( input_thread_t *p_input,
     }
     else
     {
-        int i_peek;
-        int i_skip = i_pos - i_filepos;
-        u8  *p_peek;
+        data_packet_t   *p_data;
+        int             i_skip = i_pos - i_filepos;
+        
         msg_Warn( p_input, "will skip %d bytes, slow", i_skip );
         if( i_skip < 0 )
         {
             return( 0 ); // failed
         }
+        while (i_skip > 0 )
+        {
+            int i_read;
+            
+            i_read = input_SplitBuffer( p_input, &p_data, 
+                                        __MIN( 4096, i_skip ) );
+            if( i_read < 0 )
+            {
+                return( 0 );
+            }
+            i_skip -= i_read;
+            
+            input_DeletePacket( p_input->p_method_data, p_data );
+            if( i_read == 0 && i_skip > 0 )
+            {
+                return( 0 );
+            }
+        }
+#if 0
         while( i_skip > 0 )
         {
             i_peek = input_Peek( p_input, &p_peek, i_skip+1 );
@@ -130,6 +149,7 @@ int AVI_SeekAbsolute( input_thread_t *p_input,
                 return( 0);
             }
         }
+#endif
         return( 1 );
     }
 }