- Added first attempt at general caching mechanism (GstTimeCache renamed to GstCache)
authorWim Taymans <wim.taymans@gmail.com>
Wed, 27 Nov 2002 20:47:39 +0000 (20:47 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 27 Nov 2002 20:47:39 +0000 (20:47 +0000)
Original commit message from CVS:
- Added first attempt at general caching mechanism (GstTimeCache renamed
to GstCache)
- Some more clocking checks and updates (waiting on GST_CLOCK_TIME_NONE
returns immediatly instead of blocking forever)
- Moved clock get/set functions to element class instead of instance.
- Added cache methods on elements.
- Renamed GST_PROPS_BOOL_TYPE to GST_PROPS_BOOLEAN_TYPE to make it more
consistent with gst_props_get/set_boolean and GST_PROPS_BOOLEAN.
- Give short stats about plugins in gst-inspect.

16 files changed:
common
gst/Makefile.am
gst/elements/gstfakesink.c
gst/gst.h
gst/gstcache.c [new file with mode: 0644]
gst/gstcache.h [new file with mode: 0644]
gst/gstclock.c
gst/gstelement.c
gst/gstelement.h
gst/gstprops.c
gst/gstprops.h
gst/gstscheduler.c
gst/gstutils.c
gst/registries/gstxmlregistry.c
plugins/elements/gstfakesink.c
tools/gst-inspect.c

diff --git a/common b/common
index 1ca7d9a..f2d9b99 160000 (submodule)
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit 1ca7d9a20180cab830f4383cde5ba932338e50b1
+Subproject commit f2d9b99515c73da09bfe307d273d320f79a226da
index a073d32..9ba5942 100644 (file)
@@ -56,6 +56,7 @@ libgstreamer_la_SOURCES =             \
        gstbin.c                \
        gstbuffer.c             \
        gstbufferpool-default.c \
+       gstcache.c              \
        gstcaps.c               \
        gstclock.c              \
        gstcpu.c                \
@@ -83,7 +84,6 @@ libgstreamer_la_SOURCES =             \
        $(GST_TYPEFIND_SRC)     \
        gstutils.c              \
        gstregistry.c           \
-       gsttimecache.c          \
        $(GST_PARSE_SRC)        \
        $(GSTARCH_SRCS)         \
        $(GST_LOADSAVE_SRC)
@@ -103,6 +103,7 @@ gst_headers =                       \
        gstbin.h                \
        gstbuffer.h             \
        gstbufferpool-default.h \
+       gstcache.h              \
        gstcaps.h               \
        gstclock.h              \
        gstcpu.h                \
@@ -129,7 +130,6 @@ gst_headers =                       \
        gsttypefind.h           \
        gstutils.h              \
        gstregistry.h           \
-       gsttimecache.h          \
        gstparse.h              \
        gstxml.h
 
index 36bc664..2185f28 100644 (file)
@@ -134,6 +134,7 @@ gst_fakesink_class_init (GstFakeSinkClass *klass)
   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesink_get_property);
 
   gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_fakesink_request_new_pad);
+  gstelement_class->set_clock       = GST_DEBUG_FUNCPTR (gst_fakesink_set_clock);
 }
 
 static void 
@@ -150,8 +151,6 @@ gst_fakesink_init (GstFakeSink *fakesink)
   fakesink->sync = FALSE;
   fakesink->last_message = NULL;
 
-  GST_ELEMENT (fakesink)->setclockfunc    = gst_fakesink_set_clock;
-
   GST_FLAG_SET (fakesink, GST_ELEMENT_EVENT_AWARE);
 }
 
index 01c10dd..ca13b20 100644 (file)
--- a/gst/gst.h
+++ b/gst/gst.h
@@ -35,6 +35,7 @@
 #include <gst/gstpad.h>
 #include <gst/gstbuffer.h>
 #include <gst/gstbufferpool-default.h>
+#include <gst/gstcache.h>
 #include <gst/gstcpu.h>
 #include <gst/gstelement.h>
 #include <gst/gstbin.h>
@@ -49,7 +50,6 @@
 #include <gst/gsttrace.h>
 #include <gst/gstxml.h>
 #include <gst/gstscheduler.h>
-#include <gst/gsttimecache.h>
 #include <gst/gstevent.h>
 #include <gst/gstclock.h>
 #include <gst/gstsystemclock.h>
diff --git a/gst/gstcache.c b/gst/gstcache.c
new file mode 100644 (file)
index 0000000..ffa8309
--- /dev/null
@@ -0,0 +1,407 @@
+/* GStreamer
+ * Copyright (C) 2001 RidgeRun (http://www.ridgerun.com/)
+ * Written by Erik Walthinsen <omega@ridgerun.com>
+ *
+ * gstcache.c: Cache for mappings and other data
+ *
+ * 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 "gstlog.h"
+#include "gst_private.h"
+
+#include "gstcache.h"
+
+/* Cache signals and args */
+enum {
+  ENTRY_ADDED,
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  /* FILL ME */
+};
+
+static void            gst_cache_class_init    (GstCacheClass *klass);
+static void            gst_cache_init          (GstCache *tc);
+
+#define CLASS(cache)  GST_CACHE_CLASS (G_OBJECT_GET_CLASS (cache))
+
+static GstObject *parent_class = NULL;
+static guint gst_cache_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_cache_get_type(void) {
+  static GType tc_type = 0;
+
+  if (!tc_type) {
+    static const GTypeInfo tc_info = {
+      sizeof(GstCacheClass),
+      NULL,
+      NULL,
+      (GClassInitFunc)gst_cache_class_init,
+      NULL,
+      NULL,
+      sizeof(GstCache),
+      1,
+      (GInstanceInitFunc)gst_cache_init,
+      NULL
+    };
+    tc_type = g_type_register_static(GST_TYPE_OBJECT, "GstCache", &tc_info, 0);
+  }
+  return tc_type;
+}
+
+static void
+gst_cache_class_init (GstCacheClass *klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstelement_class = (GstElementClass*)klass;
+
+  parent_class = g_type_class_ref(GST_TYPE_OBJECT);
+
+  gst_cache_signals[ENTRY_ADDED] =
+    g_signal_new ("entry_added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GstCacheClass, entry_added), NULL, NULL,
+                  gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
+                  G_TYPE_POINTER);
+}
+
+static GstCacheGroup *
+gst_cache_group_new(guint groupnum)
+{
+  GstCacheGroup *tcgroup = g_new(GstCacheGroup,1);
+
+  tcgroup->groupnum = groupnum;
+  tcgroup->entries = NULL;
+  tcgroup->certainty = GST_CACHE_UNKNOWN;
+  tcgroup->peergroup = -1;
+
+  GST_DEBUG(0, "created new cache group %d",groupnum);
+
+  return tcgroup;
+}
+
+static void
+gst_cache_init (GstCache *tc)
+{
+  tc->curgroup = gst_cache_group_new(0);
+  tc->maxgroup = 0;
+  tc->groups = g_list_prepend(NULL, tc->curgroup);
+
+  tc->writers = g_hash_table_new (NULL, NULL);
+  tc->last_id = 0;
+  
+  GST_DEBUG(0, "created new cache");
+}
+
+/**
+ * gst_cache_new:
+ *
+ * Create a new tilecache object
+ *
+ * Returns: a new cache object
+ */
+GstCache *
+gst_cache_new()
+{
+  GstCache *tc;
+
+  tc = g_object_new (gst_cache_get_type (), NULL);
+
+  return tc;
+}
+
+/**
+ * gst_cache_get_group:
+ * @tc: the cache to get the current group from
+ *
+ * Get the id of the current group.
+ *
+ * Returns: the id of the current group.
+ */
+gint
+gst_cache_get_group(GstCache *tc)
+{
+  return tc->curgroup->groupnum;
+}
+
+/**
+ * gst_cache_new_group:
+ * @tc: the cache to create the new group in
+ *
+ * Create a new group for the given cache. It will be
+ * set as the current group.
+ *
+ * Returns: the id of the newly created group.
+ */
+gint
+gst_cache_new_group(GstCache *tc)
+{
+  tc->curgroup = gst_cache_group_new(++tc->maxgroup);
+  tc->groups = g_list_append(tc->groups,tc->curgroup);
+  GST_DEBUG(0, "created new group %d in cache",tc->maxgroup);
+  return tc->maxgroup;
+}
+
+/**
+ * gst_cache_set_group:
+ * @tc: the cache to set the new group in
+ * @groupnum: the groupnumber to set
+ *
+ * Set the current groupnumber to the given argument.
+ *
+ * Returns: TRUE if the operation succeeded, FALSE if the group
+ * did not exist.
+ */
+gboolean
+gst_cache_set_group(GstCache *tc, gint groupnum)
+{
+  GList *list;
+  GstCacheGroup *tcgroup;
+
+  /* first check for null change */
+  if (groupnum == tc->curgroup->groupnum)
+    return TRUE;
+
+  /* else search for the proper group */
+  list = tc->groups;
+  while (list) {
+    tcgroup = (GstCacheGroup *)(list->data);
+    list = g_list_next(list);
+    if (tcgroup->groupnum == groupnum) {
+      tc->curgroup = tcgroup;
+      GST_DEBUG(0, "switched to cache group %d", tcgroup->groupnum);
+      return TRUE;
+    }
+  }
+
+  /* couldn't find the group in question */
+  GST_DEBUG(0, "couldn't find cache group %d",groupnum);
+  return FALSE;
+}
+
+/**
+ * gst_cache_set_certainty:
+ * @tc: the cache to set the certainty on
+ * @certainty: the certainty to set
+ *
+ * Set the certainty of the given cache.
+ */
+void
+gst_cache_set_certainty(GstCache *tc, GstCacheCertainty certainty)
+{
+  tc->curgroup->certainty = certainty;
+}
+
+/**
+ * gst_cache_get_certainty:
+ * @tc: the cache to get the certainty of
+ *
+ * Get the certainty of the given cache.
+ *
+ * Returns: the certainty of the cache.
+ */
+GstCacheCertainty
+gst_cache_get_certainty(GstCache *tc)
+{
+  return tc->curgroup->certainty;
+}
+
+
+/**
+ * gst_cache_add_format:
+ * @tc: the cache to add the entry to
+ * @id: the id of the cache writer
+ * @format: the format to add to the cache
+ *
+ * Adds a format entry into the cache. This function is
+ * used to map dynamic GstFormat ids to their original
+ * format key.
+ *
+ * Returns: a pointer to the newly added entry in the cache.
+ */
+GstCacheEntry*
+gst_cache_add_format (GstCache *tc, gint id, GstFormat format)
+{
+  GstCacheEntry *entry;
+  const GstFormatDefinition* def;
+
+  g_return_val_if_fail (GST_IS_CACHE (tc), NULL);
+  g_return_val_if_fail (format != 0, NULL);
+  
+  entry = g_new0 (GstCacheEntry, 1);
+  entry->type = GST_CACHE_ENTRY_FORMAT;
+  entry->id = id;
+  entry->data.format.format = format;
+  def = gst_format_get_details (format);
+  entry->data.format.key = def->nick;
+  
+  g_signal_emit (G_OBJECT (tc), gst_cache_signals[ENTRY_ADDED], 0, entry);
+
+  return entry;
+}
+
+/**
+ * gst_cache_add_id:
+ * @tc: the cache to add the entry to
+ * @id: the id of the cache writer
+ * @description: the description of the cache writer
+ *
+ * Returns: a pointer to the newly added entry in the cache.
+ */
+GstCacheEntry*
+gst_cache_add_id (GstCache *tc, gint id, gchar *description)
+{
+  GstCacheEntry *entry;
+
+  g_return_val_if_fail (GST_IS_CACHE (tc), NULL);
+  g_return_val_if_fail (description != NULL, NULL);
+  
+  entry = g_new0 (GstCacheEntry, 1);
+  entry->type = GST_CACHE_ENTRY_ID;
+  entry->id = id;
+  entry->data.id.description = description;
+  
+  g_signal_emit (G_OBJECT (tc), gst_cache_signals[ENTRY_ADDED], 0, entry);
+
+  return entry;
+}
+
+/**
+ * gst_cache_get_writer_id:
+ * @tc: the cache to get a unique write id for
+ * @writer: the GstObject to allocate an id for
+ * @id: a pointer to a gint to hold the id
+ *
+ * Before entries can be added to the cache, a writer
+ * should obtain a unique id. The methods to add new entries
+ * to the cache require this id as an argument. 
+ *
+ * The application or a GstCache subclass can implement
+ * custom functions to map the writer object to an id.
+ *
+ * Returns: TRUE if the writer would be mapped to an id.
+ */
+gboolean 
+gst_cache_get_writer_id (GstCache *tc, GstObject *writer, gint *id)
+{
+  gchar *writer_string = NULL;
+  gboolean success = FALSE;
+  GstCacheEntry *entry;
+
+  g_return_val_if_fail (GST_IS_CACHE (tc), FALSE);
+  g_return_val_if_fail (GST_IS_OBJECT (writer), FALSE);
+  g_return_val_if_fail (id, FALSE);
+
+  *id = -1;
+
+  entry = g_hash_table_lookup (tc->writers, writer);
+  if (entry == NULL) { 
+    *id = tc->last_id;
+
+    writer_string = gst_object_get_path_string (writer);
+    
+    gst_cache_add_id (tc, *id, writer_string);
+    tc->last_id++;
+    g_hash_table_insert (tc->writers, writer, entry);
+  }
+
+  if (CLASS (tc)->resolve_writer) {
+    success = CLASS (tc)->resolve_writer (tc, writer, id, &writer_string);
+  }
+
+  if (tc->resolver) {
+    success = tc->resolver (tc, writer, id, &writer_string, tc->user_data);
+  }
+
+  return success;
+}
+
+/**
+ * gst_cache_add_association:
+ * @tc: the cache to add the entry to
+ * @id: the id of the cache writer
+ * @format: the format of the value
+ * @value: the value 
+ * @...: other format/value pairs or 0 to end the list
+ *
+ * Associate given format/value pairs with eachother.
+ *
+ * Returns: a pointer to the newly added entry in the cache.
+ */
+GstCacheEntry*
+gst_cache_add_association (GstCache *tc, gint id, GstAssocFlags flags, 
+                               GstFormat format, gint64 value, ...)
+{
+  va_list args;
+  GstCacheAssociation *assoc;
+  GstCacheEntry *entry;
+  gulong size;
+  gint nassocs = 0;
+  GstFormat cur_format;
+
+  g_return_val_if_fail (GST_IS_CACHE (tc), NULL);
+  g_return_val_if_fail (format != 0, NULL);
+  
+  va_start (args, value);
+
+  cur_format = format;
+
+  while (cur_format) {
+    nassocs++;
+    cur_format = va_arg (args, GstFormat);
+    if (cur_format)
+      va_arg (args, gint64);
+  }
+  va_end (args);
+
+  /* make room for two assoc */
+  size = sizeof (GstCacheEntry) + (sizeof (GstCacheAssociation) * nassocs);
+
+  entry = g_malloc (size);
+
+  entry->type = GST_CACHE_ENTRY_ASSOCIATION;
+  entry->id = id;
+  entry->data.assoc.flags = flags;
+  assoc = (GstCacheAssociation *) (((guint8 *) entry) + sizeof (GstCacheEntry));
+  entry->data.assoc.assocs = assoc;
+  entry->data.assoc.nassocs = nassocs;
+
+  va_start (args, value);
+  while (format) {
+    assoc->format = format;
+    assoc->value = value;
+
+    assoc++;
+
+    format = va_arg (args, GstFormat);
+    if (format)
+      value = va_arg (args, gint64);
+  }
+  va_end (args);
+
+  if (CLASS (tc)->add_entry)
+    CLASS (tc)->add_entry (tc, entry);
+
+  g_signal_emit (G_OBJECT (tc), gst_cache_signals[ENTRY_ADDED], 0, entry);
+
+  return entry;
+}
diff --git a/gst/gstcache.h b/gst/gstcache.h
new file mode 100644 (file)
index 0000000..50bd951
--- /dev/null
@@ -0,0 +1,182 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wim.taymans@chello.be>
+ *
+ * gstcache.h: Header for GstCache
+ *
+ * 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_CACHE_H__
+#define __GST_CACHE_H__
+
+#include <gst/gstobject.h>
+#include <gst/gstformat.h>
+#include <gst/gstcaps.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_CACHE         (gst_cache_get_type ())
+#define GST_CACHE(obj)         (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CACHE, GstCache))
+#define GST_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CACHE, GstCacheClass))
+#define GST_IS_CACHE(obj)      (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CACHE))
+#define GST_IS_CACHE_CLASS(obj)        (GST_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CACHE))
+
+typedef struct _GstCacheEntry GstCacheEntry;
+typedef struct _GstCacheGroup GstCacheGroup;
+typedef struct _GstCache GstCache;
+typedef struct _GstCacheClass GstCacheClass;
+
+typedef enum {
+  GST_CACHE_UNKNOWN,
+  GST_CACHE_CERTAIN,
+  GST_CACHE_FUZZY
+} GstCacheCertainty;
+
+typedef enum {
+  GST_CACHE_ENTRY_ID,
+  GST_CACHE_ENTRY_ASSOCIATION,
+  GST_CACHE_ENTRY_OBJECT,
+  GST_CACHE_ENTRY_FORMAT,
+} GstCacheEntryType;
+
+#define GST_CACHE_NASSOCS(entry)               ((entry)->data.assoc.nassocs)
+#define GST_CACHE_ASSOC_FLAGS(entry)   ((entry)->data.assoc.flags)
+#define GST_CACHE_ASSOC_FORMAT(entry,i)        ((entry)->data.assoc.assocs[(i)].format)
+#define GST_CACHE_ASSOC_VALUE(entry,i) ((entry)->data.assoc.assocs[(i)].value)
+
+typedef struct _GstCacheAssociation GstCacheAssociation;
+
+struct _GstCacheAssociation {
+  GstFormat    format;
+  gint64       value;
+};
+
+typedef enum {
+  GST_ACCOCIATION_FLAG_NONE    = 0,
+  GST_ACCOCIATION_FLAG_KEY_UNIT = (1 << 0),
+} GstAssocFlags;
+
+#define GST_CACHE_FORMAT_FORMAT(entry) ((entry)->data.format.format)
+#define GST_CACHE_FORMAT_KEY(entry)    ((entry)->data.format.key)
+
+#define GST_CACHE_ID_DESCRIPTION(entry)        ((entry)->data.id.description)
+
+struct _GstCacheEntry {
+  GstCacheEntryType     type;
+  gint                  id;
+
+  union {
+    struct {
+      gchar            *description;
+    } id;
+    struct {
+      gint              nassocs;
+      GstCacheAssociation 
+                       *assocs;
+      GstAssocFlags     flags;
+    } assoc;
+    struct {
+      gchar            *key;
+      GType             type;
+      gpointer          object;
+    } object;
+    struct {
+      GstFormat                 format;
+      gchar            *key;
+    } format;
+  } data;
+};
+
+struct _GstCacheGroup {
+  /* unique ID of group in cache */
+  gint groupnum;
+
+  /* list of entries */
+  GList *entries;
+
+  /* the certainty level of the group */
+  GstCacheCertainty certainty;
+
+  /* peer group that contains more certain entries */
+  gint peergroup;
+};
+
+typedef gboolean       (*GstCacheWriterResolver)       (GstCache *cache, 
+                                                        GstObject *writer, 
+                                                        gint *writer_id,
+                                                        gchar **writer_string,
+                                                        gpointer user_data);
+struct _GstCache {
+  GstObject             object;
+
+  GList                        *groups;
+  GstCacheGroup                *curgroup;
+  gint                  maxgroup;
+
+  GstCacheWriterResolver resolver;
+  gpointer              user_data;
+
+  GHashTable           *writers;
+  gint                  last_id;
+};
+
+struct _GstCacheClass {
+  GstObjectClass parent_class;
+
+  gboolean     (*resolve_writer)       (GstCache *cache, GstObject *writer, 
+                                        gint *writer_id, gchar **writer_string);
+
+  /* abstract methods */
+  void         (*add_entry)            (GstCache *cache, GstCacheEntry *entry);
+  void         (*remove_entry)         (GstCache *cache, GstCacheEntry *entry);
+  void         (*modify_entry)         (GstCache *cache, GstCacheEntry *oldentry, 
+                                        GstCacheEntry *new_entry);
+
+  GstCacheEntry* (*get_entry)          (GstCache *cache); 
+
+  /* signals */
+  void         (*entry_added)          (GstCache *cache, GstCacheEntry *entry);
+  void         (*entry_removed)        (GstCache *cache, GstCacheEntry *entry);
+  void         (*entry_modified)       (GstCache *cache, GstCacheEntry *oldentry, 
+                                        GstCacheEntry *new_entry);
+};
+
+GType                  gst_cache_get_type              (void);
+GstCache*              gst_cache_new                   (void);
+
+gint                   gst_cache_get_group             (GstCache *cache);
+gint                   gst_cache_new_group             (GstCache *cache);
+gboolean               gst_cache_set_group             (GstCache *cache, gint groupnum);
+
+void                   gst_cache_set_certainty         (GstCache *cache, 
+                                                        GstCacheCertainty certainty);
+GstCacheCertainty      gst_cache_get_certainty         (GstCache *cache);
+
+gboolean               gst_cache_get_writer_id         (GstCache *cache, GstObject *writer, gint *id);
+
+GstCacheEntry*         gst_cache_add_format            (GstCache *cache, gint id, GstFormat format); 
+GstCacheEntry*         gst_cache_add_association       (GstCache *cache, gint id, GstAssocFlags flags,
+                                                        GstFormat format, gint64 value, ...);
+GstCacheEntry*         gst_cache_add_object            (GstCache *cache, gint id, gchar *key,
+                                                        GType type, gpointer object);
+GstCacheEntry*         gst_cache_add_id                (GstCache *cache, gint id,
+                                                        gchar *description); 
+
+
+G_END_DECLS
+
+#endif /* __GST_CACHE_H__ */
index bbb8098..da315a1 100644 (file)
@@ -83,6 +83,8 @@ gst_clock_entry_new (GstClock *clock, GstClockTime time,
 GstClockID
 gst_clock_new_single_shot_id (GstClock *clock, GstClockTime time)
 {
+  g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
+
   return gst_clock_entry_new (clock, 
                              time, 
                              GST_CLOCK_TIME_NONE, 
@@ -105,6 +107,10 @@ GstClockID
 gst_clock_new_periodic_id (GstClock *clock, GstClockTime start_time,
                            GstClockTime interval)
 {
+  g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
+  g_return_val_if_fail (start_time != GST_CLOCK_TIME_NONE, NULL);
+  g_return_val_if_fail (interval != 0, NULL);
+
   return gst_clock_entry_new (clock, 
                              start_time, 
                              interval, 
@@ -149,8 +155,14 @@ gst_clock_id_wait (GstClockID id, GstClockTimeDiff *jitter)
   g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
 
   entry = (GstClockEntry *) id;
-  clock = GST_CLOCK_ENTRY_CLOCK (entry);
   requested = GST_CLOCK_ENTRY_TIME (entry);
+
+  if (requested == GST_CLOCK_TIME_NONE) {
+    res = GST_CLOCK_TIMEOUT;
+    goto done;
+  }
+  
+  clock = GST_CLOCK_ENTRY_CLOCK (entry);
   
   if (CLASS (clock)->wait) {
     GstClockTime now;
@@ -170,6 +182,7 @@ gst_clock_id_wait (GstClockID id, GstClockTimeDiff *jitter)
     }
   }
 
+done:
   if (entry->type == GST_CLOCK_ENTRY_SINGLE) {
     gst_clock_id_free (id);
   }
@@ -188,7 +201,7 @@ gst_clock_id_wait (GstClockID id, GstClockTimeDiff *jitter)
  * when the clock has reached the given time. A ClockID is returned
  * that can be used to cancel the request.
  *
- * Returns: the clock id or NULL when async notification is not supported.
+ * Returns: the result of the non blocking wait.
  */
 GstClockReturn
 gst_clock_id_wait_async (GstClockID id,
@@ -199,10 +212,16 @@ gst_clock_id_wait_async (GstClockID id,
   GstClockReturn res = GST_CLOCK_UNSUPPORTED;
   
   g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
+  g_return_val_if_fail (func != NULL, GST_CLOCK_ERROR);
 
   entry = (GstClockEntry *) id;
   clock = entry->clock;
 
+  if (GST_CLOCK_ENTRY_TIME (entry) == GST_CLOCK_TIME_NONE) {
+    (func) (clock, GST_CLOCK_TIME_NONE, id, user_data);
+    return GST_CLOCK_TIMEOUT;
+  }
+
   if (CLASS (clock)->wait_async) {
     res = CLASS (clock)->wait_async (clock, entry, func, user_data);
   }
@@ -243,6 +262,8 @@ gst_clock_id_unschedule (GstClockID id)
 void
 gst_clock_id_free (GstClockID id)
 {
+  g_return_if_fail (id != NULL);
+
   gst_mem_chunk_free (_gst_clock_entries_chunk, id);
 }
 
@@ -389,6 +410,7 @@ guint64
 gst_clock_set_resolution (GstClock *clock, guint64 resolution)
 {
   g_return_val_if_fail (GST_IS_CLOCK (clock), 0LL);
+  g_return_val_if_fail (resolution != 0, 0LL);
 
   if (CLASS (clock)->change_resolution)
     clock->resolution = CLASS (clock)->change_resolution (clock, clock->resolution, resolution);
@@ -510,6 +532,9 @@ gst_clock_handle_discont (GstClock *clock, guint64 time)
   
   GST_DEBUG (GST_CAT_CLOCK, "clock discont %llu %llu %d", time, clock->start_time, clock->accept_discont);
 
+  if (time == GST_CLOCK_TIME_NONE)
+    return TRUE;
+
   GST_LOCK (clock);
   if (clock->accept_discont) {
     if (CLASS (clock)->get_internal_time) {
@@ -585,6 +610,8 @@ gst_clock_get_next_id (GstClock *clock)
 {
   GstClockEntry *entry = NULL;
 
+  g_return_val_if_fail (GST_IS_CLOCK (clock), NULL);
+
   GST_LOCK (clock);
   if (clock->entries)
     entry = GST_CLOCK_ENTRY (clock->entries->data);
index 73ed744..0130a11 100644 (file)
@@ -742,6 +742,38 @@ gst_element_get_parent (GstElement *element)
 }
 
 /**
+ * gst_element_requires_clock:
+ * @element: a #GstElement to query
+ *
+ * Query if the element requiresd a clock
+ *
+ * Returns: TRUE if the element requires a clock
+ */
+gboolean
+gst_element_requires_clock (GstElement *element)
+{
+  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
+
+  return (CLASS (element)->set_clock != NULL);
+}
+
+/**
+ * gst_element_provides_clock:
+ * @element: a #GstElement to query
+ *
+ * Query if the element provides a clock
+ *
+ * Returns: TRUE if the element provides a clock
+ */
+gboolean
+gst_element_provides_clock (GstElement *element)
+{
+  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
+
+  return (CLASS (element)->get_clock != NULL);
+}
+
+/**
  * gst_element_set_clock:
  * @element: a #GstElement to set the clock for.
  * @clock: the #GstClock to set for the element.
@@ -751,11 +783,10 @@ gst_element_get_parent (GstElement *element)
 void
 gst_element_set_clock (GstElement *element, GstClock *clock)
 {
-  g_return_if_fail (element != NULL);
   g_return_if_fail (GST_IS_ELEMENT (element));
 
-  if (element->setclockfunc)
-    element->setclockfunc (element, clock);
+  if (CLASS (element)->set_clock)
+    CLASS (element)->set_clock (element, clock);
 
   element->clock = clock;
 }
@@ -774,8 +805,8 @@ gst_element_get_clock (GstElement *element)
   g_return_val_if_fail (element != NULL, NULL);
   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
   
-  if (element->getclockfunc)
-    return element->getclockfunc (element);
+  if (CLASS (element)->get_clock)
+    return CLASS (element)->get_clock (element);
 
   return NULL;
 }
@@ -796,7 +827,6 @@ gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time,
 {
   GstClockReturn res;
 
-  g_return_val_if_fail (element != NULL, GST_CLOCK_ERROR);
   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_ERROR);
 
   if (GST_ELEMENT_SCHED (element)) {
@@ -808,6 +838,35 @@ gst_element_clock_wait (GstElement *element, GstClock *clock, GstClockTime time,
   return res;
 }
 
+gboolean
+gst_element_is_cachable (GstElement *element)
+{
+  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
+
+  return (CLASS (element)->set_cache != NULL);
+}
+
+void
+gst_element_set_cache (GstElement *element, GstCache *cache)
+{
+  g_return_if_fail (GST_IS_ELEMENT (element));
+  g_return_if_fail (GST_IS_CACHE (cache));
+
+  if (CLASS (element)->set_cache)
+    CLASS (element)->set_cache (element, cache);
+}
+
+GstCache*
+gst_element_get_cache (GstElement *element)
+{
+  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
+
+  if (CLASS (element)->get_cache)
+    return CLASS (element)->get_cache (element);
+
+  return NULL;
+}
+
 
 /**
  * gst_element_release_locks:
index a826640..c0f17f0 100644 (file)
@@ -30,6 +30,7 @@
 #include <gst/gstpad.h>
 #include <gst/gstclock.h>
 #include <gst/gstpluginfeature.h>
+#include <gst/gstcache.h>
 
 G_BEGIN_DECLS
 
@@ -109,8 +110,6 @@ typedef struct _GstElementFactory GstElementFactory;
 typedef struct _GstElementFactoryClass GstElementFactoryClass;
 
 typedef void           (*GstElementLoopFunction)       (GstElement *element);
-typedef void           (*GstElementSetClockFunction)   (GstElement *element, GstClock *clock);
-typedef GstClock*      (*GstElementGetClockFunction)   (GstElement *element);
 typedef void           (*GstElementPreRunFunction)     (GstElement *element);
 typedef void           (*GstElementPostRunFunction)    (GstElement *element);
 
@@ -125,8 +124,6 @@ struct _GstElement {
 
   GstScheduler                 *sched;
   gpointer             sched_private;
-  GstElementSetClockFunction setclockfunc;
-  GstElementGetClockFunction getclockfunc;
   GstClock             *clock;
   GstClockTime          base_time;
 
@@ -176,6 +173,12 @@ struct _GstElementClass {
   /* request a new pad */
   GstPad*              (*request_new_pad)      (GstElement *element, GstPadTemplate *templ, const gchar* name);
   void                 (*release_pad)          (GstElement *element, GstPad *pad);
+  /* set/get clocks */
+  GstClock*            (*get_clock)            (GstElement *element);
+  void                 (*set_clock)            (GstElement *element, GstClock *clock);
+  /* cache */
+  GstCache*            (*get_cache)            (GstElement *element);
+  void                 (*set_cache)            (GstElement *element, GstCache *cache);
 };
 
 void                   gst_element_class_add_pad_template      (GstElementClass *klass, GstPadTemplate *templ);
@@ -214,10 +217,18 @@ const gchar*            gst_element_get_name            (GstElement *element);
 void                    gst_element_set_parent          (GstElement *element, GstObject *parent);
 GstObject*              gst_element_get_parent          (GstElement *element);
 
+/* clocking */
+gboolean               gst_element_requires_clock      (GstElement *element);
+gboolean               gst_element_provides_clock      (GstElement *element);
 GstClock*              gst_element_get_clock           (GstElement *element);
 void                   gst_element_set_clock           (GstElement *element, GstClock *clock);
 GstClockReturn         gst_element_clock_wait          (GstElement *element, GstClock *clock, 
                                                         GstClockTime time, GstClockTimeDiff *jitter);
+/* caches */
+gboolean               gst_element_is_cachable         (GstElement *element);
+void                   gst_element_set_cache           (GstElement *element, GstCache *cache);
+GstCache*              gst_element_get_cache           (GstElement *element);
+
 
 gboolean               gst_element_release_locks       (GstElement *element);
 
index 09bbf46..d187795 100644 (file)
@@ -92,6 +92,10 @@ transform_func (const GValue *src_value,
         case GST_PROPS_FOURCC_TYPE:
          g_string_append_printf (result, "%s=(fourcc) '%4.4s'", name, (gchar *)&entry->data.fourcc_data);
          break;
+        case GST_PROPS_BOOLEAN_TYPE:
+         g_string_append_printf (result, "%s=(boolean) %s", name, 
+                         (entry->data.bool_data ? "TRUE" : "FALSE"));
+         break;
         default:
          break;
       }
@@ -147,7 +151,7 @@ gst_props_debug_entry (GstPropsEntry *entry)
        (entry->data.fourcc_data>>16)&0xff,
        (entry->data.fourcc_data>>24)&0xff);
       break;
-    case GST_PROPS_BOOL_TYPE:
+    case GST_PROPS_BOOLEAN_TYPE:
       GST_DEBUG (GST_CAT_PROPERTIES, "%s: bool %d", name, entry->data.bool_data);
       break;
     case GST_PROPS_STRING_TYPE:
@@ -223,7 +227,7 @@ G_STMT_START {                                                                      \
     case GST_PROPS_FOURCC_TYPE:                                                        \
       entry->data.fourcc_data = va_arg (var_args, gulong);                     \
       break;                                                                   \
-    case GST_PROPS_BOOL_TYPE:                                                  \
+    case GST_PROPS_BOOLEAN_TYPE:                                               \
       entry->data.bool_data = va_arg (var_args, gboolean);                     \
       break;                                                                   \
     case GST_PROPS_STRING_TYPE:                                                        \
@@ -269,7 +273,7 @@ G_STMT_START {                                                                      \
       case GST_PROPS_FOURCC_TYPE:                                              \
         *(va_arg (var_args, guint32*)) = entry->data.fourcc_data;              \
         break;                                                                 \
-      case GST_PROPS_BOOL_TYPE:                                                        \
+      case GST_PROPS_BOOLEAN_TYPE:                                             \
         *(va_arg (var_args, gboolean*)) = entry->data.bool_data;               \
         break;                                                                 \
       case GST_PROPS_STRING_TYPE:                                              \
@@ -606,7 +610,7 @@ gst_props_newv (const gchar *firstname, va_list var_args)
        entry_type = GST_PROPS_LIST_T_FLOATS;
        break;
       case GST_PROPS_FOURCC_TYPE:
-      case GST_PROPS_BOOL_TYPE:
+      case GST_PROPS_BOOLEAN_TYPE:
       case GST_PROPS_STRING_TYPE:
        entry_type = GST_PROPS_LIST_T_MISC;
        break;
@@ -1179,7 +1183,7 @@ gst_props_entry_get_fourcc_int (const GstPropsEntry *entry, guint32 *val)
 gboolean
 gst_props_entry_get_boolean (const GstPropsEntry *entry, gboolean *val)
 {
-  return gst_props_entry_get_safe (entry, GST_PROPS_BOOL_TYPE, val);
+  return gst_props_entry_get_safe (entry, GST_PROPS_BOOLEAN_TYPE, val);
 }
 
 /**
@@ -1391,10 +1395,10 @@ gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry
          break;
       }
       break;
-    case GST_PROPS_BOOL_TYPE:
+    case GST_PROPS_BOOLEAN_TYPE:
       switch (entry2->propstype) {
        /* t   <--->   t */
-        case GST_PROPS_BOOL_TYPE:
+        case GST_PROPS_BOOLEAN_TYPE:
           return (entry2->data.bool_data == entry1->data.bool_data);
         default:
          break;
@@ -1669,10 +1673,10 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
          break;
       }
       break;
-    case GST_PROPS_BOOL_TYPE:
+    case GST_PROPS_BOOLEAN_TYPE:
       switch (entry2->propstype) {
        /* t   <--->   t */
-        case GST_PROPS_BOOL_TYPE:
+        case GST_PROPS_BOOLEAN_TYPE:
           if (entry1->data.bool_data == entry2->data.bool_data)
            result = gst_props_entry_copy (entry1);
         default:
@@ -1928,7 +1932,7 @@ gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
       xmlNewProp (subtree, "hexvalue", str);
       g_free(str);
       break;
-    case GST_PROPS_BOOL_TYPE: 
+    case GST_PROPS_BOOLEAN_TYPE: 
       subtree = xmlNewChild (parent, NULL, "boolean", NULL);
       xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
       xmlNewProp (subtree, "value", (entry->data.bool_data ?  "true" : "false"));
@@ -2035,7 +2039,7 @@ gst_props_load_thyself_func (xmlNodePtr field)
     g_free (prop);
   }
   else if (!strcmp(field->name, "boolean")) {
-    entry->propstype = GST_PROPS_BOOL_TYPE;
+    entry->propstype = GST_PROPS_BOOLEAN_TYPE;
     prop = xmlGetProp(field, "name");
     entry->propid = g_quark_from_string (prop);
     g_free (prop);
index 7b46bbd..df8c17a 100644 (file)
@@ -43,7 +43,7 @@ typedef enum {
    GST_PROPS_INT_TYPE,
    GST_PROPS_FLOAT_TYPE,
    GST_PROPS_FOURCC_TYPE,
-   GST_PROPS_BOOL_TYPE,
+   GST_PROPS_BOOLEAN_TYPE,
    GST_PROPS_STRING_TYPE,
 
    GST_PROPS_VAR_TYPE,   /* after this marker start the variable properties */
@@ -66,7 +66,7 @@ typedef enum {
 #define GST_PROPS_FLOAT(a)             GST_PROPS_FLOAT_TYPE,((float)(a))
 #define GST_PROPS_FLOAT_RANGE(a,b)     GST_PROPS_FLOAT_RANGE_TYPE,((float)(a)),((float)(b))
 #define GST_PROPS_FOURCC(a)            GST_PROPS_FOURCC_TYPE,(a)
-#define GST_PROPS_BOOLEAN(a)           GST_PROPS_BOOL_TYPE,(a)
+#define GST_PROPS_BOOLEAN(a)           GST_PROPS_BOOLEAN_TYPE,(a)
 #define GST_PROPS_STRING(a)            GST_PROPS_STRING_TYPE,(a)
 
 #define GST_PROPS_INT_POSITIVE         GST_PROPS_INT_RANGE(0,G_MAXINT)
index e27c415..3f4dcce 100644 (file)
@@ -212,11 +212,11 @@ gst_scheduler_add_element (GstScheduler *sched, GstElement *element)
   /* if it's not inside this scheduler, it has to be NULL */
   g_assert (GST_ELEMENT_SCHED (element) == NULL);
 
-  if (element->getclockfunc) {
+  if (gst_element_provides_clock (element)) {
     sched->clock_providers = g_list_prepend (sched->clock_providers, element);
     GST_DEBUG (GST_CAT_CLOCK, "added clock provider %s", GST_ELEMENT_NAME (element));
   }
-  if (element->setclockfunc) {
+  if (gst_element_requires_clock (element)) {
     sched->clock_receivers = g_list_prepend (sched->clock_receivers, element);
     GST_DEBUG (GST_CAT_CLOCK, "added clock receiver %s", GST_ELEMENT_NAME (element));
   }
index d0691a3..3bb22d9 100644 (file)
@@ -506,7 +506,7 @@ gst_print_props (GString *buf, gint indent, GList *props, gboolean showname)
        g_string_append_printf (buf, "%f - %f (float)\n", min, max);
        break;
       }
-      case GST_PROPS_BOOL_TYPE:
+      case GST_PROPS_BOOLEAN_TYPE:
       {
        gboolean val;
        gst_props_entry_get_boolean (prop, &val);
index 8066adb..9ab0b47 100644 (file)
@@ -1233,7 +1233,7 @@ gst_xml_registry_save_props_func (GstPropsEntry *entry,
       CLASS (xmlregistry)->save_func (xmlregistry, "<fourcc name=\"%s\" hexvalue=\"%08x\"/>\n", name, fourcc);
       break;
     }
-    case GST_PROPS_BOOL_TYPE:
+    case GST_PROPS_BOOLEAN_TYPE:
     {
       gboolean value;
       gst_props_entry_get_boolean (entry, &value);
index 36bc664..2185f28 100644 (file)
@@ -134,6 +134,7 @@ gst_fakesink_class_init (GstFakeSinkClass *klass)
   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesink_get_property);
 
   gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_fakesink_request_new_pad);
+  gstelement_class->set_clock       = GST_DEBUG_FUNCPTR (gst_fakesink_set_clock);
 }
 
 static void 
@@ -150,8 +151,6 @@ gst_fakesink_init (GstFakeSink *fakesink)
   fakesink->sync = FALSE;
   fakesink->last_message = NULL;
 
-  GST_ELEMENT (fakesink)->setclockfunc    = gst_fakesink_set_clock;
-
   GST_FLAG_SET (fakesink, GST_ELEMENT_EVENT_AWARE);
 }
 
index 529544f..b66a98a 100644 (file)
@@ -43,7 +43,7 @@ print_prop (GstPropsEntry *prop, gboolean showname, const gchar *pfx)
       g_print("Float range: %f - %f\n", min, max);
       break;
     }
-    case GST_PROPS_BOOL_TYPE:
+    case GST_PROPS_BOOLEAN_TYPE:
     {
       gboolean val;
       gst_props_entry_get_boolean (prop, &val);
@@ -571,22 +571,31 @@ print_element_info (GstElementFactory *factory)
   have_flags = FALSE;
 
   g_print ("\nClocking Interaction:\n");
-  if (element->setclockfunc) {
+  if (gst_element_requires_clock (element)) {
     g_print ("  element requires a clock\n");
     have_flags = TRUE;
   }
-  if (element->getclockfunc) {
+  if (gst_element_provides_clock (element)) {
     GstClock *clock;
 
     clock = gst_element_get_clock (element);
     if (clock)
       g_print ("  element provides a clock: %s\n", GST_OBJECT_NAME(clock));
+    else
+      g_print ("  element is supposed to provide a clock but returned NULL\n");
     have_flags = TRUE;
   }
   if (!have_flags) {
     g_print ("  none\n");
   }
 
+  g_print ("\nCaching capabilities:\n");
+  if (gst_element_is_cachable (element)) {
+    g_print ("  element can do caching\n");
+  }
+  else {
+    g_print ("  none\n");
+  }
 
   g_print ("\nPads:\n");
   if (element->numpads) {
@@ -841,6 +850,12 @@ static void
 print_plugin_info (GstPlugin *plugin)
 {
   GList *features;
+  gint num_features = 0;
+  gint num_elements = 0;
+  gint num_autoplug = 0;
+  gint num_types = 0;
+  gint num_schedulers = 0;
+  gint num_other = 0;
   
   g_print ("Plugin Details:\n");
   g_print ("  Name:\t\t%s\n",    plugin->name);
@@ -861,12 +876,14 @@ print_plugin_info (GstPlugin *plugin)
       factory = GST_ELEMENT_FACTORY (feature);
       g_print ("  %s: %s\n", GST_OBJECT_NAME (factory),
              factory->details->longname);
+      num_elements++;
     }
     else if (GST_IS_AUTOPLUG_FACTORY (feature)) {
       GstAutoplugFactory *factory;
 
       factory = GST_AUTOPLUG_FACTORY (feature);
       g_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
+      num_autoplug++;
     }
     else if (GST_IS_TYPE_FACTORY (feature)) {
       GstTypeFactory *factory;
@@ -877,21 +894,35 @@ print_plugin_info (GstPlugin *plugin)
       if (factory->typefindfunc)
         g_print ("      Has typefind function: %s\n", 
                GST_DEBUG_FUNCPTR_NAME (factory->typefindfunc));
+      num_types++;
     }
     else if (GST_IS_SCHEDULER_FACTORY (feature)) {
       GstSchedulerFactory *factory;
 
       factory = GST_SCHEDULER_FACTORY (feature);
       g_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
+      num_schedulers++;
     }
     else {
       g_print ("  %s (%s)\n", gst_object_get_name (GST_OBJECT (feature)), 
                             g_type_name (G_OBJECT_TYPE (feature)));
+      num_other++;
     }
-
-
+    num_features++;
     features = g_list_next (features);
   }
+  g_print ("\n  %d features:\n", num_features);
+  if (num_elements > 0)
+    g_print ("  +-- %d elements\n", num_elements);
+  if (num_autoplug > 0)
+    g_print ("  +-- %d autopluggers\n", num_autoplug);
+  if (num_types > 0)
+    g_print ("  +-- %d types\n", num_types);
+  if (num_schedulers > 0)
+    g_print ("  +-- %d schedulers\n", num_schedulers);
+  if (num_other > 0)
+    g_print ("  +-- %d other objects\n", num_other);
+  
   g_print ("\n");
 }