1 /*****************************************************************************
2 * avi.c : AVI file Stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001-2009 VLC authors and VideoLAN
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_demux.h>
38 #include <vlc_input.h>
40 #include <vlc_dialog.h>
43 #include <vlc_codecs.h>
44 #include <vlc_charset.h>
45 #include <vlc_memory.h>
50 /*****************************************************************************
52 *****************************************************************************/
54 #define INTERLEAVE_TEXT N_("Force interleaved method" )
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)." )
61 static int Open ( vlc_object_t
* );
62 static void Close( vlc_object_t
* );
64 static const int pi_index
[] = {0,1,2,3};
66 static const char *const ppsz_indexes
[] = { N_("Ask for action"),
69 N_("Fix when necessary")};
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
)
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
)
84 set_callbacks( Open
, Close
)
87 /*****************************************************************************
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
* );
95 static char *FromACP( const char *str
)
97 return FromCharset(vlc_pgettext("GetACP", "CP1252"), str
, strlen(str
));
100 #define IGNORE_ES DATA_ES
101 #define READ_LENGTH (25 * 1000) // 25ms
102 #define READ_LENGTH_NONINTERLEAVED (CLOCK_FREQ * 3 / 2)
108 vlc_fourcc_t i_fourcc
;
111 vlc_fourcc_t i_type
; /* only for AVIFOURCC_LIST */
113 uint8_t i_peek
[8]; /* first 8 bytes */
115 unsigned int i_stream
;
116 enum es_format_category_e i_cat
;
126 int64_t i_lengthtotal
;
134 avi_entry_t
*p_entry
;
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
*, uint32_t *, avi_entry_t
* );
147 unsigned int i_scale
;
148 unsigned int i_samplesize
;
150 unsigned int i_width_bytes
;
155 int i_next_block_flags
;
158 es_out_id_t
*p_es_dv_audio
;
163 unsigned int i_idxposc
; /* numero of chunk */
164 unsigned int i_idxposb
; /* byte in the current chunk */
166 /* For VBR audio only */
167 unsigned int i_blockno
;
168 unsigned int i_blocksize
;
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
;
187 uint32_t i_movi_begin
;
188 uint32_t i_movi_lastchunk_pos
; /* XXX position of last valid chunk */
190 /* number of streams and information */
191 unsigned int i_track
;
197 unsigned int i_attachment
;
198 input_attachment_t
**attachment
;
201 #define __EVEN(x) (((x) & 1) ? (x) + 1 : (x))
203 static int64_t AVI_PTSToChunk( avi_track_t
*, mtime_t i_pts
);
204 static int64_t AVI_PTSToByte ( avi_track_t
*, mtime_t i_pts
);
205 static mtime_t
AVI_GetDPTS ( avi_track_t
*, int64_t i_count
);
206 static mtime_t
AVI_GetPTS ( avi_track_t
* );
209 static int AVI_StreamChunkFind( demux_t
*, unsigned int i_stream
);
210 static int AVI_StreamChunkSet ( demux_t
*,
211 unsigned int i_stream
, unsigned int i_ck
);
212 static int AVI_StreamBytesSet ( demux_t
*,
213 unsigned int i_stream
, uint32_t i_byte
);
215 vlc_fourcc_t
AVI_FourccGetCodec( unsigned int i_cat
, vlc_fourcc_t
);
216 static int AVI_GetKeyFlag ( vlc_fourcc_t
, uint8_t * );
218 static int AVI_PacketGetHeader( demux_t
*, avi_packet_t
*p_pk
);
219 static int AVI_PacketNext ( demux_t
* );
220 static int AVI_PacketSearch ( demux_t
* );
222 static void AVI_IndexLoad ( demux_t
* );
223 static void AVI_IndexCreate ( demux_t
* );
225 static void AVI_ExtractSubtitle( demux_t
*, unsigned int i_stream
, avi_chunk_list_t
*, avi_chunk_STRING_t
* );
227 static void AVI_DvHandleAudio( demux_t
*, avi_track_t
*, block_t
* );
229 static mtime_t
AVI_MovieGetLength( demux_t
* );
231 static void AVI_MetaLoad( demux_t
*, avi_chunk_list_t
*p_riff
, avi_chunk_avih_t
*p_avih
);
233 /*****************************************************************************
235 *****************************************************************************/
236 static int AVI_TrackSeek ( demux_t
*, int, mtime_t
);
237 static int AVI_TrackStopFinishedStreams( demux_t
*);
240 - For VBR mp3 stream:
241 count blocks by rounded-up chunksizes instead of chunks
242 we need full emulation of dshow avi demuxer bugs :(
243 fixes silly nandub-style a-v delaying in avi with vbr mp3...
244 (from mplayer 2002/08/02)
248 /*****************************************************************************
249 * Close: frees unused data
250 *****************************************************************************/
251 static void Close ( vlc_object_t
* p_this
)
253 demux_t
* p_demux
= (demux_t
*)p_this
;
254 demux_sys_t
*p_sys
= p_demux
->p_sys
;
256 for( unsigned int i
= 0; i
< p_sys
->i_track
; i
++ )
258 if( p_sys
->track
[i
] )
260 es_format_Clean( &p_sys
->track
[i
]->fmt
);
261 avi_index_Clean( &p_sys
->track
[i
]->idx
);
262 free( p_sys
->track
[i
] );
265 free( p_sys
->track
);
267 AVI_ChunkFreeRoot( p_demux
->s
, &p_sys
->ck_root
);
269 vlc_meta_Delete( p_sys
->meta
);
271 for( unsigned i
= 0; i
< p_sys
->i_attachment
; i
++)
272 vlc_input_attachment_Delete(p_sys
->attachment
[i
]);
273 free(p_sys
->attachment
);
278 /*****************************************************************************
279 * Open: check file and initializes AVI structures
280 *****************************************************************************/
281 static int Open( vlc_object_t
* p_this
)
283 demux_t
*p_demux
= (demux_t
*)p_this
;
286 bool b_index
= false, b_aborted
= false;
289 avi_chunk_list_t
*p_riff
;
290 avi_chunk_list_t
*p_hdrl
, *p_movi
;
291 avi_chunk_avih_t
*p_avih
;
293 unsigned int i_track
;
294 unsigned int i_peeker
;
296 const uint8_t *p_peek
;
298 /* Is it an avi file ? */
299 if( vlc_stream_Peek( p_demux
->s
, &p_peek
, 200 ) < 200 )
302 for( i_peeker
= 0; i_peeker
< 188; i_peeker
++ )
304 if( !strncmp( (char *)&p_peek
[0], "RIFF", 4 ) && !strncmp( (char *)&p_peek
[8], "AVI ", 4 ) )
306 if( !strncmp( (char *)&p_peek
[0], "ON2 ", 4 ) && !strncmp( (char *)&p_peek
[8], "ON2f", 4 ) )
310 if( i_peeker
== 188 )
316 && vlc_stream_Read( p_demux
->s
, NULL
, i_peeker
) < i_peeker
)
319 /* Initialize input structures. */
320 p_sys
= p_demux
->p_sys
= calloc( 1, sizeof(demux_sys_t
) );
321 if( unlikely(!p_sys
) )
323 p_sys
->b_odml
= false;
325 TAB_INIT(p_sys
->i_track
, p_sys
->track
);
326 TAB_INIT(p_sys
->i_attachment
, p_sys
->attachment
);
328 vlc_stream_Control( p_demux
->s
, STREAM_CAN_FASTSEEK
,
329 &p_sys
->b_fastseekable
);
330 vlc_stream_Control( p_demux
->s
, STREAM_CAN_SEEK
, &p_sys
->b_seekable
);
332 p_sys
->b_interleaved
= var_InheritBool( p_demux
, "avi-interleaved" );
334 if( AVI_ChunkReadRoot( p_demux
->s
, &p_sys
->ck_root
) )
336 msg_Err( p_demux
, "avi module discarded (invalid file)" );
341 if( AVI_ChunkCount( &p_sys
->ck_root
, AVIFOURCC_RIFF
, true ) > 1 )
343 unsigned int i_count
=
344 AVI_ChunkCount( &p_sys
->ck_root
, AVIFOURCC_RIFF
, true );
346 msg_Warn( p_demux
, "multiple riff -> OpenDML ?" );
347 for( unsigned i
= 1; i
< i_count
; i
++ )
349 avi_chunk_list_t
*p_sysx
;
351 p_sysx
= AVI_ChunkFind( &p_sys
->ck_root
, AVIFOURCC_RIFF
, i
, true );
352 if( p_sysx
&& p_sysx
->i_type
== AVIFOURCC_AVIX
)
354 msg_Warn( p_demux
, "detected OpenDML file" );
355 p_sys
->b_odml
= true;
361 p_riff
= AVI_ChunkFind( &p_sys
->ck_root
, AVIFOURCC_RIFF
, 0, true );
362 p_hdrl
= AVI_ChunkFind( p_riff
, AVIFOURCC_hdrl
, 0, true );
363 p_movi
= AVI_ChunkFind( p_riff
, AVIFOURCC_movi
, 0, true );
365 p_movi
= AVI_ChunkFind( &p_sys
->ck_root
, AVIFOURCC_movi
, 0, true );
367 if( !p_hdrl
|| !p_movi
)
369 msg_Err( p_demux
, "invalid file: cannot find hdrl or movi chunks" );
373 if( !( p_avih
= AVI_ChunkFind( p_hdrl
, AVIFOURCC_avih
, 0, false ) ) )
375 msg_Err( p_demux
, "invalid file: cannot find avih chunk" );
378 i_track
= AVI_ChunkCount( p_hdrl
, AVIFOURCC_strl
, true );
379 if( p_avih
->i_streams
!= i_track
)
382 "found %d stream but %d are declared",
383 i_track
, p_avih
->i_streams
);
387 msg_Err( p_demux
, "no stream defined!" );
391 /* print information on streams */
392 msg_Dbg( p_demux
, "AVIH: %d stream, flags %s%s%s%s ",
394 p_avih
->i_flags
&AVIF_HASINDEX
?" HAS_INDEX":"",
395 p_avih
->i_flags
&AVIF_MUSTUSEINDEX
?" MUST_USE_INDEX":"",
396 p_avih
->i_flags
&AVIF_ISINTERLEAVED
?" IS_INTERLEAVED":"",
397 p_avih
->i_flags
&AVIF_TRUSTCKTYPE
?" TRUST_CKTYPE":"" );
399 p_sys
->b_interleaved
|= (p_avih
->i_flags
& AVIF_ISINTERLEAVED
);
402 p_demux
->pf_control
= Control
;
404 if( p_sys
->b_fastseekable
)
406 p_demux
->pf_demux
= Demux_Seekable
;
407 p_sys
->i_read_increment
= READ_LENGTH
;
409 else if( p_sys
->b_seekable
)
411 p_demux
->pf_demux
= Demux_Seekable
;
412 p_sys
->i_read_increment
= READ_LENGTH_NONINTERLEAVED
;
413 if( !p_sys
->b_interleaved
)
414 msg_Warn( p_demux
, "Non interleaved content over slow seekable, "
415 "expect bad performance" );
419 msg_Warn( p_demux
, "Non seekable content " );
421 p_demux
->pf_demux
= Demux_UnSeekable
;
422 p_sys
->i_read_increment
= READ_LENGTH_NONINTERLEAVED
;
423 /* non seekable and non interleaved case ? well... */
424 if( !p_sys
->b_interleaved
)
426 msg_Warn( p_demux
, "Non seekable non interleaved content, "
427 "disabling other tracks" );
428 i_track
= __MIN(i_track
, 1);
432 AVI_MetaLoad( p_demux
, p_riff
, p_avih
);
433 p_sys
->i_avih_flags
= p_avih
->i_flags
;
435 /* now read info on each stream and create ES */
436 for( unsigned i
= 0 ; i
< i_track
; i
++ )
438 avi_track_t
*tk
= calloc( 1, sizeof( avi_track_t
) );
439 if( unlikely( !tk
) )
442 avi_chunk_list_t
*p_strl
= AVI_ChunkFind( p_hdrl
, AVIFOURCC_strl
, i
, true );
443 avi_chunk_strh_t
*p_strh
= AVI_ChunkFind( p_strl
, AVIFOURCC_strh
, 0, false );
444 avi_chunk_STRING_t
*p_strn
= AVI_ChunkFind( p_strl
, AVIFOURCC_strn
, 0, false );
445 avi_chunk_strf_auds_t
*p_auds
= NULL
;
446 avi_chunk_strf_vids_t
*p_vids
= NULL
;
449 tk
->b_activated
= true;
451 p_vids
= (avi_chunk_strf_vids_t
*)AVI_ChunkFind( p_strl
, AVIFOURCC_strf
, 0, false );
452 p_auds
= (avi_chunk_strf_auds_t
*)p_vids
;
454 if( p_strl
== NULL
|| p_strh
== NULL
|| p_vids
== NULL
)
456 msg_Warn( p_demux
, "stream[%d] incomplete", i
);
461 tk
->i_rate
= p_strh
->i_rate
;
462 tk
->i_scale
= p_strh
->i_scale
;
463 tk
->i_samplesize
= p_strh
->i_samplesize
;
464 msg_Dbg( p_demux
, "stream[%u] rate:%u scale:%u samplesize:%u",
465 i
, tk
->i_rate
, tk
->i_scale
, tk
->i_samplesize
);
466 if( tk
->i_scale
> tk
->i_rate
)
472 switch( p_strh
->i_type
)
474 case( AVIFOURCC_auds
):
476 es_format_Init( &tk
->fmt
, AUDIO_ES
, 0 );
478 if( p_auds
->p_wf
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
&&
479 p_auds
->p_wf
->cbSize
>= sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
) )
481 WAVEFORMATEXTENSIBLE
*p_wfe
= (WAVEFORMATEXTENSIBLE
*)p_auds
->p_wf
;
482 tk
->fmt
.i_codec
= AVI_FourccGetCodec( AUDIO_ES
, p_wfe
->SubFormat
.Data1
);
485 tk
->fmt
.i_codec
= AVI_FourccGetCodec( AUDIO_ES
, p_auds
->p_wf
->wFormatTag
);
487 tk
->i_blocksize
= p_auds
->p_wf
->nBlockAlign
;
488 if( tk
->i_blocksize
== 0 )
490 if( p_auds
->p_wf
->wFormatTag
== 1 )
491 tk
->i_blocksize
= p_auds
->p_wf
->nChannels
* (p_auds
->p_wf
->wBitsPerSample
/8);
495 else if( tk
->i_samplesize
!= 0 && tk
->i_samplesize
!= tk
->i_blocksize
)
497 msg_Warn( p_demux
, "track[%u] samplesize=%u and blocksize=%u are not equal."
498 "Using blocksize as a workaround.",
499 i
, tk
->i_samplesize
, tk
->i_blocksize
);
500 tk
->i_samplesize
= tk
->i_blocksize
;
503 if( tk
->fmt
.i_codec
== VLC_CODEC_VORBIS
)
505 tk
->i_blocksize
= 0; /* fix vorbis VBR decoding */
508 if ( tk
->fmt
.i_codec
== VLC_CODEC_MP4A
)
510 tk
->i_samplesize
= 0; /* ADTS/AAC VBR */
513 /* Fix broken scale/rate */
514 if ( tk
->fmt
.i_codec
== VLC_CODEC_ADPCM_IMA_WAV
&&
515 tk
->i_samplesize
&& tk
->i_samplesize
> tk
->i_rate
)
518 tk
->i_rate
= p_auds
->p_wf
->nSamplesPerSec
;
521 /* From libavformat */
522 /* Fix broken sample size (which is mp2 num samples / frame) #12722 */
523 if( tk
->fmt
.i_codec
== VLC_CODEC_MPGA
&&
524 tk
->i_samplesize
== 1152 && p_auds
->p_wf
->nBlockAlign
== 1152 )
526 p_auds
->p_wf
->nBlockAlign
= tk
->i_samplesize
= 0;
529 tk
->fmt
.audio
.i_channels
= p_auds
->p_wf
->nChannels
;
530 tk
->fmt
.audio
.i_rate
= p_auds
->p_wf
->nSamplesPerSec
;
531 tk
->fmt
.i_bitrate
= p_auds
->p_wf
->nAvgBytesPerSec
*8;
532 tk
->fmt
.audio
.i_blockalign
= p_auds
->p_wf
->nBlockAlign
;
533 tk
->fmt
.audio
.i_bitspersample
= p_auds
->p_wf
->wBitsPerSample
;
534 tk
->fmt
.b_packetized
= !tk
->i_blocksize
;
536 avi_chunk_list_t
*p_info
= AVI_ChunkFind( p_riff
, AVIFOURCC_INFO
, 0, true );
539 int i_chunk
= AVIFOURCC_IAS1
+ ((i
- 1) << 24);
540 avi_chunk_STRING_t
*p_lang
= AVI_ChunkFind( p_info
, i_chunk
, 0, false );
541 if( p_lang
!= NULL
&& p_lang
->p_str
!= NULL
)
542 tk
->fmt
.psz_language
= FromACP( p_lang
->p_str
);
546 "stream[%u] audio(0x%x - %s) %d channels %dHz %dbits",
547 i
, p_auds
->p_wf
->wFormatTag
,
548 vlc_fourcc_GetDescription(AUDIO_ES
, tk
->fmt
.i_codec
),
549 p_auds
->p_wf
->nChannels
,
550 p_auds
->p_wf
->nSamplesPerSec
,
551 p_auds
->p_wf
->wBitsPerSample
);
553 const size_t i_cboff
= sizeof(WAVEFORMATEX
);
554 const size_t i_incboff
= ( p_auds
->p_wf
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
) ?
555 sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
): 0;
556 if( p_auds
->i_chunk_size
>= i_cboff
+ p_auds
->p_wf
->cbSize
&&
557 p_auds
->p_wf
->cbSize
> i_incboff
)
559 int i_extra
= p_auds
->p_wf
->cbSize
- i_incboff
;
560 tk
->fmt
.p_extra
= malloc( i_extra
);
561 if( unlikely(tk
->fmt
.p_extra
== NULL
) )
563 es_format_Clean( &tk
->fmt
);
567 tk
->fmt
.i_extra
= i_extra
;
568 memcpy( tk
->fmt
.p_extra
, ((uint8_t *)(&p_auds
->p_wf
[1])) + i_incboff
, i_extra
);
573 case( AVIFOURCC_vids
):
575 if( p_vids
->p_bih
->biCompression
== VLC_FOURCC( 'D', 'X', 'S', 'B' ) )
577 msg_Dbg( p_demux
, "stream[%u] subtitles", i
);
578 es_format_Init( &tk
->fmt
, SPU_ES
, p_vids
->p_bih
->biCompression
);
582 es_format_Init( &tk
->fmt
, VIDEO_ES
,
583 AVI_FourccGetCodec( VIDEO_ES
, p_vids
->p_bih
->biCompression
) );
585 if( p_vids
->p_bih
->biCompression
== BI_RGB
)
587 switch( p_vids
->p_bih
->biBitCount
)
590 tk
->fmt
.i_codec
= VLC_CODEC_RGB32
;
593 tk
->fmt
.i_codec
= VLC_CODEC_RGB24
;
595 case 16: /* Yes it is RV15 */
597 tk
->fmt
.i_codec
= VLC_CODEC_RGB15
;
599 case 9: /* <- TODO check that */
600 tk
->fmt
.i_codec
= VLC_CODEC_I410
;
603 if ( p_vids
->p_bih
->biClrUsed
)
604 tk
->fmt
.i_codec
= VLC_CODEC_RGBP
;
606 tk
->fmt
.i_codec
= VLC_CODEC_GREY
;
610 switch( tk
->fmt
.i_codec
)
612 case VLC_CODEC_RGB24
:
613 case VLC_CODEC_RGB32
: /* BGR (see biBitCount) */
614 tk
->fmt
.video
.i_bmask
= 0x00ff0000;
615 tk
->fmt
.video
.i_gmask
= 0x0000ff00;
616 tk
->fmt
.video
.i_rmask
= 0x000000ff;
618 case VLC_CODEC_RGB15
: /* RGB (B least 5 bits) */
619 tk
->fmt
.video
.i_rmask
= 0x7c00;
620 tk
->fmt
.video
.i_gmask
= 0x03e0;
621 tk
->fmt
.video
.i_bmask
= 0x001f;
625 const VLC_BITMAPINFO
*p_bi
= (const VLC_BITMAPINFO
*) p_vids
->p_bih
;
626 tk
->fmt
.video
.p_palette
= malloc( sizeof(video_palette_t
) );
627 if ( tk
->fmt
.video
.p_palette
)
630 for( uint32_t j
= 0; j
< p_vids
->p_bih
->biClrUsed
; j
++ )
632 entry
= GetDWBE( &p_bi
->bmiColors
[j
] );
633 tk
->fmt
.video
.p_palette
->palette
[j
][0] = entry
>> 24;
634 tk
->fmt
.video
.p_palette
->palette
[j
][1] = (entry
>> 16) & 0xFF;
635 tk
->fmt
.video
.p_palette
->palette
[j
][2] = (entry
>> 8) & 0xFF;
636 tk
->fmt
.video
.p_palette
->palette
[j
][3] = entry
& 0xFF;
638 tk
->fmt
.video
.p_palette
->i_entries
= p_vids
->p_bih
->biClrUsed
;
646 tk
->i_width_bytes
= p_vids
->p_bih
->biWidth
* (p_vids
->p_bih
->biBitCount
>> 3);
647 /* RGB DIB are coded from bottom to top */
648 if ( p_vids
->p_bih
->biHeight
< INT32_MAX
) tk
->b_flipped
= true;
652 tk
->fmt
.i_codec
= p_vids
->p_bih
->biCompression
;
653 if( tk
->fmt
.i_codec
== VLC_CODEC_MP4V
&&
654 !strncasecmp( (char*)&p_strh
->i_handler
, "XVID", 4 ) )
657 tk
->fmt
.i_original_fourcc
= VLC_FOURCC( 'X', 'V', 'I', 'D' );
660 tk
->i_samplesize
= 0;
662 tk
->fmt
.video
.i_visible_width
=
663 tk
->fmt
.video
.i_width
= p_vids
->p_bih
->biWidth
;
664 tk
->fmt
.video
.i_visible_height
=
665 tk
->fmt
.video
.i_height
= p_vids
->p_bih
->biHeight
;
666 tk
->fmt
.video
.i_bits_per_pixel
= p_vids
->p_bih
->biBitCount
;
667 tk
->fmt
.video
.i_frame_rate
= tk
->i_rate
;
668 tk
->fmt
.video
.i_frame_rate_base
= tk
->i_scale
;
670 /* Uncompresse Bitmap or YUV, YUV being always topdown */
671 if ( tk
->fmt
.video
.i_height
> INT32_MAX
)
672 tk
->fmt
.video
.i_height
=
673 (unsigned int)(-(int)p_vids
->p_bih
->biHeight
);
675 avi_chunk_vprp_t
*p_vprp
= AVI_ChunkFind( p_strl
, AVIFOURCC_vprp
, 0, false );
678 uint32_t i_frame_aspect_ratio
= p_vprp
->i_frame_aspect_ratio
;
679 if( p_vprp
->i_video_format_token
>= 1 &&
680 p_vprp
->i_video_format_token
<= 4 )
681 i_frame_aspect_ratio
= 0x00040003;
682 tk
->fmt
.video
.i_sar_num
= ((i_frame_aspect_ratio
>> 16) & 0xffff) *
683 tk
->fmt
.video
.i_height
;
684 tk
->fmt
.video
.i_sar_den
= ((i_frame_aspect_ratio
>> 0) & 0xffff) *
685 tk
->fmt
.video
.i_width
;
687 /* Extradata is the remainder of the chunk less the BIH */
688 if( p_vids
->i_chunk_size
<= INT_MAX
- sizeof(VLC_BITMAPINFOHEADER
) )
690 int i_extra
= p_vids
->i_chunk_size
- sizeof(VLC_BITMAPINFOHEADER
);
693 tk
->fmt
.p_extra
= malloc( i_extra
);
694 if( unlikely(tk
->fmt
.p_extra
== NULL
) )
696 es_format_Clean( &tk
->fmt
);
700 tk
->fmt
.i_extra
= i_extra
;
701 memcpy( tk
->fmt
.p_extra
, &p_vids
->p_bih
[1], tk
->fmt
.i_extra
);
705 msg_Dbg( p_demux
, "stream[%u] video(%4.4s) %"PRIu32
"x%"PRIu32
" %dbpp %ffps",
706 i
, (char*)&p_vids
->p_bih
->biCompression
,
707 (uint32_t)p_vids
->p_bih
->biWidth
,
708 (uint32_t)p_vids
->p_bih
->biHeight
,
709 p_vids
->p_bih
->biBitCount
,
710 (float)tk
->i_rate
/(float)tk
->i_scale
);
712 /* Extract palette from extradata if bpp <= 8 */
713 if( tk
->fmt
.video
.i_bits_per_pixel
> 0 && tk
->fmt
.video
.i_bits_per_pixel
<= 8 )
715 /* The palette should not be included in biSize, but come
716 * directly after BITMAPINFORHEADER in the BITMAPINFO structure */
717 if( tk
->fmt
.i_extra
> 0 )
719 free( tk
->fmt
.video
.p_palette
);
720 tk
->fmt
.video
.p_palette
= calloc( 1, sizeof(video_palette_t
) );
721 if( likely(tk
->fmt
.video
.p_palette
) )
723 const uint8_t *p_pal
= tk
->fmt
.p_extra
;
724 tk
->fmt
.video
.p_palette
->i_entries
= __MIN(tk
->fmt
.i_extra
/4, 256);
725 for( int k
= 0; k
< tk
->fmt
.video
.p_palette
->i_entries
; k
++ )
727 for( int j
= 0; j
< 4; j
++ )
728 tk
->fmt
.video
.p_palette
->palette
[k
][j
] = p_pal
[4*k
+j
];
736 case( AVIFOURCC_txts
):
737 msg_Dbg( p_demux
, "stream[%u] subtitle attachment", i
);
738 AVI_ExtractSubtitle( p_demux
, i
, p_strl
, p_strn
);
742 case( AVIFOURCC_iavs
):
743 case( AVIFOURCC_ivas
):
744 msg_Dbg( p_demux
, "stream[%u] iavs with handler %4.4s", i
, (char *)&p_strh
->i_handler
);
745 es_format_Init( &tk
->fmt
, VIDEO_ES
, p_strh
->i_handler
);
746 tk
->i_samplesize
= 0;
747 tk
->i_dv_audio_rate
= p_strh
->i_handler
== VLC_CODEC_DV
? -1 : 0;
749 tk
->fmt
.video
.i_visible_width
=
750 tk
->fmt
.video
.i_width
= p_avih
->i_width
;
751 tk
->fmt
.video
.i_visible_height
=
752 tk
->fmt
.video
.i_height
= p_avih
->i_height
;
755 case( AVIFOURCC_mids
):
756 msg_Dbg( p_demux
, "stream[%u] midi is UNSUPPORTED", i
);
760 msg_Warn( p_demux
, "stream[%u] unknown type %4.4s", i
, (char *)&p_strh
->i_type
);
764 if( p_strn
&& p_strn
->p_str
)
765 tk
->fmt
.psz_description
= FromACP( p_strn
->p_str
);
766 tk
->p_es
= es_out_Add( p_demux
->out
, &tk
->fmt
);
767 TAB_APPEND( p_sys
->i_track
, p_sys
->track
, tk
);
770 if( p_sys
->i_track
<= 0 )
772 msg_Err( p_demux
, "no valid track" );
776 i_do_index
= var_InheritInteger( p_demux
, "avi-index" );
777 if( i_do_index
== 1 ) /* Always fix */
780 if( p_sys
->b_fastseekable
)
782 AVI_IndexCreate( p_demux
);
784 else if( p_sys
->b_seekable
)
786 AVI_IndexLoad( p_demux
);
790 msg_Warn( p_demux
, "cannot create index (unseekable stream)" );
793 else if( p_sys
->b_seekable
)
795 AVI_IndexLoad( p_demux
);
798 /* *** movie length in sec *** */
799 p_sys
->i_length
= AVI_MovieGetLength( p_demux
);
801 /* Check the index completeness */
802 unsigned int i_idx_totalframes
= 0;
803 for( unsigned int i
= 0; i
< p_sys
->i_track
; i
++ )
805 const avi_track_t
*tk
= p_sys
->track
[i
];
806 if( tk
->fmt
.i_cat
== VIDEO_ES
&& tk
->idx
.p_entry
)
807 i_idx_totalframes
= __MAX(i_idx_totalframes
, tk
->idx
.i_size
);
809 if( i_idx_totalframes
!= p_avih
->i_totalframes
&&
810 p_sys
->i_length
< (mtime_t
)p_avih
->i_totalframes
*
811 (mtime_t
)p_avih
->i_microsecperframe
/
814 msg_Warn( p_demux
, "broken or missing index, 'seek' will be "
815 "approximative or will exhibit strange behavior" );
816 if( (i_do_index
== 0 || i_do_index
== 3) && !b_index
)
818 if( !p_sys
->b_fastseekable
) {
822 if( i_do_index
== 0 )
824 const char *psz_msg
= _(
825 "Because this file index is broken or missing, "
826 "seeking will not work correctly.\n"
827 "VLC won't repair your file but can temporary fix this "
828 "problem by building an index in memory.\n"
829 "This step might take a long time on a large file.\n"
830 "What do you want to do?");
831 switch( vlc_dialog_wait_question( p_demux
,
832 VLC_DIALOG_QUESTION_NORMAL
,
834 _("Build index then play"),
836 _("Broken or missing Index"),
844 msg_Dbg( p_demux
, "Fixing AVI index" );
851 msg_Dbg( p_demux
, "Fixing AVI index" );
857 /* fix some BeOS MediaKit generated file */
858 for( unsigned i
= 0 ; i
< p_sys
->i_track
; i
++ )
860 avi_track_t
*tk
= p_sys
->track
[i
];
861 avi_chunk_list_t
*p_strl
;
862 avi_chunk_strf_auds_t
*p_auds
;
864 if( tk
->fmt
.i_cat
!= AUDIO_ES
)
868 if( tk
->idx
.i_size
< 1 ||
870 tk
->i_samplesize
!= 0 )
874 p_strl
= AVI_ChunkFind( p_hdrl
, AVIFOURCC_strl
, i
, true );
875 p_auds
= AVI_ChunkFind( p_strl
, AVIFOURCC_strf
, 0, false );
878 p_auds
->p_wf
->wFormatTag
!= WAVE_FORMAT_PCM
&&
879 tk
->i_rate
== p_auds
->p_wf
->nSamplesPerSec
)
881 int64_t i_track_length
=
882 tk
->idx
.p_entry
[tk
->idx
.i_size
-1].i_length
+
883 tk
->idx
.p_entry
[tk
->idx
.i_size
-1].i_lengthtotal
;
884 mtime_t i_length
= (mtime_t
)p_avih
->i_totalframes
*
885 (mtime_t
)p_avih
->i_microsecperframe
;
889 msg_Warn( p_demux
, "track[%u] cannot be fixed (BeOS MediaKit generated)", i
);
892 tk
->i_samplesize
= 1;
893 tk
->i_rate
= i_track_length
* CLOCK_FREQ
/ i_length
;
894 msg_Warn( p_demux
, "track[%u] fixed with rate=%u scale=%u (BeOS MediaKit generated)", i
, tk
->i_rate
, tk
->i_scale
);
898 if( p_sys
->b_seekable
)
900 /* we have read all chunk so go back to movi */
901 if( vlc_stream_Seek( p_demux
->s
, p_movi
->i_chunk_pos
) )
904 /* Skip movi header */
905 if( vlc_stream_Read( p_demux
->s
, NULL
, 12 ) < 12 )
908 p_sys
->i_movi_begin
= p_movi
->i_chunk_pos
;
913 return b_aborted
? VLC_ETIMEOUT
: VLC_EGENERIC
;
916 /*****************************************************************************
917 * ReadFrame: Reads frame, using stride if necessary
918 *****************************************************************************/
920 static block_t
* ReadFrame( demux_t
*p_demux
, const avi_track_t
*tk
,
921 const unsigned int i_header
, const int i_size
)
923 block_t
*p_frame
= vlc_stream_Block( p_demux
->s
, __EVEN( i_size
) );
924 if ( !p_frame
) return p_frame
;
926 if( i_size
% 2 ) /* read was padded on word boundary */
931 if( i_header
>= p_frame
->i_buffer
)
933 p_frame
->i_buffer
= 0;
938 p_frame
->p_buffer
+= i_header
;
939 p_frame
->i_buffer
-= i_header
;
941 const unsigned int i_stride_bytes
= ((( (tk
->i_width_bytes
<< 3) + 31) & ~31) >> 3);
943 if ( !tk
->i_width_bytes
|| !i_stride_bytes
)
946 if( p_frame
->i_buffer
< i_stride_bytes
)
948 p_frame
->i_buffer
= 0;
954 const uint8_t *p_src
= p_frame
->p_buffer
+ i_stride_bytes
;
955 const uint8_t *p_end
= p_frame
->p_buffer
+ p_frame
->i_buffer
;
956 uint8_t *p_dst
= p_frame
->p_buffer
+ tk
->i_width_bytes
;
958 p_frame
->i_buffer
= tk
->i_width_bytes
;
960 while ( p_src
+ i_stride_bytes
<= p_end
)
962 memmove( p_dst
, p_src
, tk
->i_width_bytes
);
963 p_src
+= i_stride_bytes
;
964 p_dst
+= tk
->i_width_bytes
;
965 p_frame
->i_buffer
+= tk
->i_width_bytes
;
970 block_t
*p_flippedframe
= block_Alloc( p_frame
->i_buffer
);
971 if ( !p_flippedframe
)
973 block_Release( p_frame
);
977 unsigned int i_lines
= p_frame
->i_buffer
/ i_stride_bytes
;
978 const uint8_t *p_src
= p_frame
->p_buffer
+ i_lines
* i_stride_bytes
;
979 uint8_t *p_dst
= p_flippedframe
->p_buffer
;
981 p_flippedframe
->i_buffer
= 0;
983 while ( i_lines
-- > 0 )
985 p_src
-= i_stride_bytes
;
986 memcpy( p_dst
, p_src
, tk
->i_width_bytes
);
987 p_dst
+= tk
->i_width_bytes
;
988 p_flippedframe
->i_buffer
+= tk
->i_width_bytes
;
991 block_Release( p_frame
);
992 p_frame
= p_flippedframe
;
998 /*****************************************************************************
999 * Demux_Seekable: reads and demuxes data packets for stream seekable
1000 *****************************************************************************
1001 * AVIDemux: reads and demuxes data packets
1002 *****************************************************************************
1003 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1004 *****************************************************************************/
1011 int64_t i_posf
; /* where we will read :
1012 if i_idxposb == 0 : begining of chunk (+8 to acces data)
1013 else : point on data directly */
1014 } avi_track_toread_t
;
1016 static int Demux_Seekable( demux_t
*p_demux
)
1018 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1020 unsigned int i_track_count
= 0;
1021 unsigned int i_track
;
1022 /* cannot be more than 100 stream (dcXX or wbXX) */
1023 avi_track_toread_t toread
[100];
1026 /* detect new selected/unselected streams */
1027 for( i_track
= 0; i_track
< p_sys
->i_track
; i_track
++ )
1029 avi_track_t
*tk
= p_sys
->track
[i_track
];
1032 es_out_Control( p_demux
->out
, ES_OUT_GET_ES_STATE
, tk
->p_es
, &b
);
1033 if( tk
->p_es_dv_audio
)
1035 bool b_extra
= false;
1036 es_out_Control( p_demux
->out
, ES_OUT_GET_ES_STATE
, tk
->p_es_dv_audio
, &b_extra
);
1039 if( b
&& !tk
->b_activated
)
1041 if( p_sys
->b_seekable
)
1043 AVI_TrackSeek( p_demux
, i_track
, p_sys
->i_time
);
1045 tk
->b_activated
= true;
1047 else if( !b
&& tk
->b_activated
)
1049 tk
->b_activated
= false;
1057 if( i_track_count
<= 0 )
1059 int64_t i_length
= p_sys
->i_length
* CLOCK_FREQ
;
1061 p_sys
->i_time
+= p_sys
->i_read_increment
;
1064 if( p_sys
->i_time
>= i_length
)
1065 return VLC_DEMUXER_EOF
;
1066 return VLC_DEMUXER_SUCCESS
;
1068 msg_Warn( p_demux
, "no track selected, exiting..." );
1069 return VLC_DEMUXER_EOF
;
1072 /* wait for the good time */
1073 es_out_SetPCR( p_demux
->out
, VLC_TS_0
+ p_sys
->i_time
);
1074 p_sys
->i_time
+= p_sys
->i_read_increment
;
1077 for( i_track
= 0; i_track
< p_sys
->i_track
; i_track
++ )
1079 avi_track_t
*tk
= p_sys
->track
[i_track
];
1081 toread
[i_track
].b_ok
= tk
->b_activated
&& !tk
->b_eof
;
1082 if( tk
->i_idxposc
< tk
->idx
.i_size
)
1084 toread
[i_track
].i_posf
= tk
->idx
.p_entry
[tk
->i_idxposc
].i_pos
;
1085 if( tk
->i_idxposb
> 0 )
1087 toread
[i_track
].i_posf
+= 8 + tk
->i_idxposb
;
1092 toread
[i_track
].i_posf
= -1;
1095 mtime_t i_dpts
= p_sys
->i_time
- AVI_GetPTS( tk
);
1097 if( tk
->i_samplesize
)
1099 toread
[i_track
].i_toread
= AVI_PTSToByte( tk
, i_dpts
);
1101 else if ( i_dpts
> -2 * CLOCK_FREQ
) /* don't send a too early dts (low fps video) */
1103 toread
[i_track
].i_toread
= AVI_PTSToChunk( tk
, i_dpts
);
1106 toread
[i_track
].i_toread
= -1;
1118 /* search for first chunk to be read */
1119 for( i
= 0, b_done
= true, i_pos
= -1; i
< p_sys
->i_track
; i
++ )
1121 if( !toread
[i
].b_ok
||
1122 ( p_sys
->b_fastseekable
&& p_sys
->b_interleaved
&&
1123 AVI_GetDPTS( p_sys
->track
[i
], toread
[i
].i_toread
) <= -p_sys
->i_read_increment
) )
1128 if( toread
[i
].i_toread
>= 0 )
1130 b_done
= false; /* not yet finished */
1132 if( toread
[i
].i_posf
> 0 )
1134 if( i_pos
== -1 || i_pos
> toread
[i
].i_posf
)
1137 i_pos
= toread
[i
].i_posf
;
1145 for( i
= 0; i
< p_sys
->i_track
; i
++ )
1147 if( toread
[i
].b_ok
)
1148 return VLC_DEMUXER_SUCCESS
;
1150 msg_Warn( p_demux
, "all tracks have failed, exiting..." );
1151 return VLC_DEMUXER_EOF
;
1156 int i_loop_count
= 0;
1158 /* no valid index, we will parse directly the stream
1159 * in case we fail we will disable all finished stream */
1160 if( p_sys
->b_seekable
&& p_sys
->i_movi_lastchunk_pos
>= p_sys
->i_movi_begin
+ 12 )
1162 vlc_stream_Seek( p_demux
->s
, p_sys
->i_movi_lastchunk_pos
);
1163 if( AVI_PacketNext( p_demux
) )
1165 return( AVI_TrackStopFinishedStreams( p_demux
) ? 0 : 1 );
1170 vlc_stream_Seek( p_demux
->s
, p_sys
->i_movi_begin
+ 12 );
1175 avi_packet_t avi_pk
;
1177 if( AVI_PacketGetHeader( p_demux
, &avi_pk
) )
1180 "cannot get packet header, track disabled" );
1181 return( AVI_TrackStopFinishedStreams( p_demux
) ? 0 : 1 );
1183 if( avi_pk
.i_stream
>= p_sys
->i_track
||
1184 ( avi_pk
.i_cat
!= AUDIO_ES
&& avi_pk
.i_cat
!= VIDEO_ES
) )
1186 if( AVI_PacketNext( p_demux
) )
1189 "cannot skip packet, track disabled" );
1190 return( AVI_TrackStopFinishedStreams( p_demux
) ? 0 : 1 );
1193 /* Prevents from eating all the CPU with broken files.
1194 * This value should be low enough so that it doesn't
1195 * affect the reading speed too much. */
1196 if( !(++i_loop_count
% 1024) )
1200 if( !(i_loop_count
% (1024 * 10)) )
1202 "don't seem to find any data..." );
1208 i_track
= avi_pk
.i_stream
;
1209 tk
= p_sys
->track
[i_track
];
1211 /* add this chunk to the index */
1213 index
.i_id
= avi_pk
.i_fourcc
;
1214 index
.i_flags
= AVI_GetKeyFlag(tk
->fmt
.i_codec
, avi_pk
.i_peek
);
1215 index
.i_pos
= avi_pk
.i_pos
;
1216 index
.i_length
= avi_pk
.i_size
;
1217 index
.i_lengthtotal
= index
.i_length
;
1218 avi_index_Append( &tk
->idx
, &p_sys
->i_movi_lastchunk_pos
, &index
);
1220 /* do we will read this data ? */
1221 if( AVI_GetDPTS( tk
, toread
[i_track
].i_toread
) > -p_sys
->i_read_increment
)
1227 if( AVI_PacketNext( p_demux
) )
1230 "cannot skip packet, track disabled" );
1231 return( AVI_TrackStopFinishedStreams( p_demux
) ? 0 : 1 );
1240 vlc_stream_Seek( p_demux
->s
, i_pos
);
1243 /* Set the track to use */
1244 tk
= p_sys
->track
[i_track
];
1246 /* read thoses data */
1247 if( tk
->i_samplesize
)
1251 if( ( i_toread
= toread
[i_track
].i_toread
) <= 0 )
1253 if( tk
->i_samplesize
> 1 )
1255 i_toread
= tk
->i_samplesize
;
1259 i_toread
= AVI_PTSToByte( tk
, 20 * 1000 );
1260 i_toread
= __MAX( i_toread
, 100 );
1263 i_size
= __MIN( tk
->idx
.p_entry
[tk
->i_idxposc
].i_length
-
1265 (size_t) i_toread
);
1269 i_size
= tk
->idx
.p_entry
[tk
->i_idxposc
].i_length
;
1272 if( tk
->i_idxposb
== 0 )
1274 i_size
+= 8; /* need to read and skip header */
1277 if( ( p_frame
= ReadFrame( p_demux
, tk
,
1278 ( tk
->i_idxposb
== 0 ) ? 8 : 0, i_size
) )==NULL
)
1280 msg_Warn( p_demux
, "failed reading data" );
1282 toread
[i_track
].b_ok
= false;
1286 p_frame
->i_pts
= VLC_TS_0
+ AVI_GetPTS( tk
);
1287 if( tk
->idx
.p_entry
[tk
->i_idxposc
].i_flags
&AVIIF_KEYFRAME
)
1289 p_frame
->i_flags
= BLOCK_FLAG_TYPE_I
;
1293 p_frame
->i_flags
= BLOCK_FLAG_TYPE_PB
;
1297 if( tk
->i_samplesize
)
1299 if( tk
->i_idxposb
== 0 )
1303 toread
[i_track
].i_toread
-= i_size
;
1304 tk
->i_idxposb
+= i_size
;
1305 if( tk
->i_idxposb
>=
1306 tk
->idx
.p_entry
[tk
->i_idxposc
].i_length
)
1314 int i_length
= tk
->idx
.p_entry
[tk
->i_idxposc
].i_length
;
1317 if( tk
->fmt
.i_cat
== AUDIO_ES
)
1319 tk
->i_blockno
+= tk
->i_blocksize
> 0 ? ( i_length
+ tk
->i_blocksize
- 1 ) / tk
->i_blocksize
: 1;
1321 toread
[i_track
].i_toread
--;
1324 if( tk
->i_idxposc
< tk
->idx
.i_size
)
1326 toread
[i_track
].i_posf
=
1327 tk
->idx
.p_entry
[tk
->i_idxposc
].i_pos
;
1328 if( tk
->i_idxposb
> 0 )
1330 toread
[i_track
].i_posf
+= 8 + tk
->i_idxposb
;
1336 toread
[i_track
].i_posf
= -1;
1339 if( tk
->fmt
.i_cat
!= VIDEO_ES
)
1340 p_frame
->i_dts
= p_frame
->i_pts
;
1343 p_frame
->i_dts
= p_frame
->i_pts
;
1344 p_frame
->i_pts
= VLC_TS_INVALID
;
1347 if( tk
->i_dv_audio_rate
)
1348 AVI_DvHandleAudio( p_demux
, tk
, p_frame
);
1350 if( tk
->i_next_block_flags
)
1352 p_frame
->i_flags
= tk
->i_next_block_flags
;
1353 tk
->i_next_block_flags
= 0;
1357 es_out_Send( p_demux
->out
, tk
->p_es
, p_frame
);
1359 block_Release( p_frame
);
1364 /*****************************************************************************
1365 * Demux_UnSeekable: reads and demuxes data packets for unseekable file
1366 *****************************************************************************
1367 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1368 *****************************************************************************/
1369 static int Demux_UnSeekable( demux_t
*p_demux
)
1371 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1372 avi_track_t
*p_stream_master
= NULL
;
1373 unsigned int i_stream
;
1374 unsigned int i_packet
;
1376 es_out_SetPCR( p_demux
->out
, VLC_TS_0
+ p_sys
->i_time
);
1378 /* *** find master stream for data packet skipping algo *** */
1379 /* *** -> first video, if any, or first audio ES *** */
1380 for( i_stream
= 0; i_stream
< p_sys
->i_track
; i_stream
++ )
1382 avi_track_t
*tk
= p_sys
->track
[i_stream
];
1385 es_out_Control( p_demux
->out
, ES_OUT_GET_ES_STATE
, tk
->p_es
, &b
);
1386 if( tk
->p_es_dv_audio
)
1389 es_out_Control( p_demux
->out
, ES_OUT_GET_ES_STATE
, tk
->p_es_dv_audio
, &b_extra
);
1395 if( tk
->fmt
.i_cat
== VIDEO_ES
)
1397 p_stream_master
= tk
;
1400 else if( !p_stream_master
)
1402 p_stream_master
= tk
;
1407 if( !p_stream_master
)
1409 if( p_sys
->i_track
)
1411 p_stream_master
= p_sys
->track
[0];
1415 msg_Warn( p_demux
, "no more stream selected" );
1416 return VLC_DEMUXER_EOF
;
1420 p_sys
->i_time
= AVI_GetPTS( p_stream_master
);
1422 for( i_packet
= 0; i_packet
< 10; i_packet
++)
1424 #define p_stream p_sys->track[avi_pk.i_stream]
1426 avi_packet_t avi_pk
;
1428 if( AVI_PacketGetHeader( p_demux
, &avi_pk
) )
1430 return VLC_DEMUXER_EOF
;
1433 if( avi_pk
.i_stream
>= p_sys
->i_track
||
1434 ( avi_pk
.i_cat
!= AUDIO_ES
&& avi_pk
.i_cat
!= VIDEO_ES
) )
1436 /* we haven't found an audio or video packet:
1437 * - we have seek, found first next packet
1438 * - others packets could be found, skip them
1440 switch( avi_pk
.i_fourcc
)
1442 case AVIFOURCC_JUNK
:
1443 case AVIFOURCC_LIST
:
1444 case AVIFOURCC_RIFF
:
1445 return( !AVI_PacketNext( p_demux
) ? 1 : 0 );
1446 case AVIFOURCC_idx1
:
1449 return( !AVI_PacketNext( p_demux
) ? 1 : 0 );
1451 return VLC_DEMUXER_EOF
;
1454 "seems to have lost position @%"PRIu64
", resync",
1455 vlc_stream_Tell(p_demux
->s
) );
1456 if( AVI_PacketSearch( p_demux
) )
1458 msg_Err( p_demux
, "resync failed" );
1459 return VLC_DEMUXER_EGENERIC
;
1465 /* check for time */
1466 if( p_stream
== p_stream_master
||
1467 llabs( AVI_GetPTS( p_stream
) -
1468 AVI_GetPTS( p_stream_master
) )< 2 * CLOCK_FREQ
)
1470 /* load it and send to decoder */
1471 block_t
*p_frame
= ReadFrame( p_demux
, p_stream
, 8, avi_pk
.i_size
+ 8 ) ;
1472 if( p_frame
== NULL
)
1474 return VLC_DEMUXER_EGENERIC
;
1476 p_frame
->i_pts
= VLC_TS_0
+ AVI_GetPTS( p_stream
);
1478 if( avi_pk
.i_cat
!= VIDEO_ES
)
1479 p_frame
->i_dts
= p_frame
->i_pts
;
1482 p_frame
->i_dts
= p_frame
->i_pts
;
1483 p_frame
->i_pts
= VLC_TS_INVALID
;
1486 if( p_stream
->i_dv_audio_rate
)
1487 AVI_DvHandleAudio( p_demux
, p_stream
, p_frame
);
1489 if( p_stream
->p_es
)
1490 es_out_Send( p_demux
->out
, p_stream
->p_es
, p_frame
);
1492 block_Release( p_frame
);
1496 if( AVI_PacketNext( p_demux
) )
1498 return VLC_DEMUXER_EOF
;
1502 /* *** update stream time position *** */
1503 if( p_stream
->i_samplesize
)
1505 p_stream
->i_idxposb
+= avi_pk
.i_size
;
1509 if( p_stream
->fmt
.i_cat
== AUDIO_ES
)
1511 p_stream
->i_blockno
+= p_stream
->i_blocksize
> 0 ? ( avi_pk
.i_size
+ p_stream
->i_blocksize
- 1 ) / p_stream
->i_blocksize
: 1;
1513 p_stream
->i_idxposc
++;
1520 return VLC_DEMUXER_SUCCESS
;
1523 /*****************************************************************************
1524 * Seek: goto to i_date or i_percent
1525 *****************************************************************************/
1526 static int Seek( demux_t
*p_demux
, mtime_t i_date
, int i_percent
, bool b_accurate
)
1528 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1529 msg_Dbg( p_demux
, "seek requested: %"PRId64
" seconds %d%%",
1530 i_date
/ CLOCK_FREQ
, i_percent
);
1532 if( p_sys
->b_seekable
)
1534 int64_t i_pos_backup
= vlc_stream_Tell( p_demux
->s
);
1536 /* Check and lazy load indexes if it was not done (not fastseekable) */
1537 if ( !p_sys
->b_indexloaded
&& ( p_sys
->i_avih_flags
& AVIF_HASINDEX
) )
1539 avi_chunk_t
*p_riff
= AVI_ChunkFind( &p_sys
->ck_root
, AVIFOURCC_RIFF
, 0, true );
1540 if (unlikely( !p_riff
))
1541 return VLC_EGENERIC
;
1543 int i_ret
= AVI_ChunkFetchIndexes( p_demux
->s
, p_riff
);
1546 /* Go back to position before index failure */
1547 if ( vlc_stream_Tell( p_demux
->s
) - i_pos_backup
)
1548 vlc_stream_Seek( p_demux
->s
, i_pos_backup
);
1550 if ( p_sys
->i_avih_flags
& AVIF_MUSTUSEINDEX
)
1551 return VLC_EGENERIC
;
1553 else AVI_IndexLoad( p_demux
);
1555 p_sys
->b_indexloaded
= true; /* we don't want to try each time */
1558 if( !p_sys
->i_length
)
1560 avi_track_t
*p_stream
= NULL
;
1561 unsigned i_stream
= 0;
1564 if ( !p_sys
->i_movi_lastchunk_pos
&& /* set when index is successfully loaded */
1565 ! ( p_sys
->i_avih_flags
& AVIF_ISINTERLEAVED
) )
1567 msg_Err( p_demux
, "seeking without index at %d%%"
1568 " only works for interleaved files", i_percent
);
1569 goto failandresetpos
;
1571 /* use i_percent to create a true i_date */
1572 if( i_percent
>= 100 )
1574 msg_Warn( p_demux
, "cannot seek so far !" );
1575 goto failandresetpos
;
1577 i_percent
= __MAX( i_percent
, 0 );
1579 /* try to find chunk that is at i_percent or the file */
1580 i_pos
= __MAX( i_percent
* stream_Size( p_demux
->s
) / 100,
1581 p_sys
->i_movi_begin
);
1582 /* search first selected stream (and prefer non-EOF ones) */
1583 for( unsigned i
= 0; i
< p_sys
->i_track
; i
++ )
1585 avi_track_t
*p_track
= p_sys
->track
[i
];
1586 if( !p_track
->b_activated
)
1591 if( !p_track
->b_eof
)
1594 if( p_stream
== NULL
)
1596 msg_Warn( p_demux
, "cannot find any selected stream" );
1597 goto failandresetpos
;
1600 /* be sure that the index exist */
1601 if( AVI_StreamChunkSet( p_demux
, i_stream
, 0 ) )
1603 msg_Warn( p_demux
, "cannot seek" );
1604 goto failandresetpos
;
1607 while( i_pos
>= p_stream
->idx
.p_entry
[p_stream
->i_idxposc
].i_pos
+
1608 p_stream
->idx
.p_entry
[p_stream
->i_idxposc
].i_length
+ 8 )
1610 /* search after i_idxposc */
1611 if( AVI_StreamChunkSet( p_demux
,
1612 i_stream
, p_stream
->i_idxposc
+ 1 ) )
1614 msg_Warn( p_demux
, "cannot seek" );
1615 goto failandresetpos
;
1619 i_date
= AVI_GetPTS( p_stream
);
1620 /* TODO better support for i_samplesize != 0 */
1621 msg_Dbg( p_demux
, "estimate date %"PRId64
, i_date
);
1625 mtime_t i_wanted
= i_date
;
1626 mtime_t i_start
= i_date
;
1627 /* Do a 2 pass seek, first with video (can seek ahead due to keyframes),
1628 so we can seek audio to the same starting time */
1629 for(int i
=0; i
<2; i
++)
1631 for( unsigned i_stream
= 0; i_stream
< p_sys
->i_track
; i_stream
++ )
1633 avi_track_t
*p_stream
= p_sys
->track
[i_stream
];
1635 if( !p_stream
->b_activated
)
1638 if( (i
==0 && p_stream
->fmt
.i_cat
!= VIDEO_ES
) ||
1639 (i
!=0 && p_stream
->fmt
.i_cat
== VIDEO_ES
) )
1642 p_stream
->b_eof
= AVI_TrackSeek( p_demux
, i_stream
, i_wanted
) != 0;
1643 if( !p_stream
->b_eof
)
1645 p_stream
->i_next_block_flags
|= BLOCK_FLAG_DISCONTINUITY
;
1647 if( p_stream
->fmt
.i_cat
== AUDIO_ES
|| p_stream
->fmt
.i_cat
== VIDEO_ES
)
1648 i_start
= __MIN(i_start
, AVI_GetPTS( p_stream
));
1650 if( i
== 0 && p_stream
->fmt
.i_cat
== VIDEO_ES
)
1655 p_sys
->i_time
= i_start
;
1656 es_out_SetPCR( p_demux
->out
, VLC_TS_0
+ p_sys
->i_time
);
1658 es_out_Control( p_demux
->out
, ES_OUT_SET_NEXT_DISPLAY_TIME
, VLC_TS_0
+ i_date
);
1659 msg_Dbg( p_demux
, "seek: %"PRId64
" seconds", p_sys
->i_time
/CLOCK_FREQ
);
1663 /* Go back to position before index failure */
1664 if ( vlc_stream_Tell( p_demux
->s
) - i_pos_backup
)
1665 vlc_stream_Seek( p_demux
->s
, i_pos_backup
);
1667 return VLC_EGENERIC
;
1671 msg_Err( p_demux
, "shouldn't yet be executed" );
1672 return VLC_EGENERIC
;
1676 /*****************************************************************************
1678 *****************************************************************************/
1679 static double ControlGetPosition( demux_t
*p_demux
)
1681 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1683 if( p_sys
->i_length
> 0 )
1685 return (double)p_sys
->i_time
/ (double)( p_sys
->i_length
* (mtime_t
)CLOCK_FREQ
);
1687 else if( stream_Size( p_demux
->s
) > 0 )
1689 double i64
= (uint64_t)vlc_stream_Tell( p_demux
->s
);
1690 return i64
/ stream_Size( p_demux
->s
);
1695 static int Control( demux_t
*p_demux
, int i_query
, va_list args
)
1697 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1705 case DEMUX_CAN_SEEK
:
1706 *va_arg( args
, bool * ) = p_sys
->b_seekable
;
1709 case DEMUX_GET_POSITION
:
1710 pf
= va_arg( args
, double * );
1711 *pf
= ControlGetPosition( p_demux
);
1713 case DEMUX_SET_POSITION
:
1714 f
= va_arg( args
, double );
1715 b
= va_arg( args
, int );
1716 if ( !p_sys
->b_seekable
)
1718 return VLC_EGENERIC
;
1722 i64
= (mtime_t
)(f
* CLOCK_FREQ
* p_sys
->i_length
);
1723 return Seek( p_demux
, i64
, (int)(f
* 100), b
);
1726 case DEMUX_GET_TIME
:
1727 pi64
= va_arg( args
, int64_t * );
1728 *pi64
= p_sys
->i_time
;
1731 case DEMUX_SET_TIME
:
1735 i64
= va_arg( args
, int64_t );
1736 b
= va_arg( args
, int );
1737 if( !p_sys
->b_seekable
)
1739 return VLC_EGENERIC
;
1741 else if( p_sys
->i_length
> 0 )
1743 i_percent
= 100 * i64
/ (p_sys
->i_length
*CLOCK_FREQ
);
1745 else if( p_sys
->i_time
> 0 )
1747 i_percent
= (int)( 100.0 * ControlGetPosition( p_demux
) *
1748 (double)i64
/ (double)p_sys
->i_time
);
1750 return Seek( p_demux
, i64
, i_percent
, b
);
1752 case DEMUX_GET_LENGTH
:
1753 pi64
= va_arg( args
, int64_t * );
1754 *pi64
= p_sys
->i_length
* (mtime_t
)CLOCK_FREQ
;
1758 pf
= va_arg( args
, double * );
1760 for( unsigned i
= 0; i
< p_sys
->i_track
; i
++ )
1762 avi_track_t
*tk
= p_sys
->track
[i
];
1763 if( tk
->fmt
.i_cat
== VIDEO_ES
&& tk
->i_scale
> 0)
1765 *pf
= (float)tk
->i_rate
/ (float)tk
->i_scale
;
1771 case DEMUX_GET_META
:
1772 p_meta
= va_arg( args
, vlc_meta_t
* );
1773 vlc_meta_Merge( p_meta
, p_sys
->meta
);
1776 case DEMUX_GET_ATTACHMENTS
:
1778 if( p_sys
->i_attachment
<= 0 )
1779 return VLC_EGENERIC
;
1781 input_attachment_t
***ppp_attach
= va_arg( args
, input_attachment_t
*** );
1782 int *pi_int
= va_arg( args
, int * );
1784 *ppp_attach
= calloc( p_sys
->i_attachment
, sizeof(**ppp_attach
) );
1785 if( likely(*ppp_attach
) )
1787 *pi_int
= p_sys
->i_attachment
;
1788 for( unsigned i
= 0; i
< p_sys
->i_attachment
; i
++ )
1789 (*ppp_attach
)[i
] = vlc_input_attachment_Duplicate( p_sys
->attachment
[i
] );
1792 return VLC_EGENERIC
;
1796 return VLC_EGENERIC
;
1800 /*****************************************************************************
1801 * Function to convert pts to chunk or byte
1802 *****************************************************************************/
1804 static int64_t AVI_Rescale( int64_t i_value
, uint32_t i_timescale
, uint32_t i_newscale
)
1806 /* TODO: replace (and mp4) with better global helper (recursive checks) */
1807 if( i_timescale
== i_newscale
)
1810 if( (i_value
>= 0 && i_value
<= INT64_MAX
/ i_newscale
) ||
1811 (i_value
< 0 && i_value
>= INT64_MIN
/ i_newscale
) )
1812 return i_value
* i_newscale
/ i_timescale
;
1815 int64_t q
= i_value
/ i_timescale
;
1816 int64_t r
= i_value
% i_timescale
;
1817 return q
* i_newscale
+ r
* i_newscale
/ i_timescale
;
1820 static int64_t AVI_PTSToChunk( avi_track_t
*tk
, mtime_t i_pts
)
1825 i_pts
= AVI_Rescale( i_pts
, tk
->i_scale
, tk
->i_rate
);
1826 return i_pts
/ CLOCK_FREQ
;
1829 static int64_t AVI_PTSToByte( avi_track_t
*tk
, mtime_t i_pts
)
1831 if( !tk
->i_scale
|| !tk
->i_samplesize
)
1834 i_pts
= AVI_Rescale( i_pts
, tk
->i_scale
, tk
->i_rate
);
1835 return i_pts
/ CLOCK_FREQ
* tk
->i_samplesize
;
1838 static mtime_t
AVI_GetDPTS( avi_track_t
*tk
, int64_t i_count
)
1845 i_dpts
= AVI_Rescale( CLOCK_FREQ
* i_count
, tk
->i_rate
, tk
->i_scale
);
1847 if( tk
->i_samplesize
)
1849 return i_dpts
/ tk
->i_samplesize
;
1854 static mtime_t
AVI_GetPTS( avi_track_t
*tk
)
1856 if( tk
->i_samplesize
)
1858 int64_t i_count
= 0;
1860 /* we need a valid entry we will emulate one */
1861 if( tk
->i_idxposc
== tk
->idx
.i_size
)
1865 /* use the last entry */
1866 i_count
= tk
->idx
.p_entry
[tk
->idx
.i_size
- 1].i_lengthtotal
1867 + tk
->idx
.p_entry
[tk
->idx
.i_size
- 1].i_length
;
1872 i_count
= tk
->idx
.p_entry
[tk
->i_idxposc
].i_lengthtotal
;
1874 return AVI_GetDPTS( tk
, i_count
+ tk
->i_idxposb
);
1878 if( tk
->fmt
.i_cat
== AUDIO_ES
)
1880 return AVI_GetDPTS( tk
, tk
->i_blockno
);
1884 return AVI_GetDPTS( tk
, tk
->i_idxposc
);
1889 static int AVI_StreamChunkFind( demux_t
*p_demux
, unsigned int i_stream
)
1891 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1892 avi_packet_t avi_pk
;
1893 int i_loop_count
= 0;
1895 /* find first chunk of i_stream that isn't in index */
1897 if( p_sys
->i_movi_lastchunk_pos
>= p_sys
->i_movi_begin
+ 12 )
1899 vlc_stream_Seek( p_demux
->s
, p_sys
->i_movi_lastchunk_pos
);
1900 if( AVI_PacketNext( p_demux
) )
1902 return VLC_EGENERIC
;
1907 vlc_stream_Seek( p_demux
->s
, p_sys
->i_movi_begin
+ 12 );
1912 if( AVI_PacketGetHeader( p_demux
, &avi_pk
) )
1914 msg_Warn( p_demux
, "cannot get packet header" );
1915 return VLC_EGENERIC
;
1917 if( avi_pk
.i_stream
>= p_sys
->i_track
||
1918 ( avi_pk
.i_cat
!= AUDIO_ES
&& avi_pk
.i_cat
!= VIDEO_ES
) )
1920 if( AVI_PacketNext( p_demux
) )
1922 return VLC_EGENERIC
;
1925 /* Prevents from eating all the CPU with broken files.
1926 * This value should be low enough so that it doesn't
1927 * affect the reading speed too much. */
1928 if( !(++i_loop_count
% 1024) )
1932 if( !(i_loop_count
% (1024 * 10)) )
1933 msg_Warn( p_demux
, "don't seem to find any data..." );
1938 avi_track_t
*tk_pk
= p_sys
->track
[avi_pk
.i_stream
];
1940 /* add this chunk to the index */
1942 index
.i_id
= avi_pk
.i_fourcc
;
1943 index
.i_flags
= AVI_GetKeyFlag(tk_pk
->fmt
.i_codec
, avi_pk
.i_peek
);
1944 index
.i_pos
= avi_pk
.i_pos
;
1945 index
.i_length
= avi_pk
.i_size
;
1946 index
.i_lengthtotal
= index
.i_length
;
1947 avi_index_Append( &tk_pk
->idx
, &p_sys
->i_movi_lastchunk_pos
, &index
);
1949 if( avi_pk
.i_stream
== i_stream
)
1954 if( AVI_PacketNext( p_demux
) )
1956 return VLC_EGENERIC
;
1962 /* be sure that i_ck will be a valid index entry */
1963 static int AVI_StreamChunkSet( demux_t
*p_demux
, unsigned int i_stream
,
1966 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1967 avi_track_t
*p_stream
= p_sys
->track
[i_stream
];
1969 p_stream
->i_idxposc
= i_ck
;
1970 p_stream
->i_idxposb
= 0;
1972 if( i_ck
>= p_stream
->idx
.i_size
)
1974 p_stream
->i_idxposc
= p_stream
->idx
.i_size
- 1;
1977 p_stream
->i_idxposc
++;
1978 if( AVI_StreamChunkFind( p_demux
, i_stream
) )
1980 return VLC_EGENERIC
;
1983 } while( p_stream
->i_idxposc
< i_ck
);
1989 /* XXX FIXME up to now, we assume that all chunk are one after one */
1990 static int AVI_StreamBytesSet( demux_t
*p_demux
,
1991 unsigned int i_stream
,
1994 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1995 avi_track_t
*p_stream
= p_sys
->track
[i_stream
];
1997 if( ( p_stream
->idx
.i_size
> 0 )
1998 &&( i_byte
< p_stream
->idx
.p_entry
[p_stream
->idx
.i_size
- 1].i_lengthtotal
+
1999 p_stream
->idx
.p_entry
[p_stream
->idx
.i_size
- 1].i_length
) )
2001 /* index is valid to find the ck */
2002 /* uses dichototmie to be fast enougth */
2003 int i_idxposc
= __MIN( p_stream
->i_idxposc
, p_stream
->idx
.i_size
- 1 );
2004 int i_idxmax
= p_stream
->idx
.i_size
;
2008 if( p_stream
->idx
.p_entry
[i_idxposc
].i_lengthtotal
> i_byte
)
2010 i_idxmax
= i_idxposc
;
2011 i_idxposc
= ( i_idxmin
+ i_idxposc
) / 2 ;
2015 if( p_stream
->idx
.p_entry
[i_idxposc
].i_lengthtotal
+
2016 p_stream
->idx
.p_entry
[i_idxposc
].i_length
<= i_byte
)
2018 i_idxmin
= i_idxposc
;
2019 i_idxposc
= (i_idxmax
+ i_idxposc
) / 2 ;
2023 p_stream
->i_idxposc
= i_idxposc
;
2024 p_stream
->i_idxposb
= i_byte
-
2025 p_stream
->idx
.p_entry
[i_idxposc
].i_lengthtotal
;
2034 p_stream
->i_idxposc
= p_stream
->idx
.i_size
- 1;
2035 p_stream
->i_idxposb
= 0;
2038 p_stream
->i_idxposc
++;
2039 if( AVI_StreamChunkFind( p_demux
, i_stream
) )
2041 return VLC_EGENERIC
;
2044 } while( p_stream
->idx
.p_entry
[p_stream
->i_idxposc
].i_lengthtotal
+
2045 p_stream
->idx
.p_entry
[p_stream
->i_idxposc
].i_length
<= i_byte
);
2047 p_stream
->i_idxposb
= i_byte
-
2048 p_stream
->idx
.p_entry
[p_stream
->i_idxposc
].i_lengthtotal
;
2053 static int AVI_TrackSeek( demux_t
*p_demux
,
2057 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2058 avi_track_t
*tk
= p_sys
->track
[i_stream
];
2060 #define p_stream p_sys->track[i_stream]
2063 i_oldpts
= AVI_GetPTS( p_stream
);
2065 if( !p_stream
->i_samplesize
)
2067 if( AVI_StreamChunkSet( p_demux
,
2069 AVI_PTSToChunk( p_stream
, i_date
) ) )
2071 return VLC_EGENERIC
;
2074 if( p_stream
->fmt
.i_cat
== AUDIO_ES
)
2078 for( i
= 0; i
< tk
->i_idxposc
; i
++ )
2080 if( tk
->i_blocksize
> 0 )
2082 tk
->i_blockno
+= ( tk
->idx
.p_entry
[i
].i_length
+ tk
->i_blocksize
- 1 ) / tk
->i_blocksize
;
2092 "old:%"PRId64
" %s new %"PRId64
,
2094 i_oldpts
> i_date
? ">" : "<",
2097 if( p_stream
->fmt
.i_cat
== VIDEO_ES
)
2099 /* search key frame */
2100 //if( i_date < i_oldpts || 1 )
2102 while( p_stream
->i_idxposc
> 0 &&
2103 !( p_stream
->idx
.p_entry
[p_stream
->i_idxposc
].i_flags
&
2106 if( AVI_StreamChunkSet( p_demux
,
2108 p_stream
->i_idxposc
- 1 ) )
2110 return VLC_EGENERIC
;
2117 while( p_stream
->i_idxposc
< p_stream
->idx
.i_size
&&
2118 !( p_stream
->idx
.p_entry
[p_stream
->i_idxposc
].i_flags
&
2121 if( AVI_StreamChunkSet( p_demux
,
2123 p_stream
->i_idxposc
+ 1 ) )
2125 return VLC_EGENERIC
;
2134 if( AVI_StreamBytesSet( p_demux
,
2136 AVI_PTSToByte( p_stream
, i_date
) ) )
2138 return VLC_EGENERIC
;
2145 /****************************************************************************
2146 * Return true if it's a key frame
2147 ****************************************************************************/
2148 static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc
, uint8_t *p_byte
)
2152 case VLC_CODEC_DIV1
:
2154 * startcode: 0x00000100 32bits
2155 * framenumber ? 5bits
2156 * piture type 0(I),1(P) 2bits
2158 if( GetDWBE( p_byte
) != 0x00000100 )
2160 /* it's not an msmpegv1 stream, strange...*/
2161 return AVIIF_KEYFRAME
;
2163 return p_byte
[4] & 0x06 ? 0 : AVIIF_KEYFRAME
;
2165 case VLC_CODEC_DIV2
:
2166 case VLC_CODEC_DIV3
:
2167 case VLC_CODEC_WMV1
:
2169 * picture type 0(I),1(P) 2bits
2171 return p_byte
[0] & 0xC0 ? 0 : AVIIF_KEYFRAME
;
2172 case VLC_CODEC_MP4V
:
2173 /* we should find first occurrence of 0x000001b6 (32bits)
2174 * startcode: 0x000001b6 32bits
2175 * piture type 0(I),1(P) 2bits
2177 if( GetDWBE( p_byte
) != 0x000001b6 )
2179 /* not true , need to find the first VOP header */
2180 return AVIIF_KEYFRAME
;
2182 return p_byte
[4] & 0xC0 ? 0 : AVIIF_KEYFRAME
;
2185 /* I can't do it, so say yes */
2186 return AVIIF_KEYFRAME
;
2190 vlc_fourcc_t
AVI_FourccGetCodec( unsigned int i_cat
, vlc_fourcc_t i_codec
)
2195 wf_tag_to_fourcc( i_codec
, &i_codec
, NULL
);
2198 return vlc_fourcc_GetCodec( i_cat
, i_codec
);
2200 return VLC_CODEC_UNKNOWN
;
2204 /****************************************************************************
2206 ****************************************************************************/
2207 static void AVI_ParseStreamHeader( vlc_fourcc_t i_id
,
2208 unsigned int *pi_number
,
2209 enum es_format_category_e
*pi_type
)
2213 c1
= ((uint8_t *)&i_id
)[0];
2214 c2
= ((uint8_t *)&i_id
)[1];
2216 if( c1
< '0' || c1
> '9' || c2
< '0' || c2
> '9' )
2218 *pi_number
= 100; /* > max stream number */
2219 *pi_type
= UNKNOWN_ES
;
2223 *pi_number
= (c1
- '0') * 10 + (c2
- '0' );
2224 switch( VLC_TWOCC( ((uint8_t *)&i_id
)[2], ((uint8_t *)&i_id
)[3] ) )
2227 *pi_type
= AUDIO_ES
;
2232 *pi_type
= VIDEO_ES
;
2239 *pi_type
= IGNORE_ES
;
2242 *pi_type
= UNKNOWN_ES
;
2248 /****************************************************************************
2250 ****************************************************************************/
2251 static int AVI_PacketGetHeader( demux_t
*p_demux
, avi_packet_t
*p_pk
)
2253 const uint8_t *p_peek
;
2255 if( vlc_stream_Peek( p_demux
->s
, &p_peek
, 16 ) < 16 )
2257 return VLC_EGENERIC
;
2259 p_pk
->i_fourcc
= VLC_FOURCC( p_peek
[0], p_peek
[1], p_peek
[2], p_peek
[3] );
2260 p_pk
->i_size
= GetDWLE( p_peek
+ 4 );
2261 p_pk
->i_pos
= vlc_stream_Tell( p_demux
->s
);
2262 if( p_pk
->i_fourcc
== AVIFOURCC_LIST
|| p_pk
->i_fourcc
== AVIFOURCC_RIFF
)
2264 p_pk
->i_type
= VLC_FOURCC( p_peek
[8], p_peek
[9],
2265 p_peek
[10], p_peek
[11] );
2272 memcpy( p_pk
->i_peek
, p_peek
+ 8, 8 );
2274 AVI_ParseStreamHeader( p_pk
->i_fourcc
, &p_pk
->i_stream
, &p_pk
->i_cat
);
2278 static int AVI_PacketNext( demux_t
*p_demux
)
2280 avi_packet_t avi_ck
;
2283 if( AVI_PacketGetHeader( p_demux
, &avi_ck
) )
2285 return VLC_EGENERIC
;
2288 if( avi_ck
.i_fourcc
== AVIFOURCC_LIST
&&
2289 ( avi_ck
.i_type
== AVIFOURCC_rec
|| avi_ck
.i_type
== AVIFOURCC_movi
) )
2293 else if( avi_ck
.i_fourcc
== AVIFOURCC_RIFF
&&
2294 avi_ck
.i_type
== AVIFOURCC_AVIX
)
2300 if( avi_ck
.i_size
> UINT32_MAX
- 9 )
2301 return VLC_EGENERIC
;
2302 i_skip
= __EVEN( avi_ck
.i_size
) + 8;
2305 if( i_skip
> SSIZE_MAX
)
2306 return VLC_EGENERIC
;
2308 ssize_t i_ret
= vlc_stream_Read( p_demux
->s
, NULL
, i_skip
);
2309 if( i_ret
< 0 || (size_t) i_ret
!= i_skip
)
2311 return VLC_EGENERIC
;
2316 static int AVI_PacketSearch( demux_t
*p_demux
)
2318 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2319 avi_packet_t avi_pk
;
2324 if( vlc_stream_Read( p_demux
->s
, NULL
, 1 ) != 1 )
2326 return VLC_EGENERIC
;
2328 AVI_PacketGetHeader( p_demux
, &avi_pk
);
2329 if( avi_pk
.i_stream
< p_sys
->i_track
&&
2330 ( avi_pk
.i_cat
== AUDIO_ES
|| avi_pk
.i_cat
== VIDEO_ES
) )
2334 switch( avi_pk
.i_fourcc
)
2336 case AVIFOURCC_JUNK
:
2337 case AVIFOURCC_LIST
:
2338 case AVIFOURCC_RIFF
:
2339 case AVIFOURCC_idx1
:
2343 /* Prevents from eating all the CPU with broken files.
2344 * This value should be low enough so that it doesn't affect the
2345 * reading speed too much (not that we care much anyway because
2346 * this code is called only on broken files). */
2347 if( !(++i_count
% 1024) )
2350 if( !(i_count
% (1024 * 10)) )
2351 msg_Warn( p_demux
, "trying to resync..." );
2356 /****************************************************************************
2358 ****************************************************************************/
2359 static void avi_index_Init( avi_index_t
*p_index
)
2361 p_index
->i_size
= 0;
2363 p_index
->p_entry
= NULL
;
2365 static void avi_index_Clean( avi_index_t
*p_index
)
2367 free( p_index
->p_entry
);
2369 static void avi_index_Append( avi_index_t
*p_index
, uint32_t *pi_last_pos
,
2370 avi_entry_t
*p_entry
)
2372 /* Update last chunk position */
2373 if( *pi_last_pos
< p_entry
->i_pos
)
2374 *pi_last_pos
= p_entry
->i_pos
;
2377 if( p_index
->i_size
>= p_index
->i_max
)
2379 p_index
->i_max
+= 16384;
2380 p_index
->p_entry
= realloc_or_free( p_index
->p_entry
,
2381 p_index
->i_max
* sizeof( *p_index
->p_entry
) );
2382 if( !p_index
->p_entry
)
2385 /* calculate cumulate length */
2386 if( p_index
->i_size
> 0 )
2388 p_entry
->i_lengthtotal
=
2389 p_index
->p_entry
[p_index
->i_size
- 1].i_length
+
2390 p_index
->p_entry
[p_index
->i_size
- 1].i_lengthtotal
;
2394 p_entry
->i_lengthtotal
= 0;
2397 p_index
->p_entry
[p_index
->i_size
++] = *p_entry
;
2400 static int AVI_IndexFind_idx1( demux_t
*p_demux
,
2401 avi_chunk_idx1_t
**pp_idx1
,
2402 uint64_t *pi_offset
)
2404 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2406 avi_chunk_list_t
*p_riff
= AVI_ChunkFind( &p_sys
->ck_root
, AVIFOURCC_RIFF
, 0, true);
2407 avi_chunk_idx1_t
*p_idx1
= AVI_ChunkFind( p_riff
, AVIFOURCC_idx1
, 0, false);
2411 msg_Warn( p_demux
, "cannot find idx1 chunk, no index defined" );
2412 return VLC_EGENERIC
;
2416 /* The offset in the index should be from the start of the movi content,
2417 * but some broken files use offset from the start of the file. Just
2418 * checking the offset of the first packet is not enough as some files
2419 * has unused chunk at the beginning of the movi content.
2421 avi_chunk_list_t
*p_movi
= AVI_ChunkFind( p_riff
, AVIFOURCC_movi
, 0, true );
2423 return VLC_EGENERIC
;
2424 uint64_t i_first_pos
= UINT64_MAX
;
2425 for( unsigned i
= 0; i
< __MIN( p_idx1
->i_entry_count
, 100 ); i
++ )
2427 if ( p_idx1
->entry
[i
].i_length
> 0 )
2428 i_first_pos
= __MIN( i_first_pos
, p_idx1
->entry
[i
].i_pos
);
2431 const uint64_t i_movi_content
= p_movi
->i_chunk_pos
+ 8;
2432 if( i_first_pos
< i_movi_content
)
2434 *pi_offset
= i_movi_content
;
2436 else if( p_sys
->b_seekable
&& i_first_pos
< UINT64_MAX
)
2438 const uint8_t *p_peek
;
2439 if( !vlc_stream_Seek( p_demux
->s
, i_movi_content
+ i_first_pos
) &&
2440 vlc_stream_Peek( p_demux
->s
, &p_peek
, 4 ) >= 4 &&
2441 ( !isdigit( p_peek
[0] ) || !isdigit( p_peek
[1] ) ||
2442 !isalpha( p_peek
[2] ) || !isalpha( p_peek
[3] ) ) )
2445 *pi_offset
= i_movi_content
;
2447 if( p_idx1
->i_entry_count
)
2449 /* Invalidate offset if index refers past the data section to avoid false
2450 positives when the offset equals sample size */
2451 size_t i_dataend
= *pi_offset
+ p_idx1
->entry
[p_idx1
->i_entry_count
- 1].i_pos
+
2452 p_idx1
->entry
[p_idx1
->i_entry_count
- 1].i_length
;
2453 if( i_dataend
> p_movi
->i_chunk_pos
+ p_movi
->i_chunk_size
)
2465 static int AVI_IndexLoad_idx1( demux_t
*p_demux
,
2466 avi_index_t p_index
[], uint32_t *pi_last_offset
)
2468 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2470 avi_chunk_idx1_t
*p_idx1
;
2472 if( AVI_IndexFind_idx1( p_demux
, &p_idx1
, &i_offset
) )
2473 return VLC_EGENERIC
;
2475 p_sys
->b_indexloaded
= true;
2477 for( unsigned i_index
= 0; i_index
< p_idx1
->i_entry_count
; i_index
++ )
2479 enum es_format_category_e i_cat
;
2482 AVI_ParseStreamHeader( p_idx1
->entry
[i_index
].i_fourcc
,
2485 if( i_stream
< p_sys
->i_track
&&
2486 (i_cat
== p_sys
->track
[i_stream
]->fmt
.i_cat
|| i_cat
== UNKNOWN_ES
) )
2489 index
.i_id
= p_idx1
->entry
[i_index
].i_fourcc
;
2490 index
.i_flags
= p_idx1
->entry
[i_index
].i_flags
&(~AVIIF_FIXKEYFRAME
);
2491 index
.i_pos
= p_idx1
->entry
[i_index
].i_pos
+ i_offset
;
2492 index
.i_length
= p_idx1
->entry
[i_index
].i_length
;
2493 index
.i_lengthtotal
= index
.i_length
;
2495 avi_index_Append( &p_index
[i_stream
], pi_last_offset
, &index
);
2500 for( unsigned i_index
= 0; i_index
< p_idx1
->i_entry_count
&& i_index
< p_sys
->i_track
; i_index
++ )
2502 for( unsigned i
= 0; i
< p_index
[i_index
].i_size
; i
++ )
2505 if( p_sys
->track
[i_index
]->i_samplesize
)
2507 i_length
= AVI_GetDPTS( p_sys
->track
[i_index
],
2508 p_index
[i_index
].p_entry
[i
].i_lengthtotal
);
2512 i_length
= AVI_GetDPTS( p_sys
->track
[i_index
], i
);
2514 msg_Dbg( p_demux
, "index stream %d @%ld time %ld", i_index
,
2515 p_index
[i_index
].p_entry
[i
].i_pos
, i_length
);
2522 static void __Parse_indx( demux_t
*p_demux
, avi_index_t
*p_index
, uint32_t *pi_max_offset
,
2523 avi_chunk_indx_t
*p_indx
)
2525 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2528 p_sys
->b_indexloaded
= true;
2530 msg_Dbg( p_demux
, "loading subindex(0x%x) %d entries", p_indx
->i_indextype
, p_indx
->i_entriesinuse
);
2531 if( p_indx
->i_indexsubtype
== 0 )
2533 for( unsigned i
= 0; i
< p_indx
->i_entriesinuse
; i
++ )
2535 index
.i_id
= p_indx
->i_id
;
2536 index
.i_flags
= p_indx
->idx
.std
[i
].i_size
& 0x80000000 ? 0 : AVIIF_KEYFRAME
;
2537 index
.i_pos
= p_indx
->i_baseoffset
+ p_indx
->idx
.std
[i
].i_offset
- 8;
2538 index
.i_length
= p_indx
->idx
.std
[i
].i_size
&0x7fffffff;
2539 index
.i_lengthtotal
= index
.i_length
;
2541 avi_index_Append( p_index
, pi_max_offset
, &index
);
2544 else if( p_indx
->i_indexsubtype
== AVI_INDEX_2FIELD
)
2546 for( unsigned i
= 0; i
< p_indx
->i_entriesinuse
; i
++ )
2548 index
.i_id
= p_indx
->i_id
;
2549 index
.i_flags
= p_indx
->idx
.field
[i
].i_size
& 0x80000000 ? 0 : AVIIF_KEYFRAME
;
2550 index
.i_pos
= p_indx
->i_baseoffset
+ p_indx
->idx
.field
[i
].i_offset
- 8;
2551 index
.i_length
= p_indx
->idx
.field
[i
].i_size
;
2552 index
.i_lengthtotal
= index
.i_length
;
2554 avi_index_Append( p_index
, pi_max_offset
, &index
);
2559 msg_Warn( p_demux
, "unknown subtype index(0x%x)", p_indx
->i_indexsubtype
);
2563 static void AVI_IndexLoad_indx( demux_t
*p_demux
,
2564 avi_index_t p_index
[], uint32_t *pi_last_offset
)
2566 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2568 avi_chunk_list_t
*p_riff
;
2569 avi_chunk_list_t
*p_hdrl
;
2571 p_riff
= AVI_ChunkFind( &p_sys
->ck_root
, AVIFOURCC_RIFF
, 0, true);
2572 p_hdrl
= AVI_ChunkFind( p_riff
, AVIFOURCC_hdrl
, 0, true );
2574 for( unsigned i_stream
= 0; i_stream
< p_sys
->i_track
; i_stream
++ )
2576 avi_chunk_list_t
*p_strl
;
2577 avi_chunk_indx_t
*p_indx
;
2579 #define p_stream p_sys->track[i_stream]
2580 p_strl
= AVI_ChunkFind( p_hdrl
, AVIFOURCC_strl
, i_stream
, true );
2581 p_indx
= AVI_ChunkFind( p_strl
, AVIFOURCC_indx
, 0, false );
2586 msg_Warn( p_demux
, "cannot find indx (misdetect/broken OpenDML "
2591 if( p_indx
->i_indextype
== AVI_INDEX_OF_CHUNKS
)
2593 __Parse_indx( p_demux
, &p_index
[i_stream
], pi_last_offset
, p_indx
);
2595 else if( p_indx
->i_indextype
== AVI_INDEX_OF_INDEXES
)
2597 if ( !p_sys
->b_seekable
)
2600 for( unsigned i
= 0; i
< p_indx
->i_entriesinuse
; i
++ )
2602 if( vlc_stream_Seek( p_demux
->s
,
2603 p_indx
->idx
.super
[i
].i_offset
) ||
2604 AVI_ChunkRead( p_demux
->s
, &ck_sub
, NULL
) )
2608 if( ck_sub
.indx
.i_indextype
== AVI_INDEX_OF_CHUNKS
)
2609 __Parse_indx( p_demux
, &p_index
[i_stream
], pi_last_offset
, &ck_sub
.indx
);
2610 AVI_ChunkClean( p_demux
->s
, &ck_sub
);
2615 msg_Warn( p_demux
, "unknown type index(0x%x)", p_indx
->i_indextype
);
2621 static void AVI_IndexLoad( demux_t
*p_demux
)
2623 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2626 assert( p_sys
->i_track
<= 100 );
2627 avi_index_t p_idx_indx
[p_sys
->i_track
];
2628 avi_index_t p_idx_idx1
[p_sys
->i_track
];
2629 for( unsigned i
= 0; i
< p_sys
->i_track
; i
++ )
2631 avi_index_Init( &p_idx_indx
[i
] );
2632 avi_index_Init( &p_idx_idx1
[i
] );
2634 uint32_t i_indx_last_pos
= p_sys
->i_movi_lastchunk_pos
;
2635 uint32_t i_idx1_last_pos
= p_sys
->i_movi_lastchunk_pos
;
2637 AVI_IndexLoad_indx( p_demux
, p_idx_indx
, &i_indx_last_pos
);
2638 if( !p_sys
->b_odml
)
2639 AVI_IndexLoad_idx1( p_demux
, p_idx_idx1
, &i_idx1_last_pos
);
2641 /* Select the longest index */
2642 for( unsigned i
= 0; i
< p_sys
->i_track
; i
++ )
2644 if( p_idx_indx
[i
].i_size
> p_idx_idx1
[i
].i_size
)
2646 msg_Dbg( p_demux
, "selected ODML index for stream[%u]", i
);
2647 p_sys
->track
[i
]->idx
= p_idx_indx
[i
];
2648 avi_index_Clean( &p_idx_idx1
[i
] );
2652 msg_Dbg( p_demux
, "selected standard index for stream[%u]", i
);
2653 p_sys
->track
[i
]->idx
= p_idx_idx1
[i
];
2654 avi_index_Clean( &p_idx_indx
[i
] );
2657 p_sys
->i_movi_lastchunk_pos
= __MAX( i_indx_last_pos
, i_idx1_last_pos
);
2659 for( unsigned i
= 0; i
< p_sys
->i_track
; i
++ )
2661 avi_index_t
*p_index
= &p_sys
->track
[i
]->idx
;
2665 for( unsigned j
= 0; !b_key
&& j
< p_index
->i_size
; j
++ )
2666 b_key
= p_index
->p_entry
[j
].i_flags
& AVIIF_KEYFRAME
;
2669 msg_Err( p_demux
, "no key frame set for track %u", i
);
2670 for( unsigned j
= 0; j
< p_index
->i_size
; j
++ )
2671 p_index
->p_entry
[j
].i_flags
|= AVIIF_KEYFRAME
;
2675 msg_Dbg( p_demux
, "stream[%d] created %d index entries",
2676 i
, p_index
->i_size
);
2680 static void AVI_IndexCreate( demux_t
*p_demux
)
2682 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2684 avi_chunk_list_t
*p_riff
;
2685 avi_chunk_list_t
*p_movi
;
2687 unsigned int i_stream
;
2688 uint32_t i_movi_end
;
2690 mtime_t i_dialog_update
;
2691 vlc_dialog_id
*p_dialog_id
= NULL
;
2693 p_riff
= AVI_ChunkFind( &p_sys
->ck_root
, AVIFOURCC_RIFF
, 0, true );
2694 p_movi
= AVI_ChunkFind( p_riff
, AVIFOURCC_movi
, 0, true );
2698 msg_Err( p_demux
, "cannot find p_movi" );
2702 for( i_stream
= 0; i_stream
< p_sys
->i_track
; i_stream
++ )
2703 avi_index_Init( &p_sys
->track
[i_stream
]->idx
);
2705 i_movi_end
= __MIN( (uint32_t)(p_movi
->i_chunk_pos
+ p_movi
->i_chunk_size
),
2706 stream_Size( p_demux
->s
) );
2708 vlc_stream_Seek( p_demux
->s
, p_movi
->i_chunk_pos
+ 12 );
2709 msg_Warn( p_demux
, "creating index from LIST-movi, will take time !" );
2712 /* Only show dialog if AVI is > 10MB */
2713 i_dialog_update
= mdate();
2714 if( stream_Size( p_demux
->s
) > 10000000 )
2717 vlc_dialog_display_progress( p_demux
, false, 0.0, _("Cancel"),
2718 _("Broken or missing AVI Index"),
2719 _("Fixing AVI Index...") );
2726 /* Don't update/check dialog too often */
2727 if( p_dialog_id
!= NULL
&& mdate() - i_dialog_update
> 100000 )
2729 if( vlc_dialog_is_cancelled( p_demux
, p_dialog_id
) )
2732 double f_current
= vlc_stream_Tell( p_demux
->s
);
2733 double f_size
= stream_Size( p_demux
->s
);
2734 double f_pos
= f_current
/ f_size
;
2735 vlc_dialog_update_progress( p_demux
, p_dialog_id
, f_pos
);
2737 i_dialog_update
= mdate();
2740 if( AVI_PacketGetHeader( p_demux
, &pk
) )
2743 if( pk
.i_stream
< p_sys
->i_track
&&
2744 pk
.i_cat
== p_sys
->track
[pk
.i_stream
]->fmt
.i_cat
)
2746 avi_track_t
*tk
= p_sys
->track
[pk
.i_stream
];
2749 index
.i_id
= pk
.i_fourcc
;
2750 index
.i_flags
= AVI_GetKeyFlag(tk
->fmt
.i_codec
, pk
.i_peek
);
2751 index
.i_pos
= pk
.i_pos
;
2752 index
.i_length
= pk
.i_size
;
2753 index
.i_lengthtotal
= pk
.i_size
;
2754 avi_index_Append( &tk
->idx
, &p_sys
->i_movi_lastchunk_pos
, &index
);
2758 switch( pk
.i_fourcc
)
2760 case AVIFOURCC_idx1
:
2763 avi_chunk_list_t
*p_sysx
;
2764 p_sysx
= AVI_ChunkFind( &p_sys
->ck_root
,
2765 AVIFOURCC_RIFF
, 1, true );
2767 msg_Dbg( p_demux
, "looking for new RIFF chunk" );
2768 if( !p_sysx
|| vlc_stream_Seek( p_demux
->s
,
2769 p_sysx
->i_chunk_pos
+ 24 ) )
2775 case AVIFOURCC_RIFF
:
2776 msg_Dbg( p_demux
, "new RIFF chunk found" );
2780 case AVIFOURCC_JUNK
:
2784 msg_Warn( p_demux
, "need resync, probably broken avi" );
2785 if( AVI_PacketSearch( p_demux
) )
2787 msg_Warn( p_demux
, "lost sync, abord index creation" );
2793 if( ( !p_sys
->b_odml
&& pk
.i_pos
+ pk
.i_size
>= i_movi_end
) ||
2794 AVI_PacketNext( p_demux
) )
2801 if( p_dialog_id
!= NULL
)
2802 vlc_dialog_release( p_demux
, p_dialog_id
);
2804 for( i_stream
= 0; i_stream
< p_sys
->i_track
; i_stream
++ )
2806 msg_Dbg( p_demux
, "stream[%d] creating %d index entries",
2807 i_stream
, p_sys
->track
[i_stream
]->idx
.i_size
);
2812 static void AVI_MetaLoad( demux_t
*p_demux
,
2813 avi_chunk_list_t
*p_riff
, avi_chunk_avih_t
*p_avih
)
2815 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2817 vlc_meta_t
*p_meta
= p_sys
->meta
= vlc_meta_New();
2822 snprintf( buffer
, sizeof(buffer
), "%s%s%s%s",
2823 p_avih
->i_flags
&AVIF_HASINDEX
? " HAS_INDEX" : "",
2824 p_avih
->i_flags
&AVIF_MUSTUSEINDEX
? " MUST_USE_INDEX" : "",
2825 p_avih
->i_flags
&AVIF_ISINTERLEAVED
? " IS_INTERLEAVED" : "",
2826 p_avih
->i_flags
&AVIF_TRUSTCKTYPE
? " TRUST_CKTYPE" : "" );
2827 vlc_meta_SetSetting( p_meta
, buffer
);
2829 avi_chunk_list_t
*p_info
= AVI_ChunkFind( p_riff
, AVIFOURCC_INFO
, 0, true );
2833 static const struct {
2837 { AVIFOURCC_IART
, vlc_meta_Artist
},
2838 { AVIFOURCC_ICMT
, vlc_meta_Description
},
2839 { AVIFOURCC_ICOP
, vlc_meta_Copyright
},
2840 { AVIFOURCC_IGNR
, vlc_meta_Genre
},
2841 { AVIFOURCC_INAM
, vlc_meta_Title
},
2842 { AVIFOURCC_ICRD
, vlc_meta_Date
},
2843 { AVIFOURCC_ILNG
, vlc_meta_Language
},
2844 { AVIFOURCC_IRTD
, vlc_meta_Rating
},
2845 { AVIFOURCC_IWEB
, vlc_meta_URL
},
2846 { AVIFOURCC_IPRT
, vlc_meta_TrackNumber
},
2847 { AVIFOURCC_IFRM
, vlc_meta_TrackTotal
},
2850 for( int i
= 0; p_dsc
[i
].i_id
!= 0; i
++ )
2852 avi_chunk_STRING_t
*p_strz
= AVI_ChunkFind( p_info
, p_dsc
[i
].i_id
, 0, false );
2853 if( !p_strz
|| !p_strz
->p_str
)
2855 char *psz_value
= FromACP( p_strz
->p_str
);
2860 vlc_meta_Set( p_meta
, p_dsc
[i
].i_type
, psz_value
);
2864 static const vlc_fourcc_t p_extra
[] = {
2865 AVIFOURCC_IARL
, AVIFOURCC_ICMS
, AVIFOURCC_ICRP
, AVIFOURCC_IDIM
, AVIFOURCC_IDPI
,
2866 AVIFOURCC_IENG
, AVIFOURCC_IKEY
, AVIFOURCC_ILGT
, AVIFOURCC_IMED
, AVIFOURCC_IPLT
,
2867 AVIFOURCC_IPRD
, AVIFOURCC_ISBJ
, AVIFOURCC_ISFT
, AVIFOURCC_ISHP
, AVIFOURCC_ISRC
,
2868 AVIFOURCC_ISRF
, AVIFOURCC_ITCH
, AVIFOURCC_ISMP
, AVIFOURCC_IDIT
, AVIFOURCC_ISGN
,
2869 AVIFOURCC_IWRI
, AVIFOURCC_IPRO
, AVIFOURCC_ICNM
, AVIFOURCC_IPDS
, AVIFOURCC_IEDT
,
2870 AVIFOURCC_ICDS
, AVIFOURCC_IMUS
, AVIFOURCC_ISTD
, AVIFOURCC_IDST
, AVIFOURCC_ICNT
,
2874 for( int i
= 0; p_extra
[i
] != 0; i
++ )
2876 avi_chunk_STRING_t
*p_strz
= AVI_ChunkFind( p_info
, p_extra
[i
], 0, false );
2877 if( !p_strz
|| !p_strz
->p_str
)
2879 char *psz_value
= FromACP( p_strz
->p_str
);
2884 vlc_meta_AddExtra( p_meta
, p_strz
->p_type
, psz_value
);
2889 static void AVI_DvHandleAudio( demux_t
*p_demux
, avi_track_t
*tk
, block_t
*p_frame
)
2891 size_t i_offset
= 80 * 6 + 80 * 16 * 3 + 3;
2892 if( p_frame
->i_buffer
< i_offset
+ 5 )
2895 if( p_frame
->p_buffer
[i_offset
] != 0x50 )
2899 dv_get_audio_format( &fmt
, &p_frame
->p_buffer
[i_offset
+ 1] );
2901 if( tk
->p_es_dv_audio
&& tk
->i_dv_audio_rate
!= (int)fmt
.audio
.i_rate
)
2903 es_out_Del( p_demux
->out
, tk
->p_es_dv_audio
);
2904 tk
->p_es_dv_audio
= es_out_Add( p_demux
->out
, &fmt
);
2906 else if( !tk
->p_es_dv_audio
)
2908 tk
->p_es_dv_audio
= es_out_Add( p_demux
->out
, &fmt
);
2910 tk
->i_dv_audio_rate
= fmt
.audio
.i_rate
;
2911 es_format_Clean( &fmt
);
2913 block_t
*p_frame_audio
= dv_extract_audio( p_frame
);
2916 if( tk
->p_es_dv_audio
)
2917 es_out_Send( p_demux
->out
, tk
->p_es_dv_audio
, p_frame_audio
);
2919 block_Release( p_frame_audio
);
2923 /*****************************************************************************
2925 *****************************************************************************/
2926 static void AVI_ExtractSubtitle( demux_t
*p_demux
,
2927 unsigned int i_stream
,
2928 avi_chunk_list_t
*p_strl
,
2929 avi_chunk_STRING_t
*p_strn
)
2931 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2932 block_t
*p_block
= NULL
;
2933 input_attachment_t
*p_attachment
= NULL
;
2934 char *psz_description
= NULL
;
2935 avi_chunk_indx_t
*p_indx
= NULL
;
2937 if( !p_sys
->b_seekable
)
2940 p_indx
= AVI_ChunkFind( p_strl
, AVIFOURCC_indx
, 0, false );
2946 if( p_indx
->i_indextype
== AVI_INDEX_OF_INDEXES
&&
2947 p_indx
->i_entriesinuse
> 0 )
2949 if( vlc_stream_Seek( p_demux
->s
, p_indx
->idx
.super
[0].i_offset
) ||
2950 AVI_ChunkRead( p_demux
->s
, &ck
, NULL
) )
2955 if( p_indx
->i_indextype
!= AVI_INDEX_OF_CHUNKS
||
2956 p_indx
->i_entriesinuse
!= 1 ||
2957 p_indx
->i_indexsubtype
!= 0 )
2960 i_position
= p_indx
->i_baseoffset
+
2961 p_indx
->idx
.std
[0].i_offset
- 8;
2962 i_size
= (p_indx
->idx
.std
[0].i_size
& 0x7fffffff) + 8;
2966 avi_chunk_idx1_t
*p_idx1
;
2969 if( AVI_IndexFind_idx1( p_demux
, &p_idx1
, &i_offset
) )
2973 for( unsigned i
= 0; i
< p_idx1
->i_entry_count
; i
++ )
2975 const idx1_entry_t
*e
= &p_idx1
->entry
[i
];
2976 enum es_format_category_e i_cat
;
2977 unsigned i_stream_idx
;
2979 AVI_ParseStreamHeader( e
->i_fourcc
, &i_stream_idx
, &i_cat
);
2980 if( i_cat
== SPU_ES
&& i_stream_idx
== i_stream
)
2982 i_position
= e
->i_pos
+ i_offset
;
2983 i_size
= e
->i_length
+ 8;
2992 if( i_size
> 10000000 )
2994 msg_Dbg( p_demux
, "Attached subtitle too big: %u", i_size
);
2998 if( vlc_stream_Seek( p_demux
->s
, i_position
) )
3000 p_block
= vlc_stream_Block( p_demux
->s
, i_size
);
3004 /* Parse packet header */
3005 const uint8_t *p
= p_block
->p_buffer
;
3006 if( i_size
< 8 || p
[2] != 't' || p
[3] != 'x' )
3011 /* Parse subtitle chunk header */
3012 if( i_size
< 11 || memcmp( p
, "GAB2", 4 ) ||
3013 p
[4] != 0x00 || GetWLE( &p
[5] ) != 0x2 )
3015 const unsigned i_name
= GetDWLE( &p
[7] );
3016 if( 11 + i_size
<= i_name
)
3019 psz_description
= FromCharset( "UTF-16LE", &p
[11], i_name
);
3021 i_size
-= 11 + i_name
;
3022 if( i_size
< 6 || GetWLE( &p
[0] ) != 0x04 )
3024 const unsigned i_payload
= GetDWLE( &p
[2] );
3025 if( i_size
< 6 + i_payload
|| i_payload
<= 0 )
3030 if( !psz_description
)
3031 psz_description
= p_strn
&& p_strn
->p_str
? FromACP( p_strn
->p_str
) : NULL
;
3033 if( asprintf( &psz_name
, "subtitle%d.srt", p_sys
->i_attachment
) <= 0 )
3035 p_attachment
= vlc_input_attachment_New( psz_name
,
3036 "application/x-srt",
3040 TAB_APPEND( p_sys
->i_attachment
, p_sys
->attachment
, p_attachment
);
3044 free( psz_description
);
3047 block_Release( p_block
);
3050 msg_Dbg( p_demux
, "Loaded an embedded subtitle" );
3052 msg_Warn( p_demux
, "Failed to load an embedded subtitle" );
3054 if( p_indx
== &ck
.indx
)
3055 AVI_ChunkClean( p_demux
->s
, &ck
);
3057 /*****************************************************************************
3059 *****************************************************************************/
3060 static int AVI_TrackStopFinishedStreams( demux_t
*p_demux
)
3062 demux_sys_t
*p_sys
= p_demux
->p_sys
;
3066 for( i
= 0; i
< p_sys
->i_track
; i
++ )
3068 avi_track_t
*tk
= p_sys
->track
[i
];
3069 if( tk
->i_idxposc
>= tk
->idx
.i_size
)
3081 /****************************************************************************
3082 * AVI_MovieGetLength give max streams length in second
3083 ****************************************************************************/
3084 static mtime_t
AVI_MovieGetLength( demux_t
*p_demux
)
3086 demux_sys_t
*p_sys
= p_demux
->p_sys
;
3087 mtime_t i_maxlength
= 0;
3090 for( i
= 0; i
< p_sys
->i_track
; i
++ )
3092 avi_track_t
*tk
= p_sys
->track
[i
];
3095 /* fix length for each stream */
3096 if( tk
->idx
.i_size
< 1 || !tk
->idx
.p_entry
)
3101 if( tk
->i_samplesize
)
3103 i_length
= AVI_GetDPTS( tk
,
3104 tk
->idx
.p_entry
[tk
->idx
.i_size
-1].i_lengthtotal
+
3105 tk
->idx
.p_entry
[tk
->idx
.i_size
-1].i_length
);
3109 i_length
= AVI_GetDPTS( tk
, tk
->idx
.i_size
);
3111 i_length
/= CLOCK_FREQ
; /* in seconds */
3114 "stream[%d] length:%"PRId64
" (based on index)",
3117 i_maxlength
= __MAX( i_maxlength
, i_length
);