mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 09:10:36 +00:00
clock: make more stuff private
Expose methods to get and set the timeout because subclasses uses this.
This commit is contained in:
parent
8909205b85
commit
eb84682e92
6 changed files with 224 additions and 200 deletions
227
gst/gstclock.c
227
gst/gstclock.c
|
@ -131,8 +131,35 @@ enum
|
||||||
PROP_TIMEOUT
|
PROP_TIMEOUT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GST_CLOCK_SLAVE_LOCK(clock) g_mutex_lock (&GST_CLOCK_CAST (clock)->priv->slave_lock)
|
||||||
|
#define GST_CLOCK_SLAVE_UNLOCK(clock) g_mutex_unlock (&GST_CLOCK_CAST (clock)->priv->slave_lock)
|
||||||
|
|
||||||
struct _GstClockPrivate
|
struct _GstClockPrivate
|
||||||
{
|
{
|
||||||
|
GMutex slave_lock; /* order: SLAVE_LOCK, OBJECT_LOCK */
|
||||||
|
|
||||||
|
/* with LOCK */
|
||||||
|
GstClockTime internal_calibration;
|
||||||
|
GstClockTime external_calibration;
|
||||||
|
GstClockTime rate_numerator;
|
||||||
|
GstClockTime rate_denominator;
|
||||||
|
GstClockTime last_time;
|
||||||
|
|
||||||
|
/* with LOCK */
|
||||||
|
GstClockTime resolution;
|
||||||
|
|
||||||
|
/* for master/slave clocks */
|
||||||
|
GstClock *master;
|
||||||
|
|
||||||
|
/* with SLAVE_LOCK */
|
||||||
|
gboolean filling;
|
||||||
|
gint window_size;
|
||||||
|
gint window_threshold;
|
||||||
|
gint time_index;
|
||||||
|
GstClockTime timeout;
|
||||||
|
GstClockTime *times;
|
||||||
|
GstClockID clockid;
|
||||||
|
|
||||||
gint pre_count;
|
gint pre_count;
|
||||||
gint post_count;
|
gint post_count;
|
||||||
};
|
};
|
||||||
|
@ -679,25 +706,25 @@ gst_clock_class_init (GstClockClass * klass)
|
||||||
static void
|
static void
|
||||||
gst_clock_init (GstClock * clock)
|
gst_clock_init (GstClock * clock)
|
||||||
{
|
{
|
||||||
clock->last_time = 0;
|
GstClockPrivate *priv;
|
||||||
clock->entries = NULL;
|
|
||||||
g_cond_init (&clock->entries_changed);
|
|
||||||
|
|
||||||
clock->priv =
|
clock->priv = priv =
|
||||||
G_TYPE_INSTANCE_GET_PRIVATE (clock, GST_TYPE_CLOCK, GstClockPrivate);
|
G_TYPE_INSTANCE_GET_PRIVATE (clock, GST_TYPE_CLOCK, GstClockPrivate);
|
||||||
|
|
||||||
clock->internal_calibration = 0;
|
priv->last_time = 0;
|
||||||
clock->external_calibration = 0;
|
|
||||||
clock->rate_numerator = 1;
|
|
||||||
clock->rate_denominator = 1;
|
|
||||||
|
|
||||||
g_mutex_init (&clock->slave_lock);
|
priv->internal_calibration = 0;
|
||||||
clock->window_size = DEFAULT_WINDOW_SIZE;
|
priv->external_calibration = 0;
|
||||||
clock->window_threshold = DEFAULT_WINDOW_THRESHOLD;
|
priv->rate_numerator = 1;
|
||||||
clock->filling = TRUE;
|
priv->rate_denominator = 1;
|
||||||
clock->time_index = 0;
|
|
||||||
clock->timeout = DEFAULT_TIMEOUT;
|
g_mutex_init (&priv->slave_lock);
|
||||||
clock->times = g_new0 (GstClockTime, 4 * clock->window_size);
|
priv->window_size = DEFAULT_WINDOW_SIZE;
|
||||||
|
priv->window_threshold = DEFAULT_WINDOW_THRESHOLD;
|
||||||
|
priv->filling = TRUE;
|
||||||
|
priv->time_index = 0;
|
||||||
|
priv->timeout = DEFAULT_TIMEOUT;
|
||||||
|
priv->times = g_new0 (GstClockTime, 4 * priv->window_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -707,7 +734,7 @@ gst_clock_dispose (GObject * object)
|
||||||
GstClock **master_p;
|
GstClock **master_p;
|
||||||
|
|
||||||
GST_OBJECT_LOCK (clock);
|
GST_OBJECT_LOCK (clock);
|
||||||
master_p = &clock->master;
|
master_p = &clock->priv->master;
|
||||||
gst_object_replace ((GstObject **) master_p, NULL);
|
gst_object_replace ((GstObject **) master_p, NULL);
|
||||||
GST_OBJECT_UNLOCK (clock);
|
GST_OBJECT_UNLOCK (clock);
|
||||||
|
|
||||||
|
@ -720,17 +747,16 @@ gst_clock_finalize (GObject * object)
|
||||||
GstClock *clock = GST_CLOCK (object);
|
GstClock *clock = GST_CLOCK (object);
|
||||||
|
|
||||||
GST_CLOCK_SLAVE_LOCK (clock);
|
GST_CLOCK_SLAVE_LOCK (clock);
|
||||||
if (clock->clockid) {
|
if (clock->priv->clockid) {
|
||||||
gst_clock_id_unschedule (clock->clockid);
|
gst_clock_id_unschedule (clock->priv->clockid);
|
||||||
gst_clock_id_unref (clock->clockid);
|
gst_clock_id_unref (clock->priv->clockid);
|
||||||
clock->clockid = NULL;
|
clock->priv->clockid = NULL;
|
||||||
}
|
}
|
||||||
g_free (clock->times);
|
g_free (clock->priv->times);
|
||||||
clock->times = NULL;
|
clock->priv->times = NULL;
|
||||||
GST_CLOCK_SLAVE_UNLOCK (clock);
|
GST_CLOCK_SLAVE_UNLOCK (clock);
|
||||||
|
|
||||||
g_cond_clear (&clock->entries_changed);
|
g_mutex_clear (&clock->priv->slave_lock);
|
||||||
g_mutex_clear (&clock->slave_lock);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
@ -751,18 +777,20 @@ gst_clock_finalize (GObject * object)
|
||||||
GstClockTime
|
GstClockTime
|
||||||
gst_clock_set_resolution (GstClock * clock, GstClockTime resolution)
|
gst_clock_set_resolution (GstClock * clock, GstClockTime resolution)
|
||||||
{
|
{
|
||||||
|
GstClockPrivate *priv;
|
||||||
GstClockClass *cclass;
|
GstClockClass *cclass;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_CLOCK (clock), 0);
|
g_return_val_if_fail (GST_IS_CLOCK (clock), 0);
|
||||||
g_return_val_if_fail (resolution != 0, 0);
|
g_return_val_if_fail (resolution != 0, 0);
|
||||||
|
|
||||||
cclass = GST_CLOCK_GET_CLASS (clock);
|
cclass = GST_CLOCK_GET_CLASS (clock);
|
||||||
|
priv = clock->priv;
|
||||||
|
|
||||||
if (cclass->change_resolution)
|
if (cclass->change_resolution)
|
||||||
clock->resolution =
|
priv->resolution =
|
||||||
cclass->change_resolution (clock, clock->resolution, resolution);
|
cclass->change_resolution (clock, priv->resolution, resolution);
|
||||||
|
|
||||||
return clock->resolution;
|
return priv->resolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -809,12 +837,13 @@ GstClockTime
|
||||||
gst_clock_adjust_unlocked (GstClock * clock, GstClockTime internal)
|
gst_clock_adjust_unlocked (GstClock * clock, GstClockTime internal)
|
||||||
{
|
{
|
||||||
GstClockTime ret, cinternal, cexternal, cnum, cdenom;
|
GstClockTime ret, cinternal, cexternal, cnum, cdenom;
|
||||||
|
GstClockPrivate *priv = clock->priv;
|
||||||
|
|
||||||
/* get calibration values for readability */
|
/* get calibration values for readability */
|
||||||
cinternal = clock->internal_calibration;
|
cinternal = priv->internal_calibration;
|
||||||
cexternal = clock->external_calibration;
|
cexternal = priv->external_calibration;
|
||||||
cnum = clock->rate_numerator;
|
cnum = priv->rate_numerator;
|
||||||
cdenom = clock->rate_denominator;
|
cdenom = priv->rate_denominator;
|
||||||
|
|
||||||
/* avoid divide by 0 */
|
/* avoid divide by 0 */
|
||||||
if (G_UNLIKELY (cdenom == 0))
|
if (G_UNLIKELY (cdenom == 0))
|
||||||
|
@ -841,9 +870,9 @@ gst_clock_adjust_unlocked (GstClock * clock, GstClockTime internal)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure the time is increasing */
|
/* make sure the time is increasing */
|
||||||
clock->last_time = MAX (ret, clock->last_time);
|
priv->last_time = MAX (ret, priv->last_time);
|
||||||
|
|
||||||
return clock->last_time;
|
return priv->last_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -866,12 +895,13 @@ GstClockTime
|
||||||
gst_clock_unadjust_unlocked (GstClock * clock, GstClockTime external)
|
gst_clock_unadjust_unlocked (GstClock * clock, GstClockTime external)
|
||||||
{
|
{
|
||||||
GstClockTime ret, cinternal, cexternal, cnum, cdenom;
|
GstClockTime ret, cinternal, cexternal, cnum, cdenom;
|
||||||
|
GstClockPrivate *priv = clock->priv;
|
||||||
|
|
||||||
/* get calibration values for readability */
|
/* get calibration values for readability */
|
||||||
cinternal = clock->internal_calibration;
|
cinternal = priv->internal_calibration;
|
||||||
cexternal = clock->external_calibration;
|
cexternal = priv->external_calibration;
|
||||||
cnum = clock->rate_numerator;
|
cnum = priv->rate_numerator;
|
||||||
cdenom = clock->rate_denominator;
|
cdenom = priv->rate_denominator;
|
||||||
|
|
||||||
/* avoid divide by 0 */
|
/* avoid divide by 0 */
|
||||||
if (G_UNLIKELY (cnum == 0))
|
if (G_UNLIKELY (cnum == 0))
|
||||||
|
@ -1008,10 +1038,14 @@ void
|
||||||
gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
|
gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
|
||||||
external, GstClockTime rate_num, GstClockTime rate_denom)
|
external, GstClockTime rate_num, GstClockTime rate_denom)
|
||||||
{
|
{
|
||||||
|
GstClockPrivate *priv;
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_CLOCK (clock));
|
g_return_if_fail (GST_IS_CLOCK (clock));
|
||||||
g_return_if_fail (rate_num != GST_CLOCK_TIME_NONE);
|
g_return_if_fail (rate_num != GST_CLOCK_TIME_NONE);
|
||||||
g_return_if_fail (rate_denom > 0 && rate_denom != GST_CLOCK_TIME_NONE);
|
g_return_if_fail (rate_denom > 0 && rate_denom != GST_CLOCK_TIME_NONE);
|
||||||
|
|
||||||
|
priv = clock->priv;
|
||||||
|
|
||||||
write_seqlock (clock);
|
write_seqlock (clock);
|
||||||
GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
|
GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock,
|
||||||
"internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT " %"
|
"internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT " %"
|
||||||
|
@ -1019,10 +1053,10 @@ gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
|
||||||
GST_TIME_ARGS (external), rate_num, rate_denom,
|
GST_TIME_ARGS (external), rate_num, rate_denom,
|
||||||
gst_guint64_to_gdouble (rate_num) / gst_guint64_to_gdouble (rate_denom));
|
gst_guint64_to_gdouble (rate_num) / gst_guint64_to_gdouble (rate_denom));
|
||||||
|
|
||||||
clock->internal_calibration = internal;
|
priv->internal_calibration = internal;
|
||||||
clock->external_calibration = external;
|
priv->external_calibration = external;
|
||||||
clock->rate_numerator = rate_num;
|
priv->rate_numerator = rate_num;
|
||||||
clock->rate_denominator = rate_denom;
|
priv->rate_denominator = rate_denom;
|
||||||
write_sequnlock (clock);
|
write_sequnlock (clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1047,19 +1081,22 @@ gst_clock_get_calibration (GstClock * clock, GstClockTime * internal,
|
||||||
GstClockTime * external, GstClockTime * rate_num, GstClockTime * rate_denom)
|
GstClockTime * external, GstClockTime * rate_num, GstClockTime * rate_denom)
|
||||||
{
|
{
|
||||||
gint seq;
|
gint seq;
|
||||||
|
GstClockPrivate *priv;
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_CLOCK (clock));
|
g_return_if_fail (GST_IS_CLOCK (clock));
|
||||||
|
|
||||||
|
priv = clock->priv;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
seq = read_seqbegin (clock);
|
seq = read_seqbegin (clock);
|
||||||
if (rate_num)
|
if (rate_num)
|
||||||
*rate_num = clock->rate_numerator;
|
*rate_num = priv->rate_numerator;
|
||||||
if (rate_denom)
|
if (rate_denom)
|
||||||
*rate_denom = clock->rate_denominator;
|
*rate_denom = priv->rate_denominator;
|
||||||
if (external)
|
if (external)
|
||||||
*external = clock->external_calibration;
|
*external = priv->external_calibration;
|
||||||
if (internal)
|
if (internal)
|
||||||
*internal = clock->internal_calibration;
|
*internal = priv->internal_calibration;
|
||||||
} while (read_seqretry (clock, seq));
|
} while (read_seqretry (clock, seq));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1113,6 +1150,7 @@ gboolean
|
||||||
gst_clock_set_master (GstClock * clock, GstClock * master)
|
gst_clock_set_master (GstClock * clock, GstClock * master)
|
||||||
{
|
{
|
||||||
GstClock **master_p;
|
GstClock **master_p;
|
||||||
|
GstClockPrivate *priv;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
|
g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
|
||||||
g_return_val_if_fail (master != clock, FALSE);
|
g_return_val_if_fail (master != clock, FALSE);
|
||||||
|
@ -1125,27 +1163,29 @@ gst_clock_set_master (GstClock * clock, GstClock * master)
|
||||||
"slaving %p to master clock %p", clock, master);
|
"slaving %p to master clock %p", clock, master);
|
||||||
GST_OBJECT_UNLOCK (clock);
|
GST_OBJECT_UNLOCK (clock);
|
||||||
|
|
||||||
|
priv = clock->priv;
|
||||||
|
|
||||||
GST_CLOCK_SLAVE_LOCK (clock);
|
GST_CLOCK_SLAVE_LOCK (clock);
|
||||||
if (clock->clockid) {
|
if (priv->clockid) {
|
||||||
gst_clock_id_unschedule (clock->clockid);
|
gst_clock_id_unschedule (priv->clockid);
|
||||||
gst_clock_id_unref (clock->clockid);
|
gst_clock_id_unref (priv->clockid);
|
||||||
clock->clockid = NULL;
|
priv->clockid = NULL;
|
||||||
}
|
}
|
||||||
if (master) {
|
if (master) {
|
||||||
clock->filling = TRUE;
|
priv->filling = TRUE;
|
||||||
clock->time_index = 0;
|
priv->time_index = 0;
|
||||||
/* use the master periodic id to schedule sampling and
|
/* use the master periodic id to schedule sampling and
|
||||||
* clock calibration. */
|
* clock calibration. */
|
||||||
clock->clockid = gst_clock_new_periodic_id (master,
|
priv->clockid = gst_clock_new_periodic_id (master,
|
||||||
gst_clock_get_time (master), clock->timeout);
|
gst_clock_get_time (master), priv->timeout);
|
||||||
gst_clock_id_wait_async_full (clock->clockid,
|
gst_clock_id_wait_async_full (priv->clockid,
|
||||||
(GstClockCallback) gst_clock_slave_callback,
|
(GstClockCallback) gst_clock_slave_callback,
|
||||||
gst_object_ref (clock), (GDestroyNotify) gst_object_unref);
|
gst_object_ref (clock), (GDestroyNotify) gst_object_unref);
|
||||||
}
|
}
|
||||||
GST_CLOCK_SLAVE_UNLOCK (clock);
|
GST_CLOCK_SLAVE_UNLOCK (clock);
|
||||||
|
|
||||||
GST_OBJECT_LOCK (clock);
|
GST_OBJECT_LOCK (clock);
|
||||||
master_p = &clock->master;
|
master_p = &priv->master;
|
||||||
gst_object_replace ((GstObject **) master_p, (GstObject *) master);
|
gst_object_replace ((GstObject **) master_p, (GstObject *) master);
|
||||||
GST_OBJECT_UNLOCK (clock);
|
GST_OBJECT_UNLOCK (clock);
|
||||||
|
|
||||||
|
@ -1177,12 +1217,15 @@ GstClock *
|
||||||
gst_clock_get_master (GstClock * clock)
|
gst_clock_get_master (GstClock * clock)
|
||||||
{
|
{
|
||||||
GstClock *result = NULL;
|
GstClock *result = NULL;
|
||||||
|
GstClockPrivate *priv;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
|
g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
|
||||||
|
|
||||||
|
priv = clock->priv;
|
||||||
|
|
||||||
GST_OBJECT_LOCK (clock);
|
GST_OBJECT_LOCK (clock);
|
||||||
if (clock->master)
|
if (priv->master)
|
||||||
result = gst_object_ref (clock->master);
|
result = gst_object_ref (priv->master);
|
||||||
GST_OBJECT_UNLOCK (clock);
|
GST_OBJECT_UNLOCK (clock);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1202,12 +1245,15 @@ do_linear_regression (GstClock * clock, GstClockTime * m_num,
|
||||||
GstClockTime *x, *y;
|
GstClockTime *x, *y;
|
||||||
gint i, j;
|
gint i, j;
|
||||||
guint n;
|
guint n;
|
||||||
|
GstClockPrivate *priv;
|
||||||
|
|
||||||
xbar = ybar = sxx = syy = sxy = 0;
|
xbar = ybar = sxx = syy = sxy = 0;
|
||||||
|
|
||||||
x = clock->times;
|
priv = clock->priv;
|
||||||
y = clock->times + 2;
|
|
||||||
n = clock->filling ? clock->time_index : clock->window_size;
|
x = priv->times;
|
||||||
|
y = priv->times + 2;
|
||||||
|
n = priv->filling ? priv->time_index : priv->window_size;
|
||||||
|
|
||||||
#ifdef DEBUGGING_ENABLED
|
#ifdef DEBUGGING_ENABLED
|
||||||
GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "doing regression on:");
|
GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "doing regression on:");
|
||||||
|
@ -1229,8 +1275,8 @@ do_linear_regression (GstClock * clock, GstClockTime * m_num,
|
||||||
ymin);
|
ymin);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
newx = clock->times + 1;
|
newx = priv->times + 1;
|
||||||
newy = clock->times + 3;
|
newy = priv->times + 3;
|
||||||
|
|
||||||
/* strip off unnecessary bits of precision */
|
/* strip off unnecessary bits of precision */
|
||||||
for (i = j = 0; i < n; i++, j += 4) {
|
for (i = j = 0; i < n; i++, j += 4) {
|
||||||
|
@ -1339,27 +1385,29 @@ gst_clock_add_observation (GstClock * clock, GstClockTime slave,
|
||||||
GstClockTime master, gdouble * r_squared)
|
GstClockTime master, gdouble * r_squared)
|
||||||
{
|
{
|
||||||
GstClockTime m_num, m_denom, b, xbase;
|
GstClockTime m_num, m_denom, b, xbase;
|
||||||
|
GstClockPrivate *priv;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
|
g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
|
||||||
g_return_val_if_fail (r_squared != NULL, FALSE);
|
g_return_val_if_fail (r_squared != NULL, FALSE);
|
||||||
|
|
||||||
|
priv = clock->priv;
|
||||||
|
|
||||||
GST_CLOCK_SLAVE_LOCK (clock);
|
GST_CLOCK_SLAVE_LOCK (clock);
|
||||||
|
|
||||||
GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock,
|
GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock,
|
||||||
"adding observation slave %" GST_TIME_FORMAT ", master %" GST_TIME_FORMAT,
|
"adding observation slave %" GST_TIME_FORMAT ", master %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (slave), GST_TIME_ARGS (master));
|
GST_TIME_ARGS (slave), GST_TIME_ARGS (master));
|
||||||
|
|
||||||
clock->times[(4 * clock->time_index)] = slave;
|
priv->times[(4 * priv->time_index)] = slave;
|
||||||
clock->times[(4 * clock->time_index) + 2] = master;
|
priv->times[(4 * priv->time_index) + 2] = master;
|
||||||
|
|
||||||
clock->time_index++;
|
priv->time_index++;
|
||||||
if (G_UNLIKELY (clock->time_index == clock->window_size)) {
|
if (G_UNLIKELY (priv->time_index == priv->window_size)) {
|
||||||
clock->filling = FALSE;
|
priv->filling = FALSE;
|
||||||
clock->time_index = 0;
|
priv->time_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (G_UNLIKELY (clock->filling
|
if (G_UNLIKELY (priv->filling && priv->time_index < priv->window_threshold))
|
||||||
&& clock->time_index < clock->window_threshold))
|
|
||||||
goto filling;
|
goto filling;
|
||||||
|
|
||||||
if (!do_linear_regression (clock, &m_num, &m_denom, &b, &xbase, r_squared))
|
if (!do_linear_regression (clock, &m_num, &m_denom, &b, &xbase, r_squared))
|
||||||
|
@ -1389,36 +1437,47 @@ invalid:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_clock_set_timeout (GstClock * clock, GstClockTime timeout)
|
||||||
|
{
|
||||||
|
clock->priv->timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstClockTime
|
||||||
|
gst_clock_get_timeout (GstClock * clock)
|
||||||
|
{
|
||||||
|
return clock->priv->timeout;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_clock_set_property (GObject * object, guint prop_id,
|
gst_clock_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * pspec)
|
const GValue * value, GParamSpec * pspec)
|
||||||
{
|
{
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
|
GstClockPrivate *priv;
|
||||||
|
|
||||||
clock = GST_CLOCK (object);
|
clock = GST_CLOCK (object);
|
||||||
|
priv = clock->priv;
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_WINDOW_SIZE:
|
case PROP_WINDOW_SIZE:
|
||||||
GST_CLOCK_SLAVE_LOCK (clock);
|
GST_CLOCK_SLAVE_LOCK (clock);
|
||||||
clock->window_size = g_value_get_int (value);
|
priv->window_size = g_value_get_int (value);
|
||||||
clock->window_threshold =
|
priv->window_threshold = MIN (priv->window_threshold, priv->window_size);
|
||||||
MIN (clock->window_threshold, clock->window_size);
|
priv->times = g_renew (GstClockTime, priv->times, 4 * priv->window_size);
|
||||||
clock->times =
|
|
||||||
g_renew (GstClockTime, clock->times, 4 * clock->window_size);
|
|
||||||
/* restart calibration */
|
/* restart calibration */
|
||||||
clock->filling = TRUE;
|
priv->filling = TRUE;
|
||||||
clock->time_index = 0;
|
priv->time_index = 0;
|
||||||
GST_CLOCK_SLAVE_UNLOCK (clock);
|
GST_CLOCK_SLAVE_UNLOCK (clock);
|
||||||
break;
|
break;
|
||||||
case PROP_WINDOW_THRESHOLD:
|
case PROP_WINDOW_THRESHOLD:
|
||||||
GST_CLOCK_SLAVE_LOCK (clock);
|
GST_CLOCK_SLAVE_LOCK (clock);
|
||||||
clock->window_threshold =
|
priv->window_threshold = MIN (g_value_get_int (value), priv->window_size);
|
||||||
MIN (g_value_get_int (value), clock->window_size);
|
|
||||||
GST_CLOCK_SLAVE_UNLOCK (clock);
|
GST_CLOCK_SLAVE_UNLOCK (clock);
|
||||||
break;
|
break;
|
||||||
case PROP_TIMEOUT:
|
case PROP_TIMEOUT:
|
||||||
GST_CLOCK_SLAVE_LOCK (clock);
|
GST_CLOCK_SLAVE_LOCK (clock);
|
||||||
clock->timeout = g_value_get_uint64 (value);
|
priv->timeout = g_value_get_uint64 (value);
|
||||||
GST_CLOCK_SLAVE_UNLOCK (clock);
|
GST_CLOCK_SLAVE_UNLOCK (clock);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1432,23 +1491,25 @@ gst_clock_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec)
|
GValue * value, GParamSpec * pspec)
|
||||||
{
|
{
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
|
GstClockPrivate *priv;
|
||||||
|
|
||||||
clock = GST_CLOCK (object);
|
clock = GST_CLOCK (object);
|
||||||
|
priv = clock->priv;
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_WINDOW_SIZE:
|
case PROP_WINDOW_SIZE:
|
||||||
GST_CLOCK_SLAVE_LOCK (clock);
|
GST_CLOCK_SLAVE_LOCK (clock);
|
||||||
g_value_set_int (value, clock->window_size);
|
g_value_set_int (value, priv->window_size);
|
||||||
GST_CLOCK_SLAVE_UNLOCK (clock);
|
GST_CLOCK_SLAVE_UNLOCK (clock);
|
||||||
break;
|
break;
|
||||||
case PROP_WINDOW_THRESHOLD:
|
case PROP_WINDOW_THRESHOLD:
|
||||||
GST_CLOCK_SLAVE_LOCK (clock);
|
GST_CLOCK_SLAVE_LOCK (clock);
|
||||||
g_value_set_int (value, clock->window_threshold);
|
g_value_set_int (value, priv->window_threshold);
|
||||||
GST_CLOCK_SLAVE_UNLOCK (clock);
|
GST_CLOCK_SLAVE_UNLOCK (clock);
|
||||||
break;
|
break;
|
||||||
case PROP_TIMEOUT:
|
case PROP_TIMEOUT:
|
||||||
GST_CLOCK_SLAVE_LOCK (clock);
|
GST_CLOCK_SLAVE_LOCK (clock);
|
||||||
g_value_set_uint64 (value, clock->timeout);
|
g_value_set_uint64 (value, priv->timeout);
|
||||||
GST_CLOCK_SLAVE_UNLOCK (clock);
|
GST_CLOCK_SLAVE_UNLOCK (clock);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -35,9 +35,6 @@ G_BEGIN_DECLS
|
||||||
#define GST_CLOCK_GET_CLASS(clock) (G_TYPE_INSTANCE_GET_CLASS ((clock), GST_TYPE_CLOCK, GstClockClass))
|
#define GST_CLOCK_GET_CLASS(clock) (G_TYPE_INSTANCE_GET_CLASS ((clock), GST_TYPE_CLOCK, GstClockClass))
|
||||||
#define GST_CLOCK_CAST(clock) ((GstClock*)(clock))
|
#define GST_CLOCK_CAST(clock) ((GstClock*)(clock))
|
||||||
|
|
||||||
#define GST_CLOCK_SLAVE_LOCK(clock) g_mutex_lock (&GST_CLOCK_CAST (clock)->slave_lock)
|
|
||||||
#define GST_CLOCK_SLAVE_UNLOCK(clock) g_mutex_unlock (&GST_CLOCK_CAST (clock)->slave_lock)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstClockTime:
|
* GstClockTime:
|
||||||
*
|
*
|
||||||
|
@ -401,38 +398,6 @@ typedef enum {
|
||||||
*/
|
*/
|
||||||
#define GST_CLOCK_FLAGS(clock) GST_OBJECT_FLAGS(clock)
|
#define GST_CLOCK_FLAGS(clock) GST_OBJECT_FLAGS(clock)
|
||||||
|
|
||||||
/**
|
|
||||||
* GST_CLOCK_GET_COND:
|
|
||||||
* @clock: the clock to query
|
|
||||||
*
|
|
||||||
* Gets the #GCond that gets signalled when the entries of the clock
|
|
||||||
* changed.
|
|
||||||
*/
|
|
||||||
#define GST_CLOCK_GET_COND(clock) (&GST_CLOCK_CAST(clock)->entries_changed)
|
|
||||||
/**
|
|
||||||
* GST_CLOCK_WAIT:
|
|
||||||
* @clock: the clock to wait on
|
|
||||||
*
|
|
||||||
* Wait on the clock until the entries changed.
|
|
||||||
*/
|
|
||||||
#define GST_CLOCK_WAIT(clock) g_cond_wait(GST_CLOCK_GET_COND(clock),GST_OBJECT_GET_LOCK(clock))
|
|
||||||
/**
|
|
||||||
* GST_CLOCK_TIMED_WAIT:
|
|
||||||
* @clock: the clock to wait on
|
|
||||||
* @tv: a #GTimeVal to wait.
|
|
||||||
*
|
|
||||||
* Wait on the clock until the entries changed or the specified timeout
|
|
||||||
* occurred.
|
|
||||||
*/
|
|
||||||
#define GST_CLOCK_TIMED_WAIT(clock,tv) g_cond_timed_wait(GST_CLOCK_GET_COND(clock),GST_OBJECT_GET_LOCK(clock),tv)
|
|
||||||
/**
|
|
||||||
* GST_CLOCK_BROADCAST:
|
|
||||||
* @clock: the clock to broadcast
|
|
||||||
*
|
|
||||||
* Signal that the entries in the clock have changed.
|
|
||||||
*/
|
|
||||||
#define GST_CLOCK_BROADCAST(clock) g_cond_broadcast(GST_CLOCK_GET_COND(clock))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstClock:
|
* GstClock:
|
||||||
*
|
*
|
||||||
|
@ -442,32 +407,6 @@ typedef enum {
|
||||||
struct _GstClock {
|
struct _GstClock {
|
||||||
GstObject object;
|
GstObject object;
|
||||||
|
|
||||||
GMutex slave_lock; /* order: SLAVE_LOCK, OBJECT_LOCK */
|
|
||||||
|
|
||||||
/*< protected >*/ /* with LOCK */
|
|
||||||
GstClockTime internal_calibration;
|
|
||||||
GstClockTime external_calibration;
|
|
||||||
GstClockTime rate_numerator;
|
|
||||||
GstClockTime rate_denominator;
|
|
||||||
GstClockTime last_time;
|
|
||||||
GList *entries;
|
|
||||||
GCond entries_changed;
|
|
||||||
|
|
||||||
/*< private >*/ /* with LOCK */
|
|
||||||
GstClockTime resolution;
|
|
||||||
|
|
||||||
/* for master/slave clocks */
|
|
||||||
GstClock *master;
|
|
||||||
|
|
||||||
/* with SLAVE_LOCK */
|
|
||||||
gboolean filling;
|
|
||||||
gint window_size;
|
|
||||||
gint window_threshold;
|
|
||||||
gint time_index;
|
|
||||||
GstClockTime timeout;
|
|
||||||
GstClockTime *times;
|
|
||||||
GstClockID clockid;
|
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
GstClockPrivate *priv;
|
GstClockPrivate *priv;
|
||||||
|
|
||||||
|
@ -531,6 +470,11 @@ void gst_clock_get_calibration (GstClock *clock, GstClo
|
||||||
/* master/slave clocks */
|
/* master/slave clocks */
|
||||||
gboolean gst_clock_set_master (GstClock *clock, GstClock *master);
|
gboolean gst_clock_set_master (GstClock *clock, GstClock *master);
|
||||||
GstClock* gst_clock_get_master (GstClock *clock);
|
GstClock* gst_clock_get_master (GstClock *clock);
|
||||||
|
|
||||||
|
void gst_clock_set_timeout (GstClock *clock,
|
||||||
|
GstClockTime timeout);
|
||||||
|
GstClockTime gst_clock_get_timeout (GstClock *clock);
|
||||||
|
|
||||||
gboolean gst_clock_add_observation (GstClock *clock, GstClockTime slave,
|
gboolean gst_clock_add_observation (GstClock *clock, GstClockTime slave,
|
||||||
GstClockTime master, gdouble *r_squared);
|
GstClockTime master, gdouble *r_squared);
|
||||||
|
|
||||||
|
|
|
@ -63,11 +63,18 @@
|
||||||
/* Define this to get some extra debug about jitter from each clock_wait */
|
/* Define this to get some extra debug about jitter from each clock_wait */
|
||||||
#undef WAIT_DEBUGGING
|
#undef WAIT_DEBUGGING
|
||||||
|
|
||||||
|
#define GST_SYSTEM_CLOCK_GET_COND(clock) (&GST_SYSTEM_CLOCK_CAST(clock)->priv->entries_changed)
|
||||||
|
#define GST_SYSTEM_CLOCK_WAIT(clock) g_cond_wait(GST_SYSTEM_CLOCK_GET_COND(clock),GST_OBJECT_GET_LOCK(clock))
|
||||||
|
#define GST_SYSTEM_CLOCK_TIMED_WAIT(clock,tv) g_cond_timed_wait(GST_SYSTEM_CLOCK_GET_COND(clock),GST_OBJECT_GET_LOCK(clock),tv)
|
||||||
|
#define GST_SYSTEM_CLOCK_BROADCAST(clock) g_cond_broadcast(GST_SYSTEM_CLOCK_GET_COND(clock))
|
||||||
|
|
||||||
struct _GstSystemClockPrivate
|
struct _GstSystemClockPrivate
|
||||||
{
|
{
|
||||||
GThread *thread; /* thread for async notify */
|
GThread *thread; /* thread for async notify */
|
||||||
gboolean stopping;
|
gboolean stopping;
|
||||||
|
|
||||||
|
GList *entries;
|
||||||
|
GCond entries_changed;
|
||||||
|
|
||||||
GstClockType clock_type;
|
GstClockType clock_type;
|
||||||
GstPoll *timer;
|
GstPoll *timer;
|
||||||
|
@ -163,23 +170,28 @@ gst_system_clock_class_init (GstSystemClockClass * klass)
|
||||||
static void
|
static void
|
||||||
gst_system_clock_init (GstSystemClock * clock)
|
gst_system_clock_init (GstSystemClock * clock)
|
||||||
{
|
{
|
||||||
|
GstSystemClockPrivate *priv;
|
||||||
|
|
||||||
GST_OBJECT_FLAG_SET (clock,
|
GST_OBJECT_FLAG_SET (clock,
|
||||||
GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC |
|
GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC |
|
||||||
GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC |
|
GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC |
|
||||||
GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC |
|
GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC |
|
||||||
GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC);
|
GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC);
|
||||||
|
|
||||||
clock->priv = GST_SYSTEM_CLOCK_GET_PRIVATE (clock);
|
clock->priv = priv = GST_SYSTEM_CLOCK_GET_PRIVATE (clock);
|
||||||
|
|
||||||
clock->priv->clock_type = DEFAULT_CLOCK_TYPE;
|
priv->clock_type = DEFAULT_CLOCK_TYPE;
|
||||||
clock->priv->timer = gst_poll_new_timer ();
|
priv->timer = gst_poll_new_timer ();
|
||||||
|
|
||||||
|
priv->entries = NULL;
|
||||||
|
g_cond_init (&priv->entries_changed);
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
QueryPerformanceFrequency (&clock->priv->frequency);
|
QueryPerformanceFrequency (&priv->frequency);
|
||||||
/* can be 0 if the hardware does not have hardware support */
|
/* can be 0 if the hardware does not have hardware support */
|
||||||
if (clock->priv->frequency.QuadPart != 0)
|
if (priv->frequency.QuadPart != 0)
|
||||||
/* we take a base time so that time starts from 0 to ease debugging */
|
/* we take a base time so that time starts from 0 to ease debugging */
|
||||||
QueryPerformanceCounter (&clock->priv->start);
|
QueryPerformanceCounter (&priv->start);
|
||||||
#endif /* G_OS_WIN32 */
|
#endif /* G_OS_WIN32 */
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -195,32 +207,34 @@ gst_system_clock_dispose (GObject * object)
|
||||||
{
|
{
|
||||||
GstClock *clock = (GstClock *) object;
|
GstClock *clock = (GstClock *) object;
|
||||||
GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
|
GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
|
||||||
|
GstSystemClockPrivate *priv = sysclock->priv;
|
||||||
GList *entries;
|
GList *entries;
|
||||||
|
|
||||||
/* else we have to stop the thread */
|
/* else we have to stop the thread */
|
||||||
GST_OBJECT_LOCK (clock);
|
GST_OBJECT_LOCK (clock);
|
||||||
sysclock->priv->stopping = TRUE;
|
priv->stopping = TRUE;
|
||||||
/* unschedule all entries */
|
/* unschedule all entries */
|
||||||
for (entries = clock->entries; entries; entries = g_list_next (entries)) {
|
for (entries = priv->entries; entries; entries = g_list_next (entries)) {
|
||||||
GstClockEntry *entry = (GstClockEntry *) entries->data;
|
GstClockEntry *entry = (GstClockEntry *) entries->data;
|
||||||
|
|
||||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "unscheduling entry %p", entry);
|
GST_CAT_DEBUG (GST_CAT_CLOCK, "unscheduling entry %p", entry);
|
||||||
SET_ENTRY_STATUS (entry, GST_CLOCK_UNSCHEDULED);
|
SET_ENTRY_STATUS (entry, GST_CLOCK_UNSCHEDULED);
|
||||||
}
|
}
|
||||||
GST_CLOCK_BROADCAST (clock);
|
GST_SYSTEM_CLOCK_BROADCAST (clock);
|
||||||
gst_system_clock_add_wakeup (sysclock);
|
gst_system_clock_add_wakeup (sysclock);
|
||||||
GST_OBJECT_UNLOCK (clock);
|
GST_OBJECT_UNLOCK (clock);
|
||||||
|
|
||||||
if (sysclock->priv->thread)
|
if (priv->thread)
|
||||||
g_thread_join (sysclock->priv->thread);
|
g_thread_join (priv->thread);
|
||||||
sysclock->priv->thread = NULL;
|
priv->thread = NULL;
|
||||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "joined thread");
|
GST_CAT_DEBUG (GST_CAT_CLOCK, "joined thread");
|
||||||
|
|
||||||
g_list_foreach (clock->entries, (GFunc) gst_clock_id_unref, NULL);
|
g_list_foreach (priv->entries, (GFunc) gst_clock_id_unref, NULL);
|
||||||
g_list_free (clock->entries);
|
g_list_free (priv->entries);
|
||||||
clock->entries = NULL;
|
priv->entries = NULL;
|
||||||
|
|
||||||
gst_poll_free (sysclock->priv->timer);
|
gst_poll_free (priv->timer);
|
||||||
|
g_cond_clear (&priv->entries_changed);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
|
|
||||||
|
@ -316,7 +330,7 @@ gst_system_clock_remove_wakeup (GstSystemClock * sysclock)
|
||||||
while (!gst_poll_read_control (sysclock->priv->timer)) {
|
while (!gst_poll_read_control (sysclock->priv->timer)) {
|
||||||
g_warning ("gstsystemclock: read control failed, trying again\n");
|
g_warning ("gstsystemclock: read control failed, trying again\n");
|
||||||
}
|
}
|
||||||
GST_CLOCK_BROADCAST (sysclock);
|
GST_SYSTEM_CLOCK_BROADCAST (sysclock);
|
||||||
}
|
}
|
||||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup count %d",
|
GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup count %d",
|
||||||
sysclock->priv->wakeup_count);
|
sysclock->priv->wakeup_count);
|
||||||
|
@ -350,7 +364,7 @@ static void
|
||||||
gst_system_clock_wait_wakeup (GstSystemClock * sysclock)
|
gst_system_clock_wait_wakeup (GstSystemClock * sysclock)
|
||||||
{
|
{
|
||||||
while (sysclock->priv->wakeup_count > 0) {
|
while (sysclock->priv->wakeup_count > 0) {
|
||||||
GST_CLOCK_WAIT (sysclock);
|
GST_SYSTEM_CLOCK_WAIT (sysclock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,38 +384,39 @@ static void
|
||||||
gst_system_clock_async_thread (GstClock * clock)
|
gst_system_clock_async_thread (GstClock * clock)
|
||||||
{
|
{
|
||||||
GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
|
GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
|
||||||
|
GstSystemClockPrivate *priv = sysclock->priv;
|
||||||
|
|
||||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "enter system clock thread");
|
GST_CAT_DEBUG (GST_CAT_CLOCK, "enter system clock thread");
|
||||||
GST_OBJECT_LOCK (clock);
|
GST_OBJECT_LOCK (clock);
|
||||||
/* signal spinup */
|
/* signal spinup */
|
||||||
GST_CLOCK_BROADCAST (clock);
|
GST_SYSTEM_CLOCK_BROADCAST (clock);
|
||||||
/* now enter our (almost) infinite loop */
|
/* now enter our (almost) infinite loop */
|
||||||
while (!sysclock->priv->stopping) {
|
while (!priv->stopping) {
|
||||||
GstClockEntry *entry;
|
GstClockEntry *entry;
|
||||||
GstClockTime requested;
|
GstClockTime requested;
|
||||||
GstClockReturn res;
|
GstClockReturn res;
|
||||||
|
|
||||||
/* check if something to be done */
|
/* check if something to be done */
|
||||||
while (clock->entries == NULL) {
|
while (priv->entries == NULL) {
|
||||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "no clock entries, waiting..");
|
GST_CAT_DEBUG (GST_CAT_CLOCK, "no clock entries, waiting..");
|
||||||
/* wait for work to do */
|
/* wait for work to do */
|
||||||
GST_CLOCK_WAIT (clock);
|
GST_SYSTEM_CLOCK_WAIT (clock);
|
||||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "got signal");
|
GST_CAT_DEBUG (GST_CAT_CLOCK, "got signal");
|
||||||
/* clock was stopping, exit */
|
/* clock was stopping, exit */
|
||||||
if (sysclock->priv->stopping)
|
if (priv->stopping)
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* see if we have a pending wakeup because the order of the list
|
/* see if we have a pending wakeup because the order of the list
|
||||||
* changed. */
|
* changed. */
|
||||||
if (sysclock->priv->async_wakeup) {
|
if (priv->async_wakeup) {
|
||||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "clear async wakeup");
|
GST_CAT_DEBUG (GST_CAT_CLOCK, "clear async wakeup");
|
||||||
gst_system_clock_remove_wakeup (sysclock);
|
gst_system_clock_remove_wakeup (sysclock);
|
||||||
sysclock->priv->async_wakeup = FALSE;
|
priv->async_wakeup = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pick the next entry */
|
/* pick the next entry */
|
||||||
entry = clock->entries->data;
|
entry = priv->entries->data;
|
||||||
GST_OBJECT_UNLOCK (clock);
|
GST_OBJECT_UNLOCK (clock);
|
||||||
|
|
||||||
requested = entry->time;
|
requested = entry->time;
|
||||||
|
@ -436,8 +451,8 @@ gst_system_clock_async_thread (GstClock * clock)
|
||||||
/* adjust time now */
|
/* adjust time now */
|
||||||
entry->time = requested + entry->interval;
|
entry->time = requested + entry->interval;
|
||||||
/* and resort the list now */
|
/* and resort the list now */
|
||||||
clock->entries =
|
priv->entries =
|
||||||
g_list_sort (clock->entries, gst_clock_id_compare_func);
|
g_list_sort (priv->entries, gst_clock_id_compare_func);
|
||||||
/* and restart */
|
/* and restart */
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
@ -466,12 +481,12 @@ gst_system_clock_async_thread (GstClock * clock)
|
||||||
}
|
}
|
||||||
next_entry:
|
next_entry:
|
||||||
/* we remove the current entry and unref it */
|
/* we remove the current entry and unref it */
|
||||||
clock->entries = g_list_remove (clock->entries, entry);
|
priv->entries = g_list_remove (priv->entries, entry);
|
||||||
gst_clock_id_unref ((GstClockID) entry);
|
gst_clock_id_unref ((GstClockID) entry);
|
||||||
}
|
}
|
||||||
exit:
|
exit:
|
||||||
/* signal exit */
|
/* signal exit */
|
||||||
GST_CLOCK_BROADCAST (clock);
|
GST_SYSTEM_CLOCK_BROADCAST (clock);
|
||||||
GST_OBJECT_UNLOCK (clock);
|
GST_OBJECT_UNLOCK (clock);
|
||||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "exit system clock thread");
|
GST_CAT_DEBUG (GST_CAT_CLOCK, "exit system clock thread");
|
||||||
}
|
}
|
||||||
|
@ -732,18 +747,19 @@ static gboolean
|
||||||
gst_system_clock_start_async (GstSystemClock * clock)
|
gst_system_clock_start_async (GstSystemClock * clock)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
GstSystemClockPrivate *priv = clock->priv;
|
||||||
|
|
||||||
if (G_LIKELY (clock->priv->thread != NULL))
|
if (G_LIKELY (priv->thread != NULL))
|
||||||
return TRUE; /* Thread already running. Nothing to do */
|
return TRUE; /* Thread already running. Nothing to do */
|
||||||
|
|
||||||
clock->priv->thread = g_thread_try_new ("GstSystemClock",
|
priv->thread = g_thread_try_new ("GstSystemClock",
|
||||||
(GThreadFunc) gst_system_clock_async_thread, clock, &error);
|
(GThreadFunc) gst_system_clock_async_thread, clock, &error);
|
||||||
|
|
||||||
if (G_UNLIKELY (error))
|
if (G_UNLIKELY (error))
|
||||||
goto no_thread;
|
goto no_thread;
|
||||||
|
|
||||||
/* wait for it to spin up */
|
/* wait for it to spin up */
|
||||||
GST_CLOCK_WAIT (clock);
|
GST_SYSTEM_CLOCK_WAIT (clock);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
@ -767,9 +783,11 @@ static GstClockReturn
|
||||||
gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
|
gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
|
||||||
{
|
{
|
||||||
GstSystemClock *sysclock;
|
GstSystemClock *sysclock;
|
||||||
|
GstSystemClockPrivate *priv;
|
||||||
GstClockEntry *head;
|
GstClockEntry *head;
|
||||||
|
|
||||||
sysclock = GST_SYSTEM_CLOCK_CAST (clock);
|
sysclock = GST_SYSTEM_CLOCK_CAST (clock);
|
||||||
|
priv = sysclock->priv;
|
||||||
|
|
||||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "adding async entry %p", entry);
|
GST_CAT_DEBUG (GST_CAT_CLOCK, "adding async entry %p", entry);
|
||||||
|
|
||||||
|
@ -781,27 +799,27 @@ gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
|
||||||
if (G_UNLIKELY (GET_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED))
|
if (G_UNLIKELY (GET_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED))
|
||||||
goto was_unscheduled;
|
goto was_unscheduled;
|
||||||
|
|
||||||
if (clock->entries)
|
if (priv->entries)
|
||||||
head = clock->entries->data;
|
head = priv->entries->data;
|
||||||
else
|
else
|
||||||
head = NULL;
|
head = NULL;
|
||||||
|
|
||||||
/* need to take a ref */
|
/* need to take a ref */
|
||||||
gst_clock_id_ref ((GstClockID) entry);
|
gst_clock_id_ref ((GstClockID) entry);
|
||||||
/* insert the entry in sorted order */
|
/* insert the entry in sorted order */
|
||||||
clock->entries = g_list_insert_sorted (clock->entries, entry,
|
priv->entries = g_list_insert_sorted (priv->entries, entry,
|
||||||
gst_clock_id_compare_func);
|
gst_clock_id_compare_func);
|
||||||
|
|
||||||
/* only need to send the signal if the entry was added to the
|
/* only need to send the signal if the entry was added to the
|
||||||
* front, else the thread is just waiting for another entry and
|
* front, else the thread is just waiting for another entry and
|
||||||
* will get to this entry automatically. */
|
* will get to this entry automatically. */
|
||||||
if (clock->entries->data == entry) {
|
if (priv->entries->data == entry) {
|
||||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry added to head %p", head);
|
GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry added to head %p", head);
|
||||||
if (head == NULL) {
|
if (head == NULL) {
|
||||||
/* the list was empty before, signal the cond so that the async thread can
|
/* the list was empty before, signal the cond so that the async thread can
|
||||||
* start taking a look at the queue */
|
* start taking a look at the queue */
|
||||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "first entry, sending signal");
|
GST_CAT_DEBUG (GST_CAT_CLOCK, "first entry, sending signal");
|
||||||
GST_CLOCK_BROADCAST (clock);
|
GST_SYSTEM_CLOCK_BROADCAST (clock);
|
||||||
} else {
|
} else {
|
||||||
GstClockReturn status;
|
GstClockReturn status;
|
||||||
|
|
||||||
|
@ -812,9 +830,9 @@ gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
|
||||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "head entry is busy");
|
GST_CAT_DEBUG (GST_CAT_CLOCK, "head entry is busy");
|
||||||
/* the async thread was waiting for an entry, unlock the wait so that it
|
/* the async thread was waiting for an entry, unlock the wait so that it
|
||||||
* looks at the new head entry instead, we only need to do this once */
|
* looks at the new head entry instead, we only need to do this once */
|
||||||
if (!sysclock->priv->async_wakeup) {
|
if (!priv->async_wakeup) {
|
||||||
GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup async thread");
|
GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup async thread");
|
||||||
sysclock->priv->async_wakeup = TRUE;
|
priv->async_wakeup = TRUE;
|
||||||
gst_system_clock_add_wakeup (sysclock);
|
gst_system_clock_add_wakeup (sysclock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,17 +128,18 @@ static void
|
||||||
gst_net_client_clock_init (GstNetClientClock * self)
|
gst_net_client_clock_init (GstNetClientClock * self)
|
||||||
{
|
{
|
||||||
GstClock *clock = GST_CLOCK_CAST (self);
|
GstClock *clock = GST_CLOCK_CAST (self);
|
||||||
|
GstNetClientClockPrivate *priv;
|
||||||
|
|
||||||
self->priv = GST_NET_CLIENT_CLOCK_GET_PRIVATE (self);
|
self->priv = priv = GST_NET_CLIENT_CLOCK_GET_PRIVATE (self);
|
||||||
|
|
||||||
self->priv->port = DEFAULT_PORT;
|
priv->port = DEFAULT_PORT;
|
||||||
self->priv->address = g_strdup (DEFAULT_ADDRESS);
|
priv->address = g_strdup (DEFAULT_ADDRESS);
|
||||||
|
|
||||||
clock->timeout = DEFAULT_TIMEOUT;
|
gst_clock_set_timeout (clock, DEFAULT_TIMEOUT);
|
||||||
|
|
||||||
self->priv->thread = NULL;
|
priv->thread = NULL;
|
||||||
|
|
||||||
self->priv->servaddr = NULL;
|
priv->servaddr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -224,19 +225,17 @@ gst_net_client_clock_observe_times (GstNetClientClock * self,
|
||||||
|
|
||||||
clock = GST_CLOCK_CAST (self);
|
clock = GST_CLOCK_CAST (self);
|
||||||
|
|
||||||
gst_clock_add_observation (GST_CLOCK (self), local_avg, remote, &r_squared);
|
if (gst_clock_add_observation (GST_CLOCK (self), local_avg, remote,
|
||||||
|
&r_squared)) {
|
||||||
GST_CLOCK_SLAVE_LOCK (self);
|
|
||||||
if (clock->filling) {
|
|
||||||
current_timeout = 0;
|
|
||||||
} else {
|
|
||||||
/* geto formula */
|
/* geto formula */
|
||||||
current_timeout = (1e-3 / (1 - MIN (r_squared, 0.99999))) * GST_SECOND;
|
current_timeout = (1e-3 / (1 - MIN (r_squared, 0.99999))) * GST_SECOND;
|
||||||
current_timeout = MIN (current_timeout, clock->timeout);
|
current_timeout = MIN (current_timeout, gst_clock_get_timeout (clock));
|
||||||
|
} else {
|
||||||
|
current_timeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_INFO ("next timeout: %" GST_TIME_FORMAT, GST_TIME_ARGS (current_timeout));
|
GST_INFO ("next timeout: %" GST_TIME_FORMAT, GST_TIME_ARGS (current_timeout));
|
||||||
self->priv->timeout_expiration = gst_util_get_timestamp () + current_timeout;
|
self->priv->timeout_expiration = gst_util_get_timestamp () + current_timeout;
|
||||||
GST_CLOCK_SLAVE_UNLOCK (clock);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -371,7 +370,7 @@ gst_net_client_clock_thread (gpointer data)
|
||||||
|
|
||||||
/* reset timeout (but are expecting a response sooner anyway) */
|
/* reset timeout (but are expecting a response sooner anyway) */
|
||||||
self->priv->timeout_expiration =
|
self->priv->timeout_expiration =
|
||||||
gst_util_get_timestamp () + clock->timeout;
|
gst_util_get_timestamp () + gst_clock_get_timeout (clock);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -608,7 +608,7 @@ GST_START_TEST (test_async_full)
|
||||||
/* register a periodic shot on the master to calibrate the slave */
|
/* register a periodic shot on the master to calibrate the slave */
|
||||||
g_mutex_lock (af_lock);
|
g_mutex_lock (af_lock);
|
||||||
clockid = gst_clock_new_periodic_id (master,
|
clockid = gst_clock_new_periodic_id (master,
|
||||||
gst_clock_get_time (master), slave->timeout);
|
gst_clock_get_time (master), gst_clock_get_timeout (slave));
|
||||||
gst_clock_id_wait_async_full (clockid,
|
gst_clock_id_wait_async_full (clockid,
|
||||||
(GstClockCallback) test_async_full_slave_callback,
|
(GstClockCallback) test_async_full_slave_callback,
|
||||||
gst_object_ref (slave), (GDestroyNotify) gst_object_unref);
|
gst_object_ref (slave), (GDestroyNotify) gst_object_unref);
|
||||||
|
|
|
@ -227,6 +227,7 @@ EXPORTS
|
||||||
gst_clock_get_master
|
gst_clock_get_master
|
||||||
gst_clock_get_resolution
|
gst_clock_get_resolution
|
||||||
gst_clock_get_time
|
gst_clock_get_time
|
||||||
|
gst_clock_get_timeout
|
||||||
gst_clock_get_type
|
gst_clock_get_type
|
||||||
gst_clock_id_compare_func
|
gst_clock_id_compare_func
|
||||||
gst_clock_id_get_time
|
gst_clock_id_get_time
|
||||||
|
@ -243,6 +244,7 @@ EXPORTS
|
||||||
gst_clock_set_calibration
|
gst_clock_set_calibration
|
||||||
gst_clock_set_master
|
gst_clock_set_master
|
||||||
gst_clock_set_resolution
|
gst_clock_set_resolution
|
||||||
|
gst_clock_set_timeout
|
||||||
gst_clock_single_shot_id_reinit
|
gst_clock_single_shot_id_reinit
|
||||||
gst_clock_type_get_type
|
gst_clock_type_get_type
|
||||||
gst_clock_unadjust_unlocked
|
gst_clock_unadjust_unlocked
|
||||||
|
|
Loading…
Reference in a new issue