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