From patchwork Wed Nov 2 16:05:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 17748 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 A0B2ABD16B for ; Wed, 2 Nov 2022 16:06:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F0ADE63075; Wed, 2 Nov 2022 17:06:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1667405164; bh=kWJCwMrYtYA7YYsvAfUaBZPCdyByOq/pHBM5DthqQ1U=; h=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=HWyQyh/3V+McJwkF9+ksl+hiT6joZWeDWijxTb2juNdEH8PShSinrHuTMe/6Dx5j6 Efnhmz0dVbI0cu6sc4sbbyXeAn6s1Nn7OrErcqVr5DNVr1FutY8tvU/YKJvnNSC0x9 xFVpE3ueGaH08ujTSgFvgQ6qJ1gvJ7eiblulkS9ufcnks6S/gTyhu5b9y5GRL8SPv0 0AzfOSFB82oEvTYpXvhCVAGLDPpM3TCvV0hskXmJk2eWN3gZjSoPhwMXpcRNlphPnM Nk4IQQUhluyjgbqLFQ1m8lmEI0re120u8H75cQnRpTkpFWu8e2eeINS3yEAh4JICRg 4Hhmg3HjkdsaQ== Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BF25E63075 for ; Wed, 2 Nov 2022 17:06:02 +0100 (CET) Received: (Authenticated sender: jacopo@jmondi.org) by mail.gandi.net (Postfix) with ESMTPSA id 33F181BF211; Wed, 2 Nov 2022 16:06:01 +0000 (UTC) To: libcamera-devel@lists.libcamera.org Date: Wed, 2 Nov 2022 17:05:56 +0100 Message-Id: <20221102160556.33086-1-jacopo@jmondi.org> X-Mailer: git-send-email 2.38.1 MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH] cam: capture_script: Support parsing array 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 support for parsing array controls to the cam capture script. Signed-off-by: Jacopo Mondi --- v1->v2: - Rebased on src/apps/ - Use the correct size when parsing boolean controls as noted by Paul --- src/apps/cam/capture_script.cpp | 158 ++++++++++++++++++++++++++++---- src/apps/cam/capture_script.h | 5 + 2 files changed, 146 insertions(+), 17 deletions(-) -- 2.38.1 diff --git a/src/apps/cam/capture_script.cpp b/src/apps/cam/capture_script.cpp index 5a27361ce4d9..062a7258e414 100644 --- a/src/apps/cam/capture_script.cpp +++ b/src/apps/cam/capture_script.cpp @@ -454,24 +454,9 @@ void CaptureScript::unpackFailure(const ControlId *id, const std::string &repr) << typeName << " control " << id->name() << std::endl; } -ControlValue CaptureScript::unpackControl(const ControlId *id) +ControlValue CaptureScript::parseScalarControl(const ControlId *id, + const std::string repr) { - /* Parse complex types. */ - switch (id->type()) { - case ControlTypeRectangle: - return parseRectangles(); - case ControlTypeSize: - /* \todo Parse Sizes. */ - return {}; - default: - break; - } - - /* Parse basic types represented by a single scalar. */ - const std::string repr = parseScalar(); - if (repr.empty()) - return {}; - ControlValue value{}; switch (id->type()) { @@ -524,6 +509,145 @@ ControlValue CaptureScript::unpackControl(const ControlId *id) return value; } +ControlValue CaptureScript::parseArrayControl(const ControlId *id, + const std::vector &repr) +{ + ControlValue value{}; + + switch (id->type()) { + case ControlTypeNone: + break; + case ControlTypeBool: { + /* + * This is unpleasant, but we cannot use an std::vector<> as its + * boolean type overload does not allow to access the raw data, + * as boolean values are stored in a bitmask for efficiency. + * + * As we need a contiguous memory region to wrap in a Span<>, + * use an array instead but be strict about not overflowing it + * by limiting the number of controls we can store. + * + * Be loud but do not fail, as the issue would present at + * runtime and it's not fatal. + */ + static constexpr unsigned int kMaxNumBooleanControls = 1024; + std::array values; + unsigned int idx = 0; + + for (const std::string &s : repr) { + bool val; + + if (s == "true") { + val = true; + } else if (s == "false") { + val = false; + } else { + unpackFailure(id, s); + return value; + } + + if (idx == kMaxNumBooleanControls) { + std::cerr << "Cannot parse more than " + << kMaxNumBooleanControls + << " boolean controls" << std::endl; + break; + } + + values[idx++] = val; + } + + value = Span(values.data(), idx); + break; + } + case ControlTypeByte: { + std::vector values; + for (const std::string &s : repr) { + uint8_t val = strtoll(s.c_str(), NULL, 10); + values.push_back(val); + } + + value = Span(values.data(), values.size()); + break; + } + case ControlTypeInteger32: { + std::vector values; + for (const std::string &s : repr) { + int32_t val = strtoll(s.c_str(), NULL, 10); + values.push_back(val); + } + + value = Span(values.data(), values.size()); + break; + } + case ControlTypeInteger64: { + std::vector values; + for (const std::string &s : repr) { + int64_t val = strtoll(s.c_str(), NULL, 10); + values.push_back(val); + } + + value = Span(values.data(), values.size()); + break; + } + case ControlTypeFloat: { + std::vector values; + for (const std::string &s : repr) + values.push_back(strtof(s.c_str(), NULL)); + + value = Span(values.data(), values.size()); + break; + } + case ControlTypeString: { + value = Span(repr.data(), repr.size()); + break; + } + default: + std::cerr << "Unsupported control type" << std::endl; + break; + } + + return value; +} + +ControlValue CaptureScript::unpackControl(const ControlId *id) +{ + /* Parse complex types. */ + switch (id->type()) { + case ControlTypeRectangle: + return parseRectangles(); + case ControlTypeSize: + /* \todo Parse Sizes. */ + return {}; + default: + break; + } + + /* Check if the control has a single scalar value or is an array. */ + EventPtr event = nextEvent(); + if (!event) + return {}; + + switch (event->type) { + case YAML_SCALAR_EVENT: { + const std::string repr = eventScalarValue(event); + if (repr.empty()) + return {}; + + return parseScalarControl(id, repr); + } + case YAML_SEQUENCE_START_EVENT: { + std::vector array = parseSingleArray(); + if (array.empty()) + return {}; + + return parseArrayControl(id, array); + } + default: + std::cerr << "Unexpected event type: " << event->type << std::endl; + return {}; + } +} + libcamera::Rectangle CaptureScript::unpackRectangle(const std::vector &strVec) { int x = strtol(strVec[0].c_str(), NULL, 10); diff --git a/src/apps/cam/capture_script.h b/src/apps/cam/capture_script.h index 7a0ddebb00b5..40042c0330f0 100644 --- a/src/apps/cam/capture_script.h +++ b/src/apps/cam/capture_script.h @@ -56,6 +56,11 @@ private: int parseFrame(EventPtr event); int parseControl(EventPtr event, libcamera::ControlList &controls); + libcamera::ControlValue parseScalarControl(const libcamera::ControlId *id, + const std::string repr); + libcamera::ControlValue parseArrayControl(const libcamera::ControlId *id, + const std::vector &repr); + std::string parseScalar(); libcamera::ControlValue parseRectangles(); std::vector> parseArrays();