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