Show a patch.

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

{
    "id": 18766,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/18766/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/18766/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/1.1/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": "<20230629071121.21459-1-umang.jain@ideasonboard.com>",
    "date": "2023-06-29T07:11:21",
    "name": "[libcamera-devel,v4] gstreamer: Maintain a control list to track libcamerasrc control properties",
    "commit_ref": null,
    "pull_url": null,
    "state": "not-applicable",
    "archived": false,
    "hash": "4ba02653bfc0b44e87ae091f70564d9e0bab0162",
    "submitter": {
        "id": 86,
        "url": "https://patchwork.libcamera.org/api/1.1/people/86/?format=api",
        "name": "Umang Jain",
        "email": "umang.jain@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/18766/mbox/",
    "series": [
        {
            "id": 3943,
            "url": "https://patchwork.libcamera.org/api/1.1/series/3943/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3943",
            "date": "2023-06-29T07:11:21",
            "name": "[libcamera-devel,v4] gstreamer: Maintain a control list to track libcamerasrc control properties",
            "version": 4,
            "mbox": "https://patchwork.libcamera.org/series/3943/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/18766/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/18766/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 21F5DBDB1D\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 29 Jun 2023 07:11:28 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 9C15F628BC;\n\tThu, 29 Jun 2023 09:11:27 +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 9CBF760576\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 29 Jun 2023 09:11:26 +0200 (CEST)",
            "from umang.jainideasonboard.com (85-160-58-109.reb.o2.cz\n\t[85.160.58.109])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 7B9EDA4C;\n\tThu, 29 Jun 2023 09:10:45 +0200 (CEST)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1688022687;\n\tbh=89gHMJ7T1ZWsCNiFic6BFlznnyVvLlKK0zAnyDBPPyc=;\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=aoWwPF1B9O/JkqVfVXQOCMVauiF0uQbdXkQuckGY8KHpw68F8X60FSmS4+Cyb3hAT\n\thsoq3k7tKKVziGiQK/4NF/dqNrHRJ/FV5JHQY1OAtED/NdMOJvHgjzritAW0a1MeCJ\n\t6Vv53QdlvYU4vcpqTzM+J3qKzZHluru3s23Dhh+WSPFRtCW2QZcS7abLRSO5NW+rYJ\n\tmah9szKRUfvsMQzaZVPrlr7lcTD6DNeZLGnicx6Xp0ubBFq/oujX5doEeKscSQwoUA\n\tW/VEcecPpGYic0cav0Z07y/Llzp+StBrjq8RABv2nVKMnVHjb/C9ejq8PZmmDHKh9e\n\tBguyvIf7gMs2Q==",
            "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1688022645;\n\tbh=89gHMJ7T1ZWsCNiFic6BFlznnyVvLlKK0zAnyDBPPyc=;\n\th=From:To:Cc:Subject:Date:From;\n\tb=OzC1TztI9iXn6i7CebJ/2MXb4/QZl3rKHF6qCl9bztAyqz5IJUFMupd/gqL/CrdEn\n\tC9Rb3Ay8JcQk71b8k/Fc4SdRhccMRqmPQzd3nwjavd8Zvtdw8B80VOd6X/Dio8lrhQ\n\trvjasqrc/8YN4OZDdYX2aKdx40mzsNrBpwMerxPM="
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"OzC1TztI\"; dkim-atps=neutral",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Thu, 29 Jun 2023 09:11:21 +0200",
        "Message-Id": "<20230629071121.21459-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 v4] 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 <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---\n src/gstreamer/gstlibcamerasrc.cpp | 39 +++++++++++++++++++++----------\n src/gstreamer/gstlibcamerasrc.h   |  6 ++---\n 2 files changed, 30 insertions(+), 15 deletions(-)",
    "diff": "diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\nindex f764a87a..1f10136b 100644\n--- a/src/gstreamer/gstlibcamerasrc.cpp\n+++ b/src/gstreamer/gstlibcamerasrc.cpp\n@@ -142,7 +142,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@@ -458,7 +458,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@@ -575,18 +577,25 @@ 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/* Check if the controls set on libcamerasrc is supported by the camera. */\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@@ -670,7 +679,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@@ -689,9 +699,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@@ -757,6 +769,7 @@ gst_libcamera_src_finalize(GObject *object)\n \tg_clear_object(&self->task);\n \tg_mutex_clear(&self->state->lock_);\n \tg_free(self->camera_name);\n+\tdelete self->controls;\n \tdelete self->state;\n \n \treturn klass->finalize(object);\n@@ -782,6 +795,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",
        "v4"
    ]
}