mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
validate: Add an action type to set timed value properties
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-devtools/-/merge_requests/207>
This commit is contained in:
parent
8f95d72262
commit
302e9e1123
4 changed files with 280 additions and 23 deletions
|
@ -67,6 +67,8 @@ 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'])
|
||||
gst_controller_dep = dependency('gstreamer-controller-' + apiversion, version : gst_req,
|
||||
fallback : ['gstreamer', 'gst_controller_dep'])
|
||||
gst_check_dep = dependency('gstreamer-check-1.0', version : gst_req,
|
||||
required : get_option('validate'),
|
||||
fallback : ['gstreamer', 'gst_check_dep'])
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "gst-validate-utils.h"
|
||||
#include "gst-validate-internal.h"
|
||||
#include "validate.h"
|
||||
#include <gst/controller/controller.h>
|
||||
#include <gst/validate/gst-validate-override.h>
|
||||
#include <gst/validate/gst-validate-override-registry.h>
|
||||
#include <gst/validate/gst-validate-pipeline-monitor.h>
|
||||
|
@ -641,8 +642,95 @@ _update_well_known_vars (GstValidateScenario * scenario)
|
|||
} else {
|
||||
GST_WARNING_OBJECT (scenario, "Could not query position");
|
||||
}
|
||||
}
|
||||
|
||||
gst_object_unref (pipeline);
|
||||
static GstElement *_get_target_element (GstValidateScenario * scenario,
|
||||
GstValidateAction * action);
|
||||
|
||||
static GstObject *
|
||||
_get_target_object_property (GstValidateScenario * scenario,
|
||||
GstValidateAction * action, const gchar * property_path,
|
||||
GParamSpec ** pspec)
|
||||
{
|
||||
GstValidateExecuteActionReturn res = GST_VALIDATE_EXECUTE_ACTION_OK;
|
||||
gchar **elem_pad_name = NULL;
|
||||
gchar **object_prop_name = NULL;
|
||||
const gchar *elemname;
|
||||
const gchar *propname;
|
||||
const gchar *padname = NULL;
|
||||
GstObject *target = NULL;
|
||||
|
||||
elem_pad_name = g_strsplit (property_path, ".", 2);
|
||||
object_prop_name =
|
||||
g_strsplit (elem_pad_name[1] ? elem_pad_name[1] : elem_pad_name[0], "::",
|
||||
2);
|
||||
REPORT_UNLESS (object_prop_name[1], err,
|
||||
"Property specification %s is missing a `:propename` part",
|
||||
property_path);
|
||||
propname = object_prop_name[1];
|
||||
|
||||
if (elem_pad_name[1]) {
|
||||
elemname = elem_pad_name[0];
|
||||
padname = object_prop_name[0];
|
||||
} else {
|
||||
elemname = object_prop_name[0];
|
||||
}
|
||||
|
||||
gst_structure_set (action->structure, "target-element-name", G_TYPE_STRING,
|
||||
elemname, NULL);
|
||||
|
||||
target = (GstObject *) _get_target_element (scenario, action);
|
||||
gst_structure_remove_field (action->structure, "target-element-name");
|
||||
REPORT_UNLESS (target, err, "Target element with given name (%s) not found",
|
||||
elemname);
|
||||
|
||||
if (padname) {
|
||||
gboolean done = FALSE;
|
||||
GstIterator *it = gst_element_iterate_pads (GST_ELEMENT (target));
|
||||
GValue v = G_VALUE_INIT;
|
||||
|
||||
gst_clear_object (&target);
|
||||
while (!done) {
|
||||
switch (gst_iterator_next (it, &v)) {
|
||||
case GST_ITERATOR_OK:{
|
||||
GstPad *pad = g_value_get_object (&v);
|
||||
gchar *name = gst_object_get_name (GST_OBJECT (pad));
|
||||
|
||||
if (!g_strcmp0 (name, padname)) {
|
||||
done = TRUE;
|
||||
gst_clear_object (&target);
|
||||
|
||||
target = gst_object_ref (pad);
|
||||
}
|
||||
g_free (name);
|
||||
g_value_reset (&v);
|
||||
break;
|
||||
}
|
||||
case GST_ITERATOR_RESYNC:
|
||||
gst_iterator_resync (it);
|
||||
break;
|
||||
case GST_ITERATOR_ERROR:
|
||||
case GST_ITERATOR_DONE:
|
||||
done = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
REPORT_UNLESS (target, err, "Could not find pad: %s::%s", elemname, padname);
|
||||
|
||||
*pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (target), propname);
|
||||
|
||||
REPORT_UNLESS (*pspec, err,
|
||||
"Could not find property from: %" GST_PTR_FORMAT ":%s", target, propname);
|
||||
REPORT_UNLESS (res == GST_VALIDATE_EXECUTE_ACTION_OK, err, "Something fishy");
|
||||
|
||||
done:
|
||||
g_strfreev (elem_pad_name);
|
||||
g_strfreev (object_prop_name);
|
||||
return target;
|
||||
|
||||
err:
|
||||
gst_clear_object (&target);
|
||||
goto done;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -1068,6 +1156,140 @@ _execute_define_vars (GstValidateScenario * scenario,
|
|||
return GST_VALIDATE_EXECUTE_ACTION_OK;
|
||||
}
|
||||
|
||||
static GstValidateExecuteActionReturn
|
||||
_set_timed_value (GQuark field_id, const GValue * gvalue,
|
||||
GstStructure * structure)
|
||||
{
|
||||
GstValidateExecuteActionReturn res = GST_VALIDATE_EXECUTE_ACTION_OK;
|
||||
gdouble value;
|
||||
GstClockTime timestamp;
|
||||
GstTimedValueControlSource *source = NULL;
|
||||
GstControlBinding *binding;
|
||||
GstValidateScenario *scenario;
|
||||
GstValidateAction *action;
|
||||
GstObject *obj = NULL;
|
||||
GParamSpec *paramspec = NULL;
|
||||
const gchar *field = g_quark_to_string (field_id);
|
||||
const gchar *unused_fields[] =
|
||||
{ "binding-type", "source-type", "interpolation-mode",
|
||||
"timestamp", "__scenario__", "__action__", "__res__", NULL
|
||||
};
|
||||
|
||||
if (g_strv_contains (unused_fields, field))
|
||||
return TRUE;
|
||||
|
||||
gst_structure_get (structure, "__scenario__", G_TYPE_POINTER, &scenario,
|
||||
"__action__", G_TYPE_POINTER, &action, NULL);
|
||||
|
||||
|
||||
if (G_VALUE_HOLDS_DOUBLE (gvalue))
|
||||
value = g_value_get_double (gvalue);
|
||||
else if (G_VALUE_HOLDS_INT (gvalue))
|
||||
value = g_value_get_int (gvalue);
|
||||
else {
|
||||
GST_VALIDATE_REPORT (scenario, SCENARIO_ACTION_EXECUTION_ERROR,
|
||||
"Invalid value type for property '%s': %s",
|
||||
field, G_VALUE_TYPE_NAME (gvalue));
|
||||
goto err;
|
||||
}
|
||||
|
||||
obj = _get_target_object_property (scenario, action, field, ¶mspec);
|
||||
if (!obj || !paramspec) {
|
||||
res = GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED;
|
||||
goto err;
|
||||
}
|
||||
|
||||
REPORT_UNLESS (gst_validate_action_get_clocktime (scenario, action,
|
||||
"timestamp", ×tamp), err,
|
||||
"Could get timestamp on %" GST_PTR_FORMAT, action->structure);
|
||||
|
||||
binding = gst_object_get_control_binding (obj, paramspec->name);
|
||||
if (!binding) {
|
||||
guint mode;
|
||||
GType source_type;
|
||||
const gchar *interpolation_mode =
|
||||
gst_structure_get_string (action->structure, "interpolation-mode");
|
||||
const gchar *source_type_name =
|
||||
gst_structure_get_string (action->structure, "source-type");
|
||||
|
||||
if (source_type_name) {
|
||||
source_type = g_type_from_name (source_type_name);
|
||||
|
||||
REPORT_UNLESS (g_type_is_a (source_type,
|
||||
GST_TYPE_TIMED_VALUE_CONTROL_SOURCE), err,
|
||||
"Source type '%s' is not supported", source_type_name);
|
||||
} else {
|
||||
source_type = GST_TYPE_INTERPOLATION_CONTROL_SOURCE;
|
||||
}
|
||||
|
||||
source = g_object_new (source_type, NULL);
|
||||
gst_object_ref_sink (source);
|
||||
if (GST_IS_INTERPOLATION_CONTROL_SOURCE (source)) {
|
||||
if (interpolation_mode)
|
||||
REPORT_UNLESS (gst_validate_utils_enum_from_str
|
||||
(GST_TYPE_INTERPOLATION_MODE, interpolation_mode, &mode), err,
|
||||
"Could not convert interpolation-mode '%s'", interpolation_mode);
|
||||
|
||||
else
|
||||
mode = GST_INTERPOLATION_MODE_LINEAR;
|
||||
|
||||
g_object_set (source, "mode", mode, NULL);
|
||||
}
|
||||
|
||||
if (!g_strcmp0 (gst_structure_get_string (action->structure,
|
||||
"binding-type"), "direct-absolute")) {
|
||||
binding =
|
||||
gst_direct_control_binding_new_absolute (obj, paramspec->name,
|
||||
GST_CONTROL_SOURCE (source));
|
||||
} else {
|
||||
binding =
|
||||
gst_direct_control_binding_new (obj, paramspec->name,
|
||||
GST_CONTROL_SOURCE (source));
|
||||
}
|
||||
|
||||
gst_object_add_control_binding (obj, binding);
|
||||
} else {
|
||||
g_object_get (binding, "control-source", &source, NULL);
|
||||
}
|
||||
|
||||
REPORT_UNLESS (GST_IS_TIMED_VALUE_CONTROL_SOURCE (source), err,
|
||||
"Could not find timed value control source on %s", field);
|
||||
|
||||
REPORT_UNLESS (gst_timed_value_control_source_set (source, timestamp, value),
|
||||
err, "Could not set %s=%f at %" GST_TIME_FORMAT, field, value,
|
||||
GST_TIME_ARGS (timestamp));
|
||||
|
||||
gst_object_unref (obj);
|
||||
gst_structure_set (structure, "__res__", G_TYPE_INT, res, NULL);
|
||||
|
||||
return TRUE;
|
||||
|
||||
err:
|
||||
gst_clear_object (&obj);
|
||||
gst_structure_set (structure, "__res__", G_TYPE_INT,
|
||||
GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED, NULL);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GstValidateExecuteActionReturn
|
||||
_set_timed_value_property (GstValidateScenario * scenario,
|
||||
GstValidateAction * action)
|
||||
{
|
||||
GstValidateExecuteActionReturn res = GST_VALIDATE_EXECUTE_ACTION_ERROR;
|
||||
|
||||
gst_structure_set (action->structure, "__action__", G_TYPE_POINTER,
|
||||
action, "__scenario__", G_TYPE_POINTER, scenario, NULL);
|
||||
|
||||
gst_structure_foreach (action->structure,
|
||||
(GstStructureForeachFunc) _set_timed_value, action->structure);
|
||||
gst_structure_get_int (action->structure, "__res__", &res);
|
||||
gst_structure_remove_fields (action->structure, "__action__", "__scenario__",
|
||||
"__res__", NULL);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static GstValidateExecuteActionReturn
|
||||
_execute_set_state (GstValidateScenario * scenario, GstValidateAction * action)
|
||||
{
|
||||
|
@ -2480,9 +2702,6 @@ stop_waiting (GstValidateAction * action)
|
|||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static GstElement *_get_target_element (GstValidateScenario * scenario,
|
||||
GstValidateAction * action);
|
||||
|
||||
static void
|
||||
stop_waiting_signal (GstStructure * data)
|
||||
{
|
||||
|
@ -6031,6 +6250,47 @@ register_action_types (void)
|
|||
"```\n",
|
||||
GST_VALIDATE_ACTION_TYPE_NONE);
|
||||
|
||||
GST_TYPE_INTERPOLATION_CONTROL_SOURCE;
|
||||
GST_TYPE_TRIGGER_CONTROL_SOURCE;
|
||||
REGISTER_ACTION_TYPE ("set-timed-value-properties", _set_timed_value_property,
|
||||
((GstValidateActionParameter []) {
|
||||
{
|
||||
.name = "binding-type",
|
||||
.description = "The name of the type of binding to use",
|
||||
.types = "string",
|
||||
.mandatory = FALSE,
|
||||
.def = "direct",
|
||||
},
|
||||
{
|
||||
.name = "source-type",
|
||||
.description = "The name of the type of ControlSource to use",
|
||||
.types = "string",
|
||||
.mandatory = FALSE,
|
||||
.def = "GstInterpolationControlSource",
|
||||
},
|
||||
{
|
||||
.name = "interpolation-mode",
|
||||
.description = "The name of the GstInterpolationMode to on the source",
|
||||
.types = "string",
|
||||
.mandatory = FALSE,
|
||||
.def = "linear",
|
||||
},
|
||||
{
|
||||
.name = "timestamp",
|
||||
.description = "The timestamp of the keyframe",
|
||||
.types = "string or float (GstClockTime)",
|
||||
.mandatory = TRUE,
|
||||
},
|
||||
{NULL}
|
||||
}),
|
||||
"Sets GstTimedValue on pads on elements properties using GstControlBindings \n"
|
||||
"and GstControlSource as defined in the parameters.\n"
|
||||
"The properties values to set will be defined as:\n\n"
|
||||
" element-name.padname::property-name=new-value\n\n"
|
||||
"> NOTE: `.padname` is not needed if setting a property on an element\n\n"
|
||||
"This action also adds necessary control source/control bindings.\n",
|
||||
GST_VALIDATE_ACTION_TYPE_NONE);
|
||||
|
||||
REGISTER_ACTION_TYPE ("set-property", _execute_set_or_check_property,
|
||||
((GstValidateActionParameter []) {
|
||||
{
|
||||
|
|
|
@ -56,6 +56,7 @@ gst_validate_enums = gnome.mkenums('gstvalidateenumtypes',
|
|||
install_header : true,
|
||||
install_dir : join_paths(get_option('includedir'), 'gstreamer-1.0/gst/validate'))
|
||||
|
||||
validate_deps = [gst_check_dep, gst_dep, gst_controller_dep, gstbase_dep, glib_dep, gio_dep, gmodule_dep, gst_pbutils_dep, mathlib, json_dep]
|
||||
gstvalidate = library('gstvalidate-1.0',
|
||||
sources: gstvalidate_sources + gst_validate_enums,
|
||||
version : libversion,
|
||||
|
@ -64,8 +65,7 @@ gstvalidate = library('gstvalidate-1.0',
|
|||
include_directories : [inc_dirs],
|
||||
install: true,
|
||||
c_args : [gst_c_args] + ['-D_GNU_SOURCE'],
|
||||
dependencies : [gst_check_dep, gst_dep, gstbase_dep, glib_dep, gio_dep,
|
||||
gmodule_dep, gst_pbutils_dep, mathlib, json_dep])
|
||||
dependencies : validate_deps)
|
||||
|
||||
gstvalidatetracer = library('gstvalidatetracer',
|
||||
sources: gstvalidate_sources + gst_validate_enums,
|
||||
|
@ -73,8 +73,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_check_dep, gst_dep, gstbase_dep, glib_dep, gio_dep, gmodule_dep,
|
||||
gst_pbutils_dep, mathlib, json_dep])
|
||||
dependencies : validate_deps)
|
||||
|
||||
validate_gen_sources = []
|
||||
if build_gir
|
||||
|
@ -93,7 +92,7 @@ if build_gir
|
|||
'Gst-' + apiversion,
|
||||
'GstPbutils-' + apiversion],
|
||||
install : true,
|
||||
dependencies : [gst_dep, gstbase_dep, glib_dep, gio_dep, gst_pbutils_dep, gst_check_dep],
|
||||
dependencies : validate_deps,
|
||||
extra_args : gst_validate_gir_extra_args,
|
||||
)
|
||||
validate_gen_sources += [validate_gir]
|
||||
|
@ -101,8 +100,7 @@ endif
|
|||
|
||||
validate_dep = declare_dependency(link_with : gstvalidate,
|
||||
include_directories : [inc_dirs],
|
||||
dependencies : [gst_dep, glib_dep, gio_dep, gmodule_dep,
|
||||
gst_pbutils_dep, mathlib],
|
||||
dependencies : validate_deps,
|
||||
sources : validate_gen_sources
|
||||
)
|
||||
|
||||
|
|
|
@ -2,24 +2,22 @@ executable('gst-validate-' + apiversion,
|
|||
'gst-validate.c',
|
||||
install: true,
|
||||
include_directories : inc_dirs,
|
||||
dependencies : [gst_dep, glib_dep, gst_pbutils_dep, gio_dep],
|
||||
dependencies : validate_dep,
|
||||
c_args : [gst_c_args],
|
||||
link_with : [gstvalidate]
|
||||
)
|
||||
executable('gst-validate-transcoding-' + apiversion,
|
||||
'gst-validate-transcoding.c', install: true,
|
||||
'gst-validate-transcoding.c',
|
||||
install: true,
|
||||
include_directories : inc_dirs,
|
||||
dependencies : [gst_dep, glib_dep, gst_pbutils_dep, gst_video_dep, gio_dep],
|
||||
dependencies : validate_dep,
|
||||
c_args : [gst_c_args],
|
||||
link_with : [gstvalidate]
|
||||
)
|
||||
executable('gst-validate-media-check-' + apiversion,
|
||||
'gst-validate-media-check.c',
|
||||
install: true,
|
||||
include_directories : inc_dirs,
|
||||
dependencies : [gst_dep, glib_dep, gst_pbutils_dep, gio_dep],
|
||||
dependencies : validate_dep,
|
||||
c_args : [gst_c_args],
|
||||
link_with : [gstvalidate]
|
||||
)
|
||||
|
||||
rtsp_server_dep = dependency('gstreamer-rtsp-server-' + apiversion,
|
||||
|
@ -32,20 +30,19 @@ if rtsp_server_dep.found()
|
|||
'gst-validate-rtsp-server.c',
|
||||
install: true,
|
||||
include_directories: inc_dirs,
|
||||
dependencies: [rtsp_server_dep, gst_dep, glib_dep],
|
||||
dependencies : [rtsp_server_dep, validate_dep],
|
||||
c_args: [gst_c_args],
|
||||
link_with: [gstvalidate]
|
||||
)
|
||||
endif
|
||||
|
||||
if cairo_dep.found()
|
||||
executable('gst-validate-images-check-' + apiversion,
|
||||
'gst-validate-images-check.c',
|
||||
'gst-validate-images-check.c',
|
||||
install: true,
|
||||
include_directories : inc_dirs,
|
||||
dependencies : [gst_dep, glib_dep, gst_pbutils_dep, gio_dep],
|
||||
dependencies : validate_dep,
|
||||
c_args : [gst_c_args],
|
||||
link_with : [gstvalidate, video]
|
||||
link_with: [video],
|
||||
)
|
||||
endif
|
||||
|
||||
|
|
Loading…
Reference in a new issue