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