From patchwork Wed May 18 17:19:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 15975 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 CC1C9C326C for ; Wed, 18 May 2022 17:19:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EB43D6565C; Wed, 18 May 2022 19:19:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1652894370; bh=FYmJbgOwMo3b8+Y4Ss0p3R4ccq6wZMoksZrM8tx0Tl8=; 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=3L5s6Ffiav5n3H08HGcy9n4HTyxbvcesioF5LAQ7WwJywP0FUfP4a+qFxux9hckyp 3WZ8ks4FKfaIWhvPJHibmssnm4JepY0iOBL/DRN+AvYBjN6vAvOFIcV72h8jKDYFiX eROiw2kctZpBU45N1TB0vH6rh7m/pBk2N0KmRjx0QzGdc66hIAeHV4Z93akFgFEvc7 OXOUgm555c1Ht/xYifa5GWJSpQtWdPysf+8J+222an4mFx/jTbrj5Lh3y01eO/lHFd YFWRKl6a/WpY1Kv7Rdqhs6Kg3bvZVVxSJ/qlgk7C9XcoZj94jo/GHhJ1t0mDoT5ThU DDyjDYEBWUD2A== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5D00465656 for ; Wed, 18 May 2022 19:19:29 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 891FD240012; Wed, 18 May 2022 17:19:28 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Wed, 18 May 2022 19:19:17 +0200 Message-Id: <20220518171921.244168-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220518171921.244168-1-jacopo@jmondi.org> References: <20220518171921.244168-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/5] cam: Add a parser for capture 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: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a parser class to the cam test application to control the capture operations through a yaml script. The capture script currently allow to specify a list of controls and their associated values to be applied per-frame. Also add a trivial capture script example to showcase the intended script structure. Signed-off-by: Jacopo Mondi --- src/cam/capture-script.yaml | 44 ++++ src/cam/capture_script.cpp | 447 ++++++++++++++++++++++++++++++++++++ src/cam/capture_script.h | 57 +++++ src/cam/meson.build | 2 + 4 files changed, 550 insertions(+) create mode 100644 src/cam/capture-script.yaml create mode 100644 src/cam/capture_script.cpp create mode 100644 src/cam/capture_script.h diff --git a/src/cam/capture-script.yaml b/src/cam/capture-script.yaml new file mode 100644 index 000000000000..48eac5fedd46 --- /dev/null +++ b/src/cam/capture-script.yaml @@ -0,0 +1,44 @@ +# Capture scrip example +# +# A capture script allows to associate a list of controls and their values +# to frame numbers. + +# \todo Formally define the capture script structure with a schema + +# Notes: +# - Controls have to be specified by name, as defined in the +# libcamera::controls:: enumeration +# - Controls not supported by the camera currently operated are ignored +# - Frame numbers shall be monotonically incrementing, gaps are allowed + +# Example: +frames: + - 1: + Brightness: 0.0 + + - 40: + Brightness: 0.2 + + - 80: + Brightness: 0.4 + + - 120: + Brightness: 0.8 + + - 160: + Brightness: 0.4 + + - 200: + Brightness: 0.2 + + - 240: + Brightness: 0.0 + + - 280: + Brightness: -0.2 + + - 300: + Brightness: -0.4 + + - 340: + Brightness: -0.8 diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp new file mode 100644 index 000000000000..d153dac7b0de --- /dev/null +++ b/src/cam/capture_script.cpp @@ -0,0 +1,447 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * capture_script.cpp - Capture session configuration script + */ + +#include "capture_script.h" + +#include +#include +#include + +using namespace libcamera; + +namespace { + +/* + * Schema error debug function + * From: https://www.wpsoftware.net/andrew/pages/libyaml.html + */ +void printToken(yaml_token_t &token) +{ + std::string type; + + switch (token.type) { + case YAML_KEY_TOKEN: + printf("(Key token) "); + break; + case YAML_VALUE_TOKEN: + printf("(Value token) "); + break; + case YAML_BLOCK_SEQUENCE_START_TOKEN: + puts("Start Block (Sequence)"); + break; + case YAML_BLOCK_ENTRY_TOKEN: + puts("Start Block (Entry)"); + break; + case YAML_BLOCK_END_TOKEN: + puts("End block"); + break; + case YAML_BLOCK_MAPPING_START_TOKEN: + puts("[Block mapping]"); + break; + case YAML_SCALAR_TOKEN: + printf("scalar %s \n", token.data.scalar.value); + break; + default: + printf("Token type %u \n", token.type); + break; + } + std::cerr << std::endl; +} + +} /* namespace */ + +CaptureScript::CaptureScript(std::shared_ptr camera, std::string fileName) + : camera_(camera), scriptPath_(fileName), valid_(false) +{ + if (!std::filesystem::is_regular_file(scriptPath_)) { + std::cerr << "Capture script file not found: " + << scriptPath_ << std::endl; + return; + } + + FILE *fh = fopen(scriptPath_.c_str(), "r"); + if (!fh) { + int ret = -errno; + std::cerr << "Failed to open capture script " << scriptPath_ + << ": " << strerror(-ret) << std::endl; + return; + } + + /* + * Map the camera's controls to their name so that they can be + * easily identified when parsing the script file. + */ + for (const auto &[control, info] : camera_->controls()) + controls_[control->name()] = control; + + int ret = parseScript(fh); + fclose(fh); + if (ret) + return; + + valid_ = true; +} + +/* Retrieve the control list associated with a frame number. */ +const ControlList &CaptureScript::frameControls(unsigned int frame) +{ + static ControlList controls{}; + + auto it = frameControls_.find(frame); + if (it == frameControls_.end()) + return controls; + + return it->second; +} + +int CaptureScript::parseScript(FILE *script) +{ + int ret = yaml_parser_initialize(&parser_); + if (!ret) { + std::cerr << "Failed to initialize yaml parser" << std::endl; + return ret; + } + + yaml_parser_set_input_file(&parser_, script); + + yaml_token_t token; + yaml_parser_scan(&parser_, &token); + if (token.type != YAML_STREAM_START_TOKEN) { + std::cerr << "Configuration file not valid" << std::endl; + printToken(token); + yaml_token_delete(&token); + yaml_parser_delete(&parser_); + return -EINVAL; + } + yaml_token_delete(&token); + + yaml_parser_scan(&parser_, &token); + if (token.type != YAML_BLOCK_MAPPING_START_TOKEN) { + std::cerr << "Configuration file not valid" << std::endl; + printToken(token); + yaml_token_delete(&token); + yaml_parser_delete(&parser_); + return -EINVAL; + } + yaml_token_delete(&token); + + /* Capture script shall start with the "frames" key. */ + std::string section = parseKey(); + if (section != "frames") { + std::cerr << "Unsupported section: " << section << std::endl; + yaml_token_delete(&token); + yaml_parser_delete(&parser_); + return -EINVAL; + } + + yaml_parser_scan(&parser_, &token); + if (token.type != YAML_VALUE_TOKEN) { + std::cerr << "Configuration file not valid" << std::endl; + printToken(token); + yaml_token_delete(&token); + yaml_parser_delete(&parser_); + return -EINVAL; + } + yaml_token_delete(&token); + + parseFrames(); + + /* Consume the tokens on the stack until we don't hit an STREAM_END */ + do { + ret = 0; + + yaml_parser_scan(&parser_, &token); + switch (token.type) { + case YAML_STREAM_END_TOKEN: + ret = -ENOENT; + [[fallthrough]]; + default: + yaml_token_delete(&token); + break; + } + } while (ret >= 0); + + return 0; +} + +int CaptureScript::parseFrames() +{ + int ret; + + yaml_token_t token; + yaml_parser_scan(&parser_, &token); + if (token.type != YAML_BLOCK_SEQUENCE_START_TOKEN) { + std::cerr << "Configuration file not valid" << std::endl; + printToken(token); + yaml_token_delete(&token); + yaml_parser_delete(&parser_); + return -EINVAL; + } + yaml_token_delete(&token); + + do { + yaml_parser_scan(&parser_, &token); + switch (token.type) { + case YAML_BLOCK_ENTRY_TOKEN: + ret = parseFrame(); + yaml_token_delete(&token); + break; + case YAML_BLOCK_END_TOKEN: + ret = -ENODEV; + yaml_token_delete(&token); + break; + default: + ret = -EINVAL; + std::cerr << "Configuration file not valid" << std::endl; + printToken(token); + yaml_token_delete(&token); + yaml_parser_delete(&parser_); + } + } while (ret == 0); + + return ret != -ENODEV ? ret : 0; +} + +int CaptureScript::parseFrame() +{ + yaml_token_t token; + + yaml_parser_scan(&parser_, &token); + if (token.type != YAML_BLOCK_MAPPING_START_TOKEN) { + std::cerr << "Configuration file not valid" << std::endl; + printToken(token); + yaml_token_delete(&token); + yaml_parser_delete(&parser_); + return -EINVAL; + } + yaml_token_delete(&token); + + std::string key = parseKey(); + unsigned int frameId = atoi(key.c_str()); + + frameControls_[frameId] = parseControls(); + + return 0; +} + +ControlList CaptureScript::parseControls() +{ + ControlList controls{}; + yaml_token_t token; + + yaml_parser_scan(&parser_, &token); + if (token.type != YAML_VALUE_TOKEN) { + std::cerr << "Configuration file not valid" << std::endl; + printToken(token); + yaml_token_delete(&token); + yaml_parser_delete(&parser_); + return controls; + } + yaml_token_delete(&token); + + /* + * Whenever we get an unbalanced block_end token, we're done + * parsing the controls. + */ + int blockCounter = 0; + + do { + yaml_parser_scan(&parser_, &token); + + switch (token.type) { + case YAML_BLOCK_MAPPING_START_TOKEN: + blockCounter++; + yaml_token_delete(&token); + break; + case YAML_BLOCK_END_TOKEN: + blockCounter--; + yaml_token_delete(&token); + break; + case YAML_KEY_TOKEN: { + /* We expect a value after a key. */ + std::string controlName = parseKey(token); + std::string controlRepr = parseValue(); + + /* + * If the camera does not support the control just + * ignore it. + */ + auto controlIt = controls_.find(controlName); + if (controlIt == controls_.end()) { + std::cerr << "Unsupported control: " + << controlName << std::endl; + break; + } + + const ControlId *controlId = controlIt->second; + ControlValue val = unpackControl(controlId, controlRepr); + controls.set(controlId->id(), val); + break; + } + default: + /* Error condition */ + yaml_token_delete(&token); + break; + } + } while (blockCounter >= 0); + + return controls; +} + +std::string CaptureScript::parseKey(yaml_token_t &token) +{ + /* Make sure the token type is a key and get its value. */ + if (token.type != YAML_KEY_TOKEN) { + std::cerr << "Configuration file not valid" << std::endl; + printToken(token); + yaml_token_delete(&token); + yaml_parser_delete(&parser_); + return ""; + } + yaml_token_delete(&token); + + yaml_parser_scan(&parser_, &token); + if (token.type != YAML_SCALAR_TOKEN) { + yaml_token_delete(&token); + return ""; + } + + std::string value(reinterpret_cast(token.data.scalar.value), + token.data.scalar.length); + yaml_token_delete(&token); + + return value; +} + +std::string CaptureScript::parseKey() +{ + yaml_token_t token; + + yaml_parser_scan(&parser_, &token); + return parseKey(token); +} + +std::string CaptureScript::parseValue() +{ + yaml_token_t token; + + /* Make sure the token type is a value and get its content. */ + yaml_parser_scan(&parser_, &token); + if (token.type != YAML_VALUE_TOKEN) { + std::cerr << "Configuration file not valid" << std::endl; + printToken(token); + yaml_token_delete(&token); + yaml_parser_delete(&parser_); + return ""; + } + yaml_token_delete(&token); + + yaml_parser_scan(&parser_, &token); + if (token.type != YAML_SCALAR_TOKEN) { + yaml_token_delete(&token); + return ""; + } + + std::string value(reinterpret_cast(token.data.scalar.value), + token.data.scalar.length); + yaml_token_delete(&token); + + return value; +} + +void CaptureScript::unpackFailure(const ControlId *id, std::string repr) +{ + std::string ctrlType; + + switch (id->type()) { + case ControlTypeNone: + ctrlType = "none"; + break; + case ControlTypeBool: + ctrlType = "bool"; + break; + case ControlTypeByte: + ctrlType = "byte"; + break; + case ControlTypeInteger32: + ctrlType = "int32"; + break; + case ControlTypeInteger64: + ctrlType = "int64"; + break; + case ControlTypeFloat: + ctrlType = "float"; + break; + case ControlTypeString: + ctrlType = "string"; + break; + case ControlTypeRectangle: + ctrlType = "Rectangle"; + break; + case ControlTypeSize: + ctrlType = "Size"; + break; + } + + std::cerr << "Unsupported control \'" << repr <<"\'" << " for " + << ctrlType << " control " << id->name() << std::endl; +} + +ControlValue CaptureScript::unpackControl(const ControlId *id, std::string repr) +{ + ControlValue value{}; + + switch (id->type()) { + case ControlTypeNone: + break; + case ControlTypeBool: { + bool val; + + if (repr == "true") { + val = true; + } else if (repr == "false") { + val = false; + } else { + unpackFailure(id, repr); + return value; + } + + value.set(val); + break; + } + case ControlTypeByte: { + uint8_t val = strtol(repr.c_str(), NULL, 10); + value.set(val); + break; + } + case ControlTypeInteger32: { + int32_t val = strtol(repr.c_str(), NULL, 10); + value.set(val); + break; + } + case ControlTypeInteger64: { + int64_t val = strtoll(repr.c_str(), NULL, 10); + value.set(val); + break; + } + case ControlTypeFloat: { + float val = strtof(repr.c_str(), NULL); + value.set(val); + break; + } + case ControlTypeString: { + value.set(repr); + break; + } + case ControlTypeRectangle: + /* \todo Parse rectangles. */ + break; + case ControlTypeSize: + /* \todo Parse Sizes. */ + break; + } + + return value; +} diff --git a/src/cam/capture_script.h b/src/cam/capture_script.h new file mode 100644 index 000000000000..39fded1250a6 --- /dev/null +++ b/src/cam/capture_script.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * capture_script.h - Capture session configuration script + */ + +#pragma once + +#if defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE < 8 +#include +namespace std { +namespace filesystem = std::experimental::filesystem; +} +#else +#include +#endif + +#include +#include +#include + +#include +#include + +#include + +class CaptureScript +{ +public: + CaptureScript(std::shared_ptr camera, + std::string fileName); + + bool valid() const { return valid_; } + + const libcamera::ControlList &frameControls(unsigned int frame); + +private: + std::map controls_; + std::map frameControls_; + std::shared_ptr camera_; + std::filesystem::path scriptPath_; + yaml_parser_t parser_; + bool valid_; + + int parseScript(FILE *script); + + libcamera::ControlList parseControls(); + int parseFrames(); + int parseFrame(); + + std::string parseKey(yaml_token_t &token); + std::string parseKey(); + std::string parseValue(); + + void unpackFailure(const libcamera::ControlId *id, std::string repr); + libcamera::ControlValue unpackControl(const libcamera::ControlId *id, + std::string repr); +}; diff --git a/src/cam/meson.build b/src/cam/meson.build index afc0ea9f397a..60ecbdca0c38 100644 --- a/src/cam/meson.build +++ b/src/cam/meson.build @@ -11,6 +11,7 @@ cam_enabled = true cam_sources = files([ 'camera_session.cpp', + 'capture_script.cpp', 'event_loop.cpp', 'file_sink.cpp', 'frame_sink.cpp', @@ -59,6 +60,7 @@ cam = executable('cam', cam_sources, libsdl2, libsdl2_image, libevent, + libyaml, ], cpp_args : cam_cpp_args, install : true) From patchwork Wed May 18 17:19:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 15976 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 73FF0C3256 for ; Wed, 18 May 2022 17:19:35 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CC8F765665; Wed, 18 May 2022 19:19:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1652894371; bh=JNaqr7MSYw0dzUfV1uFphmmHof9QCzSh+0d9Y9+SsPM=; 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=IyfekSDhxq8QZ+hNe2+Ewjc7kApCAZpuoZx79fs8wcyfUmNJFr0ISkx7a+/VGQiTp uvQxlSK9N7g1Cw3SdL9D3n5BVzp7PnZ9Kod24W7oWgUdrPizvrHIAGpgvU2ZdNN/sO 1FNmIsJ52wuMBHHnjm4Fs/guNLejHnDCRQkYG4iO3CZflKkIzTiPT4+NiWgdqvmYTQ 0Neq+cQ0qZG8xzJ6bAeazdONm+OF9rOeclQCIxPlzgkph9HOiPi9MHl1gX91tMDQs6 kII/0h2gxHEYYV9Dp/z1BExLvwP5/5FcrHj28TWdfPqtPYB6DMWIQiDyNDKU2pmKWJ XNcaZ3jTpmSmA== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 30FE265656 for ; Wed, 18 May 2022 19:19:30 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 85757240004; Wed, 18 May 2022 17:19:29 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Wed, 18 May 2022 19:19:18 +0200 Message-Id: <20220518171921.244168-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220518171921.244168-1-jacopo@jmondi.org> References: <20220518171921.244168-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/5] cam: Queue requests unconditionally 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: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The CaptureSession::queueRequest() function increments the queueCount_ counter, which tracks the number of requests queued to the camera. The number of queued requests is currently compared with the capture limit which should instead only be compared with the number of captured frames, something which already happens in the CameraSession::processRequest() function. Remove the check and only compare the capture limit with the actual number of captured frames. If more requests than the frame capture limits end up being queued to the Camera, they will be released on Camera::stop(). Signed-off-by: Jacopo Mondi --- src/cam/camera_session.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/cam/camera_session.cpp b/src/cam/camera_session.cpp index 71e6bd605139..186072817367 100644 --- a/src/cam/camera_session.cpp +++ b/src/cam/camera_session.cpp @@ -327,9 +327,6 @@ int CameraSession::startCapture() int CameraSession::queueRequest(Request *request) { - if (captureLimit_ && queueCount_ >= captureLimit_) - return 0; - queueCount_++; return camera_->queueRequest(request); From patchwork Wed May 18 17:19:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 15977 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 D5D84C326C for ; Wed, 18 May 2022 17:19:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 47F5B65663; Wed, 18 May 2022 19:19:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1652894376; bh=WcIU6SytRpLU14Pp8vq5u3xirFD8W77rkyjrHk1KLE8=; 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=wZbDO5NfJwhi6Dch6OTsParh9EkdaLc2xyEQpDHkdQC6dCpZhDkp5w/p3ngZB7F9q aylvu/vr+nXKIraeP5iiKVfKtar+YYp2RltJKeQbAEQf45E6TzQ/2bxd2DyR12Dgbz 2SjpwhXRom3+wZqn6CqUjIRxm2PJdDV/bIt3S2XgttF4YDlNeb/acM/cApU6sFp6u0 /UjaElPEPsqx66kofmoHrQXmjTfcNUhXrnuQftsVqmZ2MJfGyRy71hb1Z5eNALqJnx TjyIGG32FV2jCtJpAcDyCNdutHgI3zY1CvRE3y7Okxvm7oCera2xzoSFR4GamNKn/h chSb9MqhAROVQ== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2883865663 for ; Wed, 18 May 2022 19:19:31 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 5D52C240002; Wed, 18 May 2022 17:19:30 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Wed, 18 May 2022 19:19:19 +0200 Message-Id: <20220518171921.244168-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220518171921.244168-1-jacopo@jmondi.org> References: <20220518171921.244168-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 3/5] cam: Queue requests through CameraSession::queueRequest() 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: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The CameraSession::processRequest() frame completion handler currently re-queues completed requests by calling Camera::queueRequests() explicitely. In order to maintain the CameraSession::queuedRequest_ counter up to date with the actual number of queued requests, call the CameraSession::queueRequest() instead of operating the Camera directly. Signed-off-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/cam/camera_session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cam/camera_session.cpp b/src/cam/camera_session.cpp index 186072817367..a1b447235009 100644 --- a/src/cam/camera_session.cpp +++ b/src/cam/camera_session.cpp @@ -423,7 +423,7 @@ void CameraSession::processRequest(Request *request) return; request->reuse(Request::ReuseBuffers); - camera_->queueRequest(request); + queueRequest(request); } void CameraSession::sinkRelease(Request *request) From patchwork Wed May 18 17:19:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 15978 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 28179C3256 for ; Wed, 18 May 2022 17:19:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C62C765657; Wed, 18 May 2022 19:19:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1652894377; bh=8HyIqYlgcijs87GVqQafUSzgkYmJqhd8vNFNgrcKhso=; 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=oYlhb+asmHjxwcgsoSPkxs06hsHz/8cwrWUkOXgPcyvlzNA3P/kFDKw9qdlgZ4muX n0SSI3gzzYromIP1jeT+NwrLHy3kMgOyrZ+y6J3HeQ9Ke3c0dHnIbzwpQqFZ2lRx+x 2BiOazp2vMb/P7fTmTJoziCWURwvtLu4gP1Y5weXtz7xRy+W1sa+ekVD6Lo0M6nSaG 9LckZZr2WnOgAG0yA8w7ygG/USDHrkzjes+w+156QtCl75OSj74DybRR1IasLp/mX8 0QOBU8M0bHmL/JLhPt7n4nmNEiW/K4wiV0QVSzFx6j0MstiwxphZ86ocMyjyM01o// jlYuSwcJE8BJA== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B4E9665664 for ; Wed, 18 May 2022 19:19:31 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 423D1240002; Wed, 18 May 2022 17:19:31 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Wed, 18 May 2022 19:19:20 +0200 Message-Id: <20220518171921.244168-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220518171921.244168-1-jacopo@jmondi.org> References: <20220518171921.244168-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 4/5] cam: Add a --script option 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: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a "--script" option to the cam test application to allow specify a capture script to be used to drive the capture session. Signed-off-by: Jacopo Mondi --- src/cam/main.cpp | 4 ++++ src/cam/main.h | 1 + 2 files changed, 5 insertions(+) diff --git a/src/cam/main.cpp b/src/cam/main.cpp index fd3108b05d25..3428075c03dd 100644 --- a/src/cam/main.cpp +++ b/src/cam/main.cpp @@ -162,6 +162,10 @@ int CamApp::parseOptions(int argc, char *argv[]) "Print the metadata for completed requests", "metadata", ArgumentNone, nullptr, false, OptCamera); + parser.addOption(OptCaptureScript, OptionString, + "Load a capture session configuration script from a file\n", + "script", ArgumentRequired, "script", false, + OptCamera); options_ = parser.parse(argc, argv); if (!options_.valid()) diff --git a/src/cam/main.h b/src/cam/main.h index 2b2858084bb1..5ec20e1496eb 100644 --- a/src/cam/main.h +++ b/src/cam/main.h @@ -22,4 +22,5 @@ enum { OptListControls = 256, OptStrictFormats = 257, OptMetadata = 258, + OptCaptureScript = 259, }; From patchwork Wed May 18 17:19:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 15979 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 C6763C326D for ; Wed, 18 May 2022 17:19:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6996A6565F; Wed, 18 May 2022 19:19:38 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1652894378; bh=wrUsBZ8CUJThDMA1C4NdibKePhHSga/f40FFTebgHQ8=; 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=JrPAkh1sd0MNchGY6RiTBncpmRV6i+MMdx17XVxOC9eOUZVC2Hom2VLrmZaIoRFTe XAiImy1QVTDjTSbux23X7U2FyPl9JNsHIfTYjEsOeNSdaDfJjm4WOm3f6BLPpPaNxO pUqDerLITVrZUjQM06lDwGkEjCgWcmQn5XctueKYhSjCxvt8GqB7Zt2taVUXEqNaws GplgSFzrtGRHrQtXDTkq47MkuJxBjSGdYxpKtDfZX2M38atgdv/wB0ovvp3rK9lky+ wMr2uw9a5b+g1OJ0R29s5nxz1grP+UQG/cU6LtfA3UwtvBtYFqmgkIsia7ZD0tR8Sw tqvQw29D0Q8iA== Received: from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net [217.70.183.193]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6565A6565D for ; Wed, 18 May 2022 19:19:32 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id DBF34240002; Wed, 18 May 2022 17:19:31 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Wed, 18 May 2022 19:19:21 +0200 Message-Id: <20220518171921.244168-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220518171921.244168-1-jacopo@jmondi.org> References: <20220518171921.244168-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 5/5] cam: Use script parser to set controls 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: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add to the CameraSession class a script parser instance, created conditionally to the OptCaptureScript option. If the script parser has been created, use it at queueRequest time to retrieve the list of controls that has to be associated with a Request, and populate Request::controls() with it before queueing it to the Camera. Signed-off-by: Jacopo Mondi --- src/cam/camera_session.cpp | 10 ++++++++++ src/cam/camera_session.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/src/cam/camera_session.cpp b/src/cam/camera_session.cpp index a1b447235009..74c2acd79499 100644 --- a/src/cam/camera_session.cpp +++ b/src/cam/camera_session.cpp @@ -94,6 +94,13 @@ CameraSession::CameraSession(CameraManager *cm, } #endif + if (options_.isSet(OptCaptureScript)) { + script_ = std::make_unique(camera_, + options_[OptCaptureScript].toString()); + if (!script_->valid()) + return; + } + switch (config->validate()) { case CameraConfiguration::Valid: break; @@ -327,6 +334,9 @@ int CameraSession::startCapture() int CameraSession::queueRequest(Request *request) { + if (script_) + request->controls() = script_->frameControls(queueCount_); + queueCount_++; return camera_->queueRequest(request); diff --git a/src/cam/camera_session.h b/src/cam/camera_session.h index bf966bd15ab0..2cca92df0079 100644 --- a/src/cam/camera_session.h +++ b/src/cam/camera_session.h @@ -21,6 +21,7 @@ #include #include +#include "capture_script.h" #include "options.h" class FrameSink; @@ -60,6 +61,8 @@ private: std::shared_ptr camera_; std::unique_ptr config_; + std::unique_ptr script_; + std::map streamNames_; std::unique_ptr sink_; unsigned int cameraIndex_;