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:
Hirokazu Honda 2021-08-26 20:25:32 +09:00 committed by Laurent Pinchart
parent 86a47fdcd9
commit 8708904fad
4 changed files with 68 additions and 13 deletions

View file

@ -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:

View file

@ -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,

View file

@ -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);
} }
} }

View file

@ -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;