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,
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)));
}

View file

@ -58,6 +58,7 @@ struct _GstValidateBinMonitor {
/*< private >*/
gulong element_added_id;
gulong element_removed_id;
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
#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__ */

View file

@ -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;

View file

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

View file

@ -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)

View file

@ -68,6 +68,8 @@ struct _GstValidatePipelineMonitor {
GstStreamCollection *stream_collection;
/* Latest GstStream received from GST_MESSAGE_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')
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',

View file

@ -7,6 +7,7 @@
#include <gst/validate/gst-validate-types.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-monitor-factory.h>

View file

@ -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) {