gst: Add a filter caps parameter to all get_caps() functions

This is used to pass the possible caps and preferences to
the pad and to allow better negotiation decisions.
This commit is contained in:
Sebastian Dröge 2011-05-10 17:56:33 +02:00
parent bdbc069348
commit 3fa1594aaf
6 changed files with 126 additions and 38 deletions

View file

@ -84,6 +84,10 @@ The 0.11 porting guide
Removed GST_PAD_CAPS() use gst_pad_get_current_caps() to get a handle to the
currently configured caps.
GstPadGetCapsFunction, gst_pad_get_caps(), gst_pad_peer_get_caps(),
gst_pad_proxy_getcaps() now takes a GstCaps* parameter to inform
the other side about the possible caps and preferences.
* GstMiniObject
A miniobject is now a simple refcounted structure holding the information
common to buffers, events, messages, queries and caps.

View file

@ -188,7 +188,7 @@ gst_proxy_pad_do_checkgetrange (GstPad * pad)
}
static GstCaps *
gst_proxy_pad_do_getcaps (GstPad * pad)
gst_proxy_pad_do_getcaps (GstPad * pad, GstCaps * filter)
{
GstPad *target = gst_proxy_pad_get_target (pad);
GstCaps *res;
@ -196,7 +196,7 @@ gst_proxy_pad_do_getcaps (GstPad * pad)
if (target) {
/* if we have a real target, proxy the call */
res = gst_pad_get_caps (target);
res = gst_pad_get_caps (target, filter);
GST_DEBUG_OBJECT (pad, "get caps of target %s:%s : %" GST_PTR_FORMAT,
GST_DEBUG_PAD_NAME (target), res);
@ -209,7 +209,7 @@ gst_proxy_pad_do_getcaps (GstPad * pad)
filt = GST_PAD_TEMPLATE_CAPS (templ);
if (filt) {
tmp = gst_caps_intersect (filt, res);
tmp = gst_caps_intersect_full (res, filt, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (res);
res = tmp;
GST_DEBUG_OBJECT (pad,
@ -224,6 +224,15 @@ gst_proxy_pad_do_getcaps (GstPad * pad)
"using pad template %p with caps %p %" GST_PTR_FORMAT, templ, res,
res);
res = gst_caps_ref (res);
if (filter) {
GstCaps *intersection =
gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (res);
res = intersection;
}
goto done;
}

View file

@ -124,7 +124,7 @@ static void gst_pad_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GstFlowReturn handle_pad_block (GstPad * pad);
static GstCaps *gst_pad_get_caps_unlocked (GstPad * pad);
static GstCaps *gst_pad_get_caps_unlocked (GstPad * pad, GstCaps * filter);
static void gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ);
static gboolean gst_pad_activate_default (GstPad * pad);
static gboolean gst_pad_acceptcaps_default (GstPad * pad, GstCaps * caps);
@ -1796,8 +1796,8 @@ gst_pad_link_check_compatible_unlocked (GstPad * src, GstPad * sink,
/* Doing the expensive caps checking takes priority over only checking the template caps */
if (flags & GST_PAD_LINK_CHECK_CAPS) {
srccaps = gst_pad_get_caps_unlocked (src);
sinkcaps = gst_pad_get_caps_unlocked (sink);
srccaps = gst_pad_get_caps_unlocked (src, NULL);
sinkcaps = gst_pad_get_caps_unlocked (sink, NULL);
} else {
/* If one of the two pads doesn't have a template, consider the intersection
* as valid.*/
@ -2188,7 +2188,7 @@ gst_pad_get_pad_template (GstPad * pad)
/* 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)
gst_pad_get_caps_unlocked (GstPad * pad, GstCaps * filter)
{
GstCaps *result = NULL;
GstPadTemplate *templ;
@ -2200,11 +2200,12 @@ gst_pad_get_caps_unlocked (GstPad * pad)
if (!fixed_caps && GST_PAD_GETCAPSFUNC (pad)) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"dispatching to pad getcaps function");
"dispatching to pad getcaps function with "
"filter %" GST_PTR_FORMAT, filter);
GST_OBJECT_FLAG_SET (pad, GST_PAD_IN_GETCAPS);
GST_OBJECT_UNLOCK (pad);
result = GST_PAD_GETCAPSFUNC (pad) (pad);
result = GST_PAD_GETCAPSFUNC (pad) (pad, filter);
GST_OBJECT_LOCK (pad);
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_IN_GETCAPS);
@ -2234,29 +2235,80 @@ gst_pad_get_caps_unlocked (GstPad * pad)
result = temp;
}
}
if (filter) {
if (!gst_caps_is_subset (result, filter)) {
GstCaps *temp;
GST_CAT_ERROR_OBJECT (GST_CAT_CAPS, pad,
"pad returned caps %" GST_PTR_FORMAT
" which are not a real subset of the filter caps %"
GST_PTR_FORMAT, result, 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);
gst_caps_unref (result);
result = temp;
}
}
#endif
goto done;
}
}
if (fixed_caps && (result = get_pad_caps (pad))) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"using pad caps %p %" GST_PTR_FORMAT, result, result);
result = gst_caps_ref (result);
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);
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);
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);
}
goto done;
}
if (!fixed_caps && (result = get_pad_caps (pad))) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"using pad caps %p %" GST_PTR_FORMAT, result, result);
result = gst_caps_ref (result);
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;
}
@ -2319,6 +2371,7 @@ gst_pad_get_current_caps (GstPad * pad)
/**
* gst_pad_get_caps:
* @pad: a #GstPad to get the capabilities of.
* @filter: suggested #GstCaps.
*
* Gets the capabilities this pad can produce or consume.
* Note that this method doesn't necessarily return the caps set by
@ -2327,23 +2380,30 @@ gst_pad_get_current_caps (GstPad * pad)
* the pad's get_caps function;
* this returns the pad template caps if not explicitly set.
*
* When called on sinkpads @filter contains the caps that
* upstream could produce in the order preferred by upstream. When
* called on srcpads @filter contains the caps accepted by
* downstream in the preffered order. @filter might be %NULL but
* if it is not %NULL the returned caps will be a subset of @filter.
*
* Note that this function does not return writable #GstCaps, use
* gst_caps_make_writable() before modifying the caps.
*
* Returns: the caps of the pad with incremented ref-count.
*/
GstCaps *
gst_pad_get_caps (GstPad * pad)
gst_pad_get_caps (GstPad * pad, GstCaps * filter)
{
GstCaps *result = NULL;
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), NULL);
GST_OBJECT_LOCK (pad);
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get pad caps");
result = gst_pad_get_caps_unlocked (pad);
result = gst_pad_get_caps_unlocked (pad, filter);
GST_OBJECT_UNLOCK (pad);
@ -2354,20 +2414,28 @@ gst_pad_get_caps (GstPad * pad)
/**
* gst_pad_peer_get_caps:
* @pad: a #GstPad to get the capabilities of.
* @filter: a #GstCaps filter.
*
* Gets the capabilities of the peer connected to this pad. Similar to
* gst_pad_get_caps().
*
* When called on srcpads @filter contains the caps that
* upstream could produce in the order preferred by upstream. When
* called on sinkpads @filter contains the caps accepted by
* downstream in the preffered order. @filter might be %NULL but
* if it is not %NULL the returned caps will be a subset of @filter.
*
* Returns: the caps of the peer pad with incremented ref-count. This function
* returns %NULL when there is no peer pad.
*/
GstCaps *
gst_pad_peer_get_caps (GstPad * pad)
gst_pad_peer_get_caps (GstPad * pad, GstCaps * filter)
{
GstPad *peerpad;
GstCaps *result = NULL;
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), NULL);
GST_OBJECT_LOCK (pad);
@ -2380,7 +2448,7 @@ gst_pad_peer_get_caps (GstPad * pad)
gst_object_ref (peerpad);
GST_OBJECT_UNLOCK (pad);
result = gst_pad_get_caps (peerpad);
result = gst_pad_get_caps (peerpad, filter);
gst_object_unref (peerpad);
@ -2503,7 +2571,7 @@ gst_pad_acceptcaps_default (GstPad * pad, GstCaps * caps)
GST_DEBUG_OBJECT (pad, "caps %" GST_PTR_FORMAT, caps);
allowed = gst_pad_get_caps (pad);
allowed = gst_pad_get_caps (pad, NULL);
if (!allowed)
goto nothing_allowed;
@ -2826,9 +2894,9 @@ gst_pad_get_allowed_caps (GstPad * pad)
gst_object_ref (peer);
GST_OBJECT_UNLOCK (pad);
mycaps = gst_pad_get_caps (pad);
mycaps = gst_pad_get_caps (pad, NULL);
peercaps = gst_pad_get_caps (peer);
peercaps = gst_pad_get_caps (peer, NULL);
gst_object_unref (peer);
caps = gst_caps_intersect (mycaps, peercaps);

View file

@ -420,6 +420,13 @@ typedef void (*GstPadUnlinkFunction) (GstPad *pad);
/**
* GstPadGetCapsFunction:
* @pad: the #GstPad to get the capabilities of.
* @filter: filter #GstCaps.
*
* When called on sinkpads @filter contains the caps that
* upstream could produce in the order preferred by upstream. When
* called on srcpads @filter contains the caps accepted by
* downstream in the preffered order. @filter might be %NULL but if
* it is not %NULL only a subset of @filter must be returned.
*
* Returns a copy of the capabilities of the specified pad. By default this
* function will return the pad template capabilities, but can optionally
@ -427,7 +434,7 @@ typedef void (*GstPadUnlinkFunction) (GstPad *pad);
*
* Returns: a newly allocated copy #GstCaps of the pad.
*/
typedef GstCaps* (*GstPadGetCapsFunction) (GstPad *pad);
typedef GstCaps* (*GstPadGetCapsFunction) (GstPad *pad, GstCaps *filter);
/**
* GstPadSetCapsFunction:
@ -845,12 +852,12 @@ G_CONST_RETURN GstCaps* gst_pad_get_pad_template_caps (GstPad *pad);
/* capsnego function for linked/unlinked pads */
GstCaps * gst_pad_get_current_caps (GstPad * pad);
gboolean gst_pad_has_current_caps (GstPad * pad);
GstCaps * gst_pad_get_caps (GstPad * pad);
GstCaps * gst_pad_get_caps (GstPad * pad, GstCaps *filter);
void gst_pad_fixate_caps (GstPad * pad, GstCaps *caps);
gboolean gst_pad_accept_caps (GstPad * pad, GstCaps *caps);
gboolean gst_pad_set_caps (GstPad * pad, GstCaps *caps);
GstCaps * gst_pad_peer_get_caps (GstPad * pad);
GstCaps * gst_pad_peer_get_caps (GstPad * pad, GstCaps *filter);
gboolean gst_pad_peer_accept_caps (GstPad * pad, GstCaps *caps);
/* capsnego for linked pads */

View file

@ -1140,7 +1140,7 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
gboolean compatible;
/* Now check if the two pads' caps are compatible */
temp = gst_pad_get_caps (pad);
temp = gst_pad_get_caps (pad, NULL);
if (caps) {
intersection = gst_caps_intersect (temp, caps);
gst_caps_unref (temp);
@ -1148,7 +1148,7 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
intersection = temp;
}
temp = gst_pad_get_caps (current);
temp = gst_pad_get_caps (current, NULL);
compatible = gst_caps_can_intersect (temp, intersection);
gst_caps_unref (temp);
gst_caps_unref (intersection);
@ -1198,7 +1198,7 @@ gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
/* try to create a new one */
/* requesting is a little crazy, we need a template. Let's create one */
/* FIXME: why not gst_pad_get_pad_template (pad); */
templcaps = gst_pad_get_caps (pad);
templcaps = gst_pad_get_caps (pad, NULL);
templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad),
GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps);
@ -2691,16 +2691,15 @@ gst_buffer_join (GstBuffer * buf1, GstBuffer * buf2)
return result;
}
static gboolean
getcaps_fold_func (const GValue * vpad, GValue * ret, GstPad * orig)
getcaps_fold_func (const GValue * vpad, GValue * ret, GstCaps * filter)
{
GstPad *pad = g_value_get_object (vpad);
gboolean empty = FALSE;
GstCaps *peercaps, *existing;
existing = g_value_get_pointer (ret);
peercaps = gst_pad_peer_get_caps (pad);
peercaps = gst_pad_peer_get_caps (pad, filter);
if (G_LIKELY (peercaps)) {
GstCaps *intersection = gst_caps_intersect (existing, peercaps);
@ -2716,6 +2715,7 @@ getcaps_fold_func (const GValue * vpad, GValue * ret, GstPad * orig)
/**
* gst_pad_proxy_getcaps:
* @pad: a #GstPad to proxy.
* @filter: a #GstCaps filter.
*
* Calls gst_pad_get_allowed_caps() for every other pad belonging to the
* same element as @pad, and returns the intersection of the results.
@ -2729,7 +2729,7 @@ getcaps_fold_func (const GValue * vpad, GValue * ret, GstPad * orig)
* Returns: (transfer full): the intersection of the other pads' allowed caps.
*/
GstCaps *
gst_pad_proxy_getcaps (GstPad * pad)
gst_pad_proxy_getcaps (GstPad * pad, GstCaps * filter)
{
GstElement *element;
GstCaps *caps, *intersected;
@ -2760,7 +2760,7 @@ gst_pad_proxy_getcaps (GstPad * pad)
while (1) {
res =
gst_iterator_fold (iter, (GstIteratorFoldFunction) getcaps_fold_func,
&ret, pad);
&ret, filter);
switch (res) {
case GST_ITERATOR_RESYNC:
/* unref any value stored */

View file

@ -907,7 +907,7 @@ void gst_element_class_install_std_props (GstElementClass * klass,
/* pad functions */
void gst_pad_use_fixed_caps (GstPad *pad);
GstCaps* gst_pad_proxy_getcaps (GstPad * pad);
GstCaps* gst_pad_proxy_getcaps (GstPad * pad, GstCaps * filter);
gboolean gst_pad_proxy_setcaps (GstPad * pad, GstCaps * caps);
GstElement* gst_pad_get_parent_element (GstPad *pad);