qa: Add a GstQaReporter interface that objects needing reporting can implement

Various type of object should be able to do some reporting, so we have
to make sure all the code to do that is in one place. Creating an interface
makes it simple to share information and it avoid to have a baseclass for
something that is not actually important enough to create a baseclass.

Conflicts:
	gst/qa/gst-qa-pad-monitor.c
This commit is contained in:
Thibault Saunier 2013-07-22 19:17:53 -04:00 committed by Thiago Santos
parent 7508e35b7e
commit 4992249848
9 changed files with 304 additions and 173 deletions

View File

@ -1,3 +1,3 @@
confdir=${sysconfdir}/gstreamer scenariosdir=${datadir}/gstreamer-$(GST_API_VERSION)/qa-scenario
conf_DATA = simple_seeks.xml scenarios_DATA = simple_seeks.xml
EXTRA_DIST = simple_seeks.xml EXTRA_DIST = simple_seeks.xml

View File

@ -3,6 +3,7 @@ public_headers = \
c_sources = \ c_sources = \
gst-qa-runner.c \ gst-qa-runner.c \
gst-qa-reporter.c \
gst-qa-monitor.c \ gst-qa-monitor.c \
gst-qa-element-monitor.c \ gst-qa-element-monitor.c \
gst-qa-bin-monitor.c \ gst-qa-bin-monitor.c \

View File

@ -20,6 +20,7 @@
*/ */
#include "gst-qa-monitor.h" #include "gst-qa-monitor.h"
#include "gst-qa-reporter.h"
/** /**
* SECTION:gst-qa-monitor * 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 GST_CAT_DEFAULT gst_qa_monitor_debug
#define _do_init \ #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 #define gst_qa_monitor_parent_class parent_class
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstQaMonitor, gst_qa_monitor, G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstQaMonitor, gst_qa_monitor,
G_TYPE_OBJECT, _do_init); G_TYPE_OBJECT, _do_init);
@ -76,17 +80,13 @@ gst_qa_monitor_dispose (GObject * object)
g_object_weak_unref (G_OBJECT (monitor->target), g_object_weak_unref (G_OBJECT (monitor->target),
(GWeakNotify) _target_freed_cb, monitor); (GWeakNotify) _target_freed_cb, monitor);
g_hash_table_unref (monitor->reports);
G_OBJECT_CLASS (parent_class)->dispose (object); G_OBJECT_CLASS (parent_class)->dispose (object);
} }
static void static void
gst_qa_monitor_finalize (GObject * object) gst_qa_monitor_finalize (GObject * object)
{ {
GstQaMonitor *monitor = GST_QA_MONITOR_CAST (object); gst_qa_reporter_set_name (GST_QA_REPORTER (object), NULL);
gst_qa_monitor_set_target_name (monitor, NULL);
G_OBJECT_CLASS (parent_class)->dispose (object); G_OBJECT_CLASS (parent_class)->dispose (object);
} }
@ -133,20 +133,11 @@ gst_qa_monitor_constructor (GType type, guint n_construct_params,
return (GObject *) monitor; 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 static void
gst_qa_monitor_init (GstQaMonitor * monitor) gst_qa_monitor_init (GstQaMonitor * monitor)
{ {
g_mutex_init (&monitor->mutex); 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); (GWeakNotify) _target_freed_cb, monitor);
if (monitor->target) 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))); (GST_OBJECT_NAME (monitor->target)));
break; break;
case PROP_RUNNER: case PROP_RUNNER:
@ -238,60 +229,3 @@ gst_qa_monitor_get_property (GObject * object, guint prop_id,
break; 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;
}

View File

@ -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_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)) #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, /* #else TODO Implemen no variadic macros, use inline,
* Problem being: * Problem being:
* GST_QA_REPORT_LEVEL_ ## status * GST_QA_REPORT_LEVEL_ ## status
@ -150,18 +90,6 @@ struct _GstQaMonitorClass {
/* normal GObject stuff */ /* normal GObject stuff */
GType gst_qa_monitor_get_type (void); 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 G_END_DECLS
#endif /* __GST_QA_MONITOR_H__ */ #endif /* __GST_QA_MONITOR_H__ */

View File

@ -21,6 +21,7 @@
#include "gst-qa-pad-monitor.h" #include "gst-qa-pad-monitor.h"
#include "gst-qa-element-monitor.h" #include "gst-qa-element-monitor.h"
#include "gst-qa-reporter.h"
#include <gst/gst.h> #include <gst/gst.h>
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
@ -156,7 +157,7 @@ _check_field_type (GstQaPadMonitor * monitor, GstStructure * structure,
gint rejected_types_index = 0; gint rejected_types_index = 0;
if (!gst_structure_has_field (structure, field)) { 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, MISSING_FIELD, "%s is missing from structure: %" GST_PTR_FORMAT, field,
structure); structure);
return; return;
@ -174,7 +175,7 @@ _check_field_type (GstQaPadMonitor * monitor, GstStructure * structure,
va_end (var_args); va_end (var_args);
joined_types = g_strjoinv (" / ", (gchar **) rejected_types); 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 BAD_FIELD_TYPE, "%s has wrong type %s in structure '%" GST_PTR_FORMAT
"'. Expected: %s", field, "'. Expected: %s", field,
g_type_name (gst_structure_get_field_type (structure, 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) { if (type_match && !found) {
GST_QA_MONITOR_REPORT_WARNING (monitor, FALSE, CAPS_NEGOTIATION, GST_QA_REPORT_WARNING (monitor, FALSE, CAPS_NEGOTIATION,
GET_CAPS, GET_CAPS,
"Peer pad structure '%" GST_PTR_FORMAT "' has no similar version " "Peer pad structure '%" GST_PTR_FORMAT "' has no similar version "
"on pad's caps '%" GST_PTR_FORMAT "'", otherstructure, caps); "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 = SerializedEventData *data =
g_ptr_array_index (monitor->serialized_events, i); g_ptr_array_index (monitor->serialized_events, i);
if (data->timestamp < ts) { 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 " "Serialized event %" GST_PTR_FORMAT " wasn't pushed before expected "
"timestamp %" GST_TIME_FORMAT " on pad %s:%s", data->event, "timestamp %" GST_TIME_FORMAT " on pad %s:%s", data->event,
GST_TIME_ARGS (data->timestamp), GST_TIME_ARGS (data->timestamp),
@ -482,7 +483,7 @@ gst_qa_pad_monitor_check_late_serialized_events (GstQaPadMonitor * monitor,
void void
_parent_set_cb (GstObject * object, GstObject * parent, GstQaMonitor * monitor) _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))); GST_DEBUG_PAD_NAME (object)));
} }
@ -641,7 +642,7 @@ gst_qa_pad_monitor_check_buffer_timestamp_in_received_range (GstQaPadMonitor *
return; return;
} }
if (!found) { 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 "Timestamp %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT
" is out of range of received input", GST_TIME_ARGS (ts), " is out of range of received input", GST_TIME_ARGS (ts),
GST_TIME_ARGS (ts_end)); GST_TIME_ARGS (ts_end));
@ -657,14 +658,14 @@ gst_qa_pad_monitor_check_first_buffer (GstQaPadMonitor * pad_monitor,
if (!pad_monitor->has_segment if (!pad_monitor->has_segment
&& PAD_IS_IN_PUSH_MODE (GST_QA_PAD_MONITOR_GET_PAD (pad_monitor))) { && PAD_IS_IN_PUSH_MODE (GST_QA_PAD_MONITOR_GET_PAD (pad_monitor))) {
GST_QA_MONITOR_REPORT_WARNING (pad_monitor, FALSE, EVENT, EXPECTED, GST_QA_REPORT_WARNING (GST_QA_REPORTER (pad_monitor), FALSE, EVENT,
"Received buffer before Segment event"); EXPECTED, "Received buffer before Segment event");
} }
if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) { if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) {
gint64 running_time = gst_segment_to_running_time (&pad_monitor->segment, gint64 running_time = gst_segment_to_running_time (&pad_monitor->segment,
pad_monitor->segment.format, GST_BUFFER_TIMESTAMP (buffer)); pad_monitor->segment.format, GST_BUFFER_TIMESTAMP (buffer));
if (running_time != 0) { 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, "First buffer running time is not 0, it is: %" GST_TIME_FORMAT,
GST_TIME_ARGS (running_time)); GST_TIME_ARGS (running_time));
} }
@ -773,7 +774,7 @@ gst_qa_pad_monitor_check_aggregated_return (GstQaPadMonitor * monitor,
} }
if (aggregated != ret) { if (aggregated != ret) {
/* TODO review this error code */ /* 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)", "Wrong combined flow return %s(%d). Expected: %s(%d)",
gst_flow_get_name (ret), ret, gst_flow_get_name (ret), ret,
gst_flow_get_name (aggregated), aggregated); 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"); othermonitor = g_object_get_data ((GObject *) otherpad, "qa-monitor");
GST_QA_MONITOR_LOCK (othermonitor); GST_QA_MONITOR_LOCK (othermonitor);
if (othermonitor->expected_segment) { 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"); "expected newsegment event never pushed");
gst_event_unref (othermonitor->expected_segment); 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) { if (seqnum == pad_monitor->pending_flush_start_seqnum) {
pad_monitor->pending_flush_start_seqnum = 0; pad_monitor->pending_flush_start_seqnum = 0;
} else { } 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 " "The expected flush-start seqnum should be the same as the "
"one from the event that caused it (probably a seek). Got: %u." "one from the event that caused it (probably a seek). Got: %u."
" Expected: %u", seqnum, pad_monitor->pending_flush_start_seqnum); " 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) { 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 "Received flush-start from %" GST_PTR_FORMAT
" when flush-stop was expected", GST_EVENT_SRC (event)); " 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) { if (seqnum == pad_monitor->pending_flush_stop_seqnum) {
pad_monitor->pending_flush_stop_seqnum = 0; pad_monitor->pending_flush_stop_seqnum = 0;
} else { } 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 " "The expected flush-stop seqnum should be the same as the "
"one from the event that caused it (probably a seek). Got: %u." "one from the event that caused it (probably a seek). Got: %u."
" Expected: %u", seqnum, pad_monitor->pending_flush_stop_seqnum); " 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) { 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 flush-stop %p from %" GST_PTR_FORMAT, event, UNEXPECTED, "Unexpected flush-stop %p from %" GST_PTR_FORMAT, event,
GST_EVENT_SRC (event)); GST_EVENT_SRC (event));
} }
pad_monitor->pending_flush_stop = FALSE; 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_rate * exp_applied_rate != rate * applied_rate)
|| exp_start != start || exp_stop != stop || exp_start != start || exp_stop != stop
|| exp_position != position) { || exp_position != position) {
GST_QA_MONITOR_REPORT_WARNING (pad_monitor, TRUE, EVENT, GST_QA_REPORT_WARNING (pad_monitor, TRUE, EVENT,
EXPECTED, EXPECTED,
"Expected segment didn't match received segment event"); "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; pad_monitor->pending_newsegment_seqnum = seqnum;
} }
break; break;
/* both flushes are handled by the common event handling function */ /* both flushes are handled by the common event handling function */
case GST_EVENT_FLUSH_START: case GST_EVENT_FLUSH_START:
case GST_EVENT_FLUSH_STOP: 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_TIMESTAMP (buffer), GST_BUFFER_TIMESTAMP (buffer) +
GST_BUFFER_DURATION (buffer), NULL, NULL)) { GST_BUFFER_DURATION (buffer), NULL, NULL)) {
/* TODO is this a timestamp issue? */ /* 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: %" "buffer is out of segment and shouldn't be pushed. Timestamp: %"
GST_TIME_FORMAT " - duration: %" GST_TIME_FORMAT GST_TIME_FORMAT " - duration: %" GST_TIME_FORMAT
". Range: %" GST_TIME_FORMAT " - %" 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 if (event == stored_event->event
|| GST_EVENT_TYPE (event) == GST_EVENT_TYPE (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 " "Serialized event %" GST_PTR_FORMAT " was pushed out of original "
"serialization order in pad %s:%s", event, "serialization order in pad %s:%s", event,
GST_DEBUG_PAD_NAME (GST_QA_PAD_MONITOR_GET_PAD (monitor))); 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); gst_structure_get_value (pad_monitor->pending_setcaps_fields, name);
if (v == NULL) { if (v == NULL) {
GST_QA_MONITOR_REPORT_WARNING (pad_monitor, FALSE, CAPS_NEGOTIATION, GST_QA_REPORT_WARNING (pad_monitor, FALSE, CAPS_NEGOTIATION,
MISSING_FIELD, MISSING_FIELD,
"Field %s is missing from setcaps caps '%" GST_PTR_FORMAT "'", "Field %s is missing from setcaps caps '%" GST_PTR_FORMAT "'",
name, caps); name, caps);
} else if (gst_value_compare (v, otherv) != GST_VALUE_EQUAL) { } 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, MISSING_FIELD,
"Field %s from setcaps caps '%" GST_PTR_FORMAT "' is different " "Field %s from setcaps caps '%" GST_PTR_FORMAT "' is different "
"from expected value in caps '%" GST_PTR_FORMAT "'", name, caps, "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_getcaps_function (pad, gst_qa_pad_monitor_getcaps_func);
gst_pad_set_setcaps_function (pad, gst_qa_pad_monitor_setcaps_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))); GST_DEBUG_PAD_NAME (pad)));
g_signal_connect (pad, "parent-set", (GCallback) _parent_set_cb, monitor); g_signal_connect (pad, "parent-set", (GCallback) _parent_set_cb, monitor);

View File

@ -176,7 +176,7 @@ gst_qa_report_check_abort (GstQaReport * report)
} }
GstQaReport * 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) GstQaReportArea area, gint subarea, const gchar * id, const gchar * message)
{ {
GstQaReport *report = g_slice_new0 (GstQaReport); GstQaReport *report = g_slice_new0 (GstQaReport);
@ -184,7 +184,7 @@ gst_qa_report_new (GstQaMonitor * monitor, GstQaReportLevel level,
report->level = level; report->level = level;
report->area = area; report->area = area;
report->subarea = subarea; report->subarea = subarea;
report->source_name = g_strdup (monitor->target_name); report->source_name = g_strdup (source_name);
report->message = g_strdup (message); report->message = g_strdup (message);
report->id = g_strdup (id); report->id = g_strdup (id);
report->timestamp = gst_util_get_timestamp () - _gst_qa_report_start_time; report->timestamp = gst_util_get_timestamp () - _gst_qa_report_start_time;

View File

@ -108,7 +108,8 @@ typedef struct {
r->message r->message
void gst_qa_report_init (void); 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, GstQaReportArea area,
gint subarea, gint subarea,
const gchar *format, const gchar *format,

View File

@ -0,0 +1,142 @@
/* GStreamer
*
* Copyright (C) 2013 Thibault Saunier <thibault.saunier@collabora.com>
*
* 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;
}

View File

@ -0,0 +1,122 @@
/* GStreamer
*
* Copyright (C) 2013 Thibault Saunier <thibault.saunier@collabora.com>
*
* 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 <glib-object.h>
#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_ */