From patchwork Fri Sep 2 15:00:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 17281 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 3E76FC0DA4 for ; Fri, 2 Sep 2022 15:00:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B9EF461FF2; Fri, 2 Sep 2022 17:00:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1662130839; bh=YgBnDfr97uKlJZ/OtsIWYvU8FWEj79b6TVXzX7mXKGY=; h=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=wFiw3KqL6nsYkkUNpE1gXd/KezMnUa+6YsE9+po5k3HFyQrCER0DKSfXp3tN9n0S2 PDoGQtldjJw4nLm2d1RwJn9Z4vi/TF5uaQIgP0YFRe/h7yCQ75T+qdWUd4kfO9HUUM NeVL8y0vf0hm0Ld781n4ZEnzOxknR3p64j2lo14thASaGVnkHb2odI93xPCn7J1aV7 cR3FAmRYCaZe1lJlDICdWehLauqFZL/QK9t+v9Dvh9B1V9ECcTpLk7+IgbljLMFVIi 8VPUL45yV3eAKaytUxS9hwMkEFEGRcYLoWDe0ftt58jjQXmLUNNBxvsr97394nnm8Q ErGsQ56/N0Rfg== Received: from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net [217.70.183.194]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 83D7761F9D for ; Fri, 2 Sep 2022 17:00:37 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 056764000C; Fri, 2 Sep 2022 15:00:36 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Fri, 2 Sep 2022 17:00:31 +0200 Message-Id: <20220902150031.31184-1-jacopo@jmondi.org> X-Mailer: git-send-email 2.37.2 MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH] cam: capture_script: Introduce 'loop' property 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 capture script support for properties that control the script execution. Script properties are specified in a 'properties' section before the actual list of controls specified in the 'frames' section. Define a first 'loop' property that allows to repeat the frame list periodically. All the frame ids in the 'frames' section shall be smaller than the loop control. Modify the capture script example to show usage of the 'loop' property and better document the frames list while at it. Signed-off-by: Jacopo Mondi Reviewed-by: Paul Elder Reviewed-by: Laurent Pinchart --- src/cam/capture-script.yaml | 50 +++++++++++------------ src/cam/capture_script.cpp | 79 +++++++++++++++++++++++++++++++++++-- src/cam/capture_script.h | 3 ++ 3 files changed, 102 insertions(+), 30 deletions(-) diff --git a/src/cam/capture-script.yaml b/src/cam/capture-script.yaml index 6a749bc60cf7..dbea4a9f01a7 100644 --- a/src/cam/capture-script.yaml +++ b/src/cam/capture-script.yaml @@ -5,6 +5,20 @@ # A capture script allows to associate a list of controls and their values # to frame numbers. +# The script allows to define a list of frames associated with controls and +# an optional list of properties that controls the script behaviour +# +# properties: +# - loop: idx +# Repeat the controls every 'idx' frames. +# +# frames: +# - frameid: +# Control1: value1 +# Control2: value2 +# +# List of frame ids with associated a list of controls to be applied +# # \todo Formally define the capture script structure with a schema # Notes: @@ -12,35 +26,17 @@ # libcamera::controls:: enumeration # - Controls not supported by the camera currently operated are ignored # - Frame numbers shall be monotonically incrementing, gaps are allowed +# - If a loop limit is specified, frame numbers in the 'frames' list shall be +# strictly minor than the loop control -# Example: -frames: - - 1: - Brightness: 0.0 +# Example: Turn brightness up and down every 50 frames - - 40: - Brightness: 0.2 +properties: + - loop: 50 - - 80: - Brightness: 0.4 - - - 120: - Brightness: 0.8 - - - 160: - Brightness: 0.4 - - - 200: - Brightness: 0.2 - - - 240: +frames: + - 0: Brightness: 0.0 - - 280: - Brightness: -0.2 - - - 300: - Brightness: -0.4 - - - 340: - Brightness: -0.8 + - 25: + Brightness: 0.8 diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp index 5e85b3ca604c..52bf19961c17 100644 --- a/src/cam/capture_script.cpp +++ b/src/cam/capture_script.cpp @@ -15,7 +15,7 @@ using namespace libcamera; CaptureScript::CaptureScript(std::shared_ptr camera, const std::string &fileName) - : camera_(camera), valid_(false) + : camera_(camera), loop_(0), valid_(false) { FILE *fh = fopen(fileName.c_str(), "r"); if (!fh) { @@ -44,8 +44,13 @@ CaptureScript::CaptureScript(std::shared_ptr camera, const ControlList &CaptureScript::frameControls(unsigned int frame) { static ControlList controls{}; + unsigned int idx = frame; - auto it = frameControls_.find(frame); + /* If we loop, repeat the controls every 'loop_' frames. */ + if (loop_) + idx = frame % loop_; + + auto it = frameControls_.find(idx); if (it == frameControls_.end()) return controls; @@ -149,7 +154,11 @@ int CaptureScript::parseScript(FILE *script) std::string section = eventScalarValue(event); - if (section == "frames") { + if (section == "properties") { + ret = parseProperties(); + if (ret) + return ret; + } else if (section == "frames") { ret = parseFrames(); if (ret) return ret; @@ -161,6 +170,64 @@ int CaptureScript::parseScript(FILE *script) } } +int CaptureScript::parseProperty() +{ + EventPtr event = nextEvent(YAML_MAPPING_START_EVENT); + if (!event) + return -EINVAL; + + std::string prop = parseScalar(); + if (prop.empty()) + return -EINVAL; + + if (prop == "loop") { + event = nextEvent(); + if (!event) + return -EINVAL; + + std::string value = eventScalarValue(event); + if (value.empty()) + return -EINVAL; + + loop_ = atoi(value.c_str()); + if (!loop_) { + std::cerr << "Invalid loop limit: " << loop_ << std::endl; + return -EINVAL; + } + } else { + std::cerr << "Unsupported property: " << prop << std::endl; + return -EINVAL; + } + + event = nextEvent(YAML_MAPPING_END_EVENT); + if (!event) + return -EINVAL; + + return 0; +} + +int CaptureScript::parseProperties() +{ + EventPtr event = nextEvent(YAML_SEQUENCE_START_EVENT); + if (!event) + return -EINVAL; + + while (1) { + if (event->type == YAML_SEQUENCE_END_EVENT) + return 0; + + int ret = parseProperty(); + if (ret) + return ret; + + event = nextEvent(); + if (!event) + return -EINVAL; + } + + return 0; +} + int CaptureScript::parseFrames() { EventPtr event = nextEvent(YAML_SEQUENCE_START_EVENT); @@ -191,6 +258,12 @@ int CaptureScript::parseFrame(EventPtr event) return -EINVAL; unsigned int frameId = atoi(key.c_str()); + if (loop_ && frameId >= loop_) { + std::cerr + << "Frame id (" << frameId << ") shall be smaller than" + << "loop limit (" << loop_ << ")" << std::endl; + return -EINVAL; + } event = nextEvent(YAML_MAPPING_START_EVENT); if (!event) diff --git a/src/cam/capture_script.h b/src/cam/capture_script.h index fffe67e5a3df..7a0ddebb00b5 100644 --- a/src/cam/capture_script.h +++ b/src/cam/capture_script.h @@ -40,6 +40,7 @@ private: std::map frameControls_; std::shared_ptr camera_; yaml_parser_t parser_; + unsigned int loop_; bool valid_; EventPtr nextEvent(yaml_event_type_t expectedType = YAML_NO_EVENT); @@ -49,6 +50,8 @@ private: int parseScript(FILE *script); + int parseProperties(); + int parseProperty(); int parseFrames(); int parseFrame(EventPtr event); int parseControl(EventPtr event, libcamera::ControlList &controls);