[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