? gst/gstposixclock.c
? gst/gstposixclock.h
? gst/out
? gst/plugs
? tests/check/gst/gstposixclock.c
Index: configure.ac
===================================================================
RCS file: /cvs/gstreamer/gstreamer/configure.ac,v
retrieving revision 1.487
diff -u -r1.487 configure.ac
--- configure.ac	5 Oct 2006 15:31:15 -0000	1.487
+++ configure.ac	20 Oct 2006 12:25:44 -0000
@@ -315,6 +315,58 @@
 AC_FUNC_MMAP
 AM_CONDITIONAL(HAVE_MMAP, test "x$ac_cv_func_mmap_fixed_mapped" = "xyes")
 
+dnl Check for POSIX timers
+AC_CHECK_FUNCS(clock_gettime, [], [
+  AC_CHECK_LIB(rt, clock_gettime, [
+    AC_DEFINE(HAVE_CLOCK_GETTIME, 1)
+    LIBS="$LIBS -lrt"
+  ])
+])
+
+AC_CACHE_CHECK(for posix timers, gst_cv_posix_timers,AC_TRY_RUN([
+#include <time.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+      int main() {
+#if defined(_POSIX_TIMERS) && _POSIX_TIMERS >= 0 && defined(CLOCK_REALTIME)
+        return 0;
+#else
+        return 1;
+#endif
+      }],gst_cv_posix_timers=yes,gst_cv_posix_timers=no))
+
+if test "$gst_cv_posix_timers" = "yes"; then
+  AC_DEFINE(HAVE_POSIX_TIMERS,1,[Have posix timers])
+  GST_HAVE_POSIX_TIMERS_DEFINE="#define GST_HAVE_POSIX_TIMERS 1"
+else
+  GST_HAVE_POSIX_TIMERS_DEFINE="#define GST_HAVE_POSIX_TIMERS 0"
+fi
+AC_SUBST(GST_HAVE_POSIX_TIMERS_DEFINE)
+AM_CONDITIONAL(GST_HAVE_POSIX_TIMERS, test "$gst_cv_posix_timers" = "yes")
+
+AC_CACHE_CHECK(for monotonic clock, gst_cv_monotonic_clock,AC_TRY_RUN([
+#include <time.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+      int main() {
+#if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 && defined(CLOCK_MONOTONIC)
+        return 0;
+#else
+        return 1;
+#endif
+      }],gst_cv_monotonic_clock=yes,gst_cv_monotonic_clock=no))
+
+if test "$gst_cv_monotonic_clock" = "yes"; then
+  AC_DEFINE(HAVE_MONOTONIC_CLOCK,1,[Have a monotonic clock])
+  GST_HAVE_MONOTONIC_CLOCK_DEFINE="#define GST_HAVE_MONOTONIC_CLOCK 1"
+else
+  GST_HAVE_MONOTONIC_CLOCK_DEFINE="#define GST_HAVE_MONOTONIC_CLOCK 0"
+fi
+AC_SUBST(GST_HAVE_MONOTONIC_CLOCK_DEFINE)
+AM_CONDITIONAL(GST_HAVE_MONOTONIC_CLOCK, test "$gst_cv_monotonic_clock" = "yes")
+
 dnl Check for a way to display the function name in debug output
 GST_CHECK_FUNCTION
 
Index: gst/gstconfig.h.in
===================================================================
RCS file: /cvs/gstreamer/gstreamer/gst/gstconfig.h.in,v
retrieving revision 1.22
diff -u -r1.22 gstconfig.h.in
--- gst/gstconfig.h.in	5 Oct 2006 12:31:07 -0000	1.22
+++ gst/gstconfig.h.in	20 Oct 2006 12:25:45 -0000
@@ -167,6 +167,12 @@
    refcounting */
 @GST_HAVE_GLIB_2_8_DEFINE@
 
+/* whether or not POSIX realtime clock is supported */
+@GST_HAVE_POSIX_TIMERS_DEFINE@
+
+/* whether or not POSIX monotonic clock is supported */
+@GST_HAVE_MONOTONIC_CLOCK_DEFINE@
+
 /***** Deal with XML stuff, we have to handle both loadsave and registry *****/
 
 #if (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) )
Index: gst/gstsystemclock.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/gst/gstsystemclock.c,v
retrieving revision 1.44
diff -u -r1.44 gstsystemclock.c
--- gst/gstsystemclock.c	11 Oct 2006 16:30:14 -0000	1.44
+++ gst/gstsystemclock.c	20 Oct 2006 12:25:45 -0000
@@ -40,18 +40,121 @@
 
 #include "gst_private.h"
 #include "gstinfo.h"
+#include "gstconfig.h"
 
 #include "gstsystemclock.h"
 
+#if GST_HAVE_POSIX_TIMERS
+#include <time.h>
+#endif
+
 /* Define this to get some extra debug about jitter from each clock_wait */
 #undef WAIT_DEBUGGING
 
+typedef struct _TimeoutSource TimeoutSource;
+struct _TimeoutSource
+{
+  GSource source;
+  GstClockEntry * entry;
+  guint timeout_msecs;
+};
+
+static gboolean
+timeout_prepare (GSource *source, gint *timeout)
+{
+  return (*timeout = ((TimeoutSource *)source)->timeout_msecs) <= 0;
+}
+
+static gboolean
+timeout_check (GSource *source)
+{
+  GstClockEntry * entry = ((TimeoutSource *)source)->entry;
+  GstClock * clock = GST_CLOCK_ENTRY_CLOCK (entry);
+  gboolean ret = FALSE;
+
+  GST_OBJECT_LOCK (clock);
+  if (entry->status != GST_CLOCK_UNSCHEDULED) {
+    GstClockTime real = GST_CLOCK_GET_CLASS (clock)->get_internal_time (clock);
+    GstClockTime now = gst_clock_adjust_unlocked (clock, real);
+
+    if (GST_CLOCK_ENTRY_TIME (entry) <= now) {
+      entry->status = GST_CLOCK_OK;
+
+      ret = TRUE;
+    }
+  }
+  GST_OBJECT_UNLOCK (clock);
+
+  return ret;
+}
+
+static gboolean
+timeout_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
+{
+  return TRUE;
+}
+
+static
+GSourceFuncs timeout_funcs =
+{
+  timeout_prepare,
+  timeout_check,
+  timeout_dispatch,
+  NULL
+};
+
+static inline GSource *
+timeout_source_new (GstClockEntry * entry, guint timeout_msecs)
+{
+  GSource *source = g_source_new (&timeout_funcs, sizeof (TimeoutSource));
+  TimeoutSource * tsource = (TimeoutSource *)source;
+
+  tsource->entry = entry;
+  tsource->timeout_msecs = timeout_msecs;
+
+  return source;
+}
+
+static inline void
+timeout_source_set_timeout (TimeoutSource * source, guint timeout_msecs)
+{
+  source->timeout_msecs = timeout_msecs;
+}
+
+enum
+{
+  PROP_0,
+  PROP_CLOCK_TYPE
+      /* FILL ME */
+};
+
+#define GST_TYPE_CLOCK_TYPE (gst_clock_type_get_type())
+static GType
+gst_clock_type_get_type (void)
+{
+  static GType clock_type_type = 0;
+  static const GEnumValue clock_types[] = {
+    {GST_CLOCK_TYPE_REALTIME, "Realtime", "realtime"},
+    {GST_CLOCK_TYPE_MONOTONIC, "Monotonic", "monotonic"},
+    {0, NULL, NULL},
+  };
+
+  if (!clock_type_type) {
+    clock_type_type = g_enum_register_static ("GstClockType", clock_types);
+  }
+  return clock_type_type;
+}
+
 /* the one instance of the systemclock */
 static GstClock *_the_system_clock = NULL;
 
 static void gst_system_clock_class_init (GstSystemClockClass * klass);
 static void gst_system_clock_init (GstSystemClock * clock);
 static void gst_system_clock_dispose (GObject * object);
+static void gst_system_clock_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_system_clock_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
 
 static GstClockTime gst_system_clock_get_internal_time (GstClock * clock);
 static guint64 gst_system_clock_get_resolution (GstClock * clock);
@@ -110,6 +213,13 @@
   parent_class = g_type_class_peek_parent (klass);
 
   gobject_class->dispose = gst_system_clock_dispose;
+  gobject_class->set_property = gst_system_clock_set_property;
+  gobject_class->get_property = gst_system_clock_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_CLOCK_TYPE,
+      g_param_spec_enum ("clock-type", "Clock type",
+          "The type of underlying clock implementation used",
+          GST_TYPE_CLOCK_TYPE, GST_CLOCK_TYPE_REALTIME, G_PARAM_READWRITE));
 
   gstclock_class->get_internal_time = gst_system_clock_get_internal_time;
   gstclock_class->get_resolution = gst_system_clock_get_resolution;
@@ -123,12 +233,16 @@
 {
   GError *error = NULL;
 
+  clock->clock_type = GST_CLOCK_TYPE_REALTIME;
+
   GST_OBJECT_FLAG_SET (clock,
       GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC |
       GST_CLOCK_FLAG_CAN_DO_SINGLE_ASYNC |
       GST_CLOCK_FLAG_CAN_DO_PERIODIC_SYNC |
       GST_CLOCK_FLAG_CAN_DO_PERIODIC_ASYNC);
 
+  clock->context = g_main_context_new ();
+
   GST_OBJECT_LOCK (clock);
   clock->thread = g_thread_create ((GThreadFunc) gst_system_clock_async_thread,
       clock, TRUE, &error);
@@ -168,6 +282,7 @@
   }
   g_list_free (clock->entries);
   clock->entries = NULL;
+  g_main_context_wakeup (sysclock->context);
   GST_CLOCK_BROADCAST (clock);
   GST_OBJECT_UNLOCK (clock);
 
@@ -176,6 +291,8 @@
   sysclock->thread = NULL;
   GST_CAT_DEBUG (GST_CAT_CLOCK, "joined thread");
 
+  g_main_context_unref (sysclock->context);
+
   G_OBJECT_CLASS (parent_class)->dispose (object);
 
   if (_the_system_clock == clock) {
@@ -184,6 +301,39 @@
   }
 }
 
+static void
+gst_system_clock_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstSystemClock *src = GST_SYSTEM_CLOCK (object);
+
+  switch (prop_id) {
+    case PROP_CLOCK_TYPE:
+      src->clock_type = g_value_get_enum (value);
+      GST_CAT_DEBUG (GST_CAT_CLOCK, "clock-type set to %d", src->clock_type);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_system_clock_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  GstSystemClock *src = GST_SYSTEM_CLOCK (object);
+
+  switch (prop_id) {
+    case PROP_CLOCK_TYPE:
+      g_value_set_enum (value, src->clock_type);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
 /**
  * gst_system_clock_obtain:
  *
@@ -331,21 +481,56 @@
   GST_CAT_DEBUG (GST_CAT_CLOCK, "exit system clock thread");
 }
 
+#if GST_HAVE_POSIX_TIMERS
+static inline clockid_t
+clock_type_to_posix_id (GstClockType clock_type)
+{
+#if GST_HAVE_MONOTONIC_CLOCK
+    if (clock_type == GST_CLOCK_TYPE_MONOTONIC)
+      return CLOCK_MONOTONIC;
+    else
+#endif
+      return CLOCK_REALTIME;
+}
+#endif
+
 /* MT safe */
 static GstClockTime
 gst_system_clock_get_internal_time (GstClock * clock)
 {
+#if GST_HAVE_POSIX_TIMERS
+  struct timespec ts;
+
+  if (G_UNLIKELY (clock_gettime (
+      clock_type_to_posix_id (GST_SYSTEM_CLOCK (clock)->clock_type), &ts))) {
+    return GST_CLOCK_TIME_NONE;
+  }
+
+  return GST_TIMESPEC_TO_TIME (ts);
+#else
   GTimeVal timeval;
 
   g_get_current_time (&timeval);
 
   return GST_TIMEVAL_TO_TIME (timeval);
+#endif
 }
 
 static guint64
 gst_system_clock_get_resolution (GstClock * clock)
 {
+#if GST_HAVE_POSIX_TIMERS
+  struct timespec ts;
+
+  if (G_UNLIKELY (clock_getres (
+      clock_type_to_posix_id (GST_SYSTEM_CLOCK (clock)->clock_type), &ts))) {
+    return GST_CLOCK_TIME_NONE;
+  }
+
+  return GST_TIMESPEC_TO_TIME (ts);
+#else
   return 1 * GST_USECOND;
+#endif
 }
 
 /* synchronously wait on the given GstClockEntry.
@@ -368,74 +553,98 @@
 gst_system_clock_id_wait_jitter_unlocked (GstClock * clock,
     GstClockEntry * entry, GstClockTimeDiff * jitter)
 {
-  GstClockTime entryt, real, now, target;
+  GstClockTime entryt, real, now;
   GstClockTimeDiff diff;
+  GSource * source = NULL;
+  gboolean early = TRUE;
 
-  /* need to call the overridden method */
-  real = GST_CLOCK_GET_CLASS (clock)->get_internal_time (clock);
-  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;
-
-  GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p"
-      " target %" GST_TIME_FORMAT
-      " entry %" GST_TIME_FORMAT
-      " now %" GST_TIME_FORMAT
-      " real %" GST_TIME_FORMAT
-      " diff %" G_GINT64_FORMAT,
-      entry,
-      GST_TIME_ARGS (target),
-      GST_TIME_ARGS (entryt), GST_TIME_ARGS (now), GST_TIME_ARGS (real), diff);
+  while (TRUE) {
+    /* need to call the overridden method */
+    real = GST_CLOCK_GET_CLASS (clock)->get_internal_time (clock);
+    entryt = GST_CLOCK_ENTRY_TIME (entry);
+
+    now = gst_clock_adjust_unlocked (clock, real);
+    if (jitter) {
+      *jitter = GST_CLOCK_DIFF (entryt, now);
+    }
+    diff = entryt - now;
 
-  if (diff > 0) {
-    GTimeVal tv;
+    GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p"
+        " entry %" GST_TIME_FORMAT
+        " now %" GST_TIME_FORMAT
+        " real %" GST_TIME_FORMAT
+        " diff %" G_GINT64_FORMAT,
+        entry, GST_TIME_ARGS (entryt), GST_TIME_ARGS (now),
+        GST_TIME_ARGS (real), diff);
+
+    if (diff > 0) {
+      early = FALSE;
+      GstSystemClock *sysclock = GST_SYSTEM_CLOCK (clock);
+
+      if (!source) {
+        source = timeout_source_new (entry, diff / 1000000);
+      /* id = */ g_source_attach (source, sysclock->context);
+      } else {
+        timeout_source_set_timeout ((TimeoutSource *)source, diff / 1000000);
+      }
 
+      /* now wait on the entry, it either times out or is woken up. */
+      GST_OBJECT_UNLOCK (clock);
+      if (g_main_context_iteration (sysclock->context, TRUE)) {
+        GST_OBJECT_LOCK (clock);
+        if (entry->status == GST_CLOCK_OK) {
 #ifdef WAIT_DEBUGGING
-    GstClockTime result, final;
+          GstClockTime result, final;
 #endif
-
-    GST_TIME_TO_TIMEVAL (target, tv);
-
-    while (TRUE) {
-      /* now wait on the entry, it either times out or the cond is signaled. */
-      if (!GST_CLOCK_TIMED_WAIT (clock, &tv)) {
-        /* timeout, this is fine, we can report success now */
-        GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked after timeout", entry);
-        entry->status = GST_CLOCK_OK;
+          /* timeout, this is fine, we can report success now */
+          GST_CAT_DEBUG (GST_CAT_CLOCK,
+              "entry %p unlocked after timeout", entry);
 
 #ifdef WAIT_DEBUGGING
-        real = GST_CLOCK_GET_CLASS (clock)->get_internal_time (clock);
-        result = gst_clock_adjust_unlocked (clock, real);
-        final = gst_system_clock_get_internal_time (clock);
-        GST_CAT_DEBUG (GST_CAT_CLOCK, "Waited for %" G_GINT64_FORMAT
-            " got %" G_GINT64_FORMAT " diff %" G_GINT64_FORMAT
-            " %g target-offset %" G_GINT64_FORMAT " %g", entryt, result,
-            result - entryt,
-            (double) (GstClockTimeDiff) (result - entryt) / GST_SECOND,
-            (final - target),
-            ((double) (GstClockTimeDiff) (final - target)) / GST_SECOND);
+          real = GST_CLOCK_GET_CLASS (clock)->get_internal_time (clock);
+          result = gst_clock_adjust_unlocked (clock, real);
+          final = gst_system_clock_get_internal_time (clock);
+          GST_CAT_DEBUG (GST_CAT_CLOCK, "Waited for %" G_GINT64_FORMAT
+              " got %" G_GINT64_FORMAT " diff %" G_GINT64_FORMAT
+              " %g target-offset %" G_GINT64_FORMAT " %g", entryt, result,
+              result - entryt,
+              (double) (GstClockTimeDiff) (result - entryt) / GST_SECOND,
+              (final - target),
+              ((double) (GstClockTimeDiff) (final - target)) / GST_SECOND);
 #endif
-        break;
+          break;
+        } else {
+          /* some other source timed out, go back to sleep */
+#ifdef WAIT_DEBUGGING
+          GST_CAT_DEBUG (GST_CAT_CLOCK,
+              "Woken too early, going back to sleep.\n");
+#endif
+        }
       } else {
-        /* the waiting is interrupted because the GCond was signaled. This can
-         * be because this or some other entry was unscheduled. */
+        GST_OBJECT_LOCK (clock);
         GST_CAT_DEBUG (GST_CAT_CLOCK, "entry %p unlocked with signal", entry);
         /* if the entry is unscheduled, we can stop waiting for it, else we
          * continue our while loop. */
         if (entry->status == GST_CLOCK_UNSCHEDULED)
           break;
       }
+    } else if (entry->status == GST_CLOCK_UNSCHEDULED) {
+      /* if the entry is unscheduled, we should report it even if we have
+       * timed out. */
+      break;
+    } else if (early) {
+      entry->status = GST_CLOCK_EARLY;
+      break;
+    } else {
+      entry->status = GST_CLOCK_OK;
+      break;
     }
-  } else if (diff == 0) {
-    entry->status = GST_CLOCK_OK;
-  } else {
-    entry->status = GST_CLOCK_EARLY;
   }
+
+  if (source) {
+    g_source_destroy (source);
+  }
+
   return entry->status;
 }
 
@@ -493,11 +702,13 @@
 static void
 gst_system_clock_id_unschedule (GstClock * clock, GstClockEntry * entry)
 {
+  GstSystemClock *sysclock = GST_SYSTEM_CLOCK (clock);
+
   GST_CAT_DEBUG (GST_CAT_CLOCK, "unscheduling entry %p", entry);
 
   GST_OBJECT_LOCK (clock);
   entry->status = GST_CLOCK_UNSCHEDULED;
   GST_CAT_DEBUG (GST_CAT_CLOCK, "send signal");
-  GST_CLOCK_BROADCAST (clock);
+  g_main_context_wakeup (sysclock->context);
   GST_OBJECT_UNLOCK (clock);
 }
Index: gst/gstsystemclock.h
===================================================================
RCS file: /cvs/gstreamer/gstreamer/gst/gstsystemclock.h,v
retrieving revision 1.15
diff -u -r1.15 gstsystemclock.h
--- gst/gstsystemclock.h	28 Oct 2005 18:14:24 -0000	1.15
+++ gst/gstsystemclock.h	20 Oct 2006 12:25:45 -0000
@@ -41,6 +41,17 @@
 typedef struct _GstSystemClockClass GstSystemClockClass;
 
 /**
+ * GstClockType:
+ * @GST_CLOCK_TYPE_REALTIME       : time since Epoch
+ * @GST_CLOCK_TYPE_MONOTONIC      : monotonic time since some unspecified
+ *                                  starting point
+ */
+typedef enum {
+  GST_CLOCK_TYPE_REALTIME       = 0,
+  GST_CLOCK_TYPE_MONOTONIC      = 1,
+} GstClockType;
+
+/**
  * GstSystemClock:
  * @clock: The parent clock
  *
@@ -50,10 +61,12 @@
   GstClock 	 clock;
 
   /*< private >*/
+  GstClockType   clock_type;
   GThread	*thread;	/* thread for async notify */
   gboolean 	 stopping;
+  GMainContext  *context;       /* context for waiting */
 
-  gpointer _gst_reserved[GST_PADDING];
+  gpointer _gst_reserved[GST_PADDING - 2];
 };
 
 struct _GstSystemClockClass {
Index: tests/check/gst/gstsystemclock.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/tests/check/gst/gstsystemclock.c,v
retrieving revision 1.8
diff -u -r1.8 gstsystemclock.c
--- tests/check/gst/gstsystemclock.c	1 Jul 2006 20:56:55 -0000	1.8
+++ tests/check/gst/gstsystemclock.c	20 Oct 2006 12:25:45 -0000
@@ -20,6 +20,7 @@
  */
 
 #include <gst/check/gstcheck.h>
+#include <gst/gstconfig.h>
 
 GST_START_TEST (test_signedness)
 {
@@ -36,9 +37,11 @@
   }
 }
 
-GST_END_TEST
+GST_END_TEST;
+
 #define TIME_UNIT (GST_SECOND / 5)
-    static void
+
+static void
 gst_clock_debug (GstClock * clock)
 {
   GstClockTime time;
@@ -65,7 +68,8 @@
   return FALSE;
 }
 
-GST_START_TEST (test_single_shot)
+static
+void single_shot (GstClockType clock_type)
 {
   GstClock *clock;
   GstClockID id, id2;
@@ -75,6 +79,8 @@
   clock = gst_system_clock_obtain ();
   fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
 
+  g_object_set (G_OBJECT (clock), "clock-type", clock_type, NULL);
+
   gst_clock_debug (clock);
   base = gst_clock_get_time (clock);
 
@@ -127,8 +133,24 @@
   g_usleep (TIME_UNIT / (2 * 1000));
 }
 
-GST_END_TEST
-GST_START_TEST (test_periodic_shot)
+GST_START_TEST (test_single_shot)
+{
+  single_shot (GST_CLOCK_TYPE_REALTIME);
+}
+
+GST_END_TEST;
+
+#if GST_HAVE_MONOTONIC_CLOCK
+GST_START_TEST (test_single_shot_monotonic)
+{
+  single_shot (GST_CLOCK_TYPE_MONOTONIC);
+}
+
+GST_END_TEST;
+#endif
+
+static void
+periodic_shot (GstClockType clock_type)
 {
   GstClock *clock;
   GstClockID id, id2;
@@ -138,6 +160,8 @@
   clock = gst_system_clock_obtain ();
   fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
 
+  g_object_set (G_OBJECT (clock), "clock-type", clock_type, NULL);
+
   gst_clock_debug (clock);
   base = gst_clock_get_time (clock);
 
@@ -189,7 +213,22 @@
   gst_clock_id_unref (id);
 }
 
-GST_END_TEST
+GST_START_TEST (test_periodic_shot)
+{
+  periodic_shot (GST_CLOCK_TYPE_REALTIME);
+}
+
+GST_END_TEST;
+
+#if GST_HAVE_MONOTONIC_CLOCK
+GST_START_TEST (test_periodic_shot_monotonic)
+{
+  periodic_shot (GST_CLOCK_TYPE_MONOTONIC);
+}
+
+GST_END_TEST;
+#endif
+
 GST_START_TEST (test_diff)
 {
   GstClockTime time1[] =
@@ -203,7 +242,10 @@
     fail_if (d[i] != GST_CLOCK_DIFF (time1[i], time2[i]));
   }
 }
-GST_END_TEST Suite *
+
+GST_END_TEST;
+
+Suite *
 gst_systemclock_suite (void)
 {
   Suite *s = suite_create ("GstSystemClock");
@@ -212,7 +254,13 @@
   suite_add_tcase (s, tc_chain);
   tcase_add_test (tc_chain, test_signedness);
   tcase_add_test (tc_chain, test_single_shot);
+#if GST_HAVE_MONOTONIC_CLOCK
+  tcase_add_test (tc_chain, test_single_shot_monotonic);
+#endif
   tcase_add_test (tc_chain, test_periodic_shot);
+#if GST_HAVE_MONOTONIC_CLOCK
+  tcase_add_test (tc_chain, test_periodic_shot_monotonic);
+#endif
   tcase_add_test (tc_chain, test_diff);
 
   return s;
