diff options
Diffstat (limited to 'users/flokli/ipu6-softisp/libcamera/0013-libcamera-software_isp-add-Simple-SoftwareIsp-implem.patch')
-rw-r--r-- | users/flokli/ipu6-softisp/libcamera/0013-libcamera-software_isp-add-Simple-SoftwareIsp-implem.patch | 483 |
1 files changed, 483 insertions, 0 deletions
diff --git a/users/flokli/ipu6-softisp/libcamera/0013-libcamera-software_isp-add-Simple-SoftwareIsp-implem.patch b/users/flokli/ipu6-softisp/libcamera/0013-libcamera-software_isp-add-Simple-SoftwareIsp-implem.patch new file mode 100644 index 000000000000..24636ed7569a --- /dev/null +++ b/users/flokli/ipu6-softisp/libcamera/0013-libcamera-software_isp-add-Simple-SoftwareIsp-implem.patch @@ -0,0 +1,483 @@ +From 21f1dd954a44b4e8f81abbfea276e4b60f8a8297 Mon Sep 17 00:00:00 2001 +From: Andrey Konovalov <andrey.konovalov@linaro.org> +Date: Thu, 23 Nov 2023 16:47:15 +0300 +Subject: [PATCH 13/25] libcamera: software_isp: add Simple SoftwareIsp + implementation + +The implementation of SoftwareIsp handles creation of Soft IPA +and interactions with it, so that the pipeline handler wouldn't +need to care about the Soft IPA. + +Doxygen documentation by Dennis Bonke. + +Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org> +Co-authored-by: Dennis Bonke <admin@dennisbonke.com> +Signed-off-by: Dennis Bonke <admin@dennisbonke.com> +Co-authored-by: Hans de Goede <hdegoede@redhat.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s +Tested-by: Pavel Machek <pavel@ucw.cz> +--- + .../internal/software_isp/meson.build | 1 + + .../internal/software_isp/swisp_simple.h | 163 ++++++++++++ + src/libcamera/software_isp/meson.build | 19 ++ + src/libcamera/software_isp/swisp_simple.cpp | 238 ++++++++++++++++++ + 4 files changed, 421 insertions(+) + create mode 100644 include/libcamera/internal/software_isp/swisp_simple.h + create mode 100644 src/libcamera/software_isp/swisp_simple.cpp + +diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build +index b5a0d737..cf21ace5 100644 +--- a/include/libcamera/internal/software_isp/meson.build ++++ b/include/libcamera/internal/software_isp/meson.build +@@ -4,6 +4,7 @@ libcamera_internal_headers += files([ + 'debayer.h', + 'debayer_cpu.h', + 'debayer_params.h', ++ 'swisp_simple.h', + 'swisp_stats.h', + 'swstats.h', + 'swstats_cpu.h', +diff --git a/include/libcamera/internal/software_isp/swisp_simple.h b/include/libcamera/internal/software_isp/swisp_simple.h +new file mode 100644 +index 00000000..87613c23 +--- /dev/null ++++ b/include/libcamera/internal/software_isp/swisp_simple.h +@@ -0,0 +1,163 @@ ++/* SPDX-License-Identifier: LGPL-2.1-or-later */ ++/* ++ * Copyright (C) 2023, Linaro Ltd ++ * ++ * swisp_simple.h - Simple software ISP implementation ++ */ ++ ++#pragma once ++ ++#include <libcamera/base/log.h> ++#include <libcamera/base/thread.h> ++ ++#include <libcamera/pixel_format.h> ++ ++#include <libcamera/ipa/soft_ipa_interface.h> ++#include <libcamera/ipa/soft_ipa_proxy.h> ++ ++#include "libcamera/internal/dma_heaps.h" ++#include "libcamera/internal/software_isp.h" ++#include "libcamera/internal/software_isp/debayer_cpu.h" ++ ++namespace libcamera { ++ ++/** ++ * \brief Class for the Simple Software ISP. ++ * ++ * Implementation of the SoftwareIsp interface. ++ */ ++class SwIspSimple : public SoftwareIsp ++{ ++public: ++ /** ++ * \brief Constructor for the SwIspSimple object. ++ * ++ * \param[in] pipe The pipeline handler in use. ++ * \param[in] sensorControls The sensor controls. ++ */ ++ SwIspSimple(PipelineHandler *pipe, const ControlInfoMap &sensorControls); ++ ~SwIspSimple() {} ++ ++ /** ++ * \brief Load a configuration from a file. ++ * \param[in] filename The file to load from. ++ * ++ * \return 0 on success. ++ */ ++ int loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; } ++ ++ /** ++ * \brief Gets if there is a valid debayer object. ++ * ++ * \returns true if there is, false otherwise. ++ */ ++ bool isValid() const; ++ ++ /** ++ * \brief Get the supported output formats. ++ * \param[in] input The input format. ++ * ++ * \return all supported output formats or an empty vector if there are none. ++ */ ++ std::vector<PixelFormat> formats(PixelFormat input); ++ ++ /** ++ * \brief Get the supported output sizes for the given input format and size. ++ * \param[in] inputFormat The input format. ++ * \param[in] inputSize The input size. ++ * ++ * \return The valid size ranges or an empty range if there are none. ++ */ ++ SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); ++ ++ /** ++ * \brief Get the stride and the frame size. ++ * \param[in] outputFormat The output format. ++ * \param[in] size The output size. ++ * ++ * \return a tuple of the stride and the frame size, or a tuple with 0,0 if there is no valid output config. ++ */ ++ std::tuple<unsigned int, unsigned int> ++ strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); ++ ++ /** ++ * \brief Configure the SwIspSimple object according to the passed in parameters. ++ * \param[in] inputCfg The input configuration. ++ * \param[in] outputCfgs The output configurations. ++ * \param[in] sensorControls The sensor controls. ++ * ++ * \return 0 on success, a negative errno on failure. ++ */ ++ int configure(const StreamConfiguration &inputCfg, ++ const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs, ++ const ControlInfoMap &sensorControls); ++ ++ /** ++ * \brief Exports the buffers for use in processing. ++ * \param[in] output The number of outputs requested. ++ * \param[in] count The number of planes. ++ * \param[out] buffers The exported buffers. ++ * ++ * \return count when successful, a negative return value if an error occurred. ++ */ ++ int exportBuffers(unsigned int output, unsigned int count, ++ std::vector<std::unique_ptr<FrameBuffer>> *buffers); ++ ++ /** ++ * \brief Process the statistics gathered. ++ * \param[in] sensorControls The sensor controls. ++ */ ++ void processStats(const ControlList &sensorControls); ++ ++ /** ++ * \brief Starts the Software ISP worker. ++ * ++ * \return 0 on success, any other value indicates an error. ++ */ ++ int start(); ++ ++ /** ++ * \brief Stops the Software ISP worker. ++ */ ++ void stop(); ++ ++ /** ++ * \brief Queues buffers for processing. ++ * \param[in] input The input framebuffer. ++ * \param[in] outputs The output framebuffers. ++ * ++ * \return 0 on success, a negative errno on failure ++ */ ++ int queueBuffers(FrameBuffer *input, ++ const std::map<unsigned int, FrameBuffer *> &outputs); ++ ++ /** ++ * \brief Get the signal for when the sensor controls are set. ++ * ++ * \return The control list of the sensor controls. ++ */ ++ Signal<const ControlList &> &getSignalSetSensorControls(); ++ ++ /** ++ * \brief Process the input framebuffer. ++ * \param[in] input The input framebuffer. ++ * \param[out] output The output framebuffer. ++ */ ++ void process(FrameBuffer *input, FrameBuffer *output); ++ ++private: ++ void saveIspParams(int dummy); ++ void statsReady(int dummy); ++ void inputReady(FrameBuffer *input); ++ void outputReady(FrameBuffer *output); ++ ++ std::unique_ptr<DebayerCpu> debayer_; ++ Thread ispWorkerThread_; ++ SharedMemObject<DebayerParams> sharedParams_; ++ DebayerParams debayerParams_; ++ DmaHeap dmaHeap_; ++ ++ std::unique_ptr<ipa::soft::IPAProxySoft> ipa_; ++}; ++ ++} /* namespace libcamera */ +diff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build +index 6d7a44d7..9464f2fd 100644 +--- a/src/libcamera/software_isp/meson.build ++++ b/src/libcamera/software_isp/meson.build +@@ -6,3 +6,22 @@ libcamera_sources += files([ + 'swstats.cpp', + 'swstats_cpu.cpp', + ]) ++ ++# Software ISP is enabled for 'simple' pipeline handler. ++# The 'pipelines' option value should be ++# 'simple/<Software ISP implementation>' e.g.: ++# -Dpipelines=simple/simple ++# The source file should be named swisp_<Software ISP implementation>.cpp, ++# e.g. 'swisp_simple.cpp'. ++ ++foreach pipeline : pipelines ++ pipeline = pipeline.split('/') ++ if pipeline.length() == 2 and pipeline[0] == 'simple' ++ libcamera_sources += files([ ++ 'swisp_' + pipeline[1] + '.cpp', ++ ]) ++ # the 'break' below can be removed if/when multiple ++ # Software ISP implementations are allowed in single build ++ break ++ endif ++endforeach +diff --git a/src/libcamera/software_isp/swisp_simple.cpp b/src/libcamera/software_isp/swisp_simple.cpp +new file mode 100644 +index 00000000..0884166e +--- /dev/null ++++ b/src/libcamera/software_isp/swisp_simple.cpp +@@ -0,0 +1,238 @@ ++/* SPDX-License-Identifier: LGPL-2.1-or-later */ ++/* ++ * Copyright (C) 2023, Linaro Ltd ++ * ++ * swisp_simple.cpp - Simple software ISP implementation ++ */ ++ ++#include "libcamera/internal/software_isp/swisp_simple.h" ++ ++#include <sys/mman.h> ++#include <sys/types.h> ++#include <unistd.h> ++ ++#include <libcamera/formats.h> ++#include <libcamera/stream.h> ++ ++#include "libcamera/internal/bayer_format.h" ++#include "libcamera/internal/framebuffer.h" ++#include "libcamera/internal/ipa_manager.h" ++#include "libcamera/internal/mapped_framebuffer.h" ++ ++namespace libcamera { ++ ++SwIspSimple::SwIspSimple(PipelineHandler *pipe, const ControlInfoMap &sensorControls) ++ : SoftwareIsp(pipe, sensorControls), debayer_(nullptr), debayerParams_{ 256, 256, 256, 0.5f }, ++ dmaHeap_(DmaHeap::DmaHeapFlag::Cma | DmaHeap::DmaHeapFlag::System) ++{ ++ if (!dmaHeap_.isValid()) { ++ LOG(SoftwareIsp, Error) << "Failed to create DmaHeap object"; ++ return; ++ } ++ ++ sharedParams_ = SharedMemObject<DebayerParams>("softIsp_params"); ++ if (!sharedParams_.fd().isValid()) { ++ LOG(SoftwareIsp, Error) << "Failed to create shared memory for parameters"; ++ return; ++ } ++ ++ std::unique_ptr<SwStatsCpu> stats; ++ ++ stats = std::make_unique<SwStatsCpu>(); ++ if (!stats) { ++ LOG(SoftwareIsp, Error) << "Failed to create SwStatsCpu object"; ++ return; ++ } ++ ++ stats->statsReady.connect(this, &SwIspSimple::statsReady); ++ ++ debayer_ = std::make_unique<DebayerCpu>(std::move(stats)); ++ if (!debayer_) { ++ LOG(SoftwareIsp, Error) << "Failed to create DebayerCpu object"; ++ return; ++ } ++ ++ debayer_->inputBufferReady.connect(this, &SwIspSimple::inputReady); ++ debayer_->outputBufferReady.connect(this, &SwIspSimple::outputReady); ++ ++ ipa_ = IPAManager::createIPA<ipa::soft::IPAProxySoft>(pipe, 0, 0); ++ if (!ipa_) { ++ LOG(SoftwareIsp, Error) ++ << "Creating IPA for software ISP failed"; ++ debayer_.reset(); ++ return; ++ } ++ ++ int ret = ipa_->init(IPASettings{ "No cfg file", "No sensor model" }, ++ debayer_->getStatsFD(), ++ sharedParams_.fd(), ++ sensorControls); ++ if (ret) { ++ LOG(SoftwareIsp, Error) << "IPA init failed"; ++ debayer_.reset(); ++ return; ++ } ++ ++ ipa_->setIspParams.connect(this, &SwIspSimple::saveIspParams); ++ ++ debayer_->moveToThread(&ispWorkerThread_); ++} ++ ++void SwIspSimple::processStats(const ControlList &sensorControls) ++{ ++ ASSERT(ipa_); ++ ipa_->processStats(sensorControls); ++} ++ ++Signal<const ControlList &> &SwIspSimple::getSignalSetSensorControls() ++{ ++ ASSERT(ipa_); ++ return ipa_->setSensorControls; ++} ++ ++bool SwIspSimple::isValid() const ++{ ++ return !!debayer_; ++} ++ ++std::vector<PixelFormat> SwIspSimple::formats(PixelFormat inputFormat) ++{ ++ ASSERT(debayer_ != nullptr); ++ ++ return debayer_->formats(inputFormat); ++} ++ ++SizeRange SwIspSimple::sizes(PixelFormat inputFormat, const Size &inputSize) ++{ ++ ASSERT(debayer_ != nullptr); ++ ++ return debayer_->sizes(inputFormat, inputSize); ++} ++ ++std::tuple<unsigned int, unsigned int> ++SwIspSimple::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) ++{ ++ ASSERT(debayer_ != nullptr); ++ ++ return debayer_->strideAndFrameSize(outputFormat, size); ++} ++ ++int SwIspSimple::configure(const StreamConfiguration &inputCfg, ++ const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs, ++ const ControlInfoMap &sensorControls) ++{ ++ ASSERT(ipa_ != nullptr && debayer_ != nullptr); ++ ++ int ret = ipa_->configure(sensorControls); ++ if (ret < 0) ++ return ret; ++ ++ return debayer_->configure(inputCfg, outputCfgs); ++} ++ ++int SwIspSimple::exportBuffers(unsigned int output, unsigned int count, ++ std::vector<std::unique_ptr<FrameBuffer>> *buffers) ++{ ++ ASSERT(debayer_ != nullptr); ++ ++ /* single output for now */ ++ if (output >= 1) ++ return -EINVAL; ++ ++ for (unsigned int i = 0; i < count; i++) { ++ const std::string name = "frame-" + std::to_string(i); ++ const size_t frameSize = debayer_->frameSize(); ++ ++ FrameBuffer::Plane outPlane; ++ outPlane.fd = SharedFD(dmaHeap_.alloc(name.c_str(), frameSize)); ++ if (!outPlane.fd.isValid()) { ++ LOG(SoftwareIsp, Error) ++ << "failed to allocate a dma_buf"; ++ return -ENOMEM; ++ } ++ outPlane.offset = 0; ++ outPlane.length = frameSize; ++ ++ std::vector<FrameBuffer::Plane> planes{ outPlane }; ++ buffers->emplace_back(std::make_unique<FrameBuffer>(std::move(planes))); ++ } ++ ++ return count; ++} ++ ++int SwIspSimple::queueBuffers(FrameBuffer *input, ++ const std::map<unsigned int, FrameBuffer *> &outputs) ++{ ++ unsigned int mask = 0; ++ ++ /* ++ * Validate the outputs as a sanity check: at least one output is ++ * required, all outputs must reference a valid stream and no two ++ * outputs can reference the same stream. ++ */ ++ if (outputs.empty()) ++ return -EINVAL; ++ ++ for (auto [index, buffer] : outputs) { ++ if (!buffer) ++ return -EINVAL; ++ if (index >= 1) /* only single stream atm */ ++ return -EINVAL; ++ if (mask & (1 << index)) ++ return -EINVAL; ++ ++ mask |= 1 << index; ++ } ++ ++ process(input, outputs.at(0)); ++ ++ return 0; ++} ++ ++int SwIspSimple::start() ++{ ++ int ret = ipa_->start(); ++ if (ret) ++ return ret; ++ ++ ispWorkerThread_.start(); ++ return 0; ++} ++ ++void SwIspSimple::stop() ++{ ++ ispWorkerThread_.exit(); ++ ispWorkerThread_.wait(); ++ ++ ipa_->stop(); ++} ++ ++void SwIspSimple::process(FrameBuffer *input, FrameBuffer *output) ++{ ++ debayer_->invokeMethod(&DebayerCpu::process, ++ ConnectionTypeQueued, input, output, debayerParams_); ++} ++ ++void SwIspSimple::saveIspParams([[maybe_unused]] int dummy) ++{ ++ debayerParams_ = *sharedParams_; ++} ++ ++void SwIspSimple::statsReady(int dummy) ++{ ++ ispStatsReady.emit(dummy); ++} ++ ++void SwIspSimple::inputReady(FrameBuffer *input) ++{ ++ inputBufferReady.emit(input); ++} ++ ++void SwIspSimple::outputReady(FrameBuffer *output) ++{ ++ outputBufferReady.emit(output); ++} ++ ++REGISTER_SOFTWAREISP(SwIspSimple) ++ ++} /* namespace libcamera */ +-- +2.43.0 + |