Add the oss clock too.
authorWim Taymans <wim.taymans@gmail.com>
Sun, 3 Feb 2002 20:11:47 +0000 (20:11 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Sun, 3 Feb 2002 20:11:47 +0000 (20:11 +0000)
Original commit message from CVS:
Add the oss clock too.
This one shows that there should be more infrastructure to dispatch clock
events.

sys/oss/gstossclock.c [new file with mode: 0644]
sys/oss/gstossclock.h [new file with mode: 0644]

diff --git a/sys/oss/gstossclock.c b/sys/oss/gstossclock.c
new file mode 100644 (file)
index 0000000..625cb07
--- /dev/null
@@ -0,0 +1,329 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstclock.c: Clock subsystem for maintaining time sync
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gstossclock.h"
+
+static GMemChunk *_gst_clock_entries_chunk;
+static GMutex *_gst_clock_entries_chunk_lock;
+static GList *_gst_clock_entries_pool;
+
+typedef struct _GstClockEntry GstClockEntry;
+
+typedef enum {
+  GST_ENTRY_OK,
+  GST_ENTRY_RESTART,
+} GstEntryStatus;
+
+struct _GstClockEntry {
+  GstClockTime time;
+  GstEntryStatus status; 
+  GMutex *lock;
+  GCond *cond;
+};
+
+static void            gst_oss_clock_class_init        (GstOssClockClass *klass);
+static void            gst_oss_clock_init              (GstOssClock *clock);
+
+static void            gst_oss_clock_reset             (GstClock *clock);
+static void            gst_oss_clock_activate          (GstClock *clock, gboolean activate);
+static void            gst_oss_clock_set_time          (GstClock *clock, GstClockTime time);
+static GstClockReturn  gst_oss_clock_wait              (GstClock *clock, GstClockTime time);
+
+static GstSystemClockClass *parent_class = NULL;
+/* static guint gst_oss_clock_signals[LAST_SIGNAL] = { 0 }; */
+  
+GType
+gst_oss_clock_get_type (void)
+{ 
+  static GType clock_type = 0;
+           
+  if (!clock_type) {
+    static const GTypeInfo clock_info = {
+      sizeof (GstOssClockClass),
+      NULL,
+      NULL,
+      (GClassInitFunc) gst_oss_clock_class_init,
+      NULL,
+      NULL,
+      sizeof (GstOssClock),
+      4,
+      (GInstanceInitFunc) gst_oss_clock_init,
+      NULL
+    };
+    clock_type = g_type_register_static (GST_TYPE_SYSTEM_CLOCK, "GstOssClock",
+                                         &clock_info, 0);
+  }
+  return clock_type;
+}
+
+
+static void
+gst_oss_clock_class_init (GstOssClockClass *klass)
+{
+  GObjectClass *gobject_class;
+  GstObjectClass *gstobject_class;
+  GstClockClass *gstclock_class;
+
+  gobject_class = (GObjectClass*) klass;
+  gstobject_class = (GstObjectClass*) klass;
+  gstclock_class = (GstClockClass*) klass;
+
+  parent_class = g_type_class_ref (GST_TYPE_SYSTEM_CLOCK);
+
+  gstclock_class->reset =      gst_oss_clock_reset;
+  gstclock_class->activate =   gst_oss_clock_activate;
+  gstclock_class->set_time =   gst_oss_clock_set_time;
+  gstclock_class->wait =       gst_oss_clock_wait;
+}
+
+static void
+gst_oss_clock_init (GstOssClock *clock)
+{
+  gst_object_set_name (GST_OBJECT (clock), "GstOssClock");
+  clock->is_updated = FALSE;
+}
+
+#define GST_CLOCK_ENTRY(entry)         ((GstClockEntry *)(entry))
+#define GST_CLOCK_ENTRY_TIME(entry)    (((GstClockEntry *)(entry))->time)
+#define GST_CLOCK_ENTRY_LOCK(entry)    (g_mutex_lock ((entry)->lock))
+#define GST_CLOCK_ENTRY_UNLOCK(entry)          (g_mutex_unlock ((entry)->lock))
+#define GST_CLOCK_ENTRY_SIGNAL(entry)          (g_cond_signal ((entry)->cond))
+#define GST_CLOCK_ENTRY_WAIT(entry)    (g_cond_wait (entry->cond, entry->lock))
+#define GST_CLOCK_ENTRY_TIMED_WAIT(entry, time)        (g_cond_timed_wait (entry->cond, entry->lock, (time)))
+
+static GstClockEntry*
+gst_clock_entry_new (GstClockTime time)
+{
+  GstClockEntry *entry;
+
+  g_mutex_lock (_gst_clock_entries_chunk_lock);
+  if (_gst_clock_entries_pool) {
+    entry = GST_CLOCK_ENTRY (_gst_clock_entries_pool->data);
+
+    _gst_clock_entries_pool = g_list_remove (_gst_clock_entries_pool, entry);
+    g_mutex_unlock (_gst_clock_entries_chunk_lock);
+  }
+  else {
+    entry = g_mem_chunk_alloc (_gst_clock_entries_chunk);
+    g_mutex_unlock (_gst_clock_entries_chunk_lock);
+
+    entry->lock = g_mutex_new ();
+    entry->cond = g_cond_new ();
+  }
+
+  entry->time = time;
+
+  return entry;
+}
+
+static void
+gst_clock_entry_free (GstClockEntry *entry)
+{
+  g_mutex_lock (_gst_clock_entries_chunk_lock);
+  _gst_clock_entries_pool = g_list_prepend (_gst_clock_entries_pool, entry);
+  g_mutex_unlock (_gst_clock_entries_chunk_lock);
+}
+
+GstOssClock*
+gst_oss_clock_new (gchar *name, GstElement *owner)
+{
+  GstOssClock *oss_clock = GST_OSS_CLOCK (g_object_new (GST_TYPE_OSS_CLOCK, NULL));
+
+  oss_clock->entries = NULL;
+  oss_clock->current_time = 0;
+  oss_clock->next_time = 0;
+
+  _gst_clock_entries_chunk = g_mem_chunk_new ("GstClockEntries",
+                     sizeof (GstClockEntry), sizeof (GstClockEntry) * 32,
+                     G_ALLOC_AND_FREE);
+  _gst_clock_entries_chunk_lock = g_mutex_new ();
+  _gst_clock_entries_pool = NULL;
+
+  return oss_clock;
+}
+
+void
+gst_oss_clock_set_update (GstOssClock *clock, gboolean update)
+{
+  GST_LOCK (clock);
+
+  if (!update) { 
+
+    GST_UNLOCK (clock);
+    GST_CLOCK_CLASS (parent_class)->set_time (GST_CLOCK (clock), clock->current_time);
+    GST_LOCK (clock);
+    clock->is_updated = FALSE;
+
+    /* FIXME, convert the entries to ones that wait for the system clock */
+    if (clock->entries) {
+      GList *entries = g_list_copy (clock->entries);
+      while (entries) {
+        GstClockEntry *entry = (GstClockEntry *)entries->data;
+       
+        GST_CLOCK_ENTRY_LOCK (entry);
+        GST_CLOCK_ENTRY_SIGNAL (entry);
+       entry->status = GST_ENTRY_RESTART;
+        GST_CLOCK_ENTRY_UNLOCK (entry);
+
+        clock->entries = g_list_remove (clock->entries, entry);
+        entries = g_list_next (entries);
+      }
+    }
+  }
+  else {
+    clock->is_updated = TRUE;
+  }
+  
+  GST_UNLOCK (clock);
+}
+
+void
+gst_oss_clock_set_base (GstOssClock *clock, guint64 base)
+{
+  GstOssClock *oss_clock = GST_OSS_CLOCK (clock);
+
+  oss_clock->base_time = base;
+
+  GST_CLOCK_CLASS (parent_class)->set_time (clock, base);
+}
+
+static void
+gst_oss_clock_reset (GstClock *clock)
+{
+  GstOssClock *oss_clock = GST_OSS_CLOCK (clock);
+
+  oss_clock->next_time = 0;
+  oss_clock->current_time = 0;
+  oss_clock->base_time = 0;
+
+  GST_CLOCK_CLASS (parent_class)->reset (clock);
+}
+
+static void
+gst_oss_clock_activate (GstClock *clock, gboolean activate)
+{
+  GstOssClock *oss_clock = GST_OSS_CLOCK (clock);
+
+  if (!activate) {
+    oss_clock->base_time = oss_clock->current_time;
+  }
+
+  GST_CLOCK_CLASS (parent_class)->activate (clock, activate);
+}
+
+static void
+gst_oss_clock_set_time (GstClock *clock, GstClockTime time)
+{
+  GList *entries;
+  GstOssClock *oss_clock = GST_OSS_CLOCK (clock);
+
+  GST_LOCK (clock);
+
+  time += oss_clock->base_time;
+
+  //g_print ("set time %llu\n", time);
+
+  oss_clock->current_time = time;
+
+  if (oss_clock->next_time > time) {
+    GST_UNLOCK (clock);
+    return;
+  }
+
+  entries = g_list_copy (oss_clock->entries);
+
+  while (entries) {
+    GstClockEntry *entry = (GstClockEntry *)entries->data;
+
+    if (GST_CLOCK_ENTRY_TIME (entry) <= oss_clock->current_time) {
+
+      GST_CLOCK_ENTRY_LOCK (entry);
+      GST_CLOCK_ENTRY_SIGNAL (entry);
+      entry->status = GST_ENTRY_OK;
+      GST_CLOCK_ENTRY_UNLOCK (entry);
+
+      oss_clock->entries = g_list_remove (oss_clock->entries, entry);
+    }
+    else {
+      break;
+    }
+    entries = g_list_next (entries);
+  }
+
+  if (oss_clock->entries) {
+    oss_clock->next_time = GST_CLOCK_ENTRY_TIME (oss_clock->entries->data);
+  }
+  else {
+    oss_clock->next_time = 0;
+  }
+
+  GST_UNLOCK (oss_clock);
+}
+
+static gint
+clock_compare_func (gconstpointer a,
+                   gconstpointer b)
+{
+  GstClockEntry *entry1 = (GstClockEntry *)a;
+  GstClockEntry *entry2 = (GstClockEntry *)b;
+
+  return (entry1->time - entry2->time);
+}
+
+static GstClockReturn
+gst_oss_clock_wait (GstClock *clock, GstClockTime time)
+{
+  GstClockReturn ret;
+  GstOssClock *oss_clock = GST_OSS_CLOCK (clock);
+
+  GST_LOCK (clock);
+restart:
+  if (!oss_clock->is_updated) {
+    GST_UNLOCK (clock);
+    ret = GST_CLOCK_CLASS (parent_class)->wait (clock, time);
+  }
+  else if (time > oss_clock->current_time) {
+    GstClockEntry *entry = gst_clock_entry_new (time);
+
+    oss_clock->entries = g_list_insert_sorted (oss_clock->entries, entry, clock_compare_func);
+
+    oss_clock->next_time = GST_CLOCK_ENTRY_TIME (oss_clock->entries->data);
+
+    GST_CLOCK_ENTRY_LOCK (entry);
+    GST_UNLOCK (clock);
+    GST_CLOCK_ENTRY_WAIT (entry);
+    if (entry->status == GST_ENTRY_RESTART) 
+      goto restart;
+    GST_CLOCK_ENTRY_UNLOCK (entry);
+
+    gst_clock_entry_free (entry);
+
+    ret = GST_CLOCK_TIMEOUT;
+  }
+  else {
+    GST_UNLOCK (clock);
+
+    ret = GST_CLOCK_EARLY;
+  }
+
+  return ret;
+}
diff --git a/sys/oss/gstossclock.h b/sys/oss/gstossclock.h
new file mode 100644 (file)
index 0000000..30659fe
--- /dev/null
@@ -0,0 +1,77 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wtay@chello.be>
+ *
+ * gstclock.h: Header for clock subsystem
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_OSS_CLOCK_H__
+#define __GST_OSS_CLOCK_H__
+
+#include <gst/gstsystemclock.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_OSS_CLOCK \
+  (gst_oss_clock_get_type())
+#define GST_OSS_CLOCK(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS_CLOCK,GstOssClock))
+#define GST_OSS_CLOCK_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS_CLOCK,GstOssClockClass))
+#define GST_IS_OSS_CLOCK(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS_CLOCK))
+#define GST_IS_OSS_CLOCK_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS_CLOCK))
+
+typedef struct _GstOssClock GstOssClock;
+typedef struct _GstOssClockClass GstOssClockClass;
+
+struct _GstOssClock {
+  GstSystemClock clock;
+    
+  GList *entries;
+  GstClockTime current_time;
+  GstClockTime next_time;
+  GstClockTime base_time;
+  gboolean is_updated;
+  GstClockTime start_time;
+  GstClockTime origin;
+
+  GstElement *owner;
+};
+
+struct _GstOssClockClass {
+  GstSystemClockClass parent_class;
+};
+
+GType                   gst_oss_clock_get_type                 (void);
+GstOssClock*           gst_oss_clock_new               (gchar *name, GstElement *owner);
+
+void                   gst_oss_clock_set_update        (GstOssClock *clock, gboolean update);
+void                   gst_oss_clock_set_base          (GstOssClock *clock, guint64 base);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_OSS_CLOCK_H__ */