[libcamera-devel] [PATCH 6/6] v4l2: v4l2_camera_proxy: Use libcamera formats

Laurent Pinchart laurent.pinchart at ideasonboard.com
Tue Jun 30 00:30:13 CEST 2020


Hi Paul,

Thank you for the patch.

On Tue, Jun 30, 2020 at 12:14:11AM +0900, Paul Elder wrote:
> Now that calculation of bytes per line, image size, and conversions to
> and from v4l2 and drm formats have been moved into libcamera core,
> removed them from V4L2CameraProxy. This has a positive side-effect of
> cleaning up the code.
> 
> Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
> ---
>  src/v4l2/v4l2_camera_proxy.cpp | 167 +++++++--------------------------
>  src/v4l2/v4l2_camera_proxy.h   |   7 --
>  2 files changed, 36 insertions(+), 138 deletions(-)
> 
> diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp
> index c246570..0869797 100644
> --- a/src/v4l2/v4l2_camera_proxy.cpp
> +++ b/src/v4l2/v4l2_camera_proxy.cpp
> @@ -20,6 +20,7 @@
>  #include <libcamera/formats.h>
>  #include <libcamera/object.h>
>  
> +#include "libcamera/internal/formats.h"
>  #include "libcamera/internal/log.h"
>  #include "libcamera/internal/utils.h"
>  
> @@ -164,22 +165,21 @@ bool V4L2CameraProxy::validateMemoryType(uint32_t memory)
>  
>  void V4L2CameraProxy::setFmtFromConfig(StreamConfiguration &streamConfig)
>  {
> -	curV4L2Format_.fmt.pix.width = streamConfig.size.width;
> -	curV4L2Format_.fmt.pix.height = streamConfig.size.height;
> -	curV4L2Format_.fmt.pix.pixelformat = drmToV4L2(streamConfig.pixelFormat);
> -	curV4L2Format_.fmt.pix.field = V4L2_FIELD_NONE;
> -	curV4L2Format_.fmt.pix.bytesperline =
> -		bplMultiplier(curV4L2Format_.fmt.pix.pixelformat) *
> -		curV4L2Format_.fmt.pix.width;
> -	curV4L2Format_.fmt.pix.sizeimage =
> -		imageSize(curV4L2Format_.fmt.pix.pixelformat,
> -			  curV4L2Format_.fmt.pix.width,
> -			  curV4L2Format_.fmt.pix.height);
> -	curV4L2Format_.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
> -	curV4L2Format_.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
> -	curV4L2Format_.fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
> +	PixelFormatInfo formatInfo = PixelFormatInfo::info(streamConfig.pixelFormat);

This should be a const reference. Same for other locations below. I
would delete the copy constructor and assignement operators for
PixelFormatInfo, but that will mess up initialization of the static map
:-S

> +	unsigned int width = streamConfig.size.width;
> +	unsigned int height = streamConfig.size.height;
> +
> +	curV4L2Format_.fmt.pix.width        = width;
> +	curV4L2Format_.fmt.pix.height       = height;
> +	curV4L2Format_.fmt.pix.pixelformat  = formatInfo.v4l2Format;
> +	curV4L2Format_.fmt.pix.field        = V4L2_FIELD_NONE;
> +	curV4L2Format_.fmt.pix.bytesperline = formatInfo.bytesPerLine(width);
> +	curV4L2Format_.fmt.pix.sizeimage    = formatInfo.imageSize(width, height);
> +	curV4L2Format_.fmt.pix.colorspace   = V4L2_COLORSPACE_SRGB;
> +	curV4L2Format_.fmt.pix.priv         = V4L2_PIX_FMT_PRIV_MAGIC;
> +	curV4L2Format_.fmt.pix.ycbcr_enc    = V4L2_YCBCR_ENC_DEFAULT;
>  	curV4L2Format_.fmt.pix.quantization = V4L2_QUANTIZATION_DEFAULT;
> -	curV4L2Format_.fmt.pix.xfer_func = V4L2_XFER_FUNC_DEFAULT;
> +	curV4L2Format_.fmt.pix.xfer_func    = V4L2_XFER_FUNC_DEFAULT;
>  }
>  
>  unsigned int V4L2CameraProxy::calculateSizeImage(StreamConfiguration &streamConfig)
> @@ -188,9 +188,11 @@ unsigned int V4L2CameraProxy::calculateSizeImage(StreamConfiguration &streamConf
>  	 * \todo Merge this method with setFmtFromConfig (need imageSize to
>  	 * support all libcamera formats first, or filter out MJPEG for now).
>  	 */
> -	return imageSize(drmToV4L2(streamConfig.pixelFormat),
> -			 streamConfig.size.width,
> -			 streamConfig.size.height);
> +	PixelFormatInfo formatInfo = PixelFormatInfo::info(streamConfig.pixelFormat);
> +	unsigned int width = streamConfig.size.width;
> +	unsigned int height = streamConfig.size.height;
> +
> +	return formatInfo.imageSize(width, height);

In this case I would skip the local width and height variables. I wonder
if PixelFormatInfo::imageSize(unsigned int width, unsigned int height)
shouldn't become PixelFormatInfo::imageSize(const Size &size), so you could write

	return formatInfo.imageSize(streamConfig.size);

>  }
>  
>  void V4L2CameraProxy::querycap(std::shared_ptr<Camera> camera)
> @@ -253,12 +255,13 @@ int V4L2CameraProxy::vidioc_enum_framesizes(V4L2CameraFile *file, struct v4l2_fr
>  {
>  	LOG(V4L2Compat, Debug) << "Servicing vidioc_enum_framesizes fd = " << file->efd();
>  
> -	PixelFormat argFormat = v4l2ToDrm(arg->pixel_format);
> +	V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->pixel_format);
> +	PixelFormat format = PixelFormatInfo::info(v4l2Format).format;
>  	/*
>  	 * \todo This might need to be expanded as few pipeline handlers
>  	 * report StreamFormats.
>  	 */
> -	const std::vector<Size> &frameSizes = streamConfig_.formats().sizes(argFormat);
> +	const std::vector<Size> &frameSizes = streamConfig_.formats().sizes(format);
>  
>  	if (arg->index >= frameSizes.size())
>  		return -EINVAL;
> @@ -284,7 +287,8 @@ int V4L2CameraProxy::vidioc_enum_fmt(V4L2CameraFile *file, struct v4l2_fmtdesc *
>  	/* \todo Add map from format to description. */
>  	utils::strlcpy(reinterpret_cast<char *>(arg->description),
>  		       "Video Format Description", sizeof(arg->description));
> -	arg->pixelformat = drmToV4L2(streamConfig_.formats().pixelformats()[arg->index]);
> +	arg->pixelformat =
> +		PixelFormatInfo::info(streamConfig_.formats().pixelformats()[arg->index]).v4l2Format;

A local PixelFormat variable could make this more readable.

>  
>  	memset(arg->reserved, 0, sizeof(arg->reserved));
>  
> @@ -306,7 +310,8 @@ int V4L2CameraProxy::vidioc_g_fmt(V4L2CameraFile *file, struct v4l2_format *arg)
>  
>  void V4L2CameraProxy::tryFormat(struct v4l2_format *arg)
>  {
> -	PixelFormat format = v4l2ToDrm(arg->fmt.pix.pixelformat);
> +	V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat);
> +	PixelFormat format = PixelFormatInfo::info(v4l2Format).format;
>  	const std::vector<PixelFormat> &formats =
>  		streamConfig_.formats().pixelformats();
>  	if (std::find(formats.begin(), formats.end(), format) == formats.end())
> @@ -317,15 +322,14 @@ void V4L2CameraProxy::tryFormat(struct v4l2_format *arg)
>  	if (std::find(sizes.begin(), sizes.end(), size) == sizes.end())
>  		size = streamConfig_.formats().sizes(format)[0];
>  
> +	PixelFormatInfo formatInfo = PixelFormatInfo::info(format);
> +
>  	arg->fmt.pix.width        = size.width;
>  	arg->fmt.pix.height       = size.height;
> -	arg->fmt.pix.pixelformat  = drmToV4L2(format);
> +	arg->fmt.pix.pixelformat  = formatInfo.v4l2Format;
>  	arg->fmt.pix.field        = V4L2_FIELD_NONE;
> -	arg->fmt.pix.bytesperline = bplMultiplier(drmToV4L2(format)) *
> -				    arg->fmt.pix.width;
> -	arg->fmt.pix.sizeimage    = imageSize(drmToV4L2(format),
> -					      arg->fmt.pix.width,
> -					      arg->fmt.pix.height);
> +	arg->fmt.pix.bytesperline = formatInfo.bytesPerLine(size.width);
> +	arg->fmt.pix.sizeimage    = formatInfo.imageSize(size.width, size.height);
>  	arg->fmt.pix.colorspace   = V4L2_COLORSPACE_SRGB;
>  	arg->fmt.pix.priv         = V4L2_PIX_FMT_PRIV_MAGIC;
>  	arg->fmt.pix.ycbcr_enc    = V4L2_YCBCR_ENC_DEFAULT;
> @@ -350,8 +354,9 @@ int V4L2CameraProxy::vidioc_s_fmt(V4L2CameraFile *file, struct v4l2_format *arg)
>  	tryFormat(arg);
>  
>  	Size size(arg->fmt.pix.width, arg->fmt.pix.height);
> +	V4L2PixelFormat v4l2Format = V4L2PixelFormat(arg->fmt.pix.pixelformat);
>  	ret = vcam_->configure(&streamConfig_, size,
> -			       v4l2ToDrm(arg->fmt.pix.pixelformat),
> +			       PixelFormatInfo::info(v4l2Format).format,
>  			       bufferCount_);
>  	if (ret < 0)
>  		return -EINVAL;
> @@ -495,8 +500,9 @@ int V4L2CameraProxy::vidioc_reqbufs(V4L2CameraFile *file, struct v4l2_requestbuf
>  		freeBuffers();
>  
>  	Size size(curV4L2Format_.fmt.pix.width, curV4L2Format_.fmt.pix.height);
> +	V4L2PixelFormat v4l2Format = V4L2PixelFormat(curV4L2Format_.fmt.pix.pixelformat);
>  	int ret = vcam_->configure(&streamConfig_, size,
> -				   v4l2ToDrm(curV4L2Format_.fmt.pix.pixelformat),
> +				   PixelFormatInfo::info(v4l2Format).format,
>  				   arg->count);
>  	if (ret < 0)
>  		return -EINVAL;
> @@ -835,104 +841,3 @@ void V4L2CameraProxy::release(V4L2CameraFile *file)
>  
>  	owner_ = nullptr;
>  }
> -
> -struct PixelFormatPlaneInfo {
> -	unsigned int bitsPerPixel;
> -	unsigned int hSubSampling;
> -	unsigned int vSubSampling;
> -};
> -
> -struct PixelFormatInfo {
> -	PixelFormat format;
> -	uint32_t v4l2Format;
> -	unsigned int numPlanes;
> -	std::array<PixelFormatPlaneInfo, 3> planes;
> -};
> -
> -namespace {
> -
> -static const std::array<PixelFormatInfo, 16> pixelFormatInfo = {{
> -	/* RGB formats. */
> -	{ formats::RGB888,	V4L2_PIX_FMT_BGR24,	1, {{ { 24, 1, 1 }, {  0, 0, 0 }, {  0, 0, 0 } }} },
> -	{ formats::BGR888,	V4L2_PIX_FMT_RGB24,	1, {{ { 24, 1, 1 }, {  0, 0, 0 }, {  0, 0, 0 } }} },
> -	{ formats::BGRA8888,	V4L2_PIX_FMT_ARGB32,	1, {{ { 32, 1, 1 }, {  0, 0, 0 }, {  0, 0, 0 } }} },
> -	/* YUV packed formats. */
> -	{ formats::UYVY,	V4L2_PIX_FMT_UYVY,	1, {{ { 16, 1, 1 }, {  0, 0, 0 }, {  0, 0, 0 } }} },
> -	{ formats::VYUY,	V4L2_PIX_FMT_VYUY,	1, {{ { 16, 1, 1 }, {  0, 0, 0 }, {  0, 0, 0 } }} },
> -	{ formats::YUYV,	V4L2_PIX_FMT_YUYV,	1, {{ { 16, 1, 1 }, {  0, 0, 0 }, {  0, 0, 0 } }} },
> -	{ formats::YVYU,	V4L2_PIX_FMT_YVYU,	1, {{ { 16, 1, 1 }, {  0, 0, 0 }, {  0, 0, 0 } }} },
> -	/* YUY planar formats. */
> -	{ formats::NV12,	V4L2_PIX_FMT_NV12,	2, {{ {  8, 1, 1 }, { 16, 2, 2 }, {  0, 0, 0 } }} },
> -	{ formats::NV21,	V4L2_PIX_FMT_NV21,	2, {{ {  8, 1, 1 }, { 16, 2, 2 }, {  0, 0, 0 } }} },
> -	{ formats::NV16,	V4L2_PIX_FMT_NV16,	2, {{ {  8, 1, 1 }, { 16, 2, 1 }, {  0, 0, 0 } }} },
> -	{ formats::NV61,	V4L2_PIX_FMT_NV61,	2, {{ {  8, 1, 1 }, { 16, 2, 1 }, {  0, 0, 0 } }} },
> -	{ formats::NV24,	V4L2_PIX_FMT_NV24,	2, {{ {  8, 1, 1 }, { 16, 1, 1 }, {  0, 0, 0 } }} },
> -	{ formats::NV42,	V4L2_PIX_FMT_NV42,	2, {{ {  8, 1, 1 }, { 16, 1, 1 }, {  0, 0, 0 } }} },
> -	{ formats::YUV420,	V4L2_PIX_FMT_YUV420,	3, {{ {  8, 1, 1 }, {  8, 2, 2 }, {  8, 2, 2 } }} },
> -	{ formats::YUV422,	V4L2_PIX_FMT_YUV422P,	3, {{ {  8, 1, 1 }, {  8, 2, 1 }, {  8, 2, 1 } }} },
> -	/* Compressed formats. */
> -	/*
> -	 * \todo Get a better image size estimate for MJPEG, via
> -	 * StreamConfiguration, instead of using the worst-case
> -	 * width * height * bpp of uncompressed data.
> -	 */
> -	{ formats::MJPEG,	V4L2_PIX_FMT_MJPEG,	1, {{ { 16, 1, 1 }, {  0, 0, 0 }, {  0, 0, 0 } }} },
> -}};
> -
> -} /* namespace */
> -
> -/* \todo make libcamera export these */
> -unsigned int V4L2CameraProxy::bplMultiplier(uint32_t format)
> -{
> -	auto info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(),
> -				 [format](const PixelFormatInfo &info) {
> -					 return info.v4l2Format == format;
> -				 });
> -	if (info == pixelFormatInfo.end())
> -		return 0;
> -
> -	return info->planes[0].bitsPerPixel / 8;
> -}
> -
> -unsigned int V4L2CameraProxy::imageSize(uint32_t format, unsigned int width,
> -					unsigned int height)
> -{
> -	auto info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(),
> -				 [format](const PixelFormatInfo &info) {
> -					 return info.v4l2Format == format;
> -				 });
> -	if (info == pixelFormatInfo.end())
> -		return 0;
> -
> -	unsigned int multiplier = 0;
> -	for (unsigned int i = 0; i < info->numPlanes; ++i)
> -		multiplier += info->planes[i].bitsPerPixel
> -			    / info->planes[i].hSubSampling
> -			    / info->planes[i].vSubSampling;
> -
> -	return width * height * multiplier / 8;
> -}
> -
> -PixelFormat V4L2CameraProxy::v4l2ToDrm(uint32_t format)
> -{
> -	auto info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(),
> -				 [format](const PixelFormatInfo &info) {
> -					 return info.v4l2Format == format;
> -				 });
> -	if (info == pixelFormatInfo.end())
> -		return PixelFormat();
> -
> -	return info->format;
> -}
> -
> -uint32_t V4L2CameraProxy::drmToV4L2(const PixelFormat &format)
> -{
> -	auto info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(),
> -				 [format](const PixelFormatInfo &info) {
> -					 return info.format == format;
> -				 });
> -	if (info == pixelFormatInfo.end())
> -		return format;
> -
> -	return info->v4l2Format;
> -}
> diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h
> index d78a472..49184a1 100644
> --- a/src/v4l2/v4l2_camera_proxy.h
> +++ b/src/v4l2/v4l2_camera_proxy.h
> @@ -69,13 +69,6 @@ private:
>  	int acquire(V4L2CameraFile *file);
>  	void release(V4L2CameraFile *file);
>  
> -	static unsigned int bplMultiplier(uint32_t format);
> -	static unsigned int imageSize(uint32_t format, unsigned int width,
> -				      unsigned int height);
> -
> -	static PixelFormat v4l2ToDrm(uint32_t format);
> -	static uint32_t drmToV4L2(const PixelFormat &format);
> -
>  	static const std::set<unsigned long> supportedIoctls_;
>  
>  	unsigned int refcount_;

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list