* avi : fixed a lock problem.
[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.59 2003/08/23 11:46:06 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     if( p_avi->i_length )
508     {
509         p_input->stream.i_mux_rate =
510             stream_Size( p_avi->s ) / 50 / p_avi->i_length;
511
512         p_avi->b_interleaved = AVI_Interleaved( p_input );
513         msg_Dbg( p_input, "interleaved=%s",
514                  p_avi->b_interleaved ? "yes" : "no" );
515     }
516
517     b_stream_audio = VLC_FALSE;
518     b_stream_video = VLC_FALSE;
519
520     for( i = 0; i < p_avi->i_streams; i++ )
521     {
522 #define tk p_avi->pp_info[i]
523         if( tk->p_es->i_cat == VIDEO_ES && !b_stream_video )
524         {
525             b_stream_video = AVI_StreamStart( p_input, i );
526         }
527         else if(tk->p_es->i_cat == AUDIO_ES && !b_stream_audio )
528         {
529             b_stream_audio = AVI_StreamStart( p_input, i );
530         }
531 #undef tk
532     }
533
534     if( !b_stream_video )
535     {
536         msg_Warn( p_input, "no video stream found" );
537     }
538     if( !b_stream_audio )
539     {
540         msg_Warn( p_input, "no audio stream found!" );
541     }
542
543     vlc_mutex_lock( &p_input->stream.stream_lock );
544     p_input->stream.p_selected_program->b_is_ok = 1;
545     vlc_mutex_unlock( &p_input->stream.stream_lock );
546
547     if( p_avi->b_seekable )
548     {
549         /* we have read all chunk so go back to movi */
550         stream_Seek( p_avi->s, p_movi->i_chunk_pos );
551     }
552     /* Skip movi header */
553     stream_Read( p_avi->s, NULL, 12 );
554
555     p_avi->i_movi_begin = p_movi->i_chunk_pos;
556     return VLC_SUCCESS;
557
558 error:
559     AVI_ChunkFreeRoot( p_avi->s, &p_avi->ck_root );
560     stream_Release( p_avi->s );
561     free( p_avi );
562     return VLC_EGENERIC;
563 }
564
565 /*****************************************************************************
566  * Close: frees unused data
567  *****************************************************************************/
568 static void Close ( vlc_object_t * p_this )
569 {
570     input_thread_t *    p_input = (input_thread_t *)p_this;
571     unsigned int i;
572     demux_sys_t *p_avi = p_input->p_demux_data  ;
573
574     for( i = 0; i < p_avi->i_streams; i++ )
575     {
576         if( p_avi->pp_info[i] )
577         {
578             FREE( p_avi->pp_info[i]->p_index );
579             free( p_avi->pp_info[i] );
580         }
581     }
582     FREE( p_avi->pp_info );
583     if( p_avi->p_sub )
584     {
585         subtitle_Close( p_avi->p_sub );
586     }
587     AVI_ChunkFreeRoot( p_avi->s, &p_avi->ck_root );
588
589     stream_Release( p_avi->s );
590     free( p_avi );
591 }
592
593 /*****************************************************************************
594  * Demux_Seekable: reads and demuxes data packets for stream seekable
595  *****************************************************************************
596  * AVIDemux: reads and demuxes data packets
597  *****************************************************************************
598  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
599  *****************************************************************************/
600 typedef struct avi_stream_toread_s
601 {
602     vlc_bool_t b_ok;
603
604     int i_toread;
605
606     off_t i_posf; // where we will read :
607                   // if i_idxposb == 0 : begining of chunk (+8 to acces data)
608                   // else : point on data directly
609 } avi_stream_toread_t;
610
611 static int Demux_Seekable( input_thread_t *p_input )
612 {
613     unsigned int i_stream_count;
614     unsigned int i_stream;
615     vlc_bool_t b_stream;
616     vlc_bool_t b_play_audio;
617     vlc_bool_t b_video; /* is there some video track selected */
618     // cannot be more than 100 stream (dcXX or wbXX)
619     avi_stream_toread_t toread[100];
620
621     demux_sys_t *p_avi = p_input->p_demux_data;
622
623
624     /* detect new selected/unselected streams */
625     for( i_stream = 0,i_stream_count= 0, b_video = VLC_FALSE;
626             i_stream < p_avi->i_streams; i_stream++ )
627     {
628 #define p_stream    p_avi->pp_info[i_stream]
629         if( p_stream->p_es )
630         {
631             if( p_stream->p_es->p_decoder_fifo &&
632                 !p_stream->b_activated )
633             {
634                 AVI_StreamStart( p_input, i_stream );
635             }
636             else
637             if( !p_stream->p_es->p_decoder_fifo &&
638                 p_stream->b_activated )
639             {
640                 AVI_StreamStop( p_input, i_stream );
641             }
642         }
643         if( p_stream->b_activated )
644         {
645             i_stream_count++;
646             if( p_stream->i_cat == VIDEO_ES )
647             {
648                 b_video = VLC_TRUE;
649             }
650         }
651 #undef  p_stream
652     }
653
654     if( i_stream_count <= 0 )
655     {
656         msg_Warn( p_input, "no track selected, exiting..." );
657         return( 0 );
658     }
659
660     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
661     {
662         mtime_t i_date;
663         int i_percent;
664         /* first wait for empty buffer, arbitrary time FIXME */
665         //msleep( DEFAULT_PTS_DELAY );
666
667         i_date = (mtime_t)1000000 *
668                  (mtime_t)p_avi->i_length *
669                  (mtime_t)stream_Tell( p_avi->s ) /
670                  (mtime_t)stream_Size( p_avi->s );
671         i_percent = 100 * stream_Tell( p_avi->s ) /
672                           stream_Size( p_avi->s );
673
674         Seek( p_input, i_date, i_percent);
675
676         if( p_avi->p_sub )
677         {
678             subtitle_Seek( p_avi->p_sub, p_avi->i_time );
679         }
680     }
681
682
683     /* wait for the good time */
684
685     p_avi->i_pcr = p_avi->i_time * 9 / 100;
686
687     input_ClockManageRef( p_input,
688                           p_input->stream.p_selected_program,
689                           p_avi->i_pcr );
690
691
692     p_avi->i_time += 25*1000;  /* read 25ms */
693
694     if( p_avi->p_sub )
695     {
696         subtitle_Demux( p_avi->p_sub, p_avi->i_time );
697     }
698
699     /* Check if we need to send the audio data to decoder */
700     b_play_audio = !p_input->stream.control.b_mute;
701
702     /* init toread */
703     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
704     {
705 #define p_stream    p_avi->pp_info[i_stream]
706         mtime_t i_dpts;
707
708         toread[i_stream].b_ok = p_stream->b_activated;
709         if( p_stream->i_idxposc < p_stream->i_idxnb )
710         {
711             toread[i_stream].i_posf =
712                 p_stream->p_index[p_stream->i_idxposc].i_pos;
713            if( p_stream->i_idxposb > 0 )
714            {
715                 toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
716            }
717         }
718         else
719         {
720             toread[i_stream].i_posf = -1;
721         }
722
723         i_dpts = p_avi->i_time - AVI_GetPTS( p_stream  );
724
725         if( p_stream->i_samplesize )
726         {
727             toread[i_stream].i_toread = AVI_PTSToByte( p_stream,
728                                                        __ABS( i_dpts ) );
729         }
730         else
731         {
732             toread[i_stream].i_toread = AVI_PTSToChunk( p_stream,
733                                                         __ABS( i_dpts ) );
734         }
735
736         if( i_dpts < 0 )
737         {
738             toread[i_stream].i_toread *= -1;
739         }
740 #undef  p_stream
741     }
742
743     b_stream = VLC_FALSE;
744
745     for( ;; )
746     {
747 #define p_stream    p_avi->pp_info[i_stream]
748         vlc_bool_t       b_done;
749         pes_packet_t    *p_pes;
750         off_t i_pos;
751         unsigned int i;
752         size_t i_size;
753
754         /* search for first chunk to be read */
755         for( i = 0, b_done = VLC_TRUE, i_pos = -1; i < p_avi->i_streams; i++ )
756         {
757             if( !toread[i].b_ok ||
758                 AVI_GetDPTS( p_avi->pp_info[i],
759                              toread[i].i_toread ) <= -25 * 1000 )
760             {
761                 continue;
762             }
763
764             if( toread[i].i_toread > 0 )
765             {
766                 b_done = VLC_FALSE; // not yet finished
767             }
768
769             if( toread[i].i_posf > 0 )
770             {
771                 if( i_pos == -1 || i_pos > toread[i_stream].i_posf )
772                 {
773                     i_stream = i;
774                     i_pos = toread[i].i_posf;
775                 }
776             }
777         }
778
779         if( b_done )
780         {
781 //            return( b_stream ? 1 : 0 );
782             return( 1 );
783         }
784
785         if( i_pos == -1 )
786         {
787             /* no valid index, we will parse directly the stream
788              * in case we fail we will disable all finished stream */
789             if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin + 12 )
790             {
791                 stream_Seek( p_avi->s, p_avi->i_movi_lastchunk_pos );
792                 if( AVI_PacketNext( p_input ) )
793                 {
794                     return( AVI_StreamStopFinishedStreams( p_input ) ? 0 : 1 );
795                 }
796             }
797             else
798             {
799                 stream_Seek( p_avi->s, p_avi->i_movi_begin + 12 );
800             }
801
802             for( ;; )
803             {
804                 avi_packet_t avi_pk;
805
806                 if( AVI_PacketGetHeader( p_input, &avi_pk ) )
807                 {
808                     msg_Warn( p_input,
809                              "cannot get packet header, track disabled" );
810                     return( AVI_StreamStopFinishedStreams( p_input ) ? 0 : 1 );
811                 }
812                 if( avi_pk.i_stream >= p_avi->i_streams ||
813                     ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
814                 {
815                     if( AVI_PacketNext( p_input ) )
816                     {
817                         msg_Warn( p_input,
818                                   "cannot skip packet, track disabled" );
819                         return( AVI_StreamStopFinishedStreams( p_input ) ? 0 : 1 );
820                     }
821                     continue;
822                 }
823                 else
824                 {
825                     /* add this chunk to the index */
826                     AVIIndexEntry_t index;
827
828                     index.i_id = avi_pk.i_fourcc;
829                     index.i_flags =
830                        AVI_GetKeyFlag(p_avi->pp_info[avi_pk.i_stream]->i_codec,
831                                       avi_pk.i_peek);
832                     index.i_pos = avi_pk.i_pos;
833                     index.i_length = avi_pk.i_size;
834                     AVI_IndexAddEntry( p_avi, avi_pk.i_stream, &index );
835
836                     i_stream = avi_pk.i_stream;
837                     /* do we will read this data ? */
838                     if( AVI_GetDPTS( p_stream,
839                              toread[i_stream].i_toread ) > -25 * 1000 )
840                     {
841                         break;
842                     }
843                     else
844                     {
845                         if( AVI_PacketNext( p_input ) )
846                         {
847                             msg_Warn( p_input,
848                                       "cannot skip packet, track disabled" );
849                             return( AVI_StreamStopFinishedStreams( p_input ) ? 0 : 1 );
850                         }
851                     }
852                 }
853             }
854
855         }
856         else
857         {
858             stream_Seek( p_avi->s, i_pos );
859         }
860
861         /* read thoses data */
862         if( p_stream->i_samplesize )
863         {
864             unsigned int i_toread;
865
866             if( ( i_toread = toread[i_stream].i_toread ) <= 0 )
867             {
868                 if( p_stream->i_samplesize > 1 )
869                 {
870                     i_toread = p_stream->i_samplesize;
871                 }
872                 else
873                 {
874                     i_toread = __MAX( AVI_PTSToByte( p_stream, 20 * 1000 ), 100 );
875                 }
876             }
877             i_size = __MIN( p_stream->p_index[p_stream->i_idxposc].i_length -
878                                 p_stream->i_idxposb,
879                             i_toread );
880         }
881         else
882         {
883             i_size = p_stream->p_index[p_stream->i_idxposc].i_length;
884         }
885
886         if( p_stream->i_idxposb == 0 )
887         {
888             i_size += 8; // need to read and skip header
889         }
890
891         if( ( p_pes = stream_PesPacket( p_avi->s, __EVEN( i_size ) ) ) == NULL )
892         {
893             msg_Warn( p_input, "failled reading data" );
894             AVI_StreamStop( p_input, i_stream );
895             toread[i_stream].b_ok = VLC_FALSE;
896             continue;
897         }
898         if( i_size % 2 )    // read was padded on word boundary
899         {
900             p_pes->p_last->p_payload_end--;
901             p_pes->i_pes_size--;
902         }
903         // skip header
904         if( p_stream->i_idxposb == 0 )
905         {
906             p_pes->p_first->p_payload_start += 8;
907             p_pes->i_pes_size -= 8;
908         }
909
910         p_pes->i_pts = AVI_GetPTS( p_stream );
911
912 #if 0
913         /* fix pts for audio: ie pts sould be for the first byte of the first frame */
914         if( p_stream->i_samplesize == 1 )
915         {
916             AVI_FixPTS( p_stream, p_pes );
917         }
918 #endif
919
920         /* read data */
921         if( p_stream->i_samplesize )
922         {
923             if( p_stream->i_idxposb == 0 )
924             {
925                 i_size -= 8;
926             }
927             toread[i_stream].i_toread -= i_size;
928             p_stream->i_idxposb += i_size;
929             if( p_stream->i_idxposb >=
930                     p_stream->p_index[p_stream->i_idxposc].i_length )
931             {
932                 p_stream->i_idxposb = 0;
933                 p_stream->i_idxposc++;
934             }
935         }
936         else
937         {
938             toread[i_stream].i_toread--;
939             p_stream->i_idxposc++;
940         }
941
942         if( p_stream->i_idxposc < p_stream->i_idxnb)
943         {
944             toread[i_stream].i_posf =
945                 p_stream->p_index[p_stream->i_idxposc].i_pos;
946             if( p_stream->i_idxposb > 0 )
947             {
948                 toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
949             }
950
951         }
952         else
953         {
954             toread[i_stream].i_posf = -1;
955         }
956
957         b_stream = VLC_TRUE; // at least one read succeed
958
959         if( p_stream->p_es && p_stream->p_es->p_decoder_fifo &&
960             ( b_play_audio || p_stream->i_cat != AUDIO_ES ) )
961         {
962             p_pes->i_dts =
963                 p_pes->i_pts =
964                     input_ClockGetTS( p_input,
965                                       p_input->stream.p_selected_program,
966                                       p_pes->i_pts * 9/100);
967
968             p_pes->i_rate = p_input->stream.control.i_rate;
969
970             input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
971         }
972         else
973         {
974             input_DeletePES( p_input->p_method_data, p_pes );
975         }
976     }
977 }
978
979
980 /*****************************************************************************
981  * Demux_UnSeekable: reads and demuxes data packets for unseekable file
982  *****************************************************************************
983  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
984  *****************************************************************************/
985 static int Demux_UnSeekable( input_thread_t *p_input )
986 {
987     demux_sys_t     *p_avi = p_input->p_demux_data;
988     avi_stream_t *p_stream_master;
989     vlc_bool_t b_audio;
990     unsigned int i_stream;
991     unsigned int i_packet;
992
993     /* Check if we need to send the audio data to decoder */
994     b_audio = !p_input->stream.control.b_mute;
995
996     input_ClockManageRef( p_input,
997                           p_input->stream.p_selected_program,
998                           p_avi->i_pcr );
999     /* *** find master stream for data packet skipping algo *** */
1000     /* *** -> first video, if any, or first audio ES *** */
1001     for( i_stream = 0, p_stream_master = NULL;
1002             i_stream < p_avi->i_streams; i_stream++ )
1003     {
1004 #define p_stream    p_avi->pp_info[i_stream]
1005         if( p_stream->p_es &&
1006             p_stream->p_es->p_decoder_fifo )
1007         {
1008             if( p_stream->i_cat == VIDEO_ES )
1009             {
1010                 p_stream_master = p_stream;
1011                 break;
1012             }
1013             if( p_stream->i_cat == AUDIO_ES && !p_stream_master )
1014             {
1015                 p_stream_master = p_stream;
1016             }
1017         }
1018 #undef p_stream
1019     }
1020     if( !p_stream_master )
1021     {
1022         msg_Warn( p_input, "no more stream selected" );
1023         return( 0 );
1024     }
1025
1026     p_avi->i_pcr = AVI_GetPTS( p_stream_master ) * 9 / 100;
1027
1028     for( i_packet = 0; i_packet < 10; i_packet++)
1029     {
1030 #define p_stream    p_avi->pp_info[avi_pk.i_stream]
1031
1032         avi_packet_t    avi_pk;
1033
1034         if( AVI_PacketGetHeader( p_input, &avi_pk ) )
1035         {
1036             return( 0 );
1037         }
1038
1039         if( avi_pk.i_stream >= p_avi->i_streams ||
1040             ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1041         {
1042             /* we haven't found an audio or video packet:
1043              *  - we have seek, found first next packet
1044              *  - others packets could be found, skip them
1045              */
1046             switch( avi_pk.i_fourcc )
1047             {
1048                 case AVIFOURCC_JUNK:
1049                 case AVIFOURCC_LIST:
1050                 case AVIFOURCC_RIFF:
1051                     return( !AVI_PacketNext( p_input ) ? 1 : 0 );
1052                 case AVIFOURCC_idx1:
1053                     if( p_avi->b_odml )
1054                     {
1055                         return( !AVI_PacketNext( p_input ) ? 1 : 0 );
1056                     }
1057                     return( 0 );    // eof
1058                 default:
1059                     msg_Warn( p_input,
1060                               "seems to have lost position, resync" );
1061                     if( AVI_PacketSearch( p_input ) )
1062                     {
1063                         msg_Err( p_input, "resync failed" );
1064                         return( -1 );
1065                     }
1066             }
1067         }
1068         else
1069         {
1070             /* do will send this packet to decoder ? */
1071             if( ( !b_audio && avi_pk.i_cat == AUDIO_ES )||
1072                 !p_stream->p_es ||
1073                 !p_stream->p_es->p_decoder_fifo )
1074             {
1075                 if( AVI_PacketNext( p_input ) )
1076                 {
1077                     return( 0 );
1078                 }
1079             }
1080             else
1081             {
1082                 /* it's a selected stream, check for time */
1083                 if( __ABS( AVI_GetPTS( p_stream ) -
1084                             AVI_GetPTS( p_stream_master ) )< 600*1000 )
1085                 {
1086                     /* load it and send to decoder */
1087                     pes_packet_t    *p_pes;
1088                     if( AVI_PacketRead( p_input, &avi_pk, &p_pes ) || !p_pes)
1089                     {
1090                         return( -1 );
1091                     }
1092                     p_pes->i_dts =
1093                         p_pes->i_pts =
1094                             input_ClockGetTS( p_input,
1095                                           p_input->stream.p_selected_program,
1096                                           AVI_GetPTS( p_stream ) * 9/100);
1097
1098                     p_pes->i_rate = p_input->stream.control.i_rate;
1099
1100                     input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
1101                 }
1102                 else
1103                 {
1104                     if( AVI_PacketNext( p_input ) )
1105                     {
1106                         return( 0 );
1107                     }
1108                 }
1109             }
1110
1111             /* *** update stream time position *** */
1112             if( p_stream->i_samplesize )
1113             {
1114                 p_stream->i_idxposb += avi_pk.i_size;
1115             }
1116             else
1117             {
1118                 p_stream->i_idxposc++;
1119             }
1120
1121         }
1122
1123 #undef p_stream
1124     }
1125
1126     return( 1 );
1127 }
1128
1129 /*****************************************************************************
1130  * Seek: goto to i_date or i_percent
1131  *****************************************************************************
1132  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1133  *****************************************************************************/
1134 static int    Seek   ( input_thread_t *p_input,
1135                           mtime_t i_date, int i_percent )
1136 {
1137
1138     demux_sys_t *p_avi = p_input->p_demux_data;
1139     unsigned int i_stream;
1140     msg_Dbg( p_input,
1141              "seek requested: "I64Fd" secondes %d%%",
1142              i_date / 1000000,
1143              i_percent );
1144
1145     if( p_avi->b_seekable )
1146     {
1147         if( !p_avi->i_length || p_avi->b_interleaved )
1148         {
1149             avi_stream_t *p_stream;
1150             int64_t i_pos;
1151
1152             /* use i_percent to create a true i_date */
1153             if( !p_avi->b_interleaved )
1154             {
1155                 msg_Warn( p_input,
1156                           "mmh, seeking without index at %d%%"
1157                           " work only for interleaved file", i_percent );
1158             }
1159
1160             if( i_percent >= 100 )
1161             {
1162                 msg_Warn( p_input, "cannot seek so far !" );
1163                 return( -1 );
1164             }
1165             i_percent = __MAX( i_percent, 0 );
1166
1167             /* try to find chunk that is at i_percent or the file */
1168             i_pos = __MAX( i_percent *
1169                            stream_Size( p_avi->s ) / 100,
1170                            p_avi->i_movi_begin );
1171             /* search first selected stream */
1172             for( i_stream = 0, p_stream = NULL;
1173                         i_stream < p_avi->i_streams; i_stream++ )
1174             {
1175                 p_stream = p_avi->pp_info[i_stream];
1176                 if( p_stream->b_activated )
1177                 {
1178                     break;
1179                 }
1180             }
1181             if( !p_stream || !p_stream->b_activated )
1182             {
1183                 msg_Warn( p_input, "cannot find any selected stream" );
1184                 return( -1 );
1185             }
1186
1187             /* be sure that the index exit */
1188             if( AVI_StreamChunkSet( p_input,
1189                                     i_stream,
1190                                     0 ) )
1191             {
1192                 msg_Warn( p_input, "cannot seek" );
1193                 return( -1 );
1194             }
1195
1196             while( i_pos >= p_stream->p_index[p_stream->i_idxposc].i_pos +
1197                p_stream->p_index[p_stream->i_idxposc].i_length + 8 )
1198             {
1199                 /* search after i_idxposc */
1200                 if( AVI_StreamChunkSet( p_input,
1201                                         i_stream, p_stream->i_idxposc + 1 ) )
1202                 {
1203                     msg_Warn( p_input, "cannot seek" );
1204                     return( -1 );
1205                 }
1206             }
1207             i_date = AVI_GetPTS( p_stream );
1208             /* TODO better support for i_samplesize != 0 */
1209             msg_Dbg( p_input, "estimate date "I64Fd, i_date );
1210         }
1211
1212 #define p_stream    p_avi->pp_info[i_stream]
1213         p_avi->i_time = 0;
1214         /* seek for chunk based streams */
1215         for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1216         {
1217             if( p_stream->b_activated && !p_stream->i_samplesize )
1218 //            if( p_stream->b_activated )
1219             {
1220                 AVI_StreamSeek( p_input, i_stream, i_date );
1221                 p_avi->i_time = __MAX( AVI_GetPTS( p_stream ),
1222                                         p_avi->i_time );
1223             }
1224         }
1225 #if 1
1226         if( p_avi->i_time )
1227         {
1228             i_date = p_avi->i_time;
1229         }
1230         /* seek for bytes based streams */
1231         for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1232         {
1233             if( p_stream->b_activated && p_stream->i_samplesize )
1234             {
1235                 AVI_StreamSeek( p_input, i_stream, i_date );
1236 //                p_avi->i_time = __MAX( AVI_GetPTS( p_stream ), p_avi->i_time );
1237             }
1238         }
1239         msg_Dbg( p_input, "seek: "I64Fd" secondes", p_avi->i_time /1000000 );
1240         /* set true movie time */
1241 #endif
1242         if( !p_avi->i_time )
1243         {
1244             p_avi->i_time = i_date;
1245         }
1246 #undef p_stream
1247         return( 1 );
1248     }
1249     else
1250     {
1251         msg_Err( p_input, "shouldn't yet be executed" );
1252         return( -1 );
1253     }
1254 }
1255
1256
1257 /*****************************************************************************
1258  * Function to convert pts to chunk or byte
1259  *****************************************************************************/
1260
1261 static mtime_t AVI_PTSToChunk( avi_stream_t *tk, mtime_t i_pts )
1262 {
1263     return (mtime_t)((int64_t)i_pts *
1264                      (int64_t)tk->i_rate /
1265                      (int64_t)tk->i_scale /
1266                      (int64_t)1000000 );
1267 }
1268 static mtime_t AVI_PTSToByte( avi_stream_t *tk, mtime_t i_pts )
1269 {
1270     return (mtime_t)((int64_t)i_pts *
1271                      (int64_t)tk->i_rate /
1272                      (int64_t)tk->i_scale /
1273                      (int64_t)1000000 *
1274                      (int64_t)tk->i_samplesize );
1275 }
1276
1277 static mtime_t AVI_GetDPTS( avi_stream_t *tk, int64_t i_count )
1278 {
1279     mtime_t i_dpts;
1280
1281     i_dpts = (mtime_t)( (int64_t)1000000 *
1282                         (int64_t)i_count *
1283                         (int64_t)tk->i_scale /
1284                         (int64_t)tk->i_rate );
1285
1286     if( tk->i_samplesize )
1287     {
1288         return i_dpts / tk->i_samplesize;
1289     }
1290     return i_dpts;
1291 }
1292
1293 static mtime_t AVI_GetPTS( avi_stream_t *tk )
1294 {
1295     if( tk->i_samplesize )
1296     {
1297         int64_t i_count = 0;
1298
1299         /* we need a valid entry we will emulate one */
1300         if( tk->i_idxposc == tk->i_idxnb )
1301         {
1302             if( tk->i_idxposc )
1303             {
1304                 /* use the last entry */
1305                 i_count = tk->p_index[tk->i_idxnb - 1].i_lengthtotal
1306                             + tk->p_index[tk->i_idxnb - 1].i_length;
1307             }
1308         }
1309         else
1310         {
1311             i_count = tk->p_index[tk->i_idxposc].i_lengthtotal;
1312         }
1313         return AVI_GetDPTS( tk, i_count + tk->i_idxposb );
1314     }
1315     else
1316     {
1317         return AVI_GetDPTS( tk, tk->i_idxposc );
1318     }
1319 }
1320
1321 #if 0
1322 static void AVI_FixPTS( avi_stream_t *p_stream, pes_packet_t *p_pes )
1323 {
1324     data_packet_t *p_data;
1325     uint8_t       *p;
1326     int           i_pos = 0;
1327
1328     switch( p_stream->i_fourcc )
1329     {
1330         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
1331             p_data = p_pes->p_first;
1332             while( p_data )
1333             {
1334                 p = p_data->p_payload_start;
1335                 while( p < p_data->p_payload_end - 2 )
1336                 {
1337                     if( p[0] == 0xff && ( p[1]&0xe0) == 0xe0 )
1338                     {
1339                         mtime_t i_diff = AVI_GetDPTS( p_stream, i_pos );
1340                         p_pes->i_dts += i_diff;
1341                         p_pes->i_pts += i_diff;
1342                         return;
1343                     }
1344                     p++; i_pos++;
1345                 }
1346                 p_data = p_data->p_next;
1347             }
1348             return;
1349         case VLC_FOURCC( 'a', '5', '2', ' ' ):
1350             p_data = p_pes->p_first;
1351             while( p_data )
1352             {
1353                 p = p_data->p_payload_start;
1354                 while( p < p_data->p_payload_end - 2 )
1355                 {
1356                     if( p[0] == 0x0b && p[1] == 0x77 )
1357                     {
1358                         mtime_t i_diff = AVI_GetDPTS( p_stream, i_pos );
1359                         p_pes->i_dts += i_diff;
1360                         p_pes->i_pts += i_diff;
1361                     }
1362                     p++; i_pos++;
1363                 }
1364                 p_data = p_data->p_next;
1365             }
1366             return;
1367         default:
1368             /* we can't fix :( */
1369             return;
1370     }
1371 }
1372 #endif
1373
1374 static int AVI_StreamChunkFind( input_thread_t *p_input,
1375                                 unsigned int i_stream )
1376 {
1377     demux_sys_t *p_avi = p_input->p_demux_data;
1378     avi_packet_t avi_pk;
1379
1380     /* find first chunk of i_stream that isn't in index */
1381
1382     if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin + 12 )
1383     {
1384         stream_Seek( p_avi->s, p_avi->i_movi_lastchunk_pos );
1385         if( AVI_PacketNext( p_input ) )
1386         {
1387             return VLC_EGENERIC;
1388         }
1389     }
1390     else
1391     {
1392         stream_Seek( p_avi->s, p_avi->i_movi_begin + 12 );
1393     }
1394
1395     for( ;; )
1396     {
1397
1398         if( AVI_PacketGetHeader( p_input, &avi_pk ) )
1399         {
1400             msg_Warn( p_input, "cannot get packet header" );
1401             return VLC_EGENERIC;
1402         }
1403         if( avi_pk.i_stream >= p_avi->i_streams ||
1404             ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1405         {
1406             if( AVI_PacketNext( p_input ) )
1407             {
1408                 return VLC_EGENERIC;
1409             }
1410         }
1411         else
1412         {
1413             /* add this chunk to the index */
1414             AVIIndexEntry_t index;
1415
1416             index.i_id = avi_pk.i_fourcc;
1417             index.i_flags =
1418                AVI_GetKeyFlag(p_avi->pp_info[avi_pk.i_stream]->i_codec,
1419                               avi_pk.i_peek);
1420             index.i_pos = avi_pk.i_pos;
1421             index.i_length = avi_pk.i_size;
1422             AVI_IndexAddEntry( p_avi, avi_pk.i_stream, &index );
1423
1424             if( avi_pk.i_stream == i_stream  )
1425             {
1426                 return VLC_SUCCESS;
1427             }
1428
1429             if( AVI_PacketNext( p_input ) )
1430             {
1431                 return VLC_EGENERIC;
1432             }
1433         }
1434     }
1435 }
1436
1437
1438 /* be sure that i_ck will be a valid index entry */
1439 static int AVI_StreamChunkSet( input_thread_t    *p_input,
1440                                unsigned int i_stream,
1441                                unsigned int i_ck )
1442 {
1443     demux_sys_t *p_avi = p_input->p_demux_data;
1444     avi_stream_t *p_stream = p_avi->pp_info[i_stream];
1445
1446     p_stream->i_idxposc = i_ck;
1447     p_stream->i_idxposb = 0;
1448
1449     if(  i_ck >= p_stream->i_idxnb )
1450     {
1451         p_stream->i_idxposc = p_stream->i_idxnb - 1;
1452         do
1453         {
1454             p_stream->i_idxposc++;
1455             if( AVI_StreamChunkFind( p_input, i_stream ) )
1456             {
1457                 return VLC_EGENERIC;
1458             }
1459
1460         } while( p_stream->i_idxposc < i_ck );
1461     }
1462
1463     return VLC_SUCCESS;
1464 }
1465
1466
1467 /* XXX FIXME up to now, we assume that all chunk are one after one */
1468 static int AVI_StreamBytesSet( input_thread_t    *p_input,
1469                                unsigned int i_stream,
1470                                off_t   i_byte )
1471 {
1472     demux_sys_t *p_avi = p_input->p_demux_data;
1473     avi_stream_t *p_stream = p_avi->pp_info[i_stream];
1474
1475     if( ( p_stream->i_idxnb > 0 )
1476         &&( i_byte < p_stream->p_index[p_stream->i_idxnb - 1].i_lengthtotal +
1477                 p_stream->p_index[p_stream->i_idxnb - 1].i_length ) )
1478     {
1479         /* index is valid to find the ck */
1480         /* uses dichototmie to be fast enougth */
1481         int i_idxposc = __MIN( p_stream->i_idxposc, p_stream->i_idxnb - 1 );
1482         int i_idxmax  = p_stream->i_idxnb;
1483         int i_idxmin  = 0;
1484         for( ;; )
1485         {
1486             if( p_stream->p_index[i_idxposc].i_lengthtotal > i_byte )
1487             {
1488                 i_idxmax  = i_idxposc ;
1489                 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1490             }
1491             else
1492             {
1493                 if( p_stream->p_index[i_idxposc].i_lengthtotal +
1494                         p_stream->p_index[i_idxposc].i_length <= i_byte)
1495                 {
1496                     i_idxmin  = i_idxposc ;
1497                     i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1498                 }
1499                 else
1500                 {
1501                     p_stream->i_idxposc = i_idxposc;
1502                     p_stream->i_idxposb = i_byte -
1503                             p_stream->p_index[i_idxposc].i_lengthtotal;
1504                     return VLC_SUCCESS;
1505                 }
1506             }
1507         }
1508
1509     }
1510     else
1511     {
1512         p_stream->i_idxposc = p_stream->i_idxnb - 1;
1513         p_stream->i_idxposb = 0;
1514         do
1515         {
1516             p_stream->i_idxposc++;
1517             if( AVI_StreamChunkFind( p_input, i_stream ) )
1518             {
1519                 return VLC_EGENERIC;
1520             }
1521
1522         } while( p_stream->p_index[p_stream->i_idxposc].i_lengthtotal +
1523                     p_stream->p_index[p_stream->i_idxposc].i_length <= i_byte );
1524
1525         p_stream->i_idxposb = i_byte -
1526                        p_stream->p_index[p_stream->i_idxposc].i_lengthtotal;
1527         return VLC_SUCCESS;
1528     }
1529 }
1530
1531 static int AVI_StreamSeek( input_thread_t *p_input,
1532                            int i_stream,
1533                            mtime_t i_date )
1534 {
1535     demux_sys_t  *p_avi = p_input->p_demux_data;
1536 #define p_stream    p_avi->pp_info[i_stream]
1537     mtime_t i_oldpts;
1538
1539     i_oldpts = AVI_GetPTS( p_stream );
1540
1541     if( !p_stream->i_samplesize )
1542     {
1543         if( AVI_StreamChunkSet( p_input,
1544                                 i_stream,
1545                                 AVI_PTSToChunk( p_stream, i_date ) ) )
1546         {
1547             return VLC_EGENERIC;
1548         }
1549
1550         msg_Dbg( p_input,
1551                  "old:"I64Fd" %s new "I64Fd,
1552                  i_oldpts,
1553                  i_oldpts > i_date ? ">" : "<",
1554                  i_date );
1555
1556         if( p_stream->i_cat == VIDEO_ES )
1557         {
1558             /* search key frame */
1559             if( i_date < i_oldpts )
1560             {
1561                 while( p_stream->i_idxposc > 0 &&
1562                    !( p_stream->p_index[p_stream->i_idxposc].i_flags &
1563                                                                 AVIIF_KEYFRAME ) )
1564                 {
1565                     if( AVI_StreamChunkSet( p_input,
1566                                             i_stream,
1567                                             p_stream->i_idxposc - 1 ) )
1568                     {
1569                         return VLC_EGENERIC;
1570                     }
1571                 }
1572             }
1573             else
1574             {
1575                 while( p_stream->i_idxposc < p_stream->i_idxnb &&
1576                         !( p_stream->p_index[p_stream->i_idxposc].i_flags &
1577                                                                 AVIIF_KEYFRAME ) )
1578                 {
1579                     if( AVI_StreamChunkSet( p_input,
1580                                             i_stream,
1581                                             p_stream->i_idxposc + 1 ) )
1582                     {
1583                         return VLC_EGENERIC;
1584                     }
1585                 }
1586             }
1587         }
1588     }
1589     else
1590     {
1591         if( AVI_StreamBytesSet( p_input,
1592                                 i_stream,
1593                                 AVI_PTSToByte( p_stream, i_date ) ) )
1594         {
1595             return VLC_EGENERIC;
1596         }
1597     }
1598     return VLC_SUCCESS;
1599 #undef p_stream
1600 }
1601
1602 /*****************************************************************************
1603  * AVI_Interleaved: check weither a file is interleaved or not.
1604  *****************************************************************************/
1605 static vlc_bool_t AVI_Interleaved( input_thread_t *p_input )
1606 {
1607     demux_sys_t     *p_sys = p_input->p_demux_data;
1608     unsigned int    i;
1609     mtime_t         i_time = 0;
1610     vlc_bool_t      b_ret = VLC_TRUE;
1611
1612     int64_t         i_max;
1613
1614     if( stream_Size( p_sys->s ) <= 100 )
1615     {
1616         return VLC_FALSE;
1617     }
1618
1619     i_max = __MIN( 2000000, stream_Size( p_sys->s ) / 100 );
1620
1621 #define tk p_sys->pp_info[i]
1622     while( i_time < p_sys->i_length * (mtime_t)1000000)
1623     {
1624         int64_t     i_ref;
1625
1626         i_ref = -1;
1627         i_time += 50000;
1628         for( i = 0; i < p_sys->i_streams; i++ )
1629         {
1630             while( AVI_GetPTS( tk ) < i_time && tk->i_idxposc < tk->i_idxnb - 1 )
1631             {
1632                 tk->i_idxposc++;
1633             }
1634
1635             if( i_ref == -1 )
1636             {
1637                 i_ref = tk->p_index[tk->i_idxposc].i_pos;
1638             }
1639             if( __ABS( tk->p_index[tk->i_idxposc].i_pos - i_ref ) > i_max ||
1640                 tk->p_index[tk->i_idxposc].i_length > i_max )
1641             {
1642                 msg_Dbg( p_input, "interleaved=no because ref=%lld pos=%lld length=%d (max=%lld)",
1643                          i_ref, tk->p_index[tk->i_idxposc].i_pos, tk->p_index[tk->i_idxposc].i_length, i_max  );
1644                 b_ret = VLC_FALSE;
1645                 goto exit;
1646             }
1647         }
1648     }
1649
1650 exit:
1651     for( i = 0; i < p_sys->i_streams; i++ )
1652     {
1653         tk->i_idxposc = 0;
1654         tk->i_idxposb = 0;
1655     }
1656 #undef tk
1657     return b_ret;
1658 }
1659
1660 /****************************************************************************
1661  * Return VLC_TRUE if it's a key frame
1662  ****************************************************************************/
1663 static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, uint8_t *p_byte )
1664 {
1665     switch( i_fourcc )
1666     {
1667         case FOURCC_DIV1:
1668             /* we have:
1669              *  startcode:      0x00000100   32bits
1670              *  framenumber     ?             5bits
1671              *  piture type     0(I),1(P)     2bits
1672              */
1673             if( GetDWBE( p_byte ) != 0x00000100 )
1674             {
1675                 /* it's not an msmpegv1 stream, strange...*/
1676                 return AVIIF_KEYFRAME;
1677             }
1678             else
1679             {
1680                 return p_byte[4] & 0x06 ? 0 : AVIIF_KEYFRAME;
1681             }
1682         case FOURCC_DIV2:
1683         case FOURCC_DIV3:   // wmv1 also
1684             /* we have
1685              *  picture type    0(I),1(P)     2bits
1686              */
1687             return p_byte[0] & 0xC0 ? 0 : AVIIF_KEYFRAME;
1688         case FOURCC_mp4v:
1689             /* we should find first occurence of 0x000001b6 (32bits)
1690              *  startcode:      0x000001b6   32bits
1691              *  piture type     0(I),1(P)     2bits
1692              */
1693             if( GetDWBE( p_byte ) != 0x000001b6 )
1694             {
1695                 /* not true , need to find the first VOP header */
1696                 return AVIIF_KEYFRAME;
1697             }
1698             else
1699             {
1700                 return p_byte[4] & 0xC0 ? 0 : AVIIF_KEYFRAME;
1701             }
1702         default:
1703             /* I can't do it, so say yes */
1704             return AVIIF_KEYFRAME;
1705     }
1706 }
1707
1708 vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t i_codec )
1709 {
1710     switch( i_cat )
1711     {
1712         case AUDIO_ES:
1713             wf_tag_to_fourcc( i_codec, &i_codec, NULL );
1714             return i_codec;
1715
1716         case VIDEO_ES:
1717             // XXX DIV1 <- msmpeg4v1, DIV2 <- msmpeg4v2, DIV3 <- msmpeg4v3, mp4v for mpeg4
1718             switch( i_codec )
1719             {
1720                 case FOURCC_DIV1:
1721                 case FOURCC_div1:
1722                 case FOURCC_MPG4:
1723                 case FOURCC_mpg4:
1724                     return FOURCC_DIV1;
1725                 case FOURCC_DIV2:
1726                 case FOURCC_div2:
1727                 case FOURCC_MP42:
1728                 case FOURCC_mp42:
1729                 case FOURCC_MPG3:
1730                 case FOURCC_mpg3:
1731                     return FOURCC_DIV2;
1732                 case FOURCC_div3:
1733                 case FOURCC_MP43:
1734                 case FOURCC_mp43:
1735                 case FOURCC_DIV3:
1736                 case FOURCC_DIV4:
1737                 case FOURCC_div4:
1738                 case FOURCC_DIV5:
1739                 case FOURCC_div5:
1740                 case FOURCC_DIV6:
1741                 case FOURCC_div6:
1742                 case FOURCC_AP41:
1743                 case FOURCC_3IV1:
1744                 case FOURCC_3iv1:
1745                 case FOURCC_3IVD:
1746                 case FOURCC_3ivd:
1747                 case FOURCC_3VID:
1748                 case FOURCC_3vid:
1749                     return FOURCC_DIV3;
1750                 case FOURCC_DIVX:
1751                 case FOURCC_divx:
1752                 case FOURCC_MP4S:
1753                 case FOURCC_mp4s:
1754                 case FOURCC_M4S2:
1755                 case FOURCC_m4s2:
1756                 case FOURCC_xvid:
1757                 case FOURCC_XVID:
1758                 case FOURCC_XviD:
1759                 case FOURCC_DX50:
1760                 case FOURCC_mp4v:
1761                 case FOURCC_4:
1762                 case FOURCC_3IV2:
1763                 case FOURCC_3iv2:
1764                     return FOURCC_mp4v;
1765             }
1766         default:
1767             return VLC_FOURCC( 'u', 'n', 'd', 'f' );
1768     }
1769 }
1770
1771 /****************************************************************************
1772  *
1773  ****************************************************************************/
1774 static void AVI_ParseStreamHeader( vlc_fourcc_t i_id,
1775                                    int *pi_number, int *pi_type )
1776 {
1777 #define SET_PTR( p, v ) if( p ) *(p) = (v);
1778     int c1, c2;
1779
1780     c1 = ((uint8_t *)&i_id)[0];
1781     c2 = ((uint8_t *)&i_id)[1];
1782
1783     if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
1784     {
1785         SET_PTR( pi_number, 100 ); /* > max stream number */
1786         SET_PTR( pi_type, UNKNOWN_ES );
1787     }
1788     else
1789     {
1790         SET_PTR( pi_number, (c1 - '0') * 10 + (c2 - '0' ) );
1791         switch( VLC_TWOCC( ((uint8_t *)&i_id)[2], ((uint8_t *)&i_id)[3] ) )
1792         {
1793             case AVITWOCC_wb:
1794                 SET_PTR( pi_type, AUDIO_ES );
1795                 break;
1796             case AVITWOCC_dc:
1797             case AVITWOCC_db:
1798                 SET_PTR( pi_type, VIDEO_ES );
1799                 break;
1800             default:
1801                 SET_PTR( pi_type, UNKNOWN_ES );
1802                 break;
1803         }
1804     }
1805 #undef SET_PTR
1806 }
1807
1808 /****************************************************************************
1809  *
1810  ****************************************************************************/
1811 static int AVI_PacketGetHeader( input_thread_t *p_input, avi_packet_t *p_pk )
1812 {
1813     demux_sys_t *p_sys = p_input->p_demux_data;
1814     uint8_t  *p_peek;
1815
1816     if( stream_Peek( p_sys->s, &p_peek, 16 ) < 16 )
1817     {
1818         return VLC_EGENERIC;
1819     }
1820     p_pk->i_fourcc  = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] );
1821     p_pk->i_size    = GetDWLE( p_peek + 4 );
1822     p_pk->i_pos     = stream_Tell( p_sys->s );
1823     if( p_pk->i_fourcc == AVIFOURCC_LIST || p_pk->i_fourcc == AVIFOURCC_RIFF )
1824     {
1825         p_pk->i_type = VLC_FOURCC( p_peek[8],  p_peek[9],
1826                                    p_peek[10], p_peek[11] );
1827     }
1828     else
1829     {
1830         p_pk->i_type = 0;
1831     }
1832
1833     memcpy( p_pk->i_peek, p_peek + 8, 8 );
1834
1835     AVI_ParseStreamHeader( p_pk->i_fourcc, &p_pk->i_stream, &p_pk->i_cat );
1836     return VLC_SUCCESS;
1837 }
1838
1839 static int AVI_PacketNext( input_thread_t *p_input )
1840 {
1841     demux_sys_t *p_sys = p_input->p_demux_data;
1842     avi_packet_t    avi_ck;
1843     int             i_skip = 0;
1844
1845     if( AVI_PacketGetHeader( p_input, &avi_ck ) )
1846     {
1847         return VLC_EGENERIC;
1848     }
1849
1850     if( avi_ck.i_fourcc == AVIFOURCC_LIST &&
1851         ( avi_ck.i_type == AVIFOURCC_rec || avi_ck.i_type == AVIFOURCC_movi ) )
1852     {
1853         i_skip = 12;
1854     }
1855     else if( avi_ck.i_fourcc == AVIFOURCC_RIFF &&
1856              avi_ck.i_type == AVIFOURCC_AVIX )
1857     {
1858         i_skip = 24;
1859     }
1860     else
1861     {
1862         i_skip = __EVEN( avi_ck.i_size ) + 8;
1863     }
1864
1865     if( stream_Read( p_sys->s, NULL, i_skip ) != i_skip )
1866     {
1867         return VLC_EGENERIC;
1868     }
1869     return VLC_SUCCESS;
1870 }
1871 static int AVI_PacketRead( input_thread_t   *p_input,
1872                            avi_packet_t     *p_pk,
1873                            pes_packet_t     **pp_pes )
1874 {
1875     demux_sys_t *p_sys = p_input->p_demux_data;
1876
1877     size_t i_size;
1878
1879     i_size = __EVEN( p_pk->i_size + 8 );
1880
1881     if( ( *pp_pes = stream_PesPacket( p_sys->s, i_size ) ) == NULL )
1882     {
1883         return VLC_EGENERIC;
1884     }
1885     (*pp_pes)->p_first->p_payload_start += 8;
1886     (*pp_pes)->i_pes_size -= 8;
1887
1888     if( i_size != p_pk->i_size + 8 )
1889     {
1890         (*pp_pes)->p_last->p_payload_end--;
1891         (*pp_pes)->i_pes_size--;
1892     }
1893
1894     return VLC_SUCCESS;
1895 }
1896
1897 static int AVI_PacketSearch( input_thread_t *p_input )
1898 {
1899     demux_sys_t     *p_avi = p_input->p_demux_data;
1900
1901     avi_packet_t    avi_pk;
1902     for( ;; )
1903     {
1904         if( stream_Read( p_avi->s, NULL, 1 ) != 1 )
1905         {
1906             return VLC_EGENERIC;
1907         }
1908         AVI_PacketGetHeader( p_input, &avi_pk );
1909         if( avi_pk.i_stream < p_avi->i_streams &&
1910             ( avi_pk.i_cat == AUDIO_ES || avi_pk.i_cat == VIDEO_ES ) )
1911         {
1912             return VLC_SUCCESS;
1913         }
1914         switch( avi_pk.i_fourcc )
1915         {
1916             case AVIFOURCC_JUNK:
1917             case AVIFOURCC_LIST:
1918             case AVIFOURCC_RIFF:
1919             case AVIFOURCC_idx1:
1920                 return VLC_SUCCESS;
1921         }
1922     }
1923 }
1924
1925 /****************************************************************************
1926  * Index stuff.
1927  ****************************************************************************/
1928 static void AVI_IndexAddEntry( demux_sys_t *p_avi,
1929                                int i_stream,
1930                                AVIIndexEntry_t *p_index)
1931 {
1932     avi_stream_t *tk = p_avi->pp_info[i_stream];
1933
1934     /* Update i_movi_lastchunk_pos */
1935     if( p_avi->i_movi_lastchunk_pos < p_index->i_pos )
1936     {
1937         p_avi->i_movi_lastchunk_pos = p_index->i_pos;
1938     }
1939
1940     /* add the entry */
1941     if( tk->i_idxnb >= tk->i_idxmax )
1942     {
1943         tk->i_idxmax += 16384;
1944         tk->p_index = realloc( tk->p_index,
1945                                tk->i_idxmax * sizeof( AVIIndexEntry_t ) );
1946         if( tk->p_index == NULL )
1947         {
1948             return;
1949         }
1950     }
1951     /* calculate cumulate length */
1952     if( tk->i_idxnb > 0 )
1953     {
1954         p_index->i_lengthtotal =
1955             tk->p_index[tk->i_idxnb - 1].i_length +
1956                 tk->p_index[tk->i_idxnb - 1].i_lengthtotal;
1957     }
1958     else
1959     {
1960         p_index->i_lengthtotal = 0;
1961     }
1962
1963     tk->p_index[tk->i_idxnb++] = *p_index;
1964 }
1965
1966 static int AVI_IndexLoad_idx1( input_thread_t *p_input )
1967 {
1968     demux_sys_t *p_avi = p_input->p_demux_data;
1969
1970     avi_chunk_list_t    *p_riff;
1971     avi_chunk_list_t    *p_movi;
1972     avi_chunk_idx1_t    *p_idx1;
1973
1974     unsigned int i_stream;
1975     unsigned int i_index;
1976     off_t        i_offset;
1977     unsigned int i;
1978
1979     p_riff = AVI_ChunkFind( &p_avi->ck_root, AVIFOURCC_RIFF, 0);
1980     p_idx1 = AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0);
1981     p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
1982
1983     if( !p_idx1 )
1984     {
1985         msg_Warn( p_input, "cannot find idx1 chunk, no index defined" );
1986         return VLC_EGENERIC;
1987     }
1988
1989     /* *** calculate offset *** */
1990     /* Well, avi is __SHIT__ so test more than one entry 
1991      * (needed for some avi files) */
1992     i_offset = 0;
1993     for( i = 0; i < __MIN( p_idx1->i_entry_count, 10 ); i++ )
1994     {
1995         if( p_idx1->entry[i].i_pos < p_movi->i_chunk_pos )
1996         {
1997             i_offset = p_movi->i_chunk_pos + 8;
1998             break;
1999         }
2000     }
2001
2002     for( i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )
2003     {
2004         unsigned int i_cat;
2005
2006         AVI_ParseStreamHeader( p_idx1->entry[i_index].i_fourcc,
2007                                &i_stream,
2008                                &i_cat );
2009         if( i_stream < p_avi->i_streams &&
2010             i_cat == p_avi->pp_info[i_stream]->i_cat )
2011         {
2012             AVIIndexEntry_t index;
2013             index.i_id      = p_idx1->entry[i_index].i_fourcc;
2014             index.i_flags   =
2015                 p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME);
2016             index.i_pos     = p_idx1->entry[i_index].i_pos + i_offset;
2017             index.i_length  = p_idx1->entry[i_index].i_length;
2018             AVI_IndexAddEntry( p_avi, i_stream, &index );
2019         }
2020     }
2021     return VLC_SUCCESS;
2022 }
2023
2024 static void __Parse_indx( input_thread_t    *p_input,
2025                           int               i_stream,
2026                           avi_chunk_indx_t  *p_indx )
2027 {
2028     demux_sys_t         *p_avi    = p_input->p_demux_data;
2029     AVIIndexEntry_t     index;
2030     int32_t             i;
2031
2032     msg_Dbg( p_input, "loading subindex(0x%x) %d entries", p_indx->i_indextype, p_indx->i_entriesinuse );
2033     if( p_indx->i_indexsubtype == 0 )
2034     {
2035         for( i = 0; i < p_indx->i_entriesinuse; i++ )
2036         {
2037             index.i_id      = p_indx->i_id;
2038             index.i_flags   = p_indx->idx.std[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
2039             index.i_pos     = p_indx->i_baseoffset + p_indx->idx.std[i].i_offset - 8;
2040             index.i_length  = p_indx->idx.std[i].i_size&0x7fffffff;
2041
2042             AVI_IndexAddEntry( p_avi, i_stream, &index );
2043         }
2044     }
2045     else if( p_indx->i_indexsubtype == AVI_INDEX_2FIELD )
2046     {
2047         for( i = 0; i < p_indx->i_entriesinuse; i++ )
2048         {
2049             index.i_id      = p_indx->i_id;
2050             index.i_flags   = p_indx->idx.field[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
2051             index.i_pos     = p_indx->i_baseoffset + p_indx->idx.field[i].i_offset - 8;
2052             index.i_length  = p_indx->idx.field[i].i_size;
2053
2054             AVI_IndexAddEntry( p_avi, i_stream, &index );
2055         }
2056     }
2057     else
2058     {
2059         msg_Warn( p_input, "unknow subtype index(0x%x)", p_indx->i_indexsubtype );
2060     }
2061 }
2062
2063 static void AVI_IndexLoad_indx( input_thread_t *p_input )
2064 {
2065     demux_sys_t         *p_avi = p_input->p_demux_data;
2066     unsigned int        i_stream;
2067     int32_t             i;
2068
2069     avi_chunk_list_t    *p_riff;
2070     avi_chunk_list_t    *p_hdrl;
2071
2072     p_riff = AVI_ChunkFind( &p_avi->ck_root, AVIFOURCC_RIFF, 0);
2073     p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
2074
2075     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
2076     {
2077         avi_chunk_list_t    *p_strl;
2078         avi_chunk_indx_t    *p_indx;
2079
2080 #define p_stream  p_avi->pp_info[i_stream]
2081         p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream );
2082         p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0 );
2083
2084         if( !p_indx )
2085         {
2086             msg_Warn( p_input, "cannot find indx (misdetect/broken OpenDML file?)" );
2087             continue;
2088         }
2089
2090         if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS )
2091         {
2092             __Parse_indx( p_input, i_stream, p_indx );
2093         }
2094         else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )
2095         {
2096             avi_chunk_indx_t    ck_sub;
2097             for( i = 0; i < p_indx->i_entriesinuse; i++ )
2098             {
2099                 if( stream_Seek( p_avi->s, p_indx->idx.super[i].i_offset )||
2100                     AVI_ChunkRead( p_avi->s, &ck_sub, NULL  ) )
2101                 {
2102                     break;
2103                 }
2104                 __Parse_indx( p_input, i_stream, &ck_sub );
2105             }
2106         }
2107         else
2108         {
2109             msg_Warn( p_input, "unknow type index(0x%x)", p_indx->i_indextype );
2110         }
2111 #undef p_stream
2112     }
2113 }
2114
2115 static void AVI_IndexLoad( input_thread_t *p_input )
2116 {
2117     demux_sys_t *p_avi = p_input->p_demux_data;
2118     unsigned int i_stream;
2119
2120     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
2121     {
2122         p_avi->pp_info[i_stream]->i_idxnb  = 0;
2123         p_avi->pp_info[i_stream]->i_idxmax = 0;
2124         p_avi->pp_info[i_stream]->p_index  = NULL;
2125     }
2126
2127     if( p_avi->b_odml )
2128     {
2129         AVI_IndexLoad_indx( p_input );
2130     }
2131     else  if( AVI_IndexLoad_idx1( p_input ) )
2132     {
2133         /* try indx if idx1 failed as some "normal" file have indx too */
2134         AVI_IndexLoad_indx( p_input );
2135     }
2136
2137     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
2138     {
2139         msg_Dbg( p_input, "stream[%d] created %d index entries",
2140                 i_stream, p_avi->pp_info[i_stream]->i_idxnb );
2141     }
2142 }
2143
2144 static void AVI_IndexCreate( input_thread_t *p_input )
2145 {
2146     demux_sys_t *p_avi = p_input->p_demux_data;
2147
2148     avi_chunk_list_t    *p_riff;
2149     avi_chunk_list_t    *p_movi;
2150
2151     unsigned int i_stream;
2152     off_t i_movi_end;
2153
2154     p_riff = AVI_ChunkFind( &p_avi->ck_root, AVIFOURCC_RIFF, 0);
2155     p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
2156
2157     if( !p_movi )
2158     {
2159         msg_Err( p_input, "cannot find p_movi" );
2160         return;
2161     }
2162
2163     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
2164     {
2165         p_avi->pp_info[i_stream]->i_idxnb  = 0;
2166         p_avi->pp_info[i_stream]->i_idxmax = 0;
2167         p_avi->pp_info[i_stream]->p_index  = NULL;
2168     }
2169     i_movi_end = __MIN( (off_t)(p_movi->i_chunk_pos + p_movi->i_chunk_size),
2170                         stream_Size( p_avi->s ) );
2171
2172     stream_Seek( p_avi->s, p_movi->i_chunk_pos + 12 );
2173     msg_Warn( p_input, "creating index from LIST-movi, will take time !" );
2174     for( ;; )
2175     {
2176         avi_packet_t pk;
2177
2178         if( AVI_PacketGetHeader( p_input, &pk ) )
2179         {
2180             break;
2181         }
2182         if( pk.i_stream < p_avi->i_streams &&
2183             pk.i_cat == p_avi->pp_info[pk.i_stream]->i_cat )
2184         {
2185             AVIIndexEntry_t index;
2186             index.i_id      = pk.i_fourcc;
2187             index.i_flags   =
2188                AVI_GetKeyFlag(p_avi->pp_info[pk.i_stream]->i_codec, pk.i_peek);
2189             index.i_pos     = pk.i_pos;
2190             index.i_length  = pk.i_size;
2191             AVI_IndexAddEntry( p_avi, pk.i_stream, &index );
2192         }
2193         else
2194         {
2195             switch( pk.i_fourcc )
2196             {
2197                 case AVIFOURCC_idx1:
2198                     if( p_avi->b_odml )
2199                     {
2200                         avi_chunk_list_t *p_avix;
2201                         p_avix = AVI_ChunkFind( &p_avi->ck_root,
2202                                                 AVIFOURCC_RIFF, 1 );
2203
2204                         msg_Dbg( p_input, "looking for new RIFF chunk" );
2205                         if( stream_Seek( p_avi->s, p_avix->i_chunk_pos + 24 ) )
2206                         {
2207                             goto print_stat;
2208                         }
2209                         break;
2210                     }
2211                     goto print_stat;
2212                 case AVIFOURCC_RIFF:
2213                         msg_Dbg( p_input, "new RIFF chunk found" );
2214                 case AVIFOURCC_rec:
2215                 case AVIFOURCC_JUNK:
2216                     break;
2217                 default:
2218                     msg_Warn( p_input, "need resync, probably broken avi" );
2219                     if( AVI_PacketSearch( p_input ) )
2220                     {
2221                         msg_Warn( p_input, "lost sync, abord index creation" );
2222                         goto print_stat;
2223                     }
2224             }
2225         }
2226
2227         if( ( !p_avi->b_odml && pk.i_pos + pk.i_size >= i_movi_end ) ||
2228             AVI_PacketNext( p_input ) )
2229         {
2230             break;
2231         }
2232     }
2233
2234 print_stat:
2235     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
2236     {
2237         msg_Dbg( p_input,
2238                 "stream[%d] creating %d index entries",
2239                 i_stream,
2240                 p_avi->pp_info[i_stream]->i_idxnb );
2241     }
2242 }
2243
2244 /*****************************************************************************
2245  * Stream management
2246  *****************************************************************************/
2247 static vlc_bool_t AVI_StreamStart( input_thread_t *p_input, int i_stream )
2248 {
2249     demux_sys_t *p_avi = p_input->p_demux_data;
2250     avi_stream_t *tk = p_avi->pp_info[i_stream];
2251
2252     if( !tk->p_es )
2253     {
2254         msg_Warn( p_input, "stream[%d] unselectable", i_stream );
2255         return VLC_FALSE;
2256     }
2257     if( tk->b_activated )
2258     {
2259         msg_Warn( p_input, "stream[%d] already selected", i_stream );
2260         return VLC_TRUE;
2261     }
2262
2263     if( !tk->p_es->p_decoder_fifo )
2264     {
2265         vlc_mutex_lock( &p_input->stream.stream_lock );
2266         input_SelectES( p_input, tk->p_es );
2267         vlc_mutex_unlock( &p_input->stream.stream_lock );
2268     }
2269     tk->b_activated = tk->p_es->p_decoder_fifo ? VLC_TRUE : VLC_FALSE;
2270     if( tk->b_activated && p_avi->b_seekable)
2271     {
2272         AVI_StreamSeek( p_input, i_stream, p_avi->i_time );
2273     }
2274
2275     return tk->b_activated;
2276 }
2277
2278 static void    AVI_StreamStop( input_thread_t *p_input, int i_stream )
2279 {
2280     demux_sys_t  *p_avi = p_input->p_demux_data;
2281     avi_stream_t *tk = p_avi->pp_info[i_stream];
2282
2283     if( !tk->b_activated )
2284     {
2285         msg_Warn( p_input, "stream[%d] already unselected", i_stream );
2286         return;
2287     }
2288
2289     if( tk->p_es->p_decoder_fifo )
2290     {
2291         vlc_mutex_lock( &p_input->stream.stream_lock );
2292         input_UnselectES( p_input, tk->p_es );
2293         vlc_mutex_unlock( &p_input->stream.stream_lock );
2294     }
2295
2296     tk->b_activated = VLC_FALSE;
2297 }
2298
2299 static int AVI_StreamStopFinishedStreams( input_thread_t *p_input )
2300 {
2301     demux_sys_t *p_avi = p_input->p_demux_data;
2302     unsigned int i;
2303     int b_end = VLC_TRUE;
2304
2305     for( i = 0; i < p_avi->i_streams; i++ )
2306     {
2307 #define tk    p_avi->pp_info[i]
2308         if( tk->i_idxposc >= tk->i_idxnb )
2309         {
2310             AVI_StreamStop( p_input, i );
2311         }
2312         else
2313         {
2314             b_end = VLC_FALSE;
2315         }
2316 #undef  tk
2317     }
2318     return( b_end );
2319 }
2320
2321 /****************************************************************************
2322  * AVI_MovieGetLength give max streams length in second
2323  ****************************************************************************/
2324 static mtime_t  AVI_MovieGetLength( input_thread_t *p_input )
2325 {
2326     demux_sys_t  *p_sys = p_input->p_demux_data;
2327     mtime_t      i_maxlength = 0;
2328     unsigned int i;
2329
2330     for( i = 0; i < p_sys->i_streams; i++ )
2331     {
2332 #define tk  p_sys->pp_info[i]
2333         mtime_t i_length;
2334
2335         /* fix length for each stream */
2336         if( tk->i_idxnb < 1 || !tk->p_index )
2337         {
2338             continue;
2339         }
2340
2341         if( tk->i_samplesize )
2342         {
2343             i_length = AVI_GetDPTS( tk,
2344                                     tk->p_index[tk->i_idxnb-1].i_lengthtotal +
2345                                         tk->p_index[tk->i_idxnb-1].i_length );
2346         }
2347         else
2348         {
2349             i_length = AVI_GetDPTS( tk, tk->i_idxnb );
2350         }
2351         i_length /= (mtime_t)1000000;    /* in seconds */
2352
2353         msg_Dbg( p_input,
2354                  "stream[%d] length:"I64Fd" (based on index)",
2355                  i,
2356                  i_length );
2357         i_maxlength = __MAX( i_maxlength, i_length );
2358 #undef tk
2359     }
2360
2361     return i_maxlength;
2362 }
2363
2364