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