diff --git a/validate/gst/validate/gst-validate-bin-monitor.c b/validate/gst/validate/gst-validate-bin-monitor.c index f57dff5ba2..c3af16643f 100644 --- a/validate/gst/validate/gst-validate-bin-monitor.c +++ b/validate/gst/validate/gst-validate-bin-monitor.c @@ -64,6 +64,10 @@ static void _validate_bin_element_added (GstBin * bin, GstElement * pad, GstValidateBinMonitor * monitor); +static void +_validate_bin_element_removed (GstBin * bin, GstElement * element, + GstValidateBinMonitor * monitor); + static void gst_validate_bin_set_media_descriptor (GstValidateMonitor * monitor, GstValidateMediaDescriptor * media_descriptor) @@ -138,6 +142,8 @@ gst_validate_bin_monitor_dispose (GObject * object) if (bin) { if (monitor->element_added_id) g_signal_handler_disconnect (bin, monitor->element_added_id); + if (monitor->element_removed_id) + g_signal_handler_disconnect (bin, monitor->element_removed_id); gst_object_unref (bin); } @@ -249,6 +255,10 @@ gst_validate_bin_monitor_setup (GstValidateMonitor * monitor) g_signal_connect (bin, "element-added", G_CALLBACK (_validate_bin_element_added), monitor); + bin_monitor->element_removed_id = + g_signal_connect (bin, "element-removed", + G_CALLBACK (_validate_bin_element_removed), monitor); + iterator = gst_bin_iterate_elements (bin); done = FALSE; while (!done) { @@ -297,9 +307,18 @@ gst_validate_bin_monitor_wrap_element (GstValidateBinMonitor * monitor, GST_VALIDATE_ELEMENT_MONITOR_CAST (gst_validate_monitor_factory_create (GST_OBJECT_CAST (element), runner, GST_VALIDATE_MONITOR_CAST (monitor))); g_return_if_fail (element_monitor != NULL); + + GST_VALIDATE_MONITOR_CAST (element_monitor)->verbosity = + GST_VALIDATE_MONITOR_CAST (monitor)->verbosity; gst_validate_bin_child_added_overrides (GST_VALIDATE_MONITOR (monitor), element); + if (GST_VALIDATE_MONITOR_CAST (monitor)->verbosity & + GST_VALIDATE_VERBOSITY_NEW_ELEMENTS) + gst_validate_printf (NULL, "(element-added) %s added to %s\n", + GST_ELEMENT_NAME (element), + gst_validate_reporter_get_name (GST_VALIDATE_REPORTER (monitor))); + GST_VALIDATE_MONITOR_LOCK (monitor); monitor->element_monitors = g_list_prepend (monitor->element_monitors, element_monitor); @@ -320,3 +339,14 @@ _validate_bin_element_added (GstBin * bin, GstElement * element, gst_object_unref (target); gst_validate_bin_monitor_wrap_element (monitor, element); } + +static void +_validate_bin_element_removed (GstBin * bin, GstElement * element, + GstValidateBinMonitor * monitor) +{ + if (GST_VALIDATE_MONITOR_CAST (monitor)->verbosity & + GST_VALIDATE_VERBOSITY_NEW_ELEMENTS) + gst_validate_printf (NULL, "(element-removed) %s removed from %s\n", + GST_ELEMENT_NAME (element), + gst_validate_reporter_get_name (GST_VALIDATE_REPORTER (monitor))); +} diff --git a/validate/gst/validate/gst-validate-bin-monitor.h b/validate/gst/validate/gst-validate-bin-monitor.h index 626bc35c45..892d425eb9 100644 --- a/validate/gst/validate/gst-validate-bin-monitor.h +++ b/validate/gst/validate/gst-validate-bin-monitor.h @@ -58,6 +58,7 @@ struct _GstValidateBinMonitor { /*< private >*/ gulong element_added_id; + gulong element_removed_id; gboolean stateless; }; diff --git a/validate/gst/validate/gst-validate-enum-types.c.template b/validate/gst/validate/gst-validate-enum-types.c.template new file mode 100644 index 0000000000..bca1ab454f --- /dev/null +++ b/validate/gst/validate/gst-validate-enum-types.c.template @@ -0,0 +1,40 @@ +/*** BEGIN file-header ***/ +#include +#define C_ENUM(v) ((gint) v) +#define C_FLAGS(v) ((guint) v) + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@basename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type (void) +{ + static gsize id = 0; + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { C_@TYPE@(@VALUENAME@), "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + + if (g_once_init_enter (&id)) { + GType tmp = g_@type@_register_static ("@EnumName@", values); + g_once_init_leave (&id, tmp); + } + + return (GType) id; +} + +/*** END value-tail ***/ + +/*** BEGIN file-tail ***/ + +/*** END file-tail ***/ diff --git a/validate/gst/validate/gst-validate-enum-types.h.template b/validate/gst/validate/gst-validate-enum-types.h.template new file mode 100644 index 0000000000..d0131adf82 --- /dev/null +++ b/validate/gst/validate/gst-validate-enum-types.h.template @@ -0,0 +1,25 @@ +/*** BEGIN file-header ***/ +#ifndef __GST_ENUM_TYPES_H__ +#define __GST_ENUM_TYPES_H__ + +#include +#include + +G_BEGIN_DECLS +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/* enumerations from "@basename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GST_EXPORT GType @enum_name@_get_type (void); +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* __GST_ENUM_TYPES_H__ */ +/*** END file-tail ***/ diff --git a/validate/gst/validate/gst-validate-enums.h b/validate/gst/validate/gst-validate-enums.h index 6b3d9f691b..71a05e21ef 100644 --- a/validate/gst/validate/gst-validate-enums.h +++ b/validate/gst/validate/gst-validate-enums.h @@ -81,4 +81,19 @@ typedef enum { #define GST_VALIDATE_SHOW_DEFAULT GST_VALIDATE_SHOW_SMART #endif +/** + * GstValidateVerbosityFlags: + * + * Defines the level of verbosity of -validate (ie, printing on stdout). + */ +typedef enum +{ + GST_VALIDATE_VERBOSITY_NONE = 0, + GST_VALIDATE_VERBOSITY_POSITION = 1 << 1, + GST_VALIDATE_VERBOSITY_MESSAGES = 1 << 2, + GST_VALIDATE_VERBOSITY_PROPS_CHANGES = 1 << 3, + GST_VALIDATE_VERBOSITY_NEW_ELEMENTS = 1 << 4, + GST_VALIDATE_VERBOSITY_ALL = GST_VALIDATE_VERBOSITY_POSITION | GST_VALIDATE_VERBOSITY_MESSAGES | GST_VALIDATE_VERBOSITY_PROPS_CHANGES | GST_VALIDATE_VERBOSITY_NEW_ELEMENTS +} GstValidateVerbosityFlags; + #endif /* __GST_VALIDATE_RUNNER_H__ */ diff --git a/validate/gst/validate/gst-validate-monitor.c b/validate/gst/validate/gst-validate-monitor.c index 22e0e4b7a1..5cc46eba22 100644 --- a/validate/gst/validate/gst-validate-monitor.c +++ b/validate/gst/validate/gst-validate-monitor.c @@ -25,6 +25,7 @@ # include "config.h" #endif +#include "gst-validate-enum-types.h" #include "gst-validate-internal.h" #include "gst-validate-monitor.h" #include "gst-validate-override-registry.h" @@ -43,6 +44,7 @@ enum PROP_PIPELINE, PROP_RUNNER, PROP_VALIDATE_PARENT, + PROP_VERBOSITY, PROP_LAST }; @@ -175,6 +177,12 @@ gst_validate_monitor_class_init (GstValidateMonitorClass * klass) "The Validate monitor that is the parent of this one", GST_TYPE_VALIDATE_MONITOR, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_VERBOSITY, + g_param_spec_flags ("verbosity", "Verbosity", + "The verbosity of GstValidate on the monitor", + GST_TYPE_VALIDATE_VERBOSITY_FLAGS, + GST_VALIDATE_VERBOSITY_POSITION, G_PARAM_READWRITE)); } static GObject * @@ -219,6 +227,8 @@ gst_validate_monitor_init (GstValidateMonitor * monitor) g_mutex_init (&monitor->overrides_mutex); g_queue_init (&monitor->overrides); + + monitor->verbosity = GST_VALIDATE_VERBOSITY_POSITION; } static gboolean @@ -288,8 +298,20 @@ _determine_reporting_level (GstValidateMonitor * monitor) gboolean gst_validate_monitor_setup (GstValidateMonitor * monitor) { + GList *config; + GST_DEBUG_OBJECT (monitor, "Starting monitor setup"); + for (config = gst_validate_plugin_get_config (NULL); config; + config = config->next) { + const gchar *verbosity = + gst_structure_get_string (GST_STRUCTURE (config->data), + "verbosity"); + + if (verbosity) + gst_util_set_object_arg (G_OBJECT (monitor), "verbosity", verbosity); + } + /* For now we just need to do this at setup time */ _determine_reporting_level (monitor); return GST_VALIDATE_MONITOR_GET_CLASS (monitor)->setup (monitor); @@ -412,6 +434,9 @@ gst_validate_monitor_set_property (GObject * object, guint prop_id, case PROP_VALIDATE_PARENT: monitor->parent = g_value_get_object (value); break; + case PROP_VERBOSITY: + monitor->verbosity = g_value_get_flags (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -440,6 +465,9 @@ gst_validate_monitor_get_property (GObject * object, guint prop_id, case PROP_VALIDATE_PARENT: g_value_set_object (value, GST_VALIDATE_MONITOR_GET_PARENT (monitor)); break; + case PROP_VERBOSITY: + g_value_set_flags (value, monitor->verbosity); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/validate/gst/validate/gst-validate-monitor.h b/validate/gst/validate/gst-validate-monitor.h index 252640dfd1..77547c6a47 100644 --- a/validate/gst/validate/gst-validate-monitor.h +++ b/validate/gst/validate/gst-validate-monitor.h @@ -96,6 +96,8 @@ struct _GstValidateMonitor { /*< private >*/ GHashTable *reports; + + GstValidateVerbosityFlags verbosity; }; /** diff --git a/validate/gst/validate/gst-validate-pipeline-monitor.c b/validate/gst/validate/gst-validate-pipeline-monitor.c index 7b413e4b9c..26c9bbe0a6 100644 --- a/validate/gst/validate/gst-validate-pipeline-monitor.c +++ b/validate/gst/validate/gst-validate-pipeline-monitor.c @@ -108,6 +108,10 @@ print_position (GstValidateMonitor * monitor) gdouble rate = 1.0; GstFormat format = GST_FORMAT_TIME; + if (!(GST_VALIDATE_MONITOR_CAST (monitor)->verbosity & + GST_VALIDATE_VERBOSITY_POSITION)) + goto done; + if (!gst_element_query_position (pipeline, format, &position)) { GST_DEBUG_OBJECT (monitor, "Could not query position"); @@ -481,6 +485,46 @@ _bus_handler (GstBus * bus, GstMessage * message, const GstStructure *details = NULL; gint error_flow = GST_FLOW_OK; + if (GST_VALIDATE_MONITOR_CAST (monitor)->verbosity & + GST_VALIDATE_VERBOSITY_MESSAGES + && GST_MESSAGE_TYPE (message) != GST_MESSAGE_PROPERTY_NOTIFY) { + GstObject *src_obj; + const GstStructure *s; + guint32 seqnum; + GString *str = g_string_new (NULL); + + seqnum = gst_message_get_seqnum (message); + s = gst_message_get_structure (message); + src_obj = GST_MESSAGE_SRC (message); + + if (GST_IS_ELEMENT (src_obj)) { + g_string_append_printf (str, "Got message #%u from element \"%s\" (%s): ", + (guint) seqnum, GST_ELEMENT_NAME (src_obj), + GST_MESSAGE_TYPE_NAME (message)); + } else if (GST_IS_PAD (src_obj)) { + g_string_append_printf (str, "Got message #%u from pad \"%s:%s\" (%s): ", + (guint) seqnum, GST_DEBUG_PAD_NAME (src_obj), + GST_MESSAGE_TYPE_NAME (message)); + } else if (GST_IS_OBJECT (src_obj)) { + g_string_append_printf (str, "Got message #%u from object \"%s\" (%s): ", + (guint) seqnum, GST_OBJECT_NAME (src_obj), + GST_MESSAGE_TYPE_NAME (message)); + } else { + g_string_append_printf (str, "Got message #%u (%s): ", (guint) seqnum, + GST_MESSAGE_TYPE_NAME (message)); + } + if (s) { + gchar *sstr; + + sstr = gst_structure_to_string (s); + g_string_append_printf (str, "%s\n", sstr); + g_free (sstr); + } else { + g_string_append (str, "no message details\n"); + } + gst_validate_printf (NULL, str->str); + g_string_free (str, TRUE); + } switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: gst_message_parse_error (message, &err, &debug); @@ -616,6 +660,43 @@ _bus_handler (GstBus * bus, GstMessage * message, } break; } + case GST_MESSAGE_PROPERTY_NOTIFY: + { + const GValue *val; + const gchar *name; + GstObject *obj; + gchar *val_str = NULL; + gchar *obj_name; + + if (!(GST_VALIDATE_MONITOR_CAST (monitor)->verbosity & + GST_VALIDATE_VERBOSITY_PROPS_CHANGES)) + return; + + gst_message_parse_property_notify (message, &obj, &name, &val); + + obj_name = gst_object_get_path_string (GST_OBJECT (obj)); + if (val != NULL) { + if (G_VALUE_HOLDS_STRING (val)) + val_str = g_value_dup_string (val); + else if (G_VALUE_TYPE (val) == GST_TYPE_CAPS) + val_str = gst_caps_to_string (g_value_get_boxed (val)); + else if (G_VALUE_TYPE (val) == GST_TYPE_TAG_LIST) + val_str = gst_tag_list_to_string (g_value_get_boxed (val)); + else if (G_VALUE_TYPE (val) == GST_TYPE_STRUCTURE) + val_str = gst_structure_to_string (g_value_get_boxed (val)); + else + val_str = gst_value_serialize (val); + } else { + val_str = g_strdup ("(no value)"); + } + + gst_validate_printf (NULL, "%s: %s = %s\n", obj_name, name, val_str); + g_free (obj_name); + g_free (val_str); + break; + + break; + } default: break; } @@ -694,6 +775,10 @@ gst_validate_pipeline_monitor_new (GstPipeline * pipeline, gst_bus_enable_sync_message_emission (bus); g_signal_connect (bus, "sync-message", (GCallback) _bus_handler, monitor); + monitor->deep_notify_id = + gst_element_add_property_deep_notify_watch ((GstElement *) pipeline, NULL, + TRUE); + gst_object_unref (bus); if (g_strcmp0 (G_OBJECT_TYPE_NAME (pipeline), "GstPlayBin") == 0) diff --git a/validate/gst/validate/gst-validate-pipeline-monitor.h b/validate/gst/validate/gst-validate-pipeline-monitor.h index 502cb7d8a3..161103de43 100644 --- a/validate/gst/validate/gst-validate-pipeline-monitor.h +++ b/validate/gst/validate/gst-validate-pipeline-monitor.h @@ -68,6 +68,8 @@ struct _GstValidatePipelineMonitor { GstStreamCollection *stream_collection; /* Latest GstStream received from GST_MESSAGE_STREAMS_SELECTED */ GList *streams_selected; + + gulong deep_notify_id; }; /** diff --git a/validate/gst/validate/meson.build b/validate/gst/validate/meson.build index ef2524d760..0e461a12e4 100644 --- a/validate/gst/validate/meson.build +++ b/validate/gst/validate/meson.build @@ -44,8 +44,15 @@ gstvalidate_headers = [ install_headers(gstvalidate_headers, subdir : 'gstreamer-1.0/gst/validate') +gst_validate_enums = gnome.mkenums('gstvalidateenumtypes', + sources : gstvalidate_headers, + h_template : 'gst-validate-enum-types.h.template', + c_template : 'gst-validate-enum-types.c.template', + install_header : true, + install_dir : join_paths(get_option('includedir'), 'gstreamer-1.0/gst/validate')) + gstvalidate = shared_library('gstvalidate-1.0', - sources: gstvalidate_sources, + sources: gstvalidate_sources + gst_validate_enums, version : libversion, soversion : soversion, include_directories : [inc_dirs], @@ -56,7 +63,7 @@ gstvalidate = shared_library('gstvalidate-1.0', gst_pbutils_dep, mathlib, json_dep]) gstvalidatetracer = shared_library('gstvalidatetracer', - sources: gstvalidate_sources, + sources: gstvalidate_sources + gst_validate_enums, include_directories : [inc_dirs], install: true, c_args : [gst_c_args] + ['-D__GST_VALIDATE_PLUGIN', '-D_GNU_SOURCE'], @@ -76,7 +83,7 @@ if build_gir '--cflags-end'] endif validate_gen_sources = [gnome.generate_gir(gstvalidate, - sources : gstvalidate_sources + gstvalidate_headers, + sources : gstvalidate_sources + gstvalidate_headers + gst_validate_enums, nsversion : '1.0', namespace : 'GstValidate', symbol_prefix : 'gst_validate', diff --git a/validate/gst/validate/validate.h b/validate/gst/validate/validate.h index 254571d3cb..d4a352713e 100644 --- a/validate/gst/validate/validate.h +++ b/validate/gst/validate/validate.h @@ -7,6 +7,7 @@ #include #include +#include #include #include diff --git a/validate/tools/gst-validate.c b/validate/tools/gst-validate.c index 8135fe4195..e8bd157de8 100644 --- a/validate/tools/gst-validate.c +++ b/validate/tools/gst-validate.c @@ -305,7 +305,8 @@ int main (int argc, gchar ** argv) { GError *err = NULL; - gchar *scenario = NULL, *configs = NULL, *media_info = NULL; + gchar *scenario = NULL, *configs = NULL, *media_info = NULL, + *verbosity = NULL; gboolean list_scenarios = FALSE, monitor_handles_state, inspect_action_type = FALSE; GstStateChangeReturn sret; @@ -324,6 +325,9 @@ main (int argc, gchar ** argv) " '.scenario' extension).", NULL}, {"list-scenarios", 'l', 0, G_OPTION_ARG_NONE, &list_scenarios, "List the available scenarios that can be run", NULL}, + {"verbosity", 'v', 0, G_OPTION_ARG_STRING, &verbosity, + "Set overall verbosity as defined by GstValidateVerbosityFlags" + " as a string", NULL}, {"scenarios-defs-output-file", '\0', 0, G_OPTION_ARG_FILENAME, &output_file, "The output file to store scenarios details. " "Implies --list-scenarios", @@ -453,6 +457,8 @@ main (int argc, gchar ** argv) monitor = gst_validate_monitor_factory_create (GST_OBJECT_CAST (pipeline), runner, NULL); + if (verbosity) + gst_util_set_object_arg (G_OBJECT (monitor), "verbosity", verbosity); gst_validate_reporter_set_handle_g_logs (GST_VALIDATE_REPORTER (monitor)); if (media_info) {