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