mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-28 01:58:19 +00:00
add API to make life easier
Original commit message from CVS: add API to make life easier
This commit is contained in:
parent
780213e23a
commit
9d34e82b9a
4 changed files with 249 additions and 0 deletions
169
gst/gstelement.c
169
gst/gstelement.c
|
@ -697,6 +697,175 @@ gst_element_request_pad_by_name (GstElement *element, const gchar *name)
|
|||
return pad;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_get_compatible_pad_filtered:
|
||||
* @element: the element in which the pad should be found
|
||||
* @pad: the pad to find a compatible one for
|
||||
* @filtercaps: the caps to use as a filter
|
||||
*
|
||||
* Looks for an unconnected pad to which the given pad can connect to.
|
||||
* It is not guaranteed that connecting the pads will work, though
|
||||
* it should work in most cases.
|
||||
*
|
||||
* Returns: the pad to which a connection can be made
|
||||
*/
|
||||
|
||||
GstPad*
|
||||
gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad, GstCaps *filtercaps)
|
||||
{
|
||||
GList *pads;
|
||||
GstPadTemplate *templ;
|
||||
GstCaps *intersection;
|
||||
GstPad *foundpad = NULL;
|
||||
|
||||
/* checks */
|
||||
g_return_val_if_fail (element != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
|
||||
g_return_val_if_fail (pad != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
/* let's use the real pad */
|
||||
pad = (GstPad *) GST_PAD_REALIZE (pad);
|
||||
g_return_val_if_fail (pad != NULL, NULL);
|
||||
g_return_val_if_fail (GST_RPAD_PEER (pad) == NULL, NULL);
|
||||
|
||||
/* try to get an existing unconnected pad */
|
||||
pads = gst_element_get_pad_list (element);
|
||||
while (pads)
|
||||
{
|
||||
GstPad *current = GST_PAD (pads->data);
|
||||
if ((GST_PAD_PEER (GST_PAD_REALIZE (current)) == NULL) &&
|
||||
gst_pad_can_connect_filtered (pad, current, filtercaps))
|
||||
{
|
||||
return current;
|
||||
}
|
||||
pads = g_list_next (pads);
|
||||
}
|
||||
|
||||
/* try to create a new one */
|
||||
/* requesting is a little crazy, we need a template. Let's create one */
|
||||
if (filtercaps != NULL)
|
||||
{
|
||||
filtercaps = gst_caps_intersect (filtercaps, (GstCaps *) GST_RPAD_CAPS (pad));
|
||||
if (filtercaps == NULL)
|
||||
return NULL;
|
||||
}
|
||||
templ = gst_padtemplate_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
|
||||
GST_PAD_ALWAYS, filtercaps);
|
||||
foundpad = gst_element_request_compatible_pad (element, templ);
|
||||
gst_object_unref (GST_OBJECT (templ));
|
||||
if (filtercaps != NULL)
|
||||
gst_caps_unref (filtercaps);
|
||||
|
||||
return foundpad;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_get_compatible_pad:
|
||||
* @element: the element in which the pad should be found
|
||||
* @pad: the pad to find a compatible one for
|
||||
*
|
||||
* Looks for an unconnected pad to which the given pad can connect to.
|
||||
* It is not guaranteed that connecting the pads will work, though
|
||||
* it should work in most cases.
|
||||
*
|
||||
* Returns: the pad to which a connection can be made
|
||||
*/
|
||||
|
||||
GstPad*
|
||||
gst_element_get_compatible_pad (GstElement *element, GstPad *pad)
|
||||
{
|
||||
return gst_element_get_compatible_pad_filtered (element, pad, NULL);
|
||||
}
|
||||
/**
|
||||
* gst_element_connect_elements:
|
||||
* @src: the element containing source pad
|
||||
* @dest: the element containing destination pad
|
||||
* @filtercaps: the caps to use as filter
|
||||
*
|
||||
* Connect the source to the destination element using the filtercaps.
|
||||
* The connection must be from source to destination, the other
|
||||
* direction will not be tried.
|
||||
* The functions looks for existing pads that aren't connected yet.
|
||||
+ It will use request pads if possible. But both pads will not be requested.
|
||||
* If multiple connections are possible, only one is established.
|
||||
*
|
||||
* Return: TRUE if the elements could be connected.
|
||||
*/
|
||||
gboolean
|
||||
gst_element_connect_elements_filtered (GstElement *src, GstElement *dest,
|
||||
GstCaps *filtercaps)
|
||||
{
|
||||
GList *srcpads, *destpads;
|
||||
GstPad *srcpad, *destpad;
|
||||
|
||||
/* checks */
|
||||
g_return_val_if_fail (src != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_ELEMENT(src), FALSE);
|
||||
g_return_val_if_fail (dest != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_ELEMENT(dest), FALSE);
|
||||
|
||||
GST_DEBUG (GST_CAT_ELEMENT_PADS, "attempting to connect element %s to element %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
|
||||
|
||||
/* loop through the existing pads in the source */
|
||||
srcpads = gst_element_get_pad_list (src);
|
||||
while (srcpads)
|
||||
{
|
||||
srcpad = (GstPad *) GST_PAD_REALIZE (srcpads->data);
|
||||
if ((GST_RPAD_DIRECTION (srcpad) == GST_PAD_SRC) &&
|
||||
(GST_PAD_PEER (srcpad) == NULL))
|
||||
{
|
||||
destpad = gst_element_get_compatible_pad_filtered (dest, srcpad, filtercaps);
|
||||
if (destpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps))
|
||||
{
|
||||
GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s\n", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
srcpads = g_list_next (srcpads);
|
||||
}
|
||||
|
||||
/* loop through the existing pads in the destination */
|
||||
destpads = gst_element_get_pad_list (dest);
|
||||
while (destpads)
|
||||
{
|
||||
destpad = (GstPad *) GST_PAD_REALIZE (destpads->data);
|
||||
if ((GST_RPAD_DIRECTION (destpad) == GST_PAD_SINK) &&
|
||||
(GST_PAD_PEER (destpad) == NULL))
|
||||
{
|
||||
srcpad = gst_element_get_compatible_pad_filtered (src, destpad, filtercaps);
|
||||
if (srcpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps))
|
||||
{
|
||||
GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s\n", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
destpads = g_list_next (destpads);
|
||||
}
|
||||
|
||||
GST_DEBUG (GST_CAT_ELEMENT_PADS, "no connection possible from %s to %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_connect_elements:
|
||||
* @src: element containing source pad
|
||||
* @dest: element containing destination pad
|
||||
*
|
||||
* Connect the source to the destination element.
|
||||
* The connection must be from source to destination, the other
|
||||
* direction will not be tried.
|
||||
* The functions looks for existing pads and request pads that aren't
|
||||
* connected yet. If multiple connections are possible, only one is
|
||||
* established.
|
||||
*
|
||||
* Return: TRUE if the elements could be connected.
|
||||
*/
|
||||
gboolean
|
||||
gst_element_connect_elements (GstElement *src, GstElement *dest)
|
||||
{
|
||||
return gst_element_connect_elements_filtered (src, dest, NULL);
|
||||
}
|
||||
/**
|
||||
* gst_element_connect_filtered:
|
||||
* @src: element containing source pad
|
||||
|
|
|
@ -199,7 +199,14 @@ void gst_element_remove_ghost_pad (GstElement *element, GstPad *pad);
|
|||
|
||||
GstPad* gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ);
|
||||
GstPad* gst_element_request_pad_by_name (GstElement *element, const gchar *name);
|
||||
GstPad* gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad,
|
||||
GstCaps *filtercaps);
|
||||
GstPad* gst_element_get_compatible_pad (GstElement *element, GstPad *pad);
|
||||
|
||||
/* these functions should probably have another name, but gst_element_connect is already used */
|
||||
gboolean gst_element_connect_elements (GstElement *src, GstElement *dest);
|
||||
gboolean gst_element_connect_elements_filtered (GstElement *src, GstElement *dest,
|
||||
GstCaps *filtercaps);
|
||||
gboolean gst_element_connect (GstElement *src, const gchar *srcpadname,
|
||||
GstElement *dest, const gchar *destpadname);
|
||||
gboolean gst_element_connect_filtered (GstElement *src, const gchar *srcpadname,
|
||||
|
|
70
gst/gstpad.c
70
gst/gstpad.c
|
@ -573,6 +573,76 @@ gst_pad_disconnect (GstPad *srcpad,
|
|||
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_pad_can_connect_filtered:
|
||||
* @srcpad: the source pad to connect
|
||||
* @sinkpad: the sink pad to connect
|
||||
* @filtercaps: the filter caps.
|
||||
*
|
||||
* Checks if the source pad and the sink pad can be connected.
|
||||
* The filter indicates the media type that should flow trought this connection.
|
||||
*
|
||||
* Returns: TRUE if the pad can be connected, FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
gst_pad_can_connect_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps)
|
||||
{
|
||||
gint num_decoupled = 0;
|
||||
GstRealPad *realsrc, *realsink;
|
||||
|
||||
/* generic checks */
|
||||
g_return_val_if_fail (srcpad != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
|
||||
g_return_val_if_fail (sinkpad != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
|
||||
|
||||
/* now we need to deal with the real/ghost stuff */
|
||||
realsrc = GST_PAD_REALIZE (srcpad);
|
||||
realsink = GST_PAD_REALIZE (sinkpad);
|
||||
|
||||
g_return_val_if_fail (GST_RPAD_PEER (realsrc) == NULL, FALSE);
|
||||
g_return_val_if_fail (GST_RPAD_PEER (realsink) == NULL, FALSE);
|
||||
g_return_val_if_fail (GST_PAD_PARENT (realsrc) != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_PAD_PARENT (realsink) != NULL, FALSE);
|
||||
|
||||
if (realsrc->sched && realsink->sched) {
|
||||
if (GST_FLAG_IS_SET (GST_PAD_PARENT (realsrc), GST_ELEMENT_DECOUPLED))
|
||||
num_decoupled++;
|
||||
if (GST_FLAG_IS_SET (GST_PAD_PARENT (realsink), GST_ELEMENT_DECOUPLED))
|
||||
num_decoupled++;
|
||||
|
||||
if (realsrc->sched != realsink->sched && num_decoupled != 1) {
|
||||
g_warning ("connecting pads with different scheds requires exactly one decoupled element (queue)\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if the directions are compatible */
|
||||
if (!(((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SINK) &&
|
||||
(GST_RPAD_DIRECTION (realsink) == GST_PAD_SRC)) ||
|
||||
((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SRC) &&
|
||||
(GST_RPAD_DIRECTION (realsink) == GST_PAD_SINK))))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
/**
|
||||
* gst_pad_can_connect:
|
||||
* @srcpad: the source pad to connect
|
||||
* @sinkpad: the sink pad to connect
|
||||
*
|
||||
* Checks if the source pad can be connected to the sink pad.
|
||||
*
|
||||
* Returns: TRUE if the pads can be connected, FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
gst_pad_can_connect (GstPad *srcpad, GstPad *sinkpad)
|
||||
{
|
||||
return gst_pad_can_connect_filtered (srcpad, sinkpad, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_pad_connect_filtered:
|
||||
* @srcpad: the source pad to connect
|
||||
|
|
|
@ -385,6 +385,9 @@ GstPad* gst_pad_get_peer (GstPad *pad);
|
|||
|
||||
GstBufferPool* gst_pad_get_bufferpool (GstPad *pad);
|
||||
|
||||
gboolean gst_pad_can_connect (GstPad *srcpad, GstPad *sinkpad);
|
||||
gboolean gst_pad_can_connect_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps);
|
||||
|
||||
gboolean gst_pad_connect (GstPad *srcpad, GstPad *sinkpad);
|
||||
gboolean gst_pad_connect_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps);
|
||||
void gst_pad_disconnect (GstPad *srcpad, GstPad *sinkpad);
|
||||
|
|
Loading…
Reference in a new issue