[libcamera-devel] [PATCH] gstreamer: Add 'list-cameras' property

Umang Jain umang.jain at ideasonboard.com
Tue Jul 4 08:31:59 CEST 2023


Hi Nicolas

On 7/3/23 10:22 PM, Nicolas Dufresne wrote:
> Hi Ujain,
>
> Le lundi 03 juillet 2023 à 21:57 +0200, Umang Jain a écrit :
>> 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>
> I'm sorry, but I have to reject this. This is the job of the device provider. If
> some information is missing in the provider, just add it there.

Makes sense. I'll try writing a test to enumerate cameras on the device 
provider and using a pre-configured libcamerasrc.

For the missing information, does the camera-supported controls be a 
good candidate to get added to device-provider as well?  I see we are 
already enumerating streams in there but I understand those are part of 
the capabilities.
>
> NAK
>
>> ---
>>   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);
>>   };



More information about the libcamera-devel mailing list