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);
/* 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.*/
/* 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;
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);
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;
}
/**
* 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
* 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);
/**
* 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);
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);
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;
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);