* input_clock.c: Clock/System date convertions, stream management
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: input_clock.c,v 1.36 2002/12/12 15:10:58 gbazin Exp $
+ * $Id: input_clock.c,v 1.39 2003/07/28 13:19:37 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* in all the FIFOs, but it may be not enough.
*/
+static void ClockNewRef( pgrm_descriptor_t * p_pgrm,
+ mtime_t i_clock, mtime_t i_sysdate );
+
/*****************************************************************************
* Constants
*****************************************************************************/
/* Maximum gap allowed between two CRs. */
#define CR_MAX_GAP 1000000
+/* Latency introduced on DVDs with CR == 0 on chapter change - this is from
+ * my dice --Meuuh */
+#define CR_MEAN_PTS_GAP 300000
+
/*****************************************************************************
* ClockToSysdate: converts a movie clock to system date
*****************************************************************************/
i_sysdate /= 27;
i_sysdate /= 1000;
i_sysdate += (mtime_t)p_pgrm->sysdate_ref;
+
+ if ( i_sysdate < mdate() - CR_MAX_GAP
+ || i_sysdate > mdate() + CR_MAX_GAP )
+ {
+ msg_Warn( p_input, "Bogus clock encountered, resetting" );
+ ClockNewRef( p_pgrm, i_clock, i_sysdate = mdate() );
+ }
}
return( i_sysdate );
mtime_t i_clock, mtime_t i_sysdate )
{
p_pgrm->cr_ref = i_clock;
- /* this is actually a kludge, but it gives better results when scr
- * is zero in DVDs: we are 3-4 ms in advance instead of sometimes
- * 100ms late */
- p_pgrm->sysdate_ref = ( p_pgrm->last_syscr && !i_clock )
- ? p_pgrm->last_syscr
- : i_sysdate ;
+ p_pgrm->sysdate_ref = i_sysdate ;
}
/*****************************************************************************
void input_ClockInit( pgrm_descriptor_t * p_pgrm )
{
p_pgrm->last_cr = 0;
- p_pgrm->last_syscr = 0;
+ p_pgrm->last_pts = 0;
p_pgrm->cr_ref = 0;
p_pgrm->sysdate_ref = 0;
p_pgrm->delta_cr = 0;
vlc_cond_wait( &p_input->stream.stream_wait,
&p_input->stream.stream_lock );
- p_pgrm->last_syscr = 0;
- ClockNewRef( p_pgrm, i_clock, mdate() );
+ ClockNewRef( p_pgrm, i_clock, p_pgrm->last_pts > mdate() ?
+ p_pgrm->last_pts : mdate() );
if( p_input->stream.i_new_status == PAUSE_S )
{
if( ( p_pgrm->i_synchro_state != SYNCHRO_OK ) || ( i_clock == 0 ) )
{
/* Feed synchro with a new reference point. */
- ClockNewRef( p_pgrm, i_clock, mdate() );
+ ClockNewRef( p_pgrm, i_clock,
+ p_pgrm->last_pts + CR_MEAN_PTS_GAP > mdate() ?
+ p_pgrm->last_pts + CR_MEAN_PTS_GAP : mdate() );
p_pgrm->i_synchro_state = SYNCHRO_OK;
if( p_input->stream.b_pace_control
else
{
p_pgrm->last_cr = 0;
- p_pgrm->last_syscr = 0;
p_pgrm->delta_cr = 0;
p_pgrm->c_average_count = 0;
}
if( p_input->stream.b_pace_control
&& p_input->stream.p_selected_program == p_pgrm )
{
- /* We remember the last system date to be able to restart
- * the synchro we statistically better continuity, after
- * a zero scr */
- p_pgrm->last_syscr = ClockToSysdate( p_input, p_pgrm, i_clock );
-
/* Wait a while before delivering the packets to the decoder.
* In case of multiple programs, we arbitrarily follow the
- * clock of the first program. */
- mwait( p_pgrm->last_syscr );
+ * clock of the selected program. */
+ mwait( ClockToSysdate( p_input, p_pgrm, i_clock ) );
/* Now take into account interface changes. */
input_ClockManageControl( p_input, p_pgrm, i_clock );
if( p_pgrm->i_synchro_state == SYNCHRO_OK )
{
- return( ClockToSysdate( p_input, p_pgrm, i_ts + p_pgrm->delta_cr )
- + p_input->i_pts_delay
- + (p_input->p_vlc->i_desync > 0
- ? p_input->p_vlc->i_desync : 0) );
+ p_pgrm->last_pts = ClockToSysdate( p_input, p_pgrm,
+ i_ts + p_pgrm->delta_cr );
+ return( p_pgrm->last_pts + p_input->i_pts_delay );
}
else
{