From patchwork Fri Jul 12 05:29:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 20654 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 F2512BDB1C for ; Fri, 12 Jul 2024 05:29:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7050D63374; Fri, 12 Jul 2024 07:29:51 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="PMl6w/gV"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D921263373 for ; Fri, 12 Jul 2024 07:29:40 +0200 (CEST) Received: from localhost.localdomain (unknown [IPv6:2405:201:2015:f873:55f8:639e:8e9f:12ec]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C120DCC8; Fri, 12 Jul 2024 07:29:05 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1720762146; bh=ie7HwfJuw/xdXZQNuu2T2/iCexCnVjC/rUn72ssmos8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PMl6w/gVyS5en74MjT8ZaNLfIPybK5e+KF9MiDuXfVHwGVW51JaoqdMi3LBvzhoWf 2uTWNWh1NjGxEUyDBdLLhnWLpGP8y5VwT1TxbvKVAfXY+LaIWx+4PzvqjGqIYdaaam puxgY33cHD43WbyfZ5/77TvdXn6Nl4lXSopHgz6Q= From: Umang Jain To: libcamera-devel@lists.libcamera.org Cc: Xavier Roumegue , Umang Jain Subject: [RFC PATCH 6/6] libcamera: converter_dw100: Load and apply dewarp vertex maps Date: Fri, 12 Jul 2024 10:59:20 +0530 Message-ID: <20240712052920.33396-7-umang.jain@ideasonboard.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240712052920.33396-1-umang.jain@ideasonboard.com> References: <20240712052920.33396-1-umang.jain@ideasonboard.com> MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Load the dewarp vertex maps for different configurations using the LIBCAMERA_DEWARP_CONFIG_FILE environment variable. In addition, provide a applyMappings(stream) API for converter_dw100, in order to apply mappings for the given stream. Plumb it into rkisp1 pipeline handler, if the dewarper is being used. \todo The parsing of dewarp configuration file is yet to be determined. I've used the same parsing logic as made in previous attempts: https://patchwork.libcamera.org/patch/17348/ Signed-off-by: Umang Jain --- .../internal/converter/converter_dw100.h | 5 + src/libcamera/converter/converter_dw100.cpp | 127 ++++++++++++++++++ src/libcamera/pipeline/rkisp1/rkisp1.cpp | 4 + 3 files changed, 136 insertions(+) diff --git a/include/libcamera/internal/converter/converter_dw100.h b/include/libcamera/internal/converter/converter_dw100.h index dc41f365..a3062e84 100644 --- a/include/libcamera/internal/converter/converter_dw100.h +++ b/include/libcamera/internal/converter/converter_dw100.h @@ -19,6 +19,11 @@ class ConverterDW100 : public V4L2M2MConverter { public: ConverterDW100(std::shared_ptr media); + + int applyMappings(const Stream *stream); + +private: + int loadDewarpMaps(); }; } /* namespace libcamera */ diff --git a/src/libcamera/converter/converter_dw100.cpp b/src/libcamera/converter/converter_dw100.cpp index 3061fc71..1a641779 100644 --- a/src/libcamera/converter/converter_dw100.cpp +++ b/src/libcamera/converter/converter_dw100.cpp @@ -7,12 +7,17 @@ #include "libcamera/internal/converter/converter_dw100.h" +#include + +#include #include +#include #include #include "libcamera/internal/media_device.h" #include "libcamera/internal/v4l2_videodevice.h" +#include "libcamera/internal/yaml_parser.h" namespace libcamera { @@ -32,6 +37,128 @@ LOG_DECLARE_CATEGORY(Converter) ConverterDW100::ConverterDW100(std::shared_ptr media) : V4L2M2MConverter(media.get(), Feature::Crop) { + loadDewarpMaps(); +} + +int ConverterDW100::loadDewarpMaps() +{ + int ret; + + char const *configFromEnv = utils::secure_getenv("LIBCAMERA_DEWARP_CONFIG_FILE"); + if (!configFromEnv || *configFromEnv == '\0') + return 0; + + LOG(Converter, Info) << "Parsing dewarp configuration file " << configFromEnv; + + std::string filename = std::string(configFromEnv); + File file(filename); + + if (!file.open(File::OpenModeFlag::ReadOnly)) { + ret = file.error(); + LOG(Converter, Error) << "Failed to open configuration file " + << filename << ": " << strerror(-ret); + return ret; + } + + std::unique_ptr data = YamlParser::parse(file); + if (!data) + return -EINVAL; + + if (!data->contains("mappings")) { + LOG(Converter, Error) << "Vertex mapping key missing"; + return -EINVAL; + } + + const YamlObject &mappings = (*data)["mappings"]; + if (!mappings.isList() || mappings.size() == 0) { + LOG(Converter, Error) << "Invalid mappings entry"; + return -EINVAL; + } + + LOG(Converter, Debug) << "Parsing " << mappings.size() << " mappings"; + mappings_.clear(); + mappings_.reserve(mappings.size()); + + for (std::size_t i = 0; i < mappings.size(); i++) { + const YamlObject &mapping = mappings[i]; + if (!mapping.isDictionary()) { + LOG(Converter, Error) << "Mapping is not a dictionary"; + return -EINVAL; + } + + if (!mapping.contains("input-resolution")) { + LOG(Converter, Error) << "Input resolution missing"; + return -EINVAL; + } + + if (!mapping.contains("output-resolution")) { + LOG(Converter, Error) << "Output resolution missing"; + return -EINVAL; + } + + if (!mapping.contains("mapping")) { + LOG(Converter, Error) << "Mapping table missing"; + return -EINVAL; + } + + const YamlObject &input_res = mapping["input-resolution"]; + if (!input_res.isList() || input_res.size() != 2) { + LOG(Converter, Error) << "Incorrect input resolution"; + return -EINVAL; + } + + const YamlObject &output_res = mapping["output-resolution"]; + if (!output_res.isList() || output_res.size() != 2) { + LOG(Converter, Error) << "Incorrect output resolution"; + return -EINVAL; + } + + const YamlObject &map = mapping["mapping"]; + if (!map.isList() || map.size() == 0) { + LOG(Converter, Error) << "Incorrect mapping entries"; + return -EINVAL; + } + + Size input(input_res[0].get(0), input_res[1].get(0)); + Size output(output_res[0].get(0), output_res[1].get(0)); + const auto &mapVector = map.getList().value_or(std::vector{}); + + LOG(Converter, Debug) + << "Input/Output mapping resolution " << input << " -> " << output; + + mappings_.emplace_back(Mapping(input, output, mapVector)); + } + + return mappings.size(); +} + +/* + * \brief Apply + * \todo this is just a wrapper, trying to test waters + * \param[in] media The media device implementing the converter + */ +int ConverterDW100::applyMappings(const Stream *stream) +{ + const StreamConfiguration &config = stream->configuration(); + ControlList ctrls; + int ret = 0; + + for (const auto &map : mappings_) { + /* Currently DW100's input and output configuration are same. */ + if (map.inputSize() == config.size && + map.outputSize() == config.size) { + auto value = Span(reinterpret_cast(map.mapping()), map.size()); + + ControlValue c(value); + ctrls.set(V4L2_CID_DW100_DEWARPING_16x16_VERTEX_MAP, c); + ret = applyControls(stream, ctrls); + + LOG(Converter, Debug) << "Dewarp mapping applied for " << config.toString(); + break; + } + } + + return ret; } } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 881e10e1..f102b364 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -1019,6 +1019,10 @@ int PipelineHandlerRkISP1::start(Camera *camera, [[maybe_unused]] const ControlL LOG(RkISP1, Error) << "Failed to start dewarper"; return ret; } + + ret = dewarper_->applyMappings(&data->mainPathStream_); + if (ret) + LOG(RkISP1, Warning) << "Dewarper mapping couldn't be applied"; } }