- Keep track of pending clock waits so we can unlock them
authorWim Taymans <wim.taymans@gmail.com>
Fri, 27 Dec 2002 04:11:59 +0000 (04:11 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Fri, 27 Dec 2002 04:11:59 +0000 (04:11 +0000)
Original commit message from CVS:
- Keep track of pending clock waits so we can unlock them
- don't wait when diff bigger than configurable max to avoid clock lockups

gst/gstclock.c
gst/gstclock.h
gst/gstsystemclock.c
gst/gstsystemclock.h

index f1ff4c7..e27b2b7 100644 (file)
 #include "gstlog.h"
 #include "gstmemchunk.h"
 
+#define DEFAULT_MAX_DIFF       (2 * GST_SECOND)
+
 enum {
   ARG_0,
   ARG_STATS,
+  ARG_MAX_DIFF,
 };
 
 static GstMemChunk *_gst_clock_entries_chunk;
@@ -157,21 +160,28 @@ gst_clock_id_wait (GstClockID id, GstClockTimeDiff *jitter)
   requested = GST_CLOCK_ENTRY_TIME (entry);
 
   if (requested == GST_CLOCK_TIME_NONE) {
-    res = GST_CLOCK_TIMEOUT;
-    goto done;
+    return GST_CLOCK_TIMEOUT;
   }
-  
+
   clock = GST_CLOCK_ENTRY_CLOCK (entry);
   cclass = GST_CLOCK_GET_CLASS (clock);
   
   if (cclass->wait) {
     GstClockTime now;
+    
+    GST_LOCK (clock);
+    clock->entries = g_list_prepend (clock->entries, entry);
+    GST_UNLOCK (clock);
 
     do {
       res = cclass->wait (clock, entry);
     }
     while (res == GST_CLOCK_ENTRY_RESTART);
 
+    GST_LOCK (clock);
+    clock->entries = g_list_remove (clock->entries, entry);
+    GST_UNLOCK (clock);
+
     if (jitter) {
       now = gst_clock_get_time (clock);
       *jitter = now - requested;
@@ -182,11 +192,6 @@ gst_clock_id_wait (GstClockID id, GstClockTimeDiff *jitter)
     }
   }
 
-done:
-  if (entry->type == GST_CLOCK_ENTRY_SINGLE) {
-    gst_clock_id_free (id);
-  }
-
   return res;
 }
 
@@ -233,6 +238,14 @@ gst_clock_id_wait_async (GstClockID id,
   return res;
 }
 
+static void
+gst_clock_reschedule_func (GstClockEntry *entry)
+{
+  entry->status = GST_CLOCK_ENTRY_OK;
+  
+  gst_clock_id_unlock ((GstClockID)entry);
+}
+
 /**
  * gst_clock_id_unschedule:
  * @id: The id to unschedule
@@ -350,11 +363,16 @@ gst_clock_class_init (GstClockClass *klass)
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STATS,
     g_param_spec_boolean ("stats", "Stats", "Enable clock stats",
                           FALSE, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_DIFF,
+    g_param_spec_int64 ("max-diff", "Max diff", "The maximum amount of time to wait in nanoseconds",
+                        0, G_MAXINT64, DEFAULT_MAX_DIFF, G_PARAM_READWRITE));
 }
 
 static void
 gst_clock_init (GstClock *clock)
 {
+  clock->max_diff = DEFAULT_MAX_DIFF;
+
   clock->speed = 1.0;
   clock->active = FALSE;
   clock->start_time = 0;
@@ -489,6 +507,7 @@ gst_clock_set_active (GstClock *clock, gboolean active)
     clock->last_time = time - clock->start_time;
     clock->accept_discont = FALSE;
   }
+  g_list_foreach (clock->entries, (GFunc) gst_clock_reschedule_func, NULL);
   GST_UNLOCK (clock);
 
   g_mutex_lock (clock->active_mutex);  
@@ -536,6 +555,7 @@ gst_clock_reset (GstClock *clock)
   clock->active = FALSE;
   clock->start_time = time;
   clock->last_time = 0LL;
+  g_list_foreach (clock->entries, (GFunc) gst_clock_reschedule_func, NULL);
   GST_UNLOCK (clock);
 }
 
@@ -583,6 +603,7 @@ gst_clock_handle_discont (GstClock *clock, guint64 time)
   clock->start_time = itime - time;
   clock->last_time = time;
   clock->accept_discont = FALSE;
+  g_list_foreach (clock->entries, (GFunc) gst_clock_reschedule_func, NULL);
   GST_UNLOCK (clock);
 
   GST_DEBUG (GST_CAT_CLOCK, "new time %" G_GUINT64_FORMAT,
@@ -675,6 +696,9 @@ gst_clock_set_property (GObject *object, guint prop_id,
     case ARG_STATS:
       clock->stats = g_value_get_boolean (value);
       break;
+    case ARG_MAX_DIFF:
+      clock->max_diff = g_value_get_int64 (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -693,6 +717,9 @@ gst_clock_get_property (GObject *object, guint prop_id,
     case ARG_STATS:
       g_value_set_boolean (value, clock->stats);
       break;
+    case ARG_MAX_DIFF:
+      g_value_set_int64 (value, clock->max_diff);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
index 2dbe757..f5f9d60 100644 (file)
@@ -122,6 +122,7 @@ struct _GstClock {
   /* --- protected --- */
   GstClockTime  start_time;
   GstClockTime  last_time;
+  gint64        max_diff;
 
   /* --- private --- */
   gboolean      accept_discont;
index 174a777..e32f8ae 100644 (file)
@@ -24,6 +24,7 @@
 
 /* #define GST_DEBUG_ENABLED */
 #include "gst_private.h"
+#include "gstlog.h"
 
 #include "gstsystemclock.h"
 
@@ -35,6 +36,7 @@ static void                   gst_system_clock_init           (GstSystemClock *clock);
 static GstClockTime            gst_system_clock_get_internal_time      (GstClock *clock);
 static guint64                 gst_system_clock_get_resolution (GstClock *clock);
 static GstClockEntryStatus     gst_system_clock_wait           (GstClock *clock, GstClockEntry *entry);
+static void                    gst_system_clock_unlock         (GstClock *clock, GstClockEntry *entry);
 
 static GCond   *_gst_sysclock_cond = NULL;
 static GMutex  *_gst_sysclock_mutex = NULL;
@@ -82,6 +84,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_wait;
+  gstclock_class->unlock               = gst_system_clock_unlock;
 
   _gst_sysclock_cond  = g_cond_new ();
   _gst_sysclock_mutex = g_mutex_new ();
@@ -129,12 +132,19 @@ gst_system_clock_get_resolution (GstClock *clock)
 static GstClockEntryStatus
 gst_system_clock_wait (GstClock *clock, GstClockEntry *entry)
 {
-  GstClockEntryStatus res = GST_CLOCK_ENTRY_OK;
+  GstClockEntryStatus res;
   GstClockTime current, target;
+  gint64 diff;
 
   current = gst_clock_get_time (clock);
-  target = gst_system_clock_get_internal_time (clock) +
-           GST_CLOCK_ENTRY_TIME (entry) - current;
+  diff = GST_CLOCK_ENTRY_TIME (entry) - current;
+
+  if (ABS (diff) > clock->max_diff) {
+    g_warning ("abnormal clock request diff: %lld > %lld", diff, clock->max_diff);
+    return GST_CLOCK_ENTRY_EARLY;
+  }
+  
+  target = gst_system_clock_get_internal_time (clock) + diff;
 
   GST_DEBUG (GST_CAT_CLOCK, "real_target %" G_GUINT64_FORMAT
                            " target %" G_GUINT64_FORMAT
@@ -148,6 +158,7 @@ gst_system_clock_wait (GstClock *clock, GstClockEntry *entry)
     g_mutex_lock (_gst_sysclock_mutex);
     g_cond_timed_wait (_gst_sysclock_cond, _gst_sysclock_mutex, &tv);
     g_mutex_unlock (_gst_sysclock_mutex);
+    res = entry->status;
   }
   else {
     res = GST_CLOCK_ENTRY_EARLY;
@@ -155,3 +166,10 @@ gst_system_clock_wait (GstClock *clock, GstClockEntry *entry)
   return res;
 }
 
+static void
+gst_system_clock_unlock (GstClock *clock, GstClockEntry *entry)
+{
+  g_mutex_lock (_gst_sysclock_mutex);
+  g_cond_broadcast (_gst_sysclock_cond);
+  g_mutex_unlock (_gst_sysclock_mutex);
+}
index 674901d..49cffea 100644 (file)
@@ -40,11 +40,11 @@ typedef struct _GstSystemClock GstSystemClock;
 typedef struct _GstSystemClockClass GstSystemClockClass;
 
 struct _GstSystemClock {
-  GstClock clock;
+  GstClock      clock;
 };
 
 struct _GstSystemClockClass {
-  GstClockClass parent_class;
+  GstClockClass  parent_class;
 };
 
 GType                  gst_system_clock_get_type       (void);