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