From 3fa1594aaf58492ded94aef8ecde23b2055c0bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 10 May 2011 17:56:33 +0200 Subject: [PATCH] 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. --- docs/random/porting-to-0.11.txt | 4 ++ gst/gstghostpad.c | 15 ++++- gst/gstpad.c | 114 +++++++++++++++++++++++++------- gst/gstpad.h | 13 +++- gst/gstutils.c | 16 ++--- gst/gstutils.h | 2 +- 6 files changed, 126 insertions(+), 38 deletions(-) diff --git a/docs/random/porting-to-0.11.txt b/docs/random/porting-to-0.11.txt index 0fe03489c0..e0c1571ad9 100644 --- a/docs/random/porting-to-0.11.txt +++ b/docs/random/porting-to-0.11.txt @@ -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. diff --git a/gst/gstghostpad.c b/gst/gstghostpad.c index 62beec765e..b33a241f34 100644 --- a/gst/gstghostpad.c +++ b/gst/gstghostpad.c @@ -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; } diff --git a/gst/gstpad.c b/gst/gstpad.c index 3b6942e8f6..22cfc4620f 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -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); diff --git a/gst/gstpad.h b/gst/gstpad.h index 412c1308de..475e141bd9 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -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 */ diff --git a/gst/gstutils.c b/gst/gstutils.c index 73522ba385..38c0c488e2 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -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 */ diff --git a/gst/gstutils.h b/gst/gstutils.h index dec9e98bbe..ce0f8bcb0b 100644 --- a/gst/gstutils.h +++ b/gst/gstutils.h @@ -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);