* Fixed issues in the PTS handling of the mad plug-in (incomplete).
* 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>
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 );
* 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>
/* Optional argument to the callback */
void * p_callback_arg;
+ /*
+ * PTS retrieval
+ */
+ mtime_t i_pts, i_dts;
+ byte_t * p_pts_validity;
+
/*
* Byte structures
*/
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
/*****************************************************************************
* 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>
*
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;
* 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>
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;
}
"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
*/
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 */
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
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
*/
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;
#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 */
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 ??
}
/* 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);
* 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>
}
/*
- * Following finctions are local to this module
+ * Following functions are local to this module
*/
/*****************************************************************************
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;
* 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>
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;
* 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>
* Stéphane Borel <stef@via.ecp.fr>
{
case SEQUENCE_HEADER_CODE:
p_vpar->c_sequences++;
-
SequenceHeader( p_vpar );
return 0;
break;
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 )
{
* 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>
*
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. */
{
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;
+ }
}
/*****************************************************************************
}
}
+/*****************************************************************************
+ * 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;
+ }
+}
+
* 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>
*
(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;