validate: Add a GstValidatePipelineMonitor subclass

We had quite a bit of code dedicated to handled GstPipeline monitoring
inside GstValidateBinMonitor, cleanly split that code into a new object
type

https://bugzilla.gnome.org/show_bug.cgi?id=740704
This commit is contained in:
Thibault Saunier 2014-11-21 14:01:48 +01:00
parent 36a2d61068
commit fcb0f20828
6 changed files with 322 additions and 147 deletions

View file

@ -4,6 +4,7 @@ libgstvalidate_@GST_API_VERSION@_la_SOURCES = \
gst-validate-monitor.c \
gst-validate-element-monitor.c \
gst-validate-bin-monitor.c \
gst-validate-pipeline-monitor.c \
gst-validate-pad-monitor.c \
gst-validate-monitor-factory.c \
gst-validate-report.c \
@ -20,6 +21,7 @@ libgstvalidate_@GST_API_VERSION@_la_SOURCES = \
libgstvalidate_@GST_API_VERSION@include_HEADERS = \
validate.h \
gst-validate-bin-monitor.h \
gst-validate-pipeline-monitor.h \
gst-validate-element-monitor.h \
gst-validate-enums.h \
media-descriptor.h \

View file

@ -128,11 +128,6 @@ gst_validate_bin_monitor_dispose (GObject * object)
if (monitor->scenario)
g_object_unref (monitor->scenario);
if (monitor->print_pos_srcid) {
if (g_source_remove (monitor->print_pos_srcid))
monitor->print_pos_srcid = 0;
}
g_list_free_full (monitor->element_monitors, g_object_unref);
G_OBJECT_CLASS (parent_class)->dispose (object);
@ -168,130 +163,6 @@ gst_validate_bin_monitor_init (GstValidateBinMonitor * bin_monitor)
{
}
static gboolean
print_position (GstValidateMonitor * monitor)
{
GstQuery *query;
gint64 position, duration;
GstElement *pipeline =
GST_ELEMENT (GST_VALIDATE_MONITOR_GET_OBJECT (monitor));
gdouble rate = 1.0;
GstFormat format = GST_FORMAT_TIME;
if (!gst_element_query_position (pipeline, format, &position)) {
GST_DEBUG_OBJECT (monitor, "Could not query position");
return TRUE;
}
format = GST_FORMAT_TIME;
if (!gst_element_query_duration (pipeline, format, &duration)) {
GST_DEBUG_OBJECT (monitor, "Could not query duration");
return TRUE;
}
query = gst_query_new_segment (GST_FORMAT_DEFAULT);
if (gst_element_query (pipeline, query))
gst_query_parse_segment (query, &rate, NULL, NULL, NULL);
gst_query_unref (query);
gst_validate_printf (NULL,
"<position: %" GST_TIME_FORMAT " duration: %" GST_TIME_FORMAT
" speed: %f />\r", GST_TIME_ARGS (position), GST_TIME_ARGS (duration),
rate);
return TRUE;
}
static void
_bus_handler (GstBus * bus, GstMessage * message,
GstValidateBinMonitor * monitor)
{
GError *err = NULL;
gchar *debug = NULL;
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ERROR:
gst_message_parse_error (message, &err, &debug);
GST_VALIDATE_REPORT (monitor, ERROR_ON_BUS,
"Got error: %s -- Debug message: %s", err->message, debug);
g_error_free (err);
g_free (debug);
break;
case GST_MESSAGE_WARNING:
gst_message_parse_warning (message, &err, &debug);
GST_VALIDATE_REPORT (monitor, WARNING_ON_BUS,
"Got warning: %s -- Debug message: %s", err->message, debug);
g_error_free (err);
g_free (debug);
break;
case GST_MESSAGE_BUFFERING:
{
GstBufferingMode mode;
gint percent;
gst_message_parse_buffering (message, &percent);
gst_message_parse_buffering_stats (message, &mode, NULL, NULL, NULL);
if (percent == 100) {
/* a 100% message means buffering is done */
if (monitor->buffering) {
monitor->print_pos_srcid =
g_timeout_add (PRINT_POSITION_TIMEOUT,
(GSourceFunc) print_position, monitor);
monitor->buffering = FALSE;
}
} else {
/* buffering... */
if (!monitor->buffering) {
monitor->buffering = TRUE;
if (monitor->print_pos_srcid
&& g_source_remove (monitor->print_pos_srcid))
monitor->print_pos_srcid = 0;
}
}
break;
}
default:
break;
}
}
static void
gst_validate_bin_monitor_create_scenarios (GstValidateBinMonitor * monitor)
{
GstElement *bin = GST_ELEMENT (GST_VALIDATE_MONITOR_GET_OBJECT (monitor));
/* scenarios currently only make sense for pipelines */
if (GST_IS_PIPELINE (bin)) {
const gchar *scenario_name;
if ((scenario_name = g_getenv ("GST_VALIDATE_SCENARIO"))) {
gchar **scenario_v = g_strsplit (scenario_name, "->", 2);
if (scenario_v[1] && GST_VALIDATE_MONITOR_GET_OBJECT (monitor)) {
if (!g_pattern_match_simple (scenario_v[1],
GST_OBJECT_NAME (GST_VALIDATE_MONITOR_GET_OBJECT (monitor)))) {
GST_INFO_OBJECT (monitor, "Not attaching to bin %" GST_PTR_FORMAT
" as not matching pattern %s",
GST_VALIDATE_MONITOR_GET_OBJECT (monitor), scenario_v[1]);
g_strfreev (scenario_v);
return;
}
}
monitor->scenario =
gst_validate_scenario_factory_create (GST_VALIDATE_MONITOR_GET_RUNNER
(monitor),
GST_ELEMENT_CAST (GST_VALIDATE_MONITOR_GET_OBJECT (monitor)),
scenario_v[0]);
g_strfreev (scenario_v);
}
}
}
/**
* gst_validate_bin_monitor_new:
* @bin: (transfer-none): a #GstBin to run Validate on
@ -309,22 +180,6 @@ gst_validate_bin_monitor_new (GstBin * bin, GstValidateRunner * runner,
return NULL;
}
gst_validate_bin_monitor_create_scenarios (monitor);
if (GST_IS_PIPELINE (bin)) {
GstBus *bus;
monitor->print_pos_srcid =
g_timeout_add (PRINT_POSITION_TIMEOUT, (GSourceFunc) print_position,
monitor);
bus = gst_element_get_bus (GST_ELEMENT (bin));
gst_bus_enable_sync_message_emission (bus);
g_signal_connect (bus, "sync-message", (GCallback) _bus_handler, monitor);
gst_object_unref (bus);
}
return monitor;
}

View file

@ -60,9 +60,7 @@ struct _GstValidateBinMonitor {
/*< private >*/
gulong element_added_id;
guint print_pos_srcid;
gboolean stateless;
gboolean buffering;
};
/**

View file

@ -36,6 +36,7 @@
#include "gst-validate-monitor-factory.h"
#include "gst-validate-bin-monitor.h"
#include "gst-validate-pipeline-monitor.h"
#include "gst-validate-pad-monitor.h"
#include "gst-validate-override-registry.h"
@ -60,6 +61,10 @@ gst_validate_monitor_factory_create (GstObject * target,
monitor =
GST_VALIDATE_MONITOR_CAST (gst_validate_pad_monitor_new (GST_PAD_CAST
(target), runner, GST_VALIDATE_ELEMENT_MONITOR_CAST (parent)));
} else if (GST_IS_PIPELINE (target)) {
monitor =
GST_VALIDATE_MONITOR_CAST (gst_validate_pipeline_monitor_new
(GST_PIPELINE_CAST (target), runner, parent));
} else if (GST_IS_BIN (target)) {
monitor =
GST_VALIDATE_MONITOR_CAST (gst_validate_bin_monitor_new (GST_BIN_CAST

View file

@ -0,0 +1,234 @@
/* GStreamer
*
* Copyright (C) 2014 Thibault Saunier <tsaunier@gnome.org>
*
* gst-validate-pipeline-monitor.c - Validate PipelineMonitor 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-pipeline-monitor.h"
#include "gst-validate-monitor-factory.h"
#define PRINT_POSITION_TIMEOUT 250
/**
* SECTION:gst-validate-pipeline-monitor
* @short_description: Class that wraps a #GstPipeline for Validate checks
*
* TODO
*/
enum
{
PROP_LAST
};
#define gst_validate_pipeline_monitor_parent_class parent_class
G_DEFINE_TYPE (GstValidatePipelineMonitor, gst_validate_pipeline_monitor,
GST_TYPE_VALIDATE_BIN_MONITOR);
static void
gst_validate_pipeline_monitor_dispose (GObject * object)
{
GstValidatePipelineMonitor *monitor =
GST_VALIDATE_PIPELINE_MONITOR_CAST (object);
if (monitor->print_pos_srcid) {
if (g_source_remove (monitor->print_pos_srcid))
monitor->print_pos_srcid = 0;
}
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gst_validate_pipeline_monitor_class_init (GstValidatePipelineMonitorClass *
klass)
{
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = gst_validate_pipeline_monitor_dispose;
}
static void
gst_validate_pipeline_monitor_init (GstValidatePipelineMonitor *
pipeline_monitor)
{
}
static gboolean
print_position (GstValidateMonitor * monitor)
{
GstQuery *query;
gint64 position, duration;
GstElement *pipeline =
GST_ELEMENT (GST_VALIDATE_MONITOR_GET_OBJECT (monitor));
gdouble rate = 1.0;
GstFormat format = GST_FORMAT_TIME;
if (!gst_element_query_position (pipeline, format, &position)) {
GST_DEBUG_OBJECT (monitor, "Could not query position");
return TRUE;
}
format = GST_FORMAT_TIME;
if (!gst_element_query_duration (pipeline, format, &duration)) {
GST_DEBUG_OBJECT (monitor, "Could not query duration");
return TRUE;
}
query = gst_query_new_segment (GST_FORMAT_DEFAULT);
if (gst_element_query (pipeline, query))
gst_query_parse_segment (query, &rate, NULL, NULL, NULL);
gst_query_unref (query);
gst_validate_printf (NULL,
"<position: %" GST_TIME_FORMAT " duration: %" GST_TIME_FORMAT
" speed: %f />\r", GST_TIME_ARGS (position), GST_TIME_ARGS (duration),
rate);
return TRUE;
}
static void
_bus_handler (GstBus * bus, GstMessage * message,
GstValidatePipelineMonitor * monitor)
{
GError *err = NULL;
gchar *debug = NULL;
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ERROR:
gst_message_parse_error (message, &err, &debug);
GST_VALIDATE_REPORT (monitor, ERROR_ON_BUS,
"Got error: %s -- Debug message: %s", err->message, debug);
g_error_free (err);
g_free (debug);
break;
case GST_MESSAGE_WARNING:
gst_message_parse_warning (message, &err, &debug);
GST_VALIDATE_REPORT (monitor, WARNING_ON_BUS,
"Got warning: %s -- Debug message: %s", err->message, debug);
g_error_free (err);
g_free (debug);
break;
case GST_MESSAGE_BUFFERING:
{
GstBufferingMode mode;
gint percent;
gst_message_parse_buffering (message, &percent);
gst_message_parse_buffering_stats (message, &mode, NULL, NULL, NULL);
if (percent == 100) {
/* a 100% message means buffering is done */
if (monitor->buffering) {
monitor->print_pos_srcid =
g_timeout_add (PRINT_POSITION_TIMEOUT,
(GSourceFunc) print_position, monitor);
monitor->buffering = FALSE;
}
} else {
/* buffering... */
if (!monitor->buffering) {
monitor->buffering = TRUE;
if (monitor->print_pos_srcid
&& g_source_remove (monitor->print_pos_srcid))
monitor->print_pos_srcid = 0;
}
}
break;
}
default:
break;
}
}
static void
gst_validate_pipeline_monitor_create_scenarios (GstValidateBinMonitor * monitor)
{
/* scenarios currently only make sense for pipelines */
const gchar *scenario_name;
if ((scenario_name = g_getenv ("GST_VALIDATE_SCENARIO"))) {
gchar **scenario_v = g_strsplit (scenario_name, "->", 2);
if (scenario_v[1] && GST_VALIDATE_MONITOR_GET_OBJECT (monitor)) {
if (!g_pattern_match_simple (scenario_v[1],
GST_OBJECT_NAME (GST_VALIDATE_MONITOR_GET_OBJECT (monitor)))) {
GST_INFO_OBJECT (monitor, "Not attaching to pipeline %" GST_PTR_FORMAT
" as not matching pattern %s",
GST_VALIDATE_MONITOR_GET_OBJECT (monitor), scenario_v[1]);
g_strfreev (scenario_v);
return;
}
}
monitor->scenario =
gst_validate_scenario_factory_create (GST_VALIDATE_MONITOR_GET_RUNNER
(monitor),
GST_ELEMENT_CAST (GST_VALIDATE_MONITOR_GET_OBJECT (monitor)),
scenario_v[0]);
g_strfreev (scenario_v);
}
}
/**
* gst_validate_pipeline_monitor_new:
* @pipeline: (transfer-none): a #GstPipeline to run Validate on
*/
GstValidatePipelineMonitor *
gst_validate_pipeline_monitor_new (GstPipeline * pipeline,
GstValidateRunner * runner, GstValidateMonitor * parent)
{
GstBus *bus;
GstValidatePipelineMonitor *monitor =
g_object_new (GST_TYPE_VALIDATE_PIPELINE_MONITOR, "object",
pipeline, "validate-runner", runner, "validate-parent", parent, NULL);
if (GST_VALIDATE_MONITOR_GET_OBJECT (monitor) == NULL) {
g_object_unref (monitor);
return NULL;
}
gst_validate_pipeline_monitor_create_scenarios (GST_VALIDATE_BIN_MONITOR
(monitor));
monitor->print_pos_srcid =
g_timeout_add (PRINT_POSITION_TIMEOUT, (GSourceFunc) print_position,
monitor);
bus = gst_element_get_bus (GST_ELEMENT (pipeline));
gst_bus_enable_sync_message_emission (bus);
g_signal_connect (bus, "sync-message", (GCallback) _bus_handler, monitor);
gst_object_unref (bus);
return monitor;
}

View file

@ -0,0 +1,81 @@
/* GStreamer
* Copyright (C) 2014 Thibault Saunier <tsaunier@gnome.org>
*
* gst-validate-pipeline-monitor.h - Validate PipelineMonitor 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.
*/
#ifndef __GST_VALIDATE_PIPELINE_MONITOR_H__
#define __GST_VALIDATE_PIPELINE_MONITOR_H__
#include <glib-object.h>
#include <gst/gst.h>
#include <gst/validate/gst-validate-bin-monitor.h>
#include <gst/validate/gst-validate-runner.h>
G_BEGIN_DECLS
#define GST_TYPE_VALIDATE_PIPELINE_MONITOR (gst_validate_pipeline_monitor_get_type ())
#define GST_IS_VALIDATE_PIPELINE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VALIDATE_PIPELINE_MONITOR))
#define GST_IS_VALIDATE_PIPELINE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VALIDATE_PIPELINE_MONITOR))
#define GST_VALIDATE_PIPELINE_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VALIDATE_PIPELINE_MONITOR, GstValidatePipelineMonitorClass))
#define GST_VALIDATE_PIPELINE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VALIDATE_PIPELINE_MONITOR, GstValidatePipelineMonitor))
#define GST_VALIDATE_PIPELINE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VALIDATE_PIPELINE_MONITOR, GstValidatePipelineMonitorClass))
#define GST_VALIDATE_PIPELINE_MONITOR_CAST(obj) ((GstValidatePipelineMonitor*)(obj))
#define GST_VALIDATE_PIPELINE_MONITOR_CLASS_CAST(klass) ((GstValidatePipelineMonitorClass*)(klass))
#define GST_VALIDATE_PIPELINE_MONITOR_GET_PIPELINE(m) (GST_PIPELINE_CAST (GST_VALIDATE_ELEMENT_MONITOR_GET_ELEMENT (m)))
typedef struct _GstValidatePipelineMonitor GstValidatePipelineMonitor;
typedef struct _GstValidatePipelineMonitorClass GstValidatePipelineMonitorClass;
/**
* GstValidatePipelineMonitor:
*
* GStreamer Validate PipelineMonitor class.
*
* Class that wraps a #GstPipeline for Validate checks
*/
struct _GstValidatePipelineMonitor {
GstValidateBinMonitor parent;
/*< private >*/
gulong element_added_id;
guint print_pos_srcid;
gboolean buffering;
};
/**
* GstValidatePipelineMonitorClass:
* @parent_class: parent
*
* GStreamer Validate PipelineMonitor object class.
*/
struct _GstValidatePipelineMonitorClass {
GstValidateBinMonitorClass parent_class;
};
/* normal GObject stuff */
GType gst_validate_pipeline_monitor_get_type (void);
GstValidatePipelineMonitor * gst_validate_pipeline_monitor_new (GstPipeline * pipeline,
GstValidateRunner * runner, GstValidateMonitor * parent);
G_END_DECLS
#endif /* __GST_VALIDATE_PIPELINE_MONITOR_H__ */