summaryrefslogtreecommitdiff
path: root/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h
diff options
context:
space:
mode:
authorNaushir Patuck <naush@raspberrypi.com>2020-05-03 16:24:05 +0100
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-05-11 23:54:04 +0300
commit740fd1b62f670bd1ad4965ef0866ef5d51bdf947 (patch)
treefb5c7407d1a53256008e75eaa47b4d2418c2c8c0 /src/libcamera/pipeline/raspberrypi/staggered_ctrl.h
parent43d81d43fe91defcadec9f2f4f01e5afe9852ec5 (diff)
libcamera: pipeline: Raspberry Pi pipeline handler
Initial implementation of the Raspberry Pi (BCM2835) ISP pipeline handler. All code is licensed under the BSD-2-Clause terms. Copyright (c) 2019-2020 Raspberry Pi Trading Ltd. Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Diffstat (limited to 'src/libcamera/pipeline/raspberrypi/staggered_ctrl.h')
-rw-r--r--src/libcamera/pipeline/raspberrypi/staggered_ctrl.h236
1 files changed, 236 insertions, 0 deletions
diff --git a/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h
new file mode 100644
index 00000000..0403c087
--- /dev/null
+++ b/src/libcamera/pipeline/raspberrypi/staggered_ctrl.h
@@ -0,0 +1,236 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2020, Raspberry Pi (Trading) Ltd.
+ *
+ * staggered_ctrl.h - Helper for writing staggered ctrls to a V4L2 device.
+ */
+#pragma once
+
+#include <algorithm>
+#include <initializer_list>
+#include <mutex>
+#include <unordered_map>
+
+#include <libcamera/controls.h>
+#include "log.h"
+#include "utils.h"
+#include "v4l2_videodevice.h"
+
+/* For logging... */
+using libcamera::LogCategory;
+using libcamera::LogDebug;
+using libcamera::LogInfo;
+using libcamera::utils::hex;
+
+LOG_DEFINE_CATEGORY(RPI_S_W);
+
+namespace RPi {
+
+class StaggeredCtrl
+{
+public:
+ StaggeredCtrl()
+ : init_(false), setCount_(0), getCount_(0), maxDelay_(0)
+ {
+ }
+
+ ~StaggeredCtrl()
+ {
+ }
+
+ operator bool() const
+ {
+ return init_;
+ }
+
+ void init(libcamera::V4L2VideoDevice *dev,
+ std::initializer_list<std::pair<const uint32_t, uint8_t>> delayList)
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+
+ dev_ = dev;
+ delay_ = delayList;
+ ctrl_.clear();
+
+ /* Find the largest delay across all controls. */
+ maxDelay_ = 0;
+ for (auto const &p : delay_) {
+ LOG(RPI_S_W, Info) << "Init ctrl "
+ << hex(p.first) << " with delay "
+ << static_cast<int>(p.second);
+ maxDelay_ = std::max(maxDelay_, p.second);
+ }
+
+ init_ = true;
+ }
+
+ void reset()
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+
+ int lastSetCount = std::max<int>(0, setCount_ - 1);
+ std::unordered_map<uint32_t, int32_t> lastVal;
+
+ /* Reset the counters. */
+ setCount_ = getCount_ = 0;
+
+ /* Look for the last set values. */
+ for (auto const &c : ctrl_)
+ lastVal[c.first] = c.second[lastSetCount].value;
+
+ /* Apply the last set values as the next to be applied. */
+ ctrl_.clear();
+ for (auto &c : lastVal)
+ ctrl_[c.first][setCount_] = CtrlInfo(c.second);
+ }
+
+ bool set(uint32_t ctrl, int32_t value)
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+
+ /* Can we find this ctrl as one that is registered? */
+ if (delay_.find(ctrl) == delay_.end())
+ return false;
+
+ ctrl_[ctrl][setCount_].value = value;
+ ctrl_[ctrl][setCount_].updated = true;
+
+ return true;
+ }
+
+ bool set(std::initializer_list<std::pair<const uint32_t, int32_t>> ctrlList)
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+
+ for (auto const &p : ctrlList) {
+ /* Can we find this ctrl? */
+ if (delay_.find(p.first) == delay_.end())
+ return false;
+
+ ctrl_[p.first][setCount_] = CtrlInfo(p.second);
+ }
+
+ return true;
+ }
+
+ bool set(libcamera::ControlList &controls)
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+
+ for (auto const &p : controls) {
+ /* Can we find this ctrl? */
+ if (delay_.find(p.first) == delay_.end())
+ return false;
+
+ ctrl_[p.first][setCount_] = CtrlInfo(p.second.get<int32_t>());
+ LOG(RPI_S_W, Debug) << "Setting ctrl "
+ << hex(p.first) << " to "
+ << ctrl_[p.first][setCount_].value
+ << " at index "
+ << setCount_;
+ }
+
+ return true;
+ }
+
+ int write()
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+ libcamera::ControlList controls(dev_->controls());
+
+ for (auto &p : ctrl_) {
+ int delayDiff = maxDelay_ - delay_[p.first];
+ int index = std::max<int>(0, setCount_ - delayDiff);
+
+ if (p.second[index].updated) {
+ /* We need to write this value out. */
+ controls.set(p.first, p.second[index].value);
+ p.second[index].updated = false;
+ LOG(RPI_S_W, Debug) << "Writing ctrl "
+ << hex(p.first) << " to "
+ << p.second[index].value
+ << " at index "
+ << index;
+ }
+ }
+
+ nextFrame();
+ return dev_->setControls(&controls);
+ }
+
+ void get(std::unordered_map<uint32_t, int32_t> &ctrl, uint8_t offset = 0)
+ {
+ std::lock_guard<std::mutex> lock(lock_);
+
+ /* Account for the offset to reset the getCounter. */
+ getCount_ += offset + 1;
+
+ ctrl.clear();
+ for (auto &p : ctrl_) {
+ int index = std::max<int>(0, getCount_ - maxDelay_);
+ ctrl[p.first] = p.second[index].value;
+ LOG(RPI_S_W, Debug) << "Getting ctrl "
+ << hex(p.first) << " to "
+ << p.second[index].value
+ << " at index "
+ << index;
+ }
+ }
+
+private:
+ void nextFrame()
+ {
+ /* Advance the control history to the next frame */
+ int prevCount = setCount_;
+ setCount_++;
+
+ LOG(RPI_S_W, Debug) << "Next frame, set index is " << setCount_;
+
+ for (auto &p : ctrl_) {
+ p.second[setCount_].value = p.second[prevCount].value;
+ p.second[setCount_].updated = false;
+ }
+ }
+
+ /* listSize must be a power of 2. */
+ static constexpr int listSize = (1 << 4);
+ struct CtrlInfo {
+ CtrlInfo()
+ : value(0), updated(false)
+ {
+ }
+
+ CtrlInfo(int32_t value_)
+ : value(value_), updated(true)
+ {
+ }
+
+ int32_t value;
+ bool updated;
+ };
+
+ class CircularArray : public std::array<CtrlInfo, listSize>
+ {
+ public:
+ CtrlInfo &operator[](int index)
+ {
+ return std::array<CtrlInfo, listSize>::operator[](index & (listSize - 1));
+ }
+
+ const CtrlInfo &operator[](int index) const
+ {
+ return std::array<CtrlInfo, listSize>::operator[](index & (listSize - 1));
+ }
+ };
+
+ bool init_;
+ uint32_t setCount_;
+ uint32_t getCount_;
+ uint8_t maxDelay_;
+ libcamera::V4L2VideoDevice *dev_;
+ std::unordered_map<uint32_t, uint8_t> delay_;
+ std::unordered_map<uint32_t, CircularArray> ctrl_;
+ std::mutex lock_;
+};
+
+} /* namespace RPi */