diff --git a/ChangeLog b/ChangeLog index cc83ce13c5..c0895e7ec1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2006-08-11 Wim Taymans + + * docs/gst/gstreamer-sections.txt: + Add GstClockClass vmethod docs. + + * gst/gstcaps.h: + Mark #endif with comment for associated #if + + * gst/gstclock.c: (gst_clock_id_wait): + * gst/gstclock.h: + Add vmethod wait_jitter to avoid an unneeded _get_time() for + most clock implementations. + Document vmethods. + Flesh out docs about resolution methods. + API: GstClockClass::wait_jitter + + * gst/gstsystemclock.c: (gst_system_clock_class_init), + (gst_system_clock_async_thread), + (gst_system_clock_id_wait_jitter_unlocked), + (gst_system_clock_id_wait_jitter): + Use base class wait_jitter variant for improved performance + due to less clock polling. + 2006-08-11 Edward Hervey * gst/gst.c: (gst_init_check), (init_post): diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 3d04560dc1..ff60a00e76 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -285,6 +285,7 @@ gst_child_proxy_get_type gstclock GstClock GstClock +GstClockClass GstClockTime GstClockTimeDiff GstClockID @@ -338,7 +339,6 @@ gst_clock_id_unref GST_TYPE_CLOCK_TIME -GstClockClass GST_CLOCK GST_IS_CLOCK GST_TYPE_CLOCK diff --git a/gst/gstcaps.h b/gst/gstcaps.h index 15976d8d33..9756e2b880 100644 --- a/gst/gstcaps.h +++ b/gst/gstcaps.h @@ -94,7 +94,8 @@ typedef enum { */ #define GST_DEBUG_CAPS(string, caps) \ GST_DEBUG ( string "%s: " GST_PTR_FORMAT, caps) -#endif + +#endif /* GST_DISABLE_DEPRECATED */ /** * GST_STATIC_CAPS: diff --git a/gst/gstclock.c b/gst/gstclock.c index 53ec8a769b..f86e5b3fd7 100644 --- a/gst/gstclock.c +++ b/gst/gstclock.c @@ -333,7 +333,6 @@ gst_clock_id_get_time (GstClockID id) return GST_CLOCK_ENTRY_TIME ((GstClockEntry *) id); } - /** * gst_clock_id_wait * @id: The #GstClockID to wait on @@ -386,20 +385,29 @@ gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter) cclass = GST_CLOCK_GET_CLASS (clock); - if (G_UNLIKELY (cclass->wait == NULL)) - goto not_supported; - GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "waiting on clock entry %p", id); - if (jitter) { - GstClockTime now = gst_clock_get_time (clock); + /* if we have a wait_jitter function, use that */ + if (G_LIKELY (cclass->wait_jitter)) { + res = cclass->wait_jitter (clock, entry, jitter); + } else { + /* check if we have a simple _wait function otherwise. The function without + * the jitter arg is less optimal as we need to do an additional _get_time() + * which is not atomic with the _wait() and a typical _wait() function does + * yet another _get_time() anyway. */ + if (G_UNLIKELY (cclass->wait == NULL)) + goto not_supported; - /* jitter is the diff against the clock when this entry is scheduled. Negative - * values mean that the entry was in time, a positive value means that the - * entry was too late. */ - *jitter = GST_CLOCK_DIFF (requested, now); + if (jitter) { + GstClockTime now = gst_clock_get_time (clock); + + /* jitter is the diff against the clock when this entry is scheduled. Negative + * values mean that the entry was in time, a positive value means that the + * entry was too late. */ + *jitter = GST_CLOCK_DIFF (requested, now); + } + res = cclass->wait (clock, entry); } - res = cclass->wait (clock, entry); GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, clock, "done waiting entry %p, res: %d", id, res); @@ -669,7 +677,11 @@ gst_clock_finalize (GObject * object) * @clock: a #GstClock * @resolution: The resolution to set * - * Set the accuracy of the clock. + * 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. */ @@ -694,7 +706,8 @@ gst_clock_set_resolution (GstClock * clock, GstClockTime resolution) * gst_clock_get_resolution * @clock: a #GstClock * - * Get the accuracy of the clock. + * Get the accuracy of the clock. The accuracy of the clock is the granularity + * of the values returned by gst_clock_get_time(). * * Returns: the resolution of the clock in units of #GstClockTime. * diff --git a/gst/gstclock.h b/gst/gstclock.h index 527c9eacec..da57fb9853 100644 --- a/gst/gstclock.h +++ b/gst/gstclock.h @@ -413,10 +413,27 @@ struct _GstClock { GstClockTime _gst_reserved[GST_PADDING]; }; +/** + * GstClockClass: + * @parent_class: the parent class structure + * @change_resolution: change the resolution of the clock. Not all values might + * be acceptable. The new resolution should be returned. + * @get_resolution: get the resolution of the clock. + * @get_internal_time: get the internal unadjusted time of the clock. + * @wait: perform a blocking wait for the given GstClockEntry. Deprecated, + * implement @wait_jitter instead. + * @wait_async: perform an asynchronous wait for the given GstClockEntry. + * @unschedule: unblock a blocking or async wait operation. + * @wait_jitter: perform a blocking wait on the given GstClockEntry and return + * the jitter. + * + * GStreamer clock class. Override the vmethods to implement the clock + * functionality. + */ struct _GstClockClass { GstObjectClass parent_class; - /*< protected >*/ + /*< public >*/ /* vtable */ GstClockTime (*change_resolution) (GstClock *clock, GstClockTime old_resolution, @@ -430,8 +447,11 @@ struct _GstClockClass { GstClockReturn (*wait_async) (GstClock *clock, GstClockEntry *entry); void (*unschedule) (GstClock *clock, GstClockEntry *entry); + /* ABI added to replace the deprecated wait */ + GstClockReturn (*wait_jitter) (GstClock *clock, GstClockEntry *entry, + GstClockTimeDiff *jitter); /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; + gpointer _gst_reserved[GST_PADDING - 1]; }; GType gst_clock_get_type (void); diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c index 515aa29a07..4f95c3c1cd 100644 --- a/gst/gstsystemclock.c +++ b/gst/gstsystemclock.c @@ -55,10 +55,10 @@ static void gst_system_clock_dispose (GObject * object); static GstClockTime gst_system_clock_get_internal_time (GstClock * clock); static guint64 gst_system_clock_get_resolution (GstClock * clock); -static GstClockReturn gst_system_clock_id_wait (GstClock * clock, - GstClockEntry * entry); -static GstClockReturn gst_system_clock_id_wait_unlocked - (GstClock * clock, GstClockEntry * entry); +static GstClockReturn gst_system_clock_id_wait_jitter (GstClock * clock, + GstClockEntry * entry, GstClockTimeDiff * jitter); +static GstClockReturn gst_system_clock_id_wait_jitter_unlocked + (GstClock * clock, GstClockEntry * entry, GstClockTimeDiff * jitter); static GstClockReturn gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry); static void gst_system_clock_id_unschedule (GstClock * clock, @@ -113,7 +113,7 @@ gst_system_clock_class_init (GstSystemClockClass * klass) gstclock_class->get_internal_time = gst_system_clock_get_internal_time; gstclock_class->get_resolution = gst_system_clock_get_resolution; - gstclock_class->wait = gst_system_clock_id_wait; + gstclock_class->wait_jitter = gst_system_clock_id_wait_jitter; gstclock_class->wait_async = gst_system_clock_id_wait_async; gstclock_class->unschedule = gst_system_clock_id_unschedule; } @@ -270,7 +270,9 @@ gst_system_clock_async_thread (GstClock * clock) } /* now wait for the entry, we already hold the lock */ - res = gst_system_clock_id_wait_unlocked (clock, (GstClockID) entry); + res = + gst_system_clock_id_wait_jitter_unlocked (clock, (GstClockID) entry, + NULL); switch (res) { case GST_CLOCK_UNSCHEDULED: @@ -362,7 +364,8 @@ gst_system_clock_get_resolution (GstClock * clock) * MT safe. */ static GstClockReturn -gst_system_clock_id_wait_unlocked (GstClock * clock, GstClockEntry * entry) +gst_system_clock_id_wait_jitter_unlocked (GstClock * clock, + GstClockEntry * entry, GstClockTimeDiff * jitter) { GstClockTime entryt, real, now, target; GstClockTimeDiff diff; @@ -372,6 +375,9 @@ gst_system_clock_id_wait_unlocked (GstClock * clock, GstClockEntry * entry) entryt = GST_CLOCK_ENTRY_TIME (entry); now = gst_clock_adjust_unlocked (clock, real); + if (jitter) { + *jitter = GST_CLOCK_DIFF (entryt, now); + } diff = entryt - now; target = gst_system_clock_get_internal_time (clock) + diff; @@ -413,13 +419,13 @@ gst_system_clock_id_wait_unlocked (GstClock * clock, GstClockEntry * entry) (final - target), ((double) (GstClockTimeDiff) (final - target)) / GST_SECOND); #endif - break; } else { /* the waiting is interrupted because the GCond was signaled. This can * be because this or some other entry was unscheduled. */ GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked with signal", entry); - /* if the entry is unscheduled, we can stop waiting for it */ + /* if the entry is unscheduled, we can stop waiting for it, else we + * continue our while loop. */ if (entry->status == GST_CLOCK_UNSCHEDULED) break; } @@ -433,12 +439,13 @@ gst_system_clock_id_wait_unlocked (GstClock * clock, GstClockEntry * entry) } static GstClockReturn -gst_system_clock_id_wait (GstClock * clock, GstClockEntry * entry) +gst_system_clock_id_wait_jitter (GstClock * clock, GstClockEntry * entry, + GstClockTimeDiff * jitter) { GstClockReturn ret; GST_OBJECT_LOCK (clock); - ret = gst_system_clock_id_wait_unlocked (clock, entry); + ret = gst_system_clock_id_wait_jitter_unlocked (clock, entry, jitter); GST_OBJECT_UNLOCK (clock); return ret;