From patchwork Tue Nov 21 14:53:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 19216 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id B6B7CC3220 for ; Tue, 21 Nov 2023 14:53:58 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 66FC661DAE; Tue, 21 Nov 2023 15:53:58 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1700578438; bh=0ZwD60nqfQdCjbTmeCHK41qSqQVFFupXjBsbejdEcjE=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=TvlbzFWarFTBeNLESFwT50WRJWS7CRhpNXaU2uqxd3985UI3pvPd5GG0NEN7ccEWB FOo+eQh0lQryFtiB1ine8tfDYIAOhy4ISys9eqYGfiPJ8PHhxzvCAk1AVy1KuhndF9 d+UkRQyPg1wa/SY/ofs4LyodqA7RVNJ6LF3kT3B4vw6V2xiML+q+/gaoBLAUIEQ43q 1baDnQwFHA5i5jqaF0bRsCjWR7lIwpTwKGcJojYmOcsx9g39ZSdtSjBrECb7oTxoOR zJZ+WiuDK4RV21CDuap+2LREhQXvDy8Et3qqAzAODhIUqOwwnffQzutXyCgnHwEgih 7I1Jyj0Sz5Buw== Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0733861DAE for ; Tue, 21 Nov 2023 15:53:56 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="EzTY+16Z"; dkim-atps=neutral Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-4083f613272so29938035e9.1 for ; Tue, 21 Nov 2023 06:53:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1700578435; x=1701183235; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kmCEYPhSIOTDoj0D376ggapXdJz5HSBDUyxBY9LzPKc=; b=EzTY+16Z9AgpxY/aBu4h+3M1aCYffZTfHHVVQN8aLbfWT97u32Fs2osyjrEhWkC+eX EyODVDfZwV42z7ZynvmhilWAVBH/rAh88op6qMWU3j2ydSkype2yJqCDYknihncKQr0O jrTbxDoJorvjU975G6hQ6fIlPcMNNi6yz3/duxjAndfUinrsrfUS71xe/o1hyImvSeB4 /cYNW+N/CGixNFUIbtVW0YUGFU9Nkity2HAwo9FXyBzv6gJu85+zflx/0MnyDAkZrzsg 6HfVY1t46qGMEtmcznd575wU1Sk2Mq1iXLeh4CN4piqVLR16tt77NIr1ptakyM7Pk5U4 +UVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700578435; x=1701183235; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kmCEYPhSIOTDoj0D376ggapXdJz5HSBDUyxBY9LzPKc=; b=RlTPXdC1aD8ggYGG35/F31c4oKTzEBeXeqDU+PtUH3sLtwFNWrK/mrsFGnFq65mP0y G/Bl3TEzXejIKK2HJ9yiJV5uhKOonkxBK9amf/tm+sKinV5Zp/146eRsD0R4WFxFJmvQ TNEejpuT2Q9XVS3fP8iKYHxsvq3MjhZuCGU3zK+sKP4rMyvQ2ohwIbq3WkfkL11ZCyy2 OGgcevdtPDTcQX1Zhh4zFeoPlF1hE5HRhadcXtVMRJJQ6mT3ZJEL5JqYdqflAUr9Q7EW +g+OMhfNsgKOkgPP3W+dBIE41LKz+G2S2X+u6pmQSHSV5ptM2qeFBD+FC7c8ahms6Ga8 1fHQ== X-Gm-Message-State: AOJu0YxaxBaXzLNlB/FAad+ZG/+TWgj5RVvYI2a4K5s/kBCIkGS5iaQx IZcNxw8FimnUjG3DKtHkvuEmoIxHZ5SG5dlP16Q1BQ== X-Google-Smtp-Source: AGHT+IF9WXMKB4HaUvEDig61EuuRHwY++XL317WIpkteOWTLMYEGzc/mHVJMgzCP4AovcGI2/tQpEQ== X-Received: by 2002:a05:600c:1c9b:b0:40b:2982:5cc0 with SMTP id k27-20020a05600c1c9b00b0040b29825cc0mr1539732wms.24.1700578435079; Tue, 21 Nov 2023 06:53:55 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id h18-20020a05600c351200b004063ea92492sm17570968wmq.22.2023.11.21.06.53.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Nov 2023 06:53:54 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Tue, 21 Nov 2023 14:53:45 +0000 Message-Id: <20231121145350.5956-2-naush@raspberrypi.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231121145350.5956-1-naush@raspberrypi.com> References: <20231121145350.5956-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 1/6] controls: Add vendor control/property support to generation scripts X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add support for vendor specific controls and properties to libcamera. The controls/properties are defined by a "vendor" tag in the YAML control description file, for example: vendor: rpi controls: - MyExampleControl: type: string description: | Test for libcamera vendor specific controls. This will now generate a control id in the libcamera::controls::rpi namespace, ensuring no id conflict between different vendors, core or draft libcamera controls. Similarly, a ControlIdMap control is generated in the libcamera::controls::rpi namespace. A #define LIBCAMERA_HAS_RPI_VENDOR_CONTROLS is also generated to allow applications to conditionally compile code if the specific vendor controls are present. For the python bindings, the control is available with libcamera.controls.rpi.MyExampleControl. The above controls example applies similarly to properties. Existing libcamera controls defined in control_ids.yaml are given the "libcamera" vendor tag. A new --mode flag is added to gen-controls.py to specify the mode of operation, either 'controls' or 'properties' to allow the code generator to correctly set the #define string. Signed-off-by: Naushir Patuck --- include/libcamera/control_ids.h.in | 2 + include/libcamera/meson.build | 15 +- include/libcamera/property_ids.h.in | 2 + src/libcamera/control_ids.cpp.in | 6 + src/libcamera/control_ids.yaml | 1 + src/libcamera/meson.build | 5 +- src/libcamera/property_ids.cpp.in | 6 + src/libcamera/property_ids.yaml | 1 + src/py/libcamera/gen-py-controls.py | 75 +++++---- src/py/libcamera/py_controls_generated.cpp.in | 3 + .../libcamera/py_properties_generated.cpp.in | 3 + utils/gen-controls.py | 144 ++++++++++++++---- 12 files changed, 194 insertions(+), 69 deletions(-) diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in index 0718a8886f6c..c97b09a82450 100644 --- a/include/libcamera/control_ids.h.in +++ b/include/libcamera/control_ids.h.in @@ -32,6 +32,8 @@ ${draft_controls} } /* namespace draft */ +${vendor_controls} + } /* namespace controls */ } /* namespace libcamera */ diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index a24c50d66a82..2c8c0258c95e 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -32,20 +32,21 @@ install_headers(libcamera_public_headers, libcamera_headers_install_dir = get_option('includedir') / libcamera_include_dir -# control_ids.h and property_ids.h -control_source_files = [ - 'control_ids', - 'property_ids', -] +# control_ids.h and property_ids.h and associated modes +control_source_files = { + 'control_ids': 'controls', + 'property_ids': 'properties', +} control_headers = [] -foreach header : control_source_files +foreach header, mode : control_source_files input_files = files('../../src/libcamera/' + header +'.yaml', header + '.h.in') control_headers += custom_target(header + '_h', input : input_files, output : header + '.h', - command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@'], + command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@', + '--mode', mode], install : true, install_dir : libcamera_headers_install_dir) endforeach diff --git a/include/libcamera/property_ids.h.in b/include/libcamera/property_ids.h.in index ff0194083af0..47c5d6bf2e28 100644 --- a/include/libcamera/property_ids.h.in +++ b/include/libcamera/property_ids.h.in @@ -31,6 +31,8 @@ ${draft_controls} extern const ControlIdMap properties; +${vendor_controls} + } /* namespace properties */ } /* namespace libcamera */ diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in index 5fb1c2c30558..d26eb930b30c 100644 --- a/src/libcamera/control_ids.cpp.in +++ b/src/libcamera/control_ids.cpp.in @@ -33,6 +33,8 @@ ${draft_controls_doc} } /* namespace draft */ +${vendor_controls_doc} + #ifndef __DOXYGEN__ /* * Keep the controls definitions hidden from doxygen as it incorrectly parses @@ -45,6 +47,8 @@ namespace draft { ${draft_controls_def} } /* namespace draft */ + +${vendor_controls_def} #endif /** @@ -57,6 +61,8 @@ extern const ControlIdMap controls { ${controls_map} }; +${vendor_controls_map} + } /* namespace controls */ } /* namespace libcamera */ diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml index 5827d7ecef49..ff74ce1deedb 100644 --- a/src/libcamera/control_ids.yaml +++ b/src/libcamera/control_ids.yaml @@ -6,6 +6,7 @@ --- # Unless otherwise stated, all controls are bi-directional, i.e. they can be # set through Request::controls() and returned out through Request::metadata(). +vendor: libcamera controls: - AeEnable: type: bool diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index d0e26f6b4141..e49bf850b355 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -127,12 +127,13 @@ endif control_sources = [] -foreach source : control_source_files +foreach source, mode : control_source_files input_files = files(source +'.yaml', source + '.cpp.in') control_sources += custom_target(source + '_cpp', input : input_files, output : source + '.cpp', - command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@']) + command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@', + '--mode', mode]) endforeach libcamera_sources += control_sources diff --git a/src/libcamera/property_ids.cpp.in b/src/libcamera/property_ids.cpp.in index f917e3349766..ddbe714c3f00 100644 --- a/src/libcamera/property_ids.cpp.in +++ b/src/libcamera/property_ids.cpp.in @@ -32,6 +32,8 @@ ${draft_controls_doc} } /* namespace draft */ +${vendor_controls_doc} + #ifndef __DOXYGEN__ /* * Keep the properties definitions hidden from doxygen as it incorrectly parses @@ -44,6 +46,8 @@ namespace draft { ${draft_controls_def} } /* namespace draft */ + +${vendor_controls_def} #endif /** @@ -53,6 +57,8 @@ extern const ControlIdMap properties { ${controls_map} }; +${vendor_controls_map} + } /* namespace properties */ } /* namespace libcamera */ diff --git a/src/libcamera/property_ids.yaml b/src/libcamera/property_ids.yaml index f35563842a5a..45f3609b4236 100644 --- a/src/libcamera/property_ids.yaml +++ b/src/libcamera/property_ids.yaml @@ -4,6 +4,7 @@ # %YAML 1.1 --- +vendor: libcamera controls: - Location: type: int32_t diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py index 9948c41e42b1..8f14cdafe313 100755 --- a/src/py/libcamera/gen-py-controls.py +++ b/src/py/libcamera/gen-py-controls.py @@ -24,45 +24,59 @@ def find_common_prefix(strings): def generate_py(controls, mode): out = '' - for ctrl in controls: - name, ctrl = ctrl.popitem() - - if ctrl.get('draft'): - ns = 'libcamera::{}::draft::'.format(mode) - container = 'draft' - else: - ns = 'libcamera::{}::'.format(mode) - container = 'controls' + vendors_class_def = [] + vendor_defs = [] + vendors = [] + for vendor, ctrl_list in controls.items(): + for ctrls in ctrl_list: + name, ctrl = ctrls.popitem() + + if vendor not in vendors: + vendors_class_def.append('class Py{}Controls\n{{\n}};\n'.format(vendor)) + vendor_defs.append('\tauto {} = py::class_(controls, \"{}\");'.format(vendor, vendor, vendor)) + vendors.append(vendor) + + if ctrl.get('draft'): + ns = 'libcamera::{}::draft::'.format(mode) + container = 'draft' + elif vendor != 'libcamera': + ns = 'libcamera::{}::{}::'.format(mode, vendor) + container = vendor + else: + ns = 'libcamera::{}::'.format(mode) + container = 'controls' - out += f'\t{container}.def_readonly_static("{name}", static_cast(&{ns}{name}));\n\n' + out += f'\t{container}.def_readonly_static("{name}", static_cast(&{ns}{name}));\n\n' - enum = ctrl.get('enum') - if not enum: - continue + enum = ctrl.get('enum') + if not enum: + continue - cpp_enum = name + 'Enum' + cpp_enum = name + 'Enum' - out += '\tpy::enum_<{}{}>({}, \"{}\")\n'.format(ns, cpp_enum, container, cpp_enum) + out += '\tpy::enum_<{}{}>({}, \"{}\")\n'.format(ns, cpp_enum, container, cpp_enum) - if mode == 'controls': - # Adjustments for controls - if name == 'LensShadingMapMode': - prefix = 'LensShadingMapMode' + if mode == 'controls': + # Adjustments for controls + if name == 'LensShadingMapMode': + prefix = 'LensShadingMapMode' + else: + prefix = find_common_prefix([e['name'] for e in enum]) else: + # Adjustments for properties prefix = find_common_prefix([e['name'] for e in enum]) - else: - # Adjustments for properties - prefix = find_common_prefix([e['name'] for e in enum]) - for entry in enum: - cpp_enum = entry['name'] - py_enum = entry['name'][len(prefix):] + for entry in enum: + cpp_enum = entry['name'] + py_enum = entry['name'][len(prefix):] - out += '\t\t.value(\"{}\", {}{})\n'.format(py_enum, ns, cpp_enum) + out += '\t\t.value(\"{}\", {}{})\n'.format(py_enum, ns, cpp_enum) - out += '\t;\n\n' + out += '\t;\n\n' - return {'controls': out} + return {'controls': out, + 'vendors_class_def': '\n'.join(vendors_class_def), + 'vendors_defs': '\n'.join(vendor_defs)} def fill_template(template, data): @@ -90,7 +104,10 @@ def main(argv): return -1 data = open(args.input, 'rb').read() - controls = yaml.safe_load(data)['controls'] + + controls = {} + vendor = yaml.safe_load(data)['vendor'] + controls[vendor] = yaml.safe_load(data)['controls'] data = generate_py(controls, args.mode) diff --git a/src/py/libcamera/py_controls_generated.cpp.in b/src/py/libcamera/py_controls_generated.cpp.in index 18fa57d948ea..ec4b55ef2011 100644 --- a/src/py/libcamera/py_controls_generated.cpp.in +++ b/src/py/libcamera/py_controls_generated.cpp.in @@ -21,10 +21,13 @@ class PyDraftControls { }; +${vendors_class_def} + void init_py_controls_generated(py::module& m) { auto controls = py::class_(m, "controls"); auto draft = py::class_(controls, "draft"); +${vendors_defs} ${controls} } diff --git a/src/py/libcamera/py_properties_generated.cpp.in b/src/py/libcamera/py_properties_generated.cpp.in index e49b6e91bb83..f7b5ec8c635d 100644 --- a/src/py/libcamera/py_properties_generated.cpp.in +++ b/src/py/libcamera/py_properties_generated.cpp.in @@ -21,10 +21,13 @@ class PyDraftProperties { }; +${vendors_class_def} + void init_py_properties_generated(py::module& m) { auto controls = py::class_(m, "properties"); auto draft = py::class_(controls, "draft"); +${vendors_defs} ${controls} } diff --git a/utils/gen-controls.py b/utils/gen-controls.py index 1075ae302ce1..8f2f8fdb02c3 100755 --- a/utils/gen-controls.py +++ b/utils/gen-controls.py @@ -35,11 +35,12 @@ class ControlEnum(object): class Control(object): - def __init__(self, name, data): + def __init__(self, name, data, vendor): self.__name = name self.__data = data self.__enum_values = None self.__size = None + self.__vendor = vendor enum_values = data.get('enum') if enum_values is not None: @@ -89,6 +90,11 @@ class Control(object): """Is the control a draft control""" return self.__data.get('draft') is not None + @property + def vendor(self): + """The vendor string, or None""" + return self.__vendor + @property def name(self): """The control name (CamelCase)""" @@ -145,15 +151,19 @@ ${description} enum_values_start = string.Template('''extern const std::array ${name}Values = {''') enum_values_values = string.Template('''\tstatic_cast(${name}),''') - ctrls_doc = [] - ctrls_def = [] - draft_ctrls_doc = [] - draft_ctrls_def = [] - ctrls_map = [] + ctrls_doc = {} + ctrls_def = {} + ctrls_map = {} for ctrl in controls: id_name = snake_case(ctrl.name).upper() + vendor = 'draft' if ctrl.is_draft else ctrl.vendor + if vendor not in ctrls_doc: + ctrls_doc[vendor] = [] + ctrls_def[vendor] = [] + ctrls_map[vendor] = [] + info = { 'name': ctrl.name, 'type': ctrl.type, @@ -161,11 +171,9 @@ ${description} 'id_name': id_name, } - target_doc = ctrls_doc - target_def = ctrls_def - if ctrl.is_draft: - target_doc = draft_ctrls_doc - target_def = draft_ctrls_def + target_doc = ctrls_doc[vendor] + target_def = ctrls_def[vendor] + target_ctrls_map = ctrls_map[vendor] if ctrl.is_enum: enum_doc = [] @@ -201,41 +209,87 @@ ${description} target_doc.append(doc_template.substitute(info)) target_def.append(def_template.substitute(info)) - ctrls_map.append('\t{ ' + id_name + ', &' + ctrl.q_name + ' },') + target_ctrls_map.append('\t{ ' + id_name + ', &' + ctrl.q_name + ' },') + + vendor_ctrl_doc_sub = [] + vendor_ctrl_template = string.Template(''' +namespace ${vendor} { + +${vendor_controls_str} + +} /* namespace ${vendor} */''') + + for vendor in [v for v in ctrls_map.keys() if v not in ['libcamera', 'draft']]: + vendor_ctrl_doc_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, 'vendor_controls_str': '\n\n'.join(ctrls_doc[vendor])})) + + vendor_ctrl_def_sub = [] + for vendor in [v for v in ctrls_map.keys() if v not in ['libcamera', 'draft']]: + vendor_ctrl_def_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, 'vendor_controls_str': '\n'.join(ctrls_def[vendor])})) + + vendor_ctrl_map_sub = [] + vendor_ctrl_template = string.Template('''namespace ${vendor} { +/** + * \\brief List of all supported ${vendor} vendor controls + * + * Unless otherwise stated, all controls are bi-directional, i.e. they can be + * set through Request::controls() and returned out through Request::metadata(). + */ +extern const ControlIdMap controls { +${vendor_controls_map} +}; + +} /* namespace ${vendor} */ +''') + + for vendor in [v for v in ctrls_map.keys() if v not in ['libcamera', 'draft']]: + vendor_ctrl_map_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, + 'vendor_controls_map': '\n'.join(ctrls_map[vendor])})) return { - 'controls_doc': '\n\n'.join(ctrls_doc), - 'controls_def': '\n'.join(ctrls_def), - 'draft_controls_doc': '\n\n'.join(draft_ctrls_doc), - 'draft_controls_def': '\n\n'.join(draft_ctrls_def), - 'controls_map': '\n'.join(ctrls_map), + 'controls_doc': '\n\n'.join(ctrls_doc['libcamera']), + 'controls_def': '\n'.join(ctrls_def['libcamera']), + 'draft_controls_doc': '\n\n'.join(ctrls_doc['draft']), + 'draft_controls_def': '\n\n'.join(ctrls_def['draft']), + 'controls_map': '\n'.join(ctrls_map['libcamera'] + ctrls_map['draft']), + 'vendor_controls_doc': '\n'.join(vendor_ctrl_doc_sub), + 'vendor_controls_def': '\n'.join(vendor_ctrl_def_sub), + 'vendor_controls_map': '\n'.join(vendor_ctrl_map_sub), } -def generate_h(controls): +def generate_h(controls, mode): enum_template_start = string.Template('''enum ${name}Enum {''') enum_value_template = string.Template('''\t${name} = ${value},''') enum_values_template = string.Template('''extern const std::array ${name}Values;''') template = string.Template('''extern const Control<${type}> ${name};''') - ctrls = [] - draft_ctrls = [] - ids = [] - id_value = 1 + ctrls = {} + ids = {} + id_value = {} for ctrl in controls: id_name = snake_case(ctrl.name).upper() - ids.append('\t' + id_name + ' = ' + str(id_value) + ',') + vendor = 'draft' if ctrl.is_draft else ctrl.vendor + if vendor not in ctrls: + ids[vendor] = [] + id_value[vendor] = 1 + ctrls[vendor] = [] + + # Core and draft controls use the same ID value + target_ids = ids['libcamera'] if vendor in ['libcamera', 'draft'] else ids[vendor] + target_ids.append('\t' + id_name + ' = ' + str(id_value[vendor]) + ',') info = { 'name': ctrl.name, 'type': ctrl.type, } - target_ctrls = ctrls + target_ctrls = ctrls['libcamera'] if ctrl.is_draft: - target_ctrls = draft_ctrls + target_ctrls = ctrls['draft'] + elif vendor != 'libcamera': + target_ctrls = ctrls[vendor] if ctrl.is_enum: target_ctrls.append(enum_template_start.substitute(info)) @@ -257,12 +311,37 @@ def generate_h(controls): target_ctrls.append(enum_values_template.substitute(values_info)) target_ctrls.append(template.substitute(info)) - id_value += 1 + id_value[vendor] += 1 + + vendor_template = string.Template(''' +namespace ${vendor} { + +#define LIBCAMERA_HAS_${vendor_def}_VENDOR_${mode} + +enum { +${vendor_enums} +}; + +extern const ControlIdMap controls; + +${vendor_controls} + +} /* namespace ${vendor} */ +''') + + vendor_sub = [] + for vendor in [v for v in ctrls.keys() if v not in ['libcamera', 'draft']]: + vendor_sub.append(vendor_template.substitute({'mode': mode.upper(), + 'vendor': vendor, + 'vendor_def': vendor.upper(), + 'vendor_enums': '\n'.join(ids[vendor]), + 'vendor_controls': '\n'.join(ctrls[vendor])})) return { - 'ids': '\n'.join(ids), - 'controls': '\n'.join(ctrls), - 'draft_controls': '\n'.join(draft_ctrls) + 'ids': '\n'.join(ids['libcamera']), + 'controls': '\n'.join(ctrls['libcamera']), + 'draft_controls': '\n'.join(ctrls['draft']), + 'vendor_controls': '\n'.join(vendor_sub) } @@ -284,16 +363,19 @@ def main(argv): help='Input file name.') parser.add_argument('template', type=str, help='Template file name.') + parser.add_argument('--mode', type=str, required=True, choices=['controls', 'properties'], + help='Mode of operation') args = parser.parse_args(argv[1:]) data = open(args.input, 'rb').read() + vendor = yaml.safe_load(data)['vendor'] controls = yaml.safe_load(data)['controls'] - controls = [Control(*ctrl.popitem()) for ctrl in controls] + controls = [Control(*ctrl.popitem(), vendor) for ctrl in controls] if args.template.endswith('.cpp.in'): data = generate_cpp(controls) elif args.template.endswith('.h.in'): - data = generate_h(controls) + data = generate_h(controls, args.mode) else: raise RuntimeError('Unknown template type') From patchwork Tue Nov 21 14:53:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 19217 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 2C12DC328F for ; Tue, 21 Nov 2023 14:54:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id DDD99629B6; Tue, 21 Nov 2023 15:53:59 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1700578439; bh=N5lmsMB0/dZMHFpG1hIvgGUnLo18Jz3E9dr9ei9LXMw=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=MUt2C6I8cPQwurIg8CmyI782Eta0pzfjkXpS78vqGoBJQmGs7SMrcKMnbsYgxmmIB i5ZAPmFXuH1Y2U4L2xzAGyGI9ZaHbUrw2IB+tlzfpg+bTRwuZfKBXSl4g5kj6I4k7O u8iA6aP2QtyGL4undublD5N12o1VdRzrZDxFqPgZwXdFWJUYJggyZ2GmBruOJ/bQ+I amnru3OF+mG0tebTM0nMB1fquZK31quaJIyeOHCioVc0TAjKgrYwtmkjzTXdqOKPUD WiDZR24F9E1X128YXp6Zj1opRY9FXfLOHFkTbyKpbUBQrNxVoq3nMjYu+zdajqPEG4 9jpkJC26G87vQ== Received: from mail-lj1-x229.google.com (mail-lj1-x229.google.com [IPv6:2a00:1450:4864:20::229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0988261DB0 for ; Tue, 21 Nov 2023 15:53:58 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="bappw0w2"; dkim-atps=neutral Received: by mail-lj1-x229.google.com with SMTP id 38308e7fff4ca-2c876f1e44dso37086441fa.0 for ; Tue, 21 Nov 2023 06:53:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1700578437; x=1701183237; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=S7qLn4hXZgTbdZqaZ5za1br9W0F1gEiccigSkouVflU=; b=bappw0w21IWyohjAk4M8cqZPFObIhMrXfGz19wK50tS9X7JPsAr9vya7eqpRdUEVEP m/NRBrwwqrgeLFJkbxcWeq2FoxOv0+IDMR9XkRUWsuWLbvzQV7wJuQNG89775g/PQdwr L10uPgpvNQhaE29eoLrOiKjv54bPI7Bd4lY2lDQqnrWdBRtJPhstN/4f3B1Fau8wkv4n 02Tue94Oh6/Ibdh/nipp4rq42Eg4YA2usm80hDJU062xfkZDGoicrwDeMLEyMh2wc1a3 wJs6gG+OWCYQXy0dtSsVXfL5F74Sa7BmgQ182BJ+FvoslId84LoI2mf5hQgCl2TgUWrU /uhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700578437; x=1701183237; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=S7qLn4hXZgTbdZqaZ5za1br9W0F1gEiccigSkouVflU=; b=j1CLp7LciNU0M8KL5Uak78ZGQe7w0TcueYdhoVBqV7emgqOtnNOU3UzrhuzfeEUHge ZyCcAf4JYAtLSru6MDrZ6sXbImtKpOfWnqB33dq8sMH4zgUte+LkgwxmDmwHZJ4xG6Ep gkZ5UuNWMdyl6lWZMY5H00uCEHpWYvq1GQfH+7xsC2D8ogbpiRDswCkkZ9ZxrLU4OAVn 2aYTZyxTmPSSDaDPBL1K1YtSshWl95x6yNMhJJaXXpW5fXxc/eh/4pqd21NlvCO79XJM 5JlqPjxeFdYytpSEQuR9U+QzqTmlzxojNARzIKpLStQbUHTsdF3Efqq7xEKPOY/0abFS tmbQ== X-Gm-Message-State: AOJu0YxxsUu5cfkjOEVWKLYBJ5Jn65nVpIQ+S5Ai5T94dQ1/HkjG0P2B 9W4Z4wxc3raDDZBggYaIOGuTMnFmEkFUSp2gW4n1qg== X-Google-Smtp-Source: AGHT+IHsL0WCpBIRiqccYe7nLJAcVBYHcJHyCklmls41hzd+UbI6JM93PSG7yR2t+pQJgzLtNlSaqQ== X-Received: by 2002:a2e:b816:0:b0:2c5:2eaa:5399 with SMTP id u22-20020a2eb816000000b002c52eaa5399mr8065086ljo.6.1700578436730; Tue, 21 Nov 2023 06:53:56 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id h18-20020a05600c351200b004063ea92492sm17570968wmq.22.2023.11.21.06.53.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Nov 2023 06:53:55 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Tue, 21 Nov 2023 14:53:46 +0000 Message-Id: <20231121145350.5956-3-naush@raspberrypi.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231121145350.5956-1-naush@raspberrypi.com> References: <20231121145350.5956-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 2/6] controls: Update argument handling for controls generation scripts X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The template file to the gen-controls.py and gen-py-controls.py is now passed in through the '-t' command line argument instead of being a positional argument. This will allow multiple input files to be provided to the scripts in a future commit. Signed-off-by: Naushir Patuck --- include/libcamera/meson.build | 7 ++++--- src/libcamera/meson.build | 7 ++++--- src/py/libcamera/gen-py-controls.py | 2 +- src/py/libcamera/meson.build | 18 ++++++++---------- utils/gen-controls.py | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 2c8c0258c95e..5fb772e6dd14 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -41,12 +41,13 @@ control_source_files = { control_headers = [] foreach header, mode : control_source_files - input_files = files('../../src/libcamera/' + header +'.yaml', header + '.h.in') + input_files = files('../../src/libcamera/' + header +'.yaml') + template_file = files(header + '.h.in') control_headers += custom_target(header + '_h', input : input_files, output : header + '.h', - command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@', - '--mode', mode], + command : [gen_controls, '-o', '@OUTPUT@', + '--mode', mode, '-t', template_file, '@INPUT@'], install : true, install_dir : libcamera_headers_install_dir) endforeach diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index e49bf850b355..05ee38daf22b 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -128,12 +128,13 @@ endif control_sources = [] foreach source, mode : control_source_files - input_files = files(source +'.yaml', source + '.cpp.in') + input_files = files(source +'.yaml') + template_file = files(source + '.cpp.in') control_sources += custom_target(source + '_cpp', input : input_files, output : source + '.cpp', - command : [gen_controls, '-o', '@OUTPUT@', '@INPUT@', - '--mode', mode]) + command : [gen_controls, '-o', '@OUTPUT@', + '--mode', mode, '-t', template_file, '@INPUT@']) endforeach libcamera_sources += control_sources diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py index 8f14cdafe313..ea28f0139f23 100755 --- a/src/py/libcamera/gen-py-controls.py +++ b/src/py/libcamera/gen-py-controls.py @@ -93,7 +93,7 @@ def main(argv): help='Output file name. Defaults to standard output if not specified.') parser.add_argument('input', type=str, help='Input file name.') - parser.add_argument('template', type=str, + parser.add_argument('-t', dest='template', type=str, required=True, help='Template file name.') parser.add_argument('--mode', type=str, required=True, help='Mode is either "controls" or "properties"') diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build index f58c7198ee9e..1c3ea1843ac0 100644 --- a/src/py/libcamera/meson.build +++ b/src/py/libcamera/meson.build @@ -28,29 +28,27 @@ pycamera_sources = files([ # Generate controls -gen_py_controls_input_files = files([ - '../../libcamera/control_ids.yaml', - 'py_controls_generated.cpp.in', -]) +gen_py_controls_input_files = files('../../libcamera/control_ids.yaml') +gen_py_controls_template = files('py_controls_generated.cpp.in') gen_py_controls = files('gen-py-controls.py') pycamera_sources += custom_target('py_gen_controls', input : gen_py_controls_input_files, output : ['py_controls_generated.cpp'], - command : [gen_py_controls, '--mode', 'controls', '-o', '@OUTPUT@', '@INPUT@']) + command : [gen_py_controls, '--mode', 'controls', '-o', '@OUTPUT@', + '-t', gen_py_controls_template, '@INPUT@']) # Generate properties -gen_py_property_enums_input_files = files([ - '../../libcamera/property_ids.yaml', - 'py_properties_generated.cpp.in', -]) +gen_py_property_enums_input_files = files('../../libcamera/property_ids.yaml') +gen_py_properties_template = files('py_properties_generated.cpp.in') pycamera_sources += custom_target('py_gen_properties', input : gen_py_property_enums_input_files, output : ['py_properties_generated.cpp'], - command : [gen_py_controls, '--mode', 'properties', '-o', '@OUTPUT@', '@INPUT@']) + command : [gen_py_controls, '--mode', 'properties', '-o', '@OUTPUT@', + '-t', gen_py_properties_template, '@INPUT@']) # Generate formats diff --git a/utils/gen-controls.py b/utils/gen-controls.py index 8f2f8fdb02c3..8af33d29cd07 100755 --- a/utils/gen-controls.py +++ b/utils/gen-controls.py @@ -361,7 +361,7 @@ def main(argv): help='Output file name. Defaults to standard output if not specified.') parser.add_argument('input', type=str, help='Input file name.') - parser.add_argument('template', type=str, + parser.add_argument('-t', dest='template', type=str, required=True, help='Template file name.') parser.add_argument('--mode', type=str, required=True, choices=['controls', 'properties'], help='Mode of operation') From patchwork Tue Nov 21 14:53:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 19218 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 2C6EFC32B6 for ; Tue, 21 Nov 2023 14:54:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7A9C861DAE; Tue, 21 Nov 2023 15:54:00 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1700578440; bh=u1pzwaJCyQvFTyvZsijtKDuzg3WHLwqOttR93D7fqk8=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=NIeg185CnTEazeZol6kKLy9gyzgLy+1WW9L/3aKlickd18tU2o8YZtDPO9YK5RE90 odsItdpYDxc+bJkYOS5Qd8G1ZU8MnXZoZ5aiS1PfpHmC/UYo0wWLsZM3yG6b2yd944 FfT19sCqGnxvx7dVfAzs8tLEJWVl2AWHplZg9y/xH4DqEeSPE/4caxkVJNAa5B2DqI mX0tWUKpboWzed1cZBBguqDCBbI30tc3kDlZezymv7bOuitmS8+xkGus1cc8R0R+/3 4wNbswhy8+8a8AQqAzxzVMK2Z98+LHrFtJ9eQVt9yZ8tYGw7g36ldpKUamoLxOBRVF eBgkaAEpAwUPw== Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A8656629C2 for ; Tue, 21 Nov 2023 15:53:58 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="flyltw9h"; dkim-atps=neutral Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-40859c464daso25602965e9.1 for ; Tue, 21 Nov 2023 06:53:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1700578438; x=1701183238; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ktpi15tBs8cYjJhOKHEBmP3OaeY5TzoUYnry6TQur+I=; b=flyltw9h9rMHcLxO4G5ATtNuI5+3v6312zL0b2/PQMNESFCfF16AXY5valx6yj/ETq IGGjiEU425wqsBDTLWZYAhIaP4Jq2l8DojrlIcoMKb9mKTh2k2C1UYkcHDCIp73XXVQK NuTC9RX722dmrP7hZgpi/Tyy4qVfMTXlaavHJ9ZHFF8plmGHVEz5TIBgXFMCPsRZFWJl tLvfR1vmbI8U0jxjupv9Mc/EAFb6cEFBPvxN3G667m3Tr4tPz8xZLVLCmKZXQH9CoXqN wgCyLEdJPoHyJ9V2+DtsY/e3KSx849ZqXm9BbBzO15MKRwGfE6ybHqua3sr/ee/zeZZE LcEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700578438; x=1701183238; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ktpi15tBs8cYjJhOKHEBmP3OaeY5TzoUYnry6TQur+I=; b=jsk6oYlffKswRNXEeJwNSzm7MhTn56cqZDiEt2Gnzl4yPEj8aWb/TovDPCOwCeyysf vvvzu2MHuOHsuAUDxAietTLm1/fGewXmNbQEn7OlwZQ0ftt17OyK4ckXc/GMgvcgMcY9 Pcaahc6gV0kDFCqqZ8iNLVbf8khvwUvlPPY3tfjXWcMj8V1fYGDffHIyJLFqA8NYqtMB Y8WihY6hyXEIuRqHPBX/+7EwBilvIs7yJvQoSyBsuSfnwo+xg6dretHTkzEoX+NBUpSh y8NCRvQYa0nfPH9nSmXbv167+mQm92vfGxGoHsDXDrLtaAbHHwMU6IZSlk0cIemVwJyv 8zZA== X-Gm-Message-State: AOJu0YxMpBfWQYXb/mVmHHabWVczfz0ViatZTKJB5Yhg6wFT94OjqCWq HgMrKfm06iPiCKc6EWf8YF3UbrkjaIv+AVxV3eBIkA== X-Google-Smtp-Source: AGHT+IFipRwKbifJWtND2SAAyf0h08d+WsllpwBMmyFK1CCJ5a6HXLoyEPcLW9UBNr+besTwbYxXyQ== X-Received: by 2002:a05:600c:a02:b0:408:53d4:52dd with SMTP id z2-20020a05600c0a0200b0040853d452ddmr8050359wmp.22.1700578438025; Tue, 21 Nov 2023 06:53:58 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id h18-20020a05600c351200b004063ea92492sm17570968wmq.22.2023.11.21.06.53.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Nov 2023 06:53:57 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Tue, 21 Nov 2023 14:53:47 +0000 Message-Id: <20231121145350.5956-4-naush@raspberrypi.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231121145350.5956-1-naush@raspberrypi.com> References: <20231121145350.5956-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 3/6] controls: build: Allow separate vendor control YAML files X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add support for using separate YAML files for vendor specific controls. This simplifies management of vendor control definitions and avoids possible merge conflicts when changing the control_ids.yaml file for core and draft controls. The mapping of vendor/pipeline handler to control file is done through the vendor_controls_mapping variable in include/libcamera/meson.build. Add a new control_ids_rpi.yaml file to hold the Raspberry Pi specific vendor controls. This contains a single control PispConfigDumpFile that will be used in the Pi 5 pipeline handler as a trigger to dump the Backend configuration as a JSON file. Signed-off-by: Naushir Patuck --- include/libcamera/meson.build | 42 ++++++++++++++++++++++++++++- meson.build | 2 ++ src/libcamera/control_ids_rpi.yaml | 16 +++++++++++ src/libcamera/meson.build | 12 +++++++++ src/py/libcamera/gen-py-controls.py | 10 +++---- src/py/libcamera/meson.build | 8 ++++++ utils/gen-controls.py | 12 +++++---- 7 files changed, 91 insertions(+), 11 deletions(-) create mode 100644 src/libcamera/control_ids_rpi.yaml diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 5fb772e6dd14..54123c5b858d 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -38,10 +38,50 @@ control_source_files = { 'property_ids': 'properties', } +vendor_controls_mapping = { + # Mapping of vendor (pipeline handler) specific controls files + 'controls': + { + 'rpi/pisp': 'control_ids_rpi.yaml', + 'rpi/vc4': 'control_ids_rpi.yaml' + }, + # Mapping of vendor (pipeline handler) specific properties files + 'properties': + { + + } +} + control_headers = [] +vendor_ctrl_files = [] +vendor_prop_files = [] foreach header, mode : control_source_files - input_files = files('../../src/libcamera/' + header +'.yaml') + + # Start by populating the vendor specific mappings into vendor_ctrl_files + # and vendor_prop_files. These will be cached for later use. + vendor_files = [] + foreach pipeline, file : vendor_controls_mapping[mode] + if pipeline not in pipelines + continue + endif + if file not in vendor_files + vendor_files += file + endif + endforeach + + if mode == 'controls' + vendor_ctrl_files = vendor_files + else + vendor_prop_files = vendor_files + endif + + input_files = files('../../src/libcamera/' + header + '.yaml') + + foreach file : vendor_files + input_files += files('../../src/libcamera/' + file) + endforeach + template_file = files(header + '.h.in') control_headers += custom_target(header + '_h', input : input_files, diff --git a/meson.build b/meson.build index e9a1c7e360ce..1423abf16c77 100644 --- a/meson.build +++ b/meson.build @@ -267,6 +267,8 @@ py_mod.find_installation('python3', modules : py_modules) summary({ 'Enabled pipelines': pipelines, 'Enabled IPA modules': enabled_ipa_names, + 'Vendor controls': vendor_ctrl_files, + 'Vendor properties': vendor_prop_files, 'Hotplug support': libudev.found(), 'Tracing support': tracing_enabled, 'Android support': android_enabled, diff --git a/src/libcamera/control_ids_rpi.yaml b/src/libcamera/control_ids_rpi.yaml new file mode 100644 index 000000000000..a6f8b43a5f62 --- /dev/null +++ b/src/libcamera/control_ids_rpi.yaml @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Copyright (C) 2023, Raspberry Pi Ltd +# +%YAML 1.1 +--- +vendor: rpi +controls: + - PispConfigDumpFile: + type: string + description: | + Triggers the Raspberry Pi PiSP pipeline handler to generate a JSON + formatted dump of the Backend configuration to the filename given by the + value of the control. + +... diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 05ee38daf22b..7eb26ccbb7f5 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -129,6 +129,18 @@ control_sources = [] foreach source, mode : control_source_files input_files = files(source +'.yaml') + + # Add the vendor specific files to the input. + if mode == 'controls' + vendor_files = vendor_ctrl_files + else + vendor_files = vendor_prop_files + endif + + foreach file : vendor_files + input_files += files(file) + endforeach + template_file = files(source + '.cpp.in') control_sources += custom_target(source + '_cpp', input : input_files, diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py index ea28f0139f23..e2ddad8581fd 100755 --- a/src/py/libcamera/gen-py-controls.py +++ b/src/py/libcamera/gen-py-controls.py @@ -91,7 +91,7 @@ def main(argv): parser = argparse.ArgumentParser() parser.add_argument('-o', dest='output', metavar='file', type=str, help='Output file name. Defaults to standard output if not specified.') - parser.add_argument('input', type=str, + parser.add_argument('input', type=str, nargs='+', help='Input file name.') parser.add_argument('-t', dest='template', type=str, required=True, help='Template file name.') @@ -103,11 +103,11 @@ def main(argv): print(f'Invalid mode option "{args.mode}"', file=sys.stderr) return -1 - data = open(args.input, 'rb').read() - controls = {} - vendor = yaml.safe_load(data)['vendor'] - controls[vendor] = yaml.safe_load(data)['controls'] + for input in args.input: + data = open(input, 'rb').read() + vendor = yaml.safe_load(data)['vendor'] + controls[vendor] = yaml.safe_load(data)['controls'] data = generate_py(controls, args.mode) diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build index 1c3ea1843ac0..ea38ad6ca829 100644 --- a/src/py/libcamera/meson.build +++ b/src/py/libcamera/meson.build @@ -33,6 +33,10 @@ gen_py_controls_template = files('py_controls_generated.cpp.in') gen_py_controls = files('gen-py-controls.py') +foreach file : vendor_ctrl_files + gen_py_controls_input_files += files('../../libcamera/' + file) +endforeach + pycamera_sources += custom_target('py_gen_controls', input : gen_py_controls_input_files, output : ['py_controls_generated.cpp'], @@ -44,6 +48,10 @@ pycamera_sources += custom_target('py_gen_controls', gen_py_property_enums_input_files = files('../../libcamera/property_ids.yaml') gen_py_properties_template = files('py_properties_generated.cpp.in') +foreach file : vendor_prop_files + gen_py_property_enums_input_files += files('../../libcamera/' + file) +endforeach + pycamera_sources += custom_target('py_gen_properties', input : gen_py_property_enums_input_files, output : ['py_properties_generated.cpp'], diff --git a/utils/gen-controls.py b/utils/gen-controls.py index 8af33d29cd07..d7862142b8c1 100755 --- a/utils/gen-controls.py +++ b/utils/gen-controls.py @@ -359,7 +359,7 @@ def main(argv): parser = argparse.ArgumentParser() parser.add_argument('-o', dest='output', metavar='file', type=str, help='Output file name. Defaults to standard output if not specified.') - parser.add_argument('input', type=str, + parser.add_argument('input', type=str, nargs='+', help='Input file name.') parser.add_argument('-t', dest='template', type=str, required=True, help='Template file name.') @@ -367,10 +367,12 @@ def main(argv): help='Mode of operation') args = parser.parse_args(argv[1:]) - data = open(args.input, 'rb').read() - vendor = yaml.safe_load(data)['vendor'] - controls = yaml.safe_load(data)['controls'] - controls = [Control(*ctrl.popitem(), vendor) for ctrl in controls] + controls = [] + for input in args.input: + data = open(input, 'rb').read() + vendor = yaml.safe_load(data)['vendor'] + ctrls = yaml.safe_load(data)['controls'] + controls = controls + [Control(*ctrl.popitem(), vendor) for ctrl in ctrls] if args.template.endswith('.cpp.in'): data = generate_cpp(controls) From patchwork Tue Nov 21 14:53:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 19219 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 6AD54C3220 for ; Tue, 21 Nov 2023 14:54:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 25773629C6; Tue, 21 Nov 2023 15:54:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1700578443; bh=Lz7bqg4woco1wsI1dg+O/x/h8wf+lZqPik1AGilmbFQ=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=AfZa15WCYZ0AMzK+NjSMRO3szDUtTQcSnEe/PcZYcHERAPgE/MSzEFyTwhn190/O3 D4JzxZopLGei6Fka20Q9YdhLA7Ps/6jLY0Vv2c4vDrxxQt2EbTbx8xr/leDz1PMhjc ff7KTYk7bRbYqyo0jmO/ql38xgnvF/bQ4rd1PdMcliq8fKlQvYV+bW5V3Plsubo7Se bOIxC1FIfUayYGnH0DizfwK3PzKAncue75IrKvSABCXNBsuXrYOD9psRtxadbUM05Y 0EEkD8BSw7ertY0NQaxchT/tY9O2nin8z78S9rpoULHzvSVkzSsRpQXCQUQGqW7tgg Z/UG4xXCHUotw== Received: from mail-lj1-x233.google.com (mail-lj1-x233.google.com [IPv6:2a00:1450:4864:20::233]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A67B2629C7 for ; Tue, 21 Nov 2023 15:54:00 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="E0UdMOQi"; dkim-atps=neutral Received: by mail-lj1-x233.google.com with SMTP id 38308e7fff4ca-2c503dbe50dso72736941fa.1 for ; Tue, 21 Nov 2023 06:54:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1700578439; x=1701183239; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+se7h2b/3Pvt4IUgxQJOXLlI94EI05IQfuZIl3Zu+sI=; b=E0UdMOQi6s06A4NElxKIIccnp1JqQxRvCD27V8SUpt2NEotgTPZug7amJvTDkrX6wC R3CRQT5ZqptutneHpr4yMC0MtYt2LP+CdWErw824EHUS2tRGwaTGuRxGstAHjEgoE7nw RBlhvTsh/2rfDzu86PSEXgLjFWi0YTf40J6LkpM+ZE1AsmwSsx/0DnWJOa6wj4oYQaWH sDhAtKTx95ffgQCqWPl4bm45ENWBfxef46kdyW4sfb62uX4qeaxFOxcMxG8E5OlNHRPv pBg24KwGSkI+hOTRCVxqCr4Zcor4UDtv2E3QqZN/UAaet1d18ZmxA5oJlPTQ/YJFIxWx iWwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700578439; x=1701183239; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+se7h2b/3Pvt4IUgxQJOXLlI94EI05IQfuZIl3Zu+sI=; b=J/cYaBXhDjqMcwt0UQM1yHUN5Ox5DgEpYYREvyPCRFQWA00HjAbFUUO6NHnWVun1HM v/kf8MTpcXVs+tGM/3iOV1b5ynWpmuh61hOfHmeFeO2E+nSVJMnVOXnSwrr1LdGnz3QN lCHe4NF6P6R1XTnUlD5sTCmTPEtCgnbSZCcJ7jKYRU+grhUNg8kGcuU7Cgth97P0SvHu jXasgJPkEJ4hLPAtziOkyVXUqM/i1UWlNMtq2p/LJRYmULNyV/MG+J+SVDb8yZW7rj8D JFbtyPefdP2Om4jycfT/+6RcutoQkwoO338m3Ho2qbze7fI05/bjfuyKEytZUJ8zk6v1 998Q== X-Gm-Message-State: AOJu0Yz/4vslZaUeRHiHbDqwcJBaLJXjyIs+7KSwDgS3PfyYff2BIwi5 fMk5dJrfA0OX25bhKJozk2kihm4OOJkPJ+6emKWWOg== X-Google-Smtp-Source: AGHT+IGGfldFshS3FwXUyM8TM/WvZvbX/Kpkh4iF+gHzJ35D7TGr+uKSAF60MPAHI4B+NhC9HyO0PA== X-Received: by 2002:a2e:9ec4:0:b0:2c8:7192:817 with SMTP id h4-20020a2e9ec4000000b002c871920817mr6337638ljk.15.1700578439510; Tue, 21 Nov 2023 06:53:59 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id h18-20020a05600c351200b004063ea92492sm17570968wmq.22.2023.11.21.06.53.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Nov 2023 06:53:58 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Tue, 21 Nov 2023 14:53:48 +0000 Message-Id: <20231121145350.5956-5-naush@raspberrypi.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231121145350.5956-1-naush@raspberrypi.com> References: <20231121145350.5956-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 4/6] libcamera: control: Add vendor control id range reservation X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a new control_ranges.yaml file that is used to reserve control id ranges/offsets for libcamera and vendor specific controls. This file is used by the gen-controls.py script to generate control id values for each control. Draft controls now have a separate range from core libcamera controls, breaking the existing numbering behaviour. Signed-off-by: Naushir Patuck Reviewed-by: Laurent Pinchart --- include/libcamera/meson.build | 4 +++- src/libcamera/control_ranges.yaml | 18 ++++++++++++++++++ src/libcamera/meson.build | 4 +++- utils/gen-controls.py | 15 ++++++++++++--- 4 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 src/libcamera/control_ranges.yaml diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 54123c5b858d..6cac385fdee4 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -83,11 +83,13 @@ foreach header, mode : control_source_files endforeach template_file = files(header + '.h.in') + ranges_file = files('../../src/libcamera/control_ranges.yaml') control_headers += custom_target(header + '_h', input : input_files, output : header + '.h', command : [gen_controls, '-o', '@OUTPUT@', - '--mode', mode, '-t', template_file, '@INPUT@'], + '--mode', mode, '-t', template_file, + '-r', ranges_file, '@INPUT@'], install : true, install_dir : libcamera_headers_install_dir) endforeach diff --git a/src/libcamera/control_ranges.yaml b/src/libcamera/control_ranges.yaml new file mode 100644 index 000000000000..150ae7fa5efd --- /dev/null +++ b/src/libcamera/control_ranges.yaml @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Copyright (C) 2023, Raspberry Pi Ltd +# +%YAML 1.1 +--- +# Specifies the control id ranges/offsets for core libcamera and vendor specific +# controls. +ranges: + # Core libcamera controls + libcamera: 0 + # Draft designated libcamera controls + draft: 10000 + # Raspberry Pi vendor controls + rpi: 20000 + # Next range starts at 30000 + +... diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 7eb26ccbb7f5..303eee84a77e 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -142,11 +142,13 @@ foreach source, mode : control_source_files endforeach template_file = files(source + '.cpp.in') + ranges_file = files('control_ranges.yaml') control_sources += custom_target(source + '_cpp', input : input_files, output : source + '.cpp', command : [gen_controls, '-o', '@OUTPUT@', - '--mode', mode, '-t', template_file, '@INPUT@']) + '--mode', mode, '-t', template_file, + '-r', ranges_file, '@INPUT@']) endforeach libcamera_sources += control_sources diff --git a/utils/gen-controls.py b/utils/gen-controls.py index d7862142b8c1..9eede8940f24 100755 --- a/utils/gen-controls.py +++ b/utils/gen-controls.py @@ -257,7 +257,7 @@ ${vendor_controls_map} } -def generate_h(controls, mode): +def generate_h(controls, mode, ranges): enum_template_start = string.Template('''enum ${name}Enum {''') enum_value_template = string.Template('''\t${name} = ${value},''') enum_values_template = string.Template('''extern const std::array ${name}Values;''') @@ -272,8 +272,10 @@ def generate_h(controls, mode): vendor = 'draft' if ctrl.is_draft else ctrl.vendor if vendor not in ctrls: + if vendor not in ranges.keys(): + raise RuntimeError(f'Control id range is not defined for vendor {vendor}') + id_value[vendor] = ranges[vendor] + 1 ids[vendor] = [] - id_value[vendor] = 1 ctrls[vendor] = [] # Core and draft controls use the same ID value @@ -365,8 +367,15 @@ def main(argv): help='Template file name.') parser.add_argument('--mode', type=str, required=True, choices=['controls', 'properties'], help='Mode of operation') + parser.add_argument('-r', dest='ranges', type=str, required=True, + help='Control id range reservation file.') args = parser.parse_args(argv[1:]) + ranges = [] + if args.ranges: + data = open(args.ranges, 'rb').read() + ranges = yaml.safe_load(data)['ranges'] + controls = [] for input in args.input: data = open(input, 'rb').read() @@ -377,7 +386,7 @@ def main(argv): if args.template.endswith('.cpp.in'): data = generate_cpp(controls) elif args.template.endswith('.h.in'): - data = generate_h(controls, args.mode) + data = generate_h(controls, args.mode, ranges) else: raise RuntimeError('Unknown template type') From patchwork Tue Nov 21 14:53:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 19220 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id F3980C32B7 for ; Tue, 21 Nov 2023 14:54:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9830C61DB0; Tue, 21 Nov 2023 15:54:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1700578443; bh=j7Cv97qADJJB3EJTwpMI0i8b1TyMV7fh3AVKNS0kEI8=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=vGZ7wym3yW+ifDLUkGEc24jImgduhMHnx/jYSQuVgTBFUKGpxfgQijPN4oN3JW3C8 BjcT4lGpGSDCdiHh18dRYPKrgGlI/B2j1mNbHcw/+uxjguC+rVoWNoHqwPmY3Mv/BE wR744cQ28L7qSrrnu2IATUSNoOCiDqJwdyhagYncB0xXf7ElwuGxZHh24JiRRtNcC6 NkI8KQ+1Ou3NfOjAoEUSKldq7tl/BNnRUgtd07yHxgXmXx6Zoc9wrqWd4ELxoCAOhu kQdthRVVeJA/BLMzwLSl3Xcov/ohN33HnEFwOknfxW0dqDsYkWPri9AQ8/z7L24rbu h4xBGxoo0k2Mw== Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A8D1161DAE for ; Tue, 21 Nov 2023 15:54:02 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="XxLeSdBF"; dkim-atps=neutral Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-40b27726369so7144415e9.0 for ; Tue, 21 Nov 2023 06:54:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1700578442; x=1701183242; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ILqoDJ1URg6D1YBNyr6VpNtywrCixGglK53hUQ+03/E=; b=XxLeSdBFtjS0IWYMqRh0KFuqFqtwPKVsvQXcobxuTm9ekFTjr134/3ez15rH4hNxFN dyST2HwdeEH37sjhjsEHmRMB/qYY0vCArxrCKU2JqxmoKXJx8epA0Q4pCPUfoRNTEWCv s8E1ku/WaXLmJ/V7dRrqON8NH5Aq3ZYtPoKL/QQi+JBridRaFQtHxDdfuzRdtzRZ/xiG H00GmZgUtCSaAn7IiZPPNMWJyLuOBdY1vZmEGbyuhANBBD4tY2kbZuGLfB3+wwrfvIcT kMeP/hU7LzMUZQtHuK7CjbKGBJZuQ1XZR9pOxSw2/SFpMFC2uQxPywIuXRNdgida780W 7Vow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700578442; x=1701183242; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ILqoDJ1URg6D1YBNyr6VpNtywrCixGglK53hUQ+03/E=; b=KNs7KV9bnYqAKYhrVlHYInidLf1t8BUUpdxf5+/6ZyjxibGz9J7/Zo2Qo3P3HgaOEN nm0PINE02HQK9XVHD8SmxDxN0ondcjfH49xWqPGSBRZUTwK93mG1OM++eAQVg52KNFqQ h7iPcM9OYxyPp3pkovc3Ea3GanZ7Tj5oTiHhtuBUrGLU+Phd41ATcp1zpmWnxGDT0jan exjR4bcHP2HHzbiLmBz5/5992VZsmSCkzuJmy1OywG2IPEbJp7mTNcqvYBMJl8+XFdPj nAdGeVb7EZ2YhMtQuajSmO4a4Z8lSPe72M5GvMgUFZM8w5/O9MjAN2HQL5SOxmP0oVX7 6M7A== X-Gm-Message-State: AOJu0YwL2Zz4s8zpAI/QL/Gycnv8fGr0sjrZg31IAbAsclJzYSCb2zyP 7KQy4hBTTRlyXl3UtZ5dxHUGGDwXIKFKbeAPlbaauA== X-Google-Smtp-Source: AGHT+IFLQyiFWZcJG8hYgX6c6cX8oKPrnDP5lbCKQLbaxQvaazs6T9w5s5vs7aJJrMFvxcpyjsF9ZQ== X-Received: by 2002:a05:600c:468c:b0:405:49aa:d578 with SMTP id p12-20020a05600c468c00b0040549aad578mr8208450wmo.37.1700578441498; Tue, 21 Nov 2023 06:54:01 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id h18-20020a05600c351200b004063ea92492sm17570968wmq.22.2023.11.21.06.53.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Nov 2023 06:54:00 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Tue, 21 Nov 2023 14:53:49 +0000 Message-Id: <20231121145350.5956-6-naush@raspberrypi.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231121145350.5956-1-naush@raspberrypi.com> References: <20231121145350.5956-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 5/6] libcamera: controls: Use vendor tags for draft controls and properties X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Label draft controls and properties through the "draft" vendor tag and deprecate the existing "draft: true" mechanism. This uses the new vendor tags mechanism to place draft controls in the same libcamera::controls::draft namespace and provide a defined control id range for these controls. This requires moving all draft controls from control_ids.yaml to control_ids_draft.yaml. One breaking change in this commit is that draft control ids also move to the libcamera::controls::draft namespace from the existing libcamera::controls namespace. This is desirable to avoid API breakages when adding new libcamera controls. So, for example, the use of controls::NOISE_REDUCTION_MODE will need to be replaced with controls::draft::NOISE_REDUCTION_MODE. Signed-off-by: Naushir Patuck Reviewed-by: Laurent Pinchart --- include/libcamera/control_ids.h.in | 6 - include/libcamera/meson.build | 3 +- include/libcamera/property_ids.h.in | 6 - src/ipa/rpi/common/ipa_base.cpp | 2 +- src/ipa/rpi/vc4/vc4.cpp | 2 +- src/libcamera/control_ids.cpp.in | 16 +- src/libcamera/control_ids.yaml | 232 ----------------- src/libcamera/control_ids_draft.yaml | 240 ++++++++++++++++++ src/libcamera/meson.build | 2 +- src/libcamera/property_ids.cpp.in | 16 +- src/libcamera/property_ids.yaml | 33 --- src/libcamera/property_ids_draft.yaml | 39 +++ src/py/libcamera/gen-py-controls.py | 5 +- src/py/libcamera/meson.build | 6 +- src/py/libcamera/py_controls_generated.cpp.in | 5 - .../libcamera/py_properties_generated.cpp.in | 3 +- utils/gen-controls.py | 39 +-- 17 files changed, 303 insertions(+), 352 deletions(-) create mode 100644 src/libcamera/control_ids_draft.yaml create mode 100644 src/libcamera/property_ids_draft.yaml diff --git a/include/libcamera/control_ids.h.in b/include/libcamera/control_ids.h.in index c97b09a82450..d53b1cf7beb2 100644 --- a/include/libcamera/control_ids.h.in +++ b/include/libcamera/control_ids.h.in @@ -26,12 +26,6 @@ ${controls} extern const ControlIdMap controls; -namespace draft { - -${draft_controls} - -} /* namespace draft */ - ${vendor_controls} } /* namespace controls */ diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 6cac385fdee4..63fc120a0818 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -76,7 +76,8 @@ foreach header, mode : control_source_files vendor_prop_files = vendor_files endif - input_files = files('../../src/libcamera/' + header + '.yaml') + input_files = files(['../../src/libcamera/' + header +'.yaml', + '../../src/libcamera/' + header +'_draft.yaml']) foreach file : vendor_files input_files += files('../../src/libcamera/' + file) diff --git a/include/libcamera/property_ids.h.in b/include/libcamera/property_ids.h.in index 47c5d6bf2e28..43372c718fc9 100644 --- a/include/libcamera/property_ids.h.in +++ b/include/libcamera/property_ids.h.in @@ -23,12 +23,6 @@ ${ids} ${controls} -namespace draft { - -${draft_controls} - -} /* namespace draft */ - extern const ControlIdMap properties; ${vendor_controls} diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp index a1fec3aa3dd1..6ac9d5de2f88 100644 --- a/src/ipa/rpi/common/ipa_base.cpp +++ b/src/ipa/rpi/common/ipa_base.cpp @@ -1024,7 +1024,7 @@ void IpaBase::applyControls(const ControlList &controls) break; } - case controls::NOISE_REDUCTION_MODE: + case controls::draft::NOISE_REDUCTION_MODE: /* Handled below in handleControls() */ libcameraMetadata_.set(controls::draft::NoiseReductionMode, ctrl.second.get()); diff --git a/src/ipa/rpi/vc4/vc4.cpp b/src/ipa/rpi/vc4/vc4.cpp index c4baf04fb1e7..c165a5b8b0b6 100644 --- a/src/ipa/rpi/vc4/vc4.cpp +++ b/src/ipa/rpi/vc4/vc4.cpp @@ -260,7 +260,7 @@ void IpaVc4::handleControls(const ControlList &controls) for (auto const &ctrl : controls) { switch (ctrl.first) { - case controls::NOISE_REDUCTION_MODE: { + case controls::draft::NOISE_REDUCTION_MODE: { RPiController::DenoiseAlgorithm *sdn = dynamic_cast( controller_.getAlgorithm("SDN")); /* Some platforms may have a combined "denoise" algorithm instead. */ diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in index d26eb930b30c..284589567cfb 100644 --- a/src/libcamera/control_ids.cpp.in +++ b/src/libcamera/control_ids.cpp.in @@ -24,15 +24,6 @@ namespace controls { ${controls_doc} -/** - * \brief Namespace for libcamera draft controls - */ -namespace draft { - -${draft_controls_doc} - -} /* namespace draft */ - ${vendor_controls_doc} #ifndef __DOXYGEN__ @@ -42,13 +33,8 @@ ${vendor_controls_doc} */ ${controls_def} -namespace draft { - -${draft_controls_def} - -} /* namespace draft */ - ${vendor_controls_def} + #endif /** diff --git a/src/libcamera/control_ids.yaml b/src/libcamera/control_ids.yaml index ff74ce1deedb..76fb9347d8e3 100644 --- a/src/libcamera/control_ids.yaml +++ b/src/libcamera/control_ids.yaml @@ -865,236 +865,4 @@ controls: description: | This is a long exposure image. - # ---------------------------------------------------------------------------- - # Draft controls section - - - AePrecaptureTrigger: - type: int32_t - draft: true - description: | - Control for AE metering trigger. Currently identical to - ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER. - - Whether the camera device will trigger a precapture metering sequence - when it processes this request. - enum: - - name: AePrecaptureTriggerIdle - value: 0 - description: The trigger is idle. - - name: AePrecaptureTriggerStart - value: 1 - description: The pre-capture AE metering is started by the camera. - - name: AePrecaptureTriggerCancel - value: 2 - description: | - The camera will cancel any active or completed metering sequence. - The AE algorithm is reset to its initial state. - - - NoiseReductionMode: - type: int32_t - draft: true - description: | - Control to select the noise reduction algorithm mode. Currently - identical to ANDROID_NOISE_REDUCTION_MODE. - - Mode of operation for the noise reduction algorithm. - enum: - - name: NoiseReductionModeOff - value: 0 - description: No noise reduction is applied - - name: NoiseReductionModeFast - value: 1 - description: | - Noise reduction is applied without reducing the frame rate. - - name: NoiseReductionModeHighQuality - value: 2 - description: | - High quality noise reduction at the expense of frame rate. - - name: NoiseReductionModeMinimal - value: 3 - description: | - Minimal noise reduction is applied without reducing the frame rate. - - name: NoiseReductionModeZSL - value: 4 - description: | - Noise reduction is applied at different levels to different streams. - - - ColorCorrectionAberrationMode: - type: int32_t - draft: true - description: | - Control to select the color correction aberration mode. Currently - identical to ANDROID_COLOR_CORRECTION_ABERRATION_MODE. - - Mode of operation for the chromatic aberration correction algorithm. - enum: - - name: ColorCorrectionAberrationOff - value: 0 - description: No aberration correction is applied. - - name: ColorCorrectionAberrationFast - value: 1 - description: Aberration correction will not slow down the frame rate. - - name: ColorCorrectionAberrationHighQuality - value: 2 - description: | - High quality aberration correction which might reduce the frame - rate. - - - AeState: - type: int32_t - draft: true - description: | - Control to report the current AE algorithm state. Currently identical to - ANDROID_CONTROL_AE_STATE. - - Current state of the AE algorithm. - enum: - - name: AeStateInactive - value: 0 - description: The AE algorithm is inactive. - - name: AeStateSearching - value: 1 - description: The AE algorithm has not converged yet. - - name: AeStateConverged - value: 2 - description: The AE algorithm has converged. - - name: AeStateLocked - value: 3 - description: The AE algorithm is locked. - - name: AeStateFlashRequired - value: 4 - description: The AE algorithm would need a flash for good results - - name: AeStatePrecapture - value: 5 - description: | - The AE algorithm has started a pre-capture metering session. - \sa AePrecaptureTrigger - - - AwbState: - type: int32_t - draft: true - description: | - Control to report the current AWB algorithm state. Currently identical - to ANDROID_CONTROL_AWB_STATE. - - Current state of the AWB algorithm. - enum: - - name: AwbStateInactive - value: 0 - description: The AWB algorithm is inactive. - - name: AwbStateSearching - value: 1 - description: The AWB algorithm has not converged yet. - - name: AwbConverged - value: 2 - description: The AWB algorithm has converged. - - name: AwbLocked - value: 3 - description: The AWB algorithm is locked. - - - SensorRollingShutterSkew: - type: int64_t - draft: true - description: | - Control to report the time between the start of exposure of the first - row and the start of exposure of the last row. Currently identical to - ANDROID_SENSOR_ROLLING_SHUTTER_SKEW - - - LensShadingMapMode: - type: int32_t - draft: true - description: | - Control to report if the lens shading map is available. Currently - identical to ANDROID_STATISTICS_LENS_SHADING_MAP_MODE. - enum: - - name: LensShadingMapModeOff - value: 0 - description: No lens shading map mode is available. - - name: LensShadingMapModeOn - value: 1 - description: The lens shading map mode is available. - - - PipelineDepth: - type: int32_t - draft: true - description: | - Specifies the number of pipeline stages the frame went through from when - it was exposed to when the final completed result was available to the - framework. Always less than or equal to PipelineMaxDepth. Currently - identical to ANDROID_REQUEST_PIPELINE_DEPTH. - - The typical value for this control is 3 as a frame is first exposed, - captured and then processed in a single pass through the ISP. Any - additional processing step performed after the ISP pass (in example face - detection, additional format conversions etc) count as an additional - pipeline stage. - - - MaxLatency: - type: int32_t - draft: true - description: | - The maximum number of frames that can occur after a request (different - than the previous) has been submitted, and before the result's state - becomes synchronized. A value of -1 indicates unknown latency, and 0 - indicates per-frame control. Currently identical to - ANDROID_SYNC_MAX_LATENCY. - - - TestPatternMode: - type: int32_t - draft: true - description: | - Control to select the test pattern mode. Currently identical to - ANDROID_SENSOR_TEST_PATTERN_MODE. - enum: - - name: TestPatternModeOff - value: 0 - description: | - No test pattern mode is used. The camera device returns frames from - the image sensor. - - name: TestPatternModeSolidColor - value: 1 - description: | - Each pixel in [R, G_even, G_odd, B] is replaced by its respective - color channel provided in test pattern data. - \todo Add control for test pattern data. - - name: TestPatternModeColorBars - value: 2 - description: | - All pixel data is replaced with an 8-bar color pattern. The vertical - bars (left-to-right) are as follows; white, yellow, cyan, green, - magenta, red, blue and black. Each bar should take up 1/8 of the - sensor pixel array width. When this is not possible, the bar size - should be rounded down to the nearest integer and the pattern can - repeat on the right side. Each bar's height must always take up the - full sensor pixel array height. - - name: TestPatternModeColorBarsFadeToGray - value: 3 - description: | - The test pattern is similar to TestPatternModeColorBars, - except that each bar should start at its specified color at the top - and fade to gray at the bottom. Furthermore each bar is further - subdevided into a left and right half. The left half should have a - smooth gradient, and the right half should have a quantized - gradient. In particular, the right half's should consist of blocks - of the same color for 1/16th active sensor pixel array width. The - least significant bits in the quantized gradient should be copied - from the most significant bits of the smooth gradient. The height of - each bar should always be a multiple of 128. When this is not the - case, the pattern should repeat at the bottom of the image. - - name: TestPatternModePn9 - value: 4 - description: | - All pixel data is replaced by a pseudo-random sequence generated - from a PN9 512-bit sequence (typically implemented in hardware with - a linear feedback shift register). The generator should be reset at - the beginning of each frame, and thus each subsequent raw frame with - this test pattern should be exactly the same as the last. - - name: TestPatternModeCustom1 - value: 256 - description: | - The first custom test pattern. All custom patterns that are - available only on this camera device are at least this numeric - value. All of the custom test patterns will be static (that is the - raw image must not vary from frame to frame). - ... diff --git a/src/libcamera/control_ids_draft.yaml b/src/libcamera/control_ids_draft.yaml new file mode 100644 index 000000000000..e4f53ea51d7a --- /dev/null +++ b/src/libcamera/control_ids_draft.yaml @@ -0,0 +1,240 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Copyright (C) 2019, Google Inc. +# +%YAML 1.1 +--- +# Unless otherwise stated, all controls are bi-directional, i.e. they can be +# set through Request::controls() and returned out through Request::metadata(). +vendor: draft +controls: + - AePrecaptureTrigger: + type: int32_t + draft: true + description: | + Control for AE metering trigger. Currently identical to + ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER. + + Whether the camera device will trigger a precapture metering sequence + when it processes this request. + enum: + - name: AePrecaptureTriggerIdle + value: 0 + description: The trigger is idle. + - name: AePrecaptureTriggerStart + value: 1 + description: The pre-capture AE metering is started by the camera. + - name: AePrecaptureTriggerCancel + value: 2 + description: | + The camera will cancel any active or completed metering sequence. + The AE algorithm is reset to its initial state. + + - NoiseReductionMode: + type: int32_t + draft: true + description: | + Control to select the noise reduction algorithm mode. Currently + identical to ANDROID_NOISE_REDUCTION_MODE. + + Mode of operation for the noise reduction algorithm. + enum: + - name: NoiseReductionModeOff + value: 0 + description: No noise reduction is applied + - name: NoiseReductionModeFast + value: 1 + description: | + Noise reduction is applied without reducing the frame rate. + - name: NoiseReductionModeHighQuality + value: 2 + description: | + High quality noise reduction at the expense of frame rate. + - name: NoiseReductionModeMinimal + value: 3 + description: | + Minimal noise reduction is applied without reducing the frame rate. + - name: NoiseReductionModeZSL + value: 4 + description: | + Noise reduction is applied at different levels to different streams. + + - ColorCorrectionAberrationMode: + type: int32_t + draft: true + description: | + Control to select the color correction aberration mode. Currently + identical to ANDROID_COLOR_CORRECTION_ABERRATION_MODE. + + Mode of operation for the chromatic aberration correction algorithm. + enum: + - name: ColorCorrectionAberrationOff + value: 0 + description: No aberration correction is applied. + - name: ColorCorrectionAberrationFast + value: 1 + description: Aberration correction will not slow down the frame rate. + - name: ColorCorrectionAberrationHighQuality + value: 2 + description: | + High quality aberration correction which might reduce the frame + rate. + + - AeState: + type: int32_t + draft: true + description: | + Control to report the current AE algorithm state. Currently identical to + ANDROID_CONTROL_AE_STATE. + + Current state of the AE algorithm. + enum: + - name: AeStateInactive + value: 0 + description: The AE algorithm is inactive. + - name: AeStateSearching + value: 1 + description: The AE algorithm has not converged yet. + - name: AeStateConverged + value: 2 + description: The AE algorithm has converged. + - name: AeStateLocked + value: 3 + description: The AE algorithm is locked. + - name: AeStateFlashRequired + value: 4 + description: The AE algorithm would need a flash for good results + - name: AeStatePrecapture + value: 5 + description: | + The AE algorithm has started a pre-capture metering session. + \sa AePrecaptureTrigger + + - AwbState: + type: int32_t + draft: true + description: | + Control to report the current AWB algorithm state. Currently identical + to ANDROID_CONTROL_AWB_STATE. + + Current state of the AWB algorithm. + enum: + - name: AwbStateInactive + value: 0 + description: The AWB algorithm is inactive. + - name: AwbStateSearching + value: 1 + description: The AWB algorithm has not converged yet. + - name: AwbConverged + value: 2 + description: The AWB algorithm has converged. + - name: AwbLocked + value: 3 + description: The AWB algorithm is locked. + + - SensorRollingShutterSkew: + type: int64_t + draft: true + description: | + Control to report the time between the start of exposure of the first + row and the start of exposure of the last row. Currently identical to + ANDROID_SENSOR_ROLLING_SHUTTER_SKEW + + - LensShadingMapMode: + type: int32_t + draft: true + description: | + Control to report if the lens shading map is available. Currently + identical to ANDROID_STATISTICS_LENS_SHADING_MAP_MODE. + enum: + - name: LensShadingMapModeOff + value: 0 + description: No lens shading map mode is available. + - name: LensShadingMapModeOn + value: 1 + description: The lens shading map mode is available. + + - PipelineDepth: + type: int32_t + draft: true + description: | + Specifies the number of pipeline stages the frame went through from when + it was exposed to when the final completed result was available to the + framework. Always less than or equal to PipelineMaxDepth. Currently + identical to ANDROID_REQUEST_PIPELINE_DEPTH. + + The typical value for this control is 3 as a frame is first exposed, + captured and then processed in a single pass through the ISP. Any + additional processing step performed after the ISP pass (in example face + detection, additional format conversions etc) count as an additional + pipeline stage. + + - MaxLatency: + type: int32_t + draft: true + description: | + The maximum number of frames that can occur after a request (different + than the previous) has been submitted, and before the result's state + becomes synchronized. A value of -1 indicates unknown latency, and 0 + indicates per-frame control. Currently identical to + ANDROID_SYNC_MAX_LATENCY. + + - TestPatternMode: + type: int32_t + draft: true + description: | + Control to select the test pattern mode. Currently identical to + ANDROID_SENSOR_TEST_PATTERN_MODE. + enum: + - name: TestPatternModeOff + value: 0 + description: | + No test pattern mode is used. The camera device returns frames from + the image sensor. + - name: TestPatternModeSolidColor + value: 1 + description: | + Each pixel in [R, G_even, G_odd, B] is replaced by its respective + color channel provided in test pattern data. + \todo Add control for test pattern data. + - name: TestPatternModeColorBars + value: 2 + description: | + All pixel data is replaced with an 8-bar color pattern. The vertical + bars (left-to-right) are as follows; white, yellow, cyan, green, + magenta, red, blue and black. Each bar should take up 1/8 of the + sensor pixel array width. When this is not possible, the bar size + should be rounded down to the nearest integer and the pattern can + repeat on the right side. Each bar's height must always take up the + full sensor pixel array height. + - name: TestPatternModeColorBarsFadeToGray + value: 3 + description: | + The test pattern is similar to TestPatternModeColorBars, + except that each bar should start at its specified color at the top + and fade to gray at the bottom. Furthermore each bar is further + subdevided into a left and right half. The left half should have a + smooth gradient, and the right half should have a quantized + gradient. In particular, the right half's should consist of blocks + of the same color for 1/16th active sensor pixel array width. The + least significant bits in the quantized gradient should be copied + from the most significant bits of the smooth gradient. The height of + each bar should always be a multiple of 128. When this is not the + case, the pattern should repeat at the bottom of the image. + - name: TestPatternModePn9 + value: 4 + description: | + All pixel data is replaced by a pseudo-random sequence generated + from a PN9 512-bit sequence (typically implemented in hardware with + a linear feedback shift register). The generator should be reset at + the beginning of each frame, and thus each subsequent raw frame with + this test pattern should be exactly the same as the last. + - name: TestPatternModeCustom1 + value: 256 + description: | + The first custom test pattern. All custom patterns that are + available only on this camera device are at least this numeric + value. All of the custom test patterns will be static (that is the + raw image must not vary from frame to frame). + +... diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 303eee84a77e..e965b72e015a 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -128,7 +128,7 @@ endif control_sources = [] foreach source, mode : control_source_files - input_files = files(source +'.yaml') + input_files = files([source +'.yaml', source + '_draft.yaml']) # Add the vendor specific files to the input. if mode == 'controls' diff --git a/src/libcamera/property_ids.cpp.in b/src/libcamera/property_ids.cpp.in index ddbe714c3f00..b72e12e4cc70 100644 --- a/src/libcamera/property_ids.cpp.in +++ b/src/libcamera/property_ids.cpp.in @@ -23,14 +23,7 @@ namespace properties { ${controls_doc} -/** - * \brief Namespace for libcamera draft properties - */ -namespace draft { - -${draft_controls_doc} - -} /* namespace draft */ +${vendor_controls_doc} ${vendor_controls_doc} @@ -41,13 +34,8 @@ ${vendor_controls_doc} */ ${controls_def} -namespace draft { - -${draft_controls_def} - -} /* namespace draft */ - ${vendor_controls_def} + #endif /** diff --git a/src/libcamera/property_ids.yaml b/src/libcamera/property_ids.yaml index 45f3609b4236..834454a4e087 100644 --- a/src/libcamera/property_ids.yaml +++ b/src/libcamera/property_ids.yaml @@ -701,37 +701,4 @@ controls: Different cameras may report identical devices. - # ---------------------------------------------------------------------------- - # Draft properties section - - - ColorFilterArrangement: - type: int32_t - draft: true - description: | - The arrangement of color filters on sensor; represents the colors in the - top-left 2x2 section of the sensor, in reading order. Currently - identical to ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT. - enum: - - name: RGGB - value: 0 - description: RGGB Bayer pattern - - name: GRBG - value: 1 - description: GRBG Bayer pattern - - name: GBRG - value: 2 - description: GBRG Bayer pattern - - name: BGGR - value: 3 - description: BGGR Bayer pattern - - name: RGB - value: 4 - description: | - Sensor is not Bayer; output has 3 16-bit values for each pixel, - instead of just 1 16-bit value per pixel. - - name: MONO - value: 5 - description: | - Sensor is not Bayer; output consists of a single colour channel. - ... diff --git a/src/libcamera/property_ids_draft.yaml b/src/libcamera/property_ids_draft.yaml new file mode 100644 index 000000000000..62f0e242d0c6 --- /dev/null +++ b/src/libcamera/property_ids_draft.yaml @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Copyright (C) 2019, Google Inc. +# +%YAML 1.1 +--- +vendor: draft +controls: + - ColorFilterArrangement: + type: int32_t + vendor: draft + description: | + The arrangement of color filters on sensor; represents the colors in the + top-left 2x2 section of the sensor, in reading order. Currently + identical to ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT. + enum: + - name: RGGB + value: 0 + description: RGGB Bayer pattern + - name: GRBG + value: 1 + description: GRBG Bayer pattern + - name: GBRG + value: 2 + description: GBRG Bayer pattern + - name: BGGR + value: 3 + description: BGGR Bayer pattern + - name: RGB + value: 4 + description: | + Sensor is not Bayer; output has 3 16-bit values for each pixel, + instead of just 1 16-bit value per pixel. + - name: MONO + value: 5 + description: | + Sensor is not Bayer; output consists of a single colour channel. + +... diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py index e2ddad8581fd..e0695635dbcc 100755 --- a/src/py/libcamera/gen-py-controls.py +++ b/src/py/libcamera/gen-py-controls.py @@ -36,10 +36,7 @@ def generate_py(controls, mode): vendor_defs.append('\tauto {} = py::class_(controls, \"{}\");'.format(vendor, vendor, vendor)) vendors.append(vendor) - if ctrl.get('draft'): - ns = 'libcamera::{}::draft::'.format(mode) - container = 'draft' - elif vendor != 'libcamera': + if vendor != 'libcamera': ns = 'libcamera::{}::{}::'.format(mode, vendor) container = vendor else: diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build index ea38ad6ca829..9641862a4e9b 100644 --- a/src/py/libcamera/meson.build +++ b/src/py/libcamera/meson.build @@ -28,7 +28,8 @@ pycamera_sources = files([ # Generate controls -gen_py_controls_input_files = files('../../libcamera/control_ids.yaml') +gen_py_controls_input_files = files(['../../libcamera/control_ids.yaml', + '../../libcamera/control_ids_draft.yaml']) gen_py_controls_template = files('py_controls_generated.cpp.in') gen_py_controls = files('gen-py-controls.py') @@ -45,7 +46,8 @@ pycamera_sources += custom_target('py_gen_controls', # Generate properties -gen_py_property_enums_input_files = files('../../libcamera/property_ids.yaml') +gen_py_property_enums_input_files = files(['../../libcamera/property_ids.yaml', + '../../libcamera/property_ids_draft.yaml']) gen_py_properties_template = files('py_properties_generated.cpp.in') foreach file : vendor_prop_files diff --git a/src/py/libcamera/py_controls_generated.cpp.in b/src/py/libcamera/py_controls_generated.cpp.in index ec4b55ef2011..8d282ce51856 100644 --- a/src/py/libcamera/py_controls_generated.cpp.in +++ b/src/py/libcamera/py_controls_generated.cpp.in @@ -17,16 +17,11 @@ class PyControls { }; -class PyDraftControls -{ -}; - ${vendors_class_def} void init_py_controls_generated(py::module& m) { auto controls = py::class_(m, "controls"); - auto draft = py::class_(controls, "draft"); ${vendors_defs} ${controls} diff --git a/src/py/libcamera/py_properties_generated.cpp.in b/src/py/libcamera/py_properties_generated.cpp.in index f7b5ec8c635d..1fa1967a9672 100644 --- a/src/py/libcamera/py_properties_generated.cpp.in +++ b/src/py/libcamera/py_properties_generated.cpp.in @@ -26,8 +26,7 @@ ${vendors_class_def} void init_py_properties_generated(py::module& m) { auto controls = py::class_(m, "properties"); - auto draft = py::class_(controls, "draft"); -${vendors_defs} +${vendors_defs} ${controls} } diff --git a/utils/gen-controls.py b/utils/gen-controls.py index 9eede8940f24..f20e4eafcc2f 100755 --- a/utils/gen-controls.py +++ b/utils/gen-controls.py @@ -85,11 +85,6 @@ class Control(object): """Is the control an enumeration""" return self.__enum_values is not None - @property - def is_draft(self): - """Is the control a draft control""" - return self.__data.get('draft') is not None - @property def vendor(self): """The vendor string, or None""" @@ -100,12 +95,6 @@ class Control(object): """The control name (CamelCase)""" return self.__name - @property - def q_name(self): - """The control name, qualified with a namespace""" - ns = 'draft::' if self.is_draft else '' - return ns + self.__name - @property def type(self): typ = self.__data.get('type') @@ -158,7 +147,7 @@ ${description} for ctrl in controls: id_name = snake_case(ctrl.name).upper() - vendor = 'draft' if ctrl.is_draft else ctrl.vendor + vendor = ctrl.vendor if vendor not in ctrls_doc: ctrls_doc[vendor] = [] ctrls_def[vendor] = [] @@ -209,7 +198,7 @@ ${description} target_doc.append(doc_template.substitute(info)) target_def.append(def_template.substitute(info)) - target_ctrls_map.append('\t{ ' + id_name + ', &' + ctrl.q_name + ' },') + target_ctrls_map.append('\t{ ' + id_name + ', &' + ctrl.name + ' },') vendor_ctrl_doc_sub = [] vendor_ctrl_template = string.Template(''' @@ -219,11 +208,11 @@ ${vendor_controls_str} } /* namespace ${vendor} */''') - for vendor in [v for v in ctrls_map.keys() if v not in ['libcamera', 'draft']]: + for vendor in [v for v in ctrls_map.keys() if v != 'libcamera']: vendor_ctrl_doc_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, 'vendor_controls_str': '\n\n'.join(ctrls_doc[vendor])})) vendor_ctrl_def_sub = [] - for vendor in [v for v in ctrls_map.keys() if v not in ['libcamera', 'draft']]: + for vendor in [v for v in ctrls_map.keys() if v != 'libcamera']: vendor_ctrl_def_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, 'vendor_controls_str': '\n'.join(ctrls_def[vendor])})) vendor_ctrl_map_sub = [] @@ -241,16 +230,14 @@ ${vendor_controls_map} } /* namespace ${vendor} */ ''') - for vendor in [v for v in ctrls_map.keys() if v not in ['libcamera', 'draft']]: + for vendor in [v for v in ctrls_map.keys() if v != 'libcamera']: vendor_ctrl_map_sub.append(vendor_ctrl_template.substitute({'vendor': vendor, 'vendor_controls_map': '\n'.join(ctrls_map[vendor])})) return { 'controls_doc': '\n\n'.join(ctrls_doc['libcamera']), 'controls_def': '\n'.join(ctrls_def['libcamera']), - 'draft_controls_doc': '\n\n'.join(ctrls_doc['draft']), - 'draft_controls_def': '\n\n'.join(ctrls_def['draft']), - 'controls_map': '\n'.join(ctrls_map['libcamera'] + ctrls_map['draft']), + 'controls_map': '\n'.join(ctrls_map['libcamera']), 'vendor_controls_doc': '\n'.join(vendor_ctrl_doc_sub), 'vendor_controls_def': '\n'.join(vendor_ctrl_def_sub), 'vendor_controls_map': '\n'.join(vendor_ctrl_map_sub), @@ -270,7 +257,7 @@ def generate_h(controls, mode, ranges): for ctrl in controls: id_name = snake_case(ctrl.name).upper() - vendor = 'draft' if ctrl.is_draft else ctrl.vendor + vendor = ctrl.vendor if vendor not in ctrls: if vendor not in ranges.keys(): raise RuntimeError(f'Control id range is not defined for vendor {vendor}') @@ -278,8 +265,7 @@ def generate_h(controls, mode, ranges): ids[vendor] = [] ctrls[vendor] = [] - # Core and draft controls use the same ID value - target_ids = ids['libcamera'] if vendor in ['libcamera', 'draft'] else ids[vendor] + target_ids = ids[vendor] target_ids.append('\t' + id_name + ' = ' + str(id_value[vendor]) + ',') info = { @@ -287,11 +273,7 @@ def generate_h(controls, mode, ranges): 'type': ctrl.type, } - target_ctrls = ctrls['libcamera'] - if ctrl.is_draft: - target_ctrls = ctrls['draft'] - elif vendor != 'libcamera': - target_ctrls = ctrls[vendor] + target_ctrls = ctrls[vendor] if ctrl.is_enum: target_ctrls.append(enum_template_start.substitute(info)) @@ -332,7 +314,7 @@ ${vendor_controls} ''') vendor_sub = [] - for vendor in [v for v in ctrls.keys() if v not in ['libcamera', 'draft']]: + for vendor in [v for v in ctrls.keys() if v != 'libcamera']: vendor_sub.append(vendor_template.substitute({'mode': mode.upper(), 'vendor': vendor, 'vendor_def': vendor.upper(), @@ -342,7 +324,6 @@ ${vendor_controls} return { 'ids': '\n'.join(ids['libcamera']), 'controls': '\n'.join(ctrls['libcamera']), - 'draft_controls': '\n'.join(ctrls['draft']), 'vendor_controls': '\n'.join(vendor_sub) } From patchwork Tue Nov 21 14:53:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 19221 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 9CB62C328F for ; Tue, 21 Nov 2023 14:54:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 48A2B629C6; Tue, 21 Nov 2023 15:54:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1700578446; bh=VCa2KmEboVJanCSpihCW3DXtXj0h/UBsipooWVda5uA=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=uDD1f2omAEld30O76lq12o4fCgyqJqm+9AMNq4qPe39U3YJ3MfqeyJQ073VaT1/8o lE+42i0y0l0XY9QXu6c3eAv90VvcIekIbGnoFXmgakmaTcC/gR/t79mOsfCtfaqDy8 vbSumPAI1FmP5kjG8Atsu0bkmSAHW4UqjHxfCl1RQ3gla8qrwmfMVCEO3nIg7LcT6T MpUH8axQPVNbkNVgqeXW5O37mVRtq/z5PkklTWpEx4JJE3wyCs2PUoujXo732GEtNY oZ6Z9JnIYWkG6Eg6zKbNCAMfnCzLZ2knn0x6RRC4wMO+9x16MQ7Bqgn3usp8MfEJWZ +hwtmFDbShE1w== Received: from mail-wm1-x332.google.com (mail-wm1-x332.google.com [IPv6:2a00:1450:4864:20::332]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 56487629C7 for ; Tue, 21 Nov 2023 15:54:04 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="RHDdelsN"; dkim-atps=neutral Received: by mail-wm1-x332.google.com with SMTP id 5b1f17b1804b1-4084b0223ccso26071715e9.2 for ; Tue, 21 Nov 2023 06:54:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1700578443; x=1701183243; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=c6L1W2HLRfk9Spk6pPsjQsBwMqr3C4mCLeQWt4Cm0dw=; b=RHDdelsNgeGnsmXmu2LW+LO+FelKDn9GFjHSRvc4JrVOu+IG8+1uG+5ratg3kT6ncF yAx5hNc8YlAtu5vyQKnvifcOkC+7QSLv4z2L7ZX4Js5W8NeslXCGVuHWhuXOssBHBubw xB+euny02xzMv7+Hp4krw612baxBeX+/h4v5asnn3uB1Rb5VwR3ti91ep8Qap00blyep KE3bZtRkKxiPzgoRonv3HDZyyPN00CW8a2EjD0VOsCFEKUPzhHi3m7+hkMUJnXW3N5lq wpt/eCotnC4qgK2GSA3kTVGhTILqW6MtAtEuYQJN2wAsAPGpkH+ej2ZSK3Oep4D2R/70 2aKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700578443; x=1701183243; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=c6L1W2HLRfk9Spk6pPsjQsBwMqr3C4mCLeQWt4Cm0dw=; b=ZQV2YcepwiZd6PoitejhS9/uY5jK+cqivPgt9n2d+QVgPcDla0eMZg2zy9Q029UyAN 1avECvwEjxbC+8Wbz6NPH/IiLahXCB8/OC4Brd95sLz3q0Ca+XCIChPl6JqDUGu+gzwn SStKK8hfb76YZNSPvz4hmzsM2qy5H0G7mzIUqGXOaiSKrlFUPitj1NHS1Nxk937Pe/Ad bIu0PIA66K4g6I2btOBLL0MW0v/ul74hgmUZmNb5aq2XRp28GkIqJxXUiFGkN7ZPAWDU hLxBT4M5bcqfW5DtkJ7L0lXi0kV9O37NKsM7/UZ8mYnJZK4F2Qd6bQrl7ANfWqiIl/eW mHGw== X-Gm-Message-State: AOJu0YxUpijKlvUBkIoXRYy4SumQqEslAejyWLwXaDKuKxrstBRjhclk RDxoIu6Igl221a3gwacPW35HPf4TS2Zg6nA6qHzvYg== X-Google-Smtp-Source: AGHT+IEpbXnb4sDiusV2bk3QMZvVJbu52VklRBmtiTNzi7qKZSaO1n26InngkKAvaVtxH7zYHAsPdA== X-Received: by 2002:a05:600c:19cc:b0:406:f832:6513 with SMTP id u12-20020a05600c19cc00b00406f8326513mr8107884wmq.3.1700578443600; Tue, 21 Nov 2023 06:54:03 -0800 (PST) Received: from localhost.localdomain ([93.93.133.154]) by smtp.gmail.com with ESMTPSA id h18-20020a05600c351200b004063ea92492sm17570968wmq.22.2023.11.21.06.54.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Nov 2023 06:54:02 -0800 (PST) To: libcamera-devel@lists.libcamera.org Date: Tue, 21 Nov 2023 14:53:50 +0000 Message-Id: <20231121145350.5956-7-naush@raspberrypi.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231121145350.5956-1-naush@raspberrypi.com> References: <20231121145350.5956-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 6/6] documentation: Document vendor specific control and properties handling X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Naushir Patuck via libcamera-devel From: Naushir Patuck Reply-To: Naushir Patuck Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add some documentation to the pipeline handler file describing how to implement and handle vendor specific controls and properties with a small example. Signed-off-by: Naushir Patuck Reviewed-by: Laurent Pinchart --- Documentation/guides/pipeline-handler.rst | 52 +++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/Documentation/guides/pipeline-handler.rst b/Documentation/guides/pipeline-handler.rst index 10b9c75c2a7f..26977164accf 100644 --- a/Documentation/guides/pipeline-handler.rst +++ b/Documentation/guides/pipeline-handler.rst @@ -672,6 +672,58 @@ handling controls: #include #include +Vendor-specific controls and properties +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Vendor-specific controls and properties must be defined in a separate YAML file +and included in the build by defining the pipeline handler to file mapping in +include/libcamera/meson.build. + +For example, adding a Raspberry Pi vendor control file for the PiSP pipeline +handler is done with the following mapping: + +.. code-block:: meson + + vendor_controls_mapping = { + # Mapping of vendor (pipeline handler) specific controls files + 'controls': + { + 'rpi/pisp': 'control_ids_rpi.yaml', + }, + # Mapping of vendor (pipeline handler) specific properties files + 'properties': + { + + } + } + +Vendor-specific controls and properties must contain a `vendor: ` +tag in the YAML file. Every unique vendor tag must define a unique and +non-overlapping range of reserved control IDs in src/libcamera/control_ranges.yaml. + +For example, the following block defines a vendor-specific control with the +`rpi` vendor tag: + +.. code-block:: yaml + + vendor: rpi + controls: + - PispConfigDumpFile: + type: string + description: | + Triggers the Raspberry Pi PiSP pipeline handler to generate a JSON + formatted dump of the Backend configuration to the filename given by the + value of the control. + + +This controls will be generated in the vendor-specific namespace +`libcamera::controls::rpi`. Additionally a `#define +LIBCAMERA_HAS_RPI_VENDOR_CONTROLS` will be available to allow applications to +test for the availability of these controls. + +Note that libcamera core controls are defined with the `vendor: libcamera` tag +and libcamera draft controls are defined with the `vendor: draft` tag. + Generating a default configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~