[libcamera-devel] [PATCH] gstreamer: Add 'list-cameras' property
Kieran Bingham
kieran.bingham at ideasonboard.com
Mon Jul 3 22:27:11 CEST 2023
Quoting Umang Jain via libcamera-devel (2023-07-03 20:57:25)
> 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.
>
Having a way to list the available camera names sounds good - I don't
know if there is a better way to tie this into the gstreamer components.
How would you see this used?
is it something like
'gst-launch gstlibcamerasrc list-cameras' ?
Should this list be reported in gst-inspect or such ?
--
Kieran
> 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