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