From 61c1157d8197226ff47fcaafeeb2d4d5bd269678 Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Sun, 28 Mar 2021 22:29:29 +0300 Subject: [PATCH] Hue/saturation controls, qtmultimedia viewfinder works --- pinesrcbin.c | 38 +++++++++++++++++++++++-- pinesrcbin.h | 2 ++ utility.c | 78 ++++++++++++++++++++++------------------------------ utility.h | 7 +++++ 4 files changed, 77 insertions(+), 48 deletions(-) diff --git a/pinesrcbin.c b/pinesrcbin.c index aa74ff6..b906e36 100644 --- a/pinesrcbin.c +++ b/pinesrcbin.c @@ -36,6 +36,8 @@ enum PROP_CAPS, PROP_SYNC, PROP_NUM_BUFFERS, + PROP_TEST_PATTERN, + PROP_HUE, }; @@ -187,6 +189,14 @@ gst_pinesrcbin_set_property (GObject * object, guint prop_id, if (self->kid) g_object_set_property (G_OBJECT (self->kid), pspec->name, value); break; + case PROP_TEST_PATTERN: + self->test_pattern = g_value_get_int (value); + break; + case PROP_HUE: + self->hue = g_value_get_int (value); + g_print("setting prop hue: %d\n", self->hue); + set_camera_control("rear", CONTROL_HUE, self->hue); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -209,6 +219,13 @@ gst_pinesrcbin_get_property (GObject * object, guint prop_id, case PROP_NUM_BUFFERS: g_value_set_int (value, self->num_buffers); break; + case PROP_TEST_PATTERN: + g_value_set_int (value, self->test_pattern); + break; + case PROP_HUE: + g_print("getting prop hue: %d\n", self->hue); + g_value_set_int (value, self->hue); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -221,6 +238,8 @@ gst_pinesrcbin_detect (GstPineSrcBin * self) GstElement *kid, *filter; GstPad *target; GstPineSrcBinClass *klass = GST_PINESRCBIN_GET_CLASS (self); + g_print ("gst_pinesrcbin_detect\n"); + GST_DEBUG_OBJECT (self, "gst_pinesrcbin_detect: setting up element"); gst_pinesrcbin_clear_kid (self); @@ -333,6 +352,7 @@ gst_pinesrcbin_class_init (GstPineSrcBinClass * klass) GObjectClass *gobject_class; GstElementClass *eklass; + g_print ("Class init\n"); gobject_class = G_OBJECT_CLASS (klass); eklass = GST_ELEMENT_CLASS (klass); @@ -349,7 +369,15 @@ gst_pinesrcbin_class_init (GstPineSrcBinClass * klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS, g_param_spec_int ("num-buffers", "Num-buffers", - "Number of buffers until EOS, -1 = unlimited", -1, INT_MAX, 1000, + "Number of buffers until EOS, -1 = unlimited", -1, INT_MAX, -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_TEST_PATTERN, + g_param_spec_int ("test-pattern", "Test-pattern", + "Test pattern for camera to display", 0, INT_MAX, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_HUE, + g_param_spec_int ("hue", "Hue", + "Set image hue", 0, 65535, 128, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } @@ -358,10 +386,14 @@ GST_DEBUG_CATEGORY (pinesrcbin_debug); static void gst_pinesrcbin_init (GstPineSrcBin * self) { + g_print ("Plugin init\n"); + self->sync = DEFAULT_SYNC; + self->num_buffers = -1; + self->test_pattern = 0; + self->hue = 128; + g_print("initial hue: %d\n", self->hue); GST_DEBUG_OBJECT (self, "Starting device configuration"); gst_pinesrcbin_configure_device(self, "rear"); - self->sync = DEFAULT_SYNC; - self->num_buffers = 1000; } static gboolean diff --git a/pinesrcbin.h b/pinesrcbin.h index f791ab3..88f8407 100644 --- a/pinesrcbin.h +++ b/pinesrcbin.h @@ -31,6 +31,8 @@ typedef struct _GstPineSrcBin gboolean autofocus; /* Buffers till EOS */ int num_buffers; + int test_pattern; + int hue; } GstPineSrcBin; #endif diff --git a/utility.c b/utility.c index 973b772..01c9b82 100644 --- a/utility.c +++ b/utility.c @@ -1,3 +1,7 @@ +/* insert copyright here * + * THE manual: https://www.kernel.org/doc/html/v5.7/media/uapi/mediactl/media-ioc-g-topology.html + */ + #include #include @@ -82,13 +86,14 @@ struct camera_data { int subdev_fd; const struct media_v2_entity *entity; const struct media_v2_interface *interface; + const struct media_v2_pad *pad; int gain_ctrl; int gain_max; char devnode_path[261]; }; struct camera_config configurations[] = { - {"front", "gc2145", 320, 240, MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_SBGGR8_1X8, {1, 15}}, - {"rear", "ov5640", 320, 240, MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_SBGGR8_1X8, {1, 15}}, + {"front", "gc2145", 320, 240, MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_SBGGR8_1X8, {1, 15}}, + {"rear", "ov5640", 1280, 720, MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_SBGGR8_1X8, {1, 30}}, }; struct camera_data cam_store[] = { {}, @@ -216,48 +221,6 @@ static void disable_all_links(struct device_data *dev) setup_link(dev, source_pad->id, sink_pad->id, FALSE); } } -#if 0 - const struct media_v2_link *plink = - gst_pinesrcbin_get_link_from_entity(dev, - dev->entities[i].id); - if (plink) { - g_print("link %d %08x %08x: %08x\n", plink->id, plink->source_id, plink->sink_id, plink->flags); - if (plink->flags & MEDIA_LNK_FL_ENABLED) { - uint32_t link_type = plink->flags & MEDIA_LNK_FL_LINK_TYPE; - if (link_type == MEDIA_LNK_FL_DATA_LINK) { - g_print("data link %d\n", plink->id); - setup_link(dev, plink->source_id, plink->sink_id, FALSE); - } else if (link_type == MEDIA_LNK_FL_INTERFACE_LINK) { - struct media_v2_interface *iface = st_pinesrcbin_get_interface_by_id(dev, plink->source_id); - g_print("interface link %d entity: %d\n", plink->id, iface->); - continue; - } - const struct media_v2_pad *source_pad, *sink_pad; - g_print("link %d is active\n", plink->id); - source_pad = gst_pinesrcbin_get_pad_from_entity(dev, plink->source_id); - sink_pad = gst_pinesrcbin_get_pad_from_entity(dev, plink->sink_id); - g_assert(source_pad); - g_assert(sink_pad); - setup_link(dev, source_pad->id, sink_pad->id, FALSE); -#if 0 - struct media_link_desc link = {}; - link.flags = 0; - link.source.entity = plink->source_id; - link.source.index = 0; - link.sink.entity = plink->sink_id; - link.sink.index = 0; - if (xioctl(dev->fd, MEDIA_IOC_SETUP_LINK, &link) == -1) - g_printerr("MEDIA_IOC_SETUP_LINK: %d %s", errno, strerror(errno)); -#endif -#if 0 - /* TODO: maintain own links structure */ - else - plink->flags = 0; -#endif - } - } - } -#endif } static struct device_data * @@ -342,6 +305,7 @@ setup_gain(int fd, int *gain_ctrl, int *gain_max) *gain_max = ctrl.maximum; return; } + camera_control(fd, *gain_ctrl, VIDIOC_S_EXT_CTRLS, gain_max); } static gboolean @@ -517,6 +481,20 @@ get_camera_data(const char *conf_name) return &cam_store[conf]; } } +void set_camera_control(const char * conf_name, int control, int value) +{ + struct camera_data *cam_data = get_camera_data(conf_name); + switch(control) { + case CONTROL_HUE: + g_print("configuring hue = %d\n", value); + camera_control (cam_data->subdev_fd, V4L2_CID_HUE, VIDIOC_S_EXT_CTRLS, &value); + break; + case CONTROL_SATURATION: + g_print("configuring saturation = %d\n", value); + camera_control (cam_data->subdev_fd, V4L2_CID_SATURATION, VIDIOC_S_EXT_CTRLS, &value); + break; + } +} void gst_pinesrcbin_configure_device(GstPineSrcBin * self, const char *conf_name) { struct camera_config *conf; @@ -565,7 +543,7 @@ void gst_pinesrcbin_configure_device(GstPineSrcBin * self, const char *conf_name if (!self->v4l2entity) g_error ("can't find entity sun6i-csi\n"); GST_DEBUG_OBJECT (self, "sink entity: %d %s\n", self->v4l2entity->id, self->v4l2entity->name); - /* This is sink pad (for host controller) */ + /* This is sink pad (for media controller) */ self->v4l2pad = gst_pinesrcbin_get_pad_from_entity (self->media_if, self->v4l2entity->id); GST_DEBUG_OBJECT (self, "sink pad: %d\n", self->v4l2pad->id); @@ -591,6 +569,8 @@ void gst_pinesrcbin_configure_device(GstPineSrcBin * self, const char *conf_name disable_all_links(self->media_if); cam_data->entity = gst_pinesrcbin_find_media_entity(self->media_if, conf->camera_name); GST_DEBUG_OBJECT (self, "camera: %s: source interface entity %d\n", conf->camera_name, cam_data->entity->id); + cam_data->pad = + gst_pinesrcbin_get_pad_from_entity (self->media_if, cam_data->entity->id); cam_data->interface = gst_pinesrcbin_get_entity_interface (self->media_if, @@ -612,10 +592,18 @@ void gst_pinesrcbin_configure_device(GstPineSrcBin * self, const char *conf_name camera_control (cam_data->subdev_fd, V4L2_CID_FOCUS_AUTO, VIDIOC_S_EXT_CTRLS, &enable); } setup_gain (cam_data->subdev_fd, &cam_data->gain_ctrl, &cam_data->gain_max); + camera_control (cam_data->subdev_fd, V4L2_CID_TEST_PATTERN, VIDIOC_S_EXT_CTRLS, &self->test_pattern); + { + int auto_gain = 1; + camera_control (cam_data->subdev_fd, V4L2_CID_AUTOGAIN, VIDIOC_S_EXT_CTRLS, &auto_gain); + } + set_camera_control(conf_name, CONTROL_HUE, self->hue); /* now configuring camera modes */ GST_DEBUG_OBJECT (self, "configuring camera modes\n"); subdev_set_mode(cam_data->subdev_fd, conf->width, conf->height, conf->bus_code_video, conf->frame_interval); + GST_DEBUG_OBJECT (self, "enabling link for %s\n", conf->camera_name); + setup_link(self->media_if, cam_data->pad->id, self->v4l2pad->id, TRUE); } diff --git a/utility.h b/utility.h index ee38ad5..fff2790 100644 --- a/utility.h +++ b/utility.h @@ -18,9 +18,16 @@ struct device_data struct media_v2_link *links; size_t num_links; }; + +enum { + CONTROL_HUE, + CONTROL_SATURATION +}; + void gst_pinesrcbin_configure_device(GstPineSrcBin * self, const char *conf_name); void gst_pinesrcbin_get_gst_caps_data(const char * conf_name, int *width, int * height, const char **format, struct v4l2_fract *interval); +void set_camera_control(const char * conf_name, int control, int value); #endif