* all: move "wave format tag to fourcc" from demuxers to codecs.h
[vlc.git] / 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.55 2003/08/18 00:17:44 fenrir Exp $
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include <stdlib.h>                                      /* malloc(), free() */
27 #include <string.h>                                              /* strdup() */
28 #include <errno.h>
29 #include <sys/types.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/input.h>
33
34 #include "vlc_video.h"
35
36 #include "libavi.h"
37
38 #define __AVI_SUBTITLE__ 1
39
40 #ifdef __AVI_SUBTITLE__
41 #   include "../util/sub.h"
42 #endif
43 #include "avi.h"
44
45 /*****************************************************************************
46  * Local prototypes
47  *****************************************************************************/
48 static int    AVIInit   ( vlc_object_t * );
49 static void __AVIEnd    ( vlc_object_t * );
50 static int    AVISeek   ( input_thread_t *, mtime_t, int );
51 static int    AVIDemux_Seekable  ( input_thread_t * );
52 static int    AVIDemux_UnSeekable( input_thread_t *p_input );
53
54 #define AVIEnd(a) __AVIEnd(VLC_OBJECT(a))
55 #define FREE( p ) if( p ) { free( p ); (p) = NULL; }
56 /*****************************************************************************
57  * Module descriptor
58  *****************************************************************************/
59 vlc_module_begin();
60     add_category_hint( N_("avi-demuxer"), NULL, VLC_TRUE );
61         add_bool( "avi-interleaved", 0, NULL,
62                   N_("force interleaved method"),
63                   N_("force interleaved method"), VLC_TRUE );
64         add_bool( "avi-index", 0, NULL,
65                   N_("force index creation"),
66                   N_("force index creation"), VLC_TRUE );
67
68     set_description( N_("AVI demuxer") );
69     set_capability( "demux", 212 );
70     set_callbacks( AVIInit, __AVIEnd );
71 vlc_module_end();
72
73 static vlc_fourcc_t GetFOURCC( byte_t *p_buff )
74 {
75     return VLC_FOURCC( p_buff[0], p_buff[1], p_buff[2], p_buff[3] );
76 }
77
78 static inline off_t __EVEN( off_t i )
79 {
80     return (i & 1) ? i + 1 : i;
81 }
82
83 #define __ABS( x ) ( (x) < 0 ? (-(x)) : (x) )
84
85 /* read data in a pes */
86 static int input_ReadInPES( input_thread_t *p_input,
87                             pes_packet_t **pp_pes,
88                             size_t i_size )
89 {
90     pes_packet_t *p_pes;
91     data_packet_t *p_data;
92
93
94     if( !(p_pes = input_NewPES( p_input->p_method_data ) ) )
95     {
96         pp_pes = NULL;
97         return -1;
98     }
99
100     *pp_pes = p_pes;
101
102     if( !i_size )
103     {
104         p_pes->p_first =
105             p_pes->p_last  =
106                 input_NewPacket( p_input->p_method_data, 0 );
107         p_pes->i_nb_data = 1;
108         p_pes->i_pes_size = 0;
109         return 0;
110     }
111
112     p_pes->i_nb_data = 0;
113     p_pes->i_pes_size = 0;
114
115     while( p_pes->i_pes_size < i_size )
116     {
117         int i_read;
118
119         i_read = input_SplitBuffer(p_input,
120                                    &p_data,
121                                    __MIN( i_size -
122                                           p_pes->i_pes_size, 2048 ) );
123         if( i_read <= 0 )
124         {
125             /* should occur only with EOF and max allocation reached 
126              * it safer to  return an error */
127             /* free pes */
128             input_DeletePES( p_input->p_method_data, p_pes );
129             return -1;
130         }
131
132         if( !p_pes->p_first )
133         {
134             p_pes->p_first = p_data;
135         }
136         else
137         {
138             p_pes->p_last->p_next = p_data;
139         }
140         p_pes->p_last = p_data;
141         p_pes->i_nb_data++;
142         p_pes->i_pes_size += i_read;
143     }
144
145
146     return p_pes->i_pes_size;
147 }
148
149 /* check if the file is interleaved */
150 static vlc_bool_t AVI_Interleaved( input_thread_t *p_input );
151
152 /* Test if it seems that it's a key frame */
153 static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, uint8_t *p_byte )
154 {
155     switch( i_fourcc )
156     {
157         case FOURCC_DIV1:
158             /* we have:
159              *  startcode:      0x00000100   32bits
160              *  framenumber     ?             5bits
161              *  piture type     0(I),1(P)     2bits
162              */
163             if( GetDWBE( p_byte ) != 0x00000100 )
164             {
165                 /* it's not an msmpegv1 stream, strange...*/
166                 return AVIIF_KEYFRAME;
167             }
168             else
169             {
170                 return p_byte[4] & 0x06 ? 0 : AVIIF_KEYFRAME;
171             }
172         case FOURCC_DIV2:
173         case FOURCC_DIV3:   // wmv1 also
174             /* we have
175              *  picture type    0(I),1(P)     2bits
176              */
177             return p_byte[0] & 0xC0 ? 0 : AVIIF_KEYFRAME;
178         case FOURCC_mp4v:
179             /* we should find first occurence of 0x000001b6 (32bits)
180              *  startcode:      0x000001b6   32bits
181              *  piture type     0(I),1(P)     2bits
182              */
183             if( GetDWBE( p_byte ) != 0x000001b6 )
184             {
185                 /* not true , need to find the first VOP header */
186                 return AVIIF_KEYFRAME;
187             }
188             else
189             {
190                 return p_byte[4] & 0xC0 ? 0 : AVIIF_KEYFRAME;
191             }
192         default:
193             /* I can't do it, so say yes */
194             return AVIIF_KEYFRAME;
195     }
196 }
197
198 vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t i_codec )
199 {
200     switch( i_cat )
201     {
202         case AUDIO_ES:
203             wf_tag_to_fourcc( i_codec, &i_codec, NULL );
204             return i_codec;
205
206         case VIDEO_ES:
207             // XXX DIV1 <- msmpeg4v1, DIV2 <- msmpeg4v2, DIV3 <- msmpeg4v3, mp4v for mpeg4
208             switch( i_codec )
209             {
210                 case FOURCC_DIV1:
211                 case FOURCC_div1:
212                 case FOURCC_MPG4:
213                 case FOURCC_mpg4:
214                     return FOURCC_DIV1;
215                 case FOURCC_DIV2:
216                 case FOURCC_div2:
217                 case FOURCC_MP42:
218                 case FOURCC_mp42:
219                 case FOURCC_MPG3:
220                 case FOURCC_mpg3:
221                     return FOURCC_DIV2;
222                 case FOURCC_div3:
223                 case FOURCC_MP43:
224                 case FOURCC_mp43:
225                 case FOURCC_DIV3:
226                 case FOURCC_DIV4:
227                 case FOURCC_div4:
228                 case FOURCC_DIV5:
229                 case FOURCC_div5:
230                 case FOURCC_DIV6:
231                 case FOURCC_div6:
232                 case FOURCC_AP41:
233                 case FOURCC_3IV1:
234                 case FOURCC_3iv1:
235                 case FOURCC_3IVD:
236                 case FOURCC_3ivd:
237                 case FOURCC_3VID:
238                 case FOURCC_3vid:
239                     return FOURCC_DIV3;
240                 case FOURCC_DIVX:
241                 case FOURCC_divx:
242                 case FOURCC_MP4S:
243                 case FOURCC_mp4s:
244                 case FOURCC_M4S2:
245                 case FOURCC_m4s2:
246                 case FOURCC_xvid:
247                 case FOURCC_XVID:
248                 case FOURCC_XviD:
249                 case FOURCC_DX50:
250                 case FOURCC_mp4v:
251                 case FOURCC_4:
252                 case FOURCC_3IV2:
253                 case FOURCC_3iv2:
254                     return FOURCC_mp4v;
255             }
256         default:
257             return VLC_FOURCC( 'u', 'n', 'd', 'f' );
258     }
259 }
260
261 static void AVI_ParseStreamHeader( vlc_fourcc_t i_id,
262                                    int *pi_number, int *pi_type )
263 {
264 #define SET_PTR( p, v ) if( p ) *(p) = (v);
265     int c1, c2;
266
267     c1 = ((uint8_t *)&i_id)[0];
268     c2 = ((uint8_t *)&i_id)[1];
269
270     if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
271     {
272         SET_PTR( pi_number, 100 ); /* > max stream number */
273         SET_PTR( pi_type, UNKNOWN_ES );
274     }
275     else
276     {
277         SET_PTR( pi_number, (c1 - '0') * 10 + (c2 - '0' ) );
278         switch( VLC_TWOCC( ((uint8_t *)&i_id)[2], ((uint8_t *)&i_id)[3] ) )
279         {
280             case AVITWOCC_wb:
281                 SET_PTR( pi_type, AUDIO_ES );
282                 break;
283             case AVITWOCC_dc:
284             case AVITWOCC_db:
285                 SET_PTR( pi_type, VIDEO_ES );
286                 break;
287             default:
288                 SET_PTR( pi_type, UNKNOWN_ES );
289                 break;
290         }
291     }
292 #undef SET_PTR
293 }
294
295 static int AVI_PacketGetHeader( input_thread_t *p_input, avi_packet_t *p_pk )
296 {
297     uint8_t  *p_peek;
298
299     if( input_Peek( p_input, &p_peek, 16 ) < 16 )
300     {
301         return VLC_EGENERIC;
302     }
303     p_pk->i_fourcc  = GetFOURCC( p_peek );
304     p_pk->i_size    = GetDWLE( p_peek + 4 );
305     p_pk->i_pos     = AVI_TellAbsolute( p_input );
306     if( p_pk->i_fourcc == AVIFOURCC_LIST || p_pk->i_fourcc == AVIFOURCC_RIFF )
307     {
308         p_pk->i_type = GetFOURCC( p_peek + 8 );
309     }
310     else
311     {
312         p_pk->i_type = 0;
313     }
314
315     memcpy( p_pk->i_peek, p_peek + 8, 8 );
316
317     AVI_ParseStreamHeader( p_pk->i_fourcc, &p_pk->i_stream, &p_pk->i_cat );
318     return VLC_SUCCESS;
319 }
320
321 static int AVI_PacketNext( input_thread_t *p_input )
322 {
323     avi_packet_t    avi_ck;
324
325     if( AVI_PacketGetHeader( p_input, &avi_ck ) )
326     {
327         return VLC_EGENERIC;
328     }
329     //msg_Dbg( p_input, "skip %4.4s:%4.4s", (char*)&avi_ck.i_fourcc, (char*)&avi_ck.i_type );
330
331     if( avi_ck.i_fourcc == AVIFOURCC_LIST && ( avi_ck.i_type == AVIFOURCC_rec || avi_ck.i_type == AVIFOURCC_movi ) )
332     {
333         return AVI_SkipBytes( p_input, 12 );
334     }
335     else if( avi_ck.i_fourcc == AVIFOURCC_RIFF && avi_ck.i_type == AVIFOURCC_AVIX )
336     {
337         return AVI_SkipBytes( p_input, 24 );
338     }
339     else
340     {
341         return AVI_SkipBytes( p_input, __EVEN( avi_ck.i_size ) + 8 );
342     }
343 }
344 static int AVI_PacketRead( input_thread_t   *p_input,
345                            avi_packet_t     *p_pk,
346                            pes_packet_t     **pp_pes )
347 {
348     size_t i_size;
349     vlc_bool_t b_pad;
350
351     i_size = __EVEN( p_pk->i_size + 8 );
352     b_pad  = ( i_size != p_pk->i_size + 8 );
353
354     if( input_ReadInPES( p_input, pp_pes, i_size ) != (ssize_t)i_size )
355     {
356         return VLC_EGENERIC;
357     }
358     (*pp_pes)->p_first->p_payload_start += 8;
359     (*pp_pes)->i_pes_size -= 8;
360
361     if( b_pad )
362     {
363         (*pp_pes)->p_last->p_payload_end--;
364         (*pp_pes)->i_pes_size--;
365     }
366
367     return VLC_SUCCESS;
368 }
369
370 static int AVI_PacketSearch( input_thread_t *p_input )
371 {
372     demux_sys_t     *p_avi = p_input->p_demux_data;
373
374     avi_packet_t    avi_pk;
375     for( ;; )
376     {
377         if( AVI_SkipBytes( p_input, 1 ) )
378         {
379             return VLC_EGENERIC;
380         }
381         AVI_PacketGetHeader( p_input, &avi_pk );
382         if( avi_pk.i_stream < p_avi->i_streams &&
383             ( avi_pk.i_cat == AUDIO_ES || avi_pk.i_cat == VIDEO_ES ) )
384         {
385             return VLC_SUCCESS;
386         }
387         switch( avi_pk.i_fourcc )
388         {
389             case AVIFOURCC_JUNK:
390             case AVIFOURCC_LIST:
391             case AVIFOURCC_RIFF:
392             case AVIFOURCC_idx1:
393                 return VLC_SUCCESS;
394         }
395     }
396 }
397
398
399 static void __AVI_AddEntryIndex( avi_stream_t *p_info,
400                                  AVIIndexEntry_t *p_index)
401 {
402     if( p_info->p_index == NULL )
403     {
404         p_info->i_idxmax = 16384;
405         p_info->i_idxnb = 0;
406         if( !( p_info->p_index = calloc( p_info->i_idxmax,
407                                   sizeof( AVIIndexEntry_t ) ) ) )
408         {
409             return;
410         }
411     }
412     if( p_info->i_idxnb >= p_info->i_idxmax )
413     {
414         p_info->i_idxmax += 16384;
415         if( !( p_info->p_index = realloc( (void*)p_info->p_index,
416                            p_info->i_idxmax *
417                            sizeof( AVIIndexEntry_t ) ) ) )
418         {
419             return;
420         }
421     }
422     /* calculate cumulate length */
423     if( p_info->i_idxnb > 0 )
424     {
425         p_index->i_lengthtotal =
426             p_info->p_index[p_info->i_idxnb - 1].i_length +
427                 p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal;
428     }
429     else
430     {
431         p_index->i_lengthtotal = 0;
432     }
433
434     p_info->p_index[p_info->i_idxnb] = *p_index;
435     p_info->i_idxnb++;
436
437 }
438
439 static void AVI_IndexAddEntry( demux_sys_t *p_avi,
440                                int i_stream,
441                                AVIIndexEntry_t *p_index)
442 {
443     __AVI_AddEntryIndex( p_avi->pp_info[i_stream],
444                          p_index );
445     if( p_avi->i_movi_lastchunk_pos < p_index->i_pos )
446     {
447         p_avi->i_movi_lastchunk_pos = p_index->i_pos;
448     }
449 }
450
451 static int AVI_IndexLoad_idx1( input_thread_t *p_input )
452 {
453     demux_sys_t *p_avi = p_input->p_demux_data;
454
455     avi_chunk_list_t    *p_riff;
456     avi_chunk_list_t    *p_movi;
457     avi_chunk_idx1_t    *p_idx1;
458
459     unsigned int i_stream;
460     unsigned int i_index;
461     off_t   i_offset;
462
463     p_riff = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root,
464                                                AVIFOURCC_RIFF, 0);
465
466     p_idx1 = (avi_chunk_idx1_t*)AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0);
467     p_movi = (avi_chunk_list_t*)AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
468
469     if( !p_idx1 )
470     {
471         msg_Warn( p_input, "cannot find idx1 chunk, no index defined" );
472         return VLC_EGENERIC;
473     }
474
475     /* *** calculate offset *** */
476     if( p_idx1->i_entry_count > 0 &&
477         p_idx1->entry[0].i_pos < p_movi->i_chunk_pos )
478     {
479         i_offset = p_movi->i_chunk_pos + 8;
480     }
481     else
482     {
483         i_offset = 0;
484     }
485
486     for( i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )
487     {
488         unsigned int i_cat;
489
490         AVI_ParseStreamHeader( p_idx1->entry[i_index].i_fourcc,
491                                &i_stream,
492                                &i_cat );
493         if( i_stream < p_avi->i_streams &&
494             i_cat == p_avi->pp_info[i_stream]->i_cat )
495         {
496             AVIIndexEntry_t index;
497             index.i_id      = p_idx1->entry[i_index].i_fourcc;
498             index.i_flags   =
499                 p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME);
500             index.i_pos     = p_idx1->entry[i_index].i_pos + i_offset;
501             index.i_length  = p_idx1->entry[i_index].i_length;
502             AVI_IndexAddEntry( p_avi, i_stream, &index );
503         }
504     }
505     return VLC_SUCCESS;
506 }
507
508 static void __Parse_indx( input_thread_t    *p_input,
509                           int               i_stream,
510                           avi_chunk_indx_t  *p_indx )
511 {
512     demux_sys_t         *p_avi    = p_input->p_demux_data;
513     AVIIndexEntry_t     index;
514     int32_t             i;
515
516     msg_Dbg( p_input, "loading subindex(0x%x) %d entries", p_indx->i_indextype, p_indx->i_entriesinuse );
517     if( p_indx->i_indexsubtype == 0 )
518     {
519         for( i = 0; i < p_indx->i_entriesinuse; i++ )
520         {
521             index.i_id      = p_indx->i_id;
522             index.i_flags   = p_indx->idx.std[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
523             index.i_pos     = p_indx->i_baseoffset + p_indx->idx.std[i].i_offset - 8;
524             index.i_length  = p_indx->idx.std[i].i_size&0x7fffffff;
525
526             AVI_IndexAddEntry( p_avi, i_stream, &index );
527         }
528     }
529     else if( p_indx->i_indexsubtype == AVI_INDEX_2FIELD )
530     {
531         for( i = 0; i < p_indx->i_entriesinuse; i++ )
532         {
533             index.i_id      = p_indx->i_id;
534             index.i_flags   = p_indx->idx.field[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
535             index.i_pos     = p_indx->i_baseoffset + p_indx->idx.field[i].i_offset - 8;
536             index.i_length  = p_indx->idx.field[i].i_size;
537
538             AVI_IndexAddEntry( p_avi, i_stream, &index );
539         }
540     }
541     else
542     {
543         msg_Warn( p_input, "unknow subtype index(0x%x)", p_indx->i_indexsubtype );
544     }
545 }
546
547 static void AVI_IndexLoad_indx( input_thread_t *p_input )
548 {
549     demux_sys_t         *p_avi = p_input->p_demux_data;
550     unsigned int        i_stream;
551     int32_t             i;
552
553     avi_chunk_list_t    *p_riff;
554     avi_chunk_list_t    *p_hdrl;
555
556     p_riff = (void*)AVI_ChunkFind( &p_avi->ck_root,
557                                    AVIFOURCC_RIFF, 0);
558     p_hdrl = (void*)AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
559
560     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
561     {
562         avi_chunk_list_t    *p_strl;
563         avi_chunk_indx_t    *p_indx;
564
565 #define p_stream  p_avi->pp_info[i_stream]
566         p_strl = (void*)AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream );
567         p_indx = (void*)AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0 );
568
569         if( !p_indx )
570         {
571             msg_Warn( p_input, "cannot find indx (misdetect/broken OpenDML file?)" );
572             continue;
573         }
574
575         if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS )
576         {
577             __Parse_indx( p_input, i_stream, p_indx );
578         }
579         else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )
580         {
581             avi_chunk_indx_t    ck_sub;
582             for( i = 0; i < p_indx->i_entriesinuse; i++ )
583             {
584                 if( AVI_SeekAbsolute( p_input, p_indx->idx.super[i].i_offset ) )
585                 {
586                     break;
587                 }
588
589                 if( AVI_ChunkRead( p_input, &ck_sub, NULL, p_avi->b_seekable ) )
590                 {
591                     break;
592                 }
593             }
594         }
595         else
596         {
597             msg_Warn( p_input, "unknow type index(0x%x)", p_indx->i_indextype );
598         }
599 #undef p_stream
600     }
601 }
602
603 static void AVI_IndexLoad( input_thread_t *p_input )
604 {
605     demux_sys_t *p_avi = p_input->p_demux_data;
606     unsigned int i_stream;
607
608     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
609     {
610         p_avi->pp_info[i_stream]->i_idxnb  = 0;
611         p_avi->pp_info[i_stream]->i_idxmax = 0;
612         p_avi->pp_info[i_stream]->p_index  = NULL;
613     }
614
615     if( p_avi->b_odml )
616     {
617         AVI_IndexLoad_indx( p_input );
618     }
619     else
620     {
621         if( AVI_IndexLoad_idx1( p_input ) )
622         {
623             /* try indx if idx1 failed as some "normal" file have indx too */
624             AVI_IndexLoad_indx( p_input );
625         }
626     }
627
628     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
629     {
630         msg_Dbg( p_input,
631                 "stream[%d] created %d index entries",
632                 i_stream,
633                 p_avi->pp_info[i_stream]->i_idxnb );
634     }
635 }
636
637 static void AVI_IndexCreate( input_thread_t *p_input )
638 {
639     demux_sys_t *p_avi = p_input->p_demux_data;
640
641     avi_chunk_list_t    *p_riff;
642     avi_chunk_list_t    *p_movi;
643
644     unsigned int i_stream;
645     off_t i_movi_end;
646
647     p_riff = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root,
648                                                AVIFOURCC_RIFF, 0);
649     p_movi = (avi_chunk_list_t*)AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
650
651     if( !p_movi )
652     {
653         msg_Err( p_input, "cannot find p_movi" );
654         return;
655     }
656
657     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
658     {
659         p_avi->pp_info[i_stream]->i_idxnb  = 0;
660         p_avi->pp_info[i_stream]->i_idxmax = 0;
661         p_avi->pp_info[i_stream]->p_index  = NULL;
662     }
663     i_movi_end = __MIN( (off_t)(p_movi->i_chunk_pos + p_movi->i_chunk_size),
664                         p_input->stream.p_selected_area->i_size );
665
666     AVI_SeekAbsolute( p_input, p_movi->i_chunk_pos + 12);
667     msg_Warn( p_input, "creating index from LIST-movi, will take time !" );
668     for( ;; )
669     {
670         avi_packet_t pk;
671
672         if( AVI_PacketGetHeader( p_input, &pk ) )
673         {
674             break;
675         }
676         if( pk.i_stream < p_avi->i_streams &&
677             pk.i_cat == p_avi->pp_info[pk.i_stream]->i_cat )
678         {
679             AVIIndexEntry_t index;
680             index.i_id      = pk.i_fourcc;
681             index.i_flags   =
682                AVI_GetKeyFlag(p_avi->pp_info[pk.i_stream]->i_codec, pk.i_peek);
683             index.i_pos     = pk.i_pos;
684             index.i_length  = pk.i_size;
685             AVI_IndexAddEntry( p_avi, pk.i_stream, &index );
686         }
687         else
688         {
689             switch( pk.i_fourcc )
690             {
691                 case AVIFOURCC_idx1:
692                     if( p_avi->b_odml )
693                     {
694                         avi_chunk_list_t *p_avix;
695                         p_avix = (void*)AVI_ChunkFind( &p_avi->ck_root,
696                                                        AVIFOURCC_RIFF, 1 );
697
698                         msg_Dbg( p_input, "looking for new RIFF chunk" );
699                         if( AVI_SeekAbsolute( p_input, p_avix->i_chunk_pos + 24) )
700                         {
701                             goto print_stat;
702                         }
703                         break;
704                     }
705                     goto print_stat;
706                 case AVIFOURCC_RIFF:
707                         msg_Dbg( p_input, "new RIFF chunk found" );
708                 case AVIFOURCC_rec:
709                 case AVIFOURCC_JUNK:
710                     break;
711                 default:
712                     msg_Warn( p_input, "need resync, probably broken avi" );
713                     if( AVI_PacketSearch( p_input ) )
714                     {
715                         msg_Warn( p_input, "lost sync, abord index creation" );
716                         goto print_stat;
717                     }
718             }
719         }
720
721         if( ( !p_avi->b_odml && pk.i_pos + pk.i_size >= i_movi_end ) ||
722             AVI_PacketNext( p_input ) )
723         {
724             break;
725         }
726     }
727
728 print_stat:
729     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
730     {
731         msg_Dbg( p_input,
732                 "stream[%d] creating %d index entries",
733                 i_stream,
734                 p_avi->pp_info[i_stream]->i_idxnb );
735     }
736 }
737
738
739 /*****************************************************************************
740  * Stream management
741  *****************************************************************************/
742 static vlc_bool_t AVI_StreamStart ( input_thread_t *, demux_sys_t *, int );
743 static int  AVI_StreamSeek   ( input_thread_t *, demux_sys_t *, int, mtime_t );
744 static void AVI_StreamStop   ( input_thread_t *, demux_sys_t *, int );
745 static int  AVI_StreamStopFinishedStreams( input_thread_t *, demux_sys_t * );
746
747 static vlc_bool_t AVI_StreamStart( input_thread_t *p_input,
748                                    demux_sys_t *p_avi, int i_stream )
749 {
750 #define p_stream    p_avi->pp_info[i_stream]
751     if( !p_stream->p_es )
752     {
753         msg_Warn( p_input, "stream[%d] unselectable", i_stream );
754         return VLC_FALSE;
755     }
756     if( p_stream->b_activated )
757     {
758         msg_Warn( p_input, "stream[%d] already selected", i_stream );
759         return VLC_TRUE;
760     }
761
762     if( !p_stream->p_es->p_decoder_fifo )
763     {
764         vlc_mutex_lock( &p_input->stream.stream_lock );
765         input_SelectES( p_input, p_stream->p_es );
766         vlc_mutex_unlock( &p_input->stream.stream_lock );
767     }
768     p_stream->b_activated = p_stream->p_es->p_decoder_fifo ? VLC_TRUE
769                                                            : VLC_FALSE;
770     if( p_stream->b_activated && p_avi->b_seekable)
771     {
772         AVI_StreamSeek( p_input, p_avi, i_stream, p_avi->i_time );
773     }
774
775     return p_stream->b_activated;
776 #undef  p_stream
777 }
778
779 static void    AVI_StreamStop( input_thread_t *p_input,
780                                demux_sys_t *p_avi, int i_stream )
781 {
782 #define p_stream    p_avi->pp_info[i_stream]
783
784     if( !p_stream->b_activated )
785     {
786         msg_Warn( p_input, "stream[%d] already unselected", i_stream );
787         return;
788     }
789
790     if( p_stream->p_es->p_decoder_fifo )
791     {
792         vlc_mutex_lock( &p_input->stream.stream_lock );
793         input_UnselectES( p_input, p_stream->p_es );
794         vlc_mutex_unlock( &p_input->stream.stream_lock );
795     }
796
797
798     p_stream->b_activated = VLC_FALSE;
799
800 #undef  p_stream
801 }
802
803 static int AVI_StreamStopFinishedStreams( input_thread_t *p_input,
804                                            demux_sys_t *p_avi )
805 {
806     unsigned int i_stream;
807     int b_end;
808
809     for( i_stream = 0,b_end = VLC_TRUE;
810             i_stream < p_avi->i_streams; i_stream++ )
811     {
812 #define p_stream    p_avi->pp_info[i_stream]
813         if( p_stream->i_idxposc >= p_stream->i_idxnb )
814         {
815             AVI_StreamStop( p_input, p_avi, i_stream );
816         }
817         else
818         {
819             b_end = VLC_FALSE;
820         }
821 #undef  p_stream
822     }
823     return( b_end );
824 }
825 /****************************************************************************
826  * AVI_MovieGetLength give max streams length in second
827  ****************************************************************************/
828 static mtime_t  AVI_MovieGetLength( input_thread_t *p_input, demux_sys_t *p_avi )
829 {
830     unsigned int i_stream;
831     mtime_t i_maxlength;
832
833     i_maxlength = 0;
834     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
835     {
836 #define p_stream  p_avi->pp_info[i_stream]
837         mtime_t i_length;
838         /* fix length for each stream */
839         if( p_stream->i_idxnb < 1 || !p_stream->p_index )
840         {
841             continue;
842         }
843
844         if( p_stream->i_samplesize )
845         {
846             i_length =
847                 (mtime_t)( p_stream->p_index[p_stream->i_idxnb-1].i_lengthtotal +
848                            p_stream->p_index[p_stream->i_idxnb-1].i_length ) *
849                 (mtime_t)p_stream->i_scale /
850                 (mtime_t)p_stream->i_rate /
851                 (mtime_t)p_stream->i_samplesize;
852         }
853         else
854         {
855             i_length = (mtime_t)p_stream->i_idxnb *
856                        (mtime_t)p_stream->i_scale /
857                        (mtime_t)p_stream->i_rate;
858         }
859
860         msg_Dbg( p_input,
861                  "stream[%d] length:"I64Fd" (based on index)",
862                  i_stream,
863                  i_length );
864         i_maxlength = __MAX( i_maxlength, i_length );
865 #undef p_stream
866     }
867
868     return i_maxlength;
869 }
870
871 /*****************************************************************************
872  * AVIEnd: frees unused data
873  *****************************************************************************/
874 static void __AVIEnd ( vlc_object_t * p_this )
875 {
876     input_thread_t *    p_input = (input_thread_t *)p_this;
877     unsigned int i;
878     demux_sys_t *p_avi = p_input->p_demux_data  ;
879
880     if( p_avi->pp_info )
881     {
882         for( i = 0; i < p_avi->i_streams; i++ )
883         {
884             if( p_avi->pp_info[i] )
885             {
886                 if( p_avi->pp_info[i]->p_index )
887                 {
888                       free( p_avi->pp_info[i]->p_index );
889                 }
890                 free( p_avi->pp_info[i] );
891             }
892         }
893          free( p_avi->pp_info );
894     }
895 #ifdef __AVI_SUBTITLE__
896     if( p_avi->p_sub )
897     {
898         subtitle_Close( p_avi->p_sub );
899         p_avi->p_sub = NULL;
900     }
901 #endif
902     AVI_ChunkFreeRoot( p_input, &p_avi->ck_root );
903
904     FREE( p_input->p_demux_data );
905 }
906
907 /*****************************************************************************
908  * AVIInit: check file and initializes AVI structures
909  *****************************************************************************/
910 static int AVIInit( vlc_object_t * p_this )
911 {
912     input_thread_t *    p_input = (input_thread_t *)p_this;
913     avi_chunk_t         ck_riff;
914     avi_chunk_list_t    *p_riff = (avi_chunk_list_t*)&ck_riff;
915     avi_chunk_list_t    *p_hdrl, *p_movi;
916 #if 0
917     avi_chunk_list_t    *p_INFO;
918     avi_chunk_strz_t    *p_name;
919 #endif
920     avi_chunk_avih_t    *p_avih;
921     demux_sys_t *p_avi;
922     es_descriptor_t *p_es = NULL; /* avoid warning */
923     unsigned int i;
924 #ifdef __AVI_SUBTITLE__
925     mtime_t i_microsecperframe = 0; // for some subtitle format
926 #endif
927
928     vlc_bool_t b_stream_audio, b_stream_video;
929
930     p_input->pf_demux = AVIDemux_Seekable;
931     if( AVI_TestFile( p_input ) )
932     {
933         msg_Warn( p_input, "avi module discarded (invalid header)" );
934         return VLC_EGENERIC;
935     }
936
937     /* Initialize access plug-in structures. */
938     if( p_input->i_mtu == 0 )
939     {
940         /* Improve speed. */
941         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
942     }
943
944     if( !( p_input->p_demux_data =
945                     p_avi = malloc( sizeof(demux_sys_t) ) ) )
946     {
947         msg_Err( p_input, "out of memory" );
948         return VLC_ENOMEM;
949     }
950     memset( p_avi, 0, sizeof( demux_sys_t ) );
951     p_avi->i_time = 0;
952     p_avi->i_pcr  = 0;
953     p_avi->b_seekable = ( ( p_input->stream.b_seekable )
954                         &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
955     p_avi->i_movi_lastchunk_pos = 0;
956     p_avi->b_odml = VLC_FALSE;
957     p_avi->b_interleaved = VLC_FALSE;
958
959     /* *** for unseekable stream, automaticaly use AVIDemux_interleaved *** */
960     if( !p_avi->b_seekable || config_GetInt( p_input, "avi-interleaved" ) )
961     {
962         p_input->pf_demux = AVIDemux_UnSeekable;
963     }
964
965     if( AVI_ChunkReadRoot( p_input, &p_avi->ck_root, p_avi->b_seekable ) )
966     {
967         msg_Err( p_input, "avi module discarded (invalid file)" );
968         return VLC_EGENERIC;
969     }
970     AVI_ChunkDumpDebug( p_input, &p_avi->ck_root );
971
972     if( AVI_ChunkCount( &p_avi->ck_root, AVIFOURCC_RIFF ) > 1 )
973     {
974         int i_count = AVI_ChunkCount( &p_avi->ck_root, AVIFOURCC_RIFF );
975         int i;
976
977         msg_Warn( p_input, "multiple riff -> OpenDML ?" );
978         for( i = 1; i < i_count; i++ )
979         {
980             avi_chunk_list_t *p_avix;
981
982             p_avix = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root,
983                                                        AVIFOURCC_RIFF, i );
984             if( p_avix->i_type == AVIFOURCC_AVIX )
985             {
986                 msg_Warn( p_input, "detected OpenDML file" );
987
988                 p_avi->b_odml = VLC_TRUE;
989                 break;
990             }
991         }
992         p_avi->b_odml = VLC_TRUE;
993     }
994
995
996     p_riff  = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root,
997                                                 AVIFOURCC_RIFF, 0 );
998     p_hdrl  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff,
999                                                 AVIFOURCC_hdrl, 0 );
1000     p_movi  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff,
1001                                                 AVIFOURCC_movi, 0 );
1002 #if 0
1003     p_INFO  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff,
1004                                                 AVIFOURCC_INFO, 0 );
1005     p_name  = (avi_chunk_strz_t*)AVI_ChunkFind( p_INFO,
1006                                                 AVIFOURCC_INAM, 0 );
1007     if( p_name )
1008     {
1009
1010     }
1011 #endif
1012
1013     if( !p_hdrl || !p_movi )
1014     {
1015         msg_Err( p_input, "avi module discarded (invalid file)" );
1016         return VLC_EGENERIC;
1017     }
1018
1019     if( !( p_avih = (avi_chunk_avih_t*)AVI_ChunkFind( p_hdrl,
1020                                                       AVIFOURCC_avih, 0 ) ) )
1021     {
1022         msg_Err( p_input, "cannot find avih chunk" );
1023         return VLC_EGENERIC;
1024     }
1025     p_avi->i_streams = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl );
1026     if( p_avih->i_streams != p_avi->i_streams )
1027     {
1028         msg_Warn( p_input,
1029                   "found %d stream but %d are declared",
1030                   p_avi->i_streams,
1031                   p_avih->i_streams );
1032     }
1033     if( p_avi->i_streams == 0 )
1034     {
1035         AVIEnd( p_input );
1036         msg_Err( p_input, "no stream defined!" );
1037         return VLC_EGENERIC;
1038     }
1039
1040     /*  create one program */
1041     vlc_mutex_lock( &p_input->stream.stream_lock );
1042     if( input_InitStream( p_input, 0 ) == -1)
1043     {
1044         vlc_mutex_unlock( &p_input->stream.stream_lock );
1045         AVIEnd( p_input );
1046         msg_Err( p_input, "cannot init stream" );
1047         return VLC_EGENERIC;
1048     }
1049     if( input_AddProgram( p_input, 0, 0) == NULL )
1050     {
1051         vlc_mutex_unlock( &p_input->stream.stream_lock );
1052         AVIEnd( p_input );
1053         msg_Err( p_input, "cannot add program" );
1054         return VLC_EGENERIC;
1055     }
1056     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
1057     vlc_mutex_unlock( &p_input->stream.stream_lock );
1058
1059     /* print informations on streams */
1060     msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ",
1061              p_avi->i_streams,
1062              p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
1063              p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
1064              p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
1065              p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
1066     {
1067         input_info_category_t *p_cat = input_InfoCategory( p_input, _("Avi") );
1068         input_AddInfo( p_cat, _("Number of Streams"), "%d", p_avi->i_streams );
1069         input_AddInfo( p_cat, _("Flags"), "%s%s%s%s",
1070                        p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
1071                        p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
1072                        p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
1073                        p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
1074     }
1075
1076     /* now read info on each stream and create ES */
1077     p_avi->pp_info = calloc( p_avi->i_streams,
1078                             sizeof( avi_stream_t* ) );
1079     memset( p_avi->pp_info,
1080             0,
1081             sizeof( avi_stream_t* ) * p_avi->i_streams );
1082
1083     for( i = 0 ; i < p_avi->i_streams; i++ )
1084     {
1085         avi_chunk_list_t    *p_avi_strl;
1086         avi_chunk_strh_t    *p_avi_strh;
1087         avi_chunk_strf_auds_t    *p_avi_strf_auds;
1088         avi_chunk_strf_vids_t    *p_avi_strf_vids;
1089         int     i_init_size;
1090         void    *p_init_data;
1091 #define p_info  p_avi->pp_info[i]
1092         p_info = malloc( sizeof(avi_stream_t ) );
1093         memset( p_info, 0, sizeof( avi_stream_t ) );
1094
1095         p_avi_strl = (avi_chunk_list_t*)AVI_ChunkFind( p_hdrl,
1096                                                        AVIFOURCC_strl, i );
1097         p_avi_strh = (avi_chunk_strh_t*)AVI_ChunkFind( p_avi_strl,
1098                                                        AVIFOURCC_strh, 0 );
1099         p_avi_strf_auds = (avi_chunk_strf_auds_t*)
1100             p_avi_strf_vids = (avi_chunk_strf_vids_t*)
1101                 AVI_ChunkFind( p_avi_strl, AVIFOURCC_strf, 0 );
1102
1103         if( !p_avi_strl || !p_avi_strh ||
1104                 ( !p_avi_strf_auds && !p_avi_strf_vids ) )
1105         {
1106             msg_Warn( p_input, "stream[%d] incomlete", i );
1107             continue;
1108         }
1109
1110         /* *** Init p_info *** */
1111         p_info->i_rate  = p_avi_strh->i_rate;
1112         p_info->i_scale = p_avi_strh->i_scale;
1113         p_info->i_samplesize = p_avi_strh->i_samplesize;
1114         msg_Dbg( p_input, "stream[%d] rate:%d scale:%d samplesize:%d",
1115                  i,
1116                  p_info->i_rate, p_info->i_scale, p_info->i_samplesize );
1117         switch( p_avi_strh->i_type )
1118         {
1119             case( AVIFOURCC_auds ):
1120                 p_info->i_cat = AUDIO_ES;
1121                 p_info->i_fourcc =
1122                     AVI_FourccGetCodec( AUDIO_ES,
1123                                         p_avi_strf_auds->p_wf->wFormatTag );
1124                 p_info->i_codec  = p_info->i_fourcc;
1125                 i_init_size = p_avi_strf_auds->i_chunk_size;
1126                 p_init_data = p_avi_strf_auds->p_wf;
1127                 msg_Dbg( p_input, "stream[%d] audio(0x%x) %d channels %dHz %dbits",
1128                         i,
1129                         p_avi_strf_auds->p_wf->wFormatTag,
1130                         p_avi_strf_auds->p_wf->nChannels,
1131                         p_avi_strf_auds->p_wf->nSamplesPerSec,
1132                         p_avi_strf_auds->p_wf->wBitsPerSample );
1133                 {
1134                     char psz_cat[ sizeof("Stream") + 10 ];
1135                     input_info_category_t *p_cat;
1136                     sprintf( psz_cat, _("Stream %d"), i );
1137                     p_cat = input_InfoCategory( p_input, psz_cat );
1138                     input_AddInfo( p_cat, _("Type"), "Audio(0x%x)",
1139                                    p_avi_strf_auds->p_wf->wFormatTag );
1140                     input_AddInfo( p_cat, _("Codec"), "%4.4s",
1141                                    (const char*)&(p_info->i_codec) );
1142                     input_AddInfo( p_cat, _("FOURCC"), "0x%x",
1143                                    p_info->i_codec );
1144                     input_AddInfo( p_cat, _("Channels"), "%d",
1145                                    p_avi_strf_auds->p_wf->nChannels );
1146                     input_AddInfo( p_cat, _("Sample Rate"), "%d",
1147                                    p_avi_strf_auds->p_wf->nSamplesPerSec );
1148                     if( p_avi_strf_auds->p_wf->wBitsPerSample > 0
1149                         && p_info->i_scale != 0 )
1150                     {
1151                         input_AddInfo( p_cat, _("Bits Per Sample"), "%d",
1152                                        p_avi_strf_auds->p_wf->wBitsPerSample );
1153                         input_AddInfo( p_cat, _("Audio Bitrate"), "%d",
1154                                        p_info->i_samplesize * p_info->i_rate
1155                                        / p_info->i_scale );
1156                     }
1157                 }
1158                 break;
1159
1160             case( AVIFOURCC_vids ):
1161                 p_info->i_cat = VIDEO_ES;
1162                 /* XXX quick hack for playing ffmpeg video, I don't know
1163                     who is doing something wrong */
1164                 p_info->i_samplesize = 0;
1165                 p_info->i_fourcc = p_avi_strf_vids->p_bih->biCompression;
1166                 p_info->i_codec =
1167                     AVI_FourccGetCodec( VIDEO_ES, p_info->i_fourcc );
1168                 i_init_size = p_avi_strf_vids->i_chunk_size;
1169                 p_init_data = p_avi_strf_vids->p_bih;
1170                 msg_Dbg( p_input, "stream[%d] video(%4.4s) %dx%d %dbpp %ffps",
1171                         i,
1172                          (char*)&p_avi_strf_vids->p_bih->biCompression,
1173                          p_avi_strf_vids->p_bih->biWidth,
1174                          p_avi_strf_vids->p_bih->biHeight,
1175                          p_avi_strf_vids->p_bih->biBitCount,
1176                          (float)p_info->i_rate /
1177                              (float)p_info->i_scale );
1178                 {
1179                     char psz_cat[ sizeof("Stream") + 10 ];
1180                     input_info_category_t *p_cat;
1181                     sprintf( psz_cat, "Stream %d", i );
1182                     p_cat = input_InfoCategory( p_input, psz_cat );
1183                     input_AddInfo( p_cat, _("Type"), _("Video") );
1184                     input_AddInfo( p_cat, _("Codec"), "%4.4s",
1185                                    (const char*)&(p_info->i_codec) );
1186                     input_AddInfo( p_cat, _("FOURCC"), "0x%x",
1187                                    p_info->i_codec );
1188                     input_AddInfo( p_cat, _("Resolution"), "%dx%d",
1189                                    p_avi_strf_vids->p_bih->biWidth,
1190                                    p_avi_strf_vids->p_bih->biHeight );
1191                     input_AddInfo( p_cat, _("Frame Rate"), "%f",
1192                                    (float)p_info->i_rate /
1193                                        (float)p_info->i_scale );
1194                     input_AddInfo( p_cat, _("Bits Per Pixel"), "%d",
1195                                    p_avi_strf_vids->p_bih->biBitCount );
1196                 }
1197 #ifdef __AVI_SUBTITLE__
1198                 if( i_microsecperframe == 0 )
1199                 {
1200                     i_microsecperframe = (mtime_t)1000000 *
1201                                          (mtime_t)p_info->i_scale /
1202                                          (mtime_t)p_info->i_rate;
1203                 }
1204 #endif
1205                 break;
1206             default:
1207                 msg_Warn( p_input, "stream[%d] unknown type", i );
1208                 p_info->i_cat = UNKNOWN_ES;
1209                 i_init_size = 0;
1210                 p_init_data = NULL;
1211                 {
1212                     char psz_cat[32]; /* We'll clip i just in case */
1213                     input_info_category_t *p_cat;
1214                     sprintf( psz_cat, "Stream %d", __MIN( i, 100000 ) );
1215                     p_cat = input_InfoCategory( p_input, psz_cat );
1216                     input_AddInfo( p_cat, _("Type"), _("Unknown") );
1217                 }
1218                 break;
1219         }
1220         p_info->b_activated = VLC_FALSE;
1221         /* add one ES */
1222         vlc_mutex_lock( &p_input->stream.stream_lock );
1223         p_info->p_es =
1224             p_es = input_AddES( p_input, p_input->stream.p_selected_program,
1225                                 1+i, p_info->i_cat, NULL, 0 );
1226         vlc_mutex_unlock( &p_input->stream.stream_lock );
1227         p_es->i_stream_id =i; /* XXX: i don't use it */
1228         p_es->i_fourcc = p_info->i_fourcc;
1229         if( p_es->i_cat == AUDIO_ES )
1230         {
1231             if( i_init_size < sizeof( WAVEFORMATEX ) )
1232             {
1233                 i_init_size = sizeof( WAVEFORMATEX );
1234             }
1235             p_es->p_waveformatex = malloc( i_init_size );
1236             memcpy( p_es->p_waveformatex, p_init_data, i_init_size );
1237         }
1238         else if( p_es->i_cat == VIDEO_ES )
1239         {
1240             p_es->p_bitmapinfoheader = malloc( i_init_size );
1241             memcpy( p_es->p_bitmapinfoheader, p_init_data, i_init_size );
1242         }
1243 #undef p_info
1244     }
1245
1246 #ifdef __AVI_SUBTITLE__
1247     if( ( p_avi->p_sub = subtitle_New( p_input, NULL, i_microsecperframe ) ) )
1248     {
1249         subtitle_Select( p_avi->p_sub );
1250     }
1251 #endif
1252
1253     if( config_GetInt( p_input, "avi-index" ) )
1254     {
1255         if( p_avi->b_seekable )
1256         {
1257             AVI_IndexCreate( p_input );
1258         }
1259         else
1260         {
1261             msg_Warn( p_input, "cannot create index (unseekable stream)" );
1262             AVI_IndexLoad( p_input );
1263         }
1264     }
1265     else
1266     {
1267         AVI_IndexLoad( p_input );
1268     }
1269
1270     /* *** movie length in sec *** */
1271     p_avi->i_length = AVI_MovieGetLength( p_input, p_avi );
1272     if( p_avi->i_length < (mtime_t)p_avih->i_totalframes *
1273                           (mtime_t)p_avih->i_microsecperframe /
1274                           (mtime_t)1000000 )
1275     {
1276         msg_Warn( p_input, "broken or missing index, 'seek' will be axproximative or will have strange behavour" );
1277     }
1278
1279     /* fix some BeOS MediaKit generated file */
1280     for( i = 0 ; i < p_avi->i_streams; i++ )
1281     {
1282         avi_chunk_list_t    *p_avi_strl;
1283         avi_chunk_strh_t    *p_avi_strh;
1284         avi_chunk_strf_auds_t    *p_avi_strf_auds;
1285 #define p_stream  p_avi->pp_info[i]
1286
1287         if( p_stream->i_cat != AUDIO_ES )
1288         {
1289             continue;
1290         }
1291         if( p_stream->i_idxnb < 1 ||
1292             p_stream->i_scale != 1 ||
1293             p_stream->i_samplesize != 0 )
1294         {
1295             continue;
1296         }
1297         p_avi_strl = (avi_chunk_list_t*)AVI_ChunkFind( p_hdrl,
1298                                                        AVIFOURCC_strl, i );
1299         p_avi_strh = (avi_chunk_strh_t*)AVI_ChunkFind( p_avi_strl,
1300                                                        AVIFOURCC_strh, 0 );
1301         p_avi_strf_auds =
1302             (avi_chunk_strf_auds_t*)AVI_ChunkFind( p_avi_strl,
1303                                                    AVIFOURCC_strf, 0 );
1304
1305         if( p_avi_strf_auds->p_wf->wFormatTag != WAVE_FORMAT_PCM &&
1306             (unsigned int)p_stream->i_rate == p_avi_strf_auds->p_wf->nSamplesPerSec )
1307         {
1308             int64_t i_track_length =
1309                 p_stream->p_index[p_stream->i_idxnb-1].i_length +
1310                 p_stream->p_index[p_stream->i_idxnb-1].i_lengthtotal;
1311             mtime_t i_length = (mtime_t)p_avih->i_totalframes *
1312                                (mtime_t)p_avih->i_microsecperframe;
1313
1314             if( i_length == 0 )
1315             {
1316                 msg_Warn( p_input, "track[%d] cannot be fixed (BeOS MediaKit generated)", i );
1317                 continue;
1318             }
1319             p_stream->i_samplesize = 1;
1320             p_stream->i_rate       = i_track_length  * (int64_t)1000000/ i_length;
1321             msg_Warn( p_input, "track[%d] fixed with rate=%d scale=%d (BeOS MediaKit generated)", i, p_stream->i_rate, p_stream->i_scale );
1322         }
1323 #undef p_stream
1324     }
1325
1326     vlc_mutex_lock( &p_input->stream.stream_lock );
1327     if( p_avi->i_length )
1328     {
1329         p_input->stream.i_mux_rate =
1330             p_input->stream.p_selected_area->i_size / 50 / p_avi->i_length;
1331
1332         msg_Dbg( p_input, "checking interleaved" );
1333         p_avi->b_interleaved = AVI_Interleaved( p_input );
1334         msg_Dbg( p_input, "interleaved=%s", p_avi->b_interleaved ? "yes" : "no" );
1335     }
1336     else
1337     {
1338         p_input->stream.i_mux_rate = 0;
1339     }
1340     vlc_mutex_unlock( &p_input->stream.stream_lock );
1341
1342     b_stream_audio = VLC_FALSE;
1343     b_stream_video = VLC_FALSE;
1344
1345     for( i = 0; i < p_avi->i_streams; i++ )
1346     {
1347 #define p_info  p_avi->pp_info[i]
1348         switch( p_info->p_es->i_cat )
1349         {
1350             case( VIDEO_ES ):
1351
1352                 if( !b_stream_video )
1353                 {
1354                     b_stream_video = AVI_StreamStart( p_input, p_avi, i );
1355                 }
1356                 break;
1357
1358             case( AUDIO_ES ):
1359                 if( !b_stream_audio )
1360                 {
1361                     b_stream_audio = AVI_StreamStart( p_input, p_avi, i );
1362                 }
1363                 break;
1364             default:
1365                 break;
1366         }
1367 #undef p_info
1368     }
1369
1370     if( !b_stream_video )
1371     {
1372         msg_Warn( p_input, "no video stream found" );
1373     }
1374     if( !b_stream_audio )
1375     {
1376         msg_Warn( p_input, "no audio stream found!" );
1377     }
1378
1379     vlc_mutex_lock( &p_input->stream.stream_lock );
1380     p_input->stream.p_selected_program->b_is_ok = 1;
1381     vlc_mutex_unlock( &p_input->stream.stream_lock );
1382
1383     if( p_avi->b_seekable )
1384     {
1385         AVI_ChunkGoto( p_input, p_movi );
1386     }
1387     else
1388     {
1389         // already at begining of p_movi
1390     }
1391     AVI_SkipBytes( p_input, 12 ); // enter in p_movi
1392
1393     p_avi->i_movi_begin = p_movi->i_chunk_pos;
1394     return VLC_SUCCESS;
1395 }
1396
1397
1398
1399
1400 /*****************************************************************************
1401  * Function to convert pts to chunk or byte
1402  *****************************************************************************/
1403
1404 static inline mtime_t AVI_PTSToChunk( avi_stream_t *p_info,
1405                                         mtime_t i_pts )
1406 {
1407     return (mtime_t)((int64_t)i_pts *
1408                      (int64_t)p_info->i_rate /
1409                      (int64_t)p_info->i_scale /
1410                      (int64_t)1000000 );
1411 }
1412 static inline mtime_t AVI_PTSToByte( avi_stream_t *p_info,
1413                                        mtime_t i_pts )
1414 {
1415     return (mtime_t)((int64_t)i_pts *
1416                      (int64_t)p_info->i_rate /
1417                      (int64_t)p_info->i_scale /
1418                      (int64_t)1000000 *
1419                      (int64_t)p_info->i_samplesize );
1420 }
1421
1422 static mtime_t AVI_GetDPTS( avi_stream_t *p_stream, int i_count )
1423 {
1424     if( p_stream->i_samplesize )
1425     {
1426         return (mtime_t)( (int64_t)1000000 *
1427                    (int64_t)i_count *
1428                    (int64_t)p_stream->i_scale /
1429                    (int64_t)p_stream->i_rate /
1430                    (int64_t)p_stream->i_samplesize );
1431     }
1432     else
1433     {
1434         return (mtime_t)( (int64_t)1000000 *
1435                    (int64_t)i_count *
1436                    (int64_t)p_stream->i_scale /
1437                    (int64_t)p_stream->i_rate);
1438     }
1439
1440 }
1441
1442 static mtime_t AVI_GetPTS( avi_stream_t *p_info )
1443 {
1444
1445     if( p_info->i_samplesize )
1446     {
1447         /* we need a valid entry we will emulate one */
1448         int64_t i_len;
1449         if( p_info->i_idxposc == p_info->i_idxnb )
1450         {
1451             if( p_info->i_idxposc )
1452             {
1453                 /* use the last entry */
1454                 i_len = p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal
1455                             + p_info->p_index[p_info->i_idxnb - 1].i_length
1456                             + p_info->i_idxposb; /* should be 0 */
1457             }
1458             else
1459             {
1460                 i_len = p_info->i_idxposb;
1461                 /* no valid entry use only offset*/
1462             }
1463         }
1464         else
1465         {
1466             i_len = p_info->p_index[p_info->i_idxposc].i_lengthtotal
1467                                 + p_info->i_idxposb;
1468         }
1469         return (mtime_t)( (int64_t)1000000 *
1470                   (int64_t)i_len *
1471                    (int64_t)p_info->i_scale /
1472                    (int64_t)p_info->i_rate /
1473                    (int64_t)p_info->i_samplesize );
1474     }
1475     else
1476     {
1477         /* even if p_info->i_idxposc isn't valid, there isn't any problem */
1478         return (mtime_t)( (int64_t)1000000 *
1479                    (int64_t)(p_info->i_idxposc ) *
1480                    (int64_t)p_info->i_scale /
1481                    (int64_t)p_info->i_rate);
1482     }
1483 }
1484
1485 #if 0
1486 static void AVI_FixPTS( avi_stream_t *p_stream, pes_packet_t *p_pes )
1487 {
1488     data_packet_t *p_data;
1489     uint8_t       *p;
1490     int           i_pos = 0;
1491
1492     switch( p_stream->i_fourcc )
1493     {
1494         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
1495             p_data = p_pes->p_first;
1496             while( p_data )
1497             {
1498                 p = p_data->p_payload_start;
1499                 while( p < p_data->p_payload_end - 2 )
1500                 {
1501                     if( p[0] == 0xff && ( p[1]&0xe0) == 0xe0 )
1502                     {
1503                         mtime_t i_diff = AVI_GetDPTS( p_stream, i_pos );
1504                         p_pes->i_dts += i_diff;
1505                         p_pes->i_pts += i_diff;
1506                         return;
1507                     }
1508                     p++; i_pos++;
1509                 }
1510                 p_data = p_data->p_next;
1511             }
1512             return;
1513         case VLC_FOURCC( 'a', '5', '2', ' ' ):
1514             p_data = p_pes->p_first;
1515             while( p_data )
1516             {
1517                 p = p_data->p_payload_start;
1518                 while( p < p_data->p_payload_end - 2 )
1519                 {
1520                     if( p[0] == 0x0b && p[1] == 0x77 )
1521                     {
1522                         mtime_t i_diff = AVI_GetDPTS( p_stream, i_pos );
1523                         p_pes->i_dts += i_diff;
1524                         p_pes->i_pts += i_diff;
1525                     }
1526                     p++; i_pos++;
1527                 }
1528                 p_data = p_data->p_next;
1529             }
1530             return;
1531         default:
1532             /* we can't fix :( */
1533             return;
1534     }
1535 }
1536 #endif
1537
1538 static int AVI_StreamChunkFind( input_thread_t *p_input,
1539                                 unsigned int i_stream )
1540 {
1541     demux_sys_t *p_avi = p_input->p_demux_data;
1542     avi_packet_t avi_pk;
1543
1544     /* find first chunk of i_stream that isn't in index */
1545
1546     if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin + 12 )
1547     {
1548         AVI_SeekAbsolute( p_input, p_avi->i_movi_lastchunk_pos );
1549         if( AVI_PacketNext( p_input ) )
1550         {
1551             return VLC_EGENERIC;
1552         }
1553     }
1554     else
1555     {
1556         AVI_SeekAbsolute( p_input, p_avi->i_movi_begin + 12 );
1557     }
1558
1559     for( ;; )
1560     {
1561
1562         if( AVI_PacketGetHeader( p_input, &avi_pk ) )
1563         {
1564             msg_Warn( p_input, "cannot get packet header" );
1565             return VLC_EGENERIC;
1566         }
1567         if( avi_pk.i_stream >= p_avi->i_streams ||
1568             ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1569         {
1570             if( AVI_PacketNext( p_input ) )
1571             {
1572                 return VLC_EGENERIC;
1573             }
1574         }
1575         else
1576         {
1577             /* add this chunk to the index */
1578             AVIIndexEntry_t index;
1579
1580             index.i_id = avi_pk.i_fourcc;
1581             index.i_flags =
1582                AVI_GetKeyFlag(p_avi->pp_info[avi_pk.i_stream]->i_codec,
1583                               avi_pk.i_peek);
1584             index.i_pos = avi_pk.i_pos;
1585             index.i_length = avi_pk.i_size;
1586             AVI_IndexAddEntry( p_avi, avi_pk.i_stream, &index );
1587
1588             if( avi_pk.i_stream == i_stream  )
1589             {
1590                 return VLC_SUCCESS;
1591             }
1592
1593             if( AVI_PacketNext( p_input ) )
1594             {
1595                 return VLC_EGENERIC;
1596             }
1597         }
1598     }
1599 }
1600
1601
1602 /* be sure that i_ck will be a valid index entry */
1603 static int AVI_SetStreamChunk( input_thread_t    *p_input,
1604                                unsigned int i_stream,
1605                                unsigned int i_ck )
1606 {
1607     demux_sys_t *p_avi = p_input->p_demux_data;
1608     avi_stream_t *p_stream = p_avi->pp_info[i_stream];
1609
1610     p_stream->i_idxposc = i_ck;
1611     p_stream->i_idxposb = 0;
1612
1613     if(  i_ck >= p_stream->i_idxnb )
1614     {
1615         p_stream->i_idxposc = p_stream->i_idxnb - 1;
1616         do
1617         {
1618             p_stream->i_idxposc++;
1619             if( AVI_StreamChunkFind( p_input, i_stream ) )
1620             {
1621                 return VLC_EGENERIC;
1622             }
1623
1624         } while( p_stream->i_idxposc < i_ck );
1625     }
1626
1627     return VLC_SUCCESS;
1628 }
1629
1630
1631 /* XXX FIXME up to now, we assume that all chunk are one after one */
1632 static int AVI_SetStreamBytes( input_thread_t    *p_input,
1633                                unsigned int i_stream,
1634                                off_t   i_byte )
1635 {
1636     demux_sys_t *p_avi = p_input->p_demux_data;
1637     avi_stream_t *p_stream = p_avi->pp_info[i_stream];
1638
1639     if( ( p_stream->i_idxnb > 0 )
1640         &&( i_byte < p_stream->p_index[p_stream->i_idxnb - 1].i_lengthtotal +
1641                 p_stream->p_index[p_stream->i_idxnb - 1].i_length ) )
1642     {
1643         /* index is valid to find the ck */
1644         /* uses dichototmie to be fast enougth */
1645         int i_idxposc = __MIN( p_stream->i_idxposc, p_stream->i_idxnb - 1 );
1646         int i_idxmax  = p_stream->i_idxnb;
1647         int i_idxmin  = 0;
1648         for( ;; )
1649         {
1650             if( p_stream->p_index[i_idxposc].i_lengthtotal > i_byte )
1651             {
1652                 i_idxmax  = i_idxposc ;
1653                 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1654             }
1655             else
1656             {
1657                 if( p_stream->p_index[i_idxposc].i_lengthtotal +
1658                         p_stream->p_index[i_idxposc].i_length <= i_byte)
1659                 {
1660                     i_idxmin  = i_idxposc ;
1661                     i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1662                 }
1663                 else
1664                 {
1665                     p_stream->i_idxposc = i_idxposc;
1666                     p_stream->i_idxposb = i_byte -
1667                             p_stream->p_index[i_idxposc].i_lengthtotal;
1668                     return VLC_SUCCESS;
1669                 }
1670             }
1671         }
1672
1673     }
1674     else
1675     {
1676         p_stream->i_idxposc = p_stream->i_idxnb - 1;
1677         p_stream->i_idxposb = 0;
1678         do
1679         {
1680             p_stream->i_idxposc++;
1681             if( AVI_StreamChunkFind( p_input, i_stream ) )
1682             {
1683                 return VLC_EGENERIC;
1684             }
1685
1686         } while( p_stream->p_index[p_stream->i_idxposc].i_lengthtotal +
1687                     p_stream->p_index[p_stream->i_idxposc].i_length <= i_byte );
1688
1689         p_stream->i_idxposb = i_byte -
1690                        p_stream->p_index[p_stream->i_idxposc].i_lengthtotal;
1691         return VLC_SUCCESS;
1692     }
1693 }
1694
1695 static int AVI_StreamSeek( input_thread_t *p_input,
1696                            demux_sys_t  *p_avi,
1697                            int i_stream,
1698                            mtime_t i_date )
1699 {
1700 #define p_stream    p_avi->pp_info[i_stream]
1701     mtime_t i_oldpts;
1702
1703     i_oldpts = AVI_GetPTS( p_stream );
1704
1705     if( !p_stream->i_samplesize )
1706     {
1707         if( AVI_SetStreamChunk( p_input,
1708                                 i_stream,
1709                                 AVI_PTSToChunk( p_stream, i_date ) ) )
1710         {
1711             return VLC_EGENERIC;
1712         }
1713
1714         msg_Dbg( p_input,
1715                  "old:"I64Fd" %s new "I64Fd,
1716                  i_oldpts,
1717                  i_oldpts > i_date ? ">" : "<",
1718                  i_date );
1719
1720         if( p_stream->i_cat == VIDEO_ES )
1721         {
1722             /* search key frame */
1723             if( i_date < i_oldpts )
1724             {
1725                 while( p_stream->i_idxposc > 0 &&
1726                    !( p_stream->p_index[p_stream->i_idxposc].i_flags &
1727                                                                 AVIIF_KEYFRAME ) )
1728                 {
1729                     if( AVI_SetStreamChunk( p_input,
1730                                             i_stream,
1731                                             p_stream->i_idxposc - 1 ) )
1732                     {
1733                         return VLC_EGENERIC;
1734                     }
1735                 }
1736             }
1737             else
1738             {
1739                 while( p_stream->i_idxposc < p_stream->i_idxnb &&
1740                         !( p_stream->p_index[p_stream->i_idxposc].i_flags &
1741                                                                 AVIIF_KEYFRAME ) )
1742                 {
1743                     if( AVI_SetStreamChunk( p_input,
1744                                             i_stream,
1745                                             p_stream->i_idxposc + 1 ) )
1746                     {
1747                         return VLC_EGENERIC;
1748                     }
1749                 }
1750             }
1751         }
1752     }
1753     else
1754     {
1755         if( AVI_SetStreamBytes( p_input,
1756                                 i_stream,
1757                                 AVI_PTSToByte( p_stream, i_date ) ) )
1758         {
1759             return VLC_EGENERIC;
1760         }
1761     }
1762     return VLC_SUCCESS;
1763 #undef p_stream
1764 }
1765
1766 /*****************************************************************************
1767  * AVI_Interleaved: check weither a file is interleaved or not.
1768  *****************************************************************************/
1769 static vlc_bool_t AVI_Interleaved( input_thread_t *p_input )
1770 {
1771     demux_sys_t     *p_sys = p_input->p_demux_data;
1772     unsigned int    i;
1773     mtime_t         i_time = 0;
1774     vlc_bool_t      b_ret = VLC_TRUE;
1775
1776     int64_t         i_max;
1777
1778     if( p_input->stream.p_selected_area->i_size <= 100 )
1779     {
1780         return VLC_FALSE;
1781     }
1782
1783     i_max = __MIN( 2000000, p_input->stream.p_selected_area->i_size / 100 );
1784
1785 #define tk p_sys->pp_info[i]
1786     while( i_time < p_sys->i_length * (mtime_t)1000000)
1787     {
1788         int64_t     i_ref;
1789
1790         i_ref = -1;
1791         i_time += 50000;
1792         for( i = 0; i < p_sys->i_streams; i++ )
1793         {
1794             while( AVI_GetPTS( tk ) < i_time && tk->i_idxposc < tk->i_idxnb - 1 )
1795             {
1796                 tk->i_idxposc++;
1797             }
1798
1799             if( i_ref == -1 )
1800             {
1801                 i_ref = tk->p_index[tk->i_idxposc].i_pos;
1802             }
1803             if( tk->p_index[tk->i_idxposc].i_pos - i_ref > i_max ||
1804                 tk->p_index[tk->i_idxposc].i_pos - i_ref < -i_max ||
1805                 tk->p_index[tk->i_idxposc].i_length > i_max )
1806             {
1807                 msg_Dbg( p_input, "interleaved=no because ref=%lld pos=%lld length=%d (max=%lld)",
1808                          i_ref, tk->p_index[tk->i_idxposc].i_pos, tk->p_index[tk->i_idxposc].i_length, i_max  );
1809                 b_ret = VLC_FALSE;
1810                 goto exit;
1811             }
1812         }
1813     }
1814
1815 exit:
1816     for( i = 0; i < p_sys->i_streams; i++ )
1817     {
1818         tk->i_idxposc = 0;
1819         tk->i_idxposb = 0;
1820     }
1821 #undef tk
1822     return b_ret;
1823 }
1824
1825 /*****************************************************************************
1826  * AVISeek: goto to i_date or i_percent
1827  *****************************************************************************
1828  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1829  *****************************************************************************/
1830 static int    AVISeek   ( input_thread_t *p_input,
1831                           mtime_t i_date, int i_percent )
1832 {
1833
1834     demux_sys_t *p_avi = p_input->p_demux_data;
1835     unsigned int i_stream;
1836     msg_Dbg( p_input,
1837              "seek requested: "I64Fd" secondes %d%%",
1838              i_date / 1000000,
1839              i_percent );
1840
1841     if( p_avi->b_seekable )
1842     {
1843         if( !p_avi->i_length || p_avi->b_interleaved )
1844         {
1845             avi_stream_t *p_stream;
1846             int64_t i_pos;
1847
1848             /* use i_percent to create a true i_date */
1849             if( !p_avi->b_interleaved )
1850             {
1851                 msg_Warn( p_input,
1852                           "mmh, seeking without index at %d%%"
1853                           " work only for interleaved file", i_percent );
1854             }
1855
1856             if( i_percent >= 100 )
1857             {
1858                 msg_Warn( p_input, "cannot seek so far !" );
1859                 return( -1 );
1860             }
1861             i_percent = __MAX( i_percent, 0 );
1862
1863             /* try to find chunk that is at i_percent or the file */
1864             i_pos = __MAX( i_percent *
1865                            p_input->stream.p_selected_area->i_size / 100,
1866                            p_avi->i_movi_begin );
1867             /* search first selected stream */
1868             for( i_stream = 0, p_stream = NULL;
1869                         i_stream < p_avi->i_streams; i_stream++ )
1870             {
1871                 p_stream = p_avi->pp_info[i_stream];
1872                 if( p_stream->b_activated )
1873                 {
1874                     break;
1875                 }
1876             }
1877             if( !p_stream || !p_stream->b_activated )
1878             {
1879                 msg_Warn( p_input, "cannot find any selected stream" );
1880                 return( -1 );
1881             }
1882
1883             /* be sure that the index exit */
1884             if( AVI_SetStreamChunk( p_input,
1885                                     i_stream,
1886                                     0 ) )
1887             {
1888                 msg_Warn( p_input, "cannot seek" );
1889                 return( -1 );
1890             }
1891
1892             while( i_pos >= p_stream->p_index[p_stream->i_idxposc].i_pos +
1893                p_stream->p_index[p_stream->i_idxposc].i_length + 8 )
1894             {
1895                 /* search after i_idxposc */
1896                 if( AVI_SetStreamChunk( p_input,
1897                                         i_stream, p_stream->i_idxposc + 1 ) )
1898                 {
1899                     msg_Warn( p_input, "cannot seek" );
1900                     return( -1 );
1901                 }
1902             }
1903             i_date = AVI_GetPTS( p_stream );
1904             /* TODO better support for i_samplesize != 0 */
1905             msg_Dbg( p_input, "estimate date "I64Fd, i_date );
1906         }
1907
1908 #define p_stream    p_avi->pp_info[i_stream]
1909         p_avi->i_time = 0;
1910         /* seek for chunk based streams */
1911         for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1912         {
1913             if( p_stream->b_activated && !p_stream->i_samplesize )
1914 //            if( p_stream->b_activated )
1915             {
1916                 AVI_StreamSeek( p_input, p_avi, i_stream, i_date );
1917                 p_avi->i_time = __MAX( AVI_GetPTS( p_stream ),
1918                                         p_avi->i_time );
1919             }
1920         }
1921 #if 1
1922         if( p_avi->i_time )
1923         {
1924             i_date = p_avi->i_time;
1925         }
1926         /* seek for bytes based streams */
1927         for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1928         {
1929             if( p_stream->b_activated && p_stream->i_samplesize )
1930             {
1931                 AVI_StreamSeek( p_input, p_avi, i_stream, i_date );
1932 //                p_avi->i_time = __MAX( AVI_GetPTS( p_stream ), p_avi->i_time );
1933             }
1934         }
1935         msg_Dbg( p_input, "seek: "I64Fd" secondes", p_avi->i_time /1000000 );
1936         /* set true movie time */
1937 #endif
1938         if( !p_avi->i_time )
1939         {
1940             p_avi->i_time = i_date;
1941         }
1942 #undef p_stream
1943         return( 1 );
1944     }
1945     else
1946     {
1947         msg_Err( p_input, "shouldn't yet be executed" );
1948         return( -1 );
1949     }
1950 }
1951
1952 #if 0
1953 static pes_packet_t *PES_split( input_thread_t *p_input, avi_stream_t *p_stream, pes_packet_t *p_pes )
1954 {
1955     pes_packet_t  *p_pes2;
1956     data_packet_t *p_data;
1957     int           i_nb_data;
1958
1959     if( p_pes->i_nb_data < 2 )
1960     {
1961         return( NULL );
1962     }
1963     p_pes2 = input_NewPES( p_input->p_method_data );
1964     p_pes2->i_pts = p_pes->i_pts;
1965     p_pes2->i_dts = p_pes->i_dts;
1966     p_pes2->i_nb_data = p_pes->i_nb_data/2;
1967     p_pes2->i_pes_size = 0;
1968     for( i_nb_data = 0, p_data = p_pes->p_first;
1969          i_nb_data < p_pes2->i_nb_data;
1970          i_nb_data++, p_data = p_data->p_next )
1971     {
1972         p_pes2->i_pes_size +=
1973             p_data->p_payload_end - p_data->p_payload_start;
1974         p_pes2->p_last = p_data;
1975     }
1976     p_pes2->p_first = p_pes->p_first;
1977     p_pes2->p_last->p_next = NULL;
1978
1979     p_pes->p_first = p_data;
1980     p_pes->i_pes_size -= p_pes2->i_pes_size;
1981     p_pes->i_nb_data -= p_pes2->i_nb_data;
1982 //    p_pes->i_pts += AVI_GetDPTS( p_stream, p_pes2->i_pes_size );
1983 //    p_pes->i_dts += AVI_GetDPTS( p_stream, p_pes2->i_pes_size );
1984     p_pes->i_pts = 0;
1985     p_pes->i_dts = 0;
1986     return( p_pes2 );
1987 }
1988 #endif
1989
1990 /*****************************************************************************
1991  * AVIDemux_Seekable: reads and demuxes data packets for stream seekable
1992  *****************************************************************************
1993  * AVIDemux: reads and demuxes data packets
1994  *****************************************************************************
1995  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1996  *****************************************************************************/
1997 typedef struct avi_stream_toread_s
1998 {
1999     vlc_bool_t b_ok;
2000
2001     int i_toread;
2002
2003     off_t i_posf; // where we will read :
2004                   // if i_idxposb == 0 : begining of chunk (+8 to acces data)
2005                   // else : point on data directly
2006 } avi_stream_toread_t;
2007
2008 static int AVIDemux_Seekable( input_thread_t *p_input )
2009 {
2010     unsigned int i_stream_count;
2011     unsigned int i_stream;
2012     vlc_bool_t b_stream;
2013     vlc_bool_t b_play_audio;
2014     vlc_bool_t b_video; /* is there some video track selected */
2015     // cannot be more than 100 stream (dcXX or wbXX)
2016     avi_stream_toread_t toread[100];
2017
2018     demux_sys_t *p_avi = p_input->p_demux_data;
2019
2020
2021     /* detect new selected/unselected streams */
2022     for( i_stream = 0,i_stream_count= 0, b_video = VLC_FALSE;
2023             i_stream < p_avi->i_streams; i_stream++ )
2024     {
2025 #define p_stream    p_avi->pp_info[i_stream]
2026         if( p_stream->p_es )
2027         {
2028             if( p_stream->p_es->p_decoder_fifo &&
2029                 !p_stream->b_activated )
2030             {
2031                 AVI_StreamStart( p_input, p_avi, i_stream );
2032             }
2033             else
2034             if( !p_stream->p_es->p_decoder_fifo &&
2035                 p_stream->b_activated )
2036             {
2037                 AVI_StreamStop( p_input, p_avi, i_stream );
2038             }
2039         }
2040         if( p_stream->b_activated )
2041         {
2042             i_stream_count++;
2043             if( p_stream->i_cat == VIDEO_ES )
2044             {
2045                 b_video = VLC_TRUE;
2046             }
2047         }
2048 #undef  p_stream
2049     }
2050
2051     if( i_stream_count <= 0 )
2052     {
2053         msg_Warn( p_input, "no track selected, exiting..." );
2054         return( 0 );
2055     }
2056
2057     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
2058     {
2059         mtime_t i_date;
2060         int i_percent;
2061         /* first wait for empty buffer, arbitrary time FIXME */
2062         //msleep( DEFAULT_PTS_DELAY );
2063
2064         i_date = (mtime_t)1000000 *
2065                  (mtime_t)p_avi->i_length *
2066                  (mtime_t)AVI_TellAbsolute( p_input ) /
2067                  (mtime_t)p_input->stream.p_selected_area->i_size;
2068         i_percent = 100 * AVI_TellAbsolute( p_input ) /
2069                         p_input->stream.p_selected_area->i_size;
2070
2071 //        input_ClockInit( p_input->stream.p_selected_program );
2072         AVISeek( p_input, i_date, i_percent);
2073
2074 #ifdef __AVI_SUBTITLE__
2075         if( p_avi->p_sub )
2076         {
2077             subtitle_Seek( p_avi->p_sub, p_avi->i_time );
2078         }
2079 #endif
2080     }
2081
2082
2083     /* wait for the good time */
2084
2085     p_avi->i_pcr = p_avi->i_time * 9 / 100;
2086
2087     input_ClockManageRef( p_input,
2088                           p_input->stream.p_selected_program,
2089                           p_avi->i_pcr );
2090
2091
2092     p_avi->i_time += 25*1000;  /* read 25ms */
2093
2094 #ifdef __AVI_SUBTITLE__
2095     if( p_avi->p_sub )
2096     {
2097         subtitle_Demux( p_avi->p_sub, p_avi->i_time );
2098     }
2099 #endif
2100
2101     /* Check if we need to send the audio data to decoder */
2102     b_play_audio = !p_input->stream.control.b_mute;
2103
2104     /* init toread */
2105     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
2106     {
2107 #define p_stream    p_avi->pp_info[i_stream]
2108         mtime_t i_dpts;
2109
2110         toread[i_stream].b_ok = p_stream->b_activated;
2111         if( p_stream->i_idxposc < p_stream->i_idxnb )
2112         {
2113             toread[i_stream].i_posf =
2114                 p_stream->p_index[p_stream->i_idxposc].i_pos;
2115            if( p_stream->i_idxposb > 0 )
2116            {
2117                 toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
2118            }
2119         }
2120         else
2121         {
2122             toread[i_stream].i_posf = -1;
2123         }
2124
2125         i_dpts = p_avi->i_time - AVI_GetPTS( p_stream  );
2126
2127         if( p_stream->i_samplesize )
2128         {
2129             toread[i_stream].i_toread = AVI_PTSToByte( p_stream,
2130                                                        __ABS( i_dpts ) );
2131         }
2132         else
2133         {
2134             toread[i_stream].i_toread = AVI_PTSToChunk( p_stream,
2135                                                         __ABS( i_dpts ) );
2136         }
2137
2138         if( i_dpts < 0 )
2139         {
2140             toread[i_stream].i_toread *= -1;
2141         }
2142 #undef  p_stream
2143     }
2144
2145     b_stream = VLC_FALSE;
2146
2147     for( ;; )
2148     {
2149 #define p_stream    p_avi->pp_info[i_stream]
2150         vlc_bool_t       b_done;
2151         pes_packet_t    *p_pes;
2152         off_t i_pos;
2153         unsigned int i;
2154         size_t i_size;
2155
2156         /* search for first chunk to be read */
2157         for( i = 0, b_done = VLC_TRUE, i_pos = -1; i < p_avi->i_streams; i++ )
2158         {
2159             if( !toread[i].b_ok ||
2160                 AVI_GetDPTS( p_avi->pp_info[i],
2161                              toread[i].i_toread ) <= -25 * 1000 )
2162             {
2163                 continue;
2164             }
2165
2166             if( toread[i].i_toread > 0 )
2167             {
2168                 b_done = VLC_FALSE; // not yet finished
2169             }
2170
2171             if( toread[i].i_posf > 0 )
2172             {
2173                 if( i_pos == -1 || i_pos > toread[i_stream].i_posf )
2174                 {
2175                     i_stream = i;
2176                     i_pos = toread[i].i_posf;
2177                 }
2178             }
2179         }
2180
2181         if( b_done )
2182         {
2183 //            return( b_stream ? 1 : 0 );
2184             return( 1 );
2185         }
2186
2187         if( i_pos == -1 )
2188         {
2189             /* no valid index, we will parse directly the stream
2190              * in case we fail we will disable all finished stream */
2191             if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin + 12 )
2192             {
2193                 AVI_SeekAbsolute( p_input, p_avi->i_movi_lastchunk_pos );
2194                 if( AVI_PacketNext( p_input ) )
2195                 {
2196                     return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
2197                 }
2198             }
2199             else
2200             {
2201                 AVI_SeekAbsolute( p_input, p_avi->i_movi_begin + 12 );
2202             }
2203
2204             for( ;; )
2205             {
2206                 avi_packet_t avi_pk;
2207
2208                 if( AVI_PacketGetHeader( p_input, &avi_pk ) )
2209                 {
2210                     msg_Warn( p_input,
2211                              "cannot get packet header, track disabled" );
2212                     return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
2213                 }
2214                 if( avi_pk.i_stream >= p_avi->i_streams ||
2215                     ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
2216                 {
2217                     if( AVI_PacketNext( p_input ) )
2218                     {
2219                         msg_Warn( p_input,
2220                                   "cannot skip packet, track disabled" );
2221                         return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
2222                     }
2223                     continue;
2224                 }
2225                 else
2226                 {
2227                     /* add this chunk to the index */
2228                     AVIIndexEntry_t index;
2229
2230                     index.i_id = avi_pk.i_fourcc;
2231                     index.i_flags =
2232                        AVI_GetKeyFlag(p_avi->pp_info[avi_pk.i_stream]->i_codec,
2233                                       avi_pk.i_peek);
2234                     index.i_pos = avi_pk.i_pos;
2235                     index.i_length = avi_pk.i_size;
2236                     AVI_IndexAddEntry( p_avi, avi_pk.i_stream, &index );
2237
2238                     i_stream = avi_pk.i_stream;
2239                     /* do we will read this data ? */
2240                     if( AVI_GetDPTS( p_stream,
2241                              toread[i_stream].i_toread ) > -25 * 1000 )
2242                     {
2243                         break;
2244                     }
2245                     else
2246                     {
2247                         if( AVI_PacketNext( p_input ) )
2248                         {
2249                             msg_Warn( p_input,
2250                                       "cannot skip packet, track disabled" );
2251                             return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
2252                         }
2253                     }
2254                 }
2255             }
2256
2257         }
2258         else
2259         {
2260             AVI_SeekAbsolute( p_input, i_pos );
2261         }
2262
2263         /* read thoses data */
2264         if( p_stream->i_samplesize )
2265         {
2266             unsigned int i_toread;
2267
2268             if( ( i_toread = toread[i_stream].i_toread ) <= 0 )
2269             {
2270                 if( p_stream->i_samplesize > 1 )
2271                 {
2272                     i_toread = p_stream->i_samplesize;
2273                 }
2274                 else
2275                 {
2276                     i_toread = __MAX( AVI_PTSToByte( p_stream, 20 * 1000 ), 100 );
2277                 }
2278             }
2279             i_size = __MIN( p_stream->p_index[p_stream->i_idxposc].i_length -
2280                                 p_stream->i_idxposb,
2281                             i_toread );
2282         }
2283         else
2284         {
2285             i_size = p_stream->p_index[p_stream->i_idxposc].i_length;
2286         }
2287
2288         if( p_stream->i_idxposb == 0 )
2289         {
2290             i_size += 8; // need to read and skip header
2291         }
2292
2293         if( input_ReadInPES( p_input, &p_pes, __EVEN( i_size ) ) < 0 )
2294         {
2295             msg_Warn( p_input, "failled reading data" );
2296             AVI_StreamStop( p_input, p_avi, i_stream );
2297             toread[i_stream].b_ok = VLC_FALSE;
2298             continue;
2299         }
2300
2301         if( i_size % 2 )    // read was padded on word boundary
2302         {
2303             p_pes->p_last->p_payload_end--;
2304             p_pes->i_pes_size--;
2305         }
2306         // skip header
2307         if( p_stream->i_idxposb == 0 )
2308         {
2309             p_pes->p_first->p_payload_start += 8;
2310             p_pes->i_pes_size -= 8;
2311         }
2312
2313         p_pes->i_pts = AVI_GetPTS( p_stream );
2314
2315 #if 0
2316         /* fix pts for audio: ie pts sould be for the first byte of the first frame */
2317         if( p_stream->i_samplesize == 1 )
2318         {
2319             AVI_FixPTS( p_stream, p_pes );
2320         }
2321 #endif
2322
2323         /* read data */
2324         if( p_stream->i_samplesize )
2325         {
2326             if( p_stream->i_idxposb == 0 )
2327             {
2328                 i_size -= 8;
2329             }
2330             toread[i_stream].i_toread -= i_size;
2331             p_stream->i_idxposb += i_size;
2332             if( p_stream->i_idxposb >=
2333                     p_stream->p_index[p_stream->i_idxposc].i_length )
2334             {
2335                 p_stream->i_idxposb = 0;
2336                 p_stream->i_idxposc++;
2337             }
2338         }
2339         else
2340         {
2341             toread[i_stream].i_toread--;
2342             p_stream->i_idxposc++;
2343         }
2344
2345         if( p_stream->i_idxposc < p_stream->i_idxnb)
2346         {
2347             toread[i_stream].i_posf =
2348                 p_stream->p_index[p_stream->i_idxposc].i_pos;
2349             if( p_stream->i_idxposb > 0 )
2350             {
2351                 toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
2352             }
2353
2354         }
2355         else
2356         {
2357             toread[i_stream].i_posf = -1;
2358         }
2359
2360         b_stream = VLC_TRUE; // at least one read succeed
2361
2362         if( p_stream->p_es && p_stream->p_es->p_decoder_fifo &&
2363             ( b_play_audio || p_stream->i_cat != AUDIO_ES ) )
2364         {
2365             p_pes->i_dts =
2366                 p_pes->i_pts =
2367                     input_ClockGetTS( p_input,
2368                                       p_input->stream.p_selected_program,
2369                                       p_pes->i_pts * 9/100);
2370
2371             p_pes->i_rate = p_input->stream.control.i_rate;
2372
2373             input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
2374         }
2375         else
2376         {
2377             input_DeletePES( p_input->p_method_data, p_pes );
2378         }
2379     }
2380 }
2381
2382
2383 /*****************************************************************************
2384  * AVIDemux_UnSeekable: reads and demuxes data packets for unseekable file
2385  *****************************************************************************
2386  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
2387  *****************************************************************************/
2388 static int AVIDemux_UnSeekable( input_thread_t *p_input )
2389 {
2390     demux_sys_t     *p_avi = p_input->p_demux_data;
2391     avi_stream_t *p_stream_master;
2392     vlc_bool_t b_audio;
2393     unsigned int i_stream;
2394     unsigned int i_packet;
2395
2396     /* Check if we need to send the audio data to decoder */
2397     b_audio = !p_input->stream.control.b_mute;
2398
2399     input_ClockManageRef( p_input,
2400                           p_input->stream.p_selected_program,
2401                           p_avi->i_pcr );
2402     /* *** find master stream for data packet skipping algo *** */
2403     /* *** -> first video, if any, or first audio ES *** */
2404     for( i_stream = 0, p_stream_master = NULL;
2405             i_stream < p_avi->i_streams; i_stream++ )
2406     {
2407 #define p_stream    p_avi->pp_info[i_stream]
2408         if( p_stream->p_es &&
2409             p_stream->p_es->p_decoder_fifo )
2410         {
2411             if( p_stream->i_cat == VIDEO_ES )
2412             {
2413                 p_stream_master = p_stream;
2414                 break;
2415             }
2416             if( p_stream->i_cat == AUDIO_ES && !p_stream_master )
2417             {
2418                 p_stream_master = p_stream;
2419             }
2420         }
2421 #undef p_stream
2422     }
2423     if( !p_stream_master )
2424     {
2425         msg_Warn( p_input, "no more stream selected" );
2426         return( 0 );
2427     }
2428
2429     p_avi->i_pcr = AVI_GetPTS( p_stream_master ) * 9 / 100;
2430
2431     for( i_packet = 0; i_packet < 10; i_packet++)
2432     {
2433 #define p_stream    p_avi->pp_info[avi_pk.i_stream]
2434
2435         avi_packet_t    avi_pk;
2436
2437         if( AVI_PacketGetHeader( p_input, &avi_pk ) )
2438         {
2439             return( 0 );
2440         }
2441 //        AVI_ParseStreamHeader( avi_pk.i_fourcc, &i_stream, &i_cat );
2442
2443         if( avi_pk.i_stream >= p_avi->i_streams ||
2444             ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
2445         {
2446             /* we haven't found an audio or video packet:
2447              *  - we have seek, found first next packet
2448              *  - others packets could be found, skip them
2449              */
2450             switch( avi_pk.i_fourcc )
2451             {
2452                 case AVIFOURCC_JUNK:
2453                 case AVIFOURCC_LIST:
2454                 case AVIFOURCC_RIFF:
2455                     return( !AVI_PacketNext( p_input ) ? 1 : 0 );
2456                 case AVIFOURCC_idx1:
2457                     if( p_avi->b_odml )
2458                     {
2459                         return( !AVI_PacketNext( p_input ) ? 1 : 0 );
2460                     }
2461                     return( 0 );    // eof
2462                 default:
2463                     msg_Warn( p_input,
2464                               "seems to have lost position, resync" );
2465                     if( AVI_PacketSearch( p_input ) )
2466                     {
2467                         msg_Err( p_input, "resync failed" );
2468                         return( -1 );
2469                     }
2470             }
2471         }
2472         else
2473         {
2474             /* do will send this packet to decoder ? */
2475             if( ( !b_audio && avi_pk.i_cat == AUDIO_ES )||
2476                 !p_stream->p_es ||
2477                 !p_stream->p_es->p_decoder_fifo )
2478             {
2479                 if( AVI_PacketNext( p_input ) )
2480                 {
2481                     return( 0 );
2482                 }
2483             }
2484             else
2485             {
2486                 /* it's a selected stream, check for time */
2487                 if( __ABS( AVI_GetPTS( p_stream ) -
2488                             AVI_GetPTS( p_stream_master ) )< 600*1000 )
2489                 {
2490                     /* load it and send to decoder */
2491                     pes_packet_t    *p_pes;
2492                     if( AVI_PacketRead( p_input, &avi_pk, &p_pes ) || !p_pes)
2493                     {
2494                         return( -1 );
2495                     }
2496                     p_pes->i_dts =
2497                         p_pes->i_pts =
2498                             input_ClockGetTS( p_input,
2499                                           p_input->stream.p_selected_program,
2500                                           AVI_GetPTS( p_stream ) * 9/100);
2501
2502                     p_pes->i_rate = p_input->stream.control.i_rate;
2503
2504                     input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
2505                 }
2506                 else
2507                 {
2508                     if( AVI_PacketNext( p_input ) )
2509                     {
2510                         return( 0 );
2511                     }
2512                 }
2513             }
2514
2515             /* *** update stream time position *** */
2516             if( p_stream->i_samplesize )
2517             {
2518                 p_stream->i_idxposb += avi_pk.i_size;
2519             }
2520             else
2521             {
2522                 p_stream->i_idxposc++;
2523             }
2524
2525         }
2526
2527 #undef p_stream
2528     }
2529
2530     return( 1 );
2531 }
2532