[libcamera-devel] [PATCH v3 5/6] libcamera: v4l2_videodevice: Match formats supported by the device

Laurent Pinchart laurent.pinchart at ideasonboard.com
Fri Jul 29 20:39:53 CEST 2022


Hi Jacopo,

Thank you for the patch.

On Fri, Jul 29, 2022 at 06:00:13PM +0200, Jacopo Mondi via libcamera-devel wrote:
> Now that V4L2PixelFormat::fromPixelFormat() returns a list of formats
> to chose from, select the one supported by the video device by matching
> against the list of supported pixel formats.
> 
> The first format found to match one of the device supported ones is
> returned.
> 
> As the list of pixel formats supported by the video device does not
> change at run-time, cache it at device open() time.
> 
> Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> ---
>  include/libcamera/internal/v4l2_videodevice.h |  1 +
>  src/libcamera/v4l2_videodevice.cpp            | 28 +++++++++++++++----
>  2 files changed, 24 insertions(+), 5 deletions(-)
> 
> diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h
> index 29fa0bbaf670..6fe81d5e4cf0 100644
> --- a/include/libcamera/internal/v4l2_videodevice.h
> +++ b/include/libcamera/internal/v4l2_videodevice.h
> @@ -268,6 +268,7 @@ private:
>  	V4L2Capability caps_;
>  	V4L2DeviceFormat format_;
>  	const PixelFormatInfo *formatInfo_;
> +	std::vector<V4L2PixelFormat> pixelFormats_;
>  
>  	enum v4l2_buf_type bufferType_;
>  	enum v4l2_memory memoryType_;
> diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
> index 2ca22f485d45..0aeaae6ad573 100644
> --- a/src/libcamera/v4l2_videodevice.cpp
> +++ b/src/libcamera/v4l2_videodevice.cpp
> @@ -633,6 +633,8 @@ int V4L2VideoDevice::open()
>  		<< "Opened device " << caps_.bus_info() << ": "
>  		<< caps_.driver() << ": " << caps_.card();
>  
> +	pixelFormats_ = enumPixelformats(0);
> +
>  	ret = getFormat(&format_);
>  	if (ret) {
>  		LOG(V4L2, Error) << "Failed to get format";
> @@ -726,6 +728,8 @@ int V4L2VideoDevice::open(SharedFD handle, enum v4l2_buf_type type)
>  		<< "Opened device " << caps_.bus_info() << ": "
>  		<< caps_.driver() << ": " << caps_.card();
>  
> +	pixelFormats_ = enumPixelformats(0);
> +
>  	ret = getFormat(&format_);
>  	if (ret) {
>  		LOG(V4L2, Error) << "Failed to get format";
> @@ -1990,17 +1994,31 @@ V4L2VideoDevice::fromEntityName(const MediaDevice *media,
>  }
>  
>  /**
> - * \brief Convert \a PixelFormat to its corresponding V4L2 FourCC
> + * \brief Convert \a PixelFormat to one of the device supported V4L2 FourCC

 * \brief Convert \a PixelFormat to a V4L2PixelFormat supported by the device

>   * \param[in] pixelFormat The PixelFormat to convert
>   *
> - * The V4L2 format variant the function returns the contiguous version
> - * unconditionally.
> + * Convert a\ pixelformat to a V4L2 FourCC that is known to be supported by

s/a\/\a/

> + * the video device.
>   *
> - * \return The V4L2_PIX_FMT_* pixel format code corresponding to \a pixelFormat
> + * \return The V4L2PixelFormat corresponding to \a pixelFormat or an invalid
> + * PixelFormat if \a pixelFormat is not supported by the video device

s/PixelFormat/V4L2PixelFormat/

I'd expand this as it's also meant to cover the JPEG vs. MJPEG case:

 * A V4L2VideoDevice may support different V4L2 pixel formats that map the same
 * PixelFormat. This is the case of the contiguous and non-contiguous variants
 * of multiplanar formats, and with the V4L2 MJPEG and JPEG pixel formats.
 * Converting a PixelFormat to a V4L2PixelFormat may thus have multiple answers.
 *
 * This function converts the \a pixelFormat using the list of V4L2 pixel
 * formats that the V4L2VideoDevice supports. This guarantees that the returned
 * V4L2PixelFormat will be valid for the device. If multiple matches are still
 * possible, contiguous variants are preferred. If the \a pixelFormat is not
 * supported by the device, the function returns an invalid V4L2PixelFormat.
 *
 * \return The V4L2PixelFormat corresponding to \a pixelFormat if supported by
 * the device, or an invalid V4L2PixelFormat otherwise

>   */
>  V4L2PixelFormat V4L2VideoDevice::toV4L2PixelFormat(const PixelFormat &pixelFormat) const
>  {
> -	return V4L2PixelFormat::fromPixelFormat(pixelFormat)[0];
> +	std::vector<V4L2PixelFormat> v4l2PixelFormats =

	const std::vector<V4L2PixelFormat> &v4l2PixelFormats =

> +		V4L2PixelFormat::fromPixelFormat(pixelFormat);
> +
> +	for (const V4L2PixelFormat &v4l2Format : v4l2PixelFormats) {
> +		auto it = std::find_if(pixelFormats_.begin(), pixelFormats_.end(),
> +				       [&v4l2Format](const V4L2PixelFormat &devFormat) {
> +					       return v4l2Format == devFormat;
> +				       });
> +
> +		if (it != pixelFormats_.end())
> +			return v4l2Format;

Should we convert pixelFormats_ to a std::unordered_set to make the
lookup more efficient ?

Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

> +	}
> +
> +	return {};
>  }
>  
>  /**

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list