pad: improve the getcaps function

Refactor calling the GETCAPS function and checks.
Move the filter code in one place.
When using fixed pad caps, get the currently configured caps and then fallback
to the GETCAPS function. We used to simply ignore the GETCAPS function, which
resulted in transform elements returning the template caps instead of doing the
caps transform.
This commit is contained in:
Wim Taymans 2011-07-26 18:48:20 +02:00
parent cea4b4c7d5
commit 5e330fa456

View file

@ -2195,20 +2195,14 @@ gst_pad_get_pad_template (GstPad * pad)
return (templ ? gst_object_ref (templ) : NULL);
}
/* should be called with the pad LOCK held */
/* refs the caps, so caller is responsible for getting it unreffed */
static GstCaps *
gst_pad_get_caps_unlocked (GstPad * pad, GstCaps * filter)
caps_with_getcaps (GstPad * pad, GstCaps * filter)
{
GstCaps *result = NULL;
GstPadTemplate *templ;
gboolean fixed_caps;
GstCaps *result;
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get pad caps");
if (GST_PAD_GETCAPSFUNC (pad) == NULL)
return NULL;
fixed_caps = GST_PAD_IS_FIXED_CAPS (pad);
if (!fixed_caps && GST_PAD_GETCAPSFUNC (pad)) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"dispatching to pad getcaps function with "
"filter %" GST_PTR_FORMAT, filter);
@ -2219,12 +2213,12 @@ gst_pad_get_caps_unlocked (GstPad * pad, GstCaps * filter)
GST_OBJECT_LOCK (pad);
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_IN_GETCAPS);
if (result == NULL) {
g_critical ("pad %s:%s returned NULL caps from getcaps function",
GST_DEBUG_PAD_NAME (pad));
} else {
if (G_UNLIKELY (result == NULL))
goto null_caps;
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"pad getcaps returned %" GST_PTR_FORMAT, result);
#ifndef G_DISABLE_ASSERT
/* check that the returned caps are a real subset of the template caps */
if (GST_PAD_PAD_TEMPLATE (pad)) {
@ -2256,76 +2250,81 @@ gst_pad_get_caps_unlocked (GstPad * pad, GstCaps * filter)
g_warning ("pad %s:%s returned caps which are not a real "
"subset of the filter caps", GST_DEBUG_PAD_NAME (pad));
/* FIXME: Order? But shouldn't happen anyway... */
temp =
gst_caps_intersect_full (filter, result,
GST_CAPS_INTERSECT_FIRST);
temp = gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (result);
result = temp;
}
}
#endif
return result;
/* ERRORS */
null_caps:
{
g_critical ("pad %s:%s returned NULL caps from getcaps function",
GST_DEBUG_PAD_NAME (pad));
return NULL;
}
}
/* should be called with the pad LOCK held */
/* refs the caps, so caller is responsible for getting it unreffed */
static GstCaps *
gst_pad_get_caps_unlocked (GstPad * pad, GstCaps * filter)
{
GstCaps *result = NULL;
GstPadTemplate *templ;
gboolean fixed_caps;
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get pad caps");
fixed_caps = GST_PAD_IS_FIXED_CAPS (pad);
if (fixed_caps) {
/* fixed caps, try the negotiated caps first */
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "fixed pad caps: trying pad caps");
if ((result = get_pad_caps (pad)))
goto filter_done;
}
/* try the getcaps function next */
if ((result = caps_with_getcaps (pad, filter)))
goto done;
}
}
if (fixed_caps && (result = get_pad_caps (pad))) {
if (filter) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"using pad caps %p %" GST_PTR_FORMAT " with filter %p %"
GST_PTR_FORMAT, result, result, filter, filter);
result =
gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "result %p %" GST_PTR_FORMAT,
result);
} else {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"using pad caps %p %" GST_PTR_FORMAT, result, result);
result = gst_caps_ref (result);
}
goto done;
}
if ((templ = GST_PAD_PAD_TEMPLATE (pad))) {
result = GST_PAD_TEMPLATE_CAPS (templ);
if (filter) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"using pad template %p with caps %p %" GST_PTR_FORMAT
" and filter %p %" GST_PTR_FORMAT, templ, result, result, filter,
filter);
result =
gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "result %p %" GST_PTR_FORMAT,
result);
} else {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"using pad template %p with caps %p %" GST_PTR_FORMAT, templ, result,
result);
result = gst_caps_ref (result);
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "trying pad template caps");
if ((result = GST_PAD_TEMPLATE_CAPS (templ)))
goto filter_done;
}
goto done;
}
if (!fixed_caps && (result = get_pad_caps (pad))) {
if (filter) {
if (!fixed_caps) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"using pad caps %p %" GST_PTR_FORMAT " with filter %p %"
GST_PTR_FORMAT, result, result, filter, filter);
result =
gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "result %p %" GST_PTR_FORMAT,
result);
} else {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"using pad caps %p %" GST_PTR_FORMAT, result, result);
result = gst_caps_ref (result);
}
goto done;
"non-fixed pad caps: trying pad caps");
/* non fixed caps, try the negotiated caps */
if ((result = get_pad_caps (pad)))
goto filter_done;
}
/* this almost never happens */
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "pad has no caps");
result = gst_caps_new_empty ();
goto done;
filter_done:
/* run the filter on the result */
if (filter) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"using caps %p %" GST_PTR_FORMAT " with filter %p %"
GST_PTR_FORMAT, result, result, filter, filter);
result = gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "result %p %" GST_PTR_FORMAT,
result);
} else {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"using caps %p %" GST_PTR_FORMAT, result, result);
result = gst_caps_ref (result);
}
done:
return result;
}