b6b75f6ba04444b331aa179cfa72458fd1b73a87
[platform/upstream/gstreamer.git] / validate / gst / validate / gst-validate-monitor.c
1 /* GStreamer
2  *
3  * Copyright (C) 2013 Collabora Ltd.
4  *  Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>
5  *
6  * gst-validate-monitor.c - Validate Monitor class
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27
28 #include "gst-validate-enum-types.h"
29 #include "gst-validate-internal.h"
30 #include "gst-validate-monitor.h"
31 #include "gst-validate-override-registry.h"
32
33 /**
34  * SECTION:gst-validate-monitor
35  * @short_description: Base class that wraps a #GObject for Validate checks
36  *
37  * TODO
38  */
39
40 enum
41 {
42   PROP_0,
43   PROP_OBJECT,
44   PROP_PIPELINE,
45   PROP_RUNNER,
46   PROP_VALIDATE_PARENT,
47   PROP_VERBOSITY,
48   PROP_LAST
49 };
50
51 static gboolean gst_validate_monitor_do_setup (GstValidateMonitor * monitor);
52 static void
53 gst_validate_monitor_get_property (GObject * object, guint prop_id,
54     GValue * value, GParamSpec * pspec);
55 static void
56 gst_validate_monitor_set_property (GObject * object, guint prop_id,
57     const GValue * value, GParamSpec * pspec);
58 static GObject *gst_validate_monitor_constructor (GType type,
59     guint n_construct_params, GObjectConstructParam * construct_params);
60
61 static gboolean gst_validate_monitor_setup (GstValidateMonitor * monitor);
62
63 static GstValidateInterceptionReturn
64 gst_validate_monitor_intercept_report (GstValidateReporter * reporter,
65     GstValidateReport * report);
66
67 #define _do_init \
68   G_IMPLEMENT_INTERFACE (GST_TYPE_VALIDATE_REPORTER, _reporter_iface_init)
69
70 static GstValidateReportingDetails
71 _get_reporting_level (GstValidateReporter * monitor)
72 {
73   return GST_VALIDATE_MONITOR (monitor)->level;
74 }
75
76 /**
77  * gst_validate_monitor_get_pipeline:
78  * @monitor: The monitor to get the pipeline from
79  *
80  * Returns: (transfer full): The pipeline in which @monitor
81  * target is in.
82  */
83 GstPipeline *
84 gst_validate_monitor_get_pipeline (GstValidateMonitor * monitor)
85 {
86   return g_weak_ref_get (&monitor->pipeline);
87 }
88
89 /**
90  * gst_validate_monitor_get_target:
91  * @monitor: The monitor to get the target from
92  *
93  * Returns: (transfer full): The target object
94  */
95 GstObject *
96 gst_validate_monitor_get_target (GstValidateMonitor * monitor)
97 {
98   return g_weak_ref_get (&monitor->target);
99 }
100
101 static GstPipeline *
102 _get_pipeline (GstValidateReporter * monitor)
103 {
104   return g_weak_ref_get (&(GST_VALIDATE_MONITOR (monitor)->pipeline));
105 }
106
107 static void
108 _reporter_iface_init (GstValidateReporterInterface * iface)
109 {
110   iface->intercept_report = gst_validate_monitor_intercept_report;
111   iface->get_reporting_level = _get_reporting_level;
112   iface->get_pipeline = _get_pipeline;
113 }
114
115 #define gst_validate_monitor_parent_class parent_class
116 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstValidateMonitor, gst_validate_monitor,
117     GST_TYPE_OBJECT, _do_init);
118
119 static void
120 gst_validate_monitor_dispose (GObject * object)
121 {
122   GstValidateMonitor *monitor = GST_VALIDATE_MONITOR_CAST (object);
123
124   g_mutex_clear (&monitor->mutex);
125   g_mutex_clear (&monitor->overrides_mutex);
126   g_queue_clear (&monitor->overrides);
127
128   g_weak_ref_clear (&monitor->pipeline);
129   g_weak_ref_clear (&monitor->target);
130
131   if (monitor->media_descriptor)
132     gst_object_unref (monitor->media_descriptor);
133
134   G_OBJECT_CLASS (parent_class)->dispose (object);
135 }
136
137 static void
138 gst_validate_monitor_finalize (GObject * object)
139 {
140   gst_validate_reporter_set_name (GST_VALIDATE_REPORTER (object), NULL);
141
142   G_OBJECT_CLASS (parent_class)->finalize (object);
143 }
144
145 static void
146 gst_validate_monitor_class_init (GstValidateMonitorClass * klass)
147 {
148   GObjectClass *gobject_class;
149
150   gobject_class = G_OBJECT_CLASS (klass);
151
152   gobject_class->get_property = gst_validate_monitor_get_property;
153   gobject_class->set_property = gst_validate_monitor_set_property;
154   gobject_class->dispose = gst_validate_monitor_dispose;
155   gobject_class->finalize = gst_validate_monitor_finalize;
156   gobject_class->constructor = gst_validate_monitor_constructor;
157
158   klass->setup = gst_validate_monitor_do_setup;
159
160   g_object_class_install_property (gobject_class, PROP_OBJECT,
161       g_param_spec_object ("object", "Object", "The object to be monitored",
162           G_TYPE_OBJECT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
163
164   g_object_class_install_property (gobject_class, PROP_PIPELINE,
165       g_param_spec_object ("pipeline", "Pipeline", "The pipeline in which the"
166           "monitored object is", GST_TYPE_PIPELINE,
167           G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
168
169   g_object_class_install_property (gobject_class, PROP_RUNNER,
170       g_param_spec_object ("validate-runner", "VALIDATE Runner",
171           "The Validate runner to report errors to",
172           GST_TYPE_VALIDATE_RUNNER,
173           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
174
175   g_object_class_install_property (gobject_class, PROP_VALIDATE_PARENT,
176       g_param_spec_object ("validate-parent", "VALIDATE parent monitor",
177           "The Validate monitor that is the parent of this one",
178           GST_TYPE_VALIDATE_MONITOR,
179           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
180
181   g_object_class_install_property (gobject_class, PROP_VERBOSITY,
182       g_param_spec_flags ("verbosity", "Verbosity",
183           "The verbosity of GstValidate on the monitor",
184           GST_TYPE_VALIDATE_VERBOSITY_FLAGS,
185           GST_VALIDATE_VERBOSITY_POSITION, G_PARAM_READWRITE));
186 }
187
188 static GObject *
189 gst_validate_monitor_constructor (GType type, guint n_construct_params,
190     GObjectConstructParam * construct_params)
191 {
192   GstObject *target;
193   GstValidateMonitor *monitor =
194       GST_VALIDATE_MONITOR_CAST (G_OBJECT_CLASS (parent_class)->constructor
195       (type,
196           n_construct_params,
197           construct_params));
198
199   if (monitor->parent) {
200     GstPipeline *parent_pipeline =
201         gst_validate_monitor_get_pipeline (monitor->parent);
202
203     gst_validate_monitor_set_media_descriptor (monitor,
204         monitor->parent->media_descriptor);
205
206     if (parent_pipeline) {
207       g_weak_ref_init (&monitor->pipeline, parent_pipeline);
208
209       gst_object_unref (parent_pipeline);
210     }
211   }
212
213   gst_validate_monitor_setup (monitor);
214   gst_validate_override_registry_attach_overrides (monitor);
215
216   target = gst_validate_monitor_get_target (monitor);
217   g_object_set_data ((GObject *) target, "validate-monitor", monitor);
218   gst_object_unref (target);
219
220   return (GObject *) monitor;
221 }
222
223 static void
224 gst_validate_monitor_init (GstValidateMonitor * monitor)
225 {
226   g_mutex_init (&monitor->mutex);
227
228   g_mutex_init (&monitor->overrides_mutex);
229   g_queue_init (&monitor->overrides);
230
231   monitor->verbosity = GST_VALIDATE_VERBOSITY_POSITION;
232 }
233
234 static gboolean
235 gst_validate_monitor_do_setup (GstValidateMonitor * monitor)
236 {
237   /* NOP */
238   return TRUE;
239 }
240
241 static GstValidateReportingDetails
242 _get_report_level_for_pad (GstValidateRunner * runner, GstObject * pad)
243 {
244   gchar *name;
245   GstValidateReportingDetails level = GST_VALIDATE_SHOW_UNKNOWN;
246
247   name = g_strdup_printf ("%s__%s", GST_DEBUG_PAD_NAME (pad));
248   level = gst_validate_runner_get_reporting_level_for_name (runner, name);
249
250   g_free (name);
251   return level;
252 }
253
254 static void
255 _determine_reporting_level (GstValidateMonitor * monitor)
256 {
257   GstValidateRunner *runner;
258   GstObject *object, *parent;
259   gchar *object_name;
260   GstValidateReportingDetails level = GST_VALIDATE_SHOW_UNKNOWN;
261
262   object = gst_validate_monitor_get_target (monitor);
263   runner = gst_validate_reporter_get_runner (GST_VALIDATE_REPORTER (monitor));
264
265   do {
266     if (!GST_IS_OBJECT (object))
267       break;
268
269     /* Let's allow for singling out pads */
270     if (GST_IS_PAD (object)) {
271       level = _get_report_level_for_pad (runner, object);
272       if (level != GST_VALIDATE_SHOW_UNKNOWN)
273         break;
274     }
275
276     object_name = gst_object_get_name (object);
277     level = gst_validate_runner_get_reporting_level_for_name (runner,
278         object_name);
279     parent = gst_object_get_parent (object);
280     gst_object_unref (object);
281     object = parent;
282     g_free (object_name);
283   } while (object && level == GST_VALIDATE_SHOW_UNKNOWN);
284
285   if (object)
286     gst_object_unref (object);
287
288   if (runner)
289     gst_object_unref (runner);
290
291   monitor->level = level;
292 }
293
294 gboolean
295 gst_validate_monitor_setup (GstValidateMonitor * monitor)
296 {
297   GList *config;
298
299   GST_DEBUG_OBJECT (monitor, "Starting monitor setup");
300
301   for (config = gst_validate_plugin_get_config (NULL); config;
302       config = config->next) {
303     const gchar *verbosity =
304         gst_structure_get_string (GST_STRUCTURE (config->data),
305         "verbosity");
306
307     if (verbosity)
308       gst_util_set_object_arg (G_OBJECT (monitor), "verbosity", verbosity);
309   }
310
311   /* For now we just need to do this at setup time */
312   _determine_reporting_level (monitor);
313   return GST_VALIDATE_MONITOR_GET_CLASS (monitor)->setup (monitor);
314 }
315
316 /**
317  * gst_validate_monitor_get_element
318  * @monitor: The monitor
319  *
320  * Returns: (transfer none): The GstElement associated with @monitor
321  */
322 GstElement *
323 gst_validate_monitor_get_element (GstValidateMonitor * monitor)
324 {
325   GstValidateMonitorClass *klass = GST_VALIDATE_MONITOR_GET_CLASS (monitor);
326   GstElement *element = NULL;
327
328   if (klass->get_element)
329     element = klass->get_element (monitor);
330
331   return element;
332 }
333
334 gchar *
335 gst_validate_monitor_get_element_name (GstValidateMonitor * monitor)
336 {
337   gchar *res = NULL;
338   GstElement *element;
339
340   element = gst_validate_monitor_get_element (monitor);
341   if (element) {
342     res = g_strdup (GST_ELEMENT_NAME (element));
343     gst_object_unref (element);
344   }
345
346   return res;
347 }
348
349 /* Check if any of our overrides wants to change the report severity */
350 static GstValidateInterceptionReturn
351 gst_validate_monitor_intercept_report (GstValidateReporter * reporter,
352     GstValidateReport * report)
353 {
354   GList *iter;
355   GstValidateMonitor *monitor = GST_VALIDATE_MONITOR_CAST (reporter);
356
357   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (monitor);
358   for (iter = monitor->overrides.head; iter; iter = g_list_next (iter)) {
359     report->level =
360         gst_validate_override_get_severity (iter->data,
361         gst_validate_issue_get_id (report->issue), report->level);
362   }
363   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (monitor);
364
365   return GST_VALIDATE_REPORTER_REPORT;
366 }
367
368 void
369 gst_validate_monitor_attach_override (GstValidateMonitor * monitor,
370     GstValidateOverride * override)
371 {
372   GstValidateRunner *runner;
373   GstValidateRunner *mrunner;
374
375   if (!gst_validate_override_can_attach (override, monitor)) {
376     GST_INFO_OBJECT (monitor, "Can not attach override %s",
377         gst_validate_reporter_get_name (GST_VALIDATE_REPORTER (override)));
378
379     return;
380   }
381
382   runner = gst_validate_reporter_get_runner (GST_VALIDATE_REPORTER (override));
383   mrunner = gst_validate_reporter_get_runner (GST_VALIDATE_REPORTER (monitor));
384   GST_VALIDATE_MONITOR_OVERRIDES_LOCK (monitor);
385   if (runner) {
386     g_assert (runner == mrunner);
387   } else
388     gst_validate_reporter_set_runner (GST_VALIDATE_REPORTER (override),
389         mrunner);
390   g_queue_push_tail (&monitor->overrides, override);
391   GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (monitor);
392
393   if (runner)
394     gst_object_unref (runner);
395   if (mrunner)
396     gst_object_unref (mrunner);
397   gst_validate_override_attached (override);
398 }
399
400 static void
401 gst_validate_monitor_set_property (GObject * object, guint prop_id,
402     const GValue * value, GParamSpec * pspec)
403 {
404   GstValidateMonitor *monitor;
405
406   monitor = GST_VALIDATE_MONITOR_CAST (object);
407
408   switch (prop_id) {
409     case PROP_OBJECT:
410     {
411       GstObject *target;
412
413       target = g_value_get_object (value);
414
415       g_assert (gst_validate_monitor_get_target (monitor) == NULL);
416       g_weak_ref_init (&monitor->target, target);
417
418       if (GST_IS_OBJECT (target))
419         gst_validate_reporter_set_name (GST_VALIDATE_REPORTER (monitor),
420             gst_object_get_name (target));
421
422       break;
423     }
424     case PROP_PIPELINE:
425       g_weak_ref_init (&monitor->pipeline, g_value_get_object (value));
426       break;
427     case PROP_RUNNER:
428       gst_validate_reporter_set_runner (GST_VALIDATE_REPORTER (monitor),
429           g_value_get_object (value));
430       break;
431     case PROP_VALIDATE_PARENT:
432       monitor->parent = g_value_get_object (value);
433       break;
434     case PROP_VERBOSITY:
435       monitor->verbosity = g_value_get_flags (value);
436       break;
437     default:
438       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
439       break;
440   }
441 }
442
443 static void
444 gst_validate_monitor_get_property (GObject * object, guint prop_id,
445     GValue * value, GParamSpec * pspec)
446 {
447   GstValidateMonitor *monitor;
448
449   monitor = GST_VALIDATE_MONITOR_CAST (object);
450
451   switch (prop_id) {
452     case PROP_OBJECT:
453       g_value_take_object (value, gst_validate_monitor_get_target (monitor));
454       break;
455     case PROP_PIPELINE:
456       g_value_take_object (value, gst_validate_monitor_get_pipeline (monitor));
457       break;
458     case PROP_RUNNER:
459       g_value_take_object (value,
460           gst_validate_reporter_get_runner (GST_VALIDATE_REPORTER (monitor)));
461       break;
462     case PROP_VALIDATE_PARENT:
463       g_value_set_object (value, GST_VALIDATE_MONITOR_GET_PARENT (monitor));
464       break;
465     case PROP_VERBOSITY:
466       g_value_set_flags (value, monitor->verbosity);
467       break;
468     default:
469       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
470       break;
471   }
472 }
473
474 void
475 gst_validate_monitor_set_media_descriptor (GstValidateMonitor * monitor,
476     GstValidateMediaDescriptor * media_descriptor)
477 {
478   GstValidateMonitorClass *klass = GST_VALIDATE_MONITOR_GET_CLASS (monitor);
479
480   GST_DEBUG_OBJECT (monitor, "Set media desc: %" GST_PTR_FORMAT,
481       media_descriptor);
482   if (monitor->media_descriptor)
483     gst_object_unref (monitor->media_descriptor);
484
485   if (media_descriptor)
486     gst_object_ref (media_descriptor);
487
488   monitor->media_descriptor = media_descriptor;
489   if (klass->set_media_descriptor)
490     klass->set_media_descriptor (monitor, media_descriptor);
491 }
492
493 GstValidateMonitor *
494 gst_validate_get_monitor (GObject * object)
495 {
496   return GST_VALIDATE_MONITOR (g_object_get_data (object, "validate-monitor"));
497 }