Files
external_libcamera/src/libcamera/formats.cpp
Kaaira Gupta 2129117df9 libcamera: pixel_format: Replace hex with format names
Print format names defined in formats namespace instead of the hex
values in toString() as they are easier to comprehend. For this add
a property of 'name' in PixelFormatInfo' so as to map the formats
with their names. Print fourcc for formats which are not used in
libcamera.

Signed-off-by: Kaaira Gupta <kgupta@es.iitr.ac.in>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
2020-06-25 06:47:48 +03:00

553 lines
15 KiB
C++

/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2019, Google Inc.
*
* formats.cpp - libcamera image formats
*/
#include "libcamera/internal/formats.h"
#include <errno.h>
#include <libcamera/formats.h>
#include "libcamera/internal/log.h"
/**
* \file internal/formats.h
* \brief Types and helper methods to handle libcamera image formats
*/
namespace libcamera {
LOG_DEFINE_CATEGORY(Formats)
/**
* \class ImageFormats
* \brief Describe V4L2Device and V4L2SubDevice image formats
*
* This class stores a list of image formats, each associated with a
* corresponding set of image sizes. It is used to describe the formats and
* sizes supported by a V4L2Device or V4L2Subdevice.
*
* Formats are stored as an integer. When used for a V4L2Device, the image
* formats are fourcc pixel formats. When used for a V4L2Subdevice they are
* media bus codes. Both are defined by the V4L2 specification.
*
* Sizes are stored as a list of SizeRange.
*/
/**
* \brief Add a format and corresponding sizes to the description
* \param[in] format Pixel format or media bus code to describe
* \param[in] sizes List of supported size ranges for the format
*
* \return 0 on success or a negative error code otherwise
* \retval -EEXIST The format is already described
*/
int ImageFormats::addFormat(unsigned int format, const std::vector<SizeRange> &sizes)
{
if (data_.find(format) != data_.end())
return -EEXIST;
data_[format] = sizes;
return 0;
}
/**
* \brief Check if the list of devices supported formats is empty
* \return True if the list of supported formats is empty
*/
bool ImageFormats::isEmpty() const
{
return data_.empty();
}
/**
* \brief Retrieve a list of all supported image formats
* \return List of pixel formats or media bus codes
*/
std::vector<unsigned int> ImageFormats::formats() const
{
std::vector<unsigned int> formats;
formats.reserve(data_.size());
/* \todo: Should this be cached instead of computed each time? */
for (auto const &it : data_)
formats.push_back(it.first);
return formats;
}
/**
* \brief Retrieve all sizes for a specific format
* \param[in] format The pixel format or mbus code
*
* Retrieve all size ranges for a specific format. For V4L2Device \a format is a
* pixel format while for a V4L2Subdevice \a format is a media bus code.
*
* \return The list of image sizes supported for \a format, or an empty list if
* the format is not supported
*/
const std::vector<SizeRange> &ImageFormats::sizes(unsigned int format) const
{
static const std::vector<SizeRange> empty;
auto const &it = data_.find(format);
if (it == data_.end())
return empty;
return it->second;
}
/**
* \brief Retrieve the map that associates formats to image sizes
* \return The map that associates formats to image sizes
*/
const std::map<unsigned int, std::vector<SizeRange>> &ImageFormats::data() const
{
return data_;
}
/**
* \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 test
* representation of the PixelFormat
*
* \var PixelFormatInfo::format
* \brief The PixelFormat described by this instance
*
* \var PixelFormatInfo::v4l2Format
* \brief The V4L2 pixel format corresponding to the PixelFormat
*
* \var PixelFormatInfo::bitsPerPixel
* \brief The average number of bits per pixel
*
* The number 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.
*/
/**
* \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
*/
namespace {
const std::map<PixelFormat, PixelFormatInfo> pixelFormatInfo{
/* RGB formats. */
{ formats::BGR888, {
.name = "BGR888",
.format = formats::BGR888,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_RGB24),
.bitsPerPixel = 24,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
} },
{ formats::RGB888, {
.name = "RGB888",
.format = formats::RGB888,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_BGR24),
.bitsPerPixel = 24,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
} },
{ formats::ABGR8888, {
.name = "ABGR8888",
.format = formats::ABGR8888,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_RGBA32),
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
} },
{ formats::ARGB8888, {
.name = "ARGB8888",
.format = formats::ARGB8888,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_ABGR32),
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
} },
{ formats::BGRA8888, {
.name = "BGRA8888",
.format = formats::BGRA8888,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_ARGB32),
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
} },
{ formats::RGBA8888, {
.name = "RGBA8888",
.format = formats::RGBA8888,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_BGRA32),
.bitsPerPixel = 32,
.colourEncoding = PixelFormatInfo::ColourEncodingRGB,
.packed = false,
} },
/* YUV packed formats. */
{ formats::YUYV, {
.name = "YUYV",
.format = formats::YUYV,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_YUYV),
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
} },
{ formats::YVYU, {
.name = "YVYU",
.format = formats::YVYU,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_YVYU),
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
} },
{ formats::UYVY, {
.name = "UYVY",
.format = formats::UYVY,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_UYVY),
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
} },
{ formats::VYUY, {
.name = "VYUY",
.format = formats::VYUY,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_VYUY),
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
} },
/* YUV planar formats. */
{ formats::NV16, {
.name = "NV16",
.format = formats::NV16,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV16),
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
} },
{ formats::NV61, {
.name = "NV61",
.format = formats::NV61,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV61),
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
} },
{ formats::NV12, {
.name = "NV12",
.format = formats::NV12,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV12),
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
} },
{ formats::NV21, {
.name = "NV21",
.format = formats::NV21,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_NV21),
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
} },
{ formats::YUV420, {
.name = "YUV420",
.format = PixelFormat(formats::YUV420),
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_YUV420),
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
} },
{ formats::YUV422, {
.name = "YUV422",
.format = PixelFormat(formats::YUV422),
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_YUV422P),
.bitsPerPixel = 16,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
} },
/* Greyscale formats. */
{ formats::R8, {
.name = "R8",
.format = formats::R8,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_GREY),
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
} },
/* Bayer formats. */
{ formats::SBGGR8, {
.name = "SBGGR8",
.format = formats::SBGGR8,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR8),
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
} },
{ formats::SGBRG8, {
.name = "SGBRG8",
.format = formats::SGBRG8,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG8),
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
} },
{ formats::SGRBG8, {
.name = "SGRBG8",
.format = formats::SGRBG8,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG8),
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
} },
{ formats::SRGGB8, {
.name = "SRGGB8",
.format = formats::SRGGB8,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB8),
.bitsPerPixel = 8,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
} },
{ formats::SBGGR10, {
.name = "SBGGR10",
.format = formats::SBGGR10,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10),
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
} },
{ formats::SGBRG10, {
.name = "SGBRG10",
.format = formats::SGBRG10,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10),
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
} },
{ formats::SGRBG10, {
.name = "SGRBG10",
.format = formats::SGRBG10,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10),
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
} },
{ formats::SRGGB10, {
.name = "SRGGB10",
.format = formats::SRGGB10,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10),
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
} },
{ formats::SBGGR10_CSI2P, {
.name = "SBGGR10_CSI2P",
.format = formats::SBGGR10_CSI2P,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10P),
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
} },
{ formats::SGBRG10_CSI2P, {
.name = "SGBRG10_CSI2P",
.format = formats::SGBRG10_CSI2P,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10P),
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
} },
{ formats::SGRBG10_CSI2P, {
.name = "SGRBG10_CSI2P",
.format = formats::SGRBG10_CSI2P,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10P),
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
} },
{ formats::SRGGB10_CSI2P, {
.name = "SRGGB10_CSI2P",
.format = formats::SRGGB10_CSI2P,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10P),
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
} },
{ formats::SBGGR12, {
.name = "SBGGR12",
.format = formats::SBGGR12,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR12),
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
} },
{ formats::SGBRG12, {
.name = "SGBRG12",
.format = formats::SGBRG12,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12),
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
} },
{ formats::SGRBG12, {
.name = "SGRBG12",
.format = formats::SGRBG12,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG12),
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
} },
{ formats::SRGGB12, {
.name = "SRGGB12",
.format = formats::SRGGB12,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB12),
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = false,
} },
{ formats::SBGGR12_CSI2P, {
.name = "SBGGR12_CSI2P",
.format = formats::SBGGR12_CSI2P,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR12P),
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
} },
{ formats::SGBRG12_CSI2P, {
.name = "SGBRG12_CSI2P",
.format = formats::SGBRG12_CSI2P,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12P),
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
} },
{ formats::SGRBG12_CSI2P, {
.name = "SGRBG12_CSI2P",
.format = formats::SGRBG12_CSI2P,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SGRBG12P),
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
} },
{ formats::SRGGB12_CSI2P, {
.name = "SRGGB12_CSI2P",
.format = formats::SRGGB12_CSI2P,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_SRGGB12P),
.bitsPerPixel = 12,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
} },
{ formats::SBGGR10_IPU3, {
.name = "SBGGR10_IPU3",
.format = formats::SBGGR10_IPU3,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SBGGR10),
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
} },
{ formats::SGBRG10_IPU3, {
.name = "SGBRG10_IPU3",
.format = formats::SGBRG10_IPU3,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGBRG10),
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
} },
{ formats::SGRBG10_IPU3, {
.name = "SGRBG10_IPU3",
.format = formats::SGRBG10_IPU3,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SGRBG10),
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
} },
{ formats::SRGGB10_IPU3, {
.name = "SRGGB10_IPU3",
.format = formats::SRGGB10_IPU3,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SRGGB10),
.bitsPerPixel = 10,
.colourEncoding = PixelFormatInfo::ColourEncodingRAW,
.packed = true,
} },
/* Compressed formats. */
{ formats::MJPEG, {
.name = "MJPEG",
.format = formats::MJPEG,
.v4l2Format = V4L2PixelFormat(V4L2_PIX_FMT_MJPEG),
.bitsPerPixel = 0,
.colourEncoding = PixelFormatInfo::ColourEncodingYUV,
.packed = false,
} },
};
} /* 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)
{
static const PixelFormatInfo invalid{};
const auto iter = pixelFormatInfo.find(format);
if (iter == pixelFormatInfo.end()) {
LOG(Formats, Warning)
<< "Unsupported pixel format 0x"
<< utils::hex(format.fourcc());
return invalid;
}
return iter->second;
}
} /* namespace libcamera */