From 7839206c7fb9b243eba7987f9014b3edabad6901 Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Thu, 1 Apr 2021 14:37:45 +0300 Subject: [PATCH] Camera selection and mode change fixes --- pinesrcbin.c | 62 ++++++++++++++++++++++++++++++++++++++++------------ pinesrcbin.h | 1 + utility.c | 30 +++++++++++++------------ utility.h | 1 + 4 files changed, 66 insertions(+), 28 deletions(-) diff --git a/pinesrcbin.c b/pinesrcbin.c index 15dca62..5e75940 100644 --- a/pinesrcbin.c +++ b/pinesrcbin.c @@ -100,6 +100,7 @@ gst_pinesrcbin_create_fake_element (GstPineSrcBin * self) static gboolean gst_pinesrcbin_attach_ghost_pad (GstPineSrcBin * self) { + g_print("gst_pinesrcbin_attach_ghost_pad()\n"); GstPad *target = gst_element_get_static_pad (self->filter, self->type_klass_lc); gboolean res = gst_ghost_pad_set_target (GST_GHOST_PAD (self->pad), target); gst_object_unref (target); @@ -109,18 +110,25 @@ gst_pinesrcbin_attach_ghost_pad (GstPineSrcBin * self) static void gst_pinesrcbin_reset (GstPineSrcBin * self) { + g_print("gst_pinesrcbin_reset()\n"); gst_pinesrcbin_clear_kid (self); + GST_DEBUG_OBJECT (self, "gst_pinesrcbin_reset()"); /* placeholder element */ // self->kid = gst_pinesrcbin_create_fake_element (self); +// gst_element_set_state (self->kid, GST_STATE_NULL); +// gst_element_set_state (self->filter, GST_STATE_NULL); self->kid = gst_pinesrcbin_create_fake_element (self); self->filter = gst_element_factory_make ("capsfilter", NULL); - g_object_set (self->filter, "sync", self->sync, NULL); + if (g_object_class_find_property (G_OBJECT_GET_CLASS(self->filter), "sync")) + g_object_set (self->filter, "sync", self->sync, NULL); g_object_set (self->filter, "caps", self->filter_caps, NULL); gst_bin_add_many (GST_BIN (self), self->kid, self->filter, NULL); gst_element_link(self->kid, self->filter); gst_pinesrcbin_attach_ghost_pad (self); + gst_pinesrcbin_free_device(self); + GST_DEBUG_OBJECT (self, "gst_pinesrcbin_reset() done"); } static GstStaticCaps raw_video_caps = GST_STATIC_CAPS ("video/x-raw"); @@ -131,12 +139,15 @@ gst_pinesrcbin_constructed (GObject * object) const char *format; struct v4l2_fract interval; GstPineSrcBin *self = GST_PINESRCBIN (object); + g_print("gst_pinesrcbin_constructed()\n"); if (G_OBJECT_CLASS (parent_class)->constructed) G_OBJECT_CLASS (parent_class)->constructed (object); + GST_DEBUG_OBJECT (self, "gst_pinesrcbin_constructed: start"); self->type_klass = (self->flag == GST_ELEMENT_FLAG_SINK) ? "Sink" : "Source"; self->filter_caps = gst_static_caps_get (&raw_video_caps); gst_pinesrcbin_get_gst_caps_data(self->device, &width, &height, &format, &interval); + GST_DEBUG_OBJECT (self, "gst_pinesrcbin_constructed: got caps for %s %d %d", self->device, width, height); self->filter_caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING, format, /* we "flip" interval to get frame rate */ @@ -154,14 +165,16 @@ gst_pinesrcbin_constructed (GObject * object) GST_OBJECT_FLAG_SET (self, self->flag); gst_bin_set_suppressed_flags (GST_BIN (self), GST_ELEMENT_FLAG_SOURCE | GST_ELEMENT_FLAG_SINK); + GST_DEBUG_OBJECT (self, "gst_pinesrcbin_constructed: done"); } static void gst_pinesrcbin_dispose (GObject * object) { GstPineSrcBin *self = GST_PINESRCBIN (object); + g_print ("gst_pinesrcbin_dispose()\n"); - GST_DEBUG_OBJECT (self, "gst_pinesrcbin_dispose: dispose"); + GST_DEBUG_OBJECT (self, "gst_pinesrcbin_dispose: start"); gst_pinesrcbin_clear_kid (self); if (self->filter_caps) @@ -169,6 +182,7 @@ gst_pinesrcbin_dispose (GObject * object) self->filter_caps = NULL; G_OBJECT_CLASS (parent_class)->dispose ((GObject *) self); + GST_DEBUG_OBJECT (self, "gst_pinesrcbin_dispose: done"); } static void @@ -176,6 +190,8 @@ gst_pinesrcbin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstPineSrcBin *self = GST_PINESRCBIN (object); + GstState next_state = GST_STATE(self); + g_print ("gst_pinesrcbin_set_property()\n"); switch (prop_id) { case PROP_CAPS: @@ -196,21 +212,31 @@ gst_pinesrcbin_set_property (GObject * object, guint prop_id, case PROP_TEST_PATTERN: self->test_pattern = g_value_get_int (value); g_print("setting prop test-pattern: %d\n", self->test_pattern); - set_camera_control(self->device, CONTROL_TEST_PATTERN, self->test_pattern); + if (GST_STATE(self) == GST_STATE_PLAYING) + set_camera_control(self->device, CONTROL_TEST_PATTERN, self->test_pattern); break; case PROP_HUE: self->hue = g_value_get_int (value); g_print("setting prop hue: %d\n", self->hue); - set_camera_control(self->device, CONTROL_HUE, self->hue); + if (GST_STATE(self) == GST_STATE_PLAYING) + set_camera_control(self->device, CONTROL_HUE, self->hue); break; case PROP_MODE: - self->mode = g_value_get_int (value); - g_print("setting prop mode: %d\n", self->mode); + { + if (GST_STATE(self) > GST_STATE_NULL) + gst_element_set_state (self, GST_STATE_NULL); + self->mode = g_value_get_int (value); + g_print("setting prop mode: %d\n", self->mode); + if (GST_STATE(self) > GST_STATE_NULL) + gst_element_set_state (self, next_state); + } break; case PROP_DEVICE: { - const char * devname = g_value_get_int (value); - g_print("setting prop device: %s\n", devname); + if (GST_STATE(self) > GST_STATE_NULL) + gst_element_set_state (self, GST_STATE_NULL); + const char * devname = g_value_get_string (value); + g_print("!!!setting prop device: %s\n", devname); if (devname && strlen(devname) > 0) { if (self->device) g_free(self->device); @@ -222,6 +248,8 @@ gst_pinesrcbin_set_property (GObject * object, guint prop_id, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + if (GST_STATE(self) != next_state) + gst_element_set_state (self, next_state); } static void @@ -229,6 +257,7 @@ gst_pinesrcbin_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstPineSrcBin *self = GST_PINESRCBIN (object); + g_print ("gst_pinesrcbin_get_property()\n"); switch (prop_id) { case PROP_CAPS: @@ -252,8 +281,8 @@ gst_pinesrcbin_get_property (GObject * object, guint prop_id, g_value_set_int (value, self->mode); break; case PROP_DEVICE: - g_print("getting prop device: %s\n", ""); - g_value_set_string (value, ""); + g_print("getting prop device: %s\n", self->device); + g_value_set_string (value, self->device); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -267,9 +296,11 @@ gst_pinesrcbin_detect (GstPineSrcBin * self) GstElement *kid, *filter; GstPad *target; GstPineSrcBinClass *klass = GST_PINESRCBIN_GET_CLASS (self); - g_print ("gst_pinesrcbin_detect\n"); + g_print ("gst_pinesrcbin_detect start\n"); GST_DEBUG_OBJECT (self, "gst_pinesrcbin_detect: setting up element"); + gst_pinesrcbin_configure_device(self, self->device); + gst_pinesrcbin_clear_kid (self); GST_DEBUG_OBJECT (self, "Creating v4l2src element"); @@ -289,7 +320,7 @@ gst_pinesrcbin_detect (GstPineSrcBin * self) gst_pad_use_fixed_caps (target); gst_pad_set_caps(target, self->filter_caps); - GST_DEBUG_OBJECT (self, "Setting default properties for v4l2src element"); + GST_DEBUG_OBJECT (self, "Setting properties defaults for v4l2src element"); self->has_sync = g_object_class_find_property (G_OBJECT_GET_CLASS (kid), "sync") != NULL; if (self->has_sync) @@ -350,6 +381,7 @@ gst_pinesrcbin_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstPineSrcBin *sink = GST_PINESRCBIN (element); + g_print ("gst_pinesrcbin_change_state()\n"); GST_DEBUG_OBJECT (sink, "gst_pinesrcbin_change_state: state change"); switch (transition) { @@ -424,16 +456,18 @@ GST_DEBUG_CATEGORY (pinesrcbin_debug); static void gst_pinesrcbin_init (GstPineSrcBin * self) { + GST_DEBUG_CATEGORY_INIT (pinesrcbin_debug, "pinesrcbin", 0, + "pinephone v4lsrc camera wrapper"); g_print ("Plugin init\n"); self->sync = DEFAULT_SYNC; self->num_buffers = -1; self->test_pattern = 0; self->hue = 128; self->mode = 1; - self->device = g_strdup("front"); + self->device = g_strdup("primary"); + self->media_if = NULL; g_print("initial hue: %d\n", self->hue); GST_DEBUG_OBJECT (self, "Starting device configuration"); - gst_pinesrcbin_configure_device(self, "rear"); } static gboolean diff --git a/pinesrcbin.h b/pinesrcbin.h index d21a01e..9285633 100644 --- a/pinesrcbin.h +++ b/pinesrcbin.h @@ -34,6 +34,7 @@ typedef struct _GstPineSrcBin int test_pattern; int hue; int mode; + const gchar *device; } GstPineSrcBin; #endif diff --git a/utility.c b/utility.c index b085a91..4c50cf7 100644 --- a/utility.c +++ b/utility.c @@ -92,8 +92,8 @@ struct camera_data { char devnode_path[261]; }; struct camera_config configurations[] = { - {"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}}, + {"secondary", "gc2145", 1280, 720, MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_SBGGR8_1X8, {1, 15}}, + {"primary", "ov5640", 1280, 720, MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_SBGGR8_1X8, {1, 30}}, }; struct camera_data cam_store[] = { {}, @@ -161,10 +161,8 @@ gst_pinesrcbin_get_entity_interface(struct device_data *dev, uint32_t id) { const struct media_v2_link *link = gst_pinesrcbin_get_link_from_entity(dev, id); - g_print("entity id: %d\n", id); if (!link) return NULL; - g_print("link id: %d %d\n", link->sink_id, link->source_id); return gst_pinesrcbin_get_interface_by_id(dev, link->source_id); } @@ -186,9 +184,6 @@ gst_pinesrcbin_find_media_entity(struct device_data *dev, { int length = strlen(driver_name); int i; - for (i = 0; i < dev->num_entities; i++) - g_print("%s: entity: %s:%d:%s\n", dev->path, dev->entities[i].name, - dev->entities[i].id, driver_name); for (i = 0; i < dev->num_entities; i++) { if (!strncmp(dev->entities[i].name, driver_name, length)) return &dev->entities[i]; @@ -206,7 +201,6 @@ static void disable_all_links(struct device_data *dev) continue; if (!(sink_pad->flags & MEDIA_PAD_FL_SINK)) continue; - g_print("sink pad: %d\n", sink_pad->id); for (j = 0; j < dev->num_entities; j++) { if (i == j) continue; @@ -214,10 +208,8 @@ static void disable_all_links(struct device_data *dev) gst_pinesrcbin_get_pad_from_entity (dev, dev->entities[j].id); if (!source_pad) continue; - g_print("source pad: %d\n", source_pad->id); if (!(source_pad->flags & MEDIA_PAD_FL_SOURCE)) continue; - g_print("disabling link %d %d\n", source_pad->entity_id, sink_pad->entity_id); setup_link(dev, source_pad->id, sink_pad->id, FALSE); } } @@ -377,7 +369,7 @@ static int alloc_device(struct device_data *dev) rc = xioctl(dev->fd, MEDIA_IOC_G_TOPOLOGY, &dev->topology); if (rc < 0) { - g_printerr("topology x1 error %d %d %s\n", rc, + g_error("topology x1 error %d %d %s\n", rc, errno, strerror(errno)); goto out; } @@ -399,12 +391,10 @@ static int alloc_device(struct device_data *dev) dev->topology.ptr_interfaces = (uint64_t)dev->interfaces; dev->topology.ptr_pads = (uint64_t)dev->pads; dev->topology.ptr_links = (uint64_t)dev->links; - g_print("topology x2\n"); rc = xioctl(dev->fd, MEDIA_IOC_G_TOPOLOGY, &dev->topology); if (rc < 0) goto out; - g_print("device info\n"); rc = xioctl(dev->fd, MEDIA_IOC_DEVICE_INFO, &dev->info); out: return rc; @@ -596,7 +586,7 @@ 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); - self->test_pattern = 1; + /* self->test_pattern = 1; */ camera_control (cam_data->subdev_fd, V4L2_CID_TEST_PATTERN, VIDIOC_S_EXT_CTRLS, &self->test_pattern); { int auto_gain = 1; @@ -612,3 +602,15 @@ void gst_pinesrcbin_configure_device(GstPineSrcBin * self, const char *conf_name setup_link(self->media_if, cam_data->pad->id, self->v4l2pad->id, TRUE); } + +void gst_pinesrcbin_free_device(GstPineSrcBin * self) +{ + struct camera_data *cam_data = get_camera_data(self->device); + if (!self->media_if) + return; + close(cam_data->subdev_fd); + close(self->fd); + disable_all_links(self->media_if); + close(self->media_if); +} + diff --git a/utility.h b/utility.h index 91a4d87..35cec01 100644 --- a/utility.h +++ b/utility.h @@ -26,6 +26,7 @@ enum { }; void gst_pinesrcbin_configure_device(GstPineSrcBin * self, const char *conf_name); +void gst_pinesrcbin_free_device(GstPineSrcBin * self); void gst_pinesrcbin_get_gst_caps_data(const char * conf_name, int *width, int * height, const char **format, struct v4l2_fract *interval);