[libcamera-devel,v3,06/22] libcamera: PixelFormatInfo: Add functions stride and frameSize

Message ID 20200704133140.1738660-7-paul.elder@ideasonboard.com
State Superseded
Headers show
Series
  • Clean up formats in v4l2-compat and pipeline handlers
Related show

Commit Message

Paul Elder July 4, 2020, 1:31 p.m. UTC
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>

---
Changes in v3:
- rename functions to stride and frameSize, from bytesPerLine and
  imageSize, respectively

Changes in v2:
- make these functions const
- add documentation
- inline DIV_ROUND_UP
---
 include/libcamera/internal/formats.h |  3 +++
 src/libcamera/formats.cpp            | 40 ++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)

Comments

Laurent Pinchart July 4, 2020, 6:39 p.m. UTC | #1
Hi Paul,

Thank you for the patch.

On Sat, Jul 04, 2020 at 10:31:24PM +0900, Paul Elder wrote:
> 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>
> 
> ---
> Changes in v3:
> - rename functions to stride and frameSize, from bytesPerLine and
>   imageSize, respectively
> 
> Changes in v2:
> - make these functions const
> - add documentation
> - inline DIV_ROUND_UP
> ---
>  include/libcamera/internal/formats.h |  3 +++
>  src/libcamera/formats.cpp            | 40 ++++++++++++++++++++++++++++
>  2 files changed, 43 insertions(+)
> 
> diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h
> index cf00814..8957059 100644
> --- a/include/libcamera/internal/formats.h
> +++ b/include/libcamera/internal/formats.h
> @@ -52,6 +52,9 @@ public:
>  	static const PixelFormatInfo &info(const PixelFormat &format);
>  	static const PixelFormatInfo &info(const V4L2PixelFormat &format);
>  
> +	unsigned int stride(unsigned int width, unsigned int plane) const;
> +	unsigned int frameSize(const Size &size) const;
> +
>  	const char *name;
>  	PixelFormat format;
>  	V4L2PixelFormat v4l2Format;
> diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp
> index f96bf1f..6d558f2 100644
> --- a/src/libcamera/formats.cpp
> +++ b/src/libcamera/formats.cpp
> @@ -710,4 +710,44 @@ 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
> + * \return The number of bytes necessary to store a line, or 0 if the
> + * PixelFormatInfo instance not valid

s/not valid/or the \a plane is not valid/

> + */
> +unsigned int PixelFormatInfo::stride(unsigned int width, unsigned int plane) const
> +{
> +	if (!isValid())
> +		return 0;
> +
> +	if (plane > planes.size() || !planes[plane].bytesPerGroup)
> +		return 0;
> +
> +	/* ceil(width / pixelsPerGroup) * bytesPerGroup */
> +	return ((width + pixelsPerGroup - 1) / pixelsPerGroup) * planes[plane].bytesPerGroup;

You can remove the outer parentheses, and let's add a line break to keep
this shorter.

> +}
> +
> +/**
> + * \brief Compute the bytes necessary to store the frame
> + * \param[in] size The size of the frame, in pixels
> + * \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
> +{
> +	/* stride * ceil(height / verticalSubSampling) */
> +	unsigned int sum = 0;

s/sum/size/ ?

> +	for (int i = 0; i < 3; i++) {

unsigned int as i is always positive, but even better,

	for (const PixelFormatPlaneInfo &plane : planes) {

> +		unsigned int vertSubSample = planes[i].verticalSubSampling;
> +		if (!vertSubSample)
> +			continue;
> +		sum += stride(size.width, i)
> +		     * ((size.height + vertSubSample - 1) / vertSubSample);

This is an issue. The stride may be aligned by the pipeline handler, so
you can't calculate it here (the IPU3 pipeline handler will align it to
64 bytes for RAW formats for instance). I'm afraid you need to pass the
width and an array of strides to this function (and the range-based for
loop will then not be possible anymore). Or maybe find a better API than
what I'm proposing :-) I haven't looked at how you use this in the
pipeline handlers yet.

> +	}
> +
> +	return sum;
> +}
> +
>  } /* namespace libcamera */

Patch

diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h
index cf00814..8957059 100644
--- a/include/libcamera/internal/formats.h
+++ b/include/libcamera/internal/formats.h
@@ -52,6 +52,9 @@  public:
 	static const PixelFormatInfo &info(const PixelFormat &format);
 	static const PixelFormatInfo &info(const V4L2PixelFormat &format);
 
+	unsigned int stride(unsigned int width, unsigned int plane) const;
+	unsigned int frameSize(const Size &size) const;
+
 	const char *name;
 	PixelFormat format;
 	V4L2PixelFormat v4l2Format;
diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp
index f96bf1f..6d558f2 100644
--- a/src/libcamera/formats.cpp
+++ b/src/libcamera/formats.cpp
@@ -710,4 +710,44 @@  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
+ * \return The number of bytes necessary to store a line, or 0 if the
+ * PixelFormatInfo instance not valid
+ */
+unsigned int PixelFormatInfo::stride(unsigned int width, unsigned int plane) const
+{
+	if (!isValid())
+		return 0;
+
+	if (plane > planes.size() || !planes[plane].bytesPerGroup)
+		return 0;
+
+	/* ceil(width / pixelsPerGroup) * bytesPerGroup */
+	return ((width + pixelsPerGroup - 1) / pixelsPerGroup) * planes[plane].bytesPerGroup;
+}
+
+/**
+ * \brief Compute the bytes necessary to store the frame
+ * \param[in] size The size of the frame, in pixels
+ * \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
+{
+	/* stride * ceil(height / verticalSubSampling) */
+	unsigned int sum = 0;
+	for (int i = 0; i < 3; i++) {
+		unsigned int vertSubSample = planes[i].verticalSubSampling;
+		if (!vertSubSample)
+			continue;
+		sum += stride(size.width, i)
+		     * ((size.height + vertSubSample - 1) / vertSubSample);
+	}
+
+	return sum;
+}
+
 } /* namespace libcamera */