/* reset the filters, both filters are refcounted once */
if (GST_RPAD_FILTER (realsrc)) {
- gst_caps_unref (GST_RPAD_FILTER (realsrc));
- GST_RPAD_FILTER (realsink) = NULL;
- GST_RPAD_FILTER (realsrc) = NULL;
+ gst_caps_replace (&GST_RPAD_FILTER (realsink), NULL);
+ gst_caps_replace (&GST_RPAD_FILTER (realsrc), NULL);
}
/* now tell the scheduler */
if (src_sched && src_sched == sink_sched) {
gst_scheduler_pad_unlink (src_sched,
- GST_PAD_CAST (realsrc), GST_PAD_CAST (realsink));
+ GST_PAD_CAST (realsrc),
+ GST_PAD_CAST (realsink));
}
/* hold a reference, as they can go away in the signal handlers */
*/
gboolean
gst_pad_can_link_filtered (GstPad *srcpad, GstPad *sinkpad,
- GstCaps *filtercaps)
+ GstCaps *filtercaps)
{
GstRealPad *realsrc, *realsink;
/* try to negotiate the pads, we don't need to clear the caps here */
if (!gst_pad_try_relink_filtered_func (realsrc, realsink,
- filtercaps, FALSE)) {
+ filtercaps, FALSE)) {
GST_DEBUG (GST_CAT_CAPS, "relink_filtered_func failed, can't link");
GST_RPAD_PEER (realsrc) = NULL;
/* now tell the scheduler */
if (src_sched && src_sched == sink_sched) {
gst_scheduler_pad_link (src_sched,
- GST_PAD_CAST (realsrc), GST_PAD_CAST (realsink));
+ GST_PAD_CAST (realsrc), GST_PAD_CAST (realsink));
}
GST_INFO (GST_CAT_PADS, "linked %s:%s and %s:%s, successful",
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
- gst_caps_debug (gst_pad_get_caps (GST_PAD_CAST (realsrc)),
- "caps of newly linked src pad");
return TRUE;
}
static GstPadLinkReturn
gst_pad_try_set_caps_func (GstRealPad *pad, GstCaps *caps, gboolean notify)
{
- GstCaps *oldcaps, *allowed = NULL;
+ GstCaps *allowed = NULL;
GstPadTemplate *template;
GstElement *parent = GST_PAD_PARENT (pad);
GST_INFO (GST_CAT_CAPS, "trying to set caps %p on pad %s:%s",
caps, GST_DEBUG_PAD_NAME (pad));
- /* first see if we have to check against a filter */
- if (!(allowed = GST_RPAD_FILTER (pad))) {
+ /* first see if we have to check against a filter, we ref the caps here as we're
+ * going to unref it later on */
+ if (!(allowed = gst_caps_ref (GST_RPAD_FILTER (pad)))) {
/* no filter, make sure we check against the padtemplate then */
if ((template = gst_pad_get_pad_template (GST_PAD_CAST (pad)))) {
allowed = gst_pad_template_get_caps (template);
gst_caps_debug (caps, "caps themselves (attemped to set)");
gst_caps_debug (allowed,
"allowed caps that did not agree with caps");
+ gst_caps_unref (allowed);
return GST_PAD_LINK_REFUSED;
}
/* caps checks out fine, we can unref the intersection now */
gst_caps_unref (intersection);
+ gst_caps_unref (allowed);
/* given that the caps are fixed, we know that their intersection with the
* padtemplate caps is the same as caps itself */
}
GST_INFO (GST_CAT_CAPS, "setting caps on pad %s:%s",
GST_DEBUG_PAD_NAME (pad));
/* if we got this far all is ok, remove the old caps, set the new one */
- oldcaps = GST_PAD_CAPS (pad);
- if (caps) gst_caps_ref (caps);
- GST_PAD_CAPS (pad) = caps;
- if (oldcaps) gst_caps_unref (oldcaps);
+ gst_caps_replace_sink (&GST_PAD_CAPS (pad), caps);
g_object_notify (G_OBJECT (pad), "caps");
}
GST_INFO (GST_CAT_CAPS,
"caps are not fixed on pad %s:%s, not setting them yet",
GST_DEBUG_PAD_NAME (pad));
+
+ return GST_PAD_LINK_DELAYED;
}
return GST_PAD_LINK_OK;
}
* @pad: a #GstPad to try to set the caps on.
* @caps: the #GstCaps to set.
*
- * Tries to set the caps on the given pad.
+ * Tries to set the caps on the given pad. Ownership is always taken
+ * of the caps, so you will need to unref non-floating caps.
*
* Returns: A #GstPadLinkReturn value indicating whether the caps
* could be set.
gst_caps_debug (caps, "caps that we are trying to set");
+ /* try to take ownership */
+ gst_caps_ref (caps);
+ gst_caps_sink (caps);
+
/* setting non fixed caps on a pad is not allowed */
if (!GST_CAPS_IS_FIXED (caps)) {
- GST_INFO (GST_CAT_CAPS,
- "trying to set unfixed caps on pad %s:%s, not allowed",
- GST_DEBUG_PAD_NAME (realpad));
+ GST_INFO (GST_CAT_CAPS,
+ "trying to set unfixed caps on pad %s:%s, not allowed",
+ GST_DEBUG_PAD_NAME (realpad));
g_warning ("trying to set non fixed caps on pad %s:%s, not allowed",
GST_DEBUG_PAD_NAME (realpad));
+
gst_caps_debug (caps, "unfixed caps");
- return GST_PAD_LINK_DELAYED;
+ set_retval = GST_PAD_LINK_DELAYED;
+ goto done;
}
/* if we have a peer try to set the caps, notifying the peerpad
{
GST_INFO (GST_CAT_CAPS, "tried to set caps on peerpad %s:%s but couldn't, return value %d",
GST_DEBUG_PAD_NAME (peer), set_retval);
- return set_retval;
+ goto done;
}
/* then try to set our own caps, we don't need to be notified */
{
GST_INFO (GST_CAT_CAPS, "tried to set own caps on pad %s:%s but couldn't, return value %d",
GST_DEBUG_PAD_NAME (realpad), set_retval);
- return set_retval;
+ goto done;
}
GST_INFO (GST_CAT_CAPS, "succeeded setting caps %p on pad %s:%s, return value %d",
caps, GST_DEBUG_PAD_NAME (realpad), set_retval);
g_assert (GST_PAD_CAPS (pad));
-
+
+done:
+ /* if we took ownership, the caps will be freed */
+ gst_caps_unref (caps);
+
return set_retval;
}
GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
/* FIXME does this leak? */
- GST_PAD_CAPS (GST_PAD (realsrc)) = NULL;
- GST_PAD_CAPS (GST_PAD (realsink)) = NULL;
- GST_RPAD_FILTER (realsrc) = NULL;
- GST_RPAD_FILTER (realsink) = NULL;
+ gst_caps_replace (&GST_PAD_CAPS (GST_PAD (realsrc)), NULL);
+ gst_caps_replace (&GST_PAD_CAPS (GST_PAD (realsink)), NULL);
+ gst_caps_replace (&GST_RPAD_FILTER (realsrc), NULL);
+ gst_caps_replace (&GST_RPAD_FILTER (realsink), NULL);
}
else {
GST_INFO (GST_CAT_PADS, "start relink filtered %s:%s and %s:%s",
* this means they have no common format */
GST_INFO (GST_CAT_PADS, "pads %s:%s and %s:%s have no common type",
GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
+ /* make sure any floating caps from gst_pad_get_caps are freed here */
+ gst_caps_sink (srccaps);
+ gst_caps_sink (sinkcaps);
return FALSE;
} else {
GST_INFO (GST_CAT_PADS, "pads %s:%s and %s:%s intersected to %s caps",
(GST_CAPS_IS_FIXED (intersection) ? "fixed" : "variable") :
"NULL"));
+ /* we don't need those anymore, as the caps can be floating */
+ gst_caps_sink (srccaps);
+ gst_caps_sink (sinkcaps);
+
/* then filter this against the app filter */
if (filtercaps) {
GstCaps *filtered_intersection;
filtered_intersection = gst_caps_intersect (intersection,
filtercaps);
- /* get rid of the old intersection here */
gst_caps_unref (intersection);
if (!filtered_intersection) {
intersection = filtered_intersection;
/* keep a reference to the app caps */
- GST_RPAD_APPFILTER (realsink) = filtercaps;
- GST_RPAD_APPFILTER (realsrc) = filtercaps;
+ gst_caps_replace_sink (&GST_RPAD_APPFILTER (realsink), filtercaps);
+ gst_caps_replace_sink (&GST_RPAD_APPFILTER (realsrc), filtercaps);
}
}
GST_DEBUG (GST_CAT_CAPS, "setting filter for link to:");
/* both the app filter and the filter, while stored on both peer pads,
* are equal to the same thing on both */
- GST_RPAD_FILTER (realsrc) = intersection;
- GST_RPAD_FILTER (realsink) = intersection;
+ gst_caps_replace_sink (&GST_RPAD_FILTER (realsrc), intersection);
+ gst_caps_replace_sink (&GST_RPAD_FILTER (realsink), intersection);
+ gst_caps_unref (intersection);
return gst_pad_perform_negotiate (GST_PAD (realsrc), GST_PAD (realsink));
}
GstCaps *intersection, *filtered_intersection;
GstRealPad *realsrc, *realsink;
GstCaps *srccaps, *sinkcaps, *filter;
+ gboolean res = TRUE;
+ GstElement *parent;
+
g_return_val_if_fail (srcpad != NULL, FALSE);
g_return_val_if_fail (sinkpad != NULL, FALSE);
g_return_val_if_fail (GST_RPAD_PEER (realsrc) != NULL, FALSE);
g_return_val_if_fail (GST_RPAD_PEER (realsink) == realsrc, FALSE);
+ /* shortcut negotiation */
+ parent = GST_PAD_PARENT (realsrc);
+ if (parent && GST_STATE (parent) < GST_STATE_READY) {
+ GST_DEBUG (GST_CAT_CAPS, "parent %s of pad %s:%s is not READY",
+ GST_ELEMENT_NAME (parent), GST_DEBUG_PAD_NAME (realsrc));
+ return TRUE;
+ }
+ parent = GST_PAD_PARENT (realsink);
+ if (parent && GST_STATE (parent) < GST_STATE_READY) {
+ GST_DEBUG (GST_CAT_CAPS, "parent %s of pad %s:%s is not READY",
+ GST_ELEMENT_NAME (parent), GST_DEBUG_PAD_NAME (realsink));
+ return TRUE;
+ }
+
GST_INFO (GST_CAT_PADS, "perform negotiate for link %s:%s-%s:%s",
GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
"sink caps, awaiting negotiation, after applying filter");
intersection = gst_caps_intersect (srccaps, sinkcaps);
filtered_intersection = gst_caps_intersect (intersection, filter);
- if (filtered_intersection) {
- gst_caps_unref (intersection);
- intersection = filtered_intersection;
- }
+ gst_caps_unref (intersection);
/* no negotiation is performed if the pads have filtercaps */
- if (intersection) {
- GstPadLinkReturn res;
+ if (filtered_intersection) {
+ GstPadLinkReturn link_res;
- res = gst_pad_try_set_caps_func (realsrc, intersection, TRUE);
- if (res == GST_PAD_LINK_REFUSED)
- return FALSE;
- if (res == GST_PAD_LINK_DONE)
- return TRUE;
+ link_res = gst_pad_try_set_caps_func (realsrc, filtered_intersection, TRUE);
+ if (link_res == GST_PAD_LINK_REFUSED)
+ goto error;
+ if (link_res == GST_PAD_LINK_DONE)
+ goto success;
- res = gst_pad_try_set_caps_func (realsink, intersection, TRUE);
- if (res == GST_PAD_LINK_REFUSED)
- return FALSE;
- if (res == GST_PAD_LINK_DONE)
- return TRUE;
+ link_res = gst_pad_try_set_caps_func (realsink, filtered_intersection, TRUE);
+ if (link_res == GST_PAD_LINK_REFUSED)
+ goto error;
+ if (link_res == GST_PAD_LINK_DONE)
+ goto success;
}
- return TRUE;
+ /* no filtered_intersection, some pads had caps and ther was a filter */
+ else if ((srccaps || sinkcaps) && filter) {
+ goto error;
+ }
+
+success:
+cleanup:
+ gst_caps_sink (srccaps);
+ gst_caps_sink (sinkcaps);
+ gst_caps_unref (filtered_intersection);
+ return res;
+
+error:
+ res = FALSE;
+ goto cleanup;
}
/**
g_return_val_if_fail (GST_RPAD_PEER (realsink) == realsrc, FALSE);
return gst_pad_try_relink_filtered_func (realsrc, realsink,
- filtercaps, TRUE);
+ filtercaps, TRUE);
}
/**
g_return_val_if_fail (GST_RPAD_PEER (realsrc) != NULL, FALSE);
g_return_val_if_fail (GST_RPAD_PEER (realsink) == realsrc, FALSE);
- if (! gst_pad_try_relink_filtered_func (realsrc, realsink,
- filtercaps, TRUE)) {
+ if (!gst_pad_try_relink_filtered_func (realsrc, realsink,
+ filtercaps, TRUE))
+ {
gst_pad_unlink (srcpad, GST_PAD (GST_PAD_PEER (srcpad)));
return FALSE;
}
*
* Gets the capabilities of this pad.
*
- * Returns: the #GstCaps of this pad.
+ * Returns: the #GstCaps of this pad. This function potentially
+ * returns a floating caps, so use gst_caps_sink to get rid of
+ * it.
*/
GstCaps*
gst_pad_get_caps (GstPad *pad)
GST_DEBUG (GST_CAT_CAPS, "get pad caps of %s:%s (%p)",
GST_DEBUG_PAD_NAME (realpad), realpad);
+ /* note that we will not _ref the caps here as this function might be
+ * called recursively */
if (GST_PAD_CAPS (realpad)) {
GST_DEBUG (GST_CAT_CAPS, "using pad real caps %p", GST_PAD_CAPS (realpad));
return GST_PAD_CAPS (realpad);
*
* Gets the template capabilities of this pad.
*
- * Returns: the template #GstCaps of this pad.
+ * Returns: the template #GstCaps of this pad, unref the caps
+ * if you no longer need it.
*/
GstCaps*
gst_pad_get_pad_template_caps (GstPad *pad)
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
if (GST_PAD_PAD_TEMPLATE (pad))
- return GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad));
+ return gst_caps_ref (GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad)));
return NULL;
}
*
* Gets the capability with the given name from this pad template.
*
- * Returns: the #GstCaps, or NULL if not found or in case of an error.
+ * Returns: the #GstCaps, or NULL if not found or in case of an error. unref
+ * the caps if you no longer need it.
*/
GstCaps*
gst_pad_template_get_caps_by_name (GstPadTemplate *templ, const gchar *name)
if (!caps)
return NULL;
- return gst_caps_get_by_name (caps, name);
+ return gst_caps_ref (gst_caps_get_by_name (caps, name));
}
/**
* Gets the capabilities of the allowed media types that can
* flow through this pad. The caller must free the resulting caps.
*
- * Returns: a newly allocated copy of the allowed #GstCaps.
+ * Returns: the allowed #GstCaps of the pad link. unref the caps if
+ * you no longer need it.
*/
GstCaps*
gst_pad_get_allowed_caps (GstPad *pad)
GST_DEBUG (GST_CAT_PROPERTIES, "get allowed caps of %s:%s",
GST_DEBUG_PAD_NAME (pad));
- caps = gst_caps_copy (GST_RPAD_FILTER (pad));
+ caps = gst_caps_ref (GST_RPAD_FILTER (pad));
return caps;
}
peer = GST_RPAD_PEER (pad);
if (peer)
return gst_pad_try_relink_filtered (pad, GST_PAD (peer),
- GST_RPAD_APPFILTER (pad));
+ GST_RPAD_APPFILTER (pad));
return TRUE;
}
g_list_free (GST_REAL_PAD(pad)->ghostpads);
}
+ gst_caps_replace (&GST_PAD_CAPS (pad), NULL);
+ gst_caps_replace (&GST_RPAD_APPFILTER (pad), NULL);
+
if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))) {
GST_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'",
GST_OBJECT_NAME (GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad)))));
*/
static void gst_pad_template_class_init (GstPadTemplateClass *klass);
static void gst_pad_template_init (GstPadTemplate *templ);
+static void gst_pad_template_dispose (GObject *object);
GType
gst_pad_template_get_type (void)
NULL, NULL, gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
G_TYPE_POINTER);
+ gobject_class->dispose = gst_pad_template_dispose;
+
gstobject_class->path_string_separator = "*";
}
{
}
+static void
+gst_pad_template_dispose (GObject *object)
+{
+ GstPadTemplate *templ = GST_PAD_TEMPLATE (object);
+
+ g_free (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ));
+ gst_caps_unref (GST_PAD_TEMPLATE_CAPS (templ));
+
+ G_OBJECT_CLASS (padtemplate_parent_class)->dispose (object);
+}
+
/* ALWAYS padtemplates cannot have conversion specifications, it doesn't make
* sense.
* SOMETIMES padtemplates can do whatever they want, they are provided by the
va_start (var_args, caps);
+ GST_FLAG_SET (GST_OBJECT (new), GST_PAD_TEMPLATE_FIXED);
while (caps) {
- new->fixed &= caps->fixed;
- thecaps = gst_caps_append (thecaps, gst_caps_ref (caps));
+ if (!GST_CAPS_IS_FIXED (caps)) {
+ GST_FLAG_UNSET (GST_OBJECT (new), GST_PAD_TEMPLATE_FIXED);
+ }
+ thecaps = gst_caps_append (thecaps, caps);
caps = va_arg (var_args, GstCaps*);
}
va_end (var_args);
GST_PAD_TEMPLATE_CAPS (new) = thecaps;
+ gst_caps_ref (thecaps);
+ gst_caps_sink (thecaps);
return new;
}
*
* Gets the capabilities of the pad template.
*
- * Returns: the #GstCaps of the pad template.
+ * Returns: the #GstCaps of the pad template. unref the caps
+ * after use.
*/
GstCaps*
gst_pad_template_get_caps (GstPadTemplate *templ)
{
g_return_val_if_fail (templ != NULL, NULL);
- return GST_PAD_TEMPLATE_CAPS (templ);
+ return gst_caps_ref (GST_PAD_TEMPLATE_CAPS (templ));
}
/**