Show a patch.

GET /api/patches/18761/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 18761,
    "url": "https://patchwork.libcamera.org/api/patches/18761/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/18761/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20230626174752.71344-1-umang.jain@ideasonboard.com>",
    "date": "2023-06-26T17:47:52",
    "name": "[libcamera-devel,v2] gstreamer: Maintain a control list to track libcamerasrc control properties",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "7c238303d5df21c154199a05c4759df6cb60b04e",
    "submitter": {
        "id": 86,
        "url": "https://patchwork.libcamera.org/api/people/86/?format=api",
        "name": "Umang Jain",
        "email": "umang.jain@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/18761/mbox/",
    "series": [
        {
            "id": 3938,
            "url": "https://patchwork.libcamera.org/api/series/3938/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3938",
            "date": "2023-06-26T17:47:52",
            "name": "[libcamera-devel,v2] gstreamer: Maintain a control list to track libcamerasrc control properties",
            "version": 2,
            "mbox": "https://patchwork.libcamera.org/series/3938/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/18761/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/18761/checks/",
    "tags": {},
    "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 157F6BE175\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 26 Jun 2023 17:47:58 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6E725628BC;\n\tMon, 26 Jun 2023 19:47:57 +0200 (CEST)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C5D0D628BB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 26 Jun 2023 19:47:56 +0200 (CEST)",
            "from umang.jainideasonboard.com (85-160-54-103.reb.o2.cz\n\t[85.160.54.103])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 5E6FD4AD;\n\tMon, 26 Jun 2023 19:47:17 +0200 (CEST)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1687801677;\n\tbh=qquie6S7VOgAZwLjOBYlKTnQDJrcEq/4U1LazXFjJ3g=;\n\th=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post:\n\tList-Help:List-Subscribe:From:Reply-To:Cc:From;\n\tb=rXP3hX2l5XFdnAGxt7UwnoY3rytf8Nd5psRaqcSAwHlp+8on3QpSn4uResC81+Aaj\n\t9HnzGHtUyYaPTwFnoOc+ecGEm0brCqAJJbmBJI5QcUv/KDuxUg24aEPuhZCDe3/Hfn\n\tFybz6nvz3GehS2ySvve6dbWWdpwItHaUZMptdF/Htn+ClhY+DdDRtaTtqZBUWGyH2j\n\tdpA1n1GcvJqh7D3rPCTQ9eeTct4sjSEc7POauRGiKsqq9GKm2jCJK2lMGFDtihx9Cc\n\tS+w7n3HADc9tpEomYaSixC/icmoIbWpFWcPAkO9RWbfuHTYRIj6Nau4A2AYffa/Ixv\n\t0hKKY1MfaolbQ==",
            "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1687801637;\n\tbh=qquie6S7VOgAZwLjOBYlKTnQDJrcEq/4U1LazXFjJ3g=;\n\th=From:To:Cc:Subject:Date:From;\n\tb=ZQZt/cBEu/xRcsn2EhdVxX+3SK/Ojp4Hhmo/HwSd9zFpxAc2IMdwUjdliZOBq9Em6\n\tpqMnq5KW1+pyp7rQNCAyuKMGecFrhxYPuwvQ+24f0SlSMRUtRtvlLrKQX4Sq8dGnCO\n\tVP3ELvUyUAWc3GwQzB5ab8QBSMSEuFDHKE7heb/A="
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"ZQZt/cBE\"; dkim-atps=neutral",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Mon, 26 Jun 2023 19:47:52 +0200",
        "Message-Id": "<20230626174752.71344-1-umang.jain@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.39.1",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH v2] gstreamer: Maintain a control list to\n\ttrack libcamerasrc control properties",
        "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": "Cedric Nugteren <cedric@plumerai.com>,\n\tCedric Nugteren <web@cedricnugteren.nl>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "As more and more libcamera controls get plumbed, more member variables\nget introduced in struct GstLibcameraSrc. Instead of doing that, now\nmaintain a single ControlList which is more appropriate to keep track\nof controls that get sets on libcamerasrc.\n\nThis also brings easy validation of controls set on libcamerasrc. If\nthe controls are not supported by camera, fail negotiation and report\nwhat is not supported.\n\nThe current patch migrates previously introduced control,\nauto-focus-mode, to be set directly in control list.\n\nSigned-off-by: Umang Jain <umang.jain@ideasonboard.com>\n---\nChanges in v2:\n- Edit commit message \n- Drop a break; so that all unsupported user-provided controls are\n  reported at once.\n---\n src/gstreamer/gstlibcamerasrc.cpp | 44 ++++++++++++++++++++++---------\n src/gstreamer/gstlibcamerasrc.h   |  6 ++---\n 2 files changed, 35 insertions(+), 15 deletions(-)",
    "diff": "diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\nindex 47d8ff43..11f15068 100644\n--- a/src/gstreamer/gstlibcamerasrc.cpp\n+++ b/src/gstreamer/gstlibcamerasrc.cpp\n@@ -146,7 +146,7 @@ struct _GstLibcameraSrc {\n \tGstTask *task;\n \n \tgchar *camera_name;\n-\tcontrols::AfModeEnum auto_focus_mode = controls::AfModeManual;\n+\tControlList *controls;\n \n \tGstLibcameraSrcState *state;\n \tGstLibcameraAllocator *allocator;\n@@ -462,7 +462,9 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread,\n \tGstLibcameraSrc *self = GST_LIBCAMERA_SRC(user_data);\n \tGLibRecLocker lock(&self->stream_lock);\n \tGstLibcameraSrcState *state = self->state;\n+\tconst ControlInfoMap &info_map = state->cam_->controls();\n \tGstFlowReturn flow_ret = GST_FLOW_OK;\n+\tgboolean supported_ctrl = true;\n \tgint ret;\n \n \tg_autoptr(GstStructure) element_caps = gst_structure_new_empty(\"caps\");\n@@ -579,18 +581,30 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread,\n \t\tgst_flow_combiner_add_pad(self->flow_combiner, srcpad);\n \t}\n \n-\tif (self->auto_focus_mode != controls::AfModeManual) {\n-\t\tconst ControlInfoMap &infoMap = state->cam_->controls();\n-\t\tif (infoMap.find(&controls::AfMode) != infoMap.end()) {\n-\t\t\tstate->initControls_.set(controls::AfMode, self->auto_focus_mode);\n-\t\t} else {\n+\t/*\n+\t * Check the controls set on libcamerasrc is supported by the camera.\n+\t * This can be easily done by CameraControlValidator but it is an internal\n+\t * libcamera class. Hence avoid adding a internal header even though\n+\t * gstreamer links with libcamera-private.\n+\t */\n+\tfor (auto iter = self->controls->begin(); iter != self->controls->end(); iter++) {\n+\t\tif (info_map.find(iter->first) == info_map.end()) {\n+\t\t\tconst ControlIdMap *id_map = self->controls->idMap();\n \t\t\tGST_ELEMENT_ERROR(self, RESOURCE, SETTINGS,\n-\t\t\t\t\t  (\"Failed to enable auto focus\"),\n-\t\t\t\t\t  (\"AfMode not supported by this camera, \"\n-\t\t\t\t\t   \"please retry with 'auto-focus-mode=AfModeManual'\"));\n+\t\t\t\t\t  (\"Failed to set %s\", id_map->at(iter->first)->name().c_str()),\n+\t\t\t\t\t  (\"%s not supported by this camera, \", id_map->at(iter->first)->name().c_str()));\n+\t\t\tsupported_ctrl = false;\n \t\t}\n \t}\n \n+\tif (!supported_ctrl) {\n+\t\tgst_task_stop(task);\n+\t\tflow_ret = GST_FLOW_NOT_NEGOTIATED;\n+\t\tgoto done;\n+\t}\n+\n+\tstate->initControls_.merge(*self->controls);\n+\n \tret = state->cam_->start(&state->initControls_);\n \tif (ret) {\n \t\tGST_ELEMENT_ERROR(self, RESOURCE, SETTINGS,\n@@ -674,7 +688,8 @@ gst_libcamera_src_set_property(GObject *object, guint prop_id,\n \t\tself->camera_name = g_value_dup_string(value);\n \t\tbreak;\n \tcase PROP_AUTO_FOCUS_MODE:\n-\t\tself->auto_focus_mode = static_cast<controls::AfModeEnum>(g_value_get_enum(value));\n+\t\tself->controls->set(controls::AfMode,\n+\t\t\t\t    static_cast<controls::AfModeEnum>(g_value_get_enum(value)));\n \t\tbreak;\n \tdefault:\n \t\tG_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);\n@@ -693,9 +708,11 @@ 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_AUTO_FOCUS_MODE:\n-\t\tg_value_set_enum(value, static_cast<gint>(self->auto_focus_mode));\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 \t\tbreak;\n+\t}\n \tdefault:\n \t\tG_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);\n \t\tbreak;\n@@ -760,6 +777,7 @@ gst_libcamera_src_finalize(GObject *object)\n \tg_rec_mutex_clear(&self->stream_lock);\n \tg_clear_object(&self->task);\n \tg_free(self->camera_name);\n+\tdelete self->controls;\n \tdelete self->state;\n \n \treturn klass->finalize(object);\n@@ -783,6 +801,8 @@ gst_libcamera_src_init(GstLibcameraSrc *self)\n \t/* C-style friend. */\n \tstate->src_ = self;\n \tself->state = state;\n+\n+\tself->controls = new ControlList(controls::controls, nullptr);\n }\n \n static GstPad *\ndiff --git a/src/gstreamer/gstlibcamerasrc.h b/src/gstreamer/gstlibcamerasrc.h\nindex 0a88ba02..2e6d74cb 100644\n--- a/src/gstreamer/gstlibcamerasrc.h\n+++ b/src/gstreamer/gstlibcamerasrc.h\n@@ -26,17 +26,17 @@ gst_libcamera_auto_focus_get_type()\n \tstatic GType type = 0;\n \tstatic const GEnumValue values[] = {\n \t\t{\n-\t\t\tstatic_cast<gint>(libcamera::controls::AfModeManual),\n+\t\t\tlibcamera::controls::AfModeManual,\n \t\t\t\"AfModeManual\",\n \t\t\t\"manual-focus\",\n \t\t},\n \t\t{\n-\t\t\tstatic_cast<gint>(libcamera::controls::AfModeAuto),\n+\t\t\tlibcamera::controls::AfModeAuto,\n \t\t\t\"AfModeAuto\",\n \t\t\t\"automatic-auto-focus\",\n \t\t},\n \t\t{\n-\t\t\tstatic_cast<gint>(libcamera::controls::AfModeContinuous),\n+\t\t\tlibcamera::controls::AfModeContinuous,\n \t\t\t\"AfModeContinuous\",\n \t\t\t\"continuous-auto-focus\",\n \t\t},\n",
    "prefixes": [
        "libcamera-devel",
        "v2"
    ]
}