summaryrefslogtreecommitdiff
path: root/src/ipa/raspberrypi/controller/rpi/sdn.cpp
blob: 959bc7406a0150712dac11a18834680b0450aacf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/* SPDX-License-Identifier: BSD-2-Clause */
/*
 * Copyright (C) 2019-2021, Raspberry Pi (Trading) Limited
 *
 * sdn.cpp - SDN (spatial denoise) control algorithm
 */

#include "libcamera/internal/log.h"

#include "../denoise_status.h"
#include "../noise_status.h"

#include "sdn.hpp"

using namespace RPiController;
using namespace libcamera;

LOG_DEFINE_CATEGORY(RPiSdn)

// Calculate settings for the spatial denoise block using the noise profile in
// the image metadata.

#define NAME "rpi.sdn"

Sdn::Sdn(Controller *controller)
	: DenoiseAlgorithm(controller), mode_(DenoiseMode::ColourOff)
{
}

char const *Sdn::Name() const
{
	return NAME;
}

void Sdn::Read(boost::property_tree::ptree const &params)
{
	deviation_ = params.get<double>("deviation", 3.2);
	strength_ = params.get<double>("strength", 0.75);
}

void Sdn::Initialise() {}

void Sdn::Prepare(Metadata *image_metadata)
{
	struct NoiseStatus noise_status = {};
	noise_status.noise_slope = 3.0; // in case no metadata
	if (image_metadata->Get("noise.status", noise_status) != 0)
		LOG(RPiSdn, Warning) << "no noise profile found";
	LOG(RPiSdn, Debug)
		<< "Noise profile: constant " << noise_status.noise_constant
		<< " slope " << noise_status.noise_slope;
	struct DenoiseStatus status;
	status.noise_constant = noise_status.noise_constant * deviation_;
	status.noise_slope = noise_status.noise_slope * deviation_;
	status.strength = strength_;
	status.mode = static_cast<std::underlying_type_t<DenoiseMode>>(mode_);
	image_metadata->Set("denoise.status", status);
	LOG(RPiSdn, Debug)
		<< "programmed constant " << status.noise_constant
		<< " slope " << status.noise_slope
		<< " strength " << status.strength;
}

void Sdn::SetMode(DenoiseMode mode)
{
	// We only distinguish between off and all other modes.
	mode_ = mode;
}

// Register algorithm with the system.
static Algorithm *Create(Controller *controller)
{
	return (Algorithm *)new Sdn(controller);
}
static RegisterAlgorithm reg(NAME, &Create);
ass="hl str">"openat"); get_symbol(fops_.dup, "dup"); get_symbol(fops_.close, "close"); get_symbol(fops_.ioctl, "ioctl"); get_symbol(fops_.mmap, "mmap"); get_symbol(fops_.munmap, "munmap"); } V4L2CompatManager::~V4L2CompatManager() { devices_.clear(); mmaps_.clear(); if (isRunning()) { exit(0); /* \todo Wait with a timeout, just in case. */ wait(); } } int V4L2CompatManager::init() { start(); MutexLocker locker(mutex_); cv_.wait(locker, [&] { return initialized_; }); return 0; } void V4L2CompatManager::run() { cm_ = new CameraManager(); int ret = cm_->start(); if (ret) { LOG(V4L2Compat, Error) << "Failed to start camera manager: " << strerror(-ret); return; } LOG(V4L2Compat, Debug) << "Started camera manager"; /* * For each Camera registered in the system, a V4L2CameraProxy gets * created here to wrap a camera device. */ unsigned int index = 0; for (auto &camera : cm_->cameras()) { V4L2CameraProxy *proxy = new V4L2CameraProxy(index, camera); proxies_.emplace_back(proxy); ++index; } /* * libcamera has been initialized. Unlock the init() caller as we're * now ready to handle calls from the framework. */ mutex_.lock(); initialized_ = true; mutex_.unlock(); cv_.notify_one(); /* Now start processing events and messages. */ exec(); proxies_.clear(); cm_->stop(); delete cm_; cm_ = nullptr; } V4L2CompatManager *V4L2CompatManager::instance() { static V4L2CompatManager instance; return &instance; } V4L2CameraProxy *V4L2CompatManager::getProxy(int fd) { auto device = devices_.find(fd); if (device == devices_.end()) return nullptr; return device->second; } int V4L2CompatManager::getCameraIndex(int fd) { struct stat statbuf; int ret = fstat(fd, &statbuf); if (ret < 0) return -1; std::shared_ptr<Camera> target = cm_->get(statbuf.st_rdev); if (!target) return -1; unsigned int index = 0; for (auto &camera : cm_->cameras()) { if (camera == target) return index; ++index; } return -1; } int V4L2CompatManager::openat(int dirfd, const char *path, int oflag, mode_t mode) { int fd = fops_.openat(dirfd, path, oflag, mode); if (fd < 0) return fd; struct stat statbuf; int ret = fstat(fd, &statbuf); if (ret < 0 || (statbuf.st_mode & S_IFMT) != S_IFCHR || major(statbuf.st_rdev) != 81) return fd; if (!isRunning()) init(); ret = getCameraIndex(fd); if (ret < 0) { LOG(V4L2Compat, Info) << "No camera found for " << path; return fd; } fops_.close(fd); unsigned int camera_index = static_cast<unsigned int>(ret); V4L2CameraProxy *proxy = proxies_[camera_index].get(); ret = proxy->open(oflag & O_NONBLOCK); if (ret < 0) return ret; int efd = eventfd(0, oflag & (O_CLOEXEC | O_NONBLOCK)); if (efd < 0) { proxy->close(); return efd; } devices_.emplace(efd, proxy); return efd; } int V4L2CompatManager::dup(int oldfd) { int newfd = fops_.dup(oldfd); if (newfd < 0) return newfd; auto device = devices_.find(oldfd); if (device != devices_.end()) { V4L2CameraProxy *proxy = device->second; devices_[newfd] = proxy; proxy->dup(); } return newfd; } int V4L2CompatManager::close(int fd) { V4L2CameraProxy *proxy = getProxy(fd); if (proxy) { proxy->close(); devices_.erase(fd); return 0; } return fops_.close(fd); } void *V4L2CompatManager::mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { V4L2CameraProxy *proxy = getProxy(fd); if (!proxy) return fops_.mmap(addr, length, prot, flags, fd, offset); void *map = proxy->mmap(addr, length, prot, flags, offset); if (map == MAP_FAILED) return map; mmaps_[map] = proxy; return map; } int V4L2CompatManager::munmap(void *addr, size_t length) { auto device = mmaps_.find(addr); if (device == mmaps_.end()) return fops_.munmap(addr, length); V4L2CameraProxy *proxy = device->second; int ret = proxy->munmap(addr, length); if (ret < 0) return ret; mmaps_.erase(device); return 0; } int V4L2CompatManager::ioctl(int fd, unsigned long request, void *arg) { V4L2CameraProxy *proxy = getProxy(fd); if (!proxy) return fops_.ioctl(fd, request, arg); return proxy->ioctl(request, arg); }