summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2002-12-27 04:11:59 +0000
committerWim Taymans <wim.taymans@gmail.com>2002-12-27 04:11:59 +0000
commit290a082d535c6d316fe03bfa16b7566dc191ea2b (patch)
tree18b77f36692ba6f066e6a24c938b7a82ef52ae71
parentfb9970d85ad9ca8445dc0673f1dd4a51284d8e51 (diff)
downloadgstreamer-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.c43
-rw-r--r--gst/gstclock.h1
-rw-r--r--gst/gstsystemclock.c24
-rw-r--r--gst/gstsystemclock.h4
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);