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