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