summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2010-10-12 12:29:49 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2010-10-20 12:58:12 +0200
commit9c35e7cbde745afb0644ef0dd95840ddd2fd2c43 (patch)
tree1e09a0e754662ef1732e182aeb827f2d3f7c8a17
parentb0d7c61f180064b0e5e78d0ae33c6bb856548c51 (diff)
pad: prototype of pad push cacheperformance-push
Prototype of how we can cache the peer and caps for a pad link.
-rw-r--r--gst/gstpad.c84
1 files changed, 83 insertions, 1 deletions
diff --git a/gst/gstpad.c b/gst/gstpad.c
index bd36a190c..26c928d79 100644
--- a/gst/gstpad.c
+++ b/gst/gstpad.c
@@ -95,6 +95,14 @@ enum
/* FILL ME */
};
+typedef struct _GstPadPushCache GstPadPushCache;
+
+struct _GstPadPushCache
+{
+ GstPad *peer; /* reffed peer pad */
+ GstCaps *caps; /* caps for this link */
+};
+
#define GST_PAD_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_PAD, GstPadPrivate))
@@ -103,6 +111,9 @@ enum
struct _GstPadPrivate
{
GstPadChainListFunction chainlistfunc;
+
+ GstPadPushCache cache_slot;
+ GstPadPushCache *cache_ptr;
};
static void gst_pad_dispose (GObject * object);
@@ -2087,9 +2098,28 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
GST_OBJECT_LOCK (sinkpad);
if (result == GST_PAD_LINK_OK) {
+ GstPadPushCache *cache, *old;
+ gpointer *cache_ptr;
GST_OBJECT_UNLOCK (sinkpad);
GST_OBJECT_UNLOCK (srcpad);
+ cache_ptr = (gpointer *) & srcpad->abidata.ABI.priv->cache_ptr;
+
+ /* make cache structure */
+ cache = g_slice_new (GstPadPushCache);
+ cache->peer = gst_object_ref (sinkpad);
+ cache->caps = NULL;
+
+ do {
+ old = g_atomic_pointer_get (cache_ptr);
+ } while (!g_atomic_pointer_compare_and_exchange (cache_ptr, old, cache));
+
+ if (old) {
+ gst_object_unref (old->peer);
+ gst_caps_unref (old->caps);
+ g_slice_free (GstPadPushCache, old);
+ }
+
/* fire off a signal to each of the pads telling them
* that they've been linked */
g_signal_emit (srcpad, gst_pad_signals[PAD_LINKED], 0, sinkpad);
@@ -4487,6 +4517,33 @@ not_negotiated:
}
}
+static GstPadPushCache *
+pad_take_cache (GstPad * pad, gpointer * cache_ptr)
+{
+ GstPadPushCache *cache;
+
+ /* try to get the cached data */
+ do {
+ cache = g_atomic_pointer_get (cache_ptr);
+ /* now try to replace the pointer with NULL to mark that we are busy
+ * with it */
+ } while (!g_atomic_pointer_compare_and_exchange (cache_ptr, cache, NULL));
+
+ return cache;
+}
+
+static void
+pad_put_cache (GstPad * pad, GstPadPushCache * cache, gpointer * cache_ptr)
+{
+ /* put it back */
+ if (!g_atomic_pointer_compare_and_exchange (cache_ptr, NULL, cache)) {
+ /* something changed, clean up our cache */
+ gst_object_unref (cache->peer);
+ gst_caps_unref (cache->caps);
+ g_slice_free (GstPadPushCache, cache);
+ }
+}
+
/**
* gst_pad_push:
* @pad: a source #GstPad, returns #GST_FLOW_ERROR if not.
@@ -4516,11 +4573,36 @@ not_negotiated:
GstFlowReturn
gst_pad_push (GstPad * pad, GstBuffer * buffer)
{
+ GstPadPushCache *cache;
+ GstFlowReturn ret;
+ gpointer *cache_ptr;
+
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
- return gst_pad_push_data (pad, TRUE, buffer);
+ cache_ptr = (gpointer *) & pad->abidata.ABI.priv->cache_ptr;
+
+ cache = pad_take_cache (pad, cache_ptr);
+
+ if (G_LIKELY (cache)) {
+ GstPad *peer = cache->peer;
+
+ /* FIXME check cookies and caps */
+
+ GST_PAD_STREAM_LOCK (peer);
+
+ /* fast path */
+ ret = GST_PAD_CHAINFUNC (peer) (peer, buffer);
+
+ GST_PAD_STREAM_UNLOCK (peer);
+
+ pad_put_cache (pad, cache, cache_ptr);
+ } else {
+ /* slow path */
+ ret = gst_pad_push_data (pad, TRUE, buffer);
+ }
+ return ret;
}
/**