mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-07 15:02:40 +00:00
pad: prototype of pad push cache
Prototype of how we can cache the peer and caps for a pad link.
This commit is contained in:
parent
7106cabce3
commit
d59b7f81b7
1 changed files with 83 additions and 1 deletions
84
gst/gstpad.c
84
gst/gstpad.c
|
@ -95,6 +95,14 @@ enum
|
||||||
/* FILL ME */
|
/* 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) \
|
#define GST_PAD_GET_PRIVATE(obj) \
|
||||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_PAD, GstPadPrivate))
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_PAD, GstPadPrivate))
|
||||||
|
|
||||||
|
@ -103,6 +111,9 @@ enum
|
||||||
struct _GstPadPrivate
|
struct _GstPadPrivate
|
||||||
{
|
{
|
||||||
GstPadChainListFunction chainlistfunc;
|
GstPadChainListFunction chainlistfunc;
|
||||||
|
|
||||||
|
GstPadPushCache cache_slot;
|
||||||
|
GstPadPushCache *cache_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void gst_pad_dispose (GObject * object);
|
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);
|
GST_OBJECT_LOCK (sinkpad);
|
||||||
|
|
||||||
if (result == GST_PAD_LINK_OK) {
|
if (result == GST_PAD_LINK_OK) {
|
||||||
|
GstPadPushCache *cache, *old;
|
||||||
|
gpointer *cache_ptr;
|
||||||
GST_OBJECT_UNLOCK (sinkpad);
|
GST_OBJECT_UNLOCK (sinkpad);
|
||||||
GST_OBJECT_UNLOCK (srcpad);
|
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
|
/* fire off a signal to each of the pads telling them
|
||||||
* that they've been linked */
|
* that they've been linked */
|
||||||
g_signal_emit (srcpad, gst_pad_signals[PAD_LINKED], 0, sinkpad);
|
g_signal_emit (srcpad, gst_pad_signals[PAD_LINKED], 0, sinkpad);
|
||||||
|
@ -4490,6 +4520,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:
|
* gst_pad_push:
|
||||||
* @pad: a source #GstPad, returns #GST_FLOW_ERROR if not.
|
* @pad: a source #GstPad, returns #GST_FLOW_ERROR if not.
|
||||||
|
@ -4519,11 +4576,36 @@ not_negotiated:
|
||||||
GstFlowReturn
|
GstFlowReturn
|
||||||
gst_pad_push (GstPad * pad, GstBuffer * buffer)
|
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_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_PAD_IS_SRC (pad), GST_FLOW_ERROR);
|
||||||
g_return_val_if_fail (GST_IS_BUFFER (buffer), 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue