From 389f6d96b4a6cfb24d2a6ade9575b71c9ca0a354 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 9 Jan 2015 12:36:31 -0300 Subject: [PATCH] pad-monitor: use the same filter caps when querying downstream caps To avoid comparing the real result that has been filtered against a much larger caps that contains all possibilities. --- .../gst/validate/gst-validate-pad-monitor.c | 123 +++++++++++++++++- 1 file changed, 118 insertions(+), 5 deletions(-) diff --git a/validate/gst/validate/gst-validate-pad-monitor.c b/validate/gst/validate/gst-validate-pad-monitor.c index 7118ea915a..5e4065fd15 100644 --- a/validate/gst/validate/gst-validate-pad-monitor.c +++ b/validate/gst/validate/gst-validate-pad-monitor.c @@ -457,7 +457,8 @@ gst_validate_pad_monitor_check_caps_complete (GstValidatePadMonitor * monitor, } static GstCaps * -gst_validate_pad_monitor_get_othercaps (GstValidatePadMonitor * monitor) +gst_validate_pad_monitor_get_othercaps (GstValidatePadMonitor * monitor, + GstCaps * filter) { GstCaps *caps = gst_caps_new_empty (); GstIterator *iter; @@ -477,7 +478,7 @@ gst_validate_pad_monitor_get_othercaps (GstValidatePadMonitor * monitor) /* TODO What would be the correct caps operation to merge the caps in * case one sink is internally linked to multiple srcs? */ - peercaps = gst_pad_peer_query_caps (otherpad, NULL); + peercaps = gst_pad_peer_query_caps (otherpad, filter); if (peercaps) caps = gst_caps_merge (caps, peercaps); @@ -616,19 +617,127 @@ _structures_field_is_contained (GstStructure * s1, GstStructure * s2, return FALSE; } +static void +_check_and_copy_structure_field (GstStructure * from, GstStructure * to, + const gchar * name) +{ + if (gst_structure_has_field (from, name)) { + gst_structure_set_value (to, name, gst_structure_get_value (from, name)); + } +} + +static GstCaps * +gst_validate_pad_monitor_copy_caps_fields_into_caps (GstValidatePadMonitor * + monitor, GstCaps * from_caps, GstCaps * into_caps) +{ + gint i, j, into_size, from_size; + GstStructure *structure; + GstCaps *res = gst_caps_new_empty (); + + into_size = gst_caps_get_size (into_caps); + from_size = gst_caps_get_size (from_caps); + + for (i = 0; i < into_size; i++) { + GstStructure *s = gst_caps_get_structure (into_caps, i); + + for (j = 0; j < from_size; j++) { + GstStructure *new_structure = gst_structure_copy (s); + + structure = gst_caps_get_structure (from_caps, j); + if (_structure_is_video (structure)) { + _check_and_copy_structure_field (structure, new_structure, "width"); + _check_and_copy_structure_field (structure, new_structure, "height"); + _check_and_copy_structure_field (structure, new_structure, "framerate"); + _check_and_copy_structure_field (structure, new_structure, + "pixel-aspect-ratio"); + } else if (_structure_is_audio (s)) { + _check_and_copy_structure_field (structure, new_structure, "rate"); + _check_and_copy_structure_field (structure, new_structure, "channels"); + } + + gst_caps_append_structure (res, new_structure); + } + } + return res; +} + +static GstCaps * +gst_validate_pad_monitor_transform_caps (GstValidatePadMonitor * monitor, + GstCaps * caps) +{ + GstCaps *othercaps = gst_caps_new_empty (); + GstCaps *new_caps; + GstIterator *iter; + gboolean done; + GstPad *otherpad; + GstCaps *template_caps; + + GST_DEBUG_OBJECT (monitor->pad, "Transform caps %" GST_PTR_FORMAT, caps); + + if (caps == NULL) + return NULL; + + iter = + gst_pad_iterate_internal_links (GST_VALIDATE_PAD_MONITOR_GET_PAD + (monitor)); + done = FALSE; + while (!done) { + GValue value = { 0, }; + switch (gst_iterator_next (iter, &value)) { + case GST_ITERATOR_OK: + otherpad = g_value_get_object (&value); + template_caps = gst_pad_get_pad_template_caps (otherpad); + + new_caps = + gst_validate_pad_monitor_copy_caps_fields_into_caps (monitor, caps, + template_caps); + if (!gst_caps_is_empty (new_caps)) + gst_caps_append (othercaps, new_caps); + else + gst_caps_unref (new_caps); + + gst_caps_unref (template_caps); + g_value_reset (&value); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + gst_caps_unref (othercaps); + othercaps = gst_caps_new_empty (); + break; + case GST_ITERATOR_ERROR: + GST_WARNING_OBJECT (monitor->pad, "Internal links pad iteration error"); + done = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + gst_iterator_free (iter); + + GST_DEBUG_OBJECT (monitor->pad, "Transformed caps: %" GST_PTR_FORMAT, + othercaps); + + return othercaps; +} + static void gst_validate_pad_monitor_check_caps_fields_proxied (GstValidatePadMonitor * - monitor, GstCaps * caps) + monitor, GstCaps * caps, GstCaps * filter) { GstStructure *structure; GstStructure *otherstructure; GstCaps *othercaps; + GstCaps *otherfilter; gint i, j; if (!gst_validate_pad_monitor_pad_should_proxy_othercaps (monitor)) return; - othercaps = gst_validate_pad_monitor_get_othercaps (monitor); + otherfilter = gst_validate_pad_monitor_transform_caps (monitor, filter); + othercaps = gst_validate_pad_monitor_get_othercaps (monitor, otherfilter); + if (otherfilter) + gst_caps_unref (otherfilter); for (i = 0; i < gst_caps_get_size (othercaps); i++) { gboolean found = FALSE; @@ -1992,13 +2101,17 @@ gst_validate_pad_monitor_query_func (GstPad * pad, GstObject * parent, switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CAPS:{ GstCaps *res; + GstCaps *filter; + /* We shouldn't need to lock the parent as this doesn't modify * other monitors, just does some peer_pad_caps */ GST_VALIDATE_MONITOR_LOCK (pad_monitor); + gst_query_parse_caps (query, &filter); gst_query_parse_caps_result (query, &res); if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) { - gst_validate_pad_monitor_check_caps_fields_proxied (pad_monitor, res); + gst_validate_pad_monitor_check_caps_fields_proxied (pad_monitor, res, + filter); } GST_VALIDATE_MONITOR_UNLOCK (pad_monitor); break;