From patchwork Sat Jan 26 15:13:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 403 Return-Path: Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 29AC760C78 for ; Sat, 26 Jan 2019 16:13:14 +0100 (CET) Received: from uno.homenet.telecomitalia.it (host20-49-dynamic.18-79-r.retail.telecomitalia.it [79.18.49.20]) (Authenticated sender: jacopo@jmondi.org) by relay11.mail.gandi.net (Postfix) with ESMTPSA id 55906100005; Sat, 26 Jan 2019 15:13:13 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Sat, 26 Jan 2019 16:13:17 +0100 Message-Id: <20190126151318.28087-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190126151318.28087-1-jacopo@jmondi.org> References: <20190126151318.28087-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC 2/3] libcamera: v4l2_device: Add methods to get/set format X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 26 Jan 2019 15:13:14 -0000 Add methods to set and get the image format programmed on a V4L2Device for both the single and multi planar use case. Signed-off-by: Jacopo Mondi --- src/libcamera/include/v4l2_device.h | 13 +++ src/libcamera/v4l2_device.cpp | 131 ++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index ee0c4eb..01dbf45 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -14,6 +14,7 @@ #include #include +#include namespace libcamera { @@ -81,6 +82,9 @@ public: int requestBuffers(unsigned int qty = 8); int requestBuffers(unsigned int qty, std::vector &buffers); + int format(StreamConfiguration *config); + int setFormat(StreamConfiguration *config); + int queueBuffer(FrameBuffer *frame); FrameBuffer *dequeueBuffer(); @@ -93,6 +97,7 @@ private: std::string deviceNode_; int fd_; V4L2Capability caps_; + unsigned int buftype_; enum v4l2_memory memoryType_; enum v4l2_buf_type bufferType_; @@ -101,6 +106,14 @@ private: void bufferAvailable(EventNotifier *notifier); EventNotifier *fdEvent_; + + unsigned int getPlanesFromFormat(unsigned int pixfmt); + unsigned int getBppFromFormat(unsigned int pixfmt); + int getFormatSingleplane(StreamConfiguration *config); + int setFormatSingleplane(StreamConfiguration *config); + + int getFormatMultiplane(StreamConfiguration *config); + int setFormatMultiplane(StreamConfiguration *config); }; } /* namespace libcamera */ diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 4d39c85..d16691d 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -203,6 +203,15 @@ int V4L2Device::open() return -EINVAL; } + if (caps_.isCapture()) + buftype_ = caps_.isMultiplanar() ? + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : + V4L2_BUF_TYPE_VIDEO_CAPTURE; + else + buftype_ = caps_.isMultiplanar() ? + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : + V4L2_BUF_TYPE_VIDEO_OUTPUT; + return 0; } @@ -314,6 +323,26 @@ int V4L2Device::requestBuffers(unsigned int qty, std::vector &buf return 0; } +/** + * \brief Retrieve the image format set on the V4L2 device + * \return 0 for success, a negative error code otherwise + */ +int V4L2Device::format(StreamConfiguration *config) +{ + return caps_.isMultiplanar() ? getFormatMultiplane(config) : + getFormatSingleplane(config); +} + +/** + * \brief Program an image format on the V4L2 device + * \return 0 for success, a negative error code otherwise + */ +int V4L2Device::setFormat(StreamConfiguration *config) +{ + return caps_.isMultiplanar() ? setFormatMultiplane(config) : + setFormatSingleplane(config); +} + int V4L2Device::queueBuffer(FrameBuffer *frame) { struct v4l2_buffer buf = {}; @@ -422,6 +451,108 @@ int V4L2Device::streamOff() } delete fdEvent_; +} + +/* TODO: this is a simple stub at the moment. */ +unsigned int V4L2Device::getPlanesFromFormat(unsigned int pixfmt) +{ + return 1; +} + +/* TODO: this is a simple stub at the moment. */ +unsigned int V4L2Device::getBppFromFormat(unsigned int pixfmt) +{ + return 16; +} + +int V4L2Device::getFormatSingleplane(StreamConfiguration *config) +{ + struct v4l2_format v4l2Fmt; + struct v4l2_pix_format *pix = &v4l2Fmt.fmt.pix; + int ret; + + ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Fmt); + if (ret) { + ret = -errno; + LOG(Error) << "Unable to get format: " << strerror(-ret); + return ret; + } + + config->setWidth(pix->width); + config->setHeight(pix->height); + config->setPixelFormat(pix->pixelformat); + + return 0; +} + +int V4L2Device::setFormatSingleplane(StreamConfiguration *config) +{ + struct v4l2_format v4l2Fmt; + struct v4l2_pix_format *pix = &v4l2Fmt.fmt.pix; + int ret; + + v4l2Fmt.type = buftype_; + pix->width = config->width(); + pix->height = config->height(); + + pix->width = config->width(); + pix->height = config->height(); + pix->pixelformat = config->pixelformat(); + + 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(StreamConfiguration *config) +{ + struct v4l2_format v4l2Fmt; + struct v4l2_pix_format_mplane *pix = &v4l2Fmt.fmt.pix_mp; + int ret; + + ret = ioctl(fd_, VIDIOC_G_FMT, &v4l2Fmt); + if (ret) { + ret = -errno; + LOG(Error) << "Unable to get format: " << strerror(-ret); + return ret; + } + + config->setWidth(pix->width); + config->setHeight(pix->height); + config->setPixelFormat(pix->pixelformat); + + return 0; +} + +int V4L2Device::setFormatMultiplane(StreamConfiguration *config) +{ + struct v4l2_format v4l2Fmt; + struct v4l2_pix_format_mplane *pix = &v4l2Fmt.fmt.pix_mp; + int ret; + + v4l2Fmt.type = buftype_; + pix->width = config->width(); + pix->height = config->height(); + pix->pixelformat = config->pixelformat(); + + unsigned int numPlanes = getPlanesFromFormat(pix->pixelformat); + unsigned int bpp = getBppFromFormat(pix->pixelformat); + for (unsigned int i = 0; i < numPlanes; ++i) { + pix->plane_fmt[i].bytesperline = bpp * pix->width; + pix->plane_fmt[i].sizeimage = bpp * pix->width * pix->height; + } + + ret = ioctl(fd_, VIDIOC_S_FMT, &v4l2Fmt); + if (ret) { + ret = -errno; + LOG(Error) << "Unable to set format: " << strerror(-ret); + return ret; + } return 0; }