validate: Add a way to run a TestClock in scenarios

A TestClock will be used automatically when a scenario has a
`crank-clock` action.

And make `validate` and `debug-viewer` options features in meson,
no reason they weren't and now we require gst-check to build validate

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-devtools/-/merge_requests/182>
This commit is contained in:
Thibault Saunier 2020-04-13 16:23:32 -04:00
parent bf952d3c8b
commit 9840417a87
5 changed files with 106 additions and 17 deletions

View file

@ -28,8 +28,8 @@ The `meta` format:
## Tool arguments
In the case of [`gst-validate`](gst-validate.md) it **has to** contain a
`gst-validate-args` field with `gst-validate` argv arguments like:
In the case of [`gst-validate`](gst-validate.md) it **has to** contain an
`args` field with `gst-validate` argv arguments like:
``` yaml
# This is the default tool so it is not mandatory for the `gst-validate` tool
@ -49,7 +49,7 @@ usual [config](gst-validate-config.md) files contain.
For example:
``` json
``` yaml
configs = {
# Set videotestsrc0 pattern value to `blue`
"core, action=set-property, target-element-name=videotestsrc0, property-name=pattern, property-value=blue",

View file

@ -67,11 +67,9 @@ gst_pbutils_dep = dependency('gstreamer-pbutils-' + apiversion, version : gst_re
fallback : ['gst-plugins-base', 'pbutils_dep'])
gst_video_dep = dependency('gstreamer-video-' + apiversion, version : gst_req,
fallback : ['gst-plugins-base', 'video_dep'])
if host_machine.system() != 'windows'
gst_check_dep = dependency('gstreamer-check-1.0', version : gst_req,
required : get_option('tests'),
fallback : ['gstreamer', 'gst_check_dep'])
endif
gst_check_dep = dependency('gstreamer-check-1.0', version : gst_req,
required : get_option('validate'),
fallback : ['gstreamer', 'gst_check_dep'])
glib_dep = dependency('glib-2.0', version : '>=2.32.0',
fallback: ['glib', 'libglib_dep'])
@ -146,7 +144,7 @@ i18n = import('i18n')
python_mod = import('python')
python3 = python_mod.find_installation()
if get_option('validate')
if not get_option('validate').disabled()
subdir('validate')
endif

View file

@ -1,4 +1,4 @@
option('validate', type : 'boolean', value : true,
option('validate', type : 'feature', value : 'auto',
description : 'Build GstValidate')
option('debug_viewer', type : 'boolean', value : true,
description : 'Build GstDebugViewer')

View file

@ -47,6 +47,7 @@
#include <string.h>
#include <errno.h>
#include <gst/check/gsttestclock.h>
#include "gst-validate-internal.h"
#include "gst-validate-scenario.h"
#include "gst-validate-reporter.h"
@ -178,6 +179,8 @@ struct _GstValidateScenarioPrivate
GstStructure *vars;
GWeakRef ref_pipeline;
GstTestClock *clock;
};
typedef struct KeyFileGroupName
@ -610,6 +613,10 @@ gboolean
gst_validate_action_get_clocktime (GstValidateScenario * scenario,
GstValidateAction * action, const gchar * name, GstClockTime * retval)
{
if (!gst_structure_has_field (action->structure, name))
return FALSE;
if (!gst_validate_utils_get_clocktime (action->structure, name, retval)) {
gdouble val;
gchar *error = NULL, *strval;
@ -1710,12 +1717,12 @@ static gboolean
_should_execute_action (GstValidateScenario * scenario, GstValidateAction * act,
GstClockTime position, gdouble rate)
{
GstElement *pipeline;
GstElement *pipeline = NULL;
if (!act) {
GST_DEBUG_OBJECT (scenario, "No action to execute");
return FALSE;
goto no;
}
pipeline = gst_validate_scenario_get_pipeline (scenario);
@ -1776,7 +1783,7 @@ yes:
return TRUE;
no:
gst_object_unref (pipeline);
gst_clear_object (&pipeline);
return FALSE;
}
@ -3512,6 +3519,9 @@ gst_validate_scenario_load_structures (GstValidateScenario * scenario,
goto failed;
}
if (!g_strcmp0 (type, "crank-clock") && !priv->clock)
priv->clock = GST_TEST_CLOCK (gst_test_clock_new ());
if (action_type->parameters) {
guint i;
@ -3833,6 +3843,7 @@ gst_validate_scenario_init (GstValidateScenario * scenario)
g_weak_ref_init (&scenario->priv->ref_pipeline, NULL);
priv->max_latency = GST_CLOCK_TIME_NONE;
priv->max_dropped = -1;
priv->clock = NULL;
g_mutex_init (&priv->lock);
}
@ -3852,6 +3863,8 @@ gst_validate_scenario_dispose (GObject * object)
priv->bus = NULL;
}
gst_object_replace ((GstObject **) & priv->clock, NULL);
G_OBJECT_CLASS (gst_validate_scenario_parent_class)->dispose (object);
}
@ -4013,6 +4026,11 @@ gst_validate_scenario_new (GstValidateRunner *
GST_OBJECT_NAME (pipeline));
g_weak_ref_init (&scenario->priv->ref_pipeline, pipeline);
if (scenario->priv->clock) {
gst_element_set_clock (pipeline, GST_CLOCK_CAST (scenario->priv->clock));
gst_pipeline_use_clock (GST_PIPELINE (pipeline),
GST_CLOCK_CAST (scenario->priv->clock));
}
gst_validate_reporter_set_name (GST_VALIDATE_REPORTER (scenario),
g_strdup (scenario_name));
@ -4637,6 +4655,56 @@ done:
return GST_PAD_PROBE_OK;
}
static GstValidateExecuteActionReturn
_execute_crank_clock (GstValidateScenario * scenario,
GstValidateAction * action)
{
GstClockTime expected_diff, expected_time;
GstClockTime prev_time =
gst_clock_get_time (GST_CLOCK (scenario->priv->clock));
if (!gst_test_clock_crank (scenario->priv->clock)) {
GST_VALIDATE_REPORT_ACTION (scenario, action,
SCENARIO_ACTION_EXECUTION_ERROR, "Cranking clock failed");
return GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED;
}
if (gst_validate_action_get_clocktime (scenario, action,
"expected-elapsed-time", &expected_diff)) {
GstClockTime elapsed =
gst_clock_get_time (GST_CLOCK (scenario->priv->clock)) - prev_time;
if (expected_diff != elapsed) {
GST_VALIDATE_REPORT_ACTION (scenario, action,
SCENARIO_ACTION_EXECUTION_ERROR,
"Elapsed time during test clock cranking different than expected,"
" waited for %" GST_TIME_FORMAT " instead of the expected %"
GST_TIME_FORMAT, GST_TIME_ARGS (elapsed),
GST_TIME_ARGS (expected_diff));
return GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED;
}
}
if (gst_validate_action_get_clocktime (scenario, action, "expected-time",
&expected_time)) {
GstClockTime time = gst_clock_get_time (GST_CLOCK (scenario->priv->clock));
if (expected_time != time) {
GST_VALIDATE_REPORT_ACTION (scenario, action,
SCENARIO_ACTION_EXECUTION_ERROR,
"Clock time after cranking different than expected,"
" got %" GST_TIME_FORMAT " instead of the expected %" GST_TIME_FORMAT,
GST_TIME_ARGS (time), GST_TIME_ARGS (expected_time));
return GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED;
}
}
return GST_VALIDATE_EXECUTE_ACTION_OK;
}
static gboolean
_execute_request_key_unit (GstValidateScenario * scenario,
GstValidateAction * action)
@ -5242,7 +5310,7 @@ register_action_types (void)
.mandatory = FALSE,
.types = "boolean",
.possible_variables = NULL,
.def = "false"
.def = "true if some action requires a playback-time false otherwise"
},
{
.name = "min-media-duration",
@ -5820,6 +5888,29 @@ register_action_types (void)
" for example",
GST_VALIDATE_ACTION_TYPE_INTERLACED);
REGISTER_ACTION_TYPE ("crank-clock", _execute_crank_clock,
((GstValidateActionParameter []) {
{
.name = "expected-time",
.description = "Expected clock time after cranking",
.mandatory = FALSE,
.types = "GstClockTime",
NULL
},
{
.name = "expected-elapsed-time",
.description = "Check time elapsed during the clock cranking",
.mandatory = FALSE,
.types = "GstClockTime",
NULL
},
}), "Crank the clock, possibly checking how much time was supposed to be waited on the clock"
" and/or the clock running time after the crank."
" Using one `crank-clock` action in a scenario implies that the scenario is driving the "
" clock and a #GstTestClock will be used. The user will need to crank it the number of "
" time required (using the `repeat` parameter comes handy here).",
GST_VALIDATE_ACTION_TYPE_NEEDS_CLOCK);
REGISTER_ACTION_TYPE ("video-request-key-unit", _execute_request_key_unit,
((GstValidateActionParameter []) {
{

View file

@ -61,7 +61,7 @@ gstvalidate = library('gstvalidate-1.0',
include_directories : [inc_dirs],
install: true,
c_args : [gst_c_args] + ['-D_GNU_SOURCE'],
dependencies : [gst_dep, gstbase_dep, glib_dep, gio_dep,
dependencies : [gst_check_dep, gst_dep, gstbase_dep, glib_dep, gio_dep,
gmodule_dep, gst_pbutils_dep, mathlib, json_dep])
gstvalidatetracer = library('gstvalidatetracer',
@ -70,7 +70,7 @@ gstvalidatetracer = library('gstvalidatetracer',
install: true,
c_args : [gst_c_args] + ['-D__GST_VALIDATE_PLUGIN', '-D_GNU_SOURCE'],
install_dir : plugins_install_dir,
dependencies : [gst_dep, gstbase_dep, glib_dep, gio_dep, gmodule_dep,
dependencies : [gst_check_dep, gst_dep, gstbase_dep, glib_dep, gio_dep, gmodule_dep,
gst_pbutils_dep, mathlib, json_dep])
validate_gen_sources = []
@ -90,7 +90,7 @@ if build_gir
'Gst-' + apiversion,
'GstPbutils-' + apiversion],
install : true,
dependencies : [gst_dep, gstbase_dep, glib_dep, gio_dep, gst_pbutils_dep],
dependencies : [gst_dep, gstbase_dep, glib_dep, gio_dep, gst_pbutils_dep, gst_check_dep],
extra_args : gst_validate_gir_extra_args,
)
validate_gen_sources += [validate_gir]