Commit 27ebd5cd authored by Laurent Aimar's avatar Laurent Aimar

* asf: in fast/slow motion we don't play audio (unless there isn't any

video). Added some clean up.
parent bed89e05
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* asf.c : ASFv01 file input module for vlc * asf.c : ASFv01 file input module for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: asf.c,v 1.16 2003/01/20 13:04:03 fenrir Exp $ * $Id: asf.c,v 1.17 2003/01/23 15:07:20 fenrir Exp $
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -430,326 +430,374 @@ static int Activate( vlc_object_t * p_this ) ...@@ -430,326 +430,374 @@ static int Activate( vlc_object_t * p_this )
default: var = def; break;\ default: var = def; break;\
} }
static int Demux( input_thread_t *p_input ) static int DemuxPacket( input_thread_t *p_input, vlc_bool_t b_play_audio )
{ {
demux_sys_t *p_demux = p_input->p_demux_data; demux_sys_t *p_demux = p_input->p_demux_data;
int i; int i_data_packet_min = p_demux->p_fp->i_min_data_packet_size;
uint8_t *p_peek;
int i_skip;
/* catch seek from user */ int i_packet_size_left;
if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT ) int i_packet_flags;
int i_packet_property;
int b_packet_multiple_payload;
int i_packet_length;
int i_packet_sequence;
int i_packet_padding_length;
uint32_t i_packet_send_time;
uint16_t i_packet_duration;
int i_payload;
int i_payload_count;
int i_payload_length_type;
if( input_Peek( p_input, &p_peek, i_data_packet_min ) < i_data_packet_min )
{ {
off_t i_offset; // EOF ?
msleep( DEFAULT_PTS_DELAY ); msg_Warn( p_input, "cannot peek while getting new packet, EOF ?" );
i_offset = ASF_TellAbsolute( p_input ) - p_demux->i_data_begin; return( 0 );
}
i_skip = 0;
if( i_offset < 0 ) /* *** parse error correction if present *** */
if( p_peek[0]&0x80 )
{
int i_error_correction_length_type;
int i_error_correction_data_length;
int i_opaque_data_present;
i_error_correction_data_length = p_peek[0] & 0x0f; // 4bits
i_opaque_data_present = ( p_peek[0] >> 4 )& 0x01; // 1bit
i_error_correction_length_type = ( p_peek[0] >> 5 ) & 0x03; // 2bits
i_skip += 1; // skip error correction flags
if( i_error_correction_length_type != 0x00 ||
i_opaque_data_present != 0 ||
i_error_correction_data_length != 0x02 )
{ {
i_offset = 0; goto loop_error_recovery;
} }
/* XXX work only when i_min_data_packet_size == i_max_data_packet_size */
i_offset += p_demux->p_fp->i_min_data_packet_size -
i_offset % p_demux->p_fp->i_min_data_packet_size;
ASF_SeekAbsolute( p_input, p_demux->i_data_begin + i_offset );
p_demux->i_time = 0; i_skip += i_error_correction_data_length;
for( i = 0; i < 128 ; i++ ) }
{ else
#define p_stream p_demux->stream[i] {
if( p_stream ) msg_Warn( p_input, "p_peek[0]&0x80 != 0x80" );
{
p_stream->i_time = 0;
}
#undef p_stream
}
p_demux->i_first_pts = -1;
} }
i_packet_flags = p_peek[i_skip]; i_skip++;
i_packet_property = p_peek[i_skip]; i_skip++;
for( i = 0; i < 10; i++ ) // parse 10 packets b_packet_multiple_payload = i_packet_flags&0x01;
{
int i_data_packet_min = p_demux->p_fp->i_min_data_packet_size; /* read some value */
uint8_t *p_peek; GETVALUE2b( i_packet_flags >> 5, i_packet_length, i_data_packet_min );
int i_skip; GETVALUE2b( i_packet_flags >> 1, i_packet_sequence, 0 );
GETVALUE2b( i_packet_flags >> 3, i_packet_padding_length, 0 );
i_packet_send_time = GetDWLE( p_peek + i_skip ); i_skip += 4;
i_packet_duration = GetWLE( p_peek + i_skip ); i_skip += 2;
// i_packet_size_left = i_packet_length; // XXX donnes reellement lu
/* FIXME I have to do that for some file, I don't known why */
i_packet_size_left = i_data_packet_min;
int i_packet_size_left; if( b_packet_multiple_payload )
int i_packet_flags; {
int i_packet_property; i_payload_count = p_peek[i_skip] & 0x3f;
i_payload_length_type = ( p_peek[i_skip] >> 6 )&0x03;
i_skip++;
}
else
{
i_payload_count = 1;
i_payload_length_type = 0x02; // unused
}
int b_packet_multiple_payload; for( i_payload = 0; i_payload < i_payload_count ; i_payload++ )
int i_packet_length; {
int i_packet_sequence; asf_stream_t *p_stream;
int i_packet_padding_length;
uint32_t i_packet_send_time; int i_stream_number;
uint16_t i_packet_duration; int i_media_object_number;
int i_payload; int i_media_object_offset;
int i_payload_count; int i_replicated_data_length;
int i_payload_length_type; int i_payload_data_length;
int i_payload_data_pos;
int i_sub_payload_data_length;
int i_tmp;
mtime_t i_pts;
mtime_t i_pts_delta;
if( input_Peek( p_input, &p_peek, i_data_packet_min ) < i_data_packet_min ) if( i_skip >= i_packet_size_left )
{ {
// EOF ? /* prevent some segfault with invalid file */
msg_Warn( p_input, "cannot peek while getting new packet, EOF ?" ); break;
return( 0 );
} }
i_skip = 0;
/* *** parse error correction if present *** */ i_stream_number = p_peek[i_skip] & 0x7f;
if( p_peek[0]&0x80 ) i_skip++;
GETVALUE2b( i_packet_property >> 4, i_media_object_number, 0 );
GETVALUE2b( i_packet_property >> 2, i_tmp, 0 );
GETVALUE2b( i_packet_property, i_replicated_data_length, 0 );
if( i_replicated_data_length > 1 ) // should be at least 8 bytes
{ {
int i_error_correction_length_type; i_pts = (mtime_t)GetDWLE( p_peek + i_skip + 4 ) * 1000;
int i_error_correction_data_length; i_skip += i_replicated_data_length;
int i_opaque_data_present; i_pts_delta = 0;
i_error_correction_data_length = p_peek[0] & 0x0f; // 4bits
i_opaque_data_present = ( p_peek[0] >> 4 )& 0x01; // 1bit
i_error_correction_length_type = ( p_peek[0] >> 5 ) & 0x03; // 2bits
i_skip += 1; // skip error correction flags
if( i_error_correction_length_type != 0x00 ||
i_opaque_data_present != 0 ||
i_error_correction_data_length != 0x02 )
{
goto loop_error_recovery;
}
i_skip += i_error_correction_data_length; i_media_object_offset = i_tmp;
} }
else else if( i_replicated_data_length == 1 )
{ {
msg_Warn( p_input, "p_peek[0]&0x80 != 0x80" );
}
i_packet_flags = p_peek[i_skip]; i_skip++; msg_Dbg( p_input, "found compressed payload" );
i_packet_property = p_peek[i_skip]; i_skip++;
b_packet_multiple_payload = i_packet_flags&0x01; i_pts = (mtime_t)i_tmp * 1000;
i_pts_delta = (mtime_t)p_peek[i_skip] * 1000; i_skip++;
/* read some value */ i_media_object_offset = 0;
GETVALUE2b( i_packet_flags >> 5, i_packet_length, i_data_packet_min ); }
GETVALUE2b( i_packet_flags >> 1, i_packet_sequence, 0 ); else
GETVALUE2b( i_packet_flags >> 3, i_packet_padding_length, 0 ); {
i_pts = (mtime_t)i_packet_send_time * 1000;
i_packet_send_time = GetDWLE( p_peek + i_skip ); i_skip += 4; i_pts_delta = 0;
i_packet_duration = GetWLE( p_peek + i_skip ); i_skip += 2;
// i_packet_size_left = i_packet_length; // XXX donnes reellement lu i_media_object_offset = i_tmp;
/* FIXME I have to do that for some file, I don't known why */ }
i_packet_size_left = i_data_packet_min;
i_pts = __MAX( i_pts - p_demux->p_fp->i_preroll * 1000, 0 );
if( b_packet_multiple_payload ) if( b_packet_multiple_payload )
{ {
i_payload_count = p_peek[i_skip] & 0x3f; GETVALUE2b( i_payload_length_type, i_payload_data_length, 0 );
i_payload_length_type = ( p_peek[i_skip] >> 6 )&0x03;
i_skip++;
} }
else else
{ {
i_payload_count = 1; i_payload_data_length = i_packet_length -
i_payload_length_type = 0x02; // unused i_packet_padding_length - i_skip;
} }
for( i_payload = 0; i_payload < i_payload_count ; i_payload++ ) #if 0
msg_Dbg( p_input,
"payload(%d/%d) stream_number:%d media_object_number:%d media_object_offset:%d replicated_data_length:%d payload_data_length %d",
i_payload + 1,
i_payload_count,
i_stream_number,
i_media_object_number,
i_media_object_offset,
i_replicated_data_length,
i_payload_data_length );
#endif
if( !( p_stream = p_demux->stream[i_stream_number] ) )
{ {
asf_stream_t *p_stream; msg_Warn( p_input,
"undeclared stream[Id 0x%x]", i_stream_number );
i_skip += i_payload_data_length;
continue; // over payload
}
int i_stream_number; if( !p_stream->p_es || !p_stream->p_es->p_decoder_fifo )
int i_media_object_number; {
int i_media_object_offset; i_skip += i_payload_data_length;
int i_replicated_data_length; continue;
int i_payload_data_length; }
int i_payload_data_pos;
int i_sub_payload_data_length;
int i_tmp;
mtime_t i_pts;
mtime_t i_pts_delta;
if( i_skip >= i_packet_size_left ) for( i_payload_data_pos = 0;
i_payload_data_pos < i_payload_data_length &&
i_packet_size_left > 0;
i_payload_data_pos += i_sub_payload_data_length )
{
data_packet_t *p_data;
int i_read;
// read sub payload length
if( i_replicated_data_length == 1 )
{ {
/* prevent some segfault with invalid file */ i_sub_payload_data_length = p_peek[i_skip]; i_skip++;
break; i_payload_data_pos++;
} }
else
i_stream_number = p_peek[i_skip] & 0x7f;
i_skip++;
GETVALUE2b( i_packet_property >> 4, i_media_object_number, 0 );
GETVALUE2b( i_packet_property >> 2, i_tmp, 0 );
GETVALUE2b( i_packet_property, i_replicated_data_length, 0 );
if( i_replicated_data_length > 1 ) // should be at least 8 bytes
{ {
i_pts = (mtime_t)GetDWLE( p_peek + i_skip + 4 ) * 1000; i_sub_payload_data_length = i_payload_data_length;
i_skip += i_replicated_data_length;
i_pts_delta = 0;
i_media_object_offset = i_tmp;
} }
else if( i_replicated_data_length == 1 )
{
msg_Dbg( p_input, "found compressed payload" ); /* FIXME I don't use i_media_object_number, sould I ? */
if( p_stream->p_pes && i_media_object_offset == 0 ) {
i_pts = (mtime_t)i_tmp * 1000; /* send complete packet to decoder */
i_pts_delta = (mtime_t)p_peek[i_skip] * 1000; i_skip++; if( p_stream->p_pes->i_pes_size > 0 )
{
i_media_object_offset = 0; if( p_stream->p_es->p_decoder_fifo &&
( b_play_audio || p_stream->i_cat != AUDIO_ES ) )
{
input_DecodePES( p_stream->p_es->p_decoder_fifo,
p_stream->p_pes );
}
else
{
input_DeletePES( p_input->p_method_data,
p_stream->p_pes );
}
p_stream->p_pes = NULL;
}
} }
else
if( !p_stream->p_pes ) // add a new PES
{ {
i_pts = (mtime_t)i_packet_send_time * 1000; p_stream->i_time =
i_pts_delta = 0; ( (mtime_t)i_pts + i_payload * (mtime_t)i_pts_delta );
i_media_object_offset = i_tmp; if( p_demux->i_first_pts == -1 )
{
p_demux->i_first_pts = p_stream->i_time;
}
p_stream->i_time -= p_demux->i_first_pts;
p_stream->p_pes = input_NewPES( p_input->p_method_data );
p_stream->p_pes->i_dts =
p_stream->p_pes->i_pts =
input_ClockGetTS( p_input,
p_input->stream.p_selected_program,
( p_stream->i_time+DEFAULT_PTS_DELAY) * 9 /100 );
p_stream->p_pes->p_next = NULL;
p_stream->p_pes->i_nb_data = 0;
p_stream->p_pes->i_pes_size = 0;
} }
i_pts = __MAX( i_pts - p_demux->p_fp->i_preroll * 1000, 0 ); i_read = i_sub_payload_data_length + i_skip;
if( b_packet_multiple_payload ) if( input_SplitBuffer( p_input, &p_data, i_read ) < i_read )
{
GETVALUE2b( i_payload_length_type, i_payload_data_length, 0 );
}
else
{ {
i_payload_data_length = i_packet_length - msg_Warn( p_input, "cannot read data" );
i_packet_padding_length - i_skip; return( 0 );
} }
p_data->p_payload_start += i_skip;
i_packet_size_left -= i_read;
#if 0
msg_Dbg( p_input,
"payload(%d/%d) stream_number:%d media_object_number:%d media_object_offset:%d replicated_data_length:%d payload_data_length %d",
i_payload + 1,
i_payload_count,
i_stream_number,
i_media_object_number,
i_media_object_offset,
i_replicated_data_length,
i_payload_data_length );
#endif
if( !( p_stream = p_demux->stream[i_stream_number] ) ) if( !p_stream->p_pes->p_first )
{ {
msg_Warn( p_input, p_stream->p_pes->p_first = p_stream->p_pes->p_last = p_data;
"undeclared stream[Id 0x%x]", i_stream_number );
i_skip += i_payload_data_length;
continue; // over payload
} }
else
if( !p_stream->p_es || !p_stream->p_es->p_decoder_fifo )
{ {
i_skip += i_payload_data_length; p_stream->p_pes->p_last->p_next = p_data;
continue; p_stream->p_pes->p_last = p_data;
} }
p_stream->p_pes->i_pes_size += i_sub_payload_data_length;
p_stream->p_pes->i_nb_data++;
i_skip = 0;
for( i_payload_data_pos = 0; if( i_packet_size_left > 0 )
i_payload_data_pos < i_payload_data_length &&
i_packet_size_left > 0;
i_payload_data_pos += i_sub_payload_data_length )
{ {
data_packet_t *p_data; if( input_Peek( p_input, &p_peek, i_packet_size_left ) < i_packet_size_left )
int i_read;
// read sub payload length
if( i_replicated_data_length == 1 )
{ {
i_sub_payload_data_length = p_peek[i_skip]; i_skip++; // EOF ?
i_payload_data_pos++; msg_Warn( p_input, "cannot peek, EOF ?" );
} return( 0 );
else
{
i_sub_payload_data_length = i_payload_data_length;
} }
}
}
}
/* FIXME I don't use i_media_object_number, sould I ? */ if( i_packet_size_left > 0 )
if( p_stream->p_pes && i_media_object_offset == 0 ) { {
/* send complete packet to decoder */ if( !ASF_SkipBytes( p_input, i_packet_size_left ) )
if( p_stream->p_pes->i_pes_size > 0 ) {
{ msg_Warn( p_input, "cannot skip data, EOF ?" );
input_DecodePES( p_stream->p_es->p_decoder_fifo, p_stream->p_pes ); return( 0 );
p_stream->p_pes = NULL; }
} }
}
if( !p_stream->p_pes ) // add a new PES return( 1 );
{
p_stream->i_time =
( (mtime_t)i_pts + i_payload * (mtime_t)i_pts_delta );
if( p_demux->i_first_pts == -1 ) loop_error_recovery:
{ msg_Warn( p_input, "unsupported packet header" );
p_demux->i_first_pts = p_stream->i_time; if( p_demux->p_fp->i_min_data_packet_size != p_demux->p_fp->i_max_data_packet_size )
} {
p_stream->i_time -= p_demux->i_first_pts; msg_Err( p_input, "unsupported packet header, fatal error" );
return( -1 );
p_stream->p_pes = input_NewPES( p_input->p_method_data ); }
p_stream->p_pes->i_dts = ASF_SkipBytes( p_input, i_data_packet_min );
p_stream->p_pes->i_pts =
input_ClockGetTS( p_input,
p_input->stream.p_selected_program,
( p_stream->i_time+DEFAULT_PTS_DELAY) * 9 /100 );
p_stream->p_pes->p_next = NULL;
p_stream->p_pes->i_nb_data = 0;
p_stream->p_pes->i_pes_size = 0;
}
i_read = i_sub_payload_data_length + i_skip; return( 1 );
if( input_SplitBuffer( p_input, &p_data, i_read ) < i_read ) }
{
msg_Warn( p_input, "cannot read data" );
return( 0 );
}
p_data->p_payload_start += i_skip;
i_packet_size_left -= i_read;
static int Demux( input_thread_t *p_input )
{
demux_sys_t *p_demux = p_input->p_demux_data;
vlc_bool_t b_play_audio;
int i;
if( !p_stream->p_pes->p_first ) /* catch seek from user */
{ if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
p_stream->p_pes->p_first = p_stream->p_pes->p_last = p_data; {
} off_t i_offset;
else msleep( DEFAULT_PTS_DELAY );
{ i_offset = ASF_TellAbsolute( p_input ) - p_demux->i_data_begin;
p_stream->p_pes->p_last->p_next = p_data;
p_stream->p_pes->p_last = p_data;
}
p_stream->p_pes->i_pes_size += i_sub_payload_data_length;
p_stream->p_pes->i_nb_data++;
i_skip = 0; if( i_offset < 0 )
if( i_packet_size_left > 0 ) {
{ i_offset = 0;
if( input_Peek( p_input, &p_peek, i_packet_size_left ) < i_packet_size_left ) }
{ /* XXX work only when i_min_data_packet_size == i_max_data_packet_size */
// EOF ? i_offset += p_demux->p_fp->i_min_data_packet_size -
msg_Warn( p_input, "cannot peek, EOF ?" ); i_offset % p_demux->p_fp->i_min_data_packet_size;
return( 0 ); ASF_SeekAbsolute( p_input, p_demux->i_data_begin + i_offset );
}
} p_demux->i_time = 0;
for( i = 0; i < 128 ; i++ )
{
#define p_stream p_demux->stream[i]
if( p_stream )
{
p_stream->i_time = 0;
} }
#undef p_stream
} }
p_demux->i_first_pts = -1;
}
if( i_packet_size_left > 0 ) vlc_mutex_lock( &p_input->stream.stream_lock );
if( p_input->stream.control.i_rate == DEFAULT_RATE )
{
b_play_audio = VLC_TRUE;
}
else
{
int i;
b_play_audio = VLC_TRUE;
for( i = 0; i < 128; i++ )
{ {
if( !ASF_SkipBytes( p_input, i_packet_size_left ) ) if( p_demux->stream[i] &&
p_demux->stream[i]->i_cat == VIDEO_ES &&
p_demux->stream[i]->p_es &&
p_demux->stream[i]->p_es->p_decoder_fifo )
{ {
msg_Warn( p_input, "cannot skip data, EOF ?" ); /* there is at least ine video track so no need to play audio */
return( 0 ); b_play_audio = VLC_FALSE;
} }
} }
}
vlc_mutex_unlock( &p_input->stream.stream_lock );
continue;
loop_error_recovery: for( i = 0; i < 10; i++ ) // parse 10 packets
msg_Warn( p_input, "unsupported packet header" ); {
if( p_demux->p_fp->i_min_data_packet_size != p_demux->p_fp->i_max_data_packet_size ) int i_result;
if( ( i_result = DemuxPacket( p_input, b_play_audio ) ) <= 0 )
{ {
msg_Err( p_input, "unsupported packet header, fatal error" ); return i_result;
return( -1 );
} }
ASF_SkipBytes( p_input, i_data_packet_min ); }
} // loop over packet
p_demux->i_time = -1; p_demux->i_time = -1;
for( i = 0; i < 128 ; i++ ) for( i = 0; i < 128 ; i++ )
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment