diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/android/camera_device.cpp | 2 | ||||
-rw-r--r-- | src/apps/cam/drm.cpp | 25 | ||||
-rw-r--r-- | src/ipa/rpi/common/ipa_base.cpp | 3 | ||||
-rw-r--r-- | src/ipa/simple/algorithms/ccm.cpp | 60 | ||||
-rw-r--r-- | src/ipa/simple/algorithms/ccm.h | 11 | ||||
-rw-r--r-- | src/ipa/simple/ipa_context.h | 4 | ||||
-rw-r--r-- | src/libcamera/ipa_data_serializer.cpp | 1 | ||||
-rw-r--r-- | src/libcamera/pipeline/ipu3/cio2.h | 2 | ||||
-rw-r--r-- | src/libcamera/pipeline/mali-c55/mali-c55.cpp | 16 | ||||
-rw-r--r-- | src/libcamera/process.cpp | 18 |
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); } } |