]> git.sesse.net Git - vlc/blob - modules/demux/avi/avi.c
* modules/codec/ffmpeg/*: modified the ffmpeg video codec to use direct
[vlc] / modules / demux / avi / avi.c
1 /*****************************************************************************
2  * avi.c : AVI file Stream input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: avi.c,v 1.9 2002/11/05 10:07:56 gbazin 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 "libavi.h"
37 #include "avi.h"
38
39 /*****************************************************************************
40  * Local prototypes
41  *****************************************************************************/
42 static int    AVIInit   ( vlc_object_t * );
43 static void __AVIEnd    ( vlc_object_t * );
44 static int    AVISeek   ( input_thread_t *, mtime_t, int );
45 static int    AVIDemux_Seekable  ( input_thread_t * );
46 static int    AVIDemux_UnSeekable( input_thread_t *p_input );
47
48 #define AVIEnd(a) __AVIEnd(VLC_OBJECT(a))
49
50 /*****************************************************************************
51  * Module descriptor
52  *****************************************************************************/
53 vlc_module_begin();
54     add_category_hint( "demuxer", NULL );
55         add_bool( "avi-interleaved", 0, NULL,
56                   "force interleaved method", 
57                   "force interleaved method" );
58         add_bool( "avi-index", 0, NULL,
59                   "force index creation", 
60                   "force index creation" );
61
62     set_description( "avi demuxer" );
63     set_capability( "demux", 212 );
64     set_callbacks( AVIInit, __AVIEnd );
65 vlc_module_end();
66
67 /*****************************************************************************
68  * Some usefull functions to manipulate memory 
69  *****************************************************************************/
70
71 static u16 GetWLE( byte_t *p_buff )
72 {
73     return( p_buff[0] + ( p_buff[1] << 8 ) );
74 }
75 static u32 GetDWLE( byte_t *p_buff )
76 {
77     return( p_buff[0] + ( p_buff[1] << 8 ) + 
78             ( p_buff[2] << 16 ) + ( p_buff[3] << 24 ) );
79 }
80 static u32 GetDWBE( byte_t *p_buff )
81 {
82     return( p_buff[3] + ( p_buff[2] << 8 ) + 
83             ( p_buff[1] << 16 ) + ( p_buff[0] << 24 ) );
84 }
85 static vlc_fourcc_t GetFOURCC( byte_t *p_buff )
86 {
87     return( VLC_FOURCC( p_buff[0], p_buff[1], p_buff[2], p_buff[3] ) );
88 }
89
90 static inline off_t __EVEN( off_t i )
91 {
92     return( (i & 1) ? i+1 : i );
93 }
94
95 #define __ABS( x ) ( (x) < 0 ? (-(x)) : (x) )
96
97 /* read data in a pes */
98 static int input_ReadInPES( input_thread_t *p_input, 
99                             pes_packet_t **pp_pes, 
100                             int i_size )
101 {
102     pes_packet_t *p_pes;
103     data_packet_t *p_data;
104
105     
106     if( !(p_pes = input_NewPES( p_input->p_method_data ) ) )
107     {
108         pp_pes = NULL;
109         return( -1 );
110     }
111
112     *pp_pes = p_pes;
113
114     if( !i_size )
115     {
116         p_pes->p_first = 
117             p_pes->p_last  = 
118                 input_NewPacket( p_input->p_method_data, 0 );
119         p_pes->i_nb_data = 1;
120         p_pes->i_pes_size = 0;
121         return( 0 );
122     }
123     
124     p_pes->i_nb_data = 0;
125     p_pes->i_pes_size = 0;
126
127     while( p_pes->i_pes_size < i_size )
128     {
129         int i_read;
130
131         i_read = input_SplitBuffer(p_input, 
132                                    &p_data, 
133                                    __MIN( i_size - 
134                                           p_pes->i_pes_size, 1024 ) );
135         if( i_read <= 0 )
136         {
137             return( p_pes->i_pes_size );
138         }
139         
140         if( !p_pes->p_first )
141         {
142             p_pes->p_first = p_data;
143         }
144         else
145         {
146             p_pes->p_last->p_next = p_data;
147         }
148         p_pes->p_last = p_data;
149         p_pes->i_nb_data++;
150         p_pes->i_pes_size += i_read;
151     } 
152
153
154         return( p_pes->i_pes_size );
155 }
156
157 /* Test if it seems that it's a key frame */
158 static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, u8 *p_byte )
159 {
160     switch( i_fourcc )
161     {
162         case FOURCC_DIV1:
163             /* we have:
164                 startcode:      0x00000100   32bits
165                 framenumber     ?             5bits
166                 piture type     0(I),1(P)     2bits
167              */
168             if( GetDWBE( p_byte ) != 0x00000100 ) 
169             {
170             /* it's not an msmpegv1 stream, strange...*/
171                 return( AVIIF_KEYFRAME );
172             }
173             else
174             {
175                 return( p_byte[4]&0x06 ? 0 : AVIIF_KEYFRAME);
176             }
177         case FOURCC_DIV2:
178         case FOURCC_DIV3:   // wmv1 also
179             /* we have
180                 picture type    0(I),1(P)     2bits
181              */
182             return( p_byte[0]&0xC0 ? 0 : AVIIF_KEYFRAME );
183         case FOURCC_mp4v:
184             /* we should find first occurence of 0x000001b6 (32bits)
185                 startcode:      0x000001b6   32bits
186                 piture type     0(I),1(P)     2bits
187             */
188             if( GetDWBE( p_byte ) != 0x000001b6 )
189             {
190                 /* not true , need to find the first VOP header */
191                 return( AVIIF_KEYFRAME );
192             }
193             else
194             {
195                 return( p_byte[4]&0xC0 ? 0 : AVIIF_KEYFRAME );
196             }
197         default:
198             /* I can't do it, so said yes */
199             return( AVIIF_KEYFRAME );
200     }
201 }
202
203 vlc_fourcc_t AVI_FourccGetCodec( int i_cat, vlc_fourcc_t i_codec )
204 {
205     switch( i_cat )
206     {
207         case( AUDIO_ES ):
208             switch( i_codec )
209             {
210                 case( WAVE_FORMAT_PCM ):
211                     return( VLC_FOURCC( 'a', 'r', 'a', 'w' ) );
212                 case( WAVE_FORMAT_MPEG ):
213                 case( WAVE_FORMAT_MPEGLAYER3 ):
214                     return( VLC_FOURCC( 'm', 'p', 'g', 'a' ) );
215                 case( WAVE_FORMAT_A52 ):
216                     return( VLC_FOURCC( 'a', '5', '2', ' ' ) );
217                 case( WAVE_FORMAT_WMA1 ):
218                     return( VLC_FOURCC( 'w', 'm', 'a', '1' ) );
219                 case( WAVE_FORMAT_WMA2 ):
220                     return( VLC_FOURCC( 'w', 'm', 'a', '2' ) );
221                 default:
222                     return( VLC_FOURCC( 'm', 's', 
223                                         ( i_codec >> 8 )&0xff, 
224                                         i_codec&0xff ) );
225             }
226         case( VIDEO_ES ):
227             // XXX DIV1 <- msmpeg4v1, DIV2 <- msmpeg4v2, DIV3 <- msmpeg4v3, mp4v for mpeg4 
228             switch( i_codec )
229             {
230                 case FOURCC_DIV1:
231                 case FOURCC_div1:
232                 case FOURCC_MPG4:
233                 case FOURCC_mpg4:
234                     return( FOURCC_DIV1 );
235                 case FOURCC_DIV2:
236                 case FOURCC_div2:
237                 case FOURCC_MP42:
238                 case FOURCC_mp42:
239                 case FOURCC_MPG3:
240                 case FOURCC_mpg3:
241                     return( FOURCC_DIV2 );
242                 case FOURCC_div3:
243                 case FOURCC_MP43:
244                 case FOURCC_mp43:
245                 case FOURCC_DIV3:
246                 case FOURCC_DIV4:
247                 case FOURCC_div4:
248                 case FOURCC_DIV5:
249                 case FOURCC_div5:
250                 case FOURCC_DIV6:
251                 case FOURCC_div6:
252                 case FOURCC_AP41:
253                 case FOURCC_3IV1:
254                     return( FOURCC_DIV3 );
255                 case FOURCC_DIVX:
256                 case FOURCC_divx:
257                 case FOURCC_MP4S:
258                 case FOURCC_mp4s:
259                 case FOURCC_M4S2:
260                 case FOURCC_m4s2:
261                 case FOURCC_xvid:
262                 case FOURCC_XVID:
263                 case FOURCC_XviD:
264                 case FOURCC_DX50:
265                 case FOURCC_mp4v:
266                 case FOURCC_4:
267                     return( FOURCC_mp4v );
268             }
269         default:
270             return( VLC_FOURCC( 'u', 'n', 'd', 'f' ) );
271     }
272 }
273
274 static void AVI_ParseStreamHeader( u32 i_id, int *pi_number, int *pi_type )
275 {
276 #define SET_PTR( p, v ) if( p ) *(p) = (v);
277     int c1,c2;
278 /* XXX i_id have to be read using MKFOURCC and NOT VLC_FOURCC */
279     c1 = ( i_id ) & 0xFF;
280     c2 = ( i_id >>  8 ) & 0xFF;
281
282     if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
283     {
284         SET_PTR( pi_number, 100); /* > max stream number */
285         SET_PTR( pi_type, UNKNOWN_ES);
286     }
287     else
288     {
289         SET_PTR( pi_number, (c1 - '0') * 10 + (c2 - '0' ) );
290         switch( ( i_id >> 16 ) & 0xFFFF )
291         {
292             case( AVITWOCC_wb ):
293                 SET_PTR( pi_type, AUDIO_ES );
294                 break;
295              case( AVITWOCC_dc ):
296              case( AVITWOCC_db ):
297                 SET_PTR( pi_type, VIDEO_ES);
298                 break;
299              default:
300                 SET_PTR( pi_type, UNKNOWN_ES );
301                 break;
302         }
303     }
304 #undef SET_PTR
305 }
306
307 static int AVI_PacketGetHeader( input_thread_t *p_input, avi_packet_t *p_pk )
308 {
309     u8  *p_peek;
310     
311     if( input_Peek( p_input, &p_peek, 16 ) < 16 )
312     {
313         return( 0 );
314     }
315     p_pk->i_fourcc  = GetDWLE( p_peek );
316     p_pk->i_size    = GetDWLE( p_peek + 4 );
317     p_pk->i_pos     = AVI_TellAbsolute( p_input );
318     if( p_pk->i_fourcc == AVIFOURCC_LIST )
319     {
320         p_pk->i_type = GetDWLE( p_peek + 8 );
321     }
322     else
323     {
324         p_pk->i_type = 0;
325     }
326     
327     memcpy( p_pk->i_peek, p_peek + 8, 8 );
328
329     AVI_ParseStreamHeader( p_pk->i_fourcc, &p_pk->i_stream, &p_pk->i_cat );
330     return( 1 );
331 }
332
333 static int AVI_PacketNext( input_thread_t *p_input )
334 {
335     avi_packet_t    avi_ck;
336
337     if( !AVI_PacketGetHeader( p_input, &avi_ck ) )
338     {
339         return( 0 );
340     }
341     if( avi_ck.i_fourcc == AVIFOURCC_LIST && avi_ck.i_type == AVIFOURCC_rec )
342     {
343         return( AVI_SkipBytes( p_input, 12 ) );
344     }
345     else
346     {
347         return( AVI_SkipBytes( p_input, __EVEN( avi_ck.i_size ) + 8 ));
348     }
349 }
350 static int AVI_PacketRead( input_thread_t   *p_input,
351                            avi_packet_t     *p_pk,
352                            pes_packet_t     **pp_pes )
353 {
354     int i_size;
355     int b_pad;
356
357     i_size = __EVEN( p_pk->i_size + 8 );
358     b_pad  = ( i_size != p_pk->i_size + 8 );
359     
360     if( input_ReadInPES( p_input, pp_pes, i_size ) != i_size )
361     {
362         return( 0 );
363     }
364     (*pp_pes)->p_first->p_payload_start += 8;
365     (*pp_pes)->i_pes_size -= 8;
366
367     if( b_pad )
368     {
369         (*pp_pes)->p_last->p_payload_end--;
370         (*pp_pes)->i_pes_size--;
371     }
372
373     return( 1 );
374 }
375
376 static int AVI_PacketSearch( input_thread_t *p_input )
377 {
378     demux_sys_t     *p_avi = p_input->p_demux_data;
379
380     avi_packet_t    avi_pk;
381     for( ;; )
382     {
383         if( !AVI_SkipBytes( p_input, 1 ) )
384         {
385             return( 0 );
386         }
387         AVI_PacketGetHeader( p_input, &avi_pk );
388         if( avi_pk.i_stream < p_avi->i_streams &&
389             ( avi_pk.i_cat == AUDIO_ES || avi_pk.i_cat == VIDEO_ES ) )
390         {
391             return( 1 );
392         }
393         switch( avi_pk.i_fourcc )
394         {
395             case AVIFOURCC_JUNK:
396             case AVIFOURCC_LIST:
397             case AVIFOURCC_idx1:
398                 return( 1 );
399         }
400     }
401 }
402
403
404 static void __AVI_AddEntryIndex( avi_stream_t *p_info,
405                                  AVIIndexEntry_t *p_index)
406 {
407     if( p_info->p_index == NULL )
408     {
409         p_info->i_idxmax = 16384;
410         p_info->i_idxnb = 0;
411         if( !( p_info->p_index = calloc( p_info->i_idxmax, 
412                                   sizeof( AVIIndexEntry_t ) ) ) )
413         {
414             return;
415         }
416     }
417     if( p_info->i_idxnb >= p_info->i_idxmax )
418     {
419         p_info->i_idxmax += 16384;
420         if( !( p_info->p_index = realloc( (void*)p_info->p_index,
421                            p_info->i_idxmax * 
422                            sizeof( AVIIndexEntry_t ) ) ) )
423         {
424             return;
425         }
426     }
427     /* calculate cumulate length */
428     if( p_info->i_idxnb > 0 )
429     {
430         p_index->i_lengthtotal = 
431             p_info->p_index[p_info->i_idxnb - 1].i_length +
432                 p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal;
433     }
434     else
435     {
436         p_index->i_lengthtotal = 0;
437     }
438
439     p_info->p_index[p_info->i_idxnb] = *p_index;
440     p_info->i_idxnb++;
441
442 }
443
444 static void AVI_IndexAddEntry( demux_sys_t *p_avi, 
445                                int i_stream, 
446                                AVIIndexEntry_t *p_index)
447 {
448     __AVI_AddEntryIndex( p_avi->pp_info[i_stream],
449                          p_index );
450     if( p_avi->i_movi_lastchunk_pos < p_index->i_pos )
451     {
452         p_avi->i_movi_lastchunk_pos = p_index->i_pos;
453     }
454 }
455
456 static void AVI_IndexLoad( input_thread_t *p_input )
457 {
458     demux_sys_t *p_avi = p_input->p_demux_data;
459     
460     avi_chunk_list_t    *p_riff;
461     avi_chunk_list_t    *p_movi;
462     avi_chunk_idx1_t    *p_idx1;
463
464     int i_stream;
465     int i_index;
466     off_t   i_offset;
467     
468     p_riff = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root, 
469                                                AVIFOURCC_RIFF, 0);
470     
471     p_idx1 = (avi_chunk_idx1_t*)AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0);
472     p_movi = (avi_chunk_list_t*)AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
473
474     if( !p_idx1 )
475     {
476         msg_Warn( p_input, "cannot find idx1 chunk, no index defined" );
477         return;
478     }
479     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
480     {
481         p_avi->pp_info[i_stream]->i_idxnb  = 0;
482         p_avi->pp_info[i_stream]->i_idxmax = 0;
483         p_avi->pp_info[i_stream]->p_index  = NULL;
484     }
485     /* *** calculate offset *** */
486     if( p_idx1->i_entry_count > 0 && 
487         p_idx1->entry[0].i_pos < p_movi->i_chunk_pos )
488     {
489         i_offset = p_movi->i_chunk_pos + 8;
490     }
491     else
492     {
493         i_offset = 0;
494     }
495
496     for( i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )
497     {
498         int i_cat;
499         
500         AVI_ParseStreamHeader( p_idx1->entry[i_index].i_fourcc,
501                                &i_stream,
502                                &i_cat );
503         if( i_stream < p_avi->i_streams &&
504             i_cat == p_avi->pp_info[i_stream]->i_cat )
505         {
506             AVIIndexEntry_t index;
507             index.i_id      = p_idx1->entry[i_index].i_fourcc;
508             index.i_flags   = 
509                 p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME);
510             index.i_pos     = p_idx1->entry[i_index].i_pos + i_offset;
511             index.i_length  = p_idx1->entry[i_index].i_length;
512             AVI_IndexAddEntry( p_avi, i_stream, &index );
513         }
514     }
515     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
516     {
517         msg_Dbg( p_input, 
518                 "stream[%d] creating %d index entries", 
519                 i_stream,
520                 p_avi->pp_info[i_stream]->i_idxnb );
521     }
522     
523 }
524
525 static void AVI_IndexCreate( input_thread_t *p_input )
526 {
527     demux_sys_t *p_avi = p_input->p_demux_data;
528     
529     avi_chunk_list_t    *p_riff;
530     avi_chunk_list_t    *p_movi;
531
532     int i_stream;
533     off_t   i_movi_end;
534     
535     p_riff = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root, 
536                                                AVIFOURCC_RIFF, 0);
537     p_movi = (avi_chunk_list_t*)AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
538     
539     if( !p_movi )
540     {
541         msg_Err( p_input, "cannot find p_movi" );
542         return;
543     }
544
545     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
546     {
547         p_avi->pp_info[i_stream]->i_idxnb  = 0;
548         p_avi->pp_info[i_stream]->i_idxmax = 0;
549         p_avi->pp_info[i_stream]->p_index  = NULL;
550     }
551     i_movi_end = __MIN( p_movi->i_chunk_pos + p_movi->i_chunk_size,
552                         p_input->stream.p_selected_area->i_size );
553
554     AVI_SeekAbsolute( p_input, p_movi->i_chunk_pos + 12);
555     msg_Warn( p_input, "creating index from LIST-movi, will take time !" );
556     for( ;; )
557     {
558         avi_packet_t pk;
559         
560         if( !AVI_PacketGetHeader( p_input, &pk ) )
561         {
562             break;
563         }
564         if( pk.i_stream < p_avi->i_streams &&
565             pk.i_cat == p_avi->pp_info[pk.i_stream]->i_cat )
566         {
567             AVIIndexEntry_t index;
568             index.i_id      = pk.i_fourcc;
569             index.i_flags   = 
570                AVI_GetKeyFlag(p_avi->pp_info[pk.i_stream]->i_codec, pk.i_peek);
571             index.i_pos     = pk.i_pos;
572             index.i_length  = pk.i_size;
573             AVI_IndexAddEntry( p_avi, pk.i_stream, &index );
574         }
575         else
576         {
577             switch( pk.i_fourcc )
578             {
579                 case AVIFOURCC_idx1:
580                     goto print_stat;
581                 case AVIFOURCC_rec:
582                 case AVIFOURCC_JUNK:
583                     break;
584                 default:
585                     msg_Warn( p_input, "need resync, probably broken avi" );
586                     if( !AVI_PacketSearch( p_input ) )
587                     {
588                         msg_Warn( p_input, "lost sync, abord index creation" );
589                         goto print_stat;
590                     }
591             }
592         }
593         if( pk.i_pos + pk.i_size >= i_movi_end ||
594             !AVI_PacketNext( p_input ) )
595         {
596             break;
597         }
598     }
599
600 print_stat:
601     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
602     {
603         msg_Dbg( p_input, 
604                 "stream[%d] creating %d index entries", 
605                 i_stream,
606                 p_avi->pp_info[i_stream]->i_idxnb );
607     }
608 }
609
610
611 /*****************************************************************************
612  * Stream managment
613  *****************************************************************************/
614 static int  AVI_StreamStart  ( input_thread_t *, demux_sys_t *, int );
615 static int  AVI_StreamSeek   ( input_thread_t *, demux_sys_t *, int, mtime_t );
616 static void AVI_StreamStop   ( input_thread_t *, demux_sys_t *, int );
617
618 static int  AVI_StreamStart( input_thread_t *p_input,  
619                              demux_sys_t *p_avi, int i_stream )
620 {
621 #define p_stream    p_avi->pp_info[i_stream]
622     if( !p_stream->p_es )
623     {
624         msg_Warn( p_input, "stream[%d] unselectable", i_stream );
625         return( 0 );
626     }
627     if( p_stream->i_activated )
628     {
629         msg_Warn( p_input, "stream[%d] already selected", i_stream );
630         return( 1 );
631     }
632     
633     if( !p_stream->p_es->p_decoder_fifo )
634     {
635         vlc_mutex_lock( &p_input->stream.stream_lock );
636         input_SelectES( p_input, p_stream->p_es );
637         vlc_mutex_unlock( &p_input->stream.stream_lock );
638     }
639     p_stream->i_activated = p_stream->p_es->p_decoder_fifo ? 1 : 0;
640     if( p_stream->i_activated )
641     {
642         AVI_StreamSeek( p_input, p_avi, i_stream, p_avi->i_time );
643     }
644
645     return( p_stream->i_activated );
646 #undef  p_stream
647 }
648
649 static void    AVI_StreamStop( input_thread_t *p_input,
650                                demux_sys_t *p_avi, int i_stream )
651 {
652 #define p_stream    p_avi->pp_info[i_stream]
653
654     if( !p_stream->i_activated )
655     {
656         msg_Warn( p_input, "stream[%d] already unselected", i_stream );
657         return;
658     }
659     
660     if( p_stream->p_es->p_decoder_fifo )
661     {
662         vlc_mutex_lock( &p_input->stream.stream_lock );
663         input_UnselectES( p_input, p_stream->p_es );
664         vlc_mutex_unlock( &p_input->stream.stream_lock );
665     }
666
667             
668     p_stream->i_activated = 0;
669
670 #undef  p_stream
671 }
672
673 /****************************************************************************
674  * AVI_MovieGetLength give max streams length in second
675  ****************************************************************************/
676 static mtime_t  AVI_MovieGetLength( input_thread_t *p_input, demux_sys_t *p_avi )
677 {
678     int i_stream;
679     mtime_t i_maxlength;
680     
681     i_maxlength = 0;
682     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
683     {
684 #define p_stream  p_avi->pp_info[i_stream]
685         mtime_t i_length;
686         /* fix length for each stream */
687         if( p_stream->i_idxnb < 1 || !p_stream->p_index )
688         {
689             continue;
690         }
691
692         if( p_stream->i_samplesize )
693         {
694             i_length = 
695                 (mtime_t)( p_stream->p_index[p_stream->i_idxnb-1].i_lengthtotal + 
696                            p_stream->p_index[p_stream->i_idxnb-1].i_length ) /
697                 (mtime_t)p_stream->i_scale /
698                 (mtime_t)p_stream->i_rate /
699                 (mtime_t)p_stream->i_samplesize;
700         }
701         else
702         {
703             i_length = (mtime_t)p_stream->i_idxnb *
704                        (mtime_t)p_stream->i_scale /
705                        (mtime_t)p_stream->i_rate;
706         }
707
708         msg_Dbg( p_input, 
709                  "stream[%d] length:%lld (based on index)",
710                  i_stream,
711                  i_length );
712         i_maxlength = __MAX( i_maxlength, i_length );
713 #undef p_stream                         
714     }
715
716     return( i_maxlength );
717 }
718
719 /*****************************************************************************
720  * AVIEnd: frees unused data
721  *****************************************************************************/
722 static void __AVIEnd ( vlc_object_t * p_this )
723 {   
724     input_thread_t *    p_input = (input_thread_t *)p_this;
725     int i;
726     demux_sys_t *p_avi = p_input->p_demux_data  ; 
727     
728     if( p_avi->pp_info )
729     {
730         for( i = 0; i < p_avi->i_streams; i++ )
731         {
732             if( p_avi->pp_info[i] ) 
733             {
734                 if( p_avi->pp_info[i]->p_index )
735                 {
736                       free( p_avi->pp_info[i]->p_index );
737                 }
738                 free( p_avi->pp_info[i] ); 
739             }
740         }
741          free( p_avi->pp_info );
742     }
743     AVI_ChunkFreeRoot( p_input, &p_avi->ck_root );
744 }
745
746 /*****************************************************************************
747  * AVIInit: check file and initializes AVI structures
748  *****************************************************************************/
749 static int AVIInit( vlc_object_t * p_this )
750 {   
751     input_thread_t *    p_input = (input_thread_t *)p_this;
752     avi_chunk_t         ck_riff;
753     avi_chunk_list_t    *p_riff = (avi_chunk_list_t*)&ck_riff;
754     avi_chunk_list_t    *p_hdrl, *p_movi;
755 #if 0
756     avi_chunk_list_t    *p_INFO;
757     avi_chunk_strz_t    *p_name;
758 #endif
759     avi_chunk_avih_t    *p_avih;
760     demux_sys_t *p_avi;
761     es_descriptor_t *p_es = NULL; /* avoid warning */
762     int i;
763
764     int b_stream_audio, b_stream_video; 
765
766     p_input->pf_demux = AVIDemux_Seekable;
767     if( !AVI_TestFile( p_input ) )
768     {
769         msg_Warn( p_input, "avi module discarded (invalid headr)" );
770         return( -1 );
771     }
772
773     /* Initialize access plug-in structures. */
774     if( p_input->i_mtu == 0 )
775     {
776         /* Improve speed. */
777         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
778     }
779
780     if( !( p_input->p_demux_data = 
781                     p_avi = malloc( sizeof(demux_sys_t) ) ) )
782     {
783         msg_Err( p_input, "out of memory" );
784         return( -1 );
785     }
786     memset( p_avi, 0, sizeof( demux_sys_t ) );
787     p_avi->i_time = 0;
788     p_avi->i_pcr  = 0;
789     p_avi->b_seekable = ( ( p_input->stream.b_seekable )
790                         &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
791     p_avi->i_movi_lastchunk_pos = 0;
792
793     /* *** for unseekable stream, automaticaly use AVIDemux_interleaved *** */
794     if( !p_avi->b_seekable || config_GetInt( p_input, "avi-interleaved" ) )
795     {
796         p_input->pf_demux = AVIDemux_UnSeekable;
797     }
798     
799     if( !AVI_ChunkReadRoot( p_input, &p_avi->ck_root, p_avi->b_seekable ) )
800     {
801         msg_Err( p_input, "avi module discarded (invalid file)" );
802         return( -1 );
803     }
804     AVI_ChunkDumpDebug( p_input, &p_avi->ck_root );
805
806
807     p_riff  = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root, 
808                                                 AVIFOURCC_RIFF, 0 );
809     p_hdrl  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff,
810                                                 AVIFOURCC_hdrl, 0 );
811     p_movi  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff, 
812                                                 AVIFOURCC_movi, 0 );
813 #if 0
814     p_INFO  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff,
815                                                 AVIFOURCC_INFO, 0 );
816     p_name  = (avi_chunk_strz_t*)AVI_ChunkFind( p_INFO,
817                                                 AVIFOURCC_INAM, 0 );
818     if( p_name )
819     {
820         
821     }
822 #endif
823
824     if( !p_hdrl || !p_movi )
825     {
826         msg_Err( p_input, "avi module discarded (invalid file)" );
827         return( -1 );
828     }
829     
830     if( !( p_avih = (avi_chunk_avih_t*)AVI_ChunkFind( p_hdrl, 
831                                                       AVIFOURCC_avih, 0 ) ) )
832     {
833         msg_Err( p_input, "cannot find avih chunk" );
834         return( -1 );
835     }
836     p_avi->i_streams = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl );
837     if( p_avih->i_streams != p_avi->i_streams )
838     {
839         msg_Warn( p_input, 
840                   "found %d stream but %d are declared",
841                   p_avi->i_streams,
842                   p_avih->i_streams );
843     }
844     if( p_avi->i_streams == 0 )
845     {
846         AVIEnd( p_input );
847         msg_Err( p_input, "no stream defined!" );
848         return( -1 );
849     }
850
851     /*  create one program */
852     vlc_mutex_lock( &p_input->stream.stream_lock );
853     if( input_InitStream( p_input, 0 ) == -1)
854     {
855         vlc_mutex_unlock( &p_input->stream.stream_lock );
856         AVIEnd( p_input );
857         msg_Err( p_input, "cannot init stream" );
858         return( -1 );
859     }
860     if( input_AddProgram( p_input, 0, 0) == NULL )
861     {
862         vlc_mutex_unlock( &p_input->stream.stream_lock );
863         AVIEnd( p_input );
864         msg_Err( p_input, "cannot add program" );
865         return( -1 );
866     }
867     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
868     vlc_mutex_unlock( &p_input->stream.stream_lock ); 
869     
870     /* print informations on streams */
871     msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ", 
872              p_avi->i_streams,
873              p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
874              p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
875              p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
876              p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
877
878     /* now read info on each stream and create ES */
879     p_avi->pp_info = calloc( p_avi->i_streams, 
880                             sizeof( avi_stream_t* ) );
881     memset( p_avi->pp_info, 
882             0, 
883             sizeof( avi_stream_t* ) * p_avi->i_streams );
884
885     for( i = 0 ; i < p_avi->i_streams; i++ )
886     {
887         avi_chunk_list_t    *p_avi_strl;
888         avi_chunk_strh_t    *p_avi_strh;
889         avi_chunk_strf_auds_t    *p_avi_strf_auds;
890         avi_chunk_strf_vids_t    *p_avi_strf_vids;
891         int     i_init_size;
892         void    *p_init_data;
893 #define p_info  p_avi->pp_info[i]
894         p_info = malloc( sizeof(avi_stream_t ) );
895         memset( p_info, 0, sizeof( avi_stream_t ) );        
896     
897         p_avi_strl = (avi_chunk_list_t*)AVI_ChunkFind( p_hdrl, 
898                                                        AVIFOURCC_strl, i );
899         p_avi_strh = (avi_chunk_strh_t*)AVI_ChunkFind( p_avi_strl, 
900                                                        AVIFOURCC_strh, 0 );
901         p_avi_strf_auds = (avi_chunk_strf_auds_t*)
902             p_avi_strf_vids = (avi_chunk_strf_vids_t*)
903                 AVI_ChunkFind( p_avi_strl, AVIFOURCC_strf, 0 );
904
905         if( !p_avi_strl || !p_avi_strh || 
906                 ( !p_avi_strf_auds && !p_avi_strf_vids ) )
907         {
908             msg_Warn( p_input, "stream[%d] incomlete", i );
909             continue;
910         }
911         
912         /* *** Init p_info *** */
913         p_info->i_rate  = p_avi_strh->i_rate;
914         p_info->i_scale = p_avi_strh->i_scale;
915         p_info->i_samplesize = p_avi_strh->i_samplesize;
916
917         switch( p_avi_strh->i_type )
918         {
919             case( AVIFOURCC_auds ):
920                 p_info->i_cat = AUDIO_ES;
921                 p_info->i_fourcc = 
922                     AVI_FourccGetCodec( AUDIO_ES, 
923                                         p_avi_strf_auds->i_formattag );
924                 p_info->i_codec  = p_info->i_fourcc;
925                 i_init_size = p_avi_strf_auds->i_chunk_size;
926                 p_init_data = p_avi_strf_auds->p_wfx;
927                 msg_Dbg( p_input, "stream[%d] audio(0x%x) %d channels %dHz %dbits",
928                         i,
929                         p_avi_strf_auds->i_formattag,
930                         p_avi_strf_auds->i_channels,
931                         p_avi_strf_auds->i_samplespersec,
932                         p_avi_strf_auds->i_bitspersample );
933                 break;
934                 
935             case( AVIFOURCC_vids ):
936                 p_info->i_cat = VIDEO_ES;
937                 /* XXX quick hack for playing ffmpeg video, I don't know 
938                     who is doing something wrong */
939                 p_info->i_samplesize = 0;
940                 p_info->i_fourcc = p_avi_strf_vids->p_bih->biCompression;
941                 p_info->i_codec = 
942                     AVI_FourccGetCodec( VIDEO_ES, p_info->i_fourcc );
943                 i_init_size = p_avi_strf_vids->i_chunk_size;
944                 p_init_data = p_avi_strf_vids->p_bih;
945                 msg_Dbg( p_input, "stream[%d] video(%4.4s) %dx%d %dbpp %ffps",
946                         i,
947                          (char*)&p_avi_strf_vids->p_bih->biCompression,
948                          p_avi_strf_vids->p_bih->biWidth,
949                          p_avi_strf_vids->p_bih->biHeight,
950                          p_avi_strf_vids->p_bih->biBitCount,
951                          (float)p_info->i_rate /
952                              (float)p_info->i_scale );
953                 break;
954             default:
955                 msg_Err( p_input, "stream[%d] unknown type", i );
956                 p_info->i_cat = UNKNOWN_ES;
957                 i_init_size = 0;
958                 p_init_data = NULL;
959                 break;
960         }
961         p_info->i_activated = 0;
962         /* add one ES */
963         vlc_mutex_lock( &p_input->stream.stream_lock );
964         p_info->p_es =
965             p_es = input_AddES( p_input,
966                                 p_input->stream.p_selected_program, 1+i,
967                                 i_init_size );
968         vlc_mutex_unlock( &p_input->stream.stream_lock );
969         p_es->i_stream_id =i; /* XXX: i don't use it */ 
970         p_es->i_fourcc = p_info->i_fourcc;
971         p_es->i_cat = p_info->i_cat;
972
973         /* We copy strf for decoder in p_es->p_demux_data */
974         if( p_init_data )
975         {
976             memcpy( p_es->p_demux_data, 
977                     p_init_data,
978                     i_init_size );
979         }
980 #undef p_info           
981     }
982     if( config_GetInt( p_input, "avi-index" ) )
983     {
984         if( p_avi->b_seekable )
985         {
986             AVI_IndexCreate( p_input );
987         }
988         else
989         {
990             msg_Warn( p_input, "cannot create index (unseekable stream)" );
991             AVI_IndexLoad( p_input );
992         }
993     }
994     else
995     {
996         AVI_IndexLoad( p_input );
997     }
998     
999     /* *** movie length in sec *** */
1000 #if 0
1001     p_avi->i_length = (mtime_t)p_avih->i_totalframes * 
1002                       (mtime_t)p_avih->i_microsecperframe / 
1003                       (mtime_t)1000000;
1004 #endif
1005
1006     p_avi->i_length = AVI_MovieGetLength( p_input, p_avi );
1007     if( p_avi->i_length < (mtime_t)p_avih->i_totalframes *
1008                           (mtime_t)p_avih->i_microsecperframe /
1009                           (mtime_t)1000000 )
1010     {
1011         msg_Warn( p_input, "broken or missing index, 'seek' will be axproximative or will have strange behavour" );
1012     }
1013
1014     vlc_mutex_lock( &p_input->stream.stream_lock ); 
1015     if( p_avi->i_length )
1016     {
1017         p_input->stream.i_mux_rate = 
1018             p_input->stream.p_selected_area->i_size / 50 / p_avi->i_length;
1019     }
1020     else
1021     {
1022         p_input->stream.i_mux_rate = 0;
1023     }
1024     vlc_mutex_unlock( &p_input->stream.stream_lock ); 
1025
1026     b_stream_audio = 0;
1027     b_stream_video = 0;
1028     
1029     for( i = 0; i < p_avi->i_streams; i++ )
1030     {
1031 #define p_info  p_avi->pp_info[i]
1032         switch( p_info->p_es->i_cat )
1033         {
1034             case( VIDEO_ES ):
1035
1036                 if( !b_stream_video ) 
1037                 {
1038                     b_stream_video = AVI_StreamStart( p_input, p_avi, i );
1039                 }
1040                 break;
1041
1042             case( AUDIO_ES ):
1043                 if( !b_stream_audio ) 
1044                 {
1045                     b_stream_audio = AVI_StreamStart( p_input, p_avi, i );
1046                 }
1047                 break;
1048             default:
1049                 break;
1050         }
1051 #undef p_info    
1052     }
1053
1054     if( !b_stream_video ) 
1055     {
1056         msg_Warn( p_input, "no video stream found" );
1057     }
1058     if( !b_stream_audio )
1059     {
1060         msg_Warn( p_input, "no audio stream found!" );
1061     }
1062
1063     vlc_mutex_lock( &p_input->stream.stream_lock );
1064     p_input->stream.p_selected_program->b_is_ok = 1;
1065     vlc_mutex_unlock( &p_input->stream.stream_lock );
1066     
1067     if( p_avi->b_seekable )
1068     {
1069         AVI_ChunkGoto( p_input, p_movi );
1070     }
1071     else
1072     {
1073         // already at begining of p_movi
1074     }
1075     AVI_SkipBytes( p_input, 12 ); // enter in p_movi
1076
1077     p_avi->i_movi_begin = p_movi->i_chunk_pos;
1078     return( 0 );
1079 }
1080
1081
1082
1083
1084 /*****************************************************************************
1085  * Function to convert pts to chunk or byte
1086  *****************************************************************************/
1087
1088 static inline mtime_t AVI_PTSToChunk( avi_stream_t *p_info, 
1089                                         mtime_t i_pts )
1090 {
1091     return( (mtime_t)((s64)i_pts *
1092                       (s64)p_info->i_rate /
1093                       (s64)p_info->i_scale /
1094                       (s64)1000000 ) );
1095 }
1096 static inline mtime_t AVI_PTSToByte( avi_stream_t *p_info,
1097                                        mtime_t i_pts )
1098 {
1099     return( (mtime_t)((s64)i_pts * 
1100                       (s64)p_info->i_samplesize *
1101                       (s64)p_info->i_rate /
1102                       (s64)p_info->i_scale /
1103                       (s64)1000000 ) );
1104
1105 }
1106
1107 static mtime_t AVI_GetDPTS( avi_stream_t *p_stream, int i_count )
1108 {
1109     if( p_stream->i_samplesize )
1110     {
1111         return( (mtime_t)( (s64)1000000 *
1112                     (s64)i_count *
1113                     (s64)p_stream->i_scale /
1114                     (s64)p_stream->i_rate /
1115                     (s64)p_stream->i_samplesize ) );
1116     }
1117     else
1118     {
1119         return( (mtime_t)( (s64)1000000 *
1120                     (s64)i_count *
1121                     (s64)p_stream->i_scale /
1122                     (s64)p_stream->i_rate) );
1123     }
1124
1125 }
1126
1127 static mtime_t AVI_GetPTS( avi_stream_t *p_info )
1128 {
1129     
1130     if( p_info->i_samplesize )
1131     {
1132         /* we need a valid entry we will emulate one */
1133         int i_len;
1134         if( p_info->i_idxposc == p_info->i_idxnb )
1135         {
1136             if( p_info->i_idxposc )
1137             {
1138                 /* use the last entry */
1139                 i_len = p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal
1140                             + p_info->p_index[p_info->i_idxnb - 1].i_length
1141                             + p_info->i_idxposb; /* should be 0 */
1142             }
1143             else
1144             {
1145                 i_len = p_info->i_idxposb; 
1146                 /* no valid entry use only offset*/
1147             }
1148         }
1149         else
1150         {
1151             i_len = p_info->p_index[p_info->i_idxposc].i_lengthtotal
1152                                 + p_info->i_idxposb;
1153         }
1154         return( (mtime_t)( (s64)1000000 *
1155                    (s64)i_len *
1156                     (s64)p_info->i_scale /
1157                     (s64)p_info->i_rate /
1158                     (s64)p_info->i_samplesize ) );
1159     }
1160     else
1161     {
1162         /* even if p_info->i_idxposc isn't valid, there isn't any problem */
1163         return( (mtime_t)( (s64)1000000 *
1164                     (s64)(p_info->i_idxposc ) *
1165                     (s64)p_info->i_scale /
1166                     (s64)p_info->i_rate) );
1167     }
1168 }
1169
1170 static int AVI_StreamChunkFind( input_thread_t *p_input,
1171                                 int i_stream )
1172 {
1173     demux_sys_t *p_avi = p_input->p_demux_data;
1174     avi_packet_t avi_pk;
1175
1176     /* find first chunk of i_stream that isn't in index */
1177
1178     if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin )
1179     {
1180         AVI_SeekAbsolute( p_input, p_avi->i_movi_lastchunk_pos );
1181         if( !AVI_PacketNext( p_input ) )
1182         {
1183             return( 0 );
1184         }
1185     }
1186     else
1187     {
1188         AVI_SeekAbsolute( p_input, p_avi->i_movi_begin );
1189     }
1190
1191     for( ;; )
1192     {
1193
1194         if( !AVI_PacketGetHeader( p_input, &avi_pk ) )
1195         {
1196             msg_Err( p_input, "cannot get packet header" );
1197             return( 0 );
1198         }
1199         if( avi_pk.i_stream >= p_avi->i_streams ||
1200             ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1201         {
1202             switch( avi_pk.i_fourcc )
1203             {
1204                 case AVIFOURCC_LIST:
1205                     AVI_SkipBytes( p_input, 12 );
1206                     break;
1207                 default:
1208                     if( !AVI_PacketNext( p_input ) )
1209                     {
1210                         return( 0 );
1211                     }
1212                     break;
1213             }
1214         }
1215         else
1216         {
1217             /* add this chunk to the index */
1218             AVIIndexEntry_t index;
1219             
1220             index.i_id = avi_pk.i_fourcc;
1221             index.i_flags = 
1222                AVI_GetKeyFlag(p_avi->pp_info[avi_pk.i_stream]->i_codec,
1223                               avi_pk.i_peek);
1224             index.i_pos = avi_pk.i_pos;
1225             index.i_length = avi_pk.i_size;
1226             AVI_IndexAddEntry( p_avi, avi_pk.i_stream, &index );
1227
1228             if( avi_pk.i_stream == i_stream  )
1229             {
1230                 return( 1 );
1231             }
1232             
1233             if( !AVI_PacketNext( p_input ) )
1234             {
1235                 return( 0 );
1236             }
1237         }
1238     }
1239 }
1240
1241
1242 /* be sure that i_ck will be a valid index entry */
1243 static int AVI_SetStreamChunk( input_thread_t    *p_input,
1244                                int i_stream,
1245                                int i_ck )
1246 {
1247     demux_sys_t *p_avi = p_input->p_demux_data;
1248     avi_stream_t *p_stream = p_avi->pp_info[i_stream];
1249     
1250     p_stream->i_idxposc = i_ck;
1251     p_stream->i_idxposb = 0;
1252
1253     if(  i_ck >= p_stream->i_idxnb )
1254     {
1255         p_stream->i_idxposc = p_stream->i_idxnb - 1;
1256         do
1257         {
1258             p_stream->i_idxposc++;
1259             if( !AVI_StreamChunkFind( p_input, i_stream ) )
1260             {
1261                 return( 0 );
1262             }
1263
1264         } while( p_stream->i_idxposc < i_ck );
1265     }
1266
1267     return( 1 );
1268 }
1269
1270
1271 /* XXX FIXME up to now, we assume that all chunk are one after one */
1272 static int AVI_SetStreamBytes( input_thread_t    *p_input, 
1273                                int i_stream,
1274                                off_t   i_byte )
1275 {
1276     demux_sys_t *p_avi = p_input->p_demux_data;
1277     avi_stream_t *p_stream = p_avi->pp_info[i_stream];
1278
1279     if( ( p_stream->i_idxnb > 0 )
1280         &&( i_byte < p_stream->p_index[p_stream->i_idxnb - 1].i_lengthtotal + 
1281                 p_stream->p_index[p_stream->i_idxnb - 1].i_length ) )
1282     {
1283         /* index is valid to find the ck */
1284         /* uses dichototmie to be fast enougth */
1285         int i_idxposc = __MIN( p_stream->i_idxposc, p_stream->i_idxnb - 1 );
1286         int i_idxmax  = p_stream->i_idxnb;
1287         int i_idxmin  = 0;
1288         for( ;; )
1289         {
1290             if( p_stream->p_index[i_idxposc].i_lengthtotal > i_byte )
1291             {
1292                 i_idxmax  = i_idxposc ;
1293                 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1294             }
1295             else
1296             {
1297                 if( p_stream->p_index[i_idxposc].i_lengthtotal + 
1298                         p_stream->p_index[i_idxposc].i_length <= i_byte)
1299                 {
1300                     i_idxmin  = i_idxposc ;
1301                     i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1302                 }
1303                 else
1304                 {
1305                     p_stream->i_idxposc = i_idxposc;
1306                     p_stream->i_idxposb = i_byte - 
1307                             p_stream->p_index[i_idxposc].i_lengthtotal;
1308                     return( 1 );
1309                 }
1310             }
1311         }
1312         
1313     }
1314     else
1315     {
1316         p_stream->i_idxposc = p_stream->i_idxnb - 1;
1317         p_stream->i_idxposb = 0;
1318         do
1319         {
1320             p_stream->i_idxposc++;
1321             if( !AVI_StreamChunkFind( p_input, i_stream ) )
1322             {
1323                 return( 0 );
1324             }
1325
1326         } while( p_stream->p_index[p_stream->i_idxposc].i_lengthtotal +
1327                     p_stream->p_index[p_stream->i_idxposc].i_length <= i_byte );
1328
1329         p_stream->i_idxposb = i_byte -
1330                        p_stream->p_index[p_stream->i_idxposc].i_lengthtotal;
1331         return( 1 );
1332     }
1333 }
1334
1335 static int AVI_StreamSeek( input_thread_t *p_input,
1336                            demux_sys_t  *p_avi,
1337                            int i_stream, 
1338                            mtime_t i_date )
1339 {
1340 #define p_stream    p_avi->pp_info[i_stream]
1341     mtime_t i_oldpts;
1342     
1343     i_oldpts = AVI_GetPTS( p_stream );
1344
1345     if( !p_stream->i_samplesize )
1346     {
1347         if( !AVI_SetStreamChunk( p_input,
1348                                  i_stream, 
1349                                  AVI_PTSToChunk( p_stream, i_date ) ) )
1350         {
1351             return( 0 );
1352         }
1353                 
1354         /* search key frame */
1355         msg_Dbg( p_input, 
1356                  "old:%lld %s new %lld",
1357                  i_oldpts, 
1358                  i_oldpts > i_date ? ">" : "<",
1359                  i_date );
1360
1361         if( i_date < i_oldpts )
1362         {
1363             while( p_stream->i_idxposc > 0 && 
1364                !( p_stream->p_index[p_stream->i_idxposc].i_flags & 
1365                                                             AVIIF_KEYFRAME ) )
1366             {
1367                 if( !AVI_SetStreamChunk( p_input,
1368                                          i_stream,
1369                                          p_stream->i_idxposc - 1 ) )
1370                 {
1371                     return( 0 );
1372                 }
1373             }
1374         }
1375         else
1376         {
1377             while( p_stream->i_idxposc < p_stream->i_idxnb &&
1378                     !( p_stream->p_index[p_stream->i_idxposc].i_flags &
1379                                                             AVIIF_KEYFRAME ) )
1380             {
1381                 if( !AVI_SetStreamChunk( p_input, 
1382                                          i_stream, 
1383                                          p_stream->i_idxposc + 1 ) )
1384                 {
1385                     return( 0 );
1386                 }
1387             }
1388         }
1389     }
1390     else
1391     {
1392         if( !AVI_SetStreamBytes( p_input,
1393                                  i_stream,
1394                                  AVI_PTSToByte( p_stream, i_date ) ) )
1395         {
1396             return( 0 );
1397         }
1398     }
1399     return( 1 );
1400 #undef p_stream
1401 }
1402
1403 /*****************************************************************************
1404  * AVISeek: goto to i_date or i_percent
1405  *****************************************************************************
1406  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1407  *****************************************************************************/
1408 static int    AVISeek   ( input_thread_t *p_input, 
1409                           mtime_t i_date, int i_percent )
1410 {
1411
1412     demux_sys_t *p_avi = p_input->p_demux_data;
1413     int         i_stream;
1414     msg_Dbg( p_input, 
1415              "seek requested: %lld secondes %d%%", 
1416              i_date / 1000000,
1417              i_percent );
1418
1419     if( p_avi->b_seekable )
1420     {
1421         if( !p_avi->i_length )
1422         {
1423             avi_stream_t *p_stream;
1424             u64 i_pos;
1425
1426             /* use i_percent to create a true i_date */
1427             msg_Warn( p_input, 
1428                       "mmh, seeking without index at %d%%"
1429                       " work only for interleaved file", i_percent );
1430
1431             if( i_percent >= 100 )
1432             {
1433                 msg_Err( p_input, "cannot seek so far !" );
1434                 return( -1 );
1435             }
1436             i_percent = __MAX( i_percent, 0 );
1437             
1438             /* try to find chunk that is at i_percent or the file */
1439             i_pos = __MAX( i_percent * 
1440                            p_input->stream.p_selected_area->i_size / 100,
1441                            p_avi->i_movi_begin );
1442             /* search first selected stream */
1443             for( i_stream = 0, p_stream = NULL; 
1444                         i_stream < p_avi->i_streams; i_stream++ )
1445             {
1446                 p_stream = p_avi->pp_info[i_stream];
1447                 if( p_stream->i_activated )
1448                 {
1449                     break;
1450                 }
1451             }
1452             if( !p_stream || !p_stream->i_activated )
1453             {
1454                 msg_Err( p_input, "cannot find any selected stream" );
1455                 return( -1 );
1456             }
1457             
1458             /* be sure that the index exit */
1459             if( !AVI_SetStreamChunk( p_input, 
1460                                      i_stream,
1461                                      0 ) )
1462             {
1463                 msg_Err( p_input, "cannot seek" );
1464                 return( -1 );
1465             }
1466            
1467             while( i_pos >= p_stream->p_index[p_stream->i_idxposc].i_pos +
1468                p_stream->p_index[p_stream->i_idxposc].i_length + 8 )
1469             {
1470                 /* search after i_idxposc */
1471                 if( !AVI_SetStreamChunk( p_input, 
1472                                          i_stream, p_stream->i_idxposc + 1 ) )
1473                 {
1474                     msg_Err( p_input, "cannot seek" );
1475                     return( -1 );
1476                 }
1477             }
1478             i_date = AVI_GetPTS( p_stream );
1479             /* TODO better support for i_samplesize != 0 */
1480             msg_Dbg( p_input, "estimate date %lld", i_date );
1481         }
1482
1483 #define p_stream    p_avi->pp_info[i_stream]
1484         p_avi->i_time = 0;
1485         /* seek for chunk based streams */
1486         for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1487         {
1488             if( p_stream->i_activated && !p_stream->i_samplesize )
1489 //            if( p_stream->i_activated )
1490             {
1491                 AVI_StreamSeek( p_input, p_avi, i_stream, i_date );
1492                 p_avi->i_time = __MAX( AVI_GetPTS( p_stream ), 
1493                                         p_avi->i_time );
1494             }
1495         }
1496 #if 1
1497         if( p_avi->i_time )
1498         {
1499             i_date = p_avi->i_time;
1500         }
1501         /* seek for bytes based streams */
1502         for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1503         {
1504             if( p_stream->i_activated && p_stream->i_samplesize )
1505             {
1506                 AVI_StreamSeek( p_input, p_avi, i_stream, i_date );
1507 //                p_avi->i_time = __MAX( AVI_GetPTS( p_stream ), p_avi->i_time );
1508             }
1509         }
1510         msg_Dbg( p_input, "seek: %lld secondes", p_avi->i_time /1000000 );
1511         /* set true movie time */
1512 #endif
1513         if( !p_avi->i_time )
1514         {
1515             p_avi->i_time = i_date;
1516         }
1517 #undef p_stream
1518         return( 1 );
1519     }
1520     else
1521     {
1522         msg_Err( p_input, "shouldn't yet be executed" );
1523         return( -1 );
1524     }
1525 }
1526
1527 /*****************************************************************************
1528  * AVIDemux_Seekable: reads and demuxes data packets for stream seekable
1529  *****************************************************************************
1530  * AVIDemux: reads and demuxes data packets
1531  *****************************************************************************
1532  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1533  *****************************************************************************/
1534 typedef struct avi_stream_toread_s
1535
1536     int i_ok;
1537
1538     int i_toread;
1539     
1540     off_t i_posf; // where we will read : 
1541                   // if i_idxposb == 0 : begining of chunk (+8 to acces data)
1542                   // else : point on data directly
1543 } avi_stream_toread_t;
1544
1545 static int AVIDemux_Seekable( input_thread_t *p_input )
1546 {
1547     int i_stream;
1548     int b_stream;
1549
1550     // cannot be more than 100 stream (dcXX or wbXX)
1551     avi_stream_toread_t toread[100]; 
1552
1553     demux_sys_t *p_avi = p_input->p_demux_data;
1554
1555     /* detect new selected/unselected streams */
1556     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1557     {
1558 #define p_stream    p_avi->pp_info[i_stream]
1559         if( p_stream->p_es )
1560         {
1561             if( p_stream->p_es->p_decoder_fifo &&
1562                 !p_stream->i_activated )
1563             {
1564                 AVI_StreamStart( p_input, p_avi, i_stream );
1565             }
1566             else
1567             if( !p_stream->p_es->p_decoder_fifo &&
1568                 p_stream->i_activated )
1569             {
1570                 AVI_StreamStop( p_input, p_avi, i_stream );
1571             }
1572         }       
1573 #undef  p_stream
1574     }
1575
1576     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1577     {
1578         mtime_t i_date;
1579         int i_percent;
1580         /* first wait for empty buffer, arbitrary time FIXME */
1581 //        msleep( DEFAULT_PTS_DELAY );
1582
1583         i_date = (mtime_t)1000000 *
1584                  (mtime_t)p_avi->i_length *
1585                  (mtime_t)AVI_TellAbsolute( p_input ) /
1586                  (mtime_t)p_input->stream.p_selected_area->i_size;
1587         i_percent = 100 * AVI_TellAbsolute( p_input ) / 
1588                         p_input->stream.p_selected_area->i_size;
1589
1590 //        input_ClockInit( p_input->stream.p_selected_program );
1591         AVISeek( p_input, i_date, i_percent);
1592     }
1593
1594     
1595     /* wait for the good time */
1596
1597     p_avi->i_pcr = p_avi->i_time * 9 / 100;
1598
1599     input_ClockManageRef( p_input,
1600                           p_input->stream.p_selected_program,
1601                           p_avi->i_pcr ); 
1602
1603
1604     p_avi->i_time += 100*1000;  /* read 100ms */
1605
1606     /* init toread */
1607     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1608     {
1609 #define p_stream    p_avi->pp_info[i_stream]
1610         mtime_t i_dpts;
1611
1612         toread[i_stream].i_ok = p_stream->i_activated;
1613
1614         if( p_stream->i_idxposc < p_stream->i_idxnb )
1615         {
1616             toread[i_stream].i_posf = 
1617                 p_stream->p_index[p_stream->i_idxposc].i_pos;
1618            if( p_stream->i_idxposb > 0 )
1619            {
1620                 toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
1621            }
1622         }
1623         else
1624         { 
1625             toread[i_stream].i_posf = -1;
1626         }
1627
1628         i_dpts = p_avi->i_time - AVI_GetPTS( p_stream  );
1629
1630         if( p_stream->i_samplesize )
1631         {
1632             toread[i_stream].i_toread = AVI_PTSToByte( p_stream, 
1633                                                        __ABS( i_dpts ) );
1634         }
1635         else
1636         {
1637             toread[i_stream].i_toread = AVI_PTSToChunk( p_stream,
1638                                                         __ABS( i_dpts ) );
1639         }
1640         
1641         if( i_dpts < 0 )
1642         {
1643             toread[i_stream].i_toread *= -1;
1644         }
1645 #undef  p_stream
1646     }
1647     
1648     b_stream = 0;
1649     
1650     for( ;; )
1651     {
1652 #define p_stream    p_avi->pp_info[i_stream]
1653         int b_done;
1654         pes_packet_t    *p_pes;
1655         off_t i_pos;
1656         int i;
1657         int i_size;
1658         
1659         /* search for first chunk to be read */
1660         for( i = 0, b_done = 1, i_pos = -1; i < p_avi->i_streams; i++ )
1661         {
1662             if( !toread[i].i_ok ||
1663                 AVI_GetDPTS( p_avi->pp_info[i],
1664                              toread[i].i_toread ) <= -25 * 1000 )
1665             {
1666                 continue;
1667             }
1668
1669             if( toread[i].i_toread > 0 )
1670             {
1671                 b_done = 0; // not yet finished
1672             }
1673
1674             if( toread[i].i_posf > 0 )
1675             {
1676                 if( i_pos == -1 || i_pos > toread[i_stream].i_posf )
1677                 {
1678                     i_stream = i;
1679                     i_pos = toread[i].i_posf;
1680                 }
1681             }
1682         }
1683
1684         if( b_done )
1685         {
1686 //            return( b_stream ? 1 : 0 );
1687             return( 1 );
1688         }
1689         
1690         if( i_pos == -1 )
1691         {
1692             /* no valid index, we will parse directly the stream */
1693             if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin )
1694             {
1695                 AVI_SeekAbsolute( p_input, p_avi->i_movi_lastchunk_pos );
1696                 if( !AVI_PacketNext( p_input ) )
1697                 {
1698                     return( 0 );
1699                 }
1700             }
1701             else
1702             {
1703                 AVI_SeekAbsolute( p_input, p_avi->i_movi_begin );
1704             }
1705
1706             for( ;; )
1707             {
1708                 avi_packet_t avi_pk;
1709
1710                 if( !AVI_PacketGetHeader( p_input, &avi_pk ) )
1711                 {
1712                     msg_Err( p_input, "cannot get packet header" );
1713                     return( 0 );
1714                 }
1715                 if( avi_pk.i_stream >= p_avi->i_streams ||
1716                     ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1717                 {
1718                     switch( avi_pk.i_fourcc )
1719                     {
1720                         case AVIFOURCC_LIST:
1721                             AVI_SkipBytes( p_input, 12 );
1722                             break;
1723                         default:
1724                             if( !AVI_PacketNext( p_input ) )
1725                             {
1726                                 msg_Err( p_input, "cannot skip packet" );
1727                                 return( 0 );
1728                             }
1729                             break;
1730                     }
1731                     continue;
1732                 }
1733                 else
1734                 {
1735                     /* add this chunk to the index */
1736                     AVIIndexEntry_t index;
1737                     
1738                     index.i_id = avi_pk.i_fourcc;
1739                     index.i_flags = 
1740                        AVI_GetKeyFlag(p_avi->pp_info[avi_pk.i_stream]->i_codec,
1741                                       avi_pk.i_peek);
1742                     index.i_pos = avi_pk.i_pos;
1743                     index.i_length = avi_pk.i_size;
1744                     AVI_IndexAddEntry( p_avi, avi_pk.i_stream, &index );
1745
1746                     i_stream = avi_pk.i_stream;
1747                     /* do we will read this data ? */
1748                     if( AVI_GetDPTS( p_stream,
1749                              toread[i_stream].i_toread ) > -25 * 1000 )
1750                     {
1751                         break;
1752                     }
1753                     else
1754                     {
1755                         if( !AVI_PacketNext( p_input ) )
1756                         {
1757                             msg_Err( p_input, "cannot skip packet" );
1758                             return( 0 );
1759                         }
1760                     }
1761                 }
1762             }
1763             
1764         }
1765         else
1766         {
1767             AVI_SeekAbsolute( p_input, i_pos );
1768         }
1769
1770         /* read thoses data */
1771         if( p_stream->i_samplesize )
1772         {
1773             i_size = __MIN( p_stream->p_index[p_stream->i_idxposc].i_length - 
1774                                 p_stream->i_idxposb,
1775                                 100 * 1024 ); // 10Ko max
1776 //                            toread[i_stream].i_toread );
1777         }
1778         else
1779         {
1780             i_size = p_stream->p_index[p_stream->i_idxposc].i_length;
1781         }
1782
1783         if( p_stream->i_idxposb == 0 )
1784         {
1785             i_size += 8; // need to read and skip header
1786         }
1787
1788         if( input_ReadInPES( p_input, &p_pes, __EVEN( i_size ) ) < 0 )
1789         {
1790             msg_Err( p_input, "failled reading data" );
1791             toread[i_stream].i_ok = 0;
1792             continue;
1793         }
1794
1795         if( i_size % 2 )    // read was padded on word boundary
1796         {
1797             p_pes->p_last->p_payload_end--;
1798             p_pes->i_pes_size--;
1799         }
1800         // skip header
1801         if( p_stream->i_idxposb == 0 )
1802         {
1803             p_pes->p_first->p_payload_start += 8;
1804             p_pes->i_pes_size -= 8;
1805         }
1806
1807         p_pes->i_pts = AVI_GetPTS( p_stream );
1808        
1809         /* read data */
1810         if( p_stream->i_samplesize )
1811         {
1812             if( p_stream->i_idxposb == 0 )
1813             {
1814                 i_size -= 8;
1815             }
1816             toread[i_stream].i_toread -= i_size;
1817             p_stream->i_idxposb += i_size;
1818             if( p_stream->i_idxposb >= 
1819                     p_stream->p_index[p_stream->i_idxposc].i_length )
1820             {
1821                 p_stream->i_idxposb = 0;
1822                 p_stream->i_idxposc++;
1823             }
1824         }
1825         else
1826         {
1827             toread[i_stream].i_toread--;
1828             p_stream->i_idxposc++;
1829         }
1830
1831         if( p_stream->i_idxposc < p_stream->i_idxnb)             
1832         {
1833             toread[i_stream].i_posf = 
1834                 p_stream->p_index[p_stream->i_idxposc].i_pos;
1835             if( p_stream->i_idxposb > 0 )
1836             {
1837                 toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
1838             }
1839             
1840         }
1841         else
1842         {
1843             toread[i_stream].i_posf = -1;
1844         }
1845
1846         b_stream = 1; // at least one read succeed
1847         
1848         if( p_stream->p_es && p_stream->p_es->p_decoder_fifo )
1849         {
1850             p_pes->i_dts =
1851                 p_pes->i_pts = 
1852                     input_ClockGetTS( p_input,
1853                                       p_input->stream.p_selected_program,
1854                                       p_pes->i_pts * 9/100);
1855             
1856             input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
1857         }
1858         else
1859         {
1860             input_DeletePES( p_input->p_method_data, p_pes );
1861         }
1862     }
1863     
1864 }
1865
1866
1867 /*****************************************************************************
1868  * AVIDemux_UnSeekable: reads and demuxes data packets for unseekable
1869  *                       file
1870  *****************************************************************************
1871  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1872  *****************************************************************************/
1873 static int AVIDemux_UnSeekable( input_thread_t *p_input )
1874 {
1875     demux_sys_t     *p_avi = p_input->p_demux_data;
1876     avi_stream_t *p_stream_master;
1877     int     i_stream;
1878     int     b_audio;
1879     int     i_packet;
1880
1881     /* *** send audio data to decoder only if rate == DEFAULT_RATE *** */
1882     vlc_mutex_lock( &p_input->stream.stream_lock );
1883     b_audio = p_input->stream.control.i_rate == DEFAULT_RATE;
1884     vlc_mutex_unlock( &p_input->stream.stream_lock );    
1885
1886     input_ClockManageRef( p_input,
1887                           p_input->stream.p_selected_program,
1888                           p_avi->i_pcr );
1889     /* *** find master stream for data packet skipping algo *** */
1890     /* *** -> first video, if any, or first audio ES *** */
1891     for( i_stream = 0, p_stream_master = NULL; 
1892             i_stream < p_avi->i_streams; i_stream++ )
1893     {
1894 #define p_stream    p_avi->pp_info[i_stream]
1895         if( p_stream->p_es &&
1896             p_stream->p_es->p_decoder_fifo )
1897         {
1898             if( p_stream->i_cat == VIDEO_ES )
1899             {
1900                 p_stream_master = p_stream;
1901                 break;
1902             }
1903             if( p_stream->i_cat == AUDIO_ES && !p_stream_master )
1904             {
1905                 p_stream_master = p_stream;
1906             }
1907         }
1908 #undef p_stream
1909     }
1910     if( !p_stream_master )
1911     {
1912         msg_Err( p_input, "no more stream selected" );
1913         return( 0 );
1914     }
1915
1916     p_avi->i_pcr = AVI_GetPTS( p_stream_master ) * 9 / 100;
1917     
1918     for( i_packet = 0; i_packet < 10; i_packet++)
1919     {
1920 #define p_stream    p_avi->pp_info[avi_pk.i_stream]
1921
1922         avi_packet_t    avi_pk;
1923
1924         if( !AVI_PacketGetHeader( p_input, &avi_pk ) )
1925         {
1926             return( 0 );
1927         }
1928 //        AVI_ParseStreamHeader( avi_pk.i_fourcc, &i_stream, &i_cat );
1929
1930         if( avi_pk.i_stream >= p_avi->i_streams ||
1931             ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1932         {
1933             /* we haven't found an audio or video packet:
1934                 - we have seek, found first next packet
1935                 - others packets could be found, skip them
1936             */
1937             switch( avi_pk.i_fourcc )
1938             {
1939                 case AVIFOURCC_JUNK:
1940                 case AVIFOURCC_LIST:
1941                     return( AVI_PacketNext( p_input ) ? 1 : 0 );
1942                 case AVIFOURCC_idx1:
1943                     return( 0 );    // eof
1944                 default:
1945                     msg_Warn( p_input, 
1946                               "seems to have lost position, resync" );
1947                     if( !AVI_PacketSearch( p_input ) )
1948                     {
1949                         msg_Err( p_input, "resync failed" );
1950                         return( -1 );
1951                     }
1952             }
1953         }
1954         else
1955         {  
1956             /* do will send this packet to decoder ? */
1957             if( ( !b_audio && avi_pk.i_cat == AUDIO_ES )||
1958                 !p_stream->p_es ||
1959                 !p_stream->p_es->p_decoder_fifo )
1960             {
1961                 if( !AVI_PacketNext( p_input ) )
1962                 {
1963                     return( 0 );
1964                 }
1965             }
1966             else
1967             {
1968                 /* it's a selected stream, check for time */
1969                 if( __ABS( AVI_GetPTS( p_stream ) - 
1970                             AVI_GetPTS( p_stream_master ) )< 600*1000 )
1971                 {
1972                     /* load it and send to decoder */
1973                     pes_packet_t    *p_pes;
1974                     if( !AVI_PacketRead( p_input, &avi_pk, &p_pes ) || !p_pes)
1975                     {
1976                         return( -1 );
1977                     }
1978                     p_pes->i_pts = 
1979                         input_ClockGetTS( p_input, 
1980                                           p_input->stream.p_selected_program, 
1981                                           AVI_GetPTS( p_stream ) * 9/100);
1982                     input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
1983                 }
1984                 else
1985                 {
1986                     if( !AVI_PacketNext( p_input ) )
1987                     {
1988                         return( 0 );
1989                     }
1990                 }
1991             }
1992
1993             /* *** update stream time position *** */
1994             if( p_stream->i_samplesize )
1995             {
1996                 p_stream->i_idxposb += avi_pk.i_size;
1997             }
1998             else
1999             {
2000                 p_stream->i_idxposc++;
2001             }
2002
2003         }
2004
2005 #undef p_stream     
2006     }
2007
2008     return( 1 );
2009 }
2010