summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Olbrich <m.olbrich@pengutronix.de>2013-05-20 16:45:37 +0200
committerMichael Olbrich <m.olbrich@pengutronix.de>2013-09-13 16:29:47 +0200
commitab6a39c8ce660bd51f7f2b16a54351b45fac6031 (patch)
treec906eb81c32fe9dc629663a6beba0c343a247e37
parent2d81f1a249f0c865e2326498078a032c4e1e58ff (diff)
downloadgst-plugins-good-ab6a39c8ce660bd51f7f2b16a54351b45fac6031.tar.gz
gst-plugins-good-ab6a39c8ce660bd51f7f2b16a54351b45fac6031.tar.xz
v4l2: add a property for arbitrary v4l2 controls
This makes it possible to set any controls that can be set with VIDIOC_S_CTRL. The controls are set when the property is set (if the device is open) and when the device is opened. https://bugzilla.gnome.org/show_bug.cgi?id=698837
-rw-r--r--sys/v4l2/gstv4l2object.c28
-rw-r--r--sys/v4l2/gstv4l2object.h5
-rw-r--r--sys/v4l2/v4l2_calls.c58
-rw-r--r--sys/v4l2/v4l2_calls.h3
4 files changed, 93 insertions, 1 deletions
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index b46b7e9aa..50c88d76b 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -490,6 +490,20 @@ gst_v4l2_object_install_properties_helper (GObjectClass * gobject_class,
"I/O mode",
GST_TYPE_V4L2_IO_MODE, DEFAULT_PROP_IO_MODE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GstV4l2Src:extra-controls
+ *
+ * Additional v4l2 controls for the device. The controls are identified
+ * by the control name (lowercase with '_' for any non-alphanumeric
+ * characters).
+ *
+ * Since: 1.2
+ */
+ g_object_class_install_property (gobject_class, PROP_EXTRA_CONTROLS,
+ g_param_spec_boxed ("extra-controls", "Extra Controls",
+ "Extra v4l2 controls (CIDs) for the device",
+ GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
GstV4l2Object *
@@ -654,6 +668,17 @@ gst_v4l2_object_set_property_helper (GstV4l2Object * v4l2object,
case PROP_IO_MODE:
v4l2object->req_mode = g_value_get_enum (value);
break;
+ case PROP_EXTRA_CONTROLS:{
+ const GstStructure *s = gst_value_get_structure (value);
+
+ if (v4l2object->extra_controls)
+ gst_structure_free (v4l2object->extra_controls);
+
+ v4l2object->extra_controls = s ? gst_structure_copy (s) : NULL;
+ if (GST_V4L2_IS_OPEN (v4l2object))
+ gst_v4l2_set_controls (v4l2object, v4l2object->extra_controls);
+ break;
+ }
default:
return FALSE;
break;
@@ -730,6 +755,9 @@ gst_v4l2_object_get_property_helper (GstV4l2Object * v4l2object,
case PROP_IO_MODE:
g_value_set_enum (value, v4l2object->req_mode);
break;
+ case PROP_EXTRA_CONTROLS:
+ gst_value_set_structure (value, v4l2object->extra_controls);
+ break;
default:
return FALSE;
break;
diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h
index 3abb19365..e177937d8 100644
--- a/sys/v4l2/gstv4l2object.h
+++ b/sys/v4l2/gstv4l2object.h
@@ -143,11 +143,13 @@ struct _GstV4l2Object {
GList *colors;
GList *norms;
GList *channels;
+ GData *controls;
/* properties */
v4l2_std_id tv_norm;
gchar *channel;
gulong frequency;
+ GstStructure *extra_controls;
/* X-overlay */
GstV4l2Xv *xv;
@@ -176,7 +178,8 @@ GType gst_v4l2_object_get_type (void);
PROP_SATURATION, \
PROP_HUE, \
PROP_TV_NORM, \
- PROP_IO_MODE
+ PROP_IO_MODE, \
+ PROP_EXTRA_CONTROLS
/* create/destroy */
GstV4l2Object * gst_v4l2_object_new (GstElement * element,
diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c
index 6946e1b88..61f442e7a 100644
--- a/sys/v4l2/v4l2_calls.c
+++ b/sys/v4l2/v4l2_calls.c
@@ -269,6 +269,32 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
GST_DEBUG_OBJECT (e, "skipping disabled control");
continue;
}
+ switch (control.type) {
+ case V4L2_CTRL_TYPE_INTEGER:
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ case V4L2_CTRL_TYPE_MENU:
+ case V4L2_CTRL_TYPE_INTEGER_MENU:
+ case V4L2_CTRL_TYPE_BITMASK:
+ case V4L2_CTRL_TYPE_BUTTON:{
+ int i;
+ control.name[31] = '\0';
+ for (i = 0; control.name[i]; ++i) {
+ control.name[i] = g_ascii_tolower (control.name[i]);
+ if (!g_ascii_isalnum (control.name[i]))
+ control.name[i] = '_';
+ }
+ GST_INFO_OBJECT (e, "adding generic controls '%s'", control.name);
+ g_datalist_id_set_data (&v4l2object->controls,
+ g_quark_from_string ((const gchar *) control.name),
+ GINT_TO_POINTER (n));
+ break;
+ }
+ default:
+ GST_DEBUG_OBJECT (e,
+ "Control type for '%s' not suppored for extra controls.",
+ control.name);
+ break;
+ }
switch (n) {
case V4L2_CID_BRIGHTNESS:
@@ -406,6 +432,8 @@ gst_v4l2_empty_lists (GstV4l2Object * v4l2object)
g_list_foreach (v4l2object->colors, (GFunc) g_object_unref, NULL);
g_list_free (v4l2object->colors);
v4l2object->colors = NULL;
+
+ g_datalist_clear (&v4l2object->controls);
}
/******************************************************
@@ -485,6 +513,9 @@ gst_v4l2_open (GstV4l2Object * v4l2object)
else
gst_poll_fd_ctl_write (v4l2object->poll, &pollfd, TRUE);
+ if (v4l2object->extra_controls)
+ gst_v4l2_set_controls (v4l2object, v4l2object->extra_controls);
+
return TRUE;
/* ERRORS */
@@ -810,6 +841,33 @@ ctrl_failed:
}
}
+static gboolean
+set_contol (GQuark field_id, const GValue * value, gpointer user_data)
+{
+ GstV4l2Object *v4l2object = user_data;
+ gpointer *d = g_datalist_id_get_data (&v4l2object->controls, field_id);
+ if (!d) {
+ GST_WARNING_OBJECT (v4l2object,
+ "Control '%s' does not exist or has an unsupported type.",
+ g_quark_to_string (field_id));
+ return TRUE;
+ }
+ if (!G_VALUE_HOLDS (value, G_TYPE_INT)) {
+ GST_WARNING_OBJECT (v4l2object,
+ "'int' value expected for control '%s'.", g_quark_to_string (field_id));
+ return TRUE;
+ }
+ gst_v4l2_set_attribute (v4l2object, GPOINTER_TO_INT (d),
+ g_value_get_int (value));
+ return TRUE;
+}
+
+gboolean
+gst_v4l2_set_controls (GstV4l2Object * v4l2object, GstStructure * controls)
+{
+ return gst_structure_foreach (controls, set_contol, v4l2object);
+}
+
gboolean
gst_v4l2_get_input (GstV4l2Object * v4l2object, gint * input)
{
diff --git a/sys/v4l2/v4l2_calls.h b/sys/v4l2/v4l2_calls.h
index 36cf0f3a9..11d16b6ab 100644
--- a/sys/v4l2/v4l2_calls.h
+++ b/sys/v4l2/v4l2_calls.h
@@ -126,6 +126,9 @@ gboolean gst_v4l2_set_attribute (GstV4l2Object *v4l2object,
int attribute,
const int value);
+gboolean gst_v4l2_set_controls (GstV4l2Object * v4l2object,
+ GstStructure * controls);
+
gboolean gst_v4l2_get_capabilities (GstV4l2Object * v4l2object);