[{"id":3427,"web_url":"https://patchwork.libcamera.org/comment/3427/","msgid":"<20200112134141.GC25899@pendragon.ideasonboard.com>","date":"2020-01-12T13:41:41","subject":"Re: [libcamera-devel] [PATCH v4 08/32] libcamera: buffer: Add\n\tFrameBuffer interface","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Niklas,\n\nThank you for the patch.\n\nOn Sun, Jan 12, 2020 at 02:01:48AM +0100, Niklas Söderlund wrote:\n> Add a new FrameBuffer class to describe memory used to store frames.\n> This change just adds the new interface, future patches will migrate all\n> parts of libcamera to use this and replace the old Buffer interface.\n> \n> This change needs to specify the const keyword for Plane::length() as to\n> not get Doxygen confused with FrameBuffer::Plane::length added in this\n> change.\n> \n> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> ---\n> * Changes since v3\n> - Delete moved-constructor and move-assignment operator\n> - Update documentation.\n> \n> * Changes since v2\n> - Drop default value for planes argument for FrameBuffer::FrameBuffer(planes, cookie).\n> - Deleted FrameBuffer copy constructor and assignment operator.\n> - Add a Move constructor for FrameBuffer.\n> - Update documentation.\n> \n> Changes since v1:\n> - Rename FrameBuffer::info() to FrameBuffer::metadata()\n> - Fixup commit message\n> - Reorder method order\n> - Rewrite documentation\n> - Add operator==() and operator=!() for FrameBuffer::Plane\n> ---\n>  include/libcamera/buffer.h |  38 ++++++++++++\n>  src/libcamera/buffer.cpp   | 117 ++++++++++++++++++++++++++++++++++++-\n>  2 files changed, 154 insertions(+), 1 deletion(-)\n> \n> diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h\n> index 0b95e41a2dd205b2..e66e9c9cf828160a 100644\n> --- a/include/libcamera/buffer.h\n> +++ b/include/libcamera/buffer.h\n> @@ -11,6 +11,8 @@\n>  #include <stdint.h>\n>  #include <vector>\n>  \n> +#include <libcamera/file_descriptor.h>\n> +\n>  namespace libcamera {\n>  \n>  class Request;\n> @@ -33,6 +35,42 @@ struct FrameMetadata {\n>  \tstd::vector<Plane> planes;\n>  };\n>  \n> +class FrameBuffer final\n> +{\n> +public:\n> +\tstruct Plane {\n> +\t\tFileDescriptor fd;\n> +\t\tunsigned int length;\n> +\t};\n> +\n> +\tFrameBuffer(const std::vector<Plane> &planes, unsigned int cookie = 0);\n> +\n> +\tFrameBuffer(const FrameBuffer &) = delete;\n> +\tFrameBuffer(FrameBuffer &&) = delete;\n> +\n> +\tFrameBuffer &operator=(const FrameBuffer &) = delete;\n> +\tFrameBuffer &operator=(FrameBuffer &&) = delete;\n> +\n> +\tconst std::vector<Plane> &planes() const { return planes_; }\n> +\n> +\tRequest *request() const { return request_; }\n> +\tconst FrameMetadata &metadata() const { return metadata_; };\n> +\n> +\tunsigned int cookie() const { return cookie_; }\n> +\tvoid setCookie(unsigned int cookie) { cookie_ = cookie; }\n> +\n> +private:\n> +\tfriend class Request; /* Needed to update request_. */\n> +\tfriend class V4L2VideoDevice; /* Needed to update metadata_. */\n> +\n> +\tstd::vector<Plane> planes_;\n> +\n> +\tRequest *request_;\n> +\tFrameMetadata metadata_;\n> +\n> +\tunsigned int cookie_;\n> +};\n> +\n>  class Plane final\n>  {\n>  public:\n> diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp\n> index 360eb26cb4ca4906..2178bd2fe17111dc 100644\n> --- a/src/libcamera/buffer.cpp\n> +++ b/src/libcamera/buffer.cpp\n> @@ -240,7 +240,7 @@ void *Plane::mem()\n>  }\n>  \n>  /**\n> - * \\fn Plane::length()\n> + * \\fn Plane::length() const\n>   * \\brief Retrieve the length of the memory region\n>   * \\return The length of the memory region\n>   */\n> @@ -473,4 +473,119 @@ void Buffer::cancel()\n>   * The intended callers are Request::addBuffer() and Request::completeBuffer().\n>   */\n>  \n> +/**\n> + * \\class FrameBuffer\n> + * \\brief Frame buffer data and its associated dynamic metadata\n> + *\n> + * The FrameBuffer class is the primary interface for applications, IPAs and\n> + * pipeline handlers to interact with frame memory. It contains all the static\n> + * and dynamic information to manage the whole life cycle of a frame capture,\n> + * from buffer creation to consumption.\n> + *\n> + * The static information describes the memory planes that make a frame. The\n> + * planes are specified when creating the FrameBuffer and are expressed as a set\n> + * of dmabuf file descriptors and length.\n> + *\n> + * The dynamic information is grouped in a FrameMetadata instance. It is updated\n> + * during the processing of a queued capture request, and is valid from the\n> + * completion of the buffer as signaled by Camera::bufferComplete() until the\n> + * FrameBuffer is either reused in a new request or deleted.\n> + *\n> + * The creator of a FrameBuffer (application, IPA or pipeline handler) may\n> + * associate to it an integer cookie for any private purpose. The cookie may be\n> + * set when creating the FrameBuffer, and updated at any time with setCookie().\n> + * The cookie is transparent to the libcamera core and shall only be set by the\n> + * creator of the FrameBuffer. This mechanism supplements the Request cookie.\n> + */\n> +\n> +/**\n> + * \\struct FrameBuffer::Plane\n> + * \\brief A memory region to store a single plane of a frame\n> + *\n> + * Planar pixel formats use multiple memory regions to store the different\n> + * colour components of a frame. The Plane structure describes such a memory\n> + * region by a dmabuf file descriptor and a length. A FrameBuffer then\n> + * contains one or multiple planes, depending on the pixel format of the\n> + * frames it is meant to store.\n> + *\n> + * To support DMA access, planes are associated with dmabuf objects represented\n> + * by FileDescriptor handles. The Plane class doesn't handle mapping of the\n> + * memory to the CPU, but applications and IPAs may use the dmabuf file\n> + * descriptors to map the plane memory with mmap() and access its contents.\n> + *\n> + * \\todo Once we have a Kernel API which can express offsets within a plane\n> + * this structure shall be extended to contain this information. See commit\n> + * 83148ce8be55e for initial documentation of this feature.\n> + */\n> +\n> +/**\n> + * \\var FrameBuffer::Plane::fd\n> + * \\brief The dmabuf file descriptor\n> + */\n> +\n> +/**\n> + * \\var FrameBuffer::Plane::length\n> + * \\brief The plane length in bytes\n> + */\n> +\n> +/**\n> + * \\brief Construct a FrameBuffer with an array of planes\n> + * \\param[in] planes The frame memory planes\n> + * \\param[in] cookie Cookie\n> + */\n> +FrameBuffer::FrameBuffer(const std::vector<Plane> &planes, unsigned int cookie)\n> +\t: planes_(planes), request_(nullptr), cookie_(cookie)\n> +{\n> +}\n> +\n> +/**\n> + * \\fn FrameBuffer::planes()\n> + * \\brief Retrieve the static plane descriptors\n> + * \\return Array of plane descriptors\n> + */\n> +\n> +/**\n> + * \\fn FrameBuffer::request()\n> + * \\brief Retrieve the request this buffer belongs to\n> + *\n> + * The intended callers of this method are buffer completion handlers that\n> + * need to associate a buffer to the request it belongs to.\n> + *\n> + * A Buffer is associated to a request by Request::addBuffer() and the\n> + * association is valid until the buffer completes. The returned request\n> + * pointer is valid only during that interval.\n> + *\n> + * \\return The Request the Buffer belongs to, or nullptr if the buffer is\n> + * not associated with a request\n> + */\n> +\n> +/**\n> + * \\fn FrameBuffer::metadata()\n> + * \\brief Retrieve the dynamic metadata\n> + * \\return Dynamic metadata for the frame contained in the buffer\n> + */\n> +\n> +/**\n> + * \\fn FrameBuffer::cookie()\n> + * \\brief Retrieve the cookie\n> + *\n> + * The cookie belongs to the creator of the FrameBuffer, which controls its\n> + * lifetime and value.\n> + *\n> + * \\sa setCookie()\n> + *\n> + * \\return The cookie\n> + */\n> +\n> +/**\n> + * \\fn FrameBuffer::setCookie()\n> + * \\brief Set the cookie\n> + * \\param[in] cookie Cookie to set\n> + *\n> + * The cookie belongs to the creator of the FrameBuffer. Its value may be\n> + * modified at any time with this method. Applications and IPAs shall not modify\n> + * the cookie value of buffers they haven't created themselves. The libcamera\n> + * core never modifies the buffer cookie.\n> + */\n> +\n>  } /* namespace libcamera */","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E3CC56045E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun, 12 Jan 2020 14:42:00 +0100 (CET)","from pendragon.ideasonboard.com (85-76-9-232-nat.elisa-mobile.fi\n\t[85.76.9.232])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 09ECF30F;\n\tSun, 12 Jan 2020 14:41:59 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1578836520;\n\tbh=IddoD6StnL6aFG4rMdq28wXC2cA4zAbkBUxcWpqkIzE=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=Y6BfjYGHlfu1+5UienQHq1RlRjT62AfUG+aeTSsbcTdCJaZNavWDgc6j1IoPYTtYl\n\tWwz/1DfA/CZoqYLT+sc6nkBEca+xVOGLMut5IukcpNZWra6EF7Lp4w4LN683kdF0Y0\n\t0r6j29/EgDxfehM8yGL7FHJ7e1U9U2syGwHlifzI=","Date":"Sun, 12 Jan 2020 15:41:41 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20200112134141.GC25899@pendragon.ideasonboard.com>","References":"<20200112010212.2609025-1-niklas.soderlund@ragnatech.se>\n\t<20200112010212.2609025-9-niklas.soderlund@ragnatech.se>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20200112010212.2609025-9-niklas.soderlund@ragnatech.se>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH v4 08/32] libcamera: buffer: Add\n\tFrameBuffer interface","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Sun, 12 Jan 2020 13:42:01 -0000"}}]