Files
external_libcamera/src/libcamera/formats.cpp
Hou Qi ff069d87e2 libcamera: formats: Change bytesPerGroup of RGB565 and RGB565_BE from 3 to 2
The RGB565 and RGB565_BE formats incorrectly specify a wrong value
of 3 bytes per group of pixels, when they actually use 2. Fix them.

Signed-off-by: Hou Qi <qi.hou@nxp.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2024-10-28 18:43:02 +02:00

1219 lines
38 KiB
C++

/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2019, Google Inc.
*
* libcamera image formats
*/
#include "libcamera/internal/formats.h"
#include <map>
#include <libcamera/base/log.h>
#include <libcamera/base/utils.h>
#include <libcamera/formats.h>
/**
* \file libcamera/internal/formats.h
* \brief Types and helper functions to handle libcamera image formats
*/
namespace libcamera {
LOG_DEFINE_CATEGORY(Formats)
/**
* \class PixelFormatInfo
* \brief Information about pixel formats
*
* The PixelFormatInfo class groups together information describing a pixel
* format. It facilitates handling of pixel formats by providing data commonly
* used in pipeline handlers.
*
* \var PixelFormatInfo::name
* \brief The format name as a human-readable string, used as the text
* representation of the PixelFormat
*
* \var PixelFormatInfo::format
* \brief The PixelFormat described by this instance
*
* \var PixelFormatInfo::v4l2Formats
* \brief The V4L2 pixel formats corresponding to the PixelFormat
*
* Multiple V4L2 formats may exist for one PixelFormat, as V4L2 defines
* separate 4CCs for contiguous and non-contiguous versions of the same image
* format.
*
* \var PixelFormatInfo::bitsPerPixel
* \brief The average number of bits per pixel
*
* The number of bits per pixel averages the total number of bits for all
* colour components over the whole image, excluding any padding bits or
* padding pixels.
*
* For formats that store pixels with bit padding within words, only the
* effective bits are taken into account. For instance, 12-bit Bayer data
* stored in two bytes per pixel report 12, not 16, in this field.
*
* Formats that don't have a fixed number of bits per pixel, such as compressed
* formats, report 0 in this field.
*
* \var PixelFormatInfo::colourEncoding
* \brief The colour encoding type
*
* \var PixelFormatInfo::packed
* \brief Tell if multiple pixels are packed in the same bytes
*
* Packed formats are defined as storing data from multiple pixels in the same
* bytes. For instance, 12-bit Bayer data with two pixels stored in three bytes
* is packed, while the same data stored with 4 bits of padding in two bytes
* per pixel is not packed.
*
* \var PixelFormatInfo::pixelsPerGroup
* \brief The number of pixels in a pixel group
*
* A pixel group is defined as the minimum number of pixels (including padding)
* necessary in a row when the image has only one column of effective pixels.
* pixelsPerGroup refers to this value. PixelFormatInfo::Plane::bytesPerGroup,
* then, refers to the number of bytes that a pixel group consumes. This
* definition of a pixel group allows simple calculation of stride, as
* ceil(width / pixelsPerGroup) * bytesPerGroup. These values are determined
* only in terms of a row. The ceiling accounts for padding.
*
* A pixel group has a second constraint, such that the pixel group
* (bytesPerGroup and pixelsPerGroup) is the smallest repeatable unit.
* What this means is that, for example, in the IPU3 formats, if there is only
* one column of effective pixels, it looks like it could be fit in 5 bytes
* with 3 padding pixels (for a total of 4 pixels over 5 bytes). However, this
* unit is not repeatable, as at the 7th group in the same row, the pattern
* is broken. Therefore, the pixel group for IPU3 formats must be 25 pixels
* over 32 bytes.
*
* For example, for something simple like BGR888, it is self-explanatory:
* the pixel group size is 1, and the bytes necessary is 3, and there is
* only one plane with no (= 1) vertical subsampling. For YUYV, the
* CbCr pair is shared between two pixels, so even if you have only one
* pixel, you would still need a padded second Y sample, therefore the pixel
* group size is 2, and bytes necessary is 4. YUYV also has no vertical
* subsampling. NV12 has a pixel group size of 2 pixels, due to the CbCr plane.
* The bytes per group then, for both planes, is 2. The first plane has no
* vertical subsampling, but the second plane is subsampled by a factor of 2.
*
* The IPU3 raw Bayer formats are single-planar, and have a pixel group size of
* 25, consuming 32 bytes, due to the packing pattern being repeated in memory
* every 32 bytes. The IPU3 hardware, however, has an additional constraint on
* the DMA burst size, requiring lines to be multiple of 64 bytes. This isn't an
* intrinsic property of the formats and is thus not reflected here. It is
* instead enforced by the corresponding pipeline handler.
*
* \var PixelFormatInfo::planes
* \brief Information about pixels for each plane
*
* \sa PixelFormatInfo::Plane
*/
/**
* \enum PixelFormatInfo::ColourEncoding
* \brief The colour encoding type
*
* \var PixelFormatInfo::ColourEncodingRGB
* \brief RGB colour encoding
*
* \var PixelFormatInfo::ColourEncodingYUV
* \brief YUV colour encoding
*
* \var PixelFormatInfo::ColourEncodingRAW
* \brief RAW colour encoding
*/
/**
* \struct PixelFormatInfo::Plane
* \brief Information about a single plane of a pixel format
*
* \var PixelFormatInfo::Plane::bytesPerGroup
* \brief The number of bytes that a pixel group consumes
*
* \sa PixelFormatInfo::pixelsPerGroup
*
* \var PixelFormatInfo::Plane::verticalSubSampling
* \brief Vertical subsampling multiplier
*
* This value is the ratio between the number of rows of pixels in the frame
* to the number of rows of pixels in the plane.
*/
namespace {
const PixelFormatInfo pixelFormatInfoInvalid{};
const std::map<PixelFormat, PixelFormatInfo> pixelFormatInfo{
/* RGB formats. */
{ formats::RGB565, {
.name = "RGB565",
.format = formats::RGB565,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_RGB565), },
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::RGB565_BE, {
.name = "RGB565_BE",
.format = formats::RGB565_BE,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_RGB565X), },
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::BGR888, {
.name = "BGR888",
.format = formats::BGR888,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_RGB24), },
.bitsPerPixel = 24,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::RGB888, {
.name = "RGB888",
.format = formats::RGB888,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_BGR24), },
.bitsPerPixel = 24,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::XRGB8888, {
.name = "XRGB8888",
.format = formats::XRGB8888,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_XBGR32), },
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::XBGR8888, {
.name = "XBGR8888",
.format = formats::XBGR8888,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_RGBX32), },
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::RGBX8888, {
.name = "RGBX8888",
.format = formats::RGBX8888,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_BGRX32), },
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::BGRX8888, {
.name = "BGRX8888",
.format = formats::BGRX8888,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_XRGB32), },
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::ABGR8888, {
.name = "ABGR8888",
.format = formats::ABGR8888,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_RGBA32), },
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::ARGB8888, {
.name = "ARGB8888",
.format = formats::ARGB8888,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_ABGR32), },
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::BGRA8888, {
.name = "BGRA8888",
.format = formats::BGRA8888,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_ARGB32), },
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::RGBA8888, {
.name = "RGBA8888",
.format = formats::RGBA8888,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_BGRA32), },
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::BGR161616, {
.name = "BGR161616",
.format = formats::BGR161616,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_RGB48), },
.bitsPerPixel = 48,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::RGB161616, {
.name = "RGB161616",
.format = formats::RGB161616,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_BGR48), },
.bitsPerPixel = 48,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }},
} },
/* YUV packed formats. */
{ formats::YUYV, {
.name = "YUYV",
.format = formats::YUYV,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_YUYV), },
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::YVYU, {
.name = "YVYU",
.format = formats::YVYU,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_YVYU), },
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::UYVY, {
.name = "UYVY",
.format = formats::UYVY,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_UYVY), },
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::VYUY, {
.name = "VYUY",
.format = formats::VYUY,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_VYUY), },
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::AVUY8888, {
.name = "AVUY8888",
.format = formats::AVUY8888,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_YUVA32), },
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::XVUY8888, {
.name = "XVUY8888",
.format = formats::XVUY8888,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_YUVX32), },
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
/* YUV planar formats. */
{ formats::NV12, {
.name = "NV12",
.format = formats::NV12,
.v4l2Formats = {
V4L2PixelFormat(V4L2_PIX_FMT_NV12),
V4L2PixelFormat(V4L2_PIX_FMT_NV12M),
},
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 2, 2 }, { 0, 0 } }},
} },
{ formats::NV21, {
.name = "NV21",
.format = formats::NV21,
.v4l2Formats = {
V4L2PixelFormat(V4L2_PIX_FMT_NV21),
V4L2PixelFormat(V4L2_PIX_FMT_NV21M),
},
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 2, 2 }, { 0, 0 } }},
} },
{ formats::NV16, {
.name = "NV16",
.format = formats::NV16,
.v4l2Formats = {
V4L2PixelFormat(V4L2_PIX_FMT_NV16),
V4L2PixelFormat(V4L2_PIX_FMT_NV16M),
},
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 2, 1 }, { 0, 0 } }},
} },
{ formats::NV61, {
.name = "NV61",
.format = formats::NV61,
.v4l2Formats = {
V4L2PixelFormat(V4L2_PIX_FMT_NV61),
V4L2PixelFormat(V4L2_PIX_FMT_NV61M),
},
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 2, 1 }, { 0, 0 } }},
} },
{ formats::NV24, {
.name = "NV24",
.format = formats::NV24,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_NV24), },
.bitsPerPixel = 24,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 1, 1 }, { 2, 1 }, { 0, 0 } }},
} },
{ formats::NV42, {
.name = "NV42",
.format = formats::NV42,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_NV42), },
.bitsPerPixel = 24,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 1, 1 }, { 2, 1 }, { 0, 0 } }},
} },
{ formats::YUV420, {
.name = "YUV420",
.format = formats::YUV420,
.v4l2Formats = {
V4L2PixelFormat(V4L2_PIX_FMT_YUV420),
V4L2PixelFormat(V4L2_PIX_FMT_YUV420M),
},
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 1, 2 }, { 1, 2 } }},
} },
{ formats::YVU420, {
.name = "YVU420",
.format = formats::YVU420,
.v4l2Formats = {
V4L2PixelFormat(V4L2_PIX_FMT_YVU420),
V4L2PixelFormat(V4L2_PIX_FMT_YVU420M),
},
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 1, 2 }, { 1, 2 } }},
} },
{ formats::YUV422, {
.name = "YUV422",
.format = formats::YUV422,
.v4l2Formats = {
V4L2PixelFormat(V4L2_PIX_FMT_YUV422P),
V4L2PixelFormat(V4L2_PIX_FMT_YUV422M),
},
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 1, 1 }, { 1, 1 } }},
} },
{ formats::YVU422, {
.name = "YVU422",
.format = formats::YVU422,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_YVU422M), },
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 1, 1 }, { 1, 1 } }},
} },
{ formats::YUV444, {
.name = "YUV444",
.format = formats::YUV444,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_YUV444M), },
.bitsPerPixel = 24,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 1, 1 }, { 1, 1 }, { 1, 1 } }},
} },
{ formats::YVU444, {
.name = "YVU444",
.format = formats::YVU444,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_YVU444M), },
.bitsPerPixel = 24,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 1, 1 }, { 1, 1 }, { 1, 1 } }},
} },
/* Greyscale formats. */
{ formats::R8, {
.name = "R8",
.format = formats::R8,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_GREY), },
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 1, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::R10, {
.name = "R10",
.format = formats::R10,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_Y10), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::R10_CSI2P, {
.name = "R10_CSI2P",
.format = formats::R10_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_Y10P), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = true,
.pixelsPerGroup = 4,
.planes = {{ { 5, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::R12_CSI2P, {
.name = "R12_CSI2P",
.format = formats::R12_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_Y12P), },
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = true,
.pixelsPerGroup = 2,
.planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::R12, {
.name = "R12",
.format = formats::R12,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_Y12), },
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::R16, {
.name = "R16",
.format = formats::R16,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_Y16), },
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::MONO_PISP_COMP1, {
.name = "MONO_PISP_COMP1",
.format = formats::MONO_PISP_COMP1,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_PISP_COMP1_MONO), },
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = true,
.pixelsPerGroup = 1,
.planes = {{ { 1, 1 }, { 0, 0 }, { 0, 0 } }},
} },
/* Bayer formats. */
{ formats::SBGGR8, {
.name = "SBGGR8",
.format = formats::SBGGR8,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SBGGR8), },
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGBRG8, {
.name = "SGBRG8",
.format = formats::SGBRG8,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGBRG8), },
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGRBG8, {
.name = "SGRBG8",
.format = formats::SGRBG8,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGRBG8), },
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SRGGB8, {
.name = "SRGGB8",
.format = formats::SRGGB8,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SRGGB8), },
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SBGGR10, {
.name = "SBGGR10",
.format = formats::SBGGR10,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGBRG10, {
.name = "SGBRG10",
.format = formats::SGBRG10,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGRBG10, {
.name = "SGRBG10",
.format = formats::SGRBG10,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SRGGB10, {
.name = "SRGGB10",
.format = formats::SRGGB10,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SBGGR10_CSI2P, {
.name = "SBGGR10_CSI2P",
.format = formats::SBGGR10_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10P), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 4,
.planes = {{ { 5, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGBRG10_CSI2P, {
.name = "SGBRG10_CSI2P",
.format = formats::SGBRG10_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10P), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 4,
.planes = {{ { 5, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGRBG10_CSI2P, {
.name = "SGRBG10_CSI2P",
.format = formats::SGRBG10_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10P), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 4,
.planes = {{ { 5, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SRGGB10_CSI2P, {
.name = "SRGGB10_CSI2P",
.format = formats::SRGGB10_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10P), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 4,
.planes = {{ { 5, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SBGGR12, {
.name = "SBGGR12",
.format = formats::SBGGR12,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SBGGR12), },
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGBRG12, {
.name = "SGBRG12",
.format = formats::SGBRG12,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12), },
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGRBG12, {
.name = "SGRBG12",
.format = formats::SGRBG12,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGRBG12), },
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SRGGB12, {
.name = "SRGGB12",
.format = formats::SRGGB12,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SRGGB12), },
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SBGGR12_CSI2P, {
.name = "SBGGR12_CSI2P",
.format = formats::SBGGR12_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SBGGR12P), },
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 2,
.planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGBRG12_CSI2P, {
.name = "SGBRG12_CSI2P",
.format = formats::SGBRG12_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12P), },
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 2,
.planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGRBG12_CSI2P, {
.name = "SGRBG12_CSI2P",
.format = formats::SGRBG12_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGRBG12P), },
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 2,
.planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SRGGB12_CSI2P, {
.name = "SRGGB12_CSI2P",
.format = formats::SRGGB12_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SRGGB12P), },
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 2,
.planes = {{ { 3, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SBGGR14, {
.name = "SBGGR14",
.format = formats::SBGGR14,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SBGGR14), },
.bitsPerPixel = 14,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGBRG14, {
.name = "SGBRG14",
.format = formats::SGBRG14,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGBRG14), },
.bitsPerPixel = 14,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGRBG14, {
.name = "SGRBG14",
.format = formats::SGRBG14,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGRBG14), },
.bitsPerPixel = 14,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SRGGB14, {
.name = "SRGGB14",
.format = formats::SRGGB14,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SRGGB14), },
.bitsPerPixel = 14,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SBGGR14_CSI2P, {
.name = "SBGGR14_CSI2P",
.format = formats::SBGGR14_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SBGGR14P), },
.bitsPerPixel = 14,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 4,
.planes = {{ { 7, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGBRG14_CSI2P, {
.name = "SGBRG14_CSI2P",
.format = formats::SGBRG14_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGBRG14P), },
.bitsPerPixel = 14,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 4,
.planes = {{ { 7, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGRBG14_CSI2P, {
.name = "SGRBG14_CSI2P",
.format = formats::SGRBG14_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGRBG14P), },
.bitsPerPixel = 14,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 4,
.planes = {{ { 7, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SRGGB14_CSI2P, {
.name = "SRGGB14_CSI2P",
.format = formats::SRGGB14_CSI2P,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SRGGB14P), },
.bitsPerPixel = 14,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 4,
.planes = {{ { 7, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SBGGR16, {
.name = "SBGGR16",
.format = formats::SBGGR16,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SBGGR16), },
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGBRG16, {
.name = "SGBRG16",
.format = formats::SGBRG16,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGBRG16), },
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGRBG16, {
.name = "SGRBG16",
.format = formats::SGRBG16,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SGRBG16), },
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SRGGB16, {
.name = "SRGGB16",
.format = formats::SRGGB16,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SRGGB16), },
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
.pixelsPerGroup = 2,
.planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SBGGR10_IPU3, {
.name = "SBGGR10_IPU3",
.format = formats::SBGGR10_IPU3,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SBGGR10), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
/* \todo remember to double this in the ipu3 pipeline handler */
.pixelsPerGroup = 25,
.planes = {{ { 32, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGBRG10_IPU3, {
.name = "SGBRG10_IPU3",
.format = formats::SGBRG10_IPU3,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGBRG10), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 25,
.planes = {{ { 32, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SGRBG10_IPU3, {
.name = "SGRBG10_IPU3",
.format = formats::SGRBG10_IPU3,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGRBG10), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 25,
.planes = {{ { 32, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::SRGGB10_IPU3, {
.name = "SRGGB10_IPU3",
.format = formats::SRGGB10_IPU3,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SRGGB10), },
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 25,
.planes = {{ { 32, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::BGGR_PISP_COMP1, {
.name = "BGGR_PISP_COMP1",
.format = formats::BGGR_PISP_COMP1,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_PISP_COMP1_BGGR), },
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::GBRG_PISP_COMP1, {
.name = "GBRG_PISP_COMP1",
.format = formats::GBRG_PISP_COMP1,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_PISP_COMP1_GBRG), },
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::GRBG_PISP_COMP1, {
.name = "GRBG_PISP_COMP1",
.format = formats::GRBG_PISP_COMP1,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_PISP_COMP1_GRBG), },
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }},
} },
{ formats::RGGB_PISP_COMP1, {
.name = "RGGB_PISP_COMP1",
.format = formats::RGGB_PISP_COMP1,
.v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_PISP_COMP1_RGGB), },
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
.pixelsPerGroup = 2,
.planes = {{ { 2, 1 }, { 0, 0 }, { 0, 0 } }},
} },
/* Compressed formats. */
{ formats::MJPEG, {
.name = "MJPEG",
.format = formats::MJPEG,
.v4l2Formats = {
V4L2PixelFormat(V4L2_PIX_FMT_MJPEG),
V4L2PixelFormat(V4L2_PIX_FMT_JPEG),
},
.bitsPerPixel = 0,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
.pixelsPerGroup = 1,
.planes = {{ { 1, 1 }, { 0, 0 }, { 0, 0 } }},
} },
};
} /* namespace */
/**
* \fn bool PixelFormatInfo::isValid() const
* \brief Check if the pixel format info is valid
* \return True if the pixel format info is valid, false otherwise
*/
/**
* \brief Retrieve information about a pixel format
* \param[in] format The pixel format
* \return The PixelFormatInfo describing the \a format if known, or an invalid
* PixelFormatInfo otherwise
*/
const PixelFormatInfo &PixelFormatInfo::info(const PixelFormat &format)
{
const auto iter = pixelFormatInfo.find(format);
if (iter == pixelFormatInfo.end()) {
LOG(Formats, Warning)
<< "Unsupported pixel format "
<< utils::hex(format.fourcc());
return pixelFormatInfoInvalid;
}
return iter->second;
}
/**
* \brief Retrieve information about a V4L2 pixel format
* \param[in] format The V4L2 pixel format
* \return The PixelFormatInfo describing the V4L2 \a format if known, or an
* invalid PixelFormatInfo otherwise
*/
const PixelFormatInfo &PixelFormatInfo::info(const V4L2PixelFormat &format)
{
PixelFormat pixelFormat = format.toPixelFormat(false);
if (!pixelFormat.isValid())
return pixelFormatInfoInvalid;
const auto iter = pixelFormatInfo.find(pixelFormat);
if (iter == pixelFormatInfo.end())
return pixelFormatInfoInvalid;
return iter->second;
}
/**
* \brief Retrieve information about a pixel format
* \param[in] name The name of pixel format
* \return The PixelFormatInfo describing the PixelFormat matching the
* \a name if known, or an invalid PixelFormatInfo otherwise
*/
const PixelFormatInfo &PixelFormatInfo::info(const std::string &name)
{
for (const auto &info : pixelFormatInfo) {
if (info.second.name == name)
return info.second;
}
return pixelFormatInfoInvalid;
}
/**
* \brief Compute the stride
* \param[in] width The width of the line, in pixels
* \param[in] plane The index of the plane whose stride is to be computed
* \param[in] align The stride alignment, in bytes
*
* The stride is the number of bytes necessary to store a full line of a frame,
* including padding at the end of the line. This function takes into account
* the alignment constraints intrinsic to the format (for instance, the
* SGRBG12_CSI2P format stores two 12-bit pixels in 3 bytes, and thus has a
* required stride alignment of 3 bytes). Additional alignment constraints may
* be specified through the \a align parameter, which will cause the stride to
* be rounded up to the next multiple of \a align.
*
* For multi-planar formats, different planes may have different stride values.
* The \a plane parameter selects which plane to compute the stride for.
*
* \return The number of bytes necessary to store a line, or 0 if the
* PixelFormatInfo instance or the \a plane is not valid
*/
unsigned int PixelFormatInfo::stride(unsigned int width, unsigned int plane,
unsigned int align) const
{
if (!isValid()) {
LOG(Formats, Warning) << "Invalid pixel format, stride is zero";
return 0;
}
if (plane >= planes.size() || !planes[plane].bytesPerGroup) {
LOG(Formats, Warning) << "Invalid plane index, stride is zero";
return 0;
}
/* ceil(width / pixelsPerGroup) * bytesPerGroup */
unsigned int stride = (width + pixelsPerGroup - 1) / pixelsPerGroup
* planes[plane].bytesPerGroup;
/* ceil(stride / align) * align */
return (stride + align - 1) / align * align;
}
/**
* \brief Compute the number of bytes necessary to store a plane of a frame
* \param[in] size The size of the frame, in pixels
* \param[in] plane The plane index
* \param[in] align The stride alignment, in bytes (1 for default alignment)
*
* The plane size is computed by multiplying the line stride and the frame
* height, taking subsampling and other format characteristics into account.
* Stride alignment constraints may be specified through the \a align parameter.
*
* \sa stride()
*
* \return The number of bytes necessary to store the plane, or 0 if the
* PixelFormatInfo instance is not valid or the plane number isn't valid for the
* format
*/
unsigned int PixelFormatInfo::planeSize(const Size &size, unsigned int plane,
unsigned int align) const
{
unsigned int stride = PixelFormatInfo::stride(size.width, plane, align);
if (!stride)
return 0;
return planeSize(size.height, plane, stride);
}
/**
* \brief Compute the number of bytes necessary to store a plane of a frame
* \param[in] height The height of the frame, in pixels
* \param[in] plane The plane index
* \param[in] stride The plane stride, in bytes
*
* The plane size is computed by multiplying the line stride and the frame
* height, taking subsampling and other format characteristics into account.
* Stride alignment constraints may be specified through the \a align parameter.
*
* \return The number of bytes necessary to store the plane, or 0 if the
* PixelFormatInfo instance is not valid or the plane number isn't valid for the
* format
*/
unsigned int PixelFormatInfo::planeSize(unsigned int height, unsigned int plane,
unsigned int stride) const
{
unsigned int vertSubSample = planes[plane].verticalSubSampling;
if (!vertSubSample)
return 0;
/* stride * ceil(height / verticalSubSampling) */
return stride * ((height + vertSubSample - 1) / vertSubSample);
}
/**
* \brief Compute the number of bytes necessary to store a frame
* \param[in] size The size of the frame, in pixels
* \param[in] align The stride alignment, in bytes (1 for default alignment)
*
* The frame size is computed by adding the size of all planes, as computed by
* planeSize(), using the specified alignment constraints for all planes. For
* more complex stride constraints, use the frameSize() overloaded version that
* takes an array of stride values.
*
* \sa planeSize()
*
* \return The number of bytes necessary to store the frame, or 0 if the
* PixelFormatInfo instance is not valid
*/
unsigned int PixelFormatInfo::frameSize(const Size &size, unsigned int align) const
{
unsigned int sum = 0;
for (const auto &[i, plane] : utils::enumerate(planes)) {
if (plane.bytesPerGroup == 0)
break;
sum += planeSize(size, i, align);
}
return sum;
}
/**
* \brief Compute the number of bytes necessary to store a frame
* \param[in] size The size of the frame, in pixels
* \param[in] strides The strides to use for each plane
*
* This function is an overloaded version that takes custom strides for each
* plane, to be used when the device has custom alignment constraints that
* can't be described by just an alignment value.
*
* \return The number of bytes necessary to store the frame, or 0 if the
* PixelFormatInfo instance is not valid
*/
unsigned int
PixelFormatInfo::frameSize(const Size &size,
const std::array<unsigned int, 3> &strides) const
{
/* stride * ceil(height / verticalSubSampling) */
unsigned int sum = 0;
for (unsigned int i = 0; i < 3; i++) {
unsigned int vertSubSample = planes[i].verticalSubSampling;
if (!vertSubSample)
continue;
sum += strides[i]
* ((size.height + vertSubSample - 1) / vertSubSample);
}
return sum;
}
/**
* \brief Retrieve the number of planes represented by the format
* \return The number of planes used by the format
*/
unsigned int PixelFormatInfo::numPlanes() const
{
unsigned int count = 0;
for (const Plane &p : planes) {
if (p.bytesPerGroup == 0)
break;
count++;
}
return count;
}
} /* namespace libcamera */