[libcamera-devel] [PATCH v3 2/8] libcamera: v4l2_subdevice: Implement ENUM_FRAME_SIZES

Kieran Bingham kieran.bingham at ideasonboard.com
Wed Feb 27 00:19:40 CET 2019


Hi Jacopo,

On 26/02/2019 16:26, Jacopo Mondi wrote:
> Implement enumFormat() methods to enumerate the available image
> resolutions on the subdevice.
> 
> Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> ---
>  src/libcamera/include/v4l2_subdevice.h |   9 ++
>  src/libcamera/v4l2_subdevice.cpp       | 118 +++++++++++++++++++++++++
>  2 files changed, 127 insertions(+)
> 
> diff --git a/src/libcamera/include/v4l2_subdevice.h b/src/libcamera/include/v4l2_subdevice.h
> index eac699a06109..6b21308d2087 100644
> --- a/src/libcamera/include/v4l2_subdevice.h
> +++ b/src/libcamera/include/v4l2_subdevice.h
> @@ -7,7 +7,9 @@
>  #ifndef __LIBCAMERA_V4L2_SUBDEVICE_H__
>  #define __LIBCAMERA_V4L2_SUBDEVICE_H__
>  
> +#include <map>
>  #include <string>
> +#include <vector>
>  
>  #include "media_object.h"
>  
> @@ -38,15 +40,22 @@ public:
>  	int setCrop(unsigned int pad, Rectangle *rect);
>  	int setCompose(unsigned int pad, Rectangle *rect);
>  
> +	std::vector<V4L2SubdeviceFormat> &formats(unsigned int pad);
>  	int getFormat(unsigned int pad, V4L2SubdeviceFormat *format);
>  	int setFormat(unsigned int pad, V4L2SubdeviceFormat *format);
>  
>  private:
> +	int listPadSizes(unsigned int pad, unsigned int mbus_code,
> +			 std::vector<V4L2SubdeviceFormat> *formats);
> +	std::vector<V4L2SubdeviceFormat> listPadFormats(unsigned int pad);


The word 'list' seems a bit redundant in 'listPadSizes()' and
'listPadFormats()' ... and seems a bit hungarian notation to me?

Other than that, I trust that the tests that follow make sure the code
is doing something sane :)


I can't see anything jump out at me yet.


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



> +
>  	int setSelection(unsigned int pad, unsigned int target,
>  			 Rectangle *rect);
>  
>  	const MediaEntity *entity_;
>  	int fd_;
> +
> +	std::map<unsigned int, std::vector<V4L2SubdeviceFormat>> formats_;
>  };
>  
>  } /* namespace libcamera */
> diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp
> index 56ecf3851cb0..f81a521f9e2a 100644
> --- a/src/libcamera/v4l2_subdevice.cpp
> +++ b/src/libcamera/v4l2_subdevice.cpp
> @@ -5,6 +5,10 @@
>   * v4l2_subdevice.cpp - V4L2 Subdevice
>   */
>  
> +#include <map>
> +#include <string>
> +#include <vector>
> +
>  #include <fcntl.h>
>  #include <string.h>
>  #include <sys/ioctl.h>
> @@ -116,6 +120,9 @@ int V4L2Subdevice::open()
>  	}
>  	fd_ = ret;
>  
> +	for (MediaPad *pad : entity_->pads())
> +		formats_[pad->index()] = listPadFormats(pad->index());
> +
>  	return 0;
>  }
>  
> @@ -178,6 +185,25 @@ int V4L2Subdevice::setCompose(unsigned int pad, Rectangle *rect)
>  	return setSelection(pad, V4L2_SEL_TGT_COMPOSE, rect);
>  }
>  
> +/**
> + * \brief List the sub-device image resolutions and formats on \a pad
> + * \param[in] pad The 0-indexed pad number to enumerate formats on
> + *
> + * \return A vector of image formats, or an empty vector if the pad does not
> + * exist
> + */
> +std::vector<V4L2SubdeviceFormat> &V4L2Subdevice::formats(unsigned int pad)
> +{
> +	/*
> +	 * If pad does not exist, return an empty vector at position
> +	 * pads().size()
> +	 */
> +	if (pad > entity_->pads().size())
> +		pad = entity_->pads().size();
> +
> +	return formats_[pad];
> +}
> +
>  /**
>   * \brief Retrieve the image format set on one of the V4L2 subdevice pads
>   * \param[in] pad The 0-indexed pad number the format is to be retrieved from
> @@ -242,6 +268,98 @@ int V4L2Subdevice::setFormat(unsigned int pad, V4L2SubdeviceFormat *format)
>  	return 0;
>  }
>  
> +int V4L2Subdevice::listPadSizes(unsigned int pad, unsigned int mbus_code,
> +				std::vector<V4L2SubdeviceFormat> *formats)
> +{
> +	struct v4l2_subdev_frame_size_enum sizeEnum = {};
> +	int ret;
> +
> +	sizeEnum.index = 0;
> +	sizeEnum.pad = pad;
> +	sizeEnum.code = mbus_code;
> +	sizeEnum.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> +
> +	while (!(ret = ioctl(fd_, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &sizeEnum))) {
> +		V4L2SubdeviceFormat minFormat = {
> +			.mbus_code = mbus_code,
> +			.width = sizeEnum.min_width,
> +			.height = sizeEnum.min_height,
> +		};
> +		formats->push_back(minFormat);
> +
> +		/*
> +		 * Most subdevices report discrete frame resolutions, where
> +		 * min and max sizes are identical. For continue frame
> +		 * resolutions, store the min and max sizes interval.
> +		 */
> +		if (sizeEnum.min_width == sizeEnum.max_width &&
> +		    sizeEnum.min_height == sizeEnum.max_height) {
> +			sizeEnum.index++;
> +			continue;
> +		}
> +
> +		V4L2SubdeviceFormat maxFormat = {
> +			.mbus_code = mbus_code,
> +			.width = sizeEnum.max_width,
> +			.height = sizeEnum.max_height,
> +		};
> +		formats->push_back(maxFormat);
> +
> +		sizeEnum.index++;
> +	}
> +
> +	if (ret && (errno != EINVAL && errno != ENOTTY)) {
> +		LOG(V4L2Subdev, Error)
> +			<< "Unable to enumerate format on pad " << pad
> +			<< " of " << deviceName() << ": "
> +			<< strerror(errno);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +std::vector<V4L2SubdeviceFormat> V4L2Subdevice::listPadFormats(unsigned int pad)
> +{
> +	struct v4l2_subdev_mbus_code_enum mbusEnum = {};
> +	std::vector<V4L2SubdeviceFormat> formats = {};
> +	int ret;
> +
> +	mbusEnum.pad = pad;
> +	mbusEnum.index = 0;
> +	mbusEnum.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> +
> +	while (!(ret = ioctl(fd_, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &mbusEnum))) {
> +		ret = listPadSizes(pad, mbusEnum.code, &formats);
> +		if (ret)
> +			return formats;
> +
> +		mbusEnum.index++;
> +	}
> +
> +	if (ret && (errno != EINVAL && errno != ENOTTY)) {
> +		LOG(V4L2Subdev, Error)
> +			<< "Unable to enumerate format on pad " << pad
> +			<< " of " << deviceName() << ": " << strerror(-ret);
> +		return formats;
> +	}
> +
> +	if (mbusEnum.index == 0 && ret && errno == EINVAL) {
> +		/*
> +		 * The subdevice might not support ENUM_MBUS_CODE but
> +		 * might support ENUM_FRAME_SIZES.
> +		 */
> +		struct V4L2SubdeviceFormat subdevFormat;
> +		ret = getFormat(pad, &subdevFormat);
> +		if (ret)
> +			return formats;
> +
> +		listPadSizes(pad, subdevFormat.mbus_code, &formats);
> +	}
> +
> +	return formats;
> +}
> +
>  int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target,
>  				Rectangle *rect)
>  {
> 

-- 
Regards
--
Kieran


More information about the libcamera-devel mailing list