Port gtk-doc comments to their equivalent markdown syntax
[platform/upstream/gstreamer.git] / libs / gst / check / gsttestclock.c
index 6bdde06..ab90e49 100644 (file)
@@ -23,6 +23,7 @@
 
 /**
  * SECTION:gsttestclock
+ * @title: GstTestClock
  * @short_description: Controllable, deterministic clock for GStreamer unit tests
  * @see_also: #GstSystemClock, #GstClock
  *
  * precisely advance the time in a deterministic manner, independent of the
  * system time or any other external factors.
  *
- * <example>
- * <title>Advancing the time of a #GstTestClock</title>
- *   <programlisting language="c">
- *   #include &lt;gst/gst.h&gt;
- *   #include &lt;gst/check/gsttestclock.h&gt;
+ * ## Advancing the time of a #GstTestClock
+ *
+ * |[<!-- language="C" -->
+ *   #include <gst/gst.h>
+ *   #include <gst/check/gsttestclock.h>
  *
  *   GstClock *clock;
  *   GstTestClock *test_clock;
@@ -53,8 +54,7 @@
  *   gst_test_clock_set_time (test_clock, 42 * GST_SECOND);
  *   GST_INFO ("Time: %" GST_TIME_FORMAT, GST_TIME_ARGS (gst_clock_get_time (clock)));
  *   ...
- *   </programlisting>
- * </example>
+ * ]|
  *
  * #GstClock allows for setting up single shot or periodic clock notifications
  * as well as waiting for these notifications synchronously (using
  * second buffer will arrive a little late (7ms) due to simulated jitter in the
  * clock notification.
  *
- * <example>
- * <title>Demonstration of how to work with clock notifications and #GstTestClock</title>
- *   <programlisting language="c">
- *   #include &lt;gst/gst.h&gt;
- *   #include &lt;gst/check/gstcheck.h&gt;
- *   #include &lt;gst/check/gsttestclock.h&gt;
+ * ## Demonstration of how to work with clock notifications and #GstTestClock
+ *
+ * |[<!-- language="C" -->
+ *   #include <gst/gst.h>
+ *   #include <gst/check/gstcheck.h>
+ *   #include <gst/check/gsttestclock.h>
  *
  *   GstClockTime latency;
  *   GstElement *element;
  *   g_assert_cmpint (GST_BUFFER_TIMESTAMP (buf), ==, latency);
  *   gst_buffer_unref (buf);
  *   GST_INFO ("Check that element does not wait for any clock notification\n");
- *   g_assert (gst_test_clock_peek_next_pending_id (test_clock, NULL) == FALSE);
+ *   g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL));
  *
  *   GST_INFO ("Set time, create and push the second buffer\n");
  *   gst_test_clock_advance_time (test_clock, 10 * GST_SECOND);
  *       10 * GST_SECOND + latency + 7 * GST_MSECOND);
  *   gst_buffer_unref (buf);
  *   GST_INFO ("Check that element does not wait for any clock notification\n");
- *   g_assert (gst_test_clock_peek_next_pending_id (test_clock, NULL) == FALSE);
+ *   g_assert (!gst_test_clock_peek_next_pending_id (test_clock, NULL));
  *   ...
- *   </programlisting>
- * </example>
+ * ]|
  *
  * Since #GstTestClock is only supposed to be used in unit tests it calls
  * g_assert(), g_assert_cmpint() or g_assert_cmpuint() to validate all function
 enum
 {
   PROP_0,
-  PROP_START_TIME
+  PROP_START_TIME,
+  PROP_CLOCK_TYPE
 };
 
 typedef struct _GstClockEntryContext GstClockEntryContext;
@@ -196,6 +196,7 @@ struct _GstClockEntryContext
 
 struct _GstTestClockPrivate
 {
+  GstClockType clock_type;
   GstClockTime start_time;
   GstClockTime internal_time;
   GList *entry_contexts;
@@ -203,6 +204,8 @@ struct _GstTestClockPrivate
   GCond entry_processed_cond;
 };
 
+#define DEFAULT_CLOCK_TYPE GST_CLOCK_TYPE_MONOTONIC
+
 #define GST_TEST_CLOCK_GET_PRIVATE(obj) ((GST_TEST_CLOCK_CAST (obj))->priv)
 
 GST_DEBUG_CATEGORY_STATIC (test_clock_debug);
@@ -287,6 +290,13 @@ gst_test_clock_class_init (GstTestClockClass * klass)
       "Start Time of the Clock", 0, G_MAXUINT64, 0,
       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
   g_object_class_install_property (gobject_class, PROP_START_TIME, pspec);
+
+  g_object_class_install_property (gobject_class, PROP_CLOCK_TYPE,
+      g_param_spec_enum ("clock-type", "Clock type",
+          "The kind of clock implementation to be reported by this clock",
+          GST_TYPE_CLOCK_TYPE, DEFAULT_CLOCK_TYPE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
 }
 
 static void
@@ -301,6 +311,7 @@ gst_test_clock_init (GstTestClock * test_clock)
 
   g_cond_init (&priv->entry_added_cond);
   g_cond_init (&priv->entry_processed_cond);
+  priv->clock_type = DEFAULT_CLOCK_TYPE;
 
   GST_OBJECT_FLAG_SET (test_clock,
       GST_CLOCK_FLAG_CAN_DO_SINGLE_SYNC |
@@ -361,6 +372,9 @@ gst_test_clock_get_property (GObject * object, guint property_id,
     case PROP_START_TIME:
       g_value_set_uint64 (value, priv->start_time);
       break;
+    case PROP_CLOCK_TYPE:
+      g_value_set_enum (value, priv->clock_type);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -381,6 +395,11 @@ gst_test_clock_set_property (GObject * object, guint property_id,
           "test clock start time initialized at %" GST_TIME_FORMAT,
           GST_TIME_ARGS (priv->start_time));
       break;
+    case PROP_CLOCK_TYPE:
+      priv->clock_type = (GstClockType) g_value_get_enum (value);
+      GST_CAT_DEBUG (GST_CAT_TEST_CLOCK, "clock-type set to %d",
+          priv->clock_type);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -624,24 +643,20 @@ process_entry_context_unlocked (GstTestClock * test_clock,
   }
 }
 
-static GstTestClockIDList *
+static GList *
 gst_test_clock_get_pending_id_list_unlocked (GstTestClock * test_clock)
 {
   GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-  GstTestClockIDList *result = g_new0 (GstTestClockIDList, 1);
+  GQueue queue = G_QUEUE_INIT;
+  GList *cur;
 
-  if (priv->entry_contexts != NULL) {
-    GList *cur;
-    for (cur = priv->entry_contexts; cur != NULL; cur = cur->next) {
-      GstClockEntryContext *ctx = cur->data;
+  for (cur = priv->entry_contexts; cur != NULL; cur = cur->next) {
+    GstClockEntryContext *ctx = cur->data;
 
-      result->cur =
-          g_list_append (result->cur, gst_clock_id_ref (ctx->clock_entry));
-    }
+    g_queue_push_tail (&queue, gst_clock_id_ref (ctx->clock_entry));
   }
-  result->length = g_list_length (result->cur);
 
-  return result;
+  return queue.head;
 }
 
 /**
@@ -987,7 +1002,9 @@ gst_test_clock_get_next_entry_time (GstTestClock * test_clock)
  * gst_test_clock_wait_for_multiple_pending_ids:
  * @test_clock: #GstTestClock for which to await having enough pending clock
  * @count: the number of pending clock notifications to wait for
- * @pending_list: A #GstTestClockIDList with pending #GstClockIDs
+ * @pending_list: (out) (element-type Gst.ClockID) (transfer full) (allow-none): Address
+ *     of a #GList pointer variable to store the list of pending #GstClockIDs
+ *     that expired, or %NULL
  *
  * Blocks until at least @count clock notifications have been requested from
  * @test_clock. There is no timeout for this wait, see the main description of
@@ -999,7 +1016,7 @@ gst_test_clock_get_next_entry_time (GstTestClock * test_clock)
  */
 void
 gst_test_clock_wait_for_multiple_pending_ids (GstTestClock * test_clock,
-    guint count, GstTestClockIDList ** pending_list)
+    guint count, GList ** pending_list)
 {
   GstTestClockPrivate *priv;
 
@@ -1020,9 +1037,10 @@ gst_test_clock_wait_for_multiple_pending_ids (GstTestClock * test_clock,
 /**
  * gst_test_clock_process_id_list:
  * @test_clock: #GstTestClock for which to process the pending IDs
- * @pending_list: A #GstTestClockIDList with pending #GstClockIDs
+ * @pending_list: (element-type Gst.ClockID) (transfer none) (allow-none): List
+ *     of pending #GstClockIDs
  *
- * Processes and releases the pending IDs in #GstTestClockIDList
+ * Processes and releases the pending IDs in the list.
  *
  * MT safe.
  *
@@ -1030,16 +1048,16 @@ gst_test_clock_wait_for_multiple_pending_ids (GstTestClock * test_clock,
  */
 guint
 gst_test_clock_process_id_list (GstTestClock * test_clock,
-    GstTestClockIDList * pending_list)
+    const GList * pending_list)
 {
-  GList *cur;
+  const GList *cur;
   guint result = 0;
 
   g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), 0);
 
   GST_OBJECT_LOCK (test_clock);
 
-  for (cur = pending_list->cur; cur != NULL; cur = cur->next) {
+  for (cur = pending_list; cur != NULL; cur = cur->next) {
     GstClockID pending_id = cur->data;
     GstClockEntryContext *ctx =
         gst_test_clock_lookup_entry_context (test_clock, pending_id);
@@ -1055,21 +1073,22 @@ gst_test_clock_process_id_list (GstTestClock * test_clock,
 
 /**
  * gst_test_clock_id_list_get_latest_time:
- * @pending_list: A #GstTestClockIDList with pending #GstClockIDs
+ * @pending_list:  (element-type Gst.ClockID) (transfer none) (allow-none): List
+ *     of of pending #GstClockIDs
  *
- * Finds the latest time inside the #GstTestClockIDList
+ * Finds the latest time inside the list.
  *
  * MT safe.
  *
  * Since: 1.4
  */
 GstClockTime
-gst_test_clock_id_list_get_latest_time (GstTestClockIDList * pending_list)
+gst_test_clock_id_list_get_latest_time (const GList * pending_list)
 {
-  GList *cur;
+  const GList *cur;
   GstClockTime result = 0;
 
-  for (cur = pending_list->cur; cur != NULL; cur = cur->next) {
+  for (cur = pending_list; cur != NULL; cur = cur->next) {
     GstClockID *pending_id = cur->data;
     GstClockTime time = gst_clock_id_get_time (pending_id);
     if (time > result)
@@ -1080,25 +1099,46 @@ gst_test_clock_id_list_get_latest_time (GstTestClockIDList * pending_list)
 }
 
 /**
- * gst_test_clock_id_list_free:
- * @pending_list: A #GstTestClockIDList with pending #GstClockIDs
+ * gst_test_clock_crank:
+ * @test_clock: #GstTestClock to crank
+ *
+ * A "crank" consists of three steps:
+ * 1: Wait for a #GstClockID to be registered with the #GstTestClock.
+ * 2: Advance the #GstTestClock to the time the #GstClockID is waiting for.
+ * 3: Release the #GstClockID wait.
+ * A "crank" can be though of as the notion of
+ * manually driving the clock forward to its next logical step.
  *
- * Free the supplied #GstTestClockIDList
+ * Return: %TRUE if the crank was successful, %FALSE otherwise.
  *
  * MT safe.
  *
- * Since: 1.4
+ * Since: 1.8
  */
-void
-gst_test_clock_id_list_free (GstTestClockIDList * pending_list)
+gboolean
+gst_test_clock_crank (GstTestClock * test_clock)
 {
-  GList *cur;
+  GstClockID res, pending;
+  gboolean result;
 
-  for (cur = pending_list->cur; cur != NULL; cur = cur->next) {
-    GstClockID *pending_id = cur->data;
-    gst_clock_id_unref (pending_id);
+  gst_test_clock_wait_for_next_pending_id (test_clock, &pending);
+  gst_test_clock_set_time (test_clock, gst_clock_id_get_time (pending));
+  res = gst_test_clock_process_next_clock_id (test_clock);
+  if (G_LIKELY (res == pending)) {
+    GST_CAT_DEBUG_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
+        "cranked to time %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (gst_clock_get_time (GST_CLOCK (test_clock))));
+    result = TRUE;
+  } else {
+    GST_CAT_WARNING_OBJECT (GST_CAT_TEST_CLOCK, test_clock,
+        "testclock next id != pending (%p != %p)", res, pending);
+    result = FALSE;
   }
 
-  g_list_free (pending_list->cur);
-  g_free (pending_list);
+  if (G_LIKELY (res != NULL))
+    gst_clock_id_unref (res);
+
+  gst_clock_id_unref (pending);
+
+  return result;
 }