+#define CR_MEAN_PTS_GAP (300000)
+
+/*****************************************************************************
+ * Structures
+ *****************************************************************************/
+
+/**
+ * This structure holds long term average
+ */
+typedef struct
+{
+ mtime_t i_value;
+ int i_residue;
+
+ int i_count;
+ int i_divider;
+} average_t;
+static void AvgInit( average_t *, int i_divider );
+static void AvgClean( average_t * );
+
+static void AvgReset( average_t * );
+static void AvgUpdate( average_t *, mtime_t i_value );
+static mtime_t AvgGet( average_t * );
+static void AvgRescale( average_t *, int i_divider );
+
+/* */
+typedef struct
+{
+ mtime_t i_stream;
+ mtime_t i_system;
+} clock_point_t;
+
+static inline clock_point_t clock_point_Create( mtime_t i_stream, mtime_t i_system )
+{
+ clock_point_t p = { .i_stream = i_stream, .i_system = i_system };
+ return p;
+}
+
+/* */
+struct input_clock_t
+{
+ /* */
+ vlc_mutex_t lock;
+
+ /* Reference point */
+ bool b_has_reference;
+ clock_point_t ref;
+
+ /* Last point
+ * It is used to detect unexpected stream discontinuities */
+ clock_point_t last;
+
+ /* Maximal timestamp returned by input_clock_ConvertTS (in system unit) */
+ mtime_t i_ts_max;
+
+ /* Clock drift */
+ mtime_t i_next_drift_update;
+ average_t drift;
+
+ /* Current modifiers */
+ int i_rate;
+ mtime_t i_pts_delay;
+ bool b_paused;
+ mtime_t i_pause_date;
+};
+
+static mtime_t ClockStreamToSystem( input_clock_t *, mtime_t i_stream );
+static mtime_t ClockSystemToStream( input_clock_t *, mtime_t i_system );
+
+/*****************************************************************************
+ * input_clock_New: create a new clock
+ *****************************************************************************/
+input_clock_t *input_clock_New( int i_rate )
+{
+ input_clock_t *cl = malloc( sizeof(*cl) );
+ if( !cl )
+ return NULL;
+
+ vlc_mutex_init( &cl->lock );
+ cl->b_has_reference = false;
+ cl->ref = clock_point_Create( VLC_TS_INVALID, VLC_TS_INVALID );
+
+ cl->last = clock_point_Create( VLC_TS_INVALID, VLC_TS_INVALID );
+
+ cl->i_ts_max = VLC_TS_INVALID;
+
+ cl->i_next_drift_update = VLC_TS_INVALID;
+ AvgInit( &cl->drift, 10 );
+
+ cl->i_rate = i_rate;
+ cl->i_pts_delay = 0;
+ cl->b_paused = false;
+ cl->i_pause_date = VLC_TS_INVALID;
+
+ return cl;
+}
+
+/*****************************************************************************
+ * input_clock_Delete: destroy a new clock
+ *****************************************************************************/
+void input_clock_Delete( input_clock_t *cl )
+{
+ AvgClean( &cl->drift );
+ vlc_mutex_destroy( &cl->lock );
+ free( cl );
+}