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