mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
pad: optimize linking
Optimize linking by only releasing the pad locks when there are link functions installed on the pads. Add some G_LIKELY here and there. Move error paths out of the main code flow.
This commit is contained in:
parent
50a8e0431c
commit
2b9c34cd70
1 changed files with 63 additions and 38 deletions
101
gst/gstpad.c
101
gst/gstpad.c
|
@ -2041,6 +2041,7 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
|
||||||
{
|
{
|
||||||
GstPadLinkReturn result;
|
GstPadLinkReturn result;
|
||||||
GstElement *parent;
|
GstElement *parent;
|
||||||
|
GstPadLinkFunction srcfunc, sinkfunc;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED);
|
g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED);
|
||||||
g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), GST_PAD_LINK_WRONG_DIRECTION);
|
g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), GST_PAD_LINK_WRONG_DIRECTION);
|
||||||
|
@ -2049,8 +2050,8 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
|
||||||
GST_PAD_LINK_WRONG_DIRECTION);
|
GST_PAD_LINK_WRONG_DIRECTION);
|
||||||
|
|
||||||
/* Notify the parent early. See gst_pad_unlink for details. */
|
/* Notify the parent early. See gst_pad_unlink for details. */
|
||||||
if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad)))) {
|
if (G_LIKELY ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad))))) {
|
||||||
if (GST_IS_ELEMENT (parent)) {
|
if (G_LIKELY (GST_IS_ELEMENT (parent))) {
|
||||||
gst_element_post_message (parent,
|
gst_element_post_message (parent,
|
||||||
gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad),
|
gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad),
|
||||||
GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, TRUE));
|
GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, TRUE));
|
||||||
|
@ -2063,7 +2064,7 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
|
||||||
/* prepare will also lock the two pads */
|
/* prepare will also lock the two pads */
|
||||||
result = gst_pad_link_prepare (srcpad, sinkpad, flags);
|
result = gst_pad_link_prepare (srcpad, sinkpad, flags);
|
||||||
|
|
||||||
if (result != GST_PAD_LINK_OK)
|
if (G_UNLIKELY (result != GST_PAD_LINK_OK))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* must set peers before calling the link function */
|
/* must set peers before calling the link function */
|
||||||
|
@ -2073,39 +2074,71 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
|
||||||
/* make sure we update events */
|
/* make sure we update events */
|
||||||
prepare_event_update (srcpad, sinkpad);
|
prepare_event_update (srcpad, sinkpad);
|
||||||
|
|
||||||
GST_OBJECT_UNLOCK (sinkpad);
|
/* get the link functions */
|
||||||
GST_OBJECT_UNLOCK (srcpad);
|
srcfunc = GST_PAD_LINKFUNC (srcpad);
|
||||||
|
sinkfunc = GST_PAD_LINKFUNC (sinkpad);
|
||||||
|
|
||||||
/* FIXME released the locks here, concurrent thread might link
|
if (G_UNLIKELY (srcfunc || sinkfunc)) {
|
||||||
* something else. */
|
/* custom link functions, execute them */
|
||||||
if (GST_PAD_LINKFUNC (srcpad)) {
|
|
||||||
/* this one will call the peer link function */
|
|
||||||
result = GST_PAD_LINKFUNC (srcpad) (srcpad, sinkpad);
|
|
||||||
} else if (GST_PAD_LINKFUNC (sinkpad)) {
|
|
||||||
/* if no source link function, we need to call the sink link
|
|
||||||
* function ourselves. */
|
|
||||||
result = GST_PAD_LINKFUNC (sinkpad) (sinkpad, srcpad);
|
|
||||||
} else {
|
|
||||||
result = GST_PAD_LINK_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_OBJECT_LOCK (srcpad);
|
|
||||||
GST_OBJECT_LOCK (sinkpad);
|
|
||||||
|
|
||||||
if (result == GST_PAD_LINK_OK) {
|
|
||||||
GST_OBJECT_UNLOCK (sinkpad);
|
GST_OBJECT_UNLOCK (sinkpad);
|
||||||
GST_OBJECT_UNLOCK (srcpad);
|
GST_OBJECT_UNLOCK (srcpad);
|
||||||
|
|
||||||
/* fire off a signal to each of the pads telling them
|
if (srcfunc) {
|
||||||
* that they've been linked */
|
/* this one will call the peer link function */
|
||||||
g_signal_emit (srcpad, gst_pad_signals[PAD_LINKED], 0, sinkpad);
|
result = srcfunc (srcpad, sinkpad);
|
||||||
g_signal_emit (sinkpad, gst_pad_signals[PAD_LINKED], 0, srcpad);
|
} else if (sinkfunc) {
|
||||||
|
/* if no source link function, we need to call the sink link
|
||||||
|
* function ourselves. */
|
||||||
|
result = sinkfunc (sinkpad, srcpad);
|
||||||
|
}
|
||||||
|
|
||||||
GST_CAT_INFO (GST_CAT_PADS, "linked %s:%s and %s:%s, successful",
|
GST_OBJECT_LOCK (srcpad);
|
||||||
|
GST_OBJECT_LOCK (sinkpad);
|
||||||
|
|
||||||
|
/* we released the lock, check if the same pads are linked still */
|
||||||
|
if (GST_PAD_PEER (srcpad) != sinkpad || GST_PAD_PEER (sinkpad) != srcpad)
|
||||||
|
goto concurrent_link;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (result != GST_PAD_LINK_OK))
|
||||||
|
goto link_failed;
|
||||||
|
}
|
||||||
|
GST_OBJECT_UNLOCK (sinkpad);
|
||||||
|
GST_OBJECT_UNLOCK (srcpad);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
g_signal_emit (sinkpad, gst_pad_signals[PAD_LINKED], 0, srcpad);
|
||||||
|
|
||||||
|
GST_CAT_INFO (GST_CAT_PADS, "linked %s:%s and %s:%s, successful",
|
||||||
|
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
|
||||||
|
|
||||||
|
gst_pad_send_event (srcpad, gst_event_new_reconfigure ());
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (G_LIKELY (parent)) {
|
||||||
|
gst_element_post_message (parent,
|
||||||
|
gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad),
|
||||||
|
GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, FALSE));
|
||||||
|
gst_object_unref (parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
concurrent_link:
|
||||||
|
{
|
||||||
|
GST_CAT_INFO (GST_CAT_PADS, "concurrent link between %s:%s and %s:%s",
|
||||||
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
|
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
|
||||||
|
GST_OBJECT_UNLOCK (sinkpad);
|
||||||
|
GST_OBJECT_UNLOCK (srcpad);
|
||||||
|
|
||||||
gst_pad_send_event (srcpad, gst_event_new_reconfigure ());
|
/* The other link operation succeeded first */
|
||||||
} else {
|
result = GST_PAD_LINK_WAS_LINKED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
link_failed:
|
||||||
|
{
|
||||||
GST_CAT_INFO (GST_CAT_PADS, "link between %s:%s and %s:%s failed",
|
GST_CAT_INFO (GST_CAT_PADS, "link between %s:%s and %s:%s failed",
|
||||||
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
|
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
|
||||||
|
|
||||||
|
@ -2114,17 +2147,9 @@ gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
|
||||||
|
|
||||||
GST_OBJECT_UNLOCK (sinkpad);
|
GST_OBJECT_UNLOCK (sinkpad);
|
||||||
GST_OBJECT_UNLOCK (srcpad);
|
GST_OBJECT_UNLOCK (srcpad);
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
goto done;
|
||||||
if (parent) {
|
|
||||||
gst_element_post_message (parent,
|
|
||||||
gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad),
|
|
||||||
GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, FALSE));
|
|
||||||
gst_object_unref (parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue