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