1 /*****************************************************************************
2 * avi.c : AVI file Stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: avi.c,v 1.84 2004/01/05 13:00:20 zorglub Exp $
6 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
26 #include <stdlib.h> /* malloc(), free() */
29 #include <vlc/input.h>
30 #include "vlc_playlist.h"
36 /*****************************************************************************
38 *****************************************************************************/
39 static int Open ( vlc_object_t * );
40 static void Close ( vlc_object_t * );
43 add_category_hint( N_("AVI demuxer"), NULL, VLC_TRUE );
44 add_bool( "avi-interleaved", 0, NULL,
45 N_("force interleaved method"),
46 N_("force interleaved method"), VLC_TRUE );
47 add_bool( "avi-index", 0, NULL,
48 N_("force index creation"),
49 N_("force index creation"), VLC_TRUE );
51 set_description( N_("AVI demuxer") );
52 set_capability( "demux", 212 );
53 set_callbacks( Open, Close );
56 /*****************************************************************************
58 *****************************************************************************/
59 static int Control ( input_thread_t *, int, va_list );
60 static int Seek ( input_thread_t *, mtime_t, int );
61 static int Demux_Seekable ( input_thread_t * );
62 static int Demux_UnSeekable( input_thread_t *p_input );
64 #define FREE( p ) if( p ) { free( p ); (p) = NULL; }
65 #define __ABS( x ) ( (x) < 0 ? (-(x)) : (x) )
67 static inline off_t __EVEN( off_t i )
69 return (i & 1) ? i + 1 : i;
72 static mtime_t AVI_PTSToChunk( avi_track_t *, mtime_t i_pts );
73 static mtime_t AVI_PTSToByte ( avi_track_t *, mtime_t i_pts );
74 static mtime_t AVI_GetDPTS ( avi_track_t *, int64_t i_count );
75 static mtime_t AVI_GetPTS ( avi_track_t * );
78 static int AVI_StreamChunkFind( input_thread_t *, unsigned int i_stream );
79 static int AVI_StreamChunkSet ( input_thread_t *,
80 unsigned int i_stream, unsigned int i_ck );
81 static int AVI_StreamBytesSet ( input_thread_t *,
82 unsigned int i_stream, off_t i_byte );
84 vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t );
85 static int AVI_GetKeyFlag ( vlc_fourcc_t , uint8_t * );
87 static int AVI_PacketGetHeader( input_thread_t *, avi_packet_t *p_pk );
88 static int AVI_PacketNext ( input_thread_t * );
89 static int AVI_PacketRead ( input_thread_t *, avi_packet_t *, block_t **);
90 static int AVI_PacketSearch ( input_thread_t * );
92 static void AVI_IndexLoad ( input_thread_t * );
93 static void AVI_IndexCreate ( input_thread_t * );
94 static void AVI_IndexAddEntry( demux_sys_t *, int, AVIIndexEntry_t * );
96 static mtime_t AVI_MovieGetLength( input_thread_t * );
98 /*****************************************************************************
100 *****************************************************************************/
101 static int AVI_TrackSeek ( input_thread_t *, int, mtime_t );
102 static int AVI_TrackStopFinishedStreams( input_thread_t *);
105 - For VBR mp3 stream:
106 count blocks by rounded-up chunksizes instead of chunks
107 we need full emulation of dshow avi demuxer bugs :(
108 fixes silly nandub-style a-v delaying in avi with vbr mp3...
109 (from mplayer 2002/08/02)
113 /*****************************************************************************
114 * Open: check file and initializes AVI structures
115 *****************************************************************************/
116 static int Open( vlc_object_t * p_this )
118 input_thread_t *p_input = (input_thread_t *)p_this;
122 avi_chunk_list_t *p_riff = (avi_chunk_list_t*)&ck_riff;
123 avi_chunk_list_t *p_hdrl, *p_movi;
124 avi_chunk_avih_t *p_avih;
126 unsigned int i_track;
132 /* Is it an avi file ? */
133 if( stream_Peek( p_input->s, &p_peek, 12 ) < 12 )
135 msg_Err( p_input, "cannot peek()" );
138 if( strncmp( &p_peek[0], "RIFF", 4 ) || strncmp( &p_peek[8], "AVI ", 4 ) )
140 msg_Warn( p_input, "avi module discarded (invalid header)" );
144 /* Initialize input structures. */
145 p_sys = p_input->p_demux_data = malloc( sizeof(demux_sys_t) );
146 memset( p_sys, 0, sizeof( demux_sys_t ) );
150 p_sys->i_movi_lastchunk_pos = 0;
151 p_sys->b_odml = VLC_FALSE;
155 stream_Control( p_input->s, STREAM_CAN_FASTSEEK, &p_sys->b_seekable );
157 p_input->pf_demux_control = Control;
158 p_input->pf_demux = Demux_Seekable;
159 /* For unseekable stream, automaticaly use Demux_UnSeekable */
160 if( !p_sys->b_seekable || config_GetInt( p_input, "avi-interleaved" ) )
162 p_input->pf_demux = Demux_UnSeekable;
165 if( AVI_ChunkReadRoot( p_input->s, &p_sys->ck_root ) )
167 msg_Err( p_input, "avi module discarded (invalid file)" );
171 if( AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF ) > 1 )
173 unsigned int i_count =
174 AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF );
176 msg_Warn( p_input, "multiple riff -> OpenDML ?" );
177 for( i = 1; i < i_count; i++ )
179 avi_chunk_list_t *p_sysx;
181 p_sysx = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, i );
182 if( p_sysx->i_type == AVIFOURCC_AVIX )
184 msg_Warn( p_input, "detected OpenDML file" );
185 p_sys->b_odml = VLC_TRUE;
191 p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0 );
192 p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
193 p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0 );
195 if( !p_hdrl || !p_movi )
197 msg_Err( p_input, "avi module discarded (invalid file)" );
201 if( !( p_avih = AVI_ChunkFind( p_hdrl, AVIFOURCC_avih, 0 ) ) )
203 msg_Err( p_input, "cannot find avih chunk" );
206 i_track = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl );
207 if( p_avih->i_streams != i_track )
210 "found %d stream but %d are declared",
211 i_track, p_avih->i_streams );
215 msg_Err( p_input, "no stream defined!" );
219 /* create one program */
220 vlc_mutex_lock( &p_input->stream.stream_lock );
221 if( input_InitStream( p_input, 0 ) == -1)
223 vlc_mutex_unlock( &p_input->stream.stream_lock );
224 msg_Err( p_input, "cannot init stream" );
227 p_input->stream.i_mux_rate = 0; /* Fixed later */
228 vlc_mutex_unlock( &p_input->stream.stream_lock );
230 /* print informations on streams */
231 msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ",
233 p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
234 p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
235 p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
236 p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
238 playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_input,
239 VLC_OBJECT_PLAYLIST, FIND_PARENT);
240 input_info_category_t *p_cat = input_InfoCategory( p_input, _("Avi") );
242 input_AddInfo( p_cat, _("Number of streams"), "%d", i_track );
243 input_AddInfo( p_cat, _("Flags"), "%s%s%s%s",
244 p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
245 p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
246 p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
247 p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
250 playlist_AddInfo( p_playlist, -1 , _("Avi"),
251 _("Number of streams"), "%d", i_track );
252 playlist_AddInfo( p_playlist, -1 , _("Avi"),
253 _("Flags"), "%s%s%s%s",
254 p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
255 p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
256 p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
257 p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
258 vlc_object_release( p_playlist );
262 /* now read info on each stream and create ES */
263 for( i = 0 ; i < i_track; i++ )
265 avi_track_t *tk = malloc( sizeof( avi_track_t ) );
266 avi_chunk_list_t *p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
267 avi_chunk_strh_t *p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );
268 avi_chunk_strf_auds_t *p_auds;
269 avi_chunk_strf_vids_t *p_vids;
272 tk->b_activated = VLC_FALSE;
282 p_auds = (void*)p_vids = (void*)AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );
284 if( p_strl == NULL || p_strh == NULL || p_auds == NULL || p_vids == NULL )
286 msg_Warn( p_input, "stream[%d] incomplete", i );
290 tk->i_rate = p_strh->i_rate;
291 tk->i_scale = p_strh->i_scale;
292 tk->i_samplesize = p_strh->i_samplesize;
293 msg_Dbg( p_input, "stream[%d] rate:%d scale:%d samplesize:%d",
294 i, tk->i_rate, tk->i_scale, tk->i_samplesize );
296 switch( p_strh->i_type )
298 case( AVIFOURCC_auds ):
299 tk->i_cat = AUDIO_ES;
300 tk->i_codec = AVI_FourccGetCodec( AUDIO_ES,
301 p_auds->p_wf->wFormatTag );
302 if( ( tk->i_blocksize = p_auds->p_wf->nBlockAlign ) == 0 )
304 if( p_auds->p_wf->wFormatTag == 1 )
306 tk->i_blocksize = p_auds->p_wf->nChannels * (p_auds->p_wf->wBitsPerSample/8);
313 es_format_Init( &fmt, AUDIO_ES, tk->i_codec );
315 fmt.audio.i_channels = p_auds->p_wf->nChannels;
316 fmt.audio.i_rate = p_auds->p_wf->nSamplesPerSec;
317 fmt.i_bitrate = p_auds->p_wf->nAvgBytesPerSec*8;
318 fmt.audio.i_blockalign = p_auds->p_wf->nBlockAlign;
319 fmt.audio.i_bitspersample = p_auds->p_wf->wBitsPerSample;
320 fmt.i_extra = __MIN( p_auds->p_wf->cbSize,
321 p_auds->i_chunk_size - sizeof(WAVEFORMATEX) );
322 fmt.p_extra = &p_auds->p_wf[1];
323 msg_Dbg( p_input, "stream[%d] audio(0x%x) %d channels %dHz %dbits",
324 i, p_auds->p_wf->wFormatTag, p_auds->p_wf->nChannels,
325 p_auds->p_wf->nSamplesPerSec, p_auds->p_wf->wBitsPerSample);
328 case( AVIFOURCC_vids ):
329 tk->i_cat = VIDEO_ES;
330 tk->i_codec = AVI_FourccGetCodec( VIDEO_ES,
331 p_vids->p_bih->biCompression );
332 es_format_Init( &fmt, VIDEO_ES, p_vids->p_bih->biCompression );
333 tk->i_samplesize = 0;
334 fmt.video.i_width = p_vids->p_bih->biWidth;
335 fmt.video.i_height = p_vids->p_bih->biHeight;
337 __MIN( p_vids->p_bih->biSize - sizeof( BITMAPINFOHEADER ),
338 p_vids->i_chunk_size - sizeof(BITMAPINFOHEADER) );
339 fmt.p_extra = &p_vids->p_bih[1];
340 msg_Dbg( p_input, "stream[%d] video(%4.4s) %dx%d %dbpp %ffps",
342 (char*)&p_vids->p_bih->biCompression,
343 p_vids->p_bih->biWidth,
344 p_vids->p_bih->biHeight,
345 p_vids->p_bih->biBitCount,
346 (float)tk->i_rate/(float)tk->i_scale );
349 msg_Warn( p_input, "stream[%d] unknown type", i );
353 tk->p_es = es_out_Add( p_input->p_es_out, &fmt );
354 TAB_APPEND( p_sys->i_track, p_sys->track, tk );
357 if( p_sys->i_track <= 0 )
359 msg_Err( p_input, "No valid track" );
363 if( config_GetInt( p_input, "avi-index" ) )
365 if( p_sys->b_seekable )
367 AVI_IndexCreate( p_input );
371 msg_Warn( p_input, "cannot create index (unseekable stream)" );
372 AVI_IndexLoad( p_input );
377 AVI_IndexLoad( p_input );
380 /* *** movie length in sec *** */
381 p_sys->i_length = AVI_MovieGetLength( p_input );
382 if( p_sys->i_length < (mtime_t)p_avih->i_totalframes *
383 (mtime_t)p_avih->i_microsecperframe /
386 msg_Warn( p_input, "broken or missing index, 'seek' will be axproximative or will have strange behavour" );
388 /* fix some BeOS MediaKit generated file */
389 for( i = 0 ; i < p_sys->i_track; i++ )
391 avi_track_t *tk = p_sys->track[i];
392 avi_chunk_list_t *p_strl;
393 avi_chunk_strh_t *p_strh;
394 avi_chunk_strf_auds_t *p_auds;
396 if( tk->i_cat != AUDIO_ES )
400 if( tk->i_idxnb < 1 ||
402 tk->i_samplesize != 0 )
406 p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
407 p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );
408 p_auds = AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );
410 if( p_auds->p_wf->wFormatTag != WAVE_FORMAT_PCM &&
411 (unsigned int)tk->i_rate == p_auds->p_wf->nSamplesPerSec )
413 int64_t i_track_length =
414 tk->p_index[tk->i_idxnb-1].i_length +
415 tk->p_index[tk->i_idxnb-1].i_lengthtotal;
416 mtime_t i_length = (mtime_t)p_avih->i_totalframes *
417 (mtime_t)p_avih->i_microsecperframe;
421 msg_Warn( p_input, "track[%d] cannot be fixed (BeOS MediaKit generated)", i );
424 tk->i_samplesize = 1;
425 tk->i_rate = i_track_length * (int64_t)1000000/ i_length;
426 msg_Warn( p_input, "track[%d] fixed with rate=%d scale=%d (BeOS MediaKit generated)", i, tk->i_rate, tk->i_scale );
430 if( p_sys->i_length )
432 p_input->stream.i_mux_rate =
433 stream_Size( p_input->s ) / 50 / p_sys->i_length;
436 if( p_sys->b_seekable )
438 /* we have read all chunk so go back to movi */
439 stream_Seek( p_input->s, p_movi->i_chunk_pos );
441 /* Skip movi header */
442 stream_Read( p_input->s, NULL, 12 );
444 p_sys->i_movi_begin = p_movi->i_chunk_pos;
448 AVI_ChunkFreeRoot( p_input->s, &p_sys->ck_root );
453 /*****************************************************************************
454 * Close: frees unused data
455 *****************************************************************************/
456 static void Close ( vlc_object_t * p_this )
458 input_thread_t * p_input = (input_thread_t *)p_this;
460 demux_sys_t *p_sys = p_input->p_demux_data ;
462 for( i = 0; i < p_sys->i_track; i++ )
464 if( p_sys->track[i] )
466 FREE( p_sys->track[i]->p_index );
467 free( p_sys->track[i] );
470 FREE( p_sys->track );
471 AVI_ChunkFreeRoot( p_input->s, &p_sys->ck_root );
476 /*****************************************************************************
477 * Demux_Seekable: reads and demuxes data packets for stream seekable
478 *****************************************************************************
479 * AVIDemux: reads and demuxes data packets
480 *****************************************************************************
481 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
482 *****************************************************************************/
489 off_t i_posf; /* where we will read :
490 if i_idxposb == 0 : begining of chunk (+8 to acces data)
491 else : point on data directly */
492 } avi_track_toread_t;
494 static int Demux_Seekable( input_thread_t *p_input )
496 demux_sys_t *p_sys = p_input->p_demux_data;
498 unsigned int i_track_count = 0;
499 unsigned int i_track;
501 /* cannot be more than 100 stream (dcXX or wbXX) */
502 avi_track_toread_t toread[100];
505 /* detect new selected/unselected streams */
506 for( i_track = 0; i_track < p_sys->i_track; i_track++ )
508 avi_track_t *tk = p_sys->track[i_track];
511 es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
512 if( b && !tk->b_activated )
514 if( p_sys->b_seekable)
516 AVI_TrackSeek( p_input, i_track, p_sys->i_time );
518 tk->b_activated = VLC_TRUE;
520 else if( !b && tk->b_activated )
522 tk->b_activated = VLC_FALSE;
530 if( i_track_count <= 0 )
532 msg_Warn( p_input, "no track selected, exiting..." );
536 /* wait for the good time */
537 p_sys->i_pcr = p_sys->i_time * 9 / 100;
539 input_ClockManageRef( p_input,
540 p_input->stream.p_selected_program,
544 p_sys->i_time += 25*1000; /* read 25ms */
547 for( i_track = 0; i_track < p_sys->i_track; i_track++ )
549 avi_track_t *tk = p_sys->track[i_track];
552 toread[i_track].b_ok = tk->b_activated;
553 if( tk->i_idxposc < tk->i_idxnb )
555 toread[i_track].i_posf = tk->p_index[tk->i_idxposc].i_pos;
556 if( tk->i_idxposb > 0 )
558 toread[i_track].i_posf += 8 + tk->i_idxposb;
563 toread[i_track].i_posf = -1;
566 i_dpts = p_sys->i_time - AVI_GetPTS( tk );
568 if( tk->i_samplesize )
570 toread[i_track].i_toread = AVI_PTSToByte( tk, __ABS( i_dpts ) );
574 toread[i_track].i_toread = AVI_PTSToChunk( tk, __ABS( i_dpts ) );
579 toread[i_track].i_toread *= -1;
583 b_stream = VLC_FALSE;
594 /* search for first chunk to be read */
595 for( i = 0, b_done = VLC_TRUE, i_pos = -1; i < p_sys->i_track; i++ )
597 if( !toread[i].b_ok ||
598 AVI_GetDPTS( p_sys->track[i],
599 toread[i].i_toread ) <= -25 * 1000 )
604 if( toread[i].i_toread > 0 )
606 b_done = VLC_FALSE; /* not yet finished */
608 if( toread[i].i_posf > 0 )
610 if( i_pos == -1 || i_pos > toread[i_track].i_posf )
613 i_pos = toread[i].i_posf;
625 /* no valid index, we will parse directly the stream
626 * in case we fail we will disable all finished stream */
627 if( p_sys->i_movi_lastchunk_pos >= p_sys->i_movi_begin + 12 )
629 stream_Seek( p_input->s, p_sys->i_movi_lastchunk_pos );
630 if( AVI_PacketNext( p_input ) )
632 return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );
637 stream_Seek( p_input->s, p_sys->i_movi_begin + 12 );
644 if( AVI_PacketGetHeader( p_input, &avi_pk ) )
647 "cannot get packet header, track disabled" );
648 return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );
650 if( avi_pk.i_stream >= p_sys->i_track ||
651 ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
653 if( AVI_PacketNext( p_input ) )
656 "cannot skip packet, track disabled" );
657 return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );
663 /* add this chunk to the index */
664 AVIIndexEntry_t index;
666 index.i_id = avi_pk.i_fourcc;
668 AVI_GetKeyFlag(p_sys->track[avi_pk.i_stream]->i_codec,
670 index.i_pos = avi_pk.i_pos;
671 index.i_length = avi_pk.i_size;
672 AVI_IndexAddEntry( p_sys, avi_pk.i_stream, &index );
674 i_track = avi_pk.i_stream;
675 tk = p_sys->track[i_track];
676 /* do we will read this data ? */
677 if( AVI_GetDPTS( tk, toread[i_track].i_toread ) > -25*1000 )
683 if( AVI_PacketNext( p_input ) )
686 "cannot skip packet, track disabled" );
687 return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );
696 stream_Seek( p_input->s, i_pos );
699 /* Set the track to use */
700 tk = p_sys->track[i_track];
702 /* read thoses data */
703 if( tk->i_samplesize )
705 unsigned int i_toread;
707 if( ( i_toread = toread[i_track].i_toread ) <= 0 )
709 if( tk->i_samplesize > 1 )
711 i_toread = tk->i_samplesize;
715 i_toread = __MAX( AVI_PTSToByte( tk, 20 * 1000 ), 100 );
718 i_size = __MIN( tk->p_index[tk->i_idxposc].i_length -
724 i_size = tk->p_index[tk->i_idxposc].i_length;
727 if( tk->i_idxposb == 0 )
729 i_size += 8; /* need to read and skip header */
732 if( ( p_frame = stream_Block( p_input->s, __EVEN( i_size ) ) )==NULL )
734 msg_Warn( p_input, "failled reading data" );
735 tk->b_activated = VLC_FALSE;
736 toread[i_track].b_ok = VLC_FALSE;
739 if( i_size % 2 ) /* read was padded on word boundary */
744 if( tk->i_idxposb == 0 )
746 p_frame->p_buffer += 8;
747 p_frame->i_buffer -= 8;
749 p_frame->i_pts = AVI_GetPTS( tk );
752 if( tk->i_samplesize )
754 if( tk->i_idxposb == 0 )
758 toread[i_track].i_toread -= i_size;
759 tk->i_idxposb += i_size;
761 tk->p_index[tk->i_idxposc].i_length )
769 int i_length = tk->p_index[tk->i_idxposc].i_length;
772 if( tk->i_cat == AUDIO_ES )
774 tk->i_blockno += tk->i_blocksize > 0 ? ( i_length + tk->i_blocksize - 1 ) / tk->i_blocksize : 1;
776 toread[i_track].i_toread--;
779 if( tk->i_idxposc < tk->i_idxnb)
781 toread[i_track].i_posf =
782 tk->p_index[tk->i_idxposc].i_pos;
783 if( tk->i_idxposb > 0 )
785 toread[i_track].i_posf += 8 + tk->i_idxposb;
791 toread[i_track].i_posf = -1;
794 b_stream = VLC_TRUE; /* at least one read succeed */
797 input_ClockGetTS( p_input,
798 p_input->stream.p_selected_program,
799 p_frame->i_pts * 9/100);
801 if( tk->i_cat != VIDEO_ES )
802 p_frame->i_dts = p_frame->i_pts;
805 p_frame->i_dts = p_frame->i_pts;
809 //p_pes->i_rate = p_input->stream.control.i_rate;
810 es_out_Send( p_input->p_es_out, tk->p_es, p_frame );
815 /*****************************************************************************
816 * Demux_UnSeekable: reads and demuxes data packets for unseekable file
817 *****************************************************************************
818 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
819 *****************************************************************************/
820 static int Demux_UnSeekable( input_thread_t *p_input )
822 demux_sys_t *p_sys = p_input->p_demux_data;
823 avi_track_t *p_stream_master = NULL;
825 unsigned int i_stream;
826 unsigned int i_packet;
828 /* Check if we need to send the audio data to decoder */
829 b_audio = !p_input->stream.control.b_mute;
831 input_ClockManageRef( p_input,
832 p_input->stream.p_selected_program,
835 /* *** find master stream for data packet skipping algo *** */
836 /* *** -> first video, if any, or first audio ES *** */
837 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
839 avi_track_t *tk = p_sys->track[i_stream];
842 es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
844 if( b && tk->i_cat == VIDEO_ES )
846 p_stream_master = tk;
850 p_stream_master = tk;
854 if( !p_stream_master )
856 msg_Warn( p_input, "no more stream selected" );
860 p_sys->i_pcr = AVI_GetPTS( p_stream_master ) * 9 / 100;
862 for( i_packet = 0; i_packet < 10; i_packet++)
864 #define p_stream p_sys->track[avi_pk.i_stream]
868 if( AVI_PacketGetHeader( p_input, &avi_pk ) )
873 if( avi_pk.i_stream >= p_sys->i_track ||
874 ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
876 /* we haven't found an audio or video packet:
877 * - we have seek, found first next packet
878 * - others packets could be found, skip them
880 switch( avi_pk.i_fourcc )
885 return( !AVI_PacketNext( p_input ) ? 1 : 0 );
889 return( !AVI_PacketNext( p_input ) ? 1 : 0 );
891 return( 0 ); /* eof */
894 "seems to have lost position, resync" );
895 if( AVI_PacketSearch( p_input ) )
897 msg_Err( p_input, "resync failed" );
904 /* do will send this packet to decoder ? */
905 if( !b_audio && avi_pk.i_cat == AUDIO_ES )
907 if( AVI_PacketNext( p_input ) )
914 /* it's a selected stream, check for time */
915 if( __ABS( AVI_GetPTS( p_stream ) -
916 AVI_GetPTS( p_stream_master ) )< 600*1000 )
918 /* load it and send to decoder */
920 if( AVI_PacketRead( p_input, &avi_pk, &p_frame ) || p_frame == NULL )
925 input_ClockGetTS( p_input,
926 p_input->stream.p_selected_program,
927 AVI_GetPTS( p_stream ) * 9/100);
929 if( avi_pk.i_cat != VIDEO_ES )
930 p_frame->i_dts = p_frame->i_pts;
933 p_frame->i_dts = p_frame->i_pts;
937 //p_pes->i_rate = p_input->stream.control.i_rate;
938 es_out_Send( p_input->p_es_out, p_stream->p_es, p_frame );
942 if( AVI_PacketNext( p_input ) )
949 /* *** update stream time position *** */
950 if( p_stream->i_samplesize )
952 p_stream->i_idxposb += avi_pk.i_size;
956 if( p_stream->i_cat == AUDIO_ES )
958 p_stream->i_blockno += p_stream->i_blocksize > 0 ? ( avi_pk.i_size + p_stream->i_blocksize - 1 ) / p_stream->i_blocksize : 1;
960 p_stream->i_idxposc++;
970 /*****************************************************************************
971 * Seek: goto to i_date or i_percent
972 *****************************************************************************
973 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
974 *****************************************************************************/
975 static int Seek( input_thread_t *p_input, mtime_t i_date, int i_percent )
978 demux_sys_t *p_sys = p_input->p_demux_data;
979 unsigned int i_stream;
981 "seek requested: "I64Fd" secondes %d%%",
985 if( p_sys->b_seekable )
987 if( !p_sys->i_length )
989 avi_track_t *p_stream;
992 /* use i_percent to create a true i_date */
994 "mmh, seeking without index at %d%%"
995 " work only for interleaved file", i_percent );
996 if( i_percent >= 100 )
998 msg_Warn( p_input, "cannot seek so far !" );
1001 i_percent = __MAX( i_percent, 0 );
1003 /* try to find chunk that is at i_percent or the file */
1004 i_pos = __MAX( i_percent *
1005 stream_Size( p_input->s ) / 100,
1006 p_sys->i_movi_begin );
1007 /* search first selected stream */
1008 for( i_stream = 0, p_stream = NULL;
1009 i_stream < p_sys->i_track; i_stream++ )
1011 p_stream = p_sys->track[i_stream];
1012 if( p_stream->b_activated )
1017 if( !p_stream || !p_stream->b_activated )
1019 msg_Warn( p_input, "cannot find any selected stream" );
1023 /* be sure that the index exist */
1024 if( AVI_StreamChunkSet( p_input,
1028 msg_Warn( p_input, "cannot seek" );
1032 while( i_pos >= p_stream->p_index[p_stream->i_idxposc].i_pos +
1033 p_stream->p_index[p_stream->i_idxposc].i_length + 8 )
1035 /* search after i_idxposc */
1036 if( AVI_StreamChunkSet( p_input,
1037 i_stream, p_stream->i_idxposc + 1 ) )
1039 msg_Warn( p_input, "cannot seek" );
1043 i_date = AVI_GetPTS( p_stream );
1044 /* TODO better support for i_samplesize != 0 */
1045 msg_Dbg( p_input, "estimate date "I64Fd, i_date );
1048 #define p_stream p_sys->track[i_stream]
1050 /* seek for chunk based streams */
1051 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
1053 if( p_stream->b_activated && !p_stream->i_samplesize )
1054 /* if( p_stream->b_activated ) */
1056 AVI_TrackSeek( p_input, i_stream, i_date );
1057 p_sys->i_time = __MAX( AVI_GetPTS( p_stream ),
1064 i_date = p_sys->i_time;
1066 /* seek for bytes based streams */
1067 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
1069 if( p_stream->b_activated && p_stream->i_samplesize )
1071 AVI_TrackSeek( p_input, i_stream, i_date );
1072 /* p_sys->i_time = __MAX( AVI_GetPTS( p_stream ), p_sys->i_time );*/
1075 msg_Dbg( p_input, "seek: "I64Fd" secondes", p_sys->i_time /1000000 );
1076 /* set true movie time */
1078 if( !p_sys->i_time )
1080 p_sys->i_time = i_date;
1087 msg_Err( p_input, "shouldn't yet be executed" );
1092 /*****************************************************************************
1094 *****************************************************************************
1096 *****************************************************************************/
1097 static double ControlGetPosition( input_thread_t *p_input )
1099 demux_sys_t *p_sys = p_input->p_demux_data;
1101 if( p_sys->i_length > 0 )
1103 return (double)p_sys->i_time / (double)( p_sys->i_length * (mtime_t)1000000 );
1105 else if( stream_Size( p_input->s ) > 0 )
1111 /* search the more advanced selected es */
1112 for( i = 0; i < p_sys->i_track; i++ )
1114 avi_track_t *tk = p_sys->track[i];
1115 if( tk->b_activated && tk->i_idxposc < tk->i_idxnb )
1117 i_tmp = tk->p_index[tk->i_idxposc].i_pos +
1118 tk->p_index[tk->i_idxposc].i_length + 8;
1125 return (double)i64 / (double)stream_Size( p_input->s );
1130 static int Control( input_thread_t *p_input, int i_query, va_list args )
1132 demux_sys_t *p_sys = p_input->p_demux_data;
1139 case DEMUX_GET_POSITION:
1140 pf = (double*)va_arg( args, double * );
1141 *pf = ControlGetPosition( p_input );
1143 case DEMUX_SET_POSITION:
1144 if( p_sys->b_seekable )
1146 f = (double)va_arg( args, double );
1147 i64 = (mtime_t)(1000000.0 * p_sys->i_length * f );
1148 return Seek( p_input, i64, (int)(f * 100) ) < 0 ? VLC_EGENERIC : VLC_SUCCESS;
1150 return demux_vaControlDefault( p_input, i_query, args );
1152 case DEMUX_GET_TIME:
1153 pi64 = (int64_t*)va_arg( args, int64_t * );
1154 *pi64 = p_sys->i_time;
1157 case DEMUX_SET_TIME:
1161 i64 = (int64_t)va_arg( args, int64_t );
1162 if( p_sys->i_length > 0 )
1164 i_percent = 100 * i64 / (p_sys->i_length*1000000);
1166 else if( p_sys->i_time > 0 )
1168 i_percent = (int)( 100.0 * ControlGetPosition( p_input ) *
1169 (double)i64 / (double)p_sys->i_time );
1171 return Seek( p_input, i64, i_percent );
1173 case DEMUX_GET_LENGTH:
1174 pi64 = (int64_t*)va_arg( args, int64_t * );
1175 *pi64 = p_sys->i_length * (mtime_t)1000000;
1179 pf = (double*)va_arg( args, double * );
1181 for( i = 0; i < (int)p_sys->i_track; i++ )
1183 avi_track_t *tk = p_sys->track[i];
1184 if( tk->i_cat == VIDEO_ES && tk->i_scale > 0)
1186 *pf = (float)tk->i_rate / (float)tk->i_scale;
1193 return demux_vaControlDefault( p_input, i_query, args );
1195 return VLC_EGENERIC;
1198 /*****************************************************************************
1199 * Function to convert pts to chunk or byte
1200 *****************************************************************************/
1202 static mtime_t AVI_PTSToChunk( avi_track_t *tk, mtime_t i_pts )
1204 return (mtime_t)((int64_t)i_pts *
1205 (int64_t)tk->i_rate /
1206 (int64_t)tk->i_scale /
1209 static mtime_t AVI_PTSToByte( avi_track_t *tk, mtime_t i_pts )
1211 return (mtime_t)((int64_t)i_pts *
1212 (int64_t)tk->i_rate /
1213 (int64_t)tk->i_scale /
1215 (int64_t)tk->i_samplesize );
1218 static mtime_t AVI_GetDPTS( avi_track_t *tk, int64_t i_count )
1222 i_dpts = (mtime_t)( (int64_t)1000000 *
1224 (int64_t)tk->i_scale /
1225 (int64_t)tk->i_rate );
1227 if( tk->i_samplesize )
1229 return i_dpts / tk->i_samplesize;
1234 static mtime_t AVI_GetPTS( avi_track_t *tk )
1236 if( tk->i_samplesize )
1238 int64_t i_count = 0;
1240 /* we need a valid entry we will emulate one */
1241 if( tk->i_idxposc == tk->i_idxnb )
1245 /* use the last entry */
1246 i_count = tk->p_index[tk->i_idxnb - 1].i_lengthtotal
1247 + tk->p_index[tk->i_idxnb - 1].i_length;
1252 i_count = tk->p_index[tk->i_idxposc].i_lengthtotal;
1254 return AVI_GetDPTS( tk, i_count + tk->i_idxposb );
1258 if( tk->i_cat == AUDIO_ES )
1260 return AVI_GetDPTS( tk, tk->i_blockno );
1264 return AVI_GetDPTS( tk, tk->i_idxposc );
1269 static int AVI_StreamChunkFind( input_thread_t *p_input,
1270 unsigned int i_stream )
1272 demux_sys_t *p_sys = p_input->p_demux_data;
1273 avi_packet_t avi_pk;
1275 /* find first chunk of i_stream that isn't in index */
1277 if( p_sys->i_movi_lastchunk_pos >= p_sys->i_movi_begin + 12 )
1279 stream_Seek( p_input->s, p_sys->i_movi_lastchunk_pos );
1280 if( AVI_PacketNext( p_input ) )
1282 return VLC_EGENERIC;
1287 stream_Seek( p_input->s, p_sys->i_movi_begin + 12 );
1292 if( p_input->b_die )
1294 return VLC_EGENERIC;
1297 if( AVI_PacketGetHeader( p_input, &avi_pk ) )
1299 msg_Warn( p_input, "cannot get packet header" );
1300 return VLC_EGENERIC;
1302 if( avi_pk.i_stream >= p_sys->i_track ||
1303 ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1305 if( AVI_PacketNext( p_input ) )
1307 return VLC_EGENERIC;
1312 /* add this chunk to the index */
1313 AVIIndexEntry_t index;
1315 index.i_id = avi_pk.i_fourcc;
1317 AVI_GetKeyFlag(p_sys->track[avi_pk.i_stream]->i_codec,
1319 index.i_pos = avi_pk.i_pos;
1320 index.i_length = avi_pk.i_size;
1321 AVI_IndexAddEntry( p_sys, avi_pk.i_stream, &index );
1323 if( avi_pk.i_stream == i_stream )
1328 if( AVI_PacketNext( p_input ) )
1330 return VLC_EGENERIC;
1337 /* be sure that i_ck will be a valid index entry */
1338 static int AVI_StreamChunkSet( input_thread_t *p_input,
1339 unsigned int i_stream,
1342 demux_sys_t *p_sys = p_input->p_demux_data;
1343 avi_track_t *p_stream = p_sys->track[i_stream];
1345 p_stream->i_idxposc = i_ck;
1346 p_stream->i_idxposb = 0;
1348 if( i_ck >= p_stream->i_idxnb )
1350 p_stream->i_idxposc = p_stream->i_idxnb - 1;
1353 p_stream->i_idxposc++;
1354 if( AVI_StreamChunkFind( p_input, i_stream ) )
1356 return VLC_EGENERIC;
1359 } while( p_stream->i_idxposc < i_ck );
1366 /* XXX FIXME up to now, we assume that all chunk are one after one */
1367 static int AVI_StreamBytesSet( input_thread_t *p_input,
1368 unsigned int i_stream,
1371 demux_sys_t *p_sys = p_input->p_demux_data;
1372 avi_track_t *p_stream = p_sys->track[i_stream];
1374 if( ( p_stream->i_idxnb > 0 )
1375 &&( i_byte < p_stream->p_index[p_stream->i_idxnb - 1].i_lengthtotal +
1376 p_stream->p_index[p_stream->i_idxnb - 1].i_length ) )
1378 /* index is valid to find the ck */
1379 /* uses dichototmie to be fast enougth */
1380 int i_idxposc = __MIN( p_stream->i_idxposc, p_stream->i_idxnb - 1 );
1381 int i_idxmax = p_stream->i_idxnb;
1385 if( p_stream->p_index[i_idxposc].i_lengthtotal > i_byte )
1387 i_idxmax = i_idxposc ;
1388 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1392 if( p_stream->p_index[i_idxposc].i_lengthtotal +
1393 p_stream->p_index[i_idxposc].i_length <= i_byte)
1395 i_idxmin = i_idxposc ;
1396 i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1400 p_stream->i_idxposc = i_idxposc;
1401 p_stream->i_idxposb = i_byte -
1402 p_stream->p_index[i_idxposc].i_lengthtotal;
1411 p_stream->i_idxposc = p_stream->i_idxnb - 1;
1412 p_stream->i_idxposb = 0;
1415 p_stream->i_idxposc++;
1416 if( AVI_StreamChunkFind( p_input, i_stream ) )
1418 return VLC_EGENERIC;
1421 } while( p_stream->p_index[p_stream->i_idxposc].i_lengthtotal +
1422 p_stream->p_index[p_stream->i_idxposc].i_length <= i_byte );
1424 p_stream->i_idxposb = i_byte -
1425 p_stream->p_index[p_stream->i_idxposc].i_lengthtotal;
1430 static int AVI_TrackSeek( input_thread_t *p_input,
1434 demux_sys_t *p_sys = p_input->p_demux_data;
1435 avi_track_t *tk = p_sys->track[i_stream];
1437 #define p_stream p_sys->track[i_stream]
1440 i_oldpts = AVI_GetPTS( p_stream );
1442 if( !p_stream->i_samplesize )
1444 if( AVI_StreamChunkSet( p_input,
1446 AVI_PTSToChunk( p_stream, i_date ) ) )
1448 return VLC_EGENERIC;
1451 if( p_stream->i_cat == AUDIO_ES )
1455 for( i = 0; i < tk->i_idxposc; i++ )
1457 if( tk->i_blocksize > 0 )
1459 tk->i_blockno += ( tk->p_index[i].i_length + tk->i_blocksize - 1 ) / tk->i_blocksize;
1469 "old:"I64Fd" %s new "I64Fd,
1471 i_oldpts > i_date ? ">" : "<",
1474 if( p_stream->i_cat == VIDEO_ES )
1476 /* search key frame */
1477 if( i_date < i_oldpts )
1479 while( p_stream->i_idxposc > 0 &&
1480 !( p_stream->p_index[p_stream->i_idxposc].i_flags &
1483 if( AVI_StreamChunkSet( p_input,
1485 p_stream->i_idxposc - 1 ) )
1487 return VLC_EGENERIC;
1493 while( p_stream->i_idxposc < p_stream->i_idxnb &&
1494 !( p_stream->p_index[p_stream->i_idxposc].i_flags &
1497 if( AVI_StreamChunkSet( p_input,
1499 p_stream->i_idxposc + 1 ) )
1501 return VLC_EGENERIC;
1509 if( AVI_StreamBytesSet( p_input,
1511 AVI_PTSToByte( p_stream, i_date ) ) )
1513 return VLC_EGENERIC;
1520 /****************************************************************************
1521 * Return VLC_TRUE if it's a key frame
1522 ****************************************************************************/
1523 static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, uint8_t *p_byte )
1529 * startcode: 0x00000100 32bits
1530 * framenumber ? 5bits
1531 * piture type 0(I),1(P) 2bits
1533 if( GetDWBE( p_byte ) != 0x00000100 )
1535 /* it's not an msmpegv1 stream, strange...*/
1536 return AVIIF_KEYFRAME;
1540 return p_byte[4] & 0x06 ? 0 : AVIIF_KEYFRAME;
1543 case FOURCC_DIV3: /* wmv1 also */
1545 * picture type 0(I),1(P) 2bits
1547 return p_byte[0] & 0xC0 ? 0 : AVIIF_KEYFRAME;
1549 /* we should find first occurence of 0x000001b6 (32bits)
1550 * startcode: 0x000001b6 32bits
1551 * piture type 0(I),1(P) 2bits
1553 if( GetDWBE( p_byte ) != 0x000001b6 )
1555 /* not true , need to find the first VOP header */
1556 return AVIIF_KEYFRAME;
1560 return p_byte[4] & 0xC0 ? 0 : AVIIF_KEYFRAME;
1563 /* I can't do it, so say yes */
1564 return AVIIF_KEYFRAME;
1568 vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t i_codec )
1573 wf_tag_to_fourcc( i_codec, &i_codec, NULL );
1577 /* XXX DIV1 <- msmpeg4v1, DIV2 <- msmpeg4v2, DIV3 <- msmpeg4v3, mp4v for mpeg4 */
1628 return VLC_FOURCC( 'u', 'n', 'd', 'f' );
1632 /****************************************************************************
1634 ****************************************************************************/
1635 static void AVI_ParseStreamHeader( vlc_fourcc_t i_id,
1636 int *pi_number, int *pi_type )
1638 #define SET_PTR( p, v ) if( p ) *(p) = (v);
1641 c1 = ((uint8_t *)&i_id)[0];
1642 c2 = ((uint8_t *)&i_id)[1];
1644 if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
1646 SET_PTR( pi_number, 100 ); /* > max stream number */
1647 SET_PTR( pi_type, UNKNOWN_ES );
1651 SET_PTR( pi_number, (c1 - '0') * 10 + (c2 - '0' ) );
1652 switch( VLC_TWOCC( ((uint8_t *)&i_id)[2], ((uint8_t *)&i_id)[3] ) )
1655 SET_PTR( pi_type, AUDIO_ES );
1659 SET_PTR( pi_type, VIDEO_ES );
1662 SET_PTR( pi_type, UNKNOWN_ES );
1669 /****************************************************************************
1671 ****************************************************************************/
1672 static int AVI_PacketGetHeader( input_thread_t *p_input, avi_packet_t *p_pk )
1676 if( stream_Peek( p_input->s, &p_peek, 16 ) < 16 )
1678 return VLC_EGENERIC;
1680 p_pk->i_fourcc = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] );
1681 p_pk->i_size = GetDWLE( p_peek + 4 );
1682 p_pk->i_pos = stream_Tell( p_input->s );
1683 if( p_pk->i_fourcc == AVIFOURCC_LIST || p_pk->i_fourcc == AVIFOURCC_RIFF )
1685 p_pk->i_type = VLC_FOURCC( p_peek[8], p_peek[9],
1686 p_peek[10], p_peek[11] );
1693 memcpy( p_pk->i_peek, p_peek + 8, 8 );
1695 AVI_ParseStreamHeader( p_pk->i_fourcc, &p_pk->i_stream, &p_pk->i_cat );
1699 static int AVI_PacketNext( input_thread_t *p_input )
1701 avi_packet_t avi_ck;
1704 if( AVI_PacketGetHeader( p_input, &avi_ck ) )
1706 return VLC_EGENERIC;
1709 if( avi_ck.i_fourcc == AVIFOURCC_LIST &&
1710 ( avi_ck.i_type == AVIFOURCC_rec || avi_ck.i_type == AVIFOURCC_movi ) )
1714 else if( avi_ck.i_fourcc == AVIFOURCC_RIFF &&
1715 avi_ck.i_type == AVIFOURCC_AVIX )
1721 i_skip = __EVEN( avi_ck.i_size ) + 8;
1724 if( stream_Read( p_input->s, NULL, i_skip ) != i_skip )
1726 return VLC_EGENERIC;
1730 static int AVI_PacketRead( input_thread_t *p_input,
1732 block_t **pp_frame )
1736 i_size = __EVEN( p_pk->i_size + 8 );
1738 if( ( *pp_frame = stream_Block( p_input->s, i_size ) ) == NULL )
1740 return VLC_EGENERIC;
1742 (*pp_frame)->p_buffer += 8;
1743 (*pp_frame)->i_buffer -= 8;
1745 if( i_size != p_pk->i_size + 8 )
1747 (*pp_frame)->i_buffer--;
1753 static int AVI_PacketSearch( input_thread_t *p_input )
1755 demux_sys_t *p_sys = p_input->p_demux_data;
1756 avi_packet_t avi_pk;
1761 if( stream_Read( p_input->s, NULL, 1 ) != 1 )
1763 return VLC_EGENERIC;
1765 AVI_PacketGetHeader( p_input, &avi_pk );
1766 if( avi_pk.i_stream < p_sys->i_track &&
1767 ( avi_pk.i_cat == AUDIO_ES || avi_pk.i_cat == VIDEO_ES ) )
1771 switch( avi_pk.i_fourcc )
1773 case AVIFOURCC_JUNK:
1774 case AVIFOURCC_LIST:
1775 case AVIFOURCC_RIFF:
1776 case AVIFOURCC_idx1:
1780 /* Prevents from eating all the CPU with broken files.
1781 * This value should be low enough so that it doesn't affect the
1782 * reading speed too much (not that we care much anyway because
1783 * this code is called only on broken files). */
1784 if( !(++i_count % 1024) )
1786 if( p_input->b_die ) return VLC_EGENERIC;
1789 if( !(i_count % (1024 * 10)) )
1790 msg_Warn( p_input, "trying to resync..." );
1795 /****************************************************************************
1797 ****************************************************************************/
1798 static void AVI_IndexAddEntry( demux_sys_t *p_sys,
1800 AVIIndexEntry_t *p_index)
1802 avi_track_t *tk = p_sys->track[i_stream];
1804 /* Update i_movi_lastchunk_pos */
1805 if( p_sys->i_movi_lastchunk_pos < p_index->i_pos )
1807 p_sys->i_movi_lastchunk_pos = p_index->i_pos;
1811 if( tk->i_idxnb >= tk->i_idxmax )
1813 tk->i_idxmax += 16384;
1814 tk->p_index = realloc( tk->p_index,
1815 tk->i_idxmax * sizeof( AVIIndexEntry_t ) );
1816 if( tk->p_index == NULL )
1821 /* calculate cumulate length */
1822 if( tk->i_idxnb > 0 )
1824 p_index->i_lengthtotal =
1825 tk->p_index[tk->i_idxnb - 1].i_length +
1826 tk->p_index[tk->i_idxnb - 1].i_lengthtotal;
1830 p_index->i_lengthtotal = 0;
1833 tk->p_index[tk->i_idxnb++] = *p_index;
1836 static int AVI_IndexLoad_idx1( input_thread_t *p_input )
1838 demux_sys_t *p_sys = p_input->p_demux_data;
1840 avi_chunk_list_t *p_riff;
1841 avi_chunk_list_t *p_movi;
1842 avi_chunk_idx1_t *p_idx1;
1844 unsigned int i_stream;
1845 unsigned int i_index;
1849 p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
1850 p_idx1 = AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0);
1851 p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
1855 msg_Warn( p_input, "cannot find idx1 chunk, no index defined" );
1856 return VLC_EGENERIC;
1859 /* *** calculate offset *** */
1860 /* Well, avi is __SHIT__ so test more than one entry
1861 * (needed for some avi files) */
1863 for( i = 0; i < __MIN( p_idx1->i_entry_count, 10 ); i++ )
1865 if( p_idx1->entry[i].i_pos < p_movi->i_chunk_pos )
1867 i_offset = p_movi->i_chunk_pos + 8;
1872 for( i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )
1876 AVI_ParseStreamHeader( p_idx1->entry[i_index].i_fourcc,
1879 if( i_stream < p_sys->i_track &&
1880 i_cat == p_sys->track[i_stream]->i_cat )
1882 AVIIndexEntry_t index;
1883 index.i_id = p_idx1->entry[i_index].i_fourcc;
1885 p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME);
1886 index.i_pos = p_idx1->entry[i_index].i_pos + i_offset;
1887 index.i_length = p_idx1->entry[i_index].i_length;
1888 AVI_IndexAddEntry( p_sys, i_stream, &index );
1894 static void __Parse_indx( input_thread_t *p_input,
1896 avi_chunk_indx_t *p_indx )
1898 demux_sys_t *p_sys = p_input->p_demux_data;
1899 AVIIndexEntry_t index;
1902 msg_Dbg( p_input, "loading subindex(0x%x) %d entries", p_indx->i_indextype, p_indx->i_entriesinuse );
1903 if( p_indx->i_indexsubtype == 0 )
1905 for( i = 0; i < p_indx->i_entriesinuse; i++ )
1907 index.i_id = p_indx->i_id;
1908 index.i_flags = p_indx->idx.std[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
1909 index.i_pos = p_indx->i_baseoffset + p_indx->idx.std[i].i_offset - 8;
1910 index.i_length = p_indx->idx.std[i].i_size&0x7fffffff;
1912 AVI_IndexAddEntry( p_sys, i_stream, &index );
1915 else if( p_indx->i_indexsubtype == AVI_INDEX_2FIELD )
1917 for( i = 0; i < p_indx->i_entriesinuse; i++ )
1919 index.i_id = p_indx->i_id;
1920 index.i_flags = p_indx->idx.field[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
1921 index.i_pos = p_indx->i_baseoffset + p_indx->idx.field[i].i_offset - 8;
1922 index.i_length = p_indx->idx.field[i].i_size;
1924 AVI_IndexAddEntry( p_sys, i_stream, &index );
1929 msg_Warn( p_input, "unknow subtype index(0x%x)", p_indx->i_indexsubtype );
1933 static void AVI_IndexLoad_indx( input_thread_t *p_input )
1935 demux_sys_t *p_sys = p_input->p_demux_data;
1936 unsigned int i_stream;
1939 avi_chunk_list_t *p_riff;
1940 avi_chunk_list_t *p_hdrl;
1942 p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
1943 p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
1945 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
1947 avi_chunk_list_t *p_strl;
1948 avi_chunk_indx_t *p_indx;
1950 #define p_stream p_sys->track[i_stream]
1951 p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream );
1952 p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0 );
1956 msg_Warn( p_input, "cannot find indx (misdetect/broken OpenDML file?)" );
1960 if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS )
1962 __Parse_indx( p_input, i_stream, p_indx );
1964 else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )
1966 avi_chunk_indx_t ck_sub;
1967 for( i = 0; i < p_indx->i_entriesinuse; i++ )
1969 if( stream_Seek( p_input->s, p_indx->idx.super[i].i_offset )||
1970 AVI_ChunkRead( p_input->s, &ck_sub, NULL ) )
1974 __Parse_indx( p_input, i_stream, &ck_sub );
1979 msg_Warn( p_input, "unknow type index(0x%x)", p_indx->i_indextype );
1985 static void AVI_IndexLoad( input_thread_t *p_input )
1987 demux_sys_t *p_sys = p_input->p_demux_data;
1988 unsigned int i_stream;
1990 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
1992 p_sys->track[i_stream]->i_idxnb = 0;
1993 p_sys->track[i_stream]->i_idxmax = 0;
1994 p_sys->track[i_stream]->p_index = NULL;
1999 AVI_IndexLoad_indx( p_input );
2001 else if( AVI_IndexLoad_idx1( p_input ) )
2003 /* try indx if idx1 failed as some "normal" file have indx too */
2004 AVI_IndexLoad_indx( p_input );
2007 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
2009 msg_Dbg( p_input, "stream[%d] created %d index entries",
2010 i_stream, p_sys->track[i_stream]->i_idxnb );
2014 static void AVI_IndexCreate( input_thread_t *p_input )
2016 demux_sys_t *p_sys = p_input->p_demux_data;
2018 avi_chunk_list_t *p_riff;
2019 avi_chunk_list_t *p_movi;
2021 unsigned int i_stream;
2024 p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
2025 p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
2029 msg_Err( p_input, "cannot find p_movi" );
2033 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
2035 p_sys->track[i_stream]->i_idxnb = 0;
2036 p_sys->track[i_stream]->i_idxmax = 0;
2037 p_sys->track[i_stream]->p_index = NULL;
2039 i_movi_end = __MIN( (off_t)(p_movi->i_chunk_pos + p_movi->i_chunk_size),
2040 stream_Size( p_input->s ) );
2042 stream_Seek( p_input->s, p_movi->i_chunk_pos + 12 );
2043 msg_Warn( p_input, "creating index from LIST-movi, will take time !" );
2048 if( p_input->b_die )
2053 if( AVI_PacketGetHeader( p_input, &pk ) )
2057 if( pk.i_stream < p_sys->i_track &&
2058 pk.i_cat == p_sys->track[pk.i_stream]->i_cat )
2060 AVIIndexEntry_t index;
2061 index.i_id = pk.i_fourcc;
2063 AVI_GetKeyFlag(p_sys->track[pk.i_stream]->i_codec, pk.i_peek);
2064 index.i_pos = pk.i_pos;
2065 index.i_length = pk.i_size;
2066 AVI_IndexAddEntry( p_sys, pk.i_stream, &index );
2070 switch( pk.i_fourcc )
2072 case AVIFOURCC_idx1:
2075 avi_chunk_list_t *p_sysx;
2076 p_sysx = AVI_ChunkFind( &p_sys->ck_root,
2077 AVIFOURCC_RIFF, 1 );
2079 msg_Dbg( p_input, "looking for new RIFF chunk" );
2080 if( stream_Seek( p_input->s, p_sysx->i_chunk_pos + 24))
2087 case AVIFOURCC_RIFF:
2088 msg_Dbg( p_input, "new RIFF chunk found" );
2090 case AVIFOURCC_JUNK:
2093 msg_Warn( p_input, "need resync, probably broken avi" );
2094 if( AVI_PacketSearch( p_input ) )
2096 msg_Warn( p_input, "lost sync, abord index creation" );
2102 if( ( !p_sys->b_odml && pk.i_pos + pk.i_size >= i_movi_end ) ||
2103 AVI_PacketNext( p_input ) )
2110 for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
2113 "stream[%d] creating %d index entries",
2115 p_sys->track[i_stream]->i_idxnb );
2119 /*****************************************************************************
2121 *****************************************************************************/
2122 static int AVI_TrackStopFinishedStreams( input_thread_t *p_input )
2124 demux_sys_t *p_sys = p_input->p_demux_data;
2126 int b_end = VLC_TRUE;
2128 for( i = 0; i < p_sys->i_track; i++ )
2130 avi_track_t *tk = p_sys->track[i];
2131 if( tk->i_idxposc >= tk->i_idxnb )
2133 tk->b_activated = VLC_FALSE;
2134 es_out_Control( p_input->p_es_out, ES_OUT_SET_ES_STATE, tk->p_es, VLC_FALSE );
2144 /****************************************************************************
2145 * AVI_MovieGetLength give max streams length in second
2146 ****************************************************************************/
2147 static mtime_t AVI_MovieGetLength( input_thread_t *p_input )
2149 demux_sys_t *p_sys = p_input->p_demux_data;
2150 mtime_t i_maxlength = 0;
2153 for( i = 0; i < p_sys->i_track; i++ )
2155 avi_track_t *tk = p_sys->track[i];
2158 /* fix length for each stream */
2159 if( tk->i_idxnb < 1 || !tk->p_index )
2164 if( tk->i_samplesize )
2166 i_length = AVI_GetDPTS( tk,
2167 tk->p_index[tk->i_idxnb-1].i_lengthtotal +
2168 tk->p_index[tk->i_idxnb-1].i_length );
2172 i_length = AVI_GetDPTS( tk, tk->i_idxnb );
2174 i_length /= (mtime_t)1000000; /* in seconds */
2177 "stream[%d] length:"I64Fd" (based on index)",
2180 i_maxlength = __MAX( i_maxlength, i_length );