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