--- /dev/null
+#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)