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