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