validateflow: Allow specifying checksum type

And add an extra mode 'checksum-as-id' which basically numerate
buffers checksums as they are being received so that it is simpler
to compare expectations when you are tracking buffers from both
sinkpads and srcpads.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-devtools/-/merge_requests/202>
This commit is contained in:
Thibault Saunier 2020-05-30 15:54:31 -04:00
parent 6a305b1e23
commit 124153fe06
4 changed files with 83 additions and 12 deletions

View file

@ -126,8 +126,17 @@ several overrides and listening to different pads with different settings.
* `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`.
* `buffers-checksum`: Default: 'none'. Define the type of checksums to be used
valid values are:
- none: No checksum recorded
- as-id: Record checksum as 'ids' IDs are incremented on each new checksum
passed in
- md5: md5 checksum
- sha1: sha1 checksum
- sha256: sha256 checksum
- sha512: sha512 checksum
Note that for backward compatibility reasons, this can be passed as a boolean
and it will default to 'sha1' if true, 'none' if false.
* `ignored-fields`: Default: `"stream-start={ stream-id }"` (as they are often
non reproducible). Key with a serialized GstValueList(str) of fields to not
record.

View file

@ -37,6 +37,8 @@
#include "../../gst/validate/gst-validate-utils.h"
typedef void (*Uint64Formatter) (gchar * dest, guint64 time);
G_LOCK_DEFINE (checksums_as_id_lock);
static GstStructure *checksums_as_id = NULL;
#define CONSTIFY(strv) ((const gchar * const *) strv)
@ -226,7 +228,7 @@ buffer_get_meta_string (GstBuffer * buffer)
}
gchar *
validate_flow_format_buffer (GstBuffer * buffer, gboolean add_checksum,
validate_flow_format_buffer (GstBuffer * buffer, gint checksum_type,
GstStructure * logged_fields_struct, GstStructure * ignored_fields_struct)
{
gchar *flags_str, *meta_str, *buffer_str;
@ -241,15 +243,35 @@ validate_flow_format_buffer (GstBuffer * buffer, gboolean add_checksum,
ignored_fields_struct ?
gst_validate_utils_get_strv (ignored_fields_struct, "buffer") : NULL;
if (add_checksum || (logged_fields
if (checksum_type != CHECKSUM_TYPE_NONE || (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 {
sum = g_compute_checksum_for_data (G_CHECKSUM_SHA1, map.data, map.size);
sum =
g_compute_checksum_for_data (checksum_type ==
CHECKSUM_TYPE_AS_ID ? G_CHECKSUM_SHA1 : checksum_type, map.data,
map.size);
gst_buffer_unmap (buffer, &map);
buffer_parts[buffer_parts_index++] = g_strdup_printf ("checksum=%s", sum);
if (checksum_type == CHECKSUM_TYPE_AS_ID) {
gint id;
G_LOCK (checksums_as_id_lock);
if (!checksums_as_id)
checksums_as_id = gst_structure_new_empty ("checksums-id");
if (!gst_structure_get_int (checksums_as_id, sum, &id)) {
id = gst_structure_n_fields (checksums_as_id);
gst_structure_set (checksums_as_id, sum, G_TYPE_INT, id, NULL);
}
G_UNLOCK (checksums_as_id_lock);
buffer_parts[buffer_parts_index++] =
g_strdup_printf ("content-id=%d", id);
} else {
buffer_parts[buffer_parts_index++] =
g_strdup_printf ("checksum=%s", sum);
}
g_free (sum);
}
}

View file

@ -25,6 +25,9 @@
#include <gst/gst.h>
#define CHECKSUM_TYPE_NONE -2
#define CHECKSUM_TYPE_AS_ID -1
void format_time(gchar* dest_str, guint64 time);
gchar* validate_flow_format_segment(const GstSegment* segment, gchar** logged_fields, gchar** ignored_fields);

View file

@ -48,13 +48,35 @@ typedef enum _ValidateFlowMode
VALIDATE_FLOW_MODE_WRITING_ACTUAL_RESULTS
} ValidateFlowMode;
#define GST_TYPE_VALIDATE_FLOW_CHECKSUM_TYPE (validate_flow_checksum_type_get_type ())
static GType
validate_flow_checksum_type_get_type (void)
{
static GType gtype = 0;
if (gtype == 0) {
static const GEnumValue values[] = {
{CHECKSUM_TYPE_NONE, "NONE", "none"},
{CHECKSUM_TYPE_AS_ID, "AS-ID", "as-id"},
{G_CHECKSUM_MD5, "MD5", "md5"},
{G_CHECKSUM_SHA1, "SHA-1", "sha1"},
{G_CHECKSUM_SHA256, "SHA-256", "sha256"},
{G_CHECKSUM_SHA512, "SHA-512", "sha512"},
{0, NULL, NULL},
};
gtype = g_enum_register_static ("ValidateFlowChecksumType", values);
}
return gtype;
}
struct _ValidateFlowOverride
{
GstValidateOverride parent;
const gchar *pad_name;
gboolean record_buffers;
gboolean buffers_checksum;
gint checksum_type;
gchar *expectations_dir;
gchar *actual_results_dir;
gboolean error_writing_file;
@ -186,7 +208,7 @@ 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->checksum_type,
flow->logged_fields, flow->ignored_fields);
validate_flow_override_printf (flow, "buffer: %s\n", buffer_str);
g_free (buffer_str);
@ -220,6 +242,7 @@ validate_flow_override_new (GstStructure * config)
{
ValidateFlowOverride *flow;
GstValidateOverride *override;
gboolean use_checksum = FALSE;
gchar *ignored_fields = NULL, *logged_fields;
const GValue *tmpval;
@ -240,11 +263,25 @@ validate_flow_override_new (GstStructure * config)
flow->record_buffers = FALSE;
gst_structure_get_boolean (config, "record-buffers", &flow->record_buffers);
flow->buffers_checksum = FALSE;
gst_structure_get_boolean (config, "buffers-checksum",
&flow->buffers_checksum);
flow->checksum_type = CHECKSUM_TYPE_NONE;
gst_structure_get_boolean (config, "buffers-checksum", &use_checksum);
if (flow->buffers_checksum)
if (use_checksum) {
flow->checksum_type = G_CHECKSUM_SHA1;
} else {
const gchar *checksum_type =
gst_structure_get_string (config, "buffers-checksum");
if (checksum_type) {
if (!gst_validate_utils_enum_from_str
(GST_TYPE_VALIDATE_FLOW_CHECKSUM_TYPE, checksum_type,
(guint *) & flow->checksum_type))
gst_validate_error_structure (config,
"Invalid value for buffers-checksum: %s", checksum_type);
}
}
if (flow->checksum_type != CHECKSUM_TYPE_NONE)
flow->record_buffers = TRUE;
/* caps-properties: Caps events can include many dfferent properties, but