From patchwork Thu Aug 5 18:22:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13230 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id C070BC3235 for ; Thu, 5 Aug 2021 18:22:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 34DD36881B; Thu, 5 Aug 2021 20:22:25 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="srUHfKlr"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 12F046026D for ; Thu, 5 Aug 2021 20:22:24 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7D5B3E04; Thu, 5 Aug 2021 20:22:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628187743; bh=koRM3ZbradqDe8I9xvxRR8oGC/sSx6Dpf/r1e0jAu3c=; h=From:To:Cc:Subject:Date:From; b=srUHfKlrVJ+pOdVzIDTKP0Ykp5v1VZNYpHBgV0JoIfxYb3xhID7rpEfFcWRNHJ8wS 3mIrLgIqBAkIFzkl/VCy4gZmp4jJzyxgPJrG73/SIWOJ/qFOSazSLhs7lA2dMFlCDZ v7YsFjMRg8I/lBGKvZiAR1HxlaejUFiBuG/tpXdM= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Thu, 5 Aug 2021 21:22:03 +0300 Message-Id: <20210805182203.1297-1-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH] libcamera: Add FrameFormat class X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The FrameFormat class describes how a frame is stored in memory. It groups a pixel format, size in pixels, and per-plane stride and size. This new class will be used in the configuration API rework, but could already be put in use if desired to replace the various data structures used to carry the same information. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Hirokazu Honda --- I've developed this as part of the configuration API rework, and realized it could already be useful, in particular if we want to start cleaning up support for multi-planar formats. I'm thus sending it as an RFC. --- include/libcamera/format.h | 43 ++++++++++ include/libcamera/meson.build | 1 + src/libcamera/format.cpp | 142 ++++++++++++++++++++++++++++++++++ src/libcamera/meson.build | 1 + 4 files changed, 187 insertions(+) create mode 100644 include/libcamera/format.h create mode 100644 src/libcamera/format.cpp diff --git a/include/libcamera/format.h b/include/libcamera/format.h new file mode 100644 index 000000000000..4982ab8230dc --- /dev/null +++ b/include/libcamera/format.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google Inc. + * + * format.h - Frame Format + */ +#ifndef __LIBCAMERA_FORMAT_H__ +#define __LIBCAMERA_FORMAT_H__ + +#include +#include +#include + +#include +#include + +namespace libcamera { + +class FrameFormat +{ +public: + static constexpr unsigned int kMaxPlanes = 4; + + struct Plane { + std::size_t stride; + std::size_t size; + }; + + FrameFormat(); + FrameFormat(PixelFormat format, const Size &size); + + std::size_t stride() const; + std::size_t frameSize() const; + std::string toString() const; + + PixelFormat format_; + Size size_; + std::array planes_; +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_FORMAT_H__ */ diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 5b25ef847ed4..dcfadb381874 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -6,6 +6,7 @@ libcamera_public_headers = files([ 'compiler.h', 'controls.h', 'file_descriptor.h', + 'format.h', 'framebuffer.h', 'framebuffer_allocator.h', 'geometry.h', diff --git a/src/libcamera/format.cpp b/src/libcamera/format.cpp new file mode 100644 index 000000000000..f77413781de1 --- /dev/null +++ b/src/libcamera/format.cpp @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google Inc. + * + * format.cpp - Frame Format + */ + +#include + +#include + +/** + * \file libcamera/format.h + * \brief Frame Format + */ + +namespace libcamera { + +/** + * \class FrameFormat + * \brief Format of a frame as stored in memory + * + * The FrameFormat class fully describes how a frame is stored in memory. It + * combines a pixel format, a size in pixels, and memory layout information for + * planes. + * + * Frames are stored in memory in one or multiple planes, as specified by the + * pixel format. A plane is a two-dimensional memory area organized as lines of + * samples. A sample typically stores one or multiple components of a pixel (for + * instance, the NV12 format uses two planes, with the first plane storing only + * the luminance Y component of the pixels, and the second plane storing both + * the chroma Cb and Cr components). + * + * Planes cover the whole frame. Their number of lines and sample per lines + * correspond to the frame width and height in pixels, possibly divided by + * horizontal and vertical subsampling factors as specified by the pixel + * format. + * + * A plane may contain padding at the end of line, to support requirements of + * applications and cameras, such as alignment constraints. This is specified + * as a line stride value, equal to the distance in bytes between the first + * sample of successive lines in memory, including pixel data and padding. All + * lines in a plane have the same stride value, including the last line. + * Additionally, padding may also occur at the end of the plane, specified as + * the total plane size in bytes. + * + * \var FrameFormat::kMaxPlanes + * \brief Maximum number of data planes for a frame + * + * \var FrameFormat::format_ + * \brief Frame pixel format, defines how pixel data is packed and stored in + * memory + * + * \var FrameFormat::size_ + * \brief Frame size, defines the horizontal and vertical dimensions of the + * frame in pixels (excluding any padding) + * + * \var FrameFormat::planes_ + * \brief Frame data planes, defines the memory layout for each data plane of + * the frame + * + * Unused entries in the planes array shall be zero-initialized. + */ + +/** + * \class FrameFormat::Plane + * \brief Memory layout configuration for one data plane of a frame + * + * \var FrameFormat::Plane::stride + * \brief Distance in bytes between the beginning of two successive lines + * + * If the strides of different planes can't be set separately, the stride of the + * first plane takes precedence and is used by the camera. + * + * \var FrameFormat::Plane::size + * \brief Maximum number of bytes required to store the plane + * + * The \a size reports the number of bytes required to store data for plane. + * For uncompressed formats, it takes into account the plane's stride, the + * frame height, the plane's vertical subsampling and the overall alignment + * constraints of the camera (for instance many cameras require buffer sizes + * to be a multiple of the page size). For compressed formats, it indicates the + * maximum size of the compressed data. + */ + +/** + * \brief Construct a zero-initialized FrameFormat + */ +FrameFormat::FrameFormat() = default; + +/** + * \brief Construct a FrameFormat + * \param[in] format The pixel format + * \param[in] size The frame size in pixels + */ +FrameFormat::FrameFormat(PixelFormat format, const Size &size) + : format_(format), size_(size) +{ +} + +/** + * \brief Retrieve the frame stride in bytes + * + * The stride() function is a convenience helper to retrieve the stride of the + * first plane. For multi-planar formats that have different stride values for + * each plane, applications shall access the stride from the \ref planes_ + * instead. + * + * \return The frame stride in bytes + */ +std::size_t FrameFormat::stride() const +{ + return planes_[0].stride; +} + +/** + * \brief Retrieve the full frame size + * + * The frameSize() function is a convenience helper to retrieve the full frame + * size, defined as the sum of the sizes of all planes. + * + * \return The full frame size, in bytes + */ +std::size_t FrameFormat::frameSize() const +{ + return std::accumulate(planes_.begin(), planes_.end(), 0, + [](std::size_t a, const Plane &b) { + return a + b.size; + }); +} + +/** + * \brief Assemble and return a string describing the frame format + * + * \return A string describing the FrameFormat + */ +std::string FrameFormat::toString() const +{ + return size_.toString() + "-" + format_.toString(); +} + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 4f08580157f9..7cf17ec2c628 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -15,6 +15,7 @@ libcamera_sources = files([ 'device_enumerator.cpp', 'device_enumerator_sysfs.cpp', 'file_descriptor.cpp', + 'format.cpp', 'formats.cpp', 'framebuffer.cpp', 'framebuffer_allocator.cpp',