#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>
} 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
}
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)
{
guint state;
return G_SOURCE_REMOVE;
}
-static GstElement *_get_target_element (GstValidateScenario * scenario,
- GstValidateAction * action);
-
static void
stop_waiting_signal (GstStructure * data)
{
"```\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 []) {
{
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,
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,
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
'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]
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
)
'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,
'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