diff options
author | Michael Olbrich <m.olbrich@pengutronix.de> | 2013-05-20 16:45:37 +0200 |
---|---|---|
committer | Michael Olbrich <m.olbrich@pengutronix.de> | 2013-09-13 16:29:47 +0200 |
commit | ab6a39c8ce660bd51f7f2b16a54351b45fac6031 (patch) | |
tree | c906eb81c32fe9dc629663a6beba0c343a247e37 | |
parent | 2d81f1a249f0c865e2326498078a032c4e1e58ff (diff) | |
download | gst-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.c | 28 | ||||
-rw-r--r-- | sys/v4l2/gstv4l2object.h | 5 | ||||
-rw-r--r-- | sys/v4l2/v4l2_calls.c | 58 | ||||
-rw-r--r-- | sys/v4l2/v4l2_calls.h | 3 |
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); |