validate: Add a way to print information about pipeline status

Similare to what is done with gst-launch.

And finally generate GTypes for our flags and enums.
This commit is contained in:
Thibault Saunier 2017-07-25 11:23:35 -04:00
parent 40eb48d21f
commit b9d6f9df9e
12 changed files with 246 additions and 4 deletions

View File

@ -64,6 +64,10 @@ static void
_validate_bin_element_added (GstBin * bin, GstElement * pad, _validate_bin_element_added (GstBin * bin, GstElement * pad,
GstValidateBinMonitor * monitor); GstValidateBinMonitor * monitor);
static void
_validate_bin_element_removed (GstBin * bin, GstElement * element,
GstValidateBinMonitor * monitor);
static void static void
gst_validate_bin_set_media_descriptor (GstValidateMonitor * monitor, gst_validate_bin_set_media_descriptor (GstValidateMonitor * monitor,
GstValidateMediaDescriptor * media_descriptor) GstValidateMediaDescriptor * media_descriptor)
@ -138,6 +142,8 @@ gst_validate_bin_monitor_dispose (GObject * object)
if (bin) { if (bin) {
if (monitor->element_added_id) if (monitor->element_added_id)
g_signal_handler_disconnect (bin, 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); gst_object_unref (bin);
} }
@ -249,6 +255,10 @@ gst_validate_bin_monitor_setup (GstValidateMonitor * monitor)
g_signal_connect (bin, "element-added", g_signal_connect (bin, "element-added",
G_CALLBACK (_validate_bin_element_added), monitor); 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); iterator = gst_bin_iterate_elements (bin);
done = FALSE; done = FALSE;
while (!done) { 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_VALIDATE_ELEMENT_MONITOR_CAST (gst_validate_monitor_factory_create
(GST_OBJECT_CAST (element), runner, GST_VALIDATE_MONITOR_CAST (monitor))); (GST_OBJECT_CAST (element), runner, GST_VALIDATE_MONITOR_CAST (monitor)));
g_return_if_fail (element_monitor != NULL); 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), gst_validate_bin_child_added_overrides (GST_VALIDATE_MONITOR (monitor),
element); 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); GST_VALIDATE_MONITOR_LOCK (monitor);
monitor->element_monitors = g_list_prepend (monitor->element_monitors, monitor->element_monitors = g_list_prepend (monitor->element_monitors,
element_monitor); element_monitor);
@ -320,3 +339,14 @@ _validate_bin_element_added (GstBin * bin, GstElement * element,
gst_object_unref (target); gst_object_unref (target);
gst_validate_bin_monitor_wrap_element (monitor, element); 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)));
}

View File

@ -58,6 +58,7 @@ struct _GstValidateBinMonitor {
/*< private >*/ /*< private >*/
gulong element_added_id; gulong element_added_id;
gulong element_removed_id;
gboolean stateless; gboolean stateless;
}; };

View File

@ -0,0 +1,40 @@
/*** BEGIN file-header ***/
#include <gst/validate/validate.h>
#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 ***/

View File

@ -0,0 +1,25 @@
/*** BEGIN file-header ***/
#ifndef __GST_ENUM_TYPES_H__
#define __GST_ENUM_TYPES_H__
#include <glib-object.h>
#include <gst/validate/validate.h>
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 ***/

View File

@ -81,4 +81,19 @@ typedef enum {
#define GST_VALIDATE_SHOW_DEFAULT GST_VALIDATE_SHOW_SMART #define GST_VALIDATE_SHOW_DEFAULT GST_VALIDATE_SHOW_SMART
#endif #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__ */ #endif /* __GST_VALIDATE_RUNNER_H__ */

View File

@ -25,6 +25,7 @@
# include "config.h" # include "config.h"
#endif #endif
#include "gst-validate-enum-types.h"
#include "gst-validate-internal.h" #include "gst-validate-internal.h"
#include "gst-validate-monitor.h" #include "gst-validate-monitor.h"
#include "gst-validate-override-registry.h" #include "gst-validate-override-registry.h"
@ -43,6 +44,7 @@ enum
PROP_PIPELINE, PROP_PIPELINE,
PROP_RUNNER, PROP_RUNNER,
PROP_VALIDATE_PARENT, PROP_VALIDATE_PARENT,
PROP_VERBOSITY,
PROP_LAST PROP_LAST
}; };
@ -175,6 +177,12 @@ gst_validate_monitor_class_init (GstValidateMonitorClass * klass)
"The Validate monitor that is the parent of this one", "The Validate monitor that is the parent of this one",
GST_TYPE_VALIDATE_MONITOR, GST_TYPE_VALIDATE_MONITOR,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); 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 * static GObject *
@ -219,6 +227,8 @@ gst_validate_monitor_init (GstValidateMonitor * monitor)
g_mutex_init (&monitor->overrides_mutex); g_mutex_init (&monitor->overrides_mutex);
g_queue_init (&monitor->overrides); g_queue_init (&monitor->overrides);
monitor->verbosity = GST_VALIDATE_VERBOSITY_POSITION;
} }
static gboolean static gboolean
@ -288,8 +298,20 @@ _determine_reporting_level (GstValidateMonitor * monitor)
gboolean gboolean
gst_validate_monitor_setup (GstValidateMonitor * monitor) gst_validate_monitor_setup (GstValidateMonitor * monitor)
{ {
GList *config;
GST_DEBUG_OBJECT (monitor, "Starting monitor setup"); 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 */ /* For now we just need to do this at setup time */
_determine_reporting_level (monitor); _determine_reporting_level (monitor);
return GST_VALIDATE_MONITOR_GET_CLASS (monitor)->setup (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: case PROP_VALIDATE_PARENT:
monitor->parent = g_value_get_object (value); monitor->parent = g_value_get_object (value);
break; break;
case PROP_VERBOSITY:
monitor->verbosity = g_value_get_flags (value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -440,6 +465,9 @@ gst_validate_monitor_get_property (GObject * object, guint prop_id,
case PROP_VALIDATE_PARENT: case PROP_VALIDATE_PARENT:
g_value_set_object (value, GST_VALIDATE_MONITOR_GET_PARENT (monitor)); g_value_set_object (value, GST_VALIDATE_MONITOR_GET_PARENT (monitor));
break; break;
case PROP_VERBOSITY:
g_value_set_flags (value, monitor->verbosity);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;

View File

@ -96,6 +96,8 @@ struct _GstValidateMonitor {
/*< private >*/ /*< private >*/
GHashTable *reports; GHashTable *reports;
GstValidateVerbosityFlags verbosity;
}; };
/** /**

View File

@ -108,6 +108,10 @@ print_position (GstValidateMonitor * monitor)
gdouble rate = 1.0; gdouble rate = 1.0;
GstFormat format = GST_FORMAT_TIME; 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)) { if (!gst_element_query_position (pipeline, format, &position)) {
GST_DEBUG_OBJECT (monitor, "Could not query position"); GST_DEBUG_OBJECT (monitor, "Could not query position");
@ -481,6 +485,46 @@ _bus_handler (GstBus * bus, GstMessage * message,
const GstStructure *details = NULL; const GstStructure *details = NULL;
gint error_flow = GST_FLOW_OK; 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)) { switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ERROR: case GST_MESSAGE_ERROR:
gst_message_parse_error (message, &err, &debug); gst_message_parse_error (message, &err, &debug);
@ -616,6 +660,43 @@ _bus_handler (GstBus * bus, GstMessage * message,
} }
break; 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: default:
break; break;
} }
@ -694,6 +775,10 @@ gst_validate_pipeline_monitor_new (GstPipeline * pipeline,
gst_bus_enable_sync_message_emission (bus); gst_bus_enable_sync_message_emission (bus);
g_signal_connect (bus, "sync-message", (GCallback) _bus_handler, monitor); 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); gst_object_unref (bus);
if (g_strcmp0 (G_OBJECT_TYPE_NAME (pipeline), "GstPlayBin") == 0) if (g_strcmp0 (G_OBJECT_TYPE_NAME (pipeline), "GstPlayBin") == 0)

View File

@ -68,6 +68,8 @@ struct _GstValidatePipelineMonitor {
GstStreamCollection *stream_collection; GstStreamCollection *stream_collection;
/* Latest GstStream received from GST_MESSAGE_STREAMS_SELECTED */ /* Latest GstStream received from GST_MESSAGE_STREAMS_SELECTED */
GList *streams_selected; GList *streams_selected;
gulong deep_notify_id;
}; };
/** /**

View File

@ -44,8 +44,15 @@ gstvalidate_headers = [
install_headers(gstvalidate_headers, subdir : 'gstreamer-1.0/gst/validate') 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', gstvalidate = shared_library('gstvalidate-1.0',
sources: gstvalidate_sources, sources: gstvalidate_sources + gst_validate_enums,
version : libversion, version : libversion,
soversion : soversion, soversion : soversion,
include_directories : [inc_dirs], include_directories : [inc_dirs],
@ -56,7 +63,7 @@ gstvalidate = shared_library('gstvalidate-1.0',
gst_pbutils_dep, mathlib, json_dep]) gst_pbutils_dep, mathlib, json_dep])
gstvalidatetracer = shared_library('gstvalidatetracer', gstvalidatetracer = shared_library('gstvalidatetracer',
sources: gstvalidate_sources, sources: gstvalidate_sources + gst_validate_enums,
include_directories : [inc_dirs], include_directories : [inc_dirs],
install: true, install: true,
c_args : [gst_c_args] + ['-D__GST_VALIDATE_PLUGIN', '-D_GNU_SOURCE'], c_args : [gst_c_args] + ['-D__GST_VALIDATE_PLUGIN', '-D_GNU_SOURCE'],
@ -76,7 +83,7 @@ if build_gir
'--cflags-end'] '--cflags-end']
endif endif
validate_gen_sources = [gnome.generate_gir(gstvalidate, validate_gen_sources = [gnome.generate_gir(gstvalidate,
sources : gstvalidate_sources + gstvalidate_headers, sources : gstvalidate_sources + gstvalidate_headers + gst_validate_enums,
nsversion : '1.0', nsversion : '1.0',
namespace : 'GstValidate', namespace : 'GstValidate',
symbol_prefix : 'gst_validate', symbol_prefix : 'gst_validate',

View File

@ -7,6 +7,7 @@
#include <gst/validate/gst-validate-types.h> #include <gst/validate/gst-validate-types.h>
#include <gst/validate/gst-validate-enums.h> #include <gst/validate/gst-validate-enums.h>
#include <gst/validate/gst-validate-scenario.h>
#include <gst/validate/gst-validate-runner.h> #include <gst/validate/gst-validate-runner.h>
#include <gst/validate/gst-validate-monitor-factory.h> #include <gst/validate/gst-validate-monitor-factory.h>

View File

@ -305,7 +305,8 @@ int
main (int argc, gchar ** argv) main (int argc, gchar ** argv)
{ {
GError *err = NULL; 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, gboolean list_scenarios = FALSE, monitor_handles_state,
inspect_action_type = FALSE; inspect_action_type = FALSE;
GstStateChangeReturn sret; GstStateChangeReturn sret;
@ -324,6 +325,9 @@ main (int argc, gchar ** argv)
" '.scenario' extension).", NULL}, " '.scenario' extension).", NULL},
{"list-scenarios", 'l', 0, G_OPTION_ARG_NONE, &list_scenarios, {"list-scenarios", 'l', 0, G_OPTION_ARG_NONE, &list_scenarios,
"List the available scenarios that can be run", NULL}, "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, {"scenarios-defs-output-file", '\0', 0, G_OPTION_ARG_FILENAME,
&output_file, "The output file to store scenarios details. " &output_file, "The output file to store scenarios details. "
"Implies --list-scenarios", "Implies --list-scenarios",
@ -453,6 +457,8 @@ main (int argc, gchar ** argv)
monitor = gst_validate_monitor_factory_create (GST_OBJECT_CAST (pipeline), monitor = gst_validate_monitor_factory_create (GST_OBJECT_CAST (pipeline),
runner, NULL); 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)); gst_validate_reporter_set_handle_g_logs (GST_VALIDATE_REPORTER (monitor));
if (media_info) { if (media_info) {