summaryrefslogtreecommitdiff
path: root/test/camera
AgeCommit message (Collapse)Author
2019-04-09libcamera: Switch to CameraConfigurationNiklas Söderlund
Implement the camera configuration thru out the library, tests, cam and qcam tools. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2019-04-05libcamera: camera: Add support for stream usagesNiklas Söderlund
Instead of requesting the default configuration for a set of streams where the application has to figure out which streams provided by the camera is best suited for its intended usage, have the library figure this out by using stream usages. The application asks the library for a list of streams and a suggested default configuration for them by supplying a list of stream usages. Once the list is retrieved the application can fine-tune the returned configuration and then try to apply it to the camera. Currently no pipeline handler is prepared to handle stream usages but nor did it make use of the list of Stream IDs which was the previous interface. The main reason for this is that all cameras currently only provide one stream each. This will still be the case but the API will be prepared to expand both pipeline handlers and applications to support streams usages. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2019-04-04test: camera: Remove test for bad Stream IDsNiklas Söderlund
In preparation of reworking how a default configuration is retrieved from a camera remove test that stream IDs must be valid as the data type passed to Camera::streamConfiguration() will change. This change is in preparation for an invasive change. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
2019-04-04test: camera: Remove streams argument from configurationValid()Niklas Söderlund
In preparation of reworking how a default configuration is retrieved from a camera remove the streams and validation using the stream when judging if a camera configuration is valid. This is needed as once stream usage hints are added applications will no longer fetch default configuration based on Stream IDs so using them to verify the returned format is not useful. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
2019-03-14test: camera: Add state machine testNiklas Söderlund
Add a test of the different access level enforced by the state machine inside the camera. The state machine aims to limit operations on the camera to the cameras state. The test exercises all states of the camera and verifies that only the intended operations are possible at each stage. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2019-03-14test: camera: Add capture testNiklas Söderlund
Correctly configure the camera using the default configuration and run a capture session for 100 milliseconds, which is plenty of time, in tests over 600 requests completed using the vimc pipeline. The test passes if at least the number of buffers used in the capture times two number of requests completes to prove we cycle through all buffers. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2019-03-14test: camera: Add setting of configuration testNiklas Söderlund
Try to set the default configuration, a modified valid configuration and an invalid configuration. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
2019-03-14test: camera: Add read default configuration testNiklas Söderlund
Add a test to verify reading the default configuration from a camera works. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
3'>153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 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 344
/* 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/base/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() function.
 *
 *
 * 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() function.
 */

/**
 * \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 function 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 function 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
 *