[libcamera-devel] [PATCH] libcamera: framebuffer: Return plane begin address by MappedBuffer::maps()

Laurent Pinchart laurent.pinchart at ideasonboard.com
Mon Aug 9 01:50:17 CEST 2021


Hello,

On Fri, Aug 06, 2021 at 02:18:10PM +0100, Kieran Bingham wrote:
> On 05/08/2021 18:49, Hirokazu Honda wrote:
> > 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.
> 
> If we can handle the logic in MappedBuffer to get the correct addresses
> that would certainly be beneficial indeed, so this sounds like good
> development.
> 
> > Signed-off-by: Hirokazu Honda <hiroh at chromium.org>
> > ---
> >  include/libcamera/internal/framebuffer.h |  1 +
> >  src/libcamera/framebuffer.cpp            | 41 +++++++++++++++++-------
> >  2 files changed, 31 insertions(+), 11 deletions(-)
> > 
> > diff --git a/include/libcamera/internal/framebuffer.h b/include/libcamera/internal/framebuffer.h
> > index 8c187adf..2eb3b7c9 100644
> > --- a/include/libcamera/internal/framebuffer.h
> > +++ b/include/libcamera/internal/framebuffer.h
> > @@ -36,6 +36,7 @@ protected:
> >  
> >  	int error_;
> >  	std::vector<Plane> maps_;
> > +	std::vector<Plane> chunks_;
> >  
> >  private:
> >  	LIBCAMERA_DISABLE_COPY(MappedBuffer)
> > diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp
> > index a59e93fb..8231c1df 100644
> > --- a/src/libcamera/framebuffer.cpp
> > +++ b/src/libcamera/framebuffer.cpp
> > @@ -310,6 +310,7 @@ MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other)
> >  {
> >  	error_ = other.error_;
> >  	maps_ = std::move(other.maps_);
> > +	chunks_ = std::move(other.chunks_);
> >  	other.error_ = -ENOENT;
> >  
> >  	return *this;
> > @@ -317,8 +318,8 @@ MappedBuffer &MappedBuffer::operator=(MappedBuffer &&other)
> >  
> >  MappedBuffer::~MappedBuffer()
> >  {
> > -	for (Plane &map : maps_)
> > -		munmap(map.data(), map.size());
> > +	for (Plane &chunk : chunks_)
> > +		munmap(chunk.data(), chunk.size());

The names are a bit confusing, I would expect maps_ to contained the
mapped memory. How about doing that, and renaming chunks_ to planes_ ?

> >  }
> >  
> >  /**
> > @@ -381,18 +382,36 @@ MappedBuffer::~MappedBuffer()
> >   */
> >  MappedFrameBuffer::MappedFrameBuffer(const FrameBuffer *buffer, int flags)
> >  {
> > +	if (buffer->planes().empty())
> > +		return;
> 
> Can we have a buffer with zero planes? Is this something that should
> generate an Error or Warning message?
> 
> (Or if it really implies there's a bug, a Fatal?)

It's not supposed to happen, so I think an ASSERT() would be enough.

> >  	maps_.reserve(buffer->planes().size());
> >  
> > +	/*
> > +	 * Below assumes planes are in the same buffer and planes are
> > +	 * consecutive.
> > +	 * \todo remove this assumption.
> 
> To do that, will we need to store the PixelFormat information as part of
> the FrameBuffer? Or at least some additional data there so that we know
> it's layout?
>
> And - now I've seen Laurent posted a patch to expose a Format for that
> purpose...

I'd really like to avoid coupling FrameBuffer and FrameFormat. What we
need if an offset field in FrameBuffer::Plane. With that,
MappedFrameBuffer can check if the fds in different planes are
identical, and if so, map the fd once only and use the offsets to
compute addresses. I think that would be enough.

Until we get that, could we verify that the assertion holds with an
ASSERT() here ? An ASSERT(buffer->planes().size() == 1) should suffice.

> > +	 */
> > +	const int fd = buffer->planes()[0].fd.fd();
> > +	const off_t length = lseek(fd, 0, SEEK_END);
> > +	if (length < 0) {
> > +		error_ = -errno;
> > +		LOG(Buffer, Error) << "Failed to lseek buffer";
> > +		return;
> > +	}
> > +
> > +	void *address = mmap(nullptr, length, flags, MAP_SHARED, fd, 0);
> > +	if (address == MAP_FAILED) {
> > +		error_ = -errno;
> > +		LOG(Buffer, Error) << "Failed to mmap plane";
> > +		return;
> > +	}
> > +	chunks_ = { MappedBuffer::Plane(static_cast<uint8_t *>(address),
> > +					static_cast<size_t>(length)) };
> > +	size_t offset = 0;
> >  	for (const FrameBuffer::Plane &plane : buffer->planes()) {
> > -		void *address = mmap(nullptr, plane.length, flags,
> > -				     MAP_SHARED, plane.fd.fd(), 0);
> > -		if (address == MAP_FAILED) {
> > -			error_ = -errno;
> > -			LOG(Buffer, Error) << "Failed to mmap plane";
> > -			break;
> > -		}
> > -
> > -		maps_.emplace_back(static_cast<uint8_t *>(address), plane.length);
> > +		maps_.emplace_back(static_cast<uint8_t *>(address) + offset,
> > +				   plane.length);
> > +		offset += plane.length;
> >  	}
> >  }
> >  

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list