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