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