summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/camera_device.cpp2
-rw-r--r--src/apps/cam/drm.cpp25
-rw-r--r--src/ipa/rpi/common/ipa_base.cpp3
-rw-r--r--src/ipa/simple/algorithms/ccm.cpp60
-rw-r--r--src/ipa/simple/algorithms/ccm.h11
-rw-r--r--src/ipa/simple/ipa_context.h4
-rw-r--r--src/libcamera/ipa_data_serializer.cpp1
-rw-r--r--src/libcamera/pipeline/ipu3/cio2.h2
-rw-r--r--src/libcamera/pipeline/mali-c55/mali-c55.cpp16
-rw-r--r--src/libcamera/process.cpp18
10 files changed, 113 insertions, 29 deletions
diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index a038131a..80ff248c 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -1079,7 +1079,7 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
buffer.internalBuffer = frameBuffer;
descriptor->request_->addBuffer(sourceStream->stream(),
- frameBuffer, nullptr);
+ frameBuffer);
requestedStreams.insert(sourceStream);
}
diff --git a/src/apps/cam/drm.cpp b/src/apps/cam/drm.cpp
index 47bbb6b0..f4b47097 100644
--- a/src/apps/cam/drm.cpp
+++ b/src/apps/cam/drm.cpp
@@ -450,8 +450,6 @@ int Device::openCard()
}
for (struct dirent *res; (res = readdir(folder));) {
- uint64_t cap;
-
if (strncmp(res->d_name, "card", 4))
continue;
@@ -465,15 +463,22 @@ int Device::openCard()
}
/*
- * Skip devices that don't support the modeset API, to avoid
- * selecting a DRM device corresponding to a GPU. There is no
- * modeset capability, but the kernel returns an error for most
- * caps if mode setting isn't support by the driver. The
- * DRM_CAP_DUMB_BUFFER capability is one of those, other would
- * do as well. The capability value itself isn't relevant.
+ * Skip non-display devices. While this could in theory be done
+ * by checking for support of the mode setting API, some
+ * out-of-tree render-only GPU drivers (namely powervr)
+ * incorrectly set the DRIVER_MODESET driver feature. Check for
+ * the presence of at least one CRTC, encoder and connector
+ * instead.
*/
- ret = drmGetCap(fd_, DRM_CAP_DUMB_BUFFER, &cap);
- if (ret < 0) {
+ std::unique_ptr<drmModeRes, decltype(&drmModeFreeResources)> resources{
+ drmModeGetResources(fd_),
+ &drmModeFreeResources
+ };
+ if (!resources ||
+ resources->count_connectors <= 0 ||
+ resources->count_crtcs <= 0 ||
+ resources->count_encoders <= 0) {
+ resources.reset();
drmClose(fd_);
fd_ = -1;
continue;
diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp
index e0a93daa..e0f8b7e7 100644
--- a/src/ipa/rpi/common/ipa_base.cpp
+++ b/src/ipa/rpi/common/ipa_base.cpp
@@ -1563,7 +1563,8 @@ void IpaBase::applyFrameDurations(Duration minFrameDuration, Duration maxFrameDu
RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
controller_.getAlgorithm("agc"));
- agc->setMaxExposureTime(maxExposureTime);
+ if (agc)
+ agc->setMaxExposureTime(maxExposureTime);
}
void IpaBase::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)
diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp
index d5ba928d..0a98406c 100644
--- a/src/ipa/simple/algorithms/ccm.cpp
+++ b/src/ipa/simple/algorithms/ccm.cpp
@@ -3,7 +3,7 @@
* Copyright (C) 2024, Ideas On Board
* Copyright (C) 2024-2025, Red Hat Inc.
*
- * Color correction matrix
+ * Color correction matrix + saturation
*/
#include "ccm.h"
@@ -13,6 +13,8 @@
#include <libcamera/control_ids.h>
+#include "libcamera/internal/matrix.h"
+
namespace {
constexpr unsigned int kTemperatureThreshold = 100;
@@ -35,28 +37,77 @@ int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData
}
context.ccmEnabled = true;
+ context.ctrlMap[&controls::Saturation] = ControlInfo(0.0f, 2.0f, 1.0f);
+
+ return 0;
+}
+
+int Ccm::configure(IPAContext &context,
+ [[maybe_unused]] const IPAConfigInfo &configInfo)
+{
+ context.activeState.knobs.saturation = std::optional<double>();
return 0;
}
+void Ccm::queueRequest(typename Module::Context &context,
+ [[maybe_unused]] const uint32_t frame,
+ [[maybe_unused]] typename Module::FrameContext &frameContext,
+ const ControlList &controls)
+{
+ const auto &saturation = controls.get(controls::Saturation);
+ if (saturation.has_value()) {
+ context.activeState.knobs.saturation = saturation;
+ LOG(IPASoftCcm, Debug) << "Setting saturation to " << saturation.value();
+ }
+}
+
+void Ccm::applySaturation(Matrix<float, 3, 3> &ccm, float saturation)
+{
+ /* https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion */
+ const Matrix<float, 3, 3> rgb2ycbcr{
+ { 0.256788235294, 0.504129411765, 0.0979058823529,
+ -0.148223529412, -0.290992156863, 0.439215686275,
+ 0.439215686275, -0.367788235294, -0.0714274509804 }
+ };
+ const Matrix<float, 3, 3> ycbcr2rgb{
+ { 1.16438356164, 0, 1.59602678571,
+ 1.16438356164, -0.391762290094, -0.812967647235,
+ 1.16438356164, 2.01723214285, 0 }
+ };
+ const Matrix<float, 3, 3> saturationMatrix{
+ { 1, 0, 0,
+ 0, saturation, 0,
+ 0, 0, saturation }
+ };
+ ccm = ycbcr2rgb * saturationMatrix * rgb2ycbcr * ccm;
+}
+
void Ccm::prepare(IPAContext &context, const uint32_t frame,
IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)
{
+ auto &saturation = context.activeState.knobs.saturation;
+
const unsigned int ct = context.activeState.awb.temperatureK;
- /* Change CCM only on bigger temperature changes. */
+ /* Change CCM only on saturation or bigger temperature changes. */
if (frame > 0 &&
- utils::abs_diff(ct, lastCt_) < kTemperatureThreshold) {
+ utils::abs_diff(ct, lastCt_) < kTemperatureThreshold &&
+ saturation == lastSaturation_) {
frameContext.ccm.ccm = context.activeState.ccm.ccm;
context.activeState.ccm.changed = false;
return;
}
lastCt_ = ct;
+ lastSaturation_ = saturation;
Matrix<float, 3, 3> ccm = ccm_.getInterpolated(ct);
+ if (saturation)
+ applySaturation(ccm, saturation.value());
context.activeState.ccm.ccm = ccm;
frameContext.ccm.ccm = ccm;
+ frameContext.saturation = saturation;
context.activeState.ccm.changed = true;
}
@@ -67,6 +118,9 @@ void Ccm::process([[maybe_unused]] IPAContext &context,
ControlList &metadata)
{
metadata.set(controls::ColourCorrectionMatrix, frameContext.ccm.ccm.data());
+
+ const auto &saturation = frameContext.saturation;
+ metadata.set(controls::Saturation, saturation.value_or(1.0));
}
REGISTER_IPA_ALGORITHM(Ccm, "Ccm")
diff --git a/src/ipa/simple/algorithms/ccm.h b/src/ipa/simple/algorithms/ccm.h
index f4e2b85b..8279a3d5 100644
--- a/src/ipa/simple/algorithms/ccm.h
+++ b/src/ipa/simple/algorithms/ccm.h
@@ -7,6 +7,8 @@
#pragma once
+#include <optional>
+
#include "libcamera/internal/matrix.h"
#include <libipa/interpolator.h>
@@ -24,6 +26,12 @@ public:
~Ccm() = default;
int init(IPAContext &context, const YamlObject &tuningData) override;
+ int configure(IPAContext &context,
+ const IPAConfigInfo &configInfo) override;
+ void queueRequest(typename Module::Context &context,
+ const uint32_t frame,
+ typename Module::FrameContext &frameContext,
+ const ControlList &controls) override;
void prepare(IPAContext &context,
const uint32_t frame,
IPAFrameContext &frameContext,
@@ -34,7 +42,10 @@ public:
ControlList &metadata) override;
private:
+ void applySaturation(Matrix<float, 3, 3> &ccm, float saturation);
+
unsigned int lastCt_;
+ std::optional<float> lastSaturation_;
Interpolator<Matrix<float, 3, 3>> ccm_;
};
diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h
index 88cc6c35..a471b80a 100644
--- a/src/ipa/simple/ipa_context.h
+++ b/src/ipa/simple/ipa_context.h
@@ -63,6 +63,7 @@ struct IPAActiveState {
struct {
/* 0..2 range, 1.0 = normal */
std::optional<double> contrast;
+ std::optional<float> saturation;
} knobs;
};
@@ -75,11 +76,14 @@ struct IPAFrameContext : public FrameContext {
int32_t exposure;
double gain;
} sensor;
+
struct {
double red;
double blue;
} gains;
+
std::optional<double> contrast;
+ std::optional<float> saturation;
};
struct IPAContext {
diff --git a/src/libcamera/ipa_data_serializer.cpp b/src/libcamera/ipa_data_serializer.cpp
index 2189a246..0537f785 100644
--- a/src/libcamera/ipa_data_serializer.cpp
+++ b/src/libcamera/ipa_data_serializer.cpp
@@ -196,7 +196,6 @@ IPADataSerializer<type>::serialize(const type &data, \
[[maybe_unused]] ControlSerializer *cs) \
{ \
std::vector<uint8_t> dataVec; \
- dataVec.reserve(sizeof(type)); \
appendPOD<type>(dataVec, data); \
\
return { dataVec, {} }; \
diff --git a/src/libcamera/pipeline/ipu3/cio2.h b/src/libcamera/pipeline/ipu3/cio2.h
index 963c2f6b..3aa3a1ca 100644
--- a/src/libcamera/pipeline/ipu3/cio2.h
+++ b/src/libcamera/pipeline/ipu3/cio2.h
@@ -66,8 +66,6 @@ public:
private:
void freeBuffers();
- void cio2BufferReady(FrameBuffer *buffer);
-
std::unique_ptr<CameraSensor> sensor_;
std::unique_ptr<V4L2Subdevice> csi2_;
std::unique_ptr<V4L2VideoDevice> output_;
diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
index a05e11fc..4acc091b 100644
--- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp
+++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
@@ -131,8 +131,6 @@ private:
void setSensorControls(const ControlList &sensorControls);
std::string id_;
- std::vector<unsigned int> tpgCodes_;
- std::vector<Size> tpgSizes_;
Size tpgResolution_;
};
@@ -159,15 +157,16 @@ int MaliC55CameraData::init()
*/
sensor_ = CameraSensorFactoryBase::create(entity_);
if (!sensor_)
- return ret;
+ return -ENODEV;
const MediaPad *sourcePad = entity_->getPadByIndex(0);
MediaEntity *csiEntity = sourcePad->links()[0]->sink()->entity();
csi_ = std::make_unique<V4L2Subdevice>(csiEntity);
- if (csi_->open()) {
+ ret = csi_->open();
+ if (ret) {
LOG(MaliC55, Error) << "Failed to open CSI-2 subdevice";
- return false;
+ return ret;
}
return 0;
@@ -180,16 +179,15 @@ void MaliC55CameraData::initTPGData()
if (formats.empty())
return;
- tpgCodes_ = utils::map_keys(formats);
- std::sort(tpgCodes_.begin(), tpgCodes_.end());
+ std::vector<Size> tpgSizes;
for (const auto &format : formats) {
const std::vector<SizeRange> &ranges = format.second;
- std::transform(ranges.begin(), ranges.end(), std::back_inserter(tpgSizes_),
+ std::transform(ranges.begin(), ranges.end(), std::back_inserter(tpgSizes),
[](const SizeRange &range) { return range.max; });
}
- tpgResolution_ = tpgSizes_.back();
+ tpgResolution_ = tpgSizes.back();
}
void MaliC55CameraData::setSensorControls(const ControlList &sensorControls)
diff --git a/src/libcamera/process.cpp b/src/libcamera/process.cpp
index 68fad327..d836fb07 100644
--- a/src/libcamera/process.cpp
+++ b/src/libcamera/process.cpp
@@ -259,7 +259,21 @@ int Process::start(const std::string &path,
if (isolate())
_exit(EXIT_FAILURE);
- closeAllFdsExcept(fds);
+ std::vector<int> v(fds);
+ v.push_back(STDERR_FILENO);
+ closeAllFdsExcept(v);
+
+ const auto tryDevNullLowestFd = [](int expected, int oflag) {
+ int fd = open("/dev/null", oflag);
+ if (fd < 0)
+ _exit(EXIT_FAILURE);
+ if (fd != expected)
+ close(fd);
+ };
+
+ tryDevNullLowestFd(STDIN_FILENO, O_RDONLY);
+ tryDevNullLowestFd(STDOUT_FILENO, O_WRONLY);
+ tryDevNullLowestFd(STDERR_FILENO, O_WRONLY);
const char *file = utils::secure_getenv("LIBCAMERA_LOG_FILE");
if (file && strcmp(file, "syslog"))
@@ -274,7 +288,7 @@ int Process::start(const std::string &path,
execv(path.c_str(), (char **)argv);
- exit(EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
}