3 * Copyright (C) 2013-2016 Collabora Ltd.
4 * Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>
5 * Author: Thibault Saunier <thibault.saunier@collabora.com>
7 * gst-validate-runner.c - Validate Runner class
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
33 #include "gst-validate-internal.h"
34 #include "gst-validate-report.h"
35 #include "gst-validate-monitor-factory.h"
36 #include "gst-validate-override-registry.h"
37 #include "gst-validate-runner.h"
38 #include "gst-validate-reporter.h"
39 #include "gst-validate-mockdecryptor.h"
41 GST_DEBUG_CATEGORY_STATIC (gst_validate_runner_debug);
42 #undef GST_CAT_DEFAULT
43 #define GST_CAT_DEFAULT gst_validate_runner_debug
45 static gboolean element_created = FALSE;
47 /* We create a GstValidateRunner on _init ()
48 * so that we keep backward compatibility when
49 * the user create a Runner after creating the pipeline
50 * but the runner was actually already ready to be used.
52 static GstValidateRunner *first_runner = NULL;
55 * SECTION:gst-validate-runner
56 * @short_description: Class that runs Gst Validate tests for a pipeline
58 * Allows you to test a pipeline within GstValidate. It is the object where
59 * all issue reporting is done.
61 * In the tools using GstValidate the only minimal code to be able to monitor
65 * GstPipeline *pipeline = gst_pipeline_new ("monitored-pipeline");
66 * GstValidateRunner *runner = gst_validate_runner_new ();
67 * GstValidateMonitor *monitor = gst_validate_monitor_factory_create (
68 * GST_OBJECT (pipeline), runner, NULL);
70 * // Run the pipeline and do whatever you want with it
72 * // In that same order
73 * gst_object_unref (pipeline);
74 * gst_object_unref (runner);
75 * gst_object_unref (monitor);
79 struct _GstValidateRunnerPrivate
83 GstValidateReportingDetails default_level;
84 GHashTable *reports_by_type;
86 /* A list of PatternLevel */
87 GList *report_pattern_levels;
89 /* Whether the runner was create with GST_TRACERS=validate or not) */
90 gboolean user_created;
92 gchar *pipeline_names;
93 gchar **pipeline_names_strv;
96 /* Describes the reporting level to apply to a name pattern */
97 typedef struct _PatternLevel
99 GPatternSpec *pattern;
100 GstValidateReportingDetails level;
103 #define GST_VALIDATE_RUNNER_LOCK(r) \
105 GST_LOG_OBJECT (r, "About to lock %p", &GST_VALIDATE_RUNNER_CAST(r)->priv->mutex); \
106 (g_mutex_lock (&GST_VALIDATE_RUNNER_CAST(r)->priv->mutex)); \
107 GST_LOG_OBJECT (r, "Acquired lock %p", &GST_VALIDATE_RUNNER_CAST(r)->priv->mutex); \
110 #define GST_VALIDATE_RUNNER_UNLOCK(r) \
112 GST_LOG_OBJECT (r, "About to unlock %p", &GST_VALIDATE_RUNNER_CAST(r)->priv->mutex); \
113 (g_mutex_unlock (&GST_VALIDATE_RUNNER_CAST(r)->priv->mutex)); \
114 GST_LOG_OBJECT (r, "Released lock %p", &GST_VALIDATE_RUNNER_CAST(r)->priv->mutex); \
117 #define gst_validate_runner_parent_class parent_class
118 G_DEFINE_TYPE_WITH_PRIVATE (GstValidateRunner, gst_validate_runner,
137 static GParamSpec *properties[PROP_LAST];
139 static guint _signals[LAST_SIGNAL] = { 0, };
142 gst_validate_runner_should_monitor (GstValidateRunner * self,
143 GstElement * element)
146 GstValidateMonitor *monitor;
148 if (!GST_IS_PIPELINE (element)) {
152 if (self->priv->user_created)
155 if (!self->priv->pipeline_names_strv)
158 monitor = gst_validate_get_monitor (G_OBJECT (element));
161 GST_ERROR_OBJECT (self, "Pipeline %" GST_PTR_FORMAT " is already"
162 " monitored by %" GST_PTR_FORMAT " using runner: %" GST_PTR_FORMAT
163 " NOT monitoring again.",
165 gst_validate_reporter_get_runner (GST_VALIDATE_REPORTER (monitor)));
168 for (i = 0; self->priv->pipeline_names_strv[i]; i++) {
169 if (g_pattern_match_simple (self->priv->pipeline_names_strv[i],
170 GST_OBJECT_NAME (element)))
178 do_element_new (GstValidateRunner * self, guint64 ts, GstElement * element)
180 element_created = TRUE;
181 if (gst_validate_runner_should_monitor (self, element)) {
182 /* the reference to the monitor is lost */
183 gst_validate_monitor_factory_create (GST_OBJECT_CAST (element), self, NULL);
188 _parse_reporting_level (gchar * str, GstValidateReportingDetails * level)
196 if (g_ascii_isdigit (str[0])) {
199 l = strtoul (str, &endptr, 10);
200 if (endptr > str && endptr[0] == 0) {
201 *level = (GstValidateReportingDetails) l;
205 } else if (g_ascii_strcasecmp (str, "smart") == 0) {
206 *level = GST_VALIDATE_SHOW_SMART;
207 } else if (g_ascii_strcasecmp (str, "none") == 0) {
208 *level = GST_VALIDATE_SHOW_NONE;
209 } else if (g_ascii_strcasecmp (str, "synthetic") == 0) {
210 *level = GST_VALIDATE_SHOW_SYNTHETIC;
211 } else if (g_ascii_strcasecmp (str, "subchain") == 0) {
212 *level = GST_VALIDATE_SHOW_SUBCHAIN;
213 } else if (g_ascii_strcasecmp (str, "monitor") == 0) {
214 *level = GST_VALIDATE_SHOW_MONITOR;
215 } else if (g_ascii_strcasecmp (str, "all") == 0) {
216 *level = GST_VALIDATE_SHOW_ALL;
224 _free_report_pattern_level (PatternLevel * pattern_level)
226 g_pattern_spec_free (pattern_level->pattern);
227 g_free (pattern_level);
231 _set_reporting_level_for_name (GstValidateRunner * runner,
232 const gchar * pattern, GstValidateReportingDetails level)
234 PatternLevel *pattern_level = g_malloc (sizeof (PatternLevel));
235 GPatternSpec *pattern_spec = g_pattern_spec_new (pattern);
237 pattern_level->pattern = pattern_spec;
238 pattern_level->level = level;
240 /* Allow the user to single out a pad with the "element-name__pad-name" syntax
242 if (g_strrstr (pattern, "__"))
243 runner->priv->report_pattern_levels =
244 g_list_prepend (runner->priv->report_pattern_levels, pattern_level);
246 runner->priv->report_pattern_levels =
247 g_list_append (runner->priv->report_pattern_levels, pattern_level);
251 _replace_double_colons (gchar * word)
254 word = strstr (word, "::");
263 _set_report_levels_from_string (GstValidateRunner * self, const gchar * list)
270 GST_DEBUG_OBJECT (self, "setting report levels from string [%s]", list);
272 split = g_strsplit (list, ",", 0);
274 for (walk = split; *walk; walk++) {
275 _replace_double_colons (*walk);
276 if (strchr (*walk, ':')) {
277 gchar **values = g_strsplit (*walk, ":", 2);
279 if (values[0] && values[1]) {
280 GstValidateReportingDetails level;
282 if (_parse_reporting_level (values[1], &level))
283 _set_reporting_level_for_name (self, values[0], level);
288 GstValidateReportingDetails level;
290 if (_parse_reporting_level (*walk, &level))
291 self->priv->default_level = level;
299 _init_report_levels (GstValidateRunner * self)
303 env = g_getenv ("GST_VALIDATE_REPORTING_DETAILS");
305 _set_report_levels_from_string (self, env);
309 _unref_report_list (gpointer unused, GList * reports, gpointer unused_too)
311 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
315 gst_validate_runner_finalize (GObject * object)
317 GstValidateRunner *runner = GST_VALIDATE_RUNNER_CAST (object);
319 if (!runner->priv->user_created)
320 gst_validate_runner_exit (runner, TRUE);
322 g_list_free_full (runner->priv->reports,
323 (GDestroyNotify) gst_validate_report_unref);
325 g_list_free_full (runner->priv->report_pattern_levels,
326 (GDestroyNotify) _free_report_pattern_level);
328 g_mutex_clear (&runner->priv->mutex);
330 g_free (runner->priv->pipeline_names);
331 g_strfreev (runner->priv->pipeline_names_strv);
333 g_hash_table_foreach (runner->priv->reports_by_type, (GHFunc)
334 _unref_report_list, NULL);
335 g_hash_table_destroy (runner->priv->reports_by_type);
337 G_OBJECT_CLASS (parent_class)->finalize (object);
339 if (!runner->priv->user_created)
340 gst_validate_deinit ();
344 gst_validate_runner_constructor (GType type, guint n_construct_params,
345 GObjectConstructParam * construct_params)
347 GObject *runner = G_OBJECT_CLASS (parent_class)->constructor (type,
348 n_construct_params, construct_params);
350 if (!gst_validate_is_initialized ()) {
351 first_runner = GST_VALIDATE_RUNNER (runner);
352 gst_validate_init ();
363 gst_validate_runner_get_property (GObject * object, guint prop_id,
364 GValue * value, GParamSpec * pspec)
366 GstValidateRunner *runner;
368 runner = GST_VALIDATE_RUNNER (object);
372 g_value_set_string (value, runner->priv->pipeline_names);
376 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
382 gst_validate_runner_set_property (GObject * object, guint prop_id,
383 const GValue * value, GParamSpec * pspec)
385 GstValidateRunner *runner;
387 runner = GST_VALIDATE_RUNNER (object);
391 g_free (runner->priv->pipeline_names);
392 g_strfreev (runner->priv->pipeline_names_strv);
394 runner->priv->pipeline_names = g_value_dup_string (value);
395 if (runner->priv->pipeline_names)
396 runner->priv->pipeline_names_strv =
397 g_strsplit (runner->priv->pipeline_names, ",", -1);
401 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
407 gst_validate_runner_class_init (GstValidateRunnerClass * klass)
409 GObjectClass *gobject_class;
411 gobject_class = G_OBJECT_CLASS (klass);
413 gobject_class->finalize = gst_validate_runner_finalize;
415 gobject_class->set_property = gst_validate_runner_set_property;
416 gobject_class->get_property = gst_validate_runner_get_property;
417 gobject_class->constructor = gst_validate_runner_constructor;
419 properties[PROP_PARAMS] =
420 g_param_spec_string ("params", "Params", "Extra configuration parameters",
421 NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
423 g_object_class_install_properties (gobject_class, PROP_LAST, properties);
425 _signals[REPORT_ADDED_SIGNAL] =
426 g_signal_new ("report-added", G_TYPE_FROM_CLASS (klass),
427 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1,
428 GST_TYPE_VALIDATE_REPORT);
430 _signals[STOPPING_SIGNAL] =
431 g_signal_new ("stopping", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0,
432 NULL, NULL, NULL, G_TYPE_NONE, 0);
434 GST_DEBUG_CATEGORY_INIT (gst_validate_runner_debug, "gstvalidaterunner",
435 GST_DEBUG_FG_YELLOW, "Gst validate runner");
439 gst_validate_runner_init (GstValidateRunner * runner)
441 runner->priv = gst_validate_runner_get_instance_private (runner);
443 runner->priv->reports_by_type = g_hash_table_new (g_direct_hash,
446 runner->priv->default_level = GST_VALIDATE_SHOW_DEFAULT;
447 _init_report_levels (runner);
449 gst_tracing_register_hook (GST_TRACER (runner), "element-new",
450 G_CALLBACK (do_element_new));
452 gst_element_register (NULL, GST_MOCKDECRYPTOR_NAME, GST_RANK_MARGINAL,
453 GST_TYPE_MOCKDECRYPTOR);
457 * gst_validate_runner_new:
459 * Create a new #GstValidateRunner
461 * Returns: A newly created #GstValidateRunner
464 gst_validate_runner_new (void)
466 GstValidateRunner *runner;
469 runner = first_runner;
471 } else if (element_created) {
472 g_error ("Should never create a GstValidateRunner after a GstElement "
473 "has been created in the same process.");
477 runner = g_object_new (GST_TYPE_VALIDATE_RUNNER, NULL);
478 runner->priv->user_created = TRUE;
482 GstValidateOverrideRegistry *registry =
483 gst_validate_override_registry_get ();
484 GList *all_overrides =
485 gst_validate_override_registry_get_override_list (registry);
487 for (i = all_overrides; i; i = i->next) {
488 GstValidateOverride *override = (GstValidateOverride *) i->data;
489 gst_validate_reporter_set_runner (GST_VALIDATE_REPORTER (override),
492 g_list_free (all_overrides);
499 * gst_validate_runner_get_default_reporting_level:
501 * Returns: the default #GstValidateReportingDetails used to output a report.
503 GstValidateReportingDetails
504 gst_validate_runner_get_default_reporting_level (GstValidateRunner * runner)
506 g_return_val_if_fail (GST_IS_VALIDATE_RUNNER (runner),
507 GST_VALIDATE_SHOW_UNKNOWN);
509 return runner->priv->default_level;
513 * gst_validate_runner_get_reporting_level_for_name:
515 * Returns: the #GstValidateReportingDetails that will be applied for a given name.
516 * If no pattern was set for such a name, this function will return
517 * #GST_VALIDATE_SHOW_UNKNOWN, and reporting for that name will
518 * default to the global reporting level.
520 GstValidateReportingDetails
521 gst_validate_runner_get_reporting_level_for_name (GstValidateRunner * runner,
527 g_return_val_if_fail (GST_IS_VALIDATE_RUNNER (runner),
528 GST_VALIDATE_SHOW_UNKNOWN);
530 fixed_name = g_strdup (name);
531 _replace_double_colons (fixed_name);
532 for (tmp = runner->priv->report_pattern_levels; tmp; tmp = tmp->next) {
533 PatternLevel *pattern_level = (PatternLevel *) tmp->data;
534 if (g_pattern_match_string (pattern_level->pattern, fixed_name)) {
537 return pattern_level->level;
542 return GST_VALIDATE_SHOW_UNKNOWN;
546 synthesize_reports (GstValidateRunner * runner, GstValidateReport * report)
548 GstValidateIssueId issue_id;
551 issue_id = report->issue->issue_id;
553 GST_VALIDATE_RUNNER_LOCK (runner);
555 g_hash_table_lookup (runner->priv->reports_by_type,
556 (gconstpointer) issue_id);
557 reports = g_list_append (reports, gst_validate_report_ref (report));
558 g_hash_table_insert (runner->priv->reports_by_type, (gpointer) issue_id,
560 GST_VALIDATE_RUNNER_UNLOCK (runner);
564 _dot_pipeline (GstValidateReport * report, GstStructure * config)
566 GstPipeline *pipeline = gst_validate_reporter_get_pipeline (report->reporter);
569 gint details = GST_DEBUG_GRAPH_SHOW_ALL;
570 gchar *reporter_basename =
571 g_path_get_basename (gst_validate_reporter_get_name (report->reporter));
572 report->dotfile_name =
573 g_strdup_printf ("%" GST_TIME_FORMAT "-validate-report-%s-on-%s-%s",
574 GST_TIME_ARGS (GST_CLOCK_DIFF (_priv_start_time,
575 gst_util_get_timestamp ())),
576 gst_validate_report_level_get_name (report->level), reporter_basename,
577 g_quark_to_string (report->issue->issue_id));
579 g_free (reporter_basename);
582 gst_structure_get_int (config, "details", &details);
584 GST_DEBUG_BIN_TO_DOT_FILE (GST_BIN (pipeline),
585 GST_DEBUG_GRAPH_SHOW_ALL, report->dotfile_name);
587 gst_object_unref (pipeline);
593 gst_validate_runner_maybe_dot_pipeline (GstValidateRunner * runner,
594 GstValidateReport * report)
598 if (report->level == GST_VALIDATE_REPORT_LEVEL_CRITICAL ||
599 gst_validate_report_check_abort (report)) {
601 _dot_pipeline (report, NULL);
605 for (config = gst_validate_plugin_get_config (NULL);
606 config; config = config->next) {
608 if (gst_structure_has_name (config->data, "core")) {
609 GstValidateReportLevel level;
610 const gchar *level_str,
611 *action = gst_structure_get_string (config->data, "action");
613 if (g_strcmp0 (action, "dot-pipeline"))
616 level_str = gst_structure_get_string (config->data, "report-level");
617 level = level_str ? gst_validate_report_level_from_name (level_str) :
618 GST_VALIDATE_REPORT_LEVEL_CRITICAL;
620 if (level >= report->level) {
621 _dot_pipeline (report, config->data);
630 gst_validate_runner_add_report (GstValidateRunner * runner,
631 GstValidateReport * report)
633 GstValidateReportingDetails details, reporter_details, issue_type_details;
635 g_return_if_fail (GST_IS_VALIDATE_RUNNER (runner));
637 gst_validate_send (json_boxed_serialize (GST_MINI_OBJECT_TYPE (report),
639 gst_validate_runner_maybe_dot_pipeline (runner, report);
641 details = reporter_details =
642 gst_validate_reporter_get_reporting_level (report->reporter);
644 gst_validate_runner_get_reporting_level_for_name (runner,
645 g_quark_to_string (report->issue->issue_id));
647 if (reporter_details == GST_VALIDATE_SHOW_UNKNOWN)
648 details = issue_type_details;
650 /* Let's use our own reporting strategy */
651 if (details == GST_VALIDATE_SHOW_UNKNOWN) {
652 gst_validate_report_set_reporting_level (report,
653 runner->priv->default_level);
654 switch (runner->priv->default_level) {
655 case GST_VALIDATE_SHOW_NONE:
657 case GST_VALIDATE_SHOW_SMART:
658 if (!gst_validate_report_check_abort (report) &&
659 report->level != GST_VALIDATE_REPORT_LEVEL_CRITICAL &&
661 synthesize_reports (runner, report);
665 case GST_VALIDATE_SHOW_SYNTHETIC:
666 if (!report->trace) {
667 synthesize_reports (runner, report);
673 } else if (details == GST_VALIDATE_SHOW_NONE) {
674 GST_DEBUG ("Not reporting.");
678 GST_VALIDATE_RUNNER_LOCK (runner);
679 runner->priv->reports =
680 g_list_append (runner->priv->reports, gst_validate_report_ref (report));
681 GST_VALIDATE_RUNNER_UNLOCK (runner);
683 g_signal_emit (runner, _signals[REPORT_ADDED_SIGNAL], 0, report);
687 * gst_validate_runner_get_reports_count:
688 * @runner: The $GstValidateRunner to get the number of reports from
690 * Get the number of reports present in the runner:
692 * Returns: The number of reports present in the runner.
695 gst_validate_runner_get_reports_count (GstValidateRunner * runner)
700 g_return_val_if_fail (GST_IS_VALIDATE_RUNNER (runner), 0);
702 GST_VALIDATE_RUNNER_LOCK (runner);
703 l = g_list_length (runner->priv->reports);
704 for (tmp = runner->priv->reports; tmp; tmp = tmp->next) {
705 GstValidateReport *report = (GstValidateReport *) tmp->data;
706 l += g_list_length (report->repeated_reports);
708 l += g_hash_table_size (runner->priv->reports_by_type);
709 GST_VALIDATE_RUNNER_UNLOCK (runner);
715 * gst_validate_runner_get_reports:
716 * @runner: The #GstValidateRunner
718 * Return: (element-type GstValidateReport)(transfer full): all the reports
721 gst_validate_runner_get_reports (GstValidateRunner * runner)
725 GST_VALIDATE_RUNNER_LOCK (runner);
727 g_list_copy_deep (runner->priv->reports,
728 (GCopyFunc) gst_validate_report_ref, NULL);
729 GST_VALIDATE_RUNNER_UNLOCK (runner);
735 _do_report_synthesis (GstValidateRunner * runner)
738 GList *reports, *tmp;
740 GList *criticals = NULL;
742 /* Take the lock so the hash table won't be modified while we are iterating
744 GST_VALIDATE_RUNNER_LOCK (runner);
745 g_hash_table_iter_init (&iter, runner->priv->reports_by_type);
746 while (g_hash_table_iter_next (&iter, &key, &value)) {
747 GstValidateReport *report;
748 reports = (GList *) value;
753 report = (GstValidateReport *) (reports->data);
755 gst_validate_report_print_level (report);
756 gst_validate_report_print_detected_on (report);
758 if (report->level == GST_VALIDATE_REPORT_LEVEL_CRITICAL) {
759 criticals = g_list_append (criticals, report);
760 gst_validate_report_print_details (report);
763 for (tmp = g_list_next (reports); tmp; tmp = tmp->next) {
764 report = (GstValidateReport *) tmp->data;
765 gst_validate_report_print_detected_on (report);
767 if (report->level == GST_VALIDATE_REPORT_LEVEL_CRITICAL) {
768 criticals = g_list_append (criticals, report);
769 gst_validate_report_print_details (report);
772 report = (GstValidateReport *) (reports->data);
773 gst_validate_report_print_description (report);
774 gst_validate_printf (NULL, "\n");
776 GST_VALIDATE_RUNNER_UNLOCK (runner);
782 * gst_validate_runner_printf:
783 * @runner: The #GstValidateRunner to print all the reports for
785 * Prints all the reports on the terminal or on wherever is set
786 * in the #GST_VALIDATE_FILE env variable.
788 * Returns: 0 if no critical error has been found and 18 if a critical
789 * error has been detected. That return value is usually to be used as
790 * exit code of the application.
793 gst_validate_runner_printf (GstValidateRunner * runner)
795 GList *reports, *tmp;
797 GList *criticals = NULL;
799 g_return_val_if_fail (GST_IS_VALIDATE_RUNNER (runner), 1);
801 criticals = _do_report_synthesis (runner);
802 reports = gst_validate_runner_get_reports (runner);
803 for (tmp = reports; tmp; tmp = tmp->next) {
804 GstValidateReport *report = (GstValidateReport *) tmp->data;
806 if (gst_validate_report_should_print (report))
807 gst_validate_report_printf (report);
809 if (report->level == GST_VALIDATE_REPORT_LEVEL_CRITICAL) {
810 criticals = g_list_append (criticals, report);
816 g_printerr ("\n\n==== Got criticals. Return value set to 18 ====\n");
818 for (iter = criticals; iter; iter = iter->next) {
819 g_printerr (" Critical error %s\n",
820 ((GstValidateReport *) (iter->data))->message);
825 g_list_free_full (reports, (GDestroyNotify) gst_validate_report_unref);
826 g_list_free (criticals);
827 gst_validate_printf (NULL, "Issues found: %u\n",
828 gst_validate_runner_get_reports_count (runner));
833 gst_validate_runner_exit (GstValidateRunner * runner, gboolean print_result)
836 g_return_val_if_fail (GST_IS_VALIDATE_RUNNER (runner), 1);
837 g_signal_emit (runner, _signals[STOPPING_SIGNAL], 0);
839 ret = gst_validate_runner_printf (runner);
842 for (tmp = runner->priv->reports; tmp; tmp = tmp->next) {
843 GstValidateReport *report = (GstValidateReport *) tmp->data;
844 if (report->level == GST_VALIDATE_REPORT_LEVEL_CRITICAL)
853 gst_validate_init_runner (void)
856 first_runner = g_object_new (GST_TYPE_VALIDATE_RUNNER, NULL);
857 first_runner->priv->user_created = TRUE;
858 } /* else the first runner has been created through the GST_TRACERS system */
862 gst_validate_deinit_runner (void)
864 g_clear_object (&first_runner);
867 GstValidateReportingDetails
868 gst_validate_runner_get_default_reporting_details (GstValidateRunner * runner)
870 g_return_val_if_fail (GST_IS_VALIDATE_RUNNER (runner),
871 GST_VALIDATE_SHOW_UNKNOWN);
873 return runner->priv->default_level;
876 #ifdef __GST_VALIDATE_PLUGIN
878 plugin_init (GstPlugin * plugin)
880 if (!gst_tracer_register (plugin, "validate", GST_TYPE_VALIDATE_RUNNER))
886 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, validatetracer,
887 "GStreamer Validate tracers", plugin_init, VERSION, GST_LICENSE,
888 GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
889 #endif /* __GST_VALIDATE_PLUGIN */