[libcamera-devel] [RFC 6/8] libcamera: stream: Add operation to map buffers

Kieran Bingham kieran.bingham at ideasonboard.com
Wed Jul 3 12:47:05 CEST 2019


Hi Jacopo,

On 30/06/2019 19:10, Jacopo Mondi wrote:
> Add and operation to map external buffers provided by applications in
> a Request to the Stream's internal buffers used by the pipeline handlers
> to interact with the video device.
> 
> For streams using internal memory allocation, the two buffers are the
> same as applications effectively use Buffers from the Stream's pool
> where the video device memory has been exported to.
> 
> Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> ---
>  include/libcamera/buffer.h |  1 +
>  include/libcamera/stream.h |  5 +++
>  src/libcamera/stream.cpp   | 66 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 72 insertions(+)
> 
> diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h
> index 260a62e9e77e..d5d3dc90a096 100644
> --- a/include/libcamera/buffer.h
> +++ b/include/libcamera/buffer.h
> @@ -59,6 +59,7 @@ private:
>  	friend class BufferPool;
>  	friend class PipelineHandler;
>  	friend class Request;
> +	friend class Stream;
>  	friend class V4L2VideoDevice;
>  
>  	void cancel();
> diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h
> index 796f1aff2602..4c034c113ddb 100644
> --- a/include/libcamera/stream.h
> +++ b/include/libcamera/stream.h
> @@ -85,6 +85,8 @@ public:
>  	const StreamConfiguration &configuration() const { return configuration_; }
>  	MemoryType memoryType() const { return memoryType_; }
>  
> +	Buffer *mapBuffer(Buffer *requestBuffer);
> +
>  protected:
>  	friend class Camera;
>  
> @@ -94,6 +96,9 @@ protected:
>  	BufferPool bufferPool_;
>  	StreamConfiguration configuration_;
>  	MemoryType memoryType_;
> +
> +	std::vector<Buffer *> mappableBuffers_;
> +	std::map<unsigned int, Buffer *> bufferMaps_;
>  };
>  
>  } /* namespace libcamera */
> diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp
> index b6292427d3a2..f36336857ad6 100644
> --- a/src/libcamera/stream.cpp
> +++ b/src/libcamera/stream.cpp
> @@ -13,6 +13,8 @@
>  #include <iomanip>
>  #include <sstream>
>  
> +#include <libcamera/request.h>
> +
>  #include "log.h"
>  
>  /**
> @@ -445,6 +447,26 @@ void Stream::createBuffers(unsigned int count)
>  		return;
>  
>  	bufferPool_.createBuffers(count);
> +
> +	/* Streams with internal memory usage do not need buffer mapping. */
> +	if (memoryType_ == InternalMemory)
> +		return;
> +
> +	/*
> +	 * Prepare for buffer mapping by queuing all buffers from the internal
> +	 * pool. Each external buffer presented by application will be mapped
> +	 * on an internal one.
> +	 */
> +	mappableBuffers_.clear();
> +	for (Buffer &buffer : bufferPool_.buffers()) {
> +		/* Reserve all planes to support mapping multiplanar buffers. */
> +		buffer.planes().clear();
> +		/* \todo: I would use VIDEO_MAX_PLANES but that's V4L2 stuff.. */
> +		for (unsigned int i = 0; i < 3; ++i)
> +			buffer.planes().emplace_back();

Just a small one:

Could buffer.planes().resize(3) be better here?


> +
> +		mappableBuffers_.push_back(&buffer);
> +	}
>  }
>  
>  /**
> @@ -457,6 +479,50 @@ void Stream::destroyBuffers()
>  	createBuffers(0);
>  }
>  
> +/**
> + * \brief Map the buffer an application has associated with a Request to an
> + * internl one
> + *
> + * \todo Rewrite documentation
> + * If the Stream uses external memory, we need to map the externally
> + * provided buffer to an internal one, trying to keep a best effort
> + * association based on the Buffer's last usage time.
> + * External and internal buffers are associated by using the dmabuf
> + * fds as key.
> + */
> +Buffer *Stream::mapBuffer(Buffer *requestBuffer)
> +{
> +	/*
> +	 * \todo Multiplane APIs have one fd per plane, the key should be
> +	 * hashed using all the planes fds.
> +	 */
> +	unsigned int key = requestBuffer->planes()[0].dmabuf();
> +
> +	/* If the buffer has already been mapped, just return it. */
> +	auto mapped = bufferMaps_.find(key);
> +	if (mapped != bufferMaps_.end())
> +		return mapped->second;
> +
> +	/*
> +	 * Remove the last recently used buffer from the circular list and
> +	 * use it for mapping.
> +	 */
> +	auto mappable = mappableBuffers_.begin();
> +	Buffer *buffer = *mappable;
> +	mappableBuffers_.erase(mappable);
> +	mappableBuffers_.push_back(buffer);
> +
> +	/* \todo: Support multiplanar external buffers. */
> +	buffer->planes()[0].setDmabuf(key, 0);
> +
> +	/* Pipeline handlers use request_ at buffer completion time. */
> +	buffer->request_ = requestBuffer->request();
> +
> +	bufferMaps_[key] = buffer;
> +
> +	return buffer;
> +}
> +
>  /**
>   * \var Stream::bufferPool_
>   * \brief The pool of buffers associated with the stream
> 

-- 
Regards
--
Kieran


More information about the libcamera-devel mailing list