mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-20 10:55:07 +03:00
libcamera: mapped_framebuffer: Return plane begin address by MappedBuffer::maps()
MappedBuffer::maps() returns std::vector<MappedBuffer::Plane>. Plane has the address, but the address points the beginning of the buffer containing the plane. This makes the Plane point the beginning of the plane. So MappedBuffer::maps()[i].data() returns the address of i-th plane. Signed-off-by: Hirokazu Honda <hiroh@chromium.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
86a47fdcd9
commit
8708904fad
4 changed files with 68 additions and 13 deletions
|
@ -30,12 +30,14 @@ public:
|
||||||
|
|
||||||
bool isValid() const { return error_ == 0; }
|
bool isValid() const { return error_ == 0; }
|
||||||
int error() const { return error_; }
|
int error() const { return error_; }
|
||||||
const std::vector<Plane> &maps() const { return maps_; }
|
/* \todo rename to planes(). */
|
||||||
|
const std::vector<Plane> &maps() const { return planes_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MappedBuffer();
|
MappedBuffer();
|
||||||
|
|
||||||
int error_;
|
int error_;
|
||||||
|
std::vector<Plane> planes_;
|
||||||
std::vector<Plane> maps_;
|
std::vector<Plane> maps_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -54,8 +54,6 @@ private:
|
||||||
off_t bufferLength_;
|
off_t bufferLength_;
|
||||||
bool mapped_;
|
bool mapped_;
|
||||||
std::vector<PlaneInfo> planeInfo_;
|
std::vector<PlaneInfo> planeInfo_;
|
||||||
/* \todo Remove planes_ when it will be added to MappedBuffer */
|
|
||||||
std::vector<Span<uint8_t>> planes_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CameraBuffer::Private::Private([[maybe_unused]] CameraBuffer *cameraBuffer,
|
CameraBuffer::Private::Private([[maybe_unused]] CameraBuffer *cameraBuffer,
|
||||||
|
|
|
@ -7,8 +7,11 @@
|
||||||
|
|
||||||
#include "libcamera/internal/mapped_framebuffer.h"
|
#include "libcamera/internal/mapped_framebuffer.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <map>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <libcamera/base/log.h>
|
#include <libcamera/base/log.h>
|
||||||
|
|
||||||
|
@ -79,6 +82,7 @@ MappedBuffer::MappedBuffer(MappedBuffer &&other)
|
||||||
MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other)
|
MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other)
|
||||||
{
|
{
|
||||||
error_ = other.error_;
|
error_ = other.error_;
|
||||||
|
planes_ = std::move(other.planes_);
|
||||||
maps_ = std::move(other.maps_);
|
maps_ = std::move(other.maps_);
|
||||||
other.error_ = -ENOENT;
|
other.error_ = -ENOENT;
|
||||||
|
|
||||||
|
@ -127,10 +131,18 @@ MappedBuffer::~MappedBuffer()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \var MappedBuffer::maps_
|
* \var MappedBuffer::planes_
|
||||||
* \brief Stores the internal mapped planes
|
* \brief Stores the internal mapped planes
|
||||||
*
|
*
|
||||||
* MappedBuffer derived classes shall store the mappings they create in this
|
* MappedBuffer derived classes shall store the mappings they create in this
|
||||||
|
* vector which points the beginning of mapped plane addresses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \var MappedBuffer::maps_
|
||||||
|
* \brief Stores the mapped buffer
|
||||||
|
*
|
||||||
|
* MappedBuffer derived classes shall store the mappings they create in this
|
||||||
* vector which is parsed during destruct to unmap any memory mappings which
|
* vector which is parsed during destruct to unmap any memory mappings which
|
||||||
* completed successfully.
|
* completed successfully.
|
||||||
*/
|
*/
|
||||||
|
@ -167,7 +179,8 @@ MappedBuffer::~MappedBuffer()
|
||||||
*/
|
*/
|
||||||
MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, MapFlags flags)
|
MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, MapFlags flags)
|
||||||
{
|
{
|
||||||
maps_.reserve(buffer->planes().size());
|
ASSERT(!buffer->planes().empty());
|
||||||
|
planes_.reserve(buffer->planes().size());
|
||||||
|
|
||||||
int mmapFlags = 0;
|
int mmapFlags = 0;
|
||||||
|
|
||||||
|
@ -177,17 +190,53 @@ MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, MapFlags flags)
|
||||||
if (flags & MapFlag::Write)
|
if (flags & MapFlag::Write)
|
||||||
mmapFlags |= PROT_WRITE;
|
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()) {
|
for (const FrameBuffer::Plane &plane : buffer->planes()) {
|
||||||
void *address = mmap(nullptr, plane.length, mmapFlags,
|
const int fd = plane.fd.fd();
|
||||||
MAP_SHARED, plane.fd.fd(), 0);
|
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) {
|
||||||
|
LOG(Buffer, Fatal) << "plane is out of buffer: "
|
||||||
|
<< "buffer length=" << length
|
||||||
|
<< ", plane offset=" << plane.offset
|
||||||
|
<< ", plane length=" << plane.length;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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) {
|
if (address == MAP_FAILED) {
|
||||||
error_ = -errno;
|
error_ = -errno;
|
||||||
LOG(Buffer, Error) << "Failed to mmap plane: "
|
LOG(Buffer, Error) << "Failed to mmap plane: "
|
||||||
<< strerror(-error_);
|
<< strerror(-error_);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
maps_.emplace_back(static_cast<uint8_t *>(address), plane.length);
|
info.address = static_cast<uint8_t *>(address);
|
||||||
|
maps_.emplace_back(info.address, info.mapLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
planes_.emplace_back(info.address + plane.offset, plane.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1283,6 +1283,12 @@ std::unique_ptr<FrameBuffer> V4L2VideoDevice::createBuffer(unsigned int index)
|
||||||
|
|
||||||
FrameBuffer::Plane plane;
|
FrameBuffer::Plane plane;
|
||||||
plane.fd = std::move(fd);
|
plane.fd = std::move(fd);
|
||||||
|
/*
|
||||||
|
* V4L2 API doesn't provide dmabuf offset information of plane.
|
||||||
|
* Set 0 as a placeholder offset.
|
||||||
|
* \todo Set the right offset once V4L2 API provides a way.
|
||||||
|
*/
|
||||||
|
plane.offset = 0;
|
||||||
plane.length = multiPlanar ?
|
plane.length = multiPlanar ?
|
||||||
buf.m.planes[nplane].length : buf.length;
|
buf.m.planes[nplane].length : buf.length;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue