summaryrefslogtreecommitdiff
path: root/src/ipa/raspberrypi/controller/algorithm.hpp
blob: 5123c87bab344ee40c900cc012a655ed62f8c62e (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
/* SPDX-License-Identifier: BSD-2-Clause */
/*
 * Copyright (C) 2019, Raspberry Pi (Trading) Limited
 *
 * algorithm.hpp - ISP control algorithm interface
 */
#pragma once

// All algorithms should be derived from this class and made available to the
// Controller.

#include <string>
#include <memory>
#include <map>

#include "controller.hpp"

#include <boost/property_tree/ptree.hpp>

namespace RPiController {

// This defines the basic interface for all control algorithms.

class Algorithm
{
public:
	Algorithm(Controller *controller)
		: controller_(controller), paused_(false)
	{
	}
	virtual ~Algorithm() = default;
	virtual char const *Name() const = 0;
	virtual bool IsPaused() const { return paused_; }
	virtual void Pause() { paused_ = true; }
	virtual void Resume() { paused_ = false; }
	virtual void Read(boost::property_tree::ptree const &params);
	virtual void Initialise();
	virtual void SwitchMode(CameraMode const &camera_mode, Metadata *metadata);
	virtual void Prepare(Metadata *image_metadata);
	virtual void Process(StatisticsPtr &stats, Metadata *image_metadata);
	Metadata &GetGlobalMetadata() const
	{
		return controller_->GetGlobalMetadata();
	}

private:
	Controller *controller_;
	bool paused_;
};

// This code is for automatic registration of Front End algorithms with the
// system.

typedef Algorithm *(*AlgoCreateFunc)(Controller *controller);
struct RegisterAlgorithm {
	RegisterAlgorithm(char const *name, AlgoCreateFunc create_func);
};
std::map<std::string, AlgoCreateFunc> const &GetAlgorithms();

} // namespace RPiController
ss="hl opt">~Private(); unsigned int numPlanes() const; Span<uint8_t> plane(unsigned int plane); unsigned int stride(unsigned int plane) const; unsigned int offset(unsigned int plane) const; unsigned int size(unsigned int plane) const; size_t jpegBufferSize(size_t maxJpegBufferSize) const; private: struct PlaneInfo { unsigned int stride; unsigned int offset; unsigned int size; }; void map(); int fd_; int flags_; off_t bufferLength_; bool mapped_; std::vector<PlaneInfo> planeInfo_; }; CameraBuffer::Private::Private([[maybe_unused]] CameraBuffer *cameraBuffer, buffer_handle_t camera3Buffer, PixelFormat pixelFormat, const Size &size, int flags) : fd_(-1), flags_(flags), bufferLength_(-1), mapped_(false) { error_ = 0; const auto &info = PixelFormatInfo::info(pixelFormat); if (!info.isValid()) { error_ = -EINVAL; LOG(HAL, Error) << "Invalid pixel format: " << pixelFormat; return; } /* * As Android doesn't offer an API to query buffer layouts, assume for * now that the buffer is backed by a single dmabuf, with planes being * stored contiguously. */ for (int i = 0; i < camera3Buffer->numFds; i++) { if (camera3Buffer->data[i] == -1 || camera3Buffer->data[i] == fd_) continue; if (fd_ != -1) { error_ = -EINVAL; LOG(HAL, Error) << "Discontiguous planes are not supported"; return; } fd_ = camera3Buffer->data[i]; } if (fd_ == -1) { error_ = -EINVAL; LOG(HAL, Error) << "No valid file descriptor"; return; } bufferLength_ = lseek(fd_, 0, SEEK_END); if (bufferLength_ < 0) { error_ = -errno; LOG(HAL, Error) << "Failed to get buffer length"; return; } const unsigned int numPlanes = info.numPlanes(); planeInfo_.resize(numPlanes); unsigned int offset = 0; for (unsigned int i = 0; i < numPlanes; ++i) { const unsigned int planeSize = info.planeSize(size, i); planeInfo_[i].stride = info.stride(size.width, i, 1u); planeInfo_[i].offset = offset; planeInfo_[i].size = planeSize; if (bufferLength_ < offset + planeSize) { LOG(HAL, Error) << "Plane " << i << " is out of buffer:" << " plane offset=" << offset << ", plane size=" << planeSize << ", buffer length=" << bufferLength_; return; } offset += planeSize; } } CameraBuffer::Private::~Private() { } unsigned int CameraBuffer::Private::numPlanes() const { return planeInfo_.size(); } Span<uint8_t> CameraBuffer::Private::plane(unsigned int plane) { if (!mapped_) map(); if (!mapped_) return {}; return planes_[plane]; } unsigned int CameraBuffer::Private::stride(unsigned int plane) const { if (plane >= planeInfo_.size()) return 0; return planeInfo_[plane].stride; } unsigned int CameraBuffer::Private::offset(unsigned int plane) const { if (plane >= planeInfo_.size()) return 0; return planeInfo_[plane].offset; } unsigned int CameraBuffer::Private::size(unsigned int plane) const { if (plane >= planeInfo_.size()) return 0; return planeInfo_[plane].size; } size_t CameraBuffer::Private::jpegBufferSize(size_t maxJpegBufferSize) const { ASSERT(bufferLength_ >= 0); return std::min<unsigned int>(bufferLength_, maxJpegBufferSize); } void CameraBuffer::Private::map() { ASSERT(fd_ != -1); ASSERT(bufferLength_ >= 0); void *address = mmap(nullptr, bufferLength_, flags_, MAP_SHARED, fd_, 0); if (address == MAP_FAILED) { error_ = -errno; LOG(HAL, Error) << "Failed to mmap plane"; return; } maps_.emplace_back(static_cast<uint8_t *>(address), bufferLength_); planes_.reserve(planeInfo_.size()); for (const auto &info : planeInfo_) { planes_.emplace_back( static_cast<uint8_t *>(address) + info.offset, info.size); } mapped_ = true; } PUBLIC_CAMERA_BUFFER_IMPLEMENTATION