]> git.sesse.net Git - vlc/blob - plugins/avi/avi.c
74c4c8ed0a88787365111c058a70b74c7957a0c9
[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.20 2002/05/25 16:23:07 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 <videolan/vlc.h>
32
33 #include "stream_control.h"
34 #include "input_ext-intf.h"
35 #include "input_ext-dec.h"
36 #include "input_ext-plugins.h"
37
38 #include "video.h"
39
40 /*****************************************************************************
41  * Constants
42  *****************************************************************************/
43
44 /*****************************************************************************
45  * Local prototypes
46  *****************************************************************************/
47 static void input_getfunctions( function_list_t * p_function_list );
48 static int  AVIDemux         ( struct input_thread_s * );
49 static int  AVIInit          ( struct input_thread_s * );
50 static void AVIEnd           ( struct input_thread_s * );
51
52 /*****************************************************************************
53  * Build configuration tree.
54  *****************************************************************************/
55 MODULE_CONFIG_START
56 MODULE_CONFIG_STOP
57
58 MODULE_INIT_START
59     SET_DESCRIPTION( "RIFF-AVI Stream input" )
60     ADD_CAPABILITY( DEMUX, 150 )
61     ADD_SHORTCUT( "avi" )
62 MODULE_INIT_STOP
63
64 MODULE_ACTIVATE_START
65     input_getfunctions( &p_module->p_functions->demux );
66 MODULE_ACTIVATE_STOP
67
68 MODULE_DEACTIVATE_START
69 MODULE_DEACTIVATE_STOP
70
71 /*****************************************************************************
72  * Definition of structures and libraries for this plugins 
73  *****************************************************************************/
74 #include "libLE.c"
75 #include "libioRIFF.c"
76 #include "avi.h"
77
78 /*****************************************************************************
79  * Functions exported as capabilities. They are declared as static so that
80  * we don't pollute the namespace too much.
81  *****************************************************************************/
82 static void input_getfunctions( function_list_t * p_function_list )
83 {
84 #define input p_function_list->functions.demux
85     input.pf_init             = AVIInit;
86     input.pf_end              = AVIEnd;
87     input.pf_demux            = AVIDemux;
88     input.pf_rewind           = NULL;
89 #undef input
90 }
91
92 /********************************************************************/
93
94
95 static void __AVIFreeDemuxData( input_thread_t *p_input )
96 {
97     int i;
98     demux_data_avi_file_t *p_avi_demux;
99     p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data  ; 
100     
101     if( p_avi_demux->p_riff != NULL ) 
102             RIFF_DeleteChunk( p_input, p_avi_demux->p_riff );
103     if( p_avi_demux->p_hdrl != NULL ) 
104             RIFF_DeleteChunk( p_input, p_avi_demux->p_hdrl );
105     if( p_avi_demux->p_movi != NULL ) 
106             RIFF_DeleteChunk( p_input, p_avi_demux->p_movi );
107     if( p_avi_demux->p_idx1 != NULL ) 
108             RIFF_DeleteChunk( p_input, p_avi_demux->p_idx1 );
109     if( p_avi_demux->pp_info != NULL )
110     {
111         for( i = 0; i < p_avi_demux->i_streams; i++ )
112         {
113             if( p_avi_demux->pp_info[i] != NULL ) 
114             {
115                 if( p_avi_demux->pp_info[i]->p_index != NULL )
116                 {
117                       free( p_avi_demux->pp_info[i]->p_index );
118                 }
119                 free( p_avi_demux->pp_info[i] ); 
120             }
121         }
122          free( p_avi_demux->pp_info );
123     }
124 }
125
126 static void __AVI_Parse_avih( MainAVIHeader_t *p_avih, byte_t *p_buff )
127 {
128     p_avih->i_microsecperframe = __GetDoubleWordLittleEndianFromBuff( p_buff );
129     p_avih->i_maxbytespersec = __GetDoubleWordLittleEndianFromBuff( p_buff + 4);
130     p_avih->i_reserved1 = __GetDoubleWordLittleEndianFromBuff( p_buff + 8);
131     p_avih->i_flags = __GetDoubleWordLittleEndianFromBuff( p_buff + 12);
132     p_avih->i_totalframes = __GetDoubleWordLittleEndianFromBuff( p_buff + 16);
133     p_avih->i_initialframes = __GetDoubleWordLittleEndianFromBuff( p_buff + 20);
134     p_avih->i_streams = __GetDoubleWordLittleEndianFromBuff( p_buff + 24);
135     p_avih->i_suggestedbuffersize = 
136                         __GetDoubleWordLittleEndianFromBuff( p_buff + 28);
137     p_avih->i_width = __GetDoubleWordLittleEndianFromBuff( p_buff + 32 );
138     p_avih->i_height = __GetDoubleWordLittleEndianFromBuff( p_buff + 36 );
139     p_avih->i_scale = __GetDoubleWordLittleEndianFromBuff( p_buff + 40 );
140     p_avih->i_rate = __GetDoubleWordLittleEndianFromBuff( p_buff + 44 );
141     p_avih->i_start = __GetDoubleWordLittleEndianFromBuff( p_buff + 48);
142     p_avih->i_length = __GetDoubleWordLittleEndianFromBuff( p_buff + 52);
143 }
144
145 static void __AVI_Parse_Header( AVIStreamHeader_t *p_strh, byte_t *p_buff )
146 {
147     p_strh->i_type = __GetDoubleWordLittleEndianFromBuff( p_buff );
148     p_strh->i_handler = __GetDoubleWordLittleEndianFromBuff( p_buff + 4 );
149     p_strh->i_flags = __GetDoubleWordLittleEndianFromBuff( p_buff + 8 );
150     p_strh->i_reserved1 = __GetDoubleWordLittleEndianFromBuff( p_buff + 12);
151     p_strh->i_initialframes = __GetDoubleWordLittleEndianFromBuff( p_buff + 16);
152     p_strh->i_scale = __GetDoubleWordLittleEndianFromBuff( p_buff + 20);
153     p_strh->i_rate = __GetDoubleWordLittleEndianFromBuff( p_buff + 24);
154     p_strh->i_start = __GetDoubleWordLittleEndianFromBuff( p_buff + 28);
155     p_strh->i_length = __GetDoubleWordLittleEndianFromBuff( p_buff + 32);
156     p_strh->i_suggestedbuffersize = 
157                         __GetDoubleWordLittleEndianFromBuff( p_buff + 36);
158     p_strh->i_quality = __GetDoubleWordLittleEndianFromBuff( p_buff + 40);
159     p_strh->i_samplesize = __GetDoubleWordLittleEndianFromBuff( p_buff + 44);
160 }
161
162 int avi_ParseBitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
163 {
164     h->i_size          = __GetDoubleWordLittleEndianFromBuff( p_data );
165     h->i_width         = __GetDoubleWordLittleEndianFromBuff( p_data + 4 );
166     h->i_height        = __GetDoubleWordLittleEndianFromBuff( p_data + 8 );
167     h->i_planes        = __GetWordLittleEndianFromBuff( p_data + 12 );
168     h->i_bitcount      = __GetWordLittleEndianFromBuff( p_data + 14 );
169     h->i_compression   = __GetDoubleWordLittleEndianFromBuff( p_data + 16 );
170     h->i_sizeimage     = __GetDoubleWordLittleEndianFromBuff( p_data + 20 );
171     h->i_xpelspermeter = __GetDoubleWordLittleEndianFromBuff( p_data + 24 );
172     h->i_ypelspermeter = __GetDoubleWordLittleEndianFromBuff( p_data + 28 );
173     h->i_clrused       = __GetDoubleWordLittleEndianFromBuff( p_data + 32 );
174     h->i_clrimportant  = __GetDoubleWordLittleEndianFromBuff( p_data + 36 );
175     return( 0 );
176 }
177
178 int avi_ParseWaveFormatEx( waveformatex_t *h, byte_t *p_data )
179 {
180     h->i_formattag     = __GetWordLittleEndianFromBuff( p_data );
181     h->i_channels      = __GetWordLittleEndianFromBuff( p_data + 2 );
182     h->i_samplespersec = __GetDoubleWordLittleEndianFromBuff( p_data + 4 );
183     h->i_avgbytespersec= __GetDoubleWordLittleEndianFromBuff( p_data + 8 );
184     h->i_blockalign    = __GetWordLittleEndianFromBuff( p_data + 12 );
185     h->i_bitspersample = __GetWordLittleEndianFromBuff( p_data + 14 );
186     h->i_size          = __GetWordLittleEndianFromBuff( p_data + 16 );
187     return( 0 );
188 }
189
190 static inline int __AVIGetESTypeFromTwoCC( u16 i_type )
191 {
192     switch( i_type )
193     {
194         case( TWOCC_wb ):
195             return( AUDIO_ES );
196          case( TWOCC_dc ):
197          case( TWOCC_db ):
198             return( VIDEO_ES );
199     }
200     return( UNKNOWN_ES );
201 }
202
203
204 static int __AVI_ParseStreamHeader( u32 i_id, int *i_number, u16 *i_type )
205 {
206     int c1,c2,c3,c4;
207
208     c1 = ( i_id ) & 0xFF;
209     c2 = ( i_id >>  8 ) & 0xFF;
210     c3 = ( i_id >> 16 ) & 0xFF;
211     c4 = ( i_id >> 24 ) & 0xFF;
212
213     if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
214     {
215         return( -1 );
216     }
217     *i_number = (c1 - '0') * 10 + (c2 - '0' );
218     *i_type = ( c4 << 8) + c3;
219     return( 0 );
220 }   
221
222 static void __AVI_AddEntryIndex( AVIStreamInfo_t *p_info,
223                                  AVIIndexEntry_t *p_index)
224 {
225     AVIIndexEntry_t *p_tmp;
226     if( p_info->p_index == NULL )
227     {
228         p_info->i_idxmax = 16384;
229         p_info->i_idxnb = 0;
230         p_info->p_index = calloc( p_info->i_idxmax, 
231                                   sizeof( AVIIndexEntry_t ) );
232         if( p_info->p_index == NULL ) {return;}
233     }
234     if( p_info->i_idxnb >= p_info->i_idxmax )
235     {
236         p_info->i_idxmax += 16384;
237         p_tmp = realloc( (void*)p_info->p_index,
238                            p_info->i_idxmax * 
239                            sizeof( AVIIndexEntry_t ) );
240         if( p_tmp == NULL ) 
241         { 
242             p_info->i_idxmax -= 16384;
243             return; 
244         }
245         p_info->p_index = p_tmp;
246     }
247     /* calculate cumulate length */
248     if( p_info->i_idxnb > 0 )
249     {
250         p_index->i_lengthtotal = p_info->p_index[p_info->i_idxnb-1].i_length +
251                 p_info->p_index[p_info->i_idxnb-1].i_lengthtotal;
252     }
253     else
254     {
255         p_index->i_lengthtotal = 0;
256     }
257
258     p_info->p_index[p_info->i_idxnb] = *p_index;
259     p_info->i_idxnb++;
260 }
261
262 static void __AVI_GetIndex( input_thread_t *p_input )
263 {
264     AVIIndexEntry_t index;
265     byte_t          *p_buff;
266     riffchunk_t     *p_idx1;
267     int             i_read;
268     int             i;
269     int             i_number;
270     u16             i_type;
271     int             i_totalentry = 0;
272     demux_data_avi_file_t *p_avi_demux =
273                         (demux_data_avi_file_t*)p_input->p_demux_data  ;    
274
275     if( RIFF_FindAndGotoDataChunk( p_input,
276                                    p_avi_demux->p_riff, 
277                                    &p_idx1, 
278                                    FOURCC_idx1)!=0 )
279     {
280         intf_WarnMsg( 1, "input init: cannot find index" );
281         RIFF_GoToChunk( p_input, p_avi_demux->p_hdrl );        
282         return;
283     }
284     p_avi_demux->p_idx1 = p_idx1;
285     intf_WarnMsg( 1, "input init: loading index" ); 
286     for(;;)
287     {
288         i_read = __MIN( 16*1024, p_idx1->i_size - i_totalentry *16);
289         if( ((i_read = input_Peek( p_input, &p_buff, i_read )) < 16 )
290               ||( i_totalentry *16 >= p_idx1->i_size ) )
291         {
292             intf_WarnMsg( 1,"input info: read %d idx entries", i_totalentry );
293             return;
294         }
295         i_read /= 16 ;
296         for( i = 0; i < i_read; i++ )
297         {
298             byte_t  *p_peek = p_buff + i * 16;
299             i_totalentry++;
300             index.i_id = __GetDoubleWordLittleEndianFromBuff( p_peek );
301             index.i_flags = __GetDoubleWordLittleEndianFromBuff( p_peek+4);
302             index.i_pos = __GetDoubleWordLittleEndianFromBuff( p_peek+8);
303             index.i_length = __GetDoubleWordLittleEndianFromBuff(p_peek+12);
304             
305             if( (__AVI_ParseStreamHeader( index.i_id, &i_number, &i_type ) == 0)
306              &&(i_number <  p_avi_demux->i_streams )
307              &&(p_avi_demux->pp_info[i_number]->i_cat == 
308                      __AVIGetESTypeFromTwoCC( i_type ))) 
309             {
310                 __AVI_AddEntryIndex( p_avi_demux->pp_info[i_number],
311                                      &index );
312             }
313         }
314         __RIFF_SkipBytes( p_input, 16 * i_read );
315     }
316
317 }
318 static int __AVI_SeekToChunk( input_thread_t *p_input, AVIStreamInfo_t *p_info )
319 {
320     if( (p_info->p_index )&&(p_info->i_idxposc < p_info->i_idxnb) )
321     {
322         p_input->pf_seek( p_input, 
323                           (off_t)p_info->p_index[p_info->i_idxposc].i_pos);
324         input_AccessReinit( p_input );
325         return( 0 );
326     }
327     /* no index can't arrive but ...*/
328     intf_WarnMsg( 1, "input error: can't seek");
329     return( -1 );
330 }
331
332
333 /* XXX call after get p_movi */
334 static void __AVI_UpdateIndexOffset( input_thread_t *p_input )
335 {
336     int i_stream;
337     int b_start = 1;/* if index pos is based on start of file or not (p_movi) */
338     demux_data_avi_file_t *p_avi_demux =
339                         (demux_data_avi_file_t*)p_input->p_demux_data;
340
341 /* FIXME some work to do :
342         * test in the ile if it's true, if not do a RIFF_Find...
343 */
344 #define p_info p_avi_demux->pp_info[i_stream]
345     for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
346     {
347         if( ( p_info->p_index )
348            && ( p_info->p_index[0].i_pos < p_avi_demux->p_movi->i_pos + 8 ))
349         {
350             b_start = 0;
351             break;
352         }
353     }
354     if( !b_start )
355     {
356         for( i_stream = 0; i_stream < p_avi_demux->i_streams; i_stream++ )
357         {
358             int i;
359             if( p_info->p_index )
360             {
361                 for( i = 0; i < p_info->i_idxnb; i++ )
362                 {
363                     p_info->p_index[i].i_pos += 
364                                                 p_avi_demux->p_movi->i_pos + 8;
365                 }
366             }
367         }
368     }
369 #undef p_info
370 }
371
372 static int __AVI_AudioGetType( u32 i_type )
373 {
374     switch( i_type )
375     {
376 /*        case( WAVE_FORMAT_PCM ):
377             return( WAVE_AUDIO_ES ); */
378         case( WAVE_FORMAT_AC3 ):
379             return( AC3_AUDIO_ES );
380         case( WAVE_FORMAT_MPEG):
381         case( WAVE_FORMAT_MPEGLAYER3):
382             return( MPEG2_AUDIO_ES ); /* 2 for mpeg-2 layer 1 2 ou 3 */
383         default:
384             return( 0 );
385     }
386 }
387
388 static int __AVI_VideoGetType( u32 i_type )
389 {
390     switch( i_type )
391     {
392 /* FIXME FIXME :  what are the correct tag for msmpeg4 v1 */
393         case(  FOURCC_MPG4  ):
394         case(  FOURCC_mpg4  ):
395         case(  FOURCC_DIV2  ):
396         case(  FOURCC_div2  ):
397         case(  FOURCC_MP42  ):
398         case(  FOURCC_mp42  ):
399              return( MSMPEG4v2_VIDEO_ES );
400            
401         case(  FOURCC_MPG3  ):
402         case(  FOURCC_mpg3  ):
403         case(  FOURCC_div3  ):
404         case(  FOURCC_MP43  ):
405         case(  FOURCC_mp43  ):
406         case(  FOURCC_DIV3  ):
407         case(  FOURCC_DIV4  ):
408         case(  FOURCC_div4  ):
409         case(  FOURCC_DIV5  ):
410         case(  FOURCC_div5  ):
411         case(  FOURCC_DIV6  ):
412         case(  FOURCC_div6  ):
413         case(  FOURCC_AP41  ):
414         case(  FOURCC_3IV1  ):
415             return( MSMPEG4v3_VIDEO_ES );
416
417
418         case(  FOURCC_DIVX  ):
419         case(  FOURCC_divx  ):
420         case(  FOURCC_DIV1  ):
421         case(  FOURCC_div1  ):
422         case(  FOURCC_MP4S  ):
423         case(  FOURCC_mp4s  ):
424         case(  FOURCC_M4S2  ):
425         case(  FOURCC_m4s2  ):
426         case(  FOURCC_xvid  ):
427         case(  FOURCC_XVID  ):
428         case(  FOURCC_XviD  ):
429         case(  FOURCC_DX50  ):
430         case(  FOURCC_mp4v  ):
431         case(  FOURCC_4     ):
432             return( MPEG4_VIDEO_ES );
433
434         default:
435             return( 0 );
436     }
437 }
438
439 /*****************************************************************************
440  * AVIInit: check file and initializes AVI structures
441  *****************************************************************************/
442 static int AVIInit( input_thread_t *p_input )
443 {
444     riffchunk_t *p_riff,*p_hdrl,*p_movi;
445     riffchunk_t *p_avih;
446     riffchunk_t *p_strl,*p_strh,*p_strf;
447     demux_data_avi_file_t *p_avi_demux;
448     es_descriptor_t *p_es = NULL; /* for not warning */
449
450     int i;
451
452     /* we need to seek to be able to readcorrectly */
453     if( !p_input->stream.b_seekable ) 
454     {
455         intf_WarnMsg( 2,"input: RIFF-AVI plug-in discarded (no seekable)" );
456         return( -1 );
457     }
458     p_input->p_demux_data = 
459                 p_avi_demux = malloc( sizeof(demux_data_avi_file_t) );
460     if( p_avi_demux == NULL )
461     {
462         intf_ErrMsg( "input error: not enough memory" );
463         return( -1 );
464     }
465     memset( p_avi_demux, 0, sizeof( demux_data_avi_file_t ) );
466     p_avi_demux->i_rate = DEFAULT_RATE;
467     /* FIXME I don't know what it's do, copied from ESInit */
468     /* Initialize access plug-in structures. */
469     if( p_input->i_mtu == 0 )
470     {
471         /* Improve speed. */
472         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
473     }
474
475     if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 )    
476     {
477         __AVIFreeDemuxData( p_input );
478         intf_WarnMsg( 2,"input: RIFF-AVI plug-in discarded (avi_file)" );
479         return( -1 );
480     }
481     p_avi_demux->p_riff = p_riff;
482
483     if ( RIFF_DescendChunk(p_input) != 0 )
484     {
485         __AVIFreeDemuxData( p_input );
486         intf_ErrMsg( "input error: cannot look for subchunk (avi_file)" );
487         return ( -1 );
488     }
489
490     /* it's a riff-avi file, so search for LIST-hdrl */
491     if( RIFF_FindListChunk(p_input ,&p_hdrl,p_riff, FOURCC_hdrl) != 0 )
492     {
493         __AVIFreeDemuxData( p_input );
494         intf_ErrMsg( "input error: cannot find \"LIST-hdrl\" (avi_file)" );
495         return( -1 );
496     }
497     p_avi_demux->p_hdrl = p_hdrl;
498
499     if( RIFF_DescendChunk(p_input) != 0 )
500     {
501         __AVIFreeDemuxData( p_input );
502         intf_ErrMsg( "input error: cannot look for subchunk (avi_file)" );
503         return ( -1 );
504     }
505     /* in  LIST-hdrl search avih */
506     if( RIFF_FindAndLoadChunk( p_input, p_hdrl, 
507                                     &p_avih, FOURCC_avih ) != 0 )
508     {
509         __AVIFreeDemuxData( p_input );
510         intf_ErrMsg( "input error: cannot find \"avih\" chunk (avi_file)" );
511         return( -1 );
512     }
513     __AVI_Parse_avih( &p_avi_demux->avih, p_avih->p_data->p_payload_start );
514     RIFF_DeleteChunk( p_input, p_avih );
515     
516     if( p_avi_demux->avih.i_streams == 0 )  
517     /* no stream found, perhaps it would be cool to find it */
518     {
519         __AVIFreeDemuxData( p_input );
520         intf_ErrMsg( "input error: no defined stream !" );
521         return( -1 );
522     }
523
524     /*  create one program */
525     vlc_mutex_lock( &p_input->stream.stream_lock ); 
526     if( input_InitStream( p_input, 0 ) == -1)
527     {
528         vlc_mutex_unlock( &p_input->stream.stream_lock );
529         __AVIFreeDemuxData( p_input );
530         intf_ErrMsg( "input error: cannot init stream" );
531         return( -1 );
532     }
533     if( input_AddProgram( p_input, 0, 0) == NULL )
534     {
535         vlc_mutex_unlock( &p_input->stream.stream_lock );
536         __AVIFreeDemuxData( p_input );
537         intf_ErrMsg( "input error: cannot add program" );
538         return( -1 );
539     }
540     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
541     p_input->stream.p_new_program = p_input->stream.pp_programs[0] ;
542     p_input->stream.i_mux_rate = p_avi_demux->avih.i_maxbytespersec / 50;
543     vlc_mutex_unlock( &p_input->stream.stream_lock ); 
544
545     /* now read info on each stream and create ES */
546     p_avi_demux->i_streams = p_avi_demux->avih.i_streams;
547     
548     p_avi_demux->pp_info = calloc( p_avi_demux->i_streams, 
549                                     sizeof( AVIStreamInfo_t* ) );
550     memset( p_avi_demux->pp_info, 0, 
551                         sizeof( AVIStreamInfo_t* ) * p_avi_demux->i_streams );
552
553     for( i = 0 ; i < p_avi_demux->i_streams; i++ )
554     {
555 #define p_info  p_avi_demux->pp_info[i]
556         p_info = malloc( sizeof(AVIStreamInfo_t ) );
557         memset( p_info, 0, sizeof( AVIStreamInfo_t ) );        
558
559         if( ( RIFF_FindListChunk(p_input,
560                                 &p_strl,p_hdrl, FOURCC_strl) != 0 )
561                 ||( RIFF_DescendChunk(p_input) != 0 ))
562         {
563             __AVIFreeDemuxData( p_input );
564             intf_ErrMsg( "input error: cannot find \"LIST-strl\" (avi_file)" );
565             return( -1 );
566         }
567         
568         /* in  LIST-strl search strh */
569         if( RIFF_FindAndLoadChunk( p_input, p_hdrl, 
570                                 &p_strh, FOURCC_strh ) != 0 )
571         {
572             RIFF_DeleteChunk( p_input, p_strl );
573             __AVIFreeDemuxData( p_input );
574             intf_ErrMsg( "input error: cannot find \"strh\" (avi_file)" );
575             return( -1 );
576         }
577         __AVI_Parse_Header( &p_info->header,
578                             p_strh->p_data->p_payload_start);
579         RIFF_DeleteChunk( p_input, p_strh );      
580
581         /* in  LIST-strl search strf */
582         if( RIFF_FindAndLoadChunk( p_input, p_hdrl, 
583                                 &p_strf, FOURCC_strf ) != 0 )
584         {
585             RIFF_DeleteChunk( p_input, p_strl );
586             __AVIFreeDemuxData( p_input );
587             intf_ErrMsg( "input error: cannot find \"strf\" (avi_file)" );
588             return( -1 );
589         }
590         /* we don't get strd, it's useless for divx,opendivx,mepgaudio */ 
591         if( RIFF_AscendChunk(p_input, p_strl) != 0 )
592         {
593             RIFF_DeleteChunk( p_input, p_strf );
594             RIFF_DeleteChunk( p_input, p_strl );
595             __AVIFreeDemuxData( p_input );
596             intf_ErrMsg( "input error: cannot go out (\"strl\") (avi_file)" );
597             return( -1 );
598         }
599
600         /* add one ES */
601         vlc_mutex_lock( &p_input->stream.stream_lock );
602         p_es = input_AddES( p_input,
603                             p_input->stream.p_selected_program, 1+i,
604                             p_strf->i_size );
605         vlc_mutex_unlock( &p_input->stream.stream_lock );
606         p_es->i_stream_id =i; /* XXX: i don't use it */ 
607        
608         switch( p_info->header.i_type )
609         {
610             case( FOURCC_auds ):
611                 p_es->i_cat = AUDIO_ES;
612                 avi_ParseWaveFormatEx( &p_info->audio_format,
613                                    p_strf->p_data->p_payload_start ); 
614                 p_es->b_audio = 1;
615                 p_es->i_type = 
616                     __AVI_AudioGetType( p_info->audio_format.i_formattag );
617                 if( p_es->i_type == 0 )
618                 {
619                     intf_ErrMsg( "input error: stream(%d,0x%x) not supported",
620                                     i,
621                                     p_info->audio_format.i_formattag );
622                     p_es->i_cat = UNKNOWN_ES;
623                 }
624                 break;
625                 
626             case( FOURCC_vids ):
627                 p_es->i_cat = VIDEO_ES;
628                 avi_ParseBitMapInfoHeader( &p_info->video_format,
629                                    p_strf->p_data->p_payload_start ); 
630                 p_es->b_audio = 0;
631                 p_es->i_type = 
632                     __AVI_VideoGetType( p_info->video_format.i_compression );
633                 if( p_es->i_type == 0 )
634                 {
635                     intf_ErrMsg( "input error: stream(%d,%4.4s) not supported",
636                                i,
637                                (char*)&p_info->video_format.i_compression);
638                     p_es->i_cat = UNKNOWN_ES;
639                 }
640                 break;
641             default:
642                 intf_ErrMsg( "input error: unknown stream(%d) type",
643                             i );
644                 p_es->i_cat = UNKNOWN_ES;
645                 break;
646         }
647         p_info->p_es = p_es;
648         p_info->i_cat = p_es->i_cat;
649         /* We copy strf for decoder in p_es->p_demux_data */
650         memcpy( p_es->p_demux_data, 
651                 p_strf->p_data->p_payload_start,
652                 p_strf->i_size );
653         RIFF_DeleteChunk( p_input, p_strf );
654         RIFF_DeleteChunk( p_input, p_strl );
655 #undef p_info           
656     }
657
658
659
660     /* go out of p_hdrl */
661     if( RIFF_AscendChunk(p_input, p_hdrl) != 0)
662     {
663         __AVIFreeDemuxData( p_input );
664         intf_ErrMsg( "input error: cannot go out (\"hdrl\") (avi_file)" );
665         return( -1 );
666     }
667
668     /* go to movi chunk to get it*/
669     if( RIFF_FindListChunk(p_input ,&p_movi,p_riff, FOURCC_movi) != 0 )
670     {
671         intf_ErrMsg( "input error: cannot find \"LIST-movi\" (avi_file)" );
672         __AVIFreeDemuxData( p_input );
673         return( -1 );
674     }
675     p_avi_demux->p_movi = p_movi;
676     
677     /* get index  XXX need to have p_movi */
678     if( (p_avi_demux->avih.i_flags&AVIF_HASINDEX) != 0 )
679     {
680         /* get index */
681         __AVI_GetIndex( p_input ); 
682         /* try to get i_idxoffset for each stream  */
683         __AVI_UpdateIndexOffset( p_input );
684     }
685     else
686     {
687         intf_WarnMsg( 1, "input init: no index !" );
688     }
689
690     
691     /* we verify that each stream have at least one entry or create it */
692     for( i = 0; i < p_avi_demux->i_streams ; i++ )
693     {
694         AVIIndexEntry_t index;
695         riffchunk_t     *p_chunk;
696 #define p_info  p_avi_demux->pp_info[i]
697         if( p_info->p_index == NULL )
698         {
699             RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
700             if( RIFF_DescendChunk(p_input) != 0 ) { continue; }
701             p_chunk = NULL;
702             switch( p_info->i_cat ) 
703             {
704                 case( AUDIO_ES ):
705                     if( RIFF_FindChunk( p_input, 
706                                MAKEFOURCC('0'+i/10, '0'+i%10,'w','b' ), 
707                                              p_movi ) == 0)
708                     {
709                        p_chunk = RIFF_ReadChunk( p_input );
710                     }
711                     break;
712                     
713                 case( VIDEO_ES ):
714                     if( (RIFF_FindChunk( p_input, 
715                                     MAKEFOURCC('0'+i/10, '0'+i%10,'d','c' ),
716                                             p_movi ) == 0) )
717                     {
718                         p_chunk = RIFF_ReadChunk( p_input ); 
719                     }
720                     else
721                     {
722                         RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
723                         if( RIFF_DescendChunk(p_input) != 0 ) { continue; }
724                         if( (RIFF_FindChunk( p_input,
725                                         MAKEFOURCC('0'+i/10, '0'+i%10,'d','b' ),
726                                             p_movi ) == 0) )
727                         {
728                             p_chunk = RIFF_ReadChunk( p_input );
729                         }
730                     }
731                     break;
732             }
733             if( p_chunk != NULL )
734             {
735                 index.i_id = p_chunk->i_id;
736                 index.i_flags = AVIIF_KEYFRAME;
737                 index.i_pos = p_chunk->i_pos;
738                 index.i_length = p_chunk->i_size;
739                 __AVI_AddEntryIndex( p_info, &index );
740                 intf_WarnMsg( 3, "input init: add index entry (%4.4s) (%d)", 
741                                  (char*)&p_chunk->i_id,
742                                  i); 
743                
744             }
745         }
746 #undef p_info
747     }
748
749     /* to make sure to go the begining because unless demux will see a seek */
750     RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
751     if( RIFF_DescendChunk( p_input ) != 0 )
752     {
753         __AVIFreeDemuxData( p_input );
754         intf_ErrMsg( "input error: cannot go in (\"movi\") (avi_file)" );
755         return( -1 );
756     }
757
758     /* print informations on streams */
759     intf_Msg( "input init: AVIH: %d stream, flags %s%s%s%s%s%s ", 
760             p_avi_demux->i_streams,
761             p_avi_demux->avih.i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
762             p_avi_demux->avih.i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
763             p_avi_demux->avih.i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
764             p_avi_demux->avih.i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"",
765             p_avi_demux->avih.i_flags&AVIF_WASCAPTUREFILE?" CAPTUREFILE":"",
766             p_avi_demux->avih.i_flags&AVIF_COPYRIGHTED?" COPYRIGHTED":"" );
767
768     for( i = 0; i < p_avi_demux->i_streams; i++ )
769     {
770 #define p_info  p_avi_demux->pp_info[i]
771         switch( p_info->p_es->i_cat )
772         {
773             case( VIDEO_ES ):
774                 intf_Msg("input init: video(%4.4s) %dx%d %dbpp %ffps (size %d)",
775                         (char*)&p_info->video_format.i_compression,
776                         p_info->video_format.i_width,
777                         p_info->video_format.i_height,
778                         p_info->video_format.i_bitcount,
779                         (float)p_info->header.i_rate /
780                             (float)p_info->header.i_scale,
781                         p_info->header.i_samplesize );
782                 if( (p_avi_demux->p_info_video == NULL) ) 
783                 {
784                     p_avi_demux->p_info_video = p_info;
785                }
786                 break;
787
788             case( AUDIO_ES ):
789                 intf_Msg( "input init: audio(0x%x) %d channels %dHz %dbits %ffps (size %d)",
790                         p_info->audio_format.i_formattag,
791                         p_info->audio_format.i_channels,
792                         p_info->audio_format.i_samplespersec,
793                         p_info->audio_format.i_bitspersample,
794                         (float)p_info->header.i_rate /
795                             (float)p_info->header.i_scale,
796                         p_info->header.i_samplesize );
797                 if( (p_avi_demux->p_info_audio == NULL) ) 
798                 {
799                     p_avi_demux->p_info_audio = p_info;
800                 }
801                 break;
802             case( UNKNOWN_ES ):
803                 intf_Msg( "input init: unhanled stream %d", i );
804         }
805 #undef p_info    
806     }
807
808     /* we select the first audio and video ES */
809     vlc_mutex_lock( &p_input->stream.stream_lock );
810     if( p_avi_demux->p_info_video != NULL ) 
811     {
812         input_SelectES( p_input, p_avi_demux->p_info_video->p_es );
813         /*  it seems that it's useless to select es because there are selected 
814          *  by the interface but i'm not sure of that */
815     }
816     else
817     {
818         intf_Msg( "input error: no video stream found !" );
819     }
820     if( p_avi_demux->p_info_audio != NULL ) 
821     {
822         input_SelectES( p_input, p_avi_demux->p_info_audio->p_es );
823     }
824     else
825     {
826         intf_Msg( "input init: no audio stream found !" );
827     }
828     p_input->stream.p_selected_program->b_is_ok = 1;
829     vlc_mutex_unlock( &p_input->stream.stream_lock );
830     
831     return( 0 );
832 }
833
834
835 /*****************************************************************************
836  * AVIEnd: frees unused data
837  *****************************************************************************/
838 static void AVIEnd( input_thread_t *p_input )
839 {   
840     __AVIFreeDemuxData( p_input ); 
841     return;
842 }
843
844
845 static mtime_t AVI_GetPTS( AVIStreamInfo_t *p_info )
846 {
847     /* p_info->p_index[p_info->i_idxposc] need to be valid !! */
848     /* be careful to  *1000000 before round  ! */
849     if( p_info->header.i_samplesize != 0 )
850     {
851         return( (mtime_t)( (double)1000000.0 *
852                    (double)(p_info->p_index[p_info->i_idxposc].i_lengthtotal +
853                              p_info->i_idxposb )*
854                     (double)p_info->header.i_scale /
855                     (double)p_info->header.i_rate /
856                     (double)p_info->header.i_samplesize ) );
857     }
858     else
859     {
860         return( (mtime_t)( (double)1000000.0 *
861                     (double)(p_info->i_idxposc ) *
862                     (double)p_info->header.i_scale /
863                     (double)p_info->header.i_rate) );
864     }
865 }
866
867
868
869 static int __AVI_NextIndexEntry( input_thread_t *p_input, 
870                                   AVIStreamInfo_t *p_info )
871 {
872     AVIIndexEntry_t index;
873     riffchunk_t     *p_chunk;
874     AVIStreamInfo_t *p_info_tmp;
875     int             i;
876     int             i_idxposc;
877     int             b_inc = 0;
878     demux_data_avi_file_t *p_avi_demux =
879                         (demux_data_avi_file_t*)p_input->p_demux_data;
880
881     p_info->i_idxposc++;
882
883     if( p_info->i_idxposc < p_info->i_idxnb )
884     {
885         return( 0 );
886     }
887     if( p_info->i_idxposc > p_info->i_idxnb )
888     {
889         return( -1 );
890     }
891     p_info->i_idxposc--;
892     
893     /* create entry on the fly */
894     /* search for the more advance stream and parse from it for all streams*/
895     p_info_tmp = p_info;
896     for( i = 0; i < p_avi_demux->i_streams; i++ )
897     {
898 #define p_info_i p_avi_demux->pp_info[i]
899         if( ( p_info_i->p_index )
900             && ( p_info_i->p_index[p_info_i->i_idxnb - 1].i_pos >
901             p_info_tmp->p_index[p_info_tmp->i_idxnb - 1].i_pos ) )
902         {
903             p_info_tmp = p_info_i;
904         }
905 #undef  p_info_i
906     }
907        
908     /* go to last defined entry */
909     i_idxposc = p_info_tmp->i_idxposc; /* save p_info_tmp->i_idxposc */
910     p_info_tmp->i_idxposc = p_info_tmp->i_idxnb - 1;
911     __AVI_SeekToChunk( p_input, p_info_tmp );
912     p_info_tmp->i_idxposc = i_idxposc;
913
914     if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
915     {
916         p_info->i_idxposc++;
917         return( -1 );
918     }
919
920     /* save idxpos of p_info */
921     /* now parse for all stream and stop when reach next chunk for p_info */
922     for( i = 0; (i < 15)||(!b_inc); i++)
923     {
924         int i_number;
925         u16 i_type;
926         if( (p_chunk = RIFF_ReadChunk( p_input )) == NULL )
927         {
928             p_info->i_idxposc++;
929             return( b_inc == 1 ? 0 : -1 );
930         }
931
932         index.i_id = p_chunk->i_id;
933         index.i_flags = AVIIF_KEYFRAME;
934         index.i_pos = p_chunk->i_pos;
935         index.i_length = p_chunk->i_size;
936         RIFF_DeleteChunk( p_input, p_chunk );
937 #define p_info_i    p_avi_demux->pp_info[i_number]
938        if( (__AVI_ParseStreamHeader( index.i_id, &i_number, &i_type ) == 0)
939              &&( i_number < p_avi_demux->i_streams )
940              &&( p_info_i->p_index )
941              &&( p_info_i->p_index[p_info_i->i_idxnb - 1].i_pos + 
942                      p_info_i->p_index[p_info_i->i_idxnb - 1].i_length + 8<= 
943                         index.i_pos ) 
944              &&( __AVIGetESTypeFromTwoCC( i_type ) == p_info_i->i_cat ) )
945         {
946             __AVI_AddEntryIndex( p_info_i, &index );
947             if( (p_info_i == p_info)&&(!b_inc) )
948             {
949                 b_inc = 1;
950             }
951         }
952 #undef  p_info_i
953         if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
954         {
955             p_info->i_idxposc++;
956             return( b_inc == 1 ? 0 : -1 );
957         }
958
959     } 
960
961     p_info->i_idxposc++;
962     return( 0 );
963 }
964
965 /*****************************************************************************
966  * Functions to acces streams data 
967  * Uses it, because i plane to read unseekable stream
968  * Don't work for the moment for unseekable stream 
969  *****************************************************************************/
970
971 /*      __AVI_ReadStreamChunkInPES;   load an entire chunk 
972         __AVI_ReadStreamBytesInPES;   load bytes 
973         __AVI_GoToStreamChunk;        go to chunk
974         __AVI_GoToStreamBytes;        go to bytes in the all stream  
975  not seekable file is not yet supported
976  */
977
978 static int __AVI_GoToStreamChunk( input_thread_t    *p_input, 
979                                   AVIStreamInfo_t   *p_info,
980                                   int   i_chunk )
981 {
982     u32   u32_pos;
983     off_t i_pos;
984     
985     if( !p_input->stream.b_seekable )
986     {
987         intf_ErrMsg( "input error: need the ability to seek in stream" );
988         return( -1 );
989     }
990
991     if( p_info->p_index != NULL )
992     {
993         if( i_chunk >= p_info->i_idxnb )
994         {
995             p_info->i_idxposc = p_info->i_idxnb-1;
996             while( p_info->i_idxposc < i_chunk )
997             {
998                 if( __AVI_NextIndexEntry( p_input, p_info ) != 0)
999                 {
1000                     return( -1 );
1001                 }
1002             }
1003         }
1004         else
1005         {
1006             p_info->i_idxposc = i_chunk;
1007         }
1008
1009         /* now do we have valid index for the chunk */
1010         __RIFF_TellPos( p_input, &u32_pos );
1011
1012         i_pos = (off_t)p_info->p_index[i_chunk].i_pos;
1013         if( i_pos != u32_pos )
1014         {
1015             p_input->pf_seek( p_input, i_pos );
1016             input_AccessReinit( p_input );
1017         }
1018         p_info->i_idxposb = 0;
1019         return( 0 );
1020     }
1021     else
1022     {
1023         return( -1 );
1024     }
1025 }
1026
1027 static int __AVI_GoToStreamBytes( input_thread_t    *p_input, 
1028                                   AVIStreamInfo_t   *p_info,
1029                                   int   i_byte )
1030 {
1031     u32   u32_pos;
1032     off_t i_pos;
1033
1034     if( !p_input->stream.b_seekable )
1035     {
1036         intf_ErrMsg( "input error: need the ability to seek in stream" );
1037         return( -1 );
1038     }
1039
1040     /* now do we have valid index for the chunk */
1041     if( p_info->p_index != NULL )
1042     {
1043         if( p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal +
1044             p_info->p_index[p_info->i_idxnb - 1].i_length <= i_byte)
1045         {
1046             p_info->i_idxposc = p_info->i_idxnb - 1;
1047             while( p_info->p_index[p_info->i_idxposc].i_lengthtotal +
1048                         p_info->p_index[p_info->i_idxposc].i_length <= i_byte)
1049             {
1050                 if( __AVI_NextIndexEntry( p_input, p_info ) != 0)
1051                 {
1052                     return( -1 );
1053                 }
1054             }
1055         }
1056         else
1057         {
1058             /* uses dichototmie to be fast enougth */
1059             int i_idxposc = p_info->i_idxposc;
1060             int i_idxmax  = p_info->i_idxnb;
1061             int i_idxmin  = 0;
1062             for( ;; )
1063             {
1064                 if( p_info->p_index[i_idxposc].i_lengthtotal > i_byte )
1065                 {
1066                     i_idxmax  = i_idxposc ;
1067                     i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1068                 }
1069                 else
1070                 {
1071                     if( p_info->p_index[i_idxposc].i_lengthtotal + 
1072                             p_info->p_index[i_idxposc].i_length <= i_byte)
1073                     {
1074                         i_idxmin  = i_idxposc ;
1075                         i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1076                     }
1077                     else
1078                     {
1079                         p_info->i_idxposc = i_idxposc;
1080                        break;
1081                    }
1082                 }
1083             }
1084         }
1085
1086         p_info->i_idxposb = i_byte - 
1087                        p_info->p_index[p_info->i_idxposc].i_lengthtotal;
1088         
1089         i_pos = (off_t)p_info->p_index[p_info->i_idxposc].i_pos +
1090                       p_info->i_idxposb + 8;
1091         __RIFF_TellPos( p_input, &u32_pos );
1092         if( u32_pos != i_pos )
1093         {
1094             p_input->pf_seek( p_input, i_pos );
1095             input_AccessReinit( p_input );
1096         }
1097         return( 0 );
1098     }
1099     else
1100     {
1101         return( -1 );
1102     }
1103 }
1104
1105 static pes_packet_t *__AVI_ReadStreamChunkInPES(  input_thread_t    *p_input,
1106                                                   AVIStreamInfo_t   *p_info )
1107 {
1108     pes_packet_t    *p_pes;
1109     if( p_info->i_idxposc >= p_info->i_idxnb )
1110     {
1111         return( NULL );
1112     }
1113     /*- XXX avio is sh*t sometime chunk size is broken, and 
1114       we must choose index sie */
1115     
1116     if( ( __AVI_GoToStreamChunk( p_input, p_info, p_info->i_idxposc ) != 0 )
1117          ||( RIFF_LoadChunkDataInPES( p_input, 
1118                                       &p_pes,
1119                             p_info->p_index[p_info->i_idxposc].i_length ) != 0 ) )
1120     {
1121         return( NULL );
1122     }
1123     else
1124     {
1125       __AVI_NextIndexEntry( p_input, p_info);
1126       p_info->i_idxposb = 0;
1127       return( p_pes );
1128     }
1129 }
1130
1131 static pes_packet_t *__AVI_ReadStreamBytesInPES(  input_thread_t    *p_input,
1132                                                   AVIStreamInfo_t   *p_info,
1133                                                   int i_byte )
1134 {
1135     pes_packet_t    *p_pes = NULL;
1136     data_packet_t   *p_data;
1137     int             i_read;
1138
1139     if( ( p_pes = input_NewPES( p_input->p_method_data ) ) == NULL )
1140     {
1141         return( NULL );
1142     }
1143     
1144     while( i_byte > 0 )
1145     {
1146         if( p_info->i_idxposc >= p_info->i_idxnb )
1147         {
1148             input_DeletePES( p_input->p_method_data, p_pes );
1149             return( NULL );
1150         }
1151         if( __AVI_GoToStreamBytes( p_input, p_info, 
1152                        p_info->p_index[p_info->i_idxposc].i_lengthtotal + 
1153                         p_info->i_idxposb ) != 0 )
1154         {
1155             input_DeletePES( p_input->p_method_data, p_pes );
1156             return( NULL );
1157         }
1158
1159         i_read = input_SplitBuffer(p_input, &p_data,
1160                                  __MIN( i_byte, 
1161                                  p_info->p_index[p_info->i_idxposc].i_length 
1162                                     - p_info->i_idxposb ) );
1163         if( i_read <= 0 )
1164         {
1165             input_DeletePES( p_input->p_method_data, p_pes );
1166             return( NULL );
1167         }
1168         p_pes->i_nb_data++;
1169         if( !p_pes->p_first )
1170         {
1171             p_pes->p_first = p_data;
1172         }
1173         else
1174         {
1175             p_pes->p_last->p_next = p_data;
1176         }
1177         p_pes->p_last = p_data;
1178         p_pes->i_pes_size += i_read;
1179
1180         i_byte -= i_read;
1181         p_info->i_idxposb += i_read;
1182
1183         if( p_info->i_idxposb >= p_info->p_index[p_info->i_idxposc].i_length )
1184         {
1185             p_info->i_idxposb = 0;
1186             if( __AVI_NextIndexEntry( p_input, p_info) != 0 )
1187             {
1188                 input_DeletePES( p_input->p_method_data, p_pes );
1189                 return( NULL );
1190             }
1191         }
1192     };
1193    return( p_pes );
1194 }
1195         
1196 /*****************************************************************************
1197  * Function to convert pts to chunk or byte
1198  *****************************************************************************/
1199
1200 static inline mtime_t __AVI_PTSToChunk( AVIStreamInfo_t *p_info, 
1201                                         mtime_t i_pts )
1202 {
1203     return( (mtime_t)((double)i_pts *
1204                       (double)p_info->header.i_rate /
1205                       (double)p_info->header.i_scale /
1206                       (double)1000000.0 ) );
1207 }
1208
1209 static inline mtime_t __AVI_PTSToByte( AVIStreamInfo_t *p_info,
1210                                        mtime_t i_pts )
1211 {
1212     return( (mtime_t)((double)i_pts * 
1213                       (double)p_info->header.i_samplesize *
1214                       (double)p_info->header.i_rate /
1215                       (double)p_info->header.i_scale /
1216                       (double)1000000.0 ) );
1217
1218 }
1219
1220 /* try to realign after a seek */
1221 static int AVI_ReAlign( input_thread_t *p_input )
1222 {
1223     u32     u32_pos;
1224     off_t   i_pos;
1225     int     b_after = 0;
1226     AVIStreamInfo_t *p_info;
1227     demux_data_avi_file_t *p_avi_demux =
1228                         (demux_data_avi_file_t*)p_input->p_demux_data;
1229
1230     p_info = (p_avi_demux->p_info_video != NULL ) ? 
1231                     p_avi_demux->p_info_video :
1232                     p_avi_demux->p_info_audio;
1233     
1234     __RIFF_TellPos( p_input, &u32_pos );
1235     
1236     i_pos = (off_t)u32_pos;
1237     
1238     if( i_pos <= p_info->p_index[0].i_pos )
1239     {
1240         /*  before beginning of stream  */
1241         if( !p_info->header.i_samplesize )
1242         {
1243             __AVI_GoToStreamChunk( p_input, 
1244                                    p_info,
1245                                    0 );
1246         } 
1247         else
1248         {
1249             __AVI_GoToStreamBytes( p_input, 
1250                                    p_info, 
1251                                    0);
1252         }
1253         return( 0 );
1254     }
1255
1256     if( (p_info->p_index[p_info->i_idxposc].i_pos <= i_pos)
1257         && ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos +
1258                 p_info->p_index[p_info->i_idxposc].i_length ) )
1259     {
1260         /* FIXME if master == audio and samplesize != 0 */
1261         /* don't work with big chunk */
1262         /* don't do anything we are in the current chunk  */
1263         return( 0 );
1264     }
1265     if( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
1266     {
1267         b_after = 0;
1268     }
1269     else
1270     {
1271         b_after = 1;
1272     }
1273     /* now find in what chunk we are */
1274     while( ( i_pos < p_info->p_index[p_info->i_idxposc].i_pos )
1275            &&( p_info->i_idxposc > 0 ) )
1276     {
1277         /* search before i_idxposc */
1278         p_info->i_idxposc--;
1279     }
1280     
1281     while( i_pos >= p_info->p_index[p_info->i_idxposc].i_pos +
1282                p_info->p_index[p_info->i_idxposc].i_length + 8 )
1283     {
1284         /* search after i_idxposc */
1285         if( __AVI_NextIndexEntry( p_input, p_info ) != 0 )
1286         {
1287             return( -1 );
1288         }
1289     }
1290     /* search nearest key frame */
1291     if( ( !p_info->header.i_samplesize ) && ( p_info->i_cat == VIDEO_ES ) )
1292     {
1293         /* only for chunk stream */
1294         if( b_after )
1295         {
1296             while(!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME) )
1297             {
1298                 if( __AVI_NextIndexEntry( p_input, p_info ) != 0 )
1299                 {
1300                     break;
1301                 }
1302             }
1303         }
1304         else
1305         { 
1306             while( ( p_info->i_idxposc > 0 ) &&
1307               (!(p_info->p_index[p_info->i_idxposc].i_flags&AVIIF_KEYFRAME)) )
1308             {
1309                 p_info->i_idxposc--;
1310             }
1311         }
1312     } 
1313     __AVI_GoToStreamChunk( p_input, p_info, p_info->i_idxposc );
1314    
1315     return( 0 );
1316 }
1317
1318 /* make difference between audio and video pts as little as possible */
1319 static void AVI_SynchroReInit( input_thread_t *p_input )
1320 {
1321     demux_data_avi_file_t *p_avi_demux =
1322                         (demux_data_avi_file_t*)p_input->p_demux_data;
1323 #define p_info_video p_avi_demux->p_info_video
1324 #define p_info_audio p_avi_demux->p_info_audio
1325     if( ( p_info_video )&&( p_info_audio ) )
1326     {
1327         /* now resynch audio video video */
1328         /*don't care of AVIF_KEYFRAME */
1329         if( !p_info_audio->header.i_samplesize )
1330         {
1331             int i_chunk = __AVI_PTSToChunk( p_info_audio, 
1332                                             AVI_GetPTS( p_info_video ));
1333             __AVI_GoToStreamChunk( p_input, 
1334                                    p_info_audio, 
1335                                    i_chunk );
1336         }
1337         else
1338         {
1339             int i_byte = __AVI_PTSToByte( p_info_audio, 
1340                                           AVI_GetPTS( p_info_video ) ) ;
1341             __AVI_GoToStreamBytes( p_input,
1342                                    p_info_audio,
1343                                    i_byte );
1344         }
1345    }
1346 #undef p_info_video
1347 #undef p_info_audio
1348
1349
1350 /*****************************************************************************
1351  * AVI_GetFrameInPES : get dpts length(µs) in pes from stream
1352  *****************************************************************************
1353  * Handle multiple pes, and set pts to the good value 
1354  *****************************************************************************/
1355 static pes_packet_t *AVI_GetFrameInPES( input_thread_t *p_input,
1356                                         AVIStreamInfo_t *p_info,
1357                                         mtime_t i_dpts)
1358 {
1359     int i;
1360     pes_packet_t *p_pes = NULL;
1361     pes_packet_t *p_pes_tmp = NULL;
1362     pes_packet_t *p_pes_first = NULL;
1363     mtime_t i_pts;
1364
1365     /* we now that p_info != NULL */
1366     if( i_dpts < 1000 ) 
1367     { 
1368         return( NULL ) ; 
1369     }
1370
1371     if( !p_info->header.i_samplesize )
1372     {
1373         /* stream is chunk based , easy */
1374         int i_chunk = __MAX( __AVI_PTSToChunk( p_info, i_dpts), 1 );
1375         /* at least one frame */
1376         /* read them */
1377         p_pes_first = NULL;
1378         for( i = 0; i < i_chunk; i++ )
1379         {
1380             /* get pts while is valid */
1381             i_pts = AVI_GetPTS( p_info );
1382             p_pes_tmp = __AVI_ReadStreamChunkInPES( p_input, p_info );
1383
1384             if( !p_pes_tmp )
1385             {
1386                 return( p_pes_first );
1387             }
1388             p_pes_tmp->i_pts = i_pts;
1389             if( !p_pes_first )
1390             {
1391                 p_pes_first = p_pes_tmp;
1392             }
1393             else
1394             {
1395                 p_pes->p_next = p_pes_tmp;
1396             }
1397             p_pes = p_pes_tmp;
1398         }
1399         return( p_pes_first );
1400     }
1401     else
1402     {
1403         /* stream is byte based */
1404         int i_byte = __AVI_PTSToByte( p_info, i_dpts);
1405         if( !i_byte )
1406         {
1407             return( NULL );
1408         }
1409         /* at least one Kbyte */
1410         /*i_byte = __MIN( 1024*1000, i_byte ); *//* but no more than 1000ko */
1411         i_pts = AVI_GetPTS( p_info );
1412
1413         p_pes = __AVI_ReadStreamBytesInPES( p_input, p_info, i_byte);
1414         
1415         if( p_pes != NULL )
1416         {
1417             p_pes->i_pts = i_pts;
1418         }
1419         return( p_pes );
1420     }
1421 }
1422 /*****************************************************************************
1423  * AVI_DecodePES : send a pes to decoder 
1424  *****************************************************************************
1425  * Handle multiple pes, and set pts to the good value 
1426  *****************************************************************************/
1427 static inline void AVI_DecodePES( input_thread_t *p_input,
1428                                   AVIStreamInfo_t *p_info,
1429                                   pes_packet_t *p_pes )
1430 {
1431     pes_packet_t    *p_pes_next;
1432     /* input_decode want only one pes, but AVI_GetFrameInPES give
1433           multiple pes so send one by one */
1434     /* we now that p_info != NULL */
1435     while( p_pes )
1436     {
1437         p_pes_next = p_pes->p_next;
1438         p_pes->p_next = NULL;
1439         p_pes->i_pts = input_ClockGetTS( p_input, 
1440                                          p_input->stream.p_selected_program, 
1441                                          p_pes->i_pts * 9/100);
1442         input_DecodePES( p_info->p_es->p_decoder_fifo, p_pes );
1443         p_pes = p_pes_next;
1444     };
1445   
1446 }
1447
1448 /*****************************************************************************
1449  * AVIDemux: reads and demuxes data packets
1450  *****************************************************************************
1451  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1452  *****************************************************************************/
1453 static int AVIDemux( input_thread_t *p_input )
1454 {
1455     int i;
1456     pes_packet_t *p_pes;
1457     AVIStreamInfo_t *p_info_master;
1458     AVIStreamInfo_t *p_info_slave;    
1459
1460     demux_data_avi_file_t *p_avi_demux = 
1461                 (demux_data_avi_file_t*)p_input->p_demux_data;
1462
1463     /* search new video and audio stream selected 
1464           if current have been unselected*/
1465     if( ( !p_avi_demux->p_info_video )
1466             || ( !p_avi_demux->p_info_video->p_es->p_decoder_fifo ) )
1467     {
1468         p_avi_demux->p_info_video = NULL;
1469         for( i = 0; i < p_avi_demux->i_streams; i++ )
1470         {
1471             if( ( p_avi_demux->pp_info[i]->i_cat == VIDEO_ES )
1472                   &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo != NULL ) )
1473             {
1474                 p_avi_demux->p_info_video = p_avi_demux->pp_info[i];
1475                 p_avi_demux->p_info_video->b_selected = 1;
1476                 break;
1477             }
1478         }
1479     }
1480     if( ( !p_avi_demux->p_info_audio )
1481             ||( !p_avi_demux->p_info_audio->p_es->p_decoder_fifo ) )
1482     {
1483         p_avi_demux->p_info_audio = NULL;
1484         for( i = 0; i < p_avi_demux->i_streams; i++ )
1485         {
1486             if( ( p_avi_demux->pp_info[i]->i_cat == AUDIO_ES )
1487                   &&( p_avi_demux->pp_info[i]->p_es->p_decoder_fifo != NULL ) )
1488             {
1489                 p_avi_demux->p_info_audio = p_avi_demux->pp_info[i];
1490                 p_avi_demux->p_info_audio->b_selected = 1;
1491                 break;
1492             }
1493         }
1494     }
1495     /* by default video is master for resync audio (after a seek .. ) */
1496     if( p_avi_demux->p_info_video )
1497     {
1498         p_info_master = p_avi_demux->p_info_video;
1499         p_info_slave  = p_avi_demux->p_info_audio;
1500     }
1501     else
1502     {
1503         p_info_master = p_avi_demux->p_info_audio;
1504         p_info_slave  = NULL;
1505     }
1506
1507     if( !p_info_master ) 
1508     {
1509         intf_ErrMsg( "input error: no stream selected" );
1510         return( -1 );
1511     }
1512
1513     /* check for signal from interface */
1514     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1515     { 
1516         /* we can supposed that is a seek */
1517         /* first wait for empty buffer, arbitrary time */
1518         msleep( DEFAULT_PTS_DELAY );
1519         /* then try to realign in stream */
1520         if( AVI_ReAlign( p_input ) != 0 )
1521         {
1522             return( 0 ); /* assume EOF */
1523         }
1524         AVI_SynchroReInit( p_input ); 
1525     }
1526     /* manage rate, if not default: skeep audio */
1527     vlc_mutex_lock( &p_input->stream.stream_lock );
1528     if( p_input->stream.control.i_rate != p_avi_demux->i_rate )
1529     {
1530         if( p_avi_demux->p_info_audio)
1531         {
1532              p_avi_demux->p_info_audio->b_selected = 1;
1533         }
1534         p_avi_demux->i_rate = p_input->stream.control.i_rate;
1535     }
1536     vlc_mutex_unlock( &p_input->stream.stream_lock );    
1537     if( p_avi_demux->i_rate != DEFAULT_RATE )
1538     {
1539         p_info_slave = NULL;
1540     }
1541  
1542     /* take care of newly selected audio ES */
1543     if( p_info_master->b_selected )
1544     {
1545         p_info_master->b_selected = 0;
1546         AVI_SynchroReInit( p_input ); 
1547     }
1548     if( ( p_info_slave )&&( p_info_slave->b_selected ) )
1549     {
1550         p_info_slave->b_selected = 0;
1551         AVI_SynchroReInit( p_input );
1552     }
1553
1554     /* wait for the good time */
1555     input_ClockManageRef( p_input,
1556                           p_input->stream.p_selected_program,
1557                           p_avi_demux->i_pcr ); 
1558     /* calculate pcr, time when we must read the next data */
1559     /* 9/100 kludge ->need to convert to 1/1000000 clock unit to 1/90000 */
1560     if( p_info_slave )
1561     {
1562         p_avi_demux->i_pcr =  __MIN( AVI_GetPTS( p_info_master ),
1563                                      AVI_GetPTS( p_info_slave ) ) * 9/100;
1564     }
1565     else
1566     {
1567         p_avi_demux->i_pcr =  AVI_GetPTS( p_info_master ) * 9/100;
1568     }
1569
1570     /* get video and audio frames */
1571     p_pes = AVI_GetFrameInPES( p_input,
1572                                p_info_master,
1573                                100000 ); /* 100 ms */
1574
1575     AVI_DecodePES( p_input,
1576                    p_info_master,
1577                    p_pes);
1578
1579     if( p_info_slave )
1580     {
1581         p_pes = AVI_GetFrameInPES( p_input,
1582                                    p_info_slave,
1583                                    AVI_GetPTS( p_info_master ) -
1584                                        AVI_GetPTS( p_info_slave));
1585         AVI_DecodePES( p_input,
1586                        p_info_slave,
1587                        p_pes );
1588     }
1589     /* at the end ? */
1590     return( p_info_master->i_idxposc >= p_info_master->i_idxnb ? 0 : 1 );
1591 }