Commit 7de4e1a3 authored by Christophe Massiot's avatar Christophe Massiot
Browse files

* More precise way to retrieve a PTS from the bit stream.

* Fixed issues in the PTS handling of the mad plug-in (incomplete).
parent bb1c38e6
......@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: common.h,v 1.68 2002/01/13 18:13:07 gbazin Exp $
* $Id: common.h,v 1.69 2002/01/14 23:46:35 massiot Exp $
*
* Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr>
......@@ -571,6 +571,8 @@ typedef struct module_symbols_s
u32 ( * UnalignedShowBits ) ( struct bit_stream_s *, unsigned int );
void ( * UnalignedRemoveBits ) ( struct bit_stream_s * );
u32 ( * UnalignedGetBits ) ( struct bit_stream_s *, unsigned int );
void ( * CurrentPTS ) ( struct bit_stream_s *, mtime_t *,
mtime_t * );
char * ( * DecodeLanguage ) ( u16 );
......
......@@ -2,7 +2,7 @@
* input_ext-dec.h: structures exported to the VideoLAN decoders
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: input_ext-dec.h,v 1.50 2001/12/30 07:09:54 sam Exp $
* $Id: input_ext-dec.h,v 1.51 2002/01/14 23:46:35 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Michel Kaempf <maxx@via.ecp.fr>
......@@ -168,6 +168,12 @@ typedef struct bit_stream_s
/* Optional argument to the callback */
void * p_callback_arg;
/*
* PTS retrieval
*/
mtime_t i_pts, i_dts;
byte_t * p_pts_validity;
/*
* Byte structures
*/
......@@ -215,10 +221,12 @@ typedef struct bit_stream_s
u32 UnalignedShowBits( struct bit_stream_s *, unsigned int );
void UnalignedRemoveBits( struct bit_stream_s * );
u32 UnalignedGetBits( struct bit_stream_s *, unsigned int );
void CurrentPTS( struct bit_stream_s *, mtime_t *, mtime_t * );
#else
# define UnalignedShowBits p_symbols->UnalignedShowBits
# define UnalignedRemoveBits p_symbols->UnalignedRemoveBits
# define UnalignedGetBits p_symbols->UnalignedGetBits
# define CurrentPTS p_symbols->CurrentPTS
#endif
/*****************************************************************************
......
......@@ -2,7 +2,7 @@
* ac3_adec.c: ac3 decoder module main file
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: ac3_adec.c,v 1.13 2002/01/09 00:33:37 asmax Exp $
* $Id: ac3_adec.c,v 1.14 2002/01/14 23:46:35 massiot Exp $
*
* Authors: Michel Lespinasse <walken@zoy.org>
*
......@@ -316,14 +316,12 @@ static int decoder_Run ( decoder_config_t * p_config )
return( -1 );
}
}
if (p_ac3thread->p_fifo->p_first->i_pts)
CurrentPTS( &p_ac3thread->ac3_decoder->bit_stream,
&p_ac3thread->p_aout_fifo->date[p_ac3thread->p_aout_fifo->l_end_frame],
NULL );
if( !p_ac3thread->p_aout_fifo->date[p_ac3thread->p_aout_fifo->l_end_frame] )
{
p_ac3thread->p_aout_fifo->date[
p_ac3thread->p_aout_fifo->l_end_frame] =
p_ac3thread->p_fifo->p_first->i_pts;
p_ac3thread->p_fifo->p_first->i_pts = 0;
} else {
p_ac3thread->p_aout_fifo->date[
p_ac3thread->p_aout_fifo->l_end_frame] =
LAST_MDATE;
......
......@@ -2,7 +2,7 @@
* lpcm_decoder_thread.c: lpcm decoder thread
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: lpcm_adec.c,v 1.8 2001/12/30 07:09:55 sam Exp $
* $Id: lpcm_adec.c,v 1.9 2002/01/14 23:46:35 massiot Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Henri Fallon <henri@videolan.org>
......@@ -170,14 +170,11 @@ void DecodeFrame( lpcmdec_thread_t * p_lpcmdec )
int i_loop;
byte_t byte1, byte2;
if( p_lpcmdec->p_fifo->p_first->i_pts )
CurrentPTS( &p_lpcmdec->bit_stream,
&p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame],
NULL );
if( !p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] )
{
p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
p_lpcmdec->p_fifo->p_first->i_pts;
p_lpcmdec->p_fifo->p_first->i_pts = 0;
}
else
{
p_lpcmdec->p_aout_fifo->date[p_lpcmdec->p_aout_fifo->l_end_frame] =
LAST_MDATE;
}
......
......@@ -170,6 +170,8 @@ static int InitThread( mad_adec_thread_t * p_mad_adec )
"for decoder_InitThread() to allocate p_mad_adec->libmad_decder" );
return -1;
}
p_mad_adec->i_current_pts = p_mad_adec->i_next_pts = 0;
/*
* Initialize bit stream
*/
......@@ -178,8 +180,6 @@ static int InitThread( mad_adec_thread_t * p_mad_adec )
NULL, /* pf_bitstream_callback */
NULL ); /* void **/
RealignBits( &p_mad_adec->bit_stream );
mad_decoder_init( p_mad_adec->libmad_decoder,
p_mad_adec, /* vlc's thread structure and p_fifo playbuffer */
libmad_input, /* input_func */
......
......@@ -50,7 +50,7 @@ typedef struct mad_adec_thread_s
decoder_config_t * p_config;
/* Store i_pts for syncing audio frames */
mtime_t i_pts_save;
mtime_t i_current_pts, i_next_pts;
/*
* Output properties
......
......@@ -50,13 +50,14 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
size_t ReadSize, Remaining;
unsigned char *ReadStart;
/* Store time stamp of current frame */
if ( p_mad_adec->p_fifo->p_first->i_pts ) {
p_mad_adec->i_pts_save = p_mad_adec->p_fifo->p_first->i_pts;
p_mad_adec->p_fifo->p_first->i_pts = 0;
if ( p_mad_adec->p_fifo->b_die == 1 ) {
intf_ErrMsg( "mad_adec error: libmad_input stopping libmad decoder" );
return MAD_FLOW_STOP;
}
else {
p_mad_adec->i_pts_save = LAST_MDATE;
if ( p_mad_adec->p_fifo->b_error == 1 ) {
intf_ErrMsg( "mad_adec error: libmad_input ignoring current audio frame" );
return MAD_FLOW_IGNORE;
}
/* libmad_stream_buffer does not consume the total buffer, it consumes only data
......@@ -64,56 +65,80 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
*/
if ((p_libmad_stream->buffer==NULL) || (p_libmad_stream->error==MAD_ERROR_BUFLEN))
{
/* libmad does not consume all the buffer it's given. Some
* datas, part of a truncated frame, is left unused at the
* end of the buffer. Those datas must be put back at the
* beginning of the buffer and taken in account for
* refilling the buffer. This means that the input buffer
* must be large enough to hold a complete frame at the
* highest observable bit-rate (currently 448 kb/s). XXX=XXX
* Is 2016 bytes the size of the largest frame?
* (448000*(1152/32000))/8
*/
if(p_libmad_stream->next_frame!=NULL)
{
Remaining=p_libmad_stream->bufend-p_libmad_stream->next_frame;
memmove(p_mad_adec->buffer,p_libmad_stream->next_frame,Remaining);
ReadStart=p_mad_adec->buffer+Remaining;
ReadSize=(MAD_BUFFER_SIZE)-Remaining;
/* Store time stamp of next frame */
p_mad_adec->i_current_pts = p_mad_adec->i_next_pts;
CurrentPTS( &p_mad_adec->bit_stream, &p_mad_adec->i_next_pts, NULL );
}
else
{
ReadSize=(MAD_BUFFER_SIZE);
ReadStart=p_mad_adec->buffer;
Remaining=0;
p_mad_adec->i_next_pts = 0;
CurrentPTS( &p_mad_adec->bit_stream, &p_mad_adec->i_current_pts, NULL );
}
/* libmad does not consume all the buffer it's given. Some
* datas, part of a truncated frame, is left unused at the
* end of the buffer. Those datas must be put back at the
* beginning of the buffer and taken in account for
* refilling the buffer. This means that the input buffer
* must be large enough to hold a complete frame at the
* highest observable bit-rate (currently 448 kb/s). XXX=XXX
* Is 2016 bytes the size of the largest frame?
* (448000*(1152/32000))/8
*/
if(p_libmad_stream->next_frame!=NULL)
{
Remaining=p_libmad_stream->bufend-p_libmad_stream->next_frame;
memmove(p_mad_adec->buffer,p_libmad_stream->next_frame,Remaining);
ReadStart=p_mad_adec->buffer+Remaining;
ReadSize=(MAD_BUFFER_SIZE)-Remaining;
}
else
{
ReadSize=(MAD_BUFFER_SIZE);
ReadStart=p_mad_adec->buffer;
Remaining=0;
}
//intf_ErrMsg( "mad_adec debug: buffer size remaining [%d] and readsize [%d] total [%d]",
// Remaining, ReadSize, ReadSize+Remaining);
/* Fill-in the buffer. If an error occurs print a message
* and leave the decoding loop. If the end of stream is
* reached we also leave the loop but the return status is
* left untouched.
*/
GetChunk( &p_mad_adec->bit_stream, ReadStart, ReadSize );
/* Fill-in the buffer. If an error occurs print a message
* and leave the decoding loop. If the end of stream is
* reached we also leave the loop but the return status is
* left untouched.
*/
#if 0
/* This is currently buggy --Meuuh */
if( ReadSize > p_mad_adec->bit_stream.p_end
- p_mad_adec->bit_stream.p_byte )
{
FAST_MEMCPY( ReadStart, p_mad_adec->bit_stream.p_byte,
p_mad_adec->bit_stream.p_end - p_mad_adec->bit_stream.p_byte );
p_mad_adec->bit_stream.pf_next_data_packet( &p_mad_adec->bit_stream );
}
else
{
FAST_MEMCPY( ReadStart, p_mad_adec->bit_stream.p_byte,
ReadSize );
p_mad_adec->bit_stream.p_byte += ReadSize;
}
#else
/* This is PTS-inaccurate --Meuuh */
GetChunk( &p_mad_adec->bit_stream, ReadStart, ReadSize );
#endif
if ( p_mad_adec->p_fifo->b_die == 1 ) {
if ( p_mad_adec->p_fifo->b_die == 1 )
{
intf_ErrMsg( "mad_adec error: libmad_input stopping libmad decoder" );
return MAD_FLOW_STOP;
}
if ( p_mad_adec->p_fifo->b_error == 1 ) {
intf_ErrMsg( "mad_adec error: libmad_input ignoring current audio frame" );
if ( p_mad_adec->p_fifo->b_error == 1 )
{
intf_ErrMsg( "mad_adec error: libmad_input ignoring current audio frame" );
return MAD_FLOW_IGNORE;
}
/* Pipe the new buffer content to libmad's stream decoder facility.
* Libmad never copies the buffer, but just references it. So keep it in
* mad_adec_thread_t structure.
*/
mad_stream_buffer(p_libmad_stream,(unsigned char*) &p_mad_adec->buffer,ReadSize+Remaining);
p_libmad_stream->error=0;
/* Pipe the new buffer content to libmad's stream decoder facility.
* Libmad never copies the buffer, but just references it. So keep it in
* mad_adec_thread_t structure.
*/
mad_stream_buffer(p_libmad_stream,(unsigned char*) &p_mad_adec->buffer,
MAD_BUFFER_SIZE);
p_libmad_stream->error=0;
}
return MAD_FLOW_CONTINUE;
......@@ -270,7 +295,8 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
#endif
/* Creating the audio output fifo */
if (p_mad_adec->p_aout_fifo==NULL) {
if (p_mad_adec->p_aout_fifo==NULL)
{
p_mad_adec->p_aout_fifo = aout_CreateFifo(
AOUT_ADEC_STEREO_FIFO, /* fifo type */
p_libmad_pcm->channels, /* nr. of channels */
......@@ -284,10 +310,11 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
return( -1 );
}
intf_ErrMsg("mad_adec debug: in libmad_output aout fifo created");
intf_ErrMsg("mad_adec debug: in libmad_output aout fifo created");
}
else {
p_mad_adec->p_aout_fifo->l_rate = p_libmad_pcm->samplerate;
else
{
p_mad_adec->p_aout_fifo->l_rate = p_libmad_pcm->samplerate;
}
/* Some frames are nog quite right. Why ??? I do not know. Probably syncing and CRC errors ??
......@@ -306,7 +333,17 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
}
/* Set timestamp to synchronize audio and video decoder fifo's */
p_mad_adec->p_aout_fifo->date[p_mad_adec->p_aout_fifo->l_end_frame] = p_mad_adec->i_pts_save;
p_mad_adec->p_aout_fifo->l_rate = p_libmad_header->samplerate;
if( p_mad_adec->i_current_pts )
{
p_mad_adec->p_aout_fifo->date[p_mad_adec->p_aout_fifo->l_end_frame]
= p_mad_adec->i_current_pts;
}
else
{
p_mad_adec->p_aout_fifo->date[p_mad_adec->p_aout_fifo->l_end_frame]
= LAST_MDATE;
}
mad_timer_add(&p_mad_adec->libmad_timer,p_libmad_header->duration);
buffer = ((byte_t *)p_mad_adec->p_aout_fifo->buffer) + (p_mad_adec->p_aout_fifo->l_end_frame * MAD_OUTPUT_SIZE);
......
......@@ -2,7 +2,7 @@
* mpeg_adec.c: MPEG audio decoder thread
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: mpeg_adec.c,v 1.13 2002/01/10 23:41:08 asmax Exp $
* $Id: mpeg_adec.c,v 1.14 2002/01/14 23:46:35 massiot Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Michel Lespinasse <walken@via.ecp.fr>
......@@ -153,7 +153,7 @@ static int decoder_Run ( decoder_config_t * p_config )
}
/*
* Following finctions are local to this module
* Following functions are local to this module
*/
/*****************************************************************************
......@@ -203,13 +203,10 @@ static void DecodeThread( adec_thread_t * p_adec )
buffer = ((s16 *)p_adec->p_aout_fifo->buffer)
+ (p_adec->p_aout_fifo->l_end_frame * ADEC_FRAME_SIZE);
if( p_adec->p_fifo->p_first->i_pts )
{
p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
p_adec->p_fifo->p_first->i_pts;
p_adec->p_fifo->p_first->i_pts = 0;
}
else
CurrentPTS( &p_adec->bit_stream,
&p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame],
NULL );
if( !p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] )
{
p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
LAST_MDATE;
......
......@@ -2,7 +2,7 @@
* video_parser.c : video parser thread
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: video_parser.c,v 1.10 2001/12/30 07:09:56 sam Exp $
* $Id: video_parser.c,v 1.11 2002/01/14 23:46:35 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr>
......@@ -384,10 +384,6 @@ static void BitstreamCallback ( bit_stream_t * p_bit_stream,
if( b_new_pes )
{
p_vpar->sequence.next_pts =
p_bit_stream->p_decoder_fifo->p_first->i_pts;
p_vpar->sequence.next_dts =
p_bit_stream->p_decoder_fifo->p_first->i_dts;
p_vpar->sequence.i_current_rate =
p_bit_stream->p_decoder_fifo->p_first->i_rate;
......
......@@ -2,7 +2,7 @@
* vpar_headers.c : headers parsing
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: vpar_headers.c,v 1.11 2002/01/14 22:26:05 massiot Exp $
* $Id: vpar_headers.c,v 1.12 2002/01/14 23:46:35 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Stphane Borel <stef@via.ecp.fr>
......@@ -263,7 +263,6 @@ int vpar_ParseHeader( vpar_thread_t * p_vpar )
{
case SEQUENCE_HEADER_CODE:
p_vpar->c_sequences++;
SequenceHeader( p_vpar );
return 0;
break;
......@@ -540,6 +539,10 @@ static void PictureHeader( vpar_thread_t * p_vpar )
int i_structure, i_previous_coding_type;
boolean_t b_parsable = 0;
/* Retrieve the PTS. */
CurrentPTS( &p_vpar->bit_stream, &p_vpar->sequence.next_pts,
&p_vpar->sequence.next_dts );
/* Recover in case of stream discontinuity. */
if( p_vpar->sequence.b_expect_discontinuity )
{
......
......@@ -2,7 +2,7 @@
* input_ext-dec.c: services to the decoders
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: input_ext-dec.c,v 1.27 2001/12/31 03:26:27 massiot Exp $
* $Id: input_ext-dec.c,v 1.28 2002/01/14 23:46:35 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -63,6 +63,9 @@ void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo,
p_bit_stream->p_end = p_bit_stream->p_data->p_payload_end;
p_bit_stream->fifo.buffer = 0;
p_bit_stream->fifo.i_available = 0;
p_bit_stream->i_pts = p_fifo->p_first->i_pts;
p_bit_stream->i_dts = p_fifo->p_first->i_dts;
p_bit_stream->p_pts_validity = p_bit_stream->p_byte;
vlc_mutex_unlock( &p_fifo->data_lock );
/* Call back the decoder. */
......@@ -170,6 +173,20 @@ void NextDataPacket( bit_stream_t * p_bit_stream )
{
p_bit_stream->pf_bitstream_callback( p_bit_stream, b_new_pes );
}
/* Discontinuity management. */
if( p_bit_stream->p_data->b_discard_payload )
{
p_bit_stream->i_pts = p_bit_stream->i_dts = 0;
}
/* Retrieve the PTS. */
if( b_new_pes && p_fifo->p_first->i_pts )
{
p_bit_stream->i_pts = p_fifo->p_first->i_pts;
p_bit_stream->i_dts = p_fifo->p_first->i_dts;
p_bit_stream->p_pts_validity = p_bit_stream->p_byte;
}
}
/*****************************************************************************
......@@ -375,3 +392,28 @@ void UnalignedRemoveBits( bit_stream_t * p_bit_stream )
}
}
/*****************************************************************************
* CurrentPTS: returns the current PTS and DTS
*****************************************************************************/
void CurrentPTS( bit_stream_t * p_bit_stream, mtime_t * pi_pts,
mtime_t * pi_dts )
{
/* Check if the current PTS is already valid (ie. if the first byte
* of the packet has already been used in the decoder). */
ptrdiff_t p_diff = p_bit_stream->p_byte - p_bit_stream->p_pts_validity;
if( p_diff < 0 || p_diff > 4 /* We are far away so it is valid */
|| (p_diff * 8) >= p_bit_stream->fifo.i_available
/* We have buffered less bytes than actually read */ )
{
*pi_pts = p_bit_stream->i_pts;
if( pi_dts != NULL ) *pi_dts = p_bit_stream->i_dts;
p_bit_stream->i_pts = 0;
p_bit_stream->i_dts = 0;
}
else
{
*pi_pts = 0;
if( pi_dts != NULL) *pi_dts = 0;
}
}
......@@ -2,7 +2,7 @@
* modules_plugin.h : Plugin management functions used by the core application.
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: modules_plugin.h,v 1.4 2002/01/09 02:01:14 sam Exp $
* $Id: modules_plugin.h,v 1.5 2002/01/14 23:46:35 massiot Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -226,6 +226,7 @@ module_error( void )
(p_symbols)->UnalignedGetBits = UnalignedGetBits; \
(p_symbols)->UnalignedRemoveBits = UnalignedRemoveBits; \
(p_symbols)->UnalignedShowBits = UnalignedShowBits; \
(p_symbols)->CurrentPTS = CurrentPTS; \
(p_symbols)->DecodeLanguage = DecodeLanguage; \
(p_symbols)->module_Need = module_Need; \
(p_symbols)->module_Unneed = module_Unneed;
......
Supports Markdown
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