[libcamera-devel] [PATCH] gstreamer: Add 'list-cameras' property
Umang Jain
umang.jain at ideasonboard.com
Mon Jul 3 21:57:25 CEST 2023
Add a new property called 'list-cameras' on libcamerasrc to enumerate
and expose the cameras present on the system. The enumeration will help
appplications using libcamerasrc to know and set the 'camera-name'
property in order to use that camera with libcamerasrc.
Signed-off-by: Umang Jain <umang.jain at ideasonboard.com>
---
src/gstreamer/gstlibcamerasrc.cpp | 46 +++++++++++++++++++++++++++++++
test/gstreamer/gstreamer_test.cpp | 30 ++++++++++++++++++++
test/gstreamer/gstreamer_test.h | 2 ++
3 files changed, 78 insertions(+)
diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
index 1f10136b..f337728a 100644
--- a/src/gstreamer/gstlibcamerasrc.cpp
+++ b/src/gstreamer/gstlibcamerasrc.cpp
@@ -152,6 +152,7 @@ struct _GstLibcameraSrc {
enum {
PROP_0,
PROP_CAMERA_NAME,
+ PROP_LIST_CAMERAS,
PROP_AUTO_FOCUS_MODE,
};
@@ -666,6 +667,39 @@ gst_libcamera_src_close(GstLibcameraSrc *self)
state->cm_.reset();
}
+static gboolean
+gst_libcamera_src_set_cameras_list(GstLibcameraSrc *self, GValue *value)
+{
+ std::shared_ptr<CameraManager> cm;
+ GValue val = G_VALUE_INIT;
+ gint ret;
+
+ g_value_init(&val, G_TYPE_STRING);
+ g_value_reset(value);
+
+ cm = gst_libcamera_get_camera_manager(ret);
+ if (ret) {
+ GST_ELEMENT_ERROR(self, LIBRARY, INIT,
+ ("Failed listing cameras."),
+ ("libcamera::CameraMananger::start() failed: %s", g_strerror(-ret)));
+ return false;
+ }
+
+ if (cm->cameras().empty()) {
+ GST_ELEMENT_ERROR(self, RESOURCE, NOT_FOUND,
+ ("Could not find any supported camera on this system."),
+ ("libcamera::CameraMananger::cameras() is empty"));
+ return false;
+ }
+
+ for (const std::shared_ptr<Camera> &cam : cm->cameras()) {
+ g_value_set_string(&val, cam->id().c_str());
+ gst_value_array_append_value(value, &val);
+ }
+
+ return true;
+}
+
static void
gst_libcamera_src_set_property(GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
@@ -699,6 +733,9 @@ gst_libcamera_src_get_property(GObject *object, guint prop_id, GValue *value,
case PROP_CAMERA_NAME:
g_value_set_string(value, self->camera_name);
break;
+ case PROP_LIST_CAMERAS:
+ gst_libcamera_src_set_cameras_list(self, value);
+ break;
case PROP_AUTO_FOCUS_MODE: {
auto auto_focus_mode = self->controls->get(controls::AfMode).value_or(controls::AfModeManual);
g_value_set_enum(value, auto_focus_mode);
@@ -879,6 +916,15 @@ gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)
| G_PARAM_STATIC_STRINGS));
g_object_class_install_property(object_class, PROP_CAMERA_NAME, spec);
+ spec = gst_param_spec_array("list-cameras", "Cameras list",
+ "Retrieve list of all cameras",
+ g_param_spec_string("camera-name", "Camera name",
+ "Name of the camera", nullptr,
+ (GParamFlags)(G_PARAM_READABLE
+ | G_PARAM_STATIC_STRINGS)),
+ (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property(object_class, PROP_LIST_CAMERAS, spec);
+
spec = g_param_spec_enum("auto-focus-mode",
"Set auto-focus mode",
"Available options: AfModeManual, "
diff --git a/test/gstreamer/gstreamer_test.cpp b/test/gstreamer/gstreamer_test.cpp
index 6ad0c15c..7f3ccd2b 100644
--- a/test/gstreamer/gstreamer_test.cpp
+++ b/test/gstreamer/gstreamer_test.cpp
@@ -97,6 +97,9 @@ bool GstreamerTest::checkMinCameraStreamsAndSetCameraName(unsigned int numStream
break;
}
+ for (auto &camera : cm.cameras())
+ cameraNames_.push_back(strdup(camera->id().c_str()));
+
cm.stop();
return cameraFound;
@@ -112,6 +115,9 @@ GstreamerTest::~GstreamerTest()
int GstreamerTest::createPipeline()
{
+ GValue cameras_list_array = G_VALUE_INIT;
+ guint index, i;
+
libcameraSrc_ = gst_element_factory_make("libcamerasrc", "libcamera");
pipeline_ = gst_pipeline_new("test-pipeline");
@@ -125,6 +131,30 @@ int GstreamerTest::createPipeline()
g_object_set(libcameraSrc_, "camera-name", cameraName_.c_str(), NULL);
g_object_ref_sink(libcameraSrc_);
+ g_value_init(&cameras_list_array, GST_TYPE_ARRAY);
+ g_object_get_property(G_OBJECT(libcameraSrc_), "list-cameras", &cameras_list_array);
+ if (gst_value_array_get_size(&cameras_list_array) != cameraNames_.size()) {
+ g_printerr("libcamerasrc 'list-cameras' properties count does not match.\n");
+ return TestFail;
+ }
+
+ for (index = 0; index < cameraNames_.size(); index++) {
+ bool matched = false;
+
+ for (i = 0; i < gst_value_array_get_size(&cameras_list_array); i++) {
+ const char *cam = g_value_get_string(gst_value_array_get_value(&cameras_list_array, i));
+ if (strcmp(cam, cameraNames_[index]) == 0) {
+ matched = true;
+ break;
+ }
+ }
+
+ if (!matched) {
+ g_printerr("Camera %s not found in 'list-cameras' property.\n", cameraNames_[index]);
+ return TestFail;
+ }
+ }
+
return TestPass;
}
diff --git a/test/gstreamer/gstreamer_test.h b/test/gstreamer/gstreamer_test.h
index aa2261e2..5d61bc2a 100644
--- a/test/gstreamer/gstreamer_test.h
+++ b/test/gstreamer/gstreamer_test.h
@@ -9,6 +9,7 @@
#include <iostream>
#include <unistd.h>
+#include <vector>
#include <gst/gst.h>
@@ -29,6 +30,7 @@ protected:
GstElement *libcameraSrc_;
int status_;
+ std::vector<const char *> cameraNames_;
private:
bool checkMinCameraStreamsAndSetCameraName(unsigned int numStreams);
};
--
2.39.1
More information about the libcamera-devel
mailing list