From 0aaf23cb0f4c6b6d87afd6df8cc0ba6bd67fb633 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 19 Jul 2013 16:52:45 -0300 Subject: [PATCH] pad-monitor: add check for getcaps proxying audio/video fields Checks that the common audio/video fields are correctly proxied by the elements after a getcaps --- validate/gst/qa/gst-qa-pad-monitor.c | 143 +++++++++++++++++++++++++++ validate/gst/qa/gst-qa-report.h | 1 + 2 files changed, 144 insertions(+) diff --git a/validate/gst/qa/gst-qa-pad-monitor.c b/validate/gst/qa/gst-qa-pad-monitor.c index 210ab132f3..1a8c486cff 100644 --- a/validate/gst/qa/gst-qa-pad-monitor.c +++ b/validate/gst/qa/gst-qa-pad-monitor.c @@ -22,6 +22,7 @@ #include "gst-qa-pad-monitor.h" #include "gst-qa-element-monitor.h" #include +#include /** * SECTION:gst-qa-pad-monitor @@ -163,6 +164,147 @@ gst_qa_pad_monitor_check_caps_complete (GstQaPadMonitor * monitor, } } +static GstCaps * +gst_qa_pad_monitor_get_othercaps (GstQaPadMonitor * monitor) +{ + GstCaps *caps = gst_caps_new_empty (); + GstIterator *iter; + gboolean done; + GstPad *otherpad; + + iter = gst_pad_iterate_internal_links (GST_QA_PAD_MONITOR_GET_PAD (monitor)); + done = FALSE; + while (!done) { + switch (gst_iterator_next (iter, (gpointer *) & otherpad)) { + case GST_ITERATOR_OK: + + /* TODO What would be the correct caps operation to merge the caps in + * case one sink is internally linked to multiple srcs? */ + gst_caps_merge (caps, gst_pad_peer_get_caps_reffed (otherpad)); + gst_object_unref (otherpad); + + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + gst_caps_replace (&caps, gst_caps_new_empty ()); + break; + case GST_ITERATOR_ERROR: + GST_WARNING_OBJECT (monitor, "Internal links pad iteration error"); + done = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + gst_iterator_free (iter); + + GST_DEBUG_OBJECT (monitor, "Otherpad caps: %" GST_PTR_FORMAT, caps); + + return caps; +} + +static gboolean +_structure_is_video (GstStructure * structure) +{ + const gchar *name = gst_structure_get_name (structure); + + return g_strstr_len (name, 6, "video/") + && strcmp (name, "video/quicktime") != 0; +} + +static gboolean +_structure_is_audio (GstStructure * structure) +{ + const gchar *name = gst_structure_get_name (structure); + + return g_strstr_len (name, 6, "audio/") != NULL; +} + +static gboolean +gst_qa_pad_monitor_pad_should_proxy_othercaps (GstQaPadMonitor * monitor) +{ + GstQaMonitor *parent = GST_QA_MONITOR_GET_PARENT (monitor); + /* We only know how to handle othercaps checks for decoders so far */ + return GST_QA_ELEMENT_MONITOR_ELEMENT_IS_DECODER (parent) || + GST_QA_ELEMENT_MONITOR_ELEMENT_IS_ENCODER (parent); +} + +static gboolean +_structures_field_match (GstStructure * s1, GstStructure * s2, const gchar * f) +{ + const GValue *v1; + const GValue *v2; + + v2 = gst_structure_get_value (s2, f); + if (!v2) + return TRUE; /* nothing to compare to */ + + v1 = gst_structure_get_value (s1, f); + if (!v1) + return FALSE; + + return gst_value_compare (v1, v2) == GST_VALUE_EQUAL; +} + +static void +gst_qa_pad_monitor_check_caps_fields_proxied (GstQaPadMonitor * monitor, + GstCaps * caps) +{ + GstStructure *structure; + GstStructure *otherstructure; + GstCaps *othercaps; + gint i, j; + + if (!gst_qa_pad_monitor_pad_should_proxy_othercaps (monitor)) + return; + + othercaps = gst_qa_pad_monitor_get_othercaps (monitor); + + for (i = 0; i < gst_caps_get_size (othercaps); i++) { + gboolean found = FALSE; + gboolean type_match = FALSE; + + otherstructure = gst_caps_get_structure (othercaps, i); + + if (_structure_is_video (otherstructure)) { + for (j = 0; j < gst_caps_get_size (caps); j++) { + structure = gst_caps_get_structure (caps, j); + if (_structure_is_video (structure)) { + type_match = TRUE; + if (_structures_field_match (structure, otherstructure, "width") && + _structures_field_match (structure, otherstructure, "height") && + _structures_field_match (structure, otherstructure, "framerate") + && _structures_field_match (structure, otherstructure, + "pixel-aspect-ratio")) { + found = TRUE; + break; + } + } + } + } else if (_structure_is_audio (otherstructure)) { + for (j = 0; j < gst_caps_get_size (caps); j++) { + structure = gst_caps_get_structure (caps, j); + if (_structure_is_audio (structure)) { + type_match = TRUE; + if (_structures_field_match (structure, otherstructure, "rate") && + _structures_field_match (structure, otherstructure, "channels")) { + found = TRUE; + break; + } + } + } + } + + if (type_match && !found) { + GST_QA_MONITOR_REPORT_WARNING (monitor, FALSE, CAPS_NEGOTIATION, + GET_CAPS, + "Peer pad structure %" GST_PTR_FORMAT " has no similar version " + "on pad's caps %" GST_PTR_FORMAT, otherstructure, caps); + } + } +} + void _parent_set_cb (GstObject * object, GstObject * parent, GstQaMonitor * monitor) { @@ -870,6 +1012,7 @@ gst_qa_pad_monitor_getcaps_func (GstPad * pad) if (ret) { gst_qa_pad_monitor_check_caps_complete (pad_monitor, ret); + gst_qa_pad_monitor_check_caps_fields_proxied (pad_monitor, ret); } return ret; diff --git a/validate/gst/qa/gst-qa-report.h b/validate/gst/qa/gst-qa-report.h index 5f012c80be..3edc9f70cf 100644 --- a/validate/gst/qa/gst-qa-report.h +++ b/validate/gst/qa/gst-qa-report.h @@ -81,6 +81,7 @@ typedef enum { typedef enum { GST_QA_AREA_CAPS_NEGOTIATION_MISSING_FIELD, GST_QA_AREA_CAPS_NEGOTIATION_BAD_FIELD_TYPE, + GST_QA_AREA_CAPS_NEGOTIATION_GET_CAPS, GST_QA_AREA_CAPS_NEGOTIATION_NUM_ENTRIES } GstQaReportAreaCapsNegotiation;