}G_STMT_END
#define GST_CAT_DEFAULT GST_CAT_PADS
+/* realize and pad and grab the lock of the realized pad. */
+#define GST_PAD_REALIZE_AND_LOCK(pad, realpad, lost_ghostpad) \
+ GST_LOCK (pad); \
+ realpad = GST_PAD_REALIZE (pad); \
+ if (G_UNLIKELY (realpad == NULL)) { \
+ GST_UNLOCK (pad); \
+ goto lost_ghostpad; \
+ } \
+ if (G_UNLIKELY (pad != GST_PAD_CAST (realpad))) { \
+ GST_LOCK (realpad); \
+ GST_UNLOCK (pad); \
+ }
+
struct _GstPadLink
{
GType type;
GstPad *pad = GST_PAD (object);
gst_pad_set_pad_template (pad, NULL);
+ /* FIXME, we have links to many other things like caps
+ * and the peer pad... */
G_OBJECT_CLASS (pad_parent_class)->dispose (object);
}
static void gst_real_pad_class_init (GstRealPadClass * klass);
static void gst_real_pad_init (GstRealPad * pad);
static void gst_real_pad_dispose (GObject * object);
+static void gst_real_pad_finalize (GObject * object);
+
static gboolean _gst_real_pad_fixate_accumulator (GSignalInvocationHint * ihint,
GValue * return_accu, const GValue * handler_return, gpointer dummy);
real_pad_parent_class = g_type_class_ref (GST_TYPE_PAD);
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_real_pad_dispose);
+ gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_real_pad_finalize);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_real_pad_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_real_pad_get_property);
pad->formatsfunc = gst_pad_get_formats_default;
pad->querytypefunc = gst_pad_get_query_types_default;
- GST_FLAG_SET (pad, GST_PAD_DISABLED);
+ GST_FLAG_UNSET (pad, GST_PAD_ACTIVE);
GST_FLAG_UNSET (pad, GST_PAD_NEGOTIATING);
gst_probe_dispatcher_init (&pad->probedisp);
switch (prop_id) {
case REAL_ARG_ACTIVE:
- g_value_set_boolean (value, !GST_FLAG_IS_SET (object, GST_PAD_DISABLED));
+ g_value_set_boolean (value, GST_FLAG_IS_SET (object, GST_PAD_ACTIVE));
break;
case REAL_ARG_CAPS:
g_value_set_boxed (value, GST_PAD_CAPS (GST_REAL_PAD (object)));
}
/* FIXME-0.9: Replace these custom functions with proper inheritance via _init
- functions and object properties */
+ functions and object properties. update: probably later in the cycle. */
/**
* gst_pad_custom_new:
* @type: the #Gtype of the pad.
*
* Creates a new pad with the given name and type in the given direction.
* If name is NULL, a guaranteed unique name (across all pads)
- * will be assigned.
+ * will be assigned.
+ * This function makes a copy of the name so you can safely free the name.
*
* Returns: a new #GstPad, or NULL in case of an error.
+ *
+ * MT safe.
*/
GstPad *
gst_pad_custom_new (GType type, const gchar * name, GstPadDirection direction)
{
GstRealPad *pad;
- g_return_val_if_fail (direction != GST_PAD_UNKNOWN, NULL);
-
pad = g_object_new (type, NULL);
gst_object_set_name (GST_OBJECT (pad), name);
GST_RPAD_DIRECTION (pad) = direction;
- return GST_PAD (pad);
+ return GST_PAD_CAST (pad);
}
/**
* Creates a new real pad with the given name in the given direction.
* If name is NULL, a guaranteed unique name (across all pads)
* will be assigned.
+ * This function makes a copy of the name so you can safely free the name.
*
* Returns: a new #GstPad, or NULL in case of an error.
+ *
+ * MT safe.
*/
GstPad *
gst_pad_new (const gchar * name, GstPadDirection direction)
* Creates a new custom pad with the given name from the given template.
* If name is NULL, a guaranteed unique name (across all pads)
* will be assigned.
+ * This function makes a copy of the name so you can safely free the name.
*
* Returns: a new #GstPad, or NULL in case of an error.
*/
* Creates a new real pad with the given name from the given template.
* If name is NULL, a guaranteed unique name (across all pads)
* will be assigned.
+ * This function makes a copy of the name so you can safely free the name.
*
* Returns: a new #GstPad, or NULL in case of an error.
*/
templ, name);
}
-/* FIXME 0.9: GST_PAD_UNKNOWN needs to die! */
/**
* gst_pad_get_direction:
* @pad: a #GstPad to get the direction of.
*
- * Gets the direction of the pad.
+ * Gets the direction of the pad. The direction of the pad is
+ * decided at construction time so this function does not take
+ * the LOCK.
*
* Returns: the #GstPadDirection of the pad.
+ *
+ * MT safe.
*/
GstPadDirection
gst_pad_get_direction (GstPad * pad)
{
+ GstPadDirection result;
+
+ /* pad unkown is a little silly but we need some sort of
+ * error return value */
g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN);
- if (GST_IS_REAL_PAD (pad))
- return GST_PAD_DIRECTION (pad);
- else
- return GST_PAD_UNKNOWN;
+ /* since the direction cannot change at runtime we can
+ * safely read without locking. */
+ result = GST_PAD_DIRECTION (pad);
+
+ return result;
}
/**
* @active: TRUE to activate the pad.
*
* Activates or deactivates the given pad.
+ *
+ * Returns: TRUE if the operation was successfull.
*/
-void
+gboolean
gst_pad_set_active (GstPad * pad, gboolean active)
{
GstRealPad *realpad;
gboolean old;
GstPadLink *link;
- g_return_if_fail (GST_IS_PAD (pad));
+ g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
old = GST_PAD_IS_ACTIVE (pad);
if (old == active)
- return;
+ return TRUE;
realpad = GST_PAD_REALIZE (pad);
if (active) {
GST_CAT_DEBUG (GST_CAT_PADS, "activating pad %s:%s",
GST_DEBUG_PAD_NAME (realpad));
- GST_FLAG_UNSET (realpad, GST_PAD_DISABLED);
+ GST_FLAG_SET (realpad, GST_PAD_ACTIVE);
} else {
GST_CAT_DEBUG (GST_CAT_PADS, "de-activating pad %s:%s",
GST_DEBUG_PAD_NAME (realpad));
- GST_FLAG_SET (realpad, GST_PAD_DISABLED);
+ GST_FLAG_UNSET (realpad, GST_PAD_ACTIVE);
}
link = GST_RPAD_LINK (realpad);
if (link) {
}
g_object_notify (G_OBJECT (realpad), "active");
+
+ return TRUE;
}
/**
* Query if a pad is active
*
* Returns: TRUE if the pad is active.
+ *
+ * MT safe.
*/
gboolean
gst_pad_is_active (GstPad * pad)
{
- g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-
- return !GST_FLAG_IS_SET (pad, GST_PAD_DISABLED);
-}
+ gboolean result = FALSE;
+ GstRealPad *realpad;
-/**
- * gst_pad_set_name:
- * @pad: a #GstPad to set the name of.
- * @name: the name of the pad.
- *
- * Sets the name of a pad. If name is NULL, then a guaranteed unique
- * name will be assigned.
- */
-void
-gst_pad_set_name (GstPad * pad, const gchar * name)
-{
- g_return_if_fail (GST_IS_PAD (pad));
+ g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
- gst_object_set_name (GST_OBJECT (pad), name);
-}
+ GST_PAD_REALIZE_AND_LOCK (pad, realpad, lost_ghostpad);
+ result = GST_FLAG_IS_SET (realpad, GST_PAD_ACTIVE);
+ GST_UNLOCK (realpad);
-/* FIXME 0.9: This function must die */
-/**
- * gst_pad_get_name:
- * @pad: a #GstPad to get the name of.
- *
- * Gets the name of a pad.
- *
- * Returns: the name of the pad. This is not a newly allocated pointer
- * so you must not free it.
- */
-const gchar *
-gst_pad_get_name (GstPad * pad)
-{
- g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+ return result;
- return GST_OBJECT_NAME (pad);
+lost_ghostpad:
+ {
+ return FALSE;
+ }
}
/**
* @chain: the #GstPadChainFunction to set.
*
* Sets the given chain function for the pad. The chain function is called to
- * process a #GstData input buffer.
+ * process a #GstBuffer input buffer.
*/
void
gst_pad_set_chain_function (GstPad * pad, GstPadChainFunction chain)
gst_pad_set_event_function (GstPad * pad, GstPadEventFunction event)
{
g_return_if_fail (GST_IS_REAL_PAD (pad));
- g_return_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SRC);
GST_RPAD_EVENTFUNC (pad) = event;
* Checks if a @pad is linked to another pad or not.
*
* Returns: TRUE if the pad is linked, FALSE otherwise.
+ *
+ * MT safe.
*/
gboolean
gst_pad_is_linked (GstPad * pad)
{
+ gboolean result;
+ GstRealPad *realpad;
+
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
- return GST_PAD_PEER (pad) != NULL;
+ GST_PAD_REALIZE_AND_LOCK (pad, realpad, lost_ghostpad);
+ result = (GST_PAD_PEER (realpad) != NULL);
+ GST_UNLOCK (realpad);
+ return result;
+
+lost_ghostpad:
+ {
+ return FALSE;
+ }
}
static gboolean
gst_pad_link_free (GstPadLink * link)
{
if (link->srccaps)
- gst_caps_free (link->srccaps);
+ gst_caps_unref (link->srccaps);
if (link->sinkcaps)
- gst_caps_free (link->sinkcaps);
+ gst_caps_unref (link->sinkcaps);
if (link->filtercaps)
- gst_caps_free (link->filtercaps);
+ gst_caps_unref (link->filtercaps);
if (link->caps)
- gst_caps_free (link->caps);
+ gst_caps_unref (link->caps);
if (link->temp_store)
gst_data_unref (link->temp_store);
#ifdef USE_POISONING
GstCaps *pad_intersection;
if (link->caps)
- gst_caps_free (link->caps);
+ gst_caps_unref (link->caps);
GST_DEBUG ("intersecting link from %s:%s to %s:%s",
GST_DEBUG_PAD_NAME (link->srcpad), GST_DEBUG_PAD_NAME (link->sinkpad));
if (link->filtercaps) {
GST_DEBUG ("unfiltered intersection %" GST_PTR_FORMAT, pad_intersection);
link->caps = gst_caps_intersect (pad_intersection, link->filtercaps);
- gst_caps_free (pad_intersection);
+ gst_caps_unref (pad_intersection);
} else {
link->caps = pad_intersection;
}
} else if (gst_caps_is_empty (newcaps)) {
g_warning
("a fixation function did not fixate correctly, it returned empty caps");
- gst_caps_free (newcaps);
+ gst_caps_unref (newcaps);
continue;
} else if (gst_caps_is_any (caps)) {
bad = gst_caps_is_any (newcaps);
GstCaps *test = gst_caps_subtract (caps, newcaps);
bad = gst_caps_is_empty (test);
- gst_caps_free (test);
+ gst_caps_unref (test);
/* simplifying is ok, too */
if (bad)
bad = (gst_caps_get_size (newcaps) >= gst_caps_get_size (caps));
newcaps_str, caps_str);
g_free (newcaps_str);
g_free (caps_str);
- gst_caps_free (newcaps);
+ gst_caps_unref (newcaps);
} else
#endif
{
- gst_caps_free (caps);
+ gst_caps_unref (caps);
caps = newcaps;
break;
}
return ret;
}
+/* FIXME, temporarily put here until real code gets backported */
+gboolean
+gst_pad_set_caps (GstPad * pad, GstCaps * caps)
+{
+ return TRUE;
+}
+
/**
* gst_pad_try_set_caps_nonfixed:
* @pad: a real #GstPad
intersection = gst_caps_intersect (caps, GST_PAD_CAPS (pad));
if (!gst_caps_is_empty (intersection)) {
- gst_caps_free (intersection);
+ gst_caps_unref (intersection);
return GST_PAD_LINK_OK;
}
- gst_caps_free (intersection);
+ gst_caps_unref (intersection);
}
link = gst_pad_link_new ();
}
/**
- * gst_pad_can_link_filtered:
- * @srcpad: the source #GstPad to link.
- * @sinkpad: the sink #GstPad to link.
- * @filtercaps: the filter #GstCaps.
- *
- * Checks if the source pad and the sink pad can be linked when constrained
- * by the given filter caps. Both @srcpad and @sinkpad must be unlinked.
- *
- * Returns: TRUE if the pads can be linked, FALSE otherwise.
- */
-gboolean
-gst_pad_can_link_filtered (GstPad * srcpad, GstPad * sinkpad,
- const GstCaps * filtercaps)
-{
- GstRealPad *realsrc, *realsink;
- GstPadLink *link;
-
- /* FIXME This function is gross. It's almost a direct copy of
- * gst_pad_link_filtered(). Any decent programmer would attempt
- * to merge the two functions, which I will do some day. --ds
- */
-
- /* 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);
-
- GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s",
- GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
-
- /* now we need to deal with the real/ghost stuff */
- realsrc = GST_PAD_REALIZE (srcpad);
- realsink = GST_PAD_REALIZE (sinkpad);
-
- if ((GST_PAD (realsrc) != srcpad) || (GST_PAD (realsink) != sinkpad)) {
- GST_CAT_INFO (GST_CAT_PADS, "*actually* linking %s:%s and %s:%s",
- GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
- }
- /* FIXME: shouldn't we convert this to g_return_val_if_fail? */
- if (GST_RPAD_PEER (realsrc) != NULL) {
- GST_CAT_INFO (GST_CAT_PADS, "Real source pad %s:%s has a peer, failed",
- GST_DEBUG_PAD_NAME (realsrc));
- return FALSE;
- }
- if (GST_RPAD_PEER (realsink) != NULL) {
- GST_CAT_INFO (GST_CAT_PADS, "Real sink pad %s:%s has a peer, failed",
- GST_DEBUG_PAD_NAME (realsink));
- return FALSE;
- }
- if (GST_PAD_PARENT (realsrc) == NULL) {
- GST_CAT_INFO (GST_CAT_PADS, "Real src pad %s:%s has no parent, failed",
- GST_DEBUG_PAD_NAME (realsrc));
- return FALSE;
- }
- if (GST_PAD_PARENT (realsink) == NULL) {
- GST_CAT_INFO (GST_CAT_PADS, "Real sink pad %s:%s has no parent, failed",
- GST_DEBUG_PAD_NAME (realsrc));
- return FALSE;
- }
-
- if (!gst_pad_check_schedulers (realsrc, realsink)) {
- g_warning ("linking pads with different scheds requires "
- "exactly one decoupled element (such as queue)");
- return FALSE;
- }
-
- g_return_val_if_fail (realsrc != NULL, GST_PAD_LINK_REFUSED);
- g_return_val_if_fail (realsink != NULL, GST_PAD_LINK_REFUSED);
-
- link = gst_pad_link_new ();
-
- if (GST_RPAD_DIRECTION (realsrc) == GST_PAD_SRC) {
- link->srcpad = GST_PAD (realsrc);
- link->sinkpad = GST_PAD (realsink);
- } else {
- link->srcpad = GST_PAD (realsink);
- link->sinkpad = GST_PAD (realsrc);
- }
-
- if (GST_RPAD_DIRECTION (link->srcpad) != GST_PAD_SRC) {
- GST_CAT_INFO (GST_CAT_PADS,
- "Real src pad %s:%s is not a source pad, failed",
- GST_DEBUG_PAD_NAME (link->srcpad));
- gst_pad_link_free (link);
- return FALSE;
- }
- if (GST_RPAD_DIRECTION (link->sinkpad) != GST_PAD_SINK) {
- GST_CAT_INFO (GST_CAT_PADS, "Real sink pad %s:%s is not a sink pad, failed",
- GST_DEBUG_PAD_NAME (link->sinkpad));
- gst_pad_link_free (link);
- return FALSE;
- }
-
- link->srccaps = gst_pad_get_caps (link->srcpad);
- link->sinkcaps = gst_pad_get_caps (link->sinkpad);
- if (filtercaps)
- link->filtercaps = gst_caps_copy (filtercaps);
-
- gst_pad_link_intersect (link);
- if (gst_caps_is_empty (link->caps)) {
- gst_pad_link_free (link);
- return FALSE;
- }
-
- gst_pad_link_free (link);
- return TRUE;
-}
-
-/**
- * gst_pad_can_link:
- * @srcpad: the source #GstPad to link.
- * @sinkpad: the sink #GstPad to link.
- *
- * Checks if the source pad and the sink pad can be linked.
- *
- * Returns: TRUE if the pads can be linked, FALSE otherwise.
- */
-gboolean
-gst_pad_can_link (GstPad * srcpad, GstPad * sinkpad)
-{
- return gst_pad_can_link_filtered (srcpad, sinkpad, NULL);
-}
-
-/**
* gst_pad_link_filtered:
* @srcpad: the source #GstPad to link.
* @sinkpad: the sink #GstPad to link.
return gst_pad_link_filtered (srcpad, sinkpad, NULL);
}
-/* FIXME 0.9: Remove this */
-/**
- * gst_pad_set_parent:
- * @pad: a #GstPad to set the parent of.
- * @parent: the new parent #GstElement.
- *
- * Sets the parent object of a pad. Deprecated, use gst_object_set_parent()
- * instead.
- */
-void
-gst_pad_set_parent (GstPad * pad, GstElement * parent)
-{
- g_return_if_fail (GST_IS_PAD (pad));
- g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
- g_return_if_fail (GST_IS_ELEMENT (parent));
-
- gst_object_set_parent (GST_OBJECT (pad), GST_OBJECT (parent));
-}
-
-/* FIXME 0.9: Remove this */
-/**
- * gst_pad_get_parent:
- * @pad: the #GstPad to get the parent of.
- *
- * Gets the parent object of this pad. Deprecated, use gst_object_get_parent()
- * instead.
- *
- * Returns: the parent #GstElement.
- */
-GstElement *
-gst_pad_get_parent (GstPad * pad)
-{
- g_return_val_if_fail (pad != NULL, NULL);
- g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
- return GST_PAD_PARENT (pad);
-}
-
static void
gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ)
{
/* this function would need checks if it weren't static */
+ GST_LOCK (pad);
gst_object_replace ((GstObject **) & pad->padtemplate, (GstObject *) templ);
+ GST_UNLOCK (pad);
if (templ) {
gst_object_sink (GST_OBJECT (templ));
* Gets the real parent object of this pad. If the pad
* is a ghost pad, the actual owner of the real pad is
* returned, as opposed to #gst_pad_get_parent().
+ * Unref the object after use.
*
* Returns: the parent #GstElement.
+ *
+ * MT safe.
*/
GstElement *
gst_pad_get_real_parent (GstPad * pad)
{
+ GstRealPad *realpad;
+ GstElement *element;
+
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
- return GST_PAD_PARENT (GST_PAD (GST_PAD_REALIZE (pad)));
+ GST_PAD_REALIZE_AND_LOCK (pad, realpad, lost_ghostpad);
+ element = GST_PAD_PARENT (realpad);
+ if (element)
+ gst_object_ref (GST_OBJECT (element));
+ GST_UNLOCK (realpad);
+
+ return element;
+
+lost_ghostpad:
+ {
+ return NULL;
+ }
}
-/* FIXME 0.9: Make static. */
-/**
- * gst_pad_add_ghost_pad:
- * @pad: a #GstPad to attach the ghost pad to.
- * @ghostpad: the ghost #GstPad to to the pad.
- *
- * Adds a ghost pad to a pad. Private function, will be removed from the API in
- * 0.9.
- */
-void
+/* FIXME not MT safe */
+static void
gst_pad_add_ghost_pad (GstPad * pad, GstPad * ghostpad)
{
GstRealPad *realpad;
- g_return_if_fail (GST_IS_PAD (pad));
- g_return_if_fail (GST_IS_GHOST_PAD (ghostpad));
-
/* if we're ghosting a ghost pad, drill down to find the real pad */
realpad = (GstRealPad *) pad;
while (GST_IS_GHOST_PAD (realpad))
gst_pad_set_pad_template (GST_PAD (ghostpad), GST_PAD_PAD_TEMPLATE (pad));
}
-/* FIXME 0.9: Make static. */
-/**
- * gst_pad_remove_ghost_pad:
- * @pad: a #GstPad to remove the ghost pad from.
- * @ghostpad: the ghost #GstPad to remove from the pad.
- *
- * Removes a ghost pad from a pad. Private, will be removed from the API in 0.9.
- */
-void
+static void
gst_pad_remove_ghost_pad (GstPad * pad, GstPad * ghostpad)
{
GstRealPad *realpad;
- g_return_if_fail (GST_IS_PAD (pad));
- g_return_if_fail (GST_IS_GHOST_PAD (ghostpad));
realpad = GST_PAD_REALIZE (pad);
g_return_if_fail (GST_GPAD_REALPAD (ghostpad) == realpad);
}
static gboolean
-_gst_pad_default_fixate_foreach (GQuark field_id, GValue * value, gpointer s)
+_gst_pad_default_fixate_foreach (GQuark field_id, const GValue * value,
+ gpointer s)
{
GstStructure *structure = (GstStructure *) s;
GValue dest = { 0 };
g_return_if_fail (link != NULL);
if (link->caps) {
- gst_caps_free (link->caps);
+ gst_caps_unref (link->caps);
link->caps = NULL;
link->engaged = FALSE;
if (GST_RPAD_LINK (link->srcpad) != link) {
}
/**
- * gst_pad_proxy_getcaps:
- * @pad: a #GstPad to proxy.
- *
- * Calls gst_pad_get_allowed_caps() for every other pad belonging to the
- * same element as @pad, and returns the intersection of the results.
- *
- * This function is useful as a default getcaps function for an element
- * that can handle any stream format, but requires all its pads to have
- * the same caps. Two such elements are tee and aggregator.
- *
- * Returns: the intersection of the other pads' allowed caps.
- */
-GstCaps *
-gst_pad_proxy_getcaps (GstPad * pad)
-{
- GstElement *element;
- const GList *pads;
- GstCaps *caps, *intersected;
-
- g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
- GST_DEBUG ("proxying getcaps for %s:%s", GST_DEBUG_PAD_NAME (pad));
-
- element = gst_pad_get_parent (pad);
-
- pads = gst_element_get_pad_list (element);
-
- caps = gst_caps_new_any ();
- while (pads) {
- GstPad *otherpad = GST_PAD (pads->data);
- GstCaps *temp;
-
- if (otherpad != pad) {
- GstCaps *allowed = gst_pad_get_allowed_caps (otherpad);
-
- temp = gst_caps_intersect (caps, allowed);
- gst_caps_free (caps);
- gst_caps_free (allowed);
- caps = temp;
- }
-
- pads = g_list_next (pads);
- }
-
- intersected = gst_caps_intersect (caps, gst_pad_get_pad_template_caps (pad));
- gst_caps_free (caps);
- return intersected;
-}
-
-/**
- * gst_pad_proxy_pad_link:
- * @pad: a #GstPad to proxy from
- * @caps: the #GstCaps to link with
- *
- * Calls gst_pad_try_set_caps() for every other pad belonging to the
- * same element as @pad. If gst_pad_try_set_caps() fails on any pad,
- * the proxy link fails. May be used only during negotiation.
- *
- * Returns: GST_PAD_LINK_OK if sucessful
- */
-GstPadLinkReturn
-gst_pad_proxy_pad_link (GstPad * pad, const GstCaps * caps)
-{
- GstElement *element;
- const GList *pads;
- GstPadLinkReturn ret;
-
- g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_LINK_REFUSED);
- g_return_val_if_fail (caps != NULL, GST_PAD_LINK_REFUSED);
-
- GST_DEBUG ("proxying pad link for %s:%s", GST_DEBUG_PAD_NAME (pad));
-
- element = gst_pad_get_parent (pad);
-
- pads = gst_element_get_pad_list (element);
-
- while (pads) {
- GstPad *otherpad = GST_PAD (pads->data);
-
- if (otherpad != pad) {
- ret = gst_pad_try_set_caps (otherpad, caps);
- if (GST_PAD_LINK_FAILED (ret)) {
- return ret;
- }
- }
- pads = g_list_next (pads);
- }
-
- return GST_PAD_LINK_OK;
-}
-
-/**
* gst_pad_proxy_fixate:
* @pad: a #GstPad to proxy.
* @caps: the #GstCaps to fixate
element = gst_pad_get_parent (pad);
- pads = gst_element_get_pad_list (element);
+ /* FIXME, not MT safe but this function will be removed */
+ pads = element->pads;
while (pads) {
GstPad *otherpad = GST_PAD (pads->data);
if (!gst_caps_is_empty (icaps)) {
return icaps;
} else {
- gst_caps_free (icaps);
+ gst_caps_unref (icaps);
}
}
}
* Gets the capabilities of this pad.
*
* Returns: the #GstCaps of this pad. This function returns a new caps, so use
- * gst_caps_free to get rid of it.
+ * gst_caps_unref to get rid of it.
*/
GstCaps *
gst_pad_get_caps (GstPad * pad)
("pad %s:%s returned caps that are not a real subset of its template caps",
GST_DEBUG_PAD_NAME (realpad));
temp = gst_caps_intersect (templ_caps, caps);
- gst_caps_free (caps);
+ gst_caps_unref (caps);
caps = temp;
}
}
}
/**
+ * gst_pad_peer_get_caps:
+ * @pad: a #GstPad to get the peer capabilities of.
+ *
+ * Gets the capabilities of the peer connected to this pad.
+ *
+ * Returns: the #GstCaps of the peer pad. This function returns a new caps, so use
+ * gst_caps_unref to get rid of it.
+ */
+GstCaps *
+gst_pad_peer_get_caps (GstPad * pad)
+{
+ GstRealPad *realpad, *peerpad;
+ GstCaps *result = NULL;
+
+ g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+
+ /* now we need to deal with the real/ghost stuff */
+ GST_PAD_REALIZE_AND_LOCK (pad, realpad, lost_ghostpad);
+
+ GST_CAT_DEBUG (GST_CAT_CAPS, "get peer caps of %s:%s (%p)",
+ GST_DEBUG_PAD_NAME (realpad), realpad);
+
+ peerpad = GST_RPAD_PEER (realpad);
+ if (G_UNLIKELY (peerpad == NULL))
+ goto no_peer;
+
+ gst_object_ref (GST_OBJECT (peerpad));
+ GST_UNLOCK (realpad);
+
+ result = gst_pad_get_caps (GST_PAD_CAST (peerpad));
+
+ gst_object_unref (GST_OBJECT (peerpad));
+
+ return result;
+
+lost_ghostpad:
+ {
+ return NULL;
+ }
+no_peer:
+ {
+ GST_UNLOCK (realpad);
+ return gst_caps_new_any ();
+ }
+}
+
+/**
* gst_pad_get_pad_template_caps:
* @pad: a #GstPad to get the template capabilities from.
*
if (GST_PAD_PAD_TEMPLATE (pad))
return GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad));
-#if 0
- /* FIXME this should be enabled some day */
- /* wingo: why? mail the list during 0.9 when you find this :) */
- g_warning ("pad %s:%s (%p) has no pad template\n",
- GST_DEBUG_PAD_NAME (realpad), realpad);
-#endif
-
return gst_static_caps_get (&anycaps);
}
-/* FIXME 0.9: This function should probably die, or at least be renamed to
- * get_caps_by_format. */
+
/**
- * gst_pad_template_get_caps_by_name:
- * @templ: a #GstPadTemplate to get the capabilities of.
- * @name: the name of the capability to get.
+ * gst_pad_get_peer:
+ * @pad: a #GstPad to get the peer of.
+ *
+ * Gets the peer of @pad. This function refs the peer pad so
+ * you need to unref it after use.
*
- * Gets the capability with the given name from @templ.
+ * Returns: the peer #GstPad. Unref after usage.
*
- * Returns: the #GstCaps of this pad template, or NULL if not found. If you
- * intend to keep a reference on the caps, make a copy (see gst_caps_copy ()).
+ * MT safe.
*/
-const GstCaps *
-gst_pad_template_get_caps_by_name (GstPadTemplate * templ, const gchar * name)
+GstPad *
+gst_pad_get_peer (GstPad * pad)
{
- GstCaps *caps;
+ GstRealPad *realpad;
+ GstRealPad *result;
- g_return_val_if_fail (templ != NULL, NULL);
+ g_return_val_if_fail (GST_IS_PAD (pad), NULL);
- caps = GST_PAD_TEMPLATE_CAPS (templ);
- if (!caps)
- return NULL;
+ GST_PAD_REALIZE_AND_LOCK (pad, realpad, lost_ghostpad);
+ result = GST_RPAD_PEER (realpad);
+ if (result)
+ gst_object_ref (GST_OBJECT (result));
+ GST_UNLOCK (realpad);
- /* FIXME */
- return NULL;
-}
+ return GST_PAD_CAST (result);
-/* FIXME 0.9: What good is this if it only works for already-negotiated pads? */
-/**
- * gst_pad_check_compatibility:
- * @srcpad: the source #GstPad to check.
- * @sinkpad: the sink #GstPad to check against.
- *
- * Checks if two pads have compatible capabilities. If neither one has yet been
- * negotiated, returns TRUE for no good reason.
- *
- * Returns: TRUE if they are compatible or if the capabilities could not be
- * checked, FALSE if the capabilities are not compatible.
- */
-gboolean
-gst_pad_check_compatibility (GstPad * srcpad, GstPad * sinkpad)
-{
- g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
- g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
-
- if (GST_PAD_CAPS (srcpad) && GST_PAD_CAPS (sinkpad)) {
- if (!gst_caps_is_always_compatible (GST_PAD_CAPS (srcpad),
- GST_PAD_CAPS (sinkpad))) {
- return FALSE;
- } else {
- return TRUE;
- }
- } else {
- GST_CAT_DEBUG (GST_CAT_PADS,
- "could not check capabilities of pads (%s:%s) and (%s:%s) %p %p",
- GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad),
- GST_PAD_CAPS (srcpad), GST_PAD_CAPS (sinkpad));
- return TRUE;
+lost_ghostpad:
+ {
+ return NULL;
}
}
/**
- * gst_pad_get_peer:
- * @pad: a #GstPad to get the peer of.
+ * gst_pad_realize:
+ * @pad: a #GstPad to realize
+ *
+ * If the pad is a #GstRealPad, it is simply returned, else
+ * the #GstGhostPad will be dereffed to the real pad.
+ *
+ * After this function you always receive the real pad of
+ * the provided pad.
+ *
+ * This function unrefs the input pad and refs the result so
+ * that you can write constructs like:
+ *
+ * pad = gst_pad_realize(pad)
*
- * Gets the peer of @pad.
+ * without having to unref the old pad.
*
- * Returns: the peer #GstPad.
+ * Returns: the real #GstPad or NULL when an old reference to a
+ * ghostpad is used.
+ *
+ * MT safe.
*/
GstPad *
-gst_pad_get_peer (GstPad * pad)
+gst_pad_realize (GstPad * pad)
{
+ GstRealPad *result;
+
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
- return GST_PAD (GST_PAD_PEER (pad));
+ GST_LOCK (pad);
+ result = GST_PAD_REALIZE (pad);
+ if (result && pad != GST_PAD_CAST (result)) {
+ gst_object_ref (GST_OBJECT (result));
+ GST_UNLOCK (pad);
+ /* no other thread could dispose this since we
+ * hold at least one ref */
+ gst_object_unref (GST_OBJECT (pad));
+ } else {
+ GST_UNLOCK (pad);
+ }
+
+ return GST_PAD_CAST (result);
}
/**
* gst_pad_get_allowed_caps:
- * @pad: a real #GstPad.
+ * @srcpad: a #GstPad, it must a a source pad.
*
- * Gets the capabilities of the allowed media types that can flow through @pad.
+ * Gets the capabilities of the allowed media types that can flow through @pad
+ * and its peer. The pad must be a source pad.
* The caller must free the resulting caps.
*
* Returns: the allowed #GstCaps of the pad link. Free the caps when
- * you no longer need it.
+ * you no longer need it. This function returns NULL when the @pad has no
+ * peer.
+ *
+ * MT safe.
*/
GstCaps *
-gst_pad_get_allowed_caps (GstPad * pad)
+gst_pad_get_allowed_caps (GstPad * srcpad)
{
- const GstCaps *mycaps;
+ GstCaps *mycaps;
GstCaps *caps;
GstCaps *peercaps;
- GstCaps *icaps;
- GstPadLink *link;
+ GstRealPad *realpad, *peer;
- g_return_val_if_fail (GST_IS_REAL_PAD (pad), NULL);
+ g_return_val_if_fail (GST_IS_PAD (srcpad), NULL);
+
+ GST_PAD_REALIZE_AND_LOCK (srcpad, realpad, lost_ghostpad);
+
+ if (G_UNLIKELY ((peer = GST_RPAD_PEER (realpad)) == NULL))
+ goto no_peer;
GST_CAT_DEBUG (GST_CAT_PROPERTIES, "%s:%s: getting allowed caps",
- GST_DEBUG_PAD_NAME (pad));
+ GST_DEBUG_PAD_NAME (realpad));
- mycaps = gst_pad_get_pad_template_caps (pad);
- if (GST_RPAD_PEER (pad) == NULL) {
- GST_CAT_DEBUG (GST_CAT_PROPERTIES, "%s:%s: no peer, returning template",
- GST_DEBUG_PAD_NAME (pad));
- return gst_caps_copy (mycaps);
- }
+ gst_object_ref (GST_OBJECT_CAST (peer));
+ GST_UNLOCK (realpad);
+ mycaps = gst_pad_get_caps (GST_PAD_CAST (realpad));
+
+ peercaps = gst_pad_get_caps (GST_PAD_CAST (peer));
+ gst_object_unref (GST_OBJECT_CAST (peer));
- peercaps = gst_pad_get_caps (GST_PAD_PEER (pad));
caps = gst_caps_intersect (mycaps, peercaps);
- gst_caps_free (peercaps);
+ gst_caps_unref (peercaps);
+ gst_caps_unref (mycaps);
- link = GST_RPAD_LINK (pad);
- if (link->filtercaps) {
- icaps = gst_caps_intersect (caps, link->filtercaps);
- gst_caps_free (caps);
- GST_CAT_DEBUG (GST_CAT_PROPERTIES,
- "%s:%s: returning filtered intersection with peer",
- GST_DEBUG_PAD_NAME (pad));
- return icaps;
- } else {
- GST_CAT_DEBUG (GST_CAT_PROPERTIES,
- "%s:%s: returning unfiltered intersection with peer",
- GST_DEBUG_PAD_NAME (pad));
- return caps;
+ GST_CAT_DEBUG (GST_CAT_CAPS, "allowed caps %" GST_PTR_FORMAT, caps);
+
+ return caps;
+
+lost_ghostpad:
+ {
+ GST_UNLOCK (srcpad);
+ return NULL;
+ }
+no_peer:
+ {
+ GST_CAT_DEBUG (GST_CAT_PROPERTIES, "%s:%s: no peer",
+ GST_DEBUG_PAD_NAME (realpad));
+ GST_UNLOCK (realpad);
+
+ return NULL;
}
}
static void
gst_real_pad_dispose (GObject * object)
{
- GstPad *pad = GST_PAD (object);
+ GstPad *pad;
+ GstRealPad *rpad;
+
+ pad = GST_PAD (object);
+ rpad = GST_REAL_PAD (object);
/* No linked pad can ever be disposed.
* It has to have a parent to be linked
GST_DEBUG_PAD_NAME (pad));
/* we destroy the ghostpads, because they are nothing without the real pad */
- if (GST_REAL_PAD (pad)->ghostpads) {
+ if (rpad->ghostpads) {
GList *orig, *ghostpads;
- orig = ghostpads = g_list_copy (GST_REAL_PAD (pad)->ghostpads);
+ orig = ghostpads = g_list_copy (rpad->ghostpads);
while (ghostpads) {
GstPad *ghostpad = GST_PAD (ghostpads->data);
g_list_free (orig);
/* as the ghost pads are removed, they remove themselves from ->ghostpads.
So it should be empty now. Let's assert that. */
- g_assert (GST_REAL_PAD (pad)->ghostpads == NULL);
+ g_assert (rpad->ghostpads == NULL);
}
if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))) {
G_OBJECT_CLASS (real_pad_parent_class)->dispose (object);
}
+static void
+gst_real_pad_finalize (GObject * object)
+{
+ //GstRealPad *rpad;
+
+ //rpad = GST_REAL_PAD (object);
+
+ G_OBJECT_CLASS (real_pad_parent_class)->finalize (object);
+}
+
#ifndef GST_DISABLE_LOADSAVE
/* FIXME: why isn't this on a GstElement ? */
return parent;
}
-/* FIXME: shouldn't it be gst_pad_ghost_* ?
- * dunno -- wingo 7 feb 2004
- */
/**
* gst_ghost_pad_save_thyself:
* @pad: a ghost #GstPad to save.
}
pads[i] = NULL;
- return gst_pad_collect_array (GST_ELEMENT_SCHED (element), selected, pads);
+ return gst_pad_collect_array (GST_ELEMENT_SCHEDULER (element), selected,
+ pads);
}
/**
pad = va_arg (var_args, GstPad *);
}
padlist[i] = NULL;
- return gst_pad_collect_array (GST_ELEMENT_SCHED (element), selected, padlist);
+ return gst_pad_collect_array (GST_ELEMENT_SCHEDULER (element), selected,
+ padlist);
}
/**
g_free (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ));
if (GST_PAD_TEMPLATE_CAPS (templ)) {
- gst_caps_free (GST_PAD_TEMPLATE_CAPS (templ));
+ gst_caps_unref (GST_PAD_TEMPLATE_CAPS (templ));
}
G_OBJECT_CLASS (padtemplate_parent_class)->dispose (object);
if (caps) {
GstCaps *newcaps = gst_caps_copy (caps);
- gst_caps_free (caps);
+ gst_caps_unref (caps);
caps = newcaps;
}
#endif
rpad = GST_PAD_REALIZE (pad);
if (GST_RPAD_INTLINKFUNC (rpad))
- res = GST_RPAD_INTLINKFUNC (rpad) (GST_PAD (rpad));
+ res = GST_RPAD_INTLINKFUNC (rpad) (GST_PAD_CAST (rpad));
return res;
}