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