pad: remove getcaps and use caps query

Remove the getcaps function on the pad and use the CAPS query for
the same effect.
Add PROXY_CAPS to the pad flags. This instructs the default caps event and query
handlers to pass on the CAPS related queries and events. This simplifies a lot
of elements that passtrough caps negotiation.
Make two utility functions to proxy caps queries and aggregate the result. Needs
to use the pad forward function instead later.
Make the _query_peer_ utility functions use the gst_pad_peer_query() function to
make sure the probes are emited properly.
This commit is contained in:
Wim Taymans 2011-11-15 11:20:48 +01:00
parent d162d97e1f
commit b5c3e254b1
29 changed files with 748 additions and 881 deletions

View file

@ -1014,7 +1014,6 @@ gst_proxy_pad_iterate_internal_links_default
gst_proxy_pad_chain_default gst_proxy_pad_chain_default
gst_proxy_pad_chain_list_default gst_proxy_pad_chain_list_default
gst_proxy_pad_getrange_default gst_proxy_pad_getrange_default
gst_proxy_pad_getcaps_default
gst_proxy_pad_unlink_default gst_proxy_pad_unlink_default
<SUBSECTION Standard> <SUBSECTION Standard>
GstGhostPadClass GstGhostPadClass
@ -1643,9 +1642,8 @@ GstPadUnlinkFunction
gst_pad_accept_caps gst_pad_accept_caps
gst_pad_set_getcaps_function gst_pad_proxy_query_caps
GstPadGetCapsFunction gst_pad_proxy_query_accept_caps
gst_pad_proxy_getcaps
gst_pad_peer_accept_caps gst_pad_peer_accept_caps

View file

@ -161,15 +161,14 @@ debug_dump_pad (GstPad * pad, const gchar * color_name,
} }
} }
if (details & GST_DEBUG_GRAPH_SHOW_STATES) { if (details & GST_DEBUG_GRAPH_SHOW_STATES) {
gchar pad_flags[5]; gchar pad_flags[4];
const gchar *activation_mode = "-><"; const gchar *activation_mode = "-><";
/* check if pad flags */ /* check if pad flags */
pad_flags[0] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKED) ? 'B' : 'b'; pad_flags[0] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKED) ? 'B' : 'b';
pad_flags[1] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING) ? 'F' : 'f'; pad_flags[1] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING) ? 'F' : 'f';
pad_flags[2] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_GETCAPS) ? 'G' : 'g'; pad_flags[2] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKING) ? 'B' : 'b';
pad_flags[3] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKING) ? 'B' : 'b'; pad_flags[3] = '\0';
pad_flags[4] = '\0';
fprintf (out, fprintf (out,
"%s %s_%s [color=black, fillcolor=\"%s\", label=\"%s\\n[%c][%s]\", height=\"0.2\", style=\"%s\"];\n", "%s %s_%s [color=black, fillcolor=\"%s\", label=\"%s\\n[%c][%s]\", height=\"0.2\", style=\"%s\"];\n",

View file

@ -1267,7 +1267,7 @@ gst_element_class_add_pad_template (GstElementClass * klass,
} }
/* Take ownership of the floating ref */ /* Take ownership of the floating ref */
g_object_ref_sink (templ); gst_object_ref_sink (templ);
klass->padtemplates = g_list_append (klass->padtemplates, templ); klass->padtemplates = g_list_append (klass->padtemplates, templ);
klass->numpadtemplates++; klass->numpadtemplates++;

View file

@ -92,6 +92,87 @@ gst_proxy_pad_event_default (GstPad * pad, GstEvent * event)
return res; return res;
} }
static gboolean
gst_proxy_pad_query_caps (GstPad * pad, GstQuery * query)
{
gboolean res;
GstPad *target;
GstCaps *result;
GstPadTemplate *templ;
g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
templ = GST_PAD_PAD_TEMPLATE (pad);
target = gst_proxy_pad_get_target (pad);
if (target) {
/* if we have a real target, proxy the call */
res = gst_pad_query (target, query);
GST_DEBUG_OBJECT (pad, "get caps of target %s:%s : %" GST_PTR_FORMAT,
GST_DEBUG_PAD_NAME (target), query);
gst_object_unref (target);
/* filter against the template */
if (templ && res) {
GstCaps *filt, *tmp;
filt = GST_PAD_TEMPLATE_CAPS (templ);
if (filt) {
gst_query_parse_caps_result (query, &result);
tmp = gst_caps_intersect_full (result, filt, GST_CAPS_INTERSECT_FIRST);
gst_query_set_caps_result (query, tmp);
GST_DEBUG_OBJECT (pad,
"filtered against template gives %" GST_PTR_FORMAT, tmp);
gst_caps_unref (tmp);
}
}
} else {
GstCaps *filter;
res = TRUE;
gst_query_parse_caps (query, &filter);
/* else, if we have a template, use its caps. */
if (templ) {
result = GST_PAD_TEMPLATE_CAPS (templ);
GST_DEBUG_OBJECT (pad,
"using pad template %p with caps %p %" GST_PTR_FORMAT, templ, result,
result);
if (filter) {
GstCaps *intersection;
GST_DEBUG_OBJECT (pad, "intersect with filter");
intersection =
gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
gst_query_set_caps_result (query, intersection);
gst_caps_unref (intersection);
} else {
gst_query_set_caps_result (query, result);
}
goto done;
}
/* If there's a filter, return that */
if (filter != NULL) {
GST_DEBUG_OBJECT (pad, "return filter");
gst_query_set_caps_result (query, filter);
goto done;
}
/* last resort, any caps */
GST_DEBUG_OBJECT (pad, "pad has no template, returning ANY");
result = gst_caps_new_any ();
gst_query_set_caps_result (query, result);
gst_caps_unref (result);
}
done:
return res;
}
/** /**
* gst_proxy_pad_query_default: * gst_proxy_pad_query_default:
* @pad: a #GstPad to invoke the default query on. * @pad: a #GstPad to invoke the default query on.
@ -112,11 +193,11 @@ gst_proxy_pad_query_default (GstPad * pad, GstQuery * query)
g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE); g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
g_return_val_if_fail (GST_IS_QUERY (query), FALSE); g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
target = gst_proxy_pad_get_target (pad);
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_ACCEPT_CAPS: case GST_QUERY_ACCEPT_CAPS:
{ {
target = gst_proxy_pad_get_target (pad);
if (target) { if (target) {
res = gst_pad_query (target, query); res = gst_pad_query (target, query);
gst_object_unref (target); gst_object_unref (target);
@ -128,8 +209,14 @@ gst_proxy_pad_query_default (GstPad * pad, GstQuery * query)
} }
break; break;
} }
case GST_QUERY_CAPS:
{
res = gst_proxy_pad_query_caps (pad, query);
break;
}
default: default:
{ {
target = gst_proxy_pad_get_target (pad);
if (target) { if (target) {
res = gst_pad_query (target, query); res = gst_pad_query (target, query);
gst_object_unref (target); gst_object_unref (target);
@ -256,119 +343,6 @@ gst_proxy_pad_getrange_default (GstPad * pad, guint64 offset, guint size,
return res; return res;
} }
/**
* gst_proxy_pad_getcaps_default:
* @pad: a #GstPad to get the capabilities of.
* @filter: a #GstCaps filter.
*
* Invoke the default getcaps function of the proxy pad.
*
* Returns: (transfer full): the caps of the pad with incremented ref-count
*
* Since: 0.10.36
*/
GstCaps *
gst_proxy_pad_getcaps_default (GstPad * pad, GstCaps * filter)
{
GstPad *target;
GstCaps *res;
GstPadTemplate *templ;
g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
templ = GST_PAD_PAD_TEMPLATE (pad);
target = gst_proxy_pad_get_target (pad);
if (target) {
/* if we have a real target, proxy the call */
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);
gst_object_unref (target);
/* filter against the template */
if (templ && res) {
GstCaps *filt, *tmp;
filt = GST_PAD_TEMPLATE_CAPS (templ);
if (filt) {
tmp = gst_caps_intersect_full (res, filt, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (res);
res = tmp;
GST_DEBUG_OBJECT (pad,
"filtered against template gives %" GST_PTR_FORMAT, res);
}
}
} else {
/* else, if we have a template, use its caps. */
if (templ) {
res = GST_PAD_TEMPLATE_CAPS (templ);
GST_DEBUG_OBJECT (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;
}
/* If there's a filter, return that */
if (filter != NULL) {
res = gst_caps_ref (filter);
goto done;
}
/* last resort, any caps */
GST_DEBUG_OBJECT (pad, "pad has no template, returning ANY");
res = gst_caps_new_any ();
}
done:
return res;
}
/**
* gst_proxy_pad_acceptcaps_default:
* @pad: a #GstPad to check
* @caps: a #GstCaps to check on the pad
*
* Invoke the default acceptcaps function of the proxy pad.
*
* Returns: TRUE if the pad can accept the caps.
*
* Since: 0.10.36
*/
gboolean
gst_proxy_pad_acceptcaps_default (GstPad * pad, GstCaps * caps)
{
GstPad *target;
gboolean res;
g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
target = gst_proxy_pad_get_target (pad);
if (target) {
res = gst_pad_accept_caps (target, caps);
gst_object_unref (target);
} else {
GST_DEBUG_OBJECT (pad, "no target");
/* We don't have a target, we return TRUE and we assume that any future
* target will be able to deal with any configured caps. */
res = TRUE;
}
return res;
}
static GstPad * static GstPad *
gst_proxy_pad_get_target (GstPad * pad) gst_proxy_pad_get_target (GstPad * pad)
{ {
@ -437,8 +411,6 @@ gst_proxy_pad_class_init (GstProxyPadClass * klass)
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_event_default); GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_event_default);
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_query_default); GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_query_default);
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_iterate_internal_links_default); GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_iterate_internal_links_default);
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getcaps_default);
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_acceptcaps_default);
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_unlink_default); GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_unlink_default);
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_default); GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_default);
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_list_default); GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_list_default);
@ -458,7 +430,6 @@ gst_proxy_pad_init (GstProxyPad * ppad)
gst_pad_set_iterate_internal_links_function (pad, gst_pad_set_iterate_internal_links_function (pad,
gst_proxy_pad_iterate_internal_links_default); gst_proxy_pad_iterate_internal_links_default);
gst_pad_set_getcaps_function (pad, gst_proxy_pad_getcaps_default);
gst_pad_set_unlink_function (pad, gst_proxy_pad_unlink_default); gst_pad_set_unlink_function (pad, gst_proxy_pad_unlink_default);
} }

View file

@ -68,8 +68,6 @@ GstIterator* gst_proxy_pad_iterate_internal_links_default (GstPad *pad);
GstFlowReturn gst_proxy_pad_chain_default (GstPad *pad, GstBuffer *buffer); GstFlowReturn gst_proxy_pad_chain_default (GstPad *pad, GstBuffer *buffer);
GstFlowReturn gst_proxy_pad_chain_list_default (GstPad *pad, GstBufferList *list); GstFlowReturn gst_proxy_pad_chain_list_default (GstPad *pad, GstBufferList *list);
GstFlowReturn gst_proxy_pad_getrange_default (GstPad *pad, guint64 offset, guint size, GstBuffer **buffer); GstFlowReturn gst_proxy_pad_getrange_default (GstPad *pad, guint64 offset, guint size, GstBuffer **buffer);
GstCaps* gst_proxy_pad_getcaps_default (GstPad *pad, GstCaps * filter);
gboolean gst_proxy_pad_acceptcaps_default (GstPad *pad, GstCaps *caps);
void gst_proxy_pad_unlink_default (GstPad * pad); void gst_proxy_pad_unlink_default (GstPad * pad);
#define GST_TYPE_GHOST_PAD (gst_ghost_pad_get_type ()) #define GST_TYPE_GHOST_PAD (gst_ghost_pad_get_type ())

View file

@ -748,7 +748,7 @@ gst_object_set_parent (GstObject * object, GstObject * parent)
goto had_parent; goto had_parent;
object->parent = parent; object->parent = parent;
g_object_ref_sink (object); gst_object_ref_sink (object);
GST_OBJECT_UNLOCK (object); GST_OBJECT_UNLOCK (object);
/* FIXME, this does not work, the deep notify takes the lock from the parent /* FIXME, this does not work, the deep notify takes the lock from the parent

View file

@ -139,7 +139,6 @@ static void gst_pad_set_property (GObject * object, guint prop_id,
static void gst_pad_get_property (GObject * object, guint prop_id, static void gst_pad_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static GstCaps *gst_pad_get_caps_unlocked (GstPad * pad, GstCaps * filter);
static void gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ); static void gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ);
static gboolean gst_pad_activate_default (GstPad * pad); static gboolean gst_pad_activate_default (GstPad * pad);
static GstFlowReturn gst_pad_chain_list_default (GstPad * pad, static GstFlowReturn gst_pad_chain_list_default (GstPad * pad,
@ -1503,42 +1502,6 @@ gst_pad_set_unlink_function (GstPad * pad, GstPadUnlinkFunction unlink)
GST_DEBUG_FUNCPTR_NAME (unlink)); GST_DEBUG_FUNCPTR_NAME (unlink));
} }
/**
* gst_pad_set_getcaps_function:
* @pad: a #GstPad.
* @getcaps: the #GstPadGetCapsFunction to set.
*
* Sets the given getcaps function for the pad. @getcaps should return the
* allowable caps for a pad in the context of the element's state, its link to
* other elements, and the devices or files it has opened. These caps must be a
* subset of the pad template caps. In the NULL state with no links, @getcaps
* should ideally return the same caps as the pad template. In rare
* circumstances, an object property can affect the caps returned by @getcaps,
* but this is discouraged.
*
* You do not need to call this function if @pad's allowed caps are always the
* same as the pad template caps. This can only be true if the padtemplate
* has fixed simple caps.
*
* For most filters, the caps returned by @getcaps is directly affected by the
* allowed caps on other pads. For demuxers and decoders, the caps returned by
* the srcpad's getcaps function is directly related to the stream data. Again,
* @getcaps should return the most specific caps it reasonably can, since this
* helps with autoplugging.
*
* Note that the return value from @getcaps is owned by the caller, so the
* caller should unref the caps after usage.
*/
void
gst_pad_set_getcaps_function (GstPad * pad, GstPadGetCapsFunction getcaps)
{
g_return_if_fail (GST_IS_PAD (pad));
GST_PAD_GETCAPSFUNC (pad) = getcaps;
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "getcapsfunc set to %s",
GST_DEBUG_FUNCPTR_NAME (getcaps));
}
/** /**
* gst_pad_unlink: * gst_pad_unlink:
* @srcpad: the source #GstPad to unlink. * @srcpad: the source #GstPad to unlink.
@ -1679,8 +1642,12 @@ gst_pad_link_check_compatible_unlocked (GstPad * src, GstPad * sink,
/* Doing the expensive caps checking takes priority over only checking the template caps */ /* Doing the expensive caps checking takes priority over only checking the template caps */
if (flags & GST_PAD_LINK_CHECK_CAPS) { if (flags & GST_PAD_LINK_CHECK_CAPS) {
srccaps = gst_pad_get_caps_unlocked (src, NULL); GST_OBJECT_UNLOCK (src);
sinkcaps = gst_pad_get_caps_unlocked (sink, NULL); srccaps = gst_pad_get_caps (src, NULL);
GST_OBJECT_LOCK (src);
GST_OBJECT_UNLOCK (sink);
sinkcaps = gst_pad_get_caps (sink, NULL);
GST_OBJECT_LOCK (sink);
} else { } else {
/* If one of the two pads doesn't have a template, consider the intersection /* If one of the two pads doesn't have a template, consider the intersection
* as valid.*/ * as valid.*/
@ -2087,140 +2054,6 @@ gst_pad_get_pad_template (GstPad * pad)
return (templ ? gst_object_ref (templ) : NULL); return (templ ? gst_object_ref (templ) : NULL);
} }
static GstCaps *
caps_with_getcaps (GstPad * pad, GstCaps * filter)
{
GstCaps *result;
if (GST_PAD_GETCAPSFUNC (pad) == NULL)
return NULL;
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"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, filter);
GST_OBJECT_LOCK (pad);
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_IN_GETCAPS);
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)) {
const GstCaps *templ_caps =
GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad));
if (!gst_caps_is_subset (result, templ_caps)) {
GstCaps *temp;
GST_CAT_ERROR_OBJECT (GST_CAT_CAPS, pad,
"pad returned caps %" GST_PTR_FORMAT
" which are not a real subset of its template caps %"
GST_PTR_FORMAT, result, templ_caps);
g_warning
("pad %s:%s returned caps which are not a real "
"subset of its template caps", GST_DEBUG_PAD_NAME (pad));
temp = gst_caps_intersect (templ_caps, result);
gst_caps_unref (result);
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
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 ((templ = GST_PAD_PAD_TEMPLATE (pad))) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "trying pad template caps");
if ((result = GST_PAD_TEMPLATE_CAPS (templ)))
goto filter_done;
}
if (!fixed_caps) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"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, 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;
}
/** /**
* gst_pad_has_current_caps: * gst_pad_has_current_caps:
* @pad: a #GstPad to check * @pad: a #GstPad to check
@ -2282,8 +2115,8 @@ gst_pad_get_current_caps (GstPad * pad)
* Note that this method doesn't necessarily return the caps set by * Note that this method doesn't necessarily return the caps set by
* gst_pad_set_caps() - use gst_pad_get_current_caps() for that instead. * gst_pad_set_caps() - use gst_pad_get_current_caps() for that instead.
* gst_pad_get_caps returns all possible caps a pad can operate with, using * gst_pad_get_caps returns all possible caps a pad can operate with, using
* the pad's get_caps function; * the pad's CAPS query function, If the query fails, this function will return
* this returns the pad template caps if not explicitly set. * @filter, if not #NULL, otherwise ANY.
* *
* When called on sinkpads @filter contains the caps that * When called on sinkpads @filter contains the caps that
* upstream could produce in the order preferred by upstream. When * upstream could produce in the order preferred by upstream. When
@ -2300,17 +2133,24 @@ GstCaps *
gst_pad_get_caps (GstPad * pad, GstCaps * filter) gst_pad_get_caps (GstPad * pad, GstCaps * filter)
{ {
GstCaps *result = NULL; GstCaps *result = NULL;
GstQuery *query;
g_return_val_if_fail (GST_IS_PAD (pad), NULL); g_return_val_if_fail (GST_IS_PAD (pad), NULL);
g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), 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"); GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get pad caps");
result = gst_pad_get_caps_unlocked (pad, filter); query = gst_query_new_caps (filter);
if (gst_pad_query (pad, query)) {
GST_OBJECT_UNLOCK (pad); gst_query_parse_caps_result (query, &result);
gst_caps_ref (result);
GST_DEBUG_OBJECT (pad, "query returned %" GST_PTR_FORMAT, result);
} else if (filter) {
result = gst_caps_ref (filter);
} else {
result = gst_caps_new_any ();
}
gst_query_unref (query);
return result; return result;
} }
@ -2336,34 +2176,25 @@ gst_pad_get_caps (GstPad * pad, GstCaps * filter)
GstCaps * GstCaps *
gst_pad_peer_get_caps (GstPad * pad, GstCaps * filter) gst_pad_peer_get_caps (GstPad * pad, GstCaps * filter)
{ {
GstPad *peerpad;
GstCaps *result = NULL; GstCaps *result = NULL;
GstQuery *query;
g_return_val_if_fail (GST_IS_PAD (pad), NULL); g_return_val_if_fail (GST_IS_PAD (pad), NULL);
g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), NULL); g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), NULL);
GST_OBJECT_LOCK (pad); query = gst_query_new_caps (filter);
if (gst_pad_peer_query (pad, query)) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get peer caps"); gst_query_parse_caps_result (query, &result);
gst_caps_ref (result);
peerpad = GST_PAD_PEER (pad); GST_DEBUG_OBJECT (pad, "peer query returned %d", result);
if (G_UNLIKELY (peerpad == NULL)) } else if (filter) {
goto no_peer; result = gst_caps_ref (filter);
} else {
gst_object_ref (peerpad); result = gst_caps_new_any ();
GST_OBJECT_UNLOCK (pad); }
gst_query_unref (query);
result = gst_pad_get_caps (peerpad, filter);
gst_object_unref (peerpad);
return result; return result;
no_peer:
{
GST_OBJECT_UNLOCK (pad);
return NULL;
}
} }
/** /**
@ -2378,7 +2209,7 @@ no_peer:
gboolean gboolean
gst_pad_accept_caps (GstPad * pad, GstCaps * caps) gst_pad_accept_caps (GstPad * pad, GstCaps * caps)
{ {
gboolean res; gboolean res = TRUE;
GstQuery *query; GstQuery *query;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
@ -2387,8 +2218,7 @@ gst_pad_accept_caps (GstPad * pad, GstCaps * caps)
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "accept caps of %p", caps); GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "accept caps of %p", caps);
query = gst_query_new_accept_caps (caps); query = gst_query_new_accept_caps (caps);
res = gst_pad_query (pad, query); if (gst_pad_query (pad, query)) {
if (res) {
GST_DEBUG_OBJECT (pad, "query returned %d", res); GST_DEBUG_OBJECT (pad, "query returned %d", res);
gst_query_parse_accept_caps_result (query, &res); gst_query_parse_accept_caps_result (query, &res);
} }
@ -2403,24 +2233,27 @@ gst_pad_accept_caps (GstPad * pad, GstCaps * caps)
* @caps: a #GstCaps to check on the pad * @caps: a #GstCaps to check on the pad
* *
* Check if the peer of @pad accepts @caps. If @pad has no peer, this function * Check if the peer of @pad accepts @caps. If @pad has no peer, this function
* returns FALSE. * returns TRUE.
* *
* Returns: TRUE if the peer of @pad can accept the caps or @pad has no peer. * Returns: TRUE if the peer of @pad can accept the caps or @pad has no peer.
*/ */
gboolean gboolean
gst_pad_peer_accept_caps (GstPad * pad, GstCaps * caps) gst_pad_peer_accept_caps (GstPad * pad, GstCaps * caps)
{ {
gboolean result; gboolean res = TRUE;
GstQuery *query; GstQuery *query;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
query = gst_query_new_accept_caps (caps); query = gst_query_new_accept_caps (caps);
result = gst_pad_peer_query (pad, query); if (gst_pad_peer_query (pad, query)) {
GST_DEBUG_OBJECT (pad, "query returned %d", res);
gst_query_parse_accept_caps_result (query, &res);
}
gst_query_unref (query); gst_query_unref (query);
return result; return res;
} }
/** /**
@ -2886,8 +2719,6 @@ event_forward_func (GstPad * pad, EventData * data)
* The EOS event will pause the task associated with @pad before it is forwarded * The EOS event will pause the task associated with @pad before it is forwarded
* to all internally linked pads, * to all internally linked pads,
* *
* The CAPS event will never be forwarded.
*
* The the event is sent to all pads internally linked to @pad. This function * The the event is sent to all pads internally linked to @pad. This function
* takes ownership of @event. * takes ownership of @event.
* *
@ -2896,8 +2727,7 @@ event_forward_func (GstPad * pad, EventData * data)
gboolean gboolean
gst_pad_event_default (GstPad * pad, GstEvent * event) gst_pad_event_default (GstPad * pad, GstEvent * event)
{ {
gboolean result; gboolean result, forward = TRUE;
EventData data;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (event != NULL, FALSE); g_return_val_if_fail (event != NULL, FALSE);
@ -2911,22 +2741,30 @@ gst_pad_event_default (GstPad * pad, GstEvent * event)
gst_pad_pause_task (pad); gst_pad_pause_task (pad);
break; break;
} }
case GST_EVENT_CAPS:
forward = GST_PAD_IS_PROXY_CAPS (pad);
result = TRUE;
break;
default: default:
break; break;
} }
data.event = event; if (forward) {
data.dispatched = FALSE; EventData data;
data.result = FALSE;
gst_pad_forward (pad, (GstPadForwardFunction) event_forward_func, &data); data.event = event;
data.dispatched = FALSE;
data.result = FALSE;
/* for sinkpads without a parent element or without internal links, nothing gst_pad_forward (pad, (GstPadForwardFunction) event_forward_func, &data);
* will be dispatched but we still want to return TRUE. */
if (data.dispatched) /* for sinkpads without a parent element or without internal links, nothing
result = data.result; * will be dispatched but we still want to return TRUE. */
else if (data.dispatched)
result = TRUE; result = data.result;
else
result = TRUE;
}
gst_event_unref (event); gst_event_unref (event);
@ -2936,17 +2774,25 @@ gst_pad_event_default (GstPad * pad, GstEvent * event)
/* Default accept caps implementation just checks against /* Default accept caps implementation just checks against
* the allowed caps for the pad */ * the allowed caps for the pad */
static gboolean static gboolean
gst_pad_query_accept_caps (GstPad * pad, GstQuery * query) gst_pad_query_accept_caps_default (GstPad * pad, GstQuery * query)
{ {
/* get the caps and see if it intersects to something not empty */ /* get the caps and see if it intersects to something not empty */
GstCaps *caps, *allowed; GstCaps *caps, *allowed;
gboolean result; gboolean result;
gst_query_parse_accept_caps (query, &caps);
GST_DEBUG_OBJECT (pad, "caps %" GST_PTR_FORMAT, caps); GST_DEBUG_OBJECT (pad, "caps %" GST_PTR_FORMAT, caps);
/* first forward the query to internally linked pads when we are dealing with
* a PROXY CAPS */
if (GST_PAD_IS_PROXY_CAPS (pad)) {
if ((result = gst_pad_proxy_query_accept_caps (pad, query))) {
goto done;
}
}
allowed = gst_pad_get_caps (pad, NULL); allowed = gst_pad_get_caps (pad, NULL);
gst_query_parse_accept_caps (query, &caps);
if (allowed) { if (allowed) {
GST_DEBUG_OBJECT (pad, "allowed caps %" GST_PTR_FORMAT, allowed); GST_DEBUG_OBJECT (pad, "allowed caps %" GST_PTR_FORMAT, allowed);
result = gst_caps_is_subset (caps, allowed); result = gst_caps_is_subset (caps, allowed);
@ -2957,6 +2803,84 @@ gst_pad_query_accept_caps (GstPad * pad, GstQuery * query)
} }
gst_query_set_accept_caps_result (query, result); gst_query_set_accept_caps_result (query, result);
done:
return TRUE;
}
/* Default caps implementation */
static gboolean
gst_pad_query_caps_default (GstPad * pad, GstQuery * query)
{
GstCaps *result = NULL, *filter;
GstPadTemplate *templ;
gboolean fixed_caps;
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get pad caps");
gst_query_parse_caps (query, &filter);
/* first try to proxy if we must */
if (GST_PAD_IS_PROXY_CAPS (pad)) {
if ((gst_pad_proxy_query_caps (pad, query))) {
gst_query_parse_caps_result (query, &result);
goto filter_done;
}
}
/* no proxy or it failed, do default handling */
fixed_caps = GST_PAD_IS_FIXED_CAPS (pad);
GST_OBJECT_LOCK (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_unlock;
}
if ((templ = GST_PAD_PAD_TEMPLATE (pad))) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "trying pad template caps");
if ((result = GST_PAD_TEMPLATE_CAPS (templ)))
goto filter_done_unlock;
}
if (!fixed_caps) {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"non-fixed pad caps: trying pad caps");
/* non fixed caps, try the negotiated caps */
if ((result = get_pad_caps (pad)))
goto filter_done_unlock;
}
GST_OBJECT_UNLOCK (pad);
/* 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_unlock:
GST_OBJECT_UNLOCK (pad);
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, result);
} else {
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
"using caps %p %" GST_PTR_FORMAT, result, result);
result = gst_caps_ref (result);
}
done:
gst_query_set_caps_result (query, result);
gst_caps_unref (result);
return TRUE; return TRUE;
} }
@ -2983,7 +2907,11 @@ gst_pad_query_default (GstPad * pad, GstQuery * query)
forward = FALSE; forward = FALSE;
break; break;
case GST_QUERY_ACCEPT_CAPS: case GST_QUERY_ACCEPT_CAPS:
ret = gst_pad_query_accept_caps (pad, query); ret = gst_pad_query_accept_caps_default (pad, query);
forward = FALSE;
break;
case GST_QUERY_CAPS:
ret = gst_pad_query_caps_default (pad, query);
forward = FALSE; forward = FALSE;
break; break;
case GST_QUERY_POSITION: case GST_QUERY_POSITION:

View file

@ -398,26 +398,6 @@ typedef GstPadLinkReturn (*GstPadLinkFunction) (GstPad *pad, GstPad *peer);
typedef void (*GstPadUnlinkFunction) (GstPad *pad); typedef void (*GstPadUnlinkFunction) (GstPad *pad);
/* caps nego */
/**
* 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
* be overridden by elements.
*
* Returns: a newly allocated copy #GstCaps of the pad.
*/
typedef GstCaps* (*GstPadGetCapsFunction) (GstPad *pad, GstCaps *filter);
/* misc */ /* misc */
/** /**
* GstPadForwardFunction: * GstPadForwardFunction:
@ -566,7 +546,6 @@ typedef GstFlowReturn (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEve
* GstPadFlags: * GstPadFlags:
* @GST_PAD_BLOCKED: is dataflow on a pad blocked * @GST_PAD_BLOCKED: is dataflow on a pad blocked
* @GST_PAD_FLUSHING: is pad refusing buffers * @GST_PAD_FLUSHING: is pad refusing buffers
* @GST_PAD_IN_GETCAPS: GstPadGetCapsFunction() is running now
* @GST_PAD_BLOCKING: is pad currently blocking on a buffer or event * @GST_PAD_BLOCKING: is pad currently blocking on a buffer or event
* @GST_PAD_NEED_RECONFIGURE: the pad should be reconfigured/renegotiated. * @GST_PAD_NEED_RECONFIGURE: the pad should be reconfigured/renegotiated.
* The flag has to be unset manually after * The flag has to be unset manually after
@ -574,8 +553,11 @@ typedef GstFlowReturn (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEve
* Since: 0.10.34. * Since: 0.10.34.
* @GST_PAD_NEED_EVENTS: the pad has pending events * @GST_PAD_NEED_EVENTS: the pad has pending events
* @GST_PAD_FIXED_CAPS: the pad is using fixed caps this means that once the * @GST_PAD_FIXED_CAPS: the pad is using fixed caps this means that once the
* caps are set on the pad, the getcaps function only * caps are set on the pad, the caps query function only
* returns those caps. * returns those caps.
* @GST_PAD_PROXY_CAPS: the default event and query handler will forward
* all events and queries to the internally linked pads
* instead of discarding them.
* @GST_PAD_FLAG_LAST: offset to define more flags * @GST_PAD_FLAG_LAST: offset to define more flags
* *
* Pad state flags * Pad state flags
@ -583,11 +565,11 @@ typedef GstFlowReturn (*GstPadStickyEventsForeachFunction) (GstPad *pad, GstEve
typedef enum { typedef enum {
GST_PAD_BLOCKED = (GST_OBJECT_FLAG_LAST << 0), GST_PAD_BLOCKED = (GST_OBJECT_FLAG_LAST << 0),
GST_PAD_FLUSHING = (GST_OBJECT_FLAG_LAST << 1), GST_PAD_FLUSHING = (GST_OBJECT_FLAG_LAST << 1),
GST_PAD_IN_GETCAPS = (GST_OBJECT_FLAG_LAST << 2), GST_PAD_BLOCKING = (GST_OBJECT_FLAG_LAST << 2),
GST_PAD_BLOCKING = (GST_OBJECT_FLAG_LAST << 4), GST_PAD_NEED_RECONFIGURE = (GST_OBJECT_FLAG_LAST << 3),
GST_PAD_NEED_RECONFIGURE = (GST_OBJECT_FLAG_LAST << 5), GST_PAD_NEED_EVENTS = (GST_OBJECT_FLAG_LAST << 4),
GST_PAD_NEED_EVENTS = (GST_OBJECT_FLAG_LAST << 6), GST_PAD_FIXED_CAPS = (GST_OBJECT_FLAG_LAST << 5),
GST_PAD_FIXED_CAPS = (GST_OBJECT_FLAG_LAST << 7), GST_PAD_PROXY_CAPS = (GST_OBJECT_FLAG_LAST << 6),
/* padding */ /* padding */
GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16) GST_PAD_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16)
} GstPadFlags; } GstPadFlags;
@ -603,7 +585,6 @@ typedef enum {
* @task: task for this pad if the pad is actively driving dataflow. * @task: task for this pad if the pad is actively driving dataflow.
* @block_cond: conditional to signal pad block * @block_cond: conditional to signal pad block
* @probes: installed probes * @probes: installed probes
* @getcapsfunc: function to get caps of the pad
* @mode: current activation mode of the pad * @mode: current activation mode of the pad
* @activatefunc: pad activation function * @activatefunc: pad activation function
* @activatepushfunc: function to activate/deactivate pad in push mode * @activatepushfunc: function to activate/deactivate pad in push mode
@ -641,9 +622,6 @@ struct _GstPad {
GCond *block_cond; GCond *block_cond;
GHookList probes; GHookList probes;
/* the pad capabilities */
GstPadGetCapsFunction getcapsfunc;
GstPadActivateMode mode; GstPadActivateMode mode;
GstPadActivateFunction activatefunc; GstPadActivateFunction activatefunc;
GstPadActivateModeFunction activatepushfunc; GstPadActivateModeFunction activatepushfunc;
@ -715,8 +693,6 @@ struct _GstPadClass {
#define GST_PAD_LINKFUNC(pad) (GST_PAD_CAST(pad)->linkfunc) #define GST_PAD_LINKFUNC(pad) (GST_PAD_CAST(pad)->linkfunc)
#define GST_PAD_UNLINKFUNC(pad) (GST_PAD_CAST(pad)->unlinkfunc) #define GST_PAD_UNLINKFUNC(pad) (GST_PAD_CAST(pad)->unlinkfunc)
#define GST_PAD_GETCAPSFUNC(pad) (GST_PAD_CAST(pad)->getcapsfunc)
#define GST_PAD_IS_SRC(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SRC) #define GST_PAD_IS_SRC(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SRC)
#define GST_PAD_IS_SINK(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SINK) #define GST_PAD_IS_SINK(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SINK)
@ -731,6 +707,7 @@ struct _GstPadClass {
#define GST_PAD_NEEDS_RECONFIGURE(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_NEED_RECONFIGURE)) #define GST_PAD_NEEDS_RECONFIGURE(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_NEED_RECONFIGURE))
#define GST_PAD_NEEDS_EVENTS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_NEED_EVENTS)) #define GST_PAD_NEEDS_EVENTS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_NEED_EVENTS))
#define GST_PAD_IS_FIXED_CAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FIXED_CAPS)) #define GST_PAD_IS_FIXED_CAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FIXED_CAPS))
#define GST_PAD_IS_PROXY_CAPS(pad) (GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_PROXY_CAPS))
#define GST_PAD_SET_FLUSHING(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLUSHING)) #define GST_PAD_SET_FLUSHING(pad) (GST_OBJECT_FLAG_SET (pad, GST_PAD_FLUSHING))
#define GST_PAD_UNSET_FLUSHING(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLUSHING)) #define GST_PAD_UNSET_FLUSHING(pad) (GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLUSHING))
@ -849,9 +826,6 @@ gboolean gst_pad_is_linked (GstPad *pad);
GstPad* gst_pad_get_peer (GstPad *pad); GstPad* gst_pad_get_peer (GstPad *pad);
/* capsnego functions */
void gst_pad_set_getcaps_function (GstPad *pad, GstPadGetCapsFunction getcaps);
GstCaps* gst_pad_get_pad_template_caps (GstPad *pad); GstCaps* gst_pad_get_pad_template_caps (GstPad *pad);
/* capsnego function for linked/unlinked pads */ /* capsnego function for linked/unlinked pads */

View file

@ -55,7 +55,7 @@ static const gchar *_quark_strings[] = {
"GstQueryAllocation", "need-pool", "meta", "pool", "GstEventCaps", "GstQueryAllocation", "need-pool", "meta", "pool", "GstEventCaps",
"GstEventReconfigure", "segment", "GstQueryScheduling", "pull-mode", "GstEventReconfigure", "segment", "GstQueryScheduling", "pull-mode",
"random-access", "sequential", "allocator", "GstEventFlushStop", "options", "random-access", "sequential", "allocator", "GstEventFlushStop", "options",
"GstQueryAcceptCaps", "result", "GstQueryCaps" "GstQueryAcceptCaps", "result", "GstQueryCaps", "filter"
}; };
GQuark _priv_gst_quark_table[GST_QUARK_MAX]; GQuark _priv_gst_quark_table[GST_QUARK_MAX];

View file

@ -158,8 +158,9 @@ typedef enum _GstQuarkId
GST_QUARK_QUERY_ACCEPT_CAPS = 129, GST_QUARK_QUERY_ACCEPT_CAPS = 129,
GST_QUARK_RESULT = 130, GST_QUARK_RESULT = 130,
GST_QUARK_QUERY_CAPS = 131, GST_QUARK_QUERY_CAPS = 131,
GST_QUARK_FILTER = 132,
GST_QUARK_MAX = 132 GST_QUARK_MAX = 133
} GstQuarkId; } GstQuarkId;
extern GQuark _priv_gst_quark_table[GST_QUARK_MAX]; extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];

View file

@ -2076,20 +2076,35 @@ gst_query_parse_accept_caps_result (GstQuery * query, gboolean * result)
/** /**
* gst_query_new_caps * gst_query_new_caps
* @filer: a filter
* *
* Constructs a new query object for querying the caps. * Constructs a new query object for querying the caps.
* *
* The CAPS query should return the* allowable caps for a pad in the context
* of the element's state, its link to other elements, and the devices or files
* it has opened. These caps must be a subset of the pad template caps. In the
* NULL state with no links, the CAPS query should ideally return the same caps
* as the pad template. In rare circumstances, an object property can affect
* the caps returned by the CAPS query, but this is discouraged.
*
* For most filters, the caps returned by CAPS query is directly affected by the
* allowed caps on other pads. For demuxers and decoders, the caps returned by
* the srcpad's getcaps function is directly related to the stream data. Again,
* the CAPS query should return the most specific caps it reasonably can, since this
* helps with autoplugging.
*
* Free-function: gst_query_unref * Free-function: gst_query_unref
* *
* Returns: (transfer full): a new #GstQuery * Returns: (transfer full): a new #GstQuery
*/ */
GstQuery * GstQuery *
gst_query_new_caps (void) gst_query_new_caps (GstCaps * filter)
{ {
GstQuery *query; GstQuery *query;
GstStructure *structure; GstStructure *structure;
structure = gst_structure_new_id (GST_QUARK (QUERY_CAPS), structure = gst_structure_new_id (GST_QUARK (QUERY_CAPS),
GST_QUARK (FILTER), GST_TYPE_CAPS, filter,
GST_QUARK (CAPS), GST_TYPE_CAPS, NULL, NULL); GST_QUARK (CAPS), GST_TYPE_CAPS, NULL, NULL);
query = gst_query_new (GST_QUERY_CAPS, structure); query = gst_query_new (GST_QUERY_CAPS, structure);
@ -2097,14 +2112,34 @@ gst_query_new_caps (void)
} }
/** /**
* gst_query_set_caps: * gst_query_parse_caps:
* @query: The query to parse
* @filter: (out): A pointer to the caps filter
*
* Get the filter from the caps @query. The caps remains valid as long as
* @query remains valid.
*/
void
gst_query_parse_caps (GstQuery * query, GstCaps ** filter)
{
GstStructure *structure;
g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS);
structure = GST_QUERY_STRUCTURE (query);
*filter = g_value_get_boxed (gst_structure_id_get_value (structure,
GST_QUARK (FILTER)));
}
/**
* gst_query_set_caps_result:
* @query: The query to use * @query: The query to use
* @caps: (in): A pointer to the caps * @caps: (in): A pointer to the caps
* *
* Set the @caps in @query. * Set the @caps result in @query.
*/ */
void void
gst_query_set_caps (GstQuery * query, GstCaps * caps) gst_query_set_caps_result (GstQuery * query, GstCaps * caps)
{ {
GstStructure *structure; GstStructure *structure;
@ -2116,15 +2151,15 @@ gst_query_set_caps (GstQuery * query, GstCaps * caps)
} }
/** /**
* gst_query_parse_caps: * gst_query_parse_caps_result:
* @query: The query to parse * @query: The query to parse
* @caps: (out): A pointer to the caps * @caps: (out): A pointer to the caps
* *
* Get the caps from @query. The caps remains valid as long as @query remains * Get the caps result from @query. The caps remains valid as long as
* valid. * @query remains valid.
*/ */
void void
gst_query_parse_caps (GstQuery * query, GstCaps ** caps) gst_query_parse_caps_result (GstQuery * query, GstCaps ** caps)
{ {
GstStructure *structure; GstStructure *structure;
@ -2134,3 +2169,15 @@ gst_query_parse_caps (GstQuery * query, GstCaps ** caps)
*caps = g_value_get_boxed (gst_structure_id_get_value (structure, *caps = g_value_get_boxed (gst_structure_id_get_value (structure,
GST_QUARK (CAPS))); GST_QUARK (CAPS)));
} }
void
gst_query_intersect_caps_result (GstQuery * query, GstCaps * filter,
GstCapsIntersectMode mode)
{
GstCaps *res, *caps;
gst_query_parse_caps_result (query, &caps);
res = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
gst_query_set_caps_result (query, res);
gst_caps_unref (res);
}

View file

@ -389,9 +389,14 @@ void gst_query_set_accept_caps_result (GstQuery *query, gboolean re
void gst_query_parse_accept_caps_result (GstQuery *query, gboolean *result); void gst_query_parse_accept_caps_result (GstQuery *query, gboolean *result);
/* caps query */ /* caps query */
GstQuery * gst_query_new_caps (void); GstQuery * gst_query_new_caps (GstCaps *filter);
void gst_query_set_caps (GstQuery *query, GstCaps *caps); void gst_query_parse_caps (GstQuery *query, GstCaps **filter);
void gst_query_parse_caps (GstQuery *query, GstCaps **caps);
void gst_query_set_caps_result (GstQuery *query, GstCaps *caps);
void gst_query_parse_caps_result (GstQuery *query, GstCaps **caps);
void gst_query_intersect_caps_result (GstQuery *query, GstCaps *filter,
GstCapsIntersectMode mode);
G_END_DECLS G_END_DECLS

View file

@ -2697,54 +2697,161 @@ gst_buffer_join (GstBuffer * buf1, GstBuffer * buf2)
} }
static gboolean static gboolean
getcaps_fold_func (const GValue * vpad, GValue * ret, GstCaps * filter) query_accept_caps_fold_func (const GValue * vpad, GValue * ret,
GstQuery * query)
{
GstPad *pad = g_value_get_object (vpad);
gboolean result = TRUE;
if (G_LIKELY (gst_pad_peer_query (pad, query))) {
gst_query_parse_accept_caps_result (query, &result);
result &= g_value_get_boolean (ret);
g_value_set_boolean (ret, result);
}
return result;
}
/**
* gst_pad_proxy_query_accept_caps:
* @pad: a #GstPad to proxy.
* @query: an ACCEPT_CAPS #GstQuery.
*
* Calls gst_pad_accept_caps() for every pad with oposite direction belonging
* to the same element as @pad, and returns the intersection of the results.
*
* This function is useful as a default accept caps query function for an element
* that can handle any stream format, but requires caps that are acceptable for
* all oposite pads.
*
* Returns: TRUE if @query could be executed
*/
gboolean
gst_pad_proxy_query_accept_caps (GstPad * pad, GstQuery * query)
{
GstElement *element;
GstIterator *iter;
GstIteratorResult res;
GValue ret = { 0, };
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS, FALSE);
GST_CAT_DEBUG (GST_CAT_PADS, "proxying accept caps query for %s:%s",
GST_DEBUG_PAD_NAME (pad));
element = gst_pad_get_parent_element (pad);
if (element == NULL)
goto no_parent;
/* value to hold the return, by default it holds TRUE */
g_value_init (&ret, G_TYPE_BOOLEAN);
g_value_set_boolean (&ret, TRUE);
/* only iterate the pads in the oposite direction */
if (GST_PAD_IS_SRC (pad))
iter = gst_element_iterate_sink_pads (element);
else
iter = gst_element_iterate_src_pads (element);
while (1) {
res =
gst_iterator_fold (iter,
(GstIteratorFoldFunction) query_accept_caps_fold_func, &ret, query);
switch (res) {
case GST_ITERATOR_RESYNC:
/* need to reset the result again to TRUE */
g_value_set_boolean (&ret, TRUE);
gst_iterator_resync (iter);
break;
case GST_ITERATOR_DONE:
/* all pads iterated, return collected value */
goto done;
case GST_ITERATOR_OK:
/* premature exit (happens if caps intersection is empty) */
goto done;
default:
/* iterator returned _ERROR, mark an error and exit */
goto error;
}
}
done:
gst_iterator_free (iter);
gst_object_unref (element);
gst_query_set_accept_caps_result (query, g_value_get_boolean (&ret));
g_value_unset (&ret);
return TRUE;
/* ERRORS */
no_parent:
{
GST_DEBUG_OBJECT (pad, "no parent");
return FALSE;
}
error:
{
g_warning ("Pad list returned error on element %s",
GST_ELEMENT_NAME (element));
gst_iterator_free (iter);
gst_object_unref (element);
return FALSE;
}
}
static gboolean
query_caps_fold_func (const GValue * vpad, GValue * ret, GstQuery * query)
{ {
GstPad *pad = g_value_get_object (vpad); GstPad *pad = g_value_get_object (vpad);
gboolean empty = FALSE; gboolean empty = FALSE;
GstCaps *peercaps, *existing;
existing = g_value_get_pointer (ret); if (G_LIKELY (gst_pad_peer_query (pad, query))) {
peercaps = gst_pad_peer_get_caps (pad, filter); GstCaps *existing, *peercaps, *intersection;
if (G_LIKELY (peercaps)) {
GstCaps *intersection = gst_caps_intersect (existing, peercaps);
existing = g_value_get_pointer (ret);
gst_query_parse_caps_result (query, &peercaps);
GST_DEBUG_OBJECT (pad, "intersect with result %" GST_PTR_FORMAT, peercaps);
intersection = gst_caps_intersect (existing, peercaps);
GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, intersection);
empty = gst_caps_is_empty (intersection); empty = gst_caps_is_empty (intersection);
g_value_set_pointer (ret, intersection); g_value_set_pointer (ret, intersection);
gst_caps_unref (existing); gst_caps_unref (existing);
gst_caps_unref (peercaps);
} }
return !empty; return !empty;
} }
/** /**
* gst_pad_proxy_getcaps: * gst_pad_proxy_query_caps:
* @pad: a #GstPad to proxy. * @pad: a #GstPad to proxy.
* @filter: a #GstCaps filter. * @query: a CAPS #GstQuery.
* *
* Calls gst_pad_get_allowed_caps() for every other pad belonging to the * Calls gst_pad_get_caps() for every pad with oposite direction belonging
* same element as @pad, and returns the intersection of the results. * to the same element as @pad, and returns the intersection of the results.
* *
* This function is useful as a default getcaps function for an element * This function is useful as a default caps query function for an element
* that can handle any stream format, but requires all its pads to have * that can handle any stream format, but requires all its pads to have
* the same caps. Two such elements are tee and adder. * the same caps. Two such elements are tee and adder.
* *
* Free-function: gst_caps_unref * Returns: TRUE if @query could be executed
*
* Returns: (transfer full): the intersection of the other pads' allowed caps.
*/ */
GstCaps * gboolean
gst_pad_proxy_getcaps (GstPad * pad, GstCaps * filter) gst_pad_proxy_query_caps (GstPad * pad, GstQuery * query)
{ {
gboolean result = TRUE;
GstElement *element; GstElement *element;
GstCaps *caps, *intersected; GstCaps *caps, *intersected;
GstIterator *iter; GstIterator *iter;
GstIteratorResult res; GstIteratorResult res;
GValue ret = { 0, }; GValue ret = { 0, };
g_return_val_if_fail (GST_IS_PAD (pad), NULL); g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CAPS, FALSE);
GST_CAT_DEBUG (GST_CAT_PADS, "proxying getcaps for %s:%s", GST_CAT_DEBUG (GST_CAT_PADS, "proxying caps query for %s:%s",
GST_DEBUG_PAD_NAME (pad)); GST_DEBUG_PAD_NAME (pad));
element = gst_pad_get_parent_element (pad); element = gst_pad_get_parent_element (pad);
@ -2764,8 +2871,8 @@ gst_pad_proxy_getcaps (GstPad * pad, GstCaps * filter)
while (1) { while (1) {
res = res =
gst_iterator_fold (iter, (GstIteratorFoldFunction) getcaps_fold_func, gst_iterator_fold (iter, (GstIteratorFoldFunction) query_caps_fold_func,
&ret, filter); &ret, query);
switch (res) { switch (res) {
case GST_ITERATOR_RESYNC: case GST_ITERATOR_RESYNC:
/* unref any value stored */ /* unref any value stored */
@ -2805,13 +2912,16 @@ done:
intersected = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); intersected = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
} }
return intersected; gst_query_set_caps_result (query, intersected);
gst_caps_unref (intersected);
return result;
/* ERRORS */ /* ERRORS */
no_parent: no_parent:
{ {
GST_DEBUG_OBJECT (pad, "no parent"); GST_DEBUG_OBJECT (pad, "no parent");
return gst_caps_copy (gst_pad_get_pad_template_caps (pad)); return FALSE;
} }
error: error:
{ {
@ -2819,7 +2929,7 @@ error:
GST_ELEMENT_NAME (element)); GST_ELEMENT_NAME (element));
gst_iterator_free (iter); gst_iterator_free (iter);
gst_object_unref (element); gst_object_unref (element);
return gst_caps_copy (gst_pad_get_pad_template_caps (pad)); return FALSE;
} }
} }
@ -2843,11 +2953,8 @@ gst_pad_query_position (GstPad * pad, GstFormat format, gint64 * cur)
g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE); g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
query = gst_query_new_position (format); query = gst_query_new_position (format);
ret = gst_pad_query (pad, query); if ((ret = gst_pad_query (pad, query)))
if (ret)
gst_query_parse_position (query, NULL, cur); gst_query_parse_position (query, NULL, cur);
gst_query_unref (query); gst_query_unref (query);
return ret; return ret;
@ -2868,18 +2975,17 @@ gst_pad_query_position (GstPad * pad, GstFormat format, gint64 * cur)
gboolean gboolean
gst_pad_query_peer_position (GstPad * pad, GstFormat format, gint64 * cur) gst_pad_query_peer_position (GstPad * pad, GstFormat format, gint64 * cur)
{ {
GstQuery *query;
gboolean ret = FALSE; gboolean ret = FALSE;
GstPad *peer;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE); g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE);
g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE); g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
peer = gst_pad_get_peer (pad); query = gst_query_new_position (format);
if (peer) { if ((ret = gst_pad_peer_query (pad, query)))
ret = gst_pad_query_position (peer, format, cur); gst_query_parse_position (query, NULL, cur);
gst_object_unref (peer); gst_query_unref (query);
}
return ret; return ret;
} }
@ -2905,11 +3011,8 @@ gst_pad_query_duration (GstPad * pad, GstFormat format, gint64 * duration)
g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE); g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
query = gst_query_new_duration (format); query = gst_query_new_duration (format);
ret = gst_pad_query (pad, query); if ((ret = gst_pad_query (pad, query)))
if (ret)
gst_query_parse_duration (query, NULL, duration); gst_query_parse_duration (query, NULL, duration);
gst_query_unref (query); gst_query_unref (query);
return ret; return ret;
@ -2930,18 +3033,17 @@ gst_pad_query_duration (GstPad * pad, GstFormat format, gint64 * duration)
gboolean gboolean
gst_pad_query_peer_duration (GstPad * pad, GstFormat format, gint64 * duration) gst_pad_query_peer_duration (GstPad * pad, GstFormat format, gint64 * duration)
{ {
GstQuery *query;
gboolean ret = FALSE; gboolean ret = FALSE;
GstPad *peer;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE); g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE);
g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE); g_return_val_if_fail (format != GST_FORMAT_UNDEFINED, FALSE);
peer = gst_pad_get_peer (pad); query = gst_query_new_duration (format);
if (peer) { if ((ret = gst_pad_peer_query (pad, query)))
ret = gst_pad_query_duration (peer, format, duration); gst_query_parse_duration (query, NULL, duration);
gst_object_unref (peer); gst_query_unref (query);
}
return ret; return ret;
} }
@ -2975,11 +3077,8 @@ gst_pad_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val,
} }
query = gst_query_new_convert (src_format, src_val, dest_format); query = gst_query_new_convert (src_format, src_val, dest_format);
ret = gst_pad_query (pad, query); if ((ret = gst_pad_query (pad, query)))
if (ret)
gst_query_parse_convert (query, NULL, NULL, NULL, dest_val); gst_query_parse_convert (query, NULL, NULL, NULL, dest_val);
gst_query_unref (query); gst_query_unref (query);
return ret; return ret;
@ -3003,20 +3102,18 @@ gboolean
gst_pad_query_peer_convert (GstPad * pad, GstFormat src_format, gint64 src_val, gst_pad_query_peer_convert (GstPad * pad, GstFormat src_format, gint64 src_val,
GstFormat dest_format, gint64 * dest_val) GstFormat dest_format, gint64 * dest_val)
{ {
GstQuery *query;
gboolean ret = FALSE; gboolean ret = FALSE;
GstPad *peer;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE); g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE);
g_return_val_if_fail (dest_format != GST_FORMAT_UNDEFINED, FALSE); g_return_val_if_fail (dest_format != GST_FORMAT_UNDEFINED, FALSE);
g_return_val_if_fail (dest_val != NULL, FALSE); g_return_val_if_fail (dest_val != NULL, FALSE);
peer = gst_pad_get_peer (pad); query = gst_query_new_convert (src_format, src_val, dest_format);
if (peer) { if ((ret = gst_pad_peer_query (pad, query)))
ret = gst_pad_query_convert (peer, src_format, src_val, dest_format, gst_query_parse_convert (query, NULL, NULL, NULL, dest_val);
dest_val); gst_query_unref (query);
gst_object_unref (peer);
}
return ret; return ret;
} }

View file

@ -891,7 +891,8 @@ void gst_element_class_install_std_props (GstElementClass * k
/* pad functions */ /* pad functions */
void gst_pad_use_fixed_caps (GstPad *pad); void gst_pad_use_fixed_caps (GstPad *pad);
GstCaps* gst_pad_proxy_getcaps (GstPad * pad, GstCaps * filter); gboolean gst_pad_proxy_query_accept_caps (GstPad *pad, GstQuery *query);
gboolean gst_pad_proxy_query_caps (GstPad *pad, GstQuery *query);
GstElement* gst_pad_get_parent_element (GstPad *pad); GstElement* gst_pad_get_parent_element (GstPad *pad);

View file

@ -384,9 +384,10 @@ static gboolean gst_base_parse_handle_seek (GstBaseParse * parse,
static void gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event); static void gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event);
static gboolean gst_base_parse_src_event (GstPad * pad, GstEvent * event); static gboolean gst_base_parse_src_event (GstPad * pad, GstEvent * event);
static gboolean gst_base_parse_src_query (GstPad * pad, GstQuery * query);
static gboolean gst_base_parse_sink_event (GstPad * pad, GstEvent * event); static gboolean gst_base_parse_sink_event (GstPad * pad, GstEvent * event);
static gboolean gst_base_parse_query (GstPad * pad, GstQuery * query); static gboolean gst_base_parse_sink_query (GstPad * pad, GstQuery * query);
static GstCaps *gst_base_parse_sink_getcaps (GstPad * pad, GstCaps * filter);
static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer); static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer);
static void gst_base_parse_loop (GstPad * pad); static void gst_base_parse_loop (GstPad * pad);
@ -522,8 +523,8 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
parse->sinkpad = gst_pad_new_from_template (pad_template, "sink"); parse->sinkpad = gst_pad_new_from_template (pad_template, "sink");
gst_pad_set_event_function (parse->sinkpad, gst_pad_set_event_function (parse->sinkpad,
GST_DEBUG_FUNCPTR (gst_base_parse_sink_event)); GST_DEBUG_FUNCPTR (gst_base_parse_sink_event));
gst_pad_set_getcaps_function (parse->sinkpad, gst_pad_set_query_function (parse->sinkpad,
GST_DEBUG_FUNCPTR (gst_base_parse_sink_getcaps)); GST_DEBUG_FUNCPTR (gst_base_parse_sink_query));
gst_pad_set_chain_function (parse->sinkpad, gst_pad_set_chain_function (parse->sinkpad,
GST_DEBUG_FUNCPTR (gst_base_parse_chain)); GST_DEBUG_FUNCPTR (gst_base_parse_chain));
gst_pad_set_activate_function (parse->sinkpad, gst_pad_set_activate_function (parse->sinkpad,
@ -543,7 +544,7 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
gst_pad_set_event_function (parse->srcpad, gst_pad_set_event_function (parse->srcpad,
GST_DEBUG_FUNCPTR (gst_base_parse_src_event)); GST_DEBUG_FUNCPTR (gst_base_parse_src_event));
gst_pad_set_query_function (parse->srcpad, gst_pad_set_query_function (parse->srcpad,
GST_DEBUG_FUNCPTR (gst_base_parse_query)); GST_DEBUG_FUNCPTR (gst_base_parse_src_query));
gst_pad_use_fixed_caps (parse->srcpad); gst_pad_use_fixed_caps (parse->srcpad);
gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad); gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
GST_DEBUG_OBJECT (parse, "src created"); GST_DEBUG_OBJECT (parse, "src created");
@ -1117,6 +1118,45 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
return handled; return handled;
} }
static gboolean
gst_base_parse_sink_query (GstPad * pad, GstQuery * query)
{
GstBaseParse *parse;
GstBaseParseClass *bclass;
gboolean res;
parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
bclass = GST_BASE_PARSE_GET_CLASS (parse);
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CAPS:
{
if (bclass->get_sink_caps) {
GstCaps *caps, *filter;
gst_query_parse_caps (query, &filter);
caps = bclass->get_sink_caps (parse, filter);
GST_LOG_OBJECT (parse, "sink getcaps returning caps %" GST_PTR_FORMAT,
caps);
gst_query_set_caps_result (query, caps);
gst_caps_unref (caps);
res = TRUE;
} else
res = gst_pad_peer_query (parse->srcpad, query);
break;
}
default:
{
res = gst_pad_query_default (pad, query);
break;
}
}
gst_object_unref (parse);
return res;
}
/* gst_base_parse_src_event: /* gst_base_parse_src_event:
* @pad: #GstPad that received the event. * @pad: #GstPad that received the event.
@ -3270,7 +3310,7 @@ gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format,
} }
static gboolean static gboolean
gst_base_parse_query (GstPad * pad, GstQuery * query) gst_base_parse_src_query (GstPad * pad, GstQuery * query)
{ {
GstBaseParse *parse; GstBaseParse *parse;
gboolean res = FALSE; gboolean res = FALSE;
@ -3949,29 +3989,6 @@ gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event)
} }
} }
static GstCaps *
gst_base_parse_sink_getcaps (GstPad * pad, GstCaps * filter)
{
GstBaseParse *parse;
GstBaseParseClass *klass;
GstCaps *caps;
parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
klass = GST_BASE_PARSE_GET_CLASS (parse);
g_assert (pad == GST_BASE_PARSE_SINK_PAD (parse));
if (klass->get_sink_caps)
caps = klass->get_sink_caps (parse, filter);
else
caps = gst_pad_proxy_getcaps (pad, filter);
gst_object_unref (parse);
GST_LOG_OBJECT (parse, "sink getcaps returning caps %" GST_PTR_FORMAT, caps);
return caps;
}
static void static void
gst_base_parse_set_index (GstElement * element, GstIndex * index) gst_base_parse_set_index (GstElement * element, GstIndex * index)
{ {

View file

@ -399,7 +399,6 @@ static gboolean gst_base_sink_event (GstPad * pad, GstEvent * event);
static gboolean default_sink_query (GstBaseSink * sink, GstQuery * query); static gboolean default_sink_query (GstBaseSink * sink, GstQuery * query);
static gboolean gst_base_sink_negotiate_pull (GstBaseSink * basesink); static gboolean gst_base_sink_negotiate_pull (GstBaseSink * basesink);
static GstCaps *gst_base_sink_pad_getcaps (GstPad * pad, GstCaps * filter);
static void gst_base_sink_default_fixate (GstBaseSink * bsink, GstCaps * caps); static void gst_base_sink_default_fixate (GstBaseSink * bsink, GstCaps * caps);
static void gst_base_sink_fixate (GstBaseSink * bsink, GstCaps * caps); static void gst_base_sink_fixate (GstBaseSink * bsink, GstCaps * caps);
@ -553,7 +552,6 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
klass->query = GST_DEBUG_FUNCPTR (default_sink_query); klass->query = GST_DEBUG_FUNCPTR (default_sink_query);
/* Registering debug symbols for function pointers */ /* Registering debug symbols for function pointers */
GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_getcaps);
GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_fixate); GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_fixate);
GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_activate); GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_activate);
GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_activate_push); GST_DEBUG_REGISTER_FUNCPTR (gst_base_sink_pad_activate_push);
@ -565,17 +563,18 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
} }
static GstCaps * static GstCaps *
gst_base_sink_pad_getcaps (GstPad * pad, GstCaps * filter) gst_base_sink_query_caps (GstBaseSink * bsink, GstPad * pad, GstCaps * filter)
{ {
GstBaseSinkClass *bclass; GstBaseSinkClass *bclass;
GstBaseSink *bsink;
GstCaps *caps = NULL; GstCaps *caps = NULL;
gboolean fixed;
bsink = GST_BASE_SINK (gst_pad_get_parent (pad));
bclass = GST_BASE_SINK_GET_CLASS (bsink); bclass = GST_BASE_SINK_GET_CLASS (bsink);
fixed = GST_PAD_IS_FIXED_CAPS (pad);
if (bsink->pad_mode == GST_PAD_ACTIVATE_PULL) { if (fixed || bsink->pad_mode == GST_PAD_ACTIVATE_PULL) {
/* if we are operating in pull mode we only accept the negotiated caps */ /* if we are operating in pull mode or fixed caps, we only accept the
* currently negotiated caps */
caps = gst_pad_get_current_caps (pad); caps = gst_pad_get_current_caps (pad);
} }
if (caps == NULL) { if (caps == NULL) {
@ -602,7 +601,6 @@ gst_base_sink_pad_getcaps (GstPad * pad, GstCaps * filter)
} }
} }
} }
gst_object_unref (bsink);
return caps; return caps;
} }
@ -639,7 +637,6 @@ gst_base_sink_init (GstBaseSink * basesink, gpointer g_class)
basesink->sinkpad = gst_pad_new_from_template (pad_template, "sink"); basesink->sinkpad = gst_pad_new_from_template (pad_template, "sink");
gst_pad_set_getcaps_function (basesink->sinkpad, gst_base_sink_pad_getcaps);
gst_pad_set_activate_function (basesink->sinkpad, gst_base_sink_pad_activate); gst_pad_set_activate_function (basesink->sinkpad, gst_base_sink_pad_activate);
gst_pad_set_activatepush_function (basesink->sinkpad, gst_pad_set_activatepush_function (basesink->sinkpad,
gst_base_sink_pad_activate_push); gst_base_sink_pad_activate_push);
@ -2059,8 +2056,8 @@ gst_base_sink_wait_clock (GstBaseSink * sink, GstClockTime time,
/* FIXME: Casting to GstClockEntry only works because the types /* FIXME: Casting to GstClockEntry only works because the types
* are the same */ * are the same */
if (G_LIKELY (sink->priv->cached_clock_id != NULL if (G_LIKELY (sink->priv->cached_clock_id != NULL
&& GST_CLOCK_ENTRY_CLOCK ((GstClockEntry *) sink->priv-> && GST_CLOCK_ENTRY_CLOCK ((GstClockEntry *) sink->
cached_clock_id) == clock)) { priv->cached_clock_id) == clock)) {
if (!gst_clock_single_shot_id_reinit (clock, sink->priv->cached_clock_id, if (!gst_clock_single_shot_id_reinit (clock, sink->priv->cached_clock_id,
time)) { time)) {
gst_clock_id_unref (sink->priv->cached_clock_id); gst_clock_id_unref (sink->priv->cached_clock_id);
@ -4851,6 +4848,17 @@ default_sink_query (GstBaseSink * basesink, GstQuery * query)
res = FALSE; res = FALSE;
break; break;
} }
case GST_QUERY_CAPS:
{
GstCaps *caps, *filter;
gst_query_parse_caps (query, &filter);
caps = gst_base_sink_query_caps (basesink, basesink->sinkpad, filter);
gst_query_set_caps_result (query, caps);
gst_caps_unref (caps);
res = TRUE;
break;
}
default: default:
res = gst_pad_query_default (basesink->sinkpad, query); res = gst_pad_query_default (basesink->sinkpad, query);
break; break;

View file

@ -280,7 +280,6 @@ gst_base_src_get_type (void)
static GstCaps *gst_base_src_default_get_caps (GstBaseSrc * bsrc, static GstCaps *gst_base_src_default_get_caps (GstBaseSrc * bsrc,
GstCaps * filter); GstCaps * filter);
static GstCaps *gst_base_src_getcaps (GstPad * pad, GstCaps * filter);
static void gst_base_src_default_fixate (GstBaseSrc * src, GstCaps * caps); static void gst_base_src_default_fixate (GstBaseSrc * src, GstCaps * caps);
static void gst_base_src_fixate (GstBaseSrc * src, GstCaps * caps); static void gst_base_src_fixate (GstBaseSrc * src, GstCaps * caps);
@ -386,7 +385,6 @@ gst_base_src_class_init (GstBaseSrcClass * klass)
GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_event_handler); GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_event_handler);
GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_query); GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_query);
GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_pad_get_range); GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_pad_get_range);
GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_getcaps);
GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_fixate); GST_DEBUG_REGISTER_FUNCPTR (gst_base_src_fixate);
} }
@ -419,7 +417,6 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
gst_pad_set_event_function (pad, gst_base_src_event_handler); gst_pad_set_event_function (pad, gst_base_src_event_handler);
gst_pad_set_query_function (pad, gst_base_src_query); gst_pad_set_query_function (pad, gst_base_src_query);
gst_pad_set_getrange_function (pad, gst_base_src_pad_get_range); gst_pad_set_getrange_function (pad, gst_base_src_pad_get_range);
gst_pad_set_getcaps_function (pad, gst_base_src_getcaps);
/* hold pointer to pad */ /* hold pointer to pad */
basesrc->srcpad = pad; basesrc->srcpad = pad;
@ -836,21 +833,6 @@ gst_base_src_default_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
return caps; return caps;
} }
static GstCaps *
gst_base_src_getcaps (GstPad * pad, GstCaps * filter)
{
GstBaseSrcClass *bclass;
GstBaseSrc *bsrc;
GstCaps *caps = NULL;
bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
bclass = GST_BASE_SRC_GET_CLASS (bsrc);
if (bclass->get_caps)
caps = bclass->get_caps (bsrc, filter);
return caps;
}
static void static void
gst_base_src_default_fixate (GstBaseSrc * bsrc, GstCaps * caps) gst_base_src_default_fixate (GstBaseSrc * bsrc, GstCaps * caps)
{ {
@ -1136,12 +1118,29 @@ gst_base_src_default_query (GstBaseSrc * src, GstQuery * query)
res = TRUE; res = TRUE;
break; break;
} }
case GST_QUERY_CAPS:
{
GstBaseSrcClass *bclass;
GstCaps *caps, *filter;
bclass = GST_BASE_SRC_GET_CLASS (src);
if (bclass->get_caps) {
gst_query_parse_caps (query, &filter);
caps = bclass->get_caps (src, filter);
gst_query_set_caps_result (query, caps);
gst_caps_unref (caps);
res = TRUE;
} else
res = FALSE;
break;
}
default: default:
res = FALSE; res = FALSE;
break; break;
} }
GST_DEBUG_OBJECT (src, "query %s returns %d", GST_QUERY_TYPE_NAME (query), GST_DEBUG_OBJECT (src, "query %s returns %d", GST_QUERY_TYPE_NAME (query),
res); res);
return res; return res;
} }

View file

@ -321,7 +321,8 @@ static GstCaps *gst_base_transform_default_transform_caps (GstBaseTransform *
trans, GstPadDirection direction, GstCaps * caps, GstCaps * filter); trans, GstPadDirection direction, GstCaps * caps, GstCaps * filter);
static void gst_base_transform_default_fixate (GstBaseTransform * trans, static void gst_base_transform_default_fixate (GstBaseTransform * trans,
GstPadDirection direction, GstCaps * caps, GstCaps * othercaps); GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
static GstCaps *gst_base_transform_getcaps (GstPad * pad, GstCaps * filter); static GstCaps *gst_base_transform_query_caps (GstBaseTransform * trans,
GstPad * pad, GstCaps * filter);
static gboolean gst_base_transform_acceptcaps_default (GstBaseTransform * trans, static gboolean gst_base_transform_acceptcaps_default (GstBaseTransform * trans,
GstPadDirection direction, GstCaps * caps); GstPadDirection direction, GstCaps * caps);
static gboolean gst_base_transform_setcaps (GstBaseTransform * trans, static gboolean gst_base_transform_setcaps (GstBaseTransform * trans,
@ -410,8 +411,6 @@ gst_base_transform_init (GstBaseTransform * trans,
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink"); gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
g_return_if_fail (pad_template != NULL); g_return_if_fail (pad_template != NULL);
trans->sinkpad = gst_pad_new_from_template (pad_template, "sink"); trans->sinkpad = gst_pad_new_from_template (pad_template, "sink");
gst_pad_set_getcaps_function (trans->sinkpad,
GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
gst_pad_set_event_function (trans->sinkpad, gst_pad_set_event_function (trans->sinkpad,
GST_DEBUG_FUNCPTR (gst_base_transform_sink_event)); GST_DEBUG_FUNCPTR (gst_base_transform_sink_event));
gst_pad_set_chain_function (trans->sinkpad, gst_pad_set_chain_function (trans->sinkpad,
@ -426,8 +425,6 @@ gst_base_transform_init (GstBaseTransform * trans,
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src"); gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
g_return_if_fail (pad_template != NULL); g_return_if_fail (pad_template != NULL);
trans->srcpad = gst_pad_new_from_template (pad_template, "src"); trans->srcpad = gst_pad_new_from_template (pad_template, "src");
gst_pad_set_getcaps_function (trans->srcpad,
GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
gst_pad_set_event_function (trans->srcpad, gst_pad_set_event_function (trans->srcpad,
GST_DEBUG_FUNCPTR (gst_base_transform_src_event)); GST_DEBUG_FUNCPTR (gst_base_transform_src_event));
gst_pad_set_getrange_function (trans->srcpad, gst_pad_set_getrange_function (trans->srcpad,
@ -637,15 +634,13 @@ gst_base_transform_transform_size (GstBaseTransform * trans,
* If there is no peer, we simply return the caps of the padtemplate of pad. * If there is no peer, we simply return the caps of the padtemplate of pad.
*/ */
static GstCaps * static GstCaps *
gst_base_transform_getcaps (GstPad * pad, GstCaps * filter) gst_base_transform_query_caps (GstBaseTransform * trans, GstPad * pad,
GstCaps * filter)
{ {
GstBaseTransform *trans;
GstPad *otherpad; GstPad *otherpad;
GstCaps *peercaps, *caps, *temp, *peerfilter = NULL; GstCaps *peercaps, *caps, *temp, *peerfilter = NULL;
GstCaps *templ; GstCaps *templ;
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad; otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
/* we can do what the peer can */ /* we can do what the peer can */
@ -743,8 +738,6 @@ done:
if (peercaps) if (peercaps)
gst_caps_unref (peercaps); gst_caps_unref (peercaps);
gst_object_unref (trans);
return caps; return caps;
} }
@ -1288,10 +1281,16 @@ gst_base_transform_default_query (GstBaseTransform * trans,
GstPadDirection direction, GstQuery * query) GstPadDirection direction, GstQuery * query)
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
GstPad *otherpad; GstPad *pad, *otherpad;
GstBaseTransformClass *klass; GstBaseTransformClass *klass;
otherpad = (direction == GST_PAD_SRC) ? trans->sinkpad : trans->srcpad; if (direction == GST_PAD_SRC) {
pad = trans->srcpad;
otherpad = trans->sinkpad;
} else {
pad = trans->sinkpad;
otherpad = trans->srcpad;
}
klass = GST_BASE_TRANSFORM_GET_CLASS (trans); klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
@ -1360,6 +1359,17 @@ gst_base_transform_default_query (GstBaseTransform * trans,
} }
break; break;
} }
case GST_QUERY_CAPS:
{
GstCaps *filter, *caps;
gst_query_parse_caps (query, &filter);
caps = gst_base_transform_query_caps (trans, pad, filter);
gst_query_set_caps_result (query, caps);
gst_caps_unref (caps);
ret = TRUE;
break;
}
default: default:
ret = gst_pad_peer_query (otherpad, query); ret = gst_pad_peer_query (otherpad, query);
break; break;

View file

@ -118,7 +118,7 @@ static void gst_funnel_release_pad (GstElement * element, GstPad * pad);
static GstFlowReturn gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer); static GstFlowReturn gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer);
static gboolean gst_funnel_sink_event (GstPad * pad, GstEvent * event); static gboolean gst_funnel_sink_event (GstPad * pad, GstEvent * event);
static GstCaps *gst_funnel_sink_getcaps (GstPad * pad, GstCaps * filter); static gboolean gst_funnel_sink_query (GstPad * pad, GstQuery * query);
static gboolean gst_funnel_src_event (GstPad * pad, GstEvent * event); static gboolean gst_funnel_src_event (GstPad * pad, GstEvent * event);
@ -189,8 +189,8 @@ gst_funnel_request_new_pad (GstElement * element, GstPadTemplate * templ,
GST_DEBUG_FUNCPTR (gst_funnel_sink_chain)); GST_DEBUG_FUNCPTR (gst_funnel_sink_chain));
gst_pad_set_event_function (sinkpad, gst_pad_set_event_function (sinkpad,
GST_DEBUG_FUNCPTR (gst_funnel_sink_event)); GST_DEBUG_FUNCPTR (gst_funnel_sink_event));
gst_pad_set_getcaps_function (sinkpad, gst_pad_set_query_function (sinkpad,
GST_DEBUG_FUNCPTR (gst_funnel_sink_getcaps)); GST_DEBUG_FUNCPTR (gst_funnel_sink_query));
gst_pad_set_active (sinkpad, TRUE); gst_pad_set_active (sinkpad, TRUE);
@ -211,24 +211,6 @@ gst_funnel_release_pad (GstElement * element, GstPad * pad)
gst_element_remove_pad (GST_ELEMENT_CAST (funnel), pad); gst_element_remove_pad (GST_ELEMENT_CAST (funnel), pad);
} }
static GstCaps *
gst_funnel_sink_getcaps (GstPad * pad, GstCaps * filter)
{
GstFunnel *funnel = GST_FUNNEL (gst_pad_get_parent (pad));
GstCaps *caps;
if (G_UNLIKELY (funnel == NULL))
return gst_caps_new_any ();
caps = gst_pad_peer_get_caps (funnel->srcpad, filter);
if (caps == NULL)
caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
gst_object_unref (funnel);
return caps;
}
static GstFlowReturn static GstFlowReturn
gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer) gst_funnel_sink_chain (GstPad * pad, GstBuffer * buffer)
{ {
@ -343,6 +325,26 @@ gst_funnel_sink_event (GstPad * pad, GstEvent * event)
return res; return res;
} }
static gboolean
gst_funnel_sink_query (GstPad * pad, GstQuery * query)
{
GstFunnel *funnel = GST_FUNNEL (gst_pad_get_parent (pad));
gboolean forward = TRUE;
gboolean res = TRUE;
if (G_UNLIKELY (funnel == NULL)) {
gst_query_unref (query);
return FALSE;
}
if (forward)
res = gst_pad_peer_query (funnel->srcpad, query);
gst_object_unref (funnel);
return res;
}
static gboolean static gboolean
gst_funnel_src_event (GstPad * pad, GstEvent * event) gst_funnel_src_event (GstPad * pad, GstEvent * event)
{ {

View file

@ -179,7 +179,6 @@ static void gst_selector_pad_set_property (GObject * object,
static gint64 gst_selector_pad_get_running_time (GstSelectorPad * pad); static gint64 gst_selector_pad_get_running_time (GstSelectorPad * pad);
static void gst_selector_pad_reset (GstSelectorPad * pad); static void gst_selector_pad_reset (GstSelectorPad * pad);
static gboolean gst_selector_pad_event (GstPad * pad, GstEvent * event); static gboolean gst_selector_pad_event (GstPad * pad, GstEvent * event);
static GstCaps *gst_selector_pad_getcaps (GstPad * pad, GstCaps * filter);
static gboolean gst_selector_pad_query (GstPad * pad, GstQuery * query); static gboolean gst_selector_pad_query (GstPad * pad, GstQuery * query);
static GstIterator *gst_selector_pad_iterate_linked_pads (GstPad * pad); static GstIterator *gst_selector_pad_iterate_linked_pads (GstPad * pad);
static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstBuffer * buf); static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstBuffer * buf);
@ -496,49 +495,22 @@ gst_selector_pad_query (GstPad * pad, GstQuery * query)
{ {
gboolean res = FALSE; gboolean res = FALSE;
GstInputSelector *sel; GstInputSelector *sel;
GstPad *otherpad;
sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
if (G_UNLIKELY (sel == NULL)) if (G_UNLIKELY (sel == NULL))
return FALSE; return FALSE;
otherpad = gst_input_selector_get_linked_pad (sel, pad, TRUE);
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_ACCEPT_CAPS:
default: default:
if (otherpad) res = gst_pad_query_default (pad, query);
res = gst_pad_peer_query (otherpad, query);
break; break;
} }
if (otherpad)
gst_object_unref (otherpad);
gst_object_unref (sel); gst_object_unref (sel);
return res; return res;
} }
static GstCaps *
gst_selector_pad_getcaps (GstPad * pad, GstCaps * filter)
{
GstInputSelector *sel;
GstCaps *caps;
sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
if (G_UNLIKELY (sel == NULL))
return (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
GST_DEBUG_OBJECT (sel, "Getting caps of srcpad peer");
caps = gst_pad_peer_get_caps (sel->srcpad, filter);
if (caps == NULL)
caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
gst_object_unref (sel);
return caps;
}
/* must be called with the SELECTOR_LOCK, will block while the pad is blocked /* must be called with the SELECTOR_LOCK, will block while the pad is blocked
* or return TRUE when flushing */ * or return TRUE when flushing */
static gboolean static gboolean
@ -797,7 +769,6 @@ static void gst_input_selector_release_pad (GstElement * element, GstPad * pad);
static GstStateChangeReturn gst_input_selector_change_state (GstElement * static GstStateChangeReturn gst_input_selector_change_state (GstElement *
element, GstStateChange transition); element, GstStateChange transition);
static GstCaps *gst_input_selector_getcaps (GstPad * pad, GstCaps * filter);
static gboolean gst_input_selector_event (GstPad * pad, GstEvent * event); static gboolean gst_input_selector_event (GstPad * pad, GstEvent * event);
static gboolean gst_input_selector_query (GstPad * pad, GstQuery * query); static gboolean gst_input_selector_query (GstPad * pad, GstQuery * query);
static gint64 gst_input_selector_block (GstInputSelector * self); static gint64 gst_input_selector_block (GstInputSelector * self);
@ -914,12 +885,11 @@ gst_input_selector_init (GstInputSelector * sel)
sel->srcpad = gst_pad_new ("src", GST_PAD_SRC); sel->srcpad = gst_pad_new ("src", GST_PAD_SRC);
gst_pad_set_iterate_internal_links_function (sel->srcpad, gst_pad_set_iterate_internal_links_function (sel->srcpad,
GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads)); GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads));
gst_pad_set_getcaps_function (sel->srcpad,
GST_DEBUG_FUNCPTR (gst_input_selector_getcaps));
gst_pad_set_query_function (sel->srcpad, gst_pad_set_query_function (sel->srcpad,
GST_DEBUG_FUNCPTR (gst_input_selector_query)); GST_DEBUG_FUNCPTR (gst_input_selector_query));
gst_pad_set_event_function (sel->srcpad, gst_pad_set_event_function (sel->srcpad,
GST_DEBUG_FUNCPTR (gst_input_selector_event)); GST_DEBUG_FUNCPTR (gst_input_selector_event));
GST_OBJECT_FLAG_SET (sel->srcpad, GST_PAD_PROXY_CAPS);
gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad); gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad);
/* sinkpad management */ /* sinkpad management */
sel->active_sinkpad = NULL; sel->active_sinkpad = NULL;
@ -1139,14 +1109,11 @@ gst_input_selector_query (GstPad * pad, GstQuery * query)
{ {
gboolean res = FALSE; gboolean res = FALSE;
GstInputSelector *sel; GstInputSelector *sel;
GstPad *otherpad;
sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
if (G_UNLIKELY (sel == NULL)) if (G_UNLIKELY (sel == NULL))
return FALSE; return FALSE;
otherpad = gst_input_selector_get_linked_pad (sel, pad, TRUE);
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_LATENCY: case GST_QUERY_LATENCY:
{ {
@ -1203,48 +1170,15 @@ gst_input_selector_query (GstPad * pad, GstQuery * query)
break; break;
} }
default: default:
if (otherpad) res = gst_pad_query_default (pad, query);
res = gst_pad_peer_query (otherpad, query);
break; break;
} }
if (otherpad)
gst_object_unref (otherpad);
gst_object_unref (sel); gst_object_unref (sel);
return res; return res;
} }
static GstCaps *
gst_input_selector_getcaps (GstPad * pad, GstCaps * filter)
{
GstPad *otherpad;
GstInputSelector *sel;
GstCaps *caps;
sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
if (G_UNLIKELY (sel == NULL))
return (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
otherpad = gst_input_selector_get_linked_pad (sel, pad, FALSE);
if (!otherpad) {
GST_DEBUG_OBJECT (pad, "Pad not linked, returning ANY");
caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
} else {
GST_DEBUG_OBJECT (pad, "Pad is linked (to %s:%s), returning peer caps",
GST_DEBUG_PAD_NAME (otherpad));
/* if the peer has caps, use those. If the pad is not linked, this function
* returns NULL and we return ANY */
if (!(caps = gst_pad_peer_get_caps (otherpad, filter)))
caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
gst_object_unref (otherpad);
}
gst_object_unref (sel);
return caps;
}
/* check if the pad is the active sinkpad */ /* check if the pad is the active sinkpad */
static inline gboolean static inline gboolean
gst_input_selector_is_active_sinkpad (GstInputSelector * sel, GstPad * pad) gst_input_selector_is_active_sinkpad (GstInputSelector * sel, GstPad * pad)
@ -1304,8 +1238,6 @@ gst_input_selector_request_new_pad (GstElement * element,
gst_pad_set_event_function (sinkpad, gst_pad_set_event_function (sinkpad,
GST_DEBUG_FUNCPTR (gst_selector_pad_event)); GST_DEBUG_FUNCPTR (gst_selector_pad_event));
gst_pad_set_getcaps_function (sinkpad,
GST_DEBUG_FUNCPTR (gst_selector_pad_getcaps));
gst_pad_set_query_function (sinkpad, gst_pad_set_query_function (sinkpad,
GST_DEBUG_FUNCPTR (gst_selector_pad_query)); GST_DEBUG_FUNCPTR (gst_selector_pad_query));
gst_pad_set_chain_function (sinkpad, gst_pad_set_chain_function (sinkpad,
@ -1313,6 +1245,7 @@ gst_input_selector_request_new_pad (GstElement * element,
gst_pad_set_iterate_internal_links_function (sinkpad, gst_pad_set_iterate_internal_links_function (sinkpad,
GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads)); GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads));
GST_OBJECT_FLAG_SET (sinkpad, GST_PAD_PROXY_CAPS);
gst_pad_set_active (sinkpad, TRUE); gst_pad_set_active (sinkpad, TRUE);
gst_element_add_pad (GST_ELEMENT (sel), sinkpad); gst_element_add_pad (GST_ELEMENT (sel), sinkpad);
GST_INPUT_SELECTOR_UNLOCK (sel); GST_INPUT_SELECTOR_UNLOCK (sel);

View file

@ -1507,37 +1507,19 @@ was_eos:
static gboolean static gboolean
gst_multi_queue_sink_query (GstPad * pad, GstQuery * query) gst_multi_queue_sink_query (GstPad * pad, GstQuery * query)
{ {
GstSingleQueue *sq = gst_pad_get_element_private (pad);
gboolean res; gboolean res;
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_ACCEPT_CAPS: case GST_QUERY_ACCEPT_CAPS:
case GST_QUERY_CAPS:
default: default:
/* default handling */ /* default handling */
res = gst_pad_peer_query (sq->srcpad, query); res = gst_pad_query_default (pad, query);
break; break;
} }
return res; return res;
} }
static GstCaps *
gst_multi_queue_getcaps (GstPad * pad, GstCaps * filter)
{
GstSingleQueue *sq = gst_pad_get_element_private (pad);
GstPad *otherpad;
GstCaps *result;
otherpad = (pad == sq->srcpad) ? sq->sinkpad : sq->srcpad;
GST_LOG_OBJECT (otherpad, "Getting caps from the peer of this pad");
result = gst_pad_peer_get_caps (otherpad, filter);
if (result == NULL)
result = (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
return result;
}
static gboolean static gboolean
gst_multi_queue_src_activate_push (GstPad * pad, gboolean active) gst_multi_queue_src_activate_push (GstPad * pad, gboolean active)
{ {
@ -1571,15 +1553,15 @@ gst_multi_queue_src_event (GstPad * pad, GstEvent * event)
static gboolean static gboolean
gst_multi_queue_src_query (GstPad * pad, GstQuery * query) gst_multi_queue_src_query (GstPad * pad, GstQuery * query)
{ {
GstSingleQueue *sq = gst_pad_get_element_private (pad);
gboolean res; gboolean res;
/* FIXME, Handle position offset depending on queue size */ /* FIXME, Handle position offset depending on queue size */
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_ACCEPT_CAPS: case GST_QUERY_ACCEPT_CAPS:
case GST_QUERY_CAPS:
default: default:
/* default handling */ /* default handling */
res = gst_pad_peer_query (sq->sinkpad, query); res = gst_pad_query_default (pad, query);
break; break;
} }
return res; return res;
@ -1923,12 +1905,11 @@ gst_single_queue_new (GstMultiQueue * mqueue, guint id)
GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_push)); GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_push));
gst_pad_set_event_function (sq->sinkpad, gst_pad_set_event_function (sq->sinkpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_sink_event)); GST_DEBUG_FUNCPTR (gst_multi_queue_sink_event));
gst_pad_set_getcaps_function (sq->sinkpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_getcaps));
gst_pad_set_query_function (sq->sinkpad, gst_pad_set_query_function (sq->sinkpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_sink_query)); GST_DEBUG_FUNCPTR (gst_multi_queue_sink_query));
gst_pad_set_iterate_internal_links_function (sq->sinkpad, gst_pad_set_iterate_internal_links_function (sq->sinkpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_iterate_internal_links)); GST_DEBUG_FUNCPTR (gst_multi_queue_iterate_internal_links));
GST_OBJECT_FLAG_SET (sq->sinkpad, GST_PAD_PROXY_CAPS);
name = g_strdup_printf ("src_%u", sq->id); name = g_strdup_printf ("src_%u", sq->id);
sq->srcpad = gst_pad_new_from_static_template (&srctemplate, name); sq->srcpad = gst_pad_new_from_static_template (&srctemplate, name);
@ -1936,14 +1917,13 @@ gst_single_queue_new (GstMultiQueue * mqueue, guint id)
gst_pad_set_activatepush_function (sq->srcpad, gst_pad_set_activatepush_function (sq->srcpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_src_activate_push)); GST_DEBUG_FUNCPTR (gst_multi_queue_src_activate_push));
gst_pad_set_getcaps_function (sq->srcpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_getcaps));
gst_pad_set_event_function (sq->srcpad, gst_pad_set_event_function (sq->srcpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_src_event)); GST_DEBUG_FUNCPTR (gst_multi_queue_src_event));
gst_pad_set_query_function (sq->srcpad, gst_pad_set_query_function (sq->srcpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_src_query)); GST_DEBUG_FUNCPTR (gst_multi_queue_src_query));
gst_pad_set_iterate_internal_links_function (sq->srcpad, gst_pad_set_iterate_internal_links_function (sq->srcpad,
GST_DEBUG_FUNCPTR (gst_multi_queue_iterate_internal_links)); GST_DEBUG_FUNCPTR (gst_multi_queue_iterate_internal_links));
GST_OBJECT_FLAG_SET (sq->srcpad, GST_PAD_PROXY_CAPS);
gst_pad_set_element_private (sq->sinkpad, (gpointer) sq); gst_pad_set_element_private (sq->sinkpad, (gpointer) sq);
gst_pad_set_element_private (sq->srcpad, (gpointer) sq); gst_pad_set_element_private (sq->srcpad, (gpointer) sq);

View file

@ -105,8 +105,8 @@ static void gst_output_selector_release_pad (GstElement * element,
static GstFlowReturn gst_output_selector_chain (GstPad * pad, GstBuffer * buf); static GstFlowReturn gst_output_selector_chain (GstPad * pad, GstBuffer * buf);
static GstStateChangeReturn gst_output_selector_change_state (GstElement * static GstStateChangeReturn gst_output_selector_change_state (GstElement *
element, GstStateChange transition); element, GstStateChange transition);
static gboolean gst_output_selector_handle_sink_event (GstPad * pad, static gboolean gst_output_selector_event (GstPad * pad, GstEvent * event);
GstEvent * event); static gboolean gst_output_selector_query (GstPad * pad, GstQuery * query);
static void gst_output_selector_switch_pad_negotiation_mode (GstOutputSelector * static void gst_output_selector_switch_pad_negotiation_mode (GstOutputSelector *
sel, gint mode); sel, gint mode);
@ -161,7 +161,9 @@ gst_output_selector_init (GstOutputSelector * sel)
gst_pad_set_chain_function (sel->sinkpad, gst_pad_set_chain_function (sel->sinkpad,
GST_DEBUG_FUNCPTR (gst_output_selector_chain)); GST_DEBUG_FUNCPTR (gst_output_selector_chain));
gst_pad_set_event_function (sel->sinkpad, gst_pad_set_event_function (sel->sinkpad,
GST_DEBUG_FUNCPTR (gst_output_selector_handle_sink_event)); GST_DEBUG_FUNCPTR (gst_output_selector_event));
gst_pad_set_query_function (sel->sinkpad,
GST_DEBUG_FUNCPTR (gst_output_selector_query));
gst_element_add_pad (GST_ELEMENT (sel), sel->sinkpad); gst_element_add_pad (GST_ELEMENT (sel), sel->sinkpad);
@ -280,15 +282,10 @@ gst_output_selector_get_property (GObject * object, guint prop_id,
} }
} }
static GstCaps * static GstPad *
gst_output_selector_sink_getcaps (GstPad * pad, GstCaps * filter) gst_output_selector_get_active (GstOutputSelector * sel)
{ {
GstOutputSelector *sel = GST_OUTPUT_SELECTOR (gst_pad_get_parent (pad));
GstPad *active = NULL; GstPad *active = NULL;
GstCaps *caps = NULL;
if (G_UNLIKELY (sel == NULL))
return (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
GST_OBJECT_LOCK (sel); GST_OBJECT_LOCK (sel);
if (sel->pending_srcpad) if (sel->pending_srcpad)
@ -297,16 +294,7 @@ gst_output_selector_sink_getcaps (GstPad * pad, GstCaps * filter)
active = gst_object_ref (sel->active_srcpad); active = gst_object_ref (sel->active_srcpad);
GST_OBJECT_UNLOCK (sel); GST_OBJECT_UNLOCK (sel);
if (active) { return active;
caps = gst_pad_peer_get_caps (active, filter);
gst_object_unref (active);
}
if (caps == NULL) {
caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
}
gst_object_unref (sel);
return caps;
} }
static void static void
@ -314,14 +302,6 @@ gst_output_selector_switch_pad_negotiation_mode (GstOutputSelector * sel,
gint mode) gint mode)
{ {
sel->pad_negotiation_mode = mode; sel->pad_negotiation_mode = mode;
if (mode == GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL) {
gst_pad_set_getcaps_function (sel->sinkpad, gst_pad_proxy_getcaps);
} else if (mode == GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE) {
gst_pad_set_getcaps_function (sel->sinkpad, NULL);
} else { /* active */
gst_pad_set_getcaps_function (sel->sinkpad,
gst_output_selector_sink_getcaps);
}
} }
static GstFlowReturn static GstFlowReturn
@ -520,7 +500,7 @@ gst_output_selector_change_state (GstElement * element,
} }
static gboolean static gboolean
gst_output_selector_handle_sink_event (GstPad * pad, GstEvent * event) gst_output_selector_event (GstPad * pad, GstEvent * event)
{ {
gboolean res = TRUE; gboolean res = TRUE;
GstOutputSelector *sel; GstOutputSelector *sel;
@ -544,13 +524,7 @@ gst_output_selector_handle_sink_event (GstPad * pad, GstEvent * event)
gst_event_unref (event); gst_event_unref (event);
break; break;
default: default:
GST_OBJECT_LOCK (sel); active = gst_output_selector_get_active (sel);
if (sel->pending_srcpad)
active = gst_object_ref (sel->pending_srcpad);
else if (sel->active_srcpad)
active = gst_object_ref (sel->active_srcpad);
GST_OBJECT_UNLOCK (sel);
if (active) { if (active) {
res = gst_pad_push_event (active, event); res = gst_pad_push_event (active, event);
gst_object_unref (active); gst_object_unref (active);
@ -578,14 +552,8 @@ gst_output_selector_handle_sink_event (GstPad * pad, GstEvent * event)
break; break;
default: default:
{ {
GST_OBJECT_LOCK (sel);
if (sel->pending_srcpad)
active = gst_object_ref (sel->pending_srcpad);
else if (sel->active_srcpad)
active = gst_object_ref (sel->active_srcpad);
GST_OBJECT_UNLOCK (sel);
/* Send other events to pending or active src pad */ /* Send other events to pending or active src pad */
active = gst_output_selector_get_active (sel);
if (active) { if (active) {
res = gst_pad_push_event (active, event); res = gst_pad_push_event (active, event);
gst_object_unref (active); gst_object_unref (active);
@ -600,3 +568,47 @@ gst_output_selector_handle_sink_event (GstPad * pad, GstEvent * event)
return res; return res;
} }
static gboolean
gst_output_selector_query (GstPad * pad, GstQuery * query)
{
gboolean res = TRUE;
GstOutputSelector *sel;
GstPad *active = NULL;
sel = GST_OUTPUT_SELECTOR (gst_pad_get_parent (pad));
if (G_UNLIKELY (sel == NULL)) {
return FALSE;
}
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CAPS:
{
switch (sel->pad_negotiation_mode) {
case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_ALL:
/* Send caps to all src pads */
res = gst_pad_proxy_query_caps (pad, query);
break;
case GST_OUTPUT_SELECTOR_PAD_NEGOTIATION_MODE_NONE:
res = FALSE;
break;
default:
active = gst_output_selector_get_active (sel);
if (active) {
res = gst_pad_peer_query (active, query);
gst_object_unref (active);
} else {
res = FALSE;
}
break;
}
break;
}
default:
break;
}
gst_object_unref (sel);
return res;
}

View file

@ -202,8 +202,6 @@ static gboolean gst_queue_handle_sink_query (GstPad * pad, GstQuery * query);
static gboolean gst_queue_handle_src_event (GstPad * pad, GstEvent * event); static gboolean gst_queue_handle_src_event (GstPad * pad, GstEvent * event);
static gboolean gst_queue_handle_src_query (GstPad * pad, GstQuery * query); static gboolean gst_queue_handle_src_query (GstPad * pad, GstQuery * query);
static gboolean gst_queue_acceptcaps (GstPad * pad, GstCaps * caps);
static GstCaps *gst_queue_getcaps (GstPad * pad, GstCaps * filter);
static GstPadLinkReturn gst_queue_link_sink (GstPad * pad, GstPad * peer); static GstPadLinkReturn gst_queue_link_sink (GstPad * pad, GstPad * peer);
static GstPadLinkReturn gst_queue_link_src (GstPad * pad, GstPad * peer); static GstPadLinkReturn gst_queue_link_src (GstPad * pad, GstPad * peer);
static void gst_queue_locked_flush (GstQueue * queue); static void gst_queue_locked_flush (GstQueue * queue);
@ -368,17 +366,15 @@ gst_queue_class_init (GstQueueClass * klass)
gst_static_pad_template_get (&sinktemplate)); gst_static_pad_template_get (&sinktemplate));
/* Registering debug symbols for function pointers */ /* Registering debug symbols for function pointers */
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain); GST_DEBUG_REGISTER_FUNCPTR (gst_queue_src_activate_push);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_sink_activate_push); GST_DEBUG_REGISTER_FUNCPTR (gst_queue_sink_activate_push);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_link_sink);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_link_src);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_sink_event); GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_sink_event);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_sink_query); GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_sink_query);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_link_sink);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_getcaps);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_acceptcaps);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_src_activate_push);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_link_src);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_src_event); GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_src_event);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_src_query); GST_DEBUG_REGISTER_FUNCPTR (gst_queue_handle_src_query);
GST_DEBUG_REGISTER_FUNCPTR (gst_queue_chain);
} }
static void static void
@ -392,7 +388,6 @@ gst_queue_init (GstQueue * queue)
gst_pad_set_event_function (queue->sinkpad, gst_queue_handle_sink_event); gst_pad_set_event_function (queue->sinkpad, gst_queue_handle_sink_event);
gst_pad_set_query_function (queue->sinkpad, gst_queue_handle_sink_query); gst_pad_set_query_function (queue->sinkpad, gst_queue_handle_sink_query);
gst_pad_set_link_function (queue->sinkpad, gst_queue_link_sink); gst_pad_set_link_function (queue->sinkpad, gst_queue_link_sink);
gst_pad_set_getcaps_function (queue->sinkpad, gst_queue_getcaps);
gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad); gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
queue->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); queue->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
@ -400,7 +395,6 @@ gst_queue_init (GstQueue * queue)
gst_pad_set_activatepush_function (queue->srcpad, gst_pad_set_activatepush_function (queue->srcpad,
gst_queue_src_activate_push); gst_queue_src_activate_push);
gst_pad_set_link_function (queue->srcpad, gst_queue_link_src); gst_pad_set_link_function (queue->srcpad, gst_queue_link_src);
gst_pad_set_getcaps_function (queue->srcpad, gst_queue_getcaps);
gst_pad_set_event_function (queue->srcpad, gst_queue_handle_src_event); gst_pad_set_event_function (queue->srcpad, gst_queue_handle_src_event);
gst_pad_set_query_function (queue->srcpad, gst_queue_handle_src_query); gst_pad_set_query_function (queue->srcpad, gst_queue_handle_src_query);
gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad); gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
@ -456,46 +450,6 @@ gst_queue_finalize (GObject * object)
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
static gboolean
gst_queue_acceptcaps (GstPad * pad, GstCaps * caps)
{
gboolean result;
GstQueue *queue;
GstPad *otherpad;
queue = GST_QUEUE (gst_pad_get_parent (pad));
if (G_UNLIKELY (queue == NULL))
return FALSE;
otherpad = (pad == queue->srcpad ? queue->sinkpad : queue->srcpad);
result = gst_pad_peer_accept_caps (otherpad, caps);
gst_object_unref (queue);
return result;
}
static GstCaps *
gst_queue_getcaps (GstPad * pad, GstCaps * filter)
{
GstQueue *queue;
GstPad *otherpad;
GstCaps *result;
queue = GST_QUEUE (gst_pad_get_parent (pad));
if (G_UNLIKELY (queue == NULL))
return (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
otherpad = (pad == queue->srcpad ? queue->sinkpad : queue->srcpad);
result = gst_pad_peer_get_caps (otherpad, filter);
if (result == NULL)
result = (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
gst_object_unref (queue);
return result;
}
static GstPadLinkReturn static GstPadLinkReturn
gst_queue_link_sink (GstPad * pad, GstPad * peer) gst_queue_link_sink (GstPad * pad, GstPad * peer)
{ {
@ -874,8 +828,10 @@ gst_queue_handle_sink_query (GstPad * pad, GstQuery * query)
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_ACCEPT_CAPS: case GST_QUERY_ACCEPT_CAPS:
case GST_QUERY_CAPS:
default: default:
res = gst_pad_peer_query (queue->srcpad, query); if (!(res = gst_pad_peer_query (queue->srcpad, query)))
res = gst_pad_query_default (pad, query);
break; break;
} }
gst_object_unref (queue); gst_object_unref (queue);
@ -1093,9 +1049,6 @@ gst_queue_push_one (GstQueue * queue)
next: next:
if (is_buffer) { if (is_buffer) {
GstBuffer *buffer; GstBuffer *buffer;
#if 0
GstCaps *caps;
#endif
buffer = GST_BUFFER_CAST (data); buffer = GST_BUFFER_CAST (data);
@ -1110,21 +1063,8 @@ next:
} }
queue->head_needs_discont = FALSE; queue->head_needs_discont = FALSE;
} }
#if 0
caps = GST_BUFFER_CAPS (buffer);
#endif
GST_QUEUE_MUTEX_UNLOCK (queue); GST_QUEUE_MUTEX_UNLOCK (queue);
#if 0
/* set the right caps on the pad now. We do this before pushing the buffer
* because the pad_push call will check (using acceptcaps) if the buffer can
* be set on the pad, which might fail because this will be propagated
* upstream. Also note that if the buffer has NULL caps, it means that the
* caps did not change, so we don't have to change caps on the pad. */
if (caps && caps != GST_PAD_CAPS (queue->srcpad))
gst_pad_set_caps (queue->srcpad, caps);
#endif
if (queue->push_newsegment) { if (queue->push_newsegment) {
gst_queue_push_newsegment (queue); gst_queue_push_newsegment (queue);
} }

View file

@ -235,8 +235,6 @@ static gboolean gst_queue2_handle_src_query (GstPad * pad, GstQuery * query);
static gboolean gst_queue2_handle_query (GstElement * element, static gboolean gst_queue2_handle_query (GstElement * element,
GstQuery * query); GstQuery * query);
static GstCaps *gst_queue2_getcaps (GstPad * pad, GstCaps * filter);
static GstFlowReturn gst_queue2_get_range (GstPad * pad, guint64 offset, static GstFlowReturn gst_queue2_get_range (GstPad * pad, guint64 offset,
guint length, GstBuffer ** buffer); guint length, GstBuffer ** buffer);
@ -381,8 +379,7 @@ gst_queue2_init (GstQueue2 * queue)
GST_DEBUG_FUNCPTR (gst_queue2_handle_sink_event)); GST_DEBUG_FUNCPTR (gst_queue2_handle_sink_event));
gst_pad_set_query_function (queue->sinkpad, gst_pad_set_query_function (queue->sinkpad,
GST_DEBUG_FUNCPTR (gst_queue2_handle_sink_query)); GST_DEBUG_FUNCPTR (gst_queue2_handle_sink_query));
gst_pad_set_getcaps_function (queue->sinkpad, GST_OBJECT_FLAG_SET (queue->sinkpad, GST_PAD_PROXY_CAPS);
GST_DEBUG_FUNCPTR (gst_queue2_getcaps));
gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad); gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
queue->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); queue->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
@ -393,12 +390,11 @@ gst_queue2_init (GstQueue2 * queue)
GST_DEBUG_FUNCPTR (gst_queue2_src_activate_push)); GST_DEBUG_FUNCPTR (gst_queue2_src_activate_push));
gst_pad_set_getrange_function (queue->srcpad, gst_pad_set_getrange_function (queue->srcpad,
GST_DEBUG_FUNCPTR (gst_queue2_get_range)); GST_DEBUG_FUNCPTR (gst_queue2_get_range));
gst_pad_set_getcaps_function (queue->srcpad,
GST_DEBUG_FUNCPTR (gst_queue2_getcaps));
gst_pad_set_event_function (queue->srcpad, gst_pad_set_event_function (queue->srcpad,
GST_DEBUG_FUNCPTR (gst_queue2_handle_src_event)); GST_DEBUG_FUNCPTR (gst_queue2_handle_src_event));
gst_pad_set_query_function (queue->srcpad, gst_pad_set_query_function (queue->srcpad,
GST_DEBUG_FUNCPTR (gst_queue2_handle_src_query)); GST_DEBUG_FUNCPTR (gst_queue2_handle_src_query));
GST_OBJECT_FLAG_SET (queue->srcpad, GST_PAD_PROXY_CAPS);
gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad); gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
/* levels */ /* levels */
@ -609,27 +605,6 @@ init_ranges (GstQueue2 * queue)
queue->current = add_range (queue, 0); queue->current = add_range (queue, 0);
} }
static GstCaps *
gst_queue2_getcaps (GstPad * pad, GstCaps * filter)
{
GstQueue2 *queue;
GstPad *otherpad;
GstCaps *result;
queue = GST_QUEUE2 (gst_pad_get_parent (pad));
if (G_UNLIKELY (queue == NULL))
return (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
otherpad = (pad == queue->srcpad ? queue->sinkpad : queue->srcpad);
result = gst_pad_peer_get_caps (otherpad, filter);
if (result == NULL)
result = (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
gst_object_unref (queue);
return result;
}
/* calculate the diff between running time on the sink and src of the queue. /* calculate the diff between running time on the sink and src of the queue.
* This is the total amount of time in the queue. */ * This is the total amount of time in the queue. */
static void static void
@ -2050,7 +2025,7 @@ gst_queue2_handle_sink_query (GstPad * pad, GstQuery * query)
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
default: default:
res = gst_pad_peer_query (queue->srcpad, query); res = gst_pad_query_default (pad, query);
break; break;
} }
gst_object_unref (queue); gst_object_unref (queue);
@ -2594,7 +2569,7 @@ gst_queue2_handle_src_query (GstPad * pad, GstQuery * query)
} }
default: default:
/* peer handled other queries */ /* peer handled other queries */
if (!gst_pad_peer_query (queue->sinkpad, query)) if (!gst_pad_query_default (pad, query))
goto peer_failed; goto peer_failed;
break; break;
} }

View file

@ -140,7 +140,6 @@ static GstFlowReturn gst_tee_chain (GstPad * pad, GstBuffer * buffer);
static GstFlowReturn gst_tee_chain_list (GstPad * pad, GstBufferList * list); static GstFlowReturn gst_tee_chain_list (GstPad * pad, GstBufferList * list);
static gboolean gst_tee_sink_event (GstPad * pad, GstEvent * event); static gboolean gst_tee_sink_event (GstPad * pad, GstEvent * event);
static gboolean gst_tee_sink_query (GstPad * pad, GstQuery * query); static gboolean gst_tee_sink_query (GstPad * pad, GstQuery * query);
static gboolean gst_tee_sink_acceptcaps (GstPad * pad, GstCaps * caps);
static gboolean gst_tee_sink_activate_push (GstPad * pad, gboolean active); static gboolean gst_tee_sink_activate_push (GstPad * pad, gboolean active);
static gboolean gst_tee_src_query (GstPad * pad, GstQuery * query); static gboolean gst_tee_src_query (GstPad * pad, GstQuery * query);
static gboolean gst_tee_src_activate_pull (GstPad * pad, gboolean active); static gboolean gst_tee_src_activate_pull (GstPad * pad, gboolean active);
@ -252,13 +251,12 @@ gst_tee_init (GstTee * tee)
GST_DEBUG_FUNCPTR (gst_tee_sink_event)); GST_DEBUG_FUNCPTR (gst_tee_sink_event));
gst_pad_set_query_function (tee->sinkpad, gst_pad_set_query_function (tee->sinkpad,
GST_DEBUG_FUNCPTR (gst_tee_sink_query)); GST_DEBUG_FUNCPTR (gst_tee_sink_query));
gst_pad_set_getcaps_function (tee->sinkpad,
GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
gst_pad_set_activatepush_function (tee->sinkpad, gst_pad_set_activatepush_function (tee->sinkpad,
GST_DEBUG_FUNCPTR (gst_tee_sink_activate_push)); GST_DEBUG_FUNCPTR (gst_tee_sink_activate_push));
gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain)); gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain));
gst_pad_set_chain_list_function (tee->sinkpad, gst_pad_set_chain_list_function (tee->sinkpad,
GST_DEBUG_FUNCPTR (gst_tee_chain_list)); GST_DEBUG_FUNCPTR (gst_tee_chain_list));
GST_OBJECT_FLAG_SET (tee->sinkpad, GST_PAD_PROXY_CAPS);
gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad); gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad);
tee->last_message = NULL; tee->last_message = NULL;
@ -332,8 +330,6 @@ gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ,
if (!res) if (!res)
goto activate_failed; goto activate_failed;
gst_pad_set_getcaps_function (srcpad,
GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
gst_pad_set_activatepull_function (srcpad, gst_pad_set_activatepull_function (srcpad,
GST_DEBUG_FUNCPTR (gst_tee_src_activate_pull)); GST_DEBUG_FUNCPTR (gst_tee_src_activate_pull));
gst_pad_set_query_function (srcpad, GST_DEBUG_FUNCPTR (gst_tee_src_query)); gst_pad_set_query_function (srcpad, GST_DEBUG_FUNCPTR (gst_tee_src_query));
@ -341,6 +337,7 @@ gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ,
GST_DEBUG_FUNCPTR (gst_tee_src_get_range)); GST_DEBUG_FUNCPTR (gst_tee_src_get_range));
/* Forward sticky events to the new srcpad */ /* Forward sticky events to the new srcpad */
gst_pad_sticky_events_foreach (tee->sinkpad, forward_sticky_events, srcpad); gst_pad_sticky_events_foreach (tee->sinkpad, forward_sticky_events, srcpad);
GST_OBJECT_FLAG_SET (srcpad, GST_PAD_PROXY_CAPS);
gst_element_add_pad (GST_ELEMENT_CAST (tee), srcpad); gst_element_add_pad (GST_ELEMENT_CAST (tee), srcpad);
return srcpad; return srcpad;
@ -494,67 +491,16 @@ gst_tee_sink_event (GstPad * pad, GstEvent * event)
return res; return res;
} }
/* on the sink we accept caps that are acceptable to all srcpads */
static gboolean
gst_tee_sink_acceptcaps (GstPad * pad, GstCaps * caps)
{
GstTee *tee;
gboolean res, done;
GstIterator *it;
GValue item = { 0, };
tee = GST_TEE_CAST (GST_PAD_PARENT (pad));
it = gst_element_iterate_src_pads (GST_ELEMENT_CAST (tee));
res = TRUE;
done = FALSE;
while (!done && res) {
switch (gst_iterator_next (it, &item)) {
case GST_ITERATOR_OK:
res &= gst_pad_peer_accept_caps (g_value_get_object (&item), caps);
g_value_reset (&item);
break;
case GST_ITERATOR_RESYNC:
res = TRUE;
gst_iterator_resync (it);
break;
case GST_ITERATOR_ERROR:
res = FALSE;
done = TRUE;
break;
case GST_ITERATOR_DONE:
done = TRUE;
break;
}
}
g_value_unset (&item);
gst_iterator_free (it);
return res;
}
static gboolean static gboolean
gst_tee_sink_query (GstPad * pad, GstQuery * query) gst_tee_sink_query (GstPad * pad, GstQuery * query)
{ {
gboolean res; gboolean res;
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_ACCEPT_CAPS:
{
GstCaps *caps;
gst_query_parse_accept_caps (query, &caps);
res = gst_tee_sink_acceptcaps (pad, caps);
gst_query_set_accept_caps_result (query, res);
res = TRUE;
break;
}
default: default:
res = gst_pad_query_default (pad, query); res = gst_pad_query_default (pad, query);
break; break;
} }
return res; return res;
} }

View file

@ -72,9 +72,9 @@ static void gst_valve_set_property (GObject * object,
static void gst_valve_get_property (GObject * object, static void gst_valve_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec); guint prop_id, GValue * value, GParamSpec * pspec);
static gboolean gst_valve_event (GstPad * pad, GstEvent * event);
static GstFlowReturn gst_valve_chain (GstPad * pad, GstBuffer * buffer); static GstFlowReturn gst_valve_chain (GstPad * pad, GstBuffer * buffer);
static GstCaps *gst_valve_getcaps (GstPad * pad, GstCaps * filter); static gboolean gst_valve_sink_event (GstPad * pad, GstEvent * event);
static gboolean gst_valve_query (GstPad * pad, GstQuery * query);
#define _do_init \ #define _do_init \
GST_DEBUG_CATEGORY_INIT (valve_debug, "valve", 0, "Valve"); GST_DEBUG_CATEGORY_INIT (valve_debug, "valve", 0, "Valve");
@ -115,17 +115,17 @@ gst_valve_init (GstValve * valve)
valve->discont = FALSE; valve->discont = FALSE;
valve->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); valve->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
gst_pad_set_getcaps_function (valve->srcpad, gst_pad_set_query_function (valve->srcpad,
GST_DEBUG_FUNCPTR (gst_valve_getcaps)); GST_DEBUG_FUNCPTR (gst_valve_query));
gst_element_add_pad (GST_ELEMENT (valve), valve->srcpad); gst_element_add_pad (GST_ELEMENT (valve), valve->srcpad);
valve->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); valve->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
gst_pad_set_chain_function (valve->sinkpad, gst_pad_set_chain_function (valve->sinkpad,
GST_DEBUG_FUNCPTR (gst_valve_chain)); GST_DEBUG_FUNCPTR (gst_valve_chain));
gst_pad_set_event_function (valve->sinkpad, gst_pad_set_event_function (valve->sinkpad,
GST_DEBUG_FUNCPTR (gst_valve_event)); GST_DEBUG_FUNCPTR (gst_valve_sink_event));
gst_pad_set_getcaps_function (valve->sinkpad, gst_pad_set_query_function (valve->sinkpad,
GST_DEBUG_FUNCPTR (gst_valve_getcaps)); GST_DEBUG_FUNCPTR (gst_valve_query));
gst_element_add_pad (GST_ELEMENT (valve), valve->sinkpad); gst_element_add_pad (GST_ELEMENT (valve), valve->sinkpad);
} }
@ -193,11 +193,15 @@ gst_valve_chain (GstPad * pad, GstBuffer * buffer)
static gboolean static gboolean
gst_valve_event (GstPad * pad, GstEvent * event) gst_valve_sink_event (GstPad * pad, GstEvent * event)
{ {
GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad)); GstValve *valve;
gboolean ret = TRUE; gboolean ret = TRUE;
valve = GST_VALVE (gst_pad_get_parent (pad));
if (valve == NULL)
return FALSE;
if (g_atomic_int_get (&valve->drop)) if (g_atomic_int_get (&valve->drop))
gst_event_unref (event); gst_event_unref (event);
else else
@ -213,21 +217,30 @@ gst_valve_event (GstPad * pad, GstEvent * event)
return ret; return ret;
} }
static GstCaps * static gboolean
gst_valve_getcaps (GstPad * pad, GstCaps * filter) gst_valve_query (GstPad * pad, GstQuery * query)
{ {
GstValve *valve = GST_VALVE (gst_pad_get_parent (pad)); GstValve *valve;
GstCaps *caps; gboolean res;
GstPad *otherpad;
if (pad == valve->sinkpad) valve = GST_VALVE (gst_pad_get_parent (pad));
caps = gst_pad_peer_get_caps (valve->srcpad, filter); if (valve == NULL)
else return FALSE;
caps = gst_pad_peer_get_caps (valve->sinkpad, filter);
if (caps == NULL) otherpad = (pad == valve->sinkpad ? valve->srcpad : valve->sinkpad);
caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CAPS:
if (!(res = gst_pad_peer_query (otherpad, query)))
res = gst_pad_query_default (pad, query);
break;
default:
res = gst_pad_peer_query (otherpad, query);
break;
}
gst_object_unref (valve); gst_object_unref (valve);
return caps; return res;
} }

View file

@ -289,10 +289,27 @@ GST_START_TEST (test_request_pads_named)
GST_END_TEST; GST_END_TEST;
static GstCaps * static gboolean
mq_dummypad_getcaps (GstPad * sinkpad, GstCaps * filter) mq_dummypad_query (GstPad * sinkpad, GstQuery * query)
{ {
return (filter ? gst_caps_ref (filter) : gst_caps_new_any ()); gboolean res = TRUE;
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CAPS:
{
GstCaps *filter, *caps;
gst_query_parse_caps (query, &filter);
caps = (filter ? gst_caps_ref (filter) : gst_caps_new_any ());
gst_query_set_caps_result (query, caps);
gst_caps_unref (caps);
break;
}
default:
res = gst_pad_query_default (sinkpad, query);
break;
}
return res;
} }
struct PadData struct PadData
@ -432,11 +449,11 @@ run_output_order_test (gint n_linked)
name = g_strdup_printf ("dummysrc%d", i); name = g_strdup_printf ("dummysrc%d", i);
inputpads[i] = gst_pad_new (name, GST_PAD_SRC); inputpads[i] = gst_pad_new (name, GST_PAD_SRC);
g_free (name); g_free (name);
gst_pad_set_getcaps_function (inputpads[i], mq_dummypad_getcaps); gst_pad_set_query_function (inputpads[i], mq_dummypad_query);
mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u"); mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u");
fail_unless (mq_sinkpad != NULL); fail_unless (mq_sinkpad != NULL);
gst_pad_link (inputpads[i], mq_sinkpad); fail_unless (gst_pad_link (inputpads[i], mq_sinkpad) == GST_PAD_LINK_OK);
gst_pad_set_active (inputpads[i], TRUE); gst_pad_set_active (inputpads[i], TRUE);
@ -447,7 +464,7 @@ run_output_order_test (gint n_linked)
g_free (name); g_free (name);
gst_pad_set_chain_function (sinkpads[i], mq_dummypad_chain); gst_pad_set_chain_function (sinkpads[i], mq_dummypad_chain);
gst_pad_set_event_function (sinkpads[i], mq_dummypad_event); gst_pad_set_event_function (sinkpads[i], mq_dummypad_event);
gst_pad_set_getcaps_function (sinkpads[i], mq_dummypad_getcaps); gst_pad_set_query_function (sinkpads[i], mq_dummypad_query);
pad_data[i].pad_num = i; pad_data[i].pad_num = i;
pad_data[i].max_linked_id_ptr = &max_linked_id; pad_data[i].max_linked_id_ptr = &max_linked_id;
@ -459,7 +476,7 @@ run_output_order_test (gint n_linked)
pad_data[i].first_buf = TRUE; pad_data[i].first_buf = TRUE;
gst_pad_set_element_private (sinkpads[i], pad_data + i); gst_pad_set_element_private (sinkpads[i], pad_data + i);
gst_pad_link (mq_srcpad, sinkpads[i]); fail_unless (gst_pad_link (mq_srcpad, sinkpads[i]) == GST_PAD_LINK_OK);
gst_pad_set_active (sinkpads[i], TRUE); gst_pad_set_active (sinkpads[i], TRUE);
gst_object_unref (mq_sinkpad); gst_object_unref (mq_sinkpad);
@ -588,11 +605,11 @@ GST_START_TEST (test_sparse_stream)
name = g_strdup_printf ("dummysrc%d", i); name = g_strdup_printf ("dummysrc%d", i);
inputpads[i] = gst_pad_new (name, GST_PAD_SRC); inputpads[i] = gst_pad_new (name, GST_PAD_SRC);
g_free (name); g_free (name);
gst_pad_set_getcaps_function (inputpads[i], mq_dummypad_getcaps); gst_pad_set_query_function (inputpads[i], mq_dummypad_query);
mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u"); mq_sinkpad = gst_element_get_request_pad (mq, "sink_%u");
fail_unless (mq_sinkpad != NULL); fail_unless (mq_sinkpad != NULL);
gst_pad_link (inputpads[i], mq_sinkpad); fail_unless (gst_pad_link (inputpads[i], mq_sinkpad) == GST_PAD_LINK_OK);
gst_pad_set_active (inputpads[i], TRUE); gst_pad_set_active (inputpads[i], TRUE);
@ -603,7 +620,7 @@ GST_START_TEST (test_sparse_stream)
g_free (name); g_free (name);
gst_pad_set_chain_function (sinkpads[i], mq_dummypad_chain); gst_pad_set_chain_function (sinkpads[i], mq_dummypad_chain);
gst_pad_set_event_function (sinkpads[i], mq_dummypad_event); gst_pad_set_event_function (sinkpads[i], mq_dummypad_event);
gst_pad_set_getcaps_function (sinkpads[i], mq_dummypad_getcaps); gst_pad_set_query_function (sinkpads[i], mq_dummypad_query);
pad_data[i].pad_num = i; pad_data[i].pad_num = i;
pad_data[i].max_linked_id_ptr = &max_linked_id; pad_data[i].max_linked_id_ptr = &max_linked_id;
@ -615,7 +632,7 @@ GST_START_TEST (test_sparse_stream)
pad_data[i].first_buf = TRUE; pad_data[i].first_buf = TRUE;
gst_pad_set_element_private (sinkpads[i], pad_data + i); gst_pad_set_element_private (sinkpads[i], pad_data + i);
gst_pad_link (mq_srcpad, sinkpads[i]); fail_unless (gst_pad_link (mq_srcpad, sinkpads[i]) == GST_PAD_LINK_OK);
gst_pad_set_active (sinkpads[i], TRUE); gst_pad_set_active (sinkpads[i], TRUE);
gst_object_unref (mq_sinkpad); gst_object_unref (mq_sinkpad);

View file

@ -975,7 +975,7 @@ GST_END_TEST;
#endif #endif
#endif #endif
GST_START_TEST (test_pad_proxy_getcaps_aggregation) GST_START_TEST (test_pad_proxy_query_caps_aggregation)
{ {
GstElement *tee, *sink1, *sink2; GstElement *tee, *sink1, *sink2;
GstCaps *caps; GstCaps *caps;
@ -1113,7 +1113,7 @@ gst_utils_suite (void)
tcase_add_test (tc_chain, test_set_value_from_string); tcase_add_test (tc_chain, test_set_value_from_string);
tcase_add_test (tc_chain, test_binary_search); tcase_add_test (tc_chain, test_binary_search);
tcase_add_test (tc_chain, test_pad_proxy_getcaps_aggregation); tcase_add_test (tc_chain, test_pad_proxy_query_caps_aggregation);
tcase_add_test (tc_chain, test_greatest_common_divisor); tcase_add_test (tc_chain, test_greatest_common_divisor);
return s; return s;
} }

View file

@ -773,10 +773,6 @@ print_pad_info (GstElement * element)
n_print (" Has custom iterintlinkfunc(): %s\n", n_print (" Has custom iterintlinkfunc(): %s\n",
GST_DEBUG_FUNCPTR_NAME (pad->iterintlinkfunc)); GST_DEBUG_FUNCPTR_NAME (pad->iterintlinkfunc));
if (pad->getcapsfunc)
n_print (" Has getcapsfunc(): %s\n",
GST_DEBUG_FUNCPTR_NAME (pad->getcapsfunc));
if (pad->padtemplate) if (pad->padtemplate)
n_print (" Pad Template: '%s'\n", pad->padtemplate->name_template); n_print (" Pad Template: '%s'\n", pad->padtemplate->name_template);