summaryrefslogtreecommitdiff
path: root/src/ipa/libipa/histogram.h
blob: c2761cb29e7abdcec77ce1d640423c0ae6075ca6 (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
/* SPDX-License-Identifier: BSD-2-Clause */
/*
 * Copyright (C) 2019, Raspberry Pi (Trading) Limited
 *
 * histogram.h - histogram calculation interface
 */
#ifndef __LIBCAMERA_IPA_LIBIPA_HISTOGRAM_H__
#define __LIBCAMERA_IPA_LIBIPA_HISTOGRAM_H__

#include <assert.h>
#include <limits.h>
#include <stdint.h>

#include <vector>

#include <libcamera/base/span.h>

namespace libcamera {

namespace ipa {

class Histogram
{
public:
	Histogram(Span<uint32_t> data);
	size_t bins() const { return cumulative_.size() - 1; }
	uint64_t total() const { return cumulative_[cumulative_.size() - 1]; }
	uint64_t cumulativeFrequency(double bin) const;
	double quantile(double q, uint32_t first = 0, uint32_t last = UINT_MAX) const;
	double interQuantileMean(double lowQuantile, double hiQuantile) const;

private:
	std::vector<uint64_t> cumulative_;
};

} /* namespace ipa */

} /* namespace libcamera */

#endif /* __LIBCAMERA_IPA_LIBIPA_HISTOGRAM_H__ */
pan>::unique_ptr<Image> image{ new Image() }; assert(!buffer->planes().empty()); int mmapFlags = 0; if (mode & MapMode::ReadOnly) mmapFlags |= PROT_READ; if (mode & MapMode::WriteOnly) mmapFlags |= PROT_WRITE; struct MappedBufferInfo { uint8_t *address = nullptr; size_t mapLength = 0; size_t dmabufLength = 0; }; std::map<int, MappedBufferInfo> mappedBuffers; for (const FrameBuffer::Plane &plane : buffer->planes()) { const int fd = plane.fd.fd(); if (mappedBuffers.find(fd) == mappedBuffers.end()) { const size_t length = lseek(fd, 0, SEEK_END); mappedBuffers[fd] = MappedBufferInfo{ nullptr, 0, length }; } const size_t length = mappedBuffers[fd].dmabufLength; if (plane.offset > length || plane.offset + plane.length > length) { std::cerr << "plane is out of buffer: buffer length=" << length << ", plane offset=" << plane.offset << ", plane length=" << plane.length << std::endl; return nullptr; } size_t &mapLength = mappedBuffers[fd].mapLength; mapLength = std::max(mapLength, static_cast<size_t>(plane.offset + plane.length)); } for (const FrameBuffer::Plane &plane : buffer->planes()) { const int fd = plane.fd.fd(); auto &info = mappedBuffers[fd]; if (!info.address) { void *address = mmap(nullptr, info.mapLength, mmapFlags, MAP_SHARED, fd, 0); if (address == MAP_FAILED) { int error = -errno; std::cerr << "Failed to mmap plane: " << strerror(-error) << std::endl; return nullptr; } info.address = static_cast<uint8_t *>(address); image->maps_.emplace_back(info.address, info.mapLength); } image->planes_.emplace_back(info.address + plane.offset, plane.length); } return image; } Image::Image() = default; Image::~Image() { for (Span<uint8_t> &map : maps_) munmap(map.data(), map.size()); } unsigned int Image::numPlanes() const { return planes_.size(); } Span<uint8_t> Image::data(unsigned int plane) { assert(plane <= planes_.size()); return planes_[plane]; } Span<const uint8_t> Image::data(unsigned int plane) const { assert(plane <= planes_.size()); return planes_[plane]; }