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