mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-21 11:30:18 +00:00
e247122051
That will allow us to add more flexibility regarding the way we report thing to the user and will allow us to properly make reports per pipeline.
453 lines
13 KiB
C
453 lines
13 KiB
C
/* GStreamer
|
|
*
|
|
* Copyright (C) 2013 Collabora Ltd.
|
|
* Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>
|
|
*
|
|
* gst-validate-monitor.c - Validate Monitor class
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include "gst-validate-internal.h"
|
|
#include "gst-validate-monitor.h"
|
|
|
|
/**
|
|
* SECTION:gst-validate-monitor
|
|
* @short_description: Base class that wraps a #GObject for Validate checks
|
|
*
|
|
* TODO
|
|
*/
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_OBJECT,
|
|
PROP_PIPELINE,
|
|
PROP_RUNNER,
|
|
PROP_VALIDATE_PARENT,
|
|
PROP_LAST
|
|
};
|
|
|
|
static gboolean gst_validate_monitor_do_setup (GstValidateMonitor * monitor);
|
|
static void
|
|
gst_validate_monitor_get_property (GObject * object, guint prop_id,
|
|
GValue * value, GParamSpec * pspec);
|
|
static void
|
|
gst_validate_monitor_set_property (GObject * object, guint prop_id,
|
|
const GValue * value, GParamSpec * pspec);
|
|
static GObject *gst_validate_monitor_constructor (GType type,
|
|
guint n_construct_params, GObjectConstructParam * construct_params);
|
|
|
|
gboolean gst_validate_monitor_setup (GstValidateMonitor * monitor);
|
|
|
|
static GstValidateInterceptionReturn
|
|
gst_validate_monitor_intercept_report (GstValidateReporter * reporter,
|
|
GstValidateReport * report);
|
|
|
|
#define _do_init \
|
|
G_IMPLEMENT_INTERFACE (GST_TYPE_VALIDATE_REPORTER, _reporter_iface_init)
|
|
|
|
static GstValidateReportingDetails
|
|
_get_reporting_level (GstValidateReporter * monitor)
|
|
{
|
|
return GST_VALIDATE_MONITOR (monitor)->level;
|
|
}
|
|
|
|
static GstPipeline *
|
|
_get_pipeline (GstValidateReporter * monitor)
|
|
{
|
|
GstPipeline *pipeline;
|
|
|
|
GST_OBJECT_LOCK (monitor);
|
|
pipeline = GST_VALIDATE_MONITOR (monitor)->pipeline;
|
|
if (pipeline)
|
|
gst_object_ref (pipeline);
|
|
GST_OBJECT_UNLOCK (monitor);
|
|
|
|
return pipeline;
|
|
}
|
|
|
|
static void
|
|
_reporter_iface_init (GstValidateReporterInterface * iface)
|
|
{
|
|
iface->intercept_report = gst_validate_monitor_intercept_report;
|
|
iface->get_reporting_level = _get_reporting_level;
|
|
iface->get_pipeline = _get_pipeline;
|
|
}
|
|
|
|
#define gst_validate_monitor_parent_class parent_class
|
|
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstValidateMonitor, gst_validate_monitor,
|
|
GST_TYPE_OBJECT, _do_init);
|
|
|
|
static void
|
|
_target_freed_cb (GstValidateMonitor * monitor, GObject * where_the_object_was)
|
|
{
|
|
GST_DEBUG_OBJECT (monitor, "Target was freed");
|
|
monitor->target = NULL;
|
|
GST_OBJECT_LOCK (monitor);
|
|
monitor->pipeline = NULL;
|
|
GST_OBJECT_UNLOCK (monitor);
|
|
}
|
|
|
|
static void
|
|
_pipeline_freed_cb (GstValidateMonitor * monitor,
|
|
GObject * where_the_object_was)
|
|
{
|
|
GST_DEBUG_OBJECT (monitor, "Pipeline was freed");
|
|
GST_OBJECT_LOCK (monitor);
|
|
monitor->pipeline = NULL;
|
|
GST_OBJECT_UNLOCK (monitor);
|
|
}
|
|
|
|
static void
|
|
gst_validate_monitor_dispose (GObject * object)
|
|
{
|
|
GstValidateMonitor *monitor = GST_VALIDATE_MONITOR_CAST (object);
|
|
|
|
g_mutex_clear (&monitor->mutex);
|
|
g_mutex_clear (&monitor->overrides_mutex);
|
|
g_queue_clear (&monitor->overrides);
|
|
|
|
if (monitor->target)
|
|
g_object_weak_unref (G_OBJECT (monitor->target),
|
|
(GWeakNotify) _target_freed_cb, monitor);
|
|
|
|
if (monitor->media_descriptor)
|
|
gst_object_unref (monitor->media_descriptor);
|
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
gst_validate_monitor_finalize (GObject * object)
|
|
{
|
|
gst_validate_reporter_set_name (GST_VALIDATE_REPORTER (object), NULL);
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gst_validate_monitor_class_init (GstValidateMonitorClass * klass)
|
|
{
|
|
GObjectClass *gobject_class;
|
|
|
|
gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
gobject_class->get_property = gst_validate_monitor_get_property;
|
|
gobject_class->set_property = gst_validate_monitor_set_property;
|
|
gobject_class->dispose = gst_validate_monitor_dispose;
|
|
gobject_class->finalize = gst_validate_monitor_finalize;
|
|
gobject_class->constructor = gst_validate_monitor_constructor;
|
|
|
|
klass->setup = gst_validate_monitor_do_setup;
|
|
|
|
g_object_class_install_property (gobject_class, PROP_OBJECT,
|
|
g_param_spec_object ("object", "Object", "The object to be monitored",
|
|
G_TYPE_OBJECT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (gobject_class, PROP_PIPELINE,
|
|
g_param_spec_object ("pipeline", "Pipeline", "The pipeline in which the"
|
|
"monitored object is", GST_TYPE_PIPELINE,
|
|
G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (gobject_class, PROP_RUNNER,
|
|
g_param_spec_object ("validate-runner", "VALIDATE Runner",
|
|
"The Validate runner to report errors to",
|
|
GST_TYPE_VALIDATE_RUNNER,
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (gobject_class, PROP_VALIDATE_PARENT,
|
|
g_param_spec_object ("validate-parent", "VALIDATE parent monitor",
|
|
"The Validate monitor " "that is the parent of this one",
|
|
GST_TYPE_VALIDATE_MONITOR,
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
|
|
}
|
|
|
|
static GObject *
|
|
gst_validate_monitor_constructor (GType type, guint n_construct_params,
|
|
GObjectConstructParam * construct_params)
|
|
{
|
|
GstValidateMonitor *monitor =
|
|
GST_VALIDATE_MONITOR_CAST (G_OBJECT_CLASS (parent_class)->constructor
|
|
(type,
|
|
n_construct_params,
|
|
construct_params));
|
|
|
|
if (monitor->parent) {
|
|
gst_validate_monitor_set_media_descriptor (monitor,
|
|
monitor->parent->media_descriptor);
|
|
|
|
GST_OBJECT_LOCK (monitor);
|
|
if (monitor->parent->pipeline) {
|
|
g_object_weak_ref (G_OBJECT (monitor->parent->pipeline),
|
|
(GWeakNotify) _pipeline_freed_cb, monitor);
|
|
monitor->pipeline = monitor->parent->pipeline;
|
|
}
|
|
GST_OBJECT_UNLOCK (monitor);
|
|
}
|
|
|
|
gst_validate_monitor_setup (monitor);
|
|
return (GObject *) monitor;
|
|
}
|
|
|
|
static void
|
|
gst_validate_monitor_init (GstValidateMonitor * monitor)
|
|
{
|
|
g_mutex_init (&monitor->mutex);
|
|
|
|
g_mutex_init (&monitor->overrides_mutex);
|
|
g_queue_init (&monitor->overrides);
|
|
}
|
|
|
|
static gboolean
|
|
gst_validate_monitor_do_setup (GstValidateMonitor * monitor)
|
|
{
|
|
/* NOP */
|
|
return TRUE;
|
|
}
|
|
|
|
static GstValidateReportingDetails
|
|
_get_report_level_for_pad (GstValidateRunner * runner, GstObject * pad)
|
|
{
|
|
GstObject *parent;
|
|
gchar *name;
|
|
GstValidateReportingDetails level = GST_VALIDATE_SHOW_UNKNOWN;
|
|
|
|
parent = gst_object_get_parent (pad);
|
|
|
|
name = g_strdup_printf ("%s__%s", GST_DEBUG_PAD_NAME (pad));
|
|
level = gst_validate_runner_get_reporting_level_for_name (runner, name);
|
|
|
|
g_free (name);
|
|
gst_object_unref (parent);
|
|
return level;
|
|
}
|
|
|
|
static void
|
|
_determine_reporting_level (GstValidateMonitor * monitor)
|
|
{
|
|
GstValidateRunner *runner;
|
|
GstObject *object, *parent;
|
|
gchar *object_name;
|
|
GstValidateReportingDetails level = GST_VALIDATE_SHOW_UNKNOWN;
|
|
|
|
object = gst_object_ref (monitor->target);
|
|
runner = gst_validate_reporter_get_runner (GST_VALIDATE_REPORTER (monitor));
|
|
|
|
do {
|
|
if (!GST_IS_OBJECT (object))
|
|
break;
|
|
|
|
/* Let's allow for singling out pads */
|
|
if (GST_IS_PAD (object)) {
|
|
level = _get_report_level_for_pad (runner, object);
|
|
if (level != GST_VALIDATE_SHOW_UNKNOWN)
|
|
break;
|
|
}
|
|
|
|
object_name = gst_object_get_name (object);
|
|
level =
|
|
gst_validate_runner_get_reporting_level_for_name (runner, object_name);
|
|
parent = gst_object_get_parent (object);
|
|
gst_object_unref (object);
|
|
object = parent;
|
|
g_free (object_name);
|
|
} while (object && level == GST_VALIDATE_SHOW_UNKNOWN);
|
|
|
|
if (object)
|
|
gst_object_unref (object);
|
|
|
|
monitor->level = level;
|
|
}
|
|
|
|
gboolean
|
|
gst_validate_monitor_setup (GstValidateMonitor * monitor)
|
|
{
|
|
GST_DEBUG_OBJECT (monitor, "Starting monitor setup");
|
|
|
|
/* For now we just need to do this at setup time */
|
|
_determine_reporting_level (monitor);
|
|
return GST_VALIDATE_MONITOR_GET_CLASS (monitor)->setup (monitor);
|
|
}
|
|
|
|
/**
|
|
* gst_validate_monitor_get_element
|
|
* @monitor: The monitor
|
|
*
|
|
* Returns: (transfer none): The GstElement associated with @monitor
|
|
*/
|
|
GstElement *
|
|
gst_validate_monitor_get_element (GstValidateMonitor * monitor)
|
|
{
|
|
GstValidateMonitorClass *klass = GST_VALIDATE_MONITOR_GET_CLASS (monitor);
|
|
GstElement *element = NULL;
|
|
|
|
if (klass->get_element)
|
|
element = klass->get_element (monitor);
|
|
|
|
return element;
|
|
}
|
|
|
|
const gchar *
|
|
gst_validate_monitor_get_element_name (GstValidateMonitor * monitor)
|
|
{
|
|
GstElement *element;
|
|
|
|
element = gst_validate_monitor_get_element (monitor);
|
|
if (element)
|
|
return GST_ELEMENT_NAME (element);
|
|
return NULL;
|
|
}
|
|
|
|
/* Check if any of our overrides wants to change the report severity */
|
|
static GstValidateInterceptionReturn
|
|
gst_validate_monitor_intercept_report (GstValidateReporter * reporter,
|
|
GstValidateReport * report)
|
|
{
|
|
GList *iter;
|
|
GstValidateMonitor *monitor = GST_VALIDATE_MONITOR_CAST (reporter);
|
|
|
|
GST_VALIDATE_MONITOR_OVERRIDES_LOCK (monitor);
|
|
for (iter = monitor->overrides.head; iter; iter = g_list_next (iter)) {
|
|
report->level =
|
|
gst_validate_override_get_severity (iter->data,
|
|
gst_validate_issue_get_id (report->issue), report->level);
|
|
}
|
|
GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (monitor);
|
|
|
|
return GST_VALIDATE_REPORTER_REPORT;
|
|
}
|
|
|
|
void
|
|
gst_validate_monitor_attach_override (GstValidateMonitor * monitor,
|
|
GstValidateOverride * override)
|
|
{
|
|
GstValidateRunner *runner;
|
|
|
|
if (!gst_validate_override_can_attach (override, monitor)) {
|
|
GST_INFO_OBJECT (monitor, "Can not attach override %s",
|
|
gst_validate_reporter_get_name (GST_VALIDATE_REPORTER (override)));
|
|
|
|
return;
|
|
}
|
|
|
|
runner = gst_validate_reporter_get_runner (GST_VALIDATE_REPORTER (override));
|
|
|
|
GST_VALIDATE_MONITOR_OVERRIDES_LOCK (monitor);
|
|
if (runner)
|
|
g_assert (runner ==
|
|
gst_validate_reporter_get_runner (GST_VALIDATE_REPORTER (monitor)));
|
|
else
|
|
gst_validate_reporter_set_runner (GST_VALIDATE_REPORTER (override),
|
|
gst_validate_reporter_get_runner (GST_VALIDATE_REPORTER (monitor)));
|
|
g_queue_push_tail (&monitor->overrides, override);
|
|
GST_VALIDATE_MONITOR_OVERRIDES_UNLOCK (monitor);
|
|
}
|
|
|
|
static void
|
|
gst_validate_monitor_set_property (GObject * object, guint prop_id,
|
|
const GValue * value, GParamSpec * pspec)
|
|
{
|
|
GstValidateMonitor *monitor;
|
|
|
|
monitor = GST_VALIDATE_MONITOR_CAST (object);
|
|
|
|
switch (prop_id) {
|
|
case PROP_OBJECT:
|
|
g_assert (monitor->target == NULL);
|
|
monitor->target = g_value_get_object (value);
|
|
g_object_weak_ref (G_OBJECT (monitor->target),
|
|
(GWeakNotify) _target_freed_cb, monitor);
|
|
|
|
if (monitor->target)
|
|
gst_validate_reporter_set_name (GST_VALIDATE_REPORTER (monitor),
|
|
g_strdup (GST_OBJECT_NAME (monitor->target)));
|
|
break;
|
|
case PROP_PIPELINE:
|
|
GST_OBJECT_LOCK (monitor);
|
|
monitor->pipeline = g_value_get_object (value);
|
|
if (monitor->pipeline)
|
|
g_object_weak_ref (G_OBJECT (monitor->pipeline),
|
|
(GWeakNotify) _pipeline_freed_cb, monitor);
|
|
GST_OBJECT_UNLOCK (monitor);
|
|
case PROP_RUNNER:
|
|
gst_validate_reporter_set_runner (GST_VALIDATE_REPORTER (monitor),
|
|
g_value_get_object (value));
|
|
break;
|
|
case PROP_VALIDATE_PARENT:
|
|
monitor->parent = g_value_get_object (value);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gst_validate_monitor_get_property (GObject * object, guint prop_id,
|
|
GValue * value, GParamSpec * pspec)
|
|
{
|
|
GstValidateMonitor *monitor;
|
|
|
|
monitor = GST_VALIDATE_MONITOR_CAST (object);
|
|
|
|
switch (prop_id) {
|
|
case PROP_OBJECT:
|
|
g_value_set_object (value, GST_VALIDATE_MONITOR_GET_OBJECT (monitor));
|
|
break;
|
|
case PROP_PIPELINE:
|
|
g_value_set_object (value, monitor->pipeline);
|
|
break;
|
|
case PROP_RUNNER:
|
|
g_value_set_object (value, GST_VALIDATE_MONITOR_GET_RUNNER (monitor));
|
|
break;
|
|
case PROP_VALIDATE_PARENT:
|
|
g_value_set_object (value, GST_VALIDATE_MONITOR_GET_PARENT (monitor));
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
gst_validate_monitor_set_media_descriptor (GstValidateMonitor * monitor,
|
|
GstValidateMediaDescriptor * media_descriptor)
|
|
{
|
|
GstValidateMonitorClass *klass = GST_VALIDATE_MONITOR_GET_CLASS (monitor);
|
|
|
|
GST_DEBUG_OBJECT (monitor->target, "Set media desc: %" GST_PTR_FORMAT,
|
|
media_descriptor);
|
|
if (monitor->media_descriptor)
|
|
gst_object_unref (monitor->media_descriptor);
|
|
|
|
if (media_descriptor)
|
|
gst_object_ref (media_descriptor);
|
|
|
|
monitor->media_descriptor = media_descriptor;
|
|
if (klass->set_media_descriptor)
|
|
klass->set_media_descriptor (monitor, media_descriptor);
|
|
}
|
|
|
|
GstValidateMonitor *
|
|
gst_validate_get_monitor (GObject * object)
|
|
{
|
|
return GST_VALIDATE_MONITOR (g_object_get_data (object, "validate-monitor"));
|
|
}
|