Camera selection and mode change fixes

This commit is contained in:
Sergey Lapin
2021-04-01 14:37:45 +03:00
parent e4f5f44f85
commit 7839206c7f
4 changed files with 66 additions and 28 deletions

View File

@@ -100,6 +100,7 @@ gst_pinesrcbin_create_fake_element (GstPineSrcBin * self)
static gboolean static gboolean
gst_pinesrcbin_attach_ghost_pad (GstPineSrcBin * self) 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); 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); gboolean res = gst_ghost_pad_set_target (GST_GHOST_PAD (self->pad), target);
gst_object_unref (target); gst_object_unref (target);
@@ -109,18 +110,25 @@ gst_pinesrcbin_attach_ghost_pad (GstPineSrcBin * self)
static void static void
gst_pinesrcbin_reset (GstPineSrcBin * self) gst_pinesrcbin_reset (GstPineSrcBin * self)
{ {
g_print("gst_pinesrcbin_reset()\n");
gst_pinesrcbin_clear_kid (self); gst_pinesrcbin_clear_kid (self);
GST_DEBUG_OBJECT (self, "gst_pinesrcbin_reset()");
/* placeholder element */ /* placeholder element */
// self->kid = gst_pinesrcbin_create_fake_element (self); // 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->kid = gst_pinesrcbin_create_fake_element (self);
self->filter = gst_element_factory_make ("capsfilter", NULL); self->filter = gst_element_factory_make ("capsfilter", 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, "sync", self->sync, NULL);
g_object_set (self->filter, "caps", self->filter_caps, NULL); g_object_set (self->filter, "caps", self->filter_caps, NULL);
gst_bin_add_many (GST_BIN (self), self->kid, self->filter, NULL); gst_bin_add_many (GST_BIN (self), self->kid, self->filter, NULL);
gst_element_link(self->kid, self->filter); gst_element_link(self->kid, self->filter);
gst_pinesrcbin_attach_ghost_pad (self); 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"); static GstStaticCaps raw_video_caps = GST_STATIC_CAPS ("video/x-raw");
@@ -131,12 +139,15 @@ gst_pinesrcbin_constructed (GObject * object)
const char *format; const char *format;
struct v4l2_fract interval; struct v4l2_fract interval;
GstPineSrcBin *self = GST_PINESRCBIN (object); GstPineSrcBin *self = GST_PINESRCBIN (object);
g_print("gst_pinesrcbin_constructed()\n");
if (G_OBJECT_CLASS (parent_class)->constructed) if (G_OBJECT_CLASS (parent_class)->constructed)
G_OBJECT_CLASS (parent_class)->constructed (object); 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->type_klass = (self->flag == GST_ELEMENT_FLAG_SINK) ? "Sink" : "Source";
self->filter_caps = gst_static_caps_get (&raw_video_caps); self->filter_caps = gst_static_caps_get (&raw_video_caps);
gst_pinesrcbin_get_gst_caps_data(self->device, &width, &height, &format, &interval); 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", self->filter_caps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, format, "format", G_TYPE_STRING, format,
/* we "flip" interval to get frame rate */ /* we "flip" interval to get frame rate */
@@ -154,14 +165,16 @@ gst_pinesrcbin_constructed (GObject * object)
GST_OBJECT_FLAG_SET (self, self->flag); GST_OBJECT_FLAG_SET (self, self->flag);
gst_bin_set_suppressed_flags (GST_BIN (self), gst_bin_set_suppressed_flags (GST_BIN (self),
GST_ELEMENT_FLAG_SOURCE | GST_ELEMENT_FLAG_SINK); GST_ELEMENT_FLAG_SOURCE | GST_ELEMENT_FLAG_SINK);
GST_DEBUG_OBJECT (self, "gst_pinesrcbin_constructed: done");
} }
static void static void
gst_pinesrcbin_dispose (GObject * object) gst_pinesrcbin_dispose (GObject * object)
{ {
GstPineSrcBin *self = GST_PINESRCBIN (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); gst_pinesrcbin_clear_kid (self);
if (self->filter_caps) if (self->filter_caps)
@@ -169,6 +182,7 @@ gst_pinesrcbin_dispose (GObject * object)
self->filter_caps = NULL; self->filter_caps = NULL;
G_OBJECT_CLASS (parent_class)->dispose ((GObject *) self); G_OBJECT_CLASS (parent_class)->dispose ((GObject *) self);
GST_DEBUG_OBJECT (self, "gst_pinesrcbin_dispose: done");
} }
static void static void
@@ -176,6 +190,8 @@ gst_pinesrcbin_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec) const GValue * value, GParamSpec * pspec)
{ {
GstPineSrcBin *self = GST_PINESRCBIN (object); GstPineSrcBin *self = GST_PINESRCBIN (object);
GstState next_state = GST_STATE(self);
g_print ("gst_pinesrcbin_set_property()\n");
switch (prop_id) { switch (prop_id) {
case PROP_CAPS: case PROP_CAPS:
@@ -196,21 +212,31 @@ gst_pinesrcbin_set_property (GObject * object, guint prop_id,
case PROP_TEST_PATTERN: case PROP_TEST_PATTERN:
self->test_pattern = g_value_get_int (value); self->test_pattern = g_value_get_int (value);
g_print("setting prop test-pattern: %d\n", self->test_pattern); g_print("setting prop test-pattern: %d\n", self->test_pattern);
if (GST_STATE(self) == GST_STATE_PLAYING)
set_camera_control(self->device, CONTROL_TEST_PATTERN, self->test_pattern); set_camera_control(self->device, CONTROL_TEST_PATTERN, self->test_pattern);
break; break;
case PROP_HUE: case PROP_HUE:
self->hue = g_value_get_int (value); self->hue = g_value_get_int (value);
g_print("setting prop hue: %d\n", self->hue); g_print("setting prop hue: %d\n", self->hue);
if (GST_STATE(self) == GST_STATE_PLAYING)
set_camera_control(self->device, CONTROL_HUE, self->hue); set_camera_control(self->device, CONTROL_HUE, self->hue);
break; break;
case PROP_MODE: case PROP_MODE:
{
if (GST_STATE(self) > GST_STATE_NULL)
gst_element_set_state (self, GST_STATE_NULL);
self->mode = g_value_get_int (value); self->mode = g_value_get_int (value);
g_print("setting prop mode: %d\n", self->mode); g_print("setting prop mode: %d\n", self->mode);
if (GST_STATE(self) > GST_STATE_NULL)
gst_element_set_state (self, next_state);
}
break; break;
case PROP_DEVICE: case PROP_DEVICE:
{ {
const char * devname = g_value_get_int (value); if (GST_STATE(self) > GST_STATE_NULL)
g_print("setting prop device: %s\n", devname); 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 (devname && strlen(devname) > 0) {
if (self->device) if (self->device)
g_free(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); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
if (GST_STATE(self) != next_state)
gst_element_set_state (self, next_state);
} }
static void static void
@@ -229,6 +257,7 @@ gst_pinesrcbin_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec) GValue * value, GParamSpec * pspec)
{ {
GstPineSrcBin *self = GST_PINESRCBIN (object); GstPineSrcBin *self = GST_PINESRCBIN (object);
g_print ("gst_pinesrcbin_get_property()\n");
switch (prop_id) { switch (prop_id) {
case PROP_CAPS: case PROP_CAPS:
@@ -252,8 +281,8 @@ gst_pinesrcbin_get_property (GObject * object, guint prop_id,
g_value_set_int (value, self->mode); g_value_set_int (value, self->mode);
break; break;
case PROP_DEVICE: case PROP_DEVICE:
g_print("getting prop device: %s\n", ""); g_print("getting prop device: %s\n", self->device);
g_value_set_string (value, ""); g_value_set_string (value, self->device);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -267,9 +296,11 @@ gst_pinesrcbin_detect (GstPineSrcBin * self)
GstElement *kid, *filter; GstElement *kid, *filter;
GstPad *target; GstPad *target;
GstPineSrcBinClass *klass = GST_PINESRCBIN_GET_CLASS (self); 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_DEBUG_OBJECT (self, "gst_pinesrcbin_detect: setting up element");
gst_pinesrcbin_configure_device(self, self->device);
gst_pinesrcbin_clear_kid (self); gst_pinesrcbin_clear_kid (self);
GST_DEBUG_OBJECT (self, "Creating v4l2src element"); GST_DEBUG_OBJECT (self, "Creating v4l2src element");
@@ -289,7 +320,7 @@ gst_pinesrcbin_detect (GstPineSrcBin * self)
gst_pad_use_fixed_caps (target); gst_pad_use_fixed_caps (target);
gst_pad_set_caps(target, self->filter_caps); 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 = self->has_sync =
g_object_class_find_property (G_OBJECT_GET_CLASS (kid), "sync") != NULL; g_object_class_find_property (G_OBJECT_GET_CLASS (kid), "sync") != NULL;
if (self->has_sync) if (self->has_sync)
@@ -350,6 +381,7 @@ gst_pinesrcbin_change_state (GstElement * element, GstStateChange transition)
{ {
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
GstPineSrcBin *sink = GST_PINESRCBIN (element); GstPineSrcBin *sink = GST_PINESRCBIN (element);
g_print ("gst_pinesrcbin_change_state()\n");
GST_DEBUG_OBJECT (sink, "gst_pinesrcbin_change_state: state change"); GST_DEBUG_OBJECT (sink, "gst_pinesrcbin_change_state: state change");
switch (transition) { switch (transition) {
@@ -424,16 +456,18 @@ GST_DEBUG_CATEGORY (pinesrcbin_debug);
static void static void
gst_pinesrcbin_init (GstPineSrcBin * self) gst_pinesrcbin_init (GstPineSrcBin * self)
{ {
GST_DEBUG_CATEGORY_INIT (pinesrcbin_debug, "pinesrcbin", 0,
"pinephone v4lsrc camera wrapper");
g_print ("Plugin init\n"); g_print ("Plugin init\n");
self->sync = DEFAULT_SYNC; self->sync = DEFAULT_SYNC;
self->num_buffers = -1; self->num_buffers = -1;
self->test_pattern = 0; self->test_pattern = 0;
self->hue = 128; self->hue = 128;
self->mode = 1; 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); g_print("initial hue: %d\n", self->hue);
GST_DEBUG_OBJECT (self, "Starting device configuration"); GST_DEBUG_OBJECT (self, "Starting device configuration");
gst_pinesrcbin_configure_device(self, "rear");
} }
static gboolean static gboolean

View File

@@ -34,6 +34,7 @@ typedef struct _GstPineSrcBin
int test_pattern; int test_pattern;
int hue; int hue;
int mode; int mode;
const gchar *device;
} GstPineSrcBin; } GstPineSrcBin;
#endif #endif

View File

@@ -92,8 +92,8 @@ struct camera_data {
char devnode_path[261]; char devnode_path[261];
}; };
struct camera_config configurations[] = { struct camera_config configurations[] = {
{"front", "gc2145", 320, 240, MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_SBGGR8_1X8, {1, 15}}, {"secondary", "gc2145", 1280, 720, 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}}, {"primary", "ov5640", 1280, 720, MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_SBGGR8_1X8, {1, 30}},
}; };
struct camera_data cam_store[] = { 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 = const struct media_v2_link *link =
gst_pinesrcbin_get_link_from_entity(dev, id); gst_pinesrcbin_get_link_from_entity(dev, id);
g_print("entity id: %d\n", id);
if (!link) if (!link)
return NULL; 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); 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 length = strlen(driver_name);
int i; 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++) { for (i = 0; i < dev->num_entities; i++) {
if (!strncmp(dev->entities[i].name, driver_name, length)) if (!strncmp(dev->entities[i].name, driver_name, length))
return &dev->entities[i]; return &dev->entities[i];
@@ -206,7 +201,6 @@ static void disable_all_links(struct device_data *dev)
continue; continue;
if (!(sink_pad->flags & MEDIA_PAD_FL_SINK)) if (!(sink_pad->flags & MEDIA_PAD_FL_SINK))
continue; continue;
g_print("sink pad: %d\n", sink_pad->id);
for (j = 0; j < dev->num_entities; j++) { for (j = 0; j < dev->num_entities; j++) {
if (i == j) if (i == j)
continue; 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); gst_pinesrcbin_get_pad_from_entity (dev, dev->entities[j].id);
if (!source_pad) if (!source_pad)
continue; continue;
g_print("source pad: %d\n", source_pad->id);
if (!(source_pad->flags & MEDIA_PAD_FL_SOURCE)) if (!(source_pad->flags & MEDIA_PAD_FL_SOURCE))
continue; 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); 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); rc = xioctl(dev->fd, MEDIA_IOC_G_TOPOLOGY, &dev->topology);
if (rc < 0) 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)); errno, strerror(errno));
goto out; 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_interfaces = (uint64_t)dev->interfaces;
dev->topology.ptr_pads = (uint64_t)dev->pads; dev->topology.ptr_pads = (uint64_t)dev->pads;
dev->topology.ptr_links = (uint64_t)dev->links; dev->topology.ptr_links = (uint64_t)dev->links;
g_print("topology x2\n");
rc = xioctl(dev->fd, MEDIA_IOC_G_TOPOLOGY, &dev->topology); rc = xioctl(dev->fd, MEDIA_IOC_G_TOPOLOGY, &dev->topology);
if (rc < 0) if (rc < 0)
goto out; goto out;
g_print("device info\n");
rc = xioctl(dev->fd, MEDIA_IOC_DEVICE_INFO, &dev->info); rc = xioctl(dev->fd, MEDIA_IOC_DEVICE_INFO, &dev->info);
out: out:
return rc; 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); 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); 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); camera_control (cam_data->subdev_fd, V4L2_CID_TEST_PATTERN, VIDIOC_S_EXT_CTRLS, &self->test_pattern);
{ {
int auto_gain = 1; 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); 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);
}

View File

@@ -26,6 +26,7 @@ enum {
}; };
void gst_pinesrcbin_configure_device(GstPineSrcBin * self, const char *conf_name); 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, void gst_pinesrcbin_get_gst_caps_data(const char * conf_name,
int *width, int * height, const char **format, int *width, int * height, const char **format,
struct v4l2_fract *interval); struct v4l2_fract *interval);