[{"id":27451,"web_url":"https://patchwork.libcamera.org/comment/27451/","msgid":"<4925b314512f5983bdd5e48be5a6de3c95deaa7b.camel@collabora.com>","date":"2023-07-03T20:22:41","subject":"Re: [libcamera-devel] [PATCH] gstreamer: Add 'list-cameras' property","submitter":{"id":31,"url":"https://patchwork.libcamera.org/api/people/31/","name":"Nicolas Dufresne","email":"nicolas.dufresne@collabora.com"},"content":"Hi Ujain,\n\nLe lundi 03 juillet 2023 à 21:57 +0200, Umang Jain a écrit :\n> Add a new property called 'list-cameras' on libcamerasrc to enumerate\n> and expose the cameras present on the system. The enumeration will help\n> appplications using libcamerasrc to know and set the 'camera-name'\n> property in order to use that camera with libcamerasrc.\n> \n> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>\n\nI'm sorry, but I have to reject this. This is the job of the device provider. If\nsome information is missing in the provider, just add it there.\n\nNAK\n\n> ---\n>  src/gstreamer/gstlibcamerasrc.cpp | 46 +++++++++++++++++++++++++++++++\n>  test/gstreamer/gstreamer_test.cpp | 30 ++++++++++++++++++++\n>  test/gstreamer/gstreamer_test.h   |  2 ++\n>  3 files changed, 78 insertions(+)\n> \n> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\n> index 1f10136b..f337728a 100644\n> --- a/src/gstreamer/gstlibcamerasrc.cpp\n> +++ b/src/gstreamer/gstlibcamerasrc.cpp\n> @@ -152,6 +152,7 @@ struct _GstLibcameraSrc {\n>  enum {\n>  \tPROP_0,\n>  \tPROP_CAMERA_NAME,\n> +\tPROP_LIST_CAMERAS,\n>  \tPROP_AUTO_FOCUS_MODE,\n>  };\n>  \n> @@ -666,6 +667,39 @@ gst_libcamera_src_close(GstLibcameraSrc *self)\n>  \tstate->cm_.reset();\n>  }\n>  \n> +static gboolean\n> +gst_libcamera_src_set_cameras_list(GstLibcameraSrc *self, GValue *value)\n> +{\n> +\tstd::shared_ptr<CameraManager> cm;\n> +\tGValue val = G_VALUE_INIT;\n> +\tgint ret;\n> +\n> +\tg_value_init(&val, G_TYPE_STRING);\n> +\tg_value_reset(value);\n> +\n> +\tcm = gst_libcamera_get_camera_manager(ret);\n> +\tif (ret) {\n> +\t\tGST_ELEMENT_ERROR(self, LIBRARY, INIT,\n> +\t\t\t\t  (\"Failed listing cameras.\"),\n> +\t\t\t\t  (\"libcamera::CameraMananger::start() failed: %s\", g_strerror(-ret)));\n> +\t\treturn false;\n> +\t}\n> +\n> +\tif (cm->cameras().empty()) {\n> +\t\tGST_ELEMENT_ERROR(self, RESOURCE, NOT_FOUND,\n> +\t\t\t\t  (\"Could not find any supported camera on this system.\"),\n> +\t\t\t\t  (\"libcamera::CameraMananger::cameras() is empty\"));\n> +\t\treturn false;\n> +\t}\n> +\n> +\tfor (const std::shared_ptr<Camera> &cam : cm->cameras()) {\n> +\t\tg_value_set_string(&val, cam->id().c_str());\n> +\t\tgst_value_array_append_value(value, &val);\n> +\t}\n> +\n> +\treturn true;\n> +}\n> +\n>  static void\n>  gst_libcamera_src_set_property(GObject *object, guint prop_id,\n>  \t\t\t       const GValue *value, GParamSpec *pspec)\n> @@ -699,6 +733,9 @@ gst_libcamera_src_get_property(GObject *object, guint prop_id, GValue *value,\n>  \tcase PROP_CAMERA_NAME:\n>  \t\tg_value_set_string(value, self->camera_name);\n>  \t\tbreak;\n> +\tcase PROP_LIST_CAMERAS:\n> +\t\tgst_libcamera_src_set_cameras_list(self, value);\n> +\t\tbreak;\n>  \tcase PROP_AUTO_FOCUS_MODE: {\n>  \t\tauto auto_focus_mode = self->controls->get(controls::AfMode).value_or(controls::AfModeManual);\n>  \t\tg_value_set_enum(value, auto_focus_mode);\n> @@ -879,6 +916,15 @@ gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)\n>  \t\t\t\t\t\t\t     | G_PARAM_STATIC_STRINGS));\n>  \tg_object_class_install_property(object_class, PROP_CAMERA_NAME, spec);\n>  \n> +\tspec = gst_param_spec_array(\"list-cameras\", \"Cameras list\",\n> +\t\t\t\t    \"Retrieve list of all cameras\",\n> +\t\t\t\t    g_param_spec_string(\"camera-name\", \"Camera name\",\n> +\t\t\t\t\t\t\t\"Name of the camera\", nullptr,\n> +\t\t\t\t\t\t\t(GParamFlags)(G_PARAM_READABLE\n> +\t\t\t\t\t\t\t\t      | G_PARAM_STATIC_STRINGS)),\n> +\t\t\t\t    (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));\n> +\tg_object_class_install_property(object_class, PROP_LIST_CAMERAS, spec);\n> +\n>  \tspec = g_param_spec_enum(\"auto-focus-mode\",\n>  \t\t\t\t \"Set auto-focus mode\",\n>  \t\t\t\t \"Available options: AfModeManual, \"\n> diff --git a/test/gstreamer/gstreamer_test.cpp b/test/gstreamer/gstreamer_test.cpp\n> index 6ad0c15c..7f3ccd2b 100644\n> --- a/test/gstreamer/gstreamer_test.cpp\n> +++ b/test/gstreamer/gstreamer_test.cpp\n> @@ -97,6 +97,9 @@ bool GstreamerTest::checkMinCameraStreamsAndSetCameraName(unsigned int numStream\n>  \t\tbreak;\n>  \t}\n>  \n> +\tfor (auto &camera : cm.cameras())\n> +\t\tcameraNames_.push_back(strdup(camera->id().c_str()));\n> +\n>  \tcm.stop();\n>  \n>  \treturn cameraFound;\n> @@ -112,6 +115,9 @@ GstreamerTest::~GstreamerTest()\n>  \n>  int GstreamerTest::createPipeline()\n>  {\n> +\tGValue cameras_list_array = G_VALUE_INIT;\n> +\tguint index, i;\n> +\n>  \tlibcameraSrc_ = gst_element_factory_make(\"libcamerasrc\", \"libcamera\");\n>  \tpipeline_ = gst_pipeline_new(\"test-pipeline\");\n>  \n> @@ -125,6 +131,30 @@ int GstreamerTest::createPipeline()\n>  \tg_object_set(libcameraSrc_, \"camera-name\", cameraName_.c_str(), NULL);\n>  \tg_object_ref_sink(libcameraSrc_);\n>  \n> +\tg_value_init(&cameras_list_array, GST_TYPE_ARRAY);\n> +\tg_object_get_property(G_OBJECT(libcameraSrc_), \"list-cameras\", &cameras_list_array);\n> +\tif (gst_value_array_get_size(&cameras_list_array) != cameraNames_.size()) {\n> +\t\tg_printerr(\"libcamerasrc 'list-cameras' properties count does not match.\\n\");\n> +\t\treturn TestFail;\n> +\t}\n> +\n> +\tfor (index = 0; index < cameraNames_.size(); index++) {\n> +\t\tbool matched = false;\n> +\n> +\t\tfor (i = 0; i < gst_value_array_get_size(&cameras_list_array); i++) {\n> +\t\t\tconst char *cam = g_value_get_string(gst_value_array_get_value(&cameras_list_array, i));\n> +\t\t\tif (strcmp(cam, cameraNames_[index]) == 0) {\n> +\t\t\t\tmatched = true;\n> +\t\t\t\tbreak;\n> +\t\t\t}\n> +\t\t}\n> +\n> +\t\tif (!matched) {\n> +\t\t\tg_printerr(\"Camera %s not found in 'list-cameras' property.\\n\", cameraNames_[index]);\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\t}\n> +\n>  \treturn TestPass;\n>  }\n>  \n> diff --git a/test/gstreamer/gstreamer_test.h b/test/gstreamer/gstreamer_test.h\n> index aa2261e2..5d61bc2a 100644\n> --- a/test/gstreamer/gstreamer_test.h\n> +++ b/test/gstreamer/gstreamer_test.h\n> @@ -9,6 +9,7 @@\n>  \n>  #include <iostream>\n>  #include <unistd.h>\n> +#include <vector>\n>  \n>  #include <gst/gst.h>\n>  \n> @@ -29,6 +30,7 @@ protected:\n>  \tGstElement *libcameraSrc_;\n>  \tint status_;\n>  \n> +\tstd::vector<const char *> cameraNames_;\n>  private:\n>  \tbool checkMinCameraStreamsAndSetCameraName(unsigned int numStreams);\n>  };","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 2A764BE175\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  3 Jul 2023 20:22:52 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 8A052628C0;\n\tMon,  3 Jul 2023 22:22:51 +0200 (CEST)","from madras.collabora.co.uk (madras.collabora.co.uk\n\t[46.235.227.172])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 38B3C628BB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  3 Jul 2023 22:22:50 +0200 (CEST)","from nicolas-tpx395.localdomain (unknown\n\t[IPv6:2606:6d00:10:88d9::7a9])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\tkey-exchange X25519 server-signature RSA-PSS (4096 bits)\n\tserver-digest SHA256)\n\t(No client certificate requested) (Authenticated sender: nicolas)\n\tby madras.collabora.co.uk (Postfix) with ESMTPSA id 74E256606F85;\n\tMon,  3 Jul 2023 21:22:49 +0100 (BST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1688415771;\n\tbh=PoUVYRuSsx0R8/w0M2db7irNiMu6zdKDv5GtOXLcHy0=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=wGeuenYaFOS+akHJ8/cKKyTgq2bYN76jW7jD9pzpUCGfN1OWukre15p8oCIwfgGtN\n\tkR9NTw9pmdW16VufV6l4+fh9AbmTNBYXsRB1fIN/m//5RQuumyP8uae6b4BgsDapjj\n\tUmCg074ka0xfwrxn06ZbKXRmw3E9tZP0tt8wrNWy4os8Ozsnyp2DGxJD9SbpKhb2Dl\n\tdhBGwye06B/lfm1WZE9AgV9AWpU4fXiqJu882l4HzhcVg/vEK04CicZ4CDqpLj2Q9U\n\tlCFTfg5ofOXYR02xMiDuoklcus/hRJ3P19+o2z0+Qye8h5ZVD13+dHCrleVNe6jwjk\n\tFCLw25BTgtSRQ==","v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com;\n\ts=mail; t=1688415769;\n\tbh=PoUVYRuSsx0R8/w0M2db7irNiMu6zdKDv5GtOXLcHy0=;\n\th=Subject:From:To:Cc:Date:In-Reply-To:References:From;\n\tb=ku8WTY1RfZ/cGNKV4FsDZDa1XTgCKvi9w334kMIr9yn/KNMhuE6aomwHBvjVo6C5L\n\t2BpKpECh8jFuXBuTya/2yEI9JXCdxjL0xU5X1lMSwaoCpgJyJTywMqdCZUfHgD8D24\n\t99ToFtv35VadeGtOJKUmOaOv7SgrAPDRiRoD/RTIDecHwD657iMWu0cVDJvZY+fxD/\n\t3GDO4r4cfkjWCEjhHmp+xTCzwu+dVlgMKMzImZYLkpsQAxmKcv4W2uEmoweUbDcMsh\n\t3Lg3yeAI5GkxJ8WAlqD318/b3CZcPdfxrclpDhHxlzWZvEIGG2g0zDaz+4nyhizjPf\n\t+a4Dodjr82VPw=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=collabora.com\n\theader.i=@collabora.com\n\theader.b=\"ku8WTY1R\"; dkim-atps=neutral","Message-ID":"<4925b314512f5983bdd5e48be5a6de3c95deaa7b.camel@collabora.com>","To":"Umang Jain <umang.jain@ideasonboard.com>, \n\tlibcamera-devel@lists.libcamera.org","Date":"Mon, 03 Jul 2023 16:22:41 -0400","In-Reply-To":"<20230703195725.193585-1-umang.jain@ideasonboard.com>","References":"<20230703195725.193585-1-umang.jain@ideasonboard.com>","Content-Type":"text/plain; charset=\"UTF-8\"","Content-Transfer-Encoding":"quoted-printable","User-Agent":"Evolution 3.48.3 (3.48.3-1.fc38) ","MIME-Version":"1.0","Subject":"Re: [libcamera-devel] [PATCH] gstreamer: Add 'list-cameras' property","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Nicolas Dufresne via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Nicolas Dufresne <nicolas.dufresne@collabora.com>","Cc":"vedantparanjape160201@gmail.com","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":27452,"web_url":"https://patchwork.libcamera.org/comment/27452/","msgid":"<168841603159.2869228.11048742824490501593@Monstersaurus>","date":"2023-07-03T20:27:11","subject":"Re: [libcamera-devel] [PATCH] gstreamer: Add 'list-cameras' property","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Umang Jain via libcamera-devel (2023-07-03 20:57:25)\n> Add a new property called 'list-cameras' on libcamerasrc to enumerate\n> and expose the cameras present on the system. The enumeration will help\n> appplications using libcamerasrc to know and set the 'camera-name'\n> property in order to use that camera with libcamerasrc.\n> \n\nHaving a way to list the available camera names sounds good - I don't\nknow if there is a better way to tie this into the gstreamer components.\n\nHow would you see this used?\n\nis it something like \n  'gst-launch gstlibcamerasrc list-cameras' ?\n\n\nShould this list be reported in gst-inspect or such ?\n\n--\nKieran\n\n\n> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>\n> ---\n>  src/gstreamer/gstlibcamerasrc.cpp | 46 +++++++++++++++++++++++++++++++\n>  test/gstreamer/gstreamer_test.cpp | 30 ++++++++++++++++++++\n>  test/gstreamer/gstreamer_test.h   |  2 ++\n>  3 files changed, 78 insertions(+)\n> \n> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\n> index 1f10136b..f337728a 100644\n> --- a/src/gstreamer/gstlibcamerasrc.cpp\n> +++ b/src/gstreamer/gstlibcamerasrc.cpp\n> @@ -152,6 +152,7 @@ struct _GstLibcameraSrc {\n>  enum {\n>         PROP_0,\n>         PROP_CAMERA_NAME,\n> +       PROP_LIST_CAMERAS,\n>         PROP_AUTO_FOCUS_MODE,\n>  };\n>  \n> @@ -666,6 +667,39 @@ gst_libcamera_src_close(GstLibcameraSrc *self)\n>         state->cm_.reset();\n>  }\n>  \n> +static gboolean\n> +gst_libcamera_src_set_cameras_list(GstLibcameraSrc *self, GValue *value)\n> +{\n> +       std::shared_ptr<CameraManager> cm;\n> +       GValue val = G_VALUE_INIT;\n> +       gint ret;\n> +\n> +       g_value_init(&val, G_TYPE_STRING);\n> +       g_value_reset(value);\n> +\n> +       cm = gst_libcamera_get_camera_manager(ret);\n> +       if (ret) {\n> +               GST_ELEMENT_ERROR(self, LIBRARY, INIT,\n> +                                 (\"Failed listing cameras.\"),\n> +                                 (\"libcamera::CameraMananger::start() failed: %s\", g_strerror(-ret)));\n> +               return false;\n> +       }\n> +\n> +       if (cm->cameras().empty()) {\n> +               GST_ELEMENT_ERROR(self, RESOURCE, NOT_FOUND,\n> +                                 (\"Could not find any supported camera on this system.\"),\n> +                                 (\"libcamera::CameraMananger::cameras() is empty\"));\n> +               return false;\n> +       }\n> +\n> +       for (const std::shared_ptr<Camera> &cam : cm->cameras()) {\n> +               g_value_set_string(&val, cam->id().c_str());\n> +               gst_value_array_append_value(value, &val);\n> +       }\n> +\n> +       return true;\n> +}\n> +\n>  static void\n>  gst_libcamera_src_set_property(GObject *object, guint prop_id,\n>                                const GValue *value, GParamSpec *pspec)\n> @@ -699,6 +733,9 @@ gst_libcamera_src_get_property(GObject *object, guint prop_id, GValue *value,\n>         case PROP_CAMERA_NAME:\n>                 g_value_set_string(value, self->camera_name);\n>                 break;\n> +       case PROP_LIST_CAMERAS:\n> +               gst_libcamera_src_set_cameras_list(self, value);\n> +               break;\n>         case PROP_AUTO_FOCUS_MODE: {\n>                 auto auto_focus_mode = self->controls->get(controls::AfMode).value_or(controls::AfModeManual);\n>                 g_value_set_enum(value, auto_focus_mode);\n> @@ -879,6 +916,15 @@ gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)\n>                                                              | G_PARAM_STATIC_STRINGS));\n>         g_object_class_install_property(object_class, PROP_CAMERA_NAME, spec);\n>  \n> +       spec = gst_param_spec_array(\"list-cameras\", \"Cameras list\",\n> +                                   \"Retrieve list of all cameras\",\n> +                                   g_param_spec_string(\"camera-name\", \"Camera name\",\n> +                                                       \"Name of the camera\", nullptr,\n> +                                                       (GParamFlags)(G_PARAM_READABLE\n> +                                                                     | G_PARAM_STATIC_STRINGS)),\n> +                                   (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));\n> +       g_object_class_install_property(object_class, PROP_LIST_CAMERAS, spec);\n> +\n>         spec = g_param_spec_enum(\"auto-focus-mode\",\n>                                  \"Set auto-focus mode\",\n>                                  \"Available options: AfModeManual, \"\n> diff --git a/test/gstreamer/gstreamer_test.cpp b/test/gstreamer/gstreamer_test.cpp\n> index 6ad0c15c..7f3ccd2b 100644\n> --- a/test/gstreamer/gstreamer_test.cpp\n> +++ b/test/gstreamer/gstreamer_test.cpp\n> @@ -97,6 +97,9 @@ bool GstreamerTest::checkMinCameraStreamsAndSetCameraName(unsigned int numStream\n>                 break;\n>         }\n>  \n> +       for (auto &camera : cm.cameras())\n> +               cameraNames_.push_back(strdup(camera->id().c_str()));\n> +\n>         cm.stop();\n>  \n>         return cameraFound;\n> @@ -112,6 +115,9 @@ GstreamerTest::~GstreamerTest()\n>  \n>  int GstreamerTest::createPipeline()\n>  {\n> +       GValue cameras_list_array = G_VALUE_INIT;\n> +       guint index, i;\n> +\n>         libcameraSrc_ = gst_element_factory_make(\"libcamerasrc\", \"libcamera\");\n>         pipeline_ = gst_pipeline_new(\"test-pipeline\");\n>  \n> @@ -125,6 +131,30 @@ int GstreamerTest::createPipeline()\n>         g_object_set(libcameraSrc_, \"camera-name\", cameraName_.c_str(), NULL);\n>         g_object_ref_sink(libcameraSrc_);\n>  \n> +       g_value_init(&cameras_list_array, GST_TYPE_ARRAY);\n> +       g_object_get_property(G_OBJECT(libcameraSrc_), \"list-cameras\", &cameras_list_array);\n> +       if (gst_value_array_get_size(&cameras_list_array) != cameraNames_.size()) {\n> +               g_printerr(\"libcamerasrc 'list-cameras' properties count does not match.\\n\");\n> +               return TestFail;\n> +       }\n> +\n> +       for (index = 0; index < cameraNames_.size(); index++) {\n> +               bool matched = false;\n> +\n> +               for (i = 0; i < gst_value_array_get_size(&cameras_list_array); i++) {\n> +                       const char *cam = g_value_get_string(gst_value_array_get_value(&cameras_list_array, i));\n> +                       if (strcmp(cam, cameraNames_[index]) == 0) {\n> +                               matched = true;\n> +                               break;\n> +                       }\n> +               }\n> +\n> +               if (!matched) {\n> +                       g_printerr(\"Camera %s not found in 'list-cameras' property.\\n\", cameraNames_[index]);\n> +                       return TestFail;\n> +               }\n> +       }\n> +\n>         return TestPass;\n>  }\n>  \n> diff --git a/test/gstreamer/gstreamer_test.h b/test/gstreamer/gstreamer_test.h\n> index aa2261e2..5d61bc2a 100644\n> --- a/test/gstreamer/gstreamer_test.h\n> +++ b/test/gstreamer/gstreamer_test.h\n> @@ -9,6 +9,7 @@\n>  \n>  #include <iostream>\n>  #include <unistd.h>\n> +#include <vector>\n>  \n>  #include <gst/gst.h>\n>  \n> @@ -29,6 +30,7 @@ protected:\n>         GstElement *libcameraSrc_;\n>         int status_;\n>  \n> +       std::vector<const char *> cameraNames_;\n>  private:\n>         bool checkMinCameraStreamsAndSetCameraName(unsigned int numStreams);\n>  };\n> -- \n> 2.39.1\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 053C2BDC71\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  3 Jul 2023 20:27:16 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 63844628BC;\n\tMon,  3 Jul 2023 22:27:16 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 72444628BB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  3 Jul 2023 22:27:14 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(aztw-30-b2-v4wan-166917-cust845.vm26.cable.virginm.net\n\t[82.37.23.78])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 72DC211A9;\n\tMon,  3 Jul 2023 22:26:30 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1688416036;\n\tbh=KKn3JbHcXoEG2aNhX4xDBgIYfaVC5+p4Kk2+n27Gp4Q=;\n\th=In-Reply-To:References:To:Date:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=qZN5sw7KMvgGAFGO9T8CfkohI+298DlNmB2xiIo9YtkiaV8X7SUyPNoxE9n+oSDEw\n\tQYl5RH3FP7nYFI1bzH13TzwHeXBRJxGPng9b4RUf137J4m9DloNUCZMbKNrz2dydud\n\tyyPDzqVST2sr0i+90h5H41fuaxXix96cd882NkKKbl7pJL3cqaq94V623Xeewd6f1p\n\t7JCkVIV1Y/hwK51yQ0CN09edBwxhI2g4+rp1DX/7qvk7vL5uYCNKxD3B1X4b89HDBs\n\t7cdmNBUGd6dr/CLUgs8o9qRVPHSm4gD8T+yNKW6peKTH7FtSSN57MGP6fOnQezGnGd\n\tuOPF6eOvNi5sA==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1688415990;\n\tbh=KKn3JbHcXoEG2aNhX4xDBgIYfaVC5+p4Kk2+n27Gp4Q=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=EviPRvxzb3j49vrYQmeoyB+kNFc9N8vGC7p1Ed7enz7Opo+pwL0rwWDxT2ZYWk/TY\n\tuMLKFX0gqZQoBwSZOGi0SDwKMTNghnUr0DY913LTIPNvr3a4MCLcHZr1fNWS6O7O8s\n\tCAcoXSwmySCeBR4HPSRGc54um6HUqo7af7Lr8ha8="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"EviPRvxz\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20230703195725.193585-1-umang.jain@ideasonboard.com>","References":"<20230703195725.193585-1-umang.jain@ideasonboard.com>","To":"Umang Jain <umang.jain@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Mon, 03 Jul 2023 21:27:11 +0100","Message-ID":"<168841603159.2869228.11048742824490501593@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH] gstreamer: Add 'list-cameras' property","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"nicolas.dufresne@collabora.com, vedantparanjape160201@gmail.com","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":27453,"web_url":"https://patchwork.libcamera.org/comment/27453/","msgid":"<9a3070085d289ee69a3c30ac152df584a2c02599.camel@collabora.com>","date":"2023-07-03T20:34:53","subject":"Re: [libcamera-devel] [PATCH] gstreamer: Add 'list-cameras' property","submitter":{"id":31,"url":"https://patchwork.libcamera.org/api/people/31/","name":"Nicolas Dufresne","email":"nicolas.dufresne@collabora.com"},"content":"Le lundi 03 juillet 2023 à 21:27 +0100, Kieran Bingham a écrit :\n> Quoting Umang Jain via libcamera-devel (2023-07-03 20:57:25)\n> > Add a new property called 'list-cameras' on libcamerasrc to enumerate\n> > and expose the cameras present on the system. The enumeration will help\n> > appplications using libcamerasrc to know and set the 'camera-name'\n> > property in order to use that camera with libcamerasrc.\n> > \n> \n> Having a way to list the available camera names sounds good - I don't\n> know if there is a better way to tie this into the gstreamer components.\n> \n> How would you see this used?\n> \n> is it something like \n>   'gst-launch gstlibcamerasrc list-cameras' ?\n> \n> \n> Should this list be reported in gst-inspect or such ?\n\nListing cameras should go through the device monitor, and implemented by\nlibcamera already with a device provider. We should add some human readable\nnames in the properties, here's what it currently look like. Note that the\nreturned device can be used in replacement for gst_element_factory_make() to get\na preconfigured libcamerasrc for the selected camera.\n\n$> GST_PLUGIN_PATH=build/src/gstreamer/ gst-device-monitor-1.0 Video/Source\nDevice found:\n\n\tname  : \\_SB_.PCI0.GP17.XHC0.RHUB.SS04-4.1:1.0-046d:0893\n\tclass : Source/Video\n\tcaps  : video/x-raw, format=NV12, width=640, height=360\n\t        video/x-raw, format=NV12, width=640, height=480\n\t        video/x-raw, format=NV12, width=1280, height=720\n\t        video/x-raw, format=NV12, width=1920, height=1080\n\t        image/jpeg, width=176, height=144\n\t        image/jpeg, width=320, height=240\n\t        image/jpeg, width=424, height=240\n\t        image/jpeg, width=640, height=360\n\t        image/jpeg, width=640, height=480\n\t        image/jpeg, width=848, height=480\n\t        image/jpeg, width=960, height=540\n\t        image/jpeg, width=1280, height=720\n\t        image/jpeg, width=1600, height=896\n\t        image/jpeg, width=1920, height=1080\n\t        video/x-raw, format=YUY2, width=176, height=144\n\t        video/x-raw, format=YUY2, width=320, height=240\n\t        video/x-raw, format=YUY2, width=424, height=240\n\t        video/x-raw, format=YUY2, width=640, height=360\n\t        video/x-raw, format=YUY2, width=640, height=480\n\t        video/x-raw, format=YUY2, width=848, height=480\n\t        video/x-raw, format=YUY2, width=960, height=540\n\t        video/x-raw, format=YUY2, width=1280, height=720\n\t        video/x-raw, format=YUY2, width=1600, height=896\n\t        video/x-raw, format=YUY2, width=1920, height=1080\n\t        video/x-raw, format=YUY2, width=2304, height=1296\n\tgst-launch-1.0 libcamerasrc camera-\nname=\"\\\\_SB_.PCI0.GP17.XHC0.RHUB.SS04-4.1:1.0-046d:0893\" ! ...\n\n\nDevice found:\n\n\tname  : \\_SB_.PCI0.GP17.XHC0.RHUB.SS04-4.2.3:1.0-2997:0004\n\tclass : Source/Video\n\tcaps  : video/x-raw, format=I420, width=640, height=480\n\t        video/x-raw, format=I420, width=720, height=480\n\t        video/x-raw, format=I420, width=720, height=576\n\t        video/x-raw, format=I420, width=800, height=600\n\t        video/x-raw, format=I420, width=1024, height=768\n\t        video/x-raw, format=I420, width=1280, height=720\n\t        video/x-raw, format=I420, width=1280, height=768\n\t        video/x-raw, format=I420, width=1280, height=800\n\t        video/x-raw, format=I420, width=1360, height=768\n\t        video/x-raw, format=I420, width=1280, height=960\n\t        video/x-raw, format=I420, width=1280, height=1024\n\t        video/x-raw, format=I420, width=1600, height=1200\n\t        video/x-raw, format=I420, width=1920, height=1080\n\t        video/x-raw, format=I420, width=1920, height=1200\n\t        video/x-raw, format=I420, width=2560, height=1440\n\t        video/x-raw, format=I420, width=3840, height=2160\n\t        video/x-raw, format=I420, width=4096, height=2160\n\t        video/x-raw, format=NV12, width=640, height=480\n\t        video/x-raw, format=NV12, width=720, height=480\n\t        video/x-raw, format=NV12, width=720, height=576\n\t        video/x-raw, format=NV12, width=800, height=600\n\t        video/x-raw, format=NV12, width=1024, height=768\n\t        video/x-raw, format=NV12, width=1280, height=720\n\t        video/x-raw, format=NV12, width=1280, height=768\n\t        video/x-raw, format=NV12, width=1280, height=800\n\t        video/x-raw, format=NV12, width=1360, height=768\n\t        video/x-raw, format=NV12, width=1280, height=960\n\t        video/x-raw, format=NV12, width=1280, height=1024\n\t        video/x-raw, format=NV12, width=1600, height=1200\n\t        video/x-raw, format=NV12, width=1920, height=1080\n\t        video/x-raw, format=NV12, width=1920, height=1200\n\t        video/x-raw, format=NV12, width=2560, height=1440\n\t        video/x-raw, format=NV12, width=3840, height=2160\n\t        video/x-raw, format=NV12, width=4096, height=2160\n\t        video/x-raw, format=YV12, width=640, height=480\n\t        video/x-raw, format=YV12, width=720, height=480\n\t        video/x-raw, format=YV12, width=720, height=576\n\t        video/x-raw, format=YV12, width=800, height=600\n\t        video/x-raw, format=YV12, width=1024, height=768\n\t        video/x-raw, format=YV12, width=1280, height=720\n\t        video/x-raw, format=YV12, width=1280, height=768\n\t        video/x-raw, format=YV12, width=1280, height=800\n\t        video/x-raw, format=YV12, width=1360, height=768\n\t        video/x-raw, format=YV12, width=1280, height=960\n\t        video/x-raw, format=YV12, width=1280, height=1024\n\t        video/x-raw, format=YV12, width=1600, height=1200\n\t        video/x-raw, format=YV12, width=1920, height=1080\n\t        video/x-raw, format=YV12, width=1920, height=1200\n\t        video/x-raw, format=YV12, width=2560, height=1440\n\t        video/x-raw, format=YV12, width=3840, height=2160\n\t        video/x-raw, format=YV12, width=4096, height=2160\n\t        video/x-raw, format=YUY2, width=640, height=480\n\t        video/x-raw, format=YUY2, width=720, height=480\n\t        video/x-raw, format=YUY2, width=720, height=576\n\t        video/x-raw, format=YUY2, width=800, height=600\n\t        video/x-raw, format=YUY2, width=1024, height=768\n\t        video/x-raw, format=YUY2, width=1280, height=720\n\t        video/x-raw, format=YUY2, width=1280, height=768\n\t        video/x-raw, format=YUY2, width=1280, height=800\n\t        video/x-raw, format=YUY2, width=1360, height=768\n\t        video/x-raw, format=YUY2, width=1280, height=960\n\t        video/x-raw, format=YUY2, width=1280, height=1024\n\t        video/x-raw, format=YUY2, width=1400, height=1050\n\t        video/x-raw, format=YUY2, width=1680, height=1050\n\t        video/x-raw, format=YUY2, width=1600, height=1200\n\t        video/x-raw, format=YUY2, width=1920, height=1080\n\t        video/x-raw, format=YUY2, width=1920, height=1200\n\tgst-launch-1.0 libcamerasrc camera-\nname=\"\\\\_SB_.PCI0.GP17.XHC0.RHUB.SS04-4.2.3:1.0-2997:0004\" ! ...\n\n\nDevice found:\n\n\tname  : \\_SB_.PCI0.GP17.XHC1.RHUB.PRT2.PR21-2.1:1.0-04ca:7070\n\tclass : Source/Video\n\tcaps  : image/jpeg, width=320, height=180\n\t        image/jpeg, width=320, height=240\n\t        image/jpeg, width=352, height=288\n\t        image/jpeg, width=424, height=240\n\t        image/jpeg, width=640, height=360\n\t        image/jpeg, width=640, height=480\n\t        image/jpeg, width=848, height=480\n\t        image/jpeg, width=960, height=540\n\t        image/jpeg, width=1280, height=720\n\t        video/x-raw, format=YUY2, width=320, height=180\n\t        video/x-raw, format=YUY2, width=320, height=240\n\t        video/x-raw, format=YUY2, width=352, height=288\n\t        video/x-raw, format=YUY2, width=424, height=240\n\t        video/x-raw, format=YUY2, width=640, height=360\n\t        video/x-raw, format=YUY2, width=640, height=480\n\t        video/x-raw, format=YUY2, width=848, height=480\n\t        video/x-raw, format=YUY2, width=960, height=540\n\t        video/x-raw, format=YUY2, width=1280, height=720\n\tgst-launch-1.0 libcamerasrc camera-\nname=\"\\\\_SB_.PCI0.GP17.XHC1.RHUB.PRT2.PR21-2.1:1.0-04ca:7070\" ! ...\n\n> \n> --\n> Kieran\n> \n> \n> > Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>\n> > ---\n> >  src/gstreamer/gstlibcamerasrc.cpp | 46 +++++++++++++++++++++++++++++++\n> >  test/gstreamer/gstreamer_test.cpp | 30 ++++++++++++++++++++\n> >  test/gstreamer/gstreamer_test.h   |  2 ++\n> >  3 files changed, 78 insertions(+)\n> > \n> > diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\n> > index 1f10136b..f337728a 100644\n> > --- a/src/gstreamer/gstlibcamerasrc.cpp\n> > +++ b/src/gstreamer/gstlibcamerasrc.cpp\n> > @@ -152,6 +152,7 @@ struct _GstLibcameraSrc {\n> >  enum {\n> >         PROP_0,\n> >         PROP_CAMERA_NAME,\n> > +       PROP_LIST_CAMERAS,\n> >         PROP_AUTO_FOCUS_MODE,\n> >  };\n> >  \n> > @@ -666,6 +667,39 @@ gst_libcamera_src_close(GstLibcameraSrc *self)\n> >         state->cm_.reset();\n> >  }\n> >  \n> > +static gboolean\n> > +gst_libcamera_src_set_cameras_list(GstLibcameraSrc *self, GValue *value)\n> > +{\n> > +       std::shared_ptr<CameraManager> cm;\n> > +       GValue val = G_VALUE_INIT;\n> > +       gint ret;\n> > +\n> > +       g_value_init(&val, G_TYPE_STRING);\n> > +       g_value_reset(value);\n> > +\n> > +       cm = gst_libcamera_get_camera_manager(ret);\n> > +       if (ret) {\n> > +               GST_ELEMENT_ERROR(self, LIBRARY, INIT,\n> > +                                 (\"Failed listing cameras.\"),\n> > +                                 (\"libcamera::CameraMananger::start() failed: %s\", g_strerror(-ret)));\n> > +               return false;\n> > +       }\n> > +\n> > +       if (cm->cameras().empty()) {\n> > +               GST_ELEMENT_ERROR(self, RESOURCE, NOT_FOUND,\n> > +                                 (\"Could not find any supported camera on this system.\"),\n> > +                                 (\"libcamera::CameraMananger::cameras() is empty\"));\n> > +               return false;\n> > +       }\n> > +\n> > +       for (const std::shared_ptr<Camera> &cam : cm->cameras()) {\n> > +               g_value_set_string(&val, cam->id().c_str());\n> > +               gst_value_array_append_value(value, &val);\n> > +       }\n> > +\n> > +       return true;\n> > +}\n> > +\n> >  static void\n> >  gst_libcamera_src_set_property(GObject *object, guint prop_id,\n> >                                const GValue *value, GParamSpec *pspec)\n> > @@ -699,6 +733,9 @@ gst_libcamera_src_get_property(GObject *object, guint prop_id, GValue *value,\n> >         case PROP_CAMERA_NAME:\n> >                 g_value_set_string(value, self->camera_name);\n> >                 break;\n> > +       case PROP_LIST_CAMERAS:\n> > +               gst_libcamera_src_set_cameras_list(self, value);\n> > +               break;\n> >         case PROP_AUTO_FOCUS_MODE: {\n> >                 auto auto_focus_mode = self->controls->get(controls::AfMode).value_or(controls::AfModeManual);\n> >                 g_value_set_enum(value, auto_focus_mode);\n> > @@ -879,6 +916,15 @@ gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)\n> >                                                              | G_PARAM_STATIC_STRINGS));\n> >         g_object_class_install_property(object_class, PROP_CAMERA_NAME, spec);\n> >  \n> > +       spec = gst_param_spec_array(\"list-cameras\", \"Cameras list\",\n> > +                                   \"Retrieve list of all cameras\",\n> > +                                   g_param_spec_string(\"camera-name\", \"Camera name\",\n> > +                                                       \"Name of the camera\", nullptr,\n> > +                                                       (GParamFlags)(G_PARAM_READABLE\n> > +                                                                     | G_PARAM_STATIC_STRINGS)),\n> > +                                   (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));\n> > +       g_object_class_install_property(object_class, PROP_LIST_CAMERAS, spec);\n> > +\n> >         spec = g_param_spec_enum(\"auto-focus-mode\",\n> >                                  \"Set auto-focus mode\",\n> >                                  \"Available options: AfModeManual, \"\n> > diff --git a/test/gstreamer/gstreamer_test.cpp b/test/gstreamer/gstreamer_test.cpp\n> > index 6ad0c15c..7f3ccd2b 100644\n> > --- a/test/gstreamer/gstreamer_test.cpp\n> > +++ b/test/gstreamer/gstreamer_test.cpp\n> > @@ -97,6 +97,9 @@ bool GstreamerTest::checkMinCameraStreamsAndSetCameraName(unsigned int numStream\n> >                 break;\n> >         }\n> >  \n> > +       for (auto &camera : cm.cameras())\n> > +               cameraNames_.push_back(strdup(camera->id().c_str()));\n> > +\n> >         cm.stop();\n> >  \n> >         return cameraFound;\n> > @@ -112,6 +115,9 @@ GstreamerTest::~GstreamerTest()\n> >  \n> >  int GstreamerTest::createPipeline()\n> >  {\n> > +       GValue cameras_list_array = G_VALUE_INIT;\n> > +       guint index, i;\n> > +\n> >         libcameraSrc_ = gst_element_factory_make(\"libcamerasrc\", \"libcamera\");\n> >         pipeline_ = gst_pipeline_new(\"test-pipeline\");\n> >  \n> > @@ -125,6 +131,30 @@ int GstreamerTest::createPipeline()\n> >         g_object_set(libcameraSrc_, \"camera-name\", cameraName_.c_str(), NULL);\n> >         g_object_ref_sink(libcameraSrc_);\n> >  \n> > +       g_value_init(&cameras_list_array, GST_TYPE_ARRAY);\n> > +       g_object_get_property(G_OBJECT(libcameraSrc_), \"list-cameras\", &cameras_list_array);\n> > +       if (gst_value_array_get_size(&cameras_list_array) != cameraNames_.size()) {\n> > +               g_printerr(\"libcamerasrc 'list-cameras' properties count does not match.\\n\");\n> > +               return TestFail;\n> > +       }\n> > +\n> > +       for (index = 0; index < cameraNames_.size(); index++) {\n> > +               bool matched = false;\n> > +\n> > +               for (i = 0; i < gst_value_array_get_size(&cameras_list_array); i++) {\n> > +                       const char *cam = g_value_get_string(gst_value_array_get_value(&cameras_list_array, i));\n> > +                       if (strcmp(cam, cameraNames_[index]) == 0) {\n> > +                               matched = true;\n> > +                               break;\n> > +                       }\n> > +               }\n> > +\n> > +               if (!matched) {\n> > +                       g_printerr(\"Camera %s not found in 'list-cameras' property.\\n\", cameraNames_[index]);\n> > +                       return TestFail;\n> > +               }\n> > +       }\n> > +\n> >         return TestPass;\n> >  }\n> >  \n> > diff --git a/test/gstreamer/gstreamer_test.h b/test/gstreamer/gstreamer_test.h\n> > index aa2261e2..5d61bc2a 100644\n> > --- a/test/gstreamer/gstreamer_test.h\n> > +++ b/test/gstreamer/gstreamer_test.h\n> > @@ -9,6 +9,7 @@\n> >  \n> >  #include <iostream>\n> >  #include <unistd.h>\n> > +#include <vector>\n> >  \n> >  #include <gst/gst.h>\n> >  \n> > @@ -29,6 +30,7 @@ protected:\n> >         GstElement *libcameraSrc_;\n> >         int status_;\n> >  \n> > +       std::vector<const char *> cameraNames_;\n> >  private:\n> >         bool checkMinCameraStreamsAndSetCameraName(unsigned int numStreams);\n> >  };\n> > -- \n> > 2.39.1\n> >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 17399BE175\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  3 Jul 2023 20:35:04 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 73703628BE;\n\tMon,  3 Jul 2023 22:35:03 +0200 (CEST)","from madras.collabora.co.uk (madras.collabora.co.uk\n\t[46.235.227.172])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B9E7E628BC\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  3 Jul 2023 22:35:01 +0200 (CEST)","from nicolas-tpx395.localdomain (unknown\n\t[IPv6:2606:6d00:10:88d9::7a9])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\tkey-exchange X25519 server-signature RSA-PSS (4096 bits)\n\tserver-digest SHA256)\n\t(No client certificate requested) (Authenticated sender: nicolas)\n\tby madras.collabora.co.uk (Postfix) with ESMTPSA id EAD746606F85;\n\tMon,  3 Jul 2023 21:35:00 +0100 (BST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1688416503;\n\tbh=4j+WZbVXJf9lz8qxv6mL9IzPcsL8xXxF/Pmf9K8+VjY=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=ru+QOJpLClHRP9gb9nx7QLb79fEfulLWTdn45qgW9EKDZnWLMox1LZ65bWvWwdXvy\n\t+vUX8Sqyzt/gA7Ke7tNCuWVY/RBXYE8cDgjltPxE4+C1XMyh1iyo69U5DEAHVoqR9U\n\tjUwHyXtWXjyJ6mEAJQBn7V31OJIboURF7K5hnlOwQHw5XAgKIZyHTcjXepx2C0QJmP\n\tM/uGjIKuY+uovYj1HvBmY/U7g6HwlcfdDXr03IqJQDK56GLGN4XaV1a8nlE66H4yZr\n\tIIZlgSqkQfTlOh/AjuLKjrsk81zndvFln3y8YjWpnok/9sPzN2ihRUFo3TegF20PqN\n\tpf+2Tawznx74g==","v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com;\n\ts=mail; t=1688416501;\n\tbh=4j+WZbVXJf9lz8qxv6mL9IzPcsL8xXxF/Pmf9K8+VjY=;\n\th=Subject:From:To:Cc:Date:In-Reply-To:References:From;\n\tb=ANzlMT5qwC2Yt/8MGZOsQuvTzs2gdf7wrj620v9yJvAdBLXAG77p1fWHQqUwmpRDs\n\tr0/x5cFIDmNR0dP7/bk1jexWBO0qxOJEkGNFITfb4hvUyz7vudXabsf4HyYuD3vGLZ\n\t2W8LkeZER8B0Wf8PQz+ivwxQxTwpPM6hlhAX5mPPLS2XeCZ50t0tkXCL9HTnkkaCf9\n\to1QjdIu7XuH+ybivP7RKdXN4X9ZlDe9hrJO6vXDhYdCU7BM5iCOdfJYLjbtxgYaN2b\n\t3eDlfUE3mVC8sCAzD6WNDBMZCyKLXl2G3VHR7M7I0TwFb4ggukLDWz+2IbaV3sk5Sy\n\tW47wcLn3AvTxQ=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=collabora.com\n\theader.i=@collabora.com\n\theader.b=\"ANzlMT5q\"; dkim-atps=neutral","Message-ID":"<9a3070085d289ee69a3c30ac152df584a2c02599.camel@collabora.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>, Umang Jain\n\t<umang.jain@ideasonboard.com>, libcamera-devel@lists.libcamera.org","Date":"Mon, 03 Jul 2023 16:34:53 -0400","In-Reply-To":"<168841603159.2869228.11048742824490501593@Monstersaurus>","References":"<20230703195725.193585-1-umang.jain@ideasonboard.com>\n\t<168841603159.2869228.11048742824490501593@Monstersaurus>","Content-Type":"text/plain; charset=\"UTF-8\"","Content-Transfer-Encoding":"quoted-printable","User-Agent":"Evolution 3.48.3 (3.48.3-1.fc38) ","MIME-Version":"1.0","Subject":"Re: [libcamera-devel] [PATCH] gstreamer: Add 'list-cameras' property","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Nicolas Dufresne via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Nicolas Dufresne <nicolas.dufresne@collabora.com>","Cc":"vedantparanjape160201@gmail.com","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":27454,"web_url":"https://patchwork.libcamera.org/comment/27454/","msgid":"<383078b0-1b5b-b872-e9de-1ceadfe1239f@ideasonboard.com>","date":"2023-07-04T06:31:59","subject":"Re: [libcamera-devel] [PATCH] gstreamer: Add 'list-cameras' property","submitter":{"id":86,"url":"https://patchwork.libcamera.org/api/people/86/","name":"Umang Jain","email":"umang.jain@ideasonboard.com"},"content":"Hi Nicolas\n\nOn 7/3/23 10:22 PM, Nicolas Dufresne wrote:\n> Hi Ujain,\n>\n> Le lundi 03 juillet 2023 à 21:57 +0200, Umang Jain a écrit :\n>> Add a new property called 'list-cameras' on libcamerasrc to enumerate\n>> and expose the cameras present on the system. The enumeration will help\n>> appplications using libcamerasrc to know and set the 'camera-name'\n>> property in order to use that camera with libcamerasrc.\n>>\n>> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>\n> I'm sorry, but I have to reject this. This is the job of the device provider. If\n> some information is missing in the provider, just add it there.\n\nMakes sense. I'll try writing a test to enumerate cameras on the device \nprovider and using a pre-configured libcamerasrc.\n\nFor the missing information, does the camera-supported controls be a \ngood candidate to get added to device-provider as well?  I see we are \nalready enumerating streams in there but I understand those are part of \nthe capabilities.\n>\n> NAK\n>\n>> ---\n>>   src/gstreamer/gstlibcamerasrc.cpp | 46 +++++++++++++++++++++++++++++++\n>>   test/gstreamer/gstreamer_test.cpp | 30 ++++++++++++++++++++\n>>   test/gstreamer/gstreamer_test.h   |  2 ++\n>>   3 files changed, 78 insertions(+)\n>>\n>> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\n>> index 1f10136b..f337728a 100644\n>> --- a/src/gstreamer/gstlibcamerasrc.cpp\n>> +++ b/src/gstreamer/gstlibcamerasrc.cpp\n>> @@ -152,6 +152,7 @@ struct _GstLibcameraSrc {\n>>   enum {\n>>   \tPROP_0,\n>>   \tPROP_CAMERA_NAME,\n>> +\tPROP_LIST_CAMERAS,\n>>   \tPROP_AUTO_FOCUS_MODE,\n>>   };\n>>   \n>> @@ -666,6 +667,39 @@ gst_libcamera_src_close(GstLibcameraSrc *self)\n>>   \tstate->cm_.reset();\n>>   }\n>>   \n>> +static gboolean\n>> +gst_libcamera_src_set_cameras_list(GstLibcameraSrc *self, GValue *value)\n>> +{\n>> +\tstd::shared_ptr<CameraManager> cm;\n>> +\tGValue val = G_VALUE_INIT;\n>> +\tgint ret;\n>> +\n>> +\tg_value_init(&val, G_TYPE_STRING);\n>> +\tg_value_reset(value);\n>> +\n>> +\tcm = gst_libcamera_get_camera_manager(ret);\n>> +\tif (ret) {\n>> +\t\tGST_ELEMENT_ERROR(self, LIBRARY, INIT,\n>> +\t\t\t\t  (\"Failed listing cameras.\"),\n>> +\t\t\t\t  (\"libcamera::CameraMananger::start() failed: %s\", g_strerror(-ret)));\n>> +\t\treturn false;\n>> +\t}\n>> +\n>> +\tif (cm->cameras().empty()) {\n>> +\t\tGST_ELEMENT_ERROR(self, RESOURCE, NOT_FOUND,\n>> +\t\t\t\t  (\"Could not find any supported camera on this system.\"),\n>> +\t\t\t\t  (\"libcamera::CameraMananger::cameras() is empty\"));\n>> +\t\treturn false;\n>> +\t}\n>> +\n>> +\tfor (const std::shared_ptr<Camera> &cam : cm->cameras()) {\n>> +\t\tg_value_set_string(&val, cam->id().c_str());\n>> +\t\tgst_value_array_append_value(value, &val);\n>> +\t}\n>> +\n>> +\treturn true;\n>> +}\n>> +\n>>   static void\n>>   gst_libcamera_src_set_property(GObject *object, guint prop_id,\n>>   \t\t\t       const GValue *value, GParamSpec *pspec)\n>> @@ -699,6 +733,9 @@ gst_libcamera_src_get_property(GObject *object, guint prop_id, GValue *value,\n>>   \tcase PROP_CAMERA_NAME:\n>>   \t\tg_value_set_string(value, self->camera_name);\n>>   \t\tbreak;\n>> +\tcase PROP_LIST_CAMERAS:\n>> +\t\tgst_libcamera_src_set_cameras_list(self, value);\n>> +\t\tbreak;\n>>   \tcase PROP_AUTO_FOCUS_MODE: {\n>>   \t\tauto auto_focus_mode = self->controls->get(controls::AfMode).value_or(controls::AfModeManual);\n>>   \t\tg_value_set_enum(value, auto_focus_mode);\n>> @@ -879,6 +916,15 @@ gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)\n>>   \t\t\t\t\t\t\t     | G_PARAM_STATIC_STRINGS));\n>>   \tg_object_class_install_property(object_class, PROP_CAMERA_NAME, spec);\n>>   \n>> +\tspec = gst_param_spec_array(\"list-cameras\", \"Cameras list\",\n>> +\t\t\t\t    \"Retrieve list of all cameras\",\n>> +\t\t\t\t    g_param_spec_string(\"camera-name\", \"Camera name\",\n>> +\t\t\t\t\t\t\t\"Name of the camera\", nullptr,\n>> +\t\t\t\t\t\t\t(GParamFlags)(G_PARAM_READABLE\n>> +\t\t\t\t\t\t\t\t      | G_PARAM_STATIC_STRINGS)),\n>> +\t\t\t\t    (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));\n>> +\tg_object_class_install_property(object_class, PROP_LIST_CAMERAS, spec);\n>> +\n>>   \tspec = g_param_spec_enum(\"auto-focus-mode\",\n>>   \t\t\t\t \"Set auto-focus mode\",\n>>   \t\t\t\t \"Available options: AfModeManual, \"\n>> diff --git a/test/gstreamer/gstreamer_test.cpp b/test/gstreamer/gstreamer_test.cpp\n>> index 6ad0c15c..7f3ccd2b 100644\n>> --- a/test/gstreamer/gstreamer_test.cpp\n>> +++ b/test/gstreamer/gstreamer_test.cpp\n>> @@ -97,6 +97,9 @@ bool GstreamerTest::checkMinCameraStreamsAndSetCameraName(unsigned int numStream\n>>   \t\tbreak;\n>>   \t}\n>>   \n>> +\tfor (auto &camera : cm.cameras())\n>> +\t\tcameraNames_.push_back(strdup(camera->id().c_str()));\n>> +\n>>   \tcm.stop();\n>>   \n>>   \treturn cameraFound;\n>> @@ -112,6 +115,9 @@ GstreamerTest::~GstreamerTest()\n>>   \n>>   int GstreamerTest::createPipeline()\n>>   {\n>> +\tGValue cameras_list_array = G_VALUE_INIT;\n>> +\tguint index, i;\n>> +\n>>   \tlibcameraSrc_ = gst_element_factory_make(\"libcamerasrc\", \"libcamera\");\n>>   \tpipeline_ = gst_pipeline_new(\"test-pipeline\");\n>>   \n>> @@ -125,6 +131,30 @@ int GstreamerTest::createPipeline()\n>>   \tg_object_set(libcameraSrc_, \"camera-name\", cameraName_.c_str(), NULL);\n>>   \tg_object_ref_sink(libcameraSrc_);\n>>   \n>> +\tg_value_init(&cameras_list_array, GST_TYPE_ARRAY);\n>> +\tg_object_get_property(G_OBJECT(libcameraSrc_), \"list-cameras\", &cameras_list_array);\n>> +\tif (gst_value_array_get_size(&cameras_list_array) != cameraNames_.size()) {\n>> +\t\tg_printerr(\"libcamerasrc 'list-cameras' properties count does not match.\\n\");\n>> +\t\treturn TestFail;\n>> +\t}\n>> +\n>> +\tfor (index = 0; index < cameraNames_.size(); index++) {\n>> +\t\tbool matched = false;\n>> +\n>> +\t\tfor (i = 0; i < gst_value_array_get_size(&cameras_list_array); i++) {\n>> +\t\t\tconst char *cam = g_value_get_string(gst_value_array_get_value(&cameras_list_array, i));\n>> +\t\t\tif (strcmp(cam, cameraNames_[index]) == 0) {\n>> +\t\t\t\tmatched = true;\n>> +\t\t\t\tbreak;\n>> +\t\t\t}\n>> +\t\t}\n>> +\n>> +\t\tif (!matched) {\n>> +\t\t\tg_printerr(\"Camera %s not found in 'list-cameras' property.\\n\", cameraNames_[index]);\n>> +\t\t\treturn TestFail;\n>> +\t\t}\n>> +\t}\n>> +\n>>   \treturn TestPass;\n>>   }\n>>   \n>> diff --git a/test/gstreamer/gstreamer_test.h b/test/gstreamer/gstreamer_test.h\n>> index aa2261e2..5d61bc2a 100644\n>> --- a/test/gstreamer/gstreamer_test.h\n>> +++ b/test/gstreamer/gstreamer_test.h\n>> @@ -9,6 +9,7 @@\n>>   \n>>   #include <iostream>\n>>   #include <unistd.h>\n>> +#include <vector>\n>>   \n>>   #include <gst/gst.h>\n>>   \n>> @@ -29,6 +30,7 @@ protected:\n>>   \tGstElement *libcameraSrc_;\n>>   \tint status_;\n>>   \n>> +\tstd::vector<const char *> cameraNames_;\n>>   private:\n>>   \tbool checkMinCameraStreamsAndSetCameraName(unsigned int numStreams);\n>>   };","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id AD12DBE175\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue,  4 Jul 2023 06:32:05 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id C8D4C61E31;\n\tTue,  4 Jul 2023 08:32:04 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 52CA661E31\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  4 Jul 2023 08:32:03 +0200 (CEST)","from [192.168.0.136] (85-160-42-71.reb.o2.cz [85.160.42.71])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 14D5B4A9;\n\tTue,  4 Jul 2023 08:31:19 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1688452324;\n\tbh=QTAYSSEibPC7GWgDCt8JIC3HcL/DZcXQ54CSdLs56HE=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=XNxHJ6Z+fwxLgeI6Bu+hn8ZJpr0dMMwOwvhI8ArFJNpmSa1BNacQ5cmuv7UtN/cxO\n\t9ur9Se0QEJgCptbJuO6cD72JpXbuSyNTEiwGgqZXrOGoUZuJHGZ4Lif1izLfHjsOBZ\n\tNAYvn/NFSdSOHuUbpIfangHkGNUExy/2WRux8S8RE7XbqVbSrbJApfx8TEblGAVnBQ\n\tPJf2oaB9F1C2MR/wA3VjmA4wqgnyAL4FDZefvoPa1rr0f5wn6Qe1T4mBIeENuIHbFM\n\t1Z1ldGUYSo9qmz2rkm1Oaq/etebVM8kUvTBzOHchLmlYyOuzPBgYeQa2I2oA1CFCML\n\tSA7wmSYTOCRmA==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1688452279;\n\tbh=QTAYSSEibPC7GWgDCt8JIC3HcL/DZcXQ54CSdLs56HE=;\n\th=Date:Subject:To:Cc:References:From:In-Reply-To:From;\n\tb=iQGWf2FWR91Mq1pCHKZvpU6FjVk6Uupl2Qy2HWpdUxmfj8pIQi6+MpkJ0y+SCXKk0\n\thUZEMCiLhL6+WUpYGfK+2SWZVfNfSMEpd4jOcJtoriZ79Aj0DWxssQ3gOi7QQGBX/q\n\tpyR8eoG9Qk1yNo/U5354BodWnP1TQYevbHbr4BJs="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"iQGWf2FW\"; dkim-atps=neutral","Message-ID":"<383078b0-1b5b-b872-e9de-1ceadfe1239f@ideasonboard.com>","Date":"Tue, 4 Jul 2023 08:31:59 +0200","MIME-Version":"1.0","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101\n\tThunderbird/102.7.1","To":"Nicolas Dufresne <nicolas.dufresne@collabora.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20230703195725.193585-1-umang.jain@ideasonboard.com>\n\t<4925b314512f5983bdd5e48be5a6de3c95deaa7b.camel@collabora.com>","Content-Language":"en-US","In-Reply-To":"<4925b314512f5983bdd5e48be5a6de3c95deaa7b.camel@collabora.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","Subject":"Re: [libcamera-devel] [PATCH] gstreamer: Add 'list-cameras' property","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Umang Jain via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Umang Jain <umang.jain@ideasonboard.com>","Cc":"vedantparanjape160201@gmail.com","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":27462,"web_url":"https://patchwork.libcamera.org/comment/27462/","msgid":"<93e5b8c963fa329a97c56f674787d4b27c8c0b72.camel@collabora.com>","date":"2023-07-04T15:14:07","subject":"Re: [libcamera-devel] [PATCH] gstreamer: Add 'list-cameras' property","submitter":{"id":31,"url":"https://patchwork.libcamera.org/api/people/31/","name":"Nicolas Dufresne","email":"nicolas.dufresne@collabora.com"},"content":"Le mardi 04 juillet 2023 à 08:31 +0200, Umang Jain a écrit :\n> Hi Nicolas\n> \n> On 7/3/23 10:22 PM, Nicolas Dufresne wrote:\n> > Hi Ujain,\n> > \n> > Le lundi 03 juillet 2023 à 21:57 +0200, Umang Jain a écrit :\n> > > Add a new property called 'list-cameras' on libcamerasrc to enumerate\n> > > and expose the cameras present on the system. The enumeration will help\n> > > appplications using libcamerasrc to know and set the 'camera-name'\n> > > property in order to use that camera with libcamerasrc.\n> > > \n> > > Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>\n> > I'm sorry, but I have to reject this. This is the job of the device provider. If\n> > some information is missing in the provider, just add it there.\n> \n> Makes sense. I'll try writing a test to enumerate cameras on the device \n> provider and using a pre-configured libcamerasrc.\n> \n> For the missing information, does the camera-supported controls be a \n> good candidate to get added to device-provider as well?  I see we are \n> already enumerating streams in there but I understand those are part of \n> the capabilities.\n\nAs discussed on IRC, I'd aim maybe for a set of supported features. We can\nprobably simply use G_TYPE_FLAGS property (shared on both the provided and the\nlibcamerasrc). Each flag would state which features are to be expected, and the\ndoc will say for each flags which controls are going to exist, or which \"mode\"\nif a feature (like auto-focus) can support multiple mode which imply different\nset of controls.\n\nThe idea is that libcamera controls don't match 1:1 to features, but some\ncontrols works in tandem, e.g. if you didn't select a specific \"mode\" a specific\ncontrol may have no effect.\n\n> > \n> > NAK\n> > \n> > > ---\n> > >   src/gstreamer/gstlibcamerasrc.cpp | 46 +++++++++++++++++++++++++++++++\n> > >   test/gstreamer/gstreamer_test.cpp | 30 ++++++++++++++++++++\n> > >   test/gstreamer/gstreamer_test.h   |  2 ++\n> > >   3 files changed, 78 insertions(+)\n> > > \n> > > diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\n> > > index 1f10136b..f337728a 100644\n> > > --- a/src/gstreamer/gstlibcamerasrc.cpp\n> > > +++ b/src/gstreamer/gstlibcamerasrc.cpp\n> > > @@ -152,6 +152,7 @@ struct _GstLibcameraSrc {\n> > >   enum {\n> > >   \tPROP_0,\n> > >   \tPROP_CAMERA_NAME,\n> > > +\tPROP_LIST_CAMERAS,\n> > >   \tPROP_AUTO_FOCUS_MODE,\n> > >   };\n> > >   \n> > > @@ -666,6 +667,39 @@ gst_libcamera_src_close(GstLibcameraSrc *self)\n> > >   \tstate->cm_.reset();\n> > >   }\n> > >   \n> > > +static gboolean\n> > > +gst_libcamera_src_set_cameras_list(GstLibcameraSrc *self, GValue *value)\n> > > +{\n> > > +\tstd::shared_ptr<CameraManager> cm;\n> > > +\tGValue val = G_VALUE_INIT;\n> > > +\tgint ret;\n> > > +\n> > > +\tg_value_init(&val, G_TYPE_STRING);\n> > > +\tg_value_reset(value);\n> > > +\n> > > +\tcm = gst_libcamera_get_camera_manager(ret);\n> > > +\tif (ret) {\n> > > +\t\tGST_ELEMENT_ERROR(self, LIBRARY, INIT,\n> > > +\t\t\t\t  (\"Failed listing cameras.\"),\n> > > +\t\t\t\t  (\"libcamera::CameraMananger::start() failed: %s\", g_strerror(-ret)));\n> > > +\t\treturn false;\n> > > +\t}\n> > > +\n> > > +\tif (cm->cameras().empty()) {\n> > > +\t\tGST_ELEMENT_ERROR(self, RESOURCE, NOT_FOUND,\n> > > +\t\t\t\t  (\"Could not find any supported camera on this system.\"),\n> > > +\t\t\t\t  (\"libcamera::CameraMananger::cameras() is empty\"));\n> > > +\t\treturn false;\n> > > +\t}\n> > > +\n> > > +\tfor (const std::shared_ptr<Camera> &cam : cm->cameras()) {\n> > > +\t\tg_value_set_string(&val, cam->id().c_str());\n> > > +\t\tgst_value_array_append_value(value, &val);\n> > > +\t}\n> > > +\n> > > +\treturn true;\n> > > +}\n> > > +\n> > >   static void\n> > >   gst_libcamera_src_set_property(GObject *object, guint prop_id,\n> > >   \t\t\t       const GValue *value, GParamSpec *pspec)\n> > > @@ -699,6 +733,9 @@ gst_libcamera_src_get_property(GObject *object, guint prop_id, GValue *value,\n> > >   \tcase PROP_CAMERA_NAME:\n> > >   \t\tg_value_set_string(value, self->camera_name);\n> > >   \t\tbreak;\n> > > +\tcase PROP_LIST_CAMERAS:\n> > > +\t\tgst_libcamera_src_set_cameras_list(self, value);\n> > > +\t\tbreak;\n> > >   \tcase PROP_AUTO_FOCUS_MODE: {\n> > >   \t\tauto auto_focus_mode = self->controls->get(controls::AfMode).value_or(controls::AfModeManual);\n> > >   \t\tg_value_set_enum(value, auto_focus_mode);\n> > > @@ -879,6 +916,15 @@ gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)\n> > >   \t\t\t\t\t\t\t     | G_PARAM_STATIC_STRINGS));\n> > >   \tg_object_class_install_property(object_class, PROP_CAMERA_NAME, spec);\n> > >   \n> > > +\tspec = gst_param_spec_array(\"list-cameras\", \"Cameras list\",\n> > > +\t\t\t\t    \"Retrieve list of all cameras\",\n> > > +\t\t\t\t    g_param_spec_string(\"camera-name\", \"Camera name\",\n> > > +\t\t\t\t\t\t\t\"Name of the camera\", nullptr,\n> > > +\t\t\t\t\t\t\t(GParamFlags)(G_PARAM_READABLE\n> > > +\t\t\t\t\t\t\t\t      | G_PARAM_STATIC_STRINGS)),\n> > > +\t\t\t\t    (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));\n> > > +\tg_object_class_install_property(object_class, PROP_LIST_CAMERAS, spec);\n> > > +\n> > >   \tspec = g_param_spec_enum(\"auto-focus-mode\",\n> > >   \t\t\t\t \"Set auto-focus mode\",\n> > >   \t\t\t\t \"Available options: AfModeManual, \"\n> > > diff --git a/test/gstreamer/gstreamer_test.cpp b/test/gstreamer/gstreamer_test.cpp\n> > > index 6ad0c15c..7f3ccd2b 100644\n> > > --- a/test/gstreamer/gstreamer_test.cpp\n> > > +++ b/test/gstreamer/gstreamer_test.cpp\n> > > @@ -97,6 +97,9 @@ bool GstreamerTest::checkMinCameraStreamsAndSetCameraName(unsigned int numStream\n> > >   \t\tbreak;\n> > >   \t}\n> > >   \n> > > +\tfor (auto &camera : cm.cameras())\n> > > +\t\tcameraNames_.push_back(strdup(camera->id().c_str()));\n> > > +\n> > >   \tcm.stop();\n> > >   \n> > >   \treturn cameraFound;\n> > > @@ -112,6 +115,9 @@ GstreamerTest::~GstreamerTest()\n> > >   \n> > >   int GstreamerTest::createPipeline()\n> > >   {\n> > > +\tGValue cameras_list_array = G_VALUE_INIT;\n> > > +\tguint index, i;\n> > > +\n> > >   \tlibcameraSrc_ = gst_element_factory_make(\"libcamerasrc\", \"libcamera\");\n> > >   \tpipeline_ = gst_pipeline_new(\"test-pipeline\");\n> > >   \n> > > @@ -125,6 +131,30 @@ int GstreamerTest::createPipeline()\n> > >   \tg_object_set(libcameraSrc_, \"camera-name\", cameraName_.c_str(), NULL);\n> > >   \tg_object_ref_sink(libcameraSrc_);\n> > >   \n> > > +\tg_value_init(&cameras_list_array, GST_TYPE_ARRAY);\n> > > +\tg_object_get_property(G_OBJECT(libcameraSrc_), \"list-cameras\", &cameras_list_array);\n> > > +\tif (gst_value_array_get_size(&cameras_list_array) != cameraNames_.size()) {\n> > > +\t\tg_printerr(\"libcamerasrc 'list-cameras' properties count does not match.\\n\");\n> > > +\t\treturn TestFail;\n> > > +\t}\n> > > +\n> > > +\tfor (index = 0; index < cameraNames_.size(); index++) {\n> > > +\t\tbool matched = false;\n> > > +\n> > > +\t\tfor (i = 0; i < gst_value_array_get_size(&cameras_list_array); i++) {\n> > > +\t\t\tconst char *cam = g_value_get_string(gst_value_array_get_value(&cameras_list_array, i));\n> > > +\t\t\tif (strcmp(cam, cameraNames_[index]) == 0) {\n> > > +\t\t\t\tmatched = true;\n> > > +\t\t\t\tbreak;\n> > > +\t\t\t}\n> > > +\t\t}\n> > > +\n> > > +\t\tif (!matched) {\n> > > +\t\t\tg_printerr(\"Camera %s not found in 'list-cameras' property.\\n\", cameraNames_[index]);\n> > > +\t\t\treturn TestFail;\n> > > +\t\t}\n> > > +\t}\n> > > +\n> > >   \treturn TestPass;\n> > >   }\n> > >   \n> > > diff --git a/test/gstreamer/gstreamer_test.h b/test/gstreamer/gstreamer_test.h\n> > > index aa2261e2..5d61bc2a 100644\n> > > --- a/test/gstreamer/gstreamer_test.h\n> > > +++ b/test/gstreamer/gstreamer_test.h\n> > > @@ -9,6 +9,7 @@\n> > >   \n> > >   #include <iostream>\n> > >   #include <unistd.h>\n> > > +#include <vector>\n> > >   \n> > >   #include <gst/gst.h>\n> > >   \n> > > @@ -29,6 +30,7 @@ protected:\n> > >   \tGstElement *libcameraSrc_;\n> > >   \tint status_;\n> > >   \n> > > +\tstd::vector<const char *> cameraNames_;\n> > >   private:\n> > >   \tbool checkMinCameraStreamsAndSetCameraName(unsigned int numStreams);\n> > >   };\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 9ED36BDC71\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue,  4 Jul 2023 15:14:18 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id EE76A61E38;\n\tTue,  4 Jul 2023 17:14:17 +0200 (CEST)","from madras.collabora.co.uk (madras.collabora.co.uk\n\t[IPv6:2a00:1098:0:82:1000:25:2eeb:e5ab])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 67C5C60384\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  4 Jul 2023 17:14:16 +0200 (CEST)","from nicolas-tpx395.localdomain (unknown\n\t[IPv6:2606:6d00:10:88d9::7a9])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\tkey-exchange X25519 server-signature RSA-PSS (4096 bits)\n\tserver-digest SHA256)\n\t(No client certificate requested) (Authenticated sender: nicolas)\n\tby madras.collabora.co.uk (Postfix) with ESMTPSA id A65716606F9C;\n\tTue,  4 Jul 2023 16:14:15 +0100 (BST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1688483657;\n\tbh=UZD6oIekfiiI6vZvPRGa7rifVgudLwIoEEJqoBjbOEk=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=eSgAB/IJ2fkQndDb3yE0vkHvH922gq5Q8fb59UV/BsUHSWFtUylGVGKqS3S1t0oWV\n\toOynaWiiV45OhA+oqq/JIadLhUDrZCvpCqFxSnb20LTSRpfu7ZYKG+KHRgl9feGwdH\n\tN2VJ3mnk3CTu44SaezL8H8lHi3pDpV1KjmoIz8sFYIkr+H5qUilcdygaOrCY0J2+84\n\tr5gOiV9NW+jAtcMDKRygjcoNhVff46Jh0vB6xjbYgUs6xuk74/Jl+oVbvrY8sbjxML\n\teWJvTs9cEL3Cq54DHrZJqSB5VtjD8UoigrB868nCdaFKwbUS6Z01B7v86JNmVcxOyA\n\t+cy1I18btim3g==","v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com;\n\ts=mail; t=1688483656;\n\tbh=UZD6oIekfiiI6vZvPRGa7rifVgudLwIoEEJqoBjbOEk=;\n\th=Subject:From:To:Cc:Date:In-Reply-To:References:From;\n\tb=KE1QM4oJelpRvQijbk6UzMHPuENZnz0s9QCeW/G4PlPsQRiiu257Mpn7b1QmFIkaT\n\tGY3SyDclnwtCccBlVfy/dcli27R6y7OfkTPGNhpd2L7mcxgXbWzfrWESxxk/LTP4A7\n\tQ7usXAagdvzn/8kSMkax9HLbf9qC0dy5bR6DMbpE8uwG/dFNP4YeDbjbFwTEU8H+uo\n\tv1FlRc/CSSgSOe9ok1Qi02yAEg5INQNoISuBH7vSbIveefermDH6ICFkK9gItNUefu\n\tHDBsABIDVcjM/fXjSIBTWhNIE2ujO8YgPgorlWIptIr6QpvcluYMDojLkCzfA/LZZ3\n\ttSp0BNFxGq97w=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=collabora.com\n\theader.i=@collabora.com\n\theader.b=\"KE1QM4oJ\"; dkim-atps=neutral","Message-ID":"<93e5b8c963fa329a97c56f674787d4b27c8c0b72.camel@collabora.com>","To":"Umang Jain <umang.jain@ideasonboard.com>, \n\tlibcamera-devel@lists.libcamera.org","Date":"Tue, 04 Jul 2023 11:14:07 -0400","In-Reply-To":"<383078b0-1b5b-b872-e9de-1ceadfe1239f@ideasonboard.com>","References":"<20230703195725.193585-1-umang.jain@ideasonboard.com>\n\t<4925b314512f5983bdd5e48be5a6de3c95deaa7b.camel@collabora.com>\n\t<383078b0-1b5b-b872-e9de-1ceadfe1239f@ideasonboard.com>","Content-Type":"text/plain; charset=\"UTF-8\"","Content-Transfer-Encoding":"quoted-printable","User-Agent":"Evolution 3.48.3 (3.48.3-1.fc38) ","MIME-Version":"1.0","Subject":"Re: [libcamera-devel] [PATCH] gstreamer: Add 'list-cameras' property","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Nicolas Dufresne via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Nicolas Dufresne <nicolas.dufresne@collabora.com>","Cc":"vedantparanjape160201@gmail.com","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]