mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-12 02:15:31 +00:00
1a28e7b043
Make sure to use it where appropriate and add some logging when setting an object property from an action. And use the valgrind.conf to set all the properties instead of having a mixture of a config scenario and the config file (making sure the max-lateness is set on any sink)
349 lines
9.9 KiB
C
349 lines
9.9 KiB
C
/* GStreamer
|
|
*
|
|
* Copyright (C) 2013 Collabora Ltd.
|
|
* Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>
|
|
*
|
|
* gst-validate-element-monitor.c - Validate ElementMonitor 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-element-monitor.h"
|
|
#include "gst-validate-pad-monitor.h"
|
|
#include "gst-validate-monitor-factory.h"
|
|
#include "gst-validate-utils.h"
|
|
#include "validate.h"
|
|
#include <string.h>
|
|
|
|
/**
|
|
* SECTION:gst-validate-element-monitor
|
|
* @short_description: Class that wraps a #GstElement for Validate checks
|
|
*
|
|
* TODO
|
|
*/
|
|
|
|
#define gst_validate_element_monitor_parent_class parent_class
|
|
G_DEFINE_TYPE (GstValidateElementMonitor, gst_validate_element_monitor,
|
|
GST_TYPE_VALIDATE_MONITOR);
|
|
|
|
static void
|
|
gst_validate_element_monitor_wrap_pad (GstValidateElementMonitor * monitor,
|
|
GstPad * pad);
|
|
static gboolean gst_validate_element_monitor_do_setup (GstValidateMonitor *
|
|
monitor);
|
|
static GstElement *gst_validate_element_monitor_get_element (GstValidateMonitor
|
|
* monitor);
|
|
|
|
static void
|
|
_validate_element_pad_added (GstElement * element, GstPad * pad,
|
|
GstValidateElementMonitor * monitor);
|
|
|
|
static void
|
|
gst_validate_element_set_media_descriptor (GstValidateMonitor * monitor,
|
|
GstValidateMediaDescriptor * media_descriptor)
|
|
{
|
|
gboolean done;
|
|
GstPad *pad;
|
|
GstValidateMonitor *pmonitor;
|
|
GstIterator *iterator;
|
|
GstElement *elem = GST_ELEMENT (gst_validate_monitor_get_target (monitor));
|
|
|
|
iterator = gst_element_iterate_pads (elem);
|
|
gst_object_unref (elem);
|
|
done = FALSE;
|
|
while (!done) {
|
|
GValue value = { 0, };
|
|
|
|
switch (gst_iterator_next (iterator, &value)) {
|
|
case GST_ITERATOR_OK:
|
|
|
|
pad = g_value_get_object (&value);
|
|
|
|
pmonitor = g_object_get_data ((GObject *) pad, "validate-monitor");
|
|
if (pmonitor)
|
|
gst_validate_monitor_set_media_descriptor (pmonitor,
|
|
media_descriptor);
|
|
g_value_reset (&value);
|
|
break;
|
|
case GST_ITERATOR_RESYNC:
|
|
/* TODO how to handle this? */
|
|
gst_iterator_resync (iterator);
|
|
break;
|
|
case GST_ITERATOR_ERROR:
|
|
done = TRUE;
|
|
break;
|
|
case GST_ITERATOR_DONE:
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
gst_iterator_free (iterator);
|
|
}
|
|
|
|
static void
|
|
purge_and_unref_reporter (gpointer data)
|
|
{
|
|
GstValidateReporter *reporter = data;
|
|
|
|
gst_validate_reporter_purge_reports (reporter);
|
|
g_object_unref (reporter);
|
|
}
|
|
|
|
static void
|
|
gst_validate_element_monitor_dispose (GObject * object)
|
|
{
|
|
GstValidateElementMonitor *monitor =
|
|
GST_VALIDATE_ELEMENT_MONITOR_CAST (object);
|
|
GstObject *target =
|
|
gst_validate_monitor_get_target (GST_VALIDATE_MONITOR (monitor));
|
|
|
|
if (target) {
|
|
if (monitor->pad_added_id)
|
|
g_signal_handler_disconnect (target, monitor->pad_added_id);
|
|
gst_object_unref (target);
|
|
}
|
|
|
|
g_list_free_full (monitor->pad_monitors, purge_and_unref_reporter);
|
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
}
|
|
|
|
|
|
static void
|
|
gst_validate_element_monitor_class_init (GstValidateElementMonitorClass * klass)
|
|
{
|
|
GObjectClass *gobject_class;
|
|
GstValidateMonitorClass *monitor_klass;
|
|
|
|
gobject_class = G_OBJECT_CLASS (klass);
|
|
monitor_klass = GST_VALIDATE_MONITOR_CLASS (klass);
|
|
|
|
gobject_class->dispose = gst_validate_element_monitor_dispose;
|
|
|
|
monitor_klass->setup = gst_validate_element_monitor_do_setup;
|
|
monitor_klass->get_element = gst_validate_element_monitor_get_element;
|
|
monitor_klass->set_media_descriptor =
|
|
gst_validate_element_set_media_descriptor;
|
|
}
|
|
|
|
static void
|
|
gst_validate_element_monitor_init (GstValidateElementMonitor * element_monitor)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* gst_validate_element_monitor_new:
|
|
* @element: (transfer none): a #GstElement to run Validate on
|
|
*/
|
|
GstValidateElementMonitor *
|
|
gst_validate_element_monitor_new (GstElement * element,
|
|
GstValidateRunner * runner, GstValidateMonitor * parent)
|
|
{
|
|
GstValidateElementMonitor *monitor;
|
|
GstElement *target;
|
|
|
|
g_return_val_if_fail (element != NULL, NULL);
|
|
|
|
monitor = g_object_new (GST_TYPE_VALIDATE_ELEMENT_MONITOR, "object", element,
|
|
"validate-runner", runner, "validate-parent", parent, NULL);
|
|
|
|
target =
|
|
GST_ELEMENT (gst_validate_monitor_get_target (GST_VALIDATE_MONITOR
|
|
(monitor)));
|
|
|
|
if (!target) {
|
|
g_object_unref (monitor);
|
|
return NULL;
|
|
}
|
|
|
|
gst_object_unref (target);
|
|
return monitor;
|
|
}
|
|
|
|
static GstElement *
|
|
gst_validate_element_monitor_get_element (GstValidateMonitor * monitor)
|
|
{
|
|
return GST_ELEMENT (gst_validate_monitor_get_target (monitor));
|
|
}
|
|
|
|
static void
|
|
gst_validate_element_monitor_inspect (GstValidateElementMonitor * monitor)
|
|
{
|
|
GstElement *element;
|
|
GstElementClass *klass;
|
|
const gchar *klassname;
|
|
|
|
element =
|
|
GST_ELEMENT_CAST (gst_validate_monitor_get_target (GST_VALIDATE_MONITOR
|
|
(monitor)));
|
|
klass = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
|
|
|
|
|
|
klassname =
|
|
gst_element_class_get_metadata (klass, GST_ELEMENT_METADATA_KLASS);
|
|
if (klassname) {
|
|
monitor->is_decoder = strstr (klassname, "Decoder") != NULL;
|
|
monitor->is_encoder = strstr (klassname, "Encoder") != NULL;
|
|
monitor->is_demuxer = strstr (klassname, "Demuxer") != NULL;
|
|
monitor->is_converter = strstr (klassname, "Converter") != NULL;
|
|
} else
|
|
GST_ERROR_OBJECT (element, "no klassname");
|
|
|
|
gst_object_unref (element);
|
|
}
|
|
|
|
static void
|
|
set_config_properties (GstValidateMonitor * monitor, GstElement * element)
|
|
{
|
|
GList *config, *l;
|
|
|
|
config = gst_validate_plugin_get_config (NULL);
|
|
for (l = config; l != NULL; l = g_list_next (l)) {
|
|
GstStructure *s = l->data;
|
|
const gchar *klass;
|
|
gchar *tmp;
|
|
const gchar *prop_name;
|
|
const GValue *prop_value;
|
|
|
|
if (g_strcmp0 (gst_structure_get_string (s, "action"), "set-property") != 0)
|
|
continue;
|
|
|
|
klass = gst_structure_get_string (s, "target-element-klass");
|
|
if (klass && !gst_validate_element_has_klass (element, klass))
|
|
continue;
|
|
|
|
prop_name = gst_structure_get_string (s, "property-name");
|
|
if (!prop_name
|
|
|| !g_object_class_find_property (G_OBJECT_GET_CLASS (element),
|
|
prop_name))
|
|
continue;
|
|
|
|
prop_value = gst_structure_get_value (s, "property-value");
|
|
if (!prop_value)
|
|
continue;
|
|
|
|
tmp = gst_value_serialize (prop_value);
|
|
gst_validate_printf (monitor, "Setting %s to %s", prop_name, tmp);
|
|
g_free (tmp);
|
|
gst_validate_object_set_property (GST_VALIDATE_REPORTER (monitor),
|
|
G_OBJECT (element), prop_name, prop_value, FALSE);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
gst_validate_element_monitor_do_setup (GstValidateMonitor * monitor)
|
|
{
|
|
GstIterator *iterator;
|
|
gboolean done;
|
|
GstPad *pad;
|
|
GstValidateElementMonitor *elem_monitor;
|
|
GstElement *element;
|
|
GstObject *target = gst_validate_monitor_get_target (monitor);
|
|
|
|
if (!GST_IS_ELEMENT (target)) {
|
|
gst_object_unref (target);
|
|
GST_WARNING_OBJECT (monitor, "Trying to create element monitor with other "
|
|
"type of object");
|
|
return FALSE;
|
|
}
|
|
|
|
elem_monitor = GST_VALIDATE_ELEMENT_MONITOR_CAST (monitor);
|
|
|
|
GST_DEBUG_OBJECT (monitor, "Setting up monitor for element %" GST_PTR_FORMAT,
|
|
target);
|
|
element = GST_ELEMENT_CAST (target);
|
|
|
|
if (g_object_get_data ((GObject *) element, "validate-monitor")) {
|
|
GST_DEBUG_OBJECT (elem_monitor,
|
|
"Pad already has a validate-monitor associated");
|
|
gst_object_unref (target);
|
|
return FALSE;
|
|
}
|
|
|
|
gst_validate_element_monitor_inspect (elem_monitor);
|
|
|
|
elem_monitor->pad_added_id = g_signal_connect (element, "pad-added",
|
|
G_CALLBACK (_validate_element_pad_added), monitor);
|
|
|
|
iterator = gst_element_iterate_pads (element);
|
|
done = FALSE;
|
|
while (!done) {
|
|
GValue value = { 0, };
|
|
|
|
switch (gst_iterator_next (iterator, &value)) {
|
|
case GST_ITERATOR_OK:
|
|
pad = g_value_get_object (&value);
|
|
gst_validate_element_monitor_wrap_pad (elem_monitor, pad);
|
|
g_value_reset (&value);
|
|
break;
|
|
case GST_ITERATOR_RESYNC:
|
|
/* TODO how to handle this? */
|
|
gst_iterator_resync (iterator);
|
|
break;
|
|
case GST_ITERATOR_ERROR:
|
|
done = TRUE;
|
|
break;
|
|
case GST_ITERATOR_DONE:
|
|
done = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
gst_iterator_free (iterator);
|
|
gst_object_unref (target);
|
|
|
|
set_config_properties (monitor, element);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gst_validate_element_monitor_wrap_pad (GstValidateElementMonitor * monitor,
|
|
GstPad * pad)
|
|
{
|
|
GstValidatePadMonitor *pad_monitor;
|
|
GstValidateRunner *runner =
|
|
gst_validate_reporter_get_runner (GST_VALIDATE_REPORTER (monitor));
|
|
|
|
GST_DEBUG_OBJECT (monitor, "Wrapping pad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
|
|
|
pad_monitor =
|
|
GST_VALIDATE_PAD_MONITOR (gst_validate_monitor_factory_create (GST_OBJECT
|
|
(pad), runner, GST_VALIDATE_MONITOR (monitor)));
|
|
g_return_if_fail (pad_monitor != NULL);
|
|
|
|
GST_VALIDATE_MONITOR_LOCK (monitor);
|
|
monitor->pad_monitors = g_list_prepend (monitor->pad_monitors, pad_monitor);
|
|
GST_VALIDATE_MONITOR_UNLOCK (monitor);
|
|
|
|
gst_object_unref (runner);
|
|
}
|
|
|
|
static void
|
|
_validate_element_pad_added (GstElement * element, GstPad * pad,
|
|
GstValidateElementMonitor * monitor)
|
|
{
|
|
GstObject *target =
|
|
gst_validate_monitor_get_target (GST_VALIDATE_MONITOR (monitor));
|
|
|
|
g_return_if_fail (target == (GstObject *) element);
|
|
gst_object_unref (target);
|
|
gst_validate_element_monitor_wrap_pad (monitor, pad);
|
|
}
|