Commit d147f145 authored by Laurent Aimar's avatar Laurent Aimar

Added es_out_ControlModifyPcrSystem to synchronize the input clock on an external source.

It could be used to update the netsynch module or to lock the input
clock on the audio one.

Partially based on a patch by Jean-Paul Saman.
parent 454a3688
...@@ -87,6 +87,7 @@ enum es_out_query_e ...@@ -87,6 +87,7 @@ enum es_out_query_e
/* PCR system clock manipulation for external clock synchronization */ /* PCR system clock manipulation for external clock synchronization */
ES_OUT_GET_PCR_SYSTEM, /* arg1=mtime_t * res=can fail */ ES_OUT_GET_PCR_SYSTEM, /* arg1=mtime_t * res=can fail */
ES_OUT_MODIFY_PCR_SYSTEM, /* arg1=int is_absolute, arg2=mtime_t, res=can fail */
/* First value usable for private control */ /* First value usable for private control */
ES_OUT_PRIVATE_START = 0x10000, ES_OUT_PRIVATE_START = 0x10000,
...@@ -152,6 +153,10 @@ static inline int es_out_ControlGetPcrSystem( es_out_t *out, mtime_t *pi_system ...@@ -152,6 +153,10 @@ static inline int es_out_ControlGetPcrSystem( es_out_t *out, mtime_t *pi_system
{ {
return es_out_Control( out, ES_OUT_GET_PCR_SYSTEM, pi_system ); return es_out_Control( out, ES_OUT_GET_PCR_SYSTEM, pi_system );
} }
static inline int es_out_ControlModifyPcrSystem( es_out_t *out, bool b_absolute, mtime_t i_system )
{
return es_out_Control( out, ES_OUT_MODIFY_PCR_SYSTEM, b_absolute, i_system );
}
/** /**
* @} * @}
......
...@@ -169,6 +169,10 @@ struct input_clock_t ...@@ -169,6 +169,10 @@ struct input_clock_t
clock_point_t ref; clock_point_t ref;
bool b_has_reference; bool b_has_reference;
/* External clock drift */
mtime_t i_external_clock;
bool b_has_external_clock;
/* Current modifiers */ /* Current modifiers */
bool b_paused; bool b_paused;
int i_rate; int i_rate;
...@@ -193,6 +197,7 @@ input_clock_t *input_clock_New( int i_rate ) ...@@ -193,6 +197,7 @@ input_clock_t *input_clock_New( int i_rate )
vlc_mutex_init( &cl->lock ); vlc_mutex_init( &cl->lock );
cl->b_has_reference = false; cl->b_has_reference = false;
cl->ref = clock_point_Create( VLC_TS_INVALID, VLC_TS_INVALID ); cl->ref = clock_point_Create( VLC_TS_INVALID, VLC_TS_INVALID );
cl->b_has_external_clock = false;
cl->last = clock_point_Create( VLC_TS_INVALID, VLC_TS_INVALID ); cl->last = clock_point_Create( VLC_TS_INVALID, VLC_TS_INVALID );
...@@ -272,6 +277,7 @@ void input_clock_Update( input_clock_t *cl, vlc_object_t *p_log, ...@@ -272,6 +277,7 @@ void input_clock_Update( input_clock_t *cl, vlc_object_t *p_log,
cl->b_has_reference = true; cl->b_has_reference = true;
cl->ref = clock_point_Create( i_ck_stream, cl->ref = clock_point_Create( i_ck_stream,
__MAX( cl->i_ts_max + CR_MEAN_PTS_GAP, i_ck_system ) ); __MAX( cl->i_ts_max + CR_MEAN_PTS_GAP, i_ck_system ) );
cl->b_has_external_clock = false;
} }
/* Compute the drift between the stream clock and the system clock /* Compute the drift between the stream clock and the system clock
...@@ -329,6 +335,7 @@ void input_clock_Reset( input_clock_t *cl ) ...@@ -329,6 +335,7 @@ void input_clock_Reset( input_clock_t *cl )
cl->b_has_reference = false; cl->b_has_reference = false;
cl->ref = clock_point_Create( VLC_TS_INVALID, VLC_TS_INVALID ); cl->ref = clock_point_Create( VLC_TS_INVALID, VLC_TS_INVALID );
cl->b_has_external_clock = false;
cl->i_ts_max = VLC_TS_INVALID; cl->i_ts_max = VLC_TS_INVALID;
vlc_mutex_unlock( &cl->lock ); vlc_mutex_unlock( &cl->lock );
...@@ -482,12 +489,25 @@ int input_clock_GetState( input_clock_t *cl, ...@@ -482,12 +489,25 @@ int input_clock_GetState( input_clock_t *cl,
return VLC_SUCCESS; return VLC_SUCCESS;
} }
void input_clock_ChangeSystemOrigin( input_clock_t *cl, mtime_t i_system ) void input_clock_ChangeSystemOrigin( input_clock_t *cl, bool b_absolute, mtime_t i_system )
{ {
vlc_mutex_lock( &cl->lock ); vlc_mutex_lock( &cl->lock );
assert( cl->b_has_reference ); assert( cl->b_has_reference );
const mtime_t i_offset = i_system - cl->ref.i_system - ClockGetTsOffset( cl ); mtime_t i_offset;
if( b_absolute )
{
i_offset = i_system - cl->ref.i_system - ClockGetTsOffset( cl );
}
else
{
if( !cl->b_has_external_clock )
{
cl->b_has_external_clock = true;
cl->i_external_clock = i_system;
}
i_offset = i_system - cl->i_external_clock;
}
cl->ref.i_system += i_offset; cl->ref.i_system += i_offset;
cl->last.i_system += i_offset; cl->last.i_system += i_offset;
......
...@@ -90,11 +90,12 @@ void input_clock_ChangePause( input_clock_t *, bool b_paused, mtime_t i_date ...@@ -90,11 +90,12 @@ void input_clock_ChangePause( input_clock_t *, bool b_paused, mtime_t i_date
mtime_t input_clock_GetSystemOrigin( input_clock_t * ); mtime_t input_clock_GetSystemOrigin( input_clock_t * );
/** /**
* This function allows to rebase the original system value date. * This function allows to rebase the original system value date (a valid
* It can be called only imediatly after a input_clock_Update call. * reference point must have been set).
* FIXME ugly * When using the absolute mode, it will create a discontinuity unless
* called imediatly after a input_clock_Update.
*/ */
void input_clock_ChangeSystemOrigin( input_clock_t *, mtime_t i_system ); void input_clock_ChangeSystemOrigin( input_clock_t *, bool b_absolute, mtime_t i_system );
/** /**
* This function converts a pair of timestamp from stream clock to system clock. * This function converts a pair of timestamp from stream clock to system clock.
......
...@@ -679,7 +679,8 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced ) ...@@ -679,7 +679,8 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
const mtime_t i_wakeup_delay = 10*1000; /* FIXME CLEANUP thread wake up time*/ const mtime_t i_wakeup_delay = 10*1000; /* FIXME CLEANUP thread wake up time*/
const mtime_t i_current_date = p_sys->b_paused ? p_sys->i_pause_date : mdate(); const mtime_t i_current_date = p_sys->b_paused ? p_sys->i_pause_date : mdate();
input_clock_ChangeSystemOrigin( p_sys->p_pgrm->p_clock, i_current_date + i_wakeup_delay - i_buffering_duration ); input_clock_ChangeSystemOrigin( p_sys->p_pgrm->p_clock, true,
i_current_date + i_wakeup_delay - i_buffering_duration );
for( int i = 0; i < p_sys->i_es; i++ ) for( int i = 0; i < p_sys->i_es; i++ )
{ {
...@@ -2580,6 +2581,21 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) ...@@ -2580,6 +2581,21 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
return VLC_SUCCESS; return VLC_SUCCESS;
} }
case ES_OUT_MODIFY_PCR_SYSTEM:
{
if( p_sys->b_buffering )
return VLC_EGENERIC;
es_out_pgrm_t *p_pgrm = p_sys->p_pgrm;
if( !p_pgrm )
return VLC_EGENERIC;
const bool b_absolute = va_arg( args, int );
const mtime_t i_system = va_arg( args, mtime_t );
input_clock_ChangeSystemOrigin( p_pgrm->p_clock, b_absolute, i_system );
return VLC_SUCCESS;
}
default: default:
msg_Err( p_sys->p_input, "unknown query in es_out_Control" ); msg_Err( p_sys->p_input, "unknown query in es_out_Control" );
return VLC_EGENERIC; return VLC_EGENERIC;
......
...@@ -681,6 +681,16 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args ) ...@@ -681,6 +681,16 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
mtime_t *pi_system = (mtime_t*)va_arg( args, mtime_t * ); mtime_t *pi_system = (mtime_t*)va_arg( args, mtime_t * );
return es_out_ControlGetPcrSystem( p_sys->p_out, pi_system ); return es_out_ControlGetPcrSystem( p_sys->p_out, pi_system );
} }
case ES_OUT_MODIFY_PCR_SYSTEM:
{
const bool b_absolute = va_arg( args, int );
const mtime_t i_system = va_arg( args, mtime_t );
if( b_absolute && p_sys->b_delayed )
return VLC_EGENERIC;
return es_out_ControlModifyPcrSystem( p_sys->p_out, b_absolute, i_system );
}
default: default:
msg_Err( p_sys->p_input, "Unknown es_out_Control query !" ); msg_Err( p_sys->p_input, "Unknown es_out_Control query !" );
assert(0); assert(0);
......
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