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