libcamera: PixelFormatInfo: Add functions stride and frameSize

Add member functions to PixelFormatInfo for calculating stride and frame
size. This will simplify existing code that calculates these things.

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Paul Elder 2020-06-29 22:28:38 +09:00
parent 8addae2583
commit e83727a194
2 changed files with 108 additions and 0 deletions

View file

@ -53,6 +53,12 @@ public:
static const PixelFormatInfo &info(const PixelFormat &format); static const PixelFormatInfo &info(const PixelFormat &format);
static const PixelFormatInfo &info(const V4L2PixelFormat &format); static const PixelFormatInfo &info(const V4L2PixelFormat &format);
unsigned int stride(unsigned int width, unsigned int plane,
unsigned int align = 1) const;
unsigned int frameSize(const Size &size, unsigned int align = 1) const;
unsigned int frameSize(const Size &size,
const std::array<unsigned int, 3> &strides) const;
/* \todo Add support for non-contiguous memory planes */ /* \todo Add support for non-contiguous memory planes */
const char *name; const char *name;
PixelFormat format; PixelFormat format;

View file

@ -731,4 +731,106 @@ const PixelFormatInfo &PixelFormatInfo::info(const V4L2PixelFormat &format)
return info->second; return info->second;
} }
/**
* \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 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 is computed by adding the product of the line stride and the frame
* height for all planes, taking subsampling and other format characteristics
* into account. Additional stride alignment constraints may be specified
* through the \a align parameter, and will apply to all planes. For more
* complex stride constraints, use the frameSize() overloaded version that takes
* an array of stride values.
*
* \sa stride()
*
* \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
{
/* 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 += stride(size.width, i, align)
* ((size.height + vertSubSample - 1) / vertSubSample);
}
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;
}
} /* namespace libcamera */ } /* namespace libcamera */