diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2002-12-27 04:11:59 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2002-12-27 04:11:59 +0000 |
commit | 290a082d535c6d316fe03bfa16b7566dc191ea2b (patch) | |
tree | 18b77f36692ba6f066e6a24c938b7a82ef52ae71 | |
parent | fb9970d85ad9ca8445dc0673f1dd4a51284d8e51 (diff) | |
download | gstreamer-290a082d535c6d316fe03bfa16b7566dc191ea2b.tar.gz |
- Keep track of pending clock waits so we can unlock them
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
-rw-r--r-- | gst/gstclock.c | 43 | ||||
-rw-r--r-- | gst/gstclock.h | 1 | ||||
-rw-r--r-- | gst/gstsystemclock.c | 24 | ||||
-rw-r--r-- | gst/gstsystemclock.h | 4 |
4 files changed, 59 insertions, 13 deletions
diff --git a/gst/gstclock.c b/gst/gstclock.c index f1ff4c7b0c..e27b2b7fe7 100644 --- a/gst/gstclock.c +++ b/gst/gstclock.c @@ -29,9 +29,12 @@ #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; diff --git a/gst/gstclock.h b/gst/gstclock.h index 2dbe757f41..f5f9d60cc6 100644 --- a/gst/gstclock.h +++ b/gst/gstclock.h @@ -122,6 +122,7 @@ struct _GstClock { /* --- protected --- */ GstClockTime start_time; GstClockTime last_time; + gint64 max_diff; /* --- private --- */ gboolean accept_discont; diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c index 174a777078..e32f8aeff9 100644 --- a/gst/gstsystemclock.c +++ b/gst/gstsystemclock.c @@ -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); +} diff --git a/gst/gstsystemclock.h b/gst/gstsystemclock.h index 674901d08b..49cffea0ba 100644 --- a/gst/gstsystemclock.h +++ b/gst/gstsystemclock.h @@ -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); |