* avi.c : AVI file Stream input module for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
- * $Id: avi.c,v 1.22 2003/01/11 18:10:49 fenrir Exp $
+ * $Id: avi.c,v 1.36 2003/02/27 13:19:43 gbazin Exp $
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
static int AVIDemux_UnSeekable( input_thread_t *p_input );
#define AVIEnd(a) __AVIEnd(VLC_OBJECT(a))
-
+#define FREE( p ) if( p ) { free( p ); (p) = NULL; }
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
- add_category_hint( "demuxer", NULL );
+ add_category_hint( N_("avi-demuxer"), NULL, VLC_TRUE );
add_bool( "avi-interleaved", 0, NULL,
- "force interleaved method",
- "force interleaved method" );
+ _("force interleaved method"),
+ _("force interleaved method"), VLC_TRUE );
add_bool( "avi-index", 0, NULL,
- "force index creation",
- "force index creation" );
+ _("force index creation"),
+ _("force index creation"), VLC_TRUE );
- set_description( "avi demuxer" );
+ set_description( _("avi demuxer") );
set_capability( "demux", 212 );
set_callbacks( AVIInit, __AVIEnd );
vlc_module_end();
p_pes->i_pes_size, 2048 ) );
if( i_read <= 0 )
{
- return p_pes->i_pes_size;
+ /* should occur only with EOF and max allocation reached
+ * it safer to return an error */
+ /* free pes */
+ input_DeletePES( p_input->p_method_data, p_pes );
+ return -1;
}
if( !p_pes->p_first )
static vlc_bool_t AVI_StreamStart ( input_thread_t *, demux_sys_t *, int );
static int AVI_StreamSeek ( input_thread_t *, demux_sys_t *, int, mtime_t );
static void AVI_StreamStop ( input_thread_t *, demux_sys_t *, int );
+static int AVI_StreamStopFinishedStreams( input_thread_t *, demux_sys_t * );
static vlc_bool_t AVI_StreamStart( input_thread_t *p_input,
demux_sys_t *p_avi, int i_stream )
#undef p_stream
}
+static int AVI_StreamStopFinishedStreams( input_thread_t *p_input,
+ demux_sys_t *p_avi )
+{
+ unsigned int i_stream;
+ int b_end;
+
+ for( i_stream = 0,b_end = VLC_TRUE;
+ i_stream < p_avi->i_streams; i_stream++ )
+ {
+#define p_stream p_avi->pp_info[i_stream]
+ if( p_stream->i_idxposc >= p_stream->i_idxnb )
+ {
+ AVI_StreamStop( p_input, p_avi, i_stream );
+ }
+ else
+ {
+ b_end = VLC_FALSE;
+ }
+#undef p_stream
+ }
+ return( b_end );
+}
/****************************************************************************
* AVI_MovieGetLength give max streams length in second
****************************************************************************/
{
i_length =
(mtime_t)( p_stream->p_index[p_stream->i_idxnb-1].i_lengthtotal +
- p_stream->p_index[p_stream->i_idxnb-1].i_length ) /
+ p_stream->p_index[p_stream->i_idxnb-1].i_length ) *
(mtime_t)p_stream->i_scale /
(mtime_t)p_stream->i_rate /
(mtime_t)p_stream->i_samplesize;
}
#endif
AVI_ChunkFreeRoot( p_input, &p_avi->ck_root );
+
+ FREE( p_input->p_demux_data );
}
/*****************************************************************************
p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
}
-
+
/* now read info on each stream and create ES */
p_avi->pp_info = calloc( p_avi->i_streams,
sizeof( avi_stream_t* ) );
p_info->i_rate = p_avi_strh->i_rate;
p_info->i_scale = p_avi_strh->i_scale;
p_info->i_samplesize = p_avi_strh->i_samplesize;
-
+ msg_Dbg( p_input, "stream[%d] rate:%d scale:%d samplesize:%d",
+ i,
+ p_info->i_rate, p_info->i_scale, p_info->i_samplesize );
switch( p_avi_strh->i_type )
{
case( AVIFOURCC_auds ):
#endif
break;
default:
- msg_Err( p_input, "stream[%d] unknown type", i );
+ msg_Warn( p_input, "stream[%d] unknown type", i );
p_info->i_cat = UNKNOWN_ES;
i_init_size = 0;
p_init_data = NULL;
if( AVI_PacketGetHeader( p_input, &avi_pk ) )
{
- msg_Err( p_input, "cannot get packet header" );
+ msg_Warn( p_input, "cannot get packet header" );
return VLC_EGENERIC;
}
if( avi_pk.i_stream >= p_avi->i_streams ||
if( i_percent >= 100 )
{
- msg_Err( p_input, "cannot seek so far !" );
+ msg_Warn( p_input, "cannot seek so far !" );
return( -1 );
}
i_percent = __MAX( i_percent, 0 );
}
if( !p_stream || !p_stream->b_activated )
{
- msg_Err( p_input, "cannot find any selected stream" );
+ msg_Warn( p_input, "cannot find any selected stream" );
return( -1 );
}
i_stream,
0 ) )
{
- msg_Err( p_input, "cannot seek" );
+ msg_Warn( p_input, "cannot seek" );
return( -1 );
}
if( AVI_SetStreamChunk( p_input,
i_stream, p_stream->i_idxposc + 1 ) )
{
- msg_Err( p_input, "cannot seek" );
+ msg_Warn( p_input, "cannot seek" );
return( -1 );
}
}
static int AVIDemux_Seekable( input_thread_t *p_input )
{
+ unsigned int i_stream_count;
unsigned int i_stream;
vlc_bool_t b_stream;
-
+ vlc_bool_t b_play_audio;
+ vlc_bool_t b_video; /* is there some video track selected */
// cannot be more than 100 stream (dcXX or wbXX)
avi_stream_toread_t toread[100];
demux_sys_t *p_avi = p_input->p_demux_data;
+
/* detect new selected/unselected streams */
- for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
+ for( i_stream = 0,i_stream_count= 0, b_video = VLC_FALSE;
+ i_stream < p_avi->i_streams; i_stream++ )
{
#define p_stream p_avi->pp_info[i_stream]
if( p_stream->p_es )
AVI_StreamStop( p_input, p_avi, i_stream );
}
}
+ if( p_stream->b_activated )
+ {
+ i_stream_count++;
+ if( p_stream->i_cat == VIDEO_ES )
+ {
+ b_video = VLC_TRUE;
+ }
+ }
#undef p_stream
}
+ if( i_stream_count <= 0 )
+ {
+ msg_Warn( p_input, "no track selected, exiting..." );
+ return( 0 );
+ }
+
if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
{
mtime_t i_date;
int i_percent;
/* first wait for empty buffer, arbitrary time FIXME */
-// msleep( DEFAULT_PTS_DELAY );
+ //msleep( DEFAULT_PTS_DELAY );
i_date = (mtime_t)1000000 *
(mtime_t)p_avi->i_length *
subtitle_Demux( p_avi->p_sub, p_avi->i_time );
}
#endif
+
+ /* *** send audio data to decoder if rate == DEFAULT_RATE or no video *** */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ if( p_input->stream.control.i_rate == DEFAULT_RATE || !b_video )
+ {
+ b_play_audio = VLC_TRUE;
+ }
+ else
+ {
+ b_play_audio = VLC_FALSE;
+ }
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
/* init toread */
for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
{
mtime_t i_dpts;
toread[i_stream].b_ok = p_stream->b_activated;
-
if( p_stream->i_idxposc < p_stream->i_idxnb )
{
toread[i_stream].i_posf =
if( i_pos == -1 )
{
- /* no valid index, we will parse directly the stream */
+ /* no valid index, we will parse directly the stream
+ * in case we fail we will disable all finished stream */
if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin )
{
AVI_SeekAbsolute( p_input, p_avi->i_movi_lastchunk_pos );
if( AVI_PacketNext( p_input ) )
{
- return( 0 );
+ return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
}
}
else
if( AVI_PacketGetHeader( p_input, &avi_pk ) )
{
- msg_Err( p_input, "cannot get packet header" );
- return( 0 );
+ msg_Warn( p_input,
+ "cannot get packet header, track disabled" );
+ return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
}
if( avi_pk.i_stream >= p_avi->i_streams ||
( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
default:
if( AVI_PacketNext( p_input ) )
{
- msg_Err( p_input, "cannot skip packet" );
- return( 0 );
+ msg_Warn( p_input,
+ "cannot skip packet, track disabled" );
+ return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
}
break;
}
{
if( AVI_PacketNext( p_input ) )
{
- msg_Err( p_input, "cannot skip packet" );
- return( 0 );
+ msg_Warn( p_input,
+ "cannot skip packet, track disabled" );
+ return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
}
}
}
/* read thoses data */
if( p_stream->i_samplesize )
{
+ unsigned int i_toread;
+
+ if( ( i_toread = toread[i_stream].i_toread ) <= 0 )
+ {
+ if( p_stream->i_samplesize > 1 )
+ {
+ i_toread = p_stream->i_samplesize;
+ }
+ else
+ {
+ i_toread = __MAX( AVI_PTSToByte( p_stream, 20 * 1000 ), 100 );
+ }
+ }
i_size = __MIN( p_stream->p_index[p_stream->i_idxposc].i_length -
p_stream->i_idxposb,
- __MAX( toread[i_stream].i_toread,
- p_stream->i_samplesize ) );
+ i_toread );
}
else
{
if( input_ReadInPES( p_input, &p_pes, __EVEN( i_size ) ) < 0 )
{
- msg_Err( p_input, "failled reading data" );
+ msg_Warn( p_input, "failled reading data" );
+ AVI_StreamStop( p_input, p_avi, i_stream );
toread[i_stream].b_ok = VLC_FALSE;
continue;
}
b_stream = VLC_TRUE; // at least one read succeed
- if( p_stream->p_es && p_stream->p_es->p_decoder_fifo )
+ if( p_stream->p_es && p_stream->p_es->p_decoder_fifo &&
+ ( b_play_audio || p_stream->i_cat != AUDIO_ES ) )
{
p_pes->i_dts =
p_pes->i_pts =
input_ClockGetTS( p_input,
p_input->stream.p_selected_program,
p_pes->i_pts * 9/100);
-#if 0
- /* debuuging: split pes in 2 parts */
- if( p_pes->i_nb_data >= 2 && p_stream->i_cat == AUDIO_ES )
- {
- pes_packet_t *p_pes_;
- data_packet_t *p_data;
- int i_nb_data;
- p_pes_ = PES_split( p_input, p_stream, p_pes );
- if( p_pes_->i_nb_data >= 2 )
- {
- input_DecodePES( p_stream->p_es->p_decoder_fifo, PES_split( p_input,p_stream,p_pes_ ) );
- }
- input_DecodePES( p_stream->p_es->p_decoder_fifo,p_pes_ );
-
- if( p_pes->i_nb_data >= 2 )
- {
- input_DecodePES( p_stream->p_es->p_decoder_fifo, PES_split( p_input,p_stream,p_pes ) );
- }
- //input_DecodePES( p_stream->p_es->p_decoder_fifo,p_pes );
- }
-#endif
input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
}
else
}
if( !p_stream_master )
{
- msg_Err( p_input, "no more stream selected" );
+ msg_Warn( p_input, "no more stream selected" );
return( 0 );
}