validate:flow: Make field filtering in what is logged more generic

Instead of forcing it on event, allow specifying filters on anything
we log, meaning also buffers
This commit is contained in:
Thibault Saunier 2020-02-04 18:14:25 -03:00 committed by Thibault Saunier
parent 39d6c7760e
commit db2acf1cdf
4 changed files with 94 additions and 55 deletions

View file

@ -85,8 +85,8 @@ In order to use the plugin a validate configuration file must be provided, conta
* `pad`: Required. Name of the pad that will be monitored.
* `record-buffers`: Default: false. Whether buffers will be logged. By default only events are logged.
* `buffers-checksum`: Default: false. Whether a checkum of the buffer data is logged. Implies `record-buffers`.
* `ignored-event-fields`: Default: `"stream-start={ stream-id }"` (as they are often non reproducible). Key with a serialized GstValueList(str) of fields to not record.
* `logged-event-fields`: Default: `NULL` Key with a serialized GstValueList(str) of fields to record, eg. `logged-event-fields="stream-start={flags}, caps={width, height, framerate}"`. Overrides `ignored-event-fields` for specified event types.
* `ignored-fields`: Default: `"stream-start={ stream-id }"` (as they are often non reproducible). Key with a serialized GstValueList(str) of fields to not record.
* `logged-fields`: Default: `NULL` Key with a serialized GstValueList(str) of fields to record, eg. `logged-event-fields="stream-start={flags}, caps={width, height, framerate}, buffer={pts}"`. Overrides `ignored-event-fields` for specified event types.
* `ignored-event-types`: Default: `{ }`. List of event type names to not record
* `logged-event-types`: Default: `NULL`. List of event type names to not record, if noone provided, all events are logged, except the ones defined in the `ignored-event-types`.
* `expectations-dir`: Path to the directory where the expectations will be written if they don't exist, relative to the current working directory. By default the current working directory is used, but this setting is usually set automatically as part of the `%(validateflow)s` expansion to a correct path like `~/gst-validate/gst-integration-testsuites/flow-expectations/<test name>`.

View file

@ -37,6 +37,21 @@
typedef void (*Uint64Formatter) (gchar * dest, guint64 time);
#define CONSTIFY(strv) ((const gchar * const *) strv)
static gboolean
use_field (const gchar * field, gchar ** logged, gchar ** ignored)
{
if (logged)
return g_strv_contains (CONSTIFY (logged), field);
if (ignored)
return !g_strv_contains (CONSTIFY (ignored), field);
return TRUE;
}
void
format_time (gchar * dest_str, guint64 time)
{
@ -54,11 +69,12 @@ format_number (gchar * dest_str, guint64 number)
}
gchar *
validate_flow_format_segment (const GstSegment * segment)
validate_flow_format_segment (const GstSegment * segment,
gchar ** logged_fields, gchar ** ignored_fields)
{
Uint64Formatter uint64_format;
gchar *segment_str;
gchar *parts[7];
gchar *parts[10];
GString *format;
gchar start_str[32], offset_str[32], stop_str[32], time_str[32], base_str[32],
position_str[32], duration_str[32];
@ -76,9 +92,19 @@ validate_flow_format_segment (const GstSegment * segment)
format = g_string_new (gst_format_get_name (segment->format));
format = g_string_ascii_up (format);
parts[parts_index++] =
g_strdup_printf ("format=%s, start=%s, offset=%s, stop=%s", format->str,
start_str, offset_str, stop_str);
if (use_field ("format", logged_fields, ignored_fields))
parts[parts_index++] = g_strdup_printf ("format=%s", format->str);
if (use_field ("start", logged_fields, ignored_fields))
parts[parts_index++] = g_strdup_printf ("start=%s", start_str);
if (use_field ("offset", logged_fields, ignored_fields))
parts[parts_index++] = g_strdup_printf ("offset=%s", offset_str);
if (use_field ("stop", logged_fields, ignored_fields))
parts[parts_index++] = g_strdup_printf ("stop=%s", stop_str);
if (segment->rate != 1.0)
parts[parts_index++] = g_strdup_printf ("rate=%f", segment->rate);
if (segment->applied_rate != 1.0)
@ -193,15 +219,23 @@ buffer_get_meta_string (GstBuffer * buffer)
}
gchar *
validate_flow_format_buffer (GstBuffer * buffer, gboolean add_checksum)
validate_flow_format_buffer (GstBuffer * buffer, gboolean add_checksum,
GstStructure * logged_fields_struct, GstStructure * ignored_fields_struct)
{
gchar *flags_str, *meta_str, *buffer_str;
gchar *buffer_parts[7];
int buffer_parts_index = 0;
gchar *sum;
GstMapInfo map;
gchar **logged_fields =
logged_fields_struct ? gst_validate_utils_get_strv (logged_fields_struct,
"buffer") : NULL;
gchar **ignored_fields =
ignored_fields_struct ?
gst_validate_utils_get_strv (ignored_fields_struct, "buffer") : NULL;
if (add_checksum) {
if (add_checksum || (logged_fields
&& g_strv_contains (CONSTIFY (logged_fields), "checksum"))) {
if (!gst_buffer_map (buffer, &map, GST_MAP_READ)) {
GST_ERROR ("Buffer could not be mapped.");
} else {
@ -213,32 +247,35 @@ validate_flow_format_buffer (GstBuffer * buffer, gboolean add_checksum)
}
}
if (GST_CLOCK_TIME_IS_VALID (buffer->dts)) {
if (GST_CLOCK_TIME_IS_VALID (buffer->dts)
&& use_field ("dts", logged_fields, ignored_fields)) {
gchar time_str[32];
format_time (time_str, buffer->dts);
buffer_parts[buffer_parts_index++] = g_strdup_printf ("dts=%s", time_str);
}
if (GST_CLOCK_TIME_IS_VALID (buffer->pts)) {
if (GST_CLOCK_TIME_IS_VALID (buffer->pts)
&& use_field ("pts", logged_fields, ignored_fields)) {
gchar time_str[32];
format_time (time_str, buffer->pts);
buffer_parts[buffer_parts_index++] = g_strdup_printf ("pts=%s", time_str);
}
if (GST_CLOCK_TIME_IS_VALID (buffer->duration)) {
if (GST_CLOCK_TIME_IS_VALID (buffer->duration)
&& use_field ("dur", logged_fields, ignored_fields)) {
gchar time_str[32];
format_time (time_str, buffer->duration);
buffer_parts[buffer_parts_index++] = g_strdup_printf ("dur=%s", time_str);
}
flags_str = buffer_get_flags_string (buffer);
if (flags_str) {
if (flags_str && use_field ("flags", logged_fields, ignored_fields)) {
buffer_parts[buffer_parts_index++] =
g_strdup_printf ("flags=%s", flags_str);
}
meta_str = buffer_get_meta_string (buffer);
if (meta_str)
if (meta_str && use_field ("meta", logged_fields, ignored_fields))
buffer_parts[buffer_parts_index++] = g_strdup_printf ("meta=%s", meta_str);
buffer_parts[buffer_parts_index] = NULL;
@ -257,8 +294,8 @@ validate_flow_format_buffer (GstBuffer * buffer, gboolean add_checksum)
gchar *
validate_flow_format_event (GstEvent * event,
const gchar * const *caps_properties,
GstStructure * logged_event_fields,
GstStructure * ignored_event_fields,
GstStructure * logged_fields_struct,
GstStructure * ignored_fields_struct,
const gchar * const *ignored_event_types,
const gchar * const *logged_event_types)
{
@ -276,11 +313,17 @@ validate_flow_format_event (GstEvent * event,
if (ignored_event_types && g_strv_contains (ignored_event_types, event_type))
return NULL;
logged_fields = gst_validate_utils_get_strv (logged_event_fields, event_type);
logged_fields =
logged_fields_struct ? gst_validate_utils_get_strv (logged_fields_struct,
event_type) : NULL;
ignored_fields =
ignored_fields_struct ?
gst_validate_utils_get_strv (ignored_fields_struct, event_type) : NULL;
if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
const GstSegment *segment;
gst_event_parse_segment (event, &segment);
structure_string = validate_flow_format_segment (segment);
structure_string =
validate_flow_format_segment (segment, logged_fields, ignored_fields);
} else if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) {
GstCaps *caps;
gst_event_parse_caps (event, &caps);
@ -298,8 +341,6 @@ validate_flow_format_event (GstEvent * event,
gst_structure_filter_and_map_in_place (printable,
(GstStructureFilterMapFunc) structure_only_given_keys, logged_fields);
} else {
ignored_fields =
gst_validate_utils_get_strv (ignored_event_fields, event_type);
if (ignored_fields) {
gint i = 0;
gchar *field;

View file

@ -27,11 +27,11 @@
void format_time(gchar* dest_str, guint64 time);
gchar* validate_flow_format_segment (const GstSegment *segment);
gchar* validate_flow_format_segment(const GstSegment* segment, gchar** logged_fields, gchar** ignored_fields);
gchar* validate_flow_format_caps (const GstCaps* caps, gchar **keys_to_print);
gchar* validate_flow_format_buffer (GstBuffer *buffer, gboolean add_checksum);
gchar* validate_flow_format_buffer(GstBuffer* buffer, gboolean add_checksum, GstStructure* logged_fields_struct, GstStructure* ignored_fields_struct);
gchar* validate_flow_format_event(GstEvent* event, const gchar* const* caps_properties, GstStructure* logged_event_fields, GstStructure* ignored_event_fields, const gchar* const* ignored_event_types, const gchar* const* logged_event_types);

View file

@ -59,8 +59,8 @@ struct _ValidateFlowOverride
gchar *actual_results_dir;
gboolean error_writing_file;
gchar **caps_properties;
GstStructure *ignored_event_fields;
GstStructure *logged_event_fields;
GstStructure *ignored_fields;
GstStructure *logged_fields;
gchar **logged_event_types;
gchar **ignored_event_types;
@ -164,8 +164,8 @@ validate_flow_override_event_handler (GstValidateOverride * override,
event_string = validate_flow_format_event (event,
(const gchar * const *) flow->caps_properties,
flow->logged_event_fields,
flow->ignored_event_fields,
flow->logged_fields,
flow->ignored_fields,
(const gchar * const *) flow->ignored_event_types,
(const gchar * const *) flow->logged_event_types);
@ -185,7 +185,9 @@ validate_flow_override_buffer_handler (GstValidateOverride * override,
if (flow->error_writing_file || !flow->record_buffers)
return;
buffer_str = validate_flow_format_buffer (buffer, flow->buffers_checksum);
buffer_str =
validate_flow_format_buffer (buffer, flow->buffers_checksum,
flow->logged_fields, flow->ignored_fields);
validate_flow_override_printf (flow, "buffer: %s\n", buffer_str);
g_free (buffer_str);
}
@ -218,7 +220,7 @@ validate_flow_override_new (GstStructure * config)
{
ValidateFlowOverride *flow;
GstValidateOverride *override;
gchar *ignored_event_fields, *logged_event_fields;
gchar *ignored_fields, *logged_fields;
flow = g_object_new (VALIDATE_TYPE_FLOW_OVERRIDE, NULL);
override = GST_VALIDATE_OVERRIDE (flow);
@ -252,40 +254,36 @@ validate_flow_override_new (GstStructure * config)
flow->ignored_event_types =
gst_validate_utils_get_strv (config, "ignored-event-types");
ignored_event_fields =
(gchar *) gst_structure_get_string (config, "ignored-event-fields");
if (ignored_event_fields) {
ignored_event_fields = g_strdup_printf ("ignored,%s", ignored_event_fields);
flow->ignored_event_fields =
gst_structure_new_from_string (ignored_event_fields);
if (!flow->ignored_event_fields)
ignored_fields =
(gchar *) gst_structure_get_string (config, "ignored-fields");
if (ignored_fields) {
ignored_fields = g_strdup_printf ("ignored,%s", ignored_fields);
flow->ignored_fields = gst_structure_new_from_string (ignored_fields);
if (!flow->ignored_fields)
g_error ("Could not parse 'ignored-event-fields' %s in %s",
ignored_event_fields, gst_structure_to_string (config));
g_free (ignored_event_fields);
ignored_fields, gst_structure_to_string (config));
g_free (ignored_fields);
} else {
flow->ignored_event_fields =
flow->ignored_fields =
gst_structure_new_from_string ("ignored,stream-start={stream-id}");
}
if (!gst_structure_has_field (flow->ignored_event_fields, "stream-start"))
gst_structure_set (flow->ignored_event_fields, "stream-start",
G_TYPE_STRING, "{stream-id}", NULL);
if (!gst_structure_has_field (flow->ignored_fields, "stream-start"))
gst_structure_set (flow->ignored_fields, "stream-start",
G_TYPE_STRING, "stream-id", NULL);
logged_event_fields =
(gchar *) gst_structure_get_string (config, "logged-event-fields");
if (logged_event_fields) {
logged_event_fields = g_strdup_printf ("logged,%s", logged_event_fields);
flow->logged_event_fields =
gst_structure_new_from_string (logged_event_fields);
if (!flow->logged_event_fields)
g_error ("Could not parse 'logged-event-fields' %s in %s",
logged_event_fields, gst_structure_to_string (config));
g_free (logged_event_fields);
logged_fields = (gchar *) gst_structure_get_string (config, "logged-fields");
if (logged_fields) {
logged_fields = g_strdup_printf ("logged,%s", logged_fields);
flow->logged_fields = gst_structure_new_from_string (logged_fields);
if (!flow->logged_fields)
g_error ("Could not parse 'logged-fields' %s in %s",
logged_fields, gst_structure_to_string (config));
g_free (logged_fields);
} else {
flow->logged_event_fields = NULL;
flow->logged_fields = NULL;
}
/* expectations-dir: Path to the directory where the expectations will be
* written if they don't exist, relative to the current working directory.
* By default the current working directory is used. */
@ -507,8 +505,8 @@ validate_flow_override_finalize (GObject * object)
g_strfreev (flow->caps_properties);
g_strfreev (flow->logged_event_types);
g_strfreev (flow->ignored_event_types);
if (flow->ignored_event_fields)
gst_structure_free (flow->ignored_event_fields);
if (flow->ignored_fields)
gst_structure_free (flow->ignored_fields);
G_OBJECT_CLASS (validate_flow_override_parent_class)->finalize (object);
}