ipa: mali-c55: Add Mali-C55 ISP IPA module
Add a barebones IPA module for the Mali-C55 ISP. In this initial implementation pretty much only buffer plumbing is implemented. Acked-by: Nayden Kanchev <nayden.kanchev@arm.com> Co-developed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com> Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
parent
10ccab9db9
commit
fe989ee514
13 changed files with 641 additions and 1 deletions
|
@ -32,6 +32,7 @@ RECURSIVE = YES
|
||||||
EXCLUDE_PATTERNS = @TOP_BUILDDIR@/include/libcamera/ipa/*_serializer.h \
|
EXCLUDE_PATTERNS = @TOP_BUILDDIR@/include/libcamera/ipa/*_serializer.h \
|
||||||
@TOP_BUILDDIR@/include/libcamera/ipa/*_proxy.h \
|
@TOP_BUILDDIR@/include/libcamera/ipa/*_proxy.h \
|
||||||
@TOP_BUILDDIR@/include/libcamera/ipa/ipu3_*.h \
|
@TOP_BUILDDIR@/include/libcamera/ipa/ipu3_*.h \
|
||||||
|
@TOP_BUILDDIR@/include/libcamera/ipa/mali-c55_*.h \
|
||||||
@TOP_BUILDDIR@/include/libcamera/ipa/raspberrypi_*.h \
|
@TOP_BUILDDIR@/include/libcamera/ipa/raspberrypi_*.h \
|
||||||
@TOP_BUILDDIR@/include/libcamera/ipa/rkisp1_*.h \
|
@TOP_BUILDDIR@/include/libcamera/ipa/rkisp1_*.h \
|
||||||
@TOP_BUILDDIR@/include/libcamera/ipa/vimc_*.h
|
@TOP_BUILDDIR@/include/libcamera/ipa/vimc_*.h
|
||||||
|
|
34
include/libcamera/ipa/mali-c55.mojom
Normal file
34
include/libcamera/ipa/mali-c55.mojom
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
module ipa.mali_c55;
|
||||||
|
|
||||||
|
import "include/libcamera/ipa/core.mojom";
|
||||||
|
|
||||||
|
struct IPAConfigInfo {
|
||||||
|
libcamera.IPACameraSensorInfo sensorInfo;
|
||||||
|
libcamera.ControlInfoMap sensorControls;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IPAMaliC55Interface {
|
||||||
|
init(libcamera.IPASettings settings, IPAConfigInfo configInfo)
|
||||||
|
=> (int32 ret, libcamera.ControlInfoMap ipaControls);
|
||||||
|
start() => (int32 ret);
|
||||||
|
stop();
|
||||||
|
|
||||||
|
configure(IPAConfigInfo configInfo, uint8 bayerOrder)
|
||||||
|
=> (int32 ret, libcamera.ControlInfoMap ipaControls);
|
||||||
|
|
||||||
|
mapBuffers(array<libcamera.IPABuffer> buffers, bool readOnly);
|
||||||
|
unmapBuffers(array<libcamera.IPABuffer> buffers);
|
||||||
|
|
||||||
|
[async] queueRequest(uint32 request, libcamera.ControlList reqControls);
|
||||||
|
[async] fillParams(uint32 request, uint32 bufferId);
|
||||||
|
[async] processStats(uint32 request, uint32 bufferId,
|
||||||
|
libcamera.ControlList sensorControls);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IPAMaliC55EventInterface {
|
||||||
|
paramsComputed(uint32 request);
|
||||||
|
statsProcessed(uint32 request, libcamera.ControlList metadata);
|
||||||
|
setSensorControls(libcamera.ControlList sensorControls);
|
||||||
|
};
|
|
@ -64,6 +64,7 @@ libcamera_ipa_headers += custom_target('core_ipa_serializer_h',
|
||||||
# Mapping from pipeline handler name to mojom file
|
# Mapping from pipeline handler name to mojom file
|
||||||
pipeline_ipa_mojom_mapping = {
|
pipeline_ipa_mojom_mapping = {
|
||||||
'ipu3': 'ipu3.mojom',
|
'ipu3': 'ipu3.mojom',
|
||||||
|
'mali-c55': 'mali-c55.mojom',
|
||||||
'rkisp1': 'rkisp1.mojom',
|
'rkisp1': 'rkisp1.mojom',
|
||||||
'rpi/vc4': 'raspberrypi.mojom',
|
'rpi/vc4': 'raspberrypi.mojom',
|
||||||
'simple': 'soft.mojom',
|
'simple': 'soft.mojom',
|
||||||
|
|
|
@ -32,7 +32,7 @@ option('gstreamer',
|
||||||
|
|
||||||
option('ipas',
|
option('ipas',
|
||||||
type : 'array',
|
type : 'array',
|
||||||
choices : ['ipu3', 'rkisp1', 'rpi/vc4', 'simple', 'vimc'],
|
choices : ['ipu3', 'mali-c55', 'rkisp1', 'rpi/vc4', 'simple', 'vimc'],
|
||||||
description : 'Select which IPA modules to build')
|
description : 'Select which IPA modules to build')
|
||||||
|
|
||||||
option('lc-compliance',
|
option('lc-compliance',
|
||||||
|
|
39
src/ipa/mali-c55/algorithms/algorithm.h
Normal file
39
src/ipa/mali-c55/algorithms/algorithm.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, Ideas On Board
|
||||||
|
*
|
||||||
|
* algorithm.h - Mali-C55 control algorithm interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <linux/mali-c55-config.h>
|
||||||
|
|
||||||
|
#include <libipa/algorithm.h>
|
||||||
|
|
||||||
|
#include "module.h"
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
namespace ipa::mali_c55 {
|
||||||
|
|
||||||
|
class Algorithm : public libcamera::ipa::Algorithm<Module>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
union mali_c55_params_block {
|
||||||
|
struct mali_c55_params_block_header *header;
|
||||||
|
struct mali_c55_params_sensor_off_preshading *sensor_offs;
|
||||||
|
struct mali_c55_params_aexp_hist *aexp_hist;
|
||||||
|
struct mali_c55_params_aexp_weights *aexp_weights;
|
||||||
|
struct mali_c55_params_digital_gain *digital_gain;
|
||||||
|
struct mali_c55_params_awb_gains *awb_gains;
|
||||||
|
struct mali_c55_params_awb_config *awb_config;
|
||||||
|
struct mali_c55_params_mesh_shading_config *shading_config;
|
||||||
|
struct mali_c55_params_mesh_shading_selection *shading_selection;
|
||||||
|
__u8 *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace ipa::mali_c55 */
|
||||||
|
|
||||||
|
} /* namespace libcamera */
|
4
src/ipa/mali-c55/algorithms/meson.build
Normal file
4
src/ipa/mali-c55/algorithms/meson.build
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
mali_c55_ipa_algorithms = files([
|
||||||
|
])
|
8
src/ipa/mali-c55/data/meson.build
Normal file
8
src/ipa/mali-c55/data/meson.build
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
conf_files = files([
|
||||||
|
'uncalibrated.yaml'
|
||||||
|
])
|
||||||
|
|
||||||
|
install_data(conf_files,
|
||||||
|
install_dir : ipa_data_dir / 'mali-c55')
|
6
src/ipa/mali-c55/data/uncalibrated.yaml
Normal file
6
src/ipa/mali-c55/data/uncalibrated.yaml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
%YAML 1.1
|
||||||
|
---
|
||||||
|
version: 1
|
||||||
|
algorithms:
|
||||||
|
...
|
101
src/ipa/mali-c55/ipa_context.cpp
Normal file
101
src/ipa/mali-c55/ipa_context.cpp
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, Ideas On Board
|
||||||
|
*
|
||||||
|
* ipa_context.cpp - MaliC55 IPA Context
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ipa_context.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file ipa_context.h
|
||||||
|
* \brief Context and state information shared between the algorithms
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace libcamera::ipa::mali_c55 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \struct IPASessionConfiguration
|
||||||
|
* \brief Session configuration for the IPA module
|
||||||
|
*
|
||||||
|
* The session configuration contains all IPA configuration parameters that
|
||||||
|
* remain constant during the capture session, from IPA module start to stop.
|
||||||
|
* It is typically set during the configure() operation of the IPA module, but
|
||||||
|
* may also be updated in the start() operation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \struct IPAActiveState
|
||||||
|
* \brief Active state for algorithms
|
||||||
|
*
|
||||||
|
* The active state contains all algorithm-specific data that needs to be
|
||||||
|
* maintained by algorithms across frames. Unlike the session configuration,
|
||||||
|
* the active state is mutable and constantly updated by algorithms. The active
|
||||||
|
* state is accessible through the IPAContext structure.
|
||||||
|
*
|
||||||
|
* The active state stores two distinct categories of information:
|
||||||
|
*
|
||||||
|
* - The consolidated value of all algorithm controls. Requests passed to
|
||||||
|
* the queueRequest() function store values for controls that the
|
||||||
|
* application wants to modify for that particular frame, and the
|
||||||
|
* queueRequest() function updates the active state with those values.
|
||||||
|
* The active state thus contains a consolidated view of the value of all
|
||||||
|
* controls handled by the algorithm.
|
||||||
|
*
|
||||||
|
* - The value of parameters computed by the algorithm when running in auto
|
||||||
|
* mode. Algorithms running in auto mode compute new parameters every
|
||||||
|
* time statistics buffers are received (either synchronously, or
|
||||||
|
* possibly in a background thread). The latest computed value of those
|
||||||
|
* parameters is stored in the active state in the process() function.
|
||||||
|
*
|
||||||
|
* Each of the members in the active state belongs to a specific algorithm. A
|
||||||
|
* member may be read by any algorithm, but shall only be written by its owner.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \struct IPAFrameContext
|
||||||
|
* \brief Per-frame context for algorithms
|
||||||
|
*
|
||||||
|
* The frame context stores two distinct categories of information:
|
||||||
|
*
|
||||||
|
* - The value of the controls to be applied to the frame. These values are
|
||||||
|
* typically set in the queueRequest() function, from the consolidated
|
||||||
|
* control values stored in the active state. The frame context thus stores
|
||||||
|
* values for all controls related to the algorithm, not limited to the
|
||||||
|
* controls specified in the corresponding request, but consolidated from all
|
||||||
|
* requests that have been queued so far.
|
||||||
|
*
|
||||||
|
* For controls that can be set manually or computed by an algorithm
|
||||||
|
* (depending on the algorithm operation mode), such as for instance the
|
||||||
|
* colour gains for the AWB algorithm, the control value will be stored in
|
||||||
|
* the frame context in the queueRequest() function only when operating in
|
||||||
|
* manual mode. When operating in auto mode, the values are computed by the
|
||||||
|
* algorithm in process(), stored in the active state, and copied to the
|
||||||
|
* frame context in prepare(), just before being stored in the ISP parameters
|
||||||
|
* buffer.
|
||||||
|
*
|
||||||
|
* The queueRequest() function can also store ancillary data in the frame
|
||||||
|
* context, such as flags to indicate if (and what) control values have
|
||||||
|
* changed compared to the previous request.
|
||||||
|
*
|
||||||
|
* - Status information computed by the algorithm for a frame. For instance,
|
||||||
|
* the colour temperature estimated by the AWB algorithm from ISP statistics
|
||||||
|
* calculated on a frame is stored in the frame context for that frame in
|
||||||
|
* the process() function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \struct IPAContext
|
||||||
|
* \brief Global IPA context data shared between all algorithms
|
||||||
|
*
|
||||||
|
* \var IPAContext::configuration
|
||||||
|
* \brief The IPA session configuration, immutable during the session
|
||||||
|
*
|
||||||
|
* \var IPAContext::activeState
|
||||||
|
* \brief The IPA active state, storing the latest state for all algorithms
|
||||||
|
*
|
||||||
|
* \var IPAContext::frameContexts
|
||||||
|
* \brief Ring buffer of per-frame contexts
|
||||||
|
*/
|
||||||
|
|
||||||
|
} /* namespace libcamera::ipa::mali_c55 */
|
47
src/ipa/mali-c55/ipa_context.h
Normal file
47
src/ipa/mali-c55/ipa_context.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, Ideas On Board
|
||||||
|
*
|
||||||
|
* ipa_context.h - Mali-C55 IPA Context
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libcamera/controls.h>
|
||||||
|
|
||||||
|
#include <libipa/fc_queue.h>
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
namespace ipa::mali_c55 {
|
||||||
|
|
||||||
|
struct IPASessionConfiguration {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IPAActiveState {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IPAFrameContext : public FrameContext {
|
||||||
|
struct {
|
||||||
|
uint32_t exposure;
|
||||||
|
double sensorGain;
|
||||||
|
} agc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IPAContext {
|
||||||
|
IPAContext(unsigned int frameContextSize)
|
||||||
|
: frameContexts(frameContextSize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IPASessionConfiguration configuration;
|
||||||
|
IPAActiveState activeState;
|
||||||
|
|
||||||
|
FCQueue<IPAFrameContext> frameContexts;
|
||||||
|
|
||||||
|
ControlInfoMap::Map ctrlMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace ipa::mali_c55 */
|
||||||
|
|
||||||
|
} /* namespace libcamera*/
|
339
src/ipa/mali-c55/mali-c55.cpp
Normal file
339
src/ipa/mali-c55/mali-c55.cpp
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023, Ideas on Board Oy
|
||||||
|
*
|
||||||
|
* mali-c55.cpp - Mali-C55 ISP image processing algorithms
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <linux/mali-c55-config.h>
|
||||||
|
#include <linux/v4l2-controls.h>
|
||||||
|
|
||||||
|
#include <libcamera/base/file.h>
|
||||||
|
#include <libcamera/base/log.h>
|
||||||
|
|
||||||
|
#include <libcamera/control_ids.h>
|
||||||
|
#include <libcamera/ipa/ipa_interface.h>
|
||||||
|
#include <libcamera/ipa/ipa_module_info.h>
|
||||||
|
#include <libcamera/ipa/mali-c55_ipa_interface.h>
|
||||||
|
|
||||||
|
#include "libcamera/internal/bayer_format.h"
|
||||||
|
#include "libcamera/internal/mapped_framebuffer.h"
|
||||||
|
#include "libcamera/internal/yaml_parser.h"
|
||||||
|
|
||||||
|
#include "algorithms/algorithm.h"
|
||||||
|
#include "libipa/camera_sensor_helper.h"
|
||||||
|
|
||||||
|
#include "ipa_context.h"
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
LOG_DEFINE_CATEGORY(IPAMaliC55)
|
||||||
|
|
||||||
|
namespace ipa::mali_c55 {
|
||||||
|
|
||||||
|
/* Maximum number of frame contexts to be held */
|
||||||
|
static constexpr uint32_t kMaxFrameContexts = 16;
|
||||||
|
|
||||||
|
class IPAMaliC55 : public IPAMaliC55Interface, public Module
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IPAMaliC55();
|
||||||
|
|
||||||
|
int init(const IPASettings &settings, const IPAConfigInfo &ipaConfig,
|
||||||
|
ControlInfoMap *ipaControls) override;
|
||||||
|
int start() override;
|
||||||
|
void stop() override;
|
||||||
|
int configure(const IPAConfigInfo &ipaConfig, uint8_t bayerOrder,
|
||||||
|
ControlInfoMap *ipaControls) override;
|
||||||
|
void mapBuffers(const std::vector<IPABuffer> &buffers, bool readOnly) override;
|
||||||
|
void unmapBuffers(const std::vector<IPABuffer> &buffers) override;
|
||||||
|
void queueRequest(const uint32_t request, const ControlList &controls) override;
|
||||||
|
void fillParams(unsigned int request, uint32_t bufferId) override;
|
||||||
|
void processStats(unsigned int request, unsigned int bufferId,
|
||||||
|
const ControlList &sensorControls) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string logPrefix() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateControls(const IPACameraSensorInfo &sensorInfo,
|
||||||
|
const ControlInfoMap &sensorControls,
|
||||||
|
ControlInfoMap *ipaControls);
|
||||||
|
void setControls();
|
||||||
|
|
||||||
|
std::map<unsigned int, MappedFrameBuffer> buffers_;
|
||||||
|
|
||||||
|
ControlInfoMap sensorControls_;
|
||||||
|
|
||||||
|
/* Interface to the Camera Helper */
|
||||||
|
std::unique_ptr<CameraSensorHelper> camHelper_;
|
||||||
|
|
||||||
|
/* Local parameter storage */
|
||||||
|
struct IPAContext context_;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
} /* namespace */
|
||||||
|
|
||||||
|
IPAMaliC55::IPAMaliC55()
|
||||||
|
: context_(kMaxFrameContexts)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string IPAMaliC55::logPrefix() const
|
||||||
|
{
|
||||||
|
return "mali-c55";
|
||||||
|
}
|
||||||
|
|
||||||
|
int IPAMaliC55::init(const IPASettings &settings, const IPAConfigInfo &ipaConfig,
|
||||||
|
ControlInfoMap *ipaControls)
|
||||||
|
{
|
||||||
|
camHelper_ = CameraSensorHelperFactoryBase::create(settings.sensorModel);
|
||||||
|
if (!camHelper_) {
|
||||||
|
LOG(IPAMaliC55, Error)
|
||||||
|
<< "Failed to create camera sensor helper for "
|
||||||
|
<< settings.sensorModel;
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
File file(settings.configurationFile);
|
||||||
|
if (!file.open(File::OpenModeFlag::ReadOnly)) {
|
||||||
|
int ret = file.error();
|
||||||
|
LOG(IPAMaliC55, Error)
|
||||||
|
<< "Failed to open configuration file "
|
||||||
|
<< settings.configurationFile << ": " << strerror(-ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<libcamera::YamlObject> data = YamlParser::parse(file);
|
||||||
|
if (!data)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!data->contains("algorithms")) {
|
||||||
|
LOG(IPAMaliC55, Error)
|
||||||
|
<< "Tuning file doesn't contain any algorithm";
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = createAlgorithms(context_, (*data)["algorithms"]);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
updateControls(ipaConfig.sensorInfo, ipaConfig.sensorControls, ipaControls);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPAMaliC55::setControls()
|
||||||
|
{
|
||||||
|
ControlList ctrls(sensorControls_);
|
||||||
|
|
||||||
|
setSensorControls.emit(ctrls);
|
||||||
|
}
|
||||||
|
|
||||||
|
int IPAMaliC55::start()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPAMaliC55::stop()
|
||||||
|
{
|
||||||
|
context_.frameContexts.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPAMaliC55::updateControls(const IPACameraSensorInfo &sensorInfo,
|
||||||
|
const ControlInfoMap &sensorControls,
|
||||||
|
ControlInfoMap *ipaControls)
|
||||||
|
{
|
||||||
|
ControlInfoMap::Map ctrlMap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute the frame duration limits.
|
||||||
|
*
|
||||||
|
* The frame length is computed assuming a fixed line length combined
|
||||||
|
* with the vertical frame sizes.
|
||||||
|
*/
|
||||||
|
const ControlInfo &v4l2HBlank = sensorControls.find(V4L2_CID_HBLANK)->second;
|
||||||
|
uint32_t hblank = v4l2HBlank.def().get<int32_t>();
|
||||||
|
uint32_t lineLength = sensorInfo.outputSize.width + hblank;
|
||||||
|
|
||||||
|
const ControlInfo &v4l2VBlank = sensorControls.find(V4L2_CID_VBLANK)->second;
|
||||||
|
std::array<uint32_t, 3> frameHeights{
|
||||||
|
v4l2VBlank.min().get<int32_t>() + sensorInfo.outputSize.height,
|
||||||
|
v4l2VBlank.max().get<int32_t>() + sensorInfo.outputSize.height,
|
||||||
|
v4l2VBlank.def().get<int32_t>() + sensorInfo.outputSize.height,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::array<int64_t, 3> frameDurations;
|
||||||
|
for (unsigned int i = 0; i < frameHeights.size(); ++i) {
|
||||||
|
uint64_t frameSize = lineLength * frameHeights[i];
|
||||||
|
frameDurations[i] = frameSize / (sensorInfo.pixelRate / 1000000U);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrlMap[&controls::FrameDurationLimits] = ControlInfo(frameDurations[0],
|
||||||
|
frameDurations[1],
|
||||||
|
frameDurations[2]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute exposure time limits from the V4L2_CID_EXPOSURE control
|
||||||
|
* limits and the line duration.
|
||||||
|
*/
|
||||||
|
double lineDuration = sensorInfo.minLineLength / sensorInfo.pixelRate;
|
||||||
|
|
||||||
|
const ControlInfo &v4l2Exposure = sensorControls.find(V4L2_CID_EXPOSURE)->second;
|
||||||
|
int32_t minExposure = v4l2Exposure.min().get<int32_t>() * lineDuration;
|
||||||
|
int32_t maxExposure = v4l2Exposure.max().get<int32_t>() * lineDuration;
|
||||||
|
int32_t defExposure = v4l2Exposure.def().get<int32_t>() * lineDuration;
|
||||||
|
ctrlMap[&controls::ExposureTime] = ControlInfo(minExposure, maxExposure, defExposure);
|
||||||
|
|
||||||
|
/* Compute the analogue gain limits. */
|
||||||
|
const ControlInfo &v4l2Gain = sensorControls.find(V4L2_CID_ANALOGUE_GAIN)->second;
|
||||||
|
float minGain = camHelper_->gain(v4l2Gain.min().get<int32_t>());
|
||||||
|
float maxGain = camHelper_->gain(v4l2Gain.max().get<int32_t>());
|
||||||
|
float defGain = camHelper_->gain(v4l2Gain.def().get<int32_t>());
|
||||||
|
ctrlMap[&controls::AnalogueGain] = ControlInfo(minGain, maxGain, defGain);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Merge in any controls that we support either statically or from the
|
||||||
|
* algorithms.
|
||||||
|
*/
|
||||||
|
ctrlMap.merge(context_.ctrlMap);
|
||||||
|
|
||||||
|
*ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls);
|
||||||
|
}
|
||||||
|
|
||||||
|
int IPAMaliC55::configure(const IPAConfigInfo &ipaConfig,
|
||||||
|
[[maybe_unused]] uint8_t bayerOrder,
|
||||||
|
ControlInfoMap *ipaControls)
|
||||||
|
{
|
||||||
|
sensorControls_ = ipaConfig.sensorControls;
|
||||||
|
|
||||||
|
/* Clear the IPA context before the streaming session. */
|
||||||
|
context_.configuration = {};
|
||||||
|
context_.activeState = {};
|
||||||
|
context_.frameContexts.clear();
|
||||||
|
|
||||||
|
const IPACameraSensorInfo &info = ipaConfig.sensorInfo;
|
||||||
|
|
||||||
|
updateControls(info, ipaConfig.sensorControls, ipaControls);
|
||||||
|
|
||||||
|
for (auto const &a : algorithms()) {
|
||||||
|
Algorithm *algo = static_cast<Algorithm *>(a.get());
|
||||||
|
|
||||||
|
int ret = algo->configure(context_, info);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPAMaliC55::mapBuffers(const std::vector<IPABuffer> &buffers, bool readOnly)
|
||||||
|
{
|
||||||
|
for (const IPABuffer &buffer : buffers) {
|
||||||
|
const FrameBuffer fb(buffer.planes);
|
||||||
|
buffers_.emplace(
|
||||||
|
buffer.id,
|
||||||
|
MappedFrameBuffer(
|
||||||
|
&fb,
|
||||||
|
readOnly ? MappedFrameBuffer::MapFlag::Read
|
||||||
|
: MappedFrameBuffer::MapFlag::ReadWrite));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPAMaliC55::unmapBuffers(const std::vector<IPABuffer> &buffers)
|
||||||
|
{
|
||||||
|
for (const IPABuffer &buffer : buffers) {
|
||||||
|
auto it = buffers_.find(buffer.id);
|
||||||
|
if (it == buffers_.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
buffers_.erase(buffer.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPAMaliC55::queueRequest(const uint32_t request, const ControlList &controls)
|
||||||
|
{
|
||||||
|
IPAFrameContext &frameContext = context_.frameContexts.alloc(request);
|
||||||
|
|
||||||
|
for (auto const &a : algorithms()) {
|
||||||
|
Algorithm *algo = static_cast<Algorithm *>(a.get());
|
||||||
|
|
||||||
|
algo->queueRequest(context_, request, frameContext, controls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPAMaliC55::fillParams(unsigned int request,
|
||||||
|
[[maybe_unused]] uint32_t bufferId)
|
||||||
|
{
|
||||||
|
struct mali_c55_params_buffer *params;
|
||||||
|
IPAFrameContext &frameContext = context_.frameContexts.get(request);
|
||||||
|
|
||||||
|
params = reinterpret_cast<mali_c55_params_buffer *>(
|
||||||
|
buffers_.at(bufferId).planes()[0].data());
|
||||||
|
memset(params, 0, sizeof(mali_c55_params_buffer));
|
||||||
|
|
||||||
|
params->version = MALI_C55_PARAM_BUFFER_V1;
|
||||||
|
|
||||||
|
for (auto const &algo : algorithms()) {
|
||||||
|
algo->prepare(context_, request, frameContext, params);
|
||||||
|
|
||||||
|
ASSERT(params->total_size <= MALI_C55_PARAMS_MAX_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
paramsComputed.emit(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPAMaliC55::processStats(unsigned int request, unsigned int bufferId,
|
||||||
|
const ControlList &sensorControls)
|
||||||
|
{
|
||||||
|
IPAFrameContext &frameContext = context_.frameContexts.get(request);
|
||||||
|
const mali_c55_stats_buffer *stats = nullptr;
|
||||||
|
|
||||||
|
stats = reinterpret_cast<mali_c55_stats_buffer *>(
|
||||||
|
buffers_.at(bufferId).planes()[0].data());
|
||||||
|
|
||||||
|
frameContext.agc.exposure =
|
||||||
|
sensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>();
|
||||||
|
frameContext.agc.sensorGain =
|
||||||
|
camHelper_->gain(sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>());
|
||||||
|
|
||||||
|
ControlList metadata(controls::controls);
|
||||||
|
|
||||||
|
for (auto const &a : algorithms()) {
|
||||||
|
Algorithm *algo = static_cast<Algorithm *>(a.get());
|
||||||
|
|
||||||
|
algo->process(context_, request, frameContext, stats, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
setControls();
|
||||||
|
|
||||||
|
statsProcessed.emit(request, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace ipa::mali_c55 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External IPA module interface
|
||||||
|
*/
|
||||||
|
extern "C" {
|
||||||
|
const struct IPAModuleInfo ipaModuleInfo = {
|
||||||
|
IPA_MODULE_API_VERSION,
|
||||||
|
1,
|
||||||
|
"mali-c55",
|
||||||
|
"mali-c55",
|
||||||
|
};
|
||||||
|
|
||||||
|
IPAInterface *ipaCreate()
|
||||||
|
{
|
||||||
|
return new ipa::mali_c55::IPAMaliC55();
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* extern "C" */
|
||||||
|
|
||||||
|
} /* namespace libcamera */
|
33
src/ipa/mali-c55/meson.build
Normal file
33
src/ipa/mali-c55/meson.build
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
subdir('algorithms')
|
||||||
|
subdir('data')
|
||||||
|
|
||||||
|
ipa_name = 'ipa_mali_c55'
|
||||||
|
|
||||||
|
mali_c55_ipa_sources = files([
|
||||||
|
'ipa_context.cpp',
|
||||||
|
'mali-c55.cpp'
|
||||||
|
])
|
||||||
|
|
||||||
|
mali_c55_ipa_sources += mali_c55_ipa_algorithms
|
||||||
|
|
||||||
|
mod = shared_module(ipa_name,
|
||||||
|
mali_c55_ipa_sources,
|
||||||
|
name_prefix : '',
|
||||||
|
include_directories : [ipa_includes, libipa_includes],
|
||||||
|
dependencies : libcamera_private,
|
||||||
|
link_with : libipa,
|
||||||
|
install : true,
|
||||||
|
install_dir : ipa_install_dir)
|
||||||
|
|
||||||
|
if ipa_sign_module
|
||||||
|
custom_target(ipa_name + '.so.sign',
|
||||||
|
input : mod,
|
||||||
|
output : ipa_name + '.so.sign',
|
||||||
|
command : [ipa_sign, ipa_priv_key, '@INPUT@', '@OUTPUT@'],
|
||||||
|
install : false,
|
||||||
|
build_by_default : true)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ipa_names += ipa_name
|
27
src/ipa/mali-c55/module.h
Normal file
27
src/ipa/mali-c55/module.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024, Ideas On Board
|
||||||
|
*
|
||||||
|
* module.h - Mali-C55 IPA Module
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <linux/mali-c55-config.h>
|
||||||
|
|
||||||
|
#include <libcamera/ipa/mali-c55_ipa_interface.h>
|
||||||
|
|
||||||
|
#include <libipa/module.h>
|
||||||
|
|
||||||
|
#include "ipa_context.h"
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
namespace ipa::mali_c55 {
|
||||||
|
|
||||||
|
using Module = ipa::Module<IPAContext, IPAFrameContext, IPACameraSensorInfo,
|
||||||
|
mali_c55_params_buffer, mali_c55_stats_buffer>;
|
||||||
|
|
||||||
|
} /* namespace ipa::mali_c55 */
|
||||||
|
|
||||||
|
} /* namespace libcamera*/
|
Loading…
Add table
Add a link
Reference in a new issue