gstreamer/validate/plugins/extra_checks/gstvalidateextrachecks.c
Thibault Saunier b1b696017c validate: Add a plugin with potential extra checks
And add a way to check that a configured number of instances of a particular
element is used, this is useful to make sure for example that playing a
particular stream doesn't lead to several decoders being instanciated.
2017-06-16 17:36:34 -04:00

168 lines
4.7 KiB
C

#include <gst/gst.h>
#include "../../gst/validate/validate.h"
#include "../../gst/validate/gst-validate-utils.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define EXTRA_CHECKS_WRONG_NUMBER_OF_INSTANCES g_quark_from_static_string ("extrachecks::wrong-number-of-instances")
typedef struct
{
gchar *pname;
gchar *klass;
gint expected_n_instances;
gint n_instances;
} CheckNumInstanceData;
static CheckNumInstanceData *
gst_validate_check_num_instances_data_new (GstStructure * check)
{
CheckNumInstanceData *data = g_new0 (CheckNumInstanceData, 1);
if (!gst_structure_get_int (check, "num-instances",
&data->expected_n_instances)) {
g_error ("[CONFIG ERROR] Mandatory field `num-instances` not found in "
"extra-check `num-instances`");
goto failed;
}
data->pname = g_strdup (gst_structure_get_string (check, "pipeline-name"));
if (!data->pname) {
g_error ("[CONFIG ERROR] Mandatory field `pipeline` not found in "
"extra-check `num-instances`");
goto failed;
}
data->klass = g_strdup (gst_structure_get_string (check, "element-klass"));
if (!data->klass) {
g_error ("[CONFIG ERROR] Mandatory field `element-klass` not found in "
"extra-check `num-instances`");
goto failed;
}
return data;
failed:
g_free (data);
g_free (data->klass);
return NULL;
}
static void
gst_validate_check_num_instances_data_free (CheckNumInstanceData * data)
{
g_free (data->pname);
g_free (data);
}
static void
gst_validate_check_num_instances (GstValidateOverride * o,
GstValidateMonitor * monitor, GstElement * nelem)
{
gchar *pname;
CheckNumInstanceData *data = g_object_get_data (G_OBJECT (o), "check-data");
GstPipeline *pipe = gst_validate_monitor_get_pipeline (monitor);
if (!pipe)
return;
pname = gst_object_get_name (GST_OBJECT (pipe));
if (g_strcmp0 (data->pname, pname))
goto done;
if (!gst_validate_element_has_klass (nelem, data->klass))
return;
data->n_instances++;
if (data->n_instances > data->expected_n_instances) {
GST_VALIDATE_REPORT (o, EXTRA_CHECKS_WRONG_NUMBER_OF_INSTANCES,
"%d instances allows in pipeline %s but already %d where added.",
data->expected_n_instances, pname, data->n_instances);
}
GST_ERROR_OBJECT (nelem, "HERE I AM %d", data->n_instances);
done:
g_free (pname);
gst_object_unref (pipe);
}
static void
runner_stopping (GstValidateRunner * runner, GstValidateOverride * o)
{
CheckNumInstanceData *data = g_object_get_data (G_OBJECT (o), "check-data");
if (data->expected_n_instances != data->n_instances) {
GST_VALIDATE_REPORT (o, EXTRA_CHECKS_WRONG_NUMBER_OF_INSTANCES,
"%d instances expected in pipeline %s but %d where added.",
data->expected_n_instances, data->pname, data->n_instances);
}
}
static void
_runner_set (GObject * object, GParamSpec * pspec, gpointer user_data)
{
GstValidateRunner *runner =
gst_validate_reporter_get_runner (GST_VALIDATE_REPORTER (object));
g_signal_connect (runner, "stopping", G_CALLBACK (runner_stopping), object);
gst_object_unref (runner);
}
static void
gst_validate_add_num_instances_check (GstStructure * structure)
{
CheckNumInstanceData *data =
gst_validate_check_num_instances_data_new (structure);
GstValidateOverride *o = gst_validate_override_new ();
g_object_set_data_full (G_OBJECT (o), "check-data", data,
(GDestroyNotify) gst_validate_check_num_instances_data_free);
gst_validate_override_set_element_added_handler (o,
gst_validate_check_num_instances);
g_signal_connect (o, "notify::validate-runner", G_CALLBACK (_runner_set),
NULL);
gst_validate_override_register_by_type (GST_TYPE_BIN, o);
gst_object_unref (o);
}
static gboolean
gst_validate_extra_checks_init (GstPlugin * plugin)
{
GList *config, *tmp;
config = gst_validate_plugin_get_config (plugin);
if (!config)
return TRUE;
for (tmp = config; tmp; tmp = tmp->next) {
GstStructure *check = tmp->data;
if (gst_structure_has_field (check, "num-instances"))
gst_validate_add_num_instances_check (check);
}
gst_validate_issue_register (gst_validate_issue_new
(EXTRA_CHECKS_WRONG_NUMBER_OF_INSTANCES,
"The configured number of possible instances of an element type"
" in a pipeline is not respected.",
"The `num-instances` extra checks allow user to make sure that"
" a previously defined number of instances of an element is added"
" in a given pipeline, that test failed.",
GST_VALIDATE_REPORT_LEVEL_CRITICAL));
return TRUE;
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
extrachecks,
"GstValidate plugin that implements extra, configurable tests.",
gst_validate_extra_checks_init, VERSION, "LGPL", GST_PACKAGE_NAME,
GST_PACKAGE_ORIGIN)