libcamera: v4l2_subdevice: Implement ENUM_FRAME_SIZES
Implement format and size enumeration methods to list all the available subdevice image resolutions and formats. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
parent
54e6a3eb1f
commit
0559c740f2
4 changed files with 142 additions and 2 deletions
|
@ -46,4 +46,38 @@ namespace libcamera {
|
||||||
* \brief The distance between the top and bottom sides
|
* \brief The distance between the top and bottom sides
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \struct SizeRange
|
||||||
|
* \brief Describe a range of image sizes
|
||||||
|
*
|
||||||
|
* SizeRange describes a range of image sizes included in the (minWidth,
|
||||||
|
* minHeight) - (maxWidth, maxHeight) interval. If the minimum and
|
||||||
|
* maximum sizes are identical it represents a single image resolution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn SizeRange::SizeRange()
|
||||||
|
* \brief Construct a size range
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \var SizeRange::minWidth
|
||||||
|
* \brief The minimum image width
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \var SizeRange::minHeight
|
||||||
|
* \brief The minimum image height
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \var SizeRange::maxWidth
|
||||||
|
* \brief The maximum image width
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \var SizeRange::maxHeight
|
||||||
|
* \brief The maximum image height
|
||||||
|
*/
|
||||||
|
|
||||||
} /* namespace libcamera */
|
} /* namespace libcamera */
|
||||||
|
|
|
@ -17,6 +17,18 @@ struct Rectangle {
|
||||||
unsigned int h;
|
unsigned int h;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SizeRange {
|
||||||
|
SizeRange(unsigned int minW, unsigned int minH,
|
||||||
|
unsigned int maxW, unsigned int maxH)
|
||||||
|
: minWidth(minW), minHeight(minH), maxWidth(maxW),
|
||||||
|
maxHeight(maxH) {}
|
||||||
|
|
||||||
|
unsigned int minWidth;
|
||||||
|
unsigned int minHeight;
|
||||||
|
unsigned int maxWidth;
|
||||||
|
unsigned int maxHeight;
|
||||||
|
};
|
||||||
|
|
||||||
} /* namespace libcamera */
|
} /* namespace libcamera */
|
||||||
|
|
||||||
#endif /* __LIBCAMERA_GEOMETRY_H__ */
|
#endif /* __LIBCAMERA_GEOMETRY_H__ */
|
||||||
|
|
|
@ -7,15 +7,16 @@
|
||||||
#ifndef __LIBCAMERA_V4L2_SUBDEVICE_H__
|
#ifndef __LIBCAMERA_V4L2_SUBDEVICE_H__
|
||||||
#define __LIBCAMERA_V4L2_SUBDEVICE_H__
|
#define __LIBCAMERA_V4L2_SUBDEVICE_H__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "geometry.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "media_object.h"
|
#include "media_object.h"
|
||||||
|
|
||||||
namespace libcamera {
|
namespace libcamera {
|
||||||
|
|
||||||
struct Rectangle;
|
|
||||||
|
|
||||||
struct V4L2SubdeviceFormat {
|
struct V4L2SubdeviceFormat {
|
||||||
uint32_t mbus_code;
|
uint32_t mbus_code;
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
|
@ -39,6 +40,9 @@ public:
|
||||||
int setCrop(unsigned int pad, Rectangle *rect);
|
int setCrop(unsigned int pad, Rectangle *rect);
|
||||||
int setCompose(unsigned int pad, Rectangle *rect);
|
int setCompose(unsigned int pad, Rectangle *rect);
|
||||||
|
|
||||||
|
const std::map<unsigned int, std::vector<SizeRange>>
|
||||||
|
formats(unsigned int pad);
|
||||||
|
|
||||||
int getFormat(unsigned int pad, V4L2SubdeviceFormat *format);
|
int getFormat(unsigned int pad, V4L2SubdeviceFormat *format);
|
||||||
int setFormat(unsigned int pad, V4L2SubdeviceFormat *format);
|
int setFormat(unsigned int pad, V4L2SubdeviceFormat *format);
|
||||||
|
|
||||||
|
@ -46,6 +50,9 @@ protected:
|
||||||
std::string logPrefix() const;
|
std::string logPrefix() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int enumPadSizes(unsigned int pad, unsigned int code,
|
||||||
|
std::vector<SizeRange> *size);
|
||||||
|
|
||||||
int setSelection(unsigned int pad, unsigned int target,
|
int setSelection(unsigned int pad, unsigned int target,
|
||||||
Rectangle *rect);
|
Rectangle *rect);
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,59 @@ int V4L2Subdevice::setCompose(unsigned int pad, Rectangle *rect)
|
||||||
return setSelection(pad, V4L2_SEL_TGT_COMPOSE, 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
|
||||||
|
*
|
||||||
|
* Retrieve a list of image formats and sizes on the \a pad of a video
|
||||||
|
* subdevice. Subdevices can report either a list of discrete sizes they
|
||||||
|
* support or a list of intervals expressed as a [min-max] sizes range.
|
||||||
|
*
|
||||||
|
* Each image size list is associated with a media bus pixel code for which
|
||||||
|
* the reported resolutions are supported.
|
||||||
|
*
|
||||||
|
* \return A map of image formats associated with a list of image sizes, or
|
||||||
|
* an empty map on error or if the pad does not exist
|
||||||
|
*/
|
||||||
|
const std::map<unsigned int, std::vector<SizeRange>>
|
||||||
|
V4L2Subdevice::formats(unsigned int pad)
|
||||||
|
{
|
||||||
|
std::map<unsigned int, std::vector<SizeRange>> formatMap = {};
|
||||||
|
struct v4l2_subdev_mbus_code_enum mbusEnum = {};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (pad >= entity_->pads().size()) {
|
||||||
|
LOG(V4L2Subdev, Error) << "Invalid pad: " << pad;
|
||||||
|
return formatMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbusEnum.pad = pad;
|
||||||
|
mbusEnum.index = 0;
|
||||||
|
mbusEnum.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||||
|
while (true) {
|
||||||
|
ret = ioctl(fd_, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &mbusEnum);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = enumPadSizes(pad, mbusEnum.code,
|
||||||
|
&formatMap[mbusEnum.code]);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
|
||||||
|
mbusEnum.index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret && (errno != EINVAL && errno != ENOTTY)) {
|
||||||
|
ret = -errno;
|
||||||
|
LOG(V4L2Subdev, Error)
|
||||||
|
<< "Unable to enumerate formats on pad " << pad
|
||||||
|
<< ": " << strerror(-ret);
|
||||||
|
formatMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatMap;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Retrieve the image format set on one of the V4L2 subdevice pads
|
* \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
|
* \param[in] pad The 0-indexed pad number the format is to be retrieved from
|
||||||
|
@ -248,6 +301,40 @@ int V4L2Subdevice::setFormat(unsigned int pad, V4L2SubdeviceFormat *format)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int V4L2Subdevice::enumPadSizes(unsigned int pad,unsigned int code,
|
||||||
|
std::vector<SizeRange> *sizes)
|
||||||
|
{
|
||||||
|
struct v4l2_subdev_frame_size_enum sizeEnum = {};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
sizeEnum.index = 0;
|
||||||
|
sizeEnum.pad = pad;
|
||||||
|
sizeEnum.code = code;
|
||||||
|
sizeEnum.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||||
|
while (true) {
|
||||||
|
ret = ioctl(fd_, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &sizeEnum);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
|
||||||
|
sizes->emplace_back(sizeEnum.min_width, sizeEnum.min_height,
|
||||||
|
sizeEnum.max_width, sizeEnum.max_height);
|
||||||
|
|
||||||
|
sizeEnum.index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret && (errno != EINVAL && errno != ENOTTY)) {
|
||||||
|
ret = -errno;
|
||||||
|
LOG(V4L2Subdev, Error)
|
||||||
|
<< "Unable to enumerate sizes on pad " << pad
|
||||||
|
<< ": " << strerror(-ret);
|
||||||
|
sizes->clear();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target,
|
int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target,
|
||||||
Rectangle *rect)
|
Rectangle *rect)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue