libcamera: v4l2_device: Add methods to get/set format

Add methods to set and get the image format programmed on a V4L2Device
for both the single and multi planar use case.

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
Jacopo Mondi 2019-01-21 17:27:55 +01:00
parent 267b91373b
commit ba8da0f2fc
2 changed files with 138 additions and 0 deletions

View file

@ -86,10 +86,20 @@ public:
const char *deviceName() const { return caps_.card(); }
const char *busName() const { return caps_.bus_info(); }
int format(V4L2DeviceFormat *fmt);
int setFormat(V4L2DeviceFormat *fmt);
private:
int getFormatSingleplane(V4L2DeviceFormat *fmt);
int setFormatSingleplane(V4L2DeviceFormat *fmt);
int getFormatMultiplane(V4L2DeviceFormat *fmt);
int setFormatMultiplane(V4L2DeviceFormat *fmt);
std::string deviceNode_;
int fd_;
V4L2Capability caps_;
enum v4l2_buf_type bufferType_;
};
} /* namespace libcamera */

View file

@ -227,6 +227,15 @@ int V4L2Device::open()
return -EINVAL;
}
if (caps_.isCapture())
bufferType_ = caps_.isMultiplanar()
? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
: V4L2_BUF_TYPE_VIDEO_CAPTURE;
else
bufferType_ = caps_.isMultiplanar()
? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
: V4L2_BUF_TYPE_VIDEO_OUTPUT;
return 0;
}
@ -269,4 +278,123 @@ void V4L2Device::close()
* \return The string containing the device location
*/
/**
* \brief Retrieve the image format set on the V4L2 device
* \return 0 for success, a negative error code otherwise
*/
int V4L2Device::format(V4L2DeviceFormat *fmt)
{
return caps_.isMultiplanar() ? getFormatMultiplane(fmt) :
getFormatSingleplane(fmt);
}
/**
* \brief Configure an image format on the V4L2 device
* \return 0 for success, a negative error code otherwise
*/
int V4L2Device::setFormat(V4L2DeviceFormat *fmt)
{
return caps_.isMultiplanar() ? setFormatMultiplane(fmt) :
setFormatSingleplane(fmt);
}
int V4L2Device::getFormatSingleplane(V4L2DeviceFormat *fmt)
{
struct v4l2_format v4l2Fmt;
struct v4l2_pix_format *pix = &v4l2Fmt.fmt.pix;
int ret;
v4l2Fmt.type = bufferType_;
ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Fmt);
if (ret) {
ret = -errno;
LOG(Error) << "Unable to get format: " << strerror(-ret);
return ret;
}
fmt->width = pix->width;
fmt->height = pix->height;
fmt->fourcc = pix->pixelformat;
fmt->planes = 1;
fmt->planesFmt[0].bpl = pix->bytesperline;
fmt->planesFmt[0].size = pix->sizeimage;
return 0;
}
int V4L2Device::setFormatSingleplane(V4L2DeviceFormat *fmt)
{
struct v4l2_format v4l2Fmt;
struct v4l2_pix_format *pix = &v4l2Fmt.fmt.pix;
int ret;
v4l2Fmt.type = bufferType_;
pix->width = fmt->width;
pix->height = fmt->height;
pix->pixelformat = fmt->fourcc;
ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Fmt);
if (ret) {
ret = -errno;
LOG(Error) << "Unable to set format: " << strerror(-ret);
return ret;
}
return 0;
}
int V4L2Device::getFormatMultiplane(V4L2DeviceFormat *fmt)
{
struct v4l2_format v4l2Fmt;
struct v4l2_pix_format_mplane *pix = &v4l2Fmt.fmt.pix_mp;
int ret;
v4l2Fmt.type = bufferType_;
ret = ioctl(fd_, VIDIOC_G_FMT, &v4l2Fmt);
if (ret) {
ret = -errno;
LOG(Error) << "Unable to get format: " << strerror(-ret);
return ret;
}
fmt->width = pix->width;
fmt->height = pix->height;
fmt->fourcc = pix->pixelformat;
fmt->planes = pix->num_planes;
for (unsigned int i = 0; i < fmt->planes; ++i) {
fmt->planesFmt[i].bpl = pix->plane_fmt[i].bytesperline;
fmt->planesFmt[i].size = pix->plane_fmt[i].sizeimage;
}
return 0;
}
int V4L2Device::setFormatMultiplane(V4L2DeviceFormat *fmt)
{
struct v4l2_format v4l2Fmt;
struct v4l2_pix_format_mplane *pix = &v4l2Fmt.fmt.pix_mp;
int ret;
v4l2Fmt.type = bufferType_;
pix->width = fmt->width;
pix->height = fmt->height;
pix->pixelformat = fmt->fourcc;
pix->num_planes = fmt->planes;
for (unsigned int i = 0; i < pix->num_planes; ++i) {
pix->plane_fmt[i].bytesperline = fmt->planesFmt[i].bpl;
pix->plane_fmt[i].sizeimage = fmt->planesFmt[i].size;
}
ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Fmt);
if (ret) {
ret = -errno;
LOG(Error) << "Unable to set format: " << strerror(-ret);
return ret;
}
return 0;
}
} /* namespace libcamera */