aboutsummaryrefslogtreecommitdiff
path: root/gst/gstsystemclock.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/gstsystemclock.c')
-rw-r--r--gst/gstsystemclock.c120
1 files changed, 70 insertions, 50 deletions
diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c
index b592813..7c461c9 100644
--- a/gst/gstsystemclock.c
+++ b/gst/gstsystemclock.c
@@ -57,14 +57,25 @@
#define GET_ENTRY_STATUS(e) ((GstClockReturn) g_atomic_int_get(&GST_CLOCK_ENTRY_STATUS(e)))
#define SET_ENTRY_STATUS(e,val) (g_atomic_int_set(&GST_CLOCK_ENTRY_STATUS(e),(val)))
-#define CAS_ENTRY_STATUS(e,old,val) (G_ATOMIC_INT_COMPARE_AND_EXCHANGE(\
+#define CAS_ENTRY_STATUS(e,old,val) (g_atomic_int_compare_and_exchange(\
(&GST_CLOCK_ENTRY_STATUS(e)), (old), (val)))
/* Define this to get some extra debug about jitter from each clock_wait */
#undef WAIT_DEBUGGING
+#define GST_SYSTEM_CLOCK_GET_COND(clock) (&GST_SYSTEM_CLOCK_CAST(clock)->priv->entries_changed)
+#define GST_SYSTEM_CLOCK_WAIT(clock) g_cond_wait(GST_SYSTEM_CLOCK_GET_COND(clock),GST_OBJECT_GET_LOCK(clock))
+#define GST_SYSTEM_CLOCK_TIMED_WAIT(clock,tv) g_cond_timed_wait(GST_SYSTEM_CLOCK_GET_COND(clock),GST_OBJECT_GET_LOCK(clock),tv)
+#define GST_SYSTEM_CLOCK_BROADCAST(clock) g_cond_broadcast(GST_SYSTEM_CLOCK_GET_COND(clock))
+
struct _GstSystemClockPrivate
{
+ GThread *thread; /* thread for async notify */
+ gboolean stopping;
+
+ GList *entries;
+ GCond entries_changed;
+
GstClockType clock_type;
GstPoll *timer;
gint wakeup_count; /* the number of entries with a pending wakeup */
@@ -121,12 +132,11 @@ static void gst_system_clock_async_thread (GstClock * clock);
static gboolean gst_system_clock_start_async (GstSystemClock * clock);
static void gst_system_clock_add_wakeup (GstSystemClock * sysclock);
-static GStaticMutex _gst_sysclock_mutex = G_STATIC_MUTEX_INIT;
-
-static GstClockClass *parent_class = NULL;
+static GMutex _gst_sysclock_mutex;
/* static guint gst_system_clock_signals[LAST_SIGNAL] = { 0 }; */
+#define gst_system_clock_parent_class parent_class
G_DEFINE_TYPE (GstSystemClock, gst_system_clock, GST_TYPE_CLOCK);
static void
@@ -138,8 +148,6 @@ gst_system_clock_class_init (GstSystemClockClass * klass)
gobject_class = (GObjectClass *) klass;
gstclock_class = (GstClockClass *) klass;
- parent_class = g_type_class_peek_parent (klass);
-
g_type_class_add_private (klass, sizeof (GstSystemClockPrivate));
gobject_class->dispose = gst_system_clock_dispose;
@@ -162,23 +170,28 @@ gst_system_clock_class_init (GstSystemClockClass * klass)
static void
gst_system_clock_init (GstSystemClock * clock)
{
+ GstSystemClockPrivate *priv;
+
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->priv = GST_SYSTEM_CLOCK_GET_PRIVATE (clock);
+ clock->priv = priv = GST_SYSTEM_CLOCK_GET_PRIVATE (clock);
- clock->priv->clock_type = DEFAULT_CLOCK_TYPE;
- clock->priv->timer = gst_poll_new_timer ();
+ priv->clock_type = DEFAULT_CLOCK_TYPE;
+ priv->timer = gst_poll_new_timer ();
+
+ priv->entries = NULL;
+ g_cond_init (&priv->entries_changed);
#ifdef G_OS_WIN32
- QueryPerformanceFrequency (&clock->priv->frequency);
+ QueryPerformanceFrequency (&priv->frequency);
/* can be 0 if the hardware does not have hardware support */
- if (clock->priv->frequency.QuadPart != 0)
+ if (priv->frequency.QuadPart != 0)
/* we take a base time so that time starts from 0 to ease debugging */
- QueryPerformanceCounter (&clock->priv->start);
+ QueryPerformanceCounter (&priv->start);
#endif /* G_OS_WIN32 */
#if 0
@@ -194,32 +207,34 @@ gst_system_clock_dispose (GObject * object)
{
GstClock *clock = (GstClock *) object;
GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
+ GstSystemClockPrivate *priv = sysclock->priv;
GList *entries;
/* else we have to stop the thread */
GST_OBJECT_LOCK (clock);
- sysclock->stopping = TRUE;
+ priv->stopping = TRUE;
/* unschedule all entries */
- for (entries = clock->entries; entries; entries = g_list_next (entries)) {
+ for (entries = priv->entries; entries; entries = g_list_next (entries)) {
GstClockEntry *entry = (GstClockEntry *) entries->data;
GST_CAT_DEBUG (GST_CAT_CLOCK, "unscheduling entry %p", entry);
SET_ENTRY_STATUS (entry, GST_CLOCK_UNSCHEDULED);
}
- GST_CLOCK_BROADCAST (clock);
+ GST_SYSTEM_CLOCK_BROADCAST (clock);
gst_system_clock_add_wakeup (sysclock);
GST_OBJECT_UNLOCK (clock);
- if (sysclock->thread)
- g_thread_join (sysclock->thread);
- sysclock->thread = NULL;
+ if (priv->thread)
+ g_thread_join (priv->thread);
+ priv->thread = NULL;
GST_CAT_DEBUG (GST_CAT_CLOCK, "joined thread");
- g_list_foreach (clock->entries, (GFunc) gst_clock_id_unref, NULL);
- g_list_free (clock->entries);
- clock->entries = NULL;
+ g_list_foreach (priv->entries, (GFunc) gst_clock_id_unref, NULL);
+ g_list_free (priv->entries);
+ priv->entries = NULL;
- gst_poll_free (sysclock->priv->timer);
+ gst_poll_free (priv->timer);
+ g_cond_clear (&priv->entries_changed);
G_OBJECT_CLASS (parent_class)->dispose (object);
@@ -279,7 +294,7 @@ gst_system_clock_obtain (void)
{
GstClock *clock;
- g_static_mutex_lock (&_gst_sysclock_mutex);
+ g_mutex_lock (&_gst_sysclock_mutex);
clock = _the_system_clock;
if (clock == NULL) {
@@ -292,9 +307,9 @@ gst_system_clock_obtain (void)
gst_object_ref_sink (clock);
_the_system_clock = clock;
- g_static_mutex_unlock (&_gst_sysclock_mutex);
+ g_mutex_unlock (&_gst_sysclock_mutex);
} else {
- g_static_mutex_unlock (&_gst_sysclock_mutex);
+ g_mutex_unlock (&_gst_sysclock_mutex);
GST_CAT_DEBUG (GST_CAT_CLOCK, "returning static system clock");
}
@@ -315,7 +330,7 @@ gst_system_clock_remove_wakeup (GstSystemClock * sysclock)
while (!gst_poll_read_control (sysclock->priv->timer)) {
g_warning ("gstsystemclock: read control failed, trying again\n");
}
- GST_CLOCK_BROADCAST (sysclock);
+ GST_SYSTEM_CLOCK_BROADCAST (sysclock);
}
GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup count %d",
sysclock->priv->wakeup_count);
@@ -349,7 +364,7 @@ static void
gst_system_clock_wait_wakeup (GstSystemClock * sysclock)
{
while (sysclock->priv->wakeup_count > 0) {
- GST_CLOCK_WAIT (sysclock);
+ GST_SYSTEM_CLOCK_WAIT (sysclock);
}
}
@@ -369,38 +384,39 @@ static void
gst_system_clock_async_thread (GstClock * clock)
{
GstSystemClock *sysclock = GST_SYSTEM_CLOCK_CAST (clock);
+ GstSystemClockPrivate *priv = sysclock->priv;
GST_CAT_DEBUG (GST_CAT_CLOCK, "enter system clock thread");
GST_OBJECT_LOCK (clock);
/* signal spinup */
- GST_CLOCK_BROADCAST (clock);
+ GST_SYSTEM_CLOCK_BROADCAST (clock);
/* now enter our (almost) infinite loop */
- while (!sysclock->stopping) {
+ while (!priv->stopping) {
GstClockEntry *entry;
GstClockTime requested;
GstClockReturn res;
/* check if something to be done */
- while (clock->entries == NULL) {
+ while (priv->entries == NULL) {
GST_CAT_DEBUG (GST_CAT_CLOCK, "no clock entries, waiting..");
/* wait for work to do */
- GST_CLOCK_WAIT (clock);
+ GST_SYSTEM_CLOCK_WAIT (clock);
GST_CAT_DEBUG (GST_CAT_CLOCK, "got signal");
/* clock was stopping, exit */
- if (sysclock->stopping)
+ if (priv->stopping)
goto exit;
}
/* see if we have a pending wakeup because the order of the list
* changed. */
- if (sysclock->priv->async_wakeup) {
+ if (priv->async_wakeup) {
GST_CAT_DEBUG (GST_CAT_CLOCK, "clear async wakeup");
gst_system_clock_remove_wakeup (sysclock);
- sysclock->priv->async_wakeup = FALSE;
+ priv->async_wakeup = FALSE;
}
/* pick the next entry */
- entry = clock->entries->data;
+ entry = priv->entries->data;
GST_OBJECT_UNLOCK (clock);
requested = entry->time;
@@ -435,8 +451,8 @@ gst_system_clock_async_thread (GstClock * clock)
/* adjust time now */
entry->time = requested + entry->interval;
/* and resort the list now */
- clock->entries =
- g_list_sort (clock->entries, gst_clock_id_compare_func);
+ priv->entries =
+ g_list_sort (priv->entries, gst_clock_id_compare_func);
/* and restart */
continue;
} else {
@@ -465,12 +481,12 @@ gst_system_clock_async_thread (GstClock * clock)
}
next_entry:
/* we remove the current entry and unref it */
- clock->entries = g_list_remove (clock->entries, entry);
+ priv->entries = g_list_remove (priv->entries, entry);
gst_clock_id_unref ((GstClockID) entry);
}
exit:
/* signal exit */
- GST_CLOCK_BROADCAST (clock);
+ GST_SYSTEM_CLOCK_BROADCAST (clock);
GST_OBJECT_UNLOCK (clock);
GST_CAT_DEBUG (GST_CAT_CLOCK, "exit system clock thread");
}
@@ -731,17 +747,19 @@ static gboolean
gst_system_clock_start_async (GstSystemClock * clock)
{
GError *error = NULL;
+ GstSystemClockPrivate *priv = clock->priv;
- if (G_LIKELY (clock->thread != NULL))
+ if (G_LIKELY (priv->thread != NULL))
return TRUE; /* Thread already running. Nothing to do */
- clock->thread = g_thread_create ((GThreadFunc) gst_system_clock_async_thread,
- clock, TRUE, &error);
+ priv->thread = g_thread_try_new ("GstSystemClock",
+ (GThreadFunc) gst_system_clock_async_thread, clock, &error);
+
if (G_UNLIKELY (error))
goto no_thread;
/* wait for it to spin up */
- GST_CLOCK_WAIT (clock);
+ GST_SYSTEM_CLOCK_WAIT (clock);
return TRUE;
@@ -765,9 +783,11 @@ static GstClockReturn
gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
{
GstSystemClock *sysclock;
+ GstSystemClockPrivate *priv;
GstClockEntry *head;
sysclock = GST_SYSTEM_CLOCK_CAST (clock);
+ priv = sysclock->priv;
GST_CAT_DEBUG (GST_CAT_CLOCK, "adding async entry %p", entry);
@@ -779,27 +799,27 @@ gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
if (G_UNLIKELY (GET_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED))
goto was_unscheduled;
- if (clock->entries)
- head = clock->entries->data;
+ if (priv->entries)
+ head = priv->entries->data;
else
head = NULL;
/* need to take a ref */
gst_clock_id_ref ((GstClockID) entry);
/* insert the entry in sorted order */
- clock->entries = g_list_insert_sorted (clock->entries, entry,
+ priv->entries = g_list_insert_sorted (priv->entries, entry,
gst_clock_id_compare_func);
/* only need to send the signal if the entry was added to the
* front, else the thread is just waiting for another entry and
* will get to this entry automatically. */
- if (clock->entries->data == entry) {
+ if (priv->entries->data == entry) {
GST_CAT_DEBUG (GST_CAT_CLOCK, "async entry added to head %p", head);
if (head == NULL) {
/* the list was empty before, signal the cond so that the async thread can
* start taking a look at the queue */
GST_CAT_DEBUG (GST_CAT_CLOCK, "first entry, sending signal");
- GST_CLOCK_BROADCAST (clock);
+ GST_SYSTEM_CLOCK_BROADCAST (clock);
} else {
GstClockReturn status;
@@ -810,9 +830,9 @@ gst_system_clock_id_wait_async (GstClock * clock, GstClockEntry * entry)
GST_CAT_DEBUG (GST_CAT_CLOCK, "head entry is busy");
/* the async thread was waiting for an entry, unlock the wait so that it
* looks at the new head entry instead, we only need to do this once */
- if (!sysclock->priv->async_wakeup) {
+ if (!priv->async_wakeup) {
GST_CAT_DEBUG (GST_CAT_CLOCK, "wakeup async thread");
- sysclock->priv->async_wakeup = TRUE;
+ priv->async_wakeup = TRUE;
gst_system_clock_add_wakeup (sysclock);
}
}