{"id":19238,"url":"https://patchwork.libcamera.org/api/patches/19238/?format=json","web_url":"https://patchwork.libcamera.org/patch/19238/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20231124123713.22519-6-naush@raspberrypi.com>","date":"2023-11-24T12:37:11","name":"[libcamera-devel,v3,5/7] libcamera: controls: Use vendor tags for draft controls and properties","commit_ref":null,"pull_url":null,"state":"accepted","archived":false,"hash":"6c535f5ae7d09ca4d85fb2dbb093700d2cfafdff","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/?format=json","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/19238/mbox/","series":[{"id":4084,"url":"https://patchwork.libcamera.org/api/series/4084/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=4084","date":"2023-11-24T12:37:06","name":"Vendor controls and properties","version":3,"mbox":"https://patchwork.libcamera.org/series/4084/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/19238/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/19238/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 BB5ACC32B6\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 24 Nov 2023 12:37:25 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 50E0D629D1;\n\tFri, 24 Nov 2023 13:37:25 +0100 (CET)","from mail-wm1-x330.google.com (mail-wm1-x330.google.com\n\t[IPv6:2a00:1450:4864:20::330])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6CBFA629C0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 24 Nov 2023 13:37:22 +0100 (CET)","by mail-wm1-x330.google.com with SMTP id\n\t5b1f17b1804b1-40b2a8c7ca9so14496925e9.2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 24 Nov 2023 04:37:22 -0800 (PST)","from localhost.localdomain ([93.93.133.154])\n\tby smtp.gmail.com with ESMTPSA id\n\tv11-20020a05600c444b00b0040b3867a297sm3303690wmn.36.2023.11.24.04.37.20\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tFri, 24 Nov 2023 04:37:20 -0800 (PST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1700829445;\n\tbh=seTU+UQSsBaAMPpyKKZif1q9XqB8jxwEfOVXpwJ7DZA=;\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:\n\tFrom;\n\tb=xTar/AKPMjVV15UUXWEmmQbWrnhNmkPnv8Pt6vDV7ClSbHIF/K8Cul1jCE48ShUYg\n\tpSCXwsYqRUYU+qR+7X3ltqIOEO+9SMG/zxIcbVs4aUydehSq4M/cGiprsvy15wIJgd\n\tGHUL9hFccovG2gmHIdh/tDZTkMc4fyBvv/iGfhTPrGY2xc3SimoY2OfevcZRh7gt03\n\tgar8KaZqJEcKlCLTAin6vMuPXEWocuJ7gTPQKY+oKHdJ+k3OQLz2HYwl8z1drJoNNt\n\tX8CWjE2bpPHVtpajA6iMJiK5UeldefvsPN0P0Utj6ln9BVpoNUtNKmnegPTtr5KEea\n\tOiEfycut98Wpg==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google; t=1700829442; x=1701434242;\n\tdarn=lists.libcamera.org; \n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=5kHClKoADatMBPStz60slui8CckL4jEgFwLCEP4EeyQ=;\n\tb=rw5rKYyxE00cIQRQV35NoX0tEM6rby7Rd7kW1ClH5MvbM4THPfbWVFrLRxBM5OtqnA\n\tqsaZjxTNEF3sOYl2CzuZozilsXW3SzTBX6n4mJdRtG1E6UzS8DT+ffQjWM2M7VFHF6nu\n\t6l9LgdHR1djKv0hZXrHExhozlCu+JeT5G4YnPyKmpECQh0wPfbWjOveG4/HdByLpKC39\n\t8FkE43ycP0HTRyZxkq4swmBh+4mD5gC3e1bvq+/XCc3O90925UwTGyf08pICqcOIDpXe\n\tGrTBZaFGXy92HZwf1i0u0Z3+W6e/wCmSmkZAYodlWZUQQFNCS8nKoWK0xBr2zC8i+74F\n\tgHoQ=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"rw5rKYyx\"; dkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1700829442; x=1701434242;\n\th=content-transfer-encoding:mime-version:references:in-reply-to\n\t:message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc\n\t:subject:date:message-id:reply-to;\n\tbh=5kHClKoADatMBPStz60slui8CckL4jEgFwLCEP4EeyQ=;\n\tb=AKoCUWjRygSKRnOD+8zbqzkSBNUA1VqYbS8l0GP0/grTx3Xz9JucSPHxIM2On2+yGT\n\tLSZmfu9QvrpKtZHxhvS3IVb73yNmvI2eLOjvPZdn37Acidb/Ly5nD3PmSZs5qr4JMasd\n\th3B14MnYcpLGR626FG5lhR035vxzfOHSAPc03zmdFYeDoArs026u//FJT4Cqf+Olnf+1\n\tR6M7+y/juENANob46C0SDkef+mR3I44zeXWJU3DXngXk6sYP4KHjXBMm6nVUPUXC5shn\n\tUQolj4iglOkKENle0ivvWH9CVSKzoClH2Ip7GH02KNMu/WGJ1XK0G2dWadRVdjqcCghZ\n\tRpCQ==","X-Gm-Message-State":"AOJu0Yz659hmMTetKlp+ppaiJ4imOBqAgiQvkC63ZKnuW6bJM7IK2Uwu\n\twRnuP4J2OFypPUsSOabW8k+Jq4OjhXAaeogGTtaPDQ==","X-Google-Smtp-Source":"AGHT+IGxZy7ybFllRecZf5wsW3N9/aK4buQnYU4rcveTdErXXDSaXDJZmDb0gUfNqJyqauEOz9dXXg==","X-Received":"by 2002:a05:600c:4e8e:b0:40b:3e18:1f4 with SMTP id\n\tf14-20020a05600c4e8e00b0040b3e1801f4mr10582wmq.30.1700829441399; \n\tFri, 24 Nov 2023 04:37:21 -0800 (PST)","To":"libcamera-devel@lists.libcamera.org","Date":"Fri, 24 Nov 2023 12:37:11 +0000","Message-Id":"<20231124123713.22519-6-naush@raspberrypi.com>","X-Mailer":"git-send-email 2.34.1","In-Reply-To":"<20231124123713.22519-1-naush@raspberrypi.com>","References":"<20231124123713.22519-1-naush@raspberrypi.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use vendor\n\ttags for draft controls and 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":"Naushir Patuck via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Naushir Patuck <naush@raspberrypi.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"Label draft controls and properties through the \"draft\" vendor tag\nand deprecate the existing \"draft: true\" mechanism. This uses the new\nvendor tags mechanism to place draft controls in the same\nlibcamera::controls::draft namespace and provide a defined control id\nrange for these controls. This requires moving all draft controls from\ncontrol_ids.yaml to control_ids_draft.yaml.\n\nOne breaking change in this commit is that draft control ids also move\nto the libcamera::controls::draft namespace from the existing\nlibcamera::controls namespace. This is desirable to avoid API breakages\nwhen adding new libcamera controls. So, for example, the use of\ncontrols::NOISE_REDUCTION_MODE will need to be replaced with\ncontrols::draft::NOISE_REDUCTION_MODE.\n\nSigned-off-by: Naushir Patuck <naush@raspberrypi.com>\n---\n include/libcamera/control_ids.h.in            |   6 -\n include/libcamera/meson.build                 |   2 +\n include/libcamera/property_ids.h.in           |   6 -\n src/ipa/rpi/common/ipa_base.cpp               |   2 +-\n src/ipa/rpi/vc4/vc4.cpp                       |   2 +-\n src/libcamera/control_ids.cpp.in              |  16 +-\n src/libcamera/control_ids_core.yaml           | 232 -----------------\n src/libcamera/control_ids_draft.yaml          | 240 ++++++++++++++++++\n src/libcamera/property_ids.cpp.in             |  16 +-\n src/libcamera/property_ids_core.yaml          |  33 ---\n src/libcamera/property_ids_draft.yaml         |  39 +++\n src/py/libcamera/gen-py-controls.py           |   5 +-\n src/py/libcamera/py_controls_generated.cpp.in |   5 -\n .../libcamera/py_properties_generated.cpp.in  |   1 -\n utils/gen-controls.py                         |  36 +--\n 15 files changed, 295 insertions(+), 346 deletions(-)\n create mode 100644 src/libcamera/control_ids_draft.yaml\n create mode 100644 src/libcamera/property_ids_draft.yaml","diff":"diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in\nindex c97b09a82450..d53b1cf7beb2 100644\n--- a/include/libcamera/control_ids.h.in\n+++ b/include/libcamera/control_ids.h.in\n@@ -26,12 +26,6 @@ ${controls}\n \n extern const ControlIdMap controls;\n \n-namespace draft {\n-\n-${draft_controls}\n-\n-} /* namespace draft */\n-\n ${vendor_controls}\n \n } /* namespace controls */\ndiff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\nindex 79187d3fdfc9..1504f741ae2f 100644\n--- a/include/libcamera/meson.build\n+++ b/include/libcamera/meson.build\n@@ -34,10 +34,12 @@ libcamera_headers_install_dir = get_option('includedir') / libcamera_include_dir\n \n controls_map = {\n     'controls': {\n+        'draft': 'control_ids_draft.yaml',\n         'core': 'control_ids_core.yaml',\n     },\n \n     'properties': {\n+        'draft': 'property_ids_draft.yaml',\n         'core': 'property_ids_core.yaml',\n     }\n }\ndiff --git a/include/libcamera/property_ids.h.in b/include/libcamera/property_ids.h.in\nindex 47c5d6bf2e28..43372c718fc9 100644\n--- a/include/libcamera/property_ids.h.in\n+++ b/include/libcamera/property_ids.h.in\n@@ -23,12 +23,6 @@ ${ids}\n \n ${controls}\n \n-namespace draft {\n-\n-${draft_controls}\n-\n-} /* namespace draft */\n-\n extern const ControlIdMap properties;\n \n ${vendor_controls}\ndiff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp\nindex a1fec3aa3dd1..6ac9d5de2f88 100644\n--- a/src/ipa/rpi/common/ipa_base.cpp\n+++ b/src/ipa/rpi/common/ipa_base.cpp\n@@ -1024,7 +1024,7 @@ void IpaBase::applyControls(const ControlList &controls)\n \t\t\tbreak;\n \t\t}\n \n-\t\tcase controls::NOISE_REDUCTION_MODE:\n+\t\tcase controls::draft::NOISE_REDUCTION_MODE:\n \t\t\t/* Handled below in handleControls() */\n \t\t\tlibcameraMetadata_.set(controls::draft::NoiseReductionMode,\n \t\t\t\t\t       ctrl.second.get<int32_t>());\ndiff --git a/src/ipa/rpi/vc4/vc4.cpp b/src/ipa/rpi/vc4/vc4.cpp\nindex c4baf04fb1e7..c165a5b8b0b6 100644\n--- a/src/ipa/rpi/vc4/vc4.cpp\n+++ b/src/ipa/rpi/vc4/vc4.cpp\n@@ -260,7 +260,7 @@ void IpaVc4::handleControls(const ControlList &controls)\n \n \tfor (auto const &ctrl : controls) {\n \t\tswitch (ctrl.first) {\n-\t\tcase controls::NOISE_REDUCTION_MODE: {\n+\t\tcase controls::draft::NOISE_REDUCTION_MODE: {\n \t\t\tRPiController::DenoiseAlgorithm *sdn = dynamic_cast<RPiController::DenoiseAlgorithm *>(\n \t\t\t\tcontroller_.getAlgorithm(\"SDN\"));\n \t\t\t/* Some platforms may have a combined \"denoise\" algorithm instead. */\ndiff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in\nindex be86548cf73f..d283c1c1f401 100644\n--- a/src/libcamera/control_ids.cpp.in\n+++ b/src/libcamera/control_ids.cpp.in\n@@ -24,15 +24,6 @@ namespace controls {\n \n ${controls_doc}\n \n-/**\n- * \\brief Namespace for libcamera draft controls\n- */\n-namespace draft {\n-\n-${draft_controls_doc}\n-\n-} /* namespace draft */\n-\n ${vendor_controls_doc}\n \n #ifndef __DOXYGEN__\n@@ -42,13 +33,8 @@ ${vendor_controls_doc}\n  */\n ${controls_def}\n \n-namespace draft {\n-\n-${draft_controls_def}\n-\n-} /* namespace draft */\n-\n ${vendor_controls_def}\n+\n #endif\n \n /**\ndiff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml\nindex ff74ce1deedb..76fb9347d8e3 100644\n--- a/src/libcamera/control_ids_core.yaml\n+++ b/src/libcamera/control_ids_core.yaml\n@@ -865,236 +865,4 @@ controls:\n           description: |\n             This is a long exposure image.\n \n-  # ----------------------------------------------------------------------------\n-  # Draft controls section\n-\n-  - AePrecaptureTrigger:\n-      type: int32_t\n-      draft: true\n-      description: |\n-        Control for AE metering trigger. Currently identical to\n-        ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER.\n-\n-        Whether the camera device will trigger a precapture metering sequence\n-        when it processes this request.\n-      enum:\n-        - name: AePrecaptureTriggerIdle\n-          value: 0\n-          description: The trigger is idle.\n-        - name: AePrecaptureTriggerStart\n-          value: 1\n-          description: The pre-capture AE metering is started by the camera.\n-        - name: AePrecaptureTriggerCancel\n-          value: 2\n-          description: |\n-            The camera will cancel any active or completed metering sequence.\n-            The AE algorithm is reset to its initial state.\n-\n-  - NoiseReductionMode:\n-      type: int32_t\n-      draft: true\n-      description: |\n-       Control to select the noise reduction algorithm mode. Currently\n-       identical to ANDROID_NOISE_REDUCTION_MODE.\n-\n-        Mode of operation for the noise reduction algorithm.\n-      enum:\n-        - name: NoiseReductionModeOff\n-          value: 0\n-          description: No noise reduction is applied\n-        - name: NoiseReductionModeFast\n-          value: 1\n-          description: |\n-            Noise reduction is applied without reducing the frame rate.\n-        - name: NoiseReductionModeHighQuality\n-          value: 2\n-          description: |\n-            High quality noise reduction at the expense of frame rate.\n-        - name: NoiseReductionModeMinimal\n-          value: 3\n-          description: |\n-            Minimal noise reduction is applied without reducing the frame rate.\n-        - name: NoiseReductionModeZSL\n-          value: 4\n-          description: |\n-            Noise reduction is applied at different levels to different streams.\n-\n-  - ColorCorrectionAberrationMode:\n-      type: int32_t\n-      draft: true\n-      description: |\n-       Control to select the color correction aberration mode. Currently\n-       identical to ANDROID_COLOR_CORRECTION_ABERRATION_MODE.\n-\n-        Mode of operation for the chromatic aberration correction algorithm.\n-      enum:\n-        - name: ColorCorrectionAberrationOff\n-          value: 0\n-          description: No aberration correction is applied.\n-        - name: ColorCorrectionAberrationFast\n-          value: 1\n-          description: Aberration correction will not slow down the frame rate.\n-        - name: ColorCorrectionAberrationHighQuality\n-          value: 2\n-          description: |\n-            High quality aberration correction which might reduce the frame\n-            rate.\n-\n-  - AeState:\n-      type: int32_t\n-      draft: true\n-      description: |\n-       Control to report the current AE algorithm state. Currently identical to\n-       ANDROID_CONTROL_AE_STATE.\n-\n-        Current state of the AE algorithm.\n-      enum:\n-        - name: AeStateInactive\n-          value: 0\n-          description: The AE algorithm is inactive.\n-        - name: AeStateSearching\n-          value: 1\n-          description: The AE algorithm has not converged yet.\n-        - name: AeStateConverged\n-          value: 2\n-          description: The AE algorithm has converged.\n-        - name: AeStateLocked\n-          value: 3\n-          description: The AE algorithm is locked.\n-        - name: AeStateFlashRequired\n-          value: 4\n-          description: The AE algorithm would need a flash for good results\n-        - name: AeStatePrecapture\n-          value: 5\n-          description: |\n-            The AE algorithm has started a pre-capture metering session.\n-            \\sa AePrecaptureTrigger\n-\n-  - AwbState:\n-      type: int32_t\n-      draft: true\n-      description: |\n-       Control to report the current AWB algorithm state. Currently identical\n-       to ANDROID_CONTROL_AWB_STATE.\n-\n-        Current state of the AWB algorithm.\n-      enum:\n-        - name: AwbStateInactive\n-          value: 0\n-          description: The AWB algorithm is inactive.\n-        - name: AwbStateSearching\n-          value: 1\n-          description: The AWB algorithm has not converged yet.\n-        - name: AwbConverged\n-          value: 2\n-          description: The AWB algorithm has converged.\n-        - name: AwbLocked\n-          value: 3\n-          description: The AWB algorithm is locked.\n-\n-  - SensorRollingShutterSkew:\n-      type: int64_t\n-      draft: true\n-      description: |\n-       Control to report the time between the start of exposure of the first\n-       row and the start of exposure of the last row. Currently identical to\n-       ANDROID_SENSOR_ROLLING_SHUTTER_SKEW\n-\n-  - LensShadingMapMode:\n-      type: int32_t\n-      draft: true\n-      description: |\n-       Control to report if the lens shading map is available. Currently\n-       identical to ANDROID_STATISTICS_LENS_SHADING_MAP_MODE.\n-      enum:\n-        - name: LensShadingMapModeOff\n-          value: 0\n-          description: No lens shading map mode is available.\n-        - name: LensShadingMapModeOn\n-          value: 1\n-          description: The lens shading map mode is available.\n-\n-  - PipelineDepth:\n-      type: int32_t\n-      draft: true\n-      description: |\n-        Specifies the number of pipeline stages the frame went through from when\n-        it was exposed to when the final completed result was available to the\n-        framework. Always less than or equal to PipelineMaxDepth. Currently\n-        identical to ANDROID_REQUEST_PIPELINE_DEPTH.\n-\n-        The typical value for this control is 3 as a frame is first exposed,\n-        captured and then processed in a single pass through the ISP. Any\n-        additional processing step performed after the ISP pass (in example face\n-        detection, additional format conversions etc) count as an additional\n-        pipeline stage.\n-\n-  - MaxLatency:\n-      type: int32_t\n-      draft: true\n-      description: |\n-        The maximum number of frames that can occur after a request (different\n-        than the previous) has been submitted, and before the result's state\n-        becomes synchronized. A value of -1 indicates unknown latency, and 0\n-        indicates per-frame control. Currently identical to\n-        ANDROID_SYNC_MAX_LATENCY.\n-\n-  - TestPatternMode:\n-      type: int32_t\n-      draft: true\n-      description: |\n-        Control to select the test pattern mode. Currently identical to\n-        ANDROID_SENSOR_TEST_PATTERN_MODE.\n-      enum:\n-        - name: TestPatternModeOff\n-          value: 0\n-          description: |\n-            No test pattern mode is used. The camera device returns frames from\n-            the image sensor.\n-        - name: TestPatternModeSolidColor\n-          value: 1\n-          description: |\n-            Each pixel in [R, G_even, G_odd, B] is replaced by its respective\n-            color channel provided in test pattern data.\n-            \\todo Add control for test pattern data.\n-        - name: TestPatternModeColorBars\n-          value: 2\n-          description: |\n-            All pixel data is replaced with an 8-bar color pattern. The vertical\n-            bars (left-to-right) are as follows; white, yellow, cyan, green,\n-            magenta, red, blue and black. Each bar should take up 1/8 of the\n-            sensor pixel array width. When this is not possible, the bar size\n-            should be rounded down to the nearest integer and the pattern can\n-            repeat on the right side. Each bar's height must always take up the\n-            full sensor pixel array height.\n-        - name: TestPatternModeColorBarsFadeToGray\n-          value: 3\n-          description: |\n-            The test pattern is similar to TestPatternModeColorBars,\n-            except that each bar should start at its specified color at the top\n-            and fade to gray at the bottom. Furthermore each bar is further\n-            subdevided into a left and right half. The left half should have a\n-            smooth gradient, and the right half should have a quantized\n-            gradient. In particular, the right half's should consist of blocks\n-            of the same color for 1/16th active sensor pixel array width. The\n-            least significant bits in the quantized gradient should be copied\n-            from the most significant bits of the smooth gradient. The height of\n-            each bar should always be a multiple of 128. When this is not the\n-            case, the pattern should repeat at the bottom of the image.\n-        - name: TestPatternModePn9\n-          value: 4\n-          description: |\n-            All pixel data is replaced by a pseudo-random sequence generated\n-            from a PN9 512-bit sequence (typically implemented in hardware with\n-            a linear feedback shift register). The generator should be reset at\n-            the beginning of each frame, and thus each subsequent raw frame with\n-            this test pattern should be exactly the same as the last.\n-        - name: TestPatternModeCustom1\n-          value: 256\n-          description: |\n-            The first custom test pattern. All custom patterns that are\n-            available only on this camera device are at least this numeric\n-            value. All of the custom test patterns will be static (that is the\n-            raw image must not vary from frame to frame).\n-\n ...\ndiff --git a/src/libcamera/control_ids_draft.yaml b/src/libcamera/control_ids_draft.yaml\nnew file mode 100644\nindex 000000000000..e4f53ea51d7a\n--- /dev/null\n+++ b/src/libcamera/control_ids_draft.yaml\n@@ -0,0 +1,240 @@\n+# SPDX-License-Identifier: LGPL-2.1-or-later\n+#\n+# Copyright (C) 2019, Google Inc.\n+#\n+%YAML 1.1\n+---\n+# Unless otherwise stated, all controls are bi-directional, i.e. they can be\n+# set through Request::controls() and returned out through Request::metadata().\n+vendor: draft\n+controls:\n+  - AePrecaptureTrigger:\n+      type: int32_t\n+      draft: true\n+      description: |\n+        Control for AE metering trigger. Currently identical to\n+        ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER.\n+\n+        Whether the camera device will trigger a precapture metering sequence\n+        when it processes this request.\n+      enum:\n+        - name: AePrecaptureTriggerIdle\n+          value: 0\n+          description: The trigger is idle.\n+        - name: AePrecaptureTriggerStart\n+          value: 1\n+          description: The pre-capture AE metering is started by the camera.\n+        - name: AePrecaptureTriggerCancel\n+          value: 2\n+          description: |\n+            The camera will cancel any active or completed metering sequence.\n+            The AE algorithm is reset to its initial state.\n+\n+  - NoiseReductionMode:\n+      type: int32_t\n+      draft: true\n+      description: |\n+       Control to select the noise reduction algorithm mode. Currently\n+       identical to ANDROID_NOISE_REDUCTION_MODE.\n+\n+        Mode of operation for the noise reduction algorithm.\n+      enum:\n+        - name: NoiseReductionModeOff\n+          value: 0\n+          description: No noise reduction is applied\n+        - name: NoiseReductionModeFast\n+          value: 1\n+          description: |\n+            Noise reduction is applied without reducing the frame rate.\n+        - name: NoiseReductionModeHighQuality\n+          value: 2\n+          description: |\n+            High quality noise reduction at the expense of frame rate.\n+        - name: NoiseReductionModeMinimal\n+          value: 3\n+          description: |\n+            Minimal noise reduction is applied without reducing the frame rate.\n+        - name: NoiseReductionModeZSL\n+          value: 4\n+          description: |\n+            Noise reduction is applied at different levels to different streams.\n+\n+  - ColorCorrectionAberrationMode:\n+      type: int32_t\n+      draft: true\n+      description: |\n+       Control to select the color correction aberration mode. Currently\n+       identical to ANDROID_COLOR_CORRECTION_ABERRATION_MODE.\n+\n+        Mode of operation for the chromatic aberration correction algorithm.\n+      enum:\n+        - name: ColorCorrectionAberrationOff\n+          value: 0\n+          description: No aberration correction is applied.\n+        - name: ColorCorrectionAberrationFast\n+          value: 1\n+          description: Aberration correction will not slow down the frame rate.\n+        - name: ColorCorrectionAberrationHighQuality\n+          value: 2\n+          description: |\n+            High quality aberration correction which might reduce the frame\n+            rate.\n+\n+  - AeState:\n+      type: int32_t\n+      draft: true\n+      description: |\n+       Control to report the current AE algorithm state. Currently identical to\n+       ANDROID_CONTROL_AE_STATE.\n+\n+        Current state of the AE algorithm.\n+      enum:\n+        - name: AeStateInactive\n+          value: 0\n+          description: The AE algorithm is inactive.\n+        - name: AeStateSearching\n+          value: 1\n+          description: The AE algorithm has not converged yet.\n+        - name: AeStateConverged\n+          value: 2\n+          description: The AE algorithm has converged.\n+        - name: AeStateLocked\n+          value: 3\n+          description: The AE algorithm is locked.\n+        - name: AeStateFlashRequired\n+          value: 4\n+          description: The AE algorithm would need a flash for good results\n+        - name: AeStatePrecapture\n+          value: 5\n+          description: |\n+            The AE algorithm has started a pre-capture metering session.\n+            \\sa AePrecaptureTrigger\n+\n+  - AwbState:\n+      type: int32_t\n+      draft: true\n+      description: |\n+       Control to report the current AWB algorithm state. Currently identical\n+       to ANDROID_CONTROL_AWB_STATE.\n+\n+        Current state of the AWB algorithm.\n+      enum:\n+        - name: AwbStateInactive\n+          value: 0\n+          description: The AWB algorithm is inactive.\n+        - name: AwbStateSearching\n+          value: 1\n+          description: The AWB algorithm has not converged yet.\n+        - name: AwbConverged\n+          value: 2\n+          description: The AWB algorithm has converged.\n+        - name: AwbLocked\n+          value: 3\n+          description: The AWB algorithm is locked.\n+\n+  - SensorRollingShutterSkew:\n+      type: int64_t\n+      draft: true\n+      description: |\n+       Control to report the time between the start of exposure of the first\n+       row and the start of exposure of the last row. Currently identical to\n+       ANDROID_SENSOR_ROLLING_SHUTTER_SKEW\n+\n+  - LensShadingMapMode:\n+      type: int32_t\n+      draft: true\n+      description: |\n+       Control to report if the lens shading map is available. Currently\n+       identical to ANDROID_STATISTICS_LENS_SHADING_MAP_MODE.\n+      enum:\n+        - name: LensShadingMapModeOff\n+          value: 0\n+          description: No lens shading map mode is available.\n+        - name: LensShadingMapModeOn\n+          value: 1\n+          description: The lens shading map mode is available.\n+\n+  - PipelineDepth:\n+      type: int32_t\n+      draft: true\n+      description: |\n+        Specifies the number of pipeline stages the frame went through from when\n+        it was exposed to when the final completed result was available to the\n+        framework. Always less than or equal to PipelineMaxDepth. Currently\n+        identical to ANDROID_REQUEST_PIPELINE_DEPTH.\n+\n+        The typical value for this control is 3 as a frame is first exposed,\n+        captured and then processed in a single pass through the ISP. Any\n+        additional processing step performed after the ISP pass (in example face\n+        detection, additional format conversions etc) count as an additional\n+        pipeline stage.\n+\n+  - MaxLatency:\n+      type: int32_t\n+      draft: true\n+      description: |\n+        The maximum number of frames that can occur after a request (different\n+        than the previous) has been submitted, and before the result's state\n+        becomes synchronized. A value of -1 indicates unknown latency, and 0\n+        indicates per-frame control. Currently identical to\n+        ANDROID_SYNC_MAX_LATENCY.\n+\n+  - TestPatternMode:\n+      type: int32_t\n+      draft: true\n+      description: |\n+        Control to select the test pattern mode. Currently identical to\n+        ANDROID_SENSOR_TEST_PATTERN_MODE.\n+      enum:\n+        - name: TestPatternModeOff\n+          value: 0\n+          description: |\n+            No test pattern mode is used. The camera device returns frames from\n+            the image sensor.\n+        - name: TestPatternModeSolidColor\n+          value: 1\n+          description: |\n+            Each pixel in [R, G_even, G_odd, B] is replaced by its respective\n+            color channel provided in test pattern data.\n+            \\todo Add control for test pattern data.\n+        - name: TestPatternModeColorBars\n+          value: 2\n+          description: |\n+            All pixel data is replaced with an 8-bar color pattern. The vertical\n+            bars (left-to-right) are as follows; white, yellow, cyan, green,\n+            magenta, red, blue and black. Each bar should take up 1/8 of the\n+            sensor pixel array width. When this is not possible, the bar size\n+            should be rounded down to the nearest integer and the pattern can\n+            repeat on the right side. Each bar's height must always take up the\n+            full sensor pixel array height.\n+        - name: TestPatternModeColorBarsFadeToGray\n+          value: 3\n+          description: |\n+            The test pattern is similar to TestPatternModeColorBars,\n+            except that each bar should start at its specified color at the top\n+            and fade to gray at the bottom. Furthermore each bar is further\n+            subdevided into a left and right half. The left half should have a\n+            smooth gradient, and the right half should have a quantized\n+            gradient. In particular, the right half's should consist of blocks\n+            of the same color for 1/16th active sensor pixel array width. The\n+            least significant bits in the quantized gradient should be copied\n+            from the most significant bits of the smooth gradient. The height of\n+            each bar should always be a multiple of 128. When this is not the\n+            case, the pattern should repeat at the bottom of the image.\n+        - name: TestPatternModePn9\n+          value: 4\n+          description: |\n+            All pixel data is replaced by a pseudo-random sequence generated\n+            from a PN9 512-bit sequence (typically implemented in hardware with\n+            a linear feedback shift register). The generator should be reset at\n+            the beginning of each frame, and thus each subsequent raw frame with\n+            this test pattern should be exactly the same as the last.\n+        - name: TestPatternModeCustom1\n+          value: 256\n+          description: |\n+            The first custom test pattern. All custom patterns that are\n+            available only on this camera device are at least this numeric\n+            value. All of the custom test patterns will be static (that is the\n+            raw image must not vary from frame to frame).\n+\n+...\ndiff --git a/src/libcamera/property_ids.cpp.in b/src/libcamera/property_ids.cpp.in\nindex 0771ac5c091f..8b274c38c74b 100644\n--- a/src/libcamera/property_ids.cpp.in\n+++ b/src/libcamera/property_ids.cpp.in\n@@ -23,15 +23,6 @@ namespace properties {\n \n ${controls_doc}\n \n-/**\n- * \\brief Namespace for libcamera draft properties\n- */\n-namespace draft {\n-\n-${draft_controls_doc}\n-\n-} /* namespace draft */\n-\n ${vendor_controls_doc}\n \n #ifndef __DOXYGEN__\n@@ -41,13 +32,8 @@ ${vendor_controls_doc}\n  */\n ${controls_def}\n \n-namespace draft {\n-\n-${draft_controls_def}\n-\n-} /* namespace draft */\n-\n ${vendor_controls_def}\n+\n #endif\n \n /**\ndiff --git a/src/libcamera/property_ids_core.yaml b/src/libcamera/property_ids_core.yaml\nindex 45f3609b4236..834454a4e087 100644\n--- a/src/libcamera/property_ids_core.yaml\n+++ b/src/libcamera/property_ids_core.yaml\n@@ -701,37 +701,4 @@ controls:\n \n         Different cameras may report identical devices.\n \n-  # ----------------------------------------------------------------------------\n-  # Draft properties section\n-\n-  - ColorFilterArrangement:\n-      type: int32_t\n-      draft: true\n-      description: |\n-        The arrangement of color filters on sensor; represents the colors in the\n-        top-left 2x2 section of the sensor, in reading order. Currently\n-        identical to ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT.\n-      enum:\n-        - name: RGGB\n-          value: 0\n-          description: RGGB Bayer pattern\n-        - name: GRBG\n-          value: 1\n-          description: GRBG Bayer pattern\n-        - name: GBRG\n-          value: 2\n-          description: GBRG Bayer pattern\n-        - name: BGGR\n-          value: 3\n-          description: BGGR Bayer pattern\n-        - name: RGB\n-          value: 4\n-          description: |\n-            Sensor is not Bayer; output has 3 16-bit values for each pixel,\n-            instead of just 1 16-bit value per pixel.\n-        - name: MONO\n-          value: 5\n-          description: |\n-            Sensor is not Bayer; output consists of a single colour channel.\n-\n ...\ndiff --git a/src/libcamera/property_ids_draft.yaml b/src/libcamera/property_ids_draft.yaml\nnew file mode 100644\nindex 000000000000..62f0e242d0c6\n--- /dev/null\n+++ b/src/libcamera/property_ids_draft.yaml\n@@ -0,0 +1,39 @@\n+# SPDX-License-Identifier: LGPL-2.1-or-later\n+#\n+# Copyright (C) 2019, Google Inc.\n+#\n+%YAML 1.1\n+---\n+vendor: draft\n+controls:\n+  - ColorFilterArrangement:\n+      type: int32_t\n+      vendor: draft\n+      description: |\n+        The arrangement of color filters on sensor; represents the colors in the\n+        top-left 2x2 section of the sensor, in reading order. Currently\n+        identical to ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT.\n+      enum:\n+        - name: RGGB\n+          value: 0\n+          description: RGGB Bayer pattern\n+        - name: GRBG\n+          value: 1\n+          description: GRBG Bayer pattern\n+        - name: GBRG\n+          value: 2\n+          description: GBRG Bayer pattern\n+        - name: BGGR\n+          value: 3\n+          description: BGGR Bayer pattern\n+        - name: RGB\n+          value: 4\n+          description: |\n+            Sensor is not Bayer; output has 3 16-bit values for each pixel,\n+            instead of just 1 16-bit value per pixel.\n+        - name: MONO\n+          value: 5\n+          description: |\n+            Sensor is not Bayer; output consists of a single colour channel.\n+\n+...\ndiff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py\nindex 8ae8d5126e39..55e0b4e8e3d6 100755\n--- a/src/py/libcamera/gen-py-controls.py\n+++ b/src/py/libcamera/gen-py-controls.py\n@@ -36,10 +36,7 @@ def generate_py(controls, mode):\n                 vendor_defs.append('\\tauto {} = py::class_<Py{}Controls>(controls, \\\"{}\\\");'.format(vendor, vendor, vendor))\n                 vendors.append(vendor)\n \n-            if ctrl.get('draft'):\n-                ns = 'libcamera::{}::draft::'.format(mode)\n-                container = 'draft'\n-            elif vendor != 'libcamera':\n+            if vendor != 'libcamera':\n                 ns = 'libcamera::{}::{}::'.format(mode, vendor)\n                 container = vendor\n             else:\ndiff --git a/src/py/libcamera/py_controls_generated.cpp.in b/src/py/libcamera/py_controls_generated.cpp.in\nindex ec4b55ef2011..8d282ce51856 100644\n--- a/src/py/libcamera/py_controls_generated.cpp.in\n+++ b/src/py/libcamera/py_controls_generated.cpp.in\n@@ -17,16 +17,11 @@ class PyControls\n {\n };\n \n-class PyDraftControls\n-{\n-};\n-\n ${vendors_class_def}\n \n void init_py_controls_generated(py::module& m)\n {\n \tauto controls = py::class_<PyControls>(m, \"controls\");\n-\tauto draft = py::class_<PyDraftControls>(controls, \"draft\");\n ${vendors_defs}\n \n ${controls}\ndiff --git a/src/py/libcamera/py_properties_generated.cpp.in b/src/py/libcamera/py_properties_generated.cpp.in\nindex f7b5ec8c635d..ae61c5440d31 100644\n--- a/src/py/libcamera/py_properties_generated.cpp.in\n+++ b/src/py/libcamera/py_properties_generated.cpp.in\n@@ -26,7 +26,6 @@ ${vendors_class_def}\n void init_py_properties_generated(py::module& m)\n {\n \tauto controls = py::class_<PyProperties>(m, \"properties\");\n-\tauto draft = py::class_<PyDraftProperties>(controls, \"draft\");\n ${vendors_defs}\n \n ${controls}\ndiff --git a/utils/gen-controls.py b/utils/gen-controls.py\nindex 04c63098b19b..45da571e83e0 100755\n--- a/utils/gen-controls.py\n+++ b/utils/gen-controls.py\n@@ -86,11 +86,6 @@ class Control(object):\n         \"\"\"Is the control an enumeration\"\"\"\n         return self.__enum_values is not None\n \n-    @property\n-    def is_draft(self):\n-        \"\"\"Is the control a draft control\"\"\"\n-        return self.__data.get('draft') is not None\n-\n     @property\n     def vendor(self):\n         \"\"\"The vendor string, or None\"\"\"\n@@ -101,12 +96,6 @@ class Control(object):\n         \"\"\"The control name (CamelCase)\"\"\"\n         return self.__name\n \n-    @property\n-    def q_name(self):\n-        \"\"\"The control name, qualified with a namespace\"\"\"\n-        ns = 'draft::' if self.is_draft else ''\n-        return ns + self.__name\n-\n     @property\n     def type(self):\n         typ = self.__data.get('type')\n@@ -159,7 +148,7 @@ ${description}\n     for ctrl in controls:\n         id_name = snake_case(ctrl.name).upper()\n \n-        vendor = 'draft' if ctrl.is_draft else ctrl.vendor\n+        vendor = ctrl.vendor\n         if vendor not in ctrls_doc:\n             ctrls_doc[vendor] = []\n             ctrls_def[vendor] = []\n@@ -208,7 +197,8 @@ ${description}\n         target_doc.append(doc_template.substitute(info))\n         target_def.append(def_template.substitute(info))\n \n-        ctrls_map.append('\\t{ ' + id_name + ', &' + ctrl.q_name + ' },')\n+        vendor_ns = vendor + '::' if vendor != \"libcamera\" else ''\n+        ctrls_map.append('\\t{ ' + vendor_ns + id_name + ', &' + vendor_ns + ctrl.name + ' },')\n \n     vendor_ctrl_doc_sub = []\n     vendor_ctrl_template = string.Template('''\n@@ -218,18 +208,16 @@ ${vendor_controls_str}\n \n } /* namespace ${vendor} */''')\n \n-    for vendor in [v for v in ctrls_doc.keys() if v not in ['libcamera', 'draft']]:\n+    for vendor in [v for v in ctrls_doc.keys() if v not in ['libcamera']]:\n         vendor_ctrl_doc_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, 'vendor_controls_str': '\\n\\n'.join(ctrls_doc[vendor])}))\n \n     vendor_ctrl_def_sub = []\n-    for vendor in [v for v in ctrls_def.keys() if v not in ['libcamera', 'draft']]:\n+    for vendor in [v for v in ctrls_def.keys() if v not in ['libcamera']]:\n         vendor_ctrl_def_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, 'vendor_controls_str': '\\n'.join(ctrls_def[vendor])}))\n \n     return {\n         'controls_doc': '\\n\\n'.join(ctrls_doc['libcamera']),\n         'controls_def': '\\n'.join(ctrls_def['libcamera']),\n-        'draft_controls_doc': '\\n\\n'.join(ctrls_doc['draft']),\n-        'draft_controls_def': '\\n\\n'.join(ctrls_def['draft']),\n         'controls_map': '\\n'.join(ctrls_map),\n         'vendor_controls_doc': '\\n'.join(vendor_ctrl_doc_sub),\n         'vendor_controls_def': '\\n'.join(vendor_ctrl_def_sub),\n@@ -249,7 +237,7 @@ def generate_h(controls, mode, ranges):\n     for ctrl in controls:\n         id_name = snake_case(ctrl.name).upper()\n \n-        vendor = 'draft' if ctrl.is_draft else ctrl.vendor\n+        vendor = ctrl.vendor\n         if vendor not in ctrls:\n             if vendor not in ranges.keys():\n                 raise RuntimeError(f'Control id range is not defined for vendor {vendor}')\n@@ -257,8 +245,7 @@ def generate_h(controls, mode, ranges):\n             ids[vendor] = []\n             ctrls[vendor] = []\n \n-        # Core and draft controls use the same ID value\n-        target_ids = ids['libcamera'] if vendor in ['libcamera', 'draft'] else ids[vendor]\n+        target_ids = ids[vendor]\n         target_ids.append('\\t' + id_name + ' = ' + str(id_value[vendor]) + ',')\n \n         info = {\n@@ -266,11 +253,7 @@ def generate_h(controls, mode, ranges):\n             'type': ctrl.type,\n         }\n \n-        target_ctrls = ctrls['libcamera']\n-        if ctrl.is_draft:\n-            target_ctrls = ctrls['draft']\n-        elif vendor != 'libcamera':\n-            target_ctrls = ctrls[vendor]\n+        target_ctrls = ctrls[vendor]\n \n         if ctrl.is_enum:\n             target_ctrls.append(enum_template_start.substitute(info))\n@@ -309,7 +292,7 @@ ${vendor_controls}\n ''')\n \n     vendor_sub = []\n-    for vendor in [v for v in ctrls.keys() if v not in ['libcamera', 'draft']]:\n+    for vendor in [v for v in ctrls.keys() if v != 'libcamera']:\n         vendor_sub.append(vendor_template.substitute({'mode': mode.upper(),\n                                                       'vendor': vendor,\n                                                       'vendor_def': vendor.upper(),\n@@ -319,7 +302,6 @@ ${vendor_controls}\n     return {\n         'ids': '\\n'.join(ids['libcamera']),\n         'controls': '\\n'.join(ctrls['libcamera']),\n-        'draft_controls': '\\n'.join(ctrls['draft']),\n         'vendor_controls': '\\n'.join(vendor_sub)\n     }\n \n","prefixes":["libcamera-devel","v3","5/7"]}