#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2019, Google Inc. # # Author: Laurent Pinchart # # gen-controls.py - Generate control definitions from YAML import argparse from functools import reduce import operator import string import sys import yaml class ControlEnum(object): def __init__(self, data): self.__data = data @property def description(self): """The enum description""" return self.__data.get('description') @property def name(self): """The enum name""" return self.__data.get('name') @property def value(self): """The enum value""" return self.__data.get('value') class Control(object): def __init__(self, name, data): self.__name = name self.__data = data self.__enum_values = None self.__size = None enum_values = data.get('enum') if enum_values is not None: self.__enum_values = [ControlEnum(enum) for enum in enum_values] size = self.__data.get('size') if size is not None: if len(size) == 0: raise RuntimeError(f'Control `{self.__name}` size must have at least one dimension') # Compute the total number of elements in the array. If any of the # array dimension is a string, the array is variable-sized. num_elems = 1 for dim in size: if type(dim) is str: num_elems = 0 break dim = int(dim) if dim <= 0: raise RuntimeError(f'Control `{self.__name}` size must have positive values only') num_elems *= dim self.__size = num_elems @property def description(self): """The control description""" return self.__data.get('description') @property def enum_values(self): """The enum values, if the control is an enumeration""" if self.__enum_values is None: return for enum in self.__enum_values: yield enum @property def is_enum(self): """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 name(self): """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') size = self.__data.get('size') if typ == 'string': return 'std::string' if self.__size is None: return typ if self.__size: return f"Span" else: return f"Span" def snake_case(s): return ''.join([c.isupper() and ('_' + c) or c for c in s]).strip('_') def format_description(description): description = description.strip('\n').split('\n') description[0] = '\\brief ' + description[0] return '\n'.join([(line and ' * ' or ' *') + line for line in description]) def generate_cpp(controls): enum_doc_start_template = string.Template('''/** * \\enum ${name}Enum * \\brief Supported ${name} values''') enum_doc_value_template = string.Template(''' * \\var ${value} ${description}''') doc_template = string.Template('''/** * \\var ${name} ${description} */''') def_template = string.Template('extern const Control<${type}> ${name}(${id_name}, "${name}");') enum_values_doc = string.Template('''/** * \\var ${name}Values * \\brief List of all $name supported values */''') 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 = [] for ctrl in controls: id_name = snake_case(ctrl.name).upper() info = { 'name': ctrl.name, 'type': ctrl.type, 'description': format_description(ctrl.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 if ctrl.is_enum: enum_doc = [] enum_doc.append(enum_doc_start_template.substitute(info)) num_entries = 0 for enum in ctrl.enum_values: value_info = { 'name': ctrl.name, 'value': enum.name, 'description': format_description(enum.description), } enum_doc.append(enum_doc_value_template.substitute(value_info)) num_entries += 1 enum_doc = '\n *\n'.join(enum_doc) enum_doc += '\n */' target_doc.append(enum_doc) values_info = { 'name': info['name'], 'size': num_entries, } /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2020, Google Inc. * * camera_worker.h - Process capture requests on behalf of the Camera HAL */ #ifndef __ANDROID_CAMERA_WORKER_H__ #define __ANDROID_CAMERA_WORKER_H__ #include <memory> #include <stdint.h> #include <libcamera/base/object.h> #include <libcamera/base/thread.h> #include <libcamera/camera.h> #include <libcamera/framebuffer.h> #include <libcamera/request.h> #include <libcamera/stream.h> class CameraDevice; class CaptureRequest { public: CaptureRequest(libcamera::Camera *camera, uint64_t cookie); const std::vector<int> &fences() const { return acquireFences_; } libcamera::ControlList &controls() { return request_->controls(); } const libcamera::ControlList &metadata() const { return request_->metadata(); } unsigned long cookie() const { return request_->cookie(); } void addBuffer(libcamera::Stream *stream, libcamera::FrameBuffer *buffer, int fence); void queue(); private: libcamera::Camera *camera_; std::vector<int> acquireFences_; std::unique_ptr<libcamera::Request> request_; }; class CameraWorker : private libcamera::Thread { public: CameraWorker(); void start(); void stop(); void queueRequest(CaptureRequest *request); protected: void run() override; private: class Worker : public libcamera::Object { public: void processRequest(CaptureRequest *request); private: int waitFence(int fence); }; Worker worker_; }; #endif /* __ANDROID_CAMERA_WORKER_H__ */