[{"id":28183,"web_url":"https://patchwork.libcamera.org/comment/28183/","msgid":"<kcqhxhrnr6uzvj5d4ws7gkqmrny5hnqxvqs4ib76v3un7lpdq2@faffywfdvrpk>","date":"2023-11-27T16:57:06","subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags for draft controls and properties","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Naush\n\nOn Fri, Nov 24, 2023 at 12:37:11PM +0000, Naushir Patuck via libcamera-devel wrote:\n> Label draft controls and properties through the \"draft\" vendor tag\n> and deprecate the existing \"draft: true\" mechanism. This uses the new\n> vendor tags mechanism to place draft controls in the same\n> libcamera::controls::draft namespace and provide a defined control id\n> range for these controls. This requires moving all draft controls from\n> control_ids.yaml to control_ids_draft.yaml.\n>\n> One breaking change in this commit is that draft control ids also move\n> to the libcamera::controls::draft namespace from the existing\n> libcamera::controls namespace. This is desirable to avoid API breakages\n> when adding new libcamera controls. So, for example, the use of\n> controls::NOISE_REDUCTION_MODE will need to be replaced with\n> controls::draft::NOISE_REDUCTION_MODE.\n>\n> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n\nThanks, I like this change!\n\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\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\n>\n> diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in\n> index 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 */\n> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n> index 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>  }\n> diff --git a/include/libcamera/property_ids.h.in b/include/libcamera/property_ids.h.in\n> index 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}\n> diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp\n> index 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>());\n> diff --git a/src/ipa/rpi/vc4/vc4.cpp b/src/ipa/rpi/vc4/vc4.cpp\n> index 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. */\n> diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in\n> index 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>  /**\n> diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml\n> index 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>  ...\n> diff --git a/src/libcamera/control_ids_draft.yaml b/src/libcamera/control_ids_draft.yaml\n> new file mode 100644\n> index 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> +...\n> diff --git a/src/libcamera/property_ids.cpp.in b/src/libcamera/property_ids.cpp.in\n> index 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>  /**\n> diff --git a/src/libcamera/property_ids_core.yaml b/src/libcamera/property_ids_core.yaml\n> index 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>  ...\n> diff --git a/src/libcamera/property_ids_draft.yaml b/src/libcamera/property_ids_draft.yaml\n> new file mode 100644\n> index 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> +...\n> diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py\n> index 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:\n> diff --git a/src/py/libcamera/py_controls_generated.cpp.in b/src/py/libcamera/py_controls_generated.cpp.in\n> index 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}\n> diff --git a/src/py/libcamera/py_properties_generated.cpp.in b/src/py/libcamera/py_properties_generated.cpp.in\n> index 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}\n> diff --git a/utils/gen-controls.py b/utils/gen-controls.py\n> index 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> --\n> 2.34.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 EBF3BC31E9\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 27 Nov 2023 16:57:11 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 674A9629BB;\n\tMon, 27 Nov 2023 17:57:11 +0100 (CET)","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 41427629B6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 27 Nov 2023 17:57:09 +0100 (CET)","from ideasonboard.com (93-61-96-190.ip145.fastwebnet.it\n\t[93.61.96.190])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 79A5425A;\n\tMon, 27 Nov 2023 17:56:34 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1701104231;\n\tbh=T/n84unxy/PzrD4ucuuzYD9wCBH1hk0+40Vmb0F9OLo=;\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=vLTk6PDuTUFdcx73PqNqRJjUhz1z7NBTmTHdSx1m9BRc/HKqt0NyH7Lr1BzKMzH6W\n\tnK6w8WJy1i7GtZxgWkhiXONVLLX0C1yyvrxMHgGFs1v6YKgwpFvnL5HUt1h3IPo6oT\n\tZcBgwJrlnx2n99icN/N70OBTbnfoUeVOy/5jfQfkuMU8IcTTkPUvEA2QN25PJdHiN7\n\tvEU2Pn6fm7nanYDQ8Z12cxRTarQyrbJe0Bufrkb8trRnwWg3F4tYe+o8PQOCAjCA2q\n\tRhiALIaOTAgA3V2ZmXbynbe0QWORZPV2PHuKShpuKHGc74b0a5UtgZvzOA27Jominl\n\tWJgzCpdpkgEZA==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1701104194;\n\tbh=T/n84unxy/PzrD4ucuuzYD9wCBH1hk0+40Vmb0F9OLo=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=DgKNjyp3tEa0FOJABmGKWIVe+TG3dFh7A9P3hJyR3myU5XHswscrJ15HdUTRxR46E\n\t3dnKlAHuYfPDWFuULC/zQL6agHXD+68RK7qSkcN13Nt/emc5ZL3ke1xblBc3g+JwDv\n\tdJf8F91KpOh6nxsddHp6ZTJSgJbAMK15GZVs83KI="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"DgKNjyp3\"; dkim-atps=neutral","Date":"Mon, 27 Nov 2023 17:57:06 +0100","To":"Naushir Patuck <naush@raspberrypi.com>","Message-ID":"<kcqhxhrnr6uzvj5d4ws7gkqmrny5hnqxvqs4ib76v3un7lpdq2@faffywfdvrpk>","References":"<20231124123713.22519-1-naush@raspberrypi.com>\n\t<20231124123713.22519-6-naush@raspberrypi.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20231124123713.22519-6-naush@raspberrypi.com>","Subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags 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":"Jacopo Mondi via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":28191,"web_url":"https://patchwork.libcamera.org/comment/28191/","msgid":"<170116571290.630990.3499891286162848369@ping.linuxembedded.co.uk>","date":"2023-11-28T10:01:52","subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags for draft controls and properties","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Jacopo Mondi via libcamera-devel (2023-11-27 16:57:06)\n> Hi Naush\n> \n> On Fri, Nov 24, 2023 at 12:37:11PM +0000, Naushir Patuck via libcamera-devel wrote:\n> > Label draft controls and properties through the \"draft\" vendor tag\n> > and deprecate the existing \"draft: true\" mechanism. This uses the new\n> > vendor tags mechanism to place draft controls in the same\n> > libcamera::controls::draft namespace and provide a defined control id\n> > range for these controls. This requires moving all draft controls from\n> > control_ids.yaml to control_ids_draft.yaml.\n> >\n> > One breaking change in this commit is that draft control ids also move\n> > to the libcamera::controls::draft namespace from the existing\n> > libcamera::controls namespace. This is desirable to avoid API breakages\n> > when adding new libcamera controls. So, for example, the use of\n> > controls::NOISE_REDUCTION_MODE will need to be replaced with\n> > controls::draft::NOISE_REDUCTION_MODE.\n> >\n> > Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> \n> Thanks, I like this change!\n> \n> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> \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\n> >\n> > diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in\n> > index 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 */\n> > diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n> > index 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> >  }\n> > diff --git a/include/libcamera/property_ids.h.in b/include/libcamera/property_ids.h.in\n> > index 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}\n> > diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp\n> > index 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> >                       break;\n> >               }\n> >\n> > -             case controls::NOISE_REDUCTION_MODE:\n> > +             case controls::draft::NOISE_REDUCTION_MODE:\n> >                       /* Handled below in handleControls() */\n> >                       libcameraMetadata_.set(controls::draft::NoiseReductionMode,\n> >                                              ctrl.second.get<int32_t>());\n> > diff --git a/src/ipa/rpi/vc4/vc4.cpp b/src/ipa/rpi/vc4/vc4.cpp\n> > index 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> >       for (auto const &ctrl : controls) {\n> >               switch (ctrl.first) {\n> > -             case controls::NOISE_REDUCTION_MODE: {\n> > +             case controls::draft::NOISE_REDUCTION_MODE: {\n> >                       RPiController::DenoiseAlgorithm *sdn = dynamic_cast<RPiController::DenoiseAlgorithm *>(\n> >                               controller_.getAlgorithm(\"SDN\"));\n> >                       /* Some platforms may have a combined \"denoise\" algorithm instead. */\n> > diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in\n> > index 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> >  /**\n> > diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml\n> > index 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> >  ...\n> > diff --git a/src/libcamera/control_ids_draft.yaml b/src/libcamera/control_ids_draft.yaml\n> > new file mode 100644\n> > index 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\nIs the draft property still used? Or is this now conveyed as the vendor?\n\nThe parameter could always be dropped later.\n\nAnd I'm also a big fan of the draft controls being moved to their own\nnamespace and indexing which will lower ABI breakage in the future!\n\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\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> > +...\n> > diff --git a/src/libcamera/property_ids.cpp.in b/src/libcamera/property_ids.cpp.in\n> > index 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> >  /**\n> > diff --git a/src/libcamera/property_ids_core.yaml b/src/libcamera/property_ids_core.yaml\n> > index 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> >  ...\n> > diff --git a/src/libcamera/property_ids_draft.yaml b/src/libcamera/property_ids_draft.yaml\n> > new file mode 100644\n> > index 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> > +...\n> > diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py\n> > index 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:\n> > diff --git a/src/py/libcamera/py_controls_generated.cpp.in b/src/py/libcamera/py_controls_generated.cpp.in\n> > index 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> >       auto controls = py::class_<PyControls>(m, \"controls\");\n> > -     auto draft = py::class_<PyDraftControls>(controls, \"draft\");\n> >  ${vendors_defs}\n> >\n> >  ${controls}\n> > diff --git a/src/py/libcamera/py_properties_generated.cpp.in b/src/py/libcamera/py_properties_generated.cpp.in\n> > index 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> >       auto controls = py::class_<PyProperties>(m, \"properties\");\n> > -     auto draft = py::class_<PyDraftProperties>(controls, \"draft\");\n> >  ${vendors_defs}\n> >\n> >  ${controls}\n> > diff --git a/utils/gen-controls.py b/utils/gen-controls.py\n> > index 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> > --\n> > 2.34.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 0F7C3C31E9\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 28 Nov 2023 10:01:58 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 30BCE629C2;\n\tTue, 28 Nov 2023 11:01:57 +0100 (CET)","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 D4B4C61DA5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 28 Nov 2023 11:01:55 +0100 (CET)","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 86533BB2;\n\tTue, 28 Nov 2023 11:01:20 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1701165717;\n\tbh=eE15C5M8gpkP4erZiQ/uDz/gyBkjs5UOuXgcO6hcRiE=;\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=XVmErv1BtHUcZmG9+X0NrdHqbwlFtxCH/kI0S4+AKVdL8RBD/aQ6kTUF8RULeKyId\n\tbrHeEtPpl4MNPMLw3m9xbtyvbCTNOP7+JO4mIaBM3q+aOP5bb+83yGmB9N3geOxMXC\n\tiEAGvU6/06m3jgkNjmxJ9AgugEHHMSvURXsR8cmOT9P0qfu71hkJf2582jSqeTCeSO\n\tY0hkNqIZ2vhAShSK5iKF0YuRVwo86Ed052xKl5J0L8jk8DMql/iy//LBRnR4ZCnUbn\n\tA0H4iphqArYzSN4xDkm2r9CTPh8Bhqy7tAOjatBbXH5qeCWVl5vUewRqRYG94OSe86\n\t5qntrAPm2a85A==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1701165680;\n\tbh=eE15C5M8gpkP4erZiQ/uDz/gyBkjs5UOuXgcO6hcRiE=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=iJZivQQVy6cidAgpPafvSHpOKs8StuR0zzc7KehnkDxqU3atnnIvdnIuddQ+nypO/\n\tXSFlVlbrrByQMMCzi1GmIkgUS3Il2E7xc29fnFE8Y0J9kxOAS+wOP23hiCbXoJaWBY\n\tLK7xrTWRHy/Fwjb8cuJm2Ki9TIb7cwGQM0txIJHs="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"iJZivQQV\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<kcqhxhrnr6uzvj5d4ws7gkqmrny5hnqxvqs4ib76v3un7lpdq2@faffywfdvrpk>","References":"<20231124123713.22519-1-naush@raspberrypi.com>\n\t<20231124123713.22519-6-naush@raspberrypi.com>\n\t<kcqhxhrnr6uzvj5d4ws7gkqmrny5hnqxvqs4ib76v3un7lpdq2@faffywfdvrpk>","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tJacopo Mondi via libcamera-devel <libcamera-devel@lists.libcamera.org>, \n\tNaushir Patuck <naush@raspberrypi.com>","Date":"Tue, 28 Nov 2023 10:01:52 +0000","Message-ID":"<170116571290.630990.3499891286162848369@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags 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":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":28199,"web_url":"https://patchwork.libcamera.org/comment/28199/","msgid":"<CAEmqJPqr8Gtb7SMQWXOEj6sG1JbFY6+aXpRQT2Ksh_1ZcC9kZg@mail.gmail.com>","date":"2023-11-28T10:43:23","subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags for draft controls and properties","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"Hi Kieran,\n\nThank you for the feedback!\n\nOn Tue, 28 Nov 2023 at 10:01, Kieran Bingham\n<kieran.bingham@ideasonboard.com> wrote:\n>\n> Quoting Jacopo Mondi via libcamera-devel (2023-11-27 16:57:06)\n> > Hi Naush\n> >\n> > On Fri, Nov 24, 2023 at 12:37:11PM +0000, Naushir Patuck via libcamera-devel wrote:\n> > > Label draft controls and properties through the \"draft\" vendor tag\n> > > and deprecate the existing \"draft: true\" mechanism. This uses the new\n> > > vendor tags mechanism to place draft controls in the same\n> > > libcamera::controls::draft namespace and provide a defined control id\n> > > range for these controls. This requires moving all draft controls from\n> > > control_ids.yaml to control_ids_draft.yaml.\n> > >\n> > > One breaking change in this commit is that draft control ids also move\n> > > to the libcamera::controls::draft namespace from the existing\n> > > libcamera::controls namespace. This is desirable to avoid API breakages\n> > > when adding new libcamera controls. So, for example, the use of\n> > > controls::NOISE_REDUCTION_MODE will need to be replaced with\n> > > controls::draft::NOISE_REDUCTION_MODE.\n> > >\n> > > Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> >\n> > Thanks, I like this change!\n> >\n> > Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> >\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\n> > >\n> > > diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in\n> > > index 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 */\n> > > diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n> > > index 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> > >  }\n> > > diff --git a/include/libcamera/property_ids.h.in b/include/libcamera/property_ids.h.in\n> > > index 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}\n> > > diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp\n> > > index 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> > >                       break;\n> > >               }\n> > >\n> > > -             case controls::NOISE_REDUCTION_MODE:\n> > > +             case controls::draft::NOISE_REDUCTION_MODE:\n> > >                       /* Handled below in handleControls() */\n> > >                       libcameraMetadata_.set(controls::draft::NoiseReductionMode,\n> > >                                              ctrl.second.get<int32_t>());\n> > > diff --git a/src/ipa/rpi/vc4/vc4.cpp b/src/ipa/rpi/vc4/vc4.cpp\n> > > index 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> > >       for (auto const &ctrl : controls) {\n> > >               switch (ctrl.first) {\n> > > -             case controls::NOISE_REDUCTION_MODE: {\n> > > +             case controls::draft::NOISE_REDUCTION_MODE: {\n> > >                       RPiController::DenoiseAlgorithm *sdn = dynamic_cast<RPiController::DenoiseAlgorithm *>(\n> > >                               controller_.getAlgorithm(\"SDN\"));\n> > >                       /* Some platforms may have a combined \"denoise\" algorithm instead. */\n> > > diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in\n> > > index 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> > >  /**\n> > > diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml\n> > > index 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> > >  ...\n> > > diff --git a/src/libcamera/control_ids_draft.yaml b/src/libcamera/control_ids_draft.yaml\n> > > new file mode 100644\n> > > index 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>\n> Is the draft property still used? Or is this now conveyed as the vendor?\n\nNo, that's not used any more with this patch.  I'll remove it!\n\nRegards,\nNaush\n\n>\n> The parameter could always be dropped later.\n>\n> And I'm also a big fan of the draft controls being moved to their own\n> namespace and indexing which will lower ABI breakage in the future!\n>\n>\n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n>\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> > > +...\n> > > diff --git a/src/libcamera/property_ids.cpp.in b/src/libcamera/property_ids.cpp.in\n> > > index 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> > >  /**\n> > > diff --git a/src/libcamera/property_ids_core.yaml b/src/libcamera/property_ids_core.yaml\n> > > index 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> > >  ...\n> > > diff --git a/src/libcamera/property_ids_draft.yaml b/src/libcamera/property_ids_draft.yaml\n> > > new file mode 100644\n> > > index 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> > > +...\n> > > diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py\n> > > index 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:\n> > > diff --git a/src/py/libcamera/py_controls_generated.cpp.in b/src/py/libcamera/py_controls_generated.cpp.in\n> > > index 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> > >       auto controls = py::class_<PyControls>(m, \"controls\");\n> > > -     auto draft = py::class_<PyDraftControls>(controls, \"draft\");\n> > >  ${vendors_defs}\n> > >\n> > >  ${controls}\n> > > diff --git a/src/py/libcamera/py_properties_generated.cpp.in b/src/py/libcamera/py_properties_generated.cpp.in\n> > > index 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> > >       auto controls = py::class_<PyProperties>(m, \"properties\");\n> > > -     auto draft = py::class_<PyDraftProperties>(controls, \"draft\");\n> > >  ${vendors_defs}\n> > >\n> > >  ${controls}\n> > > diff --git a/utils/gen-controls.py b/utils/gen-controls.py\n> > > index 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> > > --\n> > > 2.34.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 2E531C31E9\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 28 Nov 2023 10:43:53 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7BE1E629C2;\n\tTue, 28 Nov 2023 11:43:52 +0100 (CET)","from mail-yw1-x1135.google.com (mail-yw1-x1135.google.com\n\t[IPv6:2607:f8b0:4864:20::1135])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 940BE61DA5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 28 Nov 2023 11:43:51 +0100 (CET)","by mail-yw1-x1135.google.com with SMTP id\n\t00721157ae682-5cfa65de9ecso25170877b3.2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 28 Nov 2023 02:43:51 -0800 (PST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1701168232;\n\tbh=wLFup/4hGaZys76KepWM7plyRsJrUOtv0huH26aGeyA=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=dk6ensgQQs1IUmi1OsHUL2TDV0vkmvvAmVYY7PEE2npjvX/CgtvowPMTn16vpQNfE\n\tuwbAryyq0HLLgrqmBnWvPvfWrxbYTidbKpG3elxzjpH08DvwZpKcH5q3NgKdFf9BoV\n\tx4wjYSzHJoQzuOKVrEF4/XS38i39PZpd+EnqHjroWvtoUAbGPkZu15gHg+gNK5nZD5\n\t//aQVYRJzbYPkNt0WbKuM7o+57IYTAsWrOD2DSRPFgPFxvs74TLoraDLW3Jc5guQAb\n\tvWwvG3rbn1oaVPd8OYfuedgU62YvmyibYRz5mGjusT7/OI27uYQrUX1pPvj8Lb8FRJ\n\tWNnj5cdzhwMiQ==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google; t=1701168230; x=1701773030;\n\tdarn=lists.libcamera.org; \n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=IACFMmjyK2UF8uWlCcLtaqhY6tRa5RqSq5TutaXK1BU=;\n\tb=p+lfsQMFbUjuEmRf85VA6IHhEJQzZbcT2Knavk32cn8nAepyR0oJ+rXxNduhBK2+uw\n\teDodRpxobmnRZBzl18og7SnCgTtxjSlbDkbuXMiN8sbWupYAVHer6UpgS8XCQg9uXmIp\n\tMH6y39uM83cvoyz8lvxH8Qi+mPd6uUG7pzocDVEy104Gvd/XqrPzHVvx2BtfQCDWrB5T\n\tLRc3LlxAb3t4uWC4vDQBKh4NUKJBuzMOKLeGrNFA3y9txJNmgDJieE7V5loxDtJr/iDr\n\t7ZBw2T2EnY8APpVTCwr9R8nKxNjtVKWxnhydk9ctVGDhZrKhRQ25forefP+43v4pmkEJ\n\tMAnw=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"p+lfsQMF\"; dkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1701168230; x=1701773030;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=IACFMmjyK2UF8uWlCcLtaqhY6tRa5RqSq5TutaXK1BU=;\n\tb=pcJHuqs3BtDPoDFynjgYzSvTFMWP19APLuPKB2y+eJPtV1cbF4maXoHiDC/D4LfTt5\n\tj65g0IBlzRhGoi0JV+gQWQ0gi4dKMjNZ9s9F7Iby2gt2XZ69TXaGBwpm0Jd54BJDw3YE\n\tGR1h/BL5WJV6yWd+u/y3vxYKB5rg9DmPl/mvI8O+HyeBOcJLPpEI7sobubPN8yD5RkUv\n\t/M9nLiaJ2RAIyveRHlptkZkVeG14Lwpu1wDz1Shj9fmKwEQBMvV22QpTgsau53neQVBQ\n\tGsosFNhz87ThLmqbK2xIoVsdIvO9I5a4WGPFGHWJcrEWxIM7Ox8u1bVcDrfOWj8A2fMi\n\tOgew==","X-Gm-Message-State":"AOJu0YzyTmfG9YGTxB91RBUeUXiC9gUpzsPRC2nNwMtSMcNrr2h42e0Z\n\tcwDY4vdFnklq8U46Jhm8dj8IrCG6+zTCB8DIVCJHvA==","X-Google-Smtp-Source":"AGHT+IHs6iprSlDL48lGr/oZPKXQejQl1n3YP1AiZS6rbvKtBkY2o4Y9bJsX4AmbsQW2gLOVi30luY57rUO/ZQIds9Y=","X-Received":"by 2002:a81:4c49:0:b0:5ca:ddd2:b03 with SMTP id\n\tz70-20020a814c49000000b005caddd20b03mr13165845ywa.5.1701168230002;\n\tTue, 28 Nov 2023 02:43:50 -0800 (PST)","MIME-Version":"1.0","References":"<20231124123713.22519-1-naush@raspberrypi.com>\n\t<20231124123713.22519-6-naush@raspberrypi.com>\n\t<kcqhxhrnr6uzvj5d4ws7gkqmrny5hnqxvqs4ib76v3un7lpdq2@faffywfdvrpk>\n\t<170116571290.630990.3499891286162848369@ping.linuxembedded.co.uk>","In-Reply-To":"<170116571290.630990.3499891286162848369@ping.linuxembedded.co.uk>","Date":"Tue, 28 Nov 2023 10:43:23 +0000","Message-ID":"<CAEmqJPqr8Gtb7SMQWXOEj6sG1JbFY6+aXpRQT2Ksh_1ZcC9kZg@mail.gmail.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Content-Type":"text/plain; charset=\"UTF-8\"","Subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags 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>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tJacopo Mondi via libcamera-devel <libcamera-devel@lists.libcamera.org>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":28213,"web_url":"https://patchwork.libcamera.org/comment/28213/","msgid":"<CAEmqJPraM2xMNvdczXMpHrx9fxt6wmvHU5JaO4mXvrbbcNWRRg@mail.gmail.com>","date":"2023-11-29T09:11:47","subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags for draft controls and properties","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"Hi Kieran and Jacopo,\n\nVersion 3 of this patch introduces a minor regression in the python\nbindings.  The fix is quite simple:\n\ndiff --git a/src/py/libcamera/gen-py-controls.py\nb/src/py/libcamera/gen-py-controls.py\nindex 55e0b4e8e3d6..d0150598ba43 100755\n--- a/src/py/libcamera/gen-py-controls.py\n+++ b/src/py/libcamera/gen-py-controls.py\n@@ -32,8 +32,9 @@ def generate_py(controls, mode):\n             name, ctrl = ctrls.popitem()\n\n             if vendor not in vendors and vendor != 'libcamera':\n-                vendors_class_def.append('class\nPy{}Controls\\n{{\\n}};\\n'.format(vendor))\n-                vendor_defs.append('\\tauto {} =\npy::class_<Py{}Controls>(controls, \\\"{}\\\");'.format(vendor, vendor,\nvendor))\n+                vendor_mode_str = f'{vendor}{mode.capitalize()}'\n+                vendors_class_def.append('class\nPy{}\\n{{\\n}};\\n'.format(vendor_mode_str))\n+                vendor_defs.append('\\tauto {} =\npy::class_<Py{}>(controls, \\\"{}\\\");'.format(vendor, vendor_mode_str,\nvendor))\n                 vendors.append(vendor)\n\nGiven you both have tagged this already, are you ok to keep your tags?\nIf so, I'll make a git-request-pull for this series.\n\nThanks,\nNaush\n\n\nOn Fri, 24 Nov 2023 at 12:37, Naushir Patuck <naush@raspberrypi.com> wrote:\n>\n> Label draft controls and properties through the \"draft\" vendor tag\n> and deprecate the existing \"draft: true\" mechanism. This uses the new\n> vendor tags mechanism to place draft controls in the same\n> libcamera::controls::draft namespace and provide a defined control id\n> range for these controls. This requires moving all draft controls from\n> control_ids.yaml to control_ids_draft.yaml.\n>\n> One breaking change in this commit is that draft control ids also move\n> to the libcamera::controls::draft namespace from the existing\n> libcamera::controls namespace. This is desirable to avoid API breakages\n> when adding new libcamera controls. So, for example, the use of\n> controls::NOISE_REDUCTION_MODE will need to be replaced with\n> controls::draft::NOISE_REDUCTION_MODE.\n>\n> Signed-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\n>\n> diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in\n> index 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 */\n> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n> index 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>  }\n> diff --git a/include/libcamera/property_ids.h.in b/include/libcamera/property_ids.h.in\n> index 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}\n> diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp\n> index 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>                         break;\n>                 }\n>\n> -               case controls::NOISE_REDUCTION_MODE:\n> +               case controls::draft::NOISE_REDUCTION_MODE:\n>                         /* Handled below in handleControls() */\n>                         libcameraMetadata_.set(controls::draft::NoiseReductionMode,\n>                                                ctrl.second.get<int32_t>());\n> diff --git a/src/ipa/rpi/vc4/vc4.cpp b/src/ipa/rpi/vc4/vc4.cpp\n> index 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>         for (auto const &ctrl : controls) {\n>                 switch (ctrl.first) {\n> -               case controls::NOISE_REDUCTION_MODE: {\n> +               case controls::draft::NOISE_REDUCTION_MODE: {\n>                         RPiController::DenoiseAlgorithm *sdn = dynamic_cast<RPiController::DenoiseAlgorithm *>(\n>                                 controller_.getAlgorithm(\"SDN\"));\n>                         /* Some platforms may have a combined \"denoise\" algorithm instead. */\n> diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in\n> index 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>  /**\n> diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml\n> index 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>  ...\n> diff --git a/src/libcamera/control_ids_draft.yaml b/src/libcamera/control_ids_draft.yaml\n> new file mode 100644\n> index 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> +...\n> diff --git a/src/libcamera/property_ids.cpp.in b/src/libcamera/property_ids.cpp.in\n> index 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>  /**\n> diff --git a/src/libcamera/property_ids_core.yaml b/src/libcamera/property_ids_core.yaml\n> index 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>  ...\n> diff --git a/src/libcamera/property_ids_draft.yaml b/src/libcamera/property_ids_draft.yaml\n> new file mode 100644\n> index 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> +...\n> diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py\n> index 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:\n> diff --git a/src/py/libcamera/py_controls_generated.cpp.in b/src/py/libcamera/py_controls_generated.cpp.in\n> index 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>         auto controls = py::class_<PyControls>(m, \"controls\");\n> -       auto draft = py::class_<PyDraftControls>(controls, \"draft\");\n>  ${vendors_defs}\n>\n>  ${controls}\n> diff --git a/src/py/libcamera/py_properties_generated.cpp.in b/src/py/libcamera/py_properties_generated.cpp.in\n> index 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>         auto controls = py::class_<PyProperties>(m, \"properties\");\n> -       auto draft = py::class_<PyDraftProperties>(controls, \"draft\");\n>  ${vendors_defs}\n>\n>  ${controls}\n> diff --git a/utils/gen-controls.py b/utils/gen-controls.py\n> index 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> --\n> 2.34.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 D7D0EBDE6B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 29 Nov 2023 09:12:20 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 381AB629B6;\n\tWed, 29 Nov 2023 10:12:20 +0100 (CET)","from mail-yw1-x112d.google.com (mail-yw1-x112d.google.com\n\t[IPv6:2607:f8b0:4864:20::112d])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7081961DA4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 29 Nov 2023 10:12:18 +0100 (CET)","by mail-yw1-x112d.google.com with SMTP id\n\t00721157ae682-5cdc0b3526eso5596097b3.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 29 Nov 2023 01:12:18 -0800 (PST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1701249140;\n\tbh=6iBFWukHGPU4KG4BTg7wOs9fn73eVukgP26jNG5E+Ro=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=KGK51uY5mxUw1ccQvCvnw4eAWxZsaiWNHYcVBRz7qQoXbvvk/g0eo8xLig1kt166T\n\t0jAWCrnT8iAYZJDKaIESJjBtBDAg1HgzAdcXEaYBPQwiKK1kBnSZ3/PXS5C3/JQg30\n\t+e+y/dayfyfs7CKyu8eiHesnHLj4V0NxXV7XKUCwAHBUkfAuW2T+YFfGbWeFsklQVl\n\teiaD6v1Xl7qOnxgTpbh19GCfjhBkY64OZSty9FGruz0GKmSrKVvKQ75p6Y9TV2V2/g\n\tyOLWzhrc2M/mf/FKwPTY3nO+J32eXWPlf85tGywe4OtmFAdSV+TSKFC4jwuZ3t6Xqh\n\tnMgqiapfD5IWg==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google; t=1701249137; x=1701853937;\n\tdarn=lists.libcamera.org; \n\th=to:subject:message-id:date:from:in-reply-to:references:mime-version\n\t:from:to:cc:subject:date:message-id:reply-to;\n\tbh=YF1hpTGiWclK+s9wST0plzJ6v6sgYIsw05UHfEdWyT8=;\n\tb=SccjzEmTNNN9UUu6yyI/rwU+YGxu4vPHYvIDqdrZH0eYKxePmqrpxw3ltNmFcklXHX\n\tFX5Lxj2sLUd4qas+0NtQSbW25Wc/SHbMlpr9Nmm6TbCStFve1s0hninEsZiN14gUH7sh\n\tkbfdIZE4OZLJNICzOxq3yjjlWT2QKc4i1HmBzgA++Y9FehN0c3fb3cRJNIBzdaQqH8xF\n\thb1K3MRpyo03gOyQUXcO6Un6HNOgSa65KPxVS75sJyTMMdQqCn/Kaukuq65eo6cY6lvY\n\tlqFDPSFV+KxtbFSkMEiviFEv/YtOKsanb7QusaR71ZkLEZwyoa+/o6pASRZbS3cvcbLb\n\t9l1A=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"SccjzEmT\"; dkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1701249137; x=1701853937;\n\th=to:subject:message-id:date:from:in-reply-to:references:mime-version\n\t:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;\n\tbh=YF1hpTGiWclK+s9wST0plzJ6v6sgYIsw05UHfEdWyT8=;\n\tb=UMKAQpWJYYKxsPAF3M0KLASSeHiSdpmsNhyiiJCxkK189fVaR7vqypI8Iq9anqTEKE\n\tIsLJRON0ke126xRHkf60lmScoiLTGB/Pcs2RR5eVQND2P/H3eORkeYNMhC0wvEkPhmmx\n\tlHzlJWLE2xR9N8N5//psQo2CJn2RPxjzDEJ0D29G3xVaUry/96Yct4jt3H0Chdg9x6jX\n\tMFgHLCtMJ95pOrw6l9U61q5mbO9rk9x1zp4n5jEhKiSW/1uQvCACp3dgymnXCuv6kiRV\n\ttASK0TdlZYVkD408tLbsZAoTO/hkuuulsscdPOlIpOkC9LsK8mMvW6ahhb90Q88y0Zp+\n\tcX+Q==","X-Gm-Message-State":"AOJu0Yw+384LVIZUeAKVZ8Lv7JK007knn24QKMQHBx1NQebZ/16baphl\n\tDu8lVz07GN2nH2n3GzRR6jLtgUHbe1R3JY5QV8VcbV2Lf5AQodmnmQs=","X-Google-Smtp-Source":"AGHT+IGoVaWneHgxtteO+fN7vmwHeGRoxORXoZ6heUI3wumHqhKstNbrFhE2/IlZyJuInWF6+tQpR5xA6qv44HtqKhA=","X-Received":"by 2002:a05:690c:4244:b0:5d1:9967:f1c0 with SMTP id\n\tgi4-20020a05690c424400b005d19967f1c0mr3038978ywb.22.1701249136147;\n\tWed, 29 Nov 2023 01:12:16 -0800 (PST)","MIME-Version":"1.0","References":"<20231124123713.22519-1-naush@raspberrypi.com>\n\t<20231124123713.22519-6-naush@raspberrypi.com>","In-Reply-To":"<20231124123713.22519-6-naush@raspberrypi.com>","Date":"Wed, 29 Nov 2023 09:11:47 +0000","Message-ID":"<CAEmqJPraM2xMNvdczXMpHrx9fxt6wmvHU5JaO4mXvrbbcNWRRg@mail.gmail.com>","To":"libcamera-devel@lists.libcamera.org, \n\tKieran Bingham <kieran.bingham@ideasonboard.com>, \n\tJacopo Mondi <jacopo.mondi@ideasonboard.com>","Content-Type":"text/plain; charset=\"UTF-8\"","Subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags 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>"}},{"id":28214,"web_url":"https://patchwork.libcamera.org/comment/28214/","msgid":"<170125037948.594465.4645861084462923513@ping.linuxembedded.co.uk>","date":"2023-11-29T09:32:59","subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags for draft controls and properties","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Naushir Patuck (2023-11-29 09:11:47)\n> Hi Kieran and Jacopo,\n> \n> Version 3 of this patch introduces a minor regression in the python\n> bindings.  The fix is quite simple:\n> \n> diff --git a/src/py/libcamera/gen-py-controls.py\n> b/src/py/libcamera/gen-py-controls.py\n> index 55e0b4e8e3d6..d0150598ba43 100755\n> --- a/src/py/libcamera/gen-py-controls.py\n> +++ b/src/py/libcamera/gen-py-controls.py\n> @@ -32,8 +32,9 @@ def generate_py(controls, mode):\n>              name, ctrl = ctrls.popitem()\n> \n>              if vendor not in vendors and vendor != 'libcamera':\n> -                vendors_class_def.append('class\n> Py{}Controls\\n{{\\n}};\\n'.format(vendor))\n> -                vendor_defs.append('\\tauto {} =\n> py::class_<Py{}Controls>(controls, \\\"{}\\\");'.format(vendor, vendor,\n> vendor))\n> +                vendor_mode_str = f'{vendor}{mode.capitalize()}'\n> +                vendors_class_def.append('class\n> Py{}\\n{{\\n}};\\n'.format(vendor_mode_str))\n> +                vendor_defs.append('\\tauto {} =\n> py::class_<Py{}>(controls, \\\"{}\\\");'.format(vendor, vendor_mode_str,\n> vendor))\n>                  vendors.append(vendor)\n> \n> Given you both have tagged this already, are you ok to keep your tags?\n> If so, I'll make a git-request-pull for this series.\n\nYes, that's fine with me.\n\n--\nKieran\n\n\n> \n> Thanks,\n> Naush\n> \n> \n> On Fri, 24 Nov 2023 at 12:37, Naushir Patuck <naush@raspberrypi.com> wrote:\n> >\n> > Label draft controls and properties through the \"draft\" vendor tag\n> > and deprecate the existing \"draft: true\" mechanism. This uses the new\n> > vendor tags mechanism to place draft controls in the same\n> > libcamera::controls::draft namespace and provide a defined control id\n> > range for these controls. This requires moving all draft controls from\n> > control_ids.yaml to control_ids_draft.yaml.\n> >\n> > One breaking change in this commit is that draft control ids also move\n> > to the libcamera::controls::draft namespace from the existing\n> > libcamera::controls namespace. This is desirable to avoid API breakages\n> > when adding new libcamera controls. So, for example, the use of\n> > controls::NOISE_REDUCTION_MODE will need to be replaced with\n> > controls::draft::NOISE_REDUCTION_MODE.\n> >\n> > Signed-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\n> >\n> > diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in\n> > index 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 */\n> > diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n> > index 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> >  }\n> > diff --git a/include/libcamera/property_ids.h.in b/include/libcamera/property_ids.h.in\n> > index 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}\n> > diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp\n> > index 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> >                         break;\n> >                 }\n> >\n> > -               case controls::NOISE_REDUCTION_MODE:\n> > +               case controls::draft::NOISE_REDUCTION_MODE:\n> >                         /* Handled below in handleControls() */\n> >                         libcameraMetadata_.set(controls::draft::NoiseReductionMode,\n> >                                                ctrl.second.get<int32_t>());\n> > diff --git a/src/ipa/rpi/vc4/vc4.cpp b/src/ipa/rpi/vc4/vc4.cpp\n> > index 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> >         for (auto const &ctrl : controls) {\n> >                 switch (ctrl.first) {\n> > -               case controls::NOISE_REDUCTION_MODE: {\n> > +               case controls::draft::NOISE_REDUCTION_MODE: {\n> >                         RPiController::DenoiseAlgorithm *sdn = dynamic_cast<RPiController::DenoiseAlgorithm *>(\n> >                                 controller_.getAlgorithm(\"SDN\"));\n> >                         /* Some platforms may have a combined \"denoise\" algorithm instead. */\n> > diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in\n> > index 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> >  /**\n> > diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml\n> > index 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> >  ...\n> > diff --git a/src/libcamera/control_ids_draft.yaml b/src/libcamera/control_ids_draft.yaml\n> > new file mode 100644\n> > index 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> > +...\n> > diff --git a/src/libcamera/property_ids.cpp.in b/src/libcamera/property_ids.cpp.in\n> > index 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> >  /**\n> > diff --git a/src/libcamera/property_ids_core.yaml b/src/libcamera/property_ids_core.yaml\n> > index 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> >  ...\n> > diff --git a/src/libcamera/property_ids_draft.yaml b/src/libcamera/property_ids_draft.yaml\n> > new file mode 100644\n> > index 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> > +...\n> > diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py\n> > index 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:\n> > diff --git a/src/py/libcamera/py_controls_generated.cpp.in b/src/py/libcamera/py_controls_generated.cpp.in\n> > index 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> >         auto controls = py::class_<PyControls>(m, \"controls\");\n> > -       auto draft = py::class_<PyDraftControls>(controls, \"draft\");\n> >  ${vendors_defs}\n> >\n> >  ${controls}\n> > diff --git a/src/py/libcamera/py_properties_generated.cpp.in b/src/py/libcamera/py_properties_generated.cpp.in\n> > index 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> >         auto controls = py::class_<PyProperties>(m, \"properties\");\n> > -       auto draft = py::class_<PyDraftProperties>(controls, \"draft\");\n> >  ${vendors_defs}\n> >\n> >  ${controls}\n> > diff --git a/utils/gen-controls.py b/utils/gen-controls.py\n> > index 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> > --\n> > 2.34.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 DC960BDE6B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 29 Nov 2023 09:33:03 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 572A661DA4;\n\tWed, 29 Nov 2023 10:33:03 +0100 (CET)","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 361B661DA4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 29 Nov 2023 10:33:02 +0100 (CET)","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 3D12C89D;\n\tWed, 29 Nov 2023 10:32:26 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1701250383;\n\tbh=n4r01dYixdB5Q+IqNjGTmR0JD39TOJl3OWDxuIUj15s=;\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:\n\tFrom;\n\tb=3l82YYzb+XOHwfexKanlYBZbINcBwmchHcp6giM4zLLVHZ97rJWtUGOZq4zgQHCAq\n\tOyQ5cbiVKUvHu8BUXkoN1zb5aHz48xOF1uQoY9U7CHkZfQrmuGpfTrjbpx4AdRDYTM\n\tHaDz0z8d9KETCDaX1loWJ6nEPNgG27ZM4GEzKfSxqW5RgpKWZ8kkfw0mthi+S0eSq5\n\t/AZA+NgoG7RJwylX4h4Lxsy0JlhQSAiirHGfEIJGqPzdYf8Xs8vrS2wCGj2GZeu2Jl\n\to0YDIL8J7M0ruYiX6S/4wXYiGOnl+YJ9UulDkbjoQQ5zn7/YPu+ZPBPSFic9bOtLut\n\t/w6jUX08FzQtQ==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1701250346;\n\tbh=n4r01dYixdB5Q+IqNjGTmR0JD39TOJl3OWDxuIUj15s=;\n\th=In-Reply-To:References:Subject:From:To:Date:From;\n\tb=jkGZbOfvGQcnN6KY4PC2l3Nrx1UMEXGWedoGPU+mvstrn49PwSo9B4+jXG+mMY091\n\t6NLDSlp3ZHHOTdm1lWmoqku+6/Es4DbSl7BrC0bSq5iiCocNxkFGNm4i39QH5BDHXH\n\tnr9gXLlBMdCUnxWrkqgbhEsQC8iEG9EPclrVo6iI="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"jkGZbOfv\"; dkim-atps=neutral","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<CAEmqJPraM2xMNvdczXMpHrx9fxt6wmvHU5JaO4mXvrbbcNWRRg@mail.gmail.com>","References":"<20231124123713.22519-1-naush@raspberrypi.com>\n\t<20231124123713.22519-6-naush@raspberrypi.com>\n\t<CAEmqJPraM2xMNvdczXMpHrx9fxt6wmvHU5JaO4mXvrbbcNWRRg@mail.gmail.com>","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tNaushir Patuck <naush@raspberrypi.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Wed, 29 Nov 2023 09:32:59 +0000","Message-ID":"<170125037948.594465.4645861084462923513@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags 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":"Kieran Bingham via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":28222,"web_url":"https://patchwork.libcamera.org/comment/28222/","msgid":"<20231130125752.GH8402@pendragon.ideasonboard.com>","date":"2023-11-30T12:57:52","subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags for draft controls and properties","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Naush,\n\nOn Wed, Nov 29, 2023 at 09:11:47AM +0000, Naushir Patuck via libcamera-devel wrote:\n> Hi Kieran and Jacopo,\n> \n> Version 3 of this patch introduces a minor regression in the python\n> bindings.  The fix is quite simple:\n> \n> diff --git a/src/py/libcamera/gen-py-controls.py\n> b/src/py/libcamera/gen-py-controls.py\n> index 55e0b4e8e3d6..d0150598ba43 100755\n> --- a/src/py/libcamera/gen-py-controls.py\n> +++ b/src/py/libcamera/gen-py-controls.py\n> @@ -32,8 +32,9 @@ def generate_py(controls, mode):\n>              name, ctrl = ctrls.popitem()\n> \n>              if vendor not in vendors and vendor != 'libcamera':\n> -                vendors_class_def.append('class Py{}Controls\\n{{\\n}};\\n'.format(vendor))\n> -                vendor_defs.append('\\tauto {} = py::class_<Py{}Controls>(controls, \\\"{}\\\");'.format(vendor, vendor, vendor))\n> +                vendor_mode_str = f'{vendor}{mode.capitalize()}'\n> +                vendors_class_def.append('class Py{}\\n{{\\n}};\\n'.format(vendor_mode_str))\n> +                vendor_defs.append('\\tauto {} = py::class_<Py{}>(controls, \\\"{}\\\");'.format(vendor, vendor_mode_str, vendor))\n>                  vendors.append(vendor)\n\nI tested this locally, and still see\n\n        auto controls = py::class_<PyControls>(m, \"controls\");\n        auto draft = py::class_<PydraftControls>(controls, \"draft\");\n        auto rpi = py::class_<PyrpiControls>(controls, \"rpi\");\n\nvs.\n\n        auto controls = py::class_<PyProperties>(m, \"properties\");\n        auto draft = py::class_<PydraftProperties>(controls, \"draft\");\n\nwhich looks good for the mode. I wonder though, shouldn't we also\ncapitalize the vendor name ?\n\n> Given you both have tagged this already, are you ok to keep your tags?\n> If so, I'll make a git-request-pull for this series.\n> \n> On Fri, 24 Nov 2023 at 12:37, Naushir Patuck <naush@raspberrypi.com> wrote:\n> >\n> > Label draft controls and properties through the \"draft\" vendor tag\n> > and deprecate the existing \"draft: true\" mechanism. This uses the new\n> > vendor tags mechanism to place draft controls in the same\n> > libcamera::controls::draft namespace and provide a defined control id\n> > range for these controls. This requires moving all draft controls from\n> > control_ids.yaml to control_ids_draft.yaml.\n> >\n> > One breaking change in this commit is that draft control ids also move\n> > to the libcamera::controls::draft namespace from the existing\n> > libcamera::controls namespace. This is desirable to avoid API breakages\n> > when adding new libcamera controls. So, for example, the use of\n> > controls::NOISE_REDUCTION_MODE will need to be replaced with\n> > controls::draft::NOISE_REDUCTION_MODE.\n> >\n> > Signed-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\n> >\n> > diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in\n> > index 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 */\n> > diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n> > index 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> >  }\n> > diff --git a/include/libcamera/property_ids.h.in b/include/libcamera/property_ids.h.in\n> > index 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}\n> > diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp\n> > index 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> >                         break;\n> >                 }\n> >\n> > -               case controls::NOISE_REDUCTION_MODE:\n> > +               case controls::draft::NOISE_REDUCTION_MODE:\n> >                         /* Handled below in handleControls() */\n> >                         libcameraMetadata_.set(controls::draft::NoiseReductionMode,\n> >                                                ctrl.second.get<int32_t>());\n> > diff --git a/src/ipa/rpi/vc4/vc4.cpp b/src/ipa/rpi/vc4/vc4.cpp\n> > index 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> >         for (auto const &ctrl : controls) {\n> >                 switch (ctrl.first) {\n> > -               case controls::NOISE_REDUCTION_MODE: {\n> > +               case controls::draft::NOISE_REDUCTION_MODE: {\n> >                         RPiController::DenoiseAlgorithm *sdn = dynamic_cast<RPiController::DenoiseAlgorithm *>(\n> >                                 controller_.getAlgorithm(\"SDN\"));\n> >                         /* Some platforms may have a combined \"denoise\" algorithm instead. */\n> > diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in\n> > index 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> >  /**\n> > diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml\n> > index 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> >  ...\n> > diff --git a/src/libcamera/control_ids_draft.yaml b/src/libcamera/control_ids_draft.yaml\n> > new file mode 100644\n> > index 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> > +...\n> > diff --git a/src/libcamera/property_ids.cpp.in b/src/libcamera/property_ids.cpp.in\n> > index 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> >  /**\n> > diff --git a/src/libcamera/property_ids_core.yaml b/src/libcamera/property_ids_core.yaml\n> > index 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> >  ...\n> > diff --git a/src/libcamera/property_ids_draft.yaml b/src/libcamera/property_ids_draft.yaml\n> > new file mode 100644\n> > index 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> > +...\n> > diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py\n> > index 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:\n> > diff --git a/src/py/libcamera/py_controls_generated.cpp.in b/src/py/libcamera/py_controls_generated.cpp.in\n> > index 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> >         auto controls = py::class_<PyControls>(m, \"controls\");\n> > -       auto draft = py::class_<PyDraftControls>(controls, \"draft\");\n> >  ${vendors_defs}\n> >\n> >  ${controls}\n> > diff --git a/src/py/libcamera/py_properties_generated.cpp.in b/src/py/libcamera/py_properties_generated.cpp.in\n> > index 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> >         auto controls = py::class_<PyProperties>(m, \"properties\");\n> > -       auto draft = py::class_<PyDraftProperties>(controls, \"draft\");\n> >  ${vendors_defs}\n> >\n> >  ${controls}\n> > diff --git a/utils/gen-controls.py b/utils/gen-controls.py\n> > index 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> >","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 B4B72C31E9\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 30 Nov 2023 12:57:49 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 13248629C2;\n\tThu, 30 Nov 2023 13:57:49 +0100 (CET)","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 D8AEA629B6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 30 Nov 2023 13:57:46 +0100 (CET)","from pendragon.ideasonboard.com (213-243-189-158.bb.dnainternet.fi\n\t[213.243.189.158])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id CB42589D;\n\tThu, 30 Nov 2023 13:57:09 +0100 (CET)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1701349069;\n\tbh=wNoeOGNij/BlOZoNEZ7vlM9xIzxyq65fzMBwcgb/3AM=;\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=A+w/burhbzvMAzFMPlTH8NUZ4v+DSO+yMUvEVy8UQkGGMv0t+YqBPez6LmEfs3QUB\n\tLsU2EYE47wFme3nTnKEESXpmwg38V9J5rPYv4Zb5oKp/v620Ds52r3L+yQe86xP3xi\n\tRRbQiaNuTe+hxWTABr50HK8DSCgsjGmp2mcczXZrHQ7O4UT0cB2StSH4tzz7sseX2w\n\tvw7NoiD94jXMLHyd6ItmTJt+PZKlaw/WkmeeDN3mtf6nUTBGwmJ0HTIe8G9/eVPg29\n\ttYWM19eCHOYjMFXTFe8i1QgCZS3x7hl35bUlaCB2ZbvPmc3MPdBT2uptV21x1wVoAe\n\t6tzXegtuAwYYw==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1701349030;\n\tbh=wNoeOGNij/BlOZoNEZ7vlM9xIzxyq65fzMBwcgb/3AM=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=hBWmbJrT1Wo/CGj87AfTfKDShcdmcD0WacgCzk9mihO8ZULTzLMXqIFXwBChw7ldC\n\t2AufWxFNSgbQBe5wFeAu0yWxTJgXSD9l2ETQBkp0N6XlnOt9vQ0WEaoriua4A5felQ\n\tll3kysWAGlwIjwwEvnc9jI/ffkajM/4GYTYEY5Fs="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"hBWmbJrT\"; dkim-atps=neutral","Date":"Thu, 30 Nov 2023 14:57:52 +0200","To":"Naushir Patuck <naush@raspberrypi.com>","Message-ID":"<20231130125752.GH8402@pendragon.ideasonboard.com>","References":"<20231124123713.22519-1-naush@raspberrypi.com>\n\t<20231124123713.22519-6-naush@raspberrypi.com>\n\t<CAEmqJPraM2xMNvdczXMpHrx9fxt6wmvHU5JaO4mXvrbbcNWRRg@mail.gmail.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<CAEmqJPraM2xMNvdczXMpHrx9fxt6wmvHU5JaO4mXvrbbcNWRRg@mail.gmail.com>","Subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags 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":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":28226,"web_url":"https://patchwork.libcamera.org/comment/28226/","msgid":"<CAEmqJPqtdjbKE56wiTJQU_+Y6r5PPx9WPJ1PEVmAwbgP0kPPhw@mail.gmail.com>","date":"2023-11-30T13:43:21","subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags for draft controls and properties","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"Hi Laurent,\n\nOn Thu, 30 Nov 2023 at 12:57, Laurent Pinchart\n<laurent.pinchart@ideasonboard.com> wrote:\n>\n> Hi Naush,\n>\n> On Wed, Nov 29, 2023 at 09:11:47AM +0000, Naushir Patuck via libcamera-devel wrote:\n> > Hi Kieran and Jacopo,\n> >\n> > Version 3 of this patch introduces a minor regression in the python\n> > bindings.  The fix is quite simple:\n> >\n> > diff --git a/src/py/libcamera/gen-py-controls.py\n> > b/src/py/libcamera/gen-py-controls.py\n> > index 55e0b4e8e3d6..d0150598ba43 100755\n> > --- a/src/py/libcamera/gen-py-controls.py\n> > +++ b/src/py/libcamera/gen-py-controls.py\n> > @@ -32,8 +32,9 @@ def generate_py(controls, mode):\n> >              name, ctrl = ctrls.popitem()\n> >\n> >              if vendor not in vendors and vendor != 'libcamera':\n> > -                vendors_class_def.append('class Py{}Controls\\n{{\\n}};\\n'.format(vendor))\n> > -                vendor_defs.append('\\tauto {} = py::class_<Py{}Controls>(controls, \\\"{}\\\");'.format(vendor, vendor, vendor))\n> > +                vendor_mode_str = f'{vendor}{mode.capitalize()}'\n> > +                vendors_class_def.append('class Py{}\\n{{\\n}};\\n'.format(vendor_mode_str))\n> > +                vendor_defs.append('\\tauto {} = py::class_<Py{}>(controls, \\\"{}\\\");'.format(vendor, vendor_mode_str, vendor))\n> >                  vendors.append(vendor)\n>\n> I tested this locally, and still see\n>\n>         auto controls = py::class_<PyControls>(m, \"controls\");\n>         auto draft = py::class_<PydraftControls>(controls, \"draft\");\n>         auto rpi = py::class_<PyrpiControls>(controls, \"rpi\");\n>\n> vs.\n>\n>         auto controls = py::class_<PyProperties>(m, \"properties\");\n>         auto draft = py::class_<PydraftProperties>(controls, \"draft\");\n>\n> which looks good for the mode. I wonder though, shouldn't we also\n> capitalize the vendor name ?\n\nYes, I'll make that change.\n\n>\n> > Given you both have tagged this already, are you ok to keep your tags?\n> > If so, I'll make a git-request-pull for this series.\n> >\n> > On Fri, 24 Nov 2023 at 12:37, Naushir Patuck <naush@raspberrypi.com> wrote:\n> > >\n> > > Label draft controls and properties through the \"draft\" vendor tag\n> > > and deprecate the existing \"draft: true\" mechanism. This uses the new\n> > > vendor tags mechanism to place draft controls in the same\n> > > libcamera::controls::draft namespace and provide a defined control id\n> > > range for these controls. This requires moving all draft controls from\n> > > control_ids.yaml to control_ids_draft.yaml.\n> > >\n> > > One breaking change in this commit is that draft control ids also move\n> > > to the libcamera::controls::draft namespace from the existing\n> > > libcamera::controls namespace. This is desirable to avoid API breakages\n> > > when adding new libcamera controls. So, for example, the use of\n> > > controls::NOISE_REDUCTION_MODE will need to be replaced with\n> > > controls::draft::NOISE_REDUCTION_MODE.\n> > >\n> > > Signed-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\n> > >\n> > > diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in\n> > > index 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 */\n> > > diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n> > > index 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> > >  }\n> > > diff --git a/include/libcamera/property_ids.h.in b/include/libcamera/property_ids.h.in\n> > > index 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}\n> > > diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp\n> > > index 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> > >                         break;\n> > >                 }\n> > >\n> > > -               case controls::NOISE_REDUCTION_MODE:\n> > > +               case controls::draft::NOISE_REDUCTION_MODE:\n> > >                         /* Handled below in handleControls() */\n> > >                         libcameraMetadata_.set(controls::draft::NoiseReductionMode,\n> > >                                                ctrl.second.get<int32_t>());\n> > > diff --git a/src/ipa/rpi/vc4/vc4.cpp b/src/ipa/rpi/vc4/vc4.cpp\n> > > index 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> > >         for (auto const &ctrl : controls) {\n> > >                 switch (ctrl.first) {\n> > > -               case controls::NOISE_REDUCTION_MODE: {\n> > > +               case controls::draft::NOISE_REDUCTION_MODE: {\n> > >                         RPiController::DenoiseAlgorithm *sdn = dynamic_cast<RPiController::DenoiseAlgorithm *>(\n> > >                                 controller_.getAlgorithm(\"SDN\"));\n> > >                         /* Some platforms may have a combined \"denoise\" algorithm instead. */\n> > > diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in\n> > > index 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> > >  /**\n> > > diff --git a/src/libcamera/control_ids_core.yaml b/src/libcamera/control_ids_core.yaml\n> > > index 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> > >  ...\n> > > diff --git a/src/libcamera/control_ids_draft.yaml b/src/libcamera/control_ids_draft.yaml\n> > > new file mode 100644\n> > > index 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> > > +...\n> > > diff --git a/src/libcamera/property_ids.cpp.in b/src/libcamera/property_ids.cpp.in\n> > > index 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> > >  /**\n> > > diff --git a/src/libcamera/property_ids_core.yaml b/src/libcamera/property_ids_core.yaml\n> > > index 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> > >  ...\n> > > diff --git a/src/libcamera/property_ids_draft.yaml b/src/libcamera/property_ids_draft.yaml\n> > > new file mode 100644\n> > > index 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> > > +...\n> > > diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py\n> > > index 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:\n> > > diff --git a/src/py/libcamera/py_controls_generated.cpp.in b/src/py/libcamera/py_controls_generated.cpp.in\n> > > index 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> > >         auto controls = py::class_<PyControls>(m, \"controls\");\n> > > -       auto draft = py::class_<PyDraftControls>(controls, \"draft\");\n> > >  ${vendors_defs}\n> > >\n> > >  ${controls}\n> > > diff --git a/src/py/libcamera/py_properties_generated.cpp.in b/src/py/libcamera/py_properties_generated.cpp.in\n> > > index 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> > >         auto controls = py::class_<PyProperties>(m, \"properties\");\n> > > -       auto draft = py::class_<PyDraftProperties>(controls, \"draft\");\n> > >  ${vendors_defs}\n> > >\n> > >  ${controls}\n> > > diff --git a/utils/gen-controls.py b/utils/gen-controls.py\n> > > index 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>\n> --\n> Regards,\n>\n> Laurent Pinchart","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 B4397BDE6B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 30 Nov 2023 13:43:59 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3DDF661DA0;\n\tThu, 30 Nov 2023 14:43:59 +0100 (CET)","from mail-yw1-x1135.google.com (mail-yw1-x1135.google.com\n\t[IPv6:2607:f8b0:4864:20::1135])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4CC5861DA0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 30 Nov 2023 14:43:57 +0100 (CET)","by mail-yw1-x1135.google.com with SMTP id\n\t00721157ae682-5d36fddbe3cso4557007b3.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 30 Nov 2023 05:43:57 -0800 (PST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1701351839;\n\tbh=UYO8golfxHIa2XsX3zmxpufFzlpbIiOGhbGgUzshRK4=;\n\th=References:In-Reply-To:Date:To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=QWqjwRBJ3e6WxUeMrVR1GmXi9uU99p3sFHnkd81CHikmOYG6wJlKlXGKP51tQVHnK\n\t1oHwnMugWcK/h7xpnFS5BRD0fIkhelqhOG4zC+ExYvBN1y6dvlBfrWqL61kBQXmrpi\n\tX6qMBL2JP1klkn2MA1z1JSKv+Er09gNSVMxFR8FidN7yZJPqhtARJLgs1iXiDiciR4\n\tCwXFUsVAFoKAgrpP6oT/tRZXsnA0pIP7zFtCE0pcx6SW6H7uj++LmRP4hor2cAkRTL\n\tdviwCN2LwVfq/eSzK8wD1eO4rDELIfQf+Ub3G1+Jfh4u4dzkKOs/js9+Bt0Bi/z0XN\n\tAgXEbElpuAdyA==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google; t=1701351836; x=1701956636;\n\tdarn=lists.libcamera.org; \n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:from:to:cc:subject:date:message-id:reply-to;\n\tbh=F4g+URc+d44OBLqhzB5wR5A6Gz1SGu2UvQHKAZg6kAw=;\n\tb=OmCjMtlqqm/eFowe3yglO1rHhK+ompI8Md3P7i3sArbgted328RmRkRP3iYdXQ+sJQ\n\tKNz7BADG/Doz2c7ED3qMk5Tpx0uVD2+nf2g14LF6raZwbgzy/59KLsVOVu0aIoUq2RMt\n\t+h/j/UICVhxJaetQ1PoP6e+bIfuQkU1LIwt46tz81Y5ErVK3QUt7j9U/86I3UsOz5ys+\n\tTiC1FE4ikzSxidqswBmbX3b2zrHRL4zbdtPtooASi1QXUOTx0hc1liY6LG24uTlhyNv5\n\t+j27wjlR/VWt7teB9TerJPxhsQPZ5m02Psq/ZGsjyHolQmGOUDpguyfVqSwkVOEhYPOg\n\t8zbQ=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"OmCjMtlq\"; dkim-atps=neutral","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1701351836; x=1701956636;\n\th=cc:to:subject:message-id:date:from:in-reply-to:references\n\t:mime-version:x-gm-message-state:from:to:cc:subject:date:message-id\n\t:reply-to;\n\tbh=F4g+URc+d44OBLqhzB5wR5A6Gz1SGu2UvQHKAZg6kAw=;\n\tb=mq2TH0E4qtC5qXHLeV0M67p1YthbcYcOUyoZPeUEk5jgVnXvcM0nrNKu8K3G6uc6AE\n\tLvuBx7aQMbBd9hl6ABnqvTh63fyPGeQw2rirIU3gw03IC7r7THjxWn/ZKERan7XKLjPf\n\ta2QBdKCJEnew41oGbykmTIyyArL9mszWng5W7Zl/dFIWoWFi8do6Mo7gpNeUC7cHaDYS\n\t79MEeMe9A+HVLqeX1T3eNzC8fR1g3ie78qcyixqyBVYX77pyDCYQ269IGeqWAlz+GuBi\n\tKYW6JXNSeDnv4J8ketpLlKqPvEYr33Mb2mPgpelxqQ3lXIx0l0Vm84Mr2amMleLhBQOB\n\t21KQ==","X-Gm-Message-State":"AOJu0YxKWkTaYg+dV3aSoQWAELK2J/P3z/MO4+k+EdFCL7symGX+yH92\n\tZe2QFlEdCsW+eRrgWYLjuLpsR2QxNk6TBYM+fbIs0s8qVf/WgiA4OJQ=","X-Google-Smtp-Source":"AGHT+IGJcaJjRXmHV5eVuuTYOiQOGNme62Y4jS30tWKSTi7zftv/JKHblal+/rV0DA5TGbcfZQ445AfE+UCMMzk1WNk=","X-Received":"by 2002:a05:690c:2e02:b0:5d1:f8ed:b4c5 with SMTP id\n\tet2-20020a05690c2e0200b005d1f8edb4c5mr6610429ywb.42.1701351835693;\n\tThu, 30 Nov 2023 05:43:55 -0800 (PST)","MIME-Version":"1.0","References":"<20231124123713.22519-1-naush@raspberrypi.com>\n\t<20231124123713.22519-6-naush@raspberrypi.com>\n\t<CAEmqJPraM2xMNvdczXMpHrx9fxt6wmvHU5JaO4mXvrbbcNWRRg@mail.gmail.com>\n\t<20231130125752.GH8402@pendragon.ideasonboard.com>","In-Reply-To":"<20231130125752.GH8402@pendragon.ideasonboard.com>","Date":"Thu, 30 Nov 2023 13:43:21 +0000","Message-ID":"<CAEmqJPqtdjbKE56wiTJQU_+Y6r5PPx9WPJ1PEVmAwbgP0kPPhw@mail.gmail.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Content-Type":"text/plain; charset=\"UTF-8\"","Subject":"Re: [libcamera-devel] [PATCH v3 5/7] libcamera: controls: Use\n\tvendor tags 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>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]