diff options
author | Wim Taymans <wim.taymans@collabora.co.uk> | 2010-10-12 12:29:49 +0200 |
---|---|---|
committer | Wim Taymans <wim.taymans@collabora.co.uk> | 2010-10-20 12:58:12 +0200 |
commit | 9c35e7cbde745afb0644ef0dd95840ddd2fd2c43 (patch) | |
tree | 1e09a0e754662ef1732e182aeb827f2d3f7c8a17 | |
parent | b0d7c61f180064b0e5e78d0ae33c6bb856548c51 (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.c | 84 |
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; } /** |