Files
external_libcamera/src/libcamera/buffer.cpp
Laurent Pinchart 1ba441cae6 libcamera: Include header related to source file first
Include the header file corresponding to the source file in the very
first position. This complies with the Google C++ coding style
guideliens, and helps ensuring that the headers are self-contained.

Three bugs are already caught by this change (missing includes or
forward declarations) in device_enumerator.h, event_dispatcher_poll.h
and pipeline_handler.h. Fix them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
2019-04-19 13:38:14 +03:00

333 lines
7.5 KiB
C++

/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2019, Google Inc.
*
* buffer.cpp - Buffer handling
*/
#include <libcamera/buffer.h>
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include "log.h"
/**
* \file buffer.h
* \brief Buffer handling
*/
namespace libcamera {
LOG_DEFINE_CATEGORY(Buffer)
/**
* \class Plane
* \brief A memory region to store a single plane of a frame
*
* Planar pixel formats use multiple memory regions to store planes
* corresponding to the different colour components of a frame. The Plane class
* tracks the specific details of a memory region used to store a single plane
* for a given frame and provides the means to access the memory, both for the
* application and for DMA. A Buffer then contains one or multiple planes
* depending on its pixel format.
*
* To support DMA access, planes are associated with dmabuf objects represented
* by file handles. Each plane carries a dmabuf file handle and an offset within
* the buffer. Those file handles may refer to the same dmabuf object, depending
* on whether the devices accessing the memory regions composing the image
* support non-contiguous DMA to planes ore require DMA-contiguous memory.
*
* To support CPU access, planes carry the CPU address of their backing memory.
* Similarly to the dmabuf file handles, the CPU addresses for planes composing
* an image may or may not be contiguous.
*/
Plane::Plane()
: fd_(-1), length_(0), mem_(0)
{
}
Plane::~Plane()
{
munmap();
if (fd_ != -1)
close(fd_);
}
/**
* \fn Plane::dmabuf()
* \brief Get the dmabuf file handle backing the buffer
*/
/**
* \brief Set the dmabuf file handle backing the buffer
* \param[in] fd The dmabuf file handle
* \param[in] length The size of the memory region
*
* The \a fd dmabuf file handle is duplicated and stored. The caller may close
* the original file handle.
*
* \return 0 on success or a negative error code otherwise
*/
int Plane::setDmabuf(int fd, unsigned int length)
{
if (fd < 0) {
LOG(Buffer, Error) << "Invalid dmabuf fd provided";
return -EINVAL;
}
if (fd_ != -1) {
close(fd_);
fd_ = -1;
}
fd_ = dup(fd);
if (fd_ == -1) {
int ret = -errno;
LOG(Buffer, Error)
<< "Failed to duplicate dmabuf: " << strerror(-ret);
return ret;
}
length_ = length;
return 0;
}
/**
* \brief Map the plane memory data to a CPU accessible address
*
* The file descriptor to map the memory from must be set by a call to
* setDmaBuf() before calling this function.
*
* \sa setDmaBuf()
*
* \return 0 on success or a negative error code otherwise
*/
int Plane::mmap()
{
void *map;
if (mem_)
return 0;
map = ::mmap(NULL, length_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0);
if (map == MAP_FAILED) {
int ret = -errno;
LOG(Buffer, Error)
<< "Failed to mmap plane: " << strerror(-ret);
return ret;
}
mem_ = map;
return 0;
}
/**
* \brief Unmap any existing CPU accessible mapping
*
* Unmap the memory mapped by an earlier call to mmap().
*
* \return 0 on success or a negative error code otherwise
*/
int Plane::munmap()
{
int ret = 0;
if (mem_)
ret = ::munmap(mem_, length_);
if (ret) {
ret = -errno;
LOG(Buffer, Warning)
<< "Failed to unmap plane: " << strerror(-ret);
} else {
mem_ = 0;
}
return ret;
}
/**
* \fn Plane::mem()
* \brief Retrieve the CPU accessible memory address of the Plane
* \return The CPU accessible memory address on success or nullptr otherwise.
*/
void *Plane::mem()
{
if (!mem_)
mmap();
return mem_;
}
/**
* \fn Plane::length()
* \brief Retrieve the length of the memory region
* \return The length of the memory region
*/
/**
* \class Buffer
* \brief A memory buffer to store an image
*
* The Buffer class represents the memory buffers used to store a
* full frame image, which may contain multiple separate memory Plane
* objects if the image format is multi-planar.
*/
/**
* \enum Buffer::Status
* Buffer completion status
* \var Buffer::BufferSuccess
* The buffer has completed with success and contains valid data. All its other
* metadata (such as bytesused(), timestamp() or sequence() number) are valid.
* \var Buffer::BufferError
* The buffer has completed with an error and doesn't contain valid data. Its
* other metadata are valid.
* \var Buffer::BufferCancelled
* The buffer has been cancelled due to capture stop. Its other metadata are
* invalid and shall not be used.
*/
Buffer::Buffer()
: index_(-1), request_(nullptr)
{
}
/**
* \fn Buffer::index()
* \brief Retrieve the Buffer index
* \return The buffer index
*/
/**
* \fn Buffer::planes()
* \brief Retrieve the planes within the buffer
* \return A reference to a vector holding all Planes within the buffer
*/
/**
* \fn Buffer::bytesused()
* \brief Retrieve the number of bytes occupied by the data in the buffer
* \return Number of bytes occupied in the buffer
*/
/**
* \fn Buffer::timestamp()
* \brief Retrieve the time when the buffer was processed
*
* The timestamp is expressed as a number number of nanoseconds since the epoch.
*
* \return Timestamp when the buffer was processed
*/
/**
* \fn Buffer::sequence()
* \brief Retrieve the buffer sequence number
*
* The sequence number is a monotonically increasing number assigned to the
* buffer processed by the stream. Gaps in the sequence numbers indicate
* dropped frames.
*
* \return Sequence number of the buffer
*/
/**
* \fn Buffer::status()
* \brief Retrieve the buffer status
*
* The buffer status reports whether the buffer has completed successfully
* (BufferSuccess) or if an error occurred (BufferError).
*
* \return The buffer status
*/
/**
* \fn Buffer::request()
* \brief Retrieve the request this buffer belongs to
*
* The intended callers of this method are buffer completion handlers that
* need to associate a buffer to the request it belongs to.
*
* A Buffer is associated to a request by Request::prepare() and the
* association is valid until the buffer completes. The returned request
* pointer is valid only during that interval.
*
* \return The Request the Buffer belongs to, or nullptr if the buffer is
* either completed or not associated with a request
* \sa Buffer::setRequest()
*/
/**
* \brief Mark a buffer as cancel by setting its status to BufferCancelled
*/
void Buffer::cancel()
{
bytesused_ = 0;
timestamp_ = 0;
sequence_ = 0;
status_ = BufferCancelled;
}
/**
* \fn Buffer::setRequest()
* \brief Set the request this buffer belongs to
*
* The intended callers are Request::prepare() and Request::completeBuffer().
*/
/**
* \class BufferPool
* \brief A pool of buffers
*
* The BufferPool class groups together a collection of Buffers to store frames.
* The buffers must be exported by a device before they can be imported into
* another device for further use.
*/
BufferPool::~BufferPool()
{
destroyBuffers();
}
/**
* \brief Create buffers in the Pool
* \param[in] count The number of buffers to create
*/
void BufferPool::createBuffers(unsigned int count)
{
unsigned int index = 0;
buffers_.resize(count);
for (Buffer &buffer : buffers_)
buffer.index_ = index++;
}
/**
* \brief Release all buffers from pool
*/
void BufferPool::destroyBuffers()
{
buffers_.resize(0);
}
/**
* \fn BufferPool::count()
* \brief Retrieve the number of buffers contained within the pool
* \return The number of buffers contained in the pool
*/
/**
* \fn BufferPool::buffers()
* \brief Retrieve all the buffers in the pool
* \return A vector containing all the buffers in the pool.
*/
} /* namespace libcamera */