summaryrefslogtreecommitdiff
path: root/src/ipa/libipa/camera_sensor_helper.cpp
AgeCommit message (Expand)Author
2024-08-12ipa: libipa: Add missing CameraSensorHelper fn label in docsMilan Zamazal
2024-08-05ipa: libipa: camera_sensor_helper: Reference blackLevel() in documentationLaurent Pinchart
2024-07-25libcamera: libipa: camera_sensor: Add onsemi AR0144 sensor propertiesLaurent Pinchart
2024-07-24libipa: camera_sensor_helper: Add OV5675 black levelDaniel Semkowicz
2024-07-03ipa: rkisp1: Move ov4689 and ov5640 black levels into sensor helpersStefan Klug
2024-07-03ipa: libipa: Add black levels to camera sensor helperStefan Klug
2024-06-13libcamera: libipa: camera_sensor: Define AR0521 helper functions inlineLaurent Pinchart
2024-05-08libcamera: Drop file name from header comment blocksLaurent Pinchart
2024-05-03libcamera: libipa: camera_sensor: Add Sony IMX415 sensor propertiesAlexander Stein
2024-05-03libcamera: libipa: camera_sensor: Add Sony IMX335 sensor propertiesKieran Bingham
2024-05-03libcamera: libipa: camera_sensor: Add Sony IMX283 sensor propertiesKieran Bingham
2024-01-09libipa: camera_sensor_helper: Add OV64A40 helperJacopo Mondi
2023-06-06libipa: camera_sensor_helper: Restore alphabetical orderBenjamin Bara
2023-05-19libipa: camera_sensor_helper: Add IMX327 helperBenjamin Bara
2023-03-21ipa: libipa: Add OV2685 Camera Sensor HelperKieran Bingham
2023-03-21ipa: libipa: Add OV5647 Camera Sensor HelperKieran Bingham
2023-01-26libcamera: Add support for OmniVision OV8858Nicholas Roth
2023-01-25ipa: camera_sensor_helper: Add OV4689 supportMikhail Rudenko
2022-12-22ipa: camera_sensor_helper: Add AR0521 supportJacopo Mondi
2022-10-07ipa: camera_sensor_helper: Implement factories through class templatesLaurent Pinchart
2022-10-07ipa: camera_sensor_helper: Return unique_ptr from createInstanceLaurent Pinchart
2022-10-07ipa: camera_sensor_helper: Make factory createInstance() function constLaurent Pinchart
2022-05-27libipa: camera_sensor_helper: Add Sony IMX477 helperNaushir Patuck
2022-05-26ipa: camera_sensor_helper: Fix equation in exponential gain documentationLaurent Pinchart
2022-05-13libipa: camera_sensor_helper: Add OV5675 helperQuentin Schulz
2022-04-01libipa: camera_sensor_helper: Add OV5640 helperPaul Elder
2022-04-01libipa: camera_sensor_helper: Add IMX296 helperLaurent Pinchart
2022-04-01libipa: camera_sensor_helper: Add IMX290 helperLaurent Pinchart
2022-04-01libipa: camera_sensor_helper: Implement exponential gain modelLaurent Pinchart
2022-04-01libipa: camera_sensor_helper: Reorganize gain constantsLaurent Pinchart
2022-03-17libipa: Add CameraSensorHelper for OV2740Daniel Scally
2021-11-29libipa: Correct IMX219 in CameraSensorHelperJean-Michel Hautbois
2021-08-09libcamera: Rename 'method' to 'function'Laurent Pinchart
2021-07-25libipa: Add CameraSensorHelper for ov8865Daniel Scally
2021-07-23libipa: Add CameraSensorHelper for IMX258Umang Jain
2021-07-15libipa: Correct OV5670 CameraSensorHelper gain valuesJean-Michel Hautbois
2021-07-15libipa: Add CameraSensorHelper for OV13858Jean-Michel Hautbois
2021-07-09ipa: libipa: Fixups in CameraSensorHelpersJean-Michel Hautbois
2021-06-28ipa: Create a camera sensor helper classJean-Michel Hautbois
n286' href='#n286'>286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * byte_stream_buffer.cpp - Byte stream buffer
 */

#include "libcamera/internal/byte_stream_buffer.h"

#include <stdint.h>
#include <string.h>

#include "libcamera/internal/log.h"

/**
 * \file byte_stream_buffer.h
 * \brief Managed memory container for serialized data
 */

namespace libcamera {

LOG_DEFINE_CATEGORY(Serialization)

/**
 * \class ByteStreamBuffer
 * \brief Wrap a memory buffer and provide sequential data read and write
 *
 * The ByteStreamBuffer class wraps a memory buffer and exposes sequential read
 * and write operation with integrated boundary checks. Access beyond the end
 * of the buffer are blocked and logged, allowing error checks to take place at
 * the of of access operations instead of at each access. This simplifies
 * serialization and deserialization of data.
 *
 * A byte stream buffer is created with a base memory pointer and a size. If the
 * memory pointer is const, the buffer operates in read-only mode, and write
 * operations are denied. Otherwise the buffer operates in write-only mode, and
 * read operations are denied.
 *
 * Once a buffer is created, data is read or written with read() and write()
 * respectively. Access is strictly sequential, the buffer keeps track of the
 * current access location and advances it automatically. Reading or writing
 * the same location multiple times is thus not possible. Bytes may also be
 * skipped with the skip() method.
 *
 * The ByteStreamBuffer also supports carving out pieces of memory into other
 * ByteStreamBuffer instances. Like a read or write operation, a carveOut()
 * advances the internal access location, but allows the carved out memory to
 * be accessed at a later time.
 *
 * All accesses beyond the end of the buffer (read, write, skip or carve out)
 * are blocked. The first of such accesses causes a message to be logged, and
 * the buffer being marked as having overflown. If the buffer has been carved
 * out from a parent buffer, the parent buffer is also marked as having
 * overflown. Any later access on an overflown buffer is blocked. The buffer
 * overflow status can be checked with the overflow() method.
 */

/**
 * \brief Construct a read ByteStreamBuffer from the memory area \a base
 * of \a size
 * \param[in] base The address of the memory area to wrap
 * \param[in] size The size of the memory area to wrap
 */
ByteStreamBuffer::ByteStreamBuffer(const uint8_t *base, size_t size)
	: parent_(nullptr), base_(base), size_(size), overflow_(false),
	  read_(base), write_(nullptr)
{
}

/**
 * \brief Construct a write ByteStreamBuffer from the memory area \a base
 * of \a size
 * \param[in] base The address of the memory area to wrap
 * \param[in] size The size of the memory area to wrap
 */
ByteStreamBuffer::ByteStreamBuffer(uint8_t *base, size_t size)
	: parent_(nullptr), base_(base), size_(size), overflow_(false),
	  read_(nullptr), write_(base)
{
}

/**
 * \brief Construct a ByteStreamBuffer from the contents of \a other using move
 * semantics
 * \param[in] other The other buffer
 *
 * After the move construction the \a other buffer is invalidated. Any attempt
 * to access its contents will be considered as an overflow.
 */
ByteStreamBuffer::ByteStreamBuffer(ByteStreamBuffer &&other)
{
	*this = std::move(other);
}

/**
 * \brief Replace the contents of the buffer with those of \a other using move
 * semantics
 * \param[in] other The other buffer
 *
 * After the assignment the \a other buffer is invalidated. Any attempt to
 * access its contents will be considered as an overflow.
 */
ByteStreamBuffer &ByteStreamBuffer::operator=(ByteStreamBuffer &&other)
{
	parent_ = other.parent_;
	base_ = other.base_;
	size_ = other.size_;
	overflow_ = other.overflow_;
	read_ = other.read_;
	write_ = other.write_;

	other.parent_ = nullptr;
	other.base_ = nullptr;
	other.size_ = 0;
	other.overflow_ = false;
	other.read_ = nullptr;
	other.write_ = nullptr;

	return *this;
}

/**
 * \fn ByteStreamBuffer::base()
 * \brief Retrieve a pointer to the start location of the managed memory buffer
 * \return A pointer to the managed memory buffer
 */

/**
 * \fn ByteStreamBuffer::offset()
 * \brief Retrieve the offset of the current access location from the base
 * \return The offset in bytes
 */

/**
 * \fn ByteStreamBuffer::size()
 * \brief Retrieve the size of the managed memory buffer
 * \return The size of managed memory buffer
 */

/**
 * \fn ByteStreamBuffer::overflow()
 * \brief Check if the buffer has overflown
 * \return True if the buffer has overflow, false otherwise
 */

void ByteStreamBuffer::setOverflow()
{
	if (parent_)
		parent_->setOverflow();

	overflow_ = true;
}

/**
 * \brief Carve out an area of \a size bytes into a new ByteStreamBuffer
 * \param[in] size The size of the newly created memory buffer
 *
 * This method carves out an area of \a size bytes from the buffer into a new
 * ByteStreamBuffer, and returns the new buffer. It operates identically to a
 * read or write access from the point of view of the current buffer, but allows
 * the new buffer to be read or written at a later time after other read or
 * write accesses on the current buffer.
 *
 * \return A newly created ByteStreamBuffer of \a size
 */
ByteStreamBuffer ByteStreamBuffer::carveOut(size_t size)
{
	if (!size_ || overflow_)
		return ByteStreamBuffer(static_cast<const uint8_t *>(nullptr), 0);

	const uint8_t *curr = read_ ? read_ : write_;
	if (curr + size > base_ + size_) {
		LOG(Serialization, Error)
			<< "Unable to reserve " << size << " bytes";
		setOverflow();

		return ByteStreamBuffer(static_cast<const uint8_t *>(nullptr), 0);
	}

	if (read_) {
		ByteStreamBuffer b(read_, size);
		b.parent_ = this;
		read_ += size;
		return b;
	} else {
		ByteStreamBuffer b(write_, size);
		b.parent_ = this;
		write_ += size;
		return b;
	}
}

/**
 * \brief Skip \a size bytes from the buffer
 * \param[in] size The number of bytes to skip
 *
 * This method skips the next \a size bytes from the buffer.
 *
 * \return 0 on success, a negative error code otherwise
 * \retval -ENOSPC no more space is available in the managed memory buffer
 */
int ByteStreamBuffer::skip(size_t size)
{
	if (overflow_)
		return -ENOSPC;

	const uint8_t *curr = read_ ? read_ : write_;
	if (curr + size > base_ + size_) {
		LOG(Serialization, Error)
			<< "Unable to skip " << size << " bytes";
		setOverflow();

		return -ENOSPC;
	}

	if (read_) {
		read_ += size;
	} else {
		memset(write_, 0, size);
		write_ += size;
	}

	return 0;
}

/**
 * \fn template<typename T> int ByteStreamBuffer::read(T *t)
 * \brief Read data from the managed memory buffer into \a t
 * \param[out] t Pointer to the memory containing the read data
 * \return 0 on success, a negative error code otherwise
 * \retval -EACCES attempting to read from a write buffer
 * \retval -ENOSPC no more space is available in the managed memory buffer
 */

/**
 * \fn template<typename T> int ByteStreamBuffer::read(const Span<T> &data)
 * \brief Read data from the managed memory buffer into Span \a data
 * \param[out] data Span representing the destination memory
 * \return 0 on success, a negative error code otherwise
 * \retval -EACCES attempting to read from a write buffer
 * \retval -ENOSPC no more space is available in the managed memory buffer
 */

/**
 * \fn template<typename T> const T *ByteStreamBuffer::read(size_t count)
 * \brief Read data from the managed memory buffer without performing a copy
 * \param[in] count Number of data items to read
 *
 * This function reads \a count elements of type \a T from the buffer. Unlike
 * the other read variants, it doesn't copy the data but returns a pointer to
 * the first element. If data can't be read for any reason (usually due to
 * reading more data than available), the function returns nullptr.
 *
 * \return A pointer to the data on success, or nullptr otherwise
 */

/**
 * \fn template<typename T> int ByteStreamBuffer::write(const T *t)
 * \brief Write \a t to the managed memory buffer
 * \param[in] t The data to write to memory
 * \return 0 on success, a negative error code otherwise
 * \retval -EACCES attempting to write to a read buffer
 * \retval -ENOSPC no more space is available in the managed memory buffer
 */

/**
 * \fn template<typename T> int ByteStreamBuffer::write(const Span<T> &data)
 * \brief Write \a data to the managed memory buffer
 * \param[in] data The data to write to memory
 * \return 0 on success, a negative error code otherwise
 * \retval -EACCES attempting to write to a read buffer
 * \retval -ENOSPC no more space is available in the managed memory buffer
 */

const uint8_t *ByteStreamBuffer::read(size_t size, size_t count)
{
	if (!read_)
		return nullptr;

	if (overflow_)
		return nullptr;

	size_t bytes;
	if (__builtin_mul_overflow(size, count, &bytes)) {
		setOverflow();
		return nullptr;
	}

	if (read_ + bytes > base_ + size_) {
		LOG(Serialization, Error)
			<< "Unable to read " << bytes << " bytes: out of bounds";
		setOverflow();
		return nullptr;
	}

	const uint8_t *data = read_;
	read_ += bytes;
	return data;
}

int ByteStreamBuffer::read(uint8_t *data, size_t size)
{
	if (!read_)
		return -EACCES;

	if (overflow_)
		return -ENOSPC;

	if (read_ + size > base_ + size_) {
		LOG(Serialization, Error)
			<< "Unable to read " << size << " bytes: out of bounds";
		setOverflow();
		return -ENOSPC;
	}

	memcpy(data, read_, size);
	read_ += size;

	return 0;
}

int ByteStreamBuffer::write(const uint8_t *data, size_t size)
{
	if (!write_)
		return -EACCES;

	if (overflow_)
		return -ENOSPC;

	if (write_ + size > base_ + size_) {
		LOG(Serialization, Error)
			<< "Unable to write " << size << " bytes: no space left";
		setOverflow();
		return -ENOSPC;
	}

	memcpy(write_, data, size);
	write_ += size;

	return 0;
}

} /* namespace libcamera */