summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Elder <paul.elder@ideasonboard.com>2020-06-29 22:28:38 +0900
committerPaul Elder <paul.elder@ideasonboard.com>2020-07-10 16:11:08 +0900
commite83727a194b5cf2e40331989bf8f762da74217fd (patch)
treebda97c62e216f39c1fb511a799e6ef69f00a17bb
parent8addae2583d68aaa4e904d7607b1d94ddc371860 (diff)
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>
-rw-r--r--include/libcamera/internal/formats.h6
-rw-r--r--src/libcamera/formats.cpp102
2 files changed, 108 insertions, 0 deletions
diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h
index 211da4a3..cad41ad8 100644
--- a/include/libcamera/internal/formats.h
+++ b/include/libcamera/internal/formats.h
@@ -53,6 +53,12 @@ public:
static const PixelFormatInfo &info(const PixelFormat &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 */
const char *name;
PixelFormat format;
diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp
index 48aa2454..3f895a7c 100644
--- a/src/libcamera/formats.cpp
+++ b/src/libcamera/formats.cpp
@@ -731,4 +731,106 @@ const PixelFormatInfo &PixelFormatInfo::info(const V4L2PixelFormat &format)
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 */