* avi.c : AVI file Stream input module for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
- * $Id: avi.c,v 1.28 2002/06/30 15:07:57 fenrir Exp $
+ * $Id: avi.c,v 1.33 2002/07/31 20:56:50 sam Exp $
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
/*****************************************************************************
* Local prototypes
*****************************************************************************/
-static void input_getfunctions( function_list_t * );
-static int AVIDemux ( input_thread_t * );
-static int AVIInit ( input_thread_t * );
-static void AVIEnd ( input_thread_t * );
+static int AVIInit ( vlc_object_t * );
+static void __AVIEnd ( vlc_object_t * );
+static int AVIDemux ( input_thread_t * );
-/*****************************************************************************
- * Build configuration tree.
- *****************************************************************************/
-MODULE_CONFIG_START
-MODULE_CONFIG_STOP
-
-MODULE_INIT_START
- SET_DESCRIPTION( "RIFF-AVI Stream input" )
- ADD_CAPABILITY( DEMUX, 150 )
-MODULE_INIT_STOP
-
-MODULE_ACTIVATE_START
- input_getfunctions( &p_module->p_functions->demux );
-MODULE_ACTIVATE_STOP
-
-MODULE_DEACTIVATE_START
-MODULE_DEACTIVATE_STOP
+#define AVIEnd(a) __AVIEnd(VLC_OBJECT(a))
/*****************************************************************************
- * Functions exported as capabilities. They are declared as static so that
- * we don't pollute the namespace too much.
+ * Module descriptor
*****************************************************************************/
-static void input_getfunctions( function_list_t * p_function_list )
-{
-#define input p_function_list->functions.demux
- input.pf_init = AVIInit;
- input.pf_end = AVIEnd;
- input.pf_demux = AVIDemux;
- input.pf_rewind = NULL;
-#undef input
-}
-
+vlc_module_begin();
+ set_description( "RIFF-AVI demuxer" );
+ set_capability( "demux", 150 );
+ set_callbacks( AVIInit, __AVIEnd );
+vlc_module_end();
/*****************************************************************************
* Some usefull functions to manipulate memory
}
}
-static int AVI_AudioGetType( u32 i_type )
+static vlc_fourcc_t AVI_AudioGetType( u32 i_type )
{
switch( i_type )
{
/* case( WAVE_FORMAT_PCM ):
- return( WAVE_AUDIO_ES ); */
+ return VLC_FOURCC('l','p','c','m'); */
case( WAVE_FORMAT_AC3 ):
- return( AC3_AUDIO_ES );
+ return VLC_FOURCC('a','5','2',' ');
case( WAVE_FORMAT_MPEG):
case( WAVE_FORMAT_MPEGLAYER3):
- return( MPEG2_AUDIO_ES ); /* 2 for mpeg-2 layer 1 2 ou 3 */
+ return VLC_FOURCC('m','p','g','a'); /* for mpeg2 layer 1 2 ou 3 */
default:
- return( 0 );
+ return 0;
}
}
-static int AVI_VideoGetType( u32 i_type )
-{
- switch( i_type )
- {
- case( FOURCC_DIV1 ): /* FIXME it is for msmpeg4v1 or old mpeg4 ?? */
- case( FOURCC_div1 ):
- case( FOURCC_MPG4 ):
- case( FOURCC_mpg4 ):
- return( MSMPEG4v1_VIDEO_ES );
-
- case( FOURCC_DIV2 ):
- case( FOURCC_div2 ):
- case( FOURCC_MP42 ):
- case( FOURCC_mp42 ):
- return( MSMPEG4v2_VIDEO_ES );
-
- case( FOURCC_MPG3 ):
- case( FOURCC_mpg3 ):
- case( FOURCC_div3 ):
- case( FOURCC_MP43 ):
- case( FOURCC_mp43 ):
- case( FOURCC_DIV3 ):
- case( FOURCC_DIV4 ):
- case( FOURCC_div4 ):
- case( FOURCC_DIV5 ):
- case( FOURCC_div5 ):
- case( FOURCC_DIV6 ):
- case( FOURCC_div6 ):
- case( FOURCC_AP41 ):
- case( FOURCC_3IV1 ):
- return( MSMPEG4v3_VIDEO_ES );
-
- case( FOURCC_DIVX ):
- case( FOURCC_divx ):
- case( FOURCC_MP4S ):
- case( FOURCC_mp4s ):
- case( FOURCC_M4S2 ):
- case( FOURCC_m4s2 ):
- case( FOURCC_xvid ):
- case( FOURCC_XVID ):
- case( FOURCC_XviD ):
- case( FOURCC_DX50 ):
- case( FOURCC_mp4v ):
- case( FOURCC_4 ):
- return( MPEG4_VIDEO_ES );
- default:
- return( 0 );
- }
-}
/* Test if it seems that it's a key frame */
-static int AVI_GetKeyFlag( int i_type, u8 *p_byte )
+static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, u8 *p_byte )
{
- switch( i_type )
+ switch( i_fourcc )
{
- case( MSMPEG4v1_VIDEO_ES ):
+ case FOURCC_DIV1:
+ case FOURCC_div1:
+ case FOURCC_MPG4:
+ case FOURCC_mpg4:
if( GetDWBE( p_byte ) != 0x00000100 )
/* startcode perhaps swapped, I haven't tested */
{
{
return( (*(p_byte+4))&0x06 ? 0 : AVIIF_KEYFRAME);
}
- case( MSMPEG4v2_VIDEO_ES ):
- case( MSMPEG4v3_VIDEO_ES ):
+ case FOURCC_DIV2:
+ case FOURCC_div2:
+ case FOURCC_MP42:
+ case FOURCC_mp42:
+ case FOURCC_MPG3:
+ case FOURCC_mpg3:
+ case FOURCC_div3:
+ case FOURCC_MP43:
+ case FOURCC_mp43:
+ case FOURCC_DIV3:
+ case FOURCC_DIV4:
+ case FOURCC_div4:
+ case FOURCC_DIV5:
+ case FOURCC_div5:
+ case FOURCC_DIV6:
+ case FOURCC_div6:
+ case FOURCC_AP41:
+ case FOURCC_3IV1:
// printf( "\n Is a Key Frame %s", (*p_byte)&0xC0 ? "no" : "yes!!" );
return( (*p_byte)&0xC0 ? 0 : AVIIF_KEYFRAME );
- case( MPEG4_VIDEO_ES ):
+ case FOURCC_DIVX:
+ case FOURCC_divx:
+ case FOURCC_MP4S:
+ case FOURCC_mp4s:
+ case FOURCC_M4S2:
+ case FOURCC_m4s2:
+ case FOURCC_xvid:
+ case FOURCC_XVID:
+ case FOURCC_XviD:
+ case FOURCC_DX50:
+ case FOURCC_mp4v:
+ case FOURCC_4:
if( GetDWBE( p_byte ) != 0x000001b6 )
{
/* not true , need to find the first VOP header
/*****************************************************************************
* AVIEnd: frees unused data
*****************************************************************************/
-static void AVIEnd( input_thread_t *p_input )
+static void __AVIEnd ( vlc_object_t * p_this )
{
+ input_thread_t * p_input = (input_thread_t *)p_this;
int i;
demux_data_avi_file_t *p_avi_demux;
p_avi_demux = (demux_data_avi_file_t*)p_input->p_demux_data ;
/*****************************************************************************
* AVIInit: check file and initializes AVI structures
*****************************************************************************/
-static int AVIInit( input_thread_t *p_input )
-{
+static int AVIInit( vlc_object_t * p_this )
+{
+ input_thread_t * p_input = (input_thread_t *)p_this;
riffchunk_t *p_riff,*p_hdrl,*p_movi;
riffchunk_t *p_avih;
riffchunk_t *p_strl,*p_strh,*p_strf;
demux_data_avi_file_t *p_avi_demux;
es_descriptor_t *p_es = NULL; /* for not warning */
-
int i;
+ p_input->pf_demux = AVIDemux;
+
if( !( p_input->p_demux_data =
p_avi_demux = malloc( sizeof(demux_data_avi_file_t) ) ) )
{
p_es->i_cat = AUDIO_ES;
AVI_Parse_WaveFormatEx( &p_info->audio_format,
p_strf->p_data->p_payload_start );
- p_es->b_audio = 1;
- p_es->i_type =
- AVI_AudioGetType( p_info->audio_format.i_formattag );
- if( !p_es->i_type )
- {
- msg_Warn( p_input, "stream(%d,0x%x) not supported", i,
- p_info->audio_format.i_formattag );
- p_es->i_cat = UNKNOWN_ES;
- }
+ p_es->i_fourcc = AVI_AudioGetType(
+ p_info->audio_format.i_formattag );
break;
case( FOURCC_vids ):
p_es->i_cat = VIDEO_ES;
AVI_Parse_BitMapInfoHeader( &p_info->video_format,
p_strf->p_data->p_payload_start );
- p_es->b_audio = 0;
- p_es->i_type =
- AVI_VideoGetType( p_info->video_format.i_compression );
- if( !p_es->i_type )
- {
- msg_Warn( p_input, "stream(%d,%4.4s) not supported", i,
- (char*)&p_info->video_format.i_compression);
- p_es->i_cat = UNKNOWN_ES;
- }
+
+ /* XXX quick hack for playing ffmpeg video, I don't know
+ who is doing something wrong */
+ p_info->header.i_samplesize = 0;
+ p_es->i_fourcc = p_info->video_format.i_compression;
break;
default:
msg_Err( p_input, "unknown stream(%d) type", i );
p_avi_demux->p_movi = p_movi;
/* get index XXX need to have p_movi */
- if( ( p_avi_demux->b_seekable )
- &&( p_avi_demux->avih.i_flags&AVIF_HASINDEX ) )
+ if( p_avi_demux->b_seekable )
{
/* get index */
__AVI_GetIndex( p_input );
__AVI_UpdateIndexOffset( p_input );
/* to make sure to go the begining unless demux will see a seek */
RIFF_GoToChunk( p_input, p_avi_demux->p_movi );
- if( RIFF_DescendChunk( p_input ) != 0 )
- {
- AVIEnd( p_input );
- msg_Err( p_input, "cannot go in (\"movi\")" );
- return( -1 );
- }
+
}
else
{
msg_Warn( p_input, "no index!" );
}
+ if( RIFF_DescendChunk( p_input ) != 0 )
+ {
+ AVIEnd( p_input );
+ msg_Err( p_input, "cannot go in (\"movi\")" );
+ return( -1 );
+ }
/* print informations on streams */
msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ",
switch( p_info->p_es->i_cat )
{
case( VIDEO_ES ):
+
msg_Dbg( p_input, "video(%4.4s) %dx%d %dbpp %ffps",
(char*)&p_info->video_format.i_compression,
p_info->video_format.i_width,
}
else
{
- i_len = 0; /* no valid zntry */
+ i_len = p_info->i_idxposb;
+ /* no valid entry use only offset*/
}
}
else
int i_read;
data_packet_t *p_data;
+
if( !(*pp_pes = input_NewPES( p_input->p_method_data ) ) )
{
return( 0 );
}
+
+ if( !i_size )
+ {
+ p_data = input_NewPacket( p_input->p_method_data, 0 );
+ (*pp_pes)->p_first = (*pp_pes)->p_last = p_data;
+ (*pp_pes)->i_nb_data = 1;
+ (*pp_pes)->i_pes_size = 0;
+ return( 0 );
+ }
+
if( ( i_size&1 )&&( b_pad ) )
{
b_pad = 1;
{
b_pad = 0;
}
-
- if( !i_size )
- {
- (*pp_pes)->p_first = (*pp_pes)->p_last = NULL;
- (*pp_pes)->i_nb_data = 0;
- (*pp_pes)->i_pes_size = 0;
- return( 0 );
- }
do
{
- i_read = input_SplitBuffer(p_input, &p_data, i_size -
- (*pp_pes)->i_pes_size );
+ i_read = input_SplitBuffer(p_input, &p_data, __MIN( i_size -
+ (*pp_pes)->i_pes_size, 1024 ) );
if( i_read < 0 )
{
return( (*pp_pes)->i_pes_size );
AVIStreamInfo_t *p_info )
{
pes_packet_t *p_pes;
- int i_length;
+ int i_length, i_ret;
i_length = __MIN( p_info->p_index[p_info->i_idxposc].i_length
- p_info->i_idxposb,
(off_t)p_info->p_index[p_info->i_idxposc].i_pos +
p_info->i_idxposb + 8);
- if( __AVI_GetDataInPES( p_input,
- &p_pes,
- i_length ,
- 0) != i_length )
+ i_ret = __AVI_GetDataInPES( p_input, &p_pes, i_length , 0);
+
+ if( i_ret != i_length )
{
return( 0 );
}
return( 0 );
}
p_pes->p_first->p_payload_start += 8;
+ p_pes->i_pes_size -= 8;
i_size = GetDWLE( p_pes->p_first->p_demux_start + 4);
AVIIndexEntry_t index;
index.i_id = p_ck->i_id;
- index.i_flags = AVI_GetKeyFlag( p_info_i->p_es->i_type,
+ index.i_flags = AVI_GetKeyFlag( p_info_i->p_es->i_fourcc,
(u8*)&p_ck->i_8bytes);
index.i_pos = p_ck->i_pos;
index.i_length = p_ck->i_size;
{
return( NULL );
}
+fprintf(stderr, "blah ibyte %i\n", i_byte);
if( !( p_data = input_NewPacket( p_input->p_method_data, i_byte ) ) )
{
input_DeletePES( p_input->p_method_data, p_pes );
}
+/*****************************************************************************
+ * AVIDemux_Seekable: reads and demuxes data packets for stream seekable
+ *****************************************************************************
+ * Called by AVIDemux, that make common work
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ *****************************************************************************/
+static int AVIDemux_Seekable( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info_master,
+ AVIStreamInfo_t *p_info_slave )
+{
+ demux_data_avi_file_t *p_avi_demux =
+ (demux_data_avi_file_t*)p_input->p_demux_data;
+
+ pes_packet_t *p_pes_master;
+ pes_packet_t *p_pes_slave;
+
+ /* check for signal from interface */
+ if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
+ {
+ /* we can supposed that is a seek */
+ /* first wait for empty buffer, arbitrary time */
+ msleep( DEFAULT_PTS_DELAY );
+ /* then try to realign in stream */
+ if( !AVI_ReAlign( p_input, p_info_master ) )
+ {
+ return( 0 ); /* assume EOF */
+ }
+ AVI_SynchroReInit( p_input );
+ }
+
+ /* take care of newly selected audio ES */
+ if( p_info_master->b_selected )
+ {
+ p_info_master->b_selected = 0;
+ AVI_SynchroReInit( p_input );
+ }
+ if( ( p_info_slave )&&( p_info_slave->b_selected ) )
+ {
+ p_info_slave->b_selected = 0;
+ AVI_SynchroReInit( p_input );
+ }
+
+ /* wait for the good time */
+ input_ClockManageRef( p_input,
+ p_input->stream.p_selected_program,
+ p_avi_demux->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
+ /* calculate pcr, time when we must read the next data */
+ /* 9/100 kludge ->need to convert to 1/1000000 clock unit to 1/90000 */
+ if( p_info_slave )
+ {
+ p_avi_demux->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
+ AVI_GetPTS( p_info_slave ) ) * 9/100;
+ }
+ else
+ {
+ p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
+ }
+
+ /* get video and audio frames */
+ p_pes_master = AVI_GetFrameInPES( p_input,
+ p_info_master,
+ 100000 ); /* 100 ms */
+ AVI_DecodePES( p_input,
+ p_info_master,
+ p_pes_master);
+
+
+ if( p_info_slave )
+ {
+ p_pes_slave = AVI_GetFrameInPES( p_input,
+ p_info_slave,
+ AVI_GetPTS( p_info_master ) -
+ AVI_GetPTS( p_info_slave) );
+ AVI_DecodePES( p_input,
+ p_info_slave,
+ p_pes_slave );
+ }
+
+
+ /* at the end ? */
+ return( p_pes_master ? 1 : 0 );
+
+}
+
+/*****************************************************************************
+ * AVIDemux_NotSeekable: reads and demuxes data packets for stream seekable
+ *****************************************************************************
+ * Called by AVIDemux, that makes common work
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ *****************************************************************************/
+
+/* 0 if can be load/updated, 1 if skip, 2 if descend into, 3 if exit, 4 if error and need recover */
+static int __AVIDemux_ChunkAction( int i_streams_max,
+ riffchunk_t *p_ck )
+{
+ int i_stream;
+ int i_type;
+
+ AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
+ if( i_stream < i_streams_max )
+ {
+ return( 0 ); /* read and/or update stream info */
+ }
+
+ if( i_stream <= 99 )
+ {
+ /* should not happen but ... */
+ return( 1 );
+ }
+
+ /* now we know that it's not a stream */
+
+ switch( p_ck->i_id )
+ {
+ case( FOURCC_JUNK ):
+ return( 1 );
+ case( FOURCC_idx1 ):
+ return( 3 );
+ case( FOURCC_LIST ):
+ if( p_ck->i_type == FOURCC_rec )
+ {
+ return( 2 );
+ }
+ else
+ {
+ return( 1 );
+ }
+ default:
+ break;
+ }
+ /* test for ix?? */
+
+ if( ( p_ck->i_id & 0xFFFF ) == VLC_TWOCC( 'i','x' ) )
+ {
+ return( 1 );
+ }
+
+ return( 4 );
+}
+
+static int AVI_NotSeekableRecover( input_thread_t *p_input )
+{
+ byte_t *p_id;
+ u32 i_id;
+ int i_number, i_type;
+ data_packet_t *p_pack;
+
+ for( ; ; )
+ {
+ if( input_Peek( p_input, &p_id, 4 ) < 4 )
+ {
+ return( 0 ); /* Failed */
+ }
+ i_id = GetDWLE( p_id );
+ switch( i_id )
+ {
+ case( FOURCC_idx1 ):
+ case( FOURCC_JUNK ):
+ case( FOURCC_LIST ):
+ return( 1 );
+ default:
+ AVI_ParseStreamHeader( i_id, &i_number, &i_type );
+ if( i_number <= 99 )
+ {
+ switch( i_type )
+ {
+ case( TWOCC_wb ):
+ case( TWOCC_db ):
+ case( TWOCC_dc ):
+ case( TWOCC_pc ):
+ return( 1 );
+ }
+ }
+ else
+ {
+
+ }
+ }
+ /* Read 1 byte VERY unoptimised */
+ if( input_SplitBuffer( p_input, &p_pack, 1) < 1 )
+ {
+ return( 0 );
+ }
+ input_DeletePacket( p_input->p_method_data, p_pack);
+ }
+
+}
+
+static int AVIDemux_NotSeekable( input_thread_t *p_input,
+ AVIStreamInfo_t *p_info_master,
+ AVIStreamInfo_t *p_info_slave )
+{
+ demux_data_avi_file_t *p_avi_demux =
+ (demux_data_avi_file_t*)p_input->p_demux_data;
+ int i_loop;
+ int i_stream;
+ int i_type;
+
+ riffchunk_t *p_ck;
+ pes_packet_t *p_pes;
+
+/*
+ i_filepos = AVI_TellAbsolute( p_input );
+ p_input->pf_seek( p_input, i_filepos );
+ input_AccessReinit( p_input );
+*/
+
+#define p_info p_avi_demux->pp_info[i_stream]
+
+ /* The managment is very basic, we will read packets, caclulate pts
+ and send it to decoder, synchro made on video, and audio is very less
+ important */
+
+ /* wait the good time */
+ input_ClockManageRef( p_input,
+ p_input->stream.p_selected_program,
+ p_avi_demux->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
+ /* TODO be smart, seeing if we can wait for min( audio, video )
+ or there is a too big deep */
+ if( !p_info_slave )
+ {
+ p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
+ }
+ else
+ {
+ p_avi_demux->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
+ AVI_GetPTS( p_info_slave ) ) * 9/100;
+ p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
+ }
+
+ for( i_loop = 0; i_loop < 10; i_loop++ )
+ {
+ int b_load =0;
+
+ /* first find a ck for master or slave */
+ do
+ {
+
+ if( !(p_ck = RIFF_ReadChunk( p_input ) ) )
+ {
+ msg_Err( p_input, "Badd" );
+ return( 0 ); /* assume EOF */
+ }
+ //msg_Err( p_input,"Looking ck: %4.4s %d",&p_ck->i_id, p_ck->i_size );
+
+ switch( __AVIDemux_ChunkAction( p_avi_demux->i_streams, p_ck ) )
+ {
+ case( 0 ): /* load it if possible */
+ b_load = 1;
+ break;
+ case( 1 ): /* skip it */
+ RIFF_DeleteChunk( p_input, p_ck );
+ if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
+ {
+ return( 0 );
+ }
+ b_load = 0;
+ break;
+ case( 2 ): /* descend into */
+ RIFF_DeleteChunk( p_input, p_ck );
+ RIFF_DescendChunk( p_input );
+ b_load = 0;
+ break;
+ case( 3 ): /* exit */
+ RIFF_DeleteChunk( p_input, p_ck );
+ return( 0 );
+ case( 4 ): /* Error */
+ RIFF_DeleteChunk( p_input, p_ck );
+ msg_Warn( p_input, "unknown chunk id 0x%8.8x, trying to recover", p_ck->i_id );
+ if( !AVI_NotSeekableRecover( p_input ) )
+ {
+ msg_Err( p_input, "cannot recover, dying" );
+ return( -1 );
+ }
+ else
+ {
+ msg_Warn( p_input, "recovered sucessfully" );
+ }
+ b_load = 0;
+ break;
+ }
+
+ } while( !b_load );
+
+ AVI_ParseStreamHeader( p_ck->i_id, &i_stream, &i_type );
+ /* now check if we really have to load it */
+ if( ( p_info != p_info_master )&&( p_info != p_info_slave ) )
+ {
+ b_load = 0;
+ }
+ else
+ {
+ if( p_info == p_info_master )
+ {
+ b_load = 1;
+ }
+ else
+ {
+ mtime_t i_dpts;
+ i_dpts = AVI_GetPTS( p_info_slave ) -
+ AVI_GetPTS( p_info_master );
+ if( i_dpts < 0 ) {i_dpts = - i_dpts; }
+ if( i_dpts < 600000 )
+ {
+ b_load = 1;
+ }
+ else
+ {
+ b_load = 0;
+ }
+ }
+
+ }
+
+ /* now do we can load this chunk ? */
+ if( b_load )
+ {
+
+ if( __AVI_GetDataInPES( p_input, &p_pes, p_ck->i_size + 8, 1) != p_ck->i_size + 8)
+ {
+ return( 0 );
+ }
+ p_pes->p_first->p_payload_start += 8;
+ p_pes->i_pes_size -= 8;
+ /* get PTS */
+ p_pes->i_pts = AVI_GetPTS( p_info );
+ AVI_DecodePES( p_input, p_info, p_pes );
+ }
+ else
+ {
+
+ if( RIFF_NextChunk( p_input, p_avi_demux->p_movi ) != 0 )
+ {
+ RIFF_DeleteChunk( p_input, p_ck );
+ return( 0 );
+ }
+ }
+
+ /* finaly update stream information */
+ if( p_info->header.i_samplesize )
+ {
+ p_info->i_idxposb += p_ck->i_size;
+ }
+ else
+ {
+ p_info->i_idxposc++;
+ }
+
+ RIFF_DeleteChunk( p_input, p_ck );
+ }
+
+ return( 1 );
+#undef p_info
+}
/*****************************************************************************
* AVIDemux: reads and demuxes data packets
*****************************************************************************
static int AVIDemux( input_thread_t *p_input )
{
int i;
- pes_packet_t *p_pes;
AVIStreamInfo_t *p_info_master;
AVIStreamInfo_t *p_info_slave;
return( -1 );
}
- /* check for signal from interface */
- if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
- {
- /* we can supposed that is a seek */
- /* first wait for empty buffer, arbitrary time */
- msleep( DEFAULT_PTS_DELAY );
- /* then try to realign in stream */
- if( !AVI_ReAlign( p_input, p_info_master ) )
- {
- return( 0 ); /* assume EOF */
- }
- AVI_SynchroReInit( p_input );
- }
-
/* manage rate, if not default: skeep audio */
vlc_mutex_lock( &p_input->stream.stream_lock );
if( p_input->stream.control.i_rate != p_avi_demux->i_rate )
p_avi_demux->i_rate = p_input->stream.control.i_rate;
}
vlc_mutex_unlock( &p_input->stream.stream_lock );
+ p_avi_demux->i_rate = DEFAULT_RATE;
if( p_avi_demux->i_rate != DEFAULT_RATE )
{
p_info_slave = NULL;
}
-
- /* take care of newly selected audio ES */
- if( p_info_master->b_selected )
- {
- p_info_master->b_selected = 0;
- AVI_SynchroReInit( p_input );
- }
- if( ( p_info_slave )&&( p_info_slave->b_selected ) )
- {
- p_info_slave->b_selected = 0;
- AVI_SynchroReInit( p_input );
- }
- /* wait for the good time */
- input_ClockManageRef( p_input,
- p_input->stream.p_selected_program,
- p_avi_demux->i_pcr /*- DEFAULT_PTS_DELAY / 2 */);
- /* calculate pcr, time when we must read the next data */
- /* 9/100 kludge ->need to convert to 1/1000000 clock unit to 1/90000 */
- if( p_info_slave )
+ if( p_avi_demux->b_seekable )
{
- p_avi_demux->i_pcr = __MIN( AVI_GetPTS( p_info_master ),
- AVI_GetPTS( p_info_slave ) ) * 9/100;
+ return( AVIDemux_Seekable( p_input,
+ p_info_master,
+ p_info_slave) );
}
else
{
- p_avi_demux->i_pcr = AVI_GetPTS( p_info_master ) * 9/100;
- }
-
- /* get video and audio frames */
- p_pes = AVI_GetFrameInPES( p_input,
- p_info_master,
- 100000 ); /* 100 ms */
-
-
- if( p_info_slave )
- {
- pes_packet_t *p_pes_slave;
- p_pes_slave = AVI_GetFrameInPES( p_input,
- p_info_slave,
- AVI_GetPTS( p_info_master ) -
- AVI_GetPTS( p_info_slave) );
- AVI_DecodePES( p_input,
- p_info_slave,
- p_pes_slave );
+ return( AVIDemux_NotSeekable( p_input,
+ p_info_master,
+ p_info_slave ) );
}
+}
- AVI_DecodePES( p_input,
- p_info_master,
- p_pes);
-
- /* at the end ? */
- return( p_pes ? 1 : 0 );
-}