diff --git a/validate/data/Makefile.am b/validate/data/Makefile.am index 3a2fc92180..50ebe3715a 100644 --- a/validate/data/Makefile.am +++ b/validate/data/Makefile.am @@ -1,3 +1,3 @@ -confdir=${sysconfdir}/gstreamer -conf_DATA = simple_seeks.xml +scenariosdir=${datadir}/gstreamer-$(GST_API_VERSION)/qa-scenario +scenarios_DATA = simple_seeks.xml EXTRA_DIST = simple_seeks.xml diff --git a/validate/gst/qa/Makefile.am b/validate/gst/qa/Makefile.am index 979effa48a..5c0aee1812 100644 --- a/validate/gst/qa/Makefile.am +++ b/validate/gst/qa/Makefile.am @@ -3,6 +3,7 @@ public_headers = \ c_sources = \ gst-qa-runner.c \ + gst-qa-reporter.c \ gst-qa-monitor.c \ gst-qa-element-monitor.c \ gst-qa-bin-monitor.c \ diff --git a/validate/gst/qa/gst-qa-monitor.c b/validate/gst/qa/gst-qa-monitor.c index a7f4567e84..3259b32bc5 100644 --- a/validate/gst/qa/gst-qa-monitor.c +++ b/validate/gst/qa/gst-qa-monitor.c @@ -20,6 +20,7 @@ */ #include "gst-qa-monitor.h" +#include "gst-qa-reporter.h" /** * SECTION:gst-qa-monitor @@ -41,7 +42,10 @@ GST_DEBUG_CATEGORY_STATIC (gst_qa_monitor_debug); #define GST_CAT_DEFAULT gst_qa_monitor_debug #define _do_init \ - GST_DEBUG_CATEGORY_INIT (gst_qa_monitor_debug, "qa_monitor", 0, "QA Monitor"); + GST_DEBUG_CATEGORY_INIT (gst_qa_monitor_debug, "qa_monitor", 0, "QA Monitor");\ + G_IMPLEMENT_INTERFACE (GST_TYPE_QA_REPORTER, NULL) + + #define gst_qa_monitor_parent_class parent_class G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstQaMonitor, gst_qa_monitor, G_TYPE_OBJECT, _do_init); @@ -76,17 +80,13 @@ gst_qa_monitor_dispose (GObject * object) g_object_weak_unref (G_OBJECT (monitor->target), (GWeakNotify) _target_freed_cb, monitor); - g_hash_table_unref (monitor->reports); - G_OBJECT_CLASS (parent_class)->dispose (object); } static void gst_qa_monitor_finalize (GObject * object) { - GstQaMonitor *monitor = GST_QA_MONITOR_CAST (object); - - gst_qa_monitor_set_target_name (monitor, NULL); + gst_qa_reporter_set_name (GST_QA_REPORTER (object), NULL); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -133,20 +133,11 @@ gst_qa_monitor_constructor (GType type, guint n_construct_params, return (GObject *) monitor; } -static inline gchar * -_qa_report_id (GstQaReport * report) -{ - return g_strdup_printf ("%i-%i-%i-%s", - report->level, report->area, report->subarea, report->id); -} - static void gst_qa_monitor_init (GstQaMonitor * monitor) { g_mutex_init (&monitor->mutex); - monitor->reports = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, (GDestroyNotify) gst_qa_report_unref); } /** @@ -198,7 +189,7 @@ gst_qa_monitor_set_property (GObject * object, guint prop_id, (GWeakNotify) _target_freed_cb, monitor); if (monitor->target) - gst_qa_monitor_set_target_name (monitor, g_strdup + gst_qa_reporter_set_name (GST_QA_REPORTER (monitor), g_strdup (GST_OBJECT_NAME (monitor->target))); break; case PROP_RUNNER: @@ -238,60 +229,3 @@ gst_qa_monitor_get_property (GObject * object, guint prop_id, break; } } - -void -gst_qa_monitor_do_report_valist (GstQaMonitor * monitor, gboolean repeat, - GstQaReportLevel level, GstQaReportArea area, - gint subarea, const gchar * format, va_list var_args) -{ - GstQaReport *report; - gchar *message, *report_id = NULL; - - message = g_strdup_vprintf (format, var_args); - report = gst_qa_report_new (monitor, level, area, subarea, format, message); - - if (repeat == FALSE) { - report_id = _qa_report_id (report); - - if (g_hash_table_lookup (monitor->reports, report_id)) { - GST_DEBUG ("Report %s already present", report_id); - g_free (report_id); - return; - } - - g_hash_table_insert (monitor->reports, report_id, report); - } - - GST_INFO_OBJECT (monitor, "Received error report %d : %d : %d : %s", - level, area, subarea, message); - gst_qa_report_printf (report); - if (GST_QA_MONITOR_GET_RUNNER (monitor)) { - gst_qa_runner_add_report (GST_QA_MONITOR_GET_RUNNER (monitor), report); - } else { - gst_qa_report_unref (report); - } - - g_free (message); -} - -void -gst_qa_monitor_do_report (GstQaMonitor * monitor, gboolean repeat, - GstQaReportLevel level, GstQaReportArea area, - gint subarea, const gchar * format, ...) -{ - va_list var_args; - - va_start (var_args, format); - gst_qa_monitor_do_report_valist (monitor, repeat, level, area, subarea, - format, var_args); - va_end (var_args); -} - -void -gst_qa_monitor_set_target_name (GstQaMonitor * monitor, gchar * target_name) -{ - if (monitor->target_name) - g_free (monitor->target_name); - - monitor->target_name = target_name; -} diff --git a/validate/gst/qa/gst-qa-monitor.h b/validate/gst/qa/gst-qa-monitor.h index 82c06f9399..d45ba10f61 100644 --- a/validate/gst/qa/gst-qa-monitor.h +++ b/validate/gst/qa/gst-qa-monitor.h @@ -44,66 +44,6 @@ G_BEGIN_DECLS #define GST_QA_MONITOR_LOCK(m) (g_mutex_lock (&GST_QA_MONITOR_CAST(m)->mutex)) #define GST_QA_MONITOR_UNLOCK(m) (g_mutex_unlock (&GST_QA_MONITOR_CAST(m)->mutex)) -#ifdef G_HAVE_ISO_VARARGS -#define GST_QA_MONITOR_REPORT(m, repeat, status, area, subarea, ...) \ -G_STMT_START { \ - gst_qa_monitor_do_report (GST_QA_MONITOR (m), repeat, \ - GST_QA_REPORT_LEVEL_ ## status, GST_QA_AREA_ ## area, \ - GST_QA_AREA_ ## area ## _ ## subarea, __VA_ARGS__ ); \ -} G_STMT_END - -#define GST_QA_MONITOR_REPORT_CRITICAL(m, repeat, area, subarea, ...) \ -G_STMT_START { \ - GST_ERROR_OBJECT (m, "Critical report: %s: %s: %s", \ - #area, #subarea, __VA_ARGS__); \ - GST_QA_MONITOR_REPORT(m, repeat, CRITICAL, area, subarea, __VA_ARGS__); \ -} G_STMT_END - -#define GST_QA_MONITOR_REPORT_WARNING(m, repeat, area, subarea, ...) \ -G_STMT_START { \ - GST_WARNING_OBJECT (m, "Warning report: %s: %s: %s", \ - #area, #subarea, __VA_ARGS__); \ - GST_QA_MONITOR_REPORT(m, repeat, WARNING, area, subarea, __VA_ARGS__); \ -} G_STMT_END - -#define GST_QA_MONITOR_REPORT_ISSUE(m, repeat, area, subarea, ...) \ -G_STMT_START { \ - GST_WARNING_OBJECT (m, "Issue report: %s: %s: %s", \ - #area, #subarea, __VA_ARGS__); \ - GST_QA_MONITOR_REPORT(m, repeat, ISSUE, area, subarea, __VA_ARGS__); \ -} G_STMT_END -#else /* G_HAVE_GNUC_VARARGS */ -#ifdef G_HAVE_GNUC_VARARGS -#define GST_QA_MONITOR_REPORT(m, repeat, status, area, subarea, args...) \ -G_STMT_START { \ - gst_qa_monitor_do_report (GST_QA_MONITOR (m), \ - GST_QA_REPORT_LEVEL_ ## status, GST_QA_AREA_ ## area, \ - GST_QA_AREA_ ## area ## _ ## subarea, ##args ); \ -} G_STMT_END - -#define GST_QA_MONITOR_REPORT_CRITICAL(m, repeat, area, subarea, args...) \ -G_STMT_START { \ - GST_ERROR_OBJECT (m, "Critical report: %s: %s: %s", \ - #area, #subarea, ##args); \ - GST_QA_MONITOR_REPORT(m, repeat, CRITICAL, area, subarea, ##args); \ -} G_STMT_END - -#define GST_QA_MONITOR_REPORT_WARNING(m, repeat, area, subarea, args...) \ -G_STMT_START { \ - GST_WARNING_OBJECT (m, "Warning report: %s: %s: %s", \ - #area, #subarea, ##args); \ - GST_QA_MONITOR_REPORT(m, repeat, WARNING, area, subarea, ##args); \ -} G_STMT_END - -#define GST_QA_MONITOR_REPORT_ISSUE(m, repeat, area, subarea, args...) \ -G_STMT_START { \ - GST_WARNING_OBJECT (m, "Issue report: %s: %s: %s", \ - #area, #subarea, ##args); \ - GST_QA_MONITOR_REPORT(m, repeat, ISSUE, area, subarea, ##args); \ -} G_STMT_END -#endif /* G_HAVE_ISO_VARARGS */ -#endif /* G_HAVE_GNUC_VARARGS */ - /* #else TODO Implemen no variadic macros, use inline, * Problem being: * GST_QA_REPORT_LEVEL_ ## status @@ -150,18 +90,6 @@ struct _GstQaMonitorClass { /* normal GObject stuff */ GType gst_qa_monitor_get_type (void); -void gst_qa_monitor_do_report (GstQaMonitor * monitor, gboolean repeat, - GstQaReportLevel level, GstQaReportArea area, - gint subarea, const gchar * format, ...); - -void gst_qa_monitor_do_report_valist (GstQaMonitor * monitor, gboolean repeat, - GstQaReportLevel level, GstQaReportArea area, - gint subarea, const gchar *format, - va_list var_args); - -void gst_qa_monitor_set_target_name (GstQaMonitor *monitor, - gchar *target_name); - G_END_DECLS #endif /* __GST_QA_MONITOR_H__ */ diff --git a/validate/gst/qa/gst-qa-pad-monitor.c b/validate/gst/qa/gst-qa-pad-monitor.c index 18b029e078..9373d336bd 100644 --- a/validate/gst/qa/gst-qa-pad-monitor.c +++ b/validate/gst/qa/gst-qa-pad-monitor.c @@ -21,6 +21,7 @@ #include "gst-qa-pad-monitor.h" #include "gst-qa-element-monitor.h" +#include "gst-qa-reporter.h" #include #include #include @@ -156,7 +157,7 @@ _check_field_type (GstQaPadMonitor * monitor, GstStructure * structure, gint rejected_types_index = 0; if (!gst_structure_has_field (structure, field)) { - GST_QA_MONITOR_REPORT_WARNING (monitor, FALSE, CAPS_NEGOTIATION, + GST_QA_REPORT_WARNING (GST_QA_REPORTER (monitor), FALSE, CAPS_NEGOTIATION, MISSING_FIELD, "%s is missing from structure: %" GST_PTR_FORMAT, field, structure); return; @@ -174,7 +175,7 @@ _check_field_type (GstQaPadMonitor * monitor, GstStructure * structure, va_end (var_args); joined_types = g_strjoinv (" / ", (gchar **) rejected_types); - GST_QA_MONITOR_REPORT_CRITICAL (monitor, FALSE, CAPS_NEGOTIATION, + GST_QA_REPORT_CRITICAL (GST_QA_REPORTER (monitor), FALSE, CAPS_NEGOTIATION, BAD_FIELD_TYPE, "%s has wrong type %s in structure '%" GST_PTR_FORMAT "'. Expected: %s", field, g_type_name (gst_structure_get_field_type (structure, field)), @@ -444,7 +445,7 @@ gst_qa_pad_monitor_check_caps_fields_proxied (GstQaPadMonitor * monitor, } if (type_match && !found) { - GST_QA_MONITOR_REPORT_WARNING (monitor, FALSE, CAPS_NEGOTIATION, + GST_QA_REPORT_WARNING (monitor, FALSE, CAPS_NEGOTIATION, GET_CAPS, "Peer pad structure '%" GST_PTR_FORMAT "' has no similar version " "on pad's caps '%" GST_PTR_FORMAT "'", otherstructure, caps); @@ -464,7 +465,7 @@ gst_qa_pad_monitor_check_late_serialized_events (GstQaPadMonitor * monitor, SerializedEventData *data = g_ptr_array_index (monitor->serialized_events, i); if (data->timestamp < ts) { - GST_QA_MONITOR_REPORT_WARNING (monitor, FALSE, EVENT, EXPECTED, + GST_QA_REPORT_WARNING (monitor, FALSE, EVENT, EXPECTED, "Serialized event %" GST_PTR_FORMAT " wasn't pushed before expected " "timestamp %" GST_TIME_FORMAT " on pad %s:%s", data->event, GST_TIME_ARGS (data->timestamp), @@ -482,7 +483,7 @@ gst_qa_pad_monitor_check_late_serialized_events (GstQaPadMonitor * monitor, void _parent_set_cb (GstObject * object, GstObject * parent, GstQaMonitor * monitor) { - gst_qa_monitor_set_target_name (monitor, g_strdup_printf ("%s:%s", + gst_qa_reporter_set_name (GST_QA_REPORTER (monitor), g_strdup_printf ("%s:%s", GST_DEBUG_PAD_NAME (object))); } @@ -641,7 +642,7 @@ gst_qa_pad_monitor_check_buffer_timestamp_in_received_range (GstQaPadMonitor * return; } if (!found) { - GST_QA_MONITOR_REPORT_WARNING (monitor, FALSE, BUFFER, TIMESTAMP, + GST_QA_REPORT_WARNING (monitor, FALSE, BUFFER, TIMESTAMP, "Timestamp %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT " is out of range of received input", GST_TIME_ARGS (ts), GST_TIME_ARGS (ts_end)); @@ -657,14 +658,14 @@ gst_qa_pad_monitor_check_first_buffer (GstQaPadMonitor * pad_monitor, if (!pad_monitor->has_segment && PAD_IS_IN_PUSH_MODE (GST_QA_PAD_MONITOR_GET_PAD (pad_monitor))) { - GST_QA_MONITOR_REPORT_WARNING (pad_monitor, FALSE, EVENT, EXPECTED, - "Received buffer before Segment event"); + GST_QA_REPORT_WARNING (GST_QA_REPORTER (pad_monitor), FALSE, EVENT, + EXPECTED, "Received buffer before Segment event"); } if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) { gint64 running_time = gst_segment_to_running_time (&pad_monitor->segment, pad_monitor->segment.format, GST_BUFFER_TIMESTAMP (buffer)); if (running_time != 0) { - GST_QA_MONITOR_REPORT_WARNING (pad_monitor, FALSE, BUFFER, TIMESTAMP, + GST_QA_REPORT_WARNING (pad_monitor, FALSE, BUFFER, TIMESTAMP, "First buffer running time is not 0, it is: %" GST_TIME_FORMAT, GST_TIME_ARGS (running_time)); } @@ -773,7 +774,7 @@ gst_qa_pad_monitor_check_aggregated_return (GstQaPadMonitor * monitor, } if (aggregated != ret) { /* TODO review this error code */ - GST_QA_MONITOR_REPORT_CRITICAL (monitor, TRUE, BUFFER, UNEXPECTED, + GST_QA_REPORT_CRITICAL (monitor, TRUE, BUFFER, UNEXPECTED, "Wrong combined flow return %s(%d). Expected: %s(%d)", gst_flow_get_name (ret), ret, gst_flow_get_name (aggregated), aggregated); @@ -923,7 +924,7 @@ gst_qa_pad_monitor_add_expected_newsegment (GstQaPadMonitor * monitor, othermonitor = g_object_get_data ((GObject *) otherpad, "qa-monitor"); GST_QA_MONITOR_LOCK (othermonitor); if (othermonitor->expected_segment) { - GST_QA_MONITOR_REPORT_WARNING (othermonitor, FALSE, EVENT, EXPECTED, + GST_QA_REPORT_WARNING (othermonitor, FALSE, EVENT, EXPECTED, "expected newsegment event never pushed"); gst_event_unref (othermonitor->expected_segment); } @@ -960,7 +961,8 @@ gst_qa_pad_monitor_common_event_check (GstQaPadMonitor * pad_monitor, if (seqnum == pad_monitor->pending_flush_start_seqnum) { pad_monitor->pending_flush_start_seqnum = 0; } else { - GST_QA_MONITOR_REPORT_ISSUE (pad_monitor, TRUE, EVENT, SEQNUM, + GST_QA_REPORT_ISSUE (GST_QA_REPORTER (pad_monitor), TRUE, EVENT, + SEQNUM, "The expected flush-start seqnum should be the same as the " "one from the event that caused it (probably a seek). Got: %u." " Expected: %u", seqnum, pad_monitor->pending_flush_start_seqnum); @@ -968,7 +970,8 @@ gst_qa_pad_monitor_common_event_check (GstQaPadMonitor * pad_monitor, } if (pad_monitor->pending_flush_stop) { - GST_QA_MONITOR_REPORT_ISSUE (pad_monitor, TRUE, EVENT, UNEXPECTED, + GST_QA_REPORT_ISSUE (GST_QA_REPORTER (pad_monitor), TRUE, EVENT, + UNEXPECTED, "Received flush-start from %" GST_PTR_FORMAT " when flush-stop was expected", GST_EVENT_SRC (event)); } @@ -981,7 +984,8 @@ gst_qa_pad_monitor_common_event_check (GstQaPadMonitor * pad_monitor, if (seqnum == pad_monitor->pending_flush_stop_seqnum) { pad_monitor->pending_flush_stop_seqnum = 0; } else { - GST_QA_MONITOR_REPORT_ISSUE (pad_monitor, TRUE, EVENT, SEQNUM, + GST_QA_REPORT_ISSUE (GST_QA_REPORTER (pad_monitor), TRUE, EVENT, + SEQNUM, "The expected flush-stop seqnum should be the same as the " "one from the event that caused it (probably a seek). Got: %u." " Expected: %u", seqnum, pad_monitor->pending_flush_stop_seqnum); @@ -989,8 +993,8 @@ gst_qa_pad_monitor_common_event_check (GstQaPadMonitor * pad_monitor, } if (!pad_monitor->pending_flush_stop) { - GST_QA_MONITOR_REPORT_ISSUE (pad_monitor, TRUE, EVENT, UNEXPECTED, - "Unexpected flush-stop %p from %" GST_PTR_FORMAT, event, + GST_QA_REPORT_ISSUE (GST_QA_REPORTER (pad_monitor), TRUE, EVENT, + UNEXPECTED, "Unexpected flush-stop %p from %" GST_PTR_FORMAT, event, GST_EVENT_SRC (event)); } pad_monitor->pending_flush_stop = FALSE; @@ -1050,7 +1054,7 @@ gst_qa_pad_monitor_sink_event_check (GstQaPadMonitor * pad_monitor, || (exp_rate * exp_applied_rate != rate * applied_rate) || exp_start != start || exp_stop != stop || exp_position != position) { - GST_QA_MONITOR_REPORT_WARNING (pad_monitor, TRUE, EVENT, + GST_QA_REPORT_WARNING (pad_monitor, TRUE, EVENT, EXPECTED, "Expected segment didn't match received segment event"); } @@ -1147,7 +1151,6 @@ gst_qa_pad_monitor_src_event_check (GstQaPadMonitor * pad_monitor, pad_monitor->pending_newsegment_seqnum = seqnum; } break; - /* both flushes are handled by the common event handling function */ case GST_EVENT_FLUSH_START: case GST_EVENT_FLUSH_STOP: @@ -1317,7 +1320,7 @@ gst_qa_pad_monitor_buffer_probe (GstPad * pad, GstBuffer * buffer, GST_BUFFER_TIMESTAMP (buffer), GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer), NULL, NULL)) { /* TODO is this a timestamp issue? */ - GST_QA_MONITOR_REPORT_ISSUE (monitor, FALSE, BUFFER, TIMESTAMP, + GST_QA_REPORT_ISSUE (monitor, FALSE, BUFFER, TIMESTAMP, "buffer is out of segment and shouldn't be pushed. Timestamp: %" GST_TIME_FORMAT " - duration: %" GST_TIME_FORMAT ". Range: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT, @@ -1361,7 +1364,7 @@ gst_qa_pad_monitor_event_probe (GstPad * pad, GstEvent * event, gpointer udata) if (event == stored_event->event || GST_EVENT_TYPE (event) == GST_EVENT_TYPE (stored_event->event)) { - GST_QA_MONITOR_REPORT_WARNING (monitor, FALSE, EVENT, UNEXPECTED, + GST_QA_REPORT_WARNING (monitor, FALSE, EVENT, UNEXPECTED, "Serialized event %" GST_PTR_FORMAT " was pushed out of original " "serialization order in pad %s:%s", event, GST_DEBUG_PAD_NAME (GST_QA_PAD_MONITOR_GET_PAD (monitor))); @@ -1432,12 +1435,12 @@ gst_qa_pad_monitor_setcaps_func (GstPad * pad, GstCaps * caps) gst_structure_get_value (pad_monitor->pending_setcaps_fields, name); if (v == NULL) { - GST_QA_MONITOR_REPORT_WARNING (pad_monitor, FALSE, CAPS_NEGOTIATION, + GST_QA_REPORT_WARNING (pad_monitor, FALSE, CAPS_NEGOTIATION, MISSING_FIELD, "Field %s is missing from setcaps caps '%" GST_PTR_FORMAT "'", name, caps); } else if (gst_value_compare (v, otherv) != GST_VALUE_EQUAL) { - GST_QA_MONITOR_REPORT_WARNING (pad_monitor, FALSE, CAPS_NEGOTIATION, + GST_QA_REPORT_WARNING (pad_monitor, FALSE, CAPS_NEGOTIATION, MISSING_FIELD, "Field %s from setcaps caps '%" GST_PTR_FORMAT "' is different " "from expected value in caps '%" GST_PTR_FORMAT "'", name, caps, @@ -1535,7 +1538,7 @@ gst_qa_pad_monitor_do_setup (GstQaMonitor * monitor) gst_pad_set_getcaps_function (pad, gst_qa_pad_monitor_getcaps_func); gst_pad_set_setcaps_function (pad, gst_qa_pad_monitor_setcaps_func); - gst_qa_monitor_set_target_name (monitor, g_strdup_printf ("%s:%s", + gst_qa_reporter_set_name (GST_QA_REPORTER (monitor), g_strdup_printf ("%s:%s", GST_DEBUG_PAD_NAME (pad))); g_signal_connect (pad, "parent-set", (GCallback) _parent_set_cb, monitor); diff --git a/validate/gst/qa/gst-qa-report.c b/validate/gst/qa/gst-qa-report.c index 55702a4554..2bdf1d87be 100644 --- a/validate/gst/qa/gst-qa-report.c +++ b/validate/gst/qa/gst-qa-report.c @@ -176,7 +176,7 @@ gst_qa_report_check_abort (GstQaReport * report) } GstQaReport * -gst_qa_report_new (GstQaMonitor * monitor, GstQaReportLevel level, +gst_qa_report_new (const gchar * source_name, GstQaReportLevel level, GstQaReportArea area, gint subarea, const gchar * id, const gchar * message) { GstQaReport *report = g_slice_new0 (GstQaReport); @@ -184,7 +184,7 @@ gst_qa_report_new (GstQaMonitor * monitor, GstQaReportLevel level, report->level = level; report->area = area; report->subarea = subarea; - report->source_name = g_strdup (monitor->target_name); + report->source_name = g_strdup (source_name); report->message = g_strdup (message); report->id = g_strdup (id); report->timestamp = gst_util_get_timestamp () - _gst_qa_report_start_time; diff --git a/validate/gst/qa/gst-qa-report.h b/validate/gst/qa/gst-qa-report.h index 3edc9f70cf..b3e4ada3a1 100644 --- a/validate/gst/qa/gst-qa-report.h +++ b/validate/gst/qa/gst-qa-report.h @@ -108,7 +108,8 @@ typedef struct { r->message void gst_qa_report_init (void); -GstQaReport * gst_qa_report_new (GstQaMonitor * monitor, GstQaReportLevel level, +GstQaReport * gst_qa_report_new (const gchar * source_name, + GstQaReportLevel level, GstQaReportArea area, gint subarea, const gchar *format, diff --git a/validate/gst/qa/gst-qa-reporter.c b/validate/gst/qa/gst-qa-reporter.c new file mode 100644 index 0000000000..06f1d5b9c7 --- /dev/null +++ b/validate/gst/qa/gst-qa-reporter.c @@ -0,0 +1,142 @@ +/* GStreamer + * + * Copyright (C) 2013 Thibault Saunier + * + * 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 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. + */ +#include "gst-qa-reporter.h" +#include "gst-qa-report.h" + +#define REPORTER_PRIVATE "gst-qa-reporter-private" + +typedef struct _GstQaReporterPrivate +{ + GstQaRunner *runner; + GHashTable *reports; + char *name; +} GstQaReporterPrivate; + +static void +gst_qa_reporter_default_init (GstQaReporterInterface * iface) +{ + g_object_interface_install_property (iface, + g_param_spec_object ("qa-runner", "QA Runner", "The QA runner to " + "report errors to", GST_TYPE_QA_RUNNER, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); +} + +G_DEFINE_INTERFACE (GstQaReporter, gst_qa_reporter, G_TYPE_OBJECT); + +static void +_free_priv (GstQaReporterPrivate * priv) +{ + g_hash_table_unref (priv->reports); + g_free (priv->name); +} + +static inline gchar * +_qa_report_id (GstQaReport * report) +{ + return g_strdup_printf ("%i-%i-%i-%s", + report->level, report->area, report->subarea, report->id); +} + +static GstQaReporterPrivate * +gst_qa_reporter_get_priv (GstQaReporter * reporter) +{ + GstQaReporterPrivate *priv = + g_object_get_data (G_OBJECT (reporter), REPORTER_PRIVATE); + + if (priv == NULL) { + priv = g_slice_new0 (GstQaReporterPrivate); + priv->reports = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) gst_qa_report_unref); + + g_object_set_data_full (G_OBJECT (reporter), REPORTER_PRIVATE, priv, + (GDestroyNotify) _free_priv); + } + + return priv; +} + +void +gst_qa_report_valist (GstQaReporter * reporter, gboolean repeat, + GstQaReportLevel level, GstQaReportArea area, + gint subarea, const gchar * format, va_list var_args) +{ + GstQaReport *report; + gchar *message, *report_id = NULL; + GstQaReporterPrivate *priv = gst_qa_reporter_get_priv (reporter); + + message = g_strdup_vprintf (format, var_args); + report = gst_qa_report_new (priv->name, level, area, subarea, + format, message); + + if (repeat == FALSE) { + report_id = _qa_report_id (report); + + if (g_hash_table_lookup (priv->reports, report_id)) { + GST_DEBUG ("Report %s already present", report_id); + g_free (report_id); + return; + } + + g_hash_table_insert (priv->reports, report_id, report); + } + + GST_INFO_OBJECT (reporter, "Received error report %d : %d : %d : %s", + level, area, subarea, message); + gst_qa_report_printf (report); + if (priv->runner) { + gst_qa_runner_add_report (priv->runner, report); + } else { + gst_qa_report_unref (report); + } + + g_free (message); +} + +void +gst_qa_report (GstQaReporter * reporter, gboolean repeat, + GstQaReportLevel level, GstQaReportArea area, + gint subarea, const gchar * format, ...) +{ + va_list var_args; + + va_start (var_args, format); + gst_qa_report_valist (reporter, repeat, level, area, subarea, + format, var_args); + va_end (var_args); +} + +void +gst_qa_reporter_set_name (GstQaReporter * reporter, const gchar * name) +{ + GstQaReporterPrivate *priv = gst_qa_reporter_get_priv (reporter); + + if (priv->name) + g_free (priv->name); + + priv->name = g_strdup (name); +} + +GstQaRunner * +gst_qa_reporter_get_runner (GstQaReporter * reporter) +{ + GstQaReporterPrivate *priv = gst_qa_reporter_get_priv (reporter); + + return priv->runner; +} diff --git a/validate/gst/qa/gst-qa-reporter.h b/validate/gst/qa/gst-qa-reporter.h new file mode 100644 index 0000000000..bdab066f7b --- /dev/null +++ b/validate/gst/qa/gst-qa-reporter.h @@ -0,0 +1,122 @@ +/* GStreamer + * + * Copyright (C) 2013 Thibault Saunier + * + * 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 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_QA_REPORTER_ +#define _GST_QA_REPORTER_ + +#include +#include "gst-qa-runner.h" + +G_BEGIN_DECLS + +typedef struct _GstQaReporter GstQaReporter; +typedef struct _GstQaReporterInterface GstQaReporterInterface; + +/* GstQaReporter interface declarations */ +#define GST_TYPE_QA_REPORTER (gst_qa_reporter_get_type ()) +#define GST_QA_REPORTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_QA_REPORTER, GstQaReporter)) +#define GST_IS_QA_REPORTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_QA_REPORTER)) +#define GST_QA_REPORTER_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_QA_REPORTER, GESExtractableInterface)) + +#ifdef G_HAVE_ISO_VARARGS +#define GST_QA_REPORT(m, repeat, status, area, subarea, ...) \ +G_STMT_START { \ + gst_qa_report (GST_QA_REPORTER (m), repeat, \ + GST_QA_REPORT_LEVEL_ ## status, GST_QA_AREA_ ## area, \ + GST_QA_AREA_ ## area ## _ ## subarea, __VA_ARGS__ ); \ +} G_STMT_END + +#define GST_QA_REPORT_CRITICAL(m, repeat, area, subarea, ...) \ +G_STMT_START { \ + GST_ERROR_OBJECT (m, "Critical report: %s: %s: %s", \ + #area, #subarea, __VA_ARGS__); \ + GST_QA_REPORT(m, repeat, CRITICAL, area, subarea, __VA_ARGS__); \ +} G_STMT_END + +#define GST_QA_REPORT_WARNING(m, repeat, area, subarea, ...) \ +G_STMT_START { \ + GST_WARNING_OBJECT (m, "Warning report: %s: %s: %s", \ + #area, #subarea, __VA_ARGS__); \ + GST_QA_REPORT(m, repeat, WARNING, area, subarea, __VA_ARGS__); \ +} G_STMT_END + +#define GST_QA_REPORT_ISSUE(m, repeat, area, subarea, ...) \ +G_STMT_START { \ + GST_WARNING_OBJECT (m, "Issue report: %s: %s: %s", \ + #area, #subarea, __VA_ARGS__); \ + GST_QA_REPORT(m, repeat, ISSUE, area, subarea, __VA_ARGS__); \ +} G_STMT_END +#else /* G_HAVE_GNUC_VARARGS */ +#ifdef G_HAVE_GNUC_VARARGS +#define GST_QA_REPORT(m, repeat, status, area, subarea, args...) \ +G_STMT_START { \ + gst_qa_reporter_do_report (GST_QA_REPORTER (m), \ + GST_QA_REPORT_LEVEL_ ## status, GST_QA_AREA_ ## area, \ + GST_QA_AREA_ ## area ## _ ## subarea, ##args ); \ +} G_STMT_END + +#define GST_QA_REPORT_CRITICAL(m, repeat, area, subarea, args...) \ +G_STMT_START { \ + GST_ERROR_OBJECT (m, "Critical report: %s: %s: %s", \ + #area, #subarea, ##args); \ + GST_QA_REPORT(m, repeat, CRITICAL, area, subarea, ##args); \ +} G_STMT_END + +#define GST_QA_REPORT_WARNING(m, repeat, area, subarea, args...) \ +G_STMT_START { \ + GST_WARNING_OBJECT (m, "Warning report: %s: %s: %s", \ + #area, #subarea, ##args); \ + GST_QA_REPORT(m, repeat, WARNING, area, subarea, ##args); \ +} G_STMT_END + +#define GST_QA_REPORT_ISSUE(m, repeat, area, subarea, args...) \ +G_STMT_START { \ + GST_WARNING_OBJECT (m, "Issue report: %s: %s: %s", \ + #area, #subarea, ##args); \ + GST_QA_REPORT(m, repeat, ISSUE, area, subarea, ##args); \ +} G_STMT_END +#endif /* G_HAVE_ISO_VARARGS */ +#endif /* G_HAVE_GNUC_VARARGS */ + +GType gst_qa_reporter_get_type (void); + +/** + * GstQaReporter: + */ +struct _GstQaReporterInterface +{ + GTypeInterface parent; +}; + +void gst_qa_reporter_set_name (GstQaReporter * reporter, + const gchar * name); +GstQaRunner * gst_qa_reporter_get_runner (GstQaReporter *reporter); +void gst_qa_reporter_init (GstQaReporter * reporter, const gchar *name); +void gst_qa_report (GstQaReporter * reporter, gboolean repeat, + GstQaReportLevel level, GstQaReportArea area, + gint subarea, const gchar * format, ...); +void gst_qa_report_valist (GstQaReporter * reporter, gboolean repeat, + GstQaReportLevel level, GstQaReportArea area, + gint subarea, const gchar * format, va_list var_args); + +G_END_DECLS +#endif /* _GST_QA_REPORTER_ */ + + +