[libcamera-devel] [RFC PATCH v1 03/12] libcamera: formats: Add planeSize() helpers to PixelFormatInfo

Kieran Bingham kieran.bingham at ideasonboard.com
Thu Sep 2 10:49:52 CEST 2021


On 02/09/2021 05:22, Laurent Pinchart wrote:
> Add two helpers functions to the PixelFormatInfo class to compute the
> byte size of a given plane, taking the frame size, the stride, the
> alignement constraints and the vertical subsampling into account.

s/alignement/alignment/


> Use the new functions through the code base to replace manual
> implementations.


\o/ that makes me happy.

Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>

> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
>  include/libcamera/internal/formats.h     |  4 ++
>  src/android/mm/generic_camera_buffer.cpp | 11 +---
>  src/android/yuv/post_processor_yuv.cpp   | 10 ++-
>  src/libcamera/formats.cpp                | 82 ++++++++++++++++++++----
>  src/libcamera/v4l2_videodevice.cpp       |  6 +-
>  5 files changed, 79 insertions(+), 34 deletions(-)
> 
> diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h
> index 51a8a6b8b0ae..8f314e99889b 100644
> --- a/include/libcamera/internal/formats.h
> +++ b/include/libcamera/internal/formats.h
> @@ -42,6 +42,10 @@ public:
>  
>  	unsigned int stride(unsigned int width, unsigned int plane,
>  			    unsigned int align = 1) const;
> +	unsigned int planeSize(const Size &size, unsigned int plane,
> +			       unsigned int align = 1) const;
> +	unsigned int planeSize(unsigned int height, unsigned int plane,
> +			       unsigned int stride) 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;
> diff --git a/src/android/mm/generic_camera_buffer.cpp b/src/android/mm/generic_camera_buffer.cpp
> index 22efc4d4b13a..93aa5821e470 100644
> --- a/src/android/mm/generic_camera_buffer.cpp
> +++ b/src/android/mm/generic_camera_buffer.cpp
> @@ -108,16 +108,9 @@ CameraBuffer::Private::Private([[maybe_unused]] CameraBuffer *cameraBuffer,
>  
>  	unsigned int offset = 0;
>  	for (unsigned int i = 0; i < numPlanes; ++i) {
> -		/*
> -		 * \todo Remove if this plane size computation function is
> -		 * added to PixelFormatInfo.
> -		 */
> -		const unsigned int vertSubSample = info.planes[i].verticalSubSampling;
> -		const unsigned int stride = info.stride(size.width, i, 1u);
> -		const unsigned int planeSize =
> -			stride * ((size.height + vertSubSample - 1) / vertSubSample);
> +		const unsigned int planeSize = info.planeSize(size, i);
>  
> -		planeInfo_[i].stride = stride;
> +		planeInfo_[i].stride = info.stride(size.width, i, 1u);
>  		planeInfo_[i].offset = offset;
>  		planeInfo_[i].size = planeSize;
>  
> diff --git a/src/android/yuv/post_processor_yuv.cpp b/src/android/yuv/post_processor_yuv.cpp
> index 6952fc38b0ef..7b3b49609cb1 100644
> --- a/src/android/yuv/post_processor_yuv.cpp
> +++ b/src/android/yuv/post_processor_yuv.cpp
> @@ -134,11 +134,9 @@ void PostProcessorYuv::calculateLengths(const StreamConfiguration &inCfg,
>  		sourceStride_[i] = inCfg.stride;
>  		destinationStride_[i] = nv12Info.stride(destinationSize_.width, i, 1);
>  
> -		const unsigned int vertSubSample =
> -			nv12Info.planes[i].verticalSubSampling;
> -		sourceLength_[i] = sourceStride_[i] *
> -			((sourceSize_.height + vertSubSample - 1) / vertSubSample);
> -		destinationLength_[i] = destinationStride_[i] *
> -			((destinationSize_.height + vertSubSample - 1) / vertSubSample);
> +		sourceLength_[i] = nv12Info.planeSize(sourceSize_.height, i,
> +						      sourceStride_[i]);
> +		destinationLength_[i] = nv12Info.planeSize(destinationSize_.height, i,
> +							   destinationStride_[i]);
>  	}
>  }
> diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp
> index 603d88619fe0..76be93bc1c5c 100644
> --- a/src/libcamera/formats.cpp
> +++ b/src/libcamera/formats.cpp
> @@ -11,6 +11,7 @@
>  #include <errno.h>
>  
>  #include <libcamera/base/log.h>
> +#include <libcamera/base/utils.h>
>  
>  #include <libcamera/formats.h>
>  
> @@ -801,32 +802,85 @@ unsigned int PixelFormatInfo::stride(unsigned int width, unsigned int plane,
>  }
>  
>  /**
> - * \brief Compute the number of bytes necessary to store a frame
> + * \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 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.
> + * 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;
> +
> +	unsigned int vertSubSample = planes[plane].verticalSubSampling;
> +	if (!vertSubSample)
> +		return 0;
> +
> +	/* stride * ceil(height / verticalSubSampling) */
> +	return stride * ((size.height + vertSubSample - 1) / vertSubSample);
> +}
> +
> +/**
> + * \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
>  {
> -	/* 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);
> +
> +	for (const auto &[i, plane] : utils::enumerate(planes)) {
> +		if (plane.bytesPerGroup == 0)
> +			break;
> +
> +		sum += planeSize(size, i, align);
>  	}
>  
>  	return sum;
> diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
> index 4e1c2b7cef5e..adabd4720668 100644
> --- a/src/libcamera/v4l2_videodevice.cpp
> +++ b/src/libcamera/v4l2_videodevice.cpp
> @@ -1337,11 +1337,7 @@ std::unique_ptr<FrameBuffer> V4L2VideoDevice::createBuffer(unsigned int index)
>  			planes[i].offset = offset;
>  
>  			/* \todo Take the V4L2 stride into account */
> -			const unsigned int vertSubSample =
> -				info.planes[i].verticalSubSampling;
> -			planes[i].length =
> -				info.stride(format_.size.width, i, 1u) *
> -				((format_.size.height + vertSubSample - 1) / vertSubSample);
> +			planes[i].length = info.planeSize(format_.size, i);
>  			offset += planes[i].length;
>  		}
>  	}
> 


More information about the libcamera-devel mailing list