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