[libcamera-devel] [PATCH v2 13/18] libcamera: software_isp: add Simple SoftwareIsp implementation
Barnabás Pőcze
pobrn at protonmail.com
Sat Jan 13 17:30:05 CET 2024
Hi
2024. január 13., szombat 15:22 keltezéssel, Hans de Goede via libcamera-devel írta:
> From: Andrey Konovalov <andrey.konovalov at linaro.org>
>
> 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 at linaro.org>
> Co-authored-by: Dennis Bonke <admin at dennisbonke.com>
> Signed-off-by: Dennis Bonke <admin at dennisbonke.com>
> Co-authored-by: Hans de Goede <hdegoede at redhat.com>
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> Tested-by: Bryan O'Donoghue <bryan.odonoghue at linaro.org> # sc8280xp Lenovo x13s
> Tested-by: Pavel Machek <pavel at 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() {}
~SwIspSimple() = default;
> +
> + /**
> + * \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>();
You can just say
auto stats = std::make_unique<SwStatsCpu>();
> + if (!stats) {
std::make_unique should never return nullptr.
> + 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_) {
Same here.
> + 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_);
> +}
> [...]
Regards,
Barnabás Pőcze
More information about the libcamera-devel
mailing list