]> git.sesse.net Git - vlc/blob - plugins/avi/avi.c
171c06009e4806724829471b4ba8a0575fb86953
[vlc] / plugins / avi / avi.c
1 /*****************************************************************************
2  * avi.c : AVI file Stream input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: avi.c,v 1.28 2002/06/30 15:07:57 fenrir Exp $
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include <stdlib.h>                                      /* malloc(), free() */
27 #include <string.h>                                              /* strdup() */
28 #include <errno.h>
29 #include <sys/types.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/input.h>
33
34 #include "video.h"
35
36 #include "libioRIFF.h"
37 #include "avi.h"
38
39 /*****************************************************************************
40  * Local prototypes
41  *****************************************************************************/
42 static void input_getfunctions( function_list_t * );
43 static int  AVIDemux         ( input_thread_t * );
44 static int  AVIInit          ( input_thread_t * );
45 static void AVIEnd           ( input_thread_t * );
46
47 /*****************************************************************************
48  * Build configuration tree.
49  *****************************************************************************/
50 MODULE_CONFIG_START
51 MODULE_CONFIG_STOP
52
53 MODULE_INIT_START
54     SET_DESCRIPTION( "RIFF-AVI Stream input" )
55     ADD_CAPABILITY( DEMUX, 150 )
56 MODULE_INIT_STOP
57
58 MODULE_ACTIVATE_START
59     input_getfunctions( &p_module->p_functions->demux );
60 MODULE_ACTIVATE_STOP
61
62 MODULE_DEACTIVATE_START
63 MODULE_DEACTIVATE_STOP
64
65 /*****************************************************************************
66  * Functions exported as capabilities. They are declared as static so that
67  * we don't pollute the namespace too much.
68  *****************************************************************************/
69 static void input_getfunctions( function_list_t * p_function_list )
70 {
71 #define input p_function_list->functions.demux
72     input.pf_init             = AVIInit;
73     input.pf_end              = AVIEnd;
74     input.pf_demux            = AVIDemux;
75     input.pf_rewind           = NULL;
76 #undef input
77 }
78
79
80 /*****************************************************************************
81  * Some usefull functions to manipulate memory 
82  *****************************************************************************/
83 static u16 GetWLE( byte_t *p_buff )
84 {
85     u16 i;
86     i = (*p_buff) + ( *(p_buff + 1) <<8 );
87     return ( i );
88 }
89 static u32 GetDWLE( byte_t *p_buff )
90 {
91     u32 i;
92     i = (*p_buff) + ( *(p_buff + 1) <<8 ) + 
93             ( *(p_buff + 2) <<16 ) + ( *(p_buff + 3) <<24 );
94     return ( i );
95 }
96 static u32 GetDWBE( byte_t *p_buff )
97 {
98     u32 i;
99     i = ((*p_buff)<<24) + ( *(p_buff + 1) <<16 ) + 
100             ( *(p_buff + 2) <<8 ) + ( *(p_buff + 3) );
101     return ( i );
102 }
103 static inline off_t __EVEN( off_t i )
104 {
105     return( (i & 1) ? i+1 : i );
106 }
107
108
109 /*****************************************************************************
110  * Functions for parsing the headers in an avi file
111  *****************************************************************************/
112 static void AVI_Parse_avih( MainAVIHeader_t *p_avih, byte_t *p_buff )
113 {
114     p_avih->i_microsecperframe = GetDWLE( p_buff );
115     p_avih->i_maxbytespersec   = GetDWLE( p_buff + 4);
116     p_avih->i_reserved1        = GetDWLE( p_buff + 8);
117     p_avih->i_flags            = GetDWLE( p_buff + 12);
118     p_avih->i_totalframes      = GetDWLE( p_buff + 16);
119     p_avih->i_initialframes    = GetDWLE( p_buff + 20);
120     p_avih->i_streams          = GetDWLE( p_buff + 24);
121     p_avih->i_suggestedbuffersize = GetDWLE( p_buff + 28);
122     p_avih->i_width            = GetDWLE( p_buff + 32 );
123     p_avih->i_height           = GetDWLE( p_buff + 36 );
124     p_avih->i_scale            = GetDWLE( p_buff + 40 );
125     p_avih->i_rate             = GetDWLE( p_buff + 44 );
126     p_avih->i_start            = GetDWLE( p_buff + 48);
127     p_avih->i_length           = GetDWLE( p_buff + 52);
128 }
129 static void AVI_Parse_Header( AVIStreamHeader_t *p_strh, byte_t *p_buff )
130 {
131     p_strh->i_type      = GetDWLE( p_buff );
132     p_strh->i_handler   = GetDWLE( p_buff + 4 );
133     p_strh->i_flags     = GetDWLE( p_buff + 8 );
134     p_strh->i_reserved1 = GetDWLE( p_buff + 12);
135     p_strh->i_initialframes = GetDWLE( p_buff + 16);
136     p_strh->i_scale     = GetDWLE( p_buff + 20);
137     p_strh->i_rate      = GetDWLE( p_buff + 24);
138     p_strh->i_start     = GetDWLE( p_buff + 28);
139     p_strh->i_length    = GetDWLE( p_buff + 32);
140     p_strh->i_suggestedbuffersize = GetDWLE( p_buff + 36);
141     p_strh->i_quality   = GetDWLE( p_buff + 40);
142     p_strh->i_samplesize = GetDWLE( p_buff + 44);
143 }
144 static void AVI_Parse_BitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
145 {
146     h->i_size          = GetDWLE( p_data );
147     h->i_width         = GetDWLE( p_data + 4 );
148     h->i_height        = GetDWLE( p_data + 8 );
149     h->i_planes        = GetWLE( p_data + 12 );
150     h->i_bitcount      = GetWLE( p_data + 14 );
151     h->i_compression   = GetDWLE( p_data + 16 );
152     h->i_sizeimage     = GetDWLE( p_data + 20 );
153     h->i_xpelspermeter = GetDWLE( p_data + 24 );
154     h->i_ypelspermeter = GetDWLE( p_data + 28 );
155     h->i_clrused       = GetDWLE( p_data + 32 );
156     h->i_clrimportant  = GetDWLE( p_data + 36 );
157 }
158 static void AVI_Parse_WaveFormatEx( waveformatex_t *h, byte_t *p_data )
159 {
160     h->i_formattag     = GetWLE( p_data );
161     h->i_channels      = GetWLE( p_data + 2 );
162     h->i_samplespersec = GetDWLE( p_data + 4 );
163     h->i_avgbytespersec= GetDWLE( p_data + 8 );
164     h->i_blockalign    = GetWLE( p_data + 12 );
165     h->i_bitspersample = GetWLE( p_data + 14 );
166     h->i_size          = GetWLE( p_data + 16 );
167 }
168
169 static inline int AVI_GetESTypeFromTwoCC( u16 i_type )
170 {
171     switch( i_type )
172     {
173         case( TWOCC_wb ):
174             return( AUDIO_ES );
175          case( TWOCC_dc ):
176          case( TWOCC_db ):
177             return( VIDEO_ES );
178          default:
179             return( UNKNOWN_ES );
180     }
181 }
182
183 static int AVI_AudioGetType( u32 i_type )
184 {
185     switch( i_type )
186     {
187 /*        case( WAVE_FORMAT_PCM ):
188             return( WAVE_AUDIO_ES ); */
189         case( WAVE_FORMAT_AC3 ):
190             return( AC3_AUDIO_ES );
191         case( WAVE_FORMAT_MPEG):
192         case( WAVE_FORMAT_MPEGLAYER3):
193             return( MPEG2_AUDIO_ES ); /* 2 for mpeg-2 layer 1 2 ou 3 */
194         default:
195             return( 0 );
196     }
197 }
198 static int AVI_VideoGetType( u32 i_type )
199 {
200     switch( i_type )
201     {
202         case( FOURCC_DIV1 ): /* FIXME it is for msmpeg4v1 or old mpeg4 ?? */
203         case( FOURCC_div1 ):
204         case( FOURCC_MPG4 ):
205         case( FOURCC_mpg4 ):
206             return( MSMPEG4v1_VIDEO_ES );
207
208         case( FOURCC_DIV2 ):
209         case( FOURCC_div2 ):
210         case( FOURCC_MP42 ):
211         case( FOURCC_mp42 ):
212             return( MSMPEG4v2_VIDEO_ES );
213          
214         case( FOURCC_MPG3 ):
215         case( FOURCC_mpg3 ):
216         case( FOURCC_div3 ):
217         case( FOURCC_MP43 ):
218         case( FOURCC_mp43 ):
219         case( FOURCC_DIV3 ):
220         case( FOURCC_DIV4 ):
221         case( FOURCC_div4 ):
222         case( FOURCC_DIV5 ):
223         case( FOURCC_div5 ):
224         case( FOURCC_DIV6 ):
225         case( FOURCC_div6 ):
226         case( FOURCC_AP41 ):
227         case( FOURCC_3IV1 ):
228             return( MSMPEG4v3_VIDEO_ES );
229
230         case( FOURCC_DIVX ):
231         case( FOURCC_divx ):
232         case( FOURCC_MP4S ):
233         case( FOURCC_mp4s ):
234         case( FOURCC_M4S2 ):
235         case( FOURCC_m4s2 ):
236         case( FOURCC_xvid ):
237         case( FOURCC_XVID ):
238         case( FOURCC_XviD ):
239         case( FOURCC_DX50 ):
240         case( FOURCC_mp4v ):
241         case( FOURCC_4    ):
242             return( MPEG4_VIDEO_ES );
243
244         default:
245             return( 0 );
246     }
247 }
248 /* Test if it seems that it's a key frame */
249 static int AVI_GetKeyFlag( int i_type, u8 *p_byte )
250 {
251     switch( i_type )
252     {
253         case( MSMPEG4v1_VIDEO_ES ):
254             if( GetDWBE( p_byte ) != 0x00000100 ) 
255             /* startcode perhaps swapped, I haven't tested */
256             {
257             /* it's seems it's not an msmpegv1 stream 
258                but perhaps I'm wrong so return yes */
259                 return( AVIIF_KEYFRAME );
260             }
261             else
262             {
263                 return( (*(p_byte+4))&0x06 ? 0 : AVIIF_KEYFRAME);
264             }
265         case( MSMPEG4v2_VIDEO_ES ):
266         case( MSMPEG4v3_VIDEO_ES ):
267 //            printf( "\n Is a Key Frame %s", (*p_byte)&0xC0 ? "no" : "yes!!" );
268             return( (*p_byte)&0xC0 ? 0 : AVIIF_KEYFRAME );
269         case( MPEG4_VIDEO_ES ):
270             if( GetDWBE( p_byte ) != 0x000001b6 )
271             {
272                 /* not true , need to find the first VOP header
273                     but, I'm lazy */
274                 return( AVIIF_KEYFRAME );
275             }
276             else
277             {
278 //                printf( "\n Is a Key Frame %s", (*(p_byte+4))&0xC0 ? "no" : 
279 //                                                                   "yes!!" );
280                 return( (*(p_byte+4))&0xC0 ? 0 : AVIIF_KEYFRAME );
281             }
282         default:
283             /* I can't do it, so said yes */
284             return( AVIIF_KEYFRAME );
285     }
286
287 }
288 /*****************************************************************************
289  * Data and functions to manipulate pes buffer
290  *****************************************************************************/
291 #define BUFFER_MAXTOTALSIZE   512*1024 /* 1/2 Mo */
292 #define BUFFER_MAXSPESSIZE 1024*200
293 static int  AVI_PESBuffer_IsFull( AVIStreamInfo_t *p_info )
294 {
295     return( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE ? 1 : 0);
296 }
297 static void AVI_PESBuffer_Add( input_buffers_t *p_method_data,
298                                AVIStreamInfo_t *p_info,
299                                pes_packet_t *p_pes,
300                                int i_posc,
301                                int i_posb )
302 {
303     AVIESBuffer_t   *p_buffer_pes;
304
305     if( p_info->i_pes_totalsize > BUFFER_MAXTOTALSIZE )
306     {
307         input_DeletePES( p_method_data, p_pes );
308         return;
309     }
310     
311     if( !( p_buffer_pes = malloc( sizeof( AVIESBuffer_t ) ) ) )
312     {
313         input_DeletePES( p_method_data, p_pes );
314         return;
315     }
316     p_buffer_pes->p_next = NULL;
317     p_buffer_pes->p_pes = p_pes;
318     p_buffer_pes->i_posc = i_posc;
319     p_buffer_pes->i_posb = i_posb;
320
321     if( p_info->p_pes_last ) 
322     {
323         p_info->p_pes_last->p_next = p_buffer_pes;
324     }
325     p_info->p_pes_last = p_buffer_pes;
326     if( !p_info->p_pes_first )
327     {
328         p_info->p_pes_first = p_buffer_pes;
329     }
330     p_info->i_pes_count++;
331     p_info->i_pes_totalsize += p_pes->i_pes_size;
332 }
333 static pes_packet_t *AVI_PESBuffer_Get( AVIStreamInfo_t *p_info )
334 {
335     AVIESBuffer_t   *p_buffer_pes;
336     pes_packet_t    *p_pes;
337     if( p_info->p_pes_first )
338     {
339         p_buffer_pes = p_info->p_pes_first;
340         p_info->p_pes_first = p_buffer_pes->p_next;
341         if( !p_info->p_pes_first )
342         {
343             p_info->p_pes_last = NULL;
344         }
345         p_pes = p_buffer_pes->p_pes;
346
347         free( p_buffer_pes );
348         p_info->i_pes_count--;
349         p_info->i_pes_totalsize -= p_pes->i_pes_size;
350         return( p_pes );
351     }
352     else
353     {
354         return( NULL );
355     }
356 }
357 static int AVI_PESBuffer_Drop( input_buffers_t *p_method_data,
358                                 AVIStreamInfo_t *p_info )
359 {
360     pes_packet_t *p_pes = AVI_PESBuffer_Get( p_info );
361     if( p_pes )
362     {
363         input_DeletePES( p_method_data, p_pes );
364         return( 1 );
365     }
366     else
367     {
368         return( 0 );
369     }
370 }
371 static void AVI_PESBuffer_Flush( input_buffers_t *p_method_data,
372                                  AVIStreamInfo_t *p_info )
373 {
374     while( p_info->p_pes_first )
375     {
376         AVI_PESBuffer_Drop( p_method_data, p_info );
377     }
378 }
379
380 static void AVI_ParseStreamHeader( u32 i_id, int *i_number, int *i_type )
381 {
382     int c1,c2;
383
384     c1 = ( i_id ) & 0xFF;
385     c2 = ( i_id >>  8 ) & 0xFF;
386
387     if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
388     {
389         *i_number = 100; /* > max stream number */
390         *i_type = 0;
391     }
392     else
393     {
394         *i_number = (c1 - '0') * 10 + (c2 - '0' );
395         *i_type = ( i_id >> 16 ) & 0xFFFF;
396     }
397 }
398
399 /* Function to manipulate stream easily */
400 static off_t AVI_TellAbsolute( input_thread_t *p_input )
401 {
402     off_t i_pos;
403     vlc_mutex_lock( &p_input->stream.stream_lock );
404     i_pos= p_input->stream.p_selected_area->i_tell -
405             ( p_input->p_last_data - p_input->p_current_data  );
406     vlc_mutex_unlock( &p_input->stream.stream_lock );
407
408     return( i_pos );
409 }
410                             
411 static int AVI_SeekAbsolute( input_thread_t *p_input,
412                              off_t i_pos)
413 {
414     off_t i_filepos;
415     /* FIXME add support for not seekable stream */
416
417     i_filepos = AVI_TellAbsolute( p_input );
418     if( i_pos != i_filepos )
419     {
420 //        msg_Err( p_input, "Seek --> delta %d", i_pos - i_filepos );
421         p_input->pf_seek( p_input, i_pos );
422         input_AccessReinit( p_input );
423     }
424     return( 1 );
425 }
426
427
428 static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
429                                  AVIIndexEntry_t *p_index)
430 {
431     AVIIndexEntry_t *p_tmp;
432     if( p_info->p_index == NULL )
433     {
434         p_info->i_idxmax = 16384;
435         p_info->i_idxnb = 0;
436         p_info->p_index = calloc( p_info->i_idxmax, 
437                                   sizeof( AVIIndexEntry_t ) );
438         if( p_info->p_index == NULL ) {return;}
439     }
440     if( p_info->i_idxnb >= p_info->i_idxmax )
441     {
442         p_info->i_idxmax += 16384;
443         p_tmp = realloc( (void*)p_info->p_index,
444                            p_info->i_idxmax * 
445                            sizeof( AVIIndexEntry_t ) );
446         if( !p_tmp ) 
447         { 
448             p_info->i_idxmax -= 16384;
449             return; 
450         }
451         p_info->p_index = p_tmp;
452     }
453     /* calculate cumulate length */
454     if( p_info->i_idxnb > 0 )
455     {
456         p_index->i_lengthtotal = p_info->p_index[p_info->i_idxnb-1].i_length +
457                 p_info->p_index[p_info->i_idxnb-1].i_lengthtotal;
458     }
459     else
460     {
461         p_index->i_lengthtotal = 0;
462     }
463
464     p_info->p_index[p_info->i_idxnb] = *p_index;
465     p_info->i_idxnb++;
466 }
467
468 static void __AVI_GetIndex( input_thread_t *p_input )
469 {
470     AVIIndexEntry_t index;
471     byte_t          *p_buff;
472     riffchunk_t     *p_idx1;
473     int             i_read;
474     int             i;
475     int             i_number;
476     int             i_type;
477     int             i_totalentry = 0;
478     demux_data_avi_file_t *p_avi_demux =
479                         (demux_data_avi_file_t*)p_input->p_demux_data  ;    
480
481     if( RIFF_FindAndGotoDataChunk( p_input,
482                                    p_avi_demux->p_riff, 
483                                    &p_idx1, 
484                                    FOURCC_idx1)!=0 )
485     {
486         msg_Warn( p_input, "cannot find index" );
487         RIFF_GoToChunk( p_input, p_avi_demux->p_hdrl );        
488         return;
489     }
490     p_avi_demux->p_idx1 = p_idx1;
491     msg_Dbg( p_input, "loading index" ); 
492     for(;;)
493     {
494         i_read = __MIN( 16*1024, p_idx1->i_size - i_totalentry *16);
495         if( ((i_read = input_Peek( p_input, &p_buff, i_read )) < 16 )
496               ||( i_totalentry *16 >= p_idx1->i_size ) )
497         {
498             msg_Dbg( p_input, "read %d idx entries", i_totalentry );
499             return;
500         }
501         i_read /= 16 ;
502         for( i = 0; i < i_read; i++ )
503         {
504             byte_t  *p_peek = p_buff + i * 16;
505             i_totalentry++;
506             index.i_id      = GetDWLE( p_peek );
507             index.i_flags   = GetDWLE( p_peek+4)&(~AVIIF_FIXKEYFRAME);
508             index.i_pos     = GetDWLE( p_peek+8);
509             index.i_length  = GetDWLE(p_peek+12);
510             AVI_ParseStreamHeader( index.i_id, &i_number, &i_type );
511             
512             if( ( i_number <  p_avi_demux->i_streams )
513                &&(p_avi_demux->pp_info[i_number]->i_cat == 
514                      AVI_GetESTypeFromTwoCC( i_type ))) 
515             {
516                 __AVI_AddEntryIndex( p_avi_demux->pp_info[i_number],
517                                      &index );
518             }
519         }
520         __RIFF_SkipBytes( p_input, 16 * i_read );
521     }
522
523 }
524
525 /* XXX call after get p_movi */
526 static void __AVI_UpdateIndexOffset( input_thread_t *p_input )
527 {
528     int i_stream;
529     int b_start = 1;/* if index pos is based on start of file or not (p_movi) */
530     demux_data_avi_file_t *p_avi_demux =
531                         (demux_data_avi_file_t*)p_input->p_demux_data;
532
533 /* FIXME some work to do :
534         * test in the file if it's true, if not do a RIFF_Find...
535 */
536 #define p_info p_avi_demux->pp_info[i_stream]
537     for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
538     {
539         if( ( p_info->p_index )
540            && ( p_info->p_index[0].i_pos < p_avi_demux->p_movi->i_pos + 8 ))
541         {
542             b_start = 0;
543             break;
544         }
545     }
546     if( !b_start )
547     {
548         for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
549         {
550             int i;
551             if( p_info->p_index )
552             {
553                 for( i = 0; i < p_info->i_idxnb; i++ )
554                 {
555                     p_info->p_index[i].i_pos += p_avi_demux->p_movi->i_pos + 8;
556                 }
557             }
558         }
559     }
560 #undef p_info
561 }
562
563 /*****************************************************************************
564  * AVIEnd: frees unused data
565  *****************************************************************************/
566 static void AVIEnd( input_thread_t *p_input )
567 {   
568     int i;
569     demux_data_avi_file_t *p_avi_demux;
570     p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data  ; 
571     
572     if( p_avi_demux->p_riff ) 
573             RIFF_DeleteChunk( p_input, p_avi_demux->p_riff );
574     if( p_avi_demux->p_hdrl ) 
575             RIFF_DeleteChunk( p_input, p_avi_demux->p_hdrl );
576     if( p_avi_demux->p_movi ) 
577             RIFF_DeleteChunk( p_input, p_avi_demux->p_movi );
578     if( p_avi_demux->p_idx1 ) 
579             RIFF_DeleteChunk( p_input, p_avi_demux->p_idx1 );
580     if( p_avi_demux->pp_info )
581     {
582         for( i = 0; i < p_avi_demux->i_streams; i++ )
583         {
584             if( p_avi_demux->pp_info[i] ) 
585             {
586                 if( p_avi_demux->pp_info[i]->p_index )
587                 {
588                       free( p_avi_demux->pp_info[i]->p_index );
589                       AVI_PESBuffer_Flush( p_input->p_method_data, 
590                                            p_avi_demux->pp_info[i] );
591                 }
592                 free( p_avi_demux->pp_info[i] ); 
593             }
594         }
595          free( p_avi_demux->pp_info );
596     }
597 }
598
599 /*****************************************************************************
600  * AVIInit: check file and initializes AVI structures
601  *****************************************************************************/
602 static int AVIInit( input_thread_t *p_input )
603 {
604     riffchunk_t *p_riff,*p_hdrl,*p_movi;
605     riffchunk_t *p_avih;
606     riffchunk_t *p_strl,*p_strh,*p_strf;
607     demux_data_avi_file_t *p_avi_demux;
608     es_descriptor_t *p_es = NULL; /* for not warning */
609
610     int i;
611
612     if( !( p_input->p_demux_data = 
613                     p_avi_demux = malloc( sizeof(demux_data_avi_file_t) ) ) )
614     {
615         msg_Err( p_input, "out of memory" );
616         return( -1 );
617     }
618     memset( p_avi_demux, 0, sizeof( demux_data_avi_file_t ) );
619     p_avi_demux->i_rate = DEFAULT_RATE;
620     p_avi_demux->b_seekable = ( ( p_input->stream.b_seekable )
621                         &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
622
623     /* Initialize access plug-in structures. */
624     if( p_input->i_mtu == 0 )
625     {
626         /* Improve speed. */
627         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
628     }
629
630     if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 )    
631     {
632         AVIEnd( p_input );
633         msg_Warn( p_input, "RIFF-AVI module discarded" );
634         return( -1 );
635     }
636     p_avi_demux->p_riff = p_riff;
637
638     if ( RIFF_DescendChunk(p_input) != 0 )
639     {
640         AVIEnd( p_input );
641         msg_Err( p_input, "cannot look for subchunk" );
642         return ( -1 );
643     }
644
645     /* it's a riff-avi file, so search for LIST-hdrl */
646     if( RIFF_FindListChunk(p_input ,&p_hdrl,p_riff, FOURCC_hdrl) != 0 )
647     {
648         AVIEnd( p_input );
649         msg_Err( p_input, "cannot find \"LIST-hdrl\"" );
650         return( -1 );
651     }
652     p_avi_demux->p_hdrl = p_hdrl;
653
654     if( RIFF_DescendChunk(p_input) != 0 )
655     {
656         AVIEnd( p_input );
657         msg_Err( p_input, "cannot look for subchunk" );
658         return ( -1 );
659     }
660     /* in  LIST-hdrl search avih */
661     if( RIFF_FindAndLoadChunk( p_input, p_hdrl, 
662                                     &p_avih, FOURCC_avih ) != 0 )
663     {
664         AVIEnd( p_input );
665         msg_Err( p_input, "cannot find \"avih\" chunk" );
666         return( -1 );
667     }
668     AVI_Parse_avih( &p_avi_demux->avih, p_avih->p_data->p_payload_start );
669     RIFF_DeleteChunk( p_input, p_avih );
670     
671     if( p_avi_demux->avih.i_streams == 0 )  
672     /* no stream found, perhaps it would be cool to find it */
673     {
674         AVIEnd( p_input );
675         msg_Err( p_input, "no stream defined!" );
676         return( -1 );
677     }
678
679     /*  create one program */
680     vlc_mutex_lock( &p_input->stream.stream_lock );
681     if( input_InitStream( p_input, 0 ) == -1)
682     {
683         vlc_mutex_unlock( &p_input->stream.stream_lock );
684         AVIEnd( p_input );
685         msg_Err( p_input, "cannot init stream" );
686         return( -1 );
687     }
688     if( input_AddProgram( p_input, 0, 0) == NULL )
689     {
690         vlc_mutex_unlock( &p_input->stream.stream_lock );
691         AVIEnd( p_input );
692         msg_Err( p_input, "cannot add program" );
693         return( -1 );
694     }
695     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
696     p_input->stream.i_mux_rate = p_avi_demux->avih.i_maxbytespersec / 50;
697     vlc_mutex_unlock( &p_input->stream.stream_lock ); 
698
699     /* now read info on each stream and create ES */
700     p_avi_demux->i_streams = p_avi_demux->avih.i_streams;
701     
702     p_avi_demux->pp_info = calloc( p_avi_demux->i_streams, 
703                                     sizeof( AVIStreamInfo_t* ) );
704     memset( p_avi_demux->pp_info, 
705             0, 
706             sizeof( AVIStreamInfo_t* ) * p_avi_demux->i_streams );
707
708     for( i = 0 ; i < p_avi_demux->i_streams; i++ )
709     {
710 #define p_info  p_avi_demux->pp_info[i]
711         p_info = malloc( sizeof(AVIStreamInfo_t ) );
712         memset( p_info, 0, sizeof( AVIStreamInfo_t ) );        
713
714         if( ( RIFF_FindListChunk(p_input,
715                                 &p_strl,p_hdrl, FOURCC_strl) != 0 )
716                 ||( RIFF_DescendChunk(p_input) != 0 ))
717         {
718             AVIEnd( p_input );
719             msg_Err( p_input, "cannot find \"LIST-strl\"" );
720             return( -1 );
721         }
722         
723         /* in  LIST-strl search strh */
724         if( RIFF_FindAndLoadChunk( p_input, p_hdrl, 
725                                 &p_strh, FOURCC_strh ) != 0 )
726         {
727             RIFF_DeleteChunk( p_input, p_strl );
728             AVIEnd( p_input );
729             msg_Err( p_input, "cannot find \"strh\"" );
730             return( -1 );
731         }
732         AVI_Parse_Header( &p_info->header,
733                             p_strh->p_data->p_payload_start);
734         RIFF_DeleteChunk( p_input, p_strh );      
735
736         /* in  LIST-strl search strf */
737         if( RIFF_FindAndLoadChunk( p_input, p_hdrl, 
738                                 &p_strf, FOURCC_strf ) != 0 )
739         {
740             RIFF_DeleteChunk( p_input, p_strl );
741             AVIEnd( p_input );
742             msg_Err( p_input, "cannot find \"strf\"" );
743             return( -1 );
744         }
745         /* we don't get strd, it's useless for divx,opendivx,mepgaudio */ 
746         if( RIFF_AscendChunk(p_input, p_strl) != 0 )
747         {
748             RIFF_DeleteChunk( p_input, p_strf );
749             RIFF_DeleteChunk( p_input, p_strl );
750             AVIEnd( p_input );
751             msg_Err( p_input, "cannot go out (\"strl\")" );
752             return( -1 );
753         }
754
755         /* add one ES */
756         vlc_mutex_lock( &p_input->stream.stream_lock );
757         p_es = input_AddES( p_input,
758                             p_input->stream.p_selected_program, 1+i,
759                             p_strf->i_size );
760         vlc_mutex_unlock( &p_input->stream.stream_lock );
761         p_es->i_stream_id =i; /* XXX: i don't use it */ 
762        
763         switch( p_info->header.i_type )
764         {
765             case( FOURCC_auds ):
766                 p_es->i_cat = AUDIO_ES;
767                 AVI_Parse_WaveFormatEx( &p_info->audio_format,
768                                    p_strf->p_data->p_payload_start ); 
769                 p_es->b_audio = 1;
770                 p_es->i_type = 
771                     AVI_AudioGetType( p_info->audio_format.i_formattag );
772                 if( !p_es->i_type )
773                 {
774                     msg_Warn( p_input, "stream(%d,0x%x) not supported", i,
775                                        p_info->audio_format.i_formattag );
776                     p_es->i_cat = UNKNOWN_ES;
777                 }
778                 break;
779                 
780             case( FOURCC_vids ):
781                 p_es->i_cat = VIDEO_ES;
782                 AVI_Parse_BitMapInfoHeader( &p_info->video_format,
783                                    p_strf->p_data->p_payload_start ); 
784                 p_es->b_audio = 0;
785                 p_es->i_type = 
786                     AVI_VideoGetType( p_info->video_format.i_compression );
787                 if( !p_es->i_type )
788                 {
789                     msg_Warn( p_input, "stream(%d,%4.4s) not supported", i,
790                               (char*)&p_info->video_format.i_compression);
791                     p_es->i_cat = UNKNOWN_ES;
792                 }
793                 break;
794             default:
795                 msg_Err( p_input, "unknown stream(%d) type", i );
796                 p_es->i_cat = UNKNOWN_ES;
797                 break;
798         }
799         p_info->p_es = p_es;
800         p_info->i_cat = p_es->i_cat;
801         /* We copy strf for decoder in p_es->p_demux_data */
802         memcpy( p_es->p_demux_data, 
803                 p_strf->p_data->p_payload_start,
804                 p_strf->i_size );
805         RIFF_DeleteChunk( p_input, p_strf );
806         RIFF_DeleteChunk( p_input, p_strl );
807 #undef p_info           
808     }
809
810
811
812     /* go out of p_hdrl */
813     if( RIFF_AscendChunk(p_input, p_hdrl) != 0)
814     {
815         AVIEnd( p_input );
816         msg_Err( p_input, "cannot go out (\"hdrl\")" );
817         return( -1 );
818     }
819
820     /* go to movi chunk to get it*/
821     if( RIFF_FindListChunk(p_input ,&p_movi,p_riff, FOURCC_movi) != 0 )
822     {
823         msg_Err( p_input, "cannot find \"LIST-movi\"" );
824         AVIEnd( p_input );
825         return( -1 );
826     }
827     p_avi_demux->p_movi = p_movi;
828     
829     /* get index  XXX need to have p_movi */
830     if( ( p_avi_demux->b_seekable )
831         &&( p_avi_demux->avih.i_flags&AVIF_HASINDEX ) ) 
832     {
833         /* get index */
834         __AVI_GetIndex( p_input ); 
835         /* try to get i_idxoffset for each stream  */
836         __AVI_UpdateIndexOffset( p_input );
837         /* to make sure to go the begining unless demux will see a seek */
838         RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
839         if( RIFF_DescendChunk( p_input ) != 0 )
840         {
841             AVIEnd( p_input );
842             msg_Err( p_input, "cannot go in (\"movi\")" );
843             return( -1 );
844         }
845     }
846     else
847     {
848         msg_Warn( p_input, "no index!" );
849     }
850
851
852     /* print informations on streams */
853     msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ", 
854              p_avi_demux->i_streams,
855              p_avi_demux->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
856              p_avi_demux->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
857              p_avi_demux->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
858              p_avi_demux->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
859
860     for( i = 0; i < p_avi_demux->i_streams; i++ )
861     {
862 #define p_info  p_avi_demux->pp_info[i]
863         switch( p_info->p_es->i_cat )
864         {
865             case( VIDEO_ES ):
866                 msg_Dbg( p_input, "video(%4.4s) %dx%d %dbpp %ffps",
867                          (char*)&p_info->video_format.i_compression,
868                          p_info->video_format.i_width,
869                          p_info->video_format.i_height,
870                          p_info->video_format.i_bitcount,
871                          (float)p_info->header.i_rate /
872                              (float)p_info->header.i_scale );
873                 if( (p_avi_demux->p_info_video == NULL) ) 
874                 {
875                     p_avi_demux->p_info_video = p_info;
876                     /* TODO add test to see if a decoder has been found */
877                     vlc_mutex_lock( &p_input->stream.stream_lock );
878                     input_SelectES( p_input, p_info->p_es );
879                     vlc_mutex_unlock( &p_input->stream.stream_lock );
880                 }
881                 break;
882
883             case( AUDIO_ES ):
884                 msg_Dbg( p_input, "audio(0x%x) %d channels %dHz %dbits",
885                          p_info->audio_format.i_formattag,
886                          p_info->audio_format.i_channels,
887                          p_info->audio_format.i_samplespersec,
888                          p_info->audio_format.i_bitspersample );
889                 if( (p_avi_demux->p_info_audio == NULL) ) 
890                 {
891                     p_avi_demux->p_info_audio = p_info;
892                     vlc_mutex_lock( &p_input->stream.stream_lock );
893                     input_SelectES( p_input, p_info->p_es );
894                     vlc_mutex_unlock( &p_input->stream.stream_lock );
895                 }
896                 break;
897             default:
898                 break;
899         }
900 #undef p_info    
901     }
902
903
904     /* we select the first audio and video ES */
905     vlc_mutex_lock( &p_input->stream.stream_lock );
906     if( !p_avi_demux->p_info_video ) 
907     {
908         msg_Warn( p_input, "no video stream found" );
909     }
910     if( !p_avi_demux->p_info_audio )
911     {
912         msg_Warn( p_input, "no audio stream found!" );
913     }
914     p_input->stream.p_selected_program->b_is_ok = 1;
915     vlc_mutex_unlock( &p_input->stream.stream_lock );
916
917     return( 0 );
918 }
919
920
921
922
923
924
925 /*****************************************************************************
926  * Function to convert pts to chunk or byte
927  *****************************************************************************/
928
929 static inline mtime_t AVI_PTSToChunk( AVIStreamInfo_t *p_info, 
930                                         mtime_t i_pts )
931 {
932     return( (mtime_t)((s64)i_pts *
933                       (s64)p_info->header.i_rate /
934                       (s64)p_info->header.i_scale /
935                       (s64)1000000 ) );
936 }
937 static inline mtime_t AVI_PTSToByte( AVIStreamInfo_t *p_info,
938                                        mtime_t i_pts )
939 {
940     return( (mtime_t)((s64)i_pts * 
941                       (s64)p_info->header.i_samplesize *
942                       (s64)p_info->header.i_rate /
943                       (s64)p_info->header.i_scale /
944                       (s64)1000000 ) );
945
946 }
947 static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
948 {
949     
950     if( p_info->header.i_samplesize )
951     {
952         /* we need a valid entry we will emulate one */
953         int i_len;
954         if( p_info->i_idxposc == p_info->i_idxnb )
955         {
956             if( p_info->i_idxposc )
957             {
958                 /* use the last entry */
959                 i_len = p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal
960                             + p_info->p_index[p_info->i_idxnb - 1].i_length
961                             + p_info->i_idxposb; /* should be 0 */
962             }
963             else
964             {
965                 i_len = 0; /* no valid zntry */
966             }
967         }
968         else
969         {
970             i_len = p_info->p_index[p_info->i_idxposc].i_lengthtotal
971                                 + p_info->i_idxposb;
972         }
973         return( (mtime_t)( (s64)1000000 *
974                    (s64)i_len *
975                     (s64)p_info->header.i_scale /
976                     (s64)p_info->header.i_rate /
977                     (s64)p_info->header.i_samplesize ) );
978     }
979     else
980     {
981         /* even if p_info->i_idxposc isn't valid, there isn't any probllem */
982         return( (mtime_t)( (s64)1000000 *
983                     (s64)(p_info->i_idxposc ) *
984                     (s64)p_info->header.i_scale /
985                     (s64)p_info->header.i_rate) );
986     }
987 }
988
989
990 /*****************************************************************************
991  * Functions to acces streams data 
992  * Uses it, because i plane to read unseekable stream
993  * Don't work for the moment for unseekable stream 
994  * XXX NEVER set directly i_idxposc and i_idxposb unless you know what you do 
995  *****************************************************************************/
996
997 /* FIXME FIXME change b_pad to number of bytes to skipp after reading */
998 static int __AVI_GetDataInPES( input_thread_t *p_input,
999                                pes_packet_t   **pp_pes,
1000                                int i_size,
1001                                int b_pad )
1002 {
1003
1004     int i_read;
1005     data_packet_t *p_data;
1006     
1007     if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
1008     {
1009         return( 0 );
1010     }
1011
1012     if( ( i_size&1 )&&( b_pad ) )
1013     {
1014         b_pad = 1;
1015         i_size++;
1016     }
1017     else
1018     {
1019         b_pad = 0;
1020     }
1021     
1022     if( !i_size )
1023     {
1024         (*pp_pes)->p_first = (*pp_pes)->p_last  = NULL;
1025         (*pp_pes)->i_nb_data = 0;
1026         (*pp_pes)->i_pes_size = 0;
1027         return( 0 );
1028     }
1029
1030     do
1031     {
1032         i_read = input_SplitBuffer(p_input, &p_data, i_size - 
1033                                                     (*pp_pes)->i_pes_size );
1034         if( i_read < 0 )
1035         {
1036             return( (*pp_pes)->i_pes_size );
1037         }
1038         if( !(*pp_pes)->p_first )
1039         {
1040             (*pp_pes)->p_first = 
1041                     (*pp_pes)->p_last  = p_data;
1042             (*pp_pes)->i_nb_data = 1;
1043             (*pp_pes)->i_pes_size = i_read;
1044         }
1045         else
1046         {
1047             (*pp_pes)->p_last->p_next = 
1048                     (*pp_pes)->p_last = p_data;
1049             (*pp_pes)->i_nb_data++;
1050             (*pp_pes)->i_pes_size += i_read;
1051         }
1052     } while( ((*pp_pes)->i_pes_size < i_size)&&( i_read ) );
1053
1054     if( b_pad )
1055     {
1056         (*pp_pes)->i_pes_size--;
1057         (*pp_pes)->p_last->p_payload_end--;
1058         i_size--;
1059     }
1060
1061         return( i_size );
1062 }
1063
1064 static int __AVI_SeekAndGetChunk( input_thread_t  *p_input,
1065                                   AVIStreamInfo_t *p_info )
1066 {
1067     pes_packet_t *p_pes;
1068     int i_length;
1069     
1070     i_length = __MIN( p_info->p_index[p_info->i_idxposc].i_length 
1071                         - p_info->i_idxposb,
1072                             BUFFER_MAXSPESSIZE );
1073
1074     AVI_SeekAbsolute( p_input, 
1075                       (off_t)p_info->p_index[p_info->i_idxposc].i_pos + 
1076                             p_info->i_idxposb + 8);
1077
1078     if( __AVI_GetDataInPES( p_input, 
1079                             &p_pes, 
1080                             i_length , 
1081                             0) != i_length )
1082     {
1083         return( 0 );
1084     }
1085     /*  TODO test key frame if i_idxposb == 0*/
1086     AVI_PESBuffer_Add( p_input->p_method_data,
1087                        p_info,
1088                        p_pes,
1089                        p_info->i_idxposc,
1090                        p_info->i_idxposb );
1091     return( 1 );
1092 }
1093 /* TODO check if it's correct (humm...) and optimisation ... */
1094 /* return 0 if we choose to get only the ck we want 
1095  *        1 if index is invalid
1096  *        2 if there is a ck_other before ck_info and the last proced ck_info*/
1097 /* XXX XXX XXX avi file is some BIG shit, and sometime index give 
1098  * a refenrence to the same chunk BUT with a different size ( usually 0 )
1099  */
1100
1101 static inline int __AVI_GetChunkMethod( input_thread_t  *p_input,
1102                                  AVIStreamInfo_t *p_info,
1103                                  AVIStreamInfo_t *p_other )
1104 {
1105     int i_info_pos;
1106     int i_other_pos;
1107     
1108     int i_info_pos_last;
1109     int i_other_pos_last;
1110
1111     /*If we don't have a valid entry we need to parse from last 
1112         defined chunk and it's the only way that we return 1*/
1113     if( p_info->i_idxposc >= p_info->i_idxnb )
1114     {
1115         return( 1 );
1116     }
1117
1118     /* KNOW we have a valid entry for p_info */
1119     /* we return 0 if we haven't an valid entry for p_other */ 
1120     if( ( !p_other )||( p_other->i_idxposc >= p_other->i_idxnb ) )
1121     {
1122         return( 0 );
1123     }
1124
1125     /* KNOW there are 2 streams with valid entry */
1126    
1127     /* we return 0 if for one of the two streams we will not read 
1128        chunk-aligned */
1129     if( ( p_info->i_idxposb )||( p_other->i_idxposb ) )
1130     { 
1131         return( 0 );
1132     }
1133     
1134     /* KNOW we have a valid entry for the 2 streams
1135          and for the 2 we want an aligned chunk (given by i_idxposc )*/
1136         /* if in stream, the next chunk is back than the one we 
1137            have just read, it's useless to parse */
1138     i_info_pos  = p_info->p_index[p_info->i_idxposc].i_pos;
1139     i_other_pos = p_other->p_index[p_other->i_idxposc].i_pos ;
1140
1141     i_info_pos_last  = p_info->i_idxposc ? 
1142                             p_info->p_index[p_info->i_idxposc - 1].i_pos : 0;
1143     i_other_pos_last = p_other->i_idxposc ?
1144                             p_other->p_index[p_other->i_idxposc - 1].i_pos : 0 ;
1145    
1146     
1147     if( ( ( p_info->i_idxposc )&&( i_info_pos <= i_info_pos_last ) ) ||
1148         ( ( p_other->i_idxposc )&&( i_other_pos <= i_other_pos_last ) ) )
1149     {
1150         return( 0 );
1151     }
1152
1153     /* KNOW for the 2 streams, the ck we want are after the last read 
1154            or it's the first */
1155
1156     /* if the first ck_other we want isn't between ck_info_last 
1157        and ck_info, don't parse */
1158     /* TODO fix this, use also number in buffered PES */
1159     if( ( i_other_pos > i_info_pos) /* ck_other too far */
1160         ||( i_other_pos < i_info_pos_last ) ) /* it's too late for ck_other */
1161     {
1162         return( 0 );
1163     } 
1164    
1165     /* we Know we will find ck_other, and before ck_info 
1166         "if ck_info is too far" will be handle after */
1167     return( 2 );
1168 }
1169
1170                          
1171 static inline int __AVI_ChooseSize( int l1, int l2 )
1172 {
1173     /* XXX l2 is prefered if 0 otherwise min not equal to 0 */
1174     if( !l2 )
1175     { 
1176         return( 0 );
1177     }
1178     return( !l1 ? l2 : __MIN( l1,l2 ) );
1179 }
1180
1181 /* We know we will read chunk align */
1182 static int __AVI_GetAndPutChunkInBuffer( input_thread_t  *p_input,
1183                                   AVIStreamInfo_t *p_info,
1184                                   int i_size,
1185                                   int i_ck )
1186 {
1187
1188     pes_packet_t    *p_pes;
1189     int i_length; 
1190
1191     i_length = __MIN( i_size, BUFFER_MAXSPESSIZE );
1192
1193     /* Skip chunk header */
1194
1195     if( __AVI_GetDataInPES( p_input, &p_pes, i_length + 8,1 ) != i_length +8 )
1196     {
1197         return( 0 );
1198     }
1199     p_pes->p_first->p_payload_start += 8;
1200
1201     i_size = GetDWLE( p_pes->p_first->p_demux_start + 4);
1202
1203     AVI_PESBuffer_Add( p_input->p_method_data,
1204                        p_info,
1205                        p_pes,
1206                        i_ck,
1207                        0 );
1208     /* skip unwanted bytes */
1209     if( i_length != i_size)
1210     {
1211         msg_Err( p_input, "Chunk Size mismatch" );
1212         AVI_SeekAbsolute( p_input,
1213                           __EVEN( AVI_TellAbsolute( p_input ) + 
1214                                   i_size - i_length ) );
1215     }
1216     return( 1 );
1217 }
1218
1219 /* XXX Don't use this function directly ! XXX */
1220 static int __AVI_GetChunk( input_thread_t  *p_input,
1221                            AVIStreamInfo_t *p_info,
1222                            int b_load )
1223 {
1224     demux_data_avi_file_t *p_avi_demux =
1225                         (demux_data_avi_file_t*)p_input->p_demux_data;
1226     AVIStreamInfo_t *p_other;
1227     int i_method;
1228     off_t i_posmax;
1229     int i;
1230    
1231 #define p_info_i p_avi_demux->pp_info[i]
1232     while( p_info->p_pes_first )
1233     {
1234         if( ( p_info->p_pes_first->i_posc == p_info->i_idxposc ) 
1235              &&( p_info->i_idxposb >= p_info->p_pes_first->i_posb )
1236              &&( p_info->i_idxposb < p_info->p_pes_first->i_posb + 
1237                      p_info->p_pes_first->p_pes->i_pes_size ) )
1238   
1239         {
1240             return( 1 ); /* we have it in buffer */
1241         }
1242         else
1243         {
1244             AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
1245         }
1246     }
1247     /* up to now we handle only one audio and video streams at the same time */
1248     p_other = (p_info == p_avi_demux->p_info_video ) ?
1249                      p_avi_demux->p_info_audio : p_avi_demux->p_info_video ;
1250
1251     i_method = __AVI_GetChunkMethod( p_input, p_info, p_other );
1252
1253     if( !i_method )
1254     {
1255         /* get directly the good chunk */
1256         return( b_load ? __AVI_SeekAndGetChunk( p_input, p_info ) : 1 );
1257     }
1258     /* We will parse
1259         * because invalid index
1260         * or will find ck_other before ck_info 
1261     */
1262 //    msg_Warn( p_input, "method %d", i_method ); 
1263     /* we will calculate the better position we have to reach */
1264     if( i_method == 1 )
1265     {
1266         /* invalid index */
1267     /*  the position max we have already reached */
1268         /* FIXME this isn't the better because sometime will fail to
1269             put in buffer p_other since it could be too far */
1270         AVIStreamInfo_t *p_info_max = p_info;
1271         
1272         for( i = 0; i < p_avi_demux->i_streams; i++ )
1273         {
1274             if( p_info_i->i_idxnb )
1275             {
1276                 if( p_info_max->i_idxnb )
1277                 {
1278                     if( p_info_i->p_index[p_info_i->i_idxnb -1 ].i_pos >
1279                             p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos )
1280                     {
1281                         p_info_max = p_info_i;
1282                     }
1283                 }
1284                 else
1285                 {
1286                     p_info_max = p_info_i;
1287                 }
1288             }
1289         }
1290         if( p_info_max->i_idxnb )
1291         {
1292             /* be carefull that size between index and ck can sometime be 
1293               different without any error (and other time it's an error) */
1294            i_posmax = p_info_max->p_index[p_info_max->i_idxnb -1 ].i_pos; 
1295            /* so choose this, and I know that we have already reach it */
1296         }
1297         else
1298         {
1299             i_posmax = p_avi_demux->p_movi->i_pos + 12;
1300         }
1301     }
1302     else
1303     {
1304         if( !b_load )
1305         {
1306             return( 1 ); /* all is ok */
1307         }
1308         /* valid index */
1309         /* we know that the entry and the last one are valid for the 2 stream */
1310         /* and ck_other will come *before* index so go directly to it*/
1311         i_posmax = p_other->p_index[p_other->i_idxposc].i_pos;
1312     }
1313
1314     AVI_SeekAbsolute( p_input, i_posmax );
1315     /* the first chunk we will see is :
1316             * the last chunk that we have already seen for broken index 
1317             * the first ck for other with good index */ 
1318     for( ; ; ) /* infinite parsing until the ck we want */
1319     {
1320         riffchunk_t  *p_ck;
1321         int i_type;
1322         
1323         /* Get the actual chunk in the stream */
1324         if( !(p_ck = RIFF_ReadChunk( p_input )) )
1325         {
1326             return( 0 );
1327         }
1328 //        msg_Dbg( p_input, "ck: %4.4s len %d", &p_ck->i_id, p_ck->i_size );
1329         /* special case for LIST-rec chunk */
1330         if( ( p_ck->i_id == FOURCC_LIST )&&( p_ck->i_type == FOURCC_rec ) )
1331         {
1332             RIFF_DescendChunk( p_input );
1333             RIFF_DeleteChunk( p_input, p_ck );
1334             continue;
1335         }
1336         AVI_ParseStreamHeader( p_ck->i_id, &i, &i_type );
1337         /* littles checks but not too much if you want to read all file */ 
1338         if( i >= p_avi_demux->i_streams )
1339         /* (AVI_GetESTypeFromTwoCC(i_type) != p_info_i->i_cat) perhaps add it*/
1340             
1341         {
1342             RIFF_DeleteChunk( p_input, p_ck );
1343             if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
1344             {
1345                 return( 0 );
1346             }
1347         }
1348         else
1349         {
1350             int i_size;
1351
1352             /* have we found a new entry (not present in index)? */
1353             if( ( !p_info_i->i_idxnb )
1354                 ||(p_info_i->p_index[p_info_i->i_idxnb-1].i_pos < p_ck->i_pos))
1355             {
1356                 AVIIndexEntry_t index;
1357
1358                 index.i_id = p_ck->i_id;
1359                 index.i_flags = AVI_GetKeyFlag( p_info_i->p_es->i_type,
1360                                                 (u8*)&p_ck->i_8bytes);
1361                 index.i_pos = p_ck->i_pos;
1362                 index.i_length = p_ck->i_size;
1363                 __AVI_AddEntryIndex( p_info_i, &index );   
1364             }
1365
1366
1367             /* TODO check if p_other is full and then if is possible 
1368                 go directly to the good chunk */
1369             if( ( p_info_i == p_other )
1370                 &&( !AVI_PESBuffer_IsFull( p_other ) )
1371                 &&( ( !p_other->p_pes_last )||
1372                     ( p_other->p_pes_last->p_pes->i_pes_size != 
1373                                                     BUFFER_MAXSPESSIZE ) ) )
1374             {
1375                 int i_ck = p_other->p_pes_last ? 
1376                         p_other->p_pes_last->i_posc + 1 : p_other->i_idxposc;
1377                 i_size = __AVI_ChooseSize( p_ck->i_size,
1378                                            p_other->p_index[i_ck].i_length);
1379                
1380                 if( p_other->p_index[i_ck].i_pos == p_ck->i_pos )
1381                 {
1382                     if( !__AVI_GetAndPutChunkInBuffer( p_input, p_other, 
1383                                                        i_size, i_ck ) )
1384                     {
1385                         RIFF_DeleteChunk( p_input, p_ck );
1386                         return( 0 );
1387                     }
1388                 }
1389                 else
1390                 {
1391                     if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
1392                     {
1393                         RIFF_DeleteChunk( p_input, p_ck );
1394
1395                         return( 0 );
1396                     }
1397
1398                 }
1399                         
1400                 RIFF_DeleteChunk( p_input, p_ck );
1401             }
1402             else
1403             if( ( p_info_i == p_info)
1404                 &&( p_info->i_idxposc < p_info->i_idxnb ) )
1405             {
1406                 /* the first ck_info is ok otherwise it should be 
1407                         loaded without parsing */
1408                 i_size = __AVI_ChooseSize( p_ck->i_size,
1409                                  p_info->p_index[p_info->i_idxposc].i_length);
1410
1411
1412                 RIFF_DeleteChunk( p_input, p_ck );
1413                 
1414                 return( b_load ? __AVI_GetAndPutChunkInBuffer( p_input,
1415                                                                p_info,
1416                                                                i_size,
1417                                                      p_info->i_idxposc ) : 1 );
1418             }
1419             else
1420             {
1421                 /* skip it */
1422                 RIFF_DeleteChunk( p_input, p_ck );
1423                 if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
1424                 {
1425                     return( 0 );
1426                 }
1427             }
1428         }
1429
1430     
1431     }
1432     
1433 #undef p_info_i
1434 }
1435
1436 /* be sure that i_ck will be a valid index entry */
1437 static int AVI_SetStreamChunk( input_thread_t    *p_input,
1438                                AVIStreamInfo_t   *p_info,
1439                                int   i_ck )
1440 {
1441
1442     p_info->i_idxposc = i_ck;
1443     p_info->i_idxposb = 0;
1444
1445     if(  i_ck < p_info->i_idxnb )
1446     {
1447         return( 1 );
1448     }
1449     else
1450     {
1451         p_info->i_idxposc = p_info->i_idxnb - 1;
1452         do
1453         {
1454             p_info->i_idxposc++;
1455             if( !__AVI_GetChunk( p_input, p_info, 0 ) )
1456             {
1457                 return( 0 );
1458             }
1459         } while( p_info->i_idxposc < i_ck );
1460
1461         return( 1 );
1462     }
1463 }
1464
1465
1466 /* XXX FIXME up to now, we assume that all chunk are one after one */
1467 static int AVI_SetStreamBytes( input_thread_t    *p_input, 
1468                                AVIStreamInfo_t   *p_info,
1469                                off_t   i_byte )
1470 {
1471     if( ( p_info->i_idxnb > 0 )
1472         &&( i_byte < p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal + 
1473                 p_info->p_index[p_info->i_idxnb - 1].i_length ) )
1474     {
1475         /* index is valid to find the ck */
1476         /* uses dichototmie to be fast enougth */
1477         int i_idxposc = __MIN( p_info->i_idxposc, p_info->i_idxnb - 1 );
1478         int i_idxmax  = p_info->i_idxnb;
1479         int i_idxmin  = 0;
1480         for( ;; )
1481         {
1482             if( p_info->p_index[i_idxposc].i_lengthtotal > i_byte )
1483             {
1484                 i_idxmax  = i_idxposc ;
1485                 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1486             }
1487             else
1488             {
1489                 if( p_info->p_index[i_idxposc].i_lengthtotal + 
1490                         p_info->p_index[i_idxposc].i_length <= i_byte)
1491                 {
1492                     i_idxmin  = i_idxposc ;
1493                     i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1494                 }
1495                 else
1496                 {
1497                     p_info->i_idxposc = i_idxposc;
1498                     p_info->i_idxposb = i_byte - 
1499                             p_info->p_index[i_idxposc].i_lengthtotal;
1500                     return( 1 );
1501                 }
1502             }
1503         }
1504         
1505     }
1506     else
1507     {
1508         p_info->i_idxposc = p_info->i_idxnb - 1;
1509         p_info->i_idxposb = 0;
1510         do
1511         {
1512             p_info->i_idxposc++;
1513             if( !__AVI_GetChunk( p_input, p_info, 0 ) )
1514             {
1515                 return( 0 );
1516             }
1517         } while( p_info->p_index[p_info->i_idxposc].i_lengthtotal +
1518                     p_info->p_index[p_info->i_idxposc].i_length <= i_byte );
1519
1520         p_info->i_idxposb = i_byte -
1521                        p_info->p_index[p_info->i_idxposc].i_lengthtotal;
1522         return( 1 );
1523     }
1524 }
1525
1526 static pes_packet_t *AVI_ReadStreamChunkInPES(  input_thread_t  *p_input,
1527                                                 AVIStreamInfo_t *p_info )
1528
1529 {
1530     if( p_info->i_idxposc > p_info->i_idxnb )
1531     {
1532         return( NULL );
1533     }
1534
1535     /* we want chunk (p_info->i_idxposc,0) */
1536     p_info->i_idxposb = 0;
1537     if( !__AVI_GetChunk( p_input, p_info, 1) )
1538     {
1539         msg_Err( p_input, "Got one chunk : failed" );
1540         return( NULL );
1541     }
1542     p_info->i_idxposc++;
1543     return( AVI_PESBuffer_Get( p_info ) );
1544 }
1545
1546 static pes_packet_t *AVI_ReadStreamBytesInPES(  input_thread_t  *p_input,
1547                                                 AVIStreamInfo_t *p_info,
1548                                                 int i_byte )
1549 {
1550     pes_packet_t    *p_pes;
1551     data_packet_t   *p_data;
1552     int             i_count = 0;
1553     int             i_read;
1554
1555         
1556     if( !( p_pes = input_NewPES( p_input->p_method_data ) ) )
1557     {
1558         return( NULL );
1559     }
1560     if( !( p_data = input_NewPacket( p_input->p_method_data, i_byte ) ) )
1561     {
1562         input_DeletePES( p_input->p_method_data, p_pes );
1563         return( NULL );
1564     }
1565
1566     p_pes->p_first =
1567             p_pes->p_last = p_data;
1568     p_pes->i_nb_data = 1;
1569     p_pes->i_pes_size = i_byte;
1570
1571     while( i_byte > 0 )
1572     {
1573         if( !__AVI_GetChunk( p_input, p_info, 1) )
1574         {
1575          msg_Err( p_input, "Got one chunk : failed" );
1576            
1577             input_DeletePES( p_input->p_method_data, p_pes );
1578             return( NULL );
1579         }
1580
1581         i_read = __MIN( p_info->p_pes_first->p_pes->i_pes_size - 
1582                             ( p_info->i_idxposb - p_info->p_pes_first->i_posb ),
1583                         i_byte);
1584         /* FIXME FIXME FIXME follow all data packet */
1585         memcpy( p_data->p_payload_start + i_count, 
1586                 p_info->p_pes_first->p_pes->p_first->p_payload_start + 
1587                     p_info->i_idxposb - p_info->p_pes_first->i_posb,
1588                 i_read );
1589
1590         AVI_PESBuffer_Drop( p_input->p_method_data, p_info );
1591         i_byte  -= i_read;
1592         i_count += i_read;
1593
1594         p_info->i_idxposb += i_read;
1595         if( p_info->p_index[p_info->i_idxposc].i_length <= p_info->i_idxposb )
1596         {
1597             p_info->i_idxposb -= p_info->p_index[p_info->i_idxposc].i_length;
1598             p_info->i_idxposc++;
1599         }
1600     }
1601    return( p_pes );
1602 }
1603         
1604
1605
1606 /* try to realign after a seek */
1607 static int AVI_ReAlign( input_thread_t *p_input,
1608                         AVIStreamInfo_t *p_info )
1609 {
1610     int i;
1611     off_t   i_pos;
1612     int     b_after = 0;
1613     demux_data_avi_file_t *p_avi_demux =
1614                         (demux_data_avi_file_t*)p_input->p_demux_data;
1615
1616
1617     for( i = 0; i < p_avi_demux->i_streams; i++ )
1618     {
1619         AVI_PESBuffer_Flush( p_input->p_method_data, p_avi_demux->pp_info[i] );
1620     }
1621     /* Reinit clock
1622        TODO use input_ClockInit instead but need to be exported 
1623     p_input->stream.p_selected_program->last_cr = 0;
1624     p_input->stream.p_selected_program->last_syscr = 0;
1625     p_input->stream.p_selected_program->cr_ref = 0;
1626     p_input->stream.p_selected_program->sysdate_ref = 0;
1627     p_input->stream.p_selected_program->delta_cr = 0;
1628     p_input->stream.p_selected_program->c_average_count = 0; */
1629        
1630     i_pos = AVI_TellAbsolute( p_input );
1631
1632     p_info->i_idxposc--; /* in fact  p_info->i_idxposc is for ck to be read */
1633     
1634
1635     if( ( p_info->i_idxposc <= 0)
1636         ||( i_pos <= p_info->p_index[0].i_pos ) )
1637     {
1638         /*  before beginning of stream  */
1639         return( p_info->header.i_samplesize ?
1640                     AVI_SetStreamBytes( p_input, p_info, 0 ) :
1641                         AVI_SetStreamChunk( p_input, p_info, 0 ) );
1642     }
1643     
1644     b_after = ( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos );
1645     /* now find in what chunk we are */
1646     while( ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
1647            &&( p_info->i_idxposc > 0 ) )
1648     {
1649         /* search before i_idxposc */
1650
1651         if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc - 1 ) )
1652         {
1653             return( 0 );   
1654         }
1655     }
1656     
1657     while( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos +
1658                p_info->p_index[p_info->i_idxposc].i_length + 8 )
1659     {
1660         /* search after i_idxposc */
1661
1662         if( !AVI_SetStreamChunk( p_input, p_info, p_info->i_idxposc + 1 ) )
1663         {
1664             return( 0 );
1665         }
1666     }
1667
1668     /* search nearest key frame, only for video */
1669     if( p_info->i_cat == VIDEO_ES )
1670     {
1671         if( b_after )
1672         {
1673             while(!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME) )
1674             {
1675                 if( !AVI_SetStreamChunk( p_input, p_info, 
1676                                          p_info->i_idxposc + 1 ) )
1677                 {
1678                     return( 0 );
1679                 }
1680             }
1681         }
1682         else
1683         { 
1684             while( ( p_info->i_idxposc > 0 ) &&
1685               (!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME)) )
1686             {
1687
1688                 if( !AVI_SetStreamChunk( p_input, p_info, 
1689                                         p_info->i_idxposc - 1 ) )
1690                 {
1691
1692                     return( 0 );
1693                 }
1694             }
1695         }
1696     } 
1697     return( 1 );
1698 }
1699
1700 /* make difference between audio and video pts as little as possible */
1701 static void AVI_SynchroReInit( input_thread_t *p_input )
1702 {
1703     demux_data_avi_file_t *p_avi_demux =
1704                         (demux_data_avi_file_t*)p_input->p_demux_data;
1705     
1706 #define p_info_video p_avi_demux->p_info_video
1707 #define p_info_audio p_avi_demux->p_info_audio
1708     if( ( !p_info_audio )||( !p_info_video ) )
1709     {
1710         return;
1711     }
1712     /* now resynch audio video video */
1713     /*don't care of AVIF_KEYFRAME */
1714     if( !p_info_audio->header.i_samplesize )
1715     {
1716         AVI_SetStreamChunk( p_input, 
1717                             p_info_audio, 
1718                             AVI_PTSToChunk( p_info_audio,
1719                                             AVI_GetPTS( p_info_video ) ) );
1720     }
1721     else
1722     {
1723         AVI_SetStreamBytes( p_input,
1724                             p_info_audio,
1725                             AVI_PTSToByte( p_info_audio,
1726                                             AVI_GetPTS( p_info_video ) ) ); 
1727     }
1728 #undef p_info_video
1729 #undef p_info_audio
1730
1731
1732 /*****************************************************************************
1733  * AVI_GetFrameInPES : get dpts length(µs) in pes from stream
1734  *****************************************************************************
1735  * Handle multiple pes, and set pts to the good value 
1736  *****************************************************************************/
1737 static pes_packet_t *AVI_GetFrameInPES( input_thread_t *p_input,
1738                                         AVIStreamInfo_t *p_info,
1739                                         mtime_t i_dpts)
1740 {
1741     int i;
1742     pes_packet_t *p_pes = NULL;
1743     pes_packet_t *p_pes_tmp = NULL;
1744     pes_packet_t *p_pes_first = NULL;
1745     mtime_t i_pts;
1746
1747     if( i_dpts < 1000 ) 
1748     { 
1749         return( NULL ) ; 
1750     }
1751
1752     if( !p_info->header.i_samplesize )
1753     {
1754         int i_chunk = __MAX( AVI_PTSToChunk( p_info, i_dpts), 1 );
1755         p_pes_first = NULL;
1756         for( i = 0; i < i_chunk; i++ )
1757         {
1758             /* get pts while is valid */
1759             i_pts = AVI_GetPTS( p_info ); 
1760  
1761             p_pes_tmp = AVI_ReadStreamChunkInPES( p_input, p_info );
1762
1763             if( !p_pes_tmp )
1764             {
1765                 return( p_pes_first );
1766             }
1767             p_pes_tmp->i_pts = i_pts;
1768             if( !p_pes_first )
1769             {
1770                 p_pes_first = p_pes_tmp;
1771             }
1772             else
1773             {
1774                 p_pes->p_next = p_pes_tmp;
1775             }
1776             p_pes = p_pes_tmp;
1777         }
1778         return( p_pes_first );
1779     }
1780     else
1781     {
1782         /* stream is byte based */
1783         int i_byte = AVI_PTSToByte( p_info, i_dpts);
1784         if( i_byte < 50 ) /* to avoid some problem with audio */
1785         {
1786             return( NULL );
1787         }
1788         i_pts = AVI_GetPTS( p_info );  /* ok even with broken index */
1789         p_pes = AVI_ReadStreamBytesInPES( p_input, p_info, i_byte);
1790
1791         if( p_pes )
1792         {
1793             p_pes->i_pts = i_pts;
1794         }
1795         return( p_pes );
1796     }
1797 }
1798 /*****************************************************************************
1799  * AVI_DecodePES : send a pes to decoder 
1800  *****************************************************************************
1801  * Handle multiple pes, and update pts to the good value 
1802  *****************************************************************************/
1803 static inline void AVI_DecodePES( input_thread_t *p_input,
1804                                   AVIStreamInfo_t *p_info,
1805                                   pes_packet_t *p_pes )
1806 {
1807     pes_packet_t    *p_pes_next;
1808     /* input_decode want only one pes, but AVI_GetFrameInPES give
1809           multiple pes so send one by one */
1810     while( p_pes )
1811     {
1812         p_pes_next = p_pes->p_next;
1813         p_pes->p_next = NULL;
1814         p_pes->i_pts = input_ClockGetTS( p_input, 
1815                                          p_input->stream.p_selected_program, 
1816                                          p_pes->i_pts * 9/100);
1817         input_DecodePES( p_info->p_es->p_decoder_fifo, p_pes );
1818         p_pes = p_pes_next;
1819     }
1820   
1821 }
1822
1823 /*****************************************************************************
1824  * AVIDemux: reads and demuxes data packets
1825  *****************************************************************************
1826  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1827  * TODO add support for unstreable file, just read a chunk and send it 
1828  *      to the right decoder, very easy
1829  *****************************************************************************/
1830
1831 static int AVIDemux( input_thread_t *p_input )
1832 {
1833     int i;
1834     pes_packet_t *p_pes;
1835     AVIStreamInfo_t *p_info_master;
1836     AVIStreamInfo_t *p_info_slave;    
1837
1838     demux_data_avi_file_t *p_avi_demux = 
1839                 (demux_data_avi_file_t*)p_input->p_demux_data;
1840
1841     /* search new video and audio stream selected 
1842           if current have been unselected*/
1843     if( ( !p_avi_demux->p_info_video )
1844             || ( !p_avi_demux->p_info_video->p_es->p_decoder_fifo ) )
1845     {
1846         p_avi_demux->p_info_video = NULL;
1847         for( i = 0; i < p_avi_demux->i_streams; i++ )
1848         {
1849             if( ( p_avi_demux->pp_info[i]->i_cat == VIDEO_ES )
1850                   &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo ) )
1851             {
1852                 p_avi_demux->p_info_video = p_avi_demux->pp_info[i];
1853                 p_avi_demux->p_info_video->b_selected = 1;
1854                 break;
1855             }
1856         }
1857     }
1858     if( ( !p_avi_demux->p_info_audio )
1859             ||( !p_avi_demux->p_info_audio->p_es->p_decoder_fifo ) )
1860     {
1861         p_avi_demux->p_info_audio = NULL;
1862         for( i = 0; i < p_avi_demux->i_streams; i++ )
1863         {
1864             if( ( p_avi_demux->pp_info[i]->i_cat == AUDIO_ES )
1865                   &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo ) )
1866             {
1867                 p_avi_demux->p_info_audio = p_avi_demux->pp_info[i];
1868                 p_avi_demux->p_info_audio->b_selected = 1;
1869                 break;
1870             }
1871         }
1872     }
1873     /* by default video is master for resync audio (after a seek .. ) */
1874     if( p_avi_demux->p_info_video )
1875     {
1876         p_info_master = p_avi_demux->p_info_video;
1877         p_info_slave  = p_avi_demux->p_info_audio;
1878     }
1879     else
1880     {
1881         p_info_master = p_avi_demux->p_info_audio;
1882         p_info_slave  = NULL;
1883     }
1884     
1885     if( !p_info_master ) 
1886     {
1887         msg_Err( p_input, "no stream selected" );
1888         return( -1 );
1889     }
1890
1891     /* check for signal from interface */
1892     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1893     { 
1894         /* we can supposed that is a seek */
1895         /* first wait for empty buffer, arbitrary time */
1896         msleep( DEFAULT_PTS_DELAY );
1897         /* then try to realign in stream */
1898         if( !AVI_ReAlign( p_input, p_info_master ) )
1899         {
1900             return( 0 ); /* assume EOF */
1901         }
1902         AVI_SynchroReInit( p_input ); 
1903     }
1904
1905     /* manage rate, if not default: skeep audio */
1906     vlc_mutex_lock( &p_input->stream.stream_lock );
1907     if( p_input->stream.control.i_rate != p_avi_demux->i_rate )
1908     {
1909         if( p_avi_demux->p_info_audio)
1910         {
1911              p_avi_demux->p_info_audio->b_selected = 1;
1912         }
1913         p_avi_demux->i_rate = p_input->stream.control.i_rate;
1914     }
1915     vlc_mutex_unlock( &p_input->stream.stream_lock );    
1916     if( p_avi_demux->i_rate != DEFAULT_RATE )
1917     {
1918         p_info_slave = NULL;
1919     }
1920  
1921     /* take care of newly selected audio ES */
1922     if( p_info_master->b_selected )
1923     {
1924         p_info_master->b_selected = 0;
1925         AVI_SynchroReInit( p_input ); 
1926     }
1927     if( ( p_info_slave )&&( p_info_slave->b_selected ) )
1928     {
1929         p_info_slave->b_selected = 0;
1930         AVI_SynchroReInit( p_input );
1931     }
1932
1933     /* wait for the good time */
1934     input_ClockManageRef( p_input,
1935                           p_input->stream.p_selected_program,
1936                           p_avi_demux->i_pcr /*- DEFAULT_PTS_DELAY / 2 */); 
1937     /* calculate pcr, time when we must read the next data */
1938     /* 9/100 kludge ->need to convert to 1/1000000 clock unit to 1/90000 */
1939     if( p_info_slave )
1940     {
1941         p_avi_demux->i_pcr =  __MIN( AVI_GetPTS( p_info_master ),
1942                                      AVI_GetPTS( p_info_slave ) ) * 9/100;
1943     }
1944     else
1945     {
1946         p_avi_demux->i_pcr =  AVI_GetPTS( p_info_master ) * 9/100;
1947     }
1948
1949     /* get video and audio frames */
1950     p_pes = AVI_GetFrameInPES( p_input,
1951                                p_info_master,
1952                                100000 ); /* 100 ms */
1953
1954
1955     if( p_info_slave )
1956     {
1957         pes_packet_t *p_pes_slave;
1958         p_pes_slave = AVI_GetFrameInPES( p_input,
1959                                          p_info_slave,
1960                                          AVI_GetPTS( p_info_master ) -
1961                                              AVI_GetPTS( p_info_slave) );
1962         AVI_DecodePES( p_input,
1963                        p_info_slave,
1964                        p_pes_slave );
1965     }
1966
1967     AVI_DecodePES( p_input,
1968                    p_info_master,
1969                    p_pes);
1970
1971     /* at the end ? */
1972     return( p_pes ? 1 : 0 );
1973
1974 }
1975