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