diff --git a/ChangeLog b/ChangeLog index 8a067ce615..ce416dbdc2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2005-11-17 Andy Wingo + + * gst/gstclock.h (GstClock): Add rate and offset properties, + preserving ABI stability. Add rate/offset accessors. Will file bug + for the freeze break. + + * gst/gstclock.c (gst_clock_adjust_unlocked): Implement using rate + and offset, trying to keep precision and avoiding + underflow/overflow. + (gst_clock_set_rate_offset, gst_clock_get_rate_offset): New + functions. Make gst_clock_set_time_adjust obsolete. + (gst_clock_set_time_adjust): Note that this function is obsolete. + Will file bug soon. + + * gst/base/gstbasetransform.h: Make the ABI-stability hack + greppable by using GST_PADDING-1+1. + 2005-11-17 Torsten Schoenfeld Reviewed by: Tim-Philipp Müller diff --git a/gst/base/gstbasetransform.h b/gst/base/gstbasetransform.h index 1a7bae56b3..77a4268dae 100644 --- a/gst/base/gstbasetransform.h +++ b/gst/base/gstbasetransform.h @@ -87,7 +87,7 @@ struct _GstBaseTransform { gint64 segment_accum; }; /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; + gpointer _gst_reserved[GST_PADDING-1+1]; }; }; diff --git a/gst/gstclock.c b/gst/gstclock.c index 129ed63777..953989a267 100644 --- a/gst/gstclock.c +++ b/gst/gstclock.c @@ -532,6 +532,9 @@ gst_clock_init (GstClock * clock) clock->entries_changed = g_cond_new (); clock->flags = 0; clock->stats = FALSE; + + clock->rate = 1.0; + clock->offset = 0; } static void @@ -600,10 +603,10 @@ gst_clock_get_resolution (GstClock * clock) * @clock: a #GstClock to use * @internal: a clock time * - * Converts the given @internal clock time to the real time, adjusting - * and making sure that the returned time is increasing. - * This function should be called with the clock LOCK held and is - * mainly used by clock subclasses. + * Converts the given @internal clock time to the real time, adjusting for the + * rate and offset set with gst_clock_set_rate_offset() and making sure that the + * returned time is increasing. This function should be called with the clock + * LOCK held and is mainly used by clock subclasses. * * Returns: the converted time of the clock. * @@ -614,30 +617,46 @@ gst_clock_adjust_unlocked (GstClock * clock, GstClockTime internal) { GstClockTime ret; - ret = internal + clock->adjust; - /* make sure the time is increasing, else return last_time */ - if ((gint64) ret < (gint64) clock->last_time) { - ret = clock->last_time; + /* internal is uint64, rate is double, offset is int64, ret is uint64 */ + + ret = internal * clock->rate; + + if (clock->offset < 0) { + if ((clock->offset == G_MININT64 && ret <= G_MAXINT64) + || (clock->offset + ((gint64) ret) < 0)) + /* underflow */ + ret = 0; + else + ret -= (guint64) (-clock->offset); } else { - clock->last_time = ret; + if (clock->offset > 0 && ret >= G_MAXINT64 + && G_MAXUINT64 - ret - 1 <= clock->offset) + /* overflow, but avoiding CLOCK_TIME_NONE which is MAXUINT64 */ + ret = G_MAXUINT64 - 1; + else + ret += (guint64) clock->offset; } - return ret; + + /* make sure the time is increasing */ + clock->last_time = MAX (ret, clock->last_time); + + return clock->last_time; } /** - * gst_clock_get_time + * gst_clock_get_internal_time * @clock: a #GstClock to query * - * Gets the current time of the given clock. The time is always - * monotonically increasing. + * Gets the current internal time of the given clock. The time is returned + * unadjusted for the offset and the rate. * - * Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when + * Returns: the internal time of the clock. Or GST_CLOCK_TIME_NONE when * giving wrong input. * * MT safe. */ GstClockTime -gst_clock_get_time (GstClock * clock) +gst_clock_get_internal_time (GstClock * clock) { GstClockTime ret; GstClockClass *cclass; @@ -654,7 +673,33 @@ gst_clock_get_time (GstClock * clock) GST_CAT_DEBUG (GST_CAT_CLOCK, "internal 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 + * giving wrong input. + * + * MT safe. + */ +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_LOCK (clock); + /* this will scale for rate and offset */ ret = gst_clock_adjust_unlocked (clock, ret); GST_UNLOCK (clock); @@ -667,13 +712,9 @@ gst_clock_get_time (GstClock * clock) /** * gst_clock_set_time_adjust * @clock: a #GstClock to adjust - * @adjust: the adjust value + * @adjust: the new time * - * Adjusts the current time of the clock with the adjust value. - * A positive value moves the clock forwards and a backwards value - * moves it backwards. Note that _get_time() always returns - * increasing values so when you move the clock backwards, _get_time() - * will report the previous value until the clock catches up. + * Adjusts the time of @clock. This function is buggy and is scheduled to die. * * MT safe. */ @@ -687,6 +728,70 @@ gst_clock_set_time_adjust (GstClock * clock, GstClockTime adjust) GST_UNLOCK (clock); } +/** + * gst_clock_set_rate_offset + * @clock: a #GstClock to adjust + * @rate: the new rate + * @offset: the "initial" offset of @clock relative to its internal time + * + * Adjusts the internal rate and offset of @clock. + * + * A @rate of 1.0 is the normal speed of the clock. Values bigger than 1.0 make + * the clock go faster. @rate must be positive. + * + * Subsequent calls to gst_clock_get_time() will return clock times computed as + * follows: + * + * + * time = internal_time * @rate + @offset + * + * + * 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_rate_offset (GstClock * clock, gdouble rate, + GstClockTimeDiff offset) +{ + g_return_if_fail (GST_IS_CLOCK (clock)); + g_return_if_fail (rate > 0.0); + + GST_LOCK (clock); + clock->rate = rate; + clock->offset = offset; + GST_UNLOCK (clock); +} + +/** + * gst_clock_get_rate_offset + * @clock: a #GstClock to adjust + * @rate: a location to store the rate + * @offset: a location to store the offset + * + * Gets the internal rate and offset of @clock. The rate and offset are relative + * to the clock's internal time. + * + * MT safe. + * + * See also: gst_clock_set_rate_offset(). + */ +void +gst_clock_get_rate_offset (GstClock * clock, gdouble * rate, + GstClockTimeDiff * offset) +{ + g_return_if_fail (GST_IS_CLOCK (clock)); + g_return_if_fail (rate != NULL); + g_return_if_fail (offset != NULL); + + GST_LOCK (clock); + *rate = clock->rate; + *offset = clock->offset; + GST_UNLOCK (clock); +} + static void gst_clock_update_stats (GstClock * clock) { diff --git a/gst/gstclock.h b/gst/gstclock.h index 75259767ba..1eb2152b2d 100644 --- a/gst/gstclock.h +++ b/gst/gstclock.h @@ -373,7 +373,7 @@ struct _GstClock { GstClockFlags flags; /*< protected >*/ /* with LOCK */ - GstClockTime adjust; + GstClockTime adjust; /* remove me */ GstClockTime last_time; GList *entries; GCond *entries_changed; @@ -382,7 +382,15 @@ struct _GstClock { guint64 resolution; gboolean stats; - gpointer _gst_reserved[GST_PADDING]; + union { + struct { + /* should be moved to protected -- note the padding is finished now, on 32 + * bit machines at least */ + gdouble rate; + GstClockTime offset; + }; + gpointer _gst_reserved[GST_PADDING-1+1]; + }; }; struct _GstClockClass { @@ -411,8 +419,15 @@ guint64 gst_clock_set_resolution (GstClock *clock, guint64 resolution); guint64 gst_clock_get_resolution (GstClock *clock); GstClockTime gst_clock_get_time (GstClock *clock); +void gst_clock_set_rate_offset (GstClock *clock, gdouble rate, + GstClockTimeDiff offset); +void gst_clock_get_rate_offset (GstClock *clock, gdouble *rate, + GstClockTimeDiff *offset); + +/* remove me */ void gst_clock_set_time_adjust (GstClock *clock, GstClockTime adjust); +GstClockTime gst_clock_get_internal_time (GstClock *clock); GstClockTime gst_clock_adjust_unlocked (GstClock *clock, GstClockTime internal); diff --git a/libs/gst/base/gstbasetransform.h b/libs/gst/base/gstbasetransform.h index 1a7bae56b3..77a4268dae 100644 --- a/libs/gst/base/gstbasetransform.h +++ b/libs/gst/base/gstbasetransform.h @@ -87,7 +87,7 @@ struct _GstBaseTransform { gint64 segment_accum; }; /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; + gpointer _gst_reserved[GST_PADDING-1+1]; }; };