/** * gst_clock_set_resolution: * @clock: a #GstClock * @resolution: The resolution to set * * Set the accuracy of the clock. Some clocks have the possibility to operate * with different accuracy at the expense of more resource usage. There is * normally no need to change the default resolution of a clock. The resolution * of a clock can only be changed if the clock has the * #GST_CLOCK_FLAG_CAN_SET_RESOLUTION flag set. * * Returns: the new resolution of the clock. */ GstClockTime gst_clock_set_resolution (GstClock * clock, GstClockTime resolution) { GstClockPrivate *priv; GstClockClass *cclass; g_return_val_if_fail (GST_IS_CLOCK (clock), 0); g_return_val_if_fail (resolution != 0, 0); cclass = GST_CLOCK_GET_CLASS (clock); priv = clock->priv; if (cclass->change_resolution) priv->resolution = cclass->change_resolution (clock, priv->resolution, resolution); return priv->resolution; }
EXPORT_C #endif GstClockTime gst_clock_set_resolution (GstClock * clock, GstClockTime resolution) { GstClockClass *cclass; g_return_val_if_fail (GST_IS_CLOCK (clock), 0); g_return_val_if_fail (resolution != 0, 0); cclass = GST_CLOCK_GET_CLASS (clock); if (cclass->change_resolution) clock->resolution = cclass->change_resolution (clock, clock->resolution, resolution); return clock->resolution; }
/** * gst_clock_get_calibration * @clock: a #GstClock * @internal: a location to store the internal time * @external: a location to store the external time * @rate_num: a location to store the rate numerator * @rate_denom: a location to store the rate denominator * * Gets the internal rate and reference time of @clock. See * gst_clock_set_calibration() for more information. * * @internal, @external, @rate_num, and @rate_denom can be left %NULL if the * caller is not interested in the values. * * MT safe. */ void gst_clock_get_calibration (GstClock * clock, GstClockTime * internal, GstClockTime * external, GstClockTime * rate_num, GstClockTime * rate_denom) { gint seq; g_return_if_fail (GST_IS_CLOCK (clock)); do { seq = read_seqbegin (clock); if (rate_num) *rate_num = clock->rate_numerator; if (rate_denom) *rate_denom = clock->rate_denominator; if (external) *external = clock->external_calibration; if (internal) *internal = clock->internal_calibration; } while (read_seqretry (clock, seq)); }
EXPORT_C #endif void gst_clock_get_calibration (GstClock * clock, GstClockTime * internal, GstClockTime * external, GstClockTime * rate_num, GstClockTime * rate_denom) { g_return_if_fail (GST_IS_CLOCK (clock)); GST_OBJECT_LOCK (clock); if (rate_num) *rate_num = clock->rate_numerator; if (rate_denom) *rate_denom = clock->rate_denominator; if (external) *external = clock->external_calibration; if (internal) *internal = clock->internal_calibration; GST_OBJECT_UNLOCK (clock); }
/** * gst_clock_set_calibration * @clock: a #GstClock to calibrate * @internal: a reference internal time * @external: a reference external time * @rate_num: the numerator of the rate of the clock relative to its * internal time * @rate_denom: the denominator of the rate of the clock * * Adjusts the rate and time of @clock. A rate of 1/1 is the normal speed of * the clock. Values bigger than 1/1 make the clock go faster. * * @internal and @external are calibration parameters that arrange that * gst_clock_get_time() should have been @external at internal time @internal. * This internal time should not be in the future; that is, it should be less * than the value of gst_clock_get_internal_time() when this function is called. * * Subsequent calls to gst_clock_get_time() will return clock times computed as * follows: * * <programlisting> * time = (internal_time - internal) * rate_num / rate_denom + external * </programlisting> * * This formula is implemented in gst_clock_adjust_unlocked(). Of course, it * tries to do the integer arithmetic as precisely as possible. * * Note that gst_clock_get_time() always returns increasing values so when you * move the clock backwards, gst_clock_get_time() will report the previous value * until the clock catches up. * * MT safe. */ void gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime external, GstClockTime rate_num, GstClockTime rate_denom) { g_return_if_fail (GST_IS_CLOCK (clock)); g_return_if_fail (rate_num != GST_CLOCK_TIME_NONE); g_return_if_fail (rate_denom > 0 && rate_denom != GST_CLOCK_TIME_NONE); write_seqlock (clock); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT " = %f", GST_TIME_ARGS (internal), GST_TIME_ARGS (external), rate_num, rate_denom, gst_guint64_to_gdouble (rate_num) / gst_guint64_to_gdouble (rate_denom)); clock->internal_calibration = internal; clock->external_calibration = external; clock->rate_numerator = rate_num; clock->rate_denominator = rate_denom; write_sequnlock (clock); }
EXPORT_C #endif GstClockTime gst_clock_get_time (GstClock * clock) { GstClockTime ret; g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE); ret = gst_clock_get_internal_time (clock); GST_OBJECT_LOCK (clock); /* this will scale for rate and offset */ ret = gst_clock_adjust_unlocked (clock, ret); GST_OBJECT_UNLOCK (clock); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "adjusted time %" GST_TIME_FORMAT, GST_TIME_ARGS (ret)); return ret; }
/** * gst_clock_get_time * @clock: a #GstClock to query * * Gets the current time of the given clock. The time is always * monotonically increasing and adjusted according to the current * offset and rate. * * Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when * given invalid input. * * MT safe. */ GstClockTime gst_clock_get_time (GstClock * clock) { GstClockTime ret; gint seq; g_return_val_if_fail (GST_IS_CLOCK (clock), GST_CLOCK_TIME_NONE); do { /* reget the internal time when we retry to get the most current * timevalue */ ret = gst_clock_get_internal_time (clock); seq = read_seqbegin (clock); /* this will scale for rate and offset */ ret = gst_clock_adjust_unlocked (clock, ret); } while (read_seqretry (clock, seq)); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "adjusted time %" GST_TIME_FORMAT, GST_TIME_ARGS (ret)); return ret; }
/** * gst_clock_add_observation_unapplied: * @clock: a #GstClock * @slave: a time on the slave * @master: a time on the master * @r_squared: (out): a pointer to hold the result * @internal: (out) (allow-none): a location to store the internal time * @external: (out) (allow-none): a location to store the external time * @rate_num: (out) (allow-none): a location to store the rate numerator * @rate_denom: (out) (allow-none): a location to store the rate denominator * * Add a clock observation to the internal slaving algorithm the same as * gst_clock_add_observation(), and return the result of the master clock * estimation, without updating the internal calibration. * * The caller can then take the results and call gst_clock_set_calibration() * with the values, or some modified version of them. * * Since: 1.6 */ gboolean gst_clock_add_observation_unapplied (GstClock * clock, GstClockTime slave, GstClockTime master, gdouble * r_squared, GstClockTime * internal, GstClockTime * external, GstClockTime * rate_num, GstClockTime * rate_denom) { GstClockTime m_num, m_denom, b, xbase; GstClockPrivate *priv; guint n; g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE); g_return_val_if_fail (r_squared != NULL, FALSE); priv = clock->priv; GST_CLOCK_SLAVE_LOCK (clock); GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock, "adding observation slave %" GST_TIME_FORMAT ", master %" GST_TIME_FORMAT, GST_TIME_ARGS (slave), GST_TIME_ARGS (master)); priv->times[(4 * priv->time_index)] = slave; priv->times[(4 * priv->time_index) + 2] = master; priv->time_index++; if (G_UNLIKELY (priv->time_index == priv->window_size)) { priv->filling = FALSE; priv->time_index = 0; } if (G_UNLIKELY (priv->filling && priv->time_index < priv->window_threshold)) goto filling; n = priv->filling ? priv->time_index : priv->window_size; if (!_priv_gst_do_linear_regression (priv->times, n, &m_num, &m_denom, &b, &xbase, r_squared)) goto invalid; GST_CLOCK_SLAVE_UNLOCK (clock); GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock, "adjusting clock to m=%" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT ", b=%" G_GUINT64_FORMAT " (rsquared=%g)", m_num, m_denom, b, *r_squared); if (internal) *internal = xbase; if (external) *external = b; if (rate_num) *rate_num = m_num; if (rate_denom) *rate_denom = m_denom; return TRUE; filling: { GST_CLOCK_SLAVE_UNLOCK (clock); return FALSE; } invalid: { /* no valid regression has been done, ignore the result then */ GST_CLOCK_SLAVE_UNLOCK (clock); return TRUE; } }