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