v4l2: enhance v4l2 control interface to support string type CID

add string type cid support for v4l2 implementation

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/676>
This commit is contained in:
Haihua Hu 2020-07-22 09:46:47 +08:00
parent c943be8b25
commit 0a453cc4a4
2 changed files with 73 additions and 5 deletions

View file

@ -337,6 +337,7 @@ gboolean gst_v4l2_signal_strength (GstV4l2Object * v4l2object, gint tunernum
/* attribute control */
gboolean gst_v4l2_get_attribute (GstV4l2Object * v4l2object, int attribute, int * value);
gboolean gst_v4l2_set_attribute (GstV4l2Object * v4l2object, int attribute, const int value);
gboolean gst_v4l2_set_string_attribute (GstV4l2Object * v4l2object, int attribute_num, const char *value);
gboolean gst_v4l2_set_controls (GstV4l2Object * v4l2object, GstStructure * controls);
G_END_DECLS

View file

@ -330,7 +330,8 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
case V4L2_CTRL_TYPE_MENU:
case V4L2_CTRL_TYPE_INTEGER_MENU:
case V4L2_CTRL_TYPE_BITMASK:
case V4L2_CTRL_TYPE_BUTTON:{
case V4L2_CTRL_TYPE_BUTTON:
case V4L2_CTRL_TYPE_STRING:{
control.name[31] = '\0';
gst_v4l2_normalise_control_name ((gchar *) control.name);
g_datalist_id_set_data (&v4l2object->controls,
@ -970,6 +971,67 @@ ctrl_failed:
}
}
/******************************************************
* gst_v4l2_set_string_attribute():
* try to set the string value of one specific attribute
* return value: TRUE on success, FALSE on error
******************************************************/
gboolean
gst_v4l2_set_string_attribute (GstV4l2Object * v4l2object,
int attribute_num, const char *value)
{
struct v4l2_ext_controls ctrls = { {0}, 1 };
struct v4l2_ext_control ctrl;
struct v4l2_queryctrl control = { 0, };
if (!GST_V4L2_IS_OPEN (v4l2object))
return FALSE;
control.id = attribute_num;
if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_QUERYCTRL, &control) < 0) {
GST_WARNING_OBJECT (v4l2object,
"Failed to find control %d on device '%s'.",
attribute_num, v4l2object->videodev);
return TRUE;
}
if (control.type != V4L2_CTRL_TYPE_STRING) {
GST_WARNING_OBJECT (v4l2object,
"control %d is not string type on device '%s'.",
attribute_num, v4l2object->videodev);
return TRUE;
}
ctrl.id = attribute_num;
ctrl.size = strlen (value) + 1;
ctrl.string = g_malloc (ctrl.size);
strcpy (ctrl.string, value);
ctrls.which = V4L2_CTRL_ID2WHICH (attribute_num);
ctrls.count = 1;
ctrls.controls = &ctrl;
GST_DEBUG_OBJECT (v4l2object->dbg_obj, "setting value of attribute %d to %s",
attribute_num, value);
if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
goto ctrl_failed;
g_free (ctrl.string);
return TRUE;
/* ERRORS */
ctrl_failed:
{
GST_WARNING_OBJECT (v4l2object,
_("Failed to set value %s for control %d on device '%s'."),
value, attribute_num, v4l2object->videodev);
g_free (ctrl.string);
return FALSE;
}
}
static gboolean
set_control (GQuark field_id, const GValue * value, gpointer user_data)
{
@ -1002,13 +1064,18 @@ set_control (GQuark field_id, const GValue * value, gpointer user_data)
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;
}
if (G_VALUE_HOLDS (value, G_TYPE_INT)) {
gst_v4l2_set_attribute (v4l2object, GPOINTER_TO_INT (d),
g_value_get_int (value));
} else if (G_VALUE_HOLDS (value, G_TYPE_STRING)) {
gst_v4l2_set_string_attribute (v4l2object, GPOINTER_TO_INT (d),
g_value_get_string (value));
} else {
GST_WARNING_OBJECT (v4l2object,
"no compatible value expected for control '%s'.",
g_quark_to_string (field_id));
return TRUE;
}
return TRUE;
}